@rhtml/schematics 0.0.133 → 0.0.135

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.
Files changed (43) hide show
  1. package/dist/lib/component/schema.json +1 -1
  2. package/dist/lib/controller/schema.json +1 -1
  3. package/dist/lib/module/schema.json +4 -4
  4. package/dist/lib/provider/schema.json +4 -4
  5. package/dist/lib/service/schema.json +3 -3
  6. package/dist/utils/metadata.manager.d.ts +65 -2
  7. package/dist/utils/metadata.manager.js +103 -23
  8. package/dist/utils/metadata.manager.ts +127 -46
  9. package/dist/utils/module-import.declarator.d.ts +31 -2
  10. package/dist/utils/module-import.declarator.js +42 -10
  11. package/dist/utils/module-import.declarator.ts +45 -12
  12. package/dist/utils/module-metadata.declarator.d.ts +12 -0
  13. package/dist/utils/module-metadata.declarator.js +13 -1
  14. package/dist/utils/module-metadata.declarator.ts +13 -1
  15. package/dist/utils/module.declarator.d.ts +21 -1
  16. package/dist/utils/module.declarator.js +23 -1
  17. package/dist/utils/module.declarator.ts +24 -2
  18. package/dist/utils/module.finder.d.ts +12 -0
  19. package/dist/utils/module.finder.js +13 -1
  20. package/dist/utils/module.finder.ts +13 -1
  21. package/dist/utils/name.parser.d.ts +6 -0
  22. package/dist/utils/name.parser.js +6 -0
  23. package/dist/utils/name.parser.ts +6 -0
  24. package/dist/utils/path.solver.d.ts +7 -0
  25. package/dist/utils/path.solver.js +7 -0
  26. package/dist/utils/path.solver.ts +7 -0
  27. package/dist/utils/source-root.helpers.d.ts +13 -1
  28. package/dist/utils/source-root.helpers.js +13 -1
  29. package/dist/utils/source-root.helpers.ts +14 -2
  30. package/package.json +5 -5
  31. package/src/lib/component/schema.json +1 -1
  32. package/src/lib/controller/schema.json +1 -1
  33. package/src/lib/module/schema.json +4 -4
  34. package/src/lib/provider/schema.json +4 -4
  35. package/src/lib/service/schema.json +3 -3
  36. package/src/utils/metadata.manager.ts +127 -46
  37. package/src/utils/module-import.declarator.ts +45 -12
  38. package/src/utils/module-metadata.declarator.ts +13 -1
  39. package/src/utils/module.declarator.ts +24 -2
  40. package/src/utils/module.finder.ts +13 -1
  41. package/src/utils/name.parser.ts +6 -0
  42. package/src/utils/path.solver.ts +7 -0
  43. 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.133",
3
+ "version": "0.0.135",
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": "^7.3.7",
19
- "@angular-devkit/schematics": "^7.3.7",
20
- "@angular-devkit/schematics-cli": "^0.13.7",
21
- "ts-morph": "^1.3.1"
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,6 +1,6 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/schema",
3
- "id": "SchematicsRHTMLComponent",
3
+ "$id": "SchematicsRHTMLComponent",
4
4
  "title": "@rhtml Component Options Schema",
5
5
  "type": "object",
6
6
  "properties": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/schema",
3
- "id": "SchematicsRHTMLController",
3
+ "$id": "SchematicsRHTMLController",
4
4
  "title": "RHTML Controller Options Schema",
5
5
  "type": "object",
6
6
  "properties": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/schema",
3
- "id": "SchematicsNestModule",
4
- "title": "Nest Module Options Schema",
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": "Nest module language (ts/js)."
28
+ "description": "Rhtml module language (ts/js)."
29
29
  },
30
30
  "sourceRoot": {
31
31
  "type": "string",
32
- "description": "Nest module source root directory."
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": "SchematicsNestProvider",
4
- "title": "Nest Provider Options Schema",
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": "Nest provider language (ts/js)."
23
+ "description": "Rhtml provider language (ts/js)."
24
24
  },
25
25
  "sourceRoot": {
26
26
  "type": "string",
27
- "description": "Nest provider source root directory."
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": "SchematicsNestService",
4
- "title": "Nest Service Options Schema",
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": "Nest service language (ts/js)."
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 decoratorNodes: Node[] = this.getDecoratorMetadata(source, '@Module');
35
- const node: Node = decoratorNodes[0];
36
- const matchingProperties: ObjectLiteralElement[] = (
37
- node as ObjectLiteralExpression
38
- ).properties
39
- .filter((prop) => prop.kind === SyntaxKind.PropertyAssignment)
40
- .filter((prop: PropertyAssignment) => {
41
- const name = prop.name;
42
- switch (name.kind) {
43
- case SyntaxKind.Identifier:
44
- return (name as Identifier).getText(source) === metadata;
45
- case SyntaxKind.StringLiteral:
46
- return (name as StringLiteral).text === metadata;
47
- default:
48
- return false;
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 = node as ObjectLiteralExpression;
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
- private getDecoratorMetadata(source: SourceFile, identifier: string): Node[] {
85
- identifier;
86
- return this.getSourceNodes(source)
87
- .filter(
88
- (node) =>
89
- node.kind === SyntaxKind.Decorator &&
90
- (node as Decorator).expression.kind === SyntaxKind.CallExpression
91
- )
92
- .map((node) => (node as Decorator).expression as CallExpression)
93
- .filter(
94
- (expr) =>
95
- expr.arguments[0] &&
96
- expr.arguments[0].kind === SyntaxKind.ObjectLiteralExpression
97
- )
98
- .map((expr) => expr.arguments[0] as ObjectLiteralExpression);
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.length > 0) {
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 {} as Node[];
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
- if (text.match(/^\r?\n/)) {
190
- toInsert = `,${text.match(/^\r?\n(\r?)\s+/)[0]}${symbol}`;
191
- } else {
192
- toInsert = `, ${symbol}`;
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(/\"([^(\")"]+)\":/g, '$1:');
214
- options = options.replace(/\"/g, `'`);
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: string = this.buildLineToInsert(options);
11
- const importLines: string[] = this.findImports(content);
12
- const otherLines: string[] = this.findOtherLines(content, importLines);
13
- importLines.push(toInsert);
14
- return importLines.join('\n').concat(otherLines.join('\n'));
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
- private findImports(content: string): string[] {
18
- return content.split('\n').filter((line) => line.match(/import {/));
19
- }
20
-
21
- private findOtherLines(content: string, importLines: string[]) {
22
- return content.split('\n').filter((line) => importLines.indexOf(line) < 0);
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
- )}';\n`;
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, unknown>;
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.type !== undefined) {
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/.test(filename)
38
+ /\.module\.(t|j)s$/.test(filename)
27
39
  );
28
40
  return moduleFilename !== undefined
29
41
  ? join(directory.path, moduleFilename.valueOf())
@@ -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(
@@ -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 = ['nest-cli.json', 'nest.json'].concat(extraFiles || []);
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 } = unknown
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']);