@stone-js/resources 0.8.9 → 0.8.10
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/ContractChecker.d.ts +96 -0
- package/dist/Resource.d.ts +96 -28
- package/dist/declarations.d.ts +54 -16
- package/dist/defineResource.d.ts +30 -8
- package/dist/errors/ResourceContractError.d.ts +31 -0
- package/dist/helpers.d.ts +15 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +450 -106
- package/dist/middleware/ResourceRouteMiddleware.d.ts +33 -12
- package/dist/options/ResourcesBlueprint.d.ts +19 -0
- package/package.json +5 -4
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { IResource } from '../declarations.js';
|
|
2
2
|
import { IBlueprint, IContainer, IncomingEvent, NextMiddleware, OutgoingResponse, type MetaMiddleware } from '@stone-js/core';
|
|
3
3
|
/**
|
|
4
|
-
* The shape a route's `resource` option may take: the resource itself,
|
|
5
|
-
* registered under `stone.resources.registry`.
|
|
4
|
+
* The shape a route's `resource` option may take: the resource itself, a class to resolve, or the
|
|
5
|
+
* name of one registered under `stone.resources.registry`.
|
|
6
6
|
*/
|
|
7
7
|
export type RouteResource = IResource<any, any> | string;
|
|
8
8
|
/**
|
|
@@ -11,17 +11,12 @@ export type RouteResource = IResource<any, any> | string;
|
|
|
11
11
|
* A route says what it exposes, once, where the route is defined:
|
|
12
12
|
*
|
|
13
13
|
* ```ts
|
|
14
|
-
* @Get('/users/:id', { resource:
|
|
14
|
+
* @Get('/users/:id', { resource: UserResource })
|
|
15
15
|
* ```
|
|
16
16
|
*
|
|
17
|
-
* The handler
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* hash, an internal flag, is not exposed by accident, because the resource decides what leaves.
|
|
21
|
-
*
|
|
22
|
-
* It runs on the raw value the handler returned, before any response wrapping, so it knows nothing
|
|
23
|
-
* of HTTP and works in every context. Sparse fieldsets are read from the event, so `?fields=id,name`
|
|
24
|
-
* narrows the output without the route changing.
|
|
17
|
+
* The handler returns its domain model, whole, and this applies the resource on the way out. That is
|
|
18
|
+
* the point: a service should not have to know which fields are public, and a handler should not have
|
|
19
|
+
* to remember to strip them.
|
|
25
20
|
*/
|
|
26
21
|
export declare class ResourceRouteMiddleware {
|
|
27
22
|
private readonly blueprint;
|
|
@@ -36,11 +31,36 @@ export declare class ResourceRouteMiddleware {
|
|
|
36
31
|
/**
|
|
37
32
|
* Run the handler, then shape what it returned.
|
|
38
33
|
*
|
|
34
|
+
* It handles both of the things a handler may hand back, which is the part that used to be wrong. A
|
|
35
|
+
* handler carrying a response decorator (`@JsonHttpResponse(201)`) has already been turned into a
|
|
36
|
+
* response by the time any route middleware runs, because that decorator wraps the method itself.
|
|
37
|
+
* Projecting the response object produced an empty payload and dropped the status with it. So a
|
|
38
|
+
* response is now projected **through its content**, in place: the payload is shaped and the status,
|
|
39
|
+
* the headers and everything else the handler chose are left exactly as they were.
|
|
40
|
+
*
|
|
39
41
|
* @param event - The incoming event.
|
|
40
42
|
* @param next - The next middleware.
|
|
41
43
|
* @returns The shaped output, or the untouched result when the route declares no resource.
|
|
42
44
|
*/
|
|
43
45
|
handle(event: IncomingEvent, next: NextMiddleware<IncomingEvent, OutgoingResponse>): Promise<OutgoingResponse>;
|
|
46
|
+
/**
|
|
47
|
+
* Project a value, whether it is one model or many.
|
|
48
|
+
*
|
|
49
|
+
* @param resource - The resource to apply.
|
|
50
|
+
* @param value - The value the handler produced.
|
|
51
|
+
* @param context - The resource context.
|
|
52
|
+
* @returns The projected value.
|
|
53
|
+
*/
|
|
54
|
+
private shape;
|
|
55
|
+
/**
|
|
56
|
+
* Whether a value is a response carrying a payload this can replace.
|
|
57
|
+
*
|
|
58
|
+
* Duck-typed: the kernel is agnostic, and each platform has its own response type.
|
|
59
|
+
*
|
|
60
|
+
* @param value - The value to test.
|
|
61
|
+
* @returns Whether it carries content.
|
|
62
|
+
*/
|
|
63
|
+
private isContentBearing;
|
|
44
64
|
/**
|
|
45
65
|
* The resource the matched route declared, with a registered name resolved to its resource.
|
|
46
66
|
*
|
|
@@ -69,7 +89,8 @@ export declare class ResourceRouteMiddleware {
|
|
|
69
89
|
private declaredOnHandler;
|
|
70
90
|
/**
|
|
71
91
|
* Resolve a registered entry: a resource class goes through the container, so its constructor gets
|
|
72
|
-
* the services it asked for
|
|
92
|
+
* the services it asked for — the validator it holds its own contract against, and whatever its
|
|
93
|
+
* `data()` needs to complete a model.
|
|
73
94
|
*
|
|
74
95
|
* @param entry - A resource, or a class to resolve into one.
|
|
75
96
|
* @returns The resource.
|
|
@@ -4,6 +4,25 @@ import { AppConfig, StoneBlueprint } from '@stone-js/core';
|
|
|
4
4
|
* Resources configuration bucket (`stone.resources`).
|
|
5
5
|
*/
|
|
6
6
|
export interface ResourcesConfig {
|
|
7
|
+
/**
|
|
8
|
+
* The query parameters a caller uses to ask for a shape.
|
|
9
|
+
*
|
|
10
|
+
* Configuration rather than convention: an API that already answers `?only=` keeps its vocabulary
|
|
11
|
+
* instead of gaining a second one. Defaults: `fields`, `include`, `view`.
|
|
12
|
+
*/
|
|
13
|
+
params?: {
|
|
14
|
+
fields?: string;
|
|
15
|
+
include?: string;
|
|
16
|
+
fragment?: string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* What to do when a projection breaks the contract its resource publishes.
|
|
20
|
+
*
|
|
21
|
+
* `throw` (the default) refuses to answer, because a caller cannot detect a broken contract and a
|
|
22
|
+
* consumer generated from it breaks on the field that is missing. `warn` chooses availability over
|
|
23
|
+
* integrity, explicitly, and puts the breach in the log.
|
|
24
|
+
*/
|
|
25
|
+
onViolation?: 'throw' | 'warn';
|
|
7
26
|
/**
|
|
8
27
|
* Named resources a route can refer to by name, instead of importing them at the route.
|
|
9
28
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stone-js/resources",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.10",
|
|
4
4
|
"description": "Framework-agnostic API resources for Stone.js. Shape what your domain exposes — sparse fieldsets, conditional fields, includes and envelopes — decoupled from controllers, the same on backend and frontend.",
|
|
5
5
|
"author": "Mr. Stone <evensstone@gmail.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -56,7 +56,8 @@
|
|
|
56
56
|
"typedoc": "^0.28.6",
|
|
57
57
|
"typedoc-plugin-markdown": "^4.7.0",
|
|
58
58
|
"typescript": "^5.6.3",
|
|
59
|
-
"vitest": "^3.2.4"
|
|
59
|
+
"vitest": "^3.2.4",
|
|
60
|
+
"zod": "^3.25.76"
|
|
60
61
|
},
|
|
61
62
|
"ts-standard": {
|
|
62
63
|
"globals": [
|
|
@@ -69,10 +70,10 @@
|
|
|
69
70
|
]
|
|
70
71
|
},
|
|
71
72
|
"dependencies": {
|
|
72
|
-
"@stone-js/config": "0.8.
|
|
73
|
+
"@stone-js/config": "0.8.10"
|
|
73
74
|
},
|
|
74
75
|
"peerDependencies": {
|
|
75
|
-
"@stone-js/core": "0.8.
|
|
76
|
+
"@stone-js/core": "0.8.10"
|
|
76
77
|
},
|
|
77
78
|
"scripts": {
|
|
78
79
|
"lint": "ts-standard src",
|