@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,473 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Fast JSON Serialization
|
|
4
|
+
*
|
|
5
|
+
* Provides optimized JSON serialization for common response patterns.
|
|
6
|
+
* Inspired by fast-json-stringify but zero dependencies.
|
|
7
|
+
*
|
|
8
|
+
* Key optimizations:
|
|
9
|
+
* 1. Schema-based serialization with pre-compiled serializers
|
|
10
|
+
* 2. Avoids JSON.stringify overhead for simple objects
|
|
11
|
+
* 3. Caches stringified templates for known schemas
|
|
12
|
+
* 4. Fast path for primitives and simple objects
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.FastSerializers = void 0;
|
|
16
|
+
exports.createSerializer = createSerializer;
|
|
17
|
+
exports.fastStringify = fastStringify;
|
|
18
|
+
exports.createRouteSerializer = createRouteSerializer;
|
|
19
|
+
/**
|
|
20
|
+
* Pre-compiled serializer cache
|
|
21
|
+
*/
|
|
22
|
+
const serializerCache = new Map();
|
|
23
|
+
/**
|
|
24
|
+
* Create a fast serializer from a JSON schema
|
|
25
|
+
* Pre-compiles the serialization logic for maximum performance
|
|
26
|
+
*/
|
|
27
|
+
function createSerializer(schema) {
|
|
28
|
+
const schemaKey = JSON.stringify(schema);
|
|
29
|
+
// Check cache first
|
|
30
|
+
const cached = serializerCache.get(schemaKey);
|
|
31
|
+
if (cached) {
|
|
32
|
+
return cached;
|
|
33
|
+
}
|
|
34
|
+
// Compile new serializer
|
|
35
|
+
const serializer = compileSerializer(schema);
|
|
36
|
+
serializerCache.set(schemaKey, serializer);
|
|
37
|
+
return serializer;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Compile a serializer function from schema
|
|
41
|
+
*/
|
|
42
|
+
function compileSerializer(schema) {
|
|
43
|
+
switch (schema.type) {
|
|
44
|
+
case 'string':
|
|
45
|
+
return serializeString;
|
|
46
|
+
case 'number':
|
|
47
|
+
return serializeNumber;
|
|
48
|
+
case 'boolean':
|
|
49
|
+
return serializeBoolean;
|
|
50
|
+
case 'null':
|
|
51
|
+
return () => 'null';
|
|
52
|
+
case 'array':
|
|
53
|
+
return compileSchemaArraySerializer(schema);
|
|
54
|
+
case 'object':
|
|
55
|
+
return compileObjectSerializer(schema);
|
|
56
|
+
default:
|
|
57
|
+
// Fallback to JSON.stringify
|
|
58
|
+
return JSON.stringify;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Fast string serialization with escape handling
|
|
63
|
+
*/
|
|
64
|
+
function serializeString(value) {
|
|
65
|
+
// Fast path: no special characters
|
|
66
|
+
if (!needsEscape(value)) {
|
|
67
|
+
return `"${value}"`;
|
|
68
|
+
}
|
|
69
|
+
return JSON.stringify(value);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Check if string needs escaping
|
|
73
|
+
* Avoids full escape processing for simple strings (90%+ of cases)
|
|
74
|
+
*/
|
|
75
|
+
function needsEscape(str) {
|
|
76
|
+
for (let i = 0; i < str.length; i++) {
|
|
77
|
+
const c = str.charCodeAt(i);
|
|
78
|
+
// Check for: " \ and control characters (< 32)
|
|
79
|
+
if (c === 34 || c === 92 || c < 32) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Fast number serialization
|
|
87
|
+
*/
|
|
88
|
+
function serializeNumber(value) {
|
|
89
|
+
// Fast path for integers
|
|
90
|
+
if (Number.isInteger(value)) {
|
|
91
|
+
return String(value);
|
|
92
|
+
}
|
|
93
|
+
// Handle special cases
|
|
94
|
+
if (!Number.isFinite(value)) {
|
|
95
|
+
return 'null';
|
|
96
|
+
}
|
|
97
|
+
return String(value);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Fast boolean serialization
|
|
101
|
+
*/
|
|
102
|
+
function serializeBoolean(value) {
|
|
103
|
+
return value ? 'true' : 'false';
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Compile array serializer for schema-based compilation
|
|
107
|
+
* This is used when a schema is provided
|
|
108
|
+
*/
|
|
109
|
+
function compileSchemaArraySerializer(schema) {
|
|
110
|
+
if (!schema.items) {
|
|
111
|
+
// Unknown item type, use fast runtime detection
|
|
112
|
+
return fastStringifyArray;
|
|
113
|
+
}
|
|
114
|
+
const itemSerializer = compileSerializer(schema.items);
|
|
115
|
+
return (arr) => {
|
|
116
|
+
if (!arr || arr.length === 0) {
|
|
117
|
+
return '[]';
|
|
118
|
+
}
|
|
119
|
+
let result = '[';
|
|
120
|
+
for (let i = 0; i < arr.length; i++) {
|
|
121
|
+
if (i > 0)
|
|
122
|
+
result += ',';
|
|
123
|
+
result += itemSerializer(arr[i]);
|
|
124
|
+
}
|
|
125
|
+
result += ']';
|
|
126
|
+
return result;
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Ultra-fast array serialization
|
|
131
|
+
* Detects array content type and uses optimized path
|
|
132
|
+
*/
|
|
133
|
+
function fastStringifyArray(arr) {
|
|
134
|
+
if (arr.length === 0)
|
|
135
|
+
return '[]';
|
|
136
|
+
// Sample first item to detect type
|
|
137
|
+
const firstItem = arr[0];
|
|
138
|
+
const firstType = typeof firstItem;
|
|
139
|
+
// Fast path: array of primitives
|
|
140
|
+
if (firstType === 'string' || firstType === 'number' || firstType === 'boolean') {
|
|
141
|
+
let result = '[';
|
|
142
|
+
for (let i = 0; i < arr.length; i++) {
|
|
143
|
+
if (i > 0)
|
|
144
|
+
result += ',';
|
|
145
|
+
const item = arr[i];
|
|
146
|
+
const itemType = typeof item;
|
|
147
|
+
if (itemType === 'string') {
|
|
148
|
+
result += serializeString(item);
|
|
149
|
+
}
|
|
150
|
+
else if (itemType === 'number') {
|
|
151
|
+
result += serializeNumber(item);
|
|
152
|
+
}
|
|
153
|
+
else if (itemType === 'boolean') {
|
|
154
|
+
result += serializeBoolean(item);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
result += 'null';
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
result += ']';
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
// Fast path: array of simple objects (like user list)
|
|
164
|
+
if (firstType === 'object' && firstItem !== null && !Array.isArray(firstItem)) {
|
|
165
|
+
// Detect object shape from first item
|
|
166
|
+
const keys = Object.keys(firstItem);
|
|
167
|
+
const keyCount = keys.length;
|
|
168
|
+
// Only optimize small objects (< 20 properties)
|
|
169
|
+
if (keyCount > 0 && keyCount <= 20) {
|
|
170
|
+
// Check if all items have same shape
|
|
171
|
+
let sameShape = true;
|
|
172
|
+
for (let i = 1; i < Math.min(arr.length, 5); i++) {
|
|
173
|
+
const item = arr[i];
|
|
174
|
+
if (!item || typeof item !== 'object' || Object.keys(item).length !== keyCount) {
|
|
175
|
+
sameShape = false;
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (sameShape) {
|
|
180
|
+
// Use optimized serialization for uniform objects
|
|
181
|
+
let result = '[';
|
|
182
|
+
for (let i = 0; i < arr.length; i++) {
|
|
183
|
+
if (i > 0)
|
|
184
|
+
result += ',';
|
|
185
|
+
result += fastStringifyObject(arr[i], keys);
|
|
186
|
+
}
|
|
187
|
+
result += ']';
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// Fallback for complex/mixed arrays
|
|
193
|
+
return JSON.stringify(arr);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Fast object serialization with known keys
|
|
197
|
+
* Used for array of objects with uniform shape
|
|
198
|
+
*/
|
|
199
|
+
function fastStringifyObject(obj, keys) {
|
|
200
|
+
if (obj === null || obj === undefined)
|
|
201
|
+
return 'null';
|
|
202
|
+
const objKeys = keys || Object.keys(obj);
|
|
203
|
+
let result = '{';
|
|
204
|
+
let first = true;
|
|
205
|
+
for (const key of objKeys) {
|
|
206
|
+
const value = obj[key];
|
|
207
|
+
if (value === undefined)
|
|
208
|
+
continue;
|
|
209
|
+
if (!first)
|
|
210
|
+
result += ',';
|
|
211
|
+
first = false;
|
|
212
|
+
// Pre-computed key (avoid multiple escapes)
|
|
213
|
+
result += `"${key}":`;
|
|
214
|
+
const valueType = typeof value;
|
|
215
|
+
if (valueType === 'string') {
|
|
216
|
+
result += serializeString(value);
|
|
217
|
+
}
|
|
218
|
+
else if (valueType === 'number') {
|
|
219
|
+
result += serializeNumber(value);
|
|
220
|
+
}
|
|
221
|
+
else if (valueType === 'boolean') {
|
|
222
|
+
result += serializeBoolean(value);
|
|
223
|
+
}
|
|
224
|
+
else if (value === null) {
|
|
225
|
+
result += 'null';
|
|
226
|
+
}
|
|
227
|
+
else if (Array.isArray(value)) {
|
|
228
|
+
// Nested arrays - use fast path if simple
|
|
229
|
+
result += fastStringifyArray(value);
|
|
230
|
+
}
|
|
231
|
+
else if (valueType === 'object') {
|
|
232
|
+
// Nested object - recurse with fast path
|
|
233
|
+
result += fastStringifyObject(value);
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
result += JSON.stringify(value);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
result += '}';
|
|
240
|
+
return result;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Compile object serializer - the key optimization!
|
|
244
|
+
* Pre-computes property order and serializers
|
|
245
|
+
*/
|
|
246
|
+
function compileObjectSerializer(schema) {
|
|
247
|
+
const properties = schema.properties;
|
|
248
|
+
if (!properties || Object.keys(properties).length === 0) {
|
|
249
|
+
// No schema, use JSON.stringify
|
|
250
|
+
return JSON.stringify;
|
|
251
|
+
}
|
|
252
|
+
const keys = Object.keys(properties);
|
|
253
|
+
const propSerializers = [];
|
|
254
|
+
// Pre-compile each property's serializer
|
|
255
|
+
for (const key of keys) {
|
|
256
|
+
propSerializers.push({
|
|
257
|
+
key,
|
|
258
|
+
serializer: compileSerializer(properties[key]),
|
|
259
|
+
jsonKey: `"${key}":` // Pre-compute the key string
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
// Return optimized serializer
|
|
263
|
+
return (obj) => {
|
|
264
|
+
if (obj === null || obj === undefined) {
|
|
265
|
+
return 'null';
|
|
266
|
+
}
|
|
267
|
+
let result = '{';
|
|
268
|
+
let first = true;
|
|
269
|
+
for (const prop of propSerializers) {
|
|
270
|
+
const value = obj[prop.key];
|
|
271
|
+
if (value !== undefined) {
|
|
272
|
+
if (!first)
|
|
273
|
+
result += ',';
|
|
274
|
+
first = false;
|
|
275
|
+
result += prop.jsonKey;
|
|
276
|
+
result += prop.serializer(value);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
// Handle additional properties if schema allows
|
|
280
|
+
if (schema.additionalProperties !== false) {
|
|
281
|
+
for (const key in obj) {
|
|
282
|
+
if (!properties[key] && obj[key] !== undefined) {
|
|
283
|
+
if (!first)
|
|
284
|
+
result += ',';
|
|
285
|
+
first = false;
|
|
286
|
+
result += `"${key}":`;
|
|
287
|
+
result += JSON.stringify(obj[key]);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
result += '}';
|
|
292
|
+
return result;
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Ultra-fast serializers for common response patterns
|
|
297
|
+
* These are hand-optimized for maximum performance
|
|
298
|
+
*/
|
|
299
|
+
exports.FastSerializers = {
|
|
300
|
+
/**
|
|
301
|
+
* { "message": string }
|
|
302
|
+
* Common for simple JSON responses like "Hello, World!"
|
|
303
|
+
*/
|
|
304
|
+
message: (data) => {
|
|
305
|
+
const msg = data.message;
|
|
306
|
+
if (!needsEscape(msg)) {
|
|
307
|
+
return `{"message":"${msg}"}`;
|
|
308
|
+
}
|
|
309
|
+
return `{"message":${JSON.stringify(msg)}}`;
|
|
310
|
+
},
|
|
311
|
+
/**
|
|
312
|
+
* { "echo": string }
|
|
313
|
+
* Common for echo endpoints
|
|
314
|
+
*/
|
|
315
|
+
echo: (data) => {
|
|
316
|
+
const echo = data.echo;
|
|
317
|
+
if (!needsEscape(echo)) {
|
|
318
|
+
return `{"echo":"${echo}"}`;
|
|
319
|
+
}
|
|
320
|
+
return `{"echo":${JSON.stringify(echo)}}`;
|
|
321
|
+
},
|
|
322
|
+
/**
|
|
323
|
+
* { "success": boolean, "data": any }
|
|
324
|
+
* Common API response wrapper
|
|
325
|
+
*/
|
|
326
|
+
successResponse: (data) => {
|
|
327
|
+
if (data.data === undefined) {
|
|
328
|
+
return data.success ? '{"success":true}' : '{"success":false}';
|
|
329
|
+
}
|
|
330
|
+
return `{"success":${data.success},"data":${JSON.stringify(data.data)}}`;
|
|
331
|
+
},
|
|
332
|
+
/**
|
|
333
|
+
* { "error": string }
|
|
334
|
+
* Common error response
|
|
335
|
+
*/
|
|
336
|
+
error: (data) => {
|
|
337
|
+
const err = data.error;
|
|
338
|
+
if (!needsEscape(err)) {
|
|
339
|
+
return `{"error":"${err}"}`;
|
|
340
|
+
}
|
|
341
|
+
return `{"error":${JSON.stringify(err)}}`;
|
|
342
|
+
},
|
|
343
|
+
/**
|
|
344
|
+
* { "received": any, "processed": boolean }
|
|
345
|
+
* Common for POST echo endpoints
|
|
346
|
+
* OPTIMIZED: Use fast path for nested data
|
|
347
|
+
*/
|
|
348
|
+
received: (data) => {
|
|
349
|
+
const receivedType = typeof data.received;
|
|
350
|
+
let receivedStr;
|
|
351
|
+
// Fast path for primitives and simple objects
|
|
352
|
+
if (receivedType === 'string') {
|
|
353
|
+
receivedStr = serializeString(data.received);
|
|
354
|
+
}
|
|
355
|
+
else if (receivedType === 'number') {
|
|
356
|
+
receivedStr = serializeNumber(data.received);
|
|
357
|
+
}
|
|
358
|
+
else if (receivedType === 'boolean') {
|
|
359
|
+
receivedStr = serializeBoolean(data.received);
|
|
360
|
+
}
|
|
361
|
+
else if (data.received === null) {
|
|
362
|
+
receivedStr = 'null';
|
|
363
|
+
}
|
|
364
|
+
else if (Array.isArray(data.received)) {
|
|
365
|
+
receivedStr = fastStringifyArray(data.received);
|
|
366
|
+
}
|
|
367
|
+
else if (receivedType === 'object') {
|
|
368
|
+
receivedStr = fastStringifyObject(data.received);
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
receivedStr = JSON.stringify(data.received);
|
|
372
|
+
}
|
|
373
|
+
return `{"received":${receivedStr},"processed":${data.processed}}`;
|
|
374
|
+
}
|
|
375
|
+
};
|
|
376
|
+
/**
|
|
377
|
+
* Smart JSON stringify that uses fast paths when possible
|
|
378
|
+
* Falls back to JSON.stringify for complex objects
|
|
379
|
+
*
|
|
380
|
+
* OPTIMIZED: Now handles arrays efficiently!
|
|
381
|
+
*/
|
|
382
|
+
function fastStringify(data) {
|
|
383
|
+
if (data === null)
|
|
384
|
+
return 'null';
|
|
385
|
+
if (data === undefined)
|
|
386
|
+
return 'undefined';
|
|
387
|
+
const type = typeof data;
|
|
388
|
+
// Fast paths for primitives
|
|
389
|
+
if (type === 'string')
|
|
390
|
+
return serializeString(data);
|
|
391
|
+
if (type === 'number')
|
|
392
|
+
return serializeNumber(data);
|
|
393
|
+
if (type === 'boolean')
|
|
394
|
+
return serializeBoolean(data);
|
|
395
|
+
// Check for known patterns (hot path optimization)
|
|
396
|
+
if (type === 'object') {
|
|
397
|
+
// Handle arrays with optimized path - BIG WIN for /users endpoint!
|
|
398
|
+
if (Array.isArray(data)) {
|
|
399
|
+
return fastStringifyArray(data);
|
|
400
|
+
}
|
|
401
|
+
// Single property objects - very common in APIs
|
|
402
|
+
const keys = Object.keys(data);
|
|
403
|
+
const keyCount = keys.length;
|
|
404
|
+
if (keyCount === 1) {
|
|
405
|
+
const key = keys[0];
|
|
406
|
+
const value = data[key];
|
|
407
|
+
// { "message": "..." } pattern
|
|
408
|
+
if (key === 'message' && typeof value === 'string') {
|
|
409
|
+
return exports.FastSerializers.message(data);
|
|
410
|
+
}
|
|
411
|
+
// { "echo": "..." } pattern
|
|
412
|
+
if (key === 'echo' && typeof value === 'string') {
|
|
413
|
+
return exports.FastSerializers.echo(data);
|
|
414
|
+
}
|
|
415
|
+
// { "error": "..." } pattern
|
|
416
|
+
if (key === 'error' && typeof value === 'string') {
|
|
417
|
+
return exports.FastSerializers.error(data);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
// Two property patterns - common API responses
|
|
421
|
+
if (keyCount === 2) {
|
|
422
|
+
// { "success": boolean, "data": any }
|
|
423
|
+
if ('success' in data && 'data' in data) {
|
|
424
|
+
return exports.FastSerializers.successResponse(data);
|
|
425
|
+
}
|
|
426
|
+
// { "received": any, "processed": boolean } - POST echo pattern!
|
|
427
|
+
if ('received' in data && 'processed' in data) {
|
|
428
|
+
return exports.FastSerializers.received(data);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
// Multi-property objects - use fast path
|
|
432
|
+
if (keyCount > 2 && keyCount <= 50) {
|
|
433
|
+
return fastStringifyObject(data);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
// Fallback to native JSON.stringify for very complex objects
|
|
437
|
+
return JSON.stringify(data);
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Create a route-specific serializer based on schema
|
|
441
|
+
* Use this in route registration to pre-compile serializers
|
|
442
|
+
*
|
|
443
|
+
* @example
|
|
444
|
+
* ```typescript
|
|
445
|
+
* const serialize = createRouteSerializer({
|
|
446
|
+
* type: 'object',
|
|
447
|
+
* properties: {
|
|
448
|
+
* id: { type: 'number' },
|
|
449
|
+
* name: { type: 'string' },
|
|
450
|
+
* email: { type: 'string' }
|
|
451
|
+
* }
|
|
452
|
+
* });
|
|
453
|
+
*
|
|
454
|
+
* app.get('/user/:id', async (ctx) => {
|
|
455
|
+
* const user = await getUser(ctx.params.id);
|
|
456
|
+
* return {
|
|
457
|
+
* statusCode: 200,
|
|
458
|
+
* headers: { 'Content-Type': 'application/json' },
|
|
459
|
+
* body: serialize(user) // 2-3x faster than JSON.stringify!
|
|
460
|
+
* };
|
|
461
|
+
* });
|
|
462
|
+
* ```
|
|
463
|
+
*/
|
|
464
|
+
function createRouteSerializer(schema) {
|
|
465
|
+
return createSerializer(schema);
|
|
466
|
+
}
|
|
467
|
+
exports.default = {
|
|
468
|
+
createSerializer,
|
|
469
|
+
createRouteSerializer,
|
|
470
|
+
fastStringify,
|
|
471
|
+
FastSerializers: exports.FastSerializers
|
|
472
|
+
};
|
|
473
|
+
//# sourceMappingURL=fast-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fast-json.js","sourceRoot":"","sources":["../../../src/core/performance/fast-json.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,20 +4,26 @@
|
|
|
4
4
|
* Automatically scans a directory and registers routes based on file/folder structure.
|
|
5
5
|
* Designed for class-based routing: 1 file = 1 class = 1 route.
|
|
6
6
|
*
|
|
7
|
-
* Smart filename conventions:
|
|
7
|
+
* Smart filename conventions (only if no body schema):
|
|
8
8
|
* - `index.ts` → GET (default), maps to parent path
|
|
9
9
|
* - `create.ts` → POST, maps to parent path (not /create)
|
|
10
10
|
* - `update.ts` → PUT, maps to parent path (not /update)
|
|
11
11
|
* - `delete.ts` → DELETE, maps to parent path (not /delete)
|
|
12
12
|
* - `patch.ts` → PATCH, maps to parent path (not /patch)
|
|
13
|
-
* - Other files → GET (
|
|
13
|
+
* - Other files → GET (default)
|
|
14
|
+
*
|
|
15
|
+
* Smart body detection (HIGHEST PRIORITY after explicit method):
|
|
16
|
+
* - If schema() returns object with `body` property → POST
|
|
17
|
+
* - Works with inheritance (parent class schema is checked too)
|
|
18
|
+
* - Overrides smart filename detection!
|
|
19
|
+
* - Override by explicitly setting `method` property in class
|
|
14
20
|
*
|
|
15
21
|
* @example
|
|
16
22
|
* ```
|
|
17
23
|
* routes/
|
|
18
24
|
* api/
|
|
19
25
|
* auth/
|
|
20
|
-
* register.ts → POST /api/auth/register (
|
|
26
|
+
* register.ts → POST /api/auth/register (auto-detected via ctx.body!)
|
|
21
27
|
* login.ts → POST /api/auth/login
|
|
22
28
|
* users/
|
|
23
29
|
* index.ts → GET /api/users
|
|
@@ -31,11 +37,18 @@
|
|
|
31
37
|
* Each file exports a class:
|
|
32
38
|
* ```typescript
|
|
33
39
|
* export default class RegisterRoute {
|
|
34
|
-
* method = 'POST'
|
|
40
|
+
* // No need to specify method = 'POST' if schema has body!
|
|
41
|
+
*
|
|
42
|
+
* schema() {
|
|
43
|
+
* return {
|
|
44
|
+
* body: z.object({ ... }) // ← auto-detects POST!
|
|
45
|
+
* };
|
|
46
|
+
* }
|
|
35
47
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
48
|
+
* async handler(ctx: Context) {
|
|
49
|
+
* const data = ctx.body;
|
|
50
|
+
* ...
|
|
51
|
+
* }
|
|
39
52
|
* }
|
|
40
53
|
* ```
|
|
41
54
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-router.d.ts","sourceRoot":"","sources":["../../../src/core/router/file-router.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"file-router.d.ts","sourceRoot":"","sources":["../../../src/core/router/file-router.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AAKH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EACH,UAAU,EACV,OAAO,EAEP,YAAY,EACZ,SAAS,EACT,UAAU,EAGb,MAAM,UAAU,CAAC;AAsClB;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAC9B,uEAAuE;IACvE,GAAG,EAAE,MAAM,CAAC;IACZ,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,2DAA2D;IAC3D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,yDAAyD;IACzD,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC3B,kDAAkD;IAClD,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,iCAAiC;IACjC,MAAM,CAAC,EAAE,MAAM,YAAY,CAAC;IAC5B,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,SAAS,CAAC;IACvB,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,UAAU,EAAE,CAAC;IACjC,wBAAwB;IACxB,OAAO,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IACxB,sCAAsC;IACtC,OAAO,CAAC,EAAE,cAAc,GAAG,CAAC,UAAU,cAAc,CAAC,CAAC;CACzD;AAED;;GAEG;AACH,UAAU,WAAW;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAUD;;;;;;;;GAQG;AACH,qBAAa,UAAU;IACnB,OAAO,CAAC,OAAO,CAA8B;IAC7C,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,eAAe,CAAyB;gBAEpC,OAAO,EAAE,iBAAiB;IAWtC;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAoBpC;;OAEG;IACG,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B/C;;OAEG;YACW,aAAa;IA4C3B;;OAEG;IACH,OAAO,CAAC,WAAW;IAYnB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAQxB;;OAEG;IACH,OAAO,CAAC,YAAY;IAgCpB;;OAEG;IACH,OAAO,CAAC,cAAc;IA+BtB;;OAEG;YACW,aAAa;IAgK3B;;OAEG;YACW,cAAc;IAwB5B;;OAEG;IACH,OAAO,CAAC,wBAAwB;CAKnC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,UAAU,CAEvE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,aAAa,CAC/B,GAAG,EAAE,WAAW,EAChB,OAAO,EAAE,iBAAiB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAGf"}
|
|
@@ -5,20 +5,26 @@
|
|
|
5
5
|
* Automatically scans a directory and registers routes based on file/folder structure.
|
|
6
6
|
* Designed for class-based routing: 1 file = 1 class = 1 route.
|
|
7
7
|
*
|
|
8
|
-
* Smart filename conventions:
|
|
8
|
+
* Smart filename conventions (only if no body schema):
|
|
9
9
|
* - `index.ts` → GET (default), maps to parent path
|
|
10
10
|
* - `create.ts` → POST, maps to parent path (not /create)
|
|
11
11
|
* - `update.ts` → PUT, maps to parent path (not /update)
|
|
12
12
|
* - `delete.ts` → DELETE, maps to parent path (not /delete)
|
|
13
13
|
* - `patch.ts` → PATCH, maps to parent path (not /patch)
|
|
14
|
-
* - Other files → GET (
|
|
14
|
+
* - Other files → GET (default)
|
|
15
|
+
*
|
|
16
|
+
* Smart body detection (HIGHEST PRIORITY after explicit method):
|
|
17
|
+
* - If schema() returns object with `body` property → POST
|
|
18
|
+
* - Works with inheritance (parent class schema is checked too)
|
|
19
|
+
* - Overrides smart filename detection!
|
|
20
|
+
* - Override by explicitly setting `method` property in class
|
|
15
21
|
*
|
|
16
22
|
* @example
|
|
17
23
|
* ```
|
|
18
24
|
* routes/
|
|
19
25
|
* api/
|
|
20
26
|
* auth/
|
|
21
|
-
* register.ts → POST /api/auth/register (
|
|
27
|
+
* register.ts → POST /api/auth/register (auto-detected via ctx.body!)
|
|
22
28
|
* login.ts → POST /api/auth/login
|
|
23
29
|
* users/
|
|
24
30
|
* index.ts → GET /api/users
|
|
@@ -32,11 +38,18 @@
|
|
|
32
38
|
* Each file exports a class:
|
|
33
39
|
* ```typescript
|
|
34
40
|
* export default class RegisterRoute {
|
|
35
|
-
* method = 'POST'
|
|
41
|
+
* // No need to specify method = 'POST' if schema has body!
|
|
42
|
+
*
|
|
43
|
+
* schema() {
|
|
44
|
+
* return {
|
|
45
|
+
* body: z.object({ ... }) // ← auto-detects POST!
|
|
46
|
+
* };
|
|
47
|
+
* }
|
|
36
48
|
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
49
|
+
* async handler(ctx: Context) {
|
|
50
|
+
* const data = ctx.body;
|
|
51
|
+
* ...
|
|
52
|
+
* }
|
|
40
53
|
* }
|
|
41
54
|
* ```
|
|
42
55
|
*/
|
|
@@ -347,18 +360,33 @@ class FileRouter {
|
|
|
347
360
|
}
|
|
348
361
|
// Determine HTTP method:
|
|
349
362
|
// 1. If class explicitly defines method → use it
|
|
350
|
-
// 2. If
|
|
351
|
-
// 3.
|
|
363
|
+
// 2. If schema has body definition → auto-detect as POST (highest priority for body!)
|
|
364
|
+
// 3. If filename is smart (create/update/delete/patch/index) → auto-detect from filename
|
|
365
|
+
// 4. Otherwise → default GET
|
|
352
366
|
let method;
|
|
353
367
|
if (route.method) {
|
|
354
368
|
// Handle both single method and array of methods (use first one for file-based routing)
|
|
355
369
|
method = Array.isArray(route.method) ? route.method[0] : route.method;
|
|
356
370
|
}
|
|
357
|
-
else if (isSmartFilename(nameWithoutExt)) {
|
|
358
|
-
method = getSmartMethod(nameWithoutExt);
|
|
359
|
-
}
|
|
360
371
|
else {
|
|
361
|
-
|
|
372
|
+
// Check schema for body definition first (works with inheritance!)
|
|
373
|
+
const schema = route.schema?.();
|
|
374
|
+
if (this.options.debug) {
|
|
375
|
+
console.log(`🔍 Smart detection for ${filePath}:`);
|
|
376
|
+
console.log(` - schema:`, schema);
|
|
377
|
+
console.log(` - has body:`, !!schema?.body);
|
|
378
|
+
}
|
|
379
|
+
if (schema?.body) {
|
|
380
|
+
// Schema has body → POST (overrides smart filename!)
|
|
381
|
+
method = 'POST';
|
|
382
|
+
}
|
|
383
|
+
else if (isSmartFilename(nameWithoutExt)) {
|
|
384
|
+
// Smart filename detection (create→POST, update→PUT, etc.)
|
|
385
|
+
method = getSmartMethod(nameWithoutExt);
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
method = DEFAULT_METHOD;
|
|
389
|
+
}
|
|
362
390
|
}
|
|
363
391
|
// Validate method
|
|
364
392
|
if (!HTTP_METHODS.includes(method)) {
|