@stone-js/resources 0.8.12 → 0.8.14
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 +7 -7
- package/package.json +7 -6
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
|
@@ -58,29 +58,29 @@ export interface ResourceEnvelope<T> {
|
|
|
58
58
|
* and to the resource itself, which validates against it before anything leaves. One declaration, three
|
|
59
59
|
* consumers, and no way for the documentation to drift from the response.
|
|
60
60
|
*/
|
|
61
|
-
export interface IResource<Model = unknown, Output = ResourceOutput> {
|
|
61
|
+
export interface IResource<Model = unknown, Output = ResourceOutput, EventType = unknown, PrincipalType = unknown> {
|
|
62
62
|
/** The contract: the schema every projection is validated against and documented from. */
|
|
63
|
-
schema
|
|
63
|
+
schema(context: ResourceContext<EventType, PrincipalType>): ResourceSchema | Promise<ResourceSchema>;
|
|
64
64
|
/**
|
|
65
65
|
* Named subsets a caller may ask for, each with its own schema.
|
|
66
66
|
*
|
|
67
67
|
* A fragment is not a filter: it is a contract of its own, documented and validated like the full
|
|
68
68
|
* one. That is what makes `?view=summary` safe to expose.
|
|
69
69
|
*/
|
|
70
|
-
fragments
|
|
70
|
+
fragments?(context: ResourceContext<EventType, PrincipalType>): Record<string, ResourceSchema> | Promise<Record<string, ResourceSchema>>;
|
|
71
71
|
/**
|
|
72
72
|
* Optional hook to shape or complete the model before it meets the schema.
|
|
73
73
|
*
|
|
74
74
|
* Asynchronous, and resolved from the container, so it may reach any service: fetch a relation,
|
|
75
75
|
* translate a label, compute a total. Whatever it returns is what the schema then validates.
|
|
76
76
|
*/
|
|
77
|
-
data
|
|
77
|
+
data?(model: Model, context: ResourceContext<EventType, PrincipalType>): Promiseable<unknown>;
|
|
78
78
|
/** Project one model. */
|
|
79
|
-
item
|
|
79
|
+
item(model: Model, context?: ResourceContext<EventType, PrincipalType>): Promise<Output>;
|
|
80
80
|
/** Project a collection. */
|
|
81
|
-
collection
|
|
81
|
+
collection(models: Model[], context?: ResourceContext<EventType, PrincipalType>): Promise<Output[]>;
|
|
82
82
|
/** Project into a `{ data, meta }` envelope. */
|
|
83
|
-
response
|
|
83
|
+
response(models: Model | Model[], context?: ResourceContext<EventType, PrincipalType>, meta?: Record<string, unknown>): Promise<ResourceEnvelope<Output | Output[]>>;
|
|
84
84
|
}
|
|
85
85
|
/** What to do when the data does not match the contract the resource published. */
|
|
86
86
|
export type ContractViolationPolicy = 'throw' | 'warn';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stone-js/resources",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.14",
|
|
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.14"
|
|
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.14"
|
|
75
75
|
},
|
|
76
76
|
"peerDependencies": {
|
|
77
|
-
"@stone-js/core": "0.8.
|
|
77
|
+
"@stone-js/core": "0.8.14"
|
|
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
|
}
|