diff --git a/docs/generated/manifests/menus.json b/docs/generated/manifests/menus.json index 1360c31836833c..6d9b585401fb65 100644 --- a/docs/generated/manifests/menus.json +++ b/docs/generated/manifests/menus.json @@ -5487,6 +5487,14 @@ "children": [], "isExternal": false, "disableCollapsible": false + }, + { + "id": "preset", + "path": "/packages/nx-plugin/generators/preset", + "name": "preset", + "children": [], + "isExternal": false, + "disableCollapsible": false } ], "isExternal": false, diff --git a/docs/generated/manifests/packages.json b/docs/generated/manifests/packages.json index 5ed45108f1c837..785474a1efeb6b 100644 --- a/docs/generated/manifests/packages.json +++ b/docs/generated/manifests/packages.json @@ -1964,6 +1964,15 @@ "originalFilePath": "/packages/nx-plugin/src/generators/lint-checks/schema.json", "path": "/packages/nx-plugin/generators/plugin-lint-checks", "type": "generator" + }, + "/packages/nx-plugin/generators/preset": { + "description": "preset generator", + "file": "generated/packages/nx-plugin/generators/preset.json", + "hidden": true, + "name": "preset", + "originalFilePath": "/packages/nx-plugin/src/generators/preset/schema.json", + "path": "/packages/nx-plugin/generators/preset", + "type": "generator" } }, "path": "/packages/nx-plugin" diff --git a/docs/generated/packages-metadata.json b/docs/generated/packages-metadata.json index a97571dc94f5ca..8dcfd836ecef4d 100644 --- a/docs/generated/packages-metadata.json +++ b/docs/generated/packages-metadata.json @@ -1939,6 +1939,15 @@ "originalFilePath": "/packages/nx-plugin/src/generators/lint-checks/schema.json", "path": "nx-plugin/generators/plugin-lint-checks", "type": "generator" + }, + { + "description": "preset generator", + "file": "generated/packages/nx-plugin/generators/preset.json", + "hidden": true, + "name": "preset", + "originalFilePath": "/packages/nx-plugin/src/generators/preset/schema.json", + "path": "nx-plugin/generators/preset", + "type": "generator" } ], "githubRoot": "https://github.com/nrwl/nx/blob/master", diff --git a/docs/generated/packages/nx-plugin/generators/preset.json b/docs/generated/packages/nx-plugin/generators/preset.json new file mode 100644 index 00000000000000..6729b484688714 --- /dev/null +++ b/docs/generated/packages/nx-plugin/generators/preset.json @@ -0,0 +1,28 @@ +{ + "name": "preset", + "factory": "./src/generators/preset/generator", + "schema": { + "$schema": "http://json-schema.org/schema", + "cli": "nx", + "$id": "NxPluginPreset", + "title": "Preset for @nrwl/nx-plugin", + "description": "Initializes a workspace with an nx-plugin inside of it. Use as: `create-nx-workspace --preset @nrwl/nx-plugin`.", + "type": "object", + "properties": { + "pluginName": { + "type": "string", + "description": "Plugin name", + "aliases": ["name"] + } + }, + "required": ["pluginName"], + "presets": [] + }, + "description": "preset generator", + "hidden": true, + "x-use-standalone-layout": true, + "implementation": "/packages/nx-plugin/src/generators/preset/generator.ts", + "aliases": [], + "path": "/packages/nx-plugin/src/generators/preset/schema.json", + "type": "generator" +} diff --git a/packages/create-nx-plugin/.eslintrc.json b/packages/create-nx-plugin/.eslintrc.json index c3541797464b0b..02cba1766ad6d8 100644 --- a/packages/create-nx-plugin/.eslintrc.json +++ b/packages/create-nx-plugin/.eslintrc.json @@ -15,8 +15,7 @@ "overrides": [ { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": { - } + "rules": {} }, { "files": ["*.ts", "*.tsx"], diff --git a/packages/create-nx-plugin/bin/create-nx-plugin.ts b/packages/create-nx-plugin/bin/create-nx-plugin.ts index 181819033d07e7..dfd091853cd1cd 100644 --- a/packages/create-nx-plugin/bin/create-nx-plugin.ts +++ b/packages/create-nx-plugin/bin/create-nx-plugin.ts @@ -1,3 +1,4 @@ +#!/usr/bin/env node import chalk = require('chalk'); import enquirer = require('enquirer'); import yargs = require('yargs'); @@ -38,8 +39,8 @@ export const yargsDecorator = { const nxVersion = require('../package.json').version; function determinePluginName(parsedArgs: CreateNxPluginArguments) { - if (parsedArgs.name) { - return Promise.resolve(parsedArgs.name); + if (parsedArgs.pluginName) { + return Promise.resolve(parsedArgs.pluginName); } return enquirer @@ -64,8 +65,7 @@ function determinePluginName(parsedArgs: CreateNxPluginArguments) { } interface CreateNxPluginArguments { - name: string; - importPath: string; + pluginName: string; packageManager: PackageManager; ci: CI; allPrompts: boolean; @@ -82,19 +82,19 @@ export const commandsObject: yargs.Argv = yargs // this is the default and only command '$0 [name] [options]', 'Create a new Nx plugin workspace', - withOptions( - (yargs) => - yargs.option('name', { + (yargs) => + withOptions( + yargs.positional('pluginName', { describe: chalk.dim`Plugin name`, type: 'string', - alias: ['pluginName'], + alias: ['name'], }), - withNxCloud, - withCI, - withAllPrompts, - withPackageManager, - withGitOptions - ), + withNxCloud, + withCI, + withAllPrompts, + withPackageManager, + withGitOptions + ), async (argv: yargs.ArgumentsCamelCase) => { await main(argv).catch((error) => { const { version } = require('../package.json'); @@ -117,11 +117,11 @@ export const commandsObject: yargs.Argv = yargs async function main(parsedArgs: yargs.Arguments) { const populatedArguments: CreateNxPluginArguments & CreateWorkspaceOptions = { ...parsedArgs, + name: parsedArgs.pluginName.includes('/') + ? parsedArgs.pluginName.split('/')[1] + : parsedArgs.pluginName, }; - await createWorkspace( - '@nrwl/nx-plugin', - populatedArguments - ); + await createWorkspace('@nrwl/nx-plugin', populatedArguments); } /** @@ -152,3 +152,6 @@ async function normalizeArgsMiddleware( process.exit(1); } } + +// Trigger Yargs +commandsObject.argv; diff --git a/packages/create-nx-plugin/bin/detect-invoked-package-manager.ts b/packages/create-nx-plugin/bin/detect-invoked-package-manager.ts deleted file mode 100644 index 3748ec252e6dcd..00000000000000 --- a/packages/create-nx-plugin/bin/detect-invoked-package-manager.ts +++ /dev/null @@ -1,32 +0,0 @@ -const packageManagerList = ['pnpm', 'yarn', 'npm'] as const; - -export type PackageManager = typeof packageManagerList[number]; - -/** - * Detects which package manager was used to invoke create-nx-{plugin|workspace} command - * based on the main Module process that invokes the command - * - npx returns 'npm' - * - pnpx returns 'pnpm' - * - yarn create returns 'yarn' - * - * Default to 'npm' - */ -export function detectInvokedPackageManager(): PackageManager { - let detectedPackageManager: PackageManager = 'npm'; - // mainModule is deprecated since Node 14, fallback for older versions - const invoker = require.main || process['mainModule']; - - // default to `npm` - if (!invoker) { - return detectedPackageManager; - } - - for (const pkgManager of packageManagerList) { - if (invoker.path.includes(pkgManager)) { - detectedPackageManager = pkgManager; - break; - } - } - - return detectedPackageManager; -} diff --git a/packages/create-nx-plugin/bin/shared.ts b/packages/create-nx-plugin/bin/shared.ts deleted file mode 100644 index 42dc250a148038..00000000000000 --- a/packages/create-nx-plugin/bin/shared.ts +++ /dev/null @@ -1,106 +0,0 @@ -import * as path from 'path'; -import { execSync, spawn, SpawnOptions } from 'child_process'; -import { output } from '@nrwl/devkit'; - -export function showNxWarning(workspaceName: string) { - try { - const pathToRunNxCommand = path.resolve(process.cwd(), workspaceName); - execSync('nx --version', { - cwd: pathToRunNxCommand, - stdio: ['ignore', 'ignore', 'ignore'], - }); - } catch { - // no nx found - output.addVerticalSeparator(); - output.note({ - title: `Nx CLI is not installed globally.`, - bodyLines: [ - `This means that you might have to use "yarn nx" or "npx nx" to execute commands in the workspace.`, - `Run "yarn global add nx" or "npm install -g nx" to be able to execute command directly.`, - ], - }); - } -} - -/* - * Because we don't want to depend on @nrwl/workspace - * we duplicate the helper functions from @nrwl/workspace in this file. - */ -export function deduceDefaultBase(): string { - const nxDefaultBase = 'main'; - try { - return ( - execSync('git config --get init.defaultBranch').toString().trim() || - nxDefaultBase - ); - } catch { - return nxDefaultBase; - } -} - -function checkGitVersion(): string | null { - try { - let gitVersionOutput = execSync('git --version').toString().trim(); - return gitVersionOutput.match(/[0-9]+\.[0-9]+\.+[0-9]+/)[0]; - } catch { - return null; - } -} - -/* - * Because we don't want to depend on create-nx-workspace - * we duplicate the helper functions from create-nx-workspace in this file. - */ -export async function initializeGitRepo(directory: string) { - const execute = (args: ReadonlyArray, ignoreErrorStream = false) => { - const errorStream = ignoreErrorStream ? 'ignore' : process.stderr; - const spawnOptions: SpawnOptions = { - stdio: [process.stdin, 'ignore', errorStream], - shell: true, - cwd: directory, - env: process.env, - }; - return new Promise((resolve, reject) => { - spawn('git', args, spawnOptions).on('close', (code) => { - if (code === 0) { - resolve(); - } else { - reject(code); - } - }); - }); - }; - const gitVersion = checkGitVersion(); - if (!gitVersion) { - return; - } - const insideRepo = await execute( - ['rev-parse', '--is-inside-work-tree'], - true - ).then( - () => true, - () => false - ); - if (insideRepo) { - output.log({ - title: - 'Directory is already under version control. Skipping initialization of git.', - }); - return; - } - const defaultBase = deduceDefaultBase(); - const [gitMajor, gitMinor] = gitVersion.split('.'); - - if (+gitMajor > 2 || (+gitMajor === 2 && +gitMinor >= 28)) { - await execute(['init', '-b', defaultBase]); - } else { - await execute(['init']); - await execute(['checkout', '-b', defaultBase]); // Git < 2.28 doesn't support -b on git init. - } - await execute(['add', '.']); - const message = 'Initial commit'; - await execute(['commit', `-m "${message}"`]); - output.log({ - title: 'Successfully initialized git.', - }); -} diff --git a/packages/create-nx-plugin/package.json b/packages/create-nx-plugin/package.json index 179572c359a977..df0f020b07ec7f 100644 --- a/packages/create-nx-plugin/package.json +++ b/packages/create-nx-plugin/package.json @@ -30,7 +30,9 @@ "homepage": "https://nx.dev", "dependencies": { "create-nx-workspace": "file:../create-nx-workspace", - "yargs-parser": "21.1.1" + "chalk": "^4.1.0", + "enquirer": "~2.3.6", + "yargs": "^17.6.2" }, "publishConfig": { "access": "public" diff --git a/packages/create-nx-workspace/bin/create-nx-workspace.ts b/packages/create-nx-workspace/bin/create-nx-workspace.ts index 005ad6d8488c73..8e1e284d7e977e 100644 --- a/packages/create-nx-workspace/bin/create-nx-workspace.ts +++ b/packages/create-nx-workspace/bin/create-nx-workspace.ts @@ -18,6 +18,7 @@ import { getThirdPartyPreset } from '../src/utils/preset/get-third-party-preset' import { Framework, frameworkList } from './types/framework-list'; import { Bundler, bundlerList } from './types/bundler-list'; import { + determineCI, determineDefaultBase, determineNxCloud, determinePackageManager, @@ -722,7 +723,3 @@ async function determineBundler( return Promise.resolve(parsedArgs.bundler); } - -function determineCI(argv: yargs.Arguments, nxCloud: boolean) { - throw new Error('Function not implemented.'); -} diff --git a/packages/create-nx-workspace/src/create-workspace.ts b/packages/create-nx-workspace/src/create-workspace.ts index b2a02cc9fffbcf..3f77507aa989d2 100644 --- a/packages/create-nx-workspace/src/create-workspace.ts +++ b/packages/create-nx-workspace/src/create-workspace.ts @@ -35,11 +35,12 @@ export async function createWorkspace( const tmpDir = await createSandbox(packageManager); + // nx new requires preset currently. We should probably make it optional. const directory = await createEmptyWorkspace( tmpDir, name, packageManager, - options + { ...options, preset } ); // If the preset is a third-party preset, we need to call createPreset to install it diff --git a/packages/create-nx-workspace/src/internal-utils/prompts.ts b/packages/create-nx-workspace/src/internal-utils/prompts.ts index b12f1ec7ac90df..2d67978aff686c 100644 --- a/packages/create-nx-workspace/src/internal-utils/prompts.ts +++ b/packages/create-nx-workspace/src/internal-utils/prompts.ts @@ -41,7 +41,7 @@ export async function determineNxCloud( } export async function determineCI( - parsedArgs: yargs.Arguments<{ ci: CI; allPrompts?: boolean }>, + parsedArgs: yargs.Arguments<{ ci?: CI; allPrompts?: boolean }>, nxCloud: boolean ): Promise { if (!nxCloud) { diff --git a/packages/eslint-plugin-nx/src/rules/nx-plugin-checks.ts b/packages/eslint-plugin-nx/src/rules/nx-plugin-checks.ts index ca18cc28d731e3..1e612c0893e22b 100644 --- a/packages/eslint-plugin-nx/src/rules/nx-plugin-checks.ts +++ b/packages/eslint-plugin-nx/src/rules/nx-plugin-checks.ts @@ -14,6 +14,7 @@ import * as path from 'path'; import { createESLintRule } from '../utils/create-eslint-rule'; import { readProjectGraph } from '../utils/project-graph-utils'; import { valid } from 'semver'; +import { resolve } from 'path'; type Options = [ { @@ -86,15 +87,16 @@ export default createESLintRule({ const { projectGraph, projectRootMappings } = readProjectGraph(RULE_NAME); - const sourceFilePath = getSourceFilePath( + const rawSourceFilePath = getSourceFilePath( context.getFilename(), workspaceRoot ); + const sourceFilePath = resolve(rawSourceFilePath); const sourceProject = findProject( projectGraph, projectRootMappings, - sourceFilePath + rawSourceFilePath ); // If source is not part of an nx workspace, return. if (!sourceProject) { @@ -144,16 +146,16 @@ function normalizeOptions( return { ...base, executorsJson: base.executorsJson - ? `${sourceProject.data.root}/${base.executorsJson}` + ? resolve(`${sourceProject.data.root}/${base.executorsJson}`) : undefined, generatorsJson: base.generatorsJson - ? `${sourceProject.data.root}/${base.generatorsJson}` + ? resolve(`${sourceProject.data.root}/${base.generatorsJson}`) : undefined, migrationsJson: base.migrationsJson - ? `${sourceProject.data.root}/${base.migrationsJson}` + ? resolve(`${sourceProject.data.root}/${base.migrationsJson}`) : undefined, packageJson: base.packageJson - ? `${sourceProject.data.root}/${base.packageJson}` + ? resolve(`${sourceProject.data.root}/${base.packageJson}`) : undefined, }; } diff --git a/packages/js/src/generators/library/files/lib/package.json__tmpl__ b/packages/js/src/generators/library/files/lib/package.json__tmpl__ deleted file mode 100644 index 7ede38f8da1ed5..00000000000000 --- a/packages/js/src/generators/library/files/lib/package.json__tmpl__ +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "<%= importPath %>", - "version": "0.0.1", - "type": "commonjs" -} diff --git a/packages/js/src/generators/library/library.ts b/packages/js/src/generators/library/library.ts index ef5a750449db49..c99090619b072e 100644 --- a/packages/js/src/generators/library/library.ts +++ b/packages/js/src/generators/library/library.ts @@ -35,6 +35,7 @@ import { typesNodeVersion, } from '../../utils/versions'; import jsInitGenerator from '../init/init'; +import { PackageJson } from 'nx/src/utils/package-json'; export async function libraryGenerator( tree: Tree, @@ -229,6 +230,7 @@ export async function addLint( `${options.projectRoot}/**/*.${options.js ? 'js' : 'ts'}`, ], setParserOptionsProject: options.setParserOptionsProject, + rootProject: options.rootProject, }); } @@ -302,6 +304,29 @@ function createFiles(tree: Tree, options: NormalizedSchema, filesDir: string) { toJS(tree); } + if (options.rootProject) { + updateJson( + tree, + joinPathFragments(options.projectRoot, 'package.json'), + (json) => { + json.name = options.importPath; + json.version = '0.0.1'; + json.type = 'commonjs'; + return json; + } + ); + } else { + writeJson( + tree, + joinPathFragments(options.projectRoot, 'package.json'), + { + name: options.importPath, + version: '0.0.1', + type: 'commonjs', + } + ); + } + const packageJsonPath = join(options.projectRoot, 'package.json'); if (options.config === 'npm-scripts') { updateJson(tree, packageJsonPath, (json) => { @@ -431,6 +456,8 @@ function normalizeOptions( const name = names(options.name).fileName; const projectDirectory = options.directory ? `${names(options.directory).fileName}/${name}` + : options.rootProject + ? '.' : name; if (!options.unitTestRunner && options.bundler === 'vite') { @@ -443,7 +470,9 @@ function normalizeOptions( options.linter = Linter.EsLint; } - const projectName = projectDirectory.replace(new RegExp('/', 'g'), '-'); + const projectName = options.rootProject + ? name + : projectDirectory.replace(new RegExp('/', 'g'), '-'); const fileName = getCaseAwareFileName({ fileName: options.simpleModuleName ? name : projectName, pascalCaseFiles: options.pascalCaseFiles, diff --git a/packages/js/src/utils/schema.d.ts b/packages/js/src/utils/schema.d.ts index a1295d7fd4a053..233a80fb9890cc 100644 --- a/packages/js/src/utils/schema.d.ts +++ b/packages/js/src/utils/schema.d.ts @@ -32,6 +32,7 @@ export interface LibraryGeneratorSchema { bundler?: Bundler; skipTypeCheck?: boolean; minimal?: boolean; + rootProject?: boolean; } export interface ExecutorOptions { diff --git a/packages/nx-plugin/generators.json b/packages/nx-plugin/generators.json index b889b233cf3b86..c457cd1f3e43e2 100644 --- a/packages/nx-plugin/generators.json +++ b/packages/nx-plugin/generators.json @@ -33,6 +33,13 @@ "factory": "./src/generators/lint-checks/generator", "schema": "./src/generators/lint-checks/schema.json", "description": "Adds linting configuration to validate common json files for nx plugins." + }, + "preset": { + "factory": "./src/generators/preset/generator", + "schema": "./src/generators/preset/schema.json", + "description": "preset generator", + "hidden": true, + "x-use-standalone-layout": true } }, "schematics": { diff --git a/packages/nx-plugin/src/generators/e2e-project/e2e.ts b/packages/nx-plugin/src/generators/e2e-project/e2e.ts index 3be83d7250359f..9170566b24dccf 100644 --- a/packages/nx-plugin/src/generators/e2e-project/e2e.ts +++ b/packages/nx-plugin/src/generators/e2e-project/e2e.ts @@ -35,10 +35,13 @@ function normalizeOptions(host: Tree, options: Schema): NormalizedSchema { const { npmScope, appsDir: defaultAppsDir } = getWorkspaceLayout(host); const appsDir = layoutDirectory ?? defaultAppsDir; - const projectName = `${options.pluginName}-e2e`; - const projectRoot = projectDirectory - ? joinPathFragments(appsDir, `${projectDirectory}-e2e`) - : joinPathFragments(appsDir, projectName); + const projectName = options.rootProject ? 'e2e' : `${options.pluginName}-e2e`; + const projectRoot = + projectDirectory && !options.rootProject + ? joinPathFragments(appsDir, `${projectDirectory}-e2e`) + : options.rootProject + ? projectName + : joinPathFragments(appsDir, projectName); const pluginPropertyName = names(options.pluginName).propertyName; return { @@ -90,6 +93,7 @@ async function addJest(host: Tree, options: NormalizedSchema) { setupFile: 'none', supportTsx: false, skipSerializers: true, + rootProject: options.rootProject, }); const project = readProjectConfiguration(host, options.projectName); @@ -120,6 +124,7 @@ async function addLintingToApplication( unitTestRunner: 'jest', skipFormat: true, setParserOptionsProject: false, + rootProject: options.rootProject, }); return lintTask; diff --git a/packages/nx-plugin/src/generators/e2e-project/schema.d.ts b/packages/nx-plugin/src/generators/e2e-project/schema.d.ts index 2afbe5a0fc63b1..51fa28791e4254 100644 --- a/packages/nx-plugin/src/generators/e2e-project/schema.d.ts +++ b/packages/nx-plugin/src/generators/e2e-project/schema.d.ts @@ -8,4 +8,5 @@ export interface Schema { jestConfig?: string; minimal?: boolean; linter?: Linter; + rootProject?: boolean; } diff --git a/packages/nx-plugin/src/generators/plugin/files/plugin/executors.json__tmpl__ b/packages/nx-plugin/src/generators/plugin/files/plugin/executors.json__tmpl__ deleted file mode 100644 index b64f99d988d2c4..00000000000000 --- a/packages/nx-plugin/src/generators/plugin/files/plugin/executors.json__tmpl__ +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "http://json-schema.org/schema", - "executors": {} -} diff --git a/packages/nx-plugin/src/generators/plugin/files/plugin/generators.json__tmpl__ b/packages/nx-plugin/src/generators/plugin/files/plugin/generators.json__tmpl__ deleted file mode 100644 index ad73df570caa3c..00000000000000 --- a/packages/nx-plugin/src/generators/plugin/files/plugin/generators.json__tmpl__ +++ /dev/null @@ -1,6 +0,0 @@ -{ - "$schema": "http://json-schema.org/schema", - "name": "<%= name %>", - "version": "0.0.1", - "generators": {} -} diff --git a/packages/nx-plugin/src/generators/plugin/files/plugin/package.json__tmpl__ b/packages/nx-plugin/src/generators/plugin/files/plugin/package.json__tmpl__ deleted file mode 100644 index 0364fd3a35c560..00000000000000 --- a/packages/nx-plugin/src/generators/plugin/files/plugin/package.json__tmpl__ +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "<%= npmPackageName %>", - "version": "0.0.1", - "main": "src/index.js", - "generators": "./generators.json", - "executors": "./executors.json" -} diff --git a/packages/nx-plugin/src/generators/plugin/plugin.ts b/packages/nx-plugin/src/generators/plugin/plugin.ts index 5defa1c21b76cb..2e805db4a2f18f 100644 --- a/packages/nx-plugin/src/generators/plugin/plugin.ts +++ b/packages/nx-plugin/src/generators/plugin/plugin.ts @@ -53,7 +53,7 @@ async function addFiles(host: Tree, options: NormalizedSchema) { }); } -function updateWorkspaceJson(host: Tree, options: NormalizedSchema) { +function updatePluginConfig(host: Tree, options: NormalizedSchema) { const project = readProjectConfiguration(host, options.name); if (project.targets.build) { @@ -114,7 +114,7 @@ export async function pluginGenerator(host: Tree, schema: Schema) { addSwcDependencies(host); await addFiles(host, options); - updateWorkspaceJson(host, options); + updatePluginConfig(host, options); if (options.e2eTestRunner !== 'none') { await e2eProjectGenerator(host, { @@ -123,6 +123,7 @@ export async function pluginGenerator(host: Tree, schema: Schema) { pluginOutputPath: `dist/${options.libsDir}/${options.projectDirectory}`, npmPackageName: options.npmPackageName, minimal: options.minimal ?? false, + rootProject: options.rootProject, }); } diff --git a/packages/nx-plugin/src/generators/plugin/schema.d.ts b/packages/nx-plugin/src/generators/plugin/schema.d.ts index b2dfbd3596dfca..2596b29095cd07 100644 --- a/packages/nx-plugin/src/generators/plugin/schema.d.ts +++ b/packages/nx-plugin/src/generators/plugin/schema.d.ts @@ -14,4 +14,5 @@ export interface Schema { setParserOptionsProject?: boolean; compiler: 'swc' | 'tsc'; minimal?: boolean; + rootProject?: boolean; } diff --git a/packages/nx-plugin/src/generators/plugin/utils/normalize-schema.ts b/packages/nx-plugin/src/generators/plugin/utils/normalize-schema.ts index 72fae51491bfd6..9585280bfcf38c 100644 --- a/packages/nx-plugin/src/generators/plugin/utils/normalize-schema.ts +++ b/packages/nx-plugin/src/generators/plugin/utils/normalize-schema.ts @@ -31,9 +31,13 @@ export function normalizeOptions( const name = names(options.name).fileName; const fullProjectDirectory = projectDirectory ? `${names(projectDirectory).fileName}/${name}` + : options.rootProject + ? '.' : name; - const projectName = fullProjectDirectory.replace(new RegExp('/', 'g'), '-'); + const projectName = options.rootProject + ? name + : fullProjectDirectory.replace(new RegExp('/', 'g'), '-'); const fileName = projectName; const projectRoot = joinPathFragments(libsDir, fullProjectDirectory); diff --git a/packages/nx-plugin/src/generators/preset/files/src/index.ts__template__ b/packages/nx-plugin/src/generators/preset/files/src/index.ts__template__ new file mode 100644 index 00000000000000..dde3cb697b7275 --- /dev/null +++ b/packages/nx-plugin/src/generators/preset/files/src/index.ts__template__ @@ -0,0 +1 @@ +const variable = "<%= projectName %>"; \ No newline at end of file diff --git a/packages/nx-plugin/src/generators/preset/generator.spec.ts b/packages/nx-plugin/src/generators/preset/generator.spec.ts new file mode 100644 index 00000000000000..10b41ed6e1c2c5 --- /dev/null +++ b/packages/nx-plugin/src/generators/preset/generator.spec.ts @@ -0,0 +1,20 @@ +import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing'; +import { Tree, readProjectConfiguration } from '@nrwl/devkit'; + +import generator from './generator'; +import { PresetGeneratorSchema } from './schema'; + +describe('preset generator', () => { + let appTree: Tree; + const options: PresetGeneratorSchema = { name: 'test' }; + + beforeEach(() => { + appTree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); + }); + + it('should run successfully', async () => { + await generator(appTree, options); + const config = readProjectConfiguration(appTree, 'test'); + expect(config).toBeDefined(); + }); +}); diff --git a/packages/nx-plugin/src/generators/preset/generator.ts b/packages/nx-plugin/src/generators/preset/generator.ts new file mode 100644 index 00000000000000..94cfe3a39d0db5 --- /dev/null +++ b/packages/nx-plugin/src/generators/preset/generator.ts @@ -0,0 +1,36 @@ +import { + Tree, + readJson, + joinPathFragments, + updateJson, + updateNxJson, + readNxJson, +} from '@nrwl/devkit'; +import { Linter } from '@nrwl/linter'; +import { PackageJson } from 'nx/src/utils/package-json'; +import { pluginGenerator } from '../plugin/plugin'; +import { PresetGeneratorSchema } from './schema'; + +export default async function (tree: Tree, options: PresetGeneratorSchema) { + const task = await pluginGenerator(tree, { + compiler: 'tsc', + linter: Linter.EsLint, + name: options.pluginName.includes('/') + ? options.pluginName.split('/')[1] + : options.pluginName, + skipFormat: false, + skipLintChecks: false, + skipTsConfig: false, + unitTestRunner: 'jest', + importPath: options.pluginName, + rootProject: true, + }); + + removeNpmScope(tree); + + return task; +} + +function removeNpmScope(tree: Tree) { + updateNxJson(tree, { ...readNxJson(tree), npmScope: undefined }); +} diff --git a/packages/nx-plugin/src/generators/preset/schema.d.ts b/packages/nx-plugin/src/generators/preset/schema.d.ts new file mode 100644 index 00000000000000..bff8df3c05dfbc --- /dev/null +++ b/packages/nx-plugin/src/generators/preset/schema.d.ts @@ -0,0 +1,3 @@ +export interface PresetGeneratorSchema { + pluginName: string; +} diff --git a/packages/nx-plugin/src/generators/preset/schema.json b/packages/nx-plugin/src/generators/preset/schema.json new file mode 100644 index 00000000000000..7790d6e464aef9 --- /dev/null +++ b/packages/nx-plugin/src/generators/preset/schema.json @@ -0,0 +1,16 @@ +{ + "$schema": "http://json-schema.org/schema", + "cli": "nx", + "$id": "NxPluginPreset", + "title": "Preset for @nrwl/nx-plugin", + "description": "Initializes a workspace with an nx-plugin inside of it. Use as: `create-nx-workspace --preset @nrwl/nx-plugin`.", + "type": "object", + "properties": { + "pluginName": { + "type": "string", + "description": "Plugin name", + "aliases": ["name"] + } + }, + "required": ["pluginName"] +} diff --git a/packages/nx/src/command-line/new.ts b/packages/nx/src/command-line/new.ts index 035f54c30ec71e..f71e5f627f6188 100644 --- a/packages/nx/src/command-line/new.ts +++ b/packages/nx/src/command-line/new.ts @@ -13,30 +13,33 @@ function removeSpecialFlags(generatorOptions: { [p: string]: any }): void { export async function newWorkspace(cwd: string, args: { [k: string]: any }) { const ws = new Workspaces(null); - return handleErrors(false, async () => { - const isInteractive = args.interactive; - const { normalizedGeneratorName, schema, implementationFactory } = - ws.readGenerator('@nrwl/workspace/generators.json', 'new'); - removeSpecialFlags(args); - const combinedOpts = await combineOptionsForGenerator( - args, - '@nrwl/workspace/generators.json', - normalizedGeneratorName, - null, - null, - schema, - isInteractive, - null, - null, - false - ); + return handleErrors( + process.env.NX_VERBOSE_LOGGING === 'true' || args.verbose, + async () => { + const isInteractive = args.interactive; + const { normalizedGeneratorName, schema, implementationFactory } = + ws.readGenerator('@nrwl/workspace/generators.json', 'new'); + removeSpecialFlags(args); + const combinedOpts = await combineOptionsForGenerator( + args, + '@nrwl/workspace/generators.json', + normalizedGeneratorName, + null, + null, + schema, + isInteractive, + null, + null, + false + ); - const host = new FsTree(cwd, false); - const implementation = implementationFactory(); - const task = await implementation(host, combinedOpts); - flushChanges(cwd, host.listChanges()); - if (task) { - await task(); + const host = new FsTree(cwd, false); + const implementation = implementationFactory(); + const task = await implementation(host, combinedOpts); + flushChanges(cwd, host.listChanges()); + if (task) { + await task(); + } } - }); + ); } diff --git a/tsconfig.base.json b/tsconfig.base.json index 75578d9e31962b..88456cbebb59b8 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -107,11 +107,11 @@ "@nrwl/workspace": ["packages/workspace"], "@nrwl/workspace/*": ["packages/workspace/*"], "@nrwl/workspace/testing": ["packages/workspace/testing"], + "create-nx-workspace": ["packages/create-nx-workspace/index.ts"], + "create-nx-workspace/*": ["packages/create-nx-workspace/*"], "nx": ["packages/nx"], "nx-dev/ui-primitives": ["nx-dev/ui-primitives/src/index.ts"], - "nx/*": ["packages/nx/*"], - "create-nx-workspace": ["packages/create-nx-workspace/index.ts"], - "create-nx-workspace/*": ["packages/create-nx-workspace/*"] + "nx/*": ["packages/nx/*"] } } }