okmodel 0.5.1 → 0.6.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/README.md +29 -14
- package/dist/adapters/pg/no-inflight-timeout.d.ts +17 -0
- package/dist/adapters/pg/postgres-extra.d.ts +22 -0
- package/dist/contracts/catalog/document.d.ts +19 -5
- package/dist/contracts/catalog/object.d.ts +2 -1
- package/dist/contracts/catalog/policy.d.ts +48 -0
- package/dist/contracts/catalog/types.d.ts +25 -1
- package/dist/contracts/catalog/view.d.ts +2 -0
- package/dist/contracts/internal.js +1 -1
- package/dist/contracts/location.d.ts +10 -0
- package/dist/dialects/pg/column.d.ts +13 -2
- package/dist/dialects/pg/ddl.d.ts +37 -1
- package/dist/dialects/pg/emit.d.ts +19 -1
- package/dist/dialects/pg/errors.d.ts +32 -1
- package/dist/dialects/pg/ext/citext.js +1 -1
- package/dist/dialects/pg/ext/index.js +1 -1
- package/dist/dialects/pg/ext/pg-trgm.js +1 -1
- package/dist/dialects/pg/filter-parse.d.ts +5 -4
- package/dist/dialects/pg/fn/index.js +2 -2
- package/dist/dialects/pg/index.d.ts +2 -1
- package/dist/dialects/pg/index.js +23 -17
- package/dist/dialects/pg/introspect.d.ts +7 -0
- package/dist/dialects/pg/model.d.ts +7 -2
- package/dist/dialects/pg/owner.d.ts +42 -0
- package/dist/dialects/pg/path-endpoint.d.ts +20 -0
- package/dist/dialects/pg/role/check.d.ts +3 -0
- package/dist/dialects/pg/role/index.d.ts +71 -6
- package/dist/dialects/pg/role/sql.d.ts +11 -0
- package/dist/dialects/pg/schema.d.ts +2 -0
- package/dist/dialects/pg/table.d.ts +25 -3
- package/dist/dialects/pg/tenancy.d.ts +45 -3
- package/dist/dialects/pg/view/client.d.ts +19 -1
- package/dist/dialects/pg/view/index.d.ts +4 -0
- package/dist/dialects/pg/view/index.js +21 -178
- package/dist/dialects/pg/view/refresh.d.ts +24 -0
- package/dist/runtime/batch.d.ts +1 -1
- package/dist/runtime/conflict.d.ts +2 -2
- package/dist/runtime/drift.d.ts +9 -0
- package/dist/runtime/inflight.d.ts +14 -0
- package/dist/runtime/pg/bun.js +4 -3
- package/dist/runtime/pg/pg.js +3 -3
- package/dist/runtime/pg/pglite.js +4 -3
- package/dist/runtime/pg/postgresjs.js +3 -3
- package/dist/runtime/plan.d.ts +18 -10
- package/dist/runtime/predicate.d.ts +19 -0
- package/dist/runtime/safety/index.js +1 -1
- package/dist/runtime/tenancy/composite.d.ts +26 -0
- package/dist/runtime/tenancy/context.d.ts +16 -0
- package/dist/runtime/tenancy/index.d.ts +9 -5
- package/dist/runtime/tenancy/index.js +1508 -37
- package/dist/runtime/tenancy/path.d.ts +87 -0
- package/dist/runtime/tenancy/rls.d.ts +67 -0
- package/dist/runtime/tenancy/via.d.ts +22 -0
- package/dist/runtime/traits/index.js +17 -11
- package/dist/runtime/types.d.ts +13 -1
- package/dist/runtime/validate/index.js +4 -4
- package/dist/runtime/write.d.ts +1 -1
- package/dist/shared/09p049xa.js +702 -0
- package/dist/shared/{6qd27mx0.js → 1f0xa3cb.js} +5 -5
- package/dist/shared/1nw1f3vs.js +23 -0
- package/dist/shared/{96qcj21c.js → 1z04fa85.js} +19 -9
- package/dist/shared/{qm7cdtvr.js → 2cg3wnxc.js} +296 -60
- package/dist/shared/{dyj86cmj.js → 2jd1sn0e.js} +2 -2
- package/dist/shared/{gbtcc2d7.js → 2z7wv5tj.js} +10 -35
- package/dist/shared/{k8v5v5wj.js → 32cnm7kn.js} +6 -1
- package/dist/shared/{t4tbsy9h.js → 358zsv4r.js} +1 -1
- package/dist/shared/{2pqx26h8.js → 3fqwmr09.js} +31 -22
- package/dist/shared/{zqrnhwsq.js → 3qnhc7w5.js} +16 -9
- package/dist/shared/{r2sp8hrc.js → 5d8t84hg.js} +12 -3
- package/dist/shared/{87jvvhnt.js → 5j36z8dn.js} +16 -5
- package/dist/shared/{1g0drakv.js → 5yv4k6a6.js} +1 -1
- package/dist/shared/8dqhth8c.js +12 -0
- package/dist/shared/8etn7d8w.js +62 -0
- package/dist/shared/{v36c5g6p.js → 8x72s86k.js} +400 -13
- package/dist/shared/{nxdp2ze3.js → 929h19xp.js} +107 -5
- package/dist/shared/{gjthds9j.js → 9628a9xt.js} +1 -1
- package/dist/shared/{8xsbagad.js → 9s0ypp87.js} +88 -7
- package/dist/shared/{efmy2gcg.js → ag4c7516.js} +1 -1
- package/dist/shared/b3awxn7h.js +45 -0
- package/dist/shared/b4v57v3x.js +9 -0
- package/dist/shared/bdk4sty6.js +58 -0
- package/dist/shared/{51mvgj8w.js → c58secgj.js} +100 -7
- package/dist/shared/d5azex6s.js +6 -0
- package/dist/shared/{5fqx9yh4.js → dk8v79p3.js} +3 -1
- package/dist/shared/{4m9fn52z.js → ed0b8k4s.js} +1 -1
- package/dist/shared/{z2rnngj4.js → ek2wt2dz.js} +8 -5
- package/dist/shared/{sycnx8gt.js → f0f1n281.js} +18 -8
- package/dist/shared/{f5cw5q5r.js → g90m9b0g.js} +2 -1
- package/dist/shared/{pf0d8f77.js → gwn6v667.js} +1 -1
- package/dist/shared/{8rsy3hxz.js → h15jx9bc.js} +1 -1
- package/dist/shared/{5enne4ma.js → hazqqecq.js} +17 -93
- package/dist/shared/{jwtxdj06.js → j3rkk835.js} +32 -9
- package/dist/shared/{hf22e0wt.js → j60w0dvr.js} +19 -18
- package/dist/shared/{ycatkxmq.js → jgqj11w4.js} +1 -1
- package/dist/shared/k68eedmy.js +85 -0
- package/dist/shared/{szm0cksa.js → knmes2kh.js} +34 -6
- package/dist/shared/{0t22wwh1.js → mb2ycs1p.js} +4 -2
- package/dist/shared/{cr74e96e.js → n076ydsc.js} +1 -1
- package/dist/shared/{cctw17hj.js → nx9hh281.js} +31 -28
- package/dist/shared/{gde73es6.js → p248q79y.js} +56 -55
- package/dist/shared/{janx09m5.js → p6bjzq9q.js} +11 -7
- package/dist/shared/{6rk2gen5.js → pjr6xrm5.js} +2 -2
- package/dist/shared/{wq9n6pwr.js → pz6rj8ay.js} +82 -9
- package/dist/shared/{caw8b9d8.js → q3j1tq7a.js} +35 -22
- package/dist/shared/{8bwbwy8h.js → qq3899ht.js} +128 -18
- package/dist/shared/{tm5ab8we.js → r11n8grd.js} +2 -2
- package/dist/shared/r1fdd0f6.js +19 -0
- package/dist/shared/{8ktwd3rh.js → r3j8s5y0.js} +1 -1
- package/dist/shared/rhs3xe4k.js +7 -0
- package/dist/shared/{ntneex2a.js → rpycarcr.js} +6 -6
- package/dist/shared/{aj2qxyhj.js → sbdme3vy.js} +14 -2
- package/dist/shared/{qv2ydck9.js → t3g0k88x.js} +638 -67
- package/dist/shared/{ga3sfy93.js → ttmg09vd.js} +535 -200
- package/dist/shared/{kfjp0gck.js → venqrjna.js} +8 -4
- package/dist/shared/{fancm5pt.js → vjpnzwjz.js} +138 -15
- package/dist/shared/{32zqc1dw.js → vmfkhszw.js} +31 -7
- package/dist/shared/{krxx77g0.js → wkme6tep.js} +10 -8
- package/dist/shared/{ps7a6h14.js → wt5rzv1h.js} +12 -8
- package/dist/shared/wxr8cwns.js +6 -0
- package/dist/shared/{6mnp99hx.js → wynzeggs.js} +16 -12
- package/dist/shared/x3jc53kg.js +220 -0
- package/dist/shared/{sdc7r2ww.js → xq0mvhts.js} +8 -8
- package/dist/shared/xqve9598.js +53 -0
- package/dist/shared/{47x8x9ze.js → y2t3jktd.js} +2 -2
- package/dist/shared/{9x25fxhc.js → y34a8714.js} +1 -1
- package/dist/shared/{k7dwkhvq.js → y6jdds7g.js} +4 -1
- package/dist/shared/{nkaxvt9q.js → ys0xzyaj.js} +1 -1
- package/dist/shared/{c9z5g0fm.js → ywr8hmey.js} +5 -2
- package/dist/shared/{g7ez901n.js → ywspezzx.js} +1 -1
- package/dist/shared/{9m80mkac.js → ze4hxsmy.js} +1 -1
- package/dist/shared/{r8x5qhd7.js → zm0mafk4.js} +10 -4
- package/dist/shared/{y005b761.js → zy8r7qvz.js} +6 -2
- package/dist/tooling/cli.js +41 -15
- package/dist/tooling/migrate/apply.d.ts +14 -0
- package/dist/tooling/migrate/check.d.ts +3 -4
- package/dist/tooling/migrate/classify.d.ts +4 -0
- package/dist/tooling/migrate/config.d.ts +3 -2
- package/dist/tooling/migrate/files.d.ts +11 -1
- package/dist/tooling/migrate/index.js +14 -14
- package/dist/tooling/migrate/lint.d.ts +1 -1
- package/dist/tooling/migrate/lost.d.ts +28 -0
- package/dist/tooling/migrate/paths.d.ts +14 -0
- package/dist/tooling/migrate/plan.d.ts +6 -3
- package/dist/tooling/migrate/runner.d.ts +25 -0
- package/dist/tooling/migrate/sandbox.d.ts +57 -0
- package/dist/tooling/migrate/sql-lex.d.ts +20 -3
- package/dist/tooling/migrate/text.d.ts +42 -0
- package/dist/tooling/node-version.d.ts +21 -0
- package/dist/tooling/testing/facts.d.ts +33 -5
- package/dist/tooling/testing/index.d.ts +1 -1
- package/dist/tooling/testing/index.js +3 -3
- package/dist/tooling/testing/isolation.d.ts +11 -5
- package/package.json +5 -2
- package/dist/shared/7zwwyh0v.js +0 -448
- package/dist/shared/q58y17hy.js +0 -21
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
okmodel is a catalog-first TypeScript ORM, PostgreSQL first. Other SQL databases are the direction. CI runs PostgreSQL 15 to 18. The schema is the single source. Migrations and queries come from it.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Apache-2.0. The published version is [okmodel on npm](https://www.npmjs.com/package/okmodel).
|
|
6
6
|
|
|
7
7
|
## Contents
|
|
8
8
|
|
|
@@ -345,12 +345,12 @@ if (row?.title !== "hello" || row.author?.name !== "Ada") {
|
|
|
345
345
|
|
|
346
346
|
### One
|
|
347
347
|
|
|
348
|
-
`one` returns the
|
|
348
|
+
`one` returns the note for that id, or null when none matches. More than one match throws `not_unique`.
|
|
349
349
|
|
|
350
350
|
```ts
|
|
351
|
-
// One row. More than one match throws.
|
|
351
|
+
// One row, or null. More than one match throws.
|
|
352
352
|
const single = await db.notes.one({ where: { id: note.id } });
|
|
353
|
-
if (single.title !== "hello") throw new Error("one did not return the note");
|
|
353
|
+
if (single === null || single.title !== "hello") throw new Error("one did not return the note");
|
|
354
354
|
```
|
|
355
355
|
|
|
356
356
|
### Count
|
|
@@ -398,6 +398,8 @@ Inserting Ada again fails because the name is unique. `safe` returns that `OkmEr
|
|
|
398
398
|
```ts
|
|
399
399
|
import { OkmError, safe } from "okmodel";
|
|
400
400
|
|
|
401
|
+
import { db } from "./db.ts";
|
|
402
|
+
|
|
401
403
|
// safe returns the unique error instead of throwing.
|
|
402
404
|
const duplicate = await safe(db.authors.insert({ name: "Ada" }));
|
|
403
405
|
if (duplicate.ok || !(duplicate.error instanceof OkmError) || duplicate.error.kind !== "unique") {
|
|
@@ -431,7 +433,7 @@ export const app = schema({ tables: [tasks] });
|
|
|
431
433
|
|
|
432
434
|
### Hidden
|
|
433
435
|
|
|
434
|
-
A password hash should not come back on an ordinary read. `.hidden()` leaves the column out of `find` and out of `include
|
|
436
|
+
A password hash should not come back on an ordinary read, and a caller should not be able to filter on it. `.hidden()` leaves the column out of `find` and out of `include`, and `where` and `orderBy` refuse it (OKM1120). Name it in `select` when that call needs it. `hidden({ filterable: true })` allows `where` and `orderBy` and still leaves it out of the default row. `filters()` still refuses a hidden column.
|
|
435
437
|
|
|
436
438
|
`hidden.ts`:
|
|
437
439
|
|
|
@@ -711,7 +713,7 @@ export async function hide(url: string, id: string): Promise<void> {
|
|
|
711
713
|
|
|
712
714
|
### Tenancy
|
|
713
715
|
|
|
714
|
-
Every note belongs to one tenant. Column tenancy adds `tenantId` and puts that tenant on every read and write. `db.for({ tenantId }).notes.find({ limit: 20 })` reads one tenant. `global("shared")` marks a table every tenant can read, such as a list of countries.
|
|
716
|
+
Every note belongs to one tenant. Column tenancy adds `tenantId` and puts that tenant on every read and write. `db.for({ tenantId }).notes.find({ limit: 20 })` reads one tenant. Composite tenancy passes every key, `compositeTenancy({ key: ["organizationId", "workspaceId"], type: "uuid" })` and `db.for({ organizationId, workspaceId })`. A table without its own key uses `tenancy: via("project.organization")`, up to three relations, and reads and writes follow that path. `global("shared")` marks a table every tenant can read, such as a list of countries. `rlsTenancy({ key: "tenantId", type: "uuid" })` keeps that predicate and adds row-level security policies. A role that owns the tables, a superuser, or `BYPASSRLS` is refused on the first scoped call. See [known limits](https://github.com/omqkhafi/okmodel/blob/main/docs/known-limits.md).
|
|
715
717
|
|
|
716
718
|
`tenancy.ts`:
|
|
717
719
|
|
|
@@ -864,7 +866,13 @@ export const app = schema({
|
|
|
864
866
|
|
|
865
867
|
### Roles and grants
|
|
866
868
|
|
|
867
|
-
The migration connects as one role and the app connects as another. `roles` names both. The app role receives select, insert, update, and delete on tables and views, select on materialized views, execute on functions, and usage plus select on sequences. Apply runs as the migration role, and switches to it with `SET ROLE` when the connection is someone else.
|
|
869
|
+
The migration connects as one role and the app connects as another. `roles` names both. The app role receives select, insert, update, and delete on tables and views, select on materialized views, execute on functions, and usage plus select on sequences. Apply also grants that role select on `okm_meta`, and nothing else there, so `connect()` can read the stored hash. Apply runs as the migration role, and switches to it with `SET ROLE` when the connection is someone else. A role you already created is external, unless you list it in `managed`.
|
|
870
|
+
|
|
871
|
+
`roles.reporting` is a third role that can only select. It gets select on tables, views, and materialized views, usage on schemas, and the same select on tables created later. It does not get insert, update, delete, or execute. A hidden column is left out unless `roles.columns` names it. Under `rlsTenancy()` this role is not `BYPASSRLS` and it is not tenant-safe against its own SQL: it sees no tenant rows until the session sets `app.tenant`, and it can set `app.unscoped` itself and then read every tenant. `unscoped()` is the application client's read escape and is not given to this role.
|
|
872
|
+
|
|
873
|
+
`roles.columns` grants select or update on named columns: `{ role, on, select, update }`. `on` is the table or view. A listed column grant on a view replaces select on the whole view for the reporting role.
|
|
874
|
+
|
|
875
|
+
`withOwner(table(...), "ignored")` keeps a table out of diffs, plans, and `okm check`. `"external"` is known and never created, altered, or dropped. A managed table that becomes either stays in the database. Drop it while it is still managed if it should go away. See [known limits](https://github.com/omqkhafi/okmodel/blob/main/docs/known-limits.md).
|
|
868
876
|
|
|
869
877
|
`roles.ts`:
|
|
870
878
|
|
|
@@ -878,7 +886,13 @@ export default defineConfig({
|
|
|
878
886
|
schema: "./schema.ts",
|
|
879
887
|
database: url,
|
|
880
888
|
// Apply uses the migration role. The app uses the app role.
|
|
881
|
-
roles: {
|
|
889
|
+
roles: {
|
|
890
|
+
migration: "okm_migrate",
|
|
891
|
+
app: "okm_app",
|
|
892
|
+
reporting: "okm_report",
|
|
893
|
+
managed: [{ name: "okm_migrate" }, { name: "okm_report", login: true }],
|
|
894
|
+
columns: [{ role: "okm_report", on: "tasks", select: ["title"] }],
|
|
895
|
+
},
|
|
882
896
|
});
|
|
883
897
|
```
|
|
884
898
|
|
|
@@ -947,7 +961,7 @@ update "public"."notes" set "title" = 'noted' where "title" = 'hello' and ("id"
|
|
|
947
961
|
|
|
948
962
|
### Testing
|
|
949
963
|
|
|
950
|
-
`okmodel/testing` opens a real pool. `factories` insert rows, `expectQueries` counts statements, and `isolation()` checks that tenant A cannot see the row it inserted for tenant B. Each call uses a new pair of tenant ids, deletes what it inserted, and names a factory that is missing. `okm seed <file>` calls the file's default export with that harness. The target must already be migrated. A protected target is refused unless `--allow-protected`.
|
|
964
|
+
`okmodel/testing` opens a real pool. `factories` insert rows, `expectQueries` counts statements, and `isolation()` checks that tenant A cannot see the row it inserted for tenant B, including through a tenant view or materialized view. Each call uses a new pair of tenant ids, deletes what it inserted, and names a factory that is missing. A global table or view is skipped and listed. `okm seed <file>` calls the file's default export with that harness. The target must already be migrated. A protected target is refused unless `--allow-protected`.
|
|
951
965
|
|
|
952
966
|
`factory.ts`:
|
|
953
967
|
|
|
@@ -1146,7 +1160,8 @@ Status is on the [board](https://github.com/users/omqkhafi/projects/1). Each rel
|
|
|
1146
1160
|
- [x] [0.3](https://github.com/omqkhafi/okmodel/milestone/3) — Extensions, domains, functions, triggers, views, roles, and grants.
|
|
1147
1161
|
- [x] [0.4](https://github.com/omqkhafi/okmodel/milestone/4) — Safer migration plans, backfill, drift checks, provisioning, reference data, and a testing package.
|
|
1148
1162
|
- [x] [0.5](https://github.com/omqkhafi/okmodel/milestone/5) — A primary with replicas, read routing, and a reference app.
|
|
1149
|
-
- [
|
|
1163
|
+
- [x] [0.5.1](https://github.com/omqkhafi/okmodel/milestone/7) — QA fixes for 0.5.0.
|
|
1164
|
+
- [x] [0.6](https://github.com/omqkhafi/okmodel/milestone/8) — Composite, path, and row-level tenancy, column grants, a reporting role, and SQL constraint names.
|
|
1150
1165
|
|
|
1151
1166
|
`okmodel/internal` has no stability promise. Names on that subpath can change or disappear in any release.
|
|
1152
1167
|
|
|
@@ -1158,11 +1173,11 @@ Measured on this release.
|
|
|
1158
1173
|
|
|
1159
1174
|
| | Minified | Gzip | Cold import |
|
|
1160
1175
|
| -------------------------------------------- | -------: | -----: | ----------: |
|
|
1161
|
-
| Runtime entry | 5,288 | 2,026 |
|
|
1162
|
-
| App startup (10 tables, one find) |
|
|
1163
|
-
| App startup, every 0.2 feature in use (full) |
|
|
1176
|
+
| Runtime entry | 5,288 | 2,026 | 1.790 ms |
|
|
1177
|
+
| App startup (10 tables, one find) | 90,762 | 30,139 | 10.490 ms |
|
|
1178
|
+
| App startup, every 0.2 feature in use (full) | 121,506 | 39,741 | 12.455 ms |
|
|
1164
1179
|
|
|
1165
|
-
The full app has column tenancy, `archivable()`, `timestamps()`, validation rules, `one`, `many` and `manyThrough` relations, presets, and calls `include`, `page`, `aggregate`, `tx` and `batch`. A feature costs bytes only in an app that uses it: the full app is 30,
|
|
1180
|
+
The full app has column tenancy, `archivable()`, `timestamps()`, validation rules, `one`, `many` and `manyThrough` relations, presets, and calls `include`, `page`, `aggregate`, `tx` and `batch`. A feature costs bytes only in an app that uses it: the full app is 30,744 minified and 9,602 gzip bytes above the plain one. The runtime entry and the plain app are gated. The full app is printed, not gated. The plain app's cold import on this sample is under the 15 ms local reference. That figure is printed and is not a gate.
|
|
1166
1181
|
|
|
1167
1182
|
The rest of the measurements are in [size](https://github.com/omqkhafi/okmodel/blob/main/docs/size.md).
|
|
1168
1183
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Refusal for a driver that cannot cancel an in-flight statement (D224).
|
|
3
|
+
*
|
|
4
|
+
* Bun.sql and PGlite throw OKM1120 for a positive `timeout`. The message
|
|
5
|
+
* stays `timeout` because the PGlite connect graph has two gzip bytes left.
|
|
6
|
+
* Kind is `invalid`, which separates it from kind `timeout`. `timeout: 0`
|
|
7
|
+
* still fails immediately as kind `timeout`. `signal` is unchanged.
|
|
8
|
+
* postgres.js and node-postgres do not import this.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Throws OKM1120 when `timeout` is a positive number.
|
|
12
|
+
*
|
|
13
|
+
* @param options - Per-call options. Absent, and a non-positive timeout, pass through
|
|
14
|
+
*/
|
|
15
|
+
export declare function noTimeout(options: {
|
|
16
|
+
readonly timeout?: number;
|
|
17
|
+
} | undefined): void;
|
|
@@ -42,6 +42,28 @@ export declare function describe(sql: Sql, text: string, params?: readonly WireV
|
|
|
42
42
|
* @returns Chunks of wire rows
|
|
43
43
|
*/
|
|
44
44
|
export declare function stream(sql: Sql, text: string, params?: readonly WireValue[]): AsyncIterable<readonly (readonly WireValue[])[]>;
|
|
45
|
+
type Lost = {
|
|
46
|
+
on: boolean;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Rejects later writes once postgres.js reports the reserved socket closed.
|
|
50
|
+
*
|
|
51
|
+
* The first statement installs `onclose`. The checkout guard then refuses
|
|
52
|
+
* the next statement, savepoint, or COMMIT before `socket.write`.
|
|
53
|
+
*
|
|
54
|
+
* @param sql - Reserved connection
|
|
55
|
+
* @param lost - Set when that socket closes
|
|
56
|
+
*/
|
|
57
|
+
/**
|
|
58
|
+
* Sets `lost` when the reserved socket closes.
|
|
59
|
+
*
|
|
60
|
+
* The first statement installs `onclose`. Later statements see the flag
|
|
61
|
+
* before they write.
|
|
62
|
+
*
|
|
63
|
+
* @param sql - Reserved connection
|
|
64
|
+
* @param lost - Set when that socket closes
|
|
65
|
+
*/
|
|
66
|
+
export declare function watchReserved(sql: Sql, lost: Lost): void;
|
|
45
67
|
/** Refcount a checkout or a listener borrows from the pool. */
|
|
46
68
|
type Gate = {
|
|
47
69
|
enter(): void;
|
|
@@ -67,11 +67,13 @@ export declare function catalogHash(source: Catalog): string;
|
|
|
67
67
|
*
|
|
68
68
|
* Roles, grants, and default privileges come from the migration config, not
|
|
69
69
|
* the schema, so they are left out. A `schema()` catalog never has them, so
|
|
70
|
-
* `connect()` hashes it unchanged. `okm check` still verifies them.
|
|
71
|
-
*
|
|
70
|
+
* `connect()` hashes it unchanged. `okm check` still verifies them. An
|
|
71
|
+
* `external` or `ignored` owner is planning state. The startup copy writes
|
|
72
|
+
* it back to `managed`, which is what `schema()` stored. A catalog with
|
|
73
|
+
* neither privileges nor those owners is returned as is.
|
|
72
74
|
*
|
|
73
75
|
* @param source - Catalog document
|
|
74
|
-
* @returns The catalog
|
|
76
|
+
* @returns The catalog `connect()` hashes
|
|
75
77
|
*/
|
|
76
78
|
export declare function startupCatalog(source: Catalog): Catalog;
|
|
77
79
|
/**
|
|
@@ -89,11 +91,23 @@ export declare function startupHash(source: Catalog): string;
|
|
|
89
91
|
* stored hash and the version, then trusts the objects (D133). `okm check`
|
|
90
92
|
* and dev keep {@link parseCatalog}.
|
|
91
93
|
*
|
|
92
|
-
* @param text -
|
|
93
|
-
* @param hash - SHA-256 of
|
|
94
|
+
* @param text - Catalog JSON. A BOM is stripped and `\r` is removed before the hash check
|
|
95
|
+
* @param hash - SHA-256 of that normalized text, stored beside the artifact
|
|
94
96
|
* @returns The catalog document
|
|
95
97
|
*/
|
|
96
98
|
export declare function loadTrustedCatalog(text: string, hash: string): Catalog;
|
|
99
|
+
/**
|
|
100
|
+
* Catalog file bytes the hash covers.
|
|
101
|
+
*
|
|
102
|
+
* A leading UTF-8 BOM is dropped. Carriage returns are removed, so a CRLF
|
|
103
|
+
* checkout hashes like the LF file the writer stored. An LF file is unchanged.
|
|
104
|
+
* UTF-16 is OKM1027.
|
|
105
|
+
*
|
|
106
|
+
* @param text - Raw catalog JSON or hash file
|
|
107
|
+
* @param label - Name used when the text is UTF-16
|
|
108
|
+
* @returns Text to hash and parse
|
|
109
|
+
*/
|
|
110
|
+
export declare function catalogFileText(text: string, label?: string): string;
|
|
97
111
|
/**
|
|
98
112
|
* Reads canonical catalog JSON.
|
|
99
113
|
*
|
|
@@ -106,7 +106,8 @@ export declare function index(input: IndexInput): IndexObject;
|
|
|
106
106
|
* Builds a constraint object.
|
|
107
107
|
*
|
|
108
108
|
* Primary key names are `{parent}_pkey` and do not include column names.
|
|
109
|
-
*
|
|
109
|
+
* Unique and foreign-key names use every SQL column. Checks use `nameKey`,
|
|
110
|
+
* which stays fixed when a field is renamed. `nameKey` is always stored.
|
|
110
111
|
*
|
|
111
112
|
* @param input - Parent, kind, columns, and the stable name key
|
|
112
113
|
* @returns A constraint envelope
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Row-level security policy catalog objects.
|
|
3
|
+
*
|
|
4
|
+
* The factory stores the record. It does not plan SQL. Postgres DDL stays in
|
|
5
|
+
* the dialect. A schema that never imports `rlsTenancy` does not load this.
|
|
6
|
+
*/
|
|
7
|
+
import type { ObjectIdentity, ObjectRef, Owner, PolicyCommand, PolicyObject, Provenance } from "./types.js";
|
|
8
|
+
/** Input for {@link policyObject}. */
|
|
9
|
+
export type PolicyInput = {
|
|
10
|
+
readonly parent: ObjectRef;
|
|
11
|
+
readonly name: string;
|
|
12
|
+
readonly command: PolicyCommand;
|
|
13
|
+
readonly expression: string;
|
|
14
|
+
/** True when the table is `FORCE ROW LEVEL SECURITY`. */
|
|
15
|
+
readonly force: boolean;
|
|
16
|
+
readonly owner?: Owner;
|
|
17
|
+
readonly provenance: Provenance;
|
|
18
|
+
/** Extra edges. The parent table is always included. */
|
|
19
|
+
readonly dependencies?: readonly ObjectIdentity[];
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Predicate stored for `{table}_tenant`.
|
|
23
|
+
*
|
|
24
|
+
* The text is what `pg_get_expr` prints, so a replayed catalog matches.
|
|
25
|
+
* An unset `app.tenant` becomes null and the comparison matches no row.
|
|
26
|
+
*
|
|
27
|
+
* @param column - SQL name of the tenant column
|
|
28
|
+
* @param dataType - Postgres type of that column
|
|
29
|
+
* @returns The `USING` and `WITH CHECK` expression
|
|
30
|
+
*/
|
|
31
|
+
export declare function tenantPolicyExpression(column: string, dataType: string): string;
|
|
32
|
+
/**
|
|
33
|
+
* Predicate stored for `{table}_unscoped_select`.
|
|
34
|
+
*
|
|
35
|
+
* `SELECT` only. Writes stay on the tenant policy.
|
|
36
|
+
*
|
|
37
|
+
* @returns The `USING` expression
|
|
38
|
+
*/
|
|
39
|
+
export declare function unscopedPolicyExpression(): string;
|
|
40
|
+
/**
|
|
41
|
+
* Builds a policy record.
|
|
42
|
+
*
|
|
43
|
+
* Identity is `(parent, name)`. A name past the dialect limit is fitted.
|
|
44
|
+
*
|
|
45
|
+
* @param input - Parent table, command, and expression
|
|
46
|
+
* @returns The catalog object
|
|
47
|
+
*/
|
|
48
|
+
export declare function policyObject(input: PolicyInput): PolicyObject;
|
|
@@ -393,6 +393,13 @@ export type ViewColumn = {
|
|
|
393
393
|
export type ViewDefinition = {
|
|
394
394
|
readonly columns: readonly ViewColumn[];
|
|
395
395
|
readonly query: string;
|
|
396
|
+
/**
|
|
397
|
+
* `WITH (security_invoker = true)`.
|
|
398
|
+
*
|
|
399
|
+
* Set only for a view over tenant tables under `rlsTenancy`. Omitted
|
|
400
|
+
* otherwise, so a view under another strategy keeps the same catalog bytes.
|
|
401
|
+
*/
|
|
402
|
+
readonly securityInvoker?: true;
|
|
396
403
|
};
|
|
397
404
|
/**
|
|
398
405
|
* Materialized view definition.
|
|
@@ -440,10 +447,27 @@ export type RoleObject = CatalogEnvelope<"role", RoleIdentity, RoleDefinition>;
|
|
|
440
447
|
export type GrantObject = CatalogEnvelope<"grant", GrantIdentity, GrantDefinition>;
|
|
441
448
|
/** A default privilege. Identity is `(forRole, namespace, objectKind, grantee, privilege)`. */
|
|
442
449
|
export type DefaultPrivilegeObject = CatalogEnvelope<"defaultPrivilege", DefaultPrivilegeIdentity, DefaultPrivilegeDefinition>;
|
|
450
|
+
/** Which statements a policy covers. `all` is every command. `select` is reads. */
|
|
451
|
+
export type PolicyCommand = "all" | "select";
|
|
452
|
+
/**
|
|
453
|
+
* One row-level security policy.
|
|
454
|
+
*
|
|
455
|
+
* `expression` is the `USING` text, and the `WITH CHECK` text when `command`
|
|
456
|
+
* is `all`. `force` is true when the table is `FORCE ROW LEVEL SECURITY`.
|
|
457
|
+
*/
|
|
458
|
+
export type PolicyDefinition = {
|
|
459
|
+
readonly command: PolicyCommand;
|
|
460
|
+
readonly expression: string;
|
|
461
|
+
readonly force: boolean;
|
|
462
|
+
};
|
|
463
|
+
/** A policy. Identity is `(parent, name)`. */
|
|
464
|
+
export type PolicyObject = CatalogEnvelope<"policy", AnchoredIdentity & {
|
|
465
|
+
readonly kind: "policy";
|
|
466
|
+
}, PolicyDefinition>;
|
|
443
467
|
/**
|
|
444
468
|
* One built catalog object.
|
|
445
469
|
*/
|
|
446
|
-
export type CatalogObject = TableObject | ColumnObject | IndexObject | ConstraintObject | SequenceObject | TypeObject | ExtensionObject | FunctionObject | TriggerObject | ViewObject | MaterializedViewObject | RoleObject | GrantObject | DefaultPrivilegeObject;
|
|
470
|
+
export type CatalogObject = TableObject | ColumnObject | IndexObject | ConstraintObject | SequenceObject | TypeObject | ExtensionObject | FunctionObject | TriggerObject | ViewObject | MaterializedViewObject | RoleObject | GrantObject | DefaultPrivilegeObject | PolicyObject;
|
|
447
471
|
/** Format version stored in the serialized catalog. */
|
|
448
472
|
export declare const CATALOG_VERSION = 1;
|
|
449
473
|
/** A catalog document. Object order is identity-key order. */
|
|
@@ -11,6 +11,8 @@ export type ViewInput = {
|
|
|
11
11
|
readonly name: string;
|
|
12
12
|
readonly columns: readonly ViewColumn[];
|
|
13
13
|
readonly query: string;
|
|
14
|
+
/** `WITH (security_invoker = true)`. Omitted from the record when unset. */
|
|
15
|
+
readonly securityInvoker?: true;
|
|
14
16
|
readonly owner?: Owner;
|
|
15
17
|
readonly provenance: Provenance;
|
|
16
18
|
readonly dependencies?: readonly ObjectIdentity[];
|
|
@@ -14,6 +14,16 @@
|
|
|
14
14
|
* @returns `file.ts:line`, or `undefined` when the runtime has no stack
|
|
15
15
|
*/
|
|
16
16
|
export declare function callerLocation(skip: number): string | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* File and line from stack lines, skipping `location.ts` frames.
|
|
19
|
+
*
|
|
20
|
+
* A frame may use `/` or `\`.
|
|
21
|
+
*
|
|
22
|
+
* @param lines - `Error.stack` split on `\n`
|
|
23
|
+
* @param skip - Callers to pass before the frame that is recorded
|
|
24
|
+
* @returns `file.ts:line`, or `undefined` when no frame remains
|
|
25
|
+
*/
|
|
26
|
+
export declare function locationFromLines(lines: readonly string[], skip: number): string | undefined;
|
|
17
27
|
/**
|
|
18
28
|
* Appends a source location to an error message.
|
|
19
29
|
*
|
|
@@ -207,6 +207,12 @@ export type ColumnState<TValue> = {
|
|
|
207
207
|
} | undefined;
|
|
208
208
|
readonly guarded: boolean;
|
|
209
209
|
readonly hidden: boolean;
|
|
210
|
+
/**
|
|
211
|
+
* Hidden, and allowed in `where` and `orderBy`.
|
|
212
|
+
*
|
|
213
|
+
* Absent otherwise. Not part of the catalog or its hash.
|
|
214
|
+
*/
|
|
215
|
+
readonly filterable?: true;
|
|
210
216
|
/** Redacted in logs, errors, and `inspect()`. Not part of the catalog hash. */
|
|
211
217
|
readonly sensitive: boolean;
|
|
212
218
|
readonly omitWrite: boolean;
|
|
@@ -383,11 +389,16 @@ export declare class ColumnBuilder<TValue, TFlags extends ColumnFlags> {
|
|
|
383
389
|
/**
|
|
384
390
|
* Excludes the column from the default row.
|
|
385
391
|
*
|
|
386
|
-
* A named `select` still returns it. Includes never do.
|
|
392
|
+
* A named `select` still returns it. Includes never do. `where` and
|
|
393
|
+
* `orderBy` refuse it (OKM1120) unless `filterable` is set. `filters()`
|
|
394
|
+
* still refuses it.
|
|
387
395
|
*
|
|
396
|
+
* @param options - `filterable` allows the column in `where` and `orderBy`
|
|
388
397
|
* @returns The same column, hidden
|
|
389
398
|
*/
|
|
390
|
-
hidden(
|
|
399
|
+
hidden(options?: {
|
|
400
|
+
readonly filterable?: boolean;
|
|
401
|
+
}): ColumnBuilder<TValue, FlagTrue<TFlags, "hidden">>;
|
|
391
402
|
/**
|
|
392
403
|
* Redacts the value in logs, errors, and `inspect()`.
|
|
393
404
|
*
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Planning and scratch comparison both render through here, so a statement
|
|
5
5
|
* has one spelling.
|
|
6
6
|
*/
|
|
7
|
-
import type { Catalog, CatalogObject, ColumnObject, FunctionObject, MaterializedViewObject, SequenceObject, TableObject, ViewObject } from "../../contracts/catalog/types.js";
|
|
7
|
+
import type { Catalog, CatalogObject, ColumnObject, FunctionObject, MaterializedViewObject, PolicyObject, SequenceObject, TableObject, ViewObject } from "../../contracts/catalog/types.js";
|
|
8
8
|
/**
|
|
9
9
|
* Quotes one identifier.
|
|
10
10
|
*
|
|
@@ -23,6 +23,18 @@ export declare function quoteIdent(name: string): string;
|
|
|
23
23
|
* @returns SQL statements
|
|
24
24
|
*/
|
|
25
25
|
export declare function renderCatalog(source: Catalog, schema: string): readonly string[];
|
|
26
|
+
/**
|
|
27
|
+
* Pulls a unique constraint in front of a foreign key that references it.
|
|
28
|
+
*
|
|
29
|
+
* The primary key is created with the table. A foreign key aimed at another
|
|
30
|
+
* unique has to wait for that unique. Create order ties those two by name, so
|
|
31
|
+
* the foreign key can otherwise come first. The planner uses this for creates
|
|
32
|
+
* and for the list it reverses when it drops.
|
|
33
|
+
*
|
|
34
|
+
* @param objects - Create order
|
|
35
|
+
* @returns The same objects, with those uniques moved forward
|
|
36
|
+
*/
|
|
37
|
+
export declare function uniqueBeforeForeignKey(objects: readonly CatalogObject[]): readonly CatalogObject[];
|
|
26
38
|
/**
|
|
27
39
|
* Reports whether an index belongs to a view or a materialized view.
|
|
28
40
|
*
|
|
@@ -74,6 +86,30 @@ export declare function functionSql(object: FunctionObject, schema: string, repl
|
|
|
74
86
|
* @returns The statement
|
|
75
87
|
*/
|
|
76
88
|
export declare function viewSql(object: ViewObject, schema: string, replace: boolean): string;
|
|
89
|
+
/** One policy statement and the planner kind that classifies it. */
|
|
90
|
+
export type PolicyPlanStep = {
|
|
91
|
+
readonly sql: string;
|
|
92
|
+
readonly kind: "enable-rls" | "create-policy" | "drop-policy" | "disable-rls";
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* `ENABLE`, `FORCE`, and `CREATE POLICY` for one policy.
|
|
96
|
+
*
|
|
97
|
+
* The `all` command policy also enables and forces row-level security.
|
|
98
|
+
* The `select` policy is the unscoped read. Names are the stored identity.
|
|
99
|
+
*
|
|
100
|
+
* @param object - Policy to create
|
|
101
|
+
* @param schema - Concrete schema name
|
|
102
|
+
* @returns Statements in apply order
|
|
103
|
+
*/
|
|
104
|
+
export declare function policyCreatePlan(object: PolicyObject, schema: string): readonly PolicyPlanStep[];
|
|
105
|
+
/**
|
|
106
|
+
* `DROP POLICY`, and for the `all` command policy `NO FORCE` and `DISABLE`.
|
|
107
|
+
*
|
|
108
|
+
* @param object - Policy to drop
|
|
109
|
+
* @param schema - Concrete schema name
|
|
110
|
+
* @returns Statements in apply order
|
|
111
|
+
*/
|
|
112
|
+
export declare function policyDropPlan(object: PolicyObject, schema: string): readonly PolicyPlanStep[];
|
|
77
113
|
/**
|
|
78
114
|
* `CREATE MATERIALIZED VIEW ... WITH NO DATA`.
|
|
79
115
|
*
|
|
@@ -6,6 +6,14 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { type BuiltSchema } from "./schema.js";
|
|
8
8
|
import { type AnyTable } from "./table.js";
|
|
9
|
+
/**
|
|
10
|
+
* Type arguments read from `t.json<T>()` and `t.jsonb<T>()` in schema source.
|
|
11
|
+
*
|
|
12
|
+
* The key is `table.field`. QA-L3 kept the wrapper for a bare `t.jsonb()`,
|
|
13
|
+
* which has no argument and stays `jsonb<unknown>`. The documented call
|
|
14
|
+
* `t.jsonb<{ published?: boolean }>()` is this map.
|
|
15
|
+
*/
|
|
16
|
+
export type JsonColumnTypes = ReadonlyMap<string, string>;
|
|
9
17
|
/**
|
|
10
18
|
* Emits row, insert, and update interfaces for every table.
|
|
11
19
|
*
|
|
@@ -13,6 +21,16 @@ import { type AnyTable } from "./table.js";
|
|
|
13
21
|
* and `TasksUpdate`.
|
|
14
22
|
*
|
|
15
23
|
* @param source - Schema from {@link schema}
|
|
24
|
+
* @param jsonTypes - Type arguments from the schema source. Omitted, json and jsonb stay `unknown`
|
|
16
25
|
* @returns Declaration text
|
|
17
26
|
*/
|
|
18
|
-
export declare function emitRowTypes(source: BuiltSchema<readonly AnyTable[]
|
|
27
|
+
export declare function emitRowTypes(source: BuiltSchema<readonly AnyTable[]>, jsonTypes?: JsonColumnTypes): string;
|
|
28
|
+
/**
|
|
29
|
+
* Reads `t.json<T>()` and `t.jsonb<T>()` type arguments from schema source.
|
|
30
|
+
*
|
|
31
|
+
* A bare `t.jsonb()` has no argument. The key is the table name and the field.
|
|
32
|
+
*
|
|
33
|
+
* @param source - Schema source, comments removed by the caller or still present
|
|
34
|
+
* @returns `table.field` to the type argument text
|
|
35
|
+
*/
|
|
36
|
+
export declare function jsonColumnTypes(source: string): JsonColumnTypes;
|
|
@@ -2,9 +2,30 @@
|
|
|
2
2
|
* Maps a Postgres {@link DriverError} to an {@link OkmError} (spec §4.2, §14).
|
|
3
3
|
*
|
|
4
4
|
* Adapters normalise the driver into `DriverError`. They do not construct
|
|
5
|
-
* `OkmError`.
|
|
5
|
+
* `OkmError`. `connect()` passes its schema. A reason then comes from the
|
|
6
|
+
* error's columns matched to a catalog object. With no catalog, the
|
|
7
|
+
* constraint name is parsed.
|
|
6
8
|
*/
|
|
9
|
+
import type { Catalog } from "../../contracts/catalog/types.js";
|
|
7
10
|
import { OkmError, type ErrorStatuses } from "../../contracts/error.js";
|
|
11
|
+
/**
|
|
12
|
+
* Catalog and model used to name a unique, foreign key, or check.
|
|
13
|
+
*
|
|
14
|
+
* `connect()` passes the schema it already holds. The reference is enough:
|
|
15
|
+
* matching stays in this module.
|
|
16
|
+
*/
|
|
17
|
+
export type MapPostgresErrorSchema = {
|
|
18
|
+
readonly catalog: Catalog;
|
|
19
|
+
readonly model: Readonly<Record<string, {
|
|
20
|
+
readonly sql: string;
|
|
21
|
+
readonly columns: readonly SqlField[];
|
|
22
|
+
}>>;
|
|
23
|
+
};
|
|
24
|
+
/** One column the reason mapper can turn back into a TypeScript field. */
|
|
25
|
+
type SqlField = {
|
|
26
|
+
readonly field: string;
|
|
27
|
+
readonly sql: string;
|
|
28
|
+
};
|
|
8
29
|
/** Options for {@link mapPostgresError}. */
|
|
9
30
|
export type MapPostgresErrorOptions = {
|
|
10
31
|
/**
|
|
@@ -15,6 +36,15 @@ export type MapPostgresErrorOptions = {
|
|
|
15
36
|
readonly includeValues?: boolean;
|
|
16
37
|
/** Category overrides from `connect({ errors })`. */
|
|
17
38
|
readonly http?: ErrorStatuses;
|
|
39
|
+
/**
|
|
40
|
+
* Schema whose catalog still has the stored name key.
|
|
41
|
+
*
|
|
42
|
+
* Columns in the error select the object. The stored name key is the
|
|
43
|
+
* reason. A composite key that is only the SQL column list becomes the
|
|
44
|
+
* TypeScript fields. With no columns, the stored name key is the reason.
|
|
45
|
+
* An index keeps its full name.
|
|
46
|
+
*/
|
|
47
|
+
readonly schema?: MapPostgresErrorSchema;
|
|
18
48
|
};
|
|
19
49
|
/**
|
|
20
50
|
* Maps a thrown driver error into an {@link OkmError}.
|
|
@@ -28,3 +58,4 @@ export type MapPostgresErrorOptions = {
|
|
|
28
58
|
* @returns A categorised error
|
|
29
59
|
*/
|
|
30
60
|
export declare function mapPostgresError(error: unknown, options?: MapPostgresErrorOptions): OkmError;
|
|
61
|
+
export {};
|
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
* before this module exists.
|
|
6
6
|
*
|
|
7
7
|
* A request key is equality when the value is a scalar and `eq` is allowed.
|
|
8
|
-
* An object value names operators
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* An object value names operators `parse` applies. `sort` is a field name
|
|
9
|
+
* from the sort list. A relation key becomes `has` over the allowlisted fields.
|
|
10
|
+
* A column key wins when the same name is in `allow` and `relations`.
|
|
11
11
|
*/
|
|
12
12
|
import type { ParsedFilters } from "./table.js";
|
|
13
13
|
/**
|
|
@@ -20,6 +20,7 @@ import type { ParsedFilters } from "./table.js";
|
|
|
20
20
|
* @param allow - Fields and the operators each one accepts
|
|
21
21
|
* @param sort - Fields a caller may sort by
|
|
22
22
|
* @param query - One request object
|
|
23
|
+
* @param relations - Relation name to fields, when `filters` passed any
|
|
23
24
|
* @returns Filters a caller can spread into `find`
|
|
24
25
|
*/
|
|
25
|
-
export declare function parseQuery(allow: Readonly<Record<string, readonly string[]>>, sort: readonly string[], query: unknown): ParsedFilters;
|
|
26
|
+
export declare function parseQuery(allow: Readonly<Record<string, readonly string[]>>, sort: readonly string[], query: unknown, relations?: Readonly<Record<string, readonly string[]>>): ParsedFilters;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
functionObject,
|
|
3
3
|
triggerObject
|
|
4
|
-
} from "../../../shared/
|
|
4
|
+
} from "../../../shared/y34a8714.js";
|
|
5
5
|
import {
|
|
6
6
|
staticNamespace2
|
|
7
|
-
} from "../../../shared/
|
|
7
|
+
} from "../../../shared/358zsv4r.js";
|
|
8
8
|
import {
|
|
9
9
|
assertIdentifier2
|
|
10
10
|
} from "../../../shared/nfzc5z0w.js";
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* Each builder is a separate export so a bundle can keep only the ones it calls.
|
|
6
6
|
*/
|
|
7
7
|
export { schema, type BuiltSchema, type SchemaCodecs, type SchemaInput, type SchemaRequires, } from "./schema.js";
|
|
8
|
-
export {
|
|
8
|
+
export { withOwner, type DeclaredOwner } from "./owner.js";
|
|
9
|
+
export { index, sql, table, type AnyTable, type ColumnHandle, type IndexCall, type SqlText, type SqlValue, type FilterOperator, type Table, type TableOptions, } from "./table.js";
|
|
9
10
|
export type { PresetQuery } from "./preset.js";
|
|
10
11
|
export { custom } from "./custom.js";
|
|
11
12
|
export { ColumnBuilder } from "./column.js";
|