ai.matey.http.core 0.2.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/LICENSE +21 -0
- package/dist/cjs/auth.js +173 -0
- package/dist/cjs/auth.js.map +1 -0
- package/dist/cjs/cors.js +140 -0
- package/dist/cjs/cors.js.map +1 -0
- package/dist/cjs/error-handler.js +147 -0
- package/dist/cjs/error-handler.js.map +1 -0
- package/dist/cjs/handler.js +335 -0
- package/dist/cjs/handler.js.map +1 -0
- package/dist/cjs/health.js +218 -0
- package/dist/cjs/health.js.map +1 -0
- package/dist/cjs/index.js +83 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/rate-limiter.js +163 -0
- package/dist/cjs/rate-limiter.js.map +1 -0
- package/dist/cjs/request-parser.js +141 -0
- package/dist/cjs/request-parser.js.map +1 -0
- package/dist/cjs/response-formatter.js +218 -0
- package/dist/cjs/response-formatter.js.map +1 -0
- package/dist/cjs/route-matcher.js +178 -0
- package/dist/cjs/route-matcher.js.map +1 -0
- package/dist/cjs/streaming-handler.js +120 -0
- package/dist/cjs/streaming-handler.js.map +1 -0
- package/dist/cjs/types.js +11 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/esm/auth.js +163 -0
- package/dist/esm/auth.js.map +1 -0
- package/dist/esm/cors.js +134 -0
- package/dist/esm/cors.js.map +1 -0
- package/dist/esm/error-handler.js +137 -0
- package/dist/esm/error-handler.js.map +1 -0
- package/dist/esm/handler.js +331 -0
- package/dist/esm/handler.js.map +1 -0
- package/dist/esm/health.js +210 -0
- package/dist/esm/health.js.map +1 -0
- package/dist/esm/index.js +30 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/rate-limiter.js +156 -0
- package/dist/esm/rate-limiter.js.map +1 -0
- package/dist/esm/request-parser.js +136 -0
- package/dist/esm/request-parser.js.map +1 -0
- package/dist/esm/response-formatter.js +206 -0
- package/dist/esm/response-formatter.js.map +1 -0
- package/dist/esm/route-matcher.js +171 -0
- package/dist/esm/route-matcher.js.map +1 -0
- package/dist/esm/streaming-handler.js +112 -0
- package/dist/esm/streaming-handler.js.map +1 -0
- package/dist/esm/types.js +10 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/types/auth.d.ts +37 -0
- package/dist/types/auth.d.ts.map +1 -0
- package/dist/types/cors.d.ts +26 -0
- package/dist/types/cors.d.ts.map +1 -0
- package/dist/types/error-handler.d.ts +38 -0
- package/dist/types/error-handler.d.ts.map +1 -0
- package/dist/types/handler.d.ts +45 -0
- package/dist/types/handler.d.ts.map +1 -0
- package/dist/types/health.d.ts +164 -0
- package/dist/types/health.d.ts.map +1 -0
- package/dist/types/index.d.ts +21 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/rate-limiter.d.ts +56 -0
- package/dist/types/rate-limiter.d.ts.map +1 -0
- package/dist/types/request-parser.d.ts +22 -0
- package/dist/types/request-parser.d.ts.map +1 -0
- package/dist/types/response-formatter.d.ts +49 -0
- package/dist/types/response-formatter.d.ts.map +1 -0
- package/dist/types/route-matcher.d.ts +45 -0
- package/dist/types/route-matcher.d.ts.map +1 -0
- package/dist/types/streaming-handler.d.ts +40 -0
- package/dist/types/streaming-handler.d.ts.map +1 -0
- package/dist/types/types.d.ts +398 -0
- package/dist/types/types.d.ts.map +1 -0
- package/package.json +73 -0
- package/readme.md +60 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Route Matcher
|
|
4
|
+
*
|
|
5
|
+
* Matches incoming HTTP requests to configured routes.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.RouteMatcher = void 0;
|
|
11
|
+
exports.createDefaultRoutes = createDefaultRoutes;
|
|
12
|
+
exports.normalizePath = normalizePath;
|
|
13
|
+
exports.applyPathPrefix = applyPathPrefix;
|
|
14
|
+
/**
|
|
15
|
+
* Route matcher class
|
|
16
|
+
*/
|
|
17
|
+
class RouteMatcher {
|
|
18
|
+
routes;
|
|
19
|
+
constructor(routes) {
|
|
20
|
+
this.routes = routes;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Match request to a route
|
|
24
|
+
*/
|
|
25
|
+
match(req) {
|
|
26
|
+
const url = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);
|
|
27
|
+
const path = url.pathname;
|
|
28
|
+
const method = req.method?.toUpperCase() || 'GET';
|
|
29
|
+
for (const route of this.routes) {
|
|
30
|
+
// Check if method matches
|
|
31
|
+
const routeMethods = route.methods || ['POST'];
|
|
32
|
+
if (!routeMethods.includes(method)) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
// Check if path matches
|
|
36
|
+
const match = matchPath(path, route.path);
|
|
37
|
+
if (match) {
|
|
38
|
+
return {
|
|
39
|
+
config: route,
|
|
40
|
+
params: match.params,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Add a route
|
|
48
|
+
*/
|
|
49
|
+
addRoute(route) {
|
|
50
|
+
this.routes.push(route);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Remove a route
|
|
54
|
+
*/
|
|
55
|
+
removeRoute(path) {
|
|
56
|
+
const index = this.routes.findIndex((r) => r.path === path);
|
|
57
|
+
if (index >= 0) {
|
|
58
|
+
this.routes.splice(index, 1);
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get all routes
|
|
65
|
+
*/
|
|
66
|
+
getRoutes() {
|
|
67
|
+
return this.routes;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.RouteMatcher = RouteMatcher;
|
|
71
|
+
function matchPath(path, pattern) {
|
|
72
|
+
// Exact match
|
|
73
|
+
if (path === pattern) {
|
|
74
|
+
return { params: {} };
|
|
75
|
+
}
|
|
76
|
+
// Wildcard match (supports simple * wildcards)
|
|
77
|
+
if (pattern.includes('*')) {
|
|
78
|
+
const regex = patternToRegex(pattern);
|
|
79
|
+
if (regex.test(path)) {
|
|
80
|
+
return { params: {} };
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
// Parameter match (supports :param syntax)
|
|
85
|
+
if (pattern.includes(':')) {
|
|
86
|
+
const match = matchParameterizedPath(path, pattern);
|
|
87
|
+
if (match) {
|
|
88
|
+
return match;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Convert path pattern to regex
|
|
95
|
+
*/
|
|
96
|
+
function patternToRegex(pattern) {
|
|
97
|
+
// Escape special regex characters except *
|
|
98
|
+
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
|
|
99
|
+
// Convert * to regex wildcard
|
|
100
|
+
const regexPattern = escaped.replace(/\*/g, '.*');
|
|
101
|
+
return new RegExp(`^${regexPattern}$`);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Match parameterized path (e.g., /users/:id)
|
|
105
|
+
*/
|
|
106
|
+
function matchParameterizedPath(path, pattern) {
|
|
107
|
+
const pathParts = path.split('/').filter(Boolean);
|
|
108
|
+
const patternParts = pattern.split('/').filter(Boolean);
|
|
109
|
+
if (pathParts.length !== patternParts.length) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
const params = {};
|
|
113
|
+
for (let i = 0; i < patternParts.length; i++) {
|
|
114
|
+
const patternPart = patternParts[i];
|
|
115
|
+
const pathPart = pathParts[i];
|
|
116
|
+
if (!patternPart || !pathPart) {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
if (patternPart.startsWith(':')) {
|
|
120
|
+
// Parameter
|
|
121
|
+
const paramName = patternPart.slice(1);
|
|
122
|
+
params[paramName] = pathPart;
|
|
123
|
+
}
|
|
124
|
+
else if (patternPart !== pathPart) {
|
|
125
|
+
// Mismatch
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return { params };
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Create default routes for common provider endpoints
|
|
133
|
+
*/
|
|
134
|
+
function createDefaultRoutes(frontendAdapters) {
|
|
135
|
+
const routes = [];
|
|
136
|
+
// OpenAI endpoint
|
|
137
|
+
if (frontendAdapters.has('openai')) {
|
|
138
|
+
routes.push({
|
|
139
|
+
path: '/v1/chat/completions',
|
|
140
|
+
methods: ['POST'],
|
|
141
|
+
frontend: frontendAdapters.get('openai'),
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
// Anthropic endpoint
|
|
145
|
+
if (frontendAdapters.has('anthropic')) {
|
|
146
|
+
routes.push({
|
|
147
|
+
path: '/v1/messages',
|
|
148
|
+
methods: ['POST'],
|
|
149
|
+
frontend: frontendAdapters.get('anthropic'),
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
return routes;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Normalize path by removing trailing slashes and adding leading slash
|
|
156
|
+
*/
|
|
157
|
+
function normalizePath(path) {
|
|
158
|
+
// Add leading slash if missing
|
|
159
|
+
if (!path.startsWith('/')) {
|
|
160
|
+
path = '/' + path;
|
|
161
|
+
}
|
|
162
|
+
// Remove trailing slash (except for root)
|
|
163
|
+
if (path.length > 1 && path.endsWith('/')) {
|
|
164
|
+
path = path.slice(0, -1);
|
|
165
|
+
}
|
|
166
|
+
return path;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Apply path prefix to route paths
|
|
170
|
+
*/
|
|
171
|
+
function applyPathPrefix(routes, prefix) {
|
|
172
|
+
const normalizedPrefix = normalizePath(prefix);
|
|
173
|
+
return routes.map((route) => ({
|
|
174
|
+
...route,
|
|
175
|
+
path: normalizedPrefix + normalizePath(route.path),
|
|
176
|
+
}));
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=route-matcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"route-matcher.js","sourceRoot":"","sources":["../../src/route-matcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Streaming Handler
|
|
4
|
+
*
|
|
5
|
+
* Handles Server-Sent Events (SSE) streaming for HTTP responses.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.SSEKeepAlive = void 0;
|
|
11
|
+
exports.handleStreamingRequest = handleStreamingRequest;
|
|
12
|
+
exports.onClientDisconnect = onClientDisconnect;
|
|
13
|
+
exports.supportsStreaming = supportsStreaming;
|
|
14
|
+
exports.createAbortController = createAbortController;
|
|
15
|
+
const response_formatter_js_1 = require("./response-formatter.js");
|
|
16
|
+
/**
|
|
17
|
+
* Handle streaming request
|
|
18
|
+
*/
|
|
19
|
+
async function handleStreamingRequest(bridge, request, res, format = 'generic', headers = {}) {
|
|
20
|
+
// Send SSE headers
|
|
21
|
+
(0, response_formatter_js_1.sendSSEHeaders)(res, headers);
|
|
22
|
+
try {
|
|
23
|
+
// Get streaming response from bridge
|
|
24
|
+
const stream = bridge.chatStream(request);
|
|
25
|
+
// Stream chunks to client
|
|
26
|
+
for await (const chunk of stream) {
|
|
27
|
+
// Check if response is still writable
|
|
28
|
+
if (!res.writable) {
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
// Format and send chunk based on provider format
|
|
32
|
+
if (format === 'anthropic') {
|
|
33
|
+
// Anthropic uses named events
|
|
34
|
+
sendAnthropicChunk(res, chunk);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
// OpenAI and generic use data-only format
|
|
38
|
+
(0, response_formatter_js_1.sendSSEChunk)(res, chunk);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Send done marker (OpenAI style)
|
|
42
|
+
if (format === 'openai' || format === 'generic') {
|
|
43
|
+
(0, response_formatter_js_1.sendSSEDone)(res);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
// Anthropic doesn't use [DONE] marker, just end the stream
|
|
47
|
+
res.end();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
// Send error in stream
|
|
52
|
+
(0, response_formatter_js_1.sendSSEError)(res, error instanceof Error ? error : new Error(String(error)), format);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Send Anthropic-formatted SSE chunk
|
|
57
|
+
*/
|
|
58
|
+
function sendAnthropicChunk(res, chunk) {
|
|
59
|
+
// Anthropic uses event types
|
|
60
|
+
if (chunk.type) {
|
|
61
|
+
(0, response_formatter_js_1.sendSSEEvent)(res, chunk.type, chunk);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
(0, response_formatter_js_1.sendSSEChunk)(res, chunk);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Create SSE keep-alive mechanism
|
|
69
|
+
*/
|
|
70
|
+
class SSEKeepAlive {
|
|
71
|
+
intervalId = null;
|
|
72
|
+
/**
|
|
73
|
+
* Start sending keep-alive pings
|
|
74
|
+
*/
|
|
75
|
+
start(res, intervalMs = 15000) {
|
|
76
|
+
this.intervalId = setInterval(() => {
|
|
77
|
+
if (res.writable) {
|
|
78
|
+
res.write(': ping\n\n');
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
this.stop();
|
|
82
|
+
}
|
|
83
|
+
}, intervalMs);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Stop sending keep-alive pings
|
|
87
|
+
*/
|
|
88
|
+
stop() {
|
|
89
|
+
if (this.intervalId) {
|
|
90
|
+
clearInterval(this.intervalId);
|
|
91
|
+
this.intervalId = null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.SSEKeepAlive = SSEKeepAlive;
|
|
96
|
+
/**
|
|
97
|
+
* Handle client disconnect
|
|
98
|
+
*/
|
|
99
|
+
function onClientDisconnect(res, callback) {
|
|
100
|
+
res.on('close', callback);
|
|
101
|
+
res.on('finish', callback);
|
|
102
|
+
res.on('error', callback);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Check if response supports streaming
|
|
106
|
+
*/
|
|
107
|
+
function supportsStreaming(res) {
|
|
108
|
+
return typeof res.flushHeaders === 'function';
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Create streaming abort controller from response
|
|
112
|
+
*/
|
|
113
|
+
function createAbortController(res) {
|
|
114
|
+
const controller = new AbortController();
|
|
115
|
+
onClientDisconnect(res, () => {
|
|
116
|
+
controller.abort();
|
|
117
|
+
});
|
|
118
|
+
return controller;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=streaming-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streaming-handler.js","sourceRoot":"","sources":["../../src/streaming-handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* HTTP Core Types
|
|
4
|
+
*
|
|
5
|
+
* Unified type definitions for the HTTP adapter system.
|
|
6
|
+
* These types allow us to write core logic once and adapt it to any framework.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG"}
|
package/dist/esm/auth.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication Handler
|
|
3
|
+
*
|
|
4
|
+
* Handles authentication validation for HTTP requests.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
import { timingSafeEqual } from 'crypto';
|
|
9
|
+
import { extractBearerToken } from './request-parser.js';
|
|
10
|
+
/**
|
|
11
|
+
* Timing-safe string comparison to prevent timing attacks.
|
|
12
|
+
* Returns false if strings have different lengths (without revealing length via timing).
|
|
13
|
+
*/
|
|
14
|
+
function safeCompare(a, b) {
|
|
15
|
+
const bufA = Buffer.from(a);
|
|
16
|
+
const bufB = Buffer.from(b);
|
|
17
|
+
// If lengths differ, still do a comparison to prevent timing leaks
|
|
18
|
+
if (bufA.length !== bufB.length) {
|
|
19
|
+
// Compare against itself to maintain constant time
|
|
20
|
+
timingSafeEqual(bufA, bufA);
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
return timingSafeEqual(bufA, bufB);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Default auth validator (always allows)
|
|
27
|
+
*/
|
|
28
|
+
export const defaultAuthValidator = () => true;
|
|
29
|
+
/**
|
|
30
|
+
* Create bearer token validator
|
|
31
|
+
*/
|
|
32
|
+
export function createBearerTokenValidator(validTokens) {
|
|
33
|
+
return async (req) => {
|
|
34
|
+
const token = extractBearerToken(req);
|
|
35
|
+
if (!token) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
if (typeof validTokens === 'function') {
|
|
39
|
+
return await validTokens(token);
|
|
40
|
+
}
|
|
41
|
+
if (validTokens instanceof Set) {
|
|
42
|
+
// Use timing-safe comparison for each token
|
|
43
|
+
for (const validToken of validTokens) {
|
|
44
|
+
if (safeCompare(validToken, token)) {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
// Use timing-safe comparison for array
|
|
51
|
+
for (const validToken of validTokens) {
|
|
52
|
+
if (safeCompare(validToken, token)) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Create API key validator (checks x-api-key header)
|
|
61
|
+
*/
|
|
62
|
+
export function createAPIKeyValidator(validKeys) {
|
|
63
|
+
return async (req) => {
|
|
64
|
+
const apiKey = req.headers['x-api-key'];
|
|
65
|
+
if (!apiKey) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
if (typeof validKeys === 'function') {
|
|
69
|
+
return await validKeys(apiKey);
|
|
70
|
+
}
|
|
71
|
+
if (validKeys instanceof Set) {
|
|
72
|
+
// Use timing-safe comparison for each key
|
|
73
|
+
for (const validKey of validKeys) {
|
|
74
|
+
if (safeCompare(validKey, apiKey)) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
// Use timing-safe comparison for array
|
|
81
|
+
for (const validKey of validKeys) {
|
|
82
|
+
if (safeCompare(validKey, apiKey)) {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Create basic auth validator
|
|
91
|
+
*/
|
|
92
|
+
export function createBasicAuthValidator(credentials) {
|
|
93
|
+
return async (req) => {
|
|
94
|
+
const auth = req.headers.authorization;
|
|
95
|
+
if (!auth?.startsWith('Basic ')) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
const encoded = auth.slice(6);
|
|
100
|
+
const decoded = Buffer.from(encoded, 'base64').toString('utf-8');
|
|
101
|
+
const [username, password] = decoded.split(':');
|
|
102
|
+
if (!username || !password) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
if (typeof credentials === 'function') {
|
|
106
|
+
return await credentials(username, password);
|
|
107
|
+
}
|
|
108
|
+
const storedPassword = credentials.get(username);
|
|
109
|
+
if (!storedPassword) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
return safeCompare(storedPassword, password);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Combine multiple auth validators (OR logic)
|
|
121
|
+
*/
|
|
122
|
+
export function combineAuthValidators(...validators) {
|
|
123
|
+
return async (req) => {
|
|
124
|
+
for (const validator of validators) {
|
|
125
|
+
if (await validator(req)) {
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return false;
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Require all auth validators to pass (AND logic)
|
|
134
|
+
*/
|
|
135
|
+
export function requireAllAuth(...validators) {
|
|
136
|
+
return async (req) => {
|
|
137
|
+
for (const validator of validators) {
|
|
138
|
+
if (!(await validator(req))) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return true;
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Skip auth for certain paths
|
|
147
|
+
*/
|
|
148
|
+
export function skipAuthForPaths(validator, paths) {
|
|
149
|
+
return async (req) => {
|
|
150
|
+
const url = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);
|
|
151
|
+
const path = url.pathname;
|
|
152
|
+
if (typeof paths === 'function') {
|
|
153
|
+
if (paths(path)) {
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
else if (paths.includes(path)) {
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
return await validator(req);
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAEzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD;;;GAGG;AACH,SAAS,WAAW,CAAC,CAAS,EAAE,CAAS;IACvC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC5B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAE5B,mEAAmE;IACnE,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;QAChC,mDAAmD;QACnD,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC5B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAkB,GAAG,EAAE,CAAC,IAAI,CAAC;AAE9D;;GAEG;AACH,MAAM,UAAU,0BAA0B,CACxC,WAAqF;IAErF,OAAO,KAAK,EAAE,GAAoB,EAAoB,EAAE;QACtD,MAAM,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;QAEtC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,OAAO,WAAW,KAAK,UAAU,EAAE,CAAC;YACtC,OAAO,MAAM,WAAW,CAAC,KAAK,CAAC,CAAC;QAClC,CAAC;QAED,IAAI,WAAW,YAAY,GAAG,EAAE,CAAC;YAC/B,4CAA4C;YAC5C,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;gBACrC,IAAI,WAAW,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC;oBACnC,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,uCAAuC;QACvC,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACrC,IAAI,WAAW,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC;gBACnC,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CACnC,SAAiF;IAEjF,OAAO,KAAK,EAAE,GAAoB,EAAoB,EAAE;QACtD,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAW,CAAC;QAElD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,OAAO,SAAS,KAAK,UAAU,EAAE,CAAC;YACpC,OAAO,MAAM,SAAS,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QAED,IAAI,SAAS,YAAY,GAAG,EAAE,CAAC;YAC7B,0CAA0C;YAC1C,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBACjC,IAAI,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;oBAClC,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,uCAAuC;QACvC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,IAAI,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;gBAClC,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB,CACtC,WAEwE;IAExE,OAAO,KAAK,EAAE,GAAoB,EAAoB,EAAE;QACtD,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;QAEvC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACjE,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAEhD,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAC3B,OAAO,KAAK,CAAC;YACf,CAAC;YAED,IAAI,OAAO,WAAW,KAAK,UAAU,EAAE,CAAC;gBACtC,OAAO,MAAM,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAC/C,CAAC;YAED,MAAM,cAAc,GAAG,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACjD,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,OAAO,KAAK,CAAC;YACf,CAAC;YACD,OAAO,WAAW,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAG,UAA2B;IAClE,OAAO,KAAK,EAAE,GAAoB,EAAoB,EAAE;QACtD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,IAAI,MAAM,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;gBACzB,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,GAAG,UAA2B;IAC3D,OAAO,KAAK,EAAE,GAAoB,EAAoB,EAAE;QACtD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,IAAI,CAAC,CAAC,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;gBAC5B,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC9B,SAAwB,EACxB,KAA6C;IAE7C,OAAO,KAAK,EAAE,GAAoB,EAAoB,EAAE;QACtD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,UAAU,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,WAAW,EAAE,CAAC,CAAC;QACjF,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC;QAE1B,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;YAChC,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChB,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;aAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/esm/cors.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CORS Handler
|
|
3
|
+
*
|
|
4
|
+
* Handles Cross-Origin Resource Sharing (CORS) for HTTP requests.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Default CORS options
|
|
10
|
+
*/
|
|
11
|
+
const DEFAULT_CORS_OPTIONS = {
|
|
12
|
+
origin: '*',
|
|
13
|
+
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
|
|
14
|
+
allowedHeaders: ['Content-Type', 'Authorization'],
|
|
15
|
+
exposedHeaders: [],
|
|
16
|
+
credentials: true,
|
|
17
|
+
maxAge: 86400, // 24 hours
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Normalize CORS options
|
|
21
|
+
*/
|
|
22
|
+
export function normalizeCORSOptions(options) {
|
|
23
|
+
if (options === false) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
if (options === true || options === undefined) {
|
|
27
|
+
return DEFAULT_CORS_OPTIONS;
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
origin: options.origin ?? DEFAULT_CORS_OPTIONS.origin,
|
|
31
|
+
methods: options.methods ?? DEFAULT_CORS_OPTIONS.methods,
|
|
32
|
+
allowedHeaders: options.allowedHeaders ?? DEFAULT_CORS_OPTIONS.allowedHeaders,
|
|
33
|
+
exposedHeaders: options.exposedHeaders ?? DEFAULT_CORS_OPTIONS.exposedHeaders,
|
|
34
|
+
credentials: options.credentials ?? DEFAULT_CORS_OPTIONS.credentials,
|
|
35
|
+
maxAge: options.maxAge ?? DEFAULT_CORS_OPTIONS.maxAge,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Handle CORS headers
|
|
40
|
+
*/
|
|
41
|
+
export function handleCORS(req, res, options) {
|
|
42
|
+
const origin = req.headers.origin || '';
|
|
43
|
+
// Check if origin is allowed
|
|
44
|
+
if (!isOriginAllowed(origin, options.origin)) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
// Set Access-Control-Allow-Origin
|
|
48
|
+
if (typeof options.origin === 'string' && options.origin === '*') {
|
|
49
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
res.setHeader('Access-Control-Allow-Origin', origin);
|
|
53
|
+
res.setHeader('Vary', 'Origin');
|
|
54
|
+
}
|
|
55
|
+
// Set Access-Control-Allow-Credentials
|
|
56
|
+
if (options.credentials) {
|
|
57
|
+
res.setHeader('Access-Control-Allow-Credentials', 'true');
|
|
58
|
+
}
|
|
59
|
+
// Set Access-Control-Expose-Headers
|
|
60
|
+
if (options.exposedHeaders.length > 0) {
|
|
61
|
+
res.setHeader('Access-Control-Expose-Headers', Array.isArray(options.exposedHeaders)
|
|
62
|
+
? options.exposedHeaders.join(', ')
|
|
63
|
+
: options.exposedHeaders);
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Handle CORS preflight (OPTIONS) request
|
|
69
|
+
*/
|
|
70
|
+
export function handlePreflight(req, res, options) {
|
|
71
|
+
const origin = req.headers.origin || '';
|
|
72
|
+
// Check if origin is allowed
|
|
73
|
+
if (!isOriginAllowed(origin, options.origin)) {
|
|
74
|
+
res.statusCode = 403;
|
|
75
|
+
res.end('Origin not allowed');
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
// Set Access-Control-Allow-Origin
|
|
79
|
+
if (typeof options.origin === 'string' && options.origin === '*') {
|
|
80
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
res.setHeader('Access-Control-Allow-Origin', origin);
|
|
84
|
+
res.setHeader('Vary', 'Origin');
|
|
85
|
+
}
|
|
86
|
+
// Set Access-Control-Allow-Methods
|
|
87
|
+
res.setHeader('Access-Control-Allow-Methods', Array.isArray(options.methods) ? options.methods.join(', ') : options.methods);
|
|
88
|
+
// Set Access-Control-Allow-Headers
|
|
89
|
+
const requestHeaders = req.headers['access-control-request-headers'];
|
|
90
|
+
if (requestHeaders) {
|
|
91
|
+
res.setHeader('Access-Control-Allow-Headers', requestHeaders);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
res.setHeader('Access-Control-Allow-Headers', Array.isArray(options.allowedHeaders)
|
|
95
|
+
? options.allowedHeaders.join(', ')
|
|
96
|
+
: options.allowedHeaders);
|
|
97
|
+
}
|
|
98
|
+
// Set Access-Control-Allow-Credentials
|
|
99
|
+
if (options.credentials) {
|
|
100
|
+
res.setHeader('Access-Control-Allow-Credentials', 'true');
|
|
101
|
+
}
|
|
102
|
+
// Set Access-Control-Max-Age
|
|
103
|
+
res.setHeader('Access-Control-Max-Age', String(options.maxAge));
|
|
104
|
+
// Send successful preflight response
|
|
105
|
+
res.statusCode = 204;
|
|
106
|
+
res.end();
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Check if origin is allowed
|
|
110
|
+
*/
|
|
111
|
+
function isOriginAllowed(origin, allowedOrigin) {
|
|
112
|
+
if (!origin) {
|
|
113
|
+
return true; // Allow requests without origin header
|
|
114
|
+
}
|
|
115
|
+
if (typeof allowedOrigin === 'string') {
|
|
116
|
+
return allowedOrigin === '*' || allowedOrigin === origin;
|
|
117
|
+
}
|
|
118
|
+
if (Array.isArray(allowedOrigin)) {
|
|
119
|
+
return allowedOrigin.includes(origin) || allowedOrigin.includes('*');
|
|
120
|
+
}
|
|
121
|
+
if (typeof allowedOrigin === 'function') {
|
|
122
|
+
return allowedOrigin(origin);
|
|
123
|
+
}
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Check if request is a CORS preflight request
|
|
128
|
+
*/
|
|
129
|
+
export function isPreflight(req) {
|
|
130
|
+
return (req.method === 'OPTIONS' &&
|
|
131
|
+
!!req.headers.origin &&
|
|
132
|
+
!!req.headers['access-control-request-method']);
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=cors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cors.js","sourceRoot":"","sources":["../../src/cors.ts"],"names":[],"mappings":"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"}
|