everything-dev 1.44.0 → 1.45.0

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 (95) hide show
  1. package/dist/api-contract.cjs +26 -21
  2. package/dist/api-contract.cjs.map +1 -1
  3. package/dist/api-contract.mjs +27 -22
  4. package/dist/api-contract.mjs.map +1 -1
  5. package/dist/cli/catalog.cjs +2 -2
  6. package/dist/cli/catalog.cjs.map +1 -1
  7. package/dist/cli/catalog.mjs +2 -2
  8. package/dist/cli/catalog.mjs.map +1 -1
  9. package/dist/cli/infra.cjs +3 -0
  10. package/dist/cli/infra.cjs.map +1 -1
  11. package/dist/cli/infra.mjs +3 -0
  12. package/dist/cli/infra.mjs.map +1 -1
  13. package/dist/cli/init.cjs +5 -2
  14. package/dist/cli/init.cjs.map +1 -1
  15. package/dist/cli/init.d.cts +1 -1
  16. package/dist/cli/init.d.cts.map +1 -1
  17. package/dist/cli/init.d.mts +1 -1
  18. package/dist/cli/init.d.mts.map +1 -1
  19. package/dist/cli/init.mjs +5 -2
  20. package/dist/cli/init.mjs.map +1 -1
  21. package/dist/cli/status.cjs +8 -19
  22. package/dist/cli/status.cjs.map +1 -1
  23. package/dist/cli/status.mjs +8 -19
  24. package/dist/cli/status.mjs.map +1 -1
  25. package/dist/cli/sync.cjs +6 -0
  26. package/dist/cli/sync.cjs.map +1 -1
  27. package/dist/cli/sync.mjs +6 -0
  28. package/dist/cli/sync.mjs.map +1 -1
  29. package/dist/cli.cjs +43 -4
  30. package/dist/cli.cjs.map +1 -1
  31. package/dist/cli.mjs +43 -4
  32. package/dist/cli.mjs.map +1 -1
  33. package/dist/config.cjs +22 -11
  34. package/dist/config.cjs.map +1 -1
  35. package/dist/config.d.cts.map +1 -1
  36. package/dist/config.d.mts.map +1 -1
  37. package/dist/config.mjs +22 -11
  38. package/dist/config.mjs.map +1 -1
  39. package/dist/contract.cjs +22 -7
  40. package/dist/contract.cjs.map +1 -1
  41. package/dist/contract.d.cts +80 -7
  42. package/dist/contract.d.cts.map +1 -1
  43. package/dist/contract.d.mts +80 -7
  44. package/dist/contract.d.mts.map +1 -1
  45. package/dist/contract.meta.cjs +2 -0
  46. package/dist/contract.meta.cjs.map +1 -1
  47. package/dist/contract.meta.d.cts +6 -0
  48. package/dist/contract.meta.d.mts +6 -0
  49. package/dist/contract.meta.mjs +2 -0
  50. package/dist/contract.meta.mjs.map +1 -1
  51. package/dist/contract.mjs +22 -8
  52. package/dist/contract.mjs.map +1 -1
  53. package/dist/dev-session.cjs +3 -1
  54. package/dist/dev-session.cjs.map +1 -1
  55. package/dist/dev-session.mjs +3 -1
  56. package/dist/dev-session.mjs.map +1 -1
  57. package/dist/fastkv.cjs +2 -1
  58. package/dist/fastkv.cjs.map +1 -1
  59. package/dist/fastkv.mjs +2 -1
  60. package/dist/fastkv.mjs.map +1 -1
  61. package/dist/http-client.cjs +22 -2
  62. package/dist/http-client.cjs.map +1 -1
  63. package/dist/http-client.mjs +22 -2
  64. package/dist/http-client.mjs.map +1 -1
  65. package/dist/index.cjs +1 -0
  66. package/dist/index.d.cts +2 -2
  67. package/dist/index.d.mts +2 -2
  68. package/dist/index.mjs +2 -2
  69. package/dist/integrity.cjs +116 -0
  70. package/dist/integrity.cjs.map +1 -1
  71. package/dist/integrity.d.cts +21 -1
  72. package/dist/integrity.d.cts.map +1 -1
  73. package/dist/integrity.d.mts +21 -1
  74. package/dist/integrity.d.mts.map +1 -1
  75. package/dist/integrity.mjs +111 -1
  76. package/dist/integrity.mjs.map +1 -1
  77. package/dist/near-cli.cjs +12 -15
  78. package/dist/near-cli.cjs.map +1 -1
  79. package/dist/near-cli.mjs +12 -15
  80. package/dist/near-cli.mjs.map +1 -1
  81. package/dist/orchestrator.cjs +39 -23
  82. package/dist/orchestrator.cjs.map +1 -1
  83. package/dist/orchestrator.mjs +39 -23
  84. package/dist/orchestrator.mjs.map +1 -1
  85. package/dist/plugin.cjs +332 -108
  86. package/dist/plugin.cjs.map +1 -1
  87. package/dist/plugin.d.cts +32 -2
  88. package/dist/plugin.d.cts.map +1 -1
  89. package/dist/plugin.d.mts +32 -2
  90. package/dist/plugin.d.mts.map +1 -1
  91. package/dist/plugin.mjs +335 -111
  92. package/dist/plugin.mjs.map +1 -1
  93. package/dist/types.d.cts +2 -2
  94. package/dist/types.d.mts +2 -2
  95. package/package.json +1 -1
package/dist/plugin.mjs CHANGED
@@ -5,7 +5,7 @@ import { BosConfigSchema } from "./types.mjs";
5
5
  import { buildRuntimePluginsForConfig, drainConfigWarnings, findConfigPath, getHostDevelopmentPort, getProjectRoot, loadLocalConfig, loadResolvedConfig, resolveConfigComposableEntries, resolveLocalDevelopmentPath, resumeWarnings, suppressWarnings, writeResolvedConfig } from "./config.mjs";
6
6
  import { createPlugin, z } from "./sdk.mjs";
7
7
  import { bosContract } from "./contract.mjs";
8
- import { computeSriHashForUrl } from "./integrity.mjs";
8
+ import { applyDeployResults, cleanDeployResultDir, computeSriHashForUrl, readAllDeployResults, readDeployResults } from "./integrity.mjs";
9
9
  import { syncApiContractBridge } from "./api-contract.mjs";
10
10
  import { buildRuntimeConfig, detectLocalPackages, prepareDevelopmentRuntimeConfig } from "./app.mjs";
11
11
  import { ensureEnvFile, loadProjectEnv, syncGeneratedInfra, writeGeneratedInfra } from "./cli/infra.mjs";
@@ -15,11 +15,11 @@ import { getStatus } from "./cli/status.mjs";
15
15
  import { syncResolvedSharedDeps } from "./shared-deps.mjs";
16
16
  import { syncTemplate } from "./cli/sync.mjs";
17
17
  import { upgradeTemplate } from "./cli/upgrade.mjs";
18
- import { colors } from "./utils/theme.mjs";
18
+ import { colors, icons } from "./utils/theme.mjs";
19
19
  import { addFunctionCallAccessKey, ensureNearCli, executeTransaction, resolveNearSigningMode } from "./near-cli.mjs";
20
20
  import { buildDescription, buildServiceDescriptorMap } from "./service-descriptor.mjs";
21
21
  import { run } from "./utils/run.mjs";
22
- import { existsSync, readFileSync, writeFileSync } from "node:fs";
22
+ import { existsSync, readFileSync, rmSync, writeFileSync } from "node:fs";
23
23
  import { basename, dirname, join, resolve } from "node:path";
24
24
  import { Effect } from "effect";
25
25
  import { EventEmitter } from "node:events";
@@ -227,9 +227,9 @@ async function waitForPublishedConfig(opts) {
227
227
  const reason = lastError instanceof Error ? ` Last error: ${lastError.message}` : "";
228
228
  throw new Error(`Timed out waiting for publish confirmation at bos://${opts.account}/${opts.gateway}.${reason}`);
229
229
  }
230
- async function buildEveryPluginQuietly(cwd) {
230
+ async function buildEveryPluginQuietly(cwd, force = false) {
231
231
  if (!await fileExists(`${`${cwd}/packages/every-plugin`}/package.json`)) return;
232
- if (await fileExists(`${cwd}/packages/every-plugin/dist/build/rspack/plugin.mjs`)) return;
232
+ if (await fileExists(`${cwd}/packages/every-plugin/dist/build/rspack/plugin.mjs`) && !force) return;
233
233
  const result = await run("bun", [
234
234
  "run",
235
235
  "--cwd",
@@ -239,17 +239,14 @@ async function buildEveryPluginQuietly(cwd) {
239
239
  cwd,
240
240
  capture: true
241
241
  });
242
- if (result.exitCode === 0) {
243
- console.log("[build:ssr] build succeeded");
244
- return;
245
- }
242
+ if (result.exitCode === 0) return;
246
243
  if (result.stdout.trim()) process.stdout.write(result.stdout);
247
244
  if (result.stderr.trim()) process.stderr.write(result.stderr);
248
245
  throw new Error(`bun run --cwd packages/every-plugin build failed with exit code ${result.exitCode}`);
249
246
  }
250
- async function buildEverythingDevQuietly(cwd) {
247
+ async function buildEverythingDevQuietly(cwd, force = false) {
251
248
  if (!await fileExists(`${`${cwd}/packages/everything-dev`}/package.json`)) return;
252
- if (await fileExists(`${cwd}/packages/everything-dev/dist/index.mjs`)) return;
249
+ if (await fileExists(`${cwd}/packages/everything-dev/dist/index.mjs`) && !force) return;
253
250
  const result = await run("bun", [
254
251
  "run",
255
252
  "--cwd",
@@ -259,10 +256,7 @@ async function buildEverythingDevQuietly(cwd) {
259
256
  cwd,
260
257
  capture: true
261
258
  });
262
- if (result.exitCode === 0) {
263
- console.log("[everything-dev] build succeeded");
264
- return;
265
- }
259
+ if (result.exitCode === 0) return;
266
260
  if (result.stdout.trim()) process.stdout.write(result.stdout);
267
261
  if (result.stderr.trim()) process.stderr.write(result.stderr);
268
262
  throw new Error(`bun run --cwd packages/everything-dev build failed with exit code ${result.exitCode}`);
@@ -295,6 +289,141 @@ function selectWorkspaceTargets(packages, bosConfig) {
295
289
  if (packages === "all") return allPackages;
296
290
  return packages.split(",").map((pkg) => pkg.trim()).filter((pkg) => allPackages.includes(pkg));
297
291
  }
292
+ function padRight(str, len) {
293
+ return str.length >= len ? str : str + " ".repeat(len - str.length);
294
+ }
295
+ function formatDuration(ms) {
296
+ if (ms < 1e3) return `${ms}ms`;
297
+ return `${(ms / 1e3).toFixed(1)}s`;
298
+ }
299
+ async function runBuildAttempt(cmd, args, cwd, env, verbose, wsKey, resultBaseDir) {
300
+ if (verbose) try {
301
+ await run(cmd, args, {
302
+ cwd,
303
+ env,
304
+ capture: false
305
+ });
306
+ if (resultBaseDir) {
307
+ const results = readDeployResults(join(resultBaseDir, wsKey));
308
+ if (results.length > 0) return {
309
+ success: true,
310
+ url: results[0]?.url,
311
+ exitCode: 0,
312
+ output: ""
313
+ };
314
+ }
315
+ return {
316
+ success: true,
317
+ exitCode: 0,
318
+ output: ""
319
+ };
320
+ } catch (err) {
321
+ return {
322
+ success: false,
323
+ error: err instanceof Error ? err.message : String(err),
324
+ exitCode: 1,
325
+ output: ""
326
+ };
327
+ }
328
+ const result = await run(cmd, args, {
329
+ cwd,
330
+ env,
331
+ capture: true
332
+ });
333
+ const stdout = result?.stdout ?? "";
334
+ const stderr = result?.stderr ?? "";
335
+ const exitCode = result?.exitCode ?? 0;
336
+ const output = `${stdout}\n${stderr}`;
337
+ if (exitCode !== 0) return {
338
+ success: false,
339
+ error: `Build failed (exit code ${exitCode})\n${output.trim().split("\n").slice(-5).join("\n")}`,
340
+ exitCode,
341
+ output
342
+ };
343
+ const zeMatch = output.match(/ZE\d+/);
344
+ if (zeMatch) return {
345
+ success: false,
346
+ error: `Zephyr upload failed (${zeMatch[0]})`,
347
+ exitCode: 0,
348
+ output
349
+ };
350
+ if (resultBaseDir) {
351
+ const results = readDeployResults(join(resultBaseDir, wsKey));
352
+ if (results.length > 0) return {
353
+ success: true,
354
+ url: results[0]?.url,
355
+ exitCode: 0,
356
+ output
357
+ };
358
+ }
359
+ const deployMatch = output.match(/🚀.*Deployed:\s*(https?:\S+)/);
360
+ if (deployMatch) return {
361
+ success: true,
362
+ url: deployMatch[1],
363
+ exitCode: 0,
364
+ output
365
+ };
366
+ if (env.DEPLOY === "true") return {
367
+ success: false,
368
+ error: "No deploy URL found (Zephyr may have failed)",
369
+ exitCode: 0,
370
+ output
371
+ };
372
+ return {
373
+ success: true,
374
+ exitCode: 0,
375
+ output
376
+ };
377
+ }
378
+ async function buildOneWorkspace(ws, env, opts, resultBaseDir) {
379
+ const pkgJson = await readJsonFile(`${ws.path}/package.json`);
380
+ const buildConfig = opts.deploy && pkgJson.scripts?.deploy ? {
381
+ cmd: "bun",
382
+ args: ["run", "deploy"]
383
+ } : buildCommands[ws.key] ?? {
384
+ cmd: "bun",
385
+ args: ["run", "build"]
386
+ };
387
+ const wsEnv = { ...env };
388
+ if (resultBaseDir) wsEnv.BOS_DEPLOY_RESULT_DIR = join(resultBaseDir, ws.key);
389
+ const startTime = Date.now();
390
+ let attempt = await runBuildAttempt(buildConfig.cmd, buildConfig.args, ws.path, wsEnv, opts.verbose ?? false, ws.key, resultBaseDir);
391
+ let retried = false;
392
+ if (!attempt.success && attempt.exitCode === 0 && opts.deploy) {
393
+ if (!opts.verbose) console.log(` ${colors.yellow("↻")} ${padRight(ws.key, 28)} retrying...`);
394
+ if (resultBaseDir) {
395
+ const wsResultDir = join(resultBaseDir, ws.key);
396
+ if (existsSync(wsResultDir)) rmSync(wsResultDir, {
397
+ recursive: true,
398
+ force: true
399
+ });
400
+ }
401
+ retried = true;
402
+ attempt = await runBuildAttempt(buildConfig.cmd, buildConfig.args, ws.path, wsEnv, opts.verbose ?? false, ws.key, resultBaseDir);
403
+ }
404
+ const durationMs = Date.now() - startTime;
405
+ const result = {
406
+ key: ws.key,
407
+ kind: ws.kind,
408
+ success: attempt.success,
409
+ url: attempt.url,
410
+ error: attempt.error,
411
+ durationMs,
412
+ retried: retried ? true : void 0
413
+ };
414
+ if (!opts.verbose) {
415
+ const name = padRight(ws.key, 28);
416
+ if (result.success) {
417
+ const duration = formatDuration(durationMs);
418
+ const retryTag = retried ? " (retried)" : "";
419
+ console.log(` ${colors.green(icons.ok)} ${name} ${colors.dim(duration + retryTag)}`);
420
+ } else {
421
+ const errorLine = (result.error ?? "Failed").split("\n")[0];
422
+ console.log(` ${colors.error(icons.err)} ${name} ${errorLine}`);
423
+ }
424
+ }
425
+ return result;
426
+ }
298
427
  async function buildWorkspaceTargets(opts) {
299
428
  const existing = [];
300
429
  const skipped = [];
@@ -317,26 +446,74 @@ async function buildWorkspaceTargets(opts) {
317
446
  bosConfig: opts.bosConfig ?? void 0,
318
447
  extendsChain: []
319
448
  })).catalogChanged) await run("bun", ["install"], { cwd: opts.configDir });
320
- if (existing.some((entry) => entry.key === "api")) await buildEveryPluginQuietly(opts.configDir);
321
- await buildEverythingDevQuietly(opts.configDir);
449
+ const shouldBuildPlugin = existing.some((entry) => entry.key === "api");
450
+ const forceRebuild = opts.deploy;
451
+ const buildTasks = [buildEverythingDevQuietly(opts.configDir, forceRebuild)];
452
+ if (shouldBuildPlugin) buildTasks.push(buildEveryPluginQuietly(opts.configDir, forceRebuild));
453
+ await Promise.all(buildTasks);
322
454
  const env = {
323
455
  ...process.env,
324
456
  NODE_ENV: opts.deploy ? "production" : "development"
325
457
  };
326
458
  if (opts.deploy) env.DEPLOY = "true";
327
459
  else delete env.DEPLOY;
460
+ const resultBaseDir = opts.deploy ? join(opts.configDir, ".bos", "deploy-results") : void 0;
461
+ if (resultBaseDir) cleanDeployResultDir(resultBaseDir);
462
+ const bosConfigPath = join(opts.configDir, "bos.config.json");
463
+ let configSnapshot;
464
+ if (opts.deploy && existsSync(bosConfigPath)) configSnapshot = readFileSync(bosConfigPath, "utf-8");
328
465
  const orderedExisting = opts.deploy ? [
329
466
  ...existing.filter((entry) => entry.kind === "app" && entry.key !== "host"),
330
467
  ...existing.filter((entry) => entry.kind === "plugin"),
331
468
  ...existing.filter((entry) => entry.kind === "app" && entry.key === "host")
332
469
  ] : existing;
470
+ const parallelGroup = opts.deploy ? orderedExisting.filter((e) => e.key !== "host") : orderedExisting;
471
+ const sequentialGroup = opts.deploy ? orderedExisting.filter((e) => e.key === "host") : [];
333
472
  const built = [];
334
- for (const resolved of orderedExisting) {
335
- const pkgJson = await readJsonFile(`${resolved.path}/package.json`);
336
- const buildConfig = opts.deploy && pkgJson.scripts?.deploy ? {
337
- cmd: "bun",
338
- args: ["run", "deploy"]
339
- } : buildCommands[resolved.key] ?? {
473
+ const deployResults = [];
474
+ if (opts.deploy && parallelGroup.length > 0) {
475
+ const total = parallelGroup.length + sequentialGroup.length;
476
+ console.log();
477
+ console.log(` Building ${total} workspace${total > 1 ? "s" : ""}...`);
478
+ console.log();
479
+ const results = await Promise.allSettled(parallelGroup.map((ws) => buildOneWorkspace(ws, env, opts, resultBaseDir)));
480
+ for (let i = 0; i < parallelGroup.length; i++) {
481
+ const ws = parallelGroup[i];
482
+ const result = results[i];
483
+ if (result.status === "fulfilled") {
484
+ if (result.value.success) built.push(ws.key);
485
+ deployResults.push(result.value);
486
+ } else deployResults.push({
487
+ key: ws.key,
488
+ kind: ws.kind,
489
+ success: false,
490
+ error: result.reason?.message ?? "Unknown error"
491
+ });
492
+ }
493
+ if (resultBaseDir && configSnapshot) {
494
+ const allResults = readAllDeployResults(resultBaseDir);
495
+ if (allResults.length > 0) {
496
+ const merged = applyDeployResults(JSON.parse(configSnapshot), allResults);
497
+ writeFileSync(bosConfigPath, `${JSON.stringify(merged, null, 2)}\n`);
498
+ }
499
+ }
500
+ for (const ws of sequentialGroup) {
501
+ const result = await buildOneWorkspace(ws, env, opts, resultBaseDir);
502
+ if (result.success) built.push(ws.key);
503
+ deployResults.push(result);
504
+ }
505
+ if (resultBaseDir && existsSync(bosConfigPath)) {
506
+ const allResults = readAllDeployResults(resultBaseDir);
507
+ const currentConfig = JSON.parse(readFileSync(bosConfigPath, "utf-8"));
508
+ const hostResults = allResults.filter((r) => r.urlField.startsWith("app.host"));
509
+ if (hostResults.length > 0) {
510
+ const merged = applyDeployResults(currentConfig, hostResults);
511
+ writeFileSync(bosConfigPath, `${JSON.stringify(merged, null, 2)}\n`);
512
+ }
513
+ }
514
+ console.log();
515
+ } else for (const resolved of orderedExisting) {
516
+ const buildConfig = buildCommands[resolved.key] ?? {
340
517
  cmd: "bun",
341
518
  args: ["run", "build"]
342
519
  };
@@ -348,7 +525,8 @@ async function buildWorkspaceTargets(opts) {
348
525
  }
349
526
  return {
350
527
  built,
351
- skipped
528
+ skipped,
529
+ deployResults: opts.deploy ? deployResults : void 0
352
530
  };
353
531
  }
354
532
  var plugin_default = createPlugin({
@@ -521,12 +699,9 @@ var plugin_default = createPlugin({
521
699
  };
522
700
  }),
523
701
  dev: builder.dev.handler(async ({ input }) => {
702
+ const devTimings = [];
524
703
  ensureEnvFile(deps.configDir);
525
704
  loadProjectEnv(deps.configDir);
526
- pluginEvents.emit("progress", {
527
- phase: "config",
528
- status: "running"
529
- });
530
705
  const localPackages = detectLocalPackages(deps.bosConfig ?? void 0, deps.runtimeConfig ?? void 0);
531
706
  const hostSource = localPackages.includes("host") ? parseSourceMode(input.host, "local") : "remote";
532
707
  const uiSource = localPackages.includes("ui") ? parseSourceMode(input.ui, "local") : "remote";
@@ -534,61 +709,44 @@ var plugin_default = createPlugin({
534
709
  const authSource = localPackages.includes("auth") ? parseSourceMode(input.auth, "local") : "remote";
535
710
  const ssr = input.ssr ?? false;
536
711
  const proxy = input.proxy ?? false;
537
- if ((await syncResolvedSharedDeps({
712
+ const sharedSync = await timePhase(devTimings, "shared deps", () => syncResolvedSharedDeps({
538
713
  configDir: deps.configDir,
539
714
  hostMode: hostSource,
540
715
  bosConfig: deps.bosConfig ?? void 0,
541
716
  extendsChain: []
542
- })).catalogChanged) {
543
- pluginEvents.emit("progress", {
544
- phase: "install",
545
- status: "running"
546
- });
547
- await run("bun", ["install"], { cwd: deps.configDir });
548
- pluginEvents.emit("progress", {
549
- phase: "install",
550
- status: "done"
551
- });
552
- }
553
- if (apiSource === "local" && !proxy || localPackages.some((pkg) => pkg.startsWith("plugin:"))) {
554
- pluginEvents.emit("progress", {
555
- phase: "build plugin",
556
- status: "running"
557
- });
558
- await buildEveryPluginQuietly(deps.configDir);
559
- pluginEvents.emit("progress", {
560
- phase: "build plugin",
561
- status: "done"
562
- });
717
+ }));
718
+ let configMayHaveChanged = false;
719
+ if (sharedSync.catalogChanged) {
720
+ await timePhase(devTimings, "install", () => run("bun", ["install"], { cwd: deps.configDir }));
721
+ configMayHaveChanged = true;
563
722
  }
564
- pluginEvents.emit("progress", {
565
- phase: "build",
566
- status: "running"
567
- });
568
- await buildEverythingDevQuietly(deps.configDir);
569
- pluginEvents.emit("progress", {
570
- phase: "build",
571
- status: "done"
572
- });
573
- pluginEvents.emit("progress", {
574
- phase: "config",
575
- status: "done"
723
+ const shouldBuildPlugin = apiSource === "local" && !proxy || localPackages.some((pkg) => pkg.startsWith("plugin:"));
724
+ await timePhase(devTimings, "build", async () => {
725
+ const buildTasks = [buildEverythingDevQuietly(deps.configDir)];
726
+ if (shouldBuildPlugin) buildTasks.push(buildEveryPluginQuietly(deps.configDir));
727
+ await Promise.all(buildTasks);
576
728
  });
577
- const refreshed = await loadResolvedConfig({
578
- cwd: deps.configDir,
579
- remotePlugins: input.remotePlugins
580
- });
581
- deps.bosConfig = refreshed?.config ?? deps.bosConfig;
582
- deps.runtimeConfig = refreshed?.runtime ?? deps.runtimeConfig;
729
+ let devExtendsChain;
730
+ if (configMayHaveChanged || input.remotePlugins?.length) {
731
+ const refreshed = await timePhase(devTimings, "resolve config", () => loadResolvedConfig({
732
+ cwd: deps.configDir,
733
+ remotePlugins: input.remotePlugins
734
+ }));
735
+ deps.bosConfig = refreshed?.config ?? deps.bosConfig;
736
+ deps.runtimeConfig = refreshed?.runtime ?? deps.runtimeConfig;
737
+ devExtendsChain = refreshed?.source.extended;
738
+ }
583
739
  if (!deps.bosConfig) return {
584
740
  status: "error",
585
741
  description: "No bos.config.json found",
586
- processes: []
742
+ processes: [],
743
+ timings: devTimings
587
744
  };
588
745
  if (proxy && !resolveProxyUrl(deps.bosConfig)) return {
589
746
  status: "error",
590
747
  description: "No valid proxy URL configured in bos.config.json",
591
- processes: []
748
+ processes: [],
749
+ timings: devTimings
592
750
  };
593
751
  const hostPort = input.port ?? getHostDevelopmentPort(deps.bosConfig.app.host.development);
594
752
  suppressWarnings();
@@ -602,20 +760,18 @@ var plugin_default = createPlugin({
602
760
  });
603
761
  drainConfigWarnings();
604
762
  resumeWarnings();
605
- const runtimeConfig = await prepareDevelopmentRuntimeConfig(developmentRuntime, {
763
+ const runtimeConfig = await timePhase(devTimings, "ports", () => prepareDevelopmentRuntimeConfig(developmentRuntime, {
606
764
  hostPort,
607
765
  ssr
608
- });
766
+ }));
609
767
  syncGeneratedInfra(deps.configDir, runtimeConfig);
610
- if (!existsSync(join(deps.configDir, ".env"))) {
611
- ensureEnvFile(deps.configDir);
612
- loadProjectEnv(deps.configDir);
613
- }
614
- await generateCodeArtifacts(deps.configDir, deps.bosConfig, {
768
+ ensureEnvFile(deps.configDir);
769
+ loadProjectEnv(deps.configDir);
770
+ await timePhase(devTimings, "generate artifacts", () => generateCodeArtifacts(deps.configDir, deps.bosConfig, {
615
771
  env: "development",
616
- extendsChain: refreshed?.source.extended,
772
+ extendsChain: devExtendsChain,
617
773
  runtimeConfig
618
- });
774
+ }));
619
775
  const services = buildServiceDescriptorMap(runtimeConfig, {
620
776
  ssr,
621
777
  proxy
@@ -647,7 +803,8 @@ var plugin_default = createPlugin({
647
803
  return {
648
804
  status: "started",
649
805
  description: orchestrator.description,
650
- processes: packages
806
+ processes: packages,
807
+ timings: devTimings
651
808
  };
652
809
  }),
653
810
  start: builder.start.handler(async ({ input }) => {
@@ -708,10 +865,8 @@ var plugin_default = createPlugin({
708
865
  if (isStaging && config.staging?.domain) runtimeConfig.domain = config.staging.domain;
709
866
  if (isStaging) runtimeConfig.env = "staging";
710
867
  syncGeneratedInfra(deps.configDir, runtimeConfig);
711
- if (!existsSync(join(deps.configDir, ".env"))) {
712
- ensureEnvFile(deps.configDir);
713
- loadProjectEnv(deps.configDir);
714
- }
868
+ ensureEnvFile(deps.configDir);
869
+ loadProjectEnv(deps.configDir);
715
870
  pluginEvents.emit("progress", {
716
871
  phase: "generate artifacts",
717
872
  status: "running"
@@ -843,6 +998,7 @@ var plugin_default = createPlugin({
843
998
  env: input.env,
844
999
  build: input.deploy,
845
1000
  dryRun: input.dryRun,
1001
+ verbose: input.verbose,
846
1002
  packages: input.packages,
847
1003
  network: input.network,
848
1004
  privateKey: input.privateKey
@@ -860,7 +1016,8 @@ var plugin_default = createPlugin({
860
1016
  txHash: result.txHash,
861
1017
  error: result.error,
862
1018
  built: result.built,
863
- skipped: result.skipped
1019
+ skipped: result.skipped,
1020
+ deployResults: result.deployResults
864
1021
  };
865
1022
  }),
866
1023
  deploy: builder.deploy.handler(async ({ input }) => {
@@ -877,6 +1034,7 @@ var plugin_default = createPlugin({
877
1034
  env: input.env,
878
1035
  build: input.build,
879
1036
  dryRun: input.dryRun,
1037
+ verbose: input.verbose,
880
1038
  packages: input.packages,
881
1039
  network: input.network,
882
1040
  privateKey: input.privateKey
@@ -888,7 +1046,8 @@ var plugin_default = createPlugin({
888
1046
  built: result.built,
889
1047
  skipped: result.skipped,
890
1048
  redeployed: false,
891
- error: result.error
1049
+ error: result.error,
1050
+ deployResults: result.deployResults
892
1051
  };
893
1052
  if (result.status === "dry-run") return {
894
1053
  status: "dry-run",
@@ -918,6 +1077,7 @@ var plugin_default = createPlugin({
918
1077
  built: result.built,
919
1078
  skipped: result.skipped,
920
1079
  redeployed: false,
1080
+ deployResults: result.deployResults,
921
1081
  error: "Config published but Railway redeploy failed: ci.railway.service is not configured in bos.config.json"
922
1082
  };
923
1083
  }
@@ -948,6 +1108,7 @@ var plugin_default = createPlugin({
948
1108
  skipped: result.skipped,
949
1109
  redeployed: false,
950
1110
  service,
1111
+ deployResults: result.deployResults,
951
1112
  error: `Config published but ${railError}`
952
1113
  };
953
1114
  }
@@ -962,7 +1123,8 @@ var plugin_default = createPlugin({
962
1123
  built: result.built,
963
1124
  skipped: result.skipped,
964
1125
  redeployed,
965
- service
1126
+ service,
1127
+ deployResults: result.deployResults
966
1128
  };
967
1129
  }),
968
1130
  keyPublish: builder.keyPublish.handler(async ({ input }) => {
@@ -1039,6 +1201,17 @@ var plugin_default = createPlugin({
1039
1201
  overrides = overrides?.length ? overrides : ["ui", "api"];
1040
1202
  if (overrides.includes("plugins") && plugins === void 0) plugins = parentPluginKeys;
1041
1203
  plugins = plugins ?? [];
1204
+ const pluginDirMap = {};
1205
+ if (parentConfig?.plugins) for (const plugin of plugins) {
1206
+ const entry = parentConfig.plugins?.[plugin];
1207
+ if (entry && typeof entry === "object") {
1208
+ const dev = entry.development;
1209
+ if (typeof dev === "string") {
1210
+ const match = dev.match(/^local:plugins\/(.+)$/);
1211
+ if (match?.[1] && match[1] !== plugin) pluginDirMap[plugin] = match[1];
1212
+ }
1213
+ }
1214
+ }
1042
1215
  directory = directory || domain || extendsGateway;
1043
1216
  const targetDir = resolve(directory);
1044
1217
  const extendsRef = `bos://${extendsAccount}/${extendsGateway}`;
@@ -1096,7 +1269,7 @@ var plugin_default = createPlugin({
1096
1269
  staging: parentConfig?.staging
1097
1270
  }));
1098
1271
  } else {
1099
- const patterns = buildInitPatterns(overrides, plugins);
1272
+ const patterns = buildInitPatterns(overrides, plugins, pluginDirMap);
1100
1273
  filesCopied = await timePhase(timings, "copy files", () => copyFilteredFiles(sourceDir, targetDir, patterns, {
1101
1274
  overrides,
1102
1275
  plugins
@@ -1384,13 +1557,28 @@ async function publishToFastKv(input) {
1384
1557
  const targets = selectWorkspaceTargets(input.packages, bosConfig);
1385
1558
  let built;
1386
1559
  let skipped;
1560
+ let deployResults;
1387
1561
  if (dryRun) return {
1388
1562
  status: "dry-run",
1389
1563
  registryUrl,
1390
1564
  built,
1391
1565
  skipped
1392
1566
  };
1567
+ const privateKey = input.privateKey || process.env.NEAR_PRIVATE_KEY || process.env.BOS_NEAR_PRIVATE_KEY;
1568
+ let signingMode;
1569
+ try {
1570
+ signingMode = resolveNearSigningMode(privateKey);
1571
+ } catch (error) {
1572
+ return {
1573
+ status: "error",
1574
+ registryUrl,
1575
+ error: error instanceof Error ? error.message : "Unknown error"
1576
+ };
1577
+ }
1393
1578
  if (input.build) {
1579
+ console.log(" Ensuring NEAR CLI...");
1580
+ await Effect.runPromise(ensureNearCli);
1581
+ console.log(" NEAR CLI ready");
1394
1582
  await generateCodeArtifacts(configDir, bosConfig, {
1395
1583
  env: "production",
1396
1584
  runtimeConfig: runtimeConfig ?? void 0
@@ -1400,16 +1588,45 @@ async function publishToFastKv(input) {
1400
1588
  bosConfig,
1401
1589
  runtimeConfig,
1402
1590
  targets,
1403
- deploy: true
1591
+ deploy: true,
1592
+ verbose: input.verbose
1404
1593
  });
1405
1594
  built = result.built;
1406
1595
  skipped = result.skipped;
1596
+ deployResults = result.deployResults;
1597
+ if (deployResults) {
1598
+ const failures = deployResults.filter((r) => !r.success);
1599
+ if (failures.length > 0) {
1600
+ const total = deployResults.length;
1601
+ console.log();
1602
+ console.log(colors.error(` ${icons.err} Deploy failed — ${failures.length} of ${total} workspace${total > 1 ? "s" : ""} failed`));
1603
+ console.log();
1604
+ for (const f of failures) {
1605
+ const errorLine = (f.error ?? "Failed").split("\n")[0];
1606
+ console.log(` ${colors.error(icons.err)} ${padRight(f.key, 28)} ${errorLine}`);
1607
+ }
1608
+ console.log();
1609
+ if (!input.verbose) {
1610
+ console.log(colors.dim(" Run with --verbose for full build output."));
1611
+ console.log();
1612
+ }
1613
+ return {
1614
+ status: "error",
1615
+ registryUrl,
1616
+ built,
1617
+ skipped,
1618
+ deployResults,
1619
+ error: `${failures.length} of ${total} workspaces failed to deploy`
1620
+ };
1621
+ }
1622
+ }
1407
1623
  const refreshed = await loadResolvedConfig({ cwd: configDir });
1408
1624
  if (!refreshed?.config) return {
1409
1625
  status: "error",
1410
1626
  registryUrl,
1411
1627
  built,
1412
1628
  skipped,
1629
+ deployResults,
1413
1630
  error: "Failed to reload bos.config.json after build"
1414
1631
  };
1415
1632
  bosConfig = refreshed.config;
@@ -1423,28 +1640,14 @@ async function publishToFastKv(input) {
1423
1640
  const registryEntries = { [`apps/${account}/${gateway}/bos.config.json`]: JSON.stringify(publishPayload) };
1424
1641
  const payload = JSON.stringify(registryEntries);
1425
1642
  const argsBase64 = Buffer.from(payload).toString("base64");
1426
- const privateKey = input.privateKey || process.env.NEAR_PRIVATE_KEY || process.env.BOS_NEAR_PRIVATE_KEY;
1427
- let signingMode;
1428
- try {
1429
- signingMode = resolveNearSigningMode(privateKey);
1430
- } catch (error) {
1431
- return {
1432
- status: "error",
1433
- registryUrl,
1434
- error: error instanceof Error ? error.message : "Unknown error"
1435
- };
1436
- }
1437
1643
  console.log();
1438
1644
  console.log(" Publishing to:");
1439
1645
  console.log(` ${colors.cyan(registryUrl)}`);
1440
1646
  try {
1441
- console.log(" Ensuring NEAR CLI...");
1442
- await Effect.runPromise(ensureNearCli);
1443
- console.log(" NEAR CLI ready");
1444
1647
  let txHash;
1445
1648
  console.log(` Submitting transaction on ${network}...`);
1446
1649
  try {
1447
- txHash = (await Effect.runPromise(executeTransaction({
1650
+ const tx = await Effect.runPromise(executeTransaction({
1448
1651
  account,
1449
1652
  contract: getRegistryNamespaceForNetwork(network),
1450
1653
  method: "__fastdata_kv",
@@ -1452,12 +1655,25 @@ async function publishToFastKv(input) {
1452
1655
  network,
1453
1656
  privateKey: signingMode._tag === "privateKey" ? signingMode.privateKey : void 0,
1454
1657
  gas: "300Tgas",
1455
- deposit: "0NEAR"
1456
- }, signingMode))).txHash;
1457
- if (txHash) console.log(` Transaction submitted: ${colors.dim(txHash)}`);
1658
+ deposit: "0NEAR",
1659
+ verbose: input.verbose
1660
+ }, signingMode));
1661
+ txHash = tx.txHash;
1662
+ if (txHash && !tx.output?.includes("CodeDoesNotExist")) console.log(` Transaction submitted: ${colors.dim(txHash)}`);
1458
1663
  } catch (error) {
1459
- txHash = extractTransactionHash(error);
1460
- if (!txHash) throw error;
1664
+ console.log(colors.dim(" Transaction reported an error — verifying publish..."));
1665
+ try {
1666
+ await waitForPublishedConfig({
1667
+ account,
1668
+ gateway,
1669
+ publishConfig: publishPayload,
1670
+ timeoutMs: 3e4,
1671
+ intervalMs: 2e3
1672
+ });
1673
+ txHash = extractTransactionHash(error);
1674
+ } catch {
1675
+ throw error;
1676
+ }
1461
1677
  }
1462
1678
  console.log(" Waiting for publish confirmation...");
1463
1679
  await waitForPublishedConfig({
@@ -1471,18 +1687,26 @@ async function publishToFastKv(input) {
1471
1687
  txHash,
1472
1688
  built,
1473
1689
  skipped,
1690
+ deployResults,
1474
1691
  publishConfig: publishPayload
1475
1692
  };
1476
1693
  } catch (error) {
1477
1694
  return {
1478
1695
  status: "error",
1479
1696
  registryUrl,
1480
- error: error instanceof Error ? error.message : "Unknown error",
1697
+ error: formatNearError(error),
1481
1698
  built,
1482
- skipped
1699
+ skipped,
1700
+ deployResults
1483
1701
  };
1484
1702
  }
1485
1703
  }
1704
+ function formatNearError(error) {
1705
+ const message = error instanceof Error ? error.message : String(error);
1706
+ if (message.includes("exceeded gas") || message.includes("GasLimitExceeded")) return `Transaction exceeded gas limit.\n Original: ${message}`;
1707
+ if (message.includes("timeout") || message.includes("Timeout")) return `Transaction timed out. Check NEAR network status.\n Original: ${message}`;
1708
+ return message;
1709
+ }
1486
1710
  function extractTransactionHash(error) {
1487
1711
  return (error instanceof Error ? error.message : String(error)).match(/Transaction ID:\s*([A-Za-z0-9]+)/i)?.[1];
1488
1712
  }