@engjts/nexus 0.1.8 → 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.
Files changed (205) hide show
  1. package/package.json +1 -1
  2. package/BENCHMARK_REPORT.md +0 -343
  3. package/documentation/01-getting-started.md +0 -240
  4. package/documentation/02-context.md +0 -335
  5. package/documentation/03-routing.md +0 -397
  6. package/documentation/04-middleware.md +0 -483
  7. package/documentation/05-validation.md +0 -514
  8. package/documentation/06-error-handling.md +0 -465
  9. package/documentation/07-performance.md +0 -364
  10. package/documentation/08-adapters.md +0 -470
  11. package/documentation/09-api-reference.md +0 -548
  12. package/documentation/10-examples.md +0 -582
  13. package/documentation/11-deployment.md +0 -477
  14. package/documentation/12-sentry.md +0 -620
  15. package/documentation/13-sentry-data-storage.md +0 -996
  16. package/documentation/14-sentry-data-reference.md +0 -457
  17. package/documentation/15-sentry-summary.md +0 -409
  18. package/documentation/16-alerts-system.md +0 -745
  19. package/documentation/17-alert-adapters.md +0 -696
  20. package/documentation/18-alerts-implementation-summary.md +0 -385
  21. package/documentation/19-class-based-routing.md +0 -840
  22. package/documentation/20-websocket-realtime.md +0 -813
  23. package/documentation/21-cache-system.md +0 -510
  24. package/documentation/22-job-queue.md +0 -772
  25. package/documentation/23-sentry-plugin.md +0 -551
  26. package/documentation/24-testing-utilities.md +0 -1287
  27. package/documentation/25-api-versioning.md +0 -533
  28. package/documentation/26-context-store.md +0 -607
  29. package/documentation/27-dependency-injection.md +0 -329
  30. package/documentation/28-lifecycle-hooks.md +0 -521
  31. package/documentation/29-package-structure.md +0 -196
  32. package/documentation/30-plugin-system.md +0 -414
  33. package/documentation/31-jwt-authentication.md +0 -597
  34. package/documentation/32-cli.md +0 -268
  35. package/documentation/ALERTS-COMPLETE-SUMMARY.md +0 -429
  36. package/documentation/ALERTS-INDEX.md +0 -330
  37. package/documentation/ALERTS-QUICK-REFERENCE.md +0 -286
  38. package/documentation/README.md +0 -178
  39. package/documentation/index.html +0 -34
  40. package/modern_framework_paper.md +0 -1870
  41. package/public/css/style.css +0 -87
  42. package/public/index.html +0 -34
  43. package/public/js/app.js +0 -27
  44. package/src/advanced/cache/InMemoryCacheStore.ts +0 -68
  45. package/src/advanced/cache/MultiTierCache.ts +0 -194
  46. package/src/advanced/cache/RedisCacheStore.ts +0 -341
  47. package/src/advanced/cache/index.ts +0 -5
  48. package/src/advanced/cache/types.ts +0 -40
  49. package/src/advanced/graphql/SimpleDataLoader.ts +0 -42
  50. package/src/advanced/graphql/index.ts +0 -22
  51. package/src/advanced/graphql/server.ts +0 -252
  52. package/src/advanced/graphql/types.ts +0 -42
  53. package/src/advanced/jobs/InMemoryQueueStore.ts +0 -68
  54. package/src/advanced/jobs/JobQueue.ts +0 -556
  55. package/src/advanced/jobs/RedisQueueStore.ts +0 -367
  56. package/src/advanced/jobs/index.ts +0 -5
  57. package/src/advanced/jobs/types.ts +0 -70
  58. package/src/advanced/observability/APMManager.ts +0 -163
  59. package/src/advanced/observability/AlertManager.ts +0 -109
  60. package/src/advanced/observability/MetricRegistry.ts +0 -151
  61. package/src/advanced/observability/ObservabilityCenter.ts +0 -304
  62. package/src/advanced/observability/StructuredLogger.ts +0 -154
  63. package/src/advanced/observability/TracingManager.ts +0 -117
  64. package/src/advanced/observability/adapters.ts +0 -304
  65. package/src/advanced/observability/createObservabilityMiddleware.ts +0 -63
  66. package/src/advanced/observability/index.ts +0 -11
  67. package/src/advanced/observability/types.ts +0 -174
  68. package/src/advanced/playground/extractPathParams.ts +0 -6
  69. package/src/advanced/playground/generateFieldExample.ts +0 -31
  70. package/src/advanced/playground/generatePlaygroundHTML.ts +0 -1956
  71. package/src/advanced/playground/generateSummary.ts +0 -19
  72. package/src/advanced/playground/getTagFromPath.ts +0 -9
  73. package/src/advanced/playground/index.ts +0 -8
  74. package/src/advanced/playground/playground.ts +0 -250
  75. package/src/advanced/playground/types.ts +0 -49
  76. package/src/advanced/playground/zodToExample.ts +0 -16
  77. package/src/advanced/playground/zodToParams.ts +0 -15
  78. package/src/advanced/postman/buildAuth.ts +0 -31
  79. package/src/advanced/postman/buildBody.ts +0 -15
  80. package/src/advanced/postman/buildQueryParams.ts +0 -27
  81. package/src/advanced/postman/buildRequestItem.ts +0 -36
  82. package/src/advanced/postman/buildResponses.ts +0 -11
  83. package/src/advanced/postman/buildUrl.ts +0 -33
  84. package/src/advanced/postman/capitalize.ts +0 -4
  85. package/src/advanced/postman/generateCollection.ts +0 -59
  86. package/src/advanced/postman/generateEnvironment.ts +0 -34
  87. package/src/advanced/postman/generateExampleFromZod.ts +0 -21
  88. package/src/advanced/postman/generateFieldExample.ts +0 -45
  89. package/src/advanced/postman/generateName.ts +0 -20
  90. package/src/advanced/postman/generateUUID.ts +0 -11
  91. package/src/advanced/postman/getTagFromPath.ts +0 -10
  92. package/src/advanced/postman/index.ts +0 -28
  93. package/src/advanced/postman/postman.ts +0 -156
  94. package/src/advanced/postman/slugify.ts +0 -7
  95. package/src/advanced/postman/types.ts +0 -140
  96. package/src/advanced/realtime/index.ts +0 -18
  97. package/src/advanced/realtime/websocket.ts +0 -231
  98. package/src/advanced/sentry/index.ts +0 -1236
  99. package/src/advanced/sentry/types.ts +0 -355
  100. package/src/advanced/static/generateDirectoryListing.ts +0 -47
  101. package/src/advanced/static/generateETag.ts +0 -7
  102. package/src/advanced/static/getMimeType.ts +0 -9
  103. package/src/advanced/static/index.ts +0 -32
  104. package/src/advanced/static/isSafePath.ts +0 -13
  105. package/src/advanced/static/publicDir.ts +0 -21
  106. package/src/advanced/static/serveStatic.ts +0 -225
  107. package/src/advanced/static/spa.ts +0 -24
  108. package/src/advanced/static/types.ts +0 -159
  109. package/src/advanced/swagger/SwaggerGenerator.ts +0 -66
  110. package/src/advanced/swagger/buildOperation.ts +0 -61
  111. package/src/advanced/swagger/buildParameters.ts +0 -61
  112. package/src/advanced/swagger/buildRequestBody.ts +0 -21
  113. package/src/advanced/swagger/buildResponses.ts +0 -54
  114. package/src/advanced/swagger/capitalize.ts +0 -5
  115. package/src/advanced/swagger/convertPath.ts +0 -9
  116. package/src/advanced/swagger/createSwagger.ts +0 -12
  117. package/src/advanced/swagger/generateOperationId.ts +0 -21
  118. package/src/advanced/swagger/generateSpec.ts +0 -105
  119. package/src/advanced/swagger/generateSummary.ts +0 -24
  120. package/src/advanced/swagger/generateSwaggerUI.ts +0 -70
  121. package/src/advanced/swagger/generateThemeCss.ts +0 -53
  122. package/src/advanced/swagger/index.ts +0 -25
  123. package/src/advanced/swagger/swagger.ts +0 -237
  124. package/src/advanced/swagger/types.ts +0 -206
  125. package/src/advanced/swagger/zodFieldToOpenAPI.ts +0 -94
  126. package/src/advanced/swagger/zodSchemaToOpenAPI.ts +0 -50
  127. package/src/advanced/swagger/zodToOpenAPI.ts +0 -22
  128. package/src/advanced/testing/factory.ts +0 -509
  129. package/src/advanced/testing/harness.ts +0 -612
  130. package/src/advanced/testing/index.ts +0 -430
  131. package/src/advanced/testing/load-test.ts +0 -618
  132. package/src/advanced/testing/mock-server.ts +0 -498
  133. package/src/advanced/testing/mock.ts +0 -670
  134. package/src/cli/bin.ts +0 -9
  135. package/src/cli/cli.ts +0 -158
  136. package/src/cli/commands/add.ts +0 -178
  137. package/src/cli/commands/build.ts +0 -73
  138. package/src/cli/commands/create.ts +0 -166
  139. package/src/cli/commands/dev.ts +0 -85
  140. package/src/cli/commands/generate.ts +0 -99
  141. package/src/cli/commands/help.ts +0 -95
  142. package/src/cli/commands/init.ts +0 -91
  143. package/src/cli/commands/version.ts +0 -38
  144. package/src/cli/index.ts +0 -6
  145. package/src/cli/templates/generators.ts +0 -359
  146. package/src/cli/templates/index.ts +0 -680
  147. package/src/cli/utils/exec.ts +0 -52
  148. package/src/cli/utils/file-system.ts +0 -78
  149. package/src/cli/utils/logger.ts +0 -111
  150. package/src/core/adapter.ts +0 -88
  151. package/src/core/application.ts +0 -1453
  152. package/src/core/context-pool.ts +0 -79
  153. package/src/core/context.ts +0 -856
  154. package/src/core/index.ts +0 -94
  155. package/src/core/middleware.ts +0 -272
  156. package/src/core/performance/buffer-pool.ts +0 -108
  157. package/src/core/performance/middleware-optimizer.ts +0 -162
  158. package/src/core/plugin/PluginManager.ts +0 -435
  159. package/src/core/plugin/builder.ts +0 -358
  160. package/src/core/plugin/index.ts +0 -50
  161. package/src/core/plugin/types.ts +0 -214
  162. package/src/core/router/file-router.ts +0 -623
  163. package/src/core/router/index.ts +0 -260
  164. package/src/core/router/radix-tree.ts +0 -242
  165. package/src/core/serializer.ts +0 -397
  166. package/src/core/store/index.ts +0 -30
  167. package/src/core/store/registry.ts +0 -178
  168. package/src/core/store/request-store.ts +0 -240
  169. package/src/core/store/types.ts +0 -233
  170. package/src/core/types.ts +0 -616
  171. package/src/database/adapter.ts +0 -35
  172. package/src/database/adapters/index.ts +0 -1
  173. package/src/database/adapters/mysql.ts +0 -669
  174. package/src/database/database.ts +0 -70
  175. package/src/database/dialect.ts +0 -388
  176. package/src/database/index.ts +0 -12
  177. package/src/database/migrations.ts +0 -86
  178. package/src/database/optimizer.ts +0 -125
  179. package/src/database/query-builder.ts +0 -404
  180. package/src/database/realtime.ts +0 -53
  181. package/src/database/schema.ts +0 -71
  182. package/src/database/transactions.ts +0 -56
  183. package/src/database/types.ts +0 -87
  184. package/src/deployment/cluster.ts +0 -471
  185. package/src/deployment/config.ts +0 -454
  186. package/src/deployment/docker.ts +0 -599
  187. package/src/deployment/graceful-shutdown.ts +0 -373
  188. package/src/deployment/index.ts +0 -56
  189. package/src/index.ts +0 -281
  190. package/src/security/adapter.ts +0 -318
  191. package/src/security/auth/JWTPlugin.ts +0 -234
  192. package/src/security/auth/JWTProvider.ts +0 -316
  193. package/src/security/auth/adapter.ts +0 -12
  194. package/src/security/auth/jwt.ts +0 -234
  195. package/src/security/auth/middleware.ts +0 -188
  196. package/src/security/csrf.ts +0 -220
  197. package/src/security/headers.ts +0 -108
  198. package/src/security/index.ts +0 -60
  199. package/src/security/rate-limit/adapter.ts +0 -7
  200. package/src/security/rate-limit/memory.ts +0 -108
  201. package/src/security/rate-limit/middleware.ts +0 -181
  202. package/src/security/sanitization.ts +0 -75
  203. package/src/security/types.ts +0 -240
  204. package/src/security/utils.ts +0 -52
  205. package/tsconfig.json +0 -39
@@ -1,335 +0,0 @@
1
- # Context API
2
-
3
- ## Overview
4
-
5
- The **Context** is the heart of Nexus Framework. It replaces the traditional `req` and `res` pattern with a single, unified, immutable object that contains all request and response data.
6
-
7
- ## Why Context?
8
-
9
- ### Traditional Express.js
10
- ```javascript
11
- app.get('/user/:id', (req, res) => {
12
- const id = req.params.id;
13
- const user = getUser(id);
14
- res.json({ user });
15
- });
16
- ```
17
-
18
- ### Nexus Framework
19
- ```typescript
20
- app.get('/user/:id', async (ctx) => {
21
- const user = await getUser(ctx.params.id);
22
- return { user }; // Auto-converted to JSON
23
- });
24
- ```
25
-
26
- **Benefits:**
27
- - ✅ Single source of truth
28
- - ✅ Immutability enables better testing
29
- - ✅ Type inference works naturally
30
- - ✅ Easier to extend with custom properties
31
-
32
- ## Context Properties
33
-
34
- ### Request Data
35
-
36
- #### `ctx.method`
37
- HTTP method of the request.
38
-
39
- ```typescript
40
- app.get('/info', async (ctx) => {
41
- return { method: ctx.method }; // "GET"
42
- });
43
- ```
44
-
45
- #### `ctx.path`
46
- Path of the request (without query string).
47
-
48
- ```typescript
49
- app.get('/api/users', async (ctx) => {
50
- return { path: ctx.path }; // "/api/users"
51
- });
52
- ```
53
-
54
- #### `ctx.url`
55
- Full URL object.
56
-
57
- ```typescript
58
- app.get('/info', async (ctx) => {
59
- return {
60
- host: ctx.url.host,
61
- protocol: ctx.url.protocol
62
- };
63
- });
64
- ```
65
-
66
- #### `ctx.params`
67
- Route parameters extracted from the path.
68
-
69
- ```typescript
70
- app.get('/users/:id/posts/:postId', async (ctx) => {
71
- const { id, postId } = ctx.params;
72
- return { userId: id, postId };
73
- });
74
- ```
75
-
76
- #### `ctx.query`
77
- Query string parameters.
78
-
79
- ```typescript
80
- // GET /search?q=nexus&limit=10
81
- app.get('/search', async (ctx) => {
82
- const { q, limit } = ctx.query;
83
- return { query: q, limit: parseInt(limit) };
84
- });
85
- ```
86
-
87
- #### `ctx.body`
88
- Parsed request body (POST, PUT, PATCH).
89
-
90
- ```typescript
91
- app.post('/users', async (ctx) => {
92
- const { name, email } = ctx.body;
93
- return { received: { name, email } };
94
- });
95
- ```
96
-
97
- **Automatic parsing for:**
98
- - `application/json`
99
- - `application/x-www-form-urlencoded`
100
- - `text/*`
101
-
102
- #### `ctx.headers`
103
- Request headers.
104
-
105
- ```typescript
106
- app.get('/auth', async (ctx) => {
107
- const token = ctx.headers.authorization;
108
- const userAgent = ctx.headers['user-agent'];
109
- return { token, userAgent };
110
- });
111
- ```
112
-
113
- #### `ctx.cookies`
114
- Cookie management.
115
-
116
- ```typescript
117
- app.get('/profile', async (ctx) => {
118
- // Get cookie
119
- const sessionId = ctx.cookies.get('session');
120
-
121
- // Set cookie
122
- ctx.cookies.set('visited', 'true', {
123
- maxAge: 86400, // 1 day in seconds
124
- httpOnly: true,
125
- secure: true,
126
- sameSite: 'strict'
127
- });
128
-
129
- // Delete cookie
130
- ctx.cookies.delete('old-cookie');
131
-
132
- return { sessionId };
133
- });
134
- ```
135
-
136
- ## Response Methods
137
-
138
- ### `ctx.json(data)`
139
- Return JSON response.
140
-
141
- ```typescript
142
- app.get('/user', async (ctx) => {
143
- return ctx.json({
144
- name: 'John',
145
- email: 'john@example.com'
146
- });
147
- });
148
-
149
- // Or simply return the object (auto-converted)
150
- app.get('/user', async (ctx) => {
151
- return { name: 'John', email: 'john@example.com' };
152
- });
153
- ```
154
-
155
- ### `ctx.html(content)`
156
- Return HTML response.
157
-
158
- ```typescript
159
- app.get('/page', async (ctx) => {
160
- return ctx.html(`
161
- <!DOCTYPE html>
162
- <html>
163
- <head><title>My Page</title></head>
164
- <body><h1>Welcome!</h1></body>
165
- </html>
166
- `);
167
- });
168
- ```
169
-
170
- ### `ctx.text(content)`
171
- Return plain text response.
172
-
173
- ```typescript
174
- app.get('/robots.txt', async (ctx) => {
175
- return ctx.text('User-agent: *\nDisallow: /admin/');
176
- });
177
- ```
178
-
179
- ### `ctx.redirect(url, status?)`
180
- Redirect to another URL.
181
-
182
- ```typescript
183
- app.get('/old-page', async (ctx) => {
184
- return ctx.redirect('/new-page', 301); // Permanent redirect
185
- });
186
-
187
- app.get('/login', async (ctx) => {
188
- return ctx.redirect('/auth/login'); // Default 302
189
- });
190
- ```
191
-
192
- ### `ctx.stream(readable)`
193
- Stream a response (for large files).
194
-
195
- ```typescript
196
- import { createReadStream } from 'fs';
197
-
198
- app.get('/download', async (ctx) => {
199
- const stream = createReadStream('./large-file.zip');
200
- return ctx.stream(stream);
201
- });
202
- ```
203
-
204
- ## Response Builder
205
-
206
- Use the response builder for custom status codes and headers:
207
-
208
- ```typescript
209
- app.get('/custom', async (ctx) => {
210
- return ctx.response
211
- .status(201)
212
- .header('X-Custom-Header', 'value')
213
- .json({ created: true });
214
- });
215
- ```
216
-
217
- ## Raw Node.js Objects
218
-
219
- Access raw Node.js objects when needed:
220
-
221
- ```typescript
222
- app.get('/raw', async (ctx) => {
223
- // Access raw request
224
- const req = ctx.raw.req;
225
- const contentLength = req.headers['content-length'];
226
-
227
- // Access raw response
228
- const res = ctx.raw.res;
229
- res.setHeader('X-Custom', 'value');
230
-
231
- return { contentLength };
232
- });
233
- ```
234
-
235
- ## Custom Context Properties
236
-
237
- Middleware can add custom properties to the context:
238
-
239
- ```typescript
240
- // Middleware adds user
241
- const auth = async (ctx: any, next: any) => {
242
- ctx.user = await authenticateUser(ctx.headers.authorization);
243
- return next(ctx);
244
- };
245
-
246
- app.get('/profile', {
247
- middlewares: [auth],
248
- handler: async (ctx: any) => {
249
- // ctx.user is now available
250
- return { user: ctx.user };
251
- }
252
- });
253
- ```
254
-
255
- For type-safe custom properties, see [Middleware Documentation](./04-middleware.md).
256
-
257
- ## Context Pooling
258
-
259
- Nexus automatically pools context objects for performance. You don't need to do anything - it's built-in!
260
-
261
- **Performance benefit:** ~60-80% reduction in object allocations.
262
-
263
- ```typescript
264
- // Get pool statistics
265
- const app = createApp();
266
- // ... after some requests
267
- const stats = app.getPoolStats();
268
- console.log(stats);
269
- // {
270
- // poolSize: 50,
271
- // maxSize: 100,
272
- // created: 150,
273
- // reused: 100,
274
- // hitRate: 0.67
275
- // }
276
- ```
277
-
278
- ## Best Practices
279
-
280
- ### ✅ DO: Return data directly
281
-
282
- ```typescript
283
- app.get('/users', async (ctx) => {
284
- const users = await getUsers();
285
- return { users };
286
- });
287
- ```
288
-
289
- ### ❌ DON'T: Mutate the context
290
-
291
- ```typescript
292
- // BAD - context is immutable
293
- app.get('/bad', async (ctx) => {
294
- ctx.path = '/new-path'; // Won't work!
295
- });
296
- ```
297
-
298
- ### ✅ DO: Use typed custom properties
299
-
300
- ```typescript
301
- interface AuthContext extends Context {
302
- user: User;
303
- }
304
-
305
- const handler = async (ctx: AuthContext) => {
306
- return { userId: ctx.user.id }; // Type-safe!
307
- };
308
- ```
309
-
310
- ### ✅ DO: Use cookies for session management
311
-
312
- ```typescript
313
- app.post('/login', async (ctx) => {
314
- const user = await authenticate(ctx.body);
315
-
316
- ctx.cookies.set('session', user.sessionId, {
317
- httpOnly: true,
318
- secure: true,
319
- sameSite: 'strict',
320
- maxAge: 86400
321
- });
322
-
323
- return { success: true };
324
- });
325
- ```
326
-
327
- ## Next Steps
328
-
329
- - 🛤️ [Routing Guide](./03-routing.md) - Learn about routing
330
- - 🔌 [Middleware](./04-middleware.md) - Extend context with middleware
331
- - ✅ [Validation](./05-validation.md) - Validate context data
332
-
333
- ---
334
-
335
- [← Getting Started](./01-getting-started.md) | [API Reference →](./09-api-reference.md)
@@ -1,397 +0,0 @@
1
- # Routing Guide
2
-
3
- ## Overview
4
-
5
- Nexus uses a **Radix Tree** for routing, providing O(log n) lookup performance. The routing system supports static routes, dynamic parameters, and wildcards.
6
-
7
- ## Basic Routes
8
-
9
- ### Static Routes
10
-
11
- ```typescript
12
- app.get('/about', async (ctx) => {
13
- return { page: 'about' };
14
- });
15
-
16
- app.get('/api/users', async (ctx) => {
17
- return { users: [] };
18
- });
19
- ```
20
-
21
- ### HTTP Methods
22
-
23
- ```typescript
24
- app.get('/resource', async (ctx) => {
25
- return { method: 'GET' };
26
- });
27
-
28
- app.post('/resource', async (ctx) => {
29
- return { method: 'POST', body: ctx.body };
30
- });
31
-
32
- app.put('/resource/:id', async (ctx) => {
33
- return { method: 'PUT', id: ctx.params.id };
34
- });
35
-
36
- app.patch('/resource/:id', async (ctx) => {
37
- return { method: 'PATCH', id: ctx.params.id };
38
- });
39
-
40
- app.delete('/resource/:id', async (ctx) => {
41
- return { method: 'DELETE', id: ctx.params.id };
42
- });
43
- ```
44
-
45
- ## Dynamic Routes
46
-
47
- ### Single Parameter
48
-
49
- ```typescript
50
- app.get('/users/:id', async (ctx) => {
51
- const userId = ctx.params.id;
52
- const user = await getUser(userId);
53
- return { user };
54
- });
55
- ```
56
-
57
- ### Multiple Parameters
58
-
59
- ```typescript
60
- app.get('/users/:userId/posts/:postId', async (ctx) => {
61
- const { userId, postId } = ctx.params;
62
- const post = await getPost(userId, postId);
63
- return { post };
64
- });
65
- ```
66
-
67
- ### Parameter Naming
68
-
69
- Use descriptive parameter names:
70
-
71
- ```typescript
72
- // Good
73
- app.get('/articles/:articleId/comments/:commentId', ...);
74
-
75
- // Avoid
76
- app.get('/articles/:id1/comments/:id2', ...);
77
- ```
78
-
79
- ## Wildcard Routes
80
-
81
- Capture the remaining path with `*`:
82
-
83
- ```typescript
84
- app.get('/files/*filepath', async (ctx) => {
85
- const filepath = ctx.params.filepath;
86
- // filepath = "docs/guide/intro.md" for /files/docs/guide/intro.md
87
- return { filepath };
88
- });
89
-
90
- app.get('/proxy/*', async (ctx) => {
91
- const path = ctx.params.wildcard; // default name
92
- return { proxiedPath: path };
93
- });
94
- ```
95
-
96
- ## Route Priority
97
-
98
- Routes are matched in this order:
99
-
100
- 1. **Static** - Exact matches
101
- 2. **Parameters** - Dynamic segments (`:param`)
102
- 3. **Wildcards** - Catch-all (`*`)
103
-
104
- ```typescript
105
- app.get('/users/active', ...); // 1. Matched first
106
- app.get('/users/:id', ...); // 2. Matched second
107
- app.get('/users/*', ...); // 3. Matched last
108
- ```
109
-
110
- Example:
111
- - `/users/active` → matches static route
112
- - `/users/123` → matches parameter route
113
- - `/users/admin/settings` → matches wildcard route
114
-
115
- ## Declarative Route Definition
116
-
117
- Use the `route()` method for advanced configuration:
118
-
119
- ```typescript
120
- import { z } from 'zod';
121
-
122
- app.route({
123
- method: 'POST',
124
- path: '/api/users',
125
-
126
- // Schema validation
127
- schema: {
128
- body: z.object({
129
- name: z.string().min(2),
130
- email: z.string().email()
131
- })
132
- },
133
-
134
- // Middleware
135
- middlewares: [authenticate, rateLimit],
136
-
137
- // Handler
138
- handler: async (ctx) => {
139
- const user = await createUser(ctx.body);
140
- return { user };
141
- },
142
-
143
- // Metadata (for documentation)
144
- meta: {
145
- description: 'Create a new user',
146
- tags: ['users'],
147
- responses: {
148
- 201: 'User created',
149
- 400: 'Validation error'
150
- }
151
- }
152
- });
153
- ```
154
-
155
- ## Route Groups
156
-
157
- Organize routes by creating separate router modules:
158
-
159
- ### `routes/users.ts`
160
-
161
- ```typescript
162
- import { Router } from '../nexus';
163
-
164
- export const userRoutes = (app: Application) => {
165
- app.get('/users', async (ctx) => {
166
- return { users: await getUsers() };
167
- });
168
-
169
- app.get('/users/:id', async (ctx) => {
170
- return { user: await getUser(ctx.params.id) };
171
- });
172
-
173
- app.post('/users', {
174
- schema: { /* ... */ },
175
- handler: async (ctx) => { /* ... */ }
176
- });
177
- };
178
- ```
179
-
180
- ### `index.ts`
181
-
182
- ```typescript
183
- import { createApp } from './nexus';
184
- import { userRoutes } from './routes/users';
185
- import { postRoutes } from './routes/posts';
186
-
187
- const app = createApp();
188
-
189
- userRoutes(app);
190
- postRoutes(app);
191
-
192
- app.listen(3000);
193
- ```
194
-
195
- ## Route Prefixes
196
-
197
- Create prefixed route groups:
198
-
199
- ```typescript
200
- const createAPIRoutes = (app: Application, prefix: string) => {
201
- app.get(`${prefix}/users`, ...);
202
- app.get(`${prefix}/posts`, ...);
203
- app.get(`${prefix}/comments`, ...);
204
- };
205
-
206
- createAPIRoutes(app, '/api/v1');
207
- createAPIRoutes(app, '/api/v2');
208
- ```
209
-
210
- ## Query Parameters
211
-
212
- Access query parameters via `ctx.query`:
213
-
214
- ```typescript
215
- // GET /search?q=nexus&page=2&limit=20
216
- app.get('/search', async (ctx) => {
217
- const query = ctx.query.q;
218
- const page = parseInt(ctx.query.page) || 1;
219
- const limit = parseInt(ctx.query.limit) || 10;
220
-
221
- const results = await search(query, page, limit);
222
- return { results, page, limit };
223
- });
224
- ```
225
-
226
- ### Type-Safe Query Validation
227
-
228
- ```typescript
229
- import { z } from 'zod';
230
-
231
- app.get('/search', {
232
- schema: {
233
- query: z.object({
234
- q: z.string().min(1),
235
- page: z.string().regex(/^\d+$/).transform(Number).default('1'),
236
- limit: z.string().regex(/^\d+$/).transform(Number).default('10')
237
- })
238
- },
239
- handler: async (ctx) => {
240
- // ctx.query is now typed and validated
241
- const { q, page, limit } = ctx.query;
242
- return await search(q, page, limit);
243
- }
244
- });
245
- ```
246
-
247
- ## 404 Not Found
248
-
249
- Nexus automatically returns 404 for unmatched routes:
250
-
251
- ```json
252
- {
253
- "error": "Not Found"
254
- }
255
- ```
256
-
257
- Custom 404 handler:
258
-
259
- ```typescript
260
- // Add a wildcard route at the end
261
- app.get('/*', async (ctx) => {
262
- return ctx.response.status(404).json({
263
- error: 'Page not found',
264
- path: ctx.path
265
- });
266
- });
267
- ```
268
-
269
- ## Route Introspection
270
-
271
- Get all registered routes:
272
-
273
- ```typescript
274
- const routes = app.getRoutes();
275
- console.log(routes);
276
- // [
277
- // { method: 'GET', path: '/users' },
278
- // { method: 'GET', path: '/users/:id' },
279
- // { method: 'POST', path: '/users' }
280
- // ]
281
- ```
282
-
283
- Useful for:
284
- - Generating API documentation
285
- - Debugging route conflicts
286
- - Creating route lists
287
-
288
- ## Best Practices
289
-
290
- ### ✅ DO: Use RESTful conventions
291
-
292
- ```typescript
293
- app.get('/users', ...); // List users
294
- app.get('/users/:id', ...); // Get user
295
- app.post('/users', ...); // Create user
296
- app.put('/users/:id', ...); // Update user (full)
297
- app.patch('/users/:id', ...); // Update user (partial)
298
- app.delete('/users/:id', ...); // Delete user
299
- ```
300
-
301
- ### ✅ DO: Version your API
302
-
303
- ```typescript
304
- app.get('/api/v1/users', ...);
305
- app.get('/api/v2/users', ...);
306
- ```
307
-
308
- ### ✅ DO: Use specific routes before wildcards
309
-
310
- ```typescript
311
- // Correct order
312
- app.get('/admin/dashboard', ...);
313
- app.get('/admin/*', ...);
314
-
315
- // Wrong order - dashboard will never be reached
316
- app.get('/admin/*', ...);
317
- app.get('/admin/dashboard', ...);
318
- ```
319
-
320
- ### ❌ DON'T: Create ambiguous routes
321
-
322
- ```typescript
323
- // Ambiguous - which route matches /users/123?
324
- app.get('/users/:id', ...);
325
- app.get('/users/:userId', ...); // Same as above!
326
- ```
327
-
328
- ### ✅ DO: Use consistent naming
329
-
330
- ```typescript
331
- // Good
332
- app.get('/users/:userId', ...);
333
- app.get('/users/:userId/posts/:postId', ...);
334
-
335
- // Inconsistent
336
- app.get('/users/:id', ...);
337
- app.get('/users/:userId/posts/:pid', ...);
338
- ```
339
-
340
- ## Performance
341
-
342
- ### Route Matching
343
-
344
- Nexus uses a **Radix Tree** for O(log n) route lookup:
345
-
346
- ```typescript
347
- // Fast - even with 1000+ routes
348
- app.get('/api/v1/users/:id', ...);
349
- // Lookup time: ~0.001ms
350
- ```
351
-
352
- ### Route Compilation
353
-
354
- Routes are compiled at startup for optimal performance:
355
-
356
- ```typescript
357
- const app = createApp({
358
- enableJIT: true // Enable JIT compilation (default)
359
- });
360
- ```
361
-
362
- ## Advanced Patterns
363
-
364
- ### Optional Parameters
365
-
366
- Use query parameters for optional data:
367
-
368
- ```typescript
369
- // GET /users?role=admin&active=true
370
- app.get('/users', async (ctx) => {
371
- const filters = {
372
- role: ctx.query.role,
373
- active: ctx.query.active === 'true'
374
- };
375
- return await getUsers(filters);
376
- });
377
- ```
378
-
379
- ### File Extensions
380
-
381
- ```typescript
382
- app.get('/download/:filename', async (ctx) => {
383
- const filename = ctx.params.filename;
384
- // filename includes extension: "document.pdf"
385
- return ctx.stream(createReadStream(filename));
386
- });
387
- ```
388
-
389
- ## Next Steps
390
-
391
- - ✅ [Schema Validation](./05-validation.md) - Validate route parameters
392
- - 🔌 [Middleware](./04-middleware.md) - Add route-specific middleware
393
- - 🔒 [Error Handling](./06-error-handling.md) - Handle route errors
394
-
395
- ---
396
-
397
- [← Context API](./02-context.md) | [Middleware →](./04-middleware.md)