@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.
Files changed (95) hide show
  1. package/dist/config.d.ts.map +1 -1
  2. package/dist/config.js +1 -0
  3. package/dist/config.js.map +1 -1
  4. package/dist/context.d.ts +6 -8
  5. package/dist/context.d.ts.map +1 -1
  6. package/dist/context.js +30 -21
  7. package/dist/context.js.map +1 -1
  8. package/dist/devtools/controllers/config.controller.d.ts +28 -0
  9. package/dist/devtools/controllers/config.controller.d.ts.map +1 -0
  10. package/dist/devtools/controllers/config.controller.js +100 -0
  11. package/dist/devtools/controllers/config.controller.js.map +1 -0
  12. package/dist/devtools/controllers/i18n.controller.d.ts +22 -0
  13. package/dist/devtools/controllers/i18n.controller.d.ts.map +1 -0
  14. package/dist/devtools/controllers/i18n.controller.js +93 -0
  15. package/dist/devtools/controllers/i18n.controller.js.map +1 -0
  16. package/dist/devtools/controllers/modules.controller.d.ts +16 -0
  17. package/dist/devtools/controllers/modules.controller.d.ts.map +1 -0
  18. package/dist/devtools/controllers/modules.controller.js +73 -0
  19. package/dist/devtools/controllers/modules.controller.js.map +1 -0
  20. package/dist/devtools/controllers/routes.controller.d.ts +13 -0
  21. package/dist/devtools/controllers/routes.controller.d.ts.map +1 -0
  22. package/dist/devtools/controllers/routes.controller.js +32 -0
  23. package/dist/devtools/controllers/routes.controller.js.map +1 -0
  24. package/dist/devtools/index.d.ts +28 -0
  25. package/dist/devtools/index.d.ts.map +1 -0
  26. package/dist/devtools/index.js +66 -0
  27. package/dist/devtools/index.js.map +1 -0
  28. package/dist/devtools/middleware.d.ts +11 -0
  29. package/dist/devtools/middleware.d.ts.map +1 -0
  30. package/dist/devtools/middleware.js +30 -0
  31. package/dist/devtools/middleware.js.map +1 -0
  32. package/dist/devtools/types.d.ts +59 -0
  33. package/dist/devtools/types.d.ts.map +1 -0
  34. package/dist/devtools/types.js +5 -0
  35. package/dist/devtools/types.js.map +1 -0
  36. package/dist/errors/ConfigError.d.ts +6 -0
  37. package/dist/errors/ConfigError.d.ts.map +1 -0
  38. package/dist/errors/ConfigError.js +16 -0
  39. package/dist/errors/ConfigError.js.map +1 -0
  40. package/dist/errors/RequestError.d.ts +6 -0
  41. package/dist/errors/RequestError.d.ts.map +1 -0
  42. package/dist/errors/RequestError.js +16 -0
  43. package/dist/errors/RequestError.js.map +1 -0
  44. package/dist/errors/index.d.ts +9 -0
  45. package/dist/errors/index.d.ts.map +1 -0
  46. package/dist/errors/index.js +5 -0
  47. package/dist/errors/index.js.map +1 -0
  48. package/dist/index.d.ts +9 -2
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +9 -1
  51. package/dist/index.js.map +1 -1
  52. package/dist/module/index.d.ts +6 -0
  53. package/dist/module/index.d.ts.map +1 -0
  54. package/dist/module/index.js +5 -0
  55. package/dist/module/index.js.map +1 -0
  56. package/dist/module/module-loader.d.ts +60 -0
  57. package/dist/module/module-loader.d.ts.map +1 -0
  58. package/dist/module/module-loader.js +119 -0
  59. package/dist/module/module-loader.js.map +1 -0
  60. package/dist/routing/ErrorCatcher.d.ts +18 -0
  61. package/dist/routing/ErrorCatcher.d.ts.map +1 -0
  62. package/dist/routing/ErrorCatcher.js +50 -0
  63. package/dist/routing/ErrorCatcher.js.map +1 -0
  64. package/dist/routing/RaiMatcher.d.ts +27 -0
  65. package/dist/routing/RaiMatcher.d.ts.map +1 -0
  66. package/dist/routing/RaiMatcher.js +127 -0
  67. package/dist/routing/RaiMatcher.js.map +1 -0
  68. package/dist/routing/Route.d.ts +28 -0
  69. package/dist/routing/Route.d.ts.map +1 -0
  70. package/dist/routing/Route.js +125 -0
  71. package/dist/routing/Route.js.map +1 -0
  72. package/dist/routing/Routes.d.ts +31 -0
  73. package/dist/routing/Routes.d.ts.map +1 -0
  74. package/dist/routing/Routes.js +151 -0
  75. package/dist/routing/Routes.js.map +1 -0
  76. package/dist/routing/RoutesParam.d.ts +29 -0
  77. package/dist/routing/RoutesParam.d.ts.map +1 -0
  78. package/dist/routing/RoutesParam.js +113 -0
  79. package/dist/routing/RoutesParam.js.map +1 -0
  80. package/dist/routing/Wecon.d.ts +66 -0
  81. package/dist/routing/Wecon.d.ts.map +1 -0
  82. package/dist/routing/Wecon.js +248 -0
  83. package/dist/routing/Wecon.js.map +1 -0
  84. package/dist/routing/index.d.ts +9 -0
  85. package/dist/routing/index.d.ts.map +1 -0
  86. package/dist/routing/index.js +7 -0
  87. package/dist/routing/index.js.map +1 -0
  88. package/dist/server/index.d.ts +29 -5
  89. package/dist/server/index.d.ts.map +1 -1
  90. package/dist/server/index.js +40 -1
  91. package/dist/server/index.js.map +1 -1
  92. package/dist/types.d.ts +75 -3
  93. package/dist/types.d.ts.map +1 -1
  94. package/dist/types.js +1 -1
  95. package/package.json +3 -1
@@ -0,0 +1,113 @@
1
+ import { randomUUID } from "crypto";
2
+ import ErrorCatcher from "./ErrorCatcher.js";
3
+ import errors from "../errors/index.js";
4
+ /**
5
+ * Parameter handler with optional validation rules.
6
+ * Attached to Routes to validate and process URL params (e.g. :userId).
7
+ */
8
+ class RoutesParam extends ErrorCatcher {
9
+ uuid;
10
+ path;
11
+ middleware;
12
+ validate;
13
+ constructor(path, middleware, validate) {
14
+ super();
15
+ this.uuid = randomUUID();
16
+ this.path = path;
17
+ this.middleware = middleware;
18
+ this.validate = validate;
19
+ try {
20
+ this.validateParam();
21
+ }
22
+ catch (err) {
23
+ const errInfo = ErrorCatcher.getCallerInfo();
24
+ this.handleConfigError(err, errInfo);
25
+ }
26
+ }
27
+ validateParam() {
28
+ if (!this.path) {
29
+ throw new errors.ConfigError("ROUTES_PARAM:MISSING_PATH");
30
+ }
31
+ if (!this.middleware) {
32
+ throw new errors.ConfigError("ROUTES_PARAM:MISSING_MIDDLEWARE");
33
+ }
34
+ if (this.validate) {
35
+ if (typeof this.validate !== "object" || Array.isArray(this.validate)) {
36
+ throw new errors.ConfigError("ROUTES_PARAM:INVALID_VALIDATE_TYPE");
37
+ }
38
+ if (this.validate.pattern && !(this.validate.pattern instanceof RegExp)) {
39
+ throw new errors.ConfigError("ROUTES_PARAM:INVALID_PATTERN_TYPE");
40
+ }
41
+ if (this.validate.minLength !== undefined && typeof this.validate.minLength !== "number") {
42
+ throw new errors.ConfigError("ROUTES_PARAM:INVALID_MIN_LENGTH_TYPE");
43
+ }
44
+ if (this.validate.maxLength !== undefined && typeof this.validate.maxLength !== "number") {
45
+ throw new errors.ConfigError("ROUTES_PARAM:INVALID_MAX_LENGTH_TYPE");
46
+ }
47
+ if (this.validate.validatorFn && typeof this.validate.validatorFn !== "function") {
48
+ throw new errors.ConfigError("ROUTES_PARAM:INVALID_VALIDATOR_FN_TYPE");
49
+ }
50
+ }
51
+ }
52
+ handleConfigError(err, errInfo) {
53
+ const POSSIBLE_ERRORS = {
54
+ "ROUTES_PARAM:INVALID_VALIDATE_TYPE": {
55
+ title: "Invalid 'validate' property type",
56
+ details: "The 'validate' property must be an object, but received: " + typeof this.validate,
57
+ fix: "Ensure validate is an object:\n validate: { pattern: /regex/, minLength: 3 }",
58
+ },
59
+ "ROUTES_PARAM:MISSING_PATH": {
60
+ title: "Missing required 'path' parameter",
61
+ details: "The RoutesParam instance requires a 'path' to be defined",
62
+ fix: "Provide a path parameter:\n new RoutesParam('userId', middleware)",
63
+ },
64
+ "ROUTES_PARAM:MISSING_MIDDLEWARE": {
65
+ title: "Missing required 'middleware' parameter",
66
+ details: "The RoutesParam instance requires a 'middleware' function",
67
+ fix: "Provide a middleware function:\n new RoutesParam('userId', (req, res, next, id) => { next() })",
68
+ },
69
+ "ROUTES_PARAM:INVALID_PATTERN_TYPE": {
70
+ title: "Invalid 'validate.pattern' property type",
71
+ details: "The 'validate.pattern' must be a RegExp, but received: " + typeof this.validate?.pattern,
72
+ fix: "Ensure pattern is a RegExp:\n validate: { pattern: /^[0-9]+$/ }",
73
+ },
74
+ "ROUTES_PARAM:INVALID_MIN_LENGTH_TYPE": {
75
+ title: "Invalid 'validate.minLength' property type",
76
+ details: "The 'validate.minLength' must be a number, but received: " + typeof this.validate?.minLength,
77
+ fix: "Ensure minLength is a number:\n validate: { minLength: 3 }",
78
+ },
79
+ "ROUTES_PARAM:INVALID_MAX_LENGTH_TYPE": {
80
+ title: "Invalid 'validate.maxLength' property type",
81
+ details: "The 'validate.maxLength' must be a number, but received: " + typeof this.validate?.maxLength,
82
+ fix: "Ensure maxLength is a number:\n validate: { maxLength: 50 }",
83
+ },
84
+ "ROUTES_PARAM:INVALID_VALIDATOR_FN_TYPE": {
85
+ title: "Invalid 'validate.validatorFn' property type",
86
+ details: "The 'validate.validatorFn' must be a function, but received: " + typeof this.validate?.validatorFn,
87
+ fix: "Ensure validatorFn is a function:\n validate: { validatorFn: (value) => value.startsWith('user-') }",
88
+ },
89
+ };
90
+ const errorConfig = POSSIBLE_ERRORS[err.message] || {
91
+ title: err.message,
92
+ details: "An unexpected error occurred",
93
+ fix: "Please check your RoutesParam configuration",
94
+ };
95
+ ErrorCatcher.logError(errorConfig, errInfo);
96
+ }
97
+ /** Run all validation rules against a param value */
98
+ validateValue(value) {
99
+ if (!this.validate)
100
+ return true;
101
+ if (this.validate.pattern && !this.validate.pattern.test(value))
102
+ return false;
103
+ if (this.validate.minLength !== undefined && value.length < this.validate.minLength)
104
+ return false;
105
+ if (this.validate.maxLength !== undefined && value.length > this.validate.maxLength)
106
+ return false;
107
+ if (this.validate.validatorFn && !this.validate.validatorFn(value))
108
+ return false;
109
+ return true;
110
+ }
111
+ }
112
+ export default RoutesParam;
113
+ //# sourceMappingURL=RoutesParam.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RoutesParam.js","sourceRoot":"","sources":["../../src/routing/RoutesParam.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAE7C,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC;;;GAGG;AACH,MAAM,WAAY,SAAQ,YAAY;IAC3B,IAAI,CAAS;IACf,IAAI,CAAS;IACb,UAAU,CAAsB;IACvC,QAAQ,CAKN;IAEF,YACE,IAAY,EACZ,UAA+B,EAC/B,QAKC;QAED,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,IAAI,GAAG,UAAU,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAEzB,IAAI,CAAC;YACH,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,YAAY,CAAC,aAAa,EAAE,CAAC;YAC7C,IAAI,CAAC,iBAAiB,CAAC,GAAY,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAEO,aAAa;QACnB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,MAAM,IAAI,MAAM,CAAC,WAAW,CAAC,2BAA2B,CAAC,CAAC;QAC5D,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,MAAM,IAAI,MAAM,CAAC,WAAW,CAAC,iCAAiC,CAAC,CAAC;QAClE,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACtE,MAAM,IAAI,MAAM,CAAC,WAAW,CAAC,oCAAoC,CAAC,CAAC;YACrE,CAAC;YACD,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,YAAY,MAAM,CAAC,EAAE,CAAC;gBACxE,MAAM,IAAI,MAAM,CAAC,WAAW,CAAC,mCAAmC,CAAC,CAAC;YACpE,CAAC;YACD,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,KAAK,SAAS,IAAI,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;gBACzF,MAAM,IAAI,MAAM,CAAC,WAAW,CAAC,sCAAsC,CAAC,CAAC;YACvE,CAAC;YACD,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,KAAK,SAAS,IAAI,OAAO,IAAI,CAAC,QAAQ,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;gBACzF,MAAM,IAAI,MAAM,CAAC,WAAW,CAAC,sCAAsC,CAAC,CAAC;YACvE,CAAC;YACD,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,IAAI,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;gBACjF,MAAM,IAAI,MAAM,CAAC,WAAW,CAAC,wCAAwC,CAAC,CAAC;YACzE,CAAC;QACH,CAAC;IACH,CAAC;IAEO,iBAAiB,CAAC,GAAU,EAAE,OAAuB;QAC3D,MAAM,eAAe,GAAsB;YACzC,oCAAoC,EAAE;gBACpC,KAAK,EAAE,kCAAkC;gBACzC,OAAO,EAAE,2DAA2D,GAAG,OAAO,IAAI,CAAC,QAAQ;gBAC3F,GAAG,EAAE,iFAAiF;aACvF;YACD,2BAA2B,EAAE;gBAC3B,KAAK,EAAE,mCAAmC;gBAC1C,OAAO,EAAE,0DAA0D;gBACnE,GAAG,EAAE,sEAAsE;aAC5E;YACD,iCAAiC,EAAE;gBACjC,KAAK,EAAE,yCAAyC;gBAChD,OAAO,EAAE,2DAA2D;gBACpE,GAAG,EAAE,mGAAmG;aACzG;YACD,mCAAmC,EAAE;gBACnC,KAAK,EAAE,0CAA0C;gBACjD,OAAO,EAAE,yDAAyD,GAAG,OAAO,IAAI,CAAC,QAAQ,EAAE,OAAO;gBAClG,GAAG,EAAE,oEAAoE;aAC1E;YACD,sCAAsC,EAAE;gBACtC,KAAK,EAAE,4CAA4C;gBACnD,OAAO,EAAE,2DAA2D,GAAG,OAAO,IAAI,CAAC,QAAQ,EAAE,SAAS;gBACtG,GAAG,EAAE,+DAA+D;aACrE;YACD,sCAAsC,EAAE;gBACtC,KAAK,EAAE,4CAA4C;gBACnD,OAAO,EAAE,2DAA2D,GAAG,OAAO,IAAI,CAAC,QAAQ,EAAE,SAAS;gBACtG,GAAG,EAAE,gEAAgE;aACtE;YACD,wCAAwC,EAAE;gBACxC,KAAK,EAAE,8CAA8C;gBACrD,OAAO,EAAE,+DAA+D,GAAG,OAAO,IAAI,CAAC,QAAQ,EAAE,WAAW;gBAC5G,GAAG,EAAE,wGAAwG;aAC9G;SACF,CAAC;QAEF,MAAM,WAAW,GAAG,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI;YAClD,KAAK,EAAE,GAAG,CAAC,OAAO;YAClB,OAAO,EAAE,8BAA8B;YACvC,GAAG,EAAE,6CAA6C;SACnD,CAAC;QAEF,YAAY,CAAC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED,qDAAqD;IACrD,aAAa,CAAC,KAAa;QACzB,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QAEhC,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QAC9E,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS;YAAE,OAAO,KAAK,CAAC;QAClG,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS;YAAE,OAAO,KAAK,CAAC;QAClG,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QAEjF,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAED,eAAe,WAAW,CAAC"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Wecon - Express.js routing with built-in RBAC
3
+ *
4
+ * Two-layer request processing:
5
+ * 1. Intelligence Layer: RaiMatcher validates and authorizes requests
6
+ * 2. Execution Layer: Single master Express Router handles the request
7
+ */
8
+ import type { RequestHandler } from "express";
9
+ import type { RAI, DefaultRole } from "../types.js";
10
+ import Routes from "./Routes.js";
11
+ import Route from "./Route.js";
12
+ /** Development mode configuration */
13
+ export interface WeconDevConfig {
14
+ /** Enable debug mode with verbose logging */
15
+ debugMode?: boolean;
16
+ /** Provide helpful error suggestions */
17
+ helpfulErrors?: boolean;
18
+ /** Log registered routes on startup */
19
+ logRoutes?: boolean;
20
+ }
21
+ /**
22
+ * Main Wecon class with fluent API.
23
+ * Compiles routes into a single master router with RBAC enforcement.
24
+ */
25
+ declare class Wecon<TRole extends string = DefaultRole> {
26
+ private _routes?;
27
+ private _roles;
28
+ private _guestRole;
29
+ private _onRoutesPrepared?;
30
+ private _dev?;
31
+ private _raiMatcher?;
32
+ private _masterRouter?;
33
+ private _built;
34
+ private _raisMap?;
35
+ private _middleware?;
36
+ constructor();
37
+ /** Set the root routes */
38
+ routes(routes: Routes<TRole>): this;
39
+ /** Define available roles */
40
+ roles<T extends string>(roles: readonly T[]): Wecon<T>;
41
+ /** Set guest role for unauthenticated users */
42
+ guestRole(guestRole: string): this;
43
+ /** Set callback for when routes are compiled */
44
+ onRoutesPrepared(callback: (routes: Route[]) => void | Promise<void>): this;
45
+ /** Configure development mode options */
46
+ dev(config: WeconDevConfig): this;
47
+ /**
48
+ * Compile all routes into the middleware.
49
+ * Must be called before using the Wecon instance.
50
+ */
51
+ build(): this;
52
+ /** Sort routes: static segments before dynamic */
53
+ private compareRoutes;
54
+ /** Create the main Express middleware (intelligence + execution layers) */
55
+ private createMiddleware;
56
+ private createHelpfulNotFoundError;
57
+ private createHelpfulUnauthorizedError;
58
+ /** Get all registered routes (must call build() first) */
59
+ getRoutes(): Route[];
60
+ /** Get a route by RAI */
61
+ getRoute(rai: RAI): Route | undefined;
62
+ /** Get the Express middleware function */
63
+ handler(): RequestHandler;
64
+ }
65
+ export default Wecon;
66
+ //# sourceMappingURL=Wecon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Wecon.d.ts","sourceRoot":"","sources":["../../src/routing/Wecon.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAGV,cAAc,EAGf,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,KAAK,MAAM,YAAY,CAAC;AAI/B,qCAAqC;AACrC,MAAM,WAAW,cAAc;IAC7B,6CAA6C;IAC7C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wCAAwC;IACxC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,uCAAuC;IACvC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;GAGG;AACH,cAAM,KAAK,CAAC,KAAK,SAAS,MAAM,GAAG,WAAW;IAC5C,OAAO,CAAC,OAAO,CAAC,CAAgB;IAChC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,UAAU,CAAmB;IACrC,OAAO,CAAC,iBAAiB,CAAC,CAAmD;IAC7E,OAAO,CAAC,IAAI,CAAC,CAAiB;IAE9B,OAAO,CAAC,WAAW,CAAC,CAAa;IACjC,OAAO,CAAC,aAAa,CAAC,CAAS;IAE/B,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,QAAQ,CAAC,CAAyB;IAC1C,OAAO,CAAC,WAAW,CAAC,CAAiB;;IAIrC,0BAA0B;IACnB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI;IAW1C,6BAA6B;IACtB,KAAK,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC;IAW7D,+CAA+C;IACxC,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAWzC,gDAAgD;IACzC,gBAAgB,CACrB,QAAQ,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAClD,IAAI;IAWP,yCAAyC;IAClC,GAAG,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAQxC;;;OAGG;IACI,KAAK,IAAI,IAAI;IA+EpB,kDAAkD;IAClD,OAAO,CAAC,aAAa;IAsBrB,2EAA2E;IAC3E,OAAO,CAAC,gBAAgB;IAiDxB,OAAO,CAAC,0BAA0B;IAelC,OAAO,CAAC,8BAA8B;IAatC,0DAA0D;IACnD,SAAS,IAAI,KAAK,EAAE;IAO3B,yBAAyB;IAClB,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,KAAK,GAAG,SAAS;IAO5C,0CAA0C;IACnC,OAAO,IAAI,cAAc;CAMjC;AAED,eAAe,KAAK,CAAC"}
@@ -0,0 +1,248 @@
1
+ /**
2
+ * Wecon - Express.js routing with built-in RBAC
3
+ *
4
+ * Two-layer request processing:
5
+ * 1. Intelligence Layer: RaiMatcher validates and authorizes requests
6
+ * 2. Execution Layer: Single master Express Router handles the request
7
+ */
8
+ import Routes from "./Routes.js";
9
+ import errors from "../errors/index.js";
10
+ import RaiMatcher from "./RaiMatcher.js";
11
+ /**
12
+ * Main Wecon class with fluent API.
13
+ * Compiles routes into a single master router with RBAC enforcement.
14
+ */
15
+ class Wecon {
16
+ _routes;
17
+ _roles = [];
18
+ _guestRole = "guest";
19
+ _onRoutesPrepared;
20
+ _dev;
21
+ _raiMatcher;
22
+ _masterRouter;
23
+ _built = false;
24
+ _raisMap;
25
+ _middleware;
26
+ constructor() { }
27
+ /** Set the root routes */
28
+ routes(routes) {
29
+ if (this._built) {
30
+ throw new Error("Cannot modify Wecon after build() has been called");
31
+ }
32
+ if (!(routes instanceof Routes)) {
33
+ throw new Error("routes() must receive an instance of the Routes class");
34
+ }
35
+ this._routes = routes;
36
+ return this;
37
+ }
38
+ /** Define available roles */
39
+ roles(roles) {
40
+ if (this._built) {
41
+ throw new Error("Cannot modify Wecon after build() has been called");
42
+ }
43
+ if (!Array.isArray(roles)) {
44
+ throw new Error("roles() must receive an array of strings");
45
+ }
46
+ this._roles = [...roles];
47
+ return this;
48
+ }
49
+ /** Set guest role for unauthenticated users */
50
+ guestRole(guestRole) {
51
+ if (this._built) {
52
+ throw new Error("Cannot modify Wecon after build() has been called");
53
+ }
54
+ if (typeof guestRole !== "string") {
55
+ throw new Error("guestRole() must receive a string");
56
+ }
57
+ this._guestRole = guestRole;
58
+ return this;
59
+ }
60
+ /** Set callback for when routes are compiled */
61
+ onRoutesPrepared(callback) {
62
+ if (this._built) {
63
+ throw new Error("Cannot modify Wecon after build() has been called");
64
+ }
65
+ if (typeof callback !== "function") {
66
+ throw new Error("onRoutesPrepared() must receive a function");
67
+ }
68
+ this._onRoutesPrepared = callback;
69
+ return this;
70
+ }
71
+ /** Configure development mode options */
72
+ dev(config) {
73
+ if (this._built) {
74
+ throw new Error("Cannot modify Wecon after build() has been called");
75
+ }
76
+ this._dev = config;
77
+ return this;
78
+ }
79
+ /**
80
+ * Compile all routes into the middleware.
81
+ * Must be called before using the Wecon instance.
82
+ */
83
+ build() {
84
+ if (this._built)
85
+ throw new Error("build() can only be called once");
86
+ if (!this._routes)
87
+ throw new Error("routes() must be called before build()");
88
+ if (this._roles.length === 0)
89
+ throw new Error("roles() missing");
90
+ this._built = true;
91
+ this._raisMap = this._routes.groupRoutesByRai();
92
+ // 1. Initialize RAI Matcher
93
+ const routesList = Array.from(this._raisMap.values()).map((r) => ({
94
+ path: r.path,
95
+ method: r.method,
96
+ rai: r.rai,
97
+ }));
98
+ this._raiMatcher = new RaiMatcher(routesList);
99
+ // 2. Create master router (dynamic import would be async, so we use require-style)
100
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
101
+ const { Router: ExpressRouter } = require("express");
102
+ this._masterRouter = ExpressRouter({ mergeParams: true });
103
+ // 3. Sort routes by specificity (static before dynamic)
104
+ const sortedRoutes = Array.from(this._raisMap.values()).sort(this.compareRoutes);
105
+ // 4. Register all routes on the master router
106
+ sortedRoutes.forEach((route) => {
107
+ // Register param handlers
108
+ route.params?.forEach((param) => {
109
+ this._masterRouter.param(param.path, param.middleware);
110
+ if (param.validate) {
111
+ this._masterRouter.param(param.path, (_req, _res, next, val) => {
112
+ if (!param.validateValue(val)) {
113
+ return next(new errors.RequestError("Invalid Parameter", {
114
+ code: "INVALID_PARAM",
115
+ }));
116
+ }
117
+ next();
118
+ });
119
+ }
120
+ });
121
+ // Register route by method
122
+ switch (route.method) {
123
+ case "GET":
124
+ this._masterRouter.get(route.path, ...route.middlewares);
125
+ break;
126
+ case "POST":
127
+ this._masterRouter.post(route.path, ...route.middlewares);
128
+ break;
129
+ case "PUT":
130
+ this._masterRouter.put(route.path, ...route.middlewares);
131
+ break;
132
+ case "DELETE":
133
+ this._masterRouter.delete(route.path, ...route.middlewares);
134
+ break;
135
+ }
136
+ });
137
+ // 5. Create the intelligence layer middleware
138
+ this._middleware = this.createMiddleware();
139
+ // 6. Notify callback
140
+ if (this._onRoutesPrepared) {
141
+ const result = this._onRoutesPrepared(sortedRoutes);
142
+ if (result instanceof Promise) {
143
+ result.catch((err) => {
144
+ console.error("Error in onRoutesPrepared callback:", err);
145
+ });
146
+ }
147
+ }
148
+ return this;
149
+ }
150
+ /** Sort routes: static segments before dynamic */
151
+ compareRoutes(a, b) {
152
+ const aSegments = a.path.split("/").filter(Boolean);
153
+ const bSegments = b.path.split("/").filter(Boolean);
154
+ const len = Math.max(aSegments.length, bSegments.length);
155
+ for (let i = 0; i < len; i++) {
156
+ const segA = aSegments[i];
157
+ const segB = bSegments[i];
158
+ if (segA === undefined)
159
+ return 1;
160
+ if (segB === undefined)
161
+ return -1;
162
+ const aIsDynamic = segA.startsWith(":");
163
+ const bIsDynamic = segB.startsWith(":");
164
+ if (aIsDynamic && !bIsDynamic)
165
+ return 1;
166
+ if (!aIsDynamic && bIsDynamic)
167
+ return -1;
168
+ }
169
+ return b.path.length - a.path.length;
170
+ }
171
+ /** Create the main Express middleware (intelligence + execution layers) */
172
+ createMiddleware() {
173
+ return async (req, res, next) => {
174
+ try {
175
+ // Intelligence Layer: match RAI and check authorization
176
+ const path = req.path;
177
+ const reqRai = this._raiMatcher.findRai(path, req.method);
178
+ if (!reqRai) {
179
+ const errorPath = req.originalUrl.split("?")[0];
180
+ res.status(404);
181
+ return next(new errors.RequestError(this._dev?.helpfulErrors
182
+ ? this.createHelpfulNotFoundError(errorPath, req.method)
183
+ : `Route not found`, { code: "RAI_NOT_FOUND" }));
184
+ }
185
+ const route = this._raisMap.get(reqRai);
186
+ req.rai = reqRai;
187
+ req.route_instance = route;
188
+ const user = req.user;
189
+ const userRoles = user?.roles || [this._guestRole];
190
+ if (!route.isAuthorized(userRoles)) {
191
+ const isGuest = userRoles.includes(this._guestRole) && userRoles.length === 1;
192
+ res.status(isGuest ? 401 : 403);
193
+ return next(new errors.RequestError(this._dev?.helpfulErrors
194
+ ? this.createHelpfulUnauthorizedError(route, userRoles)
195
+ : `Unauthorized`, { code: "UNAUTHORIZED" }));
196
+ }
197
+ // Execution Layer: delegate to master router
198
+ return this._masterRouter(req, res, next);
199
+ }
200
+ catch (error) {
201
+ return next(error);
202
+ }
203
+ };
204
+ }
205
+ createHelpfulNotFoundError(path, method) {
206
+ const availableRoutes = Array.from(this._raisMap.values())
207
+ .filter((r) => r.method === method)
208
+ .map((r) => r.path);
209
+ let message = `No route found for ${method} ${path}`;
210
+ if (availableRoutes.length > 0) {
211
+ message += `\n\nAvailable ${method} routes:\n`;
212
+ availableRoutes.forEach((route) => {
213
+ message += ` - ${route}\n`;
214
+ });
215
+ }
216
+ return message;
217
+ }
218
+ createHelpfulUnauthorizedError(route, userRoles) {
219
+ const isGuest = userRoles.length === 1 && userRoles[0] === this._guestRole;
220
+ if (isGuest) {
221
+ return `Authentication required to access ${route.method} ${route.path}\n\nThis route requires one of the following roles: ${route.roles.join(", ")}`;
222
+ }
223
+ return `Insufficient permissions to access ${route.method} ${route.path}\n\nRequired roles: ${route.roles.join(", ")}\nYour roles: ${userRoles.join(", ")}`;
224
+ }
225
+ /** Get all registered routes (must call build() first) */
226
+ getRoutes() {
227
+ if (!this._built) {
228
+ throw new Error("Cannot get routes before build() is called");
229
+ }
230
+ return Array.from(this._raisMap.values());
231
+ }
232
+ /** Get a route by RAI */
233
+ getRoute(rai) {
234
+ if (!this._built) {
235
+ throw new Error("Cannot get route before build() is called");
236
+ }
237
+ return this._raisMap.get(rai);
238
+ }
239
+ /** Get the Express middleware function */
240
+ handler() {
241
+ if (!this._built) {
242
+ throw new Error("Cannot get handler before build() is called. Make sure to call build() first.");
243
+ }
244
+ return this._middleware;
245
+ }
246
+ }
247
+ export default Wecon;
248
+ //# sourceMappingURL=Wecon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Wecon.js","sourceRoot":"","sources":["../../src/routing/Wecon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export { default as Wecon } from "./Wecon.js";
2
+ export type { WeconDevConfig } from "./Wecon.js";
3
+ export { default as Route } from "./Route.js";
4
+ export { default as Routes } from "./Routes.js";
5
+ export { default as RoutesParam } from "./RoutesParam.js";
6
+ export { default as RaiMatcher } from "./RaiMatcher.js";
7
+ export type { RaiRoutesList } from "./RaiMatcher.js";
8
+ export { ErrorCatcher } from "./ErrorCatcher.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/routing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,YAAY,CAAC;AAC9C,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACxD,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { default as Wecon } from "./Wecon.js";
2
+ export { default as Route } from "./Route.js";
3
+ export { default as Routes } from "./Routes.js";
4
+ export { default as RoutesParam } from "./RoutesParam.js";
5
+ export { default as RaiMatcher } from "./RaiMatcher.js";
6
+ export { ErrorCatcher } from "./ErrorCatcher.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/routing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,YAAY,CAAC;AAE9C,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAExD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
@@ -24,7 +24,9 @@ import http from "http";
24
24
  import https from "https";
25
25
  import type { Application, RequestHandler } from "express";
26
26
  import type { ResolvedConfig, WeconModule, WeconContext } from "../types.js";
27
+ import type Wecon from "../routing/Wecon.js";
27
28
  import { type DatabaseConnection } from "../database/index.js";
29
+ import { type DevToolsOptions } from "../devtools/index.js";
28
30
  /**
29
31
  * API Error format
30
32
  */
@@ -64,12 +66,10 @@ export interface CreateWeconOptions {
64
66
  */
65
67
  modules: WeconModule[];
66
68
  /**
67
- * The @weconjs/lib Wecon instance (for route handling)
68
- * If provided, wecon.handler() is mounted automatically
69
+ * The Wecon routing instance (for route handling).
70
+ * If provided, wecon.handler() is mounted automatically.
69
71
  */
70
- wecon?: {
71
- handler: () => RequestHandler;
72
- };
72
+ wecon?: Wecon;
73
73
  /**
74
74
  * Custom middleware to apply before routes
75
75
  */
@@ -140,6 +140,30 @@ export interface CreateWeconOptions {
140
140
  */
141
141
  logDir?: string;
142
142
  };
143
+ /**
144
+ * Module dependency options
145
+ */
146
+ moduleDeps?: {
147
+ /**
148
+ * Auto-install missing module dependencies
149
+ * @default true in development, false in production
150
+ */
151
+ autoInstall?: boolean;
152
+ /**
153
+ * Root directory for resolving module paths and node_modules
154
+ * @default process.cwd()
155
+ */
156
+ rootDir?: string;
157
+ /**
158
+ * Module paths (keyed by module name) for dependency checking.
159
+ * If not provided, dependency checking is skipped.
160
+ */
161
+ paths?: Record<string, string>;
162
+ };
163
+ /**
164
+ * DevTools REST API options
165
+ */
166
+ devtools?: DevToolsOptions;
143
167
  /**
144
168
  * Lifecycle hooks
145
169
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
@@ -28,6 +28,8 @@ import { createWinstonLogger, createConsoleLogger } from "../logger/index.js";
28
28
  import { createDatabaseConnection, buildUriFromConfig } from "../database/index.js";
29
29
  import { initI18n } from "../i18n/index.js";
30
30
  import { createContext } from "../context.js";
31
+ import { resolveAllModuleDeps } from "../module/index.js";
32
+ import { createDevToolsRouter } from "../devtools/index.js";
31
33
  /**
32
34
  * Install respond helper on Express Response prototype
33
35
  */
@@ -180,11 +182,31 @@ export async function createWecon(options) {
180
182
  // Dynamic import Express
181
183
  const express = (await import("express")).default;
182
184
  const app = express();
183
- // Create context (will update with app/io later)
185
+ // Validate and inject module configs
186
+ const moduleSchemas = new Map();
187
+ if (!config.moduleConfigs) {
188
+ config.moduleConfigs = {};
189
+ }
190
+ for (const mod of modules) {
191
+ if (mod.config?.schema) {
192
+ moduleSchemas.set(mod.name, mod.config.schema);
193
+ // Merge defaults with user-provided config, then validate
194
+ const userConfig = config.moduleConfigs[mod.name] ?? {};
195
+ const merged = { ...(mod.config.defaults ?? {}), ...userConfig };
196
+ const result = mod.config.schema.safeParse(merged);
197
+ if (!result.success) {
198
+ throw new Error(`[Wecon] Invalid config for module "${mod.name}": ${result.error.message}`);
199
+ }
200
+ config.moduleConfigs[mod.name] = result.data;
201
+ logger.debug(`Module config validated: ${mod.name}`);
202
+ }
203
+ }
204
+ // Create context with module schemas for runtime validation
184
205
  const ctx = createContext({
185
206
  config,
186
207
  app,
187
208
  logger,
209
+ moduleSchemas,
188
210
  });
189
211
  // Connect database if enabled
190
212
  let db;
@@ -264,11 +286,28 @@ export async function createWecon(options) {
264
286
  });
265
287
  }
266
288
  });
289
+ // Mount DevTools before Wecon RBAC routes (bypasses role checks)
290
+ const devToolsRouter = createDevToolsRouter(ctx, modules, options.devtools, wecon);
291
+ if (devToolsRouter) {
292
+ const prefix = options.devtools?.prefix ?? "/dev/devtools";
293
+ app.use(prefix, devToolsRouter);
294
+ }
267
295
  // Mount Wecon router if provided
268
296
  if (wecon) {
269
297
  app.use(wecon.handler());
270
298
  logger.debug("Wecon routes mounted");
271
299
  }
300
+ // Check and install module dependencies
301
+ if (options.moduleDeps?.paths) {
302
+ const rootDir = options.moduleDeps.rootDir ?? process.cwd();
303
+ const isDev = config.mode !== "production";
304
+ const autoInstall = options.moduleDeps.autoInstall ?? isDev;
305
+ const modulePaths = Object.entries(options.moduleDeps.paths).map(([name, p]) => ({
306
+ name,
307
+ path: p,
308
+ }));
309
+ await resolveAllModuleDeps(modulePaths, rootDir, logger, autoInstall);
310
+ }
272
311
  // Initialize modules
273
312
  for (const mod of modules) {
274
313
  if (mod.onInit) {