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.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cjs/auth.js +173 -0
  3. package/dist/cjs/auth.js.map +1 -0
  4. package/dist/cjs/cors.js +140 -0
  5. package/dist/cjs/cors.js.map +1 -0
  6. package/dist/cjs/error-handler.js +147 -0
  7. package/dist/cjs/error-handler.js.map +1 -0
  8. package/dist/cjs/handler.js +335 -0
  9. package/dist/cjs/handler.js.map +1 -0
  10. package/dist/cjs/health.js +218 -0
  11. package/dist/cjs/health.js.map +1 -0
  12. package/dist/cjs/index.js +83 -0
  13. package/dist/cjs/index.js.map +1 -0
  14. package/dist/cjs/rate-limiter.js +163 -0
  15. package/dist/cjs/rate-limiter.js.map +1 -0
  16. package/dist/cjs/request-parser.js +141 -0
  17. package/dist/cjs/request-parser.js.map +1 -0
  18. package/dist/cjs/response-formatter.js +218 -0
  19. package/dist/cjs/response-formatter.js.map +1 -0
  20. package/dist/cjs/route-matcher.js +178 -0
  21. package/dist/cjs/route-matcher.js.map +1 -0
  22. package/dist/cjs/streaming-handler.js +120 -0
  23. package/dist/cjs/streaming-handler.js.map +1 -0
  24. package/dist/cjs/types.js +11 -0
  25. package/dist/cjs/types.js.map +1 -0
  26. package/dist/esm/auth.js +163 -0
  27. package/dist/esm/auth.js.map +1 -0
  28. package/dist/esm/cors.js +134 -0
  29. package/dist/esm/cors.js.map +1 -0
  30. package/dist/esm/error-handler.js +137 -0
  31. package/dist/esm/error-handler.js.map +1 -0
  32. package/dist/esm/handler.js +331 -0
  33. package/dist/esm/handler.js.map +1 -0
  34. package/dist/esm/health.js +210 -0
  35. package/dist/esm/health.js.map +1 -0
  36. package/dist/esm/index.js +30 -0
  37. package/dist/esm/index.js.map +1 -0
  38. package/dist/esm/rate-limiter.js +156 -0
  39. package/dist/esm/rate-limiter.js.map +1 -0
  40. package/dist/esm/request-parser.js +136 -0
  41. package/dist/esm/request-parser.js.map +1 -0
  42. package/dist/esm/response-formatter.js +206 -0
  43. package/dist/esm/response-formatter.js.map +1 -0
  44. package/dist/esm/route-matcher.js +171 -0
  45. package/dist/esm/route-matcher.js.map +1 -0
  46. package/dist/esm/streaming-handler.js +112 -0
  47. package/dist/esm/streaming-handler.js.map +1 -0
  48. package/dist/esm/types.js +10 -0
  49. package/dist/esm/types.js.map +1 -0
  50. package/dist/types/auth.d.ts +37 -0
  51. package/dist/types/auth.d.ts.map +1 -0
  52. package/dist/types/cors.d.ts +26 -0
  53. package/dist/types/cors.d.ts.map +1 -0
  54. package/dist/types/error-handler.d.ts +38 -0
  55. package/dist/types/error-handler.d.ts.map +1 -0
  56. package/dist/types/handler.d.ts +45 -0
  57. package/dist/types/handler.d.ts.map +1 -0
  58. package/dist/types/health.d.ts +164 -0
  59. package/dist/types/health.d.ts.map +1 -0
  60. package/dist/types/index.d.ts +21 -0
  61. package/dist/types/index.d.ts.map +1 -0
  62. package/dist/types/rate-limiter.d.ts +56 -0
  63. package/dist/types/rate-limiter.d.ts.map +1 -0
  64. package/dist/types/request-parser.d.ts +22 -0
  65. package/dist/types/request-parser.d.ts.map +1 -0
  66. package/dist/types/response-formatter.d.ts +49 -0
  67. package/dist/types/response-formatter.d.ts.map +1 -0
  68. package/dist/types/route-matcher.d.ts +45 -0
  69. package/dist/types/route-matcher.d.ts.map +1 -0
  70. package/dist/types/streaming-handler.d.ts +40 -0
  71. package/dist/types/streaming-handler.d.ts.map +1 -0
  72. package/dist/types/types.d.ts +398 -0
  73. package/dist/types/types.d.ts.map +1 -0
  74. package/package.json +73 -0
  75. package/readme.md +60 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 AI Matey Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+ /**
3
+ * Authentication Handler
4
+ *
5
+ * Handles authentication validation for HTTP requests.
6
+ *
7
+ * @module
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.defaultAuthValidator = void 0;
11
+ exports.createBearerTokenValidator = createBearerTokenValidator;
12
+ exports.createAPIKeyValidator = createAPIKeyValidator;
13
+ exports.createBasicAuthValidator = createBasicAuthValidator;
14
+ exports.combineAuthValidators = combineAuthValidators;
15
+ exports.requireAllAuth = requireAllAuth;
16
+ exports.skipAuthForPaths = skipAuthForPaths;
17
+ const crypto_1 = require("crypto");
18
+ const request_parser_js_1 = require("./request-parser.js");
19
+ /**
20
+ * Timing-safe string comparison to prevent timing attacks.
21
+ * Returns false if strings have different lengths (without revealing length via timing).
22
+ */
23
+ function safeCompare(a, b) {
24
+ const bufA = Buffer.from(a);
25
+ const bufB = Buffer.from(b);
26
+ // If lengths differ, still do a comparison to prevent timing leaks
27
+ if (bufA.length !== bufB.length) {
28
+ // Compare against itself to maintain constant time
29
+ (0, crypto_1.timingSafeEqual)(bufA, bufA);
30
+ return false;
31
+ }
32
+ return (0, crypto_1.timingSafeEqual)(bufA, bufB);
33
+ }
34
+ /**
35
+ * Default auth validator (always allows)
36
+ */
37
+ const defaultAuthValidator = () => true;
38
+ exports.defaultAuthValidator = defaultAuthValidator;
39
+ /**
40
+ * Create bearer token validator
41
+ */
42
+ function createBearerTokenValidator(validTokens) {
43
+ return async (req) => {
44
+ const token = (0, request_parser_js_1.extractBearerToken)(req);
45
+ if (!token) {
46
+ return false;
47
+ }
48
+ if (typeof validTokens === 'function') {
49
+ return await validTokens(token);
50
+ }
51
+ if (validTokens instanceof Set) {
52
+ // Use timing-safe comparison for each token
53
+ for (const validToken of validTokens) {
54
+ if (safeCompare(validToken, token)) {
55
+ return true;
56
+ }
57
+ }
58
+ return false;
59
+ }
60
+ // Use timing-safe comparison for array
61
+ for (const validToken of validTokens) {
62
+ if (safeCompare(validToken, token)) {
63
+ return true;
64
+ }
65
+ }
66
+ return false;
67
+ };
68
+ }
69
+ /**
70
+ * Create API key validator (checks x-api-key header)
71
+ */
72
+ function createAPIKeyValidator(validKeys) {
73
+ return async (req) => {
74
+ const apiKey = req.headers['x-api-key'];
75
+ if (!apiKey) {
76
+ return false;
77
+ }
78
+ if (typeof validKeys === 'function') {
79
+ return await validKeys(apiKey);
80
+ }
81
+ if (validKeys instanceof Set) {
82
+ // Use timing-safe comparison for each key
83
+ for (const validKey of validKeys) {
84
+ if (safeCompare(validKey, apiKey)) {
85
+ return true;
86
+ }
87
+ }
88
+ return false;
89
+ }
90
+ // Use timing-safe comparison for array
91
+ for (const validKey of validKeys) {
92
+ if (safeCompare(validKey, apiKey)) {
93
+ return true;
94
+ }
95
+ }
96
+ return false;
97
+ };
98
+ }
99
+ /**
100
+ * Create basic auth validator
101
+ */
102
+ function createBasicAuthValidator(credentials) {
103
+ return async (req) => {
104
+ const auth = req.headers.authorization;
105
+ if (!auth?.startsWith('Basic ')) {
106
+ return false;
107
+ }
108
+ try {
109
+ const encoded = auth.slice(6);
110
+ const decoded = Buffer.from(encoded, 'base64').toString('utf-8');
111
+ const [username, password] = decoded.split(':');
112
+ if (!username || !password) {
113
+ return false;
114
+ }
115
+ if (typeof credentials === 'function') {
116
+ return await credentials(username, password);
117
+ }
118
+ const storedPassword = credentials.get(username);
119
+ if (!storedPassword) {
120
+ return false;
121
+ }
122
+ return safeCompare(storedPassword, password);
123
+ }
124
+ catch {
125
+ return false;
126
+ }
127
+ };
128
+ }
129
+ /**
130
+ * Combine multiple auth validators (OR logic)
131
+ */
132
+ function combineAuthValidators(...validators) {
133
+ return async (req) => {
134
+ for (const validator of validators) {
135
+ if (await validator(req)) {
136
+ return true;
137
+ }
138
+ }
139
+ return false;
140
+ };
141
+ }
142
+ /**
143
+ * Require all auth validators to pass (AND logic)
144
+ */
145
+ function requireAllAuth(...validators) {
146
+ return async (req) => {
147
+ for (const validator of validators) {
148
+ if (!(await validator(req))) {
149
+ return false;
150
+ }
151
+ }
152
+ return true;
153
+ };
154
+ }
155
+ /**
156
+ * Skip auth for certain paths
157
+ */
158
+ function skipAuthForPaths(validator, paths) {
159
+ return async (req) => {
160
+ const url = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);
161
+ const path = url.pathname;
162
+ if (typeof paths === 'function') {
163
+ if (paths(path)) {
164
+ return true;
165
+ }
166
+ }
167
+ else if (paths.includes(path)) {
168
+ return true;
169
+ }
170
+ return await validator(req);
171
+ };
172
+ }
173
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/auth.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAiCH,gEAgCC;AAKD,sDAgCC;AAKD,4DAkCC;AAKD,sDASC;AAKD,wCASC;AAKD,4CAkBC;AA7LD,mCAAyC;AAEzC,2DAAyD;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,IAAA,wBAAe,EAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC5B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAA,wBAAe,EAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACI,MAAM,oBAAoB,GAAkB,GAAG,EAAE,CAAC,IAAI,CAAC;AAAjD,QAAA,oBAAoB,wBAA6B;AAE9D;;GAEG;AACH,SAAgB,0BAA0B,CACxC,WAAqF;IAErF,OAAO,KAAK,EAAE,GAAoB,EAAoB,EAAE;QACtD,MAAM,KAAK,GAAG,IAAA,sCAAkB,EAAC,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,SAAgB,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,SAAgB,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,SAAgB,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,SAAgB,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,SAAgB,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"}
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ /**
3
+ * CORS Handler
4
+ *
5
+ * Handles Cross-Origin Resource Sharing (CORS) for HTTP requests.
6
+ *
7
+ * @module
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.normalizeCORSOptions = normalizeCORSOptions;
11
+ exports.handleCORS = handleCORS;
12
+ exports.handlePreflight = handlePreflight;
13
+ exports.isPreflight = isPreflight;
14
+ /**
15
+ * Default CORS options
16
+ */
17
+ const DEFAULT_CORS_OPTIONS = {
18
+ origin: '*',
19
+ methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
20
+ allowedHeaders: ['Content-Type', 'Authorization'],
21
+ exposedHeaders: [],
22
+ credentials: true,
23
+ maxAge: 86400, // 24 hours
24
+ };
25
+ /**
26
+ * Normalize CORS options
27
+ */
28
+ function normalizeCORSOptions(options) {
29
+ if (options === false) {
30
+ return null;
31
+ }
32
+ if (options === true || options === undefined) {
33
+ return DEFAULT_CORS_OPTIONS;
34
+ }
35
+ return {
36
+ origin: options.origin ?? DEFAULT_CORS_OPTIONS.origin,
37
+ methods: options.methods ?? DEFAULT_CORS_OPTIONS.methods,
38
+ allowedHeaders: options.allowedHeaders ?? DEFAULT_CORS_OPTIONS.allowedHeaders,
39
+ exposedHeaders: options.exposedHeaders ?? DEFAULT_CORS_OPTIONS.exposedHeaders,
40
+ credentials: options.credentials ?? DEFAULT_CORS_OPTIONS.credentials,
41
+ maxAge: options.maxAge ?? DEFAULT_CORS_OPTIONS.maxAge,
42
+ };
43
+ }
44
+ /**
45
+ * Handle CORS headers
46
+ */
47
+ function handleCORS(req, res, options) {
48
+ const origin = req.headers.origin || '';
49
+ // Check if origin is allowed
50
+ if (!isOriginAllowed(origin, options.origin)) {
51
+ return false;
52
+ }
53
+ // Set Access-Control-Allow-Origin
54
+ if (typeof options.origin === 'string' && options.origin === '*') {
55
+ res.setHeader('Access-Control-Allow-Origin', '*');
56
+ }
57
+ else {
58
+ res.setHeader('Access-Control-Allow-Origin', origin);
59
+ res.setHeader('Vary', 'Origin');
60
+ }
61
+ // Set Access-Control-Allow-Credentials
62
+ if (options.credentials) {
63
+ res.setHeader('Access-Control-Allow-Credentials', 'true');
64
+ }
65
+ // Set Access-Control-Expose-Headers
66
+ if (options.exposedHeaders.length > 0) {
67
+ res.setHeader('Access-Control-Expose-Headers', Array.isArray(options.exposedHeaders)
68
+ ? options.exposedHeaders.join(', ')
69
+ : options.exposedHeaders);
70
+ }
71
+ return true;
72
+ }
73
+ /**
74
+ * Handle CORS preflight (OPTIONS) request
75
+ */
76
+ function handlePreflight(req, res, options) {
77
+ const origin = req.headers.origin || '';
78
+ // Check if origin is allowed
79
+ if (!isOriginAllowed(origin, options.origin)) {
80
+ res.statusCode = 403;
81
+ res.end('Origin not allowed');
82
+ return;
83
+ }
84
+ // Set Access-Control-Allow-Origin
85
+ if (typeof options.origin === 'string' && options.origin === '*') {
86
+ res.setHeader('Access-Control-Allow-Origin', '*');
87
+ }
88
+ else {
89
+ res.setHeader('Access-Control-Allow-Origin', origin);
90
+ res.setHeader('Vary', 'Origin');
91
+ }
92
+ // Set Access-Control-Allow-Methods
93
+ res.setHeader('Access-Control-Allow-Methods', Array.isArray(options.methods) ? options.methods.join(', ') : options.methods);
94
+ // Set Access-Control-Allow-Headers
95
+ const requestHeaders = req.headers['access-control-request-headers'];
96
+ if (requestHeaders) {
97
+ res.setHeader('Access-Control-Allow-Headers', requestHeaders);
98
+ }
99
+ else {
100
+ res.setHeader('Access-Control-Allow-Headers', Array.isArray(options.allowedHeaders)
101
+ ? options.allowedHeaders.join(', ')
102
+ : options.allowedHeaders);
103
+ }
104
+ // Set Access-Control-Allow-Credentials
105
+ if (options.credentials) {
106
+ res.setHeader('Access-Control-Allow-Credentials', 'true');
107
+ }
108
+ // Set Access-Control-Max-Age
109
+ res.setHeader('Access-Control-Max-Age', String(options.maxAge));
110
+ // Send successful preflight response
111
+ res.statusCode = 204;
112
+ res.end();
113
+ }
114
+ /**
115
+ * Check if origin is allowed
116
+ */
117
+ function isOriginAllowed(origin, allowedOrigin) {
118
+ if (!origin) {
119
+ return true; // Allow requests without origin header
120
+ }
121
+ if (typeof allowedOrigin === 'string') {
122
+ return allowedOrigin === '*' || allowedOrigin === origin;
123
+ }
124
+ if (Array.isArray(allowedOrigin)) {
125
+ return allowedOrigin.includes(origin) || allowedOrigin.includes('*');
126
+ }
127
+ if (typeof allowedOrigin === 'function') {
128
+ return allowedOrigin(origin);
129
+ }
130
+ return false;
131
+ }
132
+ /**
133
+ * Check if request is a CORS preflight request
134
+ */
135
+ function isPreflight(req) {
136
+ return (req.method === 'OPTIONS' &&
137
+ !!req.headers.origin &&
138
+ !!req.headers['access-control-request-method']);
139
+ }
140
+ //# sourceMappingURL=cors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cors.js","sourceRoot":"","sources":["../../src/cors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ /**
3
+ * Error Handler
4
+ *
5
+ * Handles errors in HTTP requests and formats appropriate responses.
6
+ *
7
+ * @module
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.defaultErrorHandler = void 0;
11
+ exports.createLoggingErrorHandler = createLoggingErrorHandler;
12
+ exports.createReportingErrorHandler = createReportingErrorHandler;
13
+ exports.wrapErrorHandler = wrapErrorHandler;
14
+ exports.isRetryableError = isRetryableError;
15
+ exports.isClientError = isClientError;
16
+ exports.isServerError = isServerError;
17
+ const response_formatter_js_1 = require("./response-formatter.js");
18
+ const ai_matey_errors_1 = require("ai.matey.errors");
19
+ /**
20
+ * Default error handler
21
+ */
22
+ const defaultErrorHandler = (error, req, res) => {
23
+ // Detect provider format from request
24
+ const format = (0, response_formatter_js_1.detectProviderFormat)(req.url || '');
25
+ // Map error to HTTP status code
26
+ const statusCode = getHTTPStatusCode(error);
27
+ // Log error (in production, this should go to a proper logger)
28
+ if (statusCode >= 500) {
29
+ console.error('HTTP Server Error:', error);
30
+ }
31
+ // Send error response
32
+ (0, response_formatter_js_1.sendError)(res, error, statusCode, format);
33
+ return Promise.resolve();
34
+ };
35
+ exports.defaultErrorHandler = defaultErrorHandler;
36
+ /**
37
+ * Get HTTP status code from error
38
+ */
39
+ function getHTTPStatusCode(error) {
40
+ // Check for adapter errors
41
+ if (error instanceof ai_matey_errors_1.ValidationError) {
42
+ return 400;
43
+ }
44
+ if (error instanceof ai_matey_errors_1.AuthenticationError) {
45
+ return 401;
46
+ }
47
+ if (error instanceof ai_matey_errors_1.RateLimitError) {
48
+ return 429;
49
+ }
50
+ if (error instanceof ai_matey_errors_1.NetworkError) {
51
+ return 502;
52
+ }
53
+ if (error instanceof ai_matey_errors_1.ProviderError) {
54
+ return 503;
55
+ }
56
+ if (error instanceof ai_matey_errors_1.StreamError) {
57
+ return 500;
58
+ }
59
+ if (error instanceof ai_matey_errors_1.AdapterError) {
60
+ return 500;
61
+ }
62
+ // Check for common error patterns in message
63
+ const message = error.message.toLowerCase();
64
+ if (message.includes('invalid') || message.includes('malformed')) {
65
+ return 400;
66
+ }
67
+ if (message.includes('unauthorized') || message.includes('authentication')) {
68
+ return 401;
69
+ }
70
+ if (message.includes('forbidden') || message.includes('permission')) {
71
+ return 403;
72
+ }
73
+ if (message.includes('not found')) {
74
+ return 404;
75
+ }
76
+ if (message.includes('timeout')) {
77
+ return 504;
78
+ }
79
+ if (message.includes('too large')) {
80
+ return 413;
81
+ }
82
+ // Default to 500
83
+ return 500;
84
+ }
85
+ /**
86
+ * Create error handler that logs to a custom logger
87
+ */
88
+ function createLoggingErrorHandler(log) {
89
+ return async (error, req, res) => {
90
+ log(`HTTP Error: ${req.method} ${req.url}`, error);
91
+ await (0, exports.defaultErrorHandler)(error, req, res);
92
+ };
93
+ }
94
+ /**
95
+ * Create error handler that reports errors to an external service
96
+ */
97
+ function createReportingErrorHandler(reporter) {
98
+ return async (error, req, res) => {
99
+ // Report error asynchronously (don't wait)
100
+ reporter(error, req).catch((reportError) => {
101
+ console.error('Error reporting failed:', reportError);
102
+ });
103
+ // Send response
104
+ await (0, exports.defaultErrorHandler)(error, req, res);
105
+ };
106
+ }
107
+ /**
108
+ * Wrap error handler with custom logic
109
+ */
110
+ function wrapErrorHandler(baseHandler, wrapper) {
111
+ return async (error, req, res) => {
112
+ await wrapper(error, req, res, async () => {
113
+ await baseHandler(error, req, res);
114
+ });
115
+ };
116
+ }
117
+ /**
118
+ * Check if error should be retried
119
+ */
120
+ function isRetryableError(error) {
121
+ if (error instanceof ai_matey_errors_1.AdapterError) {
122
+ return error.isRetryable;
123
+ }
124
+ if (error instanceof ai_matey_errors_1.NetworkError || error instanceof ai_matey_errors_1.ProviderError) {
125
+ return true;
126
+ }
127
+ // Check for timeout errors by message
128
+ if (error.message.toLowerCase().includes('timeout')) {
129
+ return true;
130
+ }
131
+ return false;
132
+ }
133
+ /**
134
+ * Check if error is a client error (4xx)
135
+ */
136
+ function isClientError(error) {
137
+ const statusCode = getHTTPStatusCode(error);
138
+ return statusCode >= 400 && statusCode < 500;
139
+ }
140
+ /**
141
+ * Check if error is a server error (5xx)
142
+ */
143
+ function isServerError(error) {
144
+ const statusCode = getHTTPStatusCode(error);
145
+ return statusCode >= 500;
146
+ }
147
+ //# sourceMappingURL=error-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/error-handler.ts"],"names":[],"mappings":"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"}