@engjts/nexus 0.1.7 → 0.1.9
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/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/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/documentation/01-getting-started.md +0 -240
- package/documentation/02-context.md +0 -335
- package/documentation/03-routing.md +0 -397
- package/documentation/04-middleware.md +0 -483
- package/documentation/05-validation.md +0 -514
- package/documentation/06-error-handling.md +0 -465
- package/documentation/07-performance.md +0 -364
- package/documentation/08-adapters.md +0 -470
- package/documentation/09-api-reference.md +0 -548
- package/documentation/10-examples.md +0 -582
- package/documentation/11-deployment.md +0 -477
- package/documentation/12-sentry.md +0 -620
- package/documentation/13-sentry-data-storage.md +0 -996
- package/documentation/14-sentry-data-reference.md +0 -457
- package/documentation/15-sentry-summary.md +0 -409
- package/documentation/16-alerts-system.md +0 -745
- package/documentation/17-alert-adapters.md +0 -696
- package/documentation/18-alerts-implementation-summary.md +0 -385
- package/documentation/19-class-based-routing.md +0 -840
- package/documentation/20-websocket-realtime.md +0 -813
- package/documentation/21-cache-system.md +0 -510
- package/documentation/22-job-queue.md +0 -772
- package/documentation/23-sentry-plugin.md +0 -551
- package/documentation/24-testing-utilities.md +0 -1287
- package/documentation/25-api-versioning.md +0 -533
- package/documentation/26-context-store.md +0 -607
- package/documentation/27-dependency-injection.md +0 -329
- package/documentation/28-lifecycle-hooks.md +0 -521
- package/documentation/29-package-structure.md +0 -196
- package/documentation/30-plugin-system.md +0 -414
- package/documentation/31-jwt-authentication.md +0 -597
- package/documentation/32-cli.md +0 -268
- package/documentation/ALERTS-COMPLETE-SUMMARY.md +0 -429
- package/documentation/ALERTS-INDEX.md +0 -330
- package/documentation/ALERTS-QUICK-REFERENCE.md +0 -286
- package/documentation/README.md +0 -178
- package/documentation/index.html +0 -34
- package/modern_framework_paper.md +0 -1870
- package/public/css/style.css +0 -87
- package/public/index.html +0 -34
- package/public/js/app.js +0 -27
- package/src/advanced/cache/InMemoryCacheStore.ts +0 -68
- package/src/advanced/cache/MultiTierCache.ts +0 -194
- package/src/advanced/cache/RedisCacheStore.ts +0 -341
- package/src/advanced/cache/index.ts +0 -5
- package/src/advanced/cache/types.ts +0 -40
- package/src/advanced/graphql/SimpleDataLoader.ts +0 -42
- package/src/advanced/graphql/index.ts +0 -22
- package/src/advanced/graphql/server.ts +0 -252
- package/src/advanced/graphql/types.ts +0 -42
- package/src/advanced/jobs/InMemoryQueueStore.ts +0 -68
- package/src/advanced/jobs/JobQueue.ts +0 -556
- package/src/advanced/jobs/RedisQueueStore.ts +0 -367
- package/src/advanced/jobs/index.ts +0 -5
- package/src/advanced/jobs/types.ts +0 -70
- package/src/advanced/observability/APMManager.ts +0 -163
- package/src/advanced/observability/AlertManager.ts +0 -109
- package/src/advanced/observability/MetricRegistry.ts +0 -151
- package/src/advanced/observability/ObservabilityCenter.ts +0 -304
- package/src/advanced/observability/StructuredLogger.ts +0 -154
- package/src/advanced/observability/TracingManager.ts +0 -117
- package/src/advanced/observability/adapters.ts +0 -304
- package/src/advanced/observability/createObservabilityMiddleware.ts +0 -63
- package/src/advanced/observability/index.ts +0 -11
- package/src/advanced/observability/types.ts +0 -174
- package/src/advanced/playground/extractPathParams.ts +0 -6
- package/src/advanced/playground/generateFieldExample.ts +0 -31
- package/src/advanced/playground/generatePlaygroundHTML.ts +0 -1849
- package/src/advanced/playground/generateSummary.ts +0 -19
- package/src/advanced/playground/getTagFromPath.ts +0 -9
- package/src/advanced/playground/index.ts +0 -8
- package/src/advanced/playground/playground.ts +0 -170
- package/src/advanced/playground/types.ts +0 -20
- package/src/advanced/playground/zodToExample.ts +0 -16
- package/src/advanced/playground/zodToParams.ts +0 -15
- package/src/advanced/postman/buildAuth.ts +0 -31
- package/src/advanced/postman/buildBody.ts +0 -15
- package/src/advanced/postman/buildQueryParams.ts +0 -27
- package/src/advanced/postman/buildRequestItem.ts +0 -36
- package/src/advanced/postman/buildResponses.ts +0 -11
- package/src/advanced/postman/buildUrl.ts +0 -33
- package/src/advanced/postman/capitalize.ts +0 -4
- package/src/advanced/postman/generateCollection.ts +0 -59
- package/src/advanced/postman/generateEnvironment.ts +0 -34
- package/src/advanced/postman/generateExampleFromZod.ts +0 -21
- package/src/advanced/postman/generateFieldExample.ts +0 -45
- package/src/advanced/postman/generateName.ts +0 -20
- package/src/advanced/postman/generateUUID.ts +0 -11
- package/src/advanced/postman/getTagFromPath.ts +0 -10
- package/src/advanced/postman/index.ts +0 -28
- package/src/advanced/postman/postman.ts +0 -156
- package/src/advanced/postman/slugify.ts +0 -7
- package/src/advanced/postman/types.ts +0 -140
- package/src/advanced/realtime/index.ts +0 -18
- package/src/advanced/realtime/websocket.ts +0 -231
- package/src/advanced/sentry/index.ts +0 -1236
- package/src/advanced/sentry/types.ts +0 -355
- package/src/advanced/static/generateDirectoryListing.ts +0 -47
- package/src/advanced/static/generateETag.ts +0 -7
- package/src/advanced/static/getMimeType.ts +0 -9
- package/src/advanced/static/index.ts +0 -32
- package/src/advanced/static/isSafePath.ts +0 -13
- package/src/advanced/static/publicDir.ts +0 -21
- package/src/advanced/static/serveStatic.ts +0 -225
- package/src/advanced/static/spa.ts +0 -24
- package/src/advanced/static/types.ts +0 -159
- package/src/advanced/swagger/SwaggerGenerator.ts +0 -66
- package/src/advanced/swagger/buildOperation.ts +0 -61
- package/src/advanced/swagger/buildParameters.ts +0 -61
- package/src/advanced/swagger/buildRequestBody.ts +0 -21
- package/src/advanced/swagger/buildResponses.ts +0 -54
- package/src/advanced/swagger/capitalize.ts +0 -5
- package/src/advanced/swagger/convertPath.ts +0 -9
- package/src/advanced/swagger/createSwagger.ts +0 -12
- package/src/advanced/swagger/generateOperationId.ts +0 -21
- package/src/advanced/swagger/generateSpec.ts +0 -105
- package/src/advanced/swagger/generateSummary.ts +0 -24
- package/src/advanced/swagger/generateSwaggerUI.ts +0 -70
- package/src/advanced/swagger/generateThemeCss.ts +0 -53
- package/src/advanced/swagger/index.ts +0 -25
- package/src/advanced/swagger/swagger.ts +0 -237
- package/src/advanced/swagger/types.ts +0 -206
- package/src/advanced/swagger/zodFieldToOpenAPI.ts +0 -94
- package/src/advanced/swagger/zodSchemaToOpenAPI.ts +0 -50
- package/src/advanced/swagger/zodToOpenAPI.ts +0 -22
- package/src/advanced/testing/factory.ts +0 -509
- package/src/advanced/testing/harness.ts +0 -612
- package/src/advanced/testing/index.ts +0 -430
- package/src/advanced/testing/load-test.ts +0 -618
- package/src/advanced/testing/mock-server.ts +0 -498
- package/src/advanced/testing/mock.ts +0 -670
- package/src/cli/bin.ts +0 -9
- package/src/cli/cli.ts +0 -158
- package/src/cli/commands/add.ts +0 -178
- package/src/cli/commands/build.ts +0 -73
- package/src/cli/commands/create.ts +0 -166
- package/src/cli/commands/dev.ts +0 -85
- package/src/cli/commands/generate.ts +0 -99
- package/src/cli/commands/help.ts +0 -95
- package/src/cli/commands/init.ts +0 -91
- package/src/cli/commands/version.ts +0 -38
- package/src/cli/index.ts +0 -6
- package/src/cli/templates/generators.ts +0 -359
- package/src/cli/templates/index.ts +0 -680
- package/src/cli/utils/exec.ts +0 -52
- package/src/cli/utils/file-system.ts +0 -78
- package/src/cli/utils/logger.ts +0 -111
- package/src/core/adapter.ts +0 -88
- package/src/core/application.ts +0 -1335
- package/src/core/context-pool.ts +0 -127
- package/src/core/context.ts +0 -412
- package/src/core/index.ts +0 -80
- package/src/core/middleware.ts +0 -262
- package/src/core/performance/buffer-pool.ts +0 -108
- package/src/core/performance/middleware-optimizer.ts +0 -162
- package/src/core/plugin/PluginManager.ts +0 -435
- package/src/core/plugin/builder.ts +0 -358
- package/src/core/plugin/index.ts +0 -50
- package/src/core/plugin/types.ts +0 -214
- package/src/core/router/file-router.ts +0 -594
- package/src/core/router/index.ts +0 -227
- package/src/core/router/radix-tree.ts +0 -226
- package/src/core/store/index.ts +0 -30
- package/src/core/store/registry.ts +0 -178
- package/src/core/store/request-store.ts +0 -240
- package/src/core/store/types.ts +0 -233
- package/src/core/types.ts +0 -574
- package/src/database/adapter.ts +0 -35
- package/src/database/adapters/index.ts +0 -1
- package/src/database/adapters/mysql.ts +0 -669
- package/src/database/database.ts +0 -70
- package/src/database/dialect.ts +0 -388
- package/src/database/index.ts +0 -12
- package/src/database/migrations.ts +0 -86
- package/src/database/optimizer.ts +0 -125
- package/src/database/query-builder.ts +0 -404
- package/src/database/realtime.ts +0 -53
- package/src/database/schema.ts +0 -71
- package/src/database/transactions.ts +0 -56
- package/src/database/types.ts +0 -87
- package/src/deployment/cluster.ts +0 -471
- package/src/deployment/config.ts +0 -454
- package/src/deployment/docker.ts +0 -599
- package/src/deployment/graceful-shutdown.ts +0 -373
- package/src/deployment/index.ts +0 -56
- package/src/index.ts +0 -264
- package/src/security/adapter.ts +0 -318
- package/src/security/auth/JWTPlugin.ts +0 -234
- package/src/security/auth/JWTProvider.ts +0 -316
- package/src/security/auth/adapter.ts +0 -12
- package/src/security/auth/jwt.ts +0 -234
- package/src/security/auth/middleware.ts +0 -188
- package/src/security/csrf.ts +0 -220
- package/src/security/headers.ts +0 -108
- package/src/security/index.ts +0 -60
- package/src/security/rate-limit/adapter.ts +0 -7
- package/src/security/rate-limit/memory.ts +0 -108
- package/src/security/rate-limit/middleware.ts +0 -181
- package/src/security/sanitization.ts +0 -75
- package/src/security/types.ts +0 -240
- package/src/security/utils.ts +0 -52
- package/tsconfig.json +0 -39
package/src/core/router/index.ts
DELETED
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Router implementation with schema validation
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { RadixTree } from './radix-tree';
|
|
6
|
-
import {
|
|
7
|
-
HTTPMethod,
|
|
8
|
-
Handler,
|
|
9
|
-
Middleware,
|
|
10
|
-
RouteConfig,
|
|
11
|
-
RouteMatch,
|
|
12
|
-
SchemaConfig,
|
|
13
|
-
RouteMeta,
|
|
14
|
-
Context
|
|
15
|
-
} from '../types';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Route with validation schema and metadata
|
|
19
|
-
*/
|
|
20
|
-
export interface RouteEntry {
|
|
21
|
-
handler: Handler;
|
|
22
|
-
middlewares: Middleware[];
|
|
23
|
-
schema?: SchemaConfig;
|
|
24
|
-
meta?: RouteMeta;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Router class
|
|
29
|
-
*/
|
|
30
|
-
export class Router {
|
|
31
|
-
private trees: Map<HTTPMethod, RadixTree> = new Map();
|
|
32
|
-
private routes: Array<{ method: HTTPMethod; path: string; config: RouteEntry }> = [];
|
|
33
|
-
private prefix: string = '';
|
|
34
|
-
|
|
35
|
-
constructor(prefix: string = '') {
|
|
36
|
-
this.prefix = prefix;
|
|
37
|
-
// Initialize trees for each HTTP method
|
|
38
|
-
const methods: HTTPMethod[] = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'];
|
|
39
|
-
for (const method of methods) {
|
|
40
|
-
this.trees.set(method, new RadixTree());
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Register a route
|
|
46
|
-
*/
|
|
47
|
-
addRoute(config: RouteConfig): void {
|
|
48
|
-
const { method, path, handler, middlewares = [], schema, meta } = config;
|
|
49
|
-
const fullPath = this.prefix ? `${this.prefix}${path}` : path;
|
|
50
|
-
|
|
51
|
-
const tree = this.trees.get(method);
|
|
52
|
-
if (!tree) {
|
|
53
|
-
throw new Error(`Unsupported HTTP method: ${method}`);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Wrap handler with schema validation if provided
|
|
57
|
-
const wrappedHandler = schema ? this.wrapWithValidation(handler, schema) : handler;
|
|
58
|
-
|
|
59
|
-
tree.insert(fullPath, wrappedHandler, middlewares);
|
|
60
|
-
|
|
61
|
-
// Store for introspection (including schema and meta for documentation)
|
|
62
|
-
this.routes.push({
|
|
63
|
-
method,
|
|
64
|
-
path: fullPath,
|
|
65
|
-
config: { handler: wrappedHandler, middlewares, schema, meta }
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Find a matching route
|
|
71
|
-
*/
|
|
72
|
-
match(method: string, path: string): RouteMatch | null {
|
|
73
|
-
const tree = this.trees.get(method as HTTPMethod);
|
|
74
|
-
if (!tree) {
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const result = tree.search(path);
|
|
79
|
-
if (!result) {
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return {
|
|
84
|
-
handler: result.handler,
|
|
85
|
-
params: result.params,
|
|
86
|
-
middlewares: result.middlewares,
|
|
87
|
-
schema: undefined // Schema already applied in wrapped handler
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Get all registered routes with full metadata
|
|
93
|
-
*/
|
|
94
|
-
getRoutes(): Array<{ method: string; path: string; schema?: SchemaConfig; meta?: RouteMeta }> {
|
|
95
|
-
return this.routes.map(r => ({
|
|
96
|
-
method: r.method,
|
|
97
|
-
path: r.path,
|
|
98
|
-
schema: r.config.schema,
|
|
99
|
-
meta: r.config.meta
|
|
100
|
-
}));
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Get raw route configs for merging into Application
|
|
105
|
-
*/
|
|
106
|
-
getRawRoutes(): Array<{ method: HTTPMethod; path: string; config: RouteEntry }> {
|
|
107
|
-
return this.routes;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Get internal radix trees for merging
|
|
112
|
-
*/
|
|
113
|
-
getTrees(): Map<HTTPMethod, RadixTree> {
|
|
114
|
-
return this.trees;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Mount another router with a prefix (group routes)
|
|
119
|
-
*
|
|
120
|
-
* @example
|
|
121
|
-
* ```typescript
|
|
122
|
-
* const userRoutes = new Router();
|
|
123
|
-
* userRoutes.get('/', getAllUsers);
|
|
124
|
-
* userRoutes.get('/:id', getUserById);
|
|
125
|
-
*
|
|
126
|
-
* const router = new Router();
|
|
127
|
-
* router.group('/api/users', userRoutes);
|
|
128
|
-
* ```
|
|
129
|
-
*/
|
|
130
|
-
group(prefix: string, router: Router): void {
|
|
131
|
-
const routes = router.getRawRoutes();
|
|
132
|
-
for (const route of routes) {
|
|
133
|
-
const fullPath = `${prefix}${route.path}`;
|
|
134
|
-
this.addRoute({
|
|
135
|
-
method: route.method,
|
|
136
|
-
path: fullPath,
|
|
137
|
-
handler: route.config.handler,
|
|
138
|
-
middlewares: route.config.middlewares,
|
|
139
|
-
schema: route.config.schema,
|
|
140
|
-
meta: route.config.meta
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Convenience methods for HTTP verbs
|
|
147
|
-
*/
|
|
148
|
-
get(path: string, handler: Handler, options?: Partial<RouteConfig>): void {
|
|
149
|
-
this.addRoute({ method: 'GET', path, handler, ...options });
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
post(path: string, handler: Handler, options?: Partial<RouteConfig>): void {
|
|
153
|
-
this.addRoute({ method: 'POST', path, handler, ...options });
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
put(path: string, handler: Handler, options?: Partial<RouteConfig>): void {
|
|
157
|
-
this.addRoute({ method: 'PUT', path, handler, ...options });
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
delete(path: string, handler: Handler, options?: Partial<RouteConfig>): void {
|
|
161
|
-
this.addRoute({ method: 'DELETE', path, handler, ...options });
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
patch(path: string, handler: Handler, options?: Partial<RouteConfig>): void {
|
|
165
|
-
this.addRoute({ method: 'PATCH', path, handler, ...options });
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* Wrap handler with schema validation
|
|
170
|
-
*/
|
|
171
|
-
private wrapWithValidation(handler: Handler, schema: SchemaConfig): Handler {
|
|
172
|
-
return async (ctx: Context) => {
|
|
173
|
-
try {
|
|
174
|
-
// Validate params
|
|
175
|
-
if (schema.params) {
|
|
176
|
-
ctx.params = await schema.params.parseAsync(ctx.params);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Validate query
|
|
180
|
-
if (schema.query) {
|
|
181
|
-
ctx.query = await schema.query.parseAsync(ctx.query);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Validate body
|
|
185
|
-
if (schema.body) {
|
|
186
|
-
ctx.body = await schema.body.parseAsync(ctx.body);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Validate headers
|
|
190
|
-
if (schema.headers) {
|
|
191
|
-
ctx.headers = await schema.headers.parseAsync(ctx.headers);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Call original handler with validated data
|
|
195
|
-
return handler(ctx, {});
|
|
196
|
-
} catch (error: any) {
|
|
197
|
-
// Zod validation error
|
|
198
|
-
if (error.name === 'ZodError') {
|
|
199
|
-
// Use custom error handler if provided
|
|
200
|
-
if (schema.onValidationError) {
|
|
201
|
-
const customResponse = schema.onValidationError(error.errors, ctx);
|
|
202
|
-
// If it's already a Response object, return it
|
|
203
|
-
if (customResponse?.statusCode) {
|
|
204
|
-
return customResponse;
|
|
205
|
-
}
|
|
206
|
-
// Otherwise wrap it as JSON response
|
|
207
|
-
return ctx.json(customResponse, 400);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// Default error response - extract first error message
|
|
211
|
-
const firstError = error.errors[0];
|
|
212
|
-
const message = firstError?.message || 'Validation failed';
|
|
213
|
-
|
|
214
|
-
return ctx.json({
|
|
215
|
-
success: false,
|
|
216
|
-
message
|
|
217
|
-
}, 400);
|
|
218
|
-
}
|
|
219
|
-
throw error;
|
|
220
|
-
}
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// Re-export file router
|
|
226
|
-
export { FileRouter, createFileRouter, useFileRoutes } from './file-router';
|
|
227
|
-
export type { FileRouterOptions, FileRouteClass, RouteModule } from './file-router';
|
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Radix Tree implementation for efficient routing
|
|
3
|
-
* Provides O(log n) route lookup performance
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { Handler, Middleware } from '../types';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Node in the radix tree
|
|
10
|
-
*/
|
|
11
|
-
export class RadixNode {
|
|
12
|
-
// The path segment this node represents
|
|
13
|
-
segment: string;
|
|
14
|
-
|
|
15
|
-
// Full path for this node (used for debugging)
|
|
16
|
-
fullPath: string;
|
|
17
|
-
|
|
18
|
-
// Handler if this is a terminal node
|
|
19
|
-
handler: Handler | null = null;
|
|
20
|
-
|
|
21
|
-
// Middleware for this route
|
|
22
|
-
middlewares: Middleware[] = [];
|
|
23
|
-
|
|
24
|
-
// Child nodes
|
|
25
|
-
children: RadixNode[] = [];
|
|
26
|
-
|
|
27
|
-
// Pattern type: 'static', 'param', or 'wildcard'
|
|
28
|
-
type: 'static' | 'param' | 'wildcard' = 'static';
|
|
29
|
-
|
|
30
|
-
// Parameter name for param nodes
|
|
31
|
-
paramName?: string;
|
|
32
|
-
|
|
33
|
-
constructor(segment: string, fullPath: string) {
|
|
34
|
-
this.segment = segment;
|
|
35
|
-
this.fullPath = fullPath;
|
|
36
|
-
|
|
37
|
-
// Detect node type
|
|
38
|
-
if (segment.startsWith(':')) {
|
|
39
|
-
this.type = 'param';
|
|
40
|
-
this.paramName = segment.slice(1);
|
|
41
|
-
} else if (segment === '*' || segment.startsWith('*')) {
|
|
42
|
-
this.type = 'wildcard';
|
|
43
|
-
this.paramName = segment.length > 1 ? segment.slice(1) : 'wildcard';
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Add a child node
|
|
49
|
-
*/
|
|
50
|
-
addChild(node: RadixNode): void {
|
|
51
|
-
// Insert maintaining order: static > param > wildcard
|
|
52
|
-
const priority = this.getTypePriority(node.type);
|
|
53
|
-
let inserted = false;
|
|
54
|
-
|
|
55
|
-
for (let i = 0; i < this.children.length; i++) {
|
|
56
|
-
const childPriority = this.getTypePriority(this.children[i].type);
|
|
57
|
-
if (priority < childPriority) {
|
|
58
|
-
this.children.splice(i, 0, node);
|
|
59
|
-
inserted = true;
|
|
60
|
-
break;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (!inserted) {
|
|
65
|
-
this.children.push(node);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Find a child by segment
|
|
71
|
-
*/
|
|
72
|
-
findChild(segment: string): RadixNode | null {
|
|
73
|
-
for (const child of this.children) {
|
|
74
|
-
if (child.segment === segment) {
|
|
75
|
-
return child;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Get type priority for ordering (lower = higher priority)
|
|
83
|
-
*/
|
|
84
|
-
private getTypePriority(type: 'static' | 'param' | 'wildcard'): number {
|
|
85
|
-
switch (type) {
|
|
86
|
-
case 'static': return 0;
|
|
87
|
-
case 'param': return 1;
|
|
88
|
-
case 'wildcard': return 2;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Radix tree for route storage and matching
|
|
95
|
-
*/
|
|
96
|
-
export class RadixTree {
|
|
97
|
-
private root: RadixNode;
|
|
98
|
-
|
|
99
|
-
constructor() {
|
|
100
|
-
this.root = new RadixNode('', '/');
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Insert a route into the tree
|
|
105
|
-
*/
|
|
106
|
-
insert(path: string, handler: Handler, middlewares: Middleware[] = []): void {
|
|
107
|
-
const segments = this.splitPath(path);
|
|
108
|
-
let current = this.root;
|
|
109
|
-
|
|
110
|
-
for (let i = 0; i < segments.length; i++) {
|
|
111
|
-
const segment = segments[i];
|
|
112
|
-
let child = current.findChild(segment);
|
|
113
|
-
|
|
114
|
-
if (!child) {
|
|
115
|
-
const fullPath = '/' + segments.slice(0, i + 1).join('/');
|
|
116
|
-
child = new RadixNode(segment, fullPath);
|
|
117
|
-
current.addChild(child);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
current = child;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Set handler and middleware at terminal node
|
|
124
|
-
current.handler = handler;
|
|
125
|
-
current.middlewares = middlewares;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Search for a route match
|
|
130
|
-
*/
|
|
131
|
-
search(path: string): { handler: Handler; params: Record<string, string>; middlewares: Middleware[] } | null {
|
|
132
|
-
const segments = this.splitPath(path);
|
|
133
|
-
const params: Record<string, string> = {};
|
|
134
|
-
|
|
135
|
-
const result = this.searchNode(this.root, segments, 0, params);
|
|
136
|
-
|
|
137
|
-
if (result) {
|
|
138
|
-
return {
|
|
139
|
-
handler: result.handler!,
|
|
140
|
-
params,
|
|
141
|
-
middlewares: result.middlewares
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return null;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Recursively search nodes
|
|
150
|
-
*/
|
|
151
|
-
private searchNode(
|
|
152
|
-
node: RadixNode,
|
|
153
|
-
segments: string[],
|
|
154
|
-
index: number,
|
|
155
|
-
params: Record<string, string>
|
|
156
|
-
): RadixNode | null {
|
|
157
|
-
// Reached end of path
|
|
158
|
-
if (index === segments.length) {
|
|
159
|
-
return node.handler ? node : null;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
const segment = segments[index];
|
|
163
|
-
|
|
164
|
-
// Try children in priority order
|
|
165
|
-
for (const child of node.children) {
|
|
166
|
-
if (child.type === 'static') {
|
|
167
|
-
// Exact match required
|
|
168
|
-
if (child.segment === segment) {
|
|
169
|
-
const result = this.searchNode(child, segments, index + 1, params);
|
|
170
|
-
if (result) return result;
|
|
171
|
-
}
|
|
172
|
-
} else if (child.type === 'param') {
|
|
173
|
-
// Parameter match - capture value
|
|
174
|
-
const oldValue = params[child.paramName!];
|
|
175
|
-
params[child.paramName!] = segment;
|
|
176
|
-
|
|
177
|
-
const result = this.searchNode(child, segments, index + 1, params);
|
|
178
|
-
if (result) return result;
|
|
179
|
-
|
|
180
|
-
// Backtrack
|
|
181
|
-
if (oldValue === undefined) {
|
|
182
|
-
delete params[child.paramName!];
|
|
183
|
-
} else {
|
|
184
|
-
params[child.paramName!] = oldValue;
|
|
185
|
-
}
|
|
186
|
-
} else if (child.type === 'wildcard') {
|
|
187
|
-
// Wildcard match - capture remaining path
|
|
188
|
-
params[child.paramName!] = segments.slice(index).join('/');
|
|
189
|
-
return child;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return null;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Split path into segments
|
|
198
|
-
*/
|
|
199
|
-
private splitPath(path: string): string[] {
|
|
200
|
-
// Remove leading/trailing slashes and split
|
|
201
|
-
const normalized = path.replace(/^\/+|\/+$/g, '');
|
|
202
|
-
return normalized ? normalized.split('/') : [];
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Get all routes (for debugging/introspection)
|
|
207
|
-
*/
|
|
208
|
-
getAllRoutes(): Array<{ path: string; hasHandler: boolean }> {
|
|
209
|
-
const routes: Array<{ path: string; hasHandler: boolean }> = [];
|
|
210
|
-
this.collectRoutes(this.root, routes);
|
|
211
|
-
return routes;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Recursively collect all routes
|
|
216
|
-
*/
|
|
217
|
-
private collectRoutes(node: RadixNode, routes: Array<{ path: string; hasHandler: boolean }>): void {
|
|
218
|
-
if (node.handler) {
|
|
219
|
-
routes.push({ path: node.fullPath, hasHandler: true });
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
for (const child of node.children) {
|
|
223
|
-
this.collectRoutes(child, routes);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
package/src/core/store/index.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ContextStore System
|
|
3
|
-
* State management inspired by Flutter's Provider pattern
|
|
4
|
-
*
|
|
5
|
-
* Two types of stores:
|
|
6
|
-
* - ContextStore: Global singleton, persists across all requests
|
|
7
|
-
* - RequestStore: Per-request scoped, disposed after response
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
// Core store classes
|
|
11
|
-
export { ContextStore } from './types';
|
|
12
|
-
export { RequestStore } from './request-store';
|
|
13
|
-
|
|
14
|
-
// Types
|
|
15
|
-
export type {
|
|
16
|
-
StoreListener,
|
|
17
|
-
DisposeCallback,
|
|
18
|
-
StoreConstructor,
|
|
19
|
-
StateOf,
|
|
20
|
-
StoreOptions
|
|
21
|
-
} from './types';
|
|
22
|
-
|
|
23
|
-
export type {
|
|
24
|
-
RequestStoreConstructor,
|
|
25
|
-
RequestStateOf
|
|
26
|
-
} from './request-store';
|
|
27
|
-
|
|
28
|
-
// Registries
|
|
29
|
-
export { StoreRegistry, createStoreRegistry } from './registry';
|
|
30
|
-
export { RequestStoreRegistry } from './request-store';
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* StoreRegistry - Global store container
|
|
3
|
-
* Manages all ContextStore instances at application level
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { ContextStore, StoreConstructor, StoreRegistryOptions } from './types';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* StoreRegistry manages all stores in the application
|
|
10
|
-
* Ensures singleton instances and handles lifecycle
|
|
11
|
-
*/
|
|
12
|
-
export class StoreRegistry {
|
|
13
|
-
private stores: Map<StoreConstructor<any>, ContextStore<any>> = new Map();
|
|
14
|
-
private options: StoreRegistryOptions;
|
|
15
|
-
|
|
16
|
-
constructor(options: StoreRegistryOptions = {}) {
|
|
17
|
-
this.options = options;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Register a store class
|
|
22
|
-
* Creates instance immediately
|
|
23
|
-
*
|
|
24
|
-
* @param StoreClass - Store constructor class
|
|
25
|
-
* @returns The created store instance
|
|
26
|
-
*/
|
|
27
|
-
register<T extends ContextStore<any>>(StoreClass: StoreConstructor<T>): T {
|
|
28
|
-
if (this.stores.has(StoreClass)) {
|
|
29
|
-
if (this.options.debug) {
|
|
30
|
-
console.log(`[StoreRegistry] Store ${StoreClass.name} already registered`);
|
|
31
|
-
}
|
|
32
|
-
return this.stores.get(StoreClass) as T;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const instance = new StoreClass({ debug: this.options.debug });
|
|
36
|
-
this.stores.set(StoreClass, instance);
|
|
37
|
-
|
|
38
|
-
if (this.options.debug) {
|
|
39
|
-
console.log(`[StoreRegistry] Registered store: ${StoreClass.name}`);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Call onInit if defined
|
|
43
|
-
const initResult = instance.onInit();
|
|
44
|
-
if (initResult instanceof Promise) {
|
|
45
|
-
initResult.catch(err => {
|
|
46
|
-
console.error(`[StoreRegistry] Error in ${StoreClass.name}.onInit():`, err);
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return instance;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Register multiple stores at once
|
|
55
|
-
*
|
|
56
|
-
* @param storeClasses - Array of store constructor classes
|
|
57
|
-
*/
|
|
58
|
-
registerAll(storeClasses: StoreConstructor<any>[]): void {
|
|
59
|
-
storeClasses.forEach(StoreClass => this.register(StoreClass));
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Get a store instance by its class
|
|
64
|
-
* Throws if store is not registered
|
|
65
|
-
*
|
|
66
|
-
* @param StoreClass - Store constructor class
|
|
67
|
-
* @returns Store instance
|
|
68
|
-
*/
|
|
69
|
-
get<T extends ContextStore<any>>(StoreClass: StoreConstructor<T>): T {
|
|
70
|
-
const store = this.stores.get(StoreClass);
|
|
71
|
-
|
|
72
|
-
if (!store) {
|
|
73
|
-
throw new Error(
|
|
74
|
-
`[StoreRegistry] Store ${StoreClass.name} is not registered. ` +
|
|
75
|
-
`Make sure to call app.stores([${StoreClass.name}]) before accessing it.`
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return store as T;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Check if a store is registered
|
|
84
|
-
*
|
|
85
|
-
* @param StoreClass - Store constructor class
|
|
86
|
-
*/
|
|
87
|
-
has<T extends ContextStore<any>>(StoreClass: StoreConstructor<T>): boolean {
|
|
88
|
-
return this.stores.has(StoreClass);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Get a store instance, or register it if not exists
|
|
93
|
-
* Useful for lazy initialization
|
|
94
|
-
*
|
|
95
|
-
* @param StoreClass - Store constructor class
|
|
96
|
-
* @returns Store instance
|
|
97
|
-
*/
|
|
98
|
-
getOrRegister<T extends ContextStore<any>>(StoreClass: StoreConstructor<T>): T {
|
|
99
|
-
if (!this.stores.has(StoreClass)) {
|
|
100
|
-
return this.register(StoreClass);
|
|
101
|
-
}
|
|
102
|
-
return this.stores.get(StoreClass) as T;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Remove a store from registry and dispose it
|
|
107
|
-
*
|
|
108
|
-
* @param StoreClass - Store constructor class
|
|
109
|
-
*/
|
|
110
|
-
unregister<T extends ContextStore<any>>(StoreClass: StoreConstructor<T>): void {
|
|
111
|
-
const store = this.stores.get(StoreClass);
|
|
112
|
-
|
|
113
|
-
if (store) {
|
|
114
|
-
store.dispose();
|
|
115
|
-
this.stores.delete(StoreClass);
|
|
116
|
-
|
|
117
|
-
if (this.options.debug) {
|
|
118
|
-
console.log(`[StoreRegistry] Unregistered store: ${StoreClass.name}`);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Get all registered store classes
|
|
125
|
-
*/
|
|
126
|
-
getRegisteredStores(): StoreConstructor<any>[] {
|
|
127
|
-
return Array.from(this.stores.keys());
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Get store count
|
|
132
|
-
*/
|
|
133
|
-
get size(): number {
|
|
134
|
-
return this.stores.size;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Dispose all stores and clear registry
|
|
139
|
-
*/
|
|
140
|
-
dispose(): void {
|
|
141
|
-
if (this.options.debug) {
|
|
142
|
-
console.log(`[StoreRegistry] Disposing all stores (${this.stores.size})`);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
this.stores.forEach((store, StoreClass) => {
|
|
146
|
-
try {
|
|
147
|
-
store.dispose();
|
|
148
|
-
} catch (error) {
|
|
149
|
-
console.error(`[StoreRegistry] Error disposing ${StoreClass.name}:`, error);
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
this.stores.clear();
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/**
|
|
157
|
-
* Get debug info about all stores
|
|
158
|
-
*/
|
|
159
|
-
getDebugInfo(): Record<string, { listenerCount: number; isInitialized: boolean }> {
|
|
160
|
-
const info: Record<string, { listenerCount: number; isInitialized: boolean }> = {};
|
|
161
|
-
|
|
162
|
-
this.stores.forEach((store, StoreClass) => {
|
|
163
|
-
info[StoreClass.name] = {
|
|
164
|
-
listenerCount: store.listenerCount,
|
|
165
|
-
isInitialized: store.isInitialized
|
|
166
|
-
};
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
return info;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Create a new store registry
|
|
175
|
-
*/
|
|
176
|
-
export function createStoreRegistry(options?: StoreRegistryOptions): StoreRegistry {
|
|
177
|
-
return new StoreRegistry(options);
|
|
178
|
-
}
|