Skip to content

Commit 8b7516d

Browse files
hanslfilipesilva
authored andcommitted
refactor: types for content should be a pure template
Limitting it to a subset of JSON values is limiting. Templates can call functions, list arrays, access classes, etc.
1 parent 1caf708 commit 8b7516d

File tree

1 file changed

+19
-14
lines changed
  • packages/angular_devkit/schematics/src/rules

1 file changed

+19
-14
lines changed

packages/angular_devkit/schematics/src/rules/template.ts

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,14 @@ export const kPathTemplateComponentRE = /__(.+?)__/g;
3131
export const kPathTemplatePipeRE = /@([^@]+)/;
3232

3333

34-
export type TemplateValue = boolean | string | number | undefined;
35-
export type TemplatePipeFunction = (x: string) => TemplateValue;
36-
export type TemplateOptions = {
37-
[key: string]: TemplateValue | TemplateOptions | TemplatePipeFunction,
34+
export type PathTemplateValue = boolean | string | number | undefined;
35+
export type PathTemplatePipeFunction = (x: string) => PathTemplateValue;
36+
export type PathTemplateOptions = {
37+
[key: string]: PathTemplateValue | PathTemplateOptions | PathTemplatePipeFunction,
3838
};
3939

4040

41-
export function applyContentTemplate<T extends TemplateOptions>(options: T): FileOperator {
41+
export function applyContentTemplate<T>(options: T): FileOperator {
4242
return (entry: FileEntry) => {
4343
const {path, content} = entry;
4444
if (isBinary(content)) {
@@ -53,12 +53,12 @@ export function applyContentTemplate<T extends TemplateOptions>(options: T): Fil
5353
}
5454

5555

56-
export function contentTemplate<T extends TemplateOptions>(options: T): Rule {
56+
export function contentTemplate<T>(options: T): Rule {
5757
return forEach(applyContentTemplate(options));
5858
}
5959

6060

61-
export function applyPathTemplate<T extends TemplateOptions>(options: T): FileOperator {
61+
export function applyPathTemplate<T extends PathTemplateOptions>(options: T): FileOperator {
6262
return (entry: FileEntry) => {
6363
let path = entry.path;
6464
const content = entry.content;
@@ -67,9 +67,11 @@ export function applyPathTemplate<T extends TemplateOptions>(options: T): FileOp
6767
// Path template.
6868
path = normalize(path.replace(kPathTemplateComponentRE, (_, match) => {
6969
const [name, ...pipes] = match.split(kPathTemplatePipeRE);
70-
const value = typeof options[name] == 'function'
71-
? (options[name] as TemplatePipeFunction).call(options, original)
72-
: options[name];
70+
let value = options[name];
71+
72+
if (typeof value == 'function') {
73+
value = value.call(options, original);
74+
}
7375

7476
if (value === undefined) {
7577
throw new OptionIsNotDefinedException(name);
@@ -87,7 +89,7 @@ export function applyPathTemplate<T extends TemplateOptions>(options: T): FileOp
8789
}
8890

8991
// Coerce to string.
90-
return '' + (options[pipe] as TemplatePipeFunction)(acc);
92+
return '' + (options[pipe] as PathTemplatePipeFunction)(acc);
9193
}, '' + value);
9294
}));
9395

@@ -96,14 +98,17 @@ export function applyPathTemplate<T extends TemplateOptions>(options: T): FileOp
9698
}
9799

98100

99-
export function pathTemplate<T extends TemplateOptions>(options: T): Rule {
101+
export function pathTemplate<T extends PathTemplateOptions>(options: T): Rule {
100102
return forEach(applyPathTemplate(options));
101103
}
102104

103105

104-
export function template<T extends TemplateOptions>(options: T): Rule {
106+
export function template<T>(options: T): Rule {
105107
return chain([
106108
contentTemplate(options),
107-
pathTemplate(options),
109+
// Force cast to PathTemplateOptions. We need the type for the actual pathTemplate() call,
110+
// but in this case we cannot do anything as contentTemplate are more permissive.
111+
// Since values are coerced to strings in PathTemplates it will be fine in the end.
112+
pathTemplate(options as {} as PathTemplateOptions),
108113
]);
109114
}

0 commit comments

Comments
 (0)