@palbase/backend 30.0.0 → 32.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.
- package/dist/bin/palbase-backend.cjs +136 -3
- package/dist/bin/palbase-backend.cjs.map +1 -1
- package/dist/bin/palbase-backend.js +7 -7
- package/dist/{chunk-TWX6JTGJ.js → chunk-26GH54D2.js} +3 -5
- package/dist/{chunk-TWX6JTGJ.js.map → chunk-26GH54D2.js.map} +1 -1
- package/dist/{chunk-5J5W75A6.js → chunk-5C5UCILO.js} +27 -325
- package/dist/chunk-5C5UCILO.js.map +1 -0
- package/dist/{chunk-VN7NMDUH.js → chunk-AZJIKCOR.js} +113 -15
- package/dist/chunk-AZJIKCOR.js.map +1 -0
- package/dist/{chunk-VVMJEVQP.js → chunk-BRLJOXWS.js} +2 -2
- package/dist/{chunk-3TUJWHC2.js → chunk-IXAX5CON.js} +378 -19
- package/dist/chunk-IXAX5CON.js.map +1 -0
- package/dist/{chunk-CGNN2PUH.js → chunk-KATPXCJ5.js} +37 -4
- package/dist/{chunk-CGNN2PUH.js.map → chunk-KATPXCJ5.js.map} +1 -1
- package/dist/chunk-KGP6ALIU.js +361 -0
- package/dist/chunk-KGP6ALIU.js.map +1 -0
- package/dist/chunk-XEGZ3S2Q.js +346 -0
- package/dist/chunk-XEGZ3S2Q.js.map +1 -0
- package/dist/{chunk-ENZ2RFFJ.js → chunk-Z4CZRMNF.js} +3 -310
- package/dist/chunk-Z4CZRMNF.js.map +1 -0
- package/dist/db/index.cjs +29 -0
- package/dist/db/index.cjs.map +1 -1
- package/dist/db/index.d.cts +1 -1
- package/dist/db/index.d.ts +1 -1
- package/dist/db/index.js +12 -13
- package/dist/engine/index.cjs +136 -3
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +3 -3
- package/dist/engine/index.d.ts +3 -3
- package/dist/engine/index.js +7 -7
- package/dist/{index-b-Q3l7W5.d.ts → index-BILC9WwS.d.ts} +9 -2
- package/dist/{index-8qy3kIuA.d.ts → index-BgWnP07a.d.ts} +119 -17
- package/dist/{index-Zi7MptvP.d.cts → index-CWGiJ2Up.d.cts} +9 -2
- package/dist/{index-DtCgaZAg.d.cts → index-DgYkdNT9.d.cts} +119 -17
- package/dist/index.cjs +87 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -23
- package/dist/index.d.ts +6 -23
- package/dist/index.js +48 -48
- package/dist/index.js.map +1 -1
- package/dist/openapi/index.d.cts +2 -2
- package/dist/openapi/index.d.ts +2 -2
- package/dist/openapi/index.js +3 -4
- package/dist/openapi/index.js.map +1 -1
- package/dist/{registry-CEYLH-Iz.d.cts → registry-BcRYIQ-R.d.cts} +1 -1
- package/dist/{registry-BGJ-Al6F.d.ts → registry-ClzjxIWy.d.ts} +1 -1
- package/dist/test/index.cjs +703 -14
- package/dist/test/index.cjs.map +1 -1
- package/dist/test/index.d.cts +59 -4
- package/dist/test/index.d.ts +59 -4
- package/dist/test/index.js +51 -13
- package/dist/test/index.js.map +1 -1
- package/docs/README.md +1 -1
- package/docs/database.md +54 -0
- package/docs/llms-full.txt +87 -1
- package/docs/schema.md +32 -0
- package/package.json +1 -1
- package/template/package.json +1 -1
- package/dist/chunk-3TUJWHC2.js.map +0 -1
- package/dist/chunk-5J5W75A6.js.map +0 -1
- package/dist/chunk-ENZ2RFFJ.js.map +0 -1
- package/dist/chunk-SG4UTNOP.js +0 -374
- package/dist/chunk-SG4UTNOP.js.map +0 -1
- package/dist/chunk-VN7NMDUH.js.map +0 -1
- package/dist/chunk-VXPNPVAG.js +0 -40
- package/dist/chunk-VXPNPVAG.js.map +0 -1
- /package/dist/{chunk-VVMJEVQP.js.map → chunk-BRLJOXWS.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/db/schema.ts","../src/db/policy.ts","../src/db/extensions.ts","../src/db/columns.ts","../src/db/raw.ts","../src/db/embedding.ts"],"sourcesContent":["import type { ColumnBuilder } from \"./columns.js\";\nimport { qualifiedTableKey } from \"./schema-json.js\";\nimport { PolicyBuilder, exprCtx } from \"./policy.js\";\nimport type { PolicyDef, PolicyExprCtx, PolicyExpr, PolicyExprRef } from \"./policy.js\";\nimport type { PalbaseExtension } from \"./extensions.js\";\nimport type { RawConstraintDef } from \"./raw.js\";\nimport type { ChatModelRef, EmbeddingModelRef } from \"./embedding.js\";\n\n/**\n * A map of column builders keyed by column name — the value you write under\n * the `columns` key of `defineTable(\"<name>\", { columns })`.\n *\n * The default `Record<string, ColumnBuilder>` keeps bare references compiling\n * without a type argument.\n */\nexport type ColumnMap = Record<string, ColumnBuilder>;\n\n/**\n * The author-facing value written under each table key:\n * `{ columns, rls?, policies? }`.\n *\n * - `columns`: the column map (required).\n * - `rls`: enable + FORCE row-level security on this table. **Defaults to\n * `true`**, and is forced on when `policies` is non-empty. A table with RLS\n * and no policies is deny-all, which is the starting state: nothing reads it\n * until a policy says who may. Set `rls: false` only for a genuinely public\n * table — it is an explicit opt-out that a reviewer can grep for, not\n * something you get by forgetting.\n * - `policies`: the RLS policies for this table, authored with `policy(name)`.\n * Each entry may be a {@link PolicyBuilder} (the normal `policy(...)` chain)\n * or a raw {@link PolicyDef} object.\n *\n * The `C` type parameter preserves the precise per-column phantom types so the\n * typed `Database.public.*` surface keeps inferring insert/row shapes.\n */\n/** Arama metriği — tek kelime; opclass ve operatör bundan türetilir, asla yüzeye çıkmaz (D-5/D-6). */\nexport type SearchMetric = \"cosine\" | \"euclidean\" | \"inner_product\";\n\n/** Bir vektör arama kolu. `model` varsa auto-embed: platform yazma+sorgu embedding'ini üstlenir (D-9). */\nexport interface VectorSearchDecl {\n /** Hedef vector kolonu; tabloda TEK vector kolonu varsa atlanabilir (Go apply çözer, FR-010). */\n column?: string;\n /** Varsa auto-embed. Deskriptor düz veridir — şemayla serileşir (C-3). */\n model?: EmbeddingModelRef;\n /** model varsa ZORUNLU: embed kaynak kolonları = trigger'ın UPDATE OF listesi (C-2). */\n from?: string[];\n metric?: SearchMetric;\n /** Kaynak metin değişince ara-dönem davranışı (yalnız auto-embed'de):\n * \"null\" (vars.) — embedding anında NULL'lanır; satır yeni vektör yazılana\n * dek anlamsal aramada aday değildir. Bayat eşleşme asla servis edilmez.\n * \"keep\" — eski vektör aramada kalır, platform yenisini yazınca sessizce\n * değişir. Görünürlük penceresi sıfır; bedeli saniyeler süren bayat\n * eşleşme riski (Confluence-tipi sync yükleri için). */\n staleness?: \"null\" | \"keep\";\n}\n\n/** Tablonun arama beyanı — İKİ biçim (D-007, tek yüzey):\n *\n * YENİ (önerilen): `{ from, model, ... }` — `from` kolonları hem FTS'e hem\n * embed'e girer. Tabloda vector kolonu declare edilmişse SATIR-modu; yoksa\n * CHUNK-modu otomatiktir (D-010): vektörler türev `__palbase_chunks`\n * tablosunda yaşar, içerik otomatik bölünür. `text: false` FTS'i kapatır,\n * `text: [..]` FTS kolonlarını from'dan ayırır. `chunks` yalnız ince ayar.\n *\n * ESKİ: `text: string[]` + `vector: {...}` — aynen çalışır, wire çıktısı\n * bayt-aynı kalır (NFR-B1). İki biçim KARIŞTIRILAMAZ. */\nexport interface SearchDecl {\n text?: string[] | boolean;\n vector?: VectorSearchDecl | VectorSearchDecl[];\n /** Yeni biçim: arama kaynağı kolonlar (FTS + embed). Varlığı yeni biçimi seçer. */\n from?: string[];\n /** Yeni biçim: auto-embed modeli (zorunlu — BYO için eski biçimi kullanın). */\n model?: EmbeddingModelRef;\n metric?: SearchMetric;\n staleness?: \"null\" | \"keep\";\n /** Chunk-modu ince ayarı (yalnız vector kolonsuz tabloda anlamlı). */\n chunks?: { size?: number; overlap?: number };\n /** Sorgu-yeniden-yazımı: tek yönlü eş anlamlı haritası (FR-026). */\n synonyms?: Record<string, string[]>;\n /** Geçerlilik kolonları türetilir; arama varsayılan yalnız günceli tarar (FR-029). */\n validity?: boolean;\n}\n\n/** Hafıza beyanı (FR-032, D-019): kaynak tablonun yazımlarından platform\n * fact damıtır ve `into` tablosuna yazar. Hedef NORMAL declared tablodur —\n * kendi search/unique/validity beyanlarıyla. Okuma = Database.$search(into).\n * subject default \"owner\": fact'in kime ait olduğu kolonu (iki tabloda da). */\nexport interface MemoryDecl {\n from: string[];\n into: string;\n extract: ChatModelRef;\n subject?: string;\n}\n\n/**\n * Bir index bildiriminin girdi şekli (FR-041…043).\n *\n * `columns` ile `expression` birbirinin alternatifidir: biri kolon listesi,\n * diğeri `lower(email)` gibi bir ifade. `where` partial index koşuludur ve\n * filtre şekli sorgu tarafındaki `WhereFilter` ile aynıdır — iki ayrı filtre\n * dili olmaz.\n */\n/**\n * Bir index'in TEL şekli — `IndexJSON` ile aynı alanlar (T002).\n *\n * Bildirilmeyen alan HİÇ yazılmaz: sıfır değer yazmak, bildirmeyen her index'i\n * diff'te değişmiş gösterir ve her deploy'a boş bir migration ekler.\n */\nexport interface IndexDef {\n name: string;\n columns?: string[];\n expression?: string;\n where?: PolicyExpr;\n sort?: \"asc\" | \"desc\";\n nulls?: \"first\" | \"last\";\n include?: string[];\n}\n\n/**\n * `index(\"<ad>\")` — C-5 (FR-041…043).\n *\n * ```ts\n * indexes: (c) => [\n * index(\"orders_open\")\n * .on(c.col(\"status\")) // kolon TİPLİ\n * .where(c.col(\"deleted_at\").isNull()) // partial\n * .include([\"total\"]), // covering\n * ]\n * ```\n *\n * `policy()` ile AYNI dili konuşur: `where` politika ifade yapısının ta kendisi.\n * Üçüncü bir filtre lehçesi açmak, aynı sorunun iki yazımı demekti.\n *\n * Kolon bağlamı callback'ten geliyor çünkü index tablo tanımının İÇİNDE\n * bildiriliyor — `orders.status` yazmak, `orders` bağlaması o noktada henüz\n * kurulmadığı için mümkün değil (T015'te `policies` için ölçülen aynı kısıt).\n */\nexport class IndexBuilder {\n readonly _def: IndexDef;\n\n constructor(name: string) {\n if (name.trim() === \"\") {\n throw new Error(\"index(ad): index'in adı boş olamaz — Palbase index'leri ADA göre uzlaştırır.\");\n }\n this._def = { name };\n }\n\n /** Index'in kolonları. SIRA KORUNUR — çok kolonlu bir index'in anlamı sırasıdır. */\n on(...cols: PolicyExprRef[]): this {\n this._def.columns = cols.map((c) => {\n const e = c.expr;\n if (e.kind !== \"col\") {\n throw new Error(`index(${this._def.name}).on(): yalnız kolon referansı alır — ifade için onExpression(\"…\") kullanın.`);\n }\n return e.name;\n });\n return this;\n }\n\n /**\n * İfade index'i (`lower(email)`), kolon yerine.\n *\n * Metin VERBATIM emit ediliyor — `policy().using(\"…\")` ile aynı güven duruşu.\n * Tipli yapı bunu ifade edemiyor ve kaçış kapağını kapatmak, yazarı elle\n * migration yazmaya iterdi.\n */\n onExpression(expr: string): this {\n this._def.expression = expr;\n return this;\n }\n\n /** Partial index koşulu — politika ifade dilinin ta kendisi. */\n where(expr: PolicyExprRef): this {\n this._def.where = expr.expr;\n return this;\n }\n\n /** Sıra. Tek yönlü index'te sıra genelde önemsizdir; ORDER BY ile eşleşen\n * bir index arandığında değildir. */\n desc(): this {\n this._def.sort = \"desc\";\n return this;\n }\n\n asc(): this {\n this._def.sort = \"asc\";\n return this;\n }\n\n /** NULL'ların yeri — `ORDER BY … NULLS LAST` ile eşleşmesi için. */\n nulls(where: \"first\" | \"last\"): this {\n this._def.nulls = where;\n return this;\n }\n\n /** Covering index (`INCLUDE`): index-only scan için taşınan ama\n * ARANMAYAN kolonlar. */\n include(cols: string[]): this {\n this._def.include = cols;\n return this;\n }\n}\n\nexport function index(name: string): IndexBuilder {\n return new IndexBuilder(name);\n}\n\nexport interface TableInput<C extends ColumnMap = ColumnMap> {\n columns: C;\n rls?: boolean;\n /**\n * Bu tablonun RLS politikaları — TABLONUN KENDİ KOLONLARININ bir fonksiyonu\n * olarak (FR-022).\n *\n * Callback olmasının sebebi tip: `columns`'tan çıkarılan `C`, TypeScript\n * tarafından buraya bağlamlandırılıyor, yani `p.col(\"ownerr\")` yazım hatası\n * DERLEME hatası oluyor. Düz bir dizide `policy(\"x\")` tek başına çağrıldığı\n * için hangi tabloda olduğunu bilemez, ve yanlış kolon adı ancak deploy\n * anında `CREATE POLICY` çalışırken Postgres'ten dönerdi. Bir RLS\n * politikasında yanlış kolon adı yetki hatasıdır; derlemede yakalanır.\n *\n * ```ts\n * policies: (p) => [\n * policy(\"owner_read\").for(\"select\").using(p.col(\"owner\").eq(p.auth.uid())),\n * ]\n * ```\n */\n policies?: (p: PolicyExprCtx<Extract<keyof C, string>>) => (PolicyBuilder | PolicyDef)[];\n /** Composite/named primary key (ordered column names). Omit for single-column inline .primaryKey(). */\n primaryKey?: string[];\n /** Named multi-column UNIQUE constraints. */\n unique?: { name: string; columns: string[] }[];\n /** Named raw-SQL DDL objects (EXCLUDE, triggers, views) that the typed DSL cannot express. */\n raw?: RawConstraintDef[];\n /**\n * Named first-class CHECK constraints. Diffed by NAME with a BODY compare:\n * a changed `expr` (after pg normalization) recreates the constraint\n * (DROP + ADD). `expr` is trusted SQL emitted verbatim (like policy USING),\n * `name` is identifier-validated.\n */\n checks?: { name: string; expr: string }[];\n /**\n * Plain (non-unique) btree indexes over an ordered column list, emitted as\n * standalone `CREATE INDEX [IF NOT EXISTS] name ON table (col1, col2)`\n * statements (NOT a table clause — a separate migration statement category).\n * Structural compare by NAME (no expression normalization). `name` and each\n * column are identifier-validated by the Go differ.\n *\n * Scope: columns-only plain btree. Partial (`where`) and expression indexes\n * are a deliberate follow-up — modelling them needs the same raw-SQL\n * normalization round-trip CHECK uses (Task 10), so they are NOT in this\n * type yet to avoid a half-working partial-index path.\n */\n indexes?: (p: PolicyExprCtx<Extract<keyof C, string>>) => (IndexBuilder | IndexDef)[];\n /**\n * appendOnly (FR-030): tablo yalnız INSERT kabul eder — UPDATE/DELETE hem\n * veritabanı yetkisiyle hem üretilen tipte reddedilir (T017/T018).\n * Ledger deseninin veri katmanından istediği TEK şey budur: bakiye türetilmiş\n * bir değerdir ve entry log'u değiştirilebilirse doğruluğunu kaybeder.\n */\n appendOnly?: boolean;\n /** Arama beyanı — bkz. SearchDecl. */\n search?: SearchDecl;\n /** Hafıza beyanı — bkz. MemoryDecl (FR-032). */\n memory?: MemoryDecl;\n}\n\n/**\n * A table definition — the runtime value the Go runtime's `schema_extract.js`\n * reads. It keys tables by `tableDef.name`, reads `tableDef.columns` for the\n * column DDL, and `tableDef.rls` + `tableDef.policies` for RLS.\n *\n * `defineSchema` derives `name` from the object key, so authors never repeat\n * the table name. `rls`/`policies` are always present after normalization\n * (defaulted to `true`/`[]`).\n *\n * The `C` type parameter preserves the precise per-column phantom types so that\n * downstream mapped types (InsertShape, RowShape) can discriminate on them.\n */\nexport interface TableDef<C extends ColumnMap = ColumnMap> {\n name: string;\n columns: C;\n rls: boolean;\n policies: PolicyDef[];\n primaryKey?: string[];\n unique?: { name: string; columns: string[] }[];\n /** Named raw-SQL DDL objects emitted verbatim on deploy. Tracked by name. */\n raw?: RawConstraintDef[];\n /** Named first-class CHECK constraints. Diffed by name + (normalized) body. */\n checks?: { name: string; expr: string }[];\n /** Index bildirimleri; partial/expression/sıra/covering alanlarıyla (FR-041…043). */\n indexes?: IndexDef[];\n /** appendOnly (FR-030) — bkz. TableInput. */\n appendOnly?: boolean;\n /** Arama beyanı, doğrulanmış ve taşınmış hali. */\n search?: SearchDecl;\n /** Hafıza beyanı, doğrulanmış ve taşınmış hali (FR-032). */\n memory?: MemoryDecl;\n}\n\n/**\n * A schema definition containing multiple tables, keyed by table name.\n *\n * The `T` type parameter preserves the exact `TableDef<...>` type for each\n * table so that `SchemaDef[\"tables\"][\"rooms\"]` resolves to the precise\n * `TableDef<{ id: ColumnBuilder<'uuid', false, true, never>; ... }>`.\n */\nexport interface SchemaDef<\n T extends Record<string, TableDef> = Record<string, TableDef>,\n> {\n /** The schema's own name — `public`, `billing`, … Declared, never derived. */\n name: string;\n /** Reachable over HTTP? False unless the author opts in. */\n exposed: boolean;\n tables: T;\n /** Postgres extensions to install on deploy. Normalized to `[]` when absent. */\n extensions: PalbaseExtension[];\n}\n\n/** The author-facing input to `defineSchema` — a `tables` map whose keys are\n * the table names and whose values are `{ columns, rls?, policies? }`, plus an\n * optional `extensions` allowlist. */\nexport interface SchemaInput<\n T extends Record<string, TableInput> = Record<string, TableInput>,\n> {\n tables: T;\n /**\n * Postgres extensions to enable for this project, e.g. `[\"vector\"]`.\n * Config-as-code: installed by the deploy (CREATE EXTENSION … SCHEMA\n * extensions) with the privileged deploy connection. The type is an\n * allowlist union, so unsupported names fail typecheck.\n */\n extensions?: PalbaseExtension[];\n}\n\n/** Map the author's `{ tables: { <name>: { columns } } }` input to the\n * `{ tables: { <name>: TableDef<columns> } }` runtime/type shape, threading the\n * per-table column map `T[K][\"columns\"]` so column-level inference survives. */\ntype TablesByName<T extends readonly TableHandle[]> = {\n [K in T[number] as K[typeof TABLE_META][\"name\"]]: K[typeof TABLE_META];\n};\n\n/** Normalize a single `policies` entry into a plain `PolicyDef` (read off a\n * `PolicyBuilder._def`, or passed through when already a `PolicyDef`). */\nfunction toPolicyDef(p: PolicyBuilder | PolicyDef): PolicyDef {\n return p instanceof PolicyBuilder ? p._def : p;\n}\n\n/**\n * How a schema file reads. One file per schema — `db/public.ts`, `db/billing.ts`\n * — and the schema says its own name:\n *\n * const todos = defineTable(\"todos\", {\n * columns: {\n * id: uuid().primaryKey().defaultRandom(),\n * owner: text().notNull(),\n * title: text().notNull(),\n * },\n * rls: true,\n * policies: [\n * policy(\"owner_all\").for(\"all\").to(\"authenticated\")\n * .using(\"owner = (select auth.uid())\")\n * .withCheck(\"owner = (select auth.uid())\"),\n * ],\n * });\n *\n * export default defineSchema(\"public\", { tables: [todos] });\n *\n * The dictionary form `defineSchema({ tables: { todos: {…} } })` is RETIRED and\n * refused by name: a table whose name comes from a key does not know what it is\n * called while it is being built, so it cannot resolve `references(() =>\n * other.id)`, and a schema that does not say its own name cannot tell one\n * `invoices` from another schema's `invoices`.\n *\n * The returned value is `{ name, tables: { todos: { name, columns, rls,\n * policies } }, extensions, exposed }` — the exact shape the runtime schema\n * extractor parses. Per-column phantom types are preserved so\n * `Database.public.todos.insert({...})` stays typed.\n *\n * RLS normalization: `rls` defaults to **`true`**, `policies` to `[]`. A table\n * that declares neither is therefore deny-all — nothing reads it until a policy\n * says who may, which is the safe starting point rather than a bug. Declare\n * `rls: false` for a genuinely public table; that is an explicit, greppable\n * statement of intent instead of an omission. When `policies` is non-empty,\n * `rls` is forced on (ENABLE + FORCE) regardless of the declared flag — a table\n * with policies must have RLS enabled or the policies would be inert.\n */\n/**\n * Where a table's metadata lives.\n *\n * The table VALUE is its columns, so `lists.id` is the column — which means a\n * column called `name` would overwrite the table's own name if metadata sat in\n * a plain field. Measured, not imagined: the existing `users` / `rooms` tests\n * (both declare a `name` column) produced an `[object Object]` table key.\n * `columns`, `rls`, `search`, `memory`, `unique` and `indexes` are all plausible\n * column names too. A column cannot collide with a symbol.\n */\nexport const TABLE_META: unique symbol = Symbol.for(\"palbase.table.meta\");\n\n/** A value produced by `defineTable`: the columns, plus metadata behind the symbol. */\nexport type TableHandle<C extends ColumnMap = ColumnMap, N extends string = string> =\n C & { readonly [TABLE_META]: TableDef<C> & { name: N } };\n\n/**\n * Declare one table as a standalone value that KNOWS ITS OWN NAME.\n *\n * The name lives here, not in a dictionary key. A table whose name comes from a\n * key cannot resolve `references(() => other.id)` when it is built — it does not\n * know what to call itself — which forces a two-phase resolution with an\n * empty-name intermediate state. One name source, no empty identity.\n *\n * The returned object spreads its own columns, so a sibling can point at it:\n * `references(() => lists.id)`.\n */\nexport function defineTable<const N extends string, C extends ColumnMap>(\n name: N,\n input: TableInput<C>,\n): TableHandle<C, N> {\n if (name.trim() === \"\") {\n throw new Error(\"defineTable(name, …): name must not be empty\");\n }\n // İfade bağlamı TABLONUN KENDİ kolon adlarıyla kuruluyor (FR-022). Çalışma\n // zamanında `col()` adı doğrulamıyor — doğrulayan tip; burada yapılacak\n // ikinci bir kontrol, tipin zaten imkânsız kıldığı bir şeyi tekrar ederdi.\n const policies = (input.policies?.(exprCtx(Object.keys(input.columns), 0, name)) ?? []).map(toPolicyDef);\n // Fail closed. RLS is on unless the author explicitly says `rls: false`, and\n // policies force it on regardless — a policy on a table without RLS enabled is\n // inert, so declaring both resolves towards the safe reading.\n //\n // This defaulted to `false` until 2026-08-07, which meant a table nobody\n // thought about had no row-level security while `typed-db.ts` documented the\n // default `Database.*` path as RLS-enforced. The live proof settled it: user B\n // read user A's row in full through the typed client, while the same request\n // against a table declaring `rls: true` returned 0 of 165 rows. With no\n // policies this is deny-all.\n const rls = policies.length > 0 || input.rls !== false;\n // EACH TABLE GETS ITS OWN COLUMN OBJECTS.\n //\n // A ColumnBuilder shares one `_def` with every builder derived from it, so a\n // shared column — `const audit = { created_at: timestamp() }` spread into two\n // tables, the most ordinary pattern this DSL has — would put BOTH tables'\n // stamps on one object and the second declaration would win. A reference\n // thunk written as `() => a.created_at` then resolved to table `b`: a\n // well-formed foreign key onto the WRONG table, with no error anywhere.\n //\n // Copying is what `.ignored()` already does about the same aliasing, and it\n // keeps the spread pattern working rather than banning it. The copies are\n // what the def AND the handle carry, so the identity match that resolves a\n // reference thunk still finds its column.\n const owned = {} as C;\n for (const [colName, b] of Object.entries(input.columns)) {\n const builder = b as { _def: ColumnDefLike };\n // Same class, same phantom type parameters, its own `_def`. Cloning through\n // the prototype rather than the constructor keeps this file free of a value\n // import from columns.ts — the two modules only ever exchanged types.\n const clone = Object.create(Object.getPrototypeOf(builder)) as { _def: ColumnDefLike };\n Object.defineProperty(clone, \"_def\", { value: { ...builder._def }, enumerable: true, writable: true });\n (owned as Record<string, unknown>)[colName] = clone;\n }\n\n const def = {\n name,\n columns: owned,\n rls,\n policies,\n } as TableDef<C> & { name: N };\n if (input.primaryKey !== undefined) def.primaryKey = input.primaryKey;\n if (input.unique !== undefined) def.unique = input.unique;\n if (input.raw !== undefined && input.raw.length > 0) def.raw = input.raw.slice();\n if (input.checks !== undefined && input.checks.length > 0) def.checks = input.checks.slice();\n // İfade bağlamı `policies` ile AYNI — index kolonları da tablonun kendi\n // kolonlarından çözülüyor ve yanlış ad derleme hatası (FR-041).\n const declaredIndexes = (input.indexes?.(exprCtx(Object.keys(input.columns), 0, name)) ?? []).map(\n (i) => (i instanceof IndexBuilder ? i._def : i),\n );\n if (declaredIndexes.length > 0) def.indexes = declaredIndexes;\n if (input.appendOnly === true) def.appendOnly = true;\n if (input.search !== undefined) {\n const s = input.search;\n // Erken, beyan-anı doğrulama (apply doğrulamasını İKAME ETMEZ — yazım\n // hatası deploy'a gitmeden yazarın yüzüne söylenir).\n if (s.from !== undefined) {\n // YENİ biçim (D-007). Eski alanlarla karışım tek biçime zorlanır:\n // iki yarım beyanın hangisinin kazandığını okuyucu bilemez.\n if (s.vector !== undefined) {\n throw new Error(\n `table ${name}: search beyanında tek biçim kullanın — 'from' (yeni) ile 'vector' (eski) birlikte olamaz`,\n );\n }\n if (s.from.length === 0) {\n throw new Error(`table ${name}: search.from boş olamaz`);\n }\n if (s.model === undefined) {\n throw new Error(\n `table ${name}: search.from model'siz anlamsız — auto-embed için model verin (BYO için eski 'vector' biçimini kullanın)`,\n );\n }\n if (Array.isArray(s.text) && s.text.length === 0) {\n throw new Error(`table ${name}: search.text boş dizi olamaz — FTS istemiyorsan text: false yazın`);\n }\n } else {\n // ESKİ biçim — davranış ve hata metinleri aynen (NFR-B1'in DX yarısı).\n if (typeof s.text === \"boolean\") {\n throw new Error(`table ${name}: text:${String(s.text)} yalnız yeni biçimde ('from' ile) geçerli`);\n }\n if (s.text === undefined && s.vector === undefined) {\n throw new Error(\n `table ${name}: search beyanı boş — en az bir kol (text ya da vector) verin, yoksa alanı hiç yazmayın`,\n );\n }\n if (s.text !== undefined && s.text.length === 0) {\n throw new Error(`table ${name}: search.text boş olamaz — FTS kolu istemiyorsan alanı hiç yazma`);\n }\n const legs = s.vector === undefined ? [] : Array.isArray(s.vector) ? s.vector : [s.vector];\n for (const leg of legs) {\n if (leg.model !== undefined && (leg.from === undefined || leg.from.length === 0)) {\n throw new Error(`table ${name}: search.vector.model beyan edildi ama 'from' yok — embed kaynağı kolonlar zorunlu (C-2)`);\n }\n if (leg.model === undefined && leg.from !== undefined) {\n throw new Error(`table ${name}: search.vector.from model'siz anlamsız — auto-embed için model verin`);\n }\n }\n }\n def.search = s;\n }\n if (input.memory !== undefined) {\n if (input.memory.from.length === 0) {\n throw new Error(`table ${name}: memory.from boş olamaz`);\n }\n def.memory = input.memory;\n }\n // The stamp goes on the COPIES, after the def exists — that is how a\n // reference thunk names its target when `defineSchema` resolves it.\n for (const b of Object.values(owned as Record<string, unknown>)) {\n (b as { _def: { ownerTable?: unknown } })._def.ownerTable = def;\n }\n // Columns are the enumerable surface; metadata hangs off a non-enumerable\n // symbol so it survives spreads and cannot be shadowed by a column name.\n const handle = { ...(owned as Record<string, unknown>) } as TableHandle<C, N>;\n Object.defineProperty(handle, TABLE_META, { value: def, enumerable: false });\n return handle;\n}\n\n/**\n * Which schema declared a table.\n *\n * A `TableDef` cannot carry it: `defineTable` runs before any schema exists, and\n * `defineSchema` is where the answer arrives. It lives OUTSIDE the def rather\n * than on it because the def is serialized — a field here would either leak into\n * the wire shape or need a second rule saying not to. A WeakMap keyed by the def\n * object is the same fact with no surface.\n *\n * It exists because a foreign key names its target and that name is only half a\n * name without the schema. `resolveReferences` reads it to write the referent\n * the way `qualifiedTableKey` writes every other table name.\n */\nconst declaringSchemaOf = new WeakMap<object, string>();\n\n/**\n * Resolve every pending reference thunk.\n *\n * Runs inside `defineSchema`, where all table bindings exist and every table\n * already carries its name — which is why the name lives on the table and not in\n * a dictionary key: resolving against a table that does not yet know what it is\n * called would need a second pass over an empty-name intermediate state.\n *\n * The written referent follows the ONE naming convention (`qualifiedTableKey`):\n * a `public` table is bare, anything else is schema-qualified. The deciding fact\n * is the REFERENT's schema, not whether the key crosses a schema boundary —\n * exactly the CASE Go's introspection uses when it reads a live FK back\n * (`introspect.go`: `CASE WHEN rn.nspname = 'public' THEN rt.relname ELSE\n * rn.nspname || '.' || rt.relname END`). Writing `invoices` for a table that\n * lives in `billing` made Go read it as `public.invoices`: a FK onto a table\n * that does not exist, or — worse and silently — onto a DIFFERENT table that\n * happened to share the name.\n */\nfunction resolveReferences(tables: Record<string, TableDef>, schemaName: string): void {\n for (const table of Object.values(tables)) {\n for (const [colName, builder] of Object.entries(table.columns)) {\n const def = (builder as { _def: ColumnDefLike })._def;\n if (def.selfRefColumn !== undefined) {\n if (!(def.selfRefColumn in table.columns)) {\n throw new Error(\n `table \"${table.name}\" column \"${colName}\": selfReferences(\"${def.selfRefColumn}\") — no such column on this table`,\n );\n }\n // A self-reference is a reference: its referent is this table, in THIS\n // schema, so it is written by the same rule as any other.\n def.references = {\n table: qualifiedTableKey(schemaName, table.name),\n column: def.selfRefColumn,\n };\n continue;\n }\n if (def.referencesThunk === undefined) continue;\n const target = def.referencesThunk();\n const owner = (target as { _def?: ColumnDefLike } | undefined)?._def?.ownerTable;\n if (owner === undefined) {\n throw new Error(\n `table \"${table.name}\" column \"${colName}\": references(() => …) must point at a column of a table declared with defineTable(...)`,\n );\n }\n const targetColumn = Object.entries(owner.columns).find(\n ([, b]) => (b as { _def: unknown })._def === (target as { _def: unknown })._def,\n )?.[0];\n if (targetColumn === undefined) {\n throw new Error(\n `table \"${table.name}\" column \"${colName}\": the referenced column was not found on table \"${owner.name}\"`,\n );\n }\n const targetSchema = declaringSchemaOf.get(owner);\n if (targetSchema === undefined) {\n // Assuming `public` here is the exact silence this resolution closes:\n // it would produce a FK onto a table that does not exist, or onto a\n // same-named one that does. Name the gap instead.\n throw new Error(\n `table \"${table.name}\" column \"${colName}\": references(() => …) points at table ` +\n `\"${owner.name}\", which no defineSchema(...) has claimed yet — a foreign key cannot ` +\n `be written without its target's schema. Declare that table's schema first ` +\n `(one file per schema: db/public.ts, db/billing.ts …, imported by this one).`,\n );\n }\n def.references = {\n table: qualifiedTableKey(targetSchema, owner.name),\n column: targetColumn,\n };\n }\n }\n}\n\ntype ColumnDefLike = {\n references?: { table: string; column: string };\n referencesThunk?: () => unknown;\n selfRefColumn?: string;\n ownerTable?: { name: string; columns: Record<string, unknown> };\n};\n\n/**\n * Collect declared tables into one schema.\n *\n * Takes an ARRAY, not a dictionary: the tables already carry their names, and a\n * second name source is a second thing that can disagree.\n */\nexport function defineSchema<const T extends readonly TableHandle[]>(\n name: string,\n input: { tables: T; exposed?: boolean; extensions?: PalbaseExtension[] },\n): SchemaDef<TablesByName<T>> {\n // The TYPE first, then the value. The retired one-argument form passes an\n // object here, and a guard that only asks whether the name is blank calls\n // `.trim()` on it — which threw `name.trim is not a function` out of the child\n // process that runs `db/*.ts` during push: no file, no form, nothing to act\n // on. `references(\"t\", \"c\")` already answers its own retirement by name.\n if (typeof name !== \"string\") {\n throw new Error(\n `defineSchema(...) takes the schema NAME first: ` +\n `defineSchema(\"public\", { tables: [todos, lists] }). ` +\n `The one-argument form defineSchema({ tables: { … } }) is gone — a schema that does not ` +\n `say its own name cannot be told apart from another schema's table of the same name, ` +\n `which is what a cross-schema foreign key has to do. ` +\n `Migrate db/public.ts (one file per schema: db/public.ts, db/billing.ts …): name the ` +\n `schema, and lift each table key onto the table itself with ` +\n `defineTable(\"todos\", { columns: { … } }), then list the tables in the array.`,\n );\n }\n if (name.trim() === \"\") {\n throw new Error(\"defineSchema(name, …): name must not be empty\");\n }\n const tables = {} as Record<string, TableDef>;\n for (const handle of input.tables) {\n const table = handle[TABLE_META];\n if (tables[table.name] !== undefined) {\n throw new Error(\n `defineSchema(\"${name}\"): two tables declare the name \"${table.name}\" — table names must be unique within a schema`,\n );\n }\n tables[table.name] = table;\n // Stamped BEFORE resolution: a reference from this schema to a sibling in it\n // must find the sibling's schema, and the sibling may be declared later in\n // the array than the table pointing at it.\n declaringSchemaOf.set(table, name);\n }\n // Thunks are invoked HERE: every binding exists and every name is already set.\n resolveReferences(tables, name);\n // memory beyanları TABLOLAR-ARASI doğrulanır (into/subject/fact) — tüm\n // tablolar kurulduktan sonra: beyan sırasına bağımlılık olmasın (FR-032).\n for (const [name, def] of Object.entries(tables)) {\n const m = (def as TableDef).memory;\n if (m === undefined) continue;\n const target = Object.values(tables).find((t) => (t as TableDef).name === m.into) as TableDef | undefined;\n if (target === undefined) {\n throw new Error(`table ${name}: memory.into \"${m.into}\" şemada declared değil`);\n }\n const subject = m.subject ?? \"owner\";\n if (!(subject in (def as TableDef).columns)) {\n throw new Error(`table ${name}: memory.subject \"${subject}\" kolonu kaynak tabloda yok`);\n }\n if (!(subject in target.columns)) {\n throw new Error(`table ${name}: memory.subject \"${subject}\" kolonu hedef \"${m.into}\" tablosunda yok`);\n }\n const factCol = target.columns[\"fact\"];\n const factDef = factCol !== undefined && \"_def\" in (factCol as object)\n ? (factCol as { _def: { type?: string } })._def\n : (factCol as { type?: string } | undefined);\n if (factDef === undefined || factDef.type !== \"text\") {\n throw new Error(`table ${name}: memory.into \"${m.into}\" tablosunda \"fact\" (text) kolonu zorunlu`);\n }\n for (const c of m.from) {\n if (!(c in (def as TableDef).columns)) {\n throw new Error(`table ${name}: memory.from kolonu \"${c}\" kaynak tabloda yok`);\n }\n }\n }\n // Dedupe + normalize extensions (order-independent; deploy resolves deps).\n const extensions = [...new Set(input.extensions ?? [])];\n // Declaring a schema is not the same as putting it on the internet, so\n // `exposed` is false unless the author says otherwise — EXCEPT for `public`,\n // which is reachable today and stays reachable. Making the default uniform\n // would silently 404 every existing project's /v1/db traffic on upgrade.\n return {\n name,\n tables: tables as TablesByName<T>,\n extensions,\n exposed: input.exposed ?? name === \"public\",\n };\n}\n","import { TABLE_META } from \"./schema.js\";\nimport type { ColumnMap, TableHandle } from \"./schema.js\";\n\n/**\n * policy.ts — the RLS policy authoring DSL.\n *\n * `policy(name)` returns a fluent builder that mirrors the `ColumnBuilder`\n * style in columns.ts: each chainable method mutates the underlying\n * definition and returns the builder so calls compose. The terminal value is\n * a plain {@link PolicyDef} — the exact JSON shape the runtime's\n * `schema_extract.js` reads off the bundled module and the Go side parses into\n * `PolicyJSON` (CONTRACT-POLICY).\n *\n * @example\n * import { policy } from \"@palbase/backend\";\n *\n * policy(\"owner_select\")\n * .for(\"select\")\n * .to(\"authenticated\")\n * .using(\"owner = (select auth.uid())\");\n */\n\n\n// ---------------------------------------------------------------------------\n// C-4 — politika ifadesinin YAPISI (FR-022). SÖZLEŞME BURADA DONAR.\n//\n// T016 (`existsIn`), T027 (Go emitter) ve T028 (korelasyonlu EXISTS) bu tipi\n// tüketir; şekli değiştirmek üç tarafı birden kırar.\n//\n// NEDEN string değil de yapı: bir string ifadeyi ne TypeScript ne Go okuyabilir.\n// Kolon adı yanlışsa hata `CREATE POLICY` anında Postgres'ten gelir — deploy\n// sırasında, yazma anında değil. Dahası InitPlan sarmalaması (`auth.uid()` →\n// `(select auth.uid())`, satır başına bir kez yerine statement başına bir kez)\n// ve `TO <rol>` daraltması ancak yapı üstünde GÜVENLE verilebilir; string\n// üzerinde regex'le yapmak, yorum içindeki bir `auth.uid()`'yi de sarmalar.\n// ---------------------------------------------------------------------------\n\n/** Politika ifadesinin düğümleri. DÜZ VERİ: tele bu şekilde gider. */\nexport type PolicyExpr =\n | {\n kind: \"col\";\n name: string;\n /**\n * Hangi tablonun kolonu (FR-023). Yoksa POLİTİKANIN KENDİ tablosu —\n * Postgres politika ifadesinde onu niteliksiz çözer. Doluysa bir\n * `existsIn` alt-sorgusunun takma adı.\n *\n * Bu ayrım korelasyonun tamamı: ayırt edilmezse `team_id = team_id`\n * üretilir, her satır için doğrudur, ve politika HİÇBİR ŞEYİ süzmez —\n * yani tüm belgeler herkese görünür.\n */\n alias?: string;\n }\n | { kind: \"authUid\" }\n | { kind: \"lit\"; value: string | number | boolean | null }\n | { kind: \"binop\"; op: PolicyBinOp; left: PolicyExpr; right: PolicyExpr }\n | { kind: \"and\"; parts: PolicyExpr[] }\n | { kind: \"or\"; parts: PolicyExpr[] }\n | { kind: \"not\"; expr: PolicyExpr }\n | { kind: \"isNull\"; expr: PolicyExpr; negated: boolean }\n | {\n /**\n * Korelasyonlu `EXISTS (SELECT 1 FROM <table> <alias> WHERE <predicate>)`.\n *\n * FR-024 BAĞLAYICI: alt-sorgu DOĞRUDAN üretilir, bir `SECURITY DEFINER`\n * fonksiyona SARILMAZ. Ölçüldü (spec Research Appendix, pg16): doğrudan\n * alt-sorguda hedef tablonun KENDİ RLS'i uygulanıyor — yani sızıntı\n * kanalı yok. Sarmalama ise onu bypass ederdi.\n */\n kind: \"exists\";\n table: string;\n alias: string;\n /**\n * POLİTİKANIN KENDİ tablosunun adı — korelasyonun çalışması için ŞART.\n *\n * ÖLÇÜLDÜ (canlı pg16): alt-sorgu içinde niteliksiz bir kolon adı\n * Postgres tarafından İÇ tabloya çözülüyor. Yani dış kolon niteliksiz\n * bırakılınca `pb_e1.team_id = pb_e1.team_id` üretiliyor — her satır\n * için doğru, ve politika HİÇBİR ŞEYİ süzmüyor: iki farklı kullanıcı\n * da tüm belgeleri gördü. Dış tablo adı burada taşınıyor ki emitter\n * `\"documents\".\"team_id\"` yazabilsin.\n */\n outer: string;\n predicate: PolicyExpr;\n };\n\n/** Karşılaştırma operatörleri. `in` sağ tarafta liste bekler. */\nexport type PolicyBinOp = \"eq\" | \"neq\" | \"gt\" | \"gte\" | \"lt\" | \"lte\" | \"in\";\n\n/**\n * Bir ifadenin ETRAFINDAKİ akıcı sarmalayıcı.\n *\n * Düğüm (`expr`) düz veri kalıyor, metotlar sarmalayıcıda yaşıyor: `_def.using`\n * serileştiğinde metotlu bir nesne değil, tam olarak tele gidecek şekil olsun\n * diye. `.using()` sarmalayıcıyı açar.\n */\nexport class PolicyExprRef {\n constructor(readonly expr: PolicyExpr) {}\n\n private bin(op: PolicyBinOp, other: PolicyOperand): PolicyExprRef {\n return new PolicyExprRef({ kind: \"binop\", op, left: this.expr, right: toExpr(other) });\n }\n\n eq(other: PolicyOperand): PolicyExprRef { return this.bin(\"eq\", other); }\n neq(other: PolicyOperand): PolicyExprRef { return this.bin(\"neq\", other); }\n gt(other: PolicyOperand): PolicyExprRef { return this.bin(\"gt\", other); }\n gte(other: PolicyOperand): PolicyExprRef { return this.bin(\"gte\", other); }\n lt(other: PolicyOperand): PolicyExprRef { return this.bin(\"lt\", other); }\n lte(other: PolicyOperand): PolicyExprRef { return this.bin(\"lte\", other); }\n\n /**\n * `IS NULL` / `IS NOT NULL` — `= NULL` SQL'de her zaman UNKNOWN'dır, o yüzden\n * niyet ayrı bir düğümle yazılır. Partial index'in en sık koşulu\n * (`WHERE deleted_at IS NULL`) tam olarak bu.\n */\n isNull(negated = false): PolicyExprRef {\n return new PolicyExprRef({ kind: \"isNull\", expr: this.expr, negated });\n }\n\n and(...others: PolicyExprRef[]): PolicyExprRef {\n return new PolicyExprRef({ kind: \"and\", parts: [this.expr, ...others.map((o) => o.expr)] });\n }\n or(...others: PolicyExprRef[]): PolicyExprRef {\n return new PolicyExprRef({ kind: \"or\", parts: [this.expr, ...others.map((o) => o.expr)] });\n }\n not(): PolicyExprRef {\n return new PolicyExprRef({ kind: \"not\", expr: this.expr });\n }\n}\n\n/** `.eq()` gibi metotların sağ tarafı: başka bir ifade ya da düz bir değer. */\nexport type PolicyOperand = PolicyExprRef | string | number | boolean | null;\n\n/**\n * Düz değer LİTERAL olur, kolon referansı OLMAZ.\n *\n * `.eq(\"owner\")` bir string karşılaştırmasıdır — `owner` kolonuna referans\n * değil. İkisi karışırsa politika sessizce yanlış satırları gösterir ve RLS'te\n * bunun adı yetki atlamasıdır. Kolon istiyorsan `p.col(\"owner\")` yazacaksın.\n */\nfunction toExpr(v: PolicyOperand): PolicyExpr {\n return v instanceof PolicyExprRef ? v.expr : { kind: \"lit\", value: v };\n}\n\n/**\n * Politika ifadesi bağlamı — `defineTable`'ın `policies` callback'ine verilir.\n *\n * Kolon adları TABLONUN KENDİ kolonlarıyla sınırlıdır (FR-022). Bu, `policies`\n * bir dizi değil de callback olduğu için mümkün: TypeScript `columns`'tan\n * `C`'yi çıkarıp callback'i onunla bağlamlandırıyor. `policy(\"x\")` tek başına\n * çağrıldığında hangi tabloda olduğunu bilemezdi.\n */\nexport interface PolicyExprCtx<Cols extends string = string> {\n /** Bu tablonun bir kolonu. Bilinmeyen ad DERLENMEZ. */\n col(name: Cols): PolicyExprRef;\n /**\n * \"Bu satırın sahibi olduğum bir takıma ait mi?\" — üyelik tabanlı kiracılık\n * (FR-023), korelasyonlu bir `EXISTS` alt-sorgusu olarak.\n *\n * ```ts\n * policies: (p) => [\n * policy(\"team_read\").for(\"select\").using(\n * p.existsIn(teamMembers, (m) =>\n * m.col(\"team_id\").eq(p.col(\"team_id\"))\n * .and(m.col(\"user_id\").eq(p.auth.uid()))),\n * ),\n * ]\n * ```\n *\n * `m` ÜYELİK tablosunun kolonlarını, `p` bu tablonunkileri verir; ikisi de\n * tipli ve SQL'de farklı nitelenirler. Karışsalardı `team_id = team_id`\n * üretilir ve politika hiçbir şeyi süzmezdi.\n *\n * ÖZYİNELEME TUZAĞI: üyelik tablosunun KENDİ politikası `existsIn`\n * KULLANMAZ — `user_id = auth.uid()` yazar. İki tablo birbirini\n * sorgularsa Postgres sorgu anında\n * `infinite recursion detected in policy for relation …` der. Asimetri\n * kasıtlıdır: üyelik tablosu basit olanı alır, diğer her tablo ona\n * alt-sorgu ATAR.\n */\n existsIn<C extends ColumnMap, N extends string>(\n table: TableHandle<C, N>,\n predicate: (row: PolicyExprCtx<Extract<keyof C, string>>) => PolicyExprRef,\n ): PolicyExprRef;\n /** Çağıranın kimliği. SQL'e `(select auth.uid())` olarak iner (InitPlan). */\n auth: { uid(): PolicyExprRef };\n /** Düz bir değer — karşılaştırmanın sağ tarafında açıkça literal demek için. */\n lit(v: string | number | boolean | null): PolicyExprRef;\n and(...parts: PolicyExprRef[]): PolicyExprRef;\n or(...parts: PolicyExprRef[]): PolicyExprRef;\n not(part: PolicyExprRef): PolicyExprRef;\n}\n\n/**\n * İfade bağlamını kurar. `defineTable` bunu kendi kolon adlarıyla çağırır;\n * testler ve elle kullanım için de dışa açık.\n */\nexport function exprCtx<Cols extends string = string>(\n _columns?: readonly Cols[],\n depth = 0,\n /**\n * POLİTİKANIN KENDİ tablosu — her derinlikte AYNI kalır.\n *\n * Alt-sorgunun içinde takma adsız duran bir kolon, dış sorgudaki tabloya\n * bağlanmak zorundadır; Go tarafı onu bu adla nitelendiriyor. Değer iç içe\n * geçmede ORTA tablonun adına kayıyordu (`meta.name` aşağı veriliyordu) ve\n * sonuç canlıda `ERROR: missing FROM-clause entry for table \"…\"` oluyordu —\n * yani iç içe `existsIn` içinden politikanın kendi kolonuna erişmek imkânsızdı\n * (nihai inceleme I-1, ölçüldü). Kök tablo aşağı DEĞİŞMEDEN taşınır.\n */\n ownTable = \"\",\n): PolicyExprCtx<Cols> {\n // Takma ad DERİNLİKTEN türetiliyor, bir sayaçtan değil: aynı şema iki kez\n // yüklendiğinde (test, sonra deploy) sayaç farklı değer üretir ve golden\n // çıktı sebepsiz değişirdi. Derinlik ifadenin kendi şeklinden gelir.\n const alias = `pb_e${depth}`;\n return {\n col: (name) =>\n new PolicyExprRef(depth === 0 ? { kind: \"col\", name } : { kind: \"col\", name, alias }),\n auth: { uid: () => new PolicyExprRef({ kind: \"authUid\" }) },\n lit: (v) => new PolicyExprRef({ kind: \"lit\", value: v }),\n and: (...parts) => new PolicyExprRef({ kind: \"and\", parts: parts.map((p) => p.expr) }),\n or: (...parts) => new PolicyExprRef({ kind: \"or\", parts: parts.map((p) => p.expr) }),\n not: (part) => new PolicyExprRef({ kind: \"not\", expr: part.expr }),\n existsIn: (table, predicate) => {\n const meta = (table as { [TABLE_META]: { name: string; columns: ColumnMap } })[TABLE_META];\n const inner = exprCtx(Object.keys(meta.columns), depth + 1, ownTable);\n return new PolicyExprRef({\n kind: \"exists\",\n table: meta.name,\n alias: `pb_e${depth + 1}`,\n outer: ownTable,\n predicate: predicate(inner as never).expr,\n });\n },\n };\n}\n\n/** The SQL command a policy applies to. `\"all\"` covers SELECT/INSERT/UPDATE/DELETE. */\nexport type PolicyCommand = \"all\" | \"select\" | \"insert\" | \"update\" | \"delete\";\n\n/** Whether a policy is permissive (OR-combined, the default) or restrictive\n * (AND-combined). Mirrors Postgres `CREATE POLICY ... AS PERMISSIVE|RESTRICTIVE`. */\nexport type PolicyMode = \"permissive\" | \"restrictive\";\n\n/**\n * The compiled, serializable policy definition — the EXACT shape consumed by\n * `schema_extract.js` → Go `PolicyJSON` (CONTRACT-POLICY).\n *\n * - `roles`: the DB roles this policy applies to (`TO` clause). An empty array\n * means the policy applies to PUBLIC (all roles) — the Postgres default.\n * - `using`: the `USING (...)` row-visibility expression, or `null` when none.\n * - `withCheck`: the `WITH CHECK (...)` write-validation expression, or `null`.\n * - `permissive`: `true` for `AS PERMISSIVE` (default), `false` for restrictive.\n */\nexport interface PolicyDef {\n name: string;\n command: PolicyCommand;\n roles: string[];\n /** Yapı (FR-022) ya da ham string (FR-028 kaçış kapağı). */\n using: string | PolicyExpr | null;\n withCheck: string | PolicyExpr | null;\n permissive: boolean;\n}\n\n/**\n * Fluent RLS policy builder.\n *\n * Defaults (documented, applied at construction):\n * - `command`: `\"all\"` — applies to every SQL command unless `.for(...)` narrows it.\n * - `roles`: `[\"authenticated\"]` — the common case is \"rule applies to signed-in\n * users\". Call `.to(...)` to override; pass `.to()` with no roles (or never\n * call it after a reset) to target PUBLIC.\n * - `using` / `withCheck`: `null` — no row filter / write check until set.\n * - `permissive`: `true` — `AS PERMISSIVE` (policies OR together).\n *\n * Each method mutates `_def` in place and returns `this`, so the chain is a\n * single builder instance (no per-call allocation, like a tagged-template\n * compile target). The terminal `PolicyDef` is read directly off `_def` by\n * `schema_extract.js`.\n */\n/** Quote an identifier for the policy expression. Table and column names reach\n * here from the schema author; neither is allowed to become syntax. */\nfunction quote(name: string): string {\n return `\"${name.replace(/\"/g, '\"\"')}\"`;\n}\n\nexport class PolicyBuilder {\n readonly _def: PolicyDef;\n\n constructor(name: string) {\n this._def = {\n name,\n command: \"all\",\n roles: [\"authenticated\"],\n using: null,\n withCheck: null,\n permissive: true,\n };\n }\n\n /** Restrict the policy to a single SQL command (default `\"all\"`). */\n for(command: PolicyCommand): this {\n this._def.command = command;\n return this;\n }\n\n /**\n * Set the DB roles the policy applies to (the `TO` clause), replacing any\n * previously-set roles. Call with no arguments to target PUBLIC (all roles).\n *\n * @example\n * policy(\"p\").to(\"authenticated\")\n * policy(\"p\").to(\"authenticated\", \"service_role\")\n * policy(\"p\").to() // PUBLIC\n */\n to(...roles: string[]): this {\n this._def.roles = roles;\n return this;\n }\n\n /**\n * `USING (...)` satır görünürlüğü ifadesi.\n *\n * Tercih edilen biçim YAPI'dır (FR-022) — `policies` callback'inin verdiği\n * bağlamla kurulur ve kolon adları derlemede doğrulanır:\n *\n * ```ts\n * policies: (p) => [\n * policy(\"owner_read\").for(\"select\").using(p.col(\"owner\").eq(p.auth.uid())),\n * ]\n * ```\n *\n * Ham string KAÇIŞ KAPAĞI olarak kalır (FR-028): yapının ifade edemediği bir\n * şey gerektiğinde yol kapanmaz. Ama o yolda kolon adı doğrulaması yoktur ve\n * hata deploy anında Postgres'ten gelir.\n */\n using(expr: string | PolicyExprRef): this {\n this._def.using = expr instanceof PolicyExprRef ? expr.expr : expr;\n return this;\n }\n\n /**\n * \"Rows of THIS table whose owner the caller is a member of\" — the membership\n * pattern, written so it cannot recurse.\n *\n * THE TRAP IT EXISTS FOR. Written by hand, membership policies point at each\n * other: `channels` is visible to members, so its policy reads\n * `channel_members`; `channel_members` is visible to members, so its policy\n * reads `channels`. Postgres refuses the pair at query time with `infinite\n * recursion detected in policy for relation ...`, and the error names the\n * relation but not the cycle. The way out is asymmetry — the MEMBERSHIP table\n * is protected by `user_id = auth.uid()` and nothing else, and every other\n * table subqueries INTO it. That shape was in the platform's own schema and\n * written down nowhere; a customer recovered it by reading that schema.\n *\n * `(select auth.uid())` rather than a bare call: the scalar subquery is\n * evaluated ONCE per statement instead of per row.\n *\n * @example\n * // channels: visible to members. The membership table gets the simple one.\n * policy(\"member_read\").for(\"select\").to(\"authenticated\")\n * .memberOf(\"channel_members\", \"channel_id\")\n * // → id IN (SELECT \"channel_id\" FROM \"channel_members\"\n * // WHERE \"user_id\" = (select auth.uid()))\n */\n memberOf(\n membershipTable: string,\n foreignKey: string,\n options: { column?: string; userColumn?: string } = {},\n ): this {\n if (this._def.using !== null) {\n // Silently AND-ing the two would hide whichever the author meant; silently\n // replacing would hide the one they wrote. Neither is a thing to guess.\n throw new Error(\n `policy(${this._def.name}).memberOf(): this policy already has a using() expression. ` +\n \"Write one or the other — memberOf IS the using expression.\",\n );\n }\n const column = options.column ?? \"id\";\n const userColumn = options.userColumn ?? \"user_id\";\n this._def.using =\n `${quote(column)} IN (SELECT ${quote(foreignKey)} FROM ${quote(membershipTable)} ` +\n `WHERE ${quote(userColumn)} = (select auth.uid()))`;\n return this;\n }\n\n /** `WITH CHECK (...)` yazma doğrulaması — `using` ile aynı iki biçim. */\n withCheck(expr: string | PolicyExprRef): this {\n this._def.withCheck = expr instanceof PolicyExprRef ? expr.expr : expr;\n return this;\n }\n\n /** Set the policy mode: `\"permissive\"` (default, OR-combined) or\n * `\"restrictive\"` (AND-combined). */\n as(mode: PolicyMode): this {\n this._def.permissive = mode === \"permissive\";\n return this;\n }\n}\n\n/**\n * Start authoring an RLS policy. Returns a {@link PolicyBuilder}; the resulting\n * `PolicyBuilder` is accepted directly in a table's `policies: [...]` array\n * (its `_def` is read at schema-extract time).\n *\n * @param name The policy name. Palbase reconciliation keys policies by\n * `(table, name)`, so names must be unique per table.\n */\nexport function policy(name: string): PolicyBuilder {\n return new PolicyBuilder(name);\n}\n","/**\n * Postgres extensions a Palbase project can enable from its schema.\n *\n * Extensions are config-as-code: declare them in `defineSchema({ extensions })`\n * and the deploy installs them (CREATE EXTENSION … SCHEMA extensions) using the\n * deploy path's privileged connection. They are NOT toggled live from Studio —\n * CREATE EXTENSION requires a superuser role that only the deploy path holds.\n *\n * The list is an allowlist (a string-literal union) so editors autocomplete the\n * supported names and a typo fails typecheck. It is intentionally extensible:\n * add a name here (+ confirm the base image ships it) to support more.\n */\nexport const PALBASE_EXTENSIONS = [\n // Search & text\n \"vector\", // pgvector: AI embeddings + vector similarity search (semantic search / RAG).\n // NB: the Postgres extension is named \"vector\", not \"pgvector\" — declare \"vector\".\n \"pg_trgm\", // trigram fuzzy / typo-tolerant text search\n \"unaccent\", // accent-insensitive text search\n \"citext\", // case-insensitive text type\n // Geospatial / location\n \"cube\", // multi-dimensional cubes (dependency of earthdistance)\n \"earthdistance\", // great-circle distance (needs cube)\n // Data types & structures\n \"hstore\", // key/value pairs in a single column\n \"ltree\", // hierarchical tree-structured labels\n // Indexing & constraints\n \"btree_gist\", // GiST operator classes for scalar types — needed for EXCLUDE\n // constraints that mix \"=\" with a range/&& overlap (e.g. no-double-booking).\n // Scheduling\n // Crypto / ids (also installed by default; listable for explicitness)\n \"pgcrypto\", // cryptographic functions (hashing, encryption)\n \"uuid-ossp\", // UUID generation functions\n] as const;\n\n/** A Postgres extension supported by Palbase (allowlist union). */\nexport type PalbaseExtension = (typeof PALBASE_EXTENSIONS)[number];\n\n/**\n * Extensions that depend on another extension. The deploy installs\n * dependencies first; declaring `earthdistance` without `cube` still works\n * because the deploy resolves the order, but listing both is clearer.\n */\nexport const EXTENSION_DEPENDENCIES: Partial<Record<PalbaseExtension, PalbaseExtension[]>> = {\n earthdistance: [\"cube\"],\n};\n\n/** Runtime guard: is `name` a supported Palbase extension? */\nexport function isPalbaseExtension(name: string): name is PalbaseExtension {\n return (PALBASE_EXTENSIONS as readonly string[]).includes(name);\n}\n","/** On delete action for foreign key references. */\nexport type OnDeleteAction = 'cascade' | 'set null' | 'restrict' | 'no action';\n\n/**\n * The ON DELETE actions permitted on a foreign key to the built-in auth users\n * (`auth.users`). Both let a user's rows be removed (`cascade`) or detached\n * (`set null`) when the account is erased; `restrict` / `no action` would BLOCK\n * erasure and are therefore excluded. This is the CLIENT-SIDE mirror of the\n * server's auth-FK deletion policy — the server (validateAuthUserFK) is the real\n * boundary, this narrows the type so the common mistake is caught at compile time.\n */\nexport type AuthUserOnDelete = Extract<OnDeleteAction, 'cascade' | 'set null'>;\n\n/** Column type identifiers. */\nexport type ColumnType =\n | 'uuid'\n | 'text'\n | 'integer'\n | 'bigint'\n | 'numeric'\n | 'boolean'\n | 'timestamp'\n | 'jsonb'\n | 'enum'\n | 'vector';\n\n/** Base column definition shared by all column types. */\nexport interface ColumnDef {\n type: ColumnType;\n nullable: boolean;\n primaryKey: boolean;\n defaultValue?: unknown;\n defaultRandom?: boolean;\n defaultNow?: boolean;\n references?: { table: string; column: string };\n /** Pending FK target, resolved by `defineSchema` once every binding exists. */\n referencesThunk?: () => ColumnBuilder;\n /** FK onto THIS table — no thunk needed, the target is the declaring table. */\n selfRefColumn?: string;\n /** This column OWNS the row: erasure, RLS and the `owner` relation read it. */\n owns?: true;\n /** Explicit name for the FORWARD relation (child → parent), when the one\n * derived from the column would be ambiguous or unclear. */\n refAs?: string;\n /**\n * Explicit name for the REVERSE relation (parent → children).\n *\n * Separate from {@link refAs} because the two directions are different facts:\n * the forward name describes the parent this row points at (`author`), the\n * reverse one describes the rows hanging off the parent (`posts`). One option\n * naming both made an ordinary schema undeclarable — `posts.author_id` and\n * `comments.author_id` both named `{ as: \"author\" }` collided on `users`, and\n * the refusal asked for the `{ as }` they had both already written.\n */\n reverseAs?: string;\n /** The table this column belongs to; set by `defineTable`. */\n ownerTable?: { name: string; columns: Record<string, ColumnBuilder> };\n /**\n * The name this column used to have. A diff cannot tell a rename from a drop and\n * an add — both leave one name gone and another present — so the intent has to be\n * declared. Without it, renaming a column loses its data.\n */\n renamedFrom?: string;\n /**\n * This release's PROMISE that it does not reference this column — neither\n * reads it nor writes it, and never names it in a filter, a sort or a SET.\n *\n * The contraction gate reads it and nothing else does: dropping a column is\n * refused while the RUNNING release's declaration still lacks this mark, so\n * removing a column is two deploys — mark it, ship, then drop it.\n *\n * The word is `ignored` and not `deprecated` deliberately: RFC 9745 defines\n * deprecation as changing NO behaviour, and this changes what a deploy will\n * accept. Rails calls the same thing `ignored_columns`.\n */\n ignored?: boolean;\n onDeleteAction?: OnDeleteAction;\n /** FR-044: yalnız AÇIKÇA `false` bildirilince var. Türev FK index'ini kapatır. */\n index?: boolean;\n /** FR-049: kolon `increment()` ile güncelleniyor. Plan HOT çakışmasını uyarır. */\n counter?: boolean;\n enumName?: string;\n enumValues?: string[];\n unique?: boolean;\n /**\n * The value is written by the DATABASE — a trigger, a rule, an identity — not by\n * the author and not by a DEFAULT this schema declares. It makes the column\n * optional on INSERT without putting a DEFAULT in the DDL.\n *\n * Before this existed the only way to keep a trigger-filled column off the\n * INSERT type was to give it a fake `default()`: a value the schema claimed to\n * write and the trigger immediately overwrote. That made the schema lie about\n * its own data.\n */\n dbAssigned?: boolean;\n /** vector(n): the declared dimension count — part of the TYPE (typmod), read\n * by the wire serializer and the deploy's auto-index (FR-001). */\n dimensions?: number;\n /**\n * How the stored value is projected in and out of this process (FR-009).\n *\n * NOT part of the DDL: the column's Postgres type is unchanged and this pair\n * is never serialized into a migration. It exists so the row surface can hand\n * back the type the application actually works with.\n */\n transform?: ColumnTransform;\n}\n\n/**\n * The read/write pair a column may declare (FR-009).\n *\n * `fromDb` takes whatever the driver produced for this column and returns the\n * value the application sees; `toDb` is its inverse on the way out. Kept\n * deliberately unexported — a column declares one inline, nobody needs to name\n * the shape.\n */\ninterface ColumnTransform<T = unknown> {\n fromDb: (value: unknown) => T;\n toDb: (value: T) => unknown;\n}\n\n/** FR-002: a vector column cannot carry keys/defaults/references — the modifier\n * is named in the error so the author fixes the right line. */\nfunction refuseOnVector(def: ColumnDef, modifier: string): void {\n if (def.type === 'vector') {\n throw new Error(`vector column: .${modifier}() is not supported (FR-002 — allowed: nullable()/notNull())`);\n }\n}\n\n// Phantom brand symbols — never have runtime values; exist only to force\n// TypeScript's structural type system to distinguish ColumnBuilder instances\n// with different type-param combinations. Without these, TS sees all\n// ColumnBuilder<K,...> as structurally identical and the first branch of\n// ColValue matches everything.\ndeclare const __colKind: unique symbol;\ndeclare const __colNullable: unique symbol;\ndeclare const __colHasDefault: unique symbol;\ndeclare const __colEnumValues: unique symbol;\ndeclare const __colPayload: unique symbol;\ndeclare const __colTransform: unique symbol;\n\n/**\n * Fluent column builder with phantom type params:\n * K — ColumnType literal (e.g. \"text\", \"integer\")\n * N — boolean: true when nullable() has been called last (false = NOT NULL)\n * D — boolean: true when a default has been set\n * E — enum value union (never for non-enum columns)\n * P — jsonb payload shape (unknown unless jsonb<T>() supplied one)\n * T — transform target type (`never` when the column declares no transform;\n * `never` is the sentinel because it is the only type that survives\n * `[T] extends [never]` and never collides with a real target type)\n *\n * All six params have defaults so bare `ColumnBuilder` (no args) still\n * satisfies `Record<string, ColumnBuilder>` in schema.ts without modification.\n *\n * The six `declare readonly` brand fields carry the phantom types into the\n * structural shape so that conditional types like ColValue<C> can discriminate\n * on K without requiring runtime values on those fields.\n */\nexport class ColumnBuilder<\n K extends ColumnType = ColumnType,\n N extends boolean = boolean,\n D extends boolean = boolean,\n E = unknown,\n P = unknown,\n // `unknown`, not `never`: the schema's own constraint is a BARE\n // `ColumnBuilder`, whose T lands on this default. With `never` there, a\n // column that declares `.transform<number>()` is not assignable to the\n // constraint at all — `number` does not extend `never` — so a transform\n // could not appear in a schema and the whole table's `RowShape` collapsed.\n // Measured: TS2322 on `defineSchema`.\n T = unknown,\n> {\n // These fields exist only in the type layer (declared, never initialised at\n // runtime — TypeScript allows declared class members without an initializer\n // in strict mode as long as they're never read at runtime).\n declare readonly [__colKind]: K;\n declare readonly [__colNullable]: N;\n declare readonly [__colHasDefault]: D;\n declare readonly [__colEnumValues]: E;\n declare readonly [__colPayload]: P;\n declare readonly [__colTransform]: T;\n\n readonly _def: ColumnDef;\n\n constructor(type: K, existingDef?: ColumnDef) {\n this._def = existingDef ?? {\n type,\n nullable: false,\n primaryKey: false,\n };\n }\n\n /** Mark this column as the primary key. */\n primaryKey(): ColumnBuilder<K, N, D, E, P, T> {\n refuseOnVector(this._def, 'primaryKey');\n this._def.primaryKey = true;\n return new ColumnBuilder<K, N, D, E, P, T>(this._def.type as K, this._def);\n }\n\n /** Mark this column as NOT NULL (default). */\n notNull(): ColumnBuilder<K, false, D, E, P, T> {\n this._def.nullable = false;\n return new ColumnBuilder<K, false, D, E, P, T>(this._def.type as K, this._def);\n }\n\n /** Allow NULL values. */\n nullable(): ColumnBuilder<K, true, D, E, P, T> {\n this._def.nullable = true;\n return new ColumnBuilder<K, true, D, E, P, T>(this._def.type as K, this._def);\n }\n\n /** Set a default value. */\n default(value: unknown): ColumnBuilder<K, N, true, E, P, T> {\n refuseOnVector(this._def, 'default');\n this._def.defaultValue = value;\n return new ColumnBuilder<K, N, true, E, P, T>(this._def.type as K, this._def);\n }\n\n /** UUID: generate a random default (gen_random_uuid()). */\n defaultRandom(): ColumnBuilder<K, N, true, E, P, T> {\n refuseOnVector(this._def, 'defaultRandom');\n this._def.defaultRandom = true;\n return new ColumnBuilder<K, N, true, E, P, T>(this._def.type as K, this._def);\n }\n\n /** Timestamp: default to now(). */\n defaultNow(): ColumnBuilder<K, N, true, E, P, T> {\n refuseOnVector(this._def, 'defaultNow');\n this._def.defaultNow = true;\n return new ColumnBuilder<K, N, true, E, P, T>(this._def.type as K, this._def);\n }\n\n /**\n * The DATABASE assigns this column's value — a trigger, a rule, an identity.\n *\n * The column becomes optional on INSERT (the author has nothing to send) while\n * the DDL stays free of a DEFAULT this schema would not honour. It is NOT\n * `default()`: that declares a value the schema promises to write.\n *\n * Naming: deliberately not `generated()`. Postgres has GENERATED columns and\n * they are a different thing; borrowing the word would send a reader — or a\n * model writing a schema — to the wrong feature.\n */\n dbAssigned(): ColumnBuilder<K, N, true, E, P, T> {\n this._def.dbAssigned = true;\n return new ColumnBuilder<K, N, true, E, P, T>(this._def.type as K, this._def);\n }\n\n /** Add a foreign key reference. */\n /**\n * Declares that this column used to be called `previous`.\n *\n * A schema diff sees one name gone and another present; it cannot know whether\n * you renamed a column or dropped one and added another, and the two are very\n * different — the second loses every value. Saying so here turns the plan into\n * `ALTER TABLE … RENAME COLUMN` instead.\n *\n * Once the rename has been applied the annotation is inert (the old name is no\n * longer there to rename), so it can be deleted at your leisure.\n */\n renamedFrom(previous: string): ColumnBuilder<K, N, D, E, P, T> {\n this._def.renamedFrom = previous;\n return this as unknown as ColumnBuilder<K, N, D, E, P, T>;\n }\n\n /**\n * See {@link ColumnDef.ignored}.\n *\n * COPIES the def rather than mutating it. The constructor takes an existing\n * def BY REFERENCE, so every builder derived from another shares one object —\n * `const a = slug.unique()` leaves `a._def === slug._def`. An in-place\n * `ignored = true` therefore marks every column sharing that def, including\n * one another table actively reads, and the gate would let THAT column be\n * dropped. Measured before this copy existed.\n *\n * The aliasing is older than this method and other fields leak through it too.\n * The reason this one cannot wait: every other leak produces a VISIBLE schema\n * difference — the plan shows it, the DDL shows it. This one is invisible by\n * design (no DDL, no diff, no plan line), so its only effect is to disarm a\n * safety gate in silence.\n */\n ignored(): ColumnBuilder<K, N, D, E, P, T> {\n return new ColumnBuilder<K, N, D, E, P, T>(this._def.type as K, {\n ...this._def,\n ignored: true,\n });\n }\n\n /**\n * Foreign key onto another table's column.\n *\n * The target is a THUNK, not a direct reference. In a cycle (`x → y`, `y → x`)\n * the second table does not exist yet when the first is built; a direct\n * reference makes TypeScript chase its own tail (TS7022 — measured, and making\n * the return type independent of the target does NOT help). The thunk is\n * invoked in `defineSchema`, where every binding exists and every table\n * already knows its name.\n *\n * In a cycle, ONE side needs an explicit return type:\n * `references((): AnyColumn => y.id)`. One side is enough — measured.\n * For a self-reference use `selfReferences(column)`: no thunk, no annotation.\n *\n * `as` names the FORWARD relation (`author_id` → `author` by default);\n * `reverseAs` names the REVERSE one on the parent, whose default is this\n * table's own name (`users.posts`). Two foreign keys from one table onto one\n * parent therefore need a `reverseAs` on at least one of them — the reverse\n * names would otherwise both be this table's name.\n */\n references(\n target: () => AnyColumn,\n opts?: {\n as?: string;\n reverseAs?: string;\n onDelete?: OnDeleteAction;\n /**\n * Bu FK kolonu için TÜREVİ index üretilsin mi (FR-044). Varsayılan açık.\n *\n * Postgres bir foreign key'i otomatik indekslemez — yalnız hedef\n * taraftaki unique kısıt vardır. Bedeli FK üzerinden her JOIN'de ve her\n * `ON DELETE CASCADE`'de ödenir: bir parent silinirken child tablo tam\n * taranır.\n *\n * `false` demek gerçek bir ihtiyaç, nezaket değil (D-028): FK kolonu aynı\n * zamanda SIK GÜNCELLENEN bir kolonsa index HOT güncellemeyi kırar — ve\n * HOT, DEĞİŞEN kolon indeksliyse kırılır, tablo indeksli diye değil.\n */\n index?: boolean;\n },\n ): ColumnBuilder<K, N, D, E, P, T> {\n refuseOnVector(this._def, 'references');\n if (typeof target !== 'function') {\n // Fail where the mistake is. Storing a non-thunk here surfaces three\n // layers later as \"def.referencesThunk is not a function\", inside\n // defineSchema, naming neither the column nor the call that was wrong.\n throw new Error(\n `references(...) takes a callback: write references(() => otherTable.column). ` +\n `The two-string form references(\"table\", \"column\") is gone — a string cannot be type-checked ` +\n `and cannot point at a table that does not exist yet.`,\n );\n }\n this._def.referencesThunk = target;\n if (opts?.as !== undefined) this._def.refAs = opts.as;\n if (opts?.reverseAs !== undefined) this._def.reverseAs = opts.reverseAs;\n if (opts?.onDelete !== undefined) this._def.onDeleteAction = opts.onDelete;\n // Yalnız AÇIKÇA false bildirilince taşınıyor: `undefined` \"bildirilmedi,\n // türet\" demek ve wire'da hiç görünmemeli (bayt-aynılık).\n if (opts?.index === false) this._def.index = false;\n return new ColumnBuilder<K, N, D, E, P, T>(this._def.type as K, this._def);\n }\n\n /**\n * Bu kolon `increment()` / `decrement()` ile güncelleniyor (FR-049).\n *\n * Deploy kontrolcü kodunu OKUMAZ, o yüzden bildirimin söylemesi gerekiyor —\n * ve söylediği anda plan bir şeyi görebiliyor: aynı kolon hem sayaç hem\n * indeksliyse her güncelleme HOT'u kaybeder.\n *\n * ZİNCİR (D-028+D-030): HOT kaybı → ölü tuple → autovacuum yükü → ve\n * autovacuum worker'ları KÜME GENELİNDE bir kaynak, yani bedeli başka\n * kiracıların tabloları da öder.\n *\n * Sektörde çare \"dokümana uyarı yaz\"dır, çünkü index'i ekleyen kişi\n * `increment()`'i yazan kişi değildir. Bu bildirimde ikisi de YAN YANA\n * duruyor.\n *\n * Uyarı, HATA DEĞİL: sayaç kolonunu indekslemek bazen doğru karardır.\n */\n counter(): ColumnBuilder<K, N, D, E, P, T> {\n this._def.counter = true;\n return new ColumnBuilder<K, N, D, E, P, T>(this._def.type as K, this._def);\n }\n\n /**\n * Foreign key onto THIS table (`parent_id → id`) — category trees, comment\n * replies, org charts.\n *\n * No thunk and no type annotation: the target table is the one being declared,\n * so there is nothing to defer and nothing for TypeScript to chase in a circle.\n * Drizzle forces an explicit `(): AnyPgColumn =>` here because its reference\n * always goes through a callback; measured, we do not need one.\n */\n selfReferences(\n column: string,\n opts?: { as?: string; onDelete?: OnDeleteAction },\n ): ColumnBuilder<K, N, D, E, P, T> {\n refuseOnVector(this._def, 'selfReferences');\n this._def.selfRefColumn = column;\n if (opts?.as !== undefined) this._def.refAs = opts.as;\n if (opts?.onDelete !== undefined) this._def.onDeleteAction = opts.onDelete;\n return new ColumnBuilder<K, N, D, E, P, T>(this._def.type as K, this._def);\n }\n\n\n\n /** Set the ON DELETE action for a foreign key reference. */\n onDelete(action: OnDeleteAction): ColumnBuilder<K, N, D, E, P, T> {\n this._def.onDeleteAction = action;\n return new ColumnBuilder<K, N, D, E, P, T>(this._def.type as K, this._def);\n }\n\n /** Add a single-column UNIQUE constraint. */\n unique(): ColumnBuilder<K, N, D, E, P, T> {\n refuseOnVector(this._def, 'unique');\n this._def.unique = true;\n return new ColumnBuilder<K, N, D, E, P, T>(this._def.type as K, this._def);\n }\n\n /**\n * Declare how this column's value is projected in and out of the process.\n *\n * The DDL does not move: `numeric` stays `numeric`, and the driver still hands\n * back what Postgres sent. What changes is the type the row surface exposes —\n * it becomes `Target`:\n *\n * amount: numeric().transform<number>({ fromDb: Number, toDb: String })\n *\n * `numeric` surfacing as `string` is CORRECT (a JS number cannot hold\n * arbitrary precision), and that is exactly why this exists: application code\n * that does arithmetic on the column otherwise rewrites the same\n * `Number(row.amount)` / `String(x)` pair in every controller that touches it,\n * and each rewrite is a place the two directions can drift apart.\n *\n * A transform is a PROJECTION, never a constraint: it lives only in this\n * process, so it can neither validate nor migrate what is stored.\n */\n transform<Target>(fns: ColumnTransform<Target>): ColumnBuilder<K, N, D, E, P, Target> {\n // The cast is the variance, not a shortcut: `toDb` takes `Target`, and a\n // `ColumnTransform<unknown>` would have to accept anything. The stored pair\n // is only ever called with this column's own values.\n this._def.transform = fns as ColumnTransform;\n return new ColumnBuilder<K, N, D, E, P, Target>(this._def.type as K, this._def);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Type extractors — imported by Task 2 to derive insert/row shapes.\n// ---------------------------------------------------------------------------\n\n/**\n * Extracts the TypeScript value type for a column, respecting nullability.\n * - \"uuid\" | \"text\" | \"timestamp\" | \"bigint\" | \"numeric\" → string (or string | null when N = true)\n * Note: bigint/numeric surface as string — JS number loses precision past 2^53,\n * and pgx/PostgREST serialize int8/numeric as strings. App code uses\n * BigInt(row.amount) for bigint, or a decimal lib for numeric.\n * - \"integer\" → number\n * - \"boolean\" → boolean\n * - \"jsonb\" → P (the dev-supplied payload shape from jsonb<T>(), else unknown)\n * - \"enum\" → E (the union of literal values)\n *\n * A declared `.transform<T>()` OVERRIDES the table above: the column then\n * surfaces as T (or T | null when nullable), because that is the value the\n * application is handed. Nullability is still the column's, not the\n * transform's — `fromDb` is not called for a NULL.\n */\nexport type ColValue<C> =\n C extends ColumnBuilder<ColumnType, infer N, boolean, unknown, unknown, infer T>\n ? [unknown] extends [T]\n ? ColStoredValue<C>\n : N extends true\n ? T | null\n : T\n : never;\n\n/** The value as the DATABASE hands it over — the branch table above, before any\n * transform. This is what a column's `fromDb` receives. */\ntype ColStoredValue<C> =\n C extends ColumnBuilder<'uuid' | 'text' | 'timestamp' | 'bigint' | 'numeric', infer N, infer _D, infer _E, infer _P>\n ? N extends true\n ? string | null\n : string\n : C extends ColumnBuilder<'integer', infer N, infer _D, infer _E, infer _P>\n ? N extends true\n ? number | null\n : number\n : C extends ColumnBuilder<'boolean', infer N, infer _D, infer _E, infer _P>\n ? N extends true\n ? boolean | null\n : boolean\n : C extends ColumnBuilder<'jsonb', infer N, infer _D, infer _E, infer P>\n ? N extends true\n ? P | null\n : P\n : C extends ColumnBuilder<'vector', infer N, infer _D, infer _E, infer _P>\n ? N extends true\n ? number[] | null\n : number[]\n : C extends ColumnBuilder<'enum', infer N, infer _D, infer E, infer _P>\n ? N extends true\n ? E | null\n : E\n : never;\n\n/**\n * True when a column is optional on INSERT:\n * - nullable columns (N = true) — the DB allows NULL so the field may be omitted\n * - columns with a default (D = true) — the DB fills in the value when absent\n */\nexport type ColIsOptionalOnInsert<C> =\n C extends ColumnBuilder<ColumnType, true, boolean, unknown, unknown, unknown>\n ? true\n : C extends ColumnBuilder<ColumnType, boolean, true, unknown, unknown, unknown>\n ? true\n : false;\n\n// ---------------------------------------------------------------------------\n// Factory functions\n// ---------------------------------------------------------------------------\n\n/** Create a UUID column. */\nexport function uuid(): ColumnBuilder<'uuid', false, false, never> {\n return new ColumnBuilder('uuid');\n}\n\n/** Create a TEXT column. */\nexport function text(): ColumnBuilder<'text', false, false, never> {\n return new ColumnBuilder('text');\n}\n\n/** Create an INTEGER column. Emits int4 (max ~2.1B). */\nexport function integer(): ColumnBuilder<'integer', false, false, never> {\n return new ColumnBuilder('integer');\n}\n\n/**\n * Create a BIGINT column (Postgres int8, max ~9.2×10^18).\n * Surfaces as `string` in row/insert types — JS number loses precision past 2^53\n * and pgx/PostgREST serialize int8 as a JSON string. Use BigInt(row.column) in app code.\n */\nexport function bigint(): ColumnBuilder<'bigint', false, false, never> {\n return new ColumnBuilder('bigint');\n}\n\n/**\n * Create a NUMERIC column (Postgres `numeric`/`decimal`, arbitrary precision).\n * For exact fractional values (money with cents as a decimal, rates, weights)\n * where int4/int8 don't fit. Surfaces as `string` in row/insert types — JS\n * number can't hold arbitrary-precision decimals without rounding, and\n * pgx/PostgREST serialize numeric as a JSON string. Parse with a decimal lib\n * (or BigInt for scaled integers) in app code.\n */\nexport function numeric(): ColumnBuilder<'numeric', false, false, never> {\n return new ColumnBuilder('numeric');\n}\n\n/** Create a BOOLEAN column. */\nexport function boolean(): ColumnBuilder<'boolean', false, false, never> {\n return new ColumnBuilder('boolean');\n}\n\n/** Create a TIMESTAMP column. */\nexport function timestamp(): ColumnBuilder<'timestamp', false, false, never> {\n return new ColumnBuilder('timestamp');\n}\n\n/**\n * Create a JSONB column. Pass a payload type to make the generated row/insert\n * type concrete instead of `unknown`:\n *\n * tags: jsonb<string[]>() // row.tags: string[]\n * meta: jsonb<{ tier: string }>() // row.meta: { tier: string }\n * raw: jsonb() // row.raw: unknown (back-compat)\n *\n * The runtime accepts a plain JS object/array directly (no JSON.stringify); the\n * generic only refines the TYPE the env codegen emits.\n */\nexport function jsonb<T = unknown>(): ColumnBuilder<'jsonb', false, false, never, T> {\n return new ColumnBuilder('jsonb');\n}\n\n/**\n * Create an ENUM column.\n * @param name The PostgreSQL enum type name (used in DDL).\n * @param values A readonly tuple of valid string values — kept `const` so the\n * union `V[number]` is as narrow as possible.\n */\nexport function enumType<const V extends readonly string[]>(\n name: string,\n values: V,\n): ColumnBuilder<'enum', false, false, V[number]> {\n const builder = new ColumnBuilder<'enum', false, false, V[number]>('enum');\n builder._def.enumName = name;\n builder._def.enumValues = [...values];\n return builder;\n}\n\n/** vector(n) — pgvector kolonu. n TİPİN parçasıdır (typmod) ve [1, 2000] —\n * 2000 = pgvector'ün HNSW-indekslenebilir tavanı; auto-index bu beyanla bağlı\n * (spec FR-001, D-3). */\nexport function vector(dimensions: number): ColumnBuilder<'vector', false, false, unknown, number[]> {\n if (!Number.isInteger(dimensions) || dimensions < 1 || dimensions > 2000) {\n throw new Error(`vector(): dimensions must be an integer in [1, 2000], got ${String(dimensions)}`);\n }\n const b = new ColumnBuilder('vector') as ColumnBuilder<'vector', false, false, unknown, number[]>;\n (b._def as { dimensions?: number }).dimensions = dimensions;\n return b;\n}\n\n/**\n * Any column, whatever its type parameters.\n *\n * Exported so a cycle can be broken from ONE side:\n * `references((): AnyColumn => y.id)`.\n */\nexport type AnyColumn = ColumnBuilder;\n\n/**\n * The column that OWNS this row: a `text` FK onto `auth.users(id)`, NOT NULL,\n * ON DELETE CASCADE.\n *\n * Ownership drives account erasure, so cascade is the only correct action and\n * takes no argument. The referencing column must be `text` (palauth ids are\n * `usr_<uuid>`) and NOT NULL — both are implied here rather than left to the\n * caller, so three rules the type could not express before become UNWRITABLE.\n *\n * At most ONE per table. The old shape let several columns reference\n * `auth.users` and picked the FIRST IN DECLARATION ORDER as the owner — moving a\n * `created_by` above a `user_id` silently changed which rows an account deletion\n * took with it. A second one is now rejected at push.\n *\n * For a column that merely POINTS at a user without owning the row\n * (`created_by`, `edited_by`), use `userRef({ onDelete })`.\n */\nexport function ownedByUser(): ColumnBuilder<'text', false, false, never> {\n const b = new ColumnBuilder<'text', false, false, never>('text');\n b._def.nullable = false;\n b._def.references = { table: 'auth.users', column: 'id' };\n b._def.onDeleteAction = 'cascade';\n b._def.owns = true;\n return b;\n}\n\n/**\n * A plain FK onto `auth.users(id)` that does NOT own the row.\n *\n * `created_by` / `edited_by`: deleting that user must not delete the row. ON\n * DELETE is required and limited to `cascade | set null` so an erasure request\n * is never blocked by a lingering FK; `set null` needs a nullable column.\n */\nexport function userRef(opts: { onDelete: AuthUserOnDelete; as?: string }): ColumnBuilder<'text', boolean, false, never> {\n const b = new ColumnBuilder<'text', boolean, false, never>('text');\n b._def.references = { table: 'auth.users', column: 'id' };\n b._def.onDeleteAction = opts.onDelete;\n if (opts.as !== undefined) b._def.refAs = opts.as;\n return b;\n}\n\n/**\n * A plain FK onto `auth.installations(id)` — the app-scoped verified-device\n * anchor.\n *\n * An installation is an APP INSTALL, not a user: this is NOT ownership. A\n * user-owned row still needs its own `ownedByUser()` so account erasure removes\n * it; an installation reference alone does not tie a row to a user's deletion.\n */\nexport function installationRef(opts: { onDelete: AuthUserOnDelete; as?: string }): ColumnBuilder<'text', boolean, false, never> {\n const b = new ColumnBuilder<'text', boolean, false, never>('text');\n b._def.references = { table: 'auth.installations', column: 'id' };\n b._def.onDeleteAction = opts.onDelete;\n if (opts.as !== undefined) b._def.refAs = opts.as;\n return b;\n}\n","/**\n * A named raw-SQL DDL object declared in a schema file (`db/public.ts`,\n * `db/billing.ts`, …) for anything the typed DSL\n * cannot express (EXCLUDE, CHECK, partial/expression indexes, triggers, views).\n * The deploy emits `up` verbatim on the privileged DDL connection — same trust\n * posture as policy().using(). Tracked by NAME (not by diffing the body), so a\n * changed body needs a new name or an explicit drop+add.\n */\nexport interface RawConstraintDef {\n name: string;\n up: string;\n down?: string;\n}\n\nexport function raw(name: string, up: string, opts?: { down?: string }): RawConstraintDef {\n return { name, up, ...(opts?.down != null ? { down: opts.down } : {}) };\n}\n","/** Embedding sağlayıcı DESKRIPTORU — canlı istemci değil, düz veri: şemayla\n * birlikte serileşir, çağrıyı Go worker (yazma) ve engine (sorgu) yapar.\n * Adlandırma Vercel AI SDK'nın aynasıdır (openai.embedding(\"...\")) ama paket\n * bağımlılığı bilinçli olarak YOKTUR (spec C-3, UD-016). v1 sağlayıcı: openai (D-10). */\nexport interface EmbeddingModelRef {\n provider: \"openai\";\n model: string;\n dimensions?: number;\n apiKeyName?: string;\n baseURL?: string;\n}\n/** Chat/damıtma modeli DESKRIPTORU (C-11, D-019) — memory beyanının extract'i.\n * Embedding gibi düz veridir; çağrıyı worker yapar, anahtar vault'taki\n * OPENAI_API_KEY'dir (D-017: aynı sağlayıcı, yeni dış sistem yok). */\nexport interface ChatModelRef {\n provider: \"openai\";\n model: string;\n}\nexport const openai = {\n embedding(\n model: string,\n opts?: { dimensions?: number; apiKeyName?: string; baseURL?: string },\n ): EmbeddingModelRef {\n return { provider: \"openai\", model, apiKeyName: opts?.apiKeyName ?? \"OPENAI_API_KEY\",\n ...(opts?.dimensions !== undefined ? { dimensions: opts.dimensions } : {}),\n ...(opts?.baseURL !== undefined ? { baseURL: opts.baseURL } : {}) };\n },\n chat(model: string): ChatModelRef {\n return { provider: \"openai\", model };\n },\n};\n"],"mappings":";;;;;;;;AAyIO,IAAMA,eAAN,MAAMA;EAxIb,OAwIaA;;;EACFC;EAET,YAAYC,MAAc;AACxB,QAAIA,KAAKC,KAAI,MAAO,IAAI;AACtB,YAAM,IAAIC,MAAM,+GAAA;IAClB;AACA,SAAKH,OAAO;MAAEC;IAAK;EACrB;;EAGAG,MAAMC,MAA6B;AACjC,SAAKL,KAAKM,UAAUD,KAAKE,IAAI,CAACC,MAAAA;AAC5B,YAAMC,IAAID,EAAEE;AACZ,UAAID,EAAEE,SAAS,OAAO;AACpB,cAAM,IAAIR,MAAM,SAAS,KAAKH,KAAKC,IAAI,+GAA8E;MACvH;AACA,aAAOQ,EAAER;IACX,CAAA;AACA,WAAO;EACT;;;;;;;;EASAW,aAAaF,MAAoB;AAC/B,SAAKV,KAAKa,aAAaH;AACvB,WAAO;EACT;;EAGAI,MAAMJ,MAA2B;AAC/B,SAAKV,KAAKc,QAAQJ,KAAKA;AACvB,WAAO;EACT;;;EAIAK,OAAa;AACX,SAAKf,KAAKgB,OAAO;AACjB,WAAO;EACT;EAEAC,MAAY;AACV,SAAKjB,KAAKgB,OAAO;AACjB,WAAO;EACT;;EAGAE,MAAMJ,OAA+B;AACnC,SAAKd,KAAKkB,QAAQJ;AAClB,WAAO;EACT;;;EAIAK,QAAQd,MAAsB;AAC5B,SAAKL,KAAKmB,UAAUd;AACpB,WAAO;EACT;AACF;AAEO,SAASe,MAAMnB,MAAY;AAChC,SAAO,IAAIF,aAAaE,IAAAA;AAC1B;AAFgBmB;AA6IhB,SAASC,YAAYC,GAA4B;AAC/C,SAAOA,aAAaC,gBAAgBD,EAAEtB,OAAOsB;AAC/C;AAFSD;AAqDF,IAAMG,aAA4BC,uBAAOC,IAAI,oBAAA;AAiB7C,SAASC,YACd1B,MACA2B,OAAoB;AAEpB,MAAI3B,KAAKC,KAAI,MAAO,IAAI;AACtB,UAAM,IAAIC,MAAM,mDAAA;EAClB;AAIA,QAAM0B,YAAYD,MAAMC,WAAWC,QAAQC,OAAOC,KAAKJ,MAAMtB,OAAO,GAAG,GAAGL,IAAAA,CAAAA,KAAU,CAAA,GAAIM,IAAIc,WAAAA;AAW5F,QAAMY,MAAMJ,SAASK,SAAS,KAAKN,MAAMK,QAAQ;AAcjD,QAAME,QAAQ,CAAC;AACf,aAAW,CAACC,SAASC,CAAAA,KAAMN,OAAOO,QAAQV,MAAMtB,OAAO,GAAG;AACxD,UAAMiC,UAAUF;AAIhB,UAAMG,QAAQT,OAAOU,OAAOV,OAAOW,eAAeH,OAAAA,CAAAA;AAClDR,WAAOY,eAAeH,OAAO,QAAQ;MAAEI,OAAO;QAAE,GAAGL,QAAQvC;MAAK;MAAG6C,YAAY;MAAMC,UAAU;IAAK,CAAA;AACnGX,UAAkCC,OAAAA,IAAWI;EAChD;AAEA,QAAMO,MAAM;IACV9C;IACAK,SAAS6B;IACTF;IACAJ;EACF;AACA,MAAID,MAAMoB,eAAeC,OAAWF,KAAIC,aAAapB,MAAMoB;AAC3D,MAAIpB,MAAMsB,WAAWD,OAAWF,KAAIG,SAAStB,MAAMsB;AACnD,MAAItB,MAAMuB,QAAQF,UAAarB,MAAMuB,IAAIjB,SAAS,EAAGa,KAAII,MAAMvB,MAAMuB,IAAIC,MAAK;AAC9E,MAAIxB,MAAMyB,WAAWJ,UAAarB,MAAMyB,OAAOnB,SAAS,EAAGa,KAAIM,SAASzB,MAAMyB,OAAOD,MAAK;AAG1F,QAAME,mBAAmB1B,MAAM2B,UAAUzB,QAAQC,OAAOC,KAAKJ,MAAMtB,OAAO,GAAG,GAAGL,IAAAA,CAAAA,KAAU,CAAA,GAAIM,IAC5F,CAACiD,MAAOA,aAAazD,eAAeyD,EAAExD,OAAOwD,CAAAA;AAE/C,MAAIF,gBAAgBpB,SAAS,EAAGa,KAAIQ,UAAUD;AAC9C,MAAI1B,MAAM6B,eAAe,KAAMV,KAAIU,aAAa;AAC9C,MAAI7B,MAAM8B,WAAWT,QAAW;AAC9B,UAAMU,IAAI/B,MAAM8B;AAGhB,QAAIC,EAAEC,SAASX,QAAW;AAGxB,UAAIU,EAAEE,WAAWZ,QAAW;AAC1B,cAAM,IAAI9C,MACR,SAASF,IAAAA,6GAA+F;MAE5G;AACA,UAAI0D,EAAEC,KAAK1B,WAAW,GAAG;AACvB,cAAM,IAAI/B,MAAM,SAASF,IAAAA,+BAA8B;MACzD;AACA,UAAI0D,EAAEG,UAAUb,QAAW;AACzB,cAAM,IAAI9C,MACR,SAASF,IAAAA,mIAA+G;MAE5H;AACA,UAAI8D,MAAMC,QAAQL,EAAEM,IAAI,KAAKN,EAAEM,KAAK/B,WAAW,GAAG;AAChD,cAAM,IAAI/B,MAAM,SAASF,IAAAA,mFAAwE;MACnG;IACF,OAAO;AAEL,UAAI,OAAO0D,EAAEM,SAAS,WAAW;AAC/B,cAAM,IAAI9D,MAAM,SAASF,IAAAA,UAAciE,OAAOP,EAAEM,IAAI,CAAA,sDAA4C;MAClG;AACA,UAAIN,EAAEM,SAAShB,UAAaU,EAAEE,WAAWZ,QAAW;AAClD,cAAM,IAAI9C,MACR,SAASF,IAAAA,qHAA6F;MAE1G;AACA,UAAI0D,EAAEM,SAAShB,UAAaU,EAAEM,KAAK/B,WAAW,GAAG;AAC/C,cAAM,IAAI/B,MAAM,SAASF,IAAAA,oFAAsE;MACjG;AACA,YAAMkE,OAAOR,EAAEE,WAAWZ,SAAY,CAAA,IAAKc,MAAMC,QAAQL,EAAEE,MAAM,IAAIF,EAAEE,SAAS;QAACF,EAAEE;;AACnF,iBAAWO,OAAOD,MAAM;AACtB,YAAIC,IAAIN,UAAUb,WAAcmB,IAAIR,SAASX,UAAamB,IAAIR,KAAK1B,WAAW,IAAI;AAChF,gBAAM,IAAI/B,MAAM,SAASF,IAAAA,yGAA8F;QACzH;AACA,YAAImE,IAAIN,UAAUb,UAAamB,IAAIR,SAASX,QAAW;AACrD,gBAAM,IAAI9C,MAAM,SAASF,IAAAA,oFAA2E;QACtG;MACF;IACF;AACA8C,QAAIW,SAASC;EACf;AACA,MAAI/B,MAAMyC,WAAWpB,QAAW;AAC9B,QAAIrB,MAAMyC,OAAOT,KAAK1B,WAAW,GAAG;AAClC,YAAM,IAAI/B,MAAM,SAASF,IAAAA,+BAA8B;IACzD;AACA8C,QAAIsB,SAASzC,MAAMyC;EACrB;AAGF,aAAWhC,KAAKN,OAAOuC,OAAOnC,KAAAA,GAAmC;AAC9DE,MAAyCrC,KAAKuE,aAAaxB;EAC9D;AAGA,QAAMyB,SAAS;IAAE,GAAIrC;EAAkC;AACvDJ,SAAOY,eAAe6B,QAAQhD,YAAY;IAAEoB,OAAOG;IAAKF,YAAY;EAAM,CAAA;AAC1E,SAAO2B;AACT;AA/HgB7C;AA8IhB,IAAM8C,oBAAoB,oBAAIC,QAAAA;AAoB9B,SAASC,kBAAkBC,QAAkCC,YAAkB;AAC7E,aAAWC,SAAS/C,OAAOuC,OAAOM,MAAAA,GAAS;AACzC,eAAW,CAACxC,SAASG,OAAAA,KAAYR,OAAOO,QAAQwC,MAAMxE,OAAO,GAAG;AAC9D,YAAMyC,MAAOR,QAAoCvC;AACjD,UAAI+C,IAAIgC,kBAAkB9B,QAAW;AACnC,YAAI,EAAEF,IAAIgC,iBAAiBD,MAAMxE,UAAU;AACzC,gBAAM,IAAIH,MACR,UAAU2E,MAAM7E,IAAI,aAAamC,OAAAA,sBAA6BW,IAAIgC,aAAa,wCAAmC;QAEtH;AAGAhC,YAAIiC,aAAa;UACfF,OAAOG,kBAAkBJ,YAAYC,MAAM7E,IAAI;UAC/CiF,QAAQnC,IAAIgC;QACd;AACA;MACF;AACA,UAAIhC,IAAIoC,oBAAoBlC,OAAW;AACvC,YAAMmC,SAASrC,IAAIoC,gBAAe;AAClC,YAAME,QAASD,QAAiDpF,MAAMuE;AACtE,UAAIc,UAAUpC,QAAW;AACvB,cAAM,IAAI9C,MACR,UAAU2E,MAAM7E,IAAI,aAAamC,OAAAA,8FAAgG;MAErI;AACA,YAAMkD,eAAevD,OAAOO,QAAQ+C,MAAM/E,OAAO,EAAEiF,KACjD,CAAC,CAAA,EAAGlD,CAAAA,MAAQA,EAAwBrC,SAAUoF,OAA6BpF,IAAI,IAC7E,CAAA;AACJ,UAAIsF,iBAAiBrC,QAAW;AAC9B,cAAM,IAAI9C,MACR,UAAU2E,MAAM7E,IAAI,aAAamC,OAAAA,oDAA2DiD,MAAMpF,IAAI,GAAG;MAE7G;AACA,YAAMuF,eAAef,kBAAkBgB,IAAIJ,KAAAA;AAC3C,UAAIG,iBAAiBvC,QAAW;AAI9B,cAAM,IAAI9C,MACR,UAAU2E,MAAM7E,IAAI,aAAamC,OAAAA,gDAC3BiD,MAAMpF,IAAI,sOAE+D;MAEnF;AACA8C,UAAIiC,aAAa;QACfF,OAAOG,kBAAkBO,cAAcH,MAAMpF,IAAI;QACjDiF,QAAQI;MACV;IACF;EACF;AACF;AApDSX;AAmEF,SAASe,aACdzF,MACA2B,OAAwE;AAOxE,MAAI,OAAO3B,SAAS,UAAU;AAC5B,UAAM,IAAIE,MACR,mjBAOgF;EAEpF;AACA,MAAIF,KAAKC,KAAI,MAAO,IAAI;AACtB,UAAM,IAAIC,MAAM,oDAAA;EAClB;AACA,QAAMyE,SAAS,CAAC;AAChB,aAAWJ,UAAU5C,MAAMgD,QAAQ;AACjC,UAAME,QAAQN,OAAOhD,UAAAA;AACrB,QAAIoD,OAAOE,MAAM7E,IAAI,MAAMgD,QAAW;AACpC,YAAM,IAAI9C,MACR,iBAAiBF,IAAAA,oCAAwC6E,MAAM7E,IAAI,qDAAgD;IAEvH;AACA2E,WAAOE,MAAM7E,IAAI,IAAI6E;AAIrBL,sBAAkBkB,IAAIb,OAAO7E,IAAAA;EAC/B;AAEA0E,oBAAkBC,QAAQ3E,IAAAA;AAG1B,aAAW,CAACA,OAAM8C,GAAAA,KAAQhB,OAAOO,QAAQsC,MAAAA,GAAS;AAChD,UAAMgB,IAAK7C,IAAiBsB;AAC5B,QAAIuB,MAAM3C,OAAW;AACrB,UAAMmC,SAASrD,OAAOuC,OAAOM,MAAAA,EAAQW,KAAK,CAACM,MAAOA,EAAe5F,SAAS2F,EAAEE,IAAI;AAChF,QAAIV,WAAWnC,QAAW;AACxB,YAAM,IAAI9C,MAAM,SAASF,KAAAA,kBAAsB2F,EAAEE,IAAI,mCAAyB;IAChF;AACA,UAAMC,UAAUH,EAAEG,WAAW;AAC7B,QAAI,EAAEA,WAAYhD,IAAiBzC,UAAU;AAC3C,YAAM,IAAIH,MAAM,SAASF,KAAAA,qBAAyB8F,OAAAA,6BAAoC;IACxF;AACA,QAAI,EAAEA,WAAWX,OAAO9E,UAAU;AAChC,YAAM,IAAIH,MAAM,SAASF,KAAAA,qBAAyB8F,OAAAA,mBAA0BH,EAAEE,IAAI,kBAAkB;IACtG;AACA,UAAME,UAAUZ,OAAO9E,QAAQ,MAAA;AAC/B,UAAM2F,UAAUD,YAAY/C,UAAa,UAAW+C,UAC/CA,QAAwChG,OACxCgG;AACL,QAAIC,YAAYhD,UAAagD,QAAQC,SAAS,QAAQ;AACpD,YAAM,IAAI/F,MAAM,SAASF,KAAAA,kBAAsB2F,EAAEE,IAAI,2CAA2C;IAClG;AACA,eAAWtF,KAAKoF,EAAEhC,MAAM;AACtB,UAAI,EAAEpD,KAAMuC,IAAiBzC,UAAU;AACrC,cAAM,IAAIH,MAAM,SAASF,KAAAA,yBAA6BO,CAAAA,sBAAuB;MAC/E;IACF;EACF;AAEA,QAAM2F,aAAa;OAAI,IAAIC,IAAIxE,MAAMuE,cAAc,CAAA,CAAE;;AAKrD,SAAO;IACLlG;IACA2E;IACAuB;IACAE,SAASzE,MAAMyE,WAAWpG,SAAS;EACrC;AACF;AAjFgByF;;;ACniBT,IAAMY,gBAAN,MAAMA,eAAAA;EAhGb,OAgGaA;;;;EACX,YAAqBC,MAAkB;SAAlBA,OAAAA;EAAmB;EAEhCC,IAAIC,IAAiBC,OAAqC;AAChE,WAAO,IAAIJ,eAAc;MAAEK,MAAM;MAASF;MAAIG,MAAM,KAAKL;MAAMM,OAAOC,OAAOJ,KAAAA;IAAO,CAAA;EACtF;EAEAK,GAAGL,OAAqC;AAAE,WAAO,KAAKF,IAAI,MAAME,KAAAA;EAAQ;EACxEM,IAAIN,OAAqC;AAAE,WAAO,KAAKF,IAAI,OAAOE,KAAAA;EAAQ;EAC1EO,GAAGP,OAAqC;AAAE,WAAO,KAAKF,IAAI,MAAME,KAAAA;EAAQ;EACxEQ,IAAIR,OAAqC;AAAE,WAAO,KAAKF,IAAI,OAAOE,KAAAA;EAAQ;EAC1ES,GAAGT,OAAqC;AAAE,WAAO,KAAKF,IAAI,MAAME,KAAAA;EAAQ;EACxEU,IAAIV,OAAqC;AAAE,WAAO,KAAKF,IAAI,OAAOE,KAAAA;EAAQ;;;;;;EAO1EW,OAAOC,UAAU,OAAsB;AACrC,WAAO,IAAIhB,eAAc;MAAEK,MAAM;MAAUJ,MAAM,KAAKA;MAAMe;IAAQ,CAAA;EACtE;EAEAC,OAAOC,QAAwC;AAC7C,WAAO,IAAIlB,eAAc;MAAEK,MAAM;MAAOc,OAAO;QAAC,KAAKlB;WAASiB,OAAOE,IAAI,CAACC,MAAMA,EAAEpB,IAAI;;IAAG,CAAA;EAC3F;EACAqB,MAAMJ,QAAwC;AAC5C,WAAO,IAAIlB,eAAc;MAAEK,MAAM;MAAMc,OAAO;QAAC,KAAKlB;WAASiB,OAAOE,IAAI,CAACC,MAAMA,EAAEpB,IAAI;;IAAG,CAAA;EAC1F;EACAsB,MAAqB;AACnB,WAAO,IAAIvB,eAAc;MAAEK,MAAM;MAAOJ,MAAM,KAAKA;IAAK,CAAA;EAC1D;AACF;AAYA,SAASO,OAAOgB,GAAgB;AAC9B,SAAOA,aAAaxB,gBAAgBwB,EAAEvB,OAAO;IAAEI,MAAM;IAAOoB,OAAOD;EAAE;AACvE;AAFShB;AAyDF,SAASkB,QACdC,UACAC,QAAQ,GAWRC,WAAW,IAAE;AAKb,QAAMC,QAAQ,OAAOF,KAAAA;AACrB,SAAO;IACLG,KAAK,wBAACC,SACJ,IAAIhC,cAAc4B,UAAU,IAAI;MAAEvB,MAAM;MAAO2B;IAAK,IAAI;MAAE3B,MAAM;MAAO2B;MAAMF;IAAM,CAAA,GADhF;IAELG,MAAM;MAAEC,KAAK,6BAAM,IAAIlC,cAAc;QAAEK,MAAM;MAAU,CAAA,GAA1C;IAA6C;IAC1D8B,KAAK,wBAACX,MAAM,IAAIxB,cAAc;MAAEK,MAAM;MAAOoB,OAAOD;IAAE,CAAA,GAAjD;IACLP,KAAK,2BAAIE,UAAU,IAAInB,cAAc;MAAEK,MAAM;MAAOc,OAAOA,MAAMC,IAAI,CAACgB,MAAMA,EAAEnC,IAAI;IAAE,CAAA,GAA/E;IACLqB,IAAI,2BAAIH,UAAU,IAAInB,cAAc;MAAEK,MAAM;MAAMc,OAAOA,MAAMC,IAAI,CAACgB,MAAMA,EAAEnC,IAAI;IAAE,CAAA,GAA9E;IACJsB,KAAK,wBAACc,SAAS,IAAIrC,cAAc;MAAEK,MAAM;MAAOJ,MAAMoC,KAAKpC;IAAK,CAAA,GAA3D;IACLqC,UAAU,wBAACC,OAAOC,cAAAA;AAChB,YAAMC,OAAQF,MAAiEG,UAAAA;AAC/E,YAAMC,QAAQjB,QAAQkB,OAAOC,KAAKJ,KAAKK,OAAO,GAAGlB,QAAQ,GAAGC,QAAAA;AAC5D,aAAO,IAAI7B,cAAc;QACvBK,MAAM;QACNkC,OAAOE,KAAKT;QACZF,OAAO,OAAOF,QAAQ,CAAA;QACtBmB,OAAOlB;QACPW,WAAWA,UAAUG,KAAAA,EAAgB1C;MACvC,CAAA;IACF,GAVU;EAWZ;AACF;AAvCgByB;AAsFhB,SAASsB,MAAMhB,MAAY;AACzB,SAAO,IAAIA,KAAKiB,QAAQ,MAAM,IAAA,CAAA;AAChC;AAFSD;AAIF,IAAME,gBAAN,MAAMA;EA/Rb,OA+RaA;;;EACFC;EAET,YAAYnB,MAAc;AACxB,SAAKmB,OAAO;MACVnB;MACAoB,SAAS;MACTC,OAAO;QAAC;;MACRC,OAAO;MACPC,WAAW;MACXC,YAAY;IACd;EACF;;EAGAC,IAAIL,SAA8B;AAChC,SAAKD,KAAKC,UAAUA;AACpB,WAAO;EACT;;;;;;;;;;EAWAM,MAAML,OAAuB;AAC3B,SAAKF,KAAKE,QAAQA;AAClB,WAAO;EACT;;;;;;;;;;;;;;;;;EAkBAC,MAAMrD,MAAoC;AACxC,SAAKkD,KAAKG,QAAQrD,gBAAgBD,gBAAgBC,KAAKA,OAAOA;AAC9D,WAAO;EACT;;;;;;;;;;;;;;;;;;;;;;;;;EA0BA0D,SACEC,iBACAC,YACAC,UAAoD,CAAC,GAC/C;AACN,QAAI,KAAKX,KAAKG,UAAU,MAAM;AAG5B,YAAM,IAAIS,MACR,UAAU,KAAKZ,KAAKnB,IAAI,6HACtB;IAEN;AACA,UAAMgC,SAASF,QAAQE,UAAU;AACjC,UAAMC,aAAaH,QAAQG,cAAc;AACzC,SAAKd,KAAKG,QACR,GAAGN,MAAMgB,MAAAA,CAAAA,eAAsBhB,MAAMa,UAAAA,CAAAA,SAAoBb,MAAMY,eAAAA,CAAAA,UACtDZ,MAAMiB,UAAAA,CAAAA;AACjB,WAAO;EACT;;EAGAV,UAAUtD,MAAoC;AAC5C,SAAKkD,KAAKI,YAAYtD,gBAAgBD,gBAAgBC,KAAKA,OAAOA;AAClE,WAAO;EACT;;;EAIAiE,GAAGC,MAAwB;AACzB,SAAKhB,KAAKK,aAAaW,SAAS;AAChC,WAAO;EACT;AACF;AAUO,SAASC,OAAOpC,MAAY;AACjC,SAAO,IAAIkB,cAAclB,IAAAA;AAC3B;AAFgBoC;;;AC7YT,IAAMC,qBAAqB;;EAEhC;;EAEA;EACA;EACA;;EAEA;EACA;;EAEA;EACA;;EAEA;;;;EAIA;EACA;;AAWK,IAAMC,yBAAgF;EAC3FC,eAAe;IAAC;;AAClB;AAGO,SAASC,mBAAmBC,MAAY;AAC7C,SAAQJ,mBAAyCK,SAASD,IAAAA;AAC5D;AAFgBD;;;AC4EhB,SAASG,eAAeC,KAAgBC,UAAgB;AACtD,MAAID,IAAIE,SAAS,UAAU;AACzB,UAAM,IAAIC,MAAM,mBAAmBF,QAAAA,mEAAsE;EAC3G;AACF;AAJSF;AAoCF,IAAMK,gBAAN,MAAMA,eAAAA;EA/Jb,OA+JaA;;;EAwBFC;EAET,YAAYH,MAASI,aAAyB;AAC5C,SAAKD,OAAOC,eAAe;MACzBJ;MACAK,UAAU;MACVC,YAAY;IACd;EACF;;EAGAA,aAA8C;AAC5CT,mBAAe,KAAKM,MAAM,YAAA;AAC1B,SAAKA,KAAKG,aAAa;AACvB,WAAO,IAAIJ,eAAgC,KAAKC,KAAKH,MAAW,KAAKG,IAAI;EAC3E;;EAGAI,UAA+C;AAC7C,SAAKJ,KAAKE,WAAW;AACrB,WAAO,IAAIH,eAAoC,KAAKC,KAAKH,MAAW,KAAKG,IAAI;EAC/E;;EAGAE,WAA+C;AAC7C,SAAKF,KAAKE,WAAW;AACrB,WAAO,IAAIH,eAAmC,KAAKC,KAAKH,MAAW,KAAKG,IAAI;EAC9E;;EAGAK,QAAQC,OAAoD;AAC1DZ,mBAAe,KAAKM,MAAM,SAAA;AAC1B,SAAKA,KAAKO,eAAeD;AACzB,WAAO,IAAIP,eAAmC,KAAKC,KAAKH,MAAW,KAAKG,IAAI;EAC9E;;EAGAQ,gBAAoD;AAClDd,mBAAe,KAAKM,MAAM,eAAA;AAC1B,SAAKA,KAAKQ,gBAAgB;AAC1B,WAAO,IAAIT,eAAmC,KAAKC,KAAKH,MAAW,KAAKG,IAAI;EAC9E;;EAGAS,aAAiD;AAC/Cf,mBAAe,KAAKM,MAAM,YAAA;AAC1B,SAAKA,KAAKS,aAAa;AACvB,WAAO,IAAIV,eAAmC,KAAKC,KAAKH,MAAW,KAAKG,IAAI;EAC9E;;;;;;;;;;;;EAaAU,aAAiD;AAC/C,SAAKV,KAAKU,aAAa;AACvB,WAAO,IAAIX,eAAmC,KAAKC,KAAKH,MAAW,KAAKG,IAAI;EAC9E;;;;;;;;;;;;;EAcAW,YAAYC,UAAmD;AAC7D,SAAKZ,KAAKW,cAAcC;AACxB,WAAO;EACT;;;;;;;;;;;;;;;;;EAkBAC,UAA2C;AACzC,WAAO,IAAId,eAAgC,KAAKC,KAAKH,MAAW;MAC9D,GAAG,KAAKG;MACRa,SAAS;IACX,CAAA;EACF;;;;;;;;;;;;;;;;;;;;;EAsBAC,WACEC,QACAC,MAkBiC;AACjCtB,mBAAe,KAAKM,MAAM,YAAA;AAC1B,QAAI,OAAOe,WAAW,YAAY;AAIhC,YAAM,IAAIjB,MACR,oOAEwD;IAE5D;AACA,SAAKE,KAAKiB,kBAAkBF;AAC5B,QAAIC,MAAME,OAAOC,OAAW,MAAKnB,KAAKoB,QAAQJ,KAAKE;AACnD,QAAIF,MAAMK,cAAcF,OAAW,MAAKnB,KAAKqB,YAAYL,KAAKK;AAC9D,QAAIL,MAAMM,aAAaH,OAAW,MAAKnB,KAAKuB,iBAAiBP,KAAKM;AAGlE,QAAIN,MAAMQ,UAAU,MAAO,MAAKxB,KAAKwB,QAAQ;AAC7C,WAAO,IAAIzB,eAAgC,KAAKC,KAAKH,MAAW,KAAKG,IAAI;EAC3E;;;;;;;;;;;;;;;;;;EAmBAyB,UAA2C;AACzC,SAAKzB,KAAKyB,UAAU;AACpB,WAAO,IAAI1B,eAAgC,KAAKC,KAAKH,MAAW,KAAKG,IAAI;EAC3E;;;;;;;;;;EAWA0B,eACEC,QACAX,MACiC;AACjCtB,mBAAe,KAAKM,MAAM,gBAAA;AAC1B,SAAKA,KAAK4B,gBAAgBD;AAC1B,QAAIX,MAAME,OAAOC,OAAW,MAAKnB,KAAKoB,QAAQJ,KAAKE;AACnD,QAAIF,MAAMM,aAAaH,OAAW,MAAKnB,KAAKuB,iBAAiBP,KAAKM;AAClE,WAAO,IAAIvB,eAAgC,KAAKC,KAAKH,MAAW,KAAKG,IAAI;EAC3E;;EAKAsB,SAASO,QAAyD;AAChE,SAAK7B,KAAKuB,iBAAiBM;AAC3B,WAAO,IAAI9B,eAAgC,KAAKC,KAAKH,MAAW,KAAKG,IAAI;EAC3E;;EAGA8B,SAA0C;AACxCpC,mBAAe,KAAKM,MAAM,QAAA;AAC1B,SAAKA,KAAK8B,SAAS;AACnB,WAAO,IAAI/B,eAAgC,KAAKC,KAAKH,MAAW,KAAKG,IAAI;EAC3E;;;;;;;;;;;;;;;;;;;EAoBA+B,UAAkBC,KAAoE;AAIpF,SAAKhC,KAAK+B,YAAYC;AACtB,WAAO,IAAIjC,eAAqC,KAAKC,KAAKH,MAAW,KAAKG,IAAI;EAChF;AACF;AA6EO,SAASiC,OAAAA;AACd,SAAO,IAAIlC,cAAc,MAAA;AAC3B;AAFgBkC;AAKT,SAASC,OAAAA;AACd,SAAO,IAAInC,cAAc,MAAA;AAC3B;AAFgBmC;AAKT,SAASC,UAAAA;AACd,SAAO,IAAIpC,cAAc,SAAA;AAC3B;AAFgBoC;AAST,SAASC,SAAAA;AACd,SAAO,IAAIrC,cAAc,QAAA;AAC3B;AAFgBqC;AAYT,SAASC,UAAAA;AACd,SAAO,IAAItC,cAAc,SAAA;AAC3B;AAFgBsC;AAKT,SAASC,UAAAA;AACd,SAAO,IAAIvC,cAAc,SAAA;AAC3B;AAFgBuC;AAKT,SAASC,YAAAA;AACd,SAAO,IAAIxC,cAAc,WAAA;AAC3B;AAFgBwC;AAeT,SAASC,QAAAA;AACd,SAAO,IAAIzC,cAAc,OAAA;AAC3B;AAFgByC;AAUT,SAASC,SACdC,MACAC,QAAS;AAET,QAAMC,UAAU,IAAI7C,cAA+C,MAAA;AACnE6C,UAAQ5C,KAAK6C,WAAWH;AACxBE,UAAQ5C,KAAK8C,aAAa;OAAIH;;AAC9B,SAAOC;AACT;AARgBH;AAaT,SAASM,OAAOC,YAAkB;AACvC,MAAI,CAACC,OAAOC,UAAUF,UAAAA,KAAeA,aAAa,KAAKA,aAAa,KAAM;AACxE,UAAM,IAAIlD,MAAM,6DAA6DqD,OAAOH,UAAAA,CAAAA,EAAa;EACnG;AACA,QAAMI,IAAI,IAAIrD,cAAc,QAAA;AAC3BqD,IAAEpD,KAAiCgD,aAAaA;AACjD,SAAOI;AACT;AAPgBL;AAkCT,SAASM,cAAAA;AACd,QAAMD,IAAI,IAAIrD,cAA2C,MAAA;AACzDqD,IAAEpD,KAAKE,WAAW;AAClBkD,IAAEpD,KAAKc,aAAa;IAAEwC,OAAO;IAAc3B,QAAQ;EAAK;AACxDyB,IAAEpD,KAAKuB,iBAAiB;AACxB6B,IAAEpD,KAAKuD,OAAO;AACd,SAAOH;AACT;AAPgBC;AAgBT,SAASG,QAAQxC,MAAiD;AACvE,QAAMoC,IAAI,IAAIrD,cAA6C,MAAA;AAC3DqD,IAAEpD,KAAKc,aAAa;IAAEwC,OAAO;IAAc3B,QAAQ;EAAK;AACxDyB,IAAEpD,KAAKuB,iBAAiBP,KAAKM;AAC7B,MAAIN,KAAKE,OAAOC,OAAWiC,GAAEpD,KAAKoB,QAAQJ,KAAKE;AAC/C,SAAOkC;AACT;AANgBI;AAgBT,SAASC,gBAAgBzC,MAAiD;AAC/E,QAAMoC,IAAI,IAAIrD,cAA6C,MAAA;AAC3DqD,IAAEpD,KAAKc,aAAa;IAAEwC,OAAO;IAAsB3B,QAAQ;EAAK;AAChEyB,IAAEpD,KAAKuB,iBAAiBP,KAAKM;AAC7B,MAAIN,KAAKE,OAAOC,OAAWiC,GAAEpD,KAAKoB,QAAQJ,KAAKE;AAC/C,SAAOkC;AACT;AANgBK;;;ACjoBT,SAASC,IAAIC,MAAcC,IAAYC,MAAwB;AACpE,SAAO;IAAEF;IAAMC;IAAI,GAAIC,MAAMC,QAAQ,OAAO;MAAEA,MAAMD,KAAKC;IAAK,IAAI,CAAC;EAAG;AACxE;AAFgBJ;;;ACIT,IAAMK,SAAS;EACpBC,UACEC,OACAC,MAAqE;AAErE,WAAO;MAAEC,UAAU;MAAUF;MAAOG,YAAYF,MAAME,cAAc;MAClE,GAAIF,MAAMG,eAAeC,SAAY;QAAED,YAAYH,KAAKG;MAAW,IAAI,CAAC;MACxE,GAAIH,MAAMK,YAAYD,SAAY;QAAEC,SAASL,KAAKK;MAAQ,IAAI,CAAC;IAAG;EACtE;EACAC,KAAKP,OAAa;AAChB,WAAO;MAAEE,UAAU;MAAUF;IAAM;EACrC;AACF;","names":["IndexBuilder","_def","name","trim","Error","on","cols","columns","map","c","e","expr","kind","onExpression","expression","where","desc","sort","asc","nulls","include","index","toPolicyDef","p","PolicyBuilder","TABLE_META","Symbol","for","defineTable","input","policies","exprCtx","Object","keys","rls","length","owned","colName","b","entries","builder","clone","create","getPrototypeOf","defineProperty","value","enumerable","writable","def","primaryKey","undefined","unique","raw","slice","checks","declaredIndexes","indexes","i","appendOnly","search","s","from","vector","model","Array","isArray","text","String","legs","leg","memory","values","ownerTable","handle","declaringSchemaOf","WeakMap","resolveReferences","tables","schemaName","table","selfRefColumn","references","qualifiedTableKey","column","referencesThunk","target","owner","targetColumn","find","targetSchema","get","defineSchema","set","m","t","into","subject","factCol","factDef","type","extensions","Set","exposed","PolicyExprRef","expr","bin","op","other","kind","left","right","toExpr","eq","neq","gt","gte","lt","lte","isNull","negated","and","others","parts","map","o","or","not","v","value","exprCtx","_columns","depth","ownTable","alias","col","name","auth","uid","lit","p","part","existsIn","table","predicate","meta","TABLE_META","inner","Object","keys","columns","outer","quote","replace","PolicyBuilder","_def","command","roles","using","withCheck","permissive","for","to","memberOf","membershipTable","foreignKey","options","Error","column","userColumn","as","mode","policy","PALBASE_EXTENSIONS","EXTENSION_DEPENDENCIES","earthdistance","isPalbaseExtension","name","includes","refuseOnVector","def","modifier","type","Error","ColumnBuilder","_def","existingDef","nullable","primaryKey","notNull","default","value","defaultValue","defaultRandom","defaultNow","dbAssigned","renamedFrom","previous","ignored","references","target","opts","referencesThunk","as","undefined","refAs","reverseAs","onDelete","onDeleteAction","index","counter","selfReferences","column","selfRefColumn","action","unique","transform","fns","uuid","text","integer","bigint","numeric","boolean","timestamp","jsonb","enumType","name","values","builder","enumName","enumValues","vector","dimensions","Number","isInteger","String","b","ownedByUser","table","owns","userRef","installationRef","raw","name","up","opts","down","openai","embedding","model","opts","provider","apiKeyName","dimensions","undefined","baseURL","chat"]}
|
package/dist/chunk-SG4UTNOP.js
DELETED
|
@@ -1,374 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
TxPlanBuilder,
|
|
3
|
-
brandRef,
|
|
4
|
-
runTxPlan
|
|
5
|
-
} from "./chunk-3TUJWHC2.js";
|
|
6
|
-
import {
|
|
7
|
-
isRetryable
|
|
8
|
-
} from "./chunk-CGNN2PUH.js";
|
|
9
|
-
import {
|
|
10
|
-
__name
|
|
11
|
-
} from "./chunk-VXPNPVAG.js";
|
|
12
|
-
|
|
13
|
-
// src/db/typed-db.ts
|
|
14
|
-
function makeTypedTable(name, raw) {
|
|
15
|
-
return {
|
|
16
|
-
insert: /* @__PURE__ */ __name((data) => raw.insert(name, data), "insert"),
|
|
17
|
-
aggregate: /* @__PURE__ */ __name((q) => raw.aggregate(name, q), "aggregate"),
|
|
18
|
-
insertMany: /* @__PURE__ */ __name((rows, opts) => raw.insertMany(name, rows, opts), "insertMany"),
|
|
19
|
-
put: /* @__PURE__ */ __name((q) => raw.put(name, q.data, {
|
|
20
|
-
onConflict: q.onConflict
|
|
21
|
-
}), "put"),
|
|
22
|
-
update: /* @__PURE__ */ __name((q) => raw.update(name, q.where.id, q.set), "update"),
|
|
23
|
-
delete: /* @__PURE__ */ __name((id) => raw.delete(name, id), "delete"),
|
|
24
|
-
findById: /* @__PURE__ */ __name((id) => raw.findById(name, id), "findById"),
|
|
25
|
-
findMany: /* @__PURE__ */ __name((q) => {
|
|
26
|
-
const { where, ...opts } = q ?? {};
|
|
27
|
-
return raw.findMany(name, where, opts);
|
|
28
|
-
}, "findMany"),
|
|
29
|
-
updateMany: /* @__PURE__ */ __name((q) => raw.updateMany(name, q.where, q.set, q.returning === void 0 ? void 0 : {
|
|
30
|
-
returning: q.returning
|
|
31
|
-
}), "updateMany"),
|
|
32
|
-
deleteMany: /* @__PURE__ */ __name((q) => raw.deleteMany(name, q.where), "deleteMany"),
|
|
33
|
-
count: /* @__PURE__ */ __name((q) => raw.count(name, q?.where), "count")
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
__name(makeTypedTable, "makeTypedTable");
|
|
37
|
-
function makeTypedDB(schema, raw) {
|
|
38
|
-
const tables = {};
|
|
39
|
-
for (const key of Object.keys(schema.tables)) {
|
|
40
|
-
const tableDef = schema.tables[key];
|
|
41
|
-
if (tableDef !== void 0) {
|
|
42
|
-
tables[key] = makeTypedTable(tableDef.name, raw);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
const result = {
|
|
46
|
-
tables,
|
|
47
|
-
transaction(fn) {
|
|
48
|
-
const builder = new TxPlanBuilder();
|
|
49
|
-
const planTables = {};
|
|
50
|
-
for (const key of Object.keys(schema.tables)) {
|
|
51
|
-
const tableDef = schema.tables[key];
|
|
52
|
-
if (tableDef !== void 0) planTables[key] = builder.table(tableDef.name);
|
|
53
|
-
}
|
|
54
|
-
return runTxPlan(raw, {
|
|
55
|
-
tables: planTables
|
|
56
|
-
}, builder, fn);
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
return result;
|
|
60
|
-
}
|
|
61
|
-
__name(makeTypedDB, "makeTypedDB");
|
|
62
|
-
function col(name) {
|
|
63
|
-
return brandRef({
|
|
64
|
-
$col: name
|
|
65
|
-
}, "col");
|
|
66
|
-
}
|
|
67
|
-
__name(col, "col");
|
|
68
|
-
async function withRetry(fn, opts = {}) {
|
|
69
|
-
const budget = opts.retry ?? 0;
|
|
70
|
-
let attempt = 0;
|
|
71
|
-
for (; ; ) {
|
|
72
|
-
try {
|
|
73
|
-
return await fn();
|
|
74
|
-
} catch (e) {
|
|
75
|
-
if (attempt >= budget || !isRetryable(e)) throw e;
|
|
76
|
-
attempt += 1;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
__name(withRetry, "withRetry");
|
|
81
|
-
function sqlFragment(strings, ...values) {
|
|
82
|
-
return brandRef({
|
|
83
|
-
$sql: {
|
|
84
|
-
text: [
|
|
85
|
-
...strings
|
|
86
|
-
],
|
|
87
|
-
values
|
|
88
|
-
}
|
|
89
|
-
}, "sql");
|
|
90
|
-
}
|
|
91
|
-
__name(sqlFragment, "sqlFragment");
|
|
92
|
-
|
|
93
|
-
// src/db/schema-json.ts
|
|
94
|
-
function defOf(column) {
|
|
95
|
-
return "_def" in column ? column._def : column;
|
|
96
|
-
}
|
|
97
|
-
__name(defOf, "defOf");
|
|
98
|
-
function columnToJSON(column) {
|
|
99
|
-
const def = defOf(column);
|
|
100
|
-
const out = {
|
|
101
|
-
type: def.type,
|
|
102
|
-
nullable: def.nullable,
|
|
103
|
-
primaryKey: def.primaryKey
|
|
104
|
-
};
|
|
105
|
-
if (def.defaultValue !== void 0) out.defaultValue = def.defaultValue;
|
|
106
|
-
if (def.defaultRandom === true) out.defaultRandom = true;
|
|
107
|
-
if (def.defaultNow === true) out.defaultNow = true;
|
|
108
|
-
if (def.renamedFrom !== void 0) out.renamedFrom = def.renamedFrom;
|
|
109
|
-
if (def.ignored === true) out.ignored = true;
|
|
110
|
-
if (def.owns === true) out.owns = true;
|
|
111
|
-
if (def.references !== void 0) {
|
|
112
|
-
out.references = {
|
|
113
|
-
table: def.references.table,
|
|
114
|
-
column: def.references.column
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
if (def.onDeleteAction !== void 0) out.onDeleteAction = def.onDeleteAction;
|
|
118
|
-
if (def.index === false) out.index = false;
|
|
119
|
-
if (def.counter === true) out.counter = true;
|
|
120
|
-
if (def.enumName !== void 0) out.enumName = def.enumName;
|
|
121
|
-
if (def.enumValues !== void 0) out.enumValues = [
|
|
122
|
-
...def.enumValues
|
|
123
|
-
];
|
|
124
|
-
if (def.unique === true) out.unique = true;
|
|
125
|
-
if (def.dimensions !== void 0) out.dimensions = def.dimensions;
|
|
126
|
-
return out;
|
|
127
|
-
}
|
|
128
|
-
__name(columnToJSON, "columnToJSON");
|
|
129
|
-
function policyToJSON(policy) {
|
|
130
|
-
return {
|
|
131
|
-
name: policy.name,
|
|
132
|
-
command: policy.command ?? "all",
|
|
133
|
-
roles: policy.roles ? [
|
|
134
|
-
...policy.roles
|
|
135
|
-
] : [],
|
|
136
|
-
// null rather than omitted: a policy with no USING clause is a different
|
|
137
|
-
// thing from one whose clause the emitter forgot, and Go reads the
|
|
138
|
-
// difference.
|
|
139
|
-
using: policy.using ?? null,
|
|
140
|
-
withCheck: policy.withCheck ?? null,
|
|
141
|
-
permissive: policy.permissive !== false
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
__name(policyToJSON, "policyToJSON");
|
|
145
|
-
function commonSearchFields(search, out) {
|
|
146
|
-
if (search.synonyms !== void 0 && Object.keys(search.synonyms).length > 0) {
|
|
147
|
-
out.synonyms = Object.fromEntries(Object.entries(search.synonyms).map(([word, alts]) => [
|
|
148
|
-
word,
|
|
149
|
-
[
|
|
150
|
-
...alts
|
|
151
|
-
]
|
|
152
|
-
]));
|
|
153
|
-
}
|
|
154
|
-
if (search.validity === true) out.validity = true;
|
|
155
|
-
}
|
|
156
|
-
__name(commonSearchFields, "commonSearchFields");
|
|
157
|
-
function searchToJSON(search, vectorColumn) {
|
|
158
|
-
if (search.from !== void 0 && search.model !== void 0) {
|
|
159
|
-
const out2 = {};
|
|
160
|
-
const textCols = search.text === false ? void 0 : Array.isArray(search.text) && search.text.length > 0 ? search.text : search.from;
|
|
161
|
-
if (textCols !== void 0) out2.text = {
|
|
162
|
-
columns: [
|
|
163
|
-
...textCols
|
|
164
|
-
]
|
|
165
|
-
};
|
|
166
|
-
const v = {
|
|
167
|
-
metric: search.metric ?? "cosine"
|
|
168
|
-
};
|
|
169
|
-
if (vectorColumn !== void 0) v.column = vectorColumn;
|
|
170
|
-
v.embed = {
|
|
171
|
-
provider: search.model.provider,
|
|
172
|
-
model: search.model.model,
|
|
173
|
-
from: [
|
|
174
|
-
...search.from
|
|
175
|
-
],
|
|
176
|
-
...search.model.apiKeyName !== void 0 ? {
|
|
177
|
-
apiKeyName: search.model.apiKeyName
|
|
178
|
-
} : {},
|
|
179
|
-
...search.model.dimensions !== void 0 ? {
|
|
180
|
-
dimensions: search.model.dimensions
|
|
181
|
-
} : {},
|
|
182
|
-
...search.model.baseURL !== void 0 ? {
|
|
183
|
-
baseURL: search.model.baseURL
|
|
184
|
-
} : {}
|
|
185
|
-
};
|
|
186
|
-
if (search.staleness !== void 0) v.staleness = search.staleness;
|
|
187
|
-
if (vectorColumn === void 0) {
|
|
188
|
-
v.mode = "chunks";
|
|
189
|
-
if (search.chunks !== void 0) {
|
|
190
|
-
const c = {};
|
|
191
|
-
if (search.chunks.size !== void 0 && search.chunks.size > 0) c.sizeChars = search.chunks.size;
|
|
192
|
-
if (search.chunks.overlap !== void 0 && search.chunks.overlap > 0) c.overlapChars = search.chunks.overlap;
|
|
193
|
-
if (Object.keys(c).length > 0) v.chunks = c;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
out2.vector = [
|
|
197
|
-
v
|
|
198
|
-
];
|
|
199
|
-
commonSearchFields(search, out2);
|
|
200
|
-
return out2;
|
|
201
|
-
}
|
|
202
|
-
const out = {};
|
|
203
|
-
if (Array.isArray(search.text) && search.text.length > 0) out.text = {
|
|
204
|
-
columns: [
|
|
205
|
-
...search.text
|
|
206
|
-
]
|
|
207
|
-
};
|
|
208
|
-
const legs = search.vector === void 0 ? [] : Array.isArray(search.vector) ? search.vector : [
|
|
209
|
-
search.vector
|
|
210
|
-
];
|
|
211
|
-
if (legs.length > 0) {
|
|
212
|
-
out.vector = legs.map((leg) => {
|
|
213
|
-
const v = {
|
|
214
|
-
metric: leg.metric ?? "cosine"
|
|
215
|
-
};
|
|
216
|
-
if (leg.column !== void 0) v.column = leg.column;
|
|
217
|
-
if (leg.staleness !== void 0) v.staleness = leg.staleness;
|
|
218
|
-
if (leg.model !== void 0) {
|
|
219
|
-
v.embed = {
|
|
220
|
-
provider: leg.model.provider,
|
|
221
|
-
model: leg.model.model,
|
|
222
|
-
from: [
|
|
223
|
-
...leg.from ?? []
|
|
224
|
-
],
|
|
225
|
-
...leg.model.apiKeyName !== void 0 ? {
|
|
226
|
-
apiKeyName: leg.model.apiKeyName
|
|
227
|
-
} : {},
|
|
228
|
-
...leg.model.dimensions !== void 0 ? {
|
|
229
|
-
dimensions: leg.model.dimensions
|
|
230
|
-
} : {},
|
|
231
|
-
...leg.model.baseURL !== void 0 ? {
|
|
232
|
-
baseURL: leg.model.baseURL
|
|
233
|
-
} : {}
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
return v;
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
commonSearchFields(search, out);
|
|
240
|
-
return out;
|
|
241
|
-
}
|
|
242
|
-
__name(searchToJSON, "searchToJSON");
|
|
243
|
-
function memoryToJSON(m) {
|
|
244
|
-
return {
|
|
245
|
-
from: [
|
|
246
|
-
...m.from
|
|
247
|
-
],
|
|
248
|
-
into: m.into,
|
|
249
|
-
...m.subject !== void 0 ? {
|
|
250
|
-
subject: m.subject
|
|
251
|
-
} : {},
|
|
252
|
-
extract: {
|
|
253
|
-
provider: m.extract.provider,
|
|
254
|
-
model: m.extract.model
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
__name(memoryToJSON, "memoryToJSON");
|
|
259
|
-
function tableToJSON(table, schemaName) {
|
|
260
|
-
const columns = {};
|
|
261
|
-
for (const [name, column] of Object.entries(table.columns)) {
|
|
262
|
-
columns[name] = columnToJSON(column);
|
|
263
|
-
}
|
|
264
|
-
const out = {
|
|
265
|
-
name: table.name,
|
|
266
|
-
schema: schemaName,
|
|
267
|
-
columns,
|
|
268
|
-
// Read, not re-derived. `defineSchema` already resolves the fail-closed
|
|
269
|
-
// default (RLS on unless the author wrote `rls: false`, and forced on by any
|
|
270
|
-
// policy), and a second copy of a SECURITY default is exactly the thing that
|
|
271
|
-
// drifts — the direction it drifted last time was "expose everything", and
|
|
272
|
-
// the live proof was one user reading another's rows.
|
|
273
|
-
rls: table.rls,
|
|
274
|
-
policies: (table.policies ?? []).map(policyToJSON)
|
|
275
|
-
};
|
|
276
|
-
if (table.primaryKey !== void 0 && table.primaryKey.length > 0) {
|
|
277
|
-
out.primaryKey = [
|
|
278
|
-
...table.primaryKey
|
|
279
|
-
];
|
|
280
|
-
}
|
|
281
|
-
if (table.unique !== void 0 && table.unique.length > 0) {
|
|
282
|
-
out.uniqueConstraints = table.unique.map((u) => ({
|
|
283
|
-
name: u.name,
|
|
284
|
-
columns: [
|
|
285
|
-
...u.columns
|
|
286
|
-
]
|
|
287
|
-
}));
|
|
288
|
-
}
|
|
289
|
-
if (table.raw !== void 0 && table.raw.length > 0) {
|
|
290
|
-
out.rawConstraints = table.raw.map((r) => ({
|
|
291
|
-
name: r.name,
|
|
292
|
-
up: r.up,
|
|
293
|
-
down: r.down ?? null
|
|
294
|
-
}));
|
|
295
|
-
}
|
|
296
|
-
if (table.checks !== void 0 && table.checks.length > 0) {
|
|
297
|
-
out.checks = table.checks.map((c) => ({
|
|
298
|
-
name: c.name,
|
|
299
|
-
expr: c.expr
|
|
300
|
-
}));
|
|
301
|
-
}
|
|
302
|
-
if (table.indexes !== void 0 && table.indexes.length > 0) {
|
|
303
|
-
out.indexes = table.indexes.map((i) => {
|
|
304
|
-
const ix = {
|
|
305
|
-
name: i.name,
|
|
306
|
-
columns: i.columns ? [
|
|
307
|
-
...i.columns
|
|
308
|
-
] : []
|
|
309
|
-
};
|
|
310
|
-
if (i.where !== void 0) ix.where = i.where;
|
|
311
|
-
if (i.expression !== void 0) ix.expression = i.expression;
|
|
312
|
-
if (i.sort !== void 0) ix.sort = i.sort;
|
|
313
|
-
if (i.nulls !== void 0) ix.nulls = i.nulls;
|
|
314
|
-
if (i.include !== void 0) ix.include = [
|
|
315
|
-
...i.include
|
|
316
|
-
];
|
|
317
|
-
return ix;
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
if (table.appendOnly === true) out.appendOnly = true;
|
|
321
|
-
if (table.search !== void 0) {
|
|
322
|
-
const vectorColumn = Object.entries(columns).find(([, c]) => c.dimensions !== void 0)?.[0];
|
|
323
|
-
const sj = searchToJSON(table.search, vectorColumn);
|
|
324
|
-
if (sj.text !== void 0 || sj.vector !== void 0) out.search = sj;
|
|
325
|
-
}
|
|
326
|
-
if (table.memory !== void 0) {
|
|
327
|
-
out.memory = memoryToJSON(table.memory);
|
|
328
|
-
}
|
|
329
|
-
return out;
|
|
330
|
-
}
|
|
331
|
-
__name(tableToJSON, "tableToJSON");
|
|
332
|
-
function qualifiedTableKey(schemaName, tableName) {
|
|
333
|
-
return schemaName === "" || schemaName === "public" ? tableName : `${schemaName}.${tableName}`;
|
|
334
|
-
}
|
|
335
|
-
__name(qualifiedTableKey, "qualifiedTableKey");
|
|
336
|
-
function toSchemaJSON(schemas) {
|
|
337
|
-
const tables = {};
|
|
338
|
-
const extensions = [];
|
|
339
|
-
const meta = [];
|
|
340
|
-
const seen = /* @__PURE__ */ new Set();
|
|
341
|
-
for (const schema of schemas) {
|
|
342
|
-
if (seen.has(schema.name)) {
|
|
343
|
-
throw new Error(`two schemas declare the name "${schema.name}" \u2014 schema names must be unique`);
|
|
344
|
-
}
|
|
345
|
-
seen.add(schema.name);
|
|
346
|
-
for (const table of Object.values(schema.tables)) {
|
|
347
|
-
const json = tableToJSON(table, schema.name);
|
|
348
|
-
tables[qualifiedTableKey(schema.name, json.name)] = json;
|
|
349
|
-
}
|
|
350
|
-
extensions.push(...schema.extensions ?? []);
|
|
351
|
-
meta.push({
|
|
352
|
-
name: schema.name,
|
|
353
|
-
exposed: schema.exposed
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
return {
|
|
357
|
-
tables,
|
|
358
|
-
extensions: [
|
|
359
|
-
...new Set(extensions)
|
|
360
|
-
],
|
|
361
|
-
schemas: meta
|
|
362
|
-
};
|
|
363
|
-
}
|
|
364
|
-
__name(toSchemaJSON, "toSchemaJSON");
|
|
365
|
-
|
|
366
|
-
export {
|
|
367
|
-
makeTypedDB,
|
|
368
|
-
col,
|
|
369
|
-
withRetry,
|
|
370
|
-
sqlFragment,
|
|
371
|
-
qualifiedTableKey,
|
|
372
|
-
toSchemaJSON
|
|
373
|
-
};
|
|
374
|
-
//# sourceMappingURL=chunk-SG4UTNOP.js.map
|