{"version":3,"file":"upgrade-source.cjs","names":["readAuthoredConfigInput","getExtendsRef","walkExtendsChain","resolvePlatformManifest","parseBosRef","fetchParentConfig"],"sources":["../../../src/services/scaffold/upgrade-source.ts"],"sourcesContent":["import { readAuthoredConfigInput } from \"../../config\";\nimport { getExtendsRef, parseBosRef } from \"../../utils/bos-ref\";\nimport {\n  type ResolvedPlatformManifest,\n  type ResolvePlatformManifestOptions,\n  resolvePlatformManifest,\n  walkExtendsChain,\n} from \"../platform/manifest\";\nimport { fetchParentConfig } from \"./init\";\n\nexport interface ExtendedRootSource {\n  catalog: Record<string, string>;\n  repository?: string;\n  extendsChain: string[];\n  /** The resolved platform release manifest when one publishes (ADR 0034). */\n  platform: ResolvedPlatformManifest;\n}\n\n/** Injectable registry I/O (the test seam — mirrors the real FastKV layout). */\nexport type ExtendedRootSourceOptions = Pick<\n  ResolvePlatformManifestOptions,\n  \"fetchManifest\" | \"fetchParent\" | \"cacheRead\" | \"cacheWrite\" | \"now\" | \"cacheTtlMs\"\n>;\n\nexport async function readExtendedRootSource(\n  projectDir: string,\n  options: ExtendedRootSourceOptions = {},\n): Promise<ExtendedRootSource> {\n  const localConfig = (await readAuthoredConfigInput(projectDir)) as Record<string, unknown> | null;\n  if (!localConfig) {\n    throw new Error(\"No authored config found in current directory\");\n  }\n\n  const extendsRef = getExtendsRef(localConfig);\n  if (!extendsRef?.startsWith(\"bos://\")) {\n    throw new Error(\n      \"No bos:// extends field found in the authored config — upgrade moves children that extend a deployed runtime\",\n    );\n  }\n\n  const walk = await walkExtendsChain({\n    localConfig,\n    localRepository:\n      typeof localConfig.repository === \"string\" ? localConfig.repository : undefined,\n    ...(options.fetchParent ? { fetchParent: options.fetchParent } : {}),\n  });\n  const extendsChain = walk.chain.map((node) => `bos://${node.account}/${node.gateway}`);\n  if (walk.circularAt) {\n    throw new Error(`Circular extends detected while resolving upgrade source: ${walk.circularAt}`);\n  }\n\n  // ADR 0034: the platform release manifest is the single upgrade authority —\n  // its catalog and repository metadata. The upgrade-of-record resolves it\n  // *ignoring the child's own platform pin*: the pin freezes everyday\n  // resolution (sync, init, runtime); this is the pathway that moves the pin\n  // to the latest chain release. No manifest anywhere → fail loud.\n  const platform = await resolvePlatformManifest({\n    configDir: projectDir,\n    localConfig: { ...localConfig, platform: undefined },\n    ...(options.fetchManifest ? { fetchManifest: options.fetchManifest } : {}),\n    ...(options.fetchParent ? { fetchParent: options.fetchParent } : {}),\n    ...(options.cacheRead ? { cacheRead: options.cacheRead } : {}),\n    ...(options.cacheWrite ? { cacheWrite: options.cacheWrite } : {}),\n    ...(options.now ? { now: options.now } : {}),\n    ...(options.cacheTtlMs !== undefined ? { cacheTtlMs: options.cacheTtlMs } : {}),\n  });\n  if (!platform) {\n    throw new Error(\n      `No platform release manifest resolves in the extends chain (${extendsChain.join(\" → \")}) — publish the platform manifest (bos publish on the parent) or run \\`bos platform manifest --check\\` to diagnose`,\n    );\n  }\n\n  return {\n    catalog: platform.manifest.catalog,\n    repository: walk.repository,\n    extendsChain,\n    platform,\n  };\n}\n\nexport async function loadParentPluginOptions(projectDir: string): Promise<{\n  localConfig: Record<string, unknown>;\n  parentPlugins: Record<string, unknown>;\n  newPluginKeys: string[];\n} | null> {\n  const localConfig = (await readAuthoredConfigInput(projectDir)) as Record<string, unknown> | null;\n  if (!localConfig) {\n    return null;\n  }\n  const extendsRef = getExtendsRef(localConfig);\n  if (!extendsRef?.startsWith(\"bos://\")) {\n    return null;\n  }\n\n  const parsed = parseBosRef(extendsRef);\n  if (!parsed) {\n    return null;\n  }\n\n  let parentConfig: Record<string, unknown>;\n  try {\n    parentConfig = await fetchParentConfig(parsed.account, parsed.gateway);\n  } catch {\n    return null;\n  }\n\n  const parentPlugins =\n    parentConfig.plugins && typeof parentConfig.plugins === \"object\"\n      ? (parentConfig.plugins as Record<string, unknown>)\n      : {};\n  const localPlugins =\n    localConfig.plugins && typeof localConfig.plugins === \"object\"\n      ? (localConfig.plugins as Record<string, unknown>)\n      : {};\n\n  const newPluginKeys = Object.keys(parentPlugins).filter((key) => !(key in localPlugins));\n  return { localConfig, parentPlugins, newPluginKeys };\n}\n\nfunction extractSemver(value: string | undefined): string | null {\n  if (!value) return null;\n  const match = value.match(/\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?/);\n  return match?.[0] ?? null;\n}\n\nexport function buildChangelogUrl(\n  oldVersion: string | undefined,\n  newVersion: string,\n  repository: string | undefined,\n): string | undefined {\n  const fromVersion = extractSemver(oldVersion);\n  const toVersion = extractSemver(newVersion);\n  if (!fromVersion || !toVersion || fromVersion === toVersion) return undefined;\n\n  const repoUrl = repository;\n  if (!repoUrl) return undefined;\n\n  const githubMatch = repoUrl.match(/^https?:\\/\\/github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git)?$/);\n  if (!githubMatch) return undefined;\n\n  const [, owner, repo] = githubMatch;\n  return `https://github.com/${owner}/${repo}/compare/v${fromVersion}...v${toVersion}`;\n}\n"],"mappings":";;;;;;AAwBA,eAAsB,uBACpB,YACA,UAAqC,CAAC,GACT;CAC7B,MAAM,cAAe,MAAMA,qCAAwB,UAAU;CAC7D,IAAI,CAAC,aACH,MAAM,IAAI,MAAM,+CAA+C;CAIjE,IAAI,CADeC,8BAAc,WACnB,CAAC,EAAE,WAAW,QAAQ,GAClC,MAAM,IAAI,MACR,8GACF;CAGF,MAAM,OAAO,MAAMC,kCAAiB;EAClC;EACA,iBACE,OAAO,YAAY,eAAe,WAAW,YAAY,aAAa;EACxE,GAAI,QAAQ,cAAc,EAAE,aAAa,QAAQ,YAAY,IAAI,CAAC;CACpE,CAAC;CACD,MAAM,eAAe,KAAK,MAAM,KAAK,SAAS,SAAS,KAAK,QAAQ,GAAG,KAAK,SAAS;CACrF,IAAI,KAAK,YACP,MAAM,IAAI,MAAM,6DAA6D,KAAK,YAAY;CAQhG,MAAM,WAAW,MAAMC,yCAAwB;EAC7C,WAAW;EACX,aAAa;GAAE,GAAG;GAAa,UAAU;EAAU;EACnD,GAAI,QAAQ,gBAAgB,EAAE,eAAe,QAAQ,cAAc,IAAI,CAAC;EACxE,GAAI,QAAQ,cAAc,EAAE,aAAa,QAAQ,YAAY,IAAI,CAAC;EAClE,GAAI,QAAQ,YAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;EAC5D,GAAI,QAAQ,aAAa,EAAE,YAAY,QAAQ,WAAW,IAAI,CAAC;EAC/D,GAAI,QAAQ,MAAM,EAAE,KAAK,QAAQ,IAAI,IAAI,CAAC;EAC1C,GAAI,QAAQ,eAAe,SAAY,EAAE,YAAY,QAAQ,WAAW,IAAI,CAAC;CAC/E,CAAC;CACD,IAAI,CAAC,UACH,MAAM,IAAI,MACR,+DAA+D,aAAa,KAAK,KAAK,EAAE,mHAC1F;CAGF,OAAO;EACL,SAAS,SAAS,SAAS;EAC3B,YAAY,KAAK;EACjB;EACA;CACF;AACF;AAEA,eAAsB,wBAAwB,YAIpC;CACR,MAAM,cAAe,MAAMH,qCAAwB,UAAU;CAC7D,IAAI,CAAC,aACH,OAAO;CAET,MAAM,aAAaC,8BAAc,WAAW;CAC5C,IAAI,CAAC,YAAY,WAAW,QAAQ,GAClC,OAAO;CAGT,MAAM,SAASG,4BAAY,UAAU;CACrC,IAAI,CAAC,QACH,OAAO;CAGT,IAAI;CACJ,IAAI;EACF,eAAe,MAAMC,sCAAkB,OAAO,SAAS,OAAO,OAAO;CACvE,QAAQ;EACN,OAAO;CACT;CAEA,MAAM,gBACJ,aAAa,WAAW,OAAO,aAAa,YAAY,WACnD,aAAa,UACd,CAAC;CACP,MAAM,eACJ,YAAY,WAAW,OAAO,YAAY,YAAY,WACjD,YAAY,UACb,CAAC;CAGP,OAAO;EAAE;EAAa;EAAe,eADf,OAAO,KAAK,aAAa,CAAC,CAAC,QAAQ,QAAQ,EAAE,OAAO,aACzB;CAAE;AACrD;AAEA,SAAS,cAAc,OAA0C;CAC/D,IAAI,CAAC,OAAO,OAAO;CAEnB,OADc,MAAM,MAAM,mCACf,CAAC,GAAG,MAAM;AACvB;AAEA,SAAgB,kBACd,YACA,YACA,YACoB;CACpB,MAAM,cAAc,cAAc,UAAU;CAC5C,MAAM,YAAY,cAAc,UAAU;CAC1C,IAAI,CAAC,eAAe,CAAC,aAAa,gBAAgB,WAAW,OAAO;CAEpE,MAAM,UAAU;CAChB,IAAI,CAAC,SAAS,OAAO;CAErB,MAAM,cAAc,QAAQ,MAAM,uDAAuD;CACzF,IAAI,CAAC,aAAa,OAAO;CAEzB,MAAM,GAAG,OAAO,QAAQ;CACxB,OAAO,sBAAsB,MAAM,GAAG,KAAK,YAAY,YAAY,MAAM;AAC3E"}