@palbase/backend 39.1.4 → 39.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/MIGRATION.md ADDED
@@ -0,0 +1,577 @@
1
+ # 39.0.0 — `raw(name, up, { down })` KALDIRILDI, `DBOps` bir üye kazandı
2
+
3
+ ## 1. `raw()` artık İKİ argüman alıyor
4
+
5
+ `down` seçeneği, hiç koşmayan bir down-migration'a besleniyordu: yazarına
6
+ sahip olmadığı bir teardown'a sahip olduğunu düşündürüyordu.
7
+
8
+ ```ts
9
+ // ÖNCE (39.0.0'da derlenmiyor)
10
+ raw("chk_positive", "ALTER TABLE orders ADD CONSTRAINT chk_positive CHECK (total > 0)", {
11
+ down: "ALTER TABLE orders DROP CONSTRAINT chk_positive",
12
+ });
13
+
14
+ // SONRA — düşürmeyi BİLDİRİN
15
+ dropConstraints: ["chk_positive"],
16
+ ```
17
+
18
+ Çoğu `raw()` bu majorda zaten gereksiz: tablo düzeyi çok sütunlu `foreignKeys`,
19
+ `index(n).unique().where(...)` (partial UNIQUE), tipli `check(name, expr)`,
20
+ koşullu FK (`freeze`), reddedici `guards`, bir kez koşan `backfills` ve
21
+ `dropConstraints` geldi. Önce bunlara bakın; `raw()` artık bir kaçış kapısı.
22
+
23
+ ## 2. `raw()` gövdeleri bir YETKİ kapısından geçiyor
24
+
25
+ Rol yaratan, sahiplik devreden, yetki dağıtan ya da `search_path` kaydıran
26
+ ifadeler **push'u reddediyor**. Açık kalan tek grant biçimi:
27
+
28
+ ```sql
29
+ GRANT EXECUTE ON FUNCTION … TO <platform rolü>
30
+ ```
31
+
32
+ Bu bir ALLOWLIST — kapı sınıflandıramadığını reddeder. Reddedilen bir gövdeyi
33
+ "geçici olarak" başka biçimde yazmaya çalışmayın; bildirimsel yüzeyi kullanın.
34
+
35
+ ## 3. Kendi `DBOps` uygulamanız varsa `lockRowsWhere` ekleyin
36
+
37
+ `DBOps` — ve onun üzerinden `DBClient`, `EnvServiceDatabase`, `EnvTypedDatabase` —
38
+ ZORUNLU bir `lockRowsWhere` üyesi kazandı. Yalnız kendi uygulamasını yazan
39
+ projeleri etkiler; SDK'nın kendi sınıflarını kullanıyorsanız yapacak bir şey yok.
40
+
41
+ `TableJSON.rawConstraints[]` elemanı da `down` alanını kaybetti — şema JSON'unu
42
+ elle okuyan bir aracınız varsa o alanı beklemeyin.
43
+
44
+ # 38.0.0 — `push` artık PLAN istiyor (ve `auth` göçü kendini onarıyor)
45
+
46
+ ## 1. `palbase plan` → `palbase push`, bu sırayla
47
+
48
+ `push` plansız koşmuyor. `palbase plan` yükseltmenin ne yapacağını modül modül
49
+ gösterir ve hedef sürümün her ön kontrolünü yazar; `push` o planı taşır.
50
+
51
+ ```bash
52
+ palbase plan # ne olacağını OKUYUN
53
+ palbase push # planı taşır
54
+ ```
55
+
56
+ Bundle, koşan SDK ya da şema planı siz planladıktan sonra kaydıysa push neyin
57
+ değiştiğini ADLANDIRIR ve yeni bir plan ister. Platform da aynı şeyi kontrol
58
+ eder, yani eski bir plan kaymış bir projeye karşı tekrar oynatılamaz.
59
+
60
+ > Planın nereye yazıldığı 0.62.x'te değişti: artık checkout'unuzda değil,
61
+ > `~/.palbase/checkouts/<hash>/plan.json` altında. Bu bir göç işi değil —
62
+ > eski `.palbase/plan.json` dosyanız varsa silin.
63
+
64
+ ## 2. Yükseltmeler TAKAStan ÖNCE göç ediyor
65
+
66
+ Bir proje daha yeni bir `@palbase/backend`'e geçtiğinde, o sürümün ihtiyaç
67
+ duyduğu göçler önce canlı veritabanına — yeni sürümün kendi migrator'ıyla —
68
+ uygulanır, ve ancak ondan sonra yeni sürüm devralır. Takas saniyeler süren bir
69
+ restart'tır; istekler düşmez, bekler. Göç koşamazsa **hiçbir şey değişmez**:
70
+ proje tam olduğu gibi servis etmeye devam eder.
71
+
72
+ Sizin yapacağınız bir şey yok. Yalnız bilin: `push` sonrası kısa bir restart
73
+ normaldir ve bir göç hatası artık projeyi yarıda bırakmaz.
74
+
75
+ ## 3. BREAKING — `auth` şeması, ve sizden bir şey İSTENMİYOR
76
+
77
+ `000014` sosyal-auth göçü, OAuth yapılandırılmış her projede düpedüz reddediyor
78
+ ve operatörden elle envanter çıkarıp sıfırlamasını istiyordu; red defteri kirli
79
+ bırakıyor ve stack'i açılamaz hâle getiriyordu. Bu davranış kaldırıldı.
80
+
81
+ # 37.0.0 — OAuth istemcileri PLATFORM BAŞINA yapılandırılıyor
82
+
83
+ ## 1. Sağlayıcı-geneli kimlik bilgisi yüzeyi KALDIRILDI
84
+
85
+ Web, iOS, macOS ve Android artık mevcut `oauth` yapılandırması ve `palbase link`
86
+ akışı üzerinden AYRI AYRI yapılandırılıyor. Tarayıcı kimlik bilgileri, native
87
+ client ID'leri, Google server client ID'leri, Apple Services ID'leri ve native
88
+ bundle ID'leri birbirinden ayrı kalır.
89
+
90
+ Eski sağlayıcı-geneli kimlik bilgisi ve token değişim arayüzleri kaldırıldı.
91
+
92
+ ## 2. Göç sırası ÖNEMLİ
93
+
94
+ ```
95
+ 1. backend SDK'yı ve istemci SDK'ları BİRLİKTE yükseltin
96
+ 2. `palbase link` ile bağlı yapılandırmanızı YENİDEN ÜRETİN
97
+ 3. ancak ondan sonra migration 000014
98
+ ```
99
+
100
+ Bu sıra bir öneri değil: SDK'lar 000014'ten önce yükseltilmezse OAuth kaydı
101
+ eski şekilde kalır. OAuth artık seçili-istemci işlemleri kullanıyor — katı
102
+ audience/issuer/nonce/redirect doğrulaması, kalıcı tamamlanma kanıtı, açık
103
+ kimlik bağlama ve MFA-farkında sonuçlar.
104
+
105
+ # 36.0.0 — `defineQuery` ve `defineWorkload` KALDIRILDI, dönüş tipi ÇIKARIMI geldi
106
+
107
+ ## 1. `Query.run(...)` → sıradan CRUD
108
+
109
+ `defineQuery`, sorgu manifestleri, hazırlanmış sorgu sarmalayıcıları,
110
+ `defineWorkload` ve atomic `workload`/`conflictKeys` seçenekleri kaldırıldı.
111
+ **Uyumluluk katmanı YOK.**
112
+
113
+ ```ts
114
+ // ÖNCE
115
+ const Query = defineQuery({ /* projeksiyon */ });
116
+ const rows = await Query.run(Database, input);
117
+
118
+ // SONRA — servis içinde sıradan tipli CRUD
119
+ const rows = await this.todos.findMany({ user_id: userId });
120
+ ```
121
+
122
+ Çakışma için: ilişkili işlemleri AYNI transaction handle'ında tutun ve
123
+ **sıralı** PostgreSQL satır kilitleri kullanın (`$lockRowsWhere`, 39.0.0).
124
+
125
+ ## 2. Controller dönüş anotasyonunu ÇIKARIN
126
+
127
+ JSON şekli çıkarılabiliyorsa controller'ın dönüş tipini yazmayın: build
128
+ doğrulayıcıyı ve istemci sözleşmesini kendisi türetir.
129
+
130
+ ```ts
131
+ // ÖNCE
132
+ async list(): Promise<TodoListSchema> { … }
133
+
134
+ // SONRA — tipli CRUD için anotasyonu OMIT edin
135
+ async list() { return this.todos.list(); }
136
+ ```
137
+
138
+ Açık ya da desteklenmeyen sözleşmeler için adlandırılmış Zod şeması yazmaya
139
+ devam edin (bilinmeyen JSON, özyinelemeli değerler, sınıflar). `any` kullanmayın.
140
+
141
+ > **CLI ve core dev runtime'ı BİRLİKTE yükseltin** — tip çıkarımı ikisinin
142
+ > aynı sürümde olmasını gerektiriyor.
143
+
144
+ ## 3. `workload` bildirimlerini silin
145
+
146
+ Veritabanı admission'ı artık istek CRUD'u, atomic transaction'lar, service-role
147
+ işlemleri ve zamanlanmış iş arasında PAYLAŞILIYOR ve operatör kuyruk ayarları
148
+ uygulama kodundan ayrı. Kuyruk/eşzamanlılık ayarı core'un işi.
149
+
150
+ # 35.0.0 — bildirim istemcisi WhatsApp üyesini ZORUNLU kılıyor
151
+
152
+ Backend bildirim istemcisi, diğer kanallarıyla tutarlı olarak WhatsApp üyesini
153
+ artık zorunlu taşıyor. `PalbaseNotificationsClient`'ın **kendi uygulamasını ya da
154
+ test adaptörünü yazan** projeler o üyeyi eklemeli.
155
+
156
+ Mevcut `send` imzaları DEĞİŞMEDİ. Bildirim mesajları ve tercihleri artık bir
157
+ teslim-kanalı tipi kullanıyor; Meta şablon çevirileri eski gövde-şablonu
158
+ API'sinden ayrı.
159
+
160
+ > Sağlayıcı bağlantı ayarları mesaj dili ya da şablon adı TAŞIMAZ — bunlar
161
+ > şablon kataloğuna ve her mesajın locale'ine aittir.
162
+
163
+ Üyenin zorunlu olması bilinçli: runtime bu istemciyi her zaman yaratır, ve
164
+ opsiyonel işaretlemek çağıranı SDK'nın zaten garanti ettiği bir yeteneği
165
+ test etmeye zorlardı.
166
+
167
+ # 34.0.0 — transaction SAHİPLİĞİ açık, timestamp'ler mikrosaniye
168
+
169
+ ## 1. Savepoint planında sıfırdan farklı retry REDDEDİLİYOR
170
+
171
+ `Database.$atomic(async tx => …)` BEGIN'den kalıcı COMMIT'e kadar sahiplenir:
172
+ karar okumaları, izolasyon ve doğrulanmış serialization/deadlock rollback'lerinin
173
+ sınırlı yeniden denemeleri dahil. Kaybolan bir COMMIT onayı bir kez raporlanır
174
+ ve yazma **asla otomatik tekrarlanmaz**.
175
+
176
+ ```ts
177
+ // ÖNCE — artık reddediliyor
178
+ await Database.$transaction(fn, { retries: 3 });
179
+
180
+ // SONRA
181
+ await Database.$atomic(async (tx) => { … });
182
+ ```
183
+
184
+ İstek yazmaları ve `$transaction` savepoint planları mevcut sınırlarını korur.
185
+ Eski retry sözünü tutmak, bayat bir snapshot'a karşı sessizce yeniden koşardı.
186
+
187
+ ## 2. Timestamp'ler ALTI ondalık basamak, UTC
188
+
189
+ Şema-farkında timestamp'ler PostgreSQL mikrosaniyelerini korur ve altı
190
+ ondalık basamaklı UTC string'leri döndürür.
191
+
192
+ ```
193
+ ÖNCE: 2026-09-11T18:25:27.193Z (üç basamak)
194
+ SONRA: 2026-09-11T18:25:27.193920Z (altı basamak)
195
+ ```
196
+
197
+ Timestamp string'lerini KARŞILAŞTIRAN ya da tam üç basamak BEKLEYEN tüketiciler
198
+ bu daha hassas biçimi kabul etmeli. Ham SQL sürücünün değer sözleşmesini korur.
199
+
200
+ To-one ilişkileri artık LIMIT'i doğru uyguluyor — `0` dahil.
201
+
202
+ ## 3. Kendi DB adaptörünüz varsa yeni üyeleri ekleyin
203
+
204
+ `DBOps`, `DBClient`, `TypedDB`, `TypedTable` ve üretilen ortam arayüzlerinin
205
+ kendi uygulamaları, yeni zorunlu sorgu, sayfalama, tekil arama, komut ve
206
+ tanılama üyelerini uygulamalı. Bunları opsiyonel döndürmek, SDK'yı yetenek
207
+ kontrolü olmadan kullanılamaz kılardı.
208
+
209
+ Pakete gömülü fake, PostgreSQL'e özgü garantileri AÇIKÇA reddeder.
210
+
211
+ ## 4. Sayısal kolonlar callback filtrelerinde METİN operatörlerini reddediyor
212
+
213
+ TypeScript'in excess-property açığı geçersiz SQL üretiyordu; kapandı.
214
+
215
+ # 33.0.0 — `Flags.$asService()` TİPTE de var (yayınlanmış bir kusurun düzeltmesi)
216
+
217
+ 32.0.0'da `Flags.$asService()` YAZILDI ama TÜKETİCİYE ULAŞMIYORDU: ambient
218
+ singleton ham istemcinin tipiyle (`PalbaseFlagsClient`) anote edilmişti ve o
219
+ annotation, `Object.assign`'ın kattığı `$asService`'i public tipten SİLİYORDU.
220
+
221
+ TS2551: Property '$asService' does not exist on type 'PalbaseFlagsClient'.
222
+ Did you mean 'asService'?
223
+
224
+ Derlenen tek yol (`asService()`) ise tasarım gereği FIRLATIYOR — yani
225
+ kullanıcılar arası flag yazma 32.0.0'da tamamen kapalıydı. Singleton artık
226
+ kendi tipini taşıyor (`PalbaseFlagsAmbient`), tıpkı `Database`'in
227
+ `EnvTypedDatabase` taşıması gibi. Kod değişikliği gerekmiyor; 33.0.0'a yükselin.
228
+
229
+ # 32.0.0 — kolon codec'leri ve `$` sözünün tutulması: göç notu
230
+
231
+ ## 1. `.transform<T>()` artık REDDEDİLİYOR — `.asNumber()` / `.asDecimal()` kullanın
232
+
233
+ ```ts
234
+ // ÖNCE — derleniyordu, ama üretilen tip YALAN SÖYLÜYORDU
235
+ amount: numeric().transform<number>({ fromDb: Number, toDb: String })
236
+
237
+ // SONRA
238
+ amount: numeric().asNumber()
239
+ ```
240
+
241
+ **Neden kaldırıldı:** `transform`'un hedef tipi (`<number>`) bir TİP
242
+ PARAMETRESİDİR ve çalışma zamanında YOKTUR. `palbase-env.d.ts`'i üreten adım
243
+ şemanın çalışma zamanı nesnesini okuyor, yani o tipi hiç öğrenemiyordu:
244
+ `bigint`/`numeric` koşulsuz `string` basılıyor, motor ise `fromDb`'yi uygulayıp
245
+ `number` döndürüyordu. Tip, çalışma zamanının yaptığının TERSİNİ söylüyordu — ve
246
+ sessizce. Bu, yanlış bir tipten daha kötüdür, çünkü görünmez.
247
+
248
+ Codec TİPLENMEK yerine ADLANDIRILIR: ad `_def`'e düşer, çalışma zamanı
249
+ nesnesiyle üretece ulaşır, ve hem dönüşüm hem yayılan TypeScript tipi ondan
250
+ türer. Tek bildirim, tek gerçek.
251
+
252
+ | Bildirilen | Üretilen tip | Çalışma zamanı |
253
+ |---|---|---|
254
+ | `numeric()` / `bigint()` | `string` | dokunulmaz |
255
+ | `.asNumber()` | `number` | `Number(v)` ↔ `String(v)` |
256
+ | `.asDecimal()` | `string` | `String(v)` (açıkça BİLDİRİLMİŞ) |
257
+
258
+ Yalnız `bigint()` ve `numeric()` üzerinde; başka bir kolon tipinde çağrılırsa
259
+ adıyla reddedilir. `.asNumber()` 2^53'ün üstünde hassasiyet kaybeder — o aralık
260
+ için `.asDecimal()`.
261
+
262
+ `palbase build` codec'siz bir `.transform<T>()` görürse tabloyu ve kolonu
263
+ adlandırarak reddeder; sessizce `string` basmaz.
264
+
265
+ ## 2. `Flags.asService()` → `Flags.$asService()`
266
+
267
+ ```ts
268
+ // ÖNCE
269
+ await Flags.asService().setOverrideForUser("u_9", "checkout", true);
270
+ // SONRA
271
+ await Flags.$asService().setOverrideForUser("u_9", "checkout", true);
272
+ ```
273
+
274
+ Sistem üyeleri `$` önekli (27.0.0 §3) ve `Database` bunu zaten yapıyordu;
275
+ `Flags`'in JSDoc'u "exactly like `Database.$asService()`" diye söz veriyordu ama
276
+ söz tutulmamıştı. Eski ad SESSİZCE çalışmaz: çağrılınca yeni adı söyleyerek
277
+ fırlatır.
278
+
279
+ Ham `PalbaseFlagsClient.asService()` DEĞİŞMEDİ — o bir iç seam ve singleton ona
280
+ forward eder.
281
+
282
+ ## 3. `fakeDatabase().db` artık TİPLİ yüzey — ham istemci `raw`'da
283
+
284
+ ```ts
285
+ // ÖNCE — db, çıplak DBClient'tı
286
+ const { db } = fakeDatabase();
287
+ await db.insert("todos", { id, title });
288
+
289
+ // SONRA — db, yazarın gerçekte kullandığı yüzey
290
+ const { db, raw } = fakeDatabase();
291
+ await db.$insert("todos", { id, title }); // ham op'lar `$` önekli
292
+ await db.public.todos.findMany({ where: … }); // tipli şema yüzeyi
293
+ ```
294
+
295
+ `db` artık üretimdeki `Database`'i kuran AYNI fonksiyonla kuruluyor, yani
296
+ sahtenin yüzeyi gerçeğinden ayrışamaz. Doğrudan `db.insert(...)` yazan çağrılar
297
+ `db.$insert(...)` olur.
298
+
299
+ **DAVRANIŞ da değişti:** eşleşmeyen bir `update` artık **`null`** döndürüyor —
300
+ motorun her zaman döndürdüğü şey. Sahte eskiden uydurma bir satır
301
+ (`{ id, ...applied }`) veriyor ve onu `updated()`'a da yazıyordu. Dönüşünü
302
+ kullanan bir tüketici testi artık `null` üzerinde `TypeError` alır; bildirilen
303
+ tip zaten `| null` olduğu için derleyici uyarmaz, o yüzden burada yazıyor.
304
+
305
+ Aynı sınıftan ikinci bir düzeltme: `updateMany(…, { returning: false })` artık
306
+ **sayı** döndürüyor (motor gibi), dizi değil. `const n = await updateMany(…,
307
+ { returning: false }); if (n === 0) throw` guard'ı sahtede HİÇ çalışmıyordu.
308
+ Ve `updateMany` yazdığını artık `updated()`'a kaydediyor.
309
+
310
+ **Ambient runtime'a `raw` verilir, `db` DEĞİL:**
311
+
312
+ ```ts
313
+ withServices({ Database: fake.raw }, () => …)
314
+ ```
315
+
316
+ `RuntimeServices.Database` ham istemcidir — ambient `Database` singleton'ı onu
317
+ SARAN şeydir. `db` verilirse yüzey iki kez sarılır ve her `$op` ıskalar.
318
+
319
+ ## 4. Değişken tablo adıyla `tx.public[t]` derlenmiyor (değişiklik değil, BELGE)
320
+
321
+ Bu bir 31.0.0 kırıcısı değil; hiç çalışmamış bir yüzeyin artık YAZILI olması.
322
+
323
+ ```
324
+ error TS2590: Expression produces a union type that is too complex to represent.
325
+ ```
326
+
327
+ **Ölçüldü:** yedi tabloya kadar temiz, **sekiz tabloda düşüyor** (12, 20, 26, 40
328
+ tabloda da). Sınırı belirleyen tablo sayısı ile tabloların birbirinden FARKLI
329
+ relation ad kümesi taşıması; **kolon sayısı ETKİLEMİYOR** (8 tablo × 2 kolon
330
+ düşüyor, 4 tablo × 200 kolon temiz), yani "kolonlarını azalt" bir çare değildir.
331
+
332
+ Sebep TypeScript'in kendi karmaşıklık tavanı: değişken bir anahtar, derleyiciyi
333
+ her tablonun `where` parametresini kesiştirmeye zorluyor.
334
+
335
+ **Çare:** tablo adını literal yazın —
336
+
337
+ ```ts
338
+ await Database.$transaction((tx) => [tx.public.payments.deleteWhere({ id })]);
339
+ ```
340
+
341
+ — ya da ad gerçekten çalışma zamanında belirleniyorsa ham op'ları kullanın
342
+ (`Database.$query`, `Database.$deleteMany`). Aynı sınırı Kysely v0.28'de
343
+ kaldırdı, Drizzle'da hiç olmadı.
344
+
345
+ # 25.1.0 → 27.x — modül + DI: GERİYE DÖNÜK göç notu
346
+
347
+ **26.0.0 npm'e HİÇ YAYINLANMADI.** Registry 25.1.0'dan sonra doğrudan 27.0.0'ı
348
+ gösterir. 26.0.0 git'te kesildi ama yayınlanmadığı için İÇERİĞİ 27.0.0 ile
349
+ birlikte indi — yani 25.1.0'dan yükselen bir proje TEK yükseltmede İKİ major'ın
350
+ kırıcılarını aldı, ve bunlardan biri hiç belgelenmemişti. Bu bölüm o eksiği
351
+ kapatıyor. Aşağıdakiler 27.0.0'ın veri erişim değişikliklerine EK'tir.
352
+
353
+ ## A. `controllers/` + `services/` → `modules/<alan>/`
354
+
355
+ Keşif artık dizin adından değil MODÜL bildiriminden. Her alan kendi klasöründe
356
+ bir `*.module.ts` taşır:
357
+
358
+ ```ts
359
+ @Module({
360
+ controllers: [NotesController as Token],
361
+ providers: [NoteService as Token, DbNoteRepo as Token],
362
+ exports: [], // bu modülün DIŞARIYA açtığı sınıflar
363
+ imports: [], // bu modülün ERİŞEBİLECEĞİ modüller
364
+ })
365
+ export class NotesModule {}
366
+ ```
367
+
368
+ Dört liste dört ayrı soruyu cevaplar: neyi SAHİPLENİYOR (`providers`), hangi
369
+ giriş noktalarını (`controllers`), kendi sınıflarından hangisine BAŞKASI
370
+ erişebilir (`exports`), kimin export'una BU erişebilir (`imports`).
371
+
372
+ **Hiçbir yerde listelenmemiş bir sınıf YOKTUR:** build onu adıyla reddeder ve
373
+ sınıf rota tablosuna, dispatcher'a ya da OpenAPI belgesine hiç ulaşmaz.
374
+
375
+ Kök modül YOKTUR ve mount edilecek bir yer de yoktur — sağlık probu bile
376
+ `modules/health/`, diğerleri gibi bir alan. Kuralın istisnası olmaması, "alan
377
+ eklemek" ile "klasör eklemek"i aynı şey yapan şeydir.
378
+
379
+ Bağımlılıklar KURUCUDAN gelir (`emitDecoratorMetadata` şart). Testte ikame
380
+ `isolated().with(Token, sahte)` ile yapılır.
381
+
382
+ > `tsconfig.json`'ın `include`'unu da kontrol edin: `controllers/`,
383
+ > `services/`, `models/` diye SAYAN bir liste `modules/` düzeninde HİÇBİR ŞEYLE
384
+ > eşleşmez, `tsc --noEmit` sıfır dosya derler ve **0 ile çıkar** — sessiz bir
385
+ > yeşil. Şablon artık tek bir `"**/*.ts"` kullanıyor.
386
+
387
+ ## B. `@Job` ve `@Webhook` artık `name` İSTİYOR — ve varsayılanı YOK
388
+
389
+ ```ts
390
+ @Job({ name: "nightly-rollup", schedule: "0 3 * * *" })
391
+ @Webhook({ name: "stripe-payments", secret: { env: "STRIPE_WEBHOOK_SECRET" } })
392
+ ```
393
+
394
+ > ⚠️ **DOSYASINI YENİDEN ADLANDIRAN BİR PROJE, CANLI WEBHOOK URL'İNİ SESSİZCE
395
+ > KAYBEDİYORDU.** Kimlik dosyanın YERİNDEN geldiği sürece
396
+ > `stripe.webhook.ts` → `payments.webhook.ts` yeniden adlandırması,
397
+ > gönderenin yapılandırdığı `/webhooks/stripe`'ı çözülemez hâle getiriyordu ve
398
+ > hiçbir şey bunu söylemiyordu. Aynı şey job'lar için de geçerliydi: dosya adı
399
+ > değişince scheduler BAŞKA bir job başlatıyordu.
400
+
401
+ Bu yüzden `name` zorunlu ve VARSAYILANSIZ: bir varsayılan, kimlik için İKİNCİ
402
+ bir kaynak olurdu. Eksik ya da boş `name` açılışta adıyla fırlatır. Şekil:
403
+ küçük harf, rakam ve tire (bir URL'e ve bir log satırına ulaşıyor).
404
+
405
+ **Yükselirken:** her `@Job`/`@Webhook`'a bugünkü DOSYA ADINDAN türeyen adı
406
+ yazın — böylece scheduler satırı ve webhook URL'i DEĞİŞMEZ. Adı sonradan
407
+ değiştirmek isterseniz bu, göndereni yeniden yapılandırmayı gerektiren ayrı bir
408
+ karardır.
409
+
410
+ # 27.0.0 — veri erişim yüzeyi: göç notu
411
+
412
+ Bu sürüm **yedi kırıcı değişiklik** taşıyor. Hepsi aynı sebepten: aynı iş için iki
413
+ uyumsuz kapı vardı (`Database.tables.x.findMany()` ve `Database.query()`),
414
+ aralarında geçiş yoktu, ve yetmediğinde geliştirici her şeyi bırakıp ham SQL'e
415
+ geçiyordu — orada tipi de RLS yardımını da kaybederek.
416
+
417
+ **Codemod yok, ve bu bilinçli.** Yedisi de DERLEME hatası veriyor: kırılma
418
+ sessiz değil, `tsc` size tam olarak nerede olduğunu söylüyor. Bir codemod'un
419
+ sessizce yanlış dönüştürdüğü bir çağrı, elle düzeltilen bir hatadan pahalıdır.
420
+
421
+ `deploy/fixture` bu notun uygulanabilir olduğunun kanıtı: 41 derleme hatasıyla
422
+ başladı, sıfırla bitti, ve tek satır susturma (`as never`) kalmadı.
423
+
424
+ ---
425
+
426
+ ## 1. `Database.tables.x` → `Database.public.x`
427
+
428
+ ```diff
429
+ - await Database.tables.todos.findMany(...)
430
+ + await Database.public.todos.findMany(...)
431
+ ```
432
+
433
+ `tables` ara katmanı kalktı. Şema adı artık YOLUN kendisi.
434
+
435
+ ## 2. `Database.schema("billing").tables.x` → `Database.billing.x`
436
+
437
+ ```diff
438
+ - await Database.schema("billing").tables.invoices.findMany(...)
439
+ + await Database.billing.invoices.findMany(...)
440
+ ```
441
+
442
+ Bildirilmemiş bir şema adı artık derleme hatası — eskiden çalışma zamanında
443
+ bulunuyordu.
444
+
445
+ ## 3. Sistem üyeleri `$` önekli
446
+
447
+ ```diff
448
+ - await Database.query("select 1")
449
+ - await Database.transaction(tx => ...)
450
+ - Database.asService()
451
+ + await Database.$query("select 1")
452
+ + await Database.$transaction(tx => ...)
453
+ + Database.$asService()
454
+ ```
455
+
456
+ **Neden:** `transactions` adlı bir tablo fintech'te neredeyse kaçınılmaz ve
457
+ `transaction` bir sistem üyesiydi. `$` öneki çakışmayı MATEMATİKSEL olarak
458
+ imkânsız kılıyor: şema doğrulayıcısı bir tablo adının `$` ile başlamasına izin
459
+ vermiyor.
460
+
461
+ Etkilenen üyeler: `$query`, `$transaction`, `$asService`, `$insert`, `$put`,
462
+ `$update`, `$delete`, `$findById`, `$findMany`, `$updateMany`, `$deleteMany`,
463
+ `$count`, `$search`, `$similar`, `$recommend`, `$facets`, `$supersede`,
464
+ `$attempt`, `$claim`, `$lockRows`, `$advisoryXactLock`.
465
+
466
+ ## 4. `$query` generic'siz `unknown[]` döndürür
467
+
468
+ ```diff
469
+ - const rows = await Database.$query("select count(*)::int as n from todos");
470
+ - rows[0].n // derleniyordu, doğrulanmıyordu
471
+ + const rows = await Database.$query<{ n: number }>("select count(*)::int as n from todos");
472
+ + rows[0].n // şekli SİZ söylediniz
473
+ ```
474
+
475
+ **Neden:** eski `Row[]` dönüşü BİLİNMEYENİ biliniyormuş gibi sunuyordu.
476
+ TypeScript bir SQL string'ini okuyamaz; `rows[0].n` derleniyordu ama `n` diye bir
477
+ alan olduğunu kimse doğrulamamıştı.
478
+
479
+ ## 5. `findMany(where, opts)` → `findMany({ where, ...opts })`
480
+
481
+ ```diff
482
+ - await Database.public.todos.findMany({ done: false }, { limit: 10 })
483
+ + await Database.public.todos.findMany({ where: { done: false }, limit: 10 })
484
+ ```
485
+
486
+ **Neden:** iki argümanlı biçimde `findMany({ limit: 10 })` yazmak sessizce
487
+ "limit adlı kolonu 10'a eşit satırlar" demekti. Tek obje bu belirsizliği
488
+ kaldırıyor. Aynı değişiklik `updateMany`, `deleteMany`, `count` için de geçerli.
489
+
490
+ ## 6. `upsert(data, { onConflict })` → `put({ data, onConflict })` — ya da `claim()`
491
+
492
+ ```diff
493
+ - await Database.public.settings.upsert({ user_id, theme }, { onConflict: ["user_id"] })
494
+ + await Database.public.settings.put({ data: { user_id, theme }, onConflict: ["user_id"] })
495
+ ```
496
+
497
+ **Ve idempotency istiyorsanız `put` DEĞİL `claim`:**
498
+
499
+ ```ts
500
+ const { inserted, row } = await Database.public.payments.claim(
501
+ { idem_key: req.headers["idempotency-key"] },
502
+ { amount, user_id },
503
+ );
504
+ if (!inserted) return row; // aynı istek ikinci kez geldi
505
+ ```
506
+
507
+ **Neden:** `upsert` tek isim altında iki niyet taşıyordu ve ikincisi için
508
+ ÖLÇÜLMÜŞ biçimde yanlıştı — `ON CONFLICT DO UPDATE` ikinci çağrının verisiyle
509
+ birincininkini EZİYOR (canlıda ölçüldü: 10.00 → 999.00).
510
+
511
+ `tx.tables.x.upsert()` de `put()` oldu; aynı iş için transaction içinde ve
512
+ dışında iki farklı yazım kalmasın diye.
513
+
514
+ ## 7. `indexes: [{name, columns}]` → `indexes: (c) => [index(name).on(...)]`
515
+
516
+ ```diff
517
+ - indexes: [{ name: "orders_status_idx", columns: ["status"] }]
518
+ + indexes: (c) => [index("orders_status_idx").on(c.col("status"))]
519
+ ```
520
+
521
+ **Ve aynı biçim `policies` için de:**
522
+
523
+ ```diff
524
+ - policies: [policy("own").using("owner = auth.uid()")]
525
+ + policies: (p) => [policy("own").using(p.col("owner").eq(p.auth.uid()))]
526
+ ```
527
+
528
+ **Neden:** kolon adları artık DERLEMEDE doğrulanıyor. Bir RLS politikasında
529
+ yanlış kolon adı yetki hatasıdır ve eskiden ancak deploy sırasında
530
+ `CREATE POLICY` çalışırken görülüyordu.
531
+
532
+ Callback olmasının sebebi teknik: index ve politika tablo tanımının İÇİNDE
533
+ bildiriliyor, yani `orders.status` yazmak mümkün değil — `orders` bağlaması o
534
+ noktada henüz kurulmamış oluyor. Kolon bağlamı callback'ten geliyor.
535
+
536
+ Ham string kaçış kapağı KALDI: `policy("x").using("<sql>")` çalışmaya devam
537
+ ediyor, ama orada kolon doğrulaması yok ve hata deploy anında geliyor.
538
+
539
+ ---
540
+
541
+ ## Yeni yüzey — kırıcı olmayanlar
542
+
543
+ Bunlar için bir şey yapmanız gerekmiyor; kademeler ham SQL'e düşmeden yukarı
544
+ çıkmanız için var.
545
+
546
+ | Ne | Ne zaman |
547
+ |---|---|
548
+ | `col("x")` | kolon-kolon karşılaştırma: `{ total: { gt: col("amount_paid") } }` |
549
+ | `increment(n)` / `decrement(n)` | sayaç: tek statement, lost update yok |
550
+ | `sqlFragment` | tipli filtre yetmediğinde — `select`/`orderBy`/`limit`/RLS çalışmaya devam eder |
551
+ | `select: [...]` | projeksiyon: dönüş tipi `Pick<Row, K>`'ye daralır |
552
+ | `OR` / `AND` / `NOT` | boolean bileşim |
553
+ | `contains` / `startsWith` / `isNull` | metin ve null operatörleri |
554
+ | `claim(unique, extra)` | idempotency anahtarı |
555
+ | `$lockRows(table, ids)` | deterministik kilit sırası — deadlock önler |
556
+ | `$advisoryXactLock(key)` | satırı olmayan iş için ad kilidi |
557
+ | `$transaction(fn, { retry })` | serileştirme hatasında yeniden dener |
558
+ | `appendOnly: true` | tabloda `update`/`delete`/`put`/`supersede` üyeleri TİPTE YOK, motor onları adıyla reddediyor, veritabanında REVOKE + RESTRICTIVE policy + BEFORE UPDATE/DELETE trigger |
559
+ | `counter()` | kolonun `increment()` ile güncellendiğini bildirir; plan HOT çakışmasını uyarır |
560
+ | `existsIn(table, row => …)` | üyelik tabanlı kiracılık — korelasyonlu EXISTS |
561
+ | `numeric().transform<T>()` | para tipini bir kez şemada tanımlayın |
562
+
563
+ ## Otomatik olan şeyler
564
+
565
+ Bunları siz istemeden sistem yapıyor; plan çıktısı hepsini gerekçesiyle gösterir.
566
+
567
+ - **FK kolonlarına index** — Postgres foreign key'i otomatik indekslemez ve bedeli
568
+ her JOIN'de, her `ON DELETE CASCADE`'de ödenir. `references(..., { index: false })`
569
+ ile kapatılır.
570
+ - **Politika filtre kolonuna index** — kiracı bunu kendi bulamaz: yazdığı sorgu
571
+ `WHERE status='open'`, yavaşlığın sebebi hiç yazmadığı `tenant_id` predikatı.
572
+ - **`auth.uid()` → `(SELECT auth.uid())`** — satır başına değil statement başına
573
+ bir kez. Ölçüldü: politikada satır-başına çalışan bir fonksiyonla
574
+ 71.958 ms → 10 ms.
575
+ - **`TO <rol>`** — her politikada, roller boşsa `TO PUBLIC`.
576
+ - **`CREATE INDEX CONCURRENTLY`** — var olan tabloya index eklemek yazmaları
577
+ bloklamaz; migration transaction'ının dışında koşar.
package/README.md CHANGED
@@ -1,23 +1,69 @@
1
1
  # @palbase/backend
2
2
 
3
- The backend SDK for Palbase. Write file-based TypeScript endpoints, schema,
4
- workers, jobs, hooks, and webhooks that run in the Palbase managed runtime.
3
+ The backend SDK for Palbase. Write TypeScript class controllers, services, and
4
+ schema that run in the Palbase managed runtime as a typed HTTP API — a
5
+ `@Module` says what exists, who owns it, and what it may reach; a class no
6
+ module lists does not exist.
5
7
 
6
8
  ```ts
7
- import { defineEndpoint, z, Database } from "@palbase/backend";
8
-
9
- export default defineEndpoint({
10
- method: "POST",
11
- input: z.object({ title: z.string() }),
12
- output: z.object({ id: z.string() }),
13
- handler: async (req) => Database.insert("todos", { title: req.input.title }),
14
- });
9
+ // modules/notes/dto/create.ts the request/response schemas, as a value + a type.
10
+ import { z } from "@palbase/backend";
11
+ export const CreateNoteBody = z.object({ body: z.string().min(1) });
12
+ export type CreateNoteBody = z.infer<typeof CreateNoteBody>;
13
+ export const NoteSchema = z.object({ id: z.string(), body: z.string() });
14
+ export type NoteSchema = z.infer<typeof NoteSchema>;
15
+ ```
16
+
17
+ ```ts
18
+ // modules/notes/note.service.ts — @Injectable() classes. The real work.
19
+ import { Database, Injectable } from "@palbase/backend";
20
+ import { NoteSchema } from "./dto/create";
21
+
22
+ @Injectable()
23
+ export class NoteService {
24
+ create(userId: string, body: string): Promise<NoteSchema> {
25
+ return Database.public.notes.insert({ user_id: userId, body });
26
+ }
27
+ }
28
+ ```
29
+
30
+ ```ts
31
+ // modules/notes/notes.controller.ts — @Controller class, no `Database` import.
32
+ import { Body, Controller, Post, User } from "@palbase/backend";
33
+ import type { UserT } from "@palbase/backend";
34
+ import { CreateNoteBody, NoteSchema } from "./dto/create";
35
+ import { NoteService } from "./note.service";
36
+
37
+ @Controller("/notes")
38
+ export class NotesController {
39
+ constructor(private readonly notes: NoteService) {}
40
+
41
+ @Post("")
42
+ create(@Body(CreateNoteBody) body: CreateNoteBody, @User() user: UserT): Promise<NoteSchema> {
43
+ return this.notes.create(user.id, body.body);
44
+ }
45
+ }
46
+ ```
47
+
48
+ ```ts
49
+ // modules/notes/notes.module.ts — lists them. Nothing is wired by hand.
50
+ import { Module, type Token } from "@palbase/backend";
51
+ import { NotesController } from "./notes.controller";
52
+ import { NoteService } from "./note.service";
53
+
54
+ @Module({
55
+ controllers: [NotesController as Token],
56
+ providers: [NoteService as Token],
57
+ })
58
+ export class NotesModule {}
15
59
  ```
16
60
 
17
61
  ## Documentation
18
62
 
19
63
  Start with [`docs/README.md`](./docs/README.md). For AI coding tools, a single
20
64
  concatenated corpus is generated at [`docs/llms-full.txt`](./docs/llms-full.txt).
65
+ See [`MIGRATION.md`](./MIGRATION.md) for breaking-change notes between major
66
+ versions.
21
67
 
22
68
  ## License
23
69
 
@@ -1,4 +1,4 @@
1
- export { o as AnyColumn, p as AtomicDatabase, q as AtomicOptions, y as ColumnBuilder, z as ColumnDef, F as ColumnMap, G as ColumnType, C as CommandOptions, D as DatabaseBudget, d as DatabaseDiagnostics, c as DatabaseDiagnosticsOptions, K as DatabaseQueryEvent, N as EXTENSION_DEPENDENCIES, O as EmbeddingModelRef, E as EnvServiceDatabase, V as EnvTypedDatabase, af as InsertManyOptions, ag as InsertShape, al as Materialized, as as OnDeleteAction, au as PALBASE_EXTENSIONS, P as Page, aw as PageInfo, ax as PageInput, ay as PageNavigation, b5 as PalbaseExtension, c8 as PolicyBuilder, c9 as PolicyCommand, ca as PolicyDef, cd as PolicyMode, cg as RawConstraintDef, f as RawPageOptions, ci as Ref, ck as RowShape, S as SchemaDef, ct as TABLE_META, cu as TableDef, cv as TableHandle, cw as TableInput, T as TransactionIsolation, cz as TxColumnExpr, cA as TxInsertShape, cC as TxNow, cD as TxPlan, g as TxPlanBody, cE as TxPlanError, cF as TxPlanHandle, cG as TxPlanOpResult, cH as TxPlanRejection, h as TxPlanResponse, cI as TxRefError, cJ as TxRow, cK as TxRows, cL as TxSelectOptions, cM as TxSetShape, cO as TxTable, cP as TxTables, cQ as TxWhere, cW as TypedDB, cX as TypedTable, cY as TypedTx, c$ as UniqueWhere, d9 as bigint, da as boolean, de as dec, dh as defineSchema, di as defineTable, dj as enumType, dp as inc, ds as installationRef, dt as integer, du as isPalbaseExtension, dw as jsonb, dx as makeTypedDB, dy as now, dC as openai, dD as ownedByUser, dE as policy, dF as raw, dH as text, dI as timestamp, dJ as userRef, dK as uuid, dL as vector } from '../index-pK2At5Yc.cjs';
1
+ export { o as AnyColumn, p as AtomicDatabase, q as AtomicOptions, y as ColumnBuilder, z as ColumnDef, F as ColumnMap, G as ColumnType, C as CommandOptions, D as DatabaseBudget, d as DatabaseDiagnostics, c as DatabaseDiagnosticsOptions, K as DatabaseQueryEvent, N as EXTENSION_DEPENDENCIES, O as EmbeddingModelRef, E as EnvServiceDatabase, V as EnvTypedDatabase, af as InsertManyOptions, ag as InsertShape, al as Materialized, as as OnDeleteAction, au as PALBASE_EXTENSIONS, P as Page, aw as PageInfo, ax as PageInput, ay as PageNavigation, b5 as PalbaseExtension, c8 as PolicyBuilder, c9 as PolicyCommand, ca as PolicyDef, cd as PolicyMode, cg as RawConstraintDef, f as RawPageOptions, ci as Ref, ck as RowShape, S as SchemaDef, ct as TABLE_META, cu as TableDef, cv as TableHandle, cw as TableInput, T as TransactionIsolation, cz as TxColumnExpr, cA as TxInsertShape, cC as TxNow, cD as TxPlan, g as TxPlanBody, cE as TxPlanError, cF as TxPlanHandle, cG as TxPlanOpResult, cH as TxPlanRejection, h as TxPlanResponse, cI as TxRefError, cJ as TxRow, cK as TxRows, cL as TxSelectOptions, cM as TxSetShape, cO as TxTable, cP as TxTables, cQ as TxWhere, cW as TypedDB, cX as TypedTable, cY as TypedTx, c$ as UniqueWhere, d9 as bigint, da as boolean, de as dec, dh as defineSchema, di as defineTable, dj as enumType, dp as inc, ds as installationRef, dt as integer, du as isPalbaseExtension, dw as jsonb, dx as makeTypedDB, dy as now, dC as openai, dD as ownedByUser, dE as policy, dF as raw, dH as text, dI as timestamp, dJ as userRef, dK as uuid, dL as vector } from '../index-CCY1h_J2.cjs';
2
2
  import 'zod';
3
3
  import './env.cjs';
4
4
  import '../stack.cjs';
@@ -1,4 +1,4 @@
1
- export { o as AnyColumn, p as AtomicDatabase, q as AtomicOptions, y as ColumnBuilder, z as ColumnDef, F as ColumnMap, G as ColumnType, C as CommandOptions, D as DatabaseBudget, d as DatabaseDiagnostics, c as DatabaseDiagnosticsOptions, K as DatabaseQueryEvent, N as EXTENSION_DEPENDENCIES, O as EmbeddingModelRef, E as EnvServiceDatabase, V as EnvTypedDatabase, af as InsertManyOptions, ag as InsertShape, al as Materialized, as as OnDeleteAction, au as PALBASE_EXTENSIONS, P as Page, aw as PageInfo, ax as PageInput, ay as PageNavigation, b5 as PalbaseExtension, c8 as PolicyBuilder, c9 as PolicyCommand, ca as PolicyDef, cd as PolicyMode, cg as RawConstraintDef, f as RawPageOptions, ci as Ref, ck as RowShape, S as SchemaDef, ct as TABLE_META, cu as TableDef, cv as TableHandle, cw as TableInput, T as TransactionIsolation, cz as TxColumnExpr, cA as TxInsertShape, cC as TxNow, cD as TxPlan, g as TxPlanBody, cE as TxPlanError, cF as TxPlanHandle, cG as TxPlanOpResult, cH as TxPlanRejection, h as TxPlanResponse, cI as TxRefError, cJ as TxRow, cK as TxRows, cL as TxSelectOptions, cM as TxSetShape, cO as TxTable, cP as TxTables, cQ as TxWhere, cW as TypedDB, cX as TypedTable, cY as TypedTx, c$ as UniqueWhere, d9 as bigint, da as boolean, de as dec, dh as defineSchema, di as defineTable, dj as enumType, dp as inc, ds as installationRef, dt as integer, du as isPalbaseExtension, dw as jsonb, dx as makeTypedDB, dy as now, dC as openai, dD as ownedByUser, dE as policy, dF as raw, dH as text, dI as timestamp, dJ as userRef, dK as uuid, dL as vector } from '../index-eN4KzGa5.js';
1
+ export { o as AnyColumn, p as AtomicDatabase, q as AtomicOptions, y as ColumnBuilder, z as ColumnDef, F as ColumnMap, G as ColumnType, C as CommandOptions, D as DatabaseBudget, d as DatabaseDiagnostics, c as DatabaseDiagnosticsOptions, K as DatabaseQueryEvent, N as EXTENSION_DEPENDENCIES, O as EmbeddingModelRef, E as EnvServiceDatabase, V as EnvTypedDatabase, af as InsertManyOptions, ag as InsertShape, al as Materialized, as as OnDeleteAction, au as PALBASE_EXTENSIONS, P as Page, aw as PageInfo, ax as PageInput, ay as PageNavigation, b5 as PalbaseExtension, c8 as PolicyBuilder, c9 as PolicyCommand, ca as PolicyDef, cd as PolicyMode, cg as RawConstraintDef, f as RawPageOptions, ci as Ref, ck as RowShape, S as SchemaDef, ct as TABLE_META, cu as TableDef, cv as TableHandle, cw as TableInput, T as TransactionIsolation, cz as TxColumnExpr, cA as TxInsertShape, cC as TxNow, cD as TxPlan, g as TxPlanBody, cE as TxPlanError, cF as TxPlanHandle, cG as TxPlanOpResult, cH as TxPlanRejection, h as TxPlanResponse, cI as TxRefError, cJ as TxRow, cK as TxRows, cL as TxSelectOptions, cM as TxSetShape, cO as TxTable, cP as TxTables, cQ as TxWhere, cW as TypedDB, cX as TypedTable, cY as TypedTx, c$ as UniqueWhere, d9 as bigint, da as boolean, de as dec, dh as defineSchema, di as defineTable, dj as enumType, dp as inc, ds as installationRef, dt as integer, du as isPalbaseExtension, dw as jsonb, dx as makeTypedDB, dy as now, dC as openai, dD as ownedByUser, dE as policy, dF as raw, dH as text, dI as timestamp, dJ as userRef, dK as uuid, dL as vector } from '../index-fLaf0PN2.js';
2
2
  import 'zod';
3
3
  import './env.js';
4
4
  import '../stack.js';
@@ -1,8 +1,8 @@
1
- import '../index-pK2At5Yc.cjs';
2
- export { A as App, g as AuthVerifier, B as BootRefused, h as COMMAND_EXECUTOR_DDL, j as CreateAppOptions, D as DECLARATION_REFUSAL, a as DeclarationRefused, E as EgressPolicy, k as EngineConfig, M as ModuleClients, R as RateLimiter, l as RequestDatabase, m as RouteEntry, n as RuntimeHooks, S as ScrubResult, o as SqlDriver, p as SqlTx, q as buildRouteTable, r as createApp, s as createLazyTransaction, t as createOps, u as createRequestDatabase, v as effectiveAuth, w as hostAllowed, x as installCommandExecutor, y as installEgressFence, i as isDeclarationRefused, z as loadConfig, F as makeMemoryCache, G as matchRoute, H as quoteIdent, I as scrubSecrets, J as setCursorKey, K as withQueryCancellation, L as withTables } from '../index-Brhp8cxj.cjs';
1
+ import '../index-CCY1h_J2.cjs';
2
+ export { A as App, g as AuthVerifier, B as BootRefused, h as COMMAND_EXECUTOR_DDL, j as CreateAppOptions, D as DECLARATION_REFUSAL, a as DeclarationRefused, E as EgressPolicy, k as EngineConfig, M as ModuleClients, R as RateLimiter, l as RequestDatabase, m as RouteEntry, n as RuntimeHooks, S as ScrubResult, o as SqlDriver, p as SqlTx, q as buildRouteTable, r as createApp, s as createLazyTransaction, t as createOps, u as createRequestDatabase, v as effectiveAuth, w as hostAllowed, x as installCommandExecutor, y as installEgressFence, i as isDeclarationRefused, z as loadConfig, F as makeMemoryCache, G as matchRoute, H as quoteIdent, I as scrubSecrets, J as setCursorKey, K as withQueryCancellation, L as withTables } from '../index-Db5QHdTa.cjs';
3
3
  import 'zod';
4
4
  import '../db/env.cjs';
5
5
  import '../stack.cjs';
6
6
  import 'node:async_hooks';
7
7
  import '../module-Dl1KFVtc.cjs';
8
- import '../registry-9dNeVN5d.cjs';
8
+ import '../registry-CH6HRR6T.cjs';
@@ -1,8 +1,8 @@
1
- import '../index-eN4KzGa5.js';
2
- export { A as App, g as AuthVerifier, B as BootRefused, h as COMMAND_EXECUTOR_DDL, j as CreateAppOptions, D as DECLARATION_REFUSAL, a as DeclarationRefused, E as EgressPolicy, k as EngineConfig, M as ModuleClients, R as RateLimiter, l as RequestDatabase, m as RouteEntry, n as RuntimeHooks, S as ScrubResult, o as SqlDriver, p as SqlTx, q as buildRouteTable, r as createApp, s as createLazyTransaction, t as createOps, u as createRequestDatabase, v as effectiveAuth, w as hostAllowed, x as installCommandExecutor, y as installEgressFence, i as isDeclarationRefused, z as loadConfig, F as makeMemoryCache, G as matchRoute, H as quoteIdent, I as scrubSecrets, J as setCursorKey, K as withQueryCancellation, L as withTables } from '../index-Dlu2b9-f.js';
1
+ import '../index-fLaf0PN2.js';
2
+ export { A as App, g as AuthVerifier, B as BootRefused, h as COMMAND_EXECUTOR_DDL, j as CreateAppOptions, D as DECLARATION_REFUSAL, a as DeclarationRefused, E as EgressPolicy, k as EngineConfig, M as ModuleClients, R as RateLimiter, l as RequestDatabase, m as RouteEntry, n as RuntimeHooks, S as ScrubResult, o as SqlDriver, p as SqlTx, q as buildRouteTable, r as createApp, s as createLazyTransaction, t as createOps, u as createRequestDatabase, v as effectiveAuth, w as hostAllowed, x as installCommandExecutor, y as installEgressFence, i as isDeclarationRefused, z as loadConfig, F as makeMemoryCache, G as matchRoute, H as quoteIdent, I as scrubSecrets, J as setCursorKey, K as withQueryCancellation, L as withTables } from '../index-QWN1Ncrv.js';
3
3
  import 'zod';
4
4
  import '../db/env.js';
5
5
  import '../stack.js';
6
6
  import 'node:async_hooks';
7
7
  import '../module-Dl1KFVtc.js';
8
- import '../registry-B8ddZiMY.js';
8
+ import '../registry-C7tCRyPm.js';
@@ -2238,9 +2238,9 @@ interface PalbaseEmailSendParams {
2238
2238
  templateSlug?: string;
2239
2239
  /**
2240
2240
  * Which locale of `templateSlug` to render — a BCP47 short tag ("tr").
2241
- * Falls back to "en" when the slug has no row for it. Declaring a locale in
2242
- * config/notifications.ts is only half the feature: without this the extra
2243
- * rows exist and are unreachable.
2241
+ * Falls back to "en" when the slug has no row for it. Declaring a locale
2242
+ * with `palbase notifications templates set` is only half the feature:
2243
+ * without this the extra rows exist and are unreachable.
2244
2244
  */
2245
2245
  locale?: string;
2246
2246
  variables?: Record<string, unknown>;
@@ -1,6 +1,6 @@
1
- import { c as DatabaseDiagnosticsOptions, d as DatabaseDiagnostics, a as DBClient, T as TransactionIsolation, e as DBOps, f as RawPageOptions, P as Page, g as TxPlanBody, C as CommandOptions, h as TxPlanResponse, A as AuthSpec, i as CacheClient, b as RuntimeServices, _ as __runWithRuntime, j as __requestALS } from './index-pK2At5Yc.cjs';
1
+ import { c as DatabaseDiagnosticsOptions, d as DatabaseDiagnostics, a as DBClient, T as TransactionIsolation, e as DBOps, f as RawPageOptions, P as Page, g as TxPlanBody, C as CommandOptions, h as TxPlanResponse, A as AuthSpec, i as CacheClient, b as RuntimeServices, _ as __runWithRuntime, j as __requestALS } from './index-CCY1h_J2.cjs';
2
2
  import { T as Token } from './module-Dl1KFVtc.cjs';
3
- import { R as RouteMeta } from './registry-9dNeVN5d.cjs';
3
+ import { R as RouteMeta } from './registry-CH6HRR6T.cjs';
4
4
 
5
5
  interface AdmissionLease {
6
6
  queueMs: number;
@@ -1,6 +1,6 @@
1
- import { c as DatabaseDiagnosticsOptions, d as DatabaseDiagnostics, a as DBClient, T as TransactionIsolation, e as DBOps, f as RawPageOptions, P as Page, g as TxPlanBody, C as CommandOptions, h as TxPlanResponse, A as AuthSpec, i as CacheClient, b as RuntimeServices, _ as __runWithRuntime, j as __requestALS } from './index-eN4KzGa5.js';
1
+ import { c as DatabaseDiagnosticsOptions, d as DatabaseDiagnostics, a as DBClient, T as TransactionIsolation, e as DBOps, f as RawPageOptions, P as Page, g as TxPlanBody, C as CommandOptions, h as TxPlanResponse, A as AuthSpec, i as CacheClient, b as RuntimeServices, _ as __runWithRuntime, j as __requestALS } from './index-fLaf0PN2.js';
2
2
  import { T as Token } from './module-Dl1KFVtc.js';
3
- import { R as RouteMeta } from './registry-B8ddZiMY.js';
3
+ import { R as RouteMeta } from './registry-C7tCRyPm.js';
4
4
 
5
5
  interface AdmissionLease {
6
6
  queueMs: number;
@@ -2238,9 +2238,9 @@ interface PalbaseEmailSendParams {
2238
2238
  templateSlug?: string;
2239
2239
  /**
2240
2240
  * Which locale of `templateSlug` to render — a BCP47 short tag ("tr").
2241
- * Falls back to "en" when the slug has no row for it. Declaring a locale in
2242
- * config/notifications.ts is only half the feature: without this the extra
2243
- * rows exist and are unreachable.
2241
+ * Falls back to "en" when the slug has no row for it. Declaring a locale
2242
+ * with `palbase notifications templates set` is only half the feature:
2243
+ * without this the extra rows exist and are unreachable.
2244
2244
  */
2245
2245
  locale?: string;
2246
2246
  variables?: Record<string, unknown>;
package/dist/index.d.cts CHANGED
@@ -1,11 +1,11 @@
1
- import { k as PalbaseResult, l as PolicyExpr, S as SchemaDef, A as AuthSpec, H as HttpError } from './index-pK2At5Yc.cjs';
2
- export { m as AggregateInput, n as AggregateResult, o as AnyColumn, p as AtomicDatabase, q as AtomicOptions, r as Auth, s as AuthConfig, B as BackfillDef, t as BadRequest, u as Cache, i as CacheClient, v as CheckDef, w as ClientInfo, x as ColRef, y as ColumnBuilder, z as ColumnDef, F as ColumnMap, G as ColumnType, C as CommandOptions, I as Conflict, a as DBClient, e as DBOps, J as Database, D as DatabaseBudget, d as DatabaseDiagnostics, c as DatabaseDiagnosticsOptions, K as DatabaseQueryEvent, L as DeadlockDetected, M as Documents, N as EXTENSION_DEPENDENCIES, O as EmbeddingModelRef, Q as EnvSchemas, E as EnvServiceDatabase, U as EnvTables, V as EnvTypedDatabase, W as EnvTypedTable, X as ErrorDef, Y as ErrorMap, Z as ErrorThrowers, $ as FileContext, a0 as FindManyOpts, a1 as FkAction, a2 as FkMatch, a3 as Flags, a4 as Forbidden, a5 as ForeignKeyBuilder, a6 as ForeignKeyDef, a7 as FreezeBuilder, a8 as FreezeDef, a9 as GuardBuilder, aa as GuardDef, ab as GuardEvent, ac as HttpMethod, ad as IndexBuilder, ae as IndexDef, af as InsertManyOptions, ag as InsertShape, ah as InsertValues, ai as LifecycleHook, aj as Log, ak as Logger, al as Materialized, am as Middleware, an as MiddlewareContext, ao as MiddlewareHandler, ap as MutateInput, aq as NotFound, ar as Notifications, as as OnDeleteAction, at as OrderBySpec, au as PALBASE_EXTENSIONS, av as PBRequest, P as Page, aw as PageInfo, ax as PageInput, ay as PageNavigation, az as PalError, aA as PalbaseAnalyticsClient, aB as PalbaseAnalyticsManagementNamespace, aC as PalbaseAnalyticsProperties, aD as PalbaseAnalyticsQueryNamespace, aE as PalbaseAttestAndroidParams, aF as PalbaseAttestAndroidResult, aG as PalbaseAttestiOSParams, aH as PalbaseAttestiOSResult, aI as PalbaseAuthAdminClient, aJ as PalbaseAuthClient, aK as PalbaseBatchOverrideOperation, aL as PalbaseBatchSetOverridesResult, aM as PalbaseBindDeviceParams, aN as PalbaseBucketClient, aO as PalbaseClearAllOverridesResult, aP as PalbaseClearOverrideResult, aQ as PalbaseCohortQueryInput, aR as PalbaseCohortResult, aS as PalbaseCollectionRef, aT as PalbaseCountQueryInput, aU as PalbaseCountResult, aV as PalbaseCreateLinkParams, aW as PalbaseDeviceInfo, aX as PalbaseDeviceTokenView, aY as PalbaseDocsClient, aZ as PalbaseDocumentRef, a_ as PalbaseDocumentSnapshot, a$ as PalbaseEmailClient, b0 as PalbaseEmailSendParams, b1 as PalbaseEmailSendResponse, b2 as PalbaseEventNamesResult, b3 as PalbaseEventsQueryInput, b4 as PalbaseEventsResult, b5 as PalbaseExtension, b6 as PalbaseFileObject, b7 as PalbaseFlag, b8 as PalbaseFlagContext, b9 as PalbaseFlagSource, ba as PalbaseFlagValue, bb as PalbaseFlagVariant, bc as PalbaseFlagsClient, bd as PalbaseFlagsServiceClient, be as PalbaseFunctionsClient, bf as PalbaseFunnelQueryInput, bg as PalbaseFunnelResult, bh as PalbaseIdentifyTraits, bi as PalbaseInboxClient, bj as PalbaseInboxListOptions, bk as PalbaseInboxListResult, bl as PalbaseInboxMessage, bm as PalbaseInboxSendParams, bn as PalbaseInboxSendResponse, bo as PalbaseInitialLink, bp as PalbaseInvokeOptions, bq as PalbaseLink, br as PalbaseLinkAnalytics, bs as PalbaseLinkDetails, bt as PalbaseLinksClient, bu as PalbaseListLinksOptions, bv as PalbaseListLinksResult, bw as PalbaseListOptions, bx as PalbaseMatchParams, by as PalbaseMultiChannelResponse, bz as PalbaseNotificationChannel, bA as PalbaseNotificationsClient, bB as PalbaseOverviewResult, bC as PalbasePreferences, bD as PalbasePreferencesClient, bE as PalbasePushClient, bF as PalbasePushSendParams, bG as PalbasePushSendResponse, bH as PalbaseQrCodeOptions, bI as PalbaseQuerySnapshot, bJ as PalbaseRealtimeClient, bK as PalbaseRegisterDeviceParams, bL as PalbaseRetentionQueryInput, bM as PalbaseRetentionResult, bN as PalbaseSession, bO as PalbaseSetOverrideResult, bP as PalbaseSetOverridesResult, bQ as PalbaseSignedUrlResponse, bR as PalbaseSmsClient, bS as PalbaseSmsSendParams, bT as PalbaseSmsSendResponse, bU as PalbaseStorageClient, bV as PalbaseTransformOptions, bW as PalbaseUpdateLinkParams, bX as PalbaseUploadOptions, bY as PalbaseUser, bZ as PalbaseUserDetailResult, b_ as PalbaseUsersQueryInput, b$ as PalbaseUsersResult, c0 as PalbaseVerifyRequestSignatureParams, c1 as PalbaseWhatsAppClient, c2 as PalbaseWhatsAppEvent, c3 as PalbaseWhatsAppSendParams, c4 as PalbaseWhatsAppSendResponse, c5 as PalbaseWhatsAppTemplate, c6 as PalbaseWhereOperator, c7 as PolicyBinOp, c8 as PolicyBuilder, c9 as PolicyCommand, ca as PolicyDef, cb as PolicyExprCtx, cc as PolicyExprRef, cd as PolicyMode, ce as PolicyOperand, cf as QueryInput, R as RateLimitConfig, cg as RawConstraintDef, f as RawPageOptions, ch as Realtime, ci as Ref, cj as RequestStore, ck as RowShape, b as RuntimeServices, cl as Secrets, cm as SecretsService, cn as SerializationFailure, co as SetShape, cp as SetValue, cq as ShutdownRunner, cr as SqlFragment, cs as Storage, ct as TABLE_META, cu as TableDef, cv as TableHandle, cw as TableInput, cx as TableRef, cy as TooManyRequests, T as TransactionIsolation, cz as TxColumnExpr, cA as TxInsertShape, cB as TxInsertValue, cC as TxNow, cD as TxPlan, g as TxPlanBody, cE as TxPlanError, cF as TxPlanHandle, cG as TxPlanOpResult, cH as TxPlanRejection, h as TxPlanResponse, cI as TxRefError, cJ as TxRow, cK as TxRows, cL as TxSelectOptions, cM as TxSetShape, cN as TxSetValue, cO as TxTable, cP as TxTables, cQ as TxWhere, cR as TxWireExpr, cS as TxWireGuard, cT as TxWireOp, cU as TxWireRef, cV as TxWireValue, cW as TypedDB, cX as TypedTable, cY as TypedTx, cZ as Unauthorized, c_ as UniqueViolation, c$ as UniqueWhere, d0 as UserT, d1 as VerifiedDevice, d2 as WhereFilter, d3 as WhereOp, d4 as __getRuntime, j as __requestALS, d5 as __resetLifecycleHooks, d6 as __runStartHooks, _ as __runWithRuntime, d7 as __setRuntime, d8 as backfill, d9 as bigint, da as boolean, db as can, dc as check, dd as col, de as dec, df as decrement, dg as defineMiddleware, dh as defineSchema, di as defineTable, dj as enumType, dk as exprCtx, dl as foreignKey, dm as freeze, dn as guard, dp as inc, dq as increment, dr as index, ds as installationRef, dt as integer, du as isPalbaseExtension, dv as isRetryable, dw as jsonb, dx as makeTypedDB, dy as now, dz as numeric, dA as onShutdown, dB as onStart, dC as openai, dD as ownedByUser, dE as policy, dF as raw, dG as sqlFragment, dH as text, dI as timestamp, dJ as userRef, dK as uuid, dL as vector, dM as withRetry } from './index-pK2At5Yc.cjs';
3
- import { M as ModuleClients, C as Container } from './index-Brhp8cxj.cjs';
4
- export { D as DECLARATION_REFUSAL, a as DeclarationRefused, b as DiError, c as DiKind, d as ModulePressure, e as assertNoOrphanEntryPoints, f as buildContainer, i as isDeclarationRefused } from './index-Brhp8cxj.cjs';
1
+ import { k as PalbaseResult, l as PolicyExpr, S as SchemaDef, A as AuthSpec, H as HttpError } from './index-CCY1h_J2.cjs';
2
+ export { m as AggregateInput, n as AggregateResult, o as AnyColumn, p as AtomicDatabase, q as AtomicOptions, r as Auth, s as AuthConfig, B as BackfillDef, t as BadRequest, u as Cache, i as CacheClient, v as CheckDef, w as ClientInfo, x as ColRef, y as ColumnBuilder, z as ColumnDef, F as ColumnMap, G as ColumnType, C as CommandOptions, I as Conflict, a as DBClient, e as DBOps, J as Database, D as DatabaseBudget, d as DatabaseDiagnostics, c as DatabaseDiagnosticsOptions, K as DatabaseQueryEvent, L as DeadlockDetected, M as Documents, N as EXTENSION_DEPENDENCIES, O as EmbeddingModelRef, Q as EnvSchemas, E as EnvServiceDatabase, U as EnvTables, V as EnvTypedDatabase, W as EnvTypedTable, X as ErrorDef, Y as ErrorMap, Z as ErrorThrowers, $ as FileContext, a0 as FindManyOpts, a1 as FkAction, a2 as FkMatch, a3 as Flags, a4 as Forbidden, a5 as ForeignKeyBuilder, a6 as ForeignKeyDef, a7 as FreezeBuilder, a8 as FreezeDef, a9 as GuardBuilder, aa as GuardDef, ab as GuardEvent, ac as HttpMethod, ad as IndexBuilder, ae as IndexDef, af as InsertManyOptions, ag as InsertShape, ah as InsertValues, ai as LifecycleHook, aj as Log, ak as Logger, al as Materialized, am as Middleware, an as MiddlewareContext, ao as MiddlewareHandler, ap as MutateInput, aq as NotFound, ar as Notifications, as as OnDeleteAction, at as OrderBySpec, au as PALBASE_EXTENSIONS, av as PBRequest, P as Page, aw as PageInfo, ax as PageInput, ay as PageNavigation, az as PalError, aA as PalbaseAnalyticsClient, aB as PalbaseAnalyticsManagementNamespace, aC as PalbaseAnalyticsProperties, aD as PalbaseAnalyticsQueryNamespace, aE as PalbaseAttestAndroidParams, aF as PalbaseAttestAndroidResult, aG as PalbaseAttestiOSParams, aH as PalbaseAttestiOSResult, aI as PalbaseAuthAdminClient, aJ as PalbaseAuthClient, aK as PalbaseBatchOverrideOperation, aL as PalbaseBatchSetOverridesResult, aM as PalbaseBindDeviceParams, aN as PalbaseBucketClient, aO as PalbaseClearAllOverridesResult, aP as PalbaseClearOverrideResult, aQ as PalbaseCohortQueryInput, aR as PalbaseCohortResult, aS as PalbaseCollectionRef, aT as PalbaseCountQueryInput, aU as PalbaseCountResult, aV as PalbaseCreateLinkParams, aW as PalbaseDeviceInfo, aX as PalbaseDeviceTokenView, aY as PalbaseDocsClient, aZ as PalbaseDocumentRef, a_ as PalbaseDocumentSnapshot, a$ as PalbaseEmailClient, b0 as PalbaseEmailSendParams, b1 as PalbaseEmailSendResponse, b2 as PalbaseEventNamesResult, b3 as PalbaseEventsQueryInput, b4 as PalbaseEventsResult, b5 as PalbaseExtension, b6 as PalbaseFileObject, b7 as PalbaseFlag, b8 as PalbaseFlagContext, b9 as PalbaseFlagSource, ba as PalbaseFlagValue, bb as PalbaseFlagVariant, bc as PalbaseFlagsClient, bd as PalbaseFlagsServiceClient, be as PalbaseFunctionsClient, bf as PalbaseFunnelQueryInput, bg as PalbaseFunnelResult, bh as PalbaseIdentifyTraits, bi as PalbaseInboxClient, bj as PalbaseInboxListOptions, bk as PalbaseInboxListResult, bl as PalbaseInboxMessage, bm as PalbaseInboxSendParams, bn as PalbaseInboxSendResponse, bo as PalbaseInitialLink, bp as PalbaseInvokeOptions, bq as PalbaseLink, br as PalbaseLinkAnalytics, bs as PalbaseLinkDetails, bt as PalbaseLinksClient, bu as PalbaseListLinksOptions, bv as PalbaseListLinksResult, bw as PalbaseListOptions, bx as PalbaseMatchParams, by as PalbaseMultiChannelResponse, bz as PalbaseNotificationChannel, bA as PalbaseNotificationsClient, bB as PalbaseOverviewResult, bC as PalbasePreferences, bD as PalbasePreferencesClient, bE as PalbasePushClient, bF as PalbasePushSendParams, bG as PalbasePushSendResponse, bH as PalbaseQrCodeOptions, bI as PalbaseQuerySnapshot, bJ as PalbaseRealtimeClient, bK as PalbaseRegisterDeviceParams, bL as PalbaseRetentionQueryInput, bM as PalbaseRetentionResult, bN as PalbaseSession, bO as PalbaseSetOverrideResult, bP as PalbaseSetOverridesResult, bQ as PalbaseSignedUrlResponse, bR as PalbaseSmsClient, bS as PalbaseSmsSendParams, bT as PalbaseSmsSendResponse, bU as PalbaseStorageClient, bV as PalbaseTransformOptions, bW as PalbaseUpdateLinkParams, bX as PalbaseUploadOptions, bY as PalbaseUser, bZ as PalbaseUserDetailResult, b_ as PalbaseUsersQueryInput, b$ as PalbaseUsersResult, c0 as PalbaseVerifyRequestSignatureParams, c1 as PalbaseWhatsAppClient, c2 as PalbaseWhatsAppEvent, c3 as PalbaseWhatsAppSendParams, c4 as PalbaseWhatsAppSendResponse, c5 as PalbaseWhatsAppTemplate, c6 as PalbaseWhereOperator, c7 as PolicyBinOp, c8 as PolicyBuilder, c9 as PolicyCommand, ca as PolicyDef, cb as PolicyExprCtx, cc as PolicyExprRef, cd as PolicyMode, ce as PolicyOperand, cf as QueryInput, R as RateLimitConfig, cg as RawConstraintDef, f as RawPageOptions, ch as Realtime, ci as Ref, cj as RequestStore, ck as RowShape, b as RuntimeServices, cl as Secrets, cm as SecretsService, cn as SerializationFailure, co as SetShape, cp as SetValue, cq as ShutdownRunner, cr as SqlFragment, cs as Storage, ct as TABLE_META, cu as TableDef, cv as TableHandle, cw as TableInput, cx as TableRef, cy as TooManyRequests, T as TransactionIsolation, cz as TxColumnExpr, cA as TxInsertShape, cB as TxInsertValue, cC as TxNow, cD as TxPlan, g as TxPlanBody, cE as TxPlanError, cF as TxPlanHandle, cG as TxPlanOpResult, cH as TxPlanRejection, h as TxPlanResponse, cI as TxRefError, cJ as TxRow, cK as TxRows, cL as TxSelectOptions, cM as TxSetShape, cN as TxSetValue, cO as TxTable, cP as TxTables, cQ as TxWhere, cR as TxWireExpr, cS as TxWireGuard, cT as TxWireOp, cU as TxWireRef, cV as TxWireValue, cW as TypedDB, cX as TypedTable, cY as TypedTx, cZ as Unauthorized, c_ as UniqueViolation, c$ as UniqueWhere, d0 as UserT, d1 as VerifiedDevice, d2 as WhereFilter, d3 as WhereOp, d4 as __getRuntime, j as __requestALS, d5 as __resetLifecycleHooks, d6 as __runStartHooks, _ as __runWithRuntime, d7 as __setRuntime, d8 as backfill, d9 as bigint, da as boolean, db as can, dc as check, dd as col, de as dec, df as decrement, dg as defineMiddleware, dh as defineSchema, di as defineTable, dj as enumType, dk as exprCtx, dl as foreignKey, dm as freeze, dn as guard, dp as inc, dq as increment, dr as index, ds as installationRef, dt as integer, du as isPalbaseExtension, dv as isRetryable, dw as jsonb, dx as makeTypedDB, dy as now, dz as numeric, dA as onShutdown, dB as onStart, dC as openai, dD as ownedByUser, dE as policy, dF as raw, dG as sqlFragment, dH as text, dI as timestamp, dJ as userRef, dK as uuid, dL as vector, dM as withRetry } from './index-CCY1h_J2.cjs';
3
+ import { M as ModuleClients, C as Container } from './index-Db5QHdTa.cjs';
4
+ export { D as DECLARATION_REFUSAL, a as DeclarationRefused, b as DiError, c as DiKind, d as ModulePressure, e as assertNoOrphanEntryPoints, f as buildContainer, i as isDeclarationRefused } from './index-Db5QHdTa.cjs';
5
5
  export { TableTypes, Tables } from './db/env.cjs';
6
6
  export { PalbaseBucketName, PalbaseFlagKey, PalbaseSecretName } from './stack.cjs';
7
- import { a as RouteOptions } from './registry-9dNeVN5d.cjs';
8
- export { H as HttpMethodUpper, b as ParamKind, P as ParamMeta, R as RouteMeta, c as Signal, d as Sse, S as SseConfig, e as SseOut, f as SseWriter, T as ThrowDescriptor, g as Upload, U as UploadConfig, h as UploadedObject, i as getRoutes, r as recordThrows } from './registry-9dNeVN5d.cjs';
7
+ import { a as RouteOptions } from './registry-CH6HRR6T.cjs';
8
+ export { H as HttpMethodUpper, b as ParamKind, P as ParamMeta, R as RouteMeta, c as Signal, d as Sse, S as SseConfig, e as SseOut, f as SseWriter, T as ThrowDescriptor, g as Upload, U as UploadConfig, h as UploadedObject, i as getRoutes, r as recordThrows } from './registry-CH6HRR6T.cjs';
9
9
  import { ZodTypeAny, z } from 'zod';
10
10
  export { z } from 'zod';
11
11
  import { T as Token } from './module-Dl1KFVtc.cjs';
package/dist/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { k as PalbaseResult, l as PolicyExpr, S as SchemaDef, A as AuthSpec, H as HttpError } from './index-eN4KzGa5.js';
2
- export { m as AggregateInput, n as AggregateResult, o as AnyColumn, p as AtomicDatabase, q as AtomicOptions, r as Auth, s as AuthConfig, B as BackfillDef, t as BadRequest, u as Cache, i as CacheClient, v as CheckDef, w as ClientInfo, x as ColRef, y as ColumnBuilder, z as ColumnDef, F as ColumnMap, G as ColumnType, C as CommandOptions, I as Conflict, a as DBClient, e as DBOps, J as Database, D as DatabaseBudget, d as DatabaseDiagnostics, c as DatabaseDiagnosticsOptions, K as DatabaseQueryEvent, L as DeadlockDetected, M as Documents, N as EXTENSION_DEPENDENCIES, O as EmbeddingModelRef, Q as EnvSchemas, E as EnvServiceDatabase, U as EnvTables, V as EnvTypedDatabase, W as EnvTypedTable, X as ErrorDef, Y as ErrorMap, Z as ErrorThrowers, $ as FileContext, a0 as FindManyOpts, a1 as FkAction, a2 as FkMatch, a3 as Flags, a4 as Forbidden, a5 as ForeignKeyBuilder, a6 as ForeignKeyDef, a7 as FreezeBuilder, a8 as FreezeDef, a9 as GuardBuilder, aa as GuardDef, ab as GuardEvent, ac as HttpMethod, ad as IndexBuilder, ae as IndexDef, af as InsertManyOptions, ag as InsertShape, ah as InsertValues, ai as LifecycleHook, aj as Log, ak as Logger, al as Materialized, am as Middleware, an as MiddlewareContext, ao as MiddlewareHandler, ap as MutateInput, aq as NotFound, ar as Notifications, as as OnDeleteAction, at as OrderBySpec, au as PALBASE_EXTENSIONS, av as PBRequest, P as Page, aw as PageInfo, ax as PageInput, ay as PageNavigation, az as PalError, aA as PalbaseAnalyticsClient, aB as PalbaseAnalyticsManagementNamespace, aC as PalbaseAnalyticsProperties, aD as PalbaseAnalyticsQueryNamespace, aE as PalbaseAttestAndroidParams, aF as PalbaseAttestAndroidResult, aG as PalbaseAttestiOSParams, aH as PalbaseAttestiOSResult, aI as PalbaseAuthAdminClient, aJ as PalbaseAuthClient, aK as PalbaseBatchOverrideOperation, aL as PalbaseBatchSetOverridesResult, aM as PalbaseBindDeviceParams, aN as PalbaseBucketClient, aO as PalbaseClearAllOverridesResult, aP as PalbaseClearOverrideResult, aQ as PalbaseCohortQueryInput, aR as PalbaseCohortResult, aS as PalbaseCollectionRef, aT as PalbaseCountQueryInput, aU as PalbaseCountResult, aV as PalbaseCreateLinkParams, aW as PalbaseDeviceInfo, aX as PalbaseDeviceTokenView, aY as PalbaseDocsClient, aZ as PalbaseDocumentRef, a_ as PalbaseDocumentSnapshot, a$ as PalbaseEmailClient, b0 as PalbaseEmailSendParams, b1 as PalbaseEmailSendResponse, b2 as PalbaseEventNamesResult, b3 as PalbaseEventsQueryInput, b4 as PalbaseEventsResult, b5 as PalbaseExtension, b6 as PalbaseFileObject, b7 as PalbaseFlag, b8 as PalbaseFlagContext, b9 as PalbaseFlagSource, ba as PalbaseFlagValue, bb as PalbaseFlagVariant, bc as PalbaseFlagsClient, bd as PalbaseFlagsServiceClient, be as PalbaseFunctionsClient, bf as PalbaseFunnelQueryInput, bg as PalbaseFunnelResult, bh as PalbaseIdentifyTraits, bi as PalbaseInboxClient, bj as PalbaseInboxListOptions, bk as PalbaseInboxListResult, bl as PalbaseInboxMessage, bm as PalbaseInboxSendParams, bn as PalbaseInboxSendResponse, bo as PalbaseInitialLink, bp as PalbaseInvokeOptions, bq as PalbaseLink, br as PalbaseLinkAnalytics, bs as PalbaseLinkDetails, bt as PalbaseLinksClient, bu as PalbaseListLinksOptions, bv as PalbaseListLinksResult, bw as PalbaseListOptions, bx as PalbaseMatchParams, by as PalbaseMultiChannelResponse, bz as PalbaseNotificationChannel, bA as PalbaseNotificationsClient, bB as PalbaseOverviewResult, bC as PalbasePreferences, bD as PalbasePreferencesClient, bE as PalbasePushClient, bF as PalbasePushSendParams, bG as PalbasePushSendResponse, bH as PalbaseQrCodeOptions, bI as PalbaseQuerySnapshot, bJ as PalbaseRealtimeClient, bK as PalbaseRegisterDeviceParams, bL as PalbaseRetentionQueryInput, bM as PalbaseRetentionResult, bN as PalbaseSession, bO as PalbaseSetOverrideResult, bP as PalbaseSetOverridesResult, bQ as PalbaseSignedUrlResponse, bR as PalbaseSmsClient, bS as PalbaseSmsSendParams, bT as PalbaseSmsSendResponse, bU as PalbaseStorageClient, bV as PalbaseTransformOptions, bW as PalbaseUpdateLinkParams, bX as PalbaseUploadOptions, bY as PalbaseUser, bZ as PalbaseUserDetailResult, b_ as PalbaseUsersQueryInput, b$ as PalbaseUsersResult, c0 as PalbaseVerifyRequestSignatureParams, c1 as PalbaseWhatsAppClient, c2 as PalbaseWhatsAppEvent, c3 as PalbaseWhatsAppSendParams, c4 as PalbaseWhatsAppSendResponse, c5 as PalbaseWhatsAppTemplate, c6 as PalbaseWhereOperator, c7 as PolicyBinOp, c8 as PolicyBuilder, c9 as PolicyCommand, ca as PolicyDef, cb as PolicyExprCtx, cc as PolicyExprRef, cd as PolicyMode, ce as PolicyOperand, cf as QueryInput, R as RateLimitConfig, cg as RawConstraintDef, f as RawPageOptions, ch as Realtime, ci as Ref, cj as RequestStore, ck as RowShape, b as RuntimeServices, cl as Secrets, cm as SecretsService, cn as SerializationFailure, co as SetShape, cp as SetValue, cq as ShutdownRunner, cr as SqlFragment, cs as Storage, ct as TABLE_META, cu as TableDef, cv as TableHandle, cw as TableInput, cx as TableRef, cy as TooManyRequests, T as TransactionIsolation, cz as TxColumnExpr, cA as TxInsertShape, cB as TxInsertValue, cC as TxNow, cD as TxPlan, g as TxPlanBody, cE as TxPlanError, cF as TxPlanHandle, cG as TxPlanOpResult, cH as TxPlanRejection, h as TxPlanResponse, cI as TxRefError, cJ as TxRow, cK as TxRows, cL as TxSelectOptions, cM as TxSetShape, cN as TxSetValue, cO as TxTable, cP as TxTables, cQ as TxWhere, cR as TxWireExpr, cS as TxWireGuard, cT as TxWireOp, cU as TxWireRef, cV as TxWireValue, cW as TypedDB, cX as TypedTable, cY as TypedTx, cZ as Unauthorized, c_ as UniqueViolation, c$ as UniqueWhere, d0 as UserT, d1 as VerifiedDevice, d2 as WhereFilter, d3 as WhereOp, d4 as __getRuntime, j as __requestALS, d5 as __resetLifecycleHooks, d6 as __runStartHooks, _ as __runWithRuntime, d7 as __setRuntime, d8 as backfill, d9 as bigint, da as boolean, db as can, dc as check, dd as col, de as dec, df as decrement, dg as defineMiddleware, dh as defineSchema, di as defineTable, dj as enumType, dk as exprCtx, dl as foreignKey, dm as freeze, dn as guard, dp as inc, dq as increment, dr as index, ds as installationRef, dt as integer, du as isPalbaseExtension, dv as isRetryable, dw as jsonb, dx as makeTypedDB, dy as now, dz as numeric, dA as onShutdown, dB as onStart, dC as openai, dD as ownedByUser, dE as policy, dF as raw, dG as sqlFragment, dH as text, dI as timestamp, dJ as userRef, dK as uuid, dL as vector, dM as withRetry } from './index-eN4KzGa5.js';
3
- import { M as ModuleClients, C as Container } from './index-Dlu2b9-f.js';
4
- export { D as DECLARATION_REFUSAL, a as DeclarationRefused, b as DiError, c as DiKind, d as ModulePressure, e as assertNoOrphanEntryPoints, f as buildContainer, i as isDeclarationRefused } from './index-Dlu2b9-f.js';
1
+ import { k as PalbaseResult, l as PolicyExpr, S as SchemaDef, A as AuthSpec, H as HttpError } from './index-fLaf0PN2.js';
2
+ export { m as AggregateInput, n as AggregateResult, o as AnyColumn, p as AtomicDatabase, q as AtomicOptions, r as Auth, s as AuthConfig, B as BackfillDef, t as BadRequest, u as Cache, i as CacheClient, v as CheckDef, w as ClientInfo, x as ColRef, y as ColumnBuilder, z as ColumnDef, F as ColumnMap, G as ColumnType, C as CommandOptions, I as Conflict, a as DBClient, e as DBOps, J as Database, D as DatabaseBudget, d as DatabaseDiagnostics, c as DatabaseDiagnosticsOptions, K as DatabaseQueryEvent, L as DeadlockDetected, M as Documents, N as EXTENSION_DEPENDENCIES, O as EmbeddingModelRef, Q as EnvSchemas, E as EnvServiceDatabase, U as EnvTables, V as EnvTypedDatabase, W as EnvTypedTable, X as ErrorDef, Y as ErrorMap, Z as ErrorThrowers, $ as FileContext, a0 as FindManyOpts, a1 as FkAction, a2 as FkMatch, a3 as Flags, a4 as Forbidden, a5 as ForeignKeyBuilder, a6 as ForeignKeyDef, a7 as FreezeBuilder, a8 as FreezeDef, a9 as GuardBuilder, aa as GuardDef, ab as GuardEvent, ac as HttpMethod, ad as IndexBuilder, ae as IndexDef, af as InsertManyOptions, ag as InsertShape, ah as InsertValues, ai as LifecycleHook, aj as Log, ak as Logger, al as Materialized, am as Middleware, an as MiddlewareContext, ao as MiddlewareHandler, ap as MutateInput, aq as NotFound, ar as Notifications, as as OnDeleteAction, at as OrderBySpec, au as PALBASE_EXTENSIONS, av as PBRequest, P as Page, aw as PageInfo, ax as PageInput, ay as PageNavigation, az as PalError, aA as PalbaseAnalyticsClient, aB as PalbaseAnalyticsManagementNamespace, aC as PalbaseAnalyticsProperties, aD as PalbaseAnalyticsQueryNamespace, aE as PalbaseAttestAndroidParams, aF as PalbaseAttestAndroidResult, aG as PalbaseAttestiOSParams, aH as PalbaseAttestiOSResult, aI as PalbaseAuthAdminClient, aJ as PalbaseAuthClient, aK as PalbaseBatchOverrideOperation, aL as PalbaseBatchSetOverridesResult, aM as PalbaseBindDeviceParams, aN as PalbaseBucketClient, aO as PalbaseClearAllOverridesResult, aP as PalbaseClearOverrideResult, aQ as PalbaseCohortQueryInput, aR as PalbaseCohortResult, aS as PalbaseCollectionRef, aT as PalbaseCountQueryInput, aU as PalbaseCountResult, aV as PalbaseCreateLinkParams, aW as PalbaseDeviceInfo, aX as PalbaseDeviceTokenView, aY as PalbaseDocsClient, aZ as PalbaseDocumentRef, a_ as PalbaseDocumentSnapshot, a$ as PalbaseEmailClient, b0 as PalbaseEmailSendParams, b1 as PalbaseEmailSendResponse, b2 as PalbaseEventNamesResult, b3 as PalbaseEventsQueryInput, b4 as PalbaseEventsResult, b5 as PalbaseExtension, b6 as PalbaseFileObject, b7 as PalbaseFlag, b8 as PalbaseFlagContext, b9 as PalbaseFlagSource, ba as PalbaseFlagValue, bb as PalbaseFlagVariant, bc as PalbaseFlagsClient, bd as PalbaseFlagsServiceClient, be as PalbaseFunctionsClient, bf as PalbaseFunnelQueryInput, bg as PalbaseFunnelResult, bh as PalbaseIdentifyTraits, bi as PalbaseInboxClient, bj as PalbaseInboxListOptions, bk as PalbaseInboxListResult, bl as PalbaseInboxMessage, bm as PalbaseInboxSendParams, bn as PalbaseInboxSendResponse, bo as PalbaseInitialLink, bp as PalbaseInvokeOptions, bq as PalbaseLink, br as PalbaseLinkAnalytics, bs as PalbaseLinkDetails, bt as PalbaseLinksClient, bu as PalbaseListLinksOptions, bv as PalbaseListLinksResult, bw as PalbaseListOptions, bx as PalbaseMatchParams, by as PalbaseMultiChannelResponse, bz as PalbaseNotificationChannel, bA as PalbaseNotificationsClient, bB as PalbaseOverviewResult, bC as PalbasePreferences, bD as PalbasePreferencesClient, bE as PalbasePushClient, bF as PalbasePushSendParams, bG as PalbasePushSendResponse, bH as PalbaseQrCodeOptions, bI as PalbaseQuerySnapshot, bJ as PalbaseRealtimeClient, bK as PalbaseRegisterDeviceParams, bL as PalbaseRetentionQueryInput, bM as PalbaseRetentionResult, bN as PalbaseSession, bO as PalbaseSetOverrideResult, bP as PalbaseSetOverridesResult, bQ as PalbaseSignedUrlResponse, bR as PalbaseSmsClient, bS as PalbaseSmsSendParams, bT as PalbaseSmsSendResponse, bU as PalbaseStorageClient, bV as PalbaseTransformOptions, bW as PalbaseUpdateLinkParams, bX as PalbaseUploadOptions, bY as PalbaseUser, bZ as PalbaseUserDetailResult, b_ as PalbaseUsersQueryInput, b$ as PalbaseUsersResult, c0 as PalbaseVerifyRequestSignatureParams, c1 as PalbaseWhatsAppClient, c2 as PalbaseWhatsAppEvent, c3 as PalbaseWhatsAppSendParams, c4 as PalbaseWhatsAppSendResponse, c5 as PalbaseWhatsAppTemplate, c6 as PalbaseWhereOperator, c7 as PolicyBinOp, c8 as PolicyBuilder, c9 as PolicyCommand, ca as PolicyDef, cb as PolicyExprCtx, cc as PolicyExprRef, cd as PolicyMode, ce as PolicyOperand, cf as QueryInput, R as RateLimitConfig, cg as RawConstraintDef, f as RawPageOptions, ch as Realtime, ci as Ref, cj as RequestStore, ck as RowShape, b as RuntimeServices, cl as Secrets, cm as SecretsService, cn as SerializationFailure, co as SetShape, cp as SetValue, cq as ShutdownRunner, cr as SqlFragment, cs as Storage, ct as TABLE_META, cu as TableDef, cv as TableHandle, cw as TableInput, cx as TableRef, cy as TooManyRequests, T as TransactionIsolation, cz as TxColumnExpr, cA as TxInsertShape, cB as TxInsertValue, cC as TxNow, cD as TxPlan, g as TxPlanBody, cE as TxPlanError, cF as TxPlanHandle, cG as TxPlanOpResult, cH as TxPlanRejection, h as TxPlanResponse, cI as TxRefError, cJ as TxRow, cK as TxRows, cL as TxSelectOptions, cM as TxSetShape, cN as TxSetValue, cO as TxTable, cP as TxTables, cQ as TxWhere, cR as TxWireExpr, cS as TxWireGuard, cT as TxWireOp, cU as TxWireRef, cV as TxWireValue, cW as TypedDB, cX as TypedTable, cY as TypedTx, cZ as Unauthorized, c_ as UniqueViolation, c$ as UniqueWhere, d0 as UserT, d1 as VerifiedDevice, d2 as WhereFilter, d3 as WhereOp, d4 as __getRuntime, j as __requestALS, d5 as __resetLifecycleHooks, d6 as __runStartHooks, _ as __runWithRuntime, d7 as __setRuntime, d8 as backfill, d9 as bigint, da as boolean, db as can, dc as check, dd as col, de as dec, df as decrement, dg as defineMiddleware, dh as defineSchema, di as defineTable, dj as enumType, dk as exprCtx, dl as foreignKey, dm as freeze, dn as guard, dp as inc, dq as increment, dr as index, ds as installationRef, dt as integer, du as isPalbaseExtension, dv as isRetryable, dw as jsonb, dx as makeTypedDB, dy as now, dz as numeric, dA as onShutdown, dB as onStart, dC as openai, dD as ownedByUser, dE as policy, dF as raw, dG as sqlFragment, dH as text, dI as timestamp, dJ as userRef, dK as uuid, dL as vector, dM as withRetry } from './index-fLaf0PN2.js';
3
+ import { M as ModuleClients, C as Container } from './index-QWN1Ncrv.js';
4
+ export { D as DECLARATION_REFUSAL, a as DeclarationRefused, b as DiError, c as DiKind, d as ModulePressure, e as assertNoOrphanEntryPoints, f as buildContainer, i as isDeclarationRefused } from './index-QWN1Ncrv.js';
5
5
  export { TableTypes, Tables } from './db/env.js';
6
6
  export { PalbaseBucketName, PalbaseFlagKey, PalbaseSecretName } from './stack.js';
7
- import { a as RouteOptions } from './registry-B8ddZiMY.js';
8
- export { H as HttpMethodUpper, b as ParamKind, P as ParamMeta, R as RouteMeta, c as Signal, d as Sse, S as SseConfig, e as SseOut, f as SseWriter, T as ThrowDescriptor, g as Upload, U as UploadConfig, h as UploadedObject, i as getRoutes, r as recordThrows } from './registry-B8ddZiMY.js';
7
+ import { a as RouteOptions } from './registry-C7tCRyPm.js';
8
+ export { H as HttpMethodUpper, b as ParamKind, P as ParamMeta, R as RouteMeta, c as Signal, d as Sse, S as SseConfig, e as SseOut, f as SseWriter, T as ThrowDescriptor, g as Upload, U as UploadConfig, h as UploadedObject, i as getRoutes, r as recordThrows } from './registry-C7tCRyPm.js';
9
9
  import { ZodTypeAny, z } from 'zod';
10
10
  export { z } from 'zod';
11
11
  import { T as Token } from './module-Dl1KFVtc.js';
@@ -1,7 +1,7 @@
1
1
  import { OpenApiGeneratorV31 } from '@asteasolutions/zod-to-openapi';
2
2
  import { ZodTypeAny } from 'zod';
3
- import { A as AuthSpec, R as RateLimitConfig } from '../index-pK2At5Yc.cjs';
4
- import { P as ParamMeta, T as ThrowDescriptor, U as UploadConfig, S as SseConfig } from '../registry-9dNeVN5d.cjs';
3
+ import { A as AuthSpec, R as RateLimitConfig } from '../index-CCY1h_J2.cjs';
4
+ import { P as ParamMeta, T as ThrowDescriptor, U as UploadConfig, S as SseConfig } from '../registry-CH6HRR6T.cjs';
5
5
  import '../db/env.cjs';
6
6
  import '../stack.cjs';
7
7
  import 'node:async_hooks';
@@ -1,7 +1,7 @@
1
1
  import { OpenApiGeneratorV31 } from '@asteasolutions/zod-to-openapi';
2
2
  import { ZodTypeAny } from 'zod';
3
- import { A as AuthSpec, R as RateLimitConfig } from '../index-eN4KzGa5.js';
4
- import { P as ParamMeta, T as ThrowDescriptor, U as UploadConfig, S as SseConfig } from '../registry-B8ddZiMY.js';
3
+ import { A as AuthSpec, R as RateLimitConfig } from '../index-fLaf0PN2.js';
4
+ import { P as ParamMeta, T as ThrowDescriptor, U as UploadConfig, S as SseConfig } from '../registry-C7tCRyPm.js';
5
5
  import '../db/env.js';
6
6
  import '../stack.js';
7
7
  import 'node:async_hooks';
@@ -1,4 +1,4 @@
1
- import { D as DatabaseBudget, A as AuthSpec, R as RateLimitConfig } from './index-eN4KzGa5.js';
1
+ import { D as DatabaseBudget, A as AuthSpec, R as RateLimitConfig } from './index-fLaf0PN2.js';
2
2
  import { ZodTypeAny } from 'zod';
3
3
  import { PalbaseBucketName } from './stack.js';
4
4
 
@@ -1,4 +1,4 @@
1
- import { D as DatabaseBudget, A as AuthSpec, R as RateLimitConfig } from './index-pK2At5Yc.cjs';
1
+ import { D as DatabaseBudget, A as AuthSpec, R as RateLimitConfig } from './index-CCY1h_J2.cjs';
2
2
  import { ZodTypeAny } from 'zod';
3
3
  import { PalbaseBucketName } from './stack.cjs';
4
4
 
@@ -1,5 +1,5 @@
1
1
  import { T as Token } from '../module-Dl1KFVtc.cjs';
2
- import { E as EnvServiceDatabase, a as DBClient, b as RuntimeServices } from '../index-pK2At5Yc.cjs';
2
+ import { E as EnvServiceDatabase, a as DBClient, b as RuntimeServices } from '../index-CCY1h_J2.cjs';
3
3
  import 'zod';
4
4
  import '../db/env.cjs';
5
5
  import '../stack.cjs';
@@ -1,5 +1,5 @@
1
1
  import { T as Token } from '../module-Dl1KFVtc.js';
2
- import { E as EnvServiceDatabase, a as DBClient, b as RuntimeServices } from '../index-eN4KzGa5.js';
2
+ import { E as EnvServiceDatabase, a as DBClient, b as RuntimeServices } from '../index-fLaf0PN2.js';
3
3
  import 'zod';
4
4
  import '../db/env.js';
5
5
  import '../stack.js';
package/docs/auth.md CHANGED
@@ -252,9 +252,10 @@ caller's permissions — pushed over realtime the moment a role changes.
252
252
  ## Email verification
253
253
 
254
254
  The platform handles verification end to end. **You do not configure a sender**,
255
- and `config/notifications.ts` is unrelated that file declares providers for
256
- **your app's own** notifications. Auth email goes out through Palbase's own
257
- notification tenant, not yours.
255
+ and `palbase notifications providers` / `palbase notifications templates` are
256
+ unrelated those manage providers and templates for **your app's own**
257
+ notifications. Auth email goes out through Palbase's own notification tenant,
258
+ not yours.
258
259
 
259
260
  What happens on `POST /auth/signup`:
260
261
 
@@ -1071,9 +1071,10 @@ caller's permissions — pushed over realtime the moment a role changes.
1071
1071
  ## Email verification
1072
1072
 
1073
1073
  The platform handles verification end to end. **You do not configure a sender**,
1074
- and `config/notifications.ts` is unrelated that file declares providers for
1075
- **your app's own** notifications. Auth email goes out through Palbase's own
1076
- notification tenant, not yours.
1074
+ and `palbase notifications providers` / `palbase notifications templates` are
1075
+ unrelated those manage providers and templates for **your app's own**
1076
+ notifications. Auth email goes out through Palbase's own notification tenant,
1077
+ not yours.
1077
1078
 
1078
1079
  What happens on `POST /auth/signup`:
1079
1080
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@palbase/backend",
3
- "version": "39.1.4",
3
+ "version": "39.1.6",
4
4
  "description": "Palbase Backend SDK — class controllers (@Controller/@Get/@Post + @Body/@QueryParams/@Param), error classes, schema DSL",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -92,7 +92,8 @@
92
92
  "dist",
93
93
  "docs",
94
94
  "stager",
95
- "template"
95
+ "template",
96
+ "MIGRATION.md"
96
97
  ],
97
98
  "dependencies": {
98
99
  "@asteasolutions/zod-to-openapi": "^7.3.4",
@@ -16,7 +16,7 @@ import { Controller, Get, Post, Body, Param, User, z, Database, NotFound } from
16
16
  > field would arrive `undefined`, and the build says so by name.
17
17
 
18
18
  **The full reference** — every decorator, every platform service, every schema
19
- helper — is at <https://app.dev.palbase.studio/llms.txt> (`/llms-full.txt` for
19
+ helper — is at <https://palbase.studio/llms.txt> (`/llms-full.txt` for
20
20
  agents). This file does not repeat it; it says what the code should LOOK like.
21
21
 
22
22
  ## The layers
@@ -1,75 +0,0 @@
1
- # Fake pagination and claim: verification sources
2
-
3
- Verified 2026-09-06. Scope: repair the two existing in-memory fake contracts,
4
- using the repository's existing runtime and test runner. No new dependency or
5
- public API is introduced.
6
-
7
- | ID | Existing tool | Stakes | Tier | Status | Evidence |
8
- | --- | --- | --- | --- | --- | --- |
9
- | UD-001 | Bun 1.3.9 for independent consumer probes | 1 | quick | verified | `bun --version`; published-package and built-package probe executions |
10
- | UD-002 | Vitest 3.2.4 for SDK regressions | 1 | quick | verified | `backend/package.json`, runtime version output, Context7 CLI documentation |
11
-
12
- CLAIM: Bun supports direct TypeScript execution and reports test/runtime failures
13
- with a nonzero exit status. SOURCE:
14
- https://github.com/oven-sh/bun/blob/main/docs/test/runtime-behavior.mdx
15
- VERIFIED: 2026-09-06 via Context7 and actual Bun 1.3.9 probe exits 1/0.
16
- TIER: quick. Current docs are not an assertion that their latest Bun version is
17
- the installed version; the installed runtime was measured separately.
18
-
19
- CLAIM: Vitest's file arguments select test paths; `run` performs a single run.
20
- SOURCE: https://github.com/vitest-dev/vitest/blob/v3.2.4/docs/guide/cli.md
21
- VERIFIED: 2026-09-06 via Context7 and focused red/green executions.
22
- TIER: quick.
23
-
24
- CLAIM: `--no-file-parallelism` runs test files without file concurrency.
25
- SOURCE: https://github.com/vitest-dev/vitest/blob/v3.2.4/docs/guide/debugging.md
26
- VERIFIED: 2026-09-06 via Context7 and installed
27
- `pnpm --filter @palbase/backend exec vitest --help --fileParallelism`.
28
- TIER: quick. This flag changes scheduling, preserving test assertions, selected
29
- files, type checking, and timeouts.
30
-
31
- The SDK contracts were checked against local primary sources:
32
-
33
- - `docs/database.md:179`: `now()` works in `claim` and other insert operations.
34
- - `docs/database.md:355`: offset requires limit.
35
- - `src/engine/db.ts:1403`: nonnegative integer limit validation.
36
- - `src/engine/db.ts:1417`: nonnegative integer offset validation and limit requirement.
37
- - `src/engine/db.ts:2362`: claim merges unique/extra and compiles insert expressions.
38
- - `src/__tests__/helpers/mock-db.ts:277`: existing insert-expression resolver.
39
-
40
- Runtime evidence separating the hypotheses is in `verification.md`.
41
-
42
- ## Publication follow-up
43
-
44
- The user requested publication after the source fix was verified. Publication
45
- uses the repository's existing Changesets workflow; stakes 3, standard tier.
46
- Context7 was attempted twice but its transport was unavailable, so the official
47
- Changesets CLI documentation was read directly and checked against the local
48
- workflow and a successful live run.
49
-
50
- | ID | Existing approach | Stakes | Tier | Status | Evidence |
51
- | --- | --- | --- | --- | --- | --- |
52
- | UD-003 | Changesets version commit followed by the main release workflow | 3 | standard | verified | `.github/workflows/release.yml`, `package.json`, official CLI docs and run 34035374818 |
53
-
54
- CLAIM: `changeset version` updates package versions/changelogs, and `publish`
55
- publishes package versions absent from npm. SOURCE:
56
- https://github.com/changesets/changesets/blob/main/docs/command-line-options.md
57
- VERIFIED: 2026-09-06 via official documentation, installed CLI 2.30.0, and the
58
- repository's `ci:version`/`ci:publish` scripts. TIER: standard.
59
-
60
- CLAIM: This repository versions locally, pushes to main, verifies matching core
61
- images first, then publishes npm and advances latest/next. SOURCE:
62
- https://github.com/palgroup/palbase-ts/blob/e9765e8460bbe9c4a20641f805a5e682f0097174/.github/workflows/release.yml
63
- and https://github.com/palgroup/palbase-ts/actions/runs/34035374818
64
- VERIFIED: 2026-09-06 via the workflow source and GitHub run state. TIER: standard.
65
-
66
- Registry evidence: `latest` and `next` both resolve to 36.0.1; querying 36.0.2
67
- returned E404 before versioning. Only the backend package is selected for a
68
- patch release, with the existing image-before-npm order preserved.
69
-
70
- Publication preflight observation: `ci:version` initially failed in the GitHub
71
- changelog adapter because the local fix commit was not yet on GitHub. The commit
72
- API returned HTTP 422 for `bfd6060` and resolved the existing base commit, ruling
73
- out an authentication failure. Publishing the fix commit to a temporary branch
74
- made the same `ci:version` command succeed without changing tooling or workflow.
75
- Only backend package version/changelog and the consumed changeset changed.
@@ -1,145 +0,0 @@
1
- # Backend fake defects: proof, fix, proof
2
-
3
- Date: 2026-09-06. Runtime: Bun 1.3.9, macOS arm64.
4
- Published baseline: `@palbase/backend@36.0.0` from npm, unchanged.
5
- Source baseline: nested `palbase-ts` repository, commit `295958d`, package 36.0.1.
6
- The source checkout still contained both reported defects.
7
-
8
- ## Reproduction
9
-
10
- The supplied `scripts/reproduce-sdk-bugs.ts` was absent from this workspace.
11
- `backend/scripts/reproduce-sdk-bugs.ts` reconstructs the two supplied independent
12
- contracts with public package imports and no application fixtures or credentials.
13
- An identical copy was run in a scratch consumer of the published npm tarball.
14
-
15
- Published baseline commands:
16
-
17
- ```sh
18
- npm pack @palbase/backend@36.0.0 --ignore-scripts --pack-destination /tmp/palbase-sdk-fake-proof.CaHHuo --json
19
- # Scratch package depends on that unchanged tarball.
20
- bun install --ignore-scripts
21
- bun reproduce-sdk-bugs.ts
22
- ```
23
-
24
- Observed before any source fix:
25
-
26
- ```text
27
- FAIL findMany honors offset before limit
28
- actual: [{ id: 'a' }], expected: [{ id: 'b' }]
29
- FAIL claim evaluates now() in returned and stored rows
30
- actual typeof created_at: 'object', expected: 'string'
31
- 0 passed, 2 failed
32
- exit 1
33
- ```
34
-
35
- The raw claim's returned AND stored rows carried `Symbol(palbase.tx.expr)`.
36
- Tarball SHA-1 from npm pack: `0c665f63e2a9b98f5f736df050d17038305a5399`.
37
-
38
- ## Hypotheses and runtime discrimination
39
-
40
- Pagination hypotheses: ignored offset, lost typed forwarding, wrong ordering.
41
- With deliberately unsorted `c,a,b` seeds, raw calls at offsets 0, 1, 2 and 3
42
- all returned `a`. Sorting therefore ran, and bypassing the typed wrapper still
43
- failed. The source pagination step used `slice(0, limit)` and its local option
44
- type omitted offset.
45
-
46
- Claim hypotheses: skipped insert-expression evaluation, incompatible expression
47
- marker, accidental materialization during reading. Passing the SAME `now()`
48
- object to insert and claim returned a timestamp from insert, while claim stored
49
- that original expression object by identity. A later read also returned the
50
- expression, excluding a return-only formatting error.
51
-
52
- Observed paths, cross-checked against the source:
53
-
54
- - Public `/test` export → `src/test/fake-db.ts:65` → shared
55
- `src/__tests__/helpers/mock-db.ts` operation implementation.
56
- - Typed `fake.db.public.<table>.findMany` → `src/runtime.ts:498` → the same
57
- raw operation, with offset forwarded.
58
- - Typed claim → `src/runtime.ts:531` → raw claim.
59
- - The helper is bundled into the shipped `/test` entry by `tsup.config.ts`;
60
- its `__tests__` directory name does not make it an unused test-only copy.
61
-
62
- ## Source regression proof and changes
63
-
64
- Command before and after the implementation change, from `backend`:
65
-
66
- ```sh
67
- pnpm test src/test/fake-db.test.ts src/test/fake-db-parity.test.ts
68
- ```
69
-
70
- | Tree | Result | Exit |
71
- | --- | --- | --- |
72
- | Original existing focused suite | 37 passed | 0 |
73
- | New regressions, original implementation | 12 failed, 38 passed | 1 |
74
- | Same tests, fixed implementation | 50 passed, no type errors | 0 |
75
-
76
- The repair applies offset after filtering/ordering and before projection, and
77
- uses the engine's existing limit/offset validation contract. Claim reuses the
78
- insert-expression resolver and write-value guards before storing a new row.
79
- Existing-row claims still return the original row without recording a new write.
80
-
81
- Coverage includes raw and typed calls, filter/sort/projection ordering, distinct
82
- pages, omitted/zero offset, an empty tail, zero limit, invalid pagination,
83
- timestamp validity in returned/stored/tracked rows, repeated claims, and refusal
84
- of invalid insert values without side effects. Explicit `id` lookup/deletion
85
- semantics are unaffected.
86
-
87
- ## Built package and review
88
-
89
- Fresh build: `pnpm -w turbo run build --filter=@palbase/backend` → exit 0,
90
- backend cache miss, ESM/CJS/declarations generated.
91
-
92
- From `backend`, against the built public package entry points:
93
-
94
- ```text
95
- $ bun scripts/reproduce-sdk-bugs.ts
96
- PASS findMany honors offset before limit
97
- PASS claim evaluates now() in returned and stored rows
98
- 2 passed, 0 failed
99
- exit 0
100
- ```
101
-
102
- `pnpm typecheck` → exit 0.
103
- `pnpm check:api` → exit 0; 424 exports and 421 signatures unchanged.
104
- Independent reviewer: no actionable findings; separate source probe and
105
- 42-test fake suite both passed.
106
-
107
- ## Full-suite environment findings
108
-
109
- The first shared-workspace `pnpm test` exited 1: 6 failed / 1900 passed tests,
110
- 3 collection failures and 3 worker RPC errors. It included ignored generated
111
- Bun consumer tests under `bench/database-dx/generated/...`, which Vitest cannot
112
- load (`bun:test`), plus five timeouts under concurrent load.
113
-
114
- The sixth failure was an existing probabilistic cursor-test assertion:
115
- `src/engine/cursor.test.ts:15` replaces character 10 with `x`, even when it
116
- already is `x`. An independent loop observed this at attempt 82: the
117
- "changed" token equalled the original, and decoding correctly accepted it.
118
- Neither this test nor cursor implementation is changed by this fix.
119
-
120
- Final suite verification uses a detached temporary checkout at the same commit,
121
- with identical fix/test/probe files and the existing installed dependencies.
122
- File scheduling is serial; no assertions, timeouts or test selections are changed.
123
- The copied implementation, regression tests, and independent probe were checked
124
- byte-for-byte against the working files with `cmp` (all exit 0).
125
-
126
- Final command, from the isolated checkout's `backend` directory:
127
-
128
- ```text
129
- $ pnpm test --no-file-parallelism
130
- Test Files 128 passed (128)
131
- Tests 1906 passed (1906)
132
- Type Errors no errors
133
- Duration 38.41s
134
- exit 0
135
- ```
136
-
137
- The isolated checkout was also freshly built (backend cache miss, exit 0), and
138
- `bun scripts/reproduce-sdk-bugs.ts` there returned 2 passed / 0 failed, exit 0.
139
- The shared workspace's generated Bun tests are not tracked SDK test files; their
140
- absence in this checkout accounts for the three fewer collected files.
141
-
142
- Full raw command logs are retained in `/tmp/palbase-sdk-fake-proof.CaHHuo`.
143
- This initial verification covered source and local build artifacts, with no live
144
- PostgreSQL run. The user subsequently requested publication as backend 36.0.2;
145
- its registry installation is checked with the same independent contract probes.