@rexeus/typeweaver-core 0.0.3 โ†’ 0.1.0

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/README.md CHANGED
@@ -1,162 +1,45 @@
1
- # @rexeus/typeweaver-core
1
+ # ๐Ÿงตโœจ @rexeus/typeweaver-core
2
2
 
3
- A TypeScript library for defining type-safe HTTP APIs with runtime validation and code generation
4
- support.
3
+ [![npm version](https://img.shields.io/npm/v/@rexeus/typeweaver-core.svg)](https://www.npmjs.com/package/@rexeus/typeweaver-core)
4
+ [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
5
6
 
6
- ## Features
7
+ Typeweaver is a type-safe HTTP API framework built for API-first development with a focus on
8
+ developer experience. Use typeweaver to specify your HTTP APIs in TypeScript and Zod, and generate
9
+ clients, validators, routers, and more โœจ
7
10
 
8
- - **Type-Safe API Definitions** - Define HTTP operations with complete TypeScript type inference
9
- - **Runtime Validation** - Zod schema integration for request/response validation
10
- - **Framework Adapters** - Support for AWS Lambda, Hono, and other execution contexts
11
- - **Client Generation Ready** - Abstract base classes designed for code generation
12
- - **Route Matching** - Optimized route resolution with parameter support
13
- - **Error Handling** - Structured validation errors with detailed issue reporting
11
+ ## ๐Ÿ“ Core Package
14
12
 
15
- ## Installation
13
+ Core runtime and definition types for typeweaver. This package provides the HTTP primitives,
14
+ definition classes, validators, and error types that all generators and plugins build on. The
15
+ generated code imports these runtime utilities.
16
16
 
17
- ```bash
18
- npm install @rexeus/typeweaver-core
19
- ```
17
+ ---
20
18
 
21
- **Peer Dependencies:**
19
+ ## ๐Ÿ“ฅ Installation
22
20
 
23
21
  ```bash
24
- npm install zod@^3.25.0 axios@^1.9.0 hono@^4.8.0
25
- ```
26
-
27
- > **Important:** This library requires Zod v4 features and imports from `"zod/v4"`. Make sure you
28
- > have a compatible Zod version installed.
29
-
30
- ## Quick Start
31
-
32
- ### Define API Operations
33
-
34
- ```typescript
35
- import { z } from "zod/v4";
36
- import { HttpOperationDefinition, HttpStatusCode, HttpMethod } from "@rexeus/typeweaver-core";
37
- import { accountSchema } from "./accountSchema";
38
- import { sharedResponses } from "../shared/sharedResponses";
39
- import { defaultResponseHeader } from "../shared/defaultResponseHeader";
40
- import { defaultRequestHeadersWithPayload } from "../shared/defaultRequestHeader";
41
-
42
- export default new HttpOperationDefinition({
43
- operationId: "RegisterAccount",
44
- path: "/accounts",
45
- summary: "Register new account",
46
- method: HttpMethod.POST,
47
- request: {
48
- body: z.object({
49
- email: z.email().max(256),
50
- password: z.string().max(256),
51
- }),
52
- header: defaultRequestHeadersWithPayload.omit({
53
- Authorization: true,
54
- }),
55
- },
56
- responses: [
57
- {
58
- statusCode: HttpStatusCode.OK,
59
- description: "Account created successfully",
60
- body: accountSchema,
61
- name: "RegisterAccountSuccess",
62
- header: defaultResponseHeader,
63
- },
64
- ...sharedResponses,
65
- ],
66
- });
67
- ```
68
-
69
- ### Framework Integration
70
-
71
- ```typescript
72
- // AWS Lambda
73
- import { AwsLambdaHandler, AwsLambdaRoute } from "@rexeus/typeweaver-core";
74
-
75
- // Hono
76
- import { HonoHttpRequestHandler, HonoHttpRoute } from "@rexeus/typeweaver-core";
77
- ```
78
-
79
- ## Architecture
80
-
81
- This library provides a foundation for building type-safe APIs with:
82
-
83
- - **Definition Layer** - OpenAPI-style operation definitions with Zod schemas
84
- - **Validation Layer** - Request/response validation with detailed error reporting
85
- - **Router Layer** - Efficient route matching with framework adapters
86
- - **Client Layer** - Abstract base for generating type-safe API clients
87
-
88
- ## Key Benefits
89
-
90
- ### Type Safety
91
-
92
- Complete end-to-end type safety from API definition to runtime execution.
93
-
94
- ### Runtime Validation
95
-
96
- Zod schemas provide both TypeScript types and runtime validation.
97
-
98
- ### Code Generation Ready
99
-
100
- Abstract patterns designed for generating API clients and servers.
101
-
102
- ### Performance Optimized
103
-
104
- Route matching uses preprocessing and caching for O(n) performance.
105
-
106
- ### Framework Agnostic
107
-
108
- Core definitions work with any execution context via adapter pattern.
109
-
110
- ## Framework Adapters
111
-
112
- TypeWeaver Core includes adapters for various runtime environments:
113
-
114
- ### AWS Lambda Adapters
115
-
116
- ```typescript
117
- import {
118
- createAwsLambdaHandler,
119
- createAwsApiGatewayV1Handler,
120
- createAwsApiGatewayV2Handler,
121
- createAwsLambdaFunctionUrlHandler,
122
- createAwsAlbHandler
123
- } from "@rexeus/typeweaver-core";
124
- ```
125
-
126
- ### Hono Integration
127
-
128
- ```typescript
129
- import {
130
- createHonoHttpApiHandler,
131
- HonoHttpRouter
132
- } from "@rexeus/typeweaver-core";
22
+ npm install @rexeus/typeweaver-core
133
23
  ```
134
24
 
135
- ### Generic HTTP Adapters
25
+ ## ๐Ÿ’ก How to use
136
26
 
137
- ```typescript
138
- import {
139
- HttpAdapter,
140
- FetchApiAdapter
141
- } from "@rexeus/typeweaver-core";
142
- ```
27
+ This package is typically consumed by generated code. You can also import HTTP primitives (e.g.,
28
+ `HttpResponse`, `HttpStatusCode`) directly in your application code. To get started with generation,
29
+ see [@rexeus/typeweaver](https://github.com/rexeus/typeweaver/tree/main/packages/cli/README.md).
143
30
 
144
- ## Validation System
31
+ ## ๐Ÿ”ง What It Provides
145
32
 
146
- Comprehensive request and response validation with structured error handling:
33
+ - HTTP primitives: `HttpMethod`, `HttpStatusCode`, `IHttpRequest`, `IHttpResponse`, `HttpResponse`.
34
+ - Definitions: `HttpOperationDefinition`, `HttpRequestDefinition`, `HttpResponseDefinition` (incl.
35
+ `extend()` for composing headers/bodies).
36
+ - Validation: `IRequestValidator`, `IResponseValidator`, plus `RequestValidationError` and
37
+ `ResponseValidationError` with structured issues.
38
+ - Utilities: `UnknownResponse` for catchโ€‘all responses.
147
39
 
148
- ```typescript
149
- import {
150
- RequestValidator,
151
- ResponseValidator,
152
- RequestValidationError,
153
- ResponseValidationError
154
- } from "@rexeus/typeweaver-core";
40
+ This package does not ship framework adapters. Use plugins like `@rexeus/typeweaver-hono` or
41
+ `@rexeus/typeweaver-aws-cdk` for routers/integrations.
155
42
 
156
- const validator = new RequestValidator(operationDefinition);
157
- const result = validator.safeValidate(request);
43
+ ## ๐Ÿ“„ License
158
44
 
159
- if (!result.isValid) {
160
- console.error(result.error.issues);
161
- }
162
- ```
45
+ Apache 2.0 ยฉ Dennis Wentzien 2025
package/dist/LICENSE ADDED
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright 2025 Dennis Wentzien
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
package/dist/NOTICE ADDED
@@ -0,0 +1,4 @@
1
+ Copyright 2025 Dennis Wentzien
2
+
3
+ This project is licensed under the Apache License, Version 2.0
4
+ See LICENSE file for details.
package/dist/index.d.ts CHANGED
@@ -1,19 +1,12 @@
1
- import { ZodObject, ZodString, ZodStringFormat, ZodLiteral, ZodEnum, ZodOptional, ZodArray, ZodType, z } from 'zod/v4';
2
-
3
- type IHttpHeader = Record<string, string | string[]> | undefined;
4
- type HttpHeaderValue = ZodString | ZodStringFormat | ZodLiteral<string> | ZodEnum<Record<string, string>>;
5
- type HttpHeaderSchema = ZodObject<Record<string, HttpHeaderValue | ZodOptional<HttpHeaderValue> | ZodArray<HttpHeaderValue> | ZodOptional<ZodArray<HttpHeaderValue>>>>;
6
-
7
- type IHttpParam = Record<string, string> | undefined;
8
- type HttpParamValue = ZodString | ZodStringFormat | ZodLiteral<string> | ZodEnum<Record<string, string>>;
9
- type HttpParamSchema = ZodObject<Record<string, HttpParamValue | ZodOptional<HttpParamValue>>>;
1
+ import { ZodType, ZodObject, ZodString, ZodStringFormat, ZodLiteral, ZodEnum, ZodOptional, ZodArray } from 'zod';
2
+ import { $ZodIssue } from 'zod/v4/core';
10
3
 
11
4
  type IHttpBody = any | undefined;
12
5
  type HttpBodySchema = ZodType;
13
6
 
14
- type IHttpQuery = Record<string, string | string[]> | undefined;
15
- type HttpQueryValue = ZodString | ZodStringFormat | ZodLiteral<string> | ZodEnum<Record<string, string>>;
16
- type HttpQuerySchema = ZodObject<Record<string, HttpQueryValue | ZodOptional<HttpQueryValue> | ZodArray<HttpQueryValue> | ZodOptional<ZodArray<HttpQueryValue>>>>;
7
+ type IHttpHeader = Record<string, string | string[]> | undefined;
8
+ type HttpHeaderValue = ZodString | ZodStringFormat | ZodLiteral<string> | ZodEnum<Record<string, string>>;
9
+ type HttpHeaderSchema = ZodObject<Record<string, HttpHeaderValue | ZodOptional<HttpHeaderValue> | ZodArray<HttpHeaderValue> | ZodOptional<ZodArray<HttpHeaderValue>>>>;
17
10
 
18
11
  declare enum HttpMethod {
19
12
  GET = "GET",
@@ -22,11 +15,17 @@ declare enum HttpMethod {
22
15
  DELETE = "DELETE",
23
16
  PATCH = "PATCH",
24
17
  OPTIONS = "OPTIONS",
25
- HEAD = "HEAD",
26
- TRACE = "TRACE",
27
- CONNECT = "CONNECT"
18
+ HEAD = "HEAD"
28
19
  }
29
20
 
21
+ type IHttpParam = Record<string, string> | undefined;
22
+ type HttpParamValue = ZodString | ZodStringFormat | ZodLiteral<string> | ZodEnum<Record<string, string>>;
23
+ type HttpParamSchema = ZodObject<Record<string, HttpParamValue>>;
24
+
25
+ type IHttpQuery = Record<string, string | string[]> | undefined;
26
+ type HttpQueryValue = ZodString | ZodStringFormat | ZodLiteral<string> | ZodEnum<Record<string, string>>;
27
+ type HttpQuerySchema = ZodObject<Record<string, HttpQueryValue | ZodOptional<HttpQueryValue> | ZodArray<HttpQueryValue> | ZodOptional<ZodArray<HttpQueryValue>>>>;
28
+
30
29
  type IHttpRequest<Header extends IHttpHeader = IHttpHeader, Param extends IHttpParam = IHttpParam, Query extends IHttpQuery = IHttpQuery, Body extends IHttpBody = IHttpBody> = {
31
30
  body?: Body;
32
31
  query?: Query;
@@ -115,15 +114,14 @@ declare class HttpRequestDefinition<THeader extends HttpHeaderSchema | undefined
115
114
  constructor(definition: IHttpRequestDefinition<THeader, TParam, TQuery, TBody>);
116
115
  }
117
116
 
118
- type IHttpResponseDefinition<TName extends string = string, TStatusCode extends HttpStatusCode = HttpStatusCode, TDescription extends string = string, THeader extends HttpHeaderSchema | undefined = HttpHeaderSchema | undefined, TBody extends HttpBodySchema | undefined = HttpBodySchema | undefined, TIsShared extends boolean = boolean> = {
117
+ type IHttpResponseDefinition<TName extends string = string, TStatusCode extends HttpStatusCode = HttpStatusCode, TDescription extends string = string, THeader extends HttpHeaderSchema | undefined = HttpHeaderSchema | undefined, TBody extends HttpBodySchema | undefined = HttpBodySchema | undefined> = {
119
118
  name: TName;
120
119
  statusCode: TStatusCode;
121
120
  description: TDescription;
122
121
  header?: THeader;
123
122
  body?: TBody;
124
- isShared?: TIsShared;
125
123
  };
126
- type IExtendHttpResponseDefinition<TName extends string, TStatusCode extends HttpStatusCode, TDescription extends string, THeader extends HttpHeaderSchema | undefined, TBody extends HttpBodySchema | undefined, TIsShared extends boolean> = Partial<IHttpResponseDefinition<TName, TStatusCode, TDescription, THeader, TBody, TIsShared>> & Pick<IHttpResponseDefinition<TName, TStatusCode, TDescription, THeader, TBody, TIsShared>, "name">;
124
+ type IExtendHttpResponseDefinition<TName extends string, TStatusCode extends HttpStatusCode, TDescription extends string, THeader extends HttpHeaderSchema | undefined, TBody extends HttpBodySchema | undefined> = Partial<IHttpResponseDefinition<TName, TStatusCode, TDescription, THeader, TBody>> & Pick<IHttpResponseDefinition<TName, TStatusCode, TDescription, THeader, TBody>, "name">;
127
125
  declare class HttpResponseDefinition<TName extends string, TStatusCode extends HttpStatusCode, TDescription extends string, THeader extends HttpHeaderSchema | undefined, TBody extends HttpBodySchema | undefined, TIsShared extends boolean> {
128
126
  private definition;
129
127
  name: TName;
@@ -131,9 +129,8 @@ declare class HttpResponseDefinition<TName extends string, TStatusCode extends H
131
129
  description: TDescription;
132
130
  header?: THeader;
133
131
  body?: TBody;
134
- isShared?: TIsShared;
135
- constructor(definition: IHttpResponseDefinition<TName, TStatusCode, TDescription, THeader, TBody, TIsShared>);
136
- extend<EName extends string, EStatusCode extends HttpStatusCode = TStatusCode, EDescription extends string = TDescription, EHeader extends HttpHeaderSchema | undefined = THeader, EBody extends HttpBodySchema | undefined = TBody, EIsShared extends boolean = TIsShared>(definition: IExtendHttpResponseDefinition<EName, EStatusCode, EDescription, EHeader, EBody, EIsShared>): HttpResponseDefinition<EName, EStatusCode, EDescription, THeader extends undefined ? EHeader : EHeader extends undefined ? THeader : THeader & EHeader, TBody extends undefined ? EBody : EBody extends undefined ? TBody : TBody & EBody, EIsShared>;
132
+ constructor(definition: IHttpResponseDefinition<TName, TStatusCode, TDescription, THeader, TBody>);
133
+ extend<EName extends string, EStatusCode extends HttpStatusCode = TStatusCode, EDescription extends string = TDescription, EHeader extends HttpHeaderSchema | undefined = THeader, EBody extends HttpBodySchema | undefined = TBody, EIsShared extends boolean = TIsShared>(definition: IExtendHttpResponseDefinition<EName, EStatusCode, EDescription, EHeader, EBody>): HttpResponseDefinition<EName, EStatusCode, EDescription, THeader extends undefined ? EHeader : EHeader extends undefined ? THeader : THeader & EHeader, TBody extends undefined ? EBody : EBody extends undefined ? TBody : TBody & EBody, EIsShared>;
137
134
  }
138
135
 
139
136
  /**
@@ -202,13 +199,13 @@ declare class HttpOperationDefinition<TOperationId extends string, TPath extends
202
199
  */
203
200
  type RequestValidationErrorInput = {
204
201
  /** Validation issues found in HTTP headers */
205
- headerIssues?: z.core.$ZodRawIssue[];
202
+ headerIssues?: $ZodIssue[];
206
203
  /** Validation issues found in request body */
207
- bodyIssues?: z.core.$ZodRawIssue[];
204
+ bodyIssues?: $ZodIssue[];
208
205
  /** Validation issues found in query parameters */
209
- queryIssues?: z.core.$ZodRawIssue[];
206
+ queryIssues?: $ZodIssue[];
210
207
  /** Validation issues found in path parameters */
211
- pathParamIssues?: z.core.$ZodRawIssue[];
208
+ pathParamIssues?: $ZodIssue[];
212
209
  };
213
210
  /**
214
211
  * Error thrown when HTTP request validation fails.
@@ -223,34 +220,34 @@ type RequestValidationErrorInput = {
223
220
  declare class RequestValidationError extends Error {
224
221
  readonly message: string;
225
222
  /** Validation issues found in HTTP headers */
226
- readonly headerIssues: z.core.$ZodRawIssue[];
223
+ readonly headerIssues: $ZodIssue[];
227
224
  /** Validation issues found in request body */
228
- readonly bodyIssues: z.core.$ZodRawIssue[];
225
+ readonly bodyIssues: $ZodIssue[];
229
226
  /** Validation issues found in query parameters */
230
- readonly queryIssues: z.core.$ZodRawIssue[];
227
+ readonly queryIssues: $ZodIssue[];
231
228
  /** Validation issues found in path parameters */
232
- readonly pathParamIssues: z.core.$ZodRawIssue[];
229
+ readonly pathParamIssues: $ZodIssue[];
233
230
  constructor(input?: RequestValidationErrorInput);
234
231
  /**
235
232
  * Adds header validation issues to the error.
236
233
  * @param issues - Array of Zod validation issues
237
234
  */
238
- addHeaderIssues(issues: z.core.$ZodRawIssue[]): void;
235
+ addHeaderIssues(issues: $ZodIssue[]): void;
239
236
  /**
240
237
  * Adds body validation issues to the error.
241
238
  * @param issues - Array of Zod validation issues
242
239
  */
243
- addBodyIssues(issues: z.core.$ZodRawIssue[]): void;
240
+ addBodyIssues(issues: $ZodIssue[]): void;
244
241
  /**
245
242
  * Adds query parameter validation issues to the error.
246
243
  * @param issues - Array of Zod validation issues
247
244
  */
248
- addQueryIssues(issues: z.core.$ZodRawIssue[]): void;
245
+ addQueryIssues(issues: $ZodIssue[]): void;
249
246
  /**
250
247
  * Adds path parameter validation issues to the error.
251
248
  * @param issues - Array of Zod validation issues
252
249
  */
253
- addPathParamIssues(issues: z.core.$ZodRawIssue[]): void;
250
+ addPathParamIssues(issues: $ZodIssue[]): void;
254
251
  /**
255
252
  * Checks if this error contains any validation issues.
256
253
  * @returns true if any category has issues, false otherwise
@@ -283,28 +280,44 @@ type IRequestValidator = {
283
280
  validate(request: IHttpRequest): IHttpRequest;
284
281
  };
285
282
 
283
+ type InvalidResponseIssue = {
284
+ readonly type: "INVALID_RESPONSE";
285
+ readonly responseName: string;
286
+ readonly headerIssues: $ZodIssue[];
287
+ readonly bodyIssues: $ZodIssue[];
288
+ };
289
+ type InvalidStatusCodeIssue = {
290
+ readonly type: "INVALID_STATUS_CODE";
291
+ readonly invalidStatusCode: HttpStatusCode;
292
+ readonly expectedStatusCodes: HttpStatusCode[];
293
+ };
294
+ type ValidationIssue = InvalidResponseIssue | InvalidStatusCodeIssue;
286
295
  type ResponseValidationErrorInput = {
287
- headerIssues?: z.core.$ZodRawIssue[];
288
- bodyIssues?: z.core.$ZodRawIssue[];
296
+ readonly issues?: ValidationIssue[];
289
297
  };
290
298
  declare class ResponseValidationError extends Error {
291
299
  readonly statusCode: HttpStatusCode;
292
300
  readonly message: string;
293
- readonly headerIssues: z.core.$ZodRawIssue[];
294
- readonly bodyIssues: z.core.$ZodRawIssue[];
301
+ readonly issues: ValidationIssue[];
295
302
  constructor(statusCode: HttpStatusCode, input?: ResponseValidationErrorInput);
296
- addHeaderIssues(issues: z.core.$ZodRawIssue[]): void;
297
- addBodyIssues(issues: z.core.$ZodRawIssue[]): void;
303
+ addHeaderIssues(responseName: string, issues: $ZodIssue[]): void;
304
+ addBodyIssues(responseName: string, issues: $ZodIssue[]): void;
305
+ addResponseIssues(responseName: string, headerIssues?: $ZodIssue[], bodyIssues?: $ZodIssue[]): void;
306
+ addStatusCodeIssue(expectedStatusCodes: HttpStatusCode[]): void;
307
+ getResponseHeaderIssues(responseName: string): $ZodIssue[];
308
+ getResponseBodyIssues(responseName: string): $ZodIssue[];
309
+ hasResponseIssues(responseName?: string | undefined): boolean;
310
+ hasStatusCodeIssues(): boolean;
298
311
  hasIssues(): boolean;
299
312
  }
300
313
 
301
314
  type ValidationSuccessResult<T> = {
302
- isValid: true;
303
- data: T;
315
+ readonly isValid: true;
316
+ readonly data: T;
304
317
  };
305
318
  type ValidationFailureResult = {
306
- isValid: false;
307
- error: ResponseValidationError;
319
+ readonly isValid: false;
320
+ readonly error: ResponseValidationError;
308
321
  };
309
322
  type SafeResponseValidationResult<T> = ValidationSuccessResult<T> | ValidationFailureResult;
310
323
  /**
@@ -323,4 +336,10 @@ type IResponseValidator = {
323
336
  validate(response: IHttpResponse): IHttpResponse;
324
337
  };
325
338
 
326
- export { type HttpBodySchema, type HttpHeaderSchema, HttpMethod, HttpOperationDefinition, type HttpParamSchema, type HttpQuerySchema, HttpRequestDefinition, HttpResponse, HttpResponseDefinition, HttpStatusCode, HttpStatusCodeNameMap, type IExtendHttpResponseDefinition, type IHttpBody, type IHttpHeader, type IHttpOperationDefinition, type IHttpParam, type IHttpQuery, type IHttpRequest, type IHttpRequestDefinition, type IHttpResponse, type IHttpResponseDefinition, type IRequestValidator, type IResponseValidator, RequestValidationError, type RequestValidationErrorInput, ResponseValidationError, type ResponseValidationErrorInput, type SafeRequestValidationResult, type SafeResponseValidationResult };
339
+ declare class UnknownResponse<Header extends IHttpHeader = IHttpHeader, Body extends IHttpBody = unknown> extends HttpResponse<Header, Body> {
340
+ readonly validationError: ResponseValidationError;
341
+ constructor(statusCode: HttpStatusCode, header: Header, body: Body, validationError: ResponseValidationError);
342
+ }
343
+
344
+ export { HttpMethod, HttpOperationDefinition, HttpRequestDefinition, HttpResponse, HttpResponseDefinition, HttpStatusCode, HttpStatusCodeNameMap, RequestValidationError, ResponseValidationError, UnknownResponse };
345
+ export type { HttpBodySchema, HttpHeaderSchema, HttpParamSchema, HttpQuerySchema, IExtendHttpResponseDefinition, IHttpBody, IHttpHeader, IHttpOperationDefinition, IHttpParam, IHttpQuery, IHttpRequest, IHttpRequestDefinition, IHttpResponse, IHttpResponseDefinition, IRequestValidator, IResponseValidator, InvalidResponseIssue, InvalidStatusCodeIssue, RequestValidationErrorInput, ResponseValidationErrorInput, SafeRequestValidationResult, SafeResponseValidationResult, ValidationIssue };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import z from 'zod/v4';
1
+ import { z } from 'zod';
2
2
 
3
3
  var HttpStatusCode = /* @__PURE__ */ ((HttpStatusCode2) => {
4
4
  HttpStatusCode2[HttpStatusCode2["OK"] = 200] = "OK";
@@ -118,8 +118,6 @@ var HttpMethod = /* @__PURE__ */ ((HttpMethod2) => {
118
118
  HttpMethod2["PATCH"] = "PATCH";
119
119
  HttpMethod2["OPTIONS"] = "OPTIONS";
120
120
  HttpMethod2["HEAD"] = "HEAD";
121
- HttpMethod2["TRACE"] = "TRACE";
122
- HttpMethod2["CONNECT"] = "CONNECT";
123
121
  return HttpMethod2;
124
122
  })(HttpMethod || {});
125
123
 
@@ -161,14 +159,12 @@ class HttpResponseDefinition {
161
159
  this.description = definition.description;
162
160
  this.header = definition.header;
163
161
  this.body = definition.body;
164
- this.isShared = definition.isShared;
165
162
  }
166
163
  name;
167
164
  statusCode;
168
165
  description;
169
166
  header;
170
167
  body;
171
- isShared;
172
168
  extend(definition) {
173
169
  const mergedHeader = (() => {
174
170
  if (!this.header && !definition.header) return void 0;
@@ -196,7 +192,6 @@ class HttpResponseDefinition {
196
192
  name: definition.name,
197
193
  statusCode: definition.statusCode ?? this.statusCode,
198
194
  description: definition.description ?? this.description,
199
- isShared: definition.isShared ?? this.isShared,
200
195
  header: mergedHeader,
201
196
  body: mergedBody
202
197
  };
@@ -270,29 +265,90 @@ class RequestValidationError extends Error {
270
265
 
271
266
  class ResponseValidationError extends Error {
272
267
  constructor(statusCode, input) {
273
- const message = `Invalid response for status code '${statusCode}'`;
268
+ const message = `Response validation failed for status code '${statusCode}'`;
274
269
  super(message);
275
270
  this.statusCode = statusCode;
276
271
  this.message = message;
277
- if (input?.headerIssues) {
278
- this.headerIssues = input.headerIssues;
272
+ this.issues = input?.issues ?? [];
273
+ }
274
+ message;
275
+ issues;
276
+ addHeaderIssues(responseName, issues) {
277
+ this.addResponseIssues(responseName, issues);
278
+ }
279
+ addBodyIssues(responseName, issues) {
280
+ this.addResponseIssues(responseName, [], issues);
281
+ }
282
+ addResponseIssues(responseName, headerIssues = [], bodyIssues = []) {
283
+ if (headerIssues.length === 0 && bodyIssues.length === 0) {
284
+ return;
279
285
  }
280
- if (input?.bodyIssues) {
281
- this.bodyIssues = input.bodyIssues;
286
+ const issue = this.issues.find(
287
+ (i) => i.type === "INVALID_RESPONSE" && i.responseName === responseName
288
+ );
289
+ if (!issue) {
290
+ this.issues.push({
291
+ type: "INVALID_RESPONSE",
292
+ responseName,
293
+ headerIssues,
294
+ bodyIssues
295
+ });
296
+ return;
297
+ }
298
+ if (headerIssues.length > 0) {
299
+ issue.headerIssues.push(...headerIssues);
300
+ }
301
+ if (bodyIssues.length > 0) {
302
+ issue.bodyIssues.push(...bodyIssues);
282
303
  }
283
304
  }
284
- message;
285
- headerIssues = [];
286
- bodyIssues = [];
287
- addHeaderIssues(issues) {
288
- this.headerIssues.push(...issues);
305
+ addStatusCodeIssue(expectedStatusCodes) {
306
+ const statusCodeIssue = this.issues.find(
307
+ (i) => i.type === "INVALID_STATUS_CODE"
308
+ );
309
+ if (statusCodeIssue) {
310
+ statusCodeIssue.expectedStatusCodes.push(...expectedStatusCodes);
311
+ } else {
312
+ this.issues.push({
313
+ type: "INVALID_STATUS_CODE",
314
+ invalidStatusCode: this.statusCode,
315
+ expectedStatusCodes
316
+ });
317
+ }
289
318
  }
290
- addBodyIssues(issues) {
291
- this.bodyIssues.push(...issues);
319
+ getResponseHeaderIssues(responseName) {
320
+ const issue = this.issues.find(
321
+ (i) => i.type === "INVALID_RESPONSE" && i.responseName === responseName
322
+ );
323
+ return issue ? issue.headerIssues : [];
324
+ }
325
+ getResponseBodyIssues(responseName) {
326
+ const issue = this.issues.find(
327
+ (i) => i.type === "INVALID_RESPONSE" && i.responseName === responseName
328
+ );
329
+ return issue ? issue.bodyIssues : [];
330
+ }
331
+ hasResponseIssues(responseName) {
332
+ if (responseName) {
333
+ return this.issues.some(
334
+ (issue) => issue.type === "INVALID_RESPONSE" && issue.responseName === responseName
335
+ );
336
+ }
337
+ return this.issues.some((issue) => issue.type === "INVALID_RESPONSE");
338
+ }
339
+ hasStatusCodeIssues() {
340
+ return this.issues.some((issue) => issue.type === "INVALID_STATUS_CODE");
292
341
  }
293
342
  hasIssues() {
294
- return this.headerIssues.length > 0 || this.bodyIssues.length > 0;
343
+ return this.issues.length > 0;
344
+ }
345
+ }
346
+
347
+ class UnknownResponse extends HttpResponse {
348
+ constructor(statusCode, header, body, validationError) {
349
+ super(statusCode, header, body);
350
+ this.validationError = validationError;
295
351
  }
296
352
  }
297
353
 
298
- export { HttpMethod, HttpOperationDefinition, HttpRequestDefinition, HttpResponse, HttpResponseDefinition, HttpStatusCode, HttpStatusCodeNameMap, RequestValidationError, ResponseValidationError };
354
+ export { HttpMethod, HttpOperationDefinition, HttpRequestDefinition, HttpResponse, HttpResponseDefinition, HttpStatusCode, HttpStatusCodeNameMap, RequestValidationError, ResponseValidationError, UnknownResponse };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rexeus/typeweaver-core",
3
- "version": "0.0.3",
4
- "description": "Core TypeScript and Zod utilities for TypeWeaver API framework",
3
+ "version": "0.1.0",
4
+ "description": "Core TypeScript and Zod utilities for typeweaver API framework",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -14,7 +14,9 @@
14
14
  "files": [
15
15
  "dist",
16
16
  "package.json",
17
- "README.md"
17
+ "README.md",
18
+ "LICENSE",
19
+ "NOTICE"
18
20
  ],
19
21
  "keywords": [
20
22
  "api",
@@ -26,7 +28,7 @@
26
28
  "typeweaver"
27
29
  ],
28
30
  "author": "Dennis Wentzien <dw@rexeus.com>",
29
- "license": "ISC",
31
+ "license": "Apache-2.0",
30
32
  "repository": {
31
33
  "type": "git",
32
34
  "url": "git+https://github.com/rexeus/typeweaver.git",
@@ -37,15 +39,15 @@
37
39
  },
38
40
  "homepage": "https://github.com/rexeus/typeweaver#readme",
39
41
  "peerDependencies": {
40
- "zod": "^3.25.67"
42
+ "zod": "^4.1.5"
41
43
  },
42
44
  "devDependencies": {
43
- "zod": "^3.25.67"
45
+ "zod": "^4.1.5"
44
46
  },
45
47
  "scripts": {
46
48
  "typecheck": "tsc --noEmit",
47
49
  "format": "prettier --write .",
48
- "build": "pkgroll --clean-dist",
50
+ "build": "pkgroll --clean-dist && cp ../../LICENSE ../../NOTICE ./dist/",
49
51
  "preversion": "npm run build"
50
52
  }
51
53
  }