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.
- package/LICENSE +21 -0
- package/README.md +508 -0
- package/dist/auth/protected.d.ts +9 -0
- package/dist/auth/protected.d.ts.map +1 -0
- package/dist/auth/protected.js +26 -0
- package/dist/auth/protected.js.map +1 -0
- package/dist/cache/manager.d.ts +21 -0
- package/dist/cache/manager.d.ts.map +1 -0
- package/dist/cache/manager.js +92 -0
- package/dist/cache/manager.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +142 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/constants/index.d.ts +84 -0
- package/dist/constants/index.d.ts.map +1 -0
- package/dist/constants/index.js +88 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/core/router.d.ts +26 -0
- package/dist/core/router.d.ts.map +1 -0
- package/dist/core/router.js +208 -0
- package/dist/core/router.js.map +1 -0
- package/dist/core/server.d.ts +18 -0
- package/dist/core/server.d.ts.map +1 -0
- package/dist/core/server.js +89 -0
- package/dist/core/server.js.map +1 -0
- package/dist/core/vector.d.ts +43 -0
- package/dist/core/vector.d.ts.map +1 -0
- package/dist/core/vector.js +179 -0
- package/dist/core/vector.js.map +1 -0
- package/dist/dev/route-generator.d.ts +8 -0
- package/dist/dev/route-generator.d.ts.map +1 -0
- package/dist/dev/route-generator.js +77 -0
- package/dist/dev/route-generator.js.map +1 -0
- package/dist/dev/route-scanner.d.ts +9 -0
- package/dist/dev/route-scanner.d.ts.map +1 -0
- package/dist/dev/route-scanner.js +85 -0
- package/dist/dev/route-scanner.js.map +1 -0
- package/dist/errors/index.d.ts +24 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +73 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/http.d.ts +73 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +143 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +21 -0
- package/dist/middleware/manager.d.ts +11 -0
- package/dist/middleware/manager.d.ts.map +1 -0
- package/dist/middleware/manager.js +35 -0
- package/dist/middleware/manager.js.map +1 -0
- package/dist/types/index.d.ts +85 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/logger.d.ts +25 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +68 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/validation.d.ts +5 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +48 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +110 -0
- package/src/auth/protected.ts +41 -0
- package/src/cache/manager.ts +133 -0
- package/src/cli/index.ts +157 -0
- package/src/constants/index.ts +93 -0
- package/src/core/router.ts +258 -0
- package/src/core/server.ts +107 -0
- package/src/core/vector.ts +228 -0
- package/src/dev/route-generator.ts +93 -0
- package/src/dev/route-scanner.ts +97 -0
- package/src/errors/index.ts +91 -0
- package/src/http.ts +331 -0
- package/src/index.ts +19 -0
- package/src/middleware/manager.ts +53 -0
- package/src/types/index.ts +126 -0
- package/src/utils/logger.ts +87 -0
- 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
|
+
}
|