@simplysm/sd-cli 14.0.42 → 14.0.44
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 +41 -37
- package/dist/angular/ngtsc-build-core.d.ts.map +1 -1
- package/dist/angular/ngtsc-build-core.js +155 -52
- 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.d.ts.map +1 -1
- package/dist/commands/publish/version-upgrade.js +16 -13
- 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-resolve.d.ts.map +1 -1
- package/dist/deps/replace-deps/replace-deps-resolve.js +6 -7
- package/dist/deps/replace-deps/replace-deps-resolve.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 +175 -66
- 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-postcss-plugin.d.ts.map +1 -1
- package/dist/esbuild/esbuild-postcss-plugin.js +9 -6
- package/dist/esbuild/esbuild-postcss-plugin.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 +115 -110
- package/dist/workers/client.worker.js.map +1 -1
- package/dist/workers/incremental-mtime-tracker.d.ts +13 -0
- package/dist/workers/incremental-mtime-tracker.d.ts.map +1 -0
- package/dist/workers/incremental-mtime-tracker.js +65 -0
- package/dist/workers/incremental-mtime-tracker.js.map +1 -0
- 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 +169 -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 +5 -4
- package/src/angular/angular-compiler.ts +0 -502
- package/src/angular/hmr-candidates.ts +295 -0
- package/src/angular/ngtsc-build-core.ts +192 -91
- 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 +44 -35
- 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-resolve.ts +12 -7
- package/src/deps/replace-deps/replace-deps.ts +191 -69
- 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-postcss-plugin.ts +9 -6
- 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 +141 -126
- package/src/workers/incremental-mtime-tracker.ts +68 -0
- package/src/workers/library-build.worker.ts +214 -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/ngtsc-build-core.acc.spec.ts +210 -0
- package/tests/angular/ngtsc-build-core.spec.ts +52 -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/commands/version-upgrade.acc.spec.ts +210 -0
- package/tests/commands/version-upgrade.spec.ts +148 -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-perf.verify.md +15 -0
- package/tests/deps/replace-deps/replace-deps-resolve.acc.spec.ts +124 -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-postcss-plugin-chunking.verify.md +17 -0
- package/tests/esbuild/esbuild-postcss-plugin.acc.spec.ts +152 -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/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 +136 -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-mtime-incremental.verify.md +10 -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/incremental-mtime-tracker.acc.spec.ts +144 -0
- package/tests/workers/incremental-mtime-tracker.spec.ts +102 -0
- package/tests/workers/library-build-lint.spec.ts +40 -45
- package/tests/workers/library-build-worker.spec.ts +298 -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,148 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import os from "os";
|
|
5
|
+
import { upgradeVersion, computePublishLevels } from "../../src/commands/publish/version-upgrade";
|
|
6
|
+
|
|
7
|
+
function createTempDir(): string {
|
|
8
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), "sd-cli-vu-unit-"));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function writeJson(filePath: string, data: unknown): void {
|
|
12
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
13
|
+
fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function readJson<T>(filePath: string): T {
|
|
17
|
+
return JSON.parse(fs.readFileSync(filePath, "utf-8")) as T;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
describe("upgradeVersion — unit", () => {
|
|
21
|
+
let tmpDir: string;
|
|
22
|
+
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
tmpDir = createTempDir();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("prerelease 버전은 prerelease로 증가한다", async () => {
|
|
32
|
+
writeJson(path.join(tmpDir, "package.json"), {
|
|
33
|
+
name: "@simplysm/root",
|
|
34
|
+
version: "14.0.0-beta.3",
|
|
35
|
+
});
|
|
36
|
+
fs.mkdirSync(path.join(tmpDir, "packages", "sd-cli", "templates"), {
|
|
37
|
+
recursive: true,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const result = await upgradeVersion(tmpDir, [], false);
|
|
41
|
+
expect(result.version).toBe("14.0.0-beta.4");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("dryRun이면 파일을 수정하지 않고 새 버전만 반환한다", async () => {
|
|
45
|
+
writeJson(path.join(tmpDir, "package.json"), {
|
|
46
|
+
name: "@simplysm/root",
|
|
47
|
+
version: "14.0.0",
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const pkgDir = path.join(tmpDir, "packages", "pkg-a");
|
|
51
|
+
writeJson(path.join(pkgDir, "package.json"), {
|
|
52
|
+
name: "@simplysm/pkg-a",
|
|
53
|
+
version: "14.0.0",
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const result = await upgradeVersion(tmpDir, [pkgDir], true);
|
|
57
|
+
expect(result.version).toBe("14.0.1");
|
|
58
|
+
expect(result.changedFiles).toHaveLength(0);
|
|
59
|
+
|
|
60
|
+
// 파일이 수정되지 않았는지 확인
|
|
61
|
+
const rootPkg = readJson<{ version: string }>(path.join(tmpDir, "package.json"));
|
|
62
|
+
expect(rootPkg.version).toBe("14.0.0");
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("템플릿 파일에서 @simplysm 버전이 없으면 수정하지 않는다", async () => {
|
|
66
|
+
writeJson(path.join(tmpDir, "package.json"), {
|
|
67
|
+
name: "@simplysm/root",
|
|
68
|
+
version: "14.0.0",
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const templatesDir = path.join(tmpDir, "packages", "sd-cli", "templates");
|
|
72
|
+
fs.mkdirSync(templatesDir, { recursive: true });
|
|
73
|
+
fs.writeFileSync(path.join(templatesDir, "no-version.hbs"), "plain template content", "utf-8");
|
|
74
|
+
|
|
75
|
+
const result = await upgradeVersion(tmpDir, [], false);
|
|
76
|
+
const templateChanges = result.changedFiles.filter((f) => f.endsWith(".hbs"));
|
|
77
|
+
expect(templateChanges).toHaveLength(0);
|
|
78
|
+
|
|
79
|
+
// 파일이 수정되지 않았는지 확인
|
|
80
|
+
expect(fs.readFileSync(path.join(templatesDir, "no-version.hbs"), "utf-8")).toBe(
|
|
81
|
+
"plain template content",
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe("computePublishLevels — unit", () => {
|
|
87
|
+
let tmpDir: string;
|
|
88
|
+
|
|
89
|
+
beforeEach(() => {
|
|
90
|
+
tmpDir = createTempDir();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
afterEach(() => {
|
|
94
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("의존성 없는 패키지들은 모두 Level 0이다", async () => {
|
|
98
|
+
const publishPkgs = ["pkg-a", "pkg-b", "pkg-c"].map((name) => {
|
|
99
|
+
const pkgDir = path.join(tmpDir, "packages", name);
|
|
100
|
+
writeJson(path.join(pkgDir, "package.json"), {
|
|
101
|
+
name: `@simplysm/${name}`,
|
|
102
|
+
version: "14.0.0",
|
|
103
|
+
dependencies: {},
|
|
104
|
+
});
|
|
105
|
+
return { name, path: pkgDir };
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const levels = await computePublishLevels(publishPkgs);
|
|
109
|
+
expect(levels).toHaveLength(1);
|
|
110
|
+
expect(levels[0].map((p) => p.name).sort()).toEqual(["pkg-a", "pkg-b", "pkg-c"]);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("외부 의존성(@simplysm/ 아닌)은 레벨 계산에 영향 없다", async () => {
|
|
114
|
+
const pkgDir = path.join(tmpDir, "packages", "pkg-a");
|
|
115
|
+
writeJson(path.join(pkgDir, "package.json"), {
|
|
116
|
+
name: "@simplysm/pkg-a",
|
|
117
|
+
version: "14.0.0",
|
|
118
|
+
dependencies: { lodash: "^4.0.0", express: "^5.0.0" },
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const levels = await computePublishLevels([{ name: "pkg-a", path: pkgDir }]);
|
|
122
|
+
expect(levels).toHaveLength(1);
|
|
123
|
+
expect(levels[0][0].name).toBe("pkg-a");
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it("peerDependencies와 optionalDependencies도 레벨에 반영된다", async () => {
|
|
127
|
+
const pkgADir = path.join(tmpDir, "packages", "pkg-a");
|
|
128
|
+
writeJson(path.join(pkgADir, "package.json"), {
|
|
129
|
+
name: "@simplysm/pkg-a",
|
|
130
|
+
version: "14.0.0",
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const pkgBDir = path.join(tmpDir, "packages", "pkg-b");
|
|
134
|
+
writeJson(path.join(pkgBDir, "package.json"), {
|
|
135
|
+
name: "@simplysm/pkg-b",
|
|
136
|
+
version: "14.0.0",
|
|
137
|
+
peerDependencies: { "@simplysm/pkg-a": "~14.0.0" },
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
const levels = await computePublishLevels([
|
|
141
|
+
{ name: "pkg-a", path: pkgADir },
|
|
142
|
+
{ name: "pkg-b", path: pkgBDir },
|
|
143
|
+
]);
|
|
144
|
+
expect(levels).toHaveLength(2);
|
|
145
|
+
expect(levels[0][0].name).toBe("pkg-a");
|
|
146
|
+
expect(levels[1][0].name).toBe("pkg-b");
|
|
147
|
+
});
|
|
148
|
+
});
|
|
@@ -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
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
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", () => {
|
|
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
|
+
it("tests/ 패키지만 의존하면 workspaceDeps가 빈 배열이다", () => {
|
|
29
|
+
createPkg("tests/orm", "@test/orm");
|
|
30
|
+
createPkg("tests/service", "@test/service");
|
|
31
|
+
createPkg("packages/my-lib", "@test/my-lib", {
|
|
32
|
+
"@test/orm": "workspace:*",
|
|
33
|
+
"@test/service": "workspace:*",
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const result = collectDeps(pathx.posix(path.join(tmpDir, "packages/my-lib")), tmpDir);
|
|
37
|
+
|
|
38
|
+
expect(result.workspaceDeps).toEqual([]);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("의존성이 없는 패키지는 빈 결과를 반환한다", () => {
|
|
42
|
+
createPkg("packages/my-lib", "@test/my-lib");
|
|
43
|
+
|
|
44
|
+
const result = collectDeps(pathx.posix(path.join(tmpDir, "packages/my-lib")), tmpDir);
|
|
45
|
+
|
|
46
|
+
expect(result.workspaceDeps).toEqual([]);
|
|
47
|
+
expect(result.replaceDeps).toEqual([]);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import os from "os";
|
|
5
|
+
import { pathx } from "@simplysm/core-node";
|
|
6
|
+
import {
|
|
7
|
+
createCopyFilter,
|
|
8
|
+
loadFilesField,
|
|
9
|
+
NPM_DEFAULT_FILE_PATTERN,
|
|
10
|
+
} from "../../../src/deps/replace-deps/replace-deps";
|
|
11
|
+
|
|
12
|
+
describe("NPM_DEFAULT_FILE_PATTERN", () => {
|
|
13
|
+
it("README 변형을 매칭한다", () => {
|
|
14
|
+
expect(NPM_DEFAULT_FILE_PATTERN.test("README")).toBe(true);
|
|
15
|
+
expect(NPM_DEFAULT_FILE_PATTERN.test("README.md")).toBe(true);
|
|
16
|
+
expect(NPM_DEFAULT_FILE_PATTERN.test("readme.txt")).toBe(true);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("LICENSE/LICENCE 변형을 매칭한다", () => {
|
|
20
|
+
expect(NPM_DEFAULT_FILE_PATTERN.test("LICENSE")).toBe(true);
|
|
21
|
+
expect(NPM_DEFAULT_FILE_PATTERN.test("LICENCE")).toBe(true);
|
|
22
|
+
expect(NPM_DEFAULT_FILE_PATTERN.test("license.md")).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("CHANGELOG/HISTORY 변형을 매칭한다", () => {
|
|
26
|
+
expect(NPM_DEFAULT_FILE_PATTERN.test("CHANGELOG")).toBe(true);
|
|
27
|
+
expect(NPM_DEFAULT_FILE_PATTERN.test("CHANGELOG.md")).toBe(true);
|
|
28
|
+
expect(NPM_DEFAULT_FILE_PATTERN.test("HISTORY.md")).toBe(true);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("관련없는 파일명은 매칭하지 않는다", () => {
|
|
32
|
+
expect(NPM_DEFAULT_FILE_PATTERN.test("tsconfig.json")).toBe(false);
|
|
33
|
+
expect(NPM_DEFAULT_FILE_PATTERN.test("CLAUDE.md")).toBe(false);
|
|
34
|
+
expect(NPM_DEFAULT_FILE_PATTERN.test("package.json")).toBe(false);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
describe("createCopyFilter", () => {
|
|
39
|
+
const sourcePath = "/source/pkg";
|
|
40
|
+
|
|
41
|
+
it("allowedNames에 포함된 첫 번째 세그먼트는 허용한다", () => {
|
|
42
|
+
const filter = createCopyFilter(sourcePath, new Set(["dist", "src"]));
|
|
43
|
+
|
|
44
|
+
expect(filter(path.join(sourcePath, "dist"))).toBe(true);
|
|
45
|
+
expect(filter(path.join(sourcePath, "src"))).toBe(true);
|
|
46
|
+
expect(filter(path.join(sourcePath, "dist", "index.js"))).toBe(true);
|
|
47
|
+
expect(filter(path.join(sourcePath, "src", "utils", "helper.ts"))).toBe(true);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("allowedNames에 없는 항목은 거부한다", () => {
|
|
51
|
+
const filter = createCopyFilter(sourcePath, new Set(["dist", "src"]));
|
|
52
|
+
|
|
53
|
+
expect(filter(path.join(sourcePath, "tsconfig.json"))).toBe(false);
|
|
54
|
+
expect(filter(path.join(sourcePath, "CLAUDE.md"))).toBe(false);
|
|
55
|
+
expect(filter(path.join(sourcePath, "node_modules"))).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("package.json은 항상 거부한다", () => {
|
|
59
|
+
const filter = createCopyFilter(sourcePath, new Set(["dist", "src"]));
|
|
60
|
+
|
|
61
|
+
expect(filter(path.join(sourcePath, "package.json"))).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("npm 기본 파일 패턴은 allowedNames에 없어도 허용한다", () => {
|
|
65
|
+
const filter = createCopyFilter(sourcePath, new Set(["dist"]));
|
|
66
|
+
|
|
67
|
+
expect(filter(path.join(sourcePath, "README.md"))).toBe(true);
|
|
68
|
+
expect(filter(path.join(sourcePath, "LICENSE"))).toBe(true);
|
|
69
|
+
expect(filter(path.join(sourcePath, "CHANGELOG.md"))).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe("loadFilesField", () => {
|
|
74
|
+
let tmpDir: string;
|
|
75
|
+
|
|
76
|
+
beforeEach(async () => {
|
|
77
|
+
tmpDir = pathx.posix(await fs.promises.mkdtemp(path.join(os.tmpdir(), "sd-load-files-")));
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
afterEach(async () => {
|
|
81
|
+
await fs.promises.rm(tmpDir, { recursive: true, force: true });
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("files 필드가 있으면 문자열 배열을 반환한다", async () => {
|
|
85
|
+
await fs.promises.writeFile(
|
|
86
|
+
pathx.posix(path.join(tmpDir, "package.json")),
|
|
87
|
+
JSON.stringify({ name: "test", files: ["dist", "src"] }),
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
const result = await loadFilesField(tmpDir);
|
|
91
|
+
expect(result).toEqual(["dist", "src"]);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("files 필드가 없으면 undefined를 반환한다", async () => {
|
|
95
|
+
await fs.promises.writeFile(
|
|
96
|
+
pathx.posix(path.join(tmpDir, "package.json")),
|
|
97
|
+
JSON.stringify({ name: "test" }),
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const result = await loadFilesField(tmpDir);
|
|
101
|
+
expect(result).toBeUndefined();
|
|
102
|
+
});
|
|
103
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# replace-deps 성능 최적화 — LLM 검증
|
|
2
|
+
|
|
3
|
+
## 검증 항목
|
|
4
|
+
|
|
5
|
+
### Slice 1: Set 중복 검사 + glob 병렬화
|
|
6
|
+
|
|
7
|
+
- [x] `resolveAllReplaceDepEntries`에서 `entries.some()` 대신 `Set<string>` 사용 확인: `replace-deps-resolve.ts:143`에 `seenTargetPaths = new Set<string>()` 선언, `:205`에서 `seenTargetPaths.has(actualTargetPath)` + `seenTargetPaths.add(actualTargetPath)` 사용. 기존 `entries.some()` 제거됨.
|
|
8
|
+
- [x] glob 병렬화 확인: `replace-deps-resolve.ts:167-171`에서 `Promise.all(Object.keys(replaceDeps).map(...))` 사용. 기존 순차 `for` 루프 제거됨. `:172-174`에서 `flatMap`으로 결과를 합침.
|
|
9
|
+
- [x] `seenTargetPaths`가 while 루프 바깥에 선언되어 재귀 탐색 전체에 걸쳐 중복 방지가 유지됨 확인.
|
|
10
|
+
|
|
11
|
+
### Slice 2: watch onChange entries 사전 필터링
|
|
12
|
+
|
|
13
|
+
- [x] `watchReplaceDeps`에서 사전 필터링 확인: `replace-deps.ts:240-242`에 `sourceEntries = entries.filter(e => e.resolvedSourcePath === entry.resolvedSourcePath)` 선언. watcher 생성 전에 필터링되어 클로저에 캡처됨.
|
|
14
|
+
- [x] onChange 내부에서 `sourceEntries`만 순회 확인: `replace-deps.ts:252`에서 `for (const e of sourceEntries)` 사용. 기존 `for (const e of entries)` + `if (e.resolvedSourcePath !== entry.resolvedSourcePath) continue;` 패턴이 제거됨.
|
|
15
|
+
- [x] `entries` 배열은 `resolveAllReplaceDepEntries` 호출 후 불변이므로, 필터링 결과가 watcher 생명주기 동안 유효함 확인 (`replace-deps.ts:202`에서 `entries` 할당 후 수정 없음).
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import os from "os";
|
|
5
|
+
import { pathx } from "@simplysm/core-node";
|
|
6
|
+
import { resolveAllReplaceDepEntries } from "../../../src/deps/replace-deps/replace-deps-resolve";
|
|
7
|
+
import { consola } from "consola";
|
|
8
|
+
|
|
9
|
+
describe("resolveAllReplaceDepEntries", () => {
|
|
10
|
+
let tmpDir: string;
|
|
11
|
+
let projectRoot: string;
|
|
12
|
+
const logger = consola.withTag("test");
|
|
13
|
+
|
|
14
|
+
beforeEach(async () => {
|
|
15
|
+
tmpDir = pathx.posix(await fs.promises.mkdtemp(path.join(os.tmpdir(), "sd-resolve-deps-")));
|
|
16
|
+
projectRoot = pathx.posix(path.join(tmpDir, "project"));
|
|
17
|
+
await fs.promises.mkdir(projectRoot, { recursive: true });
|
|
18
|
+
await fs.promises.writeFile(
|
|
19
|
+
pathx.posix(path.join(projectRoot, "pnpm-workspace.yaml")),
|
|
20
|
+
"packages:\n",
|
|
21
|
+
);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
afterEach(async () => {
|
|
25
|
+
await fs.promises.rm(tmpDir, { recursive: true, force: true });
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* node_modules에 패키지 디렉토리를 생성하는 헬퍼
|
|
30
|
+
*/
|
|
31
|
+
async function createNodeModulesPkg(
|
|
32
|
+
nodeModulesDir: string,
|
|
33
|
+
pkgName: string,
|
|
34
|
+
): Promise<string> {
|
|
35
|
+
const pkgDir = pathx.posix(path.join(nodeModulesDir, pkgName));
|
|
36
|
+
await fs.promises.mkdir(pkgDir, { recursive: true });
|
|
37
|
+
await fs.promises.writeFile(
|
|
38
|
+
pathx.posix(path.join(pkgDir, "package.json")),
|
|
39
|
+
JSON.stringify({ name: pkgName }),
|
|
40
|
+
);
|
|
41
|
+
return pkgDir;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 소스 패키지를 생성하는 헬퍼
|
|
46
|
+
*/
|
|
47
|
+
async function createSourcePkg(name: string): Promise<string> {
|
|
48
|
+
const sourcePath = pathx.posix(path.join(tmpDir, name));
|
|
49
|
+
await fs.promises.mkdir(sourcePath, { recursive: true });
|
|
50
|
+
await fs.promises.writeFile(
|
|
51
|
+
pathx.posix(path.join(sourcePath, "package.json")),
|
|
52
|
+
JSON.stringify({ name, files: ["dist"] }),
|
|
53
|
+
);
|
|
54
|
+
await fs.promises.mkdir(pathx.posix(path.join(sourcePath, "dist")), { recursive: true });
|
|
55
|
+
await fs.promises.writeFile(
|
|
56
|
+
pathx.posix(path.join(sourcePath, "dist", "index.js")),
|
|
57
|
+
"module.exports = {};",
|
|
58
|
+
);
|
|
59
|
+
return sourcePath;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
it("동일 actualTargetPath를 가진 항목은 중복 등록되지 않는다", async () => {
|
|
63
|
+
// Given: 루트 node_modules와 workspace pkg의 node_modules에 동일 패키지가 존재하고
|
|
64
|
+
// 둘 다 같은 실제 경로(symlink 해석 후)를 가리킨다
|
|
65
|
+
const sourcePath = await createSourcePkg("@test/pkg");
|
|
66
|
+
const nodeModulesDir = pathx.posix(path.join(projectRoot, "node_modules"));
|
|
67
|
+
await createNodeModulesPkg(nodeModulesDir, "@test/pkg");
|
|
68
|
+
|
|
69
|
+
// workspace 패키지 설정 (pnpm-workspace.yaml에 추가)
|
|
70
|
+
const workspacePkgDir = pathx.posix(path.join(projectRoot, "packages", "my-app"));
|
|
71
|
+
await fs.promises.mkdir(workspacePkgDir, { recursive: true });
|
|
72
|
+
await fs.promises.writeFile(
|
|
73
|
+
pathx.posix(path.join(projectRoot, "pnpm-workspace.yaml")),
|
|
74
|
+
"packages:\n - packages/*\n",
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// workspace 패키지의 node_modules에도 동일 패키지 생성
|
|
78
|
+
const wsPkgNodeModules = pathx.posix(path.join(workspacePkgDir, "node_modules"));
|
|
79
|
+
await createNodeModulesPkg(wsPkgNodeModules, "@test/pkg");
|
|
80
|
+
|
|
81
|
+
// When
|
|
82
|
+
const entries = await resolveAllReplaceDepEntries(
|
|
83
|
+
projectRoot,
|
|
84
|
+
{ "@test/pkg": sourcePath },
|
|
85
|
+
logger,
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
// Then: actualTargetPath가 다르므로 2개가 반환되어야 한다
|
|
89
|
+
// (symlink가 아닌 실제 디렉토리이므로 actualTargetPath가 각각 다름)
|
|
90
|
+
// 중복 방지 로직은 동일 actualTargetPath일 때만 작동한다
|
|
91
|
+
const actualTargetPaths = entries.map((e) => e.actualTargetPath);
|
|
92
|
+
const uniqueActualTargetPaths = new Set(actualTargetPaths);
|
|
93
|
+
expect(actualTargetPaths.length).toBe(uniqueActualTargetPaths.size);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("여러 replaceDeps 패턴이 올바르게 매칭되어 결과를 반환한다", async () => {
|
|
97
|
+
// Given: 2개의 다른 패턴과 각각의 소스 패키지
|
|
98
|
+
const sourceA = await createSourcePkg("@test/pkg-a");
|
|
99
|
+
const sourceB = await createSourcePkg("@other/lib");
|
|
100
|
+
const nodeModulesDir = pathx.posix(path.join(projectRoot, "node_modules"));
|
|
101
|
+
await createNodeModulesPkg(nodeModulesDir, "@test/pkg-a");
|
|
102
|
+
await createNodeModulesPkg(nodeModulesDir, "@other/lib");
|
|
103
|
+
|
|
104
|
+
// When: 2개 패턴으로 호출 (glob이 병렬 실행되어야 함)
|
|
105
|
+
const entries = await resolveAllReplaceDepEntries(
|
|
106
|
+
projectRoot,
|
|
107
|
+
{
|
|
108
|
+
"@test/pkg-a": sourceA,
|
|
109
|
+
"@other/lib": sourceB,
|
|
110
|
+
},
|
|
111
|
+
logger,
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
// Then: 두 패턴 모두 매칭되어 2개 entries 반환
|
|
115
|
+
expect(entries).toHaveLength(2);
|
|
116
|
+
const targetNames = entries.map((e) => e.targetName).sort();
|
|
117
|
+
expect(targetNames).toEqual(["@other/lib", "@test/pkg-a"]);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it("빈 replaceDeps 설정이면 빈 배열을 반환한다", async () => {
|
|
121
|
+
const entries = await resolveAllReplaceDepEntries(projectRoot, {}, logger);
|
|
122
|
+
expect(entries).toEqual([]);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import os from "os";
|
|
5
|
+
import { setupReplaceDeps } from "../../../src/deps/replace-deps/replace-deps";
|
|
6
|
+
import { pathx } from "@simplysm/core-node";
|
|
7
|
+
|
|
8
|
+
describe("setupReplaceDeps 화이트리스트 복사", () => {
|
|
9
|
+
let tmpDir: string;
|
|
10
|
+
|
|
11
|
+
beforeEach(async () => {
|
|
12
|
+
tmpDir = pathx.posix(await fs.promises.mkdtemp(path.join(os.tmpdir(), "sd-replace-deps-")));
|
|
13
|
+
|
|
14
|
+
// pnpm-workspace.yaml
|
|
15
|
+
const projectRoot = pathx.posix(path.join(tmpDir, "project"));
|
|
16
|
+
await fs.promises.mkdir(projectRoot, { recursive: true });
|
|
17
|
+
await fs.promises.writeFile(
|
|
18
|
+
pathx.posix(path.join(projectRoot, "pnpm-workspace.yaml")),
|
|
19
|
+
"packages:\n",
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
// 타겟 (node_modules에 기존 패키지)
|
|
23
|
+
const targetPkgDir = pathx.posix(
|
|
24
|
+
path.join(projectRoot, "node_modules", "@test", "pkg"),
|
|
25
|
+
);
|
|
26
|
+
await fs.promises.mkdir(targetPkgDir, { recursive: true });
|
|
27
|
+
await fs.promises.writeFile(
|
|
28
|
+
pathx.posix(path.join(targetPkgDir, "package.json")),
|
|
29
|
+
JSON.stringify({ name: "@test/pkg", version: "2.0.0" }),
|
|
30
|
+
);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
afterEach(async () => {
|
|
34
|
+
await fs.promises.rm(tmpDir, { recursive: true, force: true });
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 소스 패키지를 생성하는 헬퍼
|
|
39
|
+
*/
|
|
40
|
+
async function createSourcePkg(opts: {
|
|
41
|
+
files?: string[];
|
|
42
|
+
extraFiles?: Record<string, string>;
|
|
43
|
+
}): Promise<string> {
|
|
44
|
+
const sourcePath = pathx.posix(path.join(tmpDir, "source-pkg"));
|
|
45
|
+
await fs.promises.mkdir(sourcePath, { recursive: true });
|
|
46
|
+
|
|
47
|
+
// package.json
|
|
48
|
+
const pkgJson: Record<string, unknown> = { name: "@test/pkg", version: "1.0.0" };
|
|
49
|
+
if (opts.files != null) {
|
|
50
|
+
pkgJson["files"] = opts.files;
|
|
51
|
+
}
|
|
52
|
+
await fs.promises.writeFile(
|
|
53
|
+
pathx.posix(path.join(sourcePath, "package.json")),
|
|
54
|
+
JSON.stringify(pkgJson),
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
// 기본 디렉토리/파일 생성
|
|
58
|
+
await fs.promises.mkdir(pathx.posix(path.join(sourcePath, "dist")), { recursive: true });
|
|
59
|
+
await fs.promises.writeFile(
|
|
60
|
+
pathx.posix(path.join(sourcePath, "dist", "index.js")),
|
|
61
|
+
"module.exports = {};",
|
|
62
|
+
);
|
|
63
|
+
await fs.promises.mkdir(pathx.posix(path.join(sourcePath, "src")), { recursive: true });
|
|
64
|
+
await fs.promises.writeFile(
|
|
65
|
+
pathx.posix(path.join(sourcePath, "src", "index.ts")),
|
|
66
|
+
"export const v = 1;",
|
|
67
|
+
);
|
|
68
|
+
// files에 없는 파일들
|
|
69
|
+
await fs.promises.writeFile(
|
|
70
|
+
pathx.posix(path.join(sourcePath, "tsconfig.json")),
|
|
71
|
+
"{}",
|
|
72
|
+
);
|
|
73
|
+
await fs.promises.writeFile(
|
|
74
|
+
pathx.posix(path.join(sourcePath, "CLAUDE.md")),
|
|
75
|
+
"# CLAUDE",
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
// 추가 파일
|
|
79
|
+
if (opts.extraFiles != null) {
|
|
80
|
+
for (const [relPath, content] of Object.entries(opts.extraFiles)) {
|
|
81
|
+
const fullPath = pathx.posix(path.join(sourcePath, relPath));
|
|
82
|
+
await fs.promises.mkdir(pathx.posix(path.dirname(fullPath)), { recursive: true });
|
|
83
|
+
await fs.promises.writeFile(fullPath, content);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return sourcePath;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
it("files에 포함된 디렉토리가 복사되고, files에 없는 파일은 복사되지 않는다", async () => {
|
|
91
|
+
const sourcePath = await createSourcePkg({ files: ["dist", "src"] });
|
|
92
|
+
const projectRoot = pathx.posix(path.join(tmpDir, "project"));
|
|
93
|
+
const targetPkgDir = pathx.posix(
|
|
94
|
+
path.join(projectRoot, "node_modules", "@test", "pkg"),
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
await setupReplaceDeps(projectRoot, { "@test/pkg": sourcePath });
|
|
98
|
+
|
|
99
|
+
// files에 포함된 디렉토리가 복사됨
|
|
100
|
+
expect(fs.existsSync(pathx.posix(path.join(targetPkgDir, "dist", "index.js")))).toBe(true);
|
|
101
|
+
expect(fs.existsSync(pathx.posix(path.join(targetPkgDir, "src", "index.ts")))).toBe(true);
|
|
102
|
+
|
|
103
|
+
// files에 없는 파일은 복사되지 않음
|
|
104
|
+
expect(fs.existsSync(pathx.posix(path.join(targetPkgDir, "tsconfig.json")))).toBe(false);
|
|
105
|
+
expect(fs.existsSync(pathx.posix(path.join(targetPkgDir, "CLAUDE.md")))).toBe(false);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("npm 기본 포함 파일(README, LICENSE)은 files에 없어도 복사된다", async () => {
|
|
109
|
+
const sourcePath = await createSourcePkg({
|
|
110
|
+
files: ["dist", "src"],
|
|
111
|
+
extraFiles: {
|
|
112
|
+
"README.md": "# README",
|
|
113
|
+
"LICENSE": "MIT License",
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
const projectRoot = pathx.posix(path.join(tmpDir, "project"));
|
|
117
|
+
const targetPkgDir = pathx.posix(
|
|
118
|
+
path.join(projectRoot, "node_modules", "@test", "pkg"),
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
await setupReplaceDeps(projectRoot, { "@test/pkg": sourcePath });
|
|
122
|
+
|
|
123
|
+
expect(fs.existsSync(pathx.posix(path.join(targetPkgDir, "README.md")))).toBe(true);
|
|
124
|
+
expect(fs.existsSync(pathx.posix(path.join(targetPkgDir, "LICENSE")))).toBe(true);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("package.json은 복사되지 않고 대상의 기존 package.json이 보존된다", async () => {
|
|
128
|
+
const sourcePath = await createSourcePkg({ files: ["dist", "src"] });
|
|
129
|
+
const projectRoot = pathx.posix(path.join(tmpDir, "project"));
|
|
130
|
+
const targetPkgDir = pathx.posix(
|
|
131
|
+
path.join(projectRoot, "node_modules", "@test", "pkg"),
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
await setupReplaceDeps(projectRoot, { "@test/pkg": sourcePath });
|
|
135
|
+
|
|
136
|
+
// 대상의 기존 package.json이 보존됨 (소스의 것으로 덮어씌워지지 않음)
|
|
137
|
+
const targetPkgJson = JSON.parse(
|
|
138
|
+
fs.readFileSync(pathx.posix(path.join(targetPkgDir, "package.json")), "utf-8"),
|
|
139
|
+
);
|
|
140
|
+
expect(targetPkgJson.version).toBe("2.0.0");
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it("files 필드가 없는 패키지는 건너뛰고 복사하지 않는다", async () => {
|
|
144
|
+
const sourcePath = await createSourcePkg({ files: undefined });
|
|
145
|
+
const projectRoot = pathx.posix(path.join(tmpDir, "project"));
|
|
146
|
+
const targetPkgDir = pathx.posix(
|
|
147
|
+
path.join(projectRoot, "node_modules", "@test", "pkg"),
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
await setupReplaceDeps(projectRoot, { "@test/pkg": sourcePath });
|
|
151
|
+
|
|
152
|
+
// 복사가 수행되지 않음
|
|
153
|
+
expect(fs.existsSync(pathx.posix(path.join(targetPkgDir, "dist")))).toBe(false);
|
|
154
|
+
expect(fs.existsSync(pathx.posix(path.join(targetPkgDir, "src")))).toBe(false);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
@@ -70,7 +70,10 @@ vi.mock("esbuild", () => ({
|
|
|
70
70
|
const mockLoggerDebug = vi.fn();
|
|
71
71
|
const mockLoggerWarn = vi.fn();
|
|
72
72
|
const mockLoggerInfo = vi.fn();
|
|
73
|
-
vi.
|
|
73
|
+
const mockLoggerStart = vi.fn();
|
|
74
|
+
const mockLoggerSuccess = vi.fn();
|
|
75
|
+
const mockLoggerError = vi.fn();
|
|
76
|
+
vi.spyOn(consola, "withTag").mockReturnValue({ debug: mockLoggerDebug, warn: mockLoggerWarn, info: mockLoggerInfo, start: mockLoggerStart, success: mockLoggerSuccess, error: mockLoggerError } as any);
|
|
74
77
|
|
|
75
78
|
//#endregion
|
|
76
79
|
|