@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
@@ -1,5 +1,5 @@
1
1
  import path from "path";
2
- import { fsExists } from "@simplysm/core-node";
2
+ import { fsx } from "@simplysm/core-node";
3
3
  import { consola } from "consola";
4
4
  import type { SdConfig, SdClientPackageConfig } from "../sd-config.types";
5
5
  import { loadSdConfig } from "../utils/sd-config";
@@ -43,7 +43,7 @@ export async function runDevice(options: DeviceOptions): Promise<void> {
43
43
  // Load sd.config.ts
44
44
  let sdConfig: SdConfig;
45
45
  try {
46
- sdConfig = await loadSdConfig({ cwd, dev: true, opt: options.options });
46
+ sdConfig = await loadSdConfig({ cwd, dev: true, options: options.options });
47
47
  logger.debug("sd.config.ts loaded");
48
48
  } catch (err) {
49
49
  logger.error(`Failed to load sd.config.ts: ${err instanceof Error ? err.message : err}`);
@@ -114,7 +114,7 @@ export async function runDevice(options: DeviceOptions): Promise<void> {
114
114
  logger.debug("development server URL", { serverUrl });
115
115
 
116
116
  const capPath = path.join(pkgDir, ".capacitor");
117
- if (!(await fsExists(capPath))) {
117
+ if (!(await fsx.exists(capPath))) {
118
118
  logger.error(
119
119
  `Capacitor project is not initialized. First run 'pnpm watch ${packageName}'.`,
120
120
  );
@@ -1,11 +1,10 @@
1
1
  import { ESLint } from "eslint";
2
2
  import { createJiti } from "jiti";
3
3
  import path from "path";
4
- import { fsExists, fsGlob, pathFilterByTargets } from "@simplysm/core-node";
4
+ import { fsx, pathx } from "@simplysm/core-node";
5
5
  import "@simplysm/core-common";
6
6
  import { SdError } from "@simplysm/core-common";
7
7
  import { consola } from "consola";
8
- import stylelint from "stylelint";
9
8
 
10
9
  //#region Types
11
10
 
@@ -27,9 +26,9 @@ export interface LintOptions {
27
26
  export interface LintResult {
28
27
  /** true if there are no lint errors */
29
28
  success: boolean;
30
- /** Total error count from ESLint + Stylelint */
29
+ /** Total error count from ESLint */
31
30
  errorCount: number;
32
- /** Total warning count from ESLint + Stylelint */
31
+ /** Total warning count from ESLint */
33
32
  warningCount: number;
34
33
  /** Formatter output string (content to write to stdout) */
35
34
  formattedOutput: string;
@@ -47,16 +46,6 @@ const ESLINT_CONFIG_FILES = [
47
46
  "eslint.config.mjs",
48
47
  ] as const;
49
48
 
50
- /** Stylelint config file search order */
51
- const STYLELINT_CONFIG_FILES = [
52
- "stylelint.config.ts",
53
- "stylelint.config.mts",
54
- "stylelint.config.js",
55
- "stylelint.config.mjs",
56
- ".stylelintrc.json",
57
- ".stylelintrc.yml",
58
- ] as const;
59
-
60
49
  /**
61
50
  * Type guard to check if an ESLint config object has only ignores property
62
51
  */
@@ -78,7 +67,7 @@ export async function loadIgnorePatterns(cwd: string): Promise<string[]> {
78
67
  let configPath: string | undefined;
79
68
  for (const f of ESLINT_CONFIG_FILES) {
80
69
  const p = path.join(cwd, f);
81
- if (await fsExists(p)) {
70
+ if (await fsx.exists(p)) {
82
71
  configPath = p;
83
72
  break;
84
73
  }
@@ -115,16 +104,6 @@ export async function loadIgnorePatterns(cwd: string): Promise<string[]> {
115
104
  return configs.filter(isGlobalIgnoresConfig).flatMap((item) => item.ignores);
116
105
  }
117
106
 
118
- /**
119
- * Check if Stylelint config file exists.
120
- */
121
- async function hasStylelintConfig(cwd: string): Promise<boolean> {
122
- for (const f of STYLELINT_CONFIG_FILES) {
123
- if (await fsExists(path.join(cwd, f))) return true;
124
- }
125
- return false;
126
- }
127
-
128
107
  //#endregion
129
108
 
130
109
  //#region Main
@@ -160,13 +139,13 @@ export async function executeLint(options: LintOptions): Promise<LintResult> {
160
139
 
161
140
  // Collect lint target files
162
141
  logger.start("collecting lint target files");
163
- let files = await fsGlob("**/*.{ts,tsx,js,jsx}", {
142
+ let files = await fsx.glob("**/*.{ts,tsx,js,jsx}", {
164
143
  cwd,
165
144
  ignore: ignorePatterns,
166
145
  nodir: true,
167
146
  absolute: true,
168
147
  });
169
- files = pathFilterByTargets(files, targets, cwd);
148
+ files = pathx.filterByTargets(files, targets, cwd);
170
149
  logger.debug("file collection complete", { fileCount: files.length });
171
150
  logger.success(`collected lint target files (${files.length} files)`);
172
151
 
@@ -192,59 +171,6 @@ export async function executeLint(options: LintOptions): Promise<LintResult> {
192
171
  }
193
172
  }
194
173
 
195
- // Stylelint
196
- const hasStylelintCfg = await hasStylelintConfig(cwd);
197
- let stylelintResult: stylelint.LinterResult | undefined;
198
- if (hasStylelintCfg) {
199
- logger.start("collecting CSS files");
200
- let cssFiles = await fsGlob("**/*.css", {
201
- cwd,
202
- ignore: ignorePatterns,
203
- nodir: true,
204
- absolute: true,
205
- });
206
- cssFiles = pathFilterByTargets(cssFiles, targets, cwd);
207
- logger.success(`collected CSS files (${cssFiles.length} files)`);
208
-
209
- if (cssFiles.length > 0) {
210
- logger.start(`running Stylelint... (${cssFiles.length} files)`);
211
- let configFile: string | undefined;
212
- for (const f of STYLELINT_CONFIG_FILES) {
213
- const configPath = path.join(cwd, f);
214
- if (await fsExists(configPath)) {
215
- configFile = configPath;
216
- break;
217
- }
218
- }
219
-
220
- // Support TypeScript config files: load with jiti, pass as config object
221
- let stylelintOptions: stylelint.LinterOptions;
222
- if (configFile != null && /\.ts$/.test(configFile)) {
223
- const jiti = createJiti(import.meta.url);
224
- const configModule = await jiti.import<{ default: stylelint.Config }>(configFile);
225
- const config = configModule.default;
226
- stylelintOptions = {
227
- files: cssFiles,
228
- config,
229
- configBasedir: cwd,
230
- fix,
231
- cache: true,
232
- cacheLocation: path.join(cwd, ".cache", "stylelint.cache"),
233
- };
234
- } else {
235
- stylelintOptions = {
236
- files: cssFiles,
237
- configFile,
238
- fix,
239
- cache: true,
240
- cacheLocation: path.join(cwd, ".cache", "stylelint.cache"),
241
- };
242
- }
243
- stylelintResult = await stylelint.lint(stylelintOptions);
244
- logger.success("Stylelint execution complete");
245
- }
246
- }
247
-
248
174
  // Return success result if no files or lint was not executed
249
175
  if (files.length === 0 || eslintResults == null || eslint == null) {
250
176
  logger.info("no files to lint");
@@ -271,43 +197,6 @@ export async function executeLint(options: LintOptions): Promise<LintResult> {
271
197
  formattedOutput += resultText;
272
198
  }
273
199
 
274
- // Collect Stylelint results
275
- if (stylelintResult != null && stylelintResult.results.length > 0) {
276
- const stylelintErrorCount = stylelintResult.results.sum(
277
- (r) => r.warnings.filter((w) => w.severity === "error").length,
278
- );
279
- const stylelintWarningCount = stylelintResult.results.sum(
280
- (r) => r.warnings.filter((w) => w.severity === "warning").length,
281
- );
282
-
283
- errorCount += stylelintErrorCount;
284
- warningCount += stylelintWarningCount;
285
-
286
- if (stylelintErrorCount > 0) {
287
- logger.error("Stylelint errors occurred", {
288
- errorCount: stylelintErrorCount,
289
- warningCount: stylelintWarningCount,
290
- });
291
- } else if (stylelintWarningCount > 0) {
292
- logger.info("Stylelint complete (warnings present)", {
293
- errorCount: stylelintErrorCount,
294
- warningCount: stylelintWarningCount,
295
- });
296
- } else {
297
- logger.info("Stylelint complete", {
298
- errorCount: stylelintErrorCount,
299
- warningCount: stylelintWarningCount,
300
- });
301
- }
302
-
303
- // Stylelint formatter output
304
- const stylelintFormatter = await stylelint.formatters.string;
305
- const stylelintOutput = stylelintFormatter(stylelintResult.results, stylelintResult);
306
- if (stylelintOutput) {
307
- formattedOutput += stylelintOutput;
308
- }
309
- }
310
-
311
200
  return {
312
201
  success: errorCount === 0,
313
202
  errorCount,
@@ -2,8 +2,8 @@ import path from "path";
2
2
  import semver from "semver";
3
3
  import { consola } from "consola";
4
4
  import { StorageFactory } from "@simplysm/storage";
5
- import { fsExists, fsRead, fsReadJson, fsWrite, fsGlob, fsCopy } from "@simplysm/core-node";
6
- import { env, jsonStringify } from "@simplysm/core-common";
5
+ import { fsx } from "@simplysm/core-node";
6
+ import { env, json } from "@simplysm/core-common";
7
7
  import "@simplysm/core-common";
8
8
  import type { SdConfig, SdPublishConfig } from "../sd-config.types";
9
9
  import { loadSdConfig } from "../utils/sd-config";
@@ -106,7 +106,7 @@ async function ensureSshAuth(
106
106
  // Collect SFTP servers without pass (deduplicate user@host)
107
107
  const sshTargets = new Map<string, { host: string; port?: number; user: string }>();
108
108
  for (const pkg of publishPackages) {
109
- if (pkg.config === "npm") continue;
109
+ if (pkg.config.type === "npm") continue;
110
110
  if (pkg.config.type !== "sftp") continue;
111
111
  if (pkg.config.pass != null) continue;
112
112
  if (pkg.config.user == null) {
@@ -272,7 +272,7 @@ async function upgradeVersion(
272
272
  ): Promise<{ version: string; changedFiles: string[] }> {
273
273
  const changedFiles: string[] = [];
274
274
  const projPkgPath = path.resolve(cwd, "package.json");
275
- const projPkg = await fsReadJson<PackageJson>(projPkgPath);
275
+ const projPkg = await fsx.readJson<PackageJson>(projPkgPath);
276
276
 
277
277
  const currentVersion = projPkg.version;
278
278
  const prereleaseInfo = semver.prerelease(currentVersion);
@@ -289,28 +289,28 @@ async function upgradeVersion(
289
289
  }
290
290
 
291
291
  projPkg.version = newVersion;
292
- await fsWrite(projPkgPath, jsonStringify(projPkg, { space: 2 }) + "\n");
292
+ await fsx.write(projPkgPath, json.stringify(projPkg, { space: 2 }) + "\n");
293
293
  changedFiles.push(projPkgPath);
294
294
 
295
295
  // Set version in each package's package.json
296
296
  for (const pkgPath of allPkgPaths) {
297
297
  const pkgJsonPath = path.resolve(pkgPath, "package.json");
298
- const pkgJson = await fsReadJson<PackageJson>(pkgJsonPath);
298
+ const pkgJson = await fsx.readJson<PackageJson>(pkgJsonPath);
299
299
  pkgJson.version = newVersion;
300
- await fsWrite(pkgJsonPath, jsonStringify(pkgJson, { space: 2 }) + "\n");
300
+ await fsx.write(pkgJsonPath, json.stringify(pkgJson, { space: 2 }) + "\n");
301
301
  changedFiles.push(pkgJsonPath);
302
302
  }
303
303
 
304
304
  // Synchronize @simplysm package version in template files
305
- const templateFiles = await fsGlob(path.resolve(cwd, "packages/sd-cli/templates/**/*.hbs"));
305
+ const templateFiles = await fsx.glob(path.resolve(cwd, "packages/sd-cli/templates/**/*.hbs"));
306
306
  const versionRegex = /("@simplysm\/[^"]+"\s*:\s*)"~[^"]+"/g;
307
307
 
308
308
  for (const templatePath of templateFiles) {
309
- const content = await fsRead(templatePath);
309
+ const content = await fsx.read(templatePath);
310
310
  const newContent = content.replace(versionRegex, `$1"~${newVersion}"`);
311
311
 
312
312
  if (content !== newContent) {
313
- await fsWrite(templatePath, newContent);
313
+ await fsx.write(templatePath, newContent);
314
314
  changedFiles.push(templatePath);
315
315
  }
316
316
  }
@@ -336,7 +336,7 @@ async function publishPackage(
336
336
  ): Promise<void> {
337
337
  const pkgName = path.basename(pkgPath);
338
338
 
339
- if (publishConfig === "npm") {
339
+ if (publishConfig.type === "npm") {
340
340
  // npm publish
341
341
  const prereleaseInfo = semver.prerelease(version);
342
342
  const args = ["publish", "--access", "public", "--no-git-checks"];
@@ -362,7 +362,7 @@ async function publishPackage(
362
362
  logger.info(`[DRY-RUN] [${pkgName}] copy to local: ${distPath} → ${targetPath}`);
363
363
  } else {
364
364
  logger.debug(`[${pkgName}] copy to local: ${distPath} → ${targetPath}`);
365
- await fsCopy(distPath, targetPath);
365
+ await fsx.copy(distPath, targetPath);
366
366
  }
367
367
  } else {
368
368
  // Upload to storage
@@ -407,7 +407,7 @@ async function computePublishLevels(
407
407
  // Collect workspace dependencies for each package
408
408
  const depsMap = new Map<string, Set<string>>();
409
409
  for (const pkg of publishPkgs) {
410
- const pkgJson = await fsReadJson<PackageJson>(path.resolve(pkg.path, "package.json"));
410
+ const pkgJson = await fsx.readJson<PackageJson>(path.resolve(pkg.path, "package.json"));
411
411
  const allDeps = {
412
412
  ...pkgJson.dependencies,
413
413
  ...pkgJson.peerDependencies,
@@ -483,7 +483,7 @@ export async function runPublish(options: PublishOptions): Promise<void> {
483
483
  // Load sd.config.ts
484
484
  let sdConfig: SdConfig;
485
485
  try {
486
- sdConfig = await loadSdConfig({ cwd, dev: false, opt: options.options });
486
+ sdConfig = await loadSdConfig({ cwd, dev: false, options: options.options });
487
487
  logger.debug("sd.config.ts loaded");
488
488
  } catch (err) {
489
489
  logger.error(`Failed to load sd.config.ts: ${err instanceof Error ? err.message : err}`);
@@ -493,18 +493,18 @@ export async function runPublish(options: PublishOptions): Promise<void> {
493
493
 
494
494
  // Load package.json
495
495
  const projPkgPath = path.resolve(cwd, "package.json");
496
- const projPkg = await fsReadJson<PackageJson>(projPkgPath);
496
+ const projPkg = await fsx.readJson<PackageJson>(projPkgPath);
497
497
 
498
498
  // Collect workspace package paths from pnpm-workspace.yaml
499
499
  const workspaceYamlPath = path.resolve(cwd, "pnpm-workspace.yaml");
500
500
  const workspaceGlobs: string[] = [];
501
- if (await fsExists(workspaceYamlPath)) {
502
- const yamlContent = await fsRead(workspaceYamlPath);
501
+ if (await fsx.exists(workspaceYamlPath)) {
502
+ const yamlContent = await fsx.read(workspaceYamlPath);
503
503
  workspaceGlobs.push(...parseWorkspaceGlobs(yamlContent));
504
504
  }
505
505
 
506
506
  const allPkgPaths = (
507
- await Promise.all(workspaceGlobs.map((item) => fsGlob(path.resolve(cwd, item))))
507
+ await Promise.all(workspaceGlobs.map((item) => fsx.glob(path.resolve(cwd, item))))
508
508
  )
509
509
  .flat()
510
510
  .filter((item) => !path.basename(item).includes("."));
@@ -550,12 +550,12 @@ export async function runPublish(options: PublishOptions): Promise<void> {
550
550
  );
551
551
 
552
552
  // Check if Git is available
553
- const hasGit = await fsExists(path.resolve(cwd, ".git"));
553
+ const hasGit = await fsx.exists(path.resolve(cwd, ".git"));
554
554
 
555
555
  //#region Phase 1: Pre-validation
556
556
 
557
557
  // Verify npm authentication (if npm publish config exists)
558
- if (publishPackages.some((p) => p.config === "npm")) {
558
+ if (publishPackages.some((p) => p.config.type === "npm")) {
559
559
  logger.debug("Verifying npm authentication...");
560
560
  try {
561
561
  const { stdout: whoami } = await execa("npm", ["whoami"]);
@@ -16,7 +16,7 @@ export interface ReplaceDepsOptions {
16
16
  export async function runReplaceDeps(opts: ReplaceDepsOptions): Promise<void> {
17
17
  const cwd = process.cwd();
18
18
 
19
- const sdConfig = await loadSdConfig({ cwd, dev: false, opt: opts.options });
19
+ const sdConfig = await loadSdConfig({ cwd, dev: false, options: opts.options });
20
20
 
21
21
  if (sdConfig.replaceDeps == null) {
22
22
  consola.warn("No replaceDeps config found in sd.config.ts.");
@@ -1,8 +1,8 @@
1
1
  import ts from "typescript";
2
2
  import path from "path";
3
3
  import os from "os";
4
- import { pathPosix, pathFilterByTargets, Worker, type WorkerProxy } from "@simplysm/core-node";
5
- import { errorMessage } from "@simplysm/core-common";
4
+ import { pathx, Worker, type WorkerProxy } from "@simplysm/core-node";
5
+ import { err as errNs } from "@simplysm/core-common";
6
6
  import { consola } from "consola";
7
7
  import type { SdConfig } from "../sd-config.types";
8
8
  import { parseRootTsconfig, type TypecheckEnv } from "../utils/tsconfig";
@@ -86,7 +86,7 @@ export function extractPackages(
86
86
  const packages = new Map<string, PackageInfo>();
87
87
 
88
88
  for (const fileName of fileNames) {
89
- const relativePath = pathPosix(path.relative(cwd, fileName));
89
+ const relativePath = pathx.posix(path.relative(cwd, fileName));
90
90
 
91
91
  // packages/{pkg}/...
92
92
  const packageMatch = relativePath.match(PATH_PATTERNS.PACKAGE);
@@ -113,7 +113,7 @@ export function extractPackages(
113
113
  */
114
114
  function hasNonPackageFiles(fileNames: string[], cwd: string): boolean {
115
115
  return fileNames.some((f) => {
116
- const relativePath = pathPosix(path.relative(cwd, f));
116
+ const relativePath = pathx.posix(path.relative(cwd, f));
117
117
  if (!relativePath.startsWith("packages/")) return true;
118
118
  // Also treat files directly under package root (config files) as non-package
119
119
  return relativePath.split("/").length === 3;
@@ -202,14 +202,14 @@ export async function executeTypecheck(options: TypecheckOptions): Promise<Typec
202
202
  try {
203
203
  parsedConfig = parseRootTsconfig(cwd);
204
204
  } catch (err) {
205
- logger.error(errorMessage(err));
205
+ logger.error(errNs.message(err));
206
206
  return { success: false, errorCount: 1, warningCount: 0, formattedOutput: "" };
207
207
  }
208
208
 
209
209
  // Load sd.config.ts
210
210
  let sdConfig: SdConfig;
211
211
  try {
212
- sdConfig = await loadSdConfig({ cwd, dev: false, opt: options.options });
212
+ sdConfig = await loadSdConfig({ cwd, dev: false, options: options.options });
213
213
  logger.debug("sd.config.ts loaded");
214
214
  } catch (err) {
215
215
  // Use defaults if sd.config.ts is missing or load fails
@@ -218,7 +218,7 @@ export async function executeTypecheck(options: TypecheckOptions): Promise<Typec
218
218
  }
219
219
 
220
220
  // Filter fileNames if targets specified
221
- const fileNames = pathFilterByTargets(parsedConfig.fileNames, targets, cwd);
221
+ const fileNames = pathx.filterByTargets(parsedConfig.fileNames, targets, cwd);
222
222
 
223
223
  if (fileNames.length === 0) {
224
224
  logger.info("no files to typecheck");
@@ -283,13 +283,13 @@ export async function executeTypecheck(options: TypecheckOptions): Promise<Typec
283
283
  }
284
284
  } catch (err) {
285
285
  logger.error(`Worker error: ${task.displayName}`, {
286
- error: errorMessage(err),
286
+ error: errNs.message(err),
287
287
  });
288
288
  allResults.push({
289
289
  displayName: task.displayName,
290
290
  result: {
291
291
  success: false,
292
- errors: [errorMessage(err)],
292
+ errors: [errNs.message(err)],
293
293
  diagnostics: [],
294
294
  errorCount: 1,
295
295
  warningCount: 0,
@@ -2,7 +2,7 @@ import path from "path";
2
2
  import os from "os";
3
3
  import fs from "fs";
4
4
  import module from "module";
5
- import { fsExists, fsMkdir, fsCopy, fsReaddir, fsReadJson, fsWriteJson } from "@simplysm/core-node";
5
+ import { fsx } from "@simplysm/core-node";
6
6
  import { consola } from "consola";
7
7
  import type { SdElectronConfig } from "../sd-config.types";
8
8
  import { execa } from "execa";
@@ -45,7 +45,7 @@ export class Electron {
45
45
  static async create(pkgPath: string, config: SdElectronConfig): Promise<Electron> {
46
46
  Electron._validateConfig(config);
47
47
 
48
- const npmConfig = await fsReadJson<NpmConfig>(path.resolve(pkgPath, "package.json"));
48
+ const npmConfig = await fsx.readJson<NpmConfig>(path.resolve(pkgPath, "package.json"));
49
49
  return new Electron(pkgPath, config, npmConfig);
50
50
  }
51
51
 
@@ -137,8 +137,8 @@ export class Electron {
137
137
  await this._bundleMainProcess(electronRunPath);
138
138
 
139
139
  // 2. Create package.json
140
- await fsMkdir(electronRunPath);
141
- await fsWriteJson(
140
+ await fsx.mkdir(electronRunPath);
141
+ await fsx.writeJson(
142
142
  path.resolve(electronRunPath, "package.json"),
143
143
  { name: this._npmConfig.name, version: this._npmConfig.version, main: "electron-main.js" },
144
144
  { space: 2 },
@@ -165,7 +165,7 @@ export class Electron {
165
165
  * Create .electron/src/package.json
166
166
  */
167
167
  private async _setupPackageJson(srcPath: string): Promise<void> {
168
- await fsMkdir(srcPath);
168
+ await fsx.mkdir(srcPath);
169
169
 
170
170
  const reinstallDeps = this._config.reinstallDependencies ?? [];
171
171
 
@@ -190,7 +190,7 @@ export class Electron {
190
190
  packageJson["scripts"] = { postinstall: this._config.postInstallScript };
191
191
  }
192
192
 
193
- await fsWriteJson(path.resolve(srcPath, "package.json"), packageJson, { space: 2 });
193
+ await fsx.writeJson(path.resolve(srcPath, "package.json"), packageJson, { space: 2 });
194
194
  }
195
195
 
196
196
  //#endregion
@@ -204,14 +204,14 @@ export class Electron {
204
204
  const esbuild = await import("esbuild");
205
205
  const entryPoint = path.resolve(this._pkgPath, "src/electron-main.ts");
206
206
 
207
- if (!(await fsExists(entryPoint))) {
207
+ if (!(await fsx.exists(entryPoint))) {
208
208
  throw new Error(`electron-main.ts file not found: ${entryPoint}`);
209
209
  }
210
210
 
211
211
  const builtinModules = module.builtinModules.flatMap((m) => [m, `node:${m}`]);
212
212
  const reinstallDeps = this._config.reinstallDependencies ?? [];
213
213
 
214
- await fsMkdir(outDir);
214
+ await fsx.mkdir(outDir);
215
215
 
216
216
  await esbuild.build({
217
217
  entryPoints: [entryPoint],
@@ -232,14 +232,14 @@ export class Electron {
232
232
  * Copy web assets (build output → .electron/src/)
233
233
  */
234
234
  private async _copyWebAssets(outPath: string, srcPath: string): Promise<void> {
235
- const items = await fsReaddir(outPath);
235
+ const items = await fsx.readdir(outPath);
236
236
  for (const item of items) {
237
237
  // Exclude electron/ subdirectory (prevent self-copying)
238
238
  if (item === "electron") continue;
239
239
 
240
240
  const source = path.resolve(outPath, item);
241
241
  const dest = path.resolve(srcPath, item);
242
- await fsCopy(source, dest);
242
+ await fsx.copy(source, dest);
243
243
  }
244
244
  }
245
245
 
@@ -297,7 +297,7 @@ export class Electron {
297
297
  }
298
298
 
299
299
  const configFilePath = path.resolve(this._electronPath, "builder-config.json");
300
- await fsWriteJson(configFilePath, builderConfig, { space: 2 });
300
+ await fsx.writeJson(configFilePath, builderConfig, { space: 2 });
301
301
 
302
302
  await this._exec(
303
303
  "npx",
@@ -312,7 +312,7 @@ export class Electron {
312
312
  private async _copyBuildOutput(outPath: string): Promise<void> {
313
313
  const distPath = path.resolve(this._electronPath, "dist");
314
314
  const electronOutPath = path.resolve(outPath, "electron");
315
- await fsMkdir(electronOutPath);
315
+ await fsx.mkdir(electronOutPath);
316
316
 
317
317
  const description = this._npmConfig.description ?? this._npmConfig.name;
318
318
  const version = this._npmConfig.version;
@@ -322,15 +322,15 @@ export class Electron {
322
322
  const builderFileName = `${description} ${isPortable ? "" : "Setup "}${version}.exe`;
323
323
  const sourcePath = path.resolve(distPath, builderFileName);
324
324
 
325
- if (await fsExists(sourcePath)) {
325
+ if (await fsx.exists(sourcePath)) {
326
326
  // Copy latest file
327
327
  const latestFileName = `${description}${isPortable ? "-portable" : ""}-latest.exe`;
328
- await fsCopy(sourcePath, path.resolve(electronOutPath, latestFileName));
328
+ await fsx.copy(sourcePath, path.resolve(electronOutPath, latestFileName));
329
329
 
330
330
  // Copy per-version file to updates/
331
331
  const updatesPath = path.resolve(electronOutPath, "updates");
332
- await fsMkdir(updatesPath);
333
- await fsCopy(sourcePath, path.resolve(updatesPath, `${version}.exe`));
332
+ await fsx.mkdir(updatesPath);
333
+ await fsx.copy(sourcePath, path.resolve(updatesPath, `${version}.exe`));
334
334
  } else {
335
335
  Electron._logger.warn(`build output not found: ${sourcePath}`);
336
336
  }
@@ -1,7 +1,7 @@
1
1
  import path from "path";
2
2
  import ts from "typescript";
3
- import { Worker, type WorkerProxy, fsRm } from "@simplysm/core-node";
4
- import { errorMessage } from "@simplysm/core-common";
3
+ import { Worker, type WorkerProxy, fsx } from "@simplysm/core-node";
4
+ import { err as errNs } from "@simplysm/core-common";
5
5
  import { consola } from "consola";
6
6
  import type {
7
7
  SdConfig,
@@ -110,7 +110,7 @@ function classifyPackages(
110
110
  * Delete dist folders
111
111
  */
112
112
  async function cleanDistFolders(cwd: string, packageNames: string[]): Promise<void> {
113
- await Promise.all(packageNames.map((name) => fsRm(path.join(cwd, "packages", name, "dist"))));
113
+ await Promise.all(packageNames.map((name) => fsx.rm(path.join(cwd, "packages", name, "dist"))));
114
114
  }
115
115
 
116
116
  //#endregion
@@ -157,7 +157,7 @@ export class BuildOrchestrator {
157
157
  this._sdConfig = await loadSdConfig({
158
158
  cwd: this._cwd,
159
159
  dev: false,
160
- opt: this._options.options,
160
+ options: this._options.options,
161
161
  });
162
162
  this._logger.debug("sd.config.ts loaded");
163
163
  } catch (err) {
@@ -375,7 +375,7 @@ export class BuildOrchestrator {
375
375
  target: "client",
376
376
  type: "capacitor",
377
377
  success: false,
378
- errors: [errorMessage(err)],
378
+ errors: [errNs.message(err)],
379
379
  });
380
380
  state.hasError = true;
381
381
  }
@@ -400,7 +400,7 @@ export class BuildOrchestrator {
400
400
  target: "client",
401
401
  type: "electron",
402
402
  success: false,
403
- errors: [errorMessage(err)],
403
+ errors: [errNs.message(err)],
404
404
  });
405
405
  state.hasError = true;
406
406
  }