@atscript/db 0.1.142 → 0.1.143
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/agg.d.cts +1 -1
- package/dist/agg.d.mts +1 -1
- package/dist/{buckets-Bv4pah66.d.cts → buckets-Ba5lP_o9.d.cts} +358 -17
- package/dist/{buckets-CjL7F-hp.d.mts → buckets-BlJ4cdlr.d.mts} +358 -17
- package/dist/{column-diff-DiBbXyLA.d.cts → column-diff-BlGxPobU.d.cts} +1 -1
- package/dist/{column-diff-CfPNcP6e.cjs → column-diff-D_Kyuh0S.cjs} +906 -209
- package/dist/{column-diff-n-k5KY0u.d.mts → column-diff-PqA_edXA.d.mts} +1 -1
- package/dist/{column-diff-CmFNXV8C.mjs → column-diff-e2oHc71_.mjs} +850 -177
- package/dist/index.cjs +16 -10
- package/dist/index.d.cts +30 -5
- package/dist/index.d.mts +30 -5
- package/dist/index.mjs +6 -5
- package/dist/nested-writer-CnOOAehr.mjs +880 -0
- package/dist/nested-writer-xfQwxplL.cjs +1029 -0
- package/dist/{object-DSN0h9lB.d.cts → object-CtPYTIvy.d.cts} +3 -1
- package/dist/{object-DSN0h9lB.d.mts → object-CtPYTIvy.d.mts} +3 -1
- package/dist/object-Djg28csK.cjs +101 -0
- package/dist/object-TkiJQ-Dp.mjs +66 -0
- package/dist/rel.cjs +5 -2
- package/dist/rel.d.cts +76 -10
- package/dist/rel.d.mts +76 -10
- package/dist/rel.mjs +3 -3
- package/dist/{relation-helpers-B59to_dG.d.mts → relation-helpers-JTEyZzVd.d.cts} +1 -1
- package/dist/{relation-helpers-DQ_nRsV9.d.cts → relation-helpers-MTwzaSGA.d.mts} +1 -1
- package/dist/{relation-loader-CgJ8bK6X.cjs → relation-loader-CBPY6kM7.cjs} +1 -1
- package/dist/{relation-loader-CuhEBzFU.mjs → relation-loader-D9XuXaMv.mjs} +1 -1
- package/dist/sync.cjs +1 -1
- package/dist/sync.d.cts +2 -2
- package/dist/sync.d.mts +2 -2
- package/dist/sync.mjs +1 -1
- package/dist/{validator-DASnXf1j.cjs → validator-CVS-onRg.cjs} +0 -101
- package/dist/{validator-D8bPsXPN.mjs → validator-Clu2q_7z.mjs} +1 -66
- package/dist/validator.cjs +4 -3
- package/dist/validator.d.cts +1 -1
- package/dist/validator.d.mts +1 -1
- package/dist/validator.mjs +2 -1
- package/package.json +1 -1
- package/dist/nested-writer-BO3vhbkP.mjs +0 -661
- package/dist/nested-writer-DYsRxZ5f.cjs +0 -768
package/dist/agg.d.cts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as TResolvedBucket } from "./buckets-
|
|
1
|
+
import { n as TResolvedBucket } from "./buckets-Ba5lP_o9.cjs";
|
|
2
2
|
import { _ as TDbAggregateFn, a as AggregateResult, c as CalendarBucketLabel, d as WeekStart, f as isAggregateExpr, h as resolveAlias, i as AggregateQuery, l as ComputedExpr, m as resolveAggregateSearch, n as AggregateExpr, o as BucketExpr, p as isBucketExpr, r as AggregateFn, s as BucketUnit, t as AggregateControls, u as ResolvedBucket, v as assertAggregateFn } from "./agg-CV7y8nC6.cjs";
|
|
3
3
|
export { type AggregateControls, type AggregateExpr, type AggregateFn, type AggregateQuery, type AggregateResult, type BucketExpr, type BucketUnit, type CalendarBucketLabel, type ComputedExpr, type ResolvedBucket, type TDbAggregateFn, type TResolvedBucket, type WeekStart, assertAggregateFn, isAggregateExpr, isBucketExpr, resolveAggregateSearch, resolveAlias };
|
package/dist/agg.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as TResolvedBucket } from "./buckets-
|
|
1
|
+
import { n as TResolvedBucket } from "./buckets-BlJ4cdlr.mjs";
|
|
2
2
|
import { _ as TDbAggregateFn, a as AggregateResult, c as CalendarBucketLabel, d as WeekStart, f as isAggregateExpr, h as resolveAlias, i as AggregateQuery, l as ComputedExpr, m as resolveAggregateSearch, n as AggregateExpr, o as BucketExpr, p as isBucketExpr, r as AggregateFn, s as BucketUnit, t as AggregateControls, u as ResolvedBucket, v as assertAggregateFn } from "./agg-D5DHsAby.mjs";
|
|
3
3
|
export { type AggregateControls, type AggregateExpr, type AggregateFn, type AggregateQuery, type AggregateResult, type BucketExpr, type BucketUnit, type CalendarBucketLabel, type ComputedExpr, type ResolvedBucket, type TDbAggregateFn, type TResolvedBucket, type WeekStart, assertAggregateFn, isAggregateExpr, isBucketExpr, resolveAggregateSearch, resolveAlias };
|
|
@@ -465,6 +465,27 @@ declare class AtscriptDbReadable<T extends TAtscriptAnnotatedType = TAtscriptAnn
|
|
|
465
465
|
get foreignKeys(): ReadonlyMap<string, TDbForeignKey>;
|
|
466
466
|
/** Navigational relation metadata from `@db.rel.to` / `@db.rel.from`. */
|
|
467
467
|
get relations(): ReadonlyMap<string, TDbRelation>;
|
|
468
|
+
/**
|
|
469
|
+
* The `@db.rel.FK` entry a `@db.rel.to` relation is backed by — paired
|
|
470
|
+
* exactly like relation loading and nested writes pair them: by the
|
|
471
|
+
* relation's alias when it has one, else by the target table. `undefined`
|
|
472
|
+
* for an unknown name, a `@db.rel.from` / `@db.rel.via` relation (their key
|
|
473
|
+
* lives on the other table) or a TO relation without a matching FK.
|
|
474
|
+
*
|
|
475
|
+
* @since 0.1.143
|
|
476
|
+
*/
|
|
477
|
+
foreignKeyOf(relationName: string): TDbForeignKey | undefined;
|
|
478
|
+
/**
|
|
479
|
+
* Logical paths stored as ONE JSON column (`storage: "json"` — `@db.json`
|
|
480
|
+
* fields and nested objects / arrays a relational adapter serializes): the
|
|
481
|
+
* engine cannot address a sub-path of such a column in a projection,
|
|
482
|
+
* filter or sort, so a permission layer treats it atomically (visible whole
|
|
483
|
+
* or not at all). Navigation fields excluded; empty on document adapters
|
|
484
|
+
* (they store nested values natively).
|
|
485
|
+
*
|
|
486
|
+
* @since 0.1.143
|
|
487
|
+
*/
|
|
488
|
+
get jsonParents(): ReadonlySet<string>;
|
|
468
489
|
/** The underlying database adapter instance. */
|
|
469
490
|
get dbAdapter(): A;
|
|
470
491
|
/**
|
|
@@ -484,6 +505,28 @@ declare class AtscriptDbReadable<T extends TAtscriptAnnotatedType = TAtscriptAnn
|
|
|
484
505
|
* of them. Every read path funnels through here.
|
|
485
506
|
*/
|
|
486
507
|
private _fromRead;
|
|
508
|
+
/**
|
|
509
|
+
* Translates a read query for the adapter. A `$select` that leaves out a
|
|
510
|
+
* key a `$with` relation joins on — a TO relation's foreign key, the key a
|
|
511
|
+
* FROM / VIA relation is looked up by — is widened with it for the read
|
|
512
|
+
* (since 0.1.143), and {@link _finishRead} strips it again once the
|
|
513
|
+
* relations are loaded: the joined object never reads `null` just because
|
|
514
|
+
* its key was not selected.
|
|
515
|
+
*/
|
|
516
|
+
private _translateRead;
|
|
517
|
+
/** Reconstructs + decrypts a read's rows, loads its `$with` relations and strips widened keys. */
|
|
518
|
+
private _finishRead;
|
|
519
|
+
/** `$select` plus the join keys of `withRelations` it leaves out — `undefined` when none is missing. */
|
|
520
|
+
private _widenSelectForWith;
|
|
521
|
+
private _joinKeysCache?;
|
|
522
|
+
/**
|
|
523
|
+
* The keys of THIS table a `$with` relation joins on: a TO relation's
|
|
524
|
+
* foreign-key fields; the fields a FROM relation's (or a VIA junction's)
|
|
525
|
+
* foreign key references — typically the primary key. An adapter that
|
|
526
|
+
* loads relations natively re-reads the rows by primary key, so it is
|
|
527
|
+
* always included there. Empty for an unknown or nested (`a.b`) name.
|
|
528
|
+
*/
|
|
529
|
+
private _joinKeysOf;
|
|
487
530
|
/**
|
|
488
531
|
* Pre-computed field metadata for adapter use.
|
|
489
532
|
*/
|
|
@@ -656,6 +699,10 @@ declare class AtscriptDbReadable<T extends TAtscriptAnnotatedType = TAtscriptAnn
|
|
|
656
699
|
* or single-field unique index.
|
|
657
700
|
* The return type excludes nav props unless `$with` is provided in controls.
|
|
658
701
|
*
|
|
702
|
+
* The id addresses exactly ONE row, primary key first (since 0.1.143) —
|
|
703
|
+
* see {@link resolveRowFilter}: when a scalar id equals one row's primary
|
|
704
|
+
* key and another row's unique key, the primary-key row is returned.
|
|
705
|
+
*
|
|
659
706
|
* ```typescript
|
|
660
707
|
* // Without relations — nav props stripped from result
|
|
661
708
|
* const user = await table.findById('123')
|
|
@@ -667,25 +714,100 @@ declare class AtscriptDbReadable<T extends TAtscriptAnnotatedType = TAtscriptAnn
|
|
|
667
714
|
findById<Q extends {
|
|
668
715
|
controls?: UniqueryControls<OwnProps, NavType>;
|
|
669
716
|
} = Record<string, never>>(id: IdType, query?: Q): Promise<DbResponse<DataType, NavType, Q> | null>;
|
|
717
|
+
/**
|
|
718
|
+
* Reads the ONE row an id addresses — resolved exactly like
|
|
719
|
+
* {@link resolveRowFilter} (primary key first, `opts.scope` /
|
|
720
|
+
* `opts.isFieldVisible` as there) — with `opts.controls` applied, in one
|
|
721
|
+
* step: the identifications are probed in order with the caller's
|
|
722
|
+
* controls and the first row found wins, so no pin-then-reread. The row
|
|
723
|
+
* must also match `opts.scope` (an out-of-scope row answers `null` like a
|
|
724
|
+
* missing one).
|
|
725
|
+
*
|
|
726
|
+
* @since 0.1.143
|
|
727
|
+
*/
|
|
728
|
+
findOneByRow<Q extends {
|
|
729
|
+
controls?: UniqueryControls<OwnProps, NavType>;
|
|
730
|
+
} = Record<string, never>>(id: unknown, opts?: TRowResolveOptions & Q): Promise<DbResponse<DataType, NavType, Q> | null>;
|
|
670
731
|
/**
|
|
671
732
|
* Resolve an id value (scalar or object) into a {@link FilterExpr} using the
|
|
672
|
-
* same
|
|
733
|
+
* same identifications as {@link findById}. Public so callers can
|
|
673
734
|
* AND-combine the id-filter with a row-level read overlay before issuing
|
|
674
735
|
* `findOne` (avoiding the existence leak that `findById` would cause).
|
|
675
736
|
* `opts.isFieldVisible` (since 0.1.134) drops unique indexes over hidden
|
|
676
737
|
* fields — see {@link identificationsVisibleTo}.
|
|
738
|
+
*
|
|
739
|
+
* The result is a plain `$or` over every identification the id is
|
|
740
|
+
* type-compatible with (a scalar can equal one row's primary key AND
|
|
741
|
+
* another row's unique key), so it may match more than one row. Code that
|
|
742
|
+
* must address exactly one row — writes, pre-images, `/one` reads — uses
|
|
743
|
+
* {@link resolveRowFilter} instead.
|
|
677
744
|
*/
|
|
678
745
|
resolveIdFilter(id: unknown, opts?: TIdResolveOptions): FilterExpr | null;
|
|
679
746
|
/**
|
|
680
|
-
* Resolve an id value into a filter
|
|
747
|
+
* Resolve an id value (scalar or object) into a filter that matches exactly
|
|
748
|
+
* ONE row, deterministically and primary key first (since 0.1.143):
|
|
749
|
+
*
|
|
750
|
+
* - an id that yields a single identification (e.g. a numeric PK with no
|
|
751
|
+
* type-compatible unique key) resolves to it without a read;
|
|
752
|
+
* - an object id carrying the complete primary key resolves by the primary
|
|
753
|
+
* key alone — exactly like a write payload is identified;
|
|
754
|
+
* - otherwise the identifications are tried in order (primary key first,
|
|
755
|
+
* then each unique index): the first one that matches a row wins and the
|
|
756
|
+
* result is that row's exact primary-key filter;
|
|
757
|
+
* - when none matches, the first identification is returned (it matches
|
|
758
|
+
* nothing, so callers answer "not found" as usual).
|
|
759
|
+
*
|
|
760
|
+
* `null` when the id resolves to no identification at all. Every write
|
|
761
|
+
* (`deleteOne`, the guards' `current()`) and `findById` go through this
|
|
762
|
+
* resolution; call it inside the write's transaction when the answer must
|
|
763
|
+
* stay pinned. `opts.isFieldVisible` as in {@link resolveIdFilter}.
|
|
764
|
+
*
|
|
765
|
+
* `opts.scope` (a row-level overlay) restricts which rows count as matches
|
|
766
|
+
* while the identifications are tried — a row outside it never shadows one
|
|
767
|
+
* inside it, so the answer is the same as if that row did not exist. AND
|
|
768
|
+
* the scope onto the result to exclude an out-of-scope row the id names
|
|
769
|
+
* unambiguously. See {@link TRowResolveOptions}.
|
|
770
|
+
*/
|
|
771
|
+
resolveRowFilter(id: unknown, opts?: TRowResolveOptions): Promise<FilterExpr | null>;
|
|
772
|
+
/**
|
|
773
|
+
* Resolve an id value into a filter expression (the `$or` of
|
|
774
|
+
* {@link _idCandidates}; a single candidate is returned as-is).
|
|
775
|
+
*/
|
|
776
|
+
protected _resolveIdFilter(id: unknown, opts?: TIdResolveOptions): FilterExpr | null;
|
|
777
|
+
/**
|
|
778
|
+
* The ordered identification filters an id value can resolve through —
|
|
779
|
+
* primary key first, then each unique index.
|
|
681
780
|
*
|
|
682
781
|
* When `preferredId` differs from the PK, scalar ids resolve only against
|
|
683
782
|
* the preferred field (deterministic addressing). Otherwise scalars try PK
|
|
684
783
|
* + every single-field unique index; objects try PK + compound unique
|
|
685
784
|
* indexes. With `opts.isFieldVisible`, only the identifications
|
|
686
|
-
* {@link identificationsVisibleTo} keeps are tried.
|
|
785
|
+
* {@link identificationsVisibleTo} keeps are tried. With `pkWins` (the
|
|
786
|
+
* default), an object id carrying the complete primary key yields the
|
|
787
|
+
* primary-key filter alone.
|
|
687
788
|
*/
|
|
688
|
-
protected
|
|
789
|
+
protected _idCandidates(id: unknown, opts?: TIdResolveOptions, pkWins?: boolean): FilterExpr[];
|
|
790
|
+
/**
|
|
791
|
+
* Picks the one row a list of identification candidates addresses — see
|
|
792
|
+
* {@link resolveRowFilter}. A lone candidate needs no read. With a
|
|
793
|
+
* non-empty `scope`, only rows matching it count as matches.
|
|
794
|
+
*/
|
|
795
|
+
protected _pinIdCandidates(candidates: FilterExpr[], scope?: FilterExpr): Promise<FilterExpr | null>;
|
|
796
|
+
/** Sequential fallback of {@link _pinIdCandidates}: first candidate matching a row wins. */
|
|
797
|
+
private _probeIdCandidates;
|
|
798
|
+
/**
|
|
799
|
+
* The exact primary-key filter of `row` (values prepared like ids) — `null`
|
|
800
|
+
* when the table has no primary key or `row` lacks a key field.
|
|
801
|
+
*/
|
|
802
|
+
protected _pkFilterFrom(row: Record<string, unknown>): FilterExpr | null;
|
|
803
|
+
/**
|
|
804
|
+
* Reads the row `filter` (AND `scope`) matches and returns its exact
|
|
805
|
+
* primary-key filter (`filter` itself on a table without one); `undefined`
|
|
806
|
+
* when no row matches.
|
|
807
|
+
*/
|
|
808
|
+
protected _readPkFilter(filter: FilterExpr, scope?: FilterExpr): Promise<FilterExpr | undefined>;
|
|
809
|
+
/** `filter` AND a row scope — `filter` itself when the scope is absent or empty. */
|
|
810
|
+
protected _andScope(filter: FilterExpr, scope?: FilterExpr): FilterExpr;
|
|
689
811
|
/** Build a single-key filter from `idObj` over `fields`, or null if any field is missing/incompatible. */
|
|
690
812
|
private _tryCompoundFilter;
|
|
691
813
|
/**
|
|
@@ -777,7 +899,9 @@ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnota
|
|
|
777
899
|
* Recursive up to `maxDepth` (default 3).
|
|
778
900
|
*
|
|
779
901
|
* `opts.guard` (since 0.1.128) runs once inside the transaction, after
|
|
780
|
-
* defaults + validation, with the prepared rows
|
|
902
|
+
* defaults + validation, with the prepared rows; `opts.check` (since
|
|
903
|
+
* 0.1.143) runs once after every phase with the inserted rows' primary-key
|
|
904
|
+
* filters — see {@link TWriteOptions}.
|
|
781
905
|
*/
|
|
782
906
|
insertMany(payloads: Array<DbPatch<DataType>>, opts?: TWriteOptions<DataType>): Promise<TDbInsertManyResult>;
|
|
783
907
|
/**
|
|
@@ -794,7 +918,9 @@ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnota
|
|
|
794
918
|
* re-create junction rows. Fully recursive up to `maxDepth` (default 3).
|
|
795
919
|
*
|
|
796
920
|
* `opts.guard` (since 0.1.128) runs once inside the transaction, after
|
|
797
|
-
* `$cas` extraction, defaults + validation
|
|
921
|
+
* `$cas` extraction, defaults + validation; `opts.check` (since 0.1.143)
|
|
922
|
+
* after every phase — see {@link TWriteOptions}. The nested phases run only
|
|
923
|
+
* for the rows the main replace matched.
|
|
798
924
|
*/
|
|
799
925
|
bulkReplace(payloads: Array<DbRow<DataType>>, opts?: TWriteOptions<DataType>): Promise<TDbUpdateResult>;
|
|
800
926
|
/**
|
|
@@ -811,7 +937,10 @@ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnota
|
|
|
811
937
|
*
|
|
812
938
|
* `opts.guard` (since 0.1.128) runs once inside the transaction, after
|
|
813
939
|
* `$cas` extraction and validation, with the patches (identifying fields
|
|
814
|
-
* present, `$cas` removed)
|
|
940
|
+
* present, `$cas` removed); `opts.check` (since 0.1.143) after every
|
|
941
|
+
* phase — see {@link TWriteOptions}. The nested phases run only for the
|
|
942
|
+
* rows the main patch matched; a nested TO object patches the row the
|
|
943
|
+
* STORED foreign key references.
|
|
815
944
|
*/
|
|
816
945
|
bulkUpdate(payloads: Array<DbPatch<DataType>>, opts?: TWriteOptions<DataType>): Promise<TDbUpdateResult>;
|
|
817
946
|
/**
|
|
@@ -842,13 +971,22 @@ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnota
|
|
|
842
971
|
touchMany(keys: Array<DbPatch<DataType>>, opts?: TTouchManyOptions): Promise<TDbUpdateResult>;
|
|
843
972
|
/**
|
|
844
973
|
* Deletes a single record by any type-compatible identifier — primary key
|
|
845
|
-
* or single-field unique index. Uses the same resolution logic as `findById
|
|
974
|
+
* or single-field unique index. Uses the same resolution logic as `findById`:
|
|
975
|
+
* the id addresses exactly ONE row, primary key first (since 0.1.143 — see
|
|
976
|
+
* {@link resolveRowFilter}); an id that could name several rows is pinned
|
|
977
|
+
* inside the transaction, so the guard, the cascade and the delete all see
|
|
978
|
+
* the same row.
|
|
846
979
|
*
|
|
847
980
|
* When the adapter does not support native foreign keys (e.g. MongoDB),
|
|
848
981
|
* cascade and setNull actions are applied before the delete.
|
|
849
982
|
*
|
|
850
983
|
* `opts.guard` (since 0.1.128) runs inside the transaction once the id has
|
|
851
984
|
* resolved to a filter, before cascade / delete — see {@link TDeleteOptions}.
|
|
985
|
+
* `opts.scope` (since 0.1.143) is a row scope: an ambiguous id is pinned
|
|
986
|
+
* among in-scope rows only (see {@link TRowResolveOptions}) and the delete
|
|
987
|
+
* — guard `current()` and cascade included — targets the row only while it
|
|
988
|
+
* matches the scope, so an out-of-scope row answers `{ deletedCount: 0 }`
|
|
989
|
+
* exactly like a missing one.
|
|
852
990
|
* An id that resolves to no filter answers `{ deletedCount: 0 }` without
|
|
853
991
|
* calling the guard.
|
|
854
992
|
*/
|
|
@@ -880,12 +1018,60 @@ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnota
|
|
|
880
1018
|
*/
|
|
881
1019
|
protected _encryptItems(items: Array<Record<string, unknown>>, mode: "write" | "patch"): Promise<void>;
|
|
882
1020
|
/**
|
|
883
|
-
*
|
|
884
|
-
* no identifying key (e.g. an auto-increment insert) or
|
|
885
|
-
* resolved — never throws for a missing key.
|
|
1021
|
+
* The record filter a guard's `current(i)` reads its pre-image by: `null`
|
|
1022
|
+
* when the row has no identifying key (e.g. an auto-increment insert) or
|
|
1023
|
+
* the key cannot be resolved — never throws for a missing key. Identified
|
|
1024
|
+
* exactly like the write itself (primary key first, then a unique index —
|
|
1025
|
+
* since 0.1.143), so it is always the row the write targets.
|
|
886
1026
|
* @internal
|
|
887
1027
|
*/
|
|
888
|
-
|
|
1028
|
+
_recordFilterOrNull(row: unknown, opts?: TIdResolveOptions): FilterExpr | null;
|
|
1029
|
+
/**
|
|
1030
|
+
* Each item's record filter (see {@link _extractRecordFilter}). A nested
|
|
1031
|
+
* FROM re-entry (`_ownedBy`) also pins the child's foreign key to its
|
|
1032
|
+
* parent, so the write never touches a child of another parent.
|
|
1033
|
+
*/
|
|
1034
|
+
private _rowFilters;
|
|
1035
|
+
/** Whether `filter` names every primary-key field (so it IS the row's exact key). */
|
|
1036
|
+
private _isPkFilter;
|
|
1037
|
+
/**
|
|
1038
|
+
* The TO relations with their single-field local foreign key (lazily
|
|
1039
|
+
* listed) — what a write pins per item for its nested TO phase.
|
|
1040
|
+
*/
|
|
1041
|
+
private _toRelationsCache?;
|
|
1042
|
+
private _toRelations;
|
|
1043
|
+
/** Whether `item` carries a nested TO object (Phase 1 work). */
|
|
1044
|
+
private _carriesNestedTo;
|
|
1045
|
+
/**
|
|
1046
|
+
* Reads — once per write call, inside its transaction — the stored row
|
|
1047
|
+
* each item `need`s, by the item's record filter: its primary key, version
|
|
1048
|
+
* and single-field TO foreign keys, in ONE read for the batch. A pre-image
|
|
1049
|
+
* the guard's `current(i)` already read by the same filter is reused.
|
|
1050
|
+
* `null` = no such row; `undefined` = not needed.
|
|
1051
|
+
*/
|
|
1052
|
+
private _pinTargets;
|
|
1053
|
+
/**
|
|
1054
|
+
* The exact primary-key filter of every row the write matched: the record
|
|
1055
|
+
* filter itself when it is the primary key, else the pinned row's key.
|
|
1056
|
+
*/
|
|
1057
|
+
private _writtenPkFilters;
|
|
1058
|
+
/** Invokes a {@link TWriteOptions.check} with de-duplicated PK filters (inside the transaction). */
|
|
1059
|
+
private _runWriteCheck;
|
|
1060
|
+
/**
|
|
1061
|
+
* The exact primary-key filter of each inserted row: the logical key from
|
|
1062
|
+
* the row (SDK defaults applied), else the stored key the adapter wrote into
|
|
1063
|
+
* the prepared row (e.g. a driver-assigned `_id`), else — single-field keys
|
|
1064
|
+
* only — the adapter's `insertedIds` (auto-increment).
|
|
1065
|
+
*/
|
|
1066
|
+
private _insertedPkFilters;
|
|
1067
|
+
/**
|
|
1068
|
+
* Drops the nested TO objects of every replace item whose main replace
|
|
1069
|
+
* cannot match (pinned row missing, or stale `$cas`) so Phase 1 never
|
|
1070
|
+
* writes a related row for a replace that does nothing. Returns, per item,
|
|
1071
|
+
* whether its TO objects stay (a later 0-match for such an item is a
|
|
1072
|
+
* concurrent change and rolls back).
|
|
1073
|
+
*/
|
|
1074
|
+
private _gateNestedTo;
|
|
889
1075
|
/**
|
|
890
1076
|
* Applies `@db.default` values in place to a row's absent fields — the
|
|
891
1077
|
* defaults pass every insert / replace path runs before validation.
|
|
@@ -905,6 +1091,16 @@ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnota
|
|
|
905
1091
|
* validator reports it against the field instead of a bare `SyntaxError`.
|
|
906
1092
|
*/
|
|
907
1093
|
private _parseValueDefault;
|
|
1094
|
+
/**
|
|
1095
|
+
* The filter an `updateOne` / `replaceOne` of `payload` targets its row by
|
|
1096
|
+
* — the write's own resolution (primary key first, then a unique index;
|
|
1097
|
+
* see {@link _extractRecordFilter}), so a caller explaining a write's
|
|
1098
|
+
* outcome (e.g. a CAS mismatch) reads exactly the row the write addressed.
|
|
1099
|
+
* Throws `NOT_FOUND` when the payload carries no identifying fields.
|
|
1100
|
+
*
|
|
1101
|
+
* @since 0.1.143
|
|
1102
|
+
*/
|
|
1103
|
+
recordFilter(payload: Record<string, unknown>, opts?: TIdResolveOptions): FilterExpr;
|
|
908
1104
|
/**
|
|
909
1105
|
* Extracts a record-identifying filter from a payload.
|
|
910
1106
|
*
|
|
@@ -1077,6 +1273,12 @@ interface TViewColumnMapping {
|
|
|
1077
1273
|
*/
|
|
1078
1274
|
aggFilter?: AtscriptQueryNode;
|
|
1079
1275
|
}
|
|
1276
|
+
/**
|
|
1277
|
+
* Whether `type` declares a view (managed `@db.view.for` or external
|
|
1278
|
+
* `@db.view`) — how `DbSpace.get` tells views from tables.
|
|
1279
|
+
* @since 0.1.143
|
|
1280
|
+
*/
|
|
1281
|
+
declare function isViewType(type: TAtscriptAnnotatedType): boolean;
|
|
1080
1282
|
/**
|
|
1081
1283
|
* Database view abstraction driven by Atscript `@db.view.*` annotations.
|
|
1082
1284
|
*
|
|
@@ -1094,6 +1296,12 @@ declare class AtscriptDbView<T extends TAtscriptAnnotatedType = TAtscriptAnnotat
|
|
|
1094
1296
|
private _viewPlan?;
|
|
1095
1297
|
private _columnMappings?;
|
|
1096
1298
|
get isView(): boolean;
|
|
1299
|
+
/**
|
|
1300
|
+
* Builds the view's metadata — first stamping its fields with their
|
|
1301
|
+
* sources' read seals (`inheritViewFieldSeals`, once per view type), so
|
|
1302
|
+
* every metadata consumer sees the sealed type.
|
|
1303
|
+
*/
|
|
1304
|
+
protected _ensureBuilt(): void;
|
|
1097
1305
|
/**
|
|
1098
1306
|
* Whether this is an external view — declared with `@db.view` only,
|
|
1099
1307
|
* without `@db.view.for`. External views reference pre-existing DB views
|
|
@@ -1385,6 +1593,14 @@ declare abstract class BaseDbAdapter {
|
|
|
1385
1593
|
* Adapters use this to retrieve DB-specific state (e.g., MongoDB `ClientSession`).
|
|
1386
1594
|
*/
|
|
1387
1595
|
protected _getTransactionState(): unknown;
|
|
1596
|
+
/**
|
|
1597
|
+
* `true` when the current async context runs inside a REAL transaction of
|
|
1598
|
+
* this adapter (its owner) — one a throw rolls back (since 0.1.143).
|
|
1599
|
+
* `false` outside any transaction and inside a pass-through
|
|
1600
|
+
* `withTransaction` (adapters without transaction primitives such as the
|
|
1601
|
+
* in-memory one, a standalone MongoDB topology).
|
|
1602
|
+
*/
|
|
1603
|
+
isInTransaction(): boolean;
|
|
1388
1604
|
/**
|
|
1389
1605
|
* Runs `fn` inside the transaction ALS context with the given state.
|
|
1390
1606
|
* Adapters that override `withTransaction` (e.g., to use MongoDB's
|
|
@@ -1665,6 +1881,14 @@ declare abstract class BaseDbAdapter {
|
|
|
1665
1881
|
* UI uses this to show index picker. Override in adapters that support search.
|
|
1666
1882
|
*/
|
|
1667
1883
|
getSearchIndexes(): TSearchIndexInfo[];
|
|
1884
|
+
private _physicalToLogical?;
|
|
1885
|
+
/**
|
|
1886
|
+
* The LOGICAL field paths an index reads (its `fields` carry physical
|
|
1887
|
+
* names) — what adapters report as {@link TSearchIndexInfo.fields}. A
|
|
1888
|
+
* derived column never shadows the regular field sharing its physical name.
|
|
1889
|
+
* @since 0.1.143
|
|
1890
|
+
*/
|
|
1891
|
+
protected _indexLogicalPaths(index: TDbIndex): string[];
|
|
1668
1892
|
/**
|
|
1669
1893
|
* Whether this adapter can run TEXT search — `search()`, `searchWithCount()`
|
|
1670
1894
|
* and the grouped `$search` path all gate on it. Vector capability is a
|
|
@@ -2270,6 +2494,19 @@ interface TSearchIndexInfo {
|
|
|
2270
2494
|
description?: string;
|
|
2271
2495
|
/** Index type: text search or vector similarity search. */
|
|
2272
2496
|
type?: "text" | "vector";
|
|
2497
|
+
/**
|
|
2498
|
+
* LOGICAL field paths the index reads. Absent when the adapter cannot tell
|
|
2499
|
+
* (e.g. a dynamic document search mapping) — treat it as "every field"
|
|
2500
|
+
* (fail closed) when gating access by field visibility.
|
|
2501
|
+
* @since 0.1.143
|
|
2502
|
+
*/
|
|
2503
|
+
fields?: string[];
|
|
2504
|
+
/**
|
|
2505
|
+
* `true` on the index of its `type` that answers a request naming none
|
|
2506
|
+
* (at most one per type).
|
|
2507
|
+
* @since 0.1.143
|
|
2508
|
+
*/
|
|
2509
|
+
isDefault?: boolean;
|
|
2273
2510
|
}
|
|
2274
2511
|
/** Relation summary in a meta response. */
|
|
2275
2512
|
interface TRelationInfo {
|
|
@@ -2825,6 +3062,16 @@ interface AtscriptDbTableLike {
|
|
|
2825
3062
|
getMetadata(): TableMetadata;
|
|
2826
3063
|
isValidFieldPath(path: string, visited?: Set<string>): boolean;
|
|
2827
3064
|
}
|
|
3065
|
+
/**
|
|
3066
|
+
* Nested FROM re-entry option (internal): pins every child's foreign key
|
|
3067
|
+
* `field` to its parent in the write's row filter; a `strict` item that
|
|
3068
|
+
* matches nothing → `CONFLICT`.
|
|
3069
|
+
* @internal
|
|
3070
|
+
*/
|
|
3071
|
+
interface TNestedOwner {
|
|
3072
|
+
field: string;
|
|
3073
|
+
strict?: ReadonlyArray<boolean>;
|
|
3074
|
+
}
|
|
2828
3075
|
/** Minimal writable table interface for nested creation/update. */
|
|
2829
3076
|
interface AtscriptDbWritable {
|
|
2830
3077
|
insertOne(payload: Record<string, unknown>, opts?: {
|
|
@@ -2840,6 +3087,7 @@ interface AtscriptDbWritable {
|
|
|
2840
3087
|
bulkReplace(payloads: Array<Record<string, unknown>>, opts?: {
|
|
2841
3088
|
maxDepth?: number;
|
|
2842
3089
|
_depth?: number;
|
|
3090
|
+
_ownedBy?: TNestedOwner;
|
|
2843
3091
|
}): Promise<TDbUpdateResult>;
|
|
2844
3092
|
updateOne(payload: Record<string, unknown>, opts?: {
|
|
2845
3093
|
maxDepth?: number;
|
|
@@ -2847,6 +3095,7 @@ interface AtscriptDbWritable {
|
|
|
2847
3095
|
bulkUpdate(payloads: Array<Record<string, unknown>>, opts?: {
|
|
2848
3096
|
maxDepth?: number;
|
|
2849
3097
|
_depth?: number;
|
|
3098
|
+
_ownedBy?: TNestedOwner;
|
|
2850
3099
|
}): Promise<TDbUpdateResult>;
|
|
2851
3100
|
findOne(query: unknown): Promise<Record<string, unknown> | null>;
|
|
2852
3101
|
count(query: {
|
|
@@ -2941,10 +3190,33 @@ interface TDbWriteGuardContext<Row = Record<string, unknown>> {
|
|
|
2941
3190
|
readonly expectedVersions: ReadonlyArray<number | undefined>;
|
|
2942
3191
|
/**
|
|
2943
3192
|
* Lazy, memoised pre-image of `rows[i]` by its identifying filter, read
|
|
2944
|
-
* inside the transaction.
|
|
3193
|
+
* inside the transaction. Identified exactly like the write (primary key
|
|
3194
|
+
* first, then a unique index — since 0.1.143), so it is always the row the
|
|
3195
|
+
* write targets. `null` when the row is missing OR when it carries
|
|
2945
3196
|
* no identifying key yet (e.g. auto-increment inserts) — never throws.
|
|
2946
3197
|
*/
|
|
2947
3198
|
current(i: number): Promise<Row | null>;
|
|
3199
|
+
/**
|
|
3200
|
+
* Every row's pre-image in ONE read (since 0.1.143): parallel to `rows`,
|
|
3201
|
+
* each entry exactly what `current(i)` resolves to — a single `findMany`
|
|
3202
|
+
* by the rows' record filters inside the transaction, which fills the
|
|
3203
|
+
* same per-index memo (an index `current(i)` already read is reused, a
|
|
3204
|
+
* later `current(i)` reads nothing). Prefer it over a `current(i)` loop
|
|
3205
|
+
* for batches.
|
|
3206
|
+
*/
|
|
3207
|
+
currentAll(): Promise<Array<Row | null>>;
|
|
3208
|
+
/**
|
|
3209
|
+
* The exact filter the write identifies `rows[i]` by (since 0.1.143) —
|
|
3210
|
+
* its primary key, else the unique index it carries (see `current(i)`),
|
|
3211
|
+
* each naming at most ONE row — or `null` when the row has no identifying
|
|
3212
|
+
* key yet (e.g. an auto-increment insert). The filter `current(i)` reads
|
|
3213
|
+
* by; memoised per index on first use (change a row's identifying fields
|
|
3214
|
+
* before asking, not after). Combine it with a policy filter to check
|
|
3215
|
+
* the batch in the database without reading it — every targeted row
|
|
3216
|
+
* matches `policy` iff `count({ $and: [{ $or: filters }, policy] })`
|
|
3217
|
+
* equals the number of DISTINCT filters (a missing row counts as a miss).
|
|
3218
|
+
*/
|
|
3219
|
+
filterFor(i: number): FilterExpr | null;
|
|
2948
3220
|
}
|
|
2949
3221
|
/**
|
|
2950
3222
|
* Context handed to a delete {@link TDeleteOptions.guard} (since 0.1.128) —
|
|
@@ -2955,7 +3227,10 @@ interface TDbWriteGuardContext<Row = Record<string, unknown>> {
|
|
|
2955
3227
|
interface TDbRemoveGuardContext<Row = Record<string, unknown>> {
|
|
2956
3228
|
/** The id `deleteOne` was called with. */
|
|
2957
3229
|
readonly id: unknown;
|
|
2958
|
-
/**
|
|
3230
|
+
/**
|
|
3231
|
+
* The exact filter the delete targets — `table.resolveRowFilter(id)`, pinned
|
|
3232
|
+
* inside the transaction (primary key first, since 0.1.143). Never null here.
|
|
3233
|
+
*/
|
|
2959
3234
|
readonly filter: FilterExpr;
|
|
2960
3235
|
/** Lazy, memoised pre-image of the row about to be deleted (`null` when missing). */
|
|
2961
3236
|
current(): Promise<Row | null>;
|
|
@@ -2978,6 +3253,12 @@ interface TTouchManyOptions {
|
|
|
2978
3253
|
* `isFieldVisible` (since 0.1.134, see {@link TIdResolveOptions}) applies to the
|
|
2979
3254
|
* top-level rows only — a payload without its primary key identifies through
|
|
2980
3255
|
* a unique index; nested-relation writes ignore it.
|
|
3256
|
+
*
|
|
3257
|
+
* The nested re-entries a deep write performs on related tables get neither
|
|
3258
|
+
* `guard`, `check` nor `isFieldVisible` — they run with the table's own
|
|
3259
|
+
* integrity rules only (a nested write touches only rows related to the
|
|
3260
|
+
* record being written). A permission layer that must authorize related
|
|
3261
|
+
* tables rejects nested payloads up front.
|
|
2981
3262
|
*/
|
|
2982
3263
|
interface TWriteOptions<Row = Record<string, unknown>> extends TIdResolveOptions {
|
|
2983
3264
|
/** Nested-relation write recursion limit (default 3). */
|
|
@@ -2991,9 +3272,51 @@ interface TWriteOptions<Row = Record<string, unknown>> extends TIdResolveOptions
|
|
|
2991
3272
|
* for the nested re-entries a deep write performs on related tables.
|
|
2992
3273
|
*/
|
|
2993
3274
|
guard?: TDbWriteGuard<Row>;
|
|
3275
|
+
/**
|
|
3276
|
+
* Post-write check (since 0.1.143): invoked exactly once per top-level call,
|
|
3277
|
+
* inside the table's transaction, AFTER the main write and every
|
|
3278
|
+
* nested-relation phase — see {@link TDbWriteCheckContext}. A throw rolls
|
|
3279
|
+
* the transaction back (when `ctx.transactional`) and propagates unchanged.
|
|
3280
|
+
* Never runs for the nested re-entries a deep write performs on related tables.
|
|
3281
|
+
*/
|
|
3282
|
+
check?: TDbWriteCheck;
|
|
3283
|
+
}
|
|
3284
|
+
/**
|
|
3285
|
+
* Context handed to a write {@link TWriteOptions.check} (since 0.1.143) — and
|
|
3286
|
+
* through it to `AsDbController.checkWrite()`. Lets a permission layer verify
|
|
3287
|
+
* the POST-image of a write with the database's own filter semantics (a
|
|
3288
|
+
* row-level "WITH CHECK"): count the written rows that still match a policy
|
|
3289
|
+
* filter and throw when one does not.
|
|
3290
|
+
*/
|
|
3291
|
+
interface TDbWriteCheckContext {
|
|
3292
|
+
/** The table method the check runs for (`insertOne` → `insert`, …). */
|
|
3293
|
+
readonly action: TDbWriteAction;
|
|
3294
|
+
/**
|
|
3295
|
+
* One exact primary-key filter per row the call wrote (inserted rows by
|
|
3296
|
+
* their resulting PK, updated / replaced rows by the PK of the row the
|
|
3297
|
+
* write actually targeted), de-duplicated. Rows the write matched nothing
|
|
3298
|
+
* for are absent.
|
|
3299
|
+
*/
|
|
3300
|
+
readonly filters: ReadonlyArray<Record<string, unknown>>;
|
|
3301
|
+
/**
|
|
3302
|
+
* `true` when the check runs inside a real transaction, so a throw rolls
|
|
3303
|
+
* the write back. `false` on adapters whose transaction is a pass-through
|
|
3304
|
+
* (e.g. a standalone MongoDB) — the write is already durable, so a caller
|
|
3305
|
+
* that needs a hard guarantee must validate BEFORE the write instead.
|
|
3306
|
+
*/
|
|
3307
|
+
readonly transactional: boolean;
|
|
3308
|
+
/** Counts rows matching `filter` inside the check's transaction. */
|
|
3309
|
+
count(filter: Record<string, unknown>): Promise<number>;
|
|
2994
3310
|
}
|
|
2995
|
-
/**
|
|
2996
|
-
|
|
3311
|
+
/** A post-write check — see {@link TWriteOptions.check}. */
|
|
3312
|
+
type TDbWriteCheck = (ctx: TDbWriteCheckContext) => void | Promise<void>;
|
|
3313
|
+
/**
|
|
3314
|
+
* Options of `deleteOne`. `isFieldVisible` since 0.1.134 — see
|
|
3315
|
+
* {@link TIdResolveOptions}. `scope` since 0.1.143 — see
|
|
3316
|
+
* {@link TRowResolveOptions}; on `deleteOne` it also restricts the delete
|
|
3317
|
+
* itself (an out-of-scope row is not deleted, `{ deletedCount: 0 }`).
|
|
3318
|
+
*/
|
|
3319
|
+
interface TDeleteOptions<Row = Record<string, unknown>> extends TRowResolveOptions {
|
|
2997
3320
|
/**
|
|
2998
3321
|
* Validated-stage guard (since 0.1.128): invoked inside the table's
|
|
2999
3322
|
* transaction after the id resolved to a filter and before cascade /
|
|
@@ -3012,6 +3335,24 @@ interface TIdResolveOptions {
|
|
|
3012
3335
|
*/
|
|
3013
3336
|
isFieldVisible?: (path: string) => boolean;
|
|
3014
3337
|
}
|
|
3338
|
+
/**
|
|
3339
|
+
* Options of `resolveRowFilter` (and `deleteOne`) — see {@link TIdResolveOptions}.
|
|
3340
|
+
*
|
|
3341
|
+
* @since 0.1.143
|
|
3342
|
+
*/
|
|
3343
|
+
interface TRowResolveOptions extends TIdResolveOptions {
|
|
3344
|
+
/**
|
|
3345
|
+
* Row scope (e.g. a per-request row-level read overlay). When an id could
|
|
3346
|
+
* name several rows (a scalar equal to one row's primary key and another
|
|
3347
|
+
* row's unique key), only rows matching `scope` count while the
|
|
3348
|
+
* identifications are tried primary key first — so a row outside the scope
|
|
3349
|
+
* can never shadow one inside it, and the outcome is exactly what it would
|
|
3350
|
+
* be if the out-of-scope row did not exist. It does not filter the result
|
|
3351
|
+
* itself: AND the scope onto the returned filter (or guard the write) to
|
|
3352
|
+
* exclude an out-of-scope row the id names unambiguously. Empty = no scope.
|
|
3353
|
+
*/
|
|
3354
|
+
scope?: FilterExpr;
|
|
3355
|
+
}
|
|
3015
3356
|
/**
|
|
3016
3357
|
* Adds `null` to every optional property of `O`. Optional columns store SQL
|
|
3017
3358
|
* NULL / Mongo null, and the runtime validator accepts `null` for optional
|
|
@@ -3109,4 +3450,4 @@ declare function isJsonValueField(fd: TDbFieldMeta): boolean;
|
|
|
3109
3450
|
*/
|
|
3110
3451
|
declare function jsonValueAncestor(path: string, jsonValueParents: ReadonlySet<string>): string | undefined;
|
|
3111
3452
|
//#endregion
|
|
3112
|
-
export {
|
|
3453
|
+
export { TDbWriteAction as $, TViewJoin as $t, TCrudPermissions as A, TWriteOptions as At, TDbForeignKey as B, BaseDbAdapter as Bt, NullableOptional as C, TSearchIndexInfo as Ct, TCascadeTarget as D, TTouchManyOptions as Dt, TCascadeResolver as E, TTableResolver as Et, TDbCollation as F, WithRelation$1 as Ft, TDbInsertResult as G, TViewColumnMapping as Gt, TDbIndexField as H, TAdapterFactory as Ht, TDbDefaultFn as I, TableMetadata as It, TDbRelation as J, aliasTargetOf as Jt, TDbObjectKind as K, isAtscriptDbView as Kt, TDbDefaultValue as L, isGeoIndexableType as Lt, TDbActionIntent as M, TypedWithRelation as Mt, TDbActionLevel as N, Uniquery$1 as Nt, TColumnDiff as O, TValueFormatterPair as Ot, TDbActionProcessor as P, UniqueryControls$1 as Pt, TDbUpdateResult as Q, AtscriptRef as Qt, TDbDeleteResult as R, isGeoPointType as Rt, NavPropsOf$1 as S, TRowResolveOptions as St, PrimaryKeyOf$1 as T, TTableOptionDiff as Tt, TDbIndexType as U, TDbSpaceOptions as Ut, TDbIndex as V, DbSpace as Vt, TDbInsertManyResult as W, AtscriptDbView as Wt, TDbRemoveGuardContext as X, AtscriptQueryFieldRef$1 as Xt, TDbRemoveGuard as Y, AtscriptQueryComparison as Yt, TDbStorageType as Z, AtscriptQueryNode$1 as Zt, DbQuery as _, TMetaResponse as _t, jsonValueAncestor as a, NativeIntegrity as an, TDerivedChangeReason as at, FilterExpr$1 as b, TReferencingForeignKey as bt, AggregateControls as c, resolveDesignType as cn, TExistingColumn as ct, AggregateQuery$1 as d, DocumentFieldMapper as dn, TFieldMeta as dt, TViewPlan as en, TDbWriteCheck as et, AggregateResult as f, FieldMappingStrategy as fn, TFkLookupResolver as ft, DbPatch as g, UniquSelect as gn, TIdentification as gt, DbControls as h, TGenericLogger as hn, TIdResolveOptions as ht, isJsonValueField as i, IntegrityStrategy as in, TDeleteOptions as it, TDbActionInfo as j, TWriteTableResolver as jt, TCrudOp as k, TViewJsonType as kt, AggregateExpr$1 as l, DbEncryption as ln, TExistingForeignKey as lt, AtscriptDbWritable as m, NoopLogger as mn, TIdDescriptor as mt, TResolvedBucket as n, translateQueryTree as nn, TDbWriteGuard as nt, normalizeComputedSelect as o, AtscriptDbReadable as on, TDerivedColumn as ot, AtscriptDbTableLike as p, TReadControls as pn, TFkLookupTarget as pt, TDbReferentialAction as q, isViewType as qt, isBucketableField as r, AtscriptDbTable as rn, TDbWriteGuardContext as rt, resolveCalendarBuckets as s, DbResponse as sn, TEnsureTableOptions as st, TBucketFieldSource as t, isFieldRef as tn, TDbWriteCheckContext as tt, AggregateFn$1 as u, TDbEncryptionOptions as un, TExistingTableOption as ut, DbRow as v, TMetadataOverrides as vt, OwnPropsOf$1 as w, TSyncColumnResult as wt, FlatOf$1 as x, TRelationInfo as xt, FieldOpsFor as y, TPrimaryKeyChange as yt, TDbFieldMeta as z, ALL_BUCKET_UNITS as zt };
|