UNPKG

everything-dev

Version:

A consolidated product package for building Module Federation apps with oRPC APIs.

1 lines • 50.3 kB
{"version":3,"file":"api-contract.cjs","names":["Schema","Context","Layer","Effect","fetchJsonOrNull","fetchResponse","join","dirname","ManagedRuntime","createHash","relative","readFileSync","existsSync","buildAuthTypesGenContent","buildAuthExportStub","readdirSync","isAuthMirrorPluginEntry"],"sources":["../src/api-contract.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { dirname, join, relative } from \"node:path\";\nimport { Context, Effect, Layer, ManagedRuntime, Schema } from \"effect\";\nimport { buildAuthExportStub, buildAuthTypesGenContent } from \"./auth-types-gen\";\nimport { fetchJsonOrNull, fetchResponse } from \"./http-client\";\nimport { isAuthMirrorPluginEntry } from \"./service-descriptor\";\nimport type { JsonObject, RuntimeConfig, RuntimePluginConfig } from \"./types\";\n\nexport interface ApiPluginManifest {\n  schemaVersion: 1;\n  kind: \"every-plugin/manifest\";\n  plugin: {\n    name: string;\n    version: string;\n  };\n  runtime: {\n    remoteEntry: string;\n  };\n  contract?: {\n    kind: \"orpc\";\n    types: {\n      path: string;\n      exportName: string;\n      typeName: string;\n      sha256?: string;\n    };\n  };\n  additionalExports?: Array<{\n    path: string;\n    exports: string[];\n    sha256?: string;\n  }>;\n  plugins?: Array<{\n    key: string;\n    name: string;\n    url: string;\n    dependsOn?: string[];\n    secrets?: string[];\n    variables?: JsonObject;\n  }>;\n  dependsOn?: string[];\n}\n\nexport class ApiManifestFetchError extends Schema.TaggedError<ApiManifestFetchError>()(\n  \"ApiManifestFetchError\",\n  { url: Schema.String, message: Schema.String },\n) {}\n\nexport class ApiManifestFormatError extends Schema.TaggedError<ApiManifestFormatError>()(\n  \"ApiManifestFormatError\",\n  { url: Schema.String, message: Schema.String },\n) {}\n\nexport class MissingContractTypesError extends Schema.TaggedError<MissingContractTypesError>()(\n  \"MissingContractTypesError\",\n  { pluginName: Schema.String, message: Schema.String },\n) {}\n\nexport class ContractTypesFetchError extends Schema.TaggedError<ContractTypesFetchError>()(\n  \"ContractTypesFetchError\",\n  { url: Schema.String, message: Schema.String },\n) {}\n\nexport class ContractTypesChecksumError extends Schema.TaggedError<ContractTypesChecksumError>()(\n  \"ContractTypesChecksumError\",\n  { url: Schema.String, message: Schema.String },\n) {}\n\nexport class AuthExportFetchError extends Schema.TaggedError<AuthExportFetchError>()(\n  \"AuthExportFetchError\",\n  { url: Schema.String, message: Schema.String },\n) {}\n\nexport type ApiContractError =\n  | ApiManifestFetchError\n  | ApiManifestFormatError\n  | MissingContractTypesError\n  | ContractTypesFetchError\n  | ContractTypesChecksumError;\n\nexport class ApiContractResolver extends Context.Service<\n  ApiContractResolver,\n  {\n    manifest: (\n      apiBaseUrl: string,\n    ) => Effect.Effect<ApiPluginManifest, ApiManifestFetchError | ApiManifestFormatError>;\n    contractSource: (opts: {\n      baseUrl: string;\n      runtimeDir: string;\n      name: string;\n      generatedSubdir: string;\n    }) => Effect.Effect<ContractSource, ApiContractError>;\n    authExportTypes: (opts: {\n      baseUrl: string;\n      runtimeDir: string;\n      manifest: ApiPluginManifest;\n    }) => Effect.Effect<string | null, AuthExportFetchError>;\n  }\n>()(\"everything-dev/api-contract/ApiContractResolver\") {\n  static readonly layer: Layer.Layer<ApiContractResolver> = Layer.effect(\n    ApiContractResolver,\n    Effect.sync(() => {\n      const manifest = Effect.fn(\"ApiContractResolver.manifest\")(function* (\n        apiBaseUrl: string,\n      ): Effect.fn.Return<ApiPluginManifest, ApiManifestFetchError | ApiManifestFormatError> {\n        const url = getApiPluginManifestUrl(apiBaseUrl);\n        const fetched = yield* Effect.tryPromise({\n          try: () => fetchJsonOrNull<ApiPluginManifest>(url, { retries: 2 }),\n          catch: () =>\n            new ApiManifestFetchError({\n              url,\n              message: `Failed to fetch API plugin manifest from ${url}`,\n            }),\n        });\n        if (!fetched) {\n          return yield* new ApiManifestFetchError({\n            url,\n            message: `Failed to fetch API plugin manifest from ${url}`,\n          });\n        }\n        if (fetched.schemaVersion !== 1 || fetched.kind !== \"every-plugin/manifest\") {\n          return yield* new ApiManifestFormatError({\n            url,\n            message: \"Unsupported API plugin manifest format\",\n          });\n        }\n        return fetched;\n      });\n\n      const writeContractTypes = Effect.fn(\"ApiContractResolver.writeContractTypes\")(\n        function* (opts: {\n          contractUrl: string;\n          manifest: ApiPluginManifest;\n          runtimeDir: string;\n          generatedSubdir: string;\n          name: string;\n        }): Effect.fn.Return<ContractSource, ContractTypesFetchError | ContractTypesChecksumError> {\n          const contractResponse = yield* Effect.tryPromise({\n            try: () => fetchResponse(opts.contractUrl),\n            catch: () =>\n              new ContractTypesFetchError({\n                url: opts.contractUrl,\n                message: `Failed to fetch contract types from ${opts.contractUrl}`,\n              }),\n          });\n          if (!contractResponse.ok) {\n            return yield* new ContractTypesFetchError({\n              url: opts.contractUrl,\n              message: `Failed to fetch contract types from ${opts.contractUrl}: ${contractResponse.status} ${contractResponse.statusText}`,\n            });\n          }\n\n          const contractTypes = yield* Effect.tryPromise({\n            try: () => contractResponse.text(),\n            catch: () =>\n              new ContractTypesFetchError({\n                url: opts.contractUrl,\n                message: `Failed to fetch contract types from ${opts.contractUrl}`,\n              }),\n          });\n          if (\n            opts.manifest.contract?.types.sha256 &&\n            opts.manifest.contract.types.sha256 !== sha256(contractTypes)\n          ) {\n            return yield* new ContractTypesChecksumError({\n              url: opts.contractUrl,\n              message: \"Fetched contract types failed checksum verification\",\n            });\n          }\n\n          const generatedPath = join(opts.runtimeDir, opts.generatedSubdir, \"contract.d.ts\");\n          yield* Effect.sync(() => {\n            mkdirSync(dirname(generatedPath), { recursive: true });\n            writeFileIfChanged(generatedPath, contractTypes);\n          });\n\n          return {\n            key: opts.name,\n            importName: `${sanitizeIdentifier(opts.name)}Contract`,\n            sourceFilePath: generatedPath,\n            generatedPath,\n          };\n        },\n      );\n\n      const contractSource = Effect.fn(\"ApiContractResolver.contractSource\")(function* (opts: {\n        baseUrl: string;\n        runtimeDir: string;\n        name: string;\n        generatedSubdir: string;\n      }): Effect.fn.Return<ContractSource, ApiContractError> {\n        const fetchedManifest = yield* manifest(opts.baseUrl);\n        if (!fetchedManifest.contract) {\n          return yield* new MissingContractTypesError({\n            pluginName: fetchedManifest.plugin.name,\n            message: `Plugin manifest for ${fetchedManifest.plugin.name} does not advertise contract types`,\n          });\n        }\n        const contractUrl = `${trimTrailingSlash(opts.baseUrl)}/${fetchedManifest.contract.types.path.replace(/^\\.\\//, \"\")}`;\n        return yield* writeContractTypes({\n          contractUrl,\n          manifest: fetchedManifest,\n          runtimeDir: opts.runtimeDir,\n          generatedSubdir: opts.generatedSubdir,\n          name: opts.name,\n        });\n      });\n\n      const authExportTypes = Effect.fn(\"ApiContractResolver.authExportTypes\")(function* (opts: {\n        baseUrl: string;\n        runtimeDir: string;\n        manifest: ApiPluginManifest;\n      }): Effect.fn.Return<string | null, AuthExportFetchError> {\n        const exports = opts.manifest.additionalExports ?? [];\n        const entry = exports.find(\n          (candidate) =>\n            candidate.path.includes(\"auth-export\") || candidate.path.endsWith(\"auth-export.d.ts\"),\n        );\n        if (!entry) return null;\n\n        const exportUrl = `${trimTrailingSlash(opts.baseUrl)}/${entry.path.replace(/^\\.\\//, \"\")}`;\n        const response = yield* Effect.tryPromise({\n          try: () => fetchResponse(exportUrl),\n          catch: () =>\n            new AuthExportFetchError({\n              url: exportUrl,\n              message: `Failed to fetch auth export types from ${exportUrl}`,\n            }),\n        });\n        if (!response.ok) {\n          return yield* new AuthExportFetchError({\n            url: exportUrl,\n            message: `Failed to fetch auth export types from ${exportUrl}: ${response.status}`,\n          });\n        }\n\n        const content = yield* Effect.tryPromise({\n          try: () => response.text(),\n          catch: () =>\n            new AuthExportFetchError({\n              url: exportUrl,\n              message: `Failed to fetch auth export types from ${exportUrl}`,\n            }),\n        });\n        if (entry.sha256 && entry.sha256 !== sha256(content)) {\n          return yield* new AuthExportFetchError({\n            url: exportUrl,\n            message: `Auth export types checksum mismatch for ${exportUrl}`,\n          });\n        }\n\n        const generatedPath = join(opts.runtimeDir, \"auth\", \"auth-export.d.ts\");\n        yield* Effect.sync(() => {\n          mkdirSync(dirname(generatedPath), { recursive: true });\n          writeFileIfChanged(generatedPath, content);\n        });\n        return generatedPath;\n      });\n\n      return ApiContractResolver.of({ manifest, contractSource, authExportTypes });\n    }),\n  );\n}\n\nlet resolverRuntime: ManagedRuntime.ManagedRuntime<ApiContractResolver, never> | null = null;\n\nfunction getResolver(): ManagedRuntime.ManagedRuntime<ApiContractResolver, never> {\n  if (!resolverRuntime) {\n    resolverRuntime = ManagedRuntime.make(ApiContractResolver.layer);\n  }\n  return resolverRuntime;\n}\n\n/** Test seam: dispose the cached resolver runtime. */\nexport function disposeApiContractResolver(): Promise<void> {\n  if (!resolverRuntime) return Promise.resolve();\n  const runtime = resolverRuntime;\n  resolverRuntime = null;\n  return runtime.dispose();\n}\n\ninterface ContractSource {\n  key: string;\n  importName: string;\n  sourceFilePath: string;\n  generatedPath?: string;\n}\n\nfunction sha256(input: string): string {\n  return createHash(\"sha256\").update(input).digest(\"hex\");\n}\n\nfunction trimTrailingSlash(input: string): string {\n  return input.replace(/\\/$/, \"\");\n}\n\nfunction sanitizeIdentifier(input: string): string {\n  return input.replace(/[^A-Za-z0-9_]/g, \"_\").replace(/^[^A-Za-z_]+/, \"_\");\n}\n\nfunction toImportPath(fromFile: string, targetFile: string): string {\n  const rel = relative(dirname(fromFile), targetFile).replace(/\\\\/g, \"/\");\n  return rel.startsWith(\".\") ? rel : `./${rel}`;\n}\n\nfunction writeFileIfChanged(filePath: string, content: string) {\n  try {\n    if (readFileSync(filePath, \"utf8\") === content) return false;\n  } catch {\n    // file does not exist yet\n  }\n\n  writeFileSync(filePath, content);\n  return true;\n}\n\nfunction getApiPluginManifestUrl(apiBaseUrl: string): string {\n  return `${trimTrailingSlash(apiBaseUrl)}/plugin.manifest.json`;\n}\n\nexport async function fetchApiPluginManifest(apiBaseUrl: string): Promise<ApiPluginManifest> {\n  return getResolver()\n    .runPromise(\n      Effect.gen(function* () {\n        const resolver = yield* ApiContractResolver;\n        return yield* resolver.manifest(apiBaseUrl);\n      }),\n    )\n    .catch((error: ApiManifestFetchError | ApiManifestFormatError) => {\n      throw new Error(error.message);\n    });\n}\n\nfunction localApiContractSource(configDir: string): ContractSource {\n  const sourcePath = join(configDir, \"api\", \"src\", \"contract.ts\");\n  if (!existsSync(sourcePath)) {\n    // Never emit an import to a missing file — fail loudly so the caller\n    // marks this source failed instead of generating a broken typecheck.\n    throw new Error(\n      `local api contract not found at api/src/contract.ts — restore the file or configure a reachable api URL`,\n    );\n  }\n  return {\n    key: \"api\",\n    importName: \"BaseApiContract\",\n    sourceFilePath: sourcePath,\n  };\n}\n\nfunction localAuthContractSource(configDir: string): ContractSource {\n  const sourcePath = join(configDir, \"plugins\", \"auth\", \"src\", \"contract.ts\");\n  if (!existsSync(sourcePath)) {\n    throw new Error(\n      `local auth contract not found at plugins/auth/src/contract.ts — restore the file or configure a reachable auth URL`,\n    );\n  }\n  return {\n    key: \"auth\",\n    importName: \"authContract\",\n    sourceFilePath: sourcePath,\n  };\n}\n\nasync function remoteContractSource(opts: {\n  configDir: string;\n  runtimeDir: string;\n  name: string;\n  baseUrl: string;\n  generatedSubdir: string;\n}): Promise<ContractSource> {\n  return getResolver()\n    .runPromise(\n      Effect.gen(function* () {\n        const resolver = yield* ApiContractResolver;\n        return yield* resolver.contractSource({\n          baseUrl: opts.baseUrl,\n          runtimeDir: opts.runtimeDir,\n          name: opts.name,\n          generatedSubdir: opts.generatedSubdir,\n        });\n      }),\n    )\n    .catch((error: ApiContractError) => {\n      throw new Error(error.message);\n    });\n}\n\nasync function fetchAuthExportTypes(opts: {\n  baseUrl: string;\n  runtimeDir: string;\n  manifest: ApiPluginManifest;\n}): Promise<string | null> {\n  return getResolver()\n    .runPromise(\n      Effect.gen(function* () {\n        const resolver = yield* ApiContractResolver;\n        return yield* resolver.authExportTypes({\n          baseUrl: opts.baseUrl,\n          runtimeDir: opts.runtimeDir,\n          manifest: opts.manifest,\n        });\n      }),\n    )\n    .catch((error: AuthExportFetchError) => {\n      console.warn(`[API Contract] ${error.message}`);\n      return null;\n    });\n}\n\nasync function resolveContractSource(opts: {\n  configDir: string;\n  runtimeDir: string;\n  key: string;\n  source: RuntimePluginConfig | { url: string; localPath?: string; name: string } | null;\n  baseUrl: string;\n  generatedSubdir: string;\n  localSourceFactory?: (configDir: string) => ContractSource;\n}): Promise<ContractSource> {\n  if (opts.key === \"api\") {\n    const localPath = opts.source && \"localPath\" in opts.source ? opts.source.localPath : undefined;\n    if (localPath != null && localPath !== \"\") {\n      return {\n        key: opts.key,\n        importName: \"BaseApiContract\",\n        sourceFilePath: join(localPath, \"src\", \"contract.ts\"),\n      };\n    }\n\n    if (!opts.baseUrl) {\n      return localApiContractSource(opts.configDir);\n    }\n  }\n\n  if (opts.key === \"auth\" && opts.localSourceFactory) {\n    const localPath = opts.source && \"localPath\" in opts.source ? opts.source.localPath : undefined;\n    if (localPath != null && localPath !== \"\") {\n      return {\n        key: opts.key,\n        importName: \"authContract\",\n        sourceFilePath: join(localPath, \"src\", \"contract.ts\"),\n      };\n    }\n\n    if (!opts.baseUrl) {\n      return opts.localSourceFactory(opts.configDir);\n    }\n  }\n\n  if (\n    opts.source &&\n    \"localPath\" in opts.source &&\n    opts.source.localPath != null &&\n    opts.source.localPath !== \"\"\n  ) {\n    return {\n      key: opts.key,\n      importName: `${sanitizeIdentifier(opts.key)}Contract`,\n      sourceFilePath: join(opts.source.localPath, \"src\", \"contract.ts\"),\n    };\n  }\n\n  return remoteContractSource({\n    configDir: opts.configDir,\n    runtimeDir: opts.runtimeDir,\n    name: opts.key,\n    baseUrl: opts.baseUrl,\n    generatedSubdir: opts.generatedSubdir,\n  });\n}\n\nfunction writePluginClientGen(opts: {\n  configDir: string;\n  pluginKey: string;\n  depSources: ContractSource[];\n  localPath: string;\n}) {\n  const pluginSrcDir = join(opts.localPath, \"src\");\n  if (!existsSync(pluginSrcDir)) return;\n\n  const targetPath = join(pluginSrcDir, \"lib\", \"plugins-client.gen.ts\");\n  const lines: string[] = [];\n\n  for (const source of opts.depSources) {\n    const importPath = toImportPath(targetPath, source.sourceFilePath);\n    lines.push(`import type { ContractType as ${source.importName} } from \"${importPath}\";`);\n  }\n\n  lines.push('import type { RouterContractClient, RouterContract } from \"@orpc/contract\";');\n  lines.push('import type { ContractedRouter } from \"@orpc/server\";');\n  lines.push(\n    \"type PluginClientEntry<C extends RouterContract> = {\\n  client: (context?: Record<string, unknown>) => RouterContractClient<C>;\\n  router: ContractedRouter<C, any>;\\n};\",\n  );\n  lines.push(\"\");\n\n  if (opts.depSources.length === 0) {\n    lines.push(\"export type PluginsClient = Record<string, never>;\");\n  } else {\n    lines.push(\"export type PluginsClient = {\");\n    for (const source of opts.depSources) {\n      const key = /^[$A-Z_][0-9A-Z_$]*$/i.test(source.key)\n        ? source.key\n        : JSON.stringify(source.key);\n      lines.push(`  ${key}: PluginClientEntry<${source.importName}>;`);\n    }\n    lines.push(\"};\");\n  }\n\n  mkdirSync(dirname(targetPath), { recursive: true });\n  writeFileIfChanged(targetPath, `${lines.join(\"\\n\")}\\n`);\n}\n\nexport function writeGeneratedFiles(opts: {\n  configDir: string;\n  sources: ContractSource[];\n  pluginKeys: string[];\n  authSource: ContractSource | null;\n  authExportPath?: string | null;\n  apiDependsOn?: string[];\n  pluginDependsOn?: Record<string, string[]>;\n  pluginLocalPaths?: Record<string, string>;\n  authLocalPath?: string;\n  authDependsOn?: string[];\n}) {\n  const hasLocalApiWorkspace = existsSync(join(opts.configDir, \"api\", \"src\"));\n  const baseSource = opts.sources.find((source) => source.key === \"api\");\n  const pluginSources = opts.pluginKeys\n    .map((key) => opts.sources.find((entry) => entry.key === key))\n    .filter((source): source is ContractSource => Boolean(source));\n\n  if (!baseSource) {\n    throw new Error(\"API contract source is required to generate the aggregate contract\");\n  }\n\n  // --- Generate ui/src/lib/api-types.gen.ts ---\n  const uiContractPath = join(opts.configDir, \"ui\", \"src\", \"lib\", \"api-types.gen.ts\");\n  const uiLines: string[] = [];\n\n  for (const source of opts.sources) {\n    const importPath = toImportPath(uiContractPath, source.sourceFilePath);\n    uiLines.push(`import type { ContractType as ${source.importName} } from \"${importPath}\";`);\n  }\n\n  uiLines.push(\"\");\n\n  const compositeParts: string[] = [];\n  if (opts.authSource) {\n    compositeParts.push(`auth: ${opts.authSource.importName}`);\n  }\n  for (const source of pluginSources) {\n    const key = /^[$A-Z_][0-9A-Z_$]*$/i.test(source.key) ? source.key : JSON.stringify(source.key);\n    compositeParts.push(`${key}: ${source.importName}`);\n  }\n\n  if (compositeParts.length === 0) {\n    uiLines.push(`export type ApiContract = ${baseSource.importName};`);\n  } else {\n    uiLines.push(`export type ApiContract = ${baseSource.importName} & {`);\n    for (const part of compositeParts) {\n      uiLines.push(`  ${part};`);\n    }\n    uiLines.push(\"};\");\n  }\n  mkdirSync(dirname(uiContractPath), { recursive: true });\n  writeFileIfChanged(uiContractPath, `${uiLines.join(\"\\n\")}\\n`);\n\n  // --- Generate api/src/lib/plugins-types.gen.ts ---\n  // Filtered by apiDependsOn when explicit; includes all plugins + auth when implicit\n  if (hasLocalApiWorkspace) {\n    const pluginsClientPath = join(opts.configDir, \"api\", \"src\", \"lib\", \"plugins-types.gen.ts\");\n    const pluginsClientLines: string[] = [];\n\n    const allPluginSources = [...pluginSources];\n    if (opts.authSource) {\n      allPluginSources.push({ ...opts.authSource, key: \"auth\" });\n    }\n\n    const apiDepSources = opts.apiDependsOn?.length\n      ? allPluginSources.filter((s) => opts.apiDependsOn!.includes(s.key))\n      : allPluginSources;\n\n    const unresolvedDepKeys =\n      opts.apiDependsOn?.filter((depKey) => !allPluginSources.some((s) => s.key === depKey)) ?? [];\n\n    for (const source of apiDepSources) {\n      const importPath = toImportPath(pluginsClientPath, source.sourceFilePath);\n      pluginsClientLines.push(\n        `import type { ContractType as ${source.importName} } from \"${importPath}\";`,\n      );\n    }\n\n    pluginsClientLines.push(\n      'import type { RouterContractClient, RouterContract } from \"@orpc/contract\";',\n    );\n    pluginsClientLines.push('import type { ContractedRouter } from \"@orpc/server\";');\n    pluginsClientLines.push(\n      \"type PluginClientEntry<C extends RouterContract> = {\\n  client: (context?: Record<string, unknown>) => RouterContractClient<C>;\\n  router: ContractedRouter<C, any>;\\n};\",\n    );\n    pluginsClientLines.push(\"\");\n\n    if (apiDepSources.length === 0 && unresolvedDepKeys.length === 0) {\n      pluginsClientLines.push(\"export type PluginsClient = Record<string, never>;\");\n    } else {\n      pluginsClientLines.push(\"export type PluginsClient = {\");\n      for (const source of apiDepSources) {\n        const key = /^[$A-Z_][0-9A-Z_$]*$/i.test(source.key)\n          ? source.key\n          : JSON.stringify(source.key);\n        pluginsClientLines.push(`  ${key}: PluginClientEntry<${source.importName}>;`);\n      }\n      for (const key of unresolvedDepKeys) {\n        const keyStr = /^[$A-Z_][0-9A-Z_$]*$/i.test(key) ? key : JSON.stringify(key);\n        pluginsClientLines.push(`  ${keyStr}?: PluginClientEntry<RouterContract>;`);\n      }\n      pluginsClientLines.push(\"};\");\n    }\n\n    mkdirSync(dirname(pluginsClientPath), { recursive: true });\n    writeFileIfChanged(pluginsClientPath, `${pluginsClientLines.join(\"\\n\")}\\n`);\n  }\n\n  // --- Generate per-plugin plugins-client.gen.ts ---\n  const allSourcesForLookup = [...pluginSources];\n  if (opts.authSource) {\n    allSourcesForLookup.push({ ...opts.authSource, key: \"auth\" });\n  }\n\n  for (const pluginKey of opts.pluginKeys) {\n    const localPath = opts.pluginLocalPaths?.[pluginKey];\n    if (!localPath) continue;\n\n    const deps = opts.pluginDependsOn?.[pluginKey] ?? [];\n    const depSources = deps\n      .map((depKey) => allSourcesForLookup.find((s) => s.key === depKey))\n      .filter((s): s is ContractSource => Boolean(s));\n\n    writePluginClientGen({\n      configDir: opts.configDir,\n      pluginKey,\n      depSources,\n      localPath,\n    });\n  }\n\n  if (opts.authLocalPath) {\n    const deps = opts.authDependsOn ?? [];\n    const depSources = deps\n      .map((depKey) => allSourcesForLookup.find((s) => s.key === depKey))\n      .filter((s): s is ContractSource => Boolean(s));\n\n    writePluginClientGen({\n      configDir: opts.configDir,\n      pluginKey: \"auth\",\n      depSources,\n      localPath: opts.authLocalPath,\n    });\n  }\n\n  // --- Generate */src/lib/auth-types.gen.ts ---\n  const authTypeTargets = [join(opts.configDir, \"ui\", \"src\", \"lib\", \"auth-types.gen.ts\")];\n  const apiLibDir = join(opts.configDir, \"api\", \"src\", \"lib\");\n  if (existsSync(apiLibDir)) {\n    authTypeTargets.push(join(apiLibDir, \"auth-types.gen.ts\"));\n  }\n  const hostLibDir = join(opts.configDir, \"host\", \"src\", \"lib\");\n  if (existsSync(join(opts.configDir, \"host\", \"src\"))) {\n    authTypeTargets.push(join(hostLibDir, \"auth-types.gen.ts\"));\n  }\n\n  // Per-plugin auth-types.gen.ts\n  for (const key of opts.pluginKeys) {\n    const localPath = opts.pluginLocalPaths?.[key];\n    if (!localPath) continue;\n    const pluginSrcDir = join(localPath, \"src\");\n    if (existsSync(pluginSrcDir)) {\n      authTypeTargets.push(join(pluginSrcDir, \"lib\", \"auth-types.gen.ts\"));\n    }\n  }\n\n  if (opts.authExportPath) {\n    for (const authTypesPath of authTypeTargets) {\n      const exportImportPath = toImportPath(authTypesPath, opts.authExportPath);\n      const contractImportPath = toImportPath(\n        authTypesPath,\n        join(dirname(opts.authExportPath), \"contract.d.ts\"),\n      );\n      mkdirSync(dirname(authTypesPath), { recursive: true });\n      writeFileIfChanged(\n        authTypesPath,\n        buildAuthTypesGenContent(exportImportPath, contractImportPath),\n      );\n    }\n  } else if (opts.authSource) {\n    const generatedAuthExportPath = join(\n      opts.configDir,\n      \".bos\",\n      \"generated\",\n      \"auth\",\n      \"auth-export.d.ts\",\n    );\n    mkdirSync(dirname(generatedAuthExportPath), { recursive: true });\n    if (!existsSync(generatedAuthExportPath)) {\n      writeFileIfChanged(generatedAuthExportPath, buildAuthExportStub());\n    }\n\n    for (const authTypesPath of authTypeTargets) {\n      const exportImportPath = toImportPath(authTypesPath, generatedAuthExportPath);\n      const contractImportPath = toImportPath(\n        authTypesPath,\n        join(opts.configDir, \".bos\", \"generated\", \"auth\", \"contract.d.ts\"),\n      );\n      mkdirSync(dirname(authTypesPath), { recursive: true });\n      writeFileIfChanged(\n        authTypesPath,\n        buildAuthTypesGenContent(exportImportPath, contractImportPath),\n      );\n    }\n  }\n\n  // --- Sweep stale per-plugin generated files ---\n  // A plugin that flips local → remote (or is removed) must not keep gen\n  // files importing local source paths, and a removed remote plugin must not\n  // keep its fetched contract. Only exact generated paths are removed —\n  // never app source.\n  const localPluginKeys = new Set(Object.keys(opts.pluginLocalPaths ?? {}));\n  if (opts.authLocalPath) localPluginKeys.add(\"auth\");\n  const pluginsRoot = join(opts.configDir, \"plugins\");\n  if (existsSync(pluginsRoot)) {\n    for (const entry of readdirSync(pluginsRoot, { withFileTypes: true })) {\n      if (!entry.isDirectory() || entry.name.startsWith(\"_\") || localPluginKeys.has(entry.name))\n        continue;\n      for (const genName of [\"plugins-client.gen.ts\", \"auth-types.gen.ts\"]) {\n        const genPath = join(pluginsRoot, entry.name, \"src\", \"lib\", genName);\n        if (existsSync(genPath)) rmSync(genPath);\n      }\n    }\n  }\n  const generatedPluginsRoot = join(opts.configDir, \".bos\", \"generated\", \"plugins\");\n  if (existsSync(generatedPluginsRoot)) {\n    const configuredKeys = new Set(opts.sources.map((source) => source.key));\n    for (const entry of readdirSync(generatedPluginsRoot, { withFileTypes: true })) {\n      if (!entry.isDirectory() || configuredKeys.has(entry.name)) continue;\n      rmSync(join(generatedPluginsRoot, entry.name), { recursive: true, force: true });\n    }\n  }\n\n  return uiContractPath;\n}\n\nexport interface ContractBridgeStatus {\n  key: string;\n  source: \"local\" | \"remote\" | \"skipped\" | \"failed\";\n  url?: string;\n  localPath?: string;\n  error?: string;\n}\n\nexport async function syncApiContractBridge(opts: {\n  configDir: string;\n  runtimeConfig: RuntimeConfig;\n  apiBaseUrl: string;\n}): Promise<{\n  bridgePath: string;\n  generatedPath: string | null;\n  manifest: ApiPluginManifest | null;\n  source: \"local\" | \"remote\";\n  status: ContractBridgeStatus[];\n}> {\n  const runtimeDir = join(opts.configDir, \".bos\", \"generated\");\n  const isAuthMirrorEntry = (key: string, plugin: RuntimePluginConfig) =>\n    isAuthMirrorPluginEntry(opts.runtimeConfig.auth, key, plugin);\n  const pluginEntries = Object.entries(opts.runtimeConfig.plugins ?? {})\n    .filter(([key, plugin]) => !isAuthMirrorEntry(key, plugin))\n    .sort(([a], [b]) => a.localeCompare(b));\n  const sources: ContractSource[] = [];\n  const status: ContractBridgeStatus[] = [];\n  let manifest: ApiPluginManifest | null = null;\n  let generatedPath: string | null = null;\n  let authSource: ContractSource | null = null;\n  let authExportPath: string | null = null;\n  const excludedPluginKeys = new Set<string>();\n\n  try {\n    const baseSource = await resolveContractSource({\n      configDir: opts.configDir,\n      runtimeDir,\n      key: \"api\",\n      source: opts.runtimeConfig.api,\n      baseUrl: opts.apiBaseUrl,\n      generatedSubdir: \"api\",\n    });\n    sources.push(baseSource);\n    status.push({\n      key: \"api\",\n      source: opts.runtimeConfig.api.source,\n      url: opts.runtimeConfig.api.source !== \"local\" ? opts.apiBaseUrl : undefined,\n      localPath:\n        opts.runtimeConfig.api.source === \"local\" ? opts.runtimeConfig.api.localPath : undefined,\n    });\n  } catch (error) {\n    const message = error instanceof Error ? error.message : String(error);\n    console.warn(`[API Contract] Failed to resolve api contract: ${message}`);\n    status.push({\n      key: \"api\",\n      source: \"failed\",\n      url: opts.apiBaseUrl || undefined,\n      error: message,\n    });\n  }\n\n  if (opts.runtimeConfig.auth) {\n    try {\n      authSource = await resolveContractSource({\n        configDir: opts.configDir,\n        runtimeDir,\n        key: \"auth\",\n        source: opts.runtimeConfig.auth,\n        baseUrl: opts.runtimeConfig.auth.url,\n        generatedSubdir: \"auth\",\n        localSourceFactory: localAuthContractSource,\n      });\n      sources.push(authSource);\n      status.push({\n        key: \"auth\",\n        source: opts.runtimeConfig.auth.source,\n        url: opts.runtimeConfig.auth.source !== \"local\" ? opts.runtimeConfig.auth.url : undefined,\n        localPath:\n          opts.runtimeConfig.auth.source === \"local\"\n            ? opts.runtimeConfig.auth.localPath\n            : undefined,\n      });\n      if (authSource.generatedPath) {\n        generatedPath = authSource.generatedPath;\n      }\n\n      if (opts.runtimeConfig.auth.url && opts.runtimeConfig.auth.source !== \"local\") {\n        try {\n          const authManifest = await fetchApiPluginManifest(opts.runtimeConfig.auth.url);\n          const fetchedAuthExportPath = await fetchAuthExportTypes({\n            baseUrl: opts.runtimeConfig.auth.url,\n            runtimeDir,\n            manifest: authManifest,\n          });\n          if (fetchedAuthExportPath) {\n            authExportPath = fetchedAuthExportPath;\n          }\n        } catch (error) {\n          console.warn(\n            `[API Contract] Failed to fetch auth additional exports: ${error instanceof Error ? error.message : String(error)}`,\n          );\n        }\n      }\n\n      if (!authExportPath) {\n        const localAuthExport = join(opts.configDir, \"plugins\", \"auth\", \"src\", \"auth-export.ts\");\n        if (existsSync(localAuthExport)) {\n          authExportPath = localAuthExport;\n        } else {\n          const generatedAuthExport = join(runtimeDir, \"auth\", \"auth-export.d.ts\");\n          if (existsSync(generatedAuthExport)) {\n            authExportPath = generatedAuthExport;\n          }\n        }\n      }\n    } catch (error) {\n      const message = error instanceof Error ? error.message : String(error);\n      console.warn(`[API Contract] Failed to resolve auth contract: ${message}`);\n      status.push({\n        key: \"auth\",\n        source: \"failed\",\n        url: opts.runtimeConfig.auth.url || undefined,\n        error: message,\n      });\n    }\n  }\n\n  for (const [key, plugin] of pluginEntries) {\n    if (!plugin.url && !plugin.localPath) {\n      console.warn(\n        `[API Contract] Skipping plugin \"${key}\" — no URL resolved (local path missing and no production URL configured)`,\n      );\n      status.push({ key, source: \"skipped\" });\n      excludedPluginKeys.add(key);\n    }\n  }\n\n  const resolvablePlugins = pluginEntries.filter(([key]) => !excludedPluginKeys.has(key));\n\n  const pluginResults = await Promise.allSettled(\n    resolvablePlugins.map(async ([key, plugin]) => {\n      const source = await resolveContractSource({\n        configDir: opts.configDir,\n        runtimeDir,\n        key,\n        source: plugin,\n        baseUrl: plugin.url,\n        generatedSubdir: `plugins/${key}`,\n      });\n      return {\n        key,\n        source,\n        plugin,\n      };\n    }),\n  );\n\n  pluginResults.forEach((result, index) => {\n    const [key, plugin] = resolvablePlugins[index]!;\n    if (result.status === \"fulfilled\") {\n      sources.push(result.value.source);\n      status.push({\n        key,\n        source: plugin.source,\n        url: plugin.source !== \"local\" ? plugin.url : undefined,\n        localPath: plugin.source === \"local\" ? plugin.localPath : undefined,\n      });\n      if (result.value.source.generatedPath) {\n        generatedPath = result.value.source.generatedPath;\n      }\n    } else {\n      const message =\n        result.reason instanceof Error ? result.reason.message : String(result.reason);\n      console.warn(`[API Contract] Failed to resolve plugin \"${key}\": ${message}`);\n      status.push({ key, source: \"failed\", url: plugin.url || undefined, error: message });\n      excludedPluginKeys.add(key);\n    }\n  });\n\n  const apiStatus = status.find((s) => s.key === \"api\");\n  if (apiStatus?.source === \"failed\") {\n    throw new Error(\n      `Cannot generate contract types without api contract: ${apiStatus.error ?? \"unknown error\"}`,\n    );\n  }\n\n  const allPluginKeys = pluginEntries\n    .filter(([key]) => !excludedPluginKeys.has(key))\n    .map(([key]) => key);\n\n  const pluginDependsOn: Record<string, string[]> = {};\n  const pluginLocalPaths: Record<string, string> = {};\n  for (const [key, plugin] of pluginEntries) {\n    if (excludedPluginKeys.has(key)) continue;\n    if (plugin.dependsOn?.length) {\n      pluginDependsOn[key] = plugin.dependsOn;\n    }\n    if (plugin.localPath) {\n      pluginLocalPaths[key] = plugin.localPath;\n    }\n  }\n\n  writeGeneratedFiles({\n    configDir: opts.configDir,\n    sources,\n    pluginKeys: allPluginKeys,\n    authSource,\n    authExportPath,\n    apiDependsOn: opts.runtimeConfig.api.dependsOn,\n    pluginDependsOn,\n    pluginLocalPaths,\n    authLocalPath:\n      opts.runtimeConfig.auth?.source === \"local\" ? opts.runtimeConfig.auth.localPath : undefined,\n    authDependsOn: opts.runtimeConfig.auth?.dependsOn,\n  });\n\n  if (opts.runtimeConfig.api.source !== \"local\") {\n    manifest = await fetchApiPluginManifest(opts.apiBaseUrl);\n  }\n\n  return {\n    bridgePath: join(opts.configDir, \"ui\", \"src\", \"lib\", \"api-types.gen.ts\"),\n    generatedPath,\n    manifest,\n    source: opts.runtimeConfig.api.source,\n    status,\n  };\n}\n"],"mappings":"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"}