@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.
Files changed (259) hide show
  1. package/dist/advanced/playground/generatePlaygroundHTML.d.ts.map +1 -1
  2. package/dist/advanced/playground/generatePlaygroundHTML.js +107 -0
  3. package/dist/advanced/playground/generatePlaygroundHTML.js.map +1 -1
  4. package/dist/advanced/playground/playground.d.ts +19 -0
  5. package/dist/advanced/playground/playground.d.ts.map +1 -1
  6. package/dist/advanced/playground/playground.js +70 -0
  7. package/dist/advanced/playground/playground.js.map +1 -1
  8. package/dist/advanced/playground/types.d.ts +20 -0
  9. package/dist/advanced/playground/types.d.ts.map +1 -1
  10. package/dist/core/application.d.ts +14 -0
  11. package/dist/core/application.d.ts.map +1 -1
  12. package/dist/core/application.js +173 -71
  13. package/dist/core/application.js.map +1 -1
  14. package/dist/core/context-pool.d.ts +2 -13
  15. package/dist/core/context-pool.d.ts.map +1 -1
  16. package/dist/core/context-pool.js +7 -45
  17. package/dist/core/context-pool.js.map +1 -1
  18. package/dist/core/context.d.ts +108 -5
  19. package/dist/core/context.d.ts.map +1 -1
  20. package/dist/core/context.js +449 -53
  21. package/dist/core/context.js.map +1 -1
  22. package/dist/core/index.d.ts +1 -0
  23. package/dist/core/index.d.ts.map +1 -1
  24. package/dist/core/index.js +9 -1
  25. package/dist/core/index.js.map +1 -1
  26. package/dist/core/middleware.d.ts +6 -0
  27. package/dist/core/middleware.d.ts.map +1 -1
  28. package/dist/core/middleware.js +83 -84
  29. package/dist/core/middleware.js.map +1 -1
  30. package/dist/core/performance/fast-json.d.ts +149 -0
  31. package/dist/core/performance/fast-json.d.ts.map +1 -0
  32. package/dist/core/performance/fast-json.js +473 -0
  33. package/dist/core/performance/fast-json.js.map +1 -0
  34. package/dist/core/router/file-router.d.ts +20 -7
  35. package/dist/core/router/file-router.d.ts.map +1 -1
  36. package/dist/core/router/file-router.js +41 -13
  37. package/dist/core/router/file-router.js.map +1 -1
  38. package/dist/core/router/index.d.ts +6 -0
  39. package/dist/core/router/index.d.ts.map +1 -1
  40. package/dist/core/router/index.js +33 -6
  41. package/dist/core/router/index.js.map +1 -1
  42. package/dist/core/router/radix-tree.d.ts +4 -1
  43. package/dist/core/router/radix-tree.d.ts.map +1 -1
  44. package/dist/core/router/radix-tree.js +7 -3
  45. package/dist/core/router/radix-tree.js.map +1 -1
  46. package/dist/core/serializer.d.ts +251 -0
  47. package/dist/core/serializer.d.ts.map +1 -0
  48. package/dist/core/serializer.js +290 -0
  49. package/dist/core/serializer.js.map +1 -0
  50. package/dist/core/types.d.ts +39 -1
  51. package/dist/core/types.d.ts.map +1 -1
  52. package/dist/core/types.js.map +1 -1
  53. package/dist/index.d.ts +1 -0
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +12 -2
  56. package/dist/index.js.map +1 -1
  57. package/package.json +3 -1
  58. package/documentation/01-getting-started.md +0 -240
  59. package/documentation/02-context.md +0 -335
  60. package/documentation/03-routing.md +0 -397
  61. package/documentation/04-middleware.md +0 -483
  62. package/documentation/05-validation.md +0 -514
  63. package/documentation/06-error-handling.md +0 -465
  64. package/documentation/07-performance.md +0 -364
  65. package/documentation/08-adapters.md +0 -470
  66. package/documentation/09-api-reference.md +0 -548
  67. package/documentation/10-examples.md +0 -582
  68. package/documentation/11-deployment.md +0 -477
  69. package/documentation/12-sentry.md +0 -620
  70. package/documentation/13-sentry-data-storage.md +0 -996
  71. package/documentation/14-sentry-data-reference.md +0 -457
  72. package/documentation/15-sentry-summary.md +0 -409
  73. package/documentation/16-alerts-system.md +0 -745
  74. package/documentation/17-alert-adapters.md +0 -696
  75. package/documentation/18-alerts-implementation-summary.md +0 -385
  76. package/documentation/19-class-based-routing.md +0 -840
  77. package/documentation/20-websocket-realtime.md +0 -813
  78. package/documentation/21-cache-system.md +0 -510
  79. package/documentation/22-job-queue.md +0 -772
  80. package/documentation/23-sentry-plugin.md +0 -551
  81. package/documentation/24-testing-utilities.md +0 -1287
  82. package/documentation/25-api-versioning.md +0 -533
  83. package/documentation/26-context-store.md +0 -607
  84. package/documentation/27-dependency-injection.md +0 -329
  85. package/documentation/28-lifecycle-hooks.md +0 -521
  86. package/documentation/29-package-structure.md +0 -196
  87. package/documentation/30-plugin-system.md +0 -414
  88. package/documentation/31-jwt-authentication.md +0 -597
  89. package/documentation/32-cli.md +0 -268
  90. package/documentation/ALERTS-COMPLETE-SUMMARY.md +0 -429
  91. package/documentation/ALERTS-INDEX.md +0 -330
  92. package/documentation/ALERTS-QUICK-REFERENCE.md +0 -286
  93. package/documentation/README.md +0 -178
  94. package/documentation/index.html +0 -34
  95. package/modern_framework_paper.md +0 -1870
  96. package/public/css/style.css +0 -87
  97. package/public/index.html +0 -34
  98. package/public/js/app.js +0 -27
  99. package/src/advanced/cache/InMemoryCacheStore.ts +0 -68
  100. package/src/advanced/cache/MultiTierCache.ts +0 -194
  101. package/src/advanced/cache/RedisCacheStore.ts +0 -341
  102. package/src/advanced/cache/index.ts +0 -5
  103. package/src/advanced/cache/types.ts +0 -40
  104. package/src/advanced/graphql/SimpleDataLoader.ts +0 -42
  105. package/src/advanced/graphql/index.ts +0 -22
  106. package/src/advanced/graphql/server.ts +0 -252
  107. package/src/advanced/graphql/types.ts +0 -42
  108. package/src/advanced/jobs/InMemoryQueueStore.ts +0 -68
  109. package/src/advanced/jobs/JobQueue.ts +0 -556
  110. package/src/advanced/jobs/RedisQueueStore.ts +0 -367
  111. package/src/advanced/jobs/index.ts +0 -5
  112. package/src/advanced/jobs/types.ts +0 -70
  113. package/src/advanced/observability/APMManager.ts +0 -163
  114. package/src/advanced/observability/AlertManager.ts +0 -109
  115. package/src/advanced/observability/MetricRegistry.ts +0 -151
  116. package/src/advanced/observability/ObservabilityCenter.ts +0 -304
  117. package/src/advanced/observability/StructuredLogger.ts +0 -154
  118. package/src/advanced/observability/TracingManager.ts +0 -117
  119. package/src/advanced/observability/adapters.ts +0 -304
  120. package/src/advanced/observability/createObservabilityMiddleware.ts +0 -63
  121. package/src/advanced/observability/index.ts +0 -11
  122. package/src/advanced/observability/types.ts +0 -174
  123. package/src/advanced/playground/extractPathParams.ts +0 -6
  124. package/src/advanced/playground/generateFieldExample.ts +0 -31
  125. package/src/advanced/playground/generatePlaygroundHTML.ts +0 -1849
  126. package/src/advanced/playground/generateSummary.ts +0 -19
  127. package/src/advanced/playground/getTagFromPath.ts +0 -9
  128. package/src/advanced/playground/index.ts +0 -8
  129. package/src/advanced/playground/playground.ts +0 -170
  130. package/src/advanced/playground/types.ts +0 -20
  131. package/src/advanced/playground/zodToExample.ts +0 -16
  132. package/src/advanced/playground/zodToParams.ts +0 -15
  133. package/src/advanced/postman/buildAuth.ts +0 -31
  134. package/src/advanced/postman/buildBody.ts +0 -15
  135. package/src/advanced/postman/buildQueryParams.ts +0 -27
  136. package/src/advanced/postman/buildRequestItem.ts +0 -36
  137. package/src/advanced/postman/buildResponses.ts +0 -11
  138. package/src/advanced/postman/buildUrl.ts +0 -33
  139. package/src/advanced/postman/capitalize.ts +0 -4
  140. package/src/advanced/postman/generateCollection.ts +0 -59
  141. package/src/advanced/postman/generateEnvironment.ts +0 -34
  142. package/src/advanced/postman/generateExampleFromZod.ts +0 -21
  143. package/src/advanced/postman/generateFieldExample.ts +0 -45
  144. package/src/advanced/postman/generateName.ts +0 -20
  145. package/src/advanced/postman/generateUUID.ts +0 -11
  146. package/src/advanced/postman/getTagFromPath.ts +0 -10
  147. package/src/advanced/postman/index.ts +0 -28
  148. package/src/advanced/postman/postman.ts +0 -156
  149. package/src/advanced/postman/slugify.ts +0 -7
  150. package/src/advanced/postman/types.ts +0 -140
  151. package/src/advanced/realtime/index.ts +0 -18
  152. package/src/advanced/realtime/websocket.ts +0 -231
  153. package/src/advanced/sentry/index.ts +0 -1236
  154. package/src/advanced/sentry/types.ts +0 -355
  155. package/src/advanced/static/generateDirectoryListing.ts +0 -47
  156. package/src/advanced/static/generateETag.ts +0 -7
  157. package/src/advanced/static/getMimeType.ts +0 -9
  158. package/src/advanced/static/index.ts +0 -32
  159. package/src/advanced/static/isSafePath.ts +0 -13
  160. package/src/advanced/static/publicDir.ts +0 -21
  161. package/src/advanced/static/serveStatic.ts +0 -225
  162. package/src/advanced/static/spa.ts +0 -24
  163. package/src/advanced/static/types.ts +0 -159
  164. package/src/advanced/swagger/SwaggerGenerator.ts +0 -66
  165. package/src/advanced/swagger/buildOperation.ts +0 -61
  166. package/src/advanced/swagger/buildParameters.ts +0 -61
  167. package/src/advanced/swagger/buildRequestBody.ts +0 -21
  168. package/src/advanced/swagger/buildResponses.ts +0 -54
  169. package/src/advanced/swagger/capitalize.ts +0 -5
  170. package/src/advanced/swagger/convertPath.ts +0 -9
  171. package/src/advanced/swagger/createSwagger.ts +0 -12
  172. package/src/advanced/swagger/generateOperationId.ts +0 -21
  173. package/src/advanced/swagger/generateSpec.ts +0 -105
  174. package/src/advanced/swagger/generateSummary.ts +0 -24
  175. package/src/advanced/swagger/generateSwaggerUI.ts +0 -70
  176. package/src/advanced/swagger/generateThemeCss.ts +0 -53
  177. package/src/advanced/swagger/index.ts +0 -25
  178. package/src/advanced/swagger/swagger.ts +0 -237
  179. package/src/advanced/swagger/types.ts +0 -206
  180. package/src/advanced/swagger/zodFieldToOpenAPI.ts +0 -94
  181. package/src/advanced/swagger/zodSchemaToOpenAPI.ts +0 -50
  182. package/src/advanced/swagger/zodToOpenAPI.ts +0 -22
  183. package/src/advanced/testing/factory.ts +0 -509
  184. package/src/advanced/testing/harness.ts +0 -612
  185. package/src/advanced/testing/index.ts +0 -430
  186. package/src/advanced/testing/load-test.ts +0 -618
  187. package/src/advanced/testing/mock-server.ts +0 -498
  188. package/src/advanced/testing/mock.ts +0 -670
  189. package/src/cli/bin.ts +0 -9
  190. package/src/cli/cli.ts +0 -158
  191. package/src/cli/commands/add.ts +0 -178
  192. package/src/cli/commands/build.ts +0 -73
  193. package/src/cli/commands/create.ts +0 -166
  194. package/src/cli/commands/dev.ts +0 -85
  195. package/src/cli/commands/generate.ts +0 -99
  196. package/src/cli/commands/help.ts +0 -95
  197. package/src/cli/commands/init.ts +0 -91
  198. package/src/cli/commands/version.ts +0 -38
  199. package/src/cli/index.ts +0 -6
  200. package/src/cli/templates/generators.ts +0 -359
  201. package/src/cli/templates/index.ts +0 -680
  202. package/src/cli/utils/exec.ts +0 -52
  203. package/src/cli/utils/file-system.ts +0 -78
  204. package/src/cli/utils/logger.ts +0 -111
  205. package/src/core/adapter.ts +0 -88
  206. package/src/core/application.ts +0 -1335
  207. package/src/core/context-pool.ts +0 -127
  208. package/src/core/context.ts +0 -412
  209. package/src/core/index.ts +0 -80
  210. package/src/core/middleware.ts +0 -262
  211. package/src/core/performance/buffer-pool.ts +0 -108
  212. package/src/core/performance/middleware-optimizer.ts +0 -162
  213. package/src/core/plugin/PluginManager.ts +0 -435
  214. package/src/core/plugin/builder.ts +0 -358
  215. package/src/core/plugin/index.ts +0 -50
  216. package/src/core/plugin/types.ts +0 -214
  217. package/src/core/router/file-router.ts +0 -594
  218. package/src/core/router/index.ts +0 -227
  219. package/src/core/router/radix-tree.ts +0 -226
  220. package/src/core/store/index.ts +0 -30
  221. package/src/core/store/registry.ts +0 -178
  222. package/src/core/store/request-store.ts +0 -240
  223. package/src/core/store/types.ts +0 -233
  224. package/src/core/types.ts +0 -574
  225. package/src/database/adapter.ts +0 -35
  226. package/src/database/adapters/index.ts +0 -1
  227. package/src/database/adapters/mysql.ts +0 -669
  228. package/src/database/database.ts +0 -70
  229. package/src/database/dialect.ts +0 -388
  230. package/src/database/index.ts +0 -12
  231. package/src/database/migrations.ts +0 -86
  232. package/src/database/optimizer.ts +0 -125
  233. package/src/database/query-builder.ts +0 -404
  234. package/src/database/realtime.ts +0 -53
  235. package/src/database/schema.ts +0 -71
  236. package/src/database/transactions.ts +0 -56
  237. package/src/database/types.ts +0 -87
  238. package/src/deployment/cluster.ts +0 -471
  239. package/src/deployment/config.ts +0 -454
  240. package/src/deployment/docker.ts +0 -599
  241. package/src/deployment/graceful-shutdown.ts +0 -373
  242. package/src/deployment/index.ts +0 -56
  243. package/src/index.ts +0 -264
  244. package/src/security/adapter.ts +0 -318
  245. package/src/security/auth/JWTPlugin.ts +0 -234
  246. package/src/security/auth/JWTProvider.ts +0 -316
  247. package/src/security/auth/adapter.ts +0 -12
  248. package/src/security/auth/jwt.ts +0 -234
  249. package/src/security/auth/middleware.ts +0 -188
  250. package/src/security/csrf.ts +0 -220
  251. package/src/security/headers.ts +0 -108
  252. package/src/security/index.ts +0 -60
  253. package/src/security/rate-limit/adapter.ts +0 -7
  254. package/src/security/rate-limit/memory.ts +0 -108
  255. package/src/security/rate-limit/middleware.ts +0 -181
  256. package/src/security/sanitization.ts +0 -75
  257. package/src/security/types.ts +0 -240
  258. package/src/security/utils.ts +0 -52
  259. package/tsconfig.json +0 -39
@@ -1,188 +0,0 @@
1
- /**
2
- * Authentication Middleware
3
- *
4
- * Provides authentication and authorization middleware
5
- */
6
-
7
- import type { Context, Next, Middleware } from '../../core/types';
8
- import type { User, AuthContext, AuthStrategies } from '../types';
9
- import type { AuthAdapter, PermissionAdapter } from '../adapter';
10
- import { DefaultPermissionAdapter } from '../adapter';
11
- import { JWTAuthAdapter } from './jwt';
12
-
13
- /**
14
- * Authentication middleware factory
15
- *
16
- * @example
17
- * ```ts
18
- * // JWT authentication
19
- * app.use(authenticate({
20
- * jwt: {
21
- * secret: process.env.JWT_SECRET,
22
- * expiresIn: '15m'
23
- * }
24
- * }));
25
- *
26
- * // Optional authentication
27
- * app.use(authenticate({ jwt: config }, { required: false }));
28
- * ```
29
- */
30
- export function authenticate(
31
- strategies: AuthStrategies,
32
- options: {
33
- required?: boolean;
34
- strategies?: ('jwt' | 'oauth' | 'session')[];
35
- } = {}
36
- ): Middleware<Context, AuthContext> {
37
- const adapters = new Map<string, AuthAdapter>();
38
- const required = options.required !== false;
39
- const strategyOrder = options.strategies || ['jwt', 'oauth', 'session'];
40
-
41
- // Initialize adapters
42
- if (strategies.jwt) {
43
- adapters.set('jwt', new JWTAuthAdapter());
44
- }
45
- // OAuth and Session will be added in future
46
- // if (strategies.oauth) adapters.set('oauth', new OAuthAdapter());
47
- // if (strategies.session) adapters.set('session', new SessionAdapter());
48
-
49
- return (async (ctx: Context, next: Next, _deps: any) => {
50
- let user: User | null = null;
51
-
52
- // Try each strategy in order
53
- for (const strategyName of strategyOrder) {
54
- const adapter = adapters.get(strategyName);
55
- const config = (strategies as any)[strategyName];
56
-
57
- if (adapter && config) {
58
- try {
59
- user = await adapter.verify(ctx, config);
60
- if (user) {
61
- break;
62
- }
63
- } catch (error) {
64
- // Try next strategy
65
- continue;
66
- }
67
- }
68
- }
69
-
70
- // If no user found and auth is required
71
- if (!user && required) {
72
- return {
73
- statusCode: 401,
74
- headers: { 'Content-Type': 'application/json' },
75
- body: JSON.stringify({ error: 'Unauthorized' })
76
- };
77
- }
78
-
79
- // Attach user to context
80
- (ctx as unknown as AuthContext).user = user!;
81
-
82
- return next(ctx as unknown as AuthContext);
83
- }) as Middleware<Context, AuthContext>;
84
- }
85
-
86
- /**
87
- * Optional authentication - doesn't throw if no auth provided
88
- */
89
- export function optionalAuth(strategies: AuthStrategies): Middleware<Context, Partial<AuthContext>> {
90
- return authenticate(strategies, { required: false }) as any;
91
- }
92
-
93
- /**
94
- * Require authentication - throws 401 if not authenticated
95
- */
96
- export function requireAuth(strategies: AuthStrategies): Middleware<Context, AuthContext> {
97
- return authenticate(strategies, { required: true });
98
- }
99
-
100
- /**
101
- * Permission-based authorization middleware
102
- *
103
- * @example
104
- * ```ts
105
- * app.post('/admin/users',
106
- * authenticate({ jwt: config }),
107
- * requirePermissions(['admin', 'write:users']),
108
- * handler
109
- * );
110
- * ```
111
- */
112
- export function requirePermissions(
113
- permissions: string[],
114
- adapter?: PermissionAdapter
115
- ): Middleware<AuthContext, AuthContext> {
116
- const permissionChecker = adapter || new DefaultPermissionAdapter();
117
-
118
- return (async (ctx: AuthContext, next: Next, _deps: any) => {
119
- if (!ctx.user) {
120
- return {
121
- statusCode: 401,
122
- headers: { 'Content-Type': 'application/json' },
123
- body: JSON.stringify({ error: 'Unauthorized' })
124
- };
125
- }
126
-
127
- const result = permissionChecker.checkPermissions(ctx.user, permissions);
128
-
129
- if (!result.allowed) {
130
- return {
131
- statusCode: 403,
132
- headers: { 'Content-Type': 'application/json' },
133
- body: JSON.stringify({
134
- error: 'Forbidden',
135
- message: 'Insufficient permissions',
136
- missing: result.missing
137
- })
138
- };
139
- }
140
-
141
- return next(ctx);
142
- }) as Middleware<AuthContext, AuthContext>;
143
- }
144
-
145
- /**
146
- * Role-based authorization middleware
147
- *
148
- * @example
149
- * ```ts
150
- * app.get('/admin/*',
151
- * authenticate({ jwt: config }),
152
- * requireRoles(['admin']),
153
- * handler
154
- * );
155
- * ```
156
- */
157
- export function requireRoles(
158
- roles: string[],
159
- adapter?: PermissionAdapter
160
- ): Middleware<AuthContext, AuthContext> {
161
- const permissionChecker = adapter || new DefaultPermissionAdapter();
162
-
163
- return (async (ctx: AuthContext, next: Next, _deps: any) => {
164
- if (!ctx.user) {
165
- return {
166
- statusCode: 401,
167
- headers: { 'Content-Type': 'application/json' },
168
- body: JSON.stringify({ error: 'Unauthorized' })
169
- };
170
- }
171
-
172
- const hasRole = permissionChecker.checkRoles(ctx.user, roles);
173
-
174
- if (!hasRole) {
175
- return {
176
- statusCode: 403,
177
- headers: { 'Content-Type': 'application/json' },
178
- body: JSON.stringify({
179
- error: 'Forbidden',
180
- message: 'Insufficient roles',
181
- required: roles
182
- })
183
- };
184
- }
185
-
186
- return next(ctx);
187
- }) as Middleware<AuthContext, AuthContext>;
188
- }
@@ -1,220 +0,0 @@
1
- /**
2
- * CSRF Protection Middleware
3
- *
4
- * Implements Cross-Site Request Forgery protection
5
- */
6
-
7
- import type { Context, Next, Middleware } from '../core/types';
8
- import type { CSRFConfig } from './types';
9
- import type { CSRFAdapter } from './adapter';
10
-
11
- /**
12
- * Default CSRF token adapter
13
- * Uses double-submit cookie pattern
14
- */
15
- class DefaultCSRFAdapter implements CSRFAdapter {
16
- private readonly tokenLength: number;
17
-
18
- constructor(tokenLength: number = 32) {
19
- this.tokenLength = tokenLength;
20
- }
21
-
22
- generateToken(_ctx: Context): string {
23
- // Generate random token
24
- const bytes = crypto.getRandomValues(new Uint8Array(this.tokenLength));
25
- return Array.from(bytes)
26
- .map(b => b.toString(16).padStart(2, '0'))
27
- .join('');
28
- }
29
-
30
- validateToken(ctx: Context, token: string): boolean {
31
- // In double-submit cookie pattern, token in cookie should match token in header/body
32
- const cookieToken = this.extractTokenFromCookie(ctx);
33
-
34
- if (!cookieToken) {
35
- return false;
36
- }
37
-
38
- // Constant-time comparison to prevent timing attacks
39
- return this.constantTimeCompare(token, cookieToken);
40
- }
41
-
42
- extractToken(ctx: Context): string | null {
43
- // Try header first
44
- const csrfHeader = ctx.headers['x-csrf-token'] || ctx.headers['X-CSRF-Token'];
45
- if (csrfHeader) {
46
- return Array.isArray(csrfHeader) ? csrfHeader[0] : csrfHeader;
47
- }
48
-
49
- const csrfTokenHeader = ctx.headers['csrf-token'] || ctx.headers['CSRF-Token'];
50
- if (csrfTokenHeader) {
51
- return Array.isArray(csrfTokenHeader) ? csrfTokenHeader[0] : csrfTokenHeader;
52
- }
53
-
54
- // Try body
55
- if (ctx.body && typeof ctx.body === 'object') {
56
- return (ctx.body as any)._csrf || (ctx.body as any).csrf_token || null;
57
- }
58
-
59
- return null;
60
- }
61
-
62
- private extractTokenFromCookie(ctx: Context): string | null {
63
- const cookieHeaderRaw = ctx.headers['cookie'] || ctx.headers['Cookie'];
64
- if (!cookieHeaderRaw) {
65
- return null;
66
- }
67
-
68
- const cookieHeader = Array.isArray(cookieHeaderRaw) ? cookieHeaderRaw[0] : cookieHeaderRaw;
69
-
70
- const match = cookieHeader.match(/_csrf=([^;]+)/);
71
- return match ? match[1] : null;
72
- }
73
-
74
- private constantTimeCompare(a: string, b: string): boolean {
75
- if (a.length !== b.length) {
76
- return false;
77
- }
78
-
79
- let result = 0;
80
- for (let i = 0; i < a.length; i++) {
81
- result |= a.charCodeAt(i) ^ b.charCodeAt(i);
82
- }
83
-
84
- return result === 0;
85
- }
86
- }
87
-
88
- /**
89
- * CSRF protection middleware
90
- *
91
- * @example
92
- * ```ts
93
- * app.use(csrf({
94
- * cookie: { sameSite: 'strict' },
95
- * excludeRoutes: ['/api/webhook/*']
96
- * }));
97
- * ```
98
- */
99
- export function csrf(
100
- config: CSRFConfig = {},
101
- adapter?: CSRFAdapter
102
- ): Middleware {
103
- const csrfAdapter = adapter || new DefaultCSRFAdapter(config.tokenLength);
104
- const auto = config.auto !== false;
105
- const excludeMethods = config.excludeMethods || ['GET', 'HEAD', 'OPTIONS'];
106
- const excludeRoutes = config.excludeRoutes || [];
107
-
108
- return async (ctx: Context, next: Next, _deps: any) => {
109
- // Skip safe methods
110
- if (excludeMethods.includes(ctx.method)) {
111
- return next(ctx);
112
- }
113
-
114
- // Skip excluded routes
115
- for (const pattern of excludeRoutes) {
116
- const regex = new RegExp('^' + pattern.replace('*', '.*') + '$');
117
- if (regex.test(ctx.path)) {
118
- return next(ctx);
119
- }
120
- }
121
-
122
- // Validate CSRF token
123
- if (auto) {
124
- const token = csrfAdapter.extractToken(ctx);
125
-
126
- if (!token) {
127
- return {
128
- statusCode: 403,
129
- headers: { 'Content-Type': 'application/json' },
130
- body: JSON.stringify({
131
- error: 'CSRF token missing'
132
- })
133
- };
134
- }
135
-
136
- const valid = csrfAdapter.validateToken(ctx, token);
137
-
138
- if (!valid) {
139
- return {
140
- statusCode: 403,
141
- headers: { 'Content-Type': 'application/json' },
142
- body: JSON.stringify({
143
- error: 'CSRF token invalid'
144
- })
145
- };
146
- }
147
- }
148
-
149
- return next(ctx);
150
- };
151
- }
152
-
153
- /**
154
- * Generate CSRF token middleware
155
- * Attaches token to context and sets cookie
156
- *
157
- * @example
158
- * ```ts
159
- * app.use(generateCSRFToken());
160
- *
161
- * // In handler
162
- * app.get('/form', async (ctx) => {
163
- * const token = ctx.csrfToken;
164
- * return ctx.html(`<input type="hidden" name="_csrf" value="${token}">`);
165
- * });
166
- * ```
167
- */
168
- export function generateCSRFToken(
169
- config: CSRFConfig = {},
170
- adapter?: CSRFAdapter
171
- ): Middleware {
172
- const csrfAdapter = adapter || new DefaultCSRFAdapter(config.tokenLength);
173
- const cookieName = config.cookie?.name || '_csrf';
174
- const cookieOptions = {
175
- sameSite: config.cookie?.sameSite || 'strict',
176
- secure: config.cookie?.secure !== false,
177
- httpOnly: config.cookie?.httpOnly !== false
178
- };
179
-
180
- return async (ctx: Context, next: Next, _deps: any) => {
181
- // Generate token
182
- const token = csrfAdapter.generateToken(ctx);
183
-
184
- // Attach to context
185
- (ctx as any).csrfToken = token;
186
-
187
- // Execute handler
188
- const response = await next(ctx);
189
-
190
- // Set cookie
191
- const cookieValue = `${cookieName}=${token}; SameSite=${cookieOptions.sameSite}${cookieOptions.secure ? '; Secure' : ''}${cookieOptions.httpOnly ? '; HttpOnly' : ''}; Path=/`;
192
-
193
- // Append cookie to response headers
194
- if (!response.headers['Set-Cookie']) {
195
- response.headers['Set-Cookie'] = cookieValue;
196
- } else if (Array.isArray(response.headers['Set-Cookie'])) {
197
- response.headers['Set-Cookie'].push(cookieValue);
198
- } else {
199
- response.headers['Set-Cookie'] = [response.headers['Set-Cookie'], cookieValue];
200
- }
201
-
202
- return response;
203
- };
204
- }
205
-
206
- /**
207
- * Combined CSRF middleware - generates and validates tokens
208
- */
209
- export function csrfProtection(config: CSRFConfig = {}): Middleware {
210
- const generateMiddleware = generateCSRFToken(config);
211
- const validateMiddleware = csrf(config);
212
-
213
- return async (ctx: Context, next: Next, deps: any) => {
214
- // First generate token
215
- return generateMiddleware(ctx, async (ctxWithToken: Context) => {
216
- // Then validate on unsafe methods
217
- return validateMiddleware(ctxWithToken, next, deps);
218
- }, deps);
219
- };
220
- }
@@ -1,108 +0,0 @@
1
- /**
2
- * Security Headers Middleware
3
- *
4
- * Automatically applies security headers to responses
5
- */
6
-
7
- import type { Context, Next, Middleware } from '../core/types';
8
- import type { SecurityHeadersConfig } from './types';
9
- import type { SecurityHeadersAdapter } from './adapter';
10
- import { DefaultSecurityHeadersAdapter } from './adapter';
11
-
12
- /**
13
- * Create security headers middleware
14
- *
15
- * @example
16
- * ```ts
17
- * app.use(securityHeaders({
18
- * mode: 'strict',
19
- * csp: {
20
- * directives: {
21
- * 'default-src': ["'self'"],
22
- * 'script-src': ["'self'", "'nonce'"]
23
- * }
24
- * }
25
- * }));
26
- * ```
27
- */
28
- export function securityHeaders(
29
- config: SecurityHeadersConfig = {},
30
- adapter?: SecurityHeadersAdapter
31
- ): Middleware {
32
- const adapterInstance = adapter || new DefaultSecurityHeadersAdapter();
33
- const nonces = new WeakMap<Context, string>();
34
-
35
- return async (ctx: Context, next: Next, _deps: any) => {
36
- // Generate nonce if CSP uses it
37
- if (config.autoNonce && config.csp) {
38
- const nonce = adapterInstance.generateNonce?.() || crypto.randomUUID();
39
- nonces.set(ctx, nonce);
40
-
41
- // Replace 'nonce' placeholder in CSP directives
42
- if (config.csp.directives) {
43
- for (const [key, values] of Object.entries(config.csp.directives)) {
44
- config.csp.directives[key] = values.map(v =>
45
- v === "'nonce'" ? `'nonce-${nonce}'` : v
46
- );
47
- }
48
- }
49
-
50
- // Attach nonce to context for use in templates
51
- (ctx as any).nonce = nonce;
52
- }
53
-
54
- // Generate headers
55
- const headers = adapterInstance.generateHeaders(ctx, config);
56
-
57
- // Execute handler
58
- const response = await next(ctx);
59
-
60
- // Apply headers to response
61
- for (const [name, value] of Object.entries(headers)) {
62
- response.headers[name] = value;
63
- }
64
-
65
- return response;
66
- };
67
- }
68
-
69
- /**
70
- * Strict security headers preset
71
- */
72
- export function strictSecurityHeaders(customConfig: Partial<SecurityHeadersConfig> = {}): Middleware {
73
- return securityHeaders({
74
- mode: 'strict',
75
- csp: {
76
- directives: {
77
- 'default-src': ["'self'"],
78
- 'script-src': ["'self'"],
79
- 'style-src': ["'self'"],
80
- 'img-src': ["'self'", 'data:', 'https:'],
81
- 'font-src': ["'self'"],
82
- 'connect-src': ["'self'"],
83
- 'frame-ancestors': ["'none'"],
84
- 'base-uri': ["'self'"],
85
- 'form-action': ["'self'"]
86
- }
87
- },
88
- ...customConfig
89
- });
90
- }
91
-
92
- /**
93
- * Moderate security headers preset
94
- */
95
- export function moderateSecurityHeaders(customConfig: Partial<SecurityHeadersConfig> = {}): Middleware {
96
- return securityHeaders({
97
- mode: 'moderate',
98
- csp: {
99
- directives: {
100
- 'default-src': ["'self'"],
101
- 'script-src': ["'self'", "'unsafe-inline'"],
102
- 'style-src': ["'self'", "'unsafe-inline'"],
103
- 'img-src': ["'self'", 'data:', 'https:']
104
- }
105
- },
106
- ...customConfig
107
- });
108
- }
@@ -1,60 +0,0 @@
1
- /**
2
- * Security Module Entry Point
3
- *
4
- * Exports all security features
5
- */
6
-
7
- // Types
8
- export * from './types';
9
-
10
- // Adapters
11
- export * from './adapter';
12
-
13
- // Security Headers
14
- export {
15
- securityHeaders,
16
- strictSecurityHeaders,
17
- moderateSecurityHeaders
18
- } from './headers';
19
-
20
- // Input Sanitization
21
- export {
22
- sanitizeInput,
23
- strictSanitization,
24
- lenientSanitization
25
- } from './sanitization';
26
-
27
- // Authentication
28
- export {
29
- authenticate,
30
- optionalAuth,
31
- requireAuth,
32
- requirePermissions,
33
- requireRoles
34
- } from './auth/middleware';
35
-
36
- export { JWTAuthAdapter } from './auth/jwt';
37
-
38
- // JWT Provider (for DI)
39
- export { JWTProvider, createJWTProvider } from './auth/JWTProvider';
40
- export type { JWTProviderConfig, TokenPayload, VerifyResult } from './auth/JWTProvider';
41
-
42
- // JWT Plugin
43
- export { jwtPlugin } from './auth/JWTPlugin';
44
- export type { JWTPluginConfig, JWTPluginExports } from './auth/JWTPlugin';
45
-
46
- // Rate Limiting
47
- export {
48
- rateLimit,
49
- strictRateLimit,
50
- lenientRateLimit
51
- } from './rate-limit/middleware';
52
-
53
- export { MemoryRateLimiter } from './rate-limit/memory';
54
-
55
- // CSRF Protection
56
- export {
57
- csrf,
58
- generateCSRFToken,
59
- csrfProtection
60
- } from './csrf';
@@ -1,7 +0,0 @@
1
- /**
2
- * Rate Limit Adapter Interface
3
- *
4
- * Extensible rate limiting storage backends
5
- */
6
-
7
- export type { RateLimitAdapter } from '../adapter';
@@ -1,108 +0,0 @@
1
- /**
2
- * In-Memory Rate Limiter
3
- *
4
- * Simple in-memory rate limiting implementation
5
- */
6
-
7
- import type { RateLimitAdapter } from '../adapter';
8
- import type { RateLimitInfo } from '../types';
9
-
10
- interface RateLimitEntry {
11
- count: number;
12
- resetTime: number;
13
- firstRequest: number;
14
- }
15
-
16
- /**
17
- * In-memory rate limit storage
18
- * Uses sliding window algorithm
19
- */
20
- export class MemoryRateLimiter implements RateLimitAdapter {
21
- private store = new Map<string, RateLimitEntry>();
22
- private cleanupInterval: NodeJS.Timeout | null = null;
23
-
24
- constructor(cleanupIntervalMs: number = 60000) {
25
- // Periodic cleanup of expired entries
26
- this.cleanupInterval = setInterval(() => {
27
- this.cleanup();
28
- }, cleanupIntervalMs);
29
- }
30
-
31
- async increment(key: string, windowMs: number): Promise<{
32
- count: number;
33
- resetTime: number;
34
- }> {
35
- const now = Date.now();
36
- const entry = this.store.get(key);
37
-
38
- // No existing entry or expired
39
- if (!entry || now >= entry.resetTime) {
40
- const newEntry: RateLimitEntry = {
41
- count: 1,
42
- resetTime: now + windowMs,
43
- firstRequest: now
44
- };
45
- this.store.set(key, newEntry);
46
-
47
- return {
48
- count: 1,
49
- resetTime: newEntry.resetTime
50
- };
51
- }
52
-
53
- // Increment existing entry
54
- entry.count++;
55
-
56
- return {
57
- count: entry.count,
58
- resetTime: entry.resetTime
59
- };
60
- }
61
-
62
- async get(key: string): Promise<RateLimitInfo | null> {
63
- const entry = this.store.get(key);
64
-
65
- if (!entry) {
66
- return null;
67
- }
68
-
69
- const now = Date.now();
70
-
71
- // Expired
72
- if (now >= entry.resetTime) {
73
- this.store.delete(key);
74
- return null;
75
- }
76
-
77
- return {
78
- limit: -1, // Will be set by middleware
79
- remaining: -1, // Will be calculated by middleware
80
- reset: Math.floor(entry.resetTime / 1000),
81
- retryAfter: Math.ceil((entry.resetTime - now) / 1000)
82
- };
83
- }
84
-
85
- async reset(key: string): Promise<void> {
86
- this.store.delete(key);
87
- }
88
-
89
- async cleanup(): Promise<void> {
90
- const now = Date.now();
91
-
92
- for (const [key, entry] of this.store.entries()) {
93
- if (now >= entry.resetTime) {
94
- this.store.delete(key);
95
- }
96
- }
97
- }
98
-
99
- /**
100
- * Stop cleanup interval
101
- */
102
- destroy(): void {
103
- if (this.cleanupInterval) {
104
- clearInterval(this.cleanupInterval);
105
- this.cleanupInterval = null;
106
- }
107
- }
108
- }