{"version":3,"file":"packageApiLoader.mjs","names":[],"sources":["../../src/adapters/packageApiLoader.ts"],"sourcesContent":["import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { type DoomApi, type DoomApiScope, isDoomApi } from '../schemas/packageApi.ts';\n\n/** Where `doompi sync` publishes the generated route modules. */\nconst API_DIR_NAME = 'api';\nconst CURRENT_DIR_NAME = 'current';\nconst DOOMPI_HOME = '.doompi';\n/** Env override, so a test or a second composition can point a host elsewhere. */\nexport const PACKAGE_API_DIR_ENV = 'DOOMPI_API_DIR';\n\n/** The directory holding the generated modules for this machine. */\nexport function packageApiDirectory(\n  env: NodeJS.ProcessEnv = process.env,\n  homeDir = os.homedir(),\n  explicitDirectory?: string,\n): string {\n  const override = env[PACKAGE_API_DIR_ENV];\n  if (override !== undefined && override !== '') return path.resolve(override);\n  if (explicitDirectory !== undefined) return path.resolve(explicitDirectory);\n  return path.join(homeDir, DOOMPI_HOME, API_DIR_NAME, CURRENT_DIR_NAME);\n}\n\n/** The generated module a host of this scope imports. */\nexport function packageApiModulePath(\n  scope: DoomApiScope,\n  env: NodeJS.ProcessEnv = process.env,\n  homeDir = os.homedir(),\n  explicitDirectory?: string,\n): string {\n  return path.join(packageApiDirectory(env, homeDir, explicitDirectory), `${scope}.routes.mjs`);\n}\n\nexport interface LoadPackageApisOptions {\n  env?: NodeJS.ProcessEnv;\n  homeDir?: string;\n  apiDirectory?: string;\n  onNotice?: (message: string) => void;\n}\n\n/**\n * The APIs a host of this scope should mount, from the module `doompi sync`\n * generated.\n *\n * No module means nothing has been synced yet, which is an ordinary state for a\n * fresh machine and not worth a notice. A module that fails to load is: the\n * host says so and serves nothing, rather than refusing to start, because a\n * broken package must not cost a session its agent.\n */\nexport async function loadPackageApis(scope: DoomApiScope, options: LoadPackageApisOptions = {}): Promise<DoomApi[]> {\n  const notice = options.onNotice ?? ((): void => {});\n  const environment = options.env ?? process.env;\n  const override = environment[PACKAGE_API_DIR_ENV];\n  if (options.apiDirectory === undefined && (override === undefined || override === '')) return [];\n  const modulePath = packageApiModulePath(scope, environment, options.homeDir ?? os.homedir(), options.apiDirectory);\n  if (!fs.existsSync(modulePath)) return [];\n  let exported: unknown;\n  try {\n    const module = (await import(pathToFileURL(modulePath).href)) as { apis?: unknown };\n    exported = module.apis;\n  } catch (error) {\n    notice(`${scope} package APIs are unavailable (${error instanceof Error ? error.message : String(error)})`);\n    return [];\n  }\n  if (!Array.isArray(exported)) {\n    notice(`${modulePath} exports no apis array; no ${scope} API is mounted`);\n    return [];\n  }\n  const seen = new Set<string>();\n  const apis: DoomApi[] = [];\n  for (const candidate of exported) {\n    if (!isDoomApi(candidate)) {\n      notice(`a ${scope} API entry is not a package API and is skipped`);\n      continue;\n    }\n    if (seen.has(candidate.basePath)) {\n      notice(`duplicate package API base path '${candidate.basePath}' dropped; base paths are global`);\n      continue;\n    }\n    seen.add(candidate.basePath);\n    apis.push(candidate);\n  }\n  return apis;\n}\n"],"mappings":"sKAOA,MAIa,EAAsB,iBAGnC,SAAgB,EACd,EAAyB,QAAQ,IACjC,EAAU,EAAG,QAAQ,EACrB,EACQ,CACR,IAAM,EAAW,EAAI,GAGrB,OAFI,IAAa,IAAA,IAAa,IAAa,GAAW,EAAK,QAAQ,CAAQ,EACvE,IAAsB,IAAA,GACnB,EAAK,KAAK,EAAS,UAAa,MAAc,SAAgB,EADzB,EAAK,QAAQ,CAAiB,CAE5E,CAGA,SAAgB,EACd,EACA,EAAyB,QAAQ,IACjC,EAAU,EAAG,QAAQ,EACrB,EACQ,CACR,OAAO,EAAK,KAAK,EAAoB,EAAK,EAAS,CAAiB,EAAG,GAAG,EAAM,YAAY,CAC9F,CAkBA,eAAsB,EAAgB,EAAqB,EAAkC,CAAC,EAAuB,CACnH,IAAM,EAAS,EAAQ,eAAyB,CAAC,GAC3C,EAAc,EAAQ,KAAO,QAAQ,IACrC,EAAW,EAAY,GAC7B,GAAI,EAAQ,eAAiB,IAAA,KAAc,IAAa,IAAA,IAAa,IAAa,IAAK,MAAO,CAAC,EAC/F,IAAM,EAAa,EAAqB,EAAO,EAAa,EAAQ,SAAW,EAAG,QAAQ,EAAG,EAAQ,YAAY,EACjH,GAAI,CAAC,EAAG,WAAW,CAAU,EAAG,MAAO,CAAC,EACxC,IAAI,EACJ,GAAI,CAEF,GAAW,MADW,OAAO,EAAc,CAAU,CAAC,CAAC,MAAA,CACrC,IACpB,OAAS,EAAO,CAEd,OADA,EAAO,GAAG,EAAM,iCAAiC,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EAAE,EAAE,EACnG,CAAC,CACV,CACA,GAAI,CAAC,MAAM,QAAQ,CAAQ,EAEzB,OADA,EAAO,GAAG,EAAW,6BAA6B,EAAM,gBAAgB,EACjE,CAAC,EAEV,IAAM,EAAO,IAAI,IACX,EAAkB,CAAC,EACzB,IAAK,IAAM,KAAa,EAAU,CAChC,GAAI,CAAC,EAAU,CAAS,EAAG,CACzB,EAAO,KAAK,EAAM,+CAA+C,EACjE,QACF,CACA,GAAI,EAAK,IAAI,EAAU,QAAQ,EAAG,CAChC,EAAO,oCAAoC,EAAU,SAAS,iCAAiC,EAC/F,QACF,CACA,EAAK,IAAI,EAAU,QAAQ,EAC3B,EAAK,KAAK,CAAS,CACrB,CACA,OAAO,CACT"}