Skip to content

Commit e4eee62

Browse files
committed
refactor(@schematics/angular): update type usage to support isolated declarations
This commit addresses various TypeScript compilation errors that arise when the 'isolatedDeclarations' option is enabled.
1 parent fab1a9b commit e4eee62

File tree

19 files changed

+452
-386
lines changed

19 files changed

+452
-386
lines changed

packages/schematics/angular/app-shell/index.ts

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
import { Rule, SchematicsException, Tree, chain, schematic } from '@angular-devkit/schematics';
9+
import {
10+
Rule,
11+
RuleFactory,
12+
SchematicsException,
13+
Tree,
14+
chain,
15+
schematic,
16+
} from '@angular-devkit/schematics';
1017
import { dirname, join } from 'node:path/posix';
1118
import ts from '../third_party/github.com/Microsoft/TypeScript/lib/typescript';
1219
import {
@@ -190,19 +197,23 @@ function addServerRoutingConfig(options: AppShellOptions, isStandalone: boolean)
190197
};
191198
}
192199

193-
export default createProjectSchematic<AppShellOptions>(async (options, { tree }) => {
194-
const browserEntryPoint = await getMainFilePath(tree, options.project);
195-
const isStandalone = isStandaloneApp(tree, browserEntryPoint);
196-
197-
return chain([
198-
validateProject(browserEntryPoint),
199-
schematic('server', options),
200-
addServerRoutingConfig(options, isStandalone),
201-
schematic('component', {
202-
name: 'app-shell',
203-
module: 'app.module.server.ts',
204-
project: options.project,
205-
standalone: isStandalone,
206-
}),
207-
]);
208-
});
200+
const appShellSchematic: RuleFactory<AppShellOptions> = createProjectSchematic(
201+
async (options, { tree }) => {
202+
const browserEntryPoint = await getMainFilePath(tree, options.project);
203+
const isStandalone = isStandaloneApp(tree, browserEntryPoint);
204+
205+
return chain([
206+
validateProject(browserEntryPoint),
207+
schematic('server', options),
208+
addServerRoutingConfig(options, isStandalone),
209+
schematic('component', {
210+
name: 'app-shell',
211+
module: 'app.module.server.ts',
212+
project: options.project,
213+
standalone: isStandalone,
214+
}),
215+
]);
216+
},
217+
);
218+
219+
export default appShellSchematic;

packages/schematics/angular/component/index.ts

Lines changed: 57 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import {
1010
FileOperator,
11-
Rule,
11+
RuleFactory,
1212
apply,
1313
applyTemplates,
1414
chain,
@@ -40,60 +40,65 @@ function buildSelector(options: ComponentOptions, projectPrefix: string) {
4040
return selector;
4141
}
4242

43-
export default createProjectSchematic<ComponentOptions>((options, { project, tree }) => {
44-
if (options.path === undefined) {
45-
options.path = buildDefaultPath(project);
46-
}
43+
const componentSchematic: RuleFactory<ComponentOptions> = createProjectSchematic(
44+
(options, { project, tree }) => {
45+
if (options.path === undefined) {
46+
options.path = buildDefaultPath(project);
47+
}
48+
49+
options.module = findModuleFromOptions(tree, options);
50+
// Schematic templates require a defined type value
51+
options.type ??= '';
4752

48-
options.module = findModuleFromOptions(tree, options);
49-
// Schematic templates require a defined type value
50-
options.type ??= '';
53+
const parsedPath = parseName(options.path, options.name);
54+
options.name = parsedPath.name;
55+
options.path = parsedPath.path;
56+
options.selector =
57+
options.selector || buildSelector(options, (project && project.prefix) || '');
5158

52-
const parsedPath = parseName(options.path, options.name);
53-
options.name = parsedPath.name;
54-
options.path = parsedPath.path;
55-
options.selector = options.selector || buildSelector(options, (project && project.prefix) || '');
59+
validateHtmlSelector(options.selector);
5660

57-
validateHtmlSelector(options.selector);
61+
const classifiedName =
62+
strings.classify(options.name) +
63+
(options.addTypeToClassName && options.type ? strings.classify(options.type) : '');
64+
validateClassName(classifiedName);
65+
const zoneless = isZonelessApp(project);
5866

59-
const classifiedName =
60-
strings.classify(options.name) +
61-
(options.addTypeToClassName && options.type ? strings.classify(options.type) : '');
62-
validateClassName(classifiedName);
63-
const zoneless = isZonelessApp(project);
67+
const skipStyleFile = options.inlineStyle || options.style === Style.None;
68+
const templateSource = apply(url('./files'), [
69+
options.skipTests ? filter((path) => !path.endsWith('.spec.ts.template')) : noop(),
70+
skipStyleFile ? filter((path) => !path.endsWith('.__style__.template')) : noop(),
71+
options.inlineTemplate ? filter((path) => !path.endsWith('.html.template')) : noop(),
72+
applyTemplates({
73+
...strings,
74+
'if-flat': (s: string) => (options.flat ? '' : s),
75+
'ngext': options.ngHtml ? '.ng' : '',
76+
...options,
77+
// Add a new variable for the classified name, conditionally including the type
78+
classifiedName,
79+
zoneless,
80+
}),
81+
!options.type
82+
? forEach(((file) => {
83+
return file.path.includes('..')
84+
? {
85+
content: file.content,
86+
path: file.path.replace('..', '.'),
87+
}
88+
: file;
89+
}) as FileOperator)
90+
: noop(),
91+
move(parsedPath.path),
92+
]);
6493

65-
const skipStyleFile = options.inlineStyle || options.style === Style.None;
66-
const templateSource = apply(url('./files'), [
67-
options.skipTests ? filter((path) => !path.endsWith('.spec.ts.template')) : noop(),
68-
skipStyleFile ? filter((path) => !path.endsWith('.__style__.template')) : noop(),
69-
options.inlineTemplate ? filter((path) => !path.endsWith('.html.template')) : noop(),
70-
applyTemplates({
71-
...strings,
72-
'if-flat': (s: string) => (options.flat ? '' : s),
73-
'ngext': options.ngHtml ? '.ng' : '',
74-
...options,
75-
// Add a new variable for the classified name, conditionally including the type
76-
classifiedName,
77-
zoneless,
78-
}),
79-
!options.type
80-
? forEach(((file) => {
81-
return file.path.includes('..')
82-
? {
83-
content: file.content,
84-
path: file.path.replace('..', '.'),
85-
}
86-
: file;
87-
}) as FileOperator)
88-
: noop(),
89-
move(parsedPath.path),
90-
]);
94+
return chain([
95+
addDeclarationToNgModule({
96+
type: 'component',
97+
...options,
98+
}),
99+
mergeWith(templateSource),
100+
]);
101+
},
102+
);
91103

92-
return chain([
93-
addDeclarationToNgModule({
94-
type: 'component',
95-
...options,
96-
}),
97-
mergeWith(templateSource),
98-
]);
99-
});
104+
export default componentSchematic;

packages/schematics/angular/config/index.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import {
1010
Rule,
11+
RuleFactory,
1112
SchematicsException,
1213
apply,
1314
applyTemplates,
@@ -24,18 +25,22 @@ import { updateWorkspace } from '../utility/workspace';
2425
import { Builders as AngularBuilder } from '../utility/workspace-models';
2526
import { Schema as ConfigOptions, Type as ConfigType } from './schema';
2627

27-
export default createProjectSchematic<ConfigOptions>((options, { project }) => {
28-
switch (options.type) {
29-
case ConfigType.Karma:
30-
return addKarmaConfig(options);
31-
case ConfigType.Browserslist:
32-
return addBrowserslistConfig(project.root);
33-
case ConfigType.Vitest:
34-
return addVitestConfig(options);
35-
default:
36-
throw new SchematicsException(`"${options.type}" is an unknown configuration file type.`);
37-
}
38-
});
28+
const configSchematic: RuleFactory<ConfigOptions> = createProjectSchematic(
29+
(options, { project }) => {
30+
switch (options.type) {
31+
case ConfigType.Karma:
32+
return addKarmaConfig(options);
33+
case ConfigType.Browserslist:
34+
return addBrowserslistConfig(project.root);
35+
case ConfigType.Vitest:
36+
return addVitestConfig(options);
37+
default:
38+
throw new SchematicsException(`"${options.type}" is an unknown configuration file type.`);
39+
}
40+
},
41+
);
42+
43+
export default configSchematic;
3944

4045
function addVitestConfig(options: ConfigOptions): Rule {
4146
return (tree, context) =>

packages/schematics/angular/directive/index.ts

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
import { Rule, chain, strings } from '@angular-devkit/schematics';
9+
import { RuleFactory, chain, strings } from '@angular-devkit/schematics';
1010
import { addDeclarationToNgModule } from '../utility/add-declaration-to-ng-module';
1111
import { findModuleFromOptions } from '../utility/find-module';
1212
import { generateFromFiles } from '../utility/generate-from-files';
@@ -27,32 +27,36 @@ function buildSelector(options: DirectiveOptions, projectPrefix: string) {
2727
return strings.camelize(selector);
2828
}
2929

30-
export default createProjectSchematic<DirectiveOptions>((options, { project, tree }) => {
31-
if (options.path === undefined) {
32-
options.path = buildDefaultPath(project);
33-
}
34-
35-
options.module = findModuleFromOptions(tree, options);
36-
const parsedPath = parseName(options.path, options.name);
37-
options.name = parsedPath.name;
38-
options.path = parsedPath.path;
39-
options.selector = options.selector || buildSelector(options, project.prefix || '');
40-
41-
validateHtmlSelector(options.selector);
42-
const classifiedName =
43-
strings.classify(options.name) +
44-
(options.addTypeToClassName && options.type ? strings.classify(options.type) : '');
45-
validateClassName(classifiedName);
46-
47-
return chain([
48-
addDeclarationToNgModule({
49-
type: 'directive',
50-
51-
...options,
52-
}),
53-
generateFromFiles({
54-
...options,
55-
classifiedName,
56-
}),
57-
]);
58-
});
30+
const directiveSchematic: RuleFactory<DirectiveOptions> = createProjectSchematic(
31+
(options, { project, tree }) => {
32+
if (options.path === undefined) {
33+
options.path = buildDefaultPath(project);
34+
}
35+
36+
options.module = findModuleFromOptions(tree, options);
37+
const parsedPath = parseName(options.path, options.name);
38+
options.name = parsedPath.name;
39+
options.path = parsedPath.path;
40+
options.selector = options.selector || buildSelector(options, project.prefix || '');
41+
42+
validateHtmlSelector(options.selector);
43+
const classifiedName =
44+
strings.classify(options.name) +
45+
(options.addTypeToClassName && options.type ? strings.classify(options.type) : '');
46+
validateClassName(classifiedName);
47+
48+
return chain([
49+
addDeclarationToNgModule({
50+
type: 'directive',
51+
52+
...options,
53+
}),
54+
generateFromFiles({
55+
...options,
56+
classifiedName,
57+
}),
58+
]);
59+
},
60+
);
61+
62+
export default directiveSchematic;

0 commit comments

Comments
 (0)