@simplysm/sd-cli 14.0.44 → 14.0.46
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/deps/server-externals/server-production-files.d.ts +10 -5
- package/dist/deps/server-externals/server-production-files.d.ts.map +1 -1
- package/dist/deps/server-externals/server-production-files.js +27 -29
- package/dist/deps/server-externals/server-production-files.js.map +1 -1
- package/dist/esbuild/esbuild-angular-compiler-plugin.d.ts +3 -8
- package/dist/esbuild/esbuild-angular-compiler-plugin.d.ts.map +1 -1
- package/dist/esbuild/esbuild-angular-compiler-plugin.js +57 -83
- package/dist/esbuild/esbuild-angular-compiler-plugin.js.map +1 -1
- package/dist/esbuild/esbuild-config.d.ts.map +1 -1
- package/dist/esbuild/esbuild-config.js +2 -5
- package/dist/esbuild/esbuild-config.js.map +1 -1
- package/dist/esbuild/esbuild-worker-plugin.d.ts +52 -0
- package/dist/esbuild/esbuild-worker-plugin.d.ts.map +1 -0
- package/dist/esbuild/esbuild-worker-plugin.js +319 -0
- package/dist/esbuild/esbuild-worker-plugin.js.map +1 -0
- package/dist/utils/output-path-rewriter.d.ts +5 -2
- package/dist/utils/output-path-rewriter.d.ts.map +1 -1
- package/dist/utils/output-path-rewriter.js +60 -12
- package/dist/utils/output-path-rewriter.js.map +1 -1
- package/dist/workers/server-build.worker.d.ts.map +1 -1
- package/dist/workers/server-build.worker.js +6 -5
- package/dist/workers/server-build.worker.js.map +1 -1
- package/dist/workers/server-esbuild-context.d.ts.map +1 -1
- package/dist/workers/server-esbuild-context.js +3 -1
- package/dist/workers/server-esbuild-context.js.map +1 -1
- package/dist/workers/server-watch-manager.js +1 -1
- package/dist/workers/server-watch-manager.js.map +1 -1
- package/package.json +7 -4
- package/src/deps/server-externals/server-production-files.ts +31 -31
- package/src/esbuild/esbuild-angular-compiler-plugin.ts +82 -123
- package/src/esbuild/esbuild-config.ts +2 -7
- package/src/esbuild/esbuild-worker-plugin.ts +419 -0
- package/src/utils/output-path-rewriter.ts +65 -17
- package/src/workers/server-build.worker.ts +6 -5
- package/src/workers/server-esbuild-context.ts +3 -1
- package/src/workers/server-watch-manager.ts +1 -1
- package/tests/deps/server-externals/mise-toml-parse-intent.verify.md +16 -0
- package/tests/esbuild/esbuild-angular-compiler-plugin-worker.verify.md +56 -28
- package/tests/esbuild/esbuild-worker-plugin-node.verify.md +11 -0
- package/tests/esbuild/esbuild-worker-plugin.acc.spec.ts +318 -0
- package/tests/esbuild/esbuild-worker-plugin.spec.ts +606 -0
- package/tests/esbuild/esbuild-worker-plugin.verify.md +7 -0
- package/tests/esbuild/fixtures/worker-plugin/node-worker.js +2 -0
- package/tests/esbuild/fixtures/worker-plugin/shared-worker.js +6 -0
- package/tests/esbuild/fixtures/worker-plugin/worker-error.js +1 -0
- package/tests/esbuild/fixtures/worker-plugin/worker.js +3 -0
- package/tests/esbuild/fixtures/worker-plugin/worker2.js +3 -0
- package/tests/workers/server-build-worker-plugin.verify.md +9 -0
- package/tests/workers/server-build-worker.spec.ts +26 -12
- package/tests/workers/server-esbuild-context.spec.ts +13 -5
- package/tests/workers/server-watch-manager.acc.spec.ts +2 -2
- package/tests/workers/server-watch-manager.spec.ts +2 -2
- package/dist/angular/web-worker-transformer.d.ts +0 -9
- package/dist/angular/web-worker-transformer.d.ts.map +0 -1
- package/dist/angular/web-worker-transformer.js +0 -73
- package/dist/angular/web-worker-transformer.js.map +0 -1
- package/src/angular/web-worker-transformer.ts +0 -117
- package/tests/angular/web-worker-transformer.spec.ts +0 -154
|
@@ -27,7 +27,7 @@ export async function startServerWatchLoop(config) {
|
|
|
27
27
|
// package.json이 변경된 경우에만 외부 모듈 재수집
|
|
28
28
|
const hasPackageJsonChange = changes.some((c) => c.path.endsWith("package.json"));
|
|
29
29
|
if (hasPackageJsonChange) {
|
|
30
|
-
cachedExternal = collectAllExternals(info.pkgDir, info.externals);
|
|
30
|
+
cachedExternal = collectAllExternals(info.pkgDir, info.externals).bundleExternals;
|
|
31
31
|
}
|
|
32
32
|
if (info.output.js) {
|
|
33
33
|
await esbuildCtx.recreateContext({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-watch-manager.js","sourceRoot":"","sources":["../../src/workers/server-watch-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,GAAG,IAAI,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAErD,OAAO,EACL,aAAa,EACb,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,mBAAmB,EAAE,MAAM,kDAAkD,CAAC;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,UAAU,MAAM,0BAA0B,CAAC;AAqBvD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,MAA6B;IACtE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC5C,IAAI,cAAc,GAAG,CAAC,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAElD,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAElD,OAAO,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;QACjD,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;YAEhD,IAAI,WAAW,EAAE,CAAC;gBAChB,MAAM,CAAC,YAAY,EAAE,CAAC;gBAEtB,sBAAsB;gBACtB,MAAM,eAAe,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACnD,MAAM,cAAc,GAAG,qBAAqB,CAAC,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;gBAE3E,mCAAmC;gBACnC,MAAM,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAC9C,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAChC,CAAC;gBACF,IAAI,oBAAoB,EAAE,CAAC;oBACzB,cAAc,GAAG,mBAAmB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"server-watch-manager.js","sourceRoot":"","sources":["../../src/workers/server-watch-manager.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplysm/sd-cli",
|
|
3
|
-
"version": "14.0.
|
|
3
|
+
"version": "14.0.46",
|
|
4
4
|
"description": "Simplysm package - CLI tool",
|
|
5
5
|
"author": "simplysm",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"acorn-walk": "^8.3.5",
|
|
28
28
|
"browserslist-to-esbuild": "^2.1.1",
|
|
29
29
|
"consola": "^3.4.2",
|
|
30
|
+
"es-module-lexer": "^2.0.0",
|
|
30
31
|
"esbuild": "^0.28.0",
|
|
31
32
|
"eslint": "^9.39.4",
|
|
32
33
|
"glob": "^13.0.6",
|
|
@@ -37,13 +38,15 @@
|
|
|
37
38
|
"sass": "^1.99.0",
|
|
38
39
|
"semver": "^7.7.4",
|
|
39
40
|
"sharp": "^0.34.5",
|
|
41
|
+
"smol-toml": "^1.6.1",
|
|
40
42
|
"ssh2": "^1.17.0",
|
|
41
43
|
"typescript": "^5.9.3",
|
|
42
44
|
"ws": "^8.20.0",
|
|
45
|
+
"yaml": "^2.8.3",
|
|
43
46
|
"yargs": "^18.0.0",
|
|
44
|
-
"@simplysm/core-common": "14.0.
|
|
45
|
-
"@simplysm/core-node": "14.0.
|
|
46
|
-
"@simplysm/storage": "14.0.
|
|
47
|
+
"@simplysm/core-common": "14.0.46",
|
|
48
|
+
"@simplysm/core-node": "14.0.46",
|
|
49
|
+
"@simplysm/storage": "14.0.46"
|
|
47
50
|
},
|
|
48
51
|
"devDependencies": {
|
|
49
52
|
"@types/semver": "^7.7.1",
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { ServerBuildInfo } from "../../workers/server-build.worker";
|
|
2
2
|
import path from "path";
|
|
3
3
|
import fs from "fs";
|
|
4
|
+
import YAML from "yaml";
|
|
5
|
+
import TOML from "smol-toml";
|
|
4
6
|
import { cpx } from "@simplysm/core-node";
|
|
5
7
|
import { consola } from "consola";
|
|
6
8
|
import { collectAllDependencyExternals } from "../../esbuild/esbuild-config";
|
|
@@ -8,21 +10,29 @@ import { collectAllDependencyExternals } from "../../esbuild/esbuild-config";
|
|
|
8
10
|
const logger = consola.withTag("sd:cli:server-production-files");
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
+
* 외부 모듈을 두 용도로 분리하여 수집한다.
|
|
14
|
+
* - bundleExternals: esbuild external — 번들에서 제외할 패키지
|
|
15
|
+
* - prodDependencies: dist/package.json dependencies — 런타임에 실제 설치되어야 하는 패키지
|
|
16
|
+
*
|
|
17
|
+
* 미설치 optional peer는 번들 제외만 필요할 뿐 런타임에 쓰이지 않으므로 prodDependencies에 포함하지 않는다.
|
|
13
18
|
*/
|
|
14
|
-
export function collectAllExternals(
|
|
19
|
+
export function collectAllExternals(
|
|
20
|
+
pkgDir: string,
|
|
21
|
+
manualExternals?: string[],
|
|
22
|
+
): { bundleExternals: string[]; prodDependencies: string[] } {
|
|
15
23
|
logger.debug("의존성 트리 스캔 중...");
|
|
16
24
|
const { optionalPeerDeps, nativeModules } = collectAllDependencyExternals(pkgDir);
|
|
17
25
|
|
|
18
26
|
const manual = manualExternals ?? [];
|
|
19
|
-
return
|
|
27
|
+
return {
|
|
28
|
+
bundleExternals: [...new Set([...optionalPeerDeps, ...nativeModules, ...manual])],
|
|
29
|
+
prodDependencies: [...new Set([...nativeModules, ...manual])],
|
|
30
|
+
};
|
|
20
31
|
}
|
|
21
32
|
|
|
22
33
|
/**
|
|
23
34
|
* pnpm-lock.yaml의 packages 섹션을 파싱하여 name→version 맵을 생성한다.
|
|
24
|
-
*
|
|
25
|
-
* YAML 파서 의존성을 피하기 위해 단순 라인 기반 파싱을 사용한다.
|
|
35
|
+
* 키 형태: "name@version" · "@scope/name@version" · "name@version(peer@ver)..."
|
|
26
36
|
*/
|
|
27
37
|
export function parseLockfileVersions(cwd: string): Map<string, string> {
|
|
28
38
|
const lockfilePath = path.join(cwd, "pnpm-lock.yaml");
|
|
@@ -31,30 +41,19 @@ export function parseLockfileVersions(cwd: string): Map<string, string> {
|
|
|
31
41
|
}
|
|
32
42
|
|
|
33
43
|
const content = fs.readFileSync(lockfilePath, "utf-8");
|
|
44
|
+
const parsed = YAML.parse(content) as { packages?: Record<string, unknown> };
|
|
34
45
|
const map = new Map<string, string>();
|
|
35
46
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
if (!inPackages) continue;
|
|
48
|
-
|
|
49
|
-
// "'@scope/name@version':" 또는 "'name@version':" 매칭
|
|
50
|
-
const match = /^\s{2}'(.+)@(\d[^']*)':\s*$/.exec(line);
|
|
51
|
-
if (match != null) {
|
|
52
|
-
const name = match[1];
|
|
53
|
-
const version = match[2];
|
|
54
|
-
// 첫 번째 항목 유지 (lockfile은 각 버전을 한 번만 기록)
|
|
55
|
-
if (!map.has(name)) {
|
|
56
|
-
map.set(name, version);
|
|
57
|
-
}
|
|
47
|
+
for (const key of Object.keys(parsed.packages ?? {})) {
|
|
48
|
+
// 첫 번째 @숫자 기준으로 name / version 분리 (scope 패키지의 선두 @ 보존)
|
|
49
|
+
const m = /^(.+?)@(\d.+)$/.exec(key);
|
|
50
|
+
if (m == null) continue;
|
|
51
|
+
const name = m[1];
|
|
52
|
+
// peerDep suffix "(peer@ver)..." 제거
|
|
53
|
+
const parenIdx = m[2].indexOf("(");
|
|
54
|
+
const version = parenIdx === -1 ? m[2] : m[2].substring(0, parenIdx);
|
|
55
|
+
if (!map.has(name)) {
|
|
56
|
+
map.set(name, version);
|
|
58
57
|
}
|
|
59
58
|
}
|
|
60
59
|
|
|
@@ -112,9 +111,10 @@ export function generateProductionFiles(
|
|
|
112
111
|
let nodeVersion = "20";
|
|
113
112
|
if (fs.existsSync(rootMiseTomlPath)) {
|
|
114
113
|
const miseContent = fs.readFileSync(rootMiseTomlPath, "utf-8");
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
114
|
+
// mise.toml은 저장소에서 관리되는 설정 파일이므로, 파싱 실패 시 폴백하지 않고 예외를 전파하여 설정 오류를 즉시 드러낸다.
|
|
115
|
+
const miseConfig = TOML.parse(miseContent) as { tools?: { node?: string } };
|
|
116
|
+
if (miseConfig.tools?.node != null) {
|
|
117
|
+
nodeVersion = miseConfig.tools.node;
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
fs.writeFileSync(path.join(distDir, "mise.toml"), `[tools]\nnode = "${nodeVersion}"\n`);
|
|
@@ -5,15 +5,15 @@ import ts from "typescript";
|
|
|
5
5
|
import type esbuild from "esbuild";
|
|
6
6
|
import { consola } from "consola";
|
|
7
7
|
import { JavaScriptTransformer, Cache as AngularCache } from "@angular/build/private";
|
|
8
|
-
import type { AngularSourceFileCache } from "../angular/angular-compiler
|
|
9
|
-
import type { SerializedDiagnostic } from "../typecheck/typecheck-serialization
|
|
10
|
-
import { SdTsCompiler } from "../ts-compiler/SdTsCompiler
|
|
11
|
-
import type { ISdTsCompilerResult } from "../ts-compiler/sd-ts-compiler-result
|
|
12
|
-
import { FileReferenceTracker } from "./file-reference-tracker
|
|
13
|
-
import { LmdbCacheStore } from "./lmdb-cache-store
|
|
14
|
-
import { createCachedLoad, type LoadResultCache } from "./load-result-cache
|
|
15
|
-
import { collectHmrCandidates, HMR_MODIFIED_FILE_LIMIT } from "../angular/hmr-candidates
|
|
16
|
-
import {
|
|
8
|
+
import type { AngularSourceFileCache } from "../angular/angular-compiler";
|
|
9
|
+
import type { SerializedDiagnostic } from "../typecheck/typecheck-serialization";
|
|
10
|
+
import { SdTsCompiler } from "../ts-compiler/SdTsCompiler";
|
|
11
|
+
import type { ISdTsCompilerResult } from "../ts-compiler/sd-ts-compiler-result";
|
|
12
|
+
import { FileReferenceTracker } from "./file-reference-tracker";
|
|
13
|
+
import { LmdbCacheStore } from "./lmdb-cache-store";
|
|
14
|
+
import { createCachedLoad, type LoadResultCache } from "./load-result-cache";
|
|
15
|
+
import { collectHmrCandidates, HMR_MODIFIED_FILE_LIMIT } from "../angular/hmr-candidates";
|
|
16
|
+
import { transformWorkerPatterns } from "./esbuild-worker-plugin";
|
|
17
17
|
|
|
18
18
|
const logger = consola.withTag("sd:cli:angular-plugin");
|
|
19
19
|
|
|
@@ -48,12 +48,6 @@ export interface AngularCompilerPluginOptions {
|
|
|
48
48
|
stylesheetErrors?: string[];
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
interface AdditionalResult {
|
|
52
|
-
outputFiles?: esbuild.OutputFile[];
|
|
53
|
-
metafile?: esbuild.Metafile;
|
|
54
|
-
errors?: esbuild.PartialMessage[];
|
|
55
|
-
}
|
|
56
|
-
|
|
57
51
|
//#endregion
|
|
58
52
|
|
|
59
53
|
//#region compilerOptions 변환
|
|
@@ -158,46 +152,6 @@ export function convertSerializedDiagnosticToEsbuild(
|
|
|
158
152
|
|
|
159
153
|
//#endregion
|
|
160
154
|
|
|
161
|
-
//#region bundleWebWorker
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Worker 파일을 esbuild.buildSync()로 별도 ESM 번들로 빌드한다.
|
|
165
|
-
* TypeScript transformer 내에서 동기적으로 호출되므로 sync API를 사용한다.
|
|
166
|
-
*/
|
|
167
|
-
export function bundleWebWorker(
|
|
168
|
-
build: esbuild.PluginBuild,
|
|
169
|
-
sourcemap: boolean,
|
|
170
|
-
workerFile: string,
|
|
171
|
-
): esbuild.BuildResult {
|
|
172
|
-
try {
|
|
173
|
-
return build.esbuild.buildSync({
|
|
174
|
-
...build.initialOptions,
|
|
175
|
-
platform: "browser",
|
|
176
|
-
write: false,
|
|
177
|
-
bundle: true,
|
|
178
|
-
metafile: true,
|
|
179
|
-
format: "esm",
|
|
180
|
-
entryNames: "worker-[hash]",
|
|
181
|
-
entryPoints: [workerFile],
|
|
182
|
-
sourcemap,
|
|
183
|
-
supported: undefined,
|
|
184
|
-
plugins: undefined,
|
|
185
|
-
});
|
|
186
|
-
} catch (error) {
|
|
187
|
-
if (
|
|
188
|
-
error != null &&
|
|
189
|
-
typeof error === "object" &&
|
|
190
|
-
"errors" in error &&
|
|
191
|
-
"warnings" in error
|
|
192
|
-
) {
|
|
193
|
-
return error as esbuild.BuildResult;
|
|
194
|
-
}
|
|
195
|
-
throw error;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
//#endregion
|
|
200
|
-
|
|
201
155
|
//#region onLoad 헬퍼
|
|
202
156
|
|
|
203
157
|
const POTENTIAL_METADATA_REGEX =
|
|
@@ -288,7 +242,12 @@ export function createAngularCompilerPlugin(
|
|
|
288
242
|
// ── 내부 상태 ──
|
|
289
243
|
const typeScriptFileCache: Map<string, string | Uint8Array> =
|
|
290
244
|
pluginOptions.typeScriptFileCache ?? new Map();
|
|
291
|
-
|
|
245
|
+
// containingFile별 Worker 번들 결과. 증분 빌드에서 변경된 파일만 선택적으로
|
|
246
|
+
// 제거하여, 변경되지 않은 Worker metafile/outputFiles가 유지되도록 함.
|
|
247
|
+
const workerResultsByContainingFile = new Map<
|
|
248
|
+
string,
|
|
249
|
+
{ outputFiles?: esbuild.OutputFile[]; metafile?: esbuild.Metafile }
|
|
250
|
+
>();
|
|
292
251
|
const referencedFileTracker = new FileReferenceTracker();
|
|
293
252
|
let sdTsCompiler: SdTsCompiler | undefined;
|
|
294
253
|
let lastResult: ISdTsCompilerResult | undefined;
|
|
@@ -308,58 +267,6 @@ export function createAngularCompilerPlugin(
|
|
|
308
267
|
return sideEffects;
|
|
309
268
|
}
|
|
310
269
|
|
|
311
|
-
// ── 서브함수: WebWorker 프로세서 생성 ──
|
|
312
|
-
function createWebWorkerProcessor(
|
|
313
|
-
errors: esbuild.PartialMessage[],
|
|
314
|
-
warnings: esbuild.PartialMessage[],
|
|
315
|
-
): (workerFile: string, containingFile: string) => string {
|
|
316
|
-
return (workerFile: string, containingFile: string): string => {
|
|
317
|
-
const fullWorkerPath = path.join(path.dirname(containingFile), workerFile);
|
|
318
|
-
const workerResult = bundleWebWorker(build, pluginOptions.sourcemap, fullWorkerPath);
|
|
319
|
-
|
|
320
|
-
warnings.push(...workerResult.warnings);
|
|
321
|
-
|
|
322
|
-
if (workerResult.errors.length > 0) {
|
|
323
|
-
errors.push(...workerResult.errors);
|
|
324
|
-
// 에러 파일 경로 추적 (rebuild 허용)
|
|
325
|
-
referencedFileTracker.add(
|
|
326
|
-
containingFile,
|
|
327
|
-
workerResult.errors
|
|
328
|
-
.map((e) => e.location?.file)
|
|
329
|
-
.filter((f): f is string => f != null)
|
|
330
|
-
.map((f) => path.join(cwd, f)),
|
|
331
|
-
);
|
|
332
|
-
additionalResults.set(fullWorkerPath, { errors: workerResult.errors });
|
|
333
|
-
return workerFile;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
additionalResults.set(fullWorkerPath, {
|
|
337
|
-
outputFiles: workerResult.outputFiles,
|
|
338
|
-
metafile: workerResult.metafile,
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
// metafile.inputs → FileReferenceTracker
|
|
342
|
-
if (workerResult.metafile != null) {
|
|
343
|
-
referencedFileTracker.add(
|
|
344
|
-
containingFile,
|
|
345
|
-
Object.keys(workerResult.metafile.inputs).map((input) => path.join(cwd, input)),
|
|
346
|
-
);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// worker-[HASH].js 파일 찾기
|
|
350
|
-
const workerCodeFile = workerResult.outputFiles?.find((file) =>
|
|
351
|
-
/^worker-[A-Z0-9]{8}\.[cm]?js$/.test(path.basename(file.path)),
|
|
352
|
-
);
|
|
353
|
-
if (workerCodeFile == null) {
|
|
354
|
-
errors.push({ text: `Web Worker bundled code file not found: ${fullWorkerPath}`, location: null });
|
|
355
|
-
return workerFile;
|
|
356
|
-
}
|
|
357
|
-
const outdir = build.initialOptions.outdir ?? "";
|
|
358
|
-
const workerCodePath = path.relative(outdir, workerCodeFile.path);
|
|
359
|
-
return workerCodePath.replaceAll("\\", "/");
|
|
360
|
-
};
|
|
361
|
-
}
|
|
362
|
-
|
|
363
270
|
// ── onStart ──
|
|
364
271
|
build.onStart(async () => {
|
|
365
272
|
const result: esbuild.OnStartResult = {};
|
|
@@ -402,9 +309,10 @@ export function createAngularCompilerPlugin(
|
|
|
402
309
|
sourceFileCache.modifiedFiles,
|
|
403
310
|
);
|
|
404
311
|
|
|
405
|
-
//
|
|
312
|
+
// 변경된 파일의 Worker 결과만 선택적 제거 (변경되지 않은 파일의
|
|
313
|
+
// Worker metafile은 유지되어 onEnd에서 재병합됨)
|
|
406
314
|
for (const file of expandedModifiedFiles) {
|
|
407
|
-
|
|
315
|
+
workerResultsByContainingFile.delete(file);
|
|
408
316
|
}
|
|
409
317
|
}
|
|
410
318
|
|
|
@@ -424,19 +332,39 @@ export function createAngularCompilerPlugin(
|
|
|
424
332
|
});
|
|
425
333
|
}
|
|
426
334
|
|
|
427
|
-
// ── processWebWorker + workerTransformer ──
|
|
428
|
-
const processWebWorker = createWebWorkerProcessor(errors, warnings);
|
|
429
|
-
const workerTransformer = createWorkerTransformer(processWebWorker);
|
|
430
|
-
|
|
431
335
|
// ── compileAsync ──
|
|
432
336
|
const compileResult = await sdTsCompiler.compileAsync(
|
|
433
337
|
isIncremental ? expandedModifiedFiles : undefined,
|
|
434
|
-
{ additionalTransformers: { before: [workerTransformer] } },
|
|
435
338
|
);
|
|
436
339
|
|
|
437
|
-
// ── emitResults → typeScriptFileCache ──
|
|
340
|
+
// ── emitResults → typeScriptFileCache (Worker 패턴 처리 포함) ──
|
|
438
341
|
for (const { contents, sourceFileName } of compileResult.emitResults ?? []) {
|
|
439
|
-
|
|
342
|
+
const normalized = path.normalize(sourceFileName);
|
|
343
|
+
const workerResult = transformWorkerPatterns(contents, normalized, build);
|
|
344
|
+
if (workerResult != null) {
|
|
345
|
+
typeScriptFileCache.set(normalized, workerResult.contents);
|
|
346
|
+
errors.push(...workerResult.errors);
|
|
347
|
+
warnings.push(...workerResult.warnings);
|
|
348
|
+
if (workerResult.workerMetafile != null) {
|
|
349
|
+
referencedFileTracker.add(
|
|
350
|
+
normalized,
|
|
351
|
+
Object.keys(workerResult.workerMetafile.inputs).map((input) =>
|
|
352
|
+
path.join(cwd, input),
|
|
353
|
+
),
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
if (
|
|
357
|
+
workerResult.workerMetafile != null ||
|
|
358
|
+
workerResult.workerOutputFiles != null
|
|
359
|
+
) {
|
|
360
|
+
workerResultsByContainingFile.set(normalized, {
|
|
361
|
+
outputFiles: workerResult.workerOutputFiles,
|
|
362
|
+
metafile: workerResult.workerMetafile,
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
} else {
|
|
366
|
+
typeScriptFileCache.set(normalized, contents);
|
|
367
|
+
}
|
|
440
368
|
}
|
|
441
369
|
|
|
442
370
|
// ── onLoad 플래그 결정 (첫 빌드에서만) ──
|
|
@@ -612,6 +540,37 @@ export function createAngularCompilerPlugin(
|
|
|
612
540
|
false, // skipLinker
|
|
613
541
|
sideEffects,
|
|
614
542
|
);
|
|
543
|
+
|
|
544
|
+
// Worker 패턴 처리 (D2)
|
|
545
|
+
const textContents = new TextDecoder().decode(contents);
|
|
546
|
+
const workerResult = transformWorkerPatterns(textContents, request, build);
|
|
547
|
+
if (workerResult != null) {
|
|
548
|
+
if (workerResult.workerMetafile != null) {
|
|
549
|
+
referencedFileTracker.add(
|
|
550
|
+
request,
|
|
551
|
+
Object.keys(workerResult.workerMetafile.inputs).map((input) =>
|
|
552
|
+
path.join(cwd, input),
|
|
553
|
+
),
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
if (
|
|
557
|
+
workerResult.workerMetafile != null ||
|
|
558
|
+
workerResult.workerOutputFiles != null
|
|
559
|
+
) {
|
|
560
|
+
workerResultsByContainingFile.set(request, {
|
|
561
|
+
outputFiles: workerResult.workerOutputFiles,
|
|
562
|
+
metafile: workerResult.workerMetafile,
|
|
563
|
+
});
|
|
564
|
+
}
|
|
565
|
+
return {
|
|
566
|
+
contents: workerResult.contents,
|
|
567
|
+
loader: "js" as const,
|
|
568
|
+
resolveDir: path.dirname(request),
|
|
569
|
+
errors: workerResult.errors.length > 0 ? workerResult.errors : undefined,
|
|
570
|
+
warnings: workerResult.warnings.length > 0 ? workerResult.warnings : undefined,
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
|
|
615
574
|
return {
|
|
616
575
|
contents,
|
|
617
576
|
loader: "js" as const,
|
|
@@ -622,13 +581,13 @@ export function createAngularCompilerPlugin(
|
|
|
622
581
|
|
|
623
582
|
// ── onEnd ──
|
|
624
583
|
build.onEnd((result: esbuild.BuildResult) => {
|
|
625
|
-
for (const
|
|
626
|
-
if (outputFiles != null && outputFiles.length > 0) {
|
|
627
|
-
result.outputFiles?.push(...outputFiles);
|
|
584
|
+
for (const wr of workerResultsByContainingFile.values()) {
|
|
585
|
+
if (wr.outputFiles != null && wr.outputFiles.length > 0) {
|
|
586
|
+
result.outputFiles?.push(...wr.outputFiles);
|
|
628
587
|
}
|
|
629
|
-
if (result.metafile != null && metafile != null) {
|
|
630
|
-
Object.assign(result.metafile.inputs, metafile.inputs);
|
|
631
|
-
Object.assign(result.metafile.outputs, metafile.outputs);
|
|
588
|
+
if (result.metafile != null && wr.metafile != null) {
|
|
589
|
+
Object.assign(result.metafile.inputs, wr.metafile.inputs);
|
|
590
|
+
Object.assign(result.metafile.outputs, wr.metafile.outputs);
|
|
632
591
|
}
|
|
633
592
|
}
|
|
634
593
|
});
|
|
@@ -4,6 +4,7 @@ import fs from "fs/promises";
|
|
|
4
4
|
import { createRequire } from "module";
|
|
5
5
|
import type esbuild from "esbuild";
|
|
6
6
|
import { consola } from "consola";
|
|
7
|
+
import { addJsExtensionToImports } from "../utils/output-path-rewriter";
|
|
7
8
|
|
|
8
9
|
const logger = consola.withTag("sd:cli:esbuild-config");
|
|
9
10
|
|
|
@@ -19,13 +20,7 @@ export async function writeChangedOutputFiles(outputFiles: esbuild.OutputFile[])
|
|
|
19
20
|
await Promise.all(
|
|
20
21
|
outputFiles.map(async (file) => {
|
|
21
22
|
const finalText = file.path.endsWith(".js")
|
|
22
|
-
? file.text
|
|
23
|
-
/((?:from|import)\s*["'])(\.\.?\/[^"']*?)(["'])/g,
|
|
24
|
-
(_match, prefix: string, importPath: string, suffix: string) => {
|
|
25
|
-
if (/\.(js|mjs|cjs|json|css|wasm|node)$/i.test(importPath)) return _match;
|
|
26
|
-
return `${prefix}${importPath}.js${suffix}`;
|
|
27
|
-
},
|
|
28
|
-
)
|
|
23
|
+
? addJsExtensionToImports(file.text)
|
|
29
24
|
: file.text;
|
|
30
25
|
|
|
31
26
|
try {
|