@rhtml/schematics 0.0.132 → 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/collection.json +6 -1
- package/dist/lib/component/schema.json +1 -1
- package/dist/lib/controller/controller.factory.d.ts +3 -0
- package/dist/lib/controller/controller.factory.js +62 -0
- package/dist/lib/controller/controller.factory.ts +92 -0
- package/dist/lib/controller/files/ts/__name__.controller.spec.ts +33 -0
- package/dist/lib/controller/files/ts/__name__.controller.ts +16 -0
- package/dist/lib/controller/schema.json +49 -0
- 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/lib/service/service.factory.js +1 -2
- package/dist/lib/service/service.factory.ts +1 -2
- 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/controller.factory.ts +92 -0
- package/src/lib/controller/files/ts/__name__.controller.spec.ts +33 -0
- package/src/lib/controller/files/ts/__name__.controller.ts +16 -0
- package/src/lib/controller/schema.json +49 -0
- 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/lib/service/service.factory.ts +1 -2
- 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
|
@@ -2,15 +2,33 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MetadataManager = void 0;
|
|
4
4
|
const typescript_1 = require("typescript");
|
|
5
|
+
/**
|
|
6
|
+
* The `MetadataManager` class provides utilities for managing metadata entries
|
|
7
|
+
* within a `@Module` decorator in a TypeScript source file. It allows for the
|
|
8
|
+
* insertion of new metadata entries, merging symbols with static options, and
|
|
9
|
+
* handling various scenarios such as empty module decorators or existing metadata
|
|
10
|
+
* properties.
|
|
11
|
+
*/
|
|
5
12
|
class MetadataManager {
|
|
6
13
|
constructor(content) {
|
|
7
14
|
this.content = content;
|
|
8
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Inserts a new metadata entry into the `@Module` decorator.
|
|
18
|
+
*
|
|
19
|
+
* @param metadata - The metadata key to insert.
|
|
20
|
+
* @param symbol - The symbol to insert.
|
|
21
|
+
* @param staticOptions - The static options to insert.
|
|
22
|
+
* @returns The new content string.
|
|
23
|
+
*/
|
|
9
24
|
insert(metadata, symbol, staticOptions) {
|
|
10
25
|
const source = (0, typescript_1.createSourceFile)('filename.ts', this.content, typescript_1.ScriptTarget.ES2017);
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
26
|
+
const moduleDecoratorNode = this.findFirstDecoratorMetadata(source, 'Module');
|
|
27
|
+
// If there is no occurrence of `@Module` decorator, nothing will be inserted
|
|
28
|
+
if (!moduleDecoratorNode) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const matchingProperties = moduleDecoratorNode.properties
|
|
14
32
|
.filter((prop) => prop.kind === typescript_1.SyntaxKind.PropertyAssignment)
|
|
15
33
|
.filter((prop) => {
|
|
16
34
|
const name = prop.name;
|
|
@@ -28,7 +46,7 @@ class MetadataManager {
|
|
|
28
46
|
symbol = staticOptions ? this.addBlankLines(symbol) : symbol;
|
|
29
47
|
};
|
|
30
48
|
if (matchingProperties.length === 0) {
|
|
31
|
-
const expr =
|
|
49
|
+
const expr = moduleDecoratorNode;
|
|
32
50
|
if (expr.properties.length === 0) {
|
|
33
51
|
addBlankLinesIfDynamic();
|
|
34
52
|
return this.insertMetadataToEmptyModuleDecorator(expr, metadata, symbol);
|
|
@@ -42,16 +60,38 @@ class MetadataManager {
|
|
|
42
60
|
return this.insertSymbolToMetadata(source, matchingProperties, symbol, staticOptions);
|
|
43
61
|
}
|
|
44
62
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
63
|
+
/**
|
|
64
|
+
* Finds the first `@Module` decorator metadata in the source file.
|
|
65
|
+
*
|
|
66
|
+
* @param source - The source file to search.
|
|
67
|
+
* @param identifier - The identifier to match.
|
|
68
|
+
* @returns The first matching `ObjectLiteralExpression` or undefined.
|
|
69
|
+
*/
|
|
70
|
+
findFirstDecoratorMetadata(source, identifier) {
|
|
71
|
+
var _a;
|
|
72
|
+
for (const node of this.getSourceNodes(source)) {
|
|
73
|
+
const isDecoratorFactoryNode = node.kind === typescript_1.SyntaxKind.Decorator &&
|
|
74
|
+
node.expression.kind === typescript_1.SyntaxKind.CallExpression;
|
|
75
|
+
if (!isDecoratorFactoryNode)
|
|
76
|
+
continue;
|
|
77
|
+
const expr = node.expression;
|
|
78
|
+
const isExpectedExpression = ((_a = expr.arguments[0]) === null || _a === void 0 ? void 0 : _a.kind) === typescript_1.SyntaxKind.ObjectLiteralExpression;
|
|
79
|
+
if (!isExpectedExpression)
|
|
80
|
+
continue;
|
|
81
|
+
if (expr.expression.kind === typescript_1.SyntaxKind.Identifier) {
|
|
82
|
+
const escapedText = expr.expression.escapedText;
|
|
83
|
+
const isTargetIdentifier = escapedText
|
|
84
|
+
? escapedText.toLowerCase() === identifier.toLowerCase()
|
|
85
|
+
: true;
|
|
86
|
+
if (isTargetIdentifier) {
|
|
87
|
+
return expr.arguments[0];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
54
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Returns an array of all nodes in the source file.
|
|
94
|
+
*/
|
|
55
95
|
getSourceNodes(sourceFile) {
|
|
56
96
|
const nodes = [sourceFile];
|
|
57
97
|
const result = [];
|
|
@@ -60,12 +100,21 @@ class MetadataManager {
|
|
|
60
100
|
if (node) {
|
|
61
101
|
result.push(node);
|
|
62
102
|
if (node.getChildCount(sourceFile) >= 0) {
|
|
63
|
-
nodes.unshift(...node.getChildren());
|
|
103
|
+
nodes.unshift(...node.getChildren(sourceFile));
|
|
64
104
|
}
|
|
65
105
|
}
|
|
66
106
|
}
|
|
67
107
|
return result;
|
|
68
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Inserts a new metadata entry into an empty `@Module` decorator.
|
|
111
|
+
* This method is called when the `@Module` decorator has no properties.
|
|
112
|
+
* It inserts the metadata and symbol into the decorator.
|
|
113
|
+
* @param expr - The `@Module` decorator node.
|
|
114
|
+
* @param metadata - The metadata key to insert.
|
|
115
|
+
* @param symbol - The symbol to insert.
|
|
116
|
+
* @returns The new content string.
|
|
117
|
+
*/
|
|
69
118
|
insertMetadataToEmptyModuleDecorator(expr, metadata, symbol) {
|
|
70
119
|
const position = expr.getEnd() - 1;
|
|
71
120
|
const toInsert = ` ${metadata}: [${symbol}]`;
|
|
@@ -78,13 +127,23 @@ class MetadataManager {
|
|
|
78
127
|
}
|
|
79
128
|
}, '');
|
|
80
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Inserts a new symbol into an existing metadata property in the `@Module` decorator.
|
|
132
|
+
* This method is called when the metadata property already exists in the decorator.
|
|
133
|
+
* It inserts the symbol into the existing metadata property.
|
|
134
|
+
* @param source - The source file.
|
|
135
|
+
* @param matchingProperties - The matching metadata properties.
|
|
136
|
+
* @param symbol - The symbol to insert.
|
|
137
|
+
* @param staticOptions - The static options to insert.
|
|
138
|
+
* @returns The new content string.
|
|
139
|
+
*/
|
|
81
140
|
insertNewMetadataToDecorator(expr, source, metadata, symbol) {
|
|
82
141
|
const node = expr.properties[expr.properties.length - 1];
|
|
83
142
|
const position = node.getEnd();
|
|
84
143
|
const text = node.getFullText(source);
|
|
85
144
|
const matches = text.match(/^\r?\n\s*/);
|
|
86
145
|
let toInsert;
|
|
87
|
-
if (matches
|
|
146
|
+
if (matches) {
|
|
88
147
|
toInsert = `,${matches[0]}${metadata}: [${symbol}]`;
|
|
89
148
|
}
|
|
90
149
|
else {
|
|
@@ -99,10 +158,24 @@ class MetadataManager {
|
|
|
99
158
|
}
|
|
100
159
|
}, '');
|
|
101
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* Inserts a new symbol into an existing metadata property in the `@Module` decorator.
|
|
163
|
+
* This method is called when the metadata property already exists in the decorator.
|
|
164
|
+
* It inserts the symbol into the existing metadata property.
|
|
165
|
+
* @param source - The source file.
|
|
166
|
+
* @param matchingProperties - The matching metadata properties.
|
|
167
|
+
* @param symbol - The symbol to insert.
|
|
168
|
+
* @param staticOptions - The static options to insert.
|
|
169
|
+
* @returns The new content string.
|
|
170
|
+
*/
|
|
102
171
|
insertSymbolToMetadata(source, matchingProperties, symbol, staticOptions) {
|
|
103
172
|
const assignment = matchingProperties[0];
|
|
104
173
|
let node;
|
|
105
174
|
const arrLiteral = assignment.initializer;
|
|
175
|
+
if (!arrLiteral.elements) {
|
|
176
|
+
// "imports" is not an array but rather function/constant
|
|
177
|
+
return this.content;
|
|
178
|
+
}
|
|
106
179
|
if (arrLiteral.elements.length === 0) {
|
|
107
180
|
node = arrLiteral;
|
|
108
181
|
}
|
|
@@ -125,12 +198,10 @@ class MetadataManager {
|
|
|
125
198
|
}
|
|
126
199
|
else {
|
|
127
200
|
const text = node.getFullText(source);
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
toInsert = `, ${symbol}`;
|
|
133
|
-
}
|
|
201
|
+
const itemSeparator = (text.match(/^\r?\n(\r?)\s+/) ||
|
|
202
|
+
text.match(/^\r?\n/) ||
|
|
203
|
+
' ')[0];
|
|
204
|
+
toInsert = `,${itemSeparator}${symbol}`;
|
|
134
205
|
}
|
|
135
206
|
return this.content.split('').reduce((content, char, index) => {
|
|
136
207
|
if (index === position) {
|
|
@@ -141,18 +212,27 @@ class MetadataManager {
|
|
|
141
212
|
}
|
|
142
213
|
}, '');
|
|
143
214
|
}
|
|
215
|
+
/**
|
|
216
|
+
* Merges a symbol with static options into a single string.
|
|
217
|
+
* @param symbol - The symbol to merge.
|
|
218
|
+
* @param staticOptions - The static options to merge.
|
|
219
|
+
* @returns The merged string.
|
|
220
|
+
*/
|
|
144
221
|
mergeSymbolAndExpr(symbol, staticOptions) {
|
|
145
222
|
if (!staticOptions) {
|
|
146
223
|
return symbol;
|
|
147
224
|
}
|
|
148
225
|
const spacing = 6;
|
|
149
226
|
let options = JSON.stringify(staticOptions.value, null, spacing);
|
|
150
|
-
options = options.replace(
|
|
151
|
-
options = options.replace(
|
|
227
|
+
options = options.replace(/"([^(")"]+)":/g, '$1:');
|
|
228
|
+
options = options.replace(/"/g, `'`);
|
|
152
229
|
options = options.slice(0, options.length - 1) + ' }';
|
|
153
230
|
symbol += `.${staticOptions.name}(${options})`;
|
|
154
231
|
return symbol;
|
|
155
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* Adds blank lines around an expression.
|
|
235
|
+
*/
|
|
156
236
|
addBlankLines(expr) {
|
|
157
237
|
return `\n ${expr}\n `;
|
|
158
238
|
}
|
|
@@ -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
|
}
|
|
@@ -1,11 +1,40 @@
|
|
|
1
1
|
import { DeclarationOptions } from './module.declarator';
|
|
2
2
|
import { PathSolver } from './path.solver';
|
|
3
|
+
/**
|
|
4
|
+
* The `ModuleImportDeclarator` class is responsible for declaring module imports
|
|
5
|
+
* in a TypeScript file. It provides methods to insert import statements into the
|
|
6
|
+
* file content based on the provided declaration options.
|
|
7
|
+
*/
|
|
3
8
|
export declare class ModuleImportDeclarator {
|
|
4
9
|
private solver;
|
|
5
10
|
constructor(solver?: PathSolver);
|
|
11
|
+
/**
|
|
12
|
+
* Declares a module import in the given content string.
|
|
13
|
+
*
|
|
14
|
+
* @param content - The content of the file where the import will be declared.
|
|
15
|
+
* @param options - The options for the declaration, including the symbol and path.
|
|
16
|
+
* @returns The updated content string with the import statement inserted.
|
|
17
|
+
*/
|
|
6
18
|
declare(content: string, options: DeclarationOptions): string;
|
|
7
|
-
|
|
8
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Finds the endpoint of the existing import statements in the content.
|
|
21
|
+
*
|
|
22
|
+
* @param contentLines - The lines of the content.
|
|
23
|
+
* @returns The index of the last import statement.
|
|
24
|
+
*/
|
|
25
|
+
private findImportsEndpoint;
|
|
26
|
+
/**
|
|
27
|
+
* Builds the import line to insert based on the declaration options.
|
|
28
|
+
*
|
|
29
|
+
* @param options - The options for the declaration, including the symbol and path.
|
|
30
|
+
* @returns The import line to insert.
|
|
31
|
+
*/
|
|
9
32
|
private buildLineToInsert;
|
|
33
|
+
/**
|
|
34
|
+
* Computes the relative path for the import statement.
|
|
35
|
+
*
|
|
36
|
+
* @param options - The options for the declaration, including the symbol and path.
|
|
37
|
+
* @returns The relative path for the import statement.
|
|
38
|
+
*/
|
|
10
39
|
private computeRelativePath;
|
|
11
40
|
}
|
|
@@ -3,26 +3,58 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ModuleImportDeclarator = void 0;
|
|
4
4
|
const core_1 = require("@angular-devkit/core");
|
|
5
5
|
const path_solver_1 = require("./path.solver");
|
|
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
|
class ModuleImportDeclarator {
|
|
7
12
|
constructor(solver = new path_solver_1.PathSolver()) {
|
|
8
13
|
this.solver = solver;
|
|
9
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Declares a module import in the given content string.
|
|
17
|
+
*
|
|
18
|
+
* @param content - The content of the file where the import will be declared.
|
|
19
|
+
* @param options - The options for the declaration, including the symbol and path.
|
|
20
|
+
* @returns The updated content string with the import statement inserted.
|
|
21
|
+
*/
|
|
10
22
|
declare(content, options) {
|
|
11
23
|
const toInsert = this.buildLineToInsert(options);
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
return
|
|
24
|
+
const contentLines = content.split('\n');
|
|
25
|
+
const finalImportIndex = this.findImportsEndpoint(contentLines);
|
|
26
|
+
contentLines.splice(finalImportIndex + 1, 0, toInsert);
|
|
27
|
+
return contentLines.join('\n');
|
|
16
28
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
+
findImportsEndpoint(contentLines) {
|
|
36
|
+
const reversedContent = Array.from(contentLines).reverse();
|
|
37
|
+
const reverseImports = reversedContent.filter((line) => line.match(/\} from ('|")/));
|
|
38
|
+
if (reverseImports.length <= 0) {
|
|
39
|
+
return 0;
|
|
40
|
+
}
|
|
41
|
+
return contentLines.indexOf(reverseImports[0]);
|
|
22
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* Builds the import line to insert based on the declaration options.
|
|
45
|
+
*
|
|
46
|
+
* @param options - The options for the declaration, including the symbol and path.
|
|
47
|
+
* @returns The import line to insert.
|
|
48
|
+
*/
|
|
23
49
|
buildLineToInsert(options) {
|
|
24
|
-
return `import { ${options.symbol} } from '${this.computeRelativePath(options)}'
|
|
50
|
+
return `import { ${options.symbol} } from '${this.computeRelativePath(options)}';`;
|
|
25
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Computes the relative path for the import statement.
|
|
54
|
+
*
|
|
55
|
+
* @param options - The options for the declaration, including the symbol and path.
|
|
56
|
+
* @returns The relative path for the import statement.
|
|
57
|
+
*/
|
|
26
58
|
computeRelativePath(options) {
|
|
27
59
|
let importModulePath;
|
|
28
60
|
if (options.type !== undefined) {
|