@rawdash/core 0.1.0 → 0.2.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 +821 -191
- package/dist/index.js +672 -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
|
@@ -50,13 +50,66 @@ var BaseConnector = class {
|
|
|
50
50
|
credentials;
|
|
51
51
|
settings;
|
|
52
52
|
creds;
|
|
53
|
+
rawCredInput;
|
|
53
54
|
constructor(settings, creds) {
|
|
54
55
|
this.settings = settings;
|
|
56
|
+
this.rawCredInput = creds;
|
|
55
57
|
this.creds = creds ? resolveSecretRefs(
|
|
56
58
|
creds,
|
|
57
59
|
new EnvSecretsResolver()
|
|
58
60
|
) : {};
|
|
59
61
|
}
|
|
62
|
+
serializeConfig() {
|
|
63
|
+
const config = {
|
|
64
|
+
...this.settings
|
|
65
|
+
};
|
|
66
|
+
if (this.rawCredInput) {
|
|
67
|
+
for (const [key, value] of Object.entries(
|
|
68
|
+
this.rawCredInput
|
|
69
|
+
)) {
|
|
70
|
+
if (value !== void 0) {
|
|
71
|
+
config[key] = value;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return config;
|
|
76
|
+
}
|
|
77
|
+
sleep(ms, signal) {
|
|
78
|
+
if (signal?.aborted) {
|
|
79
|
+
return Promise.reject(signal.reason ?? new Error("Aborted"));
|
|
80
|
+
}
|
|
81
|
+
return new Promise((resolve, reject) => {
|
|
82
|
+
const onAbort = () => {
|
|
83
|
+
clearTimeout(timer);
|
|
84
|
+
reject(signal.reason ?? new Error("Aborted"));
|
|
85
|
+
};
|
|
86
|
+
const timer = setTimeout(() => {
|
|
87
|
+
signal?.removeEventListener("abort", onAbort);
|
|
88
|
+
resolve();
|
|
89
|
+
}, ms);
|
|
90
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
async withRetry(fn, options) {
|
|
94
|
+
const {
|
|
95
|
+
maxAttempts = 10,
|
|
96
|
+
initialDelayMs = 1e3,
|
|
97
|
+
maxDelayMs = 1e4,
|
|
98
|
+
signal
|
|
99
|
+
} = options ?? {};
|
|
100
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
101
|
+
signal?.throwIfAborted();
|
|
102
|
+
const result = await fn(signal);
|
|
103
|
+
if (result.status === "done") {
|
|
104
|
+
return result.value;
|
|
105
|
+
}
|
|
106
|
+
if (attempt < maxAttempts - 1) {
|
|
107
|
+
const delay = Math.min(initialDelayMs * 2 ** attempt, maxDelayMs);
|
|
108
|
+
await this.sleep(delay, signal);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
60
113
|
};
|
|
61
114
|
function defineConnector() {
|
|
62
115
|
return function(def) {
|
|
@@ -80,32 +133,105 @@ function defineConnector() {
|
|
|
80
133
|
|
|
81
134
|
// src/widget-schemas.ts
|
|
82
135
|
import { z } from "zod";
|
|
83
|
-
var
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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(),
|
|
180
|
+
fn: z.string(),
|
|
181
|
+
window: z.string().optional(),
|
|
182
|
+
filter: z.array(filterClauseSchema).optional(),
|
|
183
|
+
groupBy: groupBySchema.optional()
|
|
184
|
+
});
|
|
185
|
+
var titleField = z.string().meta({ label: "Title", description: "Widget title." });
|
|
186
|
+
var statWidgetSchema = z.object({
|
|
187
|
+
kind: z.literal("stat"),
|
|
188
|
+
title: titleField,
|
|
189
|
+
metric: resolvedMetricSchema.meta({
|
|
190
|
+
label: "Metric",
|
|
191
|
+
description: "Resolved metric definition."
|
|
89
192
|
}),
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
193
|
+
window: z.string().optional().meta({ label: "Window", description: "Time window, e.g. '7d'." }),
|
|
194
|
+
compare: z.enum(["none", "previous-period"]).default("none").meta({ label: "Compare", description: "Comparison mode." })
|
|
195
|
+
});
|
|
196
|
+
var statusWidgetSchema = z.object({
|
|
197
|
+
kind: z.literal("status"),
|
|
198
|
+
title: titleField,
|
|
199
|
+
source: z.string().meta({
|
|
200
|
+
label: "Source",
|
|
201
|
+
description: "Connector or data source reference."
|
|
202
|
+
})
|
|
203
|
+
});
|
|
204
|
+
var timeseriesWidgetSchema = z.object({
|
|
205
|
+
kind: z.literal("timeseries"),
|
|
206
|
+
title: titleField,
|
|
207
|
+
metric: resolvedMetricSchema.meta({
|
|
208
|
+
label: "Metric",
|
|
209
|
+
description: "Resolved metric definition."
|
|
96
210
|
}),
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
211
|
+
window: z.string().meta({ label: "Window", description: "Time window, e.g. '30d'." }),
|
|
212
|
+
granularity: z.enum(["hour", "day", "week"]).default("day").meta({ label: "Granularity", description: "Time bucket size." })
|
|
213
|
+
});
|
|
214
|
+
var distributionWidgetSchema = z.object({
|
|
215
|
+
kind: z.literal("distribution"),
|
|
216
|
+
title: titleField,
|
|
217
|
+
metric: resolvedMetricSchema.meta({
|
|
218
|
+
label: "Metric",
|
|
219
|
+
description: "Resolved metric definition."
|
|
102
220
|
}),
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
221
|
+
window: z.string().meta({ label: "Window", description: "Time window, e.g. '7d'." })
|
|
222
|
+
});
|
|
223
|
+
var widgetSchemas = {
|
|
224
|
+
stat: statWidgetSchema,
|
|
225
|
+
status: statusWidgetSchema,
|
|
226
|
+
timeseries: timeseriesWidgetSchema,
|
|
227
|
+
distribution: distributionWidgetSchema
|
|
108
228
|
};
|
|
229
|
+
var widgetSchema = z.discriminatedUnion("kind", [
|
|
230
|
+
statWidgetSchema,
|
|
231
|
+
statusWidgetSchema,
|
|
232
|
+
timeseriesWidgetSchema,
|
|
233
|
+
distributionWidgetSchema
|
|
234
|
+
]);
|
|
109
235
|
function getWidgetSchema(kind) {
|
|
110
236
|
return widgetSchemas[kind];
|
|
111
237
|
}
|
|
@@ -120,17 +246,7 @@ function defineDashboard(options) {
|
|
|
120
246
|
);
|
|
121
247
|
}
|
|
122
248
|
const schema = getWidgetSchema(widget.kind);
|
|
123
|
-
const
|
|
124
|
-
if (widget.kind !== "status") {
|
|
125
|
-
const m = widget.metric;
|
|
126
|
-
if (typeof m !== "object" || m === null) {
|
|
127
|
-
throw new Error(
|
|
128
|
-
`Widget "${key}" (kind "${widget.kind}"): metric is required`
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
parseInput.metric = "placeholder";
|
|
132
|
-
}
|
|
133
|
-
const result = schema.safeParse(parseInput);
|
|
249
|
+
const result = schema.safeParse(widget);
|
|
134
250
|
if (!result.success) {
|
|
135
251
|
throw new Error(
|
|
136
252
|
`Widget "${key}" (kind "${widget.kind}"): ${result.error.issues.map((i) => i.message).join("; ")}`
|
|
@@ -283,20 +399,543 @@ function defineConfigFields(schema) {
|
|
|
283
399
|
}
|
|
284
400
|
return schema;
|
|
285
401
|
}
|
|
402
|
+
|
|
403
|
+
// src/compute.ts
|
|
404
|
+
function matchesCondition(record, cond) {
|
|
405
|
+
const val = record[cond.field];
|
|
406
|
+
switch (cond.op) {
|
|
407
|
+
case "eq":
|
|
408
|
+
return val === cond.value;
|
|
409
|
+
case "neq":
|
|
410
|
+
return val !== cond.value;
|
|
411
|
+
case "gt":
|
|
412
|
+
if (typeof val !== "number" || typeof cond.value !== "number") {
|
|
413
|
+
return false;
|
|
414
|
+
}
|
|
415
|
+
return val > cond.value;
|
|
416
|
+
case "gte":
|
|
417
|
+
if (typeof val !== "number" || typeof cond.value !== "number") {
|
|
418
|
+
return false;
|
|
419
|
+
}
|
|
420
|
+
return val >= cond.value;
|
|
421
|
+
case "lt":
|
|
422
|
+
if (typeof val !== "number" || typeof cond.value !== "number") {
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
return val < cond.value;
|
|
426
|
+
case "lte":
|
|
427
|
+
if (typeof val !== "number" || typeof cond.value !== "number") {
|
|
428
|
+
return false;
|
|
429
|
+
}
|
|
430
|
+
return val <= cond.value;
|
|
431
|
+
case "contains":
|
|
432
|
+
return String(val).includes(String(cond.value));
|
|
433
|
+
default:
|
|
434
|
+
return false;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
function applyFilter(record, filter) {
|
|
438
|
+
if (!filter) {
|
|
439
|
+
return true;
|
|
440
|
+
}
|
|
441
|
+
for (const clause of filter) {
|
|
442
|
+
if ("or" in clause) {
|
|
443
|
+
if (!clause.or.some((cond) => matchesCondition(record, cond))) {
|
|
444
|
+
return false;
|
|
445
|
+
}
|
|
446
|
+
} else {
|
|
447
|
+
if (!matchesCondition(record, clause)) {
|
|
448
|
+
return false;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
return true;
|
|
453
|
+
}
|
|
454
|
+
var WINDOW_MS = {
|
|
455
|
+
h: 36e5,
|
|
456
|
+
d: 864e5,
|
|
457
|
+
w: 6048e5,
|
|
458
|
+
m: 2592e6
|
|
459
|
+
};
|
|
460
|
+
function parseWindowMs(window) {
|
|
461
|
+
const match = /^(\d+)(h|d|w|m)$/.exec(window);
|
|
462
|
+
if (!match) {
|
|
463
|
+
return null;
|
|
464
|
+
}
|
|
465
|
+
const unitMs = WINDOW_MS[match[2]];
|
|
466
|
+
if (unitMs === void 0) {
|
|
467
|
+
return null;
|
|
468
|
+
}
|
|
469
|
+
return parseInt(match[1]) * unitMs;
|
|
470
|
+
}
|
|
471
|
+
function truncateToGranularity(ts, granularity) {
|
|
472
|
+
const d = new Date(ts);
|
|
473
|
+
switch (granularity) {
|
|
474
|
+
case "hour":
|
|
475
|
+
d.setUTCMinutes(0, 0, 0);
|
|
476
|
+
return d.toISOString();
|
|
477
|
+
case "day":
|
|
478
|
+
d.setUTCHours(0, 0, 0, 0);
|
|
479
|
+
return d.toISOString().slice(0, 10);
|
|
480
|
+
case "week": {
|
|
481
|
+
d.setUTCDate(d.getUTCDate() - d.getUTCDay());
|
|
482
|
+
d.setUTCHours(0, 0, 0, 0);
|
|
483
|
+
return d.toISOString().slice(0, 10);
|
|
484
|
+
}
|
|
485
|
+
case "month":
|
|
486
|
+
d.setUTCDate(1);
|
|
487
|
+
d.setUTCHours(0, 0, 0, 0);
|
|
488
|
+
return d.toISOString().slice(0, 7);
|
|
489
|
+
default:
|
|
490
|
+
return d.toISOString().slice(0, 10);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
function computeAgg(records, field, fn) {
|
|
494
|
+
if (fn === "count") {
|
|
495
|
+
return records.length;
|
|
496
|
+
}
|
|
497
|
+
if (fn === "latest") {
|
|
498
|
+
return records.at(-1)?.[field] ?? null;
|
|
499
|
+
}
|
|
500
|
+
if (fn === "first") {
|
|
501
|
+
return records[0]?.[field] ?? null;
|
|
502
|
+
}
|
|
503
|
+
const values = records.map((r) => r[field]).filter((v) => v !== void 0 && v !== null);
|
|
504
|
+
const nonNumeric = values.find((v) => typeof v !== "number");
|
|
505
|
+
if (nonNumeric !== void 0) {
|
|
506
|
+
throw new Error(
|
|
507
|
+
`computeAgg: fn "${fn}" requires numeric values for field "${field}", got ${typeof nonNumeric} (${String(nonNumeric)})`
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
const numbers = values;
|
|
511
|
+
if (fn === "sum") {
|
|
512
|
+
return numbers.reduce((a, b) => a + b, 0);
|
|
513
|
+
}
|
|
514
|
+
if (fn === "avg") {
|
|
515
|
+
return numbers.length > 0 ? numbers.reduce((a, b) => a + b, 0) / numbers.length : null;
|
|
516
|
+
}
|
|
517
|
+
if (fn === "min") {
|
|
518
|
+
return numbers.length > 0 ? numbers.reduce((a, b) => a < b ? a : b) : null;
|
|
519
|
+
}
|
|
520
|
+
if (fn === "max") {
|
|
521
|
+
return numbers.length > 0 ? numbers.reduce((a, b) => a > b ? a : b) : null;
|
|
522
|
+
}
|
|
523
|
+
return null;
|
|
524
|
+
}
|
|
525
|
+
function sortByTs(records, tsField) {
|
|
526
|
+
return [...records].sort((a, b) => {
|
|
527
|
+
return a[tsField] - b[tsField];
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
function computeGroupBy(records, metric, tsField) {
|
|
531
|
+
const { field, granularity } = metric.groupBy;
|
|
532
|
+
const groups = /* @__PURE__ */ new Map();
|
|
533
|
+
for (const record of records) {
|
|
534
|
+
const ts = record[field];
|
|
535
|
+
if (ts === void 0 || typeof ts !== "number") {
|
|
536
|
+
continue;
|
|
537
|
+
}
|
|
538
|
+
const key = truncateToGranularity(ts, granularity);
|
|
539
|
+
if (!groups.has(key)) {
|
|
540
|
+
groups.set(key, []);
|
|
541
|
+
}
|
|
542
|
+
groups.get(key).push(record);
|
|
543
|
+
}
|
|
544
|
+
return [...groups.entries()].map(([key, groupRecords]) => ({
|
|
545
|
+
date: key,
|
|
546
|
+
value: computeAgg(
|
|
547
|
+
sortByTs(groupRecords, tsField),
|
|
548
|
+
metric.field,
|
|
549
|
+
metric.fn
|
|
550
|
+
)
|
|
551
|
+
})).sort((a, b) => a.date < b.date ? -1 : 1);
|
|
552
|
+
}
|
|
553
|
+
function getTimestampField(shape) {
|
|
554
|
+
switch (shape) {
|
|
555
|
+
case "event":
|
|
556
|
+
return "start_ts";
|
|
557
|
+
case "metric":
|
|
558
|
+
case "distribution":
|
|
559
|
+
return "ts";
|
|
560
|
+
case "entity":
|
|
561
|
+
case "edge":
|
|
562
|
+
return "updated_at";
|
|
563
|
+
default:
|
|
564
|
+
return "start_ts";
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
async function computeMetric(storage, metric) {
|
|
568
|
+
const tsField = getTimestampField(metric.shape);
|
|
569
|
+
const windowMs = metric.window ? parseWindowMs(metric.window) : null;
|
|
570
|
+
const windowStart = windowMs !== null ? Date.now() - windowMs : void 0;
|
|
571
|
+
let records;
|
|
572
|
+
switch (metric.shape) {
|
|
573
|
+
case "event": {
|
|
574
|
+
const events = await storage.queryEvents({
|
|
575
|
+
name: metric.name,
|
|
576
|
+
start: windowStart
|
|
577
|
+
});
|
|
578
|
+
records = events.map((e) => ({
|
|
579
|
+
...e.attributes,
|
|
580
|
+
name: e.name,
|
|
581
|
+
start_ts: e.start_ts,
|
|
582
|
+
end_ts: e.end_ts
|
|
583
|
+
}));
|
|
584
|
+
break;
|
|
585
|
+
}
|
|
586
|
+
case "entity": {
|
|
587
|
+
const type = metric.entityType ?? metric.name ?? "";
|
|
588
|
+
const entities = await storage.queryEntities({ type });
|
|
589
|
+
records = entities.map((e) => ({
|
|
590
|
+
...e.attributes,
|
|
591
|
+
type: e.type,
|
|
592
|
+
id: e.id,
|
|
593
|
+
updated_at: e.updated_at
|
|
594
|
+
}));
|
|
595
|
+
if (windowStart !== void 0) {
|
|
596
|
+
records = records.filter((r) => r[tsField] >= windowStart);
|
|
597
|
+
}
|
|
598
|
+
break;
|
|
599
|
+
}
|
|
600
|
+
case "metric": {
|
|
601
|
+
const metrics = await storage.queryMetrics({
|
|
602
|
+
name: metric.name,
|
|
603
|
+
start: windowStart
|
|
604
|
+
});
|
|
605
|
+
records = metrics.map((m) => ({
|
|
606
|
+
...m.attributes,
|
|
607
|
+
name: m.name,
|
|
608
|
+
ts: m.ts,
|
|
609
|
+
value: m.value
|
|
610
|
+
}));
|
|
611
|
+
break;
|
|
612
|
+
}
|
|
613
|
+
case "edge": {
|
|
614
|
+
const edges = await storage.traverse({ kind: metric.name });
|
|
615
|
+
records = edges.map((e) => ({
|
|
616
|
+
...e.attributes,
|
|
617
|
+
from_type: e.from_type,
|
|
618
|
+
from_id: e.from_id,
|
|
619
|
+
kind: e.kind,
|
|
620
|
+
to_type: e.to_type,
|
|
621
|
+
to_id: e.to_id,
|
|
622
|
+
updated_at: e.updated_at
|
|
623
|
+
}));
|
|
624
|
+
if (windowStart !== void 0) {
|
|
625
|
+
records = records.filter((r) => r[tsField] >= windowStart);
|
|
626
|
+
}
|
|
627
|
+
break;
|
|
628
|
+
}
|
|
629
|
+
case "distribution": {
|
|
630
|
+
const distributions = await storage.queryDistributions({
|
|
631
|
+
name: metric.name,
|
|
632
|
+
start: windowStart
|
|
633
|
+
});
|
|
634
|
+
records = distributions.map((d) => ({
|
|
635
|
+
...d.attributes,
|
|
636
|
+
name: d.name,
|
|
637
|
+
ts: d.ts,
|
|
638
|
+
kind: d.kind,
|
|
639
|
+
data: d.data
|
|
640
|
+
}));
|
|
641
|
+
break;
|
|
642
|
+
}
|
|
643
|
+
default:
|
|
644
|
+
return null;
|
|
645
|
+
}
|
|
646
|
+
const filtered = records.filter((r) => applyFilter(r, metric.filter));
|
|
647
|
+
const sorted = sortByTs(filtered, tsField);
|
|
648
|
+
if (metric.groupBy) {
|
|
649
|
+
return computeGroupBy(sorted, metric, tsField);
|
|
650
|
+
}
|
|
651
|
+
return computeAgg(sorted, metric.field, metric.fn);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// src/resolve-widget.ts
|
|
655
|
+
async function resolveWidget(id, widget, connectors, storage) {
|
|
656
|
+
if (widget.kind === "status") {
|
|
657
|
+
return {
|
|
658
|
+
id,
|
|
659
|
+
widgetId: id,
|
|
660
|
+
connectorId: widget.source,
|
|
661
|
+
data: null,
|
|
662
|
+
cachedAt: null
|
|
663
|
+
};
|
|
664
|
+
}
|
|
665
|
+
const { connectorId } = widget.metric;
|
|
666
|
+
const connectorEntry = connectors.find((e) => e.connector.id === connectorId);
|
|
667
|
+
if (!connectorEntry) {
|
|
668
|
+
return void 0;
|
|
669
|
+
}
|
|
670
|
+
const handle = storage.getStorageHandle(connectorId);
|
|
671
|
+
const data = await computeMetric(handle, widget.metric);
|
|
672
|
+
return {
|
|
673
|
+
id,
|
|
674
|
+
widgetId: id,
|
|
675
|
+
connectorId,
|
|
676
|
+
data,
|
|
677
|
+
cachedAt: (await storage.getSyncState()).lastSyncAt
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
// src/in-memory-storage.ts
|
|
682
|
+
var InMemoryStorage = class {
|
|
683
|
+
eventStore = /* @__PURE__ */ new Map();
|
|
684
|
+
entityStore = /* @__PURE__ */ new Map();
|
|
685
|
+
metricStore = /* @__PURE__ */ new Map();
|
|
686
|
+
edgeStore = /* @__PURE__ */ new Map();
|
|
687
|
+
distributionStore = /* @__PURE__ */ new Map();
|
|
688
|
+
syncState = {
|
|
689
|
+
status: "idle",
|
|
690
|
+
lastSyncAt: null,
|
|
691
|
+
lastError: null
|
|
692
|
+
};
|
|
693
|
+
getStorageHandle(connectorId) {
|
|
694
|
+
const getEntityMap = () => {
|
|
695
|
+
if (!this.entityStore.has(connectorId)) {
|
|
696
|
+
this.entityStore.set(connectorId, /* @__PURE__ */ new Map());
|
|
697
|
+
}
|
|
698
|
+
return this.entityStore.get(connectorId);
|
|
699
|
+
};
|
|
700
|
+
const upsertEntities = (es) => {
|
|
701
|
+
const byType = getEntityMap();
|
|
702
|
+
for (const e of es) {
|
|
703
|
+
if (!byType.has(e.type)) {
|
|
704
|
+
byType.set(e.type, /* @__PURE__ */ new Map());
|
|
705
|
+
}
|
|
706
|
+
byType.get(e.type).set(e.id, e);
|
|
707
|
+
}
|
|
708
|
+
};
|
|
709
|
+
const upsertEdges = (es) => {
|
|
710
|
+
const existing = this.edgeStore.get(connectorId) ?? [];
|
|
711
|
+
const index = /* @__PURE__ */ new Map();
|
|
712
|
+
for (let i = 0; i < existing.length; i++) {
|
|
713
|
+
const e = existing[i];
|
|
714
|
+
index.set(
|
|
715
|
+
`${e.from_type}:${e.from_id}:${e.kind}:${e.to_type}:${e.to_id}`,
|
|
716
|
+
i
|
|
717
|
+
);
|
|
718
|
+
}
|
|
719
|
+
for (const e of es) {
|
|
720
|
+
const key = `${e.from_type}:${e.from_id}:${e.kind}:${e.to_type}:${e.to_id}`;
|
|
721
|
+
const idx = index.get(key);
|
|
722
|
+
if (idx !== void 0) {
|
|
723
|
+
existing[idx] = e;
|
|
724
|
+
} else {
|
|
725
|
+
index.set(key, existing.length);
|
|
726
|
+
existing.push(e);
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
this.edgeStore.set(connectorId, existing);
|
|
730
|
+
};
|
|
731
|
+
return {
|
|
732
|
+
event: async (e) => {
|
|
733
|
+
if (!this.eventStore.has(connectorId)) {
|
|
734
|
+
this.eventStore.set(connectorId, []);
|
|
735
|
+
}
|
|
736
|
+
this.eventStore.get(connectorId).push(e);
|
|
737
|
+
},
|
|
738
|
+
entity: async (e) => {
|
|
739
|
+
upsertEntities([e]);
|
|
740
|
+
},
|
|
741
|
+
metric: async (m) => {
|
|
742
|
+
if (!this.metricStore.has(connectorId)) {
|
|
743
|
+
this.metricStore.set(connectorId, []);
|
|
744
|
+
}
|
|
745
|
+
this.metricStore.get(connectorId).push(m);
|
|
746
|
+
},
|
|
747
|
+
edge: async (e) => {
|
|
748
|
+
upsertEdges([e]);
|
|
749
|
+
},
|
|
750
|
+
distribution: async (d) => {
|
|
751
|
+
if (!this.distributionStore.has(connectorId)) {
|
|
752
|
+
this.distributionStore.set(connectorId, []);
|
|
753
|
+
}
|
|
754
|
+
this.distributionStore.get(connectorId).push(d);
|
|
755
|
+
},
|
|
756
|
+
events: async (es, scope) => {
|
|
757
|
+
const names = new Set(scope?.names ?? es.map((e) => e.name));
|
|
758
|
+
const kept = (this.eventStore.get(connectorId) ?? []).filter(
|
|
759
|
+
(e) => !names.has(e.name)
|
|
760
|
+
);
|
|
761
|
+
this.eventStore.set(connectorId, [...kept, ...es]);
|
|
762
|
+
},
|
|
763
|
+
entities: async (es, scope) => {
|
|
764
|
+
const byType = getEntityMap();
|
|
765
|
+
const types = new Set(scope?.types ?? es.map((e) => e.type));
|
|
766
|
+
for (const type of types) {
|
|
767
|
+
byType.set(type, /* @__PURE__ */ new Map());
|
|
768
|
+
}
|
|
769
|
+
upsertEntities(es);
|
|
770
|
+
},
|
|
771
|
+
metrics: async (ms, scope) => {
|
|
772
|
+
const names = new Set(scope?.names ?? ms.map((m) => m.name));
|
|
773
|
+
const kept = (this.metricStore.get(connectorId) ?? []).filter(
|
|
774
|
+
(m) => !names.has(m.name)
|
|
775
|
+
);
|
|
776
|
+
this.metricStore.set(connectorId, [...kept, ...ms]);
|
|
777
|
+
},
|
|
778
|
+
edges: async (es, scope) => {
|
|
779
|
+
const kinds = new Set(scope?.kinds ?? es.map((e) => e.kind));
|
|
780
|
+
const kept = (this.edgeStore.get(connectorId) ?? []).filter(
|
|
781
|
+
(e) => !kinds.has(e.kind)
|
|
782
|
+
);
|
|
783
|
+
this.edgeStore.set(connectorId, kept);
|
|
784
|
+
upsertEdges(es);
|
|
785
|
+
},
|
|
786
|
+
distributions: async (ds, scope) => {
|
|
787
|
+
const names = new Set(scope?.names ?? ds.map((d) => d.name));
|
|
788
|
+
const kept = (this.distributionStore.get(connectorId) ?? []).filter(
|
|
789
|
+
(d) => !names.has(d.name)
|
|
790
|
+
);
|
|
791
|
+
this.distributionStore.set(connectorId, [...kept, ...ds]);
|
|
792
|
+
},
|
|
793
|
+
queryEvents: async (q) => {
|
|
794
|
+
let results = this.eventStore.get(connectorId) ?? [];
|
|
795
|
+
if (q.name !== void 0) {
|
|
796
|
+
results = results.filter((e) => e.name === q.name);
|
|
797
|
+
}
|
|
798
|
+
if (q.start !== void 0) {
|
|
799
|
+
results = results.filter((e) => e.start_ts >= q.start);
|
|
800
|
+
}
|
|
801
|
+
if (q.end !== void 0) {
|
|
802
|
+
results = results.filter((e) => e.start_ts <= q.end);
|
|
803
|
+
}
|
|
804
|
+
return results;
|
|
805
|
+
},
|
|
806
|
+
getEntity: async (type, id) => {
|
|
807
|
+
return getEntityMap().get(type)?.get(id) ?? null;
|
|
808
|
+
},
|
|
809
|
+
queryEntities: async (q) => {
|
|
810
|
+
const byType = getEntityMap().get(q.type);
|
|
811
|
+
if (!byType) {
|
|
812
|
+
return [];
|
|
813
|
+
}
|
|
814
|
+
return Array.from(byType.values());
|
|
815
|
+
},
|
|
816
|
+
queryMetrics: async (q) => {
|
|
817
|
+
let results = this.metricStore.get(connectorId) ?? [];
|
|
818
|
+
if (q.name !== void 0) {
|
|
819
|
+
results = results.filter((m) => m.name === q.name);
|
|
820
|
+
}
|
|
821
|
+
if (q.start !== void 0) {
|
|
822
|
+
results = results.filter((m) => m.ts >= q.start);
|
|
823
|
+
}
|
|
824
|
+
if (q.end !== void 0) {
|
|
825
|
+
results = results.filter((m) => m.ts <= q.end);
|
|
826
|
+
}
|
|
827
|
+
return results;
|
|
828
|
+
},
|
|
829
|
+
traverse: async (q) => {
|
|
830
|
+
let results = this.edgeStore.get(connectorId) ?? [];
|
|
831
|
+
if (q.fromType !== void 0) {
|
|
832
|
+
results = results.filter((e) => e.from_type === q.fromType);
|
|
833
|
+
}
|
|
834
|
+
if (q.fromId !== void 0) {
|
|
835
|
+
results = results.filter((e) => e.from_id === q.fromId);
|
|
836
|
+
}
|
|
837
|
+
if (q.kind !== void 0) {
|
|
838
|
+
results = results.filter((e) => e.kind === q.kind);
|
|
839
|
+
}
|
|
840
|
+
if (q.toType !== void 0) {
|
|
841
|
+
results = results.filter((e) => e.to_type === q.toType);
|
|
842
|
+
}
|
|
843
|
+
if (q.toId !== void 0) {
|
|
844
|
+
results = results.filter((e) => e.to_id === q.toId);
|
|
845
|
+
}
|
|
846
|
+
return results;
|
|
847
|
+
},
|
|
848
|
+
queryDistributions: async (q) => {
|
|
849
|
+
let results = this.distributionStore.get(connectorId) ?? [];
|
|
850
|
+
if (q.name !== void 0) {
|
|
851
|
+
results = results.filter((d) => d.name === q.name);
|
|
852
|
+
}
|
|
853
|
+
if (q.start !== void 0) {
|
|
854
|
+
results = results.filter((d) => d.ts >= q.start);
|
|
855
|
+
}
|
|
856
|
+
if (q.end !== void 0) {
|
|
857
|
+
results = results.filter((d) => d.ts <= q.end);
|
|
858
|
+
}
|
|
859
|
+
return results;
|
|
860
|
+
},
|
|
861
|
+
deleteOlderThan: async (shape, tsUnixMs) => {
|
|
862
|
+
if (shape === "events") {
|
|
863
|
+
const before = this.eventStore.get(connectorId) ?? [];
|
|
864
|
+
const after = before.filter((e) => e.start_ts >= tsUnixMs);
|
|
865
|
+
this.eventStore.set(connectorId, after);
|
|
866
|
+
return { rowsDeleted: before.length - after.length };
|
|
867
|
+
} else if (shape === "metrics") {
|
|
868
|
+
const before = this.metricStore.get(connectorId) ?? [];
|
|
869
|
+
const after = before.filter((m) => m.ts >= tsUnixMs);
|
|
870
|
+
this.metricStore.set(connectorId, after);
|
|
871
|
+
return { rowsDeleted: before.length - after.length };
|
|
872
|
+
} else if (shape === "distributions") {
|
|
873
|
+
const before = this.distributionStore.get(connectorId) ?? [];
|
|
874
|
+
const after = before.filter((d) => d.ts >= tsUnixMs);
|
|
875
|
+
this.distributionStore.set(connectorId, after);
|
|
876
|
+
return { rowsDeleted: before.length - after.length };
|
|
877
|
+
} else {
|
|
878
|
+
throw new Error(
|
|
879
|
+
`Unsupported shape for deleteOlderThan: ${String(shape)}`
|
|
880
|
+
);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
};
|
|
884
|
+
}
|
|
885
|
+
async getSyncState() {
|
|
886
|
+
return { ...this.syncState };
|
|
887
|
+
}
|
|
888
|
+
async setSyncing() {
|
|
889
|
+
if (this.syncState.status === "syncing") {
|
|
890
|
+
return false;
|
|
891
|
+
}
|
|
892
|
+
this.syncState = { ...this.syncState, status: "syncing" };
|
|
893
|
+
return true;
|
|
894
|
+
}
|
|
895
|
+
async setSyncSuccess() {
|
|
896
|
+
this.syncState = {
|
|
897
|
+
status: "idle",
|
|
898
|
+
lastSyncAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
899
|
+
lastError: null
|
|
900
|
+
};
|
|
901
|
+
}
|
|
902
|
+
async setSyncError(error) {
|
|
903
|
+
this.syncState = {
|
|
904
|
+
status: "error",
|
|
905
|
+
lastSyncAt: this.syncState.lastSyncAt,
|
|
906
|
+
lastError: error
|
|
907
|
+
};
|
|
908
|
+
}
|
|
909
|
+
};
|
|
286
910
|
export {
|
|
287
911
|
BaseConnector,
|
|
288
912
|
EnvSecretsResolver,
|
|
913
|
+
InMemoryStorage,
|
|
914
|
+
aggFnSchema,
|
|
915
|
+
computeMetric,
|
|
289
916
|
computeRetention,
|
|
290
917
|
defineConfig,
|
|
291
918
|
defineConfigFields,
|
|
292
919
|
defineConnector,
|
|
293
920
|
defineDashboard,
|
|
294
921
|
defineMetric,
|
|
922
|
+
distributionWidgetSchema,
|
|
923
|
+
filterClauseSchema,
|
|
924
|
+
filterConditionSchema,
|
|
925
|
+
filterOperatorSchema,
|
|
295
926
|
getWidgetSchema,
|
|
927
|
+
groupBySchema,
|
|
296
928
|
isSecretRef,
|
|
297
929
|
resolveSecretRefs,
|
|
930
|
+
resolveWidget,
|
|
931
|
+
resolvedMetricSchema,
|
|
298
932
|
secret,
|
|
299
933
|
selectForDeletion,
|
|
934
|
+
shapeSchema,
|
|
935
|
+
statWidgetSchema,
|
|
936
|
+
statusWidgetSchema,
|
|
937
|
+
timeseriesWidgetSchema,
|
|
938
|
+
widgetSchema,
|
|
300
939
|
widgetSchemas
|
|
301
940
|
};
|
|
302
941
|
//# sourceMappingURL=index.js.map
|