mirror of
https://github.com/twentyhq/twenty
synced 2026-04-21 13:37:22 +00:00
Move all sync entities in an `entities` key. Rename functions to
logicFunctions
```json
{
application: {
...
},
entities: {
objects: [],
logicFunctions: [],
...
}
}
```
654 lines
27 KiB
Text
654 lines
27 KiB
Text
---
|
||
title: Twenty Uygulamaları
|
||
description: Twenty özelleştirmelerini kod olarak oluşturun ve yönetin.
|
||
---
|
||
|
||
<Warning>
|
||
Uygulamalar şu anda alfa testinde. Özellik işlevsel ancak hâlâ gelişmekte.
|
||
</Warning>
|
||
|
||
## Uygulamalar Nedir?
|
||
|
||
Uygulamalar, Twenty özelleştirmelerini **kod olarak** oluşturup yönetmenizi sağlar. Her şeyi UI üzerinden yapılandırmak yerine, veri modelinizi ve mantık fonksiyonlarınızı kodla tanımlarsınız — bu da oluşturmayı, bakımı ve birden çok çalışma alanına dağıtmayı hızlandırır.
|
||
|
||
**Bugün Yapabilecekleriniz:**
|
||
|
||
* Özel nesneleri ve alanları kod olarak tanımlayın (yönetilen veri modeli)
|
||
* Özel tetikleyicilerle mantık fonksiyonları oluşturun
|
||
* Aynı uygulamayı birden çok çalışma alanına dağıtın
|
||
|
||
**Yakında:**
|
||
|
||
* Özel UI düzenleri ve bileşenleri
|
||
|
||
## Ön Gereksinimler
|
||
|
||
* Node.js 24+ ve Yarn 4
|
||
* Bir Twenty çalışma alanı ve bir API anahtarı (https://app.twenty.com/settings/api-webhooks adresinde oluşturun)
|
||
|
||
## Başlarken
|
||
|
||
Resmi scaffolder aracını kullanarak yeni bir uygulama oluşturun, ardından kimlik doğrulaması yapıp geliştirmeye başlayın:
|
||
|
||
```bash filename="Terminal"
|
||
# Scaffold a new app
|
||
npx create-twenty-app@latest my-twenty-app
|
||
cd my-twenty-app
|
||
|
||
# If you don't use yarn@4
|
||
corepack enable
|
||
yarn install
|
||
|
||
# Authenticate using your API key (you'll be prompted)
|
||
yarn auth:login
|
||
|
||
# Start dev mode: automatically syncs local changes to your workspace
|
||
yarn app:dev
|
||
```
|
||
|
||
Buradan şunları yapabilirsiniz:
|
||
|
||
```bash filename="Terminal"
|
||
# Add a new entity to your application (guided)
|
||
yarn entity:add
|
||
|
||
# Generate a typed Twenty client and workspace entity types
|
||
yarn app:generate
|
||
|
||
# Watch your application's function logs
|
||
yarn function:logs
|
||
|
||
# Execute a function by name
|
||
yarn function:execute -n my-function -p '{"name": "test"}'
|
||
|
||
# Uninstall the application from the current workspace
|
||
yarn app:uninstall
|
||
|
||
# Display commands' help
|
||
yarn help
|
||
```
|
||
|
||
Ayrıca bkz.: [create-twenty-app](https://www.npmjs.com/package/create-twenty-app) ve [twenty-sdk CLI](https://www.npmjs.com/package/twenty-sdk) için CLI başvuru sayfaları.
|
||
|
||
## Proje yapısı (şablondan oluşturulmuş)
|
||
|
||
`npx create-twenty-app@latest my-twenty-app` komutunu çalıştırdığınızda scaffolder şunları yapar:
|
||
|
||
* Minimal bir temel uygulamayı `my-twenty-app/` içine kopyalar
|
||
* Yerel bir `twenty-sdk` bağımlılığı ve Yarn 4 yapılandırması ekler
|
||
* `twenty` CLI ile bağlantılı yapılandırma dosyaları ve betikler oluşturur
|
||
* Varsayılan bir uygulama yapılandırması ve varsayılan bir fonksiyon rolü üretir
|
||
|
||
Yeni şablondan oluşturulan bir uygulama şöyle görünür:
|
||
|
||
```text filename="my-twenty-app/"
|
||
my-twenty-app/
|
||
package.json
|
||
yarn.lock
|
||
.gitignore
|
||
.nvmrc
|
||
.yarnrc.yml
|
||
.yarn/
|
||
install-state.gz
|
||
eslint.config.mjs
|
||
tsconfig.json
|
||
README.md
|
||
public/ # Genel varlıklar klasörü (görseller, yazı tipleri vb.)
|
||
src/
|
||
application.config.ts # Gerekli - ana uygulama yapılandırması
|
||
default-function.role.ts # Sunucusuz işlevler için varsayılan rol
|
||
hello-world.function.ts # Örnek sunucusuz işlev
|
||
hello-world.front-component.tsx # Örnek ön uç bileşeni
|
||
// varlıklarınız (*.object.ts, *.function.ts, *.front-component.tsx, *.role.ts)
|
||
```
|
||
|
||
### Sözleşme-öncelikli yapılandırma
|
||
|
||
Uygulamalar, varlıkların dosya sonekiyle algılandığı **sözleşme-öncelikli yapılandırma** yaklaşımını kullanır. Bu, `src/app/` klasörü içinde esnek bir düzenlemeye olanak tanır:
|
||
|
||
| Dosya soneki | Varlık türü |
|
||
| ----------------------- | ----------------------------- |
|
||
| `*.object.ts` | Özel nesne tanımları |
|
||
| `*.function.ts` | Sunucusuz fonksiyon tanımları |
|
||
| `*.front-component.tsx` | Front component definitions |
|
||
| `*.role.ts` | Rol tanımları |
|
||
|
||
### Desteklenen klasör düzenleri
|
||
|
||
Varlıklarınızı şu desenlerden herhangi birine göre düzenleyebilirsiniz:
|
||
|
||
**Geleneksel (türe göre):**
|
||
|
||
```text
|
||
src/
|
||
├── application.config.ts
|
||
├── objects/
|
||
│ └── postCard.object.ts
|
||
├── functions/
|
||
│ └── createPostCard.function.ts
|
||
├── components/
|
||
│ └── card.front-component.tsx
|
||
└── roles/
|
||
└── admin.role.ts
|
||
```
|
||
|
||
**Özelliğe dayalı:**
|
||
|
||
```text
|
||
src/
|
||
├── application.config.ts
|
||
└── post-card/
|
||
├── postCard.object.ts
|
||
├── createPostCard.function.ts
|
||
├── card.front-component.tsx
|
||
└── postCardAdmin.role.ts
|
||
```
|
||
|
||
**Düz:**
|
||
|
||
```text
|
||
src/
|
||
├── application.config.ts
|
||
├── postCard.object.ts
|
||
├── createPostCard.function.ts
|
||
├── card.front-component.tsx
|
||
└── admin.role.ts
|
||
```
|
||
|
||
Genel hatlarıyla:
|
||
|
||
* **package.json**: Uygulama adını, sürümünü, motorları (Node 24+, Yarn 4) bildirir ve yerel `twenty` CLI’sine yetki devreden `app:dev`, `app:generate`, `entity:add`, `function:logs`, `function:execute`, `app:uninstall` ve `auth:login` gibi betiklerin yanı sıra `twenty-sdk` ekler.
|
||
* **.gitignore**: `node_modules`, `.yarn`, `generated/` (türlendirilmiş istemci), `dist/`, `build/`, kapsam klasörleri, günlük dosyaları ve `.env*` dosyaları gibi yaygın artifaktları yok sayar.
|
||
* **yarn.lock**, **.yarnrc.yml**, **.yarn/**: Proje tarafından kullanılan Yarn 4 araç zincirini kilitler ve yapılandırır.
|
||
* **.nvmrc**: Projenin beklediği Node.js sürümünü sabitler.
|
||
* **eslint.config.mjs** ve **tsconfig.json**: Uygulamanızın TypeScript kaynakları için linting ve TypeScript yapılandırması sağlar.
|
||
* **README.md**: Uygulama kökünde temel talimatların yer aldığı kısa bir README.
|
||
* **public/**: Uygulamanızla birlikte sunulacak genel varlıkları (görseller, yazı tipleri, statik dosyalar) depolamak için bir klasör. Buraya yerleştirilen dosyalar senkronizasyon sırasında yüklenir ve çalışma zamanında erişilebilir olur.
|
||
* **src/**: Uygulamanızı kod olarak tanımladığınız ana yer:
|
||
* `application.config.ts`: Uygulamanız için genel yapılandırma (meta veriler ve çalışma zamanı bağlantıları). Aşağıda "Uygulama yapılandırması"na bakın.
|
||
* `*.role.ts`: Mantık fonksiyonlarınız tarafından kullanılan rol tanımları. Aşağıda "Varsayılan fonksiyon rolü"ne bakın.
|
||
* `*.object.ts`: Özel nesne tanımları.
|
||
* `*.function.ts`: Mantık fonksiyon tanımları.
|
||
* `*.front-component.tsx`: Ön bileşen tanımları.
|
||
|
||
İlerideki komutlar daha fazla dosya ve klasör ekleyecektir:
|
||
|
||
* `yarn app:generate`, `generated/` klasörünü oluşturur (türlendirilmiş Twenty istemcisi + çalışma alanı türleri).
|
||
* `yarn entity:add`, özel nesneleriniz, fonksiyonlarınız, ön bileşenleriniz veya rolleriniz için `src/` altında varlık tanım dosyaları ekler.
|
||
|
||
## Kimlik Doğrulama
|
||
|
||
`yarn auth:login` komutunu ilk kez çalıştırdığınızda, sizden şunlar istenir:
|
||
|
||
* API URL’si (varsayılan: http://localhost:3000 veya mevcut çalışma alanı profiliniz)
|
||
* API anahtarı
|
||
|
||
Kimlik bilgileriniz kullanıcı başına `~/.twenty/config.json` içinde saklanır. You can maintain multiple profiles and switch between them.
|
||
|
||
### Managing workspaces
|
||
|
||
```bash filename="Terminal"
|
||
# Login interactively (recommended)
|
||
yarn auth:login
|
||
|
||
# Login to a specific workspace profile
|
||
yarn auth:login --workspace my-custom-workspace
|
||
|
||
# List all configured workspaces
|
||
yarn auth:list
|
||
|
||
# Switch the default workspace (interactive)
|
||
yarn auth:switch
|
||
|
||
# Switch to a specific workspace
|
||
yarn auth:switch production
|
||
|
||
# Check current authentication status
|
||
yarn auth:status
|
||
```
|
||
|
||
Once you've switched workspaces with `auth:switch`, all subsequent commands will use that workspace by default. You can still override it temporarily with `--workspace <name>`.
|
||
|
||
## SDK kaynaklarını kullanın (türler ve yapılandırma)
|
||
|
||
twenty-sdk, uygulamanız içinde kullandığınız türlendirilmiş yapı taşları ve yardımcı fonksiyonlar sağlar. Aşağıda en sık dokunacağınız başlıca parçalar yer alıyor.
|
||
|
||
### Yardımcı fonksiyonlar
|
||
|
||
SDK, uygulama varlıklarınızı tanımlamak için yerleşik doğrulamaya sahip dört yardımcı fonksiyon sunar:
|
||
|
||
| Fonksiyon | Amaç |
|
||
| ------------------ | ---------------------------------------------- |
|
||
| `defineApplication()` | Uygulama meta verilerini yapılandırın |
|
||
| `defineObject()` | Alanlara sahip özel nesneler tanımlayın |
|
||
| `defineFunction()` | İşleyicilerle mantık fonksiyonları tanımlayın |
|
||
| `defineRole()` | Rol izinlerini ve nesne erişimini yapılandırın |
|
||
|
||
Bu fonksiyonlar, yapılandırmanızı çalışma anında doğrular ve daha iyi IDE otomatik tamamlama ve tür güvenliği sağlar.
|
||
|
||
### Nesnelerin tanımlanması
|
||
|
||
Özel nesneler, çalışma alanınızdaki kayıtlar için hem şemayı hem de davranışı tanımlar. Yerleşik doğrulamayla nesneler tanımlamak için `defineObject()` kullanın:
|
||
|
||
```typescript
|
||
// src/app/postCard.object.ts
|
||
import { defineObject, FieldType } from 'twenty-sdk';
|
||
|
||
enum PostCardStatus {
|
||
DRAFT = 'DRAFT',
|
||
SENT = 'SENT',
|
||
DELIVERED = 'DELIVERED',
|
||
RETURNED = 'RETURNED',
|
||
}
|
||
|
||
export default defineObject({
|
||
universalIdentifier: '54b589ca-eeed-4950-a176-358418b85c05',
|
||
nameSingular: 'postCard',
|
||
namePlural: 'postCards',
|
||
labelSingular: 'Post Card',
|
||
labelPlural: 'Post Cards',
|
||
description: 'A post card object',
|
||
icon: 'IconMail',
|
||
fields: [
|
||
{
|
||
universalIdentifier: '58a0a314-d7ea-4865-9850-7fb84e72f30b',
|
||
name: 'content',
|
||
type: FieldType.TEXT,
|
||
label: 'Content',
|
||
description: "Postcard's content",
|
||
icon: 'IconAbc',
|
||
},
|
||
{
|
||
universalIdentifier: 'c6aa31f3-da76-4ac6-889f-475e226009ac',
|
||
name: 'recipientName',
|
||
type: FieldType.FULL_NAME,
|
||
label: 'Recipient name',
|
||
icon: 'IconUser',
|
||
},
|
||
{
|
||
universalIdentifier: '95045777-a0ad-49ec-98f9-22f9fc0c8266',
|
||
name: 'recipientAddress',
|
||
type: FieldType.ADDRESS,
|
||
label: 'Recipient address',
|
||
icon: 'IconHome',
|
||
},
|
||
{
|
||
universalIdentifier: '87b675b8-dd8c-4448-b4ca-20e5a2234a1e',
|
||
name: 'status',
|
||
type: FieldType.SELECT,
|
||
label: 'Status',
|
||
icon: 'IconSend',
|
||
defaultValue: `'${PostCardStatus.DRAFT}'`,
|
||
options: [
|
||
{ value: PostCardStatus.DRAFT, label: 'Draft', position: 0, color: 'gray' },
|
||
{ value: PostCardStatus.SENT, label: 'Sent', position: 1, color: 'orange' },
|
||
{ value: PostCardStatus.DELIVERED, label: 'Delivered', position: 2, color: 'green' },
|
||
{ value: PostCardStatus.RETURNED, label: 'Returned', position: 3, color: 'orange' },
|
||
],
|
||
},
|
||
{
|
||
universalIdentifier: 'e06abe72-5b44-4e7f-93be-afc185a3c433',
|
||
name: 'deliveredAt',
|
||
type: FieldType.DATE_TIME,
|
||
label: 'Delivered at',
|
||
icon: 'IconCheck',
|
||
isNullable: true,
|
||
defaultValue: null,
|
||
},
|
||
],
|
||
});
|
||
```
|
||
|
||
Önemli noktalar:
|
||
|
||
* Yerleşik doğrulama ve daha iyi IDE desteği için `defineObject()` kullanın.
|
||
* `universalIdentifier` dağıtımlar arasında benzersiz ve kararlı olmalıdır.
|
||
* Her alan bir `name`, `type`, `label` ve kendi kararlı `universalIdentifier` değerini gerektirir.
|
||
* `fields` dizisi isteğe bağlıdır — özel alanlar olmadan da nesneler tanımlayabilirsiniz.
|
||
* `yarn entity:add` kullanarak, adlandırma, alanlar ve ilişkiler konusunda sizi yönlendirerek yeni nesneler oluşturabilirsiniz.
|
||
|
||
<Note>
|
||
**Temel alanlar otomatik olarak oluşturulur.** Özel bir nesne tanımladığınızda Twenty, `name`, `createdAt`, `updatedAt`, `createdBy`, `position` ve `deletedAt` gibi standart alanları otomatik olarak ekler. Bunları `fields` dizinizde tanımlamanız gerekmez — yalnızca özel alanlarınızı ekleyin.
|
||
</Note>
|
||
|
||
### Uygulama yapılandırması (application.config.ts)
|
||
|
||
Her uygulamanın aşağıdakileri açıklayan tek bir `application.config.ts` dosyası vardır:
|
||
|
||
* **Uygulamanın kim olduğu**: tanımlayıcılar, görünen ad ve açıklama.
|
||
* **Fonksiyonlarının nasıl çalıştığı**: izinler için hangi rolü kullandıkları.
|
||
* **(İsteğe bağlı) değişkenler**: fonksiyonlarınıza ortam değişkenleri olarak sunulan anahtar–değer çiftleri.
|
||
|
||
Uygulama yapılandırmanızı tanımlamak için `defineApplication()` kullanın:
|
||
|
||
```typescript
|
||
// src/app/application.config.ts
|
||
import { defineApplication } from 'twenty-sdk';
|
||
import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from './default-function.role';
|
||
|
||
export default defineApplication({
|
||
universalIdentifier: '4ec0391d-18d5-411c-b2f3-266ddc1c3ef7',
|
||
displayName: 'My Twenty App',
|
||
description: 'My first Twenty app',
|
||
icon: 'IconWorld',
|
||
applicationVariables: {
|
||
DEFAULT_RECIPIENT_NAME: {
|
||
universalIdentifier: '19e94e59-d4fe-4251-8981-b96d0a9f74de',
|
||
description: 'Default recipient name for postcards',
|
||
value: 'Jane Doe',
|
||
isSecret: false,
|
||
},
|
||
},
|
||
defaultRoleUniversalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER,
|
||
});
|
||
```
|
||
|
||
Notlar:
|
||
|
||
* `universalIdentifier` alanları size ait belirleyici kimliklerdir; bunları bir kez oluşturun ve eşitlemeler boyunca kararlı tutun.
|
||
* `applicationVariables`, fonksiyonlarınız için ortam değişkenlerine dönüşür (örneğin, `DEFAULT_RECIPIENT_NAME` değeri `process.env.DEFAULT_RECIPIENT_NAME` olarak kullanılabilir).
|
||
* `defaultRoleUniversalIdentifier`, `*.role.ts` dosyanızda tanımladığınız rolle eşleşmelidir (aşağıya bakın).
|
||
|
||
#### Roller ve izinler
|
||
|
||
Uygulamalar, çalışma alanınızdaki nesneler ve eylemler üzerindeki izinleri kapsülleyen roller tanımlayabilir. `application.config.ts` içindeki `defaultRoleUniversalIdentifier` alanı, uygulamanızın mantık fonksiyonları tarafından kullanılan varsayılan rolü belirtir.
|
||
|
||
* `TWENTY_API_KEY` olarak enjekte edilen çalışma zamanı API anahtarı bu varsayılan fonksiyon rolünden türetilir.
|
||
* Türlendirilmiş istemci, o role tanınan izinlerle sınırlandırılır.
|
||
* En az ayrıcalık ilkesini izleyin: Yalnızca fonksiyonlarınızın ihtiyaç duyduğu izinlere sahip özel bir rol oluşturun ve ardından evrensel tanımlayıcısına referans verin.
|
||
|
||
##### Varsayılan fonksiyon rolü (\*.role.ts)
|
||
|
||
Yeni bir uygulama oluşturduğunuzda CLI ayrıca varsayılan bir rol dosyası da oluşturur. Yerleşik doğrulamayla roller tanımlamak için `defineRole()` kullanın:
|
||
|
||
```typescript
|
||
// src/app/default-function.role.ts
|
||
import { defineRole, PermissionFlag } from 'twenty-sdk';
|
||
|
||
export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER =
|
||
'b648f87b-1d26-4961-b974-0908fd991061';
|
||
|
||
export default defineRole({
|
||
universalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER,
|
||
label: 'Default function role',
|
||
description: 'Default role for function Twenty client',
|
||
canReadAllObjectRecords: false,
|
||
canUpdateAllObjectRecords: false,
|
||
canSoftDeleteAllObjectRecords: false,
|
||
canDestroyAllObjectRecords: false,
|
||
canUpdateAllSettings: false,
|
||
canBeAssignedToAgents: false,
|
||
canBeAssignedToUsers: false,
|
||
canBeAssignedToApiKeys: false,
|
||
objectPermissions: [
|
||
{
|
||
objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050',
|
||
canReadObjectRecords: true,
|
||
canUpdateObjectRecords: true,
|
||
canSoftDeleteObjectRecords: false,
|
||
canDestroyObjectRecords: false,
|
||
},
|
||
],
|
||
fieldPermissions: [
|
||
{
|
||
objectUniversalIdentifier: '9f9882af-170c-4879-b013-f9628b77c050',
|
||
fieldUniversalIdentifier: 'b2c37dc0-8ae7-470e-96cd-1476b47dfaff',
|
||
canReadFieldValue: false,
|
||
canUpdateFieldValue: false,
|
||
},
|
||
],
|
||
permissionFlags: [PermissionFlag.APPLICATIONS],
|
||
});
|
||
```
|
||
|
||
Bu rolün `universalIdentifier` değeri, `application.config.ts` içinde `defaultRoleUniversalIdentifier` olarak referans verilir. Başka bir deyişle:
|
||
|
||
* **\*.role.ts**, varsayılan fonksiyon rolünün neler yapabileceğini tanımlar.
|
||
* **application.config.ts** bu role işaret eder, böylece fonksiyonlarınız onun izinlerini devralır.
|
||
|
||
Notlar:
|
||
|
||
* Oluşturulan rol ile başlayın ve en az ayrıcalık ilkesini izleyerek aşamalı olarak kısıtlayın.
|
||
* `objectPermissions` ve `fieldPermissions` değerlerini, fonksiyonlarınızın ihtiyaç duyduğu nesneler/alanlarla değiştirin.
|
||
* `permissionFlags`, platform düzeyindeki yeteneklere erişimi kontrol eder. Minimumda tutun; yalnızca ihtiyacınız olanları ekleyin.
|
||
* Çalışan bir örneği Hello World uygulamasında görün: [`packages/twenty-apps/hello-world/src/roles/function-role.ts`](https://github.com/twentyhq/twenty/blob/main/packages/twenty-apps/hello-world/src/roles/function-role.ts).
|
||
|
||
### Mantık fonksiyon yapılandırması ve giriş noktası
|
||
|
||
Her fonksiyon dosyası, bir işleyici ve isteğe bağlı tetikleyiciler içeren bir yapılandırmayı dışa aktarmak için `defineFunction()` kullanır. Otomatik algılama için `*.function.ts` dosya soneğini kullanın.
|
||
|
||
```typescript
|
||
// src/app/createPostCard.function.ts
|
||
import { defineFunction } from 'twenty-sdk';
|
||
import type { DatabaseEventPayload, ObjectRecordCreateEvent, CronPayload, RoutePayload } from 'twenty-sdk';
|
||
import Twenty, { type Person } from '~/generated';
|
||
|
||
const handler = async (params: RoutePayload) => {
|
||
const client = new Twenty(); // generated typed client
|
||
const name = 'name' in params.queryStringParameters
|
||
? params.queryStringParameters.name ?? process.env.DEFAULT_RECIPIENT_NAME ?? 'Hello world'
|
||
: 'Hello world';
|
||
|
||
const result = await client.mutation({
|
||
createPostCard: {
|
||
__args: { data: { name } },
|
||
id: true,
|
||
name: true,
|
||
},
|
||
});
|
||
return result;
|
||
};
|
||
|
||
export default defineFunction({
|
||
universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf',
|
||
name: 'create-new-post-card',
|
||
timeoutSeconds: 2,
|
||
handler,
|
||
triggers: [
|
||
// Public HTTP route trigger '/s/post-card/create'
|
||
{
|
||
universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6',
|
||
type: 'route',
|
||
path: '/post-card/create',
|
||
httpMethod: 'GET',
|
||
isAuthRequired: false,
|
||
},
|
||
// Cron trigger (CRON pattern)
|
||
// {
|
||
// universalIdentifier: 'dd802808-0695-49e1-98c9-d5c9e2704ce2',
|
||
// type: 'cron',
|
||
// pattern: '0 0 1 1 *',
|
||
// },
|
||
// Database event trigger
|
||
// {
|
||
// universalIdentifier: '203f1df3-4a82-4d06-a001-b8cf22a31156',
|
||
// type: 'databaseEvent',
|
||
// eventName: 'person.updated',
|
||
// updatedFields: ['name'],
|
||
// },
|
||
],
|
||
});
|
||
```
|
||
|
||
Yaygın tetikleyici türleri:
|
||
|
||
* **route**: Fonksiyonunuzu bir HTTP yolu ve yöntemiyle **`/s/` uç noktası altında** sunar:
|
||
|
||
> örn. `path: '/post-card/create',` -> `<APP_URL>/s/post-card/create` üzerinden çağırın
|
||
|
||
* **cron**: Bir CRON ifadesi kullanarak fonksiyonunuzu bir zamanlamayla çalıştırır.
|
||
* **databaseEvent**: Çalışma alanı nesnesi yaşam döngüsü olaylarında çalışır. Olay işlemi `updated` olduğunda, dinlenecek belirli alanlar `updatedFields` dizisinde belirtilebilir. Tanımsız veya boş bırakılırsa, herhangi bir güncelleme fonksiyonu tetikler.
|
||
|
||
> örn. `person.updated`
|
||
|
||
Notlar:
|
||
|
||
* `triggers` dizisi isteğe bağlıdır. Tetikleyicisi olmayan fonksiyonlar, diğer fonksiyonlar tarafından çağrılan yardımcı fonksiyonlar olarak kullanılabilir.
|
||
* Tek bir fonksiyonda birden çok tetikleyici türünü birleştirebilirsiniz.
|
||
|
||
### Rota tetikleyicisi yükü
|
||
|
||
<Warning>
|
||
**Kırıcı değişiklik (v1.16, Ocak 2026):** Rota tetikleyicisi yük formatı değişti. v1.16'dan önce, sorgu parametreleri, yol parametreleri ve gövde doğrudan payload olarak gönderiliyordu. v1.16 itibarıyla, yapılandırılmış bir `RoutePayload` nesnesinin içine yerleştiriliyorlar.
|
||
|
||
**v1.16'dan önce:**
|
||
|
||
```typescript
|
||
const handler = async (params) => {
|
||
const { param1, param2 } = params; // Direct access
|
||
};
|
||
```
|
||
|
||
**v1.16'dan sonra:**
|
||
|
||
```typescript
|
||
const handler = async (event: RoutePayload) => {
|
||
const { param1, param2 } = event.body; // Access via .body
|
||
const { queryParam } = event.queryStringParameters;
|
||
const { id } = event.pathParameters;
|
||
};
|
||
```
|
||
|
||
**Mevcut fonksiyonları taşımak için:** İşleyicinizi, parametreler nesnesinden doğrudan ayırmak yerine `event.body`, `event.queryStringParameters` veya `event.pathParameters` üzerinden ayrıştıracak şekilde güncelleyin.
|
||
</Warning>
|
||
|
||
Bir rota tetikleyicisi mantık fonksiyonunuzu çağırdığında, AWS HTTP API v2 formatını izleyen bir `RoutePayload` nesnesi alır. Türü `twenty-sdk` içinden içe aktarın:
|
||
|
||
```typescript
|
||
import { defineFunction, type RoutePayload } from 'twenty-sdk';
|
||
|
||
const handler = async (event: RoutePayload) => {
|
||
// Access request data
|
||
const { headers, queryStringParameters, pathParameters, body } = event;
|
||
|
||
// HTTP method and path are available in requestContext
|
||
const { method, path } = event.requestContext.http;
|
||
|
||
return { message: 'Success' };
|
||
};
|
||
```
|
||
|
||
`RoutePayload` türünün yapısı şu şekildedir:
|
||
|
||
| Özellik | Tür | Açıklama |
|
||
| ---------------------------- | ------------------------------------- | ---------------------------------------------------------------------------------- |
|
||
| `headers` | `Record<string, string \| undefined>` | HTTP başlıkları (`forwardedRequestHeaders` içinde listelenenlerle sınırlı) |
|
||
| `queryStringParameters` | `Record<string, string \| undefined>` | Sorgu dizesi parametreleri (birden çok değer virgülle birleştirilir) |
|
||
| `pathParameters` | `Record<string, string \| undefined>` | Rota deseninden çıkarılan yol parametreleri (örn., `/users/:id` → `{ id: '123' }`) |
|
||
| `gövde` | `object \| null` | Ayrıştırılmış istek gövdesi (JSON) |
|
||
| `isBase64Encoded` | `boolean` | Gövdenin base64 ile kodlanıp kodlanmadığı |
|
||
| `requestContext.http.method` | `string` | HTTP yöntemi (GET, POST, PUT, PATCH, DELETE) |
|
||
| `requestContext.http.path` | `string` | Ham istek yolu |
|
||
|
||
### HTTP başlıklarını iletme
|
||
|
||
Varsayılan olarak, güvenlik nedenleriyle gelen isteklerden HTTP başlıkları mantık fonksiyonunuza **aktarılmaz**. Belirli başlıklara erişmek için bunları açıkça `forwardedRequestHeaders` dizisinde listeleyin:
|
||
|
||
```typescript
|
||
export default defineFunction({
|
||
universalIdentifier: 'e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf',
|
||
name: 'webhook-handler',
|
||
handler,
|
||
triggers: [
|
||
{
|
||
universalIdentifier: 'c9f84c8d-b26d-40d1-95dd-4f834ae5a2c6',
|
||
type: 'route',
|
||
path: '/webhook',
|
||
httpMethod: 'POST',
|
||
isAuthRequired: false,
|
||
forwardedRequestHeaders: ['x-webhook-signature', 'content-type'],
|
||
},
|
||
],
|
||
});
|
||
```
|
||
|
||
Daha sonra işleyicinizde bu başlıklara erişebilirsiniz:
|
||
|
||
```typescript
|
||
const handler = async (event: RoutePayload) => {
|
||
const signature = event.headers['x-webhook-signature'];
|
||
const contentType = event.headers['content-type'];
|
||
|
||
// Validate webhook signature...
|
||
return { received: true };
|
||
};
|
||
```
|
||
|
||
<Note>
|
||
Başlık adları küçük harfe normalize edilir. Onlara küçük harfli anahtarlarla erişin (örneğin, `event.headers['content-type']`).
|
||
</Note>
|
||
|
||
Yeni fonksiyonları iki şekilde oluşturabilirsiniz:
|
||
|
||
* **Şablondan**: `yarn entity:add` çalıştırın ve yeni bir fonksiyon ekleme seçeneğini seçin. Bu, bir işleyici ve yapılandırma içeren bir başlangıç dosyası oluşturur.
|
||
* **Manuel**: Yeni bir `*.function.ts` dosyası oluşturun ve aynı deseni izleyerek `defineFunction()` kullanın.
|
||
|
||
### Oluşturulmuş türlendirilmiş istemci
|
||
|
||
Çalışma alanı şemanıza göre generated/ içinde yerel bir türlendirilmiş istemci oluşturmak için yarn app:generate çalıştırın. Fonksiyonlarınızda kullanın:
|
||
|
||
```typescript
|
||
import Twenty from '~/generated';
|
||
|
||
const client = new Twenty();
|
||
const { me } = await client.query({ me: { id: true, displayName: true } });
|
||
```
|
||
|
||
İstemci `yarn app:generate` tarafından yeniden oluşturulur. Nesnelerinizi değiştirdikten sonra veya yeni bir çalışma alanına katılırken yeniden çalıştırın.
|
||
|
||
#### Mantık fonksiyonlarında çalışma zamanı kimlik bilgileri
|
||
|
||
Fonksiyonunuz Twenty üzerinde çalıştığında, platform kodunuz yürütülmeden önce kimlik bilgilerini ortam değişkenleri olarak enjekte eder:
|
||
|
||
* `TWENTY_API_URL`: Uygulamanızın hedeflediği Twenty API'nin temel URL’si.
|
||
* `TWENTY_API_KEY`: Uygulamanızın varsayılan fonksiyon rolü kapsamına sahip kısa ömürlü anahtar.
|
||
|
||
Notlar:
|
||
|
||
* Oluşturulan istemciye URL veya API anahtarı geçirmeniz gerekmez. Çalışma zamanında `TWENTY_API_URL` ve `TWENTY_API_KEY` değerlerini process.env üzerinden okur.
|
||
* API anahtarının izinleri, `application.config.ts` içinde `defaultRoleUniversalIdentifier` aracılığıyla referans verilen role göre belirlenir. Bu, uygulamanızın mantık fonksiyonları tarafından kullanılan varsayılan roldür.
|
||
* Uygulamalar, en az ayrıcalık ilkesini izlemek için roller tanımlayabilir. Yalnızca fonksiyonlarınızın ihtiyaç duyduğu izinleri verin ve ardından `defaultRoleUniversalIdentifier` değerini o rolün evrensel tanımlayıcısına yönlendirin.
|
||
|
||
### Hello World örneği
|
||
|
||
Nesneleri, fonksiyonları ve birden çok tetikleyiciyi gösteren minimal, uçtan uca bir örneği [buradan](https://github.com/twentyhq/twenty/tree/main/packages/twenty-apps/hello-world) inceleyin:
|
||
|
||
## Manuel kurulum (scaffolder olmadan)
|
||
|
||
En iyi başlangıç deneyimi için `create-twenty-app` kullanmanızı önersek de, bir projeyi manuel olarak da kurabilirsiniz. CLI'yi global olarak kurmayın. Bunun yerine `twenty-sdk`'yi yerel bir bağımlılık olarak ekleyin ve package.json içinde betikleri bağlayın:
|
||
|
||
```bash filename="Terminal"
|
||
yarn add -D twenty-sdk
|
||
```
|
||
|
||
Ardından şu gibi betikler ekleyin:
|
||
|
||
```json filename="package.json"
|
||
{
|
||
"scripts": {
|
||
"auth:login": "twenty auth:login",
|
||
"auth:logout": "twenty auth:logout",
|
||
"auth:status": "twenty auth:status",
|
||
"auth:switch": "twenty auth:switch",
|
||
"auth:list": "twenty auth:list",
|
||
"app:dev": "twenty app:dev",
|
||
"app:generate": "twenty app:generate",
|
||
"app:uninstall": "twenty app:uninstall",
|
||
"entity:add": "twenty entity:add",
|
||
"function:logs": "twenty function:logs",
|
||
"function:execute": "twenty function:execute",
|
||
"help": "twenty help"
|
||
}
|
||
}
|
||
```
|
||
|
||
Artık aynı komutları Yarn üzerinden çalıştırabilirsiniz; örn. `yarn app:dev`, `yarn app:generate` vb.
|
||
|
||
## Sorun Giderme
|
||
|
||
* Kimlik doğrulama hataları: `yarn auth:login` çalıştırın ve API anahtarınızın gerekli izinlere sahip olduğundan emin olun.
|
||
* Sunucuya bağlanılamıyor: API URL’sini ve Twenty sunucusunun erişilebilir olduğunu doğrulayın.
|
||
* Türler veya istemci eksik/eski: `yarn app:generate` çalıştırın.
|
||
* Geliştirme modu eşitlenmiyor: `yarn app:dev`'in çalıştığından ve değişikliklerin ortamınız tarafından yok sayılmadığından emin olun.
|
||
|
||
Discord Yardım Kanalı: https://discord.com/channels/1130383047699738754/1130386664812982322
|