@engjts/nexus 0.1.6 → 0.1.8
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/BENCHMARK_REPORT.md +343 -0
- package/dist/advanced/playground/generatePlaygroundHTML.d.ts.map +1 -1
- package/dist/advanced/playground/generatePlaygroundHTML.js +107 -0
- package/dist/advanced/playground/generatePlaygroundHTML.js.map +1 -1
- package/dist/advanced/playground/playground.d.ts +19 -0
- package/dist/advanced/playground/playground.d.ts.map +1 -1
- package/dist/advanced/playground/playground.js +70 -0
- package/dist/advanced/playground/playground.js.map +1 -1
- package/dist/advanced/playground/types.d.ts +20 -0
- package/dist/advanced/playground/types.d.ts.map +1 -1
- package/dist/cli/templates/generators.d.ts.map +1 -1
- package/dist/cli/templates/generators.js +16 -13
- package/dist/cli/templates/generators.js.map +1 -1
- package/dist/cli/templates/index.js +25 -25
- package/dist/core/application.d.ts +14 -0
- package/dist/core/application.d.ts.map +1 -1
- package/dist/core/application.js +173 -71
- package/dist/core/application.js.map +1 -1
- package/dist/core/context-pool.d.ts +2 -13
- package/dist/core/context-pool.d.ts.map +1 -1
- package/dist/core/context-pool.js +7 -45
- package/dist/core/context-pool.js.map +1 -1
- package/dist/core/context.d.ts +108 -5
- package/dist/core/context.d.ts.map +1 -1
- package/dist/core/context.js +449 -53
- package/dist/core/context.js.map +1 -1
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +9 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/middleware.d.ts +6 -0
- package/dist/core/middleware.d.ts.map +1 -1
- package/dist/core/middleware.js +83 -84
- package/dist/core/middleware.js.map +1 -1
- package/dist/core/performance/fast-json.d.ts +149 -0
- package/dist/core/performance/fast-json.d.ts.map +1 -0
- package/dist/core/performance/fast-json.js +473 -0
- package/dist/core/performance/fast-json.js.map +1 -0
- package/dist/core/router/file-router.d.ts +20 -7
- package/dist/core/router/file-router.d.ts.map +1 -1
- package/dist/core/router/file-router.js +41 -13
- package/dist/core/router/file-router.js.map +1 -1
- package/dist/core/router/index.d.ts +6 -0
- package/dist/core/router/index.d.ts.map +1 -1
- package/dist/core/router/index.js +33 -6
- package/dist/core/router/index.js.map +1 -1
- package/dist/core/router/radix-tree.d.ts +4 -1
- package/dist/core/router/radix-tree.d.ts.map +1 -1
- package/dist/core/router/radix-tree.js +7 -3
- package/dist/core/router/radix-tree.js.map +1 -1
- package/dist/core/serializer.d.ts +251 -0
- package/dist/core/serializer.d.ts.map +1 -0
- package/dist/core/serializer.js +290 -0
- package/dist/core/serializer.js.map +1 -0
- package/dist/core/types.d.ts +39 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
- package/src/advanced/playground/generatePlaygroundHTML.ts +107 -0
- package/src/advanced/playground/playground.ts +225 -145
- package/src/advanced/playground/types.ts +29 -0
- package/src/cli/templates/generators.ts +16 -13
- package/src/cli/templates/index.ts +25 -25
- package/src/core/application.ts +202 -84
- package/src/core/context-pool.ts +8 -56
- package/src/core/context.ts +497 -53
- package/src/core/index.ts +14 -0
- package/src/core/middleware.ts +99 -89
- package/src/core/router/file-router.ts +41 -12
- package/src/core/router/index.ts +213 -180
- package/src/core/router/radix-tree.ts +20 -4
- package/src/core/serializer.ts +397 -0
- package/src/core/types.ts +43 -1
- package/src/index.ts +17 -0
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fast JSON Serializer Module
|
|
3
|
+
* Uses fast-json-stringify for 2-3x faster JSON serialization
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* // Define response schema
|
|
8
|
+
* const userSchema = {
|
|
9
|
+
* type: 'object',
|
|
10
|
+
* properties: {
|
|
11
|
+
* id: { type: 'number' },
|
|
12
|
+
* name: { type: 'string' },
|
|
13
|
+
* email: { type: 'string' }
|
|
14
|
+
* }
|
|
15
|
+
* };
|
|
16
|
+
*
|
|
17
|
+
* // Create serializer
|
|
18
|
+
* const serialize = createSerializer(userSchema);
|
|
19
|
+
*
|
|
20
|
+
* // Use in handler (2-3x faster than JSON.stringify)
|
|
21
|
+
* app.get('/user', {
|
|
22
|
+
* responseSchema: userSchema,
|
|
23
|
+
* handler: async (ctx) => ({ id: 1, name: 'John', email: 'john@example.com' })
|
|
24
|
+
* });
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import fastJson from 'fast-json-stringify';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* JSON Schema type definition for fast-json-stringify
|
|
32
|
+
*/
|
|
33
|
+
export interface JSONSchema {
|
|
34
|
+
type?: string;
|
|
35
|
+
properties?: Record<string, JSONSchema>;
|
|
36
|
+
items?: JSONSchema | JSONSchema[];
|
|
37
|
+
additionalProperties?: boolean | JSONSchema;
|
|
38
|
+
required?: string[];
|
|
39
|
+
nullable?: boolean;
|
|
40
|
+
default?: any;
|
|
41
|
+
enum?: any[];
|
|
42
|
+
const?: any;
|
|
43
|
+
format?: string;
|
|
44
|
+
minimum?: number;
|
|
45
|
+
maximum?: number;
|
|
46
|
+
minLength?: number;
|
|
47
|
+
maxLength?: number;
|
|
48
|
+
pattern?: string;
|
|
49
|
+
$ref?: string;
|
|
50
|
+
$id?: string;
|
|
51
|
+
definitions?: Record<string, JSONSchema>;
|
|
52
|
+
allOf?: JSONSchema[];
|
|
53
|
+
anyOf?: JSONSchema[];
|
|
54
|
+
oneOf?: JSONSchema[];
|
|
55
|
+
if?: JSONSchema;
|
|
56
|
+
then?: JSONSchema;
|
|
57
|
+
else?: JSONSchema;
|
|
58
|
+
// Array specific
|
|
59
|
+
minItems?: number;
|
|
60
|
+
maxItems?: number;
|
|
61
|
+
uniqueItems?: boolean;
|
|
62
|
+
// Object specific
|
|
63
|
+
minProperties?: number;
|
|
64
|
+
maxProperties?: number;
|
|
65
|
+
patternProperties?: Record<string, JSONSchema>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Response schema configuration for routes
|
|
70
|
+
*/
|
|
71
|
+
export interface ResponseSchemaConfig {
|
|
72
|
+
/** Schema for 2xx responses */
|
|
73
|
+
'2xx'?: JSONSchema;
|
|
74
|
+
/** Schema for specific status codes */
|
|
75
|
+
200?: JSONSchema;
|
|
76
|
+
201?: JSONSchema;
|
|
77
|
+
204?: JSONSchema;
|
|
78
|
+
/** Schema for error responses */
|
|
79
|
+
'4xx'?: JSONSchema;
|
|
80
|
+
400?: JSONSchema;
|
|
81
|
+
401?: JSONSchema;
|
|
82
|
+
403?: JSONSchema;
|
|
83
|
+
404?: JSONSchema;
|
|
84
|
+
'5xx'?: JSONSchema;
|
|
85
|
+
500?: JSONSchema;
|
|
86
|
+
/** Default schema for any status code */
|
|
87
|
+
default?: JSONSchema;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Serializer function type
|
|
92
|
+
*/
|
|
93
|
+
export type SerializerFunction = (data: any) => string;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Serializer options for fast-json-stringify
|
|
97
|
+
*/
|
|
98
|
+
export interface SerializerOptions {
|
|
99
|
+
/** Use strict mode for schema validation */
|
|
100
|
+
mode?: 'debug' | 'standalone';
|
|
101
|
+
/** Rounding mode for numbers */
|
|
102
|
+
rounding?: 'ceil' | 'floor' | 'round' | 'trunc';
|
|
103
|
+
/** Large array mode optimization */
|
|
104
|
+
largeArrayMechanism?: 'default' | 'json-stringify';
|
|
105
|
+
/** Large array size threshold */
|
|
106
|
+
largeArraySize?: number;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Compiled serializers cache
|
|
111
|
+
* Maps route path + method to serializer functions
|
|
112
|
+
*/
|
|
113
|
+
class SerializerRegistry {
|
|
114
|
+
private serializers: Map<string, Map<number | string, SerializerFunction>> = new Map();
|
|
115
|
+
private schemaCache: WeakMap<JSONSchema, SerializerFunction> = new WeakMap();
|
|
116
|
+
private options: SerializerOptions;
|
|
117
|
+
|
|
118
|
+
constructor(options: SerializerOptions = {}) {
|
|
119
|
+
this.options = {
|
|
120
|
+
mode: 'standalone',
|
|
121
|
+
rounding: 'trunc',
|
|
122
|
+
largeArrayMechanism: 'default',
|
|
123
|
+
largeArraySize: 20000,
|
|
124
|
+
...options
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Compile a schema into a serializer function
|
|
130
|
+
*/
|
|
131
|
+
compile(schema: JSONSchema): SerializerFunction {
|
|
132
|
+
// Check cache first
|
|
133
|
+
const cached = this.schemaCache.get(schema);
|
|
134
|
+
if (cached) return cached;
|
|
135
|
+
|
|
136
|
+
// Compile new serializer
|
|
137
|
+
const serializer = fastJson(schema as any, {
|
|
138
|
+
mode: this.options.mode,
|
|
139
|
+
rounding: this.options.rounding,
|
|
140
|
+
largeArrayMechanism: this.options.largeArrayMechanism,
|
|
141
|
+
largeArraySize: this.options.largeArraySize
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Cache it
|
|
145
|
+
this.schemaCache.set(schema, serializer);
|
|
146
|
+
return serializer;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Register serializers for a route
|
|
151
|
+
*/
|
|
152
|
+
register(routeKey: string, schemas: ResponseSchemaConfig): void {
|
|
153
|
+
const routeSerializers = new Map<number | string, SerializerFunction>();
|
|
154
|
+
|
|
155
|
+
for (const [statusKey, schema] of Object.entries(schemas)) {
|
|
156
|
+
if (schema) {
|
|
157
|
+
const serializer = this.compile(schema);
|
|
158
|
+
routeSerializers.set(statusKey, serializer);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
this.serializers.set(routeKey, routeSerializers);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Get serializer for a route and status code
|
|
167
|
+
*/
|
|
168
|
+
get(routeKey: string, statusCode: number): SerializerFunction | null {
|
|
169
|
+
const routeSerializers = this.serializers.get(routeKey);
|
|
170
|
+
if (!routeSerializers) return null;
|
|
171
|
+
|
|
172
|
+
// Try exact match first
|
|
173
|
+
const exactMatch = routeSerializers.get(statusCode);
|
|
174
|
+
if (exactMatch) return exactMatch;
|
|
175
|
+
|
|
176
|
+
// Try status code ranges (2xx, 4xx, 5xx)
|
|
177
|
+
const range = `${Math.floor(statusCode / 100)}xx`;
|
|
178
|
+
const rangeMatch = routeSerializers.get(range);
|
|
179
|
+
if (rangeMatch) return rangeMatch;
|
|
180
|
+
|
|
181
|
+
// Try default
|
|
182
|
+
return routeSerializers.get('default') || null;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Check if route has registered serializers
|
|
187
|
+
*/
|
|
188
|
+
has(routeKey: string): boolean {
|
|
189
|
+
return this.serializers.has(routeKey);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Clear all serializers
|
|
194
|
+
*/
|
|
195
|
+
clear(): void {
|
|
196
|
+
this.serializers.clear();
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Get route key from method and path
|
|
201
|
+
*/
|
|
202
|
+
static getRouteKey(method: string, path: string): string {
|
|
203
|
+
return `${method}:${path}`;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Global serializer registry instance
|
|
209
|
+
*/
|
|
210
|
+
export const serializerRegistry = new SerializerRegistry();
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Create a standalone serializer from schema
|
|
214
|
+
* Use this for manual serialization outside of routes
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* ```typescript
|
|
218
|
+
* const userSerializer = createSerializer({
|
|
219
|
+
* type: 'object',
|
|
220
|
+
* properties: {
|
|
221
|
+
* id: { type: 'number' },
|
|
222
|
+
* name: { type: 'string' }
|
|
223
|
+
* }
|
|
224
|
+
* });
|
|
225
|
+
*
|
|
226
|
+
* const json = userSerializer({ id: 1, name: 'John' });
|
|
227
|
+
* // Much faster than JSON.stringify!
|
|
228
|
+
* ```
|
|
229
|
+
*/
|
|
230
|
+
export function createSerializer(schema: JSONSchema, options?: SerializerOptions): SerializerFunction {
|
|
231
|
+
return fastJson(schema as any, {
|
|
232
|
+
mode: options?.mode || 'standalone',
|
|
233
|
+
rounding: options?.rounding || 'trunc',
|
|
234
|
+
largeArrayMechanism: options?.largeArrayMechanism || 'default',
|
|
235
|
+
largeArraySize: options?.largeArraySize || 20000
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Create an array serializer optimized for large arrays
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* ```typescript
|
|
244
|
+
* const usersSerializer = createArraySerializer({
|
|
245
|
+
* type: 'object',
|
|
246
|
+
* properties: {
|
|
247
|
+
* id: { type: 'number' },
|
|
248
|
+
* name: { type: 'string' }
|
|
249
|
+
* }
|
|
250
|
+
* });
|
|
251
|
+
*
|
|
252
|
+
* // Optimized for arrays with 100+ items
|
|
253
|
+
* const json = usersSerializer(users);
|
|
254
|
+
* ```
|
|
255
|
+
*/
|
|
256
|
+
export function createArraySerializer(itemSchema: JSONSchema, options?: SerializerOptions): SerializerFunction {
|
|
257
|
+
const arraySchema: JSONSchema = {
|
|
258
|
+
type: 'array',
|
|
259
|
+
items: itemSchema
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
return fastJson(arraySchema as any, {
|
|
263
|
+
mode: options?.mode || 'standalone',
|
|
264
|
+
rounding: options?.rounding || 'trunc',
|
|
265
|
+
// For large arrays, use optimized mechanism
|
|
266
|
+
largeArrayMechanism: options?.largeArrayMechanism || 'default',
|
|
267
|
+
largeArraySize: options?.largeArraySize || 20000
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Common schemas for quick use
|
|
273
|
+
*/
|
|
274
|
+
export const CommonSchemas = {
|
|
275
|
+
/** String type */
|
|
276
|
+
string: { type: 'string' } as JSONSchema,
|
|
277
|
+
|
|
278
|
+
/** Number type */
|
|
279
|
+
number: { type: 'number' } as JSONSchema,
|
|
280
|
+
|
|
281
|
+
/** Integer type */
|
|
282
|
+
integer: { type: 'integer' } as JSONSchema,
|
|
283
|
+
|
|
284
|
+
/** Boolean type */
|
|
285
|
+
boolean: { type: 'boolean' } as JSONSchema,
|
|
286
|
+
|
|
287
|
+
/** Null type */
|
|
288
|
+
null: { type: 'null' } as JSONSchema,
|
|
289
|
+
|
|
290
|
+
/** Any type (no validation, uses JSON.stringify internally) */
|
|
291
|
+
any: {} as JSONSchema,
|
|
292
|
+
|
|
293
|
+
/** UUID string format */
|
|
294
|
+
uuid: { type: 'string', format: 'uuid' } as JSONSchema,
|
|
295
|
+
|
|
296
|
+
/** Email string format */
|
|
297
|
+
email: { type: 'string', format: 'email' } as JSONSchema,
|
|
298
|
+
|
|
299
|
+
/** Date-time string format */
|
|
300
|
+
datetime: { type: 'string', format: 'date-time' } as JSONSchema,
|
|
301
|
+
|
|
302
|
+
/** Date string format */
|
|
303
|
+
date: { type: 'string', format: 'date' } as JSONSchema,
|
|
304
|
+
|
|
305
|
+
/** URI string format */
|
|
306
|
+
uri: { type: 'string', format: 'uri' } as JSONSchema,
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Create object schema helper
|
|
310
|
+
* @example
|
|
311
|
+
* ```typescript
|
|
312
|
+
* const userSchema = CommonSchemas.object({
|
|
313
|
+
* id: CommonSchemas.number,
|
|
314
|
+
* name: CommonSchemas.string,
|
|
315
|
+
* email: CommonSchemas.email
|
|
316
|
+
* });
|
|
317
|
+
* ```
|
|
318
|
+
*/
|
|
319
|
+
object: (properties: Record<string, JSONSchema>, required?: string[]): JSONSchema => ({
|
|
320
|
+
type: 'object',
|
|
321
|
+
properties,
|
|
322
|
+
required,
|
|
323
|
+
additionalProperties: false
|
|
324
|
+
}),
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Create array schema helper
|
|
328
|
+
* @example
|
|
329
|
+
* ```typescript
|
|
330
|
+
* const usersSchema = CommonSchemas.array(userSchema);
|
|
331
|
+
* ```
|
|
332
|
+
*/
|
|
333
|
+
array: (items: JSONSchema): JSONSchema => ({
|
|
334
|
+
type: 'array',
|
|
335
|
+
items
|
|
336
|
+
}),
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Create nullable schema helper
|
|
340
|
+
* @example
|
|
341
|
+
* ```typescript
|
|
342
|
+
* const nullableString = CommonSchemas.nullable(CommonSchemas.string);
|
|
343
|
+
* ```
|
|
344
|
+
*/
|
|
345
|
+
nullable: (schema: JSONSchema): JSONSchema => ({
|
|
346
|
+
...schema,
|
|
347
|
+
nullable: true
|
|
348
|
+
}),
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Standard error response schema
|
|
352
|
+
*/
|
|
353
|
+
error: {
|
|
354
|
+
type: 'object',
|
|
355
|
+
properties: {
|
|
356
|
+
error: { type: 'string' },
|
|
357
|
+
message: { type: 'string' },
|
|
358
|
+
statusCode: { type: 'number' }
|
|
359
|
+
}
|
|
360
|
+
} as JSONSchema,
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Standard pagination response schema helper
|
|
364
|
+
* @example
|
|
365
|
+
* ```typescript
|
|
366
|
+
* const paginatedUsers = CommonSchemas.paginated(userSchema);
|
|
367
|
+
* ```
|
|
368
|
+
*/
|
|
369
|
+
paginated: (itemSchema: JSONSchema): JSONSchema => ({
|
|
370
|
+
type: 'object',
|
|
371
|
+
properties: {
|
|
372
|
+
data: { type: 'array', items: itemSchema },
|
|
373
|
+
total: { type: 'number' },
|
|
374
|
+
page: { type: 'number' },
|
|
375
|
+
limit: { type: 'number' },
|
|
376
|
+
totalPages: { type: 'number' }
|
|
377
|
+
}
|
|
378
|
+
})
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Serialize data with fast-json-stringify
|
|
383
|
+
* Falls back to JSON.stringify if no schema is provided
|
|
384
|
+
*/
|
|
385
|
+
export function serialize(data: any, schema?: JSONSchema): string {
|
|
386
|
+
if (!schema) {
|
|
387
|
+
return JSON.stringify(data);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const serializer = serializerRegistry.compile(schema);
|
|
391
|
+
return serializer(data);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Export SerializerRegistry class for advanced usage
|
|
396
|
+
*/
|
|
397
|
+
export { SerializerRegistry };
|
package/src/core/types.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { IncomingMessage, ServerResponse } from 'http';
|
|
|
7
7
|
import { ZodSchema } from 'zod';
|
|
8
8
|
import { Application } from './application';
|
|
9
9
|
import { ContextStore, StoreConstructor, StoreRegistry, RequestStore, RequestStoreConstructor } from './store';
|
|
10
|
+
import { JSONSchema, ResponseSchemaConfig, SerializerFunction } from './serializer';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* HTTP methods supported by the framework
|
|
@@ -105,6 +106,16 @@ export interface Context {
|
|
|
105
106
|
/** Get a value from request-scoped storage */
|
|
106
107
|
get<T = any>(key: string): T | undefined;
|
|
107
108
|
|
|
109
|
+
// Body methods (for sync access after pre-parsing)
|
|
110
|
+
/** Check if body is ready for sync access (no await needed) */
|
|
111
|
+
isBodyReady: boolean;
|
|
112
|
+
|
|
113
|
+
/** Wait for body to be parsed (internal use, rarely needed by user) */
|
|
114
|
+
waitForBody(): Promise<any>;
|
|
115
|
+
|
|
116
|
+
/** Async body getter - use for POST/PUT/PATCH if body might not be ready */
|
|
117
|
+
getBody<T = any>(): Promise<T>;
|
|
118
|
+
|
|
108
119
|
// Utility methods
|
|
109
120
|
json<T>(data: T, status?: number): Response;
|
|
110
121
|
html(content: string, status?: number): Response;
|
|
@@ -157,11 +168,12 @@ export type Middleware<TIn = Context, TOut = Context, TDeps = any> = (
|
|
|
157
168
|
/**
|
|
158
169
|
* Route handler function signature
|
|
159
170
|
* Handlers can return data directly or a Response object
|
|
171
|
+
* Supports both sync and async handlers
|
|
160
172
|
*/
|
|
161
173
|
export type Handler<TContext = Context, TDeps = any> = (
|
|
162
174
|
ctx: TContext,
|
|
163
175
|
deps: TDeps
|
|
164
|
-
) => Promise<Response | any>;
|
|
176
|
+
) => Response | any | Promise<Response | any>;
|
|
165
177
|
|
|
166
178
|
/**
|
|
167
179
|
* Dependency container type
|
|
@@ -221,6 +233,32 @@ export interface SchemaConfig {
|
|
|
221
233
|
query?: ZodSchema;
|
|
222
234
|
body?: ZodSchema;
|
|
223
235
|
headers?: ZodSchema;
|
|
236
|
+
/**
|
|
237
|
+
* Response schema for fast JSON serialization
|
|
238
|
+
* When provided, uses fast-json-stringify for 2-3x faster serialization
|
|
239
|
+
*
|
|
240
|
+
* @example
|
|
241
|
+
* ```typescript
|
|
242
|
+
* app.get('/users', {
|
|
243
|
+
* schema: {
|
|
244
|
+
* response: {
|
|
245
|
+
* 200: {
|
|
246
|
+
* type: 'array',
|
|
247
|
+
* items: {
|
|
248
|
+
* type: 'object',
|
|
249
|
+
* properties: {
|
|
250
|
+
* id: { type: 'number' },
|
|
251
|
+
* name: { type: 'string' }
|
|
252
|
+
* }
|
|
253
|
+
* }
|
|
254
|
+
* }
|
|
255
|
+
* }
|
|
256
|
+
* },
|
|
257
|
+
* handler: async (ctx) => users
|
|
258
|
+
* });
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
261
|
+
response?: ResponseSchemaConfig;
|
|
224
262
|
onValidationError?: ValidationErrorHandler;
|
|
225
263
|
}
|
|
226
264
|
|
|
@@ -246,6 +284,8 @@ export interface RouteConfig<TContext = Context> {
|
|
|
246
284
|
middlewares?: Middleware<any, any>[];
|
|
247
285
|
schema?: SchemaConfig;
|
|
248
286
|
meta?: RouteMeta;
|
|
287
|
+
/** Pre-compiled serializer function (internal use) */
|
|
288
|
+
_serializer?: Map<number | string, SerializerFunction>;
|
|
249
289
|
}
|
|
250
290
|
|
|
251
291
|
/**
|
|
@@ -256,6 +296,8 @@ export interface RouteMatch {
|
|
|
256
296
|
params: Record<string, string>;
|
|
257
297
|
middlewares: Middleware[];
|
|
258
298
|
schema?: SchemaConfig;
|
|
299
|
+
/** Pre-compiled serializer for response (internal use) */
|
|
300
|
+
_serializer?: Map<number | string, SerializerFunction>;
|
|
259
301
|
}
|
|
260
302
|
|
|
261
303
|
/**
|
package/src/index.ts
CHANGED
|
@@ -93,6 +93,23 @@ export {
|
|
|
93
93
|
export { BufferPool, StreamUtils } from './core/performance/buffer-pool';
|
|
94
94
|
export { MiddlewareOptimizer, PerformanceMonitor } from './core/performance/middleware-optimizer';
|
|
95
95
|
|
|
96
|
+
// =============================================================================
|
|
97
|
+
// FAST JSON SERIALIZER
|
|
98
|
+
// =============================================================================
|
|
99
|
+
|
|
100
|
+
export {
|
|
101
|
+
createSerializer,
|
|
102
|
+
createArraySerializer,
|
|
103
|
+
serialize,
|
|
104
|
+
serializerRegistry,
|
|
105
|
+
SerializerRegistry,
|
|
106
|
+
CommonSchemas,
|
|
107
|
+
type JSONSchema,
|
|
108
|
+
type ResponseSchemaConfig,
|
|
109
|
+
type SerializerFunction,
|
|
110
|
+
type SerializerOptions
|
|
111
|
+
} from './core/serializer';
|
|
112
|
+
|
|
96
113
|
// =============================================================================
|
|
97
114
|
// SECURITY
|
|
98
115
|
// =============================================================================
|