@atscript/db 0.1.147 → 0.1.148

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.
Files changed (55) hide show
  1. package/dist/{agg-CV7y8nC6.d.cts → agg-42CSpGDR.d.cts} +2 -2
  2. package/dist/{agg-D5DHsAby.d.mts → agg-Wo-smrYV.d.mts} +3 -3
  3. package/dist/agg.cjs +1 -1
  4. package/dist/agg.d.cts +2 -2
  5. package/dist/agg.d.mts +2 -2
  6. package/dist/agg.mjs +1 -1
  7. package/dist/{aggregate-fns-CtsRbZn9.cjs → aggregate-fns-C-UJRobm.cjs} +46 -7
  8. package/dist/{aggregate-fns-C0BymEqa.mjs → aggregate-fns-CyaZyb9I.mjs} +35 -8
  9. package/dist/aggregate-rules-D_bsCpUI.cjs +26 -0
  10. package/dist/aggregate-rules-jdPrxqWa.mjs +15 -0
  11. package/dist/{buckets-DYopfd2Y.d.mts → buckets-CNdTOnei.d.mts} +312 -18
  12. package/dist/{buckets-CjdPipCC.d.cts → buckets-DJiYlMXc.d.cts} +312 -18
  13. package/dist/{column-diff-Dt7EDJsA.cjs → column-diff-CUU4GvYg.cjs} +681 -87
  14. package/dist/{column-diff-CO06iQvI.mjs → column-diff-Cp6ZoyRE.mjs} +678 -96
  15. package/dist/{db-error-D5uilS_A.mjs → db-error-Az85UhTX.mjs} +32 -1
  16. package/dist/{db-error-DTkkeu5b.cjs → db-error-DRQH4sLY.cjs} +55 -0
  17. package/dist/{fk-diff-BtOmL4OW.d.mts → fk-diff-BQ4krij8.d.cts} +1 -1
  18. package/dist/{fk-diff-DLqwVkKG.d.cts → fk-diff-DsaIijVX.d.mts} +1 -1
  19. package/dist/index.cjs +70 -5
  20. package/dist/index.d.cts +58 -13
  21. package/dist/index.d.mts +58 -13
  22. package/dist/index.mjs +64 -6
  23. package/dist/{nested-writer-SqtYJHF0.cjs → nested-writer-BUQvk6QT.cjs} +68 -2
  24. package/dist/{nested-writer-D35UsDBT.mjs → nested-writer-CUBoq1ZO.mjs} +57 -3
  25. package/dist/numeric-operand-B1jKH7x5.mjs +21 -0
  26. package/dist/numeric-operand-DKfiRLYp.cjs +26 -0
  27. package/dist/ops.cjs +1 -1
  28. package/dist/ops.mjs +1 -1
  29. package/dist/plugin.cjs +36 -9
  30. package/dist/plugin.mjs +36 -9
  31. package/dist/rel.cjs +2 -2
  32. package/dist/rel.d.cts +2 -2
  33. package/dist/rel.d.mts +2 -2
  34. package/dist/rel.mjs +2 -2
  35. package/dist/{relation-helpers-C2bLtE-t.d.mts → relation-helpers-Ba0v49sn.d.mts} +1 -1
  36. package/dist/{relation-helpers-DH3LvwLV.d.cts → relation-helpers-kX7jjgME.d.cts} +1 -1
  37. package/dist/{relation-loader-C0qE8xgR.mjs → relation-loader-ByY1Byrl.mjs} +1 -1
  38. package/dist/{relation-loader-BFhVuJ-B.cjs → relation-loader-D8OrdH-r.cjs} +1 -1
  39. package/dist/shared.cjs +3 -0
  40. package/dist/shared.d.cts +12 -1
  41. package/dist/shared.d.mts +12 -1
  42. package/dist/shared.mjs +2 -1
  43. package/dist/sync.cjs +2 -2
  44. package/dist/sync.d.cts +2 -2
  45. package/dist/sync.d.mts +2 -2
  46. package/dist/sync.mjs +2 -2
  47. package/dist/{validator-Clu2q_7z.mjs → validator-BTiIOTKP.mjs} +9 -3
  48. package/dist/{validator-CVS-onRg.cjs → validator-UcuJxHNT.cjs} +8 -2
  49. package/dist/{validator-CMnTI6r7.d.cts → validator-tBNvM1qc.d.cts} +23 -2
  50. package/dist/{validator-CMnTI6r7.d.mts → validator-tBNvM1qc.d.mts} +23 -2
  51. package/dist/validator.cjs +2 -2
  52. package/dist/validator.d.cts +1 -1
  53. package/dist/validator.d.mts +1 -1
  54. package/dist/validator.mjs +2 -2
  55. package/package.json +8 -8
package/dist/index.d.mts CHANGED
@@ -1,13 +1,13 @@
1
- import { $ as TDbStorageType, $t as AtscriptExprNode, A as TCrudPermissions, An as TDbEncryptionOptions, At as TValueFormatterPair, B as TDbDeleteResult, Bt as isGeoPointType, C as NullableOptional, Cn as andFilters, Ct as TRelationInfo, D as TCascadeTarget, Dn as isResolvedRelationFilter, Dt as TTableOptionDiff, E as TCascadeResolver, En as hasRelationOp, Et as TSyncColumnResult, F as TDbActionTargetSummary, Fn as TGenericLogger, Ft as Uniquery, G as TDbIndexType, Gt as DbSpace, H as TDbForeignKey, Ht as ALL_VIEW_CAPABILITIES, I as TDbAvailableActions, In as UniquSelect, It as UniqueryControls, J as TDbObjectKind, Jt as AtscriptDbView, K as TDbInsertManyResult, Kt as TAdapterFactory, L as TDbCollation, Lt as WithRelation, M as TDbActionIntent, Mn as FieldMappingStrategy, Mt as TWriteOptions, N as TDbActionLevel, Nn as TReadControls, Nt as TWriteTableResolver, O as TColumnDiff, On as relationStaticFilter, Ot as TTableResolver, P as TDbActionProcessor, Pn as NoopLogger, Pt as TypedWithRelation, Q as TDbRemoveGuardContext, Qt as aliasTargetOf, R as TDbDefaultFn, Rt as TableMetadata, S as NavPropsOf, Sn as TRelationStaticFilter, St as TReferencingForeignKey, T as PrimaryKeyOf, Tn as forEachResolvedRelation, Tt as TSearchIndexInfo, U as TDbIndex, Ut as BaseDbAdapter, V as TDbFieldMeta, Vt as ALL_BUCKET_UNITS, W as TDbIndexField, Wt as TViewCapability, X as TDbRelation, Xt as isAtscriptDbView, Y as TDbReferentialAction, Yt as TViewColumnMapping, Z as TDbRemoveGuard, Zt as isViewType, _ as DbQuery, _n as REL_FILTER_MAX_NODES, _t as TIdResolveOptions, a as jsonValueAncestor, an as TViewJoin, at as TDbWriteGuardContext, b as FilterExpr, bn as TRelationFilterJunction, bt as TMetadataOverrides, c as AggregateControls, cn as translateQueryTree, ct as TDerivedColumn, d as AggregateQuery, dn as NativeIntegrity, dt as TExistingForeignKey, en as AtscriptOrderItem, et as TDbUpdateResult, f as AggregateResult, fn as TCascadePin, ft as TExistingTableOption, g as DbPatch, gn as REL_FILTER_MAX_DEPTH, gt as TIdDescriptor, h as DbControls, hn as resolveDesignType, ht as TFkLookupTarget, i as isJsonValueField, in as AtscriptRef, it as TDbWriteGuard, j as TDbActionInfo, jn as DocumentFieldMapper, jt as TViewJsonType, k as TCrudOp, kn as DbEncryption, kt as TTouchManyOptions, l as AggregateExpr, ln as AtscriptDbTable, lt as TEnsureTableOptions, m as AtscriptDbWritable, mn as DbResponse, mt as TFkLookupResolver, n as TResolvedBucket, nn as AtscriptQueryFieldRef, nt as TDbWriteCheck, o as normalizeComputedSelect, on as TViewPlan, ot as TDeleteOptions, pn as AtscriptDbReadable, pt as TFieldMeta, q as TDbInsertResult, qt as TDbSpaceOptions, r as isBucketableField, rn as AtscriptQueryNode, rt as TDbWriteCheckContext, s as resolveCalendarBuckets, sn as isFieldRef, st as TDerivedChangeReason, t as TBucketFieldSource, tn as AtscriptQueryComparison, tt as TDbWriteAction, u as AggregateFn, un as IntegrityStrategy, ut as TExistingColumn, v as DbRow, vn as ResolvedRelationFilter, vt as TIdentification, w as OwnPropsOf, wn as containsRelationFilter, wt as TRowResolveOptions, x as FlatOf, xn as TRelationFilterTable, xt as TPrimaryKeyChange, y as FieldOpsFor, yn as TRelGuardState, yt as TMetaResponse, z as TDbDefaultValue, zt as isGeoIndexableType } from "./buckets-DYopfd2Y.mjs";
1
+ import { $ as TDbReferentialAction, $t as AtscriptDbView, A as TCrudOp, An as containsRelationFilter, At as TSearchIndexInfo, B as TDbDefaultValue, Bn as NoopLogger, Bt as Uniquery, C as NavPropsOf, Cn as REL_FILTER_MAX_NODES, Ct as TInsertOptions, D as TCascadeResolver, Dn as TRelationFilterTable, Dt as TReferencingForeignKey, E as PrimaryKeyOf, En as TRelationFilterJunction, Et as TPrimaryKeyChange, F as TDbActionProcessor, Fn as DbEncryption, Ft as TValueFormatterPair, G as TDbIndexField, Gn as UniquSelect, Gt as isGeoPointType, H as TDbFieldMeta, Hn as TExprAggregate, Ht as WithRelation, I as TDbActionTargetSummary, In as TDbEncryptionOptions, It as TViewJsonType, J as TDbInsertIgnoreSlot, Jt as BaseDbAdapter, K as TDbIndexType, Kt as ALL_BUCKET_UNITS, L as TDbAvailableActions, Ln as DocumentFieldMapper, Lt as TWriteOptions, M as TDbActionInfo, Mn as hasRelationOp, Mt as TTableOptionDiff, N as TDbActionIntent, Nn as isResolvedRelationFilter, Nt as TTableResolver, O as TCascadeTarget, On as TRelationStaticFilter, Ot as TRelationInfo, P as TDbActionLevel, Pn as relationStaticFilter, Pt as TTouchManyOptions, Q as TDbObjectKind, Qt as TDbSpaceOptions, R as TDbCollation, Rn as FieldMappingStrategy, Rt as TWriteTableResolver, S as FlatOf, Sn as REL_FILTER_MAX_DEPTH, St as TIdentification, T as OwnPropsOf, Tn as TRelGuardState, Tt as TMetadataOverrides, U as TDbForeignKey, Un as TFirstLast, Ut as TableMetadata, V as TDbDeleteResult, Vn as TGenericLogger, Vt as UniqueryControls, W as TDbIndex, Wn as TRowOrderKey, Wt as isGeoIndexableType, X as TDbInsertManyResult, Xt as DbSpace, Y as TDbInsertManyIgnoreResult, Yt as TViewCapability, Z as TDbInsertResult, Zt as TAdapterFactory, _ as DbPatch, _n as NativeIntegrity, _t as TFieldMeta, a as isJsonValueField, an as AtscriptOrderItem, at as TDbWriteAction, b as FieldOpsFor, bn as DbResponse, bt as TIdDescriptor, c as resolveCalendarBuckets, cn as AtscriptQueryNode, ct as TDbWriteGuard, d as AggregateFn, dn as TViewPlan, dt as TDerivedChangeReason, en as TViewColumnMapping, et as TDbRelation, f as AggregateQuery, fn as evaluateExpr, ft as TDerivedColumn, g as DbControls, gn as IntegrityStrategy, gt as TExistingTableOption, h as AtscriptDbWritable, hn as AtscriptDbTable, ht as TExistingForeignKey, i as isBucketableField, in as AtscriptExprNode, it as TDbUpdateResult, j as TCrudPermissions, jn as forEachResolvedRelation, jt as TSyncColumnResult, k as TColumnDiff, kn as andFilters, kt as TRowResolveOptions, l as AggregateControls, ln as AtscriptRef, lt as TDbWriteGuardContext, mn as translateQueryTree, mt as TExistingColumn, n as TComputedSelect, nn as isViewType, nt as TDbRemoveGuardContext, o as jsonValueAncestor, on as AtscriptQueryComparison, ot as TDbWriteCheck, p as AggregateResult, pn as isFieldRef, pt as TEnsureTableOptions, q as TDbInsertIgnoreResult, qt as ALL_VIEW_CAPABILITIES, r as TResolvedBucket, rn as aliasTargetOf, rt as TDbStorageType, s as normalizeComputedSelect, sn as AtscriptQueryFieldRef, st as TDbWriteCheckContext, t as TBucketFieldSource, tn as isAtscriptDbView, tt as TDbRemoveGuard, u as AggregateExpr, un as TViewJoin, ut as TDeleteOptions, v as DbQuery, vn as TCascadePin, vt as TFkLookupResolver, w as NullableOptional, wn as ResolvedRelationFilter, wt as TMetaResponse, x as FilterExpr, xn as resolveDesignType, xt as TIdResolveOptions, y as DbRow, yn as AtscriptDbReadable, yt as TFkLookupTarget, z as TDbDefaultFn, zn as TReadControls, zt as TypedWithRelation } from "./buckets-CNdTOnei.mjs";
2
2
  import { _ as separateFieldOps, a as $mul, c as $update, d as TDbFieldOp, f as TFieldOps, g as separateCas, h as reconcileCas, i as $insert, l as $upsert, m as isDbFieldOp, n as $dec, o as $remove, p as getDbFieldOp, r as $inc, s as $replace, t as $cas, u as TDbCas } from "./ops-AqhV7s9o.mjs";
3
3
  import { a as isPlainObject, i as isEmptyObject, n as findAncestorInSet, o as selfOrAncestor, r as getPath, t as deletePath } from "./object-CtPYTIvy.mjs";
4
- import { c as CalendarBucketLabel, d as WeekStart, g as ALL_AGGREGATE_FNS, l as ComputedExpr, o as BucketExpr, s as BucketUnit, u as ResolvedBucket } from "./agg-D5DHsAby.mjs";
5
- import { a as buildValidationContext, c as isNavRelation, d as getKeyProps, f as CasExhaustedError, g as bucketTimeZoneUnavailable, h as DbErrorCode, l as TArrayPatch, m as DbError, n as ValidatorMode, p as CasMismatchError, r as buildDbValidator, s as forceNavNonOptional, t as ValidationContext, u as TDbPatch } from "./validator-CMnTI6r7.mjs";
4
+ import { c as CalendarBucketLabel, d as WeekStart, g as ALL_AGGREGATE_FNS, l as ComputedExpr, o as BucketExpr, s as BucketUnit, u as ResolvedBucket } from "./agg-Wo-smrYV.mjs";
5
+ import { _ as aggregateFailure, a as buildValidationContext, c as isNavRelation, d as getKeyProps, f as CasExhaustedError, g as aggregateExpressionsNotSupported, h as DbErrorCode, l as TArrayPatch, m as DbError, n as ValidatorMode, p as CasMismatchError, r as buildDbValidator, s as forceNavNonOptional, t as ValidationContext, u as TDbPatch, v as bucketTimeZoneUnavailable, y as isConflict } from "./validator-tBNvM1qc.mjs";
6
6
  import { n as createDbValidatorPlugin, t as DbValidationContext } from "./db-validator-plugin-BWy60OvG.mjs";
7
- import { r as fkColumns, s as isColumnTypeChanged } from "./fk-diff-BtOmL4OW.mjs";
8
- import { i as tableNameOf } from "./relation-helpers-C2bLtE-t.mjs";
9
- import { TAtscriptAnnotatedType } from "@atscript/typescript/utils";
10
- import { AggregateQuery as AggregateQuery$1, FilterExpr as FilterExpr$1, FilterVisitor, RELATION_OPS, RelationOp, RelationOp as RelationOp$1, ResolvedBucket as ResolvedBucket$1, Uniquery as Uniquery$1, computeInsights, isPrimitive, isRelationOp, walkFilter } from "@uniqu/core";
7
+ import { r as fkColumns, s as isColumnTypeChanged } from "./fk-diff-DsaIijVX.mjs";
8
+ import { i as tableNameOf } from "./relation-helpers-Ba0v49sn.mjs";
9
+ import { AtscriptExprNode as AtscriptExprNode$1, TAtscriptAnnotatedType } from "@atscript/typescript/utils";
10
+ import { AggregateQuery as AggregateQuery$1, FilterExpr as FilterExpr$1, FilterVisitor, RELATION_OPS, RelationOp, RelationOp as RelationOp$1, ResolvedRowOrderKey, ResolvedSelectExpr, Uniquery as Uniquery$1, computeInsights, isPrimitive, isRelationOp, walkFilter } from "@uniqu/core";
11
11
 
12
12
  //#region src/shared/consts.d.ts
13
13
  /**
@@ -149,6 +149,7 @@ interface TGuardedQuery {
149
149
  $select?: unknown;
150
150
  $groupBy?: unknown;
151
151
  $having?: unknown;
152
+ $rowOrder?: unknown;
152
153
  };
153
154
  }
154
155
  /**
@@ -244,6 +245,28 @@ type TBucketSourceVerdict = {
244
245
  code: "encrypted" | "jsonDescendant" | "notTimestamp" | "notFilterable" | "notDimension" | "noBuckets";
245
246
  reason: string;
246
247
  };
248
+ /** {@link groupSourceVerdict}'s answer — the `reason` clause has no trailing period. */
249
+ type TGroupSourceVerdict = {
250
+ ok: true;
251
+ } | {
252
+ ok: false;
253
+ code: "encrypted" | "notFilterable" | "notDimension";
254
+ reason: string;
255
+ };
256
+ /**
257
+ * Whether the stored leaf `fd` may be a `$groupBy` key (since 0.1.148) — the
258
+ * one rule for the core's strict-table check and moost-db's capability index
259
+ * (`/meta.fields[P].groupable` and the HTTP gate). First failing rule wins:
260
+ *
261
+ * 1. `encrypted` — `@db.encrypted`;
262
+ * 2. `notFilterable` — the adapter cannot filter (so cannot group) the storage;
263
+ * 3. `notDimension` — a strict table ({@link isStrictTable}) and the field is
264
+ * not a dimension.
265
+ *
266
+ * A calendar-bucket alias is not a field: it groups by its source, whose
267
+ * dimension rule is {@link bucketSourceVerdict}'s (callers skip aliases).
268
+ */
269
+ declare function groupSourceVerdict(fd: TDbFieldMeta, table: Pick<TBucketSourceTable, "dimensions" | "measures">, adapter: Pick<BaseDbAdapter, "canFilterField">): TGroupSourceVerdict;
247
270
  /**
248
271
  * Whether the stored leaf `fd` may be the source of a calendar bucket
249
272
  * (since 0.1.133) — every schema and adapter rule, once, for the core path
@@ -302,8 +325,9 @@ interface TQueryPathRefs {
302
325
  *
303
326
  * Aggregate mode is `aggregate` when given, else the presence of `$groupBy`.
304
327
  * In aggregate mode `$select` computed entries are collected by kind — an
305
- * aggregate's `$field` into `aggregate`, a calendar bucket's into `bucket` —
306
- * and their aliases (`$as`, else uniqu's `resolveAlias`) are exempted from
328
+ * aggregate's `$field` (a row-level expression's names, a `first` / `last`
329
+ * field) into `aggregate`, a calendar bucket's into `bucket`, a `$rowOrder`
330
+ * key into `sort` — and their aliases (`$as`, else uniqu's `resolveAlias`) are exempted from
307
331
  * `$sort` / `$having`; a bucket alias is also dropped from `groupBy`, which
308
332
  * lists grouped fields only.
309
333
  *
@@ -414,10 +438,11 @@ declare function checkHavingKeys(refs: TQueryPathRefs): {
414
438
  * ({@link checkHavingKeys} — after the path guard so an unknown key still
415
439
  * reads `Unknown field`), then the `$having` values (`guardHavingValues`).
416
440
  *
417
- * `buckets` are the query's resolved calendar buckets when the caller already
418
- * ran `normalizeComputedSelect` (resolved here otherwise).
441
+ * `resolved` is the query's normalized computed `$select`
442
+ * (`resolveComputedSelect`) when the caller already ran it (resolved here
443
+ * otherwise).
419
444
  */
420
- declare function guardAggregate(meta: TableMetadata, adapter: BaseDbAdapter, query: AggregateQuery$1, resolved?: readonly ResolvedBucket$1[]): void;
445
+ declare function guardAggregate(meta: TableMetadata, adapter: BaseDbAdapter, query: AggregateQuery$1, resolved?: TComputedSelect): void;
421
446
  //#endregion
422
447
  //#region src/with-optimistic-retry.d.ts
423
448
  interface WithOptimisticRetryOptions {
@@ -458,6 +483,14 @@ interface WithOptimisticRetryOptions {
458
483
  */
459
484
  declare function withOptimisticRetry<TRow extends Record<string, unknown>>(table: AtscriptDbTable, filter: Record<string, unknown>, mutator: (row: TRow) => Promise<Record<string, unknown> | undefined> | Record<string, unknown> | undefined, opts?: WithOptimisticRetryOptions): Promise<TDbUpdateResult>;
460
485
  //#endregion
486
+ //#region src/shared/keys.d.ts
487
+ /**
488
+ * Identity of the key tuple `fields` of `row` for uniqueness checks, or
489
+ * `undefined` when any component is null / missing (a NULL never collides).
490
+ * Equal across driver representations (see {@link keyString}).
491
+ */
492
+ declare function uniqueKeyTuple(row: Record<string, unknown>, fields: readonly string[]): string | undefined;
493
+ //#endregion
461
494
  //#region src/shared/index-messages.d.ts
462
495
  /**
463
496
  * Wording of the "index not found" errors — one source for the core, every
@@ -556,4 +589,16 @@ declare function createFailureCollector(what: string): {
556
589
  throwIfAny: () => void;
557
590
  };
558
591
  //#endregion
559
- export { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, ADAPTER_FILTER_REASON, ALL_AGGREGATE_FNS, ALL_BUCKET_UNITS, ALL_VIEW_CAPABILITIES, type AggregateControls, type AggregateExpr, type AggregateFn, type AggregateQuery, type AggregateResult, ApplicationIntegrity, AtscriptDbReadable, AtscriptDbTable, AtscriptDbView, type AtscriptDbWritable, type AtscriptExprNode, type AtscriptOrderItem, type AtscriptQueryComparison, type AtscriptQueryFieldRef, type AtscriptQueryNode, type AtscriptRef, BaseDbAdapter, type BucketExpr, type BucketUnit, type CalendarBucketLabel, CasExhaustedError, CasMismatchError, type ComputedExpr, DEFAULT_DB_SPACE, type DbControls, DbEncryption, DbError, type DbErrorCode, type DbPatch, type DbQuery, type DbResponse, type DbRow, DbSpace, type DbValidationContext, DocumentFieldMapper, ENCRYPTED_REASON, FieldMappingStrategy, type FieldOpsFor, type FilterExpr, type FilterVisitor, type FlatOf, IntegrityStrategy, NativeIntegrity, type NavPropsOf, NoopLogger, type NullableOptional, type OwnPropsOf, type PrimaryKeyOf, RELATION_OPS, REL_FILTER_MAX_DEPTH, REL_FILTER_MAX_NODES, type RelationOp, RelationalFieldMapper, type ResolvedBucket, ResolvedRelationFilter, type TAdapterFactory, type TArrayPatch, type TBucketFieldSource, type TBucketSourceTable, type TBucketSourceVerdict, type TCascadeResolver, type TCascadeTarget, type TColumnDiff, type TCrudOp, type TCrudPermissions, type TDbActionInfo, type TDbActionIntent, type TDbActionLevel, type TDbActionProcessor, type TDbActionTargetSummary, type TDbAvailableActions, type TDbCas, type TDbCollation, type TDbDefaultFn, type TDbDefaultValue, type TDbDeleteResult, type TDbEncryptionOptions, type TDbFieldMeta, type TDbFieldOp, type TDbForeignKey, type TDbIndex, type TDbIndexField, type TDbIndexType, type TDbInsertManyResult, type TDbInsertResult, type TDbObjectKind, type TDbPatch, type TDbReferentialAction, type TDbRelation, type TDbRemoveGuard, type TDbRemoveGuardContext, type TDbSpaceOptions, type TDbStorageType, type TDbUpdateResult, type TDbWriteAction, type TDbWriteCheck, type TDbWriteCheckContext, type TDbWriteGuard, type TDbWriteGuardContext, type TDeleteOptions, type TDerivedChangeReason, type TDerivedColumn, type TEnsureTableOptions, type TExistingColumn, type TExistingForeignKey, type TExistingTableOption, type TFieldMeta, type TFieldOps, type TFilterPredicate, type TFilterRef, type TFkLookupResolver, type TFkLookupTarget, type TGenericLogger, type TGuardedQuery, type TIdDescriptor, type TIdResolveOptions, type TIdentification, type TMetaResponse, type TMetadataOverrides, type TPrimaryKeyChange, type TQueryPathKind, type TQueryPathOp, type TQueryPathRefs, type TQueryPathSource, type TReadControls, type TReferencingForeignKey, type TRelationFilterJunction, type TRelationFilterTable, type TRelationInfo, type TRelationStaticFilter, type TResolvedBucket, type TRowResolveOptions, type TSearchIndexInfo, type TSyncColumnResult, type TTableOptionDiff, type TTableResolver, type TTouchManyOptions, type TValueFormatterPair, type TViewCapability, type TViewColumnMapping, type TViewJoin, type TViewJsonType, type TViewPlan, type TWriteOptions, type TWriteTableResolver, TableMetadata, type TypedWithRelation, UniquSelect, type Uniquery, type UniqueryControls, type ValidationContext, type ValidatorMode, type WeekStart, type WithOptimisticRetryOptions, type WithRelation, acceptedOperatorsHint, aliasTargetOf, andFilters, assertGeoPoint, assertNoVersionWrites, bucketSourceVerdict, bucketTimeZoneUnavailable, buildDbValidator, buildValidationContext, canFilterLeaf, checkHavingKeys, classifyQueryPath, collectQueryPaths, computeInsights, containsRelationFilter, createDbValidatorPlugin, createFailureCollector, decomposePatch, deletePath, findAncestorInSet, fkColumns, forEachResolvedRelation, forceNavNonOptional, geoIndexNotFoundMessage, getDbFieldOp, getKeyProps, getPath, guardAggregate, guardFilter, guardPath, guardPaths, guardQuery, hasRelationOp, isAtscriptDbView, isBucketableField, isColumnTypeChanged, isDbEntityType, isDbFieldOp, isEmptyObject, isFieldRef, isGeoIndexableType, isGeoPointType, isJsonValueField, isNavRelation, isPlainObject, isPrimitive, isRelationOp, isResolvedRelationFilter, isViewType, jsonValueAncestor, narrowerFilterOps, normalizeComputedSelect, reconcileCas, relationStaticFilter, resolveCalendarBuckets, resolveDesignType, searchIndexNotFoundMessage, selfOrAncestor, separateCas, separateFieldOps, sortFieldNames, tableNameOf, translateQueryTree, unsupportedOperatorMessage, vectorIndexNotFoundMessage, walkFilter, withOptimisticRetry };
592
+ //#region src/query/aggregate-expr.d.ts
593
+ /**
594
+ * Why a field cannot be an arithmetic operand, or `undefined` when it can: it
595
+ * must be a `number` (not a decimal — those are exact, an expression is IEEE
596
+ * double — and not a timestamp-tagged number) with plain column storage. The
597
+ * runtime twin of `@db.compute`'s operand rule, so declared and query-time
598
+ * arithmetic accept the same fields.
599
+ *
600
+ * @since 0.1.148
601
+ */
602
+ declare function numericOperandProblem(fd: TDbFieldMeta): string | undefined;
603
+ //#endregion
604
+ export { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, ADAPTER_FILTER_REASON, ALL_AGGREGATE_FNS, ALL_BUCKET_UNITS, ALL_VIEW_CAPABILITIES, type AggregateControls, type AggregateExpr, type AggregateFn, type AggregateQuery, type AggregateResult, ApplicationIntegrity, AtscriptDbReadable, AtscriptDbTable, AtscriptDbView, type AtscriptDbWritable, type AtscriptExprNode, type AtscriptOrderItem, type AtscriptQueryComparison, type AtscriptQueryFieldRef, type AtscriptQueryNode, type AtscriptRef, BaseDbAdapter, type BucketExpr, type BucketUnit, type CalendarBucketLabel, CasExhaustedError, CasMismatchError, type ComputedExpr, DEFAULT_DB_SPACE, type DbControls, DbEncryption, DbError, type DbErrorCode, type DbPatch, type DbQuery, type DbResponse, type DbRow, DbSpace, type DbValidationContext, DocumentFieldMapper, ENCRYPTED_REASON, FieldMappingStrategy, type FieldOpsFor, type FilterExpr, type FilterVisitor, type FlatOf, IntegrityStrategy, NativeIntegrity, type NavPropsOf, NoopLogger, type NullableOptional, type OwnPropsOf, type PrimaryKeyOf, RELATION_OPS, REL_FILTER_MAX_DEPTH, REL_FILTER_MAX_NODES, type RelationOp, RelationalFieldMapper, type ResolvedBucket, ResolvedRelationFilter, type TAdapterFactory, type TArrayPatch, type TBucketFieldSource, type TBucketSourceTable, type TBucketSourceVerdict, type TCascadeResolver, type TCascadeTarget, type TColumnDiff, type TCrudOp, type TCrudPermissions, type TDbActionInfo, type TDbActionIntent, type TDbActionLevel, type TDbActionProcessor, type TDbActionTargetSummary, type TDbAvailableActions, type TDbCas, type TDbCollation, type TDbDefaultFn, type TDbDefaultValue, type TDbDeleteResult, type TDbEncryptionOptions, type TDbFieldMeta, type TDbFieldOp, type TDbForeignKey, type TDbIndex, type TDbIndexField, type TDbIndexType, type TDbInsertIgnoreResult, type TDbInsertIgnoreSlot, type TDbInsertManyIgnoreResult, type TDbInsertManyResult, type TDbInsertResult, type TDbObjectKind, type TDbPatch, type TDbReferentialAction, type TDbRelation, type TDbRemoveGuard, type TDbRemoveGuardContext, type TDbSpaceOptions, type TDbStorageType, type TDbUpdateResult, type TDbWriteAction, type TDbWriteCheck, type TDbWriteCheckContext, type TDbWriteGuard, type TDbWriteGuardContext, type TDeleteOptions, type TDerivedChangeReason, type TDerivedColumn, type TEnsureTableOptions, type TExistingColumn, type TExistingForeignKey, type TExistingTableOption, type TExprAggregate, type TFieldMeta, type TFieldOps, type TFilterPredicate, type TFilterRef, type TFirstLast, type TFkLookupResolver, type TFkLookupTarget, type TGenericLogger, type TGroupSourceVerdict, type TGuardedQuery, type TIdDescriptor, type TIdResolveOptions, type TIdentification, type TInsertOptions, type TMetaResponse, type TMetadataOverrides, type TPrimaryKeyChange, type TQueryPathKind, type TQueryPathOp, type TQueryPathRefs, type TQueryPathSource, type TReadControls, type TReferencingForeignKey, type TRelationFilterJunction, type TRelationFilterTable, type TRelationInfo, type TRelationStaticFilter, type TResolvedBucket, type TRowOrderKey, type TRowResolveOptions, type TSearchIndexInfo, type TSyncColumnResult, type TTableOptionDiff, type TTableResolver, type TTouchManyOptions, type TValueFormatterPair, type TViewCapability, type TViewColumnMapping, type TViewJoin, type TViewJsonType, type TViewPlan, type TWriteOptions, type TWriteTableResolver, TableMetadata, type TypedWithRelation, UniquSelect, type Uniquery, type UniqueryControls, type ValidationContext, type ValidatorMode, type WeekStart, type WithOptimisticRetryOptions, type WithRelation, acceptedOperatorsHint, aggregateExpressionsNotSupported, aggregateFailure, aliasTargetOf, andFilters, assertGeoPoint, assertNoVersionWrites, bucketSourceVerdict, bucketTimeZoneUnavailable, buildDbValidator, buildValidationContext, canFilterLeaf, checkHavingKeys, classifyQueryPath, collectQueryPaths, computeInsights, containsRelationFilter, createDbValidatorPlugin, createFailureCollector, decomposePatch, deletePath, evaluateExpr, findAncestorInSet, fkColumns, forEachResolvedRelation, forceNavNonOptional, geoIndexNotFoundMessage, getDbFieldOp, getKeyProps, getPath, groupSourceVerdict, guardAggregate, guardFilter, guardPath, guardPaths, guardQuery, hasRelationOp, isAtscriptDbView, isBucketableField, isColumnTypeChanged, isConflict, isDbEntityType, isDbFieldOp, isEmptyObject, isFieldRef, isGeoIndexableType, isGeoPointType, isJsonValueField, isNavRelation, isPlainObject, isPrimitive, isRelationOp, isResolvedRelationFilter, isViewType, jsonValueAncestor, narrowerFilterOps, normalizeComputedSelect, numericOperandProblem, reconcileCas, relationStaticFilter, resolveCalendarBuckets, resolveDesignType, searchIndexNotFoundMessage, selfOrAncestor, separateCas, separateFieldOps, sortFieldNames, tableNameOf, translateQueryTree, uniqueKeyTuple, unsupportedOperatorMessage, vectorIndexNotFoundMessage, walkFilter, withOptimisticRetry };
package/dist/index.mjs CHANGED
@@ -1,12 +1,12 @@
1
- import { a as bucketTimeZoneUnavailable, n as CasMismatchError, r as DbError, t as CasExhaustedError } from "./db-error-D5uilS_A.mjs";
2
- import { $ as UniquSelect, A as geoIndexNotFoundMessage, B as classifyQueryPath, C as ALL_VIEW_CAPABILITIES, D as NativeIntegrity, E as IntegrityStrategy, F as acceptedOperatorsHint, G as guardPaths, H as guardAggregate, I as assertGeoPoint, J as sortFieldNames, K as guardQuery, L as bucketSourceVerdict, M as vectorIndexNotFoundMessage, N as ADAPTER_FILTER_REASON, O as AtscriptDbReadable, P as ENCRYPTED_REASON, Q as FieldMappingStrategy, R as canFilterLeaf, S as ALL_BUCKET_UNITS, T as createFailureCollector, U as guardFilter, V as collectQueryPaths, W as guardPath, X as RelationalFieldMapper, Y as unsupportedOperatorMessage, Z as DocumentFieldMapper, _ as isViewType, at as isJsonValueField, b as decomposePatch, ct as resolveCalendarBuckets, et as TableMetadata, f as fkColumns, g as isAtscriptDbView, h as AtscriptDbView, it as isBucketableField, j as searchIndexNotFoundMessage, k as resolveDesignType, lt as NoopLogger, n as isColumnTypeChanged, nt as isGeoPointType, ot as jsonValueAncestor, q as narrowerFilterOps, rt as aliasTargetOf, st as normalizeComputedSelect, tt as isGeoIndexableType, v as AtscriptDbTable, w as BaseDbAdapter, x as ApplicationIntegrity, y as assertNoVersionWrites, z as checkHavingKeys } from "./column-diff-CO06iQvI.mjs";
3
- import { n as ALL_AGGREGATE_FNS } from "./aggregate-fns-C0BymEqa.mjs";
4
- import { B as tableNameOf, C as ResolvedRelationFilter, D as forEachResolvedRelation, M as relationStaticFilter, O as hasRelationOp, S as REL_FILTER_MAX_NODES, T as containsRelationFilter, U as isFieldRef, W as translateQueryTree, k as isResolvedRelationFilter, w as andFilters, x as REL_FILTER_MAX_DEPTH } from "./nested-writer-D35UsDBT.mjs";
1
+ import { a as aggregateExpressionsNotSupported, c as isConflict, l as spaceClosedError, n as CasMismatchError, o as aggregateFailure, r as DbError, s as bucketTimeZoneUnavailable, t as CasExhaustedError } from "./db-error-Az85UhTX.mjs";
2
+ import { $ as FieldMappingStrategy, A as geoIndexNotFoundMessage, B as classifyQueryPath, C as ALL_VIEW_CAPABILITIES, D as NativeIntegrity, E as IntegrityStrategy, F as acceptedOperatorsHint, G as guardPath, H as groupSourceVerdict, I as assertGeoPoint, J as narrowerFilterOps, K as guardPaths, L as bucketSourceVerdict, M as vectorIndexNotFoundMessage, N as ADAPTER_FILTER_REASON, O as AtscriptDbReadable, P as ENCRYPTED_REASON, Q as DocumentFieldMapper, R as canFilterLeaf, S as ALL_BUCKET_UNITS, T as createFailureCollector, U as guardAggregate, V as collectQueryPaths, W as guardFilter, X as unsupportedOperatorMessage, Y as sortFieldNames, Z as RelationalFieldMapper, _ as isViewType, at as aliasTargetOf, b as decomposePatch, ct as jsonValueAncestor, dt as NoopLogger, et as UniquSelect, f as fkColumns, g as isAtscriptDbView, h as AtscriptDbView, it as isGeoPointType, j as searchIndexNotFoundMessage, k as resolveDesignType, lt as normalizeComputedSelect, n as isColumnTypeChanged, nt as TableMetadata, ot as isBucketableField, q as guardQuery, rt as isGeoIndexableType, st as isJsonValueField, tt as numericOperandProblem, ut as resolveCalendarBuckets, v as AtscriptDbTable, w as BaseDbAdapter, x as ApplicationIntegrity, y as assertNoVersionWrites, z as checkHavingKeys } from "./column-diff-Cp6ZoyRE.mjs";
3
+ import { n as ALL_AGGREGATE_FNS } from "./aggregate-fns-CyaZyb9I.mjs";
4
+ import { A as isResolvedRelationFilter, C as REL_FILTER_MAX_NODES, E as containsRelationFilter, G as isFieldRef, K as translateQueryTree, N as relationStaticFilter, O as forEachResolvedRelation, S as REL_FILTER_MAX_DEPTH, T as andFilters, V as tableNameOf, W as evaluateExpr, k as hasRelationOp, w as ResolvedRelationFilter, x as uniqueKeyTuple } from "./nested-writer-CUBoq1ZO.mjs";
5
5
  import { t as DB_ENTITY_ANNOTATIONS } from "./derived-rules-0sKn4f5C.mjs";
6
6
  import { a as isPlainObject, i as isEmptyObject, n as findAncestorInSet, o as selfOrAncestor, r as getPath, t as deletePath } from "./object-TkiJQ-Dp.mjs";
7
7
  import { t as DEFAULT_DB_SPACE } from "./consts-C_-5_pFq.mjs";
8
8
  import { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, getDbFieldOp, isDbFieldOp, reconcileCas, separateCas, separateFieldOps } from "./ops.mjs";
9
- import { a as forceNavNonOptional, c as getKeyProps, o as isNavRelation, r as buildValidationContext, s as createDbValidatorPlugin, t as buildDbValidator } from "./validator-Clu2q_7z.mjs";
9
+ import { a as forceNavNonOptional, c as getKeyProps, o as isNavRelation, r as buildValidationContext, s as createDbValidatorPlugin, t as buildDbValidator } from "./validator-BTiIOTKP.mjs";
10
10
  import { isAnnotatedType } from "@atscript/typescript/utils";
11
11
  import { RELATION_OPS, computeInsights, isPrimitive, isRelationOp, walkFilter } from "@uniqu/core";
12
12
  import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
@@ -235,8 +235,14 @@ var DbSpace = class {
235
235
  _readables = /* @__PURE__ */ new WeakMap();
236
236
  /** All tables created in this space — used for reverse FK lookup during cascade. */
237
237
  _allTables = /* @__PURE__ */ new Set();
238
+ /** Every table / view handle the space created — flagged closed on {@link close}. */
239
+ _handles = /* @__PURE__ */ new Set();
238
240
  /** Lazily created adapter for administrative ops (drop table/view) that don't need a registered readable. */
239
241
  _adminAdapter;
242
+ /** Every adapter this space created (tables, views, admin) — disposed on close. */
243
+ _adapters = /* @__PURE__ */ new Set();
244
+ _onClose;
245
+ _closing;
240
246
  logger;
241
247
  /** Encryption service for `@db.encrypted` fields — validated eagerly at construction. */
242
248
  _encryption;
@@ -251,6 +257,7 @@ var DbSpace = class {
251
257
  else {
252
258
  const options = loggerOrOptions ?? {};
253
259
  this.logger = options.logger ?? NoopLogger;
260
+ this._onClose = options.onClose;
254
261
  if (options.encryption) this._encryption = new DbEncryption(options.encryption);
255
262
  }
256
263
  }
@@ -259,6 +266,7 @@ var DbSpace = class {
259
266
  * appropriate instance. Uses `@db.view` or `@db.view.for` presence to distinguish.
260
267
  */
261
268
  get(type, logger) {
269
+ this._assertOpen();
262
270
  if (isViewType(type)) return this.getView(type, logger);
263
271
  return this.getTable(type, logger);
264
272
  }
@@ -267,6 +275,7 @@ var DbSpace = class {
267
275
  * Creates the table + adapter on first access, caches for subsequent calls.
268
276
  */
269
277
  getTable(type, logger) {
278
+ this._assertOpen();
270
279
  let readable = this._readables.get(type);
271
280
  if (!readable) {
272
281
  assertNotAlias(type);
@@ -279,6 +288,7 @@ var DbSpace = class {
279
288
  readable.setFkLookupResolver((tableName) => this._getFkLookupTarget(tableName));
280
289
  readable.setEncryption(this._encryption);
281
290
  this._readables.set(type, readable);
291
+ this._handles.add(readable);
282
292
  }
283
293
  return readable;
284
294
  }
@@ -287,12 +297,14 @@ var DbSpace = class {
287
297
  * Creates the view + adapter on first access, caches for subsequent calls.
288
298
  */
289
299
  getView(type, logger) {
300
+ this._assertOpen();
290
301
  let readable = this._readables.get(type);
291
302
  if (!readable) {
292
303
  assertNotAlias(type);
293
304
  readable = new AtscriptDbView(type, this._createAdapter(), logger || this.logger, (t) => this.get(t));
294
305
  readable.setEncryption(this._encryption);
295
306
  this._readables.set(type, readable);
307
+ this._handles.add(readable);
296
308
  }
297
309
  return readable;
298
310
  }
@@ -301,6 +313,7 @@ var DbSpace = class {
301
313
  * Creates the table/view + adapter on first access if needed.
302
314
  */
303
315
  getAdapter(type) {
316
+ this._assertOpen();
304
317
  return this.get(type).dbAdapter;
305
318
  }
306
319
  /**
@@ -308,6 +321,7 @@ var DbSpace = class {
308
321
  * See `BaseDbAdapter.dropTableByName` for an adapter that does not support it.
309
322
  */
310
323
  async dropTableByName(tableName) {
324
+ this._assertOpen();
311
325
  await this._getAdminAdapter().dropTableByName(tableName);
312
326
  }
313
327
  /**
@@ -315,6 +329,7 @@ var DbSpace = class {
315
329
  * See `BaseDbAdapter.dropViewByName` for an adapter that does not support it.
316
330
  */
317
331
  async dropViewByName(viewName) {
332
+ this._assertOpen();
318
333
  await this._getAdminAdapter().dropViewByName(viewName);
319
334
  }
320
335
  /**
@@ -323,6 +338,7 @@ var DbSpace = class {
323
338
  * @since 0.1.128
324
339
  */
325
340
  async dropTablesByName(tableNames) {
341
+ this._assertOpen();
326
342
  await this._getAdminAdapter().dropTablesByName(tableNames);
327
343
  }
328
344
  /**
@@ -332,6 +348,7 @@ var DbSpace = class {
332
348
  * @since 0.1.128
333
349
  */
334
350
  async getReferencingForeignKeys(tableName) {
351
+ this._assertOpen();
335
352
  return this._getAdminAdapter().getReferencingForeignKeys?.(tableName);
336
353
  }
337
354
  /**
@@ -350,8 +367,46 @@ var DbSpace = class {
350
367
  _createAdapter() {
351
368
  const adapter = this.adapterFactory();
352
369
  adapter.registerSpace?.(this);
370
+ this._adapters.add(adapter);
353
371
  return adapter;
354
372
  }
373
+ /** `true` once {@link close} was called. @since 0.1.148 */
374
+ get closed() {
375
+ return this._closing !== void 0;
376
+ }
377
+ /** Throws `SPACE_CLOSED` once the space is closed. */
378
+ _assertOpen() {
379
+ if (this._closing) throw spaceClosedError();
380
+ }
381
+ /**
382
+ * Closes the space: marks it closed, disposes every adapter it created, then
383
+ * runs the `onClose` hook (the `createAdapter` helpers close their driver
384
+ * there). Idempotent — every call returns the first call's promise. Every
385
+ * step is attempted; failures are collected into an `AggregateError`.
386
+ *
387
+ * It does not cancel or drain in-flight queries: call it after the server
388
+ * stopped accepting requests. After close, `get*` and operations on existing
389
+ * table/view handles throw `DbError("SPACE_CLOSED")`.
390
+ * @since 0.1.148
391
+ */
392
+ close() {
393
+ return this._closing ??= this._doClose();
394
+ }
395
+ async _doClose() {
396
+ for (const readable of this._handles) readable._spaceClosed = true;
397
+ const errors = [];
398
+ for (const adapter of this._adapters) try {
399
+ await adapter.dispose?.();
400
+ } catch (error) {
401
+ errors.push(error);
402
+ }
403
+ try {
404
+ await this._onClose?.();
405
+ } catch (error) {
406
+ errors.push(error);
407
+ }
408
+ if (errors.length > 0) throw aggregateFailure("DbSpace close failed", errors);
409
+ }
355
410
  /**
356
411
  * Finds all child tables with FKs pointing to the given parent table name.
357
412
  * Accesses `table.foreignKeys` which triggers `_flatten()` if needed.
@@ -375,6 +430,9 @@ var DbSpace = class {
375
430
  for (const table of this._allTables) if (table.tableName === tableName) return { count: (filter) => table.count({ filter }) };
376
431
  }
377
432
  };
433
+ if (typeof Symbol.asyncDispose === "symbol") DbSpace.prototype[Symbol.asyncDispose] = function() {
434
+ return this.close();
435
+ };
378
436
  //#endregion
379
437
  //#region src/table/db-entity.ts
380
438
  /**
@@ -394,4 +452,4 @@ function isDbEntityType(value) {
394
452
  return DB_ENTITY_ANNOTATIONS.some((name) => value.metadata.has(name));
395
453
  }
396
454
  //#endregion
397
- export { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, ADAPTER_FILTER_REASON, ALL_AGGREGATE_FNS, ALL_BUCKET_UNITS, ALL_VIEW_CAPABILITIES, ApplicationIntegrity, AtscriptDbReadable, AtscriptDbTable, AtscriptDbView, BaseDbAdapter, CasExhaustedError, CasMismatchError, DEFAULT_DB_SPACE, DbEncryption, DbError, DbSpace, DocumentFieldMapper, ENCRYPTED_REASON, FieldMappingStrategy, IntegrityStrategy, NativeIntegrity, NoopLogger, RELATION_OPS, REL_FILTER_MAX_DEPTH, REL_FILTER_MAX_NODES, RelationalFieldMapper, ResolvedRelationFilter, TableMetadata, UniquSelect, acceptedOperatorsHint, aliasTargetOf, andFilters, assertGeoPoint, assertNoVersionWrites, bucketSourceVerdict, bucketTimeZoneUnavailable, buildDbValidator, buildValidationContext, canFilterLeaf, checkHavingKeys, classifyQueryPath, collectQueryPaths, computeInsights, containsRelationFilter, createDbValidatorPlugin, createFailureCollector, decomposePatch, deletePath, findAncestorInSet, fkColumns, forEachResolvedRelation, forceNavNonOptional, geoIndexNotFoundMessage, getDbFieldOp, getKeyProps, getPath, guardAggregate, guardFilter, guardPath, guardPaths, guardQuery, hasRelationOp, isAtscriptDbView, isBucketableField, isColumnTypeChanged, isDbEntityType, isDbFieldOp, isEmptyObject, isFieldRef, isGeoIndexableType, isGeoPointType, isJsonValueField, isNavRelation, isPlainObject, isPrimitive, isRelationOp, isResolvedRelationFilter, isViewType, jsonValueAncestor, narrowerFilterOps, normalizeComputedSelect, reconcileCas, relationStaticFilter, resolveCalendarBuckets, resolveDesignType, searchIndexNotFoundMessage, selfOrAncestor, separateCas, separateFieldOps, sortFieldNames, tableNameOf, translateQueryTree, unsupportedOperatorMessage, vectorIndexNotFoundMessage, walkFilter, withOptimisticRetry };
455
+ export { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, ADAPTER_FILTER_REASON, ALL_AGGREGATE_FNS, ALL_BUCKET_UNITS, ALL_VIEW_CAPABILITIES, ApplicationIntegrity, AtscriptDbReadable, AtscriptDbTable, AtscriptDbView, BaseDbAdapter, CasExhaustedError, CasMismatchError, DEFAULT_DB_SPACE, DbEncryption, DbError, DbSpace, DocumentFieldMapper, ENCRYPTED_REASON, FieldMappingStrategy, IntegrityStrategy, NativeIntegrity, NoopLogger, RELATION_OPS, REL_FILTER_MAX_DEPTH, REL_FILTER_MAX_NODES, RelationalFieldMapper, ResolvedRelationFilter, TableMetadata, UniquSelect, acceptedOperatorsHint, aggregateExpressionsNotSupported, aggregateFailure, aliasTargetOf, andFilters, assertGeoPoint, assertNoVersionWrites, bucketSourceVerdict, bucketTimeZoneUnavailable, buildDbValidator, buildValidationContext, canFilterLeaf, checkHavingKeys, classifyQueryPath, collectQueryPaths, computeInsights, containsRelationFilter, createDbValidatorPlugin, createFailureCollector, decomposePatch, deletePath, evaluateExpr, findAncestorInSet, fkColumns, forEachResolvedRelation, forceNavNonOptional, geoIndexNotFoundMessage, getDbFieldOp, getKeyProps, getPath, groupSourceVerdict, guardAggregate, guardFilter, guardPath, guardPaths, guardQuery, hasRelationOp, isAtscriptDbView, isBucketableField, isColumnTypeChanged, isConflict, isDbEntityType, isDbFieldOp, isEmptyObject, isFieldRef, isGeoIndexableType, isGeoPointType, isJsonValueField, isNavRelation, isPlainObject, isPrimitive, isRelationOp, isResolvedRelationFilter, isViewType, jsonValueAncestor, narrowerFilterOps, normalizeComputedSelect, numericOperandProblem, reconcileCas, relationStaticFilter, resolveCalendarBuckets, resolveDesignType, searchIndexNotFoundMessage, selfOrAncestor, separateCas, separateFieldOps, sortFieldNames, tableNameOf, translateQueryTree, uniqueKeyTuple, unsupportedOperatorMessage, vectorIndexNotFoundMessage, walkFilter, withOptimisticRetry };
@@ -1,4 +1,4 @@
1
- const require_db_error = require("./db-error-DTkkeu5b.cjs");
1
+ const require_db_error = require("./db-error-DRQH4sLY.cjs");
2
2
  const require_object = require("./object-Djg28csK.cjs");
3
3
  let _atscript_typescript_utils = require("@atscript/typescript/utils");
4
4
  let _uniqu_core = require("@uniqu/core");
@@ -44,6 +44,40 @@ function walkViewExpr(expr, leaf) {
44
44
  for (const arg of expr.args) walkViewExpr(arg, leaf);
45
45
  }
46
46
  /**
47
+ * Evaluates a computed expression in process (the memory adapter, a test, a
48
+ * third-party adapter) with the semantics every adapter shares: IEEE double,
49
+ * a leaf is `Number()`-ed, NULL / undefined propagates as `null`, `/` by zero
50
+ * is `null`, `coalesce` returns its first non-null value.
51
+ * @since 0.1.148
52
+ */
53
+ function evaluateExpr(expr, leaf) {
54
+ if (typeof expr === "number") return expr;
55
+ if ("field" in expr) {
56
+ const v = leaf(expr.field);
57
+ if (v === null || v === void 0) return null;
58
+ const n = Number(v);
59
+ return Number.isNaN(n) ? null : n;
60
+ }
61
+ if (expr.op === "coalesce") {
62
+ for (const arg of expr.args) {
63
+ const v = evaluateExpr(arg, leaf);
64
+ if (v !== null) return v;
65
+ }
66
+ return null;
67
+ }
68
+ const a = evaluateExpr(expr.args[0], leaf);
69
+ if (a === null) return null;
70
+ if (expr.op === "neg") return -a;
71
+ const b = evaluateExpr(expr.args[1], leaf);
72
+ if (b === null) return null;
73
+ switch (expr.op) {
74
+ case "+": return a + b;
75
+ case "-": return a - b;
76
+ case "*": return a * b;
77
+ default: return b === 0 ? null : a / b;
78
+ }
79
+ }
80
+ /**
47
81
  * Whether a computed-column expression may yield NULL: a `/` (division by
48
82
  * zero is NULL), a leaf for which `nullableLeaf` holds, or an operation over
49
83
  * a nullable operand — `coalesce` only when every argument is nullable.
@@ -594,8 +628,14 @@ function resolvePredicateMap(key, value, meta, depth) {
594
628
  }
595
629
  //#endregion
596
630
  //#region src/shared/keys.ts
597
- /** String form of a key value (an ObjectId stringifies to its hex, a bigint to its digits). */
631
+ /**
632
+ * String form of a key value, equal across driver representations: an
633
+ * ObjectId stringifies to its hex, a bigint to its digits, a Date to its ISO
634
+ * instant, a Buffer / Uint8Array to hex.
635
+ */
598
636
  function keyString(value) {
637
+ if (value instanceof Date) return Number.isNaN(value.getTime()) ? "Invalid Date" : value.toISOString();
638
+ if (value instanceof Uint8Array) return Array.from(value, (b) => b.toString(16).padStart(2, "0")).join("");
599
639
  return String(value);
600
640
  }
601
641
  /** Key equality across driver representations (number vs numeric string, ObjectId vs hex). */
@@ -622,6 +662,20 @@ function rowMatchesKey(row, key) {
622
662
  for (const field in key) if (!sameKey(require_object.getPath(row, field), key[field])) return false;
623
663
  return true;
624
664
  }
665
+ /**
666
+ * Identity of the key tuple `fields` of `row` for uniqueness checks, or
667
+ * `undefined` when any component is null / missing (a NULL never collides).
668
+ * Equal across driver representations (see {@link keyString}).
669
+ */
670
+ function uniqueKeyTuple(row, fields) {
671
+ const parts = [];
672
+ for (const field of fields) {
673
+ const value = require_object.getPath(row, field);
674
+ if (value === void 0 || value === null) return void 0;
675
+ parts.push(keyString(value));
676
+ }
677
+ return JSON.stringify(parts);
678
+ }
625
679
  //#endregion
626
680
  //#region src/table/error-utils.ts
627
681
  /**
@@ -1543,6 +1597,12 @@ Object.defineProperty(exports, "enrichFkViolation", {
1543
1597
  return enrichFkViolation;
1544
1598
  }
1545
1599
  });
1600
+ Object.defineProperty(exports, "evaluateExpr", {
1601
+ enumerable: true,
1602
+ get: function() {
1603
+ return evaluateExpr;
1604
+ }
1605
+ });
1546
1606
  Object.defineProperty(exports, "findFKEntryForRelation", {
1547
1607
  enumerable: true,
1548
1608
  get: function() {
@@ -1675,6 +1735,12 @@ Object.defineProperty(exports, "translateQueryTree", {
1675
1735
  return translateQueryTree;
1676
1736
  }
1677
1737
  });
1738
+ Object.defineProperty(exports, "uniqueKeyTuple", {
1739
+ enumerable: true,
1740
+ get: function() {
1741
+ return uniqueKeyTuple;
1742
+ }
1743
+ });
1678
1744
  Object.defineProperty(exports, "validateBatch", {
1679
1745
  enumerable: true,
1680
1746
  get: function() {
@@ -1,4 +1,4 @@
1
- import { i as DepthLimitExceededError, r as DbError } from "./db-error-D5uilS_A.mjs";
1
+ import { i as DepthLimitExceededError, r as DbError } from "./db-error-Az85UhTX.mjs";
2
2
  import { a as isPlainObject, r as getPath } from "./object-TkiJQ-Dp.mjs";
3
3
  import { ValidatorError } from "@atscript/typescript/utils";
4
4
  import { isRelationOp } from "@uniqu/core";
@@ -44,6 +44,40 @@ function walkViewExpr(expr, leaf) {
44
44
  for (const arg of expr.args) walkViewExpr(arg, leaf);
45
45
  }
46
46
  /**
47
+ * Evaluates a computed expression in process (the memory adapter, a test, a
48
+ * third-party adapter) with the semantics every adapter shares: IEEE double,
49
+ * a leaf is `Number()`-ed, NULL / undefined propagates as `null`, `/` by zero
50
+ * is `null`, `coalesce` returns its first non-null value.
51
+ * @since 0.1.148
52
+ */
53
+ function evaluateExpr(expr, leaf) {
54
+ if (typeof expr === "number") return expr;
55
+ if ("field" in expr) {
56
+ const v = leaf(expr.field);
57
+ if (v === null || v === void 0) return null;
58
+ const n = Number(v);
59
+ return Number.isNaN(n) ? null : n;
60
+ }
61
+ if (expr.op === "coalesce") {
62
+ for (const arg of expr.args) {
63
+ const v = evaluateExpr(arg, leaf);
64
+ if (v !== null) return v;
65
+ }
66
+ return null;
67
+ }
68
+ const a = evaluateExpr(expr.args[0], leaf);
69
+ if (a === null) return null;
70
+ if (expr.op === "neg") return -a;
71
+ const b = evaluateExpr(expr.args[1], leaf);
72
+ if (b === null) return null;
73
+ switch (expr.op) {
74
+ case "+": return a + b;
75
+ case "-": return a - b;
76
+ case "*": return a * b;
77
+ default: return b === 0 ? null : a / b;
78
+ }
79
+ }
80
+ /**
47
81
  * Whether a computed-column expression may yield NULL: a `/` (division by
48
82
  * zero is NULL), a leaf for which `nullableLeaf` holds, or an operation over
49
83
  * a nullable operand — `coalesce` only when every argument is nullable.
@@ -594,8 +628,14 @@ function resolvePredicateMap(key, value, meta, depth) {
594
628
  }
595
629
  //#endregion
596
630
  //#region src/shared/keys.ts
597
- /** String form of a key value (an ObjectId stringifies to its hex, a bigint to its digits). */
631
+ /**
632
+ * String form of a key value, equal across driver representations: an
633
+ * ObjectId stringifies to its hex, a bigint to its digits, a Date to its ISO
634
+ * instant, a Buffer / Uint8Array to hex.
635
+ */
598
636
  function keyString(value) {
637
+ if (value instanceof Date) return Number.isNaN(value.getTime()) ? "Invalid Date" : value.toISOString();
638
+ if (value instanceof Uint8Array) return Array.from(value, (b) => b.toString(16).padStart(2, "0")).join("");
599
639
  return String(value);
600
640
  }
601
641
  /** Key equality across driver representations (number vs numeric string, ObjectId vs hex). */
@@ -622,6 +662,20 @@ function rowMatchesKey(row, key) {
622
662
  for (const field in key) if (!sameKey(getPath(row, field), key[field])) return false;
623
663
  return true;
624
664
  }
665
+ /**
666
+ * Identity of the key tuple `fields` of `row` for uniqueness checks, or
667
+ * `undefined` when any component is null / missing (a NULL never collides).
668
+ * Equal across driver representations (see {@link keyString}).
669
+ */
670
+ function uniqueKeyTuple(row, fields) {
671
+ const parts = [];
672
+ for (const field of fields) {
673
+ const value = getPath(row, field);
674
+ if (value === void 0 || value === null) return void 0;
675
+ parts.push(keyString(value));
676
+ }
677
+ return JSON.stringify(parts);
678
+ }
625
679
  //#endregion
626
680
  //#region src/table/error-utils.ts
627
681
  /**
@@ -1417,4 +1471,4 @@ async function viaReplace(via, targets, parentPK, maxDepth, depth) {
1417
1471
  await viaLinkTargets(via, targets, parentPK, maxDepth, depth);
1418
1472
  }
1419
1473
  //#endregion
1420
- export { noteRelationFilter as A, tableNameOf as B, ResolvedRelationFilter as C, forEachResolvedRelation as D, createRelationFilterHost as E, findFKEntryForRelation as F, viewExprNullable as G, computedOperands as H, findFKForRelation as I, walkViewExpr as K, findRemoteFK as L, relationStaticFilter as M, resolveRelationFilterTree as N, hasRelationOp as O, compositeKey as P, resolveRelationTargetTable as R, REL_FILTER_MAX_NODES as S, containsRelationFilter as T, isFieldRef as U, computeOf as V, translateQueryTree as W, remapDeleteFkViolation as _, batchPatchNestedFrom as a, sameKey as b, batchReplaceNestedFrom as c, checkDepthOverflow as d, planNestedFromVia as f, enrichFkViolation as g, validateBatch as h, batchInsertNestedVia as i, relGuardState as j, isResolvedRelationFilter as k, batchReplaceNestedTo as l, preValidateNestedFrom as m, batchInsertNestedFrom as n, batchPatchNestedTo as o, planPatchNestedTo as p, batchInsertNestedTo as r, batchPatchNestedVia as s, applyPatchNestedTo as t, batchReplaceNestedVia as u, pkTupleKey as v, andFilters as w, REL_FILTER_MAX_DEPTH as x, rowMatchesKey as y, slicePerGroup as z };
1474
+ export { isResolvedRelationFilter as A, slicePerGroup as B, REL_FILTER_MAX_NODES as C, createRelationFilterHost as D, containsRelationFilter as E, compositeKey as F, isFieldRef as G, computeOf as H, findFKEntryForRelation as I, walkViewExpr as J, translateQueryTree as K, findFKForRelation as L, relGuardState as M, relationStaticFilter as N, forEachResolvedRelation as O, resolveRelationFilterTree as P, findRemoteFK as R, REL_FILTER_MAX_DEPTH as S, andFilters as T, computedOperands as U, tableNameOf as V, evaluateExpr as W, remapDeleteFkViolation as _, batchPatchNestedFrom as a, sameKey as b, batchReplaceNestedFrom as c, checkDepthOverflow as d, planNestedFromVia as f, enrichFkViolation as g, validateBatch as h, batchInsertNestedVia as i, noteRelationFilter as j, hasRelationOp as k, batchReplaceNestedTo as l, preValidateNestedFrom as m, batchInsertNestedFrom as n, batchPatchNestedTo as o, planPatchNestedTo as p, viewExprNullable as q, batchInsertNestedTo as r, batchPatchNestedVia as s, applyPatchNestedTo as t, batchReplaceNestedVia as u, pkTupleKey as v, ResolvedRelationFilter as w, uniqueKeyTuple as x, rowMatchesKey as y, resolveRelationTargetTable as z };
@@ -0,0 +1,21 @@
1
+ //#region src/shared/numeric-operand.ts
2
+ /** Primitive tags of timestamps (MySQL may store them as native `TIMESTAMP`). */
3
+ const TIMESTAMP_TAGS = [
4
+ "timestamp",
5
+ "created",
6
+ "updated"
7
+ ];
8
+ /**
9
+ * Why a field cannot be an arithmetic operand, or `undefined` when it can: it
10
+ * must be a `number` — not a decimal (exact; an expression is IEEE double) and
11
+ * not a timestamp-tagged number. The one rule behind `@db.compute` (declared,
12
+ * from the `.as` source) and query-time arithmetic (from the runtime
13
+ * descriptor), so the two cannot diverge. Storage rules (`@db.ignore`,
14
+ * encrypted, JSON) stay with the callers.
15
+ */
16
+ function numericTypeProblem({ base, tags }) {
17
+ if (base !== "number" && base !== "integer") return base === "decimal" ? "is a decimal" : `is a ${base}`;
18
+ if (tags && TIMESTAMP_TAGS.some((t) => tags.has(t))) return "is a timestamp";
19
+ }
20
+ //#endregion
21
+ export { numericTypeProblem as t };
@@ -0,0 +1,26 @@
1
+ //#region src/shared/numeric-operand.ts
2
+ /** Primitive tags of timestamps (MySQL may store them as native `TIMESTAMP`). */
3
+ const TIMESTAMP_TAGS = [
4
+ "timestamp",
5
+ "created",
6
+ "updated"
7
+ ];
8
+ /**
9
+ * Why a field cannot be an arithmetic operand, or `undefined` when it can: it
10
+ * must be a `number` — not a decimal (exact; an expression is IEEE double) and
11
+ * not a timestamp-tagged number. The one rule behind `@db.compute` (declared,
12
+ * from the `.as` source) and query-time arithmetic (from the runtime
13
+ * descriptor), so the two cannot diverge. Storage rules (`@db.ignore`,
14
+ * encrypted, JSON) stay with the callers.
15
+ */
16
+ function numericTypeProblem({ base, tags }) {
17
+ if (base !== "number" && base !== "integer") return base === "decimal" ? "is a decimal" : `is a ${base}`;
18
+ if (tags && TIMESTAMP_TAGS.some((t) => tags.has(t))) return "is a timestamp";
19
+ }
20
+ //#endregion
21
+ Object.defineProperty(exports, "numericTypeProblem", {
22
+ enumerable: true,
23
+ get: function() {
24
+ return numericTypeProblem;
25
+ }
26
+ });
package/dist/ops.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_db_error = require("./db-error-DTkkeu5b.cjs");
2
+ const require_db_error = require("./db-error-DRQH4sLY.cjs");
3
3
  //#region src/ops.ts
4
4
  /** Increment a numeric field by `value` (default 1). */
5
5
  function $inc(value = 1) {
package/dist/ops.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { r as DbError } from "./db-error-D5uilS_A.mjs";
1
+ import { r as DbError } from "./db-error-Az85UhTX.mjs";
2
2
  //#region src/ops.ts
3
3
  /** Increment a numeric field by `value` (default 1). */
4
4
  function $inc(value = 1) {