@singhak/nodeui-core 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +111 -111
- package/dist/index.cjs +55 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +31 -2
- package/dist/index.d.ts +31 -2
- package/dist/index.mjs +53 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/static/assets/index-Cu0xtlkD.js +11 -0
- package/static/assets/index-DlUszrsn.css +1 -0
- package/static/index.html +14 -13
- package/static/assets/index-CJCpPtrr.js +0 -11
- package/static/assets/index-ChbLMdDF.css +0 -1
package/dist/index.d.mts
CHANGED
|
@@ -155,9 +155,37 @@ interface RequestEntry {
|
|
|
155
155
|
timestampMs: number;
|
|
156
156
|
ip: string;
|
|
157
157
|
}
|
|
158
|
+
interface RouteStat {
|
|
159
|
+
method: string;
|
|
160
|
+
path: string;
|
|
161
|
+
count: number;
|
|
162
|
+
avgMs: number;
|
|
163
|
+
p95Ms: number;
|
|
164
|
+
errors: number;
|
|
165
|
+
}
|
|
166
|
+
interface RequestsSummary {
|
|
167
|
+
/** Requests currently held in the ring buffer. */
|
|
168
|
+
count: number;
|
|
169
|
+
errors: number;
|
|
170
|
+
/** `errors / count` in 0..1 (5xx only). */
|
|
171
|
+
errorRate: number;
|
|
172
|
+
avgMs: number;
|
|
173
|
+
p50Ms: number;
|
|
174
|
+
p95Ms: number;
|
|
175
|
+
p99Ms: number;
|
|
176
|
+
byStatus: {
|
|
177
|
+
'2xx': number;
|
|
178
|
+
'3xx': number;
|
|
179
|
+
'4xx': number;
|
|
180
|
+
'5xx': number;
|
|
181
|
+
};
|
|
182
|
+
/** Busiest/slowest routes, slowest p95 first (at most 8). */
|
|
183
|
+
routes: RouteStat[];
|
|
184
|
+
}
|
|
158
185
|
interface RequestsData {
|
|
159
186
|
total: number;
|
|
160
187
|
entries: RequestEntry[];
|
|
188
|
+
summary: RequestsSummary;
|
|
161
189
|
}
|
|
162
190
|
interface EnvEntry {
|
|
163
191
|
key: string;
|
|
@@ -236,7 +264,7 @@ interface ConfigData {
|
|
|
236
264
|
enabled: boolean;
|
|
237
265
|
pattern: string;
|
|
238
266
|
};
|
|
239
|
-
|
|
267
|
+
locked: boolean;
|
|
240
268
|
/** Plugin panel ids and titles, in registration order. */
|
|
241
269
|
plugins: Array<{
|
|
242
270
|
id: PanelId;
|
|
@@ -534,6 +562,7 @@ declare class HeapSnapshotProvider implements NodeUIProvider<HeapSnapshotPanelDa
|
|
|
534
562
|
takeSnapshot(ctx: ProviderContext): Promise<ProviderResult<HeapSnapshotData>>;
|
|
535
563
|
}
|
|
536
564
|
|
|
565
|
+
declare function summarizeRequests(entries: readonly RequestEntry[]): RequestsSummary;
|
|
537
566
|
/** Fixed-size ring buffer of recent HTTP requests, recorded via middleware hook. */
|
|
538
567
|
declare class RequestsProvider implements NodeUIProvider<RequestsData> {
|
|
539
568
|
readonly id: "requests";
|
|
@@ -737,4 +766,4 @@ type NodeUIMiddleware = (req: IncomingMessage, res: ServerResponse, next: () =>
|
|
|
737
766
|
declare function serializeEnvelope<T>(envelope: ApiEnvelope<T>, mask?: boolean): string;
|
|
738
767
|
declare function createNodeUI(options?: NodeUIOptions): NodeUIServer;
|
|
739
768
|
|
|
740
|
-
export { AUTH_COOKIE, type ActivationDecision, type ApiEnvelope, type BuiltInPanelId, type ConfigData, type ConfirmIssued, ConfirmationStore, type CpuClock, type CpuData, CpuProvider, type CpuUsageSnapshot, DEFAULT_LOG_SIZE, type EnvData, type EnvEntry, EnvProvider, type EventLoopClock, EventLoopLagProvider, type EventLoopSample, type GuardOptions, type GuardResult, type HealthCheck, type HealthCheckResult, type HealthData, HealthProvider, type HeapSnapshotData, type HeapSnapshotPanelData, HeapSnapshotProvider, type LogEntry, type LogLevel, type LogsData, LogsProvider, type MemoryData, MemoryProvider, type MetricsBucket, type MetricsData, MetricsProvider, type NodeUIConfig, type NodeUIMiddleware, type NodeUIOptions, type NodeUIProvider, type NodeUIServer, type OutgoingData, OutgoingProvider, type OutgoingRequestEntry, type PanelId, type ProviderContext, type ProviderError, ProviderRegistry, type ProviderResult, type RequestEntry, type RequestsData, RequestsProvider, RingBuffer, type RouteEntry, type RoutesData, RoutesProvider, SECRET_KEY_PATTERN, SECRET_MASKED, Sampler, type SamplerOptions, type SseStream, type StartupData, type StartupMark, StartupTracker, type StaticAsset, createGuard, createNodeUI, extractRoutes, hostnameFromHostHeader, interceptConsole, interceptOutgoing, isLoopbackAddress, isLoopbackHostname, maskSecretText, maskSecrets, matchesAddress, resolveActivation, resolveStaticAsset, serializeEnvelope, startSse };
|
|
769
|
+
export { AUTH_COOKIE, type ActivationDecision, type ApiEnvelope, type BuiltInPanelId, type ConfigData, type ConfirmIssued, ConfirmationStore, type CpuClock, type CpuData, CpuProvider, type CpuUsageSnapshot, DEFAULT_LOG_SIZE, type EnvData, type EnvEntry, EnvProvider, type EventLoopClock, EventLoopLagProvider, type EventLoopSample, type GuardOptions, type GuardResult, type HealthCheck, type HealthCheckResult, type HealthData, HealthProvider, type HeapSnapshotData, type HeapSnapshotPanelData, HeapSnapshotProvider, type LogEntry, type LogLevel, type LogsData, LogsProvider, type MemoryData, MemoryProvider, type MetricsBucket, type MetricsData, MetricsProvider, type NodeUIConfig, type NodeUIMiddleware, type NodeUIOptions, type NodeUIProvider, type NodeUIServer, type OutgoingData, OutgoingProvider, type OutgoingRequestEntry, type PanelId, type ProviderContext, type ProviderError, ProviderRegistry, type ProviderResult, type RequestEntry, type RequestsData, RequestsProvider, type RequestsSummary, RingBuffer, type RouteEntry, type RouteStat, type RoutesData, RoutesProvider, SECRET_KEY_PATTERN, SECRET_MASKED, Sampler, type SamplerOptions, type SseStream, type StartupData, type StartupMark, StartupTracker, type StaticAsset, createGuard, createNodeUI, extractRoutes, hostnameFromHostHeader, interceptConsole, interceptOutgoing, isLoopbackAddress, isLoopbackHostname, maskSecretText, maskSecrets, matchesAddress, resolveActivation, resolveStaticAsset, serializeEnvelope, startSse, summarizeRequests };
|
package/dist/index.d.ts
CHANGED
|
@@ -155,9 +155,37 @@ interface RequestEntry {
|
|
|
155
155
|
timestampMs: number;
|
|
156
156
|
ip: string;
|
|
157
157
|
}
|
|
158
|
+
interface RouteStat {
|
|
159
|
+
method: string;
|
|
160
|
+
path: string;
|
|
161
|
+
count: number;
|
|
162
|
+
avgMs: number;
|
|
163
|
+
p95Ms: number;
|
|
164
|
+
errors: number;
|
|
165
|
+
}
|
|
166
|
+
interface RequestsSummary {
|
|
167
|
+
/** Requests currently held in the ring buffer. */
|
|
168
|
+
count: number;
|
|
169
|
+
errors: number;
|
|
170
|
+
/** `errors / count` in 0..1 (5xx only). */
|
|
171
|
+
errorRate: number;
|
|
172
|
+
avgMs: number;
|
|
173
|
+
p50Ms: number;
|
|
174
|
+
p95Ms: number;
|
|
175
|
+
p99Ms: number;
|
|
176
|
+
byStatus: {
|
|
177
|
+
'2xx': number;
|
|
178
|
+
'3xx': number;
|
|
179
|
+
'4xx': number;
|
|
180
|
+
'5xx': number;
|
|
181
|
+
};
|
|
182
|
+
/** Busiest/slowest routes, slowest p95 first (at most 8). */
|
|
183
|
+
routes: RouteStat[];
|
|
184
|
+
}
|
|
158
185
|
interface RequestsData {
|
|
159
186
|
total: number;
|
|
160
187
|
entries: RequestEntry[];
|
|
188
|
+
summary: RequestsSummary;
|
|
161
189
|
}
|
|
162
190
|
interface EnvEntry {
|
|
163
191
|
key: string;
|
|
@@ -236,7 +264,7 @@ interface ConfigData {
|
|
|
236
264
|
enabled: boolean;
|
|
237
265
|
pattern: string;
|
|
238
266
|
};
|
|
239
|
-
|
|
267
|
+
locked: boolean;
|
|
240
268
|
/** Plugin panel ids and titles, in registration order. */
|
|
241
269
|
plugins: Array<{
|
|
242
270
|
id: PanelId;
|
|
@@ -534,6 +562,7 @@ declare class HeapSnapshotProvider implements NodeUIProvider<HeapSnapshotPanelDa
|
|
|
534
562
|
takeSnapshot(ctx: ProviderContext): Promise<ProviderResult<HeapSnapshotData>>;
|
|
535
563
|
}
|
|
536
564
|
|
|
565
|
+
declare function summarizeRequests(entries: readonly RequestEntry[]): RequestsSummary;
|
|
537
566
|
/** Fixed-size ring buffer of recent HTTP requests, recorded via middleware hook. */
|
|
538
567
|
declare class RequestsProvider implements NodeUIProvider<RequestsData> {
|
|
539
568
|
readonly id: "requests";
|
|
@@ -737,4 +766,4 @@ type NodeUIMiddleware = (req: IncomingMessage, res: ServerResponse, next: () =>
|
|
|
737
766
|
declare function serializeEnvelope<T>(envelope: ApiEnvelope<T>, mask?: boolean): string;
|
|
738
767
|
declare function createNodeUI(options?: NodeUIOptions): NodeUIServer;
|
|
739
768
|
|
|
740
|
-
export { AUTH_COOKIE, type ActivationDecision, type ApiEnvelope, type BuiltInPanelId, type ConfigData, type ConfirmIssued, ConfirmationStore, type CpuClock, type CpuData, CpuProvider, type CpuUsageSnapshot, DEFAULT_LOG_SIZE, type EnvData, type EnvEntry, EnvProvider, type EventLoopClock, EventLoopLagProvider, type EventLoopSample, type GuardOptions, type GuardResult, type HealthCheck, type HealthCheckResult, type HealthData, HealthProvider, type HeapSnapshotData, type HeapSnapshotPanelData, HeapSnapshotProvider, type LogEntry, type LogLevel, type LogsData, LogsProvider, type MemoryData, MemoryProvider, type MetricsBucket, type MetricsData, MetricsProvider, type NodeUIConfig, type NodeUIMiddleware, type NodeUIOptions, type NodeUIProvider, type NodeUIServer, type OutgoingData, OutgoingProvider, type OutgoingRequestEntry, type PanelId, type ProviderContext, type ProviderError, ProviderRegistry, type ProviderResult, type RequestEntry, type RequestsData, RequestsProvider, RingBuffer, type RouteEntry, type RoutesData, RoutesProvider, SECRET_KEY_PATTERN, SECRET_MASKED, Sampler, type SamplerOptions, type SseStream, type StartupData, type StartupMark, StartupTracker, type StaticAsset, createGuard, createNodeUI, extractRoutes, hostnameFromHostHeader, interceptConsole, interceptOutgoing, isLoopbackAddress, isLoopbackHostname, maskSecretText, maskSecrets, matchesAddress, resolveActivation, resolveStaticAsset, serializeEnvelope, startSse };
|
|
769
|
+
export { AUTH_COOKIE, type ActivationDecision, type ApiEnvelope, type BuiltInPanelId, type ConfigData, type ConfirmIssued, ConfirmationStore, type CpuClock, type CpuData, CpuProvider, type CpuUsageSnapshot, DEFAULT_LOG_SIZE, type EnvData, type EnvEntry, EnvProvider, type EventLoopClock, EventLoopLagProvider, type EventLoopSample, type GuardOptions, type GuardResult, type HealthCheck, type HealthCheckResult, type HealthData, HealthProvider, type HeapSnapshotData, type HeapSnapshotPanelData, HeapSnapshotProvider, type LogEntry, type LogLevel, type LogsData, LogsProvider, type MemoryData, MemoryProvider, type MetricsBucket, type MetricsData, MetricsProvider, type NodeUIConfig, type NodeUIMiddleware, type NodeUIOptions, type NodeUIProvider, type NodeUIServer, type OutgoingData, OutgoingProvider, type OutgoingRequestEntry, type PanelId, type ProviderContext, type ProviderError, ProviderRegistry, type ProviderResult, type RequestEntry, type RequestsData, RequestsProvider, type RequestsSummary, RingBuffer, type RouteEntry, type RouteStat, type RoutesData, RoutesProvider, SECRET_KEY_PATTERN, SECRET_MASKED, Sampler, type SamplerOptions, type SseStream, type StartupData, type StartupMark, StartupTracker, type StaticAsset, createGuard, createNodeUI, extractRoutes, hostnameFromHostHeader, interceptConsole, interceptOutgoing, isLoopbackAddress, isLoopbackHostname, maskSecretText, maskSecrets, matchesAddress, resolveActivation, resolveStaticAsset, serializeEnvelope, startSse, summarizeRequests };
|
package/dist/index.mjs
CHANGED
|
@@ -915,6 +915,54 @@ var HeapSnapshotProvider = class {
|
|
|
915
915
|
|
|
916
916
|
// src/providers/requests.ts
|
|
917
917
|
var RESPONSE_PAGE_SIZE2 = 100;
|
|
918
|
+
var MAX_ROUTE_STATS = 8;
|
|
919
|
+
function percentile(sorted, p) {
|
|
920
|
+
if (sorted.length === 0) return 0;
|
|
921
|
+
const index = Math.min(sorted.length - 1, Math.max(0, Math.ceil(p * sorted.length) - 1));
|
|
922
|
+
return sorted[index] ?? 0;
|
|
923
|
+
}
|
|
924
|
+
function routeKey(path2) {
|
|
925
|
+
return path2.split("/").map(
|
|
926
|
+
(seg) => /^\d+$/.test(seg) || /^[0-9a-f]{8}-[0-9a-f-]{27}$/i.test(seg) || /^[0-9a-f]{24}$/i.test(seg) ? ":id" : seg
|
|
927
|
+
).join("/");
|
|
928
|
+
}
|
|
929
|
+
function summarizeRequests(entries) {
|
|
930
|
+
const durations = entries.map((e) => e.durationMs).sort((a, b) => a - b);
|
|
931
|
+
const byStatus = { "2xx": 0, "3xx": 0, "4xx": 0, "5xx": 0 };
|
|
932
|
+
const groups = /* @__PURE__ */ new Map();
|
|
933
|
+
for (const e of entries) {
|
|
934
|
+
const bucket = `${Math.floor(e.status / 100)}xx`;
|
|
935
|
+
if (bucket in byStatus) byStatus[bucket] += 1;
|
|
936
|
+
const path2 = routeKey(e.path);
|
|
937
|
+
const key = `${e.method} ${path2}`;
|
|
938
|
+
const group = groups.get(key) ?? { method: e.method, path: path2, ms: [], errors: 0 };
|
|
939
|
+
group.ms.push(e.durationMs);
|
|
940
|
+
if (e.status >= 500) group.errors += 1;
|
|
941
|
+
groups.set(key, group);
|
|
942
|
+
}
|
|
943
|
+
const routes = [...groups.values()].map((g) => {
|
|
944
|
+
const sorted = [...g.ms].sort((a, b) => a - b);
|
|
945
|
+
return {
|
|
946
|
+
method: g.method,
|
|
947
|
+
path: g.path,
|
|
948
|
+
count: g.ms.length,
|
|
949
|
+
avgMs: g.ms.reduce((a, b) => a + b, 0) / g.ms.length,
|
|
950
|
+
p95Ms: percentile(sorted, 0.95),
|
|
951
|
+
errors: g.errors
|
|
952
|
+
};
|
|
953
|
+
}).sort((a, b) => b.p95Ms - a.p95Ms).slice(0, MAX_ROUTE_STATS);
|
|
954
|
+
return {
|
|
955
|
+
count: entries.length,
|
|
956
|
+
errors: byStatus["5xx"],
|
|
957
|
+
errorRate: entries.length === 0 ? 0 : byStatus["5xx"] / entries.length,
|
|
958
|
+
avgMs: durations.length === 0 ? 0 : durations.reduce((a, b) => a + b, 0) / durations.length,
|
|
959
|
+
p50Ms: percentile(durations, 0.5),
|
|
960
|
+
p95Ms: percentile(durations, 0.95),
|
|
961
|
+
p99Ms: percentile(durations, 0.99),
|
|
962
|
+
byStatus,
|
|
963
|
+
routes
|
|
964
|
+
};
|
|
965
|
+
}
|
|
918
966
|
var RequestsProvider = class {
|
|
919
967
|
id = "requests";
|
|
920
968
|
buffer;
|
|
@@ -931,7 +979,8 @@ var RequestsProvider = class {
|
|
|
931
979
|
}
|
|
932
980
|
get() {
|
|
933
981
|
const entries = this.buffer.slice(Math.max(0, this.buffer.length - RESPONSE_PAGE_SIZE2));
|
|
934
|
-
|
|
982
|
+
const summary = summarizeRequests(this.buffer.toArray());
|
|
983
|
+
return { ok: true, data: { total: this.buffer.length, entries, summary } };
|
|
935
984
|
}
|
|
936
985
|
};
|
|
937
986
|
|
|
@@ -1453,7 +1502,7 @@ function createNodeUI(options = {}) {
|
|
|
1453
1502
|
pollIntervalMs: config.pollIntervalMs,
|
|
1454
1503
|
panels: registry.ids(),
|
|
1455
1504
|
masking: { enabled: config.maskSecrets, pattern: SECRET_KEY_PATTERN.source },
|
|
1456
|
-
|
|
1505
|
+
locked: config.authRequired,
|
|
1457
1506
|
plugins: pluginMeta
|
|
1458
1507
|
};
|
|
1459
1508
|
}
|
|
@@ -1722,6 +1771,7 @@ export {
|
|
|
1722
1771
|
resolveActivation,
|
|
1723
1772
|
resolveStaticAsset,
|
|
1724
1773
|
serializeEnvelope,
|
|
1725
|
-
startSse
|
|
1774
|
+
startSse,
|
|
1775
|
+
summarizeRequests
|
|
1726
1776
|
};
|
|
1727
1777
|
//# sourceMappingURL=index.mjs.map
|