@modelprofile.com/flexharness 12.0.0 → 12.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_ts/00_commitinfo_data.js +1 -1
- package/dist_ts_stores_nosqldb/classes.nosqldbstores.d.ts +4 -3
- package/dist_ts_stores_nosqldb/classes.nosqldbstores.js +5 -4
- package/dist_ts_stores_nosqldb/classes.recordstore.d.ts +22 -12
- package/dist_ts_stores_nosqldb/classes.recordstore.js +198 -125
- package/dist_ts_typedrequest/catalog.d.ts +4 -4
- package/dist_ts_typedrequest/catalog.js +25 -7
- package/dist_ts_typedrequest/describe.js +23 -11
- package/dist_ts_typedrequest/interfaces.d.ts +17 -1
- package/package.json +3 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts_stores_nosqldb/classes.nosqldbstores.ts +4 -3
- package/ts_stores_nosqldb/classes.recordstore.ts +221 -138
- package/ts_stores_nosqldb/readme.md +11 -5
- package/ts_typedrequest/catalog.ts +24 -6
- package/ts_typedrequest/describe.ts +19 -10
- package/ts_typedrequest/interfaces.ts +21 -1
- package/ts_typedrequest/readme.md +5 -3
|
@@ -43,7 +43,7 @@ const withoutOmitted = (
|
|
|
43
43
|
const target = referencedType(schema);
|
|
44
44
|
if (target !== undefined) {
|
|
45
45
|
const named = types[target];
|
|
46
|
-
return named !== undefined &&
|
|
46
|
+
return named !== undefined && omittedIn(named, omit, types, new Set([target])).size > 0
|
|
47
47
|
? withoutOmitted(named, omit, types)
|
|
48
48
|
: schema;
|
|
49
49
|
}
|
|
@@ -63,22 +63,29 @@ const withoutOmitted = (
|
|
|
63
63
|
return stripped;
|
|
64
64
|
};
|
|
65
65
|
|
|
66
|
-
/**
|
|
67
|
-
const
|
|
66
|
+
/** The omitted properties a schema has, itself or through the schemas it composes or refers to. */
|
|
67
|
+
const omittedIn = (
|
|
68
68
|
schema: TFlexTypedRequestSchema,
|
|
69
69
|
omit: ReadonlySet<string>,
|
|
70
70
|
types: Readonly<Record<string, TFlexTypedRequestSchema>>,
|
|
71
71
|
seen: Set<string>,
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
found = new Set<string>(),
|
|
73
|
+
): Set<string> => {
|
|
74
|
+
if (isRecord(schema.properties)) {
|
|
75
|
+
for (const key of Object.keys(schema.properties)) if (omit.has(key)) found.add(key);
|
|
76
|
+
}
|
|
74
77
|
const target = referencedType(schema);
|
|
75
78
|
if (target !== undefined) {
|
|
76
|
-
if (seen.has(target) || types[target] === undefined) return
|
|
79
|
+
if (seen.has(target) || types[target] === undefined) return found;
|
|
77
80
|
seen.add(target);
|
|
78
|
-
return
|
|
81
|
+
return omittedIn(types[target], omit, types, seen, found);
|
|
79
82
|
}
|
|
80
|
-
|
|
81
|
-
|
|
83
|
+
for (const key of ['allOf', 'anyOf', 'oneOf'] as const) {
|
|
84
|
+
const members = schema[key];
|
|
85
|
+
if (!Array.isArray(members)) continue;
|
|
86
|
+
for (const member of members) if (isRecord(member)) omittedIn(member, omit, types, seen, found);
|
|
87
|
+
}
|
|
88
|
+
return found;
|
|
82
89
|
};
|
|
83
90
|
|
|
84
91
|
/** Whether a call may leave out every parameter: its schema requires none. */
|
|
@@ -169,7 +176,8 @@ export async function describeTypedRequests(options: IFlexTypedRequestSurfaceOpt
|
|
|
169
176
|
let path = base;
|
|
170
177
|
for (let suffix = 2; paths.has(path); suffix++) path = `${base}_${suffix}`;
|
|
171
178
|
paths.add(path);
|
|
172
|
-
const
|
|
179
|
+
const requestSchema = withDefinitionRefs(contract.request) as TFlexTypedRequestSchema;
|
|
180
|
+
const inputSchema = withoutOmitted(requestSchema, omitted, schemas);
|
|
173
181
|
const docLines = [
|
|
174
182
|
...(declared.documentation ? [declared.documentation] : []),
|
|
175
183
|
...(declared.request.documentation ? [`@param params ${declared.request.documentation}`] : []),
|
|
@@ -183,6 +191,7 @@ export async function describeTypedRequests(options: IFlexTypedRequestSurfaceOpt
|
|
|
183
191
|
summary: summaryOf(declared.documentation, contract.method),
|
|
184
192
|
...(declared.documentation ? { description: declared.documentation } : {}),
|
|
185
193
|
...(contract.deprecated ? { deprecated: true } : {}),
|
|
194
|
+
omitted: [...omittedIn(requestSchema, omitted, schemas, new Set())].sort(),
|
|
186
195
|
inputSchema,
|
|
187
196
|
outputSchema: withDefinitionRefs(contract.response) as TFlexTypedRequestSchema,
|
|
188
197
|
declaration: `${docLines.length ? docBlock(docLines) : ''}function ${functionName}(params${optional}: ${declared.request.type}): Promise<${declared.response.type}>;`,
|
|
@@ -42,6 +42,11 @@ export interface IFlexTypedRequestMethod {
|
|
|
42
42
|
description?: string;
|
|
43
43
|
/** Set by a `@deprecated` tag on the contract. */
|
|
44
44
|
deprecated?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* The properties of the surface's `omit` this method's request has, itself or through the types
|
|
47
|
+
* it refers to: the ones the binding fills for its calls. Empty where it has none.
|
|
48
|
+
*/
|
|
49
|
+
omitted: string[];
|
|
45
50
|
/** The request's schema, without the omitted properties. */
|
|
46
51
|
inputSchema: TFlexTypedRequestSchema;
|
|
47
52
|
/** The response's schema. */
|
|
@@ -96,7 +101,9 @@ export interface IFlexTypedRequestCatalogOptions<TScope = unknown> {
|
|
|
96
101
|
router: IFlexTypedRequestRouter;
|
|
97
102
|
/**
|
|
98
103
|
* The request properties the surface leaves out, from the run: `{ identity }` of the user the
|
|
99
|
-
* session acts for.
|
|
104
|
+
* session acts for. A call takes from it the properties its method's request has
|
|
105
|
+
* (`IFlexTypedRequestMethod.omitted`) and nothing else; a method whose request has none is called
|
|
106
|
+
* without asking.
|
|
100
107
|
*/
|
|
101
108
|
request?(
|
|
102
109
|
method: IFlexTypedRequestMethod,
|
|
@@ -116,6 +123,19 @@ export interface IFlexTypedRequestCatalogOptions<TScope = unknown> {
|
|
|
116
123
|
* `IFlexCatalogMethod.readOnly`. Default: none.
|
|
117
124
|
*/
|
|
118
125
|
readOnly?(method: IFlexTypedRequestMethod): boolean;
|
|
126
|
+
/**
|
|
127
|
+
* The request a call routes for the model's validated parameters, such as the parameters with the
|
|
128
|
+
* short names the model was shown for records turned back into their IDs. Default: the
|
|
129
|
+
* parameters. It runs when the call runs, after `onCall` decided it where the method has one:
|
|
130
|
+
* `onCall` and a proposal see the model's parameters. The omitted properties are dropped from what
|
|
131
|
+
* it returns, as from the model's, and only `request` fills them. A throw refuses the call with
|
|
132
|
+
* its error, and so does a result that is no object.
|
|
133
|
+
*/
|
|
134
|
+
params?(
|
|
135
|
+
method: IFlexTypedRequestMethod,
|
|
136
|
+
params: Record<string, unknown>,
|
|
137
|
+
context: IFlexCatalogRunContext<TScope>,
|
|
138
|
+
): Record<string, unknown> | PromiseLike<Record<string, unknown>>;
|
|
119
139
|
/**
|
|
120
140
|
* What the model sees of a method's answered response, such as the response without a
|
|
121
141
|
* credential's secret. Default: the response. A refusal does not reach it, and the method's
|
|
@@ -29,19 +29,21 @@ const catalog = catalogFromTypedRequests<IAppScope>(surface, {
|
|
|
29
29
|
- Each typed method becomes a method of the path `<area>.<method>`; the area is the base name of the file that declares the contract (`vouchers` for `requests/vouchers.ts`, the folder's name for an `index.ts`), or what `area` returns. A name that is no identifier is mapped as `FlexToolCatalog.identifierOf()` maps it (`export` becomes `export_`).
|
|
30
30
|
- Its declaration is the contract as written: `function getVoucher(params: { voucherId: string }): Promise<{ voucher: IVoucher }>;` after the contract's JSDoc with its tags, the request property's JSDoc as `@param params`, the response property's as `@returns`. `params` is optional where the request requires nothing.
|
|
31
31
|
- Its `inputSchema` and `outputSchema` are the request's and response's JSON Schema; `execute` validates every call against the request's.
|
|
32
|
-
- `omit` names request properties the binding fills from the run, such as the caller's identity or a CSRF token: they leave every request's schema and declaration, so the model can neither see nor send them.
|
|
32
|
+
- `omit` names request properties the binding fills from the run, such as the caller's identity or a CSRF token: they leave every request's schema and declaration, so the model can neither see nor send them. Each method lists in `omitted` those its request has, itself or through the types it refers to; a public method's list may be empty.
|
|
33
33
|
- The named types the requests and responses reach become the catalog's types, each with its JSON Schema, its declaration from the sources, or both: a generic is declared once (`IPage<T>`) and its instances have schemas (`IPage_IVoucher`). A method's result types are declared only as deep as `toolCatalog.outputTypeDepth` asks, as for any declaration.
|
|
34
34
|
|
|
35
35
|
The surface is plain JSON, so a build step can write it next to the server and the server read it at startup without TypeScript or `@api.global/typedopenapi`. A 330-method API is described in about 8 seconds.
|
|
36
36
|
|
|
37
37
|
`catalogFromTypedRequests(surface, options)` returns an `IFlexToolCatalog`:
|
|
38
38
|
|
|
39
|
-
- `router` answers the calls: anything with `routeAndAddResponse()`, such as a `TypedRouter` of `@api.global/typedrequest`. A call is routed as a typed request with the model's parameters
|
|
39
|
+
- `router` answers the calls: anything with `routeAndAddResponse()`, such as a `TypedRouter` of `@api.global/typedrequest`. A call is routed as a typed request with the model's parameters, `localData` as the trusted route data a transport would hand the handlers, and the run's abort signal.
|
|
40
|
+
- `request` fills the omitted properties. A call takes from what it returns only the omitted properties its method's request has, so one answer serves every method (`{ identity, csrfToken }`), and a method whose request has none is routed without asking it. A value the model passes for any omitted property never reaches the router.
|
|
40
41
|
- A refusal rejects with `FlexTypedRequestError`: the typed method, the error's `text` and `data`, as a client of the API would receive them. A handler's own failure arrives as the router's internal error. A host's `externalErrorProjector` decides what of it the model sees.
|
|
41
42
|
- `include` picks the methods the model may use, by default every method that is not deprecated; `aliases` gives methods other names by typed method; `vocabulary`, `onCall` and `onProposals` are the catalog's own (`onCall` receives the typed method first).
|
|
42
43
|
- `readOnly` marks the methods that only read. A marked method is declared `readOnly` and `onCall` does not decide its calls, so they run concurrently with other reads, may start while the model still streams, and a turn answers identical ones once; every other method's calls, gated by `onCall` or not, run in the order the model made them. Mark nothing that asks for permission.
|
|
44
|
+
- `params` makes the request a call routes of the model's validated parameters, such as the parameters with the short names the model was shown for records turned back into their IDs; by default the parameters themselves. It runs when the call runs, after `onCall` decided it where the method has one, so `onCall` and a proposal see the model's parameters. The omitted properties are dropped from what it returns as from the model's, and only `request` fills them. A throw refuses the call with its error, and so does a result that is no object.
|
|
43
45
|
- `response` decides what the model sees of an answered response, such as the response without a credential's secret; by default the response itself. A refusal does not reach it, and the method's declaration still shows the contract's response.
|
|
44
|
-
- A surface that omits properties needs `request`; an alias for a method the surface lacks is refused.
|
|
46
|
+
- A surface that omits properties needs `request`; an alias for a method the surface lacks is refused, and so is a surface whose methods have no `omitted` list, as one described by an earlier version: describe it again.
|
|
45
47
|
|
|
46
48
|
## Issue Reporting and Security
|
|
47
49
|
|