@lossless.org/client 1.15.0 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -287,15 +287,33 @@ export interface ISmartdataGroupedTotalsOptions<T, TUnwind extends TSmartdataGro
287
287
  */
288
288
  groupBy: ReadonlyArray<TSmartdataGroupedTotalsPath<T>>;
289
289
  /**
290
- * Groups by each element of one array instead of by the array: names
291
- * exactly one `groupBy` path, which must be a declared top-level array
292
- * field or a nested path declared through `@svDb({ arrayPaths })`. Every
293
- * element forms its own row, so `count` counts elements and a document
294
- * contributes its `sums` once per element; a document whose array is
295
- * missing, null or empty contributes nothing. The `filter` still selects
296
- * whole documents before the array is unwound.
290
+ * Aggregates per element of one array instead of per document: names a
291
+ * declared top-level array field or a nested path declared through
292
+ * `@svDb({ arrayPaths })`, which is itself a `groupBy` or `sums` path or
293
+ * holds the element fields that `groupBy` and `sums` paths name below it
294
+ * (`lines.accountNumber` below `unwind: 'lines'`). Element fields are
295
+ * declared nested paths like any other, through `@svDb({ atomicPaths })`
296
+ * on the array's field. Every element contributes on its own, so `count`
297
+ * counts elements and a document contributes its `sums` once per element;
298
+ * a document whose array is missing, null or empty contributes nothing.
299
+ * The `filter` still selects whole documents before the array is unwound,
300
+ * and no `groupBy` or `sums` path may contain the unwound array; use
301
+ * `elementFilter` to select elements.
297
302
  */
298
303
  unwind?: TUnwind;
304
+ /**
305
+ * Selects the unwound elements that contribute, applied after the array is
306
+ * unwound and before grouping: only an element that matches is counted and
307
+ * summed. Requires `unwind`. Every path is the unwound array itself (its
308
+ * scalar element) or a declared nested path below it
309
+ * (`lines.accountNumber` below `unwind: 'lines'`), combined through
310
+ * `$and`, `$or` and `$nor`, with the operators of atomic filters: `$eq`,
311
+ * `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$in`, `$nin`, `$exists`, `$type`,
312
+ * `$regex` with `$options`, and `$not`. Any other path or operator is
313
+ * refused with `invalid_argument`. The document `filter` can carry the same
314
+ * condition to preselect documents through an index.
315
+ */
316
+ elementFilter?: TSmartdataGroupedTotalsElementFilter<NoInfer<TUnwind>>;
299
317
  /**
300
318
  * Declared numeric top-level fields, or declared nested paths holding
301
319
  * numbers, to sum per group.
@@ -303,12 +321,21 @@ export interface ISmartdataGroupedTotalsOptions<T, TUnwind extends TSmartdataGro
303
321
  sums?: ReadonlyArray<TSmartdataNumericDocumentPath<T> | TSmartdataAtomicNestedDocumentPath<T>>;
304
322
  filter?: MongoFilter<T>;
305
323
  /**
306
- * Required bound on the number of returned groups (1..10000). The group
307
- * stage is not sorted, so when more groups exist than the limit the
308
- * returned subset is arbitrary. Use `getGroupedTotalsPage()` when the
309
- * caller must detect overflow at the 10000-group boundary.
324
+ * Required bound on the number of returned groups (1..10000). Groups are
325
+ * ordered by their key — the `groupBy` values in the given order — and the
326
+ * first `limit` groups in that order are returned. Use
327
+ * `getGroupedTotalsPage()` to detect more groups and read them through
328
+ * `nextCursor`, or `iterateGroupedTotals()` to read every group.
310
329
  */
311
330
  limit: number;
331
+ /**
332
+ * Continues after the last group of an earlier page: the `nextCursor` that
333
+ * `getGroupedTotalsPage()` returned for the same `groupBy`, `unwind`,
334
+ * `sums`, `filter` and `elementFilter`. The page holds the groups whose key
335
+ * sorts after that group's key. A cursor that does not decode, or that
336
+ * another query shape produced, is refused with `invalid_argument`.
337
+ */
338
+ cursor?: string;
312
339
  maxTimeMS?: number;
313
340
  /**
314
341
  * Client-side deadline for the aggregation cursor up to its last reply. More
@@ -336,7 +363,23 @@ export interface ISmartdataGroupedTotalsRow<T, TUnwind extends TSmartdataGrouped
336
363
  export interface ISmartdataGroupedTotalsPage<T, TUnwind extends TSmartdataGroupedTotalsUnwindPath<T> = never> {
337
364
  rows: Array<ISmartdataGroupedTotalsRow<T, TUnwind>>;
338
365
  hasMore: boolean;
366
+ /**
367
+ * Present exactly when `hasMore` is true: pass it back as `cursor`, with the
368
+ * same query, to read the next page. Opaque; it carries the query's shape
369
+ * and the last group's key.
370
+ */
371
+ nextCursor?: string;
339
372
  }
373
+ /**
374
+ * The `elementFilter` of grouped totals: conditions on the unwound array
375
+ * `TUnwind` itself or on paths below it, in the shape of atomic filter
376
+ * conditions, combined through `$and`, `$or` and `$nor`.
377
+ */
378
+ export type TSmartdataGroupedTotalsElementFilter<TUnwind extends string> = Partial<Record<TUnwind | `${TUnwind}.${string}`, TSmartdataAtomicFilterCondition<unknown>>> & {
379
+ $and?: Array<TSmartdataGroupedTotalsElementFilter<TUnwind>>;
380
+ $or?: Array<TSmartdataGroupedTotalsElementFilter<TUnwind>>;
381
+ $nor?: Array<TSmartdataGroupedTotalsElementFilter<TUnwind>>;
382
+ };
340
383
  export type TSmartdataAtomicArrayPath<T> = {
341
384
  [TKey in TSmartdataDocumentPath<T>]: NonNullable<T[TKey]> extends ReadonlyArray<unknown> ? TKey : never;
342
385
  }[TSmartdataDocumentPath<T>];
@@ -753,20 +796,47 @@ export declare class SmartDataDbDoc<T extends TImplements, TImplements, TManager
753
796
  * Computes bounded grouped counts and optional numeric sums server-side.
754
797
  * Groups by one or two declared paths — top-level fields or nested paths
755
798
  * declared through `@svDb({ atomicPaths })` or `@svDb({ arrayPaths })` —
756
- * optionally by each element of one declared array (`unwind`), always
757
- * returns a `count` per group, and sums only declared numeric paths. The
758
- * `$limit` follows the group stage without a sort, so when more groups
759
- * exist than the limit the returned subset is arbitrary. Use
760
- * `getGroupedTotalsPage()` when the caller must detect overflow. The
761
- * aggregation cursor never leaves SmartData.
799
+ * optionally per element of one declared array (`unwind`), whose element
800
+ * fields `groupBy` and `sums` may then name and `elementFilter` may select,
801
+ * always returns a `count` per group, and sums only declared numeric paths.
802
+ * Rows come ordered by group key, and the first `limit` groups in that
803
+ * order are returned. Use `getGroupedTotalsPage()` when the caller must
804
+ * detect or read further groups. The aggregation cursor never leaves
805
+ * SmartData.
762
806
  */
763
807
  static getGroupedTotals<T, TUnwind extends TSmartdataGroupedTotalsUnwindPath<T> = never>(this: plugins.tsclass.typeFest.Class<T>, optionsArg: ISmartdataGroupedTotalsOptions<T, TUnwind>): Promise<Array<ISmartdataGroupedTotalsRow<T, TUnwind>>>;
764
808
  /**
765
- * Computes the same bounded grouped totals as `getGroupedTotals()` and
766
- * reports whether at least one additional group exists beyond the requested
767
- * row limit.
809
+ * Computes the same grouped totals as `getGroupedTotals()`, reports whether
810
+ * at least one further group exists beyond the requested row limit and, when
811
+ * one does, returns `nextCursor` to read the next page through `cursor`.
812
+ * Pages follow the group key order, so reading them to the end reports
813
+ * every group exactly once while the data does not change. Under concurrent
814
+ * writes every page reads the data as it is at that page's read: the cursor
815
+ * only moves forward, so no group is reported twice, but a group created
816
+ * with a key before the cursor is not reported, and totals on different
817
+ * pages can reflect different moments. A caller that needs one consistent
818
+ * view reads every page inside one transaction session, as far as the
819
+ * engine's transaction isolation provides one. Paging orders group values that are null or missing,
820
+ * numbers, strings, ObjectIds, booleans and dates; a page that returns a
821
+ * cursor or continues one refuses any other group value — an array, a
822
+ * document, a Decimal128, NaN — with `unsupported_operation` instead of
823
+ * skipping it.
768
824
  */
769
825
  static getGroupedTotalsPage<T, TUnwind extends TSmartdataGroupedTotalsUnwindPath<T> = never>(this: plugins.tsclass.typeFest.Class<T>, optionsArg: ISmartdataGroupedTotalsOptions<T, TUnwind>): Promise<ISmartdataGroupedTotalsPage<T, TUnwind>>;
826
+ /**
827
+ * Reads every group of a grouped-totals query in group key order, one page
828
+ * of `limit` groups per database round trip through
829
+ * `getGroupedTotalsPage()`, with the same exactness, ordering and
830
+ * concurrency rules. `cursor` resumes after an earlier page; `signal`,
831
+ * `timeoutMS` and `maxTimeMS` apply to each page.
832
+ */
833
+ static iterateGroupedTotals<T, TUnwind extends TSmartdataGroupedTotalsUnwindPath<T> = never>(this: plugins.tsclass.typeFest.Class<T>, optionsArg: ISmartdataGroupedTotalsOptions<T, TUnwind>): AsyncGenerator<ISmartdataGroupedTotalsRow<T, TUnwind>, void, undefined>;
834
+ /**
835
+ * Validates grouped-totals options and reads one page. `mintCursorArg` is
836
+ * false for `getGroupedTotals()`, which returns rows only and so never
837
+ * needs the next page's cursor.
838
+ */
839
+ private static readGroupedTotalsPage;
770
840
  /**
771
841
  * gets all instances as array
772
842
  * @param this