UNPKG

everything-dev

Version:

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

587 lines (585 loc) • 26.4 kB
const require_auth_types_gen = require('./auth-types-gen.cjs'); const require_http_client = require('./http-client.cjs'); const require_service_descriptor = require('./service-descriptor.cjs'); let node_fs = require("node:fs"); let node_path = require("node:path"); let effect = require("effect"); let node_crypto = require("node:crypto"); //#region src/api-contract.ts var ApiManifestFetchError = class extends effect.Schema.TaggedError()("ApiManifestFetchError", { url: effect.Schema.String, message: effect.Schema.String }) {}; var ApiManifestFormatError = class extends effect.Schema.TaggedError()("ApiManifestFormatError", { url: effect.Schema.String, message: effect.Schema.String }) {}; var MissingContractTypesError = class extends effect.Schema.TaggedError()("MissingContractTypesError", { pluginName: effect.Schema.String, message: effect.Schema.String }) {}; var ContractTypesFetchError = class extends effect.Schema.TaggedError()("ContractTypesFetchError", { url: effect.Schema.String, message: effect.Schema.String }) {}; var ContractTypesChecksumError = class extends effect.Schema.TaggedError()("ContractTypesChecksumError", { url: effect.Schema.String, message: effect.Schema.String }) {}; var AuthExportFetchError = class extends effect.Schema.TaggedError()("AuthExportFetchError", { url: effect.Schema.String, message: effect.Schema.String }) {}; var ApiContractResolver = class ApiContractResolver extends effect.Context.Service()("everything-dev/api-contract/ApiContractResolver") { static layer = effect.Layer.effect(ApiContractResolver, effect.Effect.sync(() => { const manifest = effect.Effect.fn("ApiContractResolver.manifest")(function* (apiBaseUrl) { const url = getApiPluginManifestUrl(apiBaseUrl); const fetched = yield* effect.Effect.tryPromise({ try: () => require_http_client.fetchJsonOrNull(url, { retries: 2 }), catch: () => new ApiManifestFetchError({ url, message: `Failed to fetch API plugin manifest from ${url}` }) }); if (!fetched) return yield* new ApiManifestFetchError({ url, message: `Failed to fetch API plugin manifest from ${url}` }); if (fetched.schemaVersion !== 1 || fetched.kind !== "every-plugin/manifest") return yield* new ApiManifestFormatError({ url, message: "Unsupported API plugin manifest format" }); return fetched; }); const writeContractTypes = effect.Effect.fn("ApiContractResolver.writeContractTypes")(function* (opts) { const contractResponse = yield* effect.Effect.tryPromise({ try: () => require_http_client.fetchResponse(opts.contractUrl), catch: () => new ContractTypesFetchError({ url: opts.contractUrl, message: `Failed to fetch contract types from ${opts.contractUrl}` }) }); if (!contractResponse.ok) return yield* new ContractTypesFetchError({ url: opts.contractUrl, message: `Failed to fetch contract types from ${opts.contractUrl}: ${contractResponse.status} ${contractResponse.statusText}` }); const contractTypes = yield* effect.Effect.tryPromise({ try: () => contractResponse.text(), catch: () => new ContractTypesFetchError({ url: opts.contractUrl, message: `Failed to fetch contract types from ${opts.contractUrl}` }) }); if (opts.manifest.contract?.types.sha256 && opts.manifest.contract.types.sha256 !== sha256(contractTypes)) return yield* new ContractTypesChecksumError({ url: opts.contractUrl, message: "Fetched contract types failed checksum verification" }); const generatedPath = (0, node_path.join)(opts.runtimeDir, opts.generatedSubdir, "contract.d.ts"); yield* effect.Effect.sync(() => { (0, node_fs.mkdirSync)((0, node_path.dirname)(generatedPath), { recursive: true }); writeFileIfChanged(generatedPath, contractTypes); }); return { key: opts.name, importName: `${sanitizeIdentifier(opts.name)}Contract`, sourceFilePath: generatedPath, generatedPath }; }); const contractSource = effect.Effect.fn("ApiContractResolver.contractSource")(function* (opts) { const fetchedManifest = yield* manifest(opts.baseUrl); if (!fetchedManifest.contract) return yield* new MissingContractTypesError({ pluginName: fetchedManifest.plugin.name, message: `Plugin manifest for ${fetchedManifest.plugin.name} does not advertise contract types` }); const contractUrl = `${trimTrailingSlash(opts.baseUrl)}/${fetchedManifest.contract.types.path.replace(/^\.\//, "")}`; return yield* writeContractTypes({ contractUrl, manifest: fetchedManifest, runtimeDir: opts.runtimeDir, generatedSubdir: opts.generatedSubdir, name: opts.name }); }); const authExportTypes = effect.Effect.fn("ApiContractResolver.authExportTypes")(function* (opts) { const entry = (opts.manifest.additionalExports ?? []).find((candidate) => candidate.path.includes("auth-export") || candidate.path.endsWith("auth-export.d.ts")); if (!entry) return null; const exportUrl = `${trimTrailingSlash(opts.baseUrl)}/${entry.path.replace(/^\.\//, "")}`; const response = yield* effect.Effect.tryPromise({ try: () => require_http_client.fetchResponse(exportUrl), catch: () => new AuthExportFetchError({ url: exportUrl, message: `Failed to fetch auth export types from ${exportUrl}` }) }); if (!response.ok) return yield* new AuthExportFetchError({ url: exportUrl, message: `Failed to fetch auth export types from ${exportUrl}: ${response.status}` }); const content = yield* effect.Effect.tryPromise({ try: () => response.text(), catch: () => new AuthExportFetchError({ url: exportUrl, message: `Failed to fetch auth export types from ${exportUrl}` }) }); if (entry.sha256 && entry.sha256 !== sha256(content)) return yield* new AuthExportFetchError({ url: exportUrl, message: `Auth export types checksum mismatch for ${exportUrl}` }); const generatedPath = (0, node_path.join)(opts.runtimeDir, "auth", "auth-export.d.ts"); yield* effect.Effect.sync(() => { (0, node_fs.mkdirSync)((0, node_path.dirname)(generatedPath), { recursive: true }); writeFileIfChanged(generatedPath, content); }); return generatedPath; }); return ApiContractResolver.of({ manifest, contractSource, authExportTypes }); })); }; let resolverRuntime = null; function getResolver() { if (!resolverRuntime) resolverRuntime = effect.ManagedRuntime.make(ApiContractResolver.layer); return resolverRuntime; } function sha256(input) { return (0, node_crypto.createHash)("sha256").update(input).digest("hex"); } function trimTrailingSlash(input) { return input.replace(/\/$/, ""); } function sanitizeIdentifier(input) { return input.replace(/[^A-Za-z0-9_]/g, "_").replace(/^[^A-Za-z_]+/, "_"); } function toImportPath(fromFile, targetFile) { const rel = (0, node_path.relative)((0, node_path.dirname)(fromFile), targetFile).replace(/\\/g, "/"); return rel.startsWith(".") ? rel : `./${rel}`; } function writeFileIfChanged(filePath, content) { try { if ((0, node_fs.readFileSync)(filePath, "utf8") === content) return false; } catch {} (0, node_fs.writeFileSync)(filePath, content); return true; } function getApiPluginManifestUrl(apiBaseUrl) { return `${trimTrailingSlash(apiBaseUrl)}/plugin.manifest.json`; } async function fetchApiPluginManifest(apiBaseUrl) { return getResolver().runPromise(effect.Effect.gen(function* () { return yield* (yield* ApiContractResolver).manifest(apiBaseUrl); })).catch((error) => { throw new Error(error.message); }); } function localApiContractSource(configDir) { const sourcePath = (0, node_path.join)(configDir, "api", "src", "contract.ts"); if (!(0, node_fs.existsSync)(sourcePath)) throw new Error(`local api contract not found at api/src/contract.ts — restore the file or configure a reachable api URL`); return { key: "api", importName: "BaseApiContract", sourceFilePath: sourcePath }; } function localAuthContractSource(configDir) { const sourcePath = (0, node_path.join)(configDir, "plugins", "auth", "src", "contract.ts"); if (!(0, node_fs.existsSync)(sourcePath)) throw new Error(`local auth contract not found at plugins/auth/src/contract.ts — restore the file or configure a reachable auth URL`); return { key: "auth", importName: "authContract", sourceFilePath: sourcePath }; } async function remoteContractSource(opts) { return getResolver().runPromise(effect.Effect.gen(function* () { return yield* (yield* ApiContractResolver).contractSource({ baseUrl: opts.baseUrl, runtimeDir: opts.runtimeDir, name: opts.name, generatedSubdir: opts.generatedSubdir }); })).catch((error) => { throw new Error(error.message); }); } async function fetchAuthExportTypes(opts) { return getResolver().runPromise(effect.Effect.gen(function* () { return yield* (yield* ApiContractResolver).authExportTypes({ baseUrl: opts.baseUrl, runtimeDir: opts.runtimeDir, manifest: opts.manifest }); })).catch((error) => { console.warn(`[API Contract] ${error.message}`); return null; }); } async function resolveContractSource(opts) { if (opts.key === "api") { const localPath = opts.source && "localPath" in opts.source ? opts.source.localPath : void 0; if (localPath != null && localPath !== "") return { key: opts.key, importName: "BaseApiContract", sourceFilePath: (0, node_path.join)(localPath, "src", "contract.ts") }; if (!opts.baseUrl) return localApiContractSource(opts.configDir); } if (opts.key === "auth" && opts.localSourceFactory) { const localPath = opts.source && "localPath" in opts.source ? opts.source.localPath : void 0; if (localPath != null && localPath !== "") return { key: opts.key, importName: "authContract", sourceFilePath: (0, node_path.join)(localPath, "src", "contract.ts") }; if (!opts.baseUrl) return opts.localSourceFactory(opts.configDir); } if (opts.source && "localPath" in opts.source && opts.source.localPath != null && opts.source.localPath !== "") return { key: opts.key, importName: `${sanitizeIdentifier(opts.key)}Contract`, sourceFilePath: (0, node_path.join)(opts.source.localPath, "src", "contract.ts") }; return remoteContractSource({ configDir: opts.configDir, runtimeDir: opts.runtimeDir, name: opts.key, baseUrl: opts.baseUrl, generatedSubdir: opts.generatedSubdir }); } function writePluginClientGen(opts) { const pluginSrcDir = (0, node_path.join)(opts.localPath, "src"); if (!(0, node_fs.existsSync)(pluginSrcDir)) return; const targetPath = (0, node_path.join)(pluginSrcDir, "lib", "plugins-client.gen.ts"); const lines = []; for (const source of opts.depSources) { const importPath = toImportPath(targetPath, source.sourceFilePath); lines.push(`import type { ContractType as ${source.importName} } from "${importPath}";`); } lines.push("import type { RouterContractClient, RouterContract } from \"@orpc/contract\";"); lines.push("import type { ContractedRouter } from \"@orpc/server\";"); lines.push("type PluginClientEntry<C extends RouterContract> = {\n client: (context?: Record<string, unknown>) => RouterContractClient<C>;\n router: ContractedRouter<C, any>;\n};"); lines.push(""); if (opts.depSources.length === 0) lines.push("export type PluginsClient = Record<string, never>;"); else { lines.push("export type PluginsClient = {"); for (const source of opts.depSources) { const key = /^[$A-Z_][0-9A-Z_$]*$/i.test(source.key) ? source.key : JSON.stringify(source.key); lines.push(` ${key}: PluginClientEntry<${source.importName}>;`); } lines.push("};"); } (0, node_fs.mkdirSync)((0, node_path.dirname)(targetPath), { recursive: true }); writeFileIfChanged(targetPath, `${lines.join("\n")}\n`); } function writeGeneratedFiles(opts) { const hasLocalApiWorkspace = (0, node_fs.existsSync)((0, node_path.join)(opts.configDir, "api", "src")); const baseSource = opts.sources.find((source) => source.key === "api"); const pluginSources = opts.pluginKeys.map((key) => opts.sources.find((entry) => entry.key === key)).filter((source) => Boolean(source)); if (!baseSource) throw new Error("API contract source is required to generate the aggregate contract"); const uiContractPath = (0, node_path.join)(opts.configDir, "ui", "src", "lib", "api-types.gen.ts"); const uiLines = []; for (const source of opts.sources) { const importPath = toImportPath(uiContractPath, source.sourceFilePath); uiLines.push(`import type { ContractType as ${source.importName} } from "${importPath}";`); } uiLines.push(""); const compositeParts = []; if (opts.authSource) compositeParts.push(`auth: ${opts.authSource.importName}`); for (const source of pluginSources) { const key = /^[$A-Z_][0-9A-Z_$]*$/i.test(source.key) ? source.key : JSON.stringify(source.key); compositeParts.push(`${key}: ${source.importName}`); } if (compositeParts.length === 0) uiLines.push(`export type ApiContract = ${baseSource.importName};`); else { uiLines.push(`export type ApiContract = ${baseSource.importName} & {`); for (const part of compositeParts) uiLines.push(` ${part};`); uiLines.push("};"); } (0, node_fs.mkdirSync)((0, node_path.dirname)(uiContractPath), { recursive: true }); writeFileIfChanged(uiContractPath, `${uiLines.join("\n")}\n`); if (hasLocalApiWorkspace) { const pluginsClientPath = (0, node_path.join)(opts.configDir, "api", "src", "lib", "plugins-types.gen.ts"); const pluginsClientLines = []; const allPluginSources = [...pluginSources]; if (opts.authSource) allPluginSources.push({ ...opts.authSource, key: "auth" }); const apiDepSources = opts.apiDependsOn?.length ? allPluginSources.filter((s) => opts.apiDependsOn.includes(s.key)) : allPluginSources; const unresolvedDepKeys = opts.apiDependsOn?.filter((depKey) => !allPluginSources.some((s) => s.key === depKey)) ?? []; for (const source of apiDepSources) { const importPath = toImportPath(pluginsClientPath, source.sourceFilePath); pluginsClientLines.push(`import type { ContractType as ${source.importName} } from "${importPath}";`); } pluginsClientLines.push("import type { RouterContractClient, RouterContract } from \"@orpc/contract\";"); pluginsClientLines.push("import type { ContractedRouter } from \"@orpc/server\";"); pluginsClientLines.push("type PluginClientEntry<C extends RouterContract> = {\n client: (context?: Record<string, unknown>) => RouterContractClient<C>;\n router: ContractedRouter<C, any>;\n};"); pluginsClientLines.push(""); if (apiDepSources.length === 0 && unresolvedDepKeys.length === 0) pluginsClientLines.push("export type PluginsClient = Record<string, never>;"); else { pluginsClientLines.push("export type PluginsClient = {"); for (const source of apiDepSources) { const key = /^[$A-Z_][0-9A-Z_$]*$/i.test(source.key) ? source.key : JSON.stringify(source.key); pluginsClientLines.push(` ${key}: PluginClientEntry<${source.importName}>;`); } for (const key of unresolvedDepKeys) { const keyStr = /^[$A-Z_][0-9A-Z_$]*$/i.test(key) ? key : JSON.stringify(key); pluginsClientLines.push(` ${keyStr}?: PluginClientEntry<RouterContract>;`); } pluginsClientLines.push("};"); } (0, node_fs.mkdirSync)((0, node_path.dirname)(pluginsClientPath), { recursive: true }); writeFileIfChanged(pluginsClientPath, `${pluginsClientLines.join("\n")}\n`); } const allSourcesForLookup = [...pluginSources]; if (opts.authSource) allSourcesForLookup.push({ ...opts.authSource, key: "auth" }); for (const pluginKey of opts.pluginKeys) { const localPath = opts.pluginLocalPaths?.[pluginKey]; if (!localPath) continue; const depSources = (opts.pluginDependsOn?.[pluginKey] ?? []).map((depKey) => allSourcesForLookup.find((s) => s.key === depKey)).filter((s) => Boolean(s)); writePluginClientGen({ configDir: opts.configDir, pluginKey, depSources, localPath }); } if (opts.authLocalPath) { const depSources = (opts.authDependsOn ?? []).map((depKey) => allSourcesForLookup.find((s) => s.key === depKey)).filter((s) => Boolean(s)); writePluginClientGen({ configDir: opts.configDir, pluginKey: "auth", depSources, localPath: opts.authLocalPath }); } const authTypeTargets = [(0, node_path.join)(opts.configDir, "ui", "src", "lib", "auth-types.gen.ts")]; const apiLibDir = (0, node_path.join)(opts.configDir, "api", "src", "lib"); if ((0, node_fs.existsSync)(apiLibDir)) authTypeTargets.push((0, node_path.join)(apiLibDir, "auth-types.gen.ts")); const hostLibDir = (0, node_path.join)(opts.configDir, "host", "src", "lib"); if ((0, node_fs.existsSync)((0, node_path.join)(opts.configDir, "host", "src"))) authTypeTargets.push((0, node_path.join)(hostLibDir, "auth-types.gen.ts")); for (const key of opts.pluginKeys) { const localPath = opts.pluginLocalPaths?.[key]; if (!localPath) continue; const pluginSrcDir = (0, node_path.join)(localPath, "src"); if ((0, node_fs.existsSync)(pluginSrcDir)) authTypeTargets.push((0, node_path.join)(pluginSrcDir, "lib", "auth-types.gen.ts")); } if (opts.authExportPath) for (const authTypesPath of authTypeTargets) { const exportImportPath = toImportPath(authTypesPath, opts.authExportPath); const contractImportPath = toImportPath(authTypesPath, (0, node_path.join)((0, node_path.dirname)(opts.authExportPath), "contract.d.ts")); (0, node_fs.mkdirSync)((0, node_path.dirname)(authTypesPath), { recursive: true }); writeFileIfChanged(authTypesPath, require_auth_types_gen.buildAuthTypesGenContent(exportImportPath, contractImportPath)); } else if (opts.authSource) { const generatedAuthExportPath = (0, node_path.join)(opts.configDir, ".bos", "generated", "auth", "auth-export.d.ts"); (0, node_fs.mkdirSync)((0, node_path.dirname)(generatedAuthExportPath), { recursive: true }); if (!(0, node_fs.existsSync)(generatedAuthExportPath)) writeFileIfChanged(generatedAuthExportPath, require_auth_types_gen.buildAuthExportStub()); for (const authTypesPath of authTypeTargets) { const exportImportPath = toImportPath(authTypesPath, generatedAuthExportPath); const contractImportPath = toImportPath(authTypesPath, (0, node_path.join)(opts.configDir, ".bos", "generated", "auth", "contract.d.ts")); (0, node_fs.mkdirSync)((0, node_path.dirname)(authTypesPath), { recursive: true }); writeFileIfChanged(authTypesPath, require_auth_types_gen.buildAuthTypesGenContent(exportImportPath, contractImportPath)); } } const localPluginKeys = new Set(Object.keys(opts.pluginLocalPaths ?? {})); if (opts.authLocalPath) localPluginKeys.add("auth"); const pluginsRoot = (0, node_path.join)(opts.configDir, "plugins"); if ((0, node_fs.existsSync)(pluginsRoot)) for (const entry of (0, node_fs.readdirSync)(pluginsRoot, { withFileTypes: true })) { if (!entry.isDirectory() || entry.name.startsWith("_") || localPluginKeys.has(entry.name)) continue; for (const genName of ["plugins-client.gen.ts", "auth-types.gen.ts"]) { const genPath = (0, node_path.join)(pluginsRoot, entry.name, "src", "lib", genName); if ((0, node_fs.existsSync)(genPath)) (0, node_fs.rmSync)(genPath); } } const generatedPluginsRoot = (0, node_path.join)(opts.configDir, ".bos", "generated", "plugins"); if ((0, node_fs.existsSync)(generatedPluginsRoot)) { const configuredKeys = new Set(opts.sources.map((source) => source.key)); for (const entry of (0, node_fs.readdirSync)(generatedPluginsRoot, { withFileTypes: true })) { if (!entry.isDirectory() || configuredKeys.has(entry.name)) continue; (0, node_fs.rmSync)((0, node_path.join)(generatedPluginsRoot, entry.name), { recursive: true, force: true }); } } return uiContractPath; } async function syncApiContractBridge(opts) { const runtimeDir = (0, node_path.join)(opts.configDir, ".bos", "generated"); const isAuthMirrorEntry = (key, plugin) => require_service_descriptor.isAuthMirrorPluginEntry(opts.runtimeConfig.auth, key, plugin); const pluginEntries = Object.entries(opts.runtimeConfig.plugins ?? {}).filter(([key, plugin]) => !isAuthMirrorEntry(key, plugin)).sort(([a], [b]) => a.localeCompare(b)); const sources = []; const status = []; let manifest = null; let generatedPath = null; let authSource = null; let authExportPath = null; const excludedPluginKeys = /* @__PURE__ */ new Set(); try { const baseSource = await resolveContractSource({ configDir: opts.configDir, runtimeDir, key: "api", source: opts.runtimeConfig.api, baseUrl: opts.apiBaseUrl, generatedSubdir: "api" }); sources.push(baseSource); status.push({ key: "api", source: opts.runtimeConfig.api.source, url: opts.runtimeConfig.api.source !== "local" ? opts.apiBaseUrl : void 0, localPath: opts.runtimeConfig.api.source === "local" ? opts.runtimeConfig.api.localPath : void 0 }); } catch (error) { const message = error instanceof Error ? error.message : String(error); console.warn(`[API Contract] Failed to resolve api contract: ${message}`); status.push({ key: "api", source: "failed", url: opts.apiBaseUrl || void 0, error: message }); } if (opts.runtimeConfig.auth) try { authSource = await resolveContractSource({ configDir: opts.configDir, runtimeDir, key: "auth", source: opts.runtimeConfig.auth, baseUrl: opts.runtimeConfig.auth.url, generatedSubdir: "auth", localSourceFactory: localAuthContractSource }); sources.push(authSource); status.push({ key: "auth", source: opts.runtimeConfig.auth.source, url: opts.runtimeConfig.auth.source !== "local" ? opts.runtimeConfig.auth.url : void 0, localPath: opts.runtimeConfig.auth.source === "local" ? opts.runtimeConfig.auth.localPath : void 0 }); if (authSource.generatedPath) generatedPath = authSource.generatedPath; if (opts.runtimeConfig.auth.url && opts.runtimeConfig.auth.source !== "local") try { const authManifest = await fetchApiPluginManifest(opts.runtimeConfig.auth.url); const fetchedAuthExportPath = await fetchAuthExportTypes({ baseUrl: opts.runtimeConfig.auth.url, runtimeDir, manifest: authManifest }); if (fetchedAuthExportPath) authExportPath = fetchedAuthExportPath; } catch (error) { console.warn(`[API Contract] Failed to fetch auth additional exports: ${error instanceof Error ? error.message : String(error)}`); } if (!authExportPath) { const localAuthExport = (0, node_path.join)(opts.configDir, "plugins", "auth", "src", "auth-export.ts"); if ((0, node_fs.existsSync)(localAuthExport)) authExportPath = localAuthExport; else { const generatedAuthExport = (0, node_path.join)(runtimeDir, "auth", "auth-export.d.ts"); if ((0, node_fs.existsSync)(generatedAuthExport)) authExportPath = generatedAuthExport; } } } catch (error) { const message = error instanceof Error ? error.message : String(error); console.warn(`[API Contract] Failed to resolve auth contract: ${message}`); status.push({ key: "auth", source: "failed", url: opts.runtimeConfig.auth.url || void 0, error: message }); } for (const [key, plugin] of pluginEntries) if (!plugin.url && !plugin.localPath) { console.warn(`[API Contract] Skipping plugin "${key}" — no URL resolved (local path missing and no production URL configured)`); status.push({ key, source: "skipped" }); excludedPluginKeys.add(key); } const resolvablePlugins = pluginEntries.filter(([key]) => !excludedPluginKeys.has(key)); (await Promise.allSettled(resolvablePlugins.map(async ([key, plugin]) => { return { key, source: await resolveContractSource({ configDir: opts.configDir, runtimeDir, key, source: plugin, baseUrl: plugin.url, generatedSubdir: `plugins/${key}` }), plugin }; }))).forEach((result, index) => { const [key, plugin] = resolvablePlugins[index]; if (result.status === "fulfilled") { sources.push(result.value.source); status.push({ key, source: plugin.source, url: plugin.source !== "local" ? plugin.url : void 0, localPath: plugin.source === "local" ? plugin.localPath : void 0 }); if (result.value.source.generatedPath) generatedPath = result.value.source.generatedPath; } else { const message = result.reason instanceof Error ? result.reason.message : String(result.reason); console.warn(`[API Contract] Failed to resolve plugin "${key}": ${message}`); status.push({ key, source: "failed", url: plugin.url || void 0, error: message }); excludedPluginKeys.add(key); } }); const apiStatus = status.find((s) => s.key === "api"); if (apiStatus?.source === "failed") throw new Error(`Cannot generate contract types without api contract: ${apiStatus.error ?? "unknown error"}`); const allPluginKeys = pluginEntries.filter(([key]) => !excludedPluginKeys.has(key)).map(([key]) => key); const pluginDependsOn = {}; const pluginLocalPaths = {}; for (const [key, plugin] of pluginEntries) { if (excludedPluginKeys.has(key)) continue; if (plugin.dependsOn?.length) pluginDependsOn[key] = plugin.dependsOn; if (plugin.localPath) pluginLocalPaths[key] = plugin.localPath; } writeGeneratedFiles({ configDir: opts.configDir, sources, pluginKeys: allPluginKeys, authSource, authExportPath, apiDependsOn: opts.runtimeConfig.api.dependsOn, pluginDependsOn, pluginLocalPaths, authLocalPath: opts.runtimeConfig.auth?.source === "local" ? opts.runtimeConfig.auth.localPath : void 0, authDependsOn: opts.runtimeConfig.auth?.dependsOn }); if (opts.runtimeConfig.api.source !== "local") manifest = await fetchApiPluginManifest(opts.apiBaseUrl); return { bridgePath: (0, node_path.join)(opts.configDir, "ui", "src", "lib", "api-types.gen.ts"), generatedPath, manifest, source: opts.runtimeConfig.api.source, status }; } //#endregion exports.ApiContractResolver = ApiContractResolver; exports.ApiManifestFetchError = ApiManifestFetchError; exports.ApiManifestFormatError = ApiManifestFormatError; exports.AuthExportFetchError = AuthExportFetchError; exports.ContractTypesChecksumError = ContractTypesChecksumError; exports.ContractTypesFetchError = ContractTypesFetchError; exports.MissingContractTypesError = MissingContractTypesError; exports.fetchApiPluginManifest = fetchApiPluginManifest; exports.syncApiContractBridge = syncApiContractBridge; exports.writeGeneratedFiles = writeGeneratedFiles; //# sourceMappingURL=api-contract.cjs.map