Jack Hsu 45847a6754
feat(js): remove nx property from generated package.json files (#29705)
This PR updates our generators to no longer generate with `nx` in
`package.json` by default. The only times it is needed is if you pass
add `tags` or `implicitDependencies` to the project config.

This PR replaces our `projectType` checks to use the `getProjectType`
util from `@nx/js` to prefer the project config, but otherwise will
check for our conventions (e.g. using `exports` for libs,
`tsconfig.lib.json` vs `tsconfig.app.json`).

## Impact
- There shouldn't be any behavioral changes to existing projects that
have explicit `projectType`, `name`, etc. in with `project.json` or
`package.json` (via `nx` property).
- For new projects created under the new TS setup, the `nx` property
will no longer be there. Generators with logic that depend on
`projectType` will now check for `tsconfig.lib.json` and
`tsconfig.app.json` (so all of our generators are covered). If none of
those tsconfig files are found, then we check `package.json`, since
libraries are required to have `exports` to be consumed.
2025-01-23 20:03:28 -05:00

97 lines
2.5 KiB
TypeScript

import { Schema } from './schema';
import {
applyChangesToString,
formatFiles,
generateFiles,
getProjects,
joinPathFragments,
Tree,
} from '@nx/devkit';
import { NormalizedSchema, normalizeOptions } from './lib/normalize-options';
import { addImport } from './lib/add-import';
import { ensureTypescript } from '@nx/js/src/utils/typescript/ensure-typescript';
import { dirname, join, parse, relative } from 'path';
import { getProjectType } from '@nx/js/src/utils/typescript/ts-solution-setup';
export async function reactNativeComponentGenerator(
host: Tree,
schema: Schema
) {
const options = await normalizeOptions(host, schema);
createComponentFiles(host, options);
addExportsToBarrel(host, options);
await formatFiles(host);
}
function createComponentFiles(host: Tree, options: NormalizedSchema) {
generateFiles(
host,
join(__dirname, 'files', options.fileExtensionType),
options.directory,
{
...options,
ext: options.fileExtension,
}
);
if (options.skipTests) {
host.delete(
joinPathFragments(
options.directory,
`${options.fileName}.spec.${options.fileExtension}`
)
);
}
}
let tsModule: typeof import('typescript');
function addExportsToBarrel(host: Tree, options: NormalizedSchema) {
if (!tsModule) {
tsModule = ensureTypescript();
}
const workspace = getProjects(host);
const proj = workspace.get(options.projectName);
const isApp =
getProjectType(host, proj.root, proj.projectType) === 'application';
if (options.export && !isApp) {
const indexFilePath = joinPathFragments(
options.projectSourceRoot,
options.fileExtensionType === 'js' ? 'index.js' : 'index.ts'
);
if (!host.exists(indexFilePath)) {
return;
}
const indexSource = host.read(indexFilePath, 'utf-8');
const indexSourceFile = tsModule.createSourceFile(
indexFilePath,
indexSource,
tsModule.ScriptTarget.Latest,
true
);
const relativePathFromIndex = getRelativeImportToFile(
indexFilePath,
options.filePath
);
const changes = applyChangesToString(
indexSource,
addImport(indexSourceFile, `export * from '${relativePathFromIndex}';`)
);
host.write(indexFilePath, changes);
}
}
function getRelativeImportToFile(indexPath: string, filePath: string) {
const { name, dir } = parse(filePath);
const relativeDirToTarget = relative(dirname(indexPath), dir);
return `./${joinPathFragments(relativeDirToTarget, name)}`;
}
export default reactNativeComponentGenerator;