@simplysm/sd-cli 12.11.8 → 12.11.10

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 (38) hide show
  1. package/dist/pkg-builders/client/sd-cli-ng-routes.file-generator.d.ts +3 -2
  2. package/dist/pkg-builders/client/sd-cli-ng-routes.file-generator.js +12 -10
  3. package/dist/pkg-builders/client/sd-cli-ng-routes.file-generator.js.map +1 -1
  4. package/dist/pkg-builders/client/sd-client.build-runner.js +7 -5
  5. package/dist/pkg-builders/client/sd-client.build-runner.js.map +1 -1
  6. package/dist/pkg-builders/client/sd-ng.bundler.js +1 -1
  7. package/dist/pkg-builders/client/sd-ng.bundler.js.map +1 -1
  8. package/dist/pkg-builders/commons/build-runner.base.js +4 -5
  9. package/dist/pkg-builders/commons/build-runner.base.js.map +1 -1
  10. package/dist/pkg-builders/lib/sd-cli-db-context.file-generator.d.ts +3 -2
  11. package/dist/pkg-builders/lib/sd-cli-db-context.file-generator.js +10 -9
  12. package/dist/pkg-builders/lib/sd-cli-db-context.file-generator.js.map +1 -1
  13. package/dist/pkg-builders/lib/sd-cli-index.file-generator.d.ts +3 -2
  14. package/dist/pkg-builders/lib/sd-cli-index.file-generator.js +14 -9
  15. package/dist/pkg-builders/lib/sd-cli-index.file-generator.js.map +1 -1
  16. package/dist/pkg-builders/lib/sd-ts-lib.build-runner.js +8 -4
  17. package/dist/pkg-builders/lib/sd-ts-lib.build-runner.js.map +1 -1
  18. package/dist/pkg-builders/lib/sd-ts-lib.builder.js +19 -10
  19. package/dist/pkg-builders/lib/sd-ts-lib.builder.js.map +1 -1
  20. package/dist/pkg-builders/server/sd-server.build-runner.js +1 -1
  21. package/dist/pkg-builders/server/sd-server.bundler.js +1 -1
  22. package/dist/pkg-builders/server/sd-server.bundler.js.map +1 -1
  23. package/dist/ts-compiler/sd-dependency-cache.d.ts +56 -0
  24. package/dist/ts-compiler/sd-dependency-cache.js +183 -118
  25. package/dist/ts-compiler/sd-dependency-cache.js.map +1 -1
  26. package/package.json +5 -5
  27. package/src/pkg-builders/client/sd-cli-ng-routes.file-generator.ts +20 -15
  28. package/src/pkg-builders/client/sd-client.build-runner.ts +15 -10
  29. package/src/pkg-builders/client/sd-ng.bundler.ts +1 -1
  30. package/src/pkg-builders/commons/build-runner.base.ts +19 -16
  31. package/src/pkg-builders/lib/sd-cli-db-context.file-generator.ts +12 -9
  32. package/src/pkg-builders/lib/sd-cli-index.file-generator.ts +18 -10
  33. package/src/pkg-builders/lib/sd-ts-lib.build-runner.ts +7 -6
  34. package/src/pkg-builders/lib/sd-ts-lib.builder.ts +22 -12
  35. package/src/pkg-builders/server/sd-server.build-runner.ts +1 -1
  36. package/src/pkg-builders/server/sd-server.bundler.ts +11 -11
  37. package/src/ts-compiler/sd-dependency-cache.ts +208 -171
  38. package/tests/deps/sd-dependency-cache.spec.ts +12 -0
@@ -1,138 +1,184 @@
1
1
  import { TNormPath } from "@simplysm/sd-core-node";
2
2
 
3
3
  export class SdDependencyCache {
4
- #exportCache = new Map<
5
- /* fileNPath: */ TNormPath,
6
- /* exportSymbolSet: */ Set<string>
7
- >();
8
-
9
- #importCache = new Map<
10
- /* fileNPath: */ TNormPath,
4
+ /**
5
+ * 파일이 export한 심볼 집합 (예: export const A → "A")
6
+ */
7
+ private _exportCache = new Map<TNormPath, Set<string>>();
8
+
9
+ /**
10
+ * import한 타겟과 그 심볼 정보
11
+ * - 값이 0이면 전체 import(import * 또는 리소스 import)
12
+ * - 값이 Set이면 선택적 심볼 import (예: import { A } ...)
13
+ */
14
+ private _importCache = new Map<TNormPath, Map<TNormPath, Set<string> | 0>>();
15
+
16
+ /**
17
+ * re-export한 타겟과 그 심볼 정보
18
+ * - export * from ...
19
+ * - export { A as B } from ...
20
+ * - 값이 0이면 전체 reexport(export * from ...)
21
+ */
22
+ private _reexportCache = new Map<
23
+ TNormPath,
11
24
  Map<
12
- /* targetNPath: */ TNormPath,
13
- /* targetSymbolSet: */ Set<string> | 0
25
+ TNormPath,
26
+ | {
27
+ importSymbol: string;
28
+ exportSymbol: string;
29
+ }[]
30
+ | 0
14
31
  >
15
32
  >();
16
33
 
17
- #reexportCache = new Map<
18
- /* fileNPath: */ TNormPath,
19
- Map<
20
- /* targetNPath: */ TNormPath,
21
- /* targetSymbolInfos: */ {
22
- importSymbol: string;
23
- exportSymbol: string;
24
- }[] | 0
25
- >
26
- >();
27
-
28
- #revDepCache = new Map<
29
- /* targetNPath: */ TNormPath,
30
- Map<
31
- /* fileNPath: */ TNormPath,
32
- /* exportSymbolSet: */ Set<string> | 0 // fileNPath입장에선 import, targetNPath입장에선 export
33
- >
34
- >();
35
-
36
- #collectedCache = new Set<TNormPath>();
34
+ /**
35
+ * 역의존 정보 (revDep)
36
+ * - 특정 파일이 어떤 파일에게 의존(참조)되는지
37
+ * - symbol 기반 추적
38
+ */
39
+ private _revDepCache = new Map<TNormPath, Map<TNormPath, Set<string> | 0>>();
40
+
41
+ /**
42
+ * 분석이 완료된 파일 경로
43
+ */
44
+ private _collectedCache = new Set<TNormPath>();
45
+
46
+ /**
47
+ * .d.ts 또는 .js가 입력되었을 때 쌍으로 존재하는 파일 경로를 반환
48
+ * 예: "/a.d.ts" → ["/a.d.ts", "/a.js"]
49
+ */
50
+ #getRelatedNPaths(nPath: TNormPath): TNormPath[] {
51
+ if (nPath.endsWith(".d.ts")) {
52
+ return [nPath, nPath.replace(/\.d\.ts$/, ".js") as TNormPath];
53
+ }
54
+ if (nPath.endsWith(".js")) {
55
+ return [nPath, nPath.replace(/\.js$/, ".d.ts") as TNormPath];
56
+ }
57
+ return [nPath];
58
+ }
37
59
 
60
+ /**
61
+ * 전체 추적된 파일 경로를 반환
62
+ */
38
63
  getFiles(): Set<TNormPath> {
39
- return new Set<TNormPath>([
40
- ...this.#collectedCache.keys(),
41
- ...this.#revDepCache.keys(),
42
- ]);
64
+ return new Set<TNormPath>([...this._collectedCache.keys(), ...this._revDepCache.keys()]);
43
65
  }
44
66
 
67
+ /**
68
+ * 분석이 완료된 파일로 표시
69
+ */
45
70
  addCollected(fileNPath: TNormPath) {
46
- this.#collectedCache.add(fileNPath);
71
+ for (const path of this.#getRelatedNPaths(fileNPath)) {
72
+ this._collectedCache.add(path);
73
+ }
47
74
  }
48
75
 
49
76
  hasCollected(fileNPath: TNormPath) {
50
- return this.#collectedCache.has(fileNPath);
77
+ return this._collectedCache.has(fileNPath);
51
78
  }
52
79
 
53
- // export const ...
54
- // export function/class/interface A ...
80
+ /**
81
+ * export 심볼 등록
82
+ * 예: export const A → "A"
83
+ */
55
84
  addExport(fileNPath: TNormPath, exportSymbol: string) {
56
- const exportSymbolSet = this.#exportCache.getOrCreate(fileNPath, new Set());
57
- exportSymbolSet.add(exportSymbol);
85
+ for (const path of this.#getRelatedNPaths(fileNPath)) {
86
+ const exportSymbolSet = this._exportCache.getOrCreate(path, new Set());
87
+ exportSymbolSet.add(exportSymbol);
88
+ }
58
89
  }
59
90
 
60
- // import * from "..."
61
- // import ... from "..."
62
- // import(...)
63
- // require(...)
91
+ /**
92
+ * import 구문 등록
93
+ * - import * from ... → symbol = 0
94
+ * - import { A } from ... → symbol = "A"
95
+ */
64
96
  addImport(fileNPath: TNormPath, targetNPath: TNormPath, targetSymbol: string | 0) {
65
- const importTargetMap = this.#importCache.getOrCreate(fileNPath, new Map());
66
- if (targetSymbol === 0) {
67
- importTargetMap.set(targetNPath, 0);
68
- this.#addRevDep(targetNPath, fileNPath, 0);
69
- }
70
- else {
71
- const importTargetSymbolSet = importTargetMap.getOrCreate(targetNPath, new Set());
72
- if (importTargetSymbolSet === 0) {
73
- return;
97
+ for (const filePath of this.#getRelatedNPaths(fileNPath)) {
98
+ for (const targetPath of this.#getRelatedNPaths(targetNPath)) {
99
+ const importTargetMap = this._importCache.getOrCreate(filePath, new Map());
100
+
101
+ if (targetSymbol === 0) {
102
+ importTargetMap.set(targetPath, 0);
103
+ this.#addRevDep(targetPath, filePath, 0);
104
+ } else {
105
+ const importTargetSymbolSet = importTargetMap.getOrCreate(targetPath, new Set());
106
+ if (importTargetSymbolSet === 0) return;
107
+
108
+ importTargetSymbolSet.add(targetSymbol);
109
+ this.#addRevDep(targetPath, filePath, targetSymbol);
110
+ }
74
111
  }
75
-
76
- importTargetSymbolSet.add(targetSymbol);
77
- this.#addRevDep(targetNPath, fileNPath, targetSymbol);
78
112
  }
79
113
  }
80
114
 
81
- // export * from '...'
82
- // export { A as B } from '...'
83
- //
84
- // exoprt/import에 자동등록하진 않음.
85
- // 차후 계산시 모든 캐시가 사용되므로,
86
- // 이 클래스를 사용하는 곳에서는 따로따로 입력하면됨
115
+ /**
116
+ * export * or export { A as B } from ... 구문 등록
117
+ * ※ export/import에 자동 등록되지 않으므로 외부에서 명시적으로 따로 입력해야 함
118
+ */
87
119
  addReexport(
88
120
  fileNPath: TNormPath,
89
121
  targetNPath: TNormPath,
90
- targetSymbolInfo: { importSymbol: string, exportSymbol: string } | 0,
122
+ targetSymbolInfo:
123
+ | {
124
+ importSymbol: string;
125
+ exportSymbol: string;
126
+ }
127
+ | 0,
91
128
  ) {
92
- const reexportTargetMap = this.#reexportCache.getOrCreate(fileNPath, new Map());
93
- if (targetSymbolInfo === 0) {
94
- reexportTargetMap.set(targetNPath, 0);
95
- this.#addRevDep(targetNPath, fileNPath, 0);
96
- }
97
- else {
98
- const reexportTargetSymbolInfos = reexportTargetMap.getOrCreate(targetNPath, []);
99
- if (reexportTargetSymbolInfos === 0) {
100
- return;
101
- }
102
-
103
- if (
104
- !reexportTargetSymbolInfos.some(item =>
105
- item.importSymbol === targetSymbolInfo.importSymbol &&
106
- item.exportSymbol === targetSymbolInfo.exportSymbol,
107
- )
108
- ) {
109
- reexportTargetSymbolInfos.push(targetSymbolInfo);
110
- this.#addRevDep(targetNPath, fileNPath, targetSymbolInfo.importSymbol);
129
+ for (const filePath of this.#getRelatedNPaths(fileNPath)) {
130
+ for (const targetPath of this.#getRelatedNPaths(targetNPath)) {
131
+ const reexportTargetMap = this._reexportCache.getOrCreate(filePath, new Map());
132
+
133
+ if (targetSymbolInfo === 0) {
134
+ reexportTargetMap.set(targetPath, 0);
135
+ this.#addRevDep(targetPath, filePath, 0);
136
+ } else {
137
+ const reexportTargetSymbolInfos = reexportTargetMap.getOrCreate(targetPath, []);
138
+ if (reexportTargetSymbolInfos === 0) return;
139
+
140
+ if (
141
+ !reexportTargetSymbolInfos.some(
142
+ (item) =>
143
+ item.importSymbol === targetSymbolInfo.importSymbol &&
144
+ item.exportSymbol === targetSymbolInfo.exportSymbol,
145
+ )
146
+ ) {
147
+ reexportTargetSymbolInfos.push(targetSymbolInfo);
148
+ this.#addRevDep(targetPath, filePath, targetSymbolInfo.importSymbol);
149
+ }
150
+ }
111
151
  }
112
152
  }
113
153
  }
114
154
 
155
+ /**
156
+ * 역의존 관계 등록 (revDep)
157
+ */
115
158
  #addRevDep(targetNPath: TNormPath, fileNPath: TNormPath, exportSymbol: string | 0) {
116
- const revDepInfoMap = this.#revDepCache.getOrCreate(targetNPath, new Map());
117
- if (exportSymbol === 0) {
118
- revDepInfoMap.set(fileNPath, exportSymbol);
119
- }
120
- else {
121
- const exportSymbolSet = revDepInfoMap.getOrCreate(fileNPath, new Set());
122
- if (exportSymbolSet === 0) {
123
- return;
159
+ for (const targetPath of this.#getRelatedNPaths(targetNPath)) {
160
+ for (const filePath of this.#getRelatedNPaths(fileNPath)) {
161
+ const revDepInfoMap = this._revDepCache.getOrCreate(targetPath, new Map());
162
+ if (exportSymbol === 0) {
163
+ revDepInfoMap.set(filePath, 0);
164
+ } else {
165
+ const exportSymbolSet = revDepInfoMap.getOrCreate(filePath, new Set());
166
+ if (exportSymbolSet === 0) return;
167
+
168
+ exportSymbolSet.add(exportSymbol);
169
+ }
124
170
  }
125
-
126
- exportSymbolSet.add(exportSymbol);
127
171
  }
128
172
  }
129
173
 
174
+ /**
175
+ * 변경된 파일 경로 집합으로부터 영향을 받는 전체 파일 집합을 계산
176
+ */
130
177
  getAffectedFileSet(modifiedNPathSet: Set<TNormPath>): Set<TNormPath> {
131
178
  const visited = new Set<string>();
179
+ const result = new Set<TNormPath>();
132
180
 
133
- const result = new Set<TNormPath>(modifiedNPathSet);
134
-
135
- const queue: { fileNPath: TNormPath, exportSymbol: string | undefined }[] = [];
181
+ const queue: { fileNPath: TNormPath; exportSymbol: string | undefined }[] = [];
136
182
 
137
183
  const enqueue = (fileNPath: TNormPath, exportSymbol: string | undefined) => {
138
184
  const key = `${fileNPath}#${exportSymbol}`;
@@ -143,45 +189,37 @@ export class SdDependencyCache {
143
189
  };
144
190
 
145
191
  for (const modifiedNPath of modifiedNPathSet) {
146
- const exportSymbols = this.#getExportSymbols(modifiedNPath);
147
- if (exportSymbols.size === 0) {
148
- enqueue(modifiedNPath, undefined);
149
- }
150
- else {
151
- for (const symbol of exportSymbols) {
152
- enqueue(modifiedNPath, symbol);
192
+ for (const path of this.#getRelatedNPaths(modifiedNPath)) {
193
+ result.add(path);
194
+ const exportSymbols = this.#getExportSymbols(path);
195
+ if (exportSymbols.size === 0) {
196
+ enqueue(path, undefined);
197
+ } else {
198
+ for (const symbol of exportSymbols) {
199
+ enqueue(path, symbol);
200
+ }
153
201
  }
154
202
  }
155
203
  }
156
204
 
157
205
  while (queue.length > 0) {
158
206
  const curr = queue.shift()!;
159
-
160
- /*const key = curr.fileNPath + "#" + curr.exportSymbol;
161
- if (visited.has(key)) continue;
162
- visited.add(key);*/
163
-
164
- const revDepInfoMap = this.#revDepCache.get(curr.fileNPath);
207
+ const revDepInfoMap = this._revDepCache.get(curr.fileNPath);
165
208
  if (!revDepInfoMap) continue;
166
209
 
167
210
  for (const [revDepFileNPath, revDepInfo] of revDepInfoMap) {
168
211
  if (curr.exportSymbol != null) {
169
- // curr의 export를 토대로 revDep이 사용하고 있는지 체크
170
- // curr.exportSymbol 와 revDev의 importSymbol은 같다
171
212
  const hasImportSymbol = revDepInfo === 0 || revDepInfo.has(curr.exportSymbol);
172
213
  if (hasImportSymbol) {
173
214
  result.add(revDepFileNPath);
174
-
175
- // 하위 Deps를 queue에 넣기전 export명칭 변환 (이름을 변경한 reexport일 경우 필요)
176
215
  const exportSymbol = this.#convertImportSymbolToExportSymbol(
177
216
  revDepFileNPath,
178
217
  curr.fileNPath,
179
- curr.exportSymbol, // revdep의 importSymbol
218
+ curr.exportSymbol,
180
219
  );
181
220
  enqueue(revDepFileNPath, exportSymbol);
182
221
  }
183
- }
184
- else { // Resource
222
+ } else {
185
223
  result.add(revDepFileNPath);
186
224
  }
187
225
  }
@@ -190,61 +228,64 @@ export class SdDependencyCache {
190
228
  return result;
191
229
  }
192
230
 
231
+ /**
232
+ * 주어진 파일들 및 그 영향 범위에 해당하는 모든 캐시를 무효화
233
+ */
193
234
  invalidates(fileNPathSet: Set<TNormPath>) {
194
235
  const affectedFiles = this.getAffectedFileSet(fileNPathSet);
195
236
 
196
237
  for (const fileNPath of affectedFiles) {
197
- this.#exportCache.delete(fileNPath);
198
- this.#importCache.delete(fileNPath);
199
- this.#reexportCache.delete(fileNPath);
200
- this.#collectedCache.delete(fileNPath);
201
- this.#revDepCache.delete(fileNPath); // ← 자기 자신이 key인 경우도 정리
238
+ this._exportCache.delete(fileNPath);
239
+ this._importCache.delete(fileNPath);
240
+ this._reexportCache.delete(fileNPath);
241
+ this._collectedCache.delete(fileNPath);
242
+ this._revDepCache.delete(fileNPath); // 자신이 key인 경우
202
243
  }
203
244
 
204
- // _revDepCache 역방향으로 순회
205
- for (const [targetNPath, infoMap] of this.#revDepCache) {
245
+ for (const [targetNPath, infoMap] of this._revDepCache) {
206
246
  for (const fileNPath of affectedFiles) {
207
247
  infoMap.delete(fileNPath);
208
248
  }
209
-
210
249
  if (infoMap.size === 0) {
211
- this.#revDepCache.delete(targetNPath);
250
+ this._revDepCache.delete(targetNPath);
212
251
  }
213
252
  }
214
253
  }
215
254
 
255
+ /**
256
+ * reexport된 경우 importSymbol → exportSymbol로 변환
257
+ */
216
258
  #convertImportSymbolToExportSymbol(
217
259
  fileNPath: TNormPath,
218
260
  targetNPath: TNormPath,
219
261
  importSymbol: string,
220
262
  ) {
221
- const symbolInfos = this.#reexportCache.get(fileNPath)?.get(targetNPath);
263
+ const symbolInfos = this._reexportCache.get(fileNPath)?.get(targetNPath);
222
264
  if (symbolInfos != null && symbolInfos !== 0 && symbolInfos.length > 0) {
223
- const symbolInfo = symbolInfos.single(item => item.importSymbol === importSymbol);
224
- if (symbolInfo) {
225
- return symbolInfo.exportSymbol;
226
- }
265
+ const symbolInfo = symbolInfos.single((item) => item.importSymbol === importSymbol);
266
+ if (symbolInfo) return symbolInfo.exportSymbol;
227
267
  }
228
-
229
268
  return importSymbol;
230
269
  }
231
270
 
271
+ /**
272
+ * 해당 파일에서 export된 모든 심볼 (직접 + 재export 포함)
273
+ */
232
274
  #getExportSymbols(fileNPath: TNormPath): Set<string> {
233
275
  const result = new Set<string>();
234
276
 
235
- const set = this.#exportCache.get(fileNPath);
236
- if (set) {
237
- result.adds(...set);
238
- }
239
-
240
- const map = this.#reexportCache.get(fileNPath);
241
- if (map) {
242
- for (const [key, val] of map) {
243
- if (val === 0) {
244
- result.adds(...this.#getExportSymbols(key));
245
- }
246
- else {
247
- result.adds(...val.map(item => item.exportSymbol));
277
+ for (const path of this.#getRelatedNPaths(fileNPath)) {
278
+ const set = this._exportCache.get(path);
279
+ if (set) result.adds(...set);
280
+
281
+ const map = this._reexportCache.get(path);
282
+ if (map) {
283
+ for (const [key, val] of map) {
284
+ if (val === 0) {
285
+ result.adds(...this.#getExportSymbols(key));
286
+ } else {
287
+ result.adds(...val.map(item => item.exportSymbol));
288
+ }
248
289
  }
249
290
  }
250
291
  }
@@ -252,32 +293,30 @@ export class SdDependencyCache {
252
293
  return result;
253
294
  }
254
295
 
255
- // ---
256
-
296
+ /**
297
+ * 변경된 파일로부터 영향을 받는 전체 트리를 반환
298
+ * - 의존 관계를 시각화 및 구조적으로 추적할 수 있도록 트리 형태로 구성
299
+ */
257
300
  getAffectedFileTree(modifiedNPathSet: Set<TNormPath>): ISdAffectedFileTreeNode[] {
258
- const visited = new Set<string>(); // 순환 방지용: file#symbol
259
- const nodeMap = new Map<string, ISdAffectedFileTreeNode>(); // 중복 노드 캐시
301
+ const visited = new Set<string>();
302
+ const nodeMap = new Map<string, ISdAffectedFileTreeNode>();
260
303
 
261
304
  const buildTree = (
262
305
  fileNPath: TNormPath,
263
- exportSymbol: string | undefined
306
+ exportSymbol: string | undefined,
264
307
  ): ISdAffectedFileTreeNode => {
265
308
  const key = `${fileNPath}#${exportSymbol ?? "*"}`;
266
-
267
- // 동일 노드가 이미 만들어졌다면 재사용
268
309
  if (nodeMap.has(key)) return nodeMap.get(key)!;
269
310
 
270
- // 방문 기록
271
311
  visited.add(key);
272
312
 
273
- // 노드 생성 및 캐싱
274
313
  const node: ISdAffectedFileTreeNode = {
275
314
  fileNPath,
276
- children: []
315
+ children: [],
277
316
  };
278
317
  nodeMap.set(key, node);
279
318
 
280
- const revDepInfoMap = this.#revDepCache.get(fileNPath);
319
+ const revDepInfoMap = this._revDepCache.get(fileNPath);
281
320
  if (!revDepInfoMap) return node;
282
321
 
283
322
  for (const [revDepFileNPath, revDepInfo] of revDepInfoMap.entries()) {
@@ -285,16 +324,13 @@ export class SdDependencyCache {
285
324
  exportSymbol == null || revDepInfo === 0 || revDepInfo.has(exportSymbol);
286
325
  if (!hasImportSymbol) continue;
287
326
 
288
- const nextExportSymbol = exportSymbol != null
289
- ? this.#convertImportSymbolToExportSymbol(
290
- revDepFileNPath,
291
- fileNPath,
292
- exportSymbol
293
- )
294
- : undefined;
327
+ const nextExportSymbol =
328
+ exportSymbol != null
329
+ ? this.#convertImportSymbolToExportSymbol(revDepFileNPath, fileNPath, exportSymbol)
330
+ : undefined;
295
331
 
296
332
  const childKey = `${revDepFileNPath}#${nextExportSymbol ?? "*"}`;
297
- if (visited.has(childKey)) continue; // 순환 방지
333
+ if (visited.has(childKey)) continue;
298
334
 
299
335
  const childNode = buildTree(revDepFileNPath, nextExportSymbol);
300
336
  node.children.push(childNode);
@@ -306,15 +342,16 @@ export class SdDependencyCache {
306
342
  const result: ISdAffectedFileTreeNode[] = [];
307
343
 
308
344
  for (const modifiedNPath of modifiedNPathSet) {
309
- const exportSymbols = this.#getExportSymbols(modifiedNPath);
310
- if (exportSymbols.size === 0) {
311
- const rootNode = buildTree(modifiedNPath, undefined);
312
- result.push(rootNode);
313
- } else {
314
- for (const symbol of exportSymbols) {
315
- const rootNode = buildTree(modifiedNPath, symbol);
316
- result.push(rootNode);
317
- }
345
+ for (const path of this.#getRelatedNPaths(modifiedNPath)) {
346
+ result.push(buildTree(path, undefined)); // root는 symbol상관없이
347
+ /*const exportSymbols = this.#getExportSymbols(path);
348
+ if (exportSymbols.size === 0) {
349
+ result.push(buildTree(path, undefined));
350
+ } else {
351
+ for (const symbol of exportSymbols) {
352
+ result.push(buildTree(path, symbol));
353
+ }
354
+ }*/
318
355
  }
319
356
  }
320
357
 
@@ -325,4 +362,4 @@ export class SdDependencyCache {
325
362
  export interface ISdAffectedFileTreeNode {
326
363
  fileNPath: TNormPath;
327
364
  children: ISdAffectedFileTreeNode[];
328
- }
365
+ }
@@ -141,4 +141,16 @@ describe("SdDependencyCache", () => {
141
141
 
142
142
  console.log(printTree(trees[0]));
143
143
  });
144
+
145
+ it("d.ts를 입력하면 js도 함께 영향을 받는다", () => {
146
+ const dts = PathUtils.norm("/mod.d.ts");
147
+ const js = PathUtils.norm("/mod.js");
148
+ const consumer = PathUtils.norm("/consumer.ts");
149
+
150
+ depCache.addExport(dts, "Foo");
151
+ depCache.addImport(consumer, js, "Foo"); // js 경로로 import
152
+
153
+ const result = depCache.getAffectedFileSet(new Set([dts]));
154
+ expect(result).toEqual(new Set([dts, js, consumer]));
155
+ });
144
156
  });