@simplysm/sd-cli 12.8.21 → 12.9.1

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 (96) hide show
  1. package/dist/entry/sd-cli-ai-command.js +2 -1
  2. package/dist/entry/sd-cli-ai-command.js.map +1 -1
  3. package/dist/entry/sd-cli-cordova.d.ts +1 -1
  4. package/dist/entry/sd-cli-cordova.js +10 -9
  5. package/dist/entry/sd-cli-cordova.js.map +1 -1
  6. package/dist/entry/sd-cli-electron.d.ts +6 -6
  7. package/dist/entry/sd-cli-electron.js +15 -9
  8. package/dist/entry/sd-cli-electron.js.map +1 -1
  9. package/dist/entry/sd-cli-local-update.d.ts +5 -5
  10. package/dist/entry/sd-cli-local-update.js +8 -12
  11. package/dist/entry/sd-cli-local-update.js.map +1 -1
  12. package/dist/entry/sd-cli-project.d.ts +11 -11
  13. package/dist/entry/sd-cli-project.js +11 -14
  14. package/dist/entry/sd-cli-project.js.map +1 -1
  15. package/dist/entry/utils/loadProjConfAsync.d.ts +5 -0
  16. package/dist/entry/utils/loadProjConfAsync.js +8 -0
  17. package/dist/entry/utils/loadProjConfAsync.js.map +1 -0
  18. package/dist/pkg-builders/client/sd-client.build-runner.js +1 -1
  19. package/dist/pkg-builders/client/sd-client.build-runner.js.map +1 -1
  20. package/dist/pkg-builders/client/sd-ng.bundler-context.d.ts +6 -5
  21. package/dist/pkg-builders/client/sd-ng.bundler-context.js +6 -6
  22. package/dist/pkg-builders/client/sd-ng.bundler-context.js.map +1 -1
  23. package/dist/pkg-builders/client/sd-ng.bundler.d.ts +13 -13
  24. package/dist/pkg-builders/client/sd-ng.bundler.js +1 -1
  25. package/dist/pkg-builders/client/sd-ng.bundler.js.map +1 -1
  26. package/dist/pkg-builders/client/sd-ng.plugin-creator.js +4 -88
  27. package/dist/pkg-builders/client/sd-ng.plugin-creator.js.map +1 -1
  28. package/dist/pkg-builders/lib/sd-js-lib.build-runner.js.map +1 -1
  29. package/dist/pkg-builders/lib/sd-ts-lib.build-runner.d.ts +1 -1
  30. package/dist/pkg-builders/lib/sd-ts-lib.build-runner.js.map +1 -1
  31. package/dist/pkg-builders/lib/sd-ts-lib.builder.js.map +1 -1
  32. package/dist/pkg-builders/sd-multi.build-runner.d.ts +4 -0
  33. package/dist/pkg-builders/sd-multi.build-runner.js +33 -25
  34. package/dist/pkg-builders/sd-multi.build-runner.js.map +1 -1
  35. package/dist/pkg-builders/server/sd-server.build-runner.js.map +1 -1
  36. package/dist/pkg-builders/server/sd-server.bundler.d.ts +6 -2
  37. package/dist/pkg-builders/server/sd-server.bundler.js +24 -24
  38. package/dist/pkg-builders/server/sd-server.bundler.js.map +1 -1
  39. package/dist/sd-cli/vitest.config.d.ts +2 -0
  40. package/dist/sd-cli/vitest.config.js +15 -0
  41. package/dist/sd-cli/vitest.config.js.map +1 -0
  42. package/dist/sd-cli.js +7 -36
  43. package/dist/sd-cli.js.map +1 -1
  44. package/dist/ts-compiler/sd-dependency-analyzer.d.ts +8 -0
  45. package/dist/ts-compiler/sd-dependency-analyzer.js +244 -0
  46. package/dist/ts-compiler/sd-dependency-analyzer.js.map +1 -0
  47. package/dist/ts-compiler/sd-dependency-cache.d.ts +27 -0
  48. package/dist/ts-compiler/sd-dependency-cache.js +232 -0
  49. package/dist/ts-compiler/sd-dependency-cache.js.map +1 -0
  50. package/dist/ts-compiler/sd-ts-compiler.d.ts +7 -9
  51. package/dist/ts-compiler/sd-ts-compiler.js +101 -188
  52. package/dist/ts-compiler/sd-ts-compiler.js.map +1 -1
  53. package/dist/types/worker.types.d.ts +19 -0
  54. package/dist/utils/sd-cli-performance-time.d.ts +2 -1
  55. package/dist/utils/sd-cli-performance-time.js +9 -9
  56. package/dist/utils/sd-cli-performance-time.js.map +1 -1
  57. package/dist/workers/style-bundler.worker.d.ts +1 -0
  58. package/dist/workers/style-bundler.worker.js +56 -0
  59. package/dist/workers/style-bundler.worker.js.map +1 -0
  60. package/package.json +11 -11
  61. package/src/entry/sd-cli-ai-command.ts +2 -1
  62. package/src/entry/sd-cli-cordova.ts +20 -20
  63. package/src/entry/sd-cli-electron.ts +54 -23
  64. package/src/entry/sd-cli-local-update.ts +14 -29
  65. package/src/entry/sd-cli-project.ts +24 -41
  66. package/src/entry/utils/loadProjConfAsync.ts +12 -0
  67. package/src/pkg-builders/client/sd-client.build-runner.ts +7 -7
  68. package/src/pkg-builders/client/sd-ng.bundler-context.ts +15 -12
  69. package/src/pkg-builders/client/sd-ng.bundler.ts +17 -20
  70. package/src/pkg-builders/client/sd-ng.plugin-creator.ts +5 -94
  71. package/src/pkg-builders/lib/sd-js-lib.build-runner.ts +6 -6
  72. package/src/pkg-builders/lib/sd-ts-lib.build-runner.ts +7 -7
  73. package/src/pkg-builders/lib/sd-ts-lib.builder.ts +1 -1
  74. package/src/pkg-builders/sd-multi.build-runner.ts +54 -39
  75. package/src/pkg-builders/server/sd-server.build-runner.ts +6 -6
  76. package/src/pkg-builders/server/sd-server.bundler.ts +43 -35
  77. package/src/sd-cli.ts +7 -36
  78. package/src/ts-compiler/sd-dependency-analyzer.ts +312 -0
  79. package/src/ts-compiler/sd-dependency-cache.ts +328 -0
  80. package/src/ts-compiler/sd-ts-compiler.ts +161 -256
  81. package/src/types/worker.types.ts +17 -0
  82. package/src/utils/sd-cli-performance-time.ts +9 -9
  83. package/src/workers/style-bundler.worker.ts +70 -0
  84. package/tests/deps/sd-dependency-analyzer.spec.ts +272 -0
  85. package/tests/deps/sd-dependency-cache.spec.ts +144 -0
  86. package/tsconfig.json +1 -1
  87. package/tsconfig.test.json +8 -0
  88. package/vitest.config.ts +15 -0
  89. package/dist/index.d.ts +0 -34
  90. package/dist/index.js +0 -35
  91. package/dist/index.js.map +0 -1
  92. package/dist/ts-compiler/sd-ts-dependency-analyzer.d.ts +0 -10
  93. package/dist/ts-compiler/sd-ts-dependency-analyzer.js +0 -140
  94. package/dist/ts-compiler/sd-ts-dependency-analyzer.js.map +0 -1
  95. package/src/index.ts +0 -34
  96. package/src/ts-compiler/sd-ts-dependency-analyzer.ts +0 -176
@@ -1,33 +1,34 @@
1
1
  import esbuild from "esbuild";
2
2
  import path from "path";
3
- import { FsUtils, SdLogger, PathUtils, TNormPath } from "@simplysm/sd-core-node";
3
+ import { FsUtils, HashUtils, PathUtils, SdLogger, TNormPath } from "@simplysm/sd-core-node";
4
4
  import { SdCliConvertMessageUtils } from "../../utils/sd-cli-convert-message.utils";
5
5
  import { ISdCliServerPluginResultCache } from "../../types/build-plugin.types";
6
6
  import { ISdBuildMessage } from "../../types/build.types";
7
7
  import { createSdServerPlugin } from "./sd-server.plugin-creator";
8
- import { BuildOutputFile, BuildOutputFileType } from "@angular/build/src/tools/esbuild/bundler-context";
8
+ import {
9
+ BuildOutputFile,
10
+ BuildOutputFileType,
11
+ } from "@angular/build/src/tools/esbuild/bundler-context";
9
12
  import { convertOutputFile } from "@angular/build/src/tools/esbuild/utils";
10
13
  import { resolveAssets } from "@angular/build/src/utils/resolve-assets";
11
14
 
12
15
  export class SdServerBundler {
13
- readonly #logger = SdLogger.get(["simplysm", "sd-cli", "SdServerBundler"]);
16
+ private _logger = SdLogger.get(["simplysm", "sd-cli", "SdServerBundler"]);
14
17
 
15
- #context?: esbuild.BuildContext;
18
+ private _context?: esbuild.BuildContext;
16
19
 
17
- readonly #modifiedFileSet = new Set<TNormPath>();
18
- readonly #resultCache: ISdCliServerPluginResultCache = {};
20
+ private _modifiedFileSet = new Set<TNormPath>();
21
+ private _resultCache: ISdCliServerPluginResultCache = {};
19
22
 
20
- readonly #outputCache = new Map<TNormPath, string | number>();
23
+ private _outputHashCache = new Map<TNormPath, string>();
21
24
 
22
- constructor(
23
- private readonly _opt: {
24
- dev: boolean;
25
- pkgPath: TNormPath;
26
- entryPoints: string[];
27
- external?: string[];
28
- watchScopePaths: TNormPath[];
29
- },
30
- ) {
25
+ constructor(private _opt: {
26
+ dev: boolean;
27
+ pkgPath: TNormPath;
28
+ entryPoints: string[];
29
+ external?: string[];
30
+ watchScopePaths: TNormPath[];
31
+ }) {
31
32
  }
32
33
 
33
34
  async bundleAsync(modifiedFileSet?: Set<TNormPath>): Promise<{
@@ -36,13 +37,13 @@ export class SdServerBundler {
36
37
  results: ISdBuildMessage[];
37
38
  emitFileSet: Set<TNormPath>;
38
39
  }> {
39
- this.#modifiedFileSet.clear();
40
+ this._modifiedFileSet.clear();
40
41
  if (modifiedFileSet) {
41
- this.#modifiedFileSet.adds(...modifiedFileSet);
42
+ this._modifiedFileSet.adds(...modifiedFileSet);
42
43
  }
43
44
 
44
- if (!this.#context) {
45
- this.#context = await esbuild.context({
45
+ if (!this._context) {
46
+ this._context = await esbuild.context({
46
47
  entryPoints: this._opt.entryPoints,
47
48
  keepNames: true,
48
49
  bundle: true,
@@ -103,10 +104,10 @@ const __dirname = __path__.dirname(__filename);`.trim(),
103
104
  },
104
105
  plugins: [
105
106
  createSdServerPlugin({
106
- modifiedFileSet: this.#modifiedFileSet,
107
+ modifiedFileSet: this._modifiedFileSet,
107
108
  dev: this._opt.dev,
108
109
  pkgPath: this._opt.pkgPath,
109
- result: this.#resultCache,
110
+ result: this._resultCache,
110
111
  watchScopePaths: this._opt.watchScopePaths,
111
112
  }),
112
113
  ],
@@ -116,17 +117,18 @@ const __dirname = __path__.dirname(__filename);`.trim(),
116
117
  const emitFileSet = new Set<TNormPath>();
117
118
  let result: esbuild.BuildResult | esbuild.BuildFailure;
118
119
  try {
119
- result = await this.#context.rebuild();
120
+ result = await this._context.rebuild();
120
121
 
121
122
  const outputFiles: BuildOutputFile[] =
122
123
  result.outputFiles?.map((file) => convertOutputFile(file, BuildOutputFileType.Root)) ?? [];
123
124
 
124
125
  for (const outputFile of outputFiles) {
125
126
  const distFilePath = PathUtils.norm(this._opt.pkgPath, outputFile.path);
126
- const prev = this.#outputCache.get(distFilePath);
127
- if (prev !== Buffer.from(outputFile.contents).toString("base64")) {
127
+ const prevHash = this._outputHashCache.get(distFilePath);
128
+ const currHash = HashUtils.get(outputFile.contents);
129
+ if (prevHash !== currHash) {
128
130
  FsUtils.writeFile(distFilePath, outputFile.contents);
129
- this.#outputCache.set(distFilePath, Buffer.from(outputFile.contents).toString("base64"));
131
+ this._outputHashCache.set(distFilePath, currHash);
130
132
  emitFileSet.add(distFilePath);
131
133
  }
132
134
  }
@@ -141,11 +143,14 @@ const __dirname = __path__.dirname(__filename);`.trim(),
141
143
  );
142
144
 
143
145
  for (const assetFile of assetFiles) {
144
- const prev = this.#outputCache.get(PathUtils.norm(assetFile.source));
145
- const curr = FsUtils.lstat(assetFile.source).mtime.getTime();
146
- if (prev !== curr) {
147
- FsUtils.copy(assetFile.source, path.resolve(this._opt.pkgPath, "dist", assetFile.destination));
148
- this.#outputCache.set(PathUtils.norm(assetFile.source), curr);
146
+ const prevHash = this._outputHashCache.get(PathUtils.norm(assetFile.source));
147
+ const currHash = FsUtils.hash(assetFile.source);
148
+ if (prevHash !== currHash) {
149
+ FsUtils.copy(
150
+ assetFile.source,
151
+ path.resolve(this._opt.pkgPath, "dist", assetFile.destination),
152
+ );
153
+ this._outputHashCache.set(PathUtils.norm(assetFile.source), currHash);
149
154
  emitFileSet.add(PathUtils.norm(assetFile.destination));
150
155
  }
151
156
  }
@@ -154,15 +159,18 @@ const __dirname = __path__.dirname(__filename);`.trim(),
154
159
  result = err;
155
160
  for (const e of err.errors) {
156
161
  if (e.detail != null) {
157
- this.#logger.error(e.detail);
162
+ this._logger.error(e.detail);
158
163
  }
159
164
  }
160
165
  }
161
166
 
162
167
  return {
163
- watchFileSet: this.#resultCache.watchFileSet!,
164
- affectedFileSet: this.#resultCache.affectedFileSet!,
165
- results: SdCliConvertMessageUtils.convertToBuildMessagesFromEsbuild(result, this._opt.pkgPath),
168
+ watchFileSet: this._resultCache.watchFileSet!,
169
+ affectedFileSet: this._resultCache.affectedFileSet!,
170
+ results: SdCliConvertMessageUtils.convertToBuildMessagesFromEsbuild(
171
+ result,
172
+ this._opt.pkgPath,
173
+ ),
166
174
  emitFileSet: emitFileSet,
167
175
  };
168
176
  }
package/src/sd-cli.ts CHANGED
@@ -201,54 +201,25 @@ else {
201
201
  }
202
202
 
203
203
  if (argv._[0] === "local-update") {
204
- await SdCliLocalUpdate.runAsync({
205
- confFileRelPath: argv.config ?? "simplysm.js",
206
- optNames: argv.options ?? [],
207
- });
204
+ await SdCliLocalUpdate.runAsync(argv);
208
205
  }
209
206
  else if (argv._[0] === "watch") {
210
- await SdCliProject.watchAsync({
211
- confFileRelPath: argv.config ?? "simplysm.js",
212
- optNames: argv.options ?? [],
213
- pkgNames: argv.packages ?? [],
214
- inspectNames: argv.inspects ?? [],
215
- });
207
+ await SdCliProject.watchAsync(argv);
216
208
  }
217
209
  else if (argv._[0] === "build") {
218
- await SdCliProject.buildAsync({
219
- confFileRelPath: argv.config ?? "simplysm.js",
220
- optNames: argv.options ?? [],
221
- pkgNames: argv.packages ?? [],
222
- });
210
+ await SdCliProject.buildAsync(argv);
223
211
  }
224
212
  else if (argv._[0] === "publish") {
225
- await SdCliProject.publishAsync({
226
- noBuild: argv.noBuild,
227
- confFileRelPath: argv.config ?? "simplysm.js",
228
- optNames: argv.options ?? [],
229
- pkgNames: argv.packages ?? [],
230
- });
213
+ await SdCliProject.publishAsync(argv);
231
214
  }
232
215
  else if (argv._[0] === "run-electron") {
233
- await SdCliElectron.runAsync({
234
- confFileRelPath: argv.config ?? "simplysm.js",
235
- optNames: argv.options ?? [],
236
- pkgName: argv.package,
237
- });
216
+ await SdCliElectron.runAsync(argv);
238
217
  }
239
218
  else if (argv._[0] === "build-electron-for-dev") {
240
- await SdCliElectron.buildForDevAsync({
241
- confFileRelPath: argv.config ?? "simplysm.js",
242
- optNames: argv.options ?? [],
243
- pkgName: argv.package,
244
- });
219
+ await SdCliElectron.buildForDevAsync(argv);
245
220
  }
246
221
  else if (argv._[0] === "run-cordova") {
247
- await SdCliCordova.runWebviewOnDeviceAsync({
248
- platform: argv.platform,
249
- pkgName: argv.package,
250
- url: argv.url,
251
- });
222
+ await SdCliCordova.runWebviewOnDeviceAsync(argv);
252
223
  }
253
224
  else if (argv._[0] === "commit") {
254
225
  await SdCliAiCommand.commitAsync();
@@ -0,0 +1,312 @@
1
+ import ts from "typescript";
2
+ import { SdDependencyCache } from "./sd-dependency-cache";
3
+ import { PathUtils, TNormPath } from "@simplysm/sd-core-node";
4
+ import path from "path";
5
+ import { NgtscProgram } from "@angular/compiler-cli";
6
+
7
+ export class SdDependencyAnalyzer {
8
+ static analyze(
9
+ program: ts.Program,
10
+ compilerHost: ts.CompilerHost,
11
+ scopePaths: TNormPath[],
12
+ depCache: SdDependencyCache,
13
+ ): void {
14
+ const compilerOpts = program.getCompilerOptions();
15
+ const typeChecker = program.getTypeChecker();
16
+
17
+ const inScope = (filePath: string): boolean => {
18
+ return scopePaths.some((scope) => PathUtils.isChildPath(filePath, scope));
19
+ };
20
+
21
+ const resolveModule = (text: string, base: string): TNormPath[] => {
22
+ const res = ts.resolveModuleName(
23
+ text,
24
+ base,
25
+ compilerOpts,
26
+ compilerHost,
27
+ );
28
+
29
+ if (res.resolvedModule) {
30
+ return [
31
+ PathUtils.norm(res.resolvedModule.resolvedFileName),
32
+ ];
33
+ }
34
+
35
+ const absPath = path.resolve(path.dirname(base), text);
36
+ if (!inScope(absPath)) {
37
+ return [];
38
+ }
39
+ else if (
40
+ // 지원되게할 .png등이면 그냥 가져오고 (bundling loader에 들어가는것들과 .ts, .json등)
41
+ // fallback일때는 absPath에 .ts, .d.ts, .js, .json 등 다붙여서 가져와야함
42
+ [
43
+ ".ts",
44
+ ".d.ts",
45
+ ".js",
46
+ ".json",
47
+
48
+ ".html",
49
+ ".scss",
50
+ ".css",
51
+
52
+ ".png",
53
+ ".jpeg",
54
+ ".jpg",
55
+ ".jfif",
56
+ ".gif",
57
+ ".svg",
58
+ ".woff",
59
+ ".woff2",
60
+ ".ttf",
61
+ ".ttc",
62
+ ".eot",
63
+ ".ico",
64
+ ".otf",
65
+ ".csv",
66
+ ".xlsx",
67
+ ".xls",
68
+ ".pptx",
69
+ ".ppt",
70
+ ".docx",
71
+ ".doc",
72
+ ".zip",
73
+ ".pfx",
74
+ ".pkl",
75
+ ".mp3",
76
+ ".ogg",
77
+ ].some(ext => absPath.endsWith(ext))
78
+ ) {
79
+ return [
80
+ PathUtils.norm(absPath),
81
+ ];
82
+ }
83
+ else {
84
+ return [
85
+ PathUtils.norm(absPath + ".ts"),
86
+ PathUtils.norm(absPath + ".js"),
87
+ PathUtils.norm(absPath + ".d.ts"),
88
+ PathUtils.norm(absPath + ".json"),
89
+ ];
90
+ }
91
+ };
92
+
93
+ const isInImportOrExport = (node: ts.Node) => {
94
+ let curr = node as ts.Node | undefined;
95
+ while (curr) {
96
+ if (
97
+ ts.isImportDeclaration(curr) ||
98
+ ts.isExportDeclaration(curr) ||
99
+ ts.isImportSpecifier(curr) ||
100
+ ts.isExportSpecifier(curr) ||
101
+ ts.isNamespaceImport(curr)
102
+ ) {
103
+ return true;
104
+ }
105
+ curr = curr.parent;
106
+ }
107
+ return false;
108
+ };
109
+
110
+ const typeCache = new WeakMap<ts.Node, ts.Type>();
111
+
112
+ const getCachedType = (node: ts.Node) => {
113
+ if (typeCache.has(node)) return typeCache.get(node);
114
+ const type = typeChecker.getTypeAtLocation(node) as ts.Type | undefined;
115
+ if (type) typeCache.set(node, type);
116
+ return type;
117
+ };
118
+
119
+ const collectDeps = (sf: ts.SourceFile) => {
120
+ const sfNPath = PathUtils.norm(sf.fileName);
121
+ if (depCache.hasCollected(sfNPath)) return;
122
+ depCache.addCollected(sfNPath);
123
+
124
+ const visit = (node: ts.Node) => {
125
+ // --- import ... from '...'
126
+ if (
127
+ ts.isImportDeclaration(node) &&
128
+ ts.isStringLiteral(node.moduleSpecifier)
129
+ ) {
130
+ const resolvedNPaths = resolveModule(node.moduleSpecifier.text, sf.fileName);
131
+ for (const resolvedNPath of resolvedNPaths) {
132
+ if (
133
+ node.importClause &&
134
+ node.importClause.namedBindings &&
135
+ ts.isNamedImports(node.importClause.namedBindings)
136
+ ) {
137
+ for (const element of node.importClause.namedBindings.elements) {
138
+ depCache.addImport(
139
+ sfNPath,
140
+ resolvedNPath,
141
+ element.propertyName?.text ?? element.name.text,
142
+ );
143
+ }
144
+ }
145
+ else {
146
+ depCache.addImport(sfNPath, resolvedNPath, 0);
147
+ }
148
+ }
149
+ }
150
+
151
+ // --- export * from '...'
152
+ else if (
153
+ ts.isExportDeclaration(node) &&
154
+ !node.exportClause &&
155
+ node.moduleSpecifier &&
156
+ ts.isStringLiteral(node.moduleSpecifier)
157
+ ) {
158
+ const resolvedNPaths = resolveModule(node.moduleSpecifier.text, sf.fileName);
159
+ for (const resolvedNPath of resolvedNPaths) {
160
+ depCache.addReexport(sfNPath, resolvedNPath, 0);
161
+ }
162
+ }
163
+
164
+ // --- export { A as B } from '...'
165
+ if (
166
+ ts.isExportDeclaration(node) &&
167
+ node.exportClause &&
168
+ ts.isNamedExports(node.exportClause) &&
169
+ node.moduleSpecifier &&
170
+ ts.isStringLiteral(node.moduleSpecifier)
171
+ ) {
172
+ const resolvedNPaths = resolveModule(node.moduleSpecifier.text, sf.fileName);
173
+ for (const resolvedNPath of resolvedNPaths) {
174
+ for (const element of node.exportClause.elements) {
175
+ const local = element.propertyName?.text ?? element.name.text;
176
+ const exported = element.name.text;
177
+ depCache.addReexport(sfNPath, resolvedNPath, {
178
+ importSymbol: local,
179
+ exportSymbol: exported,
180
+ });
181
+ }
182
+ }
183
+ }
184
+
185
+ // --- export const A = ...
186
+ else if (
187
+ ts.isVariableStatement(node) &&
188
+ node.modifiers?.some(mod => mod.kind === ts.SyntaxKind.ExportKeyword)
189
+ ) {
190
+ for (const decl of node.declarationList.declarations) {
191
+ if (ts.isIdentifier(decl.name)) {
192
+ depCache.addExport(sfNPath, decl.name.text);
193
+ }
194
+ }
195
+ }
196
+
197
+ // --- export function/class/interface A ...
198
+ else if (
199
+ (
200
+ ts.isFunctionDeclaration(node) ||
201
+ ts.isClassDeclaration(node) ||
202
+ ts.isInterfaceDeclaration(node) ||
203
+ ts.isTypeAliasDeclaration(node) ||
204
+ ts.isEnumDeclaration(node)
205
+ ) &&
206
+ node.modifiers?.some(mod => mod.kind === ts.SyntaxKind.ExportKeyword) &&
207
+ node.name
208
+ ) {
209
+ depCache.addExport(sfNPath, node.name.text);
210
+ }
211
+
212
+ else if (ts.isIdentifier(node) && !isInImportOrExport(node)) {
213
+ const orgValSymbol = typeChecker.getSymbolAtLocation(node);
214
+
215
+ // alias (import된 심볼)일 경우, 원본 심볼로 치환
216
+ const valSymbol = (orgValSymbol && (orgValSymbol.flags & ts.SymbolFlags.Alias))
217
+ ? typeChecker.getAliasedSymbol(orgValSymbol)
218
+ : undefined;
219
+
220
+ for (const decl of valSymbol?.getDeclarations() ?? []) {
221
+ const declFile = decl.getSourceFile();
222
+ const declNPath = PathUtils.norm(declFile.fileName);
223
+ if (declNPath !== sfNPath && inScope(declNPath)) {
224
+ depCache.addImport(sfNPath, declNPath, 0);
225
+ }
226
+ }
227
+ }
228
+ else if (
229
+ ts.isPropertyAccessExpression(node)
230
+ ) {
231
+ const type = getCachedType(node.expression);
232
+ const propSymbol = type?.getProperty(node.name.text);
233
+
234
+ if (propSymbol) {
235
+ for (const decl of propSymbol.getDeclarations() ?? []) {
236
+ const declFile = decl.getSourceFile();
237
+ const declNPath = PathUtils.norm(declFile.fileName);
238
+ if (declNPath !== sfNPath && inScope(declNPath)) {
239
+ depCache.addImport(sfNPath, declNPath, 0);
240
+ }
241
+ }
242
+ }
243
+ }
244
+ else if (
245
+ ts.isElementAccessExpression(node) &&
246
+ ts.isStringLiteral(node.argumentExpression)
247
+ ) {
248
+ const type = getCachedType(node.expression);
249
+ const propSymbol = type?.getProperty(node.argumentExpression.text);
250
+
251
+ if (propSymbol) {
252
+ for (const decl of propSymbol.getDeclarations() ?? []) {
253
+ const declFile = decl.getSourceFile();
254
+ const declNPath = PathUtils.norm(declFile.fileName);
255
+ if (declNPath !== sfNPath && inScope(declNPath)) {
256
+ depCache.addImport(sfNPath, declNPath, 0);
257
+ }
258
+ }
259
+ }
260
+ }
261
+
262
+ ts.forEachChild(node, visit);
263
+ };
264
+
265
+ ts.forEachChild(sf, visit);
266
+ };
267
+
268
+ const getOrgSourceFile = (sf: ts.SourceFile) => {
269
+ if (sf.fileName.endsWith(".ngtypecheck.ts")) {
270
+ const orgFileName = sf.fileName.slice(0, -15) + ".ts";
271
+ return program.getSourceFile(orgFileName);
272
+ }
273
+ return sf;
274
+ };
275
+
276
+ const sourceFileSet = new Set(
277
+ program.getSourceFiles()
278
+ .filter((sf) => inScope(sf.fileName))
279
+ .map((sf) => getOrgSourceFile(sf))
280
+ .filterExists(),
281
+ );
282
+
283
+ for (const sf of sourceFileSet) {
284
+ collectDeps(sf);
285
+ }
286
+ }
287
+
288
+
289
+ static analyzeAngularResources(
290
+ ngProgram: NgtscProgram,
291
+ scopePaths: TNormPath[],
292
+ depCache: SdDependencyCache,
293
+ ) {
294
+ const inScope = (filePath: string): boolean => {
295
+ return scopePaths.some((scope) => PathUtils.isChildPath(filePath, scope));
296
+ };
297
+
298
+ for (const sf of ngProgram.getTsProgram().getSourceFiles()) {
299
+ const fileNPath = PathUtils.norm(sf.fileName);
300
+ if (!inScope(fileNPath)) continue;
301
+
302
+ const dependencies = ngProgram.compiler.getResourceDependencies(sf);
303
+ for (const dep of dependencies) {
304
+ const depNPath = PathUtils.norm(dep);
305
+ if (!inScope(depNPath)) continue;
306
+
307
+ console.log(fileNPath, depNPath);
308
+ depCache.addImport(fileNPath, depNPath, 0);
309
+ }
310
+ }
311
+ }
312
+ }