everything-dev 1.29.0 → 1.31.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 (85) hide show
  1. package/dist/api-contract.cjs +109 -49
  2. package/dist/api-contract.cjs.map +1 -1
  3. package/dist/api-contract.mjs +109 -49
  4. package/dist/api-contract.mjs.map +1 -1
  5. package/dist/cli/init.cjs +3 -2
  6. package/dist/cli/init.cjs.map +1 -1
  7. package/dist/cli/init.d.cts +1 -1
  8. package/dist/cli/init.d.cts.map +1 -1
  9. package/dist/cli/init.d.mts +1 -1
  10. package/dist/cli/init.d.mts.map +1 -1
  11. package/dist/cli/init.mjs +3 -2
  12. package/dist/cli/init.mjs.map +1 -1
  13. package/dist/cli/parse.cjs +7 -7
  14. package/dist/cli/parse.cjs.map +1 -1
  15. package/dist/cli/parse.mjs +7 -7
  16. package/dist/cli/parse.mjs.map +1 -1
  17. package/dist/cli/sync.cjs +3 -2
  18. package/dist/cli/sync.cjs.map +1 -1
  19. package/dist/cli/sync.mjs +3 -2
  20. package/dist/cli/sync.mjs.map +1 -1
  21. package/dist/cli/upgrade.cjs +1 -1
  22. package/dist/cli/upgrade.cjs.map +1 -1
  23. package/dist/cli/upgrade.mjs +1 -1
  24. package/dist/cli/upgrade.mjs.map +1 -1
  25. package/dist/cli.cjs +33 -2
  26. package/dist/cli.cjs.map +1 -1
  27. package/dist/cli.mjs +33 -2
  28. package/dist/cli.mjs.map +1 -1
  29. package/dist/config.cjs +2 -0
  30. package/dist/config.cjs.map +1 -1
  31. package/dist/config.d.cts +2 -2
  32. package/dist/config.d.mts +2 -2
  33. package/dist/config.mjs +1 -1
  34. package/dist/config.mjs.map +1 -1
  35. package/dist/contract.cjs +32 -1
  36. package/dist/contract.cjs.map +1 -1
  37. package/dist/contract.d.cts +82 -3
  38. package/dist/contract.d.cts.map +1 -1
  39. package/dist/contract.d.mts +82 -3
  40. package/dist/contract.d.mts.map +1 -1
  41. package/dist/contract.meta.cjs +18 -1
  42. package/dist/contract.meta.cjs.map +1 -1
  43. package/dist/contract.meta.d.cts +33 -0
  44. package/dist/contract.meta.d.mts +33 -0
  45. package/dist/contract.meta.mjs +18 -1
  46. package/dist/contract.meta.mjs.map +1 -1
  47. package/dist/contract.mjs +31 -2
  48. package/dist/contract.mjs.map +1 -1
  49. package/dist/index.cjs +7 -0
  50. package/dist/index.d.cts +4 -4
  51. package/dist/index.d.mts +4 -4
  52. package/dist/index.mjs +4 -4
  53. package/dist/merge.cjs +1 -0
  54. package/dist/merge.cjs.map +1 -1
  55. package/dist/merge.d.cts +5 -2
  56. package/dist/merge.d.cts.map +1 -1
  57. package/dist/merge.d.mts +5 -2
  58. package/dist/merge.d.mts.map +1 -1
  59. package/dist/merge.mjs +1 -0
  60. package/dist/merge.mjs.map +1 -1
  61. package/dist/mf.cjs +1 -0
  62. package/dist/mf.cjs.map +1 -1
  63. package/dist/mf.d.cts.map +1 -1
  64. package/dist/mf.d.mts.map +1 -1
  65. package/dist/mf.mjs +1 -0
  66. package/dist/mf.mjs.map +1 -1
  67. package/dist/plugin.cjs +243 -96
  68. package/dist/plugin.cjs.map +1 -1
  69. package/dist/plugin.d.cts +44 -1
  70. package/dist/plugin.d.mts +44 -1
  71. package/dist/plugin.mjs +243 -96
  72. package/dist/plugin.mjs.map +1 -1
  73. package/dist/types.cjs +14 -1
  74. package/dist/types.cjs.map +1 -1
  75. package/dist/types.d.cts +24 -1
  76. package/dist/types.d.cts.map +1 -1
  77. package/dist/types.d.mts +24 -1
  78. package/dist/types.d.mts.map +1 -1
  79. package/dist/types.mjs +12 -2
  80. package/dist/types.mjs.map +1 -1
  81. package/package.json +1 -1
  82. package/skills/extends-config/SKILL.md +19 -10
  83. package/skills/init-upgrade/SKILL.md +23 -16
  84. package/skills/publish-sync/SKILL.md +14 -0
  85. package/skills/super-app/SKILL.md +32 -24
package/dist/plugin.mjs CHANGED
@@ -196,7 +196,8 @@ async function generateCodeArtifacts(configDir, config, opts) {
196
196
  return {
197
197
  sidebarPath: join(configDir, "ui/src/lib/plugin-sidebar.gen.ts"),
198
198
  resolvedConfigPath: opts?.env ? join(configDir, ".bos/bos.resolved-config.json") : void 0,
199
- contractBridgePath: bridge.bridgePath
199
+ contractBridgePath: bridge.bridgePath,
200
+ contractStatus: bridge.status
200
201
  };
201
202
  }
202
203
  function extractPublishedUrl(output) {
@@ -247,8 +248,9 @@ async function buildEverythingDevQuietly(cwd) {
247
248
  async function fetchPublishedConfig(accountId, gatewayId) {
248
249
  try {
249
250
  return await fetchBosConfigFromFastKv(`bos://${accountId}/${gatewayId}`);
250
- } catch {
251
- return null;
251
+ } catch (error) {
252
+ if (error instanceof Error && error.message.startsWith("No config found")) return null;
253
+ throw error;
252
254
  }
253
255
  }
254
256
  function selectWorkspaceTargets(packages, bosConfig) {
@@ -609,20 +611,31 @@ var plugin_default = createPlugin({
609
611
  phase: "config",
610
612
  status: "running"
611
613
  });
614
+ const bosEnv = input.env ?? (process.env.BOS_ENV === "staging" ? "staging" : "production");
612
615
  const account = input.account ?? process.env.BOS_ACCOUNT;
613
616
  const domain = input.domain ?? process.env.BOS_GATEWAY;
614
617
  let config = null;
615
618
  let remoteConfig = null;
616
- if (account && domain) {
619
+ if (account && domain) try {
617
620
  remoteConfig = await fetchPublishedConfig(account, domain);
618
621
  if (remoteConfig) config = remoteConfig;
619
- else console.warn(`[Start] Failed to fetch remote config for ${account}/${domain}, falling back to local bos.config.json`);
622
+ else return {
623
+ status: "error",
624
+ url: "",
625
+ error: `No config found at bos://${account}/${domain}. Verify the account and gateway are correct and the config has been published.\nExpected URL: ${buildRegistryConfigUrl(account, domain)}`
626
+ };
627
+ } catch (error) {
628
+ return {
629
+ status: "error",
630
+ url: "",
631
+ error: `Failed to fetch config for bos://${account}/${domain}: ${error instanceof Error ? error.message : "Unknown error"}\nExpected URL: ${buildRegistryConfigUrl(account, domain)}`
632
+ };
620
633
  }
621
- if (!config) config = deps.bosConfig;
634
+ else config = deps.bosConfig;
622
635
  if (!config) return {
623
636
  status: "error",
624
637
  url: "",
625
- error: "No configuration found. Set BOS_ACCOUNT and BOS_GATEWAY environment variables, or provide a local bos.config.json."
638
+ error: "No configuration found. Provide --account and --gateway flags, or create a local bos.config.json."
626
639
  };
627
640
  if (account) config = {
628
641
  ...config,
@@ -633,7 +646,7 @@ var plugin_default = createPlugin({
633
646
  domain
634
647
  };
635
648
  const port = input.port ?? getHostDevelopmentPort(config.app.host.development);
636
- const isStaging = input.env === "staging";
649
+ const isStaging = bosEnv === "staging";
637
650
  const runtimePlugins = await buildRuntimePluginsForConfig(config, deps.configDir, "production");
638
651
  suppressWarnings();
639
652
  const runtimeConfig = buildRuntimeConfig(config, {
@@ -646,6 +659,8 @@ var plugin_default = createPlugin({
646
659
  });
647
660
  drainConfigWarnings();
648
661
  resumeWarnings();
662
+ if (isStaging && config.staging?.domain) runtimeConfig.domain = config.staging.domain;
663
+ if (isStaging) runtimeConfig.env = "staging";
649
664
  syncGeneratedInfra(deps.configDir, runtimeConfig);
650
665
  if (!existsSync(join(deps.configDir, ".env"))) {
651
666
  ensureEnvFile(deps.configDir);
@@ -666,12 +681,13 @@ var plugin_default = createPlugin({
666
681
  const productionEnv = {};
667
682
  const warnings = [];
668
683
  if (!process.env.CORS_ORIGIN && config.domain) {
669
- const defaultOrigin = `https://${config.domain}`;
684
+ const defaultOrigin = `https://${isStaging ? config.staging?.domain ?? config.domain : config.domain}`;
670
685
  productionEnv.CORS_ORIGIN = defaultOrigin;
671
686
  warnings.push(`CORS_ORIGIN defaulting to ${defaultOrigin}`);
672
687
  }
673
688
  const requiredSecrets = /* @__PURE__ */ new Set();
674
689
  const missingSecrets = [];
690
+ if (runtimeConfig.host.secrets) for (const s of runtimeConfig.host.secrets) requiredSecrets.add(s);
675
691
  if (runtimeConfig.auth?.secrets) for (const s of runtimeConfig.auth.secrets) requiredSecrets.add(s);
676
692
  if (runtimeConfig.api?.secrets) for (const s of runtimeConfig.api.secrets) requiredSecrets.add(s);
677
693
  for (const plugin of Object.values(runtimeConfig.plugins ?? {})) if (plugin.secrets) for (const s of plugin.secrets) requiredSecrets.add(s);
@@ -774,89 +790,120 @@ var plugin_default = createPlugin({
774
790
  registryUrl: "",
775
791
  error: "No bos.config.json found"
776
792
  };
777
- const account = deps.bosConfig.account;
778
- const gateway = deps.bosConfig.domain;
779
- if (!gateway) return {
793
+ const result = await publishToFastKv({
794
+ bosConfig: deps.bosConfig,
795
+ runtimeConfig: deps.runtimeConfig,
796
+ configDir: deps.configDir,
797
+ env: input.env,
798
+ build: input.deploy,
799
+ dryRun: input.dryRun,
800
+ packages: input.packages,
801
+ network: input.network,
802
+ privateKey: input.privateKey
803
+ });
804
+ if (result.publishConfig) {
805
+ const refreshed = await loadResolvedConfig({ cwd: deps.configDir });
806
+ if (refreshed?.config) {
807
+ deps.bosConfig = refreshed.config;
808
+ deps.runtimeConfig = refreshed.runtime;
809
+ }
810
+ }
811
+ return {
812
+ status: result.status,
813
+ registryUrl: result.registryUrl,
814
+ txHash: result.txHash,
815
+ error: result.error,
816
+ built: result.built,
817
+ skipped: result.skipped
818
+ };
819
+ }),
820
+ deploy: builder.deploy.handler(async ({ input }) => {
821
+ if (!deps.bosConfig) return {
780
822
  status: "error",
781
823
  registryUrl: "",
782
- error: "bos.config.json must define domain to publish"
824
+ redeployed: false,
825
+ error: "No bos.config.json found"
783
826
  };
784
- const network = input.network ?? getNetworkIdForAccount(account);
785
- const bosUrl = `bos://${account}/${gateway}`;
786
- const registryUrl = buildRegistryConfigUrlForNetwork(network, account, gateway);
787
- const targets = selectWorkspaceTargets(input.packages, deps.bosConfig);
788
- let publishConfig = deps.bosConfig;
789
- let built;
790
- let skipped;
791
- if (input.dryRun) return {
827
+ const result = await publishToFastKv({
828
+ bosConfig: deps.bosConfig,
829
+ runtimeConfig: deps.runtimeConfig,
830
+ configDir: deps.configDir,
831
+ env: input.env,
832
+ build: input.build,
833
+ dryRun: input.dryRun,
834
+ packages: input.packages,
835
+ network: input.network,
836
+ privateKey: input.privateKey
837
+ });
838
+ if (result.status === "error") return {
839
+ status: "error",
840
+ registryUrl: result.registryUrl,
841
+ txHash: result.txHash,
842
+ built: result.built,
843
+ skipped: result.skipped,
844
+ redeployed: false,
845
+ error: result.error
846
+ };
847
+ if (result.status === "dry-run") return {
792
848
  status: "dry-run",
793
- registryUrl,
794
- built,
795
- skipped
849
+ registryUrl: result.registryUrl,
850
+ built: result.built,
851
+ skipped: result.skipped,
852
+ redeployed: false
796
853
  };
797
- if (input.deploy) {
798
- await generateCodeArtifacts(deps.configDir, deps.bosConfig, {
799
- env: "production",
800
- runtimeConfig: deps.runtimeConfig ?? void 0
801
- });
802
- const result = await buildWorkspaceTargets({
803
- configDir: deps.configDir,
804
- bosConfig: deps.bosConfig,
805
- runtimeConfig: deps.runtimeConfig,
806
- targets,
807
- deploy: true
808
- });
809
- built = result.built;
810
- skipped = result.skipped;
854
+ if (result.publishConfig) {
811
855
  const refreshed = await loadResolvedConfig({ cwd: deps.configDir });
812
856
  if (refreshed?.config) {
813
857
  deps.bosConfig = refreshed.config;
814
858
  deps.runtimeConfig = refreshed.runtime;
815
- publishConfig = refreshed.config;
816
859
  }
817
860
  }
818
- const registryEntries = { [`apps/${account}/${gateway}/bos.config.json`]: JSON.stringify(publishConfig) };
819
- const payload = JSON.stringify(registryEntries);
820
- const argsBase64 = Buffer.from(payload).toString("base64");
821
- const privateKey = input.privateKey || process.env.NEAR_PRIVATE_KEY || process.env.BOS_NEAR_PRIVATE_KEY;
822
- try {
823
- await Effect.runPromise(ensureNearCli);
824
- let txHash;
861
+ let redeployed = false;
862
+ let service;
863
+ if (process.env.RAILWAY_TOKEN) {
864
+ const railwayService = input.service ?? deps.bosConfig.ci?.railway?.service;
865
+ if (!railwayService) return {
866
+ status: "published",
867
+ registryUrl: result.registryUrl,
868
+ txHash: result.txHash,
869
+ built: result.built,
870
+ skipped: result.skipped,
871
+ redeployed: false,
872
+ error: "Config published but Railway redeploy failed: ci.railway.service is not configured in bos.config.json"
873
+ };
874
+ service = railwayService;
825
875
  try {
826
- txHash = (await Effect.runPromise(executeTransaction({
827
- account,
828
- contract: getRegistryNamespaceForNetwork(network),
829
- method: "__fastdata_kv",
830
- argsBase64,
831
- network,
832
- privateKey,
833
- gas: "300Tgas",
834
- deposit: "0NEAR"
835
- }))).txHash;
876
+ await run("railway", [
877
+ "redeploy",
878
+ "--service",
879
+ railwayService,
880
+ "--yes"
881
+ ]);
882
+ redeployed = true;
836
883
  } catch (error) {
837
- txHash = extractTransactionHash(error);
838
- if (!txHash) throw error;
839
- try {
840
- const verifiedConfig = await fetchBosConfigFromFastKv(bosUrl);
841
- if (JSON.stringify(verifiedConfig) !== JSON.stringify(publishConfig)) throw error;
842
- } catch {}
884
+ const message = error instanceof Error ? error.message : String(error);
885
+ const railError = message.includes("not found") || message.includes("ENOENT") ? "Railway CLI not found. Install it: npm i -g @railway/cli" : `Railway redeploy failed: ${message}`;
886
+ return {
887
+ status: "published",
888
+ registryUrl: result.registryUrl,
889
+ txHash: result.txHash,
890
+ built: result.built,
891
+ skipped: result.skipped,
892
+ redeployed: false,
893
+ service,
894
+ error: `Config published but ${railError}`
895
+ };
843
896
  }
844
- return {
845
- status: "published",
846
- registryUrl,
847
- txHash,
848
- built,
849
- skipped
850
- };
851
- } catch (error) {
852
- return {
853
- status: "error",
854
- registryUrl,
855
- error: error instanceof Error ? error.message : "Unknown error",
856
- built,
857
- skipped
858
- };
859
897
  }
898
+ return {
899
+ status: "deployed",
900
+ registryUrl: result.registryUrl,
901
+ txHash: result.txHash,
902
+ built: result.built,
903
+ skipped: result.skipped,
904
+ redeployed,
905
+ service
906
+ };
860
907
  }),
861
908
  keyPublish: builder.keyPublish.handler(async ({ input }) => {
862
909
  if (!deps.bosConfig) return {
@@ -1132,18 +1179,16 @@ var plugin_default = createPlugin({
1132
1179
  const pluginEntries = Object.entries(refreshed.runtime.plugins ?? {});
1133
1180
  const fetched = [];
1134
1181
  const skipped = [];
1135
- if (refreshed.runtime.api.source !== "local") fetched.push(refreshed.runtime.api.url);
1182
+ const hasLocalApiWorkspace = existsSync(join(projectDir, "api", "src"));
1183
+ if (refreshed.runtime.api.source !== "local") fetched.push(`api (${refreshed.runtime.api.url})`);
1136
1184
  else skipped.push("api (local)");
1137
- if (refreshed.runtime.auth) if (refreshed.runtime.auth.source !== "local") fetched.push(refreshed.runtime.auth.url);
1185
+ if (refreshed.runtime.auth) if (refreshed.runtime.auth.source !== "local") fetched.push(`auth (${refreshed.runtime.auth.url})`);
1138
1186
  else skipped.push("auth (local)");
1139
- for (const [key, plugin] of pluginEntries) if (plugin.url && plugin.source !== "local") fetched.push(plugin.url);
1187
+ for (const [key, plugin] of pluginEntries) if (plugin.url && plugin.source !== "local") fetched.push(`${key} (${plugin.url})`);
1140
1188
  else if (plugin.localPath) skipped.push(`${key} (local)`);
1141
- const generated = [
1142
- "ui/src/lib/api-types.gen.ts",
1143
- "ui/src/lib/auth-types.gen.ts",
1144
- "api/src/lib/plugins-types.gen.ts",
1145
- "api/src/lib/auth-types.gen.ts"
1146
- ];
1189
+ else skipped.push(`${key} (no URL resolved)`);
1190
+ const generated = ["ui/src/lib/api-types.gen.ts", "ui/src/lib/auth-types.gen.ts"];
1191
+ if (hasLocalApiWorkspace) generated.push("api/src/lib/plugins-types.gen.ts", "api/src/lib/auth-types.gen.ts");
1147
1192
  if (existsSync(join(projectDir, "host", "src"))) generated.push("host/src/lib/auth-types.gen.ts");
1148
1193
  return {
1149
1194
  status: "success",
@@ -1154,21 +1199,29 @@ var plugin_default = createPlugin({
1154
1199
  source: refreshed.runtime.api.source
1155
1200
  };
1156
1201
  }
1157
- await generateCodeArtifacts(projectDir, refreshed.config, { runtimeConfig: refreshed.runtime });
1158
- const generated = [
1159
- "ui/src/lib/plugin-sidebar.gen.ts",
1160
- "ui/src/lib/api-types.gen.ts",
1161
- "api/src/lib/plugins-types.gen.ts",
1162
- "api/src/lib/auth-types.gen.ts"
1163
- ];
1202
+ const artifacts = await generateCodeArtifacts(projectDir, refreshed.config, { runtimeConfig: refreshed.runtime });
1203
+ const hasLocalApiWorkspace = existsSync(join(projectDir, "api", "src"));
1204
+ const generated = ["ui/src/lib/plugin-sidebar.gen.ts", "ui/src/lib/api-types.gen.ts"];
1205
+ if (hasLocalApiWorkspace) generated.push("api/src/lib/plugins-types.gen.ts", "api/src/lib/auth-types.gen.ts");
1164
1206
  if (refreshed.runtime.auth && (refreshed.runtime.auth.source !== "local" || refreshed.runtime.auth.localPath)) generated.push("ui/src/lib/auth-types.gen.ts");
1165
1207
  if (existsSync(join(projectDir, "host", "src"))) generated.push("host/src/lib/auth-types.gen.ts");
1208
+ const contractStatus = artifacts?.contractStatus ?? [];
1209
+ const fetched = [];
1210
+ const skipped = [];
1211
+ const failed = [];
1212
+ for (const entry of contractStatus) if (entry.source === "remote") fetched.push(entry.url ? `${entry.key} (${entry.url})` : entry.key);
1213
+ else if (entry.source === "local") skipped.push(`${entry.key} (local)`);
1214
+ else if (entry.source === "skipped") skipped.push(`${entry.key} (no URL resolved)`);
1215
+ else if (entry.source === "failed") {
1216
+ const detail = entry.error ? `: ${entry.error}` : "";
1217
+ failed.push(`${entry.key}${detail}`);
1218
+ }
1166
1219
  return {
1167
1220
  status: "success",
1168
1221
  generated,
1169
- fetched: refreshed.runtime.api.source === "remote" ? [refreshed.runtime.api.url] : [],
1170
- skipped: refreshed.runtime.api.source === "local" ? ["api (local)"] : [],
1171
- failed: [],
1222
+ fetched,
1223
+ skipped,
1224
+ failed,
1172
1225
  source: refreshed.runtime.api.source
1173
1226
  };
1174
1227
  } catch (error) {
@@ -1203,6 +1256,100 @@ var plugin_default = createPlugin({
1203
1256
  })
1204
1257
  })
1205
1258
  });
1259
+ async function publishToFastKv(input) {
1260
+ const { env, dryRun, configDir } = input;
1261
+ let bosConfig = input.bosConfig;
1262
+ const runtimeConfig = input.runtimeConfig;
1263
+ const isStaging = env === "staging";
1264
+ const account = bosConfig.account;
1265
+ const gateway = isStaging ? bosConfig.staging?.domain ?? bosConfig.domain : bosConfig.domain;
1266
+ if (!gateway) return {
1267
+ status: "error",
1268
+ registryUrl: "",
1269
+ error: "bos.config.json must define domain to publish"
1270
+ };
1271
+ const network = input.network ?? getNetworkIdForAccount(account);
1272
+ const registryUrl = buildRegistryConfigUrlForNetwork(network, account, gateway);
1273
+ const targets = selectWorkspaceTargets(input.packages, bosConfig);
1274
+ let publishConfig = isStaging ? {
1275
+ ...bosConfig,
1276
+ domain: gateway
1277
+ } : bosConfig;
1278
+ let built;
1279
+ let skipped;
1280
+ if (dryRun) return {
1281
+ status: "dry-run",
1282
+ registryUrl,
1283
+ built,
1284
+ skipped
1285
+ };
1286
+ if (input.build) {
1287
+ await generateCodeArtifacts(configDir, bosConfig, {
1288
+ env: "production",
1289
+ runtimeConfig: runtimeConfig ?? void 0
1290
+ });
1291
+ const result = await buildWorkspaceTargets({
1292
+ configDir,
1293
+ bosConfig,
1294
+ runtimeConfig,
1295
+ targets,
1296
+ deploy: true
1297
+ });
1298
+ built = result.built;
1299
+ skipped = result.skipped;
1300
+ const refreshed = await loadResolvedConfig({ cwd: configDir });
1301
+ if (refreshed?.config) {
1302
+ bosConfig = refreshed.config;
1303
+ publishConfig = isStaging ? {
1304
+ ...refreshed.config,
1305
+ domain: gateway
1306
+ } : refreshed.config;
1307
+ }
1308
+ }
1309
+ const registryEntries = { [`apps/${account}/${gateway}/bos.config.json`]: JSON.stringify(publishConfig) };
1310
+ const payload = JSON.stringify(registryEntries);
1311
+ const argsBase64 = Buffer.from(payload).toString("base64");
1312
+ const privateKey = input.privateKey || process.env.NEAR_PRIVATE_KEY || process.env.BOS_NEAR_PRIVATE_KEY;
1313
+ try {
1314
+ await Effect.runPromise(ensureNearCli);
1315
+ let txHash;
1316
+ try {
1317
+ txHash = (await Effect.runPromise(executeTransaction({
1318
+ account,
1319
+ contract: getRegistryNamespaceForNetwork(network),
1320
+ method: "__fastdata_kv",
1321
+ argsBase64,
1322
+ network,
1323
+ privateKey,
1324
+ gas: "300Tgas",
1325
+ deposit: "0NEAR"
1326
+ }))).txHash;
1327
+ } catch (error) {
1328
+ txHash = extractTransactionHash(error);
1329
+ if (!txHash) throw error;
1330
+ try {
1331
+ const verifiedConfig = await fetchBosConfigFromFastKv(`bos://${account}/${gateway}`);
1332
+ if (JSON.stringify(verifiedConfig) !== JSON.stringify(publishConfig)) throw error;
1333
+ } catch {}
1334
+ }
1335
+ return {
1336
+ status: "published",
1337
+ registryUrl,
1338
+ txHash,
1339
+ built,
1340
+ skipped,
1341
+ publishConfig
1342
+ };
1343
+ } catch (error) {
1344
+ return {
1345
+ status: "error",
1346
+ registryUrl,
1347
+ error: error instanceof Error ? error.message : "Unknown error",
1348
+ built,
1349
+ skipped
1350
+ };
1351
+ }
1352
+ }
1206
1353
  function extractTransactionHash(error) {
1207
1354
  return (error instanceof Error ? error.message : String(error)).match(/Transaction ID:\s*([A-Za-z0-9]+)/i)?.[1];
1208
1355
  }