@rawdash/core 0.2.0 → 0.3.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/index.d.ts +134 -30
- package/dist/index.js +20 -4
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -101,8 +101,16 @@ declare const resolvedMetricSchema: z.ZodObject<{
|
|
|
101
101
|
}>;
|
|
102
102
|
name: z.ZodOptional<z.ZodString>;
|
|
103
103
|
entityType: z.ZodOptional<z.ZodString>;
|
|
104
|
-
field: z.ZodString
|
|
105
|
-
fn: z.
|
|
104
|
+
field: z.ZodOptional<z.ZodString>;
|
|
105
|
+
fn: z.ZodEnum<{
|
|
106
|
+
latest: "latest";
|
|
107
|
+
count: "count";
|
|
108
|
+
sum: "sum";
|
|
109
|
+
avg: "avg";
|
|
110
|
+
min: "min";
|
|
111
|
+
max: "max";
|
|
112
|
+
first: "first";
|
|
113
|
+
}>;
|
|
106
114
|
window: z.ZodOptional<z.ZodString>;
|
|
107
115
|
filter: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
108
116
|
field: z.ZodString;
|
|
@@ -155,8 +163,16 @@ declare const statWidgetSchema: z.ZodObject<{
|
|
|
155
163
|
}>;
|
|
156
164
|
name: z.ZodOptional<z.ZodString>;
|
|
157
165
|
entityType: z.ZodOptional<z.ZodString>;
|
|
158
|
-
field: z.ZodString
|
|
159
|
-
fn: z.
|
|
166
|
+
field: z.ZodOptional<z.ZodString>;
|
|
167
|
+
fn: z.ZodEnum<{
|
|
168
|
+
latest: "latest";
|
|
169
|
+
count: "count";
|
|
170
|
+
sum: "sum";
|
|
171
|
+
avg: "avg";
|
|
172
|
+
min: "min";
|
|
173
|
+
max: "max";
|
|
174
|
+
first: "first";
|
|
175
|
+
}>;
|
|
160
176
|
window: z.ZodOptional<z.ZodString>;
|
|
161
177
|
filter: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
162
178
|
field: z.ZodString;
|
|
@@ -220,8 +236,16 @@ declare const timeseriesWidgetSchema: z.ZodObject<{
|
|
|
220
236
|
}>;
|
|
221
237
|
name: z.ZodOptional<z.ZodString>;
|
|
222
238
|
entityType: z.ZodOptional<z.ZodString>;
|
|
223
|
-
field: z.ZodString
|
|
224
|
-
fn: z.
|
|
239
|
+
field: z.ZodOptional<z.ZodString>;
|
|
240
|
+
fn: z.ZodEnum<{
|
|
241
|
+
latest: "latest";
|
|
242
|
+
count: "count";
|
|
243
|
+
sum: "sum";
|
|
244
|
+
avg: "avg";
|
|
245
|
+
min: "min";
|
|
246
|
+
max: "max";
|
|
247
|
+
first: "first";
|
|
248
|
+
}>;
|
|
225
249
|
window: z.ZodOptional<z.ZodString>;
|
|
226
250
|
filter: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
227
251
|
field: z.ZodString;
|
|
@@ -281,8 +305,16 @@ declare const distributionWidgetSchema: z.ZodObject<{
|
|
|
281
305
|
}>;
|
|
282
306
|
name: z.ZodOptional<z.ZodString>;
|
|
283
307
|
entityType: z.ZodOptional<z.ZodString>;
|
|
284
|
-
field: z.ZodString
|
|
285
|
-
fn: z.
|
|
308
|
+
field: z.ZodOptional<z.ZodString>;
|
|
309
|
+
fn: z.ZodEnum<{
|
|
310
|
+
latest: "latest";
|
|
311
|
+
count: "count";
|
|
312
|
+
sum: "sum";
|
|
313
|
+
avg: "avg";
|
|
314
|
+
min: "min";
|
|
315
|
+
max: "max";
|
|
316
|
+
first: "first";
|
|
317
|
+
}>;
|
|
286
318
|
window: z.ZodOptional<z.ZodString>;
|
|
287
319
|
filter: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
288
320
|
field: z.ZodString;
|
|
@@ -338,8 +370,16 @@ declare const widgetSchemas: {
|
|
|
338
370
|
}>;
|
|
339
371
|
name: z.ZodOptional<z.ZodString>;
|
|
340
372
|
entityType: z.ZodOptional<z.ZodString>;
|
|
341
|
-
field: z.ZodString
|
|
342
|
-
fn: z.
|
|
373
|
+
field: z.ZodOptional<z.ZodString>;
|
|
374
|
+
fn: z.ZodEnum<{
|
|
375
|
+
latest: "latest";
|
|
376
|
+
count: "count";
|
|
377
|
+
sum: "sum";
|
|
378
|
+
avg: "avg";
|
|
379
|
+
min: "min";
|
|
380
|
+
max: "max";
|
|
381
|
+
first: "first";
|
|
382
|
+
}>;
|
|
343
383
|
window: z.ZodOptional<z.ZodString>;
|
|
344
384
|
filter: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
345
385
|
field: z.ZodString;
|
|
@@ -403,8 +443,16 @@ declare const widgetSchemas: {
|
|
|
403
443
|
}>;
|
|
404
444
|
name: z.ZodOptional<z.ZodString>;
|
|
405
445
|
entityType: z.ZodOptional<z.ZodString>;
|
|
406
|
-
field: z.ZodString
|
|
407
|
-
fn: z.
|
|
446
|
+
field: z.ZodOptional<z.ZodString>;
|
|
447
|
+
fn: z.ZodEnum<{
|
|
448
|
+
latest: "latest";
|
|
449
|
+
count: "count";
|
|
450
|
+
sum: "sum";
|
|
451
|
+
avg: "avg";
|
|
452
|
+
min: "min";
|
|
453
|
+
max: "max";
|
|
454
|
+
first: "first";
|
|
455
|
+
}>;
|
|
408
456
|
window: z.ZodOptional<z.ZodString>;
|
|
409
457
|
filter: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
410
458
|
field: z.ZodString;
|
|
@@ -464,8 +512,16 @@ declare const widgetSchemas: {
|
|
|
464
512
|
}>;
|
|
465
513
|
name: z.ZodOptional<z.ZodString>;
|
|
466
514
|
entityType: z.ZodOptional<z.ZodString>;
|
|
467
|
-
field: z.ZodString
|
|
468
|
-
fn: z.
|
|
515
|
+
field: z.ZodOptional<z.ZodString>;
|
|
516
|
+
fn: z.ZodEnum<{
|
|
517
|
+
latest: "latest";
|
|
518
|
+
count: "count";
|
|
519
|
+
sum: "sum";
|
|
520
|
+
avg: "avg";
|
|
521
|
+
min: "min";
|
|
522
|
+
max: "max";
|
|
523
|
+
first: "first";
|
|
524
|
+
}>;
|
|
469
525
|
window: z.ZodOptional<z.ZodString>;
|
|
470
526
|
filter: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
471
527
|
field: z.ZodString;
|
|
@@ -521,8 +577,16 @@ declare const widgetSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
521
577
|
}>;
|
|
522
578
|
name: z.ZodOptional<z.ZodString>;
|
|
523
579
|
entityType: z.ZodOptional<z.ZodString>;
|
|
524
|
-
field: z.ZodString
|
|
525
|
-
fn: z.
|
|
580
|
+
field: z.ZodOptional<z.ZodString>;
|
|
581
|
+
fn: z.ZodEnum<{
|
|
582
|
+
latest: "latest";
|
|
583
|
+
count: "count";
|
|
584
|
+
sum: "sum";
|
|
585
|
+
avg: "avg";
|
|
586
|
+
min: "min";
|
|
587
|
+
max: "max";
|
|
588
|
+
first: "first";
|
|
589
|
+
}>;
|
|
526
590
|
window: z.ZodOptional<z.ZodString>;
|
|
527
591
|
filter: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
528
592
|
field: z.ZodString;
|
|
@@ -584,8 +648,16 @@ declare const widgetSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
584
648
|
}>;
|
|
585
649
|
name: z.ZodOptional<z.ZodString>;
|
|
586
650
|
entityType: z.ZodOptional<z.ZodString>;
|
|
587
|
-
field: z.ZodString
|
|
588
|
-
fn: z.
|
|
651
|
+
field: z.ZodOptional<z.ZodString>;
|
|
652
|
+
fn: z.ZodEnum<{
|
|
653
|
+
latest: "latest";
|
|
654
|
+
count: "count";
|
|
655
|
+
sum: "sum";
|
|
656
|
+
avg: "avg";
|
|
657
|
+
min: "min";
|
|
658
|
+
max: "max";
|
|
659
|
+
first: "first";
|
|
660
|
+
}>;
|
|
589
661
|
window: z.ZodOptional<z.ZodString>;
|
|
590
662
|
filter: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
591
663
|
field: z.ZodString;
|
|
@@ -644,8 +716,16 @@ declare const widgetSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
644
716
|
}>;
|
|
645
717
|
name: z.ZodOptional<z.ZodString>;
|
|
646
718
|
entityType: z.ZodOptional<z.ZodString>;
|
|
647
|
-
field: z.ZodString
|
|
648
|
-
fn: z.
|
|
719
|
+
field: z.ZodOptional<z.ZodString>;
|
|
720
|
+
fn: z.ZodEnum<{
|
|
721
|
+
latest: "latest";
|
|
722
|
+
count: "count";
|
|
723
|
+
sum: "sum";
|
|
724
|
+
avg: "avg";
|
|
725
|
+
min: "min";
|
|
726
|
+
max: "max";
|
|
727
|
+
first: "first";
|
|
728
|
+
}>;
|
|
649
729
|
window: z.ZodOptional<z.ZodString>;
|
|
650
730
|
filter: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
651
731
|
field: z.ZodString;
|
|
@@ -701,8 +781,16 @@ declare function getWidgetSchema(kind: WidgetKind): z.ZodObject<{
|
|
|
701
781
|
}>;
|
|
702
782
|
name: z.ZodOptional<z.ZodString>;
|
|
703
783
|
entityType: z.ZodOptional<z.ZodString>;
|
|
704
|
-
field: z.ZodString
|
|
705
|
-
fn: z.
|
|
784
|
+
field: z.ZodOptional<z.ZodString>;
|
|
785
|
+
fn: z.ZodEnum<{
|
|
786
|
+
latest: "latest";
|
|
787
|
+
count: "count";
|
|
788
|
+
sum: "sum";
|
|
789
|
+
avg: "avg";
|
|
790
|
+
min: "min";
|
|
791
|
+
max: "max";
|
|
792
|
+
first: "first";
|
|
793
|
+
}>;
|
|
706
794
|
window: z.ZodOptional<z.ZodString>;
|
|
707
795
|
filter: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
708
796
|
field: z.ZodString;
|
|
@@ -764,8 +852,16 @@ declare function getWidgetSchema(kind: WidgetKind): z.ZodObject<{
|
|
|
764
852
|
}>;
|
|
765
853
|
name: z.ZodOptional<z.ZodString>;
|
|
766
854
|
entityType: z.ZodOptional<z.ZodString>;
|
|
767
|
-
field: z.ZodString
|
|
768
|
-
fn: z.
|
|
855
|
+
field: z.ZodOptional<z.ZodString>;
|
|
856
|
+
fn: z.ZodEnum<{
|
|
857
|
+
latest: "latest";
|
|
858
|
+
count: "count";
|
|
859
|
+
sum: "sum";
|
|
860
|
+
avg: "avg";
|
|
861
|
+
min: "min";
|
|
862
|
+
max: "max";
|
|
863
|
+
first: "first";
|
|
864
|
+
}>;
|
|
769
865
|
window: z.ZodOptional<z.ZodString>;
|
|
770
866
|
filter: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
771
867
|
field: z.ZodString;
|
|
@@ -824,8 +920,16 @@ declare function getWidgetSchema(kind: WidgetKind): z.ZodObject<{
|
|
|
824
920
|
}>;
|
|
825
921
|
name: z.ZodOptional<z.ZodString>;
|
|
826
922
|
entityType: z.ZodOptional<z.ZodString>;
|
|
827
|
-
field: z.ZodString
|
|
828
|
-
fn: z.
|
|
923
|
+
field: z.ZodOptional<z.ZodString>;
|
|
924
|
+
fn: z.ZodEnum<{
|
|
925
|
+
latest: "latest";
|
|
926
|
+
count: "count";
|
|
927
|
+
sum: "sum";
|
|
928
|
+
avg: "avg";
|
|
929
|
+
min: "min";
|
|
930
|
+
max: "max";
|
|
931
|
+
first: "first";
|
|
932
|
+
}>;
|
|
829
933
|
window: z.ZodOptional<z.ZodString>;
|
|
830
934
|
filter: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{
|
|
831
935
|
field: z.ZodString;
|
|
@@ -889,7 +993,7 @@ interface MetricDef {
|
|
|
889
993
|
shape: Shape;
|
|
890
994
|
name?: string;
|
|
891
995
|
entityType?: string;
|
|
892
|
-
field
|
|
996
|
+
field?: string;
|
|
893
997
|
fn: AggFn;
|
|
894
998
|
window?: string;
|
|
895
999
|
filter?: FilterClause[];
|
|
@@ -900,8 +1004,8 @@ interface ResolvedMetric {
|
|
|
900
1004
|
readonly shape: Shape;
|
|
901
1005
|
readonly name?: string;
|
|
902
1006
|
readonly entityType?: string;
|
|
903
|
-
readonly field
|
|
904
|
-
readonly fn:
|
|
1007
|
+
readonly field?: string;
|
|
1008
|
+
readonly fn: AggFn;
|
|
905
1009
|
readonly window?: string;
|
|
906
1010
|
readonly filter?: FilterClause[];
|
|
907
1011
|
readonly groupBy?: GroupBy;
|
|
@@ -955,7 +1059,7 @@ declare function defineConfigFields<T extends z.ZodRawShape>(schema: z.ZodObject
|
|
|
955
1059
|
|
|
956
1060
|
declare function computeMetric(storage: StorageHandle, metric: ResolvedMetric): Promise<unknown>;
|
|
957
1061
|
|
|
958
|
-
declare function resolveWidget(id: string, widget: Widget, connectors: ConnectorEntry[], storage: ServerStorage): Promise<WidgetEntry | undefined>;
|
|
1062
|
+
declare function resolveWidget(id: string, widget: Widget, connectors: ConnectorEntry[] | readonly string[] | undefined, storage: ServerStorage): Promise<WidgetEntry | undefined>;
|
|
959
1063
|
|
|
960
1064
|
declare class InMemoryStorage implements ServerStorage {
|
|
961
1065
|
private eventStore;
|
package/dist/index.js
CHANGED
|
@@ -176,11 +176,14 @@ var resolvedMetricSchema = z.object({
|
|
|
176
176
|
shape: shapeSchema,
|
|
177
177
|
name: z.string().optional(),
|
|
178
178
|
entityType: z.string().optional(),
|
|
179
|
-
field: z.string(),
|
|
180
|
-
fn:
|
|
179
|
+
field: z.string().optional(),
|
|
180
|
+
fn: aggFnSchema,
|
|
181
181
|
window: z.string().optional(),
|
|
182
182
|
filter: z.array(filterClauseSchema).optional(),
|
|
183
183
|
groupBy: groupBySchema.optional()
|
|
184
|
+
}).refine((m) => m.fn === "count" || m.field !== void 0, {
|
|
185
|
+
message: 'field is required unless fn is "count"',
|
|
186
|
+
path: ["field"]
|
|
184
187
|
});
|
|
185
188
|
var titleField = z.string().meta({ label: "Title", description: "Widget title." });
|
|
186
189
|
var statWidgetSchema = z.object({
|
|
@@ -494,6 +497,9 @@ function computeAgg(records, field, fn) {
|
|
|
494
497
|
if (fn === "count") {
|
|
495
498
|
return records.length;
|
|
496
499
|
}
|
|
500
|
+
if (field === void 0) {
|
|
501
|
+
throw new Error(`computeAgg: fn "${fn}" requires a field`);
|
|
502
|
+
}
|
|
497
503
|
if (fn === "latest") {
|
|
498
504
|
return records.at(-1)?.[field] ?? null;
|
|
499
505
|
}
|
|
@@ -663,8 +669,7 @@ async function resolveWidget(id, widget, connectors, storage) {
|
|
|
663
669
|
};
|
|
664
670
|
}
|
|
665
671
|
const { connectorId } = widget.metric;
|
|
666
|
-
|
|
667
|
-
if (!connectorEntry) {
|
|
672
|
+
if (connectors !== void 0 && !isAllowedConnector(connectors, connectorId)) {
|
|
668
673
|
return void 0;
|
|
669
674
|
}
|
|
670
675
|
const handle = storage.getStorageHandle(connectorId);
|
|
@@ -677,6 +682,17 @@ async function resolveWidget(id, widget, connectors, storage) {
|
|
|
677
682
|
cachedAt: (await storage.getSyncState()).lastSyncAt
|
|
678
683
|
};
|
|
679
684
|
}
|
|
685
|
+
function isAllowedConnector(connectors, connectorId) {
|
|
686
|
+
if (connectors.length === 0) {
|
|
687
|
+
return false;
|
|
688
|
+
}
|
|
689
|
+
if (typeof connectors[0] === "string") {
|
|
690
|
+
return connectors.includes(connectorId);
|
|
691
|
+
}
|
|
692
|
+
return connectors.some(
|
|
693
|
+
(e) => e.connector.id === connectorId
|
|
694
|
+
);
|
|
695
|
+
}
|
|
680
696
|
|
|
681
697
|
// src/in-memory-storage.ts
|
|
682
698
|
var InMemoryStorage = class {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/secrets.ts","../src/connector.ts","../src/widget-schemas.ts","../src/config.ts","../src/retention.ts","../src/config-fields.ts","../src/compute.ts","../src/resolve-widget.ts","../src/in-memory-storage.ts"],"sourcesContent":["export type SecretRef = { $secret: string };\n\nexport function secret(name: string): SecretRef {\n if (!/^[A-Z][A-Z0-9_]*$/.test(name)) {\n throw new Error(\n `Invalid secret name \"${name}\". Must match /^[A-Z][A-Z0-9_]*$/ ` +\n `(uppercase letters, digits, underscores; must start with a letter).`,\n );\n }\n return { $secret: name };\n}\n\nexport function isSecretRef(value: unknown): value is SecretRef {\n return (\n typeof value === 'object' &&\n value !== null &&\n '$secret' in value &&\n typeof (value as SecretRef).$secret === 'string'\n );\n}\n\nexport interface SecretsResolver {\n resolve(name: string): string | undefined;\n}\n\nexport class EnvSecretsResolver implements SecretsResolver {\n resolve(name: string): string | undefined {\n const env = (\n globalThis as { process?: { env?: Record<string, string | undefined> } }\n ).process?.env;\n return env?.[name];\n }\n}\n\nexport function resolveSecretRefs<T>(obj: T, resolver: SecretsResolver): T {\n if (isSecretRef(obj)) {\n const name = obj.$secret;\n const value = resolver.resolve(name);\n if (value === undefined) {\n throw new Error(\n `Missing secret \"${name}\". Set it via process.env.${name} or the CLI: rawdash secrets set ${name} ...`,\n );\n }\n return value as unknown as T;\n }\n if (Array.isArray(obj)) {\n return obj.map((item) => resolveSecretRefs(item, resolver)) as unknown as T;\n }\n if (typeof obj === 'object' && obj !== null) {\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(obj as object)) {\n Object.defineProperty(result, key, {\n value: resolveSecretRefs(val, resolver),\n enumerable: true,\n configurable: true,\n writable: true,\n });\n }\n return result as T;\n }\n return obj;\n}\n","import {\n EnvSecretsResolver,\n type SecretRef,\n resolveSecretRefs,\n} from './secrets';\n\nexport type JSONValue =\n | string\n | number\n | boolean\n | null\n | JSONValue[]\n | { [key: string]: JSONValue };\n\n// ---------------------------------------------------------------------------\n// Five storage shapes\n// ---------------------------------------------------------------------------\n\nexport interface Event {\n name: string;\n start_ts: number;\n end_ts: number | null;\n attributes: Record<string, JSONValue>;\n}\n\nexport interface Entity {\n type: string;\n id: string;\n attributes: Record<string, JSONValue>;\n updated_at: number;\n}\n\nexport interface Metric {\n name: string;\n ts: number;\n value: number;\n attributes: Record<string, JSONValue>;\n}\n\nexport interface Edge {\n from_type: string;\n from_id: string;\n kind: string;\n to_type: string;\n to_id: string;\n attributes: Record<string, JSONValue>;\n updated_at: number;\n}\n\nexport type Distribution =\n | {\n name: string;\n ts: number;\n kind: 'histogram';\n data: {\n buckets: Array<{ le: number; count: number }>;\n count: number;\n sum: number;\n };\n attributes: Record<string, JSONValue>;\n }\n | {\n name: string;\n ts: number;\n kind: 'summary';\n data: {\n quantiles: Array<{ q: number; value: number }>;\n count: number;\n sum: number;\n };\n attributes: Record<string, JSONValue>;\n };\n\n// ---------------------------------------------------------------------------\n// Storage query types\n// ---------------------------------------------------------------------------\n\nexport interface EventQuery {\n name?: string;\n start?: number;\n end?: number;\n}\n\nexport interface EntityQuery {\n type: string;\n}\n\nexport interface MetricQuery {\n name?: string;\n start?: number;\n end?: number;\n}\n\nexport interface EdgeQuery {\n fromType?: string;\n fromId?: string;\n kind?: string;\n toType?: string;\n toId?: string;\n}\n\nexport interface DistributionQuery {\n name?: string;\n start?: number;\n end?: number;\n}\n\n// ---------------------------------------------------------------------------\n// StorageHandle — write and read surface\n// ---------------------------------------------------------------------------\n\nexport interface StorageHandle {\n event(e: Event): Promise<void>;\n entity(e: Entity): Promise<void>;\n metric(m: Metric): Promise<void>;\n edge(e: Edge): Promise<void>;\n distribution(d: Distribution): Promise<void>;\n\n events(es: Event[], scope?: { names?: string[] }): Promise<void>;\n entities(es: Entity[], scope?: { types?: string[] }): Promise<void>;\n metrics(ms: Metric[], scope?: { names?: string[] }): Promise<void>;\n edges(es: Edge[], scope?: { kinds?: string[] }): Promise<void>;\n distributions(\n ds: Distribution[],\n scope?: { names?: string[] },\n ): Promise<void>;\n\n queryEvents(q: EventQuery): Promise<Event[]>;\n getEntity(type: string, id: string): Promise<Entity | null>;\n queryEntities(q: EntityQuery): Promise<Entity[]>;\n queryMetrics(q: MetricQuery): Promise<Metric[]>;\n traverse(q: EdgeQuery): Promise<Edge[]>;\n queryDistributions(q: DistributionQuery): Promise<Distribution[]>;\n\n // Deletes all rows in the given time-series shape whose timestamp column is\n // strictly less than `tsUnixMs`. Only covers append-only shapes (events,\n // metrics, distributions). Entities and edges are excluded because they hold\n // the latest known state per primary key — deleting by age would lose live\n // data. The right model for those shapes is \"expire when source disappears.\"\n deleteOlderThan(\n shape: 'events' | 'metrics' | 'distributions',\n tsUnixMs: number,\n ): Promise<{ rowsDeleted: number }>;\n}\n\n// ---------------------------------------------------------------------------\n// Credentials\n// ---------------------------------------------------------------------------\n\nexport interface CredentialEntry {\n description: string;\n auth?: 'none' | 'optional' | 'required';\n}\n\nexport type CredentialSchema = Record<string, CredentialEntry>;\n\nexport type InferCredentials<TCreds extends CredentialSchema> = {\n [K in keyof TCreds]: TCreds[K] extends { auth: 'required' }\n ? string\n : string | undefined;\n};\n\nexport type InferCredentialInput<TCreds extends CredentialSchema> = {\n [K in keyof TCreds]: TCreds[K] extends { auth: 'required' }\n ? string | SecretRef\n : string | SecretRef | undefined;\n};\n\n// ---------------------------------------------------------------------------\n// Sync + Connector\n// ---------------------------------------------------------------------------\n\nexport interface SyncRequest {\n mode: 'full' | 'latest';\n since?: string;\n}\n\nexport interface Connector {\n readonly id: string;\n readonly credentials?: CredentialSchema;\n serializeConfig(): Record<string, unknown>;\n sync(\n request: SyncRequest,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<void>;\n}\n\nexport interface RetryOptions {\n maxAttempts?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n signal?: AbortSignal;\n}\n\nexport abstract class BaseConnector<\n TSettings = unknown,\n TCreds extends CredentialSchema = CredentialSchema,\n> implements Connector {\n abstract readonly id: string;\n readonly credentials?: TCreds;\n\n protected settings: TSettings;\n protected creds: InferCredentials<TCreds>;\n private rawCredInput: InferCredentialInput<TCreds> | undefined;\n\n constructor(settings: TSettings, creds?: InferCredentialInput<TCreds>) {\n this.settings = settings;\n this.rawCredInput = creds;\n this.creds = creds\n ? (resolveSecretRefs(\n creds,\n new EnvSecretsResolver(),\n ) as InferCredentials<TCreds>)\n : ({} as InferCredentials<TCreds>);\n }\n\n serializeConfig(): Record<string, unknown> {\n const config: Record<string, unknown> = {\n ...(this.settings as Record<string, unknown>),\n };\n if (this.rawCredInput) {\n for (const [key, value] of Object.entries(\n this.rawCredInput as Record<string, unknown>,\n )) {\n if (value !== undefined) {\n config[key] = value;\n }\n }\n }\n return config;\n }\n\n protected sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n return Promise.reject(signal.reason ?? new Error('Aborted'));\n }\n return new Promise<void>((resolve, reject) => {\n const onAbort = () => {\n clearTimeout(timer);\n reject(signal!.reason ?? new Error('Aborted'));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n }\n\n protected async withRetry<T>(\n fn: (\n signal?: AbortSignal,\n ) => Promise<{ status: 'done'; value: T } | { status: 'retry' }>,\n options?: RetryOptions,\n ): Promise<T | null> {\n const {\n maxAttempts = 10,\n initialDelayMs = 1000,\n maxDelayMs = 10000,\n signal,\n } = options ?? {};\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n signal?.throwIfAborted();\n const result = await fn(signal);\n if (result.status === 'done') {\n return result.value;\n }\n if (attempt < maxAttempts - 1) {\n const delay = Math.min(initialDelayMs * 2 ** attempt, maxDelayMs);\n await this.sleep(delay, signal);\n }\n }\n\n return null;\n }\n\n abstract sync(\n request: SyncRequest,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<void>;\n}\n\nexport function defineConnector<TSettings>() {\n return function <\n TCreds extends CredentialSchema = Record<string, never>,\n >(def: {\n id: string;\n credentials?: TCreds;\n sync: (\n this: { settings: TSettings; creds: InferCredentials<TCreds> },\n request: SyncRequest,\n storage: StorageHandle,\n signal?: AbortSignal,\n ) => Promise<void>;\n }): {\n new (settings: TSettings, creds?: InferCredentialInput<TCreds>): Connector;\n readonly id: string;\n readonly credentials: TCreds | undefined;\n } {\n class DynamicConnector extends BaseConnector<TSettings, TCreds> {\n static readonly id = def.id;\n static readonly credentials = def.credentials;\n\n readonly id = def.id;\n override readonly credentials = def.credentials;\n\n async sync(\n request: SyncRequest,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<void> {\n return def.sync.call(\n { settings: this.settings, creds: this.creds },\n request,\n storage,\n signal,\n );\n }\n }\n\n return DynamicConnector as unknown as {\n new (\n settings: TSettings,\n creds?: InferCredentialInput<TCreds>,\n ): Connector;\n readonly id: string;\n readonly credentials: TCreds | undefined;\n };\n };\n}\n","import { z } from 'zod';\n\nexport const shapeSchema = z.enum([\n 'event',\n 'entity',\n 'metric',\n 'edge',\n 'distribution',\n]);\n\nexport const aggFnSchema = z.enum([\n 'count',\n 'sum',\n 'avg',\n 'min',\n 'max',\n 'latest',\n 'first',\n]);\n\nexport const filterOperatorSchema = z.enum([\n 'eq',\n 'neq',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'contains',\n]);\n\nexport const filterConditionSchema = z.object({\n field: z.string(),\n op: filterOperatorSchema,\n value: z.union([z.string(), z.number(), z.boolean()]),\n});\n\nexport const filterClauseSchema = z.union([\n filterConditionSchema,\n z.object({ or: z.array(filterConditionSchema) }),\n]);\n\nexport const groupBySchema = z.object({\n field: z.string(),\n granularity: z.enum(['hour', 'day', 'week', 'month']),\n});\n\nexport const resolvedMetricSchema = z.object({\n connectorId: z.string(),\n shape: shapeSchema,\n name: z.string().optional(),\n entityType: z.string().optional(),\n field: z.string(),\n fn: z.string(),\n window: z.string().optional(),\n filter: z.array(filterClauseSchema).optional(),\n groupBy: groupBySchema.optional(),\n});\n\nconst titleField = z\n .string()\n .meta({ label: 'Title', description: 'Widget title.' });\n\nexport const statWidgetSchema = z.object({\n kind: z.literal('stat'),\n title: titleField,\n metric: resolvedMetricSchema.meta({\n label: 'Metric',\n description: 'Resolved metric definition.',\n }),\n window: z\n .string()\n .optional()\n .meta({ label: 'Window', description: \"Time window, e.g. '7d'.\" }),\n compare: z\n .enum(['none', 'previous-period'])\n .default('none')\n .meta({ label: 'Compare', description: 'Comparison mode.' }),\n});\n\nexport const statusWidgetSchema = z.object({\n kind: z.literal('status'),\n title: titleField,\n source: z.string().meta({\n label: 'Source',\n description: 'Connector or data source reference.',\n }),\n});\n\nexport const timeseriesWidgetSchema = z.object({\n kind: z.literal('timeseries'),\n title: titleField,\n metric: resolvedMetricSchema.meta({\n label: 'Metric',\n description: 'Resolved metric definition.',\n }),\n window: z\n .string()\n .meta({ label: 'Window', description: \"Time window, e.g. '30d'.\" }),\n granularity: z\n .enum(['hour', 'day', 'week'])\n .default('day')\n .meta({ label: 'Granularity', description: 'Time bucket size.' }),\n});\n\nexport const distributionWidgetSchema = z.object({\n kind: z.literal('distribution'),\n title: titleField,\n metric: resolvedMetricSchema.meta({\n label: 'Metric',\n description: 'Resolved metric definition.',\n }),\n window: z\n .string()\n .meta({ label: 'Window', description: \"Time window, e.g. '7d'.\" }),\n});\n\nexport const widgetSchemas = {\n stat: statWidgetSchema,\n status: statusWidgetSchema,\n timeseries: timeseriesWidgetSchema,\n distribution: distributionWidgetSchema,\n} as const;\n\nexport const widgetSchema = z.discriminatedUnion('kind', [\n statWidgetSchema,\n statusWidgetSchema,\n timeseriesWidgetSchema,\n distributionWidgetSchema,\n]);\n\nexport type WidgetKind = keyof typeof widgetSchemas;\n\nexport function getWidgetSchema(kind: WidgetKind) {\n return widgetSchemas[kind];\n}\n","import type { Connector } from './connector';\nimport type { RetentionConfig } from './retention';\nimport { getWidgetSchema, widgetSchemas } from './widget-schemas';\nimport type { WidgetKind } from './widget-schemas';\n\n// ---------------------------------------------------------------------------\n// Aggregation functions\n// ---------------------------------------------------------------------------\n\nexport type AggFn =\n | 'count'\n | 'sum'\n | 'avg'\n | 'min'\n | 'max'\n | 'latest'\n | 'first';\n\n// ---------------------------------------------------------------------------\n// Shape\n// ---------------------------------------------------------------------------\n\nexport type Shape = 'event' | 'entity' | 'metric' | 'edge' | 'distribution';\n\n// ---------------------------------------------------------------------------\n// Filters\n// ---------------------------------------------------------------------------\n\nexport type FilterOperator =\n | 'eq'\n | 'neq'\n | 'gt'\n | 'gte'\n | 'lt'\n | 'lte'\n | 'contains';\n\nexport interface FilterCondition {\n field: string;\n op: FilterOperator;\n value: string | number | boolean;\n}\n\nexport type FilterClause = FilterCondition | { or: FilterCondition[] };\n\n// ---------------------------------------------------------------------------\n// GroupBy\n// ---------------------------------------------------------------------------\n\nexport interface GroupBy {\n field: string;\n granularity: 'hour' | 'day' | 'week' | 'month';\n}\n\n// ---------------------------------------------------------------------------\n// Metric definition\n// ---------------------------------------------------------------------------\n\nexport interface MetricDef {\n connector: { id: string };\n shape: Shape;\n name?: string;\n entityType?: string;\n field: string;\n fn: AggFn;\n window?: string;\n filter?: FilterClause[];\n groupBy?: GroupBy;\n}\n\nexport interface ResolvedMetric {\n readonly connectorId: string;\n readonly shape: Shape;\n readonly name?: string;\n readonly entityType?: string;\n readonly field: string;\n readonly fn: string;\n readonly window?: string;\n readonly filter?: FilterClause[];\n readonly groupBy?: GroupBy;\n}\n\n// ---------------------------------------------------------------------------\n// Widget definition\n// ---------------------------------------------------------------------------\n\nexport interface StatWidget {\n kind: 'stat';\n title: string;\n metric: ResolvedMetric;\n window?: string;\n compare?: 'none' | 'previous-period';\n}\n\nexport interface StatusWidget {\n kind: 'status';\n title: string;\n source: string;\n}\n\nexport interface TimeseriesWidget {\n kind: 'timeseries';\n title: string;\n metric: ResolvedMetric;\n window: string;\n granularity?: 'hour' | 'day' | 'week';\n}\n\nexport interface DistributionWidget {\n kind: 'distribution';\n title: string;\n metric: ResolvedMetric;\n window: string;\n}\n\nexport type Widget =\n | StatWidget\n | StatusWidget\n | TimeseriesWidget\n | DistributionWidget;\n\nexport type { WidgetKind };\n\n// ---------------------------------------------------------------------------\n// Dashboard config\n// ---------------------------------------------------------------------------\n\nexport interface ConnectorEntry {\n connector: Connector;\n}\n\nexport interface Dashboard {\n widgets: Record<string, Widget>;\n}\n\nexport interface DashboardConfig {\n connectors: ConnectorEntry[];\n dashboards: Record<string, Dashboard>;\n retention?: RetentionConfig;\n}\n\n// ---------------------------------------------------------------------------\n// defineDashboard\n// ---------------------------------------------------------------------------\n\nconst VALID_WIDGET_KINDS = new Set<string>(Object.keys(widgetSchemas));\n\nexport function defineDashboard(options: {\n widgets: Record<string, Widget>;\n}): Dashboard {\n for (const [key, widget] of Object.entries(options.widgets)) {\n if (!VALID_WIDGET_KINDS.has(widget.kind)) {\n throw new Error(\n `Widget \"${key}\": unknown kind \"${widget.kind}\". Must be one of: ${[...VALID_WIDGET_KINDS].join(', ')}`,\n );\n }\n const schema = getWidgetSchema(widget.kind as WidgetKind);\n const result = schema.safeParse(widget);\n if (!result.success) {\n throw new Error(\n `Widget \"${key}\" (kind \"${widget.kind}\"): ${result.error.issues.map((i) => i.message).join('; ')}`,\n );\n }\n }\n return { widgets: options.widgets };\n}\n\n// ---------------------------------------------------------------------------\n// defineMetric\n// ---------------------------------------------------------------------------\n\nexport function defineMetric(options: MetricDef): ResolvedMetric {\n return {\n connectorId: options.connector.id,\n shape: options.shape,\n name: options.name,\n entityType: options.entityType,\n field: options.field,\n fn: options.fn,\n window: options.window,\n filter: options.filter,\n groupBy: options.groupBy,\n };\n}\n\n// ---------------------------------------------------------------------------\n// defineConfig\n// ---------------------------------------------------------------------------\n\nconst VALID_SHAPES = new Set<string>([\n 'event',\n 'entity',\n 'metric',\n 'edge',\n 'distribution',\n]);\nconst VALID_FNS = new Set<string>([\n 'count',\n 'sum',\n 'avg',\n 'min',\n 'max',\n 'latest',\n 'first',\n]);\n\nconst SAFE_KEY_RE = /^[a-zA-Z0-9_-]+$/;\n\nfunction validateConfig(config: DashboardConfig): void {\n if (config.retention) {\n const { maxAge, maxSize, floor, intervalMs } = config.retention;\n if (maxAge !== undefined && (!Number.isFinite(maxAge) || maxAge < 0)) {\n throw new Error('retention.maxAge must be a finite number >= 0');\n }\n if (maxSize !== undefined && (!Number.isInteger(maxSize) || maxSize < 0)) {\n throw new Error('retention.maxSize must be an integer >= 0');\n }\n if (floor !== undefined && (!Number.isInteger(floor) || floor < 0)) {\n throw new Error('retention.floor must be an integer >= 0');\n }\n if (\n intervalMs !== undefined &&\n (!Number.isFinite(intervalMs) || intervalMs <= 0)\n ) {\n throw new Error('retention.intervalMs must be a finite number > 0');\n }\n }\n\n if (\n !config.dashboards ||\n typeof config.dashboards !== 'object' ||\n Array.isArray(config.dashboards)\n ) {\n throw new Error(\n 'defineConfig: config must include a \"dashboards\" record — did you mean to migrate from the old flat \"widgets\" shape?',\n );\n }\n\n const connectorIds = new Set(config.connectors.map((e) => e.connector.id));\n\n for (const [dashboardKey, dashboard] of Object.entries(config.dashboards)) {\n if (\n !dashboard.widgets ||\n typeof dashboard.widgets !== 'object' ||\n Array.isArray(dashboard.widgets)\n ) {\n throw new Error(\n `Dashboard \"${dashboardKey}\" must define a \"widgets\" record`,\n );\n }\n\n if (!SAFE_KEY_RE.test(dashboardKey)) {\n throw new Error(\n `Dashboard key \"${dashboardKey}\" contains URL-unsafe characters; use only letters, digits, hyphens, and underscores`,\n );\n }\n\n for (const [widgetKey, widget] of Object.entries(dashboard.widgets)) {\n const ref = `Dashboard \"${dashboardKey}\", widget \"${widgetKey}\"`;\n\n if (!SAFE_KEY_RE.test(widgetKey)) {\n throw new Error(\n `${ref}: widget key contains URL-unsafe characters; use only letters, digits, hyphens, and underscores`,\n );\n }\n\n if (widget.kind === 'status') {\n continue;\n }\n\n const { connectorId, shape, fn } = widget.metric;\n\n if (!connectorIds.has(connectorId)) {\n throw new Error(\n `${ref}: connector \"${connectorId}\" is not listed in connectors`,\n );\n }\n\n if (!VALID_SHAPES.has(shape)) {\n throw new Error(`${ref}: invalid shape \"${shape}\"`);\n }\n\n if (!VALID_FNS.has(fn)) {\n throw new Error(`${ref}: invalid fn \"${fn}\"`);\n }\n }\n }\n}\n\nexport function defineConfig(config: DashboardConfig): DashboardConfig {\n validateConfig(config);\n return config;\n}\n","import type { Distribution, Event, Metric, StorageHandle } from './connector';\n\n// ---------------------------------------------------------------------------\n// RetentionConfig\n// ---------------------------------------------------------------------------\n\nexport interface RetentionConfig {\n maxAge?: number;\n maxSize?: number;\n floor?: number;\n intervalMs?: number;\n}\n\n// ---------------------------------------------------------------------------\n// RetentionCandidates — rows eligible for deletion across time-series shapes\n// ---------------------------------------------------------------------------\n\nexport interface RetentionCandidates {\n events: Event[];\n metrics: Metric[];\n distributions: Distribution[];\n}\n\n// ---------------------------------------------------------------------------\n// selectForDeletion — pure computation\n//\n// Receives rows pre-sorted newest-first (descending by timestamp).\n// Returns the subset that should be deleted given the policy.\n//\n// Rules applied in order:\n// 1. Rows beyond maxSize are candidates.\n// 2. Rows older than maxAge milliseconds are candidates.\n// 3. Rows within the newest `floor` positions are always kept (overrides 1 & 2).\n// ---------------------------------------------------------------------------\n\nexport function selectForDeletion<T>(\n rows: T[],\n getTs: (row: T) => number,\n config: RetentionConfig,\n nowMs: number = Date.now(),\n): T[] {\n const { maxAge, maxSize, floor = 0 } = config;\n\n if (maxAge === undefined && maxSize === undefined) {\n return [];\n }\n\n const toDelete: T[] = [];\n\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i]!;\n if (i < floor) {\n continue;\n }\n\n const overSize = maxSize !== undefined && i >= maxSize;\n const tooOld = maxAge !== undefined && getTs(row) < nowMs - maxAge;\n\n if (overSize || tooOld) {\n toDelete.push(row);\n }\n }\n\n return toDelete;\n}\n\n// ---------------------------------------------------------------------------\n// computeRetention — async, queries the handle and returns deletion candidates\n//\n// Only covers time-series shapes (events, metrics, distributions) since those\n// grow unboundedly via append. Entities and edges are upsert-keyed and do not\n// accumulate the same way.\n// ---------------------------------------------------------------------------\n\nexport async function computeRetention(\n handle: StorageHandle,\n config: RetentionConfig,\n nowMs: number = Date.now(),\n): Promise<RetentionCandidates> {\n const [events, metrics, distributions] = await Promise.all([\n handle.queryEvents({}),\n handle.queryMetrics({}),\n handle.queryDistributions({}),\n ]);\n\n const sortedEvents = [...events].sort((a, b) => b.start_ts - a.start_ts);\n const sortedMetrics = [...metrics].sort((a, b) => b.ts - a.ts);\n const sortedDistributions = [...distributions].sort((a, b) => b.ts - a.ts);\n\n return {\n events: selectForDeletion(sortedEvents, (e) => e.start_ts, config, nowMs),\n metrics: selectForDeletion(sortedMetrics, (m) => m.ts, config, nowMs),\n distributions: selectForDeletion(\n sortedDistributions,\n (d) => d.ts,\n config,\n nowMs,\n ),\n };\n}\n","import { z } from 'zod';\n\nexport type ConfigFieldsSchema = z.ZodObject<z.ZodRawShape>;\n\nexport function defineConfigFields<T extends z.ZodRawShape>(\n schema: z.ZodObject<T>,\n): z.ZodObject<T> {\n if (!(schema instanceof z.ZodObject)) {\n throw new Error(\n `configFields must be a Zod object schema (z.object({...})). Received: ${Object.prototype.toString.call(schema)}`,\n );\n }\n return schema;\n}\n","import type { ResolvedMetric } from './config';\nimport type { StorageHandle } from './connector';\n\ntype FilterClause = NonNullable<ResolvedMetric['filter']>[number];\ntype FilterCondition = Exclude<FilterClause, { or: unknown[] }>;\n\nfunction matchesCondition(\n record: Record<string, unknown>,\n cond: FilterCondition,\n): boolean {\n const val = record[cond.field];\n switch (cond.op) {\n case 'eq':\n return val === cond.value;\n case 'neq':\n return val !== cond.value;\n case 'gt':\n if (typeof val !== 'number' || typeof cond.value !== 'number') {\n return false;\n }\n return val > cond.value;\n case 'gte':\n if (typeof val !== 'number' || typeof cond.value !== 'number') {\n return false;\n }\n return val >= cond.value;\n case 'lt':\n if (typeof val !== 'number' || typeof cond.value !== 'number') {\n return false;\n }\n return val < cond.value;\n case 'lte':\n if (typeof val !== 'number' || typeof cond.value !== 'number') {\n return false;\n }\n return val <= cond.value;\n case 'contains':\n return String(val).includes(String(cond.value));\n default:\n return false;\n }\n}\n\nfunction applyFilter(\n record: Record<string, unknown>,\n filter: ResolvedMetric['filter'],\n): boolean {\n if (!filter) {\n return true;\n }\n for (const clause of filter) {\n if ('or' in clause) {\n if (!clause.or.some((cond) => matchesCondition(record, cond))) {\n return false;\n }\n } else {\n if (!matchesCondition(record, clause)) {\n return false;\n }\n }\n }\n return true;\n}\n\nconst WINDOW_MS: Record<string, number> = {\n h: 3_600_000,\n d: 86_400_000,\n w: 604_800_000,\n m: 2_592_000_000,\n};\n\nfunction parseWindowMs(window: string): number | null {\n const match = /^(\\d+)(h|d|w|m)$/.exec(window);\n if (!match) {\n return null;\n }\n const unitMs = WINDOW_MS[match[2]!];\n if (unitMs === undefined) {\n return null;\n }\n return parseInt(match[1]!) * unitMs;\n}\n\nfunction truncateToGranularity(ts: number, granularity: string): string {\n const d = new Date(ts);\n switch (granularity) {\n case 'hour':\n d.setUTCMinutes(0, 0, 0);\n return d.toISOString();\n case 'day':\n d.setUTCHours(0, 0, 0, 0);\n return d.toISOString().slice(0, 10);\n case 'week': {\n d.setUTCDate(d.getUTCDate() - d.getUTCDay());\n d.setUTCHours(0, 0, 0, 0);\n return d.toISOString().slice(0, 10);\n }\n case 'month':\n d.setUTCDate(1);\n d.setUTCHours(0, 0, 0, 0);\n return d.toISOString().slice(0, 7);\n default:\n return d.toISOString().slice(0, 10);\n }\n}\n\nfunction computeAgg(\n records: Record<string, unknown>[],\n field: string,\n fn: string,\n): unknown {\n if (fn === 'count') {\n return records.length;\n }\n if (fn === 'latest') {\n return records.at(-1)?.[field] ?? null;\n }\n if (fn === 'first') {\n return records[0]?.[field] ?? null;\n }\n const values = records\n .map((r) => r[field])\n .filter((v) => v !== undefined && v !== null);\n const nonNumeric = values.find((v) => typeof v !== 'number');\n if (nonNumeric !== undefined) {\n throw new Error(\n `computeAgg: fn \"${fn}\" requires numeric values for field \"${field}\", got ${typeof nonNumeric} (${String(nonNumeric)})`,\n );\n }\n const numbers = values as number[];\n if (fn === 'sum') {\n return numbers.reduce((a, b) => a + b, 0);\n }\n if (fn === 'avg') {\n return numbers.length > 0\n ? numbers.reduce((a, b) => a + b, 0) / numbers.length\n : null;\n }\n if (fn === 'min') {\n return numbers.length > 0\n ? numbers.reduce((a, b) => (a < b ? a : b))\n : null;\n }\n if (fn === 'max') {\n return numbers.length > 0\n ? numbers.reduce((a, b) => (a > b ? a : b))\n : null;\n }\n return null;\n}\n\nfunction sortByTs(\n records: Record<string, unknown>[],\n tsField: string,\n): Record<string, unknown>[] {\n return [...records].sort((a, b) => {\n return (a[tsField] as number) - (b[tsField] as number);\n });\n}\n\nfunction computeGroupBy(\n records: Record<string, unknown>[],\n metric: ResolvedMetric,\n tsField: string,\n): unknown {\n const { field, granularity } = metric.groupBy!;\n const groups = new Map<string, Record<string, unknown>[]>();\n\n for (const record of records) {\n const ts = record[field] as number | undefined;\n if (ts === undefined || typeof ts !== 'number') {\n continue;\n }\n const key = truncateToGranularity(ts, granularity);\n if (!groups.has(key)) {\n groups.set(key, []);\n }\n groups.get(key)!.push(record);\n }\n\n return [...groups.entries()]\n .map(([key, groupRecords]) => ({\n date: key,\n value: computeAgg(\n sortByTs(groupRecords, tsField),\n metric.field,\n metric.fn,\n ),\n }))\n .sort((a, b) => (a.date < b.date ? -1 : 1));\n}\n\nfunction getTimestampField(shape: string): string {\n switch (shape) {\n case 'event':\n return 'start_ts';\n case 'metric':\n case 'distribution':\n return 'ts';\n case 'entity':\n case 'edge':\n return 'updated_at';\n default:\n return 'start_ts';\n }\n}\n\nexport async function computeMetric(\n storage: StorageHandle,\n metric: ResolvedMetric,\n): Promise<unknown> {\n const tsField = getTimestampField(metric.shape);\n\n const windowMs = metric.window ? parseWindowMs(metric.window) : null;\n const windowStart = windowMs !== null ? Date.now() - windowMs : undefined;\n\n let records: Record<string, unknown>[];\n\n switch (metric.shape) {\n case 'event': {\n const events = await storage.queryEvents({\n name: metric.name,\n start: windowStart,\n });\n records = events.map((e) => ({\n ...e.attributes,\n name: e.name,\n start_ts: e.start_ts,\n end_ts: e.end_ts,\n }));\n break;\n }\n\n case 'entity': {\n const type = metric.entityType ?? metric.name ?? '';\n const entities = await storage.queryEntities({ type });\n records = entities.map((e) => ({\n ...e.attributes,\n type: e.type,\n id: e.id,\n updated_at: e.updated_at,\n }));\n if (windowStart !== undefined) {\n records = records.filter((r) => (r[tsField] as number) >= windowStart);\n }\n break;\n }\n\n case 'metric': {\n const metrics = await storage.queryMetrics({\n name: metric.name,\n start: windowStart,\n });\n records = metrics.map((m) => ({\n ...m.attributes,\n name: m.name,\n ts: m.ts,\n value: m.value,\n }));\n break;\n }\n\n case 'edge': {\n const edges = await storage.traverse({ kind: metric.name });\n records = edges.map((e) => ({\n ...e.attributes,\n from_type: e.from_type,\n from_id: e.from_id,\n kind: e.kind,\n to_type: e.to_type,\n to_id: e.to_id,\n updated_at: e.updated_at,\n }));\n if (windowStart !== undefined) {\n records = records.filter((r) => (r[tsField] as number) >= windowStart);\n }\n break;\n }\n\n case 'distribution': {\n const distributions = await storage.queryDistributions({\n name: metric.name,\n start: windowStart,\n });\n records = distributions.map((d) => ({\n ...d.attributes,\n name: d.name,\n ts: d.ts,\n kind: d.kind,\n data: d.data,\n }));\n break;\n }\n\n default:\n return null;\n }\n\n const filtered = records.filter((r) => applyFilter(r, metric.filter));\n const sorted = sortByTs(filtered, tsField);\n\n if (metric.groupBy) {\n return computeGroupBy(sorted, metric, tsField);\n }\n\n return computeAgg(sorted, metric.field, metric.fn);\n}\n","import { computeMetric } from './compute';\nimport type { ConnectorEntry, Widget } from './config';\nimport type { WidgetEntry } from './engine';\nimport type { ServerStorage } from './server-storage';\n\nexport async function resolveWidget(\n id: string,\n widget: Widget,\n connectors: ConnectorEntry[],\n storage: ServerStorage,\n): Promise<WidgetEntry | undefined> {\n if (widget.kind === 'status') {\n return {\n id,\n widgetId: id,\n connectorId: widget.source,\n data: null,\n cachedAt: null,\n };\n }\n const { connectorId } = widget.metric;\n const connectorEntry = connectors.find((e) => e.connector.id === connectorId);\n if (!connectorEntry) {\n return undefined;\n }\n const handle = storage.getStorageHandle(connectorId);\n const data = await computeMetric(handle, widget.metric);\n return {\n id,\n widgetId: id,\n connectorId,\n data,\n cachedAt: (await storage.getSyncState()).lastSyncAt,\n };\n}\n","import type {\n Distribution,\n DistributionQuery,\n Edge,\n EdgeQuery,\n Entity,\n EntityQuery,\n Event,\n EventQuery,\n Metric,\n MetricQuery,\n StorageHandle,\n} from './connector';\nimport type { SyncState } from './engine';\nimport type { ServerStorage } from './server-storage';\n\nexport class InMemoryStorage implements ServerStorage {\n private eventStore = new Map<string, Event[]>();\n private entityStore = new Map<string, Map<string, Map<string, Entity>>>();\n private metricStore = new Map<string, Metric[]>();\n private edgeStore = new Map<string, Edge[]>();\n private distributionStore = new Map<string, Distribution[]>();\n private syncState: SyncState = {\n status: 'idle',\n lastSyncAt: null,\n lastError: null,\n };\n\n getStorageHandle(connectorId: string): StorageHandle {\n const getEntityMap = (): Map<string, Map<string, Entity>> => {\n if (!this.entityStore.has(connectorId)) {\n this.entityStore.set(connectorId, new Map());\n }\n return this.entityStore.get(connectorId)!;\n };\n\n const upsertEntities = (es: Entity[]): void => {\n const byType = getEntityMap();\n for (const e of es) {\n if (!byType.has(e.type)) {\n byType.set(e.type, new Map());\n }\n byType.get(e.type)!.set(e.id, e);\n }\n };\n\n const upsertEdges = (es: Edge[]): void => {\n const existing = this.edgeStore.get(connectorId) ?? [];\n const index = new Map<string, number>();\n for (let i = 0; i < existing.length; i++) {\n const e = existing[i]!;\n index.set(\n `${e.from_type}:${e.from_id}:${e.kind}:${e.to_type}:${e.to_id}`,\n i,\n );\n }\n for (const e of es) {\n const key = `${e.from_type}:${e.from_id}:${e.kind}:${e.to_type}:${e.to_id}`;\n const idx = index.get(key);\n if (idx !== undefined) {\n existing[idx] = e;\n } else {\n index.set(key, existing.length);\n existing.push(e);\n }\n }\n this.edgeStore.set(connectorId, existing);\n };\n\n return {\n event: async (e) => {\n if (!this.eventStore.has(connectorId)) {\n this.eventStore.set(connectorId, []);\n }\n this.eventStore.get(connectorId)!.push(e);\n },\n\n entity: async (e) => {\n upsertEntities([e]);\n },\n\n metric: async (m) => {\n if (!this.metricStore.has(connectorId)) {\n this.metricStore.set(connectorId, []);\n }\n this.metricStore.get(connectorId)!.push(m);\n },\n\n edge: async (e) => {\n upsertEdges([e]);\n },\n\n distribution: async (d) => {\n if (!this.distributionStore.has(connectorId)) {\n this.distributionStore.set(connectorId, []);\n }\n this.distributionStore.get(connectorId)!.push(d);\n },\n\n events: async (es, scope) => {\n const names = new Set(scope?.names ?? es.map((e) => e.name));\n const kept = (this.eventStore.get(connectorId) ?? []).filter(\n (e) => !names.has(e.name),\n );\n this.eventStore.set(connectorId, [...kept, ...es]);\n },\n\n entities: async (es, scope) => {\n const byType = getEntityMap();\n const types = new Set(scope?.types ?? es.map((e) => e.type));\n for (const type of types) {\n byType.set(type, new Map());\n }\n upsertEntities(es);\n },\n\n metrics: async (ms, scope) => {\n const names = new Set(scope?.names ?? ms.map((m) => m.name));\n const kept = (this.metricStore.get(connectorId) ?? []).filter(\n (m) => !names.has(m.name),\n );\n this.metricStore.set(connectorId, [...kept, ...ms]);\n },\n\n edges: async (es, scope) => {\n const kinds = new Set(scope?.kinds ?? es.map((e) => e.kind));\n const kept = (this.edgeStore.get(connectorId) ?? []).filter(\n (e) => !kinds.has(e.kind),\n );\n this.edgeStore.set(connectorId, kept);\n upsertEdges(es);\n },\n\n distributions: async (ds, scope) => {\n const names = new Set(scope?.names ?? ds.map((d) => d.name));\n const kept = (this.distributionStore.get(connectorId) ?? []).filter(\n (d) => !names.has(d.name),\n );\n this.distributionStore.set(connectorId, [...kept, ...ds]);\n },\n\n queryEvents: async (q: EventQuery) => {\n let results = this.eventStore.get(connectorId) ?? [];\n if (q.name !== undefined) {\n results = results.filter((e) => e.name === q.name);\n }\n if (q.start !== undefined) {\n results = results.filter((e) => e.start_ts >= q.start!);\n }\n if (q.end !== undefined) {\n results = results.filter((e) => e.start_ts <= q.end!);\n }\n return results;\n },\n\n getEntity: async (type: string, id: string) => {\n return getEntityMap().get(type)?.get(id) ?? null;\n },\n\n queryEntities: async (q: EntityQuery) => {\n const byType = getEntityMap().get(q.type);\n if (!byType) {\n return [];\n }\n return Array.from(byType.values());\n },\n\n queryMetrics: async (q: MetricQuery) => {\n let results = this.metricStore.get(connectorId) ?? [];\n if (q.name !== undefined) {\n results = results.filter((m) => m.name === q.name);\n }\n if (q.start !== undefined) {\n results = results.filter((m) => m.ts >= q.start!);\n }\n if (q.end !== undefined) {\n results = results.filter((m) => m.ts <= q.end!);\n }\n return results;\n },\n\n traverse: async (q: EdgeQuery) => {\n let results = this.edgeStore.get(connectorId) ?? [];\n if (q.fromType !== undefined) {\n results = results.filter((e) => e.from_type === q.fromType);\n }\n if (q.fromId !== undefined) {\n results = results.filter((e) => e.from_id === q.fromId);\n }\n if (q.kind !== undefined) {\n results = results.filter((e) => e.kind === q.kind);\n }\n if (q.toType !== undefined) {\n results = results.filter((e) => e.to_type === q.toType);\n }\n if (q.toId !== undefined) {\n results = results.filter((e) => e.to_id === q.toId);\n }\n return results;\n },\n\n queryDistributions: async (q: DistributionQuery) => {\n let results = this.distributionStore.get(connectorId) ?? [];\n if (q.name !== undefined) {\n results = results.filter((d) => d.name === q.name);\n }\n if (q.start !== undefined) {\n results = results.filter((d) => d.ts >= q.start!);\n }\n if (q.end !== undefined) {\n results = results.filter((d) => d.ts <= q.end!);\n }\n return results;\n },\n\n deleteOlderThan: async (shape, tsUnixMs) => {\n if (shape === 'events') {\n const before = this.eventStore.get(connectorId) ?? [];\n const after = before.filter((e) => e.start_ts >= tsUnixMs);\n this.eventStore.set(connectorId, after);\n return { rowsDeleted: before.length - after.length };\n } else if (shape === 'metrics') {\n const before = this.metricStore.get(connectorId) ?? [];\n const after = before.filter((m) => m.ts >= tsUnixMs);\n this.metricStore.set(connectorId, after);\n return { rowsDeleted: before.length - after.length };\n } else if (shape === 'distributions') {\n const before = this.distributionStore.get(connectorId) ?? [];\n const after = before.filter((d) => d.ts >= tsUnixMs);\n this.distributionStore.set(connectorId, after);\n return { rowsDeleted: before.length - after.length };\n } else {\n throw new Error(\n `Unsupported shape for deleteOlderThan: ${String(shape)}`,\n );\n }\n },\n };\n }\n\n async getSyncState(): Promise<SyncState> {\n return { ...this.syncState };\n }\n\n async setSyncing(): Promise<boolean> {\n if (this.syncState.status === 'syncing') {\n return false;\n }\n this.syncState = { ...this.syncState, status: 'syncing' };\n return true;\n }\n\n async setSyncSuccess(): Promise<void> {\n this.syncState = {\n status: 'idle',\n lastSyncAt: new Date().toISOString(),\n lastError: null,\n };\n }\n\n async setSyncError(error: string): Promise<void> {\n this.syncState = {\n status: 'error',\n lastSyncAt: this.syncState.lastSyncAt,\n lastError: error,\n };\n }\n}\n"],"mappings":";AAEO,SAAS,OAAO,MAAyB;AAC9C,MAAI,CAAC,oBAAoB,KAAK,IAAI,GAAG;AACnC,UAAM,IAAI;AAAA,MACR,wBAAwB,IAAI;AAAA,IAE9B;AAAA,EACF;AACA,SAAO,EAAE,SAAS,KAAK;AACzB;AAEO,SAAS,YAAY,OAAoC;AAC9D,SACE,OAAO,UAAU,YACjB,UAAU,QACV,aAAa,SACb,OAAQ,MAAoB,YAAY;AAE5C;AAMO,IAAM,qBAAN,MAAoD;AAAA,EACzD,QAAQ,MAAkC;AACxC,UAAM,MACJ,WACA,SAAS;AACX,WAAO,MAAM,IAAI;AAAA,EACnB;AACF;AAEO,SAAS,kBAAqB,KAAQ,UAA8B;AACzE,MAAI,YAAY,GAAG,GAAG;AACpB,UAAM,OAAO,IAAI;AACjB,UAAM,QAAQ,SAAS,QAAQ,IAAI;AACnC,QAAI,UAAU,QAAW;AACvB,YAAM,IAAI;AAAA,QACR,mBAAmB,IAAI,6BAA6B,IAAI,oCAAoC,IAAI;AAAA,MAClG;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,WAAO,IAAI,IAAI,CAAC,SAAS,kBAAkB,MAAM,QAAQ,CAAC;AAAA,EAC5D;AACA,MAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC3C,UAAM,SAAkC,CAAC;AACzC,eAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,GAAa,GAAG;AACtD,aAAO,eAAe,QAAQ,KAAK;AAAA,QACjC,OAAO,kBAAkB,KAAK,QAAQ;AAAA,QACtC,YAAY;AAAA,QACZ,cAAc;AAAA,QACd,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;;;ACsIO,IAAe,gBAAf,MAGgB;AAAA,EAEZ;AAAA,EAEC;AAAA,EACA;AAAA,EACF;AAAA,EAER,YAAY,UAAqB,OAAsC;AACrE,SAAK,WAAW;AAChB,SAAK,eAAe;AACpB,SAAK,QAAQ,QACR;AAAA,MACC;AAAA,MACA,IAAI,mBAAmB;AAAA,IACzB,IACC,CAAC;AAAA,EACR;AAAA,EAEA,kBAA2C;AACzC,UAAM,SAAkC;AAAA,MACtC,GAAI,KAAK;AAAA,IACX;AACA,QAAI,KAAK,cAAc;AACrB,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO;AAAA,QAChC,KAAK;AAAA,MACP,GAAG;AACD,YAAI,UAAU,QAAW;AACvB,iBAAO,GAAG,IAAI;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEU,MAAM,IAAY,QAAqC;AAC/D,QAAI,QAAQ,SAAS;AACnB,aAAO,QAAQ,OAAO,OAAO,UAAU,IAAI,MAAM,SAAS,CAAC;AAAA,IAC7D;AACA,WAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAC5C,YAAM,UAAU,MAAM;AACpB,qBAAa,KAAK;AAClB,eAAO,OAAQ,UAAU,IAAI,MAAM,SAAS,CAAC;AAAA,MAC/C;AACA,YAAM,QAAQ,WAAW,MAAM;AAC7B,gBAAQ,oBAAoB,SAAS,OAAO;AAC5C,gBAAQ;AAAA,MACV,GAAG,EAAE;AACL,cAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,IAC3D,CAAC;AAAA,EACH;AAAA,EAEA,MAAgB,UACd,IAGA,SACmB;AACnB,UAAM;AAAA,MACJ,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,aAAa;AAAA,MACb;AAAA,IACF,IAAI,WAAW,CAAC;AAEhB,aAAS,UAAU,GAAG,UAAU,aAAa,WAAW;AACtD,cAAQ,eAAe;AACvB,YAAM,SAAS,MAAM,GAAG,MAAM;AAC9B,UAAI,OAAO,WAAW,QAAQ;AAC5B,eAAO,OAAO;AAAA,MAChB;AACA,UAAI,UAAU,cAAc,GAAG;AAC7B,cAAM,QAAQ,KAAK,IAAI,iBAAiB,KAAK,SAAS,UAAU;AAChE,cAAM,KAAK,MAAM,OAAO,MAAM;AAAA,MAChC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAOF;AAEO,SAAS,kBAA6B;AAC3C,SAAO,SAEL,KAaA;AAAA,IACA,MAAM,yBAAyB,cAAiC;AAAA,MAC9D,OAAgB,KAAK,IAAI;AAAA,MACzB,OAAgB,cAAc,IAAI;AAAA,MAEzB,KAAK,IAAI;AAAA,MACA,cAAc,IAAI;AAAA,MAEpC,MAAM,KACJ,SACA,SACA,QACe;AACf,eAAO,IAAI,KAAK;AAAA,UACd,EAAE,UAAU,KAAK,UAAU,OAAO,KAAK,MAAM;AAAA,UAC7C;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EAQT;AACF;;;AC5UA,SAAS,SAAS;AAEX,IAAM,cAAc,EAAE,KAAK;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,IAAM,cAAc,EAAE,KAAK;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,IAAM,uBAAuB,EAAE,KAAK;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,IAAM,wBAAwB,EAAE,OAAO;AAAA,EAC5C,OAAO,EAAE,OAAO;AAAA,EAChB,IAAI;AAAA,EACJ,OAAO,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,CAAC;AACtD,CAAC;AAEM,IAAM,qBAAqB,EAAE,MAAM;AAAA,EACxC;AAAA,EACA,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,EAAE,CAAC;AACjD,CAAC;AAEM,IAAM,gBAAgB,EAAE,OAAO;AAAA,EACpC,OAAO,EAAE,OAAO;AAAA,EAChB,aAAa,EAAE,KAAK,CAAC,QAAQ,OAAO,QAAQ,OAAO,CAAC;AACtD,CAAC;AAEM,IAAM,uBAAuB,EAAE,OAAO;AAAA,EAC3C,aAAa,EAAE,OAAO;AAAA,EACtB,OAAO;AAAA,EACP,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,EAChC,OAAO,EAAE,OAAO;AAAA,EAChB,IAAI,EAAE,OAAO;AAAA,EACb,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,QAAQ,EAAE,MAAM,kBAAkB,EAAE,SAAS;AAAA,EAC7C,SAAS,cAAc,SAAS;AAClC,CAAC;AAED,IAAM,aAAa,EAChB,OAAO,EACP,KAAK,EAAE,OAAO,SAAS,aAAa,gBAAgB,CAAC;AAEjD,IAAM,mBAAmB,EAAE,OAAO;AAAA,EACvC,MAAM,EAAE,QAAQ,MAAM;AAAA,EACtB,OAAO;AAAA,EACP,QAAQ,qBAAqB,KAAK;AAAA,IAChC,OAAO;AAAA,IACP,aAAa;AAAA,EACf,CAAC;AAAA,EACD,QAAQ,EACL,OAAO,EACP,SAAS,EACT,KAAK,EAAE,OAAO,UAAU,aAAa,0BAA0B,CAAC;AAAA,EACnE,SAAS,EACN,KAAK,CAAC,QAAQ,iBAAiB,CAAC,EAChC,QAAQ,MAAM,EACd,KAAK,EAAE,OAAO,WAAW,aAAa,mBAAmB,CAAC;AAC/D,CAAC;AAEM,IAAM,qBAAqB,EAAE,OAAO;AAAA,EACzC,MAAM,EAAE,QAAQ,QAAQ;AAAA,EACxB,OAAO;AAAA,EACP,QAAQ,EAAE,OAAO,EAAE,KAAK;AAAA,IACtB,OAAO;AAAA,IACP,aAAa;AAAA,EACf,CAAC;AACH,CAAC;AAEM,IAAM,yBAAyB,EAAE,OAAO;AAAA,EAC7C,MAAM,EAAE,QAAQ,YAAY;AAAA,EAC5B,OAAO;AAAA,EACP,QAAQ,qBAAqB,KAAK;AAAA,IAChC,OAAO;AAAA,IACP,aAAa;AAAA,EACf,CAAC;AAAA,EACD,QAAQ,EACL,OAAO,EACP,KAAK,EAAE,OAAO,UAAU,aAAa,2BAA2B,CAAC;AAAA,EACpE,aAAa,EACV,KAAK,CAAC,QAAQ,OAAO,MAAM,CAAC,EAC5B,QAAQ,KAAK,EACb,KAAK,EAAE,OAAO,eAAe,aAAa,oBAAoB,CAAC;AACpE,CAAC;AAEM,IAAM,2BAA2B,EAAE,OAAO;AAAA,EAC/C,MAAM,EAAE,QAAQ,cAAc;AAAA,EAC9B,OAAO;AAAA,EACP,QAAQ,qBAAqB,KAAK;AAAA,IAChC,OAAO;AAAA,IACP,aAAa;AAAA,EACf,CAAC;AAAA,EACD,QAAQ,EACL,OAAO,EACP,KAAK,EAAE,OAAO,UAAU,aAAa,0BAA0B,CAAC;AACrE,CAAC;AAEM,IAAM,gBAAgB;AAAA,EAC3B,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,cAAc;AAChB;AAEO,IAAM,eAAe,EAAE,mBAAmB,QAAQ;AAAA,EACvD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAIM,SAAS,gBAAgB,MAAkB;AAChD,SAAO,cAAc,IAAI;AAC3B;;;ACWA,IAAM,qBAAqB,IAAI,IAAY,OAAO,KAAK,aAAa,CAAC;AAE9D,SAAS,gBAAgB,SAElB;AACZ,aAAW,CAAC,KAAK,MAAM,KAAK,OAAO,QAAQ,QAAQ,OAAO,GAAG;AAC3D,QAAI,CAAC,mBAAmB,IAAI,OAAO,IAAI,GAAG;AACxC,YAAM,IAAI;AAAA,QACR,WAAW,GAAG,oBAAoB,OAAO,IAAI,sBAAsB,CAAC,GAAG,kBAAkB,EAAE,KAAK,IAAI,CAAC;AAAA,MACvG;AAAA,IACF;AACA,UAAM,SAAS,gBAAgB,OAAO,IAAkB;AACxD,UAAM,SAAS,OAAO,UAAU,MAAM;AACtC,QAAI,CAAC,OAAO,SAAS;AACnB,YAAM,IAAI;AAAA,QACR,WAAW,GAAG,YAAY,OAAO,IAAI,OAAO,OAAO,MAAM,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,MAClG;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,SAAS,QAAQ,QAAQ;AACpC;AAMO,SAAS,aAAa,SAAoC;AAC/D,SAAO;AAAA,IACL,aAAa,QAAQ,UAAU;AAAA,IAC/B,OAAO,QAAQ;AAAA,IACf,MAAM,QAAQ;AAAA,IACd,YAAY,QAAQ;AAAA,IACpB,OAAO,QAAQ;AAAA,IACf,IAAI,QAAQ;AAAA,IACZ,QAAQ,QAAQ;AAAA,IAChB,QAAQ,QAAQ;AAAA,IAChB,SAAS,QAAQ;AAAA,EACnB;AACF;AAMA,IAAM,eAAe,oBAAI,IAAY;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,IAAM,YAAY,oBAAI,IAAY;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,cAAc;AAEpB,SAAS,eAAe,QAA+B;AACrD,MAAI,OAAO,WAAW;AACpB,UAAM,EAAE,QAAQ,SAAS,OAAO,WAAW,IAAI,OAAO;AACtD,QAAI,WAAW,WAAc,CAAC,OAAO,SAAS,MAAM,KAAK,SAAS,IAAI;AACpE,YAAM,IAAI,MAAM,+CAA+C;AAAA,IACjE;AACA,QAAI,YAAY,WAAc,CAAC,OAAO,UAAU,OAAO,KAAK,UAAU,IAAI;AACxE,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC7D;AACA,QAAI,UAAU,WAAc,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,IAAI;AAClE,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC3D;AACA,QACE,eAAe,WACd,CAAC,OAAO,SAAS,UAAU,KAAK,cAAc,IAC/C;AACA,YAAM,IAAI,MAAM,kDAAkD;AAAA,IACpE;AAAA,EACF;AAEA,MACE,CAAC,OAAO,cACR,OAAO,OAAO,eAAe,YAC7B,MAAM,QAAQ,OAAO,UAAU,GAC/B;AACA,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,eAAe,IAAI,IAAI,OAAO,WAAW,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC;AAEzE,aAAW,CAAC,cAAc,SAAS,KAAK,OAAO,QAAQ,OAAO,UAAU,GAAG;AACzE,QACE,CAAC,UAAU,WACX,OAAO,UAAU,YAAY,YAC7B,MAAM,QAAQ,UAAU,OAAO,GAC/B;AACA,YAAM,IAAI;AAAA,QACR,cAAc,YAAY;AAAA,MAC5B;AAAA,IACF;AAEA,QAAI,CAAC,YAAY,KAAK,YAAY,GAAG;AACnC,YAAM,IAAI;AAAA,QACR,kBAAkB,YAAY;AAAA,MAChC;AAAA,IACF;AAEA,eAAW,CAAC,WAAW,MAAM,KAAK,OAAO,QAAQ,UAAU,OAAO,GAAG;AACnE,YAAM,MAAM,cAAc,YAAY,cAAc,SAAS;AAE7D,UAAI,CAAC,YAAY,KAAK,SAAS,GAAG;AAChC,cAAM,IAAI;AAAA,UACR,GAAG,GAAG;AAAA,QACR;AAAA,MACF;AAEA,UAAI,OAAO,SAAS,UAAU;AAC5B;AAAA,MACF;AAEA,YAAM,EAAE,aAAa,OAAO,GAAG,IAAI,OAAO;AAE1C,UAAI,CAAC,aAAa,IAAI,WAAW,GAAG;AAClC,cAAM,IAAI;AAAA,UACR,GAAG,GAAG,gBAAgB,WAAW;AAAA,QACnC;AAAA,MACF;AAEA,UAAI,CAAC,aAAa,IAAI,KAAK,GAAG;AAC5B,cAAM,IAAI,MAAM,GAAG,GAAG,oBAAoB,KAAK,GAAG;AAAA,MACpD;AAEA,UAAI,CAAC,UAAU,IAAI,EAAE,GAAG;AACtB,cAAM,IAAI,MAAM,GAAG,GAAG,iBAAiB,EAAE,GAAG;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,aAAa,QAA0C;AACrE,iBAAe,MAAM;AACrB,SAAO;AACT;;;ACjQO,SAAS,kBACd,MACA,OACA,QACA,QAAgB,KAAK,IAAI,GACpB;AACL,QAAM,EAAE,QAAQ,SAAS,QAAQ,EAAE,IAAI;AAEvC,MAAI,WAAW,UAAa,YAAY,QAAW;AACjD,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,WAAgB,CAAC;AAEvB,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,IAAI,OAAO;AACb;AAAA,IACF;AAEA,UAAM,WAAW,YAAY,UAAa,KAAK;AAC/C,UAAM,SAAS,WAAW,UAAa,MAAM,GAAG,IAAI,QAAQ;AAE5D,QAAI,YAAY,QAAQ;AACtB,eAAS,KAAK,GAAG;AAAA,IACnB;AAAA,EACF;AAEA,SAAO;AACT;AAUA,eAAsB,iBACpB,QACA,QACA,QAAgB,KAAK,IAAI,GACK;AAC9B,QAAM,CAAC,QAAQ,SAAS,aAAa,IAAI,MAAM,QAAQ,IAAI;AAAA,IACzD,OAAO,YAAY,CAAC,CAAC;AAAA,IACrB,OAAO,aAAa,CAAC,CAAC;AAAA,IACtB,OAAO,mBAAmB,CAAC,CAAC;AAAA,EAC9B,CAAC;AAED,QAAM,eAAe,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AACvE,QAAM,gBAAgB,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,EAAE;AAC7D,QAAM,sBAAsB,CAAC,GAAG,aAAa,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,EAAE,EAAE;AAEzE,SAAO;AAAA,IACL,QAAQ,kBAAkB,cAAc,CAAC,MAAM,EAAE,UAAU,QAAQ,KAAK;AAAA,IACxE,SAAS,kBAAkB,eAAe,CAAC,MAAM,EAAE,IAAI,QAAQ,KAAK;AAAA,IACpE,eAAe;AAAA,MACb;AAAA,MACA,CAAC,MAAM,EAAE;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;ACnGA,SAAS,KAAAA,UAAS;AAIX,SAAS,mBACd,QACgB;AAChB,MAAI,EAAE,kBAAkBA,GAAE,YAAY;AACpC,UAAM,IAAI;AAAA,MACR,yEAAyE,OAAO,UAAU,SAAS,KAAK,MAAM,CAAC;AAAA,IACjH;AAAA,EACF;AACA,SAAO;AACT;;;ACPA,SAAS,iBACP,QACA,MACS;AACT,QAAM,MAAM,OAAO,KAAK,KAAK;AAC7B,UAAQ,KAAK,IAAI;AAAA,IACf,KAAK;AACH,aAAO,QAAQ,KAAK;AAAA,IACtB,KAAK;AACH,aAAO,QAAQ,KAAK;AAAA,IACtB,KAAK;AACH,UAAI,OAAO,QAAQ,YAAY,OAAO,KAAK,UAAU,UAAU;AAC7D,eAAO;AAAA,MACT;AACA,aAAO,MAAM,KAAK;AAAA,IACpB,KAAK;AACH,UAAI,OAAO,QAAQ,YAAY,OAAO,KAAK,UAAU,UAAU;AAC7D,eAAO;AAAA,MACT;AACA,aAAO,OAAO,KAAK;AAAA,IACrB,KAAK;AACH,UAAI,OAAO,QAAQ,YAAY,OAAO,KAAK,UAAU,UAAU;AAC7D,eAAO;AAAA,MACT;AACA,aAAO,MAAM,KAAK;AAAA,IACpB,KAAK;AACH,UAAI,OAAO,QAAQ,YAAY,OAAO,KAAK,UAAU,UAAU;AAC7D,eAAO;AAAA,MACT;AACA,aAAO,OAAO,KAAK;AAAA,IACrB,KAAK;AACH,aAAO,OAAO,GAAG,EAAE,SAAS,OAAO,KAAK,KAAK,CAAC;AAAA,IAChD;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,YACP,QACA,QACS;AACT,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AACA,aAAW,UAAU,QAAQ;AAC3B,QAAI,QAAQ,QAAQ;AAClB,UAAI,CAAC,OAAO,GAAG,KAAK,CAAC,SAAS,iBAAiB,QAAQ,IAAI,CAAC,GAAG;AAC7D,eAAO;AAAA,MACT;AAAA,IACF,OAAO;AACL,UAAI,CAAC,iBAAiB,QAAQ,MAAM,GAAG;AACrC,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,IAAM,YAAoC;AAAA,EACxC,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACL;AAEA,SAAS,cAAc,QAA+B;AACpD,QAAM,QAAQ,mBAAmB,KAAK,MAAM;AAC5C,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AACA,QAAM,SAAS,UAAU,MAAM,CAAC,CAAE;AAClC,MAAI,WAAW,QAAW;AACxB,WAAO;AAAA,EACT;AACA,SAAO,SAAS,MAAM,CAAC,CAAE,IAAI;AAC/B;AAEA,SAAS,sBAAsB,IAAY,aAA6B;AACtE,QAAM,IAAI,IAAI,KAAK,EAAE;AACrB,UAAQ,aAAa;AAAA,IACnB,KAAK;AACH,QAAE,cAAc,GAAG,GAAG,CAAC;AACvB,aAAO,EAAE,YAAY;AAAA,IACvB,KAAK;AACH,QAAE,YAAY,GAAG,GAAG,GAAG,CAAC;AACxB,aAAO,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AAAA,IACpC,KAAK,QAAQ;AACX,QAAE,WAAW,EAAE,WAAW,IAAI,EAAE,UAAU,CAAC;AAC3C,QAAE,YAAY,GAAG,GAAG,GAAG,CAAC;AACxB,aAAO,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AAAA,IACpC;AAAA,IACA,KAAK;AACH,QAAE,WAAW,CAAC;AACd,QAAE,YAAY,GAAG,GAAG,GAAG,CAAC;AACxB,aAAO,EAAE,YAAY,EAAE,MAAM,GAAG,CAAC;AAAA,IACnC;AACE,aAAO,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AAAA,EACtC;AACF;AAEA,SAAS,WACP,SACA,OACA,IACS;AACT,MAAI,OAAO,SAAS;AAClB,WAAO,QAAQ;AAAA,EACjB;AACA,MAAI,OAAO,UAAU;AACnB,WAAO,QAAQ,GAAG,EAAE,IAAI,KAAK,KAAK;AAAA,EACpC;AACA,MAAI,OAAO,SAAS;AAClB,WAAO,QAAQ,CAAC,IAAI,KAAK,KAAK;AAAA,EAChC;AACA,QAAM,SAAS,QACZ,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,CAAC,MAAM,MAAM,UAAa,MAAM,IAAI;AAC9C,QAAM,aAAa,OAAO,KAAK,CAAC,MAAM,OAAO,MAAM,QAAQ;AAC3D,MAAI,eAAe,QAAW;AAC5B,UAAM,IAAI;AAAA,MACR,mBAAmB,EAAE,wCAAwC,KAAK,UAAU,OAAO,UAAU,KAAK,OAAO,UAAU,CAAC;AAAA,IACtH;AAAA,EACF;AACA,QAAM,UAAU;AAChB,MAAI,OAAO,OAAO;AAChB,WAAO,QAAQ,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC;AAAA,EAC1C;AACA,MAAI,OAAO,OAAO;AAChB,WAAO,QAAQ,SAAS,IACpB,QAAQ,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,QAAQ,SAC7C;AAAA,EACN;AACA,MAAI,OAAO,OAAO;AAChB,WAAO,QAAQ,SAAS,IACpB,QAAQ,OAAO,CAAC,GAAG,MAAO,IAAI,IAAI,IAAI,CAAE,IACxC;AAAA,EACN;AACA,MAAI,OAAO,OAAO;AAChB,WAAO,QAAQ,SAAS,IACpB,QAAQ,OAAO,CAAC,GAAG,MAAO,IAAI,IAAI,IAAI,CAAE,IACxC;AAAA,EACN;AACA,SAAO;AACT;AAEA,SAAS,SACP,SACA,SAC2B;AAC3B,SAAO,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM;AACjC,WAAQ,EAAE,OAAO,IAAgB,EAAE,OAAO;AAAA,EAC5C,CAAC;AACH;AAEA,SAAS,eACP,SACA,QACA,SACS;AACT,QAAM,EAAE,OAAO,YAAY,IAAI,OAAO;AACtC,QAAM,SAAS,oBAAI,IAAuC;AAE1D,aAAW,UAAU,SAAS;AAC5B,UAAM,KAAK,OAAO,KAAK;AACvB,QAAI,OAAO,UAAa,OAAO,OAAO,UAAU;AAC9C;AAAA,IACF;AACA,UAAM,MAAM,sBAAsB,IAAI,WAAW;AACjD,QAAI,CAAC,OAAO,IAAI,GAAG,GAAG;AACpB,aAAO,IAAI,KAAK,CAAC,CAAC;AAAA,IACpB;AACA,WAAO,IAAI,GAAG,EAAG,KAAK,MAAM;AAAA,EAC9B;AAEA,SAAO,CAAC,GAAG,OAAO,QAAQ,CAAC,EACxB,IAAI,CAAC,CAAC,KAAK,YAAY,OAAO;AAAA,IAC7B,MAAM;AAAA,IACN,OAAO;AAAA,MACL,SAAS,cAAc,OAAO;AAAA,MAC9B,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,EACF,EAAE,EACD,KAAK,CAAC,GAAG,MAAO,EAAE,OAAO,EAAE,OAAO,KAAK,CAAE;AAC9C;AAEA,SAAS,kBAAkB,OAAuB;AAChD,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,eAAsB,cACpB,SACA,QACkB;AAClB,QAAM,UAAU,kBAAkB,OAAO,KAAK;AAE9C,QAAM,WAAW,OAAO,SAAS,cAAc,OAAO,MAAM,IAAI;AAChE,QAAM,cAAc,aAAa,OAAO,KAAK,IAAI,IAAI,WAAW;AAEhE,MAAI;AAEJ,UAAQ,OAAO,OAAO;AAAA,IACpB,KAAK,SAAS;AACZ,YAAM,SAAS,MAAM,QAAQ,YAAY;AAAA,QACvC,MAAM,OAAO;AAAA,QACb,OAAO;AAAA,MACT,CAAC;AACD,gBAAU,OAAO,IAAI,CAAC,OAAO;AAAA,QAC3B,GAAG,EAAE;AAAA,QACL,MAAM,EAAE;AAAA,QACR,UAAU,EAAE;AAAA,QACZ,QAAQ,EAAE;AAAA,MACZ,EAAE;AACF;AAAA,IACF;AAAA,IAEA,KAAK,UAAU;AACb,YAAM,OAAO,OAAO,cAAc,OAAO,QAAQ;AACjD,YAAM,WAAW,MAAM,QAAQ,cAAc,EAAE,KAAK,CAAC;AACrD,gBAAU,SAAS,IAAI,CAAC,OAAO;AAAA,QAC7B,GAAG,EAAE;AAAA,QACL,MAAM,EAAE;AAAA,QACR,IAAI,EAAE;AAAA,QACN,YAAY,EAAE;AAAA,MAChB,EAAE;AACF,UAAI,gBAAgB,QAAW;AAC7B,kBAAU,QAAQ,OAAO,CAAC,MAAO,EAAE,OAAO,KAAgB,WAAW;AAAA,MACvE;AACA;AAAA,IACF;AAAA,IAEA,KAAK,UAAU;AACb,YAAM,UAAU,MAAM,QAAQ,aAAa;AAAA,QACzC,MAAM,OAAO;AAAA,QACb,OAAO;AAAA,MACT,CAAC;AACD,gBAAU,QAAQ,IAAI,CAAC,OAAO;AAAA,QAC5B,GAAG,EAAE;AAAA,QACL,MAAM,EAAE;AAAA,QACR,IAAI,EAAE;AAAA,QACN,OAAO,EAAE;AAAA,MACX,EAAE;AACF;AAAA,IACF;AAAA,IAEA,KAAK,QAAQ;AACX,YAAM,QAAQ,MAAM,QAAQ,SAAS,EAAE,MAAM,OAAO,KAAK,CAAC;AAC1D,gBAAU,MAAM,IAAI,CAAC,OAAO;AAAA,QAC1B,GAAG,EAAE;AAAA,QACL,WAAW,EAAE;AAAA,QACb,SAAS,EAAE;AAAA,QACX,MAAM,EAAE;AAAA,QACR,SAAS,EAAE;AAAA,QACX,OAAO,EAAE;AAAA,QACT,YAAY,EAAE;AAAA,MAChB,EAAE;AACF,UAAI,gBAAgB,QAAW;AAC7B,kBAAU,QAAQ,OAAO,CAAC,MAAO,EAAE,OAAO,KAAgB,WAAW;AAAA,MACvE;AACA;AAAA,IACF;AAAA,IAEA,KAAK,gBAAgB;AACnB,YAAM,gBAAgB,MAAM,QAAQ,mBAAmB;AAAA,QACrD,MAAM,OAAO;AAAA,QACb,OAAO;AAAA,MACT,CAAC;AACD,gBAAU,cAAc,IAAI,CAAC,OAAO;AAAA,QAClC,GAAG,EAAE;AAAA,QACL,MAAM,EAAE;AAAA,QACR,IAAI,EAAE;AAAA,QACN,MAAM,EAAE;AAAA,QACR,MAAM,EAAE;AAAA,MACV,EAAE;AACF;AAAA,IACF;AAAA,IAEA;AACE,aAAO;AAAA,EACX;AAEA,QAAM,WAAW,QAAQ,OAAO,CAAC,MAAM,YAAY,GAAG,OAAO,MAAM,CAAC;AACpE,QAAM,SAAS,SAAS,UAAU,OAAO;AAEzC,MAAI,OAAO,SAAS;AAClB,WAAO,eAAe,QAAQ,QAAQ,OAAO;AAAA,EAC/C;AAEA,SAAO,WAAW,QAAQ,OAAO,OAAO,OAAO,EAAE;AACnD;;;AC7SA,eAAsB,cACpB,IACA,QACA,YACA,SACkC;AAClC,MAAI,OAAO,SAAS,UAAU;AAC5B,WAAO;AAAA,MACL;AAAA,MACA,UAAU;AAAA,MACV,aAAa,OAAO;AAAA,MACpB,MAAM;AAAA,MACN,UAAU;AAAA,IACZ;AAAA,EACF;AACA,QAAM,EAAE,YAAY,IAAI,OAAO;AAC/B,QAAM,iBAAiB,WAAW,KAAK,CAAC,MAAM,EAAE,UAAU,OAAO,WAAW;AAC5E,MAAI,CAAC,gBAAgB;AACnB,WAAO;AAAA,EACT;AACA,QAAM,SAAS,QAAQ,iBAAiB,WAAW;AACnD,QAAM,OAAO,MAAM,cAAc,QAAQ,OAAO,MAAM;AACtD,SAAO;AAAA,IACL;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,WAAW,MAAM,QAAQ,aAAa,GAAG;AAAA,EAC3C;AACF;;;AClBO,IAAM,kBAAN,MAA+C;AAAA,EAC5C,aAAa,oBAAI,IAAqB;AAAA,EACtC,cAAc,oBAAI,IAA8C;AAAA,EAChE,cAAc,oBAAI,IAAsB;AAAA,EACxC,YAAY,oBAAI,IAAoB;AAAA,EACpC,oBAAoB,oBAAI,IAA4B;AAAA,EACpD,YAAuB;AAAA,IAC7B,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,WAAW;AAAA,EACb;AAAA,EAEA,iBAAiB,aAAoC;AACnD,UAAM,eAAe,MAAwC;AAC3D,UAAI,CAAC,KAAK,YAAY,IAAI,WAAW,GAAG;AACtC,aAAK,YAAY,IAAI,aAAa,oBAAI,IAAI,CAAC;AAAA,MAC7C;AACA,aAAO,KAAK,YAAY,IAAI,WAAW;AAAA,IACzC;AAEA,UAAM,iBAAiB,CAAC,OAAuB;AAC7C,YAAM,SAAS,aAAa;AAC5B,iBAAW,KAAK,IAAI;AAClB,YAAI,CAAC,OAAO,IAAI,EAAE,IAAI,GAAG;AACvB,iBAAO,IAAI,EAAE,MAAM,oBAAI,IAAI,CAAC;AAAA,QAC9B;AACA,eAAO,IAAI,EAAE,IAAI,EAAG,IAAI,EAAE,IAAI,CAAC;AAAA,MACjC;AAAA,IACF;AAEA,UAAM,cAAc,CAAC,OAAqB;AACxC,YAAM,WAAW,KAAK,UAAU,IAAI,WAAW,KAAK,CAAC;AACrD,YAAM,QAAQ,oBAAI,IAAoB;AACtC,eAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,cAAM,IAAI,SAAS,CAAC;AACpB,cAAM;AAAA,UACJ,GAAG,EAAE,SAAS,IAAI,EAAE,OAAO,IAAI,EAAE,IAAI,IAAI,EAAE,OAAO,IAAI,EAAE,KAAK;AAAA,UAC7D;AAAA,QACF;AAAA,MACF;AACA,iBAAW,KAAK,IAAI;AAClB,cAAM,MAAM,GAAG,EAAE,SAAS,IAAI,EAAE,OAAO,IAAI,EAAE,IAAI,IAAI,EAAE,OAAO,IAAI,EAAE,KAAK;AACzE,cAAM,MAAM,MAAM,IAAI,GAAG;AACzB,YAAI,QAAQ,QAAW;AACrB,mBAAS,GAAG,IAAI;AAAA,QAClB,OAAO;AACL,gBAAM,IAAI,KAAK,SAAS,MAAM;AAC9B,mBAAS,KAAK,CAAC;AAAA,QACjB;AAAA,MACF;AACA,WAAK,UAAU,IAAI,aAAa,QAAQ;AAAA,IAC1C;AAEA,WAAO;AAAA,MACL,OAAO,OAAO,MAAM;AAClB,YAAI,CAAC,KAAK,WAAW,IAAI,WAAW,GAAG;AACrC,eAAK,WAAW,IAAI,aAAa,CAAC,CAAC;AAAA,QACrC;AACA,aAAK,WAAW,IAAI,WAAW,EAAG,KAAK,CAAC;AAAA,MAC1C;AAAA,MAEA,QAAQ,OAAO,MAAM;AACnB,uBAAe,CAAC,CAAC,CAAC;AAAA,MACpB;AAAA,MAEA,QAAQ,OAAO,MAAM;AACnB,YAAI,CAAC,KAAK,YAAY,IAAI,WAAW,GAAG;AACtC,eAAK,YAAY,IAAI,aAAa,CAAC,CAAC;AAAA,QACtC;AACA,aAAK,YAAY,IAAI,WAAW,EAAG,KAAK,CAAC;AAAA,MAC3C;AAAA,MAEA,MAAM,OAAO,MAAM;AACjB,oBAAY,CAAC,CAAC,CAAC;AAAA,MACjB;AAAA,MAEA,cAAc,OAAO,MAAM;AACzB,YAAI,CAAC,KAAK,kBAAkB,IAAI,WAAW,GAAG;AAC5C,eAAK,kBAAkB,IAAI,aAAa,CAAC,CAAC;AAAA,QAC5C;AACA,aAAK,kBAAkB,IAAI,WAAW,EAAG,KAAK,CAAC;AAAA,MACjD;AAAA,MAEA,QAAQ,OAAO,IAAI,UAAU;AAC3B,cAAM,QAAQ,IAAI,IAAI,OAAO,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAC3D,cAAM,QAAQ,KAAK,WAAW,IAAI,WAAW,KAAK,CAAC,GAAG;AAAA,UACpD,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,IAAI;AAAA,QAC1B;AACA,aAAK,WAAW,IAAI,aAAa,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC;AAAA,MACnD;AAAA,MAEA,UAAU,OAAO,IAAI,UAAU;AAC7B,cAAM,SAAS,aAAa;AAC5B,cAAM,QAAQ,IAAI,IAAI,OAAO,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAC3D,mBAAW,QAAQ,OAAO;AACxB,iBAAO,IAAI,MAAM,oBAAI,IAAI,CAAC;AAAA,QAC5B;AACA,uBAAe,EAAE;AAAA,MACnB;AAAA,MAEA,SAAS,OAAO,IAAI,UAAU;AAC5B,cAAM,QAAQ,IAAI,IAAI,OAAO,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAC3D,cAAM,QAAQ,KAAK,YAAY,IAAI,WAAW,KAAK,CAAC,GAAG;AAAA,UACrD,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,IAAI;AAAA,QAC1B;AACA,aAAK,YAAY,IAAI,aAAa,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC;AAAA,MACpD;AAAA,MAEA,OAAO,OAAO,IAAI,UAAU;AAC1B,cAAM,QAAQ,IAAI,IAAI,OAAO,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAC3D,cAAM,QAAQ,KAAK,UAAU,IAAI,WAAW,KAAK,CAAC,GAAG;AAAA,UACnD,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,IAAI;AAAA,QAC1B;AACA,aAAK,UAAU,IAAI,aAAa,IAAI;AACpC,oBAAY,EAAE;AAAA,MAChB;AAAA,MAEA,eAAe,OAAO,IAAI,UAAU;AAClC,cAAM,QAAQ,IAAI,IAAI,OAAO,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAC3D,cAAM,QAAQ,KAAK,kBAAkB,IAAI,WAAW,KAAK,CAAC,GAAG;AAAA,UAC3D,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,IAAI;AAAA,QAC1B;AACA,aAAK,kBAAkB,IAAI,aAAa,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC;AAAA,MAC1D;AAAA,MAEA,aAAa,OAAO,MAAkB;AACpC,YAAI,UAAU,KAAK,WAAW,IAAI,WAAW,KAAK,CAAC;AACnD,YAAI,EAAE,SAAS,QAAW;AACxB,oBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI;AAAA,QACnD;AACA,YAAI,EAAE,UAAU,QAAW;AACzB,oBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,YAAY,EAAE,KAAM;AAAA,QACxD;AACA,YAAI,EAAE,QAAQ,QAAW;AACvB,oBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,YAAY,EAAE,GAAI;AAAA,QACtD;AACA,eAAO;AAAA,MACT;AAAA,MAEA,WAAW,OAAO,MAAc,OAAe;AAC7C,eAAO,aAAa,EAAE,IAAI,IAAI,GAAG,IAAI,EAAE,KAAK;AAAA,MAC9C;AAAA,MAEA,eAAe,OAAO,MAAmB;AACvC,cAAM,SAAS,aAAa,EAAE,IAAI,EAAE,IAAI;AACxC,YAAI,CAAC,QAAQ;AACX,iBAAO,CAAC;AAAA,QACV;AACA,eAAO,MAAM,KAAK,OAAO,OAAO,CAAC;AAAA,MACnC;AAAA,MAEA,cAAc,OAAO,MAAmB;AACtC,YAAI,UAAU,KAAK,YAAY,IAAI,WAAW,KAAK,CAAC;AACpD,YAAI,EAAE,SAAS,QAAW;AACxB,oBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI;AAAA,QACnD;AACA,YAAI,EAAE,UAAU,QAAW;AACzB,oBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,KAAM;AAAA,QAClD;AACA,YAAI,EAAE,QAAQ,QAAW;AACvB,oBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAI;AAAA,QAChD;AACA,eAAO;AAAA,MACT;AAAA,MAEA,UAAU,OAAO,MAAiB;AAChC,YAAI,UAAU,KAAK,UAAU,IAAI,WAAW,KAAK,CAAC;AAClD,YAAI,EAAE,aAAa,QAAW;AAC5B,oBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ;AAAA,QAC5D;AACA,YAAI,EAAE,WAAW,QAAW;AAC1B,oBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM;AAAA,QACxD;AACA,YAAI,EAAE,SAAS,QAAW;AACxB,oBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI;AAAA,QACnD;AACA,YAAI,EAAE,WAAW,QAAW;AAC1B,oBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,YAAY,EAAE,MAAM;AAAA,QACxD;AACA,YAAI,EAAE,SAAS,QAAW;AACxB,oBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI;AAAA,QACpD;AACA,eAAO;AAAA,MACT;AAAA,MAEA,oBAAoB,OAAO,MAAyB;AAClD,YAAI,UAAU,KAAK,kBAAkB,IAAI,WAAW,KAAK,CAAC;AAC1D,YAAI,EAAE,SAAS,QAAW;AACxB,oBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI;AAAA,QACnD;AACA,YAAI,EAAE,UAAU,QAAW;AACzB,oBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,KAAM;AAAA,QAClD;AACA,YAAI,EAAE,QAAQ,QAAW;AACvB,oBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAI;AAAA,QAChD;AACA,eAAO;AAAA,MACT;AAAA,MAEA,iBAAiB,OAAO,OAAO,aAAa;AAC1C,YAAI,UAAU,UAAU;AACtB,gBAAM,SAAS,KAAK,WAAW,IAAI,WAAW,KAAK,CAAC;AACpD,gBAAM,QAAQ,OAAO,OAAO,CAAC,MAAM,EAAE,YAAY,QAAQ;AACzD,eAAK,WAAW,IAAI,aAAa,KAAK;AACtC,iBAAO,EAAE,aAAa,OAAO,SAAS,MAAM,OAAO;AAAA,QACrD,WAAW,UAAU,WAAW;AAC9B,gBAAM,SAAS,KAAK,YAAY,IAAI,WAAW,KAAK,CAAC;AACrD,gBAAM,QAAQ,OAAO,OAAO,CAAC,MAAM,EAAE,MAAM,QAAQ;AACnD,eAAK,YAAY,IAAI,aAAa,KAAK;AACvC,iBAAO,EAAE,aAAa,OAAO,SAAS,MAAM,OAAO;AAAA,QACrD,WAAW,UAAU,iBAAiB;AACpC,gBAAM,SAAS,KAAK,kBAAkB,IAAI,WAAW,KAAK,CAAC;AAC3D,gBAAM,QAAQ,OAAO,OAAO,CAAC,MAAM,EAAE,MAAM,QAAQ;AACnD,eAAK,kBAAkB,IAAI,aAAa,KAAK;AAC7C,iBAAO,EAAE,aAAa,OAAO,SAAS,MAAM,OAAO;AAAA,QACrD,OAAO;AACL,gBAAM,IAAI;AAAA,YACR,0CAA0C,OAAO,KAAK,CAAC;AAAA,UACzD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,eAAmC;AACvC,WAAO,EAAE,GAAG,KAAK,UAAU;AAAA,EAC7B;AAAA,EAEA,MAAM,aAA+B;AACnC,QAAI,KAAK,UAAU,WAAW,WAAW;AACvC,aAAO;AAAA,IACT;AACA,SAAK,YAAY,EAAE,GAAG,KAAK,WAAW,QAAQ,UAAU;AACxD,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,iBAAgC;AACpC,SAAK,YAAY;AAAA,MACf,QAAQ;AAAA,MACR,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,MACnC,WAAW;AAAA,IACb;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,OAA8B;AAC/C,SAAK,YAAY;AAAA,MACf,QAAQ;AAAA,MACR,YAAY,KAAK,UAAU;AAAA,MAC3B,WAAW;AAAA,IACb;AAAA,EACF;AACF;","names":["z"]}
|
|
1
|
+
{"version":3,"sources":["../src/secrets.ts","../src/connector.ts","../src/widget-schemas.ts","../src/config.ts","../src/retention.ts","../src/config-fields.ts","../src/compute.ts","../src/resolve-widget.ts","../src/in-memory-storage.ts"],"sourcesContent":["export type SecretRef = { $secret: string };\n\nexport function secret(name: string): SecretRef {\n if (!/^[A-Z][A-Z0-9_]*$/.test(name)) {\n throw new Error(\n `Invalid secret name \"${name}\". Must match /^[A-Z][A-Z0-9_]*$/ ` +\n `(uppercase letters, digits, underscores; must start with a letter).`,\n );\n }\n return { $secret: name };\n}\n\nexport function isSecretRef(value: unknown): value is SecretRef {\n return (\n typeof value === 'object' &&\n value !== null &&\n '$secret' in value &&\n typeof (value as SecretRef).$secret === 'string'\n );\n}\n\nexport interface SecretsResolver {\n resolve(name: string): string | undefined;\n}\n\nexport class EnvSecretsResolver implements SecretsResolver {\n resolve(name: string): string | undefined {\n const env = (\n globalThis as { process?: { env?: Record<string, string | undefined> } }\n ).process?.env;\n return env?.[name];\n }\n}\n\nexport function resolveSecretRefs<T>(obj: T, resolver: SecretsResolver): T {\n if (isSecretRef(obj)) {\n const name = obj.$secret;\n const value = resolver.resolve(name);\n if (value === undefined) {\n throw new Error(\n `Missing secret \"${name}\". Set it via process.env.${name} or the CLI: rawdash secrets set ${name} ...`,\n );\n }\n return value as unknown as T;\n }\n if (Array.isArray(obj)) {\n return obj.map((item) => resolveSecretRefs(item, resolver)) as unknown as T;\n }\n if (typeof obj === 'object' && obj !== null) {\n const result: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(obj as object)) {\n Object.defineProperty(result, key, {\n value: resolveSecretRefs(val, resolver),\n enumerable: true,\n configurable: true,\n writable: true,\n });\n }\n return result as T;\n }\n return obj;\n}\n","import {\n EnvSecretsResolver,\n type SecretRef,\n resolveSecretRefs,\n} from './secrets';\n\nexport type JSONValue =\n | string\n | number\n | boolean\n | null\n | JSONValue[]\n | { [key: string]: JSONValue };\n\n// ---------------------------------------------------------------------------\n// Five storage shapes\n// ---------------------------------------------------------------------------\n\nexport interface Event {\n name: string;\n start_ts: number;\n end_ts: number | null;\n attributes: Record<string, JSONValue>;\n}\n\nexport interface Entity {\n type: string;\n id: string;\n attributes: Record<string, JSONValue>;\n updated_at: number;\n}\n\nexport interface Metric {\n name: string;\n ts: number;\n value: number;\n attributes: Record<string, JSONValue>;\n}\n\nexport interface Edge {\n from_type: string;\n from_id: string;\n kind: string;\n to_type: string;\n to_id: string;\n attributes: Record<string, JSONValue>;\n updated_at: number;\n}\n\nexport type Distribution =\n | {\n name: string;\n ts: number;\n kind: 'histogram';\n data: {\n buckets: Array<{ le: number; count: number }>;\n count: number;\n sum: number;\n };\n attributes: Record<string, JSONValue>;\n }\n | {\n name: string;\n ts: number;\n kind: 'summary';\n data: {\n quantiles: Array<{ q: number; value: number }>;\n count: number;\n sum: number;\n };\n attributes: Record<string, JSONValue>;\n };\n\n// ---------------------------------------------------------------------------\n// Storage query types\n// ---------------------------------------------------------------------------\n\nexport interface EventQuery {\n name?: string;\n start?: number;\n end?: number;\n}\n\nexport interface EntityQuery {\n type: string;\n}\n\nexport interface MetricQuery {\n name?: string;\n start?: number;\n end?: number;\n}\n\nexport interface EdgeQuery {\n fromType?: string;\n fromId?: string;\n kind?: string;\n toType?: string;\n toId?: string;\n}\n\nexport interface DistributionQuery {\n name?: string;\n start?: number;\n end?: number;\n}\n\n// ---------------------------------------------------------------------------\n// StorageHandle — write and read surface\n// ---------------------------------------------------------------------------\n\nexport interface StorageHandle {\n event(e: Event): Promise<void>;\n entity(e: Entity): Promise<void>;\n metric(m: Metric): Promise<void>;\n edge(e: Edge): Promise<void>;\n distribution(d: Distribution): Promise<void>;\n\n events(es: Event[], scope?: { names?: string[] }): Promise<void>;\n entities(es: Entity[], scope?: { types?: string[] }): Promise<void>;\n metrics(ms: Metric[], scope?: { names?: string[] }): Promise<void>;\n edges(es: Edge[], scope?: { kinds?: string[] }): Promise<void>;\n distributions(\n ds: Distribution[],\n scope?: { names?: string[] },\n ): Promise<void>;\n\n queryEvents(q: EventQuery): Promise<Event[]>;\n getEntity(type: string, id: string): Promise<Entity | null>;\n queryEntities(q: EntityQuery): Promise<Entity[]>;\n queryMetrics(q: MetricQuery): Promise<Metric[]>;\n traverse(q: EdgeQuery): Promise<Edge[]>;\n queryDistributions(q: DistributionQuery): Promise<Distribution[]>;\n\n // Deletes all rows in the given time-series shape whose timestamp column is\n // strictly less than `tsUnixMs`. Only covers append-only shapes (events,\n // metrics, distributions). Entities and edges are excluded because they hold\n // the latest known state per primary key — deleting by age would lose live\n // data. The right model for those shapes is \"expire when source disappears.\"\n deleteOlderThan(\n shape: 'events' | 'metrics' | 'distributions',\n tsUnixMs: number,\n ): Promise<{ rowsDeleted: number }>;\n}\n\n// ---------------------------------------------------------------------------\n// Credentials\n// ---------------------------------------------------------------------------\n\nexport interface CredentialEntry {\n description: string;\n auth?: 'none' | 'optional' | 'required';\n}\n\nexport type CredentialSchema = Record<string, CredentialEntry>;\n\nexport type InferCredentials<TCreds extends CredentialSchema> = {\n [K in keyof TCreds]: TCreds[K] extends { auth: 'required' }\n ? string\n : string | undefined;\n};\n\nexport type InferCredentialInput<TCreds extends CredentialSchema> = {\n [K in keyof TCreds]: TCreds[K] extends { auth: 'required' }\n ? string | SecretRef\n : string | SecretRef | undefined;\n};\n\n// ---------------------------------------------------------------------------\n// Sync + Connector\n// ---------------------------------------------------------------------------\n\nexport interface SyncRequest {\n mode: 'full' | 'latest';\n since?: string;\n}\n\nexport interface Connector {\n readonly id: string;\n readonly credentials?: CredentialSchema;\n serializeConfig(): Record<string, unknown>;\n sync(\n request: SyncRequest,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<void>;\n}\n\nexport interface RetryOptions {\n maxAttempts?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n signal?: AbortSignal;\n}\n\nexport abstract class BaseConnector<\n TSettings = unknown,\n TCreds extends CredentialSchema = CredentialSchema,\n> implements Connector {\n abstract readonly id: string;\n readonly credentials?: TCreds;\n\n protected settings: TSettings;\n protected creds: InferCredentials<TCreds>;\n private rawCredInput: InferCredentialInput<TCreds> | undefined;\n\n constructor(settings: TSettings, creds?: InferCredentialInput<TCreds>) {\n this.settings = settings;\n this.rawCredInput = creds;\n this.creds = creds\n ? (resolveSecretRefs(\n creds,\n new EnvSecretsResolver(),\n ) as InferCredentials<TCreds>)\n : ({} as InferCredentials<TCreds>);\n }\n\n serializeConfig(): Record<string, unknown> {\n const config: Record<string, unknown> = {\n ...(this.settings as Record<string, unknown>),\n };\n if (this.rawCredInput) {\n for (const [key, value] of Object.entries(\n this.rawCredInput as Record<string, unknown>,\n )) {\n if (value !== undefined) {\n config[key] = value;\n }\n }\n }\n return config;\n }\n\n protected sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n return Promise.reject(signal.reason ?? new Error('Aborted'));\n }\n return new Promise<void>((resolve, reject) => {\n const onAbort = () => {\n clearTimeout(timer);\n reject(signal!.reason ?? new Error('Aborted'));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n }\n\n protected async withRetry<T>(\n fn: (\n signal?: AbortSignal,\n ) => Promise<{ status: 'done'; value: T } | { status: 'retry' }>,\n options?: RetryOptions,\n ): Promise<T | null> {\n const {\n maxAttempts = 10,\n initialDelayMs = 1000,\n maxDelayMs = 10000,\n signal,\n } = options ?? {};\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n signal?.throwIfAborted();\n const result = await fn(signal);\n if (result.status === 'done') {\n return result.value;\n }\n if (attempt < maxAttempts - 1) {\n const delay = Math.min(initialDelayMs * 2 ** attempt, maxDelayMs);\n await this.sleep(delay, signal);\n }\n }\n\n return null;\n }\n\n abstract sync(\n request: SyncRequest,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<void>;\n}\n\nexport function defineConnector<TSettings>() {\n return function <\n TCreds extends CredentialSchema = Record<string, never>,\n >(def: {\n id: string;\n credentials?: TCreds;\n sync: (\n this: { settings: TSettings; creds: InferCredentials<TCreds> },\n request: SyncRequest,\n storage: StorageHandle,\n signal?: AbortSignal,\n ) => Promise<void>;\n }): {\n new (settings: TSettings, creds?: InferCredentialInput<TCreds>): Connector;\n readonly id: string;\n readonly credentials: TCreds | undefined;\n } {\n class DynamicConnector extends BaseConnector<TSettings, TCreds> {\n static readonly id = def.id;\n static readonly credentials = def.credentials;\n\n readonly id = def.id;\n override readonly credentials = def.credentials;\n\n async sync(\n request: SyncRequest,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<void> {\n return def.sync.call(\n { settings: this.settings, creds: this.creds },\n request,\n storage,\n signal,\n );\n }\n }\n\n return DynamicConnector as unknown as {\n new (\n settings: TSettings,\n creds?: InferCredentialInput<TCreds>,\n ): Connector;\n readonly id: string;\n readonly credentials: TCreds | undefined;\n };\n };\n}\n","import { z } from 'zod';\n\nexport const shapeSchema = z.enum([\n 'event',\n 'entity',\n 'metric',\n 'edge',\n 'distribution',\n]);\n\nexport const aggFnSchema = z.enum([\n 'count',\n 'sum',\n 'avg',\n 'min',\n 'max',\n 'latest',\n 'first',\n]);\n\nexport const filterOperatorSchema = z.enum([\n 'eq',\n 'neq',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'contains',\n]);\n\nexport const filterConditionSchema = z.object({\n field: z.string(),\n op: filterOperatorSchema,\n value: z.union([z.string(), z.number(), z.boolean()]),\n});\n\nexport const filterClauseSchema = z.union([\n filterConditionSchema,\n z.object({ or: z.array(filterConditionSchema) }),\n]);\n\nexport const groupBySchema = z.object({\n field: z.string(),\n granularity: z.enum(['hour', 'day', 'week', 'month']),\n});\n\nexport const resolvedMetricSchema = z\n .object({\n connectorId: z.string(),\n shape: shapeSchema,\n name: z.string().optional(),\n entityType: z.string().optional(),\n field: z.string().optional(),\n fn: aggFnSchema,\n window: z.string().optional(),\n filter: z.array(filterClauseSchema).optional(),\n groupBy: groupBySchema.optional(),\n })\n .refine((m) => m.fn === 'count' || m.field !== undefined, {\n message: 'field is required unless fn is \"count\"',\n path: ['field'],\n });\n\nconst titleField = z\n .string()\n .meta({ label: 'Title', description: 'Widget title.' });\n\nexport const statWidgetSchema = z.object({\n kind: z.literal('stat'),\n title: titleField,\n metric: resolvedMetricSchema.meta({\n label: 'Metric',\n description: 'Resolved metric definition.',\n }),\n window: z\n .string()\n .optional()\n .meta({ label: 'Window', description: \"Time window, e.g. '7d'.\" }),\n compare: z\n .enum(['none', 'previous-period'])\n .default('none')\n .meta({ label: 'Compare', description: 'Comparison mode.' }),\n});\n\nexport const statusWidgetSchema = z.object({\n kind: z.literal('status'),\n title: titleField,\n source: z.string().meta({\n label: 'Source',\n description: 'Connector or data source reference.',\n }),\n});\n\nexport const timeseriesWidgetSchema = z.object({\n kind: z.literal('timeseries'),\n title: titleField,\n metric: resolvedMetricSchema.meta({\n label: 'Metric',\n description: 'Resolved metric definition.',\n }),\n window: z\n .string()\n .meta({ label: 'Window', description: \"Time window, e.g. '30d'.\" }),\n granularity: z\n .enum(['hour', 'day', 'week'])\n .default('day')\n .meta({ label: 'Granularity', description: 'Time bucket size.' }),\n});\n\nexport const distributionWidgetSchema = z.object({\n kind: z.literal('distribution'),\n title: titleField,\n metric: resolvedMetricSchema.meta({\n label: 'Metric',\n description: 'Resolved metric definition.',\n }),\n window: z\n .string()\n .meta({ label: 'Window', description: \"Time window, e.g. '7d'.\" }),\n});\n\nexport const widgetSchemas = {\n stat: statWidgetSchema,\n status: statusWidgetSchema,\n timeseries: timeseriesWidgetSchema,\n distribution: distributionWidgetSchema,\n} as const;\n\nexport const widgetSchema = z.discriminatedUnion('kind', [\n statWidgetSchema,\n statusWidgetSchema,\n timeseriesWidgetSchema,\n distributionWidgetSchema,\n]);\n\nexport type WidgetKind = keyof typeof widgetSchemas;\n\nexport function getWidgetSchema(kind: WidgetKind) {\n return widgetSchemas[kind];\n}\n","import type { Connector } from './connector';\nimport type { RetentionConfig } from './retention';\nimport { getWidgetSchema, widgetSchemas } from './widget-schemas';\nimport type { WidgetKind } from './widget-schemas';\n\n// ---------------------------------------------------------------------------\n// Aggregation functions\n// ---------------------------------------------------------------------------\n\nexport type AggFn =\n | 'count'\n | 'sum'\n | 'avg'\n | 'min'\n | 'max'\n | 'latest'\n | 'first';\n\n// ---------------------------------------------------------------------------\n// Shape\n// ---------------------------------------------------------------------------\n\nexport type Shape = 'event' | 'entity' | 'metric' | 'edge' | 'distribution';\n\n// ---------------------------------------------------------------------------\n// Filters\n// ---------------------------------------------------------------------------\n\nexport type FilterOperator =\n | 'eq'\n | 'neq'\n | 'gt'\n | 'gte'\n | 'lt'\n | 'lte'\n | 'contains';\n\nexport interface FilterCondition {\n field: string;\n op: FilterOperator;\n value: string | number | boolean;\n}\n\nexport type FilterClause = FilterCondition | { or: FilterCondition[] };\n\n// ---------------------------------------------------------------------------\n// GroupBy\n// ---------------------------------------------------------------------------\n\nexport interface GroupBy {\n field: string;\n granularity: 'hour' | 'day' | 'week' | 'month';\n}\n\n// ---------------------------------------------------------------------------\n// Metric definition\n// ---------------------------------------------------------------------------\n\nexport interface MetricDef {\n connector: { id: string };\n shape: Shape;\n name?: string;\n entityType?: string;\n field?: string;\n fn: AggFn;\n window?: string;\n filter?: FilterClause[];\n groupBy?: GroupBy;\n}\n\nexport interface ResolvedMetric {\n readonly connectorId: string;\n readonly shape: Shape;\n readonly name?: string;\n readonly entityType?: string;\n readonly field?: string;\n readonly fn: AggFn;\n readonly window?: string;\n readonly filter?: FilterClause[];\n readonly groupBy?: GroupBy;\n}\n\n// ---------------------------------------------------------------------------\n// Widget definition\n// ---------------------------------------------------------------------------\n\nexport interface StatWidget {\n kind: 'stat';\n title: string;\n metric: ResolvedMetric;\n window?: string;\n compare?: 'none' | 'previous-period';\n}\n\nexport interface StatusWidget {\n kind: 'status';\n title: string;\n source: string;\n}\n\nexport interface TimeseriesWidget {\n kind: 'timeseries';\n title: string;\n metric: ResolvedMetric;\n window: string;\n granularity?: 'hour' | 'day' | 'week';\n}\n\nexport interface DistributionWidget {\n kind: 'distribution';\n title: string;\n metric: ResolvedMetric;\n window: string;\n}\n\nexport type Widget =\n | StatWidget\n | StatusWidget\n | TimeseriesWidget\n | DistributionWidget;\n\nexport type { WidgetKind };\n\n// ---------------------------------------------------------------------------\n// Dashboard config\n// ---------------------------------------------------------------------------\n\nexport interface ConnectorEntry {\n connector: Connector;\n}\n\nexport interface Dashboard {\n widgets: Record<string, Widget>;\n}\n\nexport interface DashboardConfig {\n connectors: ConnectorEntry[];\n dashboards: Record<string, Dashboard>;\n retention?: RetentionConfig;\n}\n\n// ---------------------------------------------------------------------------\n// defineDashboard\n// ---------------------------------------------------------------------------\n\nconst VALID_WIDGET_KINDS = new Set<string>(Object.keys(widgetSchemas));\n\nexport function defineDashboard(options: {\n widgets: Record<string, Widget>;\n}): Dashboard {\n for (const [key, widget] of Object.entries(options.widgets)) {\n if (!VALID_WIDGET_KINDS.has(widget.kind)) {\n throw new Error(\n `Widget \"${key}\": unknown kind \"${widget.kind}\". Must be one of: ${[...VALID_WIDGET_KINDS].join(', ')}`,\n );\n }\n const schema = getWidgetSchema(widget.kind as WidgetKind);\n const result = schema.safeParse(widget);\n if (!result.success) {\n throw new Error(\n `Widget \"${key}\" (kind \"${widget.kind}\"): ${result.error.issues.map((i) => i.message).join('; ')}`,\n );\n }\n }\n return { widgets: options.widgets };\n}\n\n// ---------------------------------------------------------------------------\n// defineMetric\n// ---------------------------------------------------------------------------\n\nexport function defineMetric(options: MetricDef): ResolvedMetric {\n return {\n connectorId: options.connector.id,\n shape: options.shape,\n name: options.name,\n entityType: options.entityType,\n field: options.field,\n fn: options.fn,\n window: options.window,\n filter: options.filter,\n groupBy: options.groupBy,\n };\n}\n\n// ---------------------------------------------------------------------------\n// defineConfig\n// ---------------------------------------------------------------------------\n\nconst VALID_SHAPES = new Set<string>([\n 'event',\n 'entity',\n 'metric',\n 'edge',\n 'distribution',\n]);\nconst VALID_FNS = new Set<string>([\n 'count',\n 'sum',\n 'avg',\n 'min',\n 'max',\n 'latest',\n 'first',\n]);\n\nconst SAFE_KEY_RE = /^[a-zA-Z0-9_-]+$/;\n\nfunction validateConfig(config: DashboardConfig): void {\n if (config.retention) {\n const { maxAge, maxSize, floor, intervalMs } = config.retention;\n if (maxAge !== undefined && (!Number.isFinite(maxAge) || maxAge < 0)) {\n throw new Error('retention.maxAge must be a finite number >= 0');\n }\n if (maxSize !== undefined && (!Number.isInteger(maxSize) || maxSize < 0)) {\n throw new Error('retention.maxSize must be an integer >= 0');\n }\n if (floor !== undefined && (!Number.isInteger(floor) || floor < 0)) {\n throw new Error('retention.floor must be an integer >= 0');\n }\n if (\n intervalMs !== undefined &&\n (!Number.isFinite(intervalMs) || intervalMs <= 0)\n ) {\n throw new Error('retention.intervalMs must be a finite number > 0');\n }\n }\n\n if (\n !config.dashboards ||\n typeof config.dashboards !== 'object' ||\n Array.isArray(config.dashboards)\n ) {\n throw new Error(\n 'defineConfig: config must include a \"dashboards\" record — did you mean to migrate from the old flat \"widgets\" shape?',\n );\n }\n\n const connectorIds = new Set(config.connectors.map((e) => e.connector.id));\n\n for (const [dashboardKey, dashboard] of Object.entries(config.dashboards)) {\n if (\n !dashboard.widgets ||\n typeof dashboard.widgets !== 'object' ||\n Array.isArray(dashboard.widgets)\n ) {\n throw new Error(\n `Dashboard \"${dashboardKey}\" must define a \"widgets\" record`,\n );\n }\n\n if (!SAFE_KEY_RE.test(dashboardKey)) {\n throw new Error(\n `Dashboard key \"${dashboardKey}\" contains URL-unsafe characters; use only letters, digits, hyphens, and underscores`,\n );\n }\n\n for (const [widgetKey, widget] of Object.entries(dashboard.widgets)) {\n const ref = `Dashboard \"${dashboardKey}\", widget \"${widgetKey}\"`;\n\n if (!SAFE_KEY_RE.test(widgetKey)) {\n throw new Error(\n `${ref}: widget key contains URL-unsafe characters; use only letters, digits, hyphens, and underscores`,\n );\n }\n\n if (widget.kind === 'status') {\n continue;\n }\n\n const { connectorId, shape, fn } = widget.metric;\n\n if (!connectorIds.has(connectorId)) {\n throw new Error(\n `${ref}: connector \"${connectorId}\" is not listed in connectors`,\n );\n }\n\n if (!VALID_SHAPES.has(shape)) {\n throw new Error(`${ref}: invalid shape \"${shape}\"`);\n }\n\n if (!VALID_FNS.has(fn)) {\n throw new Error(`${ref}: invalid fn \"${fn}\"`);\n }\n }\n }\n}\n\nexport function defineConfig(config: DashboardConfig): DashboardConfig {\n validateConfig(config);\n return config;\n}\n","import type { Distribution, Event, Metric, StorageHandle } from './connector';\n\n// ---------------------------------------------------------------------------\n// RetentionConfig\n// ---------------------------------------------------------------------------\n\nexport interface RetentionConfig {\n maxAge?: number;\n maxSize?: number;\n floor?: number;\n intervalMs?: number;\n}\n\n// ---------------------------------------------------------------------------\n// RetentionCandidates — rows eligible for deletion across time-series shapes\n// ---------------------------------------------------------------------------\n\nexport interface RetentionCandidates {\n events: Event[];\n metrics: Metric[];\n distributions: Distribution[];\n}\n\n// ---------------------------------------------------------------------------\n// selectForDeletion — pure computation\n//\n// Receives rows pre-sorted newest-first (descending by timestamp).\n// Returns the subset that should be deleted given the policy.\n//\n// Rules applied in order:\n// 1. Rows beyond maxSize are candidates.\n// 2. Rows older than maxAge milliseconds are candidates.\n// 3. Rows within the newest `floor` positions are always kept (overrides 1 & 2).\n// ---------------------------------------------------------------------------\n\nexport function selectForDeletion<T>(\n rows: T[],\n getTs: (row: T) => number,\n config: RetentionConfig,\n nowMs: number = Date.now(),\n): T[] {\n const { maxAge, maxSize, floor = 0 } = config;\n\n if (maxAge === undefined && maxSize === undefined) {\n return [];\n }\n\n const toDelete: T[] = [];\n\n for (let i = 0; i < rows.length; i++) {\n const row = rows[i]!;\n if (i < floor) {\n continue;\n }\n\n const overSize = maxSize !== undefined && i >= maxSize;\n const tooOld = maxAge !== undefined && getTs(row) < nowMs - maxAge;\n\n if (overSize || tooOld) {\n toDelete.push(row);\n }\n }\n\n return toDelete;\n}\n\n// ---------------------------------------------------------------------------\n// computeRetention — async, queries the handle and returns deletion candidates\n//\n// Only covers time-series shapes (events, metrics, distributions) since those\n// grow unboundedly via append. Entities and edges are upsert-keyed and do not\n// accumulate the same way.\n// ---------------------------------------------------------------------------\n\nexport async function computeRetention(\n handle: StorageHandle,\n config: RetentionConfig,\n nowMs: number = Date.now(),\n): Promise<RetentionCandidates> {\n const [events, metrics, distributions] = await Promise.all([\n handle.queryEvents({}),\n handle.queryMetrics({}),\n handle.queryDistributions({}),\n ]);\n\n const sortedEvents = [...events].sort((a, b) => b.start_ts - a.start_ts);\n const sortedMetrics = [...metrics].sort((a, b) => b.ts - a.ts);\n const sortedDistributions = [...distributions].sort((a, b) => b.ts - a.ts);\n\n return {\n events: selectForDeletion(sortedEvents, (e) => e.start_ts, config, nowMs),\n metrics: selectForDeletion(sortedMetrics, (m) => m.ts, config, nowMs),\n distributions: selectForDeletion(\n sortedDistributions,\n (d) => d.ts,\n config,\n nowMs,\n ),\n };\n}\n","import { z } from 'zod';\n\nexport type ConfigFieldsSchema = z.ZodObject<z.ZodRawShape>;\n\nexport function defineConfigFields<T extends z.ZodRawShape>(\n schema: z.ZodObject<T>,\n): z.ZodObject<T> {\n if (!(schema instanceof z.ZodObject)) {\n throw new Error(\n `configFields must be a Zod object schema (z.object({...})). Received: ${Object.prototype.toString.call(schema)}`,\n );\n }\n return schema;\n}\n","import type { ResolvedMetric } from './config';\nimport type { StorageHandle } from './connector';\n\ntype FilterClause = NonNullable<ResolvedMetric['filter']>[number];\ntype FilterCondition = Exclude<FilterClause, { or: unknown[] }>;\n\nfunction matchesCondition(\n record: Record<string, unknown>,\n cond: FilterCondition,\n): boolean {\n const val = record[cond.field];\n switch (cond.op) {\n case 'eq':\n return val === cond.value;\n case 'neq':\n return val !== cond.value;\n case 'gt':\n if (typeof val !== 'number' || typeof cond.value !== 'number') {\n return false;\n }\n return val > cond.value;\n case 'gte':\n if (typeof val !== 'number' || typeof cond.value !== 'number') {\n return false;\n }\n return val >= cond.value;\n case 'lt':\n if (typeof val !== 'number' || typeof cond.value !== 'number') {\n return false;\n }\n return val < cond.value;\n case 'lte':\n if (typeof val !== 'number' || typeof cond.value !== 'number') {\n return false;\n }\n return val <= cond.value;\n case 'contains':\n return String(val).includes(String(cond.value));\n default:\n return false;\n }\n}\n\nfunction applyFilter(\n record: Record<string, unknown>,\n filter: ResolvedMetric['filter'],\n): boolean {\n if (!filter) {\n return true;\n }\n for (const clause of filter) {\n if ('or' in clause) {\n if (!clause.or.some((cond) => matchesCondition(record, cond))) {\n return false;\n }\n } else {\n if (!matchesCondition(record, clause)) {\n return false;\n }\n }\n }\n return true;\n}\n\nconst WINDOW_MS: Record<string, number> = {\n h: 3_600_000,\n d: 86_400_000,\n w: 604_800_000,\n m: 2_592_000_000,\n};\n\nfunction parseWindowMs(window: string): number | null {\n const match = /^(\\d+)(h|d|w|m)$/.exec(window);\n if (!match) {\n return null;\n }\n const unitMs = WINDOW_MS[match[2]!];\n if (unitMs === undefined) {\n return null;\n }\n return parseInt(match[1]!) * unitMs;\n}\n\nfunction truncateToGranularity(ts: number, granularity: string): string {\n const d = new Date(ts);\n switch (granularity) {\n case 'hour':\n d.setUTCMinutes(0, 0, 0);\n return d.toISOString();\n case 'day':\n d.setUTCHours(0, 0, 0, 0);\n return d.toISOString().slice(0, 10);\n case 'week': {\n d.setUTCDate(d.getUTCDate() - d.getUTCDay());\n d.setUTCHours(0, 0, 0, 0);\n return d.toISOString().slice(0, 10);\n }\n case 'month':\n d.setUTCDate(1);\n d.setUTCHours(0, 0, 0, 0);\n return d.toISOString().slice(0, 7);\n default:\n return d.toISOString().slice(0, 10);\n }\n}\n\nfunction computeAgg(\n records: Record<string, unknown>[],\n field: string | undefined,\n fn: string,\n): unknown {\n if (fn === 'count') {\n return records.length;\n }\n if (field === undefined) {\n throw new Error(`computeAgg: fn \"${fn}\" requires a field`);\n }\n if (fn === 'latest') {\n return records.at(-1)?.[field] ?? null;\n }\n if (fn === 'first') {\n return records[0]?.[field] ?? null;\n }\n const values = records\n .map((r) => r[field])\n .filter((v) => v !== undefined && v !== null);\n const nonNumeric = values.find((v) => typeof v !== 'number');\n if (nonNumeric !== undefined) {\n throw new Error(\n `computeAgg: fn \"${fn}\" requires numeric values for field \"${field}\", got ${typeof nonNumeric} (${String(nonNumeric)})`,\n );\n }\n const numbers = values as number[];\n if (fn === 'sum') {\n return numbers.reduce((a, b) => a + b, 0);\n }\n if (fn === 'avg') {\n return numbers.length > 0\n ? numbers.reduce((a, b) => a + b, 0) / numbers.length\n : null;\n }\n if (fn === 'min') {\n return numbers.length > 0\n ? numbers.reduce((a, b) => (a < b ? a : b))\n : null;\n }\n if (fn === 'max') {\n return numbers.length > 0\n ? numbers.reduce((a, b) => (a > b ? a : b))\n : null;\n }\n return null;\n}\n\nfunction sortByTs(\n records: Record<string, unknown>[],\n tsField: string,\n): Record<string, unknown>[] {\n return [...records].sort((a, b) => {\n return (a[tsField] as number) - (b[tsField] as number);\n });\n}\n\nfunction computeGroupBy(\n records: Record<string, unknown>[],\n metric: ResolvedMetric,\n tsField: string,\n): unknown {\n const { field, granularity } = metric.groupBy!;\n const groups = new Map<string, Record<string, unknown>[]>();\n\n for (const record of records) {\n const ts = record[field] as number | undefined;\n if (ts === undefined || typeof ts !== 'number') {\n continue;\n }\n const key = truncateToGranularity(ts, granularity);\n if (!groups.has(key)) {\n groups.set(key, []);\n }\n groups.get(key)!.push(record);\n }\n\n return [...groups.entries()]\n .map(([key, groupRecords]) => ({\n date: key,\n value: computeAgg(\n sortByTs(groupRecords, tsField),\n metric.field,\n metric.fn,\n ),\n }))\n .sort((a, b) => (a.date < b.date ? -1 : 1));\n}\n\nfunction getTimestampField(shape: string): string {\n switch (shape) {\n case 'event':\n return 'start_ts';\n case 'metric':\n case 'distribution':\n return 'ts';\n case 'entity':\n case 'edge':\n return 'updated_at';\n default:\n return 'start_ts';\n }\n}\n\nexport async function computeMetric(\n storage: StorageHandle,\n metric: ResolvedMetric,\n): Promise<unknown> {\n const tsField = getTimestampField(metric.shape);\n\n const windowMs = metric.window ? parseWindowMs(metric.window) : null;\n const windowStart = windowMs !== null ? Date.now() - windowMs : undefined;\n\n let records: Record<string, unknown>[];\n\n switch (metric.shape) {\n case 'event': {\n const events = await storage.queryEvents({\n name: metric.name,\n start: windowStart,\n });\n records = events.map((e) => ({\n ...e.attributes,\n name: e.name,\n start_ts: e.start_ts,\n end_ts: e.end_ts,\n }));\n break;\n }\n\n case 'entity': {\n const type = metric.entityType ?? metric.name ?? '';\n const entities = await storage.queryEntities({ type });\n records = entities.map((e) => ({\n ...e.attributes,\n type: e.type,\n id: e.id,\n updated_at: e.updated_at,\n }));\n if (windowStart !== undefined) {\n records = records.filter((r) => (r[tsField] as number) >= windowStart);\n }\n break;\n }\n\n case 'metric': {\n const metrics = await storage.queryMetrics({\n name: metric.name,\n start: windowStart,\n });\n records = metrics.map((m) => ({\n ...m.attributes,\n name: m.name,\n ts: m.ts,\n value: m.value,\n }));\n break;\n }\n\n case 'edge': {\n const edges = await storage.traverse({ kind: metric.name });\n records = edges.map((e) => ({\n ...e.attributes,\n from_type: e.from_type,\n from_id: e.from_id,\n kind: e.kind,\n to_type: e.to_type,\n to_id: e.to_id,\n updated_at: e.updated_at,\n }));\n if (windowStart !== undefined) {\n records = records.filter((r) => (r[tsField] as number) >= windowStart);\n }\n break;\n }\n\n case 'distribution': {\n const distributions = await storage.queryDistributions({\n name: metric.name,\n start: windowStart,\n });\n records = distributions.map((d) => ({\n ...d.attributes,\n name: d.name,\n ts: d.ts,\n kind: d.kind,\n data: d.data,\n }));\n break;\n }\n\n default:\n return null;\n }\n\n const filtered = records.filter((r) => applyFilter(r, metric.filter));\n const sorted = sortByTs(filtered, tsField);\n\n if (metric.groupBy) {\n return computeGroupBy(sorted, metric, tsField);\n }\n\n return computeAgg(sorted, metric.field, metric.fn);\n}\n","import { computeMetric } from './compute';\nimport type { ConnectorEntry, Widget } from './config';\nimport type { WidgetEntry } from './engine';\nimport type { ServerStorage } from './server-storage';\n\nexport async function resolveWidget(\n id: string,\n widget: Widget,\n connectors: ConnectorEntry[] | readonly string[] | undefined,\n storage: ServerStorage,\n): Promise<WidgetEntry | undefined> {\n if (widget.kind === 'status') {\n return {\n id,\n widgetId: id,\n connectorId: widget.source,\n data: null,\n cachedAt: null,\n };\n }\n const { connectorId } = widget.metric;\n if (\n connectors !== undefined &&\n !isAllowedConnector(connectors, connectorId)\n ) {\n return undefined;\n }\n const handle = storage.getStorageHandle(connectorId);\n const data = await computeMetric(handle, widget.metric);\n return {\n id,\n widgetId: id,\n connectorId,\n data,\n cachedAt: (await storage.getSyncState()).lastSyncAt,\n };\n}\n\nfunction isAllowedConnector(\n connectors: ConnectorEntry[] | readonly string[],\n connectorId: string,\n): boolean {\n if (connectors.length === 0) {\n return false;\n }\n if (typeof connectors[0] === 'string') {\n return (connectors as readonly string[]).includes(connectorId);\n }\n return (connectors as ConnectorEntry[]).some(\n (e) => e.connector.id === connectorId,\n );\n}\n","import type {\n Distribution,\n DistributionQuery,\n Edge,\n EdgeQuery,\n Entity,\n EntityQuery,\n Event,\n EventQuery,\n Metric,\n MetricQuery,\n StorageHandle,\n} from './connector';\nimport type { SyncState } from './engine';\nimport type { ServerStorage } from './server-storage';\n\nexport class InMemoryStorage implements ServerStorage {\n private eventStore = new Map<string, Event[]>();\n private entityStore = new Map<string, Map<string, Map<string, Entity>>>();\n private metricStore = new Map<string, Metric[]>();\n private edgeStore = new Map<string, Edge[]>();\n private distributionStore = new Map<string, Distribution[]>();\n private syncState: SyncState = {\n status: 'idle',\n lastSyncAt: null,\n lastError: null,\n };\n\n getStorageHandle(connectorId: string): StorageHandle {\n const getEntityMap = (): Map<string, Map<string, Entity>> => {\n if (!this.entityStore.has(connectorId)) {\n this.entityStore.set(connectorId, new Map());\n }\n return this.entityStore.get(connectorId)!;\n };\n\n const upsertEntities = (es: Entity[]): void => {\n const byType = getEntityMap();\n for (const e of es) {\n if (!byType.has(e.type)) {\n byType.set(e.type, new Map());\n }\n byType.get(e.type)!.set(e.id, e);\n }\n };\n\n const upsertEdges = (es: Edge[]): void => {\n const existing = this.edgeStore.get(connectorId) ?? [];\n const index = new Map<string, number>();\n for (let i = 0; i < existing.length; i++) {\n const e = existing[i]!;\n index.set(\n `${e.from_type}:${e.from_id}:${e.kind}:${e.to_type}:${e.to_id}`,\n i,\n );\n }\n for (const e of es) {\n const key = `${e.from_type}:${e.from_id}:${e.kind}:${e.to_type}:${e.to_id}`;\n const idx = index.get(key);\n if (idx !== undefined) {\n existing[idx] = e;\n } else {\n index.set(key, existing.length);\n existing.push(e);\n }\n }\n this.edgeStore.set(connectorId, existing);\n };\n\n return {\n event: async (e) => {\n if (!this.eventStore.has(connectorId)) {\n this.eventStore.set(connectorId, []);\n }\n this.eventStore.get(connectorId)!.push(e);\n },\n\n entity: async (e) => {\n upsertEntities([e]);\n },\n\n metric: async (m) => {\n if (!this.metricStore.has(connectorId)) {\n this.metricStore.set(connectorId, []);\n }\n this.metricStore.get(connectorId)!.push(m);\n },\n\n edge: async (e) => {\n upsertEdges([e]);\n },\n\n distribution: async (d) => {\n if (!this.distributionStore.has(connectorId)) {\n this.distributionStore.set(connectorId, []);\n }\n this.distributionStore.get(connectorId)!.push(d);\n },\n\n events: async (es, scope) => {\n const names = new Set(scope?.names ?? es.map((e) => e.name));\n const kept = (this.eventStore.get(connectorId) ?? []).filter(\n (e) => !names.has(e.name),\n );\n this.eventStore.set(connectorId, [...kept, ...es]);\n },\n\n entities: async (es, scope) => {\n const byType = getEntityMap();\n const types = new Set(scope?.types ?? es.map((e) => e.type));\n for (const type of types) {\n byType.set(type, new Map());\n }\n upsertEntities(es);\n },\n\n metrics: async (ms, scope) => {\n const names = new Set(scope?.names ?? ms.map((m) => m.name));\n const kept = (this.metricStore.get(connectorId) ?? []).filter(\n (m) => !names.has(m.name),\n );\n this.metricStore.set(connectorId, [...kept, ...ms]);\n },\n\n edges: async (es, scope) => {\n const kinds = new Set(scope?.kinds ?? es.map((e) => e.kind));\n const kept = (this.edgeStore.get(connectorId) ?? []).filter(\n (e) => !kinds.has(e.kind),\n );\n this.edgeStore.set(connectorId, kept);\n upsertEdges(es);\n },\n\n distributions: async (ds, scope) => {\n const names = new Set(scope?.names ?? ds.map((d) => d.name));\n const kept = (this.distributionStore.get(connectorId) ?? []).filter(\n (d) => !names.has(d.name),\n );\n this.distributionStore.set(connectorId, [...kept, ...ds]);\n },\n\n queryEvents: async (q: EventQuery) => {\n let results = this.eventStore.get(connectorId) ?? [];\n if (q.name !== undefined) {\n results = results.filter((e) => e.name === q.name);\n }\n if (q.start !== undefined) {\n results = results.filter((e) => e.start_ts >= q.start!);\n }\n if (q.end !== undefined) {\n results = results.filter((e) => e.start_ts <= q.end!);\n }\n return results;\n },\n\n getEntity: async (type: string, id: string) => {\n return getEntityMap().get(type)?.get(id) ?? null;\n },\n\n queryEntities: async (q: EntityQuery) => {\n const byType = getEntityMap().get(q.type);\n if (!byType) {\n return [];\n }\n return Array.from(byType.values());\n },\n\n queryMetrics: async (q: MetricQuery) => {\n let results = this.metricStore.get(connectorId) ?? [];\n if (q.name !== undefined) {\n results = results.filter((m) => m.name === q.name);\n }\n if (q.start !== undefined) {\n results = results.filter((m) => m.ts >= q.start!);\n }\n if (q.end !== undefined) {\n results = results.filter((m) => m.ts <= q.end!);\n }\n return results;\n },\n\n traverse: async (q: EdgeQuery) => {\n let results = this.edgeStore.get(connectorId) ?? [];\n if (q.fromType !== undefined) {\n results = results.filter((e) => e.from_type === q.fromType);\n }\n if (q.fromId !== undefined) {\n results = results.filter((e) => e.from_id === q.fromId);\n }\n if (q.kind !== undefined) {\n results = results.filter((e) => e.kind === q.kind);\n }\n if (q.toType !== undefined) {\n results = results.filter((e) => e.to_type === q.toType);\n }\n if (q.toId !== undefined) {\n results = results.filter((e) => e.to_id === q.toId);\n }\n return results;\n },\n\n queryDistributions: async (q: DistributionQuery) => {\n let results = this.distributionStore.get(connectorId) ?? [];\n if (q.name !== undefined) {\n results = results.filter((d) => d.name === q.name);\n }\n if (q.start !== undefined) {\n results = results.filter((d) => d.ts >= q.start!);\n }\n if (q.end !== undefined) {\n results = results.filter((d) => d.ts <= q.end!);\n }\n return results;\n },\n\n deleteOlderThan: async (shape, tsUnixMs) => {\n if (shape === 'events') {\n const before = this.eventStore.get(connectorId) ?? [];\n const after = before.filter((e) => e.start_ts >= tsUnixMs);\n this.eventStore.set(connectorId, after);\n return { rowsDeleted: before.length - after.length };\n } else if (shape === 'metrics') {\n const before = this.metricStore.get(connectorId) ?? [];\n const after = before.filter((m) => m.ts >= tsUnixMs);\n this.metricStore.set(connectorId, after);\n return { rowsDeleted: before.length - after.length };\n } else if (shape === 'distributions') {\n const before = this.distributionStore.get(connectorId) ?? [];\n const after = before.filter((d) => d.ts >= tsUnixMs);\n this.distributionStore.set(connectorId, after);\n return { rowsDeleted: before.length - after.length };\n } else {\n throw new Error(\n `Unsupported shape for deleteOlderThan: ${String(shape)}`,\n );\n }\n },\n };\n }\n\n async getSyncState(): Promise<SyncState> {\n return { ...this.syncState };\n }\n\n async setSyncing(): Promise<boolean> {\n if (this.syncState.status === 'syncing') {\n return false;\n }\n this.syncState = { ...this.syncState, status: 'syncing' };\n return true;\n }\n\n async setSyncSuccess(): Promise<void> {\n this.syncState = {\n status: 'idle',\n lastSyncAt: new Date().toISOString(),\n lastError: null,\n };\n }\n\n async setSyncError(error: string): Promise<void> {\n this.syncState = {\n status: 'error',\n lastSyncAt: this.syncState.lastSyncAt,\n lastError: error,\n };\n }\n}\n"],"mappings":"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","names":["z"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rawdash/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Rawdash core — headless dashboard backend primitives",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"zod": "^4.4.3"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"@libsql/client": "
|
|
39
|
+
"@libsql/client": ">=0.14.0 <1.0.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependenciesMeta": {
|
|
42
42
|
"@libsql/client": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
}
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@libsql/client": "^0.
|
|
47
|
+
"@libsql/client": "^0.17.0",
|
|
48
48
|
"tsup": "^8.0.0",
|
|
49
49
|
"typescript": "^5.7.2"
|
|
50
50
|
}
|