everything-dev 1.51.7 → 1.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/dist/api-contract.cjs +66 -16
  2. package/dist/api-contract.cjs.map +1 -1
  3. package/dist/api-contract.mjs +65 -17
  4. package/dist/api-contract.mjs.map +1 -1
  5. package/dist/app.cjs +1 -1
  6. package/dist/app.cjs.map +1 -1
  7. package/dist/app.mjs +1 -1
  8. package/dist/app.mjs.map +1 -1
  9. package/dist/cli/infra.cjs +0 -67
  10. package/dist/cli/infra.cjs.map +1 -1
  11. package/dist/cli/infra.mjs +1 -65
  12. package/dist/cli/infra.mjs.map +1 -1
  13. package/dist/cli/init.cjs +76 -52
  14. package/dist/cli/init.cjs.map +1 -1
  15. package/dist/cli/init.d.cts +15 -7
  16. package/dist/cli/init.d.cts.map +1 -1
  17. package/dist/cli/init.d.mts +15 -7
  18. package/dist/cli/init.d.mts.map +1 -1
  19. package/dist/cli/init.mjs +70 -47
  20. package/dist/cli/init.mjs.map +1 -1
  21. package/dist/cli/sync.cjs +34 -5
  22. package/dist/cli/sync.cjs.map +1 -1
  23. package/dist/cli/sync.mjs +35 -6
  24. package/dist/cli/sync.mjs.map +1 -1
  25. package/dist/cli/upgrade.cjs +151 -93
  26. package/dist/cli/upgrade.cjs.map +1 -1
  27. package/dist/cli/upgrade.mjs +138 -80
  28. package/dist/cli/upgrade.mjs.map +1 -1
  29. package/dist/cli/utils/helpers.cjs +25 -0
  30. package/dist/cli/utils/helpers.cjs.map +1 -0
  31. package/dist/cli/utils/helpers.mjs +23 -0
  32. package/dist/cli/utils/helpers.mjs.map +1 -0
  33. package/dist/cli.cjs +84 -72
  34. package/dist/cli.cjs.map +1 -1
  35. package/dist/cli.mjs +84 -72
  36. package/dist/cli.mjs.map +1 -1
  37. package/dist/code-artifacts.cjs +1 -1
  38. package/dist/code-artifacts.mjs +1 -1
  39. package/dist/config.cjs +47 -5
  40. package/dist/config.cjs.map +1 -1
  41. package/dist/config.d.cts +1 -1
  42. package/dist/config.d.cts.map +1 -1
  43. package/dist/config.d.mts +1 -1
  44. package/dist/config.d.mts.map +1 -1
  45. package/dist/config.mjs +47 -5
  46. package/dist/config.mjs.map +1 -1
  47. package/dist/contract.cjs +9 -4
  48. package/dist/contract.cjs.map +1 -1
  49. package/dist/contract.d.cts +42 -24
  50. package/dist/contract.d.cts.map +1 -1
  51. package/dist/contract.d.mts +42 -24
  52. package/dist/contract.d.mts.map +1 -1
  53. package/dist/contract.meta.cjs +2 -1
  54. package/dist/contract.meta.cjs.map +1 -1
  55. package/dist/contract.meta.d.cts +3 -0
  56. package/dist/contract.meta.d.mts +3 -0
  57. package/dist/contract.meta.mjs +2 -1
  58. package/dist/contract.meta.mjs.map +1 -1
  59. package/dist/contract.mjs +9 -4
  60. package/dist/contract.mjs.map +1 -1
  61. package/dist/dag.cjs +177 -0
  62. package/dist/dag.cjs.map +1 -0
  63. package/dist/dag.d.cts +24 -0
  64. package/dist/dag.d.cts.map +1 -0
  65. package/dist/dag.d.mts +24 -0
  66. package/dist/dag.d.mts.map +1 -0
  67. package/dist/dag.mjs +168 -0
  68. package/dist/dag.mjs.map +1 -0
  69. package/dist/index.cjs +2 -0
  70. package/dist/index.d.cts +2 -2
  71. package/dist/index.d.mts +2 -2
  72. package/dist/index.mjs +2 -2
  73. package/dist/infra/planner.cjs +1 -1
  74. package/dist/infra/planner.mjs +1 -1
  75. package/dist/merge.cjs +1 -1
  76. package/dist/merge.cjs.map +1 -1
  77. package/dist/merge.mjs +1 -1
  78. package/dist/merge.mjs.map +1 -1
  79. package/dist/near-cli.cjs +1 -1
  80. package/dist/near-cli.mjs +1 -1
  81. package/dist/orchestrator.cjs +1 -1
  82. package/dist/orchestrator.cjs.map +1 -1
  83. package/dist/orchestrator.mjs +1 -1
  84. package/dist/orchestrator.mjs.map +1 -1
  85. package/dist/plugin.cjs +28 -30
  86. package/dist/plugin.cjs.map +1 -1
  87. package/dist/plugin.d.cts +67 -11
  88. package/dist/plugin.d.cts.map +1 -1
  89. package/dist/plugin.d.mts +67 -11
  90. package/dist/plugin.d.mts.map +1 -1
  91. package/dist/plugin.mjs +30 -32
  92. package/dist/plugin.mjs.map +1 -1
  93. package/dist/types.cjs +52 -9
  94. package/dist/types.cjs.map +1 -1
  95. package/dist/types.d.cts +131 -3
  96. package/dist/types.d.cts.map +1 -1
  97. package/dist/types.d.mts +131 -3
  98. package/dist/types.d.mts.map +1 -1
  99. package/dist/types.mjs +51 -10
  100. package/dist/types.mjs.map +1 -1
  101. package/package.json +8 -3
@@ -209,6 +209,30 @@ async function resolveContractSource(opts) {
209
209
  generatedSubdir: opts.generatedSubdir
210
210
  });
211
211
  }
212
+ function writePluginClientGen(opts) {
213
+ const pluginSrcDir = (0, node_path.join)(opts.configDir, "plugins", opts.pluginKey, "src");
214
+ if (!(0, node_fs.existsSync)(pluginSrcDir)) return;
215
+ const targetPath = (0, node_path.join)(pluginSrcDir, "lib", "plugins-client.gen.ts");
216
+ const lines = [];
217
+ for (const source of opts.depSources) {
218
+ const importPath = toImportPath(targetPath, source.sourceFilePath);
219
+ lines.push(`import type { ContractType as ${source.importName} } from "${importPath}";`);
220
+ }
221
+ lines.push("import type { ContractRouterClient, AnyContractRouter } from \"@orpc/contract\";");
222
+ lines.push("type ClientFactory<C extends AnyContractRouter> = (context?: Record<string, unknown>) => ContractRouterClient<C>;");
223
+ lines.push("");
224
+ if (opts.depSources.length === 0) lines.push("export type PluginsClient = Record<string, never>;");
225
+ else {
226
+ lines.push("export type PluginsClient = {");
227
+ for (const source of opts.depSources) {
228
+ const key = /^[$A-Z_][0-9A-Z_$]*$/i.test(source.key) ? source.key : JSON.stringify(source.key);
229
+ lines.push(` ${key}: ClientFactory<${source.importName}>;`);
230
+ }
231
+ lines.push("};");
232
+ }
233
+ (0, node_fs.mkdirSync)((0, node_path.dirname)(targetPath), { recursive: true });
234
+ writeFileIfChanged(targetPath, `${lines.join("\n")}\n`);
235
+ }
212
236
  function writeGeneratedFiles(opts) {
213
237
  const hasLocalApiWorkspace = (0, node_fs.existsSync)((0, node_path.join)(opts.configDir, "api", "src"));
214
238
  const baseSource = opts.sources.find((source) => source.key === "api");
@@ -238,34 +262,51 @@ function writeGeneratedFiles(opts) {
238
262
  if (hasLocalApiWorkspace) {
239
263
  const pluginsClientPath = (0, node_path.join)(opts.configDir, "api", "src", "lib", "plugins-types.gen.ts");
240
264
  const pluginsClientLines = [];
241
- for (const source of pluginSources) {
265
+ const allPluginSources = [...pluginSources];
266
+ if (opts.authSource) allPluginSources.push({
267
+ ...opts.authSource,
268
+ key: "auth"
269
+ });
270
+ const apiDepSources = opts.apiDependsOn?.length ? allPluginSources.filter((s) => opts.apiDependsOn.includes(s.key)) : allPluginSources;
271
+ const unresolvedDepKeys = opts.apiDependsOn?.filter((depKey) => !allPluginSources.some((s) => s.key === depKey)) ?? [];
272
+ for (const source of apiDepSources) {
242
273
  const importPath = toImportPath(pluginsClientPath, source.sourceFilePath);
243
274
  pluginsClientLines.push(`import type { ContractType as ${source.importName} } from "${importPath}";`);
244
275
  }
245
- if (opts.authSource) {
246
- const authImportPath = toImportPath(pluginsClientPath, opts.authSource.sourceFilePath);
247
- pluginsClientLines.push(`import type { ContractType as ${opts.authSource.importName} } from "${authImportPath}";`);
248
- }
249
276
  pluginsClientLines.push("import type { ContractRouterClient, AnyContractRouter } from \"@orpc/contract\";");
250
277
  pluginsClientLines.push("type ClientFactory<C extends AnyContractRouter> = (context?: Record<string, unknown>) => ContractRouterClient<C>;");
251
278
  pluginsClientLines.push("");
252
- const allPluginSources = [...pluginSources];
253
- if (opts.authSource) allPluginSources.push({
254
- ...opts.authSource,
255
- key: "auth"
256
- });
257
- if (allPluginSources.length === 0) pluginsClientLines.push("export type PluginsClient = Record<string, never>;");
279
+ if (apiDepSources.length === 0 && unresolvedDepKeys.length === 0) pluginsClientLines.push("export type PluginsClient = Record<string, never>;");
258
280
  else {
259
281
  pluginsClientLines.push("export type PluginsClient = {");
260
- for (const source of allPluginSources) {
282
+ for (const source of apiDepSources) {
261
283
  const key = /^[$A-Z_][0-9A-Z_$]*$/i.test(source.key) ? source.key : JSON.stringify(source.key);
262
284
  pluginsClientLines.push(` ${key}: ClientFactory<${source.importName}>;`);
263
285
  }
286
+ for (const key of unresolvedDepKeys) {
287
+ const keyStr = /^[$A-Z_][0-9A-Z_$]*$/i.test(key) ? key : JSON.stringify(key);
288
+ pluginsClientLines.push(` ${keyStr}?: ClientFactory<AnyContractRouter>;`);
289
+ }
264
290
  pluginsClientLines.push("};");
265
291
  }
266
292
  (0, node_fs.mkdirSync)((0, node_path.dirname)(pluginsClientPath), { recursive: true });
267
293
  writeFileIfChanged(pluginsClientPath, `${pluginsClientLines.join("\n")}\n`);
268
294
  }
295
+ const allSourcesForLookup = [...pluginSources];
296
+ if (opts.authSource) allSourcesForLookup.push({
297
+ ...opts.authSource,
298
+ key: "auth"
299
+ });
300
+ for (const pluginKey of opts.pluginKeys) {
301
+ const deps = opts.pluginDependsOn?.[pluginKey];
302
+ if (!deps?.length) continue;
303
+ const depSources = deps.map((depKey) => allSourcesForLookup.find((s) => s.key === depKey)).filter((s) => Boolean(s));
304
+ writePluginClientGen({
305
+ configDir: opts.configDir,
306
+ pluginKey,
307
+ depSources
308
+ });
309
+ }
269
310
  const authTypeTargets = [(0, node_path.join)(opts.configDir, "ui", "src", "lib", "auth-types.gen.ts")];
270
311
  const apiLibDir = (0, node_path.join)(opts.configDir, "api", "src", "lib");
271
312
  if ((0, node_fs.existsSync)(apiLibDir)) authTypeTargets.push((0, node_path.join)(apiLibDir, "auth-types.gen.ts"));
@@ -302,7 +343,8 @@ async function syncApiContractBridge(opts) {
302
343
  status.push({
303
344
  key: "api",
304
345
  source: opts.runtimeConfig.api.source,
305
- url: opts.runtimeConfig.api.source !== "local" ? opts.apiBaseUrl : void 0
346
+ url: opts.runtimeConfig.api.source !== "local" ? opts.apiBaseUrl : void 0,
347
+ localPath: opts.runtimeConfig.api.source === "local" ? opts.runtimeConfig.api.localPath : void 0
306
348
  });
307
349
  } catch (error) {
308
350
  const message = error instanceof Error ? error.message : String(error);
@@ -328,7 +370,8 @@ async function syncApiContractBridge(opts) {
328
370
  status.push({
329
371
  key: "auth",
330
372
  source: opts.runtimeConfig.auth.source,
331
- url: opts.runtimeConfig.auth.source !== "local" ? opts.runtimeConfig.auth.url : void 0
373
+ url: opts.runtimeConfig.auth.source !== "local" ? opts.runtimeConfig.auth.url : void 0,
374
+ localPath: opts.runtimeConfig.auth.source === "local" ? opts.runtimeConfig.auth.localPath : void 0
332
375
  });
333
376
  if (authSource.generatedPath) generatedPath = authSource.generatedPath;
334
377
  if (opts.runtimeConfig.auth.url && opts.runtimeConfig.auth.source !== "local") try {
@@ -389,7 +432,8 @@ async function syncApiContractBridge(opts) {
389
432
  status.push({
390
433
  key,
391
434
  source: plugin.source,
392
- url: plugin.source !== "local" ? plugin.url : void 0
435
+ url: plugin.source !== "local" ? plugin.url : void 0,
436
+ localPath: plugin.source === "local" ? plugin.localPath : void 0
393
437
  });
394
438
  if (result.value.source.generatedPath) generatedPath = result.value.source.generatedPath;
395
439
  } else {
@@ -407,12 +451,16 @@ async function syncApiContractBridge(opts) {
407
451
  const apiStatus = status.find((s) => s.key === "api");
408
452
  if (apiStatus?.source === "failed") throw new Error(`Cannot generate contract types without api contract: ${apiStatus.error ?? "unknown error"}`);
409
453
  const allPluginKeys = pluginEntries.filter(([key]) => !excludedPluginKeys.has(key)).map(([key]) => key);
454
+ const pluginDependsOn = {};
455
+ for (const [key, plugin] of pluginEntries) if (!excludedPluginKeys.has(key) && plugin.dependsOn?.length) pluginDependsOn[key] = plugin.dependsOn;
410
456
  writeGeneratedFiles({
411
457
  configDir: opts.configDir,
412
458
  sources,
413
459
  pluginKeys: allPluginKeys,
414
460
  authSource,
415
- authExportPath
461
+ authExportPath,
462
+ apiDependsOn: opts.runtimeConfig.api.dependsOn,
463
+ pluginDependsOn
416
464
  });
417
465
  if (opts.runtimeConfig.api.source !== "local") manifest = await fetchApiPluginManifest(opts.apiBaseUrl);
418
466
  return {
@@ -425,5 +473,7 @@ async function syncApiContractBridge(opts) {
425
473
  }
426
474
 
427
475
  //#endregion
476
+ exports.fetchApiPluginManifest = fetchApiPluginManifest;
428
477
  exports.syncApiContractBridge = syncApiContractBridge;
478
+ exports.writeGeneratedFiles = writeGeneratedFiles;
429
479
  //# sourceMappingURL=api-contract.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"api-contract.cjs","names":["fetchJsonOrNull","fetchResponse"],"sources":["../src/api-contract.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join, relative } from \"node:path\";\nimport { fetchJsonOrNull, fetchResponse } from \"./http-client\";\nimport type { 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}\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\nasync function fetchApiPluginManifest(apiBaseUrl: string): Promise<ApiPluginManifest> {\n const url = getApiPluginManifestUrl(apiBaseUrl);\n const manifest = await fetchJsonOrNull<ApiPluginManifest>(url, { retries: 0 });\n if (!manifest) {\n throw new Error(`Failed to fetch API plugin manifest from ${url}`);\n }\n if (manifest.schemaVersion !== 1 || manifest.kind !== \"every-plugin/manifest\") {\n throw new Error(\"Unsupported API plugin manifest format\");\n }\n\n return manifest;\n}\n\nfunction localApiContractSource(configDir: string): ContractSource {\n const sourcePath = join(configDir, \"api\", \"src\", \"contract.ts\");\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 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 const manifest = await fetchApiPluginManifest(opts.baseUrl);\n if (!manifest.contract) {\n throw new Error(\n `Plugin manifest for ${manifest.plugin.name} does not advertise contract types`,\n );\n }\n\n const contractUrl = `${trimTrailingSlash(opts.baseUrl)}/${manifest.contract.types.path.replace(/^\\.\\//, \"\")}`;\n const contractResponse = await fetchResponse(contractUrl);\n if (!contractResponse.ok) {\n throw new Error(\n `Failed to fetch contract types from ${contractUrl}: ${contractResponse.status} ${contractResponse.statusText}`,\n );\n }\n\n const contractTypes = await contractResponse.text();\n if (manifest.contract.types.sha256 && manifest.contract.types.sha256 !== sha256(contractTypes)) {\n throw new Error(\"Fetched contract types failed checksum verification\");\n }\n\n const generatedPath = join(opts.runtimeDir, opts.generatedSubdir, \"contract.d.ts\");\n mkdirSync(dirname(generatedPath), { recursive: true });\n writeFileIfChanged(generatedPath, contractTypes);\n\n return {\n key: opts.name,\n importName: `${sanitizeIdentifier(opts.name)}Contract`,\n sourceFilePath: generatedPath,\n generatedPath,\n };\n}\n\nasync function fetchAuthExportTypes(opts: {\n baseUrl: string;\n runtimeDir: string;\n manifest: ApiPluginManifest;\n}): Promise<string | null> {\n if (!opts.manifest.additionalExports || opts.manifest.additionalExports.length === 0) {\n return null;\n }\n\n const authExportEntry = opts.manifest.additionalExports.find(\n (entry) => entry.path.includes(\"auth-export\") || entry.path.endsWith(\"auth-export.d.ts\"),\n );\n\n if (!authExportEntry) {\n return null;\n }\n\n const exportUrl = `${trimTrailingSlash(opts.baseUrl)}/${authExportEntry.path.replace(/^\\.\\//, \"\")}`;\n const response = await fetchResponse(exportUrl);\n if (!response.ok) {\n console.warn(\n `[API Contract] Failed to fetch auth export types from ${exportUrl}: ${response.status}`,\n );\n return null;\n }\n\n const content = await response.text();\n if (authExportEntry.sha256 && authExportEntry.sha256 !== sha256(content)) {\n console.warn(`[API Contract] Auth export types checksum mismatch for ${exportUrl}`);\n return null;\n }\n\n const generatedPath = join(opts.runtimeDir, \"auth\", \"auth-export.d.ts\");\n mkdirSync(dirname(generatedPath), { recursive: true });\n writeFileIfChanged(generatedPath, content);\n\n return generatedPath;\n}\n\nfunction writeAuthTypesGen(targetPath: string, authExportPath: string) {\n const exportImportPath = toImportPath(targetPath, authExportPath);\n const content = [\n `export type {`,\n ` Auth,`,\n ` AuthOrganizationContext,`,\n ` AuthOrganization,`,\n ` AuthOrganizationSummary,`,\n ` AuthOrganizationMember,`,\n ` AuthApiKey,`,\n ` AuthInvitation,`,\n ` GetActiveMemberInput,`,\n ` GetOrganizationInput,`,\n ` ListMembersInput,`,\n ` ListInvitationsInput,`,\n ` ListApiKeysInput,`,\n ` AuthServices,`,\n ` createAuthInstance,`,\n `} from \"${exportImportPath}\";`,\n `import type { InferOutput, ContractType as AuthContract } from \"${toImportPath(targetPath, join(dirname(authExportPath), \"contract.d.ts\"))}\";`,\n `import type { Auth as BaseAuth } from \"${exportImportPath}\";`,\n \"\",\n 'type RawAuthSession = InferOutput<\"getSession\">;',\n 'type RawAuthRequestContext = InferOutput<\"getContext\">;',\n 'type RawAuthActiveMember = InferOutput<\"getActiveMember\">;',\n \"\",\n 'export type AuthSessionUser = NonNullable<RawAuthSession[\"user\"]>;',\n 'export type AuthSessionData = NonNullable<RawAuthSession[\"session\"]>;',\n \"export type AuthSession = {\",\n \" user: AuthSessionUser | null;\",\n \" session: AuthSessionData | null;\",\n \"};\",\n \"export type AuthRequestContext = RawAuthRequestContext;\",\n \"export type AuthPluginContext = Partial<AuthRequestContext> & {\",\n \" reqHeaders?: Headers;\",\n \" getRawBody?: () => Promise<string>;\",\n \"};\",\n \"export type AuthActiveMember = RawAuthActiveMember;\",\n 'export type AuthBaseSession = BaseAuth[\"$Infer\"][\"Session\"];',\n \"export type AuthContractType = AuthContract;\",\n \"\",\n ].join(\"\\n\");\n mkdirSync(dirname(targetPath), { recursive: true });\n writeFileIfChanged(targetPath, content);\n}\n\nfunction writeContractBasedAuthTypesGen(targetPath: string, configDir: string) {\n const authExportRel = toImportPath(\n targetPath,\n join(configDir, \".bos\", \"generated\", \"auth\", \"auth-export.d.ts\"),\n );\n const contractRel = toImportPath(\n targetPath,\n join(configDir, \".bos\", \"generated\", \"auth\", \"contract.d.ts\"),\n );\n\n const content = [\n `export type {`,\n ` Auth,`,\n ` AuthOrganizationContext,`,\n ` AuthOrganization,`,\n ` AuthOrganizationSummary,`,\n ` AuthOrganizationMember,`,\n ` AuthApiKey,`,\n ` AuthInvitation,`,\n ` GetActiveMemberInput,`,\n ` GetOrganizationInput,`,\n ` ListMembersInput,`,\n ` ListInvitationsInput,`,\n ` ListApiKeysInput,`,\n ` AuthServices,`,\n ` createAuthInstance,`,\n `} from \"${authExportRel}\";`,\n `import type { InferOutput, ContractType as AuthContract } from \"${contractRel}\";`,\n `import type { Auth as BaseAuth } from \"${authExportRel}\";`,\n \"\",\n 'type RawAuthSession = InferOutput<\"getSession\">;',\n 'type RawAuthRequestContext = InferOutput<\"getContext\">;',\n 'type RawAuthActiveMember = InferOutput<\"getActiveMember\">;',\n \"\",\n 'export type AuthSessionUser = NonNullable<RawAuthSession[\"user\"]>;',\n 'export type AuthSessionData = NonNullable<RawAuthSession[\"session\"]>;',\n \"export type AuthSession = {\",\n \" user: AuthSessionUser | null;\",\n \" session: AuthSessionData | null;\",\n \"};\",\n \"export type AuthRequestContext = RawAuthRequestContext;\",\n \"export type AuthPluginContext = Partial<AuthRequestContext> & {\",\n \" reqHeaders?: Headers;\",\n \" getRawBody?: () => Promise<string>;\",\n \"};\",\n \"export type AuthActiveMember = RawAuthActiveMember;\",\n 'export type AuthBaseSession = BaseAuth[\"$Infer\"][\"Session\"];',\n \"export type AuthContractType = AuthContract;\",\n \"\",\n ].join(\"\\n\");\n mkdirSync(dirname(targetPath), { recursive: true });\n writeFileIfChanged(targetPath, content);\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 writeGeneratedFiles(opts: {\n configDir: string;\n sources: ContractSource[];\n pluginKeys: string[];\n authSource: ContractSource | null;\n authExportPath?: string | null;\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 // Includes both plugin contracts AND auth as a unified PluginsClient type\n if (hasLocalApiWorkspace) {\n const pluginsClientPath = join(opts.configDir, \"api\", \"src\", \"lib\", \"plugins-types.gen.ts\");\n const pluginsClientLines: string[] = [];\n\n for (const source of pluginSources) {\n const importPath = toImportPath(pluginsClientPath, source.sourceFilePath);\n pluginsClientLines.push(\n `import type { ContractType as ${source.importName} } from \"${importPath}\";`,\n );\n }\n\n if (opts.authSource) {\n const authImportPath = toImportPath(pluginsClientPath, opts.authSource.sourceFilePath);\n pluginsClientLines.push(\n `import type { ContractType as ${opts.authSource.importName} } from \"${authImportPath}\";`,\n );\n }\n\n pluginsClientLines.push(\n 'import type { ContractRouterClient, AnyContractRouter } from \"@orpc/contract\";',\n );\n pluginsClientLines.push(\n \"type ClientFactory<C extends AnyContractRouter> = (context?: Record<string, unknown>) => ContractRouterClient<C>;\",\n );\n pluginsClientLines.push(\"\");\n\n const allPluginSources = [...pluginSources];\n if (opts.authSource) {\n allPluginSources.push({ ...opts.authSource, key: \"auth\" });\n }\n\n if (allPluginSources.length === 0) {\n pluginsClientLines.push(\"export type PluginsClient = Record<string, never>;\");\n } else {\n pluginsClientLines.push(\"export type PluginsClient = {\");\n for (const source of allPluginSources) {\n const key = /^[$A-Z_][0-9A-Z_$]*$/i.test(source.key)\n ? source.key\n : JSON.stringify(source.key);\n pluginsClientLines.push(` ${key}: ClientFactory<${source.importName}>;`);\n }\n pluginsClientLines.push(\"};\");\n }\n\n mkdirSync(dirname(pluginsClientPath), { recursive: true });\n writeFileIfChanged(pluginsClientPath, `${pluginsClientLines.join(\"\\n\")}\\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 pluginLibDir = join(opts.configDir, \"plugins\", key, \"src\", \"lib\");\n if (existsSync(join(opts.configDir, \"plugins\", key, \"src\"))) {\n authTypeTargets.push(join(pluginLibDir, \"auth-types.gen.ts\"));\n }\n }\n\n if (opts.authExportPath) {\n for (const authTypesPath of authTypeTargets) {\n writeAuthTypesGen(authTypesPath, opts.authExportPath);\n }\n } else if (opts.authSource) {\n for (const authTypesPath of authTypeTargets) {\n writeContractBasedAuthTypesGen(authTypesPath, opts.configDir);\n }\n }\n\n return uiContractPath;\n}\n\nexport interface ContractBridgeStatus {\n key: string;\n source: \"local\" | \"remote\" | \"skipped\" | \"failed\";\n url?: 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 pluginEntries = Object.entries(opts.runtimeConfig.plugins ?? {}).sort(([a], [b]) =>\n a.localeCompare(b),\n );\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 });\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 });\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 });\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 writeGeneratedFiles({\n configDir: opts.configDir,\n sources,\n pluginKeys: allPluginKeys,\n authSource,\n authExportPath,\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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"}
1
+ {"version":3,"file":"api-contract.cjs","names":["fetchJsonOrNull","fetchResponse"],"sources":["../src/api-contract.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join, relative } from \"node:path\";\nimport { fetchJsonOrNull, fetchResponse } from \"./http-client\";\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\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 const url = getApiPluginManifestUrl(apiBaseUrl);\n const manifest = await fetchJsonOrNull<ApiPluginManifest>(url, { retries: 0 });\n if (!manifest) {\n throw new Error(`Failed to fetch API plugin manifest from ${url}`);\n }\n if (manifest.schemaVersion !== 1 || manifest.kind !== \"every-plugin/manifest\") {\n throw new Error(\"Unsupported API plugin manifest format\");\n }\n\n return manifest;\n}\n\nfunction localApiContractSource(configDir: string): ContractSource {\n const sourcePath = join(configDir, \"api\", \"src\", \"contract.ts\");\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 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 const manifest = await fetchApiPluginManifest(opts.baseUrl);\n if (!manifest.contract) {\n throw new Error(\n `Plugin manifest for ${manifest.plugin.name} does not advertise contract types`,\n );\n }\n\n const contractUrl = `${trimTrailingSlash(opts.baseUrl)}/${manifest.contract.types.path.replace(/^\\.\\//, \"\")}`;\n const contractResponse = await fetchResponse(contractUrl);\n if (!contractResponse.ok) {\n throw new Error(\n `Failed to fetch contract types from ${contractUrl}: ${contractResponse.status} ${contractResponse.statusText}`,\n );\n }\n\n const contractTypes = await contractResponse.text();\n if (manifest.contract.types.sha256 && manifest.contract.types.sha256 !== sha256(contractTypes)) {\n throw new Error(\"Fetched contract types failed checksum verification\");\n }\n\n const generatedPath = join(opts.runtimeDir, opts.generatedSubdir, \"contract.d.ts\");\n mkdirSync(dirname(generatedPath), { recursive: true });\n writeFileIfChanged(generatedPath, contractTypes);\n\n return {\n key: opts.name,\n importName: `${sanitizeIdentifier(opts.name)}Contract`,\n sourceFilePath: generatedPath,\n generatedPath,\n };\n}\n\nasync function fetchAuthExportTypes(opts: {\n baseUrl: string;\n runtimeDir: string;\n manifest: ApiPluginManifest;\n}): Promise<string | null> {\n if (!opts.manifest.additionalExports || opts.manifest.additionalExports.length === 0) {\n return null;\n }\n\n const authExportEntry = opts.manifest.additionalExports.find(\n (entry) => entry.path.includes(\"auth-export\") || entry.path.endsWith(\"auth-export.d.ts\"),\n );\n\n if (!authExportEntry) {\n return null;\n }\n\n const exportUrl = `${trimTrailingSlash(opts.baseUrl)}/${authExportEntry.path.replace(/^\\.\\//, \"\")}`;\n const response = await fetchResponse(exportUrl);\n if (!response.ok) {\n console.warn(\n `[API Contract] Failed to fetch auth export types from ${exportUrl}: ${response.status}`,\n );\n return null;\n }\n\n const content = await response.text();\n if (authExportEntry.sha256 && authExportEntry.sha256 !== sha256(content)) {\n console.warn(`[API Contract] Auth export types checksum mismatch for ${exportUrl}`);\n return null;\n }\n\n const generatedPath = join(opts.runtimeDir, \"auth\", \"auth-export.d.ts\");\n mkdirSync(dirname(generatedPath), { recursive: true });\n writeFileIfChanged(generatedPath, content);\n\n return generatedPath;\n}\n\nfunction writeAuthTypesGen(targetPath: string, authExportPath: string) {\n const exportImportPath = toImportPath(targetPath, authExportPath);\n const content = [\n `export type {`,\n ` Auth,`,\n ` AuthOrganizationContext,`,\n ` AuthOrganization,`,\n ` AuthOrganizationSummary,`,\n ` AuthOrganizationMember,`,\n ` AuthApiKey,`,\n ` AuthInvitation,`,\n ` GetActiveMemberInput,`,\n ` GetOrganizationInput,`,\n ` ListMembersInput,`,\n ` ListInvitationsInput,`,\n ` ListApiKeysInput,`,\n ` AuthServices,`,\n ` createAuthInstance,`,\n `} from \"${exportImportPath}\";`,\n `import type { InferOutput, ContractType as AuthContract } from \"${toImportPath(targetPath, join(dirname(authExportPath), \"contract.d.ts\"))}\";`,\n `import type { Auth as BaseAuth } from \"${exportImportPath}\";`,\n \"\",\n 'type RawAuthSession = InferOutput<\"getSession\">;',\n 'type RawAuthRequestContext = InferOutput<\"getContext\">;',\n 'type RawAuthActiveMember = InferOutput<\"getActiveMember\">;',\n \"\",\n 'export type AuthSessionUser = NonNullable<RawAuthSession[\"user\"]>;',\n 'export type AuthSessionData = NonNullable<RawAuthSession[\"session\"]>;',\n \"export type AuthSession = {\",\n \" user: AuthSessionUser | null;\",\n \" session: AuthSessionData | null;\",\n \"};\",\n \"export type AuthRequestContext = RawAuthRequestContext;\",\n \"export type AuthPluginContext = Partial<AuthRequestContext> & {\",\n \" reqHeaders?: Headers;\",\n \" getRawBody?: () => Promise<string>;\",\n \"};\",\n \"export type AuthActiveMember = RawAuthActiveMember;\",\n 'export type AuthBaseSession = BaseAuth[\"$Infer\"][\"Session\"];',\n \"export type AuthContractType = AuthContract;\",\n \"\",\n ].join(\"\\n\");\n mkdirSync(dirname(targetPath), { recursive: true });\n writeFileIfChanged(targetPath, content);\n}\n\nfunction writeContractBasedAuthTypesGen(targetPath: string, configDir: string) {\n const authExportRel = toImportPath(\n targetPath,\n join(configDir, \".bos\", \"generated\", \"auth\", \"auth-export.d.ts\"),\n );\n const contractRel = toImportPath(\n targetPath,\n join(configDir, \".bos\", \"generated\", \"auth\", \"contract.d.ts\"),\n );\n\n const content = [\n `export type {`,\n ` Auth,`,\n ` AuthOrganizationContext,`,\n ` AuthOrganization,`,\n ` AuthOrganizationSummary,`,\n ` AuthOrganizationMember,`,\n ` AuthApiKey,`,\n ` AuthInvitation,`,\n ` GetActiveMemberInput,`,\n ` GetOrganizationInput,`,\n ` ListMembersInput,`,\n ` ListInvitationsInput,`,\n ` ListApiKeysInput,`,\n ` AuthServices,`,\n ` createAuthInstance,`,\n `} from \"${authExportRel}\";`,\n `import type { InferOutput, ContractType as AuthContract } from \"${contractRel}\";`,\n `import type { Auth as BaseAuth } from \"${authExportRel}\";`,\n \"\",\n 'type RawAuthSession = InferOutput<\"getSession\">;',\n 'type RawAuthRequestContext = InferOutput<\"getContext\">;',\n 'type RawAuthActiveMember = InferOutput<\"getActiveMember\">;',\n \"\",\n 'export type AuthSessionUser = NonNullable<RawAuthSession[\"user\"]>;',\n 'export type AuthSessionData = NonNullable<RawAuthSession[\"session\"]>;',\n \"export type AuthSession = {\",\n \" user: AuthSessionUser | null;\",\n \" session: AuthSessionData | null;\",\n \"};\",\n \"export type AuthRequestContext = RawAuthRequestContext;\",\n \"export type AuthPluginContext = Partial<AuthRequestContext> & {\",\n \" reqHeaders?: Headers;\",\n \" getRawBody?: () => Promise<string>;\",\n \"};\",\n \"export type AuthActiveMember = RawAuthActiveMember;\",\n 'export type AuthBaseSession = BaseAuth[\"$Infer\"][\"Session\"];',\n \"export type AuthContractType = AuthContract;\",\n \"\",\n ].join(\"\\n\");\n mkdirSync(dirname(targetPath), { recursive: true });\n writeFileIfChanged(targetPath, content);\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}) {\n const pluginSrcDir = join(opts.configDir, \"plugins\", opts.pluginKey, \"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 { ContractRouterClient, AnyContractRouter } from \"@orpc/contract\";');\n lines.push(\n \"type ClientFactory<C extends AnyContractRouter> = (context?: Record<string, unknown>) => ContractRouterClient<C>;\",\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}: ClientFactory<${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}) {\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 { ContractRouterClient, AnyContractRouter } from \"@orpc/contract\";',\n );\n pluginsClientLines.push(\n \"type ClientFactory<C extends AnyContractRouter> = (context?: Record<string, unknown>) => ContractRouterClient<C>;\",\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}: ClientFactory<${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}?: ClientFactory<AnyContractRouter>;`);\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 deps = opts.pluginDependsOn?.[pluginKey];\n if (!deps?.length) continue;\n\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 });\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 pluginLibDir = join(opts.configDir, \"plugins\", key, \"src\", \"lib\");\n if (existsSync(join(opts.configDir, \"plugins\", key, \"src\"))) {\n authTypeTargets.push(join(pluginLibDir, \"auth-types.gen.ts\"));\n }\n }\n\n if (opts.authExportPath) {\n for (const authTypesPath of authTypeTargets) {\n writeAuthTypesGen(authTypesPath, opts.authExportPath);\n }\n } else if (opts.authSource) {\n for (const authTypesPath of authTypeTargets) {\n writeContractBasedAuthTypesGen(authTypesPath, opts.configDir);\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 pluginEntries = Object.entries(opts.runtimeConfig.plugins ?? {}).sort(([a], [b]) =>\n a.localeCompare(b),\n );\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 for (const [key, plugin] of pluginEntries) {\n if (!excludedPluginKeys.has(key) && plugin.dependsOn?.length) {\n pluginDependsOn[key] = plugin.dependsOn;\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 });\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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"}
@@ -209,6 +209,30 @@ async function resolveContractSource(opts) {
209
209
  generatedSubdir: opts.generatedSubdir
210
210
  });
211
211
  }
212
+ function writePluginClientGen(opts) {
213
+ const pluginSrcDir = join(opts.configDir, "plugins", opts.pluginKey, "src");
214
+ if (!existsSync(pluginSrcDir)) return;
215
+ const targetPath = join(pluginSrcDir, "lib", "plugins-client.gen.ts");
216
+ const lines = [];
217
+ for (const source of opts.depSources) {
218
+ const importPath = toImportPath(targetPath, source.sourceFilePath);
219
+ lines.push(`import type { ContractType as ${source.importName} } from "${importPath}";`);
220
+ }
221
+ lines.push("import type { ContractRouterClient, AnyContractRouter } from \"@orpc/contract\";");
222
+ lines.push("type ClientFactory<C extends AnyContractRouter> = (context?: Record<string, unknown>) => ContractRouterClient<C>;");
223
+ lines.push("");
224
+ if (opts.depSources.length === 0) lines.push("export type PluginsClient = Record<string, never>;");
225
+ else {
226
+ lines.push("export type PluginsClient = {");
227
+ for (const source of opts.depSources) {
228
+ const key = /^[$A-Z_][0-9A-Z_$]*$/i.test(source.key) ? source.key : JSON.stringify(source.key);
229
+ lines.push(` ${key}: ClientFactory<${source.importName}>;`);
230
+ }
231
+ lines.push("};");
232
+ }
233
+ mkdirSync(dirname(targetPath), { recursive: true });
234
+ writeFileIfChanged(targetPath, `${lines.join("\n")}\n`);
235
+ }
212
236
  function writeGeneratedFiles(opts) {
213
237
  const hasLocalApiWorkspace = existsSync(join(opts.configDir, "api", "src"));
214
238
  const baseSource = opts.sources.find((source) => source.key === "api");
@@ -238,34 +262,51 @@ function writeGeneratedFiles(opts) {
238
262
  if (hasLocalApiWorkspace) {
239
263
  const pluginsClientPath = join(opts.configDir, "api", "src", "lib", "plugins-types.gen.ts");
240
264
  const pluginsClientLines = [];
241
- for (const source of pluginSources) {
265
+ const allPluginSources = [...pluginSources];
266
+ if (opts.authSource) allPluginSources.push({
267
+ ...opts.authSource,
268
+ key: "auth"
269
+ });
270
+ const apiDepSources = opts.apiDependsOn?.length ? allPluginSources.filter((s) => opts.apiDependsOn.includes(s.key)) : allPluginSources;
271
+ const unresolvedDepKeys = opts.apiDependsOn?.filter((depKey) => !allPluginSources.some((s) => s.key === depKey)) ?? [];
272
+ for (const source of apiDepSources) {
242
273
  const importPath = toImportPath(pluginsClientPath, source.sourceFilePath);
243
274
  pluginsClientLines.push(`import type { ContractType as ${source.importName} } from "${importPath}";`);
244
275
  }
245
- if (opts.authSource) {
246
- const authImportPath = toImportPath(pluginsClientPath, opts.authSource.sourceFilePath);
247
- pluginsClientLines.push(`import type { ContractType as ${opts.authSource.importName} } from "${authImportPath}";`);
248
- }
249
276
  pluginsClientLines.push("import type { ContractRouterClient, AnyContractRouter } from \"@orpc/contract\";");
250
277
  pluginsClientLines.push("type ClientFactory<C extends AnyContractRouter> = (context?: Record<string, unknown>) => ContractRouterClient<C>;");
251
278
  pluginsClientLines.push("");
252
- const allPluginSources = [...pluginSources];
253
- if (opts.authSource) allPluginSources.push({
254
- ...opts.authSource,
255
- key: "auth"
256
- });
257
- if (allPluginSources.length === 0) pluginsClientLines.push("export type PluginsClient = Record<string, never>;");
279
+ if (apiDepSources.length === 0 && unresolvedDepKeys.length === 0) pluginsClientLines.push("export type PluginsClient = Record<string, never>;");
258
280
  else {
259
281
  pluginsClientLines.push("export type PluginsClient = {");
260
- for (const source of allPluginSources) {
282
+ for (const source of apiDepSources) {
261
283
  const key = /^[$A-Z_][0-9A-Z_$]*$/i.test(source.key) ? source.key : JSON.stringify(source.key);
262
284
  pluginsClientLines.push(` ${key}: ClientFactory<${source.importName}>;`);
263
285
  }
286
+ for (const key of unresolvedDepKeys) {
287
+ const keyStr = /^[$A-Z_][0-9A-Z_$]*$/i.test(key) ? key : JSON.stringify(key);
288
+ pluginsClientLines.push(` ${keyStr}?: ClientFactory<AnyContractRouter>;`);
289
+ }
264
290
  pluginsClientLines.push("};");
265
291
  }
266
292
  mkdirSync(dirname(pluginsClientPath), { recursive: true });
267
293
  writeFileIfChanged(pluginsClientPath, `${pluginsClientLines.join("\n")}\n`);
268
294
  }
295
+ const allSourcesForLookup = [...pluginSources];
296
+ if (opts.authSource) allSourcesForLookup.push({
297
+ ...opts.authSource,
298
+ key: "auth"
299
+ });
300
+ for (const pluginKey of opts.pluginKeys) {
301
+ const deps = opts.pluginDependsOn?.[pluginKey];
302
+ if (!deps?.length) continue;
303
+ const depSources = deps.map((depKey) => allSourcesForLookup.find((s) => s.key === depKey)).filter((s) => Boolean(s));
304
+ writePluginClientGen({
305
+ configDir: opts.configDir,
306
+ pluginKey,
307
+ depSources
308
+ });
309
+ }
269
310
  const authTypeTargets = [join(opts.configDir, "ui", "src", "lib", "auth-types.gen.ts")];
270
311
  const apiLibDir = join(opts.configDir, "api", "src", "lib");
271
312
  if (existsSync(apiLibDir)) authTypeTargets.push(join(apiLibDir, "auth-types.gen.ts"));
@@ -302,7 +343,8 @@ async function syncApiContractBridge(opts) {
302
343
  status.push({
303
344
  key: "api",
304
345
  source: opts.runtimeConfig.api.source,
305
- url: opts.runtimeConfig.api.source !== "local" ? opts.apiBaseUrl : void 0
346
+ url: opts.runtimeConfig.api.source !== "local" ? opts.apiBaseUrl : void 0,
347
+ localPath: opts.runtimeConfig.api.source === "local" ? opts.runtimeConfig.api.localPath : void 0
306
348
  });
307
349
  } catch (error) {
308
350
  const message = error instanceof Error ? error.message : String(error);
@@ -328,7 +370,8 @@ async function syncApiContractBridge(opts) {
328
370
  status.push({
329
371
  key: "auth",
330
372
  source: opts.runtimeConfig.auth.source,
331
- url: opts.runtimeConfig.auth.source !== "local" ? opts.runtimeConfig.auth.url : void 0
373
+ url: opts.runtimeConfig.auth.source !== "local" ? opts.runtimeConfig.auth.url : void 0,
374
+ localPath: opts.runtimeConfig.auth.source === "local" ? opts.runtimeConfig.auth.localPath : void 0
332
375
  });
333
376
  if (authSource.generatedPath) generatedPath = authSource.generatedPath;
334
377
  if (opts.runtimeConfig.auth.url && opts.runtimeConfig.auth.source !== "local") try {
@@ -389,7 +432,8 @@ async function syncApiContractBridge(opts) {
389
432
  status.push({
390
433
  key,
391
434
  source: plugin.source,
392
- url: plugin.source !== "local" ? plugin.url : void 0
435
+ url: plugin.source !== "local" ? plugin.url : void 0,
436
+ localPath: plugin.source === "local" ? plugin.localPath : void 0
393
437
  });
394
438
  if (result.value.source.generatedPath) generatedPath = result.value.source.generatedPath;
395
439
  } else {
@@ -407,12 +451,16 @@ async function syncApiContractBridge(opts) {
407
451
  const apiStatus = status.find((s) => s.key === "api");
408
452
  if (apiStatus?.source === "failed") throw new Error(`Cannot generate contract types without api contract: ${apiStatus.error ?? "unknown error"}`);
409
453
  const allPluginKeys = pluginEntries.filter(([key]) => !excludedPluginKeys.has(key)).map(([key]) => key);
454
+ const pluginDependsOn = {};
455
+ for (const [key, plugin] of pluginEntries) if (!excludedPluginKeys.has(key) && plugin.dependsOn?.length) pluginDependsOn[key] = plugin.dependsOn;
410
456
  writeGeneratedFiles({
411
457
  configDir: opts.configDir,
412
458
  sources,
413
459
  pluginKeys: allPluginKeys,
414
460
  authSource,
415
- authExportPath
461
+ authExportPath,
462
+ apiDependsOn: opts.runtimeConfig.api.dependsOn,
463
+ pluginDependsOn
416
464
  });
417
465
  if (opts.runtimeConfig.api.source !== "local") manifest = await fetchApiPluginManifest(opts.apiBaseUrl);
418
466
  return {
@@ -425,5 +473,5 @@ async function syncApiContractBridge(opts) {
425
473
  }
426
474
 
427
475
  //#endregion
428
- export { syncApiContractBridge };
476
+ export { fetchApiPluginManifest, syncApiContractBridge, writeGeneratedFiles };
429
477
  //# sourceMappingURL=api-contract.mjs.map