@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
@@ -8,13 +8,20 @@ export type BuildTarget = "node" | "browser" | "neutral";
8
8
 
9
9
  //#region Publish configuration types
10
10
 
11
+ /**
12
+ * npm registry publish configuration
13
+ */
14
+ export interface SdNpmPublishConfig {
15
+ type: "npm";
16
+ }
17
+
11
18
  /**
12
19
  * Package publish configuration
13
- * - "npm": deploy to npm registry
20
+ * - SdNpmPublishConfig: deploy to npm registry
14
21
  * - SdLocalDirectoryPublishConfig: copy to local directory
15
22
  * - SdStoragePublishConfig: upload to FTP/FTPS/SFTP server
16
23
  */
17
- export type SdPublishConfig = "npm" | SdLocalDirectoryPublishConfig | SdStoragePublishConfig;
24
+ export type SdPublishConfig = SdNpmPublishConfig | SdLocalDirectoryPublishConfig | SdStoragePublishConfig;
18
25
 
19
26
  /**
20
27
  * Local directory publish configuration
@@ -249,7 +256,7 @@ export interface SdConfigParams {
249
256
  /** development mode flag */
250
257
  dev: boolean;
251
258
  /** additional options (from CLI's -o flag) */
252
- opt: string[];
259
+ options: string[];
253
260
  }
254
261
 
255
262
  /**
@@ -1,12 +1,8 @@
1
1
  import path from "path";
2
2
  import {
3
- fsCopy,
4
- fsMkdir,
5
- fsRm,
6
- fsGlob,
3
+ fsx,
4
+ pathx,
7
5
  FsWatcher,
8
- fsExists,
9
- pathIsChildPath,
10
6
  } from "@simplysm/core-node";
11
7
 
12
8
  /**
@@ -18,30 +14,30 @@ import {
18
14
  */
19
15
  export async function copyPublicFiles(pkgDir: string, includeDev: boolean): Promise<void> {
20
16
  const distDir = path.join(pkgDir, "dist");
21
- await fsMkdir(distDir);
17
+ await fsx.mkdir(distDir);
22
18
 
23
19
  // Copy public/
24
20
  const publicDir = path.join(pkgDir, "public");
25
- if (await fsExists(publicDir)) {
26
- const files = await fsGlob("**/*", { cwd: publicDir, absolute: true });
21
+ if (await fsx.exists(publicDir)) {
22
+ const files = await fsx.glob("**/*", { cwd: publicDir, absolute: true });
27
23
  for (const file of files) {
28
24
  const relativePath = path.relative(publicDir, file);
29
25
  const distPath = path.join(distDir, relativePath);
30
- await fsMkdir(path.dirname(distPath));
31
- await fsCopy(file, distPath);
26
+ await fsx.mkdir(path.dirname(distPath));
27
+ await fsx.copy(file, distPath);
32
28
  }
33
29
  }
34
30
 
35
31
  // Copy public-dev/ (overlay: overwrites public/)
36
32
  if (includeDev) {
37
33
  const publicDevDir = path.join(pkgDir, "public-dev");
38
- if (await fsExists(publicDevDir)) {
39
- const files = await fsGlob("**/*", { cwd: publicDevDir, absolute: true });
34
+ if (await fsx.exists(publicDevDir)) {
35
+ const files = await fsx.glob("**/*", { cwd: publicDevDir, absolute: true });
40
36
  for (const file of files) {
41
37
  const relativePath = path.relative(publicDevDir, file);
42
38
  const distPath = path.join(distDir, relativePath);
43
- await fsMkdir(path.dirname(distPath));
44
- await fsCopy(file, distPath);
39
+ await fsx.mkdir(path.dirname(distPath));
40
+ await fsx.copy(file, distPath);
45
41
  }
46
42
  }
47
43
  }
@@ -68,10 +64,10 @@ export async function watchPublicFiles(
68
64
 
69
65
  // Collect watch target paths
70
66
  const watchPaths: string[] = [];
71
- if (await fsExists(publicDir)) {
67
+ if (await fsx.exists(publicDir)) {
72
68
  watchPaths.push(path.join(publicDir, "**/*"));
73
69
  }
74
- if (includeDev && (await fsExists(publicDevDir))) {
70
+ if (includeDev && (await fsx.exists(publicDevDir))) {
75
71
  watchPaths.push(path.join(publicDevDir, "**/*"));
76
72
  }
77
73
 
@@ -85,7 +81,7 @@ export async function watchPublicFiles(
85
81
  for (const { event, path: filePath } of changes) {
86
82
  // Determine which source directory the change came from
87
83
  let sourceDir: string;
88
- if (pathIsChildPath(filePath, publicDevDir)) {
84
+ if (pathx.isChildPath(filePath, publicDevDir)) {
89
85
  sourceDir = publicDevDir;
90
86
  } else {
91
87
  sourceDir = publicDir;
@@ -98,30 +94,30 @@ export async function watchPublicFiles(
98
94
  // If deleted from public, don't delete if same file exists in public-dev
99
95
  if (sourceDir === publicDir && includeDev) {
100
96
  const devOverride = path.join(publicDevDir, relPath);
101
- if (await fsExists(devOverride)) {
97
+ if (await fsx.exists(devOverride)) {
102
98
  continue;
103
99
  }
104
100
  }
105
101
  // If deleted from public-dev, restore from public if it exists (fallback restore)
106
102
  if (sourceDir === publicDevDir && includeDev) {
107
103
  const publicFallback = path.join(publicDir, relPath);
108
- if (await fsExists(publicFallback)) {
109
- await fsMkdir(path.dirname(distPath));
110
- await fsCopy(publicFallback, distPath);
104
+ if (await fsx.exists(publicFallback)) {
105
+ await fsx.mkdir(path.dirname(distPath));
106
+ await fsx.copy(publicFallback, distPath);
111
107
  continue;
112
108
  }
113
109
  }
114
- await fsRm(distPath);
110
+ await fsx.rm(distPath);
115
111
  } else if (event === "add" || event === "change") {
116
112
  // If changed in public, skip if same file exists in public-dev (overlay takes priority)
117
113
  if (sourceDir === publicDir && includeDev) {
118
114
  const devOverride = path.join(publicDevDir, relPath);
119
- if (await fsExists(devOverride)) {
115
+ if (await fsx.exists(devOverride)) {
120
116
  continue;
121
117
  }
122
118
  }
123
- await fsMkdir(path.dirname(distPath));
124
- await fsCopy(filePath, distPath);
119
+ await fsx.mkdir(path.dirname(distPath));
120
+ await fsx.copy(filePath, distPath);
125
121
  }
126
122
  }
127
123
  });
@@ -1,5 +1,5 @@
1
1
  import path from "path";
2
- import { fsGlob, fsCopy, fsMkdir, fsRm, FsWatcher } from "@simplysm/core-node";
2
+ import { fsx, FsWatcher } from "@simplysm/core-node";
3
3
 
4
4
  /**
5
5
  * Copy files matching glob patterns from src/ to dist/
@@ -13,12 +13,12 @@ export async function copySrcFiles(pkgDir: string, patterns: string[]): Promise<
13
13
  const distDir = path.join(pkgDir, "dist");
14
14
 
15
15
  for (const pattern of patterns) {
16
- const files = await fsGlob(pattern, { cwd: srcDir, absolute: true });
16
+ const files = await fsx.glob(pattern, { cwd: srcDir, absolute: true });
17
17
  for (const file of files) {
18
18
  const relativePath = path.relative(srcDir, file);
19
19
  const distPath = path.join(distDir, relativePath);
20
- await fsMkdir(path.dirname(distPath));
21
- await fsCopy(file, distPath);
20
+ await fsx.mkdir(path.dirname(distPath));
21
+ await fsx.copy(file, distPath);
22
22
  }
23
23
  }
24
24
  }
@@ -48,10 +48,10 @@ export async function watchCopySrcFiles(pkgDir: string, patterns: string[]): Pro
48
48
  const distPath = path.join(distDir, relPath);
49
49
 
50
50
  if (event === "unlink") {
51
- await fsRm(distPath);
51
+ await fsx.rm(distPath);
52
52
  } else if (event === "add" || event === "change") {
53
- await fsMkdir(path.dirname(distPath));
54
- await fsCopy(filePath, distPath);
53
+ await fsx.mkdir(path.dirname(distPath));
54
+ await fsx.copy(filePath, distPath);
55
55
  }
56
56
  }
57
57
  });
@@ -165,28 +165,14 @@ interface PkgJson {
165
165
  }
166
166
 
167
167
  /**
168
- * Collect uninstalled optional peer deps from dependency tree
169
- *
170
- * For server builds (bundle: true), specify uninstalled optional peer dependencies
171
- * as esbuild externals to prevent build failures
168
+ * Recursively scan dependency tree and collect externals based on predicate
172
169
  */
173
- export function collectUninstalledOptionalPeerDeps(pkgDir: string): string[] {
174
- const external = new Set<string>();
175
- const visited = new Set<string>();
176
-
177
- const pkgJson = JSON.parse(readFileSync(path.join(pkgDir, "package.json"), "utf-8")) as PkgJson;
178
- for (const dep of Object.keys(pkgJson.dependencies ?? {})) {
179
- scanOptionalPeerDeps(dep, pkgDir, external, visited);
180
- }
181
-
182
- return [...external];
183
- }
184
-
185
- function scanOptionalPeerDeps(
170
+ function scanDependencyTree(
186
171
  pkgName: string,
187
172
  resolveDir: string,
188
173
  external: Set<string>,
189
174
  visited: Set<string>,
175
+ collector: (pkgName: string, depDir: string, pkgJson: PkgJson) => string[],
190
176
  ): void {
191
177
  if (visited.has(pkgName)) return;
192
178
  visited.add(pkgName);
@@ -203,23 +189,50 @@ function scanOptionalPeerDeps(
203
189
  const depDir = path.dirname(pkgJsonPath);
204
190
  const pkgJson = JSON.parse(readFileSync(pkgJsonPath, "utf-8")) as PkgJson;
205
191
 
206
- if (pkgJson.peerDependenciesMeta != null) {
207
- const peerDeps = pkgJson.peerDependencies ?? {};
208
- const depReq = createRequire(path.join(depDir, "noop.js"));
209
- for (const [name, meta] of Object.entries(pkgJson.peerDependenciesMeta)) {
210
- if (meta.optional === true && name in peerDeps) {
211
- try {
212
- depReq.resolve(name);
213
- } catch {
214
- external.add(name);
215
- }
216
- }
217
- }
192
+ // Collect packages marked as external by predicate
193
+ const toExternal = collector(pkgName, depDir, pkgJson);
194
+ for (const name of toExternal) {
195
+ external.add(name);
196
+ }
197
+
198
+ // Recursively traverse sub-dependencies
199
+ for (const dep of Object.keys(pkgJson.dependencies ?? {})) {
200
+ scanDependencyTree(dep, depDir, external, visited, collector);
218
201
  }
202
+ }
203
+
204
+ /**
205
+ * Collect uninstalled optional peer deps from dependency tree
206
+ *
207
+ * For server builds (bundle: true), specify uninstalled optional peer dependencies
208
+ * as esbuild externals to prevent build failures
209
+ */
210
+ export function collectUninstalledOptionalPeerDeps(pkgDir: string): string[] {
211
+ const external = new Set<string>();
212
+ const visited = new Set<string>();
219
213
 
214
+ const pkgJson = JSON.parse(readFileSync(path.join(pkgDir, "package.json"), "utf-8")) as PkgJson;
220
215
  for (const dep of Object.keys(pkgJson.dependencies ?? {})) {
221
- scanOptionalPeerDeps(dep, depDir, external, visited);
216
+ scanDependencyTree(dep, pkgDir, external, visited, (_pkgName, depDir, depPkgJson) => {
217
+ const found: string[] = [];
218
+ if (depPkgJson.peerDependenciesMeta != null) {
219
+ const peerDeps = depPkgJson.peerDependencies ?? {};
220
+ const depReq = createRequire(path.join(depDir, "noop.js"));
221
+ for (const [name, meta] of Object.entries(depPkgJson.peerDependenciesMeta)) {
222
+ if (meta.optional === true && name in peerDeps) {
223
+ try {
224
+ depReq.resolve(name);
225
+ } catch {
226
+ found.push(name);
227
+ }
228
+ }
229
+ }
230
+ }
231
+ return found;
232
+ });
222
233
  }
234
+
235
+ return [...external];
223
236
  }
224
237
 
225
238
  //#endregion
@@ -238,42 +251,17 @@ export function collectNativeModuleExternals(pkgDir: string): string[] {
238
251
 
239
252
  const pkgJson = JSON.parse(readFileSync(path.join(pkgDir, "package.json"), "utf-8")) as PkgJson;
240
253
  for (const dep of Object.keys(pkgJson.dependencies ?? {})) {
241
- scanNativeModules(dep, pkgDir, external, visited);
254
+ scanDependencyTree(dep, pkgDir, external, visited, (pkgName, depDir, _pkgJson) => {
255
+ const found: string[] = [];
256
+ // Detect native modules by checking for binding.gyp
257
+ if (existsSync(path.join(depDir, "binding.gyp"))) {
258
+ found.push(pkgName);
259
+ }
260
+ return found;
261
+ });
242
262
  }
243
263
 
244
264
  return [...external];
245
265
  }
246
266
 
247
- function scanNativeModules(
248
- pkgName: string,
249
- resolveDir: string,
250
- external: Set<string>,
251
- visited: Set<string>,
252
- ): void {
253
- if (visited.has(pkgName)) return;
254
- visited.add(pkgName);
255
-
256
- const req = createRequire(path.join(resolveDir, "noop.js"));
257
-
258
- let pkgJsonPath: string;
259
- try {
260
- pkgJsonPath = req.resolve(`${pkgName}/package.json`);
261
- } catch {
262
- return;
263
- }
264
-
265
- const depDir = path.dirname(pkgJsonPath);
266
-
267
- // Detect native modules by checking for binding.gyp
268
- if (existsSync(path.join(depDir, "binding.gyp"))) {
269
- external.add(pkgName);
270
- }
271
-
272
- // Recursively traverse sub-dependencies
273
- const depPkgJson = JSON.parse(readFileSync(pkgJsonPath, "utf-8")) as PkgJson;
274
- for (const dep of Object.keys(depPkgJson.dependencies ?? {})) {
275
- scanNativeModules(dep, depDir, external, visited);
276
- }
277
- }
278
-
279
267
  //#endregion
@@ -2,7 +2,7 @@ import fs from "fs";
2
2
  import path from "path";
3
3
  import { glob } from "glob";
4
4
  import { consola } from "consola";
5
- import { fsCopy, fsMkdir, fsRm, FsWatcher, pathIsChildPath } from "@simplysm/core-node";
5
+ import { fsx, pathx, FsWatcher } from "@simplysm/core-node";
6
6
 
7
7
  /**
8
8
  * Match glob patterns from replaceDeps config with target package list
@@ -249,7 +249,7 @@ export async function setupReplaceDeps(
249
249
  for (const { targetName, resolvedSourcePath, actualTargetPath } of entries) {
250
250
  try {
251
251
  // Overwrite-copy source files to actualTargetPath (maintain existing directory, preserve symlinks)
252
- await fsCopy(resolvedSourcePath, actualTargetPath, replaceDepsCopyFilter);
252
+ await fsx.copy(resolvedSourcePath, actualTargetPath, replaceDepsCopyFilter);
253
253
 
254
254
  setupCount += 1;
255
255
  } catch (err) {
@@ -300,7 +300,7 @@ export async function watchReplaceDeps(
300
300
  // Filter excluded items: basename match or path within excluded directory
301
301
  if (
302
302
  EXCLUDED_NAMES.has(path.basename(changedPath)) ||
303
- excludedPaths.some((ep) => pathIsChildPath(changedPath, ep))
303
+ excludedPaths.some((ep) => pathx.isChildPath(changedPath, ep))
304
304
  ) {
305
305
  continue;
306
306
  }
@@ -327,14 +327,14 @@ export async function watchReplaceDeps(
327
327
  // Check if source is directory or file
328
328
  const stat = await fs.promises.stat(changedPath);
329
329
  if (stat.isDirectory()) {
330
- await fsMkdir(destPath);
330
+ await fsx.mkdir(destPath);
331
331
  } else {
332
- await fsMkdir(path.dirname(destPath));
333
- await fsCopy(changedPath, destPath, replaceDepsCopyFilter);
332
+ await fsx.mkdir(path.dirname(destPath));
333
+ await fsx.copy(changedPath, destPath, replaceDepsCopyFilter);
334
334
  }
335
335
  } else {
336
336
  // Source was deleted → delete target
337
- await fsRm(destPath);
337
+ await fsx.rm(destPath);
338
338
  }
339
339
  } catch (err) {
340
340
  logger.error(
@@ -1,7 +1,7 @@
1
1
  import path from "path";
2
2
  import { createJiti } from "jiti";
3
3
  import { SdError } from "@simplysm/core-common";
4
- import { fsExists } from "@simplysm/core-node";
4
+ import { fsx } from "@simplysm/core-node";
5
5
  import type { SdConfig, SdConfigParams } from "../sd-config.types";
6
6
 
7
7
  /**
@@ -12,7 +12,7 @@ import type { SdConfig, SdConfigParams } from "../sd-config.types";
12
12
  export async function loadSdConfig(params: SdConfigParams): Promise<SdConfig> {
13
13
  const sdConfigPath = path.resolve(params.cwd, "sd.config.ts");
14
14
 
15
- if (!(await fsExists(sdConfigPath))) {
15
+ if (!(await fsx.exists(sdConfigPath))) {
16
16
  throw new SdError(`sd.config.ts file not found: ${sdConfigPath}`);
17
17
  }
18
18
 
@@ -1,6 +1,6 @@
1
1
  import path from "path";
2
2
  import Handlebars from "handlebars";
3
- import { fsCopy, fsMkdir, fsRead, fsReaddir, fsStat, fsWrite } from "@simplysm/core-node";
3
+ import { fsx } from "@simplysm/core-node";
4
4
 
5
5
  /**
6
6
  * Recursively traverse template directory, render with Handlebars, and generate files
@@ -20,13 +20,13 @@ export async function renderTemplateDir(
20
20
  context: Record<string, unknown>,
21
21
  dirReplacements?: Record<string, string>,
22
22
  ): Promise<void> {
23
- await fsMkdir(destDir);
23
+ await fsx.mkdir(destDir);
24
24
 
25
- const entries = await fsReaddir(srcDir);
25
+ const entries = await fsx.readdir(srcDir);
26
26
 
27
27
  for (const entry of entries) {
28
28
  const srcPath = path.join(srcDir, entry);
29
- const stat = await fsStat(srcPath);
29
+ const stat = await fsx.stat(srcPath);
30
30
 
31
31
  if (stat.isDirectory()) {
32
32
  // Apply directory name substitution
@@ -39,7 +39,7 @@ export async function renderTemplateDir(
39
39
  );
40
40
  } else if (entry.endsWith(".hbs")) {
41
41
  // Render Handlebars template
42
- const source = await fsRead(srcPath);
42
+ const source = await fsx.read(srcPath);
43
43
  const template = Handlebars.compile(source, { noEscape: true });
44
44
  const result = template(context);
45
45
 
@@ -47,10 +47,10 @@ export async function renderTemplateDir(
47
47
  if (result.trim().length === 0) continue;
48
48
 
49
49
  const destFileName = entry.slice(0, -4); // Remove .hbs
50
- await fsWrite(path.join(destDir, destFileName), result);
50
+ await fsx.write(path.join(destDir, destFileName), result);
51
51
  } else {
52
52
  // Copy binary files as-is
53
- await fsCopy(srcPath, path.join(destDir, entry));
53
+ await fsx.copy(srcPath, path.join(destDir, entry));
54
54
  }
55
55
  }
56
56
  }
@@ -1,6 +1,6 @@
1
1
  import ts from "typescript";
2
2
  import path from "path";
3
- import { fsExists, fsReadJson, pathIsChildPath } from "@simplysm/core-node";
3
+ import { fsx, pathx } from "@simplysm/core-node";
4
4
  import { SdError } from "@simplysm/core-common";
5
5
 
6
6
  /**
@@ -14,11 +14,11 @@ const DOM_LIB_PATTERNS = ["dom", "webworker"] as const;
14
14
  */
15
15
  export async function getTypesFromPackageJson(packageDir: string): Promise<string[]> {
16
16
  const packageJsonPath = path.join(packageDir, "package.json");
17
- if (!(await fsExists(packageJsonPath))) {
17
+ if (!(await fsx.exists(packageJsonPath))) {
18
18
  return [];
19
19
  }
20
20
 
21
- const packageJson = await fsReadJson<{ devDependencies?: Record<string, string> }>(
21
+ const packageJson = await fsx.readJson<{ devDependencies?: Record<string, string> }>(
22
22
  packageJsonPath,
23
23
  );
24
24
  const devDeps = packageJson.devDependencies ?? {};
@@ -32,9 +32,8 @@ export async function getTypesFromPackageJson(packageDir: string): Promise<strin
32
32
  * Type check environment
33
33
  * - node: remove DOM lib + add node types
34
34
  * - browser: remove node types
35
- * - neutral: keep DOM lib + add node types (for Node/browser shared packages)
36
35
  */
37
- export type TypecheckEnv = "node" | "browser" | "neutral";
36
+ export type TypecheckEnv = "node" | "browser";
38
37
 
39
38
  /**
40
39
  * Create compiler options for package
@@ -72,9 +71,6 @@ export async function getCompilerOptionsForPackage(
72
71
  case "browser":
73
72
  options.types = packageTypes.filter((t) => t !== "node");
74
73
  break;
75
- case "neutral":
76
- options.types = [...new Set([...packageTypes, "node"])];
77
- break;
78
74
  }
79
75
 
80
76
  return options;
@@ -111,7 +107,7 @@ export function getPackageSourceFiles(
111
107
  parsedConfig: ts.ParsedCommandLine,
112
108
  ): string[] {
113
109
  const pkgSrcDir = path.join(pkgDir, "src");
114
- return parsedConfig.fileNames.filter((f) => pathIsChildPath(f, pkgSrcDir));
110
+ return parsedConfig.fileNames.filter((f) => pathx.isChildPath(f, pkgSrcDir));
115
111
  }
116
112
 
117
113
  /**
@@ -119,7 +115,7 @@ export function getPackageSourceFiles(
119
115
  */
120
116
  export function getPackageFiles(pkgDir: string, parsedConfig: ts.ParsedCommandLine): string[] {
121
117
  return parsedConfig.fileNames.filter((f) => {
122
- if (!pathIsChildPath(f, pkgDir)) return false;
118
+ if (!pathx.isChildPath(f, pkgDir)) return false;
123
119
  // Exclude files directly in package root (config files) — treated same as project root files in other tasks
124
120
  const relative = path.relative(pkgDir, f);
125
121
  return path.dirname(relative) !== ".";
@@ -1,5 +1,5 @@
1
1
  import ts from "typescript";
2
- import { fsExistsSync, fsReadSync } from "@simplysm/core-node";
2
+ import { fsx } from "@simplysm/core-node";
3
3
 
4
4
  /**
5
5
  * Serialized Diagnostic that can be passed to Worker
@@ -67,7 +67,7 @@ export function deserializeDiagnostic(
67
67
  // If file was deleted or inaccessible, treat as empty content
68
68
  // (source code context won't be displayed but diagnostic message is shown normally)
69
69
  if (!fileCache.has(fileName)) {
70
- fileCache.set(fileName, fsExistsSync(fileName) ? fsReadSync(fileName) : "");
70
+ fileCache.set(fileName, fsx.existsSync(fileName) ? fsx.readSync(fileName) : "");
71
71
  }
72
72
  const content = fileCache.get(fileName)!;
73
73