@veloxts/validation 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.
@@ -0,0 +1,274 @@
1
+ /**
2
+ * Validation middleware for VeloxTS procedures and routes
3
+ *
4
+ * Provides middleware utilities for validating request data
5
+ * with proper error handling and type inference.
6
+ *
7
+ * @module middleware
8
+ */
9
+ import { ValidationError } from '@veloxts/core';
10
+ import { ZodError } from 'zod';
11
+ import { isSchema, isZodSchema } from './types.js';
12
+ // ============================================================================
13
+ // Error Transformation
14
+ // ============================================================================
15
+ /**
16
+ * Transforms Zod validation issues into a field-error map
17
+ *
18
+ * @param issues - Array of Zod validation issues
19
+ * @returns Record mapping field paths to error messages
20
+ */
21
+ export function formatZodErrors(issues) {
22
+ const fields = {};
23
+ for (const issue of issues) {
24
+ const path = issue.path.join('.') || '_root';
25
+ // Only keep the first error for each field
26
+ if (!(path in fields)) {
27
+ fields[path] = issue.message;
28
+ }
29
+ }
30
+ return fields;
31
+ }
32
+ /**
33
+ * Transforms a ZodError into a VeloxTSValidationError
34
+ *
35
+ * @param error - ZodError from failed validation
36
+ * @param customMessage - Optional custom error message
37
+ * @returns ValidationError with field-specific errors
38
+ */
39
+ export function zodErrorToValidationError(error, customMessage) {
40
+ const fields = formatZodErrors(error.issues);
41
+ const message = customMessage ?? 'Validation failed';
42
+ return new ValidationError(message, fields);
43
+ }
44
+ // ============================================================================
45
+ // Validation Functions
46
+ // ============================================================================
47
+ /**
48
+ * Parses and validates data against a schema, throwing ValidationError on failure
49
+ *
50
+ * Follows Zod's naming convention for consistency with the ecosystem.
51
+ *
52
+ * @template T - The validated output type
53
+ * @param schema - Zod schema or Schema wrapper
54
+ * @param data - Data to validate
55
+ * @param errorMessage - Optional custom error message
56
+ * @returns Validated data with proper type
57
+ * @throws ValidationError if validation fails
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * const UserSchema = z.object({ name: z.string(), email: z.string().email() });
62
+ *
63
+ * const user = parse(UserSchema, request.body);
64
+ * // user is typed as { name: string; email: string }
65
+ * ```
66
+ */
67
+ export function parse(schema, data, errorMessage) {
68
+ try {
69
+ if (isSchema(schema)) {
70
+ const result = schema.safeParse(data);
71
+ if (result.success) {
72
+ return result.data;
73
+ }
74
+ throw new ValidationError(errorMessage ?? 'Validation failed', formatZodErrors(result.error));
75
+ }
76
+ if (isZodSchema(schema)) {
77
+ return schema.parse(data);
78
+ }
79
+ throw new Error('Invalid schema provided to parse()');
80
+ }
81
+ catch (error) {
82
+ if (error instanceof ValidationError) {
83
+ throw error;
84
+ }
85
+ if (error instanceof ZodError) {
86
+ throw zodErrorToValidationError(error, errorMessage);
87
+ }
88
+ throw error;
89
+ }
90
+ }
91
+ /**
92
+ * @deprecated Use `parse` instead. This alias will be removed in v1.0.
93
+ */
94
+ export const validate = parse;
95
+ /**
96
+ * Safely parses data without throwing
97
+ *
98
+ * Follows Zod's naming convention for consistency with the ecosystem.
99
+ *
100
+ * @template T - The validated output type
101
+ * @param schema - Zod schema or Schema wrapper
102
+ * @param data - Data to validate
103
+ * @returns Safe parse result with success discriminator
104
+ *
105
+ * @example
106
+ * ```typescript
107
+ * const result = safeParse(UserSchema, request.body);
108
+ * if (result.success) {
109
+ * console.log(result.data.name);
110
+ * } else {
111
+ * console.log(result.error);
112
+ * }
113
+ * ```
114
+ */
115
+ export function safeParse(schema, data) {
116
+ if (isSchema(schema)) {
117
+ return schema.safeParse(data);
118
+ }
119
+ if (isZodSchema(schema)) {
120
+ const zodSchema = schema;
121
+ const result = zodSchema.safeParse(data);
122
+ if (result.success) {
123
+ return { success: true, data: result.data };
124
+ }
125
+ return {
126
+ success: false,
127
+ error: result.error.issues.map((issue) => ({
128
+ path: issue.path,
129
+ message: issue.message,
130
+ code: issue.code,
131
+ })),
132
+ };
133
+ }
134
+ return {
135
+ success: false,
136
+ error: [{ path: [], message: 'Invalid schema provided', code: 'custom' }],
137
+ };
138
+ }
139
+ /**
140
+ * @deprecated Use `safeParse` instead. This alias will be removed in v1.0.
141
+ */
142
+ export const safeValidate = safeParse;
143
+ // ============================================================================
144
+ // Schema Validators
145
+ // ============================================================================
146
+ /**
147
+ * Creates a reusable validator function from a schema
148
+ *
149
+ * @template TOutput - The validated output type
150
+ * @template TInput - The input type (defaults to unknown)
151
+ * @param schema - Zod schema for validation
152
+ * @returns Object with parse and safeParse methods
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * const userValidator = createValidator(UserSchema);
157
+ *
158
+ * // In a handler
159
+ * const user = userValidator.parse(request.body);
160
+ * ```
161
+ */
162
+ export function createValidator(schema) {
163
+ return {
164
+ parse(data) {
165
+ return parse(schema, data);
166
+ },
167
+ safeParse(data) {
168
+ return safeParse(schema, data);
169
+ },
170
+ // Deprecated aliases
171
+ validate(data) {
172
+ return parse(schema, data);
173
+ },
174
+ safeValidate(data) {
175
+ return safeParse(schema, data);
176
+ },
177
+ schema,
178
+ };
179
+ }
180
+ // ============================================================================
181
+ // Request Validation Helpers
182
+ // ============================================================================
183
+ /**
184
+ * Parses multiple data sources at once
185
+ *
186
+ * Useful for validating body, query, and params together.
187
+ *
188
+ * @param validations - Object mapping names to schema/data pairs
189
+ * @returns Object with validated data for each key
190
+ * @throws ValidationError with combined errors if any validation fails
191
+ *
192
+ * @example
193
+ * ```typescript
194
+ * const { body, query, params } = parseAll({
195
+ * body: [CreateUserSchema, request.body],
196
+ * query: [PaginationSchema, request.query],
197
+ * params: [IdParamSchema, request.params],
198
+ * });
199
+ * ```
200
+ */
201
+ export function parseAll(validations) {
202
+ const results = {};
203
+ const allErrors = {};
204
+ for (const [key, [schema, data]] of Object.entries(validations)) {
205
+ const result = safeParse(schema, data);
206
+ if (result.success) {
207
+ results[key] = result.data;
208
+ }
209
+ else {
210
+ for (const issue of result.error) {
211
+ const path = issue.path.length > 0 ? `${key}.${issue.path.join('.')}` : key;
212
+ if (!(path in allErrors)) {
213
+ allErrors[path] = issue.message;
214
+ }
215
+ }
216
+ }
217
+ }
218
+ if (Object.keys(allErrors).length > 0) {
219
+ throw new ValidationError('Validation failed', allErrors);
220
+ }
221
+ return results;
222
+ }
223
+ /**
224
+ * @deprecated Use `parseAll` instead. This alias will be removed in v1.0.
225
+ */
226
+ export const validateAll = parseAll;
227
+ // ============================================================================
228
+ // Type Guards
229
+ // ============================================================================
230
+ /**
231
+ * Creates a type guard from a Zod schema
232
+ *
233
+ * @template T - The validated type
234
+ * @param schema - Zod schema to use for checking
235
+ * @returns Type predicate function
236
+ *
237
+ * @example
238
+ * ```typescript
239
+ * const isUser = createTypeGuard(UserSchema);
240
+ *
241
+ * if (isUser(data)) {
242
+ * // data is typed as User
243
+ * console.log(data.name);
244
+ * }
245
+ * ```
246
+ */
247
+ export function createTypeGuard(schema) {
248
+ return (value) => {
249
+ const result = schema.safeParse(value);
250
+ return result.success;
251
+ };
252
+ }
253
+ /**
254
+ * Asserts that a value matches a schema, narrowing the type
255
+ *
256
+ * @template T - The validated type
257
+ * @param schema - Zod schema to validate against
258
+ * @param value - Value to assert
259
+ * @param errorMessage - Optional custom error message
260
+ * @throws ValidationError if assertion fails
261
+ *
262
+ * @example
263
+ * ```typescript
264
+ * function processUser(data: unknown) {
265
+ * assertSchema(UserSchema, data);
266
+ * // data is now typed as User
267
+ * console.log(data.name);
268
+ * }
269
+ * ```
270
+ */
271
+ export function assertSchema(schema, value, errorMessage) {
272
+ validate(schema, value, errorMessage);
273
+ }
274
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAiC,MAAM,KAAK,CAAC;AAG9D,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEnD,+EAA+E;AAC/E,uBAAuB;AACvB,+EAA+E;AAE/E;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAC7B,MAA0E;IAE1E,MAAM,MAAM,GAA2B,EAAE,CAAC;IAE1C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC;QAC7C,2CAA2C;QAC3C,IAAI,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC,EAAE,CAAC;YACtB,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,yBAAyB,CACvC,KAAe,EACf,aAAsB;IAEtB,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,aAAa,IAAI,mBAAmB,CAAC;IACrD,OAAO,IAAI,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AAC9C,CAAC;AAED,+EAA+E;AAC/E,uBAAuB;AACvB,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,KAAK,CACnB,MAAmD,EACnD,IAAa,EACb,YAAqB;IAErB,IAAI,CAAC;QACH,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACrB,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YACtC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,OAAO,MAAM,CAAC,IAAS,CAAC;YAC1B,CAAC;YACD,MAAM,IAAI,eAAe,CAAC,YAAY,IAAI,mBAAmB,EAAE,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAChG,CAAC;QAED,IAAI,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;YACxB,OAAQ,MAA0C,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjE,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,eAAe,EAAE,CAAC;YACrC,MAAM,KAAK,CAAC;QACd,CAAC;QACD,IAAI,KAAK,YAAY,QAAQ,EAAE,CAAC;YAC9B,MAAM,yBAAyB,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;QACvD,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,SAAS,CACvB,MAAmD,EACnD,IAAa;IAEb,IAAI,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACrB,OAAO,MAAM,CAAC,SAAS,CAAC,IAAI,CAAuB,CAAC;IACtD,CAAC;IAED,IAAI,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;QACxB,MAAM,SAAS,GAAG,MAAyC,CAAC;QAC5D,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAEzC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;QAC9C,CAAC;QAED,OAAO;YACL,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACzC,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,IAAI,EAAE,KAAK,CAAC,IAAI;aACjB,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC;IAED,OAAO;QACL,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,OAAO,EAAE,yBAAyB,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;KAC1E,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,SAAS,CAAC;AAEtC,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,eAAe,CAC7B,MAA4C;IAE5C,OAAO;QACL,KAAK,CAAC,IAAa;YACjB,OAAO,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC7B,CAAC;QAED,SAAS,CAAC,IAAa;YACrB,OAAO,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACjC,CAAC;QAED,qBAAqB;QACrB,QAAQ,CAAC,IAAa;YACpB,OAAO,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC7B,CAAC;QAED,YAAY,CAAC,IAAa;YACxB,OAAO,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACjC,CAAC;QAED,MAAM;KACP,CAAC;AACJ,CAAC;AAkBD,+EAA+E;AAC/E,6BAA6B;AAC7B,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,QAAQ,CACtB,WAAc;IAEd,MAAM,OAAO,GAA4B,EAAE,CAAC;IAC5C,MAAM,SAAS,GAA2B,EAAE,CAAC;IAE7C,KAAK,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QAChE,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAEvC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;gBACjC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;gBAC5E,IAAI,CAAC,CAAC,IAAI,IAAI,SAAS,CAAC,EAAE,CAAC;oBACzB,SAAS,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC;gBAClC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,eAAe,CAAC,mBAAmB,EAAE,SAAS,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,OAEN,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC;AAEpC,+EAA+E;AAC/E,cAAc;AACd,+EAA+E;AAE/E;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAuC;IAEvC,OAAO,CAAC,KAAc,EAAc,EAAE;QACpC,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACvC,OAAO,MAAM,CAAC,OAAO,CAAC;IACxB,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,YAAY,CAC1B,MAAuC,EACvC,KAAc,EACd,YAAqB;IAErB,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Common schema utilities and pre-built schemas
3
+ *
4
+ * Provides commonly used validation patterns with proper type inference.
5
+ *
6
+ * @module schemas/common
7
+ */
8
+ import { z } from 'zod';
9
+ /**
10
+ * UUID v4 string schema
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const id = uuidSchema.parse('123e4567-e89b-12d3-a456-426614174000');
15
+ * // id: string (validated UUID)
16
+ * ```
17
+ */
18
+ export declare const uuidSchema: z.ZodString;
19
+ /**
20
+ * Email address schema
21
+ */
22
+ export declare const emailSchema: z.ZodString;
23
+ /**
24
+ * Non-empty string schema
25
+ */
26
+ export declare const nonEmptyStringSchema: z.ZodString;
27
+ /**
28
+ * URL string schema
29
+ */
30
+ export declare const urlSchema: z.ZodString;
31
+ /**
32
+ * ISO 8601 datetime string schema
33
+ */
34
+ export declare const datetimeSchema: z.ZodString;
35
+ /**
36
+ * Generic ID parameter schema (UUID)
37
+ * Commonly used for route parameters like `/users/:id`
38
+ */
39
+ export declare const idParamSchema: z.ZodObject<{
40
+ id: z.ZodString;
41
+ }, "strip", z.ZodTypeAny, {
42
+ id: string;
43
+ }, {
44
+ id: string;
45
+ }>;
46
+ /**
47
+ * Type for id parameter objects
48
+ */
49
+ export type IdParam = z.infer<typeof idParamSchema>;
50
+ /**
51
+ * Creates an ID schema that accepts either UUID or integer string
52
+ *
53
+ * @param type - Type of ID to accept ('uuid' | 'integer' | 'string')
54
+ * @returns Zod schema for the specified ID type
55
+ */
56
+ export declare function createIdSchema<T extends 'uuid' | 'integer' | 'string'>(type: T): T extends 'uuid' ? typeof uuidSchema : T extends 'integer' ? z.ZodPipeline<z.ZodEffects<z.ZodString, number, string>, z.ZodNumber> : z.ZodString;
57
+ /**
58
+ * Timestamp fields commonly added to database records
59
+ */
60
+ export declare const timestampFieldsSchema: z.ZodObject<{
61
+ createdAt: z.ZodDate;
62
+ updatedAt: z.ZodDate;
63
+ }, "strip", z.ZodTypeAny, {
64
+ createdAt: Date;
65
+ updatedAt: Date;
66
+ }, {
67
+ createdAt: Date;
68
+ updatedAt: Date;
69
+ }>;
70
+ /**
71
+ * Type for timestamp fields
72
+ */
73
+ export type TimestampFields = z.infer<typeof timestampFieldsSchema>;
74
+ /**
75
+ * Base entity schema with ID and timestamps
76
+ */
77
+ export declare const baseEntitySchema: z.ZodObject<{
78
+ id: z.ZodString;
79
+ createdAt: z.ZodDate;
80
+ updatedAt: z.ZodDate;
81
+ }, "strip", z.ZodTypeAny, {
82
+ id: string;
83
+ createdAt: Date;
84
+ updatedAt: Date;
85
+ }, {
86
+ id: string;
87
+ createdAt: Date;
88
+ updatedAt: Date;
89
+ }>;
90
+ /**
91
+ * Type for base entity
92
+ */
93
+ export type BaseEntity = z.infer<typeof baseEntitySchema>;
94
+ /**
95
+ * Makes all fields in a schema optional
96
+ *
97
+ * @param schema - Zod object schema
98
+ * @returns Schema with all fields optional
99
+ *
100
+ * @example
101
+ * ```typescript
102
+ * const UpdateUserSchema = makePartial(UserSchema);
103
+ * // All fields are now optional
104
+ * ```
105
+ */
106
+ export declare function makePartial<T extends z.ZodRawShape>(schema: z.ZodObject<T>): z.ZodObject<{
107
+ [K in keyof T]: z.ZodOptional<T[K]>;
108
+ }>;
109
+ /**
110
+ * Makes specific fields required in a partial schema
111
+ *
112
+ * @param schema - Zod object schema
113
+ * @param keys - Array of keys to make required
114
+ * @returns Schema with specified fields required, others optional
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * const UpdateUserSchema = partialExcept(UserSchema, ['id'] as const);
119
+ * // id is required, all other fields are optional
120
+ * ```
121
+ */
122
+ export declare function partialExcept<T extends z.ZodRawShape, K extends keyof T & string>(schema: z.ZodObject<T>, keys: readonly K[]): z.ZodObject<{
123
+ [P in K]: T[P];
124
+ } & {
125
+ [P in Exclude<keyof T, K>]: z.ZodOptional<T[P]>;
126
+ }>;
127
+ /**
128
+ * Omits specified fields from a schema
129
+ *
130
+ * @param schema - Zod object schema
131
+ * @param keys - Array of keys to omit
132
+ * @returns Schema without the specified fields
133
+ *
134
+ * @example
135
+ * ```typescript
136
+ * const UserWithoutPassword = omitFields(UserSchema, ['password'] as const);
137
+ * ```
138
+ */
139
+ export declare function omitFields<T extends z.ZodRawShape, K extends keyof T & string>(schema: z.ZodObject<T>, keys: readonly K[]): z.ZodObject<Omit<T, K>>;
140
+ /**
141
+ * Picks specified fields from a schema
142
+ *
143
+ * @param schema - Zod object schema
144
+ * @param keys - Array of keys to pick
145
+ * @returns Schema with only the specified fields
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * const UserIdAndName = pickFields(UserSchema, ['id', 'name'] as const);
150
+ * ```
151
+ */
152
+ export declare function pickFields<T extends z.ZodRawShape, K extends keyof T & string>(schema: z.ZodObject<T>, keys: readonly K[]): z.ZodObject<Pick<T, K>>;
153
+ /**
154
+ * String that coerces to boolean
155
+ * Accepts 'true', '1', 'yes' as true; 'false', '0', 'no' as false
156
+ */
157
+ export declare const booleanStringSchema: z.ZodPipeline<z.ZodEffects<z.ZodString, boolean | undefined, string>, z.ZodBoolean>;
158
+ /**
159
+ * String that coerces to number
160
+ * Useful for query parameters
161
+ */
162
+ export declare const numberStringSchema: z.ZodPipeline<z.ZodEffects<z.ZodString, number, string>, z.ZodNumber>;
163
+ /**
164
+ * String that coerces to integer
165
+ * Useful for pagination parameters
166
+ */
167
+ export declare const integerStringSchema: z.ZodPipeline<z.ZodEffects<z.ZodString, number, string>, z.ZodNumber>;
168
+ //# sourceMappingURL=common.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/schemas/common.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,211 @@
1
+ /**
2
+ * Common schema utilities and pre-built schemas
3
+ *
4
+ * Provides commonly used validation patterns with proper type inference.
5
+ *
6
+ * @module schemas/common
7
+ */
8
+ import { z } from 'zod';
9
+ // ============================================================================
10
+ // Common String Schemas
11
+ // ============================================================================
12
+ /**
13
+ * UUID v4 string schema
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const id = uuidSchema.parse('123e4567-e89b-12d3-a456-426614174000');
18
+ * // id: string (validated UUID)
19
+ * ```
20
+ */
21
+ export const uuidSchema = z.string().uuid();
22
+ /**
23
+ * Email address schema
24
+ */
25
+ export const emailSchema = z.string().email();
26
+ /**
27
+ * Non-empty string schema
28
+ */
29
+ export const nonEmptyStringSchema = z.string().min(1);
30
+ /**
31
+ * URL string schema
32
+ */
33
+ export const urlSchema = z.string().url();
34
+ /**
35
+ * ISO 8601 datetime string schema
36
+ */
37
+ export const datetimeSchema = z.string().datetime();
38
+ // ============================================================================
39
+ // Common ID Schemas
40
+ // ============================================================================
41
+ /**
42
+ * Generic ID parameter schema (UUID)
43
+ * Commonly used for route parameters like `/users/:id`
44
+ */
45
+ export const idParamSchema = z.object({
46
+ id: uuidSchema,
47
+ });
48
+ /**
49
+ * Creates an ID schema that accepts either UUID or integer string
50
+ *
51
+ * @param type - Type of ID to accept ('uuid' | 'integer' | 'string')
52
+ * @returns Zod schema for the specified ID type
53
+ */
54
+ export function createIdSchema(type) {
55
+ switch (type) {
56
+ case 'uuid':
57
+ return uuidSchema;
58
+ case 'integer':
59
+ return z
60
+ .string()
61
+ .transform((val) => parseInt(val, 10))
62
+ .pipe(z.number().int().positive());
63
+ default:
64
+ return z.string().min(1);
65
+ }
66
+ }
67
+ // ============================================================================
68
+ // Common Object Schemas
69
+ // ============================================================================
70
+ /**
71
+ * Timestamp fields commonly added to database records
72
+ */
73
+ export const timestampFieldsSchema = z.object({
74
+ createdAt: z.coerce.date(),
75
+ updatedAt: z.coerce.date(),
76
+ });
77
+ /**
78
+ * Base entity schema with ID and timestamps
79
+ */
80
+ export const baseEntitySchema = z.object({
81
+ id: uuidSchema,
82
+ createdAt: z.coerce.date(),
83
+ updatedAt: z.coerce.date(),
84
+ });
85
+ // ============================================================================
86
+ // Schema Composition Utilities
87
+ // ============================================================================
88
+ /**
89
+ * Makes all fields in a schema optional
90
+ *
91
+ * @param schema - Zod object schema
92
+ * @returns Schema with all fields optional
93
+ *
94
+ * @example
95
+ * ```typescript
96
+ * const UpdateUserSchema = makePartial(UserSchema);
97
+ * // All fields are now optional
98
+ * ```
99
+ */
100
+ export function makePartial(schema) {
101
+ return schema.partial();
102
+ }
103
+ /**
104
+ * Makes specific fields required in a partial schema
105
+ *
106
+ * @param schema - Zod object schema
107
+ * @param keys - Array of keys to make required
108
+ * @returns Schema with specified fields required, others optional
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * const UpdateUserSchema = partialExcept(UserSchema, ['id'] as const);
113
+ * // id is required, all other fields are optional
114
+ * ```
115
+ */
116
+ export function partialExcept(schema, keys) {
117
+ const shape = schema.shape;
118
+ const requiredKeys = new Set(keys);
119
+ const newShape = {};
120
+ for (const key in shape) {
121
+ if (requiredKeys.has(key)) {
122
+ newShape[key] = shape[key];
123
+ }
124
+ else {
125
+ newShape[key] = shape[key].optional();
126
+ }
127
+ }
128
+ return z.object(newShape);
129
+ }
130
+ /**
131
+ * Omits specified fields from a schema
132
+ *
133
+ * @param schema - Zod object schema
134
+ * @param keys - Array of keys to omit
135
+ * @returns Schema without the specified fields
136
+ *
137
+ * @example
138
+ * ```typescript
139
+ * const UserWithoutPassword = omitFields(UserSchema, ['password'] as const);
140
+ * ```
141
+ */
142
+ export function omitFields(schema, keys) {
143
+ // Build the omit mask manually to avoid Zod's strict typing
144
+ const shape = schema.shape;
145
+ const keysToOmit = new Set(keys);
146
+ const newShape = {};
147
+ for (const key in shape) {
148
+ if (!keysToOmit.has(key)) {
149
+ newShape[key] = shape[key];
150
+ }
151
+ }
152
+ return z.object(newShape);
153
+ }
154
+ /**
155
+ * Picks specified fields from a schema
156
+ *
157
+ * @param schema - Zod object schema
158
+ * @param keys - Array of keys to pick
159
+ * @returns Schema with only the specified fields
160
+ *
161
+ * @example
162
+ * ```typescript
163
+ * const UserIdAndName = pickFields(UserSchema, ['id', 'name'] as const);
164
+ * ```
165
+ */
166
+ export function pickFields(schema, keys) {
167
+ // Build the pick mask manually to avoid Zod's strict typing
168
+ const shape = schema.shape;
169
+ const newShape = {};
170
+ for (const key of keys) {
171
+ if (key in shape) {
172
+ newShape[key] = shape[key];
173
+ }
174
+ }
175
+ return z.object(newShape);
176
+ }
177
+ // ============================================================================
178
+ // Coercion Utilities
179
+ // ============================================================================
180
+ /**
181
+ * String that coerces to boolean
182
+ * Accepts 'true', '1', 'yes' as true; 'false', '0', 'no' as false
183
+ */
184
+ export const booleanStringSchema = z
185
+ .string()
186
+ .transform((val) => {
187
+ const lower = val.toLowerCase();
188
+ if (['true', '1', 'yes'].includes(lower))
189
+ return true;
190
+ if (['false', '0', 'no'].includes(lower))
191
+ return false;
192
+ return undefined;
193
+ })
194
+ .pipe(z.boolean());
195
+ /**
196
+ * String that coerces to number
197
+ * Useful for query parameters
198
+ */
199
+ export const numberStringSchema = z
200
+ .string()
201
+ .transform((val) => Number(val))
202
+ .pipe(z.number());
203
+ /**
204
+ * String that coerces to integer
205
+ * Useful for pagination parameters
206
+ */
207
+ export const integerStringSchema = z
208
+ .string()
209
+ .transform((val) => parseInt(val, 10))
210
+ .pipe(z.number().int());
211
+ //# sourceMappingURL=common.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/schemas/common.ts"],"names":[],"mappings":"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"}