@weconjs/core 0.2.0 → 1.1.0
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/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +6 -8
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +30 -21
- package/dist/context.js.map +1 -1
- package/dist/devtools/controllers/config.controller.d.ts +28 -0
- package/dist/devtools/controllers/config.controller.d.ts.map +1 -0
- package/dist/devtools/controllers/config.controller.js +100 -0
- package/dist/devtools/controllers/config.controller.js.map +1 -0
- package/dist/devtools/controllers/i18n.controller.d.ts +22 -0
- package/dist/devtools/controllers/i18n.controller.d.ts.map +1 -0
- package/dist/devtools/controllers/i18n.controller.js +93 -0
- package/dist/devtools/controllers/i18n.controller.js.map +1 -0
- package/dist/devtools/controllers/modules.controller.d.ts +16 -0
- package/dist/devtools/controllers/modules.controller.d.ts.map +1 -0
- package/dist/devtools/controllers/modules.controller.js +73 -0
- package/dist/devtools/controllers/modules.controller.js.map +1 -0
- package/dist/devtools/controllers/routes.controller.d.ts +13 -0
- package/dist/devtools/controllers/routes.controller.d.ts.map +1 -0
- package/dist/devtools/controllers/routes.controller.js +32 -0
- package/dist/devtools/controllers/routes.controller.js.map +1 -0
- package/dist/devtools/index.d.ts +28 -0
- package/dist/devtools/index.d.ts.map +1 -0
- package/dist/devtools/index.js +66 -0
- package/dist/devtools/index.js.map +1 -0
- package/dist/devtools/middleware.d.ts +11 -0
- package/dist/devtools/middleware.d.ts.map +1 -0
- package/dist/devtools/middleware.js +30 -0
- package/dist/devtools/middleware.js.map +1 -0
- package/dist/devtools/types.d.ts +59 -0
- package/dist/devtools/types.d.ts.map +1 -0
- package/dist/devtools/types.js +5 -0
- package/dist/devtools/types.js.map +1 -0
- package/dist/errors/ConfigError.d.ts +6 -0
- package/dist/errors/ConfigError.d.ts.map +1 -0
- package/dist/errors/ConfigError.js +16 -0
- package/dist/errors/ConfigError.js.map +1 -0
- package/dist/errors/RequestError.d.ts +6 -0
- package/dist/errors/RequestError.d.ts.map +1 -0
- package/dist/errors/RequestError.js +16 -0
- package/dist/errors/RequestError.js.map +1 -0
- package/dist/errors/index.d.ts +9 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +5 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.d.ts +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/module/index.d.ts +6 -0
- package/dist/module/index.d.ts.map +1 -0
- package/dist/module/index.js +5 -0
- package/dist/module/index.js.map +1 -0
- package/dist/module/module-loader.d.ts +60 -0
- package/dist/module/module-loader.d.ts.map +1 -0
- package/dist/module/module-loader.js +119 -0
- package/dist/module/module-loader.js.map +1 -0
- package/dist/routing/ErrorCatcher.d.ts +18 -0
- package/dist/routing/ErrorCatcher.d.ts.map +1 -0
- package/dist/routing/ErrorCatcher.js +50 -0
- package/dist/routing/ErrorCatcher.js.map +1 -0
- package/dist/routing/RaiMatcher.d.ts +27 -0
- package/dist/routing/RaiMatcher.d.ts.map +1 -0
- package/dist/routing/RaiMatcher.js +127 -0
- package/dist/routing/RaiMatcher.js.map +1 -0
- package/dist/routing/Route.d.ts +28 -0
- package/dist/routing/Route.d.ts.map +1 -0
- package/dist/routing/Route.js +125 -0
- package/dist/routing/Route.js.map +1 -0
- package/dist/routing/Routes.d.ts +31 -0
- package/dist/routing/Routes.d.ts.map +1 -0
- package/dist/routing/Routes.js +151 -0
- package/dist/routing/Routes.js.map +1 -0
- package/dist/routing/RoutesParam.d.ts +29 -0
- package/dist/routing/RoutesParam.d.ts.map +1 -0
- package/dist/routing/RoutesParam.js +113 -0
- package/dist/routing/RoutesParam.js.map +1 -0
- package/dist/routing/Wecon.d.ts +66 -0
- package/dist/routing/Wecon.d.ts.map +1 -0
- package/dist/routing/Wecon.js +248 -0
- package/dist/routing/Wecon.js.map +1 -0
- package/dist/routing/index.d.ts +9 -0
- package/dist/routing/index.d.ts.map +1 -0
- package/dist/routing/index.js +7 -0
- package/dist/routing/index.js.map +1 -0
- package/dist/server/index.d.ts +29 -5
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +40 -1
- package/dist/server/index.js.map +1 -1
- package/dist/types.d.ts +75 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
/**
|
|
3
|
+
* Base class for configuration error tracking.
|
|
4
|
+
* Captures caller info from stack traces for precise error reporting.
|
|
5
|
+
*/
|
|
6
|
+
export class ErrorCatcher {
|
|
7
|
+
/**
|
|
8
|
+
* Extract caller file, line, column from the stack trace.
|
|
9
|
+
* Skips internal frames to point to the user's code.
|
|
10
|
+
*/
|
|
11
|
+
static getCallerInfo() {
|
|
12
|
+
const err = new Error();
|
|
13
|
+
const stack = err.stack || "";
|
|
14
|
+
const stackLines = stack.split("\n").slice(1);
|
|
15
|
+
// Skip getCallerInfo and constructor frames
|
|
16
|
+
const callerLine = stackLines[2] || stackLines[1] || "";
|
|
17
|
+
// V8 format: " at ClassName.method (file:///path/file.ts:15:23)"
|
|
18
|
+
let match = callerLine.match(/\((.+?):(\d+):(\d+)\)$/);
|
|
19
|
+
if (!match) {
|
|
20
|
+
// Format without parentheses: " at file:///path/file.ts:15:23"
|
|
21
|
+
match = callerLine.match(/at\s+(.+?):(\d+):(\d+)$/);
|
|
22
|
+
}
|
|
23
|
+
if (match) {
|
|
24
|
+
const file = match[1].replace("file://", "");
|
|
25
|
+
const line = parseInt(match[2], 10);
|
|
26
|
+
const column = parseInt(match[3], 10);
|
|
27
|
+
const functionMatch = callerLine.match(/at\s+(?:async\s+)?(\S+?)\s+\(/);
|
|
28
|
+
const functionName = functionMatch ? functionMatch[1] : null;
|
|
29
|
+
return { file, line, column, function: functionName };
|
|
30
|
+
}
|
|
31
|
+
return { file: "unknown", line: 0, column: 0, function: null };
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Log a formatted config error with location info, then exit.
|
|
35
|
+
*/
|
|
36
|
+
static logError(error, tracedStackInfo) {
|
|
37
|
+
console.error(chalk.red.bold("\n-=>") +
|
|
38
|
+
chalk.white.bold(" Whoops! We caught an error for you.") +
|
|
39
|
+
chalk.red.bold(" <=-\n"));
|
|
40
|
+
console.error(chalk.red.bold("✖ Error:"), chalk.white(error.title));
|
|
41
|
+
console.error(chalk.gray("\n Details:"), chalk.white(error.details));
|
|
42
|
+
console.error(chalk.gray("\n Location:"), chalk.cyan(`${tracedStackInfo.file}:${tracedStackInfo.line}:${tracedStackInfo.column}`));
|
|
43
|
+
console.error(chalk.yellow.bold("\n 💡 How to fix:"));
|
|
44
|
+
console.error(chalk.yellow(` ${error.fix.replace(/\n/g, "\n ")}`));
|
|
45
|
+
console.error("");
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export default ErrorCatcher;
|
|
50
|
+
//# sourceMappingURL=ErrorCatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ErrorCatcher.js","sourceRoot":"","sources":["../../src/routing/ErrorCatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type Route from "./Route.js";
|
|
2
|
+
export type RaiRoutesList = Array<Pick<Route, "path" | "method" | "rai">>;
|
|
3
|
+
/**
|
|
4
|
+
* High-performance RAI lookup engine.
|
|
5
|
+
* Pre-compiles path matchers, uses exact + runtime caches for O(1) lookups.
|
|
6
|
+
*/
|
|
7
|
+
declare class RaiMatcher {
|
|
8
|
+
private cache;
|
|
9
|
+
private routesByMethod;
|
|
10
|
+
private exactRoutes;
|
|
11
|
+
constructor(raisList: RaiRoutesList);
|
|
12
|
+
/** Pre-compile all route matchers and organize by HTTP method */
|
|
13
|
+
private initialize;
|
|
14
|
+
/** Score route specificity: static=10, dynamic=1, wildcard=0.5 */
|
|
15
|
+
private getRouteSpecificity;
|
|
16
|
+
/** Normalize trailing slashes */
|
|
17
|
+
private normalizeRoute;
|
|
18
|
+
/** Find RAI for the given request path and method */
|
|
19
|
+
findRai(path: string, method: string): string;
|
|
20
|
+
clearCache(): void;
|
|
21
|
+
getCacheStats(): {
|
|
22
|
+
size: number;
|
|
23
|
+
methods: string[];
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export default RaiMatcher;
|
|
27
|
+
//# sourceMappingURL=RaiMatcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RaiMatcher.d.ts","sourceRoot":"","sources":["../../src/routing/RaiMatcher.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AAEpC,MAAM,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC;AAS1E;;;GAGG;AACH,cAAM,UAAU;IACd,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,WAAW,CAAsB;gBAE7B,QAAQ,EAAE,aAAa;IAOnC,iEAAiE;IACjE,OAAO,CAAC,UAAU;IA2ClB,kEAAkE;IAClE,OAAO,CAAC,mBAAmB;IAmB3B,iCAAiC;IACjC,OAAO,CAAC,cAAc;IAQtB,qDAAqD;IAC9C,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAsD7C,UAAU,IAAI,IAAI;IAIlB,aAAa,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE;CAM5D;AAED,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { match } from "path-to-regexp";
|
|
2
|
+
import errors from "../errors/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* High-performance RAI lookup engine.
|
|
5
|
+
* Pre-compiles path matchers, uses exact + runtime caches for O(1) lookups.
|
|
6
|
+
*/
|
|
7
|
+
class RaiMatcher {
|
|
8
|
+
cache;
|
|
9
|
+
routesByMethod;
|
|
10
|
+
exactRoutes;
|
|
11
|
+
constructor(raisList) {
|
|
12
|
+
this.cache = new Map();
|
|
13
|
+
this.routesByMethod = new Map();
|
|
14
|
+
this.exactRoutes = new Map();
|
|
15
|
+
this.initialize(raisList);
|
|
16
|
+
}
|
|
17
|
+
/** Pre-compile all route matchers and organize by HTTP method */
|
|
18
|
+
initialize(raisList) {
|
|
19
|
+
for (const route of raisList) {
|
|
20
|
+
if (typeof route.path !== "string" || !route.method) {
|
|
21
|
+
console.warn(`Invalid route configuration:`, route);
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
const normalizedMethod = route.method.trim().toUpperCase();
|
|
25
|
+
// Cache exact routes (no params) for O(1) lookup
|
|
26
|
+
if (!route.path.includes(":") && !route.path.includes("*")) {
|
|
27
|
+
const exactKey = `${normalizedMethod}:${route.path}`;
|
|
28
|
+
this.exactRoutes.set(exactKey, route.rai);
|
|
29
|
+
// Also handle trailing slash variant
|
|
30
|
+
const withSlash = route.path.endsWith("/")
|
|
31
|
+
? route.path.slice(0, -1)
|
|
32
|
+
: route.path + "/";
|
|
33
|
+
this.exactRoutes.set(`${normalizedMethod}:${withSlash}`, route.rai);
|
|
34
|
+
}
|
|
35
|
+
const cachedRoute = {
|
|
36
|
+
matcher: match(route.path, { decode: decodeURIComponent }),
|
|
37
|
+
rai: route.rai,
|
|
38
|
+
method: normalizedMethod,
|
|
39
|
+
path: route.path,
|
|
40
|
+
};
|
|
41
|
+
if (!this.routesByMethod.has(normalizedMethod)) {
|
|
42
|
+
this.routesByMethod.set(normalizedMethod, []);
|
|
43
|
+
}
|
|
44
|
+
this.routesByMethod.get(normalizedMethod).push(cachedRoute);
|
|
45
|
+
}
|
|
46
|
+
// Sort by specificity (static segments score higher)
|
|
47
|
+
for (const [, routes] of this.routesByMethod) {
|
|
48
|
+
routes.sort((a, b) => this.getRouteSpecificity(b.path) - this.getRouteSpecificity(a.path));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** Score route specificity: static=10, dynamic=1, wildcard=0.5 */
|
|
52
|
+
getRouteSpecificity(path) {
|
|
53
|
+
let score = 0;
|
|
54
|
+
const segments = path.split("/").filter(Boolean);
|
|
55
|
+
for (let i = 0; i < segments.length; i++) {
|
|
56
|
+
const segment = segments[i];
|
|
57
|
+
if (segment.startsWith(":")) {
|
|
58
|
+
score += 1;
|
|
59
|
+
}
|
|
60
|
+
else if (segment === "*") {
|
|
61
|
+
score += 0.5;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
score += 10;
|
|
65
|
+
}
|
|
66
|
+
score += (segments.length - i) * 0.1;
|
|
67
|
+
}
|
|
68
|
+
return score;
|
|
69
|
+
}
|
|
70
|
+
/** Normalize trailing slashes */
|
|
71
|
+
normalizeRoute(route) {
|
|
72
|
+
const primary = route.endsWith("/") && route.length > 1 ? route.slice(0, -1) : route;
|
|
73
|
+
const alternate = primary === route ? (route === "/" ? route : route + "/") : route;
|
|
74
|
+
return { primary, alternate };
|
|
75
|
+
}
|
|
76
|
+
/** Find RAI for the given request path and method */
|
|
77
|
+
findRai(path, method) {
|
|
78
|
+
const normalizedMethod = method.trim().toUpperCase();
|
|
79
|
+
const { primary, alternate } = this.normalizeRoute(path);
|
|
80
|
+
// 1. Exact match (fastest)
|
|
81
|
+
const exactKey = `${normalizedMethod}:${primary}`;
|
|
82
|
+
if (this.exactRoutes.has(exactKey)) {
|
|
83
|
+
return this.exactRoutes.get(exactKey);
|
|
84
|
+
}
|
|
85
|
+
// 2. Runtime cache for previously matched dynamic routes
|
|
86
|
+
const cacheKey = `${normalizedMethod}:${primary}`;
|
|
87
|
+
if (this.cache.has(cacheKey)) {
|
|
88
|
+
return this.cache.get(cacheKey).rai;
|
|
89
|
+
}
|
|
90
|
+
// 3. Method-specific route matching
|
|
91
|
+
const methodRoutes = this.routesByMethod.get(normalizedMethod);
|
|
92
|
+
if (!methodRoutes) {
|
|
93
|
+
throw new errors.RequestError(`No RAI found for the request URL: ${path} with method: ${method}`, { code: "RAI_NOT_FOUND", route: path, method });
|
|
94
|
+
}
|
|
95
|
+
// 4. Pattern matching (sorted by specificity)
|
|
96
|
+
for (const route of methodRoutes) {
|
|
97
|
+
const matchResult = route.matcher(primary) || route.matcher(alternate);
|
|
98
|
+
if (matchResult) {
|
|
99
|
+
this.cache.set(cacheKey, route);
|
|
100
|
+
// Evict oldest entry if cache is too large
|
|
101
|
+
if (this.cache.size > 1000) {
|
|
102
|
+
const firstKey = this.cache.keys().next().value;
|
|
103
|
+
this.cache.delete(firstKey);
|
|
104
|
+
}
|
|
105
|
+
return route.rai;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// 5. No match
|
|
109
|
+
throw new errors.RequestError(`No RAI found for the request URL: ${path} with method: ${method}`, {
|
|
110
|
+
code: "RAI_NOT_FOUND",
|
|
111
|
+
route: path,
|
|
112
|
+
method,
|
|
113
|
+
availableRoutes: methodRoutes.map((r) => r.path),
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
clearCache() {
|
|
117
|
+
this.cache.clear();
|
|
118
|
+
}
|
|
119
|
+
getCacheStats() {
|
|
120
|
+
return {
|
|
121
|
+
size: this.cache.size,
|
|
122
|
+
methods: Array.from(this.routesByMethod.keys()),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
export default RaiMatcher;
|
|
127
|
+
//# sourceMappingURL=RaiMatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RaiMatcher.js","sourceRoot":"","sources":["../../src/routing/RaiMatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Handler, RequestHandler } from "express";
|
|
2
|
+
import type { RouteConfig, ErrorTraceType, RAI, DefaultRole } from "../types.js";
|
|
3
|
+
import ErrorCatcher from "./ErrorCatcher.js";
|
|
4
|
+
import type RoutesParam from "./RoutesParam.js";
|
|
5
|
+
/**
|
|
6
|
+
* Single API endpoint definition.
|
|
7
|
+
* Carries method, path, RAI, roles, middlewares, and metadata.
|
|
8
|
+
*/
|
|
9
|
+
declare class Route<TRole extends string = DefaultRole> extends ErrorCatcher {
|
|
10
|
+
id: string;
|
|
11
|
+
method: "GET" | "POST" | "PUT" | "DELETE";
|
|
12
|
+
path: string;
|
|
13
|
+
params?: Array<RoutesParam>;
|
|
14
|
+
middlewares: Handler[] | RequestHandler[] | any[];
|
|
15
|
+
name: string;
|
|
16
|
+
description: string;
|
|
17
|
+
rai: RAI;
|
|
18
|
+
roles: TRole[];
|
|
19
|
+
meta?: Record<string, unknown>;
|
|
20
|
+
debugInfo: ErrorTraceType;
|
|
21
|
+
constructor(r: RouteConfig<TRole>);
|
|
22
|
+
private validateRoute;
|
|
23
|
+
private handleConfigError;
|
|
24
|
+
/** Check if user roles are authorized to access this route */
|
|
25
|
+
isAuthorized(userRoles: string[]): boolean;
|
|
26
|
+
}
|
|
27
|
+
export default Route;
|
|
28
|
+
//# sourceMappingURL=Route.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Route.d.ts","sourceRoot":"","sources":["../../src/routing/Route.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACvD,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EAEd,GAAG,EACH,WAAW,EACZ,MAAM,aAAa,CAAC;AACrB,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAE7C,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAEhD;;;GAGG;AACH,cAAM,KAAK,CAAC,KAAK,SAAS,MAAM,GAAG,WAAW,CAAE,SAAQ,YAAY;IAClE,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,CAAM;IACjC,WAAW,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,GAAG,EAAE,CAAC;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,GAAG,CAAC;IACT,KAAK,EAAE,KAAK,EAAE,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxB,SAAS,EAAE,cAAc,CAAC;gBAErB,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC;IAqBjC,OAAO,CAAC,aAAa;IAwBrB,OAAO,CAAC,iBAAiB;IAqDzB,8DAA8D;IAC9D,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO;CAS3C;AAED,eAAe,KAAK,CAAC"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import { randomUUID } from "crypto";
|
|
3
|
+
import ErrorCatcher from "./ErrorCatcher.js";
|
|
4
|
+
import errors from "../errors/index.js";
|
|
5
|
+
/**
|
|
6
|
+
* Single API endpoint definition.
|
|
7
|
+
* Carries method, path, RAI, roles, middlewares, and metadata.
|
|
8
|
+
*/
|
|
9
|
+
class Route extends ErrorCatcher {
|
|
10
|
+
id;
|
|
11
|
+
method;
|
|
12
|
+
path;
|
|
13
|
+
params = [];
|
|
14
|
+
middlewares;
|
|
15
|
+
name;
|
|
16
|
+
description;
|
|
17
|
+
rai;
|
|
18
|
+
roles;
|
|
19
|
+
meta;
|
|
20
|
+
debugInfo;
|
|
21
|
+
constructor(r) {
|
|
22
|
+
super();
|
|
23
|
+
this.id = randomUUID();
|
|
24
|
+
this.method = r.method;
|
|
25
|
+
this.path = r.path;
|
|
26
|
+
this.middlewares = r.middlewares;
|
|
27
|
+
this.name = r.name ? r.name : `[${this.method}] ${this.path}`;
|
|
28
|
+
this.description = r.description ? r.description : "";
|
|
29
|
+
this.rai = r.rai;
|
|
30
|
+
this.roles = r.roles;
|
|
31
|
+
this.meta = r.meta;
|
|
32
|
+
this.debugInfo = Route.getCallerInfo();
|
|
33
|
+
try {
|
|
34
|
+
this.validateRoute();
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
this.handleConfigError(err, this.debugInfo);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
validateRoute() {
|
|
41
|
+
if (!this.method) {
|
|
42
|
+
throw new errors.ConfigError("ROUTE_CONFIG:MISSING_METHOD");
|
|
43
|
+
}
|
|
44
|
+
if (!this.path) {
|
|
45
|
+
throw new errors.ConfigError("ROUTE_CONFIG:MISSING_PATH");
|
|
46
|
+
}
|
|
47
|
+
if (!this.rai) {
|
|
48
|
+
throw new errors.ConfigError("ROUTE_CONFIG:MISSING_RAI");
|
|
49
|
+
}
|
|
50
|
+
if (typeof this.rai !== "string") {
|
|
51
|
+
throw new errors.ConfigError("ROUTE_CONFIG:INVALID_RAI_TYPE");
|
|
52
|
+
}
|
|
53
|
+
if (!this.roles) {
|
|
54
|
+
throw new errors.ConfigError("ROUTE_CONFIG:MISSING_ROLES");
|
|
55
|
+
}
|
|
56
|
+
if (!Array.isArray(this.middlewares)) {
|
|
57
|
+
throw new errors.ConfigError("ROUTE_CONFIG:INVALID_MIDDLEWARES_TYPE");
|
|
58
|
+
}
|
|
59
|
+
if (this.middlewares.length === 0) {
|
|
60
|
+
throw new errors.ConfigError("ROUTE_CONFIG:EMPTY_MIDDLEWARES");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
handleConfigError(err, errInfo) {
|
|
64
|
+
const POSSIBLE_ERRORS = {
|
|
65
|
+
"ROUTE_CONFIG:MISSING_METHOD": {
|
|
66
|
+
title: "Missing required 'method' property",
|
|
67
|
+
details: "The Route instance requires a 'method' to be defined",
|
|
68
|
+
fix: "Add a method to your route configuration:\n method: 'GET' | 'POST' | 'PUT' | 'DELETE'",
|
|
69
|
+
},
|
|
70
|
+
"ROUTE_CONFIG:MISSING_PATH": {
|
|
71
|
+
title: "Missing required 'path' property",
|
|
72
|
+
details: "The Route instance requires a 'path' to be defined",
|
|
73
|
+
fix: "Add a path to your route configuration:\n path: '/users/:id'",
|
|
74
|
+
},
|
|
75
|
+
"ROUTE_CONFIG:MISSING_RAI": {
|
|
76
|
+
title: "Missing required 'rai' property",
|
|
77
|
+
details: "The Route instance requires a unique 'rai' (Route Access Identifier)",
|
|
78
|
+
fix: "Add a rai to your route configuration:\n rai: 'users:read' // Must be unique across all routes",
|
|
79
|
+
},
|
|
80
|
+
"ROUTE_CONFIG:INVALID_RAI_TYPE": {
|
|
81
|
+
title: "Invalid 'rai' property type",
|
|
82
|
+
details: "The 'rai' property must be a string, but received: " + typeof this.rai,
|
|
83
|
+
fix: "Ensure rai is a string:\n rai: 'users:read'",
|
|
84
|
+
},
|
|
85
|
+
"ROUTE_CONFIG:DUPLICATE_RAI": {
|
|
86
|
+
title: "Duplicate 'rai' detected",
|
|
87
|
+
details: "The 'rai' provided is already registered: " + this.rai,
|
|
88
|
+
fix: "Ensure each route has a unique rai:\n rai: 'users:create'",
|
|
89
|
+
},
|
|
90
|
+
"ROUTE_CONFIG:MISSING_ROLES": {
|
|
91
|
+
title: "Missing required 'roles' property",
|
|
92
|
+
details: "The Route instance requires a 'roles' array",
|
|
93
|
+
fix: "Add roles to your route configuration:\n roles: ['admin', 'user']",
|
|
94
|
+
},
|
|
95
|
+
"ROUTE_CONFIG:INVALID_MIDDLEWARES_TYPE": {
|
|
96
|
+
title: "Invalid 'middlewares' property type",
|
|
97
|
+
details: "The 'middlewares' property must be an array, but received: " + typeof this.middlewares,
|
|
98
|
+
fix: "Ensure middlewares is an array:\n middlewares: [authMiddleware, validateMiddleware]",
|
|
99
|
+
},
|
|
100
|
+
"ROUTE_CONFIG:EMPTY_MIDDLEWARES": {
|
|
101
|
+
title: "Empty 'middlewares' array",
|
|
102
|
+
details: "The Route instance requires at least one middleware function",
|
|
103
|
+
fix: "Add at least one handler:\n middlewares: [(req, res) => { res.json({ data: 'example' }) }]",
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
const errorConfig = POSSIBLE_ERRORS[err.message] || {
|
|
107
|
+
title: err.message,
|
|
108
|
+
details: "An unexpected error occurred",
|
|
109
|
+
fix: "Please check your Route configuration",
|
|
110
|
+
};
|
|
111
|
+
ErrorCatcher.logError(errorConfig, errInfo);
|
|
112
|
+
}
|
|
113
|
+
/** Check if user roles are authorized to access this route */
|
|
114
|
+
isAuthorized(userRoles) {
|
|
115
|
+
if (this.roles.length === 0)
|
|
116
|
+
return false;
|
|
117
|
+
for (const role of userRoles) {
|
|
118
|
+
if (this.roles.includes(role))
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
export default Route;
|
|
125
|
+
//# sourceMappingURL=Route.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Route.js","sourceRoot":"","sources":["../../src/routing/Route.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Handler } from "express";
|
|
2
|
+
import Route from "./Route.js";
|
|
3
|
+
import type { RoutesConfig, DefaultRole } from "../types.js";
|
|
4
|
+
import RoutesParam from "./RoutesParam.js";
|
|
5
|
+
import ErrorCatcher from "./ErrorCatcher.js";
|
|
6
|
+
/**
|
|
7
|
+
* Hierarchical route group with shared prefix, middleware, and params.
|
|
8
|
+
* Contains Route (endpoints) and/or nested Routes (sub-groups).
|
|
9
|
+
*/
|
|
10
|
+
declare class Routes<TRole extends string = DefaultRole> extends ErrorCatcher {
|
|
11
|
+
prefix: string;
|
|
12
|
+
routes: Array<Route<TRole> | Routes<TRole>>;
|
|
13
|
+
params?: RoutesParam[];
|
|
14
|
+
middlewares?: Handler[];
|
|
15
|
+
mergeParams?: boolean;
|
|
16
|
+
meta?: Record<string, unknown>;
|
|
17
|
+
constructor(r: RoutesConfig<TRole>);
|
|
18
|
+
private validateRoutes;
|
|
19
|
+
private handleConfigError;
|
|
20
|
+
/**
|
|
21
|
+
* Flatten the route tree into a Map<RAI, enriched Route>.
|
|
22
|
+
* Accumulates paths, middlewares, and params from parent groups.
|
|
23
|
+
*/
|
|
24
|
+
groupRoutesByRai(): Map<string, Route<TRole> & {
|
|
25
|
+
params: RoutesParam[];
|
|
26
|
+
middlewares: Handler[];
|
|
27
|
+
}>;
|
|
28
|
+
private deduplicateParams;
|
|
29
|
+
}
|
|
30
|
+
export default Routes;
|
|
31
|
+
//# sourceMappingURL=Routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Routes.d.ts","sourceRoot":"","sources":["../../src/routing/Routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,KAAK,EAGV,YAAY,EACZ,WAAW,EACZ,MAAM,aAAa,CAAC;AACrB,OAAO,WAAW,MAAM,kBAAkB,CAAC;AAC3C,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAG7C;;;GAGG;AACH,cAAM,MAAM,CAAC,KAAK,SAAS,MAAM,GAAG,WAAW,CAAE,SAAQ,YAAY;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5C,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAS;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAEnB,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC;IAkBlC,OAAO,CAAC,cAAc;IAqBtB,OAAO,CAAC,iBAAiB;IA0CzB;;;OAGG;IACI,gBAAgB,IAAI,GAAG,CAC5B,MAAM,EACN,KAAK,CAAC,KAAK,CAAC,GAAG;QAAE,MAAM,EAAE,WAAW,EAAE,CAAC;QAAC,WAAW,EAAE,OAAO,EAAE,CAAA;KAAE,CACjE;IA6ED,OAAO,CAAC,iBAAiB;CAK1B;AAED,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import Route from "./Route.js";
|
|
2
|
+
import ErrorCatcher from "./ErrorCatcher.js";
|
|
3
|
+
import errors from "../errors/index.js";
|
|
4
|
+
/**
|
|
5
|
+
* Hierarchical route group with shared prefix, middleware, and params.
|
|
6
|
+
* Contains Route (endpoints) and/or nested Routes (sub-groups).
|
|
7
|
+
*/
|
|
8
|
+
class Routes extends ErrorCatcher {
|
|
9
|
+
prefix;
|
|
10
|
+
routes;
|
|
11
|
+
params;
|
|
12
|
+
middlewares;
|
|
13
|
+
mergeParams = false;
|
|
14
|
+
meta;
|
|
15
|
+
constructor(r) {
|
|
16
|
+
super();
|
|
17
|
+
this.prefix = r.prefix ? r.prefix : "";
|
|
18
|
+
this.routes = r.routes;
|
|
19
|
+
this.params = r.params ? r.params : [];
|
|
20
|
+
this.middlewares = r.middlewares ? r.middlewares : [];
|
|
21
|
+
this.mergeParams = r.mergeParams ? r.mergeParams : false;
|
|
22
|
+
this.meta = r.meta;
|
|
23
|
+
try {
|
|
24
|
+
this.validateRoutes();
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
const errInfo = Routes.getCallerInfo();
|
|
28
|
+
this.handleConfigError(err, errInfo);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
validateRoutes() {
|
|
32
|
+
if (this.prefix && typeof this.prefix !== "string") {
|
|
33
|
+
throw new errors.ConfigError("ROUTES_CONFIG:INVALID_PREFIX_TYPE");
|
|
34
|
+
}
|
|
35
|
+
if (!this.routes) {
|
|
36
|
+
throw new errors.ConfigError("ROUTES_CONFIG:MISSING_ROUTES");
|
|
37
|
+
}
|
|
38
|
+
if (!Array.isArray(this.routes)) {
|
|
39
|
+
throw new Error("ROUTES_CONFIG:INVALID_ROUTES_TYPE");
|
|
40
|
+
}
|
|
41
|
+
if (this.middlewares && !Array.isArray(this.middlewares)) {
|
|
42
|
+
throw new errors.ConfigError("ROUTES_CONFIG:INVALID_MIDDLEWARES_TYPE");
|
|
43
|
+
}
|
|
44
|
+
if (this.params && !Array.isArray(this.params)) {
|
|
45
|
+
throw new errors.ConfigError("ROUTES_CONFIG:INVALID_PARAMS_TYPE");
|
|
46
|
+
}
|
|
47
|
+
if (this.mergeParams && typeof this.mergeParams !== "boolean") {
|
|
48
|
+
throw new errors.ConfigError("ROUTES_CONFIG:INVALID_MERGE_PARAMS_TYPE");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
handleConfigError(err, errInfo) {
|
|
52
|
+
const POSSIBLE_ERRORS = {
|
|
53
|
+
"ROUTES_CONFIG:INVALID_PREFIX_TYPE": {
|
|
54
|
+
title: "Invalid 'prefix' property type",
|
|
55
|
+
details: "The 'prefix' must be a string, but received: " + typeof this.prefix,
|
|
56
|
+
fix: "Ensure prefix is a string:\n prefix: '/api' or prefix: ''",
|
|
57
|
+
},
|
|
58
|
+
"ROUTES_CONFIG:MISSING_ROUTES": {
|
|
59
|
+
title: "Missing required 'routes' property",
|
|
60
|
+
details: "The Routes instance requires a 'routes' array",
|
|
61
|
+
fix: "Add a routes array:\n routes: [new Routes(...), new Route(...)]",
|
|
62
|
+
},
|
|
63
|
+
"ROUTES_CONFIG:INVALID_ROUTES_TYPE": {
|
|
64
|
+
title: "Invalid 'routes' property type",
|
|
65
|
+
details: "The 'routes' must be an array, but received: " + typeof this.routes,
|
|
66
|
+
fix: "Ensure routes is an array:\n routes: [...]",
|
|
67
|
+
},
|
|
68
|
+
"ROUTES_CONFIG:INVALID_MIDDLEWARES_TYPE": {
|
|
69
|
+
title: "Invalid 'middlewares' property type",
|
|
70
|
+
details: "The 'middlewares' must be an array of express handlers, but received: " + typeof this.middlewares,
|
|
71
|
+
fix: "Provide an array of middleware:\n middlewares: [middleware1, middleware2]",
|
|
72
|
+
},
|
|
73
|
+
"ROUTES_CONFIG:INVALID_PARAMS_TYPE": {
|
|
74
|
+
title: "Invalid 'params' property type",
|
|
75
|
+
details: "The 'params' must be an array of RoutesParam instances, but received: " + typeof this.params,
|
|
76
|
+
fix: "Provide an array of RoutesParam:\n params: [new RoutesParam(...)]",
|
|
77
|
+
},
|
|
78
|
+
"ROUTES_CONFIG:INVALID_MERGE_PARAMS_TYPE": {
|
|
79
|
+
title: "Invalid 'mergeParams' property type",
|
|
80
|
+
details: "The 'mergeParams' must be a boolean, but received: " + typeof this.mergeParams,
|
|
81
|
+
fix: "Set mergeParams to a boolean:\n mergeParams: true",
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
const errorConfig = POSSIBLE_ERRORS[err.message] || {
|
|
85
|
+
title: err.message,
|
|
86
|
+
details: "An unexpected error occurred",
|
|
87
|
+
fix: "Please check your Routes configuration",
|
|
88
|
+
};
|
|
89
|
+
ErrorCatcher.logError(errorConfig, errInfo);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Flatten the route tree into a Map<RAI, enriched Route>.
|
|
93
|
+
* Accumulates paths, middlewares, and params from parent groups.
|
|
94
|
+
*/
|
|
95
|
+
groupRoutesByRai() {
|
|
96
|
+
const raiMap = new Map();
|
|
97
|
+
const traverse = (current, accumulatedPath, accumulatedParams, accumulatedMiddlewares, parentsMergeParams) => {
|
|
98
|
+
// Handle endpoint
|
|
99
|
+
if (current instanceof Route) {
|
|
100
|
+
const fullPath = accumulatedPath + current.path;
|
|
101
|
+
const finalMiddlewares = [
|
|
102
|
+
...accumulatedMiddlewares,
|
|
103
|
+
...(current.middlewares || []),
|
|
104
|
+
];
|
|
105
|
+
const finalParams = this.deduplicateParams(accumulatedParams);
|
|
106
|
+
if (raiMap.has(current.rai)) {
|
|
107
|
+
const errorConfig = {
|
|
108
|
+
title: "Duplicate 'rai' detected",
|
|
109
|
+
details: "The 'rai' provided is already registered: " + current.rai,
|
|
110
|
+
fix: "Ensure each route has a unique rai:\n rai: 'users:create'",
|
|
111
|
+
};
|
|
112
|
+
ErrorCatcher.logError(errorConfig, current.debugInfo);
|
|
113
|
+
}
|
|
114
|
+
const extendedRoute = Object.assign(Object.create(Object.getPrototypeOf(current)), current, {
|
|
115
|
+
path: fullPath,
|
|
116
|
+
params: finalParams,
|
|
117
|
+
middlewares: finalMiddlewares,
|
|
118
|
+
});
|
|
119
|
+
raiMap.set(current.rai, extendedRoute);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
// Handle group
|
|
123
|
+
if (current instanceof Routes) {
|
|
124
|
+
const nextPath = accumulatedPath + current.prefix;
|
|
125
|
+
const nextMiddlewares = [
|
|
126
|
+
...accumulatedMiddlewares,
|
|
127
|
+
...(current.middlewares || []),
|
|
128
|
+
];
|
|
129
|
+
let nextParams = [];
|
|
130
|
+
if (parentsMergeParams) {
|
|
131
|
+
nextParams = [...accumulatedParams, ...(current.params || [])];
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
nextParams = current.params || [];
|
|
135
|
+
}
|
|
136
|
+
current.routes.forEach((child) => {
|
|
137
|
+
traverse(child, nextPath, nextParams, nextMiddlewares, current.mergeParams || false);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
traverse(this, "", [], [], false);
|
|
142
|
+
return raiMap;
|
|
143
|
+
}
|
|
144
|
+
deduplicateParams(params) {
|
|
145
|
+
const unique = new Map();
|
|
146
|
+
params.forEach((p) => unique.set(p.path, p));
|
|
147
|
+
return Array.from(unique.values());
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
export default Routes;
|
|
151
|
+
//# sourceMappingURL=Routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Routes.js","sourceRoot":"","sources":["../../src/routing/Routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { RequestParamHandler } from "express";
|
|
2
|
+
import ErrorCatcher from "./ErrorCatcher.js";
|
|
3
|
+
/**
|
|
4
|
+
* Parameter handler with optional validation rules.
|
|
5
|
+
* Attached to Routes to validate and process URL params (e.g. :userId).
|
|
6
|
+
*/
|
|
7
|
+
declare class RoutesParam extends ErrorCatcher {
|
|
8
|
+
readonly uuid: string;
|
|
9
|
+
path: string;
|
|
10
|
+
middleware: RequestParamHandler;
|
|
11
|
+
validate?: {
|
|
12
|
+
pattern?: RegExp;
|
|
13
|
+
minLength?: number;
|
|
14
|
+
maxLength?: number;
|
|
15
|
+
validatorFn?: (value: string) => boolean;
|
|
16
|
+
};
|
|
17
|
+
constructor(path: string, middleware: RequestParamHandler, validate?: {
|
|
18
|
+
pattern?: RegExp;
|
|
19
|
+
minLength?: number;
|
|
20
|
+
maxLength?: number;
|
|
21
|
+
validatorFn?: (value: string) => boolean;
|
|
22
|
+
});
|
|
23
|
+
private validateParam;
|
|
24
|
+
private handleConfigError;
|
|
25
|
+
/** Run all validation rules against a param value */
|
|
26
|
+
validateValue(value: string): boolean;
|
|
27
|
+
}
|
|
28
|
+
export default RoutesParam;
|
|
29
|
+
//# sourceMappingURL=RoutesParam.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RoutesParam.d.ts","sourceRoot":"","sources":["../../src/routing/RoutesParam.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAI7C;;;GAGG;AACH,cAAM,WAAY,SAAQ,YAAY;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,EAAE;QACT,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;KAC1C,CAAC;gBAGA,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,mBAAmB,EAC/B,QAAQ,CAAC,EAAE;QACT,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;KAC1C;IAiBH,OAAO,CAAC,aAAa;IA4BrB,OAAO,CAAC,iBAAiB;IAgDzB,qDAAqD;IACrD,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;CAUtC;AAED,eAAe,WAAW,CAAC"}
|