everything-dev
Version:
A consolidated product package for building Module Federation apps with oRPC APIs.
1 lines • 50.3 kB
Source Map (JSON)
{"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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"}