@rawdash/core 0.1.1 → 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 +928 -210
- package/dist/index.js +635 -33
- package/dist/index.js.map +1 -1
- package/dist/libsql.d.ts +23 -0
- package/dist/libsql.js +509 -0
- package/dist/libsql.js.map +1 -0
- package/dist/server-storage-BGSLkDoF.d.ts +209 -0
- package/package.json +22 -8
- package/LICENSE +0 -202
package/dist/index.js
CHANGED
|
@@ -133,32 +133,108 @@ function defineConnector() {
|
|
|
133
133
|
|
|
134
134
|
// src/widget-schemas.ts
|
|
135
135
|
import { z } from "zod";
|
|
136
|
-
var
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
136
|
+
var shapeSchema = z.enum([
|
|
137
|
+
"event",
|
|
138
|
+
"entity",
|
|
139
|
+
"metric",
|
|
140
|
+
"edge",
|
|
141
|
+
"distribution"
|
|
142
|
+
]);
|
|
143
|
+
var aggFnSchema = z.enum([
|
|
144
|
+
"count",
|
|
145
|
+
"sum",
|
|
146
|
+
"avg",
|
|
147
|
+
"min",
|
|
148
|
+
"max",
|
|
149
|
+
"latest",
|
|
150
|
+
"first"
|
|
151
|
+
]);
|
|
152
|
+
var filterOperatorSchema = z.enum([
|
|
153
|
+
"eq",
|
|
154
|
+
"neq",
|
|
155
|
+
"gt",
|
|
156
|
+
"gte",
|
|
157
|
+
"lt",
|
|
158
|
+
"lte",
|
|
159
|
+
"contains"
|
|
160
|
+
]);
|
|
161
|
+
var filterConditionSchema = z.object({
|
|
162
|
+
field: z.string(),
|
|
163
|
+
op: filterOperatorSchema,
|
|
164
|
+
value: z.union([z.string(), z.number(), z.boolean()])
|
|
165
|
+
});
|
|
166
|
+
var filterClauseSchema = z.union([
|
|
167
|
+
filterConditionSchema,
|
|
168
|
+
z.object({ or: z.array(filterConditionSchema) })
|
|
169
|
+
]);
|
|
170
|
+
var groupBySchema = z.object({
|
|
171
|
+
field: z.string(),
|
|
172
|
+
granularity: z.enum(["hour", "day", "week", "month"])
|
|
173
|
+
});
|
|
174
|
+
var resolvedMetricSchema = z.object({
|
|
175
|
+
connectorId: z.string(),
|
|
176
|
+
shape: shapeSchema,
|
|
177
|
+
name: z.string().optional(),
|
|
178
|
+
entityType: z.string().optional(),
|
|
179
|
+
field: z.string().optional(),
|
|
180
|
+
fn: aggFnSchema,
|
|
181
|
+
window: z.string().optional(),
|
|
182
|
+
filter: z.array(filterClauseSchema).optional(),
|
|
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"]
|
|
187
|
+
});
|
|
188
|
+
var titleField = z.string().meta({ label: "Title", description: "Widget title." });
|
|
189
|
+
var statWidgetSchema = z.object({
|
|
190
|
+
kind: z.literal("stat"),
|
|
191
|
+
title: titleField,
|
|
192
|
+
metric: resolvedMetricSchema.meta({
|
|
193
|
+
label: "Metric",
|
|
194
|
+
description: "Resolved metric definition."
|
|
142
195
|
}),
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
196
|
+
window: z.string().optional().meta({ label: "Window", description: "Time window, e.g. '7d'." }),
|
|
197
|
+
compare: z.enum(["none", "previous-period"]).default("none").meta({ label: "Compare", description: "Comparison mode." })
|
|
198
|
+
});
|
|
199
|
+
var statusWidgetSchema = z.object({
|
|
200
|
+
kind: z.literal("status"),
|
|
201
|
+
title: titleField,
|
|
202
|
+
source: z.string().meta({
|
|
203
|
+
label: "Source",
|
|
204
|
+
description: "Connector or data source reference."
|
|
205
|
+
})
|
|
206
|
+
});
|
|
207
|
+
var timeseriesWidgetSchema = z.object({
|
|
208
|
+
kind: z.literal("timeseries"),
|
|
209
|
+
title: titleField,
|
|
210
|
+
metric: resolvedMetricSchema.meta({
|
|
211
|
+
label: "Metric",
|
|
212
|
+
description: "Resolved metric definition."
|
|
149
213
|
}),
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
214
|
+
window: z.string().meta({ label: "Window", description: "Time window, e.g. '30d'." }),
|
|
215
|
+
granularity: z.enum(["hour", "day", "week"]).default("day").meta({ label: "Granularity", description: "Time bucket size." })
|
|
216
|
+
});
|
|
217
|
+
var distributionWidgetSchema = z.object({
|
|
218
|
+
kind: z.literal("distribution"),
|
|
219
|
+
title: titleField,
|
|
220
|
+
metric: resolvedMetricSchema.meta({
|
|
221
|
+
label: "Metric",
|
|
222
|
+
description: "Resolved metric definition."
|
|
155
223
|
}),
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
224
|
+
window: z.string().meta({ label: "Window", description: "Time window, e.g. '7d'." })
|
|
225
|
+
});
|
|
226
|
+
var widgetSchemas = {
|
|
227
|
+
stat: statWidgetSchema,
|
|
228
|
+
status: statusWidgetSchema,
|
|
229
|
+
timeseries: timeseriesWidgetSchema,
|
|
230
|
+
distribution: distributionWidgetSchema
|
|
161
231
|
};
|
|
232
|
+
var widgetSchema = z.discriminatedUnion("kind", [
|
|
233
|
+
statWidgetSchema,
|
|
234
|
+
statusWidgetSchema,
|
|
235
|
+
timeseriesWidgetSchema,
|
|
236
|
+
distributionWidgetSchema
|
|
237
|
+
]);
|
|
162
238
|
function getWidgetSchema(kind) {
|
|
163
239
|
return widgetSchemas[kind];
|
|
164
240
|
}
|
|
@@ -173,17 +249,7 @@ function defineDashboard(options) {
|
|
|
173
249
|
);
|
|
174
250
|
}
|
|
175
251
|
const schema = getWidgetSchema(widget.kind);
|
|
176
|
-
const
|
|
177
|
-
if (widget.kind !== "status") {
|
|
178
|
-
const m = widget.metric;
|
|
179
|
-
if (typeof m !== "object" || m === null) {
|
|
180
|
-
throw new Error(
|
|
181
|
-
`Widget "${key}" (kind "${widget.kind}"): metric is required`
|
|
182
|
-
);
|
|
183
|
-
}
|
|
184
|
-
parseInput.metric = "placeholder";
|
|
185
|
-
}
|
|
186
|
-
const result = schema.safeParse(parseInput);
|
|
252
|
+
const result = schema.safeParse(widget);
|
|
187
253
|
if (!result.success) {
|
|
188
254
|
throw new Error(
|
|
189
255
|
`Widget "${key}" (kind "${widget.kind}"): ${result.error.issues.map((i) => i.message).join("; ")}`
|
|
@@ -336,20 +402,556 @@ function defineConfigFields(schema) {
|
|
|
336
402
|
}
|
|
337
403
|
return schema;
|
|
338
404
|
}
|
|
405
|
+
|
|
406
|
+
// src/compute.ts
|
|
407
|
+
function matchesCondition(record, cond) {
|
|
408
|
+
const val = record[cond.field];
|
|
409
|
+
switch (cond.op) {
|
|
410
|
+
case "eq":
|
|
411
|
+
return val === cond.value;
|
|
412
|
+
case "neq":
|
|
413
|
+
return val !== cond.value;
|
|
414
|
+
case "gt":
|
|
415
|
+
if (typeof val !== "number" || typeof cond.value !== "number") {
|
|
416
|
+
return false;
|
|
417
|
+
}
|
|
418
|
+
return val > cond.value;
|
|
419
|
+
case "gte":
|
|
420
|
+
if (typeof val !== "number" || typeof cond.value !== "number") {
|
|
421
|
+
return false;
|
|
422
|
+
}
|
|
423
|
+
return val >= cond.value;
|
|
424
|
+
case "lt":
|
|
425
|
+
if (typeof val !== "number" || typeof cond.value !== "number") {
|
|
426
|
+
return false;
|
|
427
|
+
}
|
|
428
|
+
return val < cond.value;
|
|
429
|
+
case "lte":
|
|
430
|
+
if (typeof val !== "number" || typeof cond.value !== "number") {
|
|
431
|
+
return false;
|
|
432
|
+
}
|
|
433
|
+
return val <= cond.value;
|
|
434
|
+
case "contains":
|
|
435
|
+
return String(val).includes(String(cond.value));
|
|
436
|
+
default:
|
|
437
|
+
return false;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
function applyFilter(record, filter) {
|
|
441
|
+
if (!filter) {
|
|
442
|
+
return true;
|
|
443
|
+
}
|
|
444
|
+
for (const clause of filter) {
|
|
445
|
+
if ("or" in clause) {
|
|
446
|
+
if (!clause.or.some((cond) => matchesCondition(record, cond))) {
|
|
447
|
+
return false;
|
|
448
|
+
}
|
|
449
|
+
} else {
|
|
450
|
+
if (!matchesCondition(record, clause)) {
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
return true;
|
|
456
|
+
}
|
|
457
|
+
var WINDOW_MS = {
|
|
458
|
+
h: 36e5,
|
|
459
|
+
d: 864e5,
|
|
460
|
+
w: 6048e5,
|
|
461
|
+
m: 2592e6
|
|
462
|
+
};
|
|
463
|
+
function parseWindowMs(window) {
|
|
464
|
+
const match = /^(\d+)(h|d|w|m)$/.exec(window);
|
|
465
|
+
if (!match) {
|
|
466
|
+
return null;
|
|
467
|
+
}
|
|
468
|
+
const unitMs = WINDOW_MS[match[2]];
|
|
469
|
+
if (unitMs === void 0) {
|
|
470
|
+
return null;
|
|
471
|
+
}
|
|
472
|
+
return parseInt(match[1]) * unitMs;
|
|
473
|
+
}
|
|
474
|
+
function truncateToGranularity(ts, granularity) {
|
|
475
|
+
const d = new Date(ts);
|
|
476
|
+
switch (granularity) {
|
|
477
|
+
case "hour":
|
|
478
|
+
d.setUTCMinutes(0, 0, 0);
|
|
479
|
+
return d.toISOString();
|
|
480
|
+
case "day":
|
|
481
|
+
d.setUTCHours(0, 0, 0, 0);
|
|
482
|
+
return d.toISOString().slice(0, 10);
|
|
483
|
+
case "week": {
|
|
484
|
+
d.setUTCDate(d.getUTCDate() - d.getUTCDay());
|
|
485
|
+
d.setUTCHours(0, 0, 0, 0);
|
|
486
|
+
return d.toISOString().slice(0, 10);
|
|
487
|
+
}
|
|
488
|
+
case "month":
|
|
489
|
+
d.setUTCDate(1);
|
|
490
|
+
d.setUTCHours(0, 0, 0, 0);
|
|
491
|
+
return d.toISOString().slice(0, 7);
|
|
492
|
+
default:
|
|
493
|
+
return d.toISOString().slice(0, 10);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
function computeAgg(records, field, fn) {
|
|
497
|
+
if (fn === "count") {
|
|
498
|
+
return records.length;
|
|
499
|
+
}
|
|
500
|
+
if (field === void 0) {
|
|
501
|
+
throw new Error(`computeAgg: fn "${fn}" requires a field`);
|
|
502
|
+
}
|
|
503
|
+
if (fn === "latest") {
|
|
504
|
+
return records.at(-1)?.[field] ?? null;
|
|
505
|
+
}
|
|
506
|
+
if (fn === "first") {
|
|
507
|
+
return records[0]?.[field] ?? null;
|
|
508
|
+
}
|
|
509
|
+
const values = records.map((r) => r[field]).filter((v) => v !== void 0 && v !== null);
|
|
510
|
+
const nonNumeric = values.find((v) => typeof v !== "number");
|
|
511
|
+
if (nonNumeric !== void 0) {
|
|
512
|
+
throw new Error(
|
|
513
|
+
`computeAgg: fn "${fn}" requires numeric values for field "${field}", got ${typeof nonNumeric} (${String(nonNumeric)})`
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
const numbers = values;
|
|
517
|
+
if (fn === "sum") {
|
|
518
|
+
return numbers.reduce((a, b) => a + b, 0);
|
|
519
|
+
}
|
|
520
|
+
if (fn === "avg") {
|
|
521
|
+
return numbers.length > 0 ? numbers.reduce((a, b) => a + b, 0) / numbers.length : null;
|
|
522
|
+
}
|
|
523
|
+
if (fn === "min") {
|
|
524
|
+
return numbers.length > 0 ? numbers.reduce((a, b) => a < b ? a : b) : null;
|
|
525
|
+
}
|
|
526
|
+
if (fn === "max") {
|
|
527
|
+
return numbers.length > 0 ? numbers.reduce((a, b) => a > b ? a : b) : null;
|
|
528
|
+
}
|
|
529
|
+
return null;
|
|
530
|
+
}
|
|
531
|
+
function sortByTs(records, tsField) {
|
|
532
|
+
return [...records].sort((a, b) => {
|
|
533
|
+
return a[tsField] - b[tsField];
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
function computeGroupBy(records, metric, tsField) {
|
|
537
|
+
const { field, granularity } = metric.groupBy;
|
|
538
|
+
const groups = /* @__PURE__ */ new Map();
|
|
539
|
+
for (const record of records) {
|
|
540
|
+
const ts = record[field];
|
|
541
|
+
if (ts === void 0 || typeof ts !== "number") {
|
|
542
|
+
continue;
|
|
543
|
+
}
|
|
544
|
+
const key = truncateToGranularity(ts, granularity);
|
|
545
|
+
if (!groups.has(key)) {
|
|
546
|
+
groups.set(key, []);
|
|
547
|
+
}
|
|
548
|
+
groups.get(key).push(record);
|
|
549
|
+
}
|
|
550
|
+
return [...groups.entries()].map(([key, groupRecords]) => ({
|
|
551
|
+
date: key,
|
|
552
|
+
value: computeAgg(
|
|
553
|
+
sortByTs(groupRecords, tsField),
|
|
554
|
+
metric.field,
|
|
555
|
+
metric.fn
|
|
556
|
+
)
|
|
557
|
+
})).sort((a, b) => a.date < b.date ? -1 : 1);
|
|
558
|
+
}
|
|
559
|
+
function getTimestampField(shape) {
|
|
560
|
+
switch (shape) {
|
|
561
|
+
case "event":
|
|
562
|
+
return "start_ts";
|
|
563
|
+
case "metric":
|
|
564
|
+
case "distribution":
|
|
565
|
+
return "ts";
|
|
566
|
+
case "entity":
|
|
567
|
+
case "edge":
|
|
568
|
+
return "updated_at";
|
|
569
|
+
default:
|
|
570
|
+
return "start_ts";
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
async function computeMetric(storage, metric) {
|
|
574
|
+
const tsField = getTimestampField(metric.shape);
|
|
575
|
+
const windowMs = metric.window ? parseWindowMs(metric.window) : null;
|
|
576
|
+
const windowStart = windowMs !== null ? Date.now() - windowMs : void 0;
|
|
577
|
+
let records;
|
|
578
|
+
switch (metric.shape) {
|
|
579
|
+
case "event": {
|
|
580
|
+
const events = await storage.queryEvents({
|
|
581
|
+
name: metric.name,
|
|
582
|
+
start: windowStart
|
|
583
|
+
});
|
|
584
|
+
records = events.map((e) => ({
|
|
585
|
+
...e.attributes,
|
|
586
|
+
name: e.name,
|
|
587
|
+
start_ts: e.start_ts,
|
|
588
|
+
end_ts: e.end_ts
|
|
589
|
+
}));
|
|
590
|
+
break;
|
|
591
|
+
}
|
|
592
|
+
case "entity": {
|
|
593
|
+
const type = metric.entityType ?? metric.name ?? "";
|
|
594
|
+
const entities = await storage.queryEntities({ type });
|
|
595
|
+
records = entities.map((e) => ({
|
|
596
|
+
...e.attributes,
|
|
597
|
+
type: e.type,
|
|
598
|
+
id: e.id,
|
|
599
|
+
updated_at: e.updated_at
|
|
600
|
+
}));
|
|
601
|
+
if (windowStart !== void 0) {
|
|
602
|
+
records = records.filter((r) => r[tsField] >= windowStart);
|
|
603
|
+
}
|
|
604
|
+
break;
|
|
605
|
+
}
|
|
606
|
+
case "metric": {
|
|
607
|
+
const metrics = await storage.queryMetrics({
|
|
608
|
+
name: metric.name,
|
|
609
|
+
start: windowStart
|
|
610
|
+
});
|
|
611
|
+
records = metrics.map((m) => ({
|
|
612
|
+
...m.attributes,
|
|
613
|
+
name: m.name,
|
|
614
|
+
ts: m.ts,
|
|
615
|
+
value: m.value
|
|
616
|
+
}));
|
|
617
|
+
break;
|
|
618
|
+
}
|
|
619
|
+
case "edge": {
|
|
620
|
+
const edges = await storage.traverse({ kind: metric.name });
|
|
621
|
+
records = edges.map((e) => ({
|
|
622
|
+
...e.attributes,
|
|
623
|
+
from_type: e.from_type,
|
|
624
|
+
from_id: e.from_id,
|
|
625
|
+
kind: e.kind,
|
|
626
|
+
to_type: e.to_type,
|
|
627
|
+
to_id: e.to_id,
|
|
628
|
+
updated_at: e.updated_at
|
|
629
|
+
}));
|
|
630
|
+
if (windowStart !== void 0) {
|
|
631
|
+
records = records.filter((r) => r[tsField] >= windowStart);
|
|
632
|
+
}
|
|
633
|
+
break;
|
|
634
|
+
}
|
|
635
|
+
case "distribution": {
|
|
636
|
+
const distributions = await storage.queryDistributions({
|
|
637
|
+
name: metric.name,
|
|
638
|
+
start: windowStart
|
|
639
|
+
});
|
|
640
|
+
records = distributions.map((d) => ({
|
|
641
|
+
...d.attributes,
|
|
642
|
+
name: d.name,
|
|
643
|
+
ts: d.ts,
|
|
644
|
+
kind: d.kind,
|
|
645
|
+
data: d.data
|
|
646
|
+
}));
|
|
647
|
+
break;
|
|
648
|
+
}
|
|
649
|
+
default:
|
|
650
|
+
return null;
|
|
651
|
+
}
|
|
652
|
+
const filtered = records.filter((r) => applyFilter(r, metric.filter));
|
|
653
|
+
const sorted = sortByTs(filtered, tsField);
|
|
654
|
+
if (metric.groupBy) {
|
|
655
|
+
return computeGroupBy(sorted, metric, tsField);
|
|
656
|
+
}
|
|
657
|
+
return computeAgg(sorted, metric.field, metric.fn);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
// src/resolve-widget.ts
|
|
661
|
+
async function resolveWidget(id, widget, connectors, storage) {
|
|
662
|
+
if (widget.kind === "status") {
|
|
663
|
+
return {
|
|
664
|
+
id,
|
|
665
|
+
widgetId: id,
|
|
666
|
+
connectorId: widget.source,
|
|
667
|
+
data: null,
|
|
668
|
+
cachedAt: null
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
const { connectorId } = widget.metric;
|
|
672
|
+
if (connectors !== void 0 && !isAllowedConnector(connectors, connectorId)) {
|
|
673
|
+
return void 0;
|
|
674
|
+
}
|
|
675
|
+
const handle = storage.getStorageHandle(connectorId);
|
|
676
|
+
const data = await computeMetric(handle, widget.metric);
|
|
677
|
+
return {
|
|
678
|
+
id,
|
|
679
|
+
widgetId: id,
|
|
680
|
+
connectorId,
|
|
681
|
+
data,
|
|
682
|
+
cachedAt: (await storage.getSyncState()).lastSyncAt
|
|
683
|
+
};
|
|
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
|
+
}
|
|
696
|
+
|
|
697
|
+
// src/in-memory-storage.ts
|
|
698
|
+
var InMemoryStorage = class {
|
|
699
|
+
eventStore = /* @__PURE__ */ new Map();
|
|
700
|
+
entityStore = /* @__PURE__ */ new Map();
|
|
701
|
+
metricStore = /* @__PURE__ */ new Map();
|
|
702
|
+
edgeStore = /* @__PURE__ */ new Map();
|
|
703
|
+
distributionStore = /* @__PURE__ */ new Map();
|
|
704
|
+
syncState = {
|
|
705
|
+
status: "idle",
|
|
706
|
+
lastSyncAt: null,
|
|
707
|
+
lastError: null
|
|
708
|
+
};
|
|
709
|
+
getStorageHandle(connectorId) {
|
|
710
|
+
const getEntityMap = () => {
|
|
711
|
+
if (!this.entityStore.has(connectorId)) {
|
|
712
|
+
this.entityStore.set(connectorId, /* @__PURE__ */ new Map());
|
|
713
|
+
}
|
|
714
|
+
return this.entityStore.get(connectorId);
|
|
715
|
+
};
|
|
716
|
+
const upsertEntities = (es) => {
|
|
717
|
+
const byType = getEntityMap();
|
|
718
|
+
for (const e of es) {
|
|
719
|
+
if (!byType.has(e.type)) {
|
|
720
|
+
byType.set(e.type, /* @__PURE__ */ new Map());
|
|
721
|
+
}
|
|
722
|
+
byType.get(e.type).set(e.id, e);
|
|
723
|
+
}
|
|
724
|
+
};
|
|
725
|
+
const upsertEdges = (es) => {
|
|
726
|
+
const existing = this.edgeStore.get(connectorId) ?? [];
|
|
727
|
+
const index = /* @__PURE__ */ new Map();
|
|
728
|
+
for (let i = 0; i < existing.length; i++) {
|
|
729
|
+
const e = existing[i];
|
|
730
|
+
index.set(
|
|
731
|
+
`${e.from_type}:${e.from_id}:${e.kind}:${e.to_type}:${e.to_id}`,
|
|
732
|
+
i
|
|
733
|
+
);
|
|
734
|
+
}
|
|
735
|
+
for (const e of es) {
|
|
736
|
+
const key = `${e.from_type}:${e.from_id}:${e.kind}:${e.to_type}:${e.to_id}`;
|
|
737
|
+
const idx = index.get(key);
|
|
738
|
+
if (idx !== void 0) {
|
|
739
|
+
existing[idx] = e;
|
|
740
|
+
} else {
|
|
741
|
+
index.set(key, existing.length);
|
|
742
|
+
existing.push(e);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
this.edgeStore.set(connectorId, existing);
|
|
746
|
+
};
|
|
747
|
+
return {
|
|
748
|
+
event: async (e) => {
|
|
749
|
+
if (!this.eventStore.has(connectorId)) {
|
|
750
|
+
this.eventStore.set(connectorId, []);
|
|
751
|
+
}
|
|
752
|
+
this.eventStore.get(connectorId).push(e);
|
|
753
|
+
},
|
|
754
|
+
entity: async (e) => {
|
|
755
|
+
upsertEntities([e]);
|
|
756
|
+
},
|
|
757
|
+
metric: async (m) => {
|
|
758
|
+
if (!this.metricStore.has(connectorId)) {
|
|
759
|
+
this.metricStore.set(connectorId, []);
|
|
760
|
+
}
|
|
761
|
+
this.metricStore.get(connectorId).push(m);
|
|
762
|
+
},
|
|
763
|
+
edge: async (e) => {
|
|
764
|
+
upsertEdges([e]);
|
|
765
|
+
},
|
|
766
|
+
distribution: async (d) => {
|
|
767
|
+
if (!this.distributionStore.has(connectorId)) {
|
|
768
|
+
this.distributionStore.set(connectorId, []);
|
|
769
|
+
}
|
|
770
|
+
this.distributionStore.get(connectorId).push(d);
|
|
771
|
+
},
|
|
772
|
+
events: async (es, scope) => {
|
|
773
|
+
const names = new Set(scope?.names ?? es.map((e) => e.name));
|
|
774
|
+
const kept = (this.eventStore.get(connectorId) ?? []).filter(
|
|
775
|
+
(e) => !names.has(e.name)
|
|
776
|
+
);
|
|
777
|
+
this.eventStore.set(connectorId, [...kept, ...es]);
|
|
778
|
+
},
|
|
779
|
+
entities: async (es, scope) => {
|
|
780
|
+
const byType = getEntityMap();
|
|
781
|
+
const types = new Set(scope?.types ?? es.map((e) => e.type));
|
|
782
|
+
for (const type of types) {
|
|
783
|
+
byType.set(type, /* @__PURE__ */ new Map());
|
|
784
|
+
}
|
|
785
|
+
upsertEntities(es);
|
|
786
|
+
},
|
|
787
|
+
metrics: async (ms, scope) => {
|
|
788
|
+
const names = new Set(scope?.names ?? ms.map((m) => m.name));
|
|
789
|
+
const kept = (this.metricStore.get(connectorId) ?? []).filter(
|
|
790
|
+
(m) => !names.has(m.name)
|
|
791
|
+
);
|
|
792
|
+
this.metricStore.set(connectorId, [...kept, ...ms]);
|
|
793
|
+
},
|
|
794
|
+
edges: async (es, scope) => {
|
|
795
|
+
const kinds = new Set(scope?.kinds ?? es.map((e) => e.kind));
|
|
796
|
+
const kept = (this.edgeStore.get(connectorId) ?? []).filter(
|
|
797
|
+
(e) => !kinds.has(e.kind)
|
|
798
|
+
);
|
|
799
|
+
this.edgeStore.set(connectorId, kept);
|
|
800
|
+
upsertEdges(es);
|
|
801
|
+
},
|
|
802
|
+
distributions: async (ds, scope) => {
|
|
803
|
+
const names = new Set(scope?.names ?? ds.map((d) => d.name));
|
|
804
|
+
const kept = (this.distributionStore.get(connectorId) ?? []).filter(
|
|
805
|
+
(d) => !names.has(d.name)
|
|
806
|
+
);
|
|
807
|
+
this.distributionStore.set(connectorId, [...kept, ...ds]);
|
|
808
|
+
},
|
|
809
|
+
queryEvents: async (q) => {
|
|
810
|
+
let results = this.eventStore.get(connectorId) ?? [];
|
|
811
|
+
if (q.name !== void 0) {
|
|
812
|
+
results = results.filter((e) => e.name === q.name);
|
|
813
|
+
}
|
|
814
|
+
if (q.start !== void 0) {
|
|
815
|
+
results = results.filter((e) => e.start_ts >= q.start);
|
|
816
|
+
}
|
|
817
|
+
if (q.end !== void 0) {
|
|
818
|
+
results = results.filter((e) => e.start_ts <= q.end);
|
|
819
|
+
}
|
|
820
|
+
return results;
|
|
821
|
+
},
|
|
822
|
+
getEntity: async (type, id) => {
|
|
823
|
+
return getEntityMap().get(type)?.get(id) ?? null;
|
|
824
|
+
},
|
|
825
|
+
queryEntities: async (q) => {
|
|
826
|
+
const byType = getEntityMap().get(q.type);
|
|
827
|
+
if (!byType) {
|
|
828
|
+
return [];
|
|
829
|
+
}
|
|
830
|
+
return Array.from(byType.values());
|
|
831
|
+
},
|
|
832
|
+
queryMetrics: async (q) => {
|
|
833
|
+
let results = this.metricStore.get(connectorId) ?? [];
|
|
834
|
+
if (q.name !== void 0) {
|
|
835
|
+
results = results.filter((m) => m.name === q.name);
|
|
836
|
+
}
|
|
837
|
+
if (q.start !== void 0) {
|
|
838
|
+
results = results.filter((m) => m.ts >= q.start);
|
|
839
|
+
}
|
|
840
|
+
if (q.end !== void 0) {
|
|
841
|
+
results = results.filter((m) => m.ts <= q.end);
|
|
842
|
+
}
|
|
843
|
+
return results;
|
|
844
|
+
},
|
|
845
|
+
traverse: async (q) => {
|
|
846
|
+
let results = this.edgeStore.get(connectorId) ?? [];
|
|
847
|
+
if (q.fromType !== void 0) {
|
|
848
|
+
results = results.filter((e) => e.from_type === q.fromType);
|
|
849
|
+
}
|
|
850
|
+
if (q.fromId !== void 0) {
|
|
851
|
+
results = results.filter((e) => e.from_id === q.fromId);
|
|
852
|
+
}
|
|
853
|
+
if (q.kind !== void 0) {
|
|
854
|
+
results = results.filter((e) => e.kind === q.kind);
|
|
855
|
+
}
|
|
856
|
+
if (q.toType !== void 0) {
|
|
857
|
+
results = results.filter((e) => e.to_type === q.toType);
|
|
858
|
+
}
|
|
859
|
+
if (q.toId !== void 0) {
|
|
860
|
+
results = results.filter((e) => e.to_id === q.toId);
|
|
861
|
+
}
|
|
862
|
+
return results;
|
|
863
|
+
},
|
|
864
|
+
queryDistributions: async (q) => {
|
|
865
|
+
let results = this.distributionStore.get(connectorId) ?? [];
|
|
866
|
+
if (q.name !== void 0) {
|
|
867
|
+
results = results.filter((d) => d.name === q.name);
|
|
868
|
+
}
|
|
869
|
+
if (q.start !== void 0) {
|
|
870
|
+
results = results.filter((d) => d.ts >= q.start);
|
|
871
|
+
}
|
|
872
|
+
if (q.end !== void 0) {
|
|
873
|
+
results = results.filter((d) => d.ts <= q.end);
|
|
874
|
+
}
|
|
875
|
+
return results;
|
|
876
|
+
},
|
|
877
|
+
deleteOlderThan: async (shape, tsUnixMs) => {
|
|
878
|
+
if (shape === "events") {
|
|
879
|
+
const before = this.eventStore.get(connectorId) ?? [];
|
|
880
|
+
const after = before.filter((e) => e.start_ts >= tsUnixMs);
|
|
881
|
+
this.eventStore.set(connectorId, after);
|
|
882
|
+
return { rowsDeleted: before.length - after.length };
|
|
883
|
+
} else if (shape === "metrics") {
|
|
884
|
+
const before = this.metricStore.get(connectorId) ?? [];
|
|
885
|
+
const after = before.filter((m) => m.ts >= tsUnixMs);
|
|
886
|
+
this.metricStore.set(connectorId, after);
|
|
887
|
+
return { rowsDeleted: before.length - after.length };
|
|
888
|
+
} else if (shape === "distributions") {
|
|
889
|
+
const before = this.distributionStore.get(connectorId) ?? [];
|
|
890
|
+
const after = before.filter((d) => d.ts >= tsUnixMs);
|
|
891
|
+
this.distributionStore.set(connectorId, after);
|
|
892
|
+
return { rowsDeleted: before.length - after.length };
|
|
893
|
+
} else {
|
|
894
|
+
throw new Error(
|
|
895
|
+
`Unsupported shape for deleteOlderThan: ${String(shape)}`
|
|
896
|
+
);
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
async getSyncState() {
|
|
902
|
+
return { ...this.syncState };
|
|
903
|
+
}
|
|
904
|
+
async setSyncing() {
|
|
905
|
+
if (this.syncState.status === "syncing") {
|
|
906
|
+
return false;
|
|
907
|
+
}
|
|
908
|
+
this.syncState = { ...this.syncState, status: "syncing" };
|
|
909
|
+
return true;
|
|
910
|
+
}
|
|
911
|
+
async setSyncSuccess() {
|
|
912
|
+
this.syncState = {
|
|
913
|
+
status: "idle",
|
|
914
|
+
lastSyncAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
915
|
+
lastError: null
|
|
916
|
+
};
|
|
917
|
+
}
|
|
918
|
+
async setSyncError(error) {
|
|
919
|
+
this.syncState = {
|
|
920
|
+
status: "error",
|
|
921
|
+
lastSyncAt: this.syncState.lastSyncAt,
|
|
922
|
+
lastError: error
|
|
923
|
+
};
|
|
924
|
+
}
|
|
925
|
+
};
|
|
339
926
|
export {
|
|
340
927
|
BaseConnector,
|
|
341
928
|
EnvSecretsResolver,
|
|
929
|
+
InMemoryStorage,
|
|
930
|
+
aggFnSchema,
|
|
931
|
+
computeMetric,
|
|
342
932
|
computeRetention,
|
|
343
933
|
defineConfig,
|
|
344
934
|
defineConfigFields,
|
|
345
935
|
defineConnector,
|
|
346
936
|
defineDashboard,
|
|
347
937
|
defineMetric,
|
|
938
|
+
distributionWidgetSchema,
|
|
939
|
+
filterClauseSchema,
|
|
940
|
+
filterConditionSchema,
|
|
941
|
+
filterOperatorSchema,
|
|
348
942
|
getWidgetSchema,
|
|
943
|
+
groupBySchema,
|
|
349
944
|
isSecretRef,
|
|
350
945
|
resolveSecretRefs,
|
|
946
|
+
resolveWidget,
|
|
947
|
+
resolvedMetricSchema,
|
|
351
948
|
secret,
|
|
352
949
|
selectForDeletion,
|
|
950
|
+
shapeSchema,
|
|
951
|
+
statWidgetSchema,
|
|
952
|
+
statusWidgetSchema,
|
|
953
|
+
timeseriesWidgetSchema,
|
|
954
|
+
widgetSchema,
|
|
353
955
|
widgetSchemas
|
|
354
956
|
};
|
|
355
957
|
//# sourceMappingURL=index.js.map
|