{"version":3,"file":"publish.cjs","names":["process","fetchBosConfigFromFastKv","getNetworkIdForAccount","buildRegistryConfigUrlForNetwork","selectWorkspaceTargets","resolveNearSigningMode","Effect","ensureNearCli","generateCodeArtifacts","buildWorkspaceTargets","colors","icons","padRight","loadResolvedConfig","executeTransaction","getRegistryNamespaceForNetwork"],"sources":["../src/publish.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport process from \"node:process\";\nimport { Effect } from \"effect\";\nimport { buildWorkspaceTargets, selectWorkspaceTargets } from \"./build\";\nimport { generateCodeArtifacts } from \"./code-artifacts\";\nimport { loadResolvedConfig } from \"./config\";\nimport type { WorkspaceDeployResult } from \"./contract\";\nimport {\n  buildRegistryConfigUrlForNetwork,\n  fetchBosConfigFromFastKv,\n  getRegistryNamespaceForNetwork,\n} from \"./fastkv\";\nimport { ensureNearCli, executeTransaction, resolveNearSigningMode } from \"./near-cli\";\nimport { getNetworkIdForAccount } from \"./network\";\nimport type { BosConfig, BosConfigInput, RuntimeConfig } from \"./types\";\nimport { padRight } from \"./utils/string\";\nimport { colors, icons } from \"./utils/theme\";\n\nfunction sleep(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function extractPublishedUrl(output: string): string | null {\n  const deployMatch = output.match(/🚀.*Deployed:\\s*(https?:\\S+)/);\n  if (deployMatch) return deployMatch[1];\n  const match = output.match(/https?:\\/\\/[^\\s\"'<>]+/g);\n  if (!match || match.length === 0) return null;\n  return match[match.length - 1] ?? null;\n}\n\nexport async function waitForPublishedConfig(opts: {\n  account: string;\n  gateway: string;\n  publishConfig: BosConfigInput;\n  timeoutMs?: number;\n  intervalMs?: number;\n}): Promise<void> {\n  const envTimeoutMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_TIMEOUT_MS);\n  const envIntervalMs = Number(process.env.BOS_PUBLISH_CONFIRMATION_INTERVAL_MS);\n  const timeoutMs =\n    opts.timeoutMs ?? (Number.isFinite(envTimeoutMs) ? envTimeoutMs : undefined) ?? 120_000;\n  const intervalMs =\n    opts.intervalMs ?? (Number.isFinite(envIntervalMs) ? envIntervalMs : undefined) ?? 3_000;\n  const startedAt = Date.now();\n  let lastError: unknown;\n\n  while (Date.now() - startedAt < timeoutMs) {\n    try {\n      const verifiedConfig = await fetchBosConfigFromFastKv<BosConfigInput>(\n        `bos://${opts.account}/${opts.gateway}`,\n      );\n\n      if (JSON.stringify(verifiedConfig) === JSON.stringify(opts.publishConfig)) {\n        return;\n      }\n    } catch (error) {\n      lastError = error;\n    }\n\n    await sleep(intervalMs);\n  }\n\n  const reason = lastError instanceof Error ? ` Last error: ${lastError.message}` : \"\";\n  throw new Error(\n    `Timed out waiting for publish confirmation at bos://${opts.account}/${opts.gateway}.${reason}`,\n  );\n}\n\ninterface PublishToFastKvInput {\n  bosConfig: BosConfig;\n  runtimeConfig: RuntimeConfig | null;\n  configDir: string;\n  env: \"production\" | \"staging\";\n  build: boolean;\n  dryRun: boolean;\n  verbose: boolean;\n  packages: string;\n  network?: \"mainnet\" | \"testnet\";\n  privateKey?: string;\n}\n\ninterface PublishToFastKvResult {\n  status: \"published\" | \"error\" | \"dry-run\";\n  registryUrl: string;\n  txHash?: string;\n  built?: string[];\n  skipped?: string[];\n  error?: string;\n  publishConfig?: BosConfigInput;\n  deployResults?: WorkspaceDeployResult[];\n}\n\nexport async function publishToFastKv(input: PublishToFastKvInput): Promise<PublishToFastKvResult> {\n  const { env, dryRun, configDir } = input;\n  let bosConfig = input.bosConfig;\n  const runtimeConfig = input.runtimeConfig;\n\n  const isStaging = env === \"staging\";\n  const account = bosConfig.account;\n  const gateway = isStaging ? (bosConfig.staging?.domain ?? bosConfig.domain) : bosConfig.domain;\n  if (!gateway) {\n    return {\n      status: \"error\",\n      registryUrl: \"\",\n      error: \"bos.config.json must define domain to publish\",\n    };\n  }\n\n  const network = input.network ?? getNetworkIdForAccount(account);\n  const registryUrl = buildRegistryConfigUrlForNetwork(network, account, gateway);\n  const targets = selectWorkspaceTargets(input.packages, bosConfig);\n\n  let built: string[] | undefined;\n  let skipped: string[] | undefined;\n  let deployResults: WorkspaceDeployResult[] | undefined;\n\n  if (dryRun) {\n    return { status: \"dry-run\", registryUrl, built, skipped };\n  }\n\n  const privateKey =\n    input.privateKey || process.env.NEAR_PRIVATE_KEY || process.env.BOS_NEAR_PRIVATE_KEY;\n  let signingMode: ReturnType<typeof resolveNearSigningMode>;\n  try {\n    signingMode = resolveNearSigningMode(privateKey);\n  } catch (error) {\n    return {\n      status: \"error\" as const,\n      registryUrl,\n      error: error instanceof Error ? error.message : \"Unknown error\",\n    };\n  }\n\n  if (input.build) {\n    console.log(\"  Ensuring NEAR CLI...\");\n    await Effect.runPromise(ensureNearCli);\n    console.log(\"  NEAR CLI ready\");\n\n    await generateCodeArtifacts(configDir, bosConfig, {\n      env: \"production\",\n      runtimeConfig: runtimeConfig ?? undefined,\n    });\n\n    const result = await buildWorkspaceTargets({\n      configDir,\n      bosConfig,\n      runtimeConfig,\n      targets,\n      deploy: true,\n      verbose: input.verbose,\n    });\n    built = result.built;\n    skipped = result.skipped;\n    deployResults = result.deployResults;\n\n    if (deployResults) {\n      const failures = deployResults.filter((r) => !r.success);\n      if (failures.length > 0) {\n        const total = deployResults.length;\n        console.log();\n        console.log(\n          colors.error(\n            `  ${icons.err} Deploy failed — ${failures.length} of ${total} workspace${total > 1 ? \"s\" : \"\"} failed`,\n          ),\n        );\n        console.log();\n        for (const f of failures) {\n          const errorLine = (f.error ?? \"Failed\").split(\"\\n\")[0];\n          console.log(`    ${colors.error(icons.err)} ${padRight(f.key, 28)} ${errorLine}`);\n        }\n        console.log();\n        if (!input.verbose) {\n          console.log(colors.dim(\"  Run with --verbose for full build output.\"));\n          console.log();\n        }\n        return {\n          status: \"error\" as const,\n          registryUrl,\n          built,\n          skipped,\n          deployResults,\n          error: `${failures.length} of ${total} workspaces failed to deploy`,\n        };\n      }\n    }\n\n    const refreshed = await loadResolvedConfig({ cwd: configDir });\n    if (!refreshed?.config) {\n      return {\n        status: \"error\",\n        registryUrl,\n        built,\n        skipped,\n        deployResults,\n        error: \"Failed to reload bos.config.json after build\",\n      };\n    }\n\n    bosConfig = refreshed.config;\n  }\n\n  const rawConfigPath = join(configDir, \"bos.config.json\");\n  const rawConfig = JSON.parse(readFileSync(rawConfigPath, \"utf-8\")) as BosConfigInput;\n  const publishPayload: BosConfigInput = isStaging ? { ...rawConfig, domain: gateway } : rawConfig;\n\n  const registryEntries: Record<string, string> = {\n    [`apps/${account}/${gateway}/bos.config.json`]: JSON.stringify(publishPayload),\n  };\n\n  const payload = JSON.stringify(registryEntries);\n  const argsBase64 = Buffer.from(payload).toString(\"base64\");\n\n  console.log();\n  console.log(\"  Publishing to:\");\n  console.log(`    ${colors.cyan(registryUrl)}`);\n\n  try {\n    let txHash: string | undefined;\n\n    console.log(`  Submitting transaction on ${network}...`);\n\n    try {\n      const tx = await Effect.runPromise(\n        executeTransaction(\n          {\n            account,\n            contract: getRegistryNamespaceForNetwork(network),\n            method: \"__fastdata_kv\",\n            argsBase64,\n            network,\n            privateKey: signingMode._tag === \"privateKey\" ? signingMode.privateKey : undefined,\n            gas: \"300Tgas\",\n            deposit: \"0NEAR\",\n            verbose: input.verbose,\n          },\n          signingMode,\n        ),\n      );\n      txHash = tx.txHash;\n      if (txHash && !tx.output?.includes(\"CodeDoesNotExist\")) {\n        console.log(`  Transaction submitted: ${colors.dim(txHash)}`);\n      }\n    } catch (error) {\n      console.log(colors.dim(\"  Transaction reported an error — verifying publish...\"));\n      try {\n        await waitForPublishedConfig({\n          account,\n          gateway,\n          publishConfig: publishPayload,\n          timeoutMs: 30_000,\n          intervalMs: 2_000,\n        });\n        txHash = extractTransactionHash(error);\n      } catch {\n        throw error;\n      }\n    }\n\n    console.log(\"  Waiting for publish confirmation...\");\n    await waitForPublishedConfig({\n      account,\n      gateway,\n      publishConfig: publishPayload,\n    });\n\n    return {\n      status: \"published\",\n      registryUrl,\n      txHash,\n      built,\n      skipped,\n      deployResults,\n      publishConfig: publishPayload,\n    };\n  } catch (error) {\n    return {\n      status: \"error\",\n      registryUrl,\n      error: formatNearError(error),\n      built,\n      skipped,\n      deployResults,\n    };\n  }\n}\n\nfunction formatNearError(error: unknown): string {\n  const message = error instanceof Error ? error.message : String(error);\n\n  if (message.includes(\"does not have enough allowance\")) {\n    return (\n      \"The publish access key has insufficient allowance to cover this transaction.\\n\" +\n      \"  Regenerate your key with a higher allowance:\\n\" +\n      \"    bos key generate\\n\" +\n      `  Original: ${message}`\n    );\n  }\n\n  if (message.includes(\"exceeded gas\") || message.includes(\"GasLimitExceeded\")) {\n    return `Transaction exceeded gas limit.\\n  Original: ${message}`;\n  }\n\n  if (message.includes(\"timeout\") || message.includes(\"Timeout\")) {\n    return `Transaction timed out. Check NEAR network status.\\n  Original: ${message}`;\n  }\n\n  return message;\n}\n\nfunction extractTransactionHash(error: unknown) {\n  const message = error instanceof Error ? error.message : String(error);\n  const match = message.match(/Transaction ID:\\s*([A-Za-z0-9]+)/i);\n  return match?.[1];\n}\n"],"mappings":"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"}