jcc-express-mvc 1.8.29 → 1.8.30

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 (145) hide show
  1. package/lib/Command-Line/NodeArtisanCommand.d.ts.map +1 -1
  2. package/lib/Command-Line/NodeArtisanCommand.js +28 -2
  3. package/lib/Command-Line/PublishCommand.d.ts +13 -0
  4. package/lib/Command-Line/PublishCommand.d.ts.map +1 -0
  5. package/lib/Command-Line/PublishCommand.js +279 -0
  6. package/lib/Command-Line/files/Controller.js +6 -6
  7. package/lib/Command-Line/files/MonitorConfigStub.d.ts +3 -0
  8. package/lib/Command-Line/files/MonitorConfigStub.d.ts.map +1 -0
  9. package/lib/Command-Line/files/MonitorConfigStub.js +76 -0
  10. package/lib/Command-Line/files/MonitorRouteStub.d.ts +3 -0
  11. package/lib/Command-Line/files/MonitorRouteStub.d.ts.map +1 -0
  12. package/lib/Command-Line/files/MonitorRouteStub.js +37 -0
  13. package/lib/Error/AppErrorHandler.js +1 -1
  14. package/lib/Error/public/419.html +150 -0
  15. package/lib/Inertia/index.d.ts.map +1 -1
  16. package/lib/Inertia/index.js +7 -3
  17. package/lib/Monitor/Collectors/CacheCollector.d.ts +16 -0
  18. package/lib/Monitor/Collectors/CacheCollector.d.ts.map +1 -0
  19. package/lib/Monitor/Collectors/CacheCollector.js +79 -0
  20. package/lib/Monitor/Collectors/CommandCollector.d.ts +16 -0
  21. package/lib/Monitor/Collectors/CommandCollector.d.ts.map +1 -0
  22. package/lib/Monitor/Collectors/CommandCollector.js +24 -0
  23. package/lib/Monitor/Collectors/DatabaseCollector.d.ts +34 -0
  24. package/lib/Monitor/Collectors/DatabaseCollector.d.ts.map +1 -0
  25. package/lib/Monitor/Collectors/DatabaseCollector.js +56 -0
  26. package/lib/Monitor/Collectors/ErrorCollector.d.ts +16 -0
  27. package/lib/Monitor/Collectors/ErrorCollector.d.ts.map +1 -0
  28. package/lib/Monitor/Collectors/ErrorCollector.js +26 -0
  29. package/lib/Monitor/Collectors/HttpCollector.d.ts +14 -0
  30. package/lib/Monitor/Collectors/HttpCollector.d.ts.map +1 -0
  31. package/lib/Monitor/Collectors/HttpCollector.js +22 -0
  32. package/lib/Monitor/Collectors/MailCollector.d.ts +16 -0
  33. package/lib/Monitor/Collectors/MailCollector.d.ts.map +1 -0
  34. package/lib/Monitor/Collectors/MailCollector.js +73 -0
  35. package/lib/Monitor/Collectors/NotificationCollector.d.ts +15 -0
  36. package/lib/Monitor/Collectors/NotificationCollector.d.ts.map +1 -0
  37. package/lib/Monitor/Collectors/NotificationCollector.js +21 -0
  38. package/lib/Monitor/Collectors/OutgoingRequestCollector.d.ts +18 -0
  39. package/lib/Monitor/Collectors/OutgoingRequestCollector.d.ts.map +1 -0
  40. package/lib/Monitor/Collectors/OutgoingRequestCollector.js +75 -0
  41. package/lib/Monitor/Collectors/QueueCollector.d.ts +26 -0
  42. package/lib/Monitor/Collectors/QueueCollector.d.ts.map +1 -0
  43. package/lib/Monitor/Collectors/QueueCollector.js +55 -0
  44. package/lib/Monitor/Collectors/ScheduleCollector.d.ts +15 -0
  45. package/lib/Monitor/Collectors/ScheduleCollector.d.ts.map +1 -0
  46. package/lib/Monitor/Collectors/ScheduleCollector.js +22 -0
  47. package/lib/Monitor/Collectors/SystemCollector.d.ts +15 -0
  48. package/lib/Monitor/Collectors/SystemCollector.d.ts.map +1 -0
  49. package/lib/Monitor/Collectors/SystemCollector.js +56 -0
  50. package/lib/Monitor/Controllers/MonitorController.d.ts +37 -0
  51. package/lib/Monitor/Controllers/MonitorController.d.ts.map +1 -0
  52. package/lib/Monitor/Controllers/MonitorController.js +205 -0
  53. package/lib/Monitor/Exporters/JsonExporter.d.ts +8 -0
  54. package/lib/Monitor/Exporters/JsonExporter.d.ts.map +1 -0
  55. package/lib/Monitor/Exporters/JsonExporter.js +12 -0
  56. package/lib/Monitor/Exporters/LogExporter.d.ts +25 -0
  57. package/lib/Monitor/Exporters/LogExporter.d.ts.map +1 -0
  58. package/lib/Monitor/Exporters/LogExporter.js +50 -0
  59. package/lib/Monitor/Exporters/PrometheusExporter.d.ts +7 -0
  60. package/lib/Monitor/Exporters/PrometheusExporter.d.ts.map +1 -0
  61. package/lib/Monitor/Exporters/PrometheusExporter.js +51 -0
  62. package/lib/Monitor/Exporters/PushExporter.d.ts +27 -0
  63. package/lib/Monitor/Exporters/PushExporter.d.ts.map +1 -0
  64. package/lib/Monitor/Exporters/PushExporter.js +54 -0
  65. package/lib/Monitor/HealthCheck/HealthRegistry.d.ts +13 -0
  66. package/lib/Monitor/HealthCheck/HealthRegistry.d.ts.map +1 -0
  67. package/lib/Monitor/HealthCheck/HealthRegistry.js +41 -0
  68. package/lib/Monitor/HealthCheck/checks/CacheCheck.d.ts +19 -0
  69. package/lib/Monitor/HealthCheck/checks/CacheCheck.d.ts.map +1 -0
  70. package/lib/Monitor/HealthCheck/checks/CacheCheck.js +25 -0
  71. package/lib/Monitor/HealthCheck/checks/DatabaseCheck.d.ts +23 -0
  72. package/lib/Monitor/HealthCheck/checks/DatabaseCheck.d.ts.map +1 -0
  73. package/lib/Monitor/HealthCheck/checks/DatabaseCheck.js +20 -0
  74. package/lib/Monitor/HealthCheck/checks/DiskCheck.d.ts +16 -0
  75. package/lib/Monitor/HealthCheck/checks/DiskCheck.d.ts.map +1 -0
  76. package/lib/Monitor/HealthCheck/checks/DiskCheck.js +41 -0
  77. package/lib/Monitor/HealthCheck/checks/MemoryCheck.d.ts +15 -0
  78. package/lib/Monitor/HealthCheck/checks/MemoryCheck.d.ts.map +1 -0
  79. package/lib/Monitor/HealthCheck/checks/MemoryCheck.js +25 -0
  80. package/lib/Monitor/HealthCheck/checks/QueueCheck.d.ts +19 -0
  81. package/lib/Monitor/HealthCheck/checks/QueueCheck.d.ts.map +1 -0
  82. package/lib/Monitor/HealthCheck/checks/QueueCheck.js +24 -0
  83. package/lib/Monitor/Metrics/Counter.d.ts +12 -0
  84. package/lib/Monitor/Metrics/Counter.d.ts.map +1 -0
  85. package/lib/Monitor/Metrics/Counter.js +37 -0
  86. package/lib/Monitor/Metrics/Gauge.d.ts +13 -0
  87. package/lib/Monitor/Metrics/Gauge.d.ts.map +1 -0
  88. package/lib/Monitor/Metrics/Gauge.js +38 -0
  89. package/lib/Monitor/Metrics/Histogram.d.ts +11 -0
  90. package/lib/Monitor/Metrics/Histogram.d.ts.map +1 -0
  91. package/lib/Monitor/Metrics/Histogram.js +40 -0
  92. package/lib/Monitor/Metrics/Registry.d.ts +15 -0
  93. package/lib/Monitor/Metrics/Registry.d.ts.map +1 -0
  94. package/lib/Monitor/Metrics/Registry.js +53 -0
  95. package/lib/Monitor/Metrics/labelKey.d.ts +3 -0
  96. package/lib/Monitor/Metrics/labelKey.d.ts.map +1 -0
  97. package/lib/Monitor/Metrics/labelKey.js +9 -0
  98. package/lib/Monitor/Middleware/MonitorMiddleware.d.ts +13 -0
  99. package/lib/Monitor/Middleware/MonitorMiddleware.d.ts.map +1 -0
  100. package/lib/Monitor/Middleware/MonitorMiddleware.js +68 -0
  101. package/lib/Monitor/MonitorManager.d.ts +60 -0
  102. package/lib/Monitor/MonitorManager.d.ts.map +1 -0
  103. package/lib/Monitor/MonitorManager.js +360 -0
  104. package/lib/Monitor/MonitorServiceProvider.d.ts +34 -0
  105. package/lib/Monitor/MonitorServiceProvider.d.ts.map +1 -0
  106. package/lib/Monitor/MonitorServiceProvider.js +277 -0
  107. package/lib/Monitor/Notifications/AlertManager.d.ts +7 -0
  108. package/lib/Monitor/Notifications/AlertManager.d.ts.map +1 -0
  109. package/lib/Monitor/Notifications/AlertManager.js +22 -0
  110. package/lib/Monitor/Notifications/AlertRule.d.ts +17 -0
  111. package/lib/Monitor/Notifications/AlertRule.d.ts.map +1 -0
  112. package/lib/Monitor/Notifications/AlertRule.js +13 -0
  113. package/lib/Monitor/Notifications/EmailNotifier.d.ts +28 -0
  114. package/lib/Monitor/Notifications/EmailNotifier.d.ts.map +1 -0
  115. package/lib/Monitor/Notifications/EmailNotifier.js +52 -0
  116. package/lib/Monitor/Notifications/LogNotifier.d.ts +7 -0
  117. package/lib/Monitor/Notifications/LogNotifier.d.ts.map +1 -0
  118. package/lib/Monitor/Notifications/LogNotifier.js +17 -0
  119. package/lib/Monitor/Routes/monitor.routes.d.ts +21 -0
  120. package/lib/Monitor/Routes/monitor.routes.d.ts.map +1 -0
  121. package/lib/Monitor/Routes/monitor.routes.js +30 -0
  122. package/lib/Monitor/Storage/RingBuffer.d.ts +11 -0
  123. package/lib/Monitor/Storage/RingBuffer.d.ts.map +1 -0
  124. package/lib/Monitor/Storage/RingBuffer.js +34 -0
  125. package/lib/Monitor/index.d.ts +81 -0
  126. package/lib/Monitor/index.d.ts.map +1 -0
  127. package/lib/Monitor/index.js +137 -0
  128. package/lib/Monitor/interfaces.d.ts +73 -0
  129. package/lib/Monitor/interfaces.d.ts.map +1 -0
  130. package/lib/Monitor/interfaces.js +2 -0
  131. package/lib/Monitor/types.d.ts +223 -0
  132. package/lib/Monitor/types.d.ts.map +1 -0
  133. package/lib/Monitor/types.js +62 -0
  134. package/lib/Queue/Drivers/DatabaseDriver.d.ts.map +1 -1
  135. package/lib/Queue/Drivers/DatabaseDriver.js +25 -21
  136. package/lib/Templating-engine/engineHelper.d.ts.map +1 -1
  137. package/lib/Templating-engine/engineHelper.js +95 -30
  138. package/lib/Templating-engine/expressions.d.ts.map +1 -1
  139. package/lib/Templating-engine/expressions.js +11 -11
  140. package/lib/Templating-engine/index.d.ts +16 -6
  141. package/lib/Templating-engine/index.d.ts.map +1 -1
  142. package/lib/Templating-engine/index.js +273 -123
  143. package/lib/util/index.d.ts.map +1 -1
  144. package/lib/util/index.js +7 -3
  145. package/package.json +1 -1
@@ -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;AAuCpC,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;IA6MrB,OAAO,CAAC,QAAQ;IA2IhB,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;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"}
@@ -23,6 +23,7 @@ const Tinker_1 = require("./NodeTinker/Tinker");
23
23
  const WatchCommand_1 = require("./WatchCommand");
24
24
  const util_1 = require("../util");
25
25
  const CacheCommand_1 = require("./CacheCommand");
26
+ const PublishCommand_1 = require("./PublishCommand");
26
27
  /** Parse key=value from secondArg (e.g. steps=2, class=UserSeeder) */
27
28
  const parseOption = (secondArg, key) => {
28
29
  if (!secondArg?.includes("="))
@@ -190,11 +191,16 @@ class ConsoleKernel {
190
191
  }));
191
192
  this.defineCommand("db:wipe").action(this.runAction(() => this.db.wipe()));
192
193
  // ─── route / queue / tinker / inertia ─────────────────────────────────
193
- this.defineCommand("queue:work").action(this.runAction(async (queueName) => {
194
+ this.defineCommand("queue:work").action(this.runAction(async (queueName, secondArg) => {
195
+ const rawConcurrency = Number(parseOption(secondArg, "concurrency") ?? 1);
196
+ const concurrency = Math.min(Math.max(1, rawConcurrency), 5);
194
197
  console.log("\n");
195
198
  console.log(`${colors_1.default.bgBlue(" INFO ")} Starting the queue worker... \n`);
199
+ if (concurrency > 1) {
200
+ console.log(`${colors_1.default.bgBlue(" INFO ")} Running with ${concurrency} concurrent workers \n`);
201
+ }
196
202
  const queue = app.resolve("Queue");
197
- await queue.work(queueName || undefined);
203
+ await queue.work(queueName || undefined, concurrency);
198
204
  }, { exit: false }));
199
205
  this.defineCommand("route:list").action(this.runAction((firstArg) => {
200
206
  const mw = firstArg?.includes("middleware")
@@ -215,6 +221,24 @@ class ConsoleKernel {
215
221
  exit: true,
216
222
  }));
217
223
  //cache
224
+ // ─── publish ────────────────────────────────────────────────────────
225
+ this.defineCommand("publish")
226
+ .description("Publish a framework component (config, providers, routes)")
227
+ .action(this.runAction((firstArg, secondArg) => {
228
+ // Support both `publish Monitor` and `publish=Monitor` shorthand
229
+ // (in which case commander gives us "publish=Monitor" as the cmd
230
+ // — handled by parsing the first segment).
231
+ 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 });
236
+ if (!tag) {
237
+ cmd.list();
238
+ return;
239
+ }
240
+ cmd.publish(tag);
241
+ }));
218
242
  // ─── schedule (was missing) ─────────────────────────────────────────
219
243
  this.defineCommand("schedule:run").action(this.runAction(() => this.schedule.run(), { exit: false }));
220
244
  this.defineCommand("schedule:list").action(this.runAction(() => this.schedule.list()));
@@ -280,6 +304,8 @@ class ConsoleKernel {
280
304
  console.log(line("schedule:list", "List all scheduled tasks\n"));
281
305
  console.log(section("🌐 Inertia Commands:"));
282
306
  console.log(line("inertia:start-ssr", "Start the Inertia.js SSR server\n"));
307
+ console.log(section("📦 Publish Commands:"));
308
+ console.log(line("publish [tag] [force=true]", "Publish a framework component (e.g. publish Monitor)\n"));
283
309
  if (this.customCommands.length > 0) {
284
310
  console.log(section("ℹ️ Custom:"));
285
311
  this.customCommands.forEach((c) => console.log(line(c.signature, c.description)));
@@ -0,0 +1,13 @@
1
+ export declare class PublishCommand {
2
+ private opts;
3
+ constructor(opts?: {
4
+ force?: boolean;
5
+ });
6
+ static availableTags(): string[];
7
+ list(): void;
8
+ publish(tag: string): void;
9
+ private copyFile;
10
+ private applyInsert;
11
+ private applyAppend;
12
+ }
13
+ //# sourceMappingURL=PublishCommand.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,279 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PublishCommand = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const colors_1 = __importDefault(require("colors"));
10
+ const app_root_path_1 = __importDefault(require("app-root-path"));
11
+ const MonitorConfigStub_1 = __importDefault(require("./files/MonitorConfigStub"));
12
+ const MonitorRouteStub_1 = __importDefault(require("./files/MonitorRouteStub"));
13
+ const root = app_root_path_1.default.path;
14
+ const rel = (p) => path_1.default.relative(root, p) || p;
15
+ /**
16
+ * Idempotent file modifier. Logs and returns the new content (or null on
17
+ * skip). Never throws on already-applied edits.
18
+ */
19
+ function modify(file, fn) {
20
+ if (!fs_1.default.existsSync(file))
21
+ return "missing";
22
+ const src = fs_1.default.readFileSync(file, "utf8");
23
+ const next = fn(src);
24
+ if (next === null)
25
+ return "skipped";
26
+ if (next === src)
27
+ return "skipped";
28
+ fs_1.default.writeFileSync(file, next, "utf8");
29
+ return "added";
30
+ }
31
+ /**
32
+ * Insert `line` after the last existing import, or at the top of the file if
33
+ * there are no imports yet.
34
+ */
35
+ function insertImport(source, line) {
36
+ if (source.includes(line.trim()))
37
+ return null;
38
+ const importRe = /^import .+;\s*$/gm;
39
+ let lastEnd = -1;
40
+ for (const m of source.matchAll(importRe)) {
41
+ lastEnd = (m.index ?? 0) + m[0].length;
42
+ }
43
+ if (lastEnd === -1)
44
+ return line + "\n" + source;
45
+ return source.slice(0, lastEnd) + "\n" + line + source.slice(lastEnd);
46
+ }
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
+ };
53
+ }
54
+ const publishables = {
55
+ Monitor: {
56
+ files: [
57
+ {
58
+ src: MonitorConfigStub_1.default,
59
+ dest: path_1.default.join(root, "app", "Config", "monitor.ts"),
60
+ description: "Monitor config",
61
+ },
62
+ {
63
+ src: MonitorRouteStub_1.default,
64
+ dest: path_1.default.join(root, "route", "monitor.ts"),
65
+ description: "Monitor route definitions",
66
+ },
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
+ })),
95
+ ],
96
+ configInserts: [
97
+ {
98
+ file: path_1.default.join(root, "app", "Config", "index.ts"),
99
+ importLine: `import { monitor } from "./monitor";`,
100
+ alreadyWiredMarker: /\bmonitor\b\s*[,}\n]/,
101
+ injector: (src) => {
102
+ // 1) Add import.
103
+ const withImport = insertImport(src, `import { monitor } from "./monitor";`) ?? src;
104
+ // 2) Add `monitor,` inside the exported config object.
105
+ // Find `export const config = {` ... matching `}`.
106
+ const startMatch = withImport.match(/export\s+const\s+config\s*=\s*\{/);
107
+ if (!startMatch)
108
+ return null;
109
+ const start = (startMatch.index ?? 0) + startMatch[0].length;
110
+ // Find the matching closing brace at depth 0.
111
+ let depth = 1;
112
+ let i = start;
113
+ for (; i < withImport.length; i++) {
114
+ const c = withImport[i];
115
+ if (c === "{")
116
+ depth++;
117
+ else if (c === "}") {
118
+ depth--;
119
+ if (depth === 0)
120
+ break;
121
+ }
122
+ }
123
+ if (depth !== 0)
124
+ return null;
125
+ // Walk back from `}` to find the previous non-whitespace char to
126
+ // see if we need a trailing comma before our insert.
127
+ let j = i - 1;
128
+ while (j > start && /\s/.test(withImport[j]))
129
+ j--;
130
+ const needsComma = withImport[j] !== "{" && withImport[j] !== ",";
131
+ const insertion = `${needsComma ? "," : ""}\n monitor,\n`;
132
+ return (withImport.slice(0, j + 1) +
133
+ insertion +
134
+ withImport.slice(j + 1).replace(/^\s*/, ""));
135
+ },
136
+ },
137
+ ],
138
+ appends: [
139
+ {
140
+ file: path_1.default.join(root, "route", "web.ts"),
141
+ line: `require("./monitor");`,
142
+ presenceMarker: /require\(["']\.\/monitor["']\)/,
143
+ description: "loaded monitor routes",
144
+ },
145
+ ],
146
+ providerInserts: [
147
+ {
148
+ file: path_1.default.join(root, "bootstrap", "providers.ts"),
149
+ importLine: `import { MonitorServiceProvider } from "jcc-express-mvc/lib/Monitor";`,
150
+ alreadyWiredMarker: /MonitorServiceProvider/,
151
+ injector: (src) => {
152
+ const withImport = insertImport(src, `import { MonitorServiceProvider } from "jcc-express-mvc/lib/Monitor";`) ?? src;
153
+ // Insert `MonitorServiceProvider,` inside `export const providers = [...]`.
154
+ const startMatch = withImport.match(/export\s+const\s+providers\s*=\s*\[/);
155
+ if (!startMatch)
156
+ return null;
157
+ const start = (startMatch.index ?? 0) + startMatch[0].length;
158
+ let depth = 1;
159
+ let i = start;
160
+ for (; i < withImport.length; i++) {
161
+ const c = withImport[i];
162
+ if (c === "[")
163
+ depth++;
164
+ else if (c === "]") {
165
+ depth--;
166
+ if (depth === 0)
167
+ break;
168
+ }
169
+ }
170
+ if (depth !== 0)
171
+ return null;
172
+ let j = i - 1;
173
+ while (j > start && /\s/.test(withImport[j]))
174
+ j--;
175
+ const needsComma = withImport[j] !== "[" && withImport[j] !== ",";
176
+ const insertion = `${needsComma ? "," : ""}\n MonitorServiceProvider,\n`;
177
+ return (withImport.slice(0, j + 1) +
178
+ insertion +
179
+ withImport.slice(j + 1).replace(/^\s*/, ""));
180
+ },
181
+ },
182
+ ],
183
+ },
184
+ };
185
+ class PublishCommand {
186
+ constructor(opts = {}) {
187
+ this.opts = opts;
188
+ }
189
+ static availableTags() {
190
+ return Object.keys(publishables);
191
+ }
192
+ list() {
193
+ console.log(colors_1.default.green.bold("\nAvailable publishables:\n"));
194
+ for (const tag of Object.keys(publishables)) {
195
+ console.log(" " + colors_1.default.cyan(tag));
196
+ }
197
+ console.log();
198
+ console.log(colors_1.default.gray("Usage: ") +
199
+ colors_1.default.cyan("bun artisanNode publish <tag> [force=true]"));
200
+ console.log();
201
+ }
202
+ publish(tag) {
203
+ const spec = publishables[tag];
204
+ if (!spec) {
205
+ console.log(colors_1.default.red(`\n❌ Unknown publishable: ${tag}\n`));
206
+ this.list();
207
+ return;
208
+ }
209
+ console.log(colors_1.default.green.bold(`\n📦 Publishing ${tag}\n`));
210
+ // 1) Copy stub files.
211
+ for (const f of spec.files) {
212
+ this.copyFile(f);
213
+ }
214
+ // 2) Wire config.
215
+ for (const ins of spec.configInserts ?? []) {
216
+ this.applyInsert(ins, "config");
217
+ }
218
+ // 3) Wire providers.
219
+ for (const ins of spec.providerInserts ?? []) {
220
+ this.applyInsert(ins, "provider");
221
+ }
222
+ // 4) Append require()-style side-effect lines (e.g. route/web.ts).
223
+ for (const a of spec.appends ?? []) {
224
+ this.applyAppend(a);
225
+ }
226
+ console.log(colors_1.default.green("\n✓ Done.\n"));
227
+ console.log(colors_1.default.gray("Restart your dev server (") +
228
+ colors_1.default.cyan("npm run dev") +
229
+ colors_1.default.gray(") to load the changes.\n"));
230
+ }
231
+ copyFile(f) {
232
+ const exists = fs_1.default.existsSync(f.dest);
233
+ if (exists && !this.opts.force) {
234
+ console.log(` ${colors_1.default.yellow("skip")} ${rel(f.dest)} (already exists, use force=true to overwrite)`);
235
+ return;
236
+ }
237
+ fs_1.default.mkdirSync(path_1.default.dirname(f.dest), { recursive: true });
238
+ fs_1.default.writeFileSync(f.dest, f.src(), "utf8");
239
+ console.log(` ${colors_1.default.green(exists ? "overwrite" : "create")} ${rel(f.dest)} ${colors_1.default.gray(`— ${f.description}`)}`);
240
+ }
241
+ applyInsert(ins, kind) {
242
+ if (!fs_1.default.existsSync(ins.file)) {
243
+ console.log(` ${colors_1.default.red("missing")} ${rel(ins.file)}`);
244
+ return;
245
+ }
246
+ const original = fs_1.default.readFileSync(ins.file, "utf8");
247
+ const alreadyHasImport = original.includes(ins.importLine.trim());
248
+ const alreadyWired = ins.alreadyWiredMarker.test(original);
249
+ if (alreadyHasImport && alreadyWired) {
250
+ console.log(` ${colors_1.default.yellow("skip")} ${rel(ins.file)} (${kind} already registered)`);
251
+ return;
252
+ }
253
+ const result = modify(ins.file, ins.injector);
254
+ if (result === "added") {
255
+ console.log(` ${colors_1.default.green("update")} ${rel(ins.file)} ${colors_1.default.gray(`— wired ${kind}`)}`);
256
+ }
257
+ else if (result === "skipped") {
258
+ console.log(` ${colors_1.default.yellow("skip")} ${rel(ins.file)} (no changes needed)`);
259
+ }
260
+ else {
261
+ console.log(` ${colors_1.default.red("missing")} ${rel(ins.file)}`);
262
+ }
263
+ }
264
+ applyAppend(a) {
265
+ if (!fs_1.default.existsSync(a.file)) {
266
+ console.log(` ${colors_1.default.red("missing")} ${rel(a.file)}`);
267
+ return;
268
+ }
269
+ const src = fs_1.default.readFileSync(a.file, "utf8");
270
+ if (a.presenceMarker.test(src)) {
271
+ console.log(` ${colors_1.default.yellow("skip")} ${rel(a.file)} (${a.description} already present)`);
272
+ return;
273
+ }
274
+ const sep = src.endsWith("\n") ? "" : "\n";
275
+ fs_1.default.writeFileSync(a.file, src + sep + a.line + "\n", "utf8");
276
+ console.log(` ${colors_1.default.green("append")} ${rel(a.file)} ${colors_1.default.gray(`— ${a.description}`)}`);
277
+ }
278
+ }
279
+ exports.PublishCommand = PublishCommand;
@@ -16,7 +16,7 @@ const createController = (name) => {
16
16
  *@access public
17
17
  * @return Express Request Response
18
18
  */
19
- async create({ req, res, next } = httpContext)
19
+ async create({ req, res, next } : httpContext)
20
20
  {
21
21
  //
22
22
  }
@@ -25,7 +25,7 @@ const createController = (name) => {
25
25
  * @return Express Request Response
26
26
  */
27
27
  @Method()
28
- async index({ req, res, next } = httpContext)
28
+ async index({ req, res, next } : httpContext)
29
29
  {
30
30
  //
31
31
  }
@@ -35,7 +35,7 @@ const createController = (name) => {
35
35
  *@access public
36
36
  * @return Express Request Response
37
37
  */
38
- async store({ req, res, next } = httpContext)
38
+ async store({ req, res, next } : httpContext)
39
39
  {
40
40
  //
41
41
  }
@@ -45,7 +45,7 @@ const createController = (name) => {
45
45
  *@param {id} - string
46
46
  * @return Express Request Response
47
47
  */
48
- async show({ req, res, next } = httpContext)
48
+ async show({ req, res, next } : httpContext)
49
49
  {
50
50
  //
51
51
  }
@@ -56,7 +56,7 @@ const createController = (name) => {
56
56
  * @param {id} - string
57
57
  * @return Express Request Response
58
58
  */
59
- async update({ req, res, next } = httpContext)
59
+ async update({ req, res, next } : httpContext)
60
60
  {
61
61
  //
62
62
  }
@@ -66,7 +66,7 @@ const createController = (name) => {
66
66
  * @param {id} - string
67
67
  * @return Express Response
68
68
  */
69
- async destroy({ req, res, next } = httpContext)
69
+ async destroy({ req, res, next } : httpContext)
70
70
  {
71
71
  //
72
72
  }
@@ -0,0 +1,3 @@
1
+ declare const monitorConfigStub: () => string;
2
+ export default monitorConfigStub;
3
+ //# sourceMappingURL=MonitorConfigStub.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const monitorConfigStub = () => `import { config } from "jcc-express-mvc";
4
+ import type { MonitorConfig } from "jcc-express-mvc/lib/Monitor";
5
+
6
+ /**
7
+ * Monitor configuration. The MonitorServiceProvider is opt-in — add it to
8
+ * \`bootstrap/providers.ts\` to enable. Until then, this file is a no-op.
9
+ *
10
+ * Any field omitted falls back to \`defaultMonitorConfig\` from the framework.
11
+ */
12
+ export const monitor: Partial<MonitorConfig> = {
13
+ enabled: config.get("MONITOR_ENABLED", "true") === "true",
14
+ basePath: config.get("MONITOR_BASE_PATH", "/_monitor"),
15
+
16
+ collectors: {
17
+ http: { enabled: true, sampleRate: 1.0, slowThresholdMs: 1000, ignore: ["/favicon.ico"] },
18
+ system: { enabled: true, intervalMs: 15_000 },
19
+ errors: { enabled: true },
20
+ database: { enabled: false, slowQueryMs: 200 },
21
+ queue: { enabled: false },
22
+ },
23
+
24
+ exporters: {
25
+ prometheus: { enabled: true },
26
+ json: { enabled: true },
27
+ log: { enabled: false, file: null, level: "info" },
28
+ push: {
29
+ enabled: false,
30
+ url: config.get("MONITOR_PUSH_URL", ""),
31
+ intervalMs: 30_000,
32
+ headers: {},
33
+ format: "json",
34
+ },
35
+ },
36
+
37
+ healthChecks: {
38
+ database: { enabled: false, timeoutMs: 2000 },
39
+ cache: { enabled: false, timeoutMs: 1000 },
40
+ queue: { enabled: false, timeoutMs: 1000 },
41
+ disk: { enabled: false, path: ".", warnPercent: 90 },
42
+ memory: { enabled: true, warnPercent: 85 },
43
+ },
44
+
45
+ buffers: {
46
+ recentRequests: 200,
47
+ recentErrors: 100,
48
+ recentJobs: 100,
49
+ recentQueries: 100,
50
+ },
51
+
52
+ alerts: {
53
+ enabled: false,
54
+ tickIntervalMs: 30_000,
55
+ notifications: {
56
+ email: {
57
+ enabled: config.get("MONITOR_EMAIL_ALERTS", "false") === "true",
58
+ from: config.get("MONITOR_EMAIL_FROM", "noreply@example.com"),
59
+ to: config
60
+ .get("MONITOR_EMAIL_TO", "")
61
+ .split(",")
62
+ .map((s: string) => s.trim())
63
+ .filter(Boolean),
64
+ throttleMs: 15 * 60 * 1000,
65
+ severityFloor: "warning",
66
+ },
67
+ },
68
+ },
69
+
70
+ dashboard: {
71
+ enabled: true,
72
+ guard: null,
73
+ },
74
+ };
75
+ `;
76
+ exports.default = monitorConfigStub;
@@ -0,0 +1,3 @@
1
+ declare const monitorRouteStub: () => string;
2
+ export default monitorRouteStub;
3
+ //# sourceMappingURL=MonitorRouteStub.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,37 @@
1
+ "use strict";
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";
5
+
6
+ /**
7
+ * Monitor routes — published from \`bun artisanNode publish Monitor\`.
8
+ *
9
+ * Edit freely: change the prefix, attach middleware (auth, IP allowlist),
10
+ * or swap the controller for your own. The MonitorServiceProvider detects
11
+ * this file at boot and skips its own auto-mount so routes are not
12
+ * registered twice.
13
+ */
14
+ Route.prefix("/_monitor")
15
+ .controller(MonitorController)
16
+ .group((Route) => {
17
+ // API endpoints
18
+ Route.get("/health", "health");
19
+ Route.get("/ready", "ready");
20
+ Route.get("/metrics", "metrics");
21
+ Route.get("/json", "json");
22
+
23
+ // Pages
24
+ Route.get("/", "dashboard");
25
+ Route.get("/requests", "requests");
26
+ Route.get("/jobs", "jobs");
27
+ Route.get("/commands", "commands");
28
+ Route.get("/scheduled", "scheduled");
29
+ Route.get("/exceptions", "exceptions");
30
+ Route.get("/queries", "queries");
31
+ Route.get("/notifications", "notifications");
32
+ Route.get("/mail", "mail");
33
+ Route.get("/cache", "cache");
34
+ Route.get("/outgoing", "outgoing");
35
+ });
36
+ `;
37
+ exports.default = monitorRouteStub;
@@ -66,7 +66,7 @@ class AppErrorHandler {
66
66
  return res.status(422).redirectBack();
67
67
  }
68
68
  if (err instanceof MissMatchTokenException_1.MissMatchTokenException) {
69
- if (req.expectsJson()) {
69
+ if (req.expectsJson() && !req.isInertia()) {
70
70
  return res.status(419).json({ error: err.message });
71
71
  }
72
72
  return res.status(419).sendFile(__dirname + "/public/419.html");