@simtlix/simfinity-core 3.9.0 → 3.10.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 +4 -3
- package/package.json +1 -1
- package/src/auth/index.js +5 -3
- package/src/const/QLOperator.js +2 -0
- package/src/metadata.js +24 -8
- package/src/query-emptiness.js +222 -0
- package/src/query-operators.js +8 -1
- package/src/query-plan.js +131 -24
- package/src/runtime.js +272 -58
- package/types/index.d.ts +60 -6
package/types/index.d.ts
CHANGED
|
@@ -21,10 +21,22 @@ export const QLValue: GraphQLScalarType<unknown, unknown>;
|
|
|
21
21
|
* and `IENDS_WITH` as a suffix, respecting or ignoring case, and `IEQ` as the whole value ignoring
|
|
22
22
|
* case. An empty value matches every non-null string, except for `IEQ`, where it matches only the
|
|
23
23
|
* empty string. On a list, some element must match.
|
|
24
|
+
*
|
|
25
|
+
* `IS_EMPTY` and `IS_NOT_EMPTY` take no value (omitted or null; any other value fails with
|
|
26
|
+
* `INVALID_FILTER_VALUE`), and every record matches exactly one of them. `IS_EMPTY` holds for a
|
|
27
|
+
* missing, null or `""` String (`" "` is not empty), a missing or null value of any other scalar or
|
|
28
|
+
* enum, a missing, null or `[]` list (`[null]` and `[""]` are not empty), and a missing or null
|
|
29
|
+
* embedded object or one whose stored members are all empty by these rules; the record identity is
|
|
30
|
+
* never empty. They apply to the queried record's own fields: a path that continues inside an
|
|
31
|
+
* embedded list or a collection fails with `INVALID_FILTER_PATH`, and a path that crosses or ends
|
|
32
|
+
* at a reference, a path that ends at a collection, and an embedded object with a reference or
|
|
33
|
+
* collection member fail with `UNSUPPORTED_QUERY` until reference emptiness arrives. A term or
|
|
34
|
+
* group condition without a path tests the field itself.
|
|
24
35
|
*/
|
|
25
36
|
export type QueryOperator =
|
|
26
37
|
| 'EQ' | 'NE' | 'LT' | 'LTE' | 'GT' | 'GTE' | 'BTW' | 'IN' | 'NIN' | 'LIKE'
|
|
27
|
-
| 'ILIKE' | 'STARTS_WITH' | 'ISTARTS_WITH' | 'ENDS_WITH' | 'IENDS_WITH' | 'IEQ'
|
|
38
|
+
| 'ILIKE' | 'STARTS_WITH' | 'ISTARTS_WITH' | 'ENDS_WITH' | 'IENDS_WITH' | 'IEQ'
|
|
39
|
+
| 'IS_EMPTY' | 'IS_NOT_EMPTY';
|
|
28
40
|
|
|
29
41
|
/**
|
|
30
42
|
* The query language features a {@link DatabaseAdapter} compiles. Declare it so that the runtime
|
|
@@ -279,6 +291,18 @@ export interface MutationLimitsOptions {
|
|
|
279
291
|
maxNestedOperations?: number | null;
|
|
280
292
|
}
|
|
281
293
|
|
|
294
|
+
/**
|
|
295
|
+
* The fourth `createSchema()` argument. Any other key, or a value that is not a plain object,
|
|
296
|
+
* throws `INVALID_SCHEMA_OPTIONS` (500) before models are prepared.
|
|
297
|
+
*/
|
|
298
|
+
export interface CreateSchemaOptions {
|
|
299
|
+
/**
|
|
300
|
+
* Custom queries to include, by name. `null` or omission includes every registered custom query,
|
|
301
|
+
* `[]` includes none, and names that are not registered are ignored.
|
|
302
|
+
*/
|
|
303
|
+
includedCustomQueries?: string[] | null;
|
|
304
|
+
}
|
|
305
|
+
|
|
282
306
|
export interface Runtime<Model = any, Session = any> {
|
|
283
307
|
configureQueryLimits(options?: { maxPageSize?: number }): void;
|
|
284
308
|
/**
|
|
@@ -312,7 +336,7 @@ export interface Runtime<Model = any, Session = any> {
|
|
|
312
336
|
* not virtual, and is not a reference or collection, logs a `Configuration issue` warning once. The
|
|
313
337
|
* first schema binds the types whose relation resolvers it generates to this runtime and
|
|
314
338
|
* reserves reachable types that still have a
|
|
315
|
-
* non-embedded relation field without a resolver, such as an unregistered custom
|
|
339
|
+
* non-embedded relation field without a resolver, such as an unregistered custom operation result.
|
|
316
340
|
* Every entity type resolves `id` to `_id ?? id`, whatever the allowlists include.
|
|
317
341
|
*
|
|
318
342
|
* A generated input that would have no fields is left out, with a `Configuration issue`
|
|
@@ -326,12 +350,16 @@ export interface Runtime<Model = any, Session = any> {
|
|
|
326
350
|
* metadata types `SimfinityFieldExtensionsType` and `SimfinityRelationType` (numbered when
|
|
327
351
|
* taken) for every later schema and logs a warning; once those names are fixed, a type with one
|
|
328
352
|
* of them throws `RESERVED_TYPE_NAME` (500), before `adapter.prepare()` when it is an included
|
|
329
|
-
* endpoint type, a registered
|
|
353
|
+
* endpoint type, a registered custom operation's input or output type, an output type they reach or a
|
|
330
354
|
* field argument's type, and when the schema is constructed otherwise, such as for a type inside
|
|
331
355
|
* an input object's fields. The check before `adapter.prepare()` never reads an input object's
|
|
332
356
|
* fields, so a registered input's `fields` function may call `getInputType()`.
|
|
357
|
+
*
|
|
358
|
+
* `options.includedCustomQueries` selects custom queries by name (see {@link CreateSchemaOptions});
|
|
359
|
+
* an included custom query named like an included generated query throws `QUERY_NAME_CONFLICT`
|
|
360
|
+
* (500). A schema without mutation fields has no `Mutation` root.
|
|
333
361
|
*/
|
|
334
|
-
createSchema(includedQueryTypes?: GraphQLObjectType[] | null, includedMutationTypes?: GraphQLObjectType[] | null, includedCustomMutations?: string[] | null): GraphQLSchema;
|
|
362
|
+
createSchema(includedQueryTypes?: GraphQLObjectType[] | null, includedMutationTypes?: GraphQLObjectType[] | null, includedCustomMutations?: string[] | null, options?: CreateSchemaOptions): GraphQLSchema;
|
|
335
363
|
getModel(type: GraphQLObjectType | { name: string }): Model | null | undefined;
|
|
336
364
|
getType(name: string | { name: string }): GraphQLObjectType | null | undefined;
|
|
337
365
|
/**
|
|
@@ -350,6 +378,13 @@ export interface Runtime<Model = any, Session = any> {
|
|
|
350
378
|
*/
|
|
351
379
|
use(middleware: (params: MiddlewareContext, next: () => Promise<void>) => void | Promise<void>): void;
|
|
352
380
|
registerMutation(name: string, description: string, input: GraphQLInputObjectType | null | undefined, output: GraphQLOutputType, callback: (args: any, session: Session, context: any) => any): void;
|
|
381
|
+
/**
|
|
382
|
+
* Register a custom query on `RootQueryType`, for a result that is not a stored record. The
|
|
383
|
+
* callback receives the input and the request context; no transaction or session wraps it.
|
|
384
|
+
* Throws `INVALID_QUERY_REGISTRATION` (500) for invalid arguments and `QUERY_NAME_CONFLICT`
|
|
385
|
+
* (500) for a name already registered.
|
|
386
|
+
*/
|
|
387
|
+
registerCustomQuery(name: string, description: string, input: GraphQLInputObjectType | null | undefined, output: GraphQLOutputType, callback: (input: any, context: any) => any): void;
|
|
353
388
|
/** Owns the full workflow transaction unless an active caller session is supplied. */
|
|
354
389
|
saveObject(typeName: string, args: Record<string, any>, session?: Session, context?: any): Promise<any>;
|
|
355
390
|
preventCreatingCollection(prevent: boolean): void;
|
|
@@ -366,7 +401,9 @@ export interface DatabaseAdapter<Model = any, Session = any> {
|
|
|
366
401
|
* does not support fails with `UNSUPPORTED_QUERY` (400), before middleware runs for the client's
|
|
367
402
|
* arguments and before `find`, `count`, `aggregate`, `findChildren` or `findChildrenBatch` for
|
|
368
403
|
* conditions that middleware, scopes and joined scopes added. Operators outside `QLOperator` still
|
|
369
|
-
* reach the adapter, which reports them as before.
|
|
404
|
+
* reach the adapter, which reports them as before. Declaring `IS_EMPTY` and `IS_NOT_EMPTY` means
|
|
405
|
+
* compiling their semantics on the record's own fields; it does not lift the `UNSUPPORTED_QUERY`
|
|
406
|
+
* that emptiness through references and collections gets in this release.
|
|
370
407
|
*/
|
|
371
408
|
queryFeatures?: QueryFeatures | null | undefined;
|
|
372
409
|
bind?(runtime: Pick<Runtime<Model, Session>, 'getModel' | 'getType' | 'getRegistrations'>): void;
|
|
@@ -486,7 +523,12 @@ export interface DatabaseAdapter<Model = any, Session = any> {
|
|
|
486
523
|
}
|
|
487
524
|
export function createRuntime<Model = any, Session = any>(adapter: DatabaseAdapter<Model, Session>): Runtime<Model, Session>;
|
|
488
525
|
|
|
489
|
-
/**
|
|
526
|
+
/**
|
|
527
|
+
* `operator` is a {@link QueryOperator}; the value of a text operator is a validated string. For
|
|
528
|
+
* `IS_EMPTY` and `IS_NOT_EMPTY` the value is null, and `path` may end at an embedded object, an
|
|
529
|
+
* embedded list or a scalar list as well as at a scalar; `IS_NOT_EMPTY` is the exact complement,
|
|
530
|
+
* which the compiler builds.
|
|
531
|
+
*/
|
|
490
532
|
export type QueryPredicate = { kind: 'predicate'; path: string[]; operator: string; value: any } | { kind: 'and' | 'or'; terms: QueryPredicate[] };
|
|
491
533
|
export interface QueryPlan {
|
|
492
534
|
entity: string;
|
|
@@ -502,6 +544,18 @@ export interface QueryPlan {
|
|
|
502
544
|
* a string or contains U+0000. With `operators`, the names the caller compiles, any other
|
|
503
545
|
* `QLOperator` value fails with `UNSUPPORTED_QUERY` (400); unknown operators fail with
|
|
504
546
|
* `INVALID_FILTER_OPERATOR` (400) either way.
|
|
547
|
+
*
|
|
548
|
+
* An emptiness condition is checked in this order: its form, path and group depth
|
|
549
|
+
* (`MISSING_FILTER_PATH` for `IS_EMPTY` or `IS_NOT_EMPTY` on an object filter without terms or beside
|
|
550
|
+
* terms, `AMBIGUOUS_FILTER_FIELD`, `INVALID_FILTER_PATH`, `INVALID_FILTER_FIELD`,
|
|
551
|
+
* `FILTER_DEPTH_EXCEEDED`), then `operators` (`UNSUPPORTED_QUERY`), then `INVALID_FILTER_PATH` for a
|
|
552
|
+
* value inside an embedded list or a collection, `INVALID_FILTER_OPERATOR` for an embedded type that
|
|
553
|
+
* reaches itself through single embedded members, `INVALID_FILTER_VALUE` for a value that is not
|
|
554
|
+
* omitted or null, and `UNSUPPORTED_QUERY` for a reference or collection on the path or among the
|
|
555
|
+
* members. A term without a path (omitted, null or `""`) and a group condition without a path test
|
|
556
|
+
* the field itself. For other operators, a filter path of more than one segment that ends at an
|
|
557
|
+
* object fails with `INVALID_FILTER_PATH`, as on MongoDB; a bare object field keeps
|
|
558
|
+
* `MISSING_FILTER_PATH`.
|
|
505
559
|
*/
|
|
506
560
|
export function createQueryPlan(models: ModelDescription, entityName: string, input?: Record<string, any>, options?: { mode?: QueryPlan['mode']; operators?: Iterable<string> }): QueryPlan;
|
|
507
561
|
export function resolveModelPath(models: ModelDescription, entityName: string, path: string | string[]): FieldDescription[];
|