{"version":3,"file":"layeredConfig-BRCSrgC8.mjs","names":["parseYaml"],"sources":["../src/services/layeredConfig/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nimport { parse as parseYaml } from 'yaml';\n\nimport { globalDoomConfigDirectory } from '../config';\n\n/** Repository-local doom-pi configuration directory, committed to git. */\nexport const DOOM_DIR = '.doom';\n\nconst TEXT_ENCODING = 'utf8';\n\n/** Source identity retained for diagnostics and composition fingerprints. */\nexport interface DoomConfigProvenance {\n  /** Absolute path of the declaring configuration file. */\n  filePath: string;\n  /** Directory used to resolve paths authored by that file. */\n  baseDirectory: string;\n}\n\n/** One `.doom` document plus the root its relative paths resolve against. */\nexport interface DoomConfigSource<TDocument> extends DoomConfigProvenance {\n  /** Absolute path of the file the document was read from. */\n  filePath: string;\n  /**\n   * Where relative paths inside this document point.\n   *\n   * A repository document resolves against the repository root, so `plugins/x`\n   * keeps meaning the same thing it always has. A global document resolves\n   * against the global `.doom` directory, so it can name plugins and extensions\n   * that live beside it in `~/.pi/.doom` rather than inside whichever\n   * repository happens to be open.\n   */\n  baseDirectory: string;\n  /** Raw file contents, for callers that cache parsed results by source text. */\n  text: string;\n  document: TDocument;\n}\n\n/**\n * Reads one named `.doom` document from the global and repository config\n * directories, lowest precedence first.\n *\n * A missing or empty file contributes nothing, so either location on its own is\n * a complete configuration. Documents are deliberately returned unmerged:\n * merging is by name, and only the caller knows what a name means in its own\n * document, so each one folds the sources itself with the repository last.\n */\nexport function doomConfigCandidates(\n  fileName: string,\n  repoRoot: string,\n  homeDirectory: string = os.homedir(),\n): Array<{ filePath: string; baseDirectory: string }> {\n  const globalDirectory = globalDoomConfigDirectory(homeDirectory);\n  return [\n    { filePath: path.join(globalDirectory, fileName), baseDirectory: globalDirectory },\n    { filePath: path.join(repoRoot, DOOM_DIR, fileName), baseDirectory: repoRoot },\n  ];\n}\n\nexport function readDoomConfigSources<TDocument>(\n  fileName: string,\n  repoRoot: string,\n  homeDirectory: string = os.homedir(),\n): Array<DoomConfigSource<TDocument>> {\n  const candidates = doomConfigCandidates(fileName, repoRoot, homeDirectory);\n\n  const sources: Array<DoomConfigSource<TDocument>> = [];\n  for (const candidate of candidates) {\n    if (!fs.existsSync(candidate.filePath)) continue;\n    const text = fs.readFileSync(candidate.filePath, TEXT_ENCODING);\n    const document = parseYaml(text) as TDocument | null | undefined;\n    // An empty file parses to null and is treated as an absent one, so a seeded\n    // placeholder never has to be deleted to get out of the way.\n    if (document === null || document === undefined) continue;\n    sources.push({ ...candidate, text, document });\n  }\n  return sources;\n}\n\n/**\n * Merges same-named records across sources, tagging each entry with the base\n * directory of the document that supplied it.\n *\n * Later sources win outright rather than being deep-merged: a repository that\n * redefines a name is replacing it, and a half-inherited definition whose paths\n * straddle two roots would be impossible to resolve.\n */\nexport function mergeNamedSources<TDocument, TEntry extends object>(\n  sources: ReadonlyArray<DoomConfigSource<TDocument>>,\n  select: (document: TDocument) => Record<string, TEntry> | undefined,\n): Record<string, TEntry & DoomConfigProvenance> {\n  const merged: Record<string, TEntry & DoomConfigProvenance> = {};\n  for (const source of sources) {\n    for (const [name, entry] of Object.entries(select(source.document) ?? {})) {\n      merged[name] = {\n        ...entry,\n        baseDirectory: source.baseDirectory,\n        filePath: source.filePath,\n      };\n    }\n  }\n  return merged;\n}\n"],"mappings":";;;;;;;AASA,MAAa,WAAW;AAExB,MAAM,gBAAgB;;;;;;;;;;AAsCtB,SAAgB,qBACd,UACA,UACA,gBAAwB,GAAG,QAAQ,GACiB;CACpD,MAAM,kBAAkB,0BAA0B,aAAa;CAC/D,OAAO,CACL;EAAE,UAAU,KAAK,KAAK,iBAAiB,QAAQ;EAAG,eAAe;CAAgB,GACjF;EAAE,UAAU,KAAK,KAAK,UAAU,UAAU,QAAQ;EAAG,eAAe;CAAS,CAC/E;AACF;AAEA,SAAgB,sBACd,UACA,UACA,gBAAwB,GAAG,QAAQ,GACC;CACpC,MAAM,aAAa,qBAAqB,UAAU,UAAU,aAAa;CAEzE,MAAM,UAA8C,CAAC;CACrD,KAAK,MAAM,aAAa,YAAY;EAClC,IAAI,CAAC,GAAG,WAAW,UAAU,QAAQ,GAAG;EACxC,MAAM,OAAO,GAAG,aAAa,UAAU,UAAU,aAAa;EAC9D,MAAM,WAAWA,MAAU,IAAI;EAG/B,IAAI,aAAa,QAAQ,aAAa,KAAA,GAAW;EACjD,QAAQ,KAAK;GAAE,GAAG;GAAW;GAAM;EAAS,CAAC;CAC/C;CACA,OAAO;AACT;;;;;;;;;AAUA,SAAgB,kBACd,SACA,QAC+C;CAC/C,MAAM,SAAwD,CAAC;CAC/D,KAAK,MAAM,UAAU,SACnB,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,OAAO,OAAO,QAAQ,KAAK,CAAC,CAAC,GACtE,OAAO,QAAQ;EACb,GAAG;EACH,eAAe,OAAO;EACtB,UAAU,OAAO;CACnB;CAGJ,OAAO;AACT"}