@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/README.md +12 -4
- package/package.json +1 -1
- package/src/auth/index.js +97 -36
- package/src/auth/operation-entries.js +111 -0
- package/src/const/QLOperator.js +2 -0
- package/src/execution-state.js +71 -0
- package/src/metadata.js +2 -2
- package/src/mutation-limits.js +37 -7
- package/src/operation-input.js +345 -0
- package/src/query-comparisons.js +54 -0
- package/src/query-frames.js +160 -26
- package/src/query-operators.js +98 -10
- package/src/query-plan.js +94 -29
- package/src/runtime.js +723 -77
- package/src/schema-registrations.js +6 -1
- package/src/transaction-references.js +259 -0
- package/src/transaction-schema.js +163 -0
- package/types/index.d.ts +177 -19
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
|
|
431
|
-
* such as a misspelled
|
|
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
|
|
514
|
-
*
|
|
515
|
-
*
|
|
516
|
-
* `NESTED_OPERATIONS_EXCEEDED` (400) before its
|
|
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).
|
|
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
|
|
620
|
-
*
|
|
621
|
-
*
|
|
622
|
-
*
|
|
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
|
|
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
|
|
861
|
-
*
|
|
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
|
|
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 }>;
|