@simplysm/sd-cli 7.0.65 → 7.0.66

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 (70) hide show
  1. package/dist/SdCliBuildResultError.d.ts +5 -0
  2. package/dist/bin/sd-cli.d.ts +2 -0
  3. package/dist/bin/sd-cli.mjs +3 -3
  4. package/dist/build-tool/SdCliCacheCompilerHost.d.ts +10 -0
  5. package/dist/build-tool/SdCliCordova.d.ts +16 -0
  6. package/dist/build-tool/SdCliCordova.mjs +171 -0
  7. package/dist/build-tool/SdCliIndexFileGenerator.d.ts +13 -0
  8. package/dist/{entry-points → build-tool}/SdCliIndexFileGenerator.mjs +4 -3
  9. package/dist/build-tool/SdCliNgCacheCompilerHost.d.ts +11 -0
  10. package/dist/build-tool/SdCliPackageLinter.d.ts +8 -0
  11. package/dist/build-tool/SdCliPackageLinter.mjs +19 -2
  12. package/dist/builder/SdCliClientBuilder.d.ts +23 -0
  13. package/dist/builder/SdCliClientBuilder.mjs +68 -6
  14. package/dist/builder/SdCliJsLibBuilder.d.ts +14 -0
  15. package/dist/builder/SdCliServerBuilder.d.ts +25 -0
  16. package/dist/builder/SdCliServerBuilder.mjs +11 -13
  17. package/dist/builder/SdCliTsLibBuilder.d.ts +34 -0
  18. package/dist/builder/SdCliTsLibBuilder.mjs +83 -36
  19. package/dist/commons.d.ts +85 -0
  20. package/dist/entry-points/SdCliLocalUpdate.d.ts +13 -0
  21. package/dist/entry-points/SdCliNpm.d.ts +6 -0
  22. package/dist/entry-points/SdCliPrepare.d.ts +5 -0
  23. package/dist/entry-points/SdCliWorkspace.d.ts +28 -0
  24. package/dist/entry-points/SdCliWorkspace.mjs +12 -16
  25. package/dist/index.d.ts +29 -0
  26. package/dist/index.mjs +5 -3
  27. package/dist/ng-tools/SdCliNgModuleGenerator.d.ts +26 -0
  28. package/dist/ng-tools/SdCliNgModuleGenerator.mjs +404 -0
  29. package/dist/ng-tools/babel/SdCliBbFileMetadata.d.ts +23 -0
  30. package/dist/ng-tools/babel/SdCliBbFileMetadata.mjs +187 -36
  31. package/dist/ng-tools/babel/SdCliBbRootMetadata.d.ts +22 -0
  32. package/dist/ng-tools/babel/SdCliBbRootMetadata.mjs +10 -7
  33. package/dist/ng-tools/babel/SdCliBbUtil.d.ts +5 -0
  34. package/dist/ng-tools/babel/SdCliBbUtil.mjs +2 -2
  35. package/dist/ng-tools/babel/TSdCliBbNgMetadata.d.ts +42 -0
  36. package/dist/ng-tools/babel/TSdCliBbNgMetadata.mjs +107 -76
  37. package/dist/ng-tools/babel/TSdCliBbTypeMetadata.d.ts +44 -0
  38. package/dist/ng-tools/commons.d.ts +9 -0
  39. package/dist/ng-tools/typescript/SdCliTsFileMetadata.d.ts +61 -0
  40. package/dist/ng-tools/typescript/SdCliTsFileMetadata.mjs +13 -12
  41. package/dist/ng-tools/typescript/SdCliTsRootMetadata.d.ts +8 -0
  42. package/dist/ng-tools/typescript/SdCliTsUtil.d.ts +5 -0
  43. package/dist/ng-tools/typescript/SdCliTsUtil.mjs +28 -0
  44. package/dist/packages/SdCliPackage.d.ts +23 -0
  45. package/dist/packages/SdCliPackage.mjs +2 -3
  46. package/dist/utils/SdCliBuildResultUtil.d.ts +9 -0
  47. package/dist/utils/SdCliConfigUtil.d.ts +7 -0
  48. package/dist/utils/SdCliNpmConfigUtil.d.ts +7 -0
  49. package/package.json +11 -6
  50. package/src/bin/sd-cli.ts +2 -2
  51. package/src/build-tool/SdCliCordova.ts +219 -0
  52. package/src/{entry-points → build-tool}/SdCliIndexFileGenerator.ts +3 -2
  53. package/src/build-tool/SdCliPackageLinter.ts +18 -2
  54. package/src/builder/SdCliClientBuilder.ts +83 -5
  55. package/src/builder/SdCliServerBuilder.ts +10 -12
  56. package/src/builder/SdCliTsLibBuilder.ts +100 -44
  57. package/src/commons.ts +24 -0
  58. package/src/entry-points/SdCliWorkspace.ts +14 -17
  59. package/src/index.ts +4 -2
  60. package/src/ng-tools/{NgModuleGenerator.ts → SdCliNgModuleGenerator.ts} +241 -64
  61. package/src/ng-tools/babel/SdCliBbFileMetadata.ts +234 -38
  62. package/src/ng-tools/babel/SdCliBbRootMetadata.ts +10 -6
  63. package/src/ng-tools/babel/SdCliBbUtil.ts +1 -1
  64. package/src/ng-tools/babel/TSdCliBbNgMetadata.ts +36 -22
  65. package/src/ng-tools/commons.ts +1 -1
  66. package/src/ng-tools/typescript/SdCliTsFileMetadata.ts +13 -12
  67. package/src/ng-tools/typescript/SdCliTsUtil.ts +29 -0
  68. package/src/packages/SdCliPackage.ts +1 -2
  69. package/tsconfig-build.json +1 -1
  70. package/dist/ng-tools/NgModuleGenerator.mjs +0 -278
@@ -1,5 +1,5 @@
1
1
  import { SdCliTsRootMetadata } from "./typescript/SdCliTsRootMetadata";
2
- import { SdCliBbRootMetadata } from "./babel/SdCliBbRootMetadata";
2
+ import { SdCliBbRootMetadata, TSdCliBbMetadata } from "./babel/SdCliBbRootMetadata";
3
3
  import { SdCliBbClassMetadata, SdCliBbObjectMetadata } from "./babel/TSdCliBbTypeMetadata";
4
4
  import {
5
5
  SdCliBbNgComponentMetadata,
@@ -7,7 +7,7 @@ import {
7
7
  SdCliBbNgModuleMetadata,
8
8
  SdCliBbNgPipeMetadata
9
9
  } from "./babel/TSdCliBbNgMetadata";
10
- import { NeverEntryError } from "@simplysm/sd-core-common";
10
+ import { NeverEntryError, StringUtil } from "@simplysm/sd-core-common";
11
11
  import { TSdCliMetaRef } from "./commons";
12
12
  import { SdCliTsNgInjectableMetadata } from "./typescript/SdCliTsFileMetadata";
13
13
  import path from "path";
@@ -16,29 +16,43 @@ import { FsUtil, PathUtil } from "@simplysm/sd-core-node";
16
16
  import os from "os";
17
17
 
18
18
  // TODO: 에러 메시지 처리
19
- export class NgModuleGenerator {
19
+ // TODO: forRoot에 있는 Provider 처리??
20
+ export class SdCliNgModuleGenerator {
20
21
  private readonly _bbMeta: SdCliBbRootMetadata;
21
22
  private readonly _tsMeta: SdCliTsRootMetadata;
22
23
 
23
- private readonly _srcPath = path.resolve(process.cwd(), "packages", "sd-angular", "src");
24
- private readonly _modulesPath = path.resolve(process.cwd(), "packages", "sd-angular", "src", "_modules");
24
+ private readonly _srcPath: string;
25
+ private readonly _modulesPath: string;
25
26
 
26
27
  private readonly _fileWriterCache = new Map<string, string>();
27
28
 
28
- public constructor(packagePath: string, private readonly _srcDirRelPaths: string[]) {
29
+ public constructor(packagePath: string,
30
+ private readonly _srcDirRelPaths: string[],
31
+ private readonly _routeOpts: {
32
+ glob: string;
33
+ fileEndsWith: string;
34
+ rootClassName: string;
35
+ } | undefined) {
36
+ this._srcPath = path.resolve(packagePath, "src");
37
+ this._modulesPath = path.resolve(packagePath, "src", "_modules");
38
+
29
39
  this._bbMeta = new SdCliBbRootMetadata(packagePath);
30
40
  this._tsMeta = new SdCliTsRootMetadata(packagePath);
31
- }
32
41
 
33
- public async clearModulesAsync(): Promise<void> {
34
- await FsUtil.removeAsync(this._modulesPath);
42
+ const glob = FsUtil.glob(path.resolve(this._modulesPath, "**", "*.ts"));
43
+ for (const currFilePath of glob) {
44
+ const content = FsUtil.readFile(currFilePath);
45
+ this._fileWriterCache.set(currFilePath, content);
46
+ }
35
47
  }
36
48
 
37
49
  public removeCaches(changedFilePaths: string[]): void {
38
50
  this._bbMeta.removeCaches(changedFilePaths);
39
51
  this._tsMeta.removeCaches(changedFilePaths);
40
52
  for (const changedFilePath of changedFilePaths) {
41
- this._fileWriterCache.delete(changedFilePath);
53
+ if (this._fileWriterCache.has(changedFilePath) && !FsUtil.exists(changedFilePath)) {
54
+ this._fileWriterCache.delete(changedFilePath);
55
+ }
42
56
  }
43
57
  }
44
58
 
@@ -46,8 +60,20 @@ export class NgModuleGenerator {
46
60
  const bbNgModules = this._getBbNgModuleDefs();
47
61
  const tsPreset = this._getTsGenNgModulePreset();
48
62
 
63
+ const genNgRoutingModules = await this._getGenNgRoutingModuleDefsAsync();
49
64
  const genNgModules = this._getGenNgModuleDefs(bbNgModules, tsPreset.modules, tsPreset.sources);
50
- await this._genFileAsync(genNgModules);
65
+
66
+ const files = [
67
+ ...this._getGenNgRoutingModuleFiles(genNgRoutingModules),
68
+ ...this._getGenNgModuleFiles(genNgModules)
69
+ ];
70
+
71
+ await this._writeFilesAsync(files);
72
+ }
73
+
74
+ private _findBbMetasFromMeta(srcMeta: TSdCliBbMetadata): TSdCliBbMetadata[] {
75
+ const metaTmp = typeof srcMeta !== "string" && "__TSdCliMetaRef__" in srcMeta ? this._bbMeta.findMeta(srcMeta) : srcMeta;
76
+ return metaTmp instanceof Array ? metaTmp : [metaTmp];
51
77
  }
52
78
 
53
79
  private _getBbNgModuleDefs(): IBbNgModuleDef[] {
@@ -57,8 +83,7 @@ export class NgModuleGenerator {
57
83
  for (const moduleName of Object.keys(entryRecord)) {
58
84
  const fileMeta = entryRecord[moduleName];
59
85
  for (const exp of fileMeta.exports) {
60
- const metaTmp = typeof exp.target !== "string" && "__TDeclRef__" in exp.target ? this._bbMeta.findMeta(exp.target) : exp.target;
61
- const metas = metaTmp instanceof Array ? metaTmp : [metaTmp];
86
+ const metas = this._findBbMetasFromMeta(exp.target);
62
87
  for (const meta of metas) {
63
88
  if (meta instanceof SdCliBbClassMetadata) {
64
89
  if (meta.ngDecl instanceof SdCliBbNgModuleMetadata) {
@@ -66,7 +91,7 @@ export class NgModuleGenerator {
66
91
 
67
92
  const resultItem: IBbNgModuleDef = {
68
93
  moduleName,
69
- name: exp.exportedName,
94
+ name: exp.exportedName === "*" ? meta.name : exp.exportedName,
70
95
  providers: [],
71
96
  exports: [],
72
97
  selectors: [],
@@ -74,49 +99,37 @@ export class NgModuleGenerator {
74
99
  };
75
100
 
76
101
  for (const modProv of ngDecl.def.providers) {
77
- if (modProv instanceof SdCliBbClassMetadata) {
78
- const ref = this._bbMeta.findExportRef({
79
- filePath: modProv.filePath,
80
- name: modProv.name
81
- });
82
- if (ref) {
83
- resultItem.providers.push(ref);
84
- }
85
- }
86
- else if (modProv instanceof SdCliBbObjectMetadata) {
87
- // 무시
88
- }
89
- else {
102
+ const modProvMetas = this._findBbMetasFromMeta(modProv);
103
+ if (modProvMetas.length === 0) {
90
104
  throw new NeverEntryError();
91
105
  }
92
- }
93
-
94
- for (const modExp of ngDecl.def.exports) {
95
- if (modExp instanceof SdCliBbClassMetadata) {
96
- const ref = this._bbMeta.findExportRef({
97
- filePath: modExp.filePath,
98
- name: modExp.name
99
- });
100
- if (ref) {
101
- resultItem.exports.push(ref);
102
- }
103
106
 
104
- if (modExp.ngDecl instanceof SdCliBbNgDirectiveMetadata) {
105
- resultItem.selectors.push(modExp.ngDecl.selector);
106
- }
107
- else if (modExp.ngDecl instanceof SdCliBbNgComponentMetadata) {
108
- resultItem.selectors.push(modExp.ngDecl.selector);
107
+ for (const modProvMeta of modProvMetas) {
108
+ if (modProvMeta instanceof SdCliBbClassMetadata) {
109
+ const ref = this._bbMeta.findExportRef({
110
+ filePath: modProvMeta.filePath,
111
+ name: modProvMeta.name
112
+ });
113
+ if (ref) {
114
+ resultItem.providers.push(ref);
115
+ }
109
116
  }
110
- else if (modExp.ngDecl instanceof SdCliBbNgPipeMetadata) {
111
- resultItem.pipeNames.push(modExp.ngDecl.pipeName);
117
+ else if (modProvMeta instanceof SdCliBbObjectMetadata) {
118
+ // 무시
112
119
  }
113
- }
114
- else if (typeof modExp !== "string" && "__TDeclRef__" in modExp) {
115
- const modExpMeta = this._bbMeta.findMeta(modExp);
116
- if (modExpMeta instanceof Array) {
120
+ else {
117
121
  throw new NeverEntryError();
118
122
  }
123
+ }
124
+ }
125
+
126
+ for (const modExp of ngDecl.def.exports) {
127
+ const modExpMetas = this._findBbMetasFromMeta(modExp);
128
+ if (modExpMetas.length === 0) {
129
+ throw new NeverEntryError();
130
+ }
119
131
 
132
+ for (const modExpMeta of modExpMetas) {
120
133
  if (modExpMeta instanceof SdCliBbClassMetadata) {
121
134
  const ref = this._bbMeta.findExportRef({
122
135
  filePath: modExpMeta.filePath,
@@ -136,9 +149,9 @@ export class NgModuleGenerator {
136
149
  resultItem.pipeNames.push(modExpMeta.ngDecl.pipeName);
137
150
  }
138
151
  }
139
- }
140
- else {
141
- throw new NeverEntryError();
152
+ else {
153
+ throw new NeverEntryError();
154
+ }
142
155
  }
143
156
  }
144
157
 
@@ -211,17 +224,17 @@ export class NgModuleGenerator {
211
224
  if ("moduleName" in imp) {
212
225
  for (const mod of bbModules) {
213
226
  if (mod.exports.some((item) => item.moduleName === imp.moduleName && item.name === imp.name)) {
214
- imports.push({ moduleName: mod.moduleName, name: mod.name, __TDeclRef__: "__TDeclRef__" });
227
+ imports.push({ moduleName: mod.moduleName, name: mod.name, __TSdCliMetaRef__: "__TSdCliMetaRef__" });
215
228
  }
216
229
  if (mod.providers.some((item) => item.moduleName === imp.moduleName && item.name === imp.name)) {
217
- imports.push({ moduleName: mod.moduleName, name: mod.name, __TDeclRef__: "__TDeclRef__" });
230
+ imports.push({ moduleName: mod.moduleName, name: mod.name, __TSdCliMetaRef__: "__TSdCliMetaRef__" });
218
231
  }
219
232
  }
220
233
  }
221
234
  else {
222
235
  for (const mod of presetModules) {
223
236
  if (mod.source && mod.source.filePath === imp.filePath && mod.source.name === imp.name) {
224
- imports.push({ filePath: mod.filePath, name: mod.name, __TDeclRef__: "__TDeclRef__" });
237
+ imports.push({ filePath: mod.filePath, name: mod.name, __TSdCliMetaRef__: "__TSdCliMetaRef__" });
225
238
  }
226
239
  }
227
240
  }
@@ -239,13 +252,13 @@ export class NgModuleGenerator {
239
252
  selector.replace(/\[/g, "[\\(").replace(/]/g, "\\)]")
240
253
  ].join(", ")) != null
241
254
  ) {
242
- imports.push({ moduleName: mod.moduleName, name: mod.name, __TDeclRef__: "__TDeclRef__" });
255
+ imports.push({ moduleName: mod.moduleName, name: mod.name, __TSdCliMetaRef__: "__TSdCliMetaRef__" });
243
256
  }
244
257
  }
245
258
 
246
259
  for (const pipeName of mod.pipeNames) {
247
260
  if (new RegExp("| *" + pipeName + "[^\\w]").test(el.template)) {
248
- imports.push({ moduleName: mod.moduleName, name: mod.name, __TDeclRef__: "__TDeclRef__" });
261
+ imports.push({ moduleName: mod.moduleName, name: mod.name, __TSdCliMetaRef__: "__TSdCliMetaRef__" });
249
262
  }
250
263
  }
251
264
  }
@@ -259,13 +272,13 @@ export class NgModuleGenerator {
259
272
  mod.selector.replace(/\[/g, "[\\(").replace(/]/g, "\\)]")
260
273
  ].join(", ")) != null
261
274
  ) {
262
- imports.push({ filePath: mod.filePath, name: mod.name, __TDeclRef__: "__TDeclRef__" });
275
+ imports.push({ filePath: mod.filePath, name: mod.name, __TSdCliMetaRef__: "__TSdCliMetaRef__" });
263
276
  }
264
277
  }
265
278
 
266
279
  if (mod.pipeName !== undefined) {
267
280
  if (new RegExp("| *" + mod.pipeName + "[^\\w]").test(el.template)) {
268
- imports.push({ filePath: mod.filePath, name: mod.name, __TDeclRef__: "__TDeclRef__" });
281
+ imports.push({ filePath: mod.filePath, name: mod.name, __TSdCliMetaRef__: "__TSdCliMetaRef__" });
269
282
  }
270
283
  }
271
284
  }
@@ -283,7 +296,126 @@ export class NgModuleGenerator {
283
296
  return result;
284
297
  }
285
298
 
286
- private async _genFileAsync(mods: ITsGenNgModuleDef[]): Promise<void> {
299
+ private async _getGenNgRoutingModuleDefsAsync(): Promise<TTsGenNgRoutingModuleDef[]> {
300
+ if (this._routeOpts === undefined) return [];
301
+
302
+ const result: TTsGenNgRoutingModuleDef[] = [];
303
+
304
+ const filePaths = await FsUtil.globAsync(path.resolve(this._srcPath, this._routeOpts.glob));
305
+ for (const filePath of filePaths) {
306
+ const sourceClassName = path.basename(filePath, path.extname(filePath));
307
+ if (sourceClassName === this._routeOpts.rootClassName) {
308
+ const childDirName = StringUtil.toKebabCase(sourceClassName.slice(0, -this._routeOpts.fileEndsWith.length));
309
+ const childDirPath = path.resolve(path.dirname(filePath), childDirName);
310
+
311
+ result.push({
312
+ filePath: path.resolve(this._srcPath, "_routes"),
313
+ children: await this._getGenNgRoutingModuleDefChildrenAsync(childDirPath)
314
+ });
315
+ }
316
+ else {
317
+ const routingModuleClassName = sourceClassName + "RoutingModule";
318
+ const routingModuleFilePath = path.resolve(this._modulesPath, path.relative(this._srcPath, path.dirname(filePath)), routingModuleClassName);
319
+ const childDirName = StringUtil.toKebabCase(sourceClassName.slice(0, -this._routeOpts.fileEndsWith.length));
320
+ const childDirPath = path.resolve(path.dirname(filePath), childDirName);
321
+
322
+ result.push({
323
+ filePath: routingModuleFilePath,
324
+ name: routingModuleClassName,
325
+ component: { filePath: filePath.replace(/\.ts$/, ""), name: sourceClassName },
326
+ children: FsUtil.exists(childDirPath) ? await this._getGenNgRoutingModuleDefChildrenAsync(childDirPath) : undefined
327
+ });
328
+ }
329
+ }
330
+
331
+ return result;
332
+ }
333
+
334
+ private async _getGenNgRoutingModuleDefChildrenAsync(rootPath: string): Promise<TTsGenNgRoutingModuleDefChild[]> {
335
+ const result: TTsGenNgRoutingModuleDefChild[] = [];
336
+
337
+ const childNames = await FsUtil.readdirAsync(rootPath);
338
+ for (const childName of childNames) {
339
+ if (!FsUtil.stat(path.resolve(rootPath, childName)).isDirectory()) { // 파일
340
+ const sourceFilePath = path.resolve(rootPath, childName);
341
+ const sourceClassName = path.basename(sourceFilePath, path.extname(childName));
342
+ const moduleClassName = sourceClassName + "Module";
343
+ const moduleFilePath = path.resolve(this._modulesPath, path.relative(this._srcPath, path.dirname(sourceFilePath)), moduleClassName);
344
+
345
+ result.push({
346
+ path: StringUtil.toKebabCase(childName.substring(0, childName.length - 7)),
347
+ target: { filePath: moduleFilePath, name: moduleClassName }
348
+ });
349
+ }
350
+ else if (!FsUtil.exists(path.resolve(rootPath, StringUtil.toPascalCase(childName) + this._routeOpts!.fileEndsWith + ".ts"))) { // 파일없는 디렉토리
351
+ result.push({
352
+ path: childName,
353
+ children: await this._getGenNgRoutingModuleDefChildrenAsync(path.resolve(rootPath, childName))
354
+ });
355
+ }
356
+ }
357
+
358
+ return result;
359
+ }
360
+
361
+ private _getGenNgRoutingModuleFiles(defs: TTsGenNgRoutingModuleDef[]): { filePath: string; content: string }[] {
362
+ const result: { filePath: string; content: string }[] = [];
363
+
364
+ for (const def of defs) {
365
+ const fn = (children: TTsGenNgRoutingModuleDefChild[]): string => {
366
+ let fnResult = "[\n";
367
+ for (const child of children) {
368
+ fnResult += " {\n";
369
+ fnResult += ` path: "${child.path}",\n`;
370
+ if ("target" in child) {
371
+ fnResult += ` loadChildren: async () => await import("${this._getImportModuleName(def.filePath, child.target.filePath)}").then((m) => m.${child.target.name})\n`;
372
+ }
373
+ else {
374
+ fnResult += ` children: ${fn(child.children).replace(/\n/g, "\n ")}\n`;
375
+ }
376
+ fnResult += " },\n";
377
+ }
378
+ fnResult = fnResult.slice(0, -2) + "\n";
379
+ fnResult += "]";
380
+
381
+ return fnResult;
382
+ };
383
+
384
+ const content = "component" in def ? `
385
+ import { NgModule } from "@angular/core";
386
+ import { RouterModule } from "@angular/router";
387
+ import { SdCanDeactivateGuard } from "@simplysm/sd-angular";
388
+ import { ${def.component.name} } from "${this._getImportModuleName(def.filePath, def.component.filePath)}";
389
+
390
+ @NgModule({
391
+ imports: [
392
+ RouterModule.forChild([
393
+ {
394
+ path: "",
395
+ component: ${def.component.name},
396
+ canDeactivate: [SdCanDeactivateGuard]${def.children ? `,
397
+ children: ${fn(def.children).replace(/\n/g, "\n ")}` : ""}
398
+ }
399
+ ])
400
+ ],
401
+ exports: [RouterModule]
402
+ })
403
+ export class ${def.name} {
404
+ }`.trim() : `
405
+ import { Routes } from "@angular/router";
406
+
407
+ export const routes: Routes = ${fn(def.children)};
408
+ `.trim();
409
+
410
+ result.push({ filePath: def.filePath + ".ts", content });
411
+ }
412
+
413
+ return result;
414
+ }
415
+
416
+ private _getGenNgModuleFiles(mods: ITsGenNgModuleDef[]): { filePath: string; content: string }[] {
417
+ const result: { filePath: string; content: string }[] = [];
418
+
287
419
  for (const mod of mods) {
288
420
  const importMap = [...mod.imports, ...mod.exports, ...mod.providers]
289
421
  .map((item) => ({
@@ -301,11 +433,22 @@ export class NgModuleGenerator {
301
433
  importTexts.push(`import { ${targetNames.join(", ")} } from "${moduleName}";`);
302
434
  }
303
435
 
436
+ const moduleImportNames = mod.imports.map((item) => item.name);
437
+ if (
438
+ this._routeOpts !== undefined
439
+ && mod.filePath.endsWith(this._routeOpts.fileEndsWith + "Module")
440
+ && mod.name !== this._routeOpts.rootClassName + "Module"
441
+ ) {
442
+ const routingModuleName = mod.name.replace(/Module$/, "RoutingModule");
443
+ importTexts.push(`import { ${routingModuleName} } from "./${routingModuleName}";`);
444
+ moduleImportNames.push(routingModuleName);
445
+ }
446
+
304
447
  const content = `
305
448
  ${importTexts.join(os.EOL)}
306
449
 
307
450
  @NgModule({
308
- imports: [${mod.imports.map((item) => item.name).orderBy().join(", ")}],
451
+ imports: [${moduleImportNames.orderBy().join(", ")}],
309
452
  declarations: [${mod.exports.map((item) => item.name).distinct().orderBy().join(", ")}],
310
453
  exports: [${mod.exports.map((item) => item.name).distinct().orderBy().join(", ")}],
311
454
  providers: [${mod.providers.map((item) => item.name).distinct().orderBy().join(", ")}]
@@ -313,9 +456,25 @@ ${importTexts.join(os.EOL)}
313
456
  export class ${mod.name} {
314
457
  }`.trim();
315
458
 
316
- if (this._fileWriterCache.get(mod.filePath) !== content) {
317
- await FsUtil.writeFileAsync(mod.filePath + ".ts", content);
318
- this._fileWriterCache.set(mod.filePath, content);
459
+ result.push({ filePath: mod.filePath + ".ts", content });
460
+ }
461
+
462
+ return result;
463
+ }
464
+
465
+ private async _writeFilesAsync(files: { filePath: string; content: string }[]): Promise<void> {
466
+ for (const file of files) {
467
+ if (this._fileWriterCache.get(file.filePath) !== file.content) {
468
+ await FsUtil.writeFileAsync(file.filePath, file.content);
469
+ this._fileWriterCache.set(file.filePath, file.content);
470
+ }
471
+ }
472
+
473
+ const glob = await FsUtil.globAsync(path.resolve(this._modulesPath, "**", "*"));
474
+ for (const currFilePath of glob) {
475
+ if (!files.some((item) => item.filePath.startsWith(currFilePath))) {
476
+ await FsUtil.removeAsync(currFilePath);
477
+ this._fileWriterCache.delete(currFilePath);
319
478
  }
320
479
  }
321
480
  }
@@ -359,3 +518,21 @@ interface ITsGenNgModuleDef {
359
518
  exports: { filePath: string; name: string }[];
360
519
  providers: { filePath: string; name: string }[];
361
520
  }
521
+
522
+ type TTsGenNgRoutingModuleDef = {
523
+ filePath: string;
524
+ name: string;
525
+ component: { filePath: string; name: string };
526
+ children?: TTsGenNgRoutingModuleDefChild[];
527
+ } | {
528
+ filePath: string;
529
+ children: TTsGenNgRoutingModuleDefChild[];
530
+ };
531
+
532
+ type TTsGenNgRoutingModuleDefChild = {
533
+ path: string;
534
+ target: { filePath: string; name: string };
535
+ } | {
536
+ path: string;
537
+ children: TTsGenNgRoutingModuleDefChild[];
538
+ };