@palbase/backend 27.0.0 → 28.0.0

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.
Files changed (52) hide show
  1. package/dist/bin/palbase-backend.cjs +165 -39
  2. package/dist/bin/palbase-backend.cjs.map +1 -1
  3. package/dist/bin/palbase-backend.js +4 -4
  4. package/dist/{chunk-GYK6QYS4.js → chunk-3TUJWHC2.js} +28 -3
  5. package/dist/chunk-3TUJWHC2.js.map +1 -0
  6. package/dist/{chunk-OO7R25AI.js → chunk-75YROPRZ.js} +118 -39
  7. package/dist/chunk-75YROPRZ.js.map +1 -0
  8. package/dist/{chunk-TS4U7NBD.js → chunk-IVZERLTM.js} +2 -2
  9. package/dist/{chunk-I3C4PFIW.js → chunk-RVP6BTEZ.js} +63 -6
  10. package/dist/chunk-RVP6BTEZ.js.map +1 -0
  11. package/dist/{chunk-DRZFQRJI.js → chunk-SNDXY565.js} +3 -2
  12. package/dist/chunk-SNDXY565.js.map +1 -0
  13. package/dist/db/index.cjs +30 -1
  14. package/dist/db/index.cjs.map +1 -1
  15. package/dist/db/index.d.cts +1 -1
  16. package/dist/db/index.d.ts +1 -1
  17. package/dist/db/index.js +3 -3
  18. package/dist/engine/index.cjs +175 -39
  19. package/dist/engine/index.cjs.map +1 -1
  20. package/dist/engine/index.d.cts +3 -3
  21. package/dist/engine/index.d.ts +3 -3
  22. package/dist/engine/index.js +11 -4
  23. package/dist/{index-VtToZmUm.d.cts → index-9C3JHxg-.d.cts} +112 -5
  24. package/dist/{index-NuzRCuxe.d.ts → index-BbvOoZFr.d.ts} +112 -5
  25. package/dist/{index-Bve7BBTL.d.cts → index-DtISj9QX.d.cts} +125 -22
  26. package/dist/{index-BrvvxSpn.d.ts → index-dTTLlHIn.d.ts} +125 -22
  27. package/dist/index.cjs +93 -4
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +6 -22
  30. package/dist/index.d.ts +6 -22
  31. package/dist/index.js +10 -4
  32. package/dist/index.js.map +1 -1
  33. package/dist/openapi/index.d.cts +2 -2
  34. package/dist/openapi/index.d.ts +2 -2
  35. package/dist/{registry-B0eyOF9x.d.ts → registry-JQNIX-eA.d.ts} +1 -1
  36. package/dist/{registry-Bk9_rbNd.d.cts → registry-qIPM5BQe.d.cts} +1 -1
  37. package/dist/test/index.cjs +100 -6
  38. package/dist/test/index.cjs.map +1 -1
  39. package/dist/test/index.d.cts +1 -1
  40. package/dist/test/index.d.ts +1 -1
  41. package/dist/test/index.js +88 -6
  42. package/dist/test/index.js.map +1 -1
  43. package/docs/README.md +1 -1
  44. package/docs/database.md +103 -1
  45. package/docs/llms-full.txt +104 -2
  46. package/package.json +1 -1
  47. package/template/package.json +1 -1
  48. package/dist/chunk-DRZFQRJI.js.map +0 -1
  49. package/dist/chunk-GYK6QYS4.js.map +0 -1
  50. package/dist/chunk-I3C4PFIW.js.map +0 -1
  51. package/dist/chunk-OO7R25AI.js.map +0 -1
  52. /package/dist/{chunk-TS4U7NBD.js.map → chunk-IVZERLTM.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/db/input-guards.ts","../src/db/tx-plan.ts"],"sourcesContent":["/**\n * The refusals a Database call gets BEFORE any SQL exists — written once, so the\n * engine and the test double cannot disagree about them.\n *\n * WHY THIS FILE EXISTS. `fakeDatabase()` is a second implementation of the same\n * surface (`__tests__/helpers/mock-db.ts`), and it never touched `compileWhere`\n * or `asBindParams`. Measured against the published 24.1.0: all four of the\n * calls that release had just started refusing went through the fake SILENTLY —\n * `update{title:undefined}`, `insert{title:undefined}`, `findMany{done:{}}`,\n * `deleteMany{owner,created_at:{}}`.\n *\n * The scaffold tells authors to test the service layer against exactly that\n * fake. So a test went green on a call production would throw on, and the\n * author found out in production instead — the same \"the surface does not match\n * the engine\" shape these refusals exist to end, arriving through the door the\n * SDK hands people for testing.\n *\n * These are pure and SQL-free on purpose: an in-memory store can run them as\n * easily as the driver path can.\n */\n\n/**\n * İşaretçilerin MARKASI — `col()` ve `sqlFragment()` ürünlerini bu süreçte\n * üretilmiş olmakla tanımlar.\n *\n * NEDEN ŞEKİL DEĞİL DE MARKA (gözcü W2-A/C1 ve W2-B/C3, ikisi de ÖLÇTÜ):\n * şekil kontrolü, işaretçiyi güvenilmeyen bir istek gövdesinden UYDURULABİLİR\n * kılıyordu. Ölçülen iki sonuç:\n *\n * findMany(\"docs\", { owner_id: JSON.parse('{\"$col\":\"owner_id\"}') })\n * → WHERE true AND t.\"owner_id\" = t.\"owner_id\" ← kiracılık predikatı totoloji\n * findMany(\"todos\", JSON.parse('{\"$sql\":{\"text\":[\"1=1 -- pwned\"],\"values\":[]}}'))\n * → WHERE true AND 1=1 -- pwned ← saldırganın metni SQL'e HARFİYEN\n *\n * `{ where: { tenant_id: tid, ...req.body.filter } }` bu SDK'nın öğrettiği\n * desen; T010/T014 öncesinde aynı anahtarlar \"bilinmeyen operatör\" diye\n * REDDEDİLİYORDU. Marka o reddi geri getiriyor.\n *\n * Sembol GLOBAL kayıttan (`Symbol.for`) ve ENUMERABLE DEĞİL. İkisi de kasıtlı:\n * global kayıt paketin iki kopyası arasında da eşleşir; enumerable olmaması ise\n * `JSON.stringify` ve `{...ref, gt: 5}` yayılımının markayı DÜŞÜRMESİNİ sağlar —\n * yani telden geçen ya da elle karıştırılan hiçbir şey işaretçi sayılmaz.\n * Kardeş özellik (`increment`) zaten `Symbol.for(\"palbase.tx.expr\")` kullanıyor;\n * bu onun aynısı.\n */\nconst REF_BRAND = Symbol.for(\"palbase.db.ref\");\n\n/** İşaretçiyi markalar. Yalnız `col()` ve `sqlFragment()` çağırır. */\nexport function brandRef<T extends object>(v: T, kind: \"col\" | \"sql\" | \"ref\"): T {\n Object.defineProperty(v, REF_BRAND, { value: kind, enumerable: false });\n return v;\n}\n\nfunction brandOf(v: unknown): unknown {\n if (typeof v !== \"object\" || v === null) return undefined;\n // KENDİ özelliği olmalı, prototip zincirinden MİRAS ALINMIŞ değil:\n // `Object.create(col(\"x\"))` markayı zincirden okuyup işaretçi sayılıyordu\n // (gözcü ölçtü). Telden erişilemez — JSON `__proto__` üstünden sembol\n // yazamaz — ama daraltmak bedava ve \"işaretçi bu süreçte ÜRETİLDİ\"\n // iddiasının tam karşılığı budur.\n return Object.hasOwn(v, REF_BRAND) ? (v as Record<symbol, unknown>)[REF_BRAND] : undefined;\n}\n\n/**\n * Bir değer, MARKASIZ bir işaretçi taklidi mi? (`{$col:…}` / `{$sql:…}`)\n *\n * Üst düzeyde bunlar zaten \"bilinmeyen operatör\" diye reddediliyor. Ama\n * operatörün SAĞINDA — `{ amount: { gt: {\"$col\":\"other\"} } }` — sessizce\n * PARAMETRE olarak bağlanıyorlardı: sayısal kolonda sürücünün 22P02'si,\n * jsonb/text kolonunda ise HİÇBİR SATIR, hatasız (gözcü ölçtü).\n *\n * `in` listesindeki aynı kusur adıyla reddediliyor; bu onun bir seviye\n * yanındaki hâli ve aynı cevabı hak ediyor.\n */\nexport function looksLikeUnbrandedRef(v: unknown): \"col\" | \"sql\" | null {\n if (typeof v !== \"object\" || v === null) return null;\n if (brandOf(v) !== undefined) return null; // gerçek işaretçi\n const o = v as { $col?: unknown; $sql?: unknown };\n if (typeof o.$col === \"string\") return \"col\";\n if (o.$sql !== undefined && typeof o.$sql === \"object\" && o.$sql !== null) return \"sql\";\n return null;\n}\n\n/**\n * `col()` ürünü mü? (FR-011)\n *\n * Burada, çünkü bu dosya \"iki uygulamanın da okuduğu kurallar\" dosyası: motor,\n * `fakeDatabase` ve guard AYNI cevabı vermek zorunda.\n */\nexport function isColRef(v: unknown): v is { readonly $col: string } {\n return brandOf(v) === \"col\" && typeof (v as { $col?: unknown }).$col === \"string\";\n}\n\n/**\n * `sqlFragment` ürünü mü? (FR-018)\n *\n * `isColRef` ile aynı gerekçeyle burada: motor, guard ve `fakeDatabase` üçü de\n * aynı cevabı vermek zorunda — biri fragment'i \"kolon haritası\" sanarsa filtre\n * sessizce düşer.\n */\n/**\n * Plan REFERANSI mı? (`{ $ref: { op, field } }`)\n *\n * `$ref` bu dilin MARKASIZ KALAN TEK işaretçisiydi — `engine/db.ts` onu\n * `\"$ref\" in v` diye tanıyordu — ve SDK'nın öğrettiği desen\n * `{ where: { tenant_id: tid, ...req.body.filter } }`. Ölçüldü (gözcü):\n * istek gövdesinden gelen `{\"id\":{\"$ref\":{\"op\":0,\"field\":\"id\"}}}` filtreyi\n * ÖNCEKİ bir işlemin satır değeriyle karşılaştırtıyor —\n * DELETE … WHERE t.\"tenant_id\" = $1 AND t.\"id\" = $2 PRM [\"t1\",\"SIZAN_DEGER\"]\n * gövdenin hiç görmediği bir değer. Enjeksiyon değil (değerler bound) ama bir\n * ORACLE: `op`/`field` seçip `rows_affected`'tan o değeri öğrenmek.\n *\n * Marka `Symbol.for` olduğu için SDK'nın İKİ KOPYASI arasında da eşleşiyor —\n * kontrolcü bundle'ı kendi kopyasını inline ediyor, planı çalıştıran ise\n * runtime'ınki. Ve plan gövdesi JSON'lanmıyor: tek üretim `txPlan` uygulaması\n * süreç içi (`engine/db.ts`), doğrulandı.\n */\nexport function isPlanRef(v: unknown): v is { readonly $ref: { op: number; field: string } } {\n if (brandOf(v) !== \"ref\") return false;\n const r = (v as { $ref?: { op?: unknown; field?: unknown } }).$ref;\n return r !== undefined && typeof r.op === \"number\" && typeof r.field === \"string\";\n}\n\n/** Markasız bir `{ $ref: … }` taklidi mi? Adıyla reddedilmesi için. */\nexport function looksLikeUnbrandedPlanRef(v: unknown): boolean {\n if (typeof v !== \"object\" || v === null || brandOf(v) !== undefined) return false;\n const r = (v as { $ref?: unknown }).$ref;\n return r !== undefined && typeof r === \"object\" && r !== null;\n}\n\nexport function isSqlFragment(v: unknown): v is { readonly $sql: { text: string[]; values: unknown[] } } {\n if (brandOf(v) !== \"sql\") return false;\n const f = (v as { $sql?: { text?: unknown; values?: unknown } }).$sql;\n return f !== undefined && Array.isArray(f.text) && Array.isArray(f.values);\n}\n\n/**\n * İFADE TUTAMAĞI DEĞER DEĞİLDİR — değer bekleyen yollarda adıyla reddedilir.\n *\n * `increment()` / `decrement()` / `now()` bir Proxy döndürür ve yalnız\n * `updateMany` ile plan yolunun `updateWhere`'i onu SQL'e derler. `insert` /\n * `update` / `put` / `supersede` derlemez; oralarda tutamak bound parametre\n * olarak sürücüye gidiyordu ve reddi SÜRÜCÜ veriyordu (\"Unknown object is not\n * a valid PostgreSQL type\") — yazarın yazdığı hiçbir şeyi adlandırmayan bir\n * mesaj (inceleme I-2/I8, ölçüldü). Plan yolu aynı hatayı kendi diliyle\n * reddediyor; bu, doğrudan yolun karşılığı.\n *\n * Sembol `tx-plan.ts`'in markasıyla AYNI global kayıttan okunuyor; bu dosya\n * kural dosyası olduğu için oraya bağımlılık kurmuyor.\n */\nconst TX_EXPR = Symbol.for(\"palbase.tx.expr\");\n\nexport function isColumnExpr(v: unknown): boolean {\n if (typeof v !== \"object\" && typeof v !== \"function\") return false;\n if (v === null) return false;\n try {\n return (v as Record<symbol, unknown>)[TX_EXPR] !== undefined;\n } catch {\n // Tutamak bir Proxy; bilinmeyen bir prop'ta trap fırlatabilir.\n return false;\n }\n}\n\n/**\n * Değer bekleyen bir yazma yolunda ifade tutamağı ya da `col()` var mı?\n *\n * Motor ve `fakeDatabase` AYNI cevabı vermek zorunda: fake tutamağı satıra\n * YAZIYORDU (`row[k] = proxy`) ve satır artık JSON'a bile çevrilemiyordu, motor\n * ise sürücüde patlıyordu. İki farklı yanlış, tek doğru.\n */\nexport function assertNoExpressionHandles(\n caller: string,\n table: string,\n cols: readonly string[],\n data: Record<string, unknown>,\n): void {\n for (const c of cols) {\n const v = data[c];\n if (isColumnExpr(v)) {\n throw new Error(\n `${caller}(${table}): \"${c}\" bir ifade tutamağı aldı (increment()/decrement()/now()). ` +\n `Bu yolda değer beklenir. Sayaç artışı için updateMany(where, { ${c}: increment(n) }) ` +\n `ya da $transaction içinde tx.tables.${table}.updateWhere(where, { ${c}: increment(n) }) kullanın.`,\n );\n }\n if (isColRef(v)) {\n throw new Error(\n `${caller}(${table}): \"${c}\" bir col() aldı. Kolon referansı yalnız FİLTREDE durabilir; ` +\n `bir kolonun değerini başka bir kolona yazmak için $query kullanın.`,\n );\n }\n }\n}\n\n/** The comparison operators a filter value may carry. Kept here because the\n * guard has to tell an operator object from a plain value. */\nconst KNOWN_OPS = new Set([\n \"gt\", \"gte\", \"lt\", \"lte\", \"neq\", \"in\",\n // K1 metin operatörleri (FR-005) ve null testi (FR-006). Bu küme\n // `fakeDatabase()` ile ORTAK kaynaktır: fake bir çağrıyı motorun reddettiği\n // yerde kabul ederse, yazarın testi üretimde patlayan koda karşı yeşil verir.\n \"contains\", \"icontains\", \"startsWith\", \"endsWith\", \"isNull\",\n]);\n\n/**\n * `eq` ADIYLA reddedilir, ve reddi buradadır çünkü guard'ı motor da fake de\n * okuyor.\n *\n * Eşitliğin yazımı ÇIPLAK DEĞERDİR: `{ owner: \"u1\" }`. `eq`'i ikinci bir yazım\n * olarak eklemek, bu run'ın kapatmak için var olduğu şeyi — aynı iş için iki\n * uyumsuz yazım — filtre dilinin İÇİNDE yeniden açardı. Ve eskiden kabul eden\n * ile reddeden ayrışıyordu: guard `eq`'i geçiriyor, derleyici\n * `bilinmeyen operatör \"eq\"` diyordu (gözcü ölçtü).\n */\nconst REFUSED_OPS: Record<string, string> = {\n eq: 'eşitlik ÇIPLAK yazılır: { <kolon>: <değer> } (ya da kolon karşılaştırması için { <kolon>: col(\"…\") })',\n};\n\n/**\n * Refuse a filter that would compile to something other than what it reads like.\n *\n * Three shapes, each measured in production before it was closed:\n *\n * `{ col: undefined }` binds NULL; `= NULL` matches no row, so the query\n * answered \"no records\" and said nothing.\n * `{ col: {} }` produces no term at all — every row on the read\n * path, a dropped condition on the write path.\n * `{ col: { gte: undefined } }` and an `undefined` inside `in`: the same NULL,\n * one level down.\n */\nexport function assertUsableFilter(\n caller: string,\n table: string,\n where: Record<string, unknown> | undefined,\n): void {\n // Bileşim anahtarları (FR-007) bir KOLON adı değildir; kolon doğrulamasından\n // ve operatör kontrolünden muaftır, kendi dalları özyinelemeli olarak aynı\n // kurallardan geçer.\n const COMPOSITES = new Set([\"OR\", \"AND\", \"NOT\"]);\n\n if (!where) return;\n // Fragment bir kolon haritası DEĞİLDİR (FR-018): içeriği SQL'dir, kolon\n // doğrulaması ona uygulanamaz. Değerleri zaten bound gidiyor.\n if (isSqlFragment(where)) return;\n for (const [col, cond] of Object.entries(where)) {\n // Bileşim anahtarları (FR-007) kolon DEĞİLDİR: dalları aynı kurallardan\n // özyinelemeli geçer, ama kendileri operatör kontrolüne girmez.\n if (COMPOSITES.has(col)) {\n const branches = col === \"NOT\" ? [cond] : cond;\n if (!Array.isArray(branches) && col !== \"NOT\") {\n throw new Error(`${caller}(${table}): where.${col} bir dizi olmalı`);\n }\n for (const b of branches as unknown[]) {\n if (b === null || typeof b !== \"object\") {\n throw new Error(`${caller}(${table}): where.${col} dalları filtre nesnesi olmalı`);\n }\n assertUsableFilter(caller, table, b as Record<string, unknown>);\n }\n continue;\n }\n // `has` de kolon DEĞİLDİR: anahtarları İLİŞKİ adları, değerleri BİR TABLO\n // ÖTESİNİN filtresi. İç filtre aynı kurallardan geçiyor — `has` ikinci bir\n // filtre dili değil, aynı dilin bir tablo ötesi.\n //\n // İlişki ADI burada doğrulanMIYOR: grafiği yalnız motor tanıyor (ve tip,\n // derleme anında). Guard'ın onu bilmesi ilişki grafiğinin İKİNCİ bir\n // yorumcusu demekti — `buildRelations`'ın yorumunun adıyla yasakladığı şey.\n if (col === \"has\") {\n if (cond === null || typeof cond !== \"object\" || Array.isArray(cond)) {\n throw new Error(`${caller}(${table}): where.has bir ilişki haritası olmalı ({ <ilişki>: { … } })`);\n }\n for (const [rel, inner] of Object.entries(cond as Record<string, unknown>)) {\n if (inner === null || typeof inner !== \"object\" || Array.isArray(inner)) {\n throw new Error(`${caller}(${table}): where.has.${rel} bir filtre nesnesi olmalı`);\n }\n assertUsableFilter(caller, table, inner as Record<string, unknown>);\n }\n continue;\n }\n if (cond === undefined) {\n throw new Error(\n `${caller}(${table}): where.${col} değeri undefined — bu bir filtre değeri değil. ` +\n `Bağlanınca NULL olur ve '= NULL' hiçbir satıra uymaz, yani sorgu sessizce ` +\n `boş sonuç dönerdi. Değer yoksa anahtarı filtreye hiç koymayın.`,\n );\n }\n if (cond === null || typeof cond !== \"object\" || Array.isArray(cond)) continue;\n // `col()` ürünü bir DEĞER'dir, operatör nesnesi değil (FR-011). Ayırt\n // edilmezse `{ $col: \"x\" }` bir operatör haritası sanılır ve \"bilinmeyen\n // operatör $col\" diye reddedilirdi.\n if (isColRef(cond)) continue;\n\n const entries = Object.entries(cond as Record<string, unknown>);\n if (entries.length === 0) {\n throw new Error(\n `${caller}(${table}): where.${col} boş bir operatör nesnesi ({}) — hiçbir koşul ` +\n `üretmez, yani bu alan filtreden sessizce DÜŞERDİ. Koşul kurulmayacaksa ` +\n `anahtarı filtreye hiç koymayın (D-21).`,\n );\n }\n for (const [op, v] of entries) {\n if (op === \"in\") {\n if (!Array.isArray(v)) throw new Error(`${caller}(${table}): where.${col}.in bir dizi olmalı`);\n if (v.some((x) => x === undefined)) {\n throw new Error(\n `${caller}(${table}): where.${col}.in listesinde undefined var — sessizce NULL'a ` +\n `bağlanır ve o eleman hiçbir satırla eşleşmez. Listeyi kurarken eleyin.`,\n );\n }\n continue;\n }\n // Sağ tarafta kolon durabilir: `{ total: { gt: col(\"amount_paid\") } }`.\n // Değer kontrolleri (undefined) ona da uygulanır, ama `in` gibi şekil\n // kontrolleri değil — o dal aşağıda zaten ayrı.\n if (REFUSED_OPS[op] !== undefined) {\n // Bilinmeyen değil — BİLİNEREK reddedilen. Hata çalışan yazımı söylüyor.\n throw new Error(`${caller}(${table}): where.${col}.${op} bu filtre dilinde yok — ${REFUSED_OPS[op]}`);\n }\n if (!KNOWN_OPS.has(op)) {\n throw new Error(\n `${caller}(${table}): where.${col} bilinmeyen operatör \"${op}\" (gt/gte/lt/lte/neq/in/contains/icontains/startsWith/endsWith/isNull)`,\n );\n }\n if (v === undefined) {\n throw new Error(\n `${caller}(${table}): where.${col}.${op} değeri undefined — karşılaştırmanın ` +\n `sağ tarafı NULL olur ve sonuç hiçbir satıra uymaz. Koşulu kurmayın.`,\n );\n }\n }\n }\n}\n\n/**\n * Refuse a write whose value never arrived.\n *\n * `{ title: req.body.title }` with no `title` in the body bound NULL and\n * answered 200 — the column was ERASED. `null` is untouched, and the difference\n * is the whole point: null is an author SAYING \"empty this column\"; undefined is\n * nobody saying anything.\n */\nexport function assertUsableWriteValues(\n caller: string,\n table: string,\n cols: readonly string[],\n data: Record<string, unknown>,\n): void {\n for (const c of cols) {\n if (data[c] === undefined) {\n throw new Error(\n `${caller}(${table}): \"${c}\" değeri undefined — bu bir yazma değeri değil. ` +\n `Kolonu boşaltmak istiyorsan null yaz; kolonu değiştirmek istemiyorsan nesneye hiç koyma ` +\n `(bir eksik istek alanı sessizce NULL yazıyordu — FR-016).`,\n );\n }\n }\n}\n","/**\n * tx-plan.ts — `Database.$transaction()` as a PLAN, not a pinned session.\n *\n * A transaction used to be a conversation: BEGIN, then one network round trip\n * per operation, then COMMIT. Each of those round trips cost ~4 ms and, because\n * the pooler runs in transaction mode, an open transaction pinned a Postgres\n * backend for the whole conversation. A 121-operation statement upload pinned\n * one backend for ~490 ms.\n *\n * So the callback no longer TALKS to the database. It DESCRIBES what should\n * happen; the description is serialised and sent once; the broker runs the whole\n * thing inside one transaction and answers once. Committing on return and\n * rolling back on throw is unchanged — that is the only property tenant code\n * actually asked for.\n *\n * The consequences, stated plainly, because they are the whole design:\n *\n * - The callback is SYNCHRONOUS. There is nothing to await: no statement has\n * run yet when it returns. `async` on the callback and `await` inside it are\n * both compile errors (see {@link TxPlan} and {@link NotAwaitable}).\n * - `insert()` does not hand back a row, it hands back {@link TxRows}. Reading\n * a field requires `.expectOne(err)` first, which makes \"what if the row\n * isn't there\" a question you cannot route around: it is the argument.\n * - A field read from a row is a {@link Ref} — a PROMISE OF A VALUE THE SERVER\n * WILL PRODUCE, not the value. It can be written into a later operation and\n * it can be returned from the callback (it is substituted for the real value\n * before `transaction()` resolves). It cannot be branched on. See the\n * \"Truthiness\" note below — this is the sharp edge of the whole design.\n * - Control flow that needs a real value must move OUT of the callback: read\n * before the transaction, or express the condition as a guard\n * (`updateWhere({ id, accepted_at: null }, …).expectOne(new Conflict(…))`)\n * which the server evaluates and which rolls the whole plan back.\n *\n * # Truthiness — the hole this file CANNOT close\n *\n * JavaScript does not let a Proxy trap truthiness. `if (ref)` takes the true\n * branch, always, for every Ref, and no `get` handler ever runs. `tsc` is silent\n * because a Ref is a perfectly good object. So:\n *\n * const pot = tx.tables.pots.select({ id }, { limit: 1 }).expectOne(e);\n * if (!pot.balance) { … } // ← ALWAYS false. Silently wrong data.\n *\n * What this file does close: coercion (`Symbol.toPrimitive`/`valueOf`/\n * `toString`), awaiting (`then` is a callable member with a non-thenable\n * signature, which is a *compile* error), serialisation (`toJSON`), and nesting\n * a Ref inside a literal value where the server would store it as data. What it\n * cannot close is a bare truthiness test. The real defence is the build-time\n * static analysis (`tx_analysis.js`, phase P4); until that ships, this hole is\n * open and this comment is the only warning.\n *\n * # Wire contract\n *\n * The JSON this file emits is consumed by\n * the plan executor in `engine/db.ts`. That executor rejects\n * unknown fields at every level, so an op carries EXACTLY the fields its kind\n * takes. Everything here that looks like a needless restriction is one of the\n * server's rules made visible early:\n *\n * - `$ref` only points BACKWARDS, and only at an op statically known to yield\n * at most one row (insert, or a `one`/`atMost 1` guard, or `select limit 1`).\n * `.expectOne()` is what this file uses to satisfy that, always.\n * - `$expr` is a closed set: `inc`/`dec` (update only — they read the column's\n * current value) and `now()`.\n * - `update`/`delete` require a `where`; `insert` refuses one.\n * - `insertMany` rows must all set the same columns.\n * - ≤1000 ops, ≤5000 rows per insertMany, ≤8 MiB of JSON.\n *\n * Column keys are emitted SORTED, so the same callback always produces byte-\n * identical JSON. That is what lets the Go decoder be locked to golden files\n * this SDK emits (`testdata/tx_plan_golden/`).\n */\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\n/**\n * A plan handle was used as if it were a value: awaited, coerced to a string or\n * number, serialised, or nested inside another value.\n *\n * Thrown while the callback is still BUILDING the plan, so nothing has been sent\n * and nothing has been written.\n */\n// TİP-ONLY, ve döngü kasıtlı: `typed-db.ts` bu dosyadan tip alıyor, bu dosya\n// ondan `WhereOp` alıyor. Çalışma zamanında hiçbir şey ithal edilmiyor (import\n// type), yani modül döngüsü yok — paylaşılan olan şey TEK FİLTRE DİLİ, ve onu\n// iki yerde ayrı ayrı tanımlamak bu run'ın kapattığı \"iki yazım\"ın tipteki\n// hâli olurdu.\nimport type { WhereOpWith, ColRefOf, HasOnly } from \"./typed-db.js\";\nimport { isColRef, isSqlFragment, brandRef } from \"./input-guards.js\";\n\nexport class TxRefError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"TxRefError\";\n }\n}\n\n/**\n * The plan the callback described cannot be sent: it breaks a rule the server\n * would reject, and rejecting it here names the line that wrote it instead of\n * returning a 400 about an op index.\n */\nexport class TxPlanError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"TxPlanError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Wire types — mirror the plan executor in `engine/db.ts` exactly.\n// ---------------------------------------------------------------------------\n\n/** A backwards reference to an earlier op's single-row result. */\nexport interface TxWireRef {\n $ref: { op: number; field: string };\n}\n\n/** A call from the server's closed function set. */\nexport interface TxWireExpr {\n $expr: { fn: \"inc\" | \"dec\"; by: number | string } | { fn: \"now\" };\n}\n\n/** One value in a `values`/`set`/`where` map: a literal, a `$ref` or a `$expr`. */\nexport type TxWireValue = TxWireRef | TxWireExpr | unknown;\n\n/** The tenant's declared expectation about an op's row count. `slot` indexes the\n * client-side error table — the error OBJECT never travels. */\nexport interface TxWireGuard {\n kind: \"one\" | \"none\" | \"atLeast\" | \"atMost\";\n n: number;\n slot: number;\n}\n\n/** One operation in the wire plan. Fields are omitted, never null: the decoder\n * rejects a field that does not belong to the op's kind. */\nexport interface TxWireOp {\n /** upsert and insertMany: the columns Postgres matches on. */\n onConflict?: readonly string[];\n /** insertMany only: what a collision does. Absent means no ON CONFLICT clause\n * at all, which is what every insertMany did before this option existed. */\n action?: \"ignore\" | \"update\";\n op: \"insert\" | \"insertMany\" | \"upsert\" | \"update\" | \"delete\" | \"select\";\n table: string;\n values?: Record<string, TxWireValue>;\n rows?: Record<string, TxWireValue>[];\n set?: Record<string, TxWireValue>;\n where?: Record<string, TxWireValue>;\n limit?: number;\n lock?: \"update\";\n guard?: TxWireGuard;\n}\n\n/** The plan the engine executes on the request's own transaction. */\nexport interface TxPlanBody {\n ops: TxWireOp[];\n}\n\n/** One op's outcome, positionally matched to the plan's ops. */\nexport interface TxPlanOpResult {\n rows: Record<string, unknown>[];\n rows_affected: number;\n}\n\n/** One result per op, in plan order. */\nexport interface TxPlanResponse {\n results: TxPlanOpResult[];\n}\n\n/**\n * The fields the runtime must copy from the broker's error envelope onto the\n * rejection it throws out of {@link DBClient.txPlan}.\n *\n * `slot` is the whole point: on a guard failure the server answers with the\n * INDEX of the expectation that did not hold, never with an error message of its\n * own, and this SDK maps that index back to the `Error` the callback handed to\n * `.expectOne(…)`. Without `slot` a guard failure degrades to a generic 409.\n */\nexport interface TxPlanRejection {\n status?: number;\n /** `tx_plan_invalid` | `tx_guard_failed` | `tx_ref_unresolved` | a pg class. */\n error_code?: string;\n /** Present only for `tx_guard_failed`: the client-side error table index. */\n slot?: number;\n /** Present on a database error: which op failed. */\n op?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Handle types\n// ---------------------------------------------------------------------------\n\ndeclare const refBrand: unique symbol;\ndeclare const rowBrand: unique symbol;\ndeclare const rowsBrand: unique symbol;\n\n/**\n * Makes a handle a compile error to `await`.\n *\n * `then` is declared as a CALLABLE member whose signature is not `PromiseLike`,\n * which is precisely the shape TypeScript rejects: `await handle` is TS1320 and\n * `async () => handle` is TS1058. A non-callable `then` would not do it — the\n * compiler simply ignores those.\n */\nexport interface NotAwaitable {\n /** Not a promise. Nothing here has run yet; there is nothing to await. */\n then(doNotAwaitAPlanHandle: \"a transaction plan is built synchronously\"): never;\n}\n\n/**\n * A value the SERVER will produce, standing in for a column of a row this plan\n * writes or reads.\n *\n * Legal uses: write it into a later operation's `values`/`set`/`where`, or\n * return it from the callback (it is replaced by the real value before\n * `transaction()` resolves).\n *\n * Illegal, and caught: `await`, `String(ref)`, `` `${ref}` ``, `ref + 1`,\n * `JSON.stringify(ref)`, burying it inside a jsonb object.\n *\n * Illegal, and NOT caught: `if (ref)`. See the truthiness note at the top.\n */\nexport interface Ref<T> extends NotAwaitable {\n readonly [refBrand]: T;\n}\n\n/** The brand carried by a single-row handle, and the seam `Materialized` reads\n * to turn `return st` into the whole row. */\nexport interface TxRowHandle<Row> extends NotAwaitable {\n readonly [rowBrand]: Row;\n}\n\n/**\n * A row this plan is known to produce exactly one of. Every property is a\n * {@link Ref}; returning the handle itself yields the whole row.\n *\n * Only `.expectOne(err)` produces one — which is the design: a row you can read\n * fields from is a row whose absence you have already answered for.\n */\nexport type TxRow<Row> = { readonly [K in keyof Row]: Ref<Row[K]> } & TxRowHandle<Row>;\n\n/**\n * The result of one operation, before any expectation is declared about it.\n *\n * Deliberately not a row and not a list: an operation's row count is not known\n * until the server runs it, so the only thing that can be said about it here is\n * an EXPECTATION. Declaring one is also the only way to get a readable row.\n *\n * At most one expectation per operation — the wire carries one guard per op, and\n * a second call throws rather than silently dropping the first.\n */\nexport interface TxRows<Row> extends NotAwaitable {\n readonly [rowsBrand]: Row;\n /**\n * Require exactly one row, and read it. On any other count the server rolls\n * the whole transaction back and this `error` is thrown to the caller.\n *\n * This is the only way to reach a row's fields, and the only shape a `$ref`\n * may point at.\n */\n expectOne(error: Error): TxRow<Row>;\n /** Require zero rows (e.g. \"this membership must not already exist\"). */\n expectNone(error: Error): void;\n /** Require at least `n` rows. */\n expectAtLeast(n: number, error: Error): void;\n /** Require at most `n` rows. */\n expectAtMost(n: number, error: Error): void;\n}\n\n/** `now()` — the server's clock, usable wherever a value is. */\nexport interface TxNow extends NotAwaitable {\n readonly $expr: { fn: \"now\" };\n}\n\n/** `inc(n)` / `dec(n)` — read the column's CURRENT value and write it back\n * changed. Only meaningful in an update's `set`, which is where the types allow\n * it and where the server allows it. */\nexport interface TxColumnExpr extends NotAwaitable {\n readonly $expr: { fn: \"inc\" | \"dec\"; by: number | string };\n}\n\n/**\n * Resolve a callback's return type against what actually comes back: every\n * {@link Ref} becomes its value, every {@link TxRow} becomes its row, and\n * anything else keeps its shape.\n *\n * A {@link TxRows} resolves to an explanatory string type rather than a row\n * list: it has no single answer to give, and saying so in the type is louder\n * than a runtime throw.\n */\nexport type Materialized<T> = T extends Ref<infer U>\n ? U\n : T extends TxRowHandle<infer R>\n ? R\n : T extends TxRows<unknown>\n ? \"a TxRows cannot leave the transaction callback — read a row with .expectOne(err) first\"\n : T extends Date\n ? T\n : T extends object\n ? { [K in keyof T]: Materialized<T[K]> }\n : T;\n\n// ---------------------------------------------------------------------------\n// Author-facing value types\n// ---------------------------------------------------------------------------\n\n/** A value written by an INSERT: a literal, an earlier row's field, or `now()`.\n * `inc`/`dec` are absent on purpose — they read a current value, and an inserted\n * row has none. */\nexport type TxInsertValue<V> = V | Ref<V> | TxNow;\n\n/** A value written by an UPDATE's `set`: everything an insert takes, plus the\n * read-modify-write expressions. */\n/**\n * TEK KURAL: ifade tutamağı yalnız sayısal-benzeri kolonlarda.\n *\n * Bu tip KOŞULSUZDU ve doğrudan yolun `SetValue<V>`'si koşulluydu, yani aynı\n * nesne için İKİ tip kuralı vardı: `tx.tables.todos.updateWhere({id}, { done:\n * increment(1) })` (boolean kolon!) DERLENİYOR, `updateMany`'nin aynısı derleme\n * hatası veriyordu. Bu run'ın kapatmak için var olduğu şey \"aynı iş için iki\n * uyumsuz yazım\"dı; tip kuralı ikinci yazımın kendisi olmuştu (gözcü I6/I-1).\n */\nexport type TxSetValue<V> =\n | V\n | Ref<V>\n | TxNow\n | (NonNullable<V> extends number | string ? TxColumnExpr : never);\n\n/** An insert payload: the table's insert shape, with refs and `now()` allowed. */\nexport type TxInsertShape<Insert> = { [K in keyof Insert]: TxInsertValue<Insert[K]> };\n\n/** An update's `set`: any subset of the insert shape, with expressions allowed. */\nexport type TxSetShape<Insert> = { [K in keyof Insert]?: TxSetValue<Insert[K]> };\n\n/**\n * A filter. Every entry is an equality test and they are AND-ed; a `null`\n * becomes `IS NULL`, which is what makes `{ accepted_at: null }` a usable\n * \"not yet accepted\" guard rather than a clause that matches nothing.\n */\n/**\n * Plan filtresinin tipi — `WhereFilter<Row>` ile AYNI sözlük, artı `Ref`.\n *\n * Eskiden yalnız eşitlikti (`Row[K] | Ref<Row[K]>`), ve iki şeye mal oluyordu:\n * FR-014'ün amiral deseni (`{ balance: { gte: amount } }`) `$transaction`\n * İÇİNDE yazılamıyordu — koşullu bir yazmayı plana koyamayan yazar `$query`'ye\n * düşüyordu — ve motor tarafında tip atlandığında aynı nesne SESSİZCE parametre\n * olarak bağlanıyordu.\n *\n * `Ref` fazladan üye ve öyle kalmalı: bir plan filtresi ÖNCEKİ bir işlemin\n * döndürdüğü değere bakabilir, `findMany` bakamaz — plan dışında böyle bir\n * \"önceki işlem\" yok.\n */\ntype TxWhereField<Row, K extends keyof Row> = WhereOpWith<\n Row[K],\n // `Ref` KOLON REFERANSININ YANINDA duruyor, `V`'nin içinde DEĞİL: `V`'ye\n // eklenseydi `TextOps<V>`'nin `V extends string` sorusu HAYIR olur ve\n // `contains`/`startsWith` sessizce kaybolurdu (ölçüldü).\n ColRefOf<Row, Row[K]> | Ref<Row[K]>\n>;\n\nexport type TxWhere<Row, Rels = unknown> = {\n [K in keyof Row]?: TxWhereField<Row, K>;\n} & {\n OR?: TxWhere<Row, Rels>[];\n AND?: TxWhere<Row, Rels>[];\n NOT?: TxWhere<Row, Rels>;\n} & HasOnly<Rels>;\n\n/** Options for a plan `select`. */\nexport interface TxSelectOptions {\n /** Cap the rows read. */\n limit?: number;\n /** Take a real `FOR UPDATE` row lock for the rest of the transaction. */\n lock?: \"update\";\n}\n\n/** One table, as the plan sees it. */\nexport interface TxTable<Row, Insert, Rels = unknown> {\n /** Insert one row. Returns a handle — call `.expectOne(err)` to read fields. */\n insert(values: TxInsertShape<Insert>): TxRows<Row>;\n /**\n * Insert many rows in ONE statement. Every row must set the same columns\n * (a row that omits one would silently take the column's default).\n *\n * An empty list writes nothing and sends nothing.\n */\n /**\n * Insert many rows in ONE statement, optionally choosing what a collision does.\n *\n * Without `opts` this is a plain multi-row INSERT and a collision aborts the\n * transaction — the behaviour every call had before the option existed.\n *\n * `action: \"ignore\"` emits `ON CONFLICT DO NOTHING`, which is how \"insert the\n * ones that are new\" becomes one round-trip instead of one per row with a\n * 23505 caught around each. **The returned rows are the ones actually\n * INSERTED**: a row that collided is skipped, so it is absent from the result\n * — Postgres does not return what it did not write.\n *\n * `action: \"update\"` emits `ON CONFLICT DO UPDATE`, setting every non-conflict\n * column from the incoming row, and every row comes back.\n */\n insertMany(\n rows: readonly TxInsertShape<Insert>[],\n opts?: {\n onConflict: readonly Extract<keyof Row, string>[];\n action?: \"ignore\" | \"update\";\n },\n ): TxRows<Row>;\n /**\n * Satırı yaz, `onConflict` kolonlarında çakışırsa üzerine yaz — planın\n * savepoint'i içinde, `Database.<şema>.<tablo>.put()` ile AYNI anlamda.\n *\n * Adı bilerek aynı: aynı iş için transaction içinde ve dışında iki farklı\n * yazım, bu run'ın kapatmak için var olduğu şeydir (P1). TEL şekli\n * (`op: \"upsert\"`) değişmedi — o iç sözleşme, yazarın gördüğü ad değil.\n *\n * Bir operasyon olmasının sebebi: alternatifi burada yazılamaz — başarısız\n * bir insert tüm transaction'ı abort eder, yani \"dene, sonra geri düş\" iki\n * plan adımı olamaz.\n */\n put(\n values: TxInsertShape<Insert>,\n options: { onConflict: readonly Extract<keyof Row, string>[] },\n ): TxRows<Row>;\n /**\n * Update every row matching `where`. The filter comes first because it is the\n * dangerous half: an update whose `where` you got wrong rewrites rows you\n * never looked at. The server refuses an update with no `where` at all.\n */\n updateWhere(where: TxWhere<Row, Rels>, set: TxSetShape<Insert>): TxRows<Row>;\n /** Delete every row matching `where`. The server refuses an unfiltered delete. */\n deleteWhere(where: TxWhere<Row, Rels>): TxRows<Row>;\n /** Read rows, optionally locking them for the rest of the transaction. */\n select(where?: TxWhere<Row, Rels>, options?: TxSelectOptions): TxRows<Row>;\n}\n\n/**\n * The handle a transaction callback receives.\n *\n * It carries tables and nothing else: no `query`, no `findById`, no `asService`.\n * A read whose value the plan does not write belongs OUTSIDE the transaction,\n * where it costs one round trip and can be branched on like an ordinary value.\n */\nexport interface TxPlanHandle<TTables> {\n /**\n * @deprecated `tx.public` kullanın. Bu ad public'in takma adı olarak DURUYOR\n * (göç notu onu öğretiyor ve her mevcut çağrı onu kullanıyor), ama ARTIK\n * ÖĞRETİLMİYOR: doğrudan yüzeyde `Database.tables` FR-001 ile kaldırıldı, ve\n * plan yüzeyinin onu öğretmeye devam etmesi yazarı bir yüzeyde çalışıp\n * diğerinde derlenmeyen bir yazıma alıştırıyordu (gözcü M-6).\n */\n tables: TTables;\n}\n\n// ---------------------------------------------------------------------------\n// Runtime — expressions\n// ---------------------------------------------------------------------------\n\n/** Internal marker read by the serialiser. */\nconst EXPR = Symbol.for(\"palbase.tx.expr\");\nconst REF = Symbol.for(\"palbase.tx.ref\");\nconst ROW = Symbol.for(\"palbase.tx.row\");\nconst ROWS = Symbol.for(\"palbase.tx.rows\");\n\ninterface RefDescriptor {\n op: number;\n field: string;\n}\n\n/** Property reads that must not silently produce a value on a plan handle.\n * `then` is the one that matters for correctness (it makes `await` a compile\n * error AND stops a handle from being adopted by a promise); the rest turn a\n * silent wrong answer — `\"[object Object]\"`, `NaN`, `{}` — into a thrown one. */\nconst TRAPPED_PROPS: readonly (string | symbol)[] = [\n \"then\",\n \"valueOf\",\n \"toString\",\n \"toJSON\",\n Symbol.toPrimitive,\n];\n\nfunction trap(prop: string | symbol, what: string, hint: string): never {\n const name = typeof prop === \"symbol\" ? prop.description ?? String(prop) : prop;\n throw new TxRefError(\n `${what} was used as a value (via \\`${name}\\`). Nothing in a transaction ` +\n `callback has run yet, so there is no value to read. ${hint}`,\n );\n}\n\n/** The server's `now()`. */\nexport function now(): TxNow {\n return makeExpr({ fn: \"now\" }) as TxNow;\n}\n\n/** Add `by` to the column's current value. Only valid in an update's `set`. */\nexport function increment(by: number | string): TxColumnExpr {\n assertAmount(by, \"increment\");\n return makeExpr({ fn: \"inc\", by }) as TxColumnExpr;\n}\n\n/**\n * `increment`'in eski adı. AYNI fabrikadır — iki uygulama değil, iki ad.\n *\n * @deprecated `increment()` kullanın; bu ad geriye dönük uyumluluk için duruyor.\n */\nexport const inc = increment;\n\n/** Subtract `by` from the column's current value. Only valid in an update's `set`. */\nexport function decrement(by: number | string): TxColumnExpr {\n assertAmount(by, \"decrement\");\n return makeExpr({ fn: \"dec\", by }) as TxColumnExpr;\n}\n\n/**\n * `decrement`'in eski adı. AYNI fabrikadır.\n *\n * @deprecated `decrement()` kullanın.\n */\nexport const dec = decrement;\n\n/**\n * Miktarın taşınabilir olduğunu doğrular.\n *\n * String kabul edilir ve KASITLIDIR (D-007): `numeric` bir kolonda miktar JS\n * `number`'a uğrarsa 0.1 + 0.2 orada 0.30000000000000004'tür ve para hesabı\n * sessizce kayar. String hem burada hem `renderValue`'da bound parametre olarak\n * taşınır — Postgres onu tam ondalık olarak okur.\n */\nfunction assertAmount(by: number | string, fn: string): void {\n if (typeof by === \"string\") {\n // Metin SQL'e girmiyor (bound parametre), ama şekli yine de doğrulanır:\n // \"abc\" bind edilirse hata Postgres'ten gelir, çağıranın diliyle değil.\n if (!/^-?\\d+(\\.\\d+)?$/.test(by)) {\n throw new TxPlanError(\n `${fn}() ondalık bir sayı metni bekliyor, \"${by}\" aldı — kabul edilen biçim: \"12\", \"-12\", \"12.50\"`,\n );\n }\n } else if (typeof by !== \"number\" || !Number.isFinite(by)) {\n // JSON has no NaN/Infinity: they would serialise to `null` and the server\n // would reject the plan with an unhelpful decode error.\n throw new TxPlanError(`${fn}() needs a finite number, got ${String(by)}`);\n }\n // NEGATİF MİKTAR REDDEDİLİR — ve bu şekil kontrolünden çok daha fazlası.\n // `decrement(\"-5\")` `SET c = c - $1` derliyordu, `$1 = -5`, yani beş EKLİYORDU.\n // FR-014'ün amiral deseninde (`where: { balance: { gte: amount } }`) miktar\n // istek gövdesinden geliyorsa `balance >= -5` her zaman doğru: hesap\n // KREDİLENDİRİLİR ve çağrı bunu 1 satırla \"başarı\" diye raporlar. Guard\n // okunduğunda işaret kontrol edilmiş gibi duruyordu (gözcü I9, ölçüldü).\n const negative = typeof by === \"string\" ? by.trimStart().startsWith(\"-\") : by < 0;\n if (negative) {\n const other = fn === \"increment\" ? \"decrement\" : \"increment\";\n throw new TxPlanError(\n `${fn}() negatif miktar almaz (\"${String(by)}\"). Ters yön için ${other}() kullanın — ` +\n `işaretin miktarda saklanması, yönü okuyan hiçbir kod tarafından görülmezdi.`,\n );\n }\n}\n\n/**\n * Bir değer `increment()`/`decrement()` ürünü mü? Öyleyse tel şekli.\n *\n * DOĞRUDAN yol (`updateMany`) da bu ifadeyi anlamak zorunda: aynı nesnenin iki\n * yerde çalışması, \"kolona ekle\"nin tek yazımı olmasının şartı (P1).\n */\nexport function columnExprOf(v: unknown): TxWireExpr[\"$expr\"] | null {\n return exprOf(v);\n}\n\nfunction makeExpr(expr: TxWireExpr[\"$expr\"]): unknown {\n return new Proxy(\n { [EXPR]: expr } as Record<string | symbol, unknown>,\n {\n get(target, prop) {\n if (prop === EXPR) return target[EXPR];\n if (TRAPPED_PROPS.includes(prop)) {\n trap(prop, \"A plan expression\", \"Write it into an operation instead.\");\n }\n return undefined;\n },\n },\n );\n}\n\n// ---------------------------------------------------------------------------\n// Runtime — refs and row handles\n// ---------------------------------------------------------------------------\n\nfunction makeRef(op: number, field: string): unknown {\n const target: Record<string | symbol, unknown> = { [REF]: { op, field } satisfies RefDescriptor };\n return new Proxy(target, {\n get(t, prop) {\n if (prop === REF) return t[REF];\n if (TRAPPED_PROPS.includes(prop)) {\n trap(\n prop,\n `\\`${field}\\` of a row this transaction has not written yet`,\n \"Pass it to another operation in the same plan, or return it from the \" +\n \"callback and read it after `transaction()` resolves.\",\n );\n }\n return undefined;\n },\n });\n}\n\nfunction makeRowHandle(op: number): unknown {\n const target: Record<string | symbol, unknown> = { [ROW]: op };\n return new Proxy(target, {\n get(t, prop) {\n if (prop === ROW) return t[ROW];\n if (TRAPPED_PROPS.includes(prop)) {\n trap(\n prop,\n \"A row this transaction has not written yet\",\n \"Read one of its columns to reference it, or return the row from the \" +\n \"callback and read it after `transaction()` resolves.\",\n );\n }\n if (typeof prop === \"symbol\") return undefined;\n return makeRef(op, prop);\n },\n });\n}\n\nfunction refDescriptor(v: unknown): RefDescriptor | null {\n if (typeof v !== \"object\" || v === null) return null;\n const d = (v as Record<symbol, unknown>)[REF];\n return isRefDescriptor(d) ? d : null;\n}\n\nfunction isRefDescriptor(d: unknown): d is RefDescriptor {\n return (\n typeof d === \"object\" &&\n d !== null &&\n typeof (d as RefDescriptor).op === \"number\" &&\n typeof (d as RefDescriptor).field === \"string\"\n );\n}\n\nfunction rowOpIndex(v: unknown): number | null {\n if (typeof v !== \"object\" || v === null) return null;\n const op = (v as Record<symbol, unknown>)[ROW];\n return typeof op === \"number\" ? op : null;\n}\n\nfunction exprOf(v: unknown): TxWireExpr[\"$expr\"] | null {\n if (typeof v !== \"object\" || v === null) return null;\n const e = (v as Record<symbol, unknown>)[EXPR];\n return typeof e === \"object\" && e !== null ? (e as TxWireExpr[\"$expr\"]) : null;\n}\n\nfunction isRowsHandle(v: unknown): boolean {\n return typeof v === \"object\" && v !== null && (v as Record<symbol, unknown>)[ROWS] !== undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Runtime — value encoding\n// ---------------------------------------------------------------------------\n\n/**\n * Encode one value of a `values`/`set`/`where` map.\n *\n * The nesting check is not defensive tidiness. The server treats `$ref` as a\n * tagged value only at the TOP of a column's value; a ref buried inside a jsonb\n * payload is just data, and would be stored as the literal object\n * `{\"$ref\":{...}}` — a write that succeeds, commits, and is wrong. So a nested\n * handle is a hard error here, where the line that wrote it is still on the\n * stack.\n */\nfunction encodeValue(value: unknown, column: string, allowColumnExpr: boolean): TxWireValue {\n const ref = refDescriptor(value);\n if (ref) return brandRef({ $ref: { op: ref.op, field: ref.field } }, \"ref\") satisfies TxWireRef;\n\n const expr = exprOf(value);\n if (expr) {\n if (expr.fn !== \"now\" && !allowColumnExpr) {\n throw new TxPlanError(\n `\\`${column}\\`: ${expr.fn}() reads the column's current value, so it is ` +\n `only valid in updateWhere(where, set).`,\n );\n }\n return { $expr: expr } satisfies TxWireExpr;\n }\n\n if (rowOpIndex(value) !== null) {\n throw new TxPlanError(\n `\\`${column}\\`: a row handle is not a value. Read the column you meant ` +\n `(e.g. \\`row.id\\`).`,\n );\n }\n if (isRowsHandle(value)) {\n throw new TxPlanError(\n `\\`${column}\\`: an operation result is not a value. Declare an expectation ` +\n `first (\\`.expectOne(err)\\`) and read a column from the row.`,\n );\n }\n\n assertNoNestedHandles(value, column);\n return value;\n}\n\n/**\n * Encode a FİLTRE — `values`/`set` ile AYNI kodlayıcı değil, ve olmaması bir\n * düzeltme.\n *\n * `encodeValue` bir `$ref`'i yalnız kolonun EN ÜSTÜNDE kabul ediyor, çünkü bir\n * insert değerinin İÇİNE gömülü ref sunucuda çözülmez, literal JSON olarak\n * SAKLANIR — \"başarıyla commit olan ve yanlış olan bir yazma\". O kural DEĞER\n * yolu için doğru.\n *\n * FİLTREDE öyle değil: motorun `resolveRefsDeep`'i bir ref'i filtrenin HER\n * yerinde çözüyor — operatörün sağında, `OR`/`AND`/`NOT` dallarının içinde. Ama\n * kodlayıcı hâlâ değer kuralını uyguluyordu, yani üç katman üç farklı cevap\n * veriyordu (gözcü C-2): tip kabul, motor çözüyor, kodlayıcı REDDEDİYOR — ve\n * reddin metni değer-yuvalama vakasını anlatıyor, filtrede olmayan bir şeyi.\n *\n * İFADE TUTAMAĞI ve SATIR TUTAMAĞI filtrede HÂLÂ reddediliyor: onları motor\n * filtrede çözmüyor ve çözmemeli — `increment()` bir yazma ifadesi, bir\n * karşılaştırma değil.\n */\nfunction encodeFilterValue(value: unknown, column: string): unknown {\n const ref = refDescriptor(value);\n if (ref) return brandRef({ $ref: { op: ref.op, field: ref.field } }, \"ref\") satisfies TxWireRef;\n\n const expr = exprOf(value);\n if (expr) {\n throw new TxPlanError(\n `\\`${column}\\`: ${expr.fn}() bir YAZMA ifadesi, karşılaştırma değil — ` +\n `filtrede kullanılamaz. Kolonu bir değerle ya da col() ile karşılaştırın.`,\n );\n }\n if (rowOpIndex(value) !== null) {\n throw new TxPlanError(\n `\\`${column}\\`: a row handle is not a value. Read the column you meant (e.g. \\`row.id\\`).`,\n );\n }\n if (isRowsHandle(value)) {\n throw new TxPlanError(\n `\\`${column}\\`: an operation result is not a value. Declare an expectation ` +\n `first (\\`.expectOne(err)\\`) and read a column from the row.`,\n );\n }\n if (Array.isArray(value)) return value.map((v) => encodeFilterValue(v, column));\n // `col()` ve `sqlFragment` OLDUĞU GİBİ geçer: markaları süreç içinde korunur\n // ve derleyici ikisini de kendi tanıyor.\n if (value !== null && typeof value === \"object\" && !(value instanceof Date) && !isColRef(value) && !isSqlFragment(value)) {\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n out[k] = encodeFilterValue(v, column);\n }\n return out;\n }\n return value;\n}\n\n/** Filtre haritası — anahtarlar SIRALI (aynı geri çağrı bayt-özdeş JSON üretsin). */\nfunction encodeFilterMap(map: Record<string, unknown>): Record<string, TxWireValue> {\n const out: Record<string, TxWireValue> = {};\n for (const key of Object.keys(map).sort()) {\n const value = map[key];\n if (value === undefined) continue;\n out[key] = encodeFilterValue(value, key) as TxWireValue;\n }\n return out;\n}\n\nfunction assertNoNestedHandles(value: unknown, column: string): void {\n if (typeof value !== \"object\" || value === null) return;\n if (value instanceof Date) return;\n if (refDescriptor(value) || exprOf(value) || rowOpIndex(value) !== null || isRowsHandle(value)) {\n throw new TxPlanError(\n `\\`${column}\\`: a plan handle is nested inside a value. The server would ` +\n `store it as literal JSON, not resolve it. Put the reference directly in ` +\n `the column.`,\n );\n }\n if (Array.isArray(value)) {\n for (const item of value) assertNoNestedHandles(item, column);\n return;\n }\n for (const item of Object.values(value as Record<string, unknown>)) {\n assertNoNestedHandles(item, column);\n }\n}\n\n/**\n * Encode a column map, dropping `undefined` and emitting keys SORTED.\n *\n * Sorting is what makes the same callback produce byte-identical JSON every\n * time, which is what lets the Go decoder be locked to goldens this SDK emits.\n * Dropping `undefined` mirrors what `JSON.stringify` would do anyway, but does\n * it where the resulting column list is still checkable.\n */\nfunction encodeMap(\n map: Record<string, unknown>,\n allowColumnExpr: boolean,\n): Record<string, TxWireValue> {\n const out: Record<string, TxWireValue> = {};\n for (const key of Object.keys(map).sort()) {\n const value = map[key];\n // `undefined` ATLANIR — ve bu, doğrudan yolun ADIYLA REDDETMESİNDEN\n // bilerek ayrılıyor. Buradaki anlam \"kolon varsayılanını al\"; doğrudan\n // yolunki \"kimse bir şey söylemedi, ve bu bir yazma değil\".\n //\n // İkisi de tutarlı, ama AYNI girdiye zıt cevap veriyorlar ve doğrudan\n // yolun cevabı ölçülmüş bir olaya dayanıyor (`{ title: req.body.title }`\n // gövdede `title` yokken kolonu SESSİZCE sildi ve 200 döndü). Bu ayrışma\n // deftere D-17 olarak yazıldı ve kullanıcıya teklif edildi; sekizinci bir\n // kırıcı olduğu için onay almadan kapatılmıyor.\n if (value === undefined) continue;\n out[key] = encodeValue(value, key, allowColumnExpr);\n }\n return out;\n}\n\n// ---------------------------------------------------------------------------\n// Runtime — the builder\n// ---------------------------------------------------------------------------\n\n/** How many rows an op can produce, as far as the CLIENT can tell before it\n * runs. Only the empty `insertMany` is knowable, and knowing it is what lets a\n * doomed expectation fail on the line that declared it. */\nconst SKIPPED_OP = -1;\n\nclass TxRowsImpl<Row> implements TxRows<Row> {\n // Present so `isRowsHandle` recognises the object; never read for its value.\n readonly [ROWS] = true;\n // Phantom: the type brand that stops a bare object passing as a TxRows. Never\n // present at run time, which is what `declare` says.\n declare readonly [rowsBrand]: Row;\n private guarded = false;\n\n constructor(\n private readonly builder: TxPlanBuilder,\n private readonly opIndex: number,\n private readonly what: string,\n ) {}\n\n // The type-level `await` guard made real: TS rejects `await rows` at compile\n // time, and reaching this means someone called `.then(...)` by hand.\n then(): never {\n throw new TxRefError(\n `${this.what} cannot be awaited: a transaction callback builds a plan, it ` +\n `does not run statements. Remove the \\`await\\`.`,\n );\n }\n\n expectOne(error: Error): TxRow<Row> {\n this.declareGuard(\"one\", 1, error);\n if (this.opIndex === SKIPPED_OP) throw error;\n return makeRowHandle(this.opIndex) as TxRow<Row>;\n }\n\n expectNone(error: Error): void {\n this.declareGuard(\"none\", 0, error);\n }\n\n expectAtLeast(n: number, error: Error): void {\n assertGuardCount(n, \"expectAtLeast\");\n this.declareGuard(\"atLeast\", n, error);\n if (this.opIndex === SKIPPED_OP && n > 0) throw error;\n }\n\n expectAtMost(n: number, error: Error): void {\n assertGuardCount(n, \"expectAtMost\");\n this.declareGuard(\"atMost\", n, error);\n }\n\n private declareGuard(kind: TxWireGuard[\"kind\"], n: number, error: Error): void {\n if (!(error instanceof Error)) {\n // The error object is the ONLY thing that describes this failure to the\n // caller — the server sends back an index, never a message.\n throw new TxPlanError(\n `${this.what}: an expectation needs the Error to throw when it does not ` +\n `hold (e.g. \\`.expect…(new Conflict(\"already accepted\"))\\`).`,\n );\n }\n if (this.guarded) {\n throw new TxPlanError(\n `${this.what} already has an expectation. One operation carries one ` +\n `expectation; declare the second one on its own operation.`,\n );\n }\n this.guarded = true;\n if (this.opIndex === SKIPPED_OP) return;\n this.builder.attachGuard(this.opIndex, kind, n, error);\n }\n}\n\nfunction assertGuardCount(n: number, fn: string): void {\n if (!Number.isInteger(n) || n < 0) {\n throw new TxPlanError(`${fn}(n) needs a non-negative integer, got ${String(n)}`);\n }\n}\n\n/** Bounds mirrored from the plan executor so an over-sized plan is named here rather\n * than rejected as an opaque 400 after it has crossed the network. */\nconst MAX_OPS = 1000;\nconst MAX_ROWS = 5000;\n\n/**\n * Accumulates ops and the client-side error table while the callback runs.\n *\n * Exported for the runtime and for tests that need the serialised plan without\n * a server; author code never sees it.\n */\nexport class TxPlanBuilder {\n private readonly ops: TxWireOp[] = [];\n /** Errors handed to expectations, indexed by the `slot` the server echoes. */\n private readonly slots: Error[] = [];\n\n /** The table surface handed to the callback. Untyped here; the public\n * `transaction()` signatures put the schema types on top. */\n table(name: string): TxTable<Record<string, unknown>, Record<string, unknown>> {\n return {\n insert: (values) => {\n const encoded = encodeMap(values as Record<string, unknown>, false);\n if (Object.keys(encoded).length === 0) {\n throw new TxPlanError(`${name}.insert() needs at least one column`);\n }\n return this.push({ op: \"insert\", table: name, values: encoded }, `${name}.insert()`);\n },\n\n put: (values, options) => {\n const encoded = encodeMap(values as Record<string, unknown>, false);\n if (Object.keys(encoded).length === 0) {\n throw new TxPlanError(`${name}.put() needs at least one column`);\n }\n if (options.onConflict.length === 0) {\n throw new TxPlanError(`${name}.put() needs at least one onConflict column`);\n }\n return this.push(\n { op: \"upsert\", table: name, values: encoded, onConflict: options.onConflict },\n `${name}.upsert()`,\n );\n },\n\n insertMany: (rows, opts) => {\n if (rows.length === 0) {\n // Nothing to write. Emitting an op would be a guaranteed 400 (the\n // server requires rows), and refusing outright would punish the\n // ordinary \"filtered every candidate out\" case.\n return new TxRowsImpl(this, SKIPPED_OP, `${name}.insertMany()`);\n }\n if (rows.length > MAX_ROWS) {\n throw new TxPlanError(\n `${name}.insertMany() has ${rows.length} rows; the limit is ${MAX_ROWS}. ` +\n `Split the write across requests.`,\n );\n }\n const encoded = rows.map((row) => encodeMap(row as Record<string, unknown>, false));\n assertUniformRows(encoded, name);\n if (opts !== undefined && opts.onConflict.length === 0) {\n throw new TxPlanError(\n `${name}.insertMany() was given a conflict action with no onConflict ` +\n `columns. Postgres matches a collision on columns, so name them.`,\n );\n }\n return this.push(\n {\n op: \"insertMany\",\n table: name,\n rows: encoded,\n // Omitted entirely when no options were given, so the op a plain\n // insertMany produces is byte-identical to the one it produced\n // before this option existed.\n ...(opts !== undefined\n ? { onConflict: opts.onConflict, action: opts.action ?? \"ignore\" }\n : {}),\n },\n `${name}.insertMany()`,\n );\n },\n\n updateWhere: (where, set) => {\n const encodedWhere = encodeFilterMap(where as Record<string, unknown>);\n const encodedSet = encodeMap(set as Record<string, unknown>, true);\n if (Object.keys(encodedWhere).length === 0) {\n throw new TxPlanError(\n `${name}.updateWhere() needs a filter. An update with no filter ` +\n `rewrites the whole table.`,\n );\n }\n if (Object.keys(encodedSet).length === 0) {\n throw new TxPlanError(`${name}.updateWhere() needs at least one column to set`);\n }\n return this.push(\n { op: \"update\", table: name, set: encodedSet, where: encodedWhere },\n `${name}.updateWhere()`,\n );\n },\n\n deleteWhere: (where) => {\n const encodedWhere = encodeFilterMap(where as Record<string, unknown>);\n if (Object.keys(encodedWhere).length === 0) {\n throw new TxPlanError(\n `${name}.deleteWhere() needs a filter. A delete with no filter empties ` +\n `the table.`,\n );\n }\n return this.push(\n { op: \"delete\", table: name, where: encodedWhere },\n `${name}.deleteWhere()`,\n );\n },\n\n select: (where, options) => {\n const op: TxWireOp = { op: \"select\", table: name };\n const encodedWhere = encodeFilterMap((where ?? {}) as Record<string, unknown>);\n if (Object.keys(encodedWhere).length > 0) op.where = encodedWhere;\n if (options?.limit !== undefined) {\n if (!Number.isInteger(options.limit) || options.limit < 0) {\n throw new TxPlanError(\n `${name}.select(): limit needs a non-negative integer, got ${String(options.limit)}`,\n );\n }\n op.limit = options.limit;\n }\n if (options?.lock !== undefined) op.lock = options.lock;\n return this.push(op, `${name}.select()`);\n },\n };\n }\n\n private push(op: TxWireOp, what: string): TxRows<Record<string, unknown>> {\n if (this.ops.length >= MAX_OPS) {\n throw new TxPlanError(\n `this transaction has ${MAX_OPS} operations, which is the limit. Use ` +\n `insertMany() for bulk writes, or split the work across requests.`,\n );\n }\n const index = this.ops.length;\n this.ops.push(op);\n return new TxRowsImpl(this, index, what);\n }\n\n /** Attach an expectation to an op and record its error in the slot table. */\n attachGuard(opIndex: number, kind: TxWireGuard[\"kind\"], n: number, error: Error): void {\n const op = this.ops[opIndex];\n // Unreachable: the index came from `push`. A loud failure beats a silently\n // unguarded write if that ever stops being true.\n if (!op) throw new TxPlanError(`internal: expectation on unknown operation ${opIndex}`);\n const slot = this.slots.length;\n this.slots.push(error);\n op.guard = { kind, n, slot };\n }\n\n /** The serialisable plan. Empty when the callback described no writes. */\n body(): TxPlanBody {\n return { ops: this.ops };\n }\n\n /** The error the server's `slot` selects, or `null` when it names one this\n * plan never declared (a server/client disagreement, not a tenant error). */\n errorForSlot(slot: number): Error | null {\n return this.slots[slot] ?? null;\n }\n}\n\nfunction assertUniformRows(rows: Record<string, TxWireValue>[], table: string): void {\n const first = rows[0];\n if (!first) return;\n const want = Object.keys(first);\n const wantKey = want.join(\",\");\n for (let i = 1; i < rows.length; i++) {\n const got = Object.keys(rows[i] as Record<string, TxWireValue>);\n if (got.join(\",\") !== wantKey) {\n // One statement, one column list. A ragged row would take the DB default\n // for the column it omitted — a write that succeeds and is wrong.\n throw new TxPlanError(\n `${table}.insertMany(): every row must set the same columns. Row 0 sets ` +\n `[${want.join(\", \")}] but row ${i} sets [${got.join(\", \")}]. ` +\n `(A property set to \\`undefined\\` counts as absent — use \\`null\\`.)`,\n );\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Runtime — materialisation\n// ---------------------------------------------------------------------------\n\n/**\n * Replace every handle in the callback's return value with what the server\n * actually produced.\n *\n * Walks arrays and PLAIN objects only. Class instances (a Date, a Zod schema, a\n * domain object) are returned untouched — recursing into them would rebuild them\n * as bare objects, and nothing inside one can be a handle that this SDK created.\n */\nexport function materializeResult(value: unknown, results: TxPlanOpResult[]): unknown {\n const ref = refDescriptor(value);\n if (ref) {\n const row = rowOf(results, ref.op, `\\`${ref.field}\\``);\n if (!(ref.field in row)) {\n throw new TxPlanError(\n `the transaction's operation ${ref.op} returned no column \\`${ref.field}\\`.`,\n );\n }\n return row[ref.field];\n }\n\n const rowOp = rowOpIndex(value);\n if (rowOp !== null) return rowOf(results, rowOp, \"a row\");\n\n if (isRowsHandle(value)) {\n throw new TxPlanError(\n \"an operation result cannot be returned from a transaction callback: its \" +\n \"row count is not known until the plan runs. Declare an expectation \" +\n \"(`.expectOne(err)`) and return the row, or a column of it.\",\n );\n }\n\n if (Array.isArray(value)) return value.map((item) => materializeResult(item, results));\n\n if (isPlainObject(value)) {\n const out: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) out[key] = materializeResult(item, results);\n return out;\n }\n\n return value;\n}\n\nfunction rowOf(results: TxPlanOpResult[], opIndex: number, what: string): Record<string, unknown> {\n const result = results[opIndex];\n if (!result) {\n throw new TxPlanError(\n `the transaction returned no result for operation ${opIndex}, so ${what} ` +\n `cannot be read.`,\n );\n }\n const row = result.rows[0];\n if (!row) {\n // Unreachable through the public API: a handle only exists behind an\n // `expectOne`, and the server rolls back rather than answering 200 with a\n // guard unmet. Loud, because the alternative is `undefined` in tenant data.\n throw new TxPlanError(\n `the transaction's operation ${opIndex} returned no row, so ${what} cannot ` +\n `be read.`,\n );\n }\n return row;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null) return false;\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n// ---------------------------------------------------------------------------\n// Runtime — the driver\n// ---------------------------------------------------------------------------\n\n/** What {@link runTxPlan} needs from the runtime: one call, one transaction. */\nexport interface TxPlanTransport {\n txPlan(plan: TxPlanBody): Promise<TxPlanResponse>;\n}\n\n/**\n * Build the plan, send it, and resolve the callback's return value.\n *\n * A callback that throws never reaches the network: there is nothing to roll\n * back because nothing was sent. A callback that describes no writes also skips\n * the round trip entirely.\n *\n * The RETURN type is `unknown` here on purpose. `Materialized<T>` is a compile-\n * time rewrite of the callback's return type, and it belongs on the public\n * `transaction()` signatures where `T` is inferred from the author's callback;\n * threading it through this driver as well would mean inferring `T` twice, from\n * two different positions, and reconciling them. The public wrappers narrow\n * once, at the seam where the value types were erased anyway.\n */\nexport async function runTxPlan<THandle>(\n transport: TxPlanTransport,\n // TUTAMAĞIN TAMAMI, yalnız `tables` DEĞİL. Tutamak artık şema yüzeyini de\n // taşıyor (`tx.public.x`, `tx.<şema>.x`), ve onu BURADA `{ tables }` diye\n // yeniden kurmak o yüzeyi sessizce düşürürdü.\n handle: THandle,\n builder: TxPlanBuilder,\n fn: (tx: THandle) => unknown,\n): Promise<unknown> {\n const returned = fn(handle);\n const body = builder.body();\n if (body.ops.length === 0) {\n return materializeResult(returned, []);\n }\n\n let response: TxPlanResponse;\n try {\n response = await transport.txPlan(body);\n } catch (err) {\n throw translateRejection(err, builder);\n }\n return materializeResult(returned, response.results);\n}\n\n/**\n * Turn the broker's rejection back into the tenant's own error.\n *\n * The server never sees the `Error` an expectation was given — only its slot\n * index — so this is the only place the intended error can be produced. A\n * rejection this SDK does not recognise passes through untouched: inventing an\n * error for it would hide the real failure.\n */\nfunction translateRejection(err: unknown, builder: TxPlanBuilder): unknown {\n if (typeof err !== \"object\" || err === null) return err;\n const rejection = err as TxPlanRejection;\n if (rejection.error_code !== \"tx_guard_failed\" || typeof rejection.slot !== \"number\") {\n return err;\n }\n return builder.errorForSlot(rejection.slot) ?? err;\n}\n"],"mappings":"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","names":["REF_BRAND","Symbol","for","brandRef","v","kind","Object","defineProperty","value","enumerable","brandOf","undefined","hasOwn","looksLikeUnbrandedRef","o","$col","$sql","isColRef","isPlanRef","r","$ref","op","field","looksLikeUnbrandedPlanRef","isSqlFragment","f","Array","isArray","text","values","TX_EXPR","isColumnExpr","assertNoExpressionHandles","caller","table","cols","data","c","Error","KNOWN_OPS","Set","REFUSED_OPS","eq","assertUsableFilter","where","COMPOSITES","col","cond","entries","has","branches","b","rel","inner","length","some","x","assertUsableWriteValues","TxRefError","Error","message","name","TxPlanError","EXPR","Symbol","for","REF","ROW","ROWS","TRAPPED_PROPS","toPrimitive","trap","prop","what","hint","description","String","now","makeExpr","fn","increment","by","assertAmount","inc","decrement","dec","test","Number","isFinite","negative","trimStart","startsWith","other","columnExprOf","v","exprOf","expr","Proxy","get","target","includes","undefined","makeRef","op","field","t","makeRowHandle","refDescriptor","d","isRefDescriptor","rowOpIndex","e","isRowsHandle","encodeValue","value","column","allowColumnExpr","ref","brandRef","$ref","$expr","assertNoNestedHandles","encodeFilterValue","Array","isArray","map","Date","isColRef","isSqlFragment","out","k","Object","entries","encodeFilterMap","key","keys","sort","item","values","encodeMap","SKIPPED_OP","TxRowsImpl","guarded","builder","opIndex","then","expectOne","error","declareGuard","expectNone","expectAtLeast","n","assertGuardCount","expectAtMost","kind","attachGuard","isInteger","MAX_OPS","MAX_ROWS","TxPlanBuilder","ops","slots","table","insert","encoded","length","push","put","options","onConflict","insertMany","rows","opts","row","assertUniformRows","action","updateWhere","where","set","encodedWhere","encodedSet","deleteWhere","select","limit","lock","index","slot","guard","body","errorForSlot","first","want","wantKey","join","i","got","materializeResult","results","rowOf","rowOp","isPlainObject","result","proto","getPrototypeOf","prototype","runTxPlan","transport","handle","returned","response","txPlan","err","translateRejection","rejection","error_code"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/runtime.ts","../src/db/env-gen.ts","../src/decorators/injectable.ts","../src/decorators/kinds.ts","../src/decorators/module.ts","../src/container.ts"],"sourcesContent":["/**\n * runtime.ts — request-scoped service singletons.\n *\n * The backend SDK no longer threads a `ctx` god-object through every handler.\n * Instead, controller methods import PascalCase service singletons directly:\n *\n * import { Controller, Post, Body, Database } from \"@palbase/backend\";\n *\n * \\@Controller(\"/todos\")\n * export default class TodosController {\n * \\@Post(\"\") create(\\@Body(CreateTodoBody) body: CreateTodoBody): unknown {\n * return Database.insert(\"todos\", { title: body.title });\n * }\n * }\n *\n * The singletons are thin Proxies. Every property access forwards to the live\n * client for the CURRENT request scope, resolved through {@link __getRuntime}.\n *\n * # Request-scope resolution (persistent app-server)\n *\n * The runtime is a long-running Node process that serves many concurrent\n * requests on one event loop (NOT a fresh subprocess per request). A single\n * module-global slot would let one in-flight request's services bleed into\n * another's. So the services are carried in an {@link AsyncLocalStorage} store\n * ({@link __requestALS}) that the runtime sets per request with\n * {@link __runWithRuntime}; every async continuation of that request reads its\n * own store. `__getRuntime` reads the ALS store first; the module-global slot\n * (set by {@link __setRuntime}) is only a fallback for callers that run OUTSIDE\n * an ALS scope (dev-server, unit tests, the legacy single-shot path). Because\n * each `br-<ref>` pod is single-tenant, there is no cross-tenant leakage; the\n * ALS store is what prevents cross-REQUEST leakage within the shared process.\n *\n * The seam that makes `import { Database } from \"@palbase/backend\"` resolve to\n * the runtime-injected client: `@palbase/backend` is marked esbuild-EXTERNAL\n * when the tenant bundle is built, and the package is installed globally in the\n * pod (NODE_PATH=/usr/local/lib/node_modules). So worker.js's\n * `require('@palbase/backend')` and the bundle's `import` resolve to ONE shared\n * module instance — the ALS store and `__setRuntime` slot on that instance are\n * visible to the singletons the bundle imported.\n */\n\nimport type { PalbaseFlagKey } from \"./stack.js\";\nimport type { Buckets, BucketTypes, Schemas } from \"./db/env.js\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport type {\n DBClient,\n DBOps,\n CacheClient,\n Logger,\n PalbaseDocsClient,\n SecretsService,\n} from \"./endpoint.js\";\nimport type {\n PalbaseStorageClient,\n PalbaseBucketClient,\n PalbaseNotificationsClient,\n PalbaseFlagsClient,\n PalbaseFlagsServiceClient,\n PalbaseFlagContext,\n PalbaseFlagVariant,\n PalbaseFlag,\n PalbaseFlagValue,\n PalbaseSetOverrideResult,\n PalbaseRealtimeClient,\n} from \"./clients.js\";\nimport type { PalbaseResult } from \"./endpoint.js\";\nimport type {\n EnvTypedDatabase,\n EnvServiceDatabase,\n EnvTables,\n TxPlan,\n TxTables,\n} from \"./db/typed-db.js\";\nimport type { Materialized } from \"./db/tx-plan.js\";\nimport { TxPlanBuilder, runTxPlan } from \"./db/tx-plan.js\";\nimport { withRetry } from \"./db/typed-db.js\";\nimport { qualifiedTableKey } from \"./db/schema-json.js\";\nimport type { DollarOps } from \"./db/typed-db.js\";\n\n/** The set of live clients the runtime injects per request scope.\n *\n * Realtime is BROADCAST-ONLY here (a stateless handler can push an event but\n * cannot hold a subscription socket — `subscribe()` lives on the client SDK).\n *\n * EXCLUDED on purpose: Functions, Links, Analytics, Auth. They are not\n * exposed as backend handler singletons (auth lives on the client SDK; the rest\n * are out of scope for backend endpoints). */\nexport interface RuntimeServices {\n Database: DBClient;\n Secrets: SecretsService;\n Documents: PalbaseDocsClient;\n Storage: PalbaseStorageClient;\n Cache: CacheClient;\n Log: Logger;\n Notifications: PalbaseNotificationsClient;\n Flags: PalbaseFlagsClient;\n Realtime: PalbaseRealtimeClient;\n}\n\n/**\n * The per-request ALS box.\n *\n * `runtime` is the service bundle. `userId` is the request's authenticated user\n * id, written by the runtime immediately after it assembles the request object\n * (worker.js: `requestALS.getStore().userId = pbReq.user?.id || null`) and\n * `null` on an anonymous request. It was already being written there for the\n * Flags client's auto-bind; declaring it here makes the existing contract typed\n * instead of implicit, which is what lets `currentSubjectId()` read a\n * server-owned identity rather than trusting anything the caller sent.\n */\nexport interface RequestStore {\n runtime: RuntimeServices;\n userId?: string | null;\n /** This request's id (`req_…`), written by the runtime. Used as the spend\n * idempotency scope when the caller supplied no `Idempotency-Key`. */\n requestId?: string;\n /** The caller's `Idempotency-Key` header, or `null` when absent. What makes a\n * client's retry replay its first result instead of charging twice. */\n idempotencyKey?: string | null;\n}\n\n/**\n * Per-request store. The persistent runtime runs each request inside\n * {@link __runWithRuntime}, so every async continuation of that request reads\n * its OWN `runtime` (and any other request-scoped fields the runtime adds).\n *\n * Exported with a `__` prefix so the runtime (worker.js) shares the SAME ALS\n * instance across the one module instance — two ALS instances would silently\n * not see each other's stores. NOT part of the public author-facing API.\n */\nexport const __requestALS = new AsyncLocalStorage<RequestStore>();\n\n/** Process-global fallback slot. Used only OUTSIDE an ALS scope (dev-server,\n * unit tests, legacy single-shot worker). Inside the persistent server every\n * request runs in {@link __requestALS}, which takes precedence. */\nlet runtime: RuntimeServices | null = null;\n\n/** Install the live clients in the process-global fallback slot.\n *\n * Persistent-server requests should use {@link __runWithRuntime} instead; this\n * remains for dev-server / tests / the legacy single-shot path that run without\n * an ALS scope. NOT part of the public author-facing API. */\nexport function __setRuntime(services: RuntimeServices): void {\n runtime = services;\n}\n\n/** Run `fn` with `services` bound as the request-scoped runtime.\n *\n * The persistent worker calls this once per request so concurrent requests\n * never share a services slot. NOT part of the public author-facing API. */\nexport function __runWithRuntime<T>(services: RuntimeServices, fn: () => T): T {\n return __requestALS.run({ runtime: services }, fn);\n}\n\n/** Read the live clients, throwing if accessed outside a request scope.\n *\n * Resolves the ALS store first (persistent server, per-request), then the\n * process-global fallback (dev-server / tests). NOT part of the public\n * author-facing API — used by the runtime and the singleton Proxies. */\nexport function __getRuntime(): RuntimeServices {\n const scoped = __requestALS.getStore();\n if (scoped) return scoped.runtime;\n if (runtime === null) {\n throw new Error(\n \"Palbase services accessed outside a request scope. The Database/Documents/… \" +\n \"singletons are only available inside an endpoint handler (or after the \" +\n \"runtime has called __runWithRuntime / __setRuntime).\",\n );\n }\n return runtime;\n}\n\n// ─── lifecycle: where a long-lived resource lives (FR-013) ─────────────────\n//\n// `Resource` was removed in 23.0.0 and nothing replaced the LIFECYCLE half of\n// it. What that left behind is measurable: a connection pool (the driver in\n// `docs/resources.md`'s own example was Neo4j) had no documented place to be\n// opened and NO WAY AT ALL to be closed, so every deploy left the pool it\n// opened behind. These two hooks are that half — and only that half. The\n// secret-distribution half does not come back: a handler reads `Secrets.get`,\n// and a start hook, which runs before any request scope exists, reads the\n// `process.env` the runtime mirrors the vault into at boot.\n\n/** A lifecycle hook. Sync or async; the runtime awaits what it returns. */\nexport type LifecycleHook = () => void | Promise<void>;\n\n/** Runs one release's shutdown hooks. Handed back by {@link __runStartHooks}\n * and called by the engine's `app.shutdown()`. Idempotent. */\nexport type ShutdownRunner = () => Promise<void>;\n\ninterface DeclaredHook {\n name: string;\n run: LifecycleHook;\n}\n\ninterface DeclaredLifecycle {\n start: DeclaredHook[];\n shutdown: DeclaredHook[];\n}\n\n/**\n * What has been DECLARED and not yet claimed by an app.\n *\n * On globalThis under a well-known Symbol for the reason the controller\n * registry is (`decorators/controller.ts`): a deployed bundle inlines its own\n * copy of this package, and the engine that has to RUN these hooks holds the\n * other copy. Two module-local arrays would mean the engine reads the empty one\n * and every declared hook is silently never run — which is exactly how\n * `Resource`'s `init(env)` died.\n */\nconst LIFECYCLE: unique symbol = Symbol.for(\"palbase.backend.lifecycleHooks\") as never;\n\nfunction declaredLifecycle(): DeclaredLifecycle {\n const g = globalThis as unknown as Record<symbol, DeclaredLifecycle | undefined>;\n return (g[LIFECYCLE] ??= { start: [], shutdown: [] });\n}\n\n/**\n * Run `hook` ONCE while the application comes up, before it serves anything.\n *\n * Call it at MODULE SCOPE in a file the application imports — the same rule\n * `defineDefaultAuth` and `@Controller` follow, and for the same reason: the\n * declaration is claimed when the app boots, which is after module loading and\n * before the first request. `name` is not decoration: a hook that throws is\n * reported by that name and the boot is REFUSED, so it is what tells an\n * operator which resource did not come up.\n *\n * There is no request scope yet, so the `Database`/`Secrets`/… singletons are\n * NOT available inside a start hook. A secret is read from `process.env` here\n * (the runtime mirrors the vault into it at boot).\n *\n * @example\n * // resources/graph.ts\n * import neo4j from \"neo4j-driver\";\n * import { onStart, onShutdown } from \"@palbase/backend\";\n *\n * export let graph: Driver;\n * onStart(\"graph\", () => {\n * graph = neo4j.driver(process.env.NEO4J_URL!, neo4j.auth.basic(\"neo4j\", process.env.NEO4J_PASSWORD!));\n * });\n * onShutdown(\"graph\", () => graph.close());\n */\nexport function onStart(name: string, hook: LifecycleHook): void {\n declaredLifecycle().start.push({ name, run: hook });\n}\n\n/**\n * Run `hook` while the application shuts down — the place a pool opened in\n * {@link onStart} is closed.\n *\n * Shutdown is BEST-EFFORT by design: a hook that throws is reported by name and\n * the rest still run. A drain that abandoned the remaining hooks on the first\n * failure would leak exactly what this exists to release, and the process is\n * leaving anyway.\n *\n * Hooks run in REVERSE declaration order, so a resource is released before what\n * it was built on.\n */\nexport function onShutdown(name: string, hook: LifecycleHook): void {\n declaredLifecycle().shutdown.push({ name, run: hook });\n}\n\nfunction reason(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/** Best-effort drain: every hook runs, a failure is reported, none is silent. */\nasync function drain(hooks: DeclaredHook[]): Promise<void> {\n for (const h of [...hooks].reverse()) {\n try {\n await h.run();\n } catch (err) {\n console.error(`[palbase] shutdown hook \"${h.name}\" failed: ${reason(err)}`, err);\n }\n }\n}\n\n/**\n * CLAIM what has been declared, run the start hooks, and hand back the runner\n * for this release's shutdown hooks. Called by the engine's `createApp`; the\n * `App.shutdown()` it builds calls what comes back. NOT part of the public\n * author-facing API.\n *\n * IT CLAIMS RATHER THAN READS, which is what makes it correct in this runtime:\n * a candidate release is loaded BESIDE the live one in one process\n * (`v2/runtime/src/registry-scope.ts`), and both bundles append to the one\n * shared slot above. If each app read the whole list, the live app's shutdown\n * would close the candidate's pool and the candidate's would close the live\n * app's. Taking the declarations leaves each app holding exactly its own.\n *\n * A start hook that throws REFUSES THE BOOT — with the hook's name in the\n * message — after releasing whatever the earlier hooks already opened. Serving\n * from a half-initialised app is the silence this whole surface replaces, and a\n * boot that dies holding an open pool is the leak it replaces.\n */\nexport async function __runStartHooks(): Promise<ShutdownRunner> {\n const slot = declaredLifecycle();\n const start = slot.start.splice(0);\n const shutdown = slot.shutdown.splice(0);\n\n for (const h of start) {\n try {\n await h.run();\n } catch (err) {\n await drain(shutdown);\n throw new Error(`[palbase] start hook \"${h.name}\" failed: ${reason(err)}`, { cause: err });\n }\n }\n\n let drained = false;\n return async () => {\n // SIGTERM racing a redeploy asks twice; a pool is closed once.\n if (drained) return;\n drained = true;\n await drain(shutdown);\n };\n}\n\n/** Drop every declaration. For tests, which declare repeatedly in one process.\n * NOT part of the public author-facing API. */\nexport function __resetLifecycleHooks(): void {\n const g = globalThis as unknown as Record<symbol, DeclaredLifecycle | undefined>;\n delete g[LIFECYCLE];\n}\n\n/**\n * Build a Proxy singleton that forwards every property access to the live\n * client named `key` on the current runtime.\n *\n * The single `as RuntimeServices[K]` is the only contained cast in the surface:\n * `Reflect.get` on a typed object returns `unknown` for a `string | symbol`\n * key, but `prop` is constrained to keys of the client interface at the call\n * sites (the exported singletons are typed below), so the forward is sound.\n */\nfunction makeServiceProxy<K extends keyof RuntimeServices>(key: K): RuntimeServices[K] {\n const handler: ProxyHandler<RuntimeServices[K]> = {\n get(_target, prop, receiver) {\n const client = __getRuntime()[key];\n const value = Reflect.get(client as object, prop, receiver) as unknown;\n // Bind methods to their owning client so `this` stays correct when the\n // author destructures or calls `Database.query(...)`.\n return typeof value === \"function\" ? value.bind(client) : value;\n },\n };\n // The Proxy target is irrelevant (all access goes through `get`); the cast\n // names the surface type the singleton presents to authors.\n return new Proxy({} as RuntimeServices[K], handler);\n}\n\n/**\n * Build the `.tables` accessor for the top-level `Database`. Each\n * `tables.<name>` access returns a small object that forwards the five CRUD ops\n * to the underlying client using `name` as the string table identifier. The\n * shapes are typed against the generated `palbase-env.d.ts` (`EnvTables`); at\n * runtime they are plain string-keyed calls, so no schema value is needed here.\n *\n * Returns `EnvTables` — TS cannot infer the mapped type through the Proxy, so\n * a single structural narrowing names the surface (the proxy returns a\n * correctly-shaped accessor for whatever string member is read).\n */\n/** T018 (C-8): similar/recommend'in string-keyed yüzü. DBOps'a (endpoint.ts)\n * BİLEREK eklenmedi — search-param imza üçlüsü (engine/db + typed-db +\n * endpoint) büyümesin: proxy dispatch runtime'da engine ops'una zaten ulaşır,\n * derleme güvenliğini typed yüzey (EnvTypedTable) verir. */\nexport interface RecoOps {\n similar(table: string, id: string, params?: Record<string, unknown>): Promise<Record<string, unknown>[]>;\n recommend(table: string, params: Record<string, unknown>): Promise<Record<string, unknown>[]>;\n}\n\n/**\n * The Proxy behind EVERY `.tables` map — public's and every other schema's.\n *\n * `prefix` is what the wire name is built from: `\"\"` for `public`, so its tables\n * stay BARE, and `\"<schema>.\"` for any other, so `schema(\"billing\").tables\n * .invoices` reaches the broker as `billing.invoices` (D-10 — the same\n * schema-qualified key `toSchemaJSON` and the generated `relations` use).\n *\n * One trap for both surfaces: two copies would be two op lists that can drift,\n * and the one that forgets an op does not complain — it answers `undefined`.\n */\nfunction makeTableProxy(ops: () => DBOps & RecoOps, prefix: string): object {\n return new Proxy(\n {},\n {\n get(_t, prop: string | symbol) {\n if (typeof prop !== \"string\") return undefined;\n const name = `${prefix}${prop}`;\n return {\n insert: (data: Record<string, unknown>) => ops().insert(name, data),\n update: (q: { where: { id: string }; set: Record<string, unknown> }) =>\n ops().update(name, q.where.id, q.set),\n delete: (id: string) => ops().delete(name, id),\n findById: (id: string) => ops().findById(name, id),\n findMany: (q?: Record<string, unknown>) => {\n // `where` AYIKLANIR; kalan alanlar (orderBy/limit/offset) ham op'un\n // ikinci parametresine gider. Tümünü geçirmek `where`'i tel üstünde\n // ikinci kez gönderirdi — `typed-db.test.ts` bunu yakalıyor.\n const { where, ...opts } = q ?? {};\n return ops().findMany(\n name,\n where as Record<string, unknown> | undefined,\n opts as Parameters<DBOps[\"findMany\"]>[2],\n );\n },\n put: (q: { data: Record<string, unknown>; onConflict: readonly string[] }) =>\n ops().put(name, q.data, { onConflict: q.onConflict }),\n // THREE VERBS THE TYPE PROMISED AND THIS PROXY DID NOT EMIT.\n //\n // `EnvTypedTableBase` declares `updateMany`, `deleteMany` and `count`\n // (typed-db.ts) and the ops layer implements all three — only this\n // proxy, which is what a handler actually touches, left them out. So\n // the type said the verb exists, autocomplete offered it, and the call\n // answered `undefined is not a function`.\n //\n // Older than this run, but the run rewrote this proxy for\n // `Database.schema(name).tables.*` and would have carried the gap onto\n // the new surface too.\n updateMany: (q: { where: Record<string, unknown>; set: Record<string, unknown> }) =>\n ops().updateMany(name, q.where, q.set),\n deleteMany: (q: { where: Record<string, unknown> }) => ops().deleteMany(name, q.where),\n count: (q?: { where?: Record<string, unknown> }) => ops().count(name, q?.where),\n search: (params?: Record<string, unknown>) => ops().search(name, params),\n similar: (id: string, params?: Record<string, unknown>) => ops().similar(name, id, params),\n recommend: (params: Record<string, unknown>) => ops().recommend(name, params),\n facets: (params: { facets: string[] } & Record<string, unknown>) => ops().facets(name, params),\n supersede: (id: string, row: Record<string, unknown>) => ops().supersede(name, id, row),\n claim: (unique: Record<string, unknown>, extra?: Record<string, unknown>) =>\n ops().claim(name, unique, extra),\n };\n },\n },\n );\n}\n\n\n/** The raw string-keyed `DBClient` for the current request scope. */\nconst rawDatabase: DBClient = makeServiceProxy(\"Database\");\n\n/**\n * Wrap a raw `DBClient` into the typed `{ ...ops, tables, transaction }`\n * surface. The five string ops forward straight through; `tables` is the\n * env-typed accessor; `transaction` yields typed tables. Reused for both the\n * default (RLS-enforced) `Database` and the `asService()` sibling — each is\n * fed its own raw client (the default proxy vs `rawDatabase.asService()`).\n *\n * The `satisfies` pins the op surface so a missing/renamed op is a compile\n * error; the assembled object carries `tables`/`transaction` alongside.\n */\nfunction makeTypedSurface(raw: Omit<DBClient, \"asService\">): EnvServiceDatabase {\n // Proxy dispatch her üyeyi taşır; RecoOps tipi DBClient'a eklenmediğinden\n // (yukarıdaki karar) similar/recommend erişimi bu daraltmadan geçer.\n const reco = raw as Omit<DBClient, \"asService\"> & RecoOps;\n // `$` ÖNEKİ AÇIKÇA YAZILIR, dinamik üretilmez.\n //\n // Bir tur `Object.fromEntries(Object.entries(ops).map(…))` ile üretilmişti ve\n // `database.test.ts`'in sayımı onu göremedi: sayım DEKLARASYONLARI okuyor,\n // string literal'leri değil. Görünmeyen bir yüzey denetlenemez — ve o testin\n // varlık sebebi tam olarak budur (FR-044: yüzeyde bağlantı bilgisi olmadığını\n // kanıtlamak, ama önce yüzeye gerçekten ULAŞTIĞINI kanıtlamak).\n const ops = {\n $query: (sql: string, params?: unknown[]) => raw.query(sql, params),\n $insert: (table: string, data: Record<string, unknown>) => raw.insert(table, data),\n $update: (table: string, id: string, data: Record<string, unknown>) =>\n raw.update(table, id, data),\n $delete: (table: string, id: string) => raw.delete(table, id),\n $findById: (table: string, id: string) => raw.findById(table, id),\n $findMany: (table: string, query?: Record<string, unknown>, opts?: Parameters<DBOps[\"findMany\"]>[2]) =>\n raw.findMany(table, query, opts),\n $put: (table: string, data: Record<string, unknown>, opts: { onConflict: readonly string[] }) =>\n raw.put(table, data, opts),\n $updateMany: (table: string, where: Record<string, unknown>, set: Record<string, unknown>) =>\n raw.updateMany(table, where, set),\n $deleteMany: (table: string, where: Record<string, unknown>) => raw.deleteMany(table, where),\n $count: (table: string, where?: Record<string, unknown>) => raw.count(table, where),\n $search: (table: string, params?: Record<string, unknown>) => raw.search(table, params),\n $similar: (table: string, id: string, params?: Record<string, unknown>) =>\n reco.similar(table, id, params),\n $recommend: (table: string, params: Record<string, unknown>) => reco.recommend(table, params),\n $facets: (table: string, params: { facets: string[] } & Record<string, unknown>) => reco.facets(table, params),\n $claim: (table: string, unique: Record<string, unknown>, extra?: Record<string, unknown>) =>\n reco.claim(table, unique, extra),\n $lockRows: (table: string, ids: readonly string[]) => reco.lockRows(table, ids),\n $advisoryXactLock: (key: string) => reco.advisoryXactLock(key),\n $supersede: (table: string, id: string, row: Record<string, unknown>) =>\n raw.supersede(table, id, row),\n } satisfies DollarOps<Omit<DBOps & RecoOps, \"attempt\">>;\n // `ops` DOĞRUDAN verilir, spread edilmez: sayım (`database.test.ts`) nesneyi\n // deklarasyonundan takip ediyor ve bir spread onu kaybettiriyor. Görünmeyen\n // yüzey denetlenemez.\n const base = Object.assign(ops as unknown as Record<string, unknown>, {\n // Both surfaces get it: a savepoint on the service transaction is as useful\n // as one on the request's, and each is bound to its own connection.\n $attempt: <T,>(fn: (tx: DBOps) => Promise<T>) => raw.attempt(fn),\n $transaction<T>(\n fn: (tx: TxPlan) => T extends Promise<unknown> ? never : T,\n opts?: { retry?: number },\n ): Promise<Materialized<T>> {\n // A FRESH builder per call: it holds this transaction's ops and its error\n // slot table, and the runtime serves concurrent requests on one event loop.\n // A shared builder would splice one request's writes into another's plan.\n //\n // Retry de HER DENEMEDE taze bir builder istiyor (FR-037): önceki denemenin\n // op'ları planda kalsaydı ikinci deneme birincinin yazmalarını TEKRAR\n // gönderirdi. Bu yüzden builder döngünün İÇİNDE kuruluyor.\n return withRetry(() => {\n const builder = new TxPlanBuilder();\n return runTxPlan(raw, makeTxPlanHandle(builder), builder, fn) as Promise<\n Materialized<T>\n >;\n }, opts ?? {}) as Promise<Materialized<T>>;\n },\n });\n // ŞEMA ERİŞİMİ BİR PROXY'DİR, çünkü hangi şemaların bildirildiğini yalnız TİP\n // bilir — runtime'da `Database.billing` diye bir üye yoktur, o ada dokunulduğu\n // anda üretilir. `$`'la başlamayan her ad bir ŞEMA adıdır; ayrım tam olarak\n // budur ve tip tarafındaki DollarOps ile aynı kuralı uygular.\n return new Proxy(base, {\n get(target, prop, receiver) {\n // `tables` DOĞRUDAN YÜZEYDE DE public'in takma adı.\n //\n // Plan tutamağı `tx.tables.todos`'u öğretiyor (göç notu da öyle), ama\n // `Database.tables.todos` aynı kelimeyi ADI `tables` OLAN BİR ŞEMA sanıp\n // tele `tables.todos` yazıyordu. Tip onu reddettiği için derlenen kodda\n // erişilemezdi — ama `as any` ya da düz JS ile geçen biri sessizce\n // olmayan bir şemaya gidiyordu, ve iki yüzeyin aynı kelimeye zıt cevap\n // vermesi bu run'ın kapattığı sınıfın kendisi (gözcü M-6).\n if (prop === \"tables\") return makeTableProxy(() => reco, \"\");\n if (typeof prop === \"string\" && !prop.startsWith(\"$\") && !(prop in target)) {\n // Nitelikli tablo anahtarının kuralı BURADA TEKRARLANMAZ (FR-058): tek\n // yazıcı `qualifiedTableKey` ve `table-key-single-source.test.ts` ikinci\n // bir yazıcıyı reddediyor. Prefix ondan türetilir — boş tablo adıyla\n // çağrıldığında geriye ya \"\" (public) ya \"<şema>.\" kalır.\n return makeTableProxy(() => reco, qualifiedTableKey(prop, \"\"));\n }\n return Reflect.get(target, prop, receiver);\n },\n }) as unknown as EnvServiceDatabase;\n}\n\n/**\n * `makeTableProxy`'nin plan ikizi: `tables.<name>` yields the\n * table's PLAN operations, recorded into `builder` instead of sent one by one.\n *\n * Same Proxy shape and same reason for the single narrowing — TS cannot infer a\n * mapped type through a Proxy, so the cast names what the trap returns.\n */\nfunction makeTxTablesAccessor(builder: TxPlanBuilder, prefix = \"\"): TxTables {\n const tablesProxy = new Proxy(\n {},\n {\n get(_t, prop: string | symbol) {\n if (typeof prop !== \"string\") return undefined;\n return builder.table(prefix + prop);\n },\n },\n );\n return tablesProxy as TxTables;\n}\n\n/**\n * Plan tutamağı — `Database` ile AYNI şekil: `tx.public.x`, `tx.<şema>.x`, ve\n * geriye dönük `tx.tables.x`.\n *\n * Şema adı tablo adının ÖNÜNE geçiyor (`billing.invoices`), tıpkı doğrudan\n * yüzeyin `makeTypedSurface` proxy'sinin yaptığı gibi — ve motor artık onu\n * `quoteTable` ile İKİ parça hâlinde tırnaklıyor. Bu ikisi olmadan `billing`\n * şemasındaki iki tabloyu tek atomik planda yazmak imkânsızdı.\n *\n * `tables` ve `public` DIŞINDAKİ HER ad şema kabul edilir ve altındaki tablolar\n * `<ad>.<tablo>` diye adlanır. Yanlış bir şema adı TİPTE yakalanıyor\n * (`keyof Schemas`) — `tx.constructor.x` ve `tx.toString.x` dahil, ölçüldü.\n *\n * TİPTEN KAÇAN bir ad için savunma `quoteTable`'ın KAÇIŞIDIR, başka bir şey\n * değil: `runPlanOp` `op.table`'ı doğrulamadan ona veriyor ve `quoteTable`\n * tırnak ikizleyerek tek bir tanımlayıcı üretiyor. Ölçüldü: `a\"; DROP TABLE t; --`\n * → `\"a\"\"; DROP TABLE t; --\"`, yani enjeksiyon değil, `relation does not exist`.\n * (Bu yorum bir zamanlar `validateSchemaIdentifier`'a atıf yapıyordu — o\n * fonksiyon Go tarafında yaşıyor ve BU yolu hiç görmüyor; gözcü yakaladı.)\n */\nfunction makeTxPlanHandle(builder: TxPlanBuilder): TxPlan {\n const publicTables = makeTxTablesAccessor(builder);\n return new Proxy(\n {},\n {\n get(_t, prop: string | symbol) {\n if (typeof prop !== \"string\") return undefined;\n if (prop === \"tables\") return publicTables;\n // ÖNEK TEK YAZICIDAN (FR-058): `qualifiedTableKey`. Bu kuralı burada\n // elle yazmıştım — public'i çıplak bırakıp diğerine nokta ekleyen bir\n // if/return çifti — ve FR-058 kapısı onu GÖRMEDİ, çünkü kapı yalnız\n // ternary arıyordu. (Kural burada KELİMEYLE anlatılıyor, kod biçiminde\n // DEĞİL: kapı metni tarıyor ve bir yorumdaki kopya da onu tetikler.)\n // İkinci bir yazıcı, kapının var olma sebebi olan sınıfın kendisi:\n // `env-gen.ts`'in kendi kopyası bir public FK'yi başka bir şemanın\n // tablosuna etiketlemişti ve hiçbir şey bunu söylememişti.\n // Boş tablo adıyla çağrılınca geriye ya \"\" (public) ya \"<şema>.\" kalır.\n return makeTxTablesAccessor(builder, qualifiedTableKey(prop, \"\"));\n },\n },\n ) as TxPlan;\n}\n\n/**\n * The project's own Postgres (pgx, schema `env_<envId>`).\n *\n * Typed by default: `Database.tables.<name>.insert({...})` is typed against\n * the project's generated `palbase-env.d.ts` with NO import and NO generic.\n * The raw string ops (`query`/`insert`/`update`/`delete`/`findById`/`findMany`)\n * are also available for dynamic table names and read-only SQL.\n *\n * RLS is enforced by default (the runtime runs each op as `authenticated` with\n * the verified user's claims). To bypass RLS, call `Database.asService()` —\n * explicit and greppable — which runs as the `service_role` (BYPASSRLS).\n *\n * @example\n * import { Database } from \"@palbase/backend\";\n *\n * const todo = await Database.public.todos.insert({ title: req.input.title });\n * todo.id; // string ✓\n * const rows = await Database.$query(\"SELECT id FROM todos WHERE done = $1\", [false]);\n * const all = await Database.$asService().public.todos.findMany({}); // RLS bypass\n */\nexport const Database: EnvTypedDatabase = Object.assign(makeTypedSurface(rawDatabase), {\n /**\n * Lazily resolve the runtime's service-role sibling on each call. We do NOT\n * cache it: `rawDatabase.asService()` reads the CURRENT request scope through\n * the runtime proxy, and the per-request runtime injects a service client\n * bound to that request's identity headers — caching would leak one request's\n * sibling into another concurrent request.\n */\n $asService(): EnvServiceDatabase {\n return makeTypedSurface(rawDatabase.asService());\n },\n}) as unknown as EnvTypedDatabase;\n\n/** Firestore-like document client (PalDocs). */\nexport const Documents: PalbaseDocsClient = makeServiceProxy(\"Documents\");\n\n/**\n * `buckets.<name>` — the storage twin of `Database.tables.<name>`, and the same\n * mechanism: `config/storage.ts` generates a `Buckets` augmentation into\n * `palbase-env.d.ts`, so a bucket name is a property with no import and no\n * generic, and a typo is a compile error.\n *\n * The intermediate `.buckets` is there for the reason `.tables` is: bucket\n * names must not share a namespace with the client's own methods, or the day\n * somebody declares a bucket called `bucket` the surface breaks.\n */\nexport type EnvBuckets = {\n [K in keyof Buckets]: TypedBucketClient<Buckets[K] extends BucketTypes ? Buckets[K] : BucketTypes>;\n};\n\n/** One bucket, with its declared variant names in the type. */\nexport interface TypedBucketClient<B extends BucketTypes> extends Omit<PalbaseBucketClient, \"getPublicUrl\"> {\n /** The public URL for the object, or for one of THIS bucket's declared\n * renditions. A name the bucket does not declare is a compile error. */\n getPublicUrl(path: string, options?: { variant?: B[\"variants\"] }): string;\n}\n\nfunction makeBucketsAccessor(storage: () => PalbaseStorageClient): EnvBuckets {\n return new Proxy(\n {},\n {\n get(_t, prop: string | symbol) {\n if (typeof prop !== \"string\") return undefined;\n return storage().bucket(prop);\n },\n },\n ) as EnvBuckets;\n}\n\nconst rawStorage: PalbaseStorageClient = makeServiceProxy(\"Storage\");\n\n/**\n * Object storage: buckets, objects, renditions and signed URLs.\n *\n * `Storage.buckets.posts.upload(...)` is the typed path. `Storage.bucket(name)`\n * remains for a name computed at runtime — rare, and it gives up the typing,\n * which is the honest trade rather than a second blessed way to do it.\n */\nexport const Storage: PalbaseStorageClient & { buckets: EnvBuckets } = Object.assign(\n {\n // FORWARDED explicitly, not assigned onto the service proxy.\n //\n // `Object.assign(rawStorage, {buckets})` writes onto the proxy's TARGET, and\n // the proxy's only trap is `get`, which forwards every read to the module\n // client — so the property landed somewhere nothing reads and\n // `Storage.buckets.docs` was `undefined` in a deployed handler. It\n // typechecked, every test passed, and the live call answered\n // \"TypeError: undefined is not an object\". `Database` never had the bug\n // because it builds a plain surface the same way this now does.\n bucket: (name: string) => rawStorage.bucket(name),\n },\n { buckets: makeBucketsAccessor(() => rawStorage) },\n);\n\n/** JSON-typed cache (get/set/incr/getOrSet). */\nexport const Cache: CacheClient = makeServiceProxy(\"Cache\");\n\n\n/**\n * This tenant's secrets — API keys, provider credentials, signing material the\n * BACKEND owns.\n *\n * `await Secrets.get(\"STRIPE_KEY\")` in a handler. There is no `.env` to read\n * and no file to mount: a secret is written through the vault's authenticated\n * API (or the CLI/MCP that calls it), and this is how the deployed code reads\n * it back. A name this tenant has not set answers null — as does every name\n * the STACK holds, because no route returns a platform secret's value at all.\n */\nexport const Secrets: SecretsService = makeServiceProxy(\"Secrets\");\n\n/** Structured logger. */\nexport const Log: Logger = makeServiceProxy(\"Log\");\n\n/** Push / email / SMS / in-app notifications. */\nexport const Notifications: PalbaseNotificationsClient = makeServiceProxy(\"Notifications\");\n\n\n/**\n * The raw runtime Flags client for the current request scope. Carries the\n * default-surface reads + `setOverride` AND the runtime's `asService()` sibling\n * (the br-pod's `buildFlagsClient` returns both). The default `Flags` singleton\n * below forwards reads + `setOverride` through here; `Flags.asService()`\n * forwards to this client's own `asService()`.\n */\nconst rawFlags: PalbaseFlagsClient = makeServiceProxy(\"Flags\");\n\n/**\n * Feature flags.\n *\n * Mirrors the `Database` / `Database.asService()` model. The default surface is\n * RLS-equivalent for flags: reads resolve against the CURRENT request user and\n * `Flags.setOverride(key, value)` writes an override for that same signed-in\n * user (no userId argument, no admin power). Cross-user admin writes\n * (`setOverrideForUser`, …) live behind `Flags.asService()` — explicit and\n * greppable, just like `Database.asService()`.\n *\n * @example\n * import { Flags } from \"@palbase/backend\";\n *\n * if (await Flags.isEnabled(\"new_checkout\")) { ... } // current user\n * await Flags.setOverride(\"new_checkout\", true); // current user\n * await Flags.asService().setOverrideForUser(\"u_9\", \"x\", true); // cross-user\n */\nexport const Flags: PalbaseFlagsClient = Object.assign(\n {\n isEnabled(\n flagName: PalbaseFlagKey,\n context?: PalbaseFlagContext,\n ): Promise<PalbaseResult<boolean>> {\n return rawFlags.isEnabled(flagName, context);\n },\n getVariant(\n flagName: PalbaseFlagKey,\n context?: PalbaseFlagContext,\n ): Promise<PalbaseResult<PalbaseFlagVariant>> {\n return rawFlags.getVariant(flagName, context);\n },\n getAll(context?: PalbaseFlagContext): Promise<PalbaseResult<PalbaseFlag[]>> {\n return rawFlags.getAll(context);\n },\n /**\n * Resolve a flag's value, with an optional fallback.\n *\n * FORWARDED as of 2026-08-15. This surface is written out by hand, method\n * by method, and `get` was missing from it — so the client implemented it,\n * thirty assertions covered it, and `Flags.get(\"x\")` was `undefined` in a\n * deployed handler. Exactly the shape of the `Storage.buckets` defect found\n * the same day: a hand-maintained forwarding list is a list somebody has to\n * remember to update.\n */\n get(\n flagName: PalbaseFlagKey,\n defaultOrContext?: PalbaseFlagValue | PalbaseFlagContext,\n maybeContext?: PalbaseFlagContext,\n ): Promise<PalbaseResult<PalbaseFlagValue>> {\n return rawFlags.get(flagName, defaultOrContext, maybeContext);\n },\n setOverride(\n key: PalbaseFlagKey,\n value: PalbaseFlagValue,\n ): Promise<PalbaseResult<PalbaseSetOverrideResult>> {\n return rawFlags.setOverride(key, value);\n },\n },\n {\n /**\n * Lazily resolve the runtime's cross-user sibling on each call. We do NOT\n * cache it: `rawFlags.asService()` reads the CURRENT request scope through\n * the runtime proxy, so caching would leak one request's sibling into\n * another concurrent request. Mirrors `Database.asService()`.\n */\n asService(): PalbaseFlagsServiceClient {\n return rawFlags.asService();\n },\n },\n);\n\n/**\n * The Realtime broadcast singleton for the current request scope. Backend-side\n * Realtime is BROADCAST-ONLY (a stateless handler can push but not subscribe —\n * `subscribe()` lives on the client SDK's `pb.realtime`). Fire-and-forget:\n * `broadcast` resolves once accepted (or with an `error`), never blocking the\n * handler on subscribers.\n *\n * @example\n * import { Realtime } from \"@palbase/backend\";\n *\n * await Realtime.broadcast(\"room:42\", \"message\", { text, from: user.id });\n */\nexport const Realtime: PalbaseRealtimeClient = makeServiceProxy(\"Realtime\");\n","/**\n * env-gen.ts — generate the `palbase-env.d.ts` text from a `defineSchema()`\n * result.\n *\n * The CLI (`palbase build`) and the deploy pipeline call\n * {@link makeEnvDts} with the project's schema and write the returned string to\n * `palbase-env.d.ts` at the project root. That file AUGMENTS the\n * `@palbase/backend/env` `Tables` interface (controlled global augmentation,\n * C5) so `Database.public.<name>` is typed with no import and no generic.\n *\n * The output is FLAT: each table gets a `{ row: {...}; insert: {...} }` entry\n * with plain TypeScript object types. The phantom `ColumnBuilder<...>` type\n * NEVER appears in the generated `.d.ts` — that type only lives at authoring\n * time inside the project's `db/*.ts` schema files.\n */\n\nimport type { ColumnDef } from \"./columns.js\";\n// FR-058: the \"public is bare, everything else is qualified\" rule lives in ONE\n// helper. This file used to carry two more copies of it — a module-level\n// `qualify` and a second, identical local one inside `makeEnvDts` — and the\n// duplication was not cosmetic: re-deriving the key here instead of reading the\n// one `resolveReferences` already wrote is exactly how a public foreign key got\n// relabelled onto another schema's table. Two names for one truth are two\n// interpreters of it.\nimport { qualifiedTableKey } from \"./schema-json.js\";\nimport type { SchemaDef, TableDef } from \"./schema.js\";\n\n/** The TypeScript value type for a column, ignoring nullability (added by the\n * caller). Mirrors the `ColValue` mapped type in columns.ts exactly. */\nfunction baseTsType(def: ColumnDef): string {\n switch (def.type) {\n case \"uuid\":\n case \"text\":\n case \"timestamp\":\n return \"string\";\n case \"integer\":\n return \"number\";\n // Both are exact-precision in Postgres and lossy as a JSON number, so the\n // database proxy serializes them as strings — measured: 9007199254740993\n // used to arrive as ...992 and 41.00821234567890123 as 41.0082123456789.\n // numeric had no case at all and fell through to `unknown`, which typed\n // every numeric column out of existence.\n case \"bigint\":\n case \"numeric\":\n return \"string\";\n case \"boolean\":\n return \"boolean\";\n case \"jsonb\":\n return \"unknown\";\n // FR-008: the authoring type of a pgvector column. The default `unknown`\n // branch below STAYS — an unknown wire type is refused on the Go side\n // (FR-005), never papered over here.\n case \"vector\":\n return \"number[]\";\n case \"enum\": {\n const values = def.enumValues ?? [];\n if (values.length === 0) return \"string\";\n return values.map((v) => JSON.stringify(v)).join(\" | \");\n }\n default:\n return \"unknown\";\n }\n}\n\n/** The full row type for a column: base type, `| null` when nullable. */\nfunction rowType(def: ColumnDef): string {\n const base = baseTsType(def);\n return def.nullable ? `${base} | null` : base;\n}\n\n/** True when a column may be omitted on INSERT — nullable OR has any default.\n * Mirrors `ColIsOptionalOnInsert` in columns.ts. */\nfunction optionalOnInsert(def: ColumnDef): boolean {\n return (\n def.nullable === true ||\n def.defaultRandom === true ||\n def.defaultNow === true ||\n def.defaultValue !== undefined\n );\n}\n\n\n\nexport type Relation = {\n name: string;\n to: string;\n kind: \"one\" | \"many\";\n /**\n * The foreign-key COLUMN the relation runs through.\n *\n * Without it \"there is a relation\" is half the fact, and everything that\n * consumes the map — the query builder, the seed engine, the cross-boundary\n * lock — has to re-derive the column: a second interpreter of the same graph.\n */\n via: string;\n};\n\n/** `list_id` → `list`; anything else keeps its column name (FR-019). */\nfunction forwardName(column: string): string {\n return column.endsWith(\"_id\") ? column.slice(0, -3) : column;\n}\n\n/**\n * Where a relation name came from, so a refusal can say it out loud.\n *\n * A collision on a parent table can be between two REVERSE edges, or between a\n * reverse edge and the parent's own FORWARD one — `lists.todos_id` names a\n * forward `todos`, and `todos.list_id` reverses onto `lists` as `todos` too.\n * The old message called both sides \"reverse relations\", which sent the reader\n * looking for a second reverse edge that was never there.\n */\ntype NameOrigin = {\n /** The table the foreign-key COLUMN is declared on. */\n table: string;\n column: string;\n direction: \"forward\" | \"reverse\";\n def: ColumnDef;\n};\n\nfunction describeOrigin(o: NameOrigin): string {\n return o.direction === \"forward\"\n ? `the foreign key \"${o.table}.${o.column}\"`\n : `the reverse of \"${o.table}.${o.column}\"`;\n}\n\n/**\n * The call that renames THIS relation — named per verb, because the verbs do\n * not take the same options.\n *\n * NFR-002 asks every refusal to name a remedy the reader can apply. The old\n * message said `references(() => …, { as: \"…\" })` for every case, and\n * `ownedByUser()` takes no arguments at all while `userRef` /\n * `installationRef` take `{ onDelete, as }` — so following it literally was\n * impossible for exactly the columns that most often collide.\n *\n * A reverse edge only ever exists for a target that is a DECLARED table, and\n * only `references()` can point at one: `auth.*` is not declared (no reverse\n * edge) and a self-reference has no separate parent (skipped). So the reverse\n * remedy has one form and it is always the right one.\n */\nfunction renameCall(o: NameOrigin): string {\n if (o.direction === \"reverse\") return `references(() => …, { reverseAs: \"…\" })`;\n if (o.def.owns === true) {\n return `ownedByUser() takes no { as } — if \"${o.column}\" only POINTS at a user, declare it userRef({ onDelete: … }) instead`;\n }\n const target = o.def.references?.table;\n if (target === \"auth.users\") return `userRef({ onDelete: …, as: \"…\" })`;\n if (target === \"auth.installations\") return `installationRef({ onDelete: …, as: \"…\" })`;\n if (o.def.selfRefColumn !== undefined) return `selfReferences(\"…\", { as: \"…\" })`;\n return `references(() => …, { as: \"…\" })`;\n}\n\n/**\n * Derive the relation graph from the declared foreign keys.\n *\n * Until now a SECOND foreign key onto the same parent was silently dropped: only\n * the first column in declaration order was recorded, and the other one quietly\n * became an ordinary writable column. Which relation you got was decided by the\n * order somebody happened to type the columns in. That silence is what this\n * function exists to end — ambiguity is rejected and named, never resolved by\n * declaration order.\n *\n * THE HAZARD IS ONE NAME WITH TWO RELATIONS (FR-022), not two foreign keys onto\n * one target. Those are not the same set, and treating them as one refused the\n * package's own documented shape: a table with `ownedByUser()` beside a\n * `userRef()` has two foreign keys onto `auth.users` and no ambiguity whatever —\n * the names are `owner` and the pointing column's own, and `auth.users` is not a\n * declared table, so neither takes a reverse edge to collide over. The gate\n * counted the owner toward the total while exempting it from the naming\n * requirement, so `docs/schema.md`'s example threw, naming a remedy no verb in\n * it accepts.\n *\n * The two directions are named SEPARATELY. `as` sets the forward name (FR-019),\n * `reverseAs` sets the reverse one (FR-020, whose default is the child table's\n * name). One option cannot set both: two children that each name their forward\n * edge `author` collided on the parent as `author`, and the refusal asked for\n * the `{ as }` they had both already written — a refusal with no exit.\n */\nexport function buildRelations(schemas: readonly SchemaDef[]): Map<string, Relation[]> {\n const out = new Map<string, Relation[]>();\n /** Per table key: relation name → where that name came from. */\n const taken = new Map<string, Map<string, NameOrigin>>();\n for (const schema of schemas) {\n for (const t of Object.values(schema.tables)) {\n const key = qualifiedTableKey(schema.name, t.name);\n out.set(key, []);\n taken.set(key, new Map());\n }\n }\n\n /** Record one edge on `tableKey`, or refuse the name it would take twice. */\n const claim = (tableKey: string, name: string, origin: NameOrigin, edge: Relation): void => {\n const names = taken.get(tableKey);\n if (names === undefined) return;\n const held = names.get(name);\n if (held !== undefined) {\n // FR-015 asks this one to LIST the conflicting columns; it used to name\n // neither, so the reader had to find them.\n if (held.def.owns === true && origin.def.owns === true) {\n throw new Error(\n `table \"${tableKey}\" declares TWO owner columns (${held.column}, ${origin.column}) — a table has at most ONE ownedByUser(). If the other column only POINTS at a user, declare it userRef({ onDelete: … }) instead.`,\n );\n }\n const heldFix = renameCall(held);\n const originFix = renameCall(origin);\n const remedy =\n heldFix === originFix\n ? `rename one of them: ${heldFix}`\n : `rename one of them — \"${held.table}.${held.column}\": ${heldFix}; \"${origin.table}.${origin.column}\": ${originFix}`;\n throw new Error(\n `table \"${tableKey}\": ${describeOrigin(held)} and ${describeOrigin(origin)} both resolve to the relation name \"${name}\" — ${remedy}.`,\n );\n }\n names.set(name, origin);\n out.get(tableKey)?.push(edge);\n };\n\n for (const schema of schemas) {\n for (const table of Object.values(schema.tables)) {\n const childKey = qualifiedTableKey(schema.name, table.name);\n if (!out.has(childKey)) continue;\n\n for (const [col, builder] of Object.entries(table.columns)) {\n const def = builder._def;\n if (def.references === undefined) continue;\n // `references.table` IS the canonical key — `resolveReferences` wrote it\n // with `qualifiedTableKey`, so public is bare and everything else is\n // qualified, `auth.users` included.\n //\n // It used to be re-derived here from a bare-name → key map, which gave a\n // DIFFERENT answer in exactly one case: two schemas declaring the same\n // table name. The map kept whichever was declared LAST, so a public FK\n // was relabelled onto another schema's table and the real parent got no\n // reverse edge — silently, while RefJSON (and therefore the DDL) went on\n // pointing at the right one. The generated type and the database\n // disagreed, and nothing said so.\n const targetKey = def.references.table;\n\n const name = def.owns === true ? \"owner\" : (def.refAs ?? forwardName(col));\n claim(\n childKey,\n name,\n { table: table.name, column: col, direction: \"forward\", def },\n { name, to: targetKey, kind: \"one\", via: col },\n );\n\n // Reverse edge, unless the FK points outside the declared schemas (auth.users)\n // or back at the declaring table (a self-reference has no separate parent).\n if (!out.has(targetKey) || targetKey === childKey) continue;\n // FR-020: the reverse name is the CHILD TABLE's, not the forward name.\n // `as` used to set this too, which both broke FR-020 for a single named\n // FK (`users.author` where `users.posts` was required) and left two\n // children that chose the same forward name with no way to be declared.\n const reverse = def.reverseAs ?? table.name;\n claim(\n targetKey,\n reverse,\n { table: table.name, column: col, direction: \"reverse\", def },\n { name: reverse, to: childKey, kind: \"many\", via: col },\n );\n }\n }\n }\n return out;\n}\n\n\n\n\n/** Emit the `row` / `insert` / `relations` blocks for one table at the given\n * base indentation. */\nfunction tableBlock(table: TableDef, relations: Relation[], indent: string): string {\n const cols = Object.entries(table.columns);\n const rowLines = cols.map(([col, builder]) => {\n return `${indent} ${col}: ${rowType(builder._def)};`;\n });\n const insertLines = cols.map(([col, builder]) => {\n const def = builder._def;\n const opt = optionalOnInsert(def) ? \"?\" : \"\";\n return `${indent} ${col}${opt}: ${rowType(def)};`;\n });\n const relEntries = relations\n .map(\n (r) =>\n `${r.name}: { to: ${JSON.stringify(r.to)}; kind: ${JSON.stringify(r.kind)}; via: ${JSON.stringify(r.via)} }`,\n )\n .join(\"; \");\n return [\n `${indent}${table.name}: {`,\n `${indent} row: {`,\n ...rowLines,\n `${indent} };`,\n `${indent} insert: {`,\n ...insertLines,\n `${indent} };`,\n `${indent} relations: {${relEntries === \"\" ? \"\" : ` ${relEntries} `}};`,\n // searchable: vector kolonu YA DA search beyanı → EnvTypedTable'da search()\n // üyesini açan yapısal bayrak (FR-013). Yokken satır hiç üretilmez ki\n // mevcut şemaların d.ts'i bayt-aynı kalsın.\n ...(cols.some(([, b]) => b._def.type === \"vector\") || table.search !== undefined\n ? [`${indent} searchable: true;`]\n : []),\n // appendOnly (FR-031): EnvTypedTable'ın altı yazma üyesini KALDIRAN yapısal\n // bayrak. `searchable` ile aynı desen ve aynı OMIT disiplini — bayrak yokken\n // satır hiç üretilmez ki mevcut şemaların d.ts'i bayt-aynı kalsın.\n ...(table.appendOnly === true ? [`${indent} appendOnly: true;`] : []),\n `${indent}};`,\n ].join(\"\\n\");\n}\n\n/**\n * Generate the full `palbase-env.d.ts` text for the project's schemas.\n *\n * The emitted file ends in `export {};` — same as `makeStackDts`. Without it the\n * `.d.ts` is a global script, and `declare module \"…\"` there DECLARES an ambient\n * module (shadowing the real one, so every export of `@palbase/backend/env`\n * silently becomes invalid) instead of AUGMENTING it. Measured on a minimal tsc\n * repro: with the line, exit 0; without it, `TS2305: Module '\"…\"' has no\n * exported member`. The line was dropped once in a rewrite and nothing caught\n * it, so `env-gen.test.ts` now gates it directly.\n *\n * @example\n * import { makeEnvDts } from \"@palbase/backend\";\n * import publicSchema from \"./db/public.js\";\n * import billing from \"./db/billing.js\";\n * writeFileSync(\"palbase-env.d.ts\", makeEnvDts([publicSchema, billing]));\n */\nexport function makeEnvDts(schemas: readonly SchemaDef[]): string {\n // No pruning: `relations` is a flat literal map, so it cannot expand into an\n // infinite type the way the old recursive `children` could. Dropping a back-edge\n // here would delete a REAL relation and make the type lie about the schema.\n const relations = buildRelations(schemas);\n\n const publicSchema = schemas.find((s) => s.name === \"public\");\n const others = schemas.filter((s) => s.name !== \"public\");\n\n const publicBlocks = Object.keys(publicSchema?.tables ?? {}).map((name) =>\n tableBlock(publicSchema!.tables[name]!, relations.get(name) ?? [], \" \"),\n );\n const body = publicBlocks.length > 0 ? `\\n${publicBlocks.join(\"\\n\")}\\n ` : \"\";\n\n const schemaBlocks = others.map((schema) => {\n const inner = Object.keys(schema.tables).map((name) =>\n tableBlock(schema.tables[name]!, relations.get(qualifiedTableKey(schema.name, name)) ?? [], \" \"),\n );\n return ` ${schema.name}: {\\n${inner.join(\"\\n\")}\\n };`;\n });\n const schemasBody = schemaBlocks.length > 0 ? `\\n${schemaBlocks.join(\"\\n\")}\\n ` : \"\";\n\n return `// AUTO-GENERATED by @palbase/backend — DO NOT EDIT.\n// Regenerated from db/*.ts by \\`palbase build\\` and by every deploy.\n// Augments the @palbase/backend/env \\`Tables\\` interface so \\`Database.public.*\\`\n// is typed with no import and no generic. Schemas other than \\`public\\` land\n// under \\`Schemas\\`, reached with \\`Database.schema(\"<name>\").tables.*\\`.\n\ndeclare module \"@palbase/backend/env\" {\n interface Tables {${body}}\n interface Schemas {${schemasBody}}\n}\n\nexport {};\n`;\n}\n","import { type Token } from \"./module.js\";\n\n/**\n * The slot injectable declarations accumulate in.\n *\n * On `globalThis` under a well-known Symbol for the same reason `DI_MODULES` is\n * (see `module.ts`): a tenant bundle inlines its OWN copy of `@palbase/backend`\n * and the engine that loads it carries another, so a module-local array would\n * have the decorators push into one and the container read the other.\n */\nexport const DI_INJECTABLES: unique symbol = Symbol.for(\n \"palbase.backend.diInjectables\",\n) as never;\n\n/**\n * The marker `@Injectable()` leaves ON the class.\n *\n * Two signals, because two questions are being asked and only one of them can be\n * answered by a list. \"WHICH classes were declared in this build\" needs an\n * enumeration and gets the claimable slot below. \"IS this class decorated\" needs\n * an answer that survives Bun's module cache: a rollback re-imports an artifact\n * whose body does not run again, so the slot comes back empty while the modules\n * still list the same classes. Reading the slot for that question refused a\n * correct app — measured in `engine.test.ts`, where the second `createApp` in\n * one process saw an emptied slot and called every provider undecorated.\n */\nexport const INJECTABLE: unique symbol = Symbol.for(\"palbase.backend.injectable\") as never;\n\n/** Does this class carry `@Injectable()`? Reads the class, not a registry. */\nexport const isInjectable = (c: unknown): boolean =>\n (c as Record<symbol, unknown> | null)?.[INJECTABLE] === true;\n\nfunction slot(): Token[] {\n const g = globalThis as unknown as Record<symbol, Token[] | undefined>;\n return (g[DI_INJECTABLES] ??= []);\n}\n\n/**\n * Marks a class the container can resolve.\n *\n * TWO JOBS, and the first one is why the decorator has to exist at all:\n * TypeScript under `emitDecoratorMetadata` emits `design:paramtypes` for\n * DECORATED classes only. Measured — an undecorated class with the same\n * constructor carries no metadata, and `Reflect.getMetadata` answers\n * `undefined`.\n *\n * The second is being COUNTABLE. Ownership, visibility and permission are still\n * read from a single `@Module` and never from this decorator — recording the\n * class here decides nothing. It only makes \"carries `@Injectable()` and\n * appears in no module\" a question the build can ask, which FR-010 requires it\n * to answer by name. The body was empty until 2026-09-02, and the consequence\n * was measured through the CLI: an `@Injectable()` service in no module built\n * clean, while this file's own comment claimed the build named it.\n */\nexport function Injectable(): ClassDecorator {\n return (target) => {\n (target as unknown as Record<symbol, unknown>)[INJECTABLE] = true;\n slot().push(target as unknown as Token);\n };\n}\n\n/**\n * TAKES the accumulated declarations — it does not read them.\n *\n * Same claim semantics as `__claimModules`, and for the same reason: a\n * candidate bundle is imported into the SAME process as the live app it might\n * replace, so reading would let a candidate be judged against the live app's\n * classes and a discarded candidate would leave its own behind.\n */\nexport function __claimInjectables(): Token[] {\n return slot().splice(0);\n}\n","import type { Container, Token } from \"../container.js\";\n\n/**\n * Which of a container's classes are entry points of each kind.\n *\n * Discovery used to be a DIRECTORY: `jobs/*.ts` was the list of jobs, and\n * `@Job` recorded metadata but registered nothing. That made the file system a\n * second declaration — a class could carry `@Job`, sit outside `jobs/`, and\n * never run; or sit inside it, be listed in no module, and run anyway.\n *\n * Now a module lists it and the decorator says what it is. One declaration\n * answers ownership, and the metadata answers kind. These four predicates are\n * the only place that mapping lives.\n */\nconst JOB = Symbol.for(\"palbase.backend.jobMeta\");\nconst WEBHOOK = Symbol.for(\"palbase.backend.webhookMeta\");\nconst HOOK_BLOCKING = Symbol.for(\"palbase.backend.hookBlocking\");\nconst HOOK_LISTENERS = Symbol.for(\"palbase.backend.webhookEvents\");\nconst ROOM = Symbol.for(\"palbase.backend.room\");\nconst CONTROLLER = Symbol.for(\"palbase.backend.controllerMeta\");\n\nconst has = (c: unknown, s: symbol): boolean =>\n (c as Record<symbol, unknown>)[s] !== undefined;\n\n/**\n * Does this class carry one of the surface decorators?\n *\n * The container asks, because `providers` legitimately holds `@Job`, `@Hook`,\n * `@Webhook` and `@Room` classes alongside `@Injectable()` ones, and the rule it\n * enforces there — a provider must be DECORATED, so it is constructible and its\n * constructor's types were emitted — has to know that. The predicate lives here\n * because this file is the one place the marker symbols are named.\n */\nexport const isEntryPointClass = (c: unknown): boolean =>\n has(c, JOB) || has(c, WEBHOOK) || has(c, ROOM) || has(c, CONTROLLER) ||\n has(c, HOOK_BLOCKING) || has(c, HOOK_LISTENERS);\n\nconst owned = (container: Container): Token[] => [...container.owned];\n\nexport const jobsOf = (container: Container): Token[] => owned(container).filter((c) => has(c, JOB));\n\nexport const webhooksOf = (container: Container): Token[] =>\n owned(container).filter((c) => has(c, WEBHOOK));\n\n/**\n * A hook class carries handler entries and NO class-level marker, so it is\n * recognised by having handlers while being neither a webhook nor a controller.\n * `@On` is shared with `@Webhook`, which is why the webhook marker is what\n * separates them.\n */\nexport const hooksOf = (container: Container): Token[] =>\n owned(container).filter(\n (c) =>\n !has(c, WEBHOOK) &&\n !has(c, CONTROLLER) &&\n (has(c, HOOK_BLOCKING) || has(c, HOOK_LISTENERS)),\n );\n\nexport const roomsOf = (container: Container): Token[] =>\n owned(container).filter((c) => has(c, ROOM));\n\nexport const controllersOf = (container: Container): Token[] =>\n owned(container).filter((c) => has(c, CONTROLLER));\n","/**\n * A class the container can resolve, named by its own constructor.\n *\n * There is NO separate token concept — no strings, no symbols, no `@Inject`.\n * An abstraction is an `abstract class`, which is still a runtime value and so\n * is still a token. `never[]` on the parameters makes a token something you can\n * NAME but not call: `Token` is an identity, not a factory.\n */\nexport type Token<T = unknown> = abstract new (...args: never[]) => T;\n\n/**\n * The four lists a module declares.\n *\n * `providers` is OWNERSHIP — a class belongs to exactly one module and this is\n * where that is said. `exports` is VISIBILITY — what other modules may reach.\n * `imports` is PERMISSION — whose exports this module may reach. `controllers`\n * are the entry points the module owns.\n *\n * Position in a list means nothing; ownership is read from this declaration and\n * from nowhere else — not from a directory, not from a file name, not from the\n * class's own decorator (spec FR-009).\n */\nexport interface ModuleDef {\n imports?: Token[];\n controllers?: Token[];\n providers?: Token[];\n exports?: Token[];\n}\n\n/**\n * The slot module declarations accumulate in.\n *\n * On `globalThis` under a well-known Symbol, for the same reason\n * `lifecycleHooks` is (runtime.ts:210): a tenant bundle inlines its OWN copy of\n * `@palbase/backend`, and the engine that loads it carries another. Two\n * module-local arrays would mean the engine reads the empty one — decorators\n * push into the bundle's copy, `createApp` claims from the engine's, and every\n * module silently disappears.\n */\nexport const DI_MODULES: unique symbol = Symbol.for(\"palbase.backend.diModules\") as never;\n\n/** One `@Module` declaration: the class that carried it, and what it declared. */\nexport interface ModuleEntry {\n mod: Token;\n def: ModuleDef;\n}\n\nfunction slot(): ModuleEntry[] {\n const g = globalThis as unknown as Record<symbol, ModuleEntry[] | undefined>;\n return (g[DI_MODULES] ??= []);\n}\n\n/**\n * Declares a module.\n *\n * There is no root module and nothing to mount it into: registration IS the\n * decorator running, which happens when the file is imported. A project with no\n * module file at all is not an error — it simply owns nothing, and every entry\n * point it declares is refused by name (FR-035) rather than quietly served.\n */\nexport function Module(def: ModuleDef): ClassDecorator {\n return (target) => {\n slot().push({ mod: target as unknown as Token, def });\n };\n}\n\n/**\n * TAKES the accumulated declarations — it does not read them.\n *\n * Same reason `__runStartHooks` splices (runtime.ts:297): a candidate bundle is\n * imported into the SAME process as the live app it might replace. Reading\n * would let the candidate build a container out of the live app's modules, and\n * a discarded candidate would leave its own behind for the next release to\n * adopt. Claiming makes each `createApp` see exactly the modules imported since\n * the last one, and a rollback leave nothing behind.\n */\nexport function __claimModules(): ModuleEntry[] {\n return slot().splice(0);\n}\n","import \"reflect-metadata\";\n\nimport { __claimInjectables, isInjectable } from \"./decorators/injectable.js\";\nimport { isEntryPointClass } from \"./decorators/kinds.js\";\nimport { __claimModules, type ModuleDef, type Token } from \"./decorators/module.js\";\n\n/**\n * `Token` is born in `decorators/module.ts` — the atom of a module's lists — and\n * re-exported here so a reader meets it on the container's surface too. ONE\n * definition: two would be two `abstract new (...)` signatures free to drift.\n */\nexport type { Token };\n\n/**\n * How a container refuses.\n *\n * Every refusal is one of these, and every one names the class involved. There\n * is deliberately no \"unknown\" member: a failure this list cannot classify is a\n * failure the error surface has not been taught to explain, and that is a defect\n * rather than a category.\n */\nexport type DiKind =\n | \"unresolvable dependency\"\n | \"private dependency\"\n | \"missing import\"\n | \"unowned class\"\n | \"dependency cycle\"\n | \"metadata missing\"\n | \"generic dependency\"\n | \"duplicate ownership\"\n | \"unknown export\"\n | \"unknown import\"\n | \"undeclared provider\";\n\n/**\n * A refusal carries four parts: what kind, the full resolution path, where\n * exactly, and what to do about it.\n *\n * The shape is borrowed on purpose — Angular's path, Awilix's failure kind, and\n * Nest's list of potential solutions — because each of the three answers a\n * question the other two leave open: what broke, where in the graph, and what\n * the author should type next.\n */\nexport class DiError extends Error {\n constructor(\n readonly kind: DiKind,\n readonly path: string[],\n readonly at: string,\n detail: string,\n readonly fixes: string[],\n ) {\n super(\n `\\nKind: ${kind}\\n` +\n `Path: ${path.length > 0 ? path.join(\" -> \") : \"(none)\"}\\n` +\n `At: ${at}\\n` +\n `${detail}\\n\\n` +\n `Potential solutions:\\n${fixes.map((f) => ` - ${f}`).join(\"\\n\")}\\n`,\n );\n this.name = \"DiError\";\n }\n}\n\n/** How often a module appears in the OTHERS' `imports`. */\nexport interface ModulePressure {\n module: string;\n pct: number;\n /**\n * How many OTHER modules there were — the denominator.\n *\n * Without it the percentage cannot be read. Measured 2026-09-02: a project\n * with two modules, one importing the other, reports 100% — which is true and\n * says nothing, because \"all of the others\" is one module. A reader deciding\n * whether a module has become ambient needs to know whether 80% was four\n * modules or one.\n */\n of: number;\n}\n\nexport interface Container {\n get<T>(t: Token<T>): T;\n /** Every class a module claimed — the set an entry point must be in. */\n readonly owned: ReadonlySet<Token>;\n /**\n * Where `@Global()` pressure is accumulating.\n *\n * A module that appears in more than ~80% of the others' `imports` is one the\n * design is asking to be ambient. That is a JUDGEMENT — how much sharing is\n * too much depends on the domain — so this is reported as a number and never\n * enforced as a gate. Lives on the container rather than in a module-level\n * variable: the runtime builds a candidate's container beside the live app's,\n * and a shared variable would have one overwrite the other's report.\n */\n readonly pressure: readonly ModulePressure[];\n}\n\nconst nameOf = (c: unknown): string => (c as { name?: string } | null)?.name ?? String(c);\n\n/**\n * Values a transpiler emits when a parameter's type has no runtime class.\n *\n * `Object` is the sentinel — an interface, a type alias and a union all collapse\n * to it — and that it is DISTINGUISHABLE from a real class is what lets the\n * container refuse loudly instead of injecting something arbitrary. The\n * primitives are here for the same reason: they are runtime values, so a naive\n * check would happily try to `new` them.\n */\nconst UNRESOLVABLE = new Set<unknown>([\n Object,\n Function,\n String,\n Number,\n Boolean,\n Array,\n Symbol,\n Promise,\n Date,\n undefined,\n null,\n]);\n\n/** The subset worth naming separately: these say \"you passed DATA\" (FR-036). */\nconst DATA = new Set<unknown>([String, Number, Boolean, Date, Symbol]);\n\n/**\n * Does this class SAY what its constructor asks for?\n *\n * The one predicate for the metadata-against-arity cross-check.\n * `assertZeroArgConstructor` calls this rather than re-deriving it: two copies\n * of the rule are two rules, free to drift the moment one is edited.\n */\nexport function declaresDependencies(ctor: unknown): boolean {\n const arity = (ctor as { length?: number } | null)?.length ?? 0;\n if (arity === 0) return true;\n const meta = Reflect.getMetadata(\"design:paramtypes\", ctor as object) as unknown[] | undefined;\n return meta !== undefined && meta.length === arity;\n}\n\n/**\n * Validates the declared modules and returns a container over them.\n *\n * Validation runs in a fixed order, and the order is the point: each stage may\n * assume the previous one held, so a message never has to hedge. Ownership\n * before exports, exports before dependencies, dependencies before cycles,\n * cycles before construction.\n *\n * Stages 3-5 (dependencies and visibility, cycles, resolution) are added by the\n * tasks that follow; this file grows, it is not replaced.\n */\nexport function buildContainer(): Container {\n // CLAIMS the declarations rather than reading them — see `__claimModules`.\n const entries = __claimModules();\n // Claimed HERE even when the graph is about to be refused below, so a failed\n // build cannot leave a previous import's classes for the next one to inherit.\n const declared = __claimInjectables();\n\n // 0 · a project declares at least one module.\n //\n // There is no implicit module. An implicit one would be a SECOND way for a\n // class to become owned, and the whole design rests on there being one: read\n // the module, know the answer.\n if (entries.length === 0) {\n throw new DiError(\n \"unowned class\",\n [],\n \"project\",\n \"no module was declared — every project declares at least one @Module.\",\n [\n \"create `<domain>.module.ts` with @Module({ controllers: [...], providers: [...] })\",\n \"`palbase init` scaffolds one for you\",\n ],\n );\n }\n\n // 1 · ownership — a class belongs to at most one module.\n //\n // `providers` and `controllers` share ONE namespace: a class is owned or it is\n // not, and being listed as both would make \"which module owns it\" a question\n // with two answers.\n const declaredModules = new Set<Token>(entries.map((e) => e.mod));\n\n const owner = new Map<Token, string>();\n for (const { mod, def } of entries) {\n const m = nameOf(mod);\n for (const c of [...(def.providers ?? []), ...(def.controllers ?? [])]) {\n const prev = owner.get(c);\n if (prev !== undefined) {\n throw new DiError(\n \"duplicate ownership\",\n [nameOf(c)],\n `${prev} & ${m}`,\n `${nameOf(c)} is listed by two modules, so which one owns it has two answers.`,\n [\n `remove ${nameOf(c)} from ${prev}`,\n `or remove it from ${m}`,\n `if both modules need it, keep ONE owner and export it, then import that module`,\n ],\n );\n }\n owner.set(c, m);\n }\n }\n\n // 1a · every provider is a class the container can actually BUILD.\n //\n // Measured 02.09.2026: a module that listed an `abstract class` in its\n // `providers` got `new Clock()` — which succeeds in JavaScript and returns an\n // object missing every abstract member — injected into everything that asked\n // for it, and the failure surfaced mid-request as `c.now is not a function`.\n // FR-055 already refuses that shape when the abstraction is named as a\n // DEPENDENCY; this is the same defect coming in through the other door, and\n // the SDK's own test asserted the broken shape was legal.\n //\n // The signal is the decorator. An abstraction in this design is an UNDECORATED\n // `abstract class` (the scaffold's `NoteRepo`), and an implementation carries\n // `@Injectable()`; surfaces carry `@Job`/`@Hook`/`@Webhook`/`@Room`. So a\n // provider carrying none of them is either an abstraction listed in the wrong\n // place or a class somebody forgot to decorate — and the second is not benign\n // either: without a decorator TypeScript emits no `design:paramtypes`, so\n // every constructor parameter it asks for would arrive `undefined`.\n {\n for (const { mod, def } of entries) {\n for (const p of def.providers ?? []) {\n if (isInjectable(p) || isEntryPointClass(p)) continue;\n // A class whose constructor ASKS for something but carries no emitted\n // types is a different fault with a better message — `metadata missing`\n // in stage 3, which explains `emitDecoratorMetadata` and the bundler.\n // Leaving it to that stage keeps each refusal pointed at one cause. The\n // abstract seam this rule is for has a zero-argument constructor\n // (`abstract class NoteRepo { abstract findMany(…) }`), so it lands\n // here.\n if (!declaresDependencies(p)) continue;\n throw new DiError(\n \"undeclared provider\",\n [nameOf(mod), nameOf(p)],\n `${nameOf(mod)}.providers`,\n `${nameOf(p)} is listed in ${nameOf(mod)}.providers but carries no decorator, ` +\n `so the container cannot know it is constructible or what its constructor asks for.`,\n [\n `mark ${nameOf(p)} \\`@Injectable()\\` if it is a concrete class`,\n `if ${nameOf(p)} is an \\`abstract class\\`, list the class that \\`extends\\` it instead — ` +\n `name the abstraction as the DEPENDENCY and the container resolves it`,\n ],\n );\n }\n }\n }\n\n // 1b · every declared class is OWNED by a module (FR-010).\n //\n // `@Injectable()` decides nothing — ownership is read from a module and from\n // nowhere else — but it makes the class COUNTABLE, and this is the question\n // that needs counting: a service written, imported, and listed in no module.\n // It has no entry point, so `assertNoOrphanEntryPoints` never sees it; it has\n // no dependent, so the resolution stages never reach it. It simply does not\n // exist, silently, which is the one outcome this design refuses everywhere\n // else. Measured through the CLI on 2026-09-02: the build said \"build OK\".\n //\n // Not in `isolated()`: that builds a graph without consulting this file at\n // all, deliberately, because a unit test is not a second opinion about the\n // architecture.\n {\n const orphans = declared.filter((c) => !owner.has(c));\n if (orphans.length > 0) {\n const names = orphans.map(nameOf);\n throw new DiError(\n \"unowned class\",\n names,\n \"module declarations\",\n `${names.join(\", \")} ${orphans.length === 1 ? \"is\" : \"are\"} marked @Injectable() ` +\n `but listed in no module's providers, so nothing can reach ${orphans.length === 1 ? \"it\" : \"them\"}.`,\n [\n `add ${names.length === 1 ? names[0] : \"each of them\"} to a module's \\`providers\\``,\n \"or delete the class — one no module lists is never built\",\n ],\n );\n }\n }\n\n // 2 · exports — a module may only open up what it OWNS.\n //\n // Re-exporting someone else's class would be a hole in the boundary the\n // module system exists to draw: the owner's decision about who may reach it\n // would stop being the owner's.\n const exported = new Map<string, Set<Token>>();\n const importsOf = new Map<string, Set<string>>();\n for (const { mod, def } of entries) {\n const m = nameOf(mod);\n for (const e of def.exports ?? []) {\n if (owner.get(e) !== m) {\n const holder = owner.get(e);\n throw new DiError(\n \"unknown export\",\n [m],\n `${m}.exports`,\n holder === undefined\n ? `${m} exports ${nameOf(e)}, but no module owns it.`\n : `${m} exports ${nameOf(e)}, but ${holder} owns it — a module cannot re-export another's class.`,\n holder === undefined\n ? [`add ${nameOf(e)} to ${m}.providers`, `or remove it from ${m}.exports`]\n : [\n `remove ${nameOf(e)} from ${m}.exports`,\n `and have ${holder} export it instead, then add ${holder} to the importing module's imports`,\n ],\n );\n }\n }\n // An `imports` entry must BE a module. Measured before this check existed:\n // `@Module({ imports: [NotAModule] })` built cleanly and did nothing — the\n // name simply never matched an owner, so every dependency it was meant to\n // unlock kept being refused for a reason that pointed elsewhere.\n for (const i of def.imports ?? []) {\n // Self-import is expressible — legacy decorators run after the class\n // binding exists, so `@Module({ imports: [M] }) class M {}` compiles and\n // ran silently before this check. It grants a module access to its own\n // exports, which it already has, so it is always a typo for another name.\n if (i === mod) {\n throw new DiError(\n \"unknown import\",\n [m],\n `${m}.imports`,\n `${m} imports itself, which grants nothing it does not already have.`,\n [`remove ${m} from its own imports`, \"or name the module you meant instead\"],\n );\n }\n if (!declaredModules.has(i)) {\n throw new DiError(\n \"unknown import\",\n [m],\n `${m}.imports`,\n `${m} imports ${nameOf(i)}, which is not a module.`,\n [\n `add @Module({ ... }) to ${nameOf(i)}`,\n `or remove ${nameOf(i)} from ${m}.imports — to reach a class, import the module that OWNS it`,\n ],\n );\n }\n }\n\n exported.set(m, new Set(def.exports ?? []));\n importsOf.set(m, new Set((def.imports ?? []).map(nameOf)));\n }\n\n // 3 · dependencies — metadata against arity, then type validity, then module\n // visibility. In that order, because each answer makes the next question\n // meaningful.\n const deps = new Map<Token, Token[]>();\n\n /**\n * The owned classes that EXTEND `t`.\n *\n * `abstract` does not exist at runtime — JavaScript happily runs `new Clock()`\n * and returns an object missing every abstract member. Measured before this\n * existed: the container injected exactly that, the build was green, and the\n * failure surfaced mid-request as `c.now is not a function`.\n *\n * So an abstraction is resolved through its implementation, and the\n * relationship is read from the prototype chain — which is what `extends`\n * builds. That is a DECLARATION the class makes about itself, not an\n * inference from where its file sits.\n *\n * Only consulted for a token NOTHING owns. A class that IS owned is the\n * answer to its own name, so an unrelated `extends` elsewhere can never\n * change what an existing dependency resolves to.\n */\n const implementorsOf = (t: Token): Token[] =>\n [...owner.keys()].filter(\n (c) => c !== t && Object.prototype.isPrototypeOf.call(t as object, c as object),\n );\n\n // Is missing metadata GLOBAL or local? Decided BEFORE any per-class message,\n // because the two faults look identical one class at a time and lead to\n // opposite fixes: all of them missing means the build ran without\n // `emitDecoratorMetadata` (or without `reflect-metadata`, whose absence makes\n // the emitted helper a silent no-op); some of them missing means the author\n // forgot `@Injectable()` on those. Telling someone to decorate a class when\n // the flag is off sends them to edit a file that is not the problem.\n //\n // NOT a synthetic canary. An earlier design embedded a probe class in the SDK\n // and asked whether IT carried metadata — but the SDK is built with tsup, and\n // esbuild emits zero `__metadata` (measured), so that probe would report a\n // global fault on every healthy boot. The tenant's OWN classes are the only\n // honest sample of the tenant's build.\n const withArity = [...owner.keys()].filter(\n (c) => (c as unknown as { length: number }).length > 0,\n );\n const missingMeta = withArity.filter(\n (c) => Reflect.getMetadata(\"design:paramtypes\", c) === undefined,\n );\n // TWO is the smallest sample this inference is honest on. With ONE class,\n // \"all of them are missing\" is also what a single forgotten `@Injectable()`\n // looks like, and telling that author their build is broken sends them to the\n // wrong file. Below the threshold the per-class message runs, which names the\n // class and the decorator.\n if (withArity.length >= 2 && missingMeta.length === withArity.length) {\n throw new DiError(\n \"metadata missing\",\n withArity.map(nameOf),\n \"the whole build\",\n `no class carries constructor metadata — every one of the ${withArity.length} ` +\n `class(es) that asks for a dependency is missing it, so this is the build, ` +\n `not the classes.`,\n [\n \"set `emitDecoratorMetadata: true` in the project's tsconfig.json\",\n \"and import `reflect-metadata` before any decorated class evaluates — without it the emitted helper is a silent no-op\",\n \"if the build is fine, then none of these classes carries @Injectable()\",\n ],\n );\n }\n\n for (const [cls, m] of owner) {\n const arity = (cls as unknown as { length: number }).length;\n\n // ARITY IS THE GROUND TRUTH. It survives every transpile; metadata does not.\n // Measured: a decorated class with no constructor carries `undefined`\n // metadata and a decorated one with an empty constructor carries `[]` —\n // both ask for nothing, and only arity says so. Treating absent metadata as\n // a fault would refuse every dependency-free class that never wrote a\n // constructor, which is most of them.\n if (arity === 0) {\n deps.set(cls, []);\n continue;\n }\n\n // Asked through the shared predicate, so \"does this class say what it needs\"\n // has ONE definition — the same one `assertZeroArgConstructor` answers with.\n if (!declaresDependencies(cls)) {\n const meta = Reflect.getMetadata(\"design:paramtypes\", cls) as unknown[] | undefined;\n throw new DiError(\n \"metadata missing\",\n [nameOf(cls)],\n `${nameOf(cls)} constructor`,\n `${nameOf(cls)} declares ${arity} parameter(s) but carries ` +\n `${meta === undefined ? \"no\" : String(meta.length)} metadata entries, ` +\n `so every parameter would arrive as undefined.`,\n [\n `add @Injectable() to ${nameOf(cls)} — metadata is emitted for DECORATED classes only`,\n \"or the build ran without emitDecoratorMetadata: check tsconfig.json\",\n ],\n );\n }\n\n const meta = Reflect.getMetadata(\"design:paramtypes\", cls) as unknown[];\n const list: Token[] = [];\n meta.forEach((t, i) => {\n const at = `${nameOf(cls)} constructor, parameter ${i}`;\n\n if (typeof t !== \"function\" || UNRESOLVABLE.has(t)) {\n throw new DiError(\n \"unresolvable dependency\",\n [nameOf(cls)],\n at,\n `parameter ${i} has no runtime class — an interface, a type alias, a ` +\n `union, or a data type. The container has nothing to construct.`,\n DATA.has(t)\n ? [\n \"an injectable's constructor takes dependencies, not data\",\n \"move the value to a method argument instead\",\n \"or make this a plain value class (no @Injectable, in no module) and `new` it yourself\",\n ]\n : [\n \"depend on a concrete class or an abstract class\",\n \"a TypeScript interface does not exist at runtime — there is nothing to inject\",\n ],\n );\n }\n\n const dep = t as Token;\n\n {\n let dm = owner.get(dep);\n if (dm === undefined) {\n // An ABSTRACTION, resolved to its one implementation (FR-055).\n //\n // Read from `extends`, not from a second syntax: `class SystemClock\n // extends Clock` is the class declaring \"I am a Clock\", and that is a\n // declaration — not an inference from where a file sits.\n const impls = implementorsOf(dep);\n if (impls.length === 1) {\n const impl = impls[0] as Token;\n list.push(impl);\n dm = owner.get(impl) as string;\n if (dm !== m) {\n if (!importsOf.get(m)?.has(dm)) {\n throw new DiError(\n \"missing import\",\n [nameOf(cls), nameOf(impl)],\n at,\n `${nameOf(impl)} implements ${nameOf(dep)} and is owned by ${dm}, which ${m} does not import.`,\n [`add ${dm} to ${m}.imports`],\n );\n }\n if (!exported.get(dm)?.has(impl)) {\n throw new DiError(\n \"private dependency\",\n [nameOf(cls), nameOf(impl)],\n at,\n `${nameOf(impl)} implements ${nameOf(dep)} but is internal to ${dm}.`,\n [`add ${nameOf(impl)} to ${dm}.exports (and say why)`],\n );\n }\n }\n return;\n }\n if (impls.length > 1) {\n const names = impls.map(nameOf).sort();\n throw new DiError(\n \"duplicate ownership\",\n [nameOf(cls), nameOf(dep)],\n at,\n `${names.join(\" and \")} both extend ${nameOf(dep)}, so which one ` +\n `${nameOf(cls)} should receive has two answers.`,\n [\n `keep ONE class extending ${nameOf(dep)} in this graph`,\n `or depend on ${names[0]} or ${names[1]} directly, by name`,\n ],\n );\n }\n throw new DiError(\n \"unowned class\",\n [nameOf(cls), nameOf(dep)],\n at,\n `${nameOf(dep)} belongs to no module, and nothing in this graph extends it — ` +\n `so there is nothing to construct. (An abstract class cannot be built: ` +\n `\\`abstract\\` is a type-level claim, and \\`new\\` on one returns an object ` +\n `missing every abstract member.)`,\n [\n `add ${nameOf(dep)} to a module's providers if it is concrete`,\n `or add a class that \\`extends ${nameOf(dep)}\\` to a module's providers`,\n ],\n );\n }\n if (dm !== m) {\n if (!importsOf.get(m)?.has(dm)) {\n throw new DiError(\n \"missing import\",\n [nameOf(cls), nameOf(dep)],\n at,\n `${nameOf(dep)} is owned by ${dm}, which ${m} does not import.`,\n [`add ${dm} to ${m}.imports`],\n );\n }\n if (!exported.get(dm)?.has(dep)) {\n throw new DiError(\n \"private dependency\",\n [nameOf(cls), nameOf(dep)],\n at,\n `${nameOf(dep)} is internal to ${dm} — it is not exported.`,\n [\n `use one of ${dm}'s exported classes`,\n `or add ${nameOf(dep)} to ${dm}.exports (and say why it should be public)`,\n ],\n );\n }\n }\n }\n\n list.push(dep);\n });\n\n deps.set(cls, list);\n }\n\n // 4 · cycles — refused, with the path written out by name.\n //\n // There is NO `forwardRef`-style escape, and the reason is that the shape one\n // exists to rescue cannot be built: a real ESM cycle dies at import. Measured\n // in the spike — Bun throws `Cannot access 'CB' before initialization` before\n // the container is ever consulted. What CAN still be assembled is a cycle\n // inside one file, so the detector earns its place; what it never has to do is\n // offer a way to keep one.\n const state = new Map<Token, 0 | 1 | 2>();\n const stack: Token[] = [];\n const walk = (c: Token): void => {\n if (state.get(c) === 1) {\n // Slice from where this class first entered the stack, so the message is\n // the CYCLE and not the path that happened to reach it.\n const cyc = [...stack.slice(stack.indexOf(c)), c].map(nameOf);\n throw new DiError(\n \"dependency cycle\",\n cyc,\n `${cyc[0]} constructor`,\n `the dependency graph contains a cycle: ${cyc.join(\" -> \")}.`,\n [\n \"extract the shared part into a third class both can depend on\",\n \"or invert one direction — have the callee raise an event the caller listens for\",\n ],\n );\n }\n if (state.get(c) === 2) return;\n state.set(c, 1);\n stack.push(c);\n // A platform token needs no special case: it has no `deps` entry, so the\n // walk reaches it, finds nothing to follow, and marks it done. A guard here\n // would be an inert check — it was written, measured against a mutation, and\n // removed when removing it changed nothing.\n for (const d of deps.get(c) ?? []) walk(d);\n stack.pop();\n state.set(c, 2);\n };\n for (const c of owner.keys()) walk(c);\n\n // 5 · resolution — ONE lifetime, singleton.\n //\n // No `transient`, no `request`. Request scope already exists and it is an\n // AsyncLocalStorage, not an object lifetime: what varies per request is the\n // database handle and the claims, and the engine opens that scope around the\n // handler. Making the OBJECTS per-request would duplicate that mechanism and\n // then have to keep the two in agreement.\n //\n // The consequence is a rule about constructors: they stay synchronous and do\n // nothing but wiring. Real I/O belongs in `onStart`, where it can fail loudly\n // at boot instead of halfway through the first request.\n const cache = new Map<Token, unknown>();\n const make = (c: Token): unknown => {\n // A token this container never validated is NOT built. Measured before this\n // check existed: `get(Stranger)` found no `deps` entry, fell through to\n // `new Stranger()` with zero arguments, and returned it — so a class in no\n // module could still be constructed through the container's own front door,\n // which is the hole the module system exists to close (FR-053).\n //\n // There is no platform escape hatch here: platform services (Database, Log,\n // …) are AMBIENT — imported, not injected — because they are request-scoped\n // and a boot-time singleton holding one would capture the first request's\n // client forever (FR-005). Nothing supplies a platform map, so having one\n // would be an inert extension point.\n if (!owner.has(c)) {\n throw new DiError(\n \"unowned class\",\n [nameOf(c)],\n \"container.get\",\n `${nameOf(c)} belongs to no module, so this container never validated it ` +\n `and will not build it.`,\n [\n `add ${nameOf(c)} to a module's providers`,\n \"or, if it is a plain value class, construct it yourself with `new`\",\n ],\n );\n }\n const hit = cache.get(c);\n if (hit !== undefined) return hit;\n const args = (deps.get(c) ?? []).map(make);\n const inst = new (c as unknown as new (...a: unknown[]) => unknown)(...args);\n cache.set(c, inst);\n return inst;\n };\n\n return {\n get: <T,>(t: Token<T>): T => make(t) as T,\n owned: new Set(owner.keys()),\n pressure: computePressure(entries),\n };\n}\n\n/**\n * What fraction of the OTHER modules import each module.\n *\n * `total - 1` is the denominator because a module never imports itself, so the\n * most any module can reach is everyone else. Under two modules there is nothing\n * to compare and the answer is an empty list rather than a misleading 100%.\n */\nfunction computePressure(entries: { mod: Token; def: ModuleDef }[]): ModulePressure[] {\n // No `total < 2` guard, and none is needed: a single module cannot import\n // anything (there is no other module, and both self-import and non-module\n // imports are refused above), so `count` is empty and the division below never\n // runs. The guard was written, measured against a mutation, and removed when\n // removing it changed nothing — an inert check still draws a number.\n const total = entries.length;\n const count = new Map<string, number>();\n for (const { def } of entries) {\n for (const i of def.imports ?? []) {\n const n = nameOf(i);\n count.set(n, (count.get(n) ?? 0) + 1);\n }\n }\n return [...count]\n .map(([module, c]) => ({ module, pct: Math.round((c / (total - 1)) * 100), of: total - 1 }))\n .sort((a, b) => b.pct - a.pct);\n}\n\n/** Kept so the module surface is stable while stages 3-5 land. */\nexport type { ModuleDef };\n\n/**\n * Refuses an entry point that no module lists (FR-035).\n *\n * A decorated class registers itself — `@Controller` pushes into a globalThis\n * slot the moment its file is imported — so before this check a class listed in\n * no module still reached the route table, the dispatcher and the OpenAPI\n * document. It worked, which is the problem: nothing said the module system had\n * been bypassed.\n *\n * After this, a successful boot means the two sets are EQUAL: what decorated\n * itself and what a module claimed. That equality is what lets `src/openapi/`\n * stay untouched — it renders the list it is handed, and the list is now the\n * module's.\n */\nexport function assertNoOrphanEntryPoints(\n registered: readonly unknown[],\n owned: ReadonlySet<Token>,\n): void {\n const orphans = registered.filter((c) => !owned.has(c as Token));\n if (orphans.length === 0) return;\n const names = orphans.map((c) => (c as { name?: string }).name ?? \"<anonymous>\");\n throw new DiError(\n \"unowned class\",\n names,\n \"module declarations\",\n `${names.join(\", \")} ${orphans.length === 1 ? \"is\" : \"are\"} decorated as an entry ` +\n `point but listed in no module, so nothing decides whether it should be served.`,\n [\n \"add it to a module's `controllers` (for @Controller) or `providers` (for @Room/@Job/@Hook/@Webhook)\",\n \"an entry point no module lists is never mounted and never reaches the OpenAPI document\",\n ],\n );\n}\n"],"mappings":"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","names":["AsyncLocalStorage","__requestALS","AsyncLocalStorage","runtime","__setRuntime","services","__runWithRuntime","fn","run","__getRuntime","scoped","getStore","Error","LIFECYCLE","Symbol","for","declaredLifecycle","g","globalThis","start","shutdown","onStart","name","hook","push","onShutdown","reason","err","message","String","drain","hooks","h","reverse","console","error","__runStartHooks","slot","splice","cause","drained","__resetLifecycleHooks","makeServiceProxy","key","handler","get","_target","prop","receiver","client","value","Reflect","bind","Proxy","makeTableProxy","ops","prefix","_t","undefined","insert","data","update","q","where","id","set","delete","findById","findMany","opts","put","onConflict","updateMany","deleteMany","count","search","params","similar","recommend","facets","supersede","row","claim","unique","extra","rawDatabase","makeTypedSurface","raw","reco","$query","sql","query","$insert","table","$update","$delete","$findById","$findMany","$put","$updateMany","$deleteMany","$count","$search","$similar","$recommend","$facets","$claim","$lockRows","ids","lockRows","$advisoryXactLock","advisoryXactLock","$supersede","base","Object","assign","$attempt","attempt","$transaction","withRetry","builder","TxPlanBuilder","runTxPlan","makeTxPlanHandle","target","startsWith","qualifiedTableKey","makeTxTablesAccessor","tablesProxy","publicTables","Database","$asService","asService","Documents","makeBucketsAccessor","storage","bucket","rawStorage","Storage","buckets","Cache","Secrets","Log","Notifications","rawFlags","Flags","isEnabled","flagName","context","getVariant","getAll","defaultOrContext","maybeContext","setOverride","Realtime","baseTsType","def","type","values","enumValues","length","map","v","JSON","stringify","join","rowType","base","nullable","optionalOnInsert","defaultRandom","defaultNow","defaultValue","undefined","forwardName","column","endsWith","slice","describeOrigin","o","direction","table","renameCall","owns","target","references","selfRefColumn","buildRelations","schemas","out","Map","taken","schema","t","Object","tables","key","qualifiedTableKey","name","set","claim","tableKey","origin","edge","names","get","held","Error","heldFix","originFix","remedy","push","childKey","has","col","builder","entries","columns","_def","targetKey","refAs","to","kind","via","reverse","reverseAs","tableBlock","relations","indent","cols","rowLines","insertLines","opt","relEntries","r","some","b","search","appendOnly","makeEnvDts","publicSchema","find","s","others","filter","publicBlocks","keys","body","schemaBlocks","inner","schemasBody","DI_INJECTABLES","Symbol","for","INJECTABLE","isInjectable","c","slot","g","globalThis","Injectable","target","push","__claimInjectables","splice","JOB","Symbol","for","WEBHOOK","HOOK_BLOCKING","HOOK_LISTENERS","ROOM","CONTROLLER","has","c","s","undefined","isEntryPointClass","owned","container","jobsOf","filter","webhooksOf","hooksOf","roomsOf","controllersOf","DI_MODULES","Symbol","for","slot","g","globalThis","Module","def","target","push","mod","__claimModules","splice","DiError","Error","kind","path","at","detail","fixes","length","join","map","f","name","nameOf","c","String","UNRESOLVABLE","Set","Object","Function","Number","Boolean","Array","Symbol","Promise","Date","undefined","DATA","declaresDependencies","ctor","arity","meta","Reflect","getMetadata","buildContainer","entries","__claimModules","declared","__claimInjectables","declaredModules","e","mod","owner","Map","def","m","providers","controllers","prev","get","set","p","isInjectable","isEntryPointClass","orphans","filter","has","names","exported","importsOf","exports","holder","i","imports","deps","implementorsOf","t","keys","prototype","isPrototypeOf","call","withArity","missingMeta","cls","list","forEach","dep","dm","impls","impl","push","sort","state","stack","walk","cyc","slice","indexOf","d","pop","cache","make","hit","args","inst","owned","pressure","computePressure","total","count","n","module","pct","Math","round","of","a","b","assertNoOrphanEntryPoints","registered"]}