docs(sdk): document DatabaseEventPayload and simplify its type (#20754)
closes https://discord.com/channels/1130383047699738754/1505967920163983502 Update logic-function docs to match the real `DatabaseEventPayload` shape. The docs now show database event payloads as record-level events with `recordId` and `properties.before/after/diff/updatedFields`, including compact examples for created, updated, and destroyed events. Route payload type imports now use the preferred `twenty-sdk/logic-function` surface. Also clean up the shared payload type wrapper so it models event metadata without over-promising actor fields; `userId`, `userWorkspaceId`, and `workspaceMemberId` remain optional through the underlying event type.
This commit is contained in:
@@ -13,8 +13,8 @@ Each function file uses `defineLogicFunction()` to export a configuration with a
|
||||
|
||||
```ts src/logic-functions/createPostCard.logic-function.ts
|
||||
import { defineLogicFunction } from 'twenty-sdk/define';
|
||||
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk/define';
|
||||
import { CoreApiClient, type Person } from 'twenty-client-sdk/core';
|
||||
import type { RoutePayload } from 'twenty-sdk/logic-function';
|
||||
import { CoreApiClient } from 'twenty-client-sdk/core';
|
||||
|
||||
const handler = async (params: RoutePayload) => {
|
||||
const client = new CoreApiClient();
|
||||
@@ -79,10 +79,10 @@ yarn twenty logs
|
||||
|
||||
When a route trigger invokes your logic function, it receives a `RoutePayload` object that follows the
|
||||
[AWS HTTP API v2 format](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html).
|
||||
Import the `RoutePayload` type from `twenty-sdk`:
|
||||
Import the `RoutePayload` type from `twenty-sdk/logic-function`:
|
||||
|
||||
```ts
|
||||
import { defineLogicFunction, type RoutePayload } from 'twenty-sdk/define';
|
||||
import type { RoutePayload } from 'twenty-sdk/logic-function';
|
||||
|
||||
const handler = async (event: RoutePayload) => {
|
||||
const { headers, queryStringParameters, pathParameters, body } = event;
|
||||
@@ -141,6 +141,115 @@ const handler = async (event: RoutePayload) => {
|
||||
Header names are normalized to lowercase. Access them using lowercase keys (e.g., `event.headers['content-type']`).
|
||||
</Note>
|
||||
|
||||
#### Database event trigger payload
|
||||
|
||||
When a database event trigger invokes your logic function, it receives one `DatabaseEventPayload` per changed record. The payload combines metadata about the source workspace and object with the record-level event.
|
||||
|
||||
```ts
|
||||
import type {
|
||||
DatabaseEventPayload,
|
||||
ObjectRecordCreateEvent,
|
||||
ObjectRecordDestroyEvent,
|
||||
ObjectRecordUpdateEvent,
|
||||
} from 'twenty-sdk/logic-function';
|
||||
|
||||
type Person = {
|
||||
id: string;
|
||||
emails?: { primaryEmail?: string };
|
||||
};
|
||||
```
|
||||
|
||||
The payload includes:
|
||||
|
||||
| Property | Description |
|
||||
|----------|-------------|
|
||||
| `name` | Event name, such as `person.updated`. |
|
||||
| `workspaceId` | Workspace where the event happened. |
|
||||
| `objectMetadata` | Metadata for the object that changed. |
|
||||
| `recordId` | Id of the changed record. |
|
||||
| `userId`, `userWorkspaceId`, `workspaceMemberId` | Actor fields when the event was caused by a workspace user. |
|
||||
| `properties` | Record data for the event, with `before`, `after`, `diff`, and `updatedFields` depending on the operation. |
|
||||
|
||||
| Event | Record data |
|
||||
|-------|-------------|
|
||||
| `person.created` | `event.properties.after` |
|
||||
| `person.updated` | `event.properties.before`, `event.properties.after`, `event.properties.diff`, `event.properties.updatedFields` |
|
||||
| `person.destroyed` | `event.properties.before` |
|
||||
|
||||
For soft deletes, `.deleted` follows the update-style shape because the record's `deletedAt` field changes.
|
||||
For permanent deletes, use `.destroyed`.
|
||||
|
||||
<Note>
|
||||
`databaseEventTriggerSettings.updatedFields` filters which update events trigger the function.
|
||||
`event.properties.updatedFields` tells you which fields actually changed on the current event.
|
||||
</Note>
|
||||
|
||||
Created event example:
|
||||
|
||||
```ts
|
||||
type PersonCreatedEvent = DatabaseEventPayload<
|
||||
ObjectRecordCreateEvent<Person>
|
||||
>;
|
||||
|
||||
const handler = async (event: PersonCreatedEvent) => {
|
||||
const person = event.properties.after;
|
||||
|
||||
return {
|
||||
personId: event.recordId,
|
||||
email: person.emails?.primaryEmail,
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Updated event example:
|
||||
|
||||
```ts
|
||||
type PersonUpdatedEvent = DatabaseEventPayload<
|
||||
ObjectRecordUpdateEvent<Person>
|
||||
>;
|
||||
|
||||
const handler = async (event: PersonUpdatedEvent) => {
|
||||
const { before, after, diff, updatedFields } = event.properties;
|
||||
|
||||
return {
|
||||
personId: event.recordId,
|
||||
updatedFields,
|
||||
previousEmail: before.emails?.primaryEmail,
|
||||
currentEmail: after.emails?.primaryEmail,
|
||||
emailDiff: diff.emails,
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
Trigger only on email updates:
|
||||
|
||||
```ts
|
||||
export default defineLogicFunction({
|
||||
...,
|
||||
databaseEventTriggerSettings: {
|
||||
eventName: 'person.updated',
|
||||
updatedFields: ['emails'],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Destroyed event example:
|
||||
|
||||
```ts
|
||||
type PersonDestroyedEvent = DatabaseEventPayload<
|
||||
ObjectRecordDestroyEvent<Person>
|
||||
>;
|
||||
|
||||
const handler = async (event: PersonDestroyedEvent) => {
|
||||
const personBeforeDestroy = event.properties.before;
|
||||
|
||||
return {
|
||||
personId: event.recordId,
|
||||
email: personBeforeDestroy.emails?.primaryEmail,
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
#### Exposing a function as an AI tool or workflow action
|
||||
|
||||
Logic functions can be exposed on two surfaces, each with its own trigger:
|
||||
|
||||
@@ -37,19 +37,11 @@ type SimplifiedFlatObjectMetadata = {
|
||||
viewUniversalIdentifiers: string[];
|
||||
};
|
||||
|
||||
type WorkspaceEventBatch<WorkspaceEvent> = {
|
||||
type DatabaseEventMetadata = {
|
||||
name: string;
|
||||
workspaceId: string;
|
||||
objectMetadata: SimplifiedFlatObjectMetadata;
|
||||
userId: string;
|
||||
userWorkspaceId: string;
|
||||
workspaceMemberId: string;
|
||||
recordId: string;
|
||||
events: WorkspaceEvent[];
|
||||
};
|
||||
|
||||
export type DatabaseEventPayload<T = ObjectRecordEvent> = Omit<
|
||||
WorkspaceEventBatch<T>,
|
||||
'events'
|
||||
> &
|
||||
T;
|
||||
export type DatabaseEventPayload<T = ObjectRecordEvent> =
|
||||
DatabaseEventMetadata & T;
|
||||
|
||||
Reference in New Issue
Block a user