@atscript/db 0.1.132 → 0.1.133

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 CHANGED
@@ -1,4 +1,4 @@
1
- import { n as TResolvedBucket } from "./buckets-BvoYYQ2Q.cjs";
1
+ import { n as TResolvedBucket } from "./buckets-CTWy7Y1k.cjs";
2
2
  import { AggregateControls, AggregateExpr, AggregateFn, AggregateQuery, AggregateResult, BucketExpr, BucketUnit, CalendarBucketLabel, ComputedExpr, ResolvedBucket, WeekStart, isAggregateExpr, isBucketExpr, resolveAlias } from "@uniqu/core";
3
3
 
4
4
  //#region src/agg.d.ts
package/dist/agg.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { n as TResolvedBucket } from "./buckets-D2XPrwSC.mjs";
1
+ import { n as TResolvedBucket } from "./buckets-BENuu_tK.mjs";
2
2
  import { AggregateControls, AggregateExpr, AggregateFn, AggregateQuery, AggregateResult, BucketExpr, BucketUnit, CalendarBucketLabel, ComputedExpr, ResolvedBucket, WeekStart, isAggregateExpr, isBucketExpr, resolveAlias } from "@uniqu/core";
3
3
 
4
4
  //#region src/agg.d.ts
@@ -460,10 +460,11 @@ declare class AtscriptDbReadable<T extends TAtscriptAnnotatedType = TAtscriptAnn
460
460
  * `resolveCalendarBuckets`: shapes, unit, zone, alias, grouping)
461
461
  * - Plain fields in $select are a subset of $groupBy
462
462
  * - When dimensions/measures are defined (strict mode): $groupBy fields
463
- * must be dimensions (a calendar bucket's source field included),
464
- * aggregate $field values must be measures (or '*')
465
- * - the path guard (a bucket source must be a timestamp field) and the
466
- * adapter's calendar-bucket units (`BUCKET_NOT_SUPPORTED`)
463
+ * must be dimensions, aggregate $field values must be measures (or '*')
464
+ * - the path guard (a bucket source must pass `bucketSourceVerdict` —
465
+ * timestamp type, no JSON ancestor, a dimension in strict mode, an
466
+ * adapter with calendar buckets) and the adapter's calendar-bucket units
467
+ * (`BUCKET_NOT_SUPPORTED`)
467
468
  *
468
469
  * Translates field names, delegates to adapter.aggregate(),
469
470
  * then reverse-maps and applies fromStorage formatters on results.
@@ -2184,10 +2185,12 @@ interface TBucketFieldSource {
2184
2185
  * moost-db's HTTP gate — so both layers answer with the same wording.
2185
2186
  * Everything downstream (`collectQueryPaths`, the field mappers,
2186
2187
  * `UniquSelect`, adapters) assumes normalized input and does not re-check.
2187
- * - **Schema** (timestamp-typed source, JSON ancestor, encryption, physical
2188
- * filterability) is the path guard's (`guardPath` op `bucket`), mirrored by
2189
- * moost-db's capability index; dimensions are the aggregate rules'.
2190
- * - **Adapter capability** (`calendarBucketUnits()`) is `guardAggregate`'s
2188
+ * - **The source field** (encryption, JSON ancestor, timestamp type,
2189
+ * physical filterability, strict-mode dimension, an adapter with calendar
2190
+ * buckets) is `bucketSourceVerdict` — ONE function, called by the path
2191
+ * guard (`guardPath` op `bucket`) and by moost-db's capability index, so
2192
+ * `/meta.fields[P].bucketable` and the core cannot disagree.
2193
+ * - **The unit** (`calendarBucketUnits()` lacks it) is `guardAggregate`'s
2191
2194
  * (`BUCKET_NOT_SUPPORTED`); SQL builders only re-assert the inlined
2192
2195
  * literals (defense in depth).
2193
2196
  *
@@ -2200,11 +2203,14 @@ declare function resolveCalendarBuckets(controls: {
2200
2203
  $groupBy?: unknown;
2201
2204
  } | undefined, fields: TBucketFieldSource, aggregate?: boolean): ResolvedBucket[];
2202
2205
  /**
2203
- * Whether a field can be the source of a calendar bucket: a `number` /
2204
- * `integer` leaf carrying the `timestamp` tag (`number.timestamp`,
2205
- * `.created`, `.updated`) that is not `@db.encrypted`. The type is the
2206
- * declaration — no annotation opts a field in. Physical filterability is the
2207
- * caller's (the core path guard and moost-db's capability index both add it).
2206
+ * Whether a field's TYPE allows it to be the source of a calendar bucket: a
2207
+ * `number` / `integer` leaf carrying the `timestamp` tag
2208
+ * (`number.timestamp`, `.created`, `.updated`) that is not
2209
+ * `@db.encrypted`. The type is the declaration — no annotation opts a field
2210
+ * in.
2211
+ *
2212
+ * @deprecated since 0.1.133 — the type rule alone; use `bucketSourceVerdict`,
2213
+ * the full bucket-source rule the core and moost-db apply.
2208
2214
  */
2209
2215
  declare function isBucketableField(fd: TDbFieldMeta): boolean;
2210
2216
  /**
@@ -460,10 +460,11 @@ declare class AtscriptDbReadable<T extends TAtscriptAnnotatedType = TAtscriptAnn
460
460
  * `resolveCalendarBuckets`: shapes, unit, zone, alias, grouping)
461
461
  * - Plain fields in $select are a subset of $groupBy
462
462
  * - When dimensions/measures are defined (strict mode): $groupBy fields
463
- * must be dimensions (a calendar bucket's source field included),
464
- * aggregate $field values must be measures (or '*')
465
- * - the path guard (a bucket source must be a timestamp field) and the
466
- * adapter's calendar-bucket units (`BUCKET_NOT_SUPPORTED`)
463
+ * must be dimensions, aggregate $field values must be measures (or '*')
464
+ * - the path guard (a bucket source must pass `bucketSourceVerdict` —
465
+ * timestamp type, no JSON ancestor, a dimension in strict mode, an
466
+ * adapter with calendar buckets) and the adapter's calendar-bucket units
467
+ * (`BUCKET_NOT_SUPPORTED`)
467
468
  *
468
469
  * Translates field names, delegates to adapter.aggregate(),
469
470
  * then reverse-maps and applies fromStorage formatters on results.
@@ -2184,10 +2185,12 @@ interface TBucketFieldSource {
2184
2185
  * moost-db's HTTP gate — so both layers answer with the same wording.
2185
2186
  * Everything downstream (`collectQueryPaths`, the field mappers,
2186
2187
  * `UniquSelect`, adapters) assumes normalized input and does not re-check.
2187
- * - **Schema** (timestamp-typed source, JSON ancestor, encryption, physical
2188
- * filterability) is the path guard's (`guardPath` op `bucket`), mirrored by
2189
- * moost-db's capability index; dimensions are the aggregate rules'.
2190
- * - **Adapter capability** (`calendarBucketUnits()`) is `guardAggregate`'s
2188
+ * - **The source field** (encryption, JSON ancestor, timestamp type,
2189
+ * physical filterability, strict-mode dimension, an adapter with calendar
2190
+ * buckets) is `bucketSourceVerdict` — ONE function, called by the path
2191
+ * guard (`guardPath` op `bucket`) and by moost-db's capability index, so
2192
+ * `/meta.fields[P].bucketable` and the core cannot disagree.
2193
+ * - **The unit** (`calendarBucketUnits()` lacks it) is `guardAggregate`'s
2191
2194
  * (`BUCKET_NOT_SUPPORTED`); SQL builders only re-assert the inlined
2192
2195
  * literals (defense in depth).
2193
2196
  *
@@ -2200,11 +2203,14 @@ declare function resolveCalendarBuckets(controls: {
2200
2203
  $groupBy?: unknown;
2201
2204
  } | undefined, fields: TBucketFieldSource, aggregate?: boolean): ResolvedBucket[];
2202
2205
  /**
2203
- * Whether a field can be the source of a calendar bucket: a `number` /
2204
- * `integer` leaf carrying the `timestamp` tag (`number.timestamp`,
2205
- * `.created`, `.updated`) that is not `@db.encrypted`. The type is the
2206
- * declaration — no annotation opts a field in. Physical filterability is the
2207
- * caller's (the core path guard and moost-db's capability index both add it).
2206
+ * Whether a field's TYPE allows it to be the source of a calendar bucket: a
2207
+ * `number` / `integer` leaf carrying the `timestamp` tag
2208
+ * (`number.timestamp`, `.created`, `.updated`) that is not
2209
+ * `@db.encrypted`. The type is the declaration — no annotation opts a field
2210
+ * in.
2211
+ *
2212
+ * @deprecated since 0.1.133 — the type rule alone; use `bucketSourceVerdict`,
2213
+ * the full bucket-source rule the core and moost-db apply.
2208
2214
  */
2209
2215
  declare function isBucketableField(fd: TDbFieldMeta): boolean;
2210
2216
  /**
@@ -1,4 +1,4 @@
1
- import { Dt as TableMetadata, H as TDbInsertManyResult, I as TDbDeleteResult, It as DbEncryption, Lt as TDbEncryptionOptions, Mt as BaseDbAdapter, Nt as AtscriptDbReadable, St as TWriteTableResolver, U as TDbInsertResult, Vt as TGenericLogger, X as TDbUpdateResult, et as TDeleteOptions, g as DbRow, m as DbPatch, ot as TFkLookupResolver, pt as TReferencingForeignKey, vt as TTableResolver, w as TCascadeResolver, x as NullableOptional, xt as TWriteOptions, yt as TTouchManyOptions } from "./buckets-D2XPrwSC.mjs";
1
+ import { Dt as TableMetadata, H as TDbInsertManyResult, I as TDbDeleteResult, It as DbEncryption, Lt as TDbEncryptionOptions, Mt as BaseDbAdapter, Nt as AtscriptDbReadable, St as TWriteTableResolver, U as TDbInsertResult, Vt as TGenericLogger, X as TDbUpdateResult, et as TDeleteOptions, g as DbRow, m as DbPatch, ot as TFkLookupResolver, pt as TReferencingForeignKey, vt as TTableResolver, w as TCascadeResolver, x as NullableOptional, xt as TWriteOptions, yt as TTouchManyOptions } from "./buckets-BENuu_tK.mjs";
2
2
  import { AtscriptQueryComparison, AtscriptQueryFieldRef, AtscriptQueryFieldRef as AtscriptQueryFieldRef$1, AtscriptQueryNode, AtscriptQueryNode as AtscriptQueryNode$1, AtscriptRef, FlatOf, NavPropsOf, OwnPropsOf, PrimaryKeyOf, TAtscriptAnnotatedType, TAtscriptDataType, Validator } from "@atscript/typescript/utils";
3
3
  import { FilterExpr } from "@uniqu/core";
4
4
 
@@ -1,4 +1,4 @@
1
- import { Dt as TableMetadata, H as TDbInsertManyResult, I as TDbDeleteResult, It as DbEncryption, Lt as TDbEncryptionOptions, Mt as BaseDbAdapter, Nt as AtscriptDbReadable, St as TWriteTableResolver, U as TDbInsertResult, Vt as TGenericLogger, X as TDbUpdateResult, et as TDeleteOptions, g as DbRow, m as DbPatch, ot as TFkLookupResolver, pt as TReferencingForeignKey, vt as TTableResolver, w as TCascadeResolver, x as NullableOptional, xt as TWriteOptions, yt as TTouchManyOptions } from "./buckets-BvoYYQ2Q.cjs";
1
+ import { Dt as TableMetadata, H as TDbInsertManyResult, I as TDbDeleteResult, It as DbEncryption, Lt as TDbEncryptionOptions, Mt as BaseDbAdapter, Nt as AtscriptDbReadable, St as TWriteTableResolver, U as TDbInsertResult, Vt as TGenericLogger, X as TDbUpdateResult, et as TDeleteOptions, g as DbRow, m as DbPatch, ot as TFkLookupResolver, pt as TReferencingForeignKey, vt as TTableResolver, w as TCascadeResolver, x as NullableOptional, xt as TWriteOptions, yt as TTouchManyOptions } from "./buckets-CTWy7Y1k.cjs";
2
2
  import { FilterExpr } from "@uniqu/core";
3
3
  import { AtscriptQueryComparison, AtscriptQueryFieldRef, AtscriptQueryFieldRef as AtscriptQueryFieldRef$1, AtscriptQueryNode, AtscriptQueryNode as AtscriptQueryNode$1, AtscriptRef, FlatOf, NavPropsOf, OwnPropsOf, PrimaryKeyOf, TAtscriptAnnotatedType, TAtscriptDataType, Validator } from "@atscript/typescript/utils";
4
4
 
@@ -32,10 +32,12 @@ const NoopLogger = {
32
32
  * moost-db's HTTP gate — so both layers answer with the same wording.
33
33
  * Everything downstream (`collectQueryPaths`, the field mappers,
34
34
  * `UniquSelect`, adapters) assumes normalized input and does not re-check.
35
- * - **Schema** (timestamp-typed source, JSON ancestor, encryption, physical
36
- * filterability) is the path guard's (`guardPath` op `bucket`), mirrored by
37
- * moost-db's capability index; dimensions are the aggregate rules'.
38
- * - **Adapter capability** (`calendarBucketUnits()`) is `guardAggregate`'s
35
+ * - **The source field** (encryption, JSON ancestor, timestamp type,
36
+ * physical filterability, strict-mode dimension, an adapter with calendar
37
+ * buckets) is `bucketSourceVerdict` — ONE function, called by the path
38
+ * guard (`guardPath` op `bucket`) and by moost-db's capability index, so
39
+ * `/meta.fields[P].bucketable` and the core cannot disagree.
40
+ * - **The unit** (`calendarBucketUnits()` lacks it) is `guardAggregate`'s
39
41
  * (`BUCKET_NOT_SUPPORTED`); SQL builders only re-assert the inlined
40
42
  * literals (defense in depth).
41
43
  *
@@ -52,11 +54,14 @@ function resolveCalendarBuckets(controls, fields, aggregate) {
52
54
  return res.buckets;
53
55
  }
54
56
  /**
55
- * Whether a field can be the source of a calendar bucket: a `number` /
56
- * `integer` leaf carrying the `timestamp` tag (`number.timestamp`,
57
- * `.created`, `.updated`) that is not `@db.encrypted`. The type is the
58
- * declaration — no annotation opts a field in. Physical filterability is the
59
- * caller's (the core path guard and moost-db's capability index both add it).
57
+ * Whether a field's TYPE allows it to be the source of a calendar bucket: a
58
+ * `number` / `integer` leaf carrying the `timestamp` tag
59
+ * (`number.timestamp`, `.created`, `.updated`) that is not
60
+ * `@db.encrypted`. The type is the declaration — no annotation opts a field
61
+ * in.
62
+ *
63
+ * @deprecated since 0.1.133 — the type rule alone; use `bucketSourceVerdict`,
64
+ * the full bucket-source rule the core and moost-db apply.
60
65
  */
61
66
  function isBucketableField(fd) {
62
67
  if (fd.encrypted) return false;
@@ -1362,8 +1367,10 @@ var RelationalFieldMapper = class extends FieldMappingStrategy {
1362
1367
  * - malformed `$select` computed entries / `$groupBy` entries, calendar
1363
1368
  * buckets outside grouped queries or with a bad unit / zone / alias →
1364
1369
  * `INVALID_QUERY` (the shared normalizer, `resolveCalendarBuckets`)
1365
- * - a calendar bucket over a non-timestamp field → `INVALID_QUERY`; a unit
1366
- * the adapter's `calendarBucketUnits()` lacks → `BUCKET_NOT_SUPPORTED`
1370
+ * - a calendar bucket over a field that is not a bucket source
1371
+ * (`bucketSourceVerdict`) → `INVALID_QUERY`, or `BUCKET_NOT_SUPPORTED`
1372
+ * when the adapter has no calendar buckets at all; a unit the adapter's
1373
+ * `calendarBucketUnits()` lacks → `BUCKET_NOT_SUPPORTED`
1367
1374
  * - every filter / `$sort` / `$select` / `$groupBy` / `$having` / aggregate
1368
1375
  * path must resolve to physical storage on THIS adapter and pass the
1369
1376
  * capability its position (for a filter entry: its predicate class, see
@@ -1450,8 +1457,8 @@ const OP_VERB = {
1450
1457
  aggregate: "aggregate over",
1451
1458
  bucket: "bucket"
1452
1459
  };
1453
- function pathError(path, message) {
1454
- return new require_db_error.DbError("INVALID_QUERY", [{
1460
+ function pathError(path, message, code = "INVALID_QUERY") {
1461
+ return new require_db_error.DbError(code, [{
1455
1462
  path,
1456
1463
  message
1457
1464
  }]);
@@ -1488,6 +1495,16 @@ function sortFieldNames(sort) {
1488
1495
  if (typeof sort === "object") return Object.keys(sort);
1489
1496
  return [];
1490
1497
  }
1498
+ /**
1499
+ * The reason clause for a leaf the adapter cannot filter (value comparison).
1500
+ * @internal Shared wording for moost-db's capability index — not consumer API.
1501
+ */
1502
+ const ADAPTER_FILTER_REASON = "adapter cannot filter on this storage type";
1503
+ /**
1504
+ * The reason clause for an `@db.encrypted` leaf in a comparing / ordering position.
1505
+ * @internal Shared wording for moost-db's capability index — not consumer API.
1506
+ */
1507
+ const ENCRYPTED_REASON = "field is @db.encrypted (ciphertext cannot be compared or ordered)";
1491
1508
  /** The operator each non-`compare` predicate class stands for, in `filterOps` order. */
1492
1509
  const FILTER_PREDICATE_OPS = {
1493
1510
  exists: "$exists",
@@ -1536,6 +1553,52 @@ function narrowerFilterOps(fd, adapter) {
1536
1553
  function acceptedOperatorsHint(ops) {
1537
1554
  return ops.length > 0 ? ` (accepted operators: ${ops.join(", ")})` : "";
1538
1555
  }
1556
+ /**
1557
+ * Strict mode: a table declaring dimensions or measures groups only by
1558
+ * dimensions (a calendar bucket's source included) and aggregates only
1559
+ * measures.
1560
+ */
1561
+ function isStrictTable(table) {
1562
+ return table.dimensions.length > 0 || table.measures.length > 0;
1563
+ }
1564
+ function rejectSource(code, reason) {
1565
+ return {
1566
+ ok: false,
1567
+ code,
1568
+ reason
1569
+ };
1570
+ }
1571
+ /**
1572
+ * Whether the stored leaf `fd` may be the source of a calendar bucket
1573
+ * (since 0.1.133) — every schema and adapter rule, once, for the core path
1574
+ * guard ({@link guardPath} op `bucket`) and moost-db's capability index
1575
+ * (`/meta.fields[P].bucketable` and the HTTP gate) alike. First failing rule
1576
+ * wins, in this order:
1577
+ *
1578
+ * 1. `encrypted` — `@db.encrypted` (ciphertext has no calendar);
1579
+ * 2. `jsonDescendant` — inside a JSON value (`jsonValueAncestor`):
1580
+ * relational adapters cannot address it and nested-object adapters must
1581
+ * not diverge from them;
1582
+ * 3. `notTimestamp` — not a `number.timestamp` leaf;
1583
+ * 4. `notFilterable` — the adapter cannot filter (so cannot group) the storage;
1584
+ * 5. `notDimension` — a strict table ({@link isStrictTable}) and the field
1585
+ * is not a dimension;
1586
+ * 6. `noBuckets` — the adapter reports no `calendarBucketUnits()`.
1587
+ *
1588
+ * Whether the adapter supports the requested UNIT is a per-query rule, not
1589
+ * a field's (the core's `BUCKET_NOT_SUPPORTED`). Caller-specific policy
1590
+ * layers on top: moost-db rejects `@db.writeOnly` sources before asking.
1591
+ */
1592
+ function bucketSourceVerdict(fd, table, adapter) {
1593
+ if (fd.encrypted) return rejectSource("encrypted", ENCRYPTED_REASON);
1594
+ const jsonAncestor = jsonValueAncestor(fd.path, table.jsonValueParents);
1595
+ if (jsonAncestor !== void 0) return rejectSource("jsonDescendant", `inside JSON-stored column "${jsonAncestor}"`);
1596
+ if (!isBucketableField(fd)) return rejectSource("notTimestamp", "not a timestamp field (declare it number.timestamp)");
1597
+ if (!adapter.canFilterField(fd)) return rejectSource("notFilterable", ADAPTER_FILTER_REASON);
1598
+ if (isStrictTable(table) && !table.dimensions.includes(fd.path)) return rejectSource("notDimension", "not a dimension");
1599
+ if (adapter.calendarBucketUnits().size === 0) return rejectSource("noBuckets", "adapter has no calendar buckets");
1600
+ return { ok: true };
1601
+ }
1539
1602
  function collectFilterKeys(filter, push, skip, refs) {
1540
1603
  if (!filter || typeof filter !== "object" || Array.isArray(filter)) return;
1541
1604
  for (const [key, value] of Object.entries(filter)) {
@@ -1662,8 +1725,8 @@ function pathSourceOf(meta) {
1662
1725
  * - a leaf → physical capability (`canSortField` for `$sort`; for a filter
1663
1726
  * entry {@link canFilterLeaf} of its `predicate` class; `canFilterField`
1664
1727
  * for `$groupBy` / `$having` / aggregate `$field`s; `$select` always passes);
1665
- * a calendar-bucket source must also be a timestamp field
1666
- * (`isBucketableField`);
1728
+ * a calendar-bucket source must pass `bucketSourceVerdict` (the rules
1729
+ * moost-db's capability index applies too);
1667
1730
  * - a nested-object parent → only `$select`, and only when it expands to
1668
1731
  * leaf columns (`selectExpansion`);
1669
1732
  * - everything else is rejected.
@@ -1683,17 +1746,15 @@ function guardPath(meta, adapter, path, op, predicate = "compare") {
1683
1746
  if (op === "select") return;
1684
1747
  const fd = meta.descriptorByPath.get(path);
1685
1748
  if (op === "bucket") {
1686
- const jsonAncestor = jsonValueAncestor(path, meta.jsonValueParents);
1687
- if (jsonAncestor !== void 0) throw pathError(path, `Cannot bucket "${path}" — inside JSON-stored column "${jsonAncestor}"`);
1688
- if (!isBucketableField(fd)) throw pathError(path, notTimestampMessage(path));
1689
- if (!adapter.canFilterField(fd)) throw pathError(path, `Cannot bucket "${path}" — adapter cannot filter on this storage type`);
1749
+ const verdict = bucketSourceVerdict(fd, meta, adapter);
1750
+ if (!verdict.ok) throw pathError(path, `Cannot bucket "${path}" — ${verdict.reason}`, verdict.code === "noBuckets" ? "BUCKET_NOT_SUPPORTED" : "INVALID_QUERY");
1690
1751
  return;
1691
1752
  }
1692
1753
  if (op === "sort") {
1693
1754
  if (!adapter.canSortField(fd)) throw pathError(path, `Cannot sort by "${path}" — adapter cannot sort on this storage type`);
1694
1755
  return;
1695
1756
  }
1696
- if (!canFilterLeaf(fd, predicate, adapter)) throw pathError(path, `Cannot ${verb} "${path}" — adapter cannot filter on this storage type${op === "filter" ? acceptedOperatorsHint(narrowerFilterOps(fd, adapter)) : ""}`);
1757
+ if (!canFilterLeaf(fd, predicate, adapter)) throw pathError(path, `Cannot ${verb} "${path}" — ${ADAPTER_FILTER_REASON}${op === "filter" ? acceptedOperatorsHint(narrowerFilterOps(fd, adapter)) : ""}`);
1697
1758
  return;
1698
1759
  }
1699
1760
  case "objectParent":
@@ -1793,13 +1854,10 @@ function guardAggregate(meta, adapter, query, resolved) {
1793
1854
  const having = refs ? checkHavingKeys(refs) : void 0;
1794
1855
  if (having) throw new require_db_error.DbError("INVALID_QUERY", [having]);
1795
1856
  }
1796
- /** The core wording for a bucket over a field that is not `number.timestamp`. */
1797
- function notTimestampMessage(path) {
1798
- return `Cannot bucket "${path}" — not a timestamp field (declare it number.timestamp)`;
1799
- }
1800
1857
  /**
1801
1858
  * Rejects a calendar bucket whose unit this adapter cannot group by
1802
- * (`calendarBucketUnits()`; empty by default) with `BUCKET_NOT_SUPPORTED`,
1859
+ * (`calendarBucketUnits()`; an adapter with none was already answered per
1860
+ * source by `bucketSourceVerdict`) with `BUCKET_NOT_SUPPORTED`,
1803
1861
  * before anything is translated — third-party adapters get a clean 400,
1804
1862
  * never an engine error or a silent fallback.
1805
1863
  */
@@ -2280,10 +2338,11 @@ var AtscriptDbReadable = class {
2280
2338
  * `resolveCalendarBuckets`: shapes, unit, zone, alias, grouping)
2281
2339
  * - Plain fields in $select are a subset of $groupBy
2282
2340
  * - When dimensions/measures are defined (strict mode): $groupBy fields
2283
- * must be dimensions (a calendar bucket's source field included),
2284
- * aggregate $field values must be measures (or '*')
2285
- * - the path guard (a bucket source must be a timestamp field) and the
2286
- * adapter's calendar-bucket units (`BUCKET_NOT_SUPPORTED`)
2341
+ * must be dimensions, aggregate $field values must be measures (or '*')
2342
+ * - the path guard (a bucket source must pass `bucketSourceVerdict` —
2343
+ * timestamp type, no JSON ancestor, a dimension in strict mode, an
2344
+ * adapter with calendar buckets) and the adapter's calendar-bucket units
2345
+ * (`BUCKET_NOT_SUPPORTED`)
2287
2346
  *
2288
2347
  * Translates field names, delegates to adapter.aggregate(),
2289
2348
  * then reverse-maps and applies fromStorage formatters on results.
@@ -2300,11 +2359,11 @@ var AtscriptDbReadable = class {
2300
2359
  }]);
2301
2360
  }
2302
2361
  const { dimensions, measures } = this._meta;
2303
- if (dimensions.length > 0 || measures.length > 0) {
2362
+ if (isStrictTable(this._meta)) {
2304
2363
  const dimSet = new Set(dimensions);
2305
2364
  const measSet = new Set(measures);
2306
- const bucketSource = new Map(buckets.map((b) => [b.alias, b.field]));
2307
- for (const field of $groupBy.map((key) => bucketSource.get(key) ?? key)) if (!dimSet.has(field)) throw new require_db_error.DbError("INVALID_QUERY", [{
2365
+ const bucketAliases = new Set(buckets.map((b) => b.alias));
2366
+ for (const field of $groupBy) if (!dimSet.has(field) && !bucketAliases.has(field)) throw new require_db_error.DbError("INVALID_QUERY", [{
2308
2367
  path: "$groupBy",
2309
2368
  message: `Field "${field}" is not a dimension`
2310
2369
  }]);
@@ -4652,6 +4711,12 @@ function isAtscriptDbView(readable) {
4652
4711
  return readable.isView;
4653
4712
  }
4654
4713
  //#endregion
4714
+ Object.defineProperty(exports, "ADAPTER_FILTER_REASON", {
4715
+ enumerable: true,
4716
+ get: function() {
4717
+ return ADAPTER_FILTER_REASON;
4718
+ }
4719
+ });
4655
4720
  Object.defineProperty(exports, "ALL_BUCKET_UNITS", {
4656
4721
  enumerable: true,
4657
4722
  get: function() {
@@ -4694,6 +4759,12 @@ Object.defineProperty(exports, "DocumentFieldMapper", {
4694
4759
  return DocumentFieldMapper;
4695
4760
  }
4696
4761
  });
4762
+ Object.defineProperty(exports, "ENCRYPTED_REASON", {
4763
+ enumerable: true,
4764
+ get: function() {
4765
+ return ENCRYPTED_REASON;
4766
+ }
4767
+ });
4697
4768
  Object.defineProperty(exports, "FieldMappingStrategy", {
4698
4769
  enumerable: true,
4699
4770
  get: function() {
@@ -4754,6 +4825,12 @@ Object.defineProperty(exports, "assertNoVersionWrites", {
4754
4825
  return assertNoVersionWrites;
4755
4826
  }
4756
4827
  });
4828
+ Object.defineProperty(exports, "bucketSourceVerdict", {
4829
+ enumerable: true,
4830
+ get: function() {
4831
+ return bucketSourceVerdict;
4832
+ }
4833
+ });
4757
4834
  Object.defineProperty(exports, "canFilterLeaf", {
4758
4835
  enumerable: true,
4759
4836
  get: function() {
@@ -32,10 +32,12 @@ const NoopLogger = {
32
32
  * moost-db's HTTP gate — so both layers answer with the same wording.
33
33
  * Everything downstream (`collectQueryPaths`, the field mappers,
34
34
  * `UniquSelect`, adapters) assumes normalized input and does not re-check.
35
- * - **Schema** (timestamp-typed source, JSON ancestor, encryption, physical
36
- * filterability) is the path guard's (`guardPath` op `bucket`), mirrored by
37
- * moost-db's capability index; dimensions are the aggregate rules'.
38
- * - **Adapter capability** (`calendarBucketUnits()`) is `guardAggregate`'s
35
+ * - **The source field** (encryption, JSON ancestor, timestamp type,
36
+ * physical filterability, strict-mode dimension, an adapter with calendar
37
+ * buckets) is `bucketSourceVerdict` — ONE function, called by the path
38
+ * guard (`guardPath` op `bucket`) and by moost-db's capability index, so
39
+ * `/meta.fields[P].bucketable` and the core cannot disagree.
40
+ * - **The unit** (`calendarBucketUnits()` lacks it) is `guardAggregate`'s
39
41
  * (`BUCKET_NOT_SUPPORTED`); SQL builders only re-assert the inlined
40
42
  * literals (defense in depth).
41
43
  *
@@ -52,11 +54,14 @@ function resolveCalendarBuckets(controls, fields, aggregate) {
52
54
  return res.buckets;
53
55
  }
54
56
  /**
55
- * Whether a field can be the source of a calendar bucket: a `number` /
56
- * `integer` leaf carrying the `timestamp` tag (`number.timestamp`,
57
- * `.created`, `.updated`) that is not `@db.encrypted`. The type is the
58
- * declaration — no annotation opts a field in. Physical filterability is the
59
- * caller's (the core path guard and moost-db's capability index both add it).
57
+ * Whether a field's TYPE allows it to be the source of a calendar bucket: a
58
+ * `number` / `integer` leaf carrying the `timestamp` tag
59
+ * (`number.timestamp`, `.created`, `.updated`) that is not
60
+ * `@db.encrypted`. The type is the declaration — no annotation opts a field
61
+ * in.
62
+ *
63
+ * @deprecated since 0.1.133 — the type rule alone; use `bucketSourceVerdict`,
64
+ * the full bucket-source rule the core and moost-db apply.
60
65
  */
61
66
  function isBucketableField(fd) {
62
67
  if (fd.encrypted) return false;
@@ -1362,8 +1367,10 @@ var RelationalFieldMapper = class extends FieldMappingStrategy {
1362
1367
  * - malformed `$select` computed entries / `$groupBy` entries, calendar
1363
1368
  * buckets outside grouped queries or with a bad unit / zone / alias →
1364
1369
  * `INVALID_QUERY` (the shared normalizer, `resolveCalendarBuckets`)
1365
- * - a calendar bucket over a non-timestamp field → `INVALID_QUERY`; a unit
1366
- * the adapter's `calendarBucketUnits()` lacks → `BUCKET_NOT_SUPPORTED`
1370
+ * - a calendar bucket over a field that is not a bucket source
1371
+ * (`bucketSourceVerdict`) → `INVALID_QUERY`, or `BUCKET_NOT_SUPPORTED`
1372
+ * when the adapter has no calendar buckets at all; a unit the adapter's
1373
+ * `calendarBucketUnits()` lacks → `BUCKET_NOT_SUPPORTED`
1367
1374
  * - every filter / `$sort` / `$select` / `$groupBy` / `$having` / aggregate
1368
1375
  * path must resolve to physical storage on THIS adapter and pass the
1369
1376
  * capability its position (for a filter entry: its predicate class, see
@@ -1450,8 +1457,8 @@ const OP_VERB = {
1450
1457
  aggregate: "aggregate over",
1451
1458
  bucket: "bucket"
1452
1459
  };
1453
- function pathError(path, message) {
1454
- return new DbError("INVALID_QUERY", [{
1460
+ function pathError(path, message, code = "INVALID_QUERY") {
1461
+ return new DbError(code, [{
1455
1462
  path,
1456
1463
  message
1457
1464
  }]);
@@ -1488,6 +1495,16 @@ function sortFieldNames(sort) {
1488
1495
  if (typeof sort === "object") return Object.keys(sort);
1489
1496
  return [];
1490
1497
  }
1498
+ /**
1499
+ * The reason clause for a leaf the adapter cannot filter (value comparison).
1500
+ * @internal Shared wording for moost-db's capability index — not consumer API.
1501
+ */
1502
+ const ADAPTER_FILTER_REASON = "adapter cannot filter on this storage type";
1503
+ /**
1504
+ * The reason clause for an `@db.encrypted` leaf in a comparing / ordering position.
1505
+ * @internal Shared wording for moost-db's capability index — not consumer API.
1506
+ */
1507
+ const ENCRYPTED_REASON = "field is @db.encrypted (ciphertext cannot be compared or ordered)";
1491
1508
  /** The operator each non-`compare` predicate class stands for, in `filterOps` order. */
1492
1509
  const FILTER_PREDICATE_OPS = {
1493
1510
  exists: "$exists",
@@ -1536,6 +1553,52 @@ function narrowerFilterOps(fd, adapter) {
1536
1553
  function acceptedOperatorsHint(ops) {
1537
1554
  return ops.length > 0 ? ` (accepted operators: ${ops.join(", ")})` : "";
1538
1555
  }
1556
+ /**
1557
+ * Strict mode: a table declaring dimensions or measures groups only by
1558
+ * dimensions (a calendar bucket's source included) and aggregates only
1559
+ * measures.
1560
+ */
1561
+ function isStrictTable(table) {
1562
+ return table.dimensions.length > 0 || table.measures.length > 0;
1563
+ }
1564
+ function rejectSource(code, reason) {
1565
+ return {
1566
+ ok: false,
1567
+ code,
1568
+ reason
1569
+ };
1570
+ }
1571
+ /**
1572
+ * Whether the stored leaf `fd` may be the source of a calendar bucket
1573
+ * (since 0.1.133) — every schema and adapter rule, once, for the core path
1574
+ * guard ({@link guardPath} op `bucket`) and moost-db's capability index
1575
+ * (`/meta.fields[P].bucketable` and the HTTP gate) alike. First failing rule
1576
+ * wins, in this order:
1577
+ *
1578
+ * 1. `encrypted` — `@db.encrypted` (ciphertext has no calendar);
1579
+ * 2. `jsonDescendant` — inside a JSON value (`jsonValueAncestor`):
1580
+ * relational adapters cannot address it and nested-object adapters must
1581
+ * not diverge from them;
1582
+ * 3. `notTimestamp` — not a `number.timestamp` leaf;
1583
+ * 4. `notFilterable` — the adapter cannot filter (so cannot group) the storage;
1584
+ * 5. `notDimension` — a strict table ({@link isStrictTable}) and the field
1585
+ * is not a dimension;
1586
+ * 6. `noBuckets` — the adapter reports no `calendarBucketUnits()`.
1587
+ *
1588
+ * Whether the adapter supports the requested UNIT is a per-query rule, not
1589
+ * a field's (the core's `BUCKET_NOT_SUPPORTED`). Caller-specific policy
1590
+ * layers on top: moost-db rejects `@db.writeOnly` sources before asking.
1591
+ */
1592
+ function bucketSourceVerdict(fd, table, adapter) {
1593
+ if (fd.encrypted) return rejectSource("encrypted", ENCRYPTED_REASON);
1594
+ const jsonAncestor = jsonValueAncestor(fd.path, table.jsonValueParents);
1595
+ if (jsonAncestor !== void 0) return rejectSource("jsonDescendant", `inside JSON-stored column "${jsonAncestor}"`);
1596
+ if (!isBucketableField(fd)) return rejectSource("notTimestamp", "not a timestamp field (declare it number.timestamp)");
1597
+ if (!adapter.canFilterField(fd)) return rejectSource("notFilterable", ADAPTER_FILTER_REASON);
1598
+ if (isStrictTable(table) && !table.dimensions.includes(fd.path)) return rejectSource("notDimension", "not a dimension");
1599
+ if (adapter.calendarBucketUnits().size === 0) return rejectSource("noBuckets", "adapter has no calendar buckets");
1600
+ return { ok: true };
1601
+ }
1539
1602
  function collectFilterKeys(filter, push, skip, refs) {
1540
1603
  if (!filter || typeof filter !== "object" || Array.isArray(filter)) return;
1541
1604
  for (const [key, value] of Object.entries(filter)) {
@@ -1662,8 +1725,8 @@ function pathSourceOf(meta) {
1662
1725
  * - a leaf → physical capability (`canSortField` for `$sort`; for a filter
1663
1726
  * entry {@link canFilterLeaf} of its `predicate` class; `canFilterField`
1664
1727
  * for `$groupBy` / `$having` / aggregate `$field`s; `$select` always passes);
1665
- * a calendar-bucket source must also be a timestamp field
1666
- * (`isBucketableField`);
1728
+ * a calendar-bucket source must pass `bucketSourceVerdict` (the rules
1729
+ * moost-db's capability index applies too);
1667
1730
  * - a nested-object parent → only `$select`, and only when it expands to
1668
1731
  * leaf columns (`selectExpansion`);
1669
1732
  * - everything else is rejected.
@@ -1683,17 +1746,15 @@ function guardPath(meta, adapter, path, op, predicate = "compare") {
1683
1746
  if (op === "select") return;
1684
1747
  const fd = meta.descriptorByPath.get(path);
1685
1748
  if (op === "bucket") {
1686
- const jsonAncestor = jsonValueAncestor(path, meta.jsonValueParents);
1687
- if (jsonAncestor !== void 0) throw pathError(path, `Cannot bucket "${path}" — inside JSON-stored column "${jsonAncestor}"`);
1688
- if (!isBucketableField(fd)) throw pathError(path, notTimestampMessage(path));
1689
- if (!adapter.canFilterField(fd)) throw pathError(path, `Cannot bucket "${path}" — adapter cannot filter on this storage type`);
1749
+ const verdict = bucketSourceVerdict(fd, meta, adapter);
1750
+ if (!verdict.ok) throw pathError(path, `Cannot bucket "${path}" — ${verdict.reason}`, verdict.code === "noBuckets" ? "BUCKET_NOT_SUPPORTED" : "INVALID_QUERY");
1690
1751
  return;
1691
1752
  }
1692
1753
  if (op === "sort") {
1693
1754
  if (!adapter.canSortField(fd)) throw pathError(path, `Cannot sort by "${path}" — adapter cannot sort on this storage type`);
1694
1755
  return;
1695
1756
  }
1696
- if (!canFilterLeaf(fd, predicate, adapter)) throw pathError(path, `Cannot ${verb} "${path}" — adapter cannot filter on this storage type${op === "filter" ? acceptedOperatorsHint(narrowerFilterOps(fd, adapter)) : ""}`);
1757
+ if (!canFilterLeaf(fd, predicate, adapter)) throw pathError(path, `Cannot ${verb} "${path}" — ${ADAPTER_FILTER_REASON}${op === "filter" ? acceptedOperatorsHint(narrowerFilterOps(fd, adapter)) : ""}`);
1697
1758
  return;
1698
1759
  }
1699
1760
  case "objectParent":
@@ -1793,13 +1854,10 @@ function guardAggregate(meta, adapter, query, resolved) {
1793
1854
  const having = refs ? checkHavingKeys(refs) : void 0;
1794
1855
  if (having) throw new DbError("INVALID_QUERY", [having]);
1795
1856
  }
1796
- /** The core wording for a bucket over a field that is not `number.timestamp`. */
1797
- function notTimestampMessage(path) {
1798
- return `Cannot bucket "${path}" — not a timestamp field (declare it number.timestamp)`;
1799
- }
1800
1857
  /**
1801
1858
  * Rejects a calendar bucket whose unit this adapter cannot group by
1802
- * (`calendarBucketUnits()`; empty by default) with `BUCKET_NOT_SUPPORTED`,
1859
+ * (`calendarBucketUnits()`; an adapter with none was already answered per
1860
+ * source by `bucketSourceVerdict`) with `BUCKET_NOT_SUPPORTED`,
1803
1861
  * before anything is translated — third-party adapters get a clean 400,
1804
1862
  * never an engine error or a silent fallback.
1805
1863
  */
@@ -2280,10 +2338,11 @@ var AtscriptDbReadable = class {
2280
2338
  * `resolveCalendarBuckets`: shapes, unit, zone, alias, grouping)
2281
2339
  * - Plain fields in $select are a subset of $groupBy
2282
2340
  * - When dimensions/measures are defined (strict mode): $groupBy fields
2283
- * must be dimensions (a calendar bucket's source field included),
2284
- * aggregate $field values must be measures (or '*')
2285
- * - the path guard (a bucket source must be a timestamp field) and the
2286
- * adapter's calendar-bucket units (`BUCKET_NOT_SUPPORTED`)
2341
+ * must be dimensions, aggregate $field values must be measures (or '*')
2342
+ * - the path guard (a bucket source must pass `bucketSourceVerdict` —
2343
+ * timestamp type, no JSON ancestor, a dimension in strict mode, an
2344
+ * adapter with calendar buckets) and the adapter's calendar-bucket units
2345
+ * (`BUCKET_NOT_SUPPORTED`)
2287
2346
  *
2288
2347
  * Translates field names, delegates to adapter.aggregate(),
2289
2348
  * then reverse-maps and applies fromStorage formatters on results.
@@ -2300,11 +2359,11 @@ var AtscriptDbReadable = class {
2300
2359
  }]);
2301
2360
  }
2302
2361
  const { dimensions, measures } = this._meta;
2303
- if (dimensions.length > 0 || measures.length > 0) {
2362
+ if (isStrictTable(this._meta)) {
2304
2363
  const dimSet = new Set(dimensions);
2305
2364
  const measSet = new Set(measures);
2306
- const bucketSource = new Map(buckets.map((b) => [b.alias, b.field]));
2307
- for (const field of $groupBy.map((key) => bucketSource.get(key) ?? key)) if (!dimSet.has(field)) throw new DbError("INVALID_QUERY", [{
2365
+ const bucketAliases = new Set(buckets.map((b) => b.alias));
2366
+ for (const field of $groupBy) if (!dimSet.has(field) && !bucketAliases.has(field)) throw new DbError("INVALID_QUERY", [{
2308
2367
  path: "$groupBy",
2309
2368
  message: `Field "${field}" is not a dimension`
2310
2369
  }]);
@@ -4652,4 +4711,4 @@ function isAtscriptDbView(readable) {
4652
4711
  return readable.isView;
4653
4712
  }
4654
4713
  //#endregion
4655
- export { FieldMappingStrategy as A, NoopLogger as B, guardPaths as C, unsupportedOperatorMessage as D, sortFieldNames as E, isGeoPointType as F, isBucketableField as I, isJsonValueField as L, TableMetadata as M, findAncestorInSet as N, RelationalFieldMapper as O, isGeoIndexableType as P, jsonValueAncestor as R, guardPath as S, narrowerFilterOps as T, checkHavingKeys as _, decomposePatch as a, guardAggregate as b, BaseDbAdapter as c, NativeIntegrity as d, AtscriptDbReadable as f, canFilterLeaf as g, assertGeoPoint as h, assertNoVersionWrites as i, UniquSelect as j, DocumentFieldMapper as k, createFailureCollector as l, acceptedOperatorsHint as m, isAtscriptDbView as n, ApplicationIntegrity as o, resolveDesignType as p, AtscriptDbTable as r, ALL_BUCKET_UNITS as s, AtscriptDbView as t, IntegrityStrategy as u, classifyQueryPath as v, guardQuery as w, guardFilter as x, collectQueryPaths as y, resolveCalendarBuckets as z };
4714
+ export { unsupportedOperatorMessage as A, isJsonValueField as B, guardAggregate as C, guardQuery as D, guardPaths as E, TableMetadata as F, resolveCalendarBuckets as H, findAncestorInSet as I, isGeoIndexableType as L, DocumentFieldMapper as M, FieldMappingStrategy as N, narrowerFilterOps as O, UniquSelect as P, isGeoPointType as R, collectQueryPaths as S, guardPath as T, NoopLogger as U, jsonValueAncestor as V, assertGeoPoint as _, decomposePatch as a, checkHavingKeys as b, BaseDbAdapter as c, NativeIntegrity as d, AtscriptDbReadable as f, acceptedOperatorsHint as g, ENCRYPTED_REASON as h, assertNoVersionWrites as i, RelationalFieldMapper as j, sortFieldNames as k, createFailureCollector as l, ADAPTER_FILTER_REASON as m, isAtscriptDbView as n, ApplicationIntegrity as o, resolveDesignType as p, AtscriptDbTable as r, ALL_BUCKET_UNITS as s, AtscriptDbView as t, IntegrityStrategy as u, bucketSourceVerdict as v, guardFilter as w, classifyQueryPath as x, canFilterLeaf as y, isBucketableField as z };
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_db_error = require("./db-error-DTkkeu5b.cjs");
3
- const require_db_view = require("./db-view-CuFAhzwF.cjs");
3
+ const require_db_view = require("./db-view-B5-bQ5AV.cjs");
4
4
  const require_validator = require("./validator-BtZbcLN2.cjs");
5
5
  const require_consts = require("./consts-BzRfCcH2.cjs");
6
6
  const require_ops = require("./ops.cjs");
@@ -382,6 +382,7 @@ exports.$remove = require_ops.$remove;
382
382
  exports.$replace = require_ops.$replace;
383
383
  exports.$update = require_ops.$update;
384
384
  exports.$upsert = require_ops.$upsert;
385
+ exports.ADAPTER_FILTER_REASON = require_db_view.ADAPTER_FILTER_REASON;
385
386
  exports.ALL_BUCKET_UNITS = require_db_view.ALL_BUCKET_UNITS;
386
387
  exports.ApplicationIntegrity = require_db_view.ApplicationIntegrity;
387
388
  exports.AtscriptDbReadable = require_db_view.AtscriptDbReadable;
@@ -395,6 +396,7 @@ exports.DbEncryption = DbEncryption;
395
396
  exports.DbError = require_db_error.DbError;
396
397
  exports.DbSpace = DbSpace;
397
398
  exports.DocumentFieldMapper = require_db_view.DocumentFieldMapper;
399
+ exports.ENCRYPTED_REASON = require_db_view.ENCRYPTED_REASON;
398
400
  exports.FieldMappingStrategy = require_db_view.FieldMappingStrategy;
399
401
  exports.IntegrityStrategy = require_db_view.IntegrityStrategy;
400
402
  exports.NativeIntegrity = require_db_view.NativeIntegrity;
@@ -405,6 +407,7 @@ exports.UniquSelect = require_db_view.UniquSelect;
405
407
  exports.acceptedOperatorsHint = require_db_view.acceptedOperatorsHint;
406
408
  exports.assertGeoPoint = require_db_view.assertGeoPoint;
407
409
  exports.assertNoVersionWrites = require_db_view.assertNoVersionWrites;
410
+ exports.bucketSourceVerdict = require_db_view.bucketSourceVerdict;
408
411
  exports.bucketTimeZoneUnavailable = require_db_error.bucketTimeZoneUnavailable;
409
412
  exports.buildDbValidator = require_validator.buildDbValidator;
410
413
  exports.buildValidationContext = require_validator.buildValidationContext;
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
- import { $ as TDbWriteGuardContext, A as TDbActionIntent, At as isGeoPointType, B as TDbIndexField, Bt as NoopLogger, C as PrimaryKeyOf, Ct as TypedWithRelation, D as TCrudOp, Dt as TableMetadata, E as TColumnDiff, Et as WithRelation, F as TDbDefaultValue, Ft as resolveDesignType, G as TDbReferentialAction, H as TDbInsertManyResult, Ht as UniquSelect, I as TDbDeleteResult, It as DbEncryption, J as TDbRemoveGuardContext, K as TDbRelation, L as TDbFieldMeta, Lt as TDbEncryptionOptions, M as TDbActionProcessor, Mt as BaseDbAdapter, N as TDbCollation, Nt as AtscriptDbReadable, O as TCrudPermissions, Ot as findAncestorInSet, P as TDbDefaultFn, Pt as DbResponse, Q as TDbWriteGuard, R as TDbForeignKey, Rt as DocumentFieldMapper, S as OwnPropsOf, St as TWriteTableResolver, T as TCascadeTarget, Tt as UniqueryControls, U as TDbInsertResult, V as TDbIndexType, Vt as TGenericLogger, W as TDbObjectKind, X as TDbUpdateResult, Y as TDbStorageType, Z as TDbWriteAction, _ as FieldOpsFor, _t as TTableOptionDiff, a as jsonValueAncestor, at as TFieldMeta, b as NavPropsOf, bt as TValueFormatterPair, c as AggregateExpr, ct as TIdDescriptor, d as AggregateResult, dt as TMetadataOverrides, et as TDeleteOptions, f as AtscriptDbWritable, ft as TPrimaryKeyChange, g as DbRow, gt as TSyncColumnResult, h as DbQuery, ht as TSearchIndexInfo, i as isJsonValueField, it as TExistingTableOption, j as TDbActionLevel, jt as ALL_BUCKET_UNITS, k as TDbActionInfo, kt as isGeoIndexableType, l as AggregateFn, lt as TIdentification, m as DbPatch, mt as TRelationInfo, n as TResolvedBucket, nt as TExistingColumn, o as resolveCalendarBuckets, ot as TFkLookupResolver, p as DbControls, pt as TReferencingForeignKey, q as TDbRemoveGuard, r as isBucketableField, rt as TExistingForeignKey, s as AggregateControls, st as TFkLookupTarget, t as TBucketFieldSource, tt as TEnsureTableOptions, u as AggregateQuery, ut as TMetaResponse, v as FilterExpr, vt as TTableResolver, w as TCascadeResolver, wt as Uniquery, x as NullableOptional, xt as TWriteOptions, y as FlatOf, yt as TTouchManyOptions, z as TDbIndex, zt as FieldMappingStrategy } from "./buckets-BvoYYQ2Q.cjs";
1
+ import { $ as TDbWriteGuardContext, A as TDbActionIntent, At as isGeoPointType, B as TDbIndexField, Bt as NoopLogger, C as PrimaryKeyOf, Ct as TypedWithRelation, D as TCrudOp, Dt as TableMetadata, E as TColumnDiff, Et as WithRelation, F as TDbDefaultValue, Ft as resolveDesignType, G as TDbReferentialAction, H as TDbInsertManyResult, Ht as UniquSelect, I as TDbDeleteResult, It as DbEncryption, J as TDbRemoveGuardContext, K as TDbRelation, L as TDbFieldMeta, Lt as TDbEncryptionOptions, M as TDbActionProcessor, Mt as BaseDbAdapter, N as TDbCollation, Nt as AtscriptDbReadable, O as TCrudPermissions, Ot as findAncestorInSet, P as TDbDefaultFn, Pt as DbResponse, Q as TDbWriteGuard, R as TDbForeignKey, Rt as DocumentFieldMapper, S as OwnPropsOf, St as TWriteTableResolver, T as TCascadeTarget, Tt as UniqueryControls, U as TDbInsertResult, V as TDbIndexType, Vt as TGenericLogger, W as TDbObjectKind, X as TDbUpdateResult, Y as TDbStorageType, Z as TDbWriteAction, _ as FieldOpsFor, _t as TTableOptionDiff, a as jsonValueAncestor, at as TFieldMeta, b as NavPropsOf, bt as TValueFormatterPair, c as AggregateExpr, ct as TIdDescriptor, d as AggregateResult, dt as TMetadataOverrides, et as TDeleteOptions, f as AtscriptDbWritable, ft as TPrimaryKeyChange, g as DbRow, gt as TSyncColumnResult, h as DbQuery, ht as TSearchIndexInfo, i as isJsonValueField, it as TExistingTableOption, j as TDbActionLevel, jt as ALL_BUCKET_UNITS, k as TDbActionInfo, kt as isGeoIndexableType, l as AggregateFn, lt as TIdentification, m as DbPatch, mt as TRelationInfo, n as TResolvedBucket, nt as TExistingColumn, o as resolveCalendarBuckets, ot as TFkLookupResolver, p as DbControls, pt as TReferencingForeignKey, q as TDbRemoveGuard, r as isBucketableField, rt as TExistingForeignKey, s as AggregateControls, st as TFkLookupTarget, t as TBucketFieldSource, tt as TEnsureTableOptions, u as AggregateQuery, ut as TMetaResponse, v as FilterExpr, vt as TTableResolver, w as TCascadeResolver, wt as Uniquery, x as NullableOptional, xt as TWriteOptions, y as FlatOf, yt as TTouchManyOptions, z as TDbIndex, zt as FieldMappingStrategy } from "./buckets-CTWy7Y1k.cjs";
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.cjs";
3
3
  import { BucketExpr, BucketUnit, CalendarBucketLabel, ComputedExpr, ResolvedBucket, WeekStart } from "./agg.cjs";
4
- import { a as TViewColumnMapping, c as AtscriptQueryFieldRef, d as TViewJoin, f as TViewPlan, g as NativeIntegrity, h as IntegrityStrategy, i as AtscriptDbView, l as AtscriptQueryNode, m as AtscriptDbTable, n as TAdapterFactory, o as isAtscriptDbView, p as translateQueryTree, r as TDbSpaceOptions, s as AtscriptQueryComparison, t as DbSpace, u as AtscriptRef } from "./db-space-Cslq5Dux.cjs";
4
+ import { a as TViewColumnMapping, c as AtscriptQueryFieldRef, d as TViewJoin, f as TViewPlan, g as NativeIntegrity, h as IntegrityStrategy, i as AtscriptDbView, l as AtscriptQueryNode, m as AtscriptDbTable, n as TAdapterFactory, o as isAtscriptDbView, p as translateQueryTree, r as TDbSpaceOptions, s as AtscriptQueryComparison, t as DbSpace, u as AtscriptRef } from "./db-space-DROLifb-.cjs";
5
5
  import { _ as DbErrorCode, a as buildValidationContext, c as isNavRelation, d as TArrayPatch, f as TDbPatch, g as DbError, h as CasMismatchError, l as isEmptyObject, m as CasExhaustedError, n as ValidatorMode, p as getKeyProps, r as buildDbValidator, s as forceNavNonOptional, t as ValidationContext, u as isPlainObject, v as bucketTimeZoneUnavailable } from "./validator-CewfnGZj.cjs";
6
6
  import { n as createDbValidatorPlugin, t as DbValidationContext } from "./db-validator-plugin-BWy60OvG.cjs";
7
7
  import { AggregateQuery as AggregateQuery$1, FilterExpr as FilterExpr$1, FilterVisitor, ResolvedBucket as ResolvedBucket$1, Uniquery as Uniquery$1, computeInsights, isPrimitive, walkFilter } from "@uniqu/core";
@@ -106,8 +106,10 @@ declare class ApplicationIntegrity extends IntegrityStrategy {
106
106
  * - malformed `$select` computed entries / `$groupBy` entries, calendar
107
107
  * buckets outside grouped queries or with a bad unit / zone / alias →
108
108
  * `INVALID_QUERY` (the shared normalizer, `resolveCalendarBuckets`)
109
- * - a calendar bucket over a non-timestamp field → `INVALID_QUERY`; a unit
110
- * the adapter's `calendarBucketUnits()` lacks → `BUCKET_NOT_SUPPORTED`
109
+ * - a calendar bucket over a field that is not a bucket source
110
+ * (`bucketSourceVerdict`) → `INVALID_QUERY`, or `BUCKET_NOT_SUPPORTED`
111
+ * when the adapter has no calendar buckets at all; a unit the adapter's
112
+ * `calendarBucketUnits()` lacks → `BUCKET_NOT_SUPPORTED`
111
113
  * - every filter / `$sort` / `$select` / `$groupBy` / `$having` / aggregate
112
114
  * path must resolve to physical storage on THIS adapter and pass the
113
115
  * capability its position (for a filter entry: its predicate class, see
@@ -159,6 +161,16 @@ interface TFilterRef {
159
161
  path: string;
160
162
  predicate: TFilterPredicate;
161
163
  }
164
+ /**
165
+ * The reason clause for a leaf the adapter cannot filter (value comparison).
166
+ * @internal Shared wording for moost-db's capability index — not consumer API.
167
+ */
168
+ declare const ADAPTER_FILTER_REASON = "adapter cannot filter on this storage type";
169
+ /**
170
+ * The reason clause for an `@db.encrypted` leaf in a comparing / ordering position.
171
+ * @internal Shared wording for moost-db's capability index — not consumer API.
172
+ */
173
+ declare const ENCRYPTED_REASON = "field is @db.encrypted (ciphertext cannot be compared or ordered)";
162
174
  /** The adapter-shaped capability {@link canFilterLeaf} consults (a `BaseDbAdapter` or a readable). */
163
175
  type TFilterCapabilitySource = Pick<BaseDbAdapter, "canFilterField" | "isGeoSearchable">;
164
176
  /** The operator each non-`compare` predicate class stands for, in `filterOps` order. */
@@ -184,6 +196,52 @@ declare function canFilterLeaf(fd: TDbFieldMeta, predicate: TFilterPredicate, ad
184
196
  declare function narrowerFilterOps(fd: TDbFieldMeta, adapter: TFilterCapabilitySource): string[];
185
197
  /** The rejection suffix naming {@link narrowerFilterOps} — `""` when there are none. */
186
198
  declare function acceptedOperatorsHint(ops: readonly string[]): string;
199
+ /**
200
+ * The table side of a {@link bucketSourceVerdict}: `TableMetadata` itself,
201
+ * or moost-db's capability index assembling the same names from a readable.
202
+ */
203
+ interface TBucketSourceTable {
204
+ /** Paths of the `isJsonValueField` descriptors — see `jsonValueAncestor`. */
205
+ jsonValueParents: ReadonlySet<string>;
206
+ /** Declared dimensions / measures — see {@link isStrictTable}. */
207
+ dimensions: readonly string[];
208
+ measures: readonly string[];
209
+ }
210
+ /**
211
+ * {@link bucketSourceVerdict}'s answer. `reason` is the shared clause (no
212
+ * trailing period) both layers put after the dash: the core's
213
+ * `Cannot bucket "P" — <reason>`, moost-db's
214
+ * `Bucketing field "P" is not permitted — <reason>.`
215
+ */
216
+ type TBucketSourceVerdict = {
217
+ ok: true;
218
+ } | {
219
+ ok: false;
220
+ code: "encrypted" | "jsonDescendant" | "notTimestamp" | "notFilterable" | "notDimension" | "noBuckets";
221
+ reason: string;
222
+ };
223
+ /**
224
+ * Whether the stored leaf `fd` may be the source of a calendar bucket
225
+ * (since 0.1.133) — every schema and adapter rule, once, for the core path
226
+ * guard ({@link guardPath} op `bucket`) and moost-db's capability index
227
+ * (`/meta.fields[P].bucketable` and the HTTP gate) alike. First failing rule
228
+ * wins, in this order:
229
+ *
230
+ * 1. `encrypted` — `@db.encrypted` (ciphertext has no calendar);
231
+ * 2. `jsonDescendant` — inside a JSON value (`jsonValueAncestor`):
232
+ * relational adapters cannot address it and nested-object adapters must
233
+ * not diverge from them;
234
+ * 3. `notTimestamp` — not a `number.timestamp` leaf;
235
+ * 4. `notFilterable` — the adapter cannot filter (so cannot group) the storage;
236
+ * 5. `notDimension` — a strict table ({@link isStrictTable}) and the field
237
+ * is not a dimension;
238
+ * 6. `noBuckets` — the adapter reports no `calendarBucketUnits()`.
239
+ *
240
+ * Whether the adapter supports the requested UNIT is a per-query rule, not
241
+ * a field's (the core's `BUCKET_NOT_SUPPORTED`). Caller-specific policy
242
+ * layers on top: moost-db rejects `@db.writeOnly` sources before asking.
243
+ */
244
+ declare function bucketSourceVerdict(fd: TDbFieldMeta, table: TBucketSourceTable, adapter: Pick<BaseDbAdapter, "canFilterField" | "calendarBucketUnits">): TBucketSourceVerdict;
187
245
  /** Every logical path a parsed query references, grouped by position (since 0.1.128). */
188
246
  interface TQueryPathRefs {
189
247
  /**
@@ -268,8 +326,8 @@ declare function classifyQueryPath(source: TQueryPathSource, path: string): {
268
326
  * - a leaf → physical capability (`canSortField` for `$sort`; for a filter
269
327
  * entry {@link canFilterLeaf} of its `predicate` class; `canFilterField`
270
328
  * for `$groupBy` / `$having` / aggregate `$field`s; `$select` always passes);
271
- * a calendar-bucket source must also be a timestamp field
272
- * (`isBucketableField`);
329
+ * a calendar-bucket source must pass `bucketSourceVerdict` (the rules
330
+ * moost-db's capability index applies too);
273
331
  * - a nested-object parent → only `$select`, and only when it expands to
274
332
  * leaf columns (`selectExpansion`);
275
333
  * - everything else is rejected.
@@ -429,4 +487,4 @@ declare function createFailureCollector(what: string): {
429
487
  throwIfAny: () => void;
430
488
  };
431
489
  //#endregion
432
- export { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, ALL_BUCKET_UNITS, type AggregateControls, type AggregateExpr, type AggregateFn, type AggregateQuery, type AggregateResult, ApplicationIntegrity, AtscriptDbReadable, AtscriptDbTable, AtscriptDbView, type AtscriptDbWritable, 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, FieldMappingStrategy, type FieldOpsFor, type FilterExpr, type FilterVisitor, type FlatOf, IntegrityStrategy, NativeIntegrity, type NavPropsOf, NoopLogger, type NullableOptional, type OwnPropsOf, type PrimaryKeyOf, RelationalFieldMapper, type ResolvedBucket, type TAdapterFactory, type TArrayPatch, type TBucketFieldSource, type TCascadeResolver, type TCascadeTarget, type TColumnDiff, type TCrudOp, type TCrudPermissions, type TDbActionInfo, type TDbActionIntent, type TDbActionLevel, type TDbActionProcessor, 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 TDbWriteGuard, type TDbWriteGuardContext, type TDeleteOptions, 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 TIdentification, type TMetaResponse, type TMetadataOverrides, type TPrimaryKeyChange, type TQueryPathKind, type TQueryPathOp, type TQueryPathRefs, type TQueryPathSource, type TReferencingForeignKey, type TRelationInfo, type TResolvedBucket, type TSearchIndexInfo, type TSyncColumnResult, type TTableOptionDiff, type TTableResolver, type TTouchManyOptions, type TValueFormatterPair, type TViewColumnMapping, type TViewJoin, 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, assertGeoPoint, assertNoVersionWrites, bucketTimeZoneUnavailable, buildDbValidator, buildValidationContext, canFilterLeaf, checkHavingKeys, classifyQueryPath, collectQueryPaths, computeInsights, createDbValidatorPlugin, createFailureCollector, decomposePatch, findAncestorInSet, forceNavNonOptional, getDbFieldOp, getKeyProps, guardAggregate, guardFilter, guardPath, guardPaths, guardQuery, isAtscriptDbView, isBucketableField, isDbFieldOp, isEmptyObject, isGeoIndexableType, isGeoPointType, isJsonValueField, isNavRelation, isPlainObject, isPrimitive, jsonValueAncestor, narrowerFilterOps, reconcileCas, resolveCalendarBuckets, resolveDesignType, separateCas, separateFieldOps, sortFieldNames, translateQueryTree, unsupportedOperatorMessage, walkFilter, withOptimisticRetry };
490
+ export { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, ADAPTER_FILTER_REASON, ALL_BUCKET_UNITS, type AggregateControls, type AggregateExpr, type AggregateFn, type AggregateQuery, type AggregateResult, ApplicationIntegrity, AtscriptDbReadable, AtscriptDbTable, AtscriptDbView, type AtscriptDbWritable, 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, RelationalFieldMapper, type ResolvedBucket, 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 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 TDbWriteGuard, type TDbWriteGuardContext, type TDeleteOptions, 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 TIdentification, type TMetaResponse, type TMetadataOverrides, type TPrimaryKeyChange, type TQueryPathKind, type TQueryPathOp, type TQueryPathRefs, type TQueryPathSource, type TReferencingForeignKey, type TRelationInfo, type TResolvedBucket, type TSearchIndexInfo, type TSyncColumnResult, type TTableOptionDiff, type TTableResolver, type TTouchManyOptions, type TValueFormatterPair, type TViewColumnMapping, type TViewJoin, 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, assertGeoPoint, assertNoVersionWrites, bucketSourceVerdict, bucketTimeZoneUnavailable, buildDbValidator, buildValidationContext, canFilterLeaf, checkHavingKeys, classifyQueryPath, collectQueryPaths, computeInsights, createDbValidatorPlugin, createFailureCollector, decomposePatch, findAncestorInSet, forceNavNonOptional, getDbFieldOp, getKeyProps, guardAggregate, guardFilter, guardPath, guardPaths, guardQuery, isAtscriptDbView, isBucketableField, isDbFieldOp, isEmptyObject, isGeoIndexableType, isGeoPointType, isJsonValueField, isNavRelation, isPlainObject, isPrimitive, jsonValueAncestor, narrowerFilterOps, reconcileCas, resolveCalendarBuckets, resolveDesignType, separateCas, separateFieldOps, sortFieldNames, translateQueryTree, unsupportedOperatorMessage, walkFilter, withOptimisticRetry };
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
- import { $ as TDbWriteGuardContext, A as TDbActionIntent, At as isGeoPointType, B as TDbIndexField, Bt as NoopLogger, C as PrimaryKeyOf, Ct as TypedWithRelation, D as TCrudOp, Dt as TableMetadata, E as TColumnDiff, Et as WithRelation, F as TDbDefaultValue, Ft as resolveDesignType, G as TDbReferentialAction, H as TDbInsertManyResult, Ht as UniquSelect, I as TDbDeleteResult, It as DbEncryption, J as TDbRemoveGuardContext, K as TDbRelation, L as TDbFieldMeta, Lt as TDbEncryptionOptions, M as TDbActionProcessor, Mt as BaseDbAdapter, N as TDbCollation, Nt as AtscriptDbReadable, O as TCrudPermissions, Ot as findAncestorInSet, P as TDbDefaultFn, Pt as DbResponse, Q as TDbWriteGuard, R as TDbForeignKey, Rt as DocumentFieldMapper, S as OwnPropsOf, St as TWriteTableResolver, T as TCascadeTarget, Tt as UniqueryControls, U as TDbInsertResult, V as TDbIndexType, Vt as TGenericLogger, W as TDbObjectKind, X as TDbUpdateResult, Y as TDbStorageType, Z as TDbWriteAction, _ as FieldOpsFor, _t as TTableOptionDiff, a as jsonValueAncestor, at as TFieldMeta, b as NavPropsOf, bt as TValueFormatterPair, c as AggregateExpr, ct as TIdDescriptor, d as AggregateResult, dt as TMetadataOverrides, et as TDeleteOptions, f as AtscriptDbWritable, ft as TPrimaryKeyChange, g as DbRow, gt as TSyncColumnResult, h as DbQuery, ht as TSearchIndexInfo, i as isJsonValueField, it as TExistingTableOption, j as TDbActionLevel, jt as ALL_BUCKET_UNITS, k as TDbActionInfo, kt as isGeoIndexableType, l as AggregateFn, lt as TIdentification, m as DbPatch, mt as TRelationInfo, n as TResolvedBucket, nt as TExistingColumn, o as resolveCalendarBuckets, ot as TFkLookupResolver, p as DbControls, pt as TReferencingForeignKey, q as TDbRemoveGuard, r as isBucketableField, rt as TExistingForeignKey, s as AggregateControls, st as TFkLookupTarget, t as TBucketFieldSource, tt as TEnsureTableOptions, u as AggregateQuery, ut as TMetaResponse, v as FilterExpr, vt as TTableResolver, w as TCascadeResolver, wt as Uniquery, x as NullableOptional, xt as TWriteOptions, y as FlatOf, yt as TTouchManyOptions, z as TDbIndex, zt as FieldMappingStrategy } from "./buckets-D2XPrwSC.mjs";
1
+ import { $ as TDbWriteGuardContext, A as TDbActionIntent, At as isGeoPointType, B as TDbIndexField, Bt as NoopLogger, C as PrimaryKeyOf, Ct as TypedWithRelation, D as TCrudOp, Dt as TableMetadata, E as TColumnDiff, Et as WithRelation, F as TDbDefaultValue, Ft as resolveDesignType, G as TDbReferentialAction, H as TDbInsertManyResult, Ht as UniquSelect, I as TDbDeleteResult, It as DbEncryption, J as TDbRemoveGuardContext, K as TDbRelation, L as TDbFieldMeta, Lt as TDbEncryptionOptions, M as TDbActionProcessor, Mt as BaseDbAdapter, N as TDbCollation, Nt as AtscriptDbReadable, O as TCrudPermissions, Ot as findAncestorInSet, P as TDbDefaultFn, Pt as DbResponse, Q as TDbWriteGuard, R as TDbForeignKey, Rt as DocumentFieldMapper, S as OwnPropsOf, St as TWriteTableResolver, T as TCascadeTarget, Tt as UniqueryControls, U as TDbInsertResult, V as TDbIndexType, Vt as TGenericLogger, W as TDbObjectKind, X as TDbUpdateResult, Y as TDbStorageType, Z as TDbWriteAction, _ as FieldOpsFor, _t as TTableOptionDiff, a as jsonValueAncestor, at as TFieldMeta, b as NavPropsOf, bt as TValueFormatterPair, c as AggregateExpr, ct as TIdDescriptor, d as AggregateResult, dt as TMetadataOverrides, et as TDeleteOptions, f as AtscriptDbWritable, ft as TPrimaryKeyChange, g as DbRow, gt as TSyncColumnResult, h as DbQuery, ht as TSearchIndexInfo, i as isJsonValueField, it as TExistingTableOption, j as TDbActionLevel, jt as ALL_BUCKET_UNITS, k as TDbActionInfo, kt as isGeoIndexableType, l as AggregateFn, lt as TIdentification, m as DbPatch, mt as TRelationInfo, n as TResolvedBucket, nt as TExistingColumn, o as resolveCalendarBuckets, ot as TFkLookupResolver, p as DbControls, pt as TReferencingForeignKey, q as TDbRemoveGuard, r as isBucketableField, rt as TExistingForeignKey, s as AggregateControls, st as TFkLookupTarget, t as TBucketFieldSource, tt as TEnsureTableOptions, u as AggregateQuery, ut as TMetaResponse, v as FilterExpr, vt as TTableResolver, w as TCascadeResolver, wt as Uniquery, x as NullableOptional, xt as TWriteOptions, y as FlatOf, yt as TTouchManyOptions, z as TDbIndex, zt as FieldMappingStrategy } from "./buckets-BENuu_tK.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 { BucketExpr, BucketUnit, CalendarBucketLabel, ComputedExpr, ResolvedBucket, WeekStart } from "./agg.mjs";
4
- import { a as TViewColumnMapping, c as AtscriptQueryFieldRef, d as TViewJoin, f as TViewPlan, g as NativeIntegrity, h as IntegrityStrategy, i as AtscriptDbView, l as AtscriptQueryNode, m as AtscriptDbTable, n as TAdapterFactory, o as isAtscriptDbView, p as translateQueryTree, r as TDbSpaceOptions, s as AtscriptQueryComparison, t as DbSpace, u as AtscriptRef } from "./db-space-BQQEgB3d.mjs";
4
+ import { a as TViewColumnMapping, c as AtscriptQueryFieldRef, d as TViewJoin, f as TViewPlan, g as NativeIntegrity, h as IntegrityStrategy, i as AtscriptDbView, l as AtscriptQueryNode, m as AtscriptDbTable, n as TAdapterFactory, o as isAtscriptDbView, p as translateQueryTree, r as TDbSpaceOptions, s as AtscriptQueryComparison, t as DbSpace, u as AtscriptRef } from "./db-space-Bv3Ar_Xd.mjs";
5
5
  import { _ as DbErrorCode, a as buildValidationContext, c as isNavRelation, d as TArrayPatch, f as TDbPatch, g as DbError, h as CasMismatchError, l as isEmptyObject, m as CasExhaustedError, n as ValidatorMode, p as getKeyProps, r as buildDbValidator, s as forceNavNonOptional, t as ValidationContext, u as isPlainObject, v as bucketTimeZoneUnavailable } from "./validator-CewfnGZj.mjs";
6
6
  import { n as createDbValidatorPlugin, t as DbValidationContext } from "./db-validator-plugin-BWy60OvG.mjs";
7
7
  import { AggregateQuery as AggregateQuery$1, FilterExpr as FilterExpr$1, FilterVisitor, ResolvedBucket as ResolvedBucket$1, Uniquery as Uniquery$1, computeInsights, isPrimitive, walkFilter } from "@uniqu/core";
@@ -106,8 +106,10 @@ declare class ApplicationIntegrity extends IntegrityStrategy {
106
106
  * - malformed `$select` computed entries / `$groupBy` entries, calendar
107
107
  * buckets outside grouped queries or with a bad unit / zone / alias →
108
108
  * `INVALID_QUERY` (the shared normalizer, `resolveCalendarBuckets`)
109
- * - a calendar bucket over a non-timestamp field → `INVALID_QUERY`; a unit
110
- * the adapter's `calendarBucketUnits()` lacks → `BUCKET_NOT_SUPPORTED`
109
+ * - a calendar bucket over a field that is not a bucket source
110
+ * (`bucketSourceVerdict`) → `INVALID_QUERY`, or `BUCKET_NOT_SUPPORTED`
111
+ * when the adapter has no calendar buckets at all; a unit the adapter's
112
+ * `calendarBucketUnits()` lacks → `BUCKET_NOT_SUPPORTED`
111
113
  * - every filter / `$sort` / `$select` / `$groupBy` / `$having` / aggregate
112
114
  * path must resolve to physical storage on THIS adapter and pass the
113
115
  * capability its position (for a filter entry: its predicate class, see
@@ -159,6 +161,16 @@ interface TFilterRef {
159
161
  path: string;
160
162
  predicate: TFilterPredicate;
161
163
  }
164
+ /**
165
+ * The reason clause for a leaf the adapter cannot filter (value comparison).
166
+ * @internal Shared wording for moost-db's capability index — not consumer API.
167
+ */
168
+ declare const ADAPTER_FILTER_REASON = "adapter cannot filter on this storage type";
169
+ /**
170
+ * The reason clause for an `@db.encrypted` leaf in a comparing / ordering position.
171
+ * @internal Shared wording for moost-db's capability index — not consumer API.
172
+ */
173
+ declare const ENCRYPTED_REASON = "field is @db.encrypted (ciphertext cannot be compared or ordered)";
162
174
  /** The adapter-shaped capability {@link canFilterLeaf} consults (a `BaseDbAdapter` or a readable). */
163
175
  type TFilterCapabilitySource = Pick<BaseDbAdapter, "canFilterField" | "isGeoSearchable">;
164
176
  /** The operator each non-`compare` predicate class stands for, in `filterOps` order. */
@@ -184,6 +196,52 @@ declare function canFilterLeaf(fd: TDbFieldMeta, predicate: TFilterPredicate, ad
184
196
  declare function narrowerFilterOps(fd: TDbFieldMeta, adapter: TFilterCapabilitySource): string[];
185
197
  /** The rejection suffix naming {@link narrowerFilterOps} — `""` when there are none. */
186
198
  declare function acceptedOperatorsHint(ops: readonly string[]): string;
199
+ /**
200
+ * The table side of a {@link bucketSourceVerdict}: `TableMetadata` itself,
201
+ * or moost-db's capability index assembling the same names from a readable.
202
+ */
203
+ interface TBucketSourceTable {
204
+ /** Paths of the `isJsonValueField` descriptors — see `jsonValueAncestor`. */
205
+ jsonValueParents: ReadonlySet<string>;
206
+ /** Declared dimensions / measures — see {@link isStrictTable}. */
207
+ dimensions: readonly string[];
208
+ measures: readonly string[];
209
+ }
210
+ /**
211
+ * {@link bucketSourceVerdict}'s answer. `reason` is the shared clause (no
212
+ * trailing period) both layers put after the dash: the core's
213
+ * `Cannot bucket "P" — <reason>`, moost-db's
214
+ * `Bucketing field "P" is not permitted — <reason>.`
215
+ */
216
+ type TBucketSourceVerdict = {
217
+ ok: true;
218
+ } | {
219
+ ok: false;
220
+ code: "encrypted" | "jsonDescendant" | "notTimestamp" | "notFilterable" | "notDimension" | "noBuckets";
221
+ reason: string;
222
+ };
223
+ /**
224
+ * Whether the stored leaf `fd` may be the source of a calendar bucket
225
+ * (since 0.1.133) — every schema and adapter rule, once, for the core path
226
+ * guard ({@link guardPath} op `bucket`) and moost-db's capability index
227
+ * (`/meta.fields[P].bucketable` and the HTTP gate) alike. First failing rule
228
+ * wins, in this order:
229
+ *
230
+ * 1. `encrypted` — `@db.encrypted` (ciphertext has no calendar);
231
+ * 2. `jsonDescendant` — inside a JSON value (`jsonValueAncestor`):
232
+ * relational adapters cannot address it and nested-object adapters must
233
+ * not diverge from them;
234
+ * 3. `notTimestamp` — not a `number.timestamp` leaf;
235
+ * 4. `notFilterable` — the adapter cannot filter (so cannot group) the storage;
236
+ * 5. `notDimension` — a strict table ({@link isStrictTable}) and the field
237
+ * is not a dimension;
238
+ * 6. `noBuckets` — the adapter reports no `calendarBucketUnits()`.
239
+ *
240
+ * Whether the adapter supports the requested UNIT is a per-query rule, not
241
+ * a field's (the core's `BUCKET_NOT_SUPPORTED`). Caller-specific policy
242
+ * layers on top: moost-db rejects `@db.writeOnly` sources before asking.
243
+ */
244
+ declare function bucketSourceVerdict(fd: TDbFieldMeta, table: TBucketSourceTable, adapter: Pick<BaseDbAdapter, "canFilterField" | "calendarBucketUnits">): TBucketSourceVerdict;
187
245
  /** Every logical path a parsed query references, grouped by position (since 0.1.128). */
188
246
  interface TQueryPathRefs {
189
247
  /**
@@ -268,8 +326,8 @@ declare function classifyQueryPath(source: TQueryPathSource, path: string): {
268
326
  * - a leaf → physical capability (`canSortField` for `$sort`; for a filter
269
327
  * entry {@link canFilterLeaf} of its `predicate` class; `canFilterField`
270
328
  * for `$groupBy` / `$having` / aggregate `$field`s; `$select` always passes);
271
- * a calendar-bucket source must also be a timestamp field
272
- * (`isBucketableField`);
329
+ * a calendar-bucket source must pass `bucketSourceVerdict` (the rules
330
+ * moost-db's capability index applies too);
273
331
  * - a nested-object parent → only `$select`, and only when it expands to
274
332
  * leaf columns (`selectExpansion`);
275
333
  * - everything else is rejected.
@@ -429,4 +487,4 @@ declare function createFailureCollector(what: string): {
429
487
  throwIfAny: () => void;
430
488
  };
431
489
  //#endregion
432
- export { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, ALL_BUCKET_UNITS, type AggregateControls, type AggregateExpr, type AggregateFn, type AggregateQuery, type AggregateResult, ApplicationIntegrity, AtscriptDbReadable, AtscriptDbTable, AtscriptDbView, type AtscriptDbWritable, 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, FieldMappingStrategy, type FieldOpsFor, type FilterExpr, type FilterVisitor, type FlatOf, IntegrityStrategy, NativeIntegrity, type NavPropsOf, NoopLogger, type NullableOptional, type OwnPropsOf, type PrimaryKeyOf, RelationalFieldMapper, type ResolvedBucket, type TAdapterFactory, type TArrayPatch, type TBucketFieldSource, type TCascadeResolver, type TCascadeTarget, type TColumnDiff, type TCrudOp, type TCrudPermissions, type TDbActionInfo, type TDbActionIntent, type TDbActionLevel, type TDbActionProcessor, 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 TDbWriteGuard, type TDbWriteGuardContext, type TDeleteOptions, 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 TIdentification, type TMetaResponse, type TMetadataOverrides, type TPrimaryKeyChange, type TQueryPathKind, type TQueryPathOp, type TQueryPathRefs, type TQueryPathSource, type TReferencingForeignKey, type TRelationInfo, type TResolvedBucket, type TSearchIndexInfo, type TSyncColumnResult, type TTableOptionDiff, type TTableResolver, type TTouchManyOptions, type TValueFormatterPair, type TViewColumnMapping, type TViewJoin, 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, assertGeoPoint, assertNoVersionWrites, bucketTimeZoneUnavailable, buildDbValidator, buildValidationContext, canFilterLeaf, checkHavingKeys, classifyQueryPath, collectQueryPaths, computeInsights, createDbValidatorPlugin, createFailureCollector, decomposePatch, findAncestorInSet, forceNavNonOptional, getDbFieldOp, getKeyProps, guardAggregate, guardFilter, guardPath, guardPaths, guardQuery, isAtscriptDbView, isBucketableField, isDbFieldOp, isEmptyObject, isGeoIndexableType, isGeoPointType, isJsonValueField, isNavRelation, isPlainObject, isPrimitive, jsonValueAncestor, narrowerFilterOps, reconcileCas, resolveCalendarBuckets, resolveDesignType, separateCas, separateFieldOps, sortFieldNames, translateQueryTree, unsupportedOperatorMessage, walkFilter, withOptimisticRetry };
490
+ export { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, ADAPTER_FILTER_REASON, ALL_BUCKET_UNITS, type AggregateControls, type AggregateExpr, type AggregateFn, type AggregateQuery, type AggregateResult, ApplicationIntegrity, AtscriptDbReadable, AtscriptDbTable, AtscriptDbView, type AtscriptDbWritable, 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, RelationalFieldMapper, type ResolvedBucket, 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 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 TDbWriteGuard, type TDbWriteGuardContext, type TDeleteOptions, 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 TIdentification, type TMetaResponse, type TMetadataOverrides, type TPrimaryKeyChange, type TQueryPathKind, type TQueryPathOp, type TQueryPathRefs, type TQueryPathSource, type TReferencingForeignKey, type TRelationInfo, type TResolvedBucket, type TSearchIndexInfo, type TSyncColumnResult, type TTableOptionDiff, type TTableResolver, type TTouchManyOptions, type TValueFormatterPair, type TViewColumnMapping, type TViewJoin, 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, assertGeoPoint, assertNoVersionWrites, bucketSourceVerdict, bucketTimeZoneUnavailable, buildDbValidator, buildValidationContext, canFilterLeaf, checkHavingKeys, classifyQueryPath, collectQueryPaths, computeInsights, createDbValidatorPlugin, createFailureCollector, decomposePatch, findAncestorInSet, forceNavNonOptional, getDbFieldOp, getKeyProps, guardAggregate, guardFilter, guardPath, guardPaths, guardQuery, isAtscriptDbView, isBucketableField, isDbFieldOp, isEmptyObject, isGeoIndexableType, isGeoPointType, isJsonValueField, isNavRelation, isPlainObject, isPrimitive, jsonValueAncestor, narrowerFilterOps, reconcileCas, resolveCalendarBuckets, resolveDesignType, separateCas, separateFieldOps, sortFieldNames, translateQueryTree, unsupportedOperatorMessage, walkFilter, withOptimisticRetry };
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { a as bucketTimeZoneUnavailable, n as CasMismatchError, r as DbError, t as CasExhaustedError } from "./db-error-D5uilS_A.mjs";
2
- import { A as FieldMappingStrategy, B as NoopLogger, C as guardPaths, D as unsupportedOperatorMessage, E as sortFieldNames, F as isGeoPointType, I as isBucketableField, L as isJsonValueField, M as TableMetadata, N as findAncestorInSet, O as RelationalFieldMapper, P as isGeoIndexableType, R as jsonValueAncestor, S as guardPath, T as narrowerFilterOps, _ as checkHavingKeys, a as decomposePatch, b as guardAggregate, c as BaseDbAdapter, d as NativeIntegrity, f as AtscriptDbReadable, g as canFilterLeaf, h as assertGeoPoint, i as assertNoVersionWrites, j as UniquSelect, k as DocumentFieldMapper, l as createFailureCollector, m as acceptedOperatorsHint, n as isAtscriptDbView, o as ApplicationIntegrity, p as resolveDesignType, r as AtscriptDbTable, s as ALL_BUCKET_UNITS, t as AtscriptDbView, u as IntegrityStrategy, v as classifyQueryPath, w as guardQuery, x as guardFilter, y as collectQueryPaths, z as resolveCalendarBuckets } from "./db-view-DVGWWhA3.mjs";
2
+ import { A as unsupportedOperatorMessage, B as isJsonValueField, C as guardAggregate, D as guardQuery, E as guardPaths, F as TableMetadata, H as resolveCalendarBuckets, I as findAncestorInSet, L as isGeoIndexableType, M as DocumentFieldMapper, N as FieldMappingStrategy, O as narrowerFilterOps, P as UniquSelect, R as isGeoPointType, S as collectQueryPaths, T as guardPath, U as NoopLogger, V as jsonValueAncestor, _ as assertGeoPoint, a as decomposePatch, b as checkHavingKeys, c as BaseDbAdapter, d as NativeIntegrity, f as AtscriptDbReadable, g as acceptedOperatorsHint, h as ENCRYPTED_REASON, i as assertNoVersionWrites, j as RelationalFieldMapper, k as sortFieldNames, l as createFailureCollector, m as ADAPTER_FILTER_REASON, n as isAtscriptDbView, o as ApplicationIntegrity, p as resolveDesignType, r as AtscriptDbTable, s as ALL_BUCKET_UNITS, t as AtscriptDbView, u as IntegrityStrategy, v as bucketSourceVerdict, w as guardFilter, x as classifyQueryPath, y as canFilterLeaf, z as isBucketableField } from "./db-view-caPATLmX.mjs";
3
3
  import { a as forceNavNonOptional, c as getKeyProps, l as isEmptyObject, o as isNavRelation, r as buildValidationContext, s as createDbValidatorPlugin, t as buildDbValidator, u as isPlainObject } from "./validator-Ch7UIQl9.mjs";
4
4
  import { t as DEFAULT_DB_SPACE } from "./consts-C_-5_pFq.mjs";
5
5
  import { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, getDbFieldOp, isDbFieldOp, reconcileCas, separateCas, separateFieldOps } from "./ops.mjs";
@@ -372,4 +372,4 @@ function translateQueryTree(node, resolveField) {
372
372
  return { [leftField]: { [comp.op]: comp.right } };
373
373
  }
374
374
  //#endregion
375
- export { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, ALL_BUCKET_UNITS, ApplicationIntegrity, AtscriptDbReadable, AtscriptDbTable, AtscriptDbView, BaseDbAdapter, CasExhaustedError, CasMismatchError, DEFAULT_DB_SPACE, DbEncryption, DbError, DbSpace, DocumentFieldMapper, FieldMappingStrategy, IntegrityStrategy, NativeIntegrity, NoopLogger, RelationalFieldMapper, TableMetadata, UniquSelect, acceptedOperatorsHint, assertGeoPoint, assertNoVersionWrites, bucketTimeZoneUnavailable, buildDbValidator, buildValidationContext, canFilterLeaf, checkHavingKeys, classifyQueryPath, collectQueryPaths, computeInsights, createDbValidatorPlugin, createFailureCollector, decomposePatch, findAncestorInSet, forceNavNonOptional, getDbFieldOp, getKeyProps, guardAggregate, guardFilter, guardPath, guardPaths, guardQuery, isAtscriptDbView, isBucketableField, isDbFieldOp, isEmptyObject, isGeoIndexableType, isGeoPointType, isJsonValueField, isNavRelation, isPlainObject, isPrimitive, jsonValueAncestor, narrowerFilterOps, reconcileCas, resolveCalendarBuckets, resolveDesignType, separateCas, separateFieldOps, sortFieldNames, translateQueryTree, unsupportedOperatorMessage, walkFilter, withOptimisticRetry };
375
+ export { $cas, $dec, $inc, $insert, $mul, $remove, $replace, $update, $upsert, ADAPTER_FILTER_REASON, ALL_BUCKET_UNITS, ApplicationIntegrity, AtscriptDbReadable, AtscriptDbTable, AtscriptDbView, BaseDbAdapter, CasExhaustedError, CasMismatchError, DEFAULT_DB_SPACE, DbEncryption, DbError, DbSpace, DocumentFieldMapper, ENCRYPTED_REASON, FieldMappingStrategy, IntegrityStrategy, NativeIntegrity, NoopLogger, RelationalFieldMapper, TableMetadata, UniquSelect, acceptedOperatorsHint, assertGeoPoint, assertNoVersionWrites, bucketSourceVerdict, bucketTimeZoneUnavailable, buildDbValidator, buildValidationContext, canFilterLeaf, checkHavingKeys, classifyQueryPath, collectQueryPaths, computeInsights, createDbValidatorPlugin, createFailureCollector, decomposePatch, findAncestorInSet, forceNavNonOptional, getDbFieldOp, getKeyProps, guardAggregate, guardFilter, guardPath, guardPaths, guardQuery, isAtscriptDbView, isBucketableField, isDbFieldOp, isEmptyObject, isGeoIndexableType, isGeoPointType, isJsonValueField, isNavRelation, isPlainObject, isPrimitive, jsonValueAncestor, narrowerFilterOps, reconcileCas, resolveCalendarBuckets, resolveDesignType, separateCas, separateFieldOps, sortFieldNames, translateQueryTree, unsupportedOperatorMessage, walkFilter, withOptimisticRetry };
package/dist/rel.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { Dt as TableMetadata, K as TDbRelation, Mt as BaseDbAdapter, R as TDbForeignKey, St as TWriteTableResolver, Vt as TGenericLogger, vt as TTableResolver } from "./buckets-BvoYYQ2Q.cjs";
1
+ import { Dt as TableMetadata, K as TDbRelation, Mt as BaseDbAdapter, R as TDbForeignKey, St as TWriteTableResolver, Vt as TGenericLogger, vt as TTableResolver } from "./buckets-CTWy7Y1k.cjs";
2
2
  import { t as DbValidationContext } from "./db-validator-plugin-BWy60OvG.cjs";
3
3
  import { FilterExpr, WithRelation } from "@uniqu/core";
4
4
  import { Validator } from "@atscript/typescript/utils";
package/dist/rel.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { Dt as TableMetadata, K as TDbRelation, Mt as BaseDbAdapter, R as TDbForeignKey, St as TWriteTableResolver, Vt as TGenericLogger, vt as TTableResolver } from "./buckets-D2XPrwSC.mjs";
1
+ import { Dt as TableMetadata, K as TDbRelation, Mt as BaseDbAdapter, R as TDbForeignKey, St as TWriteTableResolver, Vt as TGenericLogger, vt as TTableResolver } from "./buckets-BENuu_tK.mjs";
2
2
  import { t as DbValidationContext } from "./db-validator-plugin-BWy60OvG.mjs";
3
3
  import { Validator } from "@atscript/typescript/utils";
4
4
  import { FilterExpr, WithRelation } from "@uniqu/core";
package/dist/sync.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_db_view = require("./db-view-CuFAhzwF.cjs");
2
+ const require_db_view = require("./db-view-B5-bQ5AV.cjs");
3
3
  //#region src/schema/schema-hash.ts
4
4
  /** Extracts sorted field snapshots from a readable's field descriptors. */
5
5
  function extractFieldSnapshots(fields, typeMapper) {
package/dist/sync.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { E as TColumnDiff, F as TDbDefaultValue, L as TDbFieldMeta, Nt as AtscriptDbReadable, R as TDbForeignKey, Vt as TGenericLogger, W as TDbObjectKind, Y as TDbStorageType, _t as TTableOptionDiff, ft as TPrimaryKeyChange, it as TExistingTableOption, nt as TExistingColumn, pt as TReferencingForeignKey, rt as TExistingForeignKey, tt as TEnsureTableOptions } from "./buckets-BvoYYQ2Q.cjs";
2
- import { c as AtscriptQueryFieldRef$1, i as AtscriptDbView, l as AtscriptQueryNode$1, t as DbSpace } from "./db-space-Cslq5Dux.cjs";
1
+ import { E as TColumnDiff, F as TDbDefaultValue, L as TDbFieldMeta, Nt as AtscriptDbReadable, R as TDbForeignKey, Vt as TGenericLogger, W as TDbObjectKind, Y as TDbStorageType, _t as TTableOptionDiff, ft as TPrimaryKeyChange, it as TExistingTableOption, nt as TExistingColumn, pt as TReferencingForeignKey, rt as TExistingForeignKey, tt as TEnsureTableOptions } from "./buckets-CTWy7Y1k.cjs";
2
+ import { c as AtscriptQueryFieldRef$1, i as AtscriptDbView, l as AtscriptQueryNode$1, t as DbSpace } from "./db-space-DROLifb-.cjs";
3
3
  import { TAtscriptAnnotatedType } from "@atscript/typescript/utils";
4
4
 
5
5
  //#region src/schema/sync-entry.d.ts
package/dist/sync.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { E as TColumnDiff, F as TDbDefaultValue, L as TDbFieldMeta, Nt as AtscriptDbReadable, R as TDbForeignKey, Vt as TGenericLogger, W as TDbObjectKind, Y as TDbStorageType, _t as TTableOptionDiff, ft as TPrimaryKeyChange, it as TExistingTableOption, nt as TExistingColumn, pt as TReferencingForeignKey, rt as TExistingForeignKey, tt as TEnsureTableOptions } from "./buckets-D2XPrwSC.mjs";
2
- import { c as AtscriptQueryFieldRef$1, i as AtscriptDbView, l as AtscriptQueryNode$1, t as DbSpace } from "./db-space-BQQEgB3d.mjs";
1
+ import { E as TColumnDiff, F as TDbDefaultValue, L as TDbFieldMeta, Nt as AtscriptDbReadable, R as TDbForeignKey, Vt as TGenericLogger, W as TDbObjectKind, Y as TDbStorageType, _t as TTableOptionDiff, ft as TPrimaryKeyChange, it as TExistingTableOption, nt as TExistingColumn, pt as TReferencingForeignKey, rt as TExistingForeignKey, tt as TEnsureTableOptions } from "./buckets-BENuu_tK.mjs";
2
+ import { c as AtscriptQueryFieldRef$1, i as AtscriptDbView, l as AtscriptQueryNode$1, t as DbSpace } from "./db-space-Bv3Ar_Xd.mjs";
3
3
  import { TAtscriptAnnotatedType } from "@atscript/typescript/utils";
4
4
 
5
5
  //#region src/schema/sync-entry.d.ts
package/dist/sync.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { B as NoopLogger } from "./db-view-DVGWWhA3.mjs";
1
+ import { U as NoopLogger } from "./db-view-caPATLmX.mjs";
2
2
  //#region src/schema/schema-hash.ts
3
3
  /** Extracts sorted field snapshots from a readable's field descriptors. */
4
4
  function extractFieldSnapshots(fields, typeMapper) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atscript/db",
3
- "version": "0.1.132",
3
+ "version": "0.1.133",
4
4
  "description": "Database adapter utilities for atscript.",
5
5
  "keywords": [
6
6
  "atscript",
@@ -73,13 +73,13 @@
73
73
  "devDependencies": {
74
74
  "@atscript/core": "^0.1.92",
75
75
  "@atscript/typescript": "^0.1.92",
76
- "@uniqu/core": "^0.1.9",
76
+ "@uniqu/core": "^0.1.10",
77
77
  "unplugin-atscript": "^0.1.92"
78
78
  },
79
79
  "peerDependencies": {
80
80
  "@atscript/core": "^0.1.92",
81
81
  "@atscript/typescript": "^0.1.92",
82
- "@uniqu/core": "^0.1.9"
82
+ "@uniqu/core": "^0.1.10"
83
83
  },
84
84
  "scripts": {
85
85
  "postinstall": "asc -f dts",