跳到内容
CADCAMFUN
文档

文档

API参考

完整的 HTTP 资源引用、经过身份验证的本地访问、流合同以及从共享模式生成的客户端。

从英文自动翻译。 查看英文原文

概述

sidecar 是一个单一的 Effect HttpApi。每个端点都是一个类型化的 HttpApiEndpoint 具有模式检查的请求和响应主体,因此该引用、生成的 SDK 和正在运行的服务器来自以下相同的声明 packages/api.

表面
325 操作

跨 232 路径和 35 资源组。

类型
56 架构

请求、响应和错误形状,每个形状都与使用它的操作相关联。

合同
OpenAPI 3。1。0

由 sidecar 发出 /api/openapi.json;中的快照 packages/web 被检查者 bun run check:api-reference.

客户
一个表面

桌面 Web 视图、移动伴侣、AI 桥和脚本都调用相同的路由。

基本网址

没有托管的 CADCAMFUN API。 sidecar 在你的机器上运行,绑定 127.0.0.1 在操作系统选择的端口上(它侦听端口 0),检查自己的端口 /api/health,然后才在标准输出上打印一行 JSON。基本 URL 是 http://127.0.0.1:<port> 从那条线。

启动一次性 sidecar 并读取其端口
export CADCAMFUN_TOKEN=dev-token
CADCAMFUN_DATA_DIR=$(mktemp -d) \
CADCAMFUN_MIGRATIONS_DIR=$PWD/packages/db/drizzle \
CADCAMFUN_AI_OFFLINE=true \
  bun --no-env-file apps/sidecar/src/main.ts
# stdout: {"event":"ready","port":46709}
export CADCAMFUN_URL=http://127.0.0.1:46709

每次启动时端口都会发生变化

阅读它来自 ready 行(桌面 shell 正是这样做的)而不是假设一个固定的数字。日志转到 stderr,因此 stdout 仅携带就绪或错误事件。

验证

合同声明了一种安全方案, bearer (HTTP Bearer)。 324 个操作(共 325 个)需要它;仅有的 GET /api/health 是公开的。

凭据发送为使用者
启动代币Authorization: Bearer <token>桌面网页视图和本地脚本;的价值 CADCAMFUN_TOKEN.
同伴令牌Authorization: Bearer <token>已配对的手机;更窄的访问,请参阅 同伴配对.
账户会话x-session-token选择不记名代币之上的代理账户;看 身份 以下。
公共和受保护的
curl -s "$CADCAMFUN_URL/api/health"
curl -s "$CADCAMFUN_URL/api/projects" -H "Authorization: Bearer $CADCAMFUN_TOKEN"

惯例

  • JSON 输入,JSON 输出。 尸体是 application/json 除非卡片另有说明:两个分段上传、一个八位字节流 Webhook、一个 JavaScript 引导程序、一个 zip 下载、一个二进制插件文件和两个事件流。
  • 操作 ID 是点状的。 projects.get, vcs.commit:组标签,一个点,生成的客户端使用的方法名称。
  • 键入错误。 每个端点都声明失败并带有 _tag;打开它而不是解析消息。在整个合约中,401 在 269 操作上声明,500 在 264 上声明,400 在 206 上声明。
  • 操作锚稳定。 每张卡都可以链接为 #op-<method>-<path>, 例如 /docs/api/projects#op-get-api-projects-id.

流媒体

小路形状携带
GET /api/projects/{id}/events上证所一个项目的更改事件。
POST /api/ai/chat/stream上证所生成的辅助输出以及心跳;看 人工智能串流.
关注项目事件
curl -N "$CADCAMFUN_URL/api/projects/$PROJECT_ID/events" \
  -H "Authorization: Bearer $CADCAMFUN_TOKEN"

客户

@cadcamfun/api/sdk 是从同一个合约生成的:下面的每个操作 id 都是一个类型化方法 CadCam.make(...),采用路径参数和主体字段的单一输入。生成了 259 操作中的 325;每张卡片都显示其确切的调用。

@cadcamfun/api/sdk
import { CadCam } from "@cadcamfun/api/sdk"

const client = CadCam.make({
  baseUrl: process.env.CADCAMFUN_URL!,
  headers: { authorization: `Bearer ${process.env.CADCAMFUN_TOKEN}` },
})

const projects = await client.projects.list()
const created = await client.projects.create({ name: "Bracket" })

资源

325 操作位于 35 组中,按其服务内容排列。

核

设计

制造业

资源

扩展

账户

开放API文档

下载 /docs/api/openapi.json (此站点呈现的签入快照)或从正在运行的 sidecar 获取实时文档 /api/openapi.json。重新生成快照 bun run generate:api-reference 中 packages/web 更改端点后。

合约和服务器

@cadcamfun/api 使用 Effect HttpApi 定义请求和响应架构。它导出根 Api、域记录、标记错误和客户端。请求处理程序、授权决策、数据库查询和提供程序调用在 sidecar 中运行。导入架构不会启动服务器。

sidecar 在以下位置发布其服务合约: GET /api/openapi.json。使用该运行文档检查您所连接的应用程序的方法、路径参数、有效负载和状态代码。服务器将其组组装在 apps/sidecar/src/layers.ts;共享合约被组装在 packages/api/src/index.ts.

身份验证和身份

受保护的路线需要 Authorization: Bearer <token>。当 sidecar 启动时,桌面会收到一个新的应用程序令牌。 GET /api/health 是公共卫生调查;本国的 /health 和 /version 受到保护。应用程序承载令牌通过定时安全比较进行比较。

可选的 x-session-token 携带帐户会话 JWT。不记名令牌接纳本地应用程序;会话选择其代理帐户。缺失、过期、无效或孤立的会话将回退到安装的本地配置文件。然后,资源处理程序通过存储库授权帮助程序检查所有权或组织访问权限。

范围内的桥接令牌仅允许 GET /api/ai/actions 和 POST /api/ai/actions/invoke。它不授予对项目 CRUD、凭据设置或其他 HTTP 路由的访问权限。动作桥会再次检查其项目和读/写范围。

资源族

  • 设计: 项目、图纸、组件、图纸版本、实体导入/导出以及精确的 CAD 分析、STEP 导出和装配分析。
  • 制造业: 刀具路径和版本、注释、生成器建议、解析、重播验证、本地制造作业、材料、工具、机器配置、库项目和生产成本。
  • 助手: 提供者、凭证、模型、会话、流转、会话控制、操作、项目内存、工作区上下文和无状态建议。
  • 合作: 分支、提交、差异、拉取请求、评论、GitHub 镜像、工作流程文件和运行、实时事件和同伴配对。
  • 申请服务: 用户、身份验证、组织、通知、文件、插件、计费、分析、候补名单、MCP 配置和本地键值存储。

合同组保留其特定于端点的响应形状。客户端应该解码它调用的操作的模式,而不是假设单个应用程序范围的 JSON 信封。

响应和失败

常见标记错误映射到 HTTP 400 (BadRequest), 401 (Unauthorized), 403 (Forbidden), 404 (NotFound), 405 (MethodNotAllowed), 409 (Conflict) 和 500 (InternalError)。他们声明的模式带有人类可读的 message。有些团体使用信封 success: false, message, 和 errors;少数人使用 error 场地。

成功响应可以是记录、数组、可为空值或信封。 Envelope 包括 success, message, 和 data; EnvelopeOpt 使消息可选。创建端点在适当的情况下显式声明 201。不要在不检查 HTTP 状态和端点架构的情况下仅从 JSON 字段推断成功。

模式解码在处理程序执行之前验证传输输入。业务验证仍在服务中运行:结构上有效的请求可能引用无法访问的绘图、包含过时的制造工件或请求冲突的分支操作。

使用共享客户端

ApiClient.layer 需要一个 baseUrl 和应用 token。它提供获取传输和客户端授权中间件。其方法直接源自 Api,因此该客户端还涵盖了代码生成省略的操作。

使用 Effect 客户端阅读项目
import { ApiClient } from "@cadcamfun/api"
import { Effect } from "effect"

const projects = Effect.gen(function* () {
  const api = yield* ApiClient
  return yield* api.projects.list()
}).pipe(Effect.provide(ApiClient.layer({ baseUrl, token })))

基本 URL 是 sidecar 的环回地址和分配的端口。从桌面连接解决它,而不是在启动时保留端口。将令牌排除在 URL 和日志之外。

设计和制造要求

项目运营使用 /api/projects;图纸和刀具路径有自己的集合和详细路线。 POST /api/toolpaths/generate 生成 G 代码、解析的程序数据、警告以及来自生成器设置和几何形状的统计数据。 /suggest, /parse, 和 /verify 公开参数建议、G 代码解释和库存回放。这些计算不会创建保存的刀具路径。

POST /api/toolpaths/manufacture 接受版本化 CAD 快照并返回包含 NC、刀具分配、切削数据、声明、问题和发布级别的内核结果。通过刀具路径创建或更新操作单独保存生成的文档。看 设置 用于持久性期间的证据验证。

POST /api/cad/exact/analyze, /step, 和 /assembly 接受显式元素或存储的绘图标识符。读取存储的图形会应用调用者的正常图形访问检查。

流媒体和恢复

AI 流携带文本、推理、工具调用和结果、权限和问题请求、重试、轮次状态、上下文和完成的键入事件。客户端必须增量地使用事件并保留会话标识符。 HTTP 连接结束并不足以证明模型已完成:重新连接后可以再次读取会话状态。

AI 事件模式存在于 packages/api/src/ai-events.ts 和 packages/ai/src/events.ts。一般现场活动使用活动组。二进制下载、JavaScript 插件引导响应和签名的原始 Webhook 主体需要它们自己的传输处理。

列出分页其结果所使用的路由 page 和 limit 查询参数。对于机器配置, page 默认为 1, limit 默认为20,并被限制为1–100,响应携带 pagination 和 page, limit, total, 和 totalPages (apps/sidecar/src/http/machine-configs.ts)。检查每个组的参考页以了解其实际声明的参数。

生成的 SDK

@cadcamfun/httpapi-codegen 将 HttpApi 组反映到操作元数据和生成的客户端中。 API生成器编写一个Promise SDK来 packages/api/src/sdk/generated 并影响客户 packages/api/src/client/generated。公共 Promise SDK 导出为 @cadcamfun/api/sdk.

重新生成或检查客户端漂移
bun run --filter @cadcamfun/api generate
bun run --filter @cadcamfun/api generate:check

两个生成的目标都忽略配置文件分段上传、插件分段安装、具有多个成功模式的 MCP 创建、具有冲突标识符的 MCP 更新、具有重复输入名称的项目工具路径创建以及使用流标头提供的插件文件。 Promise 目标还省略了 Stripe 原始 webhooks、插件 JavaScript 引导程序、二进制文件下载以及生成器的生成/建议请求。这些遗漏是明确的 packages/api/scripts/generate-clients.ts;使用合同客户或适当的原始传输来进行这些操作。

来源组织

groups/ 包含资源合同。共享几何体和 CAM 方案来自 @cadcamfun/core; cad-exact.ts, cam-kernel.ts, 和 cam-program.ts 描述丰富的 CAD/CAM 结果和便携式文档。 client.ts 构建合约客户端,而生成脚本拥有生成的目标和遗漏列表。

积分规则

在传输边界重用契约模式,并将数据库依赖项保留在 sidecar 中。通过其合约、处理程序、服务或存储库以及重点 HTTP 覆盖范围来引入端点。生成的文件是输出:编辑它们的合约或生成器并重新生成它们。 API 模式版本、可移植文件版本和插件 API 版本描述单独的合约。

资源参考

325 操作 穿过 232 条路径 和 35 个资源组,具有 56 命名架构。每个资源页面都会列出其操作,并显示声明的路径/查询/标头参数、必填字段和可选字段、可为空值、内容类型、成功和错误状态以及完整架构。

数据是从发出的 packages/api/src/index.ts,客户端和 sidecar 使用的相同组成的 HttpApi 合约。这些页面描述了签出的合同;检查正在运行的服务器 /api/openapi.json 如果您连接到另一个版本。

HTTP资源

健康

具有状态和时间戳的公共进程运行状况探测。

HTTP资源

系统

经过身份验证的准备情况和本机客户端使用的应用程序版本。

HTTP资源

项目

通过所有者和组织访问权限检查来创建、列出、读取、更新和删除项目。

HTTP资源

工作空间

只读项目图纸、组件、刀具路径、库资源以及配套客户端的有限预览。

HTTP资源

图纸

项目图形及其保存的几何图形、元数据和更新操作。

HTTP资源

成分

可重用的项目组件及其持久的设计数据。

HTTP资源

精确的CAD

分析精确的几何形状、导出 STEP 并从场景快照或保存的绘图中检查装配关系。

HTTP资源

刀具路径

保存加工程序、绘图关联和经过验证的便携式制造文档。

HTTP资源

项目刀具路径

使用特定于端点的响应包络列出和创建项目范围的刀具路径。

HTTP资源

加工

本机制造、设置驱动的 G 代码生成、建议、解析和重放验证。

HTTP资源

刀具路径历史记录

刀具路径版本、恢复、库发现和线程程序注释。

HTTP资源

材料

材料记录、应用加工属性和资源访问。

HTTP资源

物料储存

用于库交换的材料存储附件和 JSON 导入/导出。

HTTP资源

工具

应用加工工作流程使用的刀具记录和尺寸。

HTTP资源

工具存放

工具存储数据和收集或每个工具的导入/导出。

HTTP资源

机器

机器配置记录、更新、删除和克隆。

HTTP资源

机器存放

机器存储附件和配置导入/导出。

HTTP资源

图书馆

共享库记录以及组件、材料和工具查找集合。

HTTP资源

生产成本

估算、计算请求、材料成本、运营成本和工具磨损记录。

HTTP资源

AI 会议和行动

提供者、凭证、对话、流转、操作调用、桥接令牌、技能和会话恢复。

HTTP资源

历史和工作流程

项目与 Git 兼容的提交、分支、恢复、审查、GitHub 镜像和工作流程调度。

HTTP资源

项目活动

项目范围的服务器为实时客户端发送的事件。

HTTP资源

同伴配对

桌面网关状态、启用/禁用、设备配对和设备撤销。

HTTP资源

插件

插件注册表、包安装、配置、启用/禁用以及提供插件资源。

HTTP资源

MCP配置

MCP 连接配置 CRUD 和服务器信息请求。

HTTP资源

文件

使用端点特定的负载和响应编码进行上传和下载操作。

HTTP资源

键值存储

具有前缀列表和每键操作的 JSON 兼容首选项和上下文条目。

HTTP资源

组织机构

组织列表和管理的组织记录。

HTTP资源

通知

通知列表、已读状态更新、删除和标记为全部已读。

HTTP资源

验证

帐户登录、注册、恢复、验证、魔术链接、会话查找和密钥注册。

HTTP资源

用户

配置文件、帐户资源、API 密钥、令牌记录、密码和帐户删除。

HTTP资源

计费

订阅信息、Stripe 结帐/门户集成、试用维护和签名的 Webhook 摄取。

HTTP资源

分析

应用程序指标、最近活动、使用查询和跟踪请求。

HTTP资源

申请服务

桌面集成路线、跟踪的项目操作、通知和推送订阅记录。

HTTP资源

候补名单

通过本地应用程序 API 提交候补名单注册。

下载 OpenAPI JSON · 通过捕获的响应来跟踪请求

连接和请求约定

API 由本地 sidecar 提供,而不是由固定的托管端点提供。 Tauri 获取其动态选择的环回 URL 和启动令牌。手动启动的 sidecar 在 JSON 就绪事件中宣布其端口。配对的移动客户端改为通过其配置的 HTTPS 网关进行连接。

使用您当前的 sidecar 连接进行阅读
curl --silent --show-error "$CADCAMFUN_URL/api/projects" \
  --header "Authorization: Bearer $CADCAMFUN_TOKEN"

从实际连接设置这两个变量。资源页面上的请求模板故意使用占位符和负载文件。可选传输字段并不保证每个业务操作都可以省略它们:例如,项目创建会拒绝其处理程序中缺少的名称。

习俗客户行为
路径参数替换指定的段并对其值进行 URL 编码。将标识符视为单个段。
查询参数对声明的值进行编码。分页和过滤是针对每个端点的;没有通用的页面大小合同。
JSON 负载发送声明的对象 Content-Type: application/json。必需的存在和接受 null 是独立的。
多部分有效负载使用上传客户端或 FormData 构建表单部件;让运输选择它的边界。
二进制、JavaScript 或流响应使用声明的媒体类型。请勿致电 response.json() 无条件地。
错误检查 HTTP 状态并解码端点声明的故障形状。不同资源系列的误差范围有所不同。
重试写入在重新提交突变之前读取中断操作后的状态。该合约不提供通用的幂等密钥机制。

生成参考维护

packages/web/script/generate-api-reference.mjs 使用 API 包已安装的 Effect 实现读取组合合约并写入参考 JSON。文档Worker消费生成的内容;它不会初始化应用程序服务器来响应文档请求。

来自包/网络
bun run generate:api-reference
bun run check:api-reference
bun run check:docs-index

根据每个声明的操作检查资源覆盖率。新添加的组必须接收面向读者的元数据和导航,并且必须重新生成更改的请求或响应。手写指南仍然解释了授权规则、副作用、服务配置以及 HTTP 模式单独无法表达的限制。

整合食谱

开始于 捕获的 HTTP 请求 看看项目创建、业务验证、承载拒绝、相关记录和键值持久性实际如何响应。使用 类型化客户端集成 使用 Promise SDK 或 Effect 客户端重现这些操作并处理其不同的故障通道。

一体化程序要保留的关键状态
项目编辑创建、保存和重新打开工作项目/资源标识、保存的数据、实际更新语义。
制造流水线生成并保留本机作业捕获的请求、精确的 NC/程序、发布声明、匹配的便携式文档。
助理界面消耗事件并恢复会话项目/会话身份、待处理的权限/问题、终端状态。
外部能力编写受支持的插件清单、模块导出、能力授予、参数验证和工具结果。
审查自动化版本和审查项目工作提交/参考、结构差异、评论、提交的工作流程、单独的检查输出。
配对客户端启用和管理设备访问网关地址、证书指纹、可单独撤销的设备令牌。

这些方法将 HTTP 契约与真实的服务行为联系起来。模式可以描述所需的存在、编码和返回的形状;其链接指南解释了访问规则、持久性影响、支持的恢复以及不能单独从这些类型推断的限制。

每个资源组的操作

该合约目前在 270 组中声明了 34 操作,所有操作都在一个单独的 bearer HTTP 安全方案。唯一没有承载安全的操作是公共卫生探测。该表是根据生成的 OpenAPI 文档计算得出的:每组的操作、使用的 HTTP 方法、多少个不同的路径以及一个代表性路径。

团体标签行动方法路径示例路径
健康health1获取11/api/health
系统system2获取22/health
项目projects5删除 1、获取 2、发布 1、放置 12/api/projects
图纸drawings5删除 1、获取 2、发布 1、放置 12/api/drawings/{id}
成分components5删除 1、获取 2、发布 1、放置 12/api/components/{id}
精确的CADcadExact3发布 33/api/cad/exact/analyze
刀具路径toolpaths7删除 1、获取 3、发布 2、放置 13/api/drawings/{id}/toolpaths
项目刀具路径projectToolpaths2获取 1,发布 11/api/projects/{id}/toolpaths
加工toolpathGenerator5发布 55/api/toolpaths/generate
刀具路径历史记录toolpathExtras8删除 1、获取 3、发布 3、放置 15/api/toolpaths/library
材料materials5删除 1、获取 2、发布 1、放置 12/api/materials
物料储存materialsStorage5删除 1、获取 2、发布 22/api/materials/export-import
工具tools5删除 1、获取 2、发布 1、放置 12/api/tools
工具存放toolsStorage7删除 1、获取 3、发布 33/api/tools/export-import
机器machineConfigs6删除 1、获取 2、发布 2、放置 13/api/machine-configs
机器存放machineConfigsStorage5删除 1、获取 2、发布 22/api/machine-configs/export-import
图书馆library8删除 1、获取 5、发布 1、放置 15/api/library
生产成本production-costs21删除 4、获取 8、发布 5、放置 49/api/production-costs/estimates
AI 会议和行动ai34删除 3、获取 8、发布 21、放置 232/api/ai/actions
历史和工作流程vcs22获取 10、发布 11、放置 119/api/projects/{id}/actions/dispatch
项目活动events1获取11/api/projects/{id}/events
同伴配对companion5删除 1、获取 1、发布 35/api/companion
插件plugins16删除 1、获取 8、修补 1、发布 4、放置 212/api/plugins
MCP配置mcp8删除 2、获取 2、发布 2、放置 23/api/mcp/config
文件files2获取 1,发布 12/api/download
键值存储kv4删除 1、获取 2、放置 12/api/kv
组织机构organizations5删除 1、获取 2、发布 1、放置 12/api/organizations
通知notifications4删除 1、获取 1、发布 1、放置 13/api/notifications
验证auth12获取 1,发布 1112/api/auth/forgot-password
用户user16删除 2、获取 10、发布 2、放置 212/api/user/api-keys
计费billing15删除 1、获取 5、发布 8、放置 110/api/better-auth-stripe/billing-portal
分析analytics10删除 1、获取 7、发布 29/api/analytics
申请服务misc10删除 2、获取 3、发布 4、放置 16/api/app-control/notify
候补名单waitlist1发布 11/api/waitlist

整个合约的状态代码

每个操作对每个声明的响应进行一次计数,可以得出客户端必须准备好解码的内容:

地位宣布于典型身材
200242 操作资源、数组、可为空值或 Envelope
20128 操作创建的记录(例如 POST /api/projects)
2041操作没有身体
400206 操作BadRequest, EnvBadRequest 和特定家族的变体
401269 操作Unauthorized (承载中间件)
403101 操作Forbidden / EnvForbidden
404149 操作NotFound / EnvNotFound
40530 操作EnvMethodNotAllowed / KeyedMethodNotAllowed
40929 操作Conflict / EnvConflict
500264 操作InternalError, EnvInternal, KeyedInternal 和家族变体
501, 503每个 1 操作端点特定

每个错误都是一个 Effect 标记的错误,因此它的 JSON 正文始终包含一个 _tag 其字段旁边的鉴别器。共有三个主体系列,继承自旧处理程序,以便现有客户端继续工作:

普通错误(仅消息)
{ "_tag": "NotFound", "message": "Project not found" }
信封错误
{ "_tag": "EnvNotFound", "success": false, "message": "Material not found", "errors": null }
键控错误(一些库路由)
{ "_tag": "KeyedInternal", "error": "Failed to load components" }

成功信封反映了错误信封: { success: true, message, data }, 在哪里 data 或许 null。这 EnvelopeOpt 变体省略 message 当处理程序没有提供时。打开 _tag 而不是基于存在 message 或 error.

如何处理请求

客户获取/SDK 路线匹配方法+路径 不记名支票401 未经授权 模式解码400 错误输入 处理程序访问+逻辑 编码成功/_标签 x-session-token 选择代理帐户;缺失或无效回退到本地配置文件
  1. 路由器匹配方法和路径。未知的路线永远不会到达处理程序。
  2. 承载中间件在恒定时间内比较令牌。丢失或错误的令牌会在任何解码之前停止使用 401 的请求。
  3. 路径、查询、标头和正文根据操作的模式进行解码。如果不运行业务代码,结构问题就会变成 400。
  4. 处理程序解析代理帐户、检查所有权或组织成员身份 (403/404) 并运行服务。
  5. 结果使用声明的成功模式进行编码,或者使用其标记的错误模式和状态对失败进行编码。

非 JSON 的响应

手术媒体类型如何食用
POST /api/ai/chat/streamtext/event-stream增量阅读;每个 data: line 是一种类型化的辅助事件。
GET /api/projects/{id}/eventstext/event-stream现场项目活动;断开后重新连接并重新读取状态。
GET /api/plugins/bootstrap.jsapplication/javascript由插件主机加载,不解析为 JSON。
GET /api/plugins/serveapplication/octet-stream插件文件字节。
GET /api/downloadapplication/zip另存为文件;使用 response.blob() 或流式传输到磁盘。

生成的 Promise SDK 拒绝内容类型不是的流响应 text/event-stream 和 ClientError("UnsupportedContentType"),以及大于 16 MiB 的单个 SSE 事件 SseEventTooLarge.

无需客户端调用 API

最小类型的获取包装器
type TaggedError = { _tag: string; message?: string; error?: string }

async function call<T>(base: string, token: string, method: string, path: string, body?: unknown): Promise<T> {
  const response = await fetch(new URL(path, base), {
    method,
    headers: {
      authorization: `Bearer ${token}`,
      ...(body === undefined ? {} : { "content-type": "application/json" }),
    },
    body: body === undefined ? undefined : JSON.stringify(body),
  })
  if (response.status === 204) return undefined as T
  const payload = await response.json()
  if (!response.ok) {
    const failure = payload as TaggedError
    throw new Error(`${response.status} ${failure._tag}: ${failure.message ?? failure.error}`)
  }
  return payload as T
}

const project = await call<{ id: string; name: string }>(
  process.env.CADCAMFUN_URL!, process.env.CADCAMFUN_TOKEN!,
  "POST", "/api/projects", { name: "Bracket" },
)

更喜欢 TypeScript 中生成的客户端:它们知道每个操作的成功状态和声明的错误状态,并将其他任何内容视为 UnexpectedStatus 而不是猜测。

在 3D

API 按大小分组 拖动进行轨道旋转·滚动进行缩放·右键拖动进行平移
Every API group as a column, height = operations counted from the generated OpenAPI document (270 in total). Rows are the six sidebar categories; ai (34), history (22) and costs (21) are the largest groups.