@simplysm/sd-cli 14.0.64 → 14.0.65

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.
Files changed (79) hide show
  1. package/dist/capacitor/capacitor-android.d.ts +2 -0
  2. package/dist/capacitor/capacitor-android.d.ts.map +1 -1
  3. package/dist/capacitor/capacitor-android.js +13 -0
  4. package/dist/capacitor/capacitor-android.js.map +1 -1
  5. package/dist/capacitor/capacitor-npm-config.d.ts.map +1 -1
  6. package/dist/capacitor/capacitor-npm-config.js +2 -6
  7. package/dist/capacitor/capacitor-npm-config.js.map +1 -1
  8. package/dist/electron/electron.d.ts.map +1 -1
  9. package/dist/electron/electron.js +1 -2
  10. package/dist/electron/electron.js.map +1 -1
  11. package/package.json +8 -8
  12. package/src/capacitor/capacitor-android.ts +14 -0
  13. package/src/capacitor/capacitor-npm-config.ts +2 -6
  14. package/src/electron/electron.ts +1 -2
  15. package/tests/angular/ngtsc-build-core.acc.spec.ts +36 -94
  16. package/tests/capacitor/capacitor-android.spec.ts +65 -28
  17. package/tests/capacitor/capacitor-build.spec.ts +40 -385
  18. package/tests/capacitor/capacitor-config-writer.acc.spec.ts +3 -17
  19. package/tests/capacitor/capacitor-config-writer.spec.ts +3 -17
  20. package/tests/capacitor/capacitor-init.spec.ts +40 -636
  21. package/tests/capacitor/capacitor-npm-config.acc.spec.ts +38 -168
  22. package/tests/capacitor/capacitor-npm-config.spec.ts +33 -71
  23. package/tests/commands/check.spec.ts +25 -36
  24. package/tests/commands/deployment-phase.acc.spec.ts +17 -26
  25. package/tests/commands/git-phase.acc.spec.ts +13 -112
  26. package/tests/commands/lint.spec.ts +7 -24
  27. package/tests/commands/post-publish-phase.acc.spec.ts +5 -10
  28. package/tests/commands/typecheck.spec.ts +43 -65
  29. package/tests/electron/electron.spec.ts +22 -46
  30. package/tests/engines/base-engine.spec.ts +4 -13
  31. package/tests/engines/engine-selection.spec.ts +14 -17
  32. package/tests/engines/engine-typecheck-selection.acc.spec.ts +13 -16
  33. package/tests/engines/esbuild-client-engine.acc.spec.ts +36 -40
  34. package/tests/engines/esbuild-client-engine.spec.ts +4 -23
  35. package/tests/engines/ngtsc-engine.spec.ts +3 -10
  36. package/tests/engines/server-esbuild-engine.spec.ts +3 -10
  37. package/tests/engines/tsc-engine.spec.ts +3 -10
  38. package/tests/esbuild/esbuild-tsc-plugin.acc.spec.ts +3 -8
  39. package/tests/esbuild/esbuild-tsc-plugin.spec.ts +3 -8
  40. package/tests/orchestrators/build-orchestrator.spec.ts +57 -102
  41. package/tests/orchestrators/dev-orchestrator.spec.ts +68 -109
  42. package/tests/orchestrators/typecheck-orchestrator.spec.ts +25 -57
  43. package/tests/orchestrators/watch-orchestrator.spec.ts +73 -99
  44. package/tests/sd-cli-entry.spec.ts +17 -20
  45. package/tests/utils/angular-source-file-cache.spec.ts +4 -8
  46. package/tests/utils/copy-src.spec.ts +9 -20
  47. package/tests/utils/esbuild-client-config.acc.spec.ts +9 -15
  48. package/tests/utils/esbuild-client-config.spec.ts +12 -24
  49. package/tests/utils/esbuild-config.spec.ts +51 -42
  50. package/tests/utils/lint-core.spec.ts +13 -19
  51. package/tests/utils/lint-utils.spec.ts +8 -15
  52. package/tests/utils/lint-with-program.spec.ts +3 -7
  53. package/tests/utils/ngtsc-build-core.spec.ts +2 -99
  54. package/tests/utils/orchestrator-utils.spec.ts +7 -20
  55. package/tests/utils/output-utils.spec.ts +5 -11
  56. package/tests/utils/sd-config.spec.ts +4 -12
  57. package/tests/utils/typecheck-env.spec.ts +49 -77
  58. package/tests/utils/typecheck-non-package.spec.ts +23 -16
  59. package/tests/workers/build-watch-paths.acc.spec.ts +4 -10
  60. package/tests/workers/build-watch-paths.spec.ts +4 -9
  61. package/tests/workers/client-worker.acc.spec.ts +64 -137
  62. package/tests/workers/client-worker.spec.ts +63 -89
  63. package/tests/workers/library-build-lint.spec.ts +19 -30
  64. package/tests/workers/library-build-worker.spec.ts +28 -55
  65. package/tests/workers/server-esbuild-context.acc.spec.ts +6 -15
  66. package/tests/workers/server-esbuild-context.spec.ts +7 -16
  67. package/tests/workers/server-runtime-worker.spec.ts +8 -10
  68. package/tests/workers/shared-worker-lifecycle.acc.spec.ts +3 -5
  69. package/tests/workers/shared-worker-lifecycle.spec.ts +4 -5
  70. package/tests/capacitor/capacitor-icon.spec.ts +0 -285
  71. package/tests/capacitor/capacitor-run.spec.ts +0 -256
  72. package/tests/capacitor/capacitor-workspace.spec.ts +0 -203
  73. package/tests/commands/device.spec.ts +0 -237
  74. package/tests/commands/publish.spec.ts +0 -1183
  75. package/tests/utils/external-modules.spec.ts +0 -217
  76. package/tests/workers/server-build-lint.spec.ts +0 -201
  77. package/tests/workers/server-build-worker.spec.ts +0 -765
  78. package/tests/workers/server-watch-manager.acc.spec.ts +0 -162
  79. package/tests/workers/server-watch-manager.spec.ts +0 -199
@@ -1,217 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from "vitest";
2
- import path from "path";
3
-
4
- // Mock fs (readFileSync, existsSync)
5
- const mockReadFileSync = vi.fn();
6
- const mockExistsSync = vi.fn();
7
-
8
- vi.mock("fs", () => ({
9
- readFileSync: (...args: any[]) => mockReadFileSync(...args),
10
- existsSync: (...args: any[]) => mockExistsSync(...args),
11
- }));
12
-
13
- // Mock createRequire to control module resolution
14
- const mockResolve = vi.fn();
15
- vi.mock("module", () => ({
16
- createRequire: vi.fn(() => ({
17
- resolve: mockResolve,
18
- })),
19
- }));
20
-
21
- const { collectUninstalledOptionalPeerDeps, collectNativeModuleExternals, collectAllDependencyExternals } =
22
- await import("../../src/esbuild/esbuild-config");
23
-
24
- describe("collectUninstalledOptionalPeerDeps", () => {
25
- beforeEach(() => {
26
- vi.clearAllMocks();
27
- });
28
-
29
- it("detects uninstalled optional peer dependencies", () => {
30
- // Root package.json with one dependency
31
- mockReadFileSync.mockImplementation((filePath: string) => {
32
- if (filePath === path.join("/pkg", "package.json")) {
33
- return JSON.stringify({ dependencies: { "some-lib": "^1.0.0" } });
34
- }
35
- // some-lib's package.json with optional peer dep
36
- return JSON.stringify({
37
- peerDependencies: { "optional-peer": "^2.0.0" },
38
- peerDependenciesMeta: { "optional-peer": { optional: true } },
39
- });
40
- });
41
-
42
- // Resolving some-lib/package.json succeeds
43
- mockResolve.mockImplementation((name: string) => {
44
- if (name === "some-lib/package.json") {
45
- return "/node_modules/some-lib/package.json";
46
- }
47
- // optional-peer cannot be resolved (not installed)
48
- throw new Error("MODULE_NOT_FOUND");
49
- });
50
-
51
- const result = collectUninstalledOptionalPeerDeps("/pkg");
52
- expect(result).toContain("optional-peer");
53
- });
54
-
55
- it("does not include installed optional peer dependencies", () => {
56
- mockReadFileSync.mockImplementation((filePath: string) => {
57
- if (filePath === path.join("/pkg", "package.json")) {
58
- return JSON.stringify({ dependencies: { "some-lib": "^1.0.0" } });
59
- }
60
- return JSON.stringify({
61
- peerDependencies: { "installed-peer": "^2.0.0" },
62
- peerDependenciesMeta: { "installed-peer": { optional: true } },
63
- });
64
- });
65
-
66
- mockResolve.mockImplementation((name: string) => {
67
- if (name === "some-lib/package.json") {
68
- return "/node_modules/some-lib/package.json";
69
- }
70
- // installed-peer resolves successfully
71
- if (name === "installed-peer") {
72
- return "/node_modules/installed-peer/index.js";
73
- }
74
- throw new Error("MODULE_NOT_FOUND");
75
- });
76
-
77
- const result = collectUninstalledOptionalPeerDeps("/pkg");
78
- expect(result).not.toContain("installed-peer");
79
- });
80
-
81
- it("returns empty array when no optional peer deps exist", () => {
82
- mockReadFileSync.mockImplementation((filePath: string) => {
83
- if (filePath === path.join("/pkg", "package.json")) {
84
- return JSON.stringify({ dependencies: { "some-lib": "^1.0.0" } });
85
- }
86
- return JSON.stringify({ dependencies: {} });
87
- });
88
-
89
- mockResolve.mockImplementation((name: string) => {
90
- if (name === "some-lib/package.json") {
91
- return "/node_modules/some-lib/package.json";
92
- }
93
- throw new Error("MODULE_NOT_FOUND");
94
- });
95
-
96
- const result = collectUninstalledOptionalPeerDeps("/pkg");
97
- expect(result).toEqual([]);
98
- });
99
- });
100
-
101
- describe("collectNativeModuleExternals", () => {
102
- beforeEach(() => {
103
- vi.clearAllMocks();
104
- });
105
-
106
- it("detects native modules with binding.gyp", () => {
107
- mockReadFileSync.mockImplementation((filePath: string) => {
108
- if (filePath === path.join("/pkg", "package.json")) {
109
- return JSON.stringify({ dependencies: { bcrypt: "^5.0.0" } });
110
- }
111
- return JSON.stringify({ dependencies: {} });
112
- });
113
-
114
- mockResolve.mockImplementation((name: string) => {
115
- if (name === "bcrypt/package.json") {
116
- return "/node_modules/bcrypt/package.json";
117
- }
118
- throw new Error("MODULE_NOT_FOUND");
119
- });
120
-
121
- mockExistsSync.mockImplementation((filePath: string) => {
122
- return filePath === path.join("/node_modules/bcrypt", "binding.gyp");
123
- });
124
-
125
- const result = collectNativeModuleExternals("/pkg");
126
- expect(result).toContain("bcrypt");
127
- });
128
-
129
- it("does not include non-native modules", () => {
130
- mockReadFileSync.mockImplementation((filePath: string) => {
131
- if (filePath === path.join("/pkg", "package.json")) {
132
- return JSON.stringify({ dependencies: { lodash: "^4.0.0" } });
133
- }
134
- return JSON.stringify({ dependencies: {} });
135
- });
136
-
137
- mockResolve.mockImplementation((name: string) => {
138
- if (name === "lodash/package.json") {
139
- return "/node_modules/lodash/package.json";
140
- }
141
- throw new Error("MODULE_NOT_FOUND");
142
- });
143
-
144
- mockExistsSync.mockReturnValue(false);
145
-
146
- const result = collectNativeModuleExternals("/pkg");
147
- expect(result).not.toContain("lodash");
148
- expect(result).toEqual([]);
149
- });
150
- });
151
-
152
- describe("collectAllDependencyExternals", () => {
153
- beforeEach(() => {
154
- vi.clearAllMocks();
155
- });
156
-
157
- it("collects both optional peer deps and native modules in a single pass", () => {
158
- mockReadFileSync.mockImplementation((filePath: string) => {
159
- if (filePath === path.join("/pkg", "package.json")) {
160
- return JSON.stringify({
161
- dependencies: { "native-lib": "^1.0.0", "peer-lib": "^2.0.0" },
162
- });
163
- }
164
- if (filePath === "/node_modules/native-lib/package.json") {
165
- return JSON.stringify({ dependencies: {} });
166
- }
167
- if (filePath === "/node_modules/peer-lib/package.json") {
168
- return JSON.stringify({
169
- peerDependencies: { "opt-peer": "^3.0.0" },
170
- peerDependenciesMeta: { "opt-peer": { optional: true } },
171
- });
172
- }
173
- return JSON.stringify({});
174
- });
175
-
176
- mockResolve.mockImplementation((name: string) => {
177
- if (name === "native-lib/package.json") {
178
- return "/node_modules/native-lib/package.json";
179
- }
180
- if (name === "peer-lib/package.json") {
181
- return "/node_modules/peer-lib/package.json";
182
- }
183
- // opt-peer not installed
184
- throw new Error("MODULE_NOT_FOUND");
185
- });
186
-
187
- mockExistsSync.mockImplementation((filePath: string) => {
188
- return filePath === path.join("/node_modules/native-lib", "binding.gyp");
189
- });
190
-
191
- const result = collectAllDependencyExternals("/pkg");
192
- expect(result.optionalPeerDeps).toContain("opt-peer");
193
- expect(result.nativeModules).toContain("native-lib");
194
- });
195
-
196
- it("returns empty arrays when no externals are found", () => {
197
- mockReadFileSync.mockImplementation((filePath: string) => {
198
- if (filePath === path.join("/pkg", "package.json")) {
199
- return JSON.stringify({ dependencies: { "some-lib": "^1.0.0" } });
200
- }
201
- return JSON.stringify({ dependencies: {} });
202
- });
203
-
204
- mockResolve.mockImplementation((name: string) => {
205
- if (name === "some-lib/package.json") {
206
- return "/node_modules/some-lib/package.json";
207
- }
208
- throw new Error("MODULE_NOT_FOUND");
209
- });
210
-
211
- mockExistsSync.mockReturnValue(false);
212
-
213
- const result = collectAllDependencyExternals("/pkg");
214
- expect(result.optionalPeerDeps).toEqual([]);
215
- expect(result.nativeModules).toEqual([]);
216
- });
217
- });
@@ -1,201 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from "vitest";
2
-
3
- // --- Mocks ---
4
-
5
- // SdTsCompiler mock (js=false path) — lint result is part of compileAsync result
6
- const mockLintResult = {
7
- success: true,
8
- errorCount: 0,
9
- warningCount: 0,
10
- formattedOutput: "",
11
- };
12
-
13
- const mockCompileAsync = vi.fn(() => Promise.resolve({
14
- program: { getSourceFiles: () => [] },
15
- builderProgram: {},
16
- isForAngular: false,
17
- affectedFiles: undefined,
18
- diagnostics: [],
19
- errorCount: 0,
20
- warningCount: 0,
21
- errors: undefined as string[] | undefined,
22
- emitResults: undefined,
23
- lint: undefined as typeof mockLintResult | undefined,
24
- scssErrors: [],
25
- scssDependencies: new Map(),
26
- }));
27
-
28
- const MockSdTsCompiler = vi.fn().mockImplementation(function () {
29
- return { compileAsync: mockCompileAsync };
30
- });
31
-
32
- vi.mock("../../src/ts-compiler/SdTsCompiler", () => ({
33
- SdTsCompiler: MockSdTsCompiler,
34
- }));
35
-
36
- // tsc plugin mock (build() js=true path)
37
- const mockTscPlugin = {
38
- plugin: { name: "sd-tsc", setup: vi.fn() },
39
- getProgram: vi.fn(),
40
- getAffectedFiles: vi.fn(),
41
- getDiagnostics: vi.fn((): unknown[] => []),
42
- getErrors: vi.fn((): string[] | undefined => undefined),
43
- getLintResult: vi.fn((): typeof mockLintResult | undefined => undefined),
44
- resetBuilderProgram: vi.fn(),
45
- };
46
-
47
- vi.mock("../../src/esbuild/esbuild-tsc-plugin", () => ({
48
- createTscPlugin: vi.fn(() => mockTscPlugin),
49
- }));
50
-
51
- vi.mock("../../src/utils/tsconfig", () => ({
52
- parseTsconfig: vi.fn(() => ({ options: {}, fileNames: [] })),
53
- getPackageSourceFiles: vi.fn(() => []),
54
- }));
55
-
56
- vi.mock("../../src/esbuild/esbuild-config", () => ({
57
- createServerEsbuildOptions: vi.fn(() => ({})),
58
- collectAllDependencyExternals: vi.fn(() => ({ optionalPeerDeps: [], nativeModules: [] })),
59
- writeChangedOutputFiles: vi.fn(),
60
- }));
61
-
62
- vi.mock("esbuild", () => ({
63
- default: {
64
- build: vi.fn().mockResolvedValue({ errors: [], warnings: [], outputFiles: [] }),
65
- context: vi.fn().mockResolvedValue({ rebuild: vi.fn(), dispose: vi.fn() }),
66
- },
67
- }));
68
-
69
- vi.mock("../../src/runtime/worker-utils", () => ({
70
- registerCleanupHandlers: vi.fn(),
71
- createOnceGuard: vi.fn(() => vi.fn()),
72
- setupWorkerConsola: vi.fn(),
73
- }));
74
-
75
- vi.mock("../../src/utils/copy-public", () => ({
76
- copyPublicFiles: vi.fn(),
77
- watchPublicFiles: vi.fn(),
78
- }));
79
-
80
- vi.mock("../../src/deps/replace-deps/collect-deps", () => ({
81
- collectDeps: vi.fn(() => ({ workspaceDeps: [], replaceDeps: [] })),
82
- }));
83
-
84
- vi.mock("@simplysm/core-node", () => ({
85
- createWorker: vi.fn(
86
- (methods: Record<string, Function>) => {
87
- Object.assign(workerMethods, methods);
88
- return { send: vi.fn() };
89
- },
90
- ),
91
- FsWatcher: { watch: vi.fn() },
92
- pathx: {
93
- posix: vi.fn((p: string) => p.replace(/\\/g, "/")),
94
- posixResolve: vi.fn((...args: string[]) => args.join("/").replace(/\/+/g, "/").replace(/\\/g, "/")),
95
- },
96
- }));
97
-
98
- vi.mock("fs", () => ({
99
- default: {
100
- existsSync: vi.fn(() => false),
101
- readFileSync: vi.fn(() => '{"name":"test","version":"1.0.0","type":"module"}'),
102
- writeFileSync: vi.fn(),
103
- mkdirSync: vi.fn(),
104
- },
105
- }));
106
-
107
- vi.mock("execa", () => ({
108
- execaSync: vi.fn(() => ({ stdout: "v20.0.0" })),
109
- }));
110
-
111
- const workerMethods: Record<string, Function> = {};
112
-
113
- await import("../../src/workers/server-build.worker");
114
-
115
- // --- Tests ---
116
-
117
- beforeEach(() => {
118
- vi.clearAllMocks();
119
- mockCompileAsync.mockResolvedValue({
120
- program: { getSourceFiles: () => [] },
121
- builderProgram: {},
122
- isForAngular: false,
123
- affectedFiles: undefined,
124
- diagnostics: [],
125
- errorCount: 0,
126
- warningCount: 0,
127
- errors: undefined,
128
- emitResults: undefined,
129
- lint: undefined,
130
- scssErrors: [],
131
- scssDependencies: new Map(),
132
- });
133
-
134
- // Reset tsc plugin mock
135
- mockTscPlugin.getProgram.mockReset();
136
- mockTscPlugin.getAffectedFiles.mockReset();
137
- mockTscPlugin.getDiagnostics.mockReset().mockReturnValue([]);
138
- mockTscPlugin.getErrors.mockReset().mockReturnValue(undefined);
139
- mockTscPlugin.getLintResult.mockReset().mockReturnValue(undefined);
140
- mockTscPlugin.resetBuilderProgram.mockReset();
141
- });
142
-
143
- describe("server-build.worker lint integration (Slice 3)", () => {
144
- describe("Scenario: js=false lint via SdTsCompiler", () => {
145
- it("returns lint result from SdTsCompiler when lint is enabled", async () => {
146
- mockCompileAsync.mockResolvedValueOnce({
147
- program: { getSourceFiles: () => [] },
148
- builderProgram: {},
149
- isForAngular: false,
150
- affectedFiles: undefined,
151
- diagnostics: [],
152
- errorCount: 0,
153
- warningCount: 0,
154
- errors: undefined,
155
- emitResults: undefined,
156
- lint: mockLintResult,
157
- scssErrors: [],
158
- scssDependencies: new Map(),
159
- });
160
-
161
- const result = await workerMethods["build"]({
162
- name: "my-server",
163
- cwd: "/workspace",
164
- pkgDir: "/workspace/packages/my-server",
165
- output: { js: false, dts: false, lint: true },
166
- });
167
-
168
- expect(result).toHaveProperty("lint");
169
- expect(result.lint).toEqual(mockLintResult);
170
- });
171
- });
172
-
173
- describe("Scenario: js=true lint via tscPlugin.getLintResult()", () => {
174
- it("returns lint result from tsc plugin when js=true and lint enabled", async () => {
175
- mockTscPlugin.getLintResult.mockReturnValue(mockLintResult);
176
-
177
- const result = await workerMethods["build"]({
178
- name: "my-server",
179
- cwd: "/workspace",
180
- pkgDir: "/workspace/packages/my-server",
181
- output: { js: true, dts: false, lint: true },
182
- });
183
-
184
- expect(result).toHaveProperty("lint");
185
- expect(result.lint).toEqual(mockLintResult);
186
- });
187
- });
188
-
189
- describe("Scenario: lint disabled", () => {
190
- it("does not run lint when output.lint is not set", async () => {
191
- const result = await workerMethods["build"]({
192
- name: "my-server",
193
- cwd: "/workspace",
194
- pkgDir: "/workspace/packages/my-server",
195
- output: { js: false, dts: false },
196
- });
197
-
198
- expect(result.lint).toBeUndefined();
199
- });
200
- });
201
- });