@superfunctions/http 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,261 @@
1
+ # @superfunctions/http
2
+
3
+ Framework-agnostic HTTP abstraction layer for building web APIs that work across Express, Hono, Fastify, Next.js, and more.
4
+
5
+ ## Features
6
+
7
+ - **Framework Agnostic**: Write your API logic once, deploy to any framework
8
+ - **Web Standards**: Built on standard `Request` and `Response` APIs
9
+ - **Type Safe**: Full TypeScript support with generic context types
10
+ - **Zero Dependencies**: Core package has no runtime dependencies
11
+ - **Middleware Support**: Compose middleware chains for authentication, CORS, etc.
12
+ - **Path Parameters**: Express-style path patterns with parameter extraction
13
+ - **Edge Compatible**: Works in edge runtimes (Cloudflare Workers, Deno, Bun)
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install @superfunctions/http
19
+ ```
20
+
21
+ For framework adapters:
22
+
23
+ ```bash
24
+ # Express
25
+ npm install @superfunctions/http-express
26
+
27
+ # Hono
28
+ npm install @superfunctions/http-hono
29
+ ```
30
+
31
+ ## Quick Start
32
+
33
+ ### Define Your API (Framework Agnostic)
34
+
35
+ ```typescript
36
+ import { createRouter } from '@superfunctions/http';
37
+
38
+ const apiRouter = createRouter({
39
+ routes: [
40
+ {
41
+ method: 'GET',
42
+ path: '/users',
43
+ handler: async () => {
44
+ const users = await db.query('SELECT * FROM users');
45
+ return Response.json(users);
46
+ },
47
+ },
48
+ {
49
+ method: 'GET',
50
+ path: '/users/:id',
51
+ handler: async (req, ctx) => {
52
+ const user = await db.query(
53
+ 'SELECT * FROM users WHERE id = ?',
54
+ [ctx.params.id]
55
+ );
56
+ return Response.json(user);
57
+ },
58
+ },
59
+ {
60
+ method: 'POST',
61
+ path: '/users',
62
+ handler: async (req, ctx) => {
63
+ const data = await ctx.json();
64
+ const user = await db.insert('users', data);
65
+ return Response.json(user, { status: 201 });
66
+ },
67
+ },
68
+ ],
69
+ });
70
+ ```
71
+
72
+ ### Use with Express
73
+
74
+ ```typescript
75
+ import express from 'express';
76
+ import { toExpressRouter } from '@superfunctions/http-express';
77
+ import { apiRouter } from './api';
78
+
79
+ const app = express();
80
+ app.use(express.json());
81
+ app.use('/api', toExpressRouter(apiRouter));
82
+ app.listen(3000);
83
+ ```
84
+
85
+ ### Use with Hono
86
+
87
+ ```typescript
88
+ import { Hono } from 'hono';
89
+ import { toHonoHandler } from '@superfunctions/http-hono';
90
+ import { apiRouter } from './api';
91
+
92
+ const app = new Hono();
93
+ app.route('/api', toHonoHandler(apiRouter));
94
+
95
+ export default app;
96
+ ```
97
+
98
+ ### Use Directly (Universal Handler)
99
+
100
+ For Fetch-native frameworks:
101
+
102
+ ```typescript
103
+ import { createRouter } from '@superfunctions/http';
104
+
105
+ const router = createRouter({ routes: [...] });
106
+
107
+ // Cloudflare Workers
108
+ export default {
109
+ fetch: (req) => router.handler(req)
110
+ };
111
+
112
+ // Deno
113
+ Deno.serve((req) => router.handler(req));
114
+
115
+ // Bun
116
+ Bun.serve({ fetch: (req) => router.handler(req) });
117
+ ```
118
+
119
+ ## Features
120
+
121
+ ### Middleware
122
+
123
+ ```typescript
124
+ const authMiddleware = async (req, ctx, next) => {
125
+ const token = req.headers.get('Authorization');
126
+ if (!token) {
127
+ return Response.json({ error: 'Unauthorized' }, { status: 401 });
128
+ }
129
+ ctx.user = await verifyToken(token);
130
+ return next();
131
+ };
132
+
133
+ const router = createRouter({
134
+ middleware: [authMiddleware],
135
+ routes: [...],
136
+ });
137
+ ```
138
+
139
+ ### Context
140
+
141
+ ```typescript
142
+ interface AppContext {
143
+ db: Database;
144
+ user?: User;
145
+ }
146
+
147
+ const router = createRouter<AppContext>({
148
+ context: async (req) => ({
149
+ db: adapter,
150
+ user: await getUser(req),
151
+ }),
152
+ routes: [
153
+ {
154
+ method: 'GET',
155
+ path: '/profile',
156
+ handler: async (req, ctx) => {
157
+ // ctx is typed as AppContext & RouteContext
158
+ return Response.json({ user: ctx.user });
159
+ },
160
+ },
161
+ ],
162
+ });
163
+ ```
164
+
165
+ ### Error Handling
166
+
167
+ ```typescript
168
+ import { RouterError, UnauthorizedError } from '@superfunctions/http';
169
+
170
+ const router = createRouter({
171
+ routes: [
172
+ {
173
+ method: 'GET',
174
+ path: '/protected',
175
+ handler: async () => {
176
+ throw new UnauthorizedError('Invalid token');
177
+ },
178
+ },
179
+ ],
180
+ onError: (error, req) => {
181
+ console.error('Error:', error);
182
+ return Response.json(
183
+ { error: error.message },
184
+ { status: error instanceof RouterError ? error.statusCode : 500 }
185
+ );
186
+ },
187
+ });
188
+ ```
189
+
190
+ ### CORS
191
+
192
+ ```typescript
193
+ import { corsMiddleware } from '@superfunctions/http/middleware';
194
+
195
+ const router = createRouter({
196
+ middleware: [
197
+ corsMiddleware({
198
+ origin: 'https://example.com',
199
+ methods: ['GET', 'POST'],
200
+ credentials: true,
201
+ }),
202
+ ],
203
+ routes: [...],
204
+ });
205
+ ```
206
+
207
+ ## API Reference
208
+
209
+ ### `createRouter<TContext>(options)`
210
+
211
+ Creates a framework-agnostic router.
212
+
213
+ **Options:**
214
+ - `routes`: Array of route definitions
215
+ - `middleware?`: Global middleware array
216
+ - `context?`: Static context or factory function
217
+ - `onError?`: Custom error handler
218
+ - `basePath?`: Base path prefix for all routes
219
+ - `cors?`: CORS configuration
220
+
221
+ **Returns:** `Router<TContext>`
222
+
223
+ ### Route Definition
224
+
225
+ ```typescript
226
+ interface Route<TContext> {
227
+ method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
228
+ path: string;
229
+ handler: RouteHandler<TContext>;
230
+ middleware?: Middleware<TContext>[];
231
+ meta?: Record<string, any>;
232
+ }
233
+ ```
234
+
235
+ ### Route Context
236
+
237
+ Every handler receives a context with:
238
+
239
+ ```typescript
240
+ interface RouteContext {
241
+ params: Record<string, string>; // Path parameters
242
+ query: URLSearchParams; // Query string
243
+ url: URL; // Full URL
244
+ json: () => Promise<any>; // Parse JSON body
245
+ formData: () => Promise<FormData>; // Parse form data
246
+ text: () => Promise<string>; // Get text body
247
+ }
248
+ ```
249
+
250
+ ## Framework Adapters
251
+
252
+ | Framework | Package | Function |
253
+ |-----------|---------|----------|
254
+ | Express | `@superfunctions/http-express` | `toExpressRouter()` |
255
+ | Hono | `@superfunctions/http-hono` | `toHonoHandler()` |
256
+
257
+ More adapters coming soon: Fastify, Next.js, SvelteKit, Remix, etc.
258
+
259
+ ## License
260
+
261
+ MIT
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Context helpers for request handling
3
+ */
4
+ import type { RouteContext } from './types.js';
5
+ /**
6
+ * Create a RouteContext from a Request and path params
7
+ */
8
+ export declare function createRouteContext(request: Request, params: Record<string, string>): RouteContext;
9
+ /**
10
+ * Merge user context with route context
11
+ */
12
+ export declare function mergeContexts<TContext>(userContext: TContext, routeContext: RouteContext): TContext & RouteContext;
13
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,YAAY,CAmCd;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EACpC,WAAW,EAAE,QAAQ,EACrB,YAAY,EAAE,YAAY,GACzB,QAAQ,GAAG,YAAY,CAKzB"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Context helpers for request handling
3
+ */
4
+ /**
5
+ * Create a RouteContext from a Request and path params
6
+ */
7
+ export function createRouteContext(request, params) {
8
+ const url = new URL(request.url);
9
+ const query = url.searchParams;
10
+ // Cache for parsed bodies to avoid multiple parsing
11
+ let jsonCache = null;
12
+ let textCache = null;
13
+ let formDataCache = null;
14
+ return {
15
+ params,
16
+ query,
17
+ url,
18
+ json: async () => {
19
+ if (!jsonCache) {
20
+ jsonCache = request.json();
21
+ }
22
+ return jsonCache;
23
+ },
24
+ text: async () => {
25
+ if (!textCache) {
26
+ textCache = request.text();
27
+ }
28
+ return textCache;
29
+ },
30
+ formData: async () => {
31
+ if (!formDataCache) {
32
+ formDataCache = request.formData();
33
+ }
34
+ return formDataCache;
35
+ },
36
+ };
37
+ }
38
+ /**
39
+ * Merge user context with route context
40
+ */
41
+ export function mergeContexts(userContext, routeContext) {
42
+ return {
43
+ ...userContext,
44
+ ...routeContext,
45
+ };
46
+ }
47
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAAgB,EAChB,MAA8B;IAE9B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACjC,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC;IAE/B,oDAAoD;IACpD,IAAI,SAAS,GAAwB,IAAI,CAAC;IAC1C,IAAI,SAAS,GAA2B,IAAI,CAAC;IAC7C,IAAI,aAAa,GAA6B,IAAI,CAAC;IAEnD,OAAO;QACL,MAAM;QACN,KAAK;QACL,GAAG;QAEH,IAAI,EAAE,KAAK,IAAyB,EAAE;YACpC,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,SAAS,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;YAC7B,CAAC;YACD,OAAO,SAAuB,CAAC;QACjC,CAAC;QAED,IAAI,EAAE,KAAK,IAAqB,EAAE;YAChC,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,SAAS,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;YAC7B,CAAC;YACD,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,QAAQ,EAAE,KAAK,IAAuB,EAAE;YACtC,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnB,aAAa,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;YACrC,CAAC;YACD,OAAO,aAAa,CAAC;QACvB,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAC3B,WAAqB,EACrB,YAA0B;IAE1B,OAAO;QACL,GAAG,WAAW;QACd,GAAG,YAAY;KAChB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Error classes for the HTTP abstraction layer
3
+ */
4
+ export declare class RouterError extends Error {
5
+ statusCode: number;
6
+ code?: string | undefined;
7
+ constructor(message: string, statusCode?: number, code?: string | undefined);
8
+ toResponse(): Response;
9
+ }
10
+ export declare class BadRequestError extends RouterError {
11
+ constructor(message?: string, code?: string);
12
+ }
13
+ export declare class UnauthorizedError extends RouterError {
14
+ constructor(message?: string, code?: string);
15
+ }
16
+ export declare class ForbiddenError extends RouterError {
17
+ constructor(message?: string, code?: string);
18
+ }
19
+ export declare class NotFoundError extends RouterError {
20
+ constructor(message?: string, code?: string);
21
+ }
22
+ export declare class MethodNotAllowedError extends RouterError {
23
+ constructor(message?: string, code?: string);
24
+ }
25
+ export declare class ConflictError extends RouterError {
26
+ constructor(message?: string, code?: string);
27
+ }
28
+ export declare class UnprocessableEntityError extends RouterError {
29
+ constructor(message?: string, code?: string);
30
+ }
31
+ export declare class TooManyRequestsError extends RouterError {
32
+ constructor(message?: string, code?: string);
33
+ }
34
+ export declare class InternalServerError extends RouterError {
35
+ constructor(message?: string, code?: string);
36
+ }
37
+ export declare class NotImplementedError extends RouterError {
38
+ constructor(message?: string, code?: string);
39
+ }
40
+ export declare class ServiceUnavailableError extends RouterError {
41
+ constructor(message?: string, code?: string);
42
+ }
43
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,qBAAa,WAAY,SAAQ,KAAK;IAG3B,UAAU,EAAE,MAAM;IAClB,IAAI,CAAC,EAAE,MAAM;gBAFpB,OAAO,EAAE,MAAM,EACR,UAAU,GAAE,MAAY,EACxB,IAAI,CAAC,EAAE,MAAM,YAAA;IAOtB,UAAU,IAAI,QAAQ;CASvB;AAED,qBAAa,eAAgB,SAAQ,WAAW;gBAClC,OAAO,GAAE,MAAsB,EAAE,IAAI,CAAC,EAAE,MAAM;CAI3D;AAED,qBAAa,iBAAkB,SAAQ,WAAW;gBACpC,OAAO,GAAE,MAAuB,EAAE,IAAI,CAAC,EAAE,MAAM;CAI5D;AAED,qBAAa,cAAe,SAAQ,WAAW;gBACjC,OAAO,GAAE,MAAoB,EAAE,IAAI,CAAC,EAAE,MAAM;CAIzD;AAED,qBAAa,aAAc,SAAQ,WAAW;gBAChC,OAAO,GAAE,MAAoB,EAAE,IAAI,CAAC,EAAE,MAAM;CAIzD;AAED,qBAAa,qBAAsB,SAAQ,WAAW;gBACxC,OAAO,GAAE,MAA6B,EAAE,IAAI,CAAC,EAAE,MAAM;CAIlE;AAED,qBAAa,aAAc,SAAQ,WAAW;gBAChC,OAAO,GAAE,MAAmB,EAAE,IAAI,CAAC,EAAE,MAAM;CAIxD;AAED,qBAAa,wBAAyB,SAAQ,WAAW;gBAC3C,OAAO,GAAE,MAA+B,EAAE,IAAI,CAAC,EAAE,MAAM;CAIpE;AAED,qBAAa,oBAAqB,SAAQ,WAAW;gBACvC,OAAO,GAAE,MAA4B,EAAE,IAAI,CAAC,EAAE,MAAM;CAIjE;AAED,qBAAa,mBAAoB,SAAQ,WAAW;gBACtC,OAAO,GAAE,MAAgC,EAAE,IAAI,CAAC,EAAE,MAAM;CAIrE;AAED,qBAAa,mBAAoB,SAAQ,WAAW;gBACtC,OAAO,GAAE,MAA0B,EAAE,IAAI,CAAC,EAAE,MAAM;CAI/D;AAED,qBAAa,uBAAwB,SAAQ,WAAW;gBAC1C,OAAO,GAAE,MAA8B,EAAE,IAAI,CAAC,EAAE,MAAM;CAInE"}
package/dist/errors.js ADDED
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Error classes for the HTTP abstraction layer
3
+ */
4
+ export class RouterError extends Error {
5
+ statusCode;
6
+ code;
7
+ constructor(message, statusCode = 500, code) {
8
+ super(message);
9
+ this.statusCode = statusCode;
10
+ this.code = code;
11
+ this.name = 'RouterError';
12
+ Object.setPrototypeOf(this, RouterError.prototype);
13
+ }
14
+ toResponse() {
15
+ return Response.json({
16
+ error: this.message,
17
+ code: this.code,
18
+ }, { status: this.statusCode });
19
+ }
20
+ }
21
+ export class BadRequestError extends RouterError {
22
+ constructor(message = 'Bad Request', code) {
23
+ super(message, 400, code);
24
+ this.name = 'BadRequestError';
25
+ }
26
+ }
27
+ export class UnauthorizedError extends RouterError {
28
+ constructor(message = 'Unauthorized', code) {
29
+ super(message, 401, code);
30
+ this.name = 'UnauthorizedError';
31
+ }
32
+ }
33
+ export class ForbiddenError extends RouterError {
34
+ constructor(message = 'Forbidden', code) {
35
+ super(message, 403, code);
36
+ this.name = 'ForbiddenError';
37
+ }
38
+ }
39
+ export class NotFoundError extends RouterError {
40
+ constructor(message = 'Not Found', code) {
41
+ super(message, 404, code);
42
+ this.name = 'NotFoundError';
43
+ }
44
+ }
45
+ export class MethodNotAllowedError extends RouterError {
46
+ constructor(message = 'Method Not Allowed', code) {
47
+ super(message, 405, code);
48
+ this.name = 'MethodNotAllowedError';
49
+ }
50
+ }
51
+ export class ConflictError extends RouterError {
52
+ constructor(message = 'Conflict', code) {
53
+ super(message, 409, code);
54
+ this.name = 'ConflictError';
55
+ }
56
+ }
57
+ export class UnprocessableEntityError extends RouterError {
58
+ constructor(message = 'Unprocessable Entity', code) {
59
+ super(message, 422, code);
60
+ this.name = 'UnprocessableEntityError';
61
+ }
62
+ }
63
+ export class TooManyRequestsError extends RouterError {
64
+ constructor(message = 'Too Many Requests', code) {
65
+ super(message, 429, code);
66
+ this.name = 'TooManyRequestsError';
67
+ }
68
+ }
69
+ export class InternalServerError extends RouterError {
70
+ constructor(message = 'Internal Server Error', code) {
71
+ super(message, 500, code);
72
+ this.name = 'InternalServerError';
73
+ }
74
+ }
75
+ export class NotImplementedError extends RouterError {
76
+ constructor(message = 'Not Implemented', code) {
77
+ super(message, 501, code);
78
+ this.name = 'NotImplementedError';
79
+ }
80
+ }
81
+ export class ServiceUnavailableError extends RouterError {
82
+ constructor(message = 'Service Unavailable', code) {
83
+ super(message, 503, code);
84
+ this.name = 'ServiceUnavailableError';
85
+ }
86
+ }
87
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @superfunctions/http - Framework-agnostic HTTP abstraction layer
3
+ */
4
+ export { createRouter } from './router.js';
5
+ export type { Router, RouterOptions, Route, RouteHandler, RouteContext, Middleware, MatchedRoute, HttpMethod, CorsOptions, } from './types.js';
6
+ export { RouterError, BadRequestError, UnauthorizedError, ForbiddenError, NotFoundError, MethodNotAllowedError, ConflictError, UnprocessableEntityError, TooManyRequestsError, InternalServerError, NotImplementedError, ServiceUnavailableError, } from './errors.js';
7
+ export { compilePattern, matchPath, normalizePath, joinPaths, } from './path-matcher.js';
8
+ export { createRouteContext, mergeContexts, } from './context.js';
9
+ export { executeMiddlewareChain, combineMiddleware, } from './middleware.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,YAAY,EACV,MAAM,EACN,aAAa,EACb,KAAK,EACL,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,UAAU,EACV,WAAW,GACZ,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,qBAAqB,EACrB,aAAa,EACb,wBAAwB,EACxB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,cAAc,EACd,SAAS,EACT,aAAa,EACb,SAAS,GACV,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,kBAAkB,EAClB,aAAa,GACd,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @superfunctions/http - Framework-agnostic HTTP abstraction layer
3
+ */
4
+ // Core router
5
+ export { createRouter } from './router.js';
6
+ // Errors
7
+ export { RouterError, BadRequestError, UnauthorizedError, ForbiddenError, NotFoundError, MethodNotAllowedError, ConflictError, UnprocessableEntityError, TooManyRequestsError, InternalServerError, NotImplementedError, ServiceUnavailableError, } from './errors.js';
8
+ // Utilities (exported for advanced use cases)
9
+ export { compilePattern, matchPath, normalizePath, joinPaths, } from './path-matcher.js';
10
+ export { createRouteContext, mergeContexts, } from './context.js';
11
+ export { executeMiddlewareChain, combineMiddleware, } from './middleware.js';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc;AACd,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAe3C,SAAS;AACT,OAAO,EACL,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,qBAAqB,EACrB,aAAa,EACb,wBAAwB,EACxB,oBAAoB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AAErB,8CAA8C;AAC9C,OAAO,EACL,cAAc,EACd,SAAS,EACT,aAAa,EACb,SAAS,GACV,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,kBAAkB,EAClB,aAAa,GACd,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * CORS middleware
3
+ */
4
+ import type { Middleware, CorsOptions } from '../types.js';
5
+ /**
6
+ * Create CORS middleware with configurable options
7
+ */
8
+ export declare function corsMiddleware<TContext = any>(options?: CorsOptions): Middleware<TContext>;
9
+ //# sourceMappingURL=cors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE3D;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,GAAG,GAAG,EAC3C,OAAO,GAAE,WAAgB,GACxB,UAAU,CAAC,QAAQ,CAAC,CA8EtB"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * CORS middleware
3
+ */
4
+ /**
5
+ * Create CORS middleware with configurable options
6
+ */
7
+ export function corsMiddleware(options = {}) {
8
+ const { origin = '*', methods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'], allowedHeaders = ['Content-Type', 'Authorization'], exposedHeaders = [], credentials = false, maxAge = 86400, // 24 hours
9
+ } = options;
10
+ return async (request, _context, next) => {
11
+ const requestOrigin = request.headers.get('Origin') || '';
12
+ // Determine if origin is allowed
13
+ let allowedOrigin = null;
14
+ if (typeof origin === 'string') {
15
+ allowedOrigin = origin;
16
+ }
17
+ else if (Array.isArray(origin)) {
18
+ if (origin.includes(requestOrigin)) {
19
+ allowedOrigin = requestOrigin;
20
+ }
21
+ }
22
+ else if (typeof origin === 'function') {
23
+ if (origin(requestOrigin)) {
24
+ allowedOrigin = requestOrigin;
25
+ }
26
+ }
27
+ // Handle preflight request
28
+ if (request.method === 'OPTIONS') {
29
+ const headers = new Headers();
30
+ if (allowedOrigin) {
31
+ headers.set('Access-Control-Allow-Origin', allowedOrigin);
32
+ }
33
+ headers.set('Access-Control-Allow-Methods', methods.join(', '));
34
+ headers.set('Access-Control-Allow-Headers', allowedHeaders.join(', '));
35
+ if (credentials) {
36
+ headers.set('Access-Control-Allow-Credentials', 'true');
37
+ }
38
+ if (maxAge) {
39
+ headers.set('Access-Control-Max-Age', maxAge.toString());
40
+ }
41
+ if (exposedHeaders.length > 0) {
42
+ headers.set('Access-Control-Expose-Headers', exposedHeaders.join(', '));
43
+ }
44
+ return new Response(null, { status: 204, headers });
45
+ }
46
+ // Handle actual request
47
+ const response = await next();
48
+ // Add CORS headers to response
49
+ if (allowedOrigin) {
50
+ const newHeaders = new Headers(response.headers);
51
+ newHeaders.set('Access-Control-Allow-Origin', allowedOrigin);
52
+ if (credentials) {
53
+ newHeaders.set('Access-Control-Allow-Credentials', 'true');
54
+ }
55
+ if (exposedHeaders.length > 0) {
56
+ newHeaders.set('Access-Control-Expose-Headers', exposedHeaders.join(', '));
57
+ }
58
+ return new Response(response.body, {
59
+ status: response.status,
60
+ statusText: response.statusText,
61
+ headers: newHeaders,
62
+ });
63
+ }
64
+ return response;
65
+ };
66
+ }
67
+ //# sourceMappingURL=cors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cors.js","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;GAEG;AACH,MAAM,UAAU,cAAc,CAC5B,UAAuB,EAAE;IAEzB,MAAM,EACJ,MAAM,GAAG,GAAG,EACZ,OAAO,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC,EACtE,cAAc,GAAG,CAAC,cAAc,EAAE,eAAe,CAAC,EAClD,cAAc,GAAG,EAAE,EACnB,WAAW,GAAG,KAAK,EACnB,MAAM,GAAG,KAAK,EAAE,WAAW;MAC5B,GAAG,OAAO,CAAC;IAEZ,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;QACvC,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QAE1D,iCAAiC;QACjC,IAAI,aAAa,GAAkB,IAAI,CAAC;QACxC,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC/B,aAAa,GAAG,MAAM,CAAC;QACzB,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACjC,IAAI,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;gBACnC,aAAa,GAAG,aAAa,CAAC;YAChC,CAAC;QACH,CAAC;aAAM,IAAI,OAAO,MAAM,KAAK,UAAU,EAAE,CAAC;YACxC,IAAI,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;gBAC1B,aAAa,GAAG,aAAa,CAAC;YAChC,CAAC;QACH,CAAC;QAED,2BAA2B;QAC3B,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACjC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;YAE9B,IAAI,aAAa,EAAE,CAAC;gBAClB,OAAO,CAAC,GAAG,CAAC,6BAA6B,EAAE,aAAa,CAAC,CAAC;YAC5D,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAChE,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAEvE,IAAI,WAAW,EAAE,CAAC;gBAChB,OAAO,CAAC,GAAG,CAAC,kCAAkC,EAAE,MAAM,CAAC,CAAC;YAC1D,CAAC;YAED,IAAI,MAAM,EAAE,CAAC;gBACX,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC3D,CAAC;YAED,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9B,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAC1E,CAAC;YAED,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QACtD,CAAC;QAED,wBAAwB;QACxB,MAAM,QAAQ,GAAG,MAAM,IAAI,EAAE,CAAC;QAE9B,+BAA+B;QAC/B,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,UAAU,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACjD,UAAU,CAAC,GAAG,CAAC,6BAA6B,EAAE,aAAa,CAAC,CAAC;YAE7D,IAAI,WAAW,EAAE,CAAC;gBAChB,UAAU,CAAC,GAAG,CAAC,kCAAkC,EAAE,MAAM,CAAC,CAAC;YAC7D,CAAC;YAED,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9B,UAAU,CAAC,GAAG,CAAC,+BAA+B,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAC7E,CAAC;YAED,OAAO,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE;gBACjC,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,UAAU,EAAE,QAAQ,CAAC,UAAU;gBAC/B,OAAO,EAAE,UAAU;aACpB,CAAC,CAAC;QACL,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Built-in middleware
3
+ */
4
+ export { corsMiddleware } from './cors.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Built-in middleware
3
+ */
4
+ export { corsMiddleware } from './cors.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Middleware chain execution
3
+ */
4
+ import type { Middleware, RouteContext } from './types.js';
5
+ /**
6
+ * Execute a chain of middleware functions
7
+ * Middleware can:
8
+ * - Call next() to continue to the next middleware/handler
9
+ * - Return a Response to short-circuit the chain
10
+ * - Throw an error to trigger error handling
11
+ */
12
+ export declare function executeMiddlewareChain<TContext>(middlewares: Middleware<TContext>[], request: Request, context: TContext & RouteContext, finalHandler: () => Promise<Response>): Promise<Response>;
13
+ /**
14
+ * Combine multiple middleware arrays into one
15
+ */
16
+ export declare function combineMiddleware<TContext>(...middlewareArrays: (Middleware<TContext>[] | undefined)[]): Middleware<TContext>[];
17
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE3D;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAAC,QAAQ,EACnD,WAAW,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,EACnC,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,QAAQ,GAAG,YAAY,EAChC,YAAY,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,GACpC,OAAO,CAAC,QAAQ,CAAC,CAiBnB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EACxC,GAAG,gBAAgB,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,GAAG,SAAS,CAAC,EAAE,GAC1D,UAAU,CAAC,QAAQ,CAAC,EAAE,CAExB"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Middleware chain execution
3
+ */
4
+ /**
5
+ * Execute a chain of middleware functions
6
+ * Middleware can:
7
+ * - Call next() to continue to the next middleware/handler
8
+ * - Return a Response to short-circuit the chain
9
+ * - Throw an error to trigger error handling
10
+ */
11
+ export async function executeMiddlewareChain(middlewares, request, context, finalHandler) {
12
+ let index = 0;
13
+ const next = async () => {
14
+ // If we've reached the end of middleware, call the final handler
15
+ if (index >= middlewares.length) {
16
+ return finalHandler();
17
+ }
18
+ // Get current middleware and increment index
19
+ const middleware = middlewares[index++];
20
+ // Execute middleware
21
+ return middleware(request, context, next);
22
+ };
23
+ return next();
24
+ }
25
+ /**
26
+ * Combine multiple middleware arrays into one
27
+ */
28
+ export function combineMiddleware(...middlewareArrays) {
29
+ return middlewareArrays.filter((arr) => !!arr).flat();
30
+ }
31
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,WAAmC,EACnC,OAAgB,EAChB,OAAgC,EAChC,YAAqC;IAErC,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,MAAM,IAAI,GAAG,KAAK,IAAuB,EAAE;QACzC,iEAAiE;QACjE,IAAI,KAAK,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC;YAChC,OAAO,YAAY,EAAE,CAAC;QACxB,CAAC;QAED,6CAA6C;QAC7C,MAAM,UAAU,GAAG,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC;QAExC,qBAAqB;QACrB,OAAO,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAC5C,CAAC,CAAC;IAEF,OAAO,IAAI,EAAE,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,GAAG,gBAAwD;IAE3D,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAiC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AACvF,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Path matching and parameter extraction for routes
3
+ */
4
+ export interface PathMatch {
5
+ matched: boolean;
6
+ params: Record<string, string>;
7
+ }
8
+ export interface CompiledPattern {
9
+ pattern: RegExp;
10
+ keys: string[];
11
+ }
12
+ /**
13
+ * Convert Express-style path pattern to regex with named capture groups
14
+ * Examples:
15
+ * - /users/:id -> /users/(?<id>[^/]+)
16
+ * - /posts/:id/comments/:commentId -> /posts/(?<id>[^/]+)/comments/(?<commentId>[^/]+)
17
+ */
18
+ export declare function compilePattern(pattern: string): CompiledPattern;
19
+ /**
20
+ * Match a path against a compiled pattern and extract parameters
21
+ */
22
+ export declare function matchPath(compiledPattern: CompiledPattern, path: string): PathMatch;
23
+ /**
24
+ * Normalize path by removing trailing slashes and ensuring leading slash
25
+ */
26
+ export declare function normalizePath(path: string): string;
27
+ /**
28
+ * Join base path with route path
29
+ */
30
+ export declare function joinPaths(basePath: string, routePath: string): string;
31
+ //# sourceMappingURL=path-matcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-matcher.d.ts","sourceRoot":"","sources":["../src/path-matcher.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe,CAgB/D;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,eAAe,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,CAiBnF;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAYlD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CASrE"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Path matching and parameter extraction for routes
3
+ */
4
+ /**
5
+ * Convert Express-style path pattern to regex with named capture groups
6
+ * Examples:
7
+ * - /users/:id -> /users/(?<id>[^/]+)
8
+ * - /posts/:id/comments/:commentId -> /posts/(?<id>[^/]+)/comments/(?<commentId>[^/]+)
9
+ */
10
+ export function compilePattern(pattern) {
11
+ const keys = [];
12
+ // Escape special regex characters except :
13
+ let regexPattern = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
14
+ // Replace :param with named capture groups
15
+ regexPattern = regexPattern.replace(/:(\w+)/g, (_, key) => {
16
+ keys.push(key);
17
+ return `(?<${key}>[^/]+)`;
18
+ });
19
+ // Add start and end anchors
20
+ const regex = new RegExp(`^${regexPattern}$`);
21
+ return { pattern: regex, keys };
22
+ }
23
+ /**
24
+ * Match a path against a compiled pattern and extract parameters
25
+ */
26
+ export function matchPath(compiledPattern, path) {
27
+ const match = path.match(compiledPattern.pattern);
28
+ if (!match) {
29
+ return { matched: false, params: {} };
30
+ }
31
+ const params = {};
32
+ // Extract named groups
33
+ if (match.groups) {
34
+ for (const key of compiledPattern.keys) {
35
+ params[key] = decodeURIComponent(match.groups[key]);
36
+ }
37
+ }
38
+ return { matched: true, params };
39
+ }
40
+ /**
41
+ * Normalize path by removing trailing slashes and ensuring leading slash
42
+ */
43
+ export function normalizePath(path) {
44
+ // Remove trailing slash (except for root path)
45
+ if (path.length > 1 && path.endsWith('/')) {
46
+ path = path.slice(0, -1);
47
+ }
48
+ // Ensure leading slash
49
+ if (!path.startsWith('/')) {
50
+ path = '/' + path;
51
+ }
52
+ return path;
53
+ }
54
+ /**
55
+ * Join base path with route path
56
+ */
57
+ export function joinPaths(basePath, routePath) {
58
+ const normalizedBase = normalizePath(basePath);
59
+ const normalizedRoute = normalizePath(routePath);
60
+ if (normalizedBase === '/') {
61
+ return normalizedRoute;
62
+ }
63
+ return normalizedBase + normalizedRoute;
64
+ }
65
+ //# sourceMappingURL=path-matcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-matcher.js","sourceRoot":"","sources":["../src/path-matcher.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,MAAM,IAAI,GAAa,EAAE,CAAC;IAE1B,2CAA2C;IAC3C,IAAI,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;IAEjE,2CAA2C;IAC3C,YAAY,GAAG,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE;QACxD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACf,OAAO,MAAM,GAAG,SAAS,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,4BAA4B;IAC5B,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,IAAI,YAAY,GAAG,CAAC,CAAC;IAE9C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,eAAgC,EAAE,IAAY;IACtE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;IAElD,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACxC,CAAC;IAED,MAAM,MAAM,GAA2B,EAAE,CAAC;IAE1C,uBAAuB;IACvB,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,KAAK,MAAM,GAAG,IAAI,eAAe,CAAC,IAAI,EAAE,CAAC;YACvC,MAAM,CAAC,GAAG,CAAC,GAAG,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,+CAA+C;IAC/C,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1C,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;IAED,uBAAuB;IACvB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1B,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC;IACpB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,SAAiB;IAC3D,MAAM,cAAc,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,eAAe,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;IAEjD,IAAI,cAAc,KAAK,GAAG,EAAE,CAAC;QAC3B,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,OAAO,cAAc,GAAG,eAAe,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Core router implementation
3
+ */
4
+ import type { Router, RouterOptions } from './types.js';
5
+ /**
6
+ * Create a framework-agnostic HTTP router
7
+ */
8
+ export declare function createRouter<TContext = any>(options: RouterOptions<TContext>): Router<TContext>;
9
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,MAAM,EACN,aAAa,EAId,MAAM,YAAY,CAAC;AAYpB;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,GAAG,GAAG,EACzC,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,GAC/B,MAAM,CAAC,QAAQ,CAAC,CA6JlB"}
package/dist/router.js ADDED
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Core router implementation
3
+ */
4
+ import { compilePattern, matchPath, normalizePath, joinPaths } from './path-matcher.js';
5
+ import { createRouteContext, mergeContexts } from './context.js';
6
+ import { executeMiddlewareChain, combineMiddleware } from './middleware.js';
7
+ import { RouterError, NotFoundError } from './errors.js';
8
+ /**
9
+ * Create a framework-agnostic HTTP router
10
+ */
11
+ export function createRouter(options) {
12
+ const { routes, middleware: globalMiddleware = [], context: contextFactory, onError, basePath = '/', } = options;
13
+ // Pre-compile all route patterns
14
+ const compiledRoutes = routes.map((route) => {
15
+ const fullPath = joinPaths(basePath, route.path);
16
+ return {
17
+ route,
18
+ compiledPattern: compilePattern(fullPath),
19
+ fullPath,
20
+ };
21
+ });
22
+ /**
23
+ * Match a route by method and path
24
+ */
25
+ function match(method, path) {
26
+ const normalizedPath = normalizePath(path);
27
+ for (const entry of compiledRoutes) {
28
+ if (entry.route.method !== method) {
29
+ continue;
30
+ }
31
+ const pathMatch = matchPath(entry.compiledPattern, normalizedPath);
32
+ if (pathMatch.matched) {
33
+ return {
34
+ route: entry.route,
35
+ params: pathMatch.params,
36
+ };
37
+ }
38
+ }
39
+ return null;
40
+ }
41
+ /**
42
+ * Handle an incoming request
43
+ */
44
+ async function handle(request) {
45
+ try {
46
+ const url = new URL(request.url);
47
+ const path = url.pathname;
48
+ const method = request.method;
49
+ // Try to match a route
50
+ const matched = match(method, path);
51
+ if (!matched) {
52
+ throw new NotFoundError(`Route not found: ${method} ${path}`);
53
+ }
54
+ // Create route context
55
+ const routeContext = createRouteContext(request, matched.params);
56
+ // Create user context
57
+ let userContext;
58
+ if (contextFactory !== undefined) {
59
+ if (typeof contextFactory === 'function') {
60
+ userContext = await contextFactory(request);
61
+ }
62
+ else {
63
+ userContext = contextFactory;
64
+ }
65
+ }
66
+ else {
67
+ userContext = {};
68
+ }
69
+ // Merge contexts
70
+ const fullContext = mergeContexts(userContext, routeContext);
71
+ // Combine global and route-specific middleware
72
+ const allMiddleware = combineMiddleware(globalMiddleware, matched.route.middleware);
73
+ // Execute middleware chain + handler
74
+ const response = await executeMiddlewareChain(allMiddleware, request, fullContext, async () => matched.route.handler(request, fullContext));
75
+ return response;
76
+ }
77
+ catch (error) {
78
+ // Handle errors
79
+ if (onError) {
80
+ try {
81
+ return await onError(error, request);
82
+ }
83
+ catch (handlerError) {
84
+ // If error handler itself fails, return 500
85
+ return Response.json({ error: 'Internal Server Error' }, { status: 500 });
86
+ }
87
+ }
88
+ // Default error handling
89
+ if (error instanceof RouterError) {
90
+ return error.toResponse();
91
+ }
92
+ // Unknown error - don't expose details
93
+ console.error('Router error:', error);
94
+ return Response.json({ error: 'Internal Server Error' }, { status: 500 });
95
+ }
96
+ }
97
+ /**
98
+ * Get all routes
99
+ */
100
+ function getRoutes() {
101
+ return routes;
102
+ }
103
+ /**
104
+ * Add a route dynamically
105
+ */
106
+ function addRoute(route) {
107
+ routes.push(route);
108
+ const fullPath = joinPaths(basePath, route.path);
109
+ compiledRoutes.push({
110
+ route,
111
+ compiledPattern: compilePattern(fullPath),
112
+ fullPath,
113
+ });
114
+ }
115
+ /**
116
+ * Add middleware dynamically
117
+ */
118
+ function use(middleware) {
119
+ globalMiddleware.push(middleware);
120
+ }
121
+ // Create router object
122
+ const router = {
123
+ handle,
124
+ getRoutes,
125
+ addRoute,
126
+ use,
127
+ match,
128
+ handler: handle, // Alias for convenience
129
+ };
130
+ return router;
131
+ }
132
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Core type definitions for the HTTP abstraction layer
3
+ */
4
+ export interface RouterOptions<TContext = any> {
5
+ /** Route definitions */
6
+ routes: Route<TContext>[];
7
+ /** Global middleware (runs before all routes) */
8
+ middleware?: Middleware<TContext>[];
9
+ /** Context factory (creates context per request) */
10
+ context?: TContext | ((request: Request) => Promise<TContext> | TContext);
11
+ /** Error handler */
12
+ onError?: (error: Error, request: Request) => Response | Promise<Response>;
13
+ /** Base path for all routes */
14
+ basePath?: string;
15
+ /** CORS configuration */
16
+ cors?: CorsOptions | false;
17
+ }
18
+ export interface Route<TContext = any> {
19
+ /** HTTP method */
20
+ method: HttpMethod;
21
+ /** Route path (supports params: /users/:id) */
22
+ path: string;
23
+ /** Route handler */
24
+ handler: RouteHandler<TContext>;
25
+ /** Route-specific middleware */
26
+ middleware?: Middleware<TContext>[];
27
+ /** Metadata (for docs, validation, etc.) */
28
+ meta?: Record<string, any>;
29
+ }
30
+ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
31
+ export type RouteHandler<TContext = any> = (request: Request, context: TContext & RouteContext) => Promise<Response> | Response;
32
+ export interface RouteContext {
33
+ /** Parsed path params */
34
+ params: Record<string, string>;
35
+ /** Query string parsed as URLSearchParams */
36
+ query: URLSearchParams;
37
+ /** Request URL */
38
+ url: URL;
39
+ /** Convenience: parse JSON body */
40
+ json: <T = any>() => Promise<T>;
41
+ /** Convenience: parse form data */
42
+ formData: () => Promise<FormData>;
43
+ /** Convenience: get text body */
44
+ text: () => Promise<string>;
45
+ }
46
+ export type Middleware<TContext = any> = (request: Request, context: TContext & RouteContext, next: () => Promise<Response>) => Promise<Response> | Response;
47
+ export interface Router<TContext = any> {
48
+ /** Handle a Web Standard Request */
49
+ handle(request: Request): Promise<Response>;
50
+ /** Get all routes */
51
+ getRoutes(): Route<TContext>[];
52
+ /** Add route dynamically */
53
+ addRoute(route: Route<TContext>): void;
54
+ /** Add middleware dynamically */
55
+ use(middleware: Middleware<TContext>): void;
56
+ /** Match route by method and path */
57
+ match(method: string, path: string): MatchedRoute<TContext> | null;
58
+ /**
59
+ * Universal handler - can be used directly in Fetch-native frameworks
60
+ * This is an alias to router.handle for convenience
61
+ */
62
+ handler: (request: Request) => Promise<Response>;
63
+ }
64
+ export interface MatchedRoute<TContext = any> {
65
+ route: Route<TContext>;
66
+ params: Record<string, string>;
67
+ }
68
+ export interface CorsOptions {
69
+ /** Allowed origins (string, array, or function) */
70
+ origin?: string | string[] | ((origin: string) => boolean);
71
+ /** Allowed methods */
72
+ methods?: HttpMethod[];
73
+ /** Allowed headers */
74
+ allowedHeaders?: string[];
75
+ /** Exposed headers */
76
+ exposedHeaders?: string[];
77
+ /** Allow credentials */
78
+ credentials?: boolean;
79
+ /** Max age for preflight cache */
80
+ maxAge?: number;
81
+ }
82
+ export interface CompiledRoute<TContext = any> {
83
+ route: Route<TContext>;
84
+ pattern: RegExp;
85
+ keys: string[];
86
+ }
87
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Core type definitions for the HTTP abstraction layer
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@superfunctions/http",
3
+ "version": "0.1.0",
4
+ "description": "Framework-agnostic HTTP abstraction layer for Superfunctions libraries",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ },
13
+ "./middleware": {
14
+ "types": "./dist/middleware/index.d.ts",
15
+ "default": "./dist/middleware/index.js"
16
+ },
17
+ "./types": {
18
+ "types": "./dist/types.d.ts"
19
+ }
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "scripts": {
25
+ "build": "tsc",
26
+ "test": "vitest",
27
+ "test:watch": "vitest --watch",
28
+ "lint": "echo 'lint not configured'",
29
+ "typecheck": "tsc --noEmit",
30
+ "clean": "rm -rf dist"
31
+ },
32
+ "keywords": [
33
+ "http",
34
+ "router",
35
+ "framework-agnostic",
36
+ "web-standard",
37
+ "express",
38
+ "hono",
39
+ "fastify",
40
+ "superfunctions"
41
+ ],
42
+ "author": "21n",
43
+ "license": "MIT",
44
+ "bugs": {
45
+ "url": "https://github.com/21nCo/super-functions/issues"
46
+ },
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "git+https://github.com/21nCo/super-functions.git",
50
+ "directory": "packages/http"
51
+ },
52
+ "publishConfig": {
53
+ "access": "public"
54
+ },
55
+ "devDependencies": {
56
+ "@types/node": "^22.0.0",
57
+ "typescript": "^5.6.0",
58
+ "vitest": "^3.2.4"
59
+ }
60
+ }