metrickit 0.1.2

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 (50) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/LICENSE +21 -0
  3. package/README.md +379 -0
  4. package/dist/cache-redis.d.ts +10 -0
  5. package/dist/cache-redis.js +24 -0
  6. package/dist/cache-utils.d.ts +5 -0
  7. package/dist/cache.d.ts +18 -0
  8. package/dist/catalog.d.ts +12 -0
  9. package/dist/define-metric.d.ts +37 -0
  10. package/dist/engine.d.ts +200 -0
  11. package/dist/filters/default-metadata.d.ts +28 -0
  12. package/dist/filters/index.d.ts +3 -0
  13. package/dist/filters/parse.d.ts +7 -0
  14. package/dist/filters/types.d.ts +19 -0
  15. package/dist/frontend/catalog.d.ts +24 -0
  16. package/dist/frontend/dashboard.d.ts +12 -0
  17. package/dist/frontend/format.d.ts +10 -0
  18. package/dist/frontend/index.d.ts +10 -0
  19. package/dist/frontend/markers.d.ts +19 -0
  20. package/dist/frontend/renderers.d.ts +14 -0
  21. package/dist/frontend/requests.d.ts +17 -0
  22. package/dist/frontend/stream-state.d.ts +14 -0
  23. package/dist/frontend/time.d.ts +5 -0
  24. package/dist/frontend/transport.d.ts +19 -0
  25. package/dist/frontend/types.d.ts +108 -0
  26. package/dist/frontend.d.ts +1 -0
  27. package/dist/frontend.js +752 -0
  28. package/dist/helpers/clickhouse.d.ts +27 -0
  29. package/dist/helpers/distribution.d.ts +15 -0
  30. package/dist/helpers/index.d.ts +6 -0
  31. package/dist/helpers/metric-type.d.ts +21 -0
  32. package/dist/helpers/pivot.d.ts +15 -0
  33. package/dist/helpers/prisma.d.ts +20 -0
  34. package/dist/helpers/timeseries.d.ts +6 -0
  35. package/dist/helpers.d.ts +1 -0
  36. package/dist/helpers.js +668 -0
  37. package/dist/index.d.ts +11 -0
  38. package/dist/index.js +1322 -0
  39. package/dist/orpc.d.ts +36 -0
  40. package/dist/orpc.js +1157 -0
  41. package/dist/registry.d.ts +269 -0
  42. package/dist/run-metrics.d.ts +14 -0
  43. package/dist/schemas/index.d.ts +4 -0
  44. package/dist/schemas/inputs.d.ts +19 -0
  45. package/dist/schemas/metric-type.d.ts +7 -0
  46. package/dist/schemas/output.d.ts +842 -0
  47. package/dist/schemas/time.d.ts +24 -0
  48. package/dist/time.d.ts +6 -0
  49. package/dist/type-guards.d.ts +7 -0
  50. package/package.json +91 -0
@@ -0,0 +1,200 @@
1
+ import type { z } from 'zod';
2
+ import type { CacheAdapter } from './cache.ts';
3
+ import type { MetricCatalogMetadata } from './catalog.ts';
4
+ import type { AnyMetricDefinition, MetricDefinition, MetricDefinitionInput } from './define-metric.ts';
5
+ import type { BaseFilters, OutputForKind, TimeSeriesOutput } from './schemas/index.ts';
6
+ import { OutputSchemaMap } from './schemas/index.ts';
7
+ export type MetricKindSchemaMap = Record<string, z.ZodTypeAny>;
8
+ type BuiltinMetricKindSchemaMap = typeof OutputSchemaMap;
9
+ type EngineMetricKindSchemaMap<TCustomKinds extends MetricKindSchemaMap> = BuiltinMetricKindSchemaMap & TCustomKinds;
10
+ type OutputForSchema<TSchema extends z.ZodTypeAny> = z.output<TSchema>;
11
+ type EmptyMetricKindSchemaMap = Record<string, never>;
12
+ export interface MetricsEngineConfig<TBaseFilters extends BaseFilters, TCustomKinds extends MetricKindSchemaMap = EmptyMetricKindSchemaMap> {
13
+ baseFilters?: z.ZodType<TBaseFilters>;
14
+ cache?: CacheAdapter;
15
+ customKinds?: TCustomKinds;
16
+ }
17
+ export declare function createMetricsEngine<TContext, TBaseFilters extends BaseFilters = BaseFilters, TCustomKinds extends MetricKindSchemaMap = EmptyMetricKindSchemaMap>(config?: MetricsEngineConfig<TBaseFilters, TCustomKinds>): {
18
+ cache: CacheAdapter;
19
+ baseFilterSchema: z.ZodType<TBaseFilters, unknown, z.core.$ZodTypeInternals<TBaseFilters, unknown>>;
20
+ kindSchemas: EngineMetricKindSchemaMap<TCustomKinds>;
21
+ defineMetric: <TKey extends string, TKind extends "kpi" | "timeseries" | "distribution" | "table" | "leaderboard" | "pivot" | Extract<keyof TCustomKinds, string>, TFilters extends TBaseFilters, TCatalog extends MetricCatalogMetadata | undefined = MetricCatalogMetadata | undefined>(kind: TKind, def: MetricDefinitionInput<TKey, TKind, TFilters, OutputForSchema<EngineMetricKindSchemaMap<TCustomKinds>[TKind]>, TContext, TCatalog>) => MetricDefinition<TKey, TKind, TFilters, OutputForSchema<EngineMetricKindSchemaMap<TCustomKinds>[TKind]>, TContext, TCatalog>;
22
+ defineKpiMetric: <TKey extends string, TFilters extends TBaseFilters, TCatalog extends MetricCatalogMetadata | undefined = MetricCatalogMetadata | undefined>(def: MetricDefinitionInput<TKey, "kpi", TFilters, OutputForKind<"kpi">, TContext, TCatalog>) => MetricDefinition<TKey, "kpi", TFilters, OutputForKind<"kpi">, TContext, TCatalog>;
23
+ defineTimeSeriesMetric: <TKey extends string, TFilters extends TBaseFilters, TCatalog extends MetricCatalogMetadata | undefined = MetricCatalogMetadata | undefined>(def: MetricDefinitionInput<TKey, "timeseries", TFilters, TimeSeriesOutput, TContext, TCatalog>) => MetricDefinition<TKey, "timeseries", TFilters, TimeSeriesOutput, TContext, TCatalog>;
24
+ defineDistributionMetric: <TKey extends string, TFilters extends TBaseFilters, TCatalog extends MetricCatalogMetadata | undefined = MetricCatalogMetadata | undefined>(def: MetricDefinitionInput<TKey, "distribution", TFilters, OutputForKind<"distribution">, TContext, TCatalog>) => MetricDefinition<TKey, "distribution", TFilters, OutputForKind<"distribution">, TContext, TCatalog>;
25
+ defineTableMetric: <TKey extends string, TFilters extends TBaseFilters, TCatalog extends MetricCatalogMetadata | undefined = MetricCatalogMetadata | undefined>(def: MetricDefinitionInput<TKey, "table", TFilters, OutputForKind<"table">, TContext, TCatalog>) => MetricDefinition<TKey, "table", TFilters, OutputForKind<"table">, TContext, TCatalog>;
26
+ defineLeaderboardMetric: <TKey extends string, TFilters extends TBaseFilters, TCatalog extends MetricCatalogMetadata | undefined = MetricCatalogMetadata | undefined>(def: MetricDefinitionInput<TKey, "leaderboard", TFilters, OutputForKind<"leaderboard">, TContext, TCatalog>) => MetricDefinition<TKey, "leaderboard", TFilters, OutputForKind<"leaderboard">, TContext, TCatalog>;
27
+ definePivotMetric: <TKey extends string, TFilters extends TBaseFilters, TCatalog extends MetricCatalogMetadata | undefined = MetricCatalogMetadata | undefined>(def: MetricDefinitionInput<TKey, "pivot", TFilters, OutputForKind<"pivot">, TContext, TCatalog>) => MetricDefinition<TKey, "pivot", TFilters, OutputForKind<"pivot">, TContext, TCatalog>;
28
+ createRegistry: <const TMetrics extends readonly AnyMetricDefinition[]>(metrics: TMetrics) => {
29
+ readonly metrics: TMetrics;
30
+ readonly baseFilterSchema: z.ZodType<TBaseFilters, unknown, z.core.$ZodTypeInternals<TBaseFilters, unknown>>;
31
+ readonly kindSchemas: {
32
+ readonly kpi: z.ZodObject<{
33
+ kind: z.ZodLiteral<"kpi">;
34
+ value: z.ZodNumber;
35
+ label: z.ZodOptional<z.ZodString>;
36
+ unit: z.ZodOptional<z.ZodEnum<{
37
+ DKK: "DKK";
38
+ EUR: "EUR";
39
+ USD: "USD";
40
+ GBP: "GBP";
41
+ SEK: "SEK";
42
+ NOK: "NOK";
43
+ PERCENTAGE: "PERCENTAGE";
44
+ }>>;
45
+ prefix: z.ZodOptional<z.ZodString>;
46
+ suffix: z.ZodOptional<z.ZodString>;
47
+ trend: z.ZodOptional<z.ZodEnum<{
48
+ up: "up";
49
+ down: "down";
50
+ flat: "flat";
51
+ }>>;
52
+ }, z.core.$strip>;
53
+ readonly timeseries: z.ZodObject<{
54
+ kind: z.ZodLiteral<"timeseries">;
55
+ granularity: z.ZodEnum<{
56
+ hour: "hour";
57
+ day: "day";
58
+ week: "week";
59
+ month: "month";
60
+ quarter: "quarter";
61
+ year: "year";
62
+ }>;
63
+ series: z.ZodArray<z.ZodObject<{
64
+ key: z.ZodString;
65
+ label: z.ZodOptional<z.ZodString>;
66
+ points: z.ZodArray<z.ZodObject<{
67
+ ts: z.ZodDate;
68
+ value: z.ZodNumber;
69
+ label: z.ZodOptional<z.ZodString>;
70
+ }, z.core.$strip>>;
71
+ chartType: z.ZodOptional<z.ZodEnum<{
72
+ line: "line";
73
+ bar: "bar";
74
+ }>>;
75
+ axis: z.ZodOptional<z.ZodEnum<{
76
+ left: "left";
77
+ right: "right";
78
+ }>>;
79
+ meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
80
+ }, z.core.$strip>>;
81
+ }, z.core.$strip>;
82
+ readonly distribution: z.ZodObject<{
83
+ kind: z.ZodLiteral<"distribution">;
84
+ total: z.ZodNumber;
85
+ segments: z.ZodArray<z.ZodObject<{
86
+ key: z.ZodString;
87
+ label: z.ZodString;
88
+ value: z.ZodNumber;
89
+ percent: z.ZodOptional<z.ZodNumber>;
90
+ }, z.core.$strip>>;
91
+ chartType: z.ZodOptional<z.ZodEnum<{
92
+ bar: "bar";
93
+ donut: "donut";
94
+ pie: "pie";
95
+ funnel: "funnel";
96
+ }>>;
97
+ }, z.core.$strip>;
98
+ readonly table: z.ZodObject<{
99
+ kind: z.ZodLiteral<"table">;
100
+ columns: z.ZodArray<z.ZodObject<{
101
+ key: z.ZodString;
102
+ label: z.ZodString;
103
+ type: z.ZodOptional<z.ZodEnum<{
104
+ string: "string";
105
+ number: "number";
106
+ boolean: "boolean";
107
+ date: "date";
108
+ }>>;
109
+ nullable: z.ZodOptional<z.ZodBoolean>;
110
+ }, z.core.$strip>>;
111
+ rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
112
+ total: z.ZodOptional<z.ZodNumber>;
113
+ }, z.core.$strip>;
114
+ readonly leaderboard: z.ZodObject<{
115
+ kind: z.ZodLiteral<"leaderboard">;
116
+ items: z.ZodArray<z.ZodObject<{
117
+ rank: z.ZodNumber;
118
+ id: z.ZodString;
119
+ label: z.ZodString;
120
+ value: z.ZodNumber;
121
+ meta: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
122
+ }, z.core.$strip>>;
123
+ total: z.ZodOptional<z.ZodNumber>;
124
+ }, z.core.$strip>;
125
+ readonly pivot: z.ZodObject<{
126
+ kind: z.ZodLiteral<"pivot">;
127
+ rowDimension: z.ZodObject<{
128
+ key: z.ZodString;
129
+ label: z.ZodString;
130
+ }, z.core.$strip>;
131
+ columnDimension: z.ZodObject<{
132
+ key: z.ZodString;
133
+ label: z.ZodString;
134
+ }, z.core.$strip>;
135
+ rows: z.ZodArray<z.ZodString>;
136
+ columns: z.ZodArray<z.ZodString>;
137
+ values: z.ZodArray<z.ZodArray<z.ZodNumber>>;
138
+ cellTooltips: z.ZodOptional<z.ZodArray<z.ZodArray<z.ZodString>>>;
139
+ totals: z.ZodOptional<z.ZodObject<{
140
+ rowTotals: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
141
+ columnTotals: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
142
+ grandTotal: z.ZodOptional<z.ZodNumber>;
143
+ }, z.core.$strip>>;
144
+ }, z.core.$strip>;
145
+ } & TCustomKinds;
146
+ readonly metricKeys: [TMetrics[number]["key"], ...TMetrics[number]["key"][]];
147
+ readonly MetricKeySchema: z.ZodEnum<{ [k_1 in TMetrics[number]["key"]]: k_1; } extends infer T ? { [k in keyof T]: T[k]; } : never>;
148
+ readonly MetricRequestSchema: z.ZodObject<{
149
+ key: z.ZodEnum<{ [k_1 in TMetrics[number]["key"]]: k_1; } extends infer T_1 ? { [k in keyof T_1]: T_1[k]; } : never>;
150
+ requestKey: z.ZodOptional<z.ZodString>;
151
+ filters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
152
+ }, z.core.$strip>;
153
+ readonly MetricsRequestSchema: z.ZodObject<{
154
+ metrics: z.ZodArray<z.ZodObject<{
155
+ key: z.ZodEnum<{ [k_1 in TMetrics[number]["key"]]: k_1; } extends infer T_2 ? { [k in keyof T_2]: T_2[k]; } : never>;
156
+ requestKey: z.ZodOptional<z.ZodString>;
157
+ filters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
158
+ }, z.core.$strip>>;
159
+ granularity: z.ZodOptional<z.ZodEnum<{
160
+ hour: "hour";
161
+ day: "day";
162
+ week: "week";
163
+ month: "month";
164
+ quarter: "quarter";
165
+ year: "year";
166
+ }>>;
167
+ from: z.ZodOptional<z.ZodDate>;
168
+ to: z.ZodOptional<z.ZodDate>;
169
+ compareToPrevious: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
170
+ disableCache: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
171
+ }, z.core.$strip>;
172
+ readonly metricsByKey: Record<TMetrics[number]["key"], AnyMetricDefinition>;
173
+ readonly getMetricByKey: {
174
+ <K extends TMetrics[number]["key"]>(key: K): Extract<TMetrics[number], {
175
+ key: K;
176
+ }>;
177
+ (key: string): AnyMetricDefinition | undefined;
178
+ };
179
+ readonly parseMetricRequestInput: <K extends TMetrics[number]["key"], TRequestKey extends string | undefined = string | undefined>(metricRequest: {
180
+ key: K;
181
+ requestKey?: TRequestKey | undefined;
182
+ filters?: Partial<Omit<z.core.output<Extract<TMetrics[number], {
183
+ key: K;
184
+ }>["filterSchema"]>, "from" | "to">> | undefined;
185
+ }, options?: {
186
+ from?: Date;
187
+ to?: Date;
188
+ } | undefined) => {
189
+ metric: Extract<TMetrics[number], {
190
+ key: K;
191
+ }>;
192
+ requestKey: K;
193
+ filters: z.core.output<Extract<TMetrics[number], {
194
+ key: K;
195
+ }>["filterSchema"]>;
196
+ };
197
+ readonly getOutputSchema: typeof import("./define-metric.ts").getOutputSchema;
198
+ };
199
+ };
200
+ export {};
@@ -0,0 +1,28 @@
1
+ import { type MetricFilterFieldMetadata } from './types.ts';
2
+ export declare const COMMON_METRIC_FILTER_FIELD_METADATA: {
3
+ metric: {
4
+ displayName: string;
5
+ description: string;
6
+ defaultOperator: "is";
7
+ };
8
+ groupBy: {
9
+ displayName: string;
10
+ description: string;
11
+ defaultOperator: "is";
12
+ };
13
+ limit: {
14
+ displayName: string;
15
+ description: string;
16
+ };
17
+ view: {
18
+ displayName: string;
19
+ description: string;
20
+ defaultOperator: "is";
21
+ };
22
+ chartType: {
23
+ displayName: string;
24
+ description: string;
25
+ defaultOperator: "is";
26
+ };
27
+ };
28
+ export declare function mergeMetricFilterFieldMetadata(...metadataEntries: Array<Partial<Record<string, MetricFilterFieldMetadata>> | undefined>): Partial<Record<string, MetricFilterFieldMetadata>>;
@@ -0,0 +1,3 @@
1
+ export * from './types.ts';
2
+ export { parseMetricFilterSchema } from './parse.ts';
3
+ export { COMMON_METRIC_FILTER_FIELD_METADATA, mergeMetricFilterFieldMetadata } from './default-metadata.ts';
@@ -0,0 +1,7 @@
1
+ import type { z } from 'zod';
2
+ import type { FilterFieldDefinition, MetricFilterFieldMetadata } from './types.ts';
3
+ export declare function parseMetricFilterSchema(schema: z.ZodTypeAny, options?: {
4
+ excludeFields?: string[];
5
+ includeFields?: string[];
6
+ fieldMetadata?: Partial<Record<string, MetricFilterFieldMetadata>>;
7
+ }): FilterFieldDefinition[];
@@ -0,0 +1,19 @@
1
+ export type FilterFieldType = 'text' | 'number' | 'numberRange' | 'boolean' | 'date' | 'option' | 'multiOption';
2
+ export type FilterFieldOption = {
3
+ label: string;
4
+ value: string;
5
+ };
6
+ export type FilterOperator = 'contains' | 'does not contain' | 'equals' | 'not equals' | 'greater than' | 'greater than or equal' | 'less than' | 'less than or equal' | 'between' | 'in range' | 'is true' | 'is false' | 'is' | 'is not' | 'is before' | 'is after' | 'is on or before' | 'is on or after' | 'is any of' | 'is none of' | 'includes' | 'excludes' | 'includes any of' | 'includes all of' | 'excludes any of';
7
+ export interface MetricFilterFieldMetadata {
8
+ displayName?: string;
9
+ description?: string;
10
+ type?: FilterFieldType;
11
+ options?: FilterFieldOption[];
12
+ defaultOperator?: FilterOperator;
13
+ }
14
+ export interface FilterFieldDefinition extends MetricFilterFieldMetadata {
15
+ id: string;
16
+ displayName: string;
17
+ type: FilterFieldType;
18
+ }
19
+ export declare function defineMetricFilterFieldMetadata<T extends Record<string, MetricFilterFieldMetadata>>(metadata: T): T;
@@ -0,0 +1,24 @@
1
+ import type { FilterFieldDefinition } from '../filters/types.ts';
2
+ type AvailableMetricLike = {
3
+ key: string;
4
+ kind: string;
5
+ filters: readonly FilterFieldDefinition[];
6
+ };
7
+ export type AvailableMetricMap<TMetrics extends readonly AvailableMetricLike[]> = {
8
+ [K in TMetrics[number]['key']]: Extract<TMetrics[number], {
9
+ key: K;
10
+ }>;
11
+ };
12
+ export declare function createAvailableMetricMap<const TMetrics extends readonly AvailableMetricLike[]>(metrics: TMetrics): AvailableMetricMap<TMetrics>;
13
+ export declare function getAvailableMetric<const TMetrics extends readonly AvailableMetricLike[], K extends TMetrics[number]['key']>(metrics: TMetrics, key: K): Extract<TMetrics[number], {
14
+ key: K;
15
+ }> | undefined;
16
+ export declare function getMetricFilterFields(metric: {
17
+ filters: readonly FilterFieldDefinition[];
18
+ } | undefined): readonly FilterFieldDefinition[];
19
+ export declare function groupAvailableMetricsByKind<const TMetrics extends readonly AvailableMetricLike[]>(metrics: TMetrics): {
20
+ [K in TMetrics[number]['kind']]: Array<Extract<TMetrics[number], {
21
+ kind: K;
22
+ }>>;
23
+ };
24
+ export {};
@@ -0,0 +1,12 @@
1
+ import type { AnyRegistry, InferAvailableMetricKey } from '../registry.ts';
2
+ import type { DashboardControls, DashboardItem, DashboardSlotId, MetricsCustomSlotConfig, MetricsDashboardConfig, MetricsHeadlineConfig, MetricsSpacerConfig, MetricsWidgetConfig, WidgetLayout } from './types.ts';
3
+ export declare function defineMetricsDashboard<R extends AnyRegistry, TRendererId extends string = string, TSlotId extends string = DashboardSlotId, const Items extends readonly DashboardItem<R, TRendererId, TSlotId>[] = readonly DashboardItem<R, TRendererId, TSlotId>[]>(config: MetricsDashboardConfig<R, TRendererId, TSlotId, Items>): MetricsDashboardConfig<R, TRendererId, TSlotId, Items>;
4
+ export declare function defineWidget<R extends AnyRegistry, const K extends InferAvailableMetricKey<R>, TRequestKey extends string | undefined = string | undefined, TRendererId extends string = string>(key: K, config?: Omit<MetricsWidgetConfig<R, K, TRequestKey, TRendererId>, 'key'>): MetricsWidgetConfig<R, K, TRequestKey, TRendererId>;
5
+ export declare function defineWidget<R extends AnyRegistry, const K extends InferAvailableMetricKey<R>, TRequestKey extends string | undefined = string | undefined, TRendererId extends string = string>(config: MetricsWidgetConfig<R, K, TRequestKey, TRendererId>): MetricsWidgetConfig<R, K, TRequestKey, TRendererId>;
6
+ export declare function defineHeadline(title: string, description?: string): MetricsHeadlineConfig;
7
+ export declare function defineSpacer(layout?: WidgetLayout): MetricsSpacerConfig;
8
+ export declare function defineCustomSlot<TSlotId extends string>(slotId: TSlotId, config?: {
9
+ layout?: WidgetLayout;
10
+ props?: Record<string, unknown>;
11
+ }): MetricsCustomSlotConfig<TSlotId>;
12
+ export declare const defaultDashboardControls: DashboardControls;
@@ -0,0 +1,10 @@
1
+ import type { MetricUnit } from '../schemas/output.ts';
2
+ export interface MetricFormatOptions {
3
+ locale?: string;
4
+ defaultCurrency?: string;
5
+ maximumFractionDigits?: number;
6
+ }
7
+ export declare function formatMetricNumber(value: number, options?: MetricFormatOptions): string;
8
+ export declare function formatMetricDecimal(value: number | undefined, options?: MetricFormatOptions): string;
9
+ export declare function formatMetricCurrency(value: number, currency?: string, options?: MetricFormatOptions): string;
10
+ export declare function formatKpiValue(value: number, unit?: MetricUnit, prefix?: string, suffix?: string, options?: MetricFormatOptions): string;
@@ -0,0 +1,10 @@
1
+ export * from './types.ts';
2
+ export * from './requests.ts';
3
+ export * from './transport.ts';
4
+ export * from './stream-state.ts';
5
+ export * from './catalog.ts';
6
+ export * from './format.ts';
7
+ export * from './time.ts';
8
+ export * from './markers.ts';
9
+ export * from './dashboard.ts';
10
+ export * from './renderers.ts';
@@ -0,0 +1,19 @@
1
+ import type { ChartMarker, MarkerCategory } from './types.ts';
2
+ export declare const SEVERITY_COLORS: Record<string, string>;
3
+ export interface LogItemForMarker {
4
+ id: string;
5
+ createdAt: Date | string;
6
+ data?: {
7
+ type: string;
8
+ title: string;
9
+ description?: string;
10
+ severity?: 'info' | 'success' | 'warning' | 'danger';
11
+ icon?: string;
12
+ };
13
+ }
14
+ export declare function getMarkerTypes(markers: readonly ChartMarker[]): string[];
15
+ export declare function filterChartMarkers(markers: readonly ChartMarker[], enabledTypes: ReadonlySet<string>): ChartMarker[];
16
+ export declare function getMarkerCategories(markers: readonly ChartMarker[], enabledTypes: ReadonlySet<string>): MarkerCategory[];
17
+ export declare function toggleMarkerType(enabledTypes: ReadonlySet<string>, type: string): Set<string>;
18
+ export declare function toggleAllMarkerTypes(markers: readonly ChartMarker[], enabled: boolean): Set<string>;
19
+ export declare function mapLogItemsToMarkers(items: readonly LogItemForMarker[]): ChartMarker[];
@@ -0,0 +1,14 @@
1
+ import type { AnyRegistry, InferAvailableMetricKey, InferRegistryMetrics, MetricKindFor } from '../registry.ts';
2
+ export interface MetricsRendererRegistry<R extends AnyRegistry = AnyRegistry, TRendererId extends string = string> {
3
+ byKind?: Partial<Record<Extract<InferRegistryMetrics<R>[number]['kind'], string>, TRendererId>>;
4
+ byMetricKey?: Partial<Record<InferAvailableMetricKey<R>, TRendererId>>;
5
+ }
6
+ export interface MetricRendererHandle<K extends string = string, TKind extends string = string, TRendererId extends string = string> {
7
+ rendererId: TRendererId | `kind:${TKind}`;
8
+ source: 'metric' | 'kind' | 'fallback';
9
+ metricKey: K;
10
+ kind: TKind;
11
+ }
12
+ export declare function defineRendererRegistry<R extends AnyRegistry, TRendererId extends string, TRegistry extends MetricsRendererRegistry<R, TRendererId>>(registry: TRegistry): TRegistry;
13
+ export declare function hasCustomRenderer<R extends AnyRegistry, K extends InferAvailableMetricKey<R>, TRendererId extends string>(metricKey: K, registry?: MetricsRendererRegistry<R, TRendererId>): boolean;
14
+ export declare function resolveRendererHandle<R extends AnyRegistry, K extends InferAvailableMetricKey<R>, TRendererId extends string = string>(metricKey: K, kind: MetricKindFor<R, K>, registry?: MetricsRendererRegistry<R, TRendererId>): MetricRendererHandle<K, MetricKindFor<R, K>, TRendererId>;
@@ -0,0 +1,17 @@
1
+ import type { AnyRegistry, InferAvailableMetricKey, MetricRequestFor, MetricResultChunkFor, MetricsExecutionResult, MetricsRequestFor, RequestedMetricKeys } from '../registry.ts';
2
+ export { getMetricResultKey as getRequestedMetricKey } from '../registry.ts';
3
+ export type FrontendMetricRequest<R extends AnyRegistry, K extends InferAvailableMetricKey<R> = InferAvailableMetricKey<R>, TRequestKey extends string | undefined = string | undefined> = MetricRequestFor<R, K, TRequestKey>;
4
+ export type FrontendMetricsRequest<R extends AnyRegistry> = MetricsRequestFor<R>;
5
+ export type FrontendMetricsResult<R extends AnyRegistry, TMetricRequests extends readonly FrontendMetricRequest<R>[]> = MetricsExecutionResult<R, TMetricRequests>;
6
+ export type FrontendMetricResultChunk<R extends AnyRegistry, TMetricRequests extends readonly FrontendMetricRequest<R>[]> = MetricResultChunkFor<R, TMetricRequests>;
7
+ export declare function defineMetricRequest<R extends AnyRegistry, K extends InferAvailableMetricKey<R>, TRequestKey extends string | undefined = string | undefined>(request: FrontendMetricRequest<R, K, TRequestKey>): FrontendMetricRequest<R, K, TRequestKey>;
8
+ export declare function defineMetricsRequest<R extends AnyRegistry, const TMetricRequests extends readonly FrontendMetricRequest<R>[] = readonly FrontendMetricRequest<R>[]>(request: Omit<FrontendMetricsRequest<R>, 'metrics'> & {
9
+ metrics: TMetricRequests;
10
+ }): Omit<FrontendMetricsRequest<R>, 'metrics'> & {
11
+ metrics: TMetricRequests;
12
+ };
13
+ export declare function getMetricResult<R extends AnyRegistry, TMetricRequests extends readonly FrontendMetricRequest<R>[], K extends RequestedMetricKeys<R, TMetricRequests>>(result: FrontendMetricsResult<R, TMetricRequests>, key: K): { [TResultKey in TMetricRequests[number] extends infer T ? T extends TMetricRequests[number] ? T extends {
14
+ requestKey: infer TRequestKey extends string;
15
+ } ? TRequestKey : T extends {
16
+ key: infer TMetricKey extends string;
17
+ } ? TMetricKey : never : never : never]?: import("../registry.ts").MetricResultForResultKey<R, TMetricRequests, TResultKey> | undefined; }[K];
@@ -0,0 +1,14 @@
1
+ import type { AnyRegistry, MetricRequestFor, MetricResultChunkFor, MetricsExecutionResult, RequestedMetricKeys } from '../registry.ts';
2
+ export interface MetricsStreamState<R extends AnyRegistry, TMetricRequests extends readonly MetricRequestFor<R>[]> extends MetricsExecutionResult<R, TMetricRequests> {
3
+ status: 'idle' | 'streaming' | 'complete';
4
+ done: boolean;
5
+ receivedKeys: RequestedMetricKeys<R, TMetricRequests>[];
6
+ pendingKeys: RequestedMetricKeys<R, TMetricRequests>[];
7
+ }
8
+ export declare function getPendingMetricKeys<R extends AnyRegistry, TMetricRequests extends readonly MetricRequestFor<R>[]>(request: {
9
+ metrics: TMetricRequests;
10
+ }): RequestedMetricKeys<R, TMetricRequests>[];
11
+ export declare function createMetricsStreamState<R extends AnyRegistry, TMetricRequests extends readonly MetricRequestFor<R>[]>(request: {
12
+ metrics: TMetricRequests;
13
+ }): MetricsStreamState<R, TMetricRequests>;
14
+ export declare function applyMetricResultChunk<R extends AnyRegistry, TMetricRequests extends readonly MetricRequestFor<R>[]>(state: MetricsStreamState<R, TMetricRequests>, chunk: MetricResultChunkFor<R, TMetricRequests>): MetricsStreamState<R, TMetricRequests>;
@@ -0,0 +1,5 @@
1
+ export interface RangeLabelOptions {
2
+ now?: Date;
3
+ locale?: string;
4
+ }
5
+ export declare function computeRangeLabel(from: Date | undefined, to: Date | undefined, options?: RangeLabelOptions): string;
@@ -0,0 +1,19 @@
1
+ import type { AvailableMetricsResult } from '../orpc.ts';
2
+ import type { AnyRegistry, MetricsRequestFor } from '../registry.ts';
3
+ import type { MetricRequestFor, MetricResultChunkFor, MetricsExecutionResult } from '../registry.ts';
4
+ export interface MetricsBatchTransport<R extends AnyRegistry = AnyRegistry> {
5
+ run<TRequest extends MetricsRequestFor<R>>(request: TRequest): Promise<MetricsExecutionResult<R, TRequest['metrics']>>;
6
+ }
7
+ export interface MetricsStreamTransport<R extends AnyRegistry = AnyRegistry> {
8
+ stream<TRequest extends MetricsRequestFor<R>>(request: TRequest): AsyncIterable<MetricResultChunkFor<R, TRequest['metrics']>>;
9
+ }
10
+ export interface MetricsCatalogTransport<R extends AnyRegistry = AnyRegistry> {
11
+ getAvailableMetrics(): Promise<AvailableMetricsResult<R>>;
12
+ }
13
+ export interface MetricsTransport<R extends AnyRegistry = AnyRegistry> extends MetricsBatchTransport<R>, MetricsStreamTransport<R>, MetricsCatalogTransport<R> {
14
+ }
15
+ export interface MetricsStreamHandlers<R extends AnyRegistry, TMetricRequests extends readonly MetricRequestFor<R>[]> {
16
+ onChunk?: (chunk: MetricResultChunkFor<R, TMetricRequests>) => void;
17
+ onError?: (error: unknown) => void;
18
+ onComplete?: () => void;
19
+ }
@@ -0,0 +1,108 @@
1
+ import type { AvailableMetricFor, AvailableMetricsResult } from '../orpc.ts';
2
+ import type { AnyRegistry, InferAvailableMetricKey, MetricOutputFor, MetricRequestFor, MetricRequestFiltersFor, MetricRequestResultKey } from '../registry.ts';
3
+ import type { MetricResult } from '../schemas/output.ts';
4
+ import type { TimeGranularity } from '../schemas/time.ts';
5
+ import type { MetricsRendererRegistry } from './renderers.ts';
6
+ export type DashboardSlotId = string;
7
+ export type RendererId = string;
8
+ export interface WidgetLayout {
9
+ cols?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
10
+ rows?: number;
11
+ minHeight?: string;
12
+ }
13
+ export type BarMode = 'stacked' | 'grouped';
14
+ export interface DashboardControls {
15
+ showTimeRange?: boolean;
16
+ showGranularity?: boolean;
17
+ showCompare?: boolean;
18
+ showFilters?: boolean;
19
+ defaultFrom?: Date;
20
+ defaultTo?: Date;
21
+ defaultGranularity?: TimeGranularity;
22
+ defaultCompareToPrevious?: boolean;
23
+ defaultDisableCache?: boolean;
24
+ }
25
+ export interface MetricsFilterControlConfig<R extends AnyRegistry, K extends InferAvailableMetricKey<R>> {
26
+ scope?: 'dashboard' | 'widget' | 'both';
27
+ includeFields?: Array<Extract<keyof MetricRequestFiltersFor<R, K>, string>>;
28
+ }
29
+ export interface MetricsWidgetConfig<R extends AnyRegistry, K extends InferAvailableMetricKey<R> = InferAvailableMetricKey<R>, TRequestKey extends string | undefined = string | undefined, TRendererId extends string = RendererId> {
30
+ key: K;
31
+ requestKey?: TRequestKey;
32
+ title?: string;
33
+ description?: string;
34
+ layout?: WidgetLayout;
35
+ filters?: Partial<MetricRequestFiltersFor<R, K>>;
36
+ filterControls?: MetricsFilterControlConfig<R, K>;
37
+ rendererId?: TRendererId;
38
+ barMode?: BarMode;
39
+ showTrendLine?: boolean;
40
+ }
41
+ export interface MetricsHeadlineConfig {
42
+ _type: 'headline';
43
+ title: string;
44
+ description?: string;
45
+ }
46
+ export interface MetricsSpacerConfig {
47
+ _type: 'spacer';
48
+ layout?: WidgetLayout;
49
+ }
50
+ export interface MetricsCustomSlotConfig<TSlotId extends string = DashboardSlotId> {
51
+ _type: 'slot';
52
+ slotId: TSlotId;
53
+ layout?: WidgetLayout;
54
+ props?: Record<string, unknown>;
55
+ }
56
+ export type DashboardItem<R extends AnyRegistry = AnyRegistry, TRendererId extends string = RendererId, TSlotId extends string = DashboardSlotId> = MetricsWidgetConfig<R, InferAvailableMetricKey<R>, string | undefined, TRendererId> | MetricsHeadlineConfig | MetricsSpacerConfig | MetricsCustomSlotConfig<TSlotId>;
57
+ export interface MetricsDashboardConfig<R extends AnyRegistry = AnyRegistry, TRendererId extends string = RendererId, TSlotId extends string = DashboardSlotId, Items extends readonly DashboardItem<R, TRendererId, TSlotId>[] = readonly DashboardItem<R, TRendererId, TSlotId>[]> {
58
+ title?: string;
59
+ description?: string;
60
+ controls?: DashboardControls;
61
+ persistKey?: string;
62
+ widgets: Items;
63
+ renderers?: MetricsRendererRegistry<R, TRendererId>;
64
+ markers?: ChartMarker[];
65
+ }
66
+ export interface WidgetState<TOutput = unknown> {
67
+ isLoading: boolean;
68
+ result?: MetricResult<TOutput>;
69
+ error?: string;
70
+ }
71
+ type DashboardWidgetItem<R extends AnyRegistry, TRendererId extends string = RendererId> = MetricsWidgetConfig<R, InferAvailableMetricKey<R>, string | undefined, TRendererId>;
72
+ type DashboardMetricRequestFromItem<R extends AnyRegistry, TItem> = TItem extends MetricsWidgetConfig<infer K extends InferAvailableMetricKey<R>, infer TRequestKey extends string | undefined, infer _TRendererId extends string> ? MetricRequestFor<R, K, TRequestKey> : never;
73
+ type DashboardItemResultKey<R extends AnyRegistry, TItem> = DashboardMetricRequestFromItem<R, TItem> extends infer TMetricRequest ? TMetricRequest extends MetricRequestFor<R> ? MetricRequestResultKey<TMetricRequest> : never : never;
74
+ type DashboardItemForResultKey<R extends AnyRegistry, Items extends readonly DashboardItem<R, string, string>[], TResultKey extends DashboardResultKey<R, Items>> = Extract<Extract<Items[number], DashboardWidgetItem<R>>, {
75
+ requestKey: TResultKey;
76
+ }> extends never ? Extract<Extract<Items[number], DashboardWidgetItem<R>>, {
77
+ key: TResultKey;
78
+ }> : Extract<Extract<Items[number], DashboardWidgetItem<R>>, {
79
+ requestKey: TResultKey;
80
+ }>;
81
+ export type DashboardResultKey<R extends AnyRegistry, Items extends readonly DashboardItem<R, string, string>[]> = DashboardItemResultKey<R, Extract<Items[number], DashboardWidgetItem<R>>>;
82
+ export type DashboardState<R extends AnyRegistry, Items extends readonly DashboardItem<R, string, string>[]> = {
83
+ [TResultKey in DashboardResultKey<R, Items>]?: WidgetState<DashboardItemForResultKey<R, Items, TResultKey> extends {
84
+ key: infer TMetricKey extends InferAvailableMetricKey<R>;
85
+ } ? MetricOutputFor<R, TMetricKey> : never>;
86
+ };
87
+ export interface ChartMarker {
88
+ id: string;
89
+ timestamp: Date;
90
+ type: string;
91
+ label: string;
92
+ title: string;
93
+ description?: string;
94
+ severity?: 'info' | 'success' | 'warning' | 'danger';
95
+ icon?: string;
96
+ meta?: Record<string, unknown>;
97
+ }
98
+ export interface MarkerCategory {
99
+ type: string;
100
+ label: string;
101
+ count: number;
102
+ enabled: boolean;
103
+ }
104
+ export interface FrontendCatalogState<R extends AnyRegistry = AnyRegistry> {
105
+ metrics: AvailableMetricFor<R>[];
106
+ total: AvailableMetricsResult<R>['total'];
107
+ }
108
+ export {};
@@ -0,0 +1 @@
1
+ export * from './frontend/index.ts';