{"version":3,"file":"update-CJUfGCxs.mjs","names":[],"sources":["../src/update.ts"],"sourcesContent":["import { spawnSync } from 'node:child_process'\nimport type { Readable, Writable } from 'node:stream'\nimport { createInterface } from 'node:readline/promises'\nimport { stdin, stdout } from 'node:process'\nimport { PACKAGE_INFO, PACKAGE_VERSION } from './version.js'\n\nconst DEFAULT_REGISTRY_URL = 'https://registry.npmjs.org'\nconst DEFAULT_TIMEOUT_MS = 3000\n\nexport interface UpdateCheckOptions {\n  packageName?: string\n  currentVersion?: string\n  registryUrl?: string\n  timeoutMs?: number\n  fetchImpl?: typeof fetch\n}\n\nexport interface UpdateCheckResult {\n  packageName: string\n  currentVersion: string\n  latestVersion?: string\n  updateAvailable: boolean\n  updateCommand: string\n  error?: string\n}\n\nexport interface NpmInvocation {\n  command: string\n  args: string[]\n  displayCommand: string\n}\n\nexport interface UpdatePromptOptions extends UpdateCheckOptions {\n  input?: NodeJS.ReadStream & Readable\n  output?: NodeJS.WriteStream & Writable\n  env?: NodeJS.ProcessEnv\n}\n\nexport function compareSemverVersions(a: string, b: string): number {\n  const left = parseSemverCore(a)\n  const right = parseSemverCore(b)\n  for (let i = 0; i < 3; i += 1) {\n    if (left[i] > right[i]) return 1\n    if (left[i] < right[i]) return -1\n  }\n  return 0\n}\n\nexport function resolveUpdateRegistryUrl(env: NodeJS.ProcessEnv = process.env): string {\n  return env['CHAIN_INSIGHTS_NPM_REGISTRY_URL']?.trim() || DEFAULT_REGISTRY_URL\n}\n\nexport function buildPackageLatestUrl(packageName: string, registryUrl = DEFAULT_REGISTRY_URL): string {\n  const base = registryUrl.endsWith('/') ? registryUrl.slice(0, -1) : registryUrl\n  return `${base}/${encodeURIComponent(packageName)}/latest`\n}\n\nexport function resolveNpmUpdateInvocation(\n  packageName = PACKAGE_INFO.name,\n  env: NodeJS.ProcessEnv = process.env,\n): NpmInvocation {\n  const packageSpec = `${packageName}@latest`\n  const displayCommand = `npm install -g ${packageSpec}`\n  const npmExecPath = env['npm_execpath']?.trim()\n  if (npmExecPath) {\n    return {\n      command: process.execPath,\n      args: [npmExecPath, 'install', '-g', packageSpec],\n      displayCommand,\n    }\n  }\n  return {\n    command: process.platform === 'win32' ? 'npm.cmd' : 'npm',\n    args: ['install', '-g', packageSpec],\n    displayCommand,\n  }\n}\n\nexport async function fetchLatestPackageVersion(options: UpdateCheckOptions = {}): Promise<string> {\n  const packageName = options.packageName ?? PACKAGE_INFO.name\n  const registryUrl = options.registryUrl ?? resolveUpdateRegistryUrl()\n  const fetchImpl = options.fetchImpl ?? fetch\n  const controller = new AbortController()\n  const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? DEFAULT_TIMEOUT_MS)\n\n  try {\n    const response = await fetchImpl(buildPackageLatestUrl(packageName, registryUrl), {\n      headers: {\n        accept: 'application/json',\n        'user-agent': `chain-insights/${PACKAGE_VERSION}`,\n      },\n      signal: controller.signal,\n    })\n    if (!response.ok) {\n      throw new Error(`npmjs registry returned ${response.status}`)\n    }\n    const body = await response.json() as { version?: unknown }\n    if (typeof body.version !== 'string' || !body.version.trim()) {\n      throw new Error('npmjs registry response did not include a version')\n    }\n    return body.version.trim()\n  } finally {\n    clearTimeout(timeout)\n  }\n}\n\nexport async function checkForUpdate(options: UpdateCheckOptions = {}): Promise<UpdateCheckResult> {\n  const packageName = options.packageName ?? PACKAGE_INFO.name\n  const currentVersion = options.currentVersion ?? PACKAGE_VERSION\n  const updateCommand = resolveNpmUpdateInvocation(packageName).displayCommand\n  try {\n    const latestVersion = await fetchLatestPackageVersion(options)\n    return {\n      packageName,\n      currentVersion,\n      latestVersion,\n      updateAvailable: compareSemverVersions(latestVersion, currentVersion) > 0,\n      updateCommand,\n    }\n  } catch (err) {\n    return {\n      packageName,\n      currentVersion,\n      updateAvailable: false,\n      updateCommand,\n      error: (err as Error).message,\n    }\n  }\n}\n\nexport function runPackageUpdate(packageName = PACKAGE_INFO.name): void {\n  const invocation = resolveNpmUpdateInvocation(packageName)\n  const result = spawnSync(invocation.command, invocation.args, { stdio: 'inherit' })\n  if (result.error) {\n    throw result.error\n  }\n  if (result.status !== 0) {\n    const detail = result.signal ? `signal ${result.signal}` : `exit code ${result.status ?? 'unknown'}`\n    throw new Error(`Update failed with ${detail}`)\n  }\n}\n\nexport function shouldPromptForUpdate(options: UpdatePromptOptions = {}): boolean {\n  const env = options.env ?? process.env\n  if (env['CHAIN_INSIGHTS_SKIP_UPDATE_CHECK'] === '1') return false\n  if (env['CI'] === 'true') return false\n  const input = options.input ?? stdin\n  const output = options.output ?? stdout\n  return input.isTTY === true && output.isTTY === true\n}\n\nexport async function maybePromptForUpdate(options: UpdatePromptOptions = {}): Promise<void> {\n  if (!shouldPromptForUpdate(options)) return\n\n  const check = await checkForUpdate(options)\n  if (check.error || !check.updateAvailable || !check.latestVersion) return\n\n  const output = options.output ?? stdout\n  output.write(`\\nChain Insights ${check.latestVersion} is available (current ${check.currentVersion}).\\n`)\n  output.write(`Update command: ${check.updateCommand}\\n`)\n\n  const rl = createInterface({\n    input: options.input ?? stdin,\n    output,\n  })\n  try {\n    const answer = await rl.question('Update now? [Y/n] ')\n    if (!answer.trim() || answer.trim().toLowerCase().startsWith('y')) {\n      try {\n        runPackageUpdate(check.packageName)\n      } catch (err) {\n        output.write(`Update failed: ${(err as Error).message}\\n`)\n        output.write('Workspace initialization is complete. Run `cia update` when ready.\\n')\n      }\n    } else {\n      output.write('Skipped update. Run `cia update` when ready.\\n')\n    }\n  } finally {\n    rl.close()\n  }\n}\n\nfunction parseSemverCore(version: string): [number, number, number] {\n  const match = /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:[-+].*)?$/.exec(version)\n  if (!match) throw new Error(`Invalid semver version: ${version}`)\n  return [Number(match[1]), Number(match[2]), Number(match[3])]\n}\n"],"mappings":"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"}