@simtlix/simfinity-core 3.5.7 → 3.5.9
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 +5 -3
- package/package.json +54 -8
- package/src/const/QLValue.js +11 -3
- package/src/errors/internal-server.error.js +5 -1
- package/src/index.js +3 -0
- package/src/introspection.js +42 -8
- package/src/runtime.js +691 -177
- package/src/scalars.js +53 -33
- package/src/validators.js +159 -47
- package/types/auth/errors.d.ts +12 -0
- package/types/auth/expressions.d.ts +25 -0
- package/types/auth/index.d.ts +36 -0
- package/types/auth/rules.d.ts +30 -0
- package/types/index.d.ts +108 -15
- package/types/plugins.d.ts +14 -0
- package/types/scalars.d.ts +16 -0
- package/types/validators.d.ts +20 -0
package/types/index.d.ts
CHANGED
|
@@ -75,6 +75,13 @@ export class SimfinityError extends Error {
|
|
|
75
75
|
getCause?(): unknown;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
/**
|
|
79
|
+
* An unexpected failure: code `INTERNAL_SERVER_ERROR` and status 500 (`getStatus()` and
|
|
80
|
+
* `extensions.status`). `cause` keeps the original error. The cause is never included in GraphQL
|
|
81
|
+
* responses, or in the errors that `buildErrorFormatter` returns when they are serialized. It is an
|
|
82
|
+
* enumerable own property of this error, so `JSON.stringify(error)`, or a logger that copies
|
|
83
|
+
* enumerable properties, includes it.
|
|
84
|
+
*/
|
|
78
85
|
export class InternalServerError extends SimfinityError {
|
|
79
86
|
constructor(message: string, cause?: unknown);
|
|
80
87
|
cause?: unknown;
|
|
@@ -106,6 +113,8 @@ export class InternalServerError extends SimfinityError {
|
|
|
106
113
|
* - a non-Error value becomes `InternalServerError('Unexpected error value')` with no cause. Servers
|
|
107
114
|
* whose executor first turns it into an `Error`, such as Yoga, pass the value's text instead.
|
|
108
115
|
*
|
|
116
|
+
* Every `InternalServerError` has code `INTERNAL_SERVER_ERROR` and status 500.
|
|
117
|
+
*
|
|
109
118
|
* `callback` receives the classified error; check `error instanceof InternalServerError` to mask
|
|
110
119
|
* unexpected errors. A returned error replaces it, and a returned `GraphQLError` is returned
|
|
111
120
|
* unchanged. The result is a `GraphQLError` that keeps the input's locations and path, has the
|
|
@@ -218,11 +227,30 @@ export interface Runtime<Model = any, Session = any> {
|
|
|
218
227
|
* reserves reachable types that still have a
|
|
219
228
|
* non-embedded relation field without a resolver, such as an unregistered custom mutation result.
|
|
220
229
|
* Every entity type resolves `id` to `_id ?? id`, whatever the allowlists include.
|
|
230
|
+
*
|
|
231
|
+
* A generated input that would have no fields is left out, with a `Configuration issue`
|
|
232
|
+
* warning: the `added` or `updated` operation of a collection whose child has no writable fields
|
|
233
|
+
* for it, an embedded field whose embedded type has none, `add<type>` for a type without
|
|
234
|
+
* writable fields, and `update<type>` and its state actions for a type without writable fields
|
|
235
|
+
* and without a writable `id`. A non-null embedded field whose embedded type has no writable
|
|
236
|
+
* fields throws `INVALID_MODEL` (400) while inputs are built when the generated mutations reach
|
|
237
|
+
* its owner's create input. When the process's first Simfinity schema has an application type
|
|
238
|
+
* named `FieldExtensionsType` or `RelationType`, Simfinity renames its `__Field.extensions`
|
|
239
|
+
* metadata types `SimfinityFieldExtensionsType` and `SimfinityRelationType` (numbered when
|
|
240
|
+
* taken) for every later schema and logs a warning; once those names are fixed, a type with one
|
|
241
|
+
* of them throws `RESERVED_TYPE_NAME` (500), before `adapter.prepare()` when it is an included
|
|
242
|
+
* endpoint type, a registered mutation's input or output type, an output type they reach or a
|
|
243
|
+
* field argument's type, and when the schema is constructed otherwise, such as for a type inside
|
|
244
|
+
* an input object's fields. The check before `adapter.prepare()` never reads an input object's
|
|
245
|
+
* fields, so a registered input's `fields` function may call `getInputType()`.
|
|
221
246
|
*/
|
|
222
247
|
createSchema(includedQueryTypes?: GraphQLObjectType[] | null, includedMutationTypes?: GraphQLObjectType[] | null, includedCustomMutations?: string[] | null): GraphQLSchema;
|
|
223
248
|
getModel(type: GraphQLObjectType | { name: string }): Model | null | undefined;
|
|
224
249
|
getType(name: string | { name: string }): GraphQLObjectType | null | undefined;
|
|
225
|
-
/**
|
|
250
|
+
/**
|
|
251
|
+
* Available after createSchema has built input types. It has no fields for a type without
|
|
252
|
+
* writable fields; such inputs are not part of generated schemas.
|
|
253
|
+
*/
|
|
226
254
|
getInputType(type: GraphQLObjectType | { name: string }): GraphQLInputObjectType | undefined;
|
|
227
255
|
getRegistrations(): RuntimeRegistration<Model, Session>[];
|
|
228
256
|
/**
|
|
@@ -267,8 +295,31 @@ export interface DatabaseAdapter<Model = any, Session = any> {
|
|
|
267
295
|
* record renders as an object although the stored value is an explicit null; return any other
|
|
268
296
|
* value unchanged. It must depend only on the value: these resolvers read no data and do not bind
|
|
269
297
|
* their types, so a runtime that reaches a shared type may read through another runtime's hook.
|
|
298
|
+
* Simfinity then reads as null an object that holds no data when a non-null member would read as
|
|
299
|
+
* null, whatever the selection. These members do not count: `id`, readOnly members, interface and
|
|
300
|
+
* union members, members with their own resolver and referenced collections. An object whose type
|
|
301
|
+
* has no member that counts is returned untouched. Otherwise Simfinity reads the stored members
|
|
302
|
+
* (see `rawEmbeddedValue`), never calling a getter, and counts a stored `_id` as `id`; an error
|
|
303
|
+
* while reading them returns the object unchanged. Runtimes that share the type read through the
|
|
304
|
+
* same resolver, with or without the hook. On MongoDB, a create that writes an empty object for a
|
|
305
|
+
* required embedded member stores it as absent (Mongoose minimizes it), so an object that holds
|
|
306
|
+
* nothing else reads as null too, except in by-ID and reference reads and update responses where
|
|
307
|
+
* the member is a nested path, as generated models declare every embedded member except one named
|
|
308
|
+
* `type`.
|
|
270
309
|
*/
|
|
271
310
|
readEmbeddedValue?(value: any): any;
|
|
311
|
+
/**
|
|
312
|
+
* Optional, used with `readEmbeddedValue`. Returns the stored data of a hydrated embedded value
|
|
313
|
+
* as a plain object, without running getters or virtuals, such as a document's raw data; returns
|
|
314
|
+
* any other value unchanged. Return a hydrated value unchanged when its stored data does not show
|
|
315
|
+
* what it renders, such as one whose schema supplies members through getters, virtuals, methods
|
|
316
|
+
* or aliases: a value that is not a plain object counts as data, so Simfinity keeps it as it is.
|
|
317
|
+
* Simfinity calls it on the embedded objects it checks for data, including those it finds inside
|
|
318
|
+
* the returned data, and reads only own data properties of the result; a null or undefined result
|
|
319
|
+
* has no members. Without it, a plain object is read as it is, an accessor property counts as
|
|
320
|
+
* present without being called, and a value that is not a plain object counts as data.
|
|
321
|
+
*/
|
|
322
|
+
rawEmbeddedValue?(value: any): any;
|
|
272
323
|
getById(model: Model, id: any, session?: Session | null, options?: { projection?: Record<string, number>; plain?: boolean; lock?: boolean; requiredId?: any; context?: any }): any;
|
|
273
324
|
/** Optional batch read: the records found for `ids`, in getById shape and any order. After a failure, the runtime reads each ID with getById. */
|
|
274
325
|
getByIds?(model: Model, ids: any[], options?: { context?: any }): any;
|
|
@@ -326,10 +377,20 @@ export interface FieldValidations {
|
|
|
326
377
|
update: FieldValidator[];
|
|
327
378
|
}
|
|
328
379
|
|
|
329
|
-
/**
|
|
380
|
+
/**
|
|
381
|
+
* What `validators.arrayLength()` runs on each item: a validator, a helper result such as
|
|
382
|
+
* `validators.maxLength('Tag', 20)`, whose `CREATE` rules run on every item on create and update,
|
|
383
|
+
* or an array of them. Falsy array entries are skipped, so `[flag && rule]` works.
|
|
384
|
+
*/
|
|
385
|
+
export type ItemValidators =
|
|
386
|
+
| FieldValidator
|
|
387
|
+
| FieldValidations
|
|
388
|
+
| ReadonlyArray<FieldValidator | FieldValidations | null | undefined | false | '' | 0>;
|
|
389
|
+
|
|
390
|
+
/** Built-in field validator factories. A `null` or omitted bound means no bound. */
|
|
330
391
|
export const validators: {
|
|
331
|
-
stringLength(name: string, min?: number, max?: number): FieldValidations;
|
|
332
|
-
maxLength(name: string, max: number): FieldValidations;
|
|
392
|
+
stringLength(name: string, min?: number | null, max?: number | null): FieldValidations;
|
|
393
|
+
maxLength(name: string, max: number | null): FieldValidations;
|
|
333
394
|
/**
|
|
334
395
|
* Copies the pattern when the helper is created and tests each value from its first character,
|
|
335
396
|
* so `g` and `y` keep no state between values. Throws `TypeError` unless the pattern is a
|
|
@@ -338,10 +399,25 @@ export const validators: {
|
|
|
338
399
|
pattern(name: string, regex: RegExp | string, message?: string): FieldValidations;
|
|
339
400
|
email(): FieldValidations;
|
|
340
401
|
url(): FieldValidations;
|
|
341
|
-
numberRange(name: string, min?: number, max?: number): FieldValidations;
|
|
402
|
+
numberRange(name: string, min?: number | null, max?: number | null): FieldValidations;
|
|
342
403
|
positive(name: string): FieldValidations;
|
|
343
|
-
|
|
404
|
+
/**
|
|
405
|
+
* A falsy `itemValidator` adds no item checks. A single validator runs when it is a plain object or a
|
|
406
|
+
* function; a class instance with its own `validate()`, such as a Joi or yup schema, is ignored with a
|
|
407
|
+
* warning. Other unusable values log a `Configuration issue` warning when the helper is created.
|
|
408
|
+
*/
|
|
409
|
+
arrayLength(
|
|
410
|
+
name: string,
|
|
411
|
+
maxItems?: number | null,
|
|
412
|
+
itemValidator?: FieldValidator | FieldValidator[] | FieldValidations | ItemValidators | null | undefined | false | '' | 0,
|
|
413
|
+
): FieldValidations;
|
|
414
|
+
/**
|
|
415
|
+
* Values must be dates JavaScript can parse. Strings that start with an ISO date (`YYYY-MM-DD`), and
|
|
416
|
+
* slashed `MM/DD/YYYY` strings, must be real calendar dates, so `2024-02-31` and `02/31/2024` fail.
|
|
417
|
+
* Only the `'YYYY-MM-DD'` format is checked; any other format logs a warning when the helper is created.
|
|
418
|
+
*/
|
|
344
419
|
dateFormat(name: string, format?: string): FieldValidations;
|
|
420
|
+
/** Same date checks as `dateFormat()` without a format, plus the date must be in the future. */
|
|
345
421
|
futureDate(name: string): FieldValidations;
|
|
346
422
|
};
|
|
347
423
|
|
|
@@ -355,9 +431,12 @@ export const scalars: {
|
|
|
355
431
|
URLScalar: GraphQLScalarType;
|
|
356
432
|
PositiveIntScalar: GraphQLScalarType;
|
|
357
433
|
PositiveFloatScalar: GraphQLScalarType;
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
434
|
+
/** A `null` or omitted bound means no bound; the description names only the bounds that are set. */
|
|
435
|
+
createBoundedStringScalar(name: string, min?: number | null, max?: number | null): GraphQLScalarType;
|
|
436
|
+
/** A `null` or omitted bound means no bound; the description names only the bounds that are set. */
|
|
437
|
+
createBoundedIntScalar(name: string, min?: number | null, max?: number | null): GraphQLScalarType;
|
|
438
|
+
/** A `null` or omitted bound means no bound; the description names only the bounds that are set. */
|
|
439
|
+
createBoundedFloatScalar(name: string, min?: number | null, max?: number | null): GraphQLScalarType;
|
|
361
440
|
/** Same pattern rules as `validators.pattern`: a private copy, tested from the first character. */
|
|
362
441
|
createPatternStringScalar(name: string, pattern: RegExp | string, message?: string): GraphQLScalarType;
|
|
363
442
|
};
|
|
@@ -393,11 +472,19 @@ export interface AuthPluginOptions {
|
|
|
393
472
|
debug?: boolean;
|
|
394
473
|
}
|
|
395
474
|
|
|
396
|
-
|
|
475
|
+
/**
|
|
476
|
+
* Authentication error: code `UNAUTHENTICATED`, status 401, default message `Authentication required`.
|
|
477
|
+
* The same class as `auth.UnauthenticatedError` and the `/auth` and `/auth/errors` subpath exports.
|
|
478
|
+
*/
|
|
479
|
+
export class UnauthenticatedError extends SimfinityError {
|
|
397
480
|
constructor(message?: string);
|
|
398
481
|
}
|
|
399
482
|
|
|
400
|
-
|
|
483
|
+
/**
|
|
484
|
+
* Authorization error: code `FORBIDDEN`, status 403, default message `Access denied`.
|
|
485
|
+
* The same class as `auth.ForbiddenError` and the `/auth` and `/auth/errors` subpath exports.
|
|
486
|
+
*/
|
|
487
|
+
export class ForbiddenError extends SimfinityError {
|
|
401
488
|
constructor(message?: string);
|
|
402
489
|
}
|
|
403
490
|
|
|
@@ -429,14 +516,20 @@ export const auth: {
|
|
|
429
516
|
* thenable denies with TypeError.
|
|
430
517
|
*/
|
|
431
518
|
requireAuth(userPath?: string | ((ctx: any) => unknown)): AuthRuleFunction;
|
|
432
|
-
/**
|
|
519
|
+
/**
|
|
520
|
+
* Required roles must be nonempty strings; invalid configuration throws TypeError. The array,
|
|
521
|
+
* which may be readonly, is copied when the rule is created.
|
|
522
|
+
*/
|
|
433
523
|
requireRole(
|
|
434
|
-
role: string | string[],
|
|
524
|
+
role: string | readonly string[],
|
|
435
525
|
options?: { userPath?: string | ((ctx: any) => unknown); rolePath?: string | ((user: any) => unknown) },
|
|
436
526
|
): AuthRuleFunction;
|
|
437
|
-
/**
|
|
527
|
+
/**
|
|
528
|
+
* Exact array membership; only a standalone '*' claim grants all permissions. The array of
|
|
529
|
+
* required permissions, which may be readonly, is copied when the rule is created.
|
|
530
|
+
*/
|
|
438
531
|
requirePermission(
|
|
439
|
-
permission: string | string[],
|
|
532
|
+
permission: string | readonly string[],
|
|
440
533
|
options?: { userPath?: string | ((ctx: any) => unknown); permissionsPath?: string | ((user: any) => unknown) },
|
|
441
534
|
): AuthRuleFunction;
|
|
442
535
|
/** Requires at least one rule function; throws TypeError otherwise. */
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declarations for `@simtlix/simfinity-core/plugins`. The default export is the root `plugins`
|
|
3
|
+
* namespace, and every named export has the type of the same member, so the two cannot drift.
|
|
4
|
+
*/
|
|
5
|
+
import { plugins } from './index.js';
|
|
6
|
+
|
|
7
|
+
export type { AuthPluginOptions, EnvelopSchemaPlugin, PermissionSchema } from './index.js';
|
|
8
|
+
// The /auth declaration itself, as the runtime re-exports that binding, so the two subpaths can be
|
|
9
|
+
// re-exported together.
|
|
10
|
+
export { createAuthPlugin } from './auth/index.js';
|
|
11
|
+
export const apolloCountPlugin: typeof plugins.apolloCountPlugin;
|
|
12
|
+
export const envelopCountPlugin: typeof plugins.envelopCountPlugin;
|
|
13
|
+
|
|
14
|
+
export default plugins;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declarations for `@simtlix/simfinity-core/scalars`. The default export is the root `scalars`
|
|
3
|
+
* namespace, and every named export has the type of the same member, so the two cannot drift.
|
|
4
|
+
*/
|
|
5
|
+
import { scalars } from './index.js';
|
|
6
|
+
|
|
7
|
+
export const EmailScalar: typeof scalars.EmailScalar;
|
|
8
|
+
export const URLScalar: typeof scalars.URLScalar;
|
|
9
|
+
export const PositiveIntScalar: typeof scalars.PositiveIntScalar;
|
|
10
|
+
export const PositiveFloatScalar: typeof scalars.PositiveFloatScalar;
|
|
11
|
+
export const createBoundedStringScalar: typeof scalars.createBoundedStringScalar;
|
|
12
|
+
export const createBoundedIntScalar: typeof scalars.createBoundedIntScalar;
|
|
13
|
+
export const createBoundedFloatScalar: typeof scalars.createBoundedFloatScalar;
|
|
14
|
+
export const createPatternStringScalar: typeof scalars.createPatternStringScalar;
|
|
15
|
+
|
|
16
|
+
export default scalars;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declarations for `@simtlix/simfinity-core/validators`. The default export is the root
|
|
3
|
+
* `validators` namespace, and every named export has the type of the same member, so the two
|
|
4
|
+
* cannot drift. A root type used by these helpers belongs in the `export type` list below.
|
|
5
|
+
*/
|
|
6
|
+
import { validators } from './index.js';
|
|
7
|
+
|
|
8
|
+
export type { FieldValidations, FieldValidator, ItemValidators } from './index.js';
|
|
9
|
+
export const stringLength: typeof validators.stringLength;
|
|
10
|
+
export const maxLength: typeof validators.maxLength;
|
|
11
|
+
export const pattern: typeof validators.pattern;
|
|
12
|
+
export const email: typeof validators.email;
|
|
13
|
+
export const url: typeof validators.url;
|
|
14
|
+
export const numberRange: typeof validators.numberRange;
|
|
15
|
+
export const positive: typeof validators.positive;
|
|
16
|
+
export const arrayLength: typeof validators.arrayLength;
|
|
17
|
+
export const dateFormat: typeof validators.dateFormat;
|
|
18
|
+
export const futureDate: typeof validators.futureDate;
|
|
19
|
+
|
|
20
|
+
export default validators;
|