- Update project generators to add the project to the workspaces setup in the new TS solution setup - Update some library generators that were not running package installation <!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> <!-- If this is a particularly complex change or feature addition, you can request a dedicated Nx release for this pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate. --> ## Current Behavior <!-- This is the behavior we have today --> ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
229 lines
6.0 KiB
TypeScript
229 lines
6.0 KiB
TypeScript
import {
|
|
addDependenciesToPackageJson,
|
|
formatFiles,
|
|
generateFiles,
|
|
GeneratorCallback,
|
|
getPackageManagerCommand,
|
|
joinPathFragments,
|
|
readJson,
|
|
readProjectConfiguration,
|
|
runTasksInSerial,
|
|
Tree,
|
|
updateJson,
|
|
updateProjectConfiguration,
|
|
} from '@nx/devkit';
|
|
import { libraryGenerator as jsLibraryGenerator } from '@nx/js';
|
|
import { addTsLibDependencies } from '@nx/js/src/utils/typescript/add-tslib-dependencies';
|
|
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
|
|
import { tsLibVersion } from '@nx/js/src/utils/versions';
|
|
import type { PackageJson } from 'nx/src/utils/package-json';
|
|
import { nxVersion } from 'nx/src/utils/versions';
|
|
import { join } from 'path';
|
|
import { hasGenerator } from '../../utils/has-generator';
|
|
import { generatorGenerator } from '../generator/generator';
|
|
import { CreatePackageSchema } from './schema';
|
|
import { NormalizedSchema, normalizeSchema } from './utils/normalize-schema';
|
|
|
|
export async function createPackageGenerator(
|
|
host: Tree,
|
|
schema: CreatePackageSchema
|
|
) {
|
|
return await createPackageGeneratorInternal(host, {
|
|
useProjectJson: true,
|
|
addPlugin: false,
|
|
...schema,
|
|
});
|
|
}
|
|
|
|
export async function createPackageGeneratorInternal(
|
|
host: Tree,
|
|
schema: CreatePackageSchema
|
|
) {
|
|
const tasks: GeneratorCallback[] = [];
|
|
|
|
const options = await normalizeSchema(host, schema);
|
|
const pluginPackageName = await addPresetGenerator(host, options);
|
|
|
|
if (options.bundler === 'tsc') {
|
|
tasks.push(addTsLibDependencies(host));
|
|
}
|
|
|
|
const installTask = addDependenciesToPackageJson(
|
|
host,
|
|
{
|
|
'create-nx-workspace': nxVersion,
|
|
},
|
|
{}
|
|
);
|
|
tasks.push(installTask);
|
|
|
|
const cliPackageTask = await createCliPackage(
|
|
host,
|
|
options,
|
|
pluginPackageName
|
|
);
|
|
tasks.push(cliPackageTask);
|
|
|
|
if (options.e2eProject) {
|
|
addE2eProject(host, options);
|
|
}
|
|
|
|
if (!options.skipFormat) {
|
|
await formatFiles(host);
|
|
}
|
|
|
|
return runTasksInSerial(...tasks);
|
|
}
|
|
|
|
/**
|
|
* Add a preset generator to the plugin if it doesn't exist
|
|
* @param host
|
|
* @param schema
|
|
* @returns package name of the plugin
|
|
*/
|
|
async function addPresetGenerator(
|
|
host: Tree,
|
|
schema: NormalizedSchema
|
|
): Promise<string> {
|
|
const { root: projectRoot } = readProjectConfiguration(host, schema.project);
|
|
if (!hasGenerator(host, schema.project, 'preset')) {
|
|
await generatorGenerator(host, {
|
|
name: 'preset',
|
|
path: join(projectRoot, 'src/generators/preset/generator'),
|
|
unitTestRunner: schema.unitTestRunner,
|
|
skipFormat: true,
|
|
skipLintChecks: schema.linter === 'none',
|
|
});
|
|
}
|
|
|
|
return readJson(host, joinPathFragments(projectRoot, 'package.json'))?.name;
|
|
}
|
|
|
|
async function createCliPackage(
|
|
host: Tree,
|
|
options: NormalizedSchema,
|
|
pluginPackageName: string
|
|
) {
|
|
const jsLibraryTask = await jsLibraryGenerator(host, {
|
|
...options,
|
|
directory: options.directory,
|
|
rootProject: false,
|
|
config: 'project',
|
|
publishable: true,
|
|
bundler: options.bundler,
|
|
importPath: options.name,
|
|
skipFormat: true,
|
|
skipTsConfig: true,
|
|
useTscExecutor: true,
|
|
});
|
|
|
|
host.delete(joinPathFragments(options.projectRoot, 'src'));
|
|
|
|
const isTsSolutionSetup = isUsingTsSolutionSetup(host);
|
|
|
|
// Add the bin entry to the package.json
|
|
updateJson<PackageJson>(
|
|
host,
|
|
joinPathFragments(options.projectRoot, 'package.json'),
|
|
(packageJson) => {
|
|
packageJson.bin = {
|
|
[options.name]: './bin/index.js',
|
|
};
|
|
if (isTsSolutionSetup) {
|
|
packageJson.bin[options.name] = './dist/bin/index.js';
|
|
// this package only exposes a binary entry point and no JS programmatic API
|
|
delete packageJson.main;
|
|
delete packageJson.types;
|
|
delete packageJson.typings;
|
|
delete packageJson.exports;
|
|
}
|
|
packageJson.dependencies = {
|
|
'create-nx-workspace': nxVersion,
|
|
...(options.bundler === 'tsc' && { tslib: tsLibVersion }),
|
|
};
|
|
return packageJson;
|
|
}
|
|
);
|
|
|
|
// update project build target to use the bin entry
|
|
const projectConfiguration = readProjectConfiguration(
|
|
host,
|
|
options.projectName
|
|
);
|
|
projectConfiguration.sourceRoot = joinPathFragments(
|
|
options.projectRoot,
|
|
'bin'
|
|
);
|
|
projectConfiguration.targets.build.options.main = joinPathFragments(
|
|
options.projectRoot,
|
|
'bin/index.ts'
|
|
);
|
|
projectConfiguration.implicitDependencies = [options.project];
|
|
if (options.isTsSolutionSetup) {
|
|
if (options.bundler === 'tsc') {
|
|
projectConfiguration.targets.build.options.generatePackageJson = false;
|
|
} else if (options.bundler === 'swc') {
|
|
delete projectConfiguration.targets.build.options.stripLeadingPaths;
|
|
}
|
|
}
|
|
updateProjectConfiguration(host, options.projectName, projectConfiguration);
|
|
|
|
// Add bin files and update rootDir in tsconfg.lib.json
|
|
updateJson(
|
|
host,
|
|
joinPathFragments(options.projectRoot, 'tsconfig.lib.json'),
|
|
(tsConfig) => {
|
|
tsConfig.include.push('bin/**/*.ts');
|
|
tsConfig.compilerOptions ??= {};
|
|
tsConfig.compilerOptions.rootDir = '.';
|
|
return tsConfig;
|
|
}
|
|
);
|
|
|
|
generateFiles(
|
|
host,
|
|
joinPathFragments(__dirname, './files/create-framework-package'),
|
|
options.projectRoot,
|
|
{
|
|
...options,
|
|
preset: pluginPackageName,
|
|
tmpl: '',
|
|
}
|
|
);
|
|
|
|
return jsLibraryTask;
|
|
}
|
|
|
|
/**
|
|
* Add a test file to plugin e2e project
|
|
* @param host
|
|
* @param options
|
|
* @returns
|
|
*/
|
|
function addE2eProject(host: Tree, options: NormalizedSchema) {
|
|
const e2eProjectConfiguration = readProjectConfiguration(
|
|
host,
|
|
options.e2eProject
|
|
);
|
|
const projectConfiguration = readProjectConfiguration(host, options.project);
|
|
const { name: pluginPackageName } = readJson(
|
|
host,
|
|
join(projectConfiguration.root, 'package.json')
|
|
);
|
|
|
|
generateFiles(
|
|
host,
|
|
joinPathFragments(__dirname, './files/e2e'),
|
|
e2eProjectConfiguration.sourceRoot,
|
|
{
|
|
pluginName: options.project,
|
|
cliName: options.name,
|
|
packageManagerCommands: getPackageManagerCommand(),
|
|
pluginPackageName,
|
|
tmpl: '',
|
|
}
|
|
);
|
|
}
|
|
|
|
export default createPackageGenerator;
|