vector-framework 0.9.4 → 0.9.5
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/README.md +9 -5
- package/dist/cli/index.js +4 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/cli.js +13 -98
- package/dist/core/config-loader.d.ts +2 -3
- package/dist/core/config-loader.d.ts.map +1 -1
- package/dist/core/config-loader.js +27 -118
- package/dist/core/config-loader.js.map +1 -1
- package/dist/core/vector.d.ts +7 -7
- package/dist/core/vector.d.ts.map +1 -1
- package/dist/core/vector.js +25 -26
- package/dist/core/vector.js.map +1 -1
- package/dist/dev/route-generator.d.ts.map +1 -1
- package/dist/dev/route-generator.js +0 -1
- package/dist/dev/route-generator.js.map +1 -1
- package/dist/dev/route-scanner.d.ts.map +1 -1
- package/dist/dev/route-scanner.js +0 -6
- package/dist/dev/route-scanner.js.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.mjs +3 -3
- package/dist/types/index.d.ts +5 -18
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cli/index.ts +4 -4
- package/src/core/config-loader.ts +36 -130
- package/src/core/vector.ts +40 -29
- package/src/dev/route-generator.ts +0 -1
- package/src/dev/route-scanner.ts +0 -6
- package/src/types/index.ts +8 -27
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { existsSync } from
|
|
2
|
-
import { resolve } from
|
|
3
|
-
import { toFileUrl } from
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { toFileUrl } from "../utils/path";
|
|
4
4
|
import type {
|
|
5
|
-
AfterMiddlewareHandler,
|
|
6
|
-
BeforeMiddlewareHandler,
|
|
7
5
|
CacheHandler,
|
|
8
6
|
CorsOptions,
|
|
9
7
|
DefaultVectorTypes,
|
|
@@ -11,14 +9,14 @@ import type {
|
|
|
11
9
|
VectorConfig,
|
|
12
10
|
VectorConfigSchema,
|
|
13
11
|
VectorTypes,
|
|
14
|
-
} from
|
|
12
|
+
} from "../types";
|
|
15
13
|
|
|
16
14
|
export class ConfigLoader<TTypes extends VectorTypes = DefaultVectorTypes> {
|
|
17
15
|
private configPath: string;
|
|
18
16
|
private config: VectorConfigSchema<TTypes> | null = null;
|
|
19
|
-
private configSource:
|
|
17
|
+
private configSource: "user" | "default" = "default";
|
|
20
18
|
|
|
21
|
-
constructor(configPath =
|
|
19
|
+
constructor(configPath = "vector.config.ts") {
|
|
22
20
|
// Always resolve from the current working directory (user's project)
|
|
23
21
|
this.configPath = resolve(process.cwd(), configPath);
|
|
24
22
|
}
|
|
@@ -28,69 +26,62 @@ export class ConfigLoader<TTypes extends VectorTypes = DefaultVectorTypes> {
|
|
|
28
26
|
if (existsSync(this.configPath)) {
|
|
29
27
|
try {
|
|
30
28
|
console.log(`→ Loading config from: ${this.configPath}`);
|
|
31
|
-
|
|
29
|
+
|
|
32
30
|
// Use explicit file:// URL to ensure correct resolution
|
|
33
31
|
const userConfigPath = toFileUrl(this.configPath);
|
|
34
32
|
const userConfig = await import(userConfigPath);
|
|
35
33
|
this.config = userConfig.default || userConfig;
|
|
36
|
-
this.configSource =
|
|
37
|
-
|
|
38
|
-
console.log(
|
|
34
|
+
this.configSource = "user";
|
|
35
|
+
|
|
36
|
+
console.log(" ✓ User config loaded successfully");
|
|
39
37
|
} catch (error) {
|
|
40
|
-
console.error(
|
|
41
|
-
|
|
38
|
+
console.error(
|
|
39
|
+
` ✗ Failed to load config from ${this.configPath}:`,
|
|
40
|
+
error
|
|
41
|
+
);
|
|
42
|
+
console.log(" → Using default configuration");
|
|
42
43
|
this.config = {};
|
|
43
44
|
}
|
|
44
45
|
} else {
|
|
45
46
|
// Config file doesn't exist, use defaults
|
|
46
47
|
console.log(` → No config file found at: ${this.configPath}`);
|
|
47
|
-
console.log(
|
|
48
|
+
console.log(" → Using default configuration");
|
|
48
49
|
this.config = {};
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
// Convert new config schema to legacy VectorConfig format
|
|
52
53
|
return await this.buildLegacyConfig();
|
|
53
54
|
}
|
|
54
|
-
|
|
55
|
-
getConfigSource():
|
|
55
|
+
|
|
56
|
+
getConfigSource(): "user" | "default" {
|
|
56
57
|
return this.configSource;
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
private async buildLegacyConfig(): Promise<VectorConfig<TTypes>> {
|
|
60
61
|
const config: VectorConfig<TTypes> = {};
|
|
61
62
|
|
|
62
|
-
//
|
|
63
|
-
if (this.config
|
|
64
|
-
config.port = this.config.
|
|
65
|
-
config.hostname = this.config.
|
|
66
|
-
config.reusePort = this.config.
|
|
67
|
-
config.development = this.config.
|
|
63
|
+
// Direct mapping - schemas are now the same (flat)
|
|
64
|
+
if (this.config) {
|
|
65
|
+
config.port = this.config.port;
|
|
66
|
+
config.hostname = this.config.hostname;
|
|
67
|
+
config.reusePort = this.config.reusePort;
|
|
68
|
+
config.development = this.config.development;
|
|
69
|
+
config.routesDir = this.config.routesDir || "./routes";
|
|
68
70
|
}
|
|
69
71
|
|
|
70
|
-
//
|
|
71
|
-
|
|
72
|
-
// New format: { routes: { dir: string } }
|
|
73
|
-
config.routesDir = this.config.routes.dir || './routes';
|
|
74
|
-
config.autoDiscover = this.config.routes.autoDiscover !== false;
|
|
75
|
-
} else if ((this.config as any)?.routesDir) {
|
|
76
|
-
// Legacy format: { routesDir: string }
|
|
77
|
-
config.routesDir = (this.config as any).routesDir;
|
|
78
|
-
config.autoDiscover = (this.config as any).autoDiscover !== false;
|
|
79
|
-
} else {
|
|
80
|
-
config.routesDir = './routes';
|
|
81
|
-
config.autoDiscover = true;
|
|
82
|
-
}
|
|
72
|
+
// Always auto-discover routes
|
|
73
|
+
config.autoDiscover = true;
|
|
83
74
|
|
|
84
75
|
// CORS configuration
|
|
85
76
|
if (this.config?.cors) {
|
|
86
|
-
if (typeof this.config.cors ===
|
|
77
|
+
if (typeof this.config.cors === "boolean") {
|
|
87
78
|
config.cors = this.config.cors
|
|
88
79
|
? {
|
|
89
|
-
origin:
|
|
80
|
+
origin: "*",
|
|
90
81
|
credentials: true,
|
|
91
|
-
allowHeaders:
|
|
92
|
-
allowMethods:
|
|
93
|
-
exposeHeaders:
|
|
82
|
+
allowHeaders: "Content-Type, Authorization",
|
|
83
|
+
allowMethods: "GET, POST, PUT, PATCH, DELETE, OPTIONS",
|
|
84
|
+
exposeHeaders: "Authorization",
|
|
94
85
|
maxAge: 86400,
|
|
95
86
|
}
|
|
96
87
|
: undefined;
|
|
@@ -99,112 +90,27 @@ export class ConfigLoader<TTypes extends VectorTypes = DefaultVectorTypes> {
|
|
|
99
90
|
}
|
|
100
91
|
}
|
|
101
92
|
|
|
102
|
-
//
|
|
93
|
+
// Middleware mapping (VectorConfig uses 'finally' instead of 'after')
|
|
103
94
|
if (this.config?.before) {
|
|
104
|
-
// Direct functions provided
|
|
105
95
|
config.before = this.config.before;
|
|
106
|
-
} else if (this.config?.middleware?.before) {
|
|
107
|
-
// File paths provided (legacy)
|
|
108
|
-
config.before = await this.loadMiddleware<BeforeMiddlewareHandler<TTypes>>(
|
|
109
|
-
this.config.middleware.before
|
|
110
|
-
);
|
|
111
96
|
}
|
|
112
97
|
|
|
113
98
|
if (this.config?.after) {
|
|
114
|
-
// Direct functions provided
|
|
115
99
|
config.finally = this.config.after;
|
|
116
|
-
} else if (this.config?.middleware?.after) {
|
|
117
|
-
// File paths provided (legacy)
|
|
118
|
-
config.finally = await this.loadMiddleware<AfterMiddlewareHandler<TTypes>>(
|
|
119
|
-
this.config.middleware.after
|
|
120
|
-
);
|
|
121
100
|
}
|
|
122
101
|
|
|
123
102
|
return config;
|
|
124
103
|
}
|
|
125
104
|
|
|
126
|
-
private async loadMiddleware<T>(paths: string[]): Promise<T[]> {
|
|
127
|
-
const middleware: T[] = [];
|
|
128
|
-
|
|
129
|
-
for (const path of paths) {
|
|
130
|
-
try {
|
|
131
|
-
const modulePath = resolve(process.cwd(), path);
|
|
132
|
-
const importPath = toFileUrl(modulePath);
|
|
133
|
-
const module = await import(importPath);
|
|
134
|
-
const handler = module.default || module;
|
|
135
|
-
|
|
136
|
-
if (typeof handler === 'function') {
|
|
137
|
-
middleware.push(handler as T);
|
|
138
|
-
} else {
|
|
139
|
-
console.warn(`Middleware at ${path} does not export a function`);
|
|
140
|
-
}
|
|
141
|
-
} catch (error) {
|
|
142
|
-
console.error(`Failed to load middleware from ${path}:`, error);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return middleware;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
105
|
async loadAuthHandler(): Promise<ProtectedHandler<TTypes> | null> {
|
|
150
|
-
|
|
151
|
-
if (this.config?.auth) {
|
|
152
|
-
return this.config.auth;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
// File path provided (legacy)
|
|
156
|
-
if (!this.config?.handlers?.auth) {
|
|
157
|
-
return null;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
try {
|
|
161
|
-
const modulePath = resolve(process.cwd(), this.config.handlers.auth);
|
|
162
|
-
const importPath = toFileUrl(modulePath);
|
|
163
|
-
const module = await import(importPath);
|
|
164
|
-
const handler = module.default || module;
|
|
165
|
-
|
|
166
|
-
if (typeof handler === 'function') {
|
|
167
|
-
return handler as ProtectedHandler<TTypes>;
|
|
168
|
-
} else {
|
|
169
|
-
console.warn(`Auth handler at ${this.config.handlers.auth} does not export a function`);
|
|
170
|
-
return null;
|
|
171
|
-
}
|
|
172
|
-
} catch (error) {
|
|
173
|
-
console.error(`Failed to load auth handler from ${this.config.handlers.auth}:`, error);
|
|
174
|
-
return null;
|
|
175
|
-
}
|
|
106
|
+
return this.config?.auth || null;
|
|
176
107
|
}
|
|
177
108
|
|
|
178
109
|
async loadCacheHandler(): Promise<CacheHandler | null> {
|
|
179
|
-
|
|
180
|
-
if (this.config?.cache) {
|
|
181
|
-
return this.config.cache;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// File path provided (legacy)
|
|
185
|
-
if (!this.config?.handlers?.cache) {
|
|
186
|
-
return null;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
try {
|
|
190
|
-
const modulePath = resolve(process.cwd(), this.config.handlers.cache);
|
|
191
|
-
const importPath = toFileUrl(modulePath);
|
|
192
|
-
const module = await import(importPath);
|
|
193
|
-
const handler = module.default || module;
|
|
194
|
-
|
|
195
|
-
if (typeof handler === 'function') {
|
|
196
|
-
return handler as CacheHandler;
|
|
197
|
-
} else {
|
|
198
|
-
console.warn(`Cache handler at ${this.config.handlers.cache} does not export a function`);
|
|
199
|
-
return null;
|
|
200
|
-
}
|
|
201
|
-
} catch (error) {
|
|
202
|
-
console.error(`Failed to load cache handler from ${this.config.handlers.cache}:`, error);
|
|
203
|
-
return null;
|
|
204
|
-
}
|
|
110
|
+
return this.config?.cache || null;
|
|
205
111
|
}
|
|
206
112
|
|
|
207
113
|
getConfig(): VectorConfigSchema<TTypes> | null {
|
|
208
114
|
return this.config;
|
|
209
115
|
}
|
|
210
|
-
}
|
|
116
|
+
}
|
package/src/core/vector.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { Server } from
|
|
2
|
-
import type { RouteEntry } from
|
|
3
|
-
import { AuthManager } from
|
|
4
|
-
import { CacheManager } from
|
|
5
|
-
import { RouteGenerator } from
|
|
6
|
-
import { RouteScanner } from
|
|
7
|
-
import { MiddlewareManager } from
|
|
8
|
-
import { toFileUrl } from
|
|
1
|
+
import type { Server } from "bun";
|
|
2
|
+
import type { RouteEntry } from "itty-router";
|
|
3
|
+
import { AuthManager } from "../auth/protected";
|
|
4
|
+
import { CacheManager } from "../cache/manager";
|
|
5
|
+
import { RouteGenerator } from "../dev/route-generator";
|
|
6
|
+
import { RouteScanner } from "../dev/route-scanner";
|
|
7
|
+
import { MiddlewareManager } from "../middleware/manager";
|
|
8
|
+
import { toFileUrl } from "../utils/path";
|
|
9
9
|
import type {
|
|
10
10
|
CacheHandler,
|
|
11
11
|
DefaultVectorTypes,
|
|
@@ -14,9 +14,9 @@ import type {
|
|
|
14
14
|
RouteOptions,
|
|
15
15
|
VectorConfig,
|
|
16
16
|
VectorTypes,
|
|
17
|
-
} from
|
|
18
|
-
import { VectorRouter } from
|
|
19
|
-
import { VectorServer } from
|
|
17
|
+
} from "../types";
|
|
18
|
+
import { VectorRouter } from "./router";
|
|
19
|
+
import { VectorServer } from "./server";
|
|
20
20
|
|
|
21
21
|
// Internal-only class - not exposed to users
|
|
22
22
|
export class Vector<TTypes extends VectorTypes = DefaultVectorTypes> {
|
|
@@ -72,7 +72,10 @@ export class Vector<TTypes extends VectorTypes = DefaultVectorTypes> {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
// Internal method to add route
|
|
75
|
-
addRoute(
|
|
75
|
+
addRoute(
|
|
76
|
+
options: RouteOptions<TTypes>,
|
|
77
|
+
handler: RouteHandler<TTypes>
|
|
78
|
+
): RouteEntry {
|
|
76
79
|
return this.router.route(options, handler);
|
|
77
80
|
}
|
|
78
81
|
|
|
@@ -102,7 +105,7 @@ export class Vector<TTypes extends VectorTypes = DefaultVectorTypes> {
|
|
|
102
105
|
}
|
|
103
106
|
|
|
104
107
|
private async discoverRoutes() {
|
|
105
|
-
const routesDir = this.config.routesDir ||
|
|
108
|
+
const routesDir = this.config.routesDir || "./routes";
|
|
106
109
|
|
|
107
110
|
// Always create a new RouteScanner with the current config's routesDir
|
|
108
111
|
// to ensure we're using the correct path from the user's config
|
|
@@ -125,7 +128,8 @@ export class Vector<TTypes extends VectorTypes = DefaultVectorTypes> {
|
|
|
125
128
|
const importPath = toFileUrl(route.path);
|
|
126
129
|
|
|
127
130
|
const module = await import(importPath);
|
|
128
|
-
const exported =
|
|
131
|
+
const exported =
|
|
132
|
+
route.name === "default" ? module.default : module[route.name];
|
|
129
133
|
|
|
130
134
|
if (exported) {
|
|
131
135
|
if (this.isRouteDefinition(exported)) {
|
|
@@ -137,36 +141,41 @@ export class Vector<TTypes extends VectorTypes = DefaultVectorTypes> {
|
|
|
137
141
|
// Legacy support for direct RouteEntry (won't have middleware)
|
|
138
142
|
this.router.addRoute(exported as RouteEntry);
|
|
139
143
|
this.logRouteLoaded(exported as RouteEntry);
|
|
140
|
-
} else if (typeof exported ===
|
|
144
|
+
} else if (typeof exported === "function") {
|
|
141
145
|
this.router.route(route.options as any, exported);
|
|
142
146
|
this.logRouteLoaded(route.options);
|
|
143
147
|
}
|
|
144
148
|
}
|
|
145
149
|
} catch (error) {
|
|
146
|
-
console.error(
|
|
150
|
+
console.error(
|
|
151
|
+
`Failed to load route ${route.name} from ${route.path}:`,
|
|
152
|
+
error
|
|
153
|
+
);
|
|
147
154
|
}
|
|
148
155
|
}
|
|
149
156
|
|
|
150
157
|
// Ensure routes are properly sorted after loading all
|
|
151
158
|
this.router.sortRoutes();
|
|
152
|
-
console.log(`✅ Loaded ${routes.length} routes from ${routesDir}`);
|
|
153
159
|
}
|
|
154
160
|
} catch (error) {
|
|
155
|
-
if (
|
|
156
|
-
|
|
161
|
+
if (
|
|
162
|
+
(error as any).code !== "ENOENT" &&
|
|
163
|
+
(error as any).code !== "ENOTDIR"
|
|
164
|
+
) {
|
|
165
|
+
console.error("Failed to discover routes:", error);
|
|
157
166
|
}
|
|
158
167
|
}
|
|
159
168
|
}
|
|
160
169
|
|
|
161
170
|
async loadRoute(routeModule: any) {
|
|
162
|
-
if (typeof routeModule ===
|
|
171
|
+
if (typeof routeModule === "function") {
|
|
163
172
|
const routeEntry = routeModule();
|
|
164
173
|
if (Array.isArray(routeEntry)) {
|
|
165
174
|
this.router.addRoute(routeEntry as RouteEntry);
|
|
166
175
|
}
|
|
167
|
-
} else if (routeModule && typeof routeModule ===
|
|
176
|
+
} else if (routeModule && typeof routeModule === "object") {
|
|
168
177
|
for (const [, value] of Object.entries(routeModule)) {
|
|
169
|
-
if (typeof value ===
|
|
178
|
+
if (typeof value === "function") {
|
|
170
179
|
const routeEntry = (value as any)();
|
|
171
180
|
if (Array.isArray(routeEntry)) {
|
|
172
181
|
this.router.addRoute(routeEntry as RouteEntry);
|
|
@@ -181,15 +190,17 @@ export class Vector<TTypes extends VectorTypes = DefaultVectorTypes> {
|
|
|
181
190
|
}
|
|
182
191
|
|
|
183
192
|
private isRouteDefinition(value: any): boolean {
|
|
184
|
-
return
|
|
193
|
+
return (
|
|
194
|
+
value &&
|
|
195
|
+
typeof value === "object" &&
|
|
196
|
+
"entry" in value &&
|
|
197
|
+
"options" in value &&
|
|
198
|
+
"handler" in value
|
|
199
|
+
);
|
|
185
200
|
}
|
|
186
201
|
|
|
187
|
-
private logRouteLoaded(
|
|
188
|
-
|
|
189
|
-
console.log(` ✓ Loaded route: ${route[0]} ${route[3] || route[1]}`);
|
|
190
|
-
} else {
|
|
191
|
-
console.log(` ✓ Loaded route: ${route.method} ${route.path}`);
|
|
192
|
-
}
|
|
202
|
+
private logRouteLoaded(_: RouteEntry | RouteOptions): void {
|
|
203
|
+
// Silent - no logging
|
|
193
204
|
}
|
|
194
205
|
|
|
195
206
|
stop(): void {
|
package/src/dev/route-scanner.ts
CHANGED
|
@@ -15,17 +15,11 @@ export class RouteScanner {
|
|
|
15
15
|
|
|
16
16
|
// Check if routes directory exists before attempting to scan
|
|
17
17
|
if (!existsSync(this.routesDir)) {
|
|
18
|
-
console.log(` → Routes directory not found: ${this.routesDir}`);
|
|
19
|
-
console.log(' → No routes will be auto-discovered');
|
|
20
18
|
return [];
|
|
21
19
|
}
|
|
22
20
|
|
|
23
21
|
try {
|
|
24
|
-
console.log(` → Scanning routes from: ${this.routesDir}`);
|
|
25
22
|
await this.scanDirectory(this.routesDir, routes);
|
|
26
|
-
if (routes.length > 0) {
|
|
27
|
-
console.log(` ✓ Found ${routes.length} route${routes.length === 1 ? '' : 's'}`);
|
|
28
|
-
}
|
|
29
23
|
} catch (error) {
|
|
30
24
|
if ((error as any).code === 'ENOENT') {
|
|
31
25
|
console.warn(` ✗ Routes directory not accessible: ${this.routesDir}`);
|
package/src/types/index.ts
CHANGED
|
@@ -85,39 +85,20 @@ export interface VectorConfig<TTypes extends VectorTypes = DefaultVectorTypes> {
|
|
|
85
85
|
autoDiscover?: boolean;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
// New config-driven schema
|
|
88
|
+
// New config-driven schema - flat structure
|
|
89
89
|
export interface VectorConfigSchema<TTypes extends VectorTypes = DefaultVectorTypes> {
|
|
90
90
|
// Server configuration
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
// Routes configuration
|
|
99
|
-
routes?: {
|
|
100
|
-
dir?: string;
|
|
101
|
-
autoDiscover?: boolean;
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
// Middleware configuration - supports both file paths and direct functions
|
|
105
|
-
middleware?: {
|
|
106
|
-
before?: string[];
|
|
107
|
-
after?: string[];
|
|
108
|
-
};
|
|
91
|
+
port?: number;
|
|
92
|
+
hostname?: string;
|
|
93
|
+
reusePort?: boolean;
|
|
94
|
+
development?: boolean;
|
|
95
|
+
routesDir?: string;
|
|
109
96
|
|
|
110
|
-
//
|
|
97
|
+
// Middleware functions
|
|
111
98
|
before?: BeforeMiddlewareHandler<TTypes>[];
|
|
112
99
|
after?: AfterMiddlewareHandler<TTypes>[];
|
|
113
100
|
|
|
114
|
-
// Handler
|
|
115
|
-
handlers?: {
|
|
116
|
-
auth?: string;
|
|
117
|
-
cache?: string;
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
// Direct handler functions (preferred approach)
|
|
101
|
+
// Handler functions
|
|
121
102
|
auth?: ProtectedHandler<TTypes>;
|
|
122
103
|
cache?: CacheHandler;
|
|
123
104
|
|