@palbase/backend 23.0.0 → 24.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 +695 -61
- package/dist/bin/palbase-backend.cjs.map +1 -1
- package/dist/bin/palbase-backend.js +4 -5
- package/dist/bin/palbase-backend.js.map +1 -1
- package/dist/{chunk-FSGSB42K.js → chunk-7Z6MGMXQ.js} +64 -4
- package/dist/chunk-7Z6MGMXQ.js.map +1 -0
- package/dist/{chunk-OMRTHM4X.js → chunk-H3JAISUY.js} +136 -1
- package/dist/chunk-H3JAISUY.js.map +1 -0
- package/dist/{chunk-REZU6UKT.js → chunk-NXDH6VQJ.js} +549 -42
- package/dist/chunk-NXDH6VQJ.js.map +1 -0
- package/dist/{chunk-W5ODXPY3.js → chunk-P2Q27SGP.js} +32 -3
- package/dist/chunk-P2Q27SGP.js.map +1 -0
- package/dist/{chunk-ZC6Q2BRD.js → chunk-T5IOSOE5.js} +7 -2
- package/dist/chunk-T5IOSOE5.js.map +1 -0
- package/dist/{chunk-HAF67F2H.js → chunk-ZUGY7RGS.js} +86 -3
- package/dist/chunk-ZUGY7RGS.js.map +1 -0
- package/dist/db/index.cjs +115 -3
- package/dist/db/index.cjs.map +1 -1
- package/dist/db/index.d.cts +2 -2
- package/dist/db/index.d.ts +2 -2
- package/dist/db/index.js +2 -2
- package/dist/{endpoint-BavvbW4P.d.ts → endpoint-0_DGBajf.d.ts} +168 -9
- package/dist/{endpoint-i8TTCohk.d.cts → endpoint-CcQ1a36a.d.cts} +168 -9
- package/dist/engine/index.cjs +684 -48
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.cts +4 -4
- package/dist/engine/index.d.ts +4 -4
- package/dist/engine/index.js +4 -4
- package/dist/{index-B3jmmItD.d.ts → index-CJiJU9ux.d.ts} +209 -36
- package/dist/{index-Bmvx1EvJ.d.cts → index-D-4-PNuQ.d.cts} +209 -36
- package/dist/{index-B7YBEG5w.d.ts → index-D17r-MKb.d.ts} +177 -7
- package/dist/{index-E7OscPJT.d.cts → index-DRFxf07H.d.cts} +177 -7
- package/dist/index.cjs +269 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +54 -12
- package/dist/index.d.ts +54 -12
- package/dist/index.js +54 -11
- package/dist/index.js.map +1 -1
- package/dist/openapi/index.cjs +45 -5
- package/dist/openapi/index.cjs.map +1 -1
- package/dist/openapi/index.d.cts +9 -4
- package/dist/openapi/index.d.ts +9 -4
- package/dist/openapi/index.js +35 -11
- package/dist/openapi/index.js.map +1 -1
- package/dist/{registry-C3H2uPeZ.d.cts → registry-1X-skBNu.d.cts} +101 -7
- package/dist/{registry-DY3d9l1k.d.ts → registry-CEod_5sz.d.ts} +101 -7
- package/dist/test/index.cjs +509 -9
- package/dist/test/index.cjs.map +1 -1
- package/dist/test/index.d.cts +35 -3
- package/dist/test/index.d.ts +35 -3
- package/dist/test/index.js +507 -8
- package/dist/test/index.js.map +1 -1
- package/docs/README.md +4 -4
- package/docs/database.md +115 -11
- package/docs/getting-started.md +5 -4
- package/docs/llms-full.txt +385 -89
- package/docs/migrations.md +81 -59
- package/docs/schema.md +82 -2
- package/docs/services.md +98 -9
- package/package.json +3 -2
- package/stager/return_types.js +23 -0
- package/template/AGENTS.md +121 -41
- package/template/controllers/notes.controller.ts +64 -0
- package/template/package.json +1 -1
- package/template/services/note.service.ts +74 -0
- package/template/tsconfig.json +11 -1
- package/dist/chunk-FSGSB42K.js.map +0 -1
- package/dist/chunk-HAF67F2H.js.map +0 -1
- package/dist/chunk-OMRTHM4X.js.map +0 -1
- package/dist/chunk-REZU6UKT.js.map +0 -1
- package/dist/chunk-W5ODXPY3.js.map +0 -1
- package/dist/chunk-Y5HXVUMP.js +0 -90
- package/dist/chunk-Y5HXVUMP.js.map +0 -1
- package/dist/chunk-ZC6Q2BRD.js.map +0 -1
package/dist/db/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { C as ColumnBuilder, a as ColumnDef, b as ColumnMap, c as ColumnType, d as EXTENSION_DEPENDENCIES, e as EmbeddingModelRef, f as EnvServiceDatabase, E as EnvTypedDatabase, I as InsertShape, O as OnDeleteAction, P as PALBASE_EXTENSIONS, i as PalbaseExtension, j as PolicyBuilder, k as PolicyCommand, l as PolicyDef, m as PolicyMode, R as RawConstraintDef, n as RowShape, S as SchemaDef, o as SchemaInput, T as TableDef, p as TableInput, q as TxPlan, r as TxTables, s as TypedDB, t as TypedTable, u as TypedTx, v as bigint, w as boolean, x as defineSchema, y as enumType, z as integer, A as isPalbaseExtension, B as jsonb, D as makeTypedDB, G as openai, H as policy, J as raw, K as text, L as timestamp, M as uuid, N as vector } from '../index-
|
|
2
|
-
export { M as Materialized, b1 as Ref, b3 as TxColumnExpr, b4 as TxInsertShape, b6 as TxNow, T as TxPlanBody, b7 as TxPlanError, b8 as TxPlanHandle, b9 as TxPlanOpResult, ba as TxPlanRejection,
|
|
1
|
+
export { C as ColumnBuilder, a as ColumnDef, b as ColumnMap, c as ColumnType, d as EXTENSION_DEPENDENCIES, e as EmbeddingModelRef, f as EnvServiceDatabase, E as EnvTypedDatabase, I as InsertShape, O as OnDeleteAction, P as PALBASE_EXTENSIONS, i as PalbaseExtension, j as PolicyBuilder, k as PolicyCommand, l as PolicyDef, m as PolicyMode, R as RawConstraintDef, n as RowShape, S as SchemaDef, o as SchemaInput, T as TableDef, p as TableInput, q as TxPlan, r as TxTables, s as TypedDB, t as TypedTable, u as TypedTx, v as bigint, w as boolean, x as defineSchema, y as enumType, z as integer, A as isPalbaseExtension, B as jsonb, D as makeTypedDB, G as openai, H as policy, J as raw, K as text, L as timestamp, M as uuid, N as vector } from '../index-D-4-PNuQ.cjs';
|
|
2
|
+
export { M as Materialized, b1 as Ref, b3 as TxColumnExpr, b4 as TxInsertShape, b6 as TxNow, T as TxPlanBody, b7 as TxPlanError, b8 as TxPlanHandle, b9 as TxPlanOpResult, ba as TxPlanRejection, g as TxPlanResponse, bb as TxRefError, bc as TxRow, bd as TxRows, be as TxSelectOptions, bf as TxSetShape, bh as TxTable, bi as TxWhere, bs as dec, bu as inc, bv as now } from '../endpoint-CcQ1a36a.cjs';
|
|
3
3
|
import './env.cjs';
|
|
4
4
|
import '../stack.cjs';
|
|
5
5
|
import 'zod';
|
package/dist/db/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { C as ColumnBuilder, a as ColumnDef, b as ColumnMap, c as ColumnType, d as EXTENSION_DEPENDENCIES, e as EmbeddingModelRef, f as EnvServiceDatabase, E as EnvTypedDatabase, I as InsertShape, O as OnDeleteAction, P as PALBASE_EXTENSIONS, i as PalbaseExtension, j as PolicyBuilder, k as PolicyCommand, l as PolicyDef, m as PolicyMode, R as RawConstraintDef, n as RowShape, S as SchemaDef, o as SchemaInput, T as TableDef, p as TableInput, q as TxPlan, r as TxTables, s as TypedDB, t as TypedTable, u as TypedTx, v as bigint, w as boolean, x as defineSchema, y as enumType, z as integer, A as isPalbaseExtension, B as jsonb, D as makeTypedDB, G as openai, H as policy, J as raw, K as text, L as timestamp, M as uuid, N as vector } from '../index-
|
|
2
|
-
export { M as Materialized, b1 as Ref, b3 as TxColumnExpr, b4 as TxInsertShape, b6 as TxNow, T as TxPlanBody, b7 as TxPlanError, b8 as TxPlanHandle, b9 as TxPlanOpResult, ba as TxPlanRejection,
|
|
1
|
+
export { C as ColumnBuilder, a as ColumnDef, b as ColumnMap, c as ColumnType, d as EXTENSION_DEPENDENCIES, e as EmbeddingModelRef, f as EnvServiceDatabase, E as EnvTypedDatabase, I as InsertShape, O as OnDeleteAction, P as PALBASE_EXTENSIONS, i as PalbaseExtension, j as PolicyBuilder, k as PolicyCommand, l as PolicyDef, m as PolicyMode, R as RawConstraintDef, n as RowShape, S as SchemaDef, o as SchemaInput, T as TableDef, p as TableInput, q as TxPlan, r as TxTables, s as TypedDB, t as TypedTable, u as TypedTx, v as bigint, w as boolean, x as defineSchema, y as enumType, z as integer, A as isPalbaseExtension, B as jsonb, D as makeTypedDB, G as openai, H as policy, J as raw, K as text, L as timestamp, M as uuid, N as vector } from '../index-CJiJU9ux.js';
|
|
2
|
+
export { M as Materialized, b1 as Ref, b3 as TxColumnExpr, b4 as TxInsertShape, b6 as TxNow, T as TxPlanBody, b7 as TxPlanError, b8 as TxPlanHandle, b9 as TxPlanOpResult, ba as TxPlanRejection, g as TxPlanResponse, bb as TxRefError, bc as TxRow, bd as TxRows, be as TxSelectOptions, bf as TxSetShape, bh as TxTable, bi as TxWhere, bs as dec, bu as inc, bv as now } from '../endpoint-0_DGBajf.js';
|
|
3
3
|
import './env.js';
|
|
4
4
|
import '../stack.js';
|
|
5
5
|
import 'zod';
|
package/dist/db/index.js
CHANGED
|
@@ -17,14 +17,14 @@ import {
|
|
|
17
17
|
timestamp,
|
|
18
18
|
uuid,
|
|
19
19
|
vector
|
|
20
|
-
} from "../chunk-
|
|
20
|
+
} from "../chunk-ZUGY7RGS.js";
|
|
21
21
|
import {
|
|
22
22
|
TxPlanError,
|
|
23
23
|
TxRefError,
|
|
24
24
|
dec,
|
|
25
25
|
inc,
|
|
26
26
|
now
|
|
27
|
-
} from "../chunk-
|
|
27
|
+
} from "../chunk-P2Q27SGP.js";
|
|
28
28
|
import "../chunk-7D4SUZUM.js";
|
|
29
29
|
export {
|
|
30
30
|
EXTENSION_DEPENDENCIES,
|
|
@@ -142,7 +142,7 @@ declare function defineMiddleware(fn: MiddlewareHandler): MiddlewareHandler;
|
|
|
142
142
|
* # Wire contract
|
|
143
143
|
*
|
|
144
144
|
* The JSON this file emits is consumed by
|
|
145
|
-
* `
|
|
145
|
+
* the plan executor in `engine/db.ts`. That executor rejects
|
|
146
146
|
* unknown fields at every level, so an op carries EXACTLY the fields its kind
|
|
147
147
|
* takes. Everything here that looks like a needless restriction is one of the
|
|
148
148
|
* server's rules made visible early:
|
|
@@ -206,7 +206,12 @@ interface TxWireGuard {
|
|
|
206
206
|
/** One operation in the wire plan. Fields are omitted, never null: the decoder
|
|
207
207
|
* rejects a field that does not belong to the op's kind. */
|
|
208
208
|
interface TxWireOp {
|
|
209
|
-
|
|
209
|
+
/** upsert and insertMany: the columns Postgres matches on. */
|
|
210
|
+
onConflict?: readonly string[];
|
|
211
|
+
/** insertMany only: what a collision does. Absent means no ON CONFLICT clause
|
|
212
|
+
* at all, which is what every insertMany did before this option existed. */
|
|
213
|
+
action?: "ignore" | "update";
|
|
214
|
+
op: "insert" | "insertMany" | "upsert" | "update" | "delete" | "select";
|
|
210
215
|
table: string;
|
|
211
216
|
values?: Record<string, TxWireValue>;
|
|
212
217
|
rows?: Record<string, TxWireValue>[];
|
|
@@ -387,7 +392,36 @@ interface TxTable<Row, Insert> {
|
|
|
387
392
|
*
|
|
388
393
|
* An empty list writes nothing and sends nothing.
|
|
389
394
|
*/
|
|
390
|
-
|
|
395
|
+
/**
|
|
396
|
+
* Insert many rows in ONE statement, optionally choosing what a collision does.
|
|
397
|
+
*
|
|
398
|
+
* Without `opts` this is a plain multi-row INSERT and a collision aborts the
|
|
399
|
+
* transaction — the behaviour every call had before the option existed.
|
|
400
|
+
*
|
|
401
|
+
* `action: "ignore"` emits `ON CONFLICT DO NOTHING`, which is how "insert the
|
|
402
|
+
* ones that are new" becomes one round-trip instead of one per row with a
|
|
403
|
+
* 23505 caught around each. **The returned rows are the ones actually
|
|
404
|
+
* INSERTED**: a row that collided is skipped, so it is absent from the result
|
|
405
|
+
* — Postgres does not return what it did not write.
|
|
406
|
+
*
|
|
407
|
+
* `action: "update"` emits `ON CONFLICT DO UPDATE`, setting every non-conflict
|
|
408
|
+
* column from the incoming row, and every row comes back.
|
|
409
|
+
*/
|
|
410
|
+
insertMany(rows: readonly TxInsertShape<Insert>[], opts?: {
|
|
411
|
+
onConflict: readonly Extract<keyof Row, string>[];
|
|
412
|
+
action?: "ignore" | "update";
|
|
413
|
+
}): TxRows<Row>;
|
|
414
|
+
/**
|
|
415
|
+
* Insert the row, or update it when it collides on `onConflict` — inside the
|
|
416
|
+
* plan's savepoint, with the same meaning `tables.<t>.upsert()` has outside it.
|
|
417
|
+
*
|
|
418
|
+
* It is an operation because the alternative is not writable here: a failed
|
|
419
|
+
* insert aborts the whole transaction, so "try, then fall back" cannot be two
|
|
420
|
+
* plan steps.
|
|
421
|
+
*/
|
|
422
|
+
upsert(values: TxInsertShape<Insert>, options: {
|
|
423
|
+
onConflict: readonly Extract<keyof Row, string>[];
|
|
424
|
+
}): TxRows<Row>;
|
|
391
425
|
/**
|
|
392
426
|
* Update every row matching `where`. The filter comes first because it is the
|
|
393
427
|
* dangerous half: an update whose `where` you got wrong rewrites rows you
|
|
@@ -512,6 +546,57 @@ declare class NotFound extends NamedHttpError {
|
|
|
512
546
|
declare class Conflict extends NamedHttpError {
|
|
513
547
|
constructor(message?: string, code?: string, data?: unknown);
|
|
514
548
|
}
|
|
549
|
+
/**
|
|
550
|
+
* 409 — a write was refused because it would duplicate an existing row.
|
|
551
|
+
* Carries the NAME of the unique constraint Postgres named (`users_email_key`).
|
|
552
|
+
*
|
|
553
|
+
* The engine produces it: a statement rejected with SQLSTATE `23505` is
|
|
554
|
+
* converted here rather than surfacing as an opaque driver error (see
|
|
555
|
+
* `engine/db.ts`, `diagnosingDriver`). What that removes is the string match —
|
|
556
|
+
* before this, the only way to act on a duplicate was to test the driver
|
|
557
|
+
* message for "duplicate key value violates unique constraint", a contract
|
|
558
|
+
* nobody signed that breaks on a Postgres upgrade, a locale, or a constraint
|
|
559
|
+
* rename, silently and in production.
|
|
560
|
+
*
|
|
561
|
+
* THE NAME IS A FIELD AND STAYS OUT OF THE DEFAULT MESSAGE. The two are not
|
|
562
|
+
* the same audience. `constraint` is read by the code that catches this — the
|
|
563
|
+
* developer, who already knows the schema. `errorDescription` is the HTTP
|
|
564
|
+
* response body, and an UNCAUGHT duplicate puts it in front of the
|
|
565
|
+
* application's end user: `users_email_key` there discloses how the schema is
|
|
566
|
+
* built to whoever sent the request. The platform's own data API took the same
|
|
567
|
+
* decision one surface over and wrote down why —
|
|
568
|
+
* `v2/internal/modules/database/internal/handler/pgerror.go:83-87` collapses
|
|
569
|
+
* every 23xxx to a generic conflict, "never disclose the constraint/column
|
|
570
|
+
* name". A thrower who WANTS the name on the wire passes it deliberately
|
|
571
|
+
* (`new UniqueViolation(c, \`\${c} already exists\`)`, or through `data`).
|
|
572
|
+
*
|
|
573
|
+
* @example
|
|
574
|
+
* try {
|
|
575
|
+
* await Database.tables.users.insert({ email });
|
|
576
|
+
* } catch (e) {
|
|
577
|
+
* if (UniqueViolation.is(e) && e.constraint === "users_email_key") {
|
|
578
|
+
* throw new Conflict("That email is taken", "email_taken");
|
|
579
|
+
* }
|
|
580
|
+
* throw e;
|
|
581
|
+
* }
|
|
582
|
+
*/
|
|
583
|
+
declare class UniqueViolation extends Conflict {
|
|
584
|
+
/**
|
|
585
|
+
* Whether `e` is a unique violation — REGARDLESS of which copy of this SDK
|
|
586
|
+
* constructed it.
|
|
587
|
+
*
|
|
588
|
+
* Use this instead of `instanceof`. Measured on a live stack: a controller
|
|
589
|
+
* bundle INLINES its own copy of `@palbase/backend`, and the engine that
|
|
590
|
+
* raises this error is the runtime's copy. Two copies, two class identities,
|
|
591
|
+
* and `e instanceof UniqueViolation` is false in the one place a caller
|
|
592
|
+
* writes it — a check that reads as correct and silently never matches.
|
|
593
|
+
*/
|
|
594
|
+
static is(e: unknown): e is UniqueViolation;
|
|
595
|
+
/** The unique constraint the statement violated, as Postgres named it.
|
|
596
|
+
* `""` when the driver did not say which — see `engine/db.ts`. */
|
|
597
|
+
readonly constraint: string;
|
|
598
|
+
constructor(constraint: string, message?: string, code?: string, data?: unknown);
|
|
599
|
+
}
|
|
515
600
|
/** A single field-level validation failure carried by {@link BadRequest}. */
|
|
516
601
|
interface FieldError {
|
|
517
602
|
/** The offending field's name (dotted path for nested fields). */
|
|
@@ -1546,6 +1631,13 @@ interface PalbaseFlagsClient {
|
|
|
1546
1631
|
/**
|
|
1547
1632
|
* Realtime broadcast surface (backend handler → subscribed clients).
|
|
1548
1633
|
*
|
|
1634
|
+
* **Every channel must be DECLARED, or the join is refused.** Channel names are
|
|
1635
|
+
* not free text: `channels.ts` at the project root publishes which names exist
|
|
1636
|
+
* and who may subscribe, publish, or write state, and a client joining a name no
|
|
1637
|
+
* declaration matches is rejected without ever reaching your code. Declare with
|
|
1638
|
+
* `ownerOnly()`, `publicChannel()`, or a custom `authorize(ctx)` — see
|
|
1639
|
+
* {@link defineChannels}. Broadcasting to an undeclared channel reaches nobody.
|
|
1640
|
+
*
|
|
1549
1641
|
* Backend-side this is BROADCAST-ONLY: a handler pushes an event to a channel
|
|
1550
1642
|
* and every client subscribed to that channel (via the client SDK's
|
|
1551
1643
|
* `pb.realtime.channel(...).on(...)`) receives it. There is no `subscribe()` on
|
|
@@ -1554,9 +1646,10 @@ interface PalbaseFlagsClient {
|
|
|
1554
1646
|
* once the broadcast is accepted (or with an `error` if it could not be sent),
|
|
1555
1647
|
* but it never blocks the handler waiting on subscribers.
|
|
1556
1648
|
*
|
|
1557
|
-
* Channel
|
|
1558
|
-
*
|
|
1559
|
-
*
|
|
1649
|
+
* Channel names are yours to choose (e.g. `"room:42"`, `"orders"`) but not yours
|
|
1650
|
+
* to leave undeclared: each must match a pattern in `channels.ts`, which is where
|
|
1651
|
+
* `"room:{roomId}"` is authorized. The Palbase-managed `flags:<ref>` channels are
|
|
1652
|
+
* internal — author channels for your own features.
|
|
1560
1653
|
*
|
|
1561
1654
|
* @example
|
|
1562
1655
|
* // Notify everyone in a chat room that a message landed:
|
|
@@ -1816,9 +1909,36 @@ interface RateLimitConfig {
|
|
|
1816
1909
|
/** The six raw string-keyed DB operations shared by `DBClient` and the
|
|
1817
1910
|
* transaction-scoped client. */
|
|
1818
1911
|
interface DBOps {
|
|
1819
|
-
/**
|
|
1912
|
+
/**
|
|
1913
|
+
* Run SQL on the REQUEST'S OWN transaction.
|
|
1914
|
+
*
|
|
1915
|
+
* This is **not** read-only. Nothing marks that transaction `READ ONLY`, so a
|
|
1916
|
+
* write passed here executes and commits with the request — a plain `UPDATE`, a
|
|
1917
|
+
* write hidden in a CTE, or a function that writes. What stands between a
|
|
1918
|
+
* statement and your data is RLS and the role the request runs as, exactly as
|
|
1919
|
+
* for every other operation on this client.
|
|
1920
|
+
*
|
|
1921
|
+
* `INSERT … ON CONFLICT DO UPDATE` therefore works here; `tables.<t>.upsert()`
|
|
1922
|
+
* is the same thing with types. Array parameters are encoded as Postgres array
|
|
1923
|
+
* literals, so `= ANY($1::uuid[])` takes a plain JS array.
|
|
1924
|
+
*
|
|
1925
|
+
* This comment used to claim a `READ ONLY` transaction. It was wrong, and the
|
|
1926
|
+
* cost was measured: a tenant read it, concluded an upsert was impossible from
|
|
1927
|
+
* here, abandoned `ON CONFLICT` and wrote a database trigger instead.
|
|
1928
|
+
*/
|
|
1820
1929
|
query(sql: string, params?: unknown[]): Promise<Record<string, unknown>[]>;
|
|
1821
1930
|
insert(table: string, data: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
1931
|
+
/**
|
|
1932
|
+
* Insert the row, or update it when it collides on `onConflict` — one
|
|
1933
|
+
* statement, so two concurrent callers cannot both lose.
|
|
1934
|
+
*
|
|
1935
|
+
* Read-then-write cannot be made safe here by catching the unique violation: a
|
|
1936
|
+
* request runs in one transaction, so the failed insert aborts it and every
|
|
1937
|
+
* later statement answers `current transaction is aborted`.
|
|
1938
|
+
*/
|
|
1939
|
+
upsert(table: string, data: Record<string, unknown>, opts: {
|
|
1940
|
+
onConflict: readonly string[];
|
|
1941
|
+
}): Promise<Record<string, unknown>>;
|
|
1822
1942
|
/**
|
|
1823
1943
|
* Update the row with the given id and resolve to the updated row, or `null`
|
|
1824
1944
|
* if no row matched (the id is absent, or the row is hidden by RLS). This is
|
|
@@ -1862,7 +1982,26 @@ interface DBOps {
|
|
|
1862
1982
|
/** Validity'li tabloda satırın yeni versiyonu — eski kapanır (valid_to/superseded_by),
|
|
1863
1983
|
* yenisi eklenir; TEK savepoint, dönüş yeni satır (FR-029, C-9). */
|
|
1864
1984
|
supersede(table: string, id: string, row: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
1865
|
-
|
|
1985
|
+
/** Filtre + sıralama + sayfa. `offset` yalnız `limit` ile birlikte geçerlidir
|
|
1986
|
+
* (limitsiz offset sayfa değildir; motor adıyla reddeder — FR-004). */
|
|
1987
|
+
/** Update every row the filter matches, in one statement; resolves to them.
|
|
1988
|
+
* An EMPTY filter is refused — a whole-table write is not something to reach
|
|
1989
|
+
* by accident. */
|
|
1990
|
+
updateMany(table: string, where: Record<string, unknown>, set: Record<string, unknown>): Promise<Record<string, unknown>[]>;
|
|
1991
|
+
/** Delete every row the filter matches; resolves to how many. Empty filter
|
|
1992
|
+
* refused, for the same reason and more so. */
|
|
1993
|
+
deleteMany(table: string, where: Record<string, unknown>): Promise<number>;
|
|
1994
|
+
/** How many rows match — the half of pagination limit/offset cannot supply.
|
|
1995
|
+
* An empty filter is legitimate here: counting is a read. */
|
|
1996
|
+
count(table: string, where?: Record<string, unknown>): Promise<number>;
|
|
1997
|
+
findMany(table: string, query?: Record<string, unknown>, opts?: {
|
|
1998
|
+
orderBy?: {
|
|
1999
|
+
column: string;
|
|
2000
|
+
direction?: "asc" | "desc";
|
|
2001
|
+
};
|
|
2002
|
+
limit?: number;
|
|
2003
|
+
offset?: number;
|
|
2004
|
+
}): Promise<Record<string, unknown>[]>;
|
|
1866
2005
|
/** "Bu satıra benzer satırlar" (FR-022) — satır-modunda kolon vektörüyle,
|
|
1867
2006
|
* chunk-modunda chunk-ortalamasıyla; kendisi hariç. */
|
|
1868
2007
|
similar(table: string, id: string, opts?: {
|
|
@@ -1878,6 +2017,18 @@ interface DBOps {
|
|
|
1878
2017
|
weight: number;
|
|
1879
2018
|
};
|
|
1880
2019
|
}): Promise<Record<string, unknown>[]>;
|
|
2020
|
+
/** D-021 (FR-027): kolon sayaçları bağımsız dönüşle — search'ün dizi-üstü
|
|
2021
|
+
* `_facets` özelliği serileşmede kaybolur; ciddi sözleşme budur. */
|
|
2022
|
+
facets(table: string, params: {
|
|
2023
|
+
facets: string[];
|
|
2024
|
+
where?: Record<string, unknown>;
|
|
2025
|
+
validity?: "all" | {
|
|
2026
|
+
asOf: string;
|
|
2027
|
+
};
|
|
2028
|
+
}): Promise<Record<string, {
|
|
2029
|
+
value: string | null;
|
|
2030
|
+
count: number;
|
|
2031
|
+
}[]>>;
|
|
1881
2032
|
/** Çok-örnekli öneri (FR-023): avg(pos) + (avg(pos) − avg(neg)); positive'ler sonuç dışı. */
|
|
1882
2033
|
recommend(table: string, opts: {
|
|
1883
2034
|
positive: string[];
|
|
@@ -1913,6 +2064,14 @@ interface DBClient extends DBOps {
|
|
|
1913
2064
|
* `.expectOne(…)`; without it a declared expectation degrades to a generic 409.
|
|
1914
2065
|
*/
|
|
1915
2066
|
txPlan(plan: TxPlanBody): Promise<TxPlanResponse>;
|
|
2067
|
+
/**
|
|
2068
|
+
* Run `fn` inside a SAVEPOINT on this request's transaction, so a failure in
|
|
2069
|
+
* it rolls back only what `fn`'s handle wrote.
|
|
2070
|
+
*
|
|
2071
|
+
* The handle is a PARAMETER on purpose: an ambient swap would capture writes
|
|
2072
|
+
* a concurrent `Promise.all` branch made outside the boundary.
|
|
2073
|
+
*/
|
|
2074
|
+
attempt<T>(fn: (tx: DBOps) => Promise<T>): Promise<T>;
|
|
1916
2075
|
/**
|
|
1917
2076
|
* Return a sibling DB client that bypasses Row-Level Security by running as
|
|
1918
2077
|
* the `service_role` (BYPASSRLS). Use sparingly and explicitly — the default
|
|
@@ -2213,4 +2372,4 @@ type Middleware = (ctx: MiddlewareContext, next: () => Promise<void>) => Promise
|
|
|
2213
2372
|
*/
|
|
2214
2373
|
type AuthSpec = boolean | Partial<AuthConfig>;
|
|
2215
2374
|
|
|
2216
|
-
export { type PalbaseCreateLinkParams as $, type AuthSpec as A, BadRequest as B, type CacheClient as C, type DBClient as D, type ErrorDef as E, type FileContext as F, type PalbaseAttestiOSParams as G, HttpError as H, type PalbaseAttestiOSResult as I, type PalbaseAuthClient as J, type PalbaseBatchOverrideOperation as K, type Logger as L, type Materialized as M, NotFound as N, type PalbaseBatchSetOverridesResult as O, type PalbaseDocsClient as P, type PalbaseBindDeviceParams as Q, type RateLimitConfig as R, type SecretsService as S, type TxPlanBody as T, type PalbaseClearAllOverridesResult as U, type PalbaseClearOverrideResult as V, type PalbaseCohortQueryInput as W, type PalbaseCohortResult as X, type PalbaseCollectionRef as Y, type PalbaseCountQueryInput as Z, type PalbaseCountResult as _, type PalbaseFlagsClient as a, type PalbaseVerifyRequestSignatureParams as a$, type PalbaseDeviceInfo as a0, type PalbaseDeviceTokenView as a1, type PalbaseDocumentRef as a2, type PalbaseDocumentSnapshot as a3, type PalbaseEmailClient as a4, type PalbaseEmailSendParams as a5, type PalbaseEmailSendResponse as a6, type PalbaseEventNamesResult as a7, type PalbaseEventsQueryInput as a8, type PalbaseEventsResult as a9, type PalbaseMatchParams as aA, type PalbaseMultiChannelResponse as aB, type PalbaseOverviewResult as aC, type PalbasePreferences as aD, type PalbasePreferencesClient as aE, type PalbasePushClient as aF, type PalbasePushSendParams as aG, type PalbasePushSendResponse as aH, type PalbaseQrCodeOptions as aI, type PalbaseQuerySnapshot as aJ, type PalbaseRegisterDeviceParams as aK, type PalbaseRetentionQueryInput as aL, type PalbaseRetentionResult as aM, type PalbaseSession as aN, type PalbaseSetOverrideResult as aO, type PalbaseSetOverridesResult as aP, type PalbaseSignedUrlResponse as aQ, type PalbaseSmsClient as aR, type PalbaseSmsSendParams as aS, type PalbaseSmsSendResponse as aT, type PalbaseTransformOptions as aU, type PalbaseUpdateLinkParams as aV, type PalbaseUploadOptions as aW, type PalbaseUser as aX, type PalbaseUserDetailResult as aY, type PalbaseUsersQueryInput as aZ, type PalbaseUsersResult as a_, type PalbaseFileObject as aa, type PalbaseFlag as ab, type PalbaseFlagContext as ac, type PalbaseFlagSource as ad, type PalbaseFlagValue as ae, type PalbaseFlagVariant as af, type PalbaseFlagsServiceClient as ag, type PalbaseFunctionsClient as ah, type PalbaseFunnelQueryInput as ai, type PalbaseFunnelResult as aj, type PalbaseIdentifyTraits as ak, type PalbaseInboxClient as al, type PalbaseInboxListOptions as am, type PalbaseInboxListResult as an, type PalbaseInboxMessage as ao, type PalbaseInboxSendParams as ap, type PalbaseInboxSendResponse as aq, type PalbaseInitialLink as ar, type PalbaseInvokeOptions as as, type PalbaseLink as at, type PalbaseLinkAnalytics as au, type PalbaseLinkDetails as av, type PalbaseLinksClient as aw, type PalbaseListLinksOptions as ax, type PalbaseListLinksResult as ay, type PalbaseListOptions as az, type PalbaseNotificationsClient as b, type PalbaseWhereOperator as b0, type Ref as b1, TooManyRequests as b2, type TxColumnExpr as b3, type TxInsertShape as b4, type TxInsertValue as b5, type TxNow as b6, TxPlanError as b7, type TxPlanHandle as b8, type TxPlanOpResult as b9, type TxPlanRejection as ba, TxRefError as bb, type TxRow as bc, type TxRows as bd, type TxSelectOptions as be, type TxSetShape as bf, type TxSetValue as bg, type TxTable as bh, type TxWhere as bi, type TxWireExpr as bj, type TxWireGuard as bk, type TxWireOp as bl, type TxWireRef as bm, type TxWireValue as bn, Unauthorized as bo, type User as
|
|
2375
|
+
export { type PalbaseCreateLinkParams as $, type AuthSpec as A, BadRequest as B, type CacheClient as C, type DBClient as D, type ErrorDef as E, type FileContext as F, type PalbaseAttestiOSParams as G, HttpError as H, type PalbaseAttestiOSResult as I, type PalbaseAuthClient as J, type PalbaseBatchOverrideOperation as K, type Logger as L, type Materialized as M, NotFound as N, type PalbaseBatchSetOverridesResult as O, type PalbaseDocsClient as P, type PalbaseBindDeviceParams as Q, type RateLimitConfig as R, type SecretsService as S, type TxPlanBody as T, type PalbaseClearAllOverridesResult as U, type PalbaseClearOverrideResult as V, type PalbaseCohortQueryInput as W, type PalbaseCohortResult as X, type PalbaseCollectionRef as Y, type PalbaseCountQueryInput as Z, type PalbaseCountResult as _, type PalbaseFlagsClient as a, type PalbaseVerifyRequestSignatureParams as a$, type PalbaseDeviceInfo as a0, type PalbaseDeviceTokenView as a1, type PalbaseDocumentRef as a2, type PalbaseDocumentSnapshot as a3, type PalbaseEmailClient as a4, type PalbaseEmailSendParams as a5, type PalbaseEmailSendResponse as a6, type PalbaseEventNamesResult as a7, type PalbaseEventsQueryInput as a8, type PalbaseEventsResult as a9, type PalbaseMatchParams as aA, type PalbaseMultiChannelResponse as aB, type PalbaseOverviewResult as aC, type PalbasePreferences as aD, type PalbasePreferencesClient as aE, type PalbasePushClient as aF, type PalbasePushSendParams as aG, type PalbasePushSendResponse as aH, type PalbaseQrCodeOptions as aI, type PalbaseQuerySnapshot as aJ, type PalbaseRegisterDeviceParams as aK, type PalbaseRetentionQueryInput as aL, type PalbaseRetentionResult as aM, type PalbaseSession as aN, type PalbaseSetOverrideResult as aO, type PalbaseSetOverridesResult as aP, type PalbaseSignedUrlResponse as aQ, type PalbaseSmsClient as aR, type PalbaseSmsSendParams as aS, type PalbaseSmsSendResponse as aT, type PalbaseTransformOptions as aU, type PalbaseUpdateLinkParams as aV, type PalbaseUploadOptions as aW, type PalbaseUser as aX, type PalbaseUserDetailResult as aY, type PalbaseUsersQueryInput as aZ, type PalbaseUsersResult as a_, type PalbaseFileObject as aa, type PalbaseFlag as ab, type PalbaseFlagContext as ac, type PalbaseFlagSource as ad, type PalbaseFlagValue as ae, type PalbaseFlagVariant as af, type PalbaseFlagsServiceClient as ag, type PalbaseFunctionsClient as ah, type PalbaseFunnelQueryInput as ai, type PalbaseFunnelResult as aj, type PalbaseIdentifyTraits as ak, type PalbaseInboxClient as al, type PalbaseInboxListOptions as am, type PalbaseInboxListResult as an, type PalbaseInboxMessage as ao, type PalbaseInboxSendParams as ap, type PalbaseInboxSendResponse as aq, type PalbaseInitialLink as ar, type PalbaseInvokeOptions as as, type PalbaseLink as at, type PalbaseLinkAnalytics as au, type PalbaseLinkDetails as av, type PalbaseLinksClient as aw, type PalbaseListLinksOptions as ax, type PalbaseListLinksResult as ay, type PalbaseListOptions as az, type PalbaseNotificationsClient as b, type PalbaseWhereOperator as b0, type Ref as b1, TooManyRequests as b2, type TxColumnExpr as b3, type TxInsertShape as b4, type TxInsertValue as b5, type TxNow as b6, TxPlanError as b7, type TxPlanHandle as b8, type TxPlanOpResult as b9, type TxPlanRejection as ba, TxRefError as bb, type TxRow as bc, type TxRows as bd, type TxSelectOptions as be, type TxSetShape as bf, type TxSetValue as bg, type TxTable as bh, type TxWhere as bi, type TxWireExpr as bj, type TxWireGuard as bk, type TxWireOp as bl, type TxWireRef as bm, type TxWireValue as bn, Unauthorized as bo, UniqueViolation as bp, type User as bq, type VerifiedDevice as br, dec as bs, defineMiddleware as bt, inc as bu, now as bv, type PalbaseRealtimeClient as c, type PalbaseStorageClient as d, type PalbaseBucketClient as e, type DBOps as f, type TxPlanResponse as g, type PalbaseResult as h, type AuthConfig as i, type ClientInfo as j, Conflict as k, type ErrorMap as l, type ErrorThrowers as m, Forbidden as n, type HttpMethod as o, type Middleware as p, type MiddlewareContext as q, type MiddlewareHandler as r, type PBRequest as s, PalError as t, type PalbaseAnalyticsClient as u, type PalbaseAnalyticsManagementNamespace as v, type PalbaseAnalyticsProperties as w, type PalbaseAnalyticsQueryNamespace as x, type PalbaseAttestAndroidParams as y, type PalbaseAttestAndroidResult as z };
|
|
@@ -142,7 +142,7 @@ declare function defineMiddleware(fn: MiddlewareHandler): MiddlewareHandler;
|
|
|
142
142
|
* # Wire contract
|
|
143
143
|
*
|
|
144
144
|
* The JSON this file emits is consumed by
|
|
145
|
-
* `
|
|
145
|
+
* the plan executor in `engine/db.ts`. That executor rejects
|
|
146
146
|
* unknown fields at every level, so an op carries EXACTLY the fields its kind
|
|
147
147
|
* takes. Everything here that looks like a needless restriction is one of the
|
|
148
148
|
* server's rules made visible early:
|
|
@@ -206,7 +206,12 @@ interface TxWireGuard {
|
|
|
206
206
|
/** One operation in the wire plan. Fields are omitted, never null: the decoder
|
|
207
207
|
* rejects a field that does not belong to the op's kind. */
|
|
208
208
|
interface TxWireOp {
|
|
209
|
-
|
|
209
|
+
/** upsert and insertMany: the columns Postgres matches on. */
|
|
210
|
+
onConflict?: readonly string[];
|
|
211
|
+
/** insertMany only: what a collision does. Absent means no ON CONFLICT clause
|
|
212
|
+
* at all, which is what every insertMany did before this option existed. */
|
|
213
|
+
action?: "ignore" | "update";
|
|
214
|
+
op: "insert" | "insertMany" | "upsert" | "update" | "delete" | "select";
|
|
210
215
|
table: string;
|
|
211
216
|
values?: Record<string, TxWireValue>;
|
|
212
217
|
rows?: Record<string, TxWireValue>[];
|
|
@@ -387,7 +392,36 @@ interface TxTable<Row, Insert> {
|
|
|
387
392
|
*
|
|
388
393
|
* An empty list writes nothing and sends nothing.
|
|
389
394
|
*/
|
|
390
|
-
|
|
395
|
+
/**
|
|
396
|
+
* Insert many rows in ONE statement, optionally choosing what a collision does.
|
|
397
|
+
*
|
|
398
|
+
* Without `opts` this is a plain multi-row INSERT and a collision aborts the
|
|
399
|
+
* transaction — the behaviour every call had before the option existed.
|
|
400
|
+
*
|
|
401
|
+
* `action: "ignore"` emits `ON CONFLICT DO NOTHING`, which is how "insert the
|
|
402
|
+
* ones that are new" becomes one round-trip instead of one per row with a
|
|
403
|
+
* 23505 caught around each. **The returned rows are the ones actually
|
|
404
|
+
* INSERTED**: a row that collided is skipped, so it is absent from the result
|
|
405
|
+
* — Postgres does not return what it did not write.
|
|
406
|
+
*
|
|
407
|
+
* `action: "update"` emits `ON CONFLICT DO UPDATE`, setting every non-conflict
|
|
408
|
+
* column from the incoming row, and every row comes back.
|
|
409
|
+
*/
|
|
410
|
+
insertMany(rows: readonly TxInsertShape<Insert>[], opts?: {
|
|
411
|
+
onConflict: readonly Extract<keyof Row, string>[];
|
|
412
|
+
action?: "ignore" | "update";
|
|
413
|
+
}): TxRows<Row>;
|
|
414
|
+
/**
|
|
415
|
+
* Insert the row, or update it when it collides on `onConflict` — inside the
|
|
416
|
+
* plan's savepoint, with the same meaning `tables.<t>.upsert()` has outside it.
|
|
417
|
+
*
|
|
418
|
+
* It is an operation because the alternative is not writable here: a failed
|
|
419
|
+
* insert aborts the whole transaction, so "try, then fall back" cannot be two
|
|
420
|
+
* plan steps.
|
|
421
|
+
*/
|
|
422
|
+
upsert(values: TxInsertShape<Insert>, options: {
|
|
423
|
+
onConflict: readonly Extract<keyof Row, string>[];
|
|
424
|
+
}): TxRows<Row>;
|
|
391
425
|
/**
|
|
392
426
|
* Update every row matching `where`. The filter comes first because it is the
|
|
393
427
|
* dangerous half: an update whose `where` you got wrong rewrites rows you
|
|
@@ -512,6 +546,57 @@ declare class NotFound extends NamedHttpError {
|
|
|
512
546
|
declare class Conflict extends NamedHttpError {
|
|
513
547
|
constructor(message?: string, code?: string, data?: unknown);
|
|
514
548
|
}
|
|
549
|
+
/**
|
|
550
|
+
* 409 — a write was refused because it would duplicate an existing row.
|
|
551
|
+
* Carries the NAME of the unique constraint Postgres named (`users_email_key`).
|
|
552
|
+
*
|
|
553
|
+
* The engine produces it: a statement rejected with SQLSTATE `23505` is
|
|
554
|
+
* converted here rather than surfacing as an opaque driver error (see
|
|
555
|
+
* `engine/db.ts`, `diagnosingDriver`). What that removes is the string match —
|
|
556
|
+
* before this, the only way to act on a duplicate was to test the driver
|
|
557
|
+
* message for "duplicate key value violates unique constraint", a contract
|
|
558
|
+
* nobody signed that breaks on a Postgres upgrade, a locale, or a constraint
|
|
559
|
+
* rename, silently and in production.
|
|
560
|
+
*
|
|
561
|
+
* THE NAME IS A FIELD AND STAYS OUT OF THE DEFAULT MESSAGE. The two are not
|
|
562
|
+
* the same audience. `constraint` is read by the code that catches this — the
|
|
563
|
+
* developer, who already knows the schema. `errorDescription` is the HTTP
|
|
564
|
+
* response body, and an UNCAUGHT duplicate puts it in front of the
|
|
565
|
+
* application's end user: `users_email_key` there discloses how the schema is
|
|
566
|
+
* built to whoever sent the request. The platform's own data API took the same
|
|
567
|
+
* decision one surface over and wrote down why —
|
|
568
|
+
* `v2/internal/modules/database/internal/handler/pgerror.go:83-87` collapses
|
|
569
|
+
* every 23xxx to a generic conflict, "never disclose the constraint/column
|
|
570
|
+
* name". A thrower who WANTS the name on the wire passes it deliberately
|
|
571
|
+
* (`new UniqueViolation(c, \`\${c} already exists\`)`, or through `data`).
|
|
572
|
+
*
|
|
573
|
+
* @example
|
|
574
|
+
* try {
|
|
575
|
+
* await Database.tables.users.insert({ email });
|
|
576
|
+
* } catch (e) {
|
|
577
|
+
* if (UniqueViolation.is(e) && e.constraint === "users_email_key") {
|
|
578
|
+
* throw new Conflict("That email is taken", "email_taken");
|
|
579
|
+
* }
|
|
580
|
+
* throw e;
|
|
581
|
+
* }
|
|
582
|
+
*/
|
|
583
|
+
declare class UniqueViolation extends Conflict {
|
|
584
|
+
/**
|
|
585
|
+
* Whether `e` is a unique violation — REGARDLESS of which copy of this SDK
|
|
586
|
+
* constructed it.
|
|
587
|
+
*
|
|
588
|
+
* Use this instead of `instanceof`. Measured on a live stack: a controller
|
|
589
|
+
* bundle INLINES its own copy of `@palbase/backend`, and the engine that
|
|
590
|
+
* raises this error is the runtime's copy. Two copies, two class identities,
|
|
591
|
+
* and `e instanceof UniqueViolation` is false in the one place a caller
|
|
592
|
+
* writes it — a check that reads as correct and silently never matches.
|
|
593
|
+
*/
|
|
594
|
+
static is(e: unknown): e is UniqueViolation;
|
|
595
|
+
/** The unique constraint the statement violated, as Postgres named it.
|
|
596
|
+
* `""` when the driver did not say which — see `engine/db.ts`. */
|
|
597
|
+
readonly constraint: string;
|
|
598
|
+
constructor(constraint: string, message?: string, code?: string, data?: unknown);
|
|
599
|
+
}
|
|
515
600
|
/** A single field-level validation failure carried by {@link BadRequest}. */
|
|
516
601
|
interface FieldError {
|
|
517
602
|
/** The offending field's name (dotted path for nested fields). */
|
|
@@ -1546,6 +1631,13 @@ interface PalbaseFlagsClient {
|
|
|
1546
1631
|
/**
|
|
1547
1632
|
* Realtime broadcast surface (backend handler → subscribed clients).
|
|
1548
1633
|
*
|
|
1634
|
+
* **Every channel must be DECLARED, or the join is refused.** Channel names are
|
|
1635
|
+
* not free text: `channels.ts` at the project root publishes which names exist
|
|
1636
|
+
* and who may subscribe, publish, or write state, and a client joining a name no
|
|
1637
|
+
* declaration matches is rejected without ever reaching your code. Declare with
|
|
1638
|
+
* `ownerOnly()`, `publicChannel()`, or a custom `authorize(ctx)` — see
|
|
1639
|
+
* {@link defineChannels}. Broadcasting to an undeclared channel reaches nobody.
|
|
1640
|
+
*
|
|
1549
1641
|
* Backend-side this is BROADCAST-ONLY: a handler pushes an event to a channel
|
|
1550
1642
|
* and every client subscribed to that channel (via the client SDK's
|
|
1551
1643
|
* `pb.realtime.channel(...).on(...)`) receives it. There is no `subscribe()` on
|
|
@@ -1554,9 +1646,10 @@ interface PalbaseFlagsClient {
|
|
|
1554
1646
|
* once the broadcast is accepted (or with an `error` if it could not be sent),
|
|
1555
1647
|
* but it never blocks the handler waiting on subscribers.
|
|
1556
1648
|
*
|
|
1557
|
-
* Channel
|
|
1558
|
-
*
|
|
1559
|
-
*
|
|
1649
|
+
* Channel names are yours to choose (e.g. `"room:42"`, `"orders"`) but not yours
|
|
1650
|
+
* to leave undeclared: each must match a pattern in `channels.ts`, which is where
|
|
1651
|
+
* `"room:{roomId}"` is authorized. The Palbase-managed `flags:<ref>` channels are
|
|
1652
|
+
* internal — author channels for your own features.
|
|
1560
1653
|
*
|
|
1561
1654
|
* @example
|
|
1562
1655
|
* // Notify everyone in a chat room that a message landed:
|
|
@@ -1816,9 +1909,36 @@ interface RateLimitConfig {
|
|
|
1816
1909
|
/** The six raw string-keyed DB operations shared by `DBClient` and the
|
|
1817
1910
|
* transaction-scoped client. */
|
|
1818
1911
|
interface DBOps {
|
|
1819
|
-
/**
|
|
1912
|
+
/**
|
|
1913
|
+
* Run SQL on the REQUEST'S OWN transaction.
|
|
1914
|
+
*
|
|
1915
|
+
* This is **not** read-only. Nothing marks that transaction `READ ONLY`, so a
|
|
1916
|
+
* write passed here executes and commits with the request — a plain `UPDATE`, a
|
|
1917
|
+
* write hidden in a CTE, or a function that writes. What stands between a
|
|
1918
|
+
* statement and your data is RLS and the role the request runs as, exactly as
|
|
1919
|
+
* for every other operation on this client.
|
|
1920
|
+
*
|
|
1921
|
+
* `INSERT … ON CONFLICT DO UPDATE` therefore works here; `tables.<t>.upsert()`
|
|
1922
|
+
* is the same thing with types. Array parameters are encoded as Postgres array
|
|
1923
|
+
* literals, so `= ANY($1::uuid[])` takes a plain JS array.
|
|
1924
|
+
*
|
|
1925
|
+
* This comment used to claim a `READ ONLY` transaction. It was wrong, and the
|
|
1926
|
+
* cost was measured: a tenant read it, concluded an upsert was impossible from
|
|
1927
|
+
* here, abandoned `ON CONFLICT` and wrote a database trigger instead.
|
|
1928
|
+
*/
|
|
1820
1929
|
query(sql: string, params?: unknown[]): Promise<Record<string, unknown>[]>;
|
|
1821
1930
|
insert(table: string, data: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
1931
|
+
/**
|
|
1932
|
+
* Insert the row, or update it when it collides on `onConflict` — one
|
|
1933
|
+
* statement, so two concurrent callers cannot both lose.
|
|
1934
|
+
*
|
|
1935
|
+
* Read-then-write cannot be made safe here by catching the unique violation: a
|
|
1936
|
+
* request runs in one transaction, so the failed insert aborts it and every
|
|
1937
|
+
* later statement answers `current transaction is aborted`.
|
|
1938
|
+
*/
|
|
1939
|
+
upsert(table: string, data: Record<string, unknown>, opts: {
|
|
1940
|
+
onConflict: readonly string[];
|
|
1941
|
+
}): Promise<Record<string, unknown>>;
|
|
1822
1942
|
/**
|
|
1823
1943
|
* Update the row with the given id and resolve to the updated row, or `null`
|
|
1824
1944
|
* if no row matched (the id is absent, or the row is hidden by RLS). This is
|
|
@@ -1862,7 +1982,26 @@ interface DBOps {
|
|
|
1862
1982
|
/** Validity'li tabloda satırın yeni versiyonu — eski kapanır (valid_to/superseded_by),
|
|
1863
1983
|
* yenisi eklenir; TEK savepoint, dönüş yeni satır (FR-029, C-9). */
|
|
1864
1984
|
supersede(table: string, id: string, row: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
1865
|
-
|
|
1985
|
+
/** Filtre + sıralama + sayfa. `offset` yalnız `limit` ile birlikte geçerlidir
|
|
1986
|
+
* (limitsiz offset sayfa değildir; motor adıyla reddeder — FR-004). */
|
|
1987
|
+
/** Update every row the filter matches, in one statement; resolves to them.
|
|
1988
|
+
* An EMPTY filter is refused — a whole-table write is not something to reach
|
|
1989
|
+
* by accident. */
|
|
1990
|
+
updateMany(table: string, where: Record<string, unknown>, set: Record<string, unknown>): Promise<Record<string, unknown>[]>;
|
|
1991
|
+
/** Delete every row the filter matches; resolves to how many. Empty filter
|
|
1992
|
+
* refused, for the same reason and more so. */
|
|
1993
|
+
deleteMany(table: string, where: Record<string, unknown>): Promise<number>;
|
|
1994
|
+
/** How many rows match — the half of pagination limit/offset cannot supply.
|
|
1995
|
+
* An empty filter is legitimate here: counting is a read. */
|
|
1996
|
+
count(table: string, where?: Record<string, unknown>): Promise<number>;
|
|
1997
|
+
findMany(table: string, query?: Record<string, unknown>, opts?: {
|
|
1998
|
+
orderBy?: {
|
|
1999
|
+
column: string;
|
|
2000
|
+
direction?: "asc" | "desc";
|
|
2001
|
+
};
|
|
2002
|
+
limit?: number;
|
|
2003
|
+
offset?: number;
|
|
2004
|
+
}): Promise<Record<string, unknown>[]>;
|
|
1866
2005
|
/** "Bu satıra benzer satırlar" (FR-022) — satır-modunda kolon vektörüyle,
|
|
1867
2006
|
* chunk-modunda chunk-ortalamasıyla; kendisi hariç. */
|
|
1868
2007
|
similar(table: string, id: string, opts?: {
|
|
@@ -1878,6 +2017,18 @@ interface DBOps {
|
|
|
1878
2017
|
weight: number;
|
|
1879
2018
|
};
|
|
1880
2019
|
}): Promise<Record<string, unknown>[]>;
|
|
2020
|
+
/** D-021 (FR-027): kolon sayaçları bağımsız dönüşle — search'ün dizi-üstü
|
|
2021
|
+
* `_facets` özelliği serileşmede kaybolur; ciddi sözleşme budur. */
|
|
2022
|
+
facets(table: string, params: {
|
|
2023
|
+
facets: string[];
|
|
2024
|
+
where?: Record<string, unknown>;
|
|
2025
|
+
validity?: "all" | {
|
|
2026
|
+
asOf: string;
|
|
2027
|
+
};
|
|
2028
|
+
}): Promise<Record<string, {
|
|
2029
|
+
value: string | null;
|
|
2030
|
+
count: number;
|
|
2031
|
+
}[]>>;
|
|
1881
2032
|
/** Çok-örnekli öneri (FR-023): avg(pos) + (avg(pos) − avg(neg)); positive'ler sonuç dışı. */
|
|
1882
2033
|
recommend(table: string, opts: {
|
|
1883
2034
|
positive: string[];
|
|
@@ -1913,6 +2064,14 @@ interface DBClient extends DBOps {
|
|
|
1913
2064
|
* `.expectOne(…)`; without it a declared expectation degrades to a generic 409.
|
|
1914
2065
|
*/
|
|
1915
2066
|
txPlan(plan: TxPlanBody): Promise<TxPlanResponse>;
|
|
2067
|
+
/**
|
|
2068
|
+
* Run `fn` inside a SAVEPOINT on this request's transaction, so a failure in
|
|
2069
|
+
* it rolls back only what `fn`'s handle wrote.
|
|
2070
|
+
*
|
|
2071
|
+
* The handle is a PARAMETER on purpose: an ambient swap would capture writes
|
|
2072
|
+
* a concurrent `Promise.all` branch made outside the boundary.
|
|
2073
|
+
*/
|
|
2074
|
+
attempt<T>(fn: (tx: DBOps) => Promise<T>): Promise<T>;
|
|
1916
2075
|
/**
|
|
1917
2076
|
* Return a sibling DB client that bypasses Row-Level Security by running as
|
|
1918
2077
|
* the `service_role` (BYPASSRLS). Use sparingly and explicitly — the default
|
|
@@ -2213,4 +2372,4 @@ type Middleware = (ctx: MiddlewareContext, next: () => Promise<void>) => Promise
|
|
|
2213
2372
|
*/
|
|
2214
2373
|
type AuthSpec = boolean | Partial<AuthConfig>;
|
|
2215
2374
|
|
|
2216
|
-
export { type PalbaseCreateLinkParams as $, type AuthSpec as A, BadRequest as B, type CacheClient as C, type DBClient as D, type ErrorDef as E, type FileContext as F, type PalbaseAttestiOSParams as G, HttpError as H, type PalbaseAttestiOSResult as I, type PalbaseAuthClient as J, type PalbaseBatchOverrideOperation as K, type Logger as L, type Materialized as M, NotFound as N, type PalbaseBatchSetOverridesResult as O, type PalbaseDocsClient as P, type PalbaseBindDeviceParams as Q, type RateLimitConfig as R, type SecretsService as S, type TxPlanBody as T, type PalbaseClearAllOverridesResult as U, type PalbaseClearOverrideResult as V, type PalbaseCohortQueryInput as W, type PalbaseCohortResult as X, type PalbaseCollectionRef as Y, type PalbaseCountQueryInput as Z, type PalbaseCountResult as _, type PalbaseFlagsClient as a, type PalbaseVerifyRequestSignatureParams as a$, type PalbaseDeviceInfo as a0, type PalbaseDeviceTokenView as a1, type PalbaseDocumentRef as a2, type PalbaseDocumentSnapshot as a3, type PalbaseEmailClient as a4, type PalbaseEmailSendParams as a5, type PalbaseEmailSendResponse as a6, type PalbaseEventNamesResult as a7, type PalbaseEventsQueryInput as a8, type PalbaseEventsResult as a9, type PalbaseMatchParams as aA, type PalbaseMultiChannelResponse as aB, type PalbaseOverviewResult as aC, type PalbasePreferences as aD, type PalbasePreferencesClient as aE, type PalbasePushClient as aF, type PalbasePushSendParams as aG, type PalbasePushSendResponse as aH, type PalbaseQrCodeOptions as aI, type PalbaseQuerySnapshot as aJ, type PalbaseRegisterDeviceParams as aK, type PalbaseRetentionQueryInput as aL, type PalbaseRetentionResult as aM, type PalbaseSession as aN, type PalbaseSetOverrideResult as aO, type PalbaseSetOverridesResult as aP, type PalbaseSignedUrlResponse as aQ, type PalbaseSmsClient as aR, type PalbaseSmsSendParams as aS, type PalbaseSmsSendResponse as aT, type PalbaseTransformOptions as aU, type PalbaseUpdateLinkParams as aV, type PalbaseUploadOptions as aW, type PalbaseUser as aX, type PalbaseUserDetailResult as aY, type PalbaseUsersQueryInput as aZ, type PalbaseUsersResult as a_, type PalbaseFileObject as aa, type PalbaseFlag as ab, type PalbaseFlagContext as ac, type PalbaseFlagSource as ad, type PalbaseFlagValue as ae, type PalbaseFlagVariant as af, type PalbaseFlagsServiceClient as ag, type PalbaseFunctionsClient as ah, type PalbaseFunnelQueryInput as ai, type PalbaseFunnelResult as aj, type PalbaseIdentifyTraits as ak, type PalbaseInboxClient as al, type PalbaseInboxListOptions as am, type PalbaseInboxListResult as an, type PalbaseInboxMessage as ao, type PalbaseInboxSendParams as ap, type PalbaseInboxSendResponse as aq, type PalbaseInitialLink as ar, type PalbaseInvokeOptions as as, type PalbaseLink as at, type PalbaseLinkAnalytics as au, type PalbaseLinkDetails as av, type PalbaseLinksClient as aw, type PalbaseListLinksOptions as ax, type PalbaseListLinksResult as ay, type PalbaseListOptions as az, type PalbaseNotificationsClient as b, type PalbaseWhereOperator as b0, type Ref as b1, TooManyRequests as b2, type TxColumnExpr as b3, type TxInsertShape as b4, type TxInsertValue as b5, type TxNow as b6, TxPlanError as b7, type TxPlanHandle as b8, type TxPlanOpResult as b9, type TxPlanRejection as ba, TxRefError as bb, type TxRow as bc, type TxRows as bd, type TxSelectOptions as be, type TxSetShape as bf, type TxSetValue as bg, type TxTable as bh, type TxWhere as bi, type TxWireExpr as bj, type TxWireGuard as bk, type TxWireOp as bl, type TxWireRef as bm, type TxWireValue as bn, Unauthorized as bo, type User as
|
|
2375
|
+
export { type PalbaseCreateLinkParams as $, type AuthSpec as A, BadRequest as B, type CacheClient as C, type DBClient as D, type ErrorDef as E, type FileContext as F, type PalbaseAttestiOSParams as G, HttpError as H, type PalbaseAttestiOSResult as I, type PalbaseAuthClient as J, type PalbaseBatchOverrideOperation as K, type Logger as L, type Materialized as M, NotFound as N, type PalbaseBatchSetOverridesResult as O, type PalbaseDocsClient as P, type PalbaseBindDeviceParams as Q, type RateLimitConfig as R, type SecretsService as S, type TxPlanBody as T, type PalbaseClearAllOverridesResult as U, type PalbaseClearOverrideResult as V, type PalbaseCohortQueryInput as W, type PalbaseCohortResult as X, type PalbaseCollectionRef as Y, type PalbaseCountQueryInput as Z, type PalbaseCountResult as _, type PalbaseFlagsClient as a, type PalbaseVerifyRequestSignatureParams as a$, type PalbaseDeviceInfo as a0, type PalbaseDeviceTokenView as a1, type PalbaseDocumentRef as a2, type PalbaseDocumentSnapshot as a3, type PalbaseEmailClient as a4, type PalbaseEmailSendParams as a5, type PalbaseEmailSendResponse as a6, type PalbaseEventNamesResult as a7, type PalbaseEventsQueryInput as a8, type PalbaseEventsResult as a9, type PalbaseMatchParams as aA, type PalbaseMultiChannelResponse as aB, type PalbaseOverviewResult as aC, type PalbasePreferences as aD, type PalbasePreferencesClient as aE, type PalbasePushClient as aF, type PalbasePushSendParams as aG, type PalbasePushSendResponse as aH, type PalbaseQrCodeOptions as aI, type PalbaseQuerySnapshot as aJ, type PalbaseRegisterDeviceParams as aK, type PalbaseRetentionQueryInput as aL, type PalbaseRetentionResult as aM, type PalbaseSession as aN, type PalbaseSetOverrideResult as aO, type PalbaseSetOverridesResult as aP, type PalbaseSignedUrlResponse as aQ, type PalbaseSmsClient as aR, type PalbaseSmsSendParams as aS, type PalbaseSmsSendResponse as aT, type PalbaseTransformOptions as aU, type PalbaseUpdateLinkParams as aV, type PalbaseUploadOptions as aW, type PalbaseUser as aX, type PalbaseUserDetailResult as aY, type PalbaseUsersQueryInput as aZ, type PalbaseUsersResult as a_, type PalbaseFileObject as aa, type PalbaseFlag as ab, type PalbaseFlagContext as ac, type PalbaseFlagSource as ad, type PalbaseFlagValue as ae, type PalbaseFlagVariant as af, type PalbaseFlagsServiceClient as ag, type PalbaseFunctionsClient as ah, type PalbaseFunnelQueryInput as ai, type PalbaseFunnelResult as aj, type PalbaseIdentifyTraits as ak, type PalbaseInboxClient as al, type PalbaseInboxListOptions as am, type PalbaseInboxListResult as an, type PalbaseInboxMessage as ao, type PalbaseInboxSendParams as ap, type PalbaseInboxSendResponse as aq, type PalbaseInitialLink as ar, type PalbaseInvokeOptions as as, type PalbaseLink as at, type PalbaseLinkAnalytics as au, type PalbaseLinkDetails as av, type PalbaseLinksClient as aw, type PalbaseListLinksOptions as ax, type PalbaseListLinksResult as ay, type PalbaseListOptions as az, type PalbaseNotificationsClient as b, type PalbaseWhereOperator as b0, type Ref as b1, TooManyRequests as b2, type TxColumnExpr as b3, type TxInsertShape as b4, type TxInsertValue as b5, type TxNow as b6, TxPlanError as b7, type TxPlanHandle as b8, type TxPlanOpResult as b9, type TxPlanRejection as ba, TxRefError as bb, type TxRow as bc, type TxRows as bd, type TxSelectOptions as be, type TxSetShape as bf, type TxSetValue as bg, type TxTable as bh, type TxWhere as bi, type TxWireExpr as bj, type TxWireGuard as bk, type TxWireOp as bl, type TxWireRef as bm, type TxWireValue as bn, Unauthorized as bo, UniqueViolation as bp, type User as bq, type VerifiedDevice as br, dec as bs, defineMiddleware as bt, inc as bu, now as bv, type PalbaseRealtimeClient as c, type PalbaseStorageClient as d, type PalbaseBucketClient as e, type DBOps as f, type TxPlanResponse as g, type PalbaseResult as h, type AuthConfig as i, type ClientInfo as j, Conflict as k, type ErrorMap as l, type ErrorThrowers as m, Forbidden as n, type HttpMethod as o, type Middleware as p, type MiddlewareContext as q, type MiddlewareHandler as r, type PBRequest as s, PalError as t, type PalbaseAnalyticsClient as u, type PalbaseAnalyticsManagementNamespace as v, type PalbaseAnalyticsProperties as w, type PalbaseAnalyticsQueryNamespace as x, type PalbaseAttestAndroidParams as y, type PalbaseAttestAndroidResult as z };
|