@simplysm/sd-cli 14.0.41 → 14.0.43
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/angular/angular-compiler.d.ts +0 -35
- package/dist/angular/angular-compiler.d.ts.map +1 -1
- package/dist/angular/angular-compiler.js +0 -374
- package/dist/angular/angular-compiler.js.map +1 -1
- package/dist/angular/hmr-candidates.d.ts +13 -0
- package/dist/angular/hmr-candidates.d.ts.map +1 -0
- package/dist/angular/hmr-candidates.js +230 -0
- package/dist/angular/hmr-candidates.js.map +1 -0
- package/dist/angular/ngtsc-build-core.d.ts +29 -34
- package/dist/angular/ngtsc-build-core.d.ts.map +1 -1
- package/dist/angular/ngtsc-build-core.js +90 -51
- package/dist/angular/ngtsc-build-core.js.map +1 -1
- package/dist/angular/vite-angular-plugin.d.ts +1 -1
- package/dist/angular/vite-angular-plugin.d.ts.map +1 -1
- package/dist/angular/vite-angular-plugin.js +63 -56
- package/dist/angular/vite-angular-plugin.js.map +1 -1
- package/dist/angular/web-worker-transformer.d.ts +9 -0
- package/dist/angular/web-worker-transformer.d.ts.map +1 -0
- package/dist/angular/web-worker-transformer.js +73 -0
- package/dist/angular/web-worker-transformer.js.map +1 -0
- package/dist/capacitor/capacitor.d.ts.map +1 -1
- package/dist/capacitor/capacitor.js +6 -4
- package/dist/capacitor/capacitor.js.map +1 -1
- package/dist/commands/check.d.ts +1 -1
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +15 -65
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/publish/deployment-phase.d.ts.map +1 -1
- package/dist/commands/publish/deployment-phase.js +13 -5
- package/dist/commands/publish/deployment-phase.js.map +1 -1
- package/dist/commands/publish/npm-publisher.js +1 -1
- package/dist/commands/publish/npm-publisher.js.map +1 -1
- package/dist/commands/publish/publish-command.js +1 -1
- package/dist/commands/publish/publish-command.js.map +1 -1
- package/dist/commands/publish/version-upgrade.js +1 -1
- package/dist/commands/publish/version-upgrade.js.map +1 -1
- package/dist/commands/replace-deps.d.ts.map +1 -1
- package/dist/commands/replace-deps.js +2 -1
- package/dist/commands/replace-deps.js.map +1 -1
- package/dist/deps/replace-deps/collect-deps.d.ts.map +1 -1
- package/dist/deps/replace-deps/collect-deps.js +5 -2
- package/dist/deps/replace-deps/collect-deps.js.map +1 -1
- package/dist/deps/replace-deps/replace-deps.d.ts +21 -3
- package/dist/deps/replace-deps/replace-deps.d.ts.map +1 -1
- package/dist/deps/replace-deps/replace-deps.js +107 -62
- package/dist/deps/replace-deps/replace-deps.js.map +1 -1
- package/dist/electron/electron.js +7 -7
- package/dist/electron/electron.js.map +1 -1
- package/dist/engines/BaseEngine.d.ts.map +1 -1
- package/dist/engines/BaseEngine.js +2 -5
- package/dist/engines/BaseEngine.js.map +1 -1
- package/dist/engines/EsbuildClientEngine.d.ts.map +1 -1
- package/dist/engines/EsbuildClientEngine.js +16 -9
- package/dist/engines/EsbuildClientEngine.js.map +1 -1
- package/dist/engines/NgtscEngine.d.ts +4 -4
- package/dist/engines/NgtscEngine.d.ts.map +1 -1
- package/dist/engines/NgtscEngine.js +5 -5
- package/dist/engines/NgtscEngine.js.map +1 -1
- package/dist/engines/TscEngine.d.ts.map +1 -1
- package/dist/engines/TscEngine.js +0 -2
- package/dist/engines/TscEngine.js.map +1 -1
- package/dist/engines/types.d.ts +2 -0
- package/dist/engines/types.d.ts.map +1 -1
- package/dist/esbuild/esbuild-angular-compiler-plugin.d.ts +36 -0
- package/dist/esbuild/esbuild-angular-compiler-plugin.d.ts.map +1 -0
- package/dist/esbuild/esbuild-angular-compiler-plugin.js +464 -0
- package/dist/esbuild/esbuild-angular-compiler-plugin.js.map +1 -0
- package/dist/esbuild/esbuild-client-config.d.ts +8 -2
- package/dist/esbuild/esbuild-client-config.d.ts.map +1 -1
- package/dist/esbuild/esbuild-client-config.js +48 -33
- package/dist/esbuild/esbuild-client-config.js.map +1 -1
- package/dist/esbuild/esbuild-tsc-plugin.d.ts +4 -1
- package/dist/esbuild/esbuild-tsc-plugin.d.ts.map +1 -1
- package/dist/esbuild/esbuild-tsc-plugin.js +27 -23
- package/dist/esbuild/esbuild-tsc-plugin.js.map +1 -1
- package/dist/esbuild/file-reference-tracker.d.ts +24 -0
- package/dist/esbuild/file-reference-tracker.d.ts.map +1 -0
- package/dist/esbuild/file-reference-tracker.js +57 -0
- package/dist/esbuild/file-reference-tracker.js.map +1 -0
- package/dist/esbuild/lmdb-cache-store.d.ts +18 -0
- package/dist/esbuild/lmdb-cache-store.d.ts.map +1 -0
- package/dist/esbuild/lmdb-cache-store.js +41 -0
- package/dist/esbuild/lmdb-cache-store.js.map +1 -0
- package/dist/esbuild/load-result-cache.d.ts +17 -0
- package/dist/esbuild/load-result-cache.d.ts.map +1 -0
- package/dist/esbuild/load-result-cache.js +61 -0
- package/dist/esbuild/load-result-cache.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/lint/lint-core.js +7 -7
- package/dist/lint/lint-core.js.map +1 -1
- package/dist/orchestrators/BaseOrchestrator.js +2 -2
- package/dist/orchestrators/BaseOrchestrator.js.map +1 -1
- package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/BuildOrchestrator.js +5 -19
- package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
- package/dist/orchestrators/DevOrchestrator.js +5 -5
- package/dist/orchestrators/DevOrchestrator.js.map +1 -1
- package/dist/orchestrators/WatchOrchestrator.js +6 -6
- package/dist/orchestrators/WatchOrchestrator.js.map +1 -1
- package/dist/runtime/ResultCollector.d.ts +1 -0
- package/dist/runtime/ResultCollector.d.ts.map +1 -1
- package/dist/runtime/ResultCollector.js.map +1 -1
- package/dist/runtime/engine-watch-events.d.ts.map +1 -1
- package/dist/runtime/engine-watch-events.js +3 -0
- package/dist/runtime/engine-watch-events.js.map +1 -1
- package/dist/runtime/rebuild-manager.js +1 -1
- package/dist/runtime/rebuild-manager.js.map +1 -1
- package/dist/runtime/worker-utils.js +1 -1
- package/dist/runtime/worker-utils.js.map +1 -1
- package/dist/sd-cli-entry.d.ts.map +1 -1
- package/dist/sd-cli-entry.js +4 -3
- package/dist/sd-cli-entry.js.map +1 -1
- package/dist/sd-cli.js +3 -3
- package/dist/sd-cli.js.map +1 -1
- package/dist/ts-compiler/SdTsCompiler.d.ts +39 -0
- package/dist/ts-compiler/SdTsCompiler.d.ts.map +1 -0
- package/dist/ts-compiler/SdTsCompiler.js +593 -0
- package/dist/ts-compiler/SdTsCompiler.js.map +1 -0
- package/dist/ts-compiler/sd-ts-compiler-options.d.ts +40 -0
- package/dist/ts-compiler/sd-ts-compiler-options.d.ts.map +1 -0
- package/dist/ts-compiler/sd-ts-compiler-options.js +2 -0
- package/dist/ts-compiler/sd-ts-compiler-options.js.map +1 -0
- package/dist/ts-compiler/sd-ts-compiler-result.d.ts +34 -0
- package/dist/ts-compiler/sd-ts-compiler-result.d.ts.map +1 -0
- package/dist/ts-compiler/sd-ts-compiler-result.js +2 -0
- package/dist/ts-compiler/sd-ts-compiler-result.js.map +1 -0
- package/dist/utils/copy-public.d.ts +6 -4
- package/dist/utils/copy-public.d.ts.map +1 -1
- package/dist/utils/copy-public.js +9 -7
- package/dist/utils/copy-public.js.map +1 -1
- package/dist/utils/diagnostic-utils.d.ts +2 -3
- package/dist/utils/diagnostic-utils.d.ts.map +1 -1
- package/dist/utils/diagnostic-utils.js +8 -9
- package/dist/utils/diagnostic-utils.js.map +1 -1
- package/dist/utils/output-utils.d.ts +8 -2
- package/dist/utils/output-utils.d.ts.map +1 -1
- package/dist/utils/output-utils.js +32 -8
- package/dist/utils/output-utils.js.map +1 -1
- package/dist/workers/client.worker.d.ts +1 -1
- package/dist/workers/client.worker.d.ts.map +1 -1
- package/dist/workers/client.worker.js +136 -110
- package/dist/workers/client.worker.js.map +1 -1
- package/dist/workers/library-build.worker.d.ts +0 -2
- package/dist/workers/library-build.worker.d.ts.map +1 -1
- package/dist/workers/library-build.worker.js +147 -70
- package/dist/workers/library-build.worker.js.map +1 -1
- package/dist/workers/server-build.worker.d.ts.map +1 -1
- package/dist/workers/server-build.worker.js +30 -57
- package/dist/workers/server-build.worker.js.map +1 -1
- package/dist/workers/server-esbuild-context.d.ts +7 -0
- package/dist/workers/server-esbuild-context.d.ts.map +1 -1
- package/dist/workers/server-esbuild-context.js +11 -2
- package/dist/workers/server-esbuild-context.js.map +1 -1
- package/package.json +7 -6
- package/src/angular/angular-compiler.ts +0 -502
- package/src/angular/hmr-candidates.ts +295 -0
- package/src/angular/ngtsc-build-core.ts +125 -92
- package/src/angular/vite-angular-plugin.ts +71 -65
- package/src/angular/web-worker-transformer.ts +117 -0
- package/src/capacitor/capacitor.ts +6 -4
- package/src/commands/check.ts +17 -76
- package/src/commands/publish/deployment-phase.ts +11 -7
- package/src/commands/publish/npm-publisher.ts +1 -1
- package/src/commands/publish/publish-command.ts +1 -1
- package/src/commands/publish/version-upgrade.ts +1 -1
- package/src/commands/replace-deps.ts +3 -1
- package/src/deps/replace-deps/collect-deps.ts +4 -2
- package/src/deps/replace-deps/replace-deps.ts +114 -66
- package/src/electron/electron.ts +7 -7
- package/src/engines/BaseEngine.ts +2 -6
- package/src/engines/EsbuildClientEngine.ts +16 -10
- package/src/engines/NgtscEngine.ts +7 -7
- package/src/engines/TscEngine.ts +0 -2
- package/src/engines/types.ts +2 -0
- package/src/esbuild/esbuild-angular-compiler-plugin.ts +647 -0
- package/src/esbuild/esbuild-client-config.ts +57 -41
- package/src/esbuild/esbuild-tsc-plugin.ts +33 -23
- package/src/esbuild/file-reference-tracker.ts +61 -0
- package/src/esbuild/lmdb-cache-store.ts +46 -0
- package/src/esbuild/load-result-cache.ts +85 -0
- package/src/index.ts +5 -0
- package/src/lint/lint-core.ts +7 -7
- package/src/orchestrators/BaseOrchestrator.ts +2 -2
- package/src/orchestrators/BuildOrchestrator.ts +5 -24
- package/src/orchestrators/DevOrchestrator.ts +5 -5
- package/src/orchestrators/WatchOrchestrator.ts +6 -6
- package/src/runtime/ResultCollector.ts +1 -0
- package/src/runtime/engine-watch-events.ts +3 -0
- package/src/runtime/rebuild-manager.ts +1 -1
- package/src/runtime/worker-utils.ts +1 -1
- package/src/sd-cli-entry.ts +5 -3
- package/src/sd-cli.ts +4 -4
- package/src/ts-compiler/SdTsCompiler.ts +815 -0
- package/src/ts-compiler/sd-ts-compiler-options.ts +46 -0
- package/src/ts-compiler/sd-ts-compiler-result.ts +34 -0
- package/src/utils/copy-public.ts +9 -6
- package/src/utils/diagnostic-utils.ts +8 -9
- package/src/utils/output-utils.ts +38 -8
- package/src/workers/client.worker.ts +160 -126
- package/src/workers/library-build.worker.ts +187 -75
- package/src/workers/server-build.worker.ts +31 -61
- package/src/workers/server-esbuild-context.ts +14 -2
- package/tests/angular/fixtures/packages/basic-app/dist/styles.css +3 -0
- package/tests/angular/fixtures/packages/basic-app/scss/styles.scss +5 -0
- package/tests/angular/vite-angular-plugin-sdtscompiler.verify.md +13 -0
- package/tests/angular/web-worker-transformer.spec.ts +154 -0
- package/tests/capacitor/capacitor-build.spec.ts +1 -1
- package/tests/capacitor/capacitor-icon.spec.ts +1 -1
- package/tests/capacitor/capacitor-init.spec.ts +1 -1
- package/tests/commands/check.spec.ts +90 -104
- package/tests/commands/publish.spec.ts +12 -4
- package/tests/commands/slice3-severity-cleanup.verify.md +12 -0
- package/tests/deps/replace-deps/collect-deps.acc.spec.ts +62 -0
- package/tests/deps/replace-deps/collect-deps.spec.ts +49 -0
- package/tests/deps/replace-deps/replace-deps-filter.spec.ts +103 -0
- package/tests/deps/replace-deps/replace-deps-setup.acc.spec.ts +156 -0
- package/tests/electron/electron.spec.ts +4 -1
- package/tests/engines/engine-adapter-isolation.spec.ts +5 -6
- package/tests/engines/engine-duplicate-output-removal.verify.md +10 -0
- package/tests/engines/esbuild-client-engine.acc.spec.ts +79 -0
- package/tests/engines/esbuild-client-engine.spec.ts +73 -3
- package/tests/esbuild/esbuild-angular-compiler-plugin-hmr.verify.md +23 -0
- package/tests/esbuild/esbuild-angular-compiler-plugin-onload.verify.md +21 -0
- package/tests/esbuild/esbuild-angular-compiler-plugin-onstart-extraction.verify.md +16 -0
- package/tests/esbuild/esbuild-angular-compiler-plugin-sdtscompiler.verify.md +15 -0
- package/tests/esbuild/esbuild-angular-compiler-plugin-stylesheet.verify.md +31 -0
- package/tests/esbuild/esbuild-angular-compiler-plugin-worker.verify.md +31 -0
- package/tests/esbuild/esbuild-angular-compiler-plugin.spec.ts +397 -0
- package/tests/esbuild/esbuild-angular-compiler-plugin.verify.md +21 -0
- package/tests/esbuild/esbuild-tsc-plugin-imports.verify.md +13 -0
- package/tests/esbuild/esbuild-tsc-plugin.acc.spec.ts +56 -111
- package/tests/esbuild/esbuild-tsc-plugin.spec.ts +116 -52
- package/tests/esbuild/file-reference-tracker.spec.ts +99 -0
- package/tests/esbuild/lmdb-cache-store.spec.ts +58 -0
- package/tests/esbuild/load-result-cache.acc.spec.ts +55 -0
- package/tests/esbuild/load-result-cache.spec.ts +133 -0
- package/tests/orchestrators/build-orchestrator.spec.ts +4 -3
- package/tests/orchestrators/dev-orchestrator.spec.ts +5 -5
- package/tests/orchestrators/slice1-stdout-to-consola.verify.md +10 -0
- package/tests/orchestrators/typecheck-orchestrator.spec.ts +1 -1
- package/tests/orchestrators/watch-orchestrator.spec.ts +7 -7
- package/tests/runtime/result-collector.spec.ts +64 -0
- package/tests/sd-cli-entry.spec.ts +3 -4
- package/tests/sd-cli-log-tag.verify.md +11 -0
- package/tests/ts-compiler/SdTsCompiler-affected-files.verify.md +8 -0
- package/tests/ts-compiler/SdTsCompiler-diagnostics.verify.md +12 -0
- package/tests/ts-compiler/SdTsCompiler-emit.verify.md +9 -0
- package/tests/ts-compiler/SdTsCompiler.acc.spec.ts +603 -0
- package/tests/ts-compiler/SdTsCompiler.spec.ts +265 -0
- package/tests/ts-compiler/SdTsCompiler.verify.md +41 -0
- package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck-browser.tsbuildinfo +1 -0
- package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck-node.tsbuildinfo +1 -0
- package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck.tsbuildinfo +1 -0
- package/tests/ts-compiler/fixtures/non-angular-pkg/dist/index.d.ts +2 -0
- package/tests/ts-compiler/fixtures/non-angular-pkg/dist/index.d.ts.map +1 -0
- package/tests/ts-compiler/fixtures/non-angular-pkg/dist/index.js +4 -0
- package/tests/ts-compiler/fixtures/non-angular-pkg/dist/index.js.map +1 -0
- package/tests/ts-compiler/fixtures/non-angular-pkg/dist/util.d.ts +2 -0
- package/tests/ts-compiler/fixtures/non-angular-pkg/dist/util.d.ts.map +1 -0
- package/tests/ts-compiler/fixtures/non-angular-pkg/dist/util.js +4 -0
- package/tests/ts-compiler/fixtures/non-angular-pkg/dist/util.js.map +1 -0
- package/tests/ts-compiler/fixtures/non-angular-pkg/src/index.ts +3 -0
- package/tests/ts-compiler/fixtures/non-angular-pkg/src/util.ts +3 -0
- package/tests/ts-compiler/fixtures/non-angular-pkg/tests/sample.test-file.ts +3 -0
- package/tests/ts-compiler/fixtures/non-angular-pkg/tsconfig.json +12 -0
- package/tests/ts-compiler/scss-lint-integration.verify.md +14 -0
- package/tests/utils/angular-build.spec.ts +1 -1
- package/tests/utils/copy-public-outdir.verify.md +8 -0
- package/tests/utils/copy-public.acc.spec.ts +52 -0
- package/tests/utils/copy-public.spec.ts +56 -0
- package/tests/utils/diagnostic-utils.spec.ts +24 -15
- package/tests/utils/engine-watch-events.acc.spec.ts +59 -0
- package/tests/utils/engine-watch-events.spec.ts +58 -0
- package/tests/utils/esbuild-client-config-integration.verify.md +9 -0
- package/tests/utils/esbuild-client-config.acc.spec.ts +45 -61
- package/tests/utils/esbuild-client-config.spec.ts +70 -52
- package/tests/utils/ngtsc-build-core-write-emit.spec.ts +12 -12
- package/tests/utils/ngtsc-build-core.spec.ts +1 -44
- package/tests/utils/output-utils.spec.ts +133 -13
- package/tests/utils/replace-deps-watch.acc.spec.ts +7 -1
- package/tests/utils/replace-deps-watch.spec.ts +57 -1
- package/tests/utils/worker-utils.spec.ts +8 -2
- package/tests/workers/client-worker-initial-build-error.verify.md +2 -3
- package/tests/workers/client-worker-initial-build-warnings.verify.md +7 -0
- package/tests/workers/client-worker-refactor.verify.md +22 -0
- package/tests/workers/client-worker-ts-cache-invalidation.verify.md +12 -0
- package/tests/workers/client-worker.acc.spec.ts +6 -3
- package/tests/workers/library-build-lint.spec.ts +40 -45
- package/tests/workers/library-build-worker.spec.ts +294 -40
- package/tests/workers/server-build-lint.spec.ts +59 -45
- package/tests/workers/server-build-worker.spec.ts +63 -24
- package/tests/workers/server-esbuild-context.acc.spec.ts +2 -0
- package/tests/workers/server-esbuild-context.spec.ts +2 -0
- package/tests/workers/server-runtime-worker.spec.ts +1 -1
- package/tests/workers/shared-worker-lifecycle.acc.spec.ts +1 -1
- package/dist/angular/angular-build-pipeline.d.ts +0 -97
- package/dist/angular/angular-build-pipeline.d.ts.map +0 -1
- package/dist/angular/angular-build-pipeline.js +0 -285
- package/dist/angular/angular-build-pipeline.js.map +0 -1
- package/dist/utils/tsc-build.d.ts +0 -51
- package/dist/utils/tsc-build.d.ts.map +0 -1
- package/dist/utils/tsc-build.js +0 -156
- package/dist/utils/tsc-build.js.map +0 -1
- package/dist/workers/ngtsc-build.worker.d.ts +0 -23
- package/dist/workers/ngtsc-build.worker.d.ts.map +0 -1
- package/dist/workers/ngtsc-build.worker.js +0 -267
- package/dist/workers/ngtsc-build.worker.js.map +0 -1
- package/src/angular/angular-build-pipeline.ts +0 -406
- package/src/utils/tsc-build.ts +0 -226
- package/src/workers/ngtsc-build.worker.ts +0 -351
- package/tests/angular/angular-build-pipeline.spec.ts +0 -247
- package/tests/angular/angular-compiler-aot.acc.spec.ts +0 -68
- package/tests/angular/angular-compiler-aot.spec.ts +0 -80
- package/tests/utils/angular-compiler-emit.spec.ts +0 -666
- package/tests/utils/angular-compiler.spec.ts +0 -707
- package/tests/utils/tsc-build.spec.ts +0 -527
- package/tests/workers/ngtsc-build-lint.spec.ts +0 -141
- package/tests/workers/ngtsc-build-worker.spec.ts +0 -199
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from "vitest";
|
|
2
|
+
import ts from "typescript";
|
|
3
|
+
|
|
4
|
+
const { createWorkerTransformer } = await import(
|
|
5
|
+
"../../src/angular/web-worker-transformer.js"
|
|
6
|
+
);
|
|
7
|
+
|
|
8
|
+
//#region 헬퍼
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* TypeScript 소스 코드에 transformer를 적용하고 결과 코드를 반환한다.
|
|
12
|
+
*/
|
|
13
|
+
function transformCode(
|
|
14
|
+
code: string,
|
|
15
|
+
fileProcessor: (workerFile: string, containingFile: string) => string,
|
|
16
|
+
fileName = "test.ts",
|
|
17
|
+
): string {
|
|
18
|
+
const sourceFile = ts.createSourceFile(fileName, code, ts.ScriptTarget.ES2022, true);
|
|
19
|
+
const transformer = createWorkerTransformer(fileProcessor);
|
|
20
|
+
const result = ts.transform(sourceFile, [transformer]);
|
|
21
|
+
const printer = ts.createPrinter();
|
|
22
|
+
const output = printer.printFile(result.transformed[0]);
|
|
23
|
+
result.dispose();
|
|
24
|
+
return output;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
//#endregion
|
|
28
|
+
|
|
29
|
+
describe("createWorkerTransformer", () => {
|
|
30
|
+
// Acceptance: Worker 표준 패턴을 감지하여 번들된 경로로 치환한다
|
|
31
|
+
it("Worker 표준 패턴 — URL 치환 + { type: 'module' } 자동 추가", () => {
|
|
32
|
+
const fileProcessor = vi.fn().mockReturnValue("worker-ABCD1234.js");
|
|
33
|
+
const code = `const w = new Worker(new URL('./my-worker.ts', import.meta.url));`;
|
|
34
|
+
|
|
35
|
+
const output = transformCode(code, fileProcessor);
|
|
36
|
+
|
|
37
|
+
expect(fileProcessor).toHaveBeenCalledWith("./my-worker.ts", "test.ts");
|
|
38
|
+
expect(output).toContain('"worker-ABCD1234.js"');
|
|
39
|
+
expect(output).toContain('type');
|
|
40
|
+
expect(output).toContain('"module"');
|
|
41
|
+
expect(output).not.toContain("./my-worker.ts");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Acceptance: SharedWorker도 동일하게 처리한다
|
|
45
|
+
it("SharedWorker도 동일하게 변환한다", () => {
|
|
46
|
+
const fileProcessor = vi.fn().mockReturnValue("worker-SHARED01.js");
|
|
47
|
+
const code = `const sw = new SharedWorker(new URL('./shared.ts', import.meta.url));`;
|
|
48
|
+
|
|
49
|
+
const output = transformCode(code, fileProcessor);
|
|
50
|
+
|
|
51
|
+
expect(fileProcessor).toHaveBeenCalledWith("./shared.ts", "test.ts");
|
|
52
|
+
expect(output).toContain('"worker-SHARED01.js"');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Acceptance: Worker의 기존 options 인자가 있으면 유지한다
|
|
56
|
+
it("기존 options 인자가 있으면 유지한다", () => {
|
|
57
|
+
const fileProcessor = vi.fn().mockReturnValue("worker-OPT00001.js");
|
|
58
|
+
const code = `const w = new Worker(new URL('./w.ts', import.meta.url), { name: 'test' });`;
|
|
59
|
+
|
|
60
|
+
const output = transformCode(code, fileProcessor);
|
|
61
|
+
|
|
62
|
+
expect(output).toContain('"worker-OPT00001.js"');
|
|
63
|
+
expect(output).toContain("name");
|
|
64
|
+
// { type: 'module' } 자동 추가 없이 기존 options가 유지됨
|
|
65
|
+
expect(output).not.toMatch(/type.*module.*name/);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe("createWorkerTransformer — 변환하지 않는 케이스", () => {
|
|
70
|
+
const noopProcessor = vi.fn().mockReturnValue("should-not-appear.js");
|
|
71
|
+
|
|
72
|
+
// URL 패턴이 아닌 Worker 생성
|
|
73
|
+
it("URL 패턴 없이 문자열 인자만 있으면 변환하지 않는다", () => {
|
|
74
|
+
const code = `const w = new Worker('./my-worker.ts');`;
|
|
75
|
+
const output = transformCode(code, noopProcessor);
|
|
76
|
+
|
|
77
|
+
expect(noopProcessor).not.toHaveBeenCalled();
|
|
78
|
+
expect(output).toContain("./my-worker.ts");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// import.meta.url이 아닌 URL
|
|
82
|
+
it("import.meta.url이 아닌 URL은 변환하지 않는다", () => {
|
|
83
|
+
const code = `const w = new Worker(new URL('./w.ts', 'http://example.com'));`;
|
|
84
|
+
const output = transformCode(code, noopProcessor);
|
|
85
|
+
|
|
86
|
+
expect(noopProcessor).not.toHaveBeenCalled();
|
|
87
|
+
expect(output).toContain("./w.ts");
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Worker 인자 없음
|
|
91
|
+
it("Worker 인자가 없으면 변환하지 않는다", () => {
|
|
92
|
+
const code = `const w = new Worker();`;
|
|
93
|
+
transformCode(code, noopProcessor);
|
|
94
|
+
|
|
95
|
+
expect(noopProcessor).not.toHaveBeenCalled();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Worker 인자 3개 이상
|
|
99
|
+
it("Worker 인자가 3개 이상이면 변환하지 않는다", () => {
|
|
100
|
+
const code = `const w = new Worker(new URL('./w.ts', import.meta.url), {}, 'extra');`;
|
|
101
|
+
transformCode(code, noopProcessor);
|
|
102
|
+
|
|
103
|
+
expect(noopProcessor).not.toHaveBeenCalled();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// URL 인자가 1개
|
|
107
|
+
it("URL 인자가 1개면 변환하지 않는다", () => {
|
|
108
|
+
const code = `const w = new Worker(new URL('./w.ts'));`;
|
|
109
|
+
transformCode(code, noopProcessor);
|
|
110
|
+
|
|
111
|
+
expect(noopProcessor).not.toHaveBeenCalled();
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// URL 인자가 3개
|
|
115
|
+
it("URL 인자가 3개면 변환하지 않는다", () => {
|
|
116
|
+
const code = `const w = new Worker(new URL('./w.ts', import.meta.url, 'extra'));`;
|
|
117
|
+
transformCode(code, noopProcessor);
|
|
118
|
+
|
|
119
|
+
expect(noopProcessor).not.toHaveBeenCalled();
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// 'Worker' 문자열 없으면 skip
|
|
123
|
+
it("소스에 'Worker' 문자열이 없으면 변환을 건너뛴다", () => {
|
|
124
|
+
const code = `const x = 1 + 2;`;
|
|
125
|
+
const output = transformCode(code, noopProcessor);
|
|
126
|
+
|
|
127
|
+
expect(noopProcessor).not.toHaveBeenCalled();
|
|
128
|
+
expect(output).toContain("1 + 2");
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
describe("createWorkerTransformer — 추가 경계 케이스", () => {
|
|
133
|
+
// fileProcessor가 원본과 동일한 경로를 반환하면 변환하지 않는다
|
|
134
|
+
it("fileProcessor가 원본 경로를 그대로 반환하면 AST를 변경하지 않는다", () => {
|
|
135
|
+
const fileProcessor = vi.fn().mockReturnValue("./my-worker.ts");
|
|
136
|
+
const code = `const w = new Worker(new URL('./my-worker.ts', import.meta.url));`;
|
|
137
|
+
|
|
138
|
+
const output = transformCode(code, fileProcessor);
|
|
139
|
+
|
|
140
|
+
expect(fileProcessor).toHaveBeenCalledWith("./my-worker.ts", "test.ts");
|
|
141
|
+
// 원본 경로가 그대로 유지 (변환 없음)
|
|
142
|
+
expect(output).toContain("./my-worker.ts");
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// 소스에 Worker 문자열은 있지만 new 표현이 아닌 경우
|
|
146
|
+
it("Worker 문자열이 있지만 new 표현이 아니면 변환하지 않는다", () => {
|
|
147
|
+
const fileProcessor = vi.fn();
|
|
148
|
+
const code = `const WorkerName = "test";`;
|
|
149
|
+
|
|
150
|
+
transformCode(code, fileProcessor);
|
|
151
|
+
|
|
152
|
+
expect(fileProcessor).not.toHaveBeenCalled();
|
|
153
|
+
});
|
|
154
|
+
});
|
|
@@ -66,7 +66,7 @@ vi.mock("sharp", () => ({
|
|
|
66
66
|
|
|
67
67
|
// consola mock (logger assertion 필요)
|
|
68
68
|
const mockLoggerWarn = vi.fn();
|
|
69
|
-
vi.spyOn(consola, "withTag").mockReturnValue({ debug: vi.fn(), warn: mockLoggerWarn, error: vi.fn(), info: vi.fn(), success: vi.fn() } as any);
|
|
69
|
+
vi.spyOn(consola, "withTag").mockReturnValue({ debug: vi.fn(), warn: mockLoggerWarn, error: vi.fn(), info: vi.fn(), success: vi.fn(), start: vi.fn() } as any);
|
|
70
70
|
|
|
71
71
|
//#endregion
|
|
72
72
|
|
|
@@ -66,7 +66,7 @@ vi.mock("sharp", () => ({ default: mockSharp }));
|
|
|
66
66
|
|
|
67
67
|
// consola mock (logger assertion 필요)
|
|
68
68
|
const mockLoggerWarn = vi.fn();
|
|
69
|
-
vi.spyOn(consola, "withTag").mockReturnValue({ debug: vi.fn(), warn: mockLoggerWarn, error: vi.fn(), info: vi.fn(), success: vi.fn() } as any);
|
|
69
|
+
vi.spyOn(consola, "withTag").mockReturnValue({ debug: vi.fn(), warn: mockLoggerWarn, error: vi.fn(), info: vi.fn(), success: vi.fn(), start: vi.fn() } as any);
|
|
70
70
|
|
|
71
71
|
//#endregion
|
|
72
72
|
|
|
@@ -62,7 +62,7 @@ vi.mock("sharp", () => ({
|
|
|
62
62
|
}));
|
|
63
63
|
|
|
64
64
|
const mockLoggerWarn = vi.fn();
|
|
65
|
-
vi.spyOn(consola, "withTag").mockReturnValue({ debug: vi.fn(), warn: mockLoggerWarn, error: vi.fn(), info: vi.fn(), success: vi.fn() } as any);
|
|
65
|
+
vi.spyOn(consola, "withTag").mockReturnValue({ debug: vi.fn(), warn: mockLoggerWarn, error: vi.fn(), info: vi.fn(), success: vi.fn(), start: vi.fn() } as any);
|
|
66
66
|
|
|
67
67
|
//#endregion
|
|
68
68
|
|
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import { consola } from "consola";
|
|
3
|
+
|
|
4
|
+
const mockLogger = {
|
|
5
|
+
debug: vi.fn(),
|
|
6
|
+
info: vi.fn(),
|
|
7
|
+
warn: vi.fn(),
|
|
8
|
+
error: vi.fn(),
|
|
9
|
+
start: vi.fn(),
|
|
10
|
+
success: vi.fn(),
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
vi.spyOn(consola, "withTag").mockReturnValue(mockLogger as any);
|
|
2
14
|
|
|
3
15
|
const mocks = vi.hoisted(() => ({
|
|
4
16
|
executeTypecheck: vi.fn(),
|
|
5
17
|
executeLint: vi.fn(),
|
|
6
18
|
runLintInWorker: vi.fn(),
|
|
7
|
-
execa: vi.fn(),
|
|
8
19
|
loadSdConfig: vi.fn(),
|
|
9
20
|
discoverWorkspacePackages: vi.fn(),
|
|
10
21
|
}));
|
|
@@ -25,13 +36,6 @@ vi.mock("../../src/utils/sd-config", () => ({
|
|
|
25
36
|
loadSdConfig: mocks.loadSdConfig,
|
|
26
37
|
}));
|
|
27
38
|
|
|
28
|
-
vi.mock("@simplysm/core-node", () => ({
|
|
29
|
-
cpx: {
|
|
30
|
-
spawn: mocks.execa,
|
|
31
|
-
spawnSync: vi.fn().mockReturnValue({ stdout: "", stderr: "", exitCode: 0 }),
|
|
32
|
-
},
|
|
33
|
-
}));
|
|
34
|
-
|
|
35
39
|
vi.mock("../../src/utils/package-utils", async (importOriginal) => {
|
|
36
40
|
const actual = await importOriginal<typeof import("../../src/utils/package-utils")>();
|
|
37
41
|
return {
|
|
@@ -42,20 +46,21 @@ vi.mock("../../src/utils/package-utils", async (importOriginal) => {
|
|
|
42
46
|
|
|
43
47
|
const { runCheck } = await import("../../src/commands/check");
|
|
44
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Collects all calls to the given mock function's first argument into an array,
|
|
51
|
+
* preserving call order for sequential assertions.
|
|
52
|
+
*/
|
|
53
|
+
function collectArgs(fn: ReturnType<typeof vi.fn>): string[] {
|
|
54
|
+
return fn.mock.calls.map((call) => String(call[0]));
|
|
55
|
+
}
|
|
56
|
+
|
|
45
57
|
describe("runCheck", () => {
|
|
46
58
|
let savedExitCode: typeof process.exitCode;
|
|
47
|
-
let writeSpy: ReturnType<typeof vi.spyOn>;
|
|
48
|
-
let stdoutOutput: string;
|
|
49
59
|
|
|
50
60
|
beforeEach(() => {
|
|
51
61
|
vi.clearAllMocks();
|
|
52
62
|
savedExitCode = process.exitCode;
|
|
53
63
|
process.exitCode = undefined;
|
|
54
|
-
stdoutOutput = "";
|
|
55
|
-
writeSpy = vi.spyOn(process.stdout, "write").mockImplementation((chunk: unknown) => {
|
|
56
|
-
stdoutOutput += String(chunk);
|
|
57
|
-
return true;
|
|
58
|
-
});
|
|
59
64
|
|
|
60
65
|
// Default: workspace packages
|
|
61
66
|
mocks.discoverWorkspacePackages.mockReturnValue(
|
|
@@ -89,41 +94,22 @@ describe("runCheck", () => {
|
|
|
89
94
|
mocks.runLintInWorker.mockResolvedValue({
|
|
90
95
|
success: true, errorCount: 0, warningCount: 0, formattedOutput: "",
|
|
91
96
|
});
|
|
92
|
-
mocks.execa.mockResolvedValue({
|
|
93
|
-
stdout: "Tests 1 passed", stderr: "", exitCode: 0,
|
|
94
|
-
});
|
|
95
97
|
});
|
|
96
98
|
|
|
97
99
|
afterEach(() => {
|
|
98
100
|
process.exitCode = savedExitCode;
|
|
99
|
-
writeSpy.mockRestore();
|
|
100
101
|
});
|
|
101
102
|
|
|
102
|
-
it("
|
|
103
|
-
await runCheck({ targets: [], types: ["typecheck", "lint"
|
|
104
|
-
|
|
105
|
-
expect(stdoutOutput).toContain("TYPECHECK");
|
|
106
|
-
expect(stdoutOutput).toContain("TEST");
|
|
107
|
-
});
|
|
103
|
+
it("outputs success sections in TYPECHECK → LINT order via logger.success", async () => {
|
|
104
|
+
await runCheck({ targets: [], types: ["typecheck", "lint"], fix: false });
|
|
108
105
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
const tcIdx = stdoutOutput.indexOf("TYPECHECK");
|
|
113
|
-
const lintIdx = stdoutOutput.indexOf("LINT");
|
|
114
|
-
const testIdx = stdoutOutput.indexOf("TEST");
|
|
115
|
-
const summaryIdx = stdoutOutput.indexOf("요약");
|
|
106
|
+
const successArgs = collectArgs(mockLogger.success);
|
|
107
|
+
const tcIdx = successArgs.findIndex((a) => a.includes("TYPECHECK"));
|
|
108
|
+
const lintIdx = successArgs.findIndex((a) => a.includes("LINT"));
|
|
116
109
|
|
|
110
|
+
expect(tcIdx).toBeGreaterThanOrEqual(0);
|
|
111
|
+
expect(lintIdx).toBeGreaterThanOrEqual(0);
|
|
117
112
|
expect(tcIdx).toBeLessThan(lintIdx);
|
|
118
|
-
expect(lintIdx).toBeLessThan(testIdx);
|
|
119
|
-
expect(testIdx).toBeLessThan(summaryIdx);
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
it("runs only specified check types", async () => {
|
|
123
|
-
await runCheck({ targets: [], types: ["test"], fix: false });
|
|
124
|
-
|
|
125
|
-
expect(stdoutOutput).not.toContain("TYPECHECK");
|
|
126
|
-
expect(stdoutOutput).toContain("TEST");
|
|
127
113
|
});
|
|
128
114
|
|
|
129
115
|
it("sets exitCode 1 when typecheck fails", async () => {
|
|
@@ -133,35 +119,52 @@ describe("runCheck", () => {
|
|
|
133
119
|
scriptsPackagePaths: [],
|
|
134
120
|
});
|
|
135
121
|
|
|
136
|
-
await runCheck({ targets: [], types: ["typecheck", "lint"
|
|
122
|
+
await runCheck({ targets: [], types: ["typecheck", "lint"], fix: false });
|
|
137
123
|
|
|
138
124
|
expect(process.exitCode).toBe(1);
|
|
139
125
|
});
|
|
140
126
|
|
|
141
|
-
it("
|
|
142
|
-
mocks.
|
|
143
|
-
success: false, errorCount:
|
|
127
|
+
it("outputs failed section via logger.error with formattedOutput", async () => {
|
|
128
|
+
mocks.executeTypecheck.mockResolvedValue({
|
|
129
|
+
success: false, errorCount: 2, warningCount: 0, formattedOutput: "type errors",
|
|
130
|
+
lint: { success: true, errorCount: 0, warningCount: 0, formattedOutput: "" },
|
|
131
|
+
scriptsPackagePaths: [],
|
|
144
132
|
});
|
|
145
133
|
|
|
146
|
-
await runCheck({ targets: [], types: ["lint"], fix: false });
|
|
134
|
+
await runCheck({ targets: [], types: ["typecheck", "lint"], fix: false });
|
|
147
135
|
|
|
148
|
-
|
|
136
|
+
const errorArgs = collectArgs(mockLogger.error);
|
|
137
|
+
expect(errorArgs.some((a) => a.includes("TYPECHECK"))).toBe(true);
|
|
138
|
+
expect(errorArgs.some((a) => a.includes("type errors"))).toBe(true);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it("outputs success summary via logger.success when all pass", async () => {
|
|
142
|
+
await runCheck({ targets: [], types: ["typecheck", "lint"], fix: false });
|
|
143
|
+
|
|
144
|
+
const successArgs = collectArgs(mockLogger.success);
|
|
145
|
+
expect(successArgs.some((a) => a.includes("전체 통과"))).toBe(true);
|
|
149
146
|
});
|
|
150
147
|
|
|
151
|
-
it("
|
|
152
|
-
mocks.
|
|
153
|
-
|
|
148
|
+
it("outputs failure summary via logger.error when any fails", async () => {
|
|
149
|
+
mocks.executeTypecheck.mockResolvedValue({
|
|
150
|
+
success: false, errorCount: 1, warningCount: 0, formattedOutput: "err",
|
|
151
|
+
lint: { success: true, errorCount: 0, warningCount: 0, formattedOutput: "" },
|
|
152
|
+
scriptsPackagePaths: [],
|
|
154
153
|
});
|
|
155
154
|
|
|
156
|
-
await runCheck({ targets: [], types: ["
|
|
155
|
+
await runCheck({ targets: [], types: ["typecheck", "lint"], fix: false });
|
|
157
156
|
|
|
158
|
-
|
|
157
|
+
const errorArgs = collectArgs(mockLogger.error);
|
|
158
|
+
expect(errorArgs.some((a) => a.includes("실패"))).toBe(true);
|
|
159
|
+
expect(errorArgs.some((a) => a.includes("합계"))).toBe(true);
|
|
159
160
|
});
|
|
160
161
|
|
|
161
|
-
it("
|
|
162
|
-
mocks.
|
|
162
|
+
it("sets exitCode to 1 when lint fails", async () => {
|
|
163
|
+
mocks.executeLint.mockResolvedValue({
|
|
164
|
+
success: false, errorCount: 1, warningCount: 0, formattedOutput: "lint errors",
|
|
165
|
+
});
|
|
163
166
|
|
|
164
|
-
await runCheck({ targets: [], types: ["
|
|
167
|
+
await runCheck({ targets: [], types: ["lint"], fix: false });
|
|
165
168
|
|
|
166
169
|
expect(process.exitCode).toBe(1);
|
|
167
170
|
});
|
|
@@ -179,51 +182,45 @@ describe("runCheck", () => {
|
|
|
179
182
|
it("resolves package target to packages/ path", async () => {
|
|
180
183
|
await runCheck({ targets: ["core-node"], types: ["typecheck"], fix: false });
|
|
181
184
|
|
|
182
|
-
|
|
185
|
+
const successArgs = collectArgs(mockLogger.success);
|
|
186
|
+
expect(successArgs.some((a) => a.includes("TYPECHECK"))).toBe(true);
|
|
183
187
|
expect(process.exitCode).toBeUndefined();
|
|
184
188
|
});
|
|
185
189
|
|
|
186
190
|
it("resolves test directory target to tests/ path", async () => {
|
|
187
191
|
await runCheck({ targets: ["orm"], types: ["typecheck"], fix: false });
|
|
188
192
|
|
|
189
|
-
|
|
193
|
+
const successArgs = collectArgs(mockLogger.success);
|
|
194
|
+
expect(successArgs.some((a) => a.includes("TYPECHECK"))).toBe(true);
|
|
190
195
|
expect(process.exitCode).toBeUndefined();
|
|
191
196
|
});
|
|
192
197
|
|
|
193
198
|
it("resolves mixed targets to correct paths", async () => {
|
|
194
199
|
await runCheck({ targets: ["core-node", "orm"], types: ["typecheck"], fix: false });
|
|
195
200
|
|
|
196
|
-
|
|
201
|
+
const successArgs = collectArgs(mockLogger.success);
|
|
202
|
+
expect(successArgs.some((a) => a.includes("TYPECHECK"))).toBe(true);
|
|
197
203
|
expect(process.exitCode).toBeUndefined();
|
|
198
204
|
});
|
|
199
205
|
|
|
200
206
|
it("resolves lint target to correct path", async () => {
|
|
201
207
|
await runCheck({ targets: ["orm"], types: ["lint"], fix: false });
|
|
202
208
|
|
|
203
|
-
|
|
209
|
+
const successArgs = collectArgs(mockLogger.success);
|
|
210
|
+
expect(successArgs.some((a) => a.includes("LINT"))).toBe(true);
|
|
204
211
|
expect(process.exitCode).toBeUndefined();
|
|
205
212
|
});
|
|
206
213
|
|
|
207
|
-
it("passes resolved paths to vitest", async () => {
|
|
208
|
-
await runCheck({ targets: ["orm"], types: ["test"], fix: false });
|
|
209
|
-
|
|
210
|
-
expect(mocks.execa).toHaveBeenCalledWith(
|
|
211
|
-
"pnpm",
|
|
212
|
-
["vitest", "tests/orm", "--run"],
|
|
213
|
-
expect.any(Object),
|
|
214
|
-
);
|
|
215
|
-
});
|
|
216
|
-
|
|
217
214
|
it("passes empty targets for all when no targets specified", async () => {
|
|
218
215
|
await runCheck({ targets: [], types: ["typecheck"], fix: false });
|
|
219
216
|
|
|
220
|
-
|
|
217
|
+
const successArgs = collectArgs(mockLogger.success);
|
|
218
|
+
expect(successArgs.some((a) => a.includes("TYPECHECK"))).toBe(true);
|
|
221
219
|
expect(process.exitCode).toBeUndefined();
|
|
222
220
|
});
|
|
223
221
|
|
|
224
222
|
describe("lint via engine integration", () => {
|
|
225
223
|
beforeEach(() => {
|
|
226
|
-
// Default: executeTypecheck returns lint result and scriptsPackagePaths
|
|
227
224
|
mocks.executeTypecheck.mockResolvedValue({
|
|
228
225
|
success: true, errorCount: 0, warningCount: 0, formattedOutput: "",
|
|
229
226
|
lint: { success: true, errorCount: 0, warningCount: 0, formattedOutput: "" },
|
|
@@ -231,15 +228,14 @@ describe("runCheck", () => {
|
|
|
231
228
|
});
|
|
232
229
|
});
|
|
233
230
|
|
|
234
|
-
// Scenario: typecheck+lint 요청 시 TYPECHECK과 LINT 섹션이 출력된다
|
|
235
231
|
it("outputs TYPECHECK and LINT sections when both are requested", async () => {
|
|
236
232
|
await runCheck({ targets: [], types: ["typecheck", "lint"], fix: false });
|
|
237
233
|
|
|
238
|
-
|
|
239
|
-
expect(
|
|
234
|
+
const successArgs = collectArgs(mockLogger.success);
|
|
235
|
+
expect(successArgs.some((a) => a.includes("TYPECHECK"))).toBe(true);
|
|
236
|
+
expect(successArgs.some((a) => a.includes("LINT"))).toBe(true);
|
|
240
237
|
});
|
|
241
238
|
|
|
242
|
-
// Scenario: lint 실패 시 exitCode 설정
|
|
243
239
|
it("sets exitCode 1 when engine lint fails", async () => {
|
|
244
240
|
mocks.executeTypecheck.mockResolvedValue({
|
|
245
241
|
success: true, errorCount: 0, warningCount: 0, formattedOutput: "",
|
|
@@ -252,7 +248,6 @@ describe("runCheck", () => {
|
|
|
252
248
|
expect(process.exitCode).toBe(1);
|
|
253
249
|
});
|
|
254
250
|
|
|
255
|
-
// Scenario: scripts 패키지 포함 시 lint가 성공한다
|
|
256
251
|
it("succeeds when scriptsPackagePaths is non-empty", async () => {
|
|
257
252
|
mocks.executeTypecheck.mockResolvedValue({
|
|
258
253
|
success: true, errorCount: 0, warningCount: 0, formattedOutput: "",
|
|
@@ -265,69 +260,62 @@ describe("runCheck", () => {
|
|
|
265
260
|
|
|
266
261
|
await runCheck({ targets: [], types: ["typecheck", "lint"], fix: false });
|
|
267
262
|
|
|
268
|
-
|
|
263
|
+
const successArgs = collectArgs(mockLogger.success);
|
|
264
|
+
expect(successArgs.some((a) => a.includes("LINT"))).toBe(true);
|
|
269
265
|
expect(process.exitCode).toBeUndefined();
|
|
270
266
|
});
|
|
271
267
|
});
|
|
272
268
|
|
|
273
269
|
describe("lint-only path", () => {
|
|
274
|
-
// Scenario: lint만 요청 시 LINT 섹션만 출력된다
|
|
275
270
|
it("outputs LINT section when only lint type is requested", async () => {
|
|
276
271
|
await runCheck({ targets: [], types: ["lint"], fix: false });
|
|
277
272
|
|
|
278
|
-
|
|
279
|
-
expect(
|
|
273
|
+
const successArgs = collectArgs(mockLogger.success);
|
|
274
|
+
expect(successArgs.some((a) => a.includes("LINT"))).toBe(true);
|
|
275
|
+
const allArgs = [...collectArgs(mockLogger.success), ...collectArgs(mockLogger.error)];
|
|
276
|
+
expect(allArgs.some((a) => a.includes("TYPECHECK"))).toBe(false);
|
|
280
277
|
});
|
|
281
278
|
|
|
282
|
-
// Scenario: lint,test 요청 시 LINT과 TEST 섹션 출력 (TYPECHECK 없음)
|
|
283
|
-
it("outputs LINT and TEST sections when lint,test are requested", async () => {
|
|
284
|
-
await runCheck({ targets: [], types: ["lint", "test"], fix: false });
|
|
285
|
-
|
|
286
|
-
expect(stdoutOutput).toContain("LINT");
|
|
287
|
-
expect(stdoutOutput).toContain("TEST");
|
|
288
|
-
expect(stdoutOutput).not.toContain("TYPECHECK");
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
// Scenario: scripts 패키지 포함 전체 lint
|
|
292
279
|
it("handles all packages via lint including scripts", async () => {
|
|
293
280
|
mocks.discoverWorkspacePackages.mockReturnValue(
|
|
294
281
|
new Map([
|
|
295
282
|
["core-common", "packages/core-common"],
|
|
296
|
-
["sd-claude", "packages/sd-claude"],
|
|
283
|
+
["sd-claude", "packages/sd-claude"],
|
|
297
284
|
]),
|
|
298
285
|
);
|
|
299
286
|
|
|
300
287
|
await runCheck({ targets: [], types: ["lint"], fix: false });
|
|
301
288
|
|
|
302
|
-
|
|
303
|
-
expect(
|
|
289
|
+
const successArgs = collectArgs(mockLogger.success);
|
|
290
|
+
expect(successArgs.some((a) => a.includes("LINT"))).toBe(true);
|
|
291
|
+
const allArgs = [...collectArgs(mockLogger.success), ...collectArgs(mockLogger.error)];
|
|
292
|
+
expect(allArgs.some((a) => a.includes("TYPECHECK"))).toBe(false);
|
|
304
293
|
});
|
|
305
294
|
|
|
306
|
-
// Scenario: 특정 타겟 지정 lint
|
|
307
295
|
it("succeeds with normalized target paths for lint", async () => {
|
|
308
296
|
await runCheck({ targets: ["core-common"], types: ["lint"], fix: false });
|
|
309
297
|
|
|
310
|
-
|
|
298
|
+
const successArgs = collectArgs(mockLogger.success);
|
|
299
|
+
expect(successArgs.some((a) => a.includes("LINT"))).toBe(true);
|
|
311
300
|
expect(process.exitCode).toBeUndefined();
|
|
312
301
|
});
|
|
313
302
|
|
|
314
|
-
// Scenario: --fix 옵션으로 자동 수정
|
|
315
303
|
it("succeeds when --fix is specified", async () => {
|
|
316
304
|
await runCheck({ targets: [], types: ["lint"], fix: true });
|
|
317
305
|
|
|
318
|
-
|
|
306
|
+
const successArgs = collectArgs(mockLogger.success);
|
|
307
|
+
expect(successArgs.some((a) => a.includes("LINT"))).toBe(true);
|
|
319
308
|
expect(process.exitCode).toBeUndefined();
|
|
320
309
|
});
|
|
321
310
|
|
|
322
|
-
// Scenario: --fix 없이 실행
|
|
323
311
|
it("succeeds when --fix is not specified", async () => {
|
|
324
312
|
await runCheck({ targets: [], types: ["lint"], fix: false });
|
|
325
313
|
|
|
326
|
-
|
|
314
|
+
const successArgs = collectArgs(mockLogger.success);
|
|
315
|
+
expect(successArgs.some((a) => a.includes("LINT"))).toBe(true);
|
|
327
316
|
expect(process.exitCode).toBeUndefined();
|
|
328
317
|
});
|
|
329
318
|
|
|
330
|
-
// Scenario: lint 에러 없음
|
|
331
319
|
it("does not set exitCode when lint passes", async () => {
|
|
332
320
|
mocks.executeLint.mockResolvedValue({
|
|
333
321
|
success: true, errorCount: 0, warningCount: 0, formattedOutput: "",
|
|
@@ -338,7 +326,6 @@ describe("runCheck", () => {
|
|
|
338
326
|
expect(process.exitCode).toBeUndefined();
|
|
339
327
|
});
|
|
340
328
|
|
|
341
|
-
// Scenario: lint 에러 발생
|
|
342
329
|
it("sets exitCode 1 when lint has errors", async () => {
|
|
343
330
|
mocks.executeLint.mockResolvedValue({
|
|
344
331
|
success: false, errorCount: 3, warningCount: 2, formattedOutput: "lint errors",
|
|
@@ -349,12 +336,11 @@ describe("runCheck", () => {
|
|
|
349
336
|
expect(process.exitCode).toBe(1);
|
|
350
337
|
});
|
|
351
338
|
|
|
352
|
-
// typecheck 관련 로그 메시지가 출력되지 않는다
|
|
353
339
|
it("does not output typecheck-related sections when only lint is requested", async () => {
|
|
354
340
|
await runCheck({ targets: [], types: ["lint"], fix: false });
|
|
355
341
|
|
|
356
|
-
|
|
342
|
+
const allArgs = [...collectArgs(mockLogger.success), ...collectArgs(mockLogger.error)];
|
|
343
|
+
expect(allArgs.some((a) => a.includes("TYPECHECK"))).toBe(false);
|
|
357
344
|
});
|
|
358
345
|
});
|
|
359
|
-
|
|
360
346
|
});
|
|
@@ -298,8 +298,16 @@ describe("runPublish", () => {
|
|
|
298
298
|
},
|
|
299
299
|
});
|
|
300
300
|
|
|
301
|
-
const
|
|
301
|
+
const { consola } = await import("consola");
|
|
302
|
+
const infoSpy = vi.fn();
|
|
303
|
+
const origWithTag = consola.withTag.bind(consola);
|
|
304
|
+
const withTagSpy = vi.spyOn(consola, "withTag").mockImplementation((tag: string) => {
|
|
305
|
+
const logger = origWithTag(tag);
|
|
306
|
+
logger.info = infoSpy as any;
|
|
307
|
+
return logger;
|
|
308
|
+
});
|
|
302
309
|
|
|
310
|
+
// Re-import to pick up the spy (module already loaded, but logger is created at call time)
|
|
303
311
|
await runPublish({
|
|
304
312
|
targets: [],
|
|
305
313
|
noBuild: false,
|
|
@@ -307,9 +315,9 @@ describe("runPublish", () => {
|
|
|
307
315
|
options: [],
|
|
308
316
|
});
|
|
309
317
|
|
|
310
|
-
const
|
|
311
|
-
expect(
|
|
312
|
-
|
|
318
|
+
const infoArgs = infoSpy.mock.calls.map((c: unknown[]) => String(c[0]));
|
|
319
|
+
expect(infoArgs.some((a: string) => a.includes("배포할 패키지가 없습니다"))).toBe(true);
|
|
320
|
+
withTagSpy.mockRestore();
|
|
313
321
|
});
|
|
314
322
|
});
|
|
315
323
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Slice 3: severity 정리 — LLM 검증
|
|
2
|
+
|
|
3
|
+
## 검증 항목
|
|
4
|
+
|
|
5
|
+
- [x] replace-deps.ts:5 — `const logger = consola.withTag("sd:cli:replace-deps")` 모듈-레벨 로거 추가 확인
|
|
6
|
+
- [x] replace-deps.ts:24 — `consola.warn(...)` → `logger.warn(...)` 변경 확인
|
|
7
|
+
- [x] deployment-phase.ts:66-70 — DRY-RUN 성공 메시지 `debug` → `info` 전환 확인: `dryRun ? logger.info("[DRY-RUN] ...") : logger.debug(...)`
|
|
8
|
+
- [x] deployment-phase.ts:76-80 — DRY-RUN 재시도 메시지 `debug` → `info` 전환 확인: 동일 패턴
|
|
9
|
+
- [x] deployment-phase.ts:102 — `logger.fail(...)` → `logger.error(...)` 전환 확인
|
|
10
|
+
- [x] BuildOrchestrator.ts:251 — `this._logger.success("빌드 실행 완료")` 행 제거 확인: 250행 뒤에 바로 `return` 문
|
|
11
|
+
- [x] BuildOrchestrator.ts:477 — `this._logger.info("빌드 완료")` → `this._logger.success("빌드 완료")` 전환 확인
|
|
12
|
+
- [x] BuildOrchestrator.ts:232-233 — `this._logger.start("빌드 실행 중...")` 유지 확인: start(232)/success(477) 쌍 정상화
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import os from "os";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { collectDeps } from "../../../src/deps/replace-deps/collect-deps";
|
|
6
|
+
import { pathx } from "@simplysm/core-node";
|
|
7
|
+
|
|
8
|
+
describe("collectDeps — tests/ 패키지 제외", () => {
|
|
9
|
+
let tmpDir: string;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
tmpDir = pathx.posix(fs.mkdtempSync(path.join(os.tmpdir(), "sd-cli-test-")));
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
function createPkg(relDir: string, name: string, deps: Record<string, string> = {}): void {
|
|
20
|
+
const dir = pathx.posix(path.join(tmpDir, relDir));
|
|
21
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
22
|
+
fs.writeFileSync(
|
|
23
|
+
pathx.posix(path.join(dir, "package.json")),
|
|
24
|
+
JSON.stringify({ name, dependencies: deps }),
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Scenario: packages/ 패키지는 워크스페이스 맵에 포함된다
|
|
29
|
+
it("packages/ 패키지를 workspaceDeps에 포함한다", () => {
|
|
30
|
+
createPkg("packages/core-common", "@test/core-common");
|
|
31
|
+
createPkg("packages/my-lib", "@test/my-lib", { "@test/core-common": "workspace:*" });
|
|
32
|
+
|
|
33
|
+
const result = collectDeps(pathx.posix(path.join(tmpDir, "packages/my-lib")), tmpDir);
|
|
34
|
+
|
|
35
|
+
expect(result.workspaceDeps).toContain("core-common");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Scenario: tests/ 패키지는 워크스페이스 맵에서 제외된다
|
|
39
|
+
it("tests/ 패키지를 workspaceDeps에 포함하지 않는다", () => {
|
|
40
|
+
createPkg("packages/my-lib", "@test/my-lib", { "@test/orm": "workspace:*" });
|
|
41
|
+
createPkg("tests/orm", "@test/orm");
|
|
42
|
+
|
|
43
|
+
const result = collectDeps(pathx.posix(path.join(tmpDir, "packages/my-lib")), tmpDir);
|
|
44
|
+
|
|
45
|
+
expect(result.workspaceDeps).not.toContain("orm");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Scenario: 패키지의 dependency에 tests/ 패키지가 있으면 workspaceDeps에서 무시된다
|
|
49
|
+
it("dependency에 tests/ 패키지가 있어도 workspaceDeps에서 무시한다", () => {
|
|
50
|
+
createPkg("packages/core-common", "@test/core-common");
|
|
51
|
+
createPkg("tests/orm", "@test/orm");
|
|
52
|
+
createPkg("packages/my-lib", "@test/my-lib", {
|
|
53
|
+
"@test/core-common": "workspace:*",
|
|
54
|
+
"@test/orm": "workspace:*",
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const result = collectDeps(pathx.posix(path.join(tmpDir, "packages/my-lib")), tmpDir);
|
|
58
|
+
|
|
59
|
+
expect(result.workspaceDeps).toContain("core-common");
|
|
60
|
+
expect(result.workspaceDeps).not.toContain("orm");
|
|
61
|
+
});
|
|
62
|
+
});
|