@simplysm/sd-cli 14.1.9 → 14.1.11
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/capacitor/capacitor-icon.js +2 -2
- package/dist/capacitor/capacitor-icon.js.map +1 -1
- package/dist/capacitor/capacitor-npm-config.d.ts +1 -1
- package/dist/capacitor/capacitor-npm-config.d.ts.map +1 -1
- package/dist/capacitor/capacitor-npm-config.js +11 -18
- package/dist/capacitor/capacitor-npm-config.js.map +1 -1
- package/dist/capacitor/capacitor.d.ts +1 -1
- package/dist/capacitor/capacitor.js +2 -2
- package/dist/capacitor/capacitor.js.map +1 -1
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +1 -0
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/device.js +2 -2
- package/dist/commands/device.js.map +1 -1
- package/dist/commands/init/generators/root.d.ts.map +1 -1
- package/dist/commands/init/generators/root.js +0 -1
- package/dist/commands/init/generators/root.js.map +1 -1
- package/dist/commands/init/init-client.js +1 -1
- package/dist/commands/init/init-client.js.map +1 -1
- package/dist/commands/init/init.js +2 -2
- package/dist/commands/init/init.js.map +1 -1
- package/dist/commands/publish/deployment-phase.d.ts.map +1 -1
- package/dist/commands/publish/deployment-phase.js +1 -0
- package/dist/commands/publish/deployment-phase.js.map +1 -1
- package/dist/commands/publish/npm-publisher.js +3 -3
- package/dist/commands/publish/npm-publisher.js.map +1 -1
- package/dist/commands/publish/post-publish-phase.d.ts.map +1 -1
- package/dist/commands/publish/post-publish-phase.js +1 -0
- package/dist/commands/publish/post-publish-phase.js.map +1 -1
- package/dist/commands/publish/publish-command.d.ts.map +1 -1
- package/dist/commands/publish/publish-command.js +7 -12
- 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 +50 -0
- package/dist/commands/publish/version-upgrade.js.map +1 -1
- package/dist/deps/replace-deps/collect-deps.js +4 -4
- package/dist/deps/replace-deps/collect-deps.js.map +1 -1
- package/dist/deps/replace-deps/replace-deps-resolve.d.ts +4 -12
- package/dist/deps/replace-deps/replace-deps-resolve.d.ts.map +1 -1
- package/dist/deps/replace-deps/replace-deps-resolve.js +13 -49
- package/dist/deps/replace-deps/replace-deps-resolve.js.map +1 -1
- package/dist/deps/replace-deps/replace-deps.d.ts +2 -2
- package/dist/deps/replace-deps/replace-deps.js +3 -3
- package/dist/deps/server-externals/server-production-files.d.ts +3 -3
- package/dist/deps/server-externals/server-production-files.d.ts.map +1 -1
- package/dist/deps/server-externals/server-production-files.js +24 -17
- package/dist/deps/server-externals/server-production-files.js.map +1 -1
- package/dist/electron/electron.d.ts.map +1 -1
- package/dist/electron/electron.js +6 -11
- package/dist/electron/electron.js.map +1 -1
- package/dist/engines/BaseEngine.d.ts +1 -0
- package/dist/engines/BaseEngine.d.ts.map +1 -1
- package/dist/engines/BaseEngine.js +2 -1
- package/dist/engines/BaseEngine.js.map +1 -1
- package/dist/esbuild/esbuild-config.d.ts +6 -2
- package/dist/esbuild/esbuild-config.d.ts.map +1 -1
- package/dist/esbuild/esbuild-config.js +4 -3
- package/dist/esbuild/esbuild-config.js.map +1 -1
- package/dist/esbuild/esbuild-tsc-plugin.d.ts.map +1 -1
- package/dist/esbuild/esbuild-tsc-plugin.js +3 -1
- package/dist/esbuild/esbuild-tsc-plugin.js.map +1 -1
- package/dist/orchestrators/BaseOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/BaseOrchestrator.js +1 -0
- package/dist/orchestrators/BaseOrchestrator.js.map +1 -1
- package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/BuildOrchestrator.js +3 -5
- package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
- package/dist/orchestrators/DevOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/DevOrchestrator.js +1 -0
- package/dist/orchestrators/DevOrchestrator.js.map +1 -1
- package/dist/orchestrators/ServerRuntimeManager.d.ts.map +1 -1
- package/dist/orchestrators/ServerRuntimeManager.js +4 -0
- package/dist/orchestrators/ServerRuntimeManager.js.map +1 -1
- package/dist/orchestrators/TypecheckOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/TypecheckOrchestrator.js +4 -6
- package/dist/orchestrators/TypecheckOrchestrator.js.map +1 -1
- package/dist/runtime/engine-watch-events.d.ts.map +1 -1
- package/dist/runtime/engine-watch-events.js +5 -0
- package/dist/runtime/engine-watch-events.js.map +1 -1
- package/dist/runtime/worker-events.d.ts +1 -0
- package/dist/runtime/worker-events.d.ts.map +1 -1
- package/dist/sd-cli-entry.d.ts.map +1 -1
- package/dist/sd-cli-entry.js +0 -4
- package/dist/sd-cli-entry.js.map +1 -1
- package/dist/sd-cli.js +2 -0
- package/dist/sd-cli.js.map +1 -1
- package/dist/typecheck/typecheck-non-package.d.ts.map +1 -1
- package/dist/typecheck/typecheck-non-package.js +10 -0
- package/dist/typecheck/typecheck-non-package.js.map +1 -1
- package/dist/utils/package-utils.d.ts +8 -6
- package/dist/utils/package-utils.d.ts.map +1 -1
- package/dist/utils/package-utils.js +26 -24
- package/dist/utils/package-utils.js.map +1 -1
- package/dist/utils/workspace-utils.d.ts +17 -0
- package/dist/utils/workspace-utils.d.ts.map +1 -0
- package/dist/utils/workspace-utils.js +95 -0
- package/dist/utils/workspace-utils.js.map +1 -0
- package/dist/workers/client.worker.d.ts +1 -0
- package/dist/workers/client.worker.d.ts.map +1 -1
- package/dist/workers/client.worker.js +8 -3
- package/dist/workers/client.worker.js.map +1 -1
- package/dist/workers/library-build.worker.d.ts +1 -0
- package/dist/workers/library-build.worker.d.ts.map +1 -1
- package/dist/workers/library-build.worker.js +3 -2
- package/dist/workers/library-build.worker.js.map +1 -1
- package/dist/workers/server-build.worker.d.ts +1 -0
- package/dist/workers/server-build.worker.d.ts.map +1 -1
- package/dist/workers/server-build.worker.js +12 -12
- package/dist/workers/server-build.worker.js.map +1 -1
- package/dist/workers/server-esbuild-context.d.ts.map +1 -1
- package/dist/workers/server-esbuild-context.js +4 -2
- package/dist/workers/server-esbuild-context.js.map +1 -1
- package/dist/workers/server-runtime.worker.d.ts +1 -0
- package/dist/workers/server-runtime.worker.d.ts.map +1 -1
- package/dist/workers/server-runtime.worker.js +9 -3
- package/dist/workers/server-runtime.worker.js.map +1 -1
- package/dist/workers/server-watch-manager.d.ts +1 -1
- package/dist/workers/server-watch-manager.d.ts.map +1 -1
- package/dist/workers/server-watch-manager.js +2 -2
- package/dist/workers/server-watch-manager.js.map +1 -1
- package/package.json +11 -11
- package/src/capacitor/capacitor-icon.ts +2 -2
- package/src/capacitor/capacitor-npm-config.ts +10 -19
- package/src/capacitor/capacitor.ts +2 -2
- package/src/commands/check.ts +1 -0
- package/src/commands/device.ts +2 -2
- package/src/commands/init/generators/root.ts +0 -1
- package/src/commands/init/init-client.ts +1 -1
- package/src/commands/init/init.ts +2 -2
- package/src/commands/init/templates/workspace-root/mise.toml.hbs +1 -1
- package/src/commands/publish/deployment-phase.ts +1 -0
- package/src/commands/publish/npm-publisher.ts +3 -3
- package/src/commands/publish/post-publish-phase.ts +1 -0
- package/src/commands/publish/publish-command.ts +7 -15
- package/src/commands/publish/version-upgrade.ts +51 -0
- package/src/deps/replace-deps/collect-deps.ts +4 -4
- package/src/deps/replace-deps/replace-deps-resolve.ts +13 -56
- package/src/deps/replace-deps/replace-deps.ts +3 -3
- package/src/deps/server-externals/server-production-files.ts +31 -18
- package/src/electron/electron.ts +7 -13
- package/src/engines/BaseEngine.ts +3 -2
- package/src/esbuild/esbuild-config.ts +12 -3
- package/src/esbuild/esbuild-tsc-plugin.ts +4 -1
- package/src/orchestrators/BaseOrchestrator.ts +1 -0
- package/src/orchestrators/BuildOrchestrator.ts +3 -5
- package/src/orchestrators/DevOrchestrator.ts +1 -0
- package/src/orchestrators/ServerRuntimeManager.ts +4 -0
- package/src/orchestrators/TypecheckOrchestrator.ts +4 -6
- package/src/runtime/engine-watch-events.ts +7 -1
- package/src/runtime/worker-events.ts +1 -0
- package/src/sd-cli-entry.ts +0 -9
- package/src/sd-cli.ts +2 -0
- package/src/typecheck/typecheck-non-package.ts +11 -0
- package/src/utils/package-utils.ts +30 -23
- package/src/utils/workspace-utils.ts +117 -0
- package/src/workers/client.worker.ts +9 -4
- package/src/workers/library-build.worker.ts +4 -3
- package/src/workers/server-build.worker.ts +13 -13
- package/src/workers/server-esbuild-context.ts +5 -2
- package/src/workers/server-runtime.worker.ts +10 -3
- package/src/workers/server-watch-manager.ts +3 -3
- package/tests/capacitor/capacitor-build.spec.ts +142 -142
- package/tests/capacitor/capacitor-init.spec.ts +181 -181
- package/tests/capacitor/capacitor-npm-config.acc.spec.ts +114 -114
- package/tests/capacitor/capacitor-npm-config.spec.ts +94 -94
- package/tests/commands/publish-manifest.acc.spec.ts +67 -0
- package/tests/deps/replace-deps/collect-deps.acc.spec.ts +16 -1
- package/tests/deps/replace-deps/replace-deps-resolve.acc.spec.ts +9 -5
- package/tests/deps/replace-deps/replace-deps-setup.acc.spec.ts +3 -3
- package/tests/deps/server-externals/server-production-files.spec.ts +68 -0
- package/tests/electron/electron.spec.ts +608 -608
- package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck-browser.tsbuildinfo +1 -1
- package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck-node.tsbuildinfo +1 -1
- package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck.tsbuildinfo +1 -1
- package/tests/utils/engine-watch-events.spec.ts +17 -0
- package/tests/utils/esbuild-config.spec.ts +15 -0
- package/tests/utils/package-utils.spec.ts +36 -4
- package/tests/utils/replace-deps-watch.acc.spec.ts +4 -4
- package/tests/utils/replace-deps-watch.spec.ts +3 -3
- package/tests/utils/replace-deps.spec.ts +1 -35
- package/tests/utils/workspace-utils.spec.ts +87 -0
- package/tests/workers/library-build-worker.spec.ts +1 -1
- package/tests/workers/server-esbuild-context.spec.ts +4 -3
- package/dist/commands/reinstall.d.ts +0 -13
- package/dist/commands/reinstall.d.ts.map +0 -1
- package/dist/commands/reinstall.js +0 -56
- package/dist/commands/reinstall.js.map +0 -1
- package/src/commands/init/templates/workspace-root/pnpm-workspace.yaml +0 -5
- package/src/commands/reinstall.ts +0 -63
- package/tests/angular/angular-compiler-hmr-removal.verify.md +0 -16
- package/tests/angular/onbuild-lint-removal.verify.md +0 -8
- package/tests/angular/vite-angular-plugin-sdtscompiler.verify.md +0 -13
- package/tests/angular/vite-angular-plugin-vitest.verify.md +0 -20
- package/tests/capacitor/capacitor-android-exports.verify.md +0 -11
- package/tests/commands/publish-npm-local-split.verify.md +0 -9
- package/tests/commands/publish-responsibility-split.verify.md +0 -13
- package/tests/commands/publish-set.verify.md +0 -7
- package/tests/commands/publish-storage-split.verify.md +0 -8
- package/tests/commands/slice3-severity-cleanup.verify.md +0 -12
- package/tests/deps/deps-directory-separation.verify.md +0 -15
- package/tests/deps/replace-deps/replace-deps-perf.verify.md +0 -15
- package/tests/deps/server-externals/mise-toml-parse-intent.verify.md +0 -16
- package/tests/electron/electron-symlink-cleanup.verify.md +0 -8
- package/tests/engines/engine-duplicate-output-removal.verify.md +0 -10
- package/tests/engines/engine-typecheck-selection.verify.md +0 -8
- package/tests/engines/esbuild-client-engine.verify.md +0 -15
- package/tests/engines/normalize-result.verify.md +0 -9
- package/tests/engines/vite-dependency-cleanup.verify.md +0 -24
- package/tests/esbuild/esbuild-angular-compiler-plugin-hmr.verify.md +0 -23
- package/tests/esbuild/esbuild-angular-compiler-plugin-onload.verify.md +0 -21
- package/tests/esbuild/esbuild-angular-compiler-plugin-onstart-extraction.verify.md +0 -16
- package/tests/esbuild/esbuild-angular-compiler-plugin-sdtscompiler.verify.md +0 -15
- package/tests/esbuild/esbuild-angular-compiler-plugin-stylesheet.verify.md +0 -31
- package/tests/esbuild/esbuild-angular-compiler-plugin-worker.verify.md +0 -59
- package/tests/esbuild/esbuild-angular-compiler-plugin.verify.md +0 -21
- package/tests/esbuild/esbuild-postcss-plugin-chunking.verify.md +0 -17
- package/tests/esbuild/esbuild-tsc-plugin-imports.verify.md +0 -13
- package/tests/esbuild/esbuild-worker-plugin-node.verify.md +0 -12
- package/tests/esbuild/esbuild-worker-plugin.verify.md +0 -7
- package/tests/orchestrators/dist-delete-watcher.verify.md +0 -10
- package/tests/orchestrators/orchestrator-baseenv.verify.md +0 -10
- package/tests/orchestrators/orchestrator-diagnostic-formatting.verify.md +0 -10
- package/tests/orchestrators/orchestrator-initializemode-signature.verify.md +0 -9
- package/tests/orchestrators/slice1-stdout-to-consola.verify.md +0 -10
- package/tests/sd-cli-catch-all.verify.md +0 -7
- package/tests/sd-cli-log-tag.verify.md +0 -11
- package/tests/ts-compiler/SdTsCompiler-affected-files.verify.md +0 -8
- package/tests/ts-compiler/SdTsCompiler-crash-handling.verify.md +0 -24
- package/tests/ts-compiler/SdTsCompiler-diagnostics.verify.md +0 -12
- package/tests/ts-compiler/SdTsCompiler-emit.verify.md +0 -9
- package/tests/ts-compiler/SdTsCompiler.verify.md +0 -41
- package/tests/ts-compiler/scss-lint-integration.verify.md +0 -14
- package/tests/utils/copy-public-outdir.verify.md +0 -8
- package/tests/utils/dev-http-server.verify.md +0 -8
- package/tests/utils/engine-watch-events.verify.md +0 -17
- package/tests/utils/esbuild-client-config-integration.verify.md +0 -9
- package/tests/utils/esbuild-client-config-postcss.verify.md +0 -6
- package/tests/utils/esbuild-client-config.verify.md +0 -26
- package/tests/utils/esbuild-index-html.verify.md +0 -10
- package/tests/utils/esbuild-pwa.verify.md +0 -9
- package/tests/utils/esbuild-scss-plugin.verify.md +0 -8
- package/tests/utils/hmr-service.verify.md +0 -17
- package/tests/utils/lint-core-import-paths.verify.md +0 -10
- package/tests/utils/replace-deps-split.verify.md +0 -15
- package/tests/utils/replace-deps-watch.verify.md +0 -9
- package/tests/utils/server-production-files-import-paths.verify.md +0 -14
- package/tests/utils/vite-config-cleanup.verify.md +0 -7
- package/tests/workers/build-watch-paths-library.verify.md +0 -10
- package/tests/workers/build-watch-paths-ngtsc-server.verify.md +0 -12
- package/tests/workers/client-worker-browser-support.verify.md +0 -7
- package/tests/workers/client-worker-cleanup.verify.md +0 -8
- package/tests/workers/client-worker-initial-build-error.verify.md +0 -7
- package/tests/workers/client-worker-initial-build-warnings.verify.md +0 -7
- package/tests/workers/client-worker-mtime-incremental.verify.md +0 -10
- package/tests/workers/client-worker-onend-sync.verify.md +0 -7
- package/tests/workers/client-worker-refactor.verify.md +0 -22
- package/tests/workers/client-worker-ts-cache-invalidation.verify.md +0 -12
- package/tests/workers/dev-port-file.verify.md +0 -6
- package/tests/workers/ngtsc-build-rootnames-refresh.verify.md +0 -8
- package/tests/workers/server-build-context-dispose.verify.md +0 -8
- package/tests/workers/server-build-worker-plugin.verify.md +0 -9
- package/tests/workers/server-build-worker-refactoring.verify.md +0 -14
- package/tests/workers/server-esbuild-context-integration.verify.md +0 -10
- package/tests/workers/server-esbuild-context-tsc.verify.md +0 -7
|
@@ -1,114 +1,114 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeAll, afterAll, beforeEach } from "vitest";
|
|
2
|
-
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { fsx, cpx } from "@simplysm/core-node";
|
|
6
|
-
|
|
7
|
-
const mockFsxExists = vi.spyOn(fsx, "exists");
|
|
8
|
-
vi.spyOn(fsx, "read");
|
|
9
|
-
vi.spyOn(fsx, "write").mockResolvedValue(undefined);
|
|
10
|
-
const mockFsxReadJson = vi.spyOn(fsx, "readJson");
|
|
11
|
-
vi.spyOn(fsx, "writeJson").mockResolvedValue(undefined);
|
|
12
|
-
vi.spyOn(fsx, "mkdir").mockResolvedValue(undefined);
|
|
13
|
-
|
|
14
|
-
const execaCalls: { command: string; args: string[]; options: unknown }[] = [];
|
|
15
|
-
vi.spyOn(cpx, "spawn").mockImplementation(((cmd: string, args: string[], options: unknown) => {
|
|
16
|
-
execaCalls.push({
|
|
17
|
-
command: cmd,
|
|
18
|
-
args,
|
|
19
|
-
options,
|
|
20
|
-
});
|
|
21
|
-
return { stdout: "", stderr: "", exitCode: 0 };
|
|
22
|
-
}) as never);
|
|
23
|
-
|
|
24
|
-
//#endregion
|
|
25
|
-
|
|
26
|
-
let tmpRoot: string;
|
|
27
|
-
let CAP_PATH: string;
|
|
28
|
-
let PKG_PATH: string;
|
|
29
|
-
|
|
30
|
-
beforeAll(() => {
|
|
31
|
-
tmpRoot = mkdtempSync(path.join(tmpdir(), "cap-npm-config-acc-"));
|
|
32
|
-
writeFileSync(path.join(tmpRoot, "
|
|
33
|
-
PKG_PATH = path.join(tmpRoot, "pkg");
|
|
34
|
-
CAP_PATH = path.join(PKG_PATH, ".capacitor");
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
afterAll(() => {
|
|
38
|
-
rmSync(tmpRoot, { recursive: true, force: true });
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
function setupDefaultMocks() {
|
|
42
|
-
mockFsxExists.mockImplementation(((p: string) => {
|
|
43
|
-
const n = p.replace(/\\/g, "/");
|
|
44
|
-
if (n.includes(".capacitor.lock")) return false;
|
|
45
|
-
return true;
|
|
46
|
-
}) as never);
|
|
47
|
-
|
|
48
|
-
mockFsxReadJson.mockImplementation(((p: string) => {
|
|
49
|
-
const normalized = p.replace(/\\/g, "/");
|
|
50
|
-
if (normalized.includes(".capacitor/package.json")) {
|
|
51
|
-
return {
|
|
52
|
-
name: "com.test.app",
|
|
53
|
-
version: "1.0.0",
|
|
54
|
-
dependencies: {
|
|
55
|
-
"@capacitor/core": "^7",
|
|
56
|
-
"@capacitor/app": "^7",
|
|
57
|
-
"@capacitor/android": "^7",
|
|
58
|
-
},
|
|
59
|
-
devDependencies: {
|
|
60
|
-
"@capacitor/cli": "^7",
|
|
61
|
-
"@capacitor/assets": "^3",
|
|
62
|
-
},
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
return { name: "test-pkg", version: "1.0.0" };
|
|
66
|
-
}) as never);
|
|
67
|
-
|
|
68
|
-
execaCalls.length = 0;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
describe("initCapNpmProject", () => {
|
|
72
|
-
beforeEach(() => {
|
|
73
|
-
vi.clearAllMocks();
|
|
74
|
-
setupDefaultMocks();
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it("의존성 미변경 + node_modules 존재 시 false를 반환하고
|
|
78
|
-
const { initCapNpmProject } = await import(
|
|
79
|
-
"../../src/capacitor/capacitor-npm-config.js"
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
const changed = await initCapNpmProject(CAP_PATH, PKG_PATH, {
|
|
83
|
-
appId: "com.test.app",
|
|
84
|
-
appName: "Test App",
|
|
85
|
-
platform: { android: {} },
|
|
86
|
-
}, { name: "test-pkg", version: "1.0.0" }, ["android"], []);
|
|
87
|
-
|
|
88
|
-
expect(changed).toBe(false);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it("node_modules가 없으면 true를 반환하고
|
|
92
|
-
mockFsxExists.mockImplementation(((p: string) => {
|
|
93
|
-
const n = p.replace(/\\/g, "/");
|
|
94
|
-
if (n.includes(".capacitor.lock")) return false;
|
|
95
|
-
if (n.includes("node_modules")) return false;
|
|
96
|
-
return true;
|
|
97
|
-
}) as never);
|
|
98
|
-
|
|
99
|
-
const { initCapNpmProject } = await import(
|
|
100
|
-
"../../src/capacitor/capacitor-npm-config.js"
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
const changed = await initCapNpmProject(CAP_PATH, PKG_PATH, {
|
|
104
|
-
appId: "com.test.app",
|
|
105
|
-
appName: "Test App",
|
|
106
|
-
platform: { android: {} },
|
|
107
|
-
}, {
|
|
108
|
-
name: "test-pkg",
|
|
109
|
-
version: "1.0.0",
|
|
110
|
-
}, ["android"], []);
|
|
111
|
-
|
|
112
|
-
expect(changed).toBe(true);
|
|
113
|
-
});
|
|
114
|
-
});
|
|
1
|
+
import { describe, it, expect, vi, beforeAll, afterAll, beforeEach } from "vitest";
|
|
2
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { fsx, cpx } from "@simplysm/core-node";
|
|
6
|
+
|
|
7
|
+
const mockFsxExists = vi.spyOn(fsx, "exists");
|
|
8
|
+
vi.spyOn(fsx, "read");
|
|
9
|
+
vi.spyOn(fsx, "write").mockResolvedValue(undefined);
|
|
10
|
+
const mockFsxReadJson = vi.spyOn(fsx, "readJson");
|
|
11
|
+
vi.spyOn(fsx, "writeJson").mockResolvedValue(undefined);
|
|
12
|
+
vi.spyOn(fsx, "mkdir").mockResolvedValue(undefined);
|
|
13
|
+
|
|
14
|
+
const execaCalls: { command: string; args: string[]; options: unknown }[] = [];
|
|
15
|
+
vi.spyOn(cpx, "spawn").mockImplementation(((cmd: string, args: string[], options: unknown) => {
|
|
16
|
+
execaCalls.push({
|
|
17
|
+
command: cmd,
|
|
18
|
+
args,
|
|
19
|
+
options,
|
|
20
|
+
});
|
|
21
|
+
return { stdout: "", stderr: "", exitCode: 0 };
|
|
22
|
+
}) as never);
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
|
|
26
|
+
let tmpRoot: string;
|
|
27
|
+
let CAP_PATH: string;
|
|
28
|
+
let PKG_PATH: string;
|
|
29
|
+
|
|
30
|
+
beforeAll(() => {
|
|
31
|
+
tmpRoot = mkdtempSync(path.join(tmpdir(), "cap-npm-config-acc-"));
|
|
32
|
+
writeFileSync(path.join(tmpRoot, "package.json"), JSON.stringify({ private: true, workspaces: ["pkg"] }));
|
|
33
|
+
PKG_PATH = path.join(tmpRoot, "pkg");
|
|
34
|
+
CAP_PATH = path.join(PKG_PATH, ".capacitor");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
afterAll(() => {
|
|
38
|
+
rmSync(tmpRoot, { recursive: true, force: true });
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
function setupDefaultMocks() {
|
|
42
|
+
mockFsxExists.mockImplementation(((p: string) => {
|
|
43
|
+
const n = p.replace(/\\/g, "/");
|
|
44
|
+
if (n.includes(".capacitor.lock")) return false;
|
|
45
|
+
return true;
|
|
46
|
+
}) as never);
|
|
47
|
+
|
|
48
|
+
mockFsxReadJson.mockImplementation(((p: string) => {
|
|
49
|
+
const normalized = p.replace(/\\/g, "/");
|
|
50
|
+
if (normalized.includes(".capacitor/package.json")) {
|
|
51
|
+
return {
|
|
52
|
+
name: "com.test.app",
|
|
53
|
+
version: "1.0.0",
|
|
54
|
+
dependencies: {
|
|
55
|
+
"@capacitor/core": "^7",
|
|
56
|
+
"@capacitor/app": "^7",
|
|
57
|
+
"@capacitor/android": "^7",
|
|
58
|
+
},
|
|
59
|
+
devDependencies: {
|
|
60
|
+
"@capacitor/cli": "^7",
|
|
61
|
+
"@capacitor/assets": "^3",
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return { name: "test-pkg", version: "1.0.0" };
|
|
66
|
+
}) as never);
|
|
67
|
+
|
|
68
|
+
execaCalls.length = 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
describe("initCapNpmProject", () => {
|
|
72
|
+
beforeEach(() => {
|
|
73
|
+
vi.clearAllMocks();
|
|
74
|
+
setupDefaultMocks();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("의존성 미변경 + node_modules 존재 시 false를 반환하고 bun install을 실행하지 않는다", async () => {
|
|
78
|
+
const { initCapNpmProject } = await import(
|
|
79
|
+
"../../src/capacitor/capacitor-npm-config.js"
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const changed = await initCapNpmProject(CAP_PATH, PKG_PATH, {
|
|
83
|
+
appId: "com.test.app",
|
|
84
|
+
appName: "Test App",
|
|
85
|
+
platform: { android: {} },
|
|
86
|
+
}, { name: "test-pkg", version: "1.0.0" }, ["android"], []);
|
|
87
|
+
|
|
88
|
+
expect(changed).toBe(false);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("node_modules가 없으면 true를 반환하고 bun install을 실행한다", async () => {
|
|
92
|
+
mockFsxExists.mockImplementation(((p: string) => {
|
|
93
|
+
const n = p.replace(/\\/g, "/");
|
|
94
|
+
if (n.includes(".capacitor.lock")) return false;
|
|
95
|
+
if (n.includes("node_modules")) return false;
|
|
96
|
+
return true;
|
|
97
|
+
}) as never);
|
|
98
|
+
|
|
99
|
+
const { initCapNpmProject } = await import(
|
|
100
|
+
"../../src/capacitor/capacitor-npm-config.js"
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
const changed = await initCapNpmProject(CAP_PATH, PKG_PATH, {
|
|
104
|
+
appId: "com.test.app",
|
|
105
|
+
appName: "Test App",
|
|
106
|
+
platform: { android: {} },
|
|
107
|
+
}, {
|
|
108
|
+
name: "test-pkg",
|
|
109
|
+
version: "1.0.0",
|
|
110
|
+
}, ["android"], []);
|
|
111
|
+
|
|
112
|
+
expect(changed).toBe(true);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
@@ -1,94 +1,94 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeAll, afterAll, beforeEach } from "vitest";
|
|
2
|
-
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import { fsx, cpx } from "@simplysm/core-node";
|
|
6
|
-
|
|
7
|
-
const mockFsxExists = vi.spyOn(fsx, "exists");
|
|
8
|
-
vi.spyOn(fsx, "write").mockResolvedValue(undefined);
|
|
9
|
-
const mockFsxReadJson = vi.spyOn(fsx, "readJson");
|
|
10
|
-
vi.spyOn(fsx, "writeJson").mockResolvedValue(undefined);
|
|
11
|
-
vi.spyOn(fsx, "mkdir").mockResolvedValue(undefined);
|
|
12
|
-
vi.spyOn(fsx, "read");
|
|
13
|
-
|
|
14
|
-
vi.spyOn(cpx, "spawn").mockResolvedValue({ stdout: "", stderr: "", exitCode: 0 });
|
|
15
|
-
|
|
16
|
-
let tmpRoot: string;
|
|
17
|
-
let CAP_PATH: string;
|
|
18
|
-
let PKG_PATH: string;
|
|
19
|
-
|
|
20
|
-
beforeAll(() => {
|
|
21
|
-
tmpRoot = mkdtempSync(path.join(tmpdir(), "cap-npm-config-"));
|
|
22
|
-
writeFileSync(path.join(tmpRoot, "
|
|
23
|
-
PKG_PATH = path.join(tmpRoot, "pkg");
|
|
24
|
-
CAP_PATH = path.join(PKG_PATH, ".capacitor");
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
afterAll(() => {
|
|
28
|
-
rmSync(tmpRoot, { recursive: true, force: true });
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
describe("setupCapNpmConfig", () => {
|
|
32
|
-
beforeEach(() => {
|
|
33
|
-
vi.clearAllMocks();
|
|
34
|
-
mockFsxExists.mockResolvedValue(true);
|
|
35
|
-
mockFsxReadJson.mockImplementation(((p: string) => {
|
|
36
|
-
const normalized = p.replace(/\\/g, "/");
|
|
37
|
-
if (normalized.includes(".capacitor/package.json")) {
|
|
38
|
-
return {
|
|
39
|
-
name: "com.test.app",
|
|
40
|
-
version: "1.0.0",
|
|
41
|
-
dependencies: {
|
|
42
|
-
"@capacitor/core": "^7",
|
|
43
|
-
"@capacitor/app": "^7",
|
|
44
|
-
"@capacitor/android": "^7",
|
|
45
|
-
},
|
|
46
|
-
devDependencies: {
|
|
47
|
-
"@capacitor/cli": "^7",
|
|
48
|
-
"@capacitor/assets": "^3",
|
|
49
|
-
},
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
return { name: "test-pkg", version: "1.0.0" };
|
|
53
|
-
}) as never);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("루트 package.json이 없으면 에러를 던진다", async () => {
|
|
57
|
-
mockFsxExists.mockImplementation(((p: string) => {
|
|
58
|
-
const n = p.replace(/\\/g, "/");
|
|
59
|
-
if (n.endsWith("package.json") && !n.includes(".capacitor")) return false;
|
|
60
|
-
return true;
|
|
61
|
-
}) as never);
|
|
62
|
-
|
|
63
|
-
const { setupCapNpmConfig } = await import(
|
|
64
|
-
"../../src/capacitor/capacitor-npm-config.js"
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
await expect(
|
|
68
|
-
setupCapNpmConfig(CAP_PATH, PKG_PATH, {
|
|
69
|
-
appId: "com.test.app",
|
|
70
|
-
appName: "Test App",
|
|
71
|
-
}, { name: "test-pkg", version: "1.0.0" }, [], []),
|
|
72
|
-
).rejects.toThrow("루트 package.json");
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it(".capacitor/package.json이 없으면 빈 설정으로 시작한다", async () => {
|
|
76
|
-
mockFsxExists.mockImplementation(((p: string) => {
|
|
77
|
-
const n = p.replace(/\\/g, "/");
|
|
78
|
-
if (n.includes(".capacitor/package.json")) return false;
|
|
79
|
-
return true;
|
|
80
|
-
}) as never);
|
|
81
|
-
|
|
82
|
-
const { setupCapNpmConfig } = await import(
|
|
83
|
-
"../../src/capacitor/capacitor-npm-config.js"
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
const changed = await setupCapNpmConfig(CAP_PATH, PKG_PATH, {
|
|
87
|
-
appId: "com.test.app",
|
|
88
|
-
appName: "Test App",
|
|
89
|
-
}, { name: "test-pkg", version: "1.0.0" }, [], []);
|
|
90
|
-
|
|
91
|
-
// 빈 설정에서 시작하므로 dependencies가 추가되어 변경됨
|
|
92
|
-
expect(changed).toBe(true);
|
|
93
|
-
});
|
|
94
|
-
});
|
|
1
|
+
import { describe, it, expect, vi, beforeAll, afterAll, beforeEach } from "vitest";
|
|
2
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { fsx, cpx } from "@simplysm/core-node";
|
|
6
|
+
|
|
7
|
+
const mockFsxExists = vi.spyOn(fsx, "exists");
|
|
8
|
+
vi.spyOn(fsx, "write").mockResolvedValue(undefined);
|
|
9
|
+
const mockFsxReadJson = vi.spyOn(fsx, "readJson");
|
|
10
|
+
vi.spyOn(fsx, "writeJson").mockResolvedValue(undefined);
|
|
11
|
+
vi.spyOn(fsx, "mkdir").mockResolvedValue(undefined);
|
|
12
|
+
vi.spyOn(fsx, "read");
|
|
13
|
+
|
|
14
|
+
vi.spyOn(cpx, "spawn").mockResolvedValue({ stdout: "", stderr: "", exitCode: 0 });
|
|
15
|
+
|
|
16
|
+
let tmpRoot: string;
|
|
17
|
+
let CAP_PATH: string;
|
|
18
|
+
let PKG_PATH: string;
|
|
19
|
+
|
|
20
|
+
beforeAll(() => {
|
|
21
|
+
tmpRoot = mkdtempSync(path.join(tmpdir(), "cap-npm-config-"));
|
|
22
|
+
writeFileSync(path.join(tmpRoot, "package.json"), JSON.stringify({ private: true, workspaces: ["pkg"] }));
|
|
23
|
+
PKG_PATH = path.join(tmpRoot, "pkg");
|
|
24
|
+
CAP_PATH = path.join(PKG_PATH, ".capacitor");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
afterAll(() => {
|
|
28
|
+
rmSync(tmpRoot, { recursive: true, force: true });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe("setupCapNpmConfig", () => {
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
vi.clearAllMocks();
|
|
34
|
+
mockFsxExists.mockResolvedValue(true);
|
|
35
|
+
mockFsxReadJson.mockImplementation(((p: string) => {
|
|
36
|
+
const normalized = p.replace(/\\/g, "/");
|
|
37
|
+
if (normalized.includes(".capacitor/package.json")) {
|
|
38
|
+
return {
|
|
39
|
+
name: "com.test.app",
|
|
40
|
+
version: "1.0.0",
|
|
41
|
+
dependencies: {
|
|
42
|
+
"@capacitor/core": "^7",
|
|
43
|
+
"@capacitor/app": "^7",
|
|
44
|
+
"@capacitor/android": "^7",
|
|
45
|
+
},
|
|
46
|
+
devDependencies: {
|
|
47
|
+
"@capacitor/cli": "^7",
|
|
48
|
+
"@capacitor/assets": "^3",
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return { name: "test-pkg", version: "1.0.0" };
|
|
53
|
+
}) as never);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("루트 package.json이 없으면 에러를 던진다", async () => {
|
|
57
|
+
mockFsxExists.mockImplementation(((p: string) => {
|
|
58
|
+
const n = p.replace(/\\/g, "/");
|
|
59
|
+
if (n.endsWith("package.json") && !n.includes(".capacitor")) return false;
|
|
60
|
+
return true;
|
|
61
|
+
}) as never);
|
|
62
|
+
|
|
63
|
+
const { setupCapNpmConfig } = await import(
|
|
64
|
+
"../../src/capacitor/capacitor-npm-config.js"
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
await expect(
|
|
68
|
+
setupCapNpmConfig(CAP_PATH, PKG_PATH, {
|
|
69
|
+
appId: "com.test.app",
|
|
70
|
+
appName: "Test App",
|
|
71
|
+
}, { name: "test-pkg", version: "1.0.0" }, [], []),
|
|
72
|
+
).rejects.toThrow("루트 package.json");
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it(".capacitor/package.json이 없으면 빈 설정으로 시작한다", async () => {
|
|
76
|
+
mockFsxExists.mockImplementation(((p: string) => {
|
|
77
|
+
const n = p.replace(/\\/g, "/");
|
|
78
|
+
if (n.includes(".capacitor/package.json")) return false;
|
|
79
|
+
return true;
|
|
80
|
+
}) as never);
|
|
81
|
+
|
|
82
|
+
const { setupCapNpmConfig } = await import(
|
|
83
|
+
"../../src/capacitor/capacitor-npm-config.js"
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const changed = await setupCapNpmConfig(CAP_PATH, PKG_PATH, {
|
|
87
|
+
appId: "com.test.app",
|
|
88
|
+
appName: "Test App",
|
|
89
|
+
}, { name: "test-pkg", version: "1.0.0" }, [], []);
|
|
90
|
+
|
|
91
|
+
// 빈 설정에서 시작하므로 dependencies가 추가되어 변경됨
|
|
92
|
+
expect(changed).toBe(true);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import os from "os";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
import { gunzipSync } from "zlib";
|
|
7
|
+
import { cpx } from "@simplysm/core-node";
|
|
8
|
+
|
|
9
|
+
const tmpDirs: string[] = [];
|
|
10
|
+
|
|
11
|
+
function readTarEntry(tgzPath: string, entryName: string): string {
|
|
12
|
+
const tarBuffer = gunzipSync(fs.readFileSync(tgzPath));
|
|
13
|
+
let offset = 0;
|
|
14
|
+
|
|
15
|
+
while (offset + 512 <= tarBuffer.length) {
|
|
16
|
+
const header = tarBuffer.subarray(offset, offset + 512);
|
|
17
|
+
const name = header.toString("utf-8", 0, 100).replace(/\0.*$/s, "");
|
|
18
|
+
if (name === "") break;
|
|
19
|
+
|
|
20
|
+
const sizeText = header.toString("utf-8", 124, 136).replace(/\0.*$/s, "").trim();
|
|
21
|
+
const size = Number.parseInt(sizeText, 8);
|
|
22
|
+
const dataStart = offset + 512;
|
|
23
|
+
const dataEnd = dataStart + size;
|
|
24
|
+
|
|
25
|
+
if (name === entryName) {
|
|
26
|
+
return tarBuffer.toString("utf-8", dataStart, dataEnd);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
offset = dataStart + Math.ceil(size / 512) * 512;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
throw new Error(`tar entry not found: ${entryName}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
afterEach(() => {
|
|
36
|
+
for (const dir of tmpDirs.splice(0)) {
|
|
37
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe("npm package manifest", () => {
|
|
42
|
+
it("keeps CLI binary and replaces workspace dependency ranges in Bun pack output", async () => {
|
|
43
|
+
const pkgRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
|
44
|
+
const destination = fs.mkdtempSync(path.join(os.tmpdir(), "sd-cli-pack-"));
|
|
45
|
+
tmpDirs.push(destination);
|
|
46
|
+
|
|
47
|
+
await cpx.spawn(
|
|
48
|
+
"bun",
|
|
49
|
+
["pm", "pack", "--destination", destination, "--ignore-scripts", "--quiet"],
|
|
50
|
+
{ cwd: pkgRoot },
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const tarball = fs.readdirSync(destination).find((item) => item.endsWith(".tgz"));
|
|
54
|
+
if (tarball == null) throw new Error("package tarball not created");
|
|
55
|
+
|
|
56
|
+
const packedPackageJson = JSON.parse(
|
|
57
|
+
readTarEntry(path.join(destination, tarball), "package/package.json"),
|
|
58
|
+
) as Record<string, unknown>;
|
|
59
|
+
const bin = packedPackageJson["bin"] as Record<string, unknown>;
|
|
60
|
+
const dependencies = packedPackageJson["dependencies"] as Record<string, string>;
|
|
61
|
+
|
|
62
|
+
expect(bin["sd-cli"]).toBe("./dist/sd-cli.js");
|
|
63
|
+
expect(dependencies["@simplysm/core-common"]).not.toContain("workspace:");
|
|
64
|
+
expect(dependencies["@simplysm/core-node"]).not.toContain("workspace:");
|
|
65
|
+
expect(dependencies["@simplysm/storage"]).not.toContain("workspace:");
|
|
66
|
+
}, 120_000);
|
|
67
|
+
});
|
|
@@ -5,11 +5,16 @@ import path from "path";
|
|
|
5
5
|
import { collectDeps } from "../../../src/deps/replace-deps/collect-deps";
|
|
6
6
|
import { pathx } from "@simplysm/core-node";
|
|
7
7
|
|
|
8
|
-
describe("collectDeps —
|
|
8
|
+
describe("collectDeps — packages/ 외 워크스페이스 제외", () => {
|
|
9
9
|
let tmpDir: string;
|
|
10
10
|
|
|
11
11
|
beforeEach(() => {
|
|
12
12
|
tmpDir = pathx.posix(fs.mkdtempSync(path.join(os.tmpdir(), "sd-cli-test-")));
|
|
13
|
+
// 워크스페이스 루트 선언 (discoverWorkspacePackages는 package.json#workspaces 기반)
|
|
14
|
+
fs.writeFileSync(
|
|
15
|
+
pathx.posix(path.join(tmpDir, "package.json")),
|
|
16
|
+
JSON.stringify({ private: true, workspaces: ["packages/*", "tests/*", "plugins/*"] }),
|
|
17
|
+
);
|
|
13
18
|
});
|
|
14
19
|
|
|
15
20
|
afterEach(() => {
|
|
@@ -59,4 +64,14 @@ describe("collectDeps — tests/ 패키지 제외", () => {
|
|
|
59
64
|
expect(result.workspaceDeps).toContain("core-common");
|
|
60
65
|
expect(result.workspaceDeps).not.toContain("orm");
|
|
61
66
|
});
|
|
67
|
+
|
|
68
|
+
// Scenario: plugins/ 패키지도 packages/ 가 아니므로 workspaceDeps에서 제외된다
|
|
69
|
+
it("dependency에 plugins/ 패키지가 있어도 workspaceDeps에서 무시한다", () => {
|
|
70
|
+
createPkg("packages/my-lib", "@test/my-lib", { "@test/sd": "workspace:*" });
|
|
71
|
+
createPkg("plugins/sd", "@test/sd");
|
|
72
|
+
|
|
73
|
+
const result = collectDeps(pathx.posix(path.join(tmpDir, "packages/my-lib")), tmpDir);
|
|
74
|
+
|
|
75
|
+
expect(result.workspaceDeps).not.toContain("sd");
|
|
76
|
+
});
|
|
62
77
|
});
|
|
@@ -16,8 +16,8 @@ describe("resolveAllReplaceDepEntries", () => {
|
|
|
16
16
|
projectRoot = pathx.posix(path.join(tmpDir, "project"));
|
|
17
17
|
await fs.promises.mkdir(projectRoot, { recursive: true });
|
|
18
18
|
await fs.promises.writeFile(
|
|
19
|
-
pathx.posix(path.join(projectRoot, "
|
|
20
|
-
|
|
19
|
+
pathx.posix(path.join(projectRoot, "package.json")),
|
|
20
|
+
JSON.stringify({ private: true, workspaces: [] }),
|
|
21
21
|
);
|
|
22
22
|
});
|
|
23
23
|
|
|
@@ -66,12 +66,16 @@ describe("resolveAllReplaceDepEntries", () => {
|
|
|
66
66
|
const nodeModulesDir = pathx.posix(path.join(projectRoot, "node_modules"));
|
|
67
67
|
await createNodeModulesPkg(nodeModulesDir, "@test/pkg");
|
|
68
68
|
|
|
69
|
-
// workspace 패키지 설정 (
|
|
69
|
+
// workspace 패키지 설정 (package.json#workspaces에 추가)
|
|
70
70
|
const workspacePkgDir = pathx.posix(path.join(projectRoot, "packages", "my-app"));
|
|
71
71
|
await fs.promises.mkdir(workspacePkgDir, { recursive: true });
|
|
72
72
|
await fs.promises.writeFile(
|
|
73
|
-
pathx.posix(path.join(
|
|
74
|
-
"
|
|
73
|
+
pathx.posix(path.join(workspacePkgDir, "package.json")),
|
|
74
|
+
JSON.stringify({ name: "my-app" }),
|
|
75
|
+
);
|
|
76
|
+
await fs.promises.writeFile(
|
|
77
|
+
pathx.posix(path.join(projectRoot, "package.json")),
|
|
78
|
+
JSON.stringify({ private: true, workspaces: ["packages/*"] }),
|
|
75
79
|
);
|
|
76
80
|
|
|
77
81
|
// workspace 패키지의 node_modules에도 동일 패키지 생성
|
|
@@ -11,12 +11,12 @@ describe("setupReplaceDeps 화이트리스트 복사", () => {
|
|
|
11
11
|
beforeEach(async () => {
|
|
12
12
|
tmpDir = pathx.posix(await fs.promises.mkdtemp(path.join(os.tmpdir(), "sd-replace-deps-")));
|
|
13
13
|
|
|
14
|
-
//
|
|
14
|
+
// package.json#workspaces
|
|
15
15
|
const projectRoot = pathx.posix(path.join(tmpDir, "project"));
|
|
16
16
|
await fs.promises.mkdir(projectRoot, { recursive: true });
|
|
17
17
|
await fs.promises.writeFile(
|
|
18
|
-
pathx.posix(path.join(projectRoot, "
|
|
19
|
-
|
|
18
|
+
pathx.posix(path.join(projectRoot, "package.json")),
|
|
19
|
+
JSON.stringify({ private: true, workspaces: [] }),
|
|
20
20
|
);
|
|
21
21
|
|
|
22
22
|
// 타겟 (node_modules에 기존 패키지)
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { describe, expect, it, afterEach } from "vitest";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import os from "os";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import {
|
|
6
|
+
parseLockfileVersions,
|
|
7
|
+
resolveLockedVersions,
|
|
8
|
+
} from "../../../src/deps/server-externals/server-production-files";
|
|
9
|
+
|
|
10
|
+
const tmpDirs: string[] = [];
|
|
11
|
+
|
|
12
|
+
function createLock(content: string): string {
|
|
13
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "sd-bun-lock-"));
|
|
14
|
+
tmpDirs.push(dir);
|
|
15
|
+
fs.writeFileSync(path.join(dir, "bun.lock"), content);
|
|
16
|
+
return dir;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
afterEach(() => {
|
|
20
|
+
for (const dir of tmpDirs.splice(0)) {
|
|
21
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe("parseLockfileVersions", () => {
|
|
26
|
+
it("reads unscoped, scoped, alias, and optional entries from bun.lock", () => {
|
|
27
|
+
const cwd = createLock(`{
|
|
28
|
+
"lockfileVersion": 1,
|
|
29
|
+
"packages": {
|
|
30
|
+
"is-number": ["is-number@7.0.0", "", {}, "sha512-a"],
|
|
31
|
+
"@types/node": ["@types/node@24.13.2", "", {}, "sha512-b"],
|
|
32
|
+
"alias-pkg": ["is-number@6.0.0", "", {}, "sha512-c"],
|
|
33
|
+
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-d"],
|
|
34
|
+
}
|
|
35
|
+
}`);
|
|
36
|
+
|
|
37
|
+
const map = parseLockfileVersions(cwd);
|
|
38
|
+
|
|
39
|
+
expect(map.get("is-number")).toBe("7.0.0");
|
|
40
|
+
expect(map.get("@types/node")).toBe("24.13.2");
|
|
41
|
+
expect(map.get("alias-pkg")).toBe("6.0.0");
|
|
42
|
+
expect(map.get("fsevents")).toBe("2.3.3");
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("strips peer suffix from package references", () => {
|
|
46
|
+
const cwd = createLock(`{
|
|
47
|
+
"lockfileVersion": 1,
|
|
48
|
+
"packages": {
|
|
49
|
+
"react-dom": ["react-dom@19.2.7(react@19.2.7)", "", {}, "sha512-a"],
|
|
50
|
+
}
|
|
51
|
+
}`);
|
|
52
|
+
|
|
53
|
+
expect(parseLockfileVersions(cwd).get("react-dom")).toBe("19.2.7");
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe("resolveLockedVersions", () => {
|
|
58
|
+
it("throws when an external dependency is missing from bun.lock", () => {
|
|
59
|
+
const cwd = createLock(`{
|
|
60
|
+
"lockfileVersion": 1,
|
|
61
|
+
"packages": {
|
|
62
|
+
"is-number": ["is-number@7.0.0", "", {}, "sha512-a"],
|
|
63
|
+
}
|
|
64
|
+
}`);
|
|
65
|
+
|
|
66
|
+
expect(() => resolveLockedVersions(cwd, ["missing"])).toThrow("bun.lock");
|
|
67
|
+
});
|
|
68
|
+
});
|