{"version":3,"file":"unknown-keys.cjs","names":[],"sources":["../../../src/services/resolution/unknown-keys.ts"],"sourcesContent":["/**\n * The authored config's lossless parse seam. `BosConfigSchema` strips unknown\n * keys silently (published snapshots, rollback targets, and merge bases must\n * keep parsing), so a retired or mistyped key vanishes before any consumer\n * sees it — detection has to happen against the authored value itself. This\n * walker diffs the authored object against the schema's declared shapes and\n * returns the paths that would be dropped. `openResolution` surfaces them as\n * `ResolutionSession.unknownAuthoredKeys`; `bos deploy` fails on them.\n *\n * Walks plain zod object shapes (unwrapping optional/lazy wrappers by\n * feature-detection); arrays, records, and primitives are leaves — plugin\n * keys and dynamic records have no unknown-key concept.\n */\n\ntype Shape = Record<string, unknown>;\n\nfunction innerShape(node: unknown, depth = 0): Shape | undefined {\n  if (depth > 4 || !node || typeof node !== \"object\") return undefined;\n  const candidate = node as {\n    shape?: unknown;\n    unwrap?: () => unknown;\n    getter?: () => unknown;\n  };\n  if (candidate.shape && typeof candidate.shape === \"object\") {\n    return candidate.shape as Shape;\n  }\n  if (typeof candidate.unwrap === \"function\") {\n    return innerShape(candidate.unwrap(), depth + 1);\n  }\n  if (typeof candidate.getter === \"function\") {\n    return innerShape(candidate.getter(), depth + 1);\n  }\n  return undefined;\n}\n\nexport function collectUnknownKeys(value: unknown, schema: unknown, prefix = \"\"): string[] {\n  const shape = innerShape(schema);\n  if (!shape || !value || typeof value !== \"object\" || Array.isArray(value)) {\n    return [];\n  }\n  const unknown: string[] = [];\n  for (const key of Object.keys(value)) {\n    const path = prefix ? `${prefix}.${key}` : key;\n    const declared = shape[key];\n    if (!declared) {\n      unknown.push(path);\n      continue;\n    }\n    const nested = innerShape(declared);\n    if (nested) {\n      unknown.push(...collectUnknownKeys((value as Shape)[key], declared, path));\n    }\n  }\n  return unknown;\n}\n"],"mappings":";AAgBA,SAAS,WAAW,MAAe,QAAQ,GAAsB;CAC/D,IAAI,QAAQ,KAAK,CAAC,QAAQ,OAAO,SAAS,UAAU,OAAO;CAC3D,MAAM,YAAY;CAKlB,IAAI,UAAU,SAAS,OAAO,UAAU,UAAU,UAChD,OAAO,UAAU;CAEnB,IAAI,OAAO,UAAU,WAAW,YAC9B,OAAO,WAAW,UAAU,OAAO,GAAG,QAAQ,CAAC;CAEjD,IAAI,OAAO,UAAU,WAAW,YAC9B,OAAO,WAAW,UAAU,OAAO,GAAG,QAAQ,CAAC;AAGnD;AAEA,SAAgB,mBAAmB,OAAgB,QAAiB,SAAS,IAAc;CACzF,MAAM,QAAQ,WAAW,MAAM;CAC/B,IAAI,CAAC,SAAS,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GACtE,OAAO,CAAC;CAEV,MAAM,UAAoB,CAAC;CAC3B,KAAK,MAAM,OAAO,OAAO,KAAK,KAAK,GAAG;EACpC,MAAM,OAAO,SAAS,GAAG,OAAO,GAAG,QAAQ;EAC3C,MAAM,WAAW,MAAM;EACvB,IAAI,CAAC,UAAU;GACb,QAAQ,KAAK,IAAI;GACjB;EACF;EAEA,IADe,WAAW,QACjB,GACP,QAAQ,KAAK,GAAG,mBAAoB,MAAgB,MAAM,UAAU,IAAI,CAAC;CAE7E;CACA,OAAO;AACT"}