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
@@ -0,0 +1,126 @@
1
+ import type { IRequest } from 'itty-router';
2
+
3
+ // Default AuthUser type - users can override this with their own type
4
+ export interface DefaultAuthUser {
5
+ id: string;
6
+ email?: string;
7
+ role?: string;
8
+ permissions?: string[];
9
+ [key: string]: any;
10
+ }
11
+
12
+ // Extensible type configuration interface
13
+ // Users can override any of these types without breaking changes
14
+ export interface VectorTypes {
15
+ auth?: any; // Custom auth user type
16
+ context?: any; // Custom request context (future)
17
+ cache?: any; // Custom cache value type (future)
18
+ metadata?: any; // Custom metadata type (future)
19
+ }
20
+
21
+ // Default types
22
+ export interface DefaultVectorTypes extends VectorTypes {
23
+ auth: DefaultAuthUser;
24
+ context: Record<string, any>;
25
+ cache: any;
26
+ metadata: Record<string, any>;
27
+ }
28
+
29
+ // Type helpers
30
+ export type GetAuthType<T extends VectorTypes> = T['auth'] extends undefined
31
+ ? DefaultAuthUser
32
+ : T['auth'];
33
+
34
+ export type GetContextType<T extends VectorTypes> = T['context'] extends undefined
35
+ ? Record<string, any>
36
+ : T['context'];
37
+
38
+ export type GetCacheType<T extends VectorTypes> = T['cache'] extends undefined ? any : T['cache'];
39
+
40
+ export type GetMetadataType<T extends VectorTypes> = T['metadata'] extends undefined
41
+ ? Record<string, any>
42
+ : T['metadata'];
43
+
44
+ // Legacy support - keep AuthUser for backward compatibility
45
+ export type AuthUser = DefaultAuthUser;
46
+
47
+ export interface VectorRequest<TTypes extends VectorTypes = DefaultVectorTypes>
48
+ extends Omit<IRequest, 'params'> {
49
+ authUser?: GetAuthType<TTypes>;
50
+ context: GetContextType<TTypes>;
51
+ metadata?: GetMetadataType<TTypes>;
52
+ content?: any;
53
+ params?: Record<string, string>;
54
+ startTime?: number;
55
+ [key: string]: any;
56
+ }
57
+
58
+ export interface CacheOptions {
59
+ key?: string;
60
+ ttl?: number;
61
+ }
62
+
63
+ export interface RouteOptions<TTypes extends VectorTypes = DefaultVectorTypes> {
64
+ method: string;
65
+ path: string;
66
+ auth?: boolean;
67
+ expose?: boolean;
68
+ cache?: CacheOptions | number;
69
+ rawRequest?: boolean;
70
+ rawResponse?: boolean;
71
+ responseContentType?: string;
72
+ metadata?: GetMetadataType<TTypes>;
73
+ }
74
+
75
+ export interface VectorConfig<TTypes extends VectorTypes = DefaultVectorTypes> {
76
+ port?: number;
77
+ hostname?: string;
78
+ reusePort?: boolean;
79
+ development?: boolean;
80
+ cors?: CorsOptions;
81
+ before?: BeforeMiddlewareHandler<TTypes>[];
82
+ finally?: AfterMiddlewareHandler<TTypes>[];
83
+ routesDir?: string;
84
+ autoDiscover?: boolean;
85
+ }
86
+
87
+ export interface CorsOptions {
88
+ origin?: string | string[] | ((origin: string) => boolean);
89
+ credentials?: boolean;
90
+ allowHeaders?: string | string[];
91
+ allowMethods?: string | string[];
92
+ exposeHeaders?: string | string[];
93
+ maxAge?: number;
94
+ }
95
+
96
+ export type BeforeMiddlewareHandler<TTypes extends VectorTypes = DefaultVectorTypes> = (
97
+ request: VectorRequest<TTypes>
98
+ ) => Promise<VectorRequest<TTypes> | Response> | VectorRequest<TTypes> | Response;
99
+
100
+ export type AfterMiddlewareHandler<TTypes extends VectorTypes = DefaultVectorTypes> = (
101
+ response: Response,
102
+ request: VectorRequest<TTypes>
103
+ ) => Promise<Response> | Response;
104
+ export type MiddlewareHandler = BeforeMiddlewareHandler | AfterMiddlewareHandler;
105
+
106
+ export type RouteHandler<TTypes extends VectorTypes = DefaultVectorTypes> = (
107
+ request: VectorRequest<TTypes>
108
+ ) => Promise<any> | any;
109
+
110
+ export type ProtectedHandler<TTypes extends VectorTypes = DefaultVectorTypes> = (
111
+ request: VectorRequest<TTypes>
112
+ ) => Promise<GetAuthType<TTypes>> | GetAuthType<TTypes>;
113
+
114
+ export type CacheHandler = (key: string, factory: () => Promise<any>, ttl: number) => Promise<any>;
115
+
116
+ export interface RouteDefinition<TTypes extends VectorTypes = DefaultVectorTypes> {
117
+ options: RouteOptions<TTypes>;
118
+ handler: RouteHandler<TTypes>;
119
+ }
120
+
121
+ export interface GeneratedRoute<TTypes extends VectorTypes = DefaultVectorTypes> {
122
+ name: string;
123
+ path: string;
124
+ method: string;
125
+ options: RouteOptions<TTypes>;
126
+ }
@@ -0,0 +1,87 @@
1
+ export enum LogLevel {
2
+ DEBUG = 0,
3
+ INFO = 1,
4
+ WARN = 2,
5
+ ERROR = 3,
6
+ }
7
+
8
+ export interface LoggerConfig {
9
+ level: LogLevel;
10
+ prefix?: string;
11
+ timestamp?: boolean;
12
+ }
13
+
14
+ export class Logger {
15
+ private config: LoggerConfig;
16
+
17
+ constructor(config: Partial<LoggerConfig> = {}) {
18
+ this.config = {
19
+ level: config.level ?? LogLevel.INFO,
20
+ prefix: config.prefix ?? '[Vector]',
21
+ timestamp: config.timestamp ?? true,
22
+ };
23
+ }
24
+
25
+ private formatMessage(level: string, message: string): string {
26
+ const parts: string[] = [];
27
+
28
+ if (this.config.timestamp) {
29
+ parts.push(`[${new Date().toISOString()}]`);
30
+ }
31
+
32
+ if (this.config.prefix) {
33
+ parts.push(this.config.prefix);
34
+ }
35
+
36
+ parts.push(`[${level}]`);
37
+ parts.push(message);
38
+
39
+ return parts.join(' ');
40
+ }
41
+
42
+ debug(message: string, ...args: any[]): void {
43
+ if (this.config.level <= LogLevel.DEBUG) {
44
+ console.log(this.formatMessage('DEBUG', message), ...args);
45
+ }
46
+ }
47
+
48
+ info(message: string, ...args: any[]): void {
49
+ if (this.config.level <= LogLevel.INFO) {
50
+ console.log(this.formatMessage('INFO', message), ...args);
51
+ }
52
+ }
53
+
54
+ warn(message: string, ...args: any[]): void {
55
+ if (this.config.level <= LogLevel.WARN) {
56
+ console.warn(this.formatMessage('WARN', message), ...args);
57
+ }
58
+ }
59
+
60
+ error(message: string, error?: Error): void {
61
+ if (this.config.level <= LogLevel.ERROR) {
62
+ console.error(this.formatMessage('ERROR', message));
63
+ if (error) {
64
+ console.error(error.stack || error.message);
65
+ }
66
+ }
67
+ }
68
+
69
+ success(message: string): void {
70
+ console.log(`✅ ${message}`);
71
+ }
72
+
73
+ loading(message: string): void {
74
+ console.log(`⏳ ${message}`);
75
+ }
76
+
77
+ setLevel(level: LogLevel): void {
78
+ this.config.level = level;
79
+ }
80
+ }
81
+
82
+ export const logger = new Logger({
83
+ level: process.env.LOG_LEVEL
84
+ ? (LogLevel[process.env.LOG_LEVEL as keyof typeof LogLevel] ?? LogLevel.INFO)
85
+ : LogLevel.INFO,
86
+ timestamp: process.env.NODE_ENV !== 'production',
87
+ });
@@ -0,0 +1,58 @@
1
+ import { DEFAULT_CONFIG } from '../constants';
2
+ import type { CorsOptions, VectorConfig } from '../types';
3
+
4
+ export function validateConfig(config: VectorConfig): VectorConfig {
5
+ const validatedConfig: VectorConfig = {
6
+ port: validatePort(config.port),
7
+ hostname: config.hostname || DEFAULT_CONFIG.HOSTNAME,
8
+ reusePort: config.reusePort !== false,
9
+ development: config.development || false,
10
+ routesDir: config.routesDir || DEFAULT_CONFIG.ROUTES_DIR,
11
+ autoDiscover: config.autoDiscover !== false,
12
+ cors: config.cors ? validateCorsOptions(config.cors) : undefined,
13
+ before: config.before || [],
14
+ finally: config.finally || [],
15
+ };
16
+
17
+ return validatedConfig;
18
+ }
19
+
20
+ function validatePort(port?: number): number {
21
+ if (port === undefined) {
22
+ return DEFAULT_CONFIG.PORT;
23
+ }
24
+
25
+ if (!Number.isInteger(port) || port < 1 || port > 65535) {
26
+ throw new Error(`Invalid port: ${port}. Port must be between 1 and 65535.`);
27
+ }
28
+
29
+ return port;
30
+ }
31
+
32
+ function validateCorsOptions(cors: CorsOptions | boolean): CorsOptions | undefined {
33
+ if (cors === false) {
34
+ return undefined;
35
+ }
36
+
37
+ if (cors === true) {
38
+ return {
39
+ origin: '*',
40
+ credentials: true,
41
+ allowHeaders: ['Content-Type', 'Authorization'],
42
+ allowMethods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
43
+ exposeHeaders: ['Authorization'],
44
+ maxAge: DEFAULT_CONFIG.CORS_MAX_AGE,
45
+ };
46
+ }
47
+
48
+ return cors;
49
+ }
50
+
51
+ export function isValidHttpMethod(method: string): boolean {
52
+ const validMethods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'];
53
+ return validMethods.includes(method.toUpperCase());
54
+ }
55
+
56
+ export function isValidPath(path: string): boolean {
57
+ return path.startsWith('/') && !path.includes(' ');
58
+ }