@simplysm/sd-cli 12.13.13 → 12.13.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/entry/sd-cli-electron.js +1 -1
- package/dist/entry/sd-cli-electron.js.map +1 -1
- package/dist/entry/sd-cli-project.d.ts +2 -0
- package/dist/entry/sd-cli-project.js +11 -3
- package/dist/entry/sd-cli-project.js.map +1 -1
- package/dist/pkg-builders/client/sd-client.build-runner.d.ts +1 -1
- package/dist/pkg-builders/client/sd-client.build-runner.js +74 -50
- package/dist/pkg-builders/client/sd-client.build-runner.js.map +1 -1
- package/dist/pkg-builders/client/sd-ng.bundler.d.ts +2 -0
- package/dist/pkg-builders/client/sd-ng.bundler.js +19 -20
- package/dist/pkg-builders/client/sd-ng.bundler.js.map +1 -1
- package/dist/pkg-builders/client/sd-ng.plugin-creator.d.ts +2 -0
- package/dist/pkg-builders/client/sd-ng.plugin-creator.js +94 -33
- package/dist/pkg-builders/client/sd-ng.plugin-creator.js.map +1 -1
- package/dist/pkg-builders/commons/build-runner.base.d.ts +4 -2
- package/dist/pkg-builders/commons/build-runner.base.js +45 -25
- package/dist/pkg-builders/commons/build-runner.base.js.map +1 -1
- package/dist/pkg-builders/lib/sd-js-lib.build-runner.d.ts +1 -1
- package/dist/pkg-builders/lib/sd-js-lib.build-runner.js +14 -4
- package/dist/pkg-builders/lib/sd-js-lib.build-runner.js.map +1 -1
- package/dist/pkg-builders/lib/sd-ts-lib.build-runner.d.ts +1 -1
- package/dist/pkg-builders/lib/sd-ts-lib.build-runner.js +21 -40
- package/dist/pkg-builders/lib/sd-ts-lib.build-runner.js.map +1 -1
- package/dist/pkg-builders/lib/sd-ts-lib.builder.d.ts +1 -1
- package/dist/pkg-builders/lib/sd-ts-lib.builder.js +3 -1
- package/dist/pkg-builders/lib/sd-ts-lib.builder.js.map +1 -1
- package/dist/pkg-builders/sd-multi.build-runner.js +116 -86
- package/dist/pkg-builders/sd-multi.build-runner.js.map +1 -1
- package/dist/pkg-builders/server/sd-server.build-runner.d.ts +1 -1
- package/dist/pkg-builders/server/sd-server.build-runner.js +9 -5
- package/dist/pkg-builders/server/sd-server.build-runner.js.map +1 -1
- package/dist/pkg-builders/server/sd-server.bundler.d.ts +2 -0
- package/dist/pkg-builders/server/sd-server.bundler.js +3 -1
- package/dist/pkg-builders/server/sd-server.bundler.js.map +1 -1
- package/dist/pkg-builders/server/sd-server.plugin-creator.d.ts +2 -0
- package/dist/pkg-builders/server/sd-server.plugin-creator.js +4 -1
- package/dist/pkg-builders/server/sd-server.plugin-creator.js.map +1 -1
- package/dist/sd-cli-entry.js +10 -0
- package/dist/sd-cli-entry.js.map +1 -1
- package/dist/sd-cli.js +8 -6
- package/dist/sd-cli.js.map +1 -1
- package/dist/ts-compiler/sd-dependency-analyzer.d.ts +8 -1
- package/dist/ts-compiler/sd-dependency-analyzer.js +128 -63
- package/dist/ts-compiler/sd-dependency-analyzer.js.map +1 -1
- package/dist/ts-compiler/sd-dependency-cache.d.ts +0 -34
- package/dist/ts-compiler/sd-dependency-cache.js +73 -119
- package/dist/ts-compiler/sd-dependency-cache.js.map +1 -1
- package/dist/ts-compiler/sd-style-bundler.d.ts +16 -0
- package/dist/ts-compiler/sd-style-bundler.js +118 -0
- package/dist/ts-compiler/sd-style-bundler.js.map +1 -0
- package/dist/ts-compiler/sd-ts-compiler.js +418 -235
- package/dist/ts-compiler/sd-ts-compiler.js.map +1 -1
- package/dist/types/build-runner.types.d.ts +2 -0
- package/dist/types/config.types.d.ts +2 -0
- package/dist/types/ts-compiler.types.d.ts +2 -0
- package/dist/types/worker.types.d.ts +1 -1
- package/dist/workers/build-runner.worker.js +1 -1
- package/dist/workers/build-runner.worker.js.map +1 -1
- package/dist/workers/server.worker.js +2 -2
- package/dist/workers/server.worker.js.map +1 -1
- package/package.json +13 -12
- package/src/entry/sd-cli-electron.ts +2 -1
- package/src/entry/sd-cli-project.ts +13 -3
- package/src/pkg-builders/client/sd-client.build-runner.ts +93 -54
- package/src/pkg-builders/client/sd-ng.bundler.ts +79 -85
- package/src/pkg-builders/client/sd-ng.plugin-creator.ts +119 -39
- package/src/pkg-builders/commons/build-runner.base.ts +78 -33
- package/src/pkg-builders/lib/sd-js-lib.build-runner.ts +24 -7
- package/src/pkg-builders/lib/sd-ts-lib.build-runner.ts +36 -42
- package/src/pkg-builders/lib/sd-ts-lib.builder.ts +4 -0
- package/src/pkg-builders/sd-multi.build-runner.ts +137 -108
- package/src/pkg-builders/server/sd-server.build-runner.ts +10 -4
- package/src/pkg-builders/server/sd-server.bundler.ts +5 -1
- package/src/pkg-builders/server/sd-server.plugin-creator.ts +10 -5
- package/src/sd-cli-entry.ts +10 -0
- package/src/sd-cli.ts +8 -6
- package/src/ts-compiler/sd-dependency-analyzer.ts +161 -86
- package/src/ts-compiler/sd-dependency-cache.ts +118 -99
- package/src/ts-compiler/sd-style-bundler.ts +150 -0
- package/src/ts-compiler/sd-ts-compiler.ts +559 -296
- package/src/types/build-runner.types.ts +2 -0
- package/src/types/config.types.ts +3 -0
- package/src/types/ts-compiler.types.ts +15 -11
- package/src/types/worker.types.ts +7 -10
- package/src/workers/build-runner.worker.ts +9 -5
- package/src/workers/server.worker.ts +2 -2
- package/tests/deps/sd-dependency-cache.spec.ts +1 -1
|
@@ -4,14 +4,14 @@ export class SdDependencyCache {
|
|
|
4
4
|
/**
|
|
5
5
|
* 각 파일이 export한 심볼 집합 (예: export const A → "A")
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
#exportCache = new Map<TNormPath, Set<string>>();
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* import한 타겟과 그 심볼 정보
|
|
11
11
|
* - 값이 0이면 전체 import(import * 또는 리소스 import)
|
|
12
12
|
* - 값이 Set이면 선택적 심볼 import (예: import { A } ...)
|
|
13
13
|
*/
|
|
14
|
-
|
|
14
|
+
#importCache = new Map<TNormPath, Map<TNormPath, Set<string> | 0>>();
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* re-export한 타겟과 그 심볼 정보
|
|
@@ -19,7 +19,7 @@ export class SdDependencyCache {
|
|
|
19
19
|
* - export { A as B } from ...
|
|
20
20
|
* - 값이 0이면 전체 reexport(export * from ...)
|
|
21
21
|
*/
|
|
22
|
-
|
|
22
|
+
#reexportCache = new Map<
|
|
23
23
|
TNormPath,
|
|
24
24
|
Map<
|
|
25
25
|
TNormPath,
|
|
@@ -36,14 +36,14 @@ export class SdDependencyCache {
|
|
|
36
36
|
* - 특정 파일이 어떤 파일에게 의존(참조)되는지
|
|
37
37
|
* - symbol 기반 추적
|
|
38
38
|
*/
|
|
39
|
-
|
|
39
|
+
#revDepCache = new Map<TNormPath, Map<TNormPath, Set<string> | 0>>();
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* 분석이 완료된 파일 경로
|
|
43
43
|
*/
|
|
44
|
-
|
|
44
|
+
#collectedCache = new Set<TNormPath>();
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
#exportSymbolCache = new Map<TNormPath, Set<string>>();
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
49
|
* .d.ts 또는 .js가 입력되었을 때 쌍으로 존재하는 파일 경로를 반환
|
|
@@ -62,21 +62,21 @@ export class SdDependencyCache {
|
|
|
62
62
|
/**
|
|
63
63
|
* 전체 추적된 파일 경로를 반환
|
|
64
64
|
*/
|
|
65
|
-
getFiles(): Set<TNormPath> {
|
|
66
|
-
|
|
67
|
-
}
|
|
65
|
+
// getFiles(): Set<TNormPath> {
|
|
66
|
+
// return new Set<TNormPath>([...this.#collectedCache.keys(), ...this.revDepCache.keys()]);
|
|
67
|
+
// }
|
|
68
68
|
|
|
69
69
|
/**
|
|
70
70
|
* 분석이 완료된 파일로 표시
|
|
71
71
|
*/
|
|
72
72
|
addCollected(fileNPath: TNormPath) {
|
|
73
73
|
for (const path of this.#getRelatedNPaths(fileNPath)) {
|
|
74
|
-
this.
|
|
74
|
+
this.#collectedCache.add(path);
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
hasCollected(fileNPath: TNormPath) {
|
|
79
|
-
return this.
|
|
79
|
+
return this.#collectedCache.has(fileNPath);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
/**
|
|
@@ -85,7 +85,7 @@ export class SdDependencyCache {
|
|
|
85
85
|
*/
|
|
86
86
|
addExport(fileNPath: TNormPath, exportSymbol: string) {
|
|
87
87
|
for (const path of this.#getRelatedNPaths(fileNPath)) {
|
|
88
|
-
const exportSymbolSet = this.
|
|
88
|
+
const exportSymbolSet = this.#exportCache.getOrCreate(path, new Set());
|
|
89
89
|
exportSymbolSet.add(exportSymbol);
|
|
90
90
|
}
|
|
91
91
|
}
|
|
@@ -97,18 +97,18 @@ export class SdDependencyCache {
|
|
|
97
97
|
*/
|
|
98
98
|
addImport(fileNPath: TNormPath, targetNPath: TNormPath, targetSymbol: string | 0) {
|
|
99
99
|
for (const filePath of this.#getRelatedNPaths(fileNPath)) {
|
|
100
|
-
|
|
101
|
-
const importTargetMap = this._importCache.getOrCreate(filePath, new Map());
|
|
100
|
+
const importTargetMap = this.#importCache.getOrCreate(filePath, new Map());
|
|
102
101
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
this.#addRevDep(targetPath, filePath, 0);
|
|
106
|
-
} else {
|
|
102
|
+
for (const targetPath of this.#getRelatedNPaths(targetNPath)) {
|
|
103
|
+
if (typeof targetSymbol === "string") {
|
|
107
104
|
const importTargetSymbolSet = importTargetMap.getOrCreate(targetPath, new Set());
|
|
108
|
-
if (importTargetSymbolSet
|
|
105
|
+
if (!(importTargetSymbolSet instanceof Set)) continue;
|
|
109
106
|
|
|
110
107
|
importTargetSymbolSet.add(targetSymbol);
|
|
111
108
|
this.#addRevDep(targetPath, filePath, targetSymbol);
|
|
109
|
+
} else {
|
|
110
|
+
importTargetMap.set(targetPath, targetSymbol);
|
|
111
|
+
this.#addRevDep(targetPath, filePath, targetSymbol);
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
}
|
|
@@ -129,9 +129,9 @@ export class SdDependencyCache {
|
|
|
129
129
|
| 0,
|
|
130
130
|
) {
|
|
131
131
|
for (const filePath of this.#getRelatedNPaths(fileNPath)) {
|
|
132
|
-
|
|
133
|
-
const reexportTargetMap = this._reexportCache.getOrCreate(filePath, new Map());
|
|
132
|
+
const reexportTargetMap = this.#reexportCache.getOrCreate(filePath, new Map());
|
|
134
133
|
|
|
134
|
+
for (const targetPath of this.#getRelatedNPaths(targetNPath)) {
|
|
135
135
|
if (targetSymbolInfo === 0) {
|
|
136
136
|
reexportTargetMap.set(targetPath, 0);
|
|
137
137
|
this.#addRevDep(targetPath, filePath, 0);
|
|
@@ -159,15 +159,16 @@ export class SdDependencyCache {
|
|
|
159
159
|
*/
|
|
160
160
|
#addRevDep(targetNPath: TNormPath, fileNPath: TNormPath, exportSymbol: string | 0) {
|
|
161
161
|
for (const targetPath of this.#getRelatedNPaths(targetNPath)) {
|
|
162
|
+
const revDepInfoMap = this.#revDepCache.getOrCreate(targetPath, new Map());
|
|
163
|
+
|
|
162
164
|
for (const filePath of this.#getRelatedNPaths(fileNPath)) {
|
|
163
|
-
|
|
164
|
-
if (exportSymbol === 0) {
|
|
165
|
-
revDepInfoMap.set(filePath, 0);
|
|
166
|
-
} else {
|
|
165
|
+
if (typeof exportSymbol === "string") {
|
|
167
166
|
const exportSymbolSet = revDepInfoMap.getOrCreate(filePath, new Set());
|
|
168
|
-
if (exportSymbolSet
|
|
167
|
+
if (!(exportSymbolSet instanceof Set)) continue;
|
|
169
168
|
|
|
170
169
|
exportSymbolSet.add(exportSymbol);
|
|
170
|
+
} else {
|
|
171
|
+
revDepInfoMap.set(filePath, exportSymbol);
|
|
171
172
|
}
|
|
172
173
|
}
|
|
173
174
|
}
|
|
@@ -229,6 +230,7 @@ export class SdDependencyCache {
|
|
|
229
230
|
|
|
230
231
|
return result;
|
|
231
232
|
}*/
|
|
233
|
+
|
|
232
234
|
getAffectedFileMap(modifiedNPathSet: Set<TNormPath>): Map<TNormPath, Set<TNormPath>> {
|
|
233
235
|
const resultMap = new Map<TNormPath, Set<TNormPath>>();
|
|
234
236
|
|
|
@@ -259,7 +261,7 @@ export class SdDependencyCache {
|
|
|
259
261
|
|
|
260
262
|
while (queue.length > 0) {
|
|
261
263
|
const curr = queue.shift()!;
|
|
262
|
-
const revDepInfoMap = this.
|
|
264
|
+
const revDepInfoMap = this.#revDepCache.get(curr.fileNPath);
|
|
263
265
|
if (!revDepInfoMap) continue;
|
|
264
266
|
|
|
265
267
|
for (const [revDepFileNPath, revDepInfo] of revDepInfoMap) {
|
|
@@ -292,21 +294,30 @@ export class SdDependencyCache {
|
|
|
292
294
|
invalidates(fileNPathSet: Set<TNormPath>) {
|
|
293
295
|
// const affectedFileMap = this.getAffectedFileMap(fileNPathSet);
|
|
294
296
|
|
|
297
|
+
const revDepCacheChanged = new Set<TNormPath>();
|
|
298
|
+
|
|
295
299
|
for (const fileNPath of fileNPathSet) {
|
|
296
|
-
this.
|
|
297
|
-
this.
|
|
298
|
-
this.
|
|
299
|
-
this.
|
|
300
|
-
this.
|
|
301
|
-
|
|
300
|
+
this.#exportCache.delete(fileNPath);
|
|
301
|
+
this.#importCache.delete(fileNPath);
|
|
302
|
+
this.#reexportCache.delete(fileNPath);
|
|
303
|
+
this.#exportSymbolCache.delete(fileNPath);
|
|
304
|
+
this.#collectedCache.delete(fileNPath);
|
|
305
|
+
|
|
306
|
+
if (this.#revDepCache.has(fileNPath)) {
|
|
307
|
+
this.#revDepCache.delete(fileNPath); // 자신이 key인 경우
|
|
308
|
+
revDepCacheChanged.add(fileNPath);
|
|
309
|
+
}
|
|
302
310
|
}
|
|
303
311
|
|
|
304
|
-
for (const [targetNPath, infoMap] of this
|
|
312
|
+
for (const [targetNPath, infoMap] of this.#revDepCache) {
|
|
305
313
|
for (const fileNPath of fileNPathSet) {
|
|
306
|
-
infoMap.
|
|
314
|
+
if (infoMap.has(fileNPath)) {
|
|
315
|
+
infoMap.delete(fileNPath);
|
|
316
|
+
revDepCacheChanged.add(targetNPath);
|
|
317
|
+
}
|
|
307
318
|
}
|
|
308
319
|
if (infoMap.size === 0) {
|
|
309
|
-
this.
|
|
320
|
+
this.#revDepCache.delete(targetNPath);
|
|
310
321
|
}
|
|
311
322
|
}
|
|
312
323
|
}
|
|
@@ -314,8 +325,12 @@ export class SdDependencyCache {
|
|
|
314
325
|
/**
|
|
315
326
|
* reexport된 경우 importSymbol → exportSymbol로 변환
|
|
316
327
|
*/
|
|
317
|
-
#convertImportSymbolToExportSymbol(
|
|
318
|
-
|
|
328
|
+
#convertImportSymbolToExportSymbol(
|
|
329
|
+
fileNPath: TNormPath,
|
|
330
|
+
targetNPath: TNormPath,
|
|
331
|
+
importSymbol: string,
|
|
332
|
+
) {
|
|
333
|
+
const symbolInfos = this.#reexportCache.get(fileNPath)?.get(targetNPath);
|
|
319
334
|
if (symbolInfos != null && symbolInfos !== 0 && symbolInfos.length > 0) {
|
|
320
335
|
const symbolInfo = symbolInfos.single((item) => item.importSymbol === importSymbol);
|
|
321
336
|
if (symbolInfo) return symbolInfo.exportSymbol;
|
|
@@ -327,17 +342,17 @@ export class SdDependencyCache {
|
|
|
327
342
|
* 해당 파일에서 export된 모든 심볼 (직접 + 재export 포함)
|
|
328
343
|
*/
|
|
329
344
|
#getExportSymbols(fileNPath: TNormPath): Set<string> {
|
|
330
|
-
if (this.
|
|
331
|
-
return this.
|
|
345
|
+
if (this.#exportSymbolCache.has(fileNPath)) {
|
|
346
|
+
return this.#exportSymbolCache.get(fileNPath)!;
|
|
332
347
|
}
|
|
333
348
|
|
|
334
349
|
const result = new Set<string>();
|
|
335
350
|
|
|
336
351
|
for (const path of this.#getRelatedNPaths(fileNPath)) {
|
|
337
|
-
const set = this.
|
|
352
|
+
const set = this.#exportCache.get(path);
|
|
338
353
|
if (set) result.adds(...set);
|
|
339
354
|
|
|
340
|
-
const map = this.
|
|
355
|
+
const map = this.#reexportCache.get(path);
|
|
341
356
|
if (map) {
|
|
342
357
|
for (const [key, val] of map) {
|
|
343
358
|
if (val === 0) {
|
|
@@ -349,7 +364,7 @@ export class SdDependencyCache {
|
|
|
349
364
|
}
|
|
350
365
|
}
|
|
351
366
|
|
|
352
|
-
this.
|
|
367
|
+
this.#exportSymbolCache.set(fileNPath, result);
|
|
353
368
|
return result;
|
|
354
369
|
}
|
|
355
370
|
|
|
@@ -357,62 +372,66 @@ export class SdDependencyCache {
|
|
|
357
372
|
* 변경된 파일로부터 영향을 받는 전체 트리를 반환
|
|
358
373
|
* - 의존 관계를 시각화 및 구조적으로 추적할 수 있도록 트리 형태로 구성
|
|
359
374
|
*/
|
|
360
|
-
getAffectedFileTree(modifiedNPathSet: Set<TNormPath>): ISdAffectedFileTreeNode[] {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
}
|
|
375
|
+
// getAffectedFileTree(modifiedNPathSet: Set<TNormPath>): ISdAffectedFileTreeNode[] {
|
|
376
|
+
// const visited = new Set<string>();
|
|
377
|
+
// const nodeMap = new Map<string, ISdAffectedFileTreeNode>();
|
|
378
|
+
//
|
|
379
|
+
// const buildTree = (
|
|
380
|
+
// fileNPath: TNormPath,
|
|
381
|
+
// exportSymbol: string | undefined,
|
|
382
|
+
// ): ISdAffectedFileTreeNode => {
|
|
383
|
+
// const key = `${fileNPath}#${exportSymbol ?? "*"}`;
|
|
384
|
+
// if (nodeMap.has(key)) return nodeMap.get(key)!;
|
|
385
|
+
//
|
|
386
|
+
// visited.add(key);
|
|
387
|
+
//
|
|
388
|
+
// const node: ISdAffectedFileTreeNode = {
|
|
389
|
+
// fileNPath,
|
|
390
|
+
// children: [],
|
|
391
|
+
// };
|
|
392
|
+
// nodeMap.set(key, node);
|
|
393
|
+
//
|
|
394
|
+
// const revDepInfoMap = this.revDepCache.get(fileNPath);
|
|
395
|
+
// if (!revDepInfoMap) return node;
|
|
396
|
+
//
|
|
397
|
+
// for (const [revDepFileNPath, revDepInfo] of revDepInfoMap.entries()) {
|
|
398
|
+
// const hasImportSymbol =
|
|
399
|
+
// exportSymbol == null || revDepInfo === 0 || revDepInfo.has(exportSymbol);
|
|
400
|
+
// if (!hasImportSymbol) continue;
|
|
401
|
+
//
|
|
402
|
+
// const nextExportSymbol =
|
|
403
|
+
// exportSymbol != null
|
|
404
|
+
// ? this.#convertImportSymbolToExportSymbol(revDepFileNPath, fileNPath, exportSymbol)
|
|
405
|
+
// : undefined;
|
|
406
|
+
//
|
|
407
|
+
// const childKey = `${revDepFileNPath}#${nextExportSymbol ?? "*"}`;
|
|
408
|
+
// if (visited.has(childKey)) continue;
|
|
409
|
+
//
|
|
410
|
+
// const childNode = buildTree(revDepFileNPath, nextExportSymbol);
|
|
411
|
+
// node.children.push(childNode);
|
|
412
|
+
// }
|
|
413
|
+
//
|
|
414
|
+
// return node;
|
|
415
|
+
// };
|
|
416
|
+
//
|
|
417
|
+
// const result: ISdAffectedFileTreeNode[] = [];
|
|
418
|
+
//
|
|
419
|
+
// for (const modifiedNPath of modifiedNPathSet) {
|
|
420
|
+
// for (const path of this.#getRelatedNPaths(modifiedNPath)) {
|
|
421
|
+
// result.push(buildTree(path, undefined)); // root는 symbol상관없이
|
|
422
|
+
// /*const exportSymbols = this.#getExportSymbols(path);
|
|
423
|
+
// if (exportSymbols.size === 0) {
|
|
424
|
+
// result.push(buildTree(path, undefined));
|
|
425
|
+
// } else {
|
|
426
|
+
// for (const symbol of exportSymbols) {
|
|
427
|
+
// result.push(buildTree(path, symbol));
|
|
428
|
+
// }
|
|
429
|
+
// }*/
|
|
430
|
+
// }
|
|
431
|
+
// }
|
|
432
|
+
//
|
|
433
|
+
// return result;
|
|
434
|
+
// }
|
|
416
435
|
}
|
|
417
436
|
|
|
418
437
|
export interface ISdAffectedFileTreeNode {
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { PathUtils, TNormPath } from "@simplysm/sd-core-node";
|
|
2
|
+
import { TStylesheetBundlingResult } from "../types/ts-compiler.types";
|
|
3
|
+
import { ComponentStylesheetBundler } from "@angular/build/src/tools/esbuild/angular/component-stylesheets";
|
|
4
|
+
import { transformSupportedBrowsersToTargets } from "@angular/build/src/tools/esbuild/utils";
|
|
5
|
+
import browserslist from "browserslist";
|
|
6
|
+
import { ScopePathSet } from "../pkg-builders/commons/scope-path";
|
|
7
|
+
|
|
8
|
+
export class SdStyleBundler {
|
|
9
|
+
#ngStyleBundler: ComponentStylesheetBundler;
|
|
10
|
+
#resultCache = new Map<TNormPath, TStylesheetBundlingResult>();
|
|
11
|
+
#refCache = new Map<TNormPath, Set<TNormPath>>();
|
|
12
|
+
#revRefCache = new Map<TNormPath, Set<TNormPath>>();
|
|
13
|
+
|
|
14
|
+
constructor(
|
|
15
|
+
private readonly _pkgPath: TNormPath,
|
|
16
|
+
private readonly _isDevMode: boolean,
|
|
17
|
+
private readonly _watchScopePathSet: ScopePathSet,
|
|
18
|
+
) {
|
|
19
|
+
this.#ngStyleBundler = new ComponentStylesheetBundler(
|
|
20
|
+
{
|
|
21
|
+
workspaceRoot: this._pkgPath,
|
|
22
|
+
optimization: !this._isDevMode,
|
|
23
|
+
inlineFonts: true,
|
|
24
|
+
preserveSymlinks: false,
|
|
25
|
+
sourcemap: this._isDevMode ? "inline" : false,
|
|
26
|
+
outputNames: { bundles: "[name]", media: "media/[name]" },
|
|
27
|
+
includePaths: [],
|
|
28
|
+
externalDependencies: [],
|
|
29
|
+
target: transformSupportedBrowsersToTargets(browserslist(["Chrome > 78"])),
|
|
30
|
+
tailwindConfiguration: undefined,
|
|
31
|
+
cacheOptions: {
|
|
32
|
+
enabled: true,
|
|
33
|
+
path: ".cache/angular",
|
|
34
|
+
basePath: ".cache",
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
"scss",
|
|
38
|
+
this._isDevMode,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
getResultCache() {
|
|
43
|
+
return this.#resultCache;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async bundleAsync(
|
|
47
|
+
data: string,
|
|
48
|
+
containingFile: TNormPath,
|
|
49
|
+
resourceFile: TNormPath | null = null,
|
|
50
|
+
): Promise<TStylesheetBundlingResult & { cached: boolean }> {
|
|
51
|
+
// containingFile: 포함된 파일 (.ts 혹은 global style.scss)
|
|
52
|
+
// resourceFile: 외부 리소스 파일 (styleUrls로 입력하지 않고 styles에 직접 입력한 경우 null)
|
|
53
|
+
// referencedFiles: import한 외부 scss 파일 혹은 woff파일등 외부 파일
|
|
54
|
+
|
|
55
|
+
const fileNPath = PathUtils.norm(resourceFile ?? containingFile);
|
|
56
|
+
if (this.#resultCache.has(fileNPath)) {
|
|
57
|
+
return {
|
|
58
|
+
...this.#resultCache.get(fileNPath)!,
|
|
59
|
+
cached: true,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
const result =
|
|
65
|
+
resourceFile != null
|
|
66
|
+
? await this.#ngStyleBundler.bundleFile(resourceFile)
|
|
67
|
+
: await this.#ngStyleBundler.bundleInline(data, containingFile, "scss");
|
|
68
|
+
|
|
69
|
+
for (const referencedFile of result.referencedFiles ?? []) {
|
|
70
|
+
if (
|
|
71
|
+
!this._watchScopePathSet.inScope(fileNPath) ||
|
|
72
|
+
!this._watchScopePathSet.inScope(PathUtils.norm(referencedFile))
|
|
73
|
+
)
|
|
74
|
+
continue;
|
|
75
|
+
|
|
76
|
+
// 참조하는 파일과 참조된 파일 사이의 의존성 관계 추가
|
|
77
|
+
this.#addReference(fileNPath, PathUtils.norm(referencedFile));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
this.#resultCache.set(fileNPath, result);
|
|
81
|
+
|
|
82
|
+
return { ...result, cached: false };
|
|
83
|
+
} catch (err) {
|
|
84
|
+
const result = {
|
|
85
|
+
errors: [
|
|
86
|
+
{
|
|
87
|
+
text: `스타일 번들링 실패: ${err.message ?? "알 수 없는 오류"}`,
|
|
88
|
+
location: { file: containingFile },
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
warnings: [],
|
|
92
|
+
};
|
|
93
|
+
this.#resultCache.set(fileNPath, result);
|
|
94
|
+
return { ...result, cached: false };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
invalidate(modifiedNPathSet: Set<TNormPath>) {
|
|
99
|
+
const affectedFileSet = this.getAffectedFileSet(modifiedNPathSet);
|
|
100
|
+
|
|
101
|
+
this.#ngStyleBundler.invalidate(affectedFileSet);
|
|
102
|
+
for (const fileNPath of affectedFileSet) {
|
|
103
|
+
this.#resultCache.delete(fileNPath);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// revRefCache/refCache
|
|
107
|
+
const targetSet = new Set<TNormPath>();
|
|
108
|
+
for (const fileNPath of affectedFileSet) {
|
|
109
|
+
targetSet.adds(...(this.#refCache.get(fileNPath) ?? []));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
for (const target of [...targetSet]) {
|
|
113
|
+
const source = this.#revRefCache.get(target);
|
|
114
|
+
if (source == null) continue;
|
|
115
|
+
|
|
116
|
+
for (const affectedFile of affectedFileSet) {
|
|
117
|
+
source.delete(affectedFile);
|
|
118
|
+
}
|
|
119
|
+
if (source.size === 0) {
|
|
120
|
+
this.#revRefCache.delete(target);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
this.#refCache.delete(target);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return affectedFileSet;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
#addReference(fileNPath: TNormPath, referencedFile: TNormPath) {
|
|
130
|
+
this.#refCache.getOrCreate(fileNPath, new Set()).add(referencedFile);
|
|
131
|
+
this.#revRefCache.getOrCreate(referencedFile, new Set()).add(fileNPath);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
getAffectedFileSet(modifiedNPathSet: Set<TNormPath>) {
|
|
135
|
+
const affectedFileSet = new Set<TNormPath>();
|
|
136
|
+
// 수정파일중 Result에 있는것
|
|
137
|
+
const modifiedResultFiles = Array.from(modifiedNPathSet)
|
|
138
|
+
// .filter((item) => item.endsWith(".scss"))
|
|
139
|
+
.filter((item) => this.#resultCache.has(item));
|
|
140
|
+
affectedFileSet.adds(...modifiedResultFiles);
|
|
141
|
+
|
|
142
|
+
// 수정파일을 사용하는 파일
|
|
143
|
+
const modifiedScssFiles = Array.from(modifiedNPathSet).filter((item) => item.endsWith(".scss"));
|
|
144
|
+
for (const modifiedScss of modifiedScssFiles) {
|
|
145
|
+
affectedFileSet.adds(...(this.#revRefCache.get(modifiedScss) ?? []));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return affectedFileSet;
|
|
149
|
+
}
|
|
150
|
+
}
|