@flightdev/core 0.6.7

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 (187) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +541 -0
  3. package/dist/actions/index.d.ts +743 -0
  4. package/dist/actions/index.js +3 -0
  5. package/dist/actions/index.js.map +1 -0
  6. package/dist/adapters/index.d.ts +502 -0
  7. package/dist/adapters/index.js +3 -0
  8. package/dist/adapters/index.js.map +1 -0
  9. package/dist/cache/index.d.ts +191 -0
  10. package/dist/cache/index.js +3 -0
  11. package/dist/cache/index.js.map +1 -0
  12. package/dist/chunk-62HISNA3.js +354 -0
  13. package/dist/chunk-62HISNA3.js.map +1 -0
  14. package/dist/chunk-63LWTEDQ.js +341 -0
  15. package/dist/chunk-63LWTEDQ.js.map +1 -0
  16. package/dist/chunk-63SCEXD7.js +3 -0
  17. package/dist/chunk-63SCEXD7.js.map +1 -0
  18. package/dist/chunk-72MYOTUB.js +667 -0
  19. package/dist/chunk-72MYOTUB.js.map +1 -0
  20. package/dist/chunk-7CNW24MQ.js +257 -0
  21. package/dist/chunk-7CNW24MQ.js.map +1 -0
  22. package/dist/chunk-7WIEAUJT.js +300 -0
  23. package/dist/chunk-7WIEAUJT.js.map +1 -0
  24. package/dist/chunk-7ZZF4ULK.js +259 -0
  25. package/dist/chunk-7ZZF4ULK.js.map +1 -0
  26. package/dist/chunk-AE3JTS73.js +222 -0
  27. package/dist/chunk-AE3JTS73.js.map +1 -0
  28. package/dist/chunk-AP5NLUSB.js +258 -0
  29. package/dist/chunk-AP5NLUSB.js.map +1 -0
  30. package/dist/chunk-C37YQQI7.js +221 -0
  31. package/dist/chunk-C37YQQI7.js.map +1 -0
  32. package/dist/chunk-DCLVXFVH.js +225 -0
  33. package/dist/chunk-DCLVXFVH.js.map +1 -0
  34. package/dist/chunk-DZMWWDFD.js +223 -0
  35. package/dist/chunk-DZMWWDFD.js.map +1 -0
  36. package/dist/chunk-GCQZ4FHI.js +245 -0
  37. package/dist/chunk-GCQZ4FHI.js.map +1 -0
  38. package/dist/chunk-IPP44XY6.js +47 -0
  39. package/dist/chunk-IPP44XY6.js.map +1 -0
  40. package/dist/chunk-IW7FTQQX.js +267 -0
  41. package/dist/chunk-IW7FTQQX.js.map +1 -0
  42. package/dist/chunk-JX4YSCBH.js +428 -0
  43. package/dist/chunk-JX4YSCBH.js.map +1 -0
  44. package/dist/chunk-KX6UYWWR.js +229 -0
  45. package/dist/chunk-KX6UYWWR.js.map +1 -0
  46. package/dist/chunk-LWVETFJV.js +46 -0
  47. package/dist/chunk-LWVETFJV.js.map +1 -0
  48. package/dist/chunk-MCL2MCA2.js +285 -0
  49. package/dist/chunk-MCL2MCA2.js.map +1 -0
  50. package/dist/chunk-MZXCF35B.js +205 -0
  51. package/dist/chunk-MZXCF35B.js.map +1 -0
  52. package/dist/chunk-NCGPUFWV.js +96 -0
  53. package/dist/chunk-NCGPUFWV.js.map +1 -0
  54. package/dist/chunk-OEJMIE2Q.js +351 -0
  55. package/dist/chunk-OEJMIE2Q.js.map +1 -0
  56. package/dist/chunk-OYF2OAKS.js +394 -0
  57. package/dist/chunk-OYF2OAKS.js.map +1 -0
  58. package/dist/chunk-P6S43FYZ.js +316 -0
  59. package/dist/chunk-P6S43FYZ.js.map +1 -0
  60. package/dist/chunk-PL37KFRJ.js +3 -0
  61. package/dist/chunk-PL37KFRJ.js.map +1 -0
  62. package/dist/chunk-Q7BS5QC5.js +197 -0
  63. package/dist/chunk-Q7BS5QC5.js.map +1 -0
  64. package/dist/chunk-SDYPG3JD.js +288 -0
  65. package/dist/chunk-SDYPG3JD.js.map +1 -0
  66. package/dist/chunk-SUG56SZO.js +256 -0
  67. package/dist/chunk-SUG56SZO.js.map +1 -0
  68. package/dist/chunk-UVH5XJRP.js +164 -0
  69. package/dist/chunk-UVH5XJRP.js.map +1 -0
  70. package/dist/chunk-WZIJKCL3.js +282 -0
  71. package/dist/chunk-WZIJKCL3.js.map +1 -0
  72. package/dist/chunk-Y22AMGTM.js +3 -0
  73. package/dist/chunk-Y22AMGTM.js.map +1 -0
  74. package/dist/chunk-Z7G23XWU.js +200 -0
  75. package/dist/chunk-Z7G23XWU.js.map +1 -0
  76. package/dist/chunk-ZJU5M4IB.js +125 -0
  77. package/dist/chunk-ZJU5M4IB.js.map +1 -0
  78. package/dist/chunk-ZVC3ZWLM.js +52 -0
  79. package/dist/chunk-ZVC3ZWLM.js.map +1 -0
  80. package/dist/chunk-ZZZML7Y3.js +310 -0
  81. package/dist/chunk-ZZZML7Y3.js.map +1 -0
  82. package/dist/client.d.ts +25 -0
  83. package/dist/client.js +16 -0
  84. package/dist/client.js.map +1 -0
  85. package/dist/config/index.d.ts +170 -0
  86. package/dist/config/index.js +3 -0
  87. package/dist/config/index.js.map +1 -0
  88. package/dist/errors/index.d.ts +267 -0
  89. package/dist/errors/index.js +4 -0
  90. package/dist/errors/index.js.map +1 -0
  91. package/dist/file-router/index.d.ts +184 -0
  92. package/dist/file-router/index.js +3 -0
  93. package/dist/file-router/index.js.map +1 -0
  94. package/dist/file-router/streaming-hints.d.ts +129 -0
  95. package/dist/file-router/streaming-hints.js +3 -0
  96. package/dist/file-router/streaming-hints.js.map +1 -0
  97. package/dist/handlers/index.d.ts +59 -0
  98. package/dist/handlers/index.js +3 -0
  99. package/dist/handlers/index.js.map +1 -0
  100. package/dist/index.d.ts +588 -0
  101. package/dist/index.js +886 -0
  102. package/dist/index.js.map +1 -0
  103. package/dist/islands/index.d.ts +234 -0
  104. package/dist/islands/index.js +3 -0
  105. package/dist/islands/index.js.map +1 -0
  106. package/dist/middleware/index.d.ts +305 -0
  107. package/dist/middleware/index.js +3 -0
  108. package/dist/middleware/index.js.map +1 -0
  109. package/dist/react/index.d.ts +73 -0
  110. package/dist/react/index.js +52 -0
  111. package/dist/react/index.js.map +1 -0
  112. package/dist/render/index.d.ts +131 -0
  113. package/dist/render/index.js +3 -0
  114. package/dist/render/index.js.map +1 -0
  115. package/dist/router/index.d.ts +65 -0
  116. package/dist/router/index.js +3 -0
  117. package/dist/router/index.js.map +1 -0
  118. package/dist/rsc/adapters/index.d.ts +8 -0
  119. package/dist/rsc/adapters/index.js +7 -0
  120. package/dist/rsc/adapters/index.js.map +1 -0
  121. package/dist/rsc/adapters/preact.d.ts +97 -0
  122. package/dist/rsc/adapters/preact.js +3 -0
  123. package/dist/rsc/adapters/preact.js.map +1 -0
  124. package/dist/rsc/adapters/react.d.ts +82 -0
  125. package/dist/rsc/adapters/react.js +3 -0
  126. package/dist/rsc/adapters/react.js.map +1 -0
  127. package/dist/rsc/adapters/solid.d.ts +84 -0
  128. package/dist/rsc/adapters/solid.js +3 -0
  129. package/dist/rsc/adapters/solid.js.map +1 -0
  130. package/dist/rsc/adapters/vue.d.ts +80 -0
  131. package/dist/rsc/adapters/vue.js +3 -0
  132. package/dist/rsc/adapters/vue.js.map +1 -0
  133. package/dist/rsc/boundaries.d.ts +182 -0
  134. package/dist/rsc/boundaries.js +3 -0
  135. package/dist/rsc/boundaries.js.map +1 -0
  136. package/dist/rsc/context.d.ts +201 -0
  137. package/dist/rsc/context.js +3 -0
  138. package/dist/rsc/context.js.map +1 -0
  139. package/dist/rsc/index.d.ts +232 -0
  140. package/dist/rsc/index.js +15 -0
  141. package/dist/rsc/index.js.map +1 -0
  142. package/dist/rsc/legacy.d.ts +155 -0
  143. package/dist/rsc/legacy.js +3 -0
  144. package/dist/rsc/legacy.js.map +1 -0
  145. package/dist/rsc/payload.d.ts +262 -0
  146. package/dist/rsc/payload.js +3 -0
  147. package/dist/rsc/payload.js.map +1 -0
  148. package/dist/rsc/plugins/esbuild.d.ts +124 -0
  149. package/dist/rsc/plugins/esbuild.js +4 -0
  150. package/dist/rsc/plugins/esbuild.js.map +1 -0
  151. package/dist/rsc/plugins/index.d.ts +4 -0
  152. package/dist/rsc/plugins/index.js +6 -0
  153. package/dist/rsc/plugins/index.js.map +1 -0
  154. package/dist/rsc/plugins/rollup.d.ts +103 -0
  155. package/dist/rsc/plugins/rollup.js +4 -0
  156. package/dist/rsc/plugins/rollup.js.map +1 -0
  157. package/dist/rsc/renderer.d.ts +162 -0
  158. package/dist/rsc/renderer.js +5 -0
  159. package/dist/rsc/renderer.js.map +1 -0
  160. package/dist/rsc/stream.d.ts +129 -0
  161. package/dist/rsc/stream.js +3 -0
  162. package/dist/rsc/stream.js.map +1 -0
  163. package/dist/rsc/vite-plugin.d.ts +78 -0
  164. package/dist/rsc/vite-plugin.js +4 -0
  165. package/dist/rsc/vite-plugin.js.map +1 -0
  166. package/dist/server/index.d.ts +135 -0
  167. package/dist/server/index.js +6 -0
  168. package/dist/server/index.js.map +1 -0
  169. package/dist/streaming/adapters/index.d.ts +223 -0
  170. package/dist/streaming/adapters/index.js +3 -0
  171. package/dist/streaming/adapters/index.js.map +1 -0
  172. package/dist/streaming/conditional.d.ts +130 -0
  173. package/dist/streaming/conditional.js +3 -0
  174. package/dist/streaming/conditional.js.map +1 -0
  175. package/dist/streaming/index.d.ts +177 -0
  176. package/dist/streaming/index.js +3 -0
  177. package/dist/streaming/index.js.map +1 -0
  178. package/dist/streaming/observability.d.ts +201 -0
  179. package/dist/streaming/observability.js +4 -0
  180. package/dist/streaming/observability.js.map +1 -0
  181. package/dist/streaming/priority.d.ts +103 -0
  182. package/dist/streaming/priority.js +3 -0
  183. package/dist/streaming/priority.js.map +1 -0
  184. package/dist/utils/index.d.ts +42 -0
  185. package/dist/utils/index.js +4 -0
  186. package/dist/utils/index.js.map +1 -0
  187. package/package.json +228 -0
@@ -0,0 +1,394 @@
1
+ // src/middleware/index.ts
2
+ function createMiddlewareChain() {
3
+ const stack = [];
4
+ function use(pathOrMiddleware, maybeMiddleware) {
5
+ if (typeof pathOrMiddleware === "function") {
6
+ stack.push({ handler: pathOrMiddleware });
7
+ } else if (typeof pathOrMiddleware === "string" && maybeMiddleware) {
8
+ stack.push({ path: pathOrMiddleware, handler: maybeMiddleware });
9
+ } else if (typeof pathOrMiddleware === "object") {
10
+ stack.push(pathOrMiddleware);
11
+ }
12
+ return chain;
13
+ }
14
+ async function execute(ctx) {
15
+ let index = -1;
16
+ async function dispatch(i) {
17
+ if (i <= index) {
18
+ throw new Error("next() called multiple times");
19
+ }
20
+ index = i;
21
+ if (i >= stack.length) {
22
+ return;
23
+ }
24
+ const definition = stack[i];
25
+ if (!definition) {
26
+ return dispatch(i + 1);
27
+ }
28
+ if (!shouldRun(definition, ctx)) {
29
+ return dispatch(i + 1);
30
+ }
31
+ await definition.handler(ctx, () => dispatch(i + 1));
32
+ }
33
+ await dispatch(0);
34
+ }
35
+ const chain = {
36
+ use,
37
+ execute,
38
+ middlewares: () => [...stack]
39
+ };
40
+ return chain;
41
+ }
42
+ function shouldRun(def, ctx) {
43
+ if (def.methods && !def.methods.includes(ctx.method.toUpperCase())) {
44
+ return false;
45
+ }
46
+ if (def.path) {
47
+ const path = ctx.url.pathname;
48
+ if (typeof def.path === "string") {
49
+ if (def.path.endsWith("*")) {
50
+ const prefix = def.path.slice(0, -1);
51
+ if (!path.startsWith(prefix)) {
52
+ return false;
53
+ }
54
+ } else if (def.path !== path) {
55
+ return false;
56
+ }
57
+ } else if (def.path instanceof RegExp) {
58
+ if (!def.path.test(path)) {
59
+ return false;
60
+ }
61
+ }
62
+ }
63
+ return true;
64
+ }
65
+ function cors(options = {}) {
66
+ const {
67
+ origin = "*",
68
+ methods = ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
69
+ headers = ["Content-Type", "Authorization"],
70
+ credentials = false,
71
+ maxAge = 86400,
72
+ exposeHeaders = []
73
+ } = options;
74
+ const isDynamicOrigin = typeof origin === "function" || Array.isArray(origin);
75
+ return async (ctx, next) => {
76
+ const requestOrigin = ctx.headers.get("Origin") || "";
77
+ if (isDynamicOrigin) {
78
+ const existingVary = ctx.responseHeaders.get("Vary");
79
+ if (existingVary) {
80
+ if (!existingVary.includes("Origin")) {
81
+ ctx.responseHeaders.set("Vary", `${existingVary}, Origin`);
82
+ }
83
+ } else {
84
+ ctx.responseHeaders.set("Vary", "Origin");
85
+ }
86
+ }
87
+ let allowedOrigin = null;
88
+ if (origin === "*") {
89
+ allowedOrigin = "*";
90
+ } else if (typeof origin === "string") {
91
+ allowedOrigin = origin;
92
+ } else if (Array.isArray(origin)) {
93
+ if (origin.includes(requestOrigin)) {
94
+ allowedOrigin = requestOrigin;
95
+ }
96
+ } else if (typeof origin === "function") {
97
+ const isAllowed = await origin(requestOrigin);
98
+ if (isAllowed) {
99
+ allowedOrigin = requestOrigin;
100
+ }
101
+ }
102
+ if (allowedOrigin) {
103
+ ctx.responseHeaders.set("Access-Control-Allow-Origin", allowedOrigin);
104
+ ctx.responseHeaders.set("Access-Control-Allow-Methods", methods.join(", "));
105
+ ctx.responseHeaders.set("Access-Control-Allow-Headers", headers.join(", "));
106
+ if (credentials) {
107
+ ctx.responseHeaders.set("Access-Control-Allow-Credentials", "true");
108
+ }
109
+ if (maxAge) {
110
+ ctx.responseHeaders.set("Access-Control-Max-Age", String(maxAge));
111
+ }
112
+ if (exposeHeaders.length > 0) {
113
+ ctx.responseHeaders.set("Access-Control-Expose-Headers", exposeHeaders.join(", "));
114
+ }
115
+ }
116
+ if (ctx.method === "OPTIONS") {
117
+ ctx.status = 204;
118
+ ctx.responseBody = null;
119
+ return;
120
+ }
121
+ await next();
122
+ };
123
+ }
124
+ var LOG_LEVEL_PRIORITY = {
125
+ debug: 0,
126
+ info: 1,
127
+ warn: 2,
128
+ error: 3,
129
+ silent: 4
130
+ };
131
+ var LOG_LEVEL_COLORS = {
132
+ debug: "\x1B[36m",
133
+ // Cyan
134
+ info: "\x1B[32m",
135
+ // Green
136
+ warn: "\x1B[33m",
137
+ // Yellow
138
+ error: "\x1B[31m",
139
+ // Red
140
+ silent: ""
141
+ };
142
+ var STATUS_COLORS = {
143
+ "2": "\x1B[32m",
144
+ // Green for 2xx
145
+ "3": "\x1B[36m",
146
+ // Cyan for 3xx
147
+ "4": "\x1B[33m",
148
+ // Yellow for 4xx
149
+ "5": "\x1B[31m"
150
+ // Red for 5xx
151
+ };
152
+ var RESET = "\x1B[0m";
153
+ var DIM = "\x1B[2m";
154
+ function logger(options = {}) {
155
+ const {
156
+ level = "info",
157
+ format = "pretty",
158
+ skip,
159
+ writer,
160
+ includeHeaders = false,
161
+ colorize = true
162
+ } = options;
163
+ const outputLog = (ctx, logLevel, startTime, duration, error) => {
164
+ const status = error ? 500 : ctx.status;
165
+ const userAgent = ctx.headers.get("user-agent");
166
+ const forwardedFor = ctx.headers.get("x-forwarded-for");
167
+ const ip = forwardedFor || "unknown";
168
+ const entry = {
169
+ timestamp: startTime,
170
+ level: logLevel,
171
+ method: ctx.method,
172
+ path: ctx.url.pathname,
173
+ status,
174
+ duration
175
+ };
176
+ if (userAgent) entry.userAgent = userAgent;
177
+ entry.ip = ip;
178
+ if (error) {
179
+ entry.error = error.message;
180
+ entry.stack = error.stack;
181
+ }
182
+ if (includeHeaders) {
183
+ const headers = {};
184
+ ctx.headers.forEach((value, key) => {
185
+ if (!key.toLowerCase().includes("authorization")) {
186
+ headers[key] = value;
187
+ }
188
+ });
189
+ entry.headers = headers;
190
+ }
191
+ let formatted;
192
+ switch (format) {
193
+ case "json":
194
+ formatted = JSON.stringify(entry);
195
+ break;
196
+ case "combined":
197
+ formatted = `${ip} - - [${startTime}] "${ctx.method} ${ctx.url.pathname}" ${status} - "${userAgent || "-"}"`;
198
+ break;
199
+ case "common":
200
+ formatted = `${ip} - - [${startTime}] "${ctx.method} ${ctx.url.pathname}" ${status}`;
201
+ break;
202
+ case "short":
203
+ formatted = `${ctx.method} ${ctx.url.pathname} ${status} ${duration}ms`;
204
+ break;
205
+ case "tiny":
206
+ formatted = `${ctx.method} ${ctx.url.pathname} ${status}`;
207
+ break;
208
+ case "pretty":
209
+ default:
210
+ if (colorize) {
211
+ const statusFirstChar = String(status).charAt(0) || "2";
212
+ const statusColor = STATUS_COLORS[statusFirstChar] ?? "";
213
+ const levelColor = LOG_LEVEL_COLORS[logLevel];
214
+ const errorSuffix = error ? ` ${LOG_LEVEL_COLORS.error}[${error.message}]${RESET}` : "";
215
+ formatted = `${DIM}${startTime}${RESET} ${levelColor}${logLevel.toUpperCase().padEnd(5)}${RESET} ${ctx.method.padEnd(7)} ${ctx.url.pathname} ${statusColor}${status}${RESET} ${DIM}${duration}ms${RESET}${errorSuffix}`;
216
+ } else {
217
+ const errorSuffix = error ? ` [${error.message}]` : "";
218
+ formatted = `${startTime} ${logLevel.toUpperCase().padEnd(5)} ${ctx.method.padEnd(7)} ${ctx.url.pathname} ${status} ${duration}ms${errorSuffix}`;
219
+ }
220
+ break;
221
+ }
222
+ if (writer) {
223
+ writer(entry, formatted);
224
+ } else {
225
+ switch (logLevel) {
226
+ case "error":
227
+ console.error(formatted);
228
+ break;
229
+ case "warn":
230
+ console.warn(formatted);
231
+ break;
232
+ case "debug":
233
+ console.debug(formatted);
234
+ break;
235
+ default:
236
+ console.log(formatted);
237
+ }
238
+ }
239
+ };
240
+ return async (ctx, next) => {
241
+ if (skip?.(ctx)) {
242
+ return next();
243
+ }
244
+ const start = Date.now();
245
+ const startTime = (/* @__PURE__ */ new Date()).toISOString();
246
+ try {
247
+ await next();
248
+ const duration = Date.now() - start;
249
+ const status = ctx.status;
250
+ let logLevel = "info";
251
+ if (status >= 500) {
252
+ logLevel = "error";
253
+ } else if (status >= 400) {
254
+ logLevel = "warn";
255
+ } else if (status >= 300) {
256
+ logLevel = "info";
257
+ } else {
258
+ logLevel = "debug";
259
+ }
260
+ if (LOG_LEVEL_PRIORITY[logLevel] >= LOG_LEVEL_PRIORITY[level]) {
261
+ outputLog(ctx, logLevel, startTime, duration);
262
+ }
263
+ } catch (error) {
264
+ const duration = Date.now() - start;
265
+ if (LOG_LEVEL_PRIORITY.error >= LOG_LEVEL_PRIORITY[level]) {
266
+ outputLog(ctx, "error", startTime, duration, error);
267
+ }
268
+ throw error;
269
+ }
270
+ };
271
+ }
272
+ function securityHeaders(options = {}) {
273
+ const {
274
+ contentSecurityPolicy = "default-src 'self'",
275
+ xFrameOptions = "DENY",
276
+ xContentTypeOptions = true,
277
+ referrerPolicy = "strict-origin-when-cross-origin",
278
+ permissionsPolicy
279
+ } = options;
280
+ return async (ctx, next) => {
281
+ if (contentSecurityPolicy) {
282
+ ctx.responseHeaders.set("Content-Security-Policy", contentSecurityPolicy);
283
+ }
284
+ if (xFrameOptions) {
285
+ ctx.responseHeaders.set("X-Frame-Options", xFrameOptions);
286
+ }
287
+ if (xContentTypeOptions) {
288
+ ctx.responseHeaders.set("X-Content-Type-Options", "nosniff");
289
+ }
290
+ if (referrerPolicy) {
291
+ ctx.responseHeaders.set("Referrer-Policy", referrerPolicy);
292
+ }
293
+ if (permissionsPolicy) {
294
+ ctx.responseHeaders.set("Permissions-Policy", permissionsPolicy);
295
+ }
296
+ await next();
297
+ };
298
+ }
299
+ function compress() {
300
+ return async (ctx, next) => {
301
+ ctx.locals["flight:compress"] = true;
302
+ await next();
303
+ };
304
+ }
305
+ function errorHandler(options = {}) {
306
+ const {
307
+ onError,
308
+ expose = false,
309
+ defaultStatus = 500,
310
+ emit
311
+ } = options;
312
+ return async (ctx, next) => {
313
+ try {
314
+ await next();
315
+ } catch (err) {
316
+ const error = err instanceof Error ? err : new Error(String(err));
317
+ const status = error.status ?? error.statusCode ?? defaultStatus;
318
+ const code = error.code;
319
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
320
+ const errorInfo = {
321
+ error,
322
+ status,
323
+ code,
324
+ ctx,
325
+ timestamp
326
+ };
327
+ if (emit) {
328
+ try {
329
+ emit(error, ctx);
330
+ } catch {
331
+ }
332
+ }
333
+ if (onError) {
334
+ await onError(errorInfo);
335
+ } else {
336
+ ctx.status = status;
337
+ ctx.responseHeaders.set("Content-Type", "application/json");
338
+ const body = expose ? {
339
+ error: error.message,
340
+ code,
341
+ status,
342
+ timestamp,
343
+ stack: error.stack
344
+ } : {
345
+ error: status >= 500 ? "Internal Server Error" : error.message,
346
+ code,
347
+ status,
348
+ timestamp
349
+ };
350
+ ctx.responseBody = JSON.stringify(body);
351
+ }
352
+ }
353
+ };
354
+ }
355
+ function createContextFromRequest(request, params = {}) {
356
+ const url = new URL(request.url);
357
+ return {
358
+ url,
359
+ method: request.method,
360
+ headers: request.headers,
361
+ params,
362
+ query: url.searchParams,
363
+ locals: {},
364
+ request,
365
+ status: 200,
366
+ responseHeaders: new Headers()
367
+ };
368
+ }
369
+ function createResponseFromContext(ctx) {
370
+ return new Response(ctx.responseBody, {
371
+ status: ctx.status,
372
+ headers: ctx.responseHeaders
373
+ });
374
+ }
375
+ function compose(...middlewares) {
376
+ return async (ctx, next) => {
377
+ let index = -1;
378
+ async function dispatch(i) {
379
+ if (i <= index) {
380
+ throw new Error("next() called multiple times");
381
+ }
382
+ index = i;
383
+ const fn = i === middlewares.length ? next : middlewares[i];
384
+ if (fn) {
385
+ await fn(ctx, () => dispatch(i + 1));
386
+ }
387
+ }
388
+ await dispatch(0);
389
+ };
390
+ }
391
+
392
+ export { compose, compress, cors, createContextFromRequest, createMiddlewareChain, createResponseFromContext, errorHandler, logger, securityHeaders };
393
+ //# sourceMappingURL=chunk-OYF2OAKS.js.map
394
+ //# sourceMappingURL=chunk-OYF2OAKS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/middleware/index.ts"],"names":[],"mappings":"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","file":"chunk-OYF2OAKS.js","sourcesContent":["/**\r\n * Flight Middleware - Composable request/response handlers\r\n * \r\n * Framework-agnostic middleware system inspired by Koa/Hono.\r\n * Provides primitives for building your own middleware solutions.\r\n * \r\n * @example\r\n * ```typescript\r\n * // Type-safe middleware with custom variables (Hono pattern)\r\n * interface MyLocals {\r\n * user: { id: string; role: string };\r\n * requestId: string;\r\n * }\r\n * \r\n * const authMiddleware: Middleware<MyLocals> = async (ctx, next) => {\r\n * ctx.locals.user = { id: '123', role: 'admin' };\r\n * await next();\r\n * };\r\n * ```\r\n */\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Request context passed through middleware chain.\r\n * \r\n * Supports generic type parameter for type-safe locals (like Hono Variables).\r\n * \r\n * @typeParam TLocals - Type of the locals object for type-safe middleware data sharing\r\n * \r\n * @example\r\n * ```typescript\r\n * interface AppLocals {\r\n * user: User;\r\n * db: DatabaseClient;\r\n * }\r\n * \r\n * const ctx: MiddlewareContext<AppLocals> = createContextFromRequest(request);\r\n * ctx.locals.user = currentUser; // Type-safe!\r\n * ```\r\n */\r\nexport interface MiddlewareContext<TLocals extends Record<string, unknown> = Record<string, unknown>> {\r\n /** Request URL */\r\n url: URL;\r\n /** Request method */\r\n method: string;\r\n /** Request headers */\r\n headers: Headers;\r\n /** URL parameters from routing */\r\n params: Record<string, string | string[]>;\r\n /** Query parameters */\r\n query: URLSearchParams;\r\n /** Parsed request body (if any) */\r\n body?: unknown;\r\n /** Local data shared between middleware - type-safe with generics */\r\n locals: TLocals;\r\n /** Original request (platform-specific) */\r\n request?: Request;\r\n\r\n // Response building\r\n /** Response status code */\r\n status: number;\r\n /** Response headers */\r\n responseHeaders: Headers;\r\n /** Response body */\r\n responseBody?: BodyInit | null;\r\n}\r\n\r\n/** Next function to call the next middleware */\r\nexport type MiddlewareNext = () => Promise<void>;\r\n\r\n/**\r\n * Middleware function signature with optional typed locals.\r\n * \r\n * @typeParam TLocals - Type of the locals object for type-safe data sharing\r\n */\r\nexport type Middleware<TLocals extends Record<string, unknown> = Record<string, unknown>> = (\r\n ctx: MiddlewareContext<TLocals>,\r\n next: MiddlewareNext\r\n) => Promise<void> | void;\r\n\r\n/** Middleware with optional path matching */\r\nexport interface MiddlewareDefinition {\r\n /** Path pattern to match (undefined = match all) */\r\n path?: string | RegExp;\r\n /** HTTP methods to match (undefined = match all) */\r\n methods?: string[];\r\n /** The middleware function */\r\n handler: Middleware;\r\n}\r\n\r\n// ============================================================================\r\n// Middleware Chain\r\n// ============================================================================\r\n\r\nexport interface MiddlewareChain {\r\n /** Add middleware to the chain */\r\n use(middleware: Middleware): MiddlewareChain;\r\n use(path: string, middleware: Middleware): MiddlewareChain;\r\n use(definition: MiddlewareDefinition): MiddlewareChain;\r\n\r\n /** Execute the middleware chain */\r\n execute(ctx: MiddlewareContext): Promise<void>;\r\n\r\n /** Get all middleware definitions */\r\n middlewares(): MiddlewareDefinition[];\r\n}\r\n\r\n/**\r\n * Create a new middleware chain\r\n */\r\nexport function createMiddlewareChain(): MiddlewareChain {\r\n const stack: MiddlewareDefinition[] = [];\r\n\r\n function use(\r\n pathOrMiddleware: string | Middleware | MiddlewareDefinition,\r\n maybeMiddleware?: Middleware\r\n ): MiddlewareChain {\r\n if (typeof pathOrMiddleware === 'function') {\r\n // use(middleware)\r\n stack.push({ handler: pathOrMiddleware });\r\n } else if (typeof pathOrMiddleware === 'string' && maybeMiddleware) {\r\n // use(path, middleware)\r\n stack.push({ path: pathOrMiddleware, handler: maybeMiddleware });\r\n } else if (typeof pathOrMiddleware === 'object') {\r\n // use(definition)\r\n stack.push(pathOrMiddleware);\r\n }\r\n return chain;\r\n }\r\n\r\n async function execute(ctx: MiddlewareContext): Promise<void> {\r\n let index = -1;\r\n\r\n async function dispatch(i: number): Promise<void> {\r\n if (i <= index) {\r\n throw new Error('next() called multiple times');\r\n }\r\n index = i;\r\n\r\n if (i >= stack.length) {\r\n return;\r\n }\r\n\r\n const definition = stack[i];\r\n if (!definition) {\r\n return dispatch(i + 1);\r\n }\r\n\r\n // Check if middleware should run\r\n if (!shouldRun(definition, ctx)) {\r\n return dispatch(i + 1);\r\n }\r\n\r\n await definition.handler(ctx, () => dispatch(i + 1));\r\n }\r\n\r\n await dispatch(0);\r\n }\r\n\r\n const chain: MiddlewareChain = {\r\n use: use as MiddlewareChain['use'],\r\n execute,\r\n middlewares: () => [...stack],\r\n };\r\n\r\n return chain;\r\n}\r\n\r\n/**\r\n * Check if a middleware should run for the given context\r\n */\r\nfunction shouldRun(def: MiddlewareDefinition, ctx: MiddlewareContext): boolean {\r\n // Check method\r\n if (def.methods && !def.methods.includes(ctx.method.toUpperCase())) {\r\n return false;\r\n }\r\n\r\n // Check path\r\n if (def.path) {\r\n const path = ctx.url.pathname;\r\n\r\n if (typeof def.path === 'string') {\r\n // Simple path matching (supports wildcards)\r\n if (def.path.endsWith('*')) {\r\n const prefix = def.path.slice(0, -1);\r\n if (!path.startsWith(prefix)) {\r\n return false;\r\n }\r\n } else if (def.path !== path) {\r\n return false;\r\n }\r\n } else if (def.path instanceof RegExp) {\r\n if (!def.path.test(path)) {\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n return true;\r\n}\r\n\r\n// ============================================================================\r\n// Built-in Middleware Factories\r\n// ============================================================================\r\n\r\n/**\r\n * CORS middleware factory\r\n */\r\n/**\r\n * CORS options for configuring cross-origin requests.\r\n */\r\nexport interface CorsOptions {\r\n /** \r\n * Allowed origins. Can be:\r\n * - '*' for any origin\r\n * - A specific origin string\r\n * - An array of allowed origins\r\n * - A function that returns true if origin is allowed\r\n * - An async function for dynamic origin validation\r\n */\r\n origin?: string | string[] | ((origin: string) => boolean | Promise<boolean>);\r\n /** Allowed HTTP methods */\r\n methods?: string[];\r\n /** Allowed headers */\r\n headers?: string[];\r\n /** Whether to include credentials */\r\n credentials?: boolean;\r\n /** Preflight cache duration in seconds */\r\n maxAge?: number;\r\n /** Exposed headers that can be accessed from the response */\r\n exposeHeaders?: string[];\r\n}\r\n\r\n/**\r\n * CORS middleware factory.\r\n * \r\n * Handles cross-origin resource sharing with best practices:\r\n * - Adds Vary: Origin for dynamic origins (CDN compatibility)\r\n * - Supports async origin validation\r\n * - Proper preflight handling\r\n * \r\n * @example\r\n * ```typescript\r\n * // Allow specific origins\r\n * chain.use(cors({ origin: ['https://app.example.com'] }));\r\n * \r\n * // Dynamic validation\r\n * chain.use(cors({\r\n * origin: async (origin) => {\r\n * return await db.allowedOrigins.exists(origin);\r\n * }\r\n * }));\r\n * ```\r\n */\r\nexport function cors(options: CorsOptions = {}): Middleware {\r\n const {\r\n origin = '*',\r\n methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],\r\n headers = ['Content-Type', 'Authorization'],\r\n credentials = false,\r\n maxAge = 86400,\r\n exposeHeaders = [],\r\n } = options;\r\n\r\n // Track if origin is dynamic (requires Vary header)\r\n const isDynamicOrigin = typeof origin === 'function' || Array.isArray(origin);\r\n\r\n return async (ctx, next) => {\r\n const requestOrigin = ctx.headers.get('Origin') || '';\r\n\r\n // Add Vary: Origin for dynamic origins (CDN/cache compatibility)\r\n if (isDynamicOrigin) {\r\n const existingVary = ctx.responseHeaders.get('Vary');\r\n if (existingVary) {\r\n if (!existingVary.includes('Origin')) {\r\n ctx.responseHeaders.set('Vary', `${existingVary}, Origin`);\r\n }\r\n } else {\r\n ctx.responseHeaders.set('Vary', 'Origin');\r\n }\r\n }\r\n\r\n // Determine allowed origin\r\n let allowedOrigin: string | null = null;\r\n if (origin === '*') {\r\n allowedOrigin = '*';\r\n } else if (typeof origin === 'string') {\r\n allowedOrigin = origin;\r\n } else if (Array.isArray(origin)) {\r\n if (origin.includes(requestOrigin)) {\r\n allowedOrigin = requestOrigin;\r\n }\r\n } else if (typeof origin === 'function') {\r\n const isAllowed = await origin(requestOrigin);\r\n if (isAllowed) {\r\n allowedOrigin = requestOrigin;\r\n }\r\n }\r\n\r\n if (allowedOrigin) {\r\n ctx.responseHeaders.set('Access-Control-Allow-Origin', allowedOrigin);\r\n ctx.responseHeaders.set('Access-Control-Allow-Methods', methods.join(', '));\r\n ctx.responseHeaders.set('Access-Control-Allow-Headers', headers.join(', '));\r\n\r\n if (credentials) {\r\n ctx.responseHeaders.set('Access-Control-Allow-Credentials', 'true');\r\n }\r\n\r\n if (maxAge) {\r\n ctx.responseHeaders.set('Access-Control-Max-Age', String(maxAge));\r\n }\r\n\r\n if (exposeHeaders.length > 0) {\r\n ctx.responseHeaders.set('Access-Control-Expose-Headers', exposeHeaders.join(', '));\r\n }\r\n }\r\n\r\n // Handle preflight\r\n if (ctx.method === 'OPTIONS') {\r\n ctx.status = 204;\r\n ctx.responseBody = null;\r\n return;\r\n }\r\n\r\n await next();\r\n };\r\n}\r\n// ============================================================================\r\n// Logger Types and Constants\r\n// ============================================================================\r\n\r\n/** Log levels in order of verbosity */\r\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';\r\n\r\n/** Log format types */\r\nexport type LogFormat = 'pretty' | 'json' | 'combined' | 'common' | 'short' | 'tiny';\r\n\r\n/** Log entry structure for JSON format */\r\nexport interface LogEntry {\r\n timestamp: string;\r\n level: LogLevel;\r\n method: string;\r\n path: string;\r\n status: number;\r\n duration: number;\r\n userAgent?: string;\r\n ip?: string;\r\n [key: string]: unknown;\r\n}\r\n\r\n/** Custom log writer function */\r\nexport type LogWriter = (entry: LogEntry, formatted: string) => void;\r\n\r\n/** Logger options */\r\nexport interface LoggerOptions {\r\n /** Minimum log level (default: 'info') */\r\n level?: LogLevel;\r\n /** Output format (default: 'pretty') */\r\n format?: LogFormat;\r\n /** Skip logging for certain requests */\r\n skip?: (ctx: MiddlewareContext) => boolean;\r\n /** Custom log writer (replaces console output) */\r\n writer?: LogWriter;\r\n /** Include request headers in logs */\r\n includeHeaders?: boolean;\r\n /** Colorize output (only for 'pretty' format, default: true) */\r\n colorize?: boolean;\r\n}\r\n\r\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\r\n debug: 0,\r\n info: 1,\r\n warn: 2,\r\n error: 3,\r\n silent: 4,\r\n};\r\n\r\nconst LOG_LEVEL_COLORS: Record<LogLevel, string> = {\r\n debug: '\\x1b[36m', // Cyan\r\n info: '\\x1b[32m', // Green\r\n warn: '\\x1b[33m', // Yellow\r\n error: '\\x1b[31m', // Red\r\n silent: '',\r\n};\r\n\r\nconst STATUS_COLORS: Record<string, string> = {\r\n '2': '\\x1b[32m', // Green for 2xx\r\n '3': '\\x1b[36m', // Cyan for 3xx\r\n '4': '\\x1b[33m', // Yellow for 4xx\r\n '5': '\\x1b[31m', // Red for 5xx\r\n};\r\n\r\nconst RESET = '\\x1b[0m';\r\nconst DIM = '\\x1b[2m';\r\n\r\n/**\r\n * Professional logger middleware with configurable levels\r\n * \r\n * @example\r\n * ```typescript\r\n * // Basic usage\r\n * server.use(logger());\r\n * \r\n * // With level control\r\n * server.use(logger({ level: 'warn' })); // Only warn and error\r\n * \r\n * // JSON format for production/observability\r\n * server.use(logger({ format: 'json', level: 'info' }));\r\n * \r\n * // Custom writer (e.g., for external logging service)\r\n * server.use(logger({\r\n * writer: (entry) => myLoggingService.log(entry)\r\n * }));\r\n * \r\n * // Silent in production\r\n * server.use(logger({ level: process.env.NODE_ENV === 'production' ? 'error' : 'debug' }));\r\n * ```\r\n */\r\nexport function logger(options: LoggerOptions = {}): Middleware {\r\n const {\r\n level = 'info',\r\n format = 'pretty',\r\n skip,\r\n writer,\r\n includeHeaders = false,\r\n colorize = true,\r\n } = options;\r\n\r\n // Helper to format and output log\r\n const outputLog = (\r\n ctx: MiddlewareContext,\r\n logLevel: LogLevel,\r\n startTime: string,\r\n duration: number,\r\n error?: Error\r\n ): void => {\r\n const status = error ? 500 : ctx.status;\r\n const userAgent = ctx.headers.get('user-agent');\r\n const forwardedFor = ctx.headers.get('x-forwarded-for');\r\n const ip = forwardedFor || 'unknown';\r\n\r\n // Build log entry\r\n const entry: LogEntry = {\r\n timestamp: startTime,\r\n level: logLevel,\r\n method: ctx.method,\r\n path: ctx.url.pathname,\r\n status,\r\n duration,\r\n };\r\n\r\n if (userAgent) entry.userAgent = userAgent;\r\n entry.ip = ip;\r\n\r\n if (error) {\r\n entry.error = error.message;\r\n entry.stack = error.stack;\r\n }\r\n\r\n if (includeHeaders) {\r\n const headers: Record<string, string> = {};\r\n ctx.headers.forEach((value, key) => {\r\n if (!key.toLowerCase().includes('authorization')) {\r\n headers[key] = value;\r\n }\r\n });\r\n entry.headers = headers;\r\n }\r\n\r\n // Format the log line\r\n let formatted: string;\r\n\r\n switch (format) {\r\n case 'json':\r\n formatted = JSON.stringify(entry);\r\n break;\r\n\r\n case 'combined':\r\n formatted = `${ip} - - [${startTime}] \"${ctx.method} ${ctx.url.pathname}\" ${status} - \"${userAgent || '-'}\"`;\r\n break;\r\n\r\n case 'common':\r\n formatted = `${ip} - - [${startTime}] \"${ctx.method} ${ctx.url.pathname}\" ${status}`;\r\n break;\r\n\r\n case 'short':\r\n formatted = `${ctx.method} ${ctx.url.pathname} ${status} ${duration}ms`;\r\n break;\r\n\r\n case 'tiny':\r\n formatted = `${ctx.method} ${ctx.url.pathname} ${status}`;\r\n break;\r\n\r\n case 'pretty':\r\n default:\r\n if (colorize) {\r\n const statusFirstChar = String(status).charAt(0) || '2';\r\n const statusColor = STATUS_COLORS[statusFirstChar] ?? '';\r\n const levelColor = LOG_LEVEL_COLORS[logLevel];\r\n const errorSuffix = error ? ` ${LOG_LEVEL_COLORS.error}[${error.message}]${RESET}` : '';\r\n formatted = `${DIM}${startTime}${RESET} ${levelColor}${logLevel.toUpperCase().padEnd(5)}${RESET} ${ctx.method.padEnd(7)} ${ctx.url.pathname} ${statusColor}${status}${RESET} ${DIM}${duration}ms${RESET}${errorSuffix}`;\r\n } else {\r\n const errorSuffix = error ? ` [${error.message}]` : '';\r\n formatted = `${startTime} ${logLevel.toUpperCase().padEnd(5)} ${ctx.method.padEnd(7)} ${ctx.url.pathname} ${status} ${duration}ms${errorSuffix}`;\r\n }\r\n break;\r\n }\r\n\r\n // Output\r\n if (writer) {\r\n writer(entry, formatted);\r\n } else {\r\n switch (logLevel) {\r\n case 'error':\r\n console.error(formatted);\r\n break;\r\n case 'warn':\r\n console.warn(formatted);\r\n break;\r\n case 'debug':\r\n console.debug(formatted);\r\n break;\r\n default:\r\n console.log(formatted);\r\n }\r\n }\r\n };\r\n\r\n return async (ctx, next) => {\r\n // Skip if configured\r\n if (skip?.(ctx)) {\r\n return next();\r\n }\r\n\r\n const start = Date.now();\r\n const startTime = new Date().toISOString();\r\n\r\n try {\r\n await next();\r\n\r\n const duration = Date.now() - start;\r\n const status = ctx.status;\r\n\r\n // Determine log level based on status\r\n let logLevel: LogLevel = 'info';\r\n if (status >= 500) {\r\n logLevel = 'error';\r\n } else if (status >= 400) {\r\n logLevel = 'warn';\r\n } else if (status >= 300) {\r\n logLevel = 'info';\r\n } else {\r\n logLevel = 'debug';\r\n }\r\n\r\n // Check if we should log based on level\r\n if (LOG_LEVEL_PRIORITY[logLevel] >= LOG_LEVEL_PRIORITY[level]) {\r\n outputLog(ctx, logLevel, startTime, duration);\r\n }\r\n } catch (error) {\r\n // Always log errors, then re-throw\r\n const duration = Date.now() - start;\r\n if (LOG_LEVEL_PRIORITY.error >= LOG_LEVEL_PRIORITY[level]) {\r\n outputLog(ctx, 'error', startTime, duration, error as Error);\r\n }\r\n throw error;\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Security headers middleware\r\n */\r\nexport function securityHeaders(options: {\r\n contentSecurityPolicy?: string | false;\r\n xFrameOptions?: 'DENY' | 'SAMEORIGIN' | false;\r\n xContentTypeOptions?: boolean;\r\n referrerPolicy?: string;\r\n permissionsPolicy?: string;\r\n} = {}): Middleware {\r\n const {\r\n contentSecurityPolicy = \"default-src 'self'\",\r\n xFrameOptions = 'DENY',\r\n xContentTypeOptions = true,\r\n referrerPolicy = 'strict-origin-when-cross-origin',\r\n permissionsPolicy,\r\n } = options;\r\n\r\n return async (ctx, next) => {\r\n if (contentSecurityPolicy) {\r\n ctx.responseHeaders.set('Content-Security-Policy', contentSecurityPolicy);\r\n }\r\n if (xFrameOptions) {\r\n ctx.responseHeaders.set('X-Frame-Options', xFrameOptions);\r\n }\r\n if (xContentTypeOptions) {\r\n ctx.responseHeaders.set('X-Content-Type-Options', 'nosniff');\r\n }\r\n if (referrerPolicy) {\r\n ctx.responseHeaders.set('Referrer-Policy', referrerPolicy);\r\n }\r\n if (permissionsPolicy) {\r\n ctx.responseHeaders.set('Permissions-Policy', permissionsPolicy);\r\n }\r\n\r\n await next();\r\n };\r\n}\r\n\r\n/**\r\n * Compression middleware (requires implementation in adapter)\r\n */\r\nexport function compress(): Middleware {\r\n return async (ctx, next) => {\r\n // Mark that compression is desired\r\n ctx.locals['flight:compress'] = true;\r\n await next();\r\n };\r\n}\r\n\r\n// ============================================================================\r\n// Error Handler Middleware\r\n// ============================================================================\r\n\r\n/**\r\n * Error information passed to error handlers.\r\n */\r\nexport interface ErrorInfo {\r\n /** The original error */\r\n error: Error;\r\n /** HTTP status code (derived from error or default 500) */\r\n status: number;\r\n /** Error code for categorization */\r\n code?: string;\r\n /** Request context */\r\n ctx: MiddlewareContext;\r\n /** Request timestamp */\r\n timestamp: string;\r\n}\r\n\r\n/**\r\n * Error handler options.\r\n */\r\nexport interface ErrorHandlerOptions {\r\n /**\r\n * Custom error handler function.\r\n * Called when an error is caught. Can modify ctx to set response.\r\n * If not provided, a default JSON response is sent.\r\n */\r\n onError?: (info: ErrorInfo) => void | Promise<void>;\r\n\r\n /**\r\n * Whether to expose error details in response.\r\n * Set to false in production to hide internal error messages.\r\n * @default false\r\n */\r\n expose?: boolean;\r\n\r\n /**\r\n * Default status code for errors without a status property.\r\n * @default 500\r\n */\r\n defaultStatus?: number;\r\n\r\n /**\r\n * Emit error events for centralized logging (Koa pattern).\r\n * Provide a function to receive error events.\r\n */\r\n emit?: (error: Error, ctx: MiddlewareContext) => void;\r\n}\r\n\r\n/**\r\n * Error handler middleware factory.\r\n * \r\n * Provides centralized error handling following Koa best practices:\r\n * - Catches all downstream errors\r\n * - Sets appropriate status codes\r\n * - Supports custom error handlers\r\n * - Supports error event emission for logging\r\n * \r\n * Place this as one of the FIRST middleware in your chain.\r\n * \r\n * @example\r\n * ```typescript\r\n * // Basic usage - default JSON error response\r\n * chain.use(errorHandler());\r\n * \r\n * // With custom handler\r\n * chain.use(errorHandler({\r\n * onError: ({ error, status, ctx }) => {\r\n * ctx.status = status;\r\n * ctx.responseBody = JSON.stringify({\r\n * error: error.message,\r\n * code: 'SERVER_ERROR'\r\n * });\r\n * },\r\n * emit: (error, ctx) => {\r\n * logger.error('Request error:', error);\r\n * errorTracker.capture(error);\r\n * }\r\n * }));\r\n * \r\n * // Production-safe (hide error details)\r\n * chain.use(errorHandler({ expose: false }));\r\n * ```\r\n */\r\nexport function errorHandler(options: ErrorHandlerOptions = {}): Middleware {\r\n const {\r\n onError,\r\n expose = false,\r\n defaultStatus = 500,\r\n emit,\r\n } = options;\r\n\r\n return async (ctx, next) => {\r\n try {\r\n await next();\r\n } catch (err) {\r\n const error = err instanceof Error ? err : new Error(String(err));\r\n\r\n // Extract status from error if available\r\n const status = (error as Error & { status?: number; statusCode?: number }).status\r\n ?? (error as Error & { status?: number; statusCode?: number }).statusCode\r\n ?? defaultStatus;\r\n\r\n // Extract error code if available\r\n const code = (error as Error & { code?: string }).code;\r\n\r\n const timestamp = new Date().toISOString();\r\n\r\n const errorInfo: ErrorInfo = {\r\n error,\r\n status,\r\n code,\r\n ctx,\r\n timestamp,\r\n };\r\n\r\n // Emit error event for centralized logging (Koa pattern)\r\n if (emit) {\r\n try {\r\n emit(error, ctx);\r\n } catch {\r\n // Ignore emission errors to prevent infinite loops\r\n }\r\n }\r\n\r\n // Call custom error handler if provided\r\n if (onError) {\r\n await onError(errorInfo);\r\n } else {\r\n // Default error response\r\n ctx.status = status;\r\n ctx.responseHeaders.set('Content-Type', 'application/json');\r\n\r\n const body = expose\r\n ? {\r\n error: error.message,\r\n code,\r\n status,\r\n timestamp,\r\n stack: error.stack,\r\n }\r\n : {\r\n error: status >= 500 ? 'Internal Server Error' : error.message,\r\n code,\r\n status,\r\n timestamp,\r\n };\r\n\r\n ctx.responseBody = JSON.stringify(body);\r\n }\r\n }\r\n };\r\n}\r\n\r\n\r\n// ============================================================================\r\n// Utility Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Create a middleware context from a Web Request\r\n */\r\nexport function createContextFromRequest(\r\n request: Request,\r\n params: Record<string, string | string[]> = {}\r\n): MiddlewareContext {\r\n const url = new URL(request.url);\r\n\r\n return {\r\n url,\r\n method: request.method,\r\n headers: request.headers,\r\n params,\r\n query: url.searchParams,\r\n locals: {},\r\n request,\r\n status: 200,\r\n responseHeaders: new Headers(),\r\n };\r\n}\r\n\r\n/**\r\n * Create a Web Response from middleware context\r\n */\r\nexport function createResponseFromContext(ctx: MiddlewareContext): Response {\r\n return new Response(ctx.responseBody, {\r\n status: ctx.status,\r\n headers: ctx.responseHeaders,\r\n });\r\n}\r\n\r\n/**\r\n * Compose multiple middleware into one\r\n */\r\nexport function compose(...middlewares: Middleware[]): Middleware {\r\n return async (ctx, next) => {\r\n let index = -1;\r\n\r\n async function dispatch(i: number): Promise<void> {\r\n if (i <= index) {\r\n throw new Error('next() called multiple times');\r\n }\r\n index = i;\r\n\r\n const fn = i === middlewares.length ? next : middlewares[i];\r\n\r\n if (fn) {\r\n await fn(ctx, () => dispatch(i + 1));\r\n }\r\n }\r\n\r\n await dispatch(0);\r\n };\r\n}\r\n"]}