jcc-express-mvc 1.8.30 → 1.9.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 (118) hide show
  1. package/global.d.ts +5 -0
  2. package/lib/Application/ApplicationBuilder.d.ts.map +1 -1
  3. package/lib/Application/ApplicationBuilder.js +2 -0
  4. package/lib/Auth/index.d.ts +2 -2
  5. package/lib/Auth/index.d.ts.map +1 -1
  6. package/lib/Auth/index.js +26 -27
  7. package/lib/Command-Line/MakeCommand.d.ts +1 -0
  8. package/lib/Command-Line/MakeCommand.d.ts.map +1 -1
  9. package/lib/Command-Line/MakeCommand.js +21 -0
  10. package/lib/Command-Line/NodeArtisanCommand.d.ts.map +1 -1
  11. package/lib/Command-Line/NodeArtisanCommand.js +29 -10
  12. package/lib/Command-Line/PublishCommand.d.ts +16 -0
  13. package/lib/Command-Line/PublishCommand.d.ts.map +1 -1
  14. package/lib/Command-Line/PublishCommand.js +113 -43
  15. package/lib/Command-Line/files/MonitorConfigStub.d.ts.map +1 -1
  16. package/lib/Command-Line/files/MonitorConfigStub.js +21 -0
  17. package/lib/Command-Line/files/MonitorRouteStub.d.ts.map +1 -1
  18. package/lib/Command-Line/files/MonitorRouteStub.js +2 -2
  19. package/lib/Command-Line/files/MonitorTableStub.d.ts +2 -0
  20. package/lib/Command-Line/files/MonitorTableStub.d.ts.map +1 -0
  21. package/lib/Command-Line/files/MonitorTableStub.js +22 -0
  22. package/lib/Error/public/419.html +1 -1
  23. package/lib/Global/helpers.d.ts.map +1 -1
  24. package/lib/Global/helpers.js +4 -0
  25. package/lib/Interface/index.d.ts +0 -5
  26. package/lib/Interface/index.d.ts.map +1 -1
  27. package/lib/Logger/DailyFileTransport.d.ts +19 -0
  28. package/lib/Logger/DailyFileTransport.d.ts.map +1 -0
  29. package/lib/Logger/DailyFileTransport.js +52 -0
  30. package/lib/Logger/Logger.d.ts +56 -0
  31. package/lib/Logger/Logger.d.ts.map +1 -0
  32. package/lib/Logger/Logger.js +151 -0
  33. package/lib/Logger/channels.d.ts +5 -0
  34. package/lib/Logger/channels.d.ts.map +1 -0
  35. package/lib/Logger/channels.js +55 -0
  36. package/lib/Logger/config.d.ts +9 -0
  37. package/lib/Logger/config.d.ts.map +1 -0
  38. package/lib/Logger/config.js +38 -0
  39. package/lib/Logger/format.d.ts +7 -0
  40. package/lib/Logger/format.d.ts.map +1 -0
  41. package/lib/Logger/format.js +24 -0
  42. package/lib/Logger/index.d.ts +5 -0
  43. package/lib/Logger/index.d.ts.map +1 -0
  44. package/lib/Logger/index.js +9 -0
  45. package/lib/Logger/types.d.ts +28 -0
  46. package/lib/Logger/types.d.ts.map +1 -0
  47. package/lib/Logger/types.js +14 -0
  48. package/lib/Monitor/Collectors/LogCollector.d.ts +17 -0
  49. package/lib/Monitor/Collectors/LogCollector.d.ts.map +1 -0
  50. package/lib/Monitor/Collectors/LogCollector.js +60 -0
  51. package/lib/Monitor/Collectors/MailCollector.d.ts.map +1 -1
  52. package/lib/Monitor/Collectors/MailCollector.js +4 -2
  53. package/lib/Monitor/Collectors/QueueCollector.d.ts.map +1 -1
  54. package/lib/Monitor/Controllers/MonitorController.d.ts +25 -19
  55. package/lib/Monitor/Controllers/MonitorController.d.ts.map +1 -1
  56. package/lib/Monitor/Controllers/MonitorController.js +44 -7
  57. package/lib/Monitor/Middleware/MonitorMiddleware.d.ts.map +1 -1
  58. package/lib/Monitor/Middleware/MonitorMiddleware.js +40 -0
  59. package/lib/Monitor/MonitorManager.d.ts +10 -1
  60. package/lib/Monitor/MonitorManager.d.ts.map +1 -1
  61. package/lib/Monitor/MonitorManager.js +65 -0
  62. package/lib/Monitor/MonitorServiceProvider.d.ts.map +1 -1
  63. package/lib/Monitor/MonitorServiceProvider.js +7 -4
  64. package/lib/Monitor/Routes/monitor.routes.d.ts.map +1 -1
  65. package/lib/Monitor/Routes/monitor.routes.js +4 -2
  66. package/lib/Monitor/Storage/DatabaseStorage.d.ts +34 -0
  67. package/lib/Monitor/Storage/DatabaseStorage.d.ts.map +1 -0
  68. package/lib/Monitor/Storage/DatabaseStorage.js +113 -0
  69. package/lib/Monitor/Storage/FileStorage.d.ts +22 -0
  70. package/lib/Monitor/Storage/FileStorage.d.ts.map +1 -0
  71. package/lib/Monitor/Storage/FileStorage.js +145 -0
  72. package/lib/Monitor/Storage/MemoryStorage.d.ts +12 -0
  73. package/lib/Monitor/Storage/MemoryStorage.d.ts.map +1 -0
  74. package/lib/Monitor/Storage/MemoryStorage.js +22 -0
  75. package/lib/Monitor/Storage/MonitorStorage.d.ts +31 -0
  76. package/lib/Monitor/Storage/MonitorStorage.d.ts.map +1 -0
  77. package/lib/Monitor/Storage/MonitorStorage.js +27 -0
  78. package/lib/Monitor/Storage/RedisStorage.d.ts +29 -0
  79. package/lib/Monitor/Storage/RedisStorage.d.ts.map +1 -0
  80. package/lib/Monitor/Storage/RedisStorage.js +93 -0
  81. package/lib/Monitor/Storage/StorageFactory.d.ts +9 -0
  82. package/lib/Monitor/Storage/StorageFactory.d.ts.map +1 -0
  83. package/lib/Monitor/Storage/StorageFactory.js +92 -0
  84. package/lib/Monitor/UI/dashboard.html +190 -0
  85. package/lib/Monitor/Views/cache.blade.html +44 -0
  86. package/lib/Monitor/Views/commands.blade.html +42 -0
  87. package/lib/Monitor/Views/dashboard.blade.html +114 -0
  88. package/lib/Monitor/Views/exceptions.blade.html +38 -0
  89. package/lib/Monitor/Views/jobs.blade.html +44 -0
  90. package/lib/Monitor/Views/logs.blade.html +45 -0
  91. package/lib/Monitor/Views/mail.blade.html +44 -0
  92. package/lib/Monitor/Views/notifications.blade.html +42 -0
  93. package/lib/Monitor/Views/outgoing.blade.html +42 -0
  94. package/lib/Monitor/Views/partials/empty-state.blade.html +9 -0
  95. package/lib/Monitor/Views/partials/sidebar.blade.html +89 -0
  96. package/lib/Monitor/Views/partials/top-header.blade.html +15 -0
  97. package/lib/Monitor/Views/queries.blade.html +57 -0
  98. package/lib/Monitor/Views/requests.blade.html +44 -0
  99. package/lib/Monitor/Views/scheduled.blade.html +42 -0
  100. package/lib/Monitor/index.d.ts +10 -2
  101. package/lib/Monitor/index.d.ts.map +1 -1
  102. package/lib/Monitor/index.js +16 -1
  103. package/lib/Monitor/interfaces.d.ts +1 -0
  104. package/lib/Monitor/interfaces.d.ts.map +1 -1
  105. package/lib/Monitor/types.d.ts +50 -0
  106. package/lib/Monitor/types.d.ts.map +1 -1
  107. package/lib/Monitor/types.js +13 -1
  108. package/lib/Providers/LogServiceProvider.d.ts +11 -0
  109. package/lib/Providers/LogServiceProvider.d.ts.map +1 -0
  110. package/lib/Providers/LogServiceProvider.js +21 -0
  111. package/lib/Queue/Controllers/QueueControllers.d.ts +1 -1
  112. package/lib/Queue/Controllers/QueueControllers.d.ts.map +1 -1
  113. package/lib/Queue/JobsLogger.d.ts.map +1 -1
  114. package/lib/Queue/JobsLogger.js +6 -4
  115. package/lib/Type/HttpContext.d.ts +7 -0
  116. package/lib/Type/HttpContext.d.ts.map +1 -0
  117. package/lib/Type/HttpContext.js +2 -0
  118. package/package.json +1 -1
package/global.d.ts CHANGED
@@ -16,6 +16,7 @@ import { Container } from "./lib/Container";
16
16
  import { Carbon } from "./lib/Date";
17
17
  import { GateFacade } from "./lib/Authorization";
18
18
  import { Authentication as Auth } from "./lib/Auth/index";
19
+ import { Log } from "./lib/Logger/Logger";
19
20
 
20
21
  declare global {
21
22
  var app: Container;
@@ -61,6 +62,10 @@ declare global {
61
62
  var authorize: typeof GateFacade.authorize;
62
63
  var session: () => Request["jccSession"];
63
64
  var defer: (callback: () => any) => void;
65
+ var logger: (
66
+ message: string | Error,
67
+ context?: any,
68
+ ) => OmitThisParameter<(typeof Log)["info"]>;
64
69
  }
65
70
 
66
71
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"ApplicationBuilder.d.ts","sourceRoot":"","sources":["../../../jcc-express-mvc/lib/Application/ApplicationBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAG/D,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAU3C,qBAAa,kBAAkB;IACtB,GAAG,EAAE,WAAW,CAAC;gBAEZ,GAAG,EAAE,WAAW;IAIrB,UAAU,CAAC,MAAM,EAAE,GAAG;IAKtB,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAMtC,WAAW,CAAC,WAAW,EAAE,WAAW,EAAE;IAOtC,aAAa,CAClB,SAAS,EAAE,KAAK,CAAC,KAAK,GAAG,EAAE,WAAW,KAAK,eAAe,CAAC;IA0B7D,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,gBAAgB;IAIjB,WAAW;IAKX,cAAc;IAWd,MAAM;CAKd"}
1
+ {"version":3,"file":"ApplicationBuilder.d.ts","sourceRoot":"","sources":["../../../jcc-express-mvc/lib/Application/ApplicationBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAG/D,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAW3C,qBAAa,kBAAkB;IACtB,GAAG,EAAE,WAAW,CAAC;gBAEZ,GAAG,EAAE,WAAW;IAIrB,UAAU,CAAC,MAAM,EAAE,GAAG;IAKtB,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAMtC,WAAW,CAAC,WAAW,EAAE,WAAW,EAAE;IAOtC,aAAa,CAClB,SAAS,EAAE,KAAK,CAAC,KAAK,GAAG,EAAE,WAAW,KAAK,eAAe,CAAC;IA2B7D,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,gBAAgB;IAIjB,WAAW;IAKX,cAAc;IAWd,MAAM;CAKd"}
@@ -9,6 +9,7 @@ const AuthServiceProvider_1 = require("../Providers/AuthServiceProvider");
9
9
  const SessionServiceProvider_1 = require("../Providers/SessionServiceProvider");
10
10
  const QueueServiceProvider_1 = require("../Queue/QueueServiceProvider");
11
11
  const CacheServiceProvider_1 = require("../Providers/CacheServiceProvider");
12
+ const LogServiceProvider_1 = require("../Providers/LogServiceProvider");
12
13
  class ApplicationBuilder {
13
14
  constructor(app) {
14
15
  this.app = app;
@@ -37,6 +38,7 @@ class ApplicationBuilder {
37
38
  ]
38
39
  : providers;
39
40
  const chain = [
41
+ LogServiceProvider_1.LogServiceProvider,
40
42
  DatabaseServiceProvider_1.DatabaseServiceProvider,
41
43
  SessionServiceProvider_1.SessionServiceProvider,
42
44
  CacheServiceProvider_1.CacheServiceProvider,
@@ -11,7 +11,7 @@ export declare class Authentication {
11
11
  /** Generate and attach tokens to cookies (refresh is rotated server-side via `jti`). */
12
12
  private static setTokens;
13
13
  /** Handle user login attempt */
14
- static attempt: (next: AppNext, redirect?: string) => Promise<void>;
14
+ static attempt(next: AppNext, redirect?: string): Promise<void>;
15
15
  /**
16
16
  * After the user is resolved (e.g. OAuth via Socialite), issue JWT cookies
17
17
  * and redirect or JSON response like {@link Authentication.attempt}.
@@ -25,6 +25,6 @@ export declare class Authentication {
25
25
  static check(): boolean;
26
26
  static user(): Record<string, any>;
27
27
  static id(): any;
28
- static socialLogin(userId: string | number): Promise<void>;
28
+ static socialLogin(userId: string | number, redirect?: string): Promise<void>;
29
29
  }
30
30
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../jcc-express-mvc/lib/Auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAgBhE,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,qBAAqB,CAAC;AAsB7B,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAC,YAAY,CAAgD;IAE3E,2EAA2E;IAC3E,MAAM,CAAC,oBAAoB,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAI5D,qDAAqD;IACrD,OAAO,CAAC,MAAM,CAAC,cAAc;IAc7B,0DAA0D;mBACrC,OAAO;IAqB5B,wFAAwF;IACxF,OAAO,CAAC,MAAM,CAAC,SAAS;IA0BxB,gCAAgC;IAChC,MAAM,CAAC,OAAO,GAAU,MAAM,OAAO,EAAE,WAAU,MAAgB,mBAsB/D;IAEF;;;OAGG;WACU,aAAa,CACxB,GAAG,EAAE,UAAU,EACf,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,QAAQ,GAAE,MAAgB,GACzB,OAAO,CAAC,IAAI,CAAC;IA4BhB,+BAA+B;WAClB,YAAY,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO;IAsC1E,qBAAqB;IACrB,MAAM,CAAC,MAAM;IAsBb,4FAA4F;IAC5F,MAAM,CAAC,KAAK,IAAI,OAAO;IAWvB,MAAM,CAAC,IAAI;IAIX,MAAM,CAAC,EAAE;WAII,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;CAGjD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../jcc-express-mvc/lib/Auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAgBhE,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,qBAAqB,CAAC;AAsB7B,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAC,YAAY,CAAgD;IAE3E,2EAA2E;IAC3E,MAAM,CAAC,oBAAoB,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAI5D,qDAAqD;IACrD,OAAO,CAAC,MAAM,CAAC,cAAc;IAc7B,0DAA0D;mBACrC,OAAO;IAqB5B,wFAAwF;IACxF,OAAO,CAAC,MAAM,CAAC,SAAS;IA0BxB,gCAAgC;WACnB,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,GAAE,MAAgB;IA2B9D;;;OAGG;WACU,aAAa,CACxB,GAAG,EAAE,UAAU,EACf,GAAG,EAAE,WAAW,EAChB,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,QAAQ,GAAE,MAAgB,GACzB,OAAO,CAAC,IAAI,CAAC;IA4BhB,+BAA+B;WAClB,YAAY,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO;IAsC1E,qBAAqB;IACrB,MAAM,CAAC,MAAM;IAsBb,4FAA4F;IAC5F,MAAM,CAAC,KAAK,IAAI,OAAO;IAWvB,MAAM,CAAC,IAAI;IAIX,MAAM,CAAC,EAAE;WAII,WAAW,CACtB,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,QAAQ,GAAE,MAAgB;CAI7B"}
package/lib/Auth/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  "use strict";
2
- var _a;
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
4
3
  exports.Authentication = void 0;
5
4
  const util_1 = require("../util");
@@ -26,7 +25,7 @@ function safeInternalRedirect(url, fallback) {
26
25
  class Authentication {
27
26
  /** Use a shared store (e.g. Redis) when running multiple app instances. */
28
27
  static setRefreshTokenStore(store) {
29
- _a.refreshStore = store;
28
+ Authentication.refreshStore = store;
30
29
  }
31
30
  /** Get user lookup field (email, phone, username) */
32
31
  static getCredentials(data) {
@@ -67,8 +66,8 @@ class Authentication {
67
66
  /** Generate and attach tokens to cookies (refresh is rotated server-side via `jti`). */
68
67
  static setTokens(res, userId) {
69
68
  const id = String(userId);
70
- const jti = _a.refreshStore.generateJti();
71
- _a.refreshStore.register(jti, id, REFRESH_TTL_MS);
69
+ const jti = Authentication.refreshStore.generateJti();
70
+ Authentication.refreshStore.register(jti, id, REFRESH_TTL_MS);
72
71
  const accessToken = (0, util_1.jwtSign)(id, { expiresIn: "1h" });
73
72
  const refreshToken = (0, util_1.jwtSign)({ id, typ: "refresh", jti }, { expiresIn: "7d" });
74
73
  const cookieOptions = (0, util_1.authSessionCookieOptions)();
@@ -82,6 +81,25 @@ class Authentication {
82
81
  });
83
82
  return { accessToken, refreshToken };
84
83
  }
84
+ /** Handle user login attempt */
85
+ static async attempt(next, redirect = "/home") {
86
+ const req = request();
87
+ const res = response();
88
+ try {
89
+ const { user, field } = await this.getUser(req.body);
90
+ if (!user)
91
+ throw new ValidationException_v2_1.ValidationException({ [field]: ["Invalid credentials"] });
92
+ // Guard against OAuth users or accounts with no password set
93
+ if (!user.password ||
94
+ !(await (0, util_1.verifyHash)(req.body.password, user.password))) {
95
+ throw new ValidationException_v2_1.ValidationException({ [field]: ["Invalid credentials"] });
96
+ }
97
+ await Authentication.completeLogin(req, res, user.id || user._id, redirect);
98
+ }
99
+ catch (error) {
100
+ next(error);
101
+ }
102
+ }
85
103
  /**
86
104
  * After the user is resolved (e.g. OAuth via Socialite), issue JWT cookies
87
105
  * and redirect or JSON response like {@link Authentication.attempt}.
@@ -133,7 +151,7 @@ class Authentication {
133
151
  if (!jti) {
134
152
  throw new Error("Invalid refresh token");
135
153
  }
136
- const session = _a.refreshStore.consume(jti);
154
+ const session = Authentication.refreshStore.consume(jti);
137
155
  const userId = (0, util_1.jwtSubjectId)(payload);
138
156
  if (!session || session.userId !== String(userId)) {
139
157
  throw new Error("Invalid refresh token");
@@ -158,7 +176,7 @@ class Authentication {
158
176
  if (payload != null &&
159
177
  typeof payload === "object" &&
160
178
  typeof payload.jti === "string") {
161
- _a.refreshStore.revoke(payload.jti);
179
+ Authentication.refreshStore.revoke(payload.jti);
162
180
  }
163
181
  }
164
182
  }
@@ -187,28 +205,9 @@ class Authentication {
187
205
  static id() {
188
206
  return request().user?.id || request().user?._id;
189
207
  }
190
- static async socialLogin(userId) {
191
- return this.completeLogin(request(), response(), userId, "/home");
208
+ static async socialLogin(userId, redirect = "/home") {
209
+ return this.completeLogin(request(), response(), userId, redirect);
192
210
  }
193
211
  }
194
212
  exports.Authentication = Authentication;
195
- _a = Authentication;
196
213
  Authentication.refreshStore = refreshTokenStore_1.defaultRefreshTokenStore;
197
- /** Handle user login attempt */
198
- Authentication.attempt = async (next, redirect = "/home") => {
199
- const req = request();
200
- const res = response();
201
- try {
202
- const { user, field } = await _a.getUser(req.body);
203
- if (!user)
204
- throw new ValidationException_v2_1.ValidationException({ [field]: ["Invalid credentials"] });
205
- // Guard against OAuth users or accounts with no password set
206
- if (!user.password || !(await (0, util_1.verifyHash)(req.body.password, user.password))) {
207
- throw new ValidationException_v2_1.ValidationException({ [field]: ["Invalid credentials"] });
208
- }
209
- await _a.completeLogin(req, res, user.id || user._id, redirect);
210
- }
211
- catch (error) {
212
- next(error);
213
- }
214
- };
@@ -10,6 +10,7 @@ export declare class MakeCommand {
10
10
  createJob(job: string): any;
11
11
  createEventListener(event: string, listener?: string): any;
12
12
  createQueueTable(): void;
13
+ createMonitorTable(): void;
13
14
  createObserver(name: string, model?: string): any;
14
15
  createPolicy(name: string, model?: string): any;
15
16
  createCommand(name: string, customSignature?: string): any;
@@ -1 +1 @@
1
- {"version":3,"file":"MakeCommand.d.ts","sourceRoot":"","sources":["../../../jcc-express-mvc/lib/Command-Line/MakeCommand.ts"],"names":[],"mappings":"AAkCA,qBAAa,WAAW;IACtB,OAAO,CAAC,aAAa,CAA0C;IAE/D,gBAAgB,CAAC,cAAc,EAAE,MAAM,EAAE,SAAS,UAAQ,GAAG,GAAG;IAsChE,mBAAmB,CAAC,cAAc,EAAE,MAAM,EAAE,SAAS,UAAQ,GAAG,GAAG;IAkDnE,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,GAAG;IAuBnC,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,GAAG;IA4BvC,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,GAAG;IA4BlE,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG;IA2B/B,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG;IA8B/B,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG;IA8B3B,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,GAAG;IAmC1D,gBAAgB;IA+BhB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,GAAG;IAiCjD,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,GAAG;IAmC/C,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,GAAG;IAmC1D,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IA+BjC,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IA+BpD,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAiC7B,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IA8BhC,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG;CAkCrC"}
1
+ {"version":3,"file":"MakeCommand.d.ts","sourceRoot":"","sources":["../../../jcc-express-mvc/lib/Command-Line/MakeCommand.ts"],"names":[],"mappings":"AAmCA,qBAAa,WAAW;IACtB,OAAO,CAAC,aAAa,CAA0C;IAE/D,gBAAgB,CAAC,cAAc,EAAE,MAAM,EAAE,SAAS,UAAQ,GAAG,GAAG;IAsChE,mBAAmB,CAAC,cAAc,EAAE,MAAM,EAAE,SAAS,UAAQ,GAAG,GAAG;IAkDnE,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,GAAG;IAuBnC,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,GAAG;IA4BvC,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,GAAG;IA4BlE,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG;IA2B/B,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG;IA8B/B,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG;IA8B3B,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,GAAG;IAmC1D,gBAAgB;IA+BhB,kBAAkB;IAyBlB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,GAAG;IAiCjD,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,GAAG;IAmC/C,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,GAAG;IAmC1D,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IA+BjC,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI;IA+BpD,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAiC7B,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IA8BhC,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG;CAkCrC"}
@@ -18,6 +18,7 @@ const Seeder_1 = __importDefault(require("./files/Seeder"));
18
18
  const Event_1 = __importDefault(require("./files/Event"));
19
19
  const Listener_1 = __importDefault(require("./files/Listener"));
20
20
  const jobs_1 = require("./files/jobs");
21
+ const MonitorTableStub_1 = require("./files/MonitorTableStub");
21
22
  const jobClass_1 = require("./files/jobClass");
22
23
  const Observer_1 = __importDefault(require("./files/Observer"));
23
24
  const Policy_1 = __importDefault(require("./files/Policy"));
@@ -279,6 +280,26 @@ class MakeCommand {
279
280
  console.log(error);
280
281
  }
281
282
  }
283
+ createMonitorTable() {
284
+ try {
285
+ const migrationPath = path_1.default.resolve(`${rootPath}/database/migrations`);
286
+ if (!fs_1.default.existsSync(migrationPath)) {
287
+ fs_1.default.mkdirSync(migrationPath, { recursive: true });
288
+ }
289
+ const exists = fs_1.default
290
+ .readdirSync(migrationPath)
291
+ .some((f) => f.endsWith(`_monitor_records_table.${this.fileExtension}`));
292
+ if (exists) {
293
+ return console.log(colors_1.default.yellow("monitor_records table already exists"));
294
+ }
295
+ fs_1.default.writeFileSync(`${migrationPath}/${(0, utils_1.formatDate)()}_monitor_records_table.${this.fileExtension}`, MonitorTableStub_1.monitorRecordsMigration);
296
+ return console.log(colors_1.default.green("Monitor table created successfully"));
297
+ }
298
+ catch (error) {
299
+ console.log(colors_1.default.red("Monitor table not created"));
300
+ console.log(error);
301
+ }
302
+ }
282
303
  createObserver(name, model) {
283
304
  try {
284
305
  if (!name) {
@@ -1 +1 @@
1
- {"version":3,"file":"NodeArtisanCommand.d.ts","sourceRoot":"","sources":["../../../jcc-express-mvc/lib/Command-Line/NodeArtisanCommand.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwCpC,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAK1B;IACF,OAAO,CAAC,cAAc,CAA0B;IAChD,OAAO,CAAC,QAAQ,CAAwB;IACxC,OAAO,CAAC,GAAG,CAA0B;IACrC,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,SAAS,CAAgC;IACjD,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,IAAI,CAAc;IAC1B,OAAO,CAAC,MAAM,CAA6B;IAE3C,OAAO,KAAK,OAAO,GAElB;IAED,OAAO,KAAK,EAAE,GAEb;IAED,OAAO,KAAK,IAAI,GAEf;IAED,OAAO,KAAK,KAAK,GAEhB;IAED,OAAO,KAAK,QAAQ,GAEnB;IAED,OAAO,KAAK,KAAK,GAEhB;IAED,OAAO,KAAK,KAAK,GAEhB;IAED,OAAO,CAAC,GAAG;;IAWX,0FAA0F;IAC1F,OAAO,CAAC,kBAAkB;IA0B1B,OAAO,CAAC,aAAa;IAOrB,wFAAwF;IACxF,OAAO,CAAC,SAAS;IAkBjB,OAAO,CAAC,aAAa;IA4OrB,OAAO,CAAC,QAAQ;IAmJhB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;CA4BpD"}
1
+ {"version":3,"file":"NodeArtisanCommand.d.ts","sourceRoot":"","sources":["../../../jcc-express-mvc/lib/Command-Line/NodeArtisanCommand.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyCpC,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiB;IACzC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAK1B;IACF,OAAO,CAAC,cAAc,CAA0B;IAChD,OAAO,CAAC,QAAQ,CAAwB;IACxC,OAAO,CAAC,GAAG,CAA0B;IACrC,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,SAAS,CAAgC;IACjD,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,IAAI,CAAc;IAC1B,OAAO,CAAC,MAAM,CAA6B;IAE3C,OAAO,KAAK,OAAO,GAElB;IAED,OAAO,KAAK,EAAE,GAEb;IAED,OAAO,KAAK,IAAI,GAEf;IAED,OAAO,KAAK,KAAK,GAEhB;IAED,OAAO,KAAK,QAAQ,GAEnB;IAED,OAAO,KAAK,KAAK,GAEhB;IAED,OAAO,KAAK,KAAK,GAEhB;IAED,OAAO,CAAC,GAAG;;IAWX,0FAA0F;IAC1F,OAAO,CAAC,kBAAkB;IA0B1B,OAAO,CAAC,aAAa;IAQrB,wFAAwF;IACxF,OAAO,CAAC,SAAS;IAkBjB,OAAO,CAAC,aAAa;IAkQrB,OAAO,CAAC,QAAQ;IA+JhB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;CA4BpD"}
@@ -104,13 +104,14 @@ class ConsoleKernel {
104
104
  return this.program
105
105
  .command(name)
106
106
  .argument("[firstArg]")
107
- .argument("[secondArg]");
107
+ .argument("[secondArg]")
108
+ .argument("[thirdArg]");
108
109
  }
109
110
  /** Wrap action with error handling; call process.exit when done (unless longRunning) */
110
111
  runAction(handler, options = { exit: true }) {
111
- return async (firstArg, secondArg) => {
112
+ return async (firstArg, secondArg, thirdArg) => {
112
113
  try {
113
- await handler(firstArg ?? "", secondArg ?? "");
114
+ await handler(firstArg ?? "", secondArg ?? "", thirdArg ?? "");
114
115
  if (options.exit !== false)
115
116
  process.exit(0);
116
117
  }
@@ -152,6 +153,10 @@ class ConsoleKernel {
152
153
  this.make.createQueueTable();
153
154
  await this.migrate.runMigration();
154
155
  }));
156
+ this.defineCommand("make:monitor-table").action(this.runAction(async () => {
157
+ this.make.createMonitorTable();
158
+ await this.migrate.runMigration();
159
+ }));
155
160
  this.defineCommand("make:job").action(this.runAction((name) => this.make.createJob(name)));
156
161
  this.defineCommand("make:observer").action(this.runAction((name, secondArg) => {
157
162
  const model = parseOption(secondArg, "model");
@@ -223,16 +228,28 @@ class ConsoleKernel {
223
228
  //cache
224
229
  // ─── publish ────────────────────────────────────────────────────────
225
230
  this.defineCommand("publish")
226
- .description("Publish a framework component (config, providers, routes)")
227
- .action(this.runAction((firstArg, secondArg) => {
231
+ .description("Publish a framework component (config, providers, routes). " +
232
+ "For Monitor pass a view: jsblade (default), react or vue — " +
233
+ "e.g. `publish Monitor react`.")
234
+ .action(this.runAction((firstArg, secondArg, thirdArg) => {
228
235
  // Support both `publish Monitor` and `publish=Monitor` shorthand
229
236
  // (in which case commander gives us "publish=Monitor" as the cmd
230
237
  // — handled by parsing the first segment).
231
238
  const tag = firstArg.includes("=") ? firstArg.split("=")[1] : firstArg;
232
- const force = parseOption(secondArg, "force") === "true" ||
233
- secondArg === "--force" ||
234
- secondArg === "-f";
235
- const cmd = new PublishCommand_1.PublishCommand({ force });
239
+ // Remaining tokens are the view (e.g. `react` / `view=react`) and/or
240
+ // the force flag (`force=true` / `--force` / `-f`), in any order.
241
+ const isForce = (t) => t === "--force" ||
242
+ t === "-f" ||
243
+ parseOption(t, "force") === "true" ||
244
+ t === "force=true";
245
+ const tokens = [secondArg, thirdArg].filter(Boolean);
246
+ const force = tokens.some(isForce);
247
+ const viewToken = tokens.find((t) => !isForce(t));
248
+ const view = viewToken
249
+ ? parseOption(viewToken, "view") ??
250
+ (viewToken.includes("=") ? viewToken.split("=")[1] : viewToken)
251
+ : undefined;
252
+ const cmd = new PublishCommand_1.PublishCommand({ force, view });
236
253
  if (!tag) {
237
254
  cmd.list();
238
255
  return;
@@ -279,6 +296,7 @@ class ConsoleKernel {
279
296
  console.log(line("make:command <name> [signature=]", "Create a new console command class"));
280
297
  console.log(line("make:test <name>", "Create a new feature test (e.g. UsersTest)"));
281
298
  console.log(line("make:queue-table", "Create migration for queue tables"));
299
+ console.log(line("make:monitor-table", "Create migration for the Monitor records table (database storage driver)"));
282
300
  console.log(line("make:service <name>", "Create a new service class in app/Services"));
283
301
  console.log(line("make:repository <name> [model=]", "Create a new repository class in app/Repositories"));
284
302
  console.log(line("make:dto <name>", "Create a new DTO class in app/DTOs"));
@@ -305,7 +323,8 @@ class ConsoleKernel {
305
323
  console.log(section("🌐 Inertia Commands:"));
306
324
  console.log(line("inertia:start-ssr", "Start the Inertia.js SSR server\n"));
307
325
  console.log(section("📦 Publish Commands:"));
308
- console.log(line("publish [tag] [force=true]", "Publish a framework component (e.g. publish Monitor)\n"));
326
+ console.log(line("publish [tag] [view] [force=true]", "Publish a framework component (e.g. publish Monitor)"));
327
+ console.log(line("", "Monitor views: jsblade (default), react, vue — e.g. publish Monitor vue\n"));
309
328
  if (this.customCommands.length > 0) {
310
329
  console.log(section("ℹ️ Custom:"));
311
330
  this.customCommands.forEach((c) => console.log(line(c.signature, c.description)));
@@ -1,7 +1,23 @@
1
+ /**
2
+ * View stacks the Monitor dashboard can be published as.
3
+ *
4
+ * jsblade — jsBlade templates rendered server-side (default)
5
+ * react — React + Inertia page components
6
+ * vue — Vue 3 + Inertia page components
7
+ */
8
+ export declare const MONITOR_VIEWS: readonly ["jsblade", "react", "vue"];
9
+ export type MonitorView = (typeof MONITOR_VIEWS)[number];
10
+ export declare const DEFAULT_MONITOR_VIEW: MonitorView;
11
+ /** Resolve a (possibly aliased / undefined) view name to a known stack. */
12
+ export declare function resolveMonitorView(requested?: string): {
13
+ view: MonitorView;
14
+ unknown?: string;
15
+ };
1
16
  export declare class PublishCommand {
2
17
  private opts;
3
18
  constructor(opts?: {
4
19
  force?: boolean;
20
+ view?: string;
5
21
  });
6
22
  static availableTags(): string[];
7
23
  list(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"PublishCommand.d.ts","sourceRoot":"","sources":["../../../jcc-express-mvc/lib/Command-Line/PublishCommand.ts"],"names":[],"mappings":"AA8OA,qBAAa,cAAc;IACb,OAAO,CAAC,IAAI;gBAAJ,IAAI,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO;IAElD,MAAM,CAAC,aAAa,IAAI,MAAM,EAAE;IAIhC,IAAI,IAAI,IAAI;IAaZ,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAsC1B,OAAO,CAAC,QAAQ;IAehB,OAAO,CAAC,WAAW;IA4BnB,OAAO,CAAC,WAAW;CAkBpB"}
1
+ {"version":3,"file":"PublishCommand.d.ts","sourceRoot":"","sources":["../../../jcc-express-mvc/lib/Command-Line/PublishCommand.ts"],"names":[],"mappings":"AAgFA;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,sCAAuC,CAAC;AAClE,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AACzD,eAAO,MAAM,oBAAoB,EAAE,WAAuB,CAAC;AAa3D,2EAA2E;AAC3E,wBAAgB,kBAAkB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG;IACtD,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAMA;AA2MD,qBAAa,cAAc;IACb,OAAO,CAAC,IAAI;gBAAJ,IAAI,GAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAO;IAEjE,MAAM,CAAC,aAAa,IAAI,MAAM,EAAE;IAIhC,IAAI,IAAI,IAAI;IAkBZ,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IA4D1B,OAAO,CAAC,QAAQ;IAehB,OAAO,CAAC,WAAW;IA4BnB,OAAO,CAAC,WAAW;CAkBpB"}
@@ -3,7 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.PublishCommand = void 0;
6
+ exports.PublishCommand = exports.DEFAULT_MONITOR_VIEW = exports.MONITOR_VIEWS = void 0;
7
+ exports.resolveMonitorView = resolveMonitorView;
7
8
  const fs_1 = __importDefault(require("fs"));
8
9
  const path_1 = __importDefault(require("path"));
9
10
  const colors_1 = __importDefault(require("colors"));
@@ -44,15 +45,87 @@ function insertImport(source, line) {
44
45
  return line + "\n" + source;
45
46
  return source.slice(0, lastEnd) + "\n" + line + source.slice(lastEnd);
46
47
  }
47
- /** Read a framework-bundled Monitor view (Blade) and return it verbatim. */
48
- function readMonitorView(name) {
49
- return () => {
50
- const p = path_1.default.join(__dirname, "..", "Monitor", "Views", name);
51
- return fs_1.default.readFileSync(p, "utf8");
52
- };
48
+ /**
49
+ * View stacks the Monitor dashboard can be published as.
50
+ *
51
+ * jsblade jsBlade templates rendered server-side (default)
52
+ * react — React + Inertia page components
53
+ * vue — Vue 3 + Inertia page components
54
+ */
55
+ exports.MONITOR_VIEWS = ["jsblade", "react", "vue"];
56
+ exports.DEFAULT_MONITOR_VIEW = "jsblade";
57
+ /** Aliases accepted on the CLI for each Monitor view stack. */
58
+ const MONITOR_VIEW_ALIASES = {
59
+ blade: "jsblade",
60
+ "js-blade": "jsblade",
61
+ jsblade: "jsblade",
62
+ react: "react",
63
+ jsx: "react",
64
+ vue: "vue",
65
+ vuejs: "vue",
66
+ };
67
+ /** Resolve a (possibly aliased / undefined) view name to a known stack. */
68
+ function resolveMonitorView(requested) {
69
+ const key = (requested ?? "").toLowerCase().trim();
70
+ if (!key)
71
+ return { view: exports.DEFAULT_MONITOR_VIEW };
72
+ const view = MONITOR_VIEW_ALIASES[key];
73
+ if (!view)
74
+ return { view: exports.DEFAULT_MONITOR_VIEW, unknown: requested };
75
+ return { view };
53
76
  }
54
- const publishables = {
55
- Monitor: {
77
+ /** Lazily read a framework-bundled file under `jcc-express-mvc/lib/Monitor/Views`. */
78
+ function readBundledView(...segments) {
79
+ return () => fs_1.default.readFileSync(path_1.default.join(__dirname, "..", "Monitor", "Views", ...segments), "utf8");
80
+ }
81
+ const MONITOR_PAGES = [
82
+ "dashboard",
83
+ "requests",
84
+ "jobs",
85
+ "commands",
86
+ "scheduled",
87
+ "exceptions",
88
+ "queries",
89
+ "notifications",
90
+ "mail",
91
+ "cache",
92
+ "outgoing",
93
+ ];
94
+ const MONITOR_PARTIALS = ["sidebar", "top-header", "empty-state"];
95
+ /** Files copied for a given Monitor view stack (everything else stays the same). */
96
+ function monitorViewFiles(view) {
97
+ if (view === "jsblade") {
98
+ return [
99
+ // Page views (each renders one Monitor section under the shared sidebar)
100
+ ...MONITOR_PAGES.map((name) => ({
101
+ src: readBundledView("JSBlade", `${name}.blade.html`),
102
+ dest: path_1.default.join(root, "resources", "views", "monitor", `${name}.blade.html`),
103
+ description: `Monitor ${name} view`,
104
+ })),
105
+ // Shared partials (sidebar, top header, empty-state)
106
+ ...MONITOR_PARTIALS.map((name) => ({
107
+ src: readBundledView("JSBlade", "partials", `${name}.blade.html`),
108
+ dest: path_1.default.join(root, "resources", "views", "partials", "monitor", `${name}.blade.html`),
109
+ description: `Monitor ${name} partial`,
110
+ })),
111
+ ];
112
+ }
113
+ // react | vue — Inertia page components + their shared helpers land together
114
+ // under resources/js/Pages/Monitor so the relative imports keep resolving.
115
+ const dir = view === "react" ? "React" : "Vue";
116
+ const srcDir = path_1.default.join(__dirname, "..", "Monitor", "Views", dir);
117
+ if (!fs_1.default.existsSync(srcDir)) {
118
+ throw new Error(`Monitor "${view}" views are not bundled with this framework build (${rel(srcDir)} not found).`);
119
+ }
120
+ return fs_1.default.readdirSync(srcDir).map((file) => ({
121
+ src: readBundledView(dir, file),
122
+ dest: path_1.default.join(root, "resources", "js", "Pages", "Monitor", file),
123
+ description: `Monitor ${file}`,
124
+ }));
125
+ }
126
+ /** Build the Monitor publishable for the chosen view stack. */
127
+ function monitorPublishable(view) {
128
+ return {
56
129
  files: [
57
130
  {
58
131
  src: MonitorConfigStub_1.default,
@@ -61,37 +134,10 @@ const publishables = {
61
134
  },
62
135
  {
63
136
  src: MonitorRouteStub_1.default,
64
- dest: path_1.default.join(root, "route", "monitor.ts"),
137
+ dest: path_1.default.join(root, "routes", "monitor.ts"),
65
138
  description: "Monitor route definitions",
66
139
  },
67
- // Page views (each renders one Monitor section under the shared sidebar)
68
- ...[
69
- "dashboard",
70
- "requests",
71
- "jobs",
72
- "commands",
73
- "scheduled",
74
- "exceptions",
75
- "queries",
76
- "notifications",
77
- "mail",
78
- "cache",
79
- "outgoing",
80
- ].map((name) => ({
81
- src: readMonitorView(`${name}.blade.html`),
82
- dest: path_1.default.join(root, "resources", "views", "monitor", `${name}.blade.html`),
83
- description: `Monitor ${name} view`,
84
- })),
85
- // Shared partials (sidebar, top header, empty-state)
86
- ...[
87
- "sidebar",
88
- "top-header",
89
- "empty-state",
90
- ].map((name) => ({
91
- src: readMonitorView(`partials/${name}.blade.html`),
92
- dest: path_1.default.join(root, "resources", "views", "partials", "monitor", `${name}.blade.html`),
93
- description: `Monitor ${name} partial`,
94
- })),
140
+ ...monitorViewFiles(view),
95
141
  ],
96
142
  configInserts: [
97
143
  {
@@ -180,7 +226,15 @@ const publishables = {
180
226
  },
181
227
  },
182
228
  ],
183
- },
229
+ };
230
+ }
231
+ /**
232
+ * Registry of publishables. Each entry is a builder so paths/contents are
233
+ * resolved fresh per invocation and options (e.g. the chosen Monitor view
234
+ * stack) can be threaded through.
235
+ */
236
+ const publishables = {
237
+ Monitor: ({ view }) => monitorPublishable(view),
184
238
  };
185
239
  class PublishCommand {
186
240
  constructor(opts = {}) {
@@ -196,17 +250,26 @@ class PublishCommand {
196
250
  }
197
251
  console.log();
198
252
  console.log(colors_1.default.gray("Usage: ") +
199
- colors_1.default.cyan("bun artisanNode publish <tag> [force=true]"));
253
+ colors_1.default.cyan("bun artisanNode publish <tag> [view] [force=true]"));
254
+ console.log(colors_1.default.gray(" Monitor views: ") +
255
+ colors_1.default.cyan(exports.MONITOR_VIEWS.join(", ")) +
256
+ colors_1.default.gray(` (default: ${exports.DEFAULT_MONITOR_VIEW})`));
200
257
  console.log();
201
258
  }
202
259
  publish(tag) {
203
- const spec = publishables[tag];
204
- if (!spec) {
260
+ const build = publishables[tag];
261
+ if (!build) {
205
262
  console.log(colors_1.default.red(`\n❌ Unknown publishable: ${tag}\n`));
206
263
  this.list();
207
264
  return;
208
265
  }
209
- console.log(colors_1.default.green.bold(`\n📦 Publishing ${tag}\n`));
266
+ const { view, unknown } = resolveMonitorView(this.opts.view);
267
+ if (unknown) {
268
+ console.log(colors_1.default.yellow(`\n⚠ Unknown view "${unknown}" — using "${view}". Choices: ${exports.MONITOR_VIEWS.join(", ")}.`));
269
+ }
270
+ const spec = build({ view });
271
+ const label = tag === "Monitor" ? `${tag} (${view} views)` : tag;
272
+ console.log(colors_1.default.green.bold(`\n📦 Publishing ${label}\n`));
210
273
  // 1) Copy stub files.
211
274
  for (const f of spec.files) {
212
275
  this.copyFile(f);
@@ -224,6 +287,13 @@ class PublishCommand {
224
287
  this.applyAppend(a);
225
288
  }
226
289
  console.log(colors_1.default.green("\n✓ Done.\n"));
290
+ if (tag === "Monitor" && view !== "jsblade") {
291
+ console.log(colors_1.default.gray("Inertia pages were written to ") +
292
+ colors_1.default.cyan("resources/js/Pages/Monitor/") +
293
+ colors_1.default.gray(` — make sure the Inertia ${view} adapter is set up and rebuild client assets (`) +
294
+ colors_1.default.cyan("npm run watch") +
295
+ colors_1.default.gray(")."));
296
+ }
227
297
  console.log(colors_1.default.gray("Restart your dev server (") +
228
298
  colors_1.default.cyan("npm run dev") +
229
299
  colors_1.default.gray(") to load the changes.\n"));
@@ -1 +1 @@
1
- {"version":3,"file":"MonitorConfigStub.d.ts","sourceRoot":"","sources":["../../../../jcc-express-mvc/lib/Command-Line/files/MonitorConfigStub.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,iBAAiB,QAAO,MAwE7B,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"MonitorConfigStub.d.ts","sourceRoot":"","sources":["../../../../jcc-express-mvc/lib/Command-Line/files/MonitorConfigStub.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,iBAAiB,QAAO,MA6F7B,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -49,6 +49,27 @@ export const monitor: Partial<MonitorConfig> = {
49
49
  recentQueries: 100,
50
50
  },
51
51
 
52
+ // Persistence for the recent-* record streams. \`memory\` (default) keeps
53
+ // everything in-process. Switch to \`file\`, \`redis\`, or \`database\` to
54
+ // survive restarts. For \`database\`, run \`bun artisanNode make:monitor-table\`.
55
+ storage: {
56
+ driver: config.get("MONITOR_STORAGE", "memory") as
57
+ | "memory"
58
+ | "file"
59
+ | "redis"
60
+ | "database",
61
+ file: {
62
+ path: config.get("MONITOR_STORAGE_PATH", "storage/monitor"),
63
+ },
64
+ redis: {
65
+ connection: config.get("MONITOR_REDIS_URL", "redis://127.0.0.1:6379"),
66
+ prefix: config.get("MONITOR_REDIS_PREFIX", "monitor"),
67
+ },
68
+ database: {
69
+ table: config.get("MONITOR_DB_TABLE", "monitor_records"),
70
+ },
71
+ },
72
+
52
73
  alerts: {
53
74
  enabled: false,
54
75
  tickIntervalMs: 30_000,
@@ -1 +1 @@
1
- {"version":3,"file":"MonitorRouteStub.d.ts","sourceRoot":"","sources":["../../../../jcc-express-mvc/lib/Command-Line/files/MonitorRouteStub.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,gBAAgB,QAAO,MAiC5B,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"MonitorRouteStub.d.ts","sourceRoot":"","sources":["../../../../jcc-express-mvc/lib/Command-Line/files/MonitorRouteStub.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,gBAAgB,QAChB,MAiCL,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const monitorRouteStub = () => `import { Route } from "../jcc-express-mvc/Core";
4
- import { MonitorController } from "../jcc-express-mvc/lib/Monitor/Controllers/MonitorController";
3
+ const monitorRouteStub = () => `import { Route } from "jcc-express-mvc/Core";
4
+ import { MonitorController } from "jcc-express-mvc/lib/Monitor/Controllers/MonitorController";
5
5
 
6
6
  /**
7
7
  * Monitor routes — published from \`bun artisanNode publish Monitor\`.
@@ -0,0 +1,2 @@
1
+ export declare const monitorRecordsMigration = "\nimport { Schema } from \"jcc-express-mvc/Eloquent\";\n\nexport class Migration {\n up() {\n return Schema.create(\"monitor_records\", (table) => {\n table.id();\n table.string(\"type\", 32);\n table.text(\"payload\");\n table.timestamp(\"created_at\").useCurrent();\n table.index([\"type\", \"id\"]);\n });\n }\n\n down() {\n return Schema.dropTable(\"monitor_records\");\n }\n}\n";
2
+ //# sourceMappingURL=MonitorTableStub.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MonitorTableStub.d.ts","sourceRoot":"","sources":["../../../../jcc-express-mvc/lib/Command-Line/files/MonitorTableStub.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB,yaAkBnC,CAAC"}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.monitorRecordsMigration = void 0;
4
+ exports.monitorRecordsMigration = `
5
+ import { Schema } from "jcc-express-mvc/Eloquent";
6
+
7
+ export class Migration {
8
+ up() {
9
+ return Schema.create("monitor_records", (table) => {
10
+ table.id();
11
+ table.string("type", 32);
12
+ table.text("payload");
13
+ table.timestamp("created_at").useCurrent();
14
+ table.index(["type", "id"]);
15
+ });
16
+ }
17
+
18
+ down() {
19
+ return Schema.dropTable("monitor_records");
20
+ }
21
+ }
22
+ `;
@@ -131,7 +131,7 @@
131
131
  <div class="card">
132
132
  <div class="icon">!</div>
133
133
 
134
- <h1>Security verification failed</h1>
134
+ <h1>419 Security verification failed</h1>
135
135
 
136
136
  <p>
137
137
  Your request couldn’t be processed because the security token is invalid