@rexeus/typeweaver-types 0.10.3 → 0.10.5
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/index.cjs +5 -2
- package/dist/index.mjs +6 -3
- package/dist/index.mjs.map +1 -1
- package/dist/lib/ResponseValidator.d.ts +1 -1
- package/dist/lib/ResponseValidator.js +9 -2
- package/dist/lib/Validator.js +4 -1
- package/dist/lib/definitionLookup.js +4 -2
- package/dist/lib/errors/MissingOperationDefinitionError.js +16 -0
- package/dist/lib/errors/MissingResponseDefinitionError.js +14 -0
- package/dist/templates/Request.ejs +2 -2
- package/dist/templates/Response.ejs +2 -1
- package/dist/templates/ResponseFactory.ejs +2 -1
- package/dist/templates/SharedResponse.ejs +2 -1
- package/package.json +6 -6
|
@@ -20,7 +20,7 @@ export declare abstract class ResponseValidator<
|
|
|
20
20
|
TResponse extends ITypedHttpResponse = ITypedHttpResponse,
|
|
21
21
|
>
|
|
22
22
|
extends Validator
|
|
23
|
-
implements IResponseValidator
|
|
23
|
+
implements IResponseValidator<TResponse>
|
|
24
24
|
{
|
|
25
25
|
protected abstract readonly responseEntries: readonly ResponseEntry[];
|
|
26
26
|
protected abstract readonly expectedStatusCodes: readonly number[];
|
|
@@ -29,9 +29,16 @@ export class ResponseValidator extends Validator {
|
|
|
29
29
|
* @returns A result object containing either the validated response or error details
|
|
30
30
|
*/
|
|
31
31
|
safeValidate(response) {
|
|
32
|
-
const
|
|
32
|
+
const statusCode = typeof response === "object" && response !== null
|
|
33
|
+
? response.statusCode
|
|
34
|
+
: undefined;
|
|
35
|
+
const error = new ResponseValidationError(statusCode);
|
|
36
|
+
if (typeof statusCode !== "number") {
|
|
37
|
+
error.addStatusCodeIssue([...this.expectedStatusCodes]);
|
|
38
|
+
return { isValid: false, error };
|
|
39
|
+
}
|
|
33
40
|
for (const entry of this.responseEntries) {
|
|
34
|
-
if (
|
|
41
|
+
if (statusCode === entry.statusCode) {
|
|
35
42
|
const result = this.validateResponseType(entry.name, entry.headerSchema, entry.bodySchema)(response, error);
|
|
36
43
|
if (result.isValid)
|
|
37
44
|
return result;
|
package/dist/lib/Validator.js
CHANGED
|
@@ -83,7 +83,7 @@ export class Validator {
|
|
|
83
83
|
* @returns Coerced data object with proper key casing and array coercion
|
|
84
84
|
*/
|
|
85
85
|
coerceToSchema(data, shape, caseSensitive) {
|
|
86
|
-
if (typeof data !== "object" || data === null) {
|
|
86
|
+
if (typeof data !== "object" || data === null || Array.isArray(data)) {
|
|
87
87
|
return data;
|
|
88
88
|
}
|
|
89
89
|
const schemaMap = this.analyzeSchema(shape, caseSensitive);
|
|
@@ -160,6 +160,9 @@ export class Validator {
|
|
|
160
160
|
if (typeof header !== "object" || header === null) {
|
|
161
161
|
return this.coerceToSchema(header ?? {}, shape, false);
|
|
162
162
|
}
|
|
163
|
+
if (Array.isArray(header)) {
|
|
164
|
+
return header;
|
|
165
|
+
}
|
|
163
166
|
const preprocessed = this.splitCommaDelimitedValues(header, shape);
|
|
164
167
|
return this.coerceToSchema(preprocessed, shape, false);
|
|
165
168
|
}
|
|
@@ -4,17 +4,19 @@
|
|
|
4
4
|
*
|
|
5
5
|
* @generated by @rexeus/typeweaver
|
|
6
6
|
*/
|
|
7
|
+
import { MissingOperationDefinitionError } from "./errors/MissingOperationDefinitionError.js";
|
|
8
|
+
import { MissingResponseDefinitionError } from "./errors/MissingResponseDefinitionError.js";
|
|
7
9
|
export const getOperationDefinition = (spec, resourceName, operationId) => {
|
|
8
10
|
const operation = spec.resources[resourceName]?.operations.find(candidate => candidate.operationId === operationId);
|
|
9
11
|
if (operation === undefined) {
|
|
10
|
-
throw new
|
|
12
|
+
throw new MissingOperationDefinitionError(String(resourceName), String(operationId));
|
|
11
13
|
}
|
|
12
14
|
return operation;
|
|
13
15
|
};
|
|
14
16
|
export const getResponseDefinition = (responses, responseName) => {
|
|
15
17
|
const response = responses.find(candidate => candidate.name === responseName);
|
|
16
18
|
if (response === undefined) {
|
|
17
|
-
throw new
|
|
19
|
+
throw new MissingResponseDefinitionError(String(responseName));
|
|
18
20
|
}
|
|
19
21
|
return response;
|
|
20
22
|
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file was automatically generated by typeweaver.
|
|
3
|
+
* DO NOT EDIT. Instead, modify the source definition file and generate again.
|
|
4
|
+
*
|
|
5
|
+
* @generated by @rexeus/typeweaver
|
|
6
|
+
*/
|
|
7
|
+
export class MissingOperationDefinitionError extends Error {
|
|
8
|
+
resourceName;
|
|
9
|
+
operationId;
|
|
10
|
+
name = "MissingOperationDefinitionError";
|
|
11
|
+
constructor(resourceName, operationId) {
|
|
12
|
+
super(`Missing operation definition '${resourceName}.${operationId}' in the generated spec runtime.`);
|
|
13
|
+
this.resourceName = resourceName;
|
|
14
|
+
this.operationId = operationId;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file was automatically generated by typeweaver.
|
|
3
|
+
* DO NOT EDIT. Instead, modify the source definition file and generate again.
|
|
4
|
+
*
|
|
5
|
+
* @generated by @rexeus/typeweaver
|
|
6
|
+
*/
|
|
7
|
+
export class MissingResponseDefinitionError extends Error {
|
|
8
|
+
responseName;
|
|
9
|
+
name = "MissingResponseDefinitionError";
|
|
10
|
+
constructor(responseName) {
|
|
11
|
+
super(`Missing response definition '${responseName}' in the generated spec runtime.`);
|
|
12
|
+
this.responseName = responseName;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -24,7 +24,8 @@ export type I<%= pascalCaseOperationId %>RequestQuery = <%- queryTsType %>
|
|
|
24
24
|
export type I<%= pascalCaseOperationId %>RequestBody = <%- bodyTsType %>
|
|
25
25
|
<% } %>
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
<% if (requestJsDoc) { %><%- requestJsDoc %>
|
|
28
|
+
<% } %>export type I<%= pascalCaseOperationId %>Request = {
|
|
28
29
|
path: string;
|
|
29
30
|
method: HttpMethod.<%= method %>;
|
|
30
31
|
<%= headerTsType ? `header: I${pascalCaseOperationId}RequestHeader;` : "" %>
|
|
@@ -32,4 +33,3 @@ export type I<%= pascalCaseOperationId %>Request = {
|
|
|
32
33
|
<%= queryTsType ? `query: I${pascalCaseOperationId}RequestQuery;` : "" %>
|
|
33
34
|
<%= bodyTsType ? `body: I${pascalCaseOperationId}RequestBody;` : "" %>
|
|
34
35
|
};
|
|
35
|
-
|
|
@@ -26,7 +26,8 @@ import type { I<%= entityResponse.identifierName %>Response } from "<%= entityRe
|
|
|
26
26
|
export type I<%= ownResponse.identifierName %>ResponseBody = <%- ownResponse.body %>;
|
|
27
27
|
<% } %>
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
<% if (ownResponse.jsDoc) { %><%- ownResponse.jsDoc.split('\n').map(line => ` ${line}`).join('\n') %>
|
|
30
|
+
<% } %>export type I<%= ownResponse.identifierName %>Response = ITypedHttpResponse<
|
|
30
31
|
"<%= ownResponse.typeValue %>",
|
|
31
32
|
HttpStatusCode.<%= ownResponse.statusCodeKey %>,
|
|
32
33
|
<%= ownResponse.hasHeader ? `I${ownResponse.identifierName}ResponseHeader` : 'undefined' %>,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
<% if (jsDoc) { %><%- jsDoc.split('\n').map(line => `${indentation}${line}`).join('\n') %>
|
|
2
|
+
<% } %><%= indentation %>export const create<%= identifierName %>Response = <% if (hasHeader || hasBody) { %>(
|
|
2
3
|
<%= indentation %>input: {
|
|
3
4
|
<% if (hasHeader) { %><%= indentation %> header: I<%= identifierName %>ResponseHeader;
|
|
4
5
|
<% } %><% if (hasBody) { %><%= indentation %> body: I<%= identifierName %>ResponseBody;
|
|
@@ -17,7 +17,8 @@ import type { ITypedHttpResponse } from "<%= coreDir %>";
|
|
|
17
17
|
export type I<%= identifierName %>ResponseBody = <%- bodyTsType %>;
|
|
18
18
|
<% } %>
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
<% if (jsDoc) { %><%- jsDoc %>
|
|
21
|
+
<% } %>export type I<%= identifierName %>Response = ITypedHttpResponse<
|
|
21
22
|
"<%= typeValue %>",
|
|
22
23
|
HttpStatusCode.<%= statusCodeKey %>,
|
|
23
24
|
<%= hasHeader ? `I${identifierName}ResponseHeader` : 'undefined' %>,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rexeus/typeweaver-types",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.5",
|
|
4
4
|
"description": "Generates request and response types plus validators aligned with your API contract. Powered by Typeweaver 🧵✨",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -47,17 +47,17 @@
|
|
|
47
47
|
},
|
|
48
48
|
"homepage": "https://github.com/rexeus/typeweaver#readme",
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"@rexeus/typeweaver-core": "^0.10.
|
|
51
|
-
"@rexeus/typeweaver-gen": "^0.10.
|
|
50
|
+
"@rexeus/typeweaver-core": "^0.10.5",
|
|
51
|
+
"@rexeus/typeweaver-gen": "^0.10.5"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"test-utils": "file:../test-utils",
|
|
55
|
-
"@rexeus/typeweaver-core": "^0.10.
|
|
56
|
-
"@rexeus/typeweaver-gen": "^0.10.
|
|
55
|
+
"@rexeus/typeweaver-core": "^0.10.5",
|
|
56
|
+
"@rexeus/typeweaver-gen": "^0.10.5"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"polycase": "^1.1.0",
|
|
60
|
-
"@rexeus/typeweaver-zod-to-ts": "^0.10.
|
|
60
|
+
"@rexeus/typeweaver-zod-to-ts": "^0.10.5"
|
|
61
61
|
},
|
|
62
62
|
"scripts": {
|
|
63
63
|
"typecheck": "tsc --noEmit -p tsconfig.typecheck.json",
|