Documentação
Crie uma integração de cliente API
Use o Promise SDK, o cliente de contrato de efeito completo ou adaptadores de efeito gerados com suas entradas reais e comportamento de erro.
Traduzido automaticamente do inglês. Ver o original em inglês
Escolha um cliente
O repositório possui três superfícies de cliente relacionadas. Eles compartilham declarações de endpoint, mas sua construção, formatos de entrada, dependências de tempo de execução e canais de erro são diferentes. Escolha um deliberadamente e mantenha juntos os exemplos dessa superfície.
| Superfície | Ponto de entrada | Execução |
|---|---|---|
| Promessa SDK | @cadcamfun/api/sdk, exportado CadCam.make | Promessas de resultados comuns; iteráveis assíncronos para SSE. Usa uma busca fornecida ou global. |
| Cliente com contrato completo | ApiClient de @cadcamfun/api | Serviço de efeito com middleware de transporte e portador fornecido por sua camada. |
| Adaptadores de efeitos gerados | packages/api/src/client/generated/index.ts | Métodos achatados em torno do cliente contratado; o chamador fornece o transporte e o middleware necessários. |
O pacote API é um espaço de trabalho privado com exportações de origem. As importações abaixo destinam-se a este monorepo ou a uma distribuição que realmente fornece essas exportações; esta página não reivindica um pacote npm público disponível separadamente. Clientes independentes podem usar o Documento OpenAPI ou HTTP simples.
Para uma primeira solicitação sem configuração de biblioteca cliente, comece com o passo a passo HTTP capturado. Estabelece como os órgãos de sucesso e fracasso diferem entre as operações.
Resolva a conexão
Use o URL e o token de portador do aplicativo pertencente à inicialização do sidecar atual. Tauri os obtém através get_sidecar_endpoint. Um processo de desenvolvimento manual imprime sua porta atribuída em um evento pronto. A origem deve apontar para o sidecar ou gateway complementar admitido, e não para o site de documentação ou ativos do Vite.
Após a reinicialização do sidecar, resolva a conexão novamente. A reutilização da porta anterior pode produzir recusa de conexão ou abordar acidentalmente outro processo. A reutilização de um token de inicialização obsoleto produz uma falha de autorização. Uma resposta de saúde pública bem sucedida não prova que um pedido protegido será admitido.
A seleção de conta, a admissão de aplicativos, a admissão de dispositivos e o acesso de agente externo são distintos. O opcional x-session-token seleciona uma conta após a admissão do aplicativo. Um token de ponte com escopo de projeto é limitado aos pontos de extremidade da ponte de ação. Um token de telefone funciona por meio da lista de permissões do gateway. Siga o referência de autenticação antes de escolher a conexão para uma integração.
Promessa SDK
O namespace exportado é CadCam, e seu construtor é make. Forneça um URL base e cabeçalhos padrão. Os métodos create e get abaixo usam campos nivelados em vez de campos aninhados payload ou params objeto.
import { CadCam } from "@cadcamfun/api/sdk"
const client = CadCam.make({
baseUrl,
headers: { Authorization: "Bearer " + token },
})
const projects = await client.projects.list()
const created = await client.projects.create({
name: "Fixture plate",
description: "An integration-created project",
})
const detail = await client.projects.get({ id: created.id })
console.log(projects.length, detail.name, detail._count.drawings) Cada chamada é resolvida diretamente para a carga de sucesso desse endpoint. projects.list() retorna uma matriz; projects.create() retorna uma linha do projeto. Não existe universal { data, error } invólucro e não throwOnError opção de construtor neste SDK. Algumas cargas úteis de endpoint contêm data ou success porque esse é o contrato HTTP deles.
O SDK prepara uma URL a partir do caminho do endpoint e da URL base configurada, codifica identificadores de caminho, serializa a entrada JSON declarada e verifica o status exato de sucesso declarado da operação. Em seguida, ele analisa JSON e retorna seu valor digitado. O tempo de execução do Promise não aplica um decodificador de esquema Effect a cada carga retornada; Os tipos de saída TypeScript não validam uma implementação de servidor arbitrária.
Erros declarados e de transporte
As falhas HTTP declaradas são rejeitadas com o corpo da resposta decodificado. Esse valor pode ser um objeto simples marcado em vez de uma instância de erro de JavaScript. Falhas de transporte e protocolo usam o SDK ClientError.
import { ClientError } from "@cadcamfun/api/sdk"
try {
await client.projects.create({})
} catch (error) {
if (error instanceof ClientError) {
console.error(error.reason, error.message)
} else if (error && typeof error === "object" && "message" in error) {
console.error(String(error.message))
} else {
console.error("Unrecognized API failure", error)
}
} | Motivo do erro do cliente | Interpretação |
|---|---|
Transport | Buscar configuração, conexão, anulação ou falha de leitura de fluxo. Inspecione sua causa e a conexão atual. |
UnexpectedStatus | O servidor retornou um status fora dos status de sucesso e falha declarados da operação. |
UnsupportedContentType | Uma resposta de fluxo não tinha o tipo de conteúdo de fluxo de evento esperado. |
MalformedResponse | JSON ou um fluxo de resposta esperado não pôde ser decodificado. |
SseEventTooLarge | O buffer do fluxo de eventos excedeu o frame guard do tempo de execução gerado. |
Por exemplo, um nome de projeto ausente é uma falha comercial HTTP 400, mesmo que o tipo de entrada create permita a omissão. Uma redefinição de conexão durante a criação de um projeto é diferente: deixa o cliente incerto se a gravação foi concluída. Leia o estado do recurso antes de repetir uma mutação. O SDK não adiciona um protocolo de idempotência para todo o aplicativo nem tenta repetir automaticamente cada chamada rejeitada.
Cancelamento e cabeçalhos
ClientOptions aceita baseUrl, uma implementação de busca opcional e cabeçalhos padrão. Por chamada RequestOptions aceita um sinal e cabeçalhos extras. Para métodos sem entrada de endpoint, as opções de solicitação são o primeiro argumento; métodos com entrada recebem opções de solicitação depois dela.
const controller = new AbortController()
const pending = client.projects.get(
{ id: projectId },
{
signal: controller.signal,
headers: { "x-session-token": accountSessionToken },
},
)
// Call controller.abort() when the operation is no longer needed.
const project = await pending O construtor de solicitação aplica cabeçalhos padrão, cabeçalhos declarados por endpoint e, em seguida, cabeçalhos por chamada. Um valor por chamada pode substituir um padrão; evite substituir acidentalmente a Autorização ao adicionar cabeçalhos de conta ou de rastreamento. Não coloque credenciais em URLs de endpoint copiados em logs.
Injetando fetch suporta um transporte de teste em processo ou um adaptador controlado. O adaptador ainda deve respeitar cabeçalhos de solicitação, corpo, cancelamento, tipos de conteúdo e semântica de status de resposta. A integração do Effect do próprio desktop e o transporte nativo fixado do telefone fazem um trabalho adicional; substituir uma busca arbitrária não reproduz esses limites nativos.
Cliente de efeito completo
ApiClient.layer constrói o cliente HttpApi completo, transporte de busca e middleware de portador. Ele expõe métodos de endpoint com o formato de solicitação HttpApi subjacente. A carga útil de uma mutação desaparece payload, e os valores do caminho vão abaixo params.
import { ApiClient } from "@cadcamfun/api"
import { Effect } from "effect"
const createProject = Effect.gen(function* () {
const api = yield* ApiClient
return yield* api.projects.create({
payload: { name: "Fixture plate" },
})
}).pipe(Effect.provide(ApiClient.layer({ baseUrl, token })))
const project = await Effect.runPromise(createProject) Este cliente deriva de toda a declaração da API e é a opção para endpoints omitidos dos destinos gerados. Ele preserva o canal de erro digitado do Effect e o transporte com reconhecimento de esquema. A vida útil do recurso, a interrupção do fluxo e o fornecimento da camada pertencem ao programa Effect de chamada; criar um efeito não o executa.
A camada reutilizável fornece o token do aplicativo. A área de trabalho constrói sua própria camada em apps/desktop/src/app/client.ts para anexar o estado opcional da sessão da conta e o transporte injetado. Reutilize essa integração ao trabalhar dentro do desktop em vez de criar uma segunda conexão/tempo de execução por componente.
Adaptadores de efeitos gerados
O cliente Effect gerado importa os esquemas reais e adapta métodos em campos nivelados. Isso é CadCam.make retorna um Efeito que constrói o cliente adaptado. Ele não fornece seu próprio transporte de busca ou camada de autorização de aplicativo, portanto, o chamador deve fornecer os serviços e middleware correspondentes.
O adaptador de erro gerado mapeia falhas de transporte/esquema/SSE em um arquivo marcado ClientError enquanto retém falhas de domínio declaradas. Essa classe de erro é separada da classe de erro JavaScript do Promise SDK com um reason corda. A semelhança de nomes não torna seu manuseio intercambiável.
Mantenha os exemplos de entrada explícitos. Os formulários Promessa e Efeito gerado usam projects.get({ id }); o formulário de contrato bruto usa projects.get({ params: { id } }). Evite passar o objeto de entrada de uma superfície para outra por meio de uma asserção de tipo não verificada.
Transmissão
As operações Promise SSE retornam iteráveis assíncronos. A configuração da rede ocorre quando a iteração começa. O tempo de execução verifica o status de sucesso e o tipo de conteúdo do fluxo de eventos, lê dados UTF-8 incrementais, normaliza os limites do quadro e decodifica quadros de dados em JSON. Um quadro malformado falha na iteração; a limpeza do leitor é executada quando a iteração termina ou termina.
A guarda do tempo de execução é 16 * 1024 * 1024 unidades de string JavaScript armazenadas em buffer. Limita a acumulação antes do limite do quadro; não é uma promessa que cada carga útil arbitrária de 16 MB seja útil ou válida para os esquemas de eventos do aplicativo.
Consumir eventos de IA de acordo com seus discriminadores e preservar o identificador de sessão. Um transporte finalizado não é prova de um evento de conversação de terminal. Usar Streaming e recuperação de IA para comportamento de fila, anulação, permissão, pergunta e recuperação de estado. EventSource não é um substituto imediato para uma solicitação POST com cabeçalhos de autorização e um corpo JSON.
Cobertura e regeneração
O gerador possui listas de omissões explícitas para formas que não pode representar. As omissões compartilhadas incluem uploads de perfil/plugin multiparte, criação de MCP com vários esquemas de sucesso, nomes de entrada em colisão e serviço de plug-in com cabeçalhos de resposta em seu fluxo. Omissões adicionais do Promise incluem webhooks assinados brutos, bootstrap de plug-in JavaScript, download binário e solicitações de gerador de formato livre.
Leia as listas atuais exatas em packages/api/scripts/generate-clients.ts e o Visão geral da API. Um método gerado ausente não estabelece que o terminal do servidor está indisponível. Utilize o cliente de contrato completo ou transporte bruto adequado para essa operação.
bun run generate
bun run generate:check
bun run --filter @cadcamfun/web generate:api-reference
bun run --filter @cadcamfun/web check:api-reference A regeneração do cliente e a regeneração da documentação são resultados separados do mesmo contrato. Mantenha ambos atualizados após alterações no endpoint. Não edite os corpos dos métodos gerados para alterar os requisitos de entrada do servidor.
O código gerado é escrito em packages/api/src/client/generated e packages/api/src/sdk/generated. Não edite esses arquivos manualmente; alterar o contrato e regenerar.
Verificação de integração
O comportamento de criação/leitura/resultado simples do Promise e a falha declarada lançada mostradas aqui foram exercidos na pilha real do manipulador sidecar usando um banco de dados descartável migrado. O passo a passo HTTP contém as respostas observadas correspondentes. Repita as verificações focadas ao alterar os esquemas do gerador, da autenticação ou do terminal.
For an integration acceptance check, verify public health; a protected request without a token; the same request with the current token; a valid create/read cycle; a declared validation failure; a cancelled request; and a stream whose terminal state is checked. Use a disposable project and never infer successful persistence from a frontend fixture alone.
As fontes de implementação são packages/api/src/sdk/generated/client.ts, isso é client-error.ts, packages/api/src/client.ts, packages/api/src/client/generated, e packages/httpapi-codegen/src/index.ts. O gerador e as saídas confirmadas estabelecem juntos o comportamento real do cliente.
Referência de opções do Promise SDK
| Opção | Onde | Effect |
|---|---|---|
baseUrl | CadCam.make | Resolvido com new URL(path, baseUrl); inclua o esquema e a porta. |
fetch | CadCam.make | Substitua o transporte, por exemplo, para adicionar log ou para injetar um teste duplo. O padrão é globalThis.fetch. |
headers | CadCam.make | Enviado com cada solicitação. Colocar authorization aqui. |
signal | por chamada | Aborta a solicitação; a rejeição é ClientError("Transport"). |
headers | por chamada | Substitua ou adicione cabeçalhos para uma chamada, como x-session-token. Os valores por chamada vencem os valores do cliente. |
Quando um corpo está presente e não content-type cabeçalho foi definido, o SDK define application/json e serializa com JSON.stringify. Parâmetros de caminho são sempre passados encodeURIComponent, então uma chave como docs.walkthrough.units ou um contendo / permanece um único segmento.
Razões do erro do cliente
| Razão | Criado quando | Resposta típica |
|---|---|---|
Transport | fetch lançado (recusado, redefinido, DNS, abortado) ou uma leitura de fluxo falhou | Resolva novamente o URL secundário; tente ler novamente; releia o estado antes de tentar novamente as gravações. |
UnexpectedStatus | O status não é o status de sucesso nem o status de erro declarado. A causa mantém { status }. | Trate como incompatibilidade de contrato, geralmente uma versão de servidor diferente. |
UnsupportedContentType | Uma operação de fluxo respondeu com algo diferente de text/event-streamou uma operação JSON com um tipo não JSON | Verifique os proxies e a versão do servidor. |
MalformedResponse | JSON vazio ou inválido, corpo ausente ou SSE data: bloco que não é JSON | Registrar a resposta bruta; denuncie. |
SseEventTooLarge | O buffer SSE não analisado excedeu 16 MiB | O evento é recusado; reinicie o fluxo. |
A mensagem de um ClientError é o motivo seguido pela mensagem de causa (por exemplo Transport: fetch failed), então registrando error.message por si só já é diagnóstico.
import { CadCam, ClientError } from "@cadcamfun/api/sdk"
async function withRetry<T>(read: () => Promise<T>, attempts = 3): Promise<T> {
for (let attempt = 1; ; attempt++) {
try {
return await read()
} catch (error) {
const transient = error instanceof ClientError && error.reason === "Transport"
if (!transient || attempt >= attempts) throw error
await new Promise((resolve) => setTimeout(resolve, 250 * 2 ** attempt))
}
}
}
const projects = await withRetry(() => client.projects.list()) Não tente escrever novamente cegamente
Uma gravação que falhou com Transport pode ter sido aplicado. Leia o recurso novamente e reenvie somente quando ele não estiver lá; a API não possui chaves de idempotência.
Consumindo um stream com o SDK
const controller = new AbortController()
const events = client.ai.chatStream(
{ message: "Pocket the 40 x 30 rectangle, 3 mm deep", projectId },
{ signal: controller.signal },
)
for await (const event of events) {
switch (event.type) {
case "delta": render(event); break
case "permission_request": askUser(event); break
case "done": finish(event); break
case "error": showError(event); break
}
} O iterador analisa cada bloco SSE: ele se junta ao data: linhas do bloco, analisa o JSON e o produz. Comentários e bloqueios sem data: são ignorados. Saindo do loop mais cedo (break, uma exceção ou anulação) cancela o leitor e libera a conexão. O evento type os valores são os listados no guia de streaming do assistente; verifique o gerado AiChatStreamOutput digite para a união exata.
Exemplo: preferências por meio do SDK
const key = "docs.walkthrough.units"
try {
await client.kv.get({ key })
} catch (error) {
if ((error as { _tag?: string })._tag !== "NotFound") throw error // first run: 404
}
const saved = await client.kv.set({ key, value: { units: "mm" } })
// saved: { key, value: { units: "mm" }, updatedAt: "2026-…" }
const { entries } = await client.kv.list({ prefix: "docs." })
await client.kv.remove({ key }) // { message: "…" } As chaves são limitadas a 512 caracteres e devem conter texto sem espaços em branco; os valores devem ser compatíveis com JSON (sem ciclos, funções ou números não finitos).