defineLogicFunction
定义逻辑函数及其触发器
defineLogicFunction
定义逻辑函数及其触发器
每个函数文件都使用 可用的触发器类型:
在你的处理程序中,可以这样访问被转发的请求头:关键点:
defineLogicFunction() 导出包含处理程序和可选触发器的配置。src/logic-functions/createPostCard.logic-function.ts
- httpRoute:在
/s/端点下通过 HTTP 路径和方法公开你的函数:
例如path: '/post-card/create'可在https://your-twenty-server.com/s/post-card/create调用
- cron:使用 CRON 表达式按计划运行你的函数。
- databaseEvent:在工作空间对象生命周期事件上运行。 当事件操作为
updated时,可以在updatedFields数组中指定要监听的特定字段。 如果未定义或为空,任何更新都会触发该函数。
例如person.updated、*.created、company.*
你也可以使用 CLI 手动执行函数:你可以通过以下方式查看日志:
路由触发器负载
当路由触发器调用你的逻辑函数时,它会接收一个遵循 AWS HTTP API v2 格式的RoutePayload 对象。
从 twenty-sdk 导入 RoutePayload 类型:RoutePayload 类型具有以下结构:| 属性 | 类型 | 描述 | 示例 |
|---|---|---|---|
headers | Record\<string, string | undefined> | HTTP 请求头(仅限 forwardedRequestHeaders 中列出的那些) | 见下文 |
queryStringParameters | Record\<string, string | undefined> | 查询字符串参数(多个值以逗号连接) | /users?ids=1&ids=2&ids=3&name=Alice -> { ids: '1,2,3', name: 'Alice' } |
pathParameters | Record\<string, string | undefined> | 从路由模式中提取的路径参数 | /users/:id,/users/123 -> { id: '123' } |
body | object | null | 已解析的请求体(JSON) | { id: 1 } -> { id: 1 } |
isBase64Encoded | boolean | 请求体是否为 base64 编码 | |
requestContext.http.method | string | HTTP 方法(GET、POST、PUT、PATCH、DELETE) | |
requestContext.http.path | string | 原始请求路径 |
forwardedRequestHeaders
出于安全原因,默认不会将传入请求的 HTTP 请求头传递给你的逻辑函数。 如需访问特定请求头,请在forwardedRequestHeaders 数组中显式列出:请求头名称会被规范化为小写。 请使用小写键访问它们(例如,
event.headers['content-type'])。将函数作为工具公开
逻辑函数可以作为供 AI 智能体和工作流使用的工具对外提供。 当函数被标记为工具时,Twenty 的 AI 功能即可发现它,并可在工作流自动化中使用。要将逻辑函数标记为工具,请设置isTool: true:src/logic-functions/enrich-company.logic-function.ts
- 你可以将
isTool与触发器结合使用——一个函数既可以作为工具(由 AI 智能体调用),也可以同时由事件触发。 toolInputSchema(可选):描述函数可接受参数的 JSON Schema 对象。 该模式会通过对源代码的静态分析自动推导,但你也可以显式设置:
写一个好的
description。 AI 智能体会依赖该函数的 description 字段来决定何时使用该工具。 明确说明该工具的作用以及应在何时调用。definePostInstallLogicFunction
定义一个安装后逻辑函数(每个应用一个)
definePostInstallLogicFunction
定义一个安装后逻辑函数(每个应用一个)
安装后函数是在你的应用安装到工作区后自动运行的逻辑函数。 服务器会在应用的元数据已同步并已生成 SDK 客户端之后执行它,因此工作区已完全可用,且新架构已就绪。 常见用例包括预置默认数据、创建初始记录、配置工作区设置,或在第三方服务上预配资源。你也可以随时使用 CLI 手动执行安装后函数:关键点:
src/logic-functions/post-install.ts
- 安装后函数使用
definePostInstallLogicFunction()—— 这是一个省略触发器设置(cronTriggerSettings、databaseEventTriggerSettings、httpRouteTriggerSettings、isTool)的专用变体。 - 处理程序会接收一个
InstallPayload,其为{ previousVersion?: string; newVersion: string }——newVersion是正在安装的版本,而previousVersion是先前已安装的版本(在全新安装时为undefined)。 使用这些值来区分全新安装与升级,并运行特定版本的迁移逻辑。 - 钩子何时运行:默认情况下,仅在全新安装时运行。 如果还希望在应用从旧版本升级时运行,请传入
shouldRunOnVersionUpgrade: true。 若省略,该标志默认为false,升级将跳过该钩子。 - 执行模型 — 默认异步,可选择同步:
shouldRunSynchronously标志控制安装后如何执行。shouldRunSynchronously: false(默认) — 该钩子会加入消息队列,设置retryLimit: 3,并在工作线程中异步运行。 作业一入列,安装响应即返回,因此缓慢或失败的处理程序不会阻塞调用方。 工作线程最多会重试三次。 将其用于长时间运行的作业——预填充大型数据集、调用缓慢的第三方 API、预配外部资源,以及任何可能超出合理 HTTP 响应窗口的任务。shouldRunSynchronously: true— 该钩子会在安装流程中内联执行(与安装前使用相同的执行器)。 安装请求将阻塞直至处理程序完成;若抛出异常,安装调用方将收到POST_INSTALL_ERROR。 不进行自动重试。 用于需要在响应前完成的快速工作——例如向用户返回验证错误,或进行安装调用返回后客户端将立即依赖的快速设置。 请注意,运行安装后时,元数据迁移已应用完成,因此同步模式下的失败不会回滚架构更改——它只会暴露错误。
- 确保你的处理程序是幂等的。 在异步模式下,队列最多可重试三次;在任一模式下,当
shouldRunOnVersionUpgrade: true时,该钩子在升级时可能再次运行。 - 在处理程序内可使用环境变量
APPLICATION_ID、APP_ACCESS_TOKEN和API_URL(与其他逻辑函数相同),因此你可以使用作用域限定到你应用的应用访问令牌调用 Twenty API。 - 每个应用仅允许一个安装后函数。 如果检测到多个,清单构建将报错。
- 构建期间,函数的
universalIdentifier、shouldRunOnVersionUpgrade和shouldRunSynchronously会自动附加到应用清单的postInstallLogicFunction字段下——你无需在defineApplication()中引用它们。 - 默认超时时间设置为 300 秒(5 分钟),以便支持更长的设置任务,如数据填充。
- 开发模式下不执行:当应用在本地注册(通过
yarn twenty dev)时,服务器会完全跳过安装流程,并通过 CLI 监视器直接同步文件——因此无论shouldRunSynchronously如何,安装后在开发模式下都不会运行。 使用yarn twenty exec --postInstall在运行中的工作区上手动触发它。
definePreInstallLogicFunction
定义一个安装前逻辑函数(每个应用一个)
definePreInstallLogicFunction
定义一个安装前逻辑函数(每个应用一个)
安装前函数是在安装期间自动运行的逻辑函数,在应用工作区元数据迁移之前。 它与安装后共享相同的负载结构(你也可以随时使用 CLI 手动执行安装前函数:关键点:
InstallPayload),但在安装流程中位置更早,因此可以准备即将到来的迁移所依赖的状态——典型用例如备份数据、验证与新架构的兼容性,或归档即将被重构或删除的记录。src/logic-functions/pre-install.ts
- 安装前函数使用
definePreInstallLogicFunction()——与安装后相同的专用配置,只是附加到不同的生命周期阶段。 - 安装前和安装后处理程序接收相同的
InstallPayload类型:{ previousVersion?: string; newVersion: string }。 导入一次,可在两个钩子中复用。 - 钩子何时运行:位于工作区元数据迁移(
synchronizeFromManifest)之前。 在执行之前,服务器会运行一次纯增量的“精简同步”,将新版本的安装前函数注册到工作区元数据中——不会触及其他任何内容——然后再执行它。 由于此次同步仅为增量操作,当你的处理程序运行时,上一版本的对象、字段和数据仍完好无损:你可以安全地读取并备份迁移前的状态。 - 执行模型:安装前以同步方式执行,并且会阻塞安装。 如果处理程序抛出异常,安装会在任何架构更改应用之前被中止——工作区将保持在上一版本且处于一致状态。 这是有意为之:安装前是你拒绝高风险升级的最后机会。
- 与安装后相同,每个应用仅允许一个安装前函数。 在构建期间,它会自动附加到应用清单的
preInstallLogicFunction下。 - 开发模式下不执行:与安装后相同——对于本地注册的应用将完全跳过安装流程,因此在
yarn twenty dev下不会运行安装前。 使用yarn twenty exec --preInstall手动触发它。
安装前 vs 安装后:何时使用哪一个
选择合适的安装钩子
安装前 vs 安装后:何时使用哪一个
选择合适的安装钩子
两个钩子都属于同一安装流程,并接收相同的 安装前始终为同步(会阻塞安装并可中止它)。 安装后默认异步——在工作线程中入列并自动重试——但可通过 当迁移可能破坏或损坏现有数据时,请使用 经验法则:
InstallPayload。 区别在于它们相对于工作区元数据迁移何时运行,这会影响它们可以安全访问的数据范围。shouldRunSynchronously: true 选择同步执行。 关于各模式的使用场景,请参见上方的 definePostInstallLogicFunction 折叠面板。对于需要新架构已存在的任何事项,请使用 post-install。 这是最常见的情况:- 针对新添加的对象和字段预填充默认数据(创建初始记录、默认视图、演示内容)。
- 在应用已有凭据的前提下,向第三方服务注册 Webhook。
- 调用你自己的 API 完成依赖已同步元数据的设置。
- 用于在每次升级时对状态进行对账的幂等“确保其存在”逻辑——结合
shouldRunOnVersionUpgrade: true使用。
PostCard 记录:src/logic-functions/post-install.ts
pre-install。 由于安装前在先前架构上运行,且其失败会回滚升级,因此凡是有风险的操作都应放在这里:- 备份即将被删除或重构的数据——例如,你在 v2 中移除某个字段,需要在迁移运行前将其值复制到另一个字段或导出到存储中。
- 归档会被新约束判为无效的记录——例如某个字段将变为
NOT NULL,你需要先删除或修正具有空值的行。 - 验证兼容性;若当前数据无法干净迁移则拒绝升级——从处理程序中抛出异常,安装将中止且不会应用任何更改。 这比在迁移中途才发现不兼容要更安全。
- 在会导致关联丢失的架构更改之前对数据进行重命名或重新设置键。
src/logic-functions/pre-install.ts
| You want to… | 使用 |
|---|---|
| 预填充默认数据、配置工作区、注册外部资源 | post-install |
| 运行不应阻塞安装响应的长时间预填充或第三方调用 | post-install (默认 — shouldRunSynchronously: false,由工作线程重试) |
| 运行安装调用返回后调用方将立即依赖的快速设置 | post-install,配合 shouldRunSynchronously: true |
| 读取或备份即将被迁移丢失的数据 | pre-install |
| 拒绝会损坏现有数据的升级 | pre-install(从处理程序中抛出异常) |
| 在每次升级时执行对账 | post-install 配合 shouldRunOnVersionUpgrade: true |
| 仅在首次安装时执行一次性设置 | post-install 配合 shouldRunOnVersionUpgrade: false(默认) |
如有不确定,默认选择安装后(post-install)。 仅当迁移本身具有破坏性,且你需要在其丢失之前拦截先前状态时,才使用安装前。
类型化 API 客户端(twenty-client-sdk)
twenty-client-sdk 包提供了两个类型化的 GraphQL 客户端,供你的逻辑函数和前端组件与 Twenty API 交互。
| 客户端 | 导入 | 端点 | 是否生成? |
|---|---|---|---|
CoreApiClient | twenty-client-sdk/core | /graphql——工作区数据(记录、对象) | 是,在开发/构建时 |
MetadataApiClient | twenty-client-sdk/metadata | /metadata——工作区配置、文件上传 | 否,已预构建提供 |
CoreApiClient
查询和变更工作区数据(记录、对象)
CoreApiClient
查询和变更工作区数据(记录、对象)
CoreApiClient 是用于查询和变更工作区数据的主要客户端。 它会在执行 yarn twenty dev 或 yarn twenty build 时根据你的工作区架构生成,因此完全类型化以匹配你的对象和字段。true 以包含某字段,使用 __args 传递参数,并通过嵌套对象表示关系。 你将基于工作区架构获得完整的自动补全和类型检查。CoreApiClient 在开发/构建时生成。 如果在未先运行
yarn twenty dev 或 yarn twenty build 的情况下尝试使用它,将会抛出错误。 该生成过程是自动完成的——CLI 会自省你的工作区 GraphQL 架构,并使用 @genql/cli 生成类型化客户端。使用 CoreSchema 进行类型标注
CoreSchema 提供与工作区对象相匹配的 TypeScript 类型,可用于为组件状态或函数参数进行类型标注:MetadataApiClient
工作区配置、应用和文件上传
MetadataApiClient
工作区配置、应用和文件上传
MetadataApiClient 随 SDK 一并提供,已预构建(无需生成)。 它会查询 /metadata 端点以获取工作区配置、应用和文件上传。上传文件
MetadataApiClient 包含一个 uploadFile 方法,用于将文件附加到文件类型字段:| 参数 | 类型 | 描述 |
|---|---|---|
fileBuffer | Buffer | 原始文件内容 |
filename | string | 文件名称(用于存储和显示) |
contentType | string | MIME 类型(如果省略,默认为 application/octet-stream) |
fieldMetadataUniversalIdentifier | string | 你的对象上文件类型字段的 universalIdentifier |
- 使用字段的
universalIdentifier(而不是其工作区特定的 ID),因此你的上传代码可在安装了你的应用的任何工作区中运行。 - 返回的
url是一个签名 URL,你可以用它来访问已上传的文件。
当你的代码在 Twenty 上运行(逻辑函数或前端组件)时,平台会以环境变量的形式注入凭据:
TWENTY_API_URL——Twenty API 的基础 URLTWENTY_APP_ACCESS_TOKEN——作用域限定为你的应用默认函数角色的短期密钥
process.env 读取。 API 密钥的权限由你的 application-config.ts 中 defaultRoleUniversalIdentifier 引用的角色决定。