Skip to content

Commit cbce3d3

Browse files
clydinalexeagle
authored andcommittedApr 15, 2019
refactor(@schematics/angular): update library to use new workspace rules
1 parent 2210b90 commit cbce3d3

File tree

2 files changed

+102
-103
lines changed

2 files changed

+102
-103
lines changed
 

‎packages/schematics/angular/library/index.ts

Lines changed: 49 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,12 @@ import {
2121
url,
2222
} from '@angular-devkit/schematics';
2323
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
24-
import {
25-
addProjectToWorkspace,
26-
getWorkspace,
27-
} from '../utility/config';
2824
import { NodeDependencyType, addPackageJsonDependency } from '../utility/dependencies';
2925
import { latestVersions } from '../utility/latest-versions';
3026
import { applyLintFix } from '../utility/lint-fix';
3127
import { validateProjectName } from '../utility/validation';
32-
import {
33-
Builders,
34-
ProjectType,
35-
WorkspaceProject,
36-
WorkspaceSchema,
37-
} from '../utility/workspace-models';
28+
import { getWorkspace, updateWorkspace } from '../utility/workspace';
29+
import { Builders, ProjectType } from '../utility/workspace-models';
3830
import { Schema as LibraryOptions } from './schema';
3931

4032
interface UpdateJsonFn<T> {
@@ -126,50 +118,57 @@ function addDependenciesToPackageJson() {
126118
};
127119
}
128120

129-
function addAppToWorkspaceFile(options: LibraryOptions, workspace: WorkspaceSchema,
130-
projectRoot: string, projectName: string): Rule {
131-
132-
const project: WorkspaceProject<ProjectType.Library> = {
133-
root: projectRoot,
134-
sourceRoot: `${projectRoot}/src`,
135-
projectType: ProjectType.Library,
136-
prefix: options.prefix || 'lib',
137-
architect: {
138-
build: {
139-
builder: Builders.NgPackagr,
140-
options: {
141-
tsConfig: `${projectRoot}/tsconfig.lib.json`,
142-
project: `${projectRoot}/ng-package.json`,
121+
function addAppToWorkspaceFile(
122+
options: LibraryOptions,
123+
projectRoot: string,
124+
projectName: string,
125+
): Rule {
126+
return updateWorkspace(workspace => {
127+
if (workspace.projects.size === 0) {
128+
workspace.extensions.defaultProject = projectName;
129+
}
130+
131+
workspace.projects.add({
132+
name: projectName,
133+
root: projectRoot,
134+
sourceRoot: `${projectRoot}/src`,
135+
projectType: ProjectType.Library,
136+
prefix: options.prefix || 'lib',
137+
targets: {
138+
build: {
139+
builder: Builders.NgPackagr,
140+
options: {
141+
tsConfig: `${projectRoot}/tsconfig.lib.json`,
142+
project: `${projectRoot}/ng-package.json`,
143+
},
143144
},
144-
},
145-
test: {
146-
builder: Builders.Karma,
147-
options: {
148-
main: `${projectRoot}/src/test.ts`,
149-
tsConfig: `${projectRoot}/tsconfig.spec.json`,
150-
karmaConfig: `${projectRoot}/karma.conf.js`,
145+
test: {
146+
builder: Builders.Karma,
147+
options: {
148+
main: `${projectRoot}/src/test.ts`,
149+
tsConfig: `${projectRoot}/tsconfig.spec.json`,
150+
karmaConfig: `${projectRoot}/karma.conf.js`,
151+
},
151152
},
152-
},
153-
lint: {
154-
builder: Builders.TsLint,
155-
options: {
156-
tsConfig: [
157-
`${projectRoot}/tsconfig.lib.json`,
158-
`${projectRoot}/tsconfig.spec.json`,
159-
],
160-
exclude: [
161-
'**/node_modules/**',
162-
],
153+
lint: {
154+
builder: Builders.TsLint,
155+
options: {
156+
tsConfig: [
157+
`${projectRoot}/tsconfig.lib.json`,
158+
`${projectRoot}/tsconfig.spec.json`,
159+
],
160+
exclude: [
161+
'**/node_modules/**',
162+
],
163+
},
163164
},
164165
},
165-
},
166-
};
167-
168-
return addProjectToWorkspace(workspace, projectName, project);
166+
});
167+
});
169168
}
170169

171170
export default function (options: LibraryOptions): Rule {
172-
return (host: Tree, context: SchematicContext) => {
171+
return async (host: Tree) => {
173172
if (!options.name) {
174173
throw new SchematicsException(`Invalid options, "name" is required.`);
175174
}
@@ -187,8 +186,8 @@ export default function (options: LibraryOptions): Rule {
187186
options.name = name;
188187
}
189188

190-
const workspace = getWorkspace(host);
191-
const newProjectRoot = workspace.newProjectRoot || '';
189+
const workspace = await getWorkspace(host);
190+
const newProjectRoot = workspace.extensions.newProjectRoot || '';
192191

193192
const scopeFolder = scopeName ? strings.dasherize(scopeName) + '/' : '';
194193
const folderName = `${scopeFolder}${strings.dasherize(options.name)}`;
@@ -215,7 +214,7 @@ export default function (options: LibraryOptions): Rule {
215214

216215
return chain([
217216
mergeWith(templateSource),
218-
addAppToWorkspaceFile(options, workspace, projectRoot, projectName),
217+
addAppToWorkspaceFile(options, projectRoot, projectName),
219218
options.skipPackageJson ? noop() : addDependenciesToPackageJson(),
220219
options.skipTsConfig ? noop() : updateTsConfig(packageName, distRoot),
221220
schematic('module', {

‎packages/schematics/angular/library/index_spec.ts

Lines changed: 53 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ describe('Library Schematic', () => {
4141
workspaceTree = schematicRunner.runSchematic('workspace', workspaceOptions);
4242
});
4343

44-
it('should create files', () => {
45-
const tree = schematicRunner.runSchematic('library', defaultOptions, workspaceTree);
44+
it('should create files', async () => {
45+
const tree = await schematicRunner.runSchematicAsync('library', defaultOptions, workspaceTree).toPromise();
4646
const files = tree.files;
4747
expect(files).toEqual(jasmine.arrayContaining([
4848
'/projects/foo/karma.conf.js',
@@ -60,81 +60,81 @@ describe('Library Schematic', () => {
6060
]));
6161
});
6262

63-
it('should create a package.json named "foo"', () => {
64-
const tree = schematicRunner.runSchematic('library', defaultOptions, workspaceTree);
63+
it('should create a package.json named "foo"', async () => {
64+
const tree = await schematicRunner.runSchematicAsync('library', defaultOptions, workspaceTree).toPromise();
6565
const fileContent = getFileContent(tree, '/projects/foo/package.json');
6666
expect(fileContent).toMatch(/"name": "foo"/);
6767
});
6868

69-
it('should have the latest Angular major versions in package.json named "foo"', () => {
70-
const tree = schematicRunner.runSchematic('library', defaultOptions, workspaceTree);
69+
it('should have the latest Angular major versions in package.json named "foo"', async () => {
70+
const tree = await schematicRunner.runSchematicAsync('library', defaultOptions, workspaceTree).toPromise();
7171
const fileContent = getJsonFileContent(tree, '/projects/foo/package.json');
7272
const angularVersion = latestVersions.Angular.replace('~', '').replace('^', '');
7373
expect(fileContent.peerDependencies['@angular/core']).toBe(`^${angularVersion}`);
7474
});
7575

76-
it('should create a README.md named "foo"', () => {
77-
const tree = schematicRunner.runSchematic('library', defaultOptions, workspaceTree);
76+
it('should create a README.md named "foo"', async () => {
77+
const tree = await schematicRunner.runSchematicAsync('library', defaultOptions, workspaceTree).toPromise();
7878
const fileContent = getFileContent(tree, '/projects/foo/README.md');
7979
expect(fileContent).toMatch(/# Foo/);
8080
});
8181

82-
it('should create a tsconfig for library', () => {
83-
const tree = schematicRunner.runSchematic('library', defaultOptions, workspaceTree);
82+
it('should create a tsconfig for library', async () => {
83+
const tree = await schematicRunner.runSchematicAsync('library', defaultOptions, workspaceTree).toPromise();
8484
const fileContent = getJsonFileContent(tree, '/projects/foo/tsconfig.lib.json');
8585
expect(fileContent).toBeDefined();
8686
});
8787

88-
it('should create a ng-package.json with ngPackage conf', () => {
89-
const tree = schematicRunner.runSchematic('library', defaultOptions, workspaceTree);
88+
it('should create a ng-package.json with ngPackage conf', async () => {
89+
const tree = await schematicRunner.runSchematicAsync('library', defaultOptions, workspaceTree).toPromise();
9090
const fileContent = getJsonFileContent(tree, '/projects/foo/ng-package.json');
9191
expect(fileContent.lib).toBeDefined();
9292
expect(fileContent.lib.entryFile).toEqual('src/my-index.ts');
9393
expect(fileContent.dest).toEqual('../../dist/foo');
9494
});
9595

96-
it('should use default value for baseDir and entryFile', () => {
97-
const tree = schematicRunner.runSchematic('library', {
96+
it('should use default value for baseDir and entryFile', async () => {
97+
const tree = await schematicRunner.runSchematicAsync('library', {
9898
name: 'foobar',
99-
}, workspaceTree);
99+
}, workspaceTree).toPromise();
100100
expect(tree.files).toContain('/projects/foobar/src/public-api.ts');
101101
});
102102

103-
it(`should add library to workspace`, () => {
104-
const tree = schematicRunner.runSchematic('library', defaultOptions, workspaceTree);
103+
it(`should add library to workspace`, async () => {
104+
const tree = await schematicRunner.runSchematicAsync('library', defaultOptions, workspaceTree).toPromise();
105105

106106
const workspace = getJsonFileContent(tree, '/angular.json');
107107
expect(workspace.projects.foo).toBeDefined();
108108
expect(workspace.defaultProject).toBe('foo');
109109
});
110110

111-
it('should set the prefix to lib if none is set', () => {
112-
const tree = schematicRunner.runSchematic('library', defaultOptions, workspaceTree);
111+
it('should set the prefix to lib if none is set', async () => {
112+
const tree = await schematicRunner.runSchematicAsync('library', defaultOptions, workspaceTree).toPromise();
113113

114114
const workspace = JSON.parse(tree.readContent('/angular.json'));
115115
expect(workspace.projects.foo.prefix).toEqual('lib');
116116
});
117117

118-
it('should set the prefix correctly', () => {
118+
it('should set the prefix correctly', async () => {
119119
const options = { ...defaultOptions, prefix: 'pre' };
120-
const tree = schematicRunner.runSchematic('library', options, workspaceTree);
120+
const tree = await schematicRunner.runSchematicAsync('library', options, workspaceTree).toPromise();
121121

122122
const workspace = JSON.parse(tree.readContent('/angular.json'));
123123
expect(workspace.projects.foo.prefix).toEqual('pre');
124124
});
125125

126-
it('should set the right prefix in the tslint file when provided is kebabed', () => {
126+
it('should set the right prefix in the tslint file when provided is kebabed', async () => {
127127
const options: GenerateLibrarySchema = { ...defaultOptions, prefix: 'foo-bar' };
128-
const tree = schematicRunner.runSchematic('library', options, workspaceTree);
128+
const tree = await schematicRunner.runSchematicAsync('library', options, workspaceTree).toPromise();
129129
const path = '/projects/foo/tslint.json';
130130
const content = JSON.parse(tree.readContent(path));
131131
expect(content.rules['directive-selector'][2]).toMatch('fooBar');
132132
expect(content.rules['component-selector'][2]).toMatch('foo-bar');
133133
});
134134

135-
it('should handle a pascalCasedName', () => {
135+
it('should handle a pascalCasedName', async () => {
136136
const options = {...defaultOptions, name: 'pascalCasedName'};
137-
const tree = schematicRunner.runSchematic('library', options, workspaceTree);
137+
const tree = await schematicRunner.runSchematicAsync('library', options, workspaceTree).toPromise();
138138
const config = getJsonFileContent(tree, '/angular.json');
139139
const project = config.projects.pascalCasedName;
140140
expect(project).toBeDefined();
@@ -143,14 +143,14 @@ describe('Library Schematic', () => {
143143
expect(svcContent).toMatch(/providedIn: 'root'/);
144144
});
145145

146-
it('should export the component in the NgModule', () => {
147-
const tree = schematicRunner.runSchematic('library', defaultOptions, workspaceTree);
146+
it('should export the component in the NgModule', async () => {
147+
const tree = await schematicRunner.runSchematicAsync('library', defaultOptions, workspaceTree).toPromise();
148148
const fileContent = getFileContent(tree, '/projects/foo/src/lib/foo.module.ts');
149149
expect(fileContent).toContain('exports: [FooComponent]');
150150
});
151151

152-
it('should set the right path and prefix in the tslint file', () => {
153-
const tree = schematicRunner.runSchematic('library', defaultOptions, workspaceTree);
152+
it('should set the right path and prefix in the tslint file', async () => {
153+
const tree = await schematicRunner.runSchematicAsync('library', defaultOptions, workspaceTree).toPromise();
154154
const path = '/projects/foo/tslint.json';
155155
const content = JSON.parse(tree.readContent(path));
156156
expect(content.extends).toMatch('../../tslint.json');
@@ -159,39 +159,39 @@ describe('Library Schematic', () => {
159159
});
160160

161161
describe(`update package.json`, () => {
162-
it(`should add ng-packagr to devDependencies`, () => {
163-
const tree = schematicRunner.runSchematic('library', defaultOptions, workspaceTree);
162+
it(`should add ng-packagr to devDependencies`, async () => {
163+
const tree = await schematicRunner.runSchematicAsync('library', defaultOptions, workspaceTree).toPromise();
164164

165165
const packageJson = getJsonFileContent(tree, 'package.json');
166166
expect(packageJson.devDependencies['ng-packagr']).toEqual('^5.0.0');
167167
expect(packageJson.devDependencies['@angular-devkit/build-ng-packagr'])
168168
.toEqual(latestVersions.DevkitBuildNgPackagr);
169169
});
170170

171-
it('should use the latest known versions in package.json', () => {
172-
const tree = schematicRunner.runSchematic('library', defaultOptions, workspaceTree);
171+
it('should use the latest known versions in package.json', async () => {
172+
const tree = await schematicRunner.runSchematicAsync('library', defaultOptions, workspaceTree).toPromise();
173173
const pkg = JSON.parse(tree.readContent('/package.json'));
174174
expect(pkg.devDependencies['@angular/compiler-cli']).toEqual(latestVersions.Angular);
175175
expect(pkg.devDependencies['typescript']).toEqual(latestVersions.TypeScript);
176176
});
177177

178-
it(`should not override existing users dependencies`, () => {
178+
it(`should not override existing users dependencies`, async () => {
179179
const oldPackageJson = workspaceTree.readContent('package.json');
180180
workspaceTree.overwrite('package.json', oldPackageJson.replace(
181181
`"typescript": "${latestVersions.TypeScript}"`,
182182
`"typescript": "~2.5.2"`,
183183
));
184184

185-
const tree = schematicRunner.runSchematic('library', defaultOptions, workspaceTree);
185+
const tree = await schematicRunner.runSchematicAsync('library', defaultOptions, workspaceTree).toPromise();
186186
const packageJson = getJsonFileContent(tree, 'package.json');
187187
expect(packageJson.devDependencies.typescript).toEqual('~2.5.2');
188188
});
189189

190-
it(`should not modify the file when --skipPackageJson`, () => {
191-
const tree = schematicRunner.runSchematic('library', {
190+
it(`should not modify the file when --skipPackageJson`, async () => {
191+
const tree = await schematicRunner.runSchematicAsync('library', {
192192
name: 'foo',
193193
skipPackageJson: true,
194-
}, workspaceTree);
194+
}, workspaceTree).toPromise();
195195

196196
const packageJson = getJsonFileContent(tree, 'package.json');
197197
expect(packageJson.devDependencies['ng-packagr']).toBeUndefined();
@@ -200,8 +200,8 @@ describe('Library Schematic', () => {
200200
});
201201

202202
describe(`update tsconfig.json`, () => {
203-
it(`should add paths mapping to empty tsconfig`, () => {
204-
const tree = schematicRunner.runSchematic('library', defaultOptions, workspaceTree);
203+
it(`should add paths mapping to empty tsconfig`, async () => {
204+
const tree = await schematicRunner.runSchematicAsync('library', defaultOptions, workspaceTree).toPromise();
205205

206206
const tsConfigJson = getJsonFileContent(tree, 'tsconfig.json');
207207
expect(tsConfigJson.compilerOptions.paths.foo).toBeTruthy();
@@ -212,7 +212,7 @@ describe('Library Schematic', () => {
212212
expect(tsConfigJson.compilerOptions.paths['foo/*'][0]).toEqual('dist/foo/*');
213213
});
214214

215-
it(`should append to existing paths mappings`, () => {
215+
it(`should append to existing paths mappings`, async () => {
216216
workspaceTree.overwrite('tsconfig.json', JSON.stringify({
217217
compilerOptions: {
218218
paths: {
@@ -221,27 +221,27 @@ describe('Library Schematic', () => {
221221
},
222222
},
223223
}));
224-
const tree = schematicRunner.runSchematic('library', defaultOptions, workspaceTree);
224+
const tree = await schematicRunner.runSchematicAsync('library', defaultOptions, workspaceTree).toPromise();
225225

226226
const tsConfigJson = getJsonFileContent(tree, 'tsconfig.json');
227227
expect(tsConfigJson.compilerOptions.paths.foo).toBeTruthy();
228228
expect(tsConfigJson.compilerOptions.paths.foo.length).toEqual(2);
229229
expect(tsConfigJson.compilerOptions.paths.foo[1]).toEqual('dist/foo');
230230
});
231231

232-
it(`should not modify the file when --skipTsConfig`, () => {
233-
const tree = schematicRunner.runSchematic('library', {
232+
it(`should not modify the file when --skipTsConfig`, async () => {
233+
const tree = await schematicRunner.runSchematicAsync('library', {
234234
name: 'foo',
235235
skipTsConfig: true,
236-
}, workspaceTree);
236+
}, workspaceTree).toPromise();
237237

238238
const tsConfigJson = getJsonFileContent(tree, 'tsconfig.json');
239239
expect(tsConfigJson.compilerOptions.paths).toBeUndefined();
240240
});
241241
});
242242

243-
it('should generate inside of a library', () => {
244-
let tree = schematicRunner.runSchematic('library', defaultOptions, workspaceTree);
243+
it('should generate inside of a library', async () => {
244+
let tree = await schematicRunner.runSchematicAsync('library', defaultOptions, workspaceTree).toPromise();
245245
const componentOptions: ComponentOptions = {
246246
name: 'comp',
247247
project: 'foo',
@@ -250,10 +250,10 @@ describe('Library Schematic', () => {
250250
expect(tree.exists('/projects/foo/src/lib/comp/comp.component.ts')).toBe(true);
251251
});
252252

253-
it(`should support creating scoped libraries`, () => {
253+
it(`should support creating scoped libraries`, async () => {
254254
const scopedName = '@myscope/mylib';
255255
const options = { ...defaultOptions, name: scopedName };
256-
const tree = schematicRunner.runSchematic('library', options, workspaceTree);
256+
const tree = await schematicRunner.runSchematicAsync('library', options, workspaceTree).toPromise();
257257

258258
const pkgJsonPath = '/projects/myscope/mylib/package.json';
259259
expect(tree.files).toContain(pkgJsonPath);
@@ -276,12 +276,12 @@ describe('Library Schematic', () => {
276276
expect(karmaConf).toContain(`dir: require('path').join(__dirname, '../../../coverage/myscope/mylib')`);
277277
});
278278

279-
it(`should dasherize scoped libraries`, () => {
279+
it(`should dasherize scoped libraries`, async () => {
280280
const scopedName = '@myScope/myLib';
281281
const expectedScopeName = '@my-scope/my-lib';
282282
const expectedFolderName = 'my-scope/my-lib';
283283
const options = { ...defaultOptions, name: scopedName };
284-
const tree = schematicRunner.runSchematic('library', options, workspaceTree);
284+
const tree = await schematicRunner.runSchematicAsync('library', options, workspaceTree).toPromise();
285285

286286
const pkgJsonPath = '/projects/my-scope/my-lib/package.json';
287287
expect(tree.readContent(pkgJsonPath)).toContain(expectedScopeName);
@@ -296,8 +296,8 @@ describe('Library Schematic', () => {
296296
expect(cfg.projects['@myScope/myLib']).toBeDefined();
297297
});
298298

299-
it(`should set coverage folder to "coverage/foo"`, () => {
300-
const tree = schematicRunner.runSchematic('library', defaultOptions, workspaceTree);
299+
it(`should set coverage folder to "coverage/foo"`, async () => {
300+
const tree = await schematicRunner.runSchematicAsync('library', defaultOptions, workspaceTree).toPromise();
301301
const karmaConf = getFileContent(tree, '/projects/foo/karma.conf.js');
302302
expect(karmaConf).toContain(`dir: require('path').join(__dirname, '../../coverage/foo')`);
303303
});

0 commit comments

Comments
 (0)
Please sign in to comment.