feat(nx): add presets to simplify the creation of workspaces with angular and fullstack apps
This commit is contained in:
parent
a6fd16d00e
commit
7f2c16f3a3
@ -6,3 +6,4 @@ node_modules
|
||||
packages/schematics/src/collection/**/files/*.json
|
||||
/.vscode
|
||||
/.idea
|
||||
/.github
|
||||
|
||||
@ -19,7 +19,7 @@ import {
|
||||
import { toClassName } from '@nrwl/schematics/src/utils/name-utils';
|
||||
|
||||
describe('Nrwl Workspace', () => {
|
||||
fit('should work', async () => {
|
||||
it('should work', async () => {
|
||||
ensureProject();
|
||||
const myapp = uniq('myapp');
|
||||
const mylib = uniq('mylib');
|
||||
|
||||
@ -14,7 +14,7 @@ import * as http from 'http';
|
||||
import * as path from 'path';
|
||||
import * as treeKill from 'tree-kill';
|
||||
|
||||
function getData() {
|
||||
function getData(): Promise<any> {
|
||||
return new Promise(resolve => {
|
||||
http.get('http://localhost:3333/api', res => {
|
||||
expect(res.statusCode).toEqual(200);
|
||||
@ -23,7 +23,7 @@ function getData() {
|
||||
data += chunk;
|
||||
});
|
||||
res.once('end', () => {
|
||||
resolve(data);
|
||||
resolve(JSON.parse(data));
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -77,7 +77,7 @@ describe('Node Applications', () => {
|
||||
expect(data.toString()).toContain('Listening at http://localhost:3333');
|
||||
const result = await getData();
|
||||
|
||||
expect(result).toEqual(`Welcome to ${nodeapp}!`);
|
||||
expect(result.message).toEqual(`Welcome to ${nodeapp}!`);
|
||||
treeKill(server.pid, 'SIGTERM', err => {
|
||||
expect(err).toBeFalsy();
|
||||
resolve();
|
||||
@ -118,7 +118,7 @@ describe('Node Applications', () => {
|
||||
}
|
||||
|
||||
const result = await getData();
|
||||
expect(result).toEqual(`Welcome to ${nodeapp}!`);
|
||||
expect(result.message).toEqual(`Welcome to ${nodeapp}!`);
|
||||
treeKill(process.pid, 'SIGTERM', err => {
|
||||
expect(collectedOutput.startsWith('DONE')).toBeTruthy();
|
||||
expect(err).toBeFalsy();
|
||||
@ -164,7 +164,7 @@ describe('Node Applications', () => {
|
||||
if (message.includes('Listening at http://localhost:3333')) {
|
||||
const result = await getData();
|
||||
|
||||
expect(result).toEqual(`Welcome to ${nestapp}!`);
|
||||
expect(result.message).toEqual(`Welcome to ${nestapp}!`);
|
||||
treeKill(server.pid, 'SIGTERM', err => {
|
||||
expect(err).toBeFalsy();
|
||||
resolve();
|
||||
@ -186,7 +186,7 @@ describe('Node Applications', () => {
|
||||
return;
|
||||
}
|
||||
const result = await getData();
|
||||
expect(result).toEqual(`Welcome to ${nestapp}!`);
|
||||
expect(result.message).toEqual(`Welcome to ${nestapp}!`);
|
||||
treeKill(process.pid, 'SIGTERM', err => {
|
||||
expect(err).toBeFalsy();
|
||||
done();
|
||||
|
||||
@ -51,6 +51,7 @@
|
||||
"tmp": "0.0.33",
|
||||
"viz.js": "^1.8.1",
|
||||
"yargs-parser": "10.0.0",
|
||||
"yargs": "^11.0.0"
|
||||
"yargs": "^11.0.0",
|
||||
"prettier": "1.15.3"
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +13,14 @@
|
||||
"ng-new": {
|
||||
"factory": "./collection/ng-new",
|
||||
"schema": "./collection/ng-new/schema.json",
|
||||
"description": "Create an empty workspace"
|
||||
"description": "Create a workspace"
|
||||
},
|
||||
|
||||
"workspace": {
|
||||
"factory": "./collection/workspace",
|
||||
"schema": "./collection/workspace/schema.json",
|
||||
"description": "Create an empty workspace",
|
||||
"hidden": true
|
||||
},
|
||||
|
||||
"application": {
|
||||
|
||||
@ -1,57 +1,200 @@
|
||||
import {
|
||||
apply,
|
||||
branchAndMerge,
|
||||
chain,
|
||||
mergeWith,
|
||||
move,
|
||||
noop,
|
||||
Rule,
|
||||
schematic,
|
||||
SchematicContext,
|
||||
template,
|
||||
Tree,
|
||||
url
|
||||
Tree
|
||||
} from '@angular-devkit/schematics';
|
||||
import { Schema } from './schema';
|
||||
import { strings } from '@angular-devkit/core';
|
||||
import { addImportToModule, insert } from '../../utils/ast-utils';
|
||||
import * as ts from 'typescript';
|
||||
import { insertImport } from '@schematics/angular/utility/ast-utils';
|
||||
import {
|
||||
NodePackageInstallTask,
|
||||
RepositoryInitializerTask
|
||||
} from '@angular-devkit/schematics/tasks';
|
||||
import { libVersions } from '../../lib-versions';
|
||||
import { DEFAULT_NRWL_PRETTIER_CONFIG } from '../../utils/common';
|
||||
|
||||
export default function(options: Schema): Rule {
|
||||
if (!options.name) {
|
||||
throw new Error(`Invalid options, "name" is required.`);
|
||||
}
|
||||
if (!options.directory) {
|
||||
options.directory = options.name;
|
||||
}
|
||||
|
||||
const workspaceOpts = { ...options, preset: undefined };
|
||||
return (host: Tree, context: SchematicContext) => {
|
||||
addTasks(options, context);
|
||||
const npmScope = options.npmScope ? options.npmScope : options.name;
|
||||
const templateSource = apply(url('./files'), [
|
||||
template({
|
||||
utils: strings,
|
||||
dot: '.',
|
||||
tmpl: '',
|
||||
...libVersions,
|
||||
...(options as object),
|
||||
npmScope,
|
||||
defaultNrwlPrettierConfig: JSON.stringify(
|
||||
DEFAULT_NRWL_PRETTIER_CONFIG,
|
||||
null,
|
||||
2
|
||||
return chain([
|
||||
schematic('workspace', workspaceOpts),
|
||||
createPreset(options),
|
||||
move('/', options.directory),
|
||||
addTasks(options)
|
||||
])(Tree.empty(), context);
|
||||
};
|
||||
}
|
||||
|
||||
function createPreset(options: Schema): Rule {
|
||||
if (options.preset === 'empty') {
|
||||
return noop();
|
||||
} else if (options.preset === 'angular') {
|
||||
return chain([
|
||||
schematic(
|
||||
'application',
|
||||
{ name: options.name, style: options.style },
|
||||
{ interactive: false }
|
||||
)
|
||||
})
|
||||
]);
|
||||
return chain([branchAndMerge(chain([mergeWith(templateSource)]))])(
|
||||
host,
|
||||
context
|
||||
} else {
|
||||
return chain([
|
||||
schematic(
|
||||
'application',
|
||||
{ name: options.name, style: options.style },
|
||||
{ interactive: false }
|
||||
),
|
||||
schematic(
|
||||
'node-application',
|
||||
{
|
||||
name: 'api',
|
||||
frontendProject: options.name
|
||||
},
|
||||
{ interactive: false }
|
||||
),
|
||||
schematic(
|
||||
'library',
|
||||
{ name: 'api-interface', framework: 'none' },
|
||||
{ interactive: false }
|
||||
),
|
||||
connectFrontendAndApi(options)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
function connectFrontendAndApi(options: Schema) {
|
||||
return (host: Tree) => {
|
||||
host.create(
|
||||
'libs/api-interface/src/lib/interfaces.ts',
|
||||
`export interface Message { message: string }`
|
||||
);
|
||||
host.overwrite(
|
||||
'libs/api-interface/src/index.ts',
|
||||
`export * from './lib/interfaces';`
|
||||
);
|
||||
|
||||
const modulePath = `apps/${options.name}/src/app/app.module.ts`;
|
||||
const moduleFile = ts.createSourceFile(
|
||||
modulePath,
|
||||
host.read(modulePath).toString(),
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
insert(host, modulePath, [
|
||||
insertImport(
|
||||
moduleFile,
|
||||
modulePath,
|
||||
'HttpClientModule',
|
||||
`@angular/common/http`
|
||||
),
|
||||
...addImportToModule(
|
||||
moduleFile,
|
||||
`@angular/common/http`,
|
||||
`HttpClientModule`
|
||||
)
|
||||
]);
|
||||
|
||||
const scope = options.npmScope ? options.npmScope : options.name;
|
||||
const style = options.style ? options.style : 'css';
|
||||
host.overwrite(
|
||||
`apps/${options.name}/src/app/app.component.ts`,
|
||||
`import { Component } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Message } from '@${scope}/api-interface';
|
||||
|
||||
@Component({
|
||||
selector: '${scope}-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.${style}']
|
||||
})
|
||||
export class AppComponent {
|
||||
hello$ = this.http.get<Message>('/api/hello')
|
||||
constructor(private http: HttpClient) {}
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
host.overwrite(
|
||||
`apps/${options.name}/src/app/app.component.spec.ts`,
|
||||
`import { Component } from '@angular/core';
|
||||
import { TestBed, async } from '@angular/core/testing';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [AppComponent],
|
||||
imports: [HttpClientModule]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
it('should create the app', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.debugElement.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
});
|
||||
});
|
||||
`
|
||||
);
|
||||
|
||||
host.overwrite(
|
||||
`apps/${options.name}/src/app/app.component.html`,
|
||||
`<div style="text-align:center">
|
||||
<h1>Welcome to ${options.name}!</h1>
|
||||
<img
|
||||
width="300"
|
||||
src="https://raw.githubusercontent.com/nrwl/nx/master/nx-logo.png"
|
||||
/>
|
||||
</div>
|
||||
<div>Message: {{ (hello$|async)|json }}</div>
|
||||
`
|
||||
);
|
||||
|
||||
host.overwrite(
|
||||
`apps/api/src/app/app.controller.ts`,
|
||||
`import { Controller, Get } from '@nestjs/common';
|
||||
|
||||
import { Message } from '@${scope}/api-interface';
|
||||
|
||||
import { AppService } from './app.service';
|
||||
|
||||
@Controller()
|
||||
export class AppController {
|
||||
constructor(private readonly appService: AppService) {}
|
||||
|
||||
@Get('hello')
|
||||
getData(): Message {
|
||||
return this.appService.getData();
|
||||
}
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
host.overwrite(
|
||||
`apps/api/src/app/app.service.ts`,
|
||||
`import { Injectable } from '@nestjs/common';
|
||||
import { Message } from '@${scope}/api-interface';
|
||||
|
||||
@Injectable()
|
||||
export class AppService {
|
||||
getData(): Message {
|
||||
return { message: 'Welcome to api!' };
|
||||
}
|
||||
}
|
||||
`
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
function addTasks(options: Schema, context: SchematicContext) {
|
||||
function addTasks(options: Schema) {
|
||||
return (host: Tree, context: SchematicContext) => {
|
||||
let packageTask;
|
||||
if (!options.skipInstall) {
|
||||
packageTask = context.addTask(
|
||||
@ -70,4 +213,5 @@ function addTasks(options: Schema, context: SchematicContext) {
|
||||
packageTask ? [packageTask] : []
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
|
||||
import * as path from 'path';
|
||||
import { Tree } from '@angular-devkit/schematics';
|
||||
import { readJsonInTree } from '../../utils/ast-utils';
|
||||
import { NxJson } from '../../command-line/shared';
|
||||
|
||||
describe('app', () => {
|
||||
describe('ng-new', () => {
|
||||
const schematicRunner = new SchematicTestRunner(
|
||||
'@nrwl/schematics',
|
||||
path.join(__dirname, '../../collection.json')
|
||||
@ -16,80 +14,29 @@ describe('app', () => {
|
||||
projectTree = Tree.empty();
|
||||
});
|
||||
|
||||
it('should update angular.json', () => {
|
||||
const tree = schematicRunner.runSchematic(
|
||||
it('should create files (preset = angular)', async () => {
|
||||
const tree = await schematicRunner
|
||||
.runSchematicAsync(
|
||||
'ng-new',
|
||||
{ name: 'proj' },
|
||||
{ name: 'proj', preset: 'angular' },
|
||||
projectTree
|
||||
);
|
||||
)
|
||||
.toPromise();
|
||||
expect(tree.exists('/proj/apps/proj/src/app/app.component.ts')).toBe(true);
|
||||
});
|
||||
|
||||
it('should create files', () => {
|
||||
const tree = schematicRunner.runSchematic(
|
||||
it('should create files (preset = fullstack)', async () => {
|
||||
const tree = await schematicRunner
|
||||
.runSchematicAsync(
|
||||
'ng-new',
|
||||
{ name: 'proj' },
|
||||
{ name: 'proj', preset: 'fullstack' },
|
||||
projectTree
|
||||
)
|
||||
.toPromise();
|
||||
expect(tree.exists('/proj/apps/proj/src/app/app.component.ts')).toBe(true);
|
||||
expect(tree.exists('/proj/apps/api/src/app/app.controller.ts')).toBe(true);
|
||||
expect(tree.exists('/proj/libs/api-interface/src/lib/interfaces.ts')).toBe(
|
||||
true
|
||||
);
|
||||
expect(tree.exists('/proj/nx.json')).toBe(true);
|
||||
expect(tree.exists('/proj/angular.json')).toBe(true);
|
||||
expect(tree.exists('/proj/.prettierrc')).toBe(true);
|
||||
expect(tree.exists('/proj/.prettierignore')).toBe(true);
|
||||
});
|
||||
|
||||
it('should create nx.json', () => {
|
||||
const tree = schematicRunner.runSchematic(
|
||||
'ng-new',
|
||||
{ name: 'proj' },
|
||||
projectTree
|
||||
);
|
||||
const nxJson = readJsonInTree<NxJson>(tree, '/proj/nx.json');
|
||||
expect(nxJson).toEqual({
|
||||
npmScope: 'proj',
|
||||
implicitDependencies: {
|
||||
'angular.json': '*',
|
||||
'package.json': '*',
|
||||
'tsconfig.json': '*',
|
||||
'tslint.json': '*',
|
||||
'nx.json': '*'
|
||||
},
|
||||
projects: {}
|
||||
});
|
||||
});
|
||||
|
||||
it('should recommend vscode extensions', () => {
|
||||
const tree = schematicRunner.runSchematic(
|
||||
'ng-new',
|
||||
{ name: 'proj' },
|
||||
projectTree
|
||||
);
|
||||
const recommendations = readJsonInTree<{ recommendations: string[] }>(
|
||||
tree,
|
||||
'/proj/.vscode/extensions.json'
|
||||
).recommendations;
|
||||
|
||||
expect(recommendations).toEqual([
|
||||
'nrwl.angular-console',
|
||||
'angular.ng-template',
|
||||
'ms-vscode.vscode-typescript-tslint-plugin',
|
||||
'esbenp.prettier-vscode'
|
||||
]);
|
||||
});
|
||||
|
||||
it('should configure the project to use style argument', () => {
|
||||
const tree = schematicRunner.runSchematic(
|
||||
'ng-new',
|
||||
{ name: 'proj', style: 'scss' },
|
||||
projectTree
|
||||
);
|
||||
expect(
|
||||
JSON.parse(tree.readContent('/proj/angular.json')).schematics
|
||||
).toEqual({
|
||||
'@nrwl/schematics:application': {
|
||||
style: 'scss'
|
||||
},
|
||||
'@nrwl/schematics:library': {
|
||||
style: 'scss'
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import { UnitTestRunner } from '../../utils/test-runners';
|
||||
|
||||
export interface Schema {
|
||||
directory: string;
|
||||
name: string;
|
||||
@ -7,5 +5,6 @@ export interface Schema {
|
||||
skipInstall?: boolean;
|
||||
skipGit?: boolean;
|
||||
style?: string;
|
||||
preset: 'empty' | 'angular' | 'fullstack';
|
||||
commit?: { name: string; email: string; message?: string };
|
||||
}
|
||||
|
||||
@ -74,6 +74,29 @@
|
||||
}
|
||||
],
|
||||
"default": true
|
||||
},
|
||||
"preset": {
|
||||
"description": "What to create in the new workspace",
|
||||
"enum": ["empty", "angular", "fullstack"],
|
||||
"default": "empty",
|
||||
"x-prompt": {
|
||||
"message": "What to create in the new workspace (You can create other applications and libraries at any point using 'ng g')",
|
||||
"type": "list",
|
||||
"items": [
|
||||
{
|
||||
"value": "empty",
|
||||
"label": "empty [an empty workspace]"
|
||||
},
|
||||
{
|
||||
"value": "angular",
|
||||
"label": "angular [a workspace with a single Angular application]"
|
||||
},
|
||||
{
|
||||
"value": "fullstack",
|
||||
"label": "full-stack [a workspace with a full stack application (NestJS + Angular)]"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ import * as express from 'express';
|
||||
const app = express();
|
||||
|
||||
app.get('/api', (req, res) => {
|
||||
res.send(`Welcome to <%= name %>!`);
|
||||
res.send({message: `Welcome to <%= name %>!`});
|
||||
});
|
||||
|
||||
const port = process.env.port || 3333;
|
||||
|
||||
@ -16,7 +16,7 @@ describe('AppController', () => {
|
||||
describe('getData', () => {
|
||||
it('should return "Welcome to <%= name %>!"', () => {
|
||||
const appController = app.get<AppController>(AppController);
|
||||
expect(appController.getData()).toBe('Welcome to <%= name %>!');
|
||||
expect(appController.getData()).toEqual({message: 'Welcome to <%= name %>!'});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -7,7 +7,7 @@ export class AppController {
|
||||
constructor(private readonly appService: AppService) {}
|
||||
|
||||
@Get()
|
||||
getData(): string {
|
||||
getData() {
|
||||
return this.appService.getData();
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ describe('AppService', () => {
|
||||
|
||||
describe('getData', () => {
|
||||
it('should return "Welcome to <%= name %>!"', () => {
|
||||
expect(service.getData()).toBe('Welcome to <%= name %>!');
|
||||
expect(service.getData()).toEqual({message: 'Welcome to <%= name %>!'});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class AppService {
|
||||
getData(): string {
|
||||
return 'Welcome to <%= name %>!';
|
||||
getData(): { message: string } {
|
||||
return ({ message: 'Welcome to <%= name %>!' });
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,7 +94,7 @@ describe('node-app', () => {
|
||||
'const app = express();'
|
||||
);
|
||||
expect(tree.readContent('apps/my-node-app/src/main.ts')).toContain(
|
||||
'res.send(`Welcome to my-node-app!`);'
|
||||
'res.send({message: `Welcome to my-node-app!`});'
|
||||
);
|
||||
|
||||
const tsconfig = readJsonInTree(tree, 'apps/my-node-app/tsconfig.json');
|
||||
|
||||
@ -5,11 +5,7 @@
|
||||
"rootDir": ".",
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"types": [
|
||||
"node"
|
||||
]
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts"
|
||||
]
|
||||
"include": ["**/*.ts"]
|
||||
}
|
||||
44
packages/schematics/src/collection/workspace/index.ts
Normal file
44
packages/schematics/src/collection/workspace/index.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import {
|
||||
apply,
|
||||
branchAndMerge,
|
||||
chain,
|
||||
mergeWith,
|
||||
Rule,
|
||||
SchematicContext,
|
||||
template,
|
||||
Tree,
|
||||
url
|
||||
} from '@angular-devkit/schematics';
|
||||
import { Schema } from './schema';
|
||||
import { strings } from '@angular-devkit/core';
|
||||
import { libVersions } from '../../lib-versions';
|
||||
import { DEFAULT_NRWL_PRETTIER_CONFIG } from '../../utils/common';
|
||||
|
||||
export default function(options: Schema): Rule {
|
||||
if (!options.name) {
|
||||
throw new Error(`Invalid options, "name" is required.`);
|
||||
}
|
||||
|
||||
return (host: Tree, context: SchematicContext) => {
|
||||
const npmScope = options.npmScope ? options.npmScope : options.name;
|
||||
const templateSource = apply(url('./files'), [
|
||||
template({
|
||||
utils: strings,
|
||||
dot: '.',
|
||||
tmpl: '',
|
||||
...libVersions,
|
||||
...(options as object),
|
||||
npmScope,
|
||||
defaultNrwlPrettierConfig: JSON.stringify(
|
||||
DEFAULT_NRWL_PRETTIER_CONFIG,
|
||||
null,
|
||||
2
|
||||
)
|
||||
})
|
||||
]);
|
||||
return chain([branchAndMerge(chain([mergeWith(templateSource)]))])(
|
||||
host,
|
||||
context
|
||||
);
|
||||
};
|
||||
}
|
||||
11
packages/schematics/src/collection/workspace/schema.d.ts
vendored
Normal file
11
packages/schematics/src/collection/workspace/schema.d.ts
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
import { UnitTestRunner } from '../../utils/test-runners';
|
||||
|
||||
export interface Schema {
|
||||
directory: string;
|
||||
name: string;
|
||||
npmScope?: string;
|
||||
skipInstall?: boolean;
|
||||
skipGit?: boolean;
|
||||
style?: string;
|
||||
commit?: { name: string; email: string; message?: string };
|
||||
}
|
||||
79
packages/schematics/src/collection/workspace/schema.json
Normal file
79
packages/schematics/src/collection/workspace/schema.json
Normal file
@ -0,0 +1,79 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"id": "SchematicsNxNgNew",
|
||||
"title": "Create an empty workspace",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "The name of the workspace.",
|
||||
"type": "string",
|
||||
"format": "html-selector",
|
||||
"$default": {
|
||||
"$source": "argv",
|
||||
"index": 0
|
||||
},
|
||||
"x-prompt": "What name would you like to use for the workspace?"
|
||||
},
|
||||
"style": {
|
||||
"description": "The file extension to be used for style files.",
|
||||
"type": "string",
|
||||
"default": "css",
|
||||
"x-prompt": {
|
||||
"message": "Which stylesheet format would you like to use?",
|
||||
"type": "list",
|
||||
"items": [
|
||||
{ "value": "css", "label": "CSS" },
|
||||
{ "value": "scss", "label": "SCSS [ http://sass-lang.com ]" },
|
||||
{ "value": "sass", "label": "SASS [ http://sass-lang.com ]" },
|
||||
{ "value": "less", "label": "LESS [ http://lesscss.org ]" },
|
||||
{ "value": "styl", "label": "Stylus [ http://stylus-lang.com ]" }
|
||||
]
|
||||
}
|
||||
},
|
||||
"directory": {
|
||||
"type": "string",
|
||||
"format": "path",
|
||||
"description": "The directory name to create the workspace in.",
|
||||
"default": ""
|
||||
},
|
||||
"npmScope": {
|
||||
"type": "string",
|
||||
"description": "Npm scope for importing libs.",
|
||||
"x-prompt": "What is the npm scope you would like to use for your Nx Workspace?"
|
||||
},
|
||||
"skipInstall": {
|
||||
"description": "Skip installing dependency packages.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"skipGit": {
|
||||
"description": "Skip initializing a git repository.",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"alias": "g"
|
||||
},
|
||||
"commit": {
|
||||
"description": "Initial repository commit information.",
|
||||
"oneOf": [
|
||||
{ "type": "boolean" },
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"email": {
|
||||
"type": "string",
|
||||
"format": "email"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": ["name", "email"]
|
||||
}
|
||||
],
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,93 @@
|
||||
import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
|
||||
import * as path from 'path';
|
||||
import { Tree } from '@angular-devkit/schematics';
|
||||
import { readJsonInTree } from '../../utils/ast-utils';
|
||||
import { NxJson } from '../../command-line/shared';
|
||||
|
||||
describe('workspace', () => {
|
||||
const schematicRunner = new SchematicTestRunner(
|
||||
'@nrwl/schematics',
|
||||
path.join(__dirname, '../../collection.json')
|
||||
);
|
||||
|
||||
let projectTree: Tree;
|
||||
|
||||
beforeEach(() => {
|
||||
projectTree = Tree.empty();
|
||||
});
|
||||
|
||||
it('should update angular.json', () => {
|
||||
const tree = schematicRunner.runSchematic(
|
||||
'workspace',
|
||||
{ name: 'proj' },
|
||||
projectTree
|
||||
);
|
||||
});
|
||||
|
||||
it('should create files', () => {
|
||||
const tree = schematicRunner.runSchematic(
|
||||
'workspace',
|
||||
{ name: 'proj' },
|
||||
projectTree
|
||||
);
|
||||
expect(tree.exists('/nx.json')).toBe(true);
|
||||
expect(tree.exists('/angular.json')).toBe(true);
|
||||
expect(tree.exists('/.prettierrc')).toBe(true);
|
||||
expect(tree.exists('/.prettierignore')).toBe(true);
|
||||
});
|
||||
|
||||
it('should create nx.json', () => {
|
||||
const tree = schematicRunner.runSchematic(
|
||||
'workspace',
|
||||
{ name: 'proj' },
|
||||
projectTree
|
||||
);
|
||||
const nxJson = readJsonInTree<NxJson>(tree, '/nx.json');
|
||||
expect(nxJson).toEqual({
|
||||
npmScope: 'proj',
|
||||
implicitDependencies: {
|
||||
'angular.json': '*',
|
||||
'package.json': '*',
|
||||
'tsconfig.json': '*',
|
||||
'tslint.json': '*',
|
||||
'nx.json': '*'
|
||||
},
|
||||
projects: {}
|
||||
});
|
||||
});
|
||||
|
||||
it('should recommend vscode extensions', () => {
|
||||
const tree = schematicRunner.runSchematic(
|
||||
'workspace',
|
||||
{ name: 'proj' },
|
||||
projectTree
|
||||
);
|
||||
const recommendations = readJsonInTree<{ recommendations: string[] }>(
|
||||
tree,
|
||||
'/.vscode/extensions.json'
|
||||
).recommendations;
|
||||
|
||||
expect(recommendations).toEqual([
|
||||
'nrwl.angular-console',
|
||||
'angular.ng-template',
|
||||
'ms-vscode.vscode-typescript-tslint-plugin',
|
||||
'esbenp.prettier-vscode'
|
||||
]);
|
||||
});
|
||||
|
||||
it('should configure the project to use style argument', () => {
|
||||
const tree = schematicRunner.runSchematic(
|
||||
'workspace',
|
||||
{ name: 'proj', style: 'scss' },
|
||||
projectTree
|
||||
);
|
||||
expect(JSON.parse(tree.readContent('/angular.json')).schematics).toEqual({
|
||||
'@nrwl/schematics:application': {
|
||||
style: 'scss'
|
||||
},
|
||||
'@nrwl/schematics:library': {
|
||||
style: 'scss'
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
50
yarn.lock
50
yarn.lock
@ -2,7 +2,7 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@angular-devkit/architect@0.13.1", "@angular-devkit/architect@~0.13.1":
|
||||
"@angular-devkit/architect@0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.13.1.tgz#39597ce94f72d89bdd89ee567cb937cff4c13b98"
|
||||
integrity sha512-QDmIbqde75ZZSEFbw6Q6kQWq4cY6C7D67yujXw6XTyubDNAs1tyXJyxTIB8vjSlEKwRizTTDd/B0ZXVcke3Mvw==
|
||||
@ -10,7 +10,7 @@
|
||||
"@angular-devkit/core" "7.3.1"
|
||||
rxjs "6.3.3"
|
||||
|
||||
"@angular-devkit/build-angular@~0.13.1":
|
||||
"@angular-devkit/build-angular@0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.13.1.tgz#369febda48dd40e47a4f0077064e792612a8e1c1"
|
||||
integrity sha512-vkKwMVQ+NNCcVR3HFMffS+Mq4b2afXeUjI+02N38hBuFTppnC83uivUB6Uu2NUk5NTSQA4BnJlG5CbMs6N4QYg==
|
||||
@ -62,7 +62,7 @@
|
||||
optionalDependencies:
|
||||
node-sass "4.11.0"
|
||||
|
||||
"@angular-devkit/build-ng-packagr@^0.13.1":
|
||||
"@angular-devkit/build-ng-packagr@0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/build-ng-packagr/-/build-ng-packagr-0.13.1.tgz#3508523a039f71ccff1364db553a904e4db2c8ea"
|
||||
integrity sha512-9qvdNvtlgJ3WDppbzwD9fOQzAsVogBlDeLE5zUH1ap+zcoyZEGjS1BKluiYSJ1u5Q5Nlfb3FSI/D1r9LuDQS/A==
|
||||
@ -82,7 +82,7 @@
|
||||
typescript "3.2.4"
|
||||
webpack-sources "1.3.0"
|
||||
|
||||
"@angular-devkit/build-webpack@0.13.1", "@angular-devkit/build-webpack@~0.13.1":
|
||||
"@angular-devkit/build-webpack@0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.13.1.tgz#98d666765705e9379c9b2e0a3b6dfcd0347a2a32"
|
||||
integrity sha512-OGwC7bAl3u+w7Glw+OqIrN7OD1BkDXgrWbeQSpKAmsx6VdNPCnI4NPS+JldWNp70LVlE2nQlJUhtEqMVfBMnlg==
|
||||
@ -102,10 +102,10 @@
|
||||
rxjs "6.3.3"
|
||||
source-map "0.7.3"
|
||||
|
||||
"@angular-devkit/core@7.2.4":
|
||||
version "7.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-7.2.4.tgz#4464d536f4838e5c61ab4bc1ff6b7f221fd43056"
|
||||
integrity sha512-XHF59tIHg2qEM1Wd415xhykBLjjfOK6yMB7CjNk1bToUMX2QDT87izJF4y1Vwa0lIw9G0jdgP/4/M/OqXcbYmA==
|
||||
"@angular-devkit/core@7.2.2":
|
||||
version "7.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-7.2.2.tgz#f0daf3e24f0ce8105341118f4505c1db4e284ab0"
|
||||
integrity sha512-gDF8iXiPN870WuBMl7bCQ5+Qz5SjGL/qMcvP4hli5hkn+kMAhgG38ligUK1bbhPQUJ+Z/nSOEmyv8gLHO09SZg==
|
||||
dependencies:
|
||||
ajv "6.6.2"
|
||||
chokidar "2.0.4"
|
||||
@ -132,12 +132,12 @@
|
||||
"@angular-devkit/core" "7.1.2"
|
||||
rxjs "6.3.3"
|
||||
|
||||
"@angular-devkit/schematics@7.2.4":
|
||||
version "7.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-7.2.4.tgz#d92b2b8b9114135806d593ea6a2b376c777354dc"
|
||||
integrity sha512-ObIDnIxXRpts+Jzs0PQ7JVuK4d5vWEh9K+Ow8nMO5/LmYJQ8/2nMEQo/9lhdKPMiXmhbuvB7qZL5J+cxwwijhw==
|
||||
"@angular-devkit/schematics@7.2.2":
|
||||
version "7.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-7.2.2.tgz#d8d667684603e1debcc4598d88a254560e787f87"
|
||||
integrity sha512-3qONTeqe+bUJ967PNDeITuD4F+3huTEs3u89zZLV+yvaxoK9XJlvaRoQXAkNAMUkij37BoFrGgBfGNijserd6A==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "7.2.4"
|
||||
"@angular-devkit/core" "7.2.2"
|
||||
rxjs "6.3.3"
|
||||
|
||||
"@angular-devkit/schematics@7.3.1", "@angular-devkit/schematics@~7.3.1":
|
||||
@ -148,7 +148,7 @@
|
||||
"@angular-devkit/core" "7.3.1"
|
||||
rxjs "6.3.3"
|
||||
|
||||
"@angular/cli@~7.3.1":
|
||||
"@angular/cli@7.3.1":
|
||||
version "7.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-7.3.1.tgz#a18acdec84deb03a1fae79cae415bbc8f9c87ffa"
|
||||
integrity sha512-8EvXYRhTqTaTk5PKv7VZxIWJiyG51R9RC9gtpRFx4bbnurqBHdEUxGMmaRsGT8QDbfvVsWnuakE0eeW1CrfZAQ==
|
||||
@ -461,6 +461,15 @@
|
||||
universal-user-agent "^2.0.0"
|
||||
url-template "^2.0.8"
|
||||
|
||||
"@schematics/angular@7.2.2":
|
||||
version "7.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-7.2.2.tgz#5a466ebbbd7e1fbb13851f26446ec308b822d1dc"
|
||||
integrity sha512-Yonddct1XBG1H5rTikagFTIT2/RhszJnNa2Iz+rvc26ffAl1mmYPB4sQb7gkOaZQSzK6SE7bT2QW32PVjYFoSQ==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "7.2.2"
|
||||
"@angular-devkit/schematics" "7.2.2"
|
||||
typescript "3.2.2"
|
||||
|
||||
"@schematics/angular@7.3.1":
|
||||
version "7.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-7.3.1.tgz#6fcd7004210fa9305310c3109c084df5c5521776"
|
||||
@ -470,15 +479,6 @@
|
||||
"@angular-devkit/schematics" "7.3.1"
|
||||
typescript "3.2.4"
|
||||
|
||||
"@schematics/angular@~7.2.2":
|
||||
version "7.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-7.2.4.tgz#4c3c942e2fd0c32e177602a20f8fa16a88552fca"
|
||||
integrity sha512-aflQwIX4E9tDhp6ZASuQCm8CzxLxdkuOe6qN1FbCxpxMUc9E+iK9jhOjw+Xnl3boJpWHAA+k9JO1sYe3wrh3Ng==
|
||||
dependencies:
|
||||
"@angular-devkit/core" "7.2.4"
|
||||
"@angular-devkit/schematics" "7.2.4"
|
||||
typescript "3.2.2"
|
||||
|
||||
"@schematics/update@0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.13.1.tgz#481475aee18b4a9472a06512b2e4d6429af68231"
|
||||
@ -3650,7 +3650,7 @@ cyclist@~0.2.2:
|
||||
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
|
||||
integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=
|
||||
|
||||
cypress@^3.1.0:
|
||||
cypress@3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.1.0.tgz#b718ba64289b887c7ab7a7f09245d871a4a409ba"
|
||||
integrity sha512-UqLbXgHvM8Y6Y+roHrepZMWcyMN5u4KcjpTbJTZi0d5O2Prvtqmnpoky7a4C65q4oRQXeSc6cBZUhxJkhU4pbQ==
|
||||
@ -12090,7 +12090,7 @@ typedarray@^0.0.6:
|
||||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||
|
||||
typescript@3.2.2, typescript@~3.2.2:
|
||||
typescript@3.2.2:
|
||||
version "3.2.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.2.2.tgz#fe8101c46aa123f8353523ebdcf5730c2ae493e5"
|
||||
integrity sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg==
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user