@simplysm/sd-cli 13.0.75 → 13.0.77

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 (167) hide show
  1. package/README.md +341 -16
  2. package/dist/builders/DtsBuilder.js +2 -2
  3. package/dist/builders/DtsBuilder.js.map +1 -1
  4. package/dist/builders/LibraryBuilder.d.ts +3 -3
  5. package/dist/builders/LibraryBuilder.d.ts.map +1 -1
  6. package/dist/builders/LibraryBuilder.js +2 -2
  7. package/dist/builders/LibraryBuilder.js.map +1 -1
  8. package/dist/builders/types.d.ts +7 -1
  9. package/dist/builders/types.d.ts.map +1 -1
  10. package/dist/capacitor/capacitor.d.ts +5 -0
  11. package/dist/capacitor/capacitor.d.ts.map +1 -1
  12. package/dist/capacitor/capacitor.js +59 -59
  13. package/dist/capacitor/capacitor.js.map +1 -1
  14. package/dist/commands/check.js +4 -4
  15. package/dist/commands/check.js.map +1 -1
  16. package/dist/commands/device.js +3 -3
  17. package/dist/commands/device.js.map +1 -1
  18. package/dist/commands/lint.d.ts +2 -2
  19. package/dist/commands/lint.d.ts.map +1 -1
  20. package/dist/commands/lint.js +4 -98
  21. package/dist/commands/lint.js.map +1 -1
  22. package/dist/commands/publish.js +20 -20
  23. package/dist/commands/publish.js.map +1 -1
  24. package/dist/commands/replace-deps.js +1 -1
  25. package/dist/commands/replace-deps.js.map +1 -1
  26. package/dist/commands/typecheck.js +9 -9
  27. package/dist/commands/typecheck.js.map +1 -1
  28. package/dist/electron/electron.js +16 -16
  29. package/dist/electron/electron.js.map +1 -1
  30. package/dist/orchestrators/BuildOrchestrator.js +6 -6
  31. package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
  32. package/dist/orchestrators/DevOrchestrator.d.ts +7 -6
  33. package/dist/orchestrators/DevOrchestrator.d.ts.map +1 -1
  34. package/dist/orchestrators/DevOrchestrator.js +157 -203
  35. package/dist/orchestrators/DevOrchestrator.js.map +1 -1
  36. package/dist/orchestrators/WatchOrchestrator.d.ts.map +1 -1
  37. package/dist/orchestrators/WatchOrchestrator.js +3 -4
  38. package/dist/orchestrators/WatchOrchestrator.js.map +1 -1
  39. package/dist/sd-cli.js +1 -1
  40. package/dist/sd-cli.js.map +1 -1
  41. package/dist/sd-config.types.d.ts +9 -3
  42. package/dist/sd-config.types.d.ts.map +1 -1
  43. package/dist/utils/copy-public.d.ts.map +1 -1
  44. package/dist/utils/copy-public.js +23 -27
  45. package/dist/utils/copy-public.js.map +1 -1
  46. package/dist/utils/copy-src.d.ts.map +1 -1
  47. package/dist/utils/copy-src.js +7 -7
  48. package/dist/utils/copy-src.js.map +1 -1
  49. package/dist/utils/esbuild-config.d.ts.map +1 -1
  50. package/dist/utils/esbuild-config.js +36 -42
  51. package/dist/utils/esbuild-config.js.map +1 -1
  52. package/dist/utils/replace-deps.js +7 -7
  53. package/dist/utils/replace-deps.js.map +1 -1
  54. package/dist/utils/sd-config.js +2 -2
  55. package/dist/utils/sd-config.js.map +1 -1
  56. package/dist/utils/template.js +7 -7
  57. package/dist/utils/template.js.map +1 -1
  58. package/dist/utils/tsconfig.d.ts +1 -2
  59. package/dist/utils/tsconfig.d.ts.map +1 -1
  60. package/dist/utils/tsconfig.js +5 -8
  61. package/dist/utils/tsconfig.js.map +1 -1
  62. package/dist/utils/typecheck-serialization.js +2 -2
  63. package/dist/utils/typecheck-serialization.js.map +1 -1
  64. package/dist/utils/vite-config.d.ts +2 -0
  65. package/dist/utils/vite-config.d.ts.map +1 -1
  66. package/dist/utils/vite-config.js +36 -3
  67. package/dist/utils/vite-config.js.map +1 -1
  68. package/dist/utils/worker-events.d.ts +11 -1
  69. package/dist/utils/worker-events.d.ts.map +1 -1
  70. package/dist/utils/worker-events.js +3 -5
  71. package/dist/utils/worker-events.js.map +1 -1
  72. package/dist/utils/worker-utils.d.ts +2 -2
  73. package/dist/utils/worker-utils.d.ts.map +1 -1
  74. package/dist/utils/worker-utils.js +1 -1
  75. package/dist/utils/worker-utils.js.map +1 -1
  76. package/dist/workers/client.worker.d.ts +1 -1
  77. package/dist/workers/client.worker.js +3 -3
  78. package/dist/workers/client.worker.js.map +1 -1
  79. package/dist/workers/dts.worker.d.ts +1 -1
  80. package/dist/workers/dts.worker.d.ts.map +1 -1
  81. package/dist/workers/dts.worker.js +13 -28
  82. package/dist/workers/dts.worker.js.map +1 -1
  83. package/dist/workers/library.worker.d.ts +1 -1
  84. package/dist/workers/library.worker.js +4 -4
  85. package/dist/workers/library.worker.js.map +1 -1
  86. package/dist/workers/lint.worker.d.ts +1 -1
  87. package/dist/workers/server-runtime.worker.d.ts +1 -1
  88. package/dist/workers/server-runtime.worker.js +4 -4
  89. package/dist/workers/server-runtime.worker.js.map +1 -1
  90. package/dist/workers/server.worker.d.ts +1 -1
  91. package/dist/workers/server.worker.js +6 -6
  92. package/dist/workers/server.worker.js.map +1 -1
  93. package/package.json +4 -5
  94. package/src/builders/DtsBuilder.ts +2 -2
  95. package/src/builders/LibraryBuilder.ts +7 -10
  96. package/src/builders/types.ts +6 -1
  97. package/src/capacitor/capacitor.ts +61 -60
  98. package/src/commands/check.ts +4 -4
  99. package/src/commands/device.ts +3 -3
  100. package/src/commands/lint.ts +6 -117
  101. package/src/commands/publish.ts +20 -20
  102. package/src/commands/replace-deps.ts +1 -1
  103. package/src/commands/typecheck.ts +9 -9
  104. package/src/electron/electron.ts +16 -16
  105. package/src/orchestrators/BuildOrchestrator.ts +6 -6
  106. package/src/orchestrators/DevOrchestrator.ts +210 -256
  107. package/src/orchestrators/WatchOrchestrator.ts +8 -10
  108. package/src/sd-cli.ts +1 -1
  109. package/src/sd-config.types.ts +10 -3
  110. package/src/utils/copy-public.ts +22 -26
  111. package/src/utils/copy-src.ts +7 -7
  112. package/src/utils/esbuild-config.ts +51 -63
  113. package/src/utils/replace-deps.ts +7 -7
  114. package/src/utils/sd-config.ts +2 -2
  115. package/src/utils/template.ts +7 -7
  116. package/src/utils/tsconfig.ts +6 -10
  117. package/src/utils/typecheck-serialization.ts +2 -2
  118. package/src/utils/vite-config.ts +376 -341
  119. package/src/utils/worker-events.ts +13 -10
  120. package/src/utils/worker-utils.ts +45 -45
  121. package/src/workers/client.worker.ts +3 -3
  122. package/src/workers/dts.worker.ts +451 -467
  123. package/src/workers/library.worker.ts +4 -4
  124. package/src/workers/server-runtime.worker.ts +4 -4
  125. package/src/workers/server.worker.ts +572 -572
  126. package/templates/init/package.json.hbs +2 -3
  127. package/templates/init/packages/client-admin/package.json.hbs +5 -5
  128. package/templates/init/packages/client-admin/src/views/auth/LoginView.tsx +2 -2
  129. package/templates/init/packages/client-admin/src/views/home/base/employee/EmployeeDetail.tsx.hbs +86 -105
  130. package/templates/init/packages/client-admin/src/views/home/base/employee/EmployeeSheet.tsx.hbs +1 -1
  131. package/templates/init/packages/client-admin/src/views/home/base/role-permission/RoleDetail.tsx.hbs +4 -12
  132. package/templates/init/packages/client-admin/src/views/home/base/role-permission/RolePermissionDetail.tsx.hbs +0 -2
  133. package/templates/init/packages/client-admin/src/views/home/base/role-permission/RolePermissionView.tsx +1 -1
  134. package/templates/init/packages/client-admin/src/views/home/base/role-permission/RoleSheet.tsx.hbs +1 -1
  135. package/templates/init/packages/client-admin/src/views/home/my-info/MyInfoDetail.tsx.hbs +36 -43
  136. package/templates/init/packages/db-main/package.json.hbs +2 -2
  137. package/templates/init/packages/server/package.json.hbs +4 -4
  138. package/templates/init/tests/e2e/package.json.hbs +1 -1
  139. package/tests/get-compiler-options-for-package.spec.ts +13 -72
  140. package/tests/get-package-source-files.spec.ts +0 -42
  141. package/tests/get-types-from-package-json.spec.ts +15 -30
  142. package/tests/infra/ResultCollector.spec.ts +0 -9
  143. package/tests/infra/WorkerManager.spec.ts +0 -34
  144. package/tests/load-ignore-patterns.spec.ts +15 -40
  145. package/tests/load-sd-config.spec.ts +16 -53
  146. package/tests/publish-config-narrowing.spec.ts +20 -0
  147. package/tests/run-lint.spec.ts +38 -87
  148. package/tests/run-typecheck.spec.ts +194 -303
  149. package/tests/run-watch.spec.ts +0 -34
  150. package/tests/sd-cli.spec.ts +0 -88
  151. package/tests/sd-public-dev-plugin-mime.spec.ts +19 -0
  152. package/dist/builders/index.d.ts +0 -5
  153. package/dist/builders/index.d.ts.map +0 -1
  154. package/dist/builders/index.js +0 -5
  155. package/dist/builders/index.js.map +0 -6
  156. package/dist/infra/index.d.ts +0 -4
  157. package/dist/infra/index.d.ts.map +0 -1
  158. package/dist/infra/index.js +0 -4
  159. package/dist/infra/index.js.map +0 -6
  160. package/dist/orchestrators/index.d.ts +0 -4
  161. package/dist/orchestrators/index.d.ts.map +0 -1
  162. package/dist/orchestrators/index.js +0 -4
  163. package/dist/orchestrators/index.js.map +0 -6
  164. package/src/builders/index.ts +0 -4
  165. package/src/infra/index.ts +0 -3
  166. package/src/orchestrators/index.ts +0 -3
  167. package/templates/init/stylelint.config.ts +0 -1
@@ -3,12 +3,16 @@ import type ts from "typescript";
3
3
 
4
4
  // Mock core-node functions
5
5
  vi.mock("@simplysm/core-node", () => ({
6
- fsExists: vi.fn(),
7
- fsReadJson: vi.fn(),
8
- pathPosix: vi.fn((p: string) => p.replace(/\\/g, "/")),
6
+ fsx: {
7
+ exists: vi.fn(),
8
+ readJson: vi.fn(),
9
+ },
10
+ pathx: {
11
+ posix: vi.fn((p: string) => p.replace(/\\/g, "/")),
12
+ },
9
13
  }));
10
14
 
11
- import { fsExists, fsReadJson } from "@simplysm/core-node";
15
+ import { fsx } from "@simplysm/core-node";
12
16
  import { getCompilerOptionsForPackage } from "../src/utils/tsconfig";
13
17
 
14
18
  describe("getCompilerOptionsForPackage", () => {
@@ -28,8 +32,8 @@ describe("getCompilerOptionsForPackage", () => {
28
32
 
29
33
  it("node target: removes DOM lib, includes node in types", async () => {
30
34
  const packageDir = "/project/packages/core-node";
31
- vi.mocked(fsExists).mockResolvedValue(true);
32
- vi.mocked(fsReadJson).mockResolvedValue({
35
+ vi.mocked(fsx.exists).mockResolvedValue(true);
36
+ vi.mocked(fsx.readJson).mockResolvedValue({
33
37
  devDependencies: {
34
38
  "@types/express": "^4.17.0",
35
39
  },
@@ -46,8 +50,8 @@ describe("getCompilerOptionsForPackage", () => {
46
50
 
47
51
  it("browser target: keeps lib, removes node from types", async () => {
48
52
  const packageDir = "/project/packages/core-browser";
49
- vi.mocked(fsExists).mockResolvedValue(true);
50
- vi.mocked(fsReadJson).mockResolvedValue({
53
+ vi.mocked(fsx.exists).mockResolvedValue(true);
54
+ vi.mocked(fsx.readJson).mockResolvedValue({
51
55
  devDependencies: {
52
56
  "@types/node": "^20.0.0",
53
57
  "@types/react": "^18.0.0",
@@ -63,42 +67,9 @@ describe("getCompilerOptionsForPackage", () => {
63
67
  expect(result.types).toContain("react");
64
68
  });
65
69
 
66
- it("neutral target: keeps lib, includes node in types", async () => {
67
- const packageDir = "/project/packages/core-common";
68
- vi.mocked(fsExists).mockResolvedValue(true);
69
- vi.mocked(fsReadJson).mockResolvedValue({
70
- devDependencies: {
71
- "@types/lodash": "^4.0.0",
72
- },
73
- });
74
-
75
- const result = await getCompilerOptionsForPackage(baseOptions, "neutral", packageDir);
76
-
77
- // lib is preserved (includes DOM)
78
- expect(result.lib).toEqual(["ES2024", "DOM", "DOM.Iterable", "WebWorker"]);
79
- // types includes node and lodash
80
- expect(result.types).toContain("node");
81
- expect(result.types).toContain("lodash");
82
- });
83
-
84
- it("node target: removes duplicate node types", async () => {
85
- const packageDir = "/project/packages/core-node";
86
- vi.mocked(fsExists).mockResolvedValue(true);
87
- vi.mocked(fsReadJson).mockResolvedValue({
88
- devDependencies: {
89
- "@types/node": "^20.0.0",
90
- },
91
- });
92
-
93
- const result = await getCompilerOptionsForPackage(baseOptions, "node", packageDir);
94
-
95
- // node type is included only once without duplicates
96
- expect(result.types?.filter((t) => t === "node")).toHaveLength(1);
97
- });
98
-
99
70
  it("handles missing package.json with empty types", async () => {
100
71
  const packageDir = "/project/packages/unknown";
101
- vi.mocked(fsExists).mockResolvedValue(false);
72
+ vi.mocked(fsx.exists).mockResolvedValue(false);
102
73
 
103
74
  const result = await getCompilerOptionsForPackage(baseOptions, "node", packageDir);
104
75
 
@@ -106,34 +77,4 @@ describe("getCompilerOptionsForPackage", () => {
106
77
  expect(result.types).toEqual(["node"]);
107
78
  });
108
79
 
109
- it("handles undefined lib correctly", async () => {
110
- const optionsWithoutLib: ts.CompilerOptions = {
111
- strict: true,
112
- };
113
- const packageDir = "/project/packages/core-node";
114
- vi.mocked(fsExists).mockResolvedValue(false);
115
-
116
- const result = await getCompilerOptionsForPackage(optionsWithoutLib, "node", packageDir);
117
-
118
- // handles undefined lib without error
119
- expect(result.lib).toBeUndefined();
120
- expect(result.types).toEqual(["node"]);
121
- });
122
-
123
- it("does not mutate original baseOptions (immutability)", async () => {
124
- const originalOptions: ts.CompilerOptions = {
125
- lib: ["ES2024", "DOM"],
126
- types: ["original"],
127
- strict: true,
128
- };
129
- const packageDir = "/project/packages/core-node";
130
- vi.mocked(fsExists).mockResolvedValue(false);
131
-
132
- await getCompilerOptionsForPackage(originalOptions, "node", packageDir);
133
-
134
- // original options are not changed
135
- expect(originalOptions.lib).toEqual(["ES2024", "DOM"]);
136
- expect(originalOptions.types).toEqual(["original"]);
137
- expect(originalOptions.noEmit).toBeUndefined();
138
- });
139
80
  });
@@ -4,8 +4,6 @@ import type ts from "typescript";
4
4
  import { getPackageSourceFiles, getPackageFiles } from "../src/utils/tsconfig";
5
5
 
6
6
  describe("getPackageSourceFiles", () => {
7
- const sep = path.sep;
8
-
9
7
  it("filters files within package src directory only", () => {
10
8
  const pkgDir = `/project/packages/core-common`;
11
9
  const parsedConfig = {
@@ -60,35 +58,6 @@ describe("getPackageSourceFiles", () => {
60
58
  ]);
61
59
  });
62
60
 
63
- it("returns empty array if no files", () => {
64
- const pkgDir = `/project/packages/empty`;
65
- const parsedConfig = {
66
- fileNames: [
67
- `/project/packages/core/src/index.ts`,
68
- `/project/packages/core-common/src/index.ts`,
69
- ],
70
- } as ts.ParsedCommandLine;
71
-
72
- const result = getPackageSourceFiles(pkgDir, parsedConfig);
73
-
74
- expect(result).toEqual([]);
75
- });
76
-
77
- it("handles path separators correctly", () => {
78
- // use path.sep for platform-independent test
79
- const pkgDir = `${sep}project${sep}packages${sep}core`;
80
- const parsedConfig = {
81
- fileNames: [
82
- `${sep}project${sep}packages${sep}core${sep}src${sep}index.ts`,
83
- `${sep}project${sep}packages${sep}core-common${sep}src${sep}index.ts`,
84
- ],
85
- } as ts.ParsedCommandLine;
86
-
87
- const result = getPackageSourceFiles(pkgDir, parsedConfig);
88
-
89
- expect(result).toEqual([`${sep}project${sep}packages${sep}core${sep}src${sep}index.ts`]);
90
- });
91
-
92
61
  it("handles forward slash paths from TypeScript API correctly (Windows compatible)", () => {
93
62
  // TypeScript API returns forward slash paths even on Windows
94
63
  // pkgDir is created with path.join using OS-native separator
@@ -152,17 +121,6 @@ describe("getPackageFiles", () => {
152
121
  ]);
153
122
  });
154
123
 
155
- it("returns empty array if no files", () => {
156
- const pkgDir = `/project/packages/empty`;
157
- const parsedConfig = {
158
- fileNames: [`/project/packages/core/src/index.ts`],
159
- } as ts.ParsedCommandLine;
160
-
161
- const result = getPackageFiles(pkgDir, parsedConfig);
162
-
163
- expect(result).toEqual([]);
164
- });
165
-
166
124
  it("handles forward slash paths from TypeScript API correctly (Windows compatible)", () => {
167
125
  const pkgDir = path.resolve("/project/packages/core-common");
168
126
  const parsedConfig = {
@@ -3,12 +3,16 @@ import path from "path";
3
3
 
4
4
  // Mock core-node functions
5
5
  vi.mock("@simplysm/core-node", () => ({
6
- fsExists: vi.fn(),
7
- fsReadJson: vi.fn(),
8
- pathPosix: vi.fn((p: string) => p.replace(/\\/g, "/")),
6
+ fsx: {
7
+ exists: vi.fn(),
8
+ readJson: vi.fn(),
9
+ },
10
+ pathx: {
11
+ posix: vi.fn((p: string) => p.replace(/\\/g, "/")),
12
+ },
9
13
  }));
10
14
 
11
- import { fsExists, fsReadJson } from "@simplysm/core-node";
15
+ import { fsx } from "@simplysm/core-node";
12
16
  import { getTypesFromPackageJson } from "../src/utils/tsconfig";
13
17
 
14
18
  describe("getTypesFromPackageJson", () => {
@@ -22,8 +26,8 @@ describe("getTypesFromPackageJson", () => {
22
26
 
23
27
  it("converts @types/* devDependencies to types list", async () => {
24
28
  const packageDir = "/project/packages/core-common";
25
- const mockFsExists = vi.mocked(fsExists);
26
- const mockFsReadJson = vi.mocked(fsReadJson);
29
+ const mockFsExists = vi.mocked(fsx.exists);
30
+ const mockFsReadJson = vi.mocked(fsx.readJson);
27
31
 
28
32
  mockFsExists.mockResolvedValue(true);
29
33
  mockFsReadJson.mockResolvedValue({
@@ -43,7 +47,7 @@ describe("getTypesFromPackageJson", () => {
43
47
 
44
48
  it("returns empty array if package.json does not exist", async () => {
45
49
  const packageDir = "/project/packages/unknown";
46
- const mockFsExists = vi.mocked(fsExists);
50
+ const mockFsExists = vi.mocked(fsx.exists);
47
51
 
48
52
  mockFsExists.mockResolvedValue(false);
49
53
 
@@ -54,8 +58,8 @@ describe("getTypesFromPackageJson", () => {
54
58
 
55
59
  it("returns empty array if devDependencies does not exist", async () => {
56
60
  const packageDir = "/project/packages/core-common";
57
- const mockFsExists = vi.mocked(fsExists);
58
- const mockFsReadJson = vi.mocked(fsReadJson);
61
+ const mockFsExists = vi.mocked(fsx.exists);
62
+ const mockFsReadJson = vi.mocked(fsx.readJson);
59
63
 
60
64
  mockFsExists.mockResolvedValue(true);
61
65
  mockFsReadJson.mockResolvedValue({
@@ -68,29 +72,10 @@ describe("getTypesFromPackageJson", () => {
68
72
  expect(result).toEqual([]);
69
73
  });
70
74
 
71
- it("filters out dependencies that are not @types/*", async () => {
72
- const packageDir = "/project/packages/core-common";
73
- const mockFsExists = vi.mocked(fsExists);
74
- const mockFsReadJson = vi.mocked(fsReadJson);
75
-
76
- mockFsExists.mockResolvedValue(true);
77
- mockFsReadJson.mockResolvedValue({
78
- devDependencies: {
79
- typescript: "^5.0.0",
80
- vitest: "^1.0.0",
81
- eslint: "^9.0.0",
82
- },
83
- });
84
-
85
- const result = await getTypesFromPackageJson(packageDir);
86
-
87
- expect(result).toEqual([]);
88
- });
89
-
90
75
  it("handles scoped @types packages correctly", async () => {
91
76
  const packageDir = "/project/packages/core-common";
92
- const mockFsExists = vi.mocked(fsExists);
93
- const mockFsReadJson = vi.mocked(fsReadJson);
77
+ const mockFsExists = vi.mocked(fsx.exists);
78
+ const mockFsReadJson = vi.mocked(fsx.readJson);
94
79
 
95
80
  mockFsExists.mockResolvedValue(true);
96
81
  mockFsReadJson.mockResolvedValue({
@@ -27,13 +27,4 @@ describe("ResultCollector", () => {
27
27
  expect(collector.toMap().size).toBe(1);
28
28
  });
29
29
 
30
- it("returns internal Map", () => {
31
- const collector = new ResultCollector();
32
- collector.add({ name: "pkg1", target: "node", type: "build", status: "success" });
33
-
34
- const map = collector.toMap();
35
-
36
- expect(map).toBeInstanceOf(Map);
37
- expect(map.size).toBe(1);
38
- });
39
30
  });
@@ -26,12 +26,6 @@ describe("WorkerManager", () => {
26
26
  expect(manager.get("test-worker")).toBe(worker);
27
27
  });
28
28
 
29
- it("returns undefined when retrieving a non-existent Worker", () => {
30
- const manager = new WorkerManager();
31
-
32
- expect(manager.get("nonexistent")).toBeUndefined();
33
- });
34
-
35
29
  it("terminates all Workers", async () => {
36
30
  const manager = new WorkerManager();
37
31
  const worker1 = manager.create("worker1", "/path/to/worker.ts");
@@ -57,34 +51,6 @@ describe("WorkerManager", () => {
57
51
  expect(manager.get("worker2")).toBe(worker2);
58
52
  });
59
53
 
60
- it("handles terminating a non-existent Worker without error", async () => {
61
- const manager = new WorkerManager();
62
-
63
- await expect(manager.terminate("nonexistent")).resolves.toBeUndefined();
64
- });
65
-
66
- it("retrieves the count of managed Workers", () => {
67
- const manager = new WorkerManager();
68
-
69
- expect(manager.size).toBe(0);
70
-
71
- manager.create("worker1", "/path/to/worker.ts");
72
- expect(manager.size).toBe(1);
73
-
74
- manager.create("worker2", "/path/to/worker.ts");
75
- expect(manager.size).toBe(2);
76
- });
77
-
78
- it("retrieves list of all Worker IDs", () => {
79
- const manager = new WorkerManager();
80
- manager.create("worker1", "/path/to/worker.ts");
81
- manager.create("worker2", "/path/to/worker.ts");
82
-
83
- const ids = manager.ids;
84
-
85
- expect(ids).toEqual(["worker1", "worker2"]);
86
- });
87
-
88
54
  it("overwrites existing Worker when creating with the same ID", () => {
89
55
  const manager = new WorkerManager();
90
56
  const worker1 = manager.create("same-id", "/path/to/worker1.ts");
@@ -4,8 +4,12 @@ import path from "path";
4
4
 
5
5
  // Mock core-node functions and jiti
6
6
  vi.mock("@simplysm/core-node", () => ({
7
- fsExists: vi.fn(),
8
- pathPosix: vi.fn(),
7
+ fsx: {
8
+ exists: vi.fn(),
9
+ },
10
+ pathx: {
11
+ posix: vi.fn(),
12
+ },
9
13
  }));
10
14
 
11
15
  const mockJitiImportFn = vi.fn();
@@ -15,7 +19,7 @@ vi.mock("jiti", () => ({
15
19
  })),
16
20
  }));
17
21
 
18
- import { fsExists } from "@simplysm/core-node";
22
+ import { fsx } from "@simplysm/core-node";
19
23
 
20
24
  describe("loadIgnorePatterns", () => {
21
25
  beforeEach(() => {
@@ -28,7 +32,7 @@ describe("loadIgnorePatterns", () => {
28
32
 
29
33
  it("extracts globalIgnores pattern from eslint.config.ts", async () => {
30
34
  const cwd = "/project";
31
- const mockExists = vi.mocked(fsExists);
35
+ const mockExists = vi.mocked(fsx.exists);
32
36
 
33
37
  mockExists.mockImplementation((filePath: string) => {
34
38
  return Promise.resolve(filePath === path.join(cwd, "eslint.config.ts"));
@@ -45,7 +49,7 @@ describe("loadIgnorePatterns", () => {
45
49
 
46
50
  it("does not extract as globalIgnores if files is present", async () => {
47
51
  const cwd = "/project";
48
- const mockExists = vi.mocked(fsExists);
52
+ const mockExists = vi.mocked(fsx.exists);
49
53
 
50
54
  mockExists.mockImplementation((filePath: string) => {
51
55
  return Promise.resolve(filePath === path.join(cwd, "eslint.config.ts"));
@@ -66,7 +70,7 @@ describe("loadIgnorePatterns", () => {
66
70
 
67
71
  it("throws error if config file not found", async () => {
68
72
  const cwd = "/project";
69
- const mockExists = vi.mocked(fsExists);
73
+ const mockExists = vi.mocked(fsx.exists);
70
74
 
71
75
  mockExists.mockResolvedValue(false);
72
76
 
@@ -75,7 +79,7 @@ describe("loadIgnorePatterns", () => {
75
79
 
76
80
  it("throws error if config is not array", async () => {
77
81
  const cwd = "/project";
78
- const mockExists = vi.mocked(fsExists);
82
+ const mockExists = vi.mocked(fsx.exists);
79
83
 
80
84
  mockExists.mockImplementation((filePath: string) => {
81
85
  return Promise.resolve(filePath === path.join(cwd, "eslint.config.ts"));
@@ -90,7 +94,7 @@ describe("loadIgnorePatterns", () => {
90
94
 
91
95
  it("merges multiple globalIgnores settings", async () => {
92
96
  const cwd = "/project";
93
- const mockExists = vi.mocked(fsExists);
97
+ const mockExists = vi.mocked(fsx.exists);
94
98
 
95
99
  mockExists.mockImplementation((filePath: string) => {
96
100
  return Promise.resolve(filePath === path.join(cwd, "eslint.config.ts"));
@@ -107,7 +111,7 @@ describe("loadIgnorePatterns", () => {
107
111
 
108
112
  it("handles config that directly exports array", async () => {
109
113
  const cwd = "/project";
110
- const mockExists = vi.mocked(fsExists);
114
+ const mockExists = vi.mocked(fsx.exists);
111
115
 
112
116
  mockExists.mockImplementation((filePath: string) => {
113
117
  return Promise.resolve(filePath === path.join(cwd, "eslint.config.js"));
@@ -122,7 +126,7 @@ describe("loadIgnorePatterns", () => {
122
126
 
123
127
  it("throws error if config has no default and is not array", async () => {
124
128
  const cwd = "/project";
125
- const mockExists = vi.mocked(fsExists);
129
+ const mockExists = vi.mocked(fsx.exists);
126
130
 
127
131
  mockExists.mockImplementation((filePath: string) => {
128
132
  return Promise.resolve(filePath === path.join(cwd, "eslint.config.ts"));
@@ -139,7 +143,7 @@ describe("loadIgnorePatterns", () => {
139
143
 
140
144
  it("uses mts file if eslint.config.ts not found", async () => {
141
145
  const cwd = "/project";
142
- const mockExists = vi.mocked(fsExists);
146
+ const mockExists = vi.mocked(fsx.exists);
143
147
 
144
148
  mockExists.mockImplementation((filePath: string) => {
145
149
  // eslint.config.ts does not exist, only eslint.config.mts
@@ -156,33 +160,4 @@ describe("loadIgnorePatterns", () => {
156
160
  expect(mockJitiImportFn).toHaveBeenCalledWith(expect.stringContaining("eslint.config.mts"));
157
161
  });
158
162
 
159
- it("returns empty pattern array if empty array exported", async () => {
160
- const cwd = "/project";
161
- const mockExists = vi.mocked(fsExists);
162
-
163
- mockExists.mockImplementation((filePath: string) => {
164
- return Promise.resolve(filePath === path.join(cwd, "eslint.config.ts"));
165
- });
166
-
167
- mockJitiImportFn.mockResolvedValue({
168
- default: [],
169
- });
170
-
171
- const patterns = await loadIgnorePatterns(cwd);
172
-
173
- expect(patterns).toEqual([]);
174
- });
175
-
176
- it("propagates error if jiti import fails", async () => {
177
- const cwd = "/project";
178
- const mockExists = vi.mocked(fsExists);
179
-
180
- mockExists.mockImplementation((filePath: string) => {
181
- return Promise.resolve(filePath === path.join(cwd, "eslint.config.ts"));
182
- });
183
-
184
- mockJitiImportFn.mockRejectedValue(new Error("Syntax error in config file"));
185
-
186
- await expect(loadIgnorePatterns(cwd)).rejects.toThrow("Syntax error in config file");
187
- });
188
163
  });
@@ -3,7 +3,9 @@ import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
3
3
  const mockJitiImport = vi.fn();
4
4
 
5
5
  vi.mock("@simplysm/core-node", () => ({
6
- fsExists: vi.fn(),
6
+ fsx: {
7
+ exists: vi.fn(),
8
+ },
7
9
  }));
8
10
 
9
11
  vi.mock("jiti", () => ({
@@ -12,7 +14,7 @@ vi.mock("jiti", () => ({
12
14
  })),
13
15
  }));
14
16
 
15
- import { fsExists } from "@simplysm/core-node";
17
+ import { fsx } from "@simplysm/core-node";
16
18
  import { loadSdConfig } from "../src/utils/sd-config";
17
19
 
18
20
  describe("loadSdConfig", () => {
@@ -25,70 +27,48 @@ describe("loadSdConfig", () => {
25
27
  });
26
28
 
27
29
  it("throws error if sd.config.ts file not found", async () => {
28
- vi.mocked(fsExists).mockResolvedValue(false);
30
+ vi.mocked(fsx.exists).mockResolvedValue(false);
29
31
 
30
- await expect(loadSdConfig({ cwd: "/project", dev: false, opt: [] })).rejects.toThrow(
32
+ await expect(loadSdConfig({ cwd: "/project", dev: false, options: [] })).rejects.toThrow(
31
33
  "sd.config.ts file not found",
32
34
  );
33
35
  });
34
36
 
35
37
  it("throws error if no default export", async () => {
36
- vi.mocked(fsExists).mockResolvedValue(true);
38
+ vi.mocked(fsx.exists).mockResolvedValue(true);
37
39
  mockJitiImport.mockResolvedValue({
38
40
  someOtherExport: () => ({}),
39
41
  });
40
42
 
41
- await expect(loadSdConfig({ cwd: "/project", dev: false, opt: [] })).rejects.toThrow(
43
+ await expect(loadSdConfig({ cwd: "/project", dev: false, options: [] })).rejects.toThrow(
42
44
  "sd.config.ts must export a function as default",
43
45
  );
44
46
  });
45
47
 
46
48
  it("throws error if default export is not function", async () => {
47
- vi.mocked(fsExists).mockResolvedValue(true);
49
+ vi.mocked(fsx.exists).mockResolvedValue(true);
48
50
  mockJitiImport.mockResolvedValue({
49
51
  default: { packages: {} }, // object not function
50
52
  });
51
53
 
52
- await expect(loadSdConfig({ cwd: "/project", dev: false, opt: [] })).rejects.toThrow(
54
+ await expect(loadSdConfig({ cwd: "/project", dev: false, options: [] })).rejects.toThrow(
53
55
  "sd.config.ts must export a function as default",
54
56
  );
55
57
  });
56
58
 
57
59
  it("throws error if return value is wrong format (missing packages)", async () => {
58
- vi.mocked(fsExists).mockResolvedValue(true);
60
+ vi.mocked(fsx.exists).mockResolvedValue(true);
59
61
  mockJitiImport.mockResolvedValue({
60
62
  default: () => ({}), // missing packages property
61
63
  });
62
64
 
63
- await expect(loadSdConfig({ cwd: "/project", dev: false, opt: [] })).rejects.toThrow(
64
- /sd\.config\.ts return value is not in .* correct format/,
65
- );
66
- });
67
-
68
- it("throws error if return value is wrong format (packages is array)", async () => {
69
- vi.mocked(fsExists).mockResolvedValue(true);
70
- mockJitiImport.mockResolvedValue({
71
- default: () => ({ packages: [] }), // packages is array
72
- });
73
-
74
- await expect(loadSdConfig({ cwd: "/project", dev: false, opt: [] })).rejects.toThrow(
75
- /sd\.config\.ts return value is not in .* correct format/,
76
- );
77
- });
78
-
79
- it("throws error if return value is wrong format (packages is null)", async () => {
80
- vi.mocked(fsExists).mockResolvedValue(true);
81
- mockJitiImport.mockResolvedValue({
82
- default: () => ({ packages: null }),
83
- });
84
-
85
- await expect(loadSdConfig({ cwd: "/project", dev: false, opt: [] })).rejects.toThrow(
65
+ await expect(loadSdConfig({ cwd: "/project", dev: false, options: [] })).rejects.toThrow(
86
66
  /sd\.config\.ts return value is not in .* correct format/,
87
67
  );
88
68
  });
89
69
 
90
70
  it("returns correct config", async () => {
91
- vi.mocked(fsExists).mockResolvedValue(true);
71
+ vi.mocked(fsx.exists).mockResolvedValue(true);
92
72
  mockJitiImport.mockResolvedValue({
93
73
  default: () => ({
94
74
  packages: {
@@ -98,7 +78,7 @@ describe("loadSdConfig", () => {
98
78
  }),
99
79
  });
100
80
 
101
- const config = await loadSdConfig({ cwd: "/project", dev: false, opt: [] });
81
+ const config = await loadSdConfig({ cwd: "/project", dev: false, options: [] });
102
82
 
103
83
  expect(config.packages).toEqual({
104
84
  "core-common": { target: "neutral" },
@@ -107,31 +87,14 @@ describe("loadSdConfig", () => {
107
87
  });
108
88
 
109
89
  it("empty packages object is valid", async () => {
110
- vi.mocked(fsExists).mockResolvedValue(true);
90
+ vi.mocked(fsx.exists).mockResolvedValue(true);
111
91
  mockJitiImport.mockResolvedValue({
112
92
  default: () => ({ packages: {} }),
113
93
  });
114
94
 
115
- const config = await loadSdConfig({ cwd: "/project", dev: false, opt: [] });
95
+ const config = await loadSdConfig({ cwd: "/project", dev: false, options: [] });
116
96
 
117
97
  expect(config.packages).toEqual({});
118
98
  });
119
99
 
120
- it("handles async function default export correctly", async () => {
121
- vi.mocked(fsExists).mockResolvedValue(true);
122
- mockJitiImport.mockResolvedValue({
123
- // eslint-disable-next-line @typescript-eslint/require-await
124
- default: async () => ({
125
- packages: {
126
- "core-common": { target: "neutral" },
127
- },
128
- }),
129
- });
130
-
131
- const config = await loadSdConfig({ cwd: "/project", dev: false, opt: [] });
132
-
133
- expect(config.packages).toEqual({
134
- "core-common": { target: "neutral" },
135
- });
136
- });
137
100
  });
@@ -0,0 +1,20 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import type { SdPublishConfig, SdNpmPublishConfig } from "../src/sd-config.types";
3
+
4
+ describe("SdPublishConfig", () => {
5
+ it("all variants have .type field for uniform narrowing", () => {
6
+ const configs: SdPublishConfig[] = [
7
+ { type: "npm" },
8
+ { type: "local-directory", path: "/deploy" },
9
+ { type: "ftp", host: "example.com" },
10
+ ];
11
+
12
+ const types = configs.map((c) => c.type);
13
+ expect(types).toEqual(["npm", "local-directory", "ftp"]);
14
+ });
15
+
16
+ it("npm config is an object with type field", () => {
17
+ const npmConfig: SdNpmPublishConfig = { type: "npm" };
18
+ expect(npmConfig.type).toBe("npm");
19
+ });
20
+ });