@stone-js/resources 0.8.11 → 0.8.13
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/Resource.d.ts +31 -18
- package/dist/declarations.d.ts +24 -13
- package/dist/index.d.ts +0 -1
- package/dist/index.js +40 -44
- package/dist/middleware/ResourceRouteMiddleware.d.ts +24 -0
- package/dist/options/ResourcesBlueprint.d.ts +23 -0
- package/package.json +7 -6
- package/dist/middleware/BlueprintMiddleware.d.ts +0 -18
package/dist/Resource.d.ts
CHANGED
|
@@ -45,7 +45,7 @@ export interface ResourceDependencies {
|
|
|
45
45
|
/** The reader every projection is held against, bound as `contractChecker`. */
|
|
46
46
|
contractChecker?: IContractChecker;
|
|
47
47
|
}
|
|
48
|
-
export declare abstract class Resource<Model = unknown, Output extends ResourceOutput = ResourceOutput> implements IResource<Model, Output> {
|
|
48
|
+
export declare abstract class Resource<Model = unknown, Output extends ResourceOutput = ResourceOutput, EventType = unknown, PrincipalType = unknown> implements IResource<Model, Output, EventType, PrincipalType> {
|
|
49
49
|
protected checker: IContractChecker;
|
|
50
50
|
protected onViolation: ContractViolationPolicy;
|
|
51
51
|
/**
|
|
@@ -68,7 +68,7 @@ export declare abstract class Resource<Model = unknown, Output extends ResourceO
|
|
|
68
68
|
* @param context - The resource context.
|
|
69
69
|
* @returns The schema.
|
|
70
70
|
*/
|
|
71
|
-
abstract schema(context: ResourceContext): ResourceSchema | Promise<ResourceSchema>;
|
|
71
|
+
abstract schema(context: ResourceContext<EventType, PrincipalType>): ResourceSchema | Promise<ResourceSchema>;
|
|
72
72
|
/**
|
|
73
73
|
* Project one model.
|
|
74
74
|
*
|
|
@@ -81,7 +81,7 @@ export declare abstract class Resource<Model = unknown, Output extends ResourceO
|
|
|
81
81
|
* @returns The projected output.
|
|
82
82
|
* @throws {ResourceContractError} When the data breaks the contract and the policy is `throw`.
|
|
83
83
|
*/
|
|
84
|
-
item(model: Model, context?: ResourceContext): Promise<Output>;
|
|
84
|
+
item(model: Model, context?: ResourceContext<EventType, PrincipalType>): Promise<Output>;
|
|
85
85
|
/**
|
|
86
86
|
* Project a collection.
|
|
87
87
|
*
|
|
@@ -93,7 +93,7 @@ export declare abstract class Resource<Model = unknown, Output extends ResourceO
|
|
|
93
93
|
* @param context - The resource context.
|
|
94
94
|
* @returns The projected collection.
|
|
95
95
|
*/
|
|
96
|
-
collection(models: Model[], context?: ResourceContext): Promise<Output[]>;
|
|
96
|
+
collection(models: Model[], context?: ResourceContext<EventType, PrincipalType>): Promise<Output[]>;
|
|
97
97
|
/**
|
|
98
98
|
* Project into a `{ data, meta }` envelope.
|
|
99
99
|
*
|
|
@@ -102,19 +102,7 @@ export declare abstract class Resource<Model = unknown, Output extends ResourceO
|
|
|
102
102
|
* @param meta - Optional metadata (pagination, counts, …).
|
|
103
103
|
* @returns The envelope.
|
|
104
104
|
*/
|
|
105
|
-
response(models: Model | Model[], context?: ResourceContext, meta?: Record<string, unknown>): Promise<ResourceEnvelope<Output | Output[]>>;
|
|
106
|
-
/**
|
|
107
|
-
* Optional: shape or complete the model before it meets the schema.
|
|
108
|
-
*
|
|
109
|
-
* `declare`, not a field: an uninitialised class field is *defined* as `undefined` on the instance,
|
|
110
|
-
* which would shadow the very method a subclass wrote — the override would exist on the prototype
|
|
111
|
-
* and never be reached. This states the type and emits nothing.
|
|
112
|
-
*/
|
|
113
|
-
data?: (model: Model, context: ResourceContext) => Promiseable<unknown>;
|
|
114
|
-
/**
|
|
115
|
-
* Named subsets a caller may ask for. Override to expose fragments.
|
|
116
|
-
*/
|
|
117
|
-
fragments?: (context: ResourceContext) => Record<string, ResourceSchema> | Promise<Record<string, ResourceSchema>>;
|
|
105
|
+
response(models: Model | Model[], context?: ResourceContext<EventType, PrincipalType>, meta?: Record<string, unknown>): Promise<ResourceEnvelope<Output | Output[]>>;
|
|
118
106
|
/**
|
|
119
107
|
* The schema to hold this projection against: the requested fragment when the resource exposes one,
|
|
120
108
|
* the full contract otherwise.
|
|
@@ -126,7 +114,7 @@ export declare abstract class Resource<Model = unknown, Output extends ResourceO
|
|
|
126
114
|
* @param context - The resource context.
|
|
127
115
|
* @returns The schema.
|
|
128
116
|
*/
|
|
129
|
-
protected schemaFor(context: ResourceContext): Promise<ResourceSchema>;
|
|
117
|
+
protected schemaFor(context: ResourceContext<EventType, PrincipalType>): Promise<ResourceSchema>;
|
|
130
118
|
/**
|
|
131
119
|
* Hold the data against the contract, and return what the contract describes.
|
|
132
120
|
*
|
|
@@ -158,3 +146,28 @@ export declare abstract class Resource<Model = unknown, Output extends ResourceO
|
|
|
158
146
|
*/
|
|
159
147
|
protected whenIncluded<T>(context: ResourceContext, name: string, value: T | (() => T)): T | undefined;
|
|
160
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* The two optional hooks, declared as methods rather than as properties.
|
|
151
|
+
*
|
|
152
|
+
* A property-typed function is contravariant on its parameters, and TypeScript refuses a method where
|
|
153
|
+
* the base declared a property. Between them, those two rules meant a subclass could neither narrow the
|
|
154
|
+
* context nor write `async data (model, context) {}`, which is the form every example uses. Declared
|
|
155
|
+
* here, on an interface merged with the class, both forms are accepted and the type parameters actually
|
|
156
|
+
* reach the signature a subclass writes.
|
|
157
|
+
*/
|
|
158
|
+
export interface Resource<Model, Output extends ResourceOutput, EventType, PrincipalType> {
|
|
159
|
+
/**
|
|
160
|
+
* Optional: shape or complete the model before it meets the schema.
|
|
161
|
+
*
|
|
162
|
+
* A method signature, deliberately, against the repository's own lint rule: a property-typed
|
|
163
|
+
* function is contravariant on its parameters, so a subclass narrowing the context was rejected, and
|
|
164
|
+
* TypeScript separately refuses a method where the base declared a property, so
|
|
165
|
+
* `async data (model, context) {}` was rejected too. The rule's soundness argument is theoretical for
|
|
166
|
+
* an extension point; the cost was measured, in an application that could not type its resources.
|
|
167
|
+
*/
|
|
168
|
+
data?(model: Model, context: ResourceContext<EventType, PrincipalType>): Promiseable<unknown>;
|
|
169
|
+
/**
|
|
170
|
+
* Named subsets a caller may ask for. Override to expose fragments.
|
|
171
|
+
*/
|
|
172
|
+
fragments?(context: ResourceContext<EventType, PrincipalType>): Record<string, ResourceSchema> | Promise<Record<string, ResourceSchema>>;
|
|
173
|
+
}
|
package/dist/declarations.d.ts
CHANGED
|
@@ -15,17 +15,28 @@ export type ResourceSchema = unknown;
|
|
|
15
15
|
* carried. The authenticated principal is part of it, because deciding what a caller may see is the
|
|
16
16
|
* most common reason a projection differs between two callers.
|
|
17
17
|
*/
|
|
18
|
-
export interface ResourceContext {
|
|
19
|
-
/** Requested sparse fieldset
|
|
18
|
+
export interface ResourceContext<EventType = unknown, PrincipalType = unknown> {
|
|
19
|
+
/** Requested sparse fieldset: narrows the output to these top-level keys. */
|
|
20
20
|
fields?: string[];
|
|
21
21
|
/** Requested relations to embed. */
|
|
22
22
|
include?: string[];
|
|
23
23
|
/** The requested fragment, when the caller asked for one by name. */
|
|
24
24
|
fragment?: string;
|
|
25
|
-
/**
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
/**
|
|
26
|
+
* The authenticated principal, when the application has one.
|
|
27
|
+
*
|
|
28
|
+
* Typed by the resource, because deciding what a caller may see is the most common reason two
|
|
29
|
+
* callers get different shapes, and `unknown` makes every such decision a cast. The default stays
|
|
30
|
+
* `unknown`: this module never assumes an application has users, let alone what a user is.
|
|
31
|
+
*/
|
|
32
|
+
principal?: PrincipalType;
|
|
33
|
+
/**
|
|
34
|
+
* The event being answered, for a resource that needs more than the parameters above.
|
|
35
|
+
*
|
|
36
|
+
* Typed by the resource for the same reason, and `unknown` by default because the module is
|
|
37
|
+
* agnostic of the platform the event came from.
|
|
38
|
+
*/
|
|
39
|
+
event?: EventType;
|
|
29
40
|
/** Anything else a resource needs. */
|
|
30
41
|
[key: string]: unknown;
|
|
31
42
|
}
|
|
@@ -47,29 +58,29 @@ export interface ResourceEnvelope<T> {
|
|
|
47
58
|
* and to the resource itself, which validates against it before anything leaves. One declaration, three
|
|
48
59
|
* consumers, and no way for the documentation to drift from the response.
|
|
49
60
|
*/
|
|
50
|
-
export interface IResource<Model = unknown, Output = ResourceOutput> {
|
|
61
|
+
export interface IResource<Model = unknown, Output = ResourceOutput, EventType = unknown, PrincipalType = unknown> {
|
|
51
62
|
/** The contract: the schema every projection is validated against and documented from. */
|
|
52
|
-
schema
|
|
63
|
+
schema(context: ResourceContext<EventType, PrincipalType>): ResourceSchema | Promise<ResourceSchema>;
|
|
53
64
|
/**
|
|
54
65
|
* Named subsets a caller may ask for, each with its own schema.
|
|
55
66
|
*
|
|
56
67
|
* A fragment is not a filter: it is a contract of its own, documented and validated like the full
|
|
57
68
|
* one. That is what makes `?view=summary` safe to expose.
|
|
58
69
|
*/
|
|
59
|
-
fragments
|
|
70
|
+
fragments?(context: ResourceContext<EventType, PrincipalType>): Record<string, ResourceSchema> | Promise<Record<string, ResourceSchema>>;
|
|
60
71
|
/**
|
|
61
72
|
* Optional hook to shape or complete the model before it meets the schema.
|
|
62
73
|
*
|
|
63
74
|
* Asynchronous, and resolved from the container, so it may reach any service: fetch a relation,
|
|
64
75
|
* translate a label, compute a total. Whatever it returns is what the schema then validates.
|
|
65
76
|
*/
|
|
66
|
-
data
|
|
77
|
+
data?(model: Model, context: ResourceContext<EventType, PrincipalType>): Promiseable<unknown>;
|
|
67
78
|
/** Project one model. */
|
|
68
|
-
item
|
|
79
|
+
item(model: Model, context?: ResourceContext<EventType, PrincipalType>): Promise<Output>;
|
|
69
80
|
/** Project a collection. */
|
|
70
|
-
collection
|
|
81
|
+
collection(models: Model[], context?: ResourceContext<EventType, PrincipalType>): Promise<Output[]>;
|
|
71
82
|
/** Project into a `{ data, meta }` envelope. */
|
|
72
|
-
response
|
|
83
|
+
response(models: Model | Model[], context?: ResourceContext<EventType, PrincipalType>, meta?: Record<string, unknown>): Promise<ResourceEnvelope<Output | Output[]>>;
|
|
73
84
|
}
|
|
74
85
|
/** What to do when the data does not match the contract the resource published. */
|
|
75
86
|
export type ContractViolationPolicy = 'throw' | 'warn';
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,6 @@ export * from './decorators/Returns.js';
|
|
|
7
7
|
export * from './defineResource.js';
|
|
8
8
|
export * from './errors/ResourceContractError.js';
|
|
9
9
|
export * from './helpers.js';
|
|
10
|
-
export * from './middleware/BlueprintMiddleware.js';
|
|
11
10
|
export * from './middleware/ResourceRouteMiddleware.js';
|
|
12
11
|
export * from './options/ResourcesBlueprint.js';
|
|
13
12
|
export * from './Resource.js';
|
package/dist/index.js
CHANGED
|
@@ -541,11 +541,48 @@ class ResourceRouteMiddleware {
|
|
|
541
541
|
onViolation: this.blueprint.get('stone.resources', {}).onViolation
|
|
542
542
|
});
|
|
543
543
|
if (this.isContentBearing(result)) {
|
|
544
|
-
const shaped = await this.
|
|
544
|
+
const shaped = await this.shapePayload(resource, result.content, context);
|
|
545
545
|
result.setContent(shaped);
|
|
546
546
|
return result;
|
|
547
547
|
}
|
|
548
|
-
return await this.
|
|
548
|
+
return await this.shapePayload(resource, result, context);
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Shape a value, or shape what is inside the envelope the application declared.
|
|
552
|
+
*
|
|
553
|
+
* A page is `{ items: [...], meta: { total } }`, and `items` and `meta` are not fields of a model:
|
|
554
|
+
* projecting that object would publish the envelope as if it were the thing. An application names its
|
|
555
|
+
* own wrapper once, in `stone.resources.envelope`, and everything around the payload is left as it
|
|
556
|
+
* was, counts and cursors included.
|
|
557
|
+
*
|
|
558
|
+
* Nothing is assumed when nothing is declared, because guessing which key holds the payload would
|
|
559
|
+
* quietly mangle a model that happens to have one by that name.
|
|
560
|
+
*
|
|
561
|
+
* @param resource - The resource to apply.
|
|
562
|
+
* @param value - The value the handler produced.
|
|
563
|
+
* @param context - The resource context.
|
|
564
|
+
* @returns The projected value, wrapper intact.
|
|
565
|
+
*/
|
|
566
|
+
async shapePayload(resource, value, context) {
|
|
567
|
+
const key = this.envelopeKeyOf(value);
|
|
568
|
+
if (key === undefined) {
|
|
569
|
+
return await this.shape(resource, value, context);
|
|
570
|
+
}
|
|
571
|
+
const envelope = value;
|
|
572
|
+
return { ...envelope, [key]: await this.shape(resource, envelope[key], context) };
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Which declared envelope key this value carries, if any.
|
|
576
|
+
*
|
|
577
|
+
* @param value - The value the handler produced.
|
|
578
|
+
* @returns The key holding the payload, or nothing when this is not an envelope.
|
|
579
|
+
*/
|
|
580
|
+
envelopeKeyOf(value) {
|
|
581
|
+
const declared = this.blueprint.get('stone.resources', {}).envelope;
|
|
582
|
+
if (declared === undefined || typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
583
|
+
return undefined;
|
|
584
|
+
}
|
|
585
|
+
return [declared.payload].flat().find((candidate) => candidate in value);
|
|
549
586
|
}
|
|
550
587
|
/**
|
|
551
588
|
* Project a value, whether it is one model or many.
|
|
@@ -669,42 +706,6 @@ const MetaResourceRouteMiddleware = {
|
|
|
669
706
|
priority: 4
|
|
670
707
|
};
|
|
671
708
|
|
|
672
|
-
/**
|
|
673
|
-
* Build-phase middleware: collect every class registered with `@ApiResource` into the registry.
|
|
674
|
-
*
|
|
675
|
-
* The same scan the router does for its route definitions, applied to this module's own key. After it
|
|
676
|
-
* runs, `stone.resources.registry` maps each alias to its class, so a route or a handler can name a
|
|
677
|
-
* resource instead of importing it, and `@stone-js/openapi` can walk the registry to publish response
|
|
678
|
-
* shapes without loading anything itself.
|
|
679
|
-
*
|
|
680
|
-
* @param context - The blueprint context.
|
|
681
|
-
* @param next - The next blueprint middleware.
|
|
682
|
-
* @returns The blueprint.
|
|
683
|
-
*/
|
|
684
|
-
async function ApiResourceMiddleware(context, next) {
|
|
685
|
-
const registered = context
|
|
686
|
-
.modules
|
|
687
|
-
.filter((module) => hasMetadata(module, API_RESOURCE_KEY))
|
|
688
|
-
.reduce((registry, module) => {
|
|
689
|
-
const { alias } = getMetadata(module, API_RESOURCE_KEY, {});
|
|
690
|
-
return { ...registry, [alias ?? module.name]: module };
|
|
691
|
-
}, {});
|
|
692
|
-
if (Object.keys(registered).length > 0) {
|
|
693
|
-
context.blueprint.set('stone.resources.registry', {
|
|
694
|
-
...context.blueprint.get('stone.resources.registry', {}),
|
|
695
|
-
...registered
|
|
696
|
-
});
|
|
697
|
-
}
|
|
698
|
-
return await next(context);
|
|
699
|
-
}
|
|
700
|
-
/**
|
|
701
|
-
* Meta blueprint middleware for resource discovery.
|
|
702
|
-
*/
|
|
703
|
-
const MetaApiResourceMiddleware = {
|
|
704
|
-
module: ApiResourceMiddleware,
|
|
705
|
-
priority: 5
|
|
706
|
-
};
|
|
707
|
-
|
|
708
709
|
/**
|
|
709
710
|
* Opt-in blueprint: register it to shape what routes return.
|
|
710
711
|
*
|
|
@@ -737,11 +738,6 @@ const resourcesBlueprint = {
|
|
|
737
738
|
stone: {
|
|
738
739
|
resources: {},
|
|
739
740
|
services: [MetaContractChecker],
|
|
740
|
-
blueprint: {
|
|
741
|
-
middleware: [
|
|
742
|
-
MetaApiResourceMiddleware
|
|
743
|
-
]
|
|
744
|
-
},
|
|
745
741
|
router: {
|
|
746
742
|
middleware: [
|
|
747
743
|
MetaResourceRouteMiddleware
|
|
@@ -849,4 +845,4 @@ const Returns = (resource) => {
|
|
|
849
845
|
});
|
|
850
846
|
};
|
|
851
847
|
|
|
852
|
-
export { API_RESOURCE_KEY, ApiResource,
|
|
848
|
+
export { API_RESOURCE_KEY, ApiResource, ContractChecker, MetaContractChecker, MetaResourceRouteMiddleware, RETURNS_KEY, Resource, ResourceContractError, ResourceRouteMiddleware, Resources, Returns, applyFields, contextFromEvent, defineResource, except, only, resourcesBlueprint, stripUndefined };
|
|
@@ -43,6 +43,30 @@ export declare class ResourceRouteMiddleware {
|
|
|
43
43
|
* @returns The shaped output, or the untouched result when the route declares no resource.
|
|
44
44
|
*/
|
|
45
45
|
handle(event: IncomingEvent, next: NextMiddleware<IncomingEvent, OutgoingResponse>): Promise<OutgoingResponse>;
|
|
46
|
+
/**
|
|
47
|
+
* Shape a value, or shape what is inside the envelope the application declared.
|
|
48
|
+
*
|
|
49
|
+
* A page is `{ items: [...], meta: { total } }`, and `items` and `meta` are not fields of a model:
|
|
50
|
+
* projecting that object would publish the envelope as if it were the thing. An application names its
|
|
51
|
+
* own wrapper once, in `stone.resources.envelope`, and everything around the payload is left as it
|
|
52
|
+
* was, counts and cursors included.
|
|
53
|
+
*
|
|
54
|
+
* Nothing is assumed when nothing is declared, because guessing which key holds the payload would
|
|
55
|
+
* quietly mangle a model that happens to have one by that name.
|
|
56
|
+
*
|
|
57
|
+
* @param resource - The resource to apply.
|
|
58
|
+
* @param value - The value the handler produced.
|
|
59
|
+
* @param context - The resource context.
|
|
60
|
+
* @returns The projected value, wrapper intact.
|
|
61
|
+
*/
|
|
62
|
+
private shapePayload;
|
|
63
|
+
/**
|
|
64
|
+
* Which declared envelope key this value carries, if any.
|
|
65
|
+
*
|
|
66
|
+
* @param value - The value the handler produced.
|
|
67
|
+
* @returns The key holding the payload, or nothing when this is not an envelope.
|
|
68
|
+
*/
|
|
69
|
+
private envelopeKeyOf;
|
|
46
70
|
/**
|
|
47
71
|
* Project a value, whether it is one model or many.
|
|
48
72
|
*
|
|
@@ -3,6 +3,13 @@ import { AppConfig, MetaService, StoneBlueprint } from '@stone-js/core';
|
|
|
3
3
|
/**
|
|
4
4
|
* Resources configuration bucket (`stone.resources`).
|
|
5
5
|
*/
|
|
6
|
+
/**
|
|
7
|
+
* The envelope an application wraps its payloads in.
|
|
8
|
+
*/
|
|
9
|
+
export interface ResourceEnvelopeConfig {
|
|
10
|
+
/** The key, or keys, that hold the payload to shape. */
|
|
11
|
+
payload: string | string[];
|
|
12
|
+
}
|
|
6
13
|
export interface ResourcesConfig {
|
|
7
14
|
/**
|
|
8
15
|
* The query parameters a caller uses to ask for a shape.
|
|
@@ -35,6 +42,22 @@ export interface ResourcesConfig {
|
|
|
35
42
|
* model unshaped, because an unshaped model is exactly what a resource exists to prevent.
|
|
36
43
|
*/
|
|
37
44
|
registry?: Record<string, IResource<any, any>>;
|
|
45
|
+
/**
|
|
46
|
+
* The envelope this application wraps its payloads in, if it wraps them at all.
|
|
47
|
+
*
|
|
48
|
+
* A handler answering a page returns something like `{ items: [...], meta: { total } }`, and `items`
|
|
49
|
+
* and `meta` are not fields of a model: shaping that object would publish the wrapper as if it were
|
|
50
|
+
* the thing. Naming the word once is enough, and everything around the payload is left as it was,
|
|
51
|
+
* counts and cursors included.
|
|
52
|
+
*
|
|
53
|
+
* ```ts
|
|
54
|
+
* blueprint.set('stone.resources.envelope', { payload: 'items' })
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* Undeclared by default, because guessing which key holds the payload would quietly mangle a model
|
|
58
|
+
* that happens to have one by that name.
|
|
59
|
+
*/
|
|
60
|
+
envelope?: ResourceEnvelopeConfig;
|
|
38
61
|
}
|
|
39
62
|
/**
|
|
40
63
|
* Application config augmented with the resources bucket.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stone-js/resources",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.13",
|
|
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",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"typescript": "^5.6.3",
|
|
59
59
|
"vitest": "^3.2.4",
|
|
60
60
|
"zod": "^3.25.76",
|
|
61
|
-
"@stone-js/service-container": "0.8.
|
|
61
|
+
"@stone-js/service-container": "0.8.13"
|
|
62
62
|
},
|
|
63
63
|
"ts-standard": {
|
|
64
64
|
"globals": [
|
|
@@ -71,10 +71,10 @@
|
|
|
71
71
|
]
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
|
-
"@stone-js/config": "0.8.
|
|
74
|
+
"@stone-js/config": "0.8.13"
|
|
75
75
|
},
|
|
76
76
|
"peerDependencies": {
|
|
77
|
-
"@stone-js/core": "0.8.
|
|
77
|
+
"@stone-js/core": "0.8.13"
|
|
78
78
|
},
|
|
79
79
|
"scripts": {
|
|
80
80
|
"lint": "ts-standard src",
|
|
@@ -83,10 +83,11 @@
|
|
|
83
83
|
"doc": "typedoc",
|
|
84
84
|
"clean": "rimraf dist",
|
|
85
85
|
"build": "rollup -c",
|
|
86
|
-
"test": "vitest run",
|
|
86
|
+
"test": "vitest run && npm run test:types",
|
|
87
87
|
"test:cvg": "npm run test -- --coverage",
|
|
88
88
|
"test:text": "npm run test:cvg -- --coverage.reporter=text",
|
|
89
89
|
"test:html": "npm run test:cvg -- --coverage.reporter=html",
|
|
90
|
-
"test:clover": "npm run test:cvg -- --coverage.reporter=clover"
|
|
90
|
+
"test:clover": "npm run test:cvg -- --coverage.reporter=clover",
|
|
91
|
+
"test:types": "tsc -p tsconfig.types.json"
|
|
91
92
|
}
|
|
92
93
|
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { BlueprintContext, ClassType, IBlueprint, NextMiddleware, type MetaMiddleware } from '@stone-js/core';
|
|
2
|
-
/**
|
|
3
|
-
* Build-phase middleware: collect every class registered with `@ApiResource` into the registry.
|
|
4
|
-
*
|
|
5
|
-
* The same scan the router does for its route definitions, applied to this module's own key. After it
|
|
6
|
-
* runs, `stone.resources.registry` maps each alias to its class, so a route or a handler can name a
|
|
7
|
-
* resource instead of importing it, and `@stone-js/openapi` can walk the registry to publish response
|
|
8
|
-
* shapes without loading anything itself.
|
|
9
|
-
*
|
|
10
|
-
* @param context - The blueprint context.
|
|
11
|
-
* @param next - The next blueprint middleware.
|
|
12
|
-
* @returns The blueprint.
|
|
13
|
-
*/
|
|
14
|
-
export declare function ApiResourceMiddleware(context: BlueprintContext<IBlueprint, ClassType>, next: NextMiddleware<BlueprintContext<IBlueprint, ClassType>, IBlueprint>): Promise<IBlueprint>;
|
|
15
|
-
/**
|
|
16
|
-
* Meta blueprint middleware for resource discovery.
|
|
17
|
-
*/
|
|
18
|
-
export declare const MetaApiResourceMiddleware: MetaMiddleware<any, any>;
|