@simtlix/simfinity-core 3.15.0 → 3.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.
package/types/index.d.ts CHANGED
@@ -56,11 +56,18 @@ export const MAX_RECORD_VERSION: number;
56
56
  * missing; constructs that middleware and scopes add read stored data. With any other adapter they
57
57
  * fail with `UNSUPPORTED_QUERY`. A term or group condition without a path tests the field itself, except that every term
58
58
  * of a quantified relation filter needs a non-empty element-relative path.
59
+ *
60
+ * `IIN` is `IN` ignoring case: an array of non-null strings without U+0000, possibly empty, on a `String` field or
61
+ * `String` list by its effective scalar; it matches where `IEQ` matches one of them, and `[]` matches nothing.
62
+ * `CONTAINS_ALL` takes a non-empty array of non-null scalars, cast like `IN` elements; it applies to a scalar list or a
63
+ * field reached through embedded lists, where it holds when every value is among the values of all items, and fails
64
+ * with `INVALID_FILTER_OPERATOR` on other leaves and with `INVALID_FILTER_PATH` through a collection or a reference
65
+ * inside an embedded list. Neither has a negated form.
59
66
  */
60
67
  export type QueryOperator =
61
68
  | 'EQ' | 'NE' | 'LT' | 'LTE' | 'GT' | 'GTE' | 'BTW' | 'IN' | 'NIN' | 'LIKE'
62
69
  | 'ILIKE' | 'STARTS_WITH' | 'ISTARTS_WITH' | 'ENDS_WITH' | 'IENDS_WITH' | 'IEQ'
63
- | 'IS_EMPTY' | 'IS_NOT_EMPTY';
70
+ | 'IS_EMPTY' | 'IS_NOT_EMPTY' | 'CONTAINS_ALL' | 'IIN';
64
71
 
65
72
  /** The quantifier applied to the elements visible in a collection or reference frame. */
66
73
  export type QueryQuantifier = 'ANY' | 'ALL' | 'NONE';
@@ -70,6 +77,8 @@ export interface QLFilterCondition {
70
77
  field: string;
71
78
  operator?: QueryOperator | null;
72
79
  value?: any;
80
+ /** A stored field path, mutually exclusive with a supplied value; null preserves literal behavior. */
81
+ valuePath?: string | null;
73
82
  path?: string | null;
74
83
  }
75
84
 
@@ -94,6 +103,8 @@ export interface QLTypeFilterExpression {
94
103
  terms?: Array<{
95
104
  operator?: QueryOperator | null;
96
105
  value?: any;
106
+ /** A stored field path, mutually exclusive with a supplied value; null preserves literal behavior. */
107
+ valuePath?: string | null;
97
108
  path?: string | null;
98
109
  } | null> | null;
99
110
  }
@@ -108,6 +119,8 @@ export interface FilterCondition {
108
119
  field: string;
109
120
  operator?: QueryOperator | (string & {});
110
121
  value?: any;
122
+ /** A stored field path, mutually exclusive with a supplied value; null preserves literal behavior. */
123
+ valuePath?: string | null;
111
124
  path?: string;
112
125
  }
113
126
 
@@ -149,6 +162,8 @@ export interface QueryFeatures {
149
162
  * legacy joins. All adapters reject list sorts through collections, including count mode.
150
163
  */
151
164
  quantifiers?: boolean | null | undefined;
165
+ /** Field operands, including scoped references. Requires referenceEmptiness: true. */
166
+ valuePath?: boolean | null | undefined;
152
167
  }
153
168
 
154
169
  export interface ModelRegistration {
@@ -169,6 +184,10 @@ export interface FieldDescription {
169
184
  scalar?: 'ID' | 'String' | 'Int' | 'Float' | 'Boolean' | 'DateTime' | 'Enum' | 'Version';
170
185
  values?: string[];
171
186
  enumValues?: { name: string; value: unknown }[];
187
+ /** Logical GraphQL enum identity, required for field comparisons. */
188
+ enumName?: string;
189
+ /** Effective temporal base before storage normalizes Date and Time to DateTime. */
190
+ temporalName?: 'DateTime' | 'Date' | 'Time';
172
191
  target?: string;
173
192
  connectionField?: string;
174
193
  fields?: FieldDescription[];
@@ -427,16 +446,24 @@ export interface ConcurrencyDeclaration {
427
446
  }
428
447
 
429
448
  /**
430
- * Process-wide limits for generated add, update and state-action mutations. Any other option,
431
- * such as a misspelled `maxNestedOperation`, throws `INVALID_MUTATION_LIMITS` (400).
449
+ * Process-wide limits for generated mutations. Each call replaces both values: an omitted or
450
+ * `undefined` option restores its default. Any other option, such as a misspelled
451
+ * `maxNestedOperation`, throws `INVALID_MUTATION_LIMITS` (400) and keeps the current limits.
432
452
  */
433
453
  export interface MutationLimitsOptions {
434
454
  /**
435
455
  * Maximum number of `added`, `updated` and `deleted` entries across every nested level of
436
456
  * non-embedded collection fields in one generated mutation. A non-negative safe integer;
437
- * `null` or omitted means unlimited (the default).
457
+ * `null` or omitted means unlimited (the default). The helpers `updateObject` and
458
+ * `transitionObject` apply it to their `input` as the generated mutations do.
438
459
  */
439
460
  maxNestedOperations?: number | null;
461
+ /**
462
+ * Maximum number of operations in one generated transaction mutation. A positive safe integer;
463
+ * omitted means 100 (the default). `null`, `0`, a negative number or a non-integer throws
464
+ * `INVALID_MUTATION_LIMITS` (400).
465
+ */
466
+ maxTransactionOperations?: number;
440
467
  }
441
468
 
442
469
  /**
@@ -449,6 +476,21 @@ export interface CreateSchemaOptions {
449
476
  * `[]` includes none, and names that are not registered are ignored.
450
477
  */
451
478
  includedCustomQueries?: string[] | null;
479
+ /**
480
+ * Adds one mutation field that runs a list of generated mutations in order in one database
481
+ * transaction. `null` or omission adds none. `name` defaults to `transaction` and must be a GraphQL
482
+ * name that does not start with `__`; it names the field and its types (for `transaction`:
483
+ * `TransactionOperation`, a `@oneOf` input keyed by operation, `TransactionResult` and, for deletes
484
+ * of types without optimistic concurrency, `TransactionDeleteInput`). The operations are the
485
+ * generated add, update, delete and state machine action mutations of `types` that this schema
486
+ * includes; registered mutations never are. `types` is a non-empty array of distinct types registered
487
+ * in this runtime. An invalid option throws `INVALID_SCHEMA_OPTIONS` (500) before models are prepared,
488
+ * or once the generated mutations are built when the field name or a derived type name is taken or
489
+ * no operation remains; a type bound to another runtime throws `TYPE_BOUND_TO_OTHER_RUNTIME` (409),
490
+ * and an adapter without `assertTransactionModels` throws `TRANSACTION_UNSUPPORTED` (500). A failed
491
+ * `createSchema()` keeps no transaction field or type.
492
+ */
493
+ transaction?: { name?: string; types: GraphQLObjectType[] } | null;
452
494
  }
453
495
 
454
496
  export interface QueryLimitsOptions {
@@ -510,10 +552,12 @@ export interface Runtime<Model = any, Session = any> {
510
552
  /** The same process-wide setting as the root `configureQueryLimits`. */
511
553
  configureQueryLimits(options?: QueryLimitsOptions): void;
512
554
  /**
513
- * Process-wide; calling it without options restores the unlimited default. Invalid options,
514
- * including unknown or misspelled option keys, throw `INVALID_MUTATION_LIMITS` (400) and keep
515
- * the current limit. A generated mutation over the limit fails with
516
- * `NESTED_OPERATIONS_EXCEEDED` (400) before its transaction starts.
555
+ * Process-wide; calling it without options restores both defaults (`maxNestedOperations`
556
+ * unlimited, `maxTransactionOperations` 100). Invalid options, including unknown or misspelled
557
+ * option keys, throw `INVALID_MUTATION_LIMITS` (400) and keep the current limits. A generated
558
+ * mutation over the nested limit fails with `NESTED_OPERATIONS_EXCEEDED` (400) before its
559
+ * transaction starts. `updateObject` and `transitionObject` apply `maxNestedOperations` to their
560
+ * `input` in the same way (`null` = no limit).
517
561
  */
518
562
  configureMutationLimits(options?: MutationLimitsOptions): void;
519
563
  /**
@@ -561,7 +605,8 @@ export interface Runtime<Model = any, Session = any> {
561
605
  *
562
606
  * `options.includedCustomQueries` selects custom queries by name (see {@link CreateSchemaOptions});
563
607
  * an included custom query named like an included generated query throws `QUERY_NAME_CONFLICT`
564
- * (500). A schema without mutation fields has no `Mutation` root.
608
+ * (500). `options.transaction` adds the generated transaction field (see {@link CreateSchemaOptions}).
609
+ * A schema without mutation fields has no `Mutation` root.
565
610
  */
566
611
  createSchema(includedQueryTypes?: GraphQLObjectType[] | null, includedMutationTypes?: GraphQLObjectType[] | null, includedCustomMutations?: string[] | null, options?: CreateSchemaOptions): GraphQLSchema;
567
612
  getModel(type: GraphQLObjectType | { name: string }): Model | null | undefined;
@@ -602,6 +647,64 @@ export interface Runtime<Model = any, Session = any> {
602
647
  registerView(name: string, options: ViewOptions): void;
603
648
  /** Owns the full workflow transaction unless an active caller session is supplied. */
604
649
  saveObject(typeName: string, args: Record<string, any>, session?: Session, context?: any): Promise<any>;
650
+ /**
651
+ * Runs the lifecycle of the generated update mutation from code: validators, controller hooks,
652
+ * optimistic concurrency and the nested `added`, `updated` and `deleted` entries, in one transaction.
653
+ * `typeName` names a type registered in this runtime that stores records and has its update input
654
+ * prepared by `createSchema()`, with an `id` field. Whether a schema exposes the mutation does not
655
+ * matter: the helper is not an authorization boundary. Any other `typeName` rejects with
656
+ * `INVALID_OPERATION_TARGET` (500), before the input is read.
657
+ *
658
+ * `input` has the shape of the type's generated update input, `version` included on a type with
659
+ * optimistic concurrency. It is checked structurally and copied before anything runs, and the
660
+ * caller's object is never written to. It is not coerced like a GraphQL input: enum fields take
661
+ * their internal values, scalars are not parsed, a reference is its record key as a string, such as
662
+ * `{ id: String(record._id) }`, and the `state` of a type with a state machine changes only through
663
+ * `transitionObject`. A scalar field takes a primitive, a `Date` or plain data (objects and arrays,
664
+ * copied deeply, at most 256 levels deep); class instances such as `ObjectId`, `Buffer` or `Map` are
665
+ * rejected with `INVALID_INPUT`. An own `undefined` counts as omitted, and a bare value is never
666
+ * wrapped into a list. A missing `input`, `id` or value for a non-null field rejects with
667
+ * `REQUIRED_VALUE` (400); any other violation, such as an unknown field, an object that is not plain
668
+ * or a list that is not dense, rejects with `INVALID_INPUT` (400). The message names the path, such
669
+ * as `input.lines.added[1].price`, and never a value. More nested entries than `maxNestedOperations`
670
+ * from `configureMutationLimits()` (`null` = no limit) reject with `NESTED_OPERATIONS_EXCEEDED` (400)
671
+ * before the transaction starts.
672
+ *
673
+ * Without `session`, the adapter owns the transaction and its retries. A supplied `session` must have
674
+ * an active transaction, and the helper itself never commits, retries, aborts or cleans up a supplied
675
+ * session; an adapter may still abort it on a write error (for example MongoDB with transactional
676
+ * reference integrity). Like `saveObject`, it skips the global middleware of the record itself; nested entries keep theirs and
677
+ * receive `context`, which may be `undefined`.
678
+ *
679
+ * Resolves to the updated record, as the generated mutation returns it. An `id` that has no record
680
+ * rejects with `NOT_VALID_ID` (404), and a stale `version` with `VERSION_CONFLICT` (409).
681
+ */
682
+ updateObject(typeName: string, input: Record<string, any>, session?: Session, context?: any): Promise<any>;
683
+ /**
684
+ * Runs the lifecycle of the generated delete mutation from code. `target` is `{ id }`, the record key
685
+ * as a string, plus `version`, the version read, on a type with optimistic concurrency; on any other
686
+ * type `version` is an unknown field. The type is checked as in {@link Runtime.updateObject}, except
687
+ * that it needs no update input of its own; the type must still be a stored record type, which only
688
+ * `createSchema()` establishes. The target is checked before anything runs: a missing
689
+ * target, `id` or required `version` rejects with `REQUIRED_VALUE` (400), and any other violation
690
+ * with `INVALID_INPUT` (400). A stale `version` rejects with `VERSION_CONFLICT` (409). Sessions,
691
+ * `context` and middleware work as in `updateObject`.
692
+ *
693
+ * Resolves to the deleted record, or to `null` when no record has that ID.
694
+ */
695
+ deleteObject(typeName: string, target: { id: string; version?: number }, session?: Session, context?: any): Promise<any>;
696
+ /**
697
+ * Runs the state machine action `actionName` of `typeName` from code, with the lifecycle of the
698
+ * generated action mutation: the check of the current state, the action's callback, the update and the
699
+ * controller hooks, in one transaction. An `actionName` that is not an own action of the type's state
700
+ * machine, or a type without one, rejects with `UNKNOWN_ACTION` (500). The type, the checks of `input`,
701
+ * the session, `context`, the middleware and the errors are as in {@link Runtime.updateObject}. `input` has
702
+ * the shape of the update input and does not carry `state`. An action that does not start from the
703
+ * record's state rejects with `BAD_REQUEST` (400).
704
+ *
705
+ * Resolves to the updated record, with `state` set to the action's target state.
706
+ */
707
+ transitionObject(typeName: string, actionName: string, input: Record<string, any>, session?: Session, context?: any): Promise<any>;
605
708
  preventCreatingCollection(prevent: boolean): void;
606
709
  }
607
710
 
@@ -616,10 +719,17 @@ export interface DatabaseAdapter<Model = any, Session = any> {
616
719
  * by-ID read through a `get_by_id` scope, whose arguments use a `QLOperator` value the adapter
617
720
  * does not support fails with `UNSUPPORTED_QUERY` (400), before middleware runs for the client's
618
721
  * arguments and before `find`, `count`, `aggregate`, `findChildren` or `findChildrenBatch` for
619
- * conditions that middleware, scopes and joined scopes added. Operators outside `QLOperator` still
620
- * reach the adapter, which reports them as before. Declaring `IS_EMPTY` and `IS_NOT_EMPTY` means
621
- * compiling their semantics on the record's own fields; emptiness through references and
622
- * collections also needs `referenceEmptiness: true`, and fails with `UNSUPPORTED_QUERY` without it.
722
+ * conditions that middleware, scopes and joined scopes added. Operators outside `QLOperator`, which
723
+ * only trusted code can write, fail with `INVALID_FILTER_OPERATOR` (400) before the adapter is
724
+ * called, except in the forms the compilers ignore: an operator beside the `terms` of an object
725
+ * filter, and the `terms` of a scalar, scalar-list, interface or union field's filter. Those reach
726
+ * the adapter, which ignores them. Declaring `IS_EMPTY` and `IS_NOT_EMPTY` means compiling their
727
+ * semantics on the record's own fields; emptiness through references and collections also needs
728
+ * `referenceEmptiness: true`, and fails with `UNSUPPORTED_QUERY` without it.
729
+ * Declaring `CONTAINS_ALL` means compiling set containment over the leaf's values, including the
730
+ * values of every item of embedded lists, two-valued under negation; declaring `IIN` means
731
+ * compiling case-insensitive membership under the case-folding contract of the text operators.
732
+ * Names that an older version ignored are honored once this version knows them.
623
733
  */
624
734
  queryFeatures?: QueryFeatures | null | undefined;
625
735
  /**
@@ -631,6 +741,16 @@ export interface DatabaseAdapter<Model = any, Session = any> {
631
741
  * contract of `update` and `delete` and to the requirements on `find` below.
632
742
  */
633
743
  writeFeatures?: { optimisticConcurrency?: boolean } | null | undefined;
744
+ /**
745
+ * Optional, and required to enable the generated transaction field (see
746
+ * `CreateSchemaOptions.transaction`). Receives the models one transaction of that field may
747
+ * write: those of the types that own its operations and of the referenced collection items their
748
+ * inputs declare, at any depth, without duplicates. Core calls it before each transaction of the
749
+ * field opens, never in `createSchema()`, so a schema can be created before the connection opens.
750
+ * It must be synchronous and never write, and it throws when the models cannot share one session; a
751
+ * returned promise fails the transaction with `TRANSACTION_UNSUPPORTED` (500).
752
+ */
753
+ assertTransactionModels?(models: Model[]): void;
634
754
  bind?(runtime: Pick<Runtime<Model, Session>, 'getModel' | 'getType' | 'getRegistrations'>): void;
635
755
  validateRegistration?(registration: RuntimeRegistration<Model, Session>): void;
636
756
  /**
@@ -789,8 +909,13 @@ export function createRuntime<Model = any, Session = any>(adapter: DatabaseAdapt
789
909
  /** Scoped single-reference joins, keyed by a dotted prefix relative to the containing frame. */
790
910
  export type QueryJoins = Record<string, QueryPredicate | null>;
791
911
 
912
+ /** A field operand in the same frame (up: 0) or an enclosing shorthand frame. */
913
+ export type QueryOperand = { up: number; path: string[]; joins?: QueryJoins };
914
+
792
915
  /**
793
916
  * `operator` is a {@link QueryOperator}; the value of a text operator is a validated string. For
917
+ * `CONTAINS_ALL` the value is a non-empty array of non-null scalars, validated and not cast; the
918
+ * compiler casts each element as for `IN`. For `IIN` it is an array of strings, possibly empty. For
794
919
  * `IS_EMPTY` and `IS_NOT_EMPTY` the value is null, and `path` may end at an embedded object, an
795
920
  * embedded list or a scalar list as well as at a scalar; `IS_NOT_EMPTY` is the exact complement,
796
921
  * which the compiler builds. With `referenceEmptiness: true`, their `path` may also cross single
@@ -808,10 +933,11 @@ export type QueryJoins = Record<string, QueryPredicate | null>;
808
933
  * A `quantified` node selects elements with `ANY`, `ALL` or `NONE`, applying `scope` before `where`;
809
934
  * both predicates use paths relative to the element, and null means no restriction. Empty elements
810
935
  * give ANY false, ALL/NONE true; scope is never negated, and frames never multiply roots. `anchor` is
811
- * an aggregate's legacy join chain; when present, `path` is relative to it and `joins` is absent.
936
+ * an aggregate's legacy join chain; when present, `path` is relative to it. Comparison-bearing
937
+ * anchored frames may carry full-prefix joins as visibility guards, preserving the existing J row.
812
938
  */
813
939
  export type QueryPredicate =
814
- | { kind: 'predicate'; path: string[]; operator: string; value: any; scopes?: Record<string, QueryPredicate | null>; joins?: QueryJoins }
940
+ | { kind: 'predicate'; path: string[]; operator: string; value: any; operand?: QueryOperand; scopes?: Record<string, QueryPredicate | null>; joins?: QueryJoins }
815
941
  | { kind: 'and' | 'or'; terms: QueryPredicate[] }
816
942
  | {
817
943
  kind: 'quantified';
@@ -849,6 +975,29 @@ export interface QueryPlan {
849
975
  * object fails with `INVALID_FILTER_PATH`, as on MongoDB; a bare object field keeps
850
976
  * `MISSING_FILTER_PATH`.
851
977
  *
978
+ * `CONTAINS_ALL` and `IIN` are checked in this order: the path (`AMBIGUOUS_FILTER_FIELD`,
979
+ * `INVALID_FILTER_PATH`, `INVALID_FILTER_FIELD`) and the object-end rule above, then an unknown name
980
+ * (`INVALID_FILTER_OPERATOR`) and `operators` (`UNSUPPORTED_QUERY`), then, for `CONTAINS_ALL` only,
981
+ * `INVALID_FILTER_PATH` through a collection, aggregate join prefixes included
982
+ * (`The shorthand excludes them; use an explicit group`), `INVALID_FILTER_PATH` through a reference
983
+ * inside an embedded list, and `INVALID_FILTER_OPERATOR` on a leaf that is neither a scalar list nor
984
+ * a scalar reached through an embedded list, and the values last, with `INVALID_FILTER_VALUE`.
985
+ * `CONTAINS_ALL` takes a non-empty array of non-null scalars, none of them an array or a plain
986
+ * object; `IIN` takes an array of strings without U+0000, possibly empty, on a `String` field or list
987
+ * by its effective scalar. A hole of a sparse array fails for both, while `IN`, `NIN` and `BTW` keep
988
+ * skipping holes.
989
+ * Both plan `{ kind: 'predicate', path, operator, value }` with the array as validated, neither cast
990
+ * nor deduplicated. `IIN` through a collection plans as `IN` does: an implicit `ANY` frame with
991
+ * `quantifiers`, a row filter on an aggregate's join prefix, a legacy join otherwise. `CONTAINS_ALL`
992
+ * is never cut into a frame.
993
+ *
994
+ * `valuePath` selects a compatible stored scalar operand instead of a literal value. It defaults
995
+ * like `quantifiers`; a comparison node has `value: null` and `operand: { up, path, joins? }`.
996
+ * Same-frame operands use the union of scoped paths in `joins`; internal shorthand outer bindings
997
+ * use positive `up` and their own operand joins. Public inputs do not accept outer-frame syntax.
998
+ * Null equality is two-valued, and a left scalar list uses null-safe EQ/NE membership.
999
+ * Embedded-list comparisons, right scalar lists and incompatible logical types fail explicitly.
1000
+ *
852
1001
  * `referenceEmptiness` defaults to true when `operators` is omitted and to false when it is given.
853
1002
  * When it is false, an emptiness condition that crosses or ends at a reference or a collection, or
854
1003
  * reads a reference or collection member, fails with `UNSUPPORTED_QUERY` where the order above has
@@ -857,10 +1006,19 @@ export interface QueryPlan {
857
1006
  * becomes the predicate's `scopes`. `quantifiers` has the same default rule and requires reference
858
1007
  * emptiness; enabled collection filters emit quantified nodes, with per-group/prefix correlation,
859
1008
  * element-relative scopes/joins and aggregate anchors beyond legacy J joins. `__scope`, `__implicit`
860
- * and `__anchor` are reserved internal input metadata. A marker not filled for every path fails
861
- * with `DETACHED_CLIENT_FILTER` (500).
1009
+ * and `__anchor` are reserved internal input metadata. A group that trusted code writes with
1010
+ * `__implicit: true` must, after its `__anchor`, end at a collection, or at a reference without
1011
+ * crossing a list, and its `__anchor`, when present, must have exactly the shape the collection
1012
+ * shorthand writes: in an aggregate, on a group at the root, a non-empty array of field names without
1013
+ * dots that crosses at least one collection, each a join prefix, followed by a `path` of one
1014
+ * collection. Otherwise the group fails with `INVALID_FILTER_PATH` (400), whatever operators it holds
1015
+ * and before its conditions are checked, with the message
1016
+ * `An implicit quantified path must end at a collection, or at a reference without crossing a list` or
1017
+ * `An implicit quantified anchor must name the aggregate's join prefixes`; the anchor's form is
1018
+ * checked before the path rule, the rest after it.
1019
+ * A marker not filled for every path fails with `DETACHED_CLIENT_FILTER` (500).
862
1020
  */
863
- export function createQueryPlan(models: ModelDescription, entityName: string, input?: Record<string, any>, options?: { mode?: QueryPlan['mode']; operators?: Iterable<string>; referenceEmptiness?: boolean; quantifiers?: boolean }): QueryPlan;
1021
+ export function createQueryPlan(models: ModelDescription, entityName: string, input?: Record<string, any>, options?: { mode?: QueryPlan['mode']; operators?: Iterable<string>; referenceEmptiness?: boolean; quantifiers?: boolean; valuePath?: boolean }): QueryPlan;
864
1022
  export function resolveModelPath(models: ModelDescription, entityName: string, path: string | string[]): FieldDescription[];
865
1023
 
866
1024
  /**
@@ -874,7 +1032,7 @@ export function resolveModelPath(models: ModelDescription, entityName: string, p
874
1032
  export function configureQueryLimits(options?: QueryLimitsOptions): void;
875
1033
  /**
876
1034
  * Same process-wide setting as `Runtime.configureMutationLimits`. Unknown or misspelled options
877
- * throw `INVALID_MUTATION_LIMITS` (400) and keep the current limit.
1035
+ * throw `INVALID_MUTATION_LIMITS` (400) and keep the current limits.
878
1036
  */
879
1037
  export function configureMutationLimits(options?: MutationLimitsOptions): void;
880
1038
  export function paginationStages(pagination: { page: number; size: number } | null | undefined, withDefault: boolean): Array<{ $skip: number } | { $limit: number }>;