feat(client): add embedded V2 host
This commit is contained in:
@@ -200,7 +200,9 @@ export function emitEffect(contract: Contract): Output {
|
||||
|
||||
export function emitEffectImported(
|
||||
contract: Contract,
|
||||
options: { readonly module: string; readonly api: string },
|
||||
options:
|
||||
| { readonly module: string; readonly api: string }
|
||||
| { readonly module: string; readonly endpoints: Readonly<Record<string, string>> },
|
||||
): Output {
|
||||
return {
|
||||
operations: operations(contract.groups),
|
||||
@@ -291,7 +293,9 @@ function renderEffectFiles(groups: ReadonlyArray<Group>): Output["files"] {
|
||||
|
||||
function renderImportedEffectFiles(
|
||||
groups: ReadonlyArray<Group>,
|
||||
options: { readonly module: string; readonly api: string },
|
||||
options:
|
||||
| { readonly module: string; readonly api: string }
|
||||
| { readonly module: string; readonly endpoints: Readonly<Record<string, string>> },
|
||||
): Output["files"] {
|
||||
const adapters = groups.map((group, groupIndex) => {
|
||||
const rawGroup = group.endpoints[0]?.topLevel ? "RawClient" : `RawClient[${JSON.stringify(group.identifier)}]`
|
||||
@@ -328,7 +332,15 @@ function renderImportedEffectFiles(
|
||||
: [`${JSON.stringify(group.identifier)}: adaptGroup${index}(raw[${JSON.stringify(group.identifier)}])`],
|
||||
)
|
||||
const usesStream = groups.some((group) => group.endpoints.some((item) => item.operation.success === "stream"))
|
||||
const client = `// Generated by @opencode-ai/httpapi-codegen. Do not edit.\nimport { Effect${usesStream ? ", Stream" : ""}, Schema } from "effect"\nimport { Sse } from "effect/unstable/encoding"\nimport { HttpClientError } from "effect/unstable/http"\nimport { HttpApiClient } from "effect/unstable/httpapi"\nimport { ${options.api} } from ${JSON.stringify(options.module)}\nimport { ClientError } from "./client-error"\n\ntype RawClient = HttpApiClient.ForApi<typeof ${options.api}>\n\nconst mapClientError = <E>(error: E) => HttpClientError.isHttpClientError(error) || Schema.isSchemaError(error) || Sse.Retry.is(error) ? new ClientError({ cause: error }) : error\n\n${adapters.join("\n\n")}\n\nexport const make = (options?: { readonly baseUrl?: URL | string }) => HttpApiClient.make(${options.api}, options).pipe(Effect.map((raw) => ({ ${fields.join(", ")} })))\n`
|
||||
const imported = "api" in options
|
||||
const projection = imported ? undefined : renderImportedProjection(groups, options.endpoints)
|
||||
const api = imported ? options.api : "Api"
|
||||
const imports =
|
||||
projection === undefined
|
||||
? `import { ${api} } from ${JSON.stringify(options.module)}`
|
||||
: `import { HttpApi, HttpApiClient, HttpApiGroup } from "effect/unstable/httpapi"\nimport { ${projection.imports.join(", ")} } from ${JSON.stringify(options.module)}`
|
||||
const httpApiImport = projection === undefined ? 'import { HttpApiClient } from "effect/unstable/httpapi"\n' : ""
|
||||
const client = `// Generated by @opencode-ai/httpapi-codegen. Do not edit.\nimport { Effect${usesStream ? ", Stream" : ""}, Schema } from "effect"\nimport { Sse } from "effect/unstable/encoding"\nimport { HttpClientError } from "effect/unstable/http"\n${httpApiImport}${imports}\nimport { ClientError } from "./client-error"\n\n${projection?.source ?? ""}type RawClient = HttpApiClient.ForApi<typeof ${api}>\n\nconst mapClientError = <E>(error: E) => HttpClientError.isHttpClientError(error) || Schema.isSchemaError(error) || Sse.Retry.is(error) ? new ClientError({ cause: error }) : error\n\n${adapters.join("\n\n")}\n\nexport const make = (options?: { readonly baseUrl?: URL | string }) => HttpApiClient.make(${api}, options).pipe(Effect.map((raw) => ({ ${fields.join(", ")} })))\n`
|
||||
return [
|
||||
{
|
||||
path: "client-error.ts",
|
||||
@@ -343,6 +355,27 @@ function renderImportedEffectFiles(
|
||||
]
|
||||
}
|
||||
|
||||
function renderImportedProjection(groups: ReadonlyArray<Group>, endpoints: Readonly<Record<string, string>>) {
|
||||
const imports = groups.flatMap((group) =>
|
||||
group.endpoints.map((endpoint) => {
|
||||
const name = endpoints[`${group.identifier}.${endpoint.endpoint.name}`]
|
||||
if (name === undefined) {
|
||||
throw new GenerationError({
|
||||
reason: `Missing imported endpoint: ${group.identifier}.${endpoint.endpoint.name}`,
|
||||
})
|
||||
}
|
||||
return name
|
||||
}),
|
||||
)
|
||||
const source = `const Api = HttpApi.make("generated").${groups
|
||||
.map((group) => {
|
||||
const options = group.endpoints[0]?.topLevel ? ", { topLevel: true }" : ""
|
||||
return `add(HttpApiGroup.make(${JSON.stringify(group.identifier)}${options})${group.endpoints.map((endpoint) => `.add(${endpoints[`${group.identifier}.${endpoint.endpoint.name}`]})`).join("")})`
|
||||
})
|
||||
.join(".")}\n\n`
|
||||
return { imports: [...new Set(imports)], source }
|
||||
}
|
||||
|
||||
function renderPromiseTypes(groups: ReadonlyArray<Group>) {
|
||||
const types = new Map<SchemaAST.AST, string>()
|
||||
const typeOf = (schema: Schema.Top) => {
|
||||
|
||||
Reference in New Issue
Block a user