vector-framework 0.8.1

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 (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +508 -0
  3. package/dist/auth/protected.d.ts +9 -0
  4. package/dist/auth/protected.d.ts.map +1 -0
  5. package/dist/auth/protected.js +26 -0
  6. package/dist/auth/protected.js.map +1 -0
  7. package/dist/cache/manager.d.ts +21 -0
  8. package/dist/cache/manager.d.ts.map +1 -0
  9. package/dist/cache/manager.js +92 -0
  10. package/dist/cache/manager.js.map +1 -0
  11. package/dist/cli/index.d.ts +3 -0
  12. package/dist/cli/index.d.ts.map +1 -0
  13. package/dist/cli/index.js +142 -0
  14. package/dist/cli/index.js.map +1 -0
  15. package/dist/constants/index.d.ts +84 -0
  16. package/dist/constants/index.d.ts.map +1 -0
  17. package/dist/constants/index.js +88 -0
  18. package/dist/constants/index.js.map +1 -0
  19. package/dist/core/router.d.ts +26 -0
  20. package/dist/core/router.d.ts.map +1 -0
  21. package/dist/core/router.js +208 -0
  22. package/dist/core/router.js.map +1 -0
  23. package/dist/core/server.d.ts +18 -0
  24. package/dist/core/server.d.ts.map +1 -0
  25. package/dist/core/server.js +89 -0
  26. package/dist/core/server.js.map +1 -0
  27. package/dist/core/vector.d.ts +43 -0
  28. package/dist/core/vector.d.ts.map +1 -0
  29. package/dist/core/vector.js +179 -0
  30. package/dist/core/vector.js.map +1 -0
  31. package/dist/dev/route-generator.d.ts +8 -0
  32. package/dist/dev/route-generator.d.ts.map +1 -0
  33. package/dist/dev/route-generator.js +77 -0
  34. package/dist/dev/route-generator.js.map +1 -0
  35. package/dist/dev/route-scanner.d.ts +9 -0
  36. package/dist/dev/route-scanner.d.ts.map +1 -0
  37. package/dist/dev/route-scanner.js +85 -0
  38. package/dist/dev/route-scanner.js.map +1 -0
  39. package/dist/errors/index.d.ts +24 -0
  40. package/dist/errors/index.d.ts.map +1 -0
  41. package/dist/errors/index.js +73 -0
  42. package/dist/errors/index.js.map +1 -0
  43. package/dist/http.d.ts +73 -0
  44. package/dist/http.d.ts.map +1 -0
  45. package/dist/http.js +143 -0
  46. package/dist/http.js.map +1 -0
  47. package/dist/index.d.ts +13 -0
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +21 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/index.mjs +21 -0
  52. package/dist/middleware/manager.d.ts +11 -0
  53. package/dist/middleware/manager.d.ts.map +1 -0
  54. package/dist/middleware/manager.js +35 -0
  55. package/dist/middleware/manager.js.map +1 -0
  56. package/dist/types/index.d.ts +85 -0
  57. package/dist/types/index.d.ts.map +1 -0
  58. package/dist/types/index.js +2 -0
  59. package/dist/types/index.js.map +1 -0
  60. package/dist/utils/logger.d.ts +25 -0
  61. package/dist/utils/logger.d.ts.map +1 -0
  62. package/dist/utils/logger.js +68 -0
  63. package/dist/utils/logger.js.map +1 -0
  64. package/dist/utils/validation.d.ts +5 -0
  65. package/dist/utils/validation.d.ts.map +1 -0
  66. package/dist/utils/validation.js +48 -0
  67. package/dist/utils/validation.js.map +1 -0
  68. package/package.json +110 -0
  69. package/src/auth/protected.ts +41 -0
  70. package/src/cache/manager.ts +133 -0
  71. package/src/cli/index.ts +157 -0
  72. package/src/constants/index.ts +93 -0
  73. package/src/core/router.ts +258 -0
  74. package/src/core/server.ts +107 -0
  75. package/src/core/vector.ts +228 -0
  76. package/src/dev/route-generator.ts +93 -0
  77. package/src/dev/route-scanner.ts +97 -0
  78. package/src/errors/index.ts +91 -0
  79. package/src/http.ts +331 -0
  80. package/src/index.ts +19 -0
  81. package/src/middleware/manager.ts +53 -0
  82. package/src/types/index.ts +126 -0
  83. package/src/utils/logger.ts +87 -0
  84. package/src/utils/validation.ts +58 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 webhie-com
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.
package/README.md ADDED
@@ -0,0 +1,508 @@
1
+ # Vector Framework
2
+
3
+ **The speed of Bun. The developer experience you love.**
4
+
5
+ Vector brings the blazing performance of Bun to developers who appreciate the simplicity and elegance of frameworks like Encore. Build production-ready APIs with a familiar, declarative syntax while leveraging Bun's incredible speed.
6
+
7
+ ## Why Vector?
8
+
9
+ If you've been looking for Encore-like developer experience with Bun's performance, Vector is your answer. Define your routes declaratively, enjoy automatic type safety, and ship faster than ever.
10
+
11
+ ## Features
12
+
13
+ - **Fast & Lightweight** - Built on Bun and itty-router for maximum performance
14
+ - **Type-Safe** - Full TypeScript support with excellent type inference
15
+ - **Auto Route Discovery** - Automatically discovers and loads routes from your filesystem
16
+ - **Middleware System** - Flexible pre/post request middleware pipeline
17
+ - **Built-in Authentication** - Simple but powerful authentication system
18
+ - **Response Caching** - Automatic response caching with configurable TTL
19
+ - **CORS Support** - Configurable CORS with sensible defaults
20
+ - **Developer Experience** - Auto route discovery and CLI tools
21
+
22
+ ## Quick Start
23
+
24
+ ### Installation
25
+
26
+ ```bash
27
+ bun add vector
28
+ ```
29
+
30
+ ### Your First API (Encore-style)
31
+
32
+ ```typescript
33
+ // routes/hello.ts
34
+ import { route } from "vector";
35
+
36
+ // Public endpoint - clean and declarative
37
+ export const hello = route(
38
+ {
39
+ method: "GET",
40
+ path: "/hello/:name",
41
+ expose: true,
42
+ },
43
+ async (req) => {
44
+ const { name } = req.params!;
45
+ return { message: `Hello ${name}!` };
46
+ }
47
+ );
48
+
49
+ // Protected endpoint - auth built-in
50
+ export const getProfile = route(
51
+ {
52
+ method: "GET",
53
+ path: "/profile",
54
+ expose: true,
55
+ auth: true, // That's it! Auth handled.
56
+ },
57
+ async (req) => {
58
+ return {
59
+ user: req.authUser,
60
+ lastLogin: new Date(),
61
+ };
62
+ }
63
+ );
64
+ ```
65
+
66
+ ### Start Your Server
67
+
68
+ ```typescript
69
+ // server.ts
70
+ import vector from "vector";
71
+
72
+ // Set up auth (once, globally)
73
+ vector.protected = async (request) => {
74
+ const token = request.headers.get("Authorization")?.replace("Bearer ", "");
75
+ // Your auth logic here
76
+ if (token === "valid-token") {
77
+ return { id: "user-123", email: "user@example.com" };
78
+ }
79
+ throw new Error("Invalid token");
80
+ };
81
+
82
+ // Start server - routes auto-discovered from ./routes
83
+ vector.serve({ port: 3000 });
84
+ ```
85
+
86
+ ## Familiar Patterns, Modern Performance
87
+
88
+ ### Real-World Example: User Service
89
+
90
+ ```typescript
91
+ // routes/users.ts
92
+ import { route } from "vector";
93
+ import { db } from "../db";
94
+
95
+ // Public endpoint with caching
96
+ export const listUsers = route(
97
+ {
98
+ method: "GET",
99
+ path: "/users",
100
+ expose: true,
101
+ cache: 300, // Cache for 5 minutes
102
+ },
103
+ async () => {
104
+ const users = await db.user.findMany();
105
+ return { users };
106
+ }
107
+ );
108
+
109
+ // Protected endpoint with automatic body parsing
110
+ export const createUser = route(
111
+ {
112
+ method: "POST",
113
+ path: "/users",
114
+ expose: true,
115
+ auth: true, // Auth required
116
+ },
117
+ async (req) => {
118
+ const { name, email } = req.content; // Type-safe, auto-parsed
119
+
120
+ const user = await db.user.create({
121
+ data: { name, email },
122
+ });
123
+
124
+ return { user };
125
+ }
126
+ );
127
+
128
+ // Parameter extraction made simple
129
+ export const getUser = route(
130
+ {
131
+ method: "GET",
132
+ path: "/users/:id",
133
+ expose: true,
134
+ },
135
+ async (req) => {
136
+ const { id } = req.params!;
137
+ const user = await db.user.findUnique({ where: { id } });
138
+
139
+ if (!user) {
140
+ throw new APIError("User not found", 404);
141
+ }
142
+
143
+ return { user };
144
+ }
145
+ );
146
+ ```
147
+
148
+ ## Why Choose Vector?
149
+
150
+ ### 🚀 Bun-Powered Performance
151
+
152
+ - **Native TypeScript** execution without transpilation overhead
153
+ - **Significantly faster** startup times and request handling
154
+ - **Minimal memory footprint** thanks to Bun's efficient runtime
155
+
156
+ ### 💡 Developer Experience
157
+
158
+ - **Encore-inspired API** - If you know Encore, you already know Vector
159
+ - **Auto route discovery** - Just write your routes, we'll find them
160
+ - **Type safety everywhere** - Full TypeScript support
161
+ - **Built-in essentials** - Auth, caching, CORS, middleware - all included
162
+
163
+ ### 🔄 Easy Migration
164
+
165
+ Moving from Express, Fastify, or Encore? Vector makes it simple:
166
+
167
+ ```typescript
168
+ // Encore-style (what you know)
169
+ export const get = api(
170
+ { expose: true, method: "GET", path: "/hello/:name" },
171
+ async ({ name }: { name: string }): Promise<Response> => {
172
+ const msg = `Hello ${name}!`;
173
+ return { message: msg };
174
+ }
175
+ );
176
+
177
+ // Vector-style (what you write)
178
+ export const hello = route(
179
+ { expose: true, method: "GET", path: "/hello/:name" },
180
+ async (req) => {
181
+ return { message: `Hello ${req.params.name}!` };
182
+ }
183
+ );
184
+ ```
185
+
186
+ ## For Encore Users
187
+
188
+ Switching from Encore? You'll feel right at home. Vector provides the same declarative, type-safe API design with the performance benefits of Bun:
189
+
190
+ | Encore | Vector |
191
+ | ---------------------- | -------------------------------- |
192
+ | `api.requireAuth()` | `{ auth: true }` in route config |
193
+ | Auto-generated clients | Not yet available |
194
+ | Built-in tracing | Middleware support |
195
+ | Cloud deployment | Deploy anywhere Bun runs |
196
+
197
+ **The key difference:** Vector runs on Bun, giving you significantly better performance and lower resource usage while maintaining the developer experience you love.
198
+
199
+ ## CLI Commands
200
+
201
+ Vector includes a built-in CLI for development and production:
202
+
203
+ ```bash
204
+ # Development server
205
+ bun run dev
206
+
207
+ # Production server
208
+ bun run start
209
+
210
+ # Run with custom options
211
+ bun run src/cli/index.ts dev --port 3000 --routes ./api
212
+ ```
213
+
214
+ Or use npm scripts:
215
+
216
+ ```bash
217
+ # Start development server
218
+ bun run dev
219
+
220
+ # Start production server
221
+ bun run start
222
+
223
+ # Build for production
224
+ bun run build
225
+ ```
226
+
227
+ ## Route Options
228
+
229
+ ```typescript
230
+ interface RouteOptions {
231
+ method: string; // HTTP method (GET, POST, etc.)
232
+ path: string; // Route path with params (/users/:id)
233
+ expose?: boolean; // Make route accessible (default: false)
234
+ auth?: boolean; // Require authentication (default: false)
235
+ cache?:
236
+ | number
237
+ | {
238
+ // Cache configuration
239
+ ttl: number; // Time to live in seconds
240
+ key?: string; // Custom cache key
241
+ };
242
+ rawRequest?: boolean; // Skip body parsing (default: false)
243
+ rawResponse?: boolean; // Return raw response (default: false)
244
+ responseContentType?: string; // Response content type
245
+ }
246
+ ```
247
+
248
+ ## Middleware
249
+
250
+ ### Before Middleware (Pre-handlers)
251
+
252
+ ```typescript
253
+ const authMiddleware = async (request) => {
254
+ // Modify request or return Response to short-circuit
255
+ request.customData = "value";
256
+ return request;
257
+ };
258
+
259
+ const rateLimitMiddleware = async (request) => {
260
+ // Return Response to stop processing
261
+ if (tooManyRequests) {
262
+ return new Response("Too Many Requests", { status: 429 });
263
+ }
264
+ return request;
265
+ };
266
+ ```
267
+
268
+ ### Finally Middleware (Post-handlers)
269
+
270
+ ```typescript
271
+ const corsMiddleware = async (response, request) => {
272
+ // Modify response headers
273
+ response.headers.set("X-Custom-Header", "value");
274
+ return response;
275
+ };
276
+ ```
277
+
278
+ ## Authentication
279
+
280
+ Implement your authentication logic:
281
+
282
+ ```typescript
283
+ vector.protected = async (request) => {
284
+ const authHeader = request.headers.get("Authorization");
285
+
286
+ if (!authHeader?.startsWith("Bearer ")) {
287
+ throw new Error("Invalid authorization header");
288
+ }
289
+
290
+ const token = authHeader.substring(7);
291
+ const user = await validateToken(token);
292
+
293
+ if (!user) {
294
+ throw new Error("Invalid token");
295
+ }
296
+
297
+ return user; // This will be available as req.authUser
298
+ };
299
+ ```
300
+
301
+ ## Caching
302
+
303
+ Implement your caching strategy:
304
+
305
+ ```typescript
306
+ vector.cache = async (key, factory, ttl) => {
307
+ // Example with Redis
308
+ const cached = await redis.get(key);
309
+ if (cached) return JSON.parse(cached);
310
+
311
+ const value = await factory();
312
+ await redis.setex(key, ttl, JSON.stringify(value));
313
+
314
+ return value;
315
+ };
316
+ ```
317
+
318
+ ## Configuration
319
+
320
+ ```typescript
321
+ interface VectorConfig {
322
+ port?: number; // Server port (default: 3000)
323
+ hostname?: string; // Server hostname (default: localhost)
324
+ reusePort?: boolean; // Reuse port (default: true)
325
+ development?: boolean; // Development mode
326
+ routesDir?: string; // Routes directory (default: ./routes)
327
+ }
328
+ ```
329
+
330
+ ### Middleware Configuration
331
+
332
+ ```typescript
333
+ // Add before middleware (runs before routes)
334
+ vector.before(async (request) => {
335
+ console.log(`${request.method} ${request.url}`);
336
+ return request;
337
+ });
338
+
339
+ // Add finally middleware (runs after routes)
340
+ vector.finally(async (response, request) => {
341
+ response.headers.set("X-Response-Time", Date.now() - request.startTime);
342
+ return response;
343
+ });
344
+ ```
345
+
346
+ ## Project Structure
347
+
348
+ ```
349
+ my-app/
350
+ ├── routes/ # Auto-discovered routes
351
+ │ ├── users.ts
352
+ │ ├── posts.ts
353
+ │ └── health.ts
354
+ ├── middleware/ # Custom middleware
355
+ │ ├── auth.ts
356
+ │ └── logging.ts
357
+ ├── server.ts # Main server file
358
+ └── package.json
359
+ ```
360
+
361
+ ## TypeScript Support
362
+
363
+ Vector is written in TypeScript and provides full type safety with customizable types:
364
+
365
+ ```typescript
366
+ import { createVector, route, APIError } from "vector";
367
+ import type { VectorRequest, VectorTypes } from "vector";
368
+
369
+ // Define your custom user type
370
+ interface MyUser {
371
+ id: string;
372
+ email: string;
373
+ role: "admin" | "user";
374
+ permissions: string[];
375
+ }
376
+
377
+ // Extend Vector types
378
+ interface MyAppTypes extends VectorTypes {
379
+ auth: MyUser;
380
+ }
381
+
382
+ // Create typed Vector instance
383
+ const vector = createVector<MyAppTypes>();
384
+
385
+ // Configure authentication with your custom type
386
+ vector.protected = async (request): Promise<MyUser> => {
387
+ // Your auth logic here
388
+ return {
389
+ id: "user-123",
390
+ email: "user@example.com",
391
+ role: "admin",
392
+ permissions: ["read", "write"],
393
+ };
394
+ };
395
+
396
+ // Routes automatically have typed authUser
397
+ vector.route(
398
+ { method: "GET", path: "/admin", expose: true, auth: true },
399
+ async (request) => {
400
+ // request.authUser is typed as MyUser
401
+ if (request.authUser?.role !== "admin") {
402
+ throw APIError.forbidden("Admin access required");
403
+ }
404
+ return { adminData: "..." };
405
+ }
406
+ );
407
+ ```
408
+
409
+ ## Error Handling
410
+
411
+ Vector provides comprehensive built-in error responses for all HTTP status codes:
412
+
413
+ ### Common Client Errors (4xx)
414
+
415
+ ```typescript
416
+ import { APIError } from "vector";
417
+
418
+ // Basic errors
419
+ APIError.badRequest("Invalid input"); // 400
420
+ APIError.unauthorized("Please login"); // 401
421
+ APIError.forbidden("Access denied"); // 403
422
+ APIError.notFound("Resource not found"); // 404
423
+ APIError.conflict("Resource already exists"); // 409
424
+
425
+ // Validation and input errors
426
+ APIError.unprocessableEntity("Invalid data"); // 422
427
+ APIError.invalidArgument("Field required"); // 422 (alias)
428
+ APIError.payloadTooLarge("File too large"); // 413
429
+ APIError.unsupportedMediaType("Invalid type"); // 415
430
+
431
+ // Rate limiting and timeouts
432
+ APIError.tooManyRequests("Rate limit exceeded"); // 429
433
+ APIError.rateLimitExceeded("Try again later"); // 429 (alias)
434
+ APIError.requestTimeout("Request took too long"); // 408
435
+
436
+ // Method and protocol errors
437
+ APIError.methodNotAllowed("POST not allowed"); // 405
438
+ APIError.notAcceptable("Cannot produce response"); // 406
439
+ APIError.preconditionFailed("ETag mismatch"); // 412
440
+ ```
441
+
442
+ ### Server Errors (5xx)
443
+
444
+ ```typescript
445
+ // Server errors
446
+ APIError.internalServerError("Something went wrong"); // 500
447
+ APIError.notImplemented("Feature coming soon"); // 501
448
+ APIError.badGateway("Upstream server error"); // 502
449
+ APIError.serviceUnavailable("Service down"); // 503
450
+ APIError.maintenance("Under maintenance"); // 503 (alias)
451
+ APIError.gatewayTimeout("Upstream timeout"); // 504
452
+ ```
453
+
454
+ ### Custom Errors
455
+
456
+ ```typescript
457
+ // Create custom error with any status code
458
+ APIError.custom(456, 'Custom error message');
459
+
460
+ // All errors include additional metadata
461
+ // Response format:
462
+ {
463
+ "error": true,
464
+ "message": "Error message",
465
+ "statusCode": 400,
466
+ "timestamp": "2025-01-01T00:00:00.000Z"
467
+ }
468
+ ```
469
+
470
+ ### Usage in Routes
471
+
472
+ ```typescript
473
+ vector.route(
474
+ { method: "GET", path: "/api/data/:id", expose: true },
475
+ async (req) => {
476
+ // Validation
477
+ if (!req.params?.id) {
478
+ throw APIError.badRequest("ID is required");
479
+ }
480
+
481
+ // Check rate limits
482
+ if (await isRateLimited(req)) {
483
+ throw APIError.tooManyRequests("Please wait before trying again");
484
+ }
485
+
486
+ // Fetch data
487
+ const data = await fetchData(req.params.id);
488
+ if (!data) {
489
+ throw APIError.notFound("Data not found");
490
+ }
491
+
492
+ // Check permissions
493
+ if (!canAccess(req.authUser, data)) {
494
+ throw APIError.forbidden("You cannot access this resource");
495
+ }
496
+
497
+ return data;
498
+ }
499
+ );
500
+ ```
501
+
502
+ ## Contributing
503
+
504
+ Contributions are welcome! Please feel free to submit a Pull Request.
505
+
506
+ ## License
507
+
508
+ MIT
@@ -0,0 +1,9 @@
1
+ import type { DefaultVectorTypes, GetAuthType, ProtectedHandler, VectorRequest, VectorTypes } from '../types';
2
+ export declare class AuthManager<TTypes extends VectorTypes = DefaultVectorTypes> {
3
+ private protectedHandler;
4
+ setProtectedHandler(handler: ProtectedHandler<TTypes>): void;
5
+ authenticate(request: VectorRequest<TTypes>): Promise<GetAuthType<TTypes> | null>;
6
+ isAuthenticated(request: VectorRequest<TTypes>): boolean;
7
+ getUser(request: VectorRequest<TTypes>): GetAuthType<TTypes> | null;
8
+ }
9
+ //# sourceMappingURL=protected.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protected.d.ts","sourceRoot":"","sources":["../../src/auth/protected.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,WAAW,EACX,gBAAgB,EAChB,aAAa,EACb,WAAW,EACZ,MAAM,UAAU,CAAC;AAElB,qBAAa,WAAW,CAAC,MAAM,SAAS,WAAW,GAAG,kBAAkB;IACtE,OAAO,CAAC,gBAAgB,CAAyC;IAEjE,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC;IAI/C,YAAY,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAkBvF,eAAe,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,OAAO;IAIxD,OAAO,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,GAAG,IAAI;CAGpE"}
@@ -0,0 +1,26 @@
1
+ export class AuthManager {
2
+ protectedHandler = null;
3
+ setProtectedHandler(handler) {
4
+ this.protectedHandler = handler;
5
+ }
6
+ async authenticate(request) {
7
+ if (!this.protectedHandler) {
8
+ throw new Error('Protected handler not configured. Use vector.protected() to set authentication handler.');
9
+ }
10
+ try {
11
+ const authUser = await this.protectedHandler(request);
12
+ request.authUser = authUser;
13
+ return authUser;
14
+ }
15
+ catch (error) {
16
+ throw new Error(`Authentication failed: ${error instanceof Error ? error.message : String(error)}`);
17
+ }
18
+ }
19
+ isAuthenticated(request) {
20
+ return !!request.authUser;
21
+ }
22
+ getUser(request) {
23
+ return request.authUser || null;
24
+ }
25
+ }
26
+ //# sourceMappingURL=protected.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protected.js","sourceRoot":"","sources":["../../src/auth/protected.ts"],"names":[],"mappings":"AAQA,MAAM,OAAO,WAAW;IACd,gBAAgB,GAAoC,IAAI,CAAC;IAEjE,mBAAmB,CAAC,OAAiC;QACnD,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,OAA8B;QAC/C,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CACb,yFAAyF,CAC1F,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;YACtD,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAC5B,OAAO,QAAQ,CAAC;QAClB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,0BAA0B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACnF,CAAC;QACJ,CAAC;IACH,CAAC;IAED,eAAe,CAAC,OAA8B;QAC5C,OAAO,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;IAC5B,CAAC;IAED,OAAO,CAAC,OAA8B;QACpC,OAAO,OAAO,CAAC,QAAQ,IAAI,IAAI,CAAC;IAClC,CAAC;CACF"}
@@ -0,0 +1,21 @@
1
+ import type { CacheHandler, DefaultVectorTypes, GetCacheType, VectorTypes } from '../types';
2
+ export declare class CacheManager<TTypes extends VectorTypes = DefaultVectorTypes> {
3
+ private cacheHandler;
4
+ private memoryCache;
5
+ private cleanupInterval;
6
+ setCacheHandler(handler: CacheHandler): void;
7
+ get<T = GetCacheType<TTypes>>(key: string, factory: () => Promise<T>, ttl?: number): Promise<T>;
8
+ private getFromMemoryCache;
9
+ private isCacheValid;
10
+ private setInMemoryCache;
11
+ private scheduleCleanup;
12
+ private cleanupExpired;
13
+ clear(): void;
14
+ set<T = GetCacheType<TTypes>>(key: string, value: T, ttl?: number): Promise<void>;
15
+ delete(key: string): boolean;
16
+ has(key: string): boolean;
17
+ generateKey(request: Request, options?: {
18
+ authUser?: any;
19
+ }): string;
20
+ }
21
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/cache/manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAO5F,qBAAa,YAAY,CAAC,MAAM,SAAS,WAAW,GAAG,kBAAkB;IACvE,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,WAAW,CAAsC;IACzD,OAAO,CAAC,eAAe,CAAsB;IAE7C,eAAe,CAAC,OAAO,EAAE,YAAY;IAI/B,GAAG,CAAC,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,EAChC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACzB,GAAG,GAAE,MAAiC,GACrC,OAAO,CAAC,CAAC,CAAC;YAYC,kBAAkB;IAkBhC,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,cAAc;IActB,KAAK,IAAI,IAAI;IAQP,GAAG,CAAC,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,EAChC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,CAAC,EACR,GAAG,GAAE,MAAiC,GACrC,OAAO,CAAC,IAAI,CAAC;IAchB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI5B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAYzB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,GAAG,CAAA;KAAE,GAAG,MAAM;CAMpE"}
@@ -0,0 +1,92 @@
1
+ import { DEFAULT_CONFIG } from '../constants';
2
+ export class CacheManager {
3
+ cacheHandler = null;
4
+ memoryCache = new Map();
5
+ cleanupInterval = null;
6
+ setCacheHandler(handler) {
7
+ this.cacheHandler = handler;
8
+ }
9
+ async get(key, factory, ttl = DEFAULT_CONFIG.CACHE_TTL) {
10
+ if (ttl <= 0) {
11
+ return factory();
12
+ }
13
+ if (this.cacheHandler) {
14
+ return this.cacheHandler(key, factory, ttl);
15
+ }
16
+ return this.getFromMemoryCache(key, factory, ttl);
17
+ }
18
+ async getFromMemoryCache(key, factory, ttl) {
19
+ const now = Date.now();
20
+ const cached = this.memoryCache.get(key);
21
+ if (this.isCacheValid(cached, now)) {
22
+ return cached.value;
23
+ }
24
+ const value = await factory();
25
+ this.setInMemoryCache(key, value, ttl);
26
+ return value;
27
+ }
28
+ isCacheValid(entry, now) {
29
+ return entry !== undefined && entry.expires > now;
30
+ }
31
+ setInMemoryCache(key, value, ttl) {
32
+ const expires = Date.now() + ttl * 1000;
33
+ this.memoryCache.set(key, { value, expires });
34
+ this.scheduleCleanup();
35
+ }
36
+ scheduleCleanup() {
37
+ if (this.cleanupInterval)
38
+ return;
39
+ this.cleanupInterval = setInterval(() => {
40
+ this.cleanupExpired();
41
+ }, 60000); // Clean up every minute
42
+ }
43
+ cleanupExpired() {
44
+ const now = Date.now();
45
+ for (const [key, entry] of this.memoryCache.entries()) {
46
+ if (entry.expires <= now) {
47
+ this.memoryCache.delete(key);
48
+ }
49
+ }
50
+ if (this.memoryCache.size === 0 && this.cleanupInterval) {
51
+ clearInterval(this.cleanupInterval);
52
+ this.cleanupInterval = null;
53
+ }
54
+ }
55
+ clear() {
56
+ this.memoryCache.clear();
57
+ if (this.cleanupInterval) {
58
+ clearInterval(this.cleanupInterval);
59
+ this.cleanupInterval = null;
60
+ }
61
+ }
62
+ async set(key, value, ttl = DEFAULT_CONFIG.CACHE_TTL) {
63
+ if (ttl <= 0) {
64
+ return;
65
+ }
66
+ if (this.cacheHandler) {
67
+ // Custom cache handler can implement its own set logic
68
+ await this.cacheHandler(key, async () => value, ttl);
69
+ return;
70
+ }
71
+ this.setInMemoryCache(key, value, ttl);
72
+ }
73
+ delete(key) {
74
+ return this.memoryCache.delete(key);
75
+ }
76
+ has(key) {
77
+ const entry = this.memoryCache.get(key);
78
+ if (!entry)
79
+ return false;
80
+ if (entry.expires <= Date.now()) {
81
+ this.memoryCache.delete(key);
82
+ return false;
83
+ }
84
+ return true;
85
+ }
86
+ generateKey(request, options) {
87
+ const url = new URL(request.url);
88
+ const parts = [request.method, url.pathname, url.search, options?.authUser?.id || 'anonymous'];
89
+ return parts.join(':');
90
+ }
91
+ }
92
+ //# sourceMappingURL=manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/cache/manager.ts"],"names":[],"mappings":"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"}