i18n - docs translations (#22715)
Created by Github action <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/22715?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> Co-authored-by: github-actions <github-actions@twenty.com>
This commit is contained in:
committed by
GitHub
parent
a0cf4cc9e1
commit
ebee7d71b9
@@ -4,7 +4,7 @@ description: 在安装之前或之后运行逻辑——预置数据、备份记
|
||||
icon: wrench
|
||||
---
|
||||
|
||||
安装钩子是在安装或升级生命周期期间运行的特殊逻辑函数。 它们与常规的[逻辑函数](/l/zh/developers/extend/apps/logic/logic-functions)共享相同的处理程序运行时,并接收 `InstallPayload`,但它们使用自己的定义函数声明——`definePostInstallLogicFunction()` 和 `definePreInstallLogicFunction()`——并且存在于普通触发模型(HTTP、cron、数据库事件)之外。
|
||||
安装钩子是在安装或升级生命周期期间运行的特殊逻辑函数。 它们与常规的[逻辑函数](/l/zh/developers/extend/apps/logic/logic-functions)共享相同的处理程序运行时,并接收一个 `InstallPayload`(`{ previousVersion?: string; newVersion: string }`——在全新安装时 `previousVersion` 为 `undefined`),但它们使用自己的 define 函数声明,并且存在于普通触发模型(HTTP、cron、数据库事件)之外。
|
||||
|
||||
每个应用**最多只能定义一个安装前函数**和**最多一个安装后函数**。 如果检测到任一类型多于一个,清单构建将报错。
|
||||
|
||||
@@ -19,111 +19,59 @@ icon: wrench
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="definePostInstallLogicFunction" description="在应用工作区元数据迁移之后运行">
|
||||
## 一览
|
||||
|
||||
安装后函数会在你的应用完成安装到某个工作区后自动运行。 服务器会在应用的元数据已同步并已生成 SDK 客户端**之后**执行它,因此工作区已完全可用,且新架构已就绪。 常见用例包括预置默认数据、创建初始记录、配置工作区设置,或在第三方服务上预配资源。
|
||||
| | `definePreInstallLogicFunction` | `definePostInstallLogicFunction` |
|
||||
| ---- | ------------------------------- | --------------------------------------------------------- |
|
||||
| 运行 | 元数据迁移之前——**先前**的模式和数据仍然完好无损 | 迁移和 SDK 生成之后——**新的**模式已就位 |
|
||||
| 执行 | 始终为同步;会阻塞安装 | 默认异步(排队,重试 3 次);可通过 `shouldRunSynchronously: true` 选择同步 |
|
||||
| 失败时 | 安装在任何模式更改之前被**中止** | 异步:最多重试 3 次。 同步:调用方会收到 `POST_INSTALL_ERROR`(模式更改**不会**回滚) |
|
||||
| 典型用途 | 备份或修复迁移会丢失的数据;通过抛出异常拒绝存在风险的升级 | 预填充默认数据、配置工作区、注册外部资源 |
|
||||
|
||||
```ts src/logic-functions/post-install.ts
|
||||
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
|
||||
**经验法则:** 默认使用 post-install。 仅当迁移本身具有破坏性,且你需要在其丢失之前拦截先前状态时,才使用安装前。
|
||||
|
||||
const handler = async (payload: InstallPayload): Promise<void> => {
|
||||
console.log('Post install logic function executed successfully!', payload.previousVersion);
|
||||
};
|
||||
| 你想要... | 使用 |
|
||||
| ------------------ | ------------------------------------------------ |
|
||||
| 预填充数据、配置工作区、注册外部资源 | `post-install` |
|
||||
| 不应阻塞安装响应的长时间运行任务 | `post-install`(默认异步模式,带工作线程重试) |
|
||||
| 安装返回后调用方会立即依赖的快速设置 | `post-install`,配合 `shouldRunSynchronously: true` |
|
||||
| 读取或备份即将被迁移丢失的数据 | `pre-install` |
|
||||
| 拒绝会损坏现有数据的升级 | `pre-install`(从处理程序中抛出异常) |
|
||||
| 在每次升级时执行对账 | 任一钩子配合 `shouldRunOnVersionUpgrade: true` |
|
||||
|
||||
export default definePostInstallLogicFunction({
|
||||
universalIdentifier: 'f7a2b9c1-3d4e-5678-abcd-ef9876543210',
|
||||
name: 'post-install',
|
||||
description: 'Runs after installation to set up the application.',
|
||||
timeoutSeconds: 300,
|
||||
shouldRunOnVersionUpgrade: false,
|
||||
shouldRunSynchronously: false,
|
||||
handler,
|
||||
});
|
||||
```
|
||||
## 两个钩子共享的行为
|
||||
|
||||
你也可以随时使用 CLI 手动执行安装后函数:
|
||||
* 该配置等同于 `defineLogicFunction` 的配置减去触发器设置,再加上 `shouldRunOnVersionUpgrade`。
|
||||
* **运行时机**:默认情况下,仅在全新安装时运行。 将 `shouldRunOnVersionUpgrade: true` 设为 true 以便在升级时也运行。 使用 `previousVersion` / `newVersion` 按升级路径分支处理。
|
||||
* **幂等性很重要**:异步 post-install 可能会被重试,而且当开启 `shouldRunOnVersionUpgrade` 时,任一钩子都会在升级时重新运行。
|
||||
* 会注入常规的逻辑函数环境(`APPLICATION_ID`、`APP_ACCESS_TOKEN`、`API_URL`),因此你可以使用应用的令牌调用 Twenty API。
|
||||
* 该钩子会在构建时自动附加到应用清单上(`preInstallLogicFunction` / `postInstallLogicFunction`)——在 [`defineApplication()`](/l/zh/developers/extend/apps/config/application) 中无需额外引用。
|
||||
* 默认的 `timeoutSeconds` 为 300,以便支持更长的设置任务,例如数据填充。
|
||||
* **在开发模式下不会执行**:`yarn twenty dev` 会跳过安装流程并直接同步文件,因此钩子在其中不会运行。 改为手动触发它们:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty dev:function:exec --postInstall
|
||||
```
|
||||
|
||||
关键点:
|
||||
* 安装后函数使用 `definePostInstallLogicFunction()` — 这是一个省略触发器设置(`cronTriggerSettings`、`databaseEventTriggerSettings`、`httpRouteTriggerSettings`、`toolTriggerSettings`、`workflowActionTriggerSettings`)的专用变体。
|
||||
* 处理程序会接收一个 `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()`](/l/zh/developers/extend/apps/config/application) 中引用它们。
|
||||
* 默认超时时间设置为 300 秒(5 分钟),以便支持更长的设置任务,如数据填充。
|
||||
* **开发模式下不执行**:当应用在本地注册(通过 `yarn twenty dev`)时,服务器会完全跳过安装流程,并通过 CLI 监视器直接同步文件——因此无论 `shouldRunSynchronously` 如何,安装后在开发模式下都不会运行。 使用 `yarn twenty dev:function:exec --postInstall` 在运行中的工作区上手动触发它。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="definePreInstallLogicFunction" description="在应用工作区元数据迁移之前运行">
|
||||
|
||||
安装前函数会在安装期间自动运行,**在应用工作区元数据迁移之前**。 它与安装后共享相同的负载结构(`InstallPayload`),但在安装流程中位置更早,因此可以准备即将到来的迁移所依赖的状态——典型用例如备份数据、验证与新架构的兼容性,或归档即将被重构或删除的记录。
|
||||
|
||||
```ts src/logic-functions/pre-install.ts
|
||||
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
|
||||
|
||||
const handler = async (payload: InstallPayload): Promise<void> => {
|
||||
console.log('Pre install logic function executed successfully!', payload.previousVersion);
|
||||
};
|
||||
|
||||
export default definePreInstallLogicFunction({
|
||||
universalIdentifier: 'a1b2c3d4-5678-90ab-cdef-1234567890ab',
|
||||
name: 'pre-install',
|
||||
description: 'Runs before installation to prepare the application.',
|
||||
timeoutSeconds: 300,
|
||||
shouldRunOnVersionUpgrade: true,
|
||||
handler,
|
||||
});
|
||||
```
|
||||
|
||||
你也可以随时使用 CLI 手动执行安装前函数:
|
||||
|
||||
```bash filename="Terminal"
|
||||
yarn twenty dev:function:exec --preInstall
|
||||
```
|
||||
|
||||
关键点:
|
||||
* 安装前函数使用 `definePreInstallLogicFunction()`——与安装后相同的专用配置,只是附加到不同的生命周期阶段。
|
||||
* 安装前和安装后处理程序接收相同的 `InstallPayload` 类型:`{ previousVersion?: string; newVersion: string }`。 导入一次,可在两个钩子中复用。
|
||||
* **钩子何时运行**:位于工作区元数据迁移(`synchronizeFromManifest`)之前。 在执行之前,服务器会运行一次纯增量的“精简同步”,将**新**版本的安装前函数注册到工作区元数据中——不会触及其他任何内容——然后再执行它。 由于此次同步仅为增量操作,当你的处理程序运行时,上一版本的对象、字段和数据仍完好无损:你可以安全地读取并备份迁移前的状态。
|
||||
* **执行模型**:安装前以**同步**方式执行,并且**会阻塞安装**。 如果处理程序抛出异常,安装会在任何架构更改应用之前被中止——工作区将保持在上一版本且处于一致状态。 这是有意为之:安装前是你拒绝高风险升级的最后机会。
|
||||
* 与安装后相同,每个应用仅允许一个安装前函数。 在构建期间,它会自动附加到应用清单的 `preInstallLogicFunction` 下。
|
||||
* **开发模式下不执行**:与安装后相同——对于本地注册的应用将完全跳过安装流程,因此在 `yarn twenty dev` 下不会运行安装前。 使用 `yarn twenty dev:function:exec --preInstall` 手动触发它。
|
||||
<AccordionGroup>
|
||||
<Accordion title="definePostInstallLogicFunction" description="在应用工作区元数据迁移之后运行">
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="安装前 vs 安装后:何时使用哪一个" description="选择合适的安装钩子">
|
||||
|
||||
两个钩子都属于同一安装流程,并接收相同的 `InstallPayload`。 区别在于它们相对于工作区元数据迁移**何时**运行,这会影响它们可以安全访问的数据范围。
|
||||
|
||||
安装前始终为**同步**(会阻塞安装并可中止它)。 安装后**默认异步**——在工作线程中入列并自动重试——但可通过 `shouldRunSynchronously: true` 选择同步执行。 关于各模式的使用场景,请参见上方的 `definePostInstallLogicFunction` 折叠面板。
|
||||
|
||||
**对于需要新架构已存在的任何事项,请使用 `post-install`。** 这是最常见的情况:
|
||||
|
||||
* 针对新添加的对象和字段预填充默认数据(创建初始记录、默认视图、演示内容)。
|
||||
* 在应用已有凭据的前提下,向第三方服务注册 Webhook。
|
||||
* 调用你自己的 API 完成依赖已同步元数据的设置。
|
||||
* 用于在每次升级时对状态进行对账的幂等“确保其存在”逻辑——结合 `shouldRunOnVersionUpgrade: true` 使用。
|
||||
|
||||
示例——在安装后预填充一个默认的 `PostCard` 记录:
|
||||
在应用完成安装后运行:元数据已同步、SDK 客户端已生成、新模式可被查询。 示例——在全新安装时预填充一个默认记录:
|
||||
|
||||
```ts src/logic-functions/post-install.ts
|
||||
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
|
||||
import { createClient } from './generated/client';
|
||||
import { CoreApiClient } from 'twenty-client-sdk/core';
|
||||
|
||||
const handler = async ({ previousVersion }: InstallPayload): Promise<void> => {
|
||||
if (previousVersion) return; // fresh installs only
|
||||
|
||||
const client = createClient();
|
||||
await client.postCard.create({
|
||||
data: { title: 'Welcome to Postcard', content: 'Your first card!' },
|
||||
const client = new CoreApiClient();
|
||||
await client.mutation({
|
||||
createPostCard: {
|
||||
__args: { data: { name: 'Welcome to Postcard', content: 'Your first card!' } },
|
||||
id: true,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -133,22 +81,28 @@ export default definePostInstallLogicFunction({
|
||||
description: 'Seeds a welcome post card after install.',
|
||||
timeoutSeconds: 300,
|
||||
shouldRunOnVersionUpgrade: false,
|
||||
shouldRunSynchronously: false,
|
||||
handler,
|
||||
});
|
||||
```
|
||||
|
||||
**当迁移可能破坏或损坏现有数据时,请使用 `pre-install`。** 由于安装前在*先前*架构上运行,且其失败会回滚升级,因此凡是有风险的操作都应放在这里:
|
||||
`shouldRunSynchronously` 标志控制执行模型:
|
||||
|
||||
* **备份即将被删除或重构的数据**——例如,你在 v2 中移除某个字段,需要在迁移运行前将其值复制到另一个字段或导出到存储中。
|
||||
* **归档会被新约束判为无效的记录**——例如某个字段将变为 `NOT NULL`,你需要先删除或修正具有空值的行。
|
||||
* **验证兼容性;若当前数据无法干净迁移则拒绝升级**——从处理程序中抛出异常,安装将中止且不会应用任何更改。 这比在迁移中途才发现不兼容要更安全。
|
||||
* **在会导致关联丢失的架构更改之前**对数据进行重命名或重新设置键。
|
||||
* `false` *(默认)*——放入消息队列(`retryLimit: 3`)并由工作线程运行。 安装响应会在任务被放入队列后立即返回。 **用于长时间运行的任务**——例如预填充大型数据集、调用缓慢的第三方 API。
|
||||
* `true`——在安装流程中内联执行。 安装请求会阻塞直至处理程序完成;抛出的错误会以 `POST_INSTALL_ERROR` 的形式暴露给调用方(不重试)。 **用于必须在返回响应前完成的快速任务。** 此时迁移已应用,因此失败不会回滚模式更改——只会将错误暴露出来。
|
||||
|
||||
示例——在破坏性迁移之前归档记录:
|
||||
</Accordion>
|
||||
<Accordion title="definePreInstallLogicFunction" description="在应用工作区元数据迁移之前运行">
|
||||
|
||||
在元数据迁移之前、针对**先前**模式运行——适合在迁移会删除数据前对其进行备份,或拒绝存在风险的升级。 在执行之前,服务器会运行一次纯增量的“精简同步”,仅注册新版本的 pre-install 函数;当你的处理程序运行时,其他一切——上一版本的对象、字段和数据——都不会被触及。
|
||||
|
||||
安装前始终为**同步**,并会阻塞安装。 如果处理程序抛出异常,安装会在任何模式更改之前被中止——工作区将保持在上一版本且处于一致状态。 这是有意为之:安装前是你拒绝高风险升级的最后机会。
|
||||
|
||||
示例——在迁移删除旧字段之前复制该旧字段的值:
|
||||
|
||||
```ts src/logic-functions/pre-install.ts
|
||||
import { definePreInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
|
||||
import { createClient } from './generated/client';
|
||||
import { CoreApiClient } from 'twenty-client-sdk/core';
|
||||
|
||||
const handler = async ({ previousVersion, newVersion }: InstallPayload): Promise<void> => {
|
||||
// Only the 1.x → 2.x upgrade drops the legacy `notes` field.
|
||||
@@ -156,24 +110,24 @@ const handler = async ({ previousVersion, newVersion }: InstallPayload): Promise
|
||||
return;
|
||||
}
|
||||
|
||||
const client = createClient();
|
||||
const legacyRecords = await client.postCard.findMany({
|
||||
where: { notes: { isNotNull: true } },
|
||||
const client = new CoreApiClient();
|
||||
const { postCards } = await client.query({
|
||||
postCards: {
|
||||
__args: { filter: { notes: { isNot: null } } },
|
||||
edges: { node: { id: true, notes: true } },
|
||||
},
|
||||
});
|
||||
|
||||
if (legacyRecords.length === 0) return;
|
||||
|
||||
// Copy legacy `notes` into the new `description` field before the migration
|
||||
// drops the `notes` column. If this fails, the upgrade is aborted and the
|
||||
// workspace stays on v1 with all data intact.
|
||||
await Promise.all(
|
||||
legacyRecords.map((record) =>
|
||||
client.postCard.update({
|
||||
where: { id: record.id },
|
||||
data: { description: record.notes },
|
||||
}),
|
||||
),
|
||||
);
|
||||
// Copy legacy `notes` into `description` before the migration drops the
|
||||
// column. If this fails, the upgrade aborts and the workspace stays on v1.
|
||||
for (const { node } of postCards.edges) {
|
||||
await client.mutation({
|
||||
updatePostCard: {
|
||||
__args: { id: node.id, data: { description: node.notes } },
|
||||
id: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default definePreInstallLogicFunction({
|
||||
@@ -186,21 +140,5 @@ export default definePreInstallLogicFunction({
|
||||
});
|
||||
```
|
||||
|
||||
**经验法则:**
|
||||
|
||||
| 你想要... | 使用 |
|
||||
| ----------------------- | ------------------------------------------------------------- |
|
||||
| 预填充默认数据、配置工作区、注册外部资源 | `post-install` |
|
||||
| 运行不应阻塞安装响应的长时间预填充或第三方调用 | `post-install` (默认 — `shouldRunSynchronously: false`,由工作线程重试) |
|
||||
| 运行安装调用返回后调用方将立即依赖的快速设置 | `post-install`,配合 `shouldRunSynchronously: true` |
|
||||
| 读取或备份即将被迁移丢失的数据 | `pre-install` |
|
||||
| 拒绝会损坏现有数据的升级 | `pre-install`(从处理程序中抛出异常) |
|
||||
| 在每次升级时执行对账 | `post-install` 配合 `shouldRunOnVersionUpgrade: true` |
|
||||
| 仅在首次安装时执行一次性设置 | `post-install` 配合 `shouldRunOnVersionUpgrade: false`(默认) |
|
||||
|
||||
<Note>
|
||||
如有不确定,默认选择**安装后(post-install)**。 仅当迁移本身具有破坏性,且你需要在其丢失之前拦截先前状态时,才使用安装前。
|
||||
</Note>
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
Reference in New Issue
Block a user