@rhtml/schematics 0.0.133 → 0.0.134
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/component/schema.json +1 -1
- package/dist/lib/controller/schema.json +1 -1
- package/dist/lib/module/schema.json +4 -4
- package/dist/lib/provider/schema.json +4 -4
- package/dist/lib/service/schema.json +3 -3
- package/dist/utils/metadata.manager.d.ts +65 -2
- package/dist/utils/metadata.manager.js +103 -23
- package/dist/utils/metadata.manager.ts +127 -46
- package/dist/utils/module-import.declarator.d.ts +31 -2
- package/dist/utils/module-import.declarator.js +42 -10
- package/dist/utils/module-import.declarator.ts +45 -12
- package/dist/utils/module-metadata.declarator.d.ts +12 -0
- package/dist/utils/module-metadata.declarator.js +13 -1
- package/dist/utils/module-metadata.declarator.ts +13 -1
- package/dist/utils/module.declarator.d.ts +21 -1
- package/dist/utils/module.declarator.js +23 -1
- package/dist/utils/module.declarator.ts +24 -2
- package/dist/utils/module.finder.d.ts +12 -0
- package/dist/utils/module.finder.js +13 -1
- package/dist/utils/module.finder.ts +13 -1
- package/dist/utils/name.parser.d.ts +6 -0
- package/dist/utils/name.parser.js +6 -0
- package/dist/utils/name.parser.ts +6 -0
- package/dist/utils/path.solver.d.ts +7 -0
- package/dist/utils/path.solver.js +7 -0
- package/dist/utils/path.solver.ts +7 -0
- package/dist/utils/source-root.helpers.d.ts +13 -1
- package/dist/utils/source-root.helpers.js +13 -1
- package/dist/utils/source-root.helpers.ts +14 -2
- package/package.json +5 -5
- package/src/lib/component/schema.json +1 -1
- package/src/lib/controller/schema.json +1 -1
- package/src/lib/module/schema.json +4 -4
- package/src/lib/provider/schema.json +4 -4
- package/src/lib/service/schema.json +3 -3
- package/src/utils/metadata.manager.ts +127 -46
- package/src/utils/module-import.declarator.ts +45 -12
- package/src/utils/module-metadata.declarator.ts +13 -1
- package/src/utils/module.declarator.ts +24 -2
- package/src/utils/module.finder.ts +13 -1
- package/src/utils/name.parser.ts +6 -0
- package/src/utils/path.solver.ts +7 -0
- package/src/utils/source-root.helpers.ts +14 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rhtml/schematics",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.134",
|
|
4
4
|
"description": "Reactive HyperText Markup Language",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"start": "npx parcel ./examples/index.html --out-dir build/examples",
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
"build": "rm -rf dist && tsc || true && rsync -a --prune-empty-dirs --include '*/' --include '*' --exclude '*' src/ dist/"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@angular-devkit/core": "^
|
|
19
|
-
"@angular-devkit/schematics": "^
|
|
20
|
-
"@angular-devkit/schematics-cli": "^
|
|
21
|
-
"ts-morph": "^
|
|
18
|
+
"@angular-devkit/core": "^19.2.0",
|
|
19
|
+
"@angular-devkit/schematics": "^19.2.0",
|
|
20
|
+
"@angular-devkit/schematics-cli": "^19.2.0",
|
|
21
|
+
"ts-morph": "^25.0.1"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {},
|
|
24
24
|
"repository": {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "http://json-schema.org/schema",
|
|
3
|
-
"id": "
|
|
4
|
-
"title": "
|
|
3
|
+
"$id": "SchematicsRhtmlModule",
|
|
4
|
+
"title": "Rhtml Module Options Schema",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"properties": {
|
|
7
7
|
"name": {
|
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
},
|
|
26
26
|
"language": {
|
|
27
27
|
"type": "string",
|
|
28
|
-
"description": "
|
|
28
|
+
"description": "Rhtml module language (ts/js)."
|
|
29
29
|
},
|
|
30
30
|
"sourceRoot": {
|
|
31
31
|
"type": "string",
|
|
32
|
-
"description": "
|
|
32
|
+
"description": "Rhtml module source root directory."
|
|
33
33
|
},
|
|
34
34
|
"skipImport": {
|
|
35
35
|
"description": "Flag to skip the module import.",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "http://json-schema.org/schema",
|
|
3
|
-
"id": "
|
|
4
|
-
"title": "
|
|
3
|
+
"$id": "SchematicsRhtmlProvider",
|
|
4
|
+
"title": "Rhtml Provider Options Schema",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"properties": {
|
|
7
7
|
"name": {
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
},
|
|
21
21
|
"language": {
|
|
22
22
|
"type": "string",
|
|
23
|
-
"description": "
|
|
23
|
+
"description": "Rhtml provider language (ts/js)."
|
|
24
24
|
},
|
|
25
25
|
"sourceRoot": {
|
|
26
26
|
"type": "string",
|
|
27
|
-
"description": "
|
|
27
|
+
"description": "Rhtml provider source root directory."
|
|
28
28
|
},
|
|
29
29
|
"flat": {
|
|
30
30
|
"default": true,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "http://json-schema.org/schema",
|
|
3
|
-
"id": "
|
|
4
|
-
"title": "
|
|
3
|
+
"$id": "SchematicsRhtmlService",
|
|
4
|
+
"title": "Rhtml Service Options Schema",
|
|
5
5
|
"type": "object",
|
|
6
6
|
"properties": {
|
|
7
7
|
"name": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"language": {
|
|
22
22
|
"type": "string",
|
|
23
|
-
"description": "
|
|
23
|
+
"description": "Rhtml service language (ts/js)."
|
|
24
24
|
},
|
|
25
25
|
"sourceRoot": {
|
|
26
26
|
"type": "string",
|
|
@@ -12,49 +12,68 @@ import {
|
|
|
12
12
|
PropertyAssignment,
|
|
13
13
|
ScriptTarget,
|
|
14
14
|
SourceFile,
|
|
15
|
-
StringLiteral,
|
|
16
15
|
SyntaxKind,
|
|
17
16
|
} from 'typescript';
|
|
18
17
|
|
|
19
18
|
import { DeclarationOptions } from './module.declarator';
|
|
20
19
|
|
|
20
|
+
/**
|
|
21
|
+
* The `MetadataManager` class provides utilities for managing metadata entries
|
|
22
|
+
* within a `@Module` decorator in a TypeScript source file. It allows for the
|
|
23
|
+
* insertion of new metadata entries, merging symbols with static options, and
|
|
24
|
+
* handling various scenarios such as empty module decorators or existing metadata
|
|
25
|
+
* properties.
|
|
26
|
+
*/
|
|
21
27
|
export class MetadataManager {
|
|
22
28
|
constructor(private content: string) {}
|
|
23
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Inserts a new metadata entry into the `@Module` decorator.
|
|
32
|
+
*
|
|
33
|
+
* @param metadata - The metadata key to insert.
|
|
34
|
+
* @param symbol - The symbol to insert.
|
|
35
|
+
* @param staticOptions - The static options to insert.
|
|
36
|
+
* @returns The new content string.
|
|
37
|
+
*/
|
|
24
38
|
public insert(
|
|
25
39
|
metadata: string,
|
|
26
40
|
symbol: string,
|
|
27
41
|
staticOptions?: DeclarationOptions['staticOptions']
|
|
28
|
-
): string {
|
|
42
|
+
): string | undefined {
|
|
29
43
|
const source: SourceFile = createSourceFile(
|
|
30
44
|
'filename.ts',
|
|
31
45
|
this.content,
|
|
32
46
|
ScriptTarget.ES2017
|
|
33
47
|
);
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
const moduleDecoratorNode = this.findFirstDecoratorMetadata(
|
|
49
|
+
source,
|
|
50
|
+
'Module'
|
|
51
|
+
);
|
|
52
|
+
// If there is no occurrence of `@Module` decorator, nothing will be inserted
|
|
53
|
+
if (!moduleDecoratorNode) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const matchingProperties: ObjectLiteralElement[] =
|
|
57
|
+
moduleDecoratorNode.properties
|
|
58
|
+
.filter((prop) => prop.kind === SyntaxKind.PropertyAssignment)
|
|
59
|
+
.filter((prop: PropertyAssignment) => {
|
|
60
|
+
const name = prop.name;
|
|
61
|
+
switch (name.kind) {
|
|
62
|
+
case SyntaxKind.Identifier:
|
|
63
|
+
return name.getText(source) === metadata;
|
|
64
|
+
case SyntaxKind.StringLiteral:
|
|
65
|
+
return name.text === metadata;
|
|
66
|
+
default:
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
51
70
|
|
|
52
71
|
symbol = this.mergeSymbolAndExpr(symbol, staticOptions);
|
|
53
72
|
const addBlankLinesIfDynamic = () => {
|
|
54
73
|
symbol = staticOptions ? this.addBlankLines(symbol) : symbol;
|
|
55
74
|
};
|
|
56
75
|
if (matchingProperties.length === 0) {
|
|
57
|
-
const expr =
|
|
76
|
+
const expr = moduleDecoratorNode;
|
|
58
77
|
if (expr.properties.length === 0) {
|
|
59
78
|
addBlankLinesIfDynamic();
|
|
60
79
|
return this.insertMetadataToEmptyModuleDecorator(
|
|
@@ -81,38 +100,68 @@ export class MetadataManager {
|
|
|
81
100
|
}
|
|
82
101
|
}
|
|
83
102
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
103
|
+
/**
|
|
104
|
+
* Finds the first `@Module` decorator metadata in the source file.
|
|
105
|
+
*
|
|
106
|
+
* @param source - The source file to search.
|
|
107
|
+
* @param identifier - The identifier to match.
|
|
108
|
+
* @returns The first matching `ObjectLiteralExpression` or undefined.
|
|
109
|
+
*/
|
|
110
|
+
private findFirstDecoratorMetadata(
|
|
111
|
+
source: SourceFile,
|
|
112
|
+
identifier: string
|
|
113
|
+
): ObjectLiteralExpression | undefined {
|
|
114
|
+
for (const node of this.getSourceNodes(source)) {
|
|
115
|
+
const isDecoratorFactoryNode =
|
|
116
|
+
node.kind === SyntaxKind.Decorator &&
|
|
117
|
+
(node as Decorator).expression.kind === SyntaxKind.CallExpression;
|
|
118
|
+
if (!isDecoratorFactoryNode) continue;
|
|
119
|
+
|
|
120
|
+
const expr = (node as Decorator).expression as CallExpression;
|
|
121
|
+
|
|
122
|
+
const isExpectedExpression =
|
|
123
|
+
expr.arguments[0]?.kind === SyntaxKind.ObjectLiteralExpression;
|
|
124
|
+
if (!isExpectedExpression) continue;
|
|
125
|
+
|
|
126
|
+
if (expr.expression.kind === SyntaxKind.Identifier) {
|
|
127
|
+
const escapedText = (expr.expression as Identifier).escapedText;
|
|
128
|
+
const isTargetIdentifier = escapedText
|
|
129
|
+
? escapedText.toLowerCase() === identifier.toLowerCase()
|
|
130
|
+
: true;
|
|
131
|
+
if (isTargetIdentifier) {
|
|
132
|
+
return expr.arguments[0] as ObjectLiteralExpression;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
99
136
|
}
|
|
100
137
|
|
|
138
|
+
/**
|
|
139
|
+
* Returns an array of all nodes in the source file.
|
|
140
|
+
*/
|
|
101
141
|
private getSourceNodes(sourceFile: SourceFile): Node[] {
|
|
102
142
|
const nodes: Node[] = [sourceFile];
|
|
103
|
-
const result = [];
|
|
143
|
+
const result: Node[] = [];
|
|
104
144
|
while (nodes.length > 0) {
|
|
105
145
|
const node = nodes.shift();
|
|
106
146
|
if (node) {
|
|
107
147
|
result.push(node);
|
|
108
148
|
if (node.getChildCount(sourceFile) >= 0) {
|
|
109
|
-
nodes.unshift(...node.getChildren());
|
|
149
|
+
nodes.unshift(...node.getChildren(sourceFile));
|
|
110
150
|
}
|
|
111
151
|
}
|
|
112
152
|
}
|
|
113
153
|
return result;
|
|
114
154
|
}
|
|
115
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Inserts a new metadata entry into an empty `@Module` decorator.
|
|
158
|
+
* This method is called when the `@Module` decorator has no properties.
|
|
159
|
+
* It inserts the metadata and symbol into the decorator.
|
|
160
|
+
* @param expr - The `@Module` decorator node.
|
|
161
|
+
* @param metadata - The metadata key to insert.
|
|
162
|
+
* @param symbol - The symbol to insert.
|
|
163
|
+
* @returns The new content string.
|
|
164
|
+
*/
|
|
116
165
|
private insertMetadataToEmptyModuleDecorator(
|
|
117
166
|
expr: ObjectLiteralExpression,
|
|
118
167
|
metadata: string,
|
|
@@ -129,6 +178,16 @@ export class MetadataManager {
|
|
|
129
178
|
}, '');
|
|
130
179
|
}
|
|
131
180
|
|
|
181
|
+
/**
|
|
182
|
+
* Inserts a new symbol into an existing metadata property in the `@Module` decorator.
|
|
183
|
+
* This method is called when the metadata property already exists in the decorator.
|
|
184
|
+
* It inserts the symbol into the existing metadata property.
|
|
185
|
+
* @param source - The source file.
|
|
186
|
+
* @param matchingProperties - The matching metadata properties.
|
|
187
|
+
* @param symbol - The symbol to insert.
|
|
188
|
+
* @param staticOptions - The static options to insert.
|
|
189
|
+
* @returns The new content string.
|
|
190
|
+
*/
|
|
132
191
|
private insertNewMetadataToDecorator(
|
|
133
192
|
expr: ObjectLiteralExpression,
|
|
134
193
|
source: SourceFile,
|
|
@@ -140,7 +199,7 @@ export class MetadataManager {
|
|
|
140
199
|
const text = node.getFullText(source);
|
|
141
200
|
const matches = text.match(/^\r?\n\s*/);
|
|
142
201
|
let toInsert: string;
|
|
143
|
-
if (matches
|
|
202
|
+
if (matches) {
|
|
144
203
|
toInsert = `,${matches[0]}${metadata}: [${symbol}]`;
|
|
145
204
|
} else {
|
|
146
205
|
toInsert = `, ${metadata}: [${symbol}]`;
|
|
@@ -154,6 +213,16 @@ export class MetadataManager {
|
|
|
154
213
|
}, '');
|
|
155
214
|
}
|
|
156
215
|
|
|
216
|
+
/**
|
|
217
|
+
* Inserts a new symbol into an existing metadata property in the `@Module` decorator.
|
|
218
|
+
* This method is called when the metadata property already exists in the decorator.
|
|
219
|
+
* It inserts the symbol into the existing metadata property.
|
|
220
|
+
* @param source - The source file.
|
|
221
|
+
* @param matchingProperties - The matching metadata properties.
|
|
222
|
+
* @param symbol - The symbol to insert.
|
|
223
|
+
* @param staticOptions - The static options to insert.
|
|
224
|
+
* @returns The new content string.
|
|
225
|
+
*/
|
|
157
226
|
private insertSymbolToMetadata(
|
|
158
227
|
source: SourceFile,
|
|
159
228
|
matchingProperties: ObjectLiteralElement[],
|
|
@@ -163,13 +232,17 @@ export class MetadataManager {
|
|
|
163
232
|
const assignment = matchingProperties[0] as PropertyAssignment;
|
|
164
233
|
let node: Node | NodeArray<Expression>;
|
|
165
234
|
const arrLiteral = assignment.initializer as ArrayLiteralExpression;
|
|
235
|
+
if (!arrLiteral.elements) {
|
|
236
|
+
// "imports" is not an array but rather function/constant
|
|
237
|
+
return this.content;
|
|
238
|
+
}
|
|
166
239
|
if (arrLiteral.elements.length === 0) {
|
|
167
240
|
node = arrLiteral;
|
|
168
241
|
} else {
|
|
169
242
|
node = arrLiteral.elements;
|
|
170
243
|
}
|
|
171
244
|
if (Array.isArray(node)) {
|
|
172
|
-
const nodeArray = node as
|
|
245
|
+
const nodeArray = node as unknown as Node[];
|
|
173
246
|
const symbolsArray = nodeArray.map((childNode) =>
|
|
174
247
|
childNode.getText(source)
|
|
175
248
|
);
|
|
@@ -186,11 +259,10 @@ export class MetadataManager {
|
|
|
186
259
|
toInsert = staticOptions ? this.addBlankLines(symbol) : `${symbol}`;
|
|
187
260
|
} else {
|
|
188
261
|
const text = (node as Node).getFullText(source);
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
262
|
+
const itemSeparator = (text.match(/^\r?\n(\r?)\s+/) ||
|
|
263
|
+
text.match(/^\r?\n/) ||
|
|
264
|
+
' ')[0];
|
|
265
|
+
toInsert = `,${itemSeparator}${symbol}`;
|
|
194
266
|
}
|
|
195
267
|
return this.content.split('').reduce((content, char, index) => {
|
|
196
268
|
if (index === position) {
|
|
@@ -201,6 +273,12 @@ export class MetadataManager {
|
|
|
201
273
|
}, '');
|
|
202
274
|
}
|
|
203
275
|
|
|
276
|
+
/**
|
|
277
|
+
* Merges a symbol with static options into a single string.
|
|
278
|
+
* @param symbol - The symbol to merge.
|
|
279
|
+
* @param staticOptions - The static options to merge.
|
|
280
|
+
* @returns The merged string.
|
|
281
|
+
*/
|
|
204
282
|
private mergeSymbolAndExpr(
|
|
205
283
|
symbol: string,
|
|
206
284
|
staticOptions?: DeclarationOptions['staticOptions']
|
|
@@ -210,13 +288,16 @@ export class MetadataManager {
|
|
|
210
288
|
}
|
|
211
289
|
const spacing = 6;
|
|
212
290
|
let options = JSON.stringify(staticOptions.value, null, spacing);
|
|
213
|
-
options = options.replace(
|
|
214
|
-
options = options.replace(
|
|
291
|
+
options = options.replace(/"([^(")"]+)":/g, '$1:');
|
|
292
|
+
options = options.replace(/"/g, `'`);
|
|
215
293
|
options = options.slice(0, options.length - 1) + ' }';
|
|
216
294
|
symbol += `.${staticOptions.name}(${options})`;
|
|
217
295
|
return symbol;
|
|
218
296
|
}
|
|
219
297
|
|
|
298
|
+
/**
|
|
299
|
+
* Adds blank lines around an expression.
|
|
300
|
+
*/
|
|
220
301
|
private addBlankLines(expr: string): string {
|
|
221
302
|
return `\n ${expr}\n `;
|
|
222
303
|
}
|
|
@@ -3,31 +3,64 @@ import { normalize, Path } from '@angular-devkit/core';
|
|
|
3
3
|
import { DeclarationOptions } from './module.declarator';
|
|
4
4
|
import { PathSolver } from './path.solver';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* The `ModuleImportDeclarator` class is responsible for declaring module imports
|
|
8
|
+
* in a TypeScript file. It provides methods to insert import statements into the
|
|
9
|
+
* file content based on the provided declaration options.
|
|
10
|
+
*/
|
|
6
11
|
export class ModuleImportDeclarator {
|
|
7
12
|
constructor(private solver: PathSolver = new PathSolver()) {}
|
|
8
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Declares a module import in the given content string.
|
|
16
|
+
*
|
|
17
|
+
* @param content - The content of the file where the import will be declared.
|
|
18
|
+
* @param options - The options for the declaration, including the symbol and path.
|
|
19
|
+
* @returns The updated content string with the import statement inserted.
|
|
20
|
+
*/
|
|
9
21
|
public declare(content: string, options: DeclarationOptions): string {
|
|
10
|
-
const toInsert
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
return
|
|
22
|
+
const toInsert = this.buildLineToInsert(options);
|
|
23
|
+
const contentLines = content.split('\n');
|
|
24
|
+
const finalImportIndex = this.findImportsEndpoint(contentLines);
|
|
25
|
+
contentLines.splice(finalImportIndex + 1, 0, toInsert);
|
|
26
|
+
return contentLines.join('\n');
|
|
15
27
|
}
|
|
16
28
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Finds the endpoint of the existing import statements in the content.
|
|
31
|
+
*
|
|
32
|
+
* @param contentLines - The lines of the content.
|
|
33
|
+
* @returns The index of the last import statement.
|
|
34
|
+
*/
|
|
35
|
+
private findImportsEndpoint(contentLines: string[]): number {
|
|
36
|
+
const reversedContent = Array.from(contentLines).reverse();
|
|
37
|
+
const reverseImports = reversedContent.filter((line) =>
|
|
38
|
+
line.match(/\} from ('|")/)
|
|
39
|
+
);
|
|
40
|
+
if (reverseImports.length <= 0) {
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
return contentLines.indexOf(reverseImports[0]);
|
|
23
44
|
}
|
|
24
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Builds the import line to insert based on the declaration options.
|
|
48
|
+
*
|
|
49
|
+
* @param options - The options for the declaration, including the symbol and path.
|
|
50
|
+
* @returns The import line to insert.
|
|
51
|
+
*/
|
|
25
52
|
private buildLineToInsert(options: DeclarationOptions): string {
|
|
26
53
|
return `import { ${options.symbol} } from '${this.computeRelativePath(
|
|
27
54
|
options
|
|
28
|
-
)}'
|
|
55
|
+
)}';`;
|
|
29
56
|
}
|
|
30
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Computes the relative path for the import statement.
|
|
60
|
+
*
|
|
61
|
+
* @param options - The options for the declaration, including the symbol and path.
|
|
62
|
+
* @returns The relative path for the import statement.
|
|
63
|
+
*/
|
|
31
64
|
private computeRelativePath(options: DeclarationOptions): string {
|
|
32
65
|
let importModulePath: Path;
|
|
33
66
|
if (options.type !== undefined) {
|
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
import { MetadataManager } from './metadata.manager';
|
|
2
2
|
import { DeclarationOptions } from './module.declarator';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* The `ModuleMetadataDeclarator` class is responsible for declaring metadata
|
|
6
|
+
* in a TypeScript file. It provides methods to insert metadata entries into the
|
|
7
|
+
* file content based on the provided declaration options.
|
|
8
|
+
*/
|
|
4
9
|
export class ModuleMetadataDeclarator {
|
|
10
|
+
/**
|
|
11
|
+
* Declares metadata in the given content string.
|
|
12
|
+
*
|
|
13
|
+
* @param content - The content of the file where the metadata will be declared.
|
|
14
|
+
* @param options - The options for the declaration, including the metadata, symbol, and static options.
|
|
15
|
+
* @returns The updated content string with the metadata entry inserted.
|
|
16
|
+
*/
|
|
5
17
|
public declare(content: string, options: DeclarationOptions): string {
|
|
6
18
|
const manager = new MetadataManager(content);
|
|
7
19
|
const inserted = manager.insert(
|
|
@@ -9,6 +21,6 @@ export class ModuleMetadataDeclarator {
|
|
|
9
21
|
options.symbol,
|
|
10
22
|
options.staticOptions
|
|
11
23
|
);
|
|
12
|
-
return inserted;
|
|
24
|
+
return inserted ?? content;
|
|
13
25
|
}
|
|
14
26
|
}
|
|
@@ -8,21 +8,35 @@ export interface DeclarationOptions {
|
|
|
8
8
|
metadata: string;
|
|
9
9
|
type?: string;
|
|
10
10
|
name: string;
|
|
11
|
+
className?: string;
|
|
11
12
|
path: Path;
|
|
12
13
|
module: Path;
|
|
13
14
|
symbol?: string;
|
|
14
15
|
staticOptions?: {
|
|
15
16
|
name: string;
|
|
16
|
-
value: Record<string,
|
|
17
|
+
value: Record<string, never>;
|
|
17
18
|
};
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export class ModuleDeclarator {
|
|
22
|
+
/**
|
|
23
|
+
* Constructs a new `ModuleDeclarator` instance.
|
|
24
|
+
*
|
|
25
|
+
* @param imports - The `ModuleImportDeclarator` instance for handling import declarations.
|
|
26
|
+
* @param metadata - The `ModuleMetadataDeclarator` instance for handling metadata declarations.
|
|
27
|
+
*/
|
|
21
28
|
constructor(
|
|
22
29
|
private imports: ModuleImportDeclarator = new ModuleImportDeclarator(),
|
|
23
30
|
private metadata: ModuleMetadataDeclarator = new ModuleMetadataDeclarator()
|
|
24
31
|
) {}
|
|
25
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Declares module imports and metadata in the given content string.
|
|
35
|
+
*
|
|
36
|
+
* @param content - The content of the file where the declarations will be made.
|
|
37
|
+
* @param options - The options for the declaration, including the symbol and static options.
|
|
38
|
+
* @returns The updated content string with the declarations inserted.
|
|
39
|
+
*/
|
|
26
40
|
public declare(content: string, options: DeclarationOptions): string {
|
|
27
41
|
options = this.computeSymbol(options);
|
|
28
42
|
content = this.imports.declare(content, options);
|
|
@@ -30,9 +44,17 @@ export class ModuleDeclarator {
|
|
|
30
44
|
return content;
|
|
31
45
|
}
|
|
32
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Computes the symbol for the declaration options if not provided.
|
|
49
|
+
*
|
|
50
|
+
* @param options - The options for the declaration.
|
|
51
|
+
* @returns The updated declaration options with the computed symbol.
|
|
52
|
+
*/
|
|
33
53
|
private computeSymbol(options: DeclarationOptions): DeclarationOptions {
|
|
34
54
|
const target = Object.assign({}, options);
|
|
35
|
-
if (options.
|
|
55
|
+
if (options.className) {
|
|
56
|
+
target.symbol = options.className;
|
|
57
|
+
} else if (options.type !== undefined) {
|
|
36
58
|
target.symbol = classify(options.name).concat(capitalize(options.type));
|
|
37
59
|
} else {
|
|
38
60
|
target.symbol = classify(options.name);
|
|
@@ -10,6 +10,12 @@ export interface FindOptions {
|
|
|
10
10
|
export class ModuleFinder {
|
|
11
11
|
constructor(private tree: Tree) {}
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Finds the module file in the given path.
|
|
15
|
+
*
|
|
16
|
+
* @param options - The options for finding the module, including the path.
|
|
17
|
+
* @returns The path to the module file, or null if not found.
|
|
18
|
+
*/
|
|
13
19
|
public find(options: FindOptions): Path | null {
|
|
14
20
|
const generatedDirectoryPath: Path = options.path;
|
|
15
21
|
const generatedDirectory: DirEntry = this.tree.getDir(
|
|
@@ -18,12 +24,18 @@ export class ModuleFinder {
|
|
|
18
24
|
return this.findIn(generatedDirectory);
|
|
19
25
|
}
|
|
20
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Recursively searches for the module file in the given directory.
|
|
29
|
+
*
|
|
30
|
+
* @param directory - The directory to search in.
|
|
31
|
+
* @returns The path to the module file, or null if not found.
|
|
32
|
+
*/
|
|
21
33
|
private findIn(directory: DirEntry): Path | null {
|
|
22
34
|
if (!directory) {
|
|
23
35
|
return null;
|
|
24
36
|
}
|
|
25
37
|
const moduleFilename: PathFragment = directory.subfiles.find((filename) =>
|
|
26
|
-
/\.module\.(t|j)s
|
|
38
|
+
/\.module\.(t|j)s$/.test(filename)
|
|
27
39
|
);
|
|
28
40
|
return moduleFilename !== undefined
|
|
29
41
|
? join(directory.path, moduleFilename.valueOf())
|
package/src/utils/name.parser.ts
CHANGED
|
@@ -11,6 +11,12 @@ export interface Location {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export class NameParser {
|
|
14
|
+
/**
|
|
15
|
+
* Parses the provided options to extract the name and path.
|
|
16
|
+
*
|
|
17
|
+
* @param options - The options containing the name and path.
|
|
18
|
+
* @returns An object containing the parsed name and normalized path.
|
|
19
|
+
*/
|
|
14
20
|
public parse(options: ParseOptions): Location {
|
|
15
21
|
const nameWithoutPath: string = basename(options.name as Path);
|
|
16
22
|
const namePath: string = dirname(
|
package/src/utils/path.solver.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { basename, dirname, Path, relative } from '@angular-devkit/core';
|
|
2
2
|
|
|
3
3
|
export class PathSolver {
|
|
4
|
+
/**
|
|
5
|
+
* Computes the relative path between two paths.
|
|
6
|
+
*
|
|
7
|
+
* @param from - The source path.
|
|
8
|
+
* @param to - The target path.
|
|
9
|
+
* @returns The relative path between the two paths.
|
|
10
|
+
*/
|
|
4
11
|
public relative(from: Path, to: Path): string {
|
|
5
12
|
const placeholder = '/placeholder';
|
|
6
13
|
const relativeDir = relative(
|
|
@@ -3,16 +3,28 @@ import { Rule, Tree } from '@angular-devkit/schematics';
|
|
|
3
3
|
|
|
4
4
|
import { DEFAULT_PATH_NAME } from '../lib/defaults';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Checks if the current directory is the root directory.
|
|
8
|
+
*
|
|
9
|
+
* @param host - The file tree representing the project.
|
|
10
|
+
* @param extraFiles - Additional files to check for in the root directory.
|
|
11
|
+
* @returns True if the current directory is the root directory, otherwise false.
|
|
12
|
+
*/
|
|
6
13
|
export function isInRootDirectory(
|
|
7
14
|
host: Tree,
|
|
8
15
|
extraFiles: string[] = []
|
|
9
16
|
): boolean {
|
|
10
|
-
const files = [
|
|
17
|
+
const files = [].concat(extraFiles || []);
|
|
11
18
|
return files.map((file) => host.exists(file)).some((isPresent) => isPresent);
|
|
12
19
|
}
|
|
13
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Merges the source root with the provided options.
|
|
23
|
+
* @param options - The options to merge with the source root.
|
|
24
|
+
* @returns A rule to merge the source root with the provided options.
|
|
25
|
+
*/
|
|
14
26
|
export function mergeSourceRoot<
|
|
15
|
-
T extends { sourceRoot?: string; path?: string } =
|
|
27
|
+
T extends { sourceRoot?: string; path?: string } = never
|
|
16
28
|
>(options: T): Rule {
|
|
17
29
|
return (host: Tree) => {
|
|
18
30
|
const isInRoot = isInRootDirectory(host, ['tsconfig.json', 'package.json']);
|