@simplysm/sd-cli 13.0.76 → 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 (154) 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.js +4 -4
  19. package/dist/commands/lint.js.map +1 -1
  20. package/dist/commands/publish.js +20 -20
  21. package/dist/commands/publish.js.map +1 -1
  22. package/dist/commands/replace-deps.js +1 -1
  23. package/dist/commands/replace-deps.js.map +1 -1
  24. package/dist/commands/typecheck.js +9 -9
  25. package/dist/commands/typecheck.js.map +1 -1
  26. package/dist/electron/electron.js +16 -16
  27. package/dist/electron/electron.js.map +1 -1
  28. package/dist/orchestrators/BuildOrchestrator.js +6 -6
  29. package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
  30. package/dist/orchestrators/DevOrchestrator.d.ts +7 -6
  31. package/dist/orchestrators/DevOrchestrator.d.ts.map +1 -1
  32. package/dist/orchestrators/DevOrchestrator.js +157 -203
  33. package/dist/orchestrators/DevOrchestrator.js.map +1 -1
  34. package/dist/orchestrators/WatchOrchestrator.d.ts.map +1 -1
  35. package/dist/orchestrators/WatchOrchestrator.js +3 -4
  36. package/dist/orchestrators/WatchOrchestrator.js.map +1 -1
  37. package/dist/sd-cli.js +1 -1
  38. package/dist/sd-cli.js.map +1 -1
  39. package/dist/sd-config.types.d.ts +9 -3
  40. package/dist/sd-config.types.d.ts.map +1 -1
  41. package/dist/utils/copy-public.d.ts.map +1 -1
  42. package/dist/utils/copy-public.js +23 -27
  43. package/dist/utils/copy-public.js.map +1 -1
  44. package/dist/utils/copy-src.d.ts.map +1 -1
  45. package/dist/utils/copy-src.js +7 -7
  46. package/dist/utils/copy-src.js.map +1 -1
  47. package/dist/utils/esbuild-config.d.ts.map +1 -1
  48. package/dist/utils/esbuild-config.js +36 -42
  49. package/dist/utils/esbuild-config.js.map +1 -1
  50. package/dist/utils/replace-deps.js +7 -7
  51. package/dist/utils/replace-deps.js.map +1 -1
  52. package/dist/utils/sd-config.js +2 -2
  53. package/dist/utils/sd-config.js.map +1 -1
  54. package/dist/utils/template.js +7 -7
  55. package/dist/utils/template.js.map +1 -1
  56. package/dist/utils/tsconfig.d.ts +1 -2
  57. package/dist/utils/tsconfig.d.ts.map +1 -1
  58. package/dist/utils/tsconfig.js +5 -8
  59. package/dist/utils/tsconfig.js.map +1 -1
  60. package/dist/utils/typecheck-serialization.js +2 -2
  61. package/dist/utils/typecheck-serialization.js.map +1 -1
  62. package/dist/utils/vite-config.d.ts +2 -0
  63. package/dist/utils/vite-config.d.ts.map +1 -1
  64. package/dist/utils/vite-config.js +36 -3
  65. package/dist/utils/vite-config.js.map +1 -1
  66. package/dist/utils/worker-events.d.ts +11 -1
  67. package/dist/utils/worker-events.d.ts.map +1 -1
  68. package/dist/utils/worker-events.js +3 -5
  69. package/dist/utils/worker-events.js.map +1 -1
  70. package/dist/utils/worker-utils.d.ts +2 -2
  71. package/dist/utils/worker-utils.d.ts.map +1 -1
  72. package/dist/utils/worker-utils.js +1 -1
  73. package/dist/utils/worker-utils.js.map +1 -1
  74. package/dist/workers/client.worker.d.ts +1 -1
  75. package/dist/workers/client.worker.js +3 -3
  76. package/dist/workers/client.worker.js.map +1 -1
  77. package/dist/workers/dts.worker.d.ts +1 -1
  78. package/dist/workers/dts.worker.d.ts.map +1 -1
  79. package/dist/workers/dts.worker.js +13 -28
  80. package/dist/workers/dts.worker.js.map +1 -1
  81. package/dist/workers/library.worker.d.ts +1 -1
  82. package/dist/workers/library.worker.js +4 -4
  83. package/dist/workers/library.worker.js.map +1 -1
  84. package/dist/workers/lint.worker.d.ts +1 -1
  85. package/dist/workers/server-runtime.worker.d.ts +1 -1
  86. package/dist/workers/server-runtime.worker.js +4 -4
  87. package/dist/workers/server-runtime.worker.js.map +1 -1
  88. package/dist/workers/server.worker.d.ts +1 -1
  89. package/dist/workers/server.worker.js +6 -6
  90. package/dist/workers/server.worker.js.map +1 -1
  91. package/package.json +4 -4
  92. package/src/builders/DtsBuilder.ts +2 -2
  93. package/src/builders/LibraryBuilder.ts +7 -10
  94. package/src/builders/types.ts +6 -1
  95. package/src/capacitor/capacitor.ts +61 -60
  96. package/src/commands/check.ts +4 -4
  97. package/src/commands/device.ts +3 -3
  98. package/src/commands/lint.ts +4 -4
  99. package/src/commands/publish.ts +20 -20
  100. package/src/commands/replace-deps.ts +1 -1
  101. package/src/commands/typecheck.ts +9 -9
  102. package/src/electron/electron.ts +16 -16
  103. package/src/orchestrators/BuildOrchestrator.ts +6 -6
  104. package/src/orchestrators/DevOrchestrator.ts +210 -256
  105. package/src/orchestrators/WatchOrchestrator.ts +8 -10
  106. package/src/sd-cli.ts +1 -1
  107. package/src/sd-config.types.ts +10 -3
  108. package/src/utils/copy-public.ts +22 -26
  109. package/src/utils/copy-src.ts +7 -7
  110. package/src/utils/esbuild-config.ts +51 -63
  111. package/src/utils/replace-deps.ts +7 -7
  112. package/src/utils/sd-config.ts +2 -2
  113. package/src/utils/template.ts +7 -7
  114. package/src/utils/tsconfig.ts +6 -10
  115. package/src/utils/typecheck-serialization.ts +2 -2
  116. package/src/utils/vite-config.ts +376 -341
  117. package/src/utils/worker-events.ts +13 -10
  118. package/src/utils/worker-utils.ts +45 -45
  119. package/src/workers/client.worker.ts +3 -3
  120. package/src/workers/dts.worker.ts +451 -467
  121. package/src/workers/library.worker.ts +4 -4
  122. package/src/workers/server-runtime.worker.ts +4 -4
  123. package/src/workers/server.worker.ts +572 -572
  124. package/templates/init/package.json.hbs +2 -2
  125. package/templates/init/packages/client-admin/package.json.hbs +5 -5
  126. package/templates/init/packages/client-admin/src/views/auth/LoginView.tsx +2 -2
  127. package/templates/init/packages/client-admin/src/views/home/base/employee/EmployeeSheet.tsx.hbs +1 -1
  128. package/templates/init/packages/client-admin/src/views/home/base/role-permission/RoleSheet.tsx.hbs +1 -1
  129. package/templates/init/packages/db-main/package.json.hbs +2 -2
  130. package/templates/init/packages/server/package.json.hbs +4 -4
  131. package/templates/init/tests/e2e/package.json.hbs +1 -1
  132. package/tests/get-compiler-options-for-package.spec.ts +13 -27
  133. package/tests/get-types-from-package-json.spec.ts +15 -11
  134. package/tests/load-ignore-patterns.spec.ts +15 -11
  135. package/tests/load-sd-config.spec.ts +16 -14
  136. package/tests/publish-config-narrowing.spec.ts +20 -0
  137. package/tests/run-lint.spec.ts +38 -34
  138. package/tests/run-typecheck.spec.ts +194 -135
  139. package/tests/sd-public-dev-plugin-mime.spec.ts +19 -0
  140. package/dist/builders/index.d.ts +0 -5
  141. package/dist/builders/index.d.ts.map +0 -1
  142. package/dist/builders/index.js +0 -5
  143. package/dist/builders/index.js.map +0 -6
  144. package/dist/infra/index.d.ts +0 -4
  145. package/dist/infra/index.d.ts.map +0 -1
  146. package/dist/infra/index.js +0 -4
  147. package/dist/infra/index.js.map +0 -6
  148. package/dist/orchestrators/index.d.ts +0 -4
  149. package/dist/orchestrators/index.d.ts.map +0 -1
  150. package/dist/orchestrators/index.js +0 -4
  151. package/dist/orchestrators/index.js.map +0 -6
  152. package/src/builders/index.ts +0 -4
  153. package/src/infra/index.ts +0 -3
  154. package/src/orchestrators/index.ts +0 -3
@@ -1,6 +1,6 @@
1
1
  import path from "path";
2
2
  import { Worker, type WorkerProxy } from "@simplysm/core-node";
3
- import { errorMessage } from "@simplysm/core-common";
3
+ import { err as errNs } from "@simplysm/core-common";
4
4
  import type { SdConfig, SdClientPackageConfig, SdServerPackageConfig } from "../sd-config.types";
5
5
  import { consola } from "consola";
6
6
  import { loadSdConfig } from "../utils/sd-config";
@@ -16,7 +16,6 @@ import { formatBuildMessages, printErrors, printServers } from "../utils/output-
16
16
  import { RebuildManager } from "../utils/rebuild-manager";
17
17
  import {
18
18
  registerWorkerEventHandlers,
19
- type BaseWorkerInfo,
20
19
  type ServerReadyEventData,
21
20
  type ServerBuildEventData,
22
21
  type ErrorEventData,
@@ -45,6 +44,19 @@ interface ClientWorkerInfo {
45
44
  buildResolver: (() => void) | undefined;
46
45
  }
47
46
 
47
+ /**
48
+ * Options for client worker setup
49
+ */
50
+ interface ClientSetupOptions {
51
+ workers: ClientWorkerInfo[];
52
+ /** Called on serverReady event. If undefined, completeTask is called with running status. */
53
+ onServerReady?: (workerInfo: ClientWorkerInfo, port: number, completeTask: (result: BuildResult) => void) => void;
54
+ /** Called on error event (in addition to default error handling) */
55
+ onError?: (workerInfo: ClientWorkerInfo) => void;
56
+ /** Create the config to pass to worker.startWatch() */
57
+ createConfig: (workerInfo: ClientWorkerInfo) => SdClientPackageConfig;
58
+ }
59
+
48
60
  //#endregion
49
61
 
50
62
  //#region DevOrchestrator
@@ -130,7 +142,7 @@ export class DevOrchestrator {
130
142
  this._sdConfig = await loadSdConfig({
131
143
  cwd: this._cwd,
132
144
  dev: true,
133
- opt: this._options.options,
145
+ options: this._options.options,
134
146
  });
135
147
  this._logger.debug("sd.config.ts loaded successfully");
136
148
  } catch (err) {
@@ -236,9 +248,54 @@ export class DevOrchestrator {
236
248
  }));
237
249
 
238
250
  // Setup and start workers for each section
239
- const standaloneClientPromises = this._setupStandaloneClients();
240
- const { buildPromises: viteClientPromises, readyPromises: viteClientReadyPromises } =
241
- this._setupViteClients();
251
+ const standaloneClientPromises = this._setupClientWorkers({
252
+ workers: this._standaloneClientWorkers,
253
+ createConfig: (workerInfo) => ({
254
+ ...workerInfo.config,
255
+ env: { ...this._baseEnv, ...workerInfo.config.env },
256
+ }),
257
+ });
258
+
259
+ // Vite client ready promises (server waits for client ports before starting runtime)
260
+ const viteClientReadyPromises = new Map<string, { promise: Promise<void>; resolver: () => void }>();
261
+ for (const workerInfo of this._viteClientWorkers) {
262
+ let readyResolver!: () => void;
263
+ const readyPromise = new Promise<void>((resolve) => {
264
+ readyResolver = resolve;
265
+ });
266
+ viteClientReadyPromises.set(workerInfo.name, {
267
+ promise: readyPromise,
268
+ resolver: readyResolver,
269
+ });
270
+ }
271
+
272
+ const viteClientPromises = this._setupClientWorkers({
273
+ workers: this._viteClientWorkers,
274
+ onServerReady: (workerInfo, port, completeTask) => {
275
+ this._logger.debug(`[${workerInfo.name}] Vite serverReady (port: ${String(port)})`);
276
+ this._clientPorts[workerInfo.name] = port;
277
+ // Notify Vite server ready (server is waiting for proxy setup)
278
+ viteClientReadyPromises.get(workerInfo.name)?.resolver();
279
+ // Call completeTask for build completion (Vite doesn't emit build event)
280
+ completeTask({
281
+ name: workerInfo.name,
282
+ target: workerInfo.config.target,
283
+ type: "build",
284
+ status: "success",
285
+ });
286
+ },
287
+ onError: (workerInfo) => {
288
+ // Also resolve readyPromises on Vite client error
289
+ // (prevent server from hanging indefinitely in await Promise.all(clientReadyPromises))
290
+ viteClientReadyPromises.get(workerInfo.name)?.resolver();
291
+ },
292
+ createConfig: (workerInfo) => ({
293
+ ...workerInfo.config,
294
+ server: 0, // Vite will automatically assign port
295
+ env: { ...this._baseEnv, ...workerInfo.config.env },
296
+ }),
297
+ });
298
+
242
299
  const serverPromises = this._setupServers(
243
300
  serverWorkerPath,
244
301
  serverRuntimeWorkerPath,
@@ -295,7 +352,7 @@ export class DevOrchestrator {
295
352
  target: "client",
296
353
  type: "capacitor",
297
354
  status: "error",
298
- message: errorMessage(err),
355
+ message: errNs.message(err),
299
356
  });
300
357
  this._logger.fail(taskName);
301
358
  }
@@ -308,11 +365,11 @@ export class DevOrchestrator {
308
365
  }
309
366
 
310
367
  /**
311
- * Setup and start standalone client workers
368
+ * Setup and start client workers (unified for standalone and server-connected clients)
312
369
  */
313
- private _setupStandaloneClients(): Array<{ name: string; promise: Promise<void> }> {
370
+ private _setupClientWorkers(opts: ClientSetupOptions): Array<{ name: string; promise: Promise<void> }> {
314
371
  const buildPromises = new Map<string, Promise<void>>();
315
- for (const workerInfo of this._standaloneClientWorkers) {
372
+ for (const workerInfo of opts.workers) {
316
373
  buildPromises.set(
317
374
  workerInfo.name,
318
375
  new Promise<void>((resolve) => {
@@ -322,9 +379,9 @@ export class DevOrchestrator {
322
379
  }
323
380
 
324
381
  // Register event handlers
325
- for (const workerInfo of this._standaloneClientWorkers) {
382
+ for (const workerInfo of opts.workers) {
326
383
  const completeTask = registerWorkerEventHandlers(
327
- workerInfo as unknown as BaseWorkerInfo,
384
+ workerInfo,
328
385
  {
329
386
  resultKey: `${workerInfo.name}:build`,
330
387
  listrTitle: `${workerInfo.name} (client)`,
@@ -337,112 +394,25 @@ export class DevOrchestrator {
337
394
  // serverReady (Vite dev server)
338
395
  workerInfo.worker.on("serverReady", (data) => {
339
396
  const event = data as ServerReadyEventData;
340
- completeTask({
341
- name: workerInfo.name,
342
- target: workerInfo.config.target,
343
- type: "server",
344
- status: "running",
345
- port: event.port,
346
- });
347
- });
348
-
349
- // Print server URL when scope package rebuild is detected
350
- workerInfo.worker.on("scopeRebuild", () => {
351
- this._schedulePrintServers();
352
- });
353
-
354
- // Start worker
355
- const pkgDir = path.join(this._cwd, "packages", workerInfo.name);
356
- const clientConfig: SdClientPackageConfig = {
357
- ...workerInfo.config,
358
- env: { ...this._baseEnv, ...workerInfo.config.env },
359
- };
360
- workerInfo.worker
361
- .startWatch({
362
- name: workerInfo.name,
363
- config: clientConfig,
364
- cwd: this._cwd,
365
- pkgDir,
366
- replaceDeps: this._sdConfig!.replaceDeps,
367
- })
368
- .catch((err: unknown) => {
397
+ if (opts.onServerReady != null) {
398
+ opts.onServerReady(workerInfo, event.port, completeTask);
399
+ } else {
369
400
  completeTask({
370
401
  name: workerInfo.name,
371
402
  target: workerInfo.config.target,
372
- type: "build",
373
- status: "error",
374
- message: errorMessage(err),
403
+ type: "server",
404
+ status: "running",
405
+ port: event.port,
375
406
  });
376
- });
377
- }
378
-
379
- return this._standaloneClientWorkers.map((workerInfo) => ({
380
- name: `${workerInfo.name} (client)`,
381
- promise: buildPromises.get(workerInfo.name) ?? Promise.resolve(),
382
- }));
383
- }
384
-
385
- /**
386
- * Setup and start Vite client (server-connected) workers
387
- */
388
- private _setupViteClients(): {
389
- buildPromises: Array<{ name: string; promise: Promise<void> }>;
390
- readyPromises: Map<string, { promise: Promise<void>; resolver: () => void }>;
391
- } {
392
- const buildPromiseMap = new Map<string, Promise<void>>();
393
- const readyPromises = new Map<string, { promise: Promise<void>; resolver: () => void }>();
394
- for (const workerInfo of this._viteClientWorkers) {
395
- buildPromiseMap.set(
396
- workerInfo.name,
397
- new Promise<void>((resolve) => {
398
- workerInfo.buildResolver = resolve;
399
- }),
400
- );
401
- // Vite server ready promise (wait until server knows client port)
402
- let readyResolver!: () => void;
403
- const readyPromise = new Promise<void>((resolve) => {
404
- readyResolver = resolve;
405
- });
406
- readyPromises.set(workerInfo.name, {
407
- promise: readyPromise,
408
- resolver: readyResolver,
407
+ }
409
408
  });
410
- }
411
409
 
412
- // Register event handlers
413
- for (const workerInfo of this._viteClientWorkers) {
414
- const completeTask = registerWorkerEventHandlers(
415
- workerInfo as unknown as BaseWorkerInfo,
416
- {
417
- resultKey: `${workerInfo.name}:build`,
418
- listrTitle: `${workerInfo.name} (client)`,
419
- resultType: "build",
420
- },
421
- this._results,
422
- this._rebuildManager,
423
- );
424
-
425
- // serverReady - Store Vite port in clientPorts (URL is printed via server)
426
- workerInfo.worker.on("serverReady", (data) => {
427
- const event = data as ServerReadyEventData;
428
- this._logger.debug(`[${workerInfo.name}] Vite serverReady (port: ${String(event.port)})`);
429
- this._clientPorts[workerInfo.name] = event.port;
430
- // Notify Vite server ready (server is waiting for proxy setup)
431
- readyPromises.get(workerInfo.name)?.resolver();
432
- // Call completeTask for build completion (Vite doesn't emit build event)
433
- completeTask({
434
- name: workerInfo.name,
435
- target: workerInfo.config.target,
436
- type: "build",
437
- status: "success",
410
+ // Additional error handling (in addition to default from registerWorkerEventHandlers)
411
+ if (opts.onError != null) {
412
+ workerInfo.worker.on("error", () => {
413
+ opts.onError!(workerInfo);
438
414
  });
439
- });
440
-
441
- // Also resolve readyPromises on Vite client error
442
- // (prevent server from hanging indefinitely in await Promise.all(clientReadyPromises))
443
- workerInfo.worker.on("error", () => {
444
- readyPromises.get(workerInfo.name)?.resolver();
445
- });
415
+ }
446
416
 
447
417
  // Print server URL when scope package rebuild is detected
448
418
  workerInfo.worker.on("scopeRebuild", () => {
@@ -451,16 +421,11 @@ export class DevOrchestrator {
451
421
 
452
422
  // Start worker
453
423
  const pkgDir = path.join(this._cwd, "packages", workerInfo.name);
454
- // Allow Vite to automatically assign port
455
- const viteConfig: SdClientPackageConfig = {
456
- ...workerInfo.config,
457
- server: 0, // Vite will automatically assign port
458
- env: { ...this._baseEnv, ...workerInfo.config.env },
459
- };
424
+ const clientConfig = opts.createConfig(workerInfo);
460
425
  workerInfo.worker
461
426
  .startWatch({
462
427
  name: workerInfo.name,
463
- config: viteConfig,
428
+ config: clientConfig,
464
429
  cwd: this._cwd,
465
430
  pkgDir,
466
431
  replaceDeps: this._sdConfig!.replaceDeps,
@@ -471,18 +436,15 @@ export class DevOrchestrator {
471
436
  target: workerInfo.config.target,
472
437
  type: "build",
473
438
  status: "error",
474
- message: errorMessage(err),
439
+ message: errNs.message(err),
475
440
  });
476
441
  });
477
442
  }
478
443
 
479
- return {
480
- buildPromises: this._viteClientWorkers.map((workerInfo) => ({
481
- name: `${workerInfo.name} (client)`,
482
- promise: buildPromiseMap.get(workerInfo.name) ?? Promise.resolve(),
483
- })),
484
- readyPromises,
485
- };
444
+ return opts.workers.map((workerInfo) => ({
445
+ name: `${workerInfo.name} (client)`,
446
+ promise: buildPromises.get(workerInfo.name) ?? Promise.resolve(),
447
+ }));
486
448
  }
487
449
 
488
450
  /**
@@ -519,13 +481,28 @@ export class DevOrchestrator {
519
481
  serverRuntimePromises.set(name, { promise, resolver });
520
482
  }
521
483
 
484
+ // Track first build state per server
485
+ const isFirstBuild = new Map<string, boolean>(
486
+ this._serverPackages.map(({ name }) => [name, true])
487
+ );
488
+
489
+ // Helper to encapsulate result + promise resolution pattern
490
+ const resolveServerStep = (serverName: string, resultKey: string, result: BuildResult): void => {
491
+ this._results.set(resultKey, result);
492
+ if (isFirstBuild.get(serverName)) {
493
+ isFirstBuild.set(serverName, false);
494
+ serverRuntimePromises.get(serverName)?.resolver();
495
+ }
496
+ const updatedBuild = this._serverBuildWorkers.get(serverName)!;
497
+ updatedBuild.buildResolver();
498
+ };
499
+
522
500
  // Register Server Build Worker event handlers
523
501
  for (const { name } of this._serverPackages) {
524
502
  const serverBuild = this._serverBuildWorkers.get(name)!;
525
- let isFirstBuild = true;
526
503
 
527
504
  serverBuild.worker.on("buildStart", () => {
528
- if (!isFirstBuild) {
505
+ if (!isFirstBuild.get(name)) {
529
506
  // Register with RebuildManager on rebuild
530
507
  const resolver = this._rebuildManager.registerBuild(`${name}:server`, `${name} (server)`);
531
508
  this._serverBuildWorkers.set(name, {
@@ -545,162 +522,47 @@ export class DevOrchestrator {
545
522
  }
546
523
 
547
524
  if (!event.success) {
548
- this._results.set(`${name}:build`, {
525
+ resolveServerStep(name, `${name}:build`, {
549
526
  name,
550
527
  target: "server",
551
528
  type: "build",
552
529
  status: "error",
553
530
  message: event.errors?.join("\n"),
554
531
  });
555
-
556
- if (isFirstBuild) {
557
- isFirstBuild = false;
558
- serverRuntimePromises.get(name)?.resolver();
559
- }
560
- this._serverBuildWorkers.get(name)!.buildResolver();
561
532
  return;
562
533
  }
563
534
 
564
535
  // Start runtime worker on build success (separate async function to prevent error propagation)
565
- void startServerRuntime(name, event.mainJsPath).catch((err: unknown) => {
566
- const message = errorMessage(err);
536
+ void this._startServerRuntime(
537
+ name,
538
+ event.mainJsPath,
539
+ serverRuntimeWorkerPath,
540
+ serverRuntimePromises,
541
+ resolveServerStep,
542
+ viteClientReadyPromises,
543
+ ).catch((err: unknown) => {
544
+ const message = errNs.message(err);
567
545
  this._logger.error(`[${name}] Error starting Server Runtime:`, message);
568
546
 
569
- this._results.set(`${name}:server`, {
547
+ resolveServerStep(name, `${name}:server`, {
570
548
  name,
571
549
  target: "server",
572
550
  type: "server",
573
551
  status: "error",
574
552
  message,
575
553
  });
576
-
577
- if (isFirstBuild) {
578
- isFirstBuild = false;
579
- serverRuntimePromises.get(name)?.resolver();
580
- }
581
- const updatedBuild = this._serverBuildWorkers.get(name)!;
582
- updatedBuild.buildResolver();
583
554
  });
584
555
  });
585
556
 
586
- /**
587
- * Start server runtime worker.
588
- * Separated as a dedicated function to catch errors from async event handlers.
589
- */
590
- const startServerRuntime = async (serverName: string, mainJsPath: string): Promise<void> => {
591
- this._logger.debug(`[${serverName}] startServerRuntime: ${mainJsPath}`);
592
- const updatedBuild = this._serverBuildWorkers.get(serverName)!;
593
- updatedBuild.mainJsPath = mainJsPath;
594
-
595
- // Terminate existing Server Runtime Worker
596
- const existingRuntime = this._serverRuntimeWorkers.get(serverName);
597
- if (existingRuntime != null) {
598
- this._logger.info(`[${serverName}] Restarting server...`);
599
- await existingRuntime.terminate();
600
- }
601
-
602
- // Create and start new Server Runtime Worker
603
- const runtimeWorker =
604
- Worker.create<typeof ServerRuntimeWorkerModule>(serverRuntimeWorkerPath);
605
- this._serverRuntimeWorkers.set(serverName, runtimeWorker);
606
-
607
- // Wait for Vite servers of clients connected to this server to be ready
608
- const connectedClients = this._serverClientsMap.get(serverName) ?? [];
609
- const clientReadyPromises = connectedClients
610
- .map((clientName) => viteClientReadyPromises.get(clientName)?.promise)
611
- .filter((p): p is Promise<void> => p != null);
612
- this._logger.debug(
613
- `[${serverName}] Waiting for clients: ${String(clientReadyPromises.length)} total`,
614
- );
615
- if (clientReadyPromises.length > 0) {
616
- await Promise.all(clientReadyPromises);
617
- }
618
-
619
- // Collect client ports for this server
620
- const serverClientPorts: Record<string, number> = {};
621
- for (const clientName of connectedClients) {
622
- if (clientName in this._clientPorts) {
623
- serverClientPorts[clientName] = this._clientPorts[clientName];
624
- }
625
- }
626
-
627
- // Server Runtime event handlers
628
- runtimeWorker.on("serverReady", (readyData) => {
629
- const readyEvent = readyData as ServerReadyEventData;
630
- this._results.set(`${serverName}:server`, {
631
- name: serverName,
632
- target: "server",
633
- type: "server",
634
- status: "running",
635
- port: readyEvent.port,
636
- });
637
-
638
- if (isFirstBuild) {
639
- isFirstBuild = false;
640
- serverRuntimePromises.get(serverName)?.resolver();
641
- }
642
- updatedBuild.buildResolver();
643
- });
644
-
645
- runtimeWorker.on("error", (errorData) => {
646
- const errorEvent = errorData as ErrorEventData;
647
- this._results.set(`${serverName}:server`, {
648
- name: serverName,
649
- target: "server",
650
- type: "server",
651
- status: "error",
652
- message: errorEvent.message,
653
- });
654
-
655
- if (isFirstBuild) {
656
- isFirstBuild = false;
657
- serverRuntimePromises.get(serverName)?.resolver();
658
- }
659
- updatedBuild.buildResolver();
660
- });
661
-
662
- // Start Server Runtime
663
- // If worker crashes, it terminates without emitting "serverReady"/"error" events,
664
- // so catch promise rejection to prevent hanging
665
- runtimeWorker
666
- .start({
667
- mainJsPath,
668
- clientPorts: serverClientPorts,
669
- })
670
- .catch((err: unknown) => {
671
- const message = errorMessage(err);
672
- this._logger.error(`[${serverName}] Server Runtime Worker crashed:`, message);
673
-
674
- this._results.set(`${serverName}:server`, {
675
- name: serverName,
676
- target: "server",
677
- type: "server",
678
- status: "error",
679
- message,
680
- });
681
-
682
- if (isFirstBuild) {
683
- isFirstBuild = false;
684
- serverRuntimePromises.get(serverName)?.resolver();
685
- }
686
- updatedBuild.buildResolver();
687
- });
688
- };
689
-
690
557
  serverBuild.worker.on("error", (data) => {
691
558
  const event = data as ErrorEventData;
692
- this._results.set(`${name}:build`, {
559
+ resolveServerStep(name, `${name}:build`, {
693
560
  name,
694
561
  target: "server",
695
562
  type: "build",
696
563
  status: "error",
697
564
  message: event.message,
698
565
  });
699
- if (isFirstBuild) {
700
- isFirstBuild = false;
701
- serverRuntimePromises.get(name)?.resolver();
702
- }
703
- this._serverBuildWorkers.get(name)!.buildResolver();
704
566
  });
705
567
  }
706
568
 
@@ -724,7 +586,7 @@ export class DevOrchestrator {
724
586
  target: "server",
725
587
  type: "build",
726
588
  status: "error",
727
- message: errorMessage(err),
589
+ message: errNs.message(err),
728
590
  });
729
591
  serverRuntimePromises.get(name)?.resolver();
730
592
  serverBuild.buildResolver();
@@ -737,6 +599,98 @@ export class DevOrchestrator {
737
599
  }));
738
600
  }
739
601
 
602
+ /**
603
+ * Start server runtime worker.
604
+ * Separated as a dedicated method to catch errors from async event handlers.
605
+ */
606
+ private async _startServerRuntime(
607
+ serverName: string,
608
+ mainJsPath: string,
609
+ serverRuntimeWorkerPath: string,
610
+ serverRuntimePromises: Map<string, { promise: Promise<void>; resolver: () => void }>,
611
+ resolveServerStep: (serverName: string, resultKey: string, result: BuildResult) => void,
612
+ viteClientReadyPromises: Map<string, { promise: Promise<void>; resolver: () => void }>,
613
+ ): Promise<void> {
614
+ this._logger.debug(`[${serverName}] _startServerRuntime: ${mainJsPath}`);
615
+ const updatedBuild = this._serverBuildWorkers.get(serverName)!;
616
+ updatedBuild.mainJsPath = mainJsPath;
617
+
618
+ // Terminate existing Server Runtime Worker
619
+ const existingRuntime = this._serverRuntimeWorkers.get(serverName);
620
+ if (existingRuntime != null) {
621
+ this._logger.info(`[${serverName}] Restarting server...`);
622
+ await existingRuntime.terminate();
623
+ }
624
+
625
+ // Create and start new Server Runtime Worker
626
+ const runtimeWorker = Worker.create<typeof ServerRuntimeWorkerModule>(serverRuntimeWorkerPath);
627
+ this._serverRuntimeWorkers.set(serverName, runtimeWorker);
628
+
629
+ // Wait for Vite servers of clients connected to this server to be ready
630
+ const connectedClients = this._serverClientsMap.get(serverName) ?? [];
631
+ const clientReadyPromises = connectedClients
632
+ .map((clientName) => viteClientReadyPromises.get(clientName)?.promise)
633
+ .filter((p): p is Promise<void> => p != null);
634
+ this._logger.debug(
635
+ `[${serverName}] Waiting for clients: ${String(clientReadyPromises.length)} total`,
636
+ );
637
+ if (clientReadyPromises.length > 0) {
638
+ await Promise.all(clientReadyPromises);
639
+ }
640
+
641
+ // Collect client ports for this server
642
+ const serverClientPorts: Record<string, number> = {};
643
+ for (const clientName of connectedClients) {
644
+ if (clientName in this._clientPorts) {
645
+ serverClientPorts[clientName] = this._clientPorts[clientName];
646
+ }
647
+ }
648
+
649
+ // Server Runtime event handlers
650
+ runtimeWorker.on("serverReady", (readyData) => {
651
+ const readyEvent = readyData as ServerReadyEventData;
652
+ resolveServerStep(serverName, `${serverName}:server`, {
653
+ name: serverName,
654
+ target: "server",
655
+ type: "server",
656
+ status: "running",
657
+ port: readyEvent.port,
658
+ });
659
+ });
660
+
661
+ runtimeWorker.on("error", (errorData) => {
662
+ const errorEvent = errorData as ErrorEventData;
663
+ resolveServerStep(serverName, `${serverName}:server`, {
664
+ name: serverName,
665
+ target: "server",
666
+ type: "server",
667
+ status: "error",
668
+ message: errorEvent.message,
669
+ });
670
+ });
671
+
672
+ // Start Server Runtime
673
+ // If worker crashes, it terminates without emitting "serverReady"/"error" events,
674
+ // so catch promise rejection to prevent hanging
675
+ runtimeWorker
676
+ .start({
677
+ mainJsPath,
678
+ clientPorts: serverClientPorts,
679
+ })
680
+ .catch((err: unknown) => {
681
+ const message = errNs.message(err);
682
+ this._logger.error(`[${serverName}] Server Runtime Worker crashed:`, message);
683
+
684
+ resolveServerStep(serverName, `${serverName}:server`, {
685
+ name: serverName,
686
+ target: "server",
687
+ type: "server",
688
+ status: "error",
689
+ message,
690
+ });
691
+ });
692
+ }
693
+
740
694
  /**
741
695
  * Wait for termination signal
742
696
  */
@@ -1,6 +1,6 @@
1
1
  import path from "path";
2
2
  import { consola } from "consola";
3
- import type { BuildTarget, SdConfig, SdPackageConfig } from "../sd-config.types";
3
+ import type { BuildTarget, SdBuildPackageConfig, SdConfig } from "../sd-config.types";
4
4
  import { loadSdConfig } from "../utils/sd-config";
5
5
  import { filterPackagesByTargets } from "../utils/package-utils";
6
6
  import { watchReplaceDeps, type WatchReplaceDepResult } from "../utils/replace-deps";
@@ -10,10 +10,9 @@ import { ResultCollector } from "../infra/ResultCollector";
10
10
  import { SignalHandler } from "../infra/SignalHandler";
11
11
  import { LibraryBuilder } from "../builders/LibraryBuilder";
12
12
  import { DtsBuilder } from "../builders/DtsBuilder";
13
- import type { PackageInfo } from "../builders/types";
13
+ import type { BuildPackageInfo } from "../builders/types";
14
14
  import { watchCopySrcFiles } from "../utils/copy-src";
15
15
  import type { FsWatcher } from "@simplysm/core-node";
16
- import type { SdBuildPackageConfig } from "../sd-config.types";
17
16
 
18
17
  /**
19
18
  * Watch command options
@@ -40,7 +39,7 @@ export class WatchOrchestrator {
40
39
  private _rebuildManager!: RebuildManager;
41
40
  private _libraryBuilder!: LibraryBuilder;
42
41
  private _dtsBuilder!: DtsBuilder;
43
- private _packages: PackageInfo[] = [];
42
+ private _packages: BuildPackageInfo[] = [];
44
43
  private _copySrcWatchers: FsWatcher[] = [];
45
44
  private _replaceDepWatcher: WatchReplaceDepResult | undefined;
46
45
 
@@ -64,7 +63,7 @@ export class WatchOrchestrator {
64
63
  sdConfig = await loadSdConfig({
65
64
  cwd: this._cwd,
66
65
  dev: true,
67
- opt: this._options.options,
66
+ options: this._options.options,
68
67
  });
69
68
  this._logger.debug("sd.config.ts loaded");
70
69
  } catch (err) {
@@ -85,10 +84,10 @@ export class WatchOrchestrator {
85
84
  const isLibraryTarget = (target: string): target is BuildTarget =>
86
85
  target === "node" || target === "browser" || target === "neutral";
87
86
 
88
- const libraryConfigs: Record<string, SdPackageConfig> = {};
87
+ const libraryConfigs: Record<string, SdBuildPackageConfig> = {};
89
88
  for (const [name, config] of Object.entries(allPackages)) {
90
89
  if (isLibraryTarget(config.target)) {
91
- libraryConfigs[name] = config;
90
+ libraryConfigs[name] = config as SdBuildPackageConfig;
92
91
  }
93
92
  }
94
93
 
@@ -145,9 +144,8 @@ export class WatchOrchestrator {
145
144
 
146
145
  // Start copySrc watch
147
146
  for (const pkg of this._packages) {
148
- const buildConfig = pkg.config as SdBuildPackageConfig;
149
- if (buildConfig.copySrc != null && buildConfig.copySrc.length > 0) {
150
- const watcher = await watchCopySrcFiles(pkg.dir, buildConfig.copySrc);
147
+ if (pkg.config.copySrc != null && pkg.config.copySrc.length > 0) {
148
+ const watcher = await watchCopySrcFiles(pkg.dir, pkg.config.copySrc);
151
149
  this._copySrcWatchers.push(watcher);
152
150
  }
153
151
  }
package/src/sd-cli.ts CHANGED
@@ -30,7 +30,7 @@ if (isDev) {
30
30
  try {
31
31
  const { loadSdConfig } = await import("./utils/sd-config.js");
32
32
  const { setupReplaceDeps } = await import("./utils/replace-deps.js");
33
- const sdConfig = await loadSdConfig({ cwd: process.cwd(), dev: false, opt: [] });
33
+ const sdConfig = await loadSdConfig({ cwd: process.cwd(), dev: false, options: [] });
34
34
  if (sdConfig.replaceDeps != null) {
35
35
  await setupReplaceDeps(process.cwd(), sdConfig.replaceDeps);
36
36
  }