lumen-framework 3.0.3 → 3.1.1
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/dist/cli.cjs +70 -38
- package/dist/cli.cjs.map +4 -4
- package/dist/index.js +928 -259
- package/dist/index.js.map +4 -4
- package/dist/index.mjs +919 -250
- package/dist/index.mjs.map +4 -4
- package/dist/types/errors/namespaced-serializer-missing-error.d.ts +15 -0
- package/dist/types/packages/application/utils/validate-namespaced-serializers.d.ts +15 -0
- package/dist/types/packages/controller/errors/index.d.ts +1 -0
- package/dist/types/packages/controller/errors/related-record-not-found-error.d.ts +14 -0
- package/dist/types/packages/controller/index.d.ts +65 -0
- package/dist/types/packages/controller/utils/find-many.d.ts +2 -1
- package/dist/types/packages/controller/utils/find-one.d.ts +2 -1
- package/dist/types/packages/controller/utils/params-to-query.d.ts +7 -2
- package/dist/types/packages/controller/utils/validate-relationships.d.ts +8 -0
- package/dist/types/packages/database/constants.d.ts +1 -0
- package/dist/types/packages/database/model/index.d.ts +11 -0
- package/dist/types/packages/database/model/utils/process-write-error.d.ts +9 -1
- package/dist/types/packages/database/validation/errors/validation-error.d.ts +11 -2
- package/dist/types/packages/jsonapi/interfaces.d.ts +1 -1
- package/dist/types/packages/router/route/params/errors/client-generated-id-error.d.ts +13 -0
- package/dist/types/packages/router/route/params/errors/forbidden-parameter-error.d.ts +14 -0
- package/dist/types/packages/router/route/params/errors/index.d.ts +2 -0
- package/dist/types/packages/router/route/params/errors/invalid-parameter-error.d.ts +2 -0
- package/dist/types/packages/router/route/params/errors/parameter-not-nullable-error.d.ts +2 -0
- package/dist/types/packages/router/route/params/errors/parameter-required-error.d.ts +2 -0
- package/dist/types/packages/router/route/params/errors/parameter-type-error.d.ts +2 -0
- package/dist/types/packages/router/route/params/errors/parameter-value-error.d.ts +2 -0
- package/dist/types/packages/router/route/params/errors/resource-mismatch-error.d.ts +2 -0
- package/dist/types/packages/router/route/params/index.d.ts +1 -0
- package/dist/types/packages/router/route/params/parameter/forbidden-parameter.d.ts +12 -0
- package/dist/types/packages/router/route/params/parameter/index.d.ts +8 -0
- package/dist/types/packages/router/route/params/utils/validate-client-id.d.ts +8 -0
- package/dist/types/packages/serializer/index.d.ts +111 -36
- package/dist/types/packages/serializer/utils/include-tree.d.ts +29 -0
- package/dist/types/packages/serializer/utils/load-linkage.d.ts +22 -0
- package/dist/types/packages/server/index.d.ts +2 -1
- package/dist/types/packages/server/interfaces.d.ts +5 -0
- package/dist/types/packages/server/utils/source-for.d.ts +10 -0
- package/package.json +1 -1
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown at boot when a namespace that opted out of serializer fallback
|
|
3
|
+
* (`serializerFallback = false` on its ApplicationController) can reach a type
|
|
4
|
+
* that has no Serializer in that namespace.
|
|
5
|
+
*
|
|
6
|
+
* @private
|
|
7
|
+
*/
|
|
8
|
+
declare class NamespacedSerializerMissingError extends ReferenceError {
|
|
9
|
+
/**
|
|
10
|
+
* @param missing - Each missing serializer key (`admin/comments`) with an
|
|
11
|
+
* example of how it is reached (`admin/posts?include=comments`).
|
|
12
|
+
*/
|
|
13
|
+
constructor(missing: Map<string, string>);
|
|
14
|
+
}
|
|
15
|
+
export default NamespacedSerializerMissingError;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type Controller from '../../controller';
|
|
2
|
+
import type Serializer from '../../serializer';
|
|
3
|
+
import type { Model } from '../../database';
|
|
4
|
+
import type { Bundle$Namespace } from '../../loader';
|
|
5
|
+
/**
|
|
6
|
+
* Enforce `serializerFallback = false`: for every namespace whose
|
|
7
|
+
* ApplicationController sets it, each type its controllers can serialize — the
|
|
8
|
+
* resource itself, and everything reachable through `include` (and so
|
|
9
|
+
* `fields`) down to the controller's `maxIncludeDepth` — must have a
|
|
10
|
+
* Serializer in exactly that namespace. Throws listing every gap, so a missing
|
|
11
|
+
* serializer fails the boot instead of silently falling back to the root one.
|
|
12
|
+
*
|
|
13
|
+
* @private
|
|
14
|
+
*/
|
|
15
|
+
export default function validateNamespacedSerializers(controllers: Bundle$Namespace<Controller> | Map<string, Controller>, serializers: Bundle$Namespace<Serializer<Model>> | Map<string, Serializer<Model>>): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as RelatedRecordNotFoundError } from './related-record-not-found-error';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ModelClass } from '../../database';
|
|
2
|
+
import type { Server$ErrorSource } from '../../server';
|
|
3
|
+
/**
|
|
4
|
+
* JSON:API 1.0: "A server MUST return 404 Not Found when processing a request
|
|
5
|
+
* that references a related resource that does not exist."
|
|
6
|
+
*
|
|
7
|
+
* @private
|
|
8
|
+
*/
|
|
9
|
+
declare class RelatedRecordNotFoundError extends Error {
|
|
10
|
+
source: Server$ErrorSource;
|
|
11
|
+
constructor({ name, primaryKey }: ModelClass, primaryKeyValue: unknown, path: string);
|
|
12
|
+
}
|
|
13
|
+
declare const _default: new (...args: Array<any>) => RelatedRecordNotFoundError & import("../../server/interfaces").Server$Error;
|
|
14
|
+
export default _default;
|
|
@@ -442,6 +442,71 @@ declare class Controller {
|
|
|
442
442
|
* @public
|
|
443
443
|
*/
|
|
444
444
|
defaultPerPage: number;
|
|
445
|
+
/**
|
|
446
|
+
* How many relationships deep an `?include` path may go on this
|
|
447
|
+
* controller's routes. `comments.reactions.user` is 3 levels deep; with `1`
|
|
448
|
+
* only direct relationships (`comments`) can be included. Paths deeper than
|
|
449
|
+
* this are rejected with `400 Bad Request`.
|
|
450
|
+
*
|
|
451
|
+
* Set it on `ApplicationController` to change it for the whole app, or on a
|
|
452
|
+
* single controller to override it there.
|
|
453
|
+
*
|
|
454
|
+
* ```javascript
|
|
455
|
+
* class ApplicationController extends Controller {
|
|
456
|
+
* maxIncludeDepth = 2;
|
|
457
|
+
* }
|
|
458
|
+
* ```
|
|
459
|
+
*
|
|
460
|
+
* Every allowed path is enumerated up front from the serializers'
|
|
461
|
+
* relationships, and each nested level costs its own queries per request, so
|
|
462
|
+
* keep this small.
|
|
463
|
+
*
|
|
464
|
+
* @property maxIncludeDepth
|
|
465
|
+
* @type {Number}
|
|
466
|
+
* @default 3
|
|
467
|
+
* @public
|
|
468
|
+
*/
|
|
469
|
+
maxIncludeDepth: number;
|
|
470
|
+
/**
|
|
471
|
+
* Whether a namespace may fall back to the root Serializer of a type it has
|
|
472
|
+
* no Serializer for. Read from a namespace's `ApplicationController` and
|
|
473
|
+
* applies to the whole namespace.
|
|
474
|
+
*
|
|
475
|
+
* By default `app/controllers/admin/comments.js` without an
|
|
476
|
+
* `app/serializers/admin/comments.js` — or an included type without one —
|
|
477
|
+
* is serialized by the root Serializer, with every attribute and
|
|
478
|
+
* relationship it declares. For a namespace that must only expose what it
|
|
479
|
+
* declares itself, turn the fallback off:
|
|
480
|
+
*
|
|
481
|
+
* ```javascript
|
|
482
|
+
* // app/controllers/admin/application.js
|
|
483
|
+
* class AdminApplicationController extends ApplicationController {
|
|
484
|
+
* serializerFallback = false;
|
|
485
|
+
* }
|
|
486
|
+
* ```
|
|
487
|
+
*
|
|
488
|
+
* The application then refuses to boot while any type the namespace can
|
|
489
|
+
* serialize or `include` (down to each controller's `maxIncludeDepth`) has
|
|
490
|
+
* no Serializer in that namespace, listing each missing one.
|
|
491
|
+
*
|
|
492
|
+
* @property serializerFallback
|
|
493
|
+
* @type {Boolean}
|
|
494
|
+
* @default true
|
|
495
|
+
* @public
|
|
496
|
+
*/
|
|
497
|
+
serializerFallback: boolean;
|
|
498
|
+
/**
|
|
499
|
+
* The Serializer to serialize (and validate, and load) related resources of
|
|
500
|
+
* this Controller's responses with: the related model's Serializer in this
|
|
501
|
+
* Controller's namespace, falling back to the root one.
|
|
502
|
+
*
|
|
503
|
+
* Always this Controller's namespace — not its Serializer's, which is the
|
|
504
|
+
* root one when the namespace has no Serializer for this resource.
|
|
505
|
+
*
|
|
506
|
+
* @method serializerFor
|
|
507
|
+
* @private
|
|
508
|
+
*/
|
|
509
|
+
serializerFor(model: ModelClass): Serializer<Model>;
|
|
445
510
|
/**
|
|
446
511
|
* The resolved Model for a Controller instance.
|
|
447
512
|
*
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Model, ModelClass, Query } from '../../database';
|
|
2
|
+
import type Serializer from '../../serializer';
|
|
2
3
|
import type { Request } from '../../server';
|
|
3
4
|
/**
|
|
4
5
|
* @private
|
|
5
6
|
*/
|
|
6
|
-
export default function findMany<T extends Model>(model: ModelClass<T>, req: Request): Query<Array<Model>>;
|
|
7
|
+
export default function findMany<T extends Model>(model: ModelClass<T>, req: Request, serializerFor?: (model: ModelClass) => Serializer<Model>): Query<Array<Model>>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Model, ModelClass, Query } from '../../database';
|
|
2
|
+
import type Serializer from '../../serializer';
|
|
2
3
|
import type { Request } from '../../server';
|
|
3
4
|
/**
|
|
4
5
|
* @private
|
|
5
6
|
*/
|
|
6
|
-
export default function findOne<T extends Model>(model: ModelClass<T>, req: Request): Query<T>;
|
|
7
|
+
export default function findOne<T extends Model>(model: ModelClass<T>, req: Request, serializerFor?: (model: ModelClass) => Serializer<Model>): Query<T>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { ModelClass } from '../../database';
|
|
1
|
+
import type { Model, ModelClass } from '../../database';
|
|
2
|
+
import type Serializer from '../../serializer';
|
|
2
3
|
import type { Request$params } from '../../server';
|
|
3
4
|
type Controller$query = {
|
|
4
5
|
id?: number | string | Buffer;
|
|
@@ -10,7 +11,11 @@ type Controller$query = {
|
|
|
10
11
|
include: Record<string, Array<string>>;
|
|
11
12
|
};
|
|
12
13
|
/**
|
|
14
|
+
* `serializerFor` resolves the Serializer an included resource is serialized
|
|
15
|
+
* with — in the request's namespace (`Controller#serializerFor()`) — so its
|
|
16
|
+
* attributes are the ones loaded. Defaults to the related model's root one.
|
|
17
|
+
*
|
|
13
18
|
* @private
|
|
14
19
|
*/
|
|
15
|
-
export default function paramsToQuery(model: ModelClass, { id, page, sort, filter, fields, include }: Request$params): Controller$query;
|
|
20
|
+
export default function paramsToQuery(model: ModelClass, { id, page, sort, filter, fields, include }: Request$params, serializerFor?: (related: ModelClass) => Serializer<Model>): Controller$query;
|
|
16
21
|
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Model, ModelClass } from '../../database';
|
|
2
|
+
/**
|
|
3
|
+
* Check that every resource referenced from `data.relationships` exists, so a
|
|
4
|
+
* write cannot leave dangling linkage. One query per relationship.
|
|
5
|
+
*
|
|
6
|
+
* @private
|
|
7
|
+
*/
|
|
8
|
+
export default function validateRelationships<T extends Model>(model: ModelClass<T>, relationships?: Record<string, unknown>): Promise<void>;
|
|
@@ -78,6 +78,17 @@ declare class Model {
|
|
|
78
78
|
* @private
|
|
79
79
|
*/
|
|
80
80
|
prevAssociations: Set<Model>;
|
|
81
|
+
/**
|
|
82
|
+
* Names of `hasOne` relationships that were eager-loaded (joined) and found
|
|
83
|
+
* to have no related record. Lets the relationship getter answer `null`
|
|
84
|
+
* without a per-record query. Kept outside of the change sets so it never
|
|
85
|
+
* counts as a change to the record.
|
|
86
|
+
*
|
|
87
|
+
* @property absentRelationships
|
|
88
|
+
* @type {Set}
|
|
89
|
+
* @private
|
|
90
|
+
*/
|
|
91
|
+
absentRelationships: Set<string>;
|
|
81
92
|
/**
|
|
82
93
|
* @property changeSets
|
|
83
94
|
* @type {Array}
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* Map a database write error to the server error it should surface as.
|
|
3
|
+
*
|
|
2
4
|
* @private
|
|
3
5
|
*/
|
|
4
|
-
export default function
|
|
6
|
+
export default function processWriteError(err: unknown): unknown;
|
|
7
|
+
/**
|
|
8
|
+
* `.catch()` handler for a write: rethrows the mapped error.
|
|
9
|
+
*
|
|
10
|
+
* @private
|
|
11
|
+
*/
|
|
12
|
+
export declare function rethrowWriteError(err: unknown): never;
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
+
import type { Server$ErrorSource } from '../../../server';
|
|
1
2
|
/**
|
|
3
|
+
* A model validator (`static validates`) rejected an attribute. Answered with
|
|
4
|
+
* 422 and a pointer to the attribute, which clients such as ember-data map to
|
|
5
|
+
* field errors. The rejected value is deliberately not in the message: it
|
|
6
|
+
* ends up in logs and may be a secret (e.g. a password).
|
|
7
|
+
*
|
|
2
8
|
* @private
|
|
3
9
|
*/
|
|
4
10
|
declare class ValidationError extends Error {
|
|
5
|
-
|
|
11
|
+
key: string;
|
|
12
|
+
source: Server$ErrorSource;
|
|
13
|
+
constructor(key: string);
|
|
6
14
|
}
|
|
7
|
-
|
|
15
|
+
declare const _default: new (...args: Array<any>) => ValidationError & import("../../../server/interfaces").Server$Error;
|
|
16
|
+
export default _default;
|
|
@@ -28,7 +28,7 @@ export interface JSONAPI$ResourceObject {
|
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
export interface JSONAPI$RelationshipObject {
|
|
31
|
-
data: JSONAPI$IdentifierObject;
|
|
31
|
+
data: JSONAPI$IdentifierObject | Array<JSONAPI$IdentifierObject> | null;
|
|
32
32
|
meta?: JSONAPI$BaseObject;
|
|
33
33
|
links?: JSONAPI$ResourceLinksObject;
|
|
34
34
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Server$ErrorSource } from '../../../../server';
|
|
2
|
+
/**
|
|
3
|
+
* JSON:API 1.0: "A server MUST return 403 Forbidden in response to an
|
|
4
|
+
* unsupported request to create a resource with a client-generated ID."
|
|
5
|
+
*
|
|
6
|
+
* @private
|
|
7
|
+
*/
|
|
8
|
+
declare class ClientGeneratedIdError extends TypeError {
|
|
9
|
+
source: Server$ErrorSource;
|
|
10
|
+
constructor();
|
|
11
|
+
}
|
|
12
|
+
declare const _default: new (...args: Array<any>) => ClientGeneratedIdError & import("../../../../server/interfaces").Server$Error;
|
|
13
|
+
export default _default;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Server$ErrorSource } from '../../../../server';
|
|
2
|
+
/**
|
|
3
|
+
* JSON:API 1.0: "A server MUST return 403 Forbidden in response to an
|
|
4
|
+
* unsupported request to update a resource or relationship." Used for members
|
|
5
|
+
* the model knows about but the controller does not accept (`params`).
|
|
6
|
+
*
|
|
7
|
+
* @private
|
|
8
|
+
*/
|
|
9
|
+
declare class ForbiddenParameterError extends TypeError {
|
|
10
|
+
source: Server$ErrorSource;
|
|
11
|
+
constructor(path: string);
|
|
12
|
+
}
|
|
13
|
+
declare const _default: new (...args: Array<any>) => ForbiddenParameterError & import("../../../../server/interfaces").Server$Error;
|
|
14
|
+
export default _default;
|
|
@@ -3,3 +3,5 @@ export { default as ParameterValueError } from './parameter-value-error';
|
|
|
3
3
|
export { default as InvalidParameterError } from './invalid-parameter-error';
|
|
4
4
|
export { default as ResourceMismatchError } from './resource-mismatch-error';
|
|
5
5
|
export { default as ParameterRequiredError } from './parameter-required-error';
|
|
6
|
+
export { default as ClientGeneratedIdError } from './client-generated-id-error';
|
|
7
|
+
export { default as ForbiddenParameterError } from './forbidden-parameter-error';
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import type { Server$ErrorSource } from '../../../../server';
|
|
1
2
|
/**
|
|
2
3
|
* @private
|
|
3
4
|
*/
|
|
4
5
|
declare class InvalidParameterError extends TypeError {
|
|
6
|
+
source: Server$ErrorSource;
|
|
5
7
|
constructor(path: string);
|
|
6
8
|
}
|
|
7
9
|
declare const _default: new (...args: Array<any>) => InvalidParameterError & import("../../../../server/interfaces").Server$Error;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import type { Server$ErrorSource } from '../../../../server';
|
|
1
2
|
import type { ParameterLike } from '../index';
|
|
2
3
|
/**
|
|
3
4
|
* @private
|
|
4
5
|
*/
|
|
5
6
|
declare class ParameterNotNullableError extends TypeError {
|
|
7
|
+
source: Server$ErrorSource;
|
|
6
8
|
constructor({ path }: ParameterLike);
|
|
7
9
|
}
|
|
8
10
|
declare const _default: new (...args: Array<any>) => ParameterNotNullableError & import("../../../../server/interfaces").Server$Error;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import type { Server$ErrorSource } from '../../../../server';
|
|
1
2
|
/**
|
|
2
3
|
* @private
|
|
3
4
|
*/
|
|
4
5
|
declare class ParameterRequiredError extends TypeError {
|
|
6
|
+
source: Server$ErrorSource;
|
|
5
7
|
constructor(path: string);
|
|
6
8
|
}
|
|
7
9
|
declare const _default: new (...args: Array<any>) => ParameterRequiredError & import("../../../../server/interfaces").Server$Error;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import type { Server$ErrorSource } from '../../../../server';
|
|
1
2
|
import type { ParameterLike } from '../index';
|
|
2
3
|
/**
|
|
3
4
|
* @private
|
|
4
5
|
*/
|
|
5
6
|
declare class ParameterTypeError extends TypeError {
|
|
7
|
+
source: Server$ErrorSource;
|
|
6
8
|
constructor(param: ParameterLike, actual: string);
|
|
7
9
|
}
|
|
8
10
|
declare const _default: new (...args: Array<any>) => ParameterTypeError & import("../../../../server/interfaces").Server$Error;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import type { Server$ErrorSource } from '../../../../server';
|
|
1
2
|
import type { ParameterLike } from '../index';
|
|
2
3
|
/**
|
|
3
4
|
* @private
|
|
4
5
|
*/
|
|
5
6
|
declare class ParameterValueError extends TypeError {
|
|
7
|
+
source: Server$ErrorSource;
|
|
6
8
|
constructor(param: ParameterLike, actual: unknown);
|
|
7
9
|
}
|
|
8
10
|
declare const _default: new (...args: Array<any>) => ParameterValueError & import("../../../../server/interfaces").Server$Error;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import type { Server$ErrorSource } from '../../../../server';
|
|
1
2
|
/**
|
|
2
3
|
* @private
|
|
3
4
|
*/
|
|
4
5
|
declare class ResourceMismatchError extends TypeError {
|
|
6
|
+
source: Server$ErrorSource;
|
|
5
7
|
constructor(path: string, expected: unknown, actual: unknown);
|
|
6
8
|
}
|
|
7
9
|
declare const _default: new (...args: Array<any>) => ResourceMismatchError & import("../../../../server/interfaces").Server$Error;
|
|
@@ -12,6 +12,7 @@ export declare function defaultParamsFor({ type, controller }: {
|
|
|
12
12
|
type: string;
|
|
13
13
|
controller: Controller;
|
|
14
14
|
}): Record<string, unknown>;
|
|
15
|
+
export { default as validateClientId } from './utils/validate-client-id';
|
|
15
16
|
export { default as validateResourceId } from './utils/validate-resource-id';
|
|
16
17
|
export type { ParameterLike, ParameterLike$opts } from './interfaces';
|
|
17
18
|
export type { default as Parameter } from './parameter';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import Parameter from './index';
|
|
2
|
+
/**
|
|
3
|
+
* A member the resource has but the controller does not accept. Any value for
|
|
4
|
+
* it is rejected with 403 rather than the 400 an unknown member gets.
|
|
5
|
+
*
|
|
6
|
+
* @private
|
|
7
|
+
*/
|
|
8
|
+
declare class ForbiddenParameter extends Parameter {
|
|
9
|
+
constructor(path: string);
|
|
10
|
+
validate<V>(): V;
|
|
11
|
+
}
|
|
12
|
+
export default ForbiddenParameter;
|
|
@@ -8,6 +8,14 @@ declare class Parameter extends FreezeableSet<unknown> {
|
|
|
8
8
|
type: string;
|
|
9
9
|
required: boolean;
|
|
10
10
|
sanitize: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Whether the parameter only accepts the given `values`. A parameter built
|
|
13
|
+
* without `values` accepts any value of its type; one built with `values`
|
|
14
|
+
* accepts only those — so an empty list accepts nothing. (Both used to look
|
|
15
|
+
* alike as an empty set, which let e.g. `?include=anything` through on a
|
|
16
|
+
* serializer without relationships, where JSON:API requires a 400.)
|
|
17
|
+
*/
|
|
18
|
+
restricted: boolean;
|
|
11
19
|
constructor({ path, type, values, required, sanitize }: Parameter$opts);
|
|
12
20
|
validate<V>(value: V): V;
|
|
13
21
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reject `data.id` on a create request before the parameter tree runs, so it
|
|
3
|
+
* is answered with 403 (unsupported client-generated ID) rather than the 400
|
|
4
|
+
* an unknown member gets.
|
|
5
|
+
*
|
|
6
|
+
* @private
|
|
7
|
+
*/
|
|
8
|
+
export default function validateClientId(params: Record<string, unknown>): boolean;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import type { Bundle$Namespace } from '../loader';
|
|
1
2
|
import type { Model, ModelClass } from '../database';
|
|
2
3
|
import type { JSONAPI$Document, JSONAPI$DocumentLinks, JSONAPI$ResourceObject, JSONAPI$RelationshipObject } from '../jsonapi';
|
|
3
4
|
import type { Serializer$opts } from './interfaces';
|
|
5
|
+
import type { Linkage } from './utils/load-linkage';
|
|
6
|
+
import type { IncludeTree } from './utils/include-tree';
|
|
4
7
|
/**
|
|
5
8
|
* ## Overview
|
|
6
9
|
*
|
|
@@ -155,6 +158,17 @@ import type { Serializer$opts } from './interfaces';
|
|
|
155
158
|
* If we request that the `posts` association is included from the `/users`
|
|
156
159
|
* endpoint, we will only get the `attributes` that the `PostsSerializer` has
|
|
157
160
|
* defined even though the response is processed by the `UsersSerializer`.
|
|
161
|
+
* The same goes for relationships: each included resource carries the
|
|
162
|
+
* `relationships` its own Serializer declares in `hasOne` and `hasMany`.
|
|
163
|
+
*
|
|
164
|
+
* Included resources follow the request's namespace: from `/admin/posts`,
|
|
165
|
+
* included comments are serialized by `AdminCommentsSerializer` when it
|
|
166
|
+
* exists and by `CommentsSerializer` otherwise (the same fallback a
|
|
167
|
+
* namespaced Controller uses), and their links point into `/admin`.
|
|
168
|
+
*
|
|
169
|
+
* Relationship paths may be nested, e.g. `/posts?include=comments.user`, up
|
|
170
|
+
* to the controller's `maxIncludeDepth` (3 by default). The intermediate
|
|
171
|
+
* resources (the comments) are included along with the leaves (their users).
|
|
158
172
|
*
|
|
159
173
|
* #### Sparse Fieldsets
|
|
160
174
|
*
|
|
@@ -401,6 +415,17 @@ declare class Serializer<T extends Model> {
|
|
|
401
415
|
* @private
|
|
402
416
|
*/
|
|
403
417
|
namespace: string;
|
|
418
|
+
/**
|
|
419
|
+
* Every Serializer of the application, keyed by namespaced path (`posts`,
|
|
420
|
+
* `admin/posts`). Attached once all of them are built, and used by
|
|
421
|
+
* `serializerFor()` to serialize related resources in this Serializer's
|
|
422
|
+
* namespace.
|
|
423
|
+
*
|
|
424
|
+
* @property serializers
|
|
425
|
+
* @type {Map}
|
|
426
|
+
* @private
|
|
427
|
+
*/
|
|
428
|
+
serializers?: Bundle$Namespace<Serializer<Model>>;
|
|
404
429
|
constructor({ model, parent, namespace }: Serializer$opts<T>);
|
|
405
430
|
/**
|
|
406
431
|
* Transform an array of Model instances or a single Model instance into a
|
|
@@ -423,25 +448,40 @@ declare class Serializer<T extends Model> {
|
|
|
423
448
|
* the resource and relationship objects in the returned [JSON API](
|
|
424
449
|
* http://jsonapi.org) document object.
|
|
425
450
|
*
|
|
426
|
-
* @param {Array} options.include - An array of
|
|
427
|
-
*
|
|
428
|
-
* the returned [JSON API](http://jsonapi.org)
|
|
451
|
+
* @param {Array} options.include - An array of relationship paths (e.g.
|
|
452
|
+
* `'comments'` or `'comments.user'`) whose resources should be added to the
|
|
453
|
+
* top level included object of the returned [JSON API](http://jsonapi.org)
|
|
454
|
+
* document object. Intermediate resources of a nested path are included too.
|
|
455
|
+
*
|
|
456
|
+
* @param {String} options.namespace - The namespace of the request, i.e. of
|
|
457
|
+
* the Controller handling it. Every link in the document is built in it, and
|
|
458
|
+
* included resources are serialized by their Serializer in it (falling back
|
|
459
|
+
* to the root). Defaults to this Serializer's namespace — which is the root
|
|
460
|
+
* one when a namespaced Controller has no Serializer of its own, so the
|
|
461
|
+
* Controller passes its namespace explicitly.
|
|
429
462
|
*
|
|
430
463
|
* @return {Promise} Resolves with a [JSON API](http://jsonapi.org) document
|
|
431
464
|
* object.
|
|
432
465
|
*
|
|
433
466
|
* @private
|
|
434
467
|
*/
|
|
435
|
-
format({ data, links, domain, include }: {
|
|
468
|
+
format({ data, links, domain, include, namespace }: {
|
|
436
469
|
data: T | Array<T>;
|
|
437
470
|
links: JSONAPI$DocumentLinks;
|
|
438
471
|
domain: string;
|
|
439
472
|
include: Array<string>;
|
|
473
|
+
namespace?: string;
|
|
440
474
|
}): Promise<JSONAPI$Document>;
|
|
441
475
|
/**
|
|
442
476
|
* Transform a single Model instance into a [JSON API](http://jsonapi.org)
|
|
443
477
|
* resource object.
|
|
444
478
|
*
|
|
479
|
+
* Relationships are serialized in one of two ways. By default each one is
|
|
480
|
+
* read from the Model instance (for primary data the query has already
|
|
481
|
+
* loaded them). When `linkage` is given — as it is for included resources,
|
|
482
|
+
* whose relationships are batch-loaded by `addIncluded()` — the resource
|
|
483
|
+
* linkage is built from it instead, without touching the database.
|
|
484
|
+
*
|
|
445
485
|
* @method formatOne
|
|
446
486
|
*
|
|
447
487
|
* @param {Object} options - An options object used for building the returned
|
|
@@ -458,30 +498,33 @@ declare class Serializer<T extends Model> {
|
|
|
458
498
|
* the top level links object or relationship links objects in the returned
|
|
459
499
|
* [JSON API](http://jsonapi.org) resource object.
|
|
460
500
|
*
|
|
461
|
-
* @param {Array} options.include - An array of
|
|
462
|
-
*
|
|
463
|
-
* a [JSON API](http://jsonapi.org) document object.
|
|
501
|
+
* @param {Array} options.include - An array of the relationship keys whose
|
|
502
|
+
* related records should be collected into `options.related`.
|
|
464
503
|
*
|
|
465
|
-
* @param {
|
|
466
|
-
*
|
|
467
|
-
* included
|
|
504
|
+
* @param {Map} options.related - Collects, per relationship key in
|
|
505
|
+
* `options.include`, the related Model instances that belong in the top
|
|
506
|
+
* level included object of a [JSON API](http://jsonapi.org) document object.
|
|
468
507
|
*
|
|
469
|
-
* @param {
|
|
470
|
-
*
|
|
471
|
-
*
|
|
508
|
+
* @param {Object} options.linkage - Pre-loaded resource linkage (related
|
|
509
|
+
* primary keys per relationship key) to serialize relationships from.
|
|
510
|
+
*
|
|
511
|
+
* @param {String} options.namespace - The namespace to build links in.
|
|
512
|
+
* Defaults to this Serializer's; included resources pass the namespace of
|
|
513
|
+
* the request, so every link in a document points into the same namespace.
|
|
472
514
|
*
|
|
473
515
|
* @return {Promise} Resolves with a [JSON API](http://jsonapi.org) resource
|
|
474
516
|
* object.
|
|
475
517
|
*
|
|
476
518
|
* @private
|
|
477
519
|
*/
|
|
478
|
-
formatOne({ item, links, domain, include,
|
|
520
|
+
formatOne({ item, links, domain, include, related, linkage, namespace }: {
|
|
479
521
|
item: T;
|
|
480
522
|
links?: boolean;
|
|
481
523
|
domain: string;
|
|
482
|
-
include
|
|
483
|
-
|
|
484
|
-
|
|
524
|
+
include?: Array<string>;
|
|
525
|
+
related?: Map<string, Array<Model>>;
|
|
526
|
+
linkage?: Linkage;
|
|
527
|
+
namespace?: string;
|
|
485
528
|
}): Promise<JSONAPI$ResourceObject>;
|
|
486
529
|
/**
|
|
487
530
|
* Transform a single Model instance into a [JSON API](http://jsonapi.org)
|
|
@@ -489,33 +532,65 @@ declare class Serializer<T extends Model> {
|
|
|
489
532
|
*
|
|
490
533
|
* @method formatRelationship
|
|
491
534
|
*
|
|
492
|
-
* @param {
|
|
535
|
+
* @param {Model} item - The Model instance to transform into the returned
|
|
493
536
|
* [JSON API](http://jsonapi.org) relationship object.
|
|
494
537
|
*
|
|
495
|
-
* @param {
|
|
538
|
+
* @param {String} domain - A string used to build links included in the
|
|
496
539
|
* returned [JSON API](http://jsonapi.org) relationship object.
|
|
497
540
|
*
|
|
498
|
-
* @
|
|
499
|
-
* the returned [JSON API](http://jsonapi.org) relationship object.
|
|
500
|
-
*
|
|
501
|
-
* @param {Array} options.include - An array of strings containing the
|
|
502
|
-
* relationship keys that should be added to the top level included object of
|
|
503
|
-
* a [JSON API](http://jsonapi.org) document object.
|
|
541
|
+
* @return {Object} A [JSON API](http://jsonapi.org) relationship object.
|
|
504
542
|
*
|
|
505
|
-
* @
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
*
|
|
510
|
-
*
|
|
543
|
+
* @private
|
|
544
|
+
*/
|
|
545
|
+
formatRelationship(item: Model, domain: string, namespace?: string): JSONAPI$RelationshipObject;
|
|
546
|
+
/**
|
|
547
|
+
* Build a [JSON API](http://jsonapi.org) relationship object from resource
|
|
548
|
+
* linkage, in the same shape `formatRelationship()` produces from Model
|
|
549
|
+
* instances: to-one relationships carry a `links` object, to-many ones only
|
|
550
|
+
* `data`, and a missing to-one relationship is `{ data: null }`.
|
|
511
551
|
*
|
|
552
|
+
* @method formatLinkage
|
|
553
|
+
* @private
|
|
554
|
+
*/
|
|
555
|
+
formatLinkage(domain: string, type: string | undefined, linkage: Array<string> | string | null | undefined, namespace?: string): JSONAPI$RelationshipObject;
|
|
556
|
+
/**
|
|
557
|
+
* Add `records` (instances of `model`) to `included` as resource objects,
|
|
558
|
+
* then recurse into the relationships named in `tree`. Each is serialized by
|
|
559
|
+
* `model`'s Serializer in this Serializer's namespace (`serializerFor()`), so
|
|
560
|
+
* `/admin/posts?include=comments` uses `AdminCommentsSerializer` when there
|
|
561
|
+
* is one and `CommentsSerializer` otherwise. The relationships of every level
|
|
562
|
+
* are batch-loaded with one query per relationship, not one per record.
|
|
563
|
+
*
|
|
564
|
+
* @method addIncluded
|
|
512
565
|
* @private
|
|
513
566
|
*/
|
|
514
|
-
|
|
515
|
-
|
|
567
|
+
addIncluded({ model, records, tree, domain, included, namespace }: {
|
|
568
|
+
model: ModelClass;
|
|
569
|
+
records: Array<Model>;
|
|
570
|
+
tree: IncludeTree;
|
|
516
571
|
domain: string;
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
}): Promise<
|
|
572
|
+
included: Map<string, JSONAPI$ResourceObject>;
|
|
573
|
+
namespace: string;
|
|
574
|
+
}): Promise<void>;
|
|
575
|
+
/**
|
|
576
|
+
* Resolve the Serializer for `model` in `namespace` (this Serializer's by
|
|
577
|
+
* default), the way a namespaced Controller resolves its own:
|
|
578
|
+
* `admin/comments` if it exists, otherwise the closest ancestor namespace's,
|
|
579
|
+
* down to the root `comments` Serializer. Falls back to `model.serializer`
|
|
580
|
+
* when this Serializer was not created by an application (e.g. in
|
|
581
|
+
* isolation).
|
|
582
|
+
*
|
|
583
|
+
* Pass the request's namespace when there is one: a Serializer's own
|
|
584
|
+
* namespace is the root one whenever it is a namespaced Controller's
|
|
585
|
+
* fallback.
|
|
586
|
+
*
|
|
587
|
+
* @method serializerFor
|
|
588
|
+
* @private
|
|
589
|
+
*/
|
|
590
|
+
serializerFor(model: ModelClass, namespace?: string): Serializer<Model>;
|
|
591
|
+
/**
|
|
592
|
+
* @private
|
|
593
|
+
*/
|
|
594
|
+
linkFor(domain: string, type: string, id: string, namespace?: string): string;
|
|
520
595
|
}
|
|
521
596
|
export default Serializer;
|