@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/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
- /** Available after createSchema has built input types. */
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
- /** Built-in field validator factories. */
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
- arrayLength(name: string, maxItems?: number, itemValidator?: FieldValidator[]): FieldValidations;
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
- createBoundedStringScalar(name: string, min?: number, max?: number): GraphQLScalarType;
359
- createBoundedIntScalar(name: string, min?: number, max?: number): GraphQLScalarType;
360
- createBoundedFloatScalar(name: string, min?: number, max?: number): GraphQLScalarType;
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
- declare class UnauthenticatedError extends SimfinityError {
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
- declare class ForbiddenError extends SimfinityError {
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
- /** Required roles must be nonempty strings; invalid configuration throws TypeError. */
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
- /** Exact array membership; only a standalone '*' claim grants all permissions. */
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;