From 566676e69f4430051770f0290518792b8ad97a4c Mon Sep 17 00:00:00 2001 From: Jack Hsu Date: Wed, 14 Aug 2019 21:15:49 -0400 Subject: [PATCH] feat(react): update workspace defaults based on app schematic option The defaults make it easier to generate other apps/libs/components later. An option `skipWorkspaceJson` can be used to skip updates entirely. --- .../api-cypress/schematics/cypress-project.md | 2 +- docs/api-react/schematics/application.md | 8 +++ .../application/application.spec.ts | 29 ++++++++++ .../src/schematics/application/application.ts | 54 ++++++++++++++++--- .../src/schematics/application/schema.d.ts | 1 + .../src/schematics/application/schema.json | 5 ++ .../src/schematics/library/library.spec.ts | 3 +- .../src/schematics/ng-add/ng-add.spec.ts | 7 +-- .../react/src/schematics/ng-add/ng-add.ts | 27 ++++++---- 9 files changed, 111 insertions(+), 25 deletions(-) diff --git a/docs/api-cypress/schematics/cypress-project.md b/docs/api-cypress/schematics/cypress-project.md index 62d60a4a43d4d..472d3da98b48b 100644 --- a/docs/api-cypress/schematics/cypress-project.md +++ b/docs/api-cypress/schematics/cypress-project.md @@ -15,7 +15,7 @@ ng generate cypress-project ... Type: `string` -A directory where the app is placed +A directory where the project is placed ### linter diff --git a/docs/api-react/schematics/application.md b/docs/api-react/schematics/application.md index 85d4b27846d6d..29999e367c4cc 100644 --- a/docs/api-react/schematics/application.md +++ b/docs/api-react/schematics/application.md @@ -77,6 +77,14 @@ Type: `boolean` Skip formatting files +### skipWorkspaceJson + +Default: `false` + +Type: `boolean` + +Skip updating workspace.json with default schematic options based on values provided to this app (e.g. babel, style) + ### style Default: `css` diff --git a/packages/react/src/schematics/application/application.spec.ts b/packages/react/src/schematics/application/application.spec.ts index 504e5ef472f19..df2dd91420407 100644 --- a/packages/react/src/schematics/application/application.spec.ts +++ b/packages/react/src/schematics/application/application.spec.ts @@ -499,4 +499,33 @@ describe('app', () => { expect(polyfillsSource).toContain('core-js'); }); }); + + describe('--skipWorkspaceJson', () => { + it('should update workspace with defaults when --skipWorkspaceJson=false', async () => { + const tree = await runSchematic( + 'app', + { + name: 'myApp', + babel: true, + style: 'styled-components', + skipWorkspaceJson: false + }, + appTree + ); + + const workspaceJson = readJsonInTree(tree, '/workspace.json'); + expect(workspaceJson.schematics['@nrwl/react']).toMatchObject({ + application: { + babel: true, + style: 'styled-components' + }, + component: { + style: 'styled-components' + }, + library: { + style: 'styled-components' + } + }); + }); + }); }); diff --git a/packages/react/src/schematics/application/application.ts b/packages/react/src/schematics/application/application.ts index 1836131cd6e52..b9242e7075c00 100644 --- a/packages/react/src/schematics/application/application.ts +++ b/packages/react/src/schematics/application/application.ts @@ -1,4 +1,4 @@ -import { join, normalize, Path } from '@angular-devkit/core'; +import { join, JsonObject, normalize, Path } from '@angular-devkit/core'; import { apply, chain, @@ -14,21 +14,20 @@ import { url } from '@angular-devkit/schematics'; import { + addGlobal, + addLintFiles, formatFiles, + generateProjectLint, insert, names, NxJson, offsetFromRoot, toFileName, updateJsonInTree, - generateProjectLint, - addLintFiles, - toPropertyName, - addGlobal + updateWorkspace } from '@nrwl/workspace'; import { addDepsToPackageJson, - insertImport, updateWorkspaceInTree } from '@nrwl/workspace/src/utils/ast-utils'; import ngAdd from '../ng-add/ng-add'; @@ -36,7 +35,7 @@ import * as ts from 'typescript'; import { Schema } from './schema'; import { CSS_IN_JS_DEPENDENCIES } from '../../utils/styled'; -import { addRoute, addInitialRoutes } from '../../utils/ast-utils'; +import { addInitialRoutes } from '../../utils/ast-utils'; import { babelCoreVersion, babelLoaderVersion, @@ -49,7 +48,6 @@ import { reactRouterVersion, regeneratorVersion } from '../../utils/versions'; -import { addImportToModule } from '../../../../angular/src/utils/ast-utils'; import { assertValidStyle } from '../../utils/assertion'; interface NormalizedSchema extends Schema { @@ -93,6 +91,7 @@ export default function(schema: Schema): Rule { addStyledModuleDependencies(options), addRouting(options, context), addBabel(options), + setDefaults(options), formatFiles(options) ]); }; @@ -301,6 +300,45 @@ import 'regenerator-runtime/runtime'; }; } +function setDefaults(options: NormalizedSchema): Rule { + return options.skipWorkspaceJson + ? noop() + : updateWorkspace(workspace => { + workspace.extensions.schematics = jsonIdentity( + workspace.extensions.schematics || {} + ); + workspace.extensions.schematics['@nrwl/react'] = + workspace.extensions.schematics['@nrwl/react'] || {}; + const prev = jsonIdentity( + workspace.extensions.schematics['@nrwl/react'] + ); + + workspace.extensions.schematics = { + ...workspace.extensions.schematics, + '@nrwl/react': { + ...prev, + application: { + babel: options.babel, + style: options.style, + ...jsonIdentity(prev.application) + }, + component: { + style: options.style, + ...jsonIdentity(prev.component) + }, + library: { + style: options.style, + ...jsonIdentity(prev.library) + } + } + }; + }); +} + +function jsonIdentity(x: any): JsonObject { + return x as JsonObject; +} + function normalizeOptions(host: Tree, options: Schema): NormalizedSchema { const appDirectory = options.directory ? `${toFileName(options.directory)}/${toFileName(options.name)}` diff --git a/packages/react/src/schematics/application/schema.d.ts b/packages/react/src/schematics/application/schema.d.ts index 82bce484269e3..9d937d5b710ad 100644 --- a/packages/react/src/schematics/application/schema.d.ts +++ b/packages/react/src/schematics/application/schema.d.ts @@ -13,4 +13,5 @@ export interface Schema { classComponent?: boolean; routing?: boolean; babel?: boolean; + skipWorkspaceJson?: boolean; } diff --git a/packages/react/src/schematics/application/schema.json b/packages/react/src/schematics/application/schema.json index 3c8a1f71a1c55..64230c882ed43 100644 --- a/packages/react/src/schematics/application/schema.json +++ b/packages/react/src/schematics/application/schema.json @@ -65,6 +65,11 @@ "type": "boolean", "default": false }, + "skipWorkspaceJson": { + "description": "Skip updating workspace.json with default schematic options based on values provided to this app (e.g. babel, style)", + "type": "boolean", + "default": false + }, "unitTestRunner": { "type": "string", "enum": ["jest", "none"], diff --git a/packages/react/src/schematics/library/library.spec.ts b/packages/react/src/schematics/library/library.spec.ts index c80dabc862c20..27cf04c961321 100644 --- a/packages/react/src/schematics/library/library.spec.ts +++ b/packages/react/src/schematics/library/library.spec.ts @@ -127,8 +127,7 @@ describe('lib', () => { { name: 'myLib2', directory: 'myDir', - tags: 'one,two', - simpleModuleName: true + tags: 'one,two' }, tree ); diff --git a/packages/react/src/schematics/ng-add/ng-add.spec.ts b/packages/react/src/schematics/ng-add/ng-add.spec.ts index 68e4d1c750e7c..153ae89147fad 100644 --- a/packages/react/src/schematics/ng-add/ng-add.spec.ts +++ b/packages/react/src/schematics/ng-add/ng-add.spec.ts @@ -29,7 +29,7 @@ describe('ng-add', () => { const result = await runSchematic('ng-add', {}, tree); const workspaceJson = readJsonInTree(result, 'workspace.json'); expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/react'); - expect(workspaceJson.schematics['@nrwl/react:application'].babel).toBe( + expect(workspaceJson.schematics['@nrwl/react'].application.babel).toBe( true ); }); @@ -48,7 +48,7 @@ describe('ng-add', () => { const result = await runSchematic('ng-add', {}, tree); const workspaceJson = readJsonInTree(result, 'workspace.json'); expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/react'); - expect(workspaceJson.schematics['@nrwl/react:application'].babel).toBe( + expect(workspaceJson.schematics['@nrwl/react'].application.babel).toBe( true ); }); @@ -69,9 +69,6 @@ describe('ng-add', () => { const result = await runSchematic('ng-add', {}, tree); const workspaceJson = readJsonInTree(result, 'workspace.json'); expect(workspaceJson.cli.defaultCollection).toEqual('@nrwl/angular'); - expect( - workspaceJson.schematics['@nrwl/react:application'] - ).not.toBeDefined(); }); }); }); diff --git a/packages/react/src/schematics/ng-add/ng-add.ts b/packages/react/src/schematics/ng-add/ng-add.ts index 192485dfaa346..1d1702ac29525 100644 --- a/packages/react/src/schematics/ng-add/ng-add.ts +++ b/packages/react/src/schematics/ng-add/ng-add.ts @@ -41,8 +41,8 @@ function moveDependency(): Rule { function setDefault(): Rule { return updateWorkspace(workspace => { + // Set workspace default collection to 'react' if not already set. workspace.extensions.cli = workspace.extensions.cli || {}; - const defaultCollection: string = workspace.extensions.cli && ((workspace.extensions.cli as JsonObject).defaultCollection as string); @@ -50,20 +50,29 @@ function setDefault(): Rule { if (!defaultCollection || defaultCollection === '@nrwl/workspace') { (workspace.extensions.cli as JsonObject).defaultCollection = '@nrwl/react'; + } - // Also generate apps with babel option by default. - workspace.extensions.schematics = { - ...(workspace.extensions.schematics - ? (workspace.extensions.schematics as JsonObject) - : {}), - '@nrwl/react:application': { + // Also generate all new react apps with babel. + workspace.extensions.schematics = + jsonIdentity(workspace.extensions.schematics) || {}; + const reactSchematics = + jsonIdentity(workspace.extensions.schematics['@nrwl/react']) || {}; + workspace.extensions.schematics = { + ...workspace.extensions.schematics, + '@nrwl/react': { + application: { + ...jsonIdentity(reactSchematics.application), babel: true } - }; - } + } + }; }); } +function jsonIdentity(x: any): JsonObject { + return x as JsonObject; +} + export default function(schema: Schema) { return chain([ setDefault(),