> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kazzle.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Otomasyonlar

> Kazzle uygulaması içinden işleri zamanla ve webhook'lara yanıt ver.

Otomasyonlar, bir uygulamanın kendi başına çalışan bölümleridir — bir zamanlamaya göre veya dış bir hizmet bir olay gönderdiğinde.

Bunları `kazzle.config.ts` dosyasında bir process bileşeni üzerinde tanımlarsınız. Bir bileşen ihtiyacınız kadar çok tetikleyiciye sahip olabilir.

## Yapı

```ts theme={"theme":"material-theme-darker"}
{
  name: 'events',
  type: 'process',
  path: './components/events/index.ts',
  processMode: 'persistent', // veya 'triggered'
  triggers: [
    { name: 'daily-digest', kind: 'schedule', schedule: '0 9 * * *', path: '/cron/daily-digest' },
    { name: 'stripe',       kind: 'webhook',                          path: '/webhook/stripe' },
  ],
}
```

Burada iki şey olup bitiyor:

* `processMode` **yaşam döngüsünü** seçer — uzun süre çalışan sunucu veya tetikleyici başına tek seferlik çalışma.
* `triggers[]` bu bileşeni tetiklemesi gereken **olayları** listeler.

İki parça bağımsızdır. Kalıcı bir sunucu cron'a sahip olabilir. Geçici bir işlem webhook'a sahip olabilir. İş yüküne uygun yaşam döngüsünü seçin, ardından istediğiniz kadar çok tetikleyici ekleyin.

## `processMode`

| Mod                       | Ne çalışır                                                        | Ne zaman kullanılır                                                                             |
| ------------------------- | ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `persistent` (varsayılan) | Uzun süre çalışan HTTP sunucusu. Tetikleyiciler buna POST edilir. | Bileşen zaten HTTP sunuyor veya bellekte durum tutuyor (kuyruklar, websocket'ler, önbellekler). |
| `triggered`               | Giriş betiği tetikleyici başına oluşturulur ve çıkar.             | Saf arka plan işleri — gece temizliği, tek Stripe webhook işleyicisi, vb. Boş sunucular yok.    |

## Tetikleyiciler

Her tetikleyicinin bir `name` (bileşen içinde benzersiz), bir `kind` ve — moda bağlı olarak — bir `schedule` ve/veya `path` vardır.

| Alan       | Ne zaman gerekli                      | Notlar                                                         |
| ---------- | ------------------------------------- | -------------------------------------------------------------- |
| `name`     | her zaman                             | Webhook URL segmentinde ve günlüklerde kullanılır. Kebab-case. |
| `kind`     | her zaman                             | `'schedule'` veya `'webhook'`.                                 |
| `schedule` | `kind: 'schedule'` olduğunda          | 5 alanlı cron ifadesi. Dakika çözünürlüğü minimum.             |
| `path`     | `processMode: 'persistent'` olduğunda | Tetikleyicinin iniş yaptığı sunucunuzda HTTP rotası.           |

## Kalıcı mod — sunucuya HTTP

Kalıcı bir bileşen için tetikleyici ateşlendiğinde, Kazzle belirtilen `path` adresinde sunucunuza POST yapar. İstek şunları taşır:

| Başlık                                           | Ne söyler                                 |
| ------------------------------------------------ | ----------------------------------------- |
| `Authorization: Bearer ${KAZZLE_TRIGGER_SECRET}` | Bunu doğrulayın. Eşleşmeyenleri reddedin. |
| `x-kazzle-trigger-name`                          | Manifestten tetikleyicinin `name` değeri. |
| `x-kazzle-trigger-run-id`                        | Günlük korelasyonu için opak kimlik.      |
| `x-kazzle-triggered-by`                          | `cron` \| `webhook` \| `manual`.          |

Webhook tetikleyicileri için orijinal istek gövdesi POST gövdesi olarak iletilir. Zamanlama tetikleyicileri için gövde boştur.

```ts theme={"theme":"material-theme-darker"}
// components/events/index.ts (kalıcı mod)
const TRIGGER_SECRET = process.env.KAZZLE_TRIGGER_SECRET ?? '';

Bun.serve({
  port: Number(process.env.PORT),
  hostname: process.env.HOST,
  async fetch(req) {
    const url = new URL(req.url);

    if (req.method === 'POST' && url.pathname === '/cron/daily-digest') {
      if (req.headers.get('authorization') !== `Bearer ${TRIGGER_SECRET}`) {
        return new Response('Unauthorized', { status: 401 });
      }
      await sendDigest();
      return Response.json({ ok: true });
    }

    if (req.method === 'POST' && url.pathname === '/webhook/stripe') {
      if (req.headers.get('authorization') !== `Bearer ${TRIGGER_SECRET}`) {
        return new Response('Unauthorized', { status: 401 });
      }
      const event = await req.json();
      await handleStripe(event);
      return Response.json({ ok: true });
    }

    return new Response('not found', { status: 404 });
  },
});
```

## Tetiklenen mod — tetikleyici başına tek seferlik

`triggered` bileşen için tetikleyici ateşlendiğinde, Kazzle giriş betiğini yeni oluşturur ve çıkmasını bekler. `path` yoktur; betik hangi tetikleyicinin ateşlendiğini ortam değişkenlerinden öğrenir.

| Ortam değişkeni   | Değer                                            |
| ----------------- | ------------------------------------------------ |
| `TRIGGER_NAME`    | Manifestten tetikleyicinin `name` değeri.        |
| `TRIGGERED_BY`    | `cron` \| `webhook` \| `manual`.                 |
| `RUN_ID`          | Günlük korelasyonu için opak kimlik.             |
| `WEBHOOK_PAYLOAD` | JSON gövdesi (yalnızca webhook tetikleyicileri). |

```ts theme={"theme":"material-theme-darker"}
// components/events/index.ts (tetiklenen mod)
const trigger = process.env.TRIGGER_NAME;
const runId = process.env.RUN_ID;

if (trigger === 'daily-digest') {
  await sendDigest();
} else if (trigger === 'stripe') {
  const event = JSON.parse(process.env.WEBHOOK_PAYLOAD ?? '{}');
  await handleStripe(event);
}

console.log(`run ${runId} done`);
```

Tetiklenen bileşenlerin üretimde boş makineleri yoktur — çağrı başına başlatılırlar ve çıkışta kapatılırlar.

## Webhook URL'leri

```text theme={"theme":"material-theme-darker"}
POST https://api.kazzle.app/webhooks/{spaceId}/{appId}/{componentName}/{triggerName}
```

`triggerName` segmenti o bileşenin `triggers[]` içinde bir `kind: 'webhook'` girişiyle eşleşmelidir. Bilinmeyen tetikleyici adları 404 döndürür.

## Zamanlama çözünürlüğü

Cron ifadeleri 5 alanlıdır (dakika, saat, ayın günü, ay, haftanın günü) ve dakika çözünürlüğü minimumdur. Dakika altı zamanlamalar manifest doğrulama sırasında reddedilir.

## Çalışmalar nasıl kaydedilir

Her tetikleyici ateşlemesi, `trigger_name`, `triggered_by`, `run_id` ve çalışmanın çıkış durumunu içeren bir `process_runs` satırı yazar. Bunları kendi kodunuzdan sorgulayabilir veya uygulamanın çalışmalar görünümünde inceleyebilirsiniz.

## Krediler tükenmek

Başarısız bir çalışma kaydedilir ve günlüğe alınır, ancak zamanlama normal temposuyla çalışmaya devam eder — hatalı bir çalışma tetikleyiciyi asla devre dışı bırakmaz. Bir çalışmayı durduran tek şey kredilerdir: her tetikleyici ateşlemesi alanın bakiyesine karşı kontrol edilir ve alan kredileri bittiğinde (veya faturalandırma ayarlanmadığında) çalışmalar `402` ile atlanır. Bu kendi kendini iyileştirir — zamanlama silahlı kalır ve bakiyeyi doldurduktan sonraki sonraki ateşleme normal şekilde çalışır, manuel devam etmeye gerek yoktur.

## Otomasyonları daha sonra ekleme

Basit bir uygulama tetikleyici olmadan başlayabilir ve daha sonra bunları kazanabilir — günlük bir özet ekleyin, Stripe'ı bağlayın, temizliği çalıştırın. Bileşenin yaşam döngüsü (`processMode`) ve tetikleyicileri (`triggers[]`) bağımsızdır, bu nedenle uygulamanın geri kalanını yeniden yazmadan bunları değiştirebilirsiniz.
