From cfacf6b7d0b5c058d360fda2c23c137432b3b98b Mon Sep 17 00:00:00 2001 From: Banst Date: Thu, 25 May 2023 18:07:04 +0200 Subject: [PATCH] chore(core): nx plugin submission @loft-orbital/terraform (#16935) --- community/approved-plugins.json | 5 ++ .../bin/create-nx-workspace.ts | 39 +++++++++---- .../src/internal-utils/prompts.ts | 55 ++++++++++++++++++- .../src/utils/preset/preset.ts | 1 + .../__snapshots__/library.spec.ts.snap | 1 + .../files/jest-config/jest.config.__ext__ | 1 + .../library/files/lib/tsconfig.json__tmpl__ | 14 ----- packages/js/src/generators/library/library.ts | 32 ++++++++++- packages/js/src/utils/swc/compile-swc.ts | 8 ++- .../generate-workspace-files.spec.ts.snap | 21 +++++++ .../new/files-readme/README.md.template | 4 +- .../src/generators/new/generate-preset.ts | 2 + .../new/generate-workspace-files.spec.ts | 1 + .../new/generate-workspace-files.ts | 16 +++++- packages/workspace/src/generators/new/new.ts | 1 + .../workspace/src/generators/preset/preset.ts | 12 ++++ .../src/generators/preset/schema.d.ts | 3 +- .../workspace/src/generators/utils/presets.ts | 1 + 18 files changed, 184 insertions(+), 33 deletions(-) delete mode 100644 packages/js/src/generators/library/files/lib/tsconfig.json__tmpl__ diff --git a/community/approved-plugins.json b/community/approved-plugins.json index 7e64df928b184a..dde20fc0e006d3 100644 --- a/community/approved-plugins.json +++ b/community/approved-plugins.json @@ -443,5 +443,10 @@ "name": "@jnxplus/nx-quarkus-maven", "description": "Nx plugin to add Quarkus and Maven multi-module project support to Nx workspace", "url": "https://github.com/khalilou88/jnxplus/tree/main/packages/nx-quarkus-maven" + }, + { + "name": "@loft-orbital/terraform", + "description": "Terraform executors and generators", + "url": "https://github.com/loft-orbital/nx-plugins/tree/main/packages/terraform" } ] diff --git a/packages/create-nx-workspace/bin/create-nx-workspace.ts b/packages/create-nx-workspace/bin/create-nx-workspace.ts index 35fcca90360716..8edae4e11c6957 100644 --- a/packages/create-nx-workspace/bin/create-nx-workspace.ts +++ b/packages/create-nx-workspace/bin/create-nx-workspace.ts @@ -19,6 +19,8 @@ import { determineDefaultBase, determineNxCloud, determinePackageManager, + determinePackageName, + determineTypeScriptUsage, } from '../src/internal-utils/prompts'; import { withAllPrompts, @@ -42,6 +44,7 @@ interface Arguments extends CreateWorkspaceOptions { nextAppDir: boolean; routing: boolean; bundler: Bundler; + js: boolean; } export const commandsObject: yargs.Argv = yargs @@ -182,16 +185,17 @@ async function normalizeArgsMiddleware( argv: yargs.Arguments ): Promise { try { - let name, - appName, - style, - preset, - framework, - bundler, - docker, - nextAppDir, - routing, - standaloneApi; + let name; + let appName; + let style; + let preset; + let framework; + let bundler; + let docker; + let nextAppDir; + let routing; + let standaloneApi; + let js; output.log({ title: @@ -224,6 +228,8 @@ async function normalizeArgsMiddleware( preset = Preset.AngularStandalone; } else if (monorepoStyle === 'node-standalone') { preset = Preset.NodeStandalone; + } else if (monorepoStyle === 'ts-standalone') { + preset = Preset.TsStandalone; } else { // when choose integrated monorepo, further prompt for preset preset = await determinePreset(argv); @@ -269,6 +275,10 @@ async function normalizeArgsMiddleware( argv.routing ?? (argv.interactive ? await determineRouting(argv) : true); } + } else if (preset === Preset.TsStandalone) { + name = await determinePackageName(preset, argv); + appName = name; + js = !(await determineTypeScriptUsage(argv)); } else { name = await determineRepoName(argv); appName = await determineAppName(preset as Preset, argv); @@ -308,6 +318,7 @@ async function normalizeArgsMiddleware( bundler, docker, nextAppDir, + js, }); } catch (e) { console.error(e); @@ -402,6 +413,11 @@ async function determineMonorepoStyle(): Promise { message: 'Standalone Node app: Nx configures a framework (e.g. Express), esbuild, ESlint and Jest.', }, + { + name: 'ts-standalone', + message: + 'Standalone TS/JS package: Nx configures a TypeScript/JavaScript package suitable for publishing to npm.', + }, ], }, ]); @@ -671,7 +687,8 @@ async function determineStyle( preset === Preset.Express || preset === Preset.ReactNative || preset === Preset.Expo || - preset === Preset.NodeStandalone + preset === Preset.NodeStandalone || + preset === Preset.TsStandalone ) { return Promise.resolve(null); } diff --git a/packages/create-nx-workspace/src/internal-utils/prompts.ts b/packages/create-nx-workspace/src/internal-utils/prompts.ts index 304fbf104c8a99..3dbf7c8dd8a29d 100644 --- a/packages/create-nx-workspace/src/internal-utils/prompts.ts +++ b/packages/create-nx-workspace/src/internal-utils/prompts.ts @@ -1,6 +1,5 @@ import * as yargs from 'yargs'; import { messages } from '../utils/nx/ab-testing'; -import enquirer = require('enquirer'); import { CI } from '../utils/ci/ci-list'; import { output } from '../utils/output'; import { deduceDefaultBase } from '../utils/git/default-base'; @@ -9,7 +8,9 @@ import { PackageManager, packageManagerList, } from '../utils/package-manager'; +import { Preset } from '../utils/preset/preset'; import { stringifyCollection } from '../utils/string-utils'; +import enquirer = require('enquirer'); export async function determineNxCloud( parsedArgs: yargs.Arguments<{ nxCloud: boolean }> @@ -157,3 +158,55 @@ export async function determinePackageManager( return Promise.resolve(detectInvokedPackageManager()); } + +export async function determinePackageName( + preset: Preset, + parsedArgs: yargs.Arguments<{ name?: string }> +): Promise { + if (parsedArgs.name) { + return Promise.resolve(parsedArgs.name); + } + + return enquirer + .prompt<{ PackageName: string }>([ + { + name: 'PackageName', + message: `Package name `, + type: 'input', + }, + ]) + .then((a) => { + if (!a.PackageName) { + output.error({ + title: 'Invalid name', + bodyLines: [`Name cannot be empty`], + }); + process.exit(1); + } + return a.PackageName; + }); +} + +export async function determineTypeScriptUsage( + parsedArgs: yargs.Arguments<{ js?: boolean }> +): Promise { + if (parsedArgs.js) return false; + return enquirer + .prompt<{ TypeScript: 'Yes' | 'No' }>([ + { + name: 'TypeScript', + message: `Would you like to use TypeScript with this project?`, + type: 'autocomplete', + choices: [ + { + name: 'Yes', + }, + { + name: 'No', + }, + ], + initial: 'Yes' as any, + }, + ]) + .then((a) => a.TypeScript === 'Yes'); +} diff --git a/packages/create-nx-workspace/src/utils/preset/preset.ts b/packages/create-nx-workspace/src/utils/preset/preset.ts index 554d3742748361..edaff5d60479d4 100644 --- a/packages/create-nx-workspace/src/utils/preset/preset.ts +++ b/packages/create-nx-workspace/src/utils/preset/preset.ts @@ -18,6 +18,7 @@ export enum Preset { React = 'react', Angular = 'angular', NodeStandalone = 'node-standalone', + TsStandalone = 'ts-standalone', } /** diff --git a/packages/js/src/generators/library/__snapshots__/library.spec.ts.snap b/packages/js/src/generators/library/__snapshots__/library.spec.ts.snap index c83f6670d4f248..4dc931094e8487 100644 --- a/packages/js/src/generators/library/__snapshots__/library.spec.ts.snap +++ b/packages/js/src/generators/library/__snapshots__/library.spec.ts.snap @@ -28,6 +28,7 @@ module.exports = { '^.+\\\\.[tj]s$': ['@swc/jest', swcJestConfig], }, moduleFileExtensions: ['ts', 'js', 'html'], + testEnvironment: 'jsdom', coverageDirectory: '../../coverage/libs/my-lib', }; " diff --git a/packages/js/src/generators/library/files/jest-config/jest.config.__ext__ b/packages/js/src/generators/library/files/jest-config/jest.config.__ext__ index 25c74092cfd2d8..aa6ab15eca99cf 100644 --- a/packages/js/src/generators/library/files/jest-config/jest.config.__ext__ +++ b/packages/js/src/generators/library/files/jest-config/jest.config.__ext__ @@ -25,5 +25,6 @@ if (swcJestConfig.swcrc === undefined) { '^.+\\.[tj]s$': ['@swc/jest', swcJestConfig], }, moduleFileExtensions: ['ts', 'js', 'html'], + testEnvironment: '<%= testEnvironment %>', coverageDirectory: '<%= offsetFromRoot %>coverage/<%= projectRoot %>' }; diff --git a/packages/js/src/generators/library/files/lib/tsconfig.json__tmpl__ b/packages/js/src/generators/library/files/lib/tsconfig.json__tmpl__ deleted file mode 100644 index 8d27bd10719eba..00000000000000 --- a/packages/js/src/generators/library/files/lib/tsconfig.json__tmpl__ +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "<%= rootTsConfigPath %>", - "compilerOptions": { - "module": "commonjs"<% if (js) { %>, - "allowJs": true<% } %> - }, - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - } - ] -} diff --git a/packages/js/src/generators/library/library.ts b/packages/js/src/generators/library/library.ts index a3b386098c64a5..1c815cd2fd4261 100644 --- a/packages/js/src/generators/library/library.ts +++ b/packages/js/src/generators/library/library.ts @@ -37,6 +37,7 @@ import { import jsInitGenerator from '../init/init'; import { PackageJson } from 'nx/src/utils/package-json'; import setupVerdaccio from '../setup-verdaccio/generator'; +import { tsConfigBaseOptions } from '../../utils/typescript/create-ts-config'; export async function libraryGenerator( tree: Tree, @@ -63,6 +64,7 @@ export async function projectGenerator( await jsInitGenerator(tree, { ...schema, skipFormat: true, + tsConfigName: schema.rootProject ? 'tsconfig.json' : 'tsconfig.base.json', }) ); const options = normalizeOptions(tree, schema, destinationDir); @@ -275,6 +277,9 @@ function addBabelRc(tree: Tree, options: NormalizedSchema) { function createFiles(tree: Tree, options: NormalizedSchema, filesDir: string) { const { className, name, propertyName } = names(options.name); + + createProjectTsConfigJson(tree, options); + generateFiles(tree, filesDir, options.projectRoot, { ...options, dot: '.', @@ -286,7 +291,6 @@ function createFiles(tree: Tree, options: NormalizedSchema, filesDir: string) { strict: undefined, tmpl: '', offsetFromRoot: offsetFromRoot(options.projectRoot), - rootTsConfigPath: getRelativePathToRootTsConfig(tree, options.projectRoot), buildable: options.bundler && options.bundler !== 'none', hasUnitTestRunner: options.unitTestRunner !== 'none', }); @@ -403,6 +407,7 @@ function replaceJestConfig( project: options.name, offsetFromRoot: offsetFromRoot(options.projectRoot), projectRoot: options.projectRoot, + testEnvironment: options.testEnvironment, }); } @@ -595,5 +600,30 @@ function getOutputPath(options: NormalizedSchema, destinationDir?: string) { return joinPathFragments(...parts); } +function createProjectTsConfigJson(tree: Tree, options: NormalizedSchema) { + const tsconfig = { + extends: options.rootProject + ? undefined + : getRelativePathToRootTsConfig(tree, options.projectRoot), + compilerOptions: { + ...(options.rootProject ? tsConfigBaseOptions : {}), + module: 'commonjs', + allowJs: options.js ? true : undefined, + }, + files: [], + include: [], + references: [ + { + path: './tsconfig.lib.json', + }, + ], + }; + writeJson( + tree, + joinPathFragments(options.projectRoot, 'tsconfig.json'), + tsconfig + ); +} + export default libraryGenerator; export const librarySchematic = convertNxGenerator(libraryGenerator); diff --git a/packages/js/src/utils/swc/compile-swc.ts b/packages/js/src/utils/swc/compile-swc.ts index 61edec414dc431..30dbab9edb689d 100644 --- a/packages/js/src/utils/swc/compile-swc.ts +++ b/packages/js/src/utils/swc/compile-swc.ts @@ -10,7 +10,11 @@ function getSwcCmd( { swcrcPath, srcPath, destPath }: SwcCliOptions, watch = false ) { - let swcCmd = `npx swc ${srcPath} -d ${destPath} --config-file=${swcrcPath}`; + let swcCmd = `npx swc ${ + // TODO(jack): clean this up when we remove inline module support + // Handle root project + srcPath === '.' ? 'src' : srcPath + } -d ${destPath} --config-file=${swcrcPath}`; return watch ? swcCmd.concat(' --watch') : swcCmd; } @@ -38,6 +42,8 @@ export async function compileSwc( normalizedOptions: NormalizedSwcExecutorOptions, postCompilationCallback: () => Promise ) { + const isRootProject = + context.projectGraph.nodes[context.projectName].data.root === '.'; logger.log(`Compiling with SWC for ${context.projectName}...`); if (normalizedOptions.clean) { diff --git a/packages/workspace/src/generators/new/__snapshots__/generate-workspace-files.spec.ts.snap b/packages/workspace/src/generators/new/__snapshots__/generate-workspace-files.spec.ts.snap index 97464c3467d2a2..f31019c061d67c 100644 --- a/packages/workspace/src/generators/new/__snapshots__/generate-workspace-files.spec.ts.snap +++ b/packages/workspace/src/generators/new/__snapshots__/generate-workspace-files.spec.ts.snap @@ -372,6 +372,27 @@ Visit the [Nx Documentation](https://nx.dev) to learn more. " `; +exports[`@nx/workspace:generateWorkspaceFiles README.md should be created for TsStandalone preset 1`] = ` +"# Proj + + + +✨ **This workspace has been generated by [Nx, a Smart, fast and extensible build system.](https://nx.dev)** ✨ + +## Understand this workspace + +Run \`nx graph\` to see a diagram of the dependencies of the projects. + +## Remote caching + +Run \`npx nx connect-to-nx-cloud\` to enable [remote caching](https://nx.app) and make CI faster. + +## Further help + +Visit the [Nx Documentation](https://nx.dev) to learn more. +" +`; + exports[`@nx/workspace:generateWorkspaceFiles README.md should be created for WebComponents preset 1`] = ` "# Proj diff --git a/packages/workspace/src/generators/new/files-readme/README.md.template b/packages/workspace/src/generators/new/files-readme/README.md.template index e3e1dfd17166e4..44227e955ec2e0 100644 --- a/packages/workspace/src/generators/new/files-readme/README.md.template +++ b/packages/workspace/src/generators/new/files-readme/README.md.template @@ -3,11 +3,11 @@ ✨ **This workspace has been generated by [Nx, a Smart, fast and extensible build system.](https://nx.dev)** ✨<% if (!!appName) { %> - +<% if (includeServe) { %> ## Development server Run `nx serve <%= appName %>` for a dev server. Navigate to http://localhost:4200/. The app will automatically reload if you change any of the source files.<% } %> - +<% } %> ## Understand this workspace Run `nx graph` to see a diagram of the dependencies of the projects. diff --git a/packages/workspace/src/generators/new/generate-preset.ts b/packages/workspace/src/generators/new/generate-preset.ts index c9f03d8f8d8ec2..888f73d6619d9a 100644 --- a/packages/workspace/src/generators/new/generate-preset.ts +++ b/packages/workspace/src/generators/new/generate-preset.ts @@ -76,6 +76,7 @@ export function generatePreset(host: Tree, opts: NormalizedSchema) { opts.bundler ? `--bundler=${opts.bundler}` : null, opts.framework ? `--framework=${opts.framework}` : null, opts.docker ? `--docker=${opts.docker}` : null, + opts.js ? `--js` : null, opts.nextAppDir ? `--nextAppDir=${opts.nextAppDir}` : null, opts.packageManager ? `--packageManager=${opts.packageManager}` : null, opts.standaloneApi !== undefined @@ -98,6 +99,7 @@ function getPresetDependencies({ }: NormalizedSchema) { switch (preset) { case Preset.TS: + case Preset.TsStandalone: return { dependencies: {}, dev: { '@nx/js': nxVersion } }; case Preset.AngularMonorepo: diff --git a/packages/workspace/src/generators/new/generate-workspace-files.spec.ts b/packages/workspace/src/generators/new/generate-workspace-files.spec.ts index 52eddbec50a4f1..0a0931bd303ecb 100644 --- a/packages/workspace/src/generators/new/generate-workspace-files.spec.ts +++ b/packages/workspace/src/generators/new/generate-workspace-files.spec.ts @@ -42,6 +42,7 @@ describe('@nx/workspace:generateWorkspaceFiles', () => { Preset.Express, Preset.NodeStandalone, Preset.NextJsStandalone, + Preset.TsStandalone, ].includes(Preset[preset]) ) { appName = 'app1'; diff --git a/packages/workspace/src/generators/new/generate-workspace-files.ts b/packages/workspace/src/generators/new/generate-workspace-files.ts index 3a2a319dd64e49..8cd89ed85b1c35 100644 --- a/packages/workspace/src/generators/new/generate-workspace-files.ts +++ b/packages/workspace/src/generators/new/generate-workspace-files.ts @@ -67,6 +67,7 @@ function createAppsAndLibsFolders(tree: Tree, options: NormalizedSchema) { options.preset === Preset.ReactStandalone || options.preset === Preset.NodeStandalone || options.preset === Preset.NextJsStandalone || + options.preset === Preset.TsStandalone || options.isCustomPreset ) { // don't generate any folders @@ -126,7 +127,8 @@ function createFiles(tree: Tree, options: NormalizedSchema) { options.preset === Preset.AngularStandalone || options.preset === Preset.ReactStandalone || options.preset === Preset.NodeStandalone || - options.preset === Preset.NextJsStandalone + options.preset === Preset.NextJsStandalone || + options.preset === Preset.TsStandalone ? './files-root-app' : options.preset === Preset.NPM || options.preset === Preset.Core ? './files-package-based-repo' @@ -145,11 +147,12 @@ function createFiles(tree: Tree, options: NormalizedSchema) { function createReadme( tree: Tree, - { name, appName, directory }: NormalizedSchema + { name, appName, directory, preset }: NormalizedSchema ) { const formattedNames = names(name); generateFiles(tree, join(__dirname, './files-readme'), directory, { formattedNames, + includeServe: preset !== Preset.TsStandalone, appName, name, }); @@ -189,6 +192,15 @@ function addNpmScripts(tree: Tree, options: NormalizedSchema) { return json; }); } + if (options.preset === Preset.TsStandalone) { + updateJson(tree, join(options.directory, 'package.json'), (json) => { + Object.assign(json.scripts, { + build: 'nx build', + test: 'nx test', + }); + return json; + }); + } } function addPropertyWithStableKeys(obj: any, key: string, value: string) { diff --git a/packages/workspace/src/generators/new/new.ts b/packages/workspace/src/generators/new/new.ts index 49fb389b446759..67de7c8d662d3f 100644 --- a/packages/workspace/src/generators/new/new.ts +++ b/packages/workspace/src/generators/new/new.ts @@ -23,6 +23,7 @@ interface Schema { defaultBase: string; framework?: string; docker?: boolean; + js?: boolean; nextAppDir?: boolean; linter?: Linter; bundler?: 'vite' | 'webpack'; diff --git a/packages/workspace/src/generators/preset/preset.ts b/packages/workspace/src/generators/preset/preset.ts index f61c0e85c21525..c9ddecd0da0977 100644 --- a/packages/workspace/src/generators/preset/preset.ts +++ b/packages/workspace/src/generators/preset/preset.ts @@ -147,6 +147,18 @@ async function createPreset(tree: Tree, options: Schema) { }; updateNxJson(tree, c); return initGenerator(tree, {}); + } else if (options.preset === Preset.TsStandalone) { + const c = readNxJson(tree); + const { libraryGenerator } = require('@nx' + '/js'); + updateNxJson(tree, c); + return libraryGenerator(tree, { + name: options.name, + bundler: 'swc', + unitTestRunner: 'jest', + testEnvironment: 'node', + js: options.js, + rootProject: true, + }); } else if (options.preset === Preset.NodeStandalone) { const { applicationGenerator: nodeApplicationGenerator } = require('@nx' + '/node'); diff --git a/packages/workspace/src/generators/preset/schema.d.ts b/packages/workspace/src/generators/preset/schema.d.ts index af1ba69a8f6169..dd75bedfb54ff0 100644 --- a/packages/workspace/src/generators/preset/schema.d.ts +++ b/packages/workspace/src/generators/preset/schema.d.ts @@ -3,9 +3,9 @@ import { PackageManager } from '@nx/devkit'; export interface Schema { name: string; + preset: Preset; style?: string; linter?: string; - preset: Preset; standaloneConfig?: boolean; framework?: string; packageManager?: PackageManager; @@ -15,4 +15,5 @@ export interface Schema { routing?: boolean; standaloneApi?: boolean; e2eTestRunner?: 'cypress' | 'jest' | 'detox' | 'none'; + js?: boolean; } diff --git a/packages/workspace/src/generators/utils/presets.ts b/packages/workspace/src/generators/utils/presets.ts index 2874fa5b506a56..9ed7ea035f24a6 100644 --- a/packages/workspace/src/generators/utils/presets.ts +++ b/packages/workspace/src/generators/utils/presets.ts @@ -16,4 +16,5 @@ export enum Preset { Nest = 'nest', Express = 'express', NodeStandalone = 'node-standalone', + TsStandalone = 'ts-standalone', }