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 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,oBAAY,QAAQ;IAClB,KAAK,IAAI;IACT,IAAI,IAAI;IACR,IAAI,IAAI;IACR,KAAK,IAAI;CACV;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,QAAQ,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAe;gBAEjB,MAAM,GAAE,OAAO,CAAC,YAAY,CAAM;IAQ9C,OAAO,CAAC,aAAa;IAiBrB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAM5C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAM3C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI;IAM3C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI;IAS3C,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI9B,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAI9B,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;CAGhC;AAED,eAAO,MAAM,MAAM,QAKjB,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export var LogLevel;
|
|
2
|
+
(function (LogLevel) {
|
|
3
|
+
LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG";
|
|
4
|
+
LogLevel[LogLevel["INFO"] = 1] = "INFO";
|
|
5
|
+
LogLevel[LogLevel["WARN"] = 2] = "WARN";
|
|
6
|
+
LogLevel[LogLevel["ERROR"] = 3] = "ERROR";
|
|
7
|
+
})(LogLevel || (LogLevel = {}));
|
|
8
|
+
export class Logger {
|
|
9
|
+
config;
|
|
10
|
+
constructor(config = {}) {
|
|
11
|
+
this.config = {
|
|
12
|
+
level: config.level ?? LogLevel.INFO,
|
|
13
|
+
prefix: config.prefix ?? '[Vector]',
|
|
14
|
+
timestamp: config.timestamp ?? true,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
formatMessage(level, message) {
|
|
18
|
+
const parts = [];
|
|
19
|
+
if (this.config.timestamp) {
|
|
20
|
+
parts.push(`[${new Date().toISOString()}]`);
|
|
21
|
+
}
|
|
22
|
+
if (this.config.prefix) {
|
|
23
|
+
parts.push(this.config.prefix);
|
|
24
|
+
}
|
|
25
|
+
parts.push(`[${level}]`);
|
|
26
|
+
parts.push(message);
|
|
27
|
+
return parts.join(' ');
|
|
28
|
+
}
|
|
29
|
+
debug(message, ...args) {
|
|
30
|
+
if (this.config.level <= LogLevel.DEBUG) {
|
|
31
|
+
console.log(this.formatMessage('DEBUG', message), ...args);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
info(message, ...args) {
|
|
35
|
+
if (this.config.level <= LogLevel.INFO) {
|
|
36
|
+
console.log(this.formatMessage('INFO', message), ...args);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
warn(message, ...args) {
|
|
40
|
+
if (this.config.level <= LogLevel.WARN) {
|
|
41
|
+
console.warn(this.formatMessage('WARN', message), ...args);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
error(message, error) {
|
|
45
|
+
if (this.config.level <= LogLevel.ERROR) {
|
|
46
|
+
console.error(this.formatMessage('ERROR', message));
|
|
47
|
+
if (error) {
|
|
48
|
+
console.error(error.stack || error.message);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
success(message) {
|
|
53
|
+
console.log(`✅ ${message}`);
|
|
54
|
+
}
|
|
55
|
+
loading(message) {
|
|
56
|
+
console.log(`⏳ ${message}`);
|
|
57
|
+
}
|
|
58
|
+
setLevel(level) {
|
|
59
|
+
this.config.level = level;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export const logger = new Logger({
|
|
63
|
+
level: process.env.LOG_LEVEL
|
|
64
|
+
? (LogLevel[process.env.LOG_LEVEL] ?? LogLevel.INFO)
|
|
65
|
+
: LogLevel.INFO,
|
|
66
|
+
timestamp: process.env.NODE_ENV !== 'production',
|
|
67
|
+
});
|
|
68
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { VectorConfig } from '../types';
|
|
2
|
+
export declare function validateConfig(config: VectorConfig): VectorConfig;
|
|
3
|
+
export declare function isValidHttpMethod(method: string): boolean;
|
|
4
|
+
export declare function isValidPath(path: string): boolean;
|
|
5
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,YAAY,EAAE,MAAM,UAAU,CAAC;AAE1D,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,YAAY,CAcjE;AAiCD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGzD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjD"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { DEFAULT_CONFIG } from '../constants';
|
|
2
|
+
export function validateConfig(config) {
|
|
3
|
+
const validatedConfig = {
|
|
4
|
+
port: validatePort(config.port),
|
|
5
|
+
hostname: config.hostname || DEFAULT_CONFIG.HOSTNAME,
|
|
6
|
+
reusePort: config.reusePort !== false,
|
|
7
|
+
development: config.development || false,
|
|
8
|
+
routesDir: config.routesDir || DEFAULT_CONFIG.ROUTES_DIR,
|
|
9
|
+
autoDiscover: config.autoDiscover !== false,
|
|
10
|
+
cors: config.cors ? validateCorsOptions(config.cors) : undefined,
|
|
11
|
+
before: config.before || [],
|
|
12
|
+
finally: config.finally || [],
|
|
13
|
+
};
|
|
14
|
+
return validatedConfig;
|
|
15
|
+
}
|
|
16
|
+
function validatePort(port) {
|
|
17
|
+
if (port === undefined) {
|
|
18
|
+
return DEFAULT_CONFIG.PORT;
|
|
19
|
+
}
|
|
20
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
21
|
+
throw new Error(`Invalid port: ${port}. Port must be between 1 and 65535.`);
|
|
22
|
+
}
|
|
23
|
+
return port;
|
|
24
|
+
}
|
|
25
|
+
function validateCorsOptions(cors) {
|
|
26
|
+
if (cors === false) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
if (cors === true) {
|
|
30
|
+
return {
|
|
31
|
+
origin: '*',
|
|
32
|
+
credentials: true,
|
|
33
|
+
allowHeaders: ['Content-Type', 'Authorization'],
|
|
34
|
+
allowMethods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
|
|
35
|
+
exposeHeaders: ['Authorization'],
|
|
36
|
+
maxAge: DEFAULT_CONFIG.CORS_MAX_AGE,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return cors;
|
|
40
|
+
}
|
|
41
|
+
export function isValidHttpMethod(method) {
|
|
42
|
+
const validMethods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'];
|
|
43
|
+
return validMethods.includes(method.toUpperCase());
|
|
44
|
+
}
|
|
45
|
+
export function isValidPath(path) {
|
|
46
|
+
return path.startsWith('/') && !path.includes(' ');
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,MAAM,UAAU,cAAc,CAAC,MAAoB;IACjD,MAAM,eAAe,GAAiB;QACpC,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC;QAC/B,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,cAAc,CAAC,QAAQ;QACpD,SAAS,EAAE,MAAM,CAAC,SAAS,KAAK,KAAK;QACrC,WAAW,EAAE,MAAM,CAAC,WAAW,IAAI,KAAK;QACxC,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,cAAc,CAAC,UAAU;QACxD,YAAY,EAAE,MAAM,CAAC,YAAY,KAAK,KAAK;QAC3C,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;QAChE,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE;QAC3B,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE;KAC9B,CAAC;IAEF,OAAO,eAAe,CAAC;AACzB,CAAC;AAED,SAAS,YAAY,CAAC,IAAa;IACjC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO,cAAc,CAAC,IAAI,CAAC;IAC7B,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CAAC,iBAAiB,IAAI,qCAAqC,CAAC,CAAC;IAC9E,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,mBAAmB,CAAC,IAA2B;IACtD,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACnB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO;YACL,MAAM,EAAE,GAAG;YACX,WAAW,EAAE,IAAI;YACjB,YAAY,EAAE,CAAC,cAAc,EAAE,eAAe,CAAC;YAC/C,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC;YAClE,aAAa,EAAE,CAAC,eAAe,CAAC;YAChC,MAAM,EAAE,cAAc,CAAC,YAAY;SACpC,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAClF,OAAO,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACrD,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vector-framework",
|
|
3
|
+
"version": "0.8.1",
|
|
4
|
+
"author": "",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/webhie-com/vector.git"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"module": "./dist/index.mjs",
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"itty-router": "^5.0.0"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/bun": "latest",
|
|
16
|
+
"oxlint": "^1.15.0",
|
|
17
|
+
"typescript": "^5.0.0"
|
|
18
|
+
},
|
|
19
|
+
"peerDependencies": {
|
|
20
|
+
"bun": ">=1.0.0"
|
|
21
|
+
},
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"import": "./dist/index.mjs",
|
|
26
|
+
"require": "./dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./middleware": {
|
|
29
|
+
"types": "./dist/middleware/index.d.ts",
|
|
30
|
+
"import": "./dist/middleware/index.mjs",
|
|
31
|
+
"require": "./dist/middleware/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./types": {
|
|
34
|
+
"types": "./dist/types/index.d.ts",
|
|
35
|
+
"import": "./dist/types/index.mjs",
|
|
36
|
+
"require": "./dist/types/index.js"
|
|
37
|
+
},
|
|
38
|
+
"./errors": {
|
|
39
|
+
"types": "./dist/errors/index.d.ts",
|
|
40
|
+
"import": "./dist/errors/index.mjs",
|
|
41
|
+
"require": "./dist/errors/index.js"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"bin": {
|
|
45
|
+
"vector": "./src/cli/index.ts"
|
|
46
|
+
},
|
|
47
|
+
"bugs": {
|
|
48
|
+
"url": "https://github.com/webhie-com/vector/issues"
|
|
49
|
+
},
|
|
50
|
+
"description": "A modern TypeScript API framework built with Bun and itty-router",
|
|
51
|
+
"engines": {
|
|
52
|
+
"bun": ">=1.0.0"
|
|
53
|
+
},
|
|
54
|
+
"files": [
|
|
55
|
+
"dist",
|
|
56
|
+
"src",
|
|
57
|
+
"README.md",
|
|
58
|
+
"LICENSE",
|
|
59
|
+
"package.json"
|
|
60
|
+
],
|
|
61
|
+
"homepage": "https://github.com/webhie-com/vector#readme",
|
|
62
|
+
"keywords": [
|
|
63
|
+
"api",
|
|
64
|
+
"framework",
|
|
65
|
+
"bun",
|
|
66
|
+
"itty-router",
|
|
67
|
+
"typescript",
|
|
68
|
+
"rest",
|
|
69
|
+
"http",
|
|
70
|
+
"server",
|
|
71
|
+
"middleware",
|
|
72
|
+
"router"
|
|
73
|
+
],
|
|
74
|
+
"license": "MIT",
|
|
75
|
+
"scripts": {
|
|
76
|
+
"dev": "bun run src/cli/index.ts dev",
|
|
77
|
+
"start": "bun run src/cli/index.ts start",
|
|
78
|
+
"build": "bun run src/cli/index.ts build",
|
|
79
|
+
"example": "bun run examples/server.ts",
|
|
80
|
+
"build:lib": "bun run build:clean && bun run build:ts && bun run build:bundle",
|
|
81
|
+
"build:clean": "rm -rf dist",
|
|
82
|
+
"build:ts": "tsc",
|
|
83
|
+
"build:bundle": "bun build src/index.ts --format esm --minify --outfile dist/index.mjs && bun build src/index.ts --format cjs --minify --outfile dist/index.js",
|
|
84
|
+
"test": "bun test tests/api-error.test.ts tests/cache.test.ts tests/middleware.test.ts tests/router.test.ts tests/vector.test.ts",
|
|
85
|
+
"test:unit": "bun test tests/*.test.ts",
|
|
86
|
+
"test:watch": "bun test --watch tests/*.test.ts",
|
|
87
|
+
"test:coverage": "bun test --coverage tests/*.test.ts",
|
|
88
|
+
"test:e2e": "bun test tests/e2e/e2e.test.ts",
|
|
89
|
+
"test:load": "bun run tests/e2e/load.test.ts",
|
|
90
|
+
"test:soak": "bun run tests/e2e/soak.test.ts",
|
|
91
|
+
"test:benchmark": "bun run tests/e2e/benchmark.test.ts",
|
|
92
|
+
"test:all": "bun test 'tests/**/*.test.ts'",
|
|
93
|
+
"test:perf": "bun run test:load && bun run test:soak && bun run test:benchmark",
|
|
94
|
+
"docker:build": "docker build -t vector:latest .",
|
|
95
|
+
"docker:build:test": "docker build -t vector:test --target test .",
|
|
96
|
+
"docker:run": "docker-compose up",
|
|
97
|
+
"docker:run:dev": "docker-compose --profile dev up",
|
|
98
|
+
"docker:test": "docker-compose -f docker-compose.test.yml run test-all",
|
|
99
|
+
"docker:test:unit": "docker-compose -f docker-compose.test.yml run test-unit",
|
|
100
|
+
"docker:test:e2e": "docker-compose -f docker-compose.test.yml run test-e2e",
|
|
101
|
+
"docker:test:load": "docker-compose -f docker-compose.test.yml run test-load",
|
|
102
|
+
"docker:test:benchmark": "docker-compose -f docker-compose.test.yml run test-benchmark",
|
|
103
|
+
"lint": "oxlint .",
|
|
104
|
+
"lint:fix": "oxlint . --fix",
|
|
105
|
+
"typecheck": "tsc --noEmit",
|
|
106
|
+
"prepublishOnly": "bun run build:lib && bun run test"
|
|
107
|
+
},
|
|
108
|
+
"type": "module",
|
|
109
|
+
"types": "./dist/index.d.ts"
|
|
110
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
DefaultVectorTypes,
|
|
3
|
+
GetAuthType,
|
|
4
|
+
ProtectedHandler,
|
|
5
|
+
VectorRequest,
|
|
6
|
+
VectorTypes,
|
|
7
|
+
} from '../types';
|
|
8
|
+
|
|
9
|
+
export class AuthManager<TTypes extends VectorTypes = DefaultVectorTypes> {
|
|
10
|
+
private protectedHandler: ProtectedHandler<TTypes> | null = null;
|
|
11
|
+
|
|
12
|
+
setProtectedHandler(handler: ProtectedHandler<TTypes>) {
|
|
13
|
+
this.protectedHandler = handler;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async authenticate(request: VectorRequest<TTypes>): Promise<GetAuthType<TTypes> | null> {
|
|
17
|
+
if (!this.protectedHandler) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
'Protected handler not configured. Use vector.protected() to set authentication handler.'
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const authUser = await this.protectedHandler(request);
|
|
25
|
+
request.authUser = authUser;
|
|
26
|
+
return authUser;
|
|
27
|
+
} catch (error) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
`Authentication failed: ${error instanceof Error ? error.message : String(error)}`
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
isAuthenticated(request: VectorRequest<TTypes>): boolean {
|
|
35
|
+
return !!request.authUser;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
getUser(request: VectorRequest<TTypes>): GetAuthType<TTypes> | null {
|
|
39
|
+
return request.authUser || null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { DEFAULT_CONFIG } from '../constants';
|
|
2
|
+
import type { CacheHandler, DefaultVectorTypes, GetCacheType, VectorTypes } from '../types';
|
|
3
|
+
|
|
4
|
+
interface CacheEntry<T = any> {
|
|
5
|
+
value: T;
|
|
6
|
+
expires: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class CacheManager<TTypes extends VectorTypes = DefaultVectorTypes> {
|
|
10
|
+
private cacheHandler: CacheHandler | null = null;
|
|
11
|
+
private memoryCache: Map<string, CacheEntry> = new Map();
|
|
12
|
+
private cleanupInterval: Timer | null = null;
|
|
13
|
+
|
|
14
|
+
setCacheHandler(handler: CacheHandler) {
|
|
15
|
+
this.cacheHandler = handler;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async get<T = GetCacheType<TTypes>>(
|
|
19
|
+
key: string,
|
|
20
|
+
factory: () => Promise<T>,
|
|
21
|
+
ttl: number = DEFAULT_CONFIG.CACHE_TTL
|
|
22
|
+
): Promise<T> {
|
|
23
|
+
if (ttl <= 0) {
|
|
24
|
+
return factory();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (this.cacheHandler) {
|
|
28
|
+
return this.cacheHandler(key, factory, ttl) as Promise<T>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return this.getFromMemoryCache(key, factory, ttl);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
private async getFromMemoryCache<T>(
|
|
35
|
+
key: string,
|
|
36
|
+
factory: () => Promise<T>,
|
|
37
|
+
ttl: number
|
|
38
|
+
): Promise<T> {
|
|
39
|
+
const now = Date.now();
|
|
40
|
+
const cached = this.memoryCache.get(key);
|
|
41
|
+
|
|
42
|
+
if (this.isCacheValid(cached, now)) {
|
|
43
|
+
return cached!.value as T;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const value = await factory();
|
|
47
|
+
this.setInMemoryCache(key, value, ttl);
|
|
48
|
+
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private isCacheValid(entry: CacheEntry | undefined, now: number): boolean {
|
|
53
|
+
return entry !== undefined && entry.expires > now;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private setInMemoryCache(key: string, value: any, ttl: number): void {
|
|
57
|
+
const expires = Date.now() + ttl * 1000;
|
|
58
|
+
this.memoryCache.set(key, { value, expires });
|
|
59
|
+
|
|
60
|
+
this.scheduleCleanup();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private scheduleCleanup(): void {
|
|
64
|
+
if (this.cleanupInterval) return;
|
|
65
|
+
|
|
66
|
+
this.cleanupInterval = setInterval(() => {
|
|
67
|
+
this.cleanupExpired();
|
|
68
|
+
}, 60000); // Clean up every minute
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private cleanupExpired(): void {
|
|
72
|
+
const now = Date.now();
|
|
73
|
+
for (const [key, entry] of this.memoryCache.entries()) {
|
|
74
|
+
if (entry.expires <= now) {
|
|
75
|
+
this.memoryCache.delete(key);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (this.memoryCache.size === 0 && this.cleanupInterval) {
|
|
80
|
+
clearInterval(this.cleanupInterval);
|
|
81
|
+
this.cleanupInterval = null;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
clear(): void {
|
|
86
|
+
this.memoryCache.clear();
|
|
87
|
+
if (this.cleanupInterval) {
|
|
88
|
+
clearInterval(this.cleanupInterval);
|
|
89
|
+
this.cleanupInterval = null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async set<T = GetCacheType<TTypes>>(
|
|
94
|
+
key: string,
|
|
95
|
+
value: T,
|
|
96
|
+
ttl: number = DEFAULT_CONFIG.CACHE_TTL
|
|
97
|
+
): Promise<void> {
|
|
98
|
+
if (ttl <= 0) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (this.cacheHandler) {
|
|
103
|
+
// Custom cache handler can implement its own set logic
|
|
104
|
+
await this.cacheHandler(key, async () => value, ttl);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
this.setInMemoryCache(key, value, ttl);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
delete(key: string): boolean {
|
|
112
|
+
return this.memoryCache.delete(key);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
has(key: string): boolean {
|
|
116
|
+
const entry = this.memoryCache.get(key);
|
|
117
|
+
if (!entry) return false;
|
|
118
|
+
|
|
119
|
+
if (entry.expires <= Date.now()) {
|
|
120
|
+
this.memoryCache.delete(key);
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
generateKey(request: Request, options?: { authUser?: any }): string {
|
|
128
|
+
const url = new URL(request.url);
|
|
129
|
+
const parts = [request.method, url.pathname, url.search, options?.authUser?.id || 'anonymous'];
|
|
130
|
+
|
|
131
|
+
return parts.join(':');
|
|
132
|
+
}
|
|
133
|
+
}
|
package/src/cli/index.ts
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { parseArgs } from 'node:util';
|
|
5
|
+
import vector from '../core/vector';
|
|
6
|
+
|
|
7
|
+
const { values, positionals } = parseArgs({
|
|
8
|
+
args: Bun.argv.slice(2),
|
|
9
|
+
options: {
|
|
10
|
+
port: {
|
|
11
|
+
type: 'string',
|
|
12
|
+
short: 'p',
|
|
13
|
+
default: '3000',
|
|
14
|
+
},
|
|
15
|
+
host: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
short: 'h',
|
|
18
|
+
default: 'localhost',
|
|
19
|
+
},
|
|
20
|
+
routes: {
|
|
21
|
+
type: 'string',
|
|
22
|
+
short: 'r',
|
|
23
|
+
default: './routes',
|
|
24
|
+
},
|
|
25
|
+
watch: {
|
|
26
|
+
type: 'boolean',
|
|
27
|
+
short: 'w',
|
|
28
|
+
default: true,
|
|
29
|
+
},
|
|
30
|
+
cors: {
|
|
31
|
+
type: 'boolean',
|
|
32
|
+
default: true,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
strict: true,
|
|
36
|
+
allowPositionals: true,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const command = positionals[0] || 'dev';
|
|
40
|
+
|
|
41
|
+
async function runDev() {
|
|
42
|
+
const isDev = command === 'dev';
|
|
43
|
+
console.log(`\n→ Starting Vector ${isDev ? 'development' : 'production'} server\n`);
|
|
44
|
+
|
|
45
|
+
const config = {
|
|
46
|
+
port: Number.parseInt(values.port as string),
|
|
47
|
+
hostname: values.host as string,
|
|
48
|
+
routesDir: values.routes as string,
|
|
49
|
+
development: isDev,
|
|
50
|
+
autoDiscover: true,
|
|
51
|
+
cors: values.cors
|
|
52
|
+
? {
|
|
53
|
+
origin: '*',
|
|
54
|
+
credentials: true,
|
|
55
|
+
allowHeaders: 'Content-Type, Authorization',
|
|
56
|
+
allowMethods: 'GET, POST, PUT, PATCH, DELETE, OPTIONS',
|
|
57
|
+
exposeHeaders: 'Authorization',
|
|
58
|
+
maxAge: 86400,
|
|
59
|
+
}
|
|
60
|
+
: undefined,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
const userConfigPath = join(process.cwd(), 'vector.config.ts');
|
|
65
|
+
try {
|
|
66
|
+
const userConfig = await import(userConfigPath);
|
|
67
|
+
if (userConfig.default) {
|
|
68
|
+
Object.assign(config, userConfig.default);
|
|
69
|
+
}
|
|
70
|
+
} catch {
|
|
71
|
+
// No user config file, use defaults
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
await vector.serve(config);
|
|
75
|
+
|
|
76
|
+
const gray = '\x1b[90m';
|
|
77
|
+
const reset = '\x1b[0m';
|
|
78
|
+
const cyan = '\x1b[36m';
|
|
79
|
+
const green = '\x1b[32m';
|
|
80
|
+
|
|
81
|
+
console.log(` ${gray}Routes${reset} ${config.routesDir}`);
|
|
82
|
+
if (isDev && values.watch) {
|
|
83
|
+
console.log(` ${gray}Watching${reset} Enabled`);
|
|
84
|
+
}
|
|
85
|
+
console.log(` ${gray}CORS${reset} ${values.cors ? 'Enabled' : 'Disabled'}`);
|
|
86
|
+
console.log(` ${gray}Mode${reset} ${isDev ? 'Development' : 'Production'}\n`);
|
|
87
|
+
console.log(
|
|
88
|
+
` ${green}Ready${reset} → ${cyan}http://${config.hostname}:${config.port}${reset}\n`
|
|
89
|
+
);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.error('[ERROR] Failed to start server:', error);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function runBuild() {
|
|
97
|
+
console.log('\n→ Building Vector application\n');
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
const { RouteScanner } = await import('../dev/route-scanner');
|
|
101
|
+
const { RouteGenerator } = await import('../dev/route-generator');
|
|
102
|
+
|
|
103
|
+
const scanner = new RouteScanner(values.routes as string);
|
|
104
|
+
const generator = new RouteGenerator();
|
|
105
|
+
|
|
106
|
+
const routes = await scanner.scan();
|
|
107
|
+
await generator.generate(routes);
|
|
108
|
+
|
|
109
|
+
console.log(` Generated ${routes.length} routes`);
|
|
110
|
+
|
|
111
|
+
const buildProcess = Bun.spawn([
|
|
112
|
+
'bun',
|
|
113
|
+
'build',
|
|
114
|
+
'src/index.ts',
|
|
115
|
+
'--outdir',
|
|
116
|
+
'dist',
|
|
117
|
+
'--minify',
|
|
118
|
+
]);
|
|
119
|
+
await buildProcess.exited;
|
|
120
|
+
|
|
121
|
+
console.log('\n ✓ Build complete\n');
|
|
122
|
+
} catch (error) {
|
|
123
|
+
console.error('[ERROR] Build failed:', error);
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
switch (command) {
|
|
129
|
+
case 'dev':
|
|
130
|
+
await runDev();
|
|
131
|
+
break;
|
|
132
|
+
case 'build':
|
|
133
|
+
await runBuild();
|
|
134
|
+
break;
|
|
135
|
+
case 'start':
|
|
136
|
+
process.env.NODE_ENV = 'production';
|
|
137
|
+
await runDev();
|
|
138
|
+
break;
|
|
139
|
+
default:
|
|
140
|
+
console.error(`Unknown command: ${command}`);
|
|
141
|
+
console.log(`
|
|
142
|
+
Usage: vector [command] [options]
|
|
143
|
+
|
|
144
|
+
Commands:
|
|
145
|
+
dev Start development server (default)
|
|
146
|
+
build Build for production
|
|
147
|
+
start Start production server
|
|
148
|
+
|
|
149
|
+
Options:
|
|
150
|
+
-p, --port <port> Port to listen on (default: 3000)
|
|
151
|
+
-h, --host <host> Hostname to bind to (default: localhost)
|
|
152
|
+
-r, --routes <dir> Routes directory (default: ./routes)
|
|
153
|
+
-w, --watch Watch for file changes (default: true)
|
|
154
|
+
--cors Enable CORS (default: true)
|
|
155
|
+
`);
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
export const HTTP_STATUS = {
|
|
2
|
+
// 2xx Success
|
|
3
|
+
OK: 200,
|
|
4
|
+
CREATED: 201,
|
|
5
|
+
ACCEPTED: 202,
|
|
6
|
+
NON_AUTHORITATIVE_INFORMATION: 203,
|
|
7
|
+
NO_CONTENT: 204,
|
|
8
|
+
RESET_CONTENT: 205,
|
|
9
|
+
PARTIAL_CONTENT: 206,
|
|
10
|
+
MULTI_STATUS: 207,
|
|
11
|
+
ALREADY_REPORTED: 208,
|
|
12
|
+
IM_USED: 226,
|
|
13
|
+
|
|
14
|
+
// 3xx Redirection
|
|
15
|
+
MULTIPLE_CHOICES: 300,
|
|
16
|
+
MOVED_PERMANENTLY: 301,
|
|
17
|
+
FOUND: 302,
|
|
18
|
+
SEE_OTHER: 303,
|
|
19
|
+
NOT_MODIFIED: 304,
|
|
20
|
+
USE_PROXY: 305,
|
|
21
|
+
TEMPORARY_REDIRECT: 307,
|
|
22
|
+
PERMANENT_REDIRECT: 308,
|
|
23
|
+
|
|
24
|
+
// 4xx Client Errors
|
|
25
|
+
BAD_REQUEST: 400,
|
|
26
|
+
UNAUTHORIZED: 401,
|
|
27
|
+
PAYMENT_REQUIRED: 402,
|
|
28
|
+
FORBIDDEN: 403,
|
|
29
|
+
NOT_FOUND: 404,
|
|
30
|
+
METHOD_NOT_ALLOWED: 405,
|
|
31
|
+
NOT_ACCEPTABLE: 406,
|
|
32
|
+
PROXY_AUTHENTICATION_REQUIRED: 407,
|
|
33
|
+
REQUEST_TIMEOUT: 408,
|
|
34
|
+
CONFLICT: 409,
|
|
35
|
+
GONE: 410,
|
|
36
|
+
LENGTH_REQUIRED: 411,
|
|
37
|
+
PRECONDITION_FAILED: 412,
|
|
38
|
+
PAYLOAD_TOO_LARGE: 413,
|
|
39
|
+
URI_TOO_LONG: 414,
|
|
40
|
+
UNSUPPORTED_MEDIA_TYPE: 415,
|
|
41
|
+
RANGE_NOT_SATISFIABLE: 416,
|
|
42
|
+
EXPECTATION_FAILED: 417,
|
|
43
|
+
IM_A_TEAPOT: 418,
|
|
44
|
+
MISDIRECTED_REQUEST: 421,
|
|
45
|
+
UNPROCESSABLE_ENTITY: 422,
|
|
46
|
+
LOCKED: 423,
|
|
47
|
+
FAILED_DEPENDENCY: 424,
|
|
48
|
+
TOO_EARLY: 425,
|
|
49
|
+
UPGRADE_REQUIRED: 426,
|
|
50
|
+
PRECONDITION_REQUIRED: 428,
|
|
51
|
+
TOO_MANY_REQUESTS: 429,
|
|
52
|
+
REQUEST_HEADER_FIELDS_TOO_LARGE: 431,
|
|
53
|
+
UNAVAILABLE_FOR_LEGAL_REASONS: 451,
|
|
54
|
+
|
|
55
|
+
// 5xx Server Errors
|
|
56
|
+
INTERNAL_SERVER_ERROR: 500,
|
|
57
|
+
NOT_IMPLEMENTED: 501,
|
|
58
|
+
BAD_GATEWAY: 502,
|
|
59
|
+
SERVICE_UNAVAILABLE: 503,
|
|
60
|
+
GATEWAY_TIMEOUT: 504,
|
|
61
|
+
HTTP_VERSION_NOT_SUPPORTED: 505,
|
|
62
|
+
VARIANT_ALSO_NEGOTIATES: 506,
|
|
63
|
+
INSUFFICIENT_STORAGE: 507,
|
|
64
|
+
LOOP_DETECTED: 508,
|
|
65
|
+
NOT_EXTENDED: 510,
|
|
66
|
+
NETWORK_AUTHENTICATION_REQUIRED: 511,
|
|
67
|
+
} as const;
|
|
68
|
+
|
|
69
|
+
export const DEFAULT_CONFIG = {
|
|
70
|
+
PORT: 3000,
|
|
71
|
+
HOSTNAME: 'localhost',
|
|
72
|
+
ROUTES_DIR: './routes',
|
|
73
|
+
CACHE_TTL: 0,
|
|
74
|
+
CORS_MAX_AGE: 86400,
|
|
75
|
+
} as const;
|
|
76
|
+
|
|
77
|
+
export const CONTENT_TYPES = {
|
|
78
|
+
JSON: 'application/json',
|
|
79
|
+
TEXT: 'text/plain',
|
|
80
|
+
HTML: 'text/html',
|
|
81
|
+
FORM_URLENCODED: 'application/x-www-form-urlencoded',
|
|
82
|
+
MULTIPART: 'multipart/form-data',
|
|
83
|
+
} as const;
|
|
84
|
+
|
|
85
|
+
export const HTTP_METHODS = {
|
|
86
|
+
GET: 'GET',
|
|
87
|
+
POST: 'POST',
|
|
88
|
+
PUT: 'PUT',
|
|
89
|
+
PATCH: 'PATCH',
|
|
90
|
+
DELETE: 'DELETE',
|
|
91
|
+
OPTIONS: 'OPTIONS',
|
|
92
|
+
HEAD: 'HEAD',
|
|
93
|
+
} as const;
|