{"version":3,"file":"index.cjs","names":["path","fs","require","createRequire","DOOM_SERVER_BUNDLE_FILE","parseDoomServerBundle","DOOM_SERVER_BUNDLE_VERSION","declaredServerFacetsOf","orderServerFacets","compileExtensionModule","extensionModuleManifestPath","compileApiContracts"],"sources":["../../../src/builders/server/index.ts"],"sourcesContent":["import fs from 'node:fs';\nimport { createRequire } from 'node:module';\nimport path from 'node:path';\n\nimport { writeFileAtomic } from '@agimon-ai/doompi-core/runtime-json';\nimport {\n  DOOM_SERVER_BUNDLE_FILE,\n  DOOM_SERVER_BUNDLE_VERSION,\n  type DeclaredServerFacet,\n  type DoomServerBundle,\n  type DoomServerBundleEntry,\n  type DoomServerBundleOwner,\n  declaredServerFacetsOf,\n  orderServerFacets,\n  parseDoomServerBundle,\n} from '@agimon-ai/doompi-core/server-facet';\n\nimport {\n  compileExtensionModule,\n  extensionModuleManifestPath,\n  type CompileExtensionResourceBinding,\n  type CompileExtensionResourcePackage,\n} from '../../compiler';\nimport { compileApiContracts } from '../apiContracts';\nimport type { ExtensionComposition } from '../cli/extensionAssembler';\n\nexport interface ServerBundleSyncInput {\n  readonly generation: string;\n  readonly fingerprint: string;\n  readonly repositoryRoot: string;\n  readonly compositions: readonly ExtensionComposition[];\n  /** Unpublished generation directory, protected by the caller's sync lock. */\n  readonly outputDirectory: string;\n  readonly cacheDirectory: string;\n  readonly sharedCacheDirectory?: string;\n}\n\nexport interface ServerBundleSyncResult {\n  readonly descriptor: DoomServerBundle;\n  readonly compilerManifests: Record<string, string>;\n  readonly contractGaps: readonly string[];\n}\n\nfunction packageRootOf(entry: string): string {\n  let directory = path.dirname(fs.realpathSync(entry));\n  for (;;) {\n    if (fs.existsSync(path.join(directory, 'package.json'))) return directory;\n    const parent = path.dirname(directory);\n    if (parent === directory) throw new Error(`No package manifest owns ${entry}`);\n    directory = parent;\n  }\n}\nfunction packageFiles(packageDirectory: string, extensions: readonly string[]): { path: string }[] {\n  const files: { path: string }[] = [{ path: 'package.json' }];\n  const collect = (directory: string, relativeDirectory: string): void => {\n    for (const name of fs.readdirSync(directory)) {\n      const source = path.join(directory, name);\n      const relative = `${relativeDirectory}/${name}`;\n      const stat = fs.lstatSync(source);\n      if (stat.isSymbolicLink()) throw new Error(`Runtime resource contains a symlink: ${relative}`);\n      if (stat.isDirectory()) collect(source, relative);\n      else if (extensions.some((extension) => name.endsWith(extension))) files.push({ path: relative });\n    }\n  };\n  for (const directoryName of ['dist', 'build']) {\n    const directory = path.join(packageDirectory, directoryName);\n    if (fs.existsSync(directory)) collect(directory, directoryName);\n  }\n  return files;\n}\n\nfunction packageRuntimeFiles(packageDirectory: string): { path: string }[] {\n  return packageFiles(packageDirectory, ['.mjs']);\n}\n\n/** Packages whose executable must survive independently of the installed source graph. */\nfunction resourceBindingFor(\n  declaration: DeclaredServerFacet,\n  manifest: Record<string, unknown>,\n): CompileExtensionResourceBinding | undefined {\n  const optional = manifest.optionalDependencies;\n  if (optional === null || typeof optional !== 'object' || Array.isArray(optional)) return undefined;\n  const currentPlatformPackage = `@agimon-ai/doompi-runner-rmux-${process.platform}-${process.arch}`;\n  const require = createRequire(path.join(declaration.packageDir, 'package.json'));\n  for (const packageName of Object.keys(optional)) {\n    if (packageName !== currentPlatformPackage) continue;\n    let packageManifest: string;\n    try {\n      packageManifest = require.resolve(`${packageName}/package.json`);\n    } catch {\n      continue;\n    }\n    const packageDirectory = path.dirname(fs.realpathSync(packageManifest));\n    if (!fs.existsSync(path.join(packageDirectory, 'vendor', 'bin', 'rmux'))) continue;\n    const owner: CompileExtensionResourcePackage = {\n      packageName: declaration.packageName,\n      packageDirectory: declaration.packageDir,\n      files: packageRuntimeFiles(declaration.packageDir),\n    };\n    const platform: CompileExtensionResourcePackage = {\n      packageName,\n      packageDirectory,\n      files: ['package.json', 'vendor/bin/rmux', 'vendor/bin/rmux-daemon', 'vendor/libexec/rmux/rmux']\n        .filter((file) => fs.existsSync(path.join(packageDirectory, file)))\n        .map((file) => ({ path: file })),\n    };\n    const packages = [owner];\n    const dependencies = manifest.dependencies;\n    if (dependencies && typeof dependencies === 'object' && '@agimon-ai/doompi-telemetry' in dependencies) {\n      // runnerHost imports telemetry at runtime. Declared dependencies are required,\n      // so missing packages must fail staging rather than publish an incomplete graph.\n      const telemetryManifest = require.resolve('@agimon-ai/doompi-telemetry/package.json');\n      const telemetryDirectory = path.dirname(fs.realpathSync(telemetryManifest));\n      packages.push({\n        packageName: '@agimon-ai/doompi-telemetry',\n        packageDirectory: telemetryDirectory,\n        files: packageRuntimeFiles(telemetryDirectory),\n      });\n      const telemetryRequire = createRequire(telemetryManifest);\n      const apiEntry = telemetryRequire.resolve('@opentelemetry/api');\n      const apiDirectory = packageRootOf(apiEntry);\n      packages.push({\n        packageName: '@opentelemetry/api',\n        packageDirectory: apiDirectory,\n        files: packageFiles(apiDirectory, ['.js']),\n      });\n    }\n    packages.push(platform);\n    return {\n      ownerPackageName: declaration.packageName,\n      ownerDirectory: declaration.packageDir,\n      packages,\n    };\n  }\n  return undefined;\n}\n\n/** Stage one descriptor. The caller publishes the containing generation only after all gates pass. */\nexport async function syncServerBundle(input: ServerBundleSyncInput): Promise<ServerBundleSyncResult> {\n  const descriptorPath = path.join(input.outputDirectory, DOOM_SERVER_BUNDLE_FILE);\n  if (fs.existsSync(descriptorPath)) throw new Error('A server bundle generation cannot be overwritten');\n  const descriptor = parseDoomServerBundle({\n    version: DOOM_SERVER_BUNDLE_VERSION,\n    generation: input.generation,\n    fingerprint: input.fingerprint,\n    entries: [],\n  });\n  const packages = new Map<string, { declaration: DeclaredServerFacet; owners: DoomServerBundleOwner[] }>();\n  for (const composition of input.compositions) {\n    const majorMode = composition.majorMode?.name;\n    if (!majorMode) throw new Error('A server bundle composition needs its major mode');\n    const roots = new Set(composition.parentActivation.map(packageRootOf));\n    for (const root of roots) {\n      const manifest = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8')) as Record<string, unknown>;\n      for (const declaration of declaredServerFacetsOf(root, manifest)) {\n        const previous = packages.get(declaration.packageName);\n        if (previous && previous.declaration.packageDir !== root) {\n          throw new Error(`Ambiguous server bundle package: ${declaration.packageName}`);\n        }\n        const candidate = previous ?? { declaration, owners: [] };\n        const layers = composition.selections\n          .filter(\n            (selection) => selection.outcome === 'resolved' && selection.path && packageRootOf(selection.path) === root,\n          )\n          .map((selection) => selection.layer);\n        // Fixed host packages have no layer selection; default is always explicitly admitted.\n        for (const layer of new Set(layers.length > 0 ? layers : ['default'])) {\n          if (!candidate.owners.some((owner) => owner.majorMode === majorMode && owner.layer === layer)) {\n            candidate.owners.push({ majorMode, layer });\n          }\n        }\n        packages.set(declaration.packageName, candidate);\n      }\n    }\n  }\n  const ordered = orderServerFacets([...packages.values()].map(({ declaration }) => declaration));\n  const entries: DoomServerBundleEntry[] = [];\n  const compilerManifests: Record<string, string> = {};\n  for (const [index, declaration] of ordered.entries()) {\n    const builtEntry = fs.realpathSync(path.resolve(declaration.packageDir, declaration.dist));\n    const relative = path.relative(declaration.packageDir, builtEntry);\n    if (relative === '..' || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {\n      throw new Error(`Server entry escapes package: ${declaration.packageName}`);\n    }\n    const packageManifest = JSON.parse(\n      fs.readFileSync(path.join(declaration.packageDir, 'package.json'), 'utf8'),\n    ) as Record<string, unknown>;\n    const resources = resourceBindingFor(declaration, packageManifest);\n    const compileOptions = {\n      repositoryRoot: input.repositoryRoot,\n      sharedCacheDirectory: input.sharedCacheDirectory,\n      ...(resources ? { resources: [resources] } : {}),\n      outputDirectory: path.join(input.outputDirectory, 'modules', String(index)),\n      outputName: 'facet',\n    };\n    const module = await compileExtensionModule(builtEntry, input.cacheDirectory, compileOptions);\n    compilerManifests[declaration.packageName] = extensionModuleManifestPath(\n      builtEntry,\n      input.cacheDirectory,\n      compileOptions,\n    );\n    entries.push({\n      packageName: declaration.packageName,\n      entry: declaration.entry,\n      module: `./${path.relative(input.outputDirectory, module).split(path.sep).join('/')}`,\n      scopes: declaration.scopes,\n      owners: packages.get(declaration.packageName)!.owners,\n      required: declaration.required === true,\n    });\n  }\n  const contracts = await compileApiContracts({\n    descriptor: { ...descriptor, entries },\n    packageRoots: new Map([...packages].map(([name, value]) => [name, value.declaration.packageDir])),\n    repositoryRoot: input.repositoryRoot,\n    outputDirectory: input.outputDirectory,\n    cacheDirectory: input.cacheDirectory,\n    sharedCacheDirectory: input.sharedCacheDirectory,\n  });\n  Object.assign(compilerManifests, contracts.compilerManifests);\n  const complete = parseDoomServerBundle({ ...descriptor, entries, contracts: contracts.contracts });\n  writeFileAtomic(descriptorPath, `${JSON.stringify(complete, null, 2)}\\n`);\n  return { descriptor: complete, compilerManifests, contractGaps: contracts.gaps };\n}\n"],"mappings":"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"}