diff --git a/package.json b/package.json index e310a8bc2..d35c105d4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@nestjs/schematics", - "version": "6.5.0", + "version": "6.5.1", "description": "Nest - modern, fast, powerful node.js web framework (@schematics)", "main": "index.js", "publishConfig": { diff --git a/src/lib/defaults.ts b/src/lib/defaults.ts index 918c02ef8..ad1666b0e 100644 --- a/src/lib/defaults.ts +++ b/src/lib/defaults.ts @@ -5,4 +5,6 @@ export const DEFAULT_VERSION = '0.0.1'; export const DEFAULT_PATH_NAME = 'src'; export const DEFAULT_LIB_PATH = 'libs'; export const DEFAULT_APPS_PATH = 'apps'; +export const DEFAULT_DIR_ENTRY_APP = 'main'; +export const ALTERNATIVE_DIR_ENTRY_APP = 'default'; export const TEST_ENV = 'test'; diff --git a/src/lib/sub-app/sub-app.factory.test.ts b/src/lib/sub-app/sub-app.factory.test.ts index 12e8a6df3..a1133845d 100644 --- a/src/lib/sub-app/sub-app.factory.test.ts +++ b/src/lib/sub-app/sub-app.factory.test.ts @@ -17,6 +17,8 @@ describe('SubApp Factory', () => { const tree: UnitTestTree = runner.runSchematic('app', options); const files: string[] = tree.files; expect(files).toEqual([ + '/apps/main/tsconfig.app.json', + '/apps/main/tslint.json', '/apps/project/tsconfig.app.json', '/apps/project/tslint.json', '/apps/project/src/app.controller.spec.ts', @@ -35,6 +37,8 @@ describe('SubApp Factory', () => { const tree: UnitTestTree = runner.runSchematic('app', options); const files: string[] = tree.files; expect(files).toEqual([ + '/apps/main/tsconfig.app.json', + '/apps/main/tslint.json', '/apps/awesome-project/tsconfig.app.json', '/apps/awesome-project/tslint.json', '/apps/awesome-project/src/app.controller.spec.ts', @@ -54,6 +58,9 @@ describe('SubApp Factory', () => { const tree: UnitTestTree = runner.runSchematic('app', options); const files: string[] = tree.files; expect(files).toEqual([ + '/apps/main/.babelrc', + '/apps/main/index.js', + '/apps/main/jsconfig.json', '/apps/project/.babelrc', '/apps/project/index.js', '/apps/project/jsconfig.json', diff --git a/src/lib/sub-app/sub-app.factory.ts b/src/lib/sub-app/sub-app.factory.ts index a762e752e..761a98451 100644 --- a/src/lib/sub-app/sub-app.factory.ts +++ b/src/lib/sub-app/sub-app.factory.ts @@ -20,7 +20,9 @@ import { } from '@angular-devkit/schematics'; import * as fse from 'fs-extra'; import { + ALTERNATIVE_DIR_ENTRY_APP, DEFAULT_APPS_PATH, + DEFAULT_DIR_ENTRY_APP, DEFAULT_LANGUAGE, DEFAULT_PATH_NAME, TEST_ENV, @@ -38,11 +40,18 @@ interface TsConfigPartialType { } export function main(options: SubAppOptions): Rule { + const defaultAppName = + options.name === DEFAULT_DIR_ENTRY_APP + ? ALTERNATIVE_DIR_ENTRY_APP + : DEFAULT_DIR_ENTRY_APP; + options = transform(options); return chain([ updateTsConfig(), - addSubAppToCliOptions(options.path, options.name), - moveDefaultAppToApps(options.path), + updatePackageJson(options, defaultAppName), + addSubAppToCliOptions(options.path, options.name, defaultAppName), + branchAndMerge(mergeWith(generateWorkspace(options, defaultAppName))), + moveDefaultAppToApps(options.path, defaultAppName, options.sourceRoot), branchAndMerge(mergeWith(generate(options))), ]); } @@ -77,7 +86,6 @@ function updateJsonFile( callback((json as {}) as T); host.overwrite(path, JSON.stringify(json, null, 2)); } - return host; } @@ -104,32 +112,62 @@ function updateTsConfig() { }; } -function moveDefaultAppToApps(projectRoot: string): Rule { +function updatePackageJson(options: SubAppOptions, defaultAppName: string) { return (host: Tree) => { - const nestCliFileExists = host.exists('nest-cli.json'); - const nestFileExists = host.exists('nest.json'); + if (!host.exists('package.json')) { + return host; + } + return updateJsonFile( + host, + 'package.json', + (packageJson: Record) => { + const scripts = packageJson.scripts; + if (!scripts) { + return; + } + const defaultTestScriptName = 'test:e2e'; + if (!scripts[defaultTestScriptName]) { + return; + } + const defaultTestDir = 'test'; + const newTestDir = join( + options.path as Path, + defaultAppName, + options.sourceRoot, + ); + scripts[defaultTestScriptName] = (scripts[ + defaultTestScriptName + ] as string).replace(defaultTestDir, newTestDir); + }, + ); + }; +} - let sourceRoot: string; - if (!nestCliFileExists && !nestFileExists) { - sourceRoot = DEFAULT_PATH_NAME; - } else { - const source = host.read( - nestCliFileExists ? 'nest-cli.json' : 'nest.json', - ); - if (source) { - const sourceText = source.toString('utf-8'); - const config = parseJson(sourceText) as Record; - sourceRoot = (config && config.sourceRoot) || DEFAULT_PATH_NAME; - } +function moveDefaultAppToApps( + projectRoot: string, + appName: string, + sourceRoot = DEFAULT_PATH_NAME, +): Rule { + return (host: Tree) => { + if (process.env.NODE_ENV === TEST_ENV) { + return host; + } + if (fse.existsSync(sourceRoot)) { + fse.moveSync(sourceRoot, join(projectRoot as Path, appName, sourceRoot)); } - if (fse.existsSync(sourceRoot) && process.env.NODE_ENV !== TEST_ENV) { - fse.moveSync(sourceRoot, join(projectRoot as Path, sourceRoot)); + const testDir = 'test'; + if (fse.existsSync(testDir)) { + fse.moveSync(testDir, join(projectRoot as Path, appName, testDir)); } return host; }; } -function addSubAppToCliOptions(projectRoot: string, projectName: string): Rule { +function addSubAppToCliOptions( + projectRoot: string, + projectName: string, + appName: string, +): Rule { const project = { root: join(projectRoot as Path, projectName), sourceRoot: join(projectRoot as Path, projectName, 'src'), @@ -151,8 +189,15 @@ function addSubAppToCliOptions(projectRoot: string, projectName: string): Rule { optionsFile.projects[projectName] = project; // Update initial application options + if ( + optionsFile.sourceRoot && + optionsFile.sourceRoot.indexOf(projectRoot) >= 0 + ) { + return; + } optionsFile.sourceRoot = join( projectRoot as Path, + appName, optionsFile.sourceRoot || DEFAULT_PATH_NAME, ); }, @@ -160,6 +205,18 @@ function addSubAppToCliOptions(projectRoot: string, projectName: string): Rule { }; } +function generateWorkspace(options: SubAppOptions, appName: string): Source { + const path = join(options.path as Path, appName); + + return apply(url(join('./workspace' as Path, options.language)), [ + template({ + ...strings, + ...options, + }), + move(path), + ]); +} + function generate(options: SubAppOptions): Source { const path = join(options.path as Path, options.name); diff --git a/src/lib/sub-app/sub-app.schema.d.ts b/src/lib/sub-app/sub-app.schema.d.ts index 76667e888..0217ca602 100644 --- a/src/lib/sub-app/sub-app.schema.d.ts +++ b/src/lib/sub-app/sub-app.schema.d.ts @@ -17,4 +17,5 @@ export interface SubAppOptions { * Applications root directory */ rootDir?: string | Path; + sourceRoot?: string; } diff --git a/src/lib/sub-app/workspace/js/.babelrc b/src/lib/sub-app/workspace/js/.babelrc new file mode 100644 index 000000000..08db170c1 --- /dev/null +++ b/src/lib/sub-app/workspace/js/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["env", "stage-0"], + "plugins": ["transform-decorators-legacy"] +} \ No newline at end of file diff --git a/src/lib/sub-app/workspace/js/index.js b/src/lib/sub-app/workspace/js/index.js new file mode 100644 index 000000000..bc47b5e29 --- /dev/null +++ b/src/lib/sub-app/workspace/js/index.js @@ -0,0 +1,2 @@ +require('@babel/register'); +require('./src/main'); diff --git a/src/lib/sub-app/workspace/js/jsconfig.json b/src/lib/sub-app/workspace/js/jsconfig.json new file mode 100644 index 000000000..e9f77af48 --- /dev/null +++ b/src/lib/sub-app/workspace/js/jsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "target": "ES6", + "experimentalDecorators": true + }, + "exclude": [ + "node_modules", + "dist" + ] +} diff --git a/src/lib/sub-app/workspace/ts/tsconfig.app.json b/src/lib/sub-app/workspace/ts/tsconfig.app.json new file mode 100644 index 000000000..871086339 --- /dev/null +++ b/src/lib/sub-app/workspace/ts/tsconfig.app.json @@ -0,0 +1,5 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src/**/*"], + "exclude": ["node_modules", "dist", "test", "**/*spec.ts"] +} diff --git a/src/lib/sub-app/workspace/ts/tslint.json b/src/lib/sub-app/workspace/ts/tslint.json new file mode 100644 index 000000000..5651b2f3d --- /dev/null +++ b/src/lib/sub-app/workspace/ts/tslint.json @@ -0,0 +1,18 @@ +{ + "defaultSeverity": "error", + "extends": ["tslint:recommended"], + "jsRules": { + "no-unused-expression": true + }, + "rules": { + "quotemark": [true, "single"], + "member-access": [false], + "ordered-imports": [false], + "max-line-length": [true, 150], + "member-ordering": [false], + "interface-name": [false], + "arrow-parens": false, + "object-literal-sort-keys": false + }, + "rulesDirectory": [] +}