everything-dev 1.44.0 → 1.44.1
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.
- package/dist/api-contract.cjs +26 -21
- package/dist/api-contract.cjs.map +1 -1
- package/dist/api-contract.mjs +27 -22
- package/dist/api-contract.mjs.map +1 -1
- package/dist/cli/catalog.cjs +2 -2
- package/dist/cli/catalog.cjs.map +1 -1
- package/dist/cli/catalog.mjs +2 -2
- package/dist/cli/catalog.mjs.map +1 -1
- package/dist/cli/infra.cjs +3 -0
- package/dist/cli/infra.cjs.map +1 -1
- package/dist/cli/infra.mjs +3 -0
- package/dist/cli/infra.mjs.map +1 -1
- package/dist/cli/init.cjs +5 -2
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.d.cts +1 -1
- package/dist/cli/init.d.cts.map +1 -1
- package/dist/cli/init.d.mts +1 -1
- package/dist/cli/init.d.mts.map +1 -1
- package/dist/cli/init.mjs +5 -2
- package/dist/cli/init.mjs.map +1 -1
- package/dist/cli/status.cjs +8 -19
- package/dist/cli/status.cjs.map +1 -1
- package/dist/cli/status.mjs +8 -19
- package/dist/cli/status.mjs.map +1 -1
- package/dist/cli.cjs +9 -4
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +9 -4
- package/dist/cli.mjs.map +1 -1
- package/dist/config.cjs +22 -11
- package/dist/config.cjs.map +1 -1
- package/dist/config.d.cts.map +1 -1
- package/dist/config.d.mts.map +1 -1
- package/dist/config.mjs +22 -11
- package/dist/config.mjs.map +1 -1
- package/dist/contract.cjs +6 -5
- package/dist/contract.cjs.map +1 -1
- package/dist/contract.d.cts +12 -4
- package/dist/contract.d.cts.map +1 -1
- package/dist/contract.d.mts +12 -4
- package/dist/contract.d.mts.map +1 -1
- package/dist/contract.mjs +6 -5
- package/dist/contract.mjs.map +1 -1
- package/dist/dev-session.cjs +3 -1
- package/dist/dev-session.cjs.map +1 -1
- package/dist/dev-session.mjs +3 -1
- package/dist/dev-session.mjs.map +1 -1
- package/dist/fastkv.cjs +2 -1
- package/dist/fastkv.cjs.map +1 -1
- package/dist/fastkv.mjs +2 -1
- package/dist/fastkv.mjs.map +1 -1
- package/dist/http-client.cjs +22 -2
- package/dist/http-client.cjs.map +1 -1
- package/dist/http-client.mjs +22 -2
- package/dist/http-client.mjs.map +1 -1
- package/dist/orchestrator.cjs +39 -23
- package/dist/orchestrator.cjs.map +1 -1
- package/dist/orchestrator.mjs +39 -23
- package/dist/orchestrator.mjs.map +1 -1
- package/dist/plugin.cjs +53 -63
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +4 -0
- package/dist/plugin.d.mts +4 -0
- package/dist/plugin.mjs +53 -63
- package/dist/plugin.mjs.map +1 -1
- package/package.json +1 -1
package/dist/api-contract.cjs
CHANGED
|
@@ -30,9 +30,8 @@ function getApiPluginManifestUrl(apiBaseUrl) {
|
|
|
30
30
|
}
|
|
31
31
|
async function fetchApiPluginManifest(apiBaseUrl) {
|
|
32
32
|
const url = getApiPluginManifestUrl(apiBaseUrl);
|
|
33
|
-
const
|
|
34
|
-
if (!
|
|
35
|
-
const manifest = await response.json();
|
|
33
|
+
const manifest = await require_http_client.fetchJsonOrNull(url, { retries: 0 });
|
|
34
|
+
if (!manifest) throw new Error(`Failed to fetch API plugin manifest from ${url}`);
|
|
36
35
|
if (manifest.schemaVersion !== 1 || manifest.kind !== "every-plugin/manifest") throw new Error("Unsupported API plugin manifest format");
|
|
37
36
|
return manifest;
|
|
38
37
|
}
|
|
@@ -362,34 +361,40 @@ async function syncApiContractBridge(opts) {
|
|
|
362
361
|
error: message
|
|
363
362
|
});
|
|
364
363
|
}
|
|
365
|
-
for (const [key, plugin] of pluginEntries) {
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
364
|
+
for (const [key, plugin] of pluginEntries) if (!plugin.url && !plugin.localPath) {
|
|
365
|
+
console.warn(`[API Contract] Skipping plugin "${key}" — no URL resolved (local path missing and no production URL configured)`);
|
|
366
|
+
status.push({
|
|
367
|
+
key,
|
|
368
|
+
source: "skipped"
|
|
369
|
+
});
|
|
370
|
+
excludedPluginKeys.add(key);
|
|
371
|
+
}
|
|
372
|
+
const resolvablePlugins = pluginEntries.filter(([key]) => !excludedPluginKeys.has(key));
|
|
373
|
+
(await Promise.allSettled(resolvablePlugins.map(async ([key, plugin]) => {
|
|
374
|
+
return {
|
|
375
|
+
key,
|
|
376
|
+
source: await resolveContractSource({
|
|
377
377
|
configDir: opts.configDir,
|
|
378
378
|
runtimeDir,
|
|
379
379
|
key,
|
|
380
380
|
source: plugin,
|
|
381
381
|
baseUrl: plugin.url,
|
|
382
382
|
generatedSubdir: `plugins/${key}`
|
|
383
|
-
})
|
|
384
|
-
|
|
383
|
+
}),
|
|
384
|
+
plugin
|
|
385
|
+
};
|
|
386
|
+
}))).forEach((result, index) => {
|
|
387
|
+
const [key, plugin] = resolvablePlugins[index];
|
|
388
|
+
if (result.status === "fulfilled") {
|
|
389
|
+
sources.push(result.value.source);
|
|
385
390
|
status.push({
|
|
386
391
|
key,
|
|
387
392
|
source: plugin.source,
|
|
388
393
|
url: plugin.source !== "local" ? plugin.url : void 0
|
|
389
394
|
});
|
|
390
|
-
if (source.generatedPath) generatedPath = source.generatedPath;
|
|
391
|
-
}
|
|
392
|
-
const message =
|
|
395
|
+
if (result.value.source.generatedPath) generatedPath = result.value.source.generatedPath;
|
|
396
|
+
} else {
|
|
397
|
+
const message = result.reason instanceof Error ? result.reason.message : String(result.reason);
|
|
393
398
|
console.warn(`[API Contract] Failed to resolve plugin "${key}": ${message}`);
|
|
394
399
|
status.push({
|
|
395
400
|
key,
|
|
@@ -399,7 +404,7 @@ async function syncApiContractBridge(opts) {
|
|
|
399
404
|
});
|
|
400
405
|
excludedPluginKeys.add(key);
|
|
401
406
|
}
|
|
402
|
-
}
|
|
407
|
+
});
|
|
403
408
|
const apiStatus = status.find((s) => s.key === "api");
|
|
404
409
|
if (apiStatus?.source === "failed") throw new Error(`Cannot generate contract types without api contract: ${apiStatus.error ?? "unknown error"}`);
|
|
405
410
|
const allPluginKeys = pluginEntries.filter(([key]) => !excludedPluginKeys.has(key)).map(([key]) => key);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-contract.cjs","names":["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 { 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 response = await fetchResponse(url);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch API plugin manifest from ${url}: ${response.status} ${response.statusText}`,\n );\n }\n\n const manifest = (await response.json()) as ApiPluginManifest;\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 continue;\n }\n try {\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 sources.push(source);\n status.push({\n key,\n source: plugin.source,\n url: plugin.source !== \"local\" ? plugin.url : undefined,\n });\n if (source.generatedPath) {\n generatedPath = source.generatedPath;\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\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 { 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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"}
|
package/dist/api-contract.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fetchResponse } from "./http-client.mjs";
|
|
1
|
+
import { fetchJsonOrNull, fetchResponse } from "./http-client.mjs";
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { dirname, join, relative } from "node:path";
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
@@ -29,9 +29,8 @@ function getApiPluginManifestUrl(apiBaseUrl) {
|
|
|
29
29
|
}
|
|
30
30
|
async function fetchApiPluginManifest(apiBaseUrl) {
|
|
31
31
|
const url = getApiPluginManifestUrl(apiBaseUrl);
|
|
32
|
-
const
|
|
33
|
-
if (!
|
|
34
|
-
const manifest = await response.json();
|
|
32
|
+
const manifest = await fetchJsonOrNull(url, { retries: 0 });
|
|
33
|
+
if (!manifest) throw new Error(`Failed to fetch API plugin manifest from ${url}`);
|
|
35
34
|
if (manifest.schemaVersion !== 1 || manifest.kind !== "every-plugin/manifest") throw new Error("Unsupported API plugin manifest format");
|
|
36
35
|
return manifest;
|
|
37
36
|
}
|
|
@@ -361,34 +360,40 @@ async function syncApiContractBridge(opts) {
|
|
|
361
360
|
error: message
|
|
362
361
|
});
|
|
363
362
|
}
|
|
364
|
-
for (const [key, plugin] of pluginEntries) {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
363
|
+
for (const [key, plugin] of pluginEntries) if (!plugin.url && !plugin.localPath) {
|
|
364
|
+
console.warn(`[API Contract] Skipping plugin "${key}" — no URL resolved (local path missing and no production URL configured)`);
|
|
365
|
+
status.push({
|
|
366
|
+
key,
|
|
367
|
+
source: "skipped"
|
|
368
|
+
});
|
|
369
|
+
excludedPluginKeys.add(key);
|
|
370
|
+
}
|
|
371
|
+
const resolvablePlugins = pluginEntries.filter(([key]) => !excludedPluginKeys.has(key));
|
|
372
|
+
(await Promise.allSettled(resolvablePlugins.map(async ([key, plugin]) => {
|
|
373
|
+
return {
|
|
374
|
+
key,
|
|
375
|
+
source: await resolveContractSource({
|
|
376
376
|
configDir: opts.configDir,
|
|
377
377
|
runtimeDir,
|
|
378
378
|
key,
|
|
379
379
|
source: plugin,
|
|
380
380
|
baseUrl: plugin.url,
|
|
381
381
|
generatedSubdir: `plugins/${key}`
|
|
382
|
-
})
|
|
383
|
-
|
|
382
|
+
}),
|
|
383
|
+
plugin
|
|
384
|
+
};
|
|
385
|
+
}))).forEach((result, index) => {
|
|
386
|
+
const [key, plugin] = resolvablePlugins[index];
|
|
387
|
+
if (result.status === "fulfilled") {
|
|
388
|
+
sources.push(result.value.source);
|
|
384
389
|
status.push({
|
|
385
390
|
key,
|
|
386
391
|
source: plugin.source,
|
|
387
392
|
url: plugin.source !== "local" ? plugin.url : void 0
|
|
388
393
|
});
|
|
389
|
-
if (source.generatedPath) generatedPath = source.generatedPath;
|
|
390
|
-
}
|
|
391
|
-
const message =
|
|
394
|
+
if (result.value.source.generatedPath) generatedPath = result.value.source.generatedPath;
|
|
395
|
+
} else {
|
|
396
|
+
const message = result.reason instanceof Error ? result.reason.message : String(result.reason);
|
|
392
397
|
console.warn(`[API Contract] Failed to resolve plugin "${key}": ${message}`);
|
|
393
398
|
status.push({
|
|
394
399
|
key,
|
|
@@ -398,7 +403,7 @@ async function syncApiContractBridge(opts) {
|
|
|
398
403
|
});
|
|
399
404
|
excludedPluginKeys.add(key);
|
|
400
405
|
}
|
|
401
|
-
}
|
|
406
|
+
});
|
|
402
407
|
const apiStatus = status.find((s) => s.key === "api");
|
|
403
408
|
if (apiStatus?.source === "failed") throw new Error(`Cannot generate contract types without api contract: ${apiStatus.error ?? "unknown error"}`);
|
|
404
409
|
const allPluginKeys = pluginEntries.filter(([key]) => !excludedPluginKeys.has(key)).map(([key]) => key);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-contract.mjs","names":[],"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 { 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 response = await fetchResponse(url);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch API plugin manifest from ${url}: ${response.status} ${response.statusText}`,\n );\n }\n\n const manifest = (await response.json()) as ApiPluginManifest;\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 continue;\n }\n try {\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 sources.push(source);\n status.push({\n key,\n source: plugin.source,\n url: plugin.source !== \"local\" ? plugin.url : undefined,\n });\n if (source.generatedPath) {\n generatedPath = source.generatedPath;\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\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.mjs","names":[],"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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"}
|
package/dist/cli/catalog.cjs
CHANGED
|
@@ -15,9 +15,9 @@ const commandCatalog = Object.entries(require_contract.bosContract).map(([key, p
|
|
|
15
15
|
procedure
|
|
16
16
|
};
|
|
17
17
|
});
|
|
18
|
+
const sortedCommandCatalog = [...commandCatalog].sort((a, b) => b.commandPath.length - a.commandPath.length);
|
|
18
19
|
function findCommandDescriptor(args) {
|
|
19
|
-
const
|
|
20
|
-
for (const descriptor of sorted) if (args.slice(0, descriptor.commandPath.length).map((part) => part.toLowerCase()).join(" ") === descriptor.commandPath.join(" ")) return {
|
|
20
|
+
for (const descriptor of sortedCommandCatalog) if (args.slice(0, descriptor.commandPath.length).map((part) => part.toLowerCase()).join(" ") === descriptor.commandPath.join(" ")) return {
|
|
21
21
|
descriptor,
|
|
22
22
|
consumed: descriptor.commandPath.length
|
|
23
23
|
};
|
package/dist/cli/catalog.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.cjs","names":["bosContract","cliCommandMeta"],"sources":["../../src/cli/catalog.ts"],"sourcesContent":["import { bosContract } from \"../contract\";\nimport { type CliCommandMeta, cliCommandMeta } from \"../contract.meta\";\n\nexport type CommandDescriptor = {\n key: keyof typeof bosContract;\n commandPath: string[];\n summary: string;\n meta: CliCommandMeta;\n procedure: (typeof bosContract)[keyof typeof bosContract];\n};\n\nfunction splitCamelCase(value: string): string[] {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .split(/\\s+/)\n .map((part) => part.trim())\n .filter(Boolean)\n .map((part) => part.toLowerCase());\n}\n\nexport const commandCatalog: CommandDescriptor[] = (\n Object.entries(bosContract) as Array<\n [keyof typeof bosContract, (typeof bosContract)[keyof typeof bosContract]]\n >\n).map(([key, procedure]) => {\n const meta = cliCommandMeta[key as keyof typeof cliCommandMeta] ?? {\n summary: splitCamelCase(String(key)).join(\" \"),\n };\n return {\n key,\n commandPath: meta.commandPath ?? splitCamelCase(String(key)),\n summary: meta.summary,\n meta,\n procedure,\n };\n});\n\nexport function findCommandDescriptor(\n args: string[],\n): { descriptor: CommandDescriptor; consumed: number } | null {\n
|
|
1
|
+
{"version":3,"file":"catalog.cjs","names":["bosContract","cliCommandMeta"],"sources":["../../src/cli/catalog.ts"],"sourcesContent":["import { bosContract } from \"../contract\";\nimport { type CliCommandMeta, cliCommandMeta } from \"../contract.meta\";\n\nexport type CommandDescriptor = {\n key: keyof typeof bosContract;\n commandPath: string[];\n summary: string;\n meta: CliCommandMeta;\n procedure: (typeof bosContract)[keyof typeof bosContract];\n};\n\nfunction splitCamelCase(value: string): string[] {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .split(/\\s+/)\n .map((part) => part.trim())\n .filter(Boolean)\n .map((part) => part.toLowerCase());\n}\n\nexport const commandCatalog: CommandDescriptor[] = (\n Object.entries(bosContract) as Array<\n [keyof typeof bosContract, (typeof bosContract)[keyof typeof bosContract]]\n >\n).map(([key, procedure]) => {\n const meta = cliCommandMeta[key as keyof typeof cliCommandMeta] ?? {\n summary: splitCamelCase(String(key)).join(\" \"),\n };\n return {\n key,\n commandPath: meta.commandPath ?? splitCamelCase(String(key)),\n summary: meta.summary,\n meta,\n procedure,\n };\n});\n\nconst sortedCommandCatalog = [...commandCatalog].sort(\n (a, b) => b.commandPath.length - a.commandPath.length,\n);\n\nexport function findCommandDescriptor(\n args: string[],\n): { descriptor: CommandDescriptor; consumed: number } | null {\n for (const descriptor of sortedCommandCatalog) {\n const parts = args.slice(0, descriptor.commandPath.length).map((part) => part.toLowerCase());\n if (parts.join(\" \") === descriptor.commandPath.join(\" \")) {\n return { descriptor, consumed: descriptor.commandPath.length };\n }\n }\n return null;\n}\n"],"mappings":";;;;AAWA,SAAS,eAAe,OAAyB;AAC/C,QAAO,MACJ,QAAQ,sBAAsB,QAAQ,CACtC,MAAM,MAAM,CACZ,KAAK,SAAS,KAAK,MAAM,CAAC,CAC1B,OAAO,QAAQ,CACf,KAAK,SAAS,KAAK,aAAa,CAAC;;AAGtC,MAAa,iBACX,OAAO,QAAQA,6BAAY,CAG3B,KAAK,CAAC,KAAK,eAAe;CAC1B,MAAM,OAAOC,qCAAe,QAAuC,EACjE,SAAS,eAAe,OAAO,IAAI,CAAC,CAAC,KAAK,IAAI,EAC/C;AACD,QAAO;EACL;EACA,aAAa,KAAK,eAAe,eAAe,OAAO,IAAI,CAAC;EAC5D,SAAS,KAAK;EACd;EACA;EACD;EACD;AAEF,MAAM,uBAAuB,CAAC,GAAG,eAAe,CAAC,MAC9C,GAAG,MAAM,EAAE,YAAY,SAAS,EAAE,YAAY,OAChD;AAED,SAAgB,sBACd,MAC4D;AAC5D,MAAK,MAAM,cAAc,qBAEvB,KADc,KAAK,MAAM,GAAG,WAAW,YAAY,OAAO,CAAC,KAAK,SAAS,KAAK,aAAa,CAClF,CAAC,KAAK,IAAI,KAAK,WAAW,YAAY,KAAK,IAAI,CACtD,QAAO;EAAE;EAAY,UAAU,WAAW,YAAY;EAAQ;AAGlE,QAAO"}
|
package/dist/cli/catalog.mjs
CHANGED
|
@@ -15,9 +15,9 @@ const commandCatalog = Object.entries(bosContract).map(([key, procedure]) => {
|
|
|
15
15
|
procedure
|
|
16
16
|
};
|
|
17
17
|
});
|
|
18
|
+
const sortedCommandCatalog = [...commandCatalog].sort((a, b) => b.commandPath.length - a.commandPath.length);
|
|
18
19
|
function findCommandDescriptor(args) {
|
|
19
|
-
const
|
|
20
|
-
for (const descriptor of sorted) if (args.slice(0, descriptor.commandPath.length).map((part) => part.toLowerCase()).join(" ") === descriptor.commandPath.join(" ")) return {
|
|
20
|
+
for (const descriptor of sortedCommandCatalog) if (args.slice(0, descriptor.commandPath.length).map((part) => part.toLowerCase()).join(" ") === descriptor.commandPath.join(" ")) return {
|
|
21
21
|
descriptor,
|
|
22
22
|
consumed: descriptor.commandPath.length
|
|
23
23
|
};
|
package/dist/cli/catalog.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.mjs","names":[],"sources":["../../src/cli/catalog.ts"],"sourcesContent":["import { bosContract } from \"../contract\";\nimport { type CliCommandMeta, cliCommandMeta } from \"../contract.meta\";\n\nexport type CommandDescriptor = {\n key: keyof typeof bosContract;\n commandPath: string[];\n summary: string;\n meta: CliCommandMeta;\n procedure: (typeof bosContract)[keyof typeof bosContract];\n};\n\nfunction splitCamelCase(value: string): string[] {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .split(/\\s+/)\n .map((part) => part.trim())\n .filter(Boolean)\n .map((part) => part.toLowerCase());\n}\n\nexport const commandCatalog: CommandDescriptor[] = (\n Object.entries(bosContract) as Array<\n [keyof typeof bosContract, (typeof bosContract)[keyof typeof bosContract]]\n >\n).map(([key, procedure]) => {\n const meta = cliCommandMeta[key as keyof typeof cliCommandMeta] ?? {\n summary: splitCamelCase(String(key)).join(\" \"),\n };\n return {\n key,\n commandPath: meta.commandPath ?? splitCamelCase(String(key)),\n summary: meta.summary,\n meta,\n procedure,\n };\n});\n\nexport function findCommandDescriptor(\n args: string[],\n): { descriptor: CommandDescriptor; consumed: number } | null {\n
|
|
1
|
+
{"version":3,"file":"catalog.mjs","names":[],"sources":["../../src/cli/catalog.ts"],"sourcesContent":["import { bosContract } from \"../contract\";\nimport { type CliCommandMeta, cliCommandMeta } from \"../contract.meta\";\n\nexport type CommandDescriptor = {\n key: keyof typeof bosContract;\n commandPath: string[];\n summary: string;\n meta: CliCommandMeta;\n procedure: (typeof bosContract)[keyof typeof bosContract];\n};\n\nfunction splitCamelCase(value: string): string[] {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .split(/\\s+/)\n .map((part) => part.trim())\n .filter(Boolean)\n .map((part) => part.toLowerCase());\n}\n\nexport const commandCatalog: CommandDescriptor[] = (\n Object.entries(bosContract) as Array<\n [keyof typeof bosContract, (typeof bosContract)[keyof typeof bosContract]]\n >\n).map(([key, procedure]) => {\n const meta = cliCommandMeta[key as keyof typeof cliCommandMeta] ?? {\n summary: splitCamelCase(String(key)).join(\" \"),\n };\n return {\n key,\n commandPath: meta.commandPath ?? splitCamelCase(String(key)),\n summary: meta.summary,\n meta,\n procedure,\n };\n});\n\nconst sortedCommandCatalog = [...commandCatalog].sort(\n (a, b) => b.commandPath.length - a.commandPath.length,\n);\n\nexport function findCommandDescriptor(\n args: string[],\n): { descriptor: CommandDescriptor; consumed: number } | null {\n for (const descriptor of sortedCommandCatalog) {\n const parts = args.slice(0, descriptor.commandPath.length).map((part) => part.toLowerCase());\n if (parts.join(\" \") === descriptor.commandPath.join(\" \")) {\n return { descriptor, consumed: descriptor.commandPath.length };\n }\n }\n return null;\n}\n"],"mappings":";;;;AAWA,SAAS,eAAe,OAAyB;AAC/C,QAAO,MACJ,QAAQ,sBAAsB,QAAQ,CACtC,MAAM,MAAM,CACZ,KAAK,SAAS,KAAK,MAAM,CAAC,CAC1B,OAAO,QAAQ,CACf,KAAK,SAAS,KAAK,aAAa,CAAC;;AAGtC,MAAa,iBACX,OAAO,QAAQ,YAAY,CAG3B,KAAK,CAAC,KAAK,eAAe;CAC1B,MAAM,OAAO,eAAe,QAAuC,EACjE,SAAS,eAAe,OAAO,IAAI,CAAC,CAAC,KAAK,IAAI,EAC/C;AACD,QAAO;EACL;EACA,aAAa,KAAK,eAAe,eAAe,OAAO,IAAI,CAAC;EAC5D,SAAS,KAAK;EACd;EACA;EACD;EACD;AAEF,MAAM,uBAAuB,CAAC,GAAG,eAAe,CAAC,MAC9C,GAAG,MAAM,EAAE,YAAY,SAAS,EAAE,YAAY,OAChD;AAED,SAAgB,sBACd,MAC4D;AAC5D,MAAK,MAAM,cAAc,qBAEvB,KADc,KAAK,MAAM,GAAG,WAAW,YAAY,OAAO,CAAC,KAAK,SAAS,KAAK,aAAa,CAClF,CAAC,KAAK,IAAI,KAAK,WAAW,YAAY,KAAK,IAAI,CACtD,QAAO;EAAE;EAAY,UAAU,WAAW,YAAY;EAAQ;AAGlE,QAAO"}
|
package/dist/cli/infra.cjs
CHANGED
|
@@ -310,7 +310,9 @@ function ensureEnvFile(configDir) {
|
|
|
310
310
|
}).join("\n"));
|
|
311
311
|
_clack_prompts.log.info("Created .env from generated .env.example with generated BETTER_AUTH_SECRET");
|
|
312
312
|
}
|
|
313
|
+
let envLoadedDir = null;
|
|
313
314
|
function loadProjectEnv(configDir) {
|
|
315
|
+
if (envLoadedDir === configDir) return;
|
|
314
316
|
const envPath = (0, node_path.join)(configDir, ".env");
|
|
315
317
|
if (!(0, node_fs.existsSync)(envPath)) return;
|
|
316
318
|
(0, dotenv.config)({
|
|
@@ -318,6 +320,7 @@ function loadProjectEnv(configDir) {
|
|
|
318
320
|
processEnv: process.env,
|
|
319
321
|
quiet: true
|
|
320
322
|
});
|
|
323
|
+
envLoadedDir = configDir;
|
|
321
324
|
}
|
|
322
325
|
|
|
323
326
|
//#endregion
|