Skip to content

Commit 0ab1ddf

Browse files
committed
feat(@schematics/angular): generate libraries using TypeScript project references
When generating a project (via `ng generate library`), the created TypeScript configuration files (`tsconfig.lib.json`/`tsconfig.spec.json`) will be setup as composite projects and added as project references in the root `tsconfig.json`. This transforms the root `tsconfig.json` into a "solution" style configuration. This allows IDEs to more accurately discover and provide type information for the varying types of files (test, library, etc.) within each project. The Angular build process is otherwise unaffected by these changes.
1 parent 84e7267 commit 0ab1ddf

File tree

4 files changed

+43
-2
lines changed

4 files changed

+43
-2
lines changed

packages/schematics/angular/library/files/tsconfig.lib.json.template

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
"inlineSources": true,
1010
"types": []
1111
},
12+
"include": [
13+
"src/**/*.ts"
14+
],
1215
"exclude": [
1316
"**/*.spec.ts"
1417
]

packages/schematics/angular/library/files/tsconfig.spec.json.template

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
]
1010
},
1111
"include": [
12-
"**/*.spec.ts",
13-
"**/*.d.ts"
12+
"src/**/*.ts"
1413
]
1514
}

packages/schematics/angular/library/index.ts

+21
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,21 @@ function updateTsConfig(packageName: string, ...paths: string[]) {
4343
};
4444
}
4545

46+
function addTsProjectReference(...paths: string[]) {
47+
return (host: Tree) => {
48+
if (!host.exists('tsconfig.json')) {
49+
return host;
50+
}
51+
52+
const newReferences = paths.map((path) => ({ path }));
53+
54+
const file = new JSONFile(host, 'tsconfig.json');
55+
const jsonPath = ['references'];
56+
const value = file.get(jsonPath);
57+
file.modify(jsonPath, Array.isArray(value) ? [...value, ...newReferences] : newReferences);
58+
};
59+
}
60+
4661
function addDependenciesToPackageJson() {
4762
return (host: Tree) => {
4863
[
@@ -162,6 +177,12 @@ export default function (options: LibraryOptions): Rule {
162177
addLibToWorkspaceFile(options, libDir, packageName),
163178
options.skipPackageJson ? noop() : addDependenciesToPackageJson(),
164179
options.skipTsConfig ? noop() : updateTsConfig(packageName, './' + distRoot),
180+
options.skipTsConfig
181+
? noop()
182+
: addTsProjectReference(
183+
'./' + join(libDir, 'tsconfig.lib.json'),
184+
'./' + join(libDir, 'tsconfig.spec.json'),
185+
),
165186
options.standalone
166187
? noop()
167188
: schematic('module', {

packages/schematics/angular/library/index_spec.ts

+18
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,24 @@ describe('Library Schematic', () => {
293293

294294
const tsConfigJson = getJsonFileContent(tree, 'tsconfig.json');
295295
expect(tsConfigJson.compilerOptions.paths).toBeUndefined();
296+
expect(tsConfigJson.references).not.toContain(
297+
jasmine.objectContaining({ path: './projects/foo/tsconfig.lib.json' }),
298+
);
299+
expect(tsConfigJson.references).not.toContain(
300+
jasmine.objectContaining({ path: './projects/foo/tsconfig.spec.json' }),
301+
);
302+
});
303+
304+
it('should add project references in the root tsconfig.json', async () => {
305+
const tree = await schematicRunner.runSchematic('library', defaultOptions, workspaceTree);
306+
307+
const { references } = getJsonFileContent(tree, '/tsconfig.json');
308+
expect(references).toContain(
309+
jasmine.objectContaining({ path: './projects/foo/tsconfig.lib.json' }),
310+
);
311+
expect(references).toContain(
312+
jasmine.objectContaining({ path: './projects/foo/tsconfig.spec.json' }),
313+
);
296314
});
297315
});
298316

0 commit comments

Comments
 (0)