adonisjs-server-stats 1.10.0 → 1.11.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 (248) hide show
  1. package/README.md +23 -14
  2. package/dist/core/config-utils.d.ts +8 -0
  3. package/dist/core/constants.d.ts +4 -0
  4. package/dist/core/dashboard-data-controller.d.ts +16 -0
  5. package/dist/core/dashboard-data-helpers.d.ts +12 -0
  6. package/dist/core/debug-data-controller.d.ts +4 -0
  7. package/dist/core/define-config-helpers.d.ts +25 -0
  8. package/dist/core/feature-detect-helpers.d.ts +36 -0
  9. package/dist/core/field-resolvers.d.ts +64 -0
  10. package/dist/core/formatters-helpers.d.ts +23 -0
  11. package/dist/core/formatters.d.ts +15 -0
  12. package/dist/core/index.d.ts +1 -1
  13. package/dist/core/index.js +599 -509
  14. package/dist/core/log-utils-helpers.d.ts +13 -0
  15. package/dist/core/metrics.d.ts +3 -28
  16. package/dist/core/pagination.d.ts +0 -9
  17. package/dist/core/server-stats-controller.d.ts +6 -0
  18. package/dist/core/transmit-helpers.d.ts +7 -0
  19. package/dist/core/types-dashboard.d.ts +178 -0
  20. package/dist/core/types-diagnostics.d.ts +85 -0
  21. package/dist/core/types.d.ts +10 -442
  22. package/dist/react/CacheSection-BYN53kYO.js +135 -0
  23. package/dist/react/CacheStatsBar-CRodCOeP.js +27 -0
  24. package/dist/react/CacheTab-DOhuK05d.js +106 -0
  25. package/dist/react/{ConfigSection-DfFd-WRq.js → ConfigSection-B9EHh4Rp.js} +1 -1
  26. package/dist/react/{ConfigTab-Bdg8YMer.js → ConfigTab-C8kriE2b.js} +1 -1
  27. package/dist/react/CustomPaneTab-CvzQS_Wh.js +99 -0
  28. package/dist/react/EmailPreviewOverlay-BmXOAvqG.js +58 -0
  29. package/dist/react/EmailsSection-BJyFJf7A.js +226 -0
  30. package/dist/react/EmailsTab-Ch8jp10B.js +110 -0
  31. package/dist/react/{EventsSection-ByQ-9blq.js → EventsSection-DJPwHeT8.js} +28 -27
  32. package/dist/react/EventsTab-B-FoehXC.js +58 -0
  33. package/dist/react/{FilterBar-DQRXpWrb.js → FilterBar-CQ7bD669.js} +15 -15
  34. package/dist/react/{InternalsContent-DBzsI0CG.js → InternalsContent-O8ino9oM.js} +133 -109
  35. package/dist/react/InternalsSection-B6VlVx5f.js +22 -0
  36. package/dist/react/InternalsTab-CkEKpRMU.js +17 -0
  37. package/dist/react/JobStatsBar-C7RslAFE.js +30 -0
  38. package/dist/react/JobsSection-DWF4i1t_.js +167 -0
  39. package/dist/react/JobsTab-DqnifQXV.js +129 -0
  40. package/dist/react/LogEntryRow-CMMkqA9M.js +43 -0
  41. package/dist/react/LogsSection-C1xC5aP4.js +198 -0
  42. package/dist/react/LogsTab-CS4sLfLw.js +79 -0
  43. package/dist/react/{OverviewSection-C4T1ur51.js → OverviewSection-CxvfOR0v.js} +70 -80
  44. package/dist/react/QueriesSection-CrMdU5Ax.js +458 -0
  45. package/dist/react/{QueriesTab-osLUWd4L.js → QueriesTab-x85PjkyS.js} +38 -40
  46. package/dist/react/RequestsSection-DETN9oZb.js +321 -0
  47. package/dist/react/{RoutesSection-BUSkM6PY.js → RoutesSection-CmorkJeC.js} +2 -2
  48. package/dist/react/RoutesTab-CbzBOzpc.js +68 -0
  49. package/dist/react/SplitPaneWrapper-BiIgT4ND.js +49 -0
  50. package/dist/react/TimeAgoCell-o3KigGfM.js +8 -0
  51. package/dist/react/{TimelineTab-Covg5weo.js → TimelineTab-Ue9tUD_n.js} +76 -102
  52. package/dist/react/index-DwDK-4oX.js +1121 -0
  53. package/dist/react/index.js +6 -6
  54. package/dist/react/react/components/shared/CacheStatsBar.d.ts +13 -0
  55. package/dist/react/react/components/shared/EmailPreviewOverlay.d.ts +29 -0
  56. package/dist/react/react/components/{Dashboard/shared → shared}/FilterBar.d.ts +4 -3
  57. package/dist/react/react/components/shared/JobStatsBar.d.ts +12 -0
  58. package/dist/react/react/components/shared/LogEntryRow.d.ts +9 -0
  59. package/dist/react/react/components/shared/RelatedLogs.d.ts +2 -2
  60. package/dist/react/react/components/shared/SplitPaneWrapper.d.ts +7 -0
  61. package/dist/react/react/components/shared/TimeAgoCell.d.ts +17 -0
  62. package/dist/react/react/hooks/useDashboardData.d.ts +4 -8
  63. package/dist/react/react/hooks/useDiagnosticsData.d.ts +14 -0
  64. package/dist/react/style.css +1 -1
  65. package/dist/src/collectors/app_collector.d.ts +0 -8
  66. package/dist/src/collectors/app_collector.js +45 -52
  67. package/dist/src/collectors/auto_detect.d.ts +0 -23
  68. package/dist/src/collectors/auto_detect.js +33 -55
  69. package/dist/src/collectors/db_pool_collector.d.ts +14 -16
  70. package/dist/src/collectors/db_pool_collector.js +72 -57
  71. package/dist/src/collectors/log_collector.d.ts +0 -47
  72. package/dist/src/collectors/log_collector.js +36 -65
  73. package/dist/src/collectors/queue_collector.d.ts +0 -20
  74. package/dist/src/collectors/queue_collector.js +60 -76
  75. package/dist/src/collectors/redis_collector.d.ts +10 -10
  76. package/dist/src/collectors/redis_collector.js +69 -66
  77. package/dist/src/config/deprecation_migration.d.ts +7 -0
  78. package/dist/src/config/deprecation_migration.js +201 -0
  79. package/dist/src/controller/debug_controller.d.ts +1 -1
  80. package/dist/src/controller/debug_controller.js +87 -81
  81. package/dist/src/dashboard/cache_handlers.d.ts +14 -0
  82. package/dist/src/dashboard/cache_handlers.js +52 -0
  83. package/dist/src/dashboard/chart_aggregator.d.ts +0 -7
  84. package/dist/src/dashboard/chart_aggregator.js +68 -50
  85. package/dist/src/dashboard/coalesce_cache.d.ts +25 -0
  86. package/dist/src/dashboard/coalesce_cache.js +47 -0
  87. package/dist/src/dashboard/dashboard_controller.d.ts +11 -37
  88. package/dist/src/dashboard/dashboard_controller.js +51 -544
  89. package/dist/src/dashboard/dashboard_page_assets.d.ts +17 -0
  90. package/dist/src/dashboard/dashboard_page_assets.js +51 -0
  91. package/dist/src/dashboard/dashboard_store.d.ts +19 -218
  92. package/dist/src/dashboard/dashboard_store.js +115 -1116
  93. package/dist/src/dashboard/dashboard_types.d.ts +83 -0
  94. package/dist/src/dashboard/dashboard_types.js +4 -0
  95. package/dist/src/dashboard/detail_queries.d.ts +19 -0
  96. package/dist/src/dashboard/detail_queries.js +98 -0
  97. package/dist/src/dashboard/email_event_builder.d.ts +8 -0
  98. package/dist/src/dashboard/email_event_builder.js +65 -0
  99. package/dist/src/dashboard/explain_query.d.ts +8 -0
  100. package/dist/src/dashboard/explain_query.js +22 -0
  101. package/dist/src/dashboard/filter_handlers.d.ts +23 -0
  102. package/dist/src/dashboard/filter_handlers.js +56 -0
  103. package/dist/src/dashboard/filtered_queries.d.ts +15 -0
  104. package/dist/src/dashboard/filtered_queries.js +155 -0
  105. package/dist/src/dashboard/flush_manager.d.ts +25 -0
  106. package/dist/src/dashboard/flush_manager.js +107 -0
  107. package/dist/src/dashboard/format_helpers.d.ts +126 -0
  108. package/dist/src/dashboard/format_helpers.js +140 -0
  109. package/dist/src/dashboard/inspector_manager.d.ts +36 -0
  110. package/dist/src/dashboard/inspector_manager.js +102 -0
  111. package/dist/src/dashboard/integrations/config_inspector.js +11 -13
  112. package/dist/src/dashboard/integrations/queue_inspector.d.ts +3 -3
  113. package/dist/src/dashboard/integrations/queue_inspector.js +13 -10
  114. package/dist/src/dashboard/jobs_handlers.d.ts +14 -0
  115. package/dist/src/dashboard/jobs_handlers.js +61 -0
  116. package/dist/src/dashboard/knex_factory.d.ts +18 -0
  117. package/dist/src/dashboard/knex_factory.js +91 -0
  118. package/dist/src/dashboard/migrator.js +30 -159
  119. package/dist/src/dashboard/migrator_tables.d.ts +19 -0
  120. package/dist/src/dashboard/migrator_tables.js +153 -0
  121. package/dist/src/dashboard/overview_queries.d.ts +66 -0
  122. package/dist/src/dashboard/overview_queries.js +155 -0
  123. package/dist/src/dashboard/overview_query_runners.d.ts +25 -0
  124. package/dist/src/dashboard/overview_query_runners.js +84 -0
  125. package/dist/src/dashboard/overview_store_queries.d.ts +40 -0
  126. package/dist/src/dashboard/overview_store_queries.js +69 -0
  127. package/dist/src/dashboard/paginate_helper.d.ts +12 -0
  128. package/dist/src/dashboard/paginate_helper.js +33 -0
  129. package/dist/src/dashboard/query_explain_handler.d.ts +10 -0
  130. package/dist/src/dashboard/query_explain_handler.js +80 -0
  131. package/dist/src/dashboard/read_queries.d.ts +32 -0
  132. package/dist/src/dashboard/read_queries.js +107 -0
  133. package/dist/src/dashboard/saved_filter_queries.d.ts +10 -0
  134. package/dist/src/dashboard/saved_filter_queries.js +24 -0
  135. package/dist/src/dashboard/storage_stats.d.ts +41 -0
  136. package/dist/src/dashboard/storage_stats.js +81 -0
  137. package/dist/src/dashboard/write_queue.d.ts +106 -0
  138. package/dist/src/dashboard/write_queue.js +225 -0
  139. package/dist/src/data/data_access.d.ts +2 -39
  140. package/dist/src/data/data_access.js +17 -193
  141. package/dist/src/data/data_access_helpers.d.ts +130 -0
  142. package/dist/src/data/data_access_helpers.js +212 -0
  143. package/dist/src/debug/debug_store.js +37 -32
  144. package/dist/src/debug/email_collector.d.ts +1 -10
  145. package/dist/src/debug/email_collector.js +78 -81
  146. package/dist/src/debug/event_collector.d.ts +0 -9
  147. package/dist/src/debug/event_collector.js +79 -62
  148. package/dist/src/debug/query_collector.js +23 -19
  149. package/dist/src/debug/route_inspector.d.ts +1 -5
  150. package/dist/src/debug/route_inspector.js +50 -51
  151. package/dist/src/debug/trace_collector.d.ts +9 -1
  152. package/dist/src/debug/trace_collector.js +21 -15
  153. package/dist/src/debug/types.d.ts +1 -1
  154. package/dist/src/define_config.d.ts +0 -65
  155. package/dist/src/define_config.js +93 -333
  156. package/dist/src/edge/client/dashboard.js +2 -2
  157. package/dist/src/edge/client/debug-panel-deferred.js +1 -1
  158. package/dist/src/edge/client/stats-bar.js +1 -1
  159. package/dist/src/edge/client-vue/dashboard.js +5 -5
  160. package/dist/src/edge/client-vue/debug-panel-deferred.js +4 -4
  161. package/dist/src/edge/client-vue/stats-bar.js +3 -3
  162. package/dist/src/edge/plugin.d.ts +0 -16
  163. package/dist/src/edge/plugin.js +57 -64
  164. package/dist/src/engine/request_metrics.d.ts +1 -0
  165. package/dist/src/engine/request_metrics.js +32 -42
  166. package/dist/src/middleware/request_tracking_middleware.d.ts +2 -8
  167. package/dist/src/middleware/request_tracking_middleware.js +65 -93
  168. package/dist/src/provider/auth_middleware_detector.d.ts +16 -0
  169. package/dist/src/provider/auth_middleware_detector.js +97 -0
  170. package/dist/src/provider/boot_helpers.d.ts +20 -0
  171. package/dist/src/provider/boot_helpers.js +91 -0
  172. package/dist/src/provider/boot_initializer.d.ts +28 -0
  173. package/dist/src/provider/boot_initializer.js +35 -0
  174. package/dist/src/provider/dashboard_init.d.ts +30 -0
  175. package/dist/src/provider/dashboard_init.js +138 -0
  176. package/dist/src/provider/dashboard_setup.d.ts +25 -0
  177. package/dist/src/provider/dashboard_setup.js +78 -0
  178. package/dist/src/provider/diagnostics.d.ts +134 -0
  179. package/dist/src/provider/diagnostics.js +127 -0
  180. package/dist/src/provider/email_bridge.d.ts +43 -0
  181. package/dist/src/provider/email_bridge.js +80 -0
  182. package/dist/src/provider/email_helpers.d.ts +13 -0
  183. package/dist/src/provider/email_helpers.js +68 -0
  184. package/dist/src/provider/pino_hook.d.ts +17 -0
  185. package/dist/src/provider/pino_hook.js +35 -0
  186. package/dist/src/provider/provider_helpers_extra.d.ts +47 -0
  187. package/dist/src/provider/provider_helpers_extra.js +177 -0
  188. package/dist/src/provider/server_stats_provider.d.ts +39 -85
  189. package/dist/src/provider/server_stats_provider.js +132 -951
  190. package/dist/src/provider/shutdown_helpers.d.ts +43 -0
  191. package/dist/src/provider/shutdown_helpers.js +70 -0
  192. package/dist/src/provider/toolbar_setup.d.ts +57 -0
  193. package/dist/src/provider/toolbar_setup.js +141 -0
  194. package/dist/src/routes/dashboard_routes.d.ts +14 -0
  195. package/dist/src/routes/dashboard_routes.js +197 -0
  196. package/dist/src/routes/debug_routes.d.ts +14 -0
  197. package/dist/src/routes/debug_routes.js +101 -0
  198. package/dist/src/routes/register_routes.d.ts +0 -78
  199. package/dist/src/routes/register_routes.js +22 -352
  200. package/dist/src/routes/stats_routes.d.ts +5 -0
  201. package/dist/src/routes/stats_routes.js +14 -0
  202. package/dist/src/styles/components.css +163 -0
  203. package/dist/src/styles/dashboard.css +13 -105
  204. package/dist/src/styles/debug-panel.css +2 -53
  205. package/dist/src/styles/utilities.css +3 -1
  206. package/dist/src/types.d.ts +305 -14
  207. package/dist/vue/{CacheSection-oFAJL3mo.js → CacheSection-DT2Mwf_s.js} +1 -1
  208. package/dist/vue/{ConfigSection-BhfJ4KqL.js → ConfigSection-BwKwS9lh.js} +1 -1
  209. package/dist/vue/CustomPaneTab-Hr1IBHfz.js +172 -0
  210. package/dist/vue/{EmailsSection-BcNyhyHs.js → EmailsSection-B65g0FVS.js} +1 -1
  211. package/dist/vue/{EventsSection-r60Q5Lmu.js → EventsSection-CxqtVF-o.js} +1 -1
  212. package/dist/vue/{JobsSection-BHL-hkQw.js → JobsSection-rMIyMb-g.js} +1 -1
  213. package/dist/vue/{LogsSection-DRMGzJmg.js → LogsSection-DmmZVJ7D.js} +9 -3
  214. package/dist/vue/{LogsTab-Bg3o0Mm6.js → LogsTab-47zEK7jL.js} +4 -1
  215. package/dist/vue/{OverviewSection-CXh6Ja1B.js → OverviewSection-BMabyqw-.js} +49 -50
  216. package/dist/vue/{QueriesSection-IodIsCJ-.js → QueriesSection-BfDFwGqH.js} +44 -45
  217. package/dist/vue/{QueriesTab-C8_7oprC.js → QueriesTab-DuTG7cpC.js} +30 -31
  218. package/dist/vue/RelatedLogs.vue_vue_type_script_setup_true_lang-Py1iu9GU.js +77 -0
  219. package/dist/vue/{RequestsSection-BPuMdmMc.js → RequestsSection-CTu4jPZ_.js} +143 -147
  220. package/dist/vue/{RoutesSection-NKo3Rbq3.js → RoutesSection-zQZDedL7.js} +1 -1
  221. package/dist/vue/TimelineTab-DHfXsX7t.js +334 -0
  222. package/dist/vue/components/shared/RelatedLogs.vue.d.ts +1 -4
  223. package/dist/vue/composables/useDashboardData.d.ts +12 -23
  224. package/dist/vue/index-CM3yNVUR.js +1232 -0
  225. package/dist/vue/index.js +1 -1
  226. package/dist/vue/style.css +1 -1
  227. package/package.json +1 -1
  228. package/dist/react/CacheSection-UCMptWyn.js +0 -146
  229. package/dist/react/CacheTab-CA8LB1J5.js +0 -123
  230. package/dist/react/CustomPaneTab-Bxtv_8Rw.js +0 -104
  231. package/dist/react/EmailsSection-CM7stSyh.js +0 -262
  232. package/dist/react/EmailsTab-BDhEiomM.js +0 -153
  233. package/dist/react/EventsTab-CMfY98Rl.js +0 -63
  234. package/dist/react/InternalsSection-t7ihcWO-.js +0 -32
  235. package/dist/react/InternalsTab-Oij0A2fN.js +0 -30
  236. package/dist/react/JobsSection-DF3qEv9O.js +0 -187
  237. package/dist/react/JobsTab-BbrBWIOb.js +0 -141
  238. package/dist/react/LogsSection-DcFTZY7b.js +0 -227
  239. package/dist/react/LogsTab-CicucmVk.js +0 -103
  240. package/dist/react/QueriesSection-PswteoF9.js +0 -461
  241. package/dist/react/RelatedLogs-DFDOyUMr.js +0 -40
  242. package/dist/react/RequestsSection-Nag30rEA.js +0 -341
  243. package/dist/react/RoutesTab-DgVzd2PZ.js +0 -74
  244. package/dist/react/index-Cflz9Ebj.js +0 -1069
  245. package/dist/vue/CustomPaneTab-BJxT5Dp7.js +0 -172
  246. package/dist/vue/RelatedLogs.vue_vue_type_script_setup_true_lang-CB2_TzYW.js +0 -84
  247. package/dist/vue/TimelineTab-zj5Z5OdT.js +0 -338
  248. package/dist/vue/index-Dtgysd26.js +0 -1229
@@ -6,97 +6,19 @@ import type { AdonisRouter } from './router_types.js';
6
6
  import type { HttpContext } from '@adonisjs/core/http';
7
7
  /**
8
8
  * Options for the unified route registration function.
9
- *
10
- * Brings together stats, debug, and dashboard route registration
11
- * into a single call with all required dependencies declared upfront.
12
9
  */
13
10
  export interface RegisterRoutesOptions {
14
- /** The AdonisJS router instance. */
15
11
  router: AdonisRouter;
16
- /**
17
- * The unified API controller that serves all data resource endpoints
18
- * (queries, events, emails, traces, routes, logs).
19
- *
20
- * Pass `null` during early boot — routes will return 503 until the
21
- * controller is wired up.
22
- */
23
12
  getApiController: () => ApiController | null;
24
- /**
25
- * Lazy getter for the stats bar controller.
26
- *
27
- * The controller is created during `ready()`, but routes are
28
- * registered during `boot()`, so a lazy getter is required.
29
- */
30
13
  getStatsController: () => ServerStatsController | null;
31
- /**
32
- * Lazy getter for the debug controller.
33
- *
34
- * Handles non-data debug endpoints: `/config` and `/diagnostics`.
35
- */
36
14
  getDebugController: () => DebugController | null;
37
- /**
38
- * Lazy getter for the dashboard controller.
39
- *
40
- * Handles dashboard-specific endpoints that are **not** data
41
- * resources: page rendering, overview, requests, cache, jobs,
42
- * config, saved filters, grouped queries, and query explain.
43
- */
44
15
  getDashboardController: () => DashboardController | null;
45
- /**
46
- * Stats polling endpoint path (e.g. `'/admin/api/server-stats'`).
47
- *
48
- * Set to `false` to skip registering the stats endpoint entirely.
49
- */
50
16
  statsEndpoint?: string | false;
51
- /**
52
- * Base path for debug panel API routes (e.g. `'/admin/api/debug'`).
53
- *
54
- * When omitted, debug routes are **not** registered.
55
- */
56
17
  debugEndpoint?: string;
57
- /**
58
- * Base path for the full-page dashboard (e.g. `'/__stats'`).
59
- *
60
- * When omitted, dashboard routes are **not** registered.
61
- */
62
18
  dashboardPath?: string;
63
- /**
64
- * Optional access-control callback applied to **all** registered
65
- * routes as middleware. When it returns `false`, the request
66
- * receives a 403 Forbidden response.
67
- */
68
19
  shouldShow?: (ctx: HttpContext) => boolean;
69
20
  }
70
21
  /**
71
22
  * Register all server-stats routes in a single call.
72
- *
73
- * This is the unified replacement for the three separate registrars:
74
- *
75
- * - `registerStatsRoutes` — stats bar polling endpoint
76
- * - `registerDebugRoutes` — debug panel API endpoints
77
- * - `registerDashboardRoutes` — full-page dashboard endpoints
78
- *
79
- * **Data resource** endpoints (queries, events, emails, traces, routes,
80
- * logs) are routed through the unified {@link ApiController} so that
81
- * both the debug panel and the dashboard read from the same handler.
82
- *
83
- * **Non-data** endpoints (stats polling, config, diagnostics, overview,
84
- * requests, cache, jobs, saved filters, grouped queries, query explain,
85
- * and the dashboard HTML page) continue to use their original controllers.
86
- *
87
- * @example
88
- * ```ts
89
- * registerAllRoutes({
90
- * router,
91
- * getApiController: () => apiController,
92
- * getStatsController: () => statsController,
93
- * getDebugController: () => debugController,
94
- * getDashboardController: () => dashboardController,
95
- * statsEndpoint: '/admin/api/server-stats',
96
- * debugEndpoint: '/admin/api/debug',
97
- * dashboardPath: '/__stats',
98
- * shouldShow: (ctx) => ctx.auth?.user?.role === 'admin',
99
- * })
100
- * ```
101
23
  */
102
24
  export declare function registerAllRoutes(options: RegisterRoutesOptions): void;
@@ -1,361 +1,31 @@
1
1
  import { createAccessMiddleware } from './access_middleware.js';
2
- // ---------------------------------------------------------------------------
3
- // Registration
4
- // ---------------------------------------------------------------------------
2
+ import { registerDashboardRoutes } from './dashboard_routes.js';
3
+ import { registerDebugRoutes } from './debug_routes.js';
4
+ import { registerStatsRoute } from './stats_routes.js';
5
5
  /**
6
6
  * Register all server-stats routes in a single call.
7
- *
8
- * This is the unified replacement for the three separate registrars:
9
- *
10
- * - `registerStatsRoutes` — stats bar polling endpoint
11
- * - `registerDebugRoutes` — debug panel API endpoints
12
- * - `registerDashboardRoutes` — full-page dashboard endpoints
13
- *
14
- * **Data resource** endpoints (queries, events, emails, traces, routes,
15
- * logs) are routed through the unified {@link ApiController} so that
16
- * both the debug panel and the dashboard read from the same handler.
17
- *
18
- * **Non-data** endpoints (stats polling, config, diagnostics, overview,
19
- * requests, cache, jobs, saved filters, grouped queries, query explain,
20
- * and the dashboard HTML page) continue to use their original controllers.
21
- *
22
- * @example
23
- * ```ts
24
- * registerAllRoutes({
25
- * router,
26
- * getApiController: () => apiController,
27
- * getStatsController: () => statsController,
28
- * getDebugController: () => debugController,
29
- * getDashboardController: () => dashboardController,
30
- * statsEndpoint: '/admin/api/server-stats',
31
- * debugEndpoint: '/admin/api/debug',
32
- * dashboardPath: '/__stats',
33
- * shouldShow: (ctx) => ctx.auth?.user?.role === 'admin',
34
- * })
35
- * ```
36
7
  */
37
8
  export function registerAllRoutes(options) {
38
- const { router, getApiController, getStatsController, getDebugController, getDashboardController, statsEndpoint, debugEndpoint, dashboardPath, shouldShow, } = options;
39
- const middleware = shouldShow ? [createAccessMiddleware(shouldShow)] : [];
40
- // =========================================================================
41
- // Stats polling endpoint
42
- // =========================================================================
43
- if (typeof statsEndpoint === 'string') {
44
- router
45
- .get(statsEndpoint, async (ctx) => {
46
- const controller = getStatsController();
47
- if (!controller) {
48
- return ctx.response.serviceUnavailable({
49
- error: 'Stats engine is starting up, please retry',
50
- });
51
- }
52
- return controller.index(ctx);
53
- })
54
- .as('server-stats.api')
55
- .use(middleware);
9
+ const middleware = options.shouldShow ? [createAccessMiddleware(options.shouldShow)] : [];
10
+ if (typeof options.statsEndpoint === 'string') {
11
+ registerStatsRoute(options.router, options.statsEndpoint, options.getStatsController, middleware);
56
12
  }
57
- // =========================================================================
58
- // Debug panel API routes
59
- // =========================================================================
60
- if (debugEndpoint) {
61
- const base = debugEndpoint.replace(/\/+$/, '');
62
- /**
63
- * Bind a debug controller method with lazy initialization and
64
- * 503 fallback when the controller is not yet ready.
65
- */
66
- const bindDebug = (method) => {
67
- return async (ctx) => {
68
- const controller = getDebugController();
69
- if (!controller) {
70
- return ctx.response.serviceUnavailable({
71
- error: 'Debug toolbar is starting up, please retry',
72
- });
73
- }
74
- return controller[method].call(controller, ctx);
75
- };
76
- };
77
- /**
78
- * Wrap an ApiController method as an HTTP handler with lazy
79
- * initialization and 503 fallback.
80
- */
81
- const bindApi = (fn) => {
82
- return async (ctx) => {
83
- const api = getApiController();
84
- if (!api) {
85
- return ctx.response.serviceUnavailable({
86
- error: 'Debug toolbar is starting up, please retry',
87
- });
88
- }
89
- return fn(api, ctx);
90
- };
91
- };
92
- router
93
- .group(() => {
94
- // Non-data endpoints — stay with DebugController
95
- router.get('/config', bindDebug('config')).as('server-stats.debug.config');
96
- router.get('/diagnostics', bindDebug('diagnostics')).as('server-stats.debug.diagnostics');
97
- // Data endpoints — unified through ApiController
98
- // Queries, events, and traces read from ring buffers (source: 'memory')
99
- // because SQLite column names (snake_case) differ from the
100
- // camelCase QueryRecord/EventRecord/etc. shapes the frontend expects.
101
- // Logs and emails use 'auto' (SQLite when available) since the
102
- // frontend resolvers handle both snake_case and camelCase fields.
103
- router
104
- .get('/queries', bindApi(async (api, ctx) => {
105
- const queries = await api.getQueries({ source: 'memory' });
106
- const summary = api.getQuerySummary();
107
- return ctx.response.json({ queries: queries.data, summary });
108
- }))
109
- .as('server-stats.debug.queries');
110
- router
111
- .get('/events', bindApi(async (api, ctx) => {
112
- const result = await api.getEvents({ source: 'memory' });
113
- return ctx.response.json({ events: result.data, total: result.meta.total });
114
- }))
115
- .as('server-stats.debug.events');
116
- router
117
- .get('/routes', bindApi((api, ctx) => {
118
- const result = api.getRoutes();
119
- return ctx.response.json({ routes: result.data, total: result.meta.total });
120
- }))
121
- .as('server-stats.debug.routes');
122
- router
123
- .get('/logs', bindApi(async (api, ctx) => {
124
- // Request up to 200 entries so the debug panel frontend
125
- // (which caps at `.slice(0, 200)`) always has enough
126
- // recent logs instead of the default 50-row page.
127
- const result = await api.getLogs({ source: 'auto', perPage: 200 });
128
- return ctx.response.json(result.data);
129
- }))
130
- .as('server-stats.debug.logs');
131
- router
132
- .get('/emails', bindApi(async (api, ctx) => {
133
- const result = await api.getEmails({});
134
- return ctx.response.json({ emails: result.data, total: result.meta.total });
135
- }))
136
- .as('server-stats.debug.emails');
137
- router
138
- .get('/emails/:id/preview', bindApi(async (api, ctx) => {
139
- const id = Number(ctx.params.id);
140
- const html = await api.getEmailPreview(id);
141
- if (!html) {
142
- return ctx.response.notFound({ error: 'Email not found' });
143
- }
144
- return ctx.response.header('Content-Type', 'text/html; charset=utf-8').send(html);
145
- }))
146
- .as('server-stats.debug.emailPreview');
147
- router
148
- .get('/traces', bindApi(async (api, ctx) => {
149
- const result = await api.getTraces({ source: 'memory' });
150
- return ctx.response.json({ traces: result.data, total: result.meta.total });
151
- }))
152
- .as('server-stats.debug.traces');
153
- router
154
- .get('/traces/:id', bindApi(async (api, ctx) => {
155
- const id = Number(ctx.params.id);
156
- const trace = await api.getTraceDetail(id, 'memory');
157
- if (!trace) {
158
- return ctx.response.notFound({ error: 'Trace not found' });
159
- }
160
- return ctx.response.json(trace);
161
- }))
162
- .as('server-stats.debug.traceDetail');
163
- })
164
- .prefix(base)
165
- .use(middleware);
13
+ if (options.debugEndpoint) {
14
+ registerDebugRoutes({
15
+ router: options.router,
16
+ debugEndpoint: options.debugEndpoint,
17
+ getDebugController: options.getDebugController,
18
+ getApiController: options.getApiController,
19
+ middleware,
20
+ });
166
21
  }
167
- // =========================================================================
168
- // Dashboard routes
169
- // =========================================================================
170
- if (dashboardPath) {
171
- const base = dashboardPath.replace(/\/+$/, '');
172
- /**
173
- * Bind a dashboard controller method with lazy initialization
174
- * and 503 fallback.
175
- */
176
- const bindDash = (method) => {
177
- return async (ctx) => {
178
- const controller = getDashboardController();
179
- if (!controller) {
180
- return ctx.response.serviceUnavailable({
181
- error: 'Dashboard is starting up, please retry',
182
- });
183
- }
184
- return controller[method].call(controller, ctx);
185
- };
186
- };
187
- /**
188
- * Wrap an ApiController method as a dashboard HTTP handler with
189
- * lazy initialization and 503 fallback.
190
- */
191
- const bindApi = (fn) => {
192
- return async (ctx) => {
193
- const api = getApiController();
194
- if (!api) {
195
- return ctx.response.serviceUnavailable({
196
- error: 'Dashboard is starting up, please retry',
197
- });
198
- }
199
- return fn(api, ctx);
200
- };
201
- };
202
- router
203
- .group(() => {
204
- // ── Page ────────────────────────────────────────────────────
205
- router.get('/', bindDash('page')).as('server-stats.dashboard');
206
- // ── Overview (dashboard-only) ───────────────────────────────
207
- router.get('/api/overview', bindDash('overview')).as('server-stats.overview');
208
- router
209
- .get('/api/overview/chart', bindDash('overviewChart'))
210
- .as('server-stats.overview.chart');
211
- // ── Requests (dashboard-only) ───────────────────────────────
212
- router.get('/api/requests', bindDash('requests')).as('server-stats.requests');
213
- router.get('/api/requests/:id', bindDash('requestDetail')).as('server-stats.requests.show');
214
- // ── Queries — unified data via ApiController ────────────────
215
- router
216
- .get('/api/queries', bindApi(async (api, ctx) => {
217
- const qs = ctx.request.qs();
218
- const result = await api.getQueries({
219
- page: Number(qs.page) || 1,
220
- perPage: Number(qs.perPage) || 25,
221
- search: qs.search || undefined,
222
- filters: {
223
- durationMin: qs.duration_min ? Number(qs.duration_min) : undefined,
224
- model: qs.model || undefined,
225
- method: qs.method || undefined,
226
- connection: qs.connection || undefined,
227
- },
228
- });
229
- return ctx.response.json(result);
230
- }))
231
- .as('server-stats.queries');
232
- // Grouped queries and explain stay on DashboardController
233
- router
234
- .get('/api/queries/grouped', bindDash('queriesGrouped'))
235
- .as('server-stats.queries.grouped');
236
- router
237
- .get('/api/queries/:id/explain', bindDash('queryExplain'))
238
- .as('server-stats.queries.explain');
239
- // ── Events — unified data via ApiController ─────────────────
240
- router
241
- .get('/api/events', bindApi(async (api, ctx) => {
242
- const qs = ctx.request.qs();
243
- const result = await api.getEvents({
244
- page: Number(qs.page) || 1,
245
- perPage: Number(qs.perPage) || 25,
246
- search: qs.search || undefined,
247
- filters: {
248
- eventName: qs.event_name || undefined,
249
- },
250
- });
251
- return ctx.response.json(result);
252
- }))
253
- .as('server-stats.events');
254
- // ── Routes — unified data via ApiController ─────────────────
255
- router
256
- .get('/api/routes', bindApi((api, ctx) => {
257
- const qs = ctx.request.qs();
258
- const result = api.getRoutes(qs.search || undefined);
259
- return ctx.response.json(result);
260
- }))
261
- .as('server-stats.routes');
262
- // ── Logs — unified data via ApiController ───────────────────
263
- router
264
- .get('/api/logs', bindApi(async (api, ctx) => {
265
- const qs = ctx.request.qs();
266
- const result = await api.getLogs({
267
- page: Number(qs.page) || 1,
268
- perPage: Number(qs.perPage) || 50,
269
- search: qs.message || qs.search || undefined,
270
- filters: {
271
- level: qs.level || undefined,
272
- requestId: qs.request_id || qs.requestId || undefined,
273
- },
274
- });
275
- return ctx.response.json(result);
276
- }))
277
- .as('server-stats.logs');
278
- // ── Emails — unified data via ApiController ─────────────────
279
- router
280
- .get('/api/emails', bindApi(async (api, ctx) => {
281
- const qs = ctx.request.qs();
282
- const result = await api.getEmails({
283
- page: Number(qs.page) || 1,
284
- perPage: Number(qs.perPage) || 25,
285
- search: qs.search || undefined,
286
- filters: {
287
- from: qs.from || undefined,
288
- to: qs.to || undefined,
289
- subject: qs.subject || undefined,
290
- status: qs.status || undefined,
291
- mailer: qs.mailer || undefined,
292
- },
293
- });
294
- return ctx.response.json(result);
295
- }))
296
- .as('server-stats.emails');
297
- router
298
- .get('/api/emails/:id/preview', bindApi(async (api, ctx) => {
299
- const id = Number(ctx.params.id);
300
- const html = await api.getEmailPreview(id);
301
- if (!html) {
302
- return ctx.response.notFound({ error: 'Email not found' });
303
- }
304
- return ctx.response.header('Content-Type', 'text/html; charset=utf-8').send(html);
305
- }))
306
- .as('server-stats.emails.preview');
307
- // ── Traces — unified data via ApiController ─────────────────
308
- router
309
- .get('/api/traces', bindApi(async (api, ctx) => {
310
- const qs = ctx.request.qs();
311
- const result = await api.getTraces({
312
- page: Number(qs.page) || 1,
313
- perPage: Number(qs.perPage) || 25,
314
- search: qs.search || undefined,
315
- filters: {
316
- method: qs.method ? qs.method.toUpperCase() : undefined,
317
- url: qs.url || undefined,
318
- statusMin: qs.status_min ? Number(qs.status_min) : undefined,
319
- statusMax: qs.status_max ? Number(qs.status_max) : undefined,
320
- },
321
- });
322
- return ctx.response.json(result);
323
- }))
324
- .as('server-stats.traces');
325
- router
326
- .get('/api/traces/:id', bindApi(async (api, ctx) => {
327
- const id = Number(ctx.params.id);
328
- const trace = await api.getTraceDetail(id);
329
- if (!trace) {
330
- return ctx.response.notFound({ error: 'Trace not found' });
331
- }
332
- return ctx.response.json(trace);
333
- }))
334
- .as('server-stats.traces.show');
335
- // ── Cache (dashboard-only) ──────────────────────────────────
336
- router.get('/api/cache', bindDash('cacheStats')).as('server-stats.cache');
337
- router
338
- .get('/api/cache/:key', bindDash('cacheKey'))
339
- .as('server-stats.cache.show')
340
- .where('key', /.*/);
341
- router
342
- .delete('/api/cache/:key', bindDash('cacheKeyDelete'))
343
- .as('server-stats.cache.delete')
344
- .where('key', /.*/);
345
- // ── Jobs / Queue (dashboard-only) ───────────────────────────
346
- router.get('/api/jobs', bindDash('jobs')).as('server-stats.jobs');
347
- router.get('/api/jobs/:id', bindDash('jobDetail')).as('server-stats.jobs.show');
348
- router.post('/api/jobs/:id/retry', bindDash('jobRetry')).as('server-stats.jobs.retry');
349
- // ── Config (dashboard-only) ─────────────────────────────────
350
- router.get('/api/config', bindDash('config')).as('server-stats.config');
351
- // ── Saved Filters (dashboard-only) ──────────────────────────
352
- router.get('/api/filters', bindDash('savedFilters')).as('server-stats.filters');
353
- router.post('/api/filters', bindDash('createSavedFilter')).as('server-stats.filters.create');
354
- router
355
- .delete('/api/filters/:id', bindDash('deleteSavedFilter'))
356
- .as('server-stats.filters.delete');
357
- })
358
- .prefix(base)
359
- .use(middleware);
22
+ if (options.dashboardPath) {
23
+ registerDashboardRoutes({
24
+ router: options.router,
25
+ dashboardPath: options.dashboardPath,
26
+ getDashboardController: options.getDashboardController,
27
+ getApiController: options.getApiController,
28
+ middleware,
29
+ });
360
30
  }
361
31
  }
@@ -0,0 +1,5 @@
1
+ import type ServerStatsController from '../controller/server_stats_controller.js';
2
+ import type { AdonisRouter } from './router_types.js';
3
+ import type { HttpContext } from '@adonisjs/core/http';
4
+ /** Register the stats polling endpoint. */
5
+ export declare function registerStatsRoute(router: AdonisRouter, endpoint: string, getController: () => ServerStatsController | null, middleware: Array<(ctx: HttpContext, next: () => Promise<void>) => Promise<void>>): void;
@@ -0,0 +1,14 @@
1
+ /** Register the stats polling endpoint. */
2
+ export function registerStatsRoute(router, endpoint, getController, middleware) {
3
+ router
4
+ .get(endpoint, async (ctx) => {
5
+ const controller = getController();
6
+ if (!controller)
7
+ return ctx.response.serviceUnavailable({
8
+ error: 'Stats engine is starting up, please retry',
9
+ });
10
+ return controller.index(ctx);
11
+ })
12
+ .as('server-stats.api')
13
+ .use(middleware);
14
+ }
@@ -309,6 +309,102 @@
309
309
  color: var(--ss-border);
310
310
  }
311
311
 
312
+ /* ── Filter / Search Bar ─────────────────────────────────────── */
313
+ /* Padding can be overridden via --ss-filter-px (debug: 12px, dashboard: 16px). */
314
+ .ss-filter-bar,
315
+ .ss-dash-filter-bar,
316
+ .ss-dash-search-bar,
317
+ .ss-dbg-filter-bar,
318
+ .ss-dbg-search-bar {
319
+ display: flex;
320
+ align-items: center;
321
+ gap: 8px;
322
+ padding: 8px var(--ss-filter-px, 12px);
323
+ border-bottom: 1px solid var(--ss-border-dim);
324
+ background: var(--ss-surface-alt);
325
+ flex-shrink: 0;
326
+ flex-wrap: wrap;
327
+ }
328
+ .ss-search-wrapper,
329
+ .ss-dash-search-wrapper,
330
+ .ss-dbg-search-wrapper {
331
+ position: relative;
332
+ flex: 1;
333
+ min-width: 180px;
334
+ }
335
+ .ss-search-icon,
336
+ .ss-dash-search-icon,
337
+ .ss-dbg-search-icon {
338
+ position: absolute;
339
+ left: 8px;
340
+ top: 50%;
341
+ transform: translateY(-50%);
342
+ width: 14px;
343
+ height: 14px;
344
+ color: var(--ss-dim);
345
+ pointer-events: none;
346
+ }
347
+ .ss-search,
348
+ .ss-dash-search,
349
+ .ss-dbg-search {
350
+ flex: 1;
351
+ width: 100%;
352
+ padding: var(--ss-search-py, 4px) var(--ss-search-px, 8px);
353
+ padding-left: 28px;
354
+ padding-right: 24px;
355
+ font-size: 11px;
356
+ color: var(--ss-text);
357
+ background: var(--ss-input-bg);
358
+ border: 1px solid var(--ss-border);
359
+ border-radius: 4px;
360
+ outline: none;
361
+ }
362
+ .ss-search:focus,
363
+ .ss-dash-search:focus,
364
+ .ss-dbg-search:focus {
365
+ border-color: var(--ss-accent);
366
+ }
367
+ .ss-search::placeholder,
368
+ .ss-dash-search::placeholder,
369
+ .ss-dbg-search::placeholder {
370
+ color: var(--ss-dim);
371
+ }
372
+ .ss-search-clear,
373
+ .ss-dash-search-clear,
374
+ .ss-dbg-search-clear {
375
+ position: absolute;
376
+ right: 6px;
377
+ top: 50%;
378
+ transform: translateY(-50%);
379
+ background: none;
380
+ border: none;
381
+ color: var(--ss-dim);
382
+ cursor: pointer;
383
+ font-size: 14px;
384
+ padding: 2px 4px;
385
+ line-height: 1;
386
+ }
387
+ .ss-search-clear:hover,
388
+ .ss-dash-search-clear:hover,
389
+ .ss-dbg-search-clear:hover {
390
+ color: var(--ss-text);
391
+ }
392
+ .ss-filter-controls,
393
+ .ss-dash-filter-controls,
394
+ .ss-dbg-filter-controls {
395
+ display: flex;
396
+ align-items: center;
397
+ gap: 6px;
398
+ margin-left: auto;
399
+ }
400
+ .ss-summary,
401
+ .ss-dash-summary,
402
+ .ss-dbg-summary {
403
+ font-size: 11px;
404
+ color: var(--ss-muted);
405
+ white-space: nowrap;
406
+ }
407
+
312
408
  /* ═══════════════════════════════════════════════════════════════
313
409
  * Phase 4: Full Component Unification
314
410
  * ═══════════════════════════════════════════════════════════════ */
@@ -1211,3 +1307,70 @@ tr:hover .ss-dbg-copy-row-btn,
1211
1307
  font-weight: 400;
1212
1308
  color: var(--ss-dim);
1213
1309
  }
1310
+
1311
+ /* ── Cache stats bar ─────────────────────────────────────────── */
1312
+ /* Shared between Dashboard CacheSection and DebugPanel CacheTab.
1313
+ * Gap/padding differ slightly — override via --ss-cache-stats-gap
1314
+ * and --ss-cache-stats-px / --ss-cache-stats-py. */
1315
+ .ss-cache-stats,
1316
+ .ss-dash-cache-stats,
1317
+ .ss-dbg-cache-stats {
1318
+ display: flex;
1319
+ gap: var(--ss-cache-stats-gap, 16px);
1320
+ padding: var(--ss-cache-stats-py, 8px) var(--ss-cache-stats-px, 12px);
1321
+ border-bottom: 1px solid var(--ss-border-dim);
1322
+ background: var(--ss-surface-alt);
1323
+ font-size: 11px;
1324
+ flex-shrink: 0;
1325
+ }
1326
+ .ss-cache-stat,
1327
+ .ss-dash-cache-stat,
1328
+ .ss-dbg-cache-stat {
1329
+ display: inline-flex;
1330
+ align-items: center;
1331
+ gap: 4px;
1332
+ }
1333
+ .ss-cache-stat-label,
1334
+ .ss-dash-cache-stat-label,
1335
+ .ss-dbg-cache-stat-label {
1336
+ color: var(--ss-muted);
1337
+ }
1338
+ .ss-cache-stat-value,
1339
+ .ss-dash-cache-stat-value,
1340
+ .ss-dbg-cache-stat-value {
1341
+ color: var(--ss-text);
1342
+ font-weight: 600;
1343
+ }
1344
+
1345
+ /* ── Job stats bar ──────────────────────────────────────────── */
1346
+ /* Shared between Dashboard JobsSection and DebugPanel JobsTab.
1347
+ * Gap/padding differ slightly — override via --ss-job-stats-gap
1348
+ * and --ss-job-stats-px / --ss-job-stats-py. */
1349
+ .ss-job-stats,
1350
+ .ss-dash-job-stats,
1351
+ .ss-dbg-job-stats {
1352
+ display: flex;
1353
+ gap: var(--ss-job-stats-gap, 16px);
1354
+ padding: var(--ss-job-stats-py, 8px) var(--ss-job-stats-px, 12px);
1355
+ background: var(--ss-surface-alt);
1356
+ font-size: 11px;
1357
+ flex-shrink: 0;
1358
+ }
1359
+ .ss-job-stat,
1360
+ .ss-dash-job-stat,
1361
+ .ss-dbg-job-stat {
1362
+ display: inline-flex;
1363
+ align-items: center;
1364
+ gap: 4px;
1365
+ }
1366
+ .ss-job-stat-label,
1367
+ .ss-dash-job-stat-label,
1368
+ .ss-dbg-job-stat-label {
1369
+ color: var(--ss-muted);
1370
+ }
1371
+ .ss-job-stat-value,
1372
+ .ss-dash-job-stat-value,
1373
+ .ss-dbg-job-stat-value {
1374
+ color: var(--ss-text);
1375
+ font-weight: 600;
1376
+ }