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:
github-actions[bot]
2026-07-09 11:51:54 +02:00
committed by GitHub
parent a0cf4cc9e1
commit ebee7d71b9
228 changed files with 4216 additions and 4583 deletions
@@ -4,7 +4,7 @@ description: Kurulumdan önce veya sonra mantığı çalıştırın — veri toh
icon: wrench
---
Kurulum kancaları, kurulum veya yükseltme yaşam döngüsü sırasında çalışan özel mantık işlevleridir. Bunlar, normal [mantık işlevleri](/l/tr/developers/extend/apps/logic/logic-functions) ile aynı işleyici çalışma zamanını paylaşır ve bir `InstallPayload` alırlar, ancak kendi tanımlama işlevleri — `definePostInstallLogicFunction()` ve `definePreInstallLogicFunction()` — ile bildirilirler ve normal tetikleyici modelinin (HTTP, cron, veritabanı olayları) dışında yaşarlar.
Kurulum kancaları, kurulum veya yükseltme yaşam döngüsü sırasında çalışan özel mantık işlevleridir. Bunlar, normal [mantık işlevleri](/l/tr/developers/extend/apps/logic/logic-functions) ile aynı işleyici çalışma zamanını paylaşır ve bir `InstallPayload` alırlar (`{ previousVersion?: string; newVersion: string }` — yeni bir kurulumda `previousVersion` `undefined` olur), ancak kendi define işlevleriyle bildirilirler ve normal tetikleyici modelinin (HTTP, cron, veritabanı olayları) dışında yer alırlar.
Her uygulama **en fazla bir kurulum öncesi** ve **en fazla bir kurulum sonrası** işlev tanımlayabilir. Her ikisinden de birden fazla tespit edilirse manifest oluşturma hataya düşer.
@@ -19,111 +19,59 @@ Her uygulama **en fazla bir kurulum öncesi** ve **en fazla bir kurulum sonrası
└─────────────────────────────────────────────────────────────┘
```
<AccordionGroup>
<Accordion title="definePostInstallLogicFunction" description="Çalışma alanı üstveri (metadata) geçişi uygulanıp tamamlandıktan sonra çalışır">
## Bir bakışta
Kurulum sonrası işlev, uygulamanız bir çalışma alanına kurulmasını tamamladıktan sonra otomatik olarak çalışır. Sunucu, uygulamanın meta verileri senkronize edildikten ve SDK istemcisi oluşturulduktan **sonra** bunu yürütür; böylece çalışma alanı tamamen kullanıma hazırdır ve yeni şema kullanıma alınmıştır. Tipik kullanım örnekleri arasında varsayılan verilerin tohumlanması, başlangıç kayıtlarının oluşturulması, çalışma alanı ayarlarının yapılandırılması veya üçüncü taraf hizmetlerde kaynak sağlanması yer alır.
| | `definePreInstallLogicFunction` | `definePostInstallLogicFunction` |
| ---------------------- | ------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| Çalıştırmalar | Üstveri geçişinden önce — **önceki** şema ve veriler hâlâ sağlamdır | Geçişten ve SDK oluşturmasından sonra — **yeni** şema devrededir |
| Yürütme | Her zaman senkron; kurulumu bloke eder | Varsayılan olarak async (kuyruğa alınır, 3 yeniden deneme); `shouldRunSynchronously: true` ile isteğe bağlı senkron |
| Başarısızlık durumunda | Kurulum, herhangi bir şema değişikliğinden önce **iptal edilir** | Async: en fazla 3 kez yeniden denenir. Sync: çağıran `POST_INSTALL_ERROR` alır (şema değişiklikleri **geri alınmaz**) |
| Tipik kullanım | Bir geçişin kaybedeceği verileri yedeklemek veya düzeltmek; fırlatarak riskli bir yükseltmeyi reddetmek | Varsayılan verileri tohumlamak, çalışma alanını yapılandırmak, harici kaynakları kaydetmek |
```ts src/logic-functions/post-install.ts
import { definePostInstallLogicFunction, type InstallPayload } from 'twenty-sdk/define';
**Kural:** varsayılan olarak post-install kullanın. Yalnızca geçişin kendisi yıkıcıysa ve önceki durum yok olmadan önce onu yakalamanız gerekiyorsa kurulum öncesine başvurun.
const handler = async (payload: InstallPayload): Promise<void> => {
console.log('Post install logic function executed successfully!', payload.previousVersion);
};
| Şunu yapmak istiyorsunuz... | Kullan |
| --------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
| Verileri tohumlamak, çalışma alanını yapılandırmak, harici kaynakları kaydetmek | `post-install` |
| Kurulum yanıtını engellememesi gereken uzun süreli işleri yürütmek | `post-install` (varsayılan async mod, worker yeniden denemeleriyle) |
| Kurulum döndükten hemen sonra çağıranın güveneceği hızlı kurulumu gerçekleştirmek | `post-install` ile `shouldRunSynchronously: true` |
| Yaklaşan geçişin kaybedeceği verileri okumak veya yedeklemek | `pre-install` |
| Mevcut verileri bozacak bir yükseltmeyi reddetmek | `pre-install` (işleyiciden hata fırlatmak) |
| Her yükseltmede uzlaştırma çalıştırmak | `shouldRunOnVersionUpgrade: true` ile her iki kancadan biri |
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,
});
```
## Her iki kanca tarafından paylaşılan davranış
Ayrıca kurulum sonrası işlevi istediğiniz zaman CLI kullanarak manuel olarak çalıştırabilirsiniz:
* Yapılandırma, tetikleyici ayarları çıkarılmış bir `defineLogicFunction` yapılandırmasıdır ve buna ek olarak `shouldRunOnVersionUpgrade` içerir.
* **Ne zaman çalışır**: varsayılan olarak yalnızca ilk kurulumlarda. Yükseltmelerde de çalışması için `shouldRunOnVersionUpgrade: true` olarak ayarlayın. Yükseltme yoluna göre dallanmak için `previousVersion` / `newVersion` kullanın.
* **İdempotans önemlidir**: async post-install yeniden denenebilir ve `shouldRunOnVersionUpgrade` açıkken her iki kanca da yükseltmelerde yeniden çalıştırılır.
* Alışıldık mantık işlevi ortamı (`APPLICATION_ID`, `APP_ACCESS_TOKEN`, `API_URL`) enjekte edilir, böylece Twenty API'sini uygulamanızın jetonuyla çağırabilirsiniz.
* Kanca, derleme zamanında otomatik olarak uygulama manifestine (`preInstallLogicFunction` / `postInstallLogicFunction`) eklenir — [`defineApplication()`](/l/tr/developers/extend/apps/config/application) içinde referans verilecek bir şey yoktur.
* Varsayılan `timeoutSeconds`, veri tohumlama gibi daha uzun kurulum görevlerine izin vermek için 300 olarak ayarlanmıştır.
* **Geliştirme modunda yürütülmez**: `yarn twenty dev` kurulum akışını atlar ve dosyaları doğrudan eşitler, bu nedenle kancalar burada asla çalışmaz. Bunları bunun yerine manuel olarak tetikleyin:
```bash filename="Terminal"
yarn twenty dev:function:exec --postInstall
```
Önemli noktalar:
* Kurulum sonrası işlevler `definePostInstallLogicFunction()` kullanır — tetikleyici ayarlarını atlayan (`cronTriggerSettings`, `databaseEventTriggerSettings`, `httpRouteTriggerSettings`, `toolTriggerSettings`, `workflowActionTriggerSettings`) özel bir varyanttır.
* İşleyici, `{ previousVersion?: string; newVersion: string }` içeren bir `InstallPayload` alır — `newVersion`, yüklenen sürümdür; `previousVersion` ise daha önce yüklü olan sürümdür (veya ilk kurulumda `undefined`). Bu değerleri ilk kurulumları yükseltmelerden ayırt etmek ve sürüme özgü geçiş (migration) mantığını çalıştırmak için kullanın.
* **Kanca ne zaman çalışır**: varsayılan olarak yalnızca ilk kurulumlarda. Uygulama önceki bir sürümden yükseltildiğinde de çalışmasını istiyorsanız `shouldRunOnVersionUpgrade: true` geçin. Belirtilmediğinde, bayrak varsayılan olarak `false` olur ve yükseltmeler kancayı atlar.
* **Yürütme modeli — varsayılan olarak eşzamansız, isteğe bağlı senkron**: `shouldRunSynchronously` bayrağı kurulum sonrası işlemin *nasıl* yürütüldüğünü kontrol eder.
* `shouldRunSynchronously: false` *(varsayılan)* — kanca, `retryLimit: 3` ile **mesaj kuyruğuna alınır** ve bir worker içinde eşzamansız çalışır. İş kuyruğa alınır alınmaz kurulum yanıtı döner; dolayısıyla yavaşlayan veya hata veren bir işleyici çağıranı engellemez. Worker en fazla üç kez yeniden deneyecektir. **Bunu uzun süre çalışan işler için kullanın** — büyük veri kümelerini tohumlama, yavaş üçüncü taraf API'lerini çağırma, harici kaynakları sağlama; makul bir HTTP yanıt süresini aşabilecek her şey.
* `shouldRunSynchronously: true` — kanca **kurulum akışı sırasında satır içi** olarak yürütülür (kurulum öncesi ile aynı yürütücü). İşleyici bitene kadar kurulum isteği engellenir; hata fırlatırsa, kurulum çağıranı bir `POST_INSTALL_ERROR` alır. Otomatik yeniden deneme yok. **Bunu, yanıt dönmeden mutlaka tamamlanması gereken hızlı işler için kullanın** — örneğin, kullanıcıya bir doğrulama hatası iletmek veya kurulum çağrısı döner dönmez istemcinin ihtiyaç duyacağı hızlı bir kurulum yapmak. Kurulum sonrası çalıştığında, üstveri (metadata) geçişinin zaten uygulanmış olduğunu unutmayın; bu nedenle, senkron moddaki bir hata şema değişikliklerini **geri almaz** — yalnızca hatayı görünür kılar.
* İşleyicinizin idempotent olduğundan emin olun. Eşzamansız modda kuyruk en fazla üç kez yeniden deneyebilir; her iki modda da `shouldRunOnVersionUpgrade: true` iken yükseltmelerde kanca tekrar çalışabilir.
* Ortam değişkenleri `APPLICATION_ID`, `APP_ACCESS_TOKEN` ve `API_URL` işleyici içinde kullanılabilir (diğer mantık işlevlerinde olduğu gibi), böylece uygulamanıza özel kapsamda bir uygulama erişim belirteciyle Twenty API'sini çağırabilirsiniz.
* Uygulama başına yalnızca bir kurulum sonrası işlevine izin verilir. Birden fazla tespit edilirse manifest oluşturma hataya düşer.
* İşlevin `universalIdentifier`, `shouldRunOnVersionUpgrade` ve `shouldRunSynchronously` değerleri, derleme sırasında uygulama manifestine `postInstallLogicFunction` alanı altında otomatik olarak eklenir — bunlara [`defineApplication()`](/l/tr/developers/extend/apps/config/application) içinde atıfta bulunmanıza gerek yoktur.
* Varsayılan zaman aşımı, veri tohumlama gibi daha uzun kurulum görevlerine izin vermek için 300 saniye (5 dakika) olarak ayarlanmıştır.
* **Geliştirme modunda çalıştırılmaz**: bir uygulama yerel olarak kaydedildiğinde (`yarn twenty dev` aracılığıyla), sunucu kurulum akışını tamamen atlar ve dosyaları doğrudan CLI watcher üzerinden eşitler — bu nedenle, `shouldRunSynchronously` ne olursa olsun, kurulum sonrası geliştirme modunda hiç çalışmaz. Çalışan bir çalışma alanında bunu elle tetiklemek için `yarn twenty dev:function:exec --postInstall` kullanın.
</Accordion>
<Accordion title="definePreInstallLogicFunction" description="Çalışma alanı üstveri (metadata) geçişi uygulanmadan önce çalışır">
Kurulum öncesi işlev, kurulum sırasında otomatik olarak çalışır ve **çalışma alanı üstveri (metadata) geçişi uygulanmadan önce** yürütülür. Kurulum sonrası ile (`InstallPayload`) aynı yük (payload) biçimini paylaşır, ancak kurulum akışında daha erken konumlandığından yaklaşan geçişin bağlı olduğu durumu hazırlayabilir — tipik kullanımlar arasında verileri yedeklemek, yeni şemayla uyumluluğu doğrulamak veya yeniden yapılandırılacak ya da kaldırılacak kayıtları arşivlemek yer alır.
```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,
});
```
Ayrıca kurulum öncesi işlevi istediğiniz zaman CLI kullanarak manuel olarak çalıştırabilirsiniz:
```bash filename="Terminal"
yarn twenty dev:function:exec --preInstall
```
Önemli noktalar:
* Kurulum öncesi işlevler `definePreInstallLogicFunction()` kullanır — kurulum sonrasıyla aynı özel yapılandırma, sadece yaşam döngüsünde farklı bir yuvaya eklenir.
* Hem kurulum öncesi hem de kurulum sonrası işleyiciler aynı `InstallPayload` türünü alır: `{ previousVersion?: string; newVersion: string }`. Bunu bir kez içe aktarın ve her iki kanca için yeniden kullanın.
* **Kanca ne zaman çalışır**: çalışma alanı üstveri (metadata) geçişinden hemen önce konumlandırılır (`synchronizeFromManifest`). Çalıştırmadan önce, sunucu yalnızca ekleyici bir "indirgenmiş eşitleme" yürütür; bu, çalışma alanı üstverisinde **yeni** sürümün kurulum öncesi işlevini kaydeder — başka hiçbir şeye dokunulmaz — ve ardından bunu yürütür. Bu eşitleme yalnızca ekleyici olduğundan, işleyiciniz çalıştığında önceki sürümün nesneleri, alanları ve verileri hâlâ sağlamdır: geçiş öncesi durumu güvenle okuyabilir ve yedekleyebilirsiniz.
* **Yürütme modeli**: kurulum öncesi **senkron** olarak yürütülür ve **kurulumu bloklar**. İşleyici bir hata fırlatırsa, herhangi bir şema değişikliği uygulanmadan önce kurulum iptal edilir — çalışma alanı, tutarlı bir durumda önceki sürümde kalır. Bu kasıtlıdır: kurulum öncesi, riskli bir yükseltmeyi reddetmek için son şansınızdır.
* Kurulum sonrası ile aynı şekilde, uygulama başına yalnızca bir kurulum öncesi işlevine izin verilir. Derleme sırasında uygulama manifestine `preInstallLogicFunction` altında otomatik olarak eklenir.
* **Geliştirme modunda çalıştırılmaz**: kurulum sonrasında olduğu gibi — yerel olarak kaydedilen uygulamalarda kurulum akışı tamamen atlanır, bu nedenle `yarn twenty dev` altında kurulum öncesi hiç çalışmaz. Bunu elle tetiklemek için `yarn twenty dev:function:exec --preInstall` kullanın.
<AccordionGroup>
<Accordion title="definePostInstallLogicFunction" description="Çalışma alanı üstveri (metadata) geçişi uygulanıp tamamlandıktan sonra çalışır">
</Accordion>
<Accordion title="Kurulum öncesi vs kurulum sonrası: hangisini ne zaman kullanmalı" description="Doğru kurulum kancasını seçme">
Her iki kanca da aynı kurulum akışının parçasıdır ve aynı `InstallPayload`'ı alır. Fark, çalışma alanı üstveri (metadata) geçişine göre **ne zaman** çalıştıklarıdır ve bu, güvenle erişebilecekleri verileri değiştirir.
Kurulum öncesi her zaman **senkron**dur (kurulumu bloke eder ve iptal edebilir). Kurulum sonrası **varsayılan olarak asenkron**dur — otomatik yeniden denemelerle bir worker üzerinde kuyruğa alınır — ancak `shouldRunSynchronously: true` ile senkron yürütmeye geçebilir. Her modun ne zaman kullanılacağı için yukarıdaki `definePostInstallLogicFunction` akordeonuna bakın.
**Yeni şemanın mevcut olmasını gerektiren her şey için `post-install` kullanın.** Bu yaygın durumdur:
* Yeni eklenen nesne ve alanlara karşı varsayılan verileri tohumlama (ilk kayıtları, varsayılan görünümleri, demo içeriği oluşturma).
* Uygulamanın kimlik bilgileri artık mevcut olduğuna göre, üçüncü taraf hizmetlerle webhook'ları kaydetmek.
* Eşitlenmiş üstveriye (metadata) bağlı kurulumu tamamlamak için kendi API'nizi çağırmak.
* Her yükseltmede durumu uzlaştırması gereken idempotent "bu mevcut olsun" mantığı — `shouldRunOnVersionUpgrade: true` ile birleştirin.
Örnek — kurulumdan sonra varsayılan bir `PostCard` kaydı tohumlama:
Uygulamanızın kurulumu tamamlandıktan sonra bir kez çalışır: üstveri eşitlenmiştir, SDK istemcisi oluşturulmuştur, yeni şema sorgulanabilir durumdadır. Örnek — ilk kurulumlarda varsayılan bir kaydı tohumlamak:
```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,
});
```
**Bir geçiş mevcut verileri aksi takdirde silecek veya bozacaksa `pre-install` kullanın.** Kurulum öncesi *önceki* şemaya karşı çalıştığı ve hatalandığında yükseltmeyi geri aldığı için, riskli olan her şey için doğru yerdir:
`shouldRunSynchronously` bayrağı yürütme modelini kontrol eder:
* **Kaldırılmak veya yeniden yapılandırılmak üzere olan verileri yedekleme** — örn. v2'de bir alanı kaldırıyorsunuz ve geçiş çalışmadan önce değerlerini başka bir alana kopyalamanız veya depolamaya aktarmanız gerekiyor.
* **Yeni bir kısıtın geçersiz kılacağı kayıtları arşivleme** — örn. bir alan `NOT NULL` oluyor ve önce null değerli satırları silmeniz veya düzeltmeniz gerekiyor.
* **Uyumluluğu doğrulama ve mevcut veriler temiz bir şekilde geçirilemiyorsa yükseltmeyi reddetme** — işleyiciden hata fırlatın ve kurulum, herhangi bir değişiklik uygulanmadan iptal edilir. Bu, uyumsuzluğu geçişin ortasında keşfetmekten daha güvenlidir.
* İlişkilendirmeyi kaybettirecek bir şema değişikliğinden önce **verileri yeniden adlandırma veya yeniden anahtarlama**.
* `false` *(varsayılan)* — mesaj kuyruğuna alınır (`retryLimit: 3`) ve bir worker tarafından çalıştırılır. Kurulum yanıtı, iş kuyruğa alınır alınmaz döner. **Uzun süreli işler için kullanın** — büyük veri kümelerinin tohumlanması, yavaş üçüncü taraf API'leri.
* `true` — kurulum akışı sırasında satır içi olarak yürütülür. Kurulum isteği, işleyici bitene kadar bloke olur; fırlatılan bir hata, çağırana `POST_INSTALL_ERROR` olarak yansır (yeniden deneme yoktur). **Hızlı ve yanıt dönmeden önce mutlaka tamamlanması gereken işler için kullanın.** Bu noktada geçiş zaten uygulanmıştır, bu nedenle bir hata şema değişikliklerini geri almaz — yalnızca hatayı görünür kılar.
Örnek — yıkıcı bir geçişten önce kayıtları arşivleme:
</Accordion>
<Accordion title="definePreInstallLogicFunction" description="Çalışma alanı üstveri (metadata) geçişi uygulanmadan önce çalışır">
Üstveri geçişinden önce, **önceki** şemaya karşı çalışır — bir geçişin kaybedeceği verileri yedeklemek veya riskli bir yükseltmeyi reddetmek için doğru yerdir. Çalıştırmadan önce, sunucu yalnızca ekleyici bir "indirgenmiş eşitleme" yürütür; bu, yalnızca yeni sürümün kurulum öncesi işlevini kaydeder, diğer her şey — önceki sürümün nesneleri, alanları ve verileri — işleyiciniz çalıştığında dokunulmadan kalır.
Kurulum öncesi her zaman **senkron**dur ve kurulumu bloke eder. İşleyici bir hata fırlatırsa, herhangi bir şema değişikliğinden önce kurulum iptal edilir — çalışma alanı, tutarlı bir durumda önceki sürümde kalır. Bu kasıtlıdır: kurulum öncesi, riskli bir yükseltmeyi reddetmek için son şansınızdır.
Örnek — geçiş onu düşürmeden önce eski bir alanın değerlerini kopyalamak:
```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({
});
```
**Kural olarak:**
| Şunu yapmak istiyorsunuz... | Kullan |
| ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------- |
| Varsayılan verileri tohumlamak, çalışma alanını yapılandırmak, harici kaynakları kaydetmek | `post-install` |
| Kurulum yanıtını engellememesi gereken uzun süreli tohumlama veya üçüncü taraf çağrılarını çalıştırmak | `post-install` (varsayılan — `shouldRunSynchronously: false`, worker yeniden denemeleriyle) |
| Kurulum çağrısı döner dönmez çağıranın güveneceği hızlı kurulumu çalıştırmak | `post-install` ile `shouldRunSynchronously: true` |
| Yaklaşan geçişin kaybedeceği verileri okumak veya yedeklemek | `pre-install` |
| Mevcut verileri bozacak bir yükseltmeyi reddetmek | `pre-install` (işleyiciden hata fırlatmak) |
| Her yükseltmede uzlaştırma çalıştırmak | `post-install` ile `shouldRunOnVersionUpgrade: true` |
| Yalnızca ilk kurulumda tek seferlik kurulum yapmak | `post-install` ile `shouldRunOnVersionUpgrade: false` (varsayılan) |
<Note>
Emin değilseniz, varsayılan olarak **kurulum sonrası**nı tercih edin. Yalnızca geçişin kendisi yıkıcıysa ve önceki durum yok olmadan önce onu yakalamanız gerekiyorsa kurulum öncesine başvurun.
</Note>
</Accordion>
</AccordionGroup>
@@ -86,6 +86,22 @@ export default defineObject({
**Temel alanlar otomatik olarak eklenir.** Özel bir nesne tanımladığınızda Twenty, sizin için `id`, `name`, `createdAt`, `updatedAt`, `createdBy`, `updatedBy` ve `deletedAt` gibi standart alanlar oluşturur. Bunları `fields` dizinizde bildirmenize gerek yok — yalnızca özel alanlarınızı ekleyin. Aynı ada sahip bir alan bildirerek varsayılan bir alanı geçersiz kılabilirsiniz, ancak bu nadiren iyi bir fikirdir.
</Note>
## Alan tipleri
`twenty-sdk/define` içinden dışa aktarılan, `FieldType` değerlerinin tam kümesi:
| Kategori | Türler |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| Metin | `TEXT`, `RICH_TEXT`, `ARRAY` (string dizisi), `RAW_JSON` |
| Sayısal | `NUMBER` (`universalSettings.dataType`: `'float'` / `'int'` / `'bigint'`), `NUMERIC` (keyfi duyarlılık), `RATING`, `POSITION` |
| Tarihler | `DATE`, `DATE_TIME` |
| Seçim | `BOOLEAN`, `SELECT`, `MULTI_SELECT` |
| Bileşik | `FULL_NAME`, `ADDRESS`, `EMAILS`, `PHONES`, `LINKS`, `CURRENCY`, `ACTOR`, `FILES` |
| Tanımlayıcılar ve ilişkiler | `UUID`, `RELATION`, `MORPH_RELATION` (bkz. [İlişkiler](/l/tr/developers/extend/apps/data/relations)) |
| Sistem | `TS_VECTOR` (sunucu tarafından yönetilen tam metin arama vektörü) |
Bileşik tipler birden çok alt alan depolar (ör. `FULL_NAME` = ad + soyad; `CURRENCY` = `amountMicros` + `currencyCode`). `SELECT` ve `MULTI_SELECT`, yukarıdaki örnekte olduğu gibi bir `options` dizisi gerektirir.
## Varsayılan değerler
Sabit (literal) dize varsayılanları, dize **içinde** tek tırnak içine alınmış olmalıdır — `defaultValue: "'Draft'"`, `defaultValue: "Draft"` değil. Bu nedenle yukarıdaki `status` alanı `` `'${PostCardStatus.DRAFT}'` `` kullanır.
@@ -14,26 +14,39 @@ my-twenty-app/
default-role.ts # Permissions for logic functions
constants/
universal-identifiers.ts # Auto-generated UUIDs and metadata
front-components/
main-page.tsx # Welcome page component
navigation-menu-items/
main-page.navigation-menu-item.ts # Sidebar entry for the welcome page
page-layouts/
main-page.page-layout.ts # Standalone page hosting the component
__tests__/
setup-test.ts
app-install.integration-test.ts
.github/workflows/ci.yml # GitHub Actions
public/ # Static assets
vitest.config.ts # Test runner config
application-config.test.ts # Unit test
global-setup.ts # Integration test setup (sync + uninstall)
schema.integration-test.ts # Integration test against a live server
.github/workflows/
ci.yml # Lint, typecheck, unit + integration tests
cd.yml # Deploy + install on push to main
public/
logo.svg # Static assets
vitest.config.ts # Integration test runner config
vitest.unit.config.ts # Unit test runner config
tsconfig.json, tsconfig.spec.json
.nvmrc, .yarnrc.yml, .oxlintrc.json
README.md, LLMS.md
README.md, AGENTS.md, CLAUDE.md
```
## Temel dosyalar
| Dosya / Klasör | Amaç |
| ---------------------------------------- | --------------------------------------------------------------------------- |
| `src/application-config.ts` | **Gerekli.** Uygulamanızın ana yapılandırma dosyası. |
| `src/default-role.ts` | Mantık işlevlerinizin neye erişebileceğini denetleyen varsayılan rol. |
| `src/constants/universal-identifiers.ts` | Otomatik oluşturulan UUID'ler ve meta veriler (görünen ad, açıklama). |
| `src/__tests__/` | Entegrasyon testleri (kurulum + örnek test). |
| `public/` | Uygulamanızla birlikte sunulan statik varlıklar (görüntüler, yazı tipleri). |
| Dosya / Klasör | Amaç |
| -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `src/application-config.ts` | **Gerekli.** Uygulamanızın ana yapılandırma dosyası. |
| `src/default-role.ts` | Mantık işlevlerinizin neye erişebileceğini denetleyen varsayılan rol. |
| `src/constants/universal-identifiers.ts` | Otomatik oluşturulan UUID'ler ve meta veriler (görünen ad, açıklama). |
| `src/front-components/`, `src/navigation-menu-items/`, `src/page-layouts/` | Bir başlangıç karşılama sayfası: kenar çubuğundan erişilebilen, bağımsız bir sayfa düzeni tarafından oluşturulan bir ön bileşen. |
| `src/__tests__/` | Uygulamayı gerçek bir sunucuya karşı senkronize eden (genel kurulumu ile birlikte) bir birim testi artı bir entegrasyon testi. |
| `public/` | Uygulamanızla birlikte sunulan statik varlıklar (görüntüler, yazı tipleri). |
| `AGENTS.md` / `CLAUDE.md` | Uygulama üzerinde çalışan yapay zekâ kodlama aracıları için yönergeler. |
<Note>
**Dosya organizasyonu size kalmış.** Yukarıdaki klasörler birer konvansiyondur — SDK, dosyanın nerede olduğundan bağımsız olarak `export default defineEntity(...)` çağrılarını AST analizi yoluyla algılar.
@@ -47,15 +60,18 @@ Her iki Twenty SDK paketi de `dependencies` değil, `devDependencies` altında o
{
"dependencies": {},
"devDependencies": {
"twenty-client-sdk": "^2.13.0",
"twenty-sdk": "^2.13.0"
"twenty-client-sdk": "2.20.0",
"twenty-sdk": "2.20.0",
"twenty-ui": "1.0.0-alpha.1"
}
}
```
İskele oluşturucu, `twenty-sdk` ve `twenty-client-sdk` paketlerini kendi sürümüne sabitler — yükseltme yaparken bu ikisini senkron tutun.
* **`twenty-sdk`**, `twenty` CLI'yi ve derleme/iskelet oluşturma araçlarını sağlar. Yalnızca geliştirme ve derleme zamanında çalışır ve yayımlanmış uygulamanızın çalışma zamanında asla içe aktarılmaz.
* **`twenty-client-sdk`** uygulama kodunuz tarafından (`CoreApiClient`, `MetadataApiClient`, `RestApiClient`) içe aktarılır, ancak Twenty bunu çalışma zamanında sağlar — mantık fonksiyonları bunu oluşturulan bir SDK katmanından alır ve ön yüz bileşenleri bunu sunucu tarafından sunulan modüllerden çözümler. Yüklediğiniz kopya yalnızca tür denetimi ve dağıtım zamanındaki derleme için kullanılır, bu yüzden dağıtılan paket ile birlikte gönderilmesine gerek yoktur.
`dependencies` altında bu paketlerden herhangi birinin tutulması, onu kurulu uygulamanın çalışma zamanı paketine dahil eder ve orada gereksiz yük haline getirir. `twenty build`, bunlardan herhangi biri hâlâ `dependencies` altında listelendiğinde bir uyarı verir.
`dependencies` altında bu paketlerden herhangi birinin tutulması, onu kurulu uygulamanın çalışma zamanı paketine dahil eder ve orada gereksiz yük haline getirir. `twenty dev:build`, bunlardan herhangi biri hâlâ `dependencies` altında listelendiğinde bir uyarı verir.
Uygulamanızın kendi çalışma zamanı bağımlılıklarını (mantık fonksiyonlarınızın çalışma zamanında gerçekten içe aktardığı kütüphaneler) her zamanki gibi `dependencies` altına ekleyin.
@@ -6,17 +6,17 @@ description: İlk Twenty uygulamanızı dakikalar içinde oluşturun.
## Ön Gereksinimler
* **Node.js 24+** — [Buradan indirin](https://nodejs.org/)
* **Node.js 24.5+** — [Buradan indirin](https://nodejs.org/)
* **Yarn 4** — Corepack aracılığıyla Node ile birlikte gelir. Etkinleştirin: `corepack enable`
* **Docker** — [Buradan indirin](https://www.docker.com/products/docker-desktop/). Yerel bir Twenty sunucusunu çalıştırmak için gereklidir. Zaten başka bir yerde Twenty çalıştırıyorsanız atlayın.
Bir Twenty uygulaması oluşturmanın üç aşaması vardır. İskelet oluşturucu bunları tek bir sorunsuz akış komutuna indirger, ancak her aşama ayrı bir kavramdır — bir şeyler başarısız olduğunda hangi aşamada olduğunuzu bilmek neyi düzeltmeniz gerektiğini söyler.
| Aşama | Ne yaparsınız | Araç | Sonuç |
| ---------------------------- | ------------------------------------------------- | ----------------------------- | ---------------------------------- |
| **1. İskelet Oluşturma** | Uygulamanın kaynak kodunu oluşturun | `npx create-twenty-app` | Diskte bir TypeScript projesi |
| **2. Bir sunucu çalıştırma** | Eşitleme yapacağınız bir Twenty sunucusu başlatın | Docker + `yarn twenty server` | Çalışan bir Twenty örneği |
| **3. Eşitleme** | Kodunuzu sunucuya canlı olarak eşitleyin | `yarn twenty dev` | Değişiklikleriniz arayüzde görünür |
| Aşama | Ne yaparsınız | Araç | Sonuç |
| ---------------------------- | ------------------------------------------------- | ----------------------------------- | ---------------------------------- |
| **1. İskelet Oluşturma** | Uygulamanın kaynak kodunu oluşturun | `npx create-twenty-app` | Diskte bir TypeScript projesi |
| **2. Bir sunucu çalıştırma** | Eşitleme yapacağınız bir Twenty sunucusu başlatın | Docker + `yarn twenty docker:start` | Çalışan bir Twenty örneği |
| **3. Eşitleme** | Kodunuzu sunucuya canlı olarak eşitleyin | `yarn twenty dev` | Değişiklikleriniz arayüzde görünür |
---
@@ -28,7 +28,7 @@ Bir Twenty uygulaması oluşturmanın üç aşaması vardır. İskelet oluşturu
npx create-twenty-app@latest my-twenty-app
```
Sizden bir ad ve açıklama istenir — varsayılanlar için **Enter** tuşuna basın. Bu, `my-twenty-app/` içinde bir başlangıç `application-config.ts`, varsayılan bir rol, bir CI iş akışı ve bir entegrasyon testi ile bir TypeScript projesi oluşturur.
İskele oluşturucu etkileşimsizdir: dizin adı uygulama adı olur. Oluşturulan üstveriyi özelleştirmek için `--display-name` ve `--description` parametrelerini iletin (bunu daha sonra `src/constants/universal-identifiers.ts` içinde de düzenleyebilirsiniz). Bu, `my-twenty-app/` içinde bir başlangıç `application-config.ts`, varsayılan bir rol, CI/CD iş akışları ve bir entegrasyon testi ile bir TypeScript projesi oluşturur.
**Bu aşamadan sonra:** makinenizde uygulamanın kaynak kodu bulunur. Henüz çalışmıyor — bu, 2. Aşama.
@@ -38,28 +38,14 @@ Sizden bir ad ve açıklama istenir — varsayılanlar için **Enter** tuşuna b
Uygulamanızın eşitleme yapacağı bir Twenty sunucusuna ihtiyacı vardır. Sunucu, Docker içinde yerel olarak çalışan tam bir Twenty örneğidir — UI, GraphQL API, PostgreSQL. Yerel kodunuz tanımlarını bu sunucuya yükler; bu da onların arayüzde görünmesini sağlar.
İskelet oluşturucu sizin için bir tane başlatmayı teklif eder:
İskele oluşturucu bunu sizin için başlatır: Docker çalışırken `twentycrm/twenty-app-dev` imajını çeker, onu `2020` portunda başlatır ve CLI'yı önceden doldurulmuş demo çalışma alanına (`tim@apple.dev`) karşı kimlik doğrular — oturum açmanız gerekmez.
> **Yerel bir Twenty örneği kurmak ister misiniz?**
* **Evet (önerilir)** — `twentycrm/twenty-app-dev` Docker imajını çeker ve `2020` portunda başlatır. Önce Docker'ın çalıştığından emin olun.
* **Hayır** — Zaten bağlanmak istediğiniz bir Twenty sunucunuz varsa bunu seçin. Bunu daha sonra `yarn twenty remote:add` ile bağlayabilirsiniz.
<div style={{textAlign: 'center'}}>
<img src="/images/docs/developers/extends/apps/start-instance.png" alt="Yerel örnek başlatılsın mı?" />
</div>
Sunucu çalışır duruma geldiğinde, oturum açmak için bir tarayıcı açılır. Önceden eklenmiş demo hesabını kullanın:
* **E-posta:** `tim@apple.dev`
* **Parola:** `tim@apple.dev`
Bunun yerine mevcut bir Twenty sunucusuna bağlanmak için `--url \<your-server-url>` parametresini iletin. Uzak sunucular OAuth ile kimlik doğrular: oturum açabilmeniz ve **Authorize**'a tıklayabilmeniz için bir tarayıcı açılır; bu, CLI'ye çalışma alanınıza erişim sağlar. (Yerelde de `--authentication-method oauth` ile OAuth kullanmayı tercih edebilirsiniz — `tim@apple.dev` / `tim@apple.dev` ile oturum açın.)
<div style={{textAlign: 'center'}}>
<img src="/images/docs/developers/extends/apps/login.png" alt="Twenty oturum açma ekranı" />
</div>
Sonraki ekranda **Authorize**'a tıklayın — bu işlem CLI'nin çalışma alanınıza erişmesine izin verir.
<div style={{textAlign: 'center'}}>
<img src="/images/docs/developers/extends/apps/authorize.png" alt="Twenty CLI yetkilendirme ekranı" />
</div>
@@ -117,27 +103,31 @@ Daha ayrıntılı çıktı (derleme günlükleri, eşitleme istekleri, hata izle
### CI ve betikler için tek seferlik eşitleme
Tek bir derleme + eşitleme çalıştırıp çıkmak için `--once` parametresini geçin — aynı ardışık düzen, izleyici yok:
Bir izleyici olmadan aynı boru hattını bir kez çalıştırmak için `plan` ve `apply` komutlarını kullanın:
```bash filename="Terminal"
yarn twenty dev --once
yarn twenty plan # preview the metadata changes without applying them
yarn twenty apply # show the plan, then apply it
```
| Komut | Davranış | Ne zaman kullanılmalı |
| ---------------------------------- | ----------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| `yarn twenty dev` | Her değişiklikte izler ve yeniden eşitler. Siz durdurana kadar çalışır. | Etkileşimli yerel geliştirme. |
| `yarn twenty dev --once` | Tek derleme + eşitleme; başarıda `0`, başarısızlıkta `1` ile çıkar. | CI, pre-commit kancaları, AI ajanları, betiklenmiş iş akışları. |
| `yarn twenty dev --once --dry-run` | Meta veri değişikliklerini **uygulamadan oluşturur ve yazdırır**. | Bir senkronizasyonun, ona başlamadan önce neleri değiştireceğini incelemek. |
| Komut | Davranış | Ne zaman kullanılmalı |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| `yarn twenty dev` | Her değişiklikte izler ve yeniden eşitler. Siz durdurana kadar çalışır. | Etkileşimli yerel geliştirme. |
| `yarn twenty apply` | Tek derleme + eşitleme; başarıda `0`, başarısızlıkta `1` ile çıkar. Yıkıcı değişiklikler için onay ister (atlamak için `--force` parametresini iletin). | CI, pre-commit kancaları, AI ajanları, betiklenmiş iş akışları. |
| `yarn twenty plan` | Meta veri değişikliklerini **uygulamadan oluşturur ve yazdırır**. | Bir senkronizasyonun, ona başlamadan önce neleri değiştireceğini incelemek. |
Her iki kipin de kimliği doğrulanmış bir uzak sunucuya ihtiyaç duyar. `--dry-run` hakkında daha fazla bilgi için [Senkronizasyon ve kurtarma](/l/tr/developers/extend/apps/operations/sync-and-recovery#previewing-changes-dry-run) bölümüne bakın.
Tüm kiplerin kimliği doğrulanmış bir uzak sunucuya ihtiyacı vardır. `plan` hakkında daha fazla bilgi için [Senkronizasyon ve kurtarma](/l/tr/developers/extend/apps/operations/sync-and-recovery#previewing-changes-plan) bölümüne bakın.
<Note>
`yarn twenty dev --once` ve `yarn twenty dev --once --dry-run`, `yarn twenty apply` ve `yarn twenty plan` için kullanımdan kaldırılmış takma adlardır.
</Note>
### Geliştirme kipi seçenekleri
| Bayrak | Açıklama |
| ------------------------------------- | ------------------------------------------------------------------------------------------ |
| `--once` | Bir kez derleyip eşitleyin, ardından çıkın. |
| `--dry-run` | `--once` ile meta veri değişikliklerini uygulamadan önizleyin. Hiçbir şey yazmaz. |
| `--debounceMs \<ms>` | Dosya değişikliği geciktirme süresini milisaniye cinsinden ayarlayın (varsayılan: `2000`). |
| `--force` | Onay olmadan yıkıcı değişiklikleri (silme işlemlerini) uygular. |
| `--debounceMs \<ms>` | Dosya değişikliği geciktirme süresini milisaniye cinsinden ayarlayın (varsayılan: `1000`). |
| `--verbose` / `--debug` | Ayrıntılı derleme günlüklerini, eşitleme isteklerini ve hata izlerini gösterin. |
## Oluşturabilecekleriniz
@@ -34,6 +34,10 @@ yarn twenty dev:add frontComponent
| Görünüm | `yarn twenty dev:add view` | `src/views/\<name>.ts` |
| Gezinme menüsü öğesi | `yarn twenty dev:add navigationMenuItem` | `src/navigation-menu-items/\<name>.ts` |
| Sayfa düzeni | `yarn twenty dev:add pageLayout` | `src/page-layouts/\<name>.ts` |
| Sayfa düzeni sekmesi | `yarn twenty dev:add pageLayoutTab` | `src/page-layout-tabs/\<name>.ts` |
| Komut menüsü öğesi | `yarn twenty dev:add commandMenuItem` | `src/command-menu-items/\<name>.ts` |
| Görünüm alanı | `yarn twenty dev:add viewField` | `src/view-fields/\<name>.ts` |
| Bağlantı sağlayıcısı | `yarn twenty dev:add connectionProvider` | `src/connection-providers/\<name>.ts` |
## İskelet oluşturucunun ürettikleri
@@ -5,10 +5,10 @@ icon: wrench
---
* **Docker hataları** — `yarn twenty docker:start` öncesinde Docker Desktop'ın (veya daemon'un) çalıştığından emin olun. Hata iletisi, işletim sisteminiz için doğru başlatma komutunu gösterecektir.
* **Yanlış Node sürümü** — 24+ gerekir. `node -v` ile kontrol edin.
* **Yanlış Node sürümü** — 24.5+ gerekiyor (`engines.node: ^24.5.0`). `node -v` ile kontrol edin.
* **Yarn 4 eksik** — `corepack enable` çalıştırın.
* **Bağımlılıklar bozuk** — `rm -rf node_modules && yarn install`.
* **`twenty-sdk` v2.8.0 sürümüne yükselttikten sonra oluşan hatalar** — v2.8.0 sürümünde `dependencies` içinden `devDependencies` içine taşındı. [Proje Yapısı → Bağımlılıklar](/l/tr/developers/extend/apps/getting-started/project-structure#dependencies) bölümüne bakın.
* **`twenty build`, `dependencies` altındaki `twenty-client-sdk` konusunda uyarır** — Bu paket, çalışma zamanında Twenty tarafından sağlanır, bu nedenle `twenty-sdk` ile birlikte `devDependencies` altına taşınmalıdır. [Proje Yapısı → Bağımlılıklar](/l/tr/developers/extend/apps/getting-started/project-structure#dependencies) bölümüne bakın.
* **`dependencies` altındaki `twenty-client-sdk` hakkında `twenty dev:build` uyarısı** — Bu paket, çalışma zamanında Twenty tarafından sağlanır, bu nedenle `twenty-sdk` ile birlikte `devDependencies` altına taşınmalıdır. [Proje Yapısı → Bağımlılıklar](/l/tr/developers/extend/apps/getting-started/project-structure#dependencies) bölümüne bakın.
Takıldınız mı? [Twenty Discord](https://discord.com/channels/1130383047699738754/1130386664812982322) üzerinde yardım isteyin.
@@ -13,7 +13,6 @@ export default defineCommandMenuItem({
universalIdentifier: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
label: 'Open Dashboard',
shortLabel: 'Dashboard',
icon: 'IconLayoutDashboard',
isPinned: true,
availabilityType: 'GLOBAL',
frontComponentUniversalIdentifier: '74c526eb-cb68-4cf7-b05c-0dd8c288d948',
@@ -22,51 +21,23 @@ export default defineCommandMenuItem({
## Yapılandırma alanları
| Alan | Zorunlu | Açıklama |
| --------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `universalIdentifier` | Evet | Komut için kalıcı benzersiz kimlik |
| `label` | Evet | Komut menüsünde (Cmd+K) gösterilen tam etiket |
| `frontComponentUniversalIdentifier` | Evet | Bu komutun açtığı ön bileşenin `universalIdentifier` değeri |
| `shortLabel` | Hayır | Sabitlenmiş hızlı işlem düğmesinde görüntülenen daha kısa etiket |
| `icon` | Hayır | Etiketin yanında görüntülenen simge adı (örn. `'IconBolt'`, `'IconSend'`) |
| `isPinned` | Hayır | `true` olduğunda, komutu sayfanın sağ üst köşesinde bir hızlı işlem düğmesi olarak gösterir |
| `availabilityType` | Hayır | Komutun nerede görüneceğini kontrol eder: `'GLOBAL'` (her zaman kullanılabilir), `'RECORD_SELECTION'` (yalnızca kayıtlar seçiliyken) veya `'FALLBACK'` (başka hiçbir komut eşleşmediğinde gösterilir) |
| `availabilityObjectUniversalIdentifier` | Hayır | Komutu belirli bir nesne türünün sayfalarıyla sınırlandırın (örn. yalnızca Company kayıtlarında) |
| `conditionalAvailabilityExpression` | Hayır | Görünürlüğü dinamik olarak kontrol eden bir boolean ifade (aşağıya bakın) |
| Alan | Zorunlu | Açıklama |
| --------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `universalIdentifier` | Evet | Komut için kalıcı benzersiz kimlik |
| `label` | Evet | Komut menüsünde (Cmd+K) gösterilen tam etiket |
| `frontComponentUniversalIdentifier` | Evet | Bu komutun açtığı ön bileşenin `universalIdentifier` değeri |
| `shortLabel` | Hayır | Sabitlenmiş hızlı işlem düğmesinde görüntülenen daha kısa etiket |
| `icon` | Hayır | **Kullanımdan kaldırıldı** — uygulama simgesi tercih edildiği için yok sayılır; ayarlanırsa oluşturma sırasında bir uyarı verir |
| `isPinned` | Hayır | `true` olduğunda, komutu sayfanın sağ üst köşesinde bir hızlı işlem düğmesi olarak gösterir |
| `availabilityType` | Hayır | Komutun nerede görüneceğini kontrol eder: `'GLOBAL'` (her zaman kullanılabilir), `'GLOBAL_OBJECT_CONTEXT'` (yalnızca bir nesne bağlamı olan sayfalarda — indeks ve kayıt sayfaları), `'RECORD_SELECTION'` (yalnızca kayıtlar seçiliyken) veya `'FALLBACK'` (başka hiçbir komut eşleşmediğinde gösterilir) |
| `availabilityObjectUniversalIdentifier` | Hayır | Komutu belirli bir nesne türünün sayfalarıyla sınırlandırın (örn. yalnızca Company kayıtlarında) |
| `conditionalAvailabilityExpression` | Hayır | Görünürlüğü dinamik olarak kontrol eden bir boolean ifade (aşağıya bakın) |
## Arayüzsüz komutlar
Bir [arayüzsüz ön bileşen](/l/tr/developers/extend/apps/layout/front-components#headless-vs-non-headless) ile eşleştirilmiş bir komut menüsü öğesi, tek tıklamayla bir eylem sunmanın — kod çalıştırma, gezinme veya onaylayıp yürütme — yaygın kullanılan biçimidir. Ön Bileşenler sayfası, eylem-ve-kaldırma modelini yöneten [SDK Command bileşenlerini](/l/tr/developers/extend/apps/layout/front-components#sdk-command-components) (`Command`, `CommandLink`, `CommandModal`, `CommandOpenSidePanelPage`) kapsar.
Tipik bir akış:
```tsx src/front-components/run-action.tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import { Command } from 'twenty-sdk/command';
import { CoreApiClient } from 'twenty-sdk/clients';
const RunAction = () => {
const execute = async () => {
const client = new CoreApiClient();
await client.mutation({
createTask: {
__args: { data: { title: 'Created by my app' } },
id: true,
},
});
};
return <Command execute={execute} />;
};
export default defineFrontComponent({
universalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
name: 'run-action',
description: 'Creates a task from the command menu',
component: RunAction,
isHeadless: true,
});
```
Tipik bir akış: başsız bir bileşen `<Command execute={...} />` oluşturur (bkz. [tam örnek](/l/tr/developers/extend/apps/layout/front-components#sdk-command-components)) ve komut menüsü öğesi ona işaret eder:
```ts src/command-menu-items/run-action.command-menu-item.ts
import { defineCommandMenuItem } from 'twenty-sdk/define';
@@ -74,7 +45,6 @@ import { defineCommandMenuItem } from 'twenty-sdk/define';
export default defineCommandMenuItem({
universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345',
label: 'Run my action',
icon: 'IconPlayerPlay',
frontComponentUniversalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
});
```
@@ -49,14 +49,13 @@ export default defineCommandMenuItem({
universalIdentifier: 'd4e5f6a7-b8c9-0123-defa-456789012345',
shortLabel: 'Hello',
label: 'Hello World',
icon: 'IconBolt',
isPinned: true,
availabilityType: 'GLOBAL',
frontComponentUniversalIdentifier: '74c526eb-cb68-4cf7-b05c-0dd8c288d948',
});
```
`yarn twenty dev` ile senkronize ettikten sonra (veya tek seferlik bir `yarn twenty dev --once` çalıştırdıktan sonra), hızlı işlem sayfanın sağ üst köşesinde görünür:
`yarn twenty dev` ile senkronize ettikten sonra (veya tek seferlik bir `yarn twenty apply` çalıştırdıktan sonra), hızlı işlem sayfanın sağ üst köşesinde görünür:
<div style={{textAlign: 'center'}}>
<img src="/images/docs/developers/extends/apps/quick-action.png" alt="Sağ üst köşedeki hızlı işlem düğmesi" />
@@ -88,11 +87,11 @@ Komutların ötesinde, bir ön uç bileşenini bir **sayfa düzeninde** widget o
```tsx src/front-components/sync-tracker.tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import { useRecordId, enqueueSnackbar } from 'twenty-sdk/front-component';
import { useSelectedRecordIds, enqueueSnackbar } from 'twenty-sdk/front-component';
import { useEffect } from 'react';
const SyncTracker = () => {
const recordId = useRecordId();
const [recordId] = useSelectedRecordIds();
useEffect(() => {
enqueueSnackbar({ message: `Tracking record ${recordId}`, variant: 'info' });
@@ -116,7 +115,7 @@ Bileşen `null` döndürdüğü için, Twenty bunun için bir kapsayıcı oluşt
`twenty-sdk` paketi, headless ön uç bileşenler için tasarlanmış dört Command yardımcı bileşeni sağlar. Her bileşen bağlandığında bir eylem yürütür, hataları bir snackbar bildirimi göstererek ele alır ve tamamlandığında ön bileşeni otomatik olarak kaldırır.
Bunları `twenty-sdk/command` içinden içe aktarın:
Bunları `twenty-sdk/front-component` içinden içe aktarın:
* **`Command`** — `execute` prop'u aracılığıyla async bir geri çağrıyı çalıştırır.
* **`CommandLink`** — Bir uygulama yoluna gider. Props: `to`, `params`, `queryParams`, `options`.
@@ -127,8 +126,8 @@ Bunları `twenty-sdk/command` içinden içe aktarın:
```tsx src/front-components/run-action.tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import { Command } from 'twenty-sdk/command';
import { CoreApiClient } from 'twenty-sdk/clients';
import { Command } from 'twenty-sdk/front-component';
import { CoreApiClient } from 'twenty-client-sdk/core';
const RunAction = () => {
const execute = async () => {
@@ -160,7 +159,6 @@ import { defineCommandMenuItem } from 'twenty-sdk/define';
export default defineCommandMenuItem({
universalIdentifier: 'f6a7b8c9-d0e1-2345-fabc-456789012345',
label: 'Run my action',
icon: 'IconPlayerPlay',
frontComponentUniversalIdentifier: 'e5f6a7b8-c9d0-1234-efab-345678901234',
});
```
@@ -169,7 +167,7 @@ Ve yürütmeden önce onay istemek için `CommandModal` kullanan bir örnek:
```tsx src/front-components/delete-draft.tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import { CommandModal } from 'twenty-sdk/command';
import { CommandModal } from 'twenty-sdk/front-component';
const DeleteDraft = () => {
const execute = async () => {
@@ -202,7 +200,7 @@ export default defineFrontComponent({
`httpRouteTriggerSettings` ile bildirilen bir mantık işlevi, rota yolunda HTTP üzerinden erişilebilir durumdadır. Twenty, işlevlerinizin sunulduğu temel URLyi, çağrıyı kimlik doğrulayan `TWENTY_APP_ACCESS_TOKEN` ile birlikte, workera `TWENTY_FUNCTIONS_URL` olarak enjekte eder. Kendi işlevlerinizi çağırmak için henüz özel bir SDK istemcisi yoktur, bu yüzden onları basit bir `fetch` ile çağırın:
> **Twenty Cloud üzerinde, HTTP ile tetiklenen mantık işlevleri, çalışma alanı başına ayrılmış özel bir etki alanında** `https://\<your-workspace-subdomain>.twenty.com\<path>` adresinde sunulur — bu, `TWENTY_FUNCTIONS_URL`'ün tam olarak çözümlendiği değerdir. Harici çağrıcılar için, tam URLyi işlevin **HTTP trigger** ayarlarından veya uygulamanın **Settings** sekmesinden kopyalayın.
> **Twenty Cloud üzerinde, HTTP ile tetiklenen mantık işlevleri, çalışma alanı başına ayrılmış özel bir etki alanında** `https://\<your-workspace-subdomain>.withtwenty.com\<path>` adresinde sunulur — bu, `TWENTY_FUNCTIONS_URL`'ün tam olarak çözümlendiği değerdir. Harici çağrıcılar için, tam URLyi işlevin **HTTP trigger** ayarlarından veya uygulamanın **Settings** sekmesinden kopyalayın.
<Warning>
Eski `/s/` fonksiyon rotası **kullanımdan kaldırılmıştır (deprecated)** ve **2026-07-24 tarihinde devre dışı bırakılacaktır**. Bunun yerine yukarıdaki `TWENTY_FUNCTIONS_URL` değerini kullanın ve o tarihten önce sabit (hard-coded) tüm `/s/` URLlerini taşıyın. `/s/` rotası, self-hosting için kullanılabilir olmaya devam eder.
@@ -212,7 +210,7 @@ Başsız bir ön bileşen, çağrıyı `Command` bileşeni aracılığıyla moun
```tsx src/front-components/sync-prs.tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import { Command } from 'twenty-sdk/command';
import { Command } from 'twenty-sdk/front-component';
const SyncPrs = () => {
const execute = async () => {
@@ -316,13 +314,13 @@ Bileşeninizin içinde, geçerli kullanıcıya, kayda ve bileşen örneğine eri
import { defineFrontComponent } from 'twenty-sdk/define';
import {
useUserId,
useRecordId,
useSelectedRecordIds,
useFrontComponentId,
} from 'twenty-sdk/front-component';
const RecordInfo = () => {
const userId = useUserId();
const recordId = useRecordId();
const [recordId] = useSelectedRecordIds();
const componentId = useFrontComponentId();
return (
@@ -405,12 +403,11 @@ Bir eylem tamamlandıktan sonra bir snackbar göstermek ve yan paneli kapatmak i
```tsx src/front-components/archive-record.tsx
import { defineFrontComponent } from 'twenty-sdk/define';
import { useRecordId } from 'twenty-sdk/front-component';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk/front-component';
import { CoreApiClient } from 'twenty-sdk/clients';
import { enqueueSnackbar, closeSidePanel, useSelectedRecordIds } from 'twenty-sdk/front-component';
import { CoreApiClient } from 'twenty-client-sdk/core';
const ArchiveRecord = () => {
const recordId = useRecordId();
const [recordId] = useSelectedRecordIds();
const handleArchive = async () => {
const client = new CoreApiClient();
@@ -451,10 +448,10 @@ export default defineFrontComponent({
Birden çok seçili kaydı yönetmek için `useSelectedRecordIds()` kullanın. Bu, toplu işlemler için kullanışlıdır:
```tsx src/front-components/bulk-export.tsx
import { defineFrontComponent, numberOfSelectedRecords } from 'twenty-sdk/define';
import { defineFrontComponent } from 'twenty-sdk/define';
import { useSelectedRecordIds } from 'twenty-sdk/front-component';
import { enqueueSnackbar, closeSidePanel } from 'twenty-sdk/front-component';
import { CoreApiClient } from 'twenty-sdk/clients';
import { CoreApiClient } from 'twenty-client-sdk/core';
const BulkExport = () => {
const selectedRecordIds = useSelectedRecordIds();
@@ -492,12 +489,19 @@ export default defineFrontComponent({
name: 'bulk-export',
description: 'Export selected records',
component: BulkExport,
command: {
universalIdentifier: 'd0e1f2a3-b4c5-6789-defa-012345678902',
label: 'Bulk Export',
availabilityType: 'RECORD_SELECTION',
conditionalAvailabilityExpression: numberOfSelectedRecords > 0,
},
});
```
Bunu, kayıt seçimleriyle kısıtlanmış bir [komut menüsü öğesi](/l/tr/developers/extend/apps/layout/command-menu-items) ile yüzeye çıkarın:
```ts src/command-menu-items/bulk-export.command-menu-item.ts
import { defineCommandMenuItem } from 'twenty-sdk/define';
export default defineCommandMenuItem({
universalIdentifier: 'd0e1f2a3-b4c5-6789-defa-012345678902',
label: 'Bulk Export',
availabilityType: 'RECORD_SELECTION',
frontComponentUniversalIdentifier: 'd0e1f2a3-b4c5-6789-defa-012345678901',
});
```
@@ -35,6 +35,8 @@ export default defineNavigationMenuItem({
* `position`, kenar çubuğundaki sıralamayı kontrol eder.
* Enum ayrıca dahili olarak kullanıcı tarafından oluşturulan kayıt favorileri için kullanılan `NavigationMenuItemType.RECORD` öğesini de içerir — bir kayıt başvuracak bir alan olmadığı için bir uygulama manifestinden kullanılamaz.
* `icon` ve `color` isteğe bağlıdır ve öğenin görünümünü özelleştirir.
* `folderUniversalIdentifier`, herhangi bir öğede de mevcuttur ve onu bir `FOLDER` türü üst öğenin içine yerleştirmek için kullanılır.
@@ -33,17 +33,32 @@ export default defineView({
## Önemli noktalar
* `objectUniversalIdentifier`, bu görünümün hangi nesneye uygulanacağını belirtir. Bu, tanımladığınız özel bir nesne veya standart bir Twenty nesnesi olabilir.
* `key`, görünüm türünü belirler — `ViewKey.INDEX`, nesne için ana liste görünümüdür.
* `key: ViewKey.INDEX` görünümü nesnenin ana liste görünümü olarak işaretler (bir `OBJECT` gezinme öğesinin açtığı görünüm).
* `fields`, hangi sütunların görüneceğini ve hangi sırayla görüneceğini kontrol eder. Her alan bir `fieldMetadataUniversalIdentifier` öğesine referans verir.
* Daha gelişmiş yapılandırmalar için `filters`, `filterGroups`, `groups` ve `fieldGroups` da tanımlayabilirsiniz.
* Daha gelişmiş yapılandırmalar için `filters`, `filterGroups`, `sorts`, `groups` ve `fieldGroups` da tanımlayabilirsiniz.
* `position`, aynı nesne için birden fazla görünüm olduğunda sıralamayı kontrol eder.
## İsteğe bağlı özellikler
| Özellik | Değerler | Açıklama |
| ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | `ViewType.TABLE` (varsayılan), `ViewType.KANBAN`, `ViewType.CALENDAR` | Kayıtların nasıl düzenlendiği. (`FIELDS_WIDGET` / `TABLE_WIDGET` da mevcuttur ancak sayfa düzeni bileşenleri tarafından dahili olarak kullanılır.) |
| `visibility` | `ViewVisibility.WORKSPACE` (varsayılan), `ViewVisibility.UNLISTED` | Görünümün tüm çalışma alanı için listelenip listelenmediği veya seçicilerden gizlenip gizlenmediği. |
| `openRecordIn` | `ViewOpenRecordIn.SIDE_PANEL` (varsayılan), `ViewOpenRecordIn.RECORD_PAGE` | Bir kayda tıklandığında onun nerede açıldığı. |
| `sorts` | `{ fieldMetadataUniversalIdentifier, direction: ViewSortDirection.ASC \| DESC }[]` | Varsayılan sıralama düzeni. |
| `isCompact` | `boolean` | Sıkıştırılmış satır gösterimi. |
| `mainGroupByFieldMetadataUniversalIdentifier` + `shouldHideEmptyGroups` | — | Kayıtları bir alana göre gruplayın (ör. kanban sütunları). |
| `kanbanAggregateOperation`, `kanbanAggregateOperationFieldMetadataUniversalIdentifier`, `kanbanColumnWidth` | `AggregateOperations.*` | Kanban sütunu toplamları ve boyutlandırması. |
| `calendarLayout`, `calendarFieldMetadataUniversalIdentifier` | `ViewCalendarLayout.DAY` / `WEEK` / `MONTH` | Takvim görünümleri: düzen ve kayıtları konumlandıran tarih alanı. |
Yukarıdaki tüm enum"lar `twenty-sdk/define` içinden dışa aktarılır.
## Filtreler
Bir görünüm, önceden uygulanmış filtrelerle gelebilir. Her filtrenin üç koordinatı vardır: filtrelenen **alan**, **işleç** (nasıl karşılaştırılacağı) ve **değer** (neyle karşılaştırılacağı). Üçünün de hizalı olması gerekir — bir alan türüne uygulanmayan bir işlecin kullanılması, senkronizasyon sırasında reddedilir.
```ts
import { ViewFilterOperand } from 'twenty-shared/types';
import { ViewFilterOperand } from 'twenty-sdk/define';
filters: [
{
@@ -51,8 +51,12 @@ export default defineLogicFunction({
```
Kullanılabilir tetikleyici türleri:
* **httpRoute**: İşlevinizi bir HTTP yolu ve yöntemiyle **`/s/` uç noktasının altında** kullanıma sunar:
> örn. `path: '/post-card/create'` `https://your-twenty-server.com/s/post-card/create` adresinden çağrılabilir
* **httpRoute**: İşlevinizi çalışma alanınızın **işlevler temel URL'sinde** bir HTTP yolunda ve yönteminde açığa çıkarır — Twenty'nin `TWENTY_FUNCTIONS_URL` olarak enjekte ettiği değer (Twenty Cloud'da, çalışma alanı başına ayrılmış özel bir alan adı):
> örn. `path: '/post-card/create'` `https://your-workspace.withtwenty.com/post-card/create` adresinden çağrılabilir
<Warning>
Eski `/s/` ön ekli rota (`https://your-twenty-server.com/s/post-card/create`) **Twenty Cloud üzerinde kullanım dışıdır (deprecated)** ve **2026-07-24** tarihinde devre dışı bırakılacaktır. Yalıtılmış bir işlev alanı yapılandırmayan kendi kendine barındırılan ve yerel örnekler için kullanılabilir durumda kalır — ayarlanmışsa `TWENTY_FUNCTIONS_URL` kullanın ve aksi takdirde `\<server-url>/s/\<path>` rotasına geri dönün.
</Warning>
<Note>
Arayüzsüz bir ön uç bileşeninden rota tarafından tetiklenen mantık fonksiyonunu çağırmak için bkz. [Mantık fonksiyonu çağırma](/l/tr/developers/extend/apps/layout/front-components#calling-a-logic-function).
@@ -42,7 +42,7 @@ Bir mantık fonksiyonu bir veya daha fazla tetikleyici seçer — aşağıdaki h
| Tetikleyici | Ne zaman çalışır | Ayar |
| --------------------- | ---------------------------------------------------------------------------- | ------------------------------- |
| **HTTP rotası** | Bir istek `/s/\<path>` endpoint'inize ulaşır | `httpRouteTriggerSettings` |
| **HTTP rotası** | Bir istek, işlevinizin genel URL'sine ulaşır | `httpRouteTriggerSettings` |
| **Cron** | Bir CRON ifadesi eşleştiğinde | `cronTriggerSettings` |
| **Veritabanı olayı** | Bir çalışma alanı kaydı oluşturulduğunda, güncellendiğinde veya silindiğinde | `databaseEventTriggerSettings` |
| **Yapay zeka aracı** | Bir Twenty yapay zeka özelliği, fonksiyonunuzu çağırmaya karar verdiğinde | `toolTriggerSettings` |
@@ -4,7 +4,25 @@ description: Fonksiyonları çalıştırmak, günlükleri akış olarak izlemek,
icon: terminal
---
`dev`, `dev:build`, `dev:add` ve `dev:typecheck` dışında, `yarn twenty` CLI, fonksiyonları çalıştırma, günlükleri görüntüleme ve uygulama kurulumlarını yönetme komutları sağlar.
`yarn twenty` CLI, uygulama ile ilgili her şey için arayüzünüzdür. Tam komut listesi:
| Komut | Ne yapar | Şurada belgelenmiştir |
| ----------------------------------------------- | ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `dev` | Kaynak dosyaları izleyin ve değişiklikleri canlı olarak eşitleyin | [Hızlı Başlangıç](/l/tr/developers/extend/apps/getting-started/quick-start) |
| `plan` | Meta veri değişikliklerini uygulamadan önizleyin | [Senkronizasyon ve kurtarma](/l/tr/developers/extend/apps/operations/sync-and-recovery#previewing-changes-plan) |
| `apply` | Planı gösterdikten sonra meta veri değişikliklerini uygulayın | [Senkronizasyon ve kurtarma](/l/tr/developers/extend/apps/operations/sync-and-recovery) |
| `dev:build` | Uygulamayı derleyin ve API istemcisini oluşturun (`.tgz` paketlemek için `--tarball`) | [Yayınlama](/l/tr/developers/extend/apps/operations/publishing) |
| `dev:typecheck` | TypeScript tür kontrolünü çalıştırın | [Testing](/l/tr/developers/extend/apps/operations/testing) |
| `dev:add` | Yeni bir varlık iskeleti oluşturun | [İskele oluşturma](/l/tr/developers/extend/apps/getting-started/scaffolding) |
| `dev:generate-client` | Türlendirilmiş API istemcisini yeniden oluşturun | bu sayfa |
| `dev:function:exec` / `dev:function:logs` | Fonksiyonları çalıştırın ve günlüklerini akış halinde alın | bu sayfa |
| `dev:translations-extract` | Çevrilebilir dizeleri `locales/` kataloglarına çıkarın | [Çeviriler](/l/tr/developers/extend/apps/translations/overview) |
| `dev:catalog-sync` | Pazar yeri katalog eşitlemesini tetikleyin | [Yayınlama](/l/tr/developers/extend/apps/operations/publishing#how-marketplace-discovery-works) |
| `app:publish` / `app:install` / `app:uninstall` | Yayın yaşam döngüsü | [Yayınlama](/l/tr/developers/extend/apps/operations/publishing) ve bu sayfa |
| `docker:*` | Yerel Twenty sunucu konteynerini yönetin | [Yerel Sunucu](/l/tr/developers/extend/apps/getting-started/local-server) |
| `remote:*` | Sunucu bağlantılarını yönetin | bu sayfa |
Her komut, varsayılan yerine belirli bir uzak sunucuyu hedeflemek için `-r, --remote \<name>` kabul eder.
## Fonksiyonları çalıştırma (`yarn twenty dev:function:exec`)
@@ -20,8 +38,9 @@ yarn twenty dev:function:exec -u e56d363b-0bdc-4d8a-a393-6f0d1c75bdcf
# Pass a JSON payload
yarn twenty dev:function:exec -n create-new-post-card -p '{"name": "Hello"}'
# Execute the post-install function
# Execute the install hooks
yarn twenty dev:function:exec --postInstall
yarn twenty dev:function:exec --preInstall
```
## Fonksiyon günlüklerini görüntüleme (`yarn twenty dev:function:logs`)
@@ -100,6 +119,12 @@ yarn twenty remote:list
# Set the active remote
yarn twenty remote:use <name>
# Check that the active remote's authentication is still valid
yarn twenty remote:status
# Remove a remote
yarn twenty remote:remove <name>
```
Kimlik bilgileriniz `~/.twenty/config.json` içinde saklanır.
@@ -229,7 +229,7 @@ yarn twenty dev:catalog-sync
# yarn twenty dev:catalog-sync --remote production
```
Pazar yerinde gösterilen meta veriler, `defineApplication()` yapılandırmanızdan gelir — `displayName`, `description`, `author`, `category`, `logoUrl`, `screenshots`, `aboutDescription`, `websiteUrl` ve `termsUrl` gibi alanlar.
Pazaryerinde gösterilen meta veriler, `defineApplication()` yapılandırmanızdan gelir — yukarıdaki [Pazaryeri meta verileri](#marketplace-metadata) bölümüne bakın.
<Note>
Uygulamanız `defineApplication()` içinde bir `aboutDescription` tanımlamıyorsa, pazaryeri, hakkında sayfasının içeriği olarak paketinizin npm'deki `README.md` dosyasını otomatik olarak kullanır. Bu, hem npm hem de Twenty pazaryeri için tek bir README dosyası kullanabileceğiniz anlamına gelir. Pazaryerinde farklı bir açıklama istiyorsanız, `aboutDescription` değerini açıkça ayarlayın.
@@ -15,33 +15,44 @@ Günlük yerel yinelemelerde neredeyse her zaman `yarn twenty dev` kullanmak ist
| Şunu yapmak istiyorsunuz… | Komut | Notlar |
| ---------------------------------------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| Canlı senkronizasyonla yerelde yineleyin | `yarn twenty dev` | Dosyalarınızı izler ve her değişiklikte senkronize eder. |
| Bir kez senkronize et ve çık (CI, betikler, kancalar) | `yarn twenty dev --once` | Tek bir derleme + senkronizasyon yapar ve ardından çıkar. |
| Değişiklikleri **uygulamadan** önizleyin | `yarn twenty dev --once --dry-run` | Farkı hesaplar ve yazdırır; hiçbir şey yazmaz. |
| Bir kez senkronize et ve çık (CI, betikler, kancalar) | `yarn twenty apply` | Tek bir derleme + senkronizasyon yapar ve ardından çıkar. Yıkıcı değişiklik onayını atlamak için `--force` ekleyin. |
| Değişiklikleri **uygulamadan** önizleyin | `yarn twenty plan` | Farkı hesaplar ve yazdırır; hiçbir şey yazmaz. |
| Uygulamayı çalışma alanından kaldırın | `yarn twenty app:uninstall` | İstemi atlamak için `--yes` ekleyin. |
| Bir tarball'ı sunucuya gönderin | `yarn twenty app:publish --private` | `package.json` içinde **kesin olarak daha yüksek** bir sürüm gerektirir — bkz. [Publishing](/l/tr/developers/extend/apps/operations/publishing). |
| Pazaryerine (npm) yayımlayın | `yarn twenty app:publish` | — |
| Dağıtılmış bir sürümü yükleyin / yükseltin | `yarn twenty app:install` | Şu anda dağıtılmış olan sürümü yükler. |
| Yerel sunucuyu silin ve temiz bir şekilde yeniden başlatın | `yarn twenty docker:reset` | Yerel verilerin **tamamını** siler — son çare. |
<Note>
`yarn twenty dev --once` ve `yarn twenty dev --once --dry-run`, `yarn twenty apply` ve `yarn twenty plan` için kullanımdan kaldırılmış takma adlar olsalar da hâlâ çalışırlar.
</Note>
### Yerel senkronizasyon için sürüm artırmaya gerek yoktur
Sıkı artan `version` kuralı (dağıtımda `VERSION_ALREADY_EXISTS`, yüklemede `APP_ALREADY_INSTALLED` / `CANNOT_DOWNGRADE_APPLICATION`) **`app:publish` / `app:install`** için — yani yayın yolu için — geçerlidir. `yarn twenty dev`, manifestinizi yerinde senkronize eder ve hiçbir zaman bir sürüm değişikliği gerektirmez, bu yüzden yineleme yapmak için `package.json` dosyasına dokunmanız gerekmez. Yerel bir değişikliği test etmek için kendinizi sürümü artırırken buluyorsanız, ihtiyacınız olan geliştirme döngüsü yerine yayın yolunu kullanıyorsunuz demektir.
## Senkronizasyon çıktısını okuma
Her senkronizasyon, uyguladığı (veya `--dry-run` ile uygulayacağı) üst veri değişikliklerini yazdırır:
Her senkronizasyon, uyguladığı (veya `plan` ile uygulayacağı) üst veri değişikliklerini, Terraform tarzında — varlık başına bir blok olacak şekilde, öznitelikleriyle birlikte ve ardından bir özet satırıyla yazdırır:
```text filename="Terminal"
Metadata changes: 2 created, 1 updated, 1 deleted
created objectMetadata rocket
created fieldMetadata timelineActivities
updated fieldMetadata launchedAt
deleted pageLayout legacyTab
✓ Synced
# objectMetadata "rocket" will be created
+ icon = "IconRocket"
+ labelSingular = "Rocket"
+ ...
# fieldMetadata "launchedAt" will be updated
~ isNullable = false -> true
Plan: 2 to add, 1 to change, 1 to destroy.
✓ Synced My App (4 files)
```
Bu, ilk tanı aracınızdır: tam olarak hangi nesnelerin, alanların ve düzenlerin değiştiğini size bildirir; böylece bir senkronizasyonun beklediğiniz gibi davranıp davranmadığını, arayüzü kontrol etmeden önce doğrulayabilirsiniz.
Yıkıcı değişiklikler (`to destroy`), neyi kaldırdıklarıyla birlikte listelenir (ör. `objectMetadata "auditNote" — drops the table and all its rows`) ve etkileşimli onay gerektirir ya da betiklerde `--force` kullanılmasını gerektirir.
Bir senkronizasyon tek bir varlıkta başarısız olduğunda, hata mesajı sorunlu varlığı ve onun `universalIdentifier` değerini adlandırır, örneğin:
```text
@@ -50,39 +61,42 @@ Migration action 'create' for 'fieldMetadata' (universalIdentifier: 2020...4337)
Bu tanımlayıcıyı, çakışanın hangisi olduğunu tahmin etmek yerine, manifestinizdeki (ve gerekirse çalışma alanındaki) varlığı bulmak için kullanın.
## Değişiklikleri önizleme (dry run)
## Değişiklikleri önizleme (plan)
`yarn twenty dev --once --dry-run`, manifestinizi derler, sunucudan geçiş planını ister ve onu yazdırır — **hiçbir şeyi uygulamadan**. Bu, ona taahhüt etmeden önce "Bu senkronizasyon neyi değiştirir?" sorusunu yanıtlamanın güvenli yoludur.
`yarn twenty plan`, manifestinizi derler, sunucudan geçiş planını ister ve onu — **hiçbir şeyi uygulamadan** — yazdırır. Bu, ona taahhüt etmeden önce "Bu senkronizasyon neyi değiştirir?" sorusunu yanıtlamanın güvenli yoludur.
```bash filename="Terminal"
yarn twenty dev --once --dry-run
yarn twenty plan
```
```text filename="Terminal"
Building manifest...
Computing metadata diff (dry run, nothing will be applied)...
Metadata changes: 1 created, 1 updated
created fieldMetadata timelineActivities
updated objectMetadata rocket
✓ Dry run complete for My App — no changes were applied
Computing metadata plan (read-only, nothing will be applied)...
# fieldMetadata "timelineActivities" will be created
+ ...
Plan: 1 to add, 1 to change, 0 to destroy.
✓ Plan complete for My App — no changes were applied
```
Bir dry run şunları yapar:
Bir plan:
* **Hiçbir şey yazmaz** — üst veri geçişi, uygulama kaydı güncellemesi, varsayılan rol/sekme değişiklikleri ve API istemcisi oluşturma işlemleri yapılmaz.
* Gerçek bir senkronizasyonun uygulayacağı **aynı farkı** döndürür; böylece oluşturulan/güncellenen/silinen varlıkları en baştan inceleyebilirsiniz.
* Riskli bir değişiklikten önce, bir yapay zekâ tarafından oluşturulan değişikliği gözden geçirirken veya beklenmedik bir değişiklik gerçekleşmek üzereyse betiğin başarısız olması gereken durumlarda kullanışlıdır.
<Note>
Bir dry run yalnızca **üst veri** değişikliklerini önizler ve uygulamanın en az bir kez senkronize edilmiş olmasını gerektirir (böylece çalışma alanı ondan haberdar olur). Hiç senkronize edilmemiş bir uygulamaya karşı çalıştırırsanız, sunucu uygulamanın yüklü olmadığını bildirir — önce bir kez `yarn twenty dev` çalıştırın.
Bir plan yalnızca **üst veri** değişikliklerini önizler ve uygulamanın en az bir kez senkronize edilmiş olmasını gerektirir (böylece çalışma alanı ondan haberdar olur). Hiç senkronize edilmemiş bir uygulamaya karşı çalıştırırsanız, sunucu uygulamanın yüklü olmadığını bildirir — önce bir kez `yarn twenty dev` çalıştırın.
</Note>
## Kurtarma merdiveni
Yerel üst veriler hatalı görünüyorsa, bu adımları sırayla uygulayın ve engeliniz kalkar kalkmaz durun. Her adım bir öncekinden daha yıkıcıdır.
1. **Yeniden senkronize edin.** `yarn twenty dev --once` komutunu tekrar çalıştırın. Senkronizasyonlar idempotenttir — temiz bir manifesti yeniden çalıştırmak güvenlidir ve çoğu zaman geçici bir aksaklığı giderir.
2. **Planı önizleyin.** Bir sonraki senkronizasyonun tam olarak neyi değiştirmeyi amaçladığını, uygulamadan görmek için `yarn twenty dev --once --dry-run` çalıştırın.
1. **Yeniden senkronize edin.** `yarn twenty apply` komutunu tekrar çalıştırın. Senkronizasyonlar idempotenttir — temiz bir manifesti yeniden çalıştırmak güvenlidir ve çoğu zaman geçici bir aksaklığı giderir.
2. **Planı önizleyin.** Bir sonraki senkronizasyonun tam olarak neyi değiştirmeyi amaçladığını, uygulamadan görmek için `yarn twenty plan` komutunu çalıştırın.
3. **Adlandırılmış hatayı okuyun.** Bir senkronizasyon başarısız olursa, iletideki üst veri türünü ve `universalIdentifier` değerini not alın (yukarıya bakın) ve manifestinizdeki o varlığı bulun. Bir çakışma genellikle yinelenen veya tekrar kullanılan bir tanımlayıcıya işaret eder.
4. **Kaldırın ve yeniden yükleyin.** `yarn twenty app:uninstall` komutunu çalıştırın, ardından yeniden senkronize edin (`yarn twenty dev`). Bu, uygulamanın üst verilerini temiz bir başlangıçtan yeniden oluşturur ve çalışma alanınızın geri kalanını olduğu gibi bırakır.
5. **Tam sıfırlama (son çare).** `yarn twenty docker:reset` komutunu çalıştırın, ardından yeniden tohumlayın ve yeniden senkronize edin.
@@ -78,6 +78,13 @@ Uygulamanızın kök dizininde bir `vitest.config.ts` oluşturun:
import tsconfigPaths from 'vite-tsconfig-paths';
import { defineConfig } from 'vitest/config';
const TWENTY_API_URL = process.env.TWENTY_API_URL ?? 'http://localhost:2020';
const TWENTY_API_KEY = process.env.TWENTY_API_KEY ?? '<the pre-seeded local dev key>';
// Make env vars available to globalSetup (test.env only applies to workers)
process.env.TWENTY_API_URL = TWENTY_API_URL;
process.env.TWENTY_API_KEY = TWENTY_API_KEY;
export default defineConfig({
plugins: [
tsconfigPaths({
@@ -88,66 +95,74 @@ export default defineConfig({
test: {
testTimeout: 120_000,
hookTimeout: 120_000,
fileParallelism: false,
include: ['src/**/*.integration-test.ts'],
setupFiles: ['src/__tests__/setup-test.ts'],
globalSetup: ['src/__tests__/global-setup.ts'],
env: {
TWENTY_API_URL: 'http://localhost:2020',
TWENTY_API_KEY: 'your-api-key',
TWENTY_API_URL,
TWENTY_API_KEY,
},
},
});
```
Testler çalışmadan önce sunucuya erişilebildiğini doğrulayan bir kurulum dosyası oluşturun:
Sunucunun erişilebilir olduğunu doğrulayan, SDK için bir test yapılandırması (`~/.twenty/config.test.json`) yazan ve testler çalışmadan önce uygulamayı eşitleyen genel bir kurulum dosyası oluşturun:
```ts src/__tests__/setup-test.ts
```ts src/__tests__/global-setup.ts
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import { beforeAll } from 'vitest';
const TWENTY_API_URL = process.env.TWENTY_API_URL ?? 'http://localhost:2020';
const TEST_CONFIG_DIR = path.join(os.tmpdir(), '.twenty-sdk-test');
import { appDevOnce, appUninstall } from 'twenty-sdk/cli';
const APP_PATH = process.cwd();
const CONFIG_DIR = path.join(os.homedir(), '.twenty');
export async function setup() {
const apiUrl = process.env.TWENTY_API_URL!;
const apiKey = process.env.TWENTY_API_KEY!;
beforeAll(async () => {
// Verify the server is running
const response = await fetch(`${TWENTY_API_URL}/healthz`);
const response = await fetch(`${apiUrl}/healthz`);
if (!response.ok) {
throw new Error(
`Twenty server is not reachable at ${TWENTY_API_URL}. ` +
'Start the server before running integration tests.',
);
throw new Error(`Twenty server is not reachable at ${apiUrl}.`);
}
// Write a temporary config for the SDK
fs.mkdirSync(TEST_CONFIG_DIR, { recursive: true });
// Write the SDK's test config (the CLI reads config.test.json when NODE_ENV=test)
fs.mkdirSync(CONFIG_DIR, { recursive: true });
fs.writeFileSync(
path.join(TEST_CONFIG_DIR, 'config.json'),
path.join(CONFIG_DIR, 'config.test.json'),
JSON.stringify({
remotes: {
local: {
apiUrl: process.env.TWENTY_API_URL,
apiKey: process.env.TWENTY_API_KEY,
},
},
remotes: { local: { apiUrl, apiKey } },
defaultRemote: 'local',
}, null, 2),
);
});
// Start from a clean slate, then sync the app
await appUninstall({ appPath: APP_PATH }).catch(() => {});
const result = await appDevOnce({ appPath: APP_PATH });
if (!result.success) {
throw new Error(`Dev sync failed: ${result.error?.message}`);
}
}
export async function teardown() {
await appUninstall({ appPath: APP_PATH });
}
```
## Programatik SDK API'leri
`twenty-sdk/cli` alt yolu, test kodundan doğrudan çağırabileceğiniz fonksiyonları dışa aktarır:
| Fonksiyon | Açıklama |
| -------------- | ----------------------------------------------------------------- |
| `appBuild` | Uygulamayı derleyin ve isteğe bağlı olarak bir tarball paketleyin |
| `appDeploy` | Bir tarball'ı sunucuya yükleyin |
| `appInstall` | Uygulamayı etkin çalışma alanına yükleyin |
| `appUninstall` | Uygulamayı etkin çalışma alanından kaldırın |
| Fonksiyon | Açıklama |
| -------------- | --------------------------------------------------------------------------- |
| `appBuild` | Uygulamayı derleyin ve isteğe bağlı olarak bir tarball paketleyin |
| `appDeploy` | Bir tarball'ı sunucuya yükleyin |
| `appDevOnce` | Uygulamayı bir kez oluşturun ve eşitleyin (`yarn twenty apply` ile aynıdır) |
| `appInstall` | Uygulamayı etkin çalışma alanına yükleyin |
| `appUninstall` | Uygulamayı etkin çalışma alanından kaldırın |
Her fonksiyon, `success: boolean` ile birlikte `data` veya `error` içeren bir sonuç nesnesi döndürür.
@@ -238,64 +253,10 @@ Ayrıca testleri çalıştırmadan uygulamanızda tip denetimi çalıştırabili
yarn twenty dev:typecheck
```
Bu, `tsc --noEmit` komutunu çalıştırır ve tüm tip hatalarını raporlar.
Bu, uygulamanızın `tsconfig.json` dosyasına karşı `tsc --noEmit` komutunu çalıştırır ve tüm tip hatalarını raporlar. İskelet olarak oluşturulan uygulamalar ayrıca test dosyalarını da kapsayan (`tsconfig.spec.json`) bir `yarn typecheck` betiği ile birlikte gelir.
## GitHub Actions ile CI
İskelet oluşturucu, `.github/workflows/ci.yml` konumunda kullanıma hazır bir GitHub Actions iş akışı üretir. Entegrasyon testlerinizi `main` dalına yapılan her itmede ve çekme isteklerinde otomatik olarak çalıştırır.
İskelet oluşturucu, `.github/workflows/ci.yml` konumunda kullanıma hazır bir iş akışı üretir. `main` dalına yapılan her itmede ve her çekme isteğinde, çalıştırıcı içinde geçici bir Twenty sunucusu başlatır (`twentyhq/twenty/.github/actions/spawn-twenty-app-dev-test` eylemi aracılığıyla) ve ardından `yarn lint`, `yarn typecheck`, `yarn test:unit` ve `yarn test` komutlarını, `TWENTY_API_URL` / `TWENTY_API_KEY` bu sunucuyu işaret edecek şekilde çalıştırır. Herhangi bir gizli bilgi gerekmez ve iş akışının en üstündeki `TWENTY_VERSION` ortam değişkeni aracılığıyla sunucu sürümünü sabitleyebilirsiniz.
İş akışı:
1. Kodunuzu çalışma alanına alır
2. `twentyhq/twenty/.github/actions/spawn-twenty-docker-image` eylemini kullanarak geçici bir Twenty sunucusu başlatır
3. `yarn install --immutable` ile bağımlılıkları kurar
4. Eylem çıktılarından enjekte edilen `TWENTY_API_URL` ve `TWENTY_API_KEY` ile `yarn test` çalıştırır
```yaml .github/workflows/ci.yml
name: CI
on:
push:
branches:
- main
pull_request: {}
env:
TWENTY_VERSION: latest
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Spawn Twenty instance
id: twenty
uses: twentyhq/twenty/.github/actions/spawn-twenty-docker-image@main
with:
twenty-version: ${{ env.TWENTY_VERSION }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Enable Corepack
run: corepack enable
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- name: Install dependencies
run: yarn install --immutable
- name: Run integration tests
run: yarn test
env:
TWENTY_API_URL: ${{ steps.twenty.outputs.server-url }}
TWENTY_API_KEY: ${{ steps.twenty.outputs.access-token }}
```
Herhangi bir gizli değişken yapılandırmanız gerekmez — `spawn-twenty-docker-image` eylemi, koşucu içinde doğrudan geçici bir Twenty sunucusu başlatır ve bağlantı ayrıntılarını çıktı olarak verir. `GITHUB_TOKEN` gizli değişkeni GitHub tarafından otomatik olarak sağlanır.
`latest` yerine belirli bir Twenty sürümünü sabitlemek için iş akışının başındaki `TWENTY_VERSION` ortam değişkenini değiştirin.
Hem iskelet iş akışlarının (`ci.yml` ve `cd.yml` dağıtım hattı) tam adım adım anlatımı için [Yayınlama → Otomatik CI/CD](/l/tr/developers/extend/apps/operations/publishing#automated-cicd-scaffolded-workflows) bölümüne bakın.
@@ -85,9 +85,11 @@ const GenerateDocumentForm = () => {
}, []);
const generate = async () => {
const apiBaseUrl = process.env.TWENTY_API_URL;
// Prefer the injected functions URL; fall back to the legacy /s prefix (self-hosted/local)
const functionsBaseUrl =
process.env.TWENTY_FUNCTIONS_URL || `${process.env.TWENTY_API_URL}/s`;
const token = process.env.TWENTY_APP_ACCESS_TOKEN ?? process.env.TWENTY_API_KEY;
const res = await fetch(`${apiBaseUrl}/s/documents/generate`, {
const res = await fetch(`${functionsBaseUrl}/documents/generate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
body: JSON.stringify({ templateId, recordId }),
@@ -168,7 +170,9 @@ const DocumentViewer = () => {
const recordId = useFrontComponentExecutionContext((c) => c.recordId ?? null);
// ...load { content, file } for recordId, then derive the links:
const pdfUrl = document.file?.[0]?.url;
const webUrl = `${process.env.TWENTY_API_URL ?? ''}/s/documents/view?id=${recordId}`;
const functionsBaseUrl =
process.env.TWENTY_FUNCTIONS_URL || `${process.env.TWENTY_API_URL ?? ''}/s`;
const webUrl = `${functionsBaseUrl}/documents/view?id=${recordId}`;
// Render the template body, plus quick links to the web page and the PDF.
// Links open in a new tab so they don't navigate the embedded component.
@@ -9,7 +9,12 @@ Aynı işleyici HTTP isteklerine de yanıt verebilir. İki rota ekleyeceğiz:
* belge oluşturmak için arayüzün çağırdığı bir **POST** uç noktası ve
* belgeyi yazdırılabilir bir web sayfası olarak oluşturan herkese açık bir **GET** uç noktası.
Her ikisi de `httpRouteTriggerSettings` kullanır. Uygulama rotaları Twenty sunucunuzda `/s` altında sunulur (ör. `http://localhost:2020/s/documents/generate`).
Her ikisi de `httpRouteTriggerSettings` kullanır. Yerel geliştirme sunucusunda, uygulama yönlendirmeleri `/s` öneki altında sunulur (örneğin, `http://localhost:2020/s/documents/generate`).
<Note>
Twenty Cloud üzerinde yönlendirmeler, çalışma alanına ayrılmış fonksiyon alan adında sunulur — Twenty'nin `/s` öneki olmadan `TWENTY_FUNCTIONS_URL` olarak eklediği URL'de. `/s` öneki orada kullanım dışıdır ve yalnızca kendi barındırılan ve yerel örneklerde kalmıştır.
[Mantık fonksiyonunu çağırma](/l/tr/developers/extend/apps/layout/front-components#calling-a-logic-function) bölümüne bakın.
</Note>
## POST rotası — istek üzerine oluşturma
@@ -69,10 +69,11 @@ CI ile aynı denetimleri çalıştırın:
yarn lint # oxlint
yarn typecheck # tsgo
yarn test:unit # unit tests
yarn twenty dev --once --dry-run # preview the metadata diff
yarn twenty plan # preview the metadata diff
```
Deneme çalıştırması, sunucuda neyin değişeceğini uygulamadan tam olarak gösterir — iyi bir son sağlama kontrolüdür. Bkz.
Plan, sunucuda neyin değişeceğini uygulamadan tam olarak gösterir —
iyi bir son sağlama kontrolüdür. Bkz.
[Testing](/l/tr/developers/extend/apps/operations/testing) ve
[Syncing & recovery](/l/tr/developers/extend/apps/operations/sync-and-recovery).