@engjts/nexus 0.1.7 → 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.
Files changed (72) hide show
  1. package/BENCHMARK_REPORT.md +343 -0
  2. package/dist/advanced/playground/generatePlaygroundHTML.d.ts.map +1 -1
  3. package/dist/advanced/playground/generatePlaygroundHTML.js +107 -0
  4. package/dist/advanced/playground/generatePlaygroundHTML.js.map +1 -1
  5. package/dist/advanced/playground/playground.d.ts +19 -0
  6. package/dist/advanced/playground/playground.d.ts.map +1 -1
  7. package/dist/advanced/playground/playground.js +70 -0
  8. package/dist/advanced/playground/playground.js.map +1 -1
  9. package/dist/advanced/playground/types.d.ts +20 -0
  10. package/dist/advanced/playground/types.d.ts.map +1 -1
  11. package/dist/core/application.d.ts +14 -0
  12. package/dist/core/application.d.ts.map +1 -1
  13. package/dist/core/application.js +173 -71
  14. package/dist/core/application.js.map +1 -1
  15. package/dist/core/context-pool.d.ts +2 -13
  16. package/dist/core/context-pool.d.ts.map +1 -1
  17. package/dist/core/context-pool.js +7 -45
  18. package/dist/core/context-pool.js.map +1 -1
  19. package/dist/core/context.d.ts +108 -5
  20. package/dist/core/context.d.ts.map +1 -1
  21. package/dist/core/context.js +449 -53
  22. package/dist/core/context.js.map +1 -1
  23. package/dist/core/index.d.ts +1 -0
  24. package/dist/core/index.d.ts.map +1 -1
  25. package/dist/core/index.js +9 -1
  26. package/dist/core/index.js.map +1 -1
  27. package/dist/core/middleware.d.ts +6 -0
  28. package/dist/core/middleware.d.ts.map +1 -1
  29. package/dist/core/middleware.js +83 -84
  30. package/dist/core/middleware.js.map +1 -1
  31. package/dist/core/performance/fast-json.d.ts +149 -0
  32. package/dist/core/performance/fast-json.d.ts.map +1 -0
  33. package/dist/core/performance/fast-json.js +473 -0
  34. package/dist/core/performance/fast-json.js.map +1 -0
  35. package/dist/core/router/file-router.d.ts +20 -7
  36. package/dist/core/router/file-router.d.ts.map +1 -1
  37. package/dist/core/router/file-router.js +41 -13
  38. package/dist/core/router/file-router.js.map +1 -1
  39. package/dist/core/router/index.d.ts +6 -0
  40. package/dist/core/router/index.d.ts.map +1 -1
  41. package/dist/core/router/index.js +33 -6
  42. package/dist/core/router/index.js.map +1 -1
  43. package/dist/core/router/radix-tree.d.ts +4 -1
  44. package/dist/core/router/radix-tree.d.ts.map +1 -1
  45. package/dist/core/router/radix-tree.js +7 -3
  46. package/dist/core/router/radix-tree.js.map +1 -1
  47. package/dist/core/serializer.d.ts +251 -0
  48. package/dist/core/serializer.d.ts.map +1 -0
  49. package/dist/core/serializer.js +290 -0
  50. package/dist/core/serializer.js.map +1 -0
  51. package/dist/core/types.d.ts +39 -1
  52. package/dist/core/types.d.ts.map +1 -1
  53. package/dist/core/types.js.map +1 -1
  54. package/dist/index.d.ts +1 -0
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +12 -2
  57. package/dist/index.js.map +1 -1
  58. package/package.json +3 -1
  59. package/src/advanced/playground/generatePlaygroundHTML.ts +107 -0
  60. package/src/advanced/playground/playground.ts +225 -145
  61. package/src/advanced/playground/types.ts +29 -0
  62. package/src/core/application.ts +202 -84
  63. package/src/core/context-pool.ts +8 -56
  64. package/src/core/context.ts +497 -53
  65. package/src/core/index.ts +14 -0
  66. package/src/core/middleware.ts +99 -89
  67. package/src/core/router/file-router.ts +41 -12
  68. package/src/core/router/index.ts +213 -180
  69. package/src/core/router/radix-tree.ts +20 -4
  70. package/src/core/serializer.ts +397 -0
  71. package/src/core/types.ts +43 -1
  72. 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
  // =============================================================================