okmodel 0.6.0 → 0.7.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 +100 -1131
- package/dist/adapters/capabilities.d.ts +3 -0
- package/dist/adapters/failure.d.ts +13 -2
- package/dist/adapters/lazy-errors.d.ts +22 -0
- package/dist/adapters/pg/bunsql-extra.d.ts +54 -3
- package/dist/adapters/pg/bunsql.d.ts +14 -1
- package/dist/adapters/pg/cursor.d.ts +17 -0
- package/dist/adapters/pg/no-inflight-timeout.d.ts +11 -8
- package/dist/adapters/pg/nodepostgres-extra.d.ts +22 -1
- package/dist/adapters/pg/nodepostgres.d.ts +12 -0
- package/dist/adapters/pg/pglite-wire.d.ts +24 -0
- package/dist/adapters/pg/pglite.d.ts +10 -0
- package/dist/adapters/pg/postgres-extra.d.ts +27 -11
- package/dist/adapters/pg/reserved.d.ts +42 -0
- package/dist/adapters/pg/session.d.ts +0 -18
- package/dist/contracts/connection.d.ts +7 -6
- package/dist/dialects/pg/floor.d.ts +68 -0
- package/dist/dialects/pg/index.d.ts +6 -1
- package/dist/dialects/pg/index.js +49 -159
- package/dist/dialects/pg/keys.d.ts +11 -8
- package/dist/dialects/pg/model.d.ts +40 -0
- package/dist/dialects/pg/morph.d.ts +43 -0
- package/dist/dialects/pg/operator-fit.d.ts +2 -2
- package/dist/dialects/pg/operators.d.ts +14 -7
- package/dist/dialects/pg/ops/bucket.d.ts +65 -0
- package/dist/dialects/pg/ops/inc.d.ts +2 -2
- package/dist/dialects/pg/ops/matches.d.ts +9 -12
- package/dist/dialects/pg/ops/relevance.d.ts +13 -0
- package/dist/dialects/pg/ops/search-query.d.ts +22 -0
- package/dist/dialects/pg/ops/window.d.ts +103 -0
- package/dist/dialects/pg/preset.d.ts +1 -1
- package/dist/dialects/pg/relations.d.ts +100 -3
- package/dist/dialects/pg/schema.d.ts +31 -3
- package/dist/dialects/pg/view/index.js +1 -1
- package/dist/runtime/aggregate.d.ts +8 -2
- package/dist/runtime/bucket-group.d.ts +70 -0
- package/dist/runtime/conflict.d.ts +22 -4
- package/dist/runtime/include.d.ts +0 -8
- package/dist/runtime/inflight.d.ts +1 -1
- package/dist/runtime/page.d.ts +4 -1
- package/dist/runtime/pg/bun.js +12 -6
- package/dist/runtime/pg/pg.js +5 -5
- package/dist/runtime/pg/pglite.d.ts +1 -0
- package/dist/runtime/pg/pglite.js +9 -9
- package/dist/runtime/pg/postgresjs.js +5 -5
- package/dist/runtime/plan.d.ts +95 -5
- package/dist/runtime/read-stream.d.ts +13 -16
- package/dist/runtime/result-name.d.ts +17 -0
- package/dist/runtime/server-check.d.ts +3 -3
- package/dist/runtime/sort-bind.d.ts +21 -0
- package/dist/runtime/sort.d.ts +56 -0
- package/dist/runtime/sync.d.ts +70 -0
- package/dist/runtime/tenancy/index.js +7 -5
- package/dist/runtime/text-search.d.ts +20 -0
- package/dist/runtime/traits/index.d.ts +80 -0
- package/dist/runtime/traits/index.js +175 -11
- package/dist/runtime/tree.d.ts +38 -0
- package/dist/runtime/types.d.ts +218 -22
- package/dist/runtime/validate/index.js +2 -2
- package/dist/runtime/version.d.ts +39 -0
- package/dist/runtime/window.d.ts +21 -0
- package/dist/runtime/write.d.ts +54 -2
- package/dist/shared/{wkme6tep.js → 14vx95q4.js} +8 -16
- package/dist/shared/1est4ezg.js +313 -0
- package/dist/shared/{4az561fn.js → 1qa0qajz.js} +8 -23
- package/dist/shared/{2cg3wnxc.js → 1w508jbr.js} +593 -130
- package/dist/shared/2c13q96h.js +18 -0
- package/dist/shared/{b4v57v3x.js → 2d3xq4ps.js} +2 -2
- package/dist/shared/{1nw1f3vs.js → 2shdbn8q.js} +7 -7
- package/dist/shared/3v7t1yrv.js +208 -0
- package/dist/shared/{x3jc53kg.js → 5e3tf63j.js} +2 -2
- package/dist/shared/5fe3kbsh.js +10 -0
- package/dist/shared/5v3xf80k.js +37 -0
- package/dist/shared/{c58secgj.js → 63qtkrca.js} +38 -4
- package/dist/shared/{2z7wv5tj.js → 67txcrcw.js} +55 -34
- package/dist/shared/79dt02vc.js +12 -0
- package/dist/shared/{8x72s86k.js → 7k9grvf6.js} +10 -4
- package/dist/shared/7kms6fvj.js +20 -0
- package/dist/shared/7mnme5tn.js +8 -0
- package/dist/shared/7n7ddwt4.js +6 -0
- package/dist/shared/{5j36z8dn.js → 81ebdx9p.js} +39 -70
- package/dist/shared/{knmes2kh.js → 8skf0cam.js} +1 -1
- package/dist/shared/9a4ae4p8.js +31 -0
- package/dist/shared/9y3mmmh1.js +436 -0
- package/dist/shared/ab9gmbwy.js +213 -0
- package/dist/shared/{f0f1n281.js → ax7qv55k.js} +2 -2
- package/dist/shared/{g90m9b0g.js → aytqh5y2.js} +6 -5
- package/dist/shared/{vjpnzwjz.js → b5pftnn2.js} +1 -1
- package/dist/shared/{ag4c7516.js → b76b8d95.js} +2 -2
- package/dist/shared/{vmfkhszw.js → bg3rym3g.js} +33 -26
- package/dist/shared/{mb2ycs1p.js → bm22fvzr.js} +15 -15
- package/dist/shared/{q3j1tq7a.js → bz84tkzm.js} +148 -23
- package/dist/shared/{31vm914h.js → cm3w0ywp.js} +15 -16
- package/dist/shared/cn957f8d.js +179 -0
- package/dist/shared/{gwn6v667.js → cnkky55j.js} +25 -14
- package/dist/shared/{ys0xzyaj.js → dkxgzaqd.js} +224 -19
- package/dist/shared/dzj09cye.js +10 -0
- package/dist/shared/exn3sd90.js +359 -0
- package/dist/shared/g6evj1j3.js +66 -0
- package/dist/shared/ga9j92qj.js +25 -0
- package/dist/shared/{t3g0k88x.js → gs74dbj5.js} +16 -12
- package/dist/shared/gzaveazc.js +285 -0
- package/dist/shared/{2jd1sn0e.js → hyh73qk6.js} +1 -1
- package/dist/shared/{r1fdd0f6.js → je4axnm8.js} +5 -2
- package/dist/shared/{1f0xa3cb.js → jvd0mqag.js} +3 -3
- package/dist/shared/jznfax0y.js +155 -0
- package/dist/shared/{cgbamx3e.js → kb2sdhfb.js} +7 -4
- package/dist/shared/{wt5rzv1h.js → kr0jzbw2.js} +5 -5
- package/dist/shared/{p6bjzq9q.js → ktz42yez.js} +12 -4
- package/dist/shared/{p248q79y.js → m6p12kbr.js} +2 -2
- package/dist/shared/{r6nwkxnt.js → m7n9h2a5.js} +4 -4
- package/dist/shared/{672t5vym.js → mss6ctgv.js} +2 -2
- package/dist/shared/{929h19xp.js → mtaszv5a.js} +40 -10
- package/dist/shared/{b3awxn7h.js → n816peh1.js} +1 -1
- package/dist/shared/nbw1z4yd.js +18 -0
- package/dist/shared/{nx9hh281.js → p6qc5gcp.js} +12 -11
- package/dist/shared/{pjr6xrm5.js → pbp1ss85.js} +20 -17
- package/dist/shared/pt94kz7f.js +6 -0
- package/dist/shared/q5c6ngn3.js +13 -0
- package/dist/shared/{xq0mvhts.js → rs73fca9.js} +4 -4
- package/dist/shared/{r11n8grd.js → sfz1ksn6.js} +7 -4
- package/dist/shared/{wynzeggs.js → svncdeh5.js} +6 -6
- package/dist/shared/{j60w0dvr.js → tbrvgw6z.js} +57 -38
- package/dist/shared/te5as7z7.js +622 -0
- package/dist/shared/{ttmg09vd.js → tsvww22q.js} +1 -1
- package/dist/shared/{y2t3jktd.js → ttsqgp4p.js} +19 -12
- package/dist/shared/{x72jb7ad.js → v8g1vgv8.js} +1 -1
- package/dist/shared/{sbdme3vy.js → vb6qfyve.js} +60 -10
- package/dist/shared/{5d8t84hg.js → vczs8gd4.js} +14 -14
- package/dist/shared/{5yv4k6a6.js → vqrjpcqn.js} +144 -2
- package/dist/shared/{3fqwmr09.js → w72kgg4q.js} +4 -4
- package/dist/shared/{1z04fa85.js → w79hsckn.js} +12 -57
- package/dist/shared/{09p049xa.js → wa07eas9.js} +42 -14
- package/dist/shared/{32cnm7kn.js → x933k9a3.js} +74 -38
- package/dist/shared/{n076ydsc.js → xhfsfkgk.js} +62 -28
- package/dist/shared/xjk7hnn5.js +272 -0
- package/dist/shared/{hazqqecq.js → xnxsed62.js} +50 -21
- package/dist/shared/y6njgyda.js +249 -0
- package/dist/shared/{8etn7d8w.js → z7s6fpxv.js} +1 -1
- package/dist/shared/{n7mcc1gk.js → zchaghkf.js} +4 -3
- package/dist/shared/zm0ptry0.js +40 -0
- package/dist/shared/{nsva2a6b.js → znm0bpp5.js} +3 -0
- package/dist/shared/zp9fmend.js +145 -0
- package/dist/tooling/cli.js +11 -11
- package/dist/tooling/migrate/engine.d.ts +3 -2
- package/dist/tooling/migrate/index.js +7 -7
- package/dist/tooling/testing/index.js +1 -1
- package/package.json +4 -2
- package/dist/shared/3qnhc7w5.js +0 -38
- package/dist/shared/7m88x3e9.js +0 -45
- package/dist/shared/8dqhth8c.js +0 -12
- package/dist/shared/d5azex6s.js +0 -6
- package/dist/shared/j3rkk835.js +0 -99
- package/dist/shared/k68eedmy.js +0 -85
- package/dist/shared/venqrjna.js +0 -216
- package/dist/shared/wxr8cwns.js +0 -6
- package/dist/shared/zm0mafk4.js +0 -92
|
@@ -2,7 +2,7 @@ import"../../shared/qq3899ht.js";
|
|
|
2
2
|
import {
|
|
3
3
|
checkPresetNames,
|
|
4
4
|
duplicatePreset
|
|
5
|
-
} from "../../shared/
|
|
5
|
+
} from "../../shared/znm0bpp5.js";
|
|
6
6
|
import {
|
|
7
7
|
checkTrait
|
|
8
8
|
} from "../../shared/n0dgs0pb.js";
|
|
@@ -17,11 +17,12 @@ import {
|
|
|
17
17
|
triggerObject
|
|
18
18
|
} from "../../shared/y34a8714.js";
|
|
19
19
|
import {
|
|
20
|
+
integer2,
|
|
20
21
|
timestamptz2
|
|
21
|
-
} from "../../shared/
|
|
22
|
+
} from "../../shared/vqrjpcqn.js";
|
|
22
23
|
import {
|
|
23
24
|
uuid2
|
|
24
|
-
} from "../../shared/
|
|
25
|
+
} from "../../shared/hyh73qk6.js";
|
|
25
26
|
import {
|
|
26
27
|
snakeCase
|
|
27
28
|
} from "../../shared/rpycarcr.js";
|
|
@@ -41,10 +42,12 @@ import {
|
|
|
41
42
|
queryHandle,
|
|
42
43
|
attachHttp,
|
|
43
44
|
settleCall
|
|
44
|
-
} from "../../shared/
|
|
45
|
+
} from "../../shared/tbrvgw6z.js";
|
|
45
46
|
import {
|
|
46
|
-
installArchiveInspect
|
|
47
|
-
|
|
47
|
+
installArchiveInspect,
|
|
48
|
+
indexes,
|
|
49
|
+
isRecord
|
|
50
|
+
} from "../../shared/67txcrcw.js";
|
|
48
51
|
import {
|
|
49
52
|
fitIdentifier2
|
|
50
53
|
} from "../../shared/nfzc5z0w.js";
|
|
@@ -465,13 +468,13 @@ function refuse(host, table) {
|
|
|
465
468
|
}
|
|
466
469
|
var archiveMod;
|
|
467
470
|
function loadArchive() {
|
|
468
|
-
archiveMod ??= import("../../shared/
|
|
471
|
+
archiveMod ??= import("../../shared/bm22fvzr.js");
|
|
469
472
|
return archiveMod;
|
|
470
473
|
}
|
|
471
474
|
async function settle(host, table, mods) {
|
|
472
475
|
if (mods.uses === undefined)
|
|
473
476
|
return mods;
|
|
474
|
-
const { resolve } = await import("../../shared/
|
|
477
|
+
const { resolve } = await import("../../shared/m7n9h2a5.js");
|
|
475
478
|
return { ...mods, presets: resolve(host.schema, table, mods.uses).wheres };
|
|
476
479
|
}
|
|
477
480
|
async function run(host, op, table, input, options, mods) {
|
|
@@ -484,6 +487,93 @@ async function run(host, op, table, input, options, mods) {
|
|
|
484
487
|
}
|
|
485
488
|
}
|
|
486
489
|
|
|
490
|
+
// src/runtime/sort-bind.ts
|
|
491
|
+
function rewriteSortable(self, tables, casing, schemaTraits, group) {
|
|
492
|
+
return tables.map((item) => {
|
|
493
|
+
if (!applies2(self, item, schemaTraits))
|
|
494
|
+
return item;
|
|
495
|
+
refusePath(item);
|
|
496
|
+
return withIndex(item, casing, schemaTraits, group);
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
function applies2(self, item, schemaTraits) {
|
|
500
|
+
const options = item.options;
|
|
501
|
+
const own = Array.isArray(options?.traits) ? options.traits : [];
|
|
502
|
+
if (own.includes(self))
|
|
503
|
+
return true;
|
|
504
|
+
if (options?.omitDefaults !== undefined)
|
|
505
|
+
return false;
|
|
506
|
+
return schemaTraits?.includes(self) ?? false;
|
|
507
|
+
}
|
|
508
|
+
function refusePath(item) {
|
|
509
|
+
const tenancy = item.options?.tenancy;
|
|
510
|
+
if (typeof tenancy === "object" && tenancy !== null && "via" in tenancy) {
|
|
511
|
+
definition(`sortable() on ${item.name} does not combine with via(). Position needs the tenant columns on the row.`);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
function withIndex(item, casing, schemaTraits, group) {
|
|
515
|
+
const options = item.options;
|
|
516
|
+
const prior = options?.indexes;
|
|
517
|
+
const tenantKeys = options?.tenantKeys ?? [];
|
|
518
|
+
const fields = [];
|
|
519
|
+
for (const field of tenantKeys)
|
|
520
|
+
if (!fields.includes(field))
|
|
521
|
+
fields.push(field);
|
|
522
|
+
if (group !== undefined && !fields.includes(group))
|
|
523
|
+
fields.push(group);
|
|
524
|
+
fields.push("position");
|
|
525
|
+
const predicate = archivedPredicate(item, casing, schemaTraits);
|
|
526
|
+
const indexes = (handles) => {
|
|
527
|
+
const calls = prior === undefined ? [] : prior(handles);
|
|
528
|
+
const columns = fields.map((field) => {
|
|
529
|
+
const handle = handles[field];
|
|
530
|
+
if (handle === undefined) {
|
|
531
|
+
definition(`sortable() on ${item.name} needs a column named ${field}.`);
|
|
532
|
+
}
|
|
533
|
+
return handle.name;
|
|
534
|
+
});
|
|
535
|
+
return [...Array.isArray(calls) ? calls : [], uniqueIndex(columns, predicate)];
|
|
536
|
+
};
|
|
537
|
+
return {
|
|
538
|
+
...item,
|
|
539
|
+
options: { ...options, indexes }
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
function archivedPredicate(item, casing, schemaTraits) {
|
|
543
|
+
if (!archivable(item, schemaTraits))
|
|
544
|
+
return;
|
|
545
|
+
return casing === "snake" ? "(archived_at IS NULL)" : '("archivedAt" IS NULL)';
|
|
546
|
+
}
|
|
547
|
+
function archivable(item, schemaTraits) {
|
|
548
|
+
const options = item.options;
|
|
549
|
+
const own = Array.isArray(options?.traits) ? options.traits : [];
|
|
550
|
+
for (const trait of own)
|
|
551
|
+
if (marked2(trait))
|
|
552
|
+
return true;
|
|
553
|
+
if (options?.omitDefaults !== undefined)
|
|
554
|
+
return false;
|
|
555
|
+
if (schemaTraits === undefined)
|
|
556
|
+
return false;
|
|
557
|
+
for (const trait of schemaTraits)
|
|
558
|
+
if (marked2(trait))
|
|
559
|
+
return true;
|
|
560
|
+
return false;
|
|
561
|
+
}
|
|
562
|
+
function marked2(value) {
|
|
563
|
+
return value["~archive"] === true;
|
|
564
|
+
}
|
|
565
|
+
function uniqueIndex(columns, predicate) {
|
|
566
|
+
const call = {
|
|
567
|
+
columns,
|
|
568
|
+
isUnique: true,
|
|
569
|
+
...predicate !== undefined ? { predicate } : {},
|
|
570
|
+
unique() {
|
|
571
|
+
return call;
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
return call;
|
|
575
|
+
}
|
|
576
|
+
|
|
487
577
|
// src/runtime/traits/index.ts
|
|
488
578
|
function trait(name, input) {
|
|
489
579
|
if (input.presets !== undefined)
|
|
@@ -561,7 +651,7 @@ function timestamps(options) {
|
|
|
561
651
|
function stamped() {
|
|
562
652
|
return timestamptz2().defaultSql("now()").guarded();
|
|
563
653
|
}
|
|
564
|
-
function
|
|
654
|
+
function archivable2(options) {
|
|
565
655
|
installArchiveContributions();
|
|
566
656
|
const cascade = readCascade(options);
|
|
567
657
|
const base = trait("archivable", {
|
|
@@ -585,6 +675,78 @@ function archivable(options) {
|
|
|
585
675
|
};
|
|
586
676
|
return self;
|
|
587
677
|
}
|
|
678
|
+
function versioned() {
|
|
679
|
+
return trait("versioned", {
|
|
680
|
+
fields: {
|
|
681
|
+
version: integer2().defaultSql("1").guarded()
|
|
682
|
+
},
|
|
683
|
+
sealed: ["version"]
|
|
684
|
+
});
|
|
685
|
+
}
|
|
686
|
+
function sortable(groupBy) {
|
|
687
|
+
if (groupBy !== undefined && groupBy.length === 0) {
|
|
688
|
+
definition("sortable() groupBy must be a column name.");
|
|
689
|
+
}
|
|
690
|
+
if (groupBy === "position")
|
|
691
|
+
definition("sortable() cannot group by position.");
|
|
692
|
+
const base = trait("sortable", {
|
|
693
|
+
fields: {
|
|
694
|
+
position: integer2().guarded()
|
|
695
|
+
},
|
|
696
|
+
sealed: ["position"]
|
|
697
|
+
});
|
|
698
|
+
const self = {
|
|
699
|
+
...base,
|
|
700
|
+
...groupBy !== undefined ? { group: groupBy } : {},
|
|
701
|
+
"~sort": true,
|
|
702
|
+
apply(model, ctx) {
|
|
703
|
+
if (groupBy !== undefined && !Object.hasOwn(model.columns, groupBy)) {
|
|
704
|
+
definition(`sortable() on ${ctx.table} needs a column named ${groupBy}.`);
|
|
705
|
+
}
|
|
706
|
+
base.apply(model, ctx);
|
|
707
|
+
},
|
|
708
|
+
rewrite(tables, casing, schemaTraits) {
|
|
709
|
+
return rewriteSortable(self, tables, casing, schemaTraits, groupBy);
|
|
710
|
+
},
|
|
711
|
+
hook: attachSort
|
|
712
|
+
};
|
|
713
|
+
return self;
|
|
714
|
+
}
|
|
715
|
+
function attachSort(target, ctx) {
|
|
716
|
+
const tableName = ctx.table;
|
|
717
|
+
const session = ctx.session;
|
|
718
|
+
if (tableName === undefined || session === undefined)
|
|
719
|
+
return;
|
|
720
|
+
const host = session;
|
|
721
|
+
const table = indexes(host.schema).get(tableName);
|
|
722
|
+
if (table === undefined)
|
|
723
|
+
return;
|
|
724
|
+
let sortableTable = false;
|
|
725
|
+
for (const item of table.model.traits ?? []) {
|
|
726
|
+
if (item.name === "sortable")
|
|
727
|
+
sortableTable = true;
|
|
728
|
+
}
|
|
729
|
+
if (!sortableTable)
|
|
730
|
+
return;
|
|
731
|
+
const order = { position: "asc" };
|
|
732
|
+
for (const field of table.model.primary) {
|
|
733
|
+
if (field !== "position")
|
|
734
|
+
order[field] = "asc";
|
|
735
|
+
}
|
|
736
|
+
wrapOrder(target, "find", order);
|
|
737
|
+
wrapOrder(target, "page", order);
|
|
738
|
+
const view = ctx.view;
|
|
739
|
+
target.move = (id, place) => import("../../shared/9y3mmmh1.js").then((mod) => mod.move(host, tableName, id, place, view));
|
|
740
|
+
}
|
|
741
|
+
function wrapOrder(target, key, order) {
|
|
742
|
+
const previous = target[key];
|
|
743
|
+
if (typeof previous !== "function")
|
|
744
|
+
return;
|
|
745
|
+
target[key] = (options = {}) => {
|
|
746
|
+
const next = isRecord(options) && options.orderBy !== undefined ? options : { ...options, orderBy: order };
|
|
747
|
+
return previous.call(target, next);
|
|
748
|
+
};
|
|
749
|
+
}
|
|
588
750
|
function readCascade(options) {
|
|
589
751
|
if (options === undefined)
|
|
590
752
|
return [];
|
|
@@ -647,7 +809,9 @@ function addFields(name, fields, model, ctx) {
|
|
|
647
809
|
}
|
|
648
810
|
}
|
|
649
811
|
export {
|
|
650
|
-
archivable,
|
|
812
|
+
archivable2 as archivable,
|
|
813
|
+
sortable,
|
|
651
814
|
timestamps,
|
|
652
|
-
trait
|
|
815
|
+
trait,
|
|
816
|
+
versioned
|
|
653
817
|
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `descendants` and `ancestors` (spec §13 tool 11).
|
|
3
|
+
*
|
|
4
|
+
* One recursive statement walks a self-relation's parent column. A row already
|
|
5
|
+
* on the path is not entered again, so a cycle in the data returns. `depth`
|
|
6
|
+
* stops the walk earlier. `ltree` is not read: the extension is a later index,
|
|
7
|
+
* and this statement does not require it.
|
|
8
|
+
*
|
|
9
|
+
* Tenancy and the active set apply on the start row, on every step, and on
|
|
10
|
+
* the rows that come back. `where` and presets filter those rows and do not
|
|
11
|
+
* cut the walk short. A missing id returns no rows, including with `self`.
|
|
12
|
+
* The root has no ancestors. Loaded on the first call.
|
|
13
|
+
*/
|
|
14
|
+
import type { ColumnModel } from "../dialects/pg/model.js";
|
|
15
|
+
import { type Mods, type Session } from "./client.js";
|
|
16
|
+
import { type ArchiveView, type Indexed } from "./plan.js";
|
|
17
|
+
/**
|
|
18
|
+
* Builds the handle for one `descendants` or `ancestors` call.
|
|
19
|
+
*
|
|
20
|
+
* @param session - Client session
|
|
21
|
+
* @param table - Table name
|
|
22
|
+
* @param options - The packed call: the id, the direction, and the caller's options
|
|
23
|
+
* @param mods - Presets, signal, and timeout
|
|
24
|
+
* @param view - Archive visibility
|
|
25
|
+
* @returns A handle that resolves to the walked rows
|
|
26
|
+
*/
|
|
27
|
+
export declare function build(session: Session, table: string, options: object, mods: Mods, view: ArchiveView | undefined): Promise<unknown> & Record<string, unknown>;
|
|
28
|
+
/**
|
|
29
|
+
* The primary key the caller passes, without the tenant key.
|
|
30
|
+
*
|
|
31
|
+
* A tree walk and `sync` both address one column. A composite key beside the
|
|
32
|
+
* tenant key is refused.
|
|
33
|
+
*
|
|
34
|
+
* @param session - Client session, for the tenant key
|
|
35
|
+
* @param table - The table
|
|
36
|
+
* @returns That column
|
|
37
|
+
*/
|
|
38
|
+
export declare function identityColumn(session: Session, table: Indexed): ColumnModel;
|
package/dist/runtime/types.d.ts
CHANGED
|
@@ -7,8 +7,10 @@
|
|
|
7
7
|
import type { DriverTimeouts, Notice } from "../contracts/driver.js";
|
|
8
8
|
import type { SafeResult } from "../contracts/error.js";
|
|
9
9
|
import type { QuerySchema } from "../dialects/pg/model.js";
|
|
10
|
+
import type { Bucket } from "../dialects/pg/ops/bucket.js";
|
|
11
|
+
import type { Window } from "../dialects/pg/ops/window.js";
|
|
10
12
|
import type { Inc } from "../dialects/pg/ops/inc.js";
|
|
11
|
-
import type { ArrAppend, ArrRemove, JsonSet, Or, RelationFilter } from "../dialects/pg/operators.js";
|
|
13
|
+
import type { ArrAppend, ArrRemove, JsonSet, Or, RelationFilter, Relevance, SearchMatch } from "../dialects/pg/operators.js";
|
|
12
14
|
import type { FieldWhere, IsJsonObject } from "../dialects/pg/where.js";
|
|
13
15
|
import type { AppliedRule, ReadOp } from "./plan.js";
|
|
14
16
|
export type { FieldWhere, WhereValue } from "../dialects/pg/where.js";
|
|
@@ -22,8 +24,20 @@ export type RelationsOf<S extends QuerySchema, K extends keyof S["~byName"]> = S
|
|
|
22
24
|
} ? R : Record<string, never>;
|
|
23
25
|
/** Array and JSON writes the column value type can accept. */
|
|
24
26
|
type WriteOp<V> = [unknown] extends [V] ? JsonSet<unknown> | ArrAppend<unknown> | ArrRemove<unknown> : (V extends readonly (infer E)[] ? ArrAppend<E> | ArrRemove<E> : never) | (IsJsonObject<V> extends true ? JsonSet<unknown> : never);
|
|
25
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* `inc` on a number or bigint column.
|
|
29
|
+
*
|
|
30
|
+
* A `string` column is not included. `text` is a string, and so is `numeric`
|
|
31
|
+
* or `bigint` when the codec keeps the decimal text. The statement still
|
|
32
|
+
* accepts `inc` on a numeric database type.
|
|
33
|
+
*/
|
|
34
|
+
type IncOf<V> = [unknown] extends [V] ? Inc<number> | Inc<bigint> : [NonNullable<V>] extends [number] ? Inc<number> : [NonNullable<V>] extends [bigint] ? Inc<bigint> : never;
|
|
35
|
+
/** `has`, `none`, and `every` against the related row. A morph include is not a filter. */
|
|
26
36
|
export type RelFilter<S extends QuerySchema, Rel> = Rel extends {
|
|
37
|
+
readonly morph: {
|
|
38
|
+
readonly targets: readonly string[];
|
|
39
|
+
};
|
|
40
|
+
} ? never : Rel extends {
|
|
27
41
|
readonly table: infer T extends string;
|
|
28
42
|
} ? T extends keyof S["~byName"] ? RelationFilter<"has" | "none" | "every", FieldWhere<RowOf<S, T>>> : never : never;
|
|
29
43
|
/** Known relation names. A string index (no declared relations) adds none. */
|
|
@@ -39,14 +53,34 @@ export type OrderBy<Row> = {
|
|
|
39
53
|
readonly [K in keyof Row]?: "asc" | "desc" | {
|
|
40
54
|
readonly dir: "asc" | "desc";
|
|
41
55
|
readonly nulls?: "first" | "last";
|
|
42
|
-
} | undefined;
|
|
56
|
+
} | Relevance | undefined;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Text to look for.
|
|
60
|
+
*
|
|
61
|
+
* A string is enough when the table has one column built for search. `in`
|
|
62
|
+
* names the column when it has more than one.
|
|
63
|
+
*/
|
|
64
|
+
export type TextSearch<Row> = string | {
|
|
65
|
+
/** Text to look for. */
|
|
66
|
+
readonly for: string;
|
|
67
|
+
/** Column to search. Required when the table has more than one. */
|
|
68
|
+
readonly in?: keyof Row & string;
|
|
69
|
+
/** How to match. Omitted means `natural`. */
|
|
70
|
+
readonly match?: SearchMatch;
|
|
71
|
+
/** Text search language, such as `english`. Omitted uses the database default. */
|
|
72
|
+
readonly language?: string;
|
|
43
73
|
};
|
|
44
74
|
type Related<S extends QuerySchema, T extends keyof S["~byName"], Opt> = Opt extends {
|
|
45
75
|
readonly select: infer Sel;
|
|
46
76
|
} ? Selected<RowOf<S, T>, Sel> : RowOf<S, T>;
|
|
47
|
-
/** One include. To-many needs `limit`. */
|
|
77
|
+
/** One include. To-many needs `limit`. A morph include is `true`. */
|
|
48
78
|
export type IncludeOf<S extends QuerySchema, K extends keyof S["~byName"]> = {
|
|
49
79
|
readonly [R in RelationKeys<RelationsOf<S, K>>]?: RelationsOf<S, K>[R] extends {
|
|
80
|
+
readonly morph: {
|
|
81
|
+
readonly targets: readonly string[];
|
|
82
|
+
};
|
|
83
|
+
} ? true : RelationsOf<S, K>[R] extends {
|
|
50
84
|
readonly kind: "many";
|
|
51
85
|
readonly table: infer T extends string;
|
|
52
86
|
} ? T extends keyof S["~byName"] ? {
|
|
@@ -63,14 +97,40 @@ export type IncludeOf<S extends QuerySchema, K extends keyof S["~byName"]> = {
|
|
|
63
97
|
readonly orderBy?: OrderBy<RowOf<S, T>>;
|
|
64
98
|
} : never : never;
|
|
65
99
|
};
|
|
100
|
+
/**
|
|
101
|
+
* Rows a morph include can return.
|
|
102
|
+
*
|
|
103
|
+
* Each target's row, plus the type field set to that table name, or null when
|
|
104
|
+
* the target row is missing.
|
|
105
|
+
*/
|
|
106
|
+
/** Flattens an intersection so a morph arm is one object type. */
|
|
107
|
+
type Flat<T> = {
|
|
108
|
+
readonly [K in keyof T]: T[K];
|
|
109
|
+
};
|
|
110
|
+
/** One arm of a morph union. Distributes over the closed target list. */
|
|
111
|
+
type MorphArm<S extends QuerySchema, T extends string, Field extends string> = T extends keyof S["~byName"] ? Flat<RowOf<S, T> & {
|
|
112
|
+
readonly [P in Field]: T;
|
|
113
|
+
}> : never;
|
|
114
|
+
type MorphUnion<S extends QuerySchema, Targets extends readonly string[], Field extends string> = MorphArm<S, Targets[number], Field> | null;
|
|
66
115
|
/** Columns kept by `select`. The full row when `select` is omitted. */
|
|
67
116
|
export type Selected<Row, Sel> = [Sel] extends [readonly (infer P)[]] ? [P] extends [keyof Row] ? {
|
|
68
117
|
readonly [K in P & keyof Row]: Row[K];
|
|
69
|
-
} : Row : Row;
|
|
118
|
+
} : boolean extends HasWindow<P> ? Pick<Row, Extract<P, keyof Row>> & WindowFields<Row, P> : [P] extends [Window<string, string | number>] ? WindowFields<Row, P> : Row : Row;
|
|
119
|
+
/** `true` when a select entry is a window. A mix of fields and windows is `boolean`. */
|
|
120
|
+
type HasWindow<P> = P extends Window<string, string | number> ? true : false;
|
|
121
|
+
/** Result keys a window helper adds. A field name contributes nothing. */
|
|
122
|
+
type WindowFields<Row, P> = Intersect<P extends Window<infer A, infer V> ? {
|
|
123
|
+
readonly [K in A]: V extends keyof Row ? NonNullable<Row[V]> | null : number;
|
|
124
|
+
} : {}>;
|
|
70
125
|
type IncludeRows<S extends QuerySchema, K extends keyof S["~byName"], Inc> = [Inc] extends [
|
|
71
126
|
Record<string, unknown>
|
|
72
127
|
] ? {
|
|
73
128
|
readonly [R in keyof Inc & keyof RelationsOf<S, K>]: RelationsOf<S, K>[R] extends {
|
|
129
|
+
readonly morph: {
|
|
130
|
+
readonly targets: infer Targets extends readonly string[];
|
|
131
|
+
readonly typeField: infer Field extends string;
|
|
132
|
+
};
|
|
133
|
+
} ? MorphUnion<S, Targets, Field> : RelationsOf<S, K>[R] extends {
|
|
74
134
|
readonly kind: "many";
|
|
75
135
|
readonly table: infer T extends keyof S["~byName"];
|
|
76
136
|
} ? readonly Related<S, T, Inc[R]>[] : RelationsOf<S, K>[R] extends {
|
|
@@ -109,7 +169,8 @@ export type CallOptions = {
|
|
|
109
169
|
/** Options shared by reads. */
|
|
110
170
|
export type ReadOptions<S extends QuerySchema, K extends keyof S["~byName"]> = CallOptions & {
|
|
111
171
|
readonly where?: WhereOf<S, K>;
|
|
112
|
-
|
|
172
|
+
/** Field names, or a window helper (`rowNumber`, `rank`, `denseRank`, `runningTotal`). */
|
|
173
|
+
readonly select?: readonly ((keyof RowOf<S, K> & string) | Window<string, string | number>)[];
|
|
113
174
|
readonly orderBy?: OrderBy<RowOf<S, K>>;
|
|
114
175
|
readonly include?: IncludeOf<S, K>;
|
|
115
176
|
};
|
|
@@ -118,6 +179,7 @@ export type ReadOptions<S extends QuerySchema, K extends keyof S["~byName"]> = C
|
|
|
118
179
|
*
|
|
119
180
|
* `wait` says what happens when a row is locked by another transaction: `nowait`
|
|
120
181
|
* fails at once (kind `lock_timeout`) and `skip` leaves that row out.
|
|
182
|
+
* `lock: "skip"` is not a read lock. It claims rows on `update`.
|
|
121
183
|
*/
|
|
122
184
|
export type LockOptions = {
|
|
123
185
|
readonly lock?: "update" | "share";
|
|
@@ -126,6 +188,48 @@ export type LockOptions = {
|
|
|
126
188
|
/** `find` options. `limit` is required unless the caller uses `.all(reason)`. */
|
|
127
189
|
export type FindOptions<S extends QuerySchema, K extends keyof S["~byName"]> = ReadOptions<S, K> & {
|
|
128
190
|
readonly limit?: number;
|
|
191
|
+
/** Text to look for. The closest matches come first unless `orderBy` is set. */
|
|
192
|
+
readonly search?: TextSearch<RowOf<S, K>>;
|
|
193
|
+
};
|
|
194
|
+
/**
|
|
195
|
+
* Options for `descendants` and `ancestors`.
|
|
196
|
+
*
|
|
197
|
+
* `depth` is how many steps from the starting row. Omit it to walk the whole
|
|
198
|
+
* tree. `self` includes that row. `relation` names which self-relation when
|
|
199
|
+
* the table has more than one.
|
|
200
|
+
*/
|
|
201
|
+
export type TreeOptions<S extends QuerySchema, K extends keyof S["~byName"]> = CallOptions & {
|
|
202
|
+
readonly where?: WhereOf<S, K>;
|
|
203
|
+
readonly select?: readonly (keyof RowOf<S, K> & string)[];
|
|
204
|
+
readonly orderBy?: OrderBy<RowOf<S, K>>;
|
|
205
|
+
readonly depth?: number;
|
|
206
|
+
/** Include the starting row. Omitted leaves it out. */
|
|
207
|
+
readonly self?: boolean;
|
|
208
|
+
/** Which self-relation. Required when the table has more than one. */
|
|
209
|
+
readonly relation?: string;
|
|
210
|
+
};
|
|
211
|
+
/** Links `sync` added and removed. Values are the related row's primary key. */
|
|
212
|
+
export type SyncResult = {
|
|
213
|
+
readonly added: readonly unknown[];
|
|
214
|
+
readonly removed: readonly unknown[];
|
|
215
|
+
};
|
|
216
|
+
/** Options for `sync`. `expect` matches an update: the count is links added plus links removed. */
|
|
217
|
+
export type SyncOptions = CallOptions & {
|
|
218
|
+
readonly expect?: number;
|
|
219
|
+
};
|
|
220
|
+
/** The handle `sync` returns. */
|
|
221
|
+
export type SyncHandle = Promise<SyncResult> & {
|
|
222
|
+
/** The statement, before it runs. */
|
|
223
|
+
sql(): Promise<{
|
|
224
|
+
readonly statements: readonly {
|
|
225
|
+
readonly text: string;
|
|
226
|
+
readonly params?: readonly (string | null)[];
|
|
227
|
+
}[];
|
|
228
|
+
}>;
|
|
229
|
+
/** `{ ok, value }` or `{ ok, error }`. */
|
|
230
|
+
safe(): Promise<SafeResult<SyncResult>>;
|
|
231
|
+
/** Throws `not_found` when the number of added and removed links is not `count`. */
|
|
232
|
+
expect(count: number): SyncHandle;
|
|
129
233
|
};
|
|
130
234
|
/** A query handle. Await it, or inspect it before it runs. */
|
|
131
235
|
export type Query<T> = Promise<T> & {
|
|
@@ -148,15 +252,27 @@ export type Read<T> = Query<T> & {
|
|
|
148
252
|
all(reason: string): Read<T>;
|
|
149
253
|
/** Turns a null `one()` into `not_found`. */
|
|
150
254
|
required(): Read<NonNullable<T>>;
|
|
151
|
-
/**
|
|
152
|
-
|
|
255
|
+
/**
|
|
256
|
+
* Yields rows in keyset batches on every driver.
|
|
257
|
+
*
|
|
258
|
+
* `batch` is how many rows one query fetches. The default is 1000.
|
|
259
|
+
* `limit` on the find is the total. A table with no primary key is OKM1120.
|
|
260
|
+
*/
|
|
261
|
+
stream(options?: {
|
|
262
|
+
readonly batch?: number;
|
|
263
|
+
}): AsyncIterable<T extends readonly (infer R)[] ? R : T>;
|
|
153
264
|
};
|
|
154
265
|
/** One page: the rows, and the cursor for the next page. `next` is `null` on the last page. */
|
|
155
266
|
export type Page<Row> = {
|
|
156
267
|
readonly items: readonly Row[];
|
|
157
268
|
readonly next: string | null;
|
|
158
269
|
};
|
|
159
|
-
/**
|
|
270
|
+
/**
|
|
271
|
+
* `page` options. `after` is the `next` of the page before.
|
|
272
|
+
*
|
|
273
|
+
* `page` refuses a window helper when the call runs (OKM1120). The keyset
|
|
274
|
+
* cursor has no window value to encode.
|
|
275
|
+
*/
|
|
160
276
|
export type PageOptions<S extends QuerySchema, K extends keyof S["~byName"]> = ReadOptions<S, K> & {
|
|
161
277
|
/** Rows in the page. At least 1. */
|
|
162
278
|
readonly limit: number;
|
|
@@ -172,25 +288,51 @@ export type PageOptions<S extends QuerySchema, K extends keyof S["~byName"]> = R
|
|
|
172
288
|
type NumericKeys<Row> = {
|
|
173
289
|
readonly [F in keyof Row]-?: [NonNullable<Row[F]>] extends [number | string] ? F : never;
|
|
174
290
|
}[keyof Row] & string;
|
|
291
|
+
/** One `orderBy` value. `asc` is nulls last and `desc` is nulls first unless `nulls` is set. */
|
|
292
|
+
type SortDir = "asc" | "desc" | {
|
|
293
|
+
readonly dir: "asc" | "desc";
|
|
294
|
+
readonly nulls?: "first" | "last";
|
|
295
|
+
};
|
|
175
296
|
/** `aggregate` options. A hidden field is refused at runtime. */
|
|
176
297
|
export type AggregateOptions<S extends QuerySchema, K extends keyof S["~byName"]> = CallOptions & {
|
|
177
298
|
readonly where?: WhereOf<S, K>;
|
|
178
299
|
/** One result row per distinct combination. Needs `limit`, or `.all(reason)`. */
|
|
179
|
-
readonly groupBy?: readonly (keyof RowOf<S, K> & string)[];
|
|
300
|
+
readonly groupBy?: readonly ((keyof RowOf<S, K> & string) | Bucket<string, string, string>)[];
|
|
180
301
|
/** Adds `count`, the number of rows in the group. */
|
|
181
302
|
readonly count?: true;
|
|
182
303
|
readonly sum?: readonly NumericKeys<RowOf<S, K>>[];
|
|
183
304
|
readonly avg?: readonly NumericKeys<RowOf<S, K>>[];
|
|
184
305
|
readonly min?: readonly (keyof RowOf<S, K> & string)[];
|
|
185
306
|
readonly max?: readonly (keyof RowOf<S, K> & string)[];
|
|
186
|
-
/**
|
|
187
|
-
|
|
307
|
+
/**
|
|
308
|
+
* Orders the groups. A `groupBy` field or a bucket `as`.
|
|
309
|
+
* Without it, groups come in `groupBy` order.
|
|
310
|
+
*/
|
|
311
|
+
readonly orderBy?: OrderBy<RowOf<S, K>> | {
|
|
312
|
+
readonly [key: string]: SortDir | undefined;
|
|
313
|
+
};
|
|
188
314
|
readonly limit?: number;
|
|
189
315
|
};
|
|
316
|
+
/** `true` when a group entry is a bucket. A mix of fields and buckets is `boolean`. */
|
|
317
|
+
type HasBucket<G> = G extends Bucket<string, string, string> ? true : false;
|
|
318
|
+
/** One bucket key. A string group contributes nothing. */
|
|
319
|
+
type BucketPiece<Row, G> = G extends Bucket<infer C, infer U, infer A> ? {
|
|
320
|
+
readonly [K in A]: (U extends "second" | "minute" | "hour" ? Temporal.Instant : Temporal.PlainDate) | (C extends keyof Row ? (null extends Row[C] ? null : never) : null);
|
|
321
|
+
} : {};
|
|
322
|
+
/** Intersection of a union of group pieces. */
|
|
323
|
+
type Intersect<U> = (U extends unknown ? (arg: U) => void : never) extends (arg: infer I) => void ? I : unknown;
|
|
324
|
+
/**
|
|
325
|
+
* Group keys on an aggregate row.
|
|
326
|
+
*
|
|
327
|
+
* A plain field list stays `Pick`. A bucket list adds each `as` key. The value
|
|
328
|
+
* is `Temporal.PlainDate` for a calendar unit and `Temporal.Instant` for a
|
|
329
|
+
* clock unit, and includes `null` when the column does.
|
|
330
|
+
*/
|
|
331
|
+
type GroupOf<Row, G> = boolean extends HasBucket<G> ? Pick<Row, Extract<G, keyof Row>> & Intersect<BucketPiece<Row, G>> : [G] extends [Bucket<string, string, string>] ? Intersect<BucketPiece<Row, G>> : Pick<Row, G & keyof Row>;
|
|
190
332
|
/** A group: its fields, and the aggregates the call named. */
|
|
191
333
|
export type AggregateRow<Row, O> = Show<(O extends {
|
|
192
334
|
readonly groupBy: readonly (infer G)[];
|
|
193
|
-
} ?
|
|
335
|
+
} ? GroupOf<Row, G> : unknown) & (O extends {
|
|
194
336
|
readonly count: true;
|
|
195
337
|
} ? {
|
|
196
338
|
readonly count: number;
|
|
@@ -311,9 +453,15 @@ export type InsertOf<S extends QuerySchema, K extends keyof S["~byName"]> = S["~
|
|
|
311
453
|
export type UpdateOf<S extends QuerySchema, K extends keyof S["~byName"]> = S["~byName"][K] extends {
|
|
312
454
|
readonly "~update": infer U;
|
|
313
455
|
} ? U : never;
|
|
314
|
-
/**
|
|
456
|
+
/**
|
|
457
|
+
* `set` values.
|
|
458
|
+
*
|
|
459
|
+
* `undefined` leaves the field unchanged. `null` sets null, and only on a
|
|
460
|
+
* nullable column. `inc` adds to a number or bigint column. A null number
|
|
461
|
+
* stays null. `json.set` and `arr` write json and arrays.
|
|
462
|
+
*/
|
|
315
463
|
export type UpdateSet<S extends QuerySchema, K extends keyof S["~byName"]> = {
|
|
316
|
-
readonly [F in keyof UpdateOf<S, K>]?: UpdateOf<S, K>[F] |
|
|
464
|
+
readonly [F in keyof UpdateOf<S, K>]?: UpdateOf<S, K>[F] | IncOf<UpdateOf<S, K>[F]> | WriteOp<NonNullable<UpdateOf<S, K>[F]>>;
|
|
317
465
|
};
|
|
318
466
|
/** Conflict handling on `insert` (spec §11). */
|
|
319
467
|
export type OnConflict<S extends QuerySchema, K extends keyof S["~byName"]> = "error" | "ignore" | {
|
|
@@ -337,7 +485,7 @@ export type InsertOptions<S extends QuerySchema, K extends keyof S["~byName"]> =
|
|
|
337
485
|
};
|
|
338
486
|
/** Options for `update` and `delete`. */
|
|
339
487
|
export type WriteOptions<S extends QuerySchema, K extends keyof S["~byName"]> = {
|
|
340
|
-
readonly returning?: readonly (keyof RowOf<S, K> & string)[];
|
|
488
|
+
readonly returning?: true | readonly (keyof RowOf<S, K> & string)[];
|
|
341
489
|
/** Guarded fields this call may set. `delete` ignores it. */
|
|
342
490
|
readonly allow?: readonly (keyof RowOf<S, K> & string)[];
|
|
343
491
|
readonly expect?: number;
|
|
@@ -372,19 +520,32 @@ type AllowedSet<S extends QuerySchema, K extends keyof S["~byName"], Allow exten
|
|
|
372
520
|
type AllowedUpdate<S extends QuerySchema, K extends keyof S["~byName"], Allow extends readonly (keyof RowOf<S, K> & string)[]> = {
|
|
373
521
|
readonly where?: WhereOf<S, K>;
|
|
374
522
|
readonly set: AllowedSet<S, K, Allow>;
|
|
523
|
+
readonly version?: number;
|
|
375
524
|
} | readonly {
|
|
376
525
|
readonly id?: unknown;
|
|
377
526
|
readonly where?: WhereOf<S, K>;
|
|
378
527
|
readonly set: AllowedSet<S, K, Allow>;
|
|
528
|
+
readonly version?: number;
|
|
379
529
|
}[];
|
|
380
|
-
/**
|
|
530
|
+
/**
|
|
531
|
+
* One update, or a per-row list in one statement.
|
|
532
|
+
*
|
|
533
|
+
* `lock: "skip"` with `limit` claims that many matching rows and leaves rows
|
|
534
|
+
* another transaction already holds. It is not valid on a list.
|
|
535
|
+
*/
|
|
381
536
|
export type UpdateTarget<S extends QuerySchema, K extends keyof S["~byName"]> = {
|
|
382
537
|
readonly where?: WhereOf<S, K>;
|
|
383
538
|
readonly set: UpdateSet<S, K>;
|
|
539
|
+
readonly limit?: number;
|
|
540
|
+
readonly lock?: "skip";
|
|
541
|
+
/** Version read from the row. Required at runtime when the table is `versioned()`. */
|
|
542
|
+
readonly version?: number;
|
|
384
543
|
} | readonly {
|
|
385
544
|
readonly id?: unknown;
|
|
386
545
|
readonly where?: WhereOf<S, K>;
|
|
387
546
|
readonly set: UpdateSet<S, K>;
|
|
547
|
+
/** Version read from the row. Required at runtime when the table is `versioned()`. */
|
|
548
|
+
readonly version?: number;
|
|
388
549
|
}[];
|
|
389
550
|
/** `{ count, archiveId }` from one `archive()` call. */
|
|
390
551
|
export type ArchiveCount = {
|
|
@@ -462,6 +623,7 @@ export type TableApi<S extends QuerySchema, K extends keyof S["~byName"] & strin
|
|
|
462
623
|
};
|
|
463
624
|
count(options?: CallOptions & {
|
|
464
625
|
readonly where?: WhereOf<S, K>;
|
|
626
|
+
readonly search?: TextSearch<RowOf<S, K>>;
|
|
465
627
|
}): Read<number>;
|
|
466
628
|
exists(options?: CallOptions & {
|
|
467
629
|
readonly where?: WhereOf<S, K>;
|
|
@@ -482,15 +644,49 @@ export type TableApi<S extends QuerySchema, K extends keyof S["~byName"] & strin
|
|
|
482
644
|
* database default for that row; `null` stays NULL.
|
|
483
645
|
*/
|
|
484
646
|
insert(data: readonly (RequiredInsert<InsertOf<S, K>> & OptionalInsert<InsertOf<S, K>>)[], options?: InsertOptions<S, K>): Write<readonly Show<RowOf<S, K>>[]>;
|
|
485
|
-
/**
|
|
486
|
-
|
|
647
|
+
/**
|
|
648
|
+
* Updates matching rows, or a per-row list in one statement. `where` is required.
|
|
649
|
+
*
|
|
650
|
+
* `{ allow, returning: true }` returns the written rows. `{ allow }` without
|
|
651
|
+
* `returning: true` returns `{ count }`.
|
|
652
|
+
*/
|
|
653
|
+
update<const Allow extends readonly (keyof RowOf<S, K> & string)[], const Opt extends WriteOptions<S, K> & {
|
|
487
654
|
readonly allow: Allow;
|
|
488
|
-
}): Write<WriteCount>;
|
|
655
|
+
}>(target: AllowedUpdate<S, K, Allow>, options: Opt): [Opt["returning"]] extends [true] ? Write<readonly Show<RowOf<S, K>>[]> : Write<WriteCount>;
|
|
656
|
+
update(target: UpdateTarget<S, K>, options: WriteOptions<S, K> & {
|
|
657
|
+
readonly returning: true;
|
|
658
|
+
}): Write<readonly Show<RowOf<S, K>>[]>;
|
|
489
659
|
update(target: UpdateTarget<S, K>, options?: WriteOptions<S, K>): Write<WriteCount>;
|
|
490
|
-
/**
|
|
660
|
+
/**
|
|
661
|
+
* Deletes matching rows. `where` is required.
|
|
662
|
+
*
|
|
663
|
+
* `{ returning: true }` is not accepted. Pass the field names, or omit
|
|
664
|
+
* `returning` for `{ count }`.
|
|
665
|
+
*/
|
|
491
666
|
delete(target: {
|
|
492
667
|
readonly where?: WhereOf<S, K>;
|
|
493
|
-
}, options?: WriteOptions<S, K>
|
|
668
|
+
}, options?: Omit<WriteOptions<S, K>, "returning"> & {
|
|
669
|
+
readonly returning?: Exclude<WriteOptions<S, K>["returning"], true>;
|
|
670
|
+
}): Write<WriteCount>;
|
|
671
|
+
/**
|
|
672
|
+
* Rows below `id`, walking the table's self-relation.
|
|
673
|
+
*
|
|
674
|
+
* One statement. A row already seen is not entered again, so a cycle in the
|
|
675
|
+
* data returns. A missing id returns no rows. `where` and a preset filter
|
|
676
|
+
* the rows that come back. Tenancy and the active set apply at every step.
|
|
677
|
+
*/
|
|
678
|
+
descendants<const O extends TreeOptions<S, K>>(id: unknown, options?: O): Query<readonly ResultRow<S, K, O>[]>;
|
|
679
|
+
/** Rows above `id`. The options match {@link TableApi.descendants}. */
|
|
680
|
+
ancestors<const O extends TreeOptions<S, K>>(id: unknown, options?: O): Query<readonly ResultRow<S, K, O>[]>;
|
|
681
|
+
/**
|
|
682
|
+
* Sets a to-many relation to exactly `ids`.
|
|
683
|
+
*
|
|
684
|
+
* One statement. A join table gains and loses link rows. A nullable foreign
|
|
685
|
+
* key is set or cleared, and the related row stays. A link that would have
|
|
686
|
+
* to delete a row is refused. Duplicate ids count once. An id that is not
|
|
687
|
+
* in the related table is `not_found`, and nothing is written.
|
|
688
|
+
*/
|
|
689
|
+
sync(id: unknown, relation: string, ids: readonly unknown[], options?: SyncOptions): SyncHandle;
|
|
494
690
|
} & (S["~byName"][K] extends {
|
|
495
691
|
readonly "~archive": true;
|
|
496
692
|
} ? ArchiveOps<S, K, L> : unknown) & PresetApi<S, K, L> & TableExtras<S, K>;
|