@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.js CHANGED
@@ -133,32 +133,108 @@ function defineConnector() {
133
133
 
134
134
  // src/widget-schemas.ts
135
135
  import { z } from "zod";
136
- var widgetSchemas = {
137
- stat: z.object({
138
- title: z.string().meta({ label: "Title", description: "Widget title." }),
139
- metric: z.string().meta({ label: "Metric", description: "Metric reference." }),
140
- window: z.string().optional().meta({ label: "Window", description: "Time window, e.g. '7d'." }),
141
- compare: z.enum(["none", "previous-period"]).default("none").meta({ label: "Compare", description: "Comparison mode." })
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
- status: z.object({
144
- title: z.string().meta({ label: "Title", description: "Widget title." }),
145
- source: z.string().meta({
146
- label: "Source",
147
- description: "Connector or data source reference."
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
- timeseries: z.object({
151
- title: z.string().meta({ label: "Title", description: "Widget title." }),
152
- metric: z.string().meta({ label: "Metric", description: "Metric reference." }),
153
- window: z.string().meta({ label: "Window", description: "Time window, e.g. '30d'." }),
154
- granularity: z.enum(["hour", "day", "week"]).default("day").meta({ label: "Granularity", description: "Time bucket size." })
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
- distribution: z.object({
157
- title: z.string().meta({ label: "Title", description: "Widget title." }),
158
- metric: z.string().meta({ label: "Metric", description: "Metric reference." }),
159
- window: z.string().meta({ label: "Window", description: "Time window, e.g. '7d'." })
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 parseInput = { ...widget };
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