adonisjs-server-stats 1.11.7 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/explain-utils.d.ts +77 -0
- package/dist/core/index.d.ts +8 -2
- package/dist/core/index.js +1089 -877
- package/dist/core/queries-columns.d.ts +42 -0
- package/dist/core/queries-controller.d.ts +94 -0
- package/dist/core/query-utils.d.ts +49 -0
- package/dist/react/{CacheSection-DOUnyUrw.js → CacheSection-DZFOiOYH.js} +1 -1
- package/dist/react/{CacheTab-D9o6bsPc.js → CacheTab-D8js5o69.js} +1 -1
- package/dist/react/{ConfigSection-DzNC7pOJ.js → ConfigSection-DoJmvNkF.js} +1 -1
- package/dist/react/{ConfigTab-CT-Tu-ct.js → ConfigTab-CDvljuBF.js} +1 -1
- package/dist/react/{CustomPaneTab-CvIPe7NP.js → CustomPaneTab-Db9eIQ-9.js} +1 -1
- package/dist/react/{EmailsSection-B1LT7Nx3.js → EmailsSection-D7oxvAjA.js} +1 -1
- package/dist/react/{EmailsTab-DKxK322z.js → EmailsTab-BITuGTQm.js} +1 -1
- package/dist/react/{EventsSection-D3AK0mhw.js → EventsSection-7mDZv70I.js} +1 -1
- package/dist/react/{EventsTab-BRRSW6RI.js → EventsTab-DF13BChE.js} +1 -1
- package/dist/react/{JobsSection-BMvj5886.js → JobsSection-B_VJFWy6.js} +1 -1
- package/dist/react/{JobsTab-CQXWCrl8.js → JobsTab-DK8Fl9nz.js} +1 -1
- package/dist/react/{LogEntryRow-DFI52ZEw.js → LogEntryRow-Bdie9SFe.js} +1 -1
- package/dist/react/{LogsSection-CW2hQ976.js → LogsSection-CrWqxWRr.js} +2 -2
- package/dist/react/{LogsTab-CV4Gf_yb.js → LogsTab-DYSpL637.js} +2 -2
- package/dist/react/{OverviewSection-CxF9cabq.js → OverviewSection-CuaccMZt.js} +1 -1
- package/dist/react/QueriesContent-BDIx8zFn.js +288 -0
- package/dist/react/QueriesSection-CvGGh5Ij.js +117 -0
- package/dist/react/QueriesTab-C7CCwhVc.js +87 -0
- package/dist/react/{RequestsSection-Cb5YeqvI.js → RequestsSection-mENyeNsk.js} +2 -2
- package/dist/react/{RoutesSection-B43olD9v.js → RoutesSection-DjovlaNS.js} +1 -1
- package/dist/react/{RoutesTab-RfhCUbkx.js → RoutesTab-CbQECiUc.js} +1 -1
- package/dist/react/{SplitPaneWrapper-B05Mg6Sg.js → SplitPaneWrapper-DyRyH5Re.js} +1 -1
- package/dist/react/{TimelineTab-Dx4686Ti.js → TimelineTab-BKTFbsPe.js} +2 -2
- package/dist/react/components/shared/QueriesContent.d.ts +33 -0
- package/dist/react/{index-C4EMJrkH.js → index-CAUHa8QX.js} +2 -2
- package/dist/react/index.js +1 -1
- package/dist/react/style.css +1 -1
- package/dist/src/dashboard/query_explain_handler.d.ts +11 -0
- package/dist/src/dashboard/query_explain_handler.js +64 -11
- package/dist/src/debug/query_collector.d.ts +1 -0
- package/dist/src/debug/query_collector.js +3 -0
- package/dist/src/edge/client/dashboard.js +2 -2
- package/dist/src/edge/client/debug-panel-deferred.js +1 -1
- package/dist/src/edge/client-vue/dashboard.js +4 -4
- package/dist/src/edge/client-vue/debug-panel-deferred.js +2 -2
- package/dist/src/provider/server_stats_provider.js +2 -0
- package/dist/src/routes/debug_routes.d.ts +4 -0
- package/dist/src/routes/debug_routes.js +45 -0
- package/dist/src/routes/register_routes.d.ts +4 -0
- package/dist/src/routes/register_routes.js +2 -0
- package/dist/src/styles/components.css +238 -0
- package/dist/src/styles/dashboard.css +6 -173
- package/dist/src/styles/debug-panel.css +2 -24
- package/dist/vue/{CacheSection-BAotiuQq.js → CacheSection-Bx41lpfK.js} +1 -1
- package/dist/vue/{ConfigSection-JZjK5E5F.js → ConfigSection-fkfUdCmx.js} +1 -1
- package/dist/vue/{EmailsSection-BLwyQO7B.js → EmailsSection-CbcDKF9Q.js} +1 -1
- package/dist/vue/{EventsSection-BUEwO-0A.js → EventsSection-CWbTYOBi.js} +1 -1
- package/dist/vue/{JobsSection-21A0yQMq.js → JobsSection-CGGO6rtS.js} +1 -1
- package/dist/vue/{LogsSection-BmOx8SNa.js → LogsSection-BPB-C-XA.js} +1 -1
- package/dist/vue/{OverviewSection-BRDK3Ony.js → OverviewSection-BTcnPeoM.js} +1 -1
- package/dist/vue/QueriesSection-2SE3igQJ.js +411 -0
- package/dist/vue/QueriesTab-DO5XwJ--.js +112 -0
- package/dist/vue/{RequestsSection-DLrjCfcE.js → RequestsSection-DXcG5Zok.js} +1 -1
- package/dist/vue/{RoutesSection-CPr9w42B.js → RoutesSection-BkNGWdoP.js} +1 -1
- package/dist/vue/components/Dashboard/sections/QueriesSection.vue.d.ts +1 -41
- package/dist/vue/{index-CYaqRGIT.js → index-CptF6Qbp.js} +2 -2
- package/dist/vue/index.js +1 -1
- package/dist/vue/style.css +1 -1
- package/package.json +1 -1
- package/dist/react/QueriesSection-CZJ-imAb.js +0 -474
- package/dist/react/QueriesTab-CQHa1ck3.js +0 -97
- package/dist/vue/QueriesSection-D2WGsuR4.js +0 -444
- package/dist/vue/QueriesTab-6D_xfi7Q.js +0 -114
|
@@ -88,6 +88,8 @@ export default class ServerStatsProvider {
|
|
|
88
88
|
getStatsController: () => this.statsController,
|
|
89
89
|
getDebugController: () => this.debugController,
|
|
90
90
|
getDashboardController: () => this.dashboardController,
|
|
91
|
+
getDebugStore: () => this.debugStore,
|
|
92
|
+
getApp: () => this.app,
|
|
91
93
|
statsEndpoint,
|
|
92
94
|
debugEndpoint,
|
|
93
95
|
dashboardPath,
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import type { ApiController } from '../controller/api_controller.js';
|
|
2
2
|
import type DebugController from '../controller/debug_controller.js';
|
|
3
|
+
import type { DebugStore } from '../debug/debug_store.js';
|
|
3
4
|
import type { AdonisRouter } from './router_types.js';
|
|
4
5
|
import type { HttpContext } from '@adonisjs/core/http';
|
|
6
|
+
import type { ApplicationService } from '@adonisjs/core/types';
|
|
5
7
|
interface DebugRoutesOpts {
|
|
6
8
|
router: AdonisRouter;
|
|
7
9
|
debugEndpoint: string;
|
|
8
10
|
getDebugController: () => DebugController | null;
|
|
9
11
|
getApiController: () => ApiController | null;
|
|
12
|
+
getDebugStore?: () => DebugStore | null;
|
|
13
|
+
getApp?: () => ApplicationService | null;
|
|
10
14
|
middleware: Array<(ctx: HttpContext, next: () => Promise<void>) => Promise<void>>;
|
|
11
15
|
whenReady?: () => Promise<void>;
|
|
12
16
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getAppDbClient, buildExplainSql, extractPlan } from '../dashboard/query_explain_handler.js';
|
|
1
2
|
let _whenReady;
|
|
2
3
|
function bindDebug(getController, method) {
|
|
3
4
|
return async (ctx) => {
|
|
@@ -89,6 +90,49 @@ function registerDebugTraceRoutes(router, getApiController) {
|
|
|
89
90
|
}))
|
|
90
91
|
.as('server-stats.debug.traceDetail');
|
|
91
92
|
}
|
|
93
|
+
function registerDebugExplainRoute(router, getDebugStore, getApp) {
|
|
94
|
+
if (!getDebugStore || !getApp)
|
|
95
|
+
return;
|
|
96
|
+
router
|
|
97
|
+
.get('/queries/:id/explain', async (ctx) => {
|
|
98
|
+
if (_whenReady)
|
|
99
|
+
await _whenReady();
|
|
100
|
+
const store = getDebugStore();
|
|
101
|
+
const app = getApp();
|
|
102
|
+
if (!store || !app) {
|
|
103
|
+
return ctx.response.serviceUnavailable({ error: 'Debug store not ready' });
|
|
104
|
+
}
|
|
105
|
+
const query = store.queries.getQueryById(Number(ctx.params.id));
|
|
106
|
+
if (!query)
|
|
107
|
+
return ctx.response.notFound({ error: 'Query not found' });
|
|
108
|
+
if (!query.sql.trim().toUpperCase().startsWith('SELECT')) {
|
|
109
|
+
return ctx.response.badRequest({ error: 'EXPLAIN is only supported for SELECT queries' });
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
const appDb = await getAppDbClient(app, query.connection || undefined);
|
|
113
|
+
if (!appDb) {
|
|
114
|
+
return ctx.response.serviceUnavailable({ error: 'App database connection not available' });
|
|
115
|
+
}
|
|
116
|
+
const bindings = Array.isArray(query.bindings) ? query.bindings : [];
|
|
117
|
+
const explainSql = buildExplainSql(query.sql, appDb.dialect);
|
|
118
|
+
if (!explainSql) {
|
|
119
|
+
return ctx.response.badRequest({
|
|
120
|
+
error: `EXPLAIN is not supported for ${appDb.dialect} databases`,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
const explainResult = await appDb.raw(explainSql, bindings);
|
|
124
|
+
const plan = extractPlan(explainResult, appDb.dialect);
|
|
125
|
+
return ctx.response.json({ queryId: query.id, sql: query.sql, plan });
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
return ctx.response.internalServerError({
|
|
129
|
+
error: 'EXPLAIN failed',
|
|
130
|
+
message: error?.message ?? 'Unknown error',
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
})
|
|
134
|
+
.as('server-stats.debug.queryExplain');
|
|
135
|
+
}
|
|
92
136
|
/** Register debug panel API routes. */
|
|
93
137
|
export function registerDebugRoutes(opts) {
|
|
94
138
|
const { router, debugEndpoint, getDebugController, getApiController, middleware } = opts;
|
|
@@ -99,6 +143,7 @@ export function registerDebugRoutes(opts) {
|
|
|
99
143
|
.group(() => {
|
|
100
144
|
registerDebugConfigRoutes(router, getDebugController);
|
|
101
145
|
registerDebugQueryAndEventRoutes(router, getApiController);
|
|
146
|
+
registerDebugExplainRoute(router, opts.getDebugStore, opts.getApp);
|
|
102
147
|
registerDebugLogRoutes(router, getApiController);
|
|
103
148
|
registerDebugEmailRoutes(router, getApiController);
|
|
104
149
|
registerDebugTraceRoutes(router, getApiController);
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { ApiController } from '../controller/api_controller.js';
|
|
2
2
|
import type DebugController from '../controller/debug_controller.js';
|
|
3
|
+
import type { DebugStore } from '../debug/debug_store.js';
|
|
3
4
|
import type ServerStatsController from '../controller/server_stats_controller.js';
|
|
4
5
|
import type DashboardController from '../dashboard/dashboard_controller.js';
|
|
5
6
|
import type { AdonisRouter } from './router_types.js';
|
|
6
7
|
import type { HttpContext } from '@adonisjs/core/http';
|
|
8
|
+
import type { ApplicationService } from '@adonisjs/core/types';
|
|
7
9
|
/**
|
|
8
10
|
* Options for the unified route registration function.
|
|
9
11
|
*/
|
|
@@ -13,6 +15,8 @@ export interface RegisterRoutesOptions {
|
|
|
13
15
|
getStatsController: () => ServerStatsController | null;
|
|
14
16
|
getDebugController: () => DebugController | null;
|
|
15
17
|
getDashboardController: () => DashboardController | null;
|
|
18
|
+
getDebugStore?: () => DebugStore | null;
|
|
19
|
+
getApp?: () => ApplicationService | null;
|
|
16
20
|
statsEndpoint?: string | false;
|
|
17
21
|
debugEndpoint?: string;
|
|
18
22
|
dashboardPath?: string;
|
|
@@ -16,6 +16,8 @@ export function registerAllRoutes(options) {
|
|
|
16
16
|
debugEndpoint: options.debugEndpoint,
|
|
17
17
|
getDebugController: options.getDebugController,
|
|
18
18
|
getApiController: options.getApiController,
|
|
19
|
+
getDebugStore: options.getDebugStore,
|
|
20
|
+
getApp: options.getApp,
|
|
19
21
|
middleware,
|
|
20
22
|
whenReady: options.whenReady,
|
|
21
23
|
});
|
|
@@ -451,6 +451,7 @@
|
|
|
451
451
|
background: var(--ss-surface);
|
|
452
452
|
border-bottom: 1px solid var(--ss-border);
|
|
453
453
|
white-space: nowrap;
|
|
454
|
+
z-index: 2;
|
|
454
455
|
}
|
|
455
456
|
.ss-table td,
|
|
456
457
|
.ss-dash-table td,
|
|
@@ -462,6 +463,7 @@
|
|
|
462
463
|
text-overflow: ellipsis;
|
|
463
464
|
white-space: nowrap;
|
|
464
465
|
color: var(--ss-text);
|
|
466
|
+
max-width: 0;
|
|
465
467
|
}
|
|
466
468
|
.ss-table tr:hover td,
|
|
467
469
|
.ss-dash-table tr:hover td,
|
|
@@ -533,6 +535,242 @@
|
|
|
533
535
|
background: var(--ss-red-bg);
|
|
534
536
|
color: var(--ss-red-fg);
|
|
535
537
|
}
|
|
538
|
+
/* SQL method variants (query tables) */
|
|
539
|
+
.ss-method-select,
|
|
540
|
+
.ss-dash-method-select,
|
|
541
|
+
.ss-dbg-method-select {
|
|
542
|
+
background: var(--ss-green-bg);
|
|
543
|
+
color: var(--ss-green-fg);
|
|
544
|
+
}
|
|
545
|
+
.ss-method-insert,
|
|
546
|
+
.ss-dash-method-insert,
|
|
547
|
+
.ss-dbg-method-insert {
|
|
548
|
+
background: var(--ss-blue-bg);
|
|
549
|
+
color: var(--ss-blue-fg);
|
|
550
|
+
}
|
|
551
|
+
.ss-method-update,
|
|
552
|
+
.ss-dash-method-update,
|
|
553
|
+
.ss-dbg-method-update {
|
|
554
|
+
background: var(--ss-amber-bg);
|
|
555
|
+
color: var(--ss-amber-fg);
|
|
556
|
+
}
|
|
557
|
+
.ss-method-head,
|
|
558
|
+
.ss-method-options,
|
|
559
|
+
.ss-method-raw,
|
|
560
|
+
.ss-dash-method-head,
|
|
561
|
+
.ss-dash-method-options,
|
|
562
|
+
.ss-dash-method-raw,
|
|
563
|
+
.ss-dbg-method-head,
|
|
564
|
+
.ss-dbg-method-options,
|
|
565
|
+
.ss-dbg-method-raw {
|
|
566
|
+
background: var(--ss-surface);
|
|
567
|
+
color: var(--ss-dim);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/* ── SQL cell text ───────────────────────────────────────────── */
|
|
571
|
+
.ss-sql,
|
|
572
|
+
.ss-dash-sql,
|
|
573
|
+
.ss-dbg-sql {
|
|
574
|
+
font-size: 11px;
|
|
575
|
+
color: var(--ss-sql-color);
|
|
576
|
+
word-break: break-all;
|
|
577
|
+
cursor: pointer;
|
|
578
|
+
max-width: 600px;
|
|
579
|
+
display: inline-block;
|
|
580
|
+
}
|
|
581
|
+
.ss-sql.ss-expanded,
|
|
582
|
+
.ss-dash-sql.ss-dash-expanded,
|
|
583
|
+
.ss-dbg-sql.ss-dbg-expanded {
|
|
584
|
+
white-space: pre-wrap;
|
|
585
|
+
max-width: none;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/* ── Duplicate query badge ───────────────────────────────────── */
|
|
589
|
+
.ss-dup,
|
|
590
|
+
.ss-dash-dup,
|
|
591
|
+
.ss-dbg-dup {
|
|
592
|
+
color: var(--ss-purple-fg);
|
|
593
|
+
font-size: 10px;
|
|
594
|
+
font-weight: 600;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/* ── Scrollable table container ──────────────────────────────── */
|
|
598
|
+
.ss-table-wrap,
|
|
599
|
+
.ss-dash-table-wrap,
|
|
600
|
+
.ss-dbg-table-wrap {
|
|
601
|
+
flex: 1;
|
|
602
|
+
overflow-x: auto;
|
|
603
|
+
overflow-y: visible;
|
|
604
|
+
margin: 0 -2px;
|
|
605
|
+
padding: 0 2px;
|
|
606
|
+
scrollbar-width: thin;
|
|
607
|
+
scrollbar-color: var(--ss-border) transparent;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/* ── Sortable column headers ─────────────────────────────────── */
|
|
611
|
+
.ss-sortable,
|
|
612
|
+
.ss-dash-sortable,
|
|
613
|
+
.ss-dbg-sortable {
|
|
614
|
+
cursor: pointer;
|
|
615
|
+
user-select: none;
|
|
616
|
+
}
|
|
617
|
+
.ss-sortable:hover,
|
|
618
|
+
.ss-dash-sortable:hover,
|
|
619
|
+
.ss-dbg-sortable:hover {
|
|
620
|
+
color: var(--ss-accent);
|
|
621
|
+
}
|
|
622
|
+
.ss-sort-arrow,
|
|
623
|
+
.ss-dash-sort-arrow,
|
|
624
|
+
.ss-dbg-sort-arrow {
|
|
625
|
+
font-size: 10px;
|
|
626
|
+
color: var(--ss-accent);
|
|
627
|
+
margin-left: 2px;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/* ── Clickable table rows ────────────────────────────────────── */
|
|
631
|
+
.ss-table tr.ss-clickable,
|
|
632
|
+
.ss-dash-table tr.ss-dash-clickable,
|
|
633
|
+
.ss-dbg-table tr.ss-dbg-clickable {
|
|
634
|
+
cursor: pointer;
|
|
635
|
+
}
|
|
636
|
+
.ss-table tr.ss-clickable:hover td,
|
|
637
|
+
.ss-dash-table tr.ss-dash-clickable:hover td,
|
|
638
|
+
.ss-dbg-table tr.ss-dbg-clickable:hover td {
|
|
639
|
+
background: var(--ss-hover-accent);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/* ── Event time ──────────────────────────────────────────────── */
|
|
643
|
+
.ss-event-time,
|
|
644
|
+
.ss-dash-event-time,
|
|
645
|
+
.ss-dbg-event-time {
|
|
646
|
+
color: var(--ss-dim);
|
|
647
|
+
font-size: 10px;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
/* ── EXPLAIN panel ───────────────────────────────────────────── */
|
|
651
|
+
.ss-explain-row td,
|
|
652
|
+
.ss-dash-explain-row td,
|
|
653
|
+
.ss-dbg-explain-row td {
|
|
654
|
+
white-space: normal;
|
|
655
|
+
overflow: visible;
|
|
656
|
+
max-width: none;
|
|
657
|
+
}
|
|
658
|
+
.ss-table tr.ss-explain-row:hover td,
|
|
659
|
+
.ss-dash-table tr.ss-dash-explain-row:hover td,
|
|
660
|
+
.ss-dbg-table tr.ss-dbg-explain-row:hover td {
|
|
661
|
+
background: var(--ss-surface-alt);
|
|
662
|
+
}
|
|
663
|
+
.ss-explain,
|
|
664
|
+
.ss-dash-explain,
|
|
665
|
+
.ss-dbg-explain {
|
|
666
|
+
padding: 12px 16px;
|
|
667
|
+
background: var(--ss-surface-alt);
|
|
668
|
+
border-top: 1px solid var(--ss-border-dim);
|
|
669
|
+
font-size: 11px;
|
|
670
|
+
overflow: hidden;
|
|
671
|
+
word-break: break-word;
|
|
672
|
+
}
|
|
673
|
+
.ss-explain-btn,
|
|
674
|
+
.ss-dash-explain-btn,
|
|
675
|
+
.ss-dbg-explain-btn {
|
|
676
|
+
padding: 2px 8px;
|
|
677
|
+
font-size: 9px;
|
|
678
|
+
color: var(--ss-purple-fg);
|
|
679
|
+
background: var(--ss-purple-bg);
|
|
680
|
+
border: none;
|
|
681
|
+
border-radius: 3px;
|
|
682
|
+
cursor: pointer;
|
|
683
|
+
text-transform: uppercase;
|
|
684
|
+
letter-spacing: 0.04em;
|
|
685
|
+
font-weight: 600;
|
|
686
|
+
}
|
|
687
|
+
.ss-explain-btn:hover,
|
|
688
|
+
.ss-dash-explain-btn:hover,
|
|
689
|
+
.ss-dbg-explain-btn:hover {
|
|
690
|
+
opacity: 0.8;
|
|
691
|
+
}
|
|
692
|
+
.ss-explain-btn-active,
|
|
693
|
+
.ss-dash-explain-btn-active,
|
|
694
|
+
.ss-dbg-explain-btn-active {
|
|
695
|
+
background: var(--ss-purple-fg);
|
|
696
|
+
color: #fff;
|
|
697
|
+
}
|
|
698
|
+
.ss-explain-result,
|
|
699
|
+
.ss-dash-explain-result,
|
|
700
|
+
.ss-dbg-explain-result {
|
|
701
|
+
margin-top: 6px;
|
|
702
|
+
font-size: 11px;
|
|
703
|
+
color: var(--ss-text-secondary);
|
|
704
|
+
}
|
|
705
|
+
.ss-explain-error,
|
|
706
|
+
.ss-dash-explain-error,
|
|
707
|
+
.ss-dbg-explain-error {
|
|
708
|
+
color: var(--ss-red-fg);
|
|
709
|
+
padding: 8px;
|
|
710
|
+
background: var(--ss-red-bg);
|
|
711
|
+
border-radius: 4px;
|
|
712
|
+
}
|
|
713
|
+
.ss-explain-node,
|
|
714
|
+
.ss-dash-explain-node,
|
|
715
|
+
.ss-dbg-explain-node {
|
|
716
|
+
padding: 4px 0;
|
|
717
|
+
border-left: 2px solid var(--ss-border-dim);
|
|
718
|
+
padding-left: 10px;
|
|
719
|
+
margin-top: 2px;
|
|
720
|
+
}
|
|
721
|
+
.ss-explain-node:first-child,
|
|
722
|
+
.ss-dash-explain-node:first-child,
|
|
723
|
+
.ss-dbg-explain-node:first-child {
|
|
724
|
+
border-left: 2px solid var(--ss-purple-fg);
|
|
725
|
+
}
|
|
726
|
+
.ss-explain-node-header,
|
|
727
|
+
.ss-dash-explain-node-header,
|
|
728
|
+
.ss-dbg-explain-node-header {
|
|
729
|
+
font-weight: 600;
|
|
730
|
+
color: var(--ss-text-primary);
|
|
731
|
+
font-size: 11px;
|
|
732
|
+
}
|
|
733
|
+
.ss-explain-node-type,
|
|
734
|
+
.ss-dash-explain-node-type,
|
|
735
|
+
.ss-dbg-explain-node-type {
|
|
736
|
+
color: var(--ss-purple-fg);
|
|
737
|
+
font-weight: 700;
|
|
738
|
+
}
|
|
739
|
+
.ss-explain-metrics,
|
|
740
|
+
.ss-dash-explain-metrics,
|
|
741
|
+
.ss-dbg-explain-metrics {
|
|
742
|
+
font-size: 10px;
|
|
743
|
+
color: var(--ss-dim);
|
|
744
|
+
margin-top: 1px;
|
|
745
|
+
font-family: var(--ss-font-mono);
|
|
746
|
+
word-break: break-all;
|
|
747
|
+
overflow-wrap: break-word;
|
|
748
|
+
}
|
|
749
|
+
.ss-explain-result table,
|
|
750
|
+
.ss-dash-explain-result table,
|
|
751
|
+
.ss-dbg-explain-result table {
|
|
752
|
+
width: 100%;
|
|
753
|
+
border-collapse: collapse;
|
|
754
|
+
margin-top: 4px;
|
|
755
|
+
}
|
|
756
|
+
.ss-explain-result th,
|
|
757
|
+
.ss-dash-explain-result th,
|
|
758
|
+
.ss-dbg-explain-result th {
|
|
759
|
+
padding: 3px 8px;
|
|
760
|
+
text-align: left;
|
|
761
|
+
font-weight: 600;
|
|
762
|
+
color: var(--ss-muted);
|
|
763
|
+
border-bottom: 1px solid var(--ss-border);
|
|
764
|
+
font-size: 9px;
|
|
765
|
+
text-transform: uppercase;
|
|
766
|
+
}
|
|
767
|
+
.ss-explain-result td,
|
|
768
|
+
.ss-dash-explain-result td,
|
|
769
|
+
.ss-dbg-explain-result td {
|
|
770
|
+
padding: 3px 8px;
|
|
771
|
+
border-bottom: 1px solid var(--ss-border-faint);
|
|
772
|
+
color: var(--ss-text-secondary);
|
|
773
|
+
}
|
|
536
774
|
|
|
537
775
|
/* ── 3. Log system ───────────────────────────────────────────── */
|
|
538
776
|
/* Log entry row: dashboard uses 16px horizontal padding, debug uses 12px.
|
|
@@ -366,48 +366,12 @@ html:has(#ss-dash) body {
|
|
|
366
366
|
}
|
|
367
367
|
|
|
368
368
|
/* ── Tables ────────────────────────────────────────────────────── */
|
|
369
|
+
/* Table base / table-wrap / sortable / clickable → components.css */
|
|
370
|
+
/* Dashboard overrides: wider cell padding */
|
|
369
371
|
.ss-dash-table-wrap {
|
|
370
372
|
--ss-table-cell-px: 12px;
|
|
371
373
|
--ss-table-cell-py: 7px;
|
|
372
374
|
--ss-table-td-py: 6px;
|
|
373
|
-
flex: 1;
|
|
374
|
-
overflow-x: auto;
|
|
375
|
-
overflow-y: visible;
|
|
376
|
-
margin: 0 -2px;
|
|
377
|
-
padding: 0 2px;
|
|
378
|
-
scrollbar-width: thin;
|
|
379
|
-
scrollbar-color: var(--ss-border) transparent;
|
|
380
|
-
}
|
|
381
|
-
/* Table base → components.css */
|
|
382
|
-
/* Column resize → components.css */
|
|
383
|
-
.ss-dash-table th {
|
|
384
|
-
z-index: 2;
|
|
385
|
-
}
|
|
386
|
-
.ss-dash-table td {
|
|
387
|
-
max-width: 0;
|
|
388
|
-
}
|
|
389
|
-
.ss-dash-table tr.ss-dash-explain-row:hover td {
|
|
390
|
-
background: var(--ss-surface-alt);
|
|
391
|
-
}
|
|
392
|
-
.ss-dash-table tr.ss-dash-clickable {
|
|
393
|
-
cursor: pointer;
|
|
394
|
-
}
|
|
395
|
-
.ss-dash-table tr.ss-dash-clickable:hover td {
|
|
396
|
-
background: var(--ss-hover-accent);
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
.ss-dash-sortable {
|
|
400
|
-
cursor: pointer;
|
|
401
|
-
user-select: none;
|
|
402
|
-
}
|
|
403
|
-
.ss-dash-sortable:hover {
|
|
404
|
-
color: var(--ss-accent);
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
.ss-dash-sort-arrow {
|
|
408
|
-
font-size: 10px;
|
|
409
|
-
color: var(--ss-accent);
|
|
410
|
-
margin-left: 2px;
|
|
411
375
|
}
|
|
412
376
|
|
|
413
377
|
.ss-dash-data-cell {
|
|
@@ -415,27 +379,7 @@ html:has(#ss-dash) body {
|
|
|
415
379
|
max-width: 300px;
|
|
416
380
|
}
|
|
417
381
|
|
|
418
|
-
/* ── Method badges
|
|
419
|
-
/* Base + GET/POST/PUT/PATCH/DELETE → components.css */
|
|
420
|
-
/* Dashboard-only SQL method variants */
|
|
421
|
-
.ss-dash-method-select {
|
|
422
|
-
background: var(--ss-green-bg);
|
|
423
|
-
color: var(--ss-green-fg);
|
|
424
|
-
}
|
|
425
|
-
.ss-dash-method-insert {
|
|
426
|
-
background: var(--ss-blue-bg);
|
|
427
|
-
color: var(--ss-blue-fg);
|
|
428
|
-
}
|
|
429
|
-
.ss-dash-method-update {
|
|
430
|
-
background: var(--ss-amber-bg);
|
|
431
|
-
color: var(--ss-amber-fg);
|
|
432
|
-
}
|
|
433
|
-
.ss-dash-method-head,
|
|
434
|
-
.ss-dash-method-options,
|
|
435
|
-
.ss-dash-method-raw {
|
|
436
|
-
background: var(--ss-surface);
|
|
437
|
-
color: var(--ss-dim);
|
|
438
|
-
}
|
|
382
|
+
/* ── Method badges → components.css ────────────────────────────── */
|
|
439
383
|
|
|
440
384
|
/* Status badges → components.css */
|
|
441
385
|
/* Badge generic → components.css */
|
|
@@ -447,26 +391,7 @@ html:has(#ss-dash) body {
|
|
|
447
391
|
|
|
448
392
|
/* Duration → components.css */
|
|
449
393
|
|
|
450
|
-
/* ── SQL
|
|
451
|
-
.ss-dash-sql {
|
|
452
|
-
font-size: 11px;
|
|
453
|
-
color: var(--ss-sql-color);
|
|
454
|
-
word-break: break-all;
|
|
455
|
-
cursor: pointer;
|
|
456
|
-
max-width: 600px;
|
|
457
|
-
/* truncation → utilities.css */
|
|
458
|
-
display: inline-block;
|
|
459
|
-
}
|
|
460
|
-
.ss-dash-sql.ss-dash-expanded {
|
|
461
|
-
white-space: pre-wrap;
|
|
462
|
-
max-width: none;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
.ss-dash-dup {
|
|
466
|
-
color: var(--ss-purple-fg);
|
|
467
|
-
font-size: 10px;
|
|
468
|
-
font-weight: 600;
|
|
469
|
-
}
|
|
394
|
+
/* ── SQL / Dup → components.css ────────────────────────────────── */
|
|
470
395
|
|
|
471
396
|
/* ── Current route highlight ───────────────────────────────────── */
|
|
472
397
|
.ss-dash-current-route td {
|
|
@@ -520,11 +445,7 @@ html:has(#ss-dash) body {
|
|
|
520
445
|
font-size: 10px;
|
|
521
446
|
position: relative;
|
|
522
447
|
}
|
|
523
|
-
.ss-dash-event-time
|
|
524
|
-
color: var(--ss-dim);
|
|
525
|
-
font-size: 10px;
|
|
526
|
-
/* tabular-nums → utilities.css */
|
|
527
|
-
}
|
|
448
|
+
/* .ss-dash-event-time → components.css */
|
|
528
449
|
|
|
529
450
|
/* ── Logs ──────────────────────────────────────────────────────── */
|
|
530
451
|
/* Log entry / level / time / reqid / msg → components.css */
|
|
@@ -734,95 +655,7 @@ html:has(#ss-dash) body {
|
|
|
734
655
|
flex-shrink: 0;
|
|
735
656
|
}
|
|
736
657
|
|
|
737
|
-
/* ── EXPLAIN panel
|
|
738
|
-
.ss-dash-explain-row td {
|
|
739
|
-
white-space: normal;
|
|
740
|
-
overflow: visible;
|
|
741
|
-
max-width: none;
|
|
742
|
-
}
|
|
743
|
-
.ss-dash-explain {
|
|
744
|
-
padding: 12px 16px;
|
|
745
|
-
background: var(--ss-surface-alt);
|
|
746
|
-
border-top: 1px solid var(--ss-border-dim);
|
|
747
|
-
font-size: 11px;
|
|
748
|
-
overflow: hidden;
|
|
749
|
-
word-break: break-word;
|
|
750
|
-
}
|
|
751
|
-
.ss-dash-explain-btn {
|
|
752
|
-
padding: 2px 8px;
|
|
753
|
-
font-size: 9px;
|
|
754
|
-
color: var(--ss-purple-fg);
|
|
755
|
-
background: var(--ss-purple-bg);
|
|
756
|
-
border: none;
|
|
757
|
-
border-radius: 3px;
|
|
758
|
-
cursor: pointer;
|
|
759
|
-
text-transform: uppercase;
|
|
760
|
-
letter-spacing: 0.04em;
|
|
761
|
-
font-weight: 600;
|
|
762
|
-
}
|
|
763
|
-
.ss-dash-explain-btn:hover {
|
|
764
|
-
opacity: 0.8;
|
|
765
|
-
}
|
|
766
|
-
.ss-dash-explain-btn-active {
|
|
767
|
-
background: var(--ss-purple-fg);
|
|
768
|
-
color: #fff;
|
|
769
|
-
}
|
|
770
|
-
.ss-dash-explain-result {
|
|
771
|
-
margin-top: 6px;
|
|
772
|
-
font-size: 11px;
|
|
773
|
-
color: var(--ss-text-secondary);
|
|
774
|
-
}
|
|
775
|
-
.ss-dash-explain-error {
|
|
776
|
-
color: var(--ss-red-fg);
|
|
777
|
-
padding: 8px;
|
|
778
|
-
background: var(--ss-red-bg);
|
|
779
|
-
border-radius: 4px;
|
|
780
|
-
}
|
|
781
|
-
.ss-dash-explain-node {
|
|
782
|
-
padding: 4px 0;
|
|
783
|
-
border-left: 2px solid var(--ss-border-dim);
|
|
784
|
-
padding-left: 10px;
|
|
785
|
-
margin-top: 2px;
|
|
786
|
-
}
|
|
787
|
-
.ss-dash-explain-node:first-child {
|
|
788
|
-
border-left: 2px solid var(--ss-purple-fg);
|
|
789
|
-
}
|
|
790
|
-
.ss-dash-explain-node-header {
|
|
791
|
-
font-weight: 600;
|
|
792
|
-
color: var(--ss-text-primary);
|
|
793
|
-
font-size: 11px;
|
|
794
|
-
}
|
|
795
|
-
.ss-dash-explain-node-type {
|
|
796
|
-
color: var(--ss-purple-fg);
|
|
797
|
-
font-weight: 700;
|
|
798
|
-
}
|
|
799
|
-
.ss-dash-explain-metrics {
|
|
800
|
-
font-size: 10px;
|
|
801
|
-
color: var(--ss-dim);
|
|
802
|
-
margin-top: 1px;
|
|
803
|
-
font-family: var(--ss-font-mono);
|
|
804
|
-
word-break: break-all;
|
|
805
|
-
overflow-wrap: break-word;
|
|
806
|
-
}
|
|
807
|
-
.ss-dash-explain-result table {
|
|
808
|
-
width: 100%;
|
|
809
|
-
border-collapse: collapse;
|
|
810
|
-
margin-top: 4px;
|
|
811
|
-
}
|
|
812
|
-
.ss-dash-explain-result th {
|
|
813
|
-
padding: 3px 8px;
|
|
814
|
-
text-align: left;
|
|
815
|
-
font-weight: 600;
|
|
816
|
-
color: var(--ss-muted);
|
|
817
|
-
border-bottom: 1px solid var(--ss-border);
|
|
818
|
-
font-size: 9px;
|
|
819
|
-
text-transform: uppercase;
|
|
820
|
-
}
|
|
821
|
-
.ss-dash-explain-result td {
|
|
822
|
-
padding: 3px 8px;
|
|
823
|
-
border-bottom: 1px solid var(--ss-border-faint);
|
|
824
|
-
color: var(--ss-text-secondary);
|
|
825
|
-
}
|
|
658
|
+
/* ── EXPLAIN panel → components.css ────────────────────────────── */
|
|
826
659
|
|
|
827
660
|
/* ── Overview cards ────────────────────────────────────────────── */
|
|
828
661
|
.ss-dash-overview {
|
|
@@ -272,24 +272,7 @@
|
|
|
272
272
|
|
|
273
273
|
/* Table base / column resize → components.css */
|
|
274
274
|
|
|
275
|
-
/* Query-specific styles */
|
|
276
|
-
.ss-dbg-sql {
|
|
277
|
-
font-size: 11px;
|
|
278
|
-
color: var(--ss-sql-color);
|
|
279
|
-
word-break: break-all;
|
|
280
|
-
cursor: pointer;
|
|
281
|
-
max-width: 500px;
|
|
282
|
-
/* truncation → utilities.css */
|
|
283
|
-
}
|
|
284
|
-
.ss-dbg-sql.ss-dbg-expanded {
|
|
285
|
-
white-space: pre-wrap;
|
|
286
|
-
max-width: none;
|
|
287
|
-
}
|
|
288
|
-
/* Duration → components.css */
|
|
289
|
-
.ss-dbg-dup {
|
|
290
|
-
color: var(--ss-purple-fg);
|
|
291
|
-
font-size: 10px;
|
|
292
|
-
}
|
|
275
|
+
/* Query-specific styles → components.css (sql, dup, explain, etc.) */
|
|
293
276
|
|
|
294
277
|
/* Method badges → components.css */
|
|
295
278
|
|
|
@@ -309,12 +292,7 @@
|
|
|
309
292
|
position: relative;
|
|
310
293
|
/* truncation → utilities.css */
|
|
311
294
|
}
|
|
312
|
-
.ss-dbg-event-time
|
|
313
|
-
color: var(--ss-dim);
|
|
314
|
-
font-size: 10px;
|
|
315
|
-
/* tabular-nums → utilities.css */
|
|
316
|
-
white-space: nowrap;
|
|
317
|
-
}
|
|
295
|
+
/* .ss-dbg-event-time → components.css */
|
|
318
296
|
.ss-dbg-data-preview {
|
|
319
297
|
cursor: pointer;
|
|
320
298
|
color: var(--ss-text-secondary);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineComponent as E, inject as v, ref as h, computed as C, openBlock as a, createElementBlock as l, createElementVNode as e, toDisplayString as c, createCommentVNode as g, createVNode as F, unref as y, Fragment as N, renderList as A, withModifiers as B, createBlock as U } from "vue";
|
|
2
|
-
import { u as H } from "./index-
|
|
2
|
+
import { u as H } from "./index-CptF6Qbp.js";
|
|
3
3
|
import { u as M } from "./useResizableTable-BoivAevK.js";
|
|
4
4
|
import { DashboardApi as j, formatCacheSize as q, formatTtl as I } from "adonisjs-server-stats/core";
|
|
5
5
|
import { u as G } from "./useApiClient-BQQ9CF-q.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineComponent as re, inject as m, ref as w, computed as x, openBlock as i, createElementBlock as r, createElementVNode as n, normalizeClass as a, createCommentVNode as b, Fragment as _, toDisplayString as u, unref as c, renderList as A, withModifiers as I, normalizeStyle as R } from "vue";
|
|
2
|
-
import { u as ue } from "./index-
|
|
2
|
+
import { u as ue } from "./index-CptF6Qbp.js";
|
|
3
3
|
import { isRedactedValue as d, flattenConfig as z, TAB_ICONS as g, countLeaves as ce, collectTopLevelObjectKeys as pe, copyWithFeedback as de, formatFlatValue as ve } from "adonisjs-server-stats/core";
|
|
4
4
|
const fe = { style: { position: "relative", flex: 1 } }, he = ["value"], ge = ["title", "onClick"], ye = ["viewBox", "innerHTML"], be = ["viewBox", "innerHTML"], $e = ["onClick"], we = { key: 0 }, xe = ["title", "onClick"], ke = ["viewBox", "innerHTML"], Ce = ["viewBox", "innerHTML"], _e = ["onClick"], Se = { key: 0 }, Be = { style: { padding: "4px 16px", fontSize: "10px", color: "var(--ss-muted)" } }, Le = ["onClick"], He = ["title"], Te = ["title"], je = ["title", "onClick"], Me = ["viewBox", "innerHTML"], me = ["viewBox", "innerHTML"], Ae = ["onClick"], Ie = ["title", "onClick"], Ee = ["viewBox", "innerHTML"], Ve = ["viewBox", "innerHTML"], Oe = {
|
|
5
5
|
key: 1,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineComponent as V, inject as h, ref as f, computed as A, openBlock as o, createElementBlock as i, createElementVNode as e, Fragment as c, createTextVNode as u, toDisplayString as n, createCommentVNode as y, normalizeClass as _, createVNode as F, unref as r, renderList as B, createBlock as D } from "vue";
|
|
2
2
|
import { formatTime as R, timeAgo as z } from "adonisjs-server-stats/core";
|
|
3
|
-
import { u as L } from "./index-
|
|
3
|
+
import { u as L } from "./index-CptF6Qbp.js";
|
|
4
4
|
import { u as M } from "./useResizableTable-BoivAevK.js";
|
|
5
5
|
import { _ as U } from "./FilterBar.vue_vue_type_script_setup_true_lang-ClJ37hhT.js";
|
|
6
6
|
import { _ as q } from "./PaginationControls.vue_vue_type_script_setup_true_lang-CuN7g_8Z.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineComponent as E, inject as i, ref as p, computed as P, openBlock as s, createElementBlock as l, createVNode as v, unref as a, Fragment as h, createElementVNode as e, renderList as T, toDisplayString as c, createBlock as C, createCommentVNode as D } from "vue";
|
|
2
2
|
import { formatTime as S, timeAgo as V } from "adonisjs-server-stats/core";
|
|
3
|
-
import { u as $ } from "./index-
|
|
3
|
+
import { u as $ } from "./index-CptF6Qbp.js";
|
|
4
4
|
import { u as A } from "./useResizableTable-BoivAevK.js";
|
|
5
5
|
import { _ as B } from "./FilterBar.vue_vue_type_script_setup_true_lang-ClJ37hhT.js";
|
|
6
6
|
import { _ as R } from "./PaginationControls.vue_vue_type_script_setup_true_lang-CuN7g_8Z.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { defineComponent as L, inject as h, ref as p, computed as g, openBlock as o, createElementBlock as d, createElementVNode as s, toDisplayString as n, createCommentVNode as v, createVNode as k, unref as a, withCtx as z, Fragment as _, renderList as x, normalizeClass as w, withModifiers as K, createBlock as M } from "vue";
|
|
2
2
|
import { extractJobs as O, extractJobStats as Q, JOB_STATUS_FILTERS as W, getJobStatusBadgeColor as q, formatDuration as G, formatTime as H, timeAgo as X } from "adonisjs-server-stats/core";
|
|
3
|
-
import { u as Y } from "./index-
|
|
3
|
+
import { u as Y } from "./index-CptF6Qbp.js";
|
|
4
4
|
import { u as Z } from "./useResizableTable-BoivAevK.js";
|
|
5
5
|
import { _ as I } from "./JsonViewer.vue_vue_type_script_setup_true_lang-Bid05zpm.js";
|
|
6
6
|
import { _ as j } from "./FilterBar.vue_vue_type_script_setup_true_lang-ClJ37hhT.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineComponent as ie, inject as C, ref as u, computed as B, openBlock as a, createElementBlock as o, createVNode as O, unref as s, withCtx as ue, createElementVNode as n, Fragment as q, renderList as x, normalizeClass as $, toDisplayString as i, withKeys as V, createCommentVNode as _, createStaticVNode as re, createTextVNode as w, withModifiers as U, createBlock as de } from "vue";
|
|
2
2
|
import { LOG_LEVELS as ce, getStructuredData as m, getLogLevelCssClass as ve, resolveLogLevel as W, resolveLogTimestamp as F, formatTime as pe, timeAgo as he, resolveLogRequestId as g, resolveLogMessage as _e } from "adonisjs-server-stats/core";
|
|
3
3
|
import { _ as fe } from "./JsonViewer.vue_vue_type_script_setup_true_lang-Bid05zpm.js";
|
|
4
|
-
import { u as me } from "./index-
|
|
4
|
+
import { u as me } from "./index-CptF6Qbp.js";
|
|
5
5
|
import { _ as ge } from "./FilterBar.vue_vue_type_script_setup_true_lang-ClJ37hhT.js";
|
|
6
6
|
import { _ as ye } from "./PaginationControls.vue_vue_type_script_setup_true_lang-CuN7g_8Z.js";
|
|
7
7
|
const ke = { class: "ss-dash-log-filters" }, be = ["onClick"], Ce = ["value"], qe = { class: "ss-dash-structured-search" }, $e = ["value"], Fe = ["value"], Le = ["value"], Se = {
|