@rexeus/typeweaver-types 0.0.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/README.md ADDED
@@ -0,0 +1,483 @@
1
+ # @rexeus/typeweaver-types
2
+
3
+ TypeScript type and Zod validator generators for TypeWeaver APIs.
4
+
5
+ ## Overview
6
+
7
+ This plugin generates TypeScript types and Zod validators from your TypeWeaver API definitions,
8
+ providing the foundation for type-safe API development. This is the core plugin that's included by
9
+ default in TypeWeaver.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install @rexeus/typeweaver-types
15
+ ```
16
+
17
+ **Peer Dependencies:**
18
+
19
+ ```bash
20
+ npm install @rexeus/typeweaver-core @rexeus/typeweaver-gen
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ This plugin is included by default and doesn't need to be explicitly specified:
26
+
27
+ ```bash
28
+ npx typeweaver generate --input ./api/definitions --output ./api/generated
29
+ ```
30
+
31
+ You can also explicitly include it with other plugins:
32
+
33
+ ```bash
34
+ npx typeweaver generate --input ./api/definitions --output ./api/generated --plugins types,clients,aws-cdk
35
+ ```
36
+
37
+ ## Generated Output
38
+
39
+ This plugin generates comprehensive TypeScript types and validators for each API operation.
40
+
41
+ ### Generated Files per Operation
42
+
43
+ For each operation (e.g., `GetUser`), the plugin generates:
44
+
45
+ 1. **Request Types** (`GetUserRequest.ts`)
46
+ 2. **Response Types** (`GetUserResponse.ts`)
47
+ 3. **Request Validators** (`GetUserRequestValidator.ts`)
48
+ 4. **Response Validators** (`GetUserResponseValidator.ts`)
49
+
50
+ ### Shared Response Types
51
+
52
+ For shared error responses, generates:
53
+
54
+ - **Shared Response Types** (in `shared/` directory)
55
+
56
+ ## Example Generated Code
57
+
58
+ ### Request Types
59
+
60
+ ```typescript
61
+ // GetUserRequest.ts
62
+ import { HttpRequest } from "@rexeus/typeweaver-core";
63
+ import { z } from "zod/v4";
64
+
65
+ export const GetUserRequestSchema = z.object({
66
+ param: z.object({
67
+ userId: z.string().uuid(),
68
+ }),
69
+ header: z
70
+ .object({
71
+ Authorization: z.string(),
72
+ Accept: z.literal("application/json"),
73
+ })
74
+ .optional(),
75
+ });
76
+
77
+ export type GetUserRequest = z.infer<typeof GetUserRequestSchema>;
78
+
79
+ export interface IGetUserRequest extends HttpRequest {
80
+ param: {
81
+ userId: string;
82
+ };
83
+ header?: {
84
+ Authorization: string;
85
+ Accept: "application/json";
86
+ };
87
+ }
88
+
89
+ export class GetUserRequestCommand {
90
+ constructor(public readonly data: IGetUserRequest) {
91
+ GetUserRequestSchema.parse(data);
92
+ }
93
+ }
94
+ ```
95
+
96
+ ### Response Types
97
+
98
+ ```typescript
99
+ // GetUserResponse.ts
100
+ import { HttpResponse } from "@rexeus/typeweaver-core";
101
+ import { z } from "zod/v4";
102
+
103
+ // Success Response
104
+ export const GetUserSuccessResponseSchema = z.object({
105
+ statusCode: z.literal(200),
106
+ header: z.object({
107
+ "Content-Type": z.literal("application/json"),
108
+ }),
109
+ body: z.object({
110
+ id: z.string().uuid(),
111
+ name: z.string(),
112
+ email: z.string().email(),
113
+ }),
114
+ });
115
+
116
+ export type GetUserSuccessResponse = z.infer<typeof GetUserSuccessResponseSchema>;
117
+
118
+ // Error Responses
119
+ export type GetUserErrorResponse =
120
+ | UserNotFoundErrorResponse
121
+ | ValidationErrorResponse
122
+ | InternalServerErrorResponse;
123
+
124
+ // Union Type
125
+ export type GetUserResponse = GetUserSuccessResponse | GetUserErrorResponse;
126
+
127
+ export interface IGetUserResponse extends HttpResponse {
128
+ statusCode: 200 | 404 | 400 | 500;
129
+ header: {
130
+ "Content-Type": "application/json";
131
+ };
132
+ body:
133
+ | {
134
+ id: string;
135
+ name: string;
136
+ email: string;
137
+ }
138
+ | {
139
+ message: string;
140
+ code: string;
141
+ };
142
+ }
143
+ ```
144
+
145
+ ### Request Validators
146
+
147
+ ```typescript
148
+ // GetUserRequestValidator.ts
149
+ import { RequestValidator } from "@rexeus/typeweaver-core";
150
+ import { GetUserRequestSchema } from "./GetUserRequest";
151
+
152
+ export class GetUserRequestValidator extends RequestValidator<typeof GetUserRequestSchema> {
153
+ constructor() {
154
+ super(GetUserRequestSchema);
155
+ }
156
+
157
+ public validate(request: unknown): GetUserRequest {
158
+ return this.schema.parse(request);
159
+ }
160
+
161
+ public safeValidate(request: unknown): SafeParseResult<GetUserRequest> {
162
+ return this.schema.safeParse(request);
163
+ }
164
+ }
165
+ ```
166
+
167
+ ### Response Validators
168
+
169
+ ```typescript
170
+ // GetUserResponseValidator.ts
171
+ import { ResponseValidator } from "@rexeus/typeweaver-core";
172
+ import { GetUserResponse } from "./GetUserResponse";
173
+
174
+ export class GetUserResponseValidator extends ResponseValidator {
175
+ public validate(response: unknown): GetUserResponse {
176
+ const statusCode = (response as any)?.statusCode;
177
+
178
+ switch (statusCode) {
179
+ case 200:
180
+ return this.validateSuccessResponse(response);
181
+ case 404:
182
+ return this.validateUserNotFoundError(response);
183
+ case 400:
184
+ return this.validateValidationError(response);
185
+ case 500:
186
+ return this.validateInternalServerError(response);
187
+ default:
188
+ throw new ResponseValidationError(`Unexpected status code: ${statusCode}`);
189
+ }
190
+ }
191
+
192
+ private validateSuccessResponse(response: unknown): GetUserSuccessResponse {
193
+ return GetUserSuccessResponseSchema.parse(response);
194
+ }
195
+
196
+ // ... other validation methods
197
+ }
198
+ ```
199
+
200
+ ## Type Features
201
+
202
+ ### Complete Type Safety
203
+
204
+ - **Request Types** - Fully typed request interfaces
205
+ - **Response Types** - Union types for all possible responses
206
+ - **Parameter Types** - Path, query, header, and body parameters
207
+ - **Validation Types** - Runtime validation with Zod schemas
208
+
209
+ ### Zod Integration
210
+
211
+ - **Schema Generation** - Automatic Zod schema creation
212
+ - **Runtime Validation** - Type-safe validation at runtime
213
+ - **Error Handling** - Structured validation errors
214
+ - **Type Inference** - TypeScript types inferred from Zod schemas
215
+
216
+ ### Error Response Handling
217
+
218
+ ```typescript
219
+ // Shared error responses are reused across operations
220
+ export type UserNotFoundErrorResponse = {
221
+ statusCode: 404;
222
+ body: {
223
+ message: "User not found";
224
+ code: "USER_NOT_FOUND";
225
+ userId: string;
226
+ };
227
+ };
228
+
229
+ // Operation-specific error handling
230
+ export type GetUserErrorResponse =
231
+ | UserNotFoundErrorResponse
232
+ | ValidationErrorResponse
233
+ | InternalServerErrorResponse;
234
+ ```
235
+
236
+ ## Usage Examples
237
+
238
+ ### Request Validation
239
+
240
+ ```typescript
241
+ import { GetUserRequestValidator } from "./api/generated";
242
+
243
+ const validator = new GetUserRequestValidator();
244
+
245
+ try {
246
+ const validatedRequest = validator.validate({
247
+ param: { userId: "123e4567-e89b-12d3-a456-426614174000" },
248
+ header: { Authorization: "Bearer token" },
249
+ });
250
+
251
+ // validatedRequest is fully typed
252
+ console.log(validatedRequest.param.userId);
253
+ } catch (error) {
254
+ console.error("Validation failed:", error.issues);
255
+ }
256
+ ```
257
+
258
+ ### Response Validation
259
+
260
+ ```typescript
261
+ import { GetUserResponseValidator } from "./api/generated";
262
+
263
+ const validator = new GetUserResponseValidator();
264
+
265
+ try {
266
+ const validatedResponse = validator.validate({
267
+ statusCode: 200,
268
+ header: { "Content-Type": "application/json" },
269
+ body: { id: "123", name: "John", email: "john@example.com" },
270
+ });
271
+
272
+ // Response is typed based on status code
273
+ if (validatedResponse.statusCode === 200) {
274
+ console.log(validatedResponse.body.name); // Type-safe access
275
+ }
276
+ } catch (error) {
277
+ console.error("Response validation failed:", error);
278
+ }
279
+ ```
280
+
281
+ ### Type Guards
282
+
283
+ ```typescript
284
+ import { GetUserResponse } from "./api/generated";
285
+
286
+ function isSuccessResponse(response: GetUserResponse): response is GetUserSuccessResponse {
287
+ return response.statusCode === 200;
288
+ }
289
+
290
+ function handleResponse(response: GetUserResponse) {
291
+ if (isSuccessResponse(response)) {
292
+ // TypeScript knows this is a success response
293
+ console.log(response.body.name);
294
+ } else {
295
+ // TypeScript knows this is an error response
296
+ console.error(response.body.message);
297
+ }
298
+ }
299
+ ```
300
+
301
+ ## Integration with Other Plugins
302
+
303
+ ### With Clients Plugin
304
+
305
+ The types plugin provides the foundation for type-safe clients:
306
+
307
+ ```typescript
308
+ // Generated by types plugin
309
+ import { GetUserRequestCommand, GetUserResponse } from "./GetUserRequest";
310
+ import { GetUserResponseValidator } from "./GetUserResponseValidator";
311
+
312
+ // Used by clients plugin
313
+ export class UsersClient {
314
+ async send(command: GetUserRequestCommand): Promise<GetUserResponse> {
315
+ const response = await this.makeRequest(command);
316
+ const validator = new GetUserResponseValidator();
317
+ return validator.validate(response);
318
+ }
319
+ }
320
+ ```
321
+
322
+ ### With AWS CDK Plugin
323
+
324
+ Types provide the foundation for request/response handling:
325
+
326
+ ```typescript
327
+ // In your Lambda handler
328
+ import { GetUserRequestValidator, GetUserResponseValidator } from "./api/generated";
329
+
330
+ export const handler = async (event: APIGatewayProxyEvent) => {
331
+ const requestValidator = new GetUserRequestValidator();
332
+
333
+ try {
334
+ const validatedRequest = requestValidator.validate({
335
+ param: event.pathParameters,
336
+ header: event.headers,
337
+ });
338
+
339
+ // Handle request with type safety
340
+ const user = await userService.getUser(validatedRequest.param.userId);
341
+
342
+ return {
343
+ statusCode: 200,
344
+ body: JSON.stringify(user),
345
+ };
346
+ } catch (error) {
347
+ if (error instanceof ValidationError) {
348
+ return {
349
+ statusCode: 400,
350
+ body: JSON.stringify({ message: "Invalid request", issues: error.issues }),
351
+ };
352
+ }
353
+ throw error;
354
+ }
355
+ };
356
+ ```
357
+
358
+ ## Advanced Features
359
+
360
+ ### Custom Validators
361
+
362
+ Extend generated validators for custom validation logic:
363
+
364
+ ```typescript
365
+ import { GetUserRequestValidator } from "./api/generated";
366
+
367
+ export class CustomGetUserRequestValidator extends GetUserRequestValidator {
368
+ public validate(request: unknown): GetUserRequest {
369
+ const validated = super.validate(request);
370
+
371
+ // Custom validation logic
372
+ if (validated.param.userId.startsWith("test_")) {
373
+ throw new Error("Test users not allowed in production");
374
+ }
375
+
376
+ return validated;
377
+ }
378
+ }
379
+ ```
380
+
381
+ ### Schema Composition
382
+
383
+ Generated schemas can be composed and extended:
384
+
385
+ ```typescript
386
+ import { GetUserRequestSchema } from "./api/generated";
387
+
388
+ // Extend for internal usage
389
+ export const InternalGetUserRequestSchema = GetUserRequestSchema.extend({
390
+ internal: z.object({
391
+ requestId: z.string(),
392
+ userId: z.string(),
393
+ }),
394
+ });
395
+ ```
396
+
397
+ ## Plugin Architecture
398
+
399
+ This plugin extends the TypeWeaver plugin system:
400
+
401
+ ```typescript
402
+ import { BasePlugin, type GeneratorContext } from "@rexeus/typeweaver-gen";
403
+
404
+ export default class TypesPlugin extends BasePlugin {
405
+ public name = "types";
406
+
407
+ public override generate(context: GeneratorContext): void {
408
+ // Generates types and validators for all operations
409
+ SharedResponseGenerator.generate(context);
410
+ RequestGenerator.generate(context);
411
+ RequestValidationGenerator.generate(context);
412
+ ResponseGenerator.generate(context);
413
+ ResponseValidationGenerator.generate(context);
414
+ }
415
+ }
416
+ ```
417
+
418
+ ## Best Practices
419
+
420
+ ### Organization
421
+
422
+ - Keep generated types in source control for review
423
+ - Regenerate types when API definitions change
424
+ - Use TypeScript strict mode for maximum safety
425
+
426
+ ### Validation Strategy
427
+
428
+ ```typescript
429
+ // Validate at boundaries
430
+ export class ApiController {
431
+ async getUser(request: unknown) {
432
+ // Validate input
433
+ const validator = new GetUserRequestValidator();
434
+ const validatedRequest = validator.validate(request);
435
+
436
+ // Business logic with typed data
437
+ const user = await this.userService.getUser(validatedRequest.param.userId);
438
+
439
+ // Return typed response
440
+ return {
441
+ statusCode: 200,
442
+ body: user,
443
+ } as GetUserSuccessResponse;
444
+ }
445
+ }
446
+ ```
447
+
448
+ ### Error Handling
449
+
450
+ ```typescript
451
+ // Centralized error mapping
452
+ export function mapValidationError(error: ZodError): ValidationErrorResponse {
453
+ return {
454
+ statusCode: 400,
455
+ body: {
456
+ message: "Validation failed",
457
+ issues: error.issues.map(issue => ({
458
+ path: issue.path.join("."),
459
+ message: issue.message,
460
+ })),
461
+ },
462
+ };
463
+ }
464
+ ```
465
+
466
+ ## Troubleshooting
467
+
468
+ ### Common Issues
469
+
470
+ **Type conflicts**: Ensure API definitions are consistent **Validation errors**: Check Zod schema
471
+ compatibility **Import issues**: Verify generated files are properly exported
472
+
473
+ ### Debug Mode
474
+
475
+ Enable detailed generation logging:
476
+
477
+ ```bash
478
+ DEBUG=typeweaver:types npx typeweaver generate --plugins types
479
+ ```
480
+
481
+ ## License
482
+
483
+ ISC © Dennis Wentzien 2025
@@ -0,0 +1,8 @@
1
+ import { BasePlugin, GeneratorContext } from '@rexeus/typeweaver-gen';
2
+
3
+ declare class TypesPlugin extends BasePlugin {
4
+ name: string;
5
+ generate(context: GeneratorContext): void;
6
+ }
7
+
8
+ export { TypesPlugin as default };