@gravito/mass 3.0.1 → 3.0.3

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,168 @@
1
+ import type { ValueError } from '@sinclair/typebox/errors';
2
+ import type { ValidationSource } from './types';
3
+ /**
4
+ * Error Messages - Traditional Chinese
5
+ *
6
+ * Provides common validation error messages in Traditional Chinese.
7
+ */
8
+ export declare const ERROR_MESSAGES_ZH_TW: {
9
+ readonly REQUIRED: "此欄位為必填";
10
+ readonly INVALID_TYPE: "資料型別不正確";
11
+ readonly INVALID_EMAIL: "電子郵件格式不正確";
12
+ readonly INVALID_URL: "網址格式不正確";
13
+ readonly INVALID_UUID: "UUID 格式不正確";
14
+ readonly INVALID_DATE: "日期格式不正確";
15
+ readonly TOO_SHORT: "長度過短";
16
+ readonly TOO_LONG: "長度過長";
17
+ readonly TOO_SMALL: "數值過小";
18
+ readonly TOO_LARGE: "數值過大";
19
+ readonly INVALID_PATTERN: "格式不符合規則";
20
+ readonly INVALID_FORMAT: "格式不正確";
21
+ };
22
+ /**
23
+ * Error Messages - English
24
+ *
25
+ * Provides common validation error messages in English.
26
+ */
27
+ export declare const ERROR_MESSAGES_EN: {
28
+ readonly REQUIRED: "This field is required";
29
+ readonly INVALID_TYPE: "Invalid data type";
30
+ readonly INVALID_EMAIL: "Invalid email format";
31
+ readonly INVALID_URL: "Invalid URL format";
32
+ readonly INVALID_UUID: "Invalid UUID format";
33
+ readonly INVALID_DATE: "Invalid date format";
34
+ readonly TOO_SHORT: "Too short";
35
+ readonly TOO_LONG: "Too long";
36
+ readonly TOO_SMALL: "Value too small";
37
+ readonly TOO_LARGE: "Value too large";
38
+ readonly INVALID_PATTERN: "Does not match required pattern";
39
+ readonly INVALID_FORMAT: "Invalid format";
40
+ };
41
+ /**
42
+ * Error Formatter Function Type
43
+ *
44
+ * Function type for converting TypeBox errors into a custom format.
45
+ */
46
+ export type ErrorFormatter = (error: ValueError) => {
47
+ path: string;
48
+ message: string;
49
+ expected?: string;
50
+ received?: string;
51
+ };
52
+ /**
53
+ * Custom error class thrown or returned when validation fails.
54
+ *
55
+ * This class encapsulates the validation error details and the source of the data
56
+ * (e.g., 'json', 'query') that failed validation. It is suitable for use in
57
+ * exception filters or global error handlers.
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * throw new MassValidationError('json', [
62
+ * { path: '/email', message: 'Invalid email format' }
63
+ * ])
64
+ * ```
65
+ */
66
+ export declare class MassValidationError extends Error {
67
+ readonly source: ValidationSource;
68
+ readonly errors: Array<{
69
+ path: string;
70
+ message: string;
71
+ }>;
72
+ /**
73
+ * Creates a new MassValidationError instance.
74
+ *
75
+ * @param source - The source of the invalid data
76
+ * @param errors - The list of validation errors
77
+ */
78
+ constructor(source: ValidationSource, errors: Array<{
79
+ path: string;
80
+ message: string;
81
+ }>);
82
+ /**
83
+ * Serializes the error to a JSON-compatible object.
84
+ *
85
+ * @returns A structured error object suitable for API responses
86
+ */
87
+ toJSON(): {
88
+ error: string;
89
+ source: ValidationSource;
90
+ details: {
91
+ path: string;
92
+ message: string;
93
+ }[];
94
+ };
95
+ }
96
+ /**
97
+ * Enhances TypeBox Validation Errors.
98
+ *
99
+ * Converts raw TypeBox errors into structured error objects with more context,
100
+ * suitable for returning directly to clients or logging.
101
+ *
102
+ * @param error - The raw TypeBox validation error
103
+ * @param locale - Locale ('zh-TW' or 'en'), defaults to 'zh-TW'
104
+ * @returns Enhanced error object
105
+ *
106
+ * @example
107
+ * ```typescript
108
+ * import { Value } from '@sinclair/typebox/value'
109
+ *
110
+ * const errors = [...Value.Errors(schema, data)]
111
+ * const enhanced = errors.map(err => enhanceError(err, 'zh-TW'))
112
+ * // [{ path: '/email', message: '電子郵件格式不正確', expected: 'string<email>', received: 'string' }]
113
+ * ```
114
+ */
115
+ export declare function enhanceError(error: ValueError, locale?: 'zh-TW' | 'en'): {
116
+ path: string;
117
+ message: string;
118
+ expected?: string;
119
+ received?: string;
120
+ };
121
+ /**
122
+ * Creates Custom Error Formatter.
123
+ *
124
+ * High-order function that allows creating custom error formatting logic for TypeBox validation errors.
125
+ * Useful for standardizing error formats or supporting multiple languages.
126
+ *
127
+ * @param formatter - Custom formatter function
128
+ * @returns Error formatter function
129
+ *
130
+ * @example
131
+ * ```typescript
132
+ * const myFormatter = createErrorFormatter((error) => ({
133
+ * path: error.path,
134
+ * message: `Custom Message: ${error.message}`,
135
+ * code: 'VALIDATION_ERROR'
136
+ * }))
137
+ *
138
+ * const errors = [...Value.Errors(schema, data)]
139
+ * const formatted = errors.map(myFormatter)
140
+ * ```
141
+ */
142
+ export declare function createErrorFormatter(formatter: (error: ValueError) => {
143
+ path: string;
144
+ message: string;
145
+ [key: string]: unknown;
146
+ }): ErrorFormatter;
147
+ /**
148
+ * Formats a flat list of validation errors into a field-grouped structure.
149
+ *
150
+ * This helper transforms TypeBox's error format into a more frontend-friendly
151
+ * format where errors are grouped by field name.
152
+ *
153
+ * @param errors - The raw validation errors
154
+ * @returns An object where keys are field names and values are arrays of error messages
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * const errors = [{ path: '/user/name', message: 'Required' }]
159
+ * const formatted = formatErrors(errors)
160
+ * // Result: { fields: { 'user.name': ['Required'] } }
161
+ * ```
162
+ */
163
+ export declare function formatErrors(errors: Array<{
164
+ path: string;
165
+ message: string;
166
+ }>): {
167
+ fields: Record<string, string[]>;
168
+ };
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Pre-registered Format Names.
3
+ *
4
+ * Provides common data format validators including email, url, uuid, date-time, etc.
5
+ */
6
+ export declare const REGISTERED_FORMATS: readonly ["email", "uri", "uri-reference", "uuid", "date-time", "date", "time", "ipv4", "ipv6"];
7
+ export type RegisteredFormat = (typeof REGISTERED_FORMATS)[number];
8
+ /**
9
+ * Registers Custom Format Validator.
10
+ *
11
+ * Allows registering custom format validation logic to TypeBox's FormatRegistry.
12
+ * Once registered, can be used in Schema.String() via the format option.
13
+ *
14
+ * @param name - Format name (e.g., 'phone-number', 'credit-card')
15
+ * @param validator - Validation function, returns true if valid
16
+ *
17
+ * @example Register Taiwan Phone Number Format
18
+ * ```typescript
19
+ * registerFormat('tw-phone', (value) => /^09\d{8}$/.test(value))
20
+ *
21
+ * const schema = Schema.String({ format: 'tw-phone' })
22
+ * const valid = Value.Check(schema, '0912345678') // true
23
+ * ```
24
+ *
25
+ * @example Register Credit Card Format (Simplified)
26
+ * ```typescript
27
+ * registerFormat('credit-card', (value) => {
28
+ * const cleaned = value.replace(/\s/g, '')
29
+ * return /^\d{13,19}$/.test(cleaned)
30
+ * })
31
+ * ```
32
+ */
33
+ export declare function registerFormat(name: string, validator: (value: string) => boolean): void;
34
+ /**
35
+ * Registers All Predefined Format Validators.
36
+ *
37
+ * Registers all common formats (email, url, uuid, etc.) to TypeBox's FormatRegistry.
38
+ * Typically called once at application startup.
39
+ *
40
+ * @example Register at Application Entry Point
41
+ * ```typescript
42
+ * import { registerAllFormats } from '@gravito/mass'
43
+ *
44
+ * // Register all predefined formats
45
+ * registerAllFormats()
46
+ *
47
+ * // Now you can use these formats in schemas
48
+ * const userSchema = Schema.Object({
49
+ * email: Schema.String({ format: 'email' }),
50
+ * website: Schema.String({ format: 'uri' }),
51
+ * id: Schema.String({ format: 'uuid' })
52
+ * })
53
+ * ```
54
+ */
55
+ export declare function registerAllFormats(): void;
56
+ /**
57
+ * Checks if a Specific Format is Registered.
58
+ *
59
+ * @param name - Format name
60
+ * @returns True if the format is registered
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * registerFormat('custom-format', (value) => true)
65
+ * isFormatRegistered('custom-format') // true
66
+ * isFormatRegistered('unknown-format') // false
67
+ * ```
68
+ */
69
+ export declare function isFormatRegistered(name: string): boolean;
70
+ /**
71
+ * Gets Registered Format Validator.
72
+ *
73
+ * @param name - Format name
74
+ * @returns Validation function, or undefined if not registered
75
+ *
76
+ * @example
77
+ * ```typescript
78
+ * const emailValidator = getFormatValidator('email')
79
+ * if (emailValidator) {
80
+ * const isValid = emailValidator('test@example.com') // true
81
+ * }
82
+ * ```
83
+ */
84
+ export declare function getFormatValidator(name: string): ((value: string) => boolean) | undefined;
85
+ /**
86
+ * Removes Registered Format Validator.
87
+ *
88
+ * @param name - Format name
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * registerFormat('temp-format', (value) => true)
93
+ * unregisterFormat('temp-format')
94
+ * isFormatRegistered('temp-format') // false
95
+ * ```
96
+ */
97
+ export declare function unregisterFormat(name: string): void;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * @gravito/mass - TypeBox-based validation for Gravito Galaxy Architecture.
3
+ *
4
+ * Mass provides high-performance schema validation with full TypeScript support,
5
+ * seamlessly integrating with Photon middleware system. Named after the concept
6
+ * of "mass" in physics, this package provides the "weight" of data integrity
7
+ * to your API endpoints.
8
+ *
9
+ * ## Key Features
10
+ *
11
+ * - **Zero-overhead TypeBox validation** - Generates validators at build-time for faster runtime performance
12
+ * - **Full TypeScript inference** - Validated data is fully typed without manual typings
13
+ * - **Multiple validation sources** - Validate JSON, query, params, and form data
14
+ * - **Custom error handling hooks** - Override default error responses
15
+ * - **Seamless Photon/Hono integration** - Works out of the box with Gravito's HTTP layer
16
+ *
17
+ * @example Basic JSON validation
18
+ * ```typescript
19
+ * import { Photon } from '@gravito/photon'
20
+ * import { Schema, validate } from '@gravito/mass'
21
+ *
22
+ * const app = new Photon()
23
+ *
24
+ * const loginSchema = Schema.Object({
25
+ * username: Schema.String({ minLength: 3, maxLength: 50 }),
26
+ * password: Schema.String({ minLength: 8 })
27
+ * })
28
+ *
29
+ * app.post('/login', validate('json', loginSchema), (c) => {
30
+ * const { username } = c.req.valid('json')
31
+ * // username is fully typed as string
32
+ * return c.json({ success: true, user: username })
33
+ * })
34
+ * ```
35
+ *
36
+ * @example Custom error handling
37
+ * ```typescript
38
+ * app.post('/register',
39
+ * validate('json', registerSchema, (result, c) => {
40
+ * if (!result.success) {
41
+ * return c.json({
42
+ * error: 'Validation failed',
43
+ * details: result.errors
44
+ * }, 400)
45
+ * }
46
+ * }),
47
+ * handler
48
+ * )
49
+ * ```
50
+ *
51
+ * @example Query parameter validation
52
+ * ```typescript
53
+ * const searchSchema = Schema.Object({
54
+ * q: Schema.String(),
55
+ * page: Schema.Optional(Schema.Number({ minimum: 1, default: 1 })),
56
+ * limit: Schema.Optional(Schema.Number({ minimum: 1, maximum: 100, default: 20 }))
57
+ * })
58
+ *
59
+ * app.get('/search', validate('query', searchSchema), (c) => {
60
+ * const { q, page, limit } = c.req.valid('query')
61
+ * return c.json({ query: q, page, limit })
62
+ * })
63
+ * ```
64
+ *
65
+ * @see {@link validate} - Main validation middleware
66
+ * @see {@link Schema} - TypeBox schema builders
67
+ * @see {@link https://github.com/sinclairzx81/typebox | TypeBox Documentation}
68
+ *
69
+ * @packageDocumentation
70
+ */
71
+ export type { Static, TSchema } from '@sinclair/typebox';
72
+ export * as Schema from '@sinclair/typebox';
73
+ export { CoercibleBoolean, CoercibleInteger, CoercibleNumber, coerceBoolean, coerceData, coerceDate, coerceInteger, coerceNumber, validateWithCoercion, } from './coercion';
74
+ export { createErrorFormatter, ERROR_MESSAGES_EN, ERROR_MESSAGES_ZH_TW, type ErrorFormatter, enhanceError, formatErrors, MassValidationError, } from './errors';
75
+ export { getFormatValidator, isFormatRegistered, REGISTERED_FORMATS, type RegisteredFormat, registerAllFormats, registerFormat, unregisterFormat, } from './formats';
76
+ export { type AstralResource, createAstralResource, createCrudResources, type OpenApiSchema, typeboxToOpenApi, } from './openapi';
77
+ export type { ValidationError, ValidationHook, ValidationResult, } from './types';
78
+ export { partial } from './utils';
79
+ export { type ValidationSource, validate } from './validator';
package/dist/index.js CHANGED
@@ -1,15 +1,30 @@
1
1
  // @bun
2
- // src/index.ts
3
- import { tbValidator as tbValidator2 } from "@hono/typebox-validator";
4
- import * as Schema from "@sinclair/typebox";
5
-
6
- // src/validator.ts
7
- import { tbValidator } from "@hono/typebox-validator";
8
- function validate(source, schema, hook) {
9
- return tbValidator(source, schema, hook);
10
- }
11
2
  export {
12
- tbValidator2 as validator,
3
+ validateWithCoercion,
13
4
  validate,
14
- Schema
5
+ unregisterFormat,
6
+ typeboxToOpenApi,
7
+ registerFormat,
8
+ registerAllFormats,
9
+ partial,
10
+ isFormatRegistered,
11
+ getFormatValidator,
12
+ formatErrors,
13
+ enhanceError,
14
+ createErrorFormatter,
15
+ createCrudResources,
16
+ createAstralResource,
17
+ coerceNumber,
18
+ coerceInteger,
19
+ coerceDate,
20
+ coerceData,
21
+ coerceBoolean,
22
+ Schema,
23
+ REGISTERED_FORMATS,
24
+ MassValidationError,
25
+ ERROR_MESSAGES_ZH_TW,
26
+ ERROR_MESSAGES_EN,
27
+ CoercibleNumber,
28
+ CoercibleInteger,
29
+ CoercibleBoolean
15
30
  };
@@ -0,0 +1,214 @@
1
+ import type { TSchema } from '@sinclair/typebox';
2
+ /**
3
+ * OpenAPI Schema Object Type
4
+ *
5
+ * Represents a Schema Object in the OpenAPI 3.0 specification.
6
+ */
7
+ export interface OpenApiSchema {
8
+ type?: string;
9
+ format?: string;
10
+ description?: string;
11
+ enum?: unknown[];
12
+ items?: OpenApiSchema;
13
+ properties?: Record<string, OpenApiSchema>;
14
+ required?: string[];
15
+ additionalProperties?: boolean | OpenApiSchema;
16
+ minLength?: number;
17
+ maxLength?: number;
18
+ minimum?: number;
19
+ maximum?: number;
20
+ pattern?: string;
21
+ default?: unknown;
22
+ example?: unknown;
23
+ nullable?: boolean;
24
+ readOnly?: boolean;
25
+ writeOnly?: boolean;
26
+ deprecated?: boolean;
27
+ [key: string]: unknown;
28
+ }
29
+ /**
30
+ * Astral Resource Definition Type
31
+ *
32
+ * Represents the resource definition for Gravito Astral automatic API documentation.
33
+ */
34
+ export interface AstralResource {
35
+ path: string;
36
+ method: string;
37
+ summary?: string;
38
+ description?: string;
39
+ tags?: string[];
40
+ requestBody?: {
41
+ description?: string;
42
+ required?: boolean;
43
+ content: {
44
+ 'application/json': {
45
+ schema: OpenApiSchema;
46
+ };
47
+ };
48
+ };
49
+ responses: {
50
+ [statusCode: string]: {
51
+ description: string;
52
+ content?: {
53
+ 'application/json': {
54
+ schema: OpenApiSchema;
55
+ };
56
+ };
57
+ };
58
+ };
59
+ }
60
+ /**
61
+ * Converts a TypeBox Schema to an OpenAPI Schema.
62
+ *
63
+ * This function transforms TypeBox schema definitions into OpenAPI 3.0 compliant schema objects,
64
+ * suitable for automatic API documentation generation or integration with third-party tools.
65
+ *
66
+ * @param schema - The TypeBox schema object
67
+ * @returns An OpenAPI Schema object
68
+ *
69
+ * @example Basic Type Conversion
70
+ * ```typescript
71
+ * import { Type } from '@sinclair/typebox'
72
+ *
73
+ * const schema = Type.String({ minLength: 3, maxLength: 50 })
74
+ * const openapi = typeboxToOpenApi(schema)
75
+ * // {
76
+ * // type: 'string',
77
+ * // minLength: 3,
78
+ * // maxLength: 50
79
+ * // }
80
+ * ```
81
+ *
82
+ * @example Object Type Conversion
83
+ * ```typescript
84
+ * const userSchema = Type.Object({
85
+ * name: Type.String(),
86
+ * email: Type.String({ format: 'email' }),
87
+ * age: Type.Optional(Type.Number({ minimum: 0 }))
88
+ * })
89
+ *
90
+ * const openapi = typeboxToOpenApi(userSchema)
91
+ * // {
92
+ * // type: 'object',
93
+ * // properties: {
94
+ * // name: { type: 'string' },
95
+ * // email: { type: 'string', format: 'email' },
96
+ * // age: { type: 'number', minimum: 0 }
97
+ * // },
98
+ * // required: ['name', 'email']
99
+ * // }
100
+ * ```
101
+ */
102
+ export declare function typeboxToOpenApi(schema: TSchema): OpenApiSchema;
103
+ /**
104
+ * Creates an Astral Resource Definition.
105
+ *
106
+ * This function builds resource definitions for the Gravito Astral automatic API documentation system,
107
+ * combining TypeBox schemas with HTTP route information to generate complete API endpoint documentation.
108
+ *
109
+ * @param options - Resource definition options
110
+ * @returns Astral Resource Definition object
111
+ *
112
+ * @example Create POST endpoint resource
113
+ * ```typescript
114
+ * const createUserResource = createAstralResource({
115
+ * path: '/users',
116
+ * method: 'POST',
117
+ * summary: 'Create New User',
118
+ * description: 'Creates a new user account with the provided data',
119
+ * tags: ['users'],
120
+ * requestSchema: Type.Object({
121
+ * name: Type.String({ minLength: 1 }),
122
+ * email: Type.String({ format: 'email' }),
123
+ * password: Type.String({ minLength: 8 })
124
+ * }),
125
+ * responseSchema: Type.Object({
126
+ * id: Type.String({ format: 'uuid' }),
127
+ * name: Type.String(),
128
+ * email: Type.String(),
129
+ * createdAt: Type.String({ format: 'date-time' })
130
+ * }),
131
+ * responseStatusCode: 201
132
+ * })
133
+ * ```
134
+ *
135
+ * @example Create GET endpoint resource (no request body)
136
+ * ```typescript
137
+ * const getUsersResource = createAstralResource({
138
+ * path: '/users',
139
+ * method: 'GET',
140
+ * summary: 'Get User List',
141
+ * tags: ['users'],
142
+ * responseSchema: Type.Array(
143
+ * Type.Object({
144
+ * id: Type.String(),
145
+ * name: Type.String()
146
+ * })
147
+ * )
148
+ * })
149
+ * ```
150
+ */
151
+ export declare function createAstralResource(options: {
152
+ path: string;
153
+ method: string;
154
+ summary?: string;
155
+ description?: string;
156
+ tags?: string[];
157
+ requestSchema?: TSchema;
158
+ requestDescription?: string;
159
+ requestRequired?: boolean;
160
+ responseSchema: TSchema;
161
+ responseDescription?: string;
162
+ responseStatusCode?: number;
163
+ }): AstralResource;
164
+ /**
165
+ * Batch creates CRUD Resource Definitions.
166
+ *
167
+ * Automatically generates all relevant Astral resource definitions for standard CRUD operations.
168
+ *
169
+ * @param options - CRUD resource options
170
+ * @returns CRUD Resource Definition object
171
+ *
172
+ * @example Create full User CRUD resources
173
+ * ```typescript
174
+ * const userCrudResources = createCrudResources({
175
+ * resourceName: 'user',
176
+ * basePath: '/users',
177
+ * tags: ['users'],
178
+ * schemas: {
179
+ * item: Type.Object({
180
+ * id: Type.String({ format: 'uuid' }),
181
+ * name: Type.String(),
182
+ * email: Type.String({ format: 'email' })
183
+ * }),
184
+ * create: Type.Object({
185
+ * name: Type.String(),
186
+ * email: Type.String({ format: 'email' })
187
+ * }),
188
+ * update: Type.Partial(Type.Object({
189
+ * name: Type.String(),
190
+ * email: Type.String({ format: 'email' })
191
+ * }))
192
+ * }
193
+ * })
194
+ *
195
+ * // Returns: { list, get, create, update, delete }
196
+ * ```
197
+ */
198
+ export declare function createCrudResources(options: {
199
+ resourceName: string;
200
+ basePath: string;
201
+ tags?: string[];
202
+ schemas: {
203
+ item: TSchema;
204
+ list?: TSchema;
205
+ create: TSchema;
206
+ update: TSchema;
207
+ };
208
+ }): {
209
+ list: AstralResource;
210
+ get: AstralResource;
211
+ create: AstralResource;
212
+ update: AstralResource;
213
+ delete: AstralResource;
214
+ };
@@ -0,0 +1,50 @@
1
+ import type { GravitoContext } from '@gravito/photon';
2
+ import type { Static, TSchema } from '@sinclair/typebox';
3
+ /**
4
+ * Supported data sources for validation.
5
+ *
6
+ * Determines which part of the HTTP request should be validated against the schema.
7
+ */
8
+ export type ValidationSource = 'json' | 'query' | 'param' | 'form';
9
+ /**
10
+ * Details of a validation error.
11
+ *
12
+ * Provides structured information about why a specific field failed validation.
13
+ */
14
+ export interface ValidationError {
15
+ /** The path to the invalid field (e.g., "/user/name") */
16
+ path: string;
17
+ /** A human-readable description of the error */
18
+ message: string;
19
+ /** The value or type that was expected */
20
+ expected?: string;
21
+ /** The value or type that was actually received */
22
+ received?: string;
23
+ }
24
+ /**
25
+ * The outcome of a validation attempt.
26
+ *
27
+ * Passed to validation hooks to allow custom handling of success or failure states.
28
+ *
29
+ * @template T - The TypeBox schema type used for validation
30
+ */
31
+ export interface ValidationResult<T extends TSchema> {
32
+ /** Indicates whether the data satisfied the schema */
33
+ success: boolean;
34
+ /** The validated and typed data (only present if success is true) */
35
+ data?: Static<T>;
36
+ /** A list of validation errors (only present if success is false) */
37
+ errors?: ValidationError[];
38
+ }
39
+ /**
40
+ * A callback function for intercepting validation results.
41
+ *
42
+ * Use this hook to customize error responses, log failures, or transform data
43
+ * after validation but before the main route handler.
44
+ *
45
+ * @template T - The TypeBox schema type
46
+ * @param result - The outcome of the validation
47
+ * @param context - The Photon request context
48
+ * @returns A Response object to short-circuit the request, or undefined to proceed
49
+ */
50
+ export type ValidationHook<T extends TSchema> = (result: ValidationResult<T>, context: GravitoContext) => Response | Promise<Response> | undefined;
@@ -0,0 +1,22 @@
1
+ import type { TObject, TPartial } from '@sinclair/typebox';
2
+ /**
3
+ * Creates a new schema with all properties of the original schema set to optional.
4
+ *
5
+ * This utility is useful for creating "update" schemas (e.g., for PATCH requests)
6
+ * where clients can send a subset of fields to update.
7
+ *
8
+ * @param schema - The original TypeBox object schema
9
+ * @returns A new schema with all properties marked as optional
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const userSchema = Schema.Object({
14
+ * name: Schema.String(),
15
+ * email: Schema.String()
16
+ * })
17
+ *
18
+ * // All fields in updateSchema are optional
19
+ * const updateSchema = partial(userSchema)
20
+ * ```
21
+ */
22
+ export declare function partial<T extends TObject>(schema: T): TPartial<T>;