vector-framework 0.9.9 → 1.1.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 (54) hide show
  1. package/README.md +6 -5
  2. package/dist/cache/manager.d.ts +5 -2
  3. package/dist/cache/manager.d.ts.map +1 -1
  4. package/dist/cache/manager.js +21 -7
  5. package/dist/cache/manager.js.map +1 -1
  6. package/dist/cli/index.js +76 -98
  7. package/dist/cli/index.js.map +1 -1
  8. package/dist/cli.js +134 -69
  9. package/dist/core/config-loader.d.ts +2 -2
  10. package/dist/core/config-loader.d.ts.map +1 -1
  11. package/dist/core/config-loader.js +16 -21
  12. package/dist/core/config-loader.js.map +1 -1
  13. package/dist/core/router.d.ts +2 -0
  14. package/dist/core/router.d.ts.map +1 -1
  15. package/dist/core/router.js +52 -16
  16. package/dist/core/router.js.map +1 -1
  17. package/dist/core/server.d.ts +4 -3
  18. package/dist/core/server.d.ts.map +1 -1
  19. package/dist/core/server.js +40 -20
  20. package/dist/core/server.js.map +1 -1
  21. package/dist/core/vector.d.ts +7 -7
  22. package/dist/core/vector.d.ts.map +1 -1
  23. package/dist/core/vector.js +20 -21
  24. package/dist/core/vector.js.map +1 -1
  25. package/dist/dev/route-scanner.d.ts +1 -1
  26. package/dist/dev/route-scanner.d.ts.map +1 -1
  27. package/dist/dev/route-scanner.js +40 -42
  28. package/dist/dev/route-scanner.js.map +1 -1
  29. package/dist/http.d.ts +2 -2
  30. package/dist/http.d.ts.map +1 -1
  31. package/dist/http.js +70 -63
  32. package/dist/http.js.map +1 -1
  33. package/dist/index.d.ts +3 -3
  34. package/dist/index.js +4 -4
  35. package/dist/index.mjs +4 -4
  36. package/dist/middleware/manager.d.ts +1 -1
  37. package/dist/middleware/manager.d.ts.map +1 -1
  38. package/dist/middleware/manager.js.map +1 -1
  39. package/dist/utils/path.d.ts +1 -0
  40. package/dist/utils/path.d.ts.map +1 -1
  41. package/dist/utils/path.js +9 -3
  42. package/dist/utils/path.js.map +1 -1
  43. package/package.json +14 -9
  44. package/src/cache/manager.ts +23 -14
  45. package/src/cli/index.ts +83 -117
  46. package/src/core/config-loader.ts +19 -27
  47. package/src/core/router.ts +52 -18
  48. package/src/core/server.ts +43 -30
  49. package/src/core/vector.ts +25 -35
  50. package/src/dev/route-scanner.ts +41 -47
  51. package/src/http.ts +82 -112
  52. package/src/index.ts +3 -3
  53. package/src/middleware/manager.ts +4 -11
  54. package/src/utils/path.ts +13 -4
package/dist/cli.js CHANGED
@@ -161,7 +161,7 @@ var init_route_scanner = __esm(() => {
161
161
  isExcluded(filePath) {
162
162
  const relativePath = relative2(this.routesDir, filePath);
163
163
  for (const pattern of this.excludePatterns) {
164
- const regexPattern = pattern.replace(/\./g, "\\.").replace(/\*/g, "[^/]*").replace(/\*\*/g, ".*").replace(/\?/g, ".");
164
+ const regexPattern = pattern.replace(/\./g, "\\.").replace(/\*\*/g, "__GLOBSTAR__").replace(/\*/g, "[^/]*").replace(/__GLOBSTAR__/g, ".*").replace(/\?/g, ".");
165
165
  const regex = new RegExp(`^${regexPattern}$`);
166
166
  const filename = relativePath.split(sep).pop() || "";
167
167
  if (regex.test(relativePath) || regex.test(filename)) {
@@ -351,6 +351,7 @@ class CacheManager {
351
351
  cacheHandler = null;
352
352
  memoryCache = new Map;
353
353
  cleanupInterval = null;
354
+ inflight = new Map;
354
355
  setCacheHandler(handler) {
355
356
  this.cacheHandler = handler;
356
357
  }
@@ -369,9 +370,20 @@ class CacheManager {
369
370
  if (this.isCacheValid(cached, now)) {
370
371
  return cached.value;
371
372
  }
372
- const value = await factory();
373
- this.setInMemoryCache(key, value, ttl);
374
- return value;
373
+ if (this.inflight.has(key)) {
374
+ return await this.inflight.get(key);
375
+ }
376
+ const promise = (async () => {
377
+ const value = await factory();
378
+ this.setInMemoryCache(key, value, ttl);
379
+ return value;
380
+ })();
381
+ this.inflight.set(key, promise);
382
+ try {
383
+ return await promise;
384
+ } finally {
385
+ this.inflight.delete(key);
386
+ }
375
387
  }
376
388
  isCacheValid(entry, now) {
377
389
  return entry !== undefined && entry.expires > now;
@@ -431,12 +443,12 @@ class CacheManager {
431
443
  return true;
432
444
  }
433
445
  generateKey(request, options) {
434
- const url = new URL(request.url);
446
+ const url = request._parsedUrl ?? new URL(request.url);
435
447
  const parts = [
436
448
  request.method,
437
449
  url.pathname,
438
450
  url.search,
439
- options?.authUser?.id || "anonymous"
451
+ options?.authUser?.id != null ? String(options.authUser.id) : "anonymous"
440
452
  ];
441
453
  return parts.join(":");
442
454
  }
@@ -494,6 +506,9 @@ class MiddlewareManager {
494
506
  function toFileUrl(path) {
495
507
  return process.platform === "win32" ? `file:///${path.replace(/\\/g, "/")}` : path;
496
508
  }
509
+ function buildRouteRegex(path) {
510
+ return RegExp(`^${path.replace(/\/+(\/|$)/g, "$1").replace(/(\/?\.?):(\w+)\+/g, "($1(?<$2>[\\s\\S]+))").replace(/(\/?\.?):(\w+)/g, "($1(?<$2>[^$1/]+?))").replace(/\./g, "\\.").replace(/(\/?)\*/g, "($1.*)?")}/*$`);
511
+ }
497
512
 
498
513
  // node_modules/itty-router/index.mjs
499
514
  var r = (e = "text/plain; charset=utf-8", t) => (r2, o = {}) => {
@@ -508,9 +523,6 @@ var f = r("text/html");
508
523
  var u = r("image/jpeg");
509
524
  var h = r("image/png");
510
525
  var g = r("image/webp");
511
- var w = (e) => {
512
- e.cookies = (e.headers.get("Cookie") || "").split(/;\s*/).map((e2) => e2.split(/=(.+)/)).reduce((e2, [t, r2]) => r2 ? (e2[t] = r2, e2) : e2, {});
513
- };
514
526
  var y = (e = {}) => {
515
527
  const { origin: t = "*", credentials: r2 = false, allowMethods: o2 = "*", allowHeaders: a, exposeHeaders: s, maxAge: c } = e, n = (e2) => {
516
528
  const o3 = e2?.headers.get("origin");
@@ -537,8 +549,22 @@ var { preflight, corsify } = y({
537
549
  exposeHeaders: "Authorization",
538
550
  maxAge: 86400
539
551
  });
552
+ function hasBigInt(value, depth = 0) {
553
+ if (typeof value === "bigint")
554
+ return true;
555
+ if (depth > 4 || value === null || typeof value !== "object")
556
+ return false;
557
+ for (const v of Object.values(value)) {
558
+ if (hasBigInt(v, depth + 1))
559
+ return true;
560
+ }
561
+ return false;
562
+ }
540
563
  function stringifyData(data) {
541
- return JSON.stringify(data ?? null, (_key, value) => typeof value === "bigint" ? value.toString() : value);
564
+ const val = data ?? null;
565
+ if (!hasBigInt(val))
566
+ return JSON.stringify(val);
567
+ return JSON.stringify(val, (_key, value) => typeof value === "bigint" ? value.toString() : value);
542
568
  }
543
569
  function createErrorResponse(code, message, contentType) {
544
570
  const errorBody = {
@@ -608,12 +634,16 @@ class VectorRouter {
608
634
  authManager;
609
635
  cacheManager;
610
636
  routes = [];
637
+ specificityCache = new Map;
611
638
  constructor(middlewareManager, authManager, cacheManager) {
612
639
  this.middlewareManager = middlewareManager;
613
640
  this.authManager = authManager;
614
641
  this.cacheManager = cacheManager;
615
642
  }
616
643
  getRouteSpecificity(path) {
644
+ const cached = this.specificityCache.get(path);
645
+ if (cached !== undefined)
646
+ return cached;
617
647
  const STATIC_SEGMENT_WEIGHT = 1000;
618
648
  const PARAM_SEGMENT_WEIGHT = 10;
619
649
  const WILDCARD_WEIGHT = 1;
@@ -633,6 +663,7 @@ class VectorRouter {
633
663
  if (this.isExactPath(path)) {
634
664
  score += EXACT_MATCH_BONUS;
635
665
  }
666
+ this.specificityCache.set(path, score);
636
667
  return score;
637
668
  }
638
669
  isStaticSegment(segment) {
@@ -673,7 +704,7 @@ class VectorRouter {
673
704
  return routeEntry;
674
705
  }
675
706
  createRouteRegex(path) {
676
- return RegExp(`^${path.replace(/\/+(\/|$)/g, "$1").replace(/(\/?\.?):(\w+)\+/g, "($1(?<$2>*))").replace(/(\/?\.?):(\w+)/g, "($1(?<$2>[^$1/]+?))").replace(/\./g, "\\.").replace(/(\/?)\*/g, "($1.*)?")}/*$`);
707
+ return buildRouteRegex(path);
677
708
  }
678
709
  prepareRequest(request, options) {
679
710
  if (!request.context) {
@@ -689,7 +720,7 @@ class VectorRouter {
689
720
  request.metadata = options.metadata;
690
721
  }
691
722
  if (!request.query && request.url) {
692
- const url = new URL(request.url);
723
+ const url = request._parsedUrl ?? new URL(request.url);
693
724
  const query = {};
694
725
  for (const [key, value] of url.searchParams) {
695
726
  if (key in query) {
@@ -704,8 +735,30 @@ class VectorRouter {
704
735
  }
705
736
  request.query = query;
706
737
  }
707
- if (!request.cookies) {
708
- w(request);
738
+ if (!Object.getOwnPropertyDescriptor(request, "cookies")) {
739
+ Object.defineProperty(request, "cookies", {
740
+ get() {
741
+ const cookieHeader = this.headers.get("cookie") ?? "";
742
+ const cookies = {};
743
+ if (cookieHeader) {
744
+ for (const pair of cookieHeader.split(";")) {
745
+ const idx = pair.indexOf("=");
746
+ if (idx > 0) {
747
+ cookies[pair.slice(0, idx).trim()] = pair.slice(idx + 1).trim();
748
+ }
749
+ }
750
+ }
751
+ Object.defineProperty(this, "cookies", {
752
+ value: cookies,
753
+ writable: true,
754
+ configurable: true,
755
+ enumerable: true
756
+ });
757
+ return cookies;
758
+ },
759
+ configurable: true,
760
+ enumerable: true
761
+ });
709
762
  }
710
763
  }
711
764
  wrapHandler(options, handler) {
@@ -801,11 +854,23 @@ class VectorRouter {
801
854
  this.routes.push(routeEntry);
802
855
  this.sortRoutes();
803
856
  }
857
+ bulkAddRoutes(entries) {
858
+ for (const entry of entries) {
859
+ this.routes.push(entry);
860
+ }
861
+ this.sortRoutes();
862
+ }
804
863
  getRoutes() {
805
864
  return this.routes;
806
865
  }
807
866
  async handle(request) {
808
- const url = new URL(request.url);
867
+ let url;
868
+ try {
869
+ url = new URL(request.url);
870
+ } catch {
871
+ return APIError.badRequest("Malformed request URL");
872
+ }
873
+ request._parsedUrl = url;
809
874
  const pathname = url.pathname;
810
875
  for (const [method, regex, handlers, path] of this.routes) {
811
876
  if (request.method === "OPTIONS" || request.method === method) {
@@ -828,6 +893,7 @@ class VectorRouter {
828
893
  }
829
894
  clearRoutes() {
830
895
  this.routes = [];
896
+ this.specificityCache.clear();
831
897
  }
832
898
  }
833
899
 
@@ -837,12 +903,26 @@ class VectorServer {
837
903
  router;
838
904
  config;
839
905
  corsHandler;
906
+ corsHeaders = null;
840
907
  constructor(router, config) {
841
908
  this.router = router;
842
909
  this.config = config;
843
910
  if (config.cors) {
844
- const { preflight: preflight2, corsify: corsify2 } = y(this.normalizeCorsOptions(config.cors));
911
+ const opts = this.normalizeCorsOptions(config.cors);
912
+ const { preflight: preflight2, corsify: corsify2 } = y(opts);
845
913
  this.corsHandler = { preflight: preflight2, corsify: corsify2 };
914
+ if (typeof opts.origin === "string") {
915
+ this.corsHeaders = {
916
+ "access-control-allow-origin": opts.origin,
917
+ "access-control-allow-methods": opts.allowMethods,
918
+ "access-control-allow-headers": opts.allowHeaders,
919
+ "access-control-expose-headers": opts.exposeHeaders,
920
+ "access-control-max-age": String(opts.maxAge)
921
+ };
922
+ if (opts.credentials) {
923
+ this.corsHeaders["access-control-allow-credentials"] = "true";
924
+ }
925
+ }
846
926
  }
847
927
  }
848
928
  normalizeCorsOptions(options) {
@@ -864,7 +944,11 @@ class VectorServer {
864
944
  return this.corsHandler.preflight(request);
865
945
  }
866
946
  let response = await this.router.handle(request);
867
- if (this.corsHandler) {
947
+ if (this.corsHeaders) {
948
+ for (const [k, v] of Object.entries(this.corsHeaders)) {
949
+ response.headers.set(k, v);
950
+ }
951
+ } else if (this.corsHandler) {
868
952
  response = this.corsHandler.corsify(response, request);
869
953
  }
870
954
  return response;
@@ -888,7 +972,6 @@ class VectorServer {
888
972
  if (!this.server || !this.server.port) {
889
973
  throw new Error(`Failed to start server on ${hostname}:${port} - server object is invalid`);
890
974
  }
891
- console.log(`\u2192 Vector server running at http://${hostname}:${port}`);
892
975
  return this.server;
893
976
  } catch (error) {
894
977
  if (error.code === "EADDRINUSE" || error.message?.includes("address already in use")) {
@@ -1093,20 +1176,17 @@ class ConfigLoader {
1093
1176
  async load() {
1094
1177
  if (existsSync2(this.configPath)) {
1095
1178
  try {
1096
- console.log(`\u2192 Loading config from: ${this.configPath}`);
1097
1179
  const userConfigPath = toFileUrl(this.configPath);
1098
1180
  const userConfig = await import(userConfigPath);
1099
1181
  this.config = userConfig.default || userConfig;
1100
1182
  this.configSource = "user";
1101
- console.log(" \u2713 User config loaded successfully");
1102
1183
  } catch (error) {
1103
- console.error(` \u2717 Failed to load config from ${this.configPath}:`, error);
1104
- console.log(" \u2192 Using default configuration");
1184
+ const msg = error instanceof Error ? error.message : String(error);
1185
+ console.error(`[Vector] Failed to load config from ${this.configPath}: ${msg}`);
1186
+ console.error("[Vector] Server is using default configuration. Fix your config file and restart.");
1105
1187
  this.config = {};
1106
1188
  }
1107
1189
  } else {
1108
- console.log(` \u2192 No config file found at: ${this.configPath}`);
1109
- console.log(" \u2192 Using default configuration");
1110
1190
  this.config = {};
1111
1191
  }
1112
1192
  return await this.buildLegacyConfig();
@@ -1198,9 +1278,6 @@ var { values, positionals } = parseArgs({
1198
1278
  var command = positionals[0] || "dev";
1199
1279
  async function runDev() {
1200
1280
  const isDev = command === "dev";
1201
- console.log(`
1202
- \u2192 Starting Vector ${isDev ? "development" : "production"} server
1203
- `);
1204
1281
  let server = null;
1205
1282
  let vector = null;
1206
1283
  async function startServer() {
@@ -1212,7 +1289,6 @@ async function runDev() {
1212
1289
  const serverStartPromise = (async () => {
1213
1290
  const configLoader = new ConfigLoader(values.config);
1214
1291
  const config = await configLoader.load();
1215
- const configSource = configLoader.getConfigSource();
1216
1292
  config.port = config.port ?? Number.parseInt(values.port);
1217
1293
  config.hostname = config.hostname ?? values.host;
1218
1294
  config.routesDir = config.routesDir ?? values.routes;
@@ -1241,19 +1317,10 @@ async function runDev() {
1241
1317
  if (!server || !server.port) {
1242
1318
  throw new Error("Server started but is not responding correctly");
1243
1319
  }
1244
- const gray = "\x1B[90m";
1245
- const reset = "\x1B[0m";
1246
1320
  const cyan = "\x1B[36m";
1247
- const green = "\x1B[32m";
1248
- console.log(` ${gray}Config${reset} ${configSource === "user" ? "User config loaded" : "Using defaults"}`);
1249
- console.log(` ${gray}Routes${reset} ${config.routesDir}`);
1250
- if (isDev && values.watch) {
1251
- console.log(` ${gray}Watching${reset} All project files`);
1252
- }
1253
- console.log(` ${gray}CORS${reset} ${config.cors ? "Enabled" : "Disabled"}`);
1254
- console.log(` ${gray}Mode${reset} ${config.development ? "Development" : "Production"}
1255
- `);
1256
- console.log(` ${green}Ready${reset} \u2192 ${cyan}http://${config.hostname}:${config.port}${reset}
1321
+ const reset = "\x1B[0m";
1322
+ console.log(`
1323
+ Listening on ${cyan}http://${config.hostname}:${config.port}${reset}
1257
1324
  `);
1258
1325
  return { server, vector, config };
1259
1326
  })();
@@ -1272,7 +1339,9 @@ async function runDev() {
1272
1339
  const now = Date.now();
1273
1340
  if (isReloading || now - lastReloadTime < 1000)
1274
1341
  return;
1275
- if (filename && (filename.endsWith(".ts") || filename.endsWith(".js") || filename.endsWith(".json")) && !filename.includes("node_modules") && !filename.includes(".git") && !filename.includes(".vector") && !filename.includes("dist") && !filename.includes("bun.lockb") && !filename.endsWith(".generated.ts")) {
1342
+ const segments = filename ? filename.split(/[/\\]/) : [];
1343
+ const excluded = segments.some((s) => ["node_modules", ".git", ".vector", "dist"].includes(s));
1344
+ if (filename && (filename.endsWith(".ts") || filename.endsWith(".js") || filename.endsWith(".json")) && !excluded && !filename.includes("bun.lockb") && !filename.endsWith(".generated.ts")) {
1276
1345
  changedFiles.add(filename);
1277
1346
  if (reloadTimeout) {
1278
1347
  clearTimeout(reloadTimeout);
@@ -1287,13 +1356,6 @@ async function runDev() {
1287
1356
  vector.stop();
1288
1357
  }
1289
1358
  await new Promise((resolve3) => setTimeout(resolve3, 100));
1290
- if (__require.cache) {
1291
- for (const key in __require.cache) {
1292
- if (!key.includes("node_modules")) {
1293
- delete __require.cache[key];
1294
- }
1295
- }
1296
- }
1297
1359
  try {
1298
1360
  const result2 = await startServer();
1299
1361
  server = result2.server;
@@ -1308,32 +1370,24 @@ async function runDev() {
1308
1370
  }
1309
1371
  });
1310
1372
  } catch {
1311
- console.warn(" \u26A0\uFE0F File watching not available");
1373
+ const yellow = "\x1B[33m";
1374
+ const reset = "\x1B[0m";
1375
+ console.warn(`${yellow}Warning: File watching not available${reset}`);
1312
1376
  }
1313
1377
  }
1314
1378
  } catch (error) {
1315
1379
  const red = "\x1B[31m";
1316
1380
  const reset = "\x1B[0m";
1317
1381
  console.error(`
1318
- ${red}[ERROR] Failed to start server${reset}
1382
+ ${red}Error: ${error.message || error}${reset}
1319
1383
  `);
1320
- if (error.message) {
1321
- console.error(`Message: ${error.message}`);
1322
- }
1323
- if (error.stack) {
1324
- console.error(`
1325
- Stack trace:`);
1384
+ if (error.stack && true) {
1326
1385
  console.error(error.stack);
1327
- } else if (!error.message) {
1328
- console.error(`Raw error:`, error);
1329
1386
  }
1330
1387
  process.exit(1);
1331
1388
  }
1332
1389
  }
1333
1390
  async function runBuild() {
1334
- console.log(`
1335
- \u2192 Building Vector application
1336
- `);
1337
1391
  try {
1338
1392
  const { RouteScanner: RouteScanner2 } = await Promise.resolve().then(() => (init_route_scanner(), exports_route_scanner));
1339
1393
  const { RouteGenerator: RouteGenerator2 } = await Promise.resolve().then(() => (init_route_generator(), exports_route_generator));
@@ -1341,29 +1395,40 @@ async function runBuild() {
1341
1395
  const generator = new RouteGenerator2;
1342
1396
  const routes = await scanner.scan();
1343
1397
  await generator.generate(routes);
1344
- console.log(` Generated ${routes.length} routes`);
1345
1398
  if (typeof Bun !== "undefined") {
1346
1399
  const buildProcess = Bun.spawn([
1347
1400
  "bun",
1348
1401
  "build",
1349
- "src/index.ts",
1350
- "--outdir",
1351
- "dist",
1402
+ "src/cli/index.ts",
1403
+ "--target",
1404
+ "bun",
1405
+ "--outfile",
1406
+ "dist/server.js",
1352
1407
  "--minify"
1353
1408
  ]);
1354
- await buildProcess.exited;
1409
+ const exitCode = await buildProcess.exited;
1410
+ if (exitCode !== 0) {
1411
+ throw new Error(`Build failed with exit code ${exitCode}`);
1412
+ }
1355
1413
  } else {
1356
1414
  const { spawnSync } = await import("child_process");
1357
- spawnSync("bun", ["build", "src/index.ts", "--outdir", "dist", "--minify"], {
1415
+ const result = spawnSync("bun", ["build", "src/cli/index.ts", "--target", "bun", "--outfile", "dist/server.js", "--minify"], {
1358
1416
  stdio: "inherit",
1359
1417
  shell: true
1360
1418
  });
1419
+ if (result.status !== 0) {
1420
+ throw new Error(`Build failed with exit code ${result.status}`);
1421
+ }
1361
1422
  }
1362
1423
  console.log(`
1363
- \u2713 Build complete
1424
+ Build complete: dist/server.js
1364
1425
  `);
1365
1426
  } catch (error) {
1366
- console.error("[ERROR] Build failed:", error);
1427
+ const red = "\x1B[31m";
1428
+ const reset = "\x1B[0m";
1429
+ console.error(`
1430
+ ${red}Error: ${error.message || error}${reset}
1431
+ `);
1367
1432
  process.exit(1);
1368
1433
  }
1369
1434
  }
@@ -1,11 +1,11 @@
1
- import type { CacheHandler, DefaultVectorTypes, ProtectedHandler, VectorConfig, VectorConfigSchema, VectorTypes } from "../types";
1
+ import type { CacheHandler, DefaultVectorTypes, ProtectedHandler, VectorConfig, VectorConfigSchema, VectorTypes } from '../types';
2
2
  export declare class ConfigLoader<TTypes extends VectorTypes = DefaultVectorTypes> {
3
3
  private configPath;
4
4
  private config;
5
5
  private configSource;
6
6
  constructor(configPath?: string);
7
7
  load(): Promise<VectorConfig<TTypes>>;
8
- getConfigSource(): "user" | "default";
8
+ getConfigSource(): 'user' | 'default';
9
9
  private buildLegacyConfig;
10
10
  loadAuthHandler(): Promise<ProtectedHandler<TTypes> | null>;
11
11
  loadCacheHandler(): Promise<CacheHandler | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/core/config-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,YAAY,EAEZ,kBAAkB,EAClB,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACZ,MAAM,UAAU,CAAC;AAElB,qBAAa,YAAY,CAAC,MAAM,SAAS,WAAW,GAAG,kBAAkB;IACvE,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAA2C;IACzD,OAAO,CAAC,YAAY,CAAiC;gBAEzC,UAAU,CAAC,EAAE,MAAM;IAUzB,IAAI,IAAI,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IAgC3C,eAAe,IAAI,MAAM,GAAG,SAAS;YAIvB,iBAAiB;IA8CzB,eAAe,IAAI,OAAO,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAI3D,gBAAgB,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAItD,SAAS,IAAI,kBAAkB,CAAC,MAAM,CAAC,GAAG,IAAI;CAG/C"}
1
+ {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/core/config-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,YAAY,EAEZ,kBAAkB,EAClB,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACZ,MAAM,UAAU,CAAC;AAElB,qBAAa,YAAY,CAAC,MAAM,SAAS,WAAW,GAAG,kBAAkB;IACvE,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,MAAM,CAA2C;IACzD,OAAO,CAAC,YAAY,CAAiC;gBAEzC,UAAU,CAAC,EAAE,MAAM;IAQzB,IAAI,IAAI,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IA0B3C,eAAe,IAAI,MAAM,GAAG,SAAS;YAIvB,iBAAiB;IA8CzB,eAAe,IAAI,OAAO,CAAC,gBAAgB,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAI3D,gBAAgB,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAItD,SAAS,IAAI,kBAAkB,CAAC,MAAM,CAAC,GAAG,IAAI;CAG/C"}
@@ -1,40 +1,35 @@
1
- import { existsSync } from "node:fs";
2
- import { resolve, isAbsolute } from "node:path";
3
- import { toFileUrl } from "../utils/path";
1
+ import { existsSync } from 'node:fs';
2
+ import { resolve, isAbsolute } from 'node:path';
3
+ import { toFileUrl } from '../utils/path';
4
4
  export class ConfigLoader {
5
5
  configPath;
6
6
  config = null;
7
- configSource = "default";
7
+ configSource = 'default';
8
8
  constructor(configPath) {
9
9
  // Use provided config path or default to vector.config.ts
10
- const path = configPath || "vector.config.ts";
10
+ const path = configPath || 'vector.config.ts';
11
11
  // Handle absolute vs relative paths
12
- this.configPath = isAbsolute(path)
13
- ? path
14
- : resolve(process.cwd(), path);
12
+ this.configPath = isAbsolute(path) ? path : resolve(process.cwd(), path);
15
13
  }
16
14
  async load() {
17
15
  // Check if config file exists before attempting to load
18
16
  if (existsSync(this.configPath)) {
19
17
  try {
20
- console.log(`→ Loading config from: ${this.configPath}`);
21
18
  // Use explicit file:// URL to ensure correct resolution
22
19
  const userConfigPath = toFileUrl(this.configPath);
23
20
  const userConfig = await import(userConfigPath);
24
21
  this.config = userConfig.default || userConfig;
25
- this.configSource = "user";
26
- console.log(" ✓ User config loaded successfully");
22
+ this.configSource = 'user';
27
23
  }
28
24
  catch (error) {
29
- console.error(` ✗ Failed to load config from ${this.configPath}:`, error);
30
- console.log(" → Using default configuration");
25
+ const msg = error instanceof Error ? error.message : String(error);
26
+ console.error(`[Vector] Failed to load config from ${this.configPath}: ${msg}`);
27
+ console.error('[Vector] Server is using default configuration. Fix your config file and restart.');
31
28
  this.config = {};
32
29
  }
33
30
  }
34
31
  else {
35
32
  // Config file doesn't exist, use defaults
36
- console.log(` → No config file found at: ${this.configPath}`);
37
- console.log(" → Using default configuration");
38
33
  this.config = {};
39
34
  }
40
35
  // Convert new config schema to legacy VectorConfig format
@@ -51,21 +46,21 @@ export class ConfigLoader {
51
46
  config.hostname = this.config.hostname;
52
47
  config.reusePort = this.config.reusePort;
53
48
  config.development = this.config.development;
54
- config.routesDir = this.config.routesDir || "./routes";
49
+ config.routesDir = this.config.routesDir || './routes';
55
50
  config.idleTimeout = this.config.idleTimeout;
56
51
  }
57
52
  // Always auto-discover routes
58
53
  config.autoDiscover = true;
59
54
  // CORS configuration
60
55
  if (this.config?.cors) {
61
- if (typeof this.config.cors === "boolean") {
56
+ if (typeof this.config.cors === 'boolean') {
62
57
  config.cors = this.config.cors
63
58
  ? {
64
- origin: "*",
59
+ origin: '*',
65
60
  credentials: true,
66
- allowHeaders: "Content-Type, Authorization",
67
- allowMethods: "GET, POST, PUT, PATCH, DELETE, OPTIONS",
68
- exposeHeaders: "Authorization",
61
+ allowHeaders: 'Content-Type, Authorization',
62
+ allowMethods: 'GET, POST, PUT, PATCH, DELETE, OPTIONS',
63
+ exposeHeaders: 'Authorization',
69
64
  maxAge: 86400,
70
65
  }
71
66
  : undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../../src/core/config-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAW1C,MAAM,OAAO,YAAY;IACf,UAAU,CAAS;IACnB,MAAM,GAAsC,IAAI,CAAC;IACjD,YAAY,GAAuB,SAAS,CAAC;IAErD,YAAY,UAAmB;QAC7B,0DAA0D;QAC1D,MAAM,IAAI,GAAG,UAAU,IAAI,kBAAkB,CAAC;QAE9C,oCAAoC;QACpC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC;YAChC,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,IAAI;QACR,wDAAwD;QACxD,IAAI,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC;gBACH,OAAO,CAAC,GAAG,CAAC,0BAA0B,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;gBAEzD,wDAAwD;gBACxD,MAAM,cAAc,GAAG,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAClD,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;gBAChD,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC,OAAO,IAAI,UAAU,CAAC;gBAC/C,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC;gBAE3B,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;YACrD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CACX,kCAAkC,IAAI,CAAC,UAAU,GAAG,EACpD,KAAK,CACN,CAAC;gBACF,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;gBAC/C,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;YACnB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,0CAA0C;YAC1C,OAAO,CAAC,GAAG,CAAC,gCAAgC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;YAC/D,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;YAC/C,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACnB,CAAC;QAED,0DAA0D;QAC1D,OAAO,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;IACxC,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAEO,KAAK,CAAC,iBAAiB;QAC7B,MAAM,MAAM,GAAyB,EAAE,CAAC;QAExC,mDAAmD;QACnD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YAC/B,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;YACvC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;YACzC,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;YAC7C,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,UAAU,CAAC;YACvD,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC;QAC/C,CAAC;QAED,8BAA8B;QAC9B,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC;QAE3B,qBAAqB;QACrB,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;YACtB,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC1C,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI;oBAC5B,CAAC,CAAC;wBACE,MAAM,EAAE,GAAG;wBACX,WAAW,EAAE,IAAI;wBACjB,YAAY,EAAE,6BAA6B;wBAC3C,YAAY,EAAE,wCAAwC;wBACtD,aAAa,EAAE,eAAe;wBAC9B,MAAM,EAAE,KAAK;qBACd;oBACH,CAAC,CAAC,SAAS,CAAC;YAChB,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAmB,CAAC;YAChD,CAAC;QACH,CAAC;QAED,sEAAsE;QACtE,IAAI,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;YACxB,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QACrC,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;YACvB,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;QACrC,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,eAAe;QACnB,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI,IAAI,IAAI,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,OAAO,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,IAAI,CAAC;IACpC,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;CACF"}
1
+ {"version":3,"file":"config-loader.js","sourceRoot":"","sources":["../../src/core/config-loader.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,7 @@ export declare class VectorRouter<TTypes extends VectorTypes = DefaultVectorType
8
8
  private authManager;
9
9
  private cacheManager;
10
10
  private routes;
11
+ private specificityCache;
11
12
  constructor(middlewareManager: MiddlewareManager<TTypes>, authManager: AuthManager<TTypes>, cacheManager: CacheManager<TTypes>);
12
13
  private getRouteSpecificity;
13
14
  private isStaticSegment;
@@ -21,6 +22,7 @@ export declare class VectorRouter<TTypes extends VectorTypes = DefaultVectorType
21
22
  private prepareRequest;
22
23
  private wrapHandler;
23
24
  addRoute(routeEntry: RouteEntry): void;
25
+ bulkAddRoutes(entries: RouteEntry[]): void;
24
26
  getRoutes(): RouteEntry[];
25
27
  handle(request: Request): Promise<Response>;
26
28
  clearRoutes(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/core/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,YAAY,EAEZ,WAAW,EACZ,MAAM,UAAU,CAAC;AAElB,qBAAa,YAAY,CAAC,MAAM,SAAS,WAAW,GAAG,kBAAkB;IACvE,OAAO,CAAC,iBAAiB,CAA4B;IACrD,OAAO,CAAC,WAAW,CAAsB;IACzC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,MAAM,CAAoB;gBAGhC,iBAAiB,EAAE,iBAAiB,CAAC,MAAM,CAAC,EAC5C,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,EAChC,YAAY,EAAE,YAAY,CAAC,MAAM,CAAC;IAOpC,OAAO,CAAC,mBAAmB;IA4B3B,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,WAAW;IAInB,UAAU,IAAI,IAAI;IAYlB,OAAO,CAAC,WAAW;IAKnB,KAAK,CAAC,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC,GAAG,UAAU;IAc/E,OAAO,CAAC,gBAAgB;IAWxB,OAAO,CAAC,cAAc;IAgDtB,OAAO,CAAC,WAAW;IAqHnB,QAAQ,CAAC,UAAU,EAAE,UAAU;IAK/B,SAAS,IAAI,UAAU,EAAE;IAInB,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;IA2BjD,WAAW,IAAI,IAAI;CAGpB"}
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/core/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,YAAY,EAEZ,WAAW,EACZ,MAAM,UAAU,CAAC;AAGlB,qBAAa,YAAY,CAAC,MAAM,SAAS,WAAW,GAAG,kBAAkB;IACvE,OAAO,CAAC,iBAAiB,CAA4B;IACrD,OAAO,CAAC,WAAW,CAAsB;IACzC,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,gBAAgB,CAAkC;gBAGxD,iBAAiB,EAAE,iBAAiB,CAAC,MAAM,CAAC,EAC5C,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,EAChC,YAAY,EAAE,YAAY,CAAC,MAAM,CAAC;IAOpC,OAAO,CAAC,mBAAmB;IAgC3B,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,WAAW;IAInB,UAAU,IAAI,IAAI;IAYlB,OAAO,CAAC,WAAW;IAKnB,KAAK,CAAC,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC,GAAG,UAAU;IAc/E,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,cAAc;IAsEtB,OAAO,CAAC,WAAW;IAqHnB,QAAQ,CAAC,UAAU,EAAE,UAAU;IAK/B,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI;IAO1C,SAAS,IAAI,UAAU,EAAE;IAInB,MAAM,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC;IAiCjD,WAAW,IAAI,IAAI;CAIpB"}