@rawdash/core 0.14.0 → 0.15.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/README.md CHANGED
@@ -20,7 +20,6 @@ npm install @rawdash/core @rawdash/connector-github
20
20
  ## Quick example
21
21
 
22
22
  ```ts
23
- import { GitHubConnector } from '@rawdash/connector-github';
24
23
  import {
25
24
  defineConfig,
26
25
  defineDashboard,
@@ -28,18 +27,18 @@ import {
28
27
  secret,
29
28
  } from '@rawdash/core';
30
29
 
31
- const github = new GitHubConnector(
32
- {
30
+ const github = {
31
+ name: 'github',
32
+ connectorId: 'github-actions',
33
+ config: {
33
34
  owner: 'my-org',
34
35
  repo: 'my-repo',
35
- },
36
- {
37
36
  token: secret('GITHUB_TOKEN'),
38
37
  },
39
- );
38
+ };
40
39
 
41
40
  export default defineConfig({
42
- connectors: [{ connector: github }],
41
+ connectors: [github],
43
42
  dashboards: {
44
43
  engineering: defineDashboard({
45
44
  widgets: {
@@ -58,6 +57,10 @@ export default defineConfig({
58
57
  }),
59
58
  },
60
59
  });
60
+
61
+ // When mounting the engine, register the connector class:
62
+ // import { GitHubConnector } from '@rawdash/connector-github';
63
+ // mountEngine(config, { connectorRegistry: { 'github-actions': GitHubConnector } });
61
64
  ```
62
65
 
63
66
  ## API
package/dist/index.d.ts CHANGED
@@ -127,6 +127,13 @@ interface StorageHandle {
127
127
  deleteOlderThan(shape: 'events' | 'metrics' | 'distributions', tsUnixMs: number): Promise<{
128
128
  rowsDeleted: number;
129
129
  }>;
130
+ getHealth?(): Promise<ConnectorHealth | null>;
131
+ }
132
+ interface ConnectorHealth {
133
+ status: 'idle' | 'syncing' | 'error' | 'auth_failed' | 'paused';
134
+ lastSyncAt: string | null;
135
+ lastError: string | null;
136
+ syncIntervalSeconds: number;
130
137
  }
131
138
  interface CredentialField {
132
139
  description: string;
@@ -1219,7 +1226,7 @@ interface GroupBy {
1219
1226
  }
1220
1227
  interface Metric {
1221
1228
  connector: {
1222
- id: string;
1229
+ name: string;
1223
1230
  };
1224
1231
  shape: Shape;
1225
1232
  name?: string;
@@ -1269,7 +1276,12 @@ interface DistributionWidget {
1269
1276
  type Widget = StatWidget | StatusWidget | TimeseriesWidget | DistributionWidget;
1270
1277
 
1271
1278
  interface ConfiguredConnector {
1272
- connector: Connector;
1279
+ name: string;
1280
+ connectorId: string;
1281
+ config: Record<string, unknown>;
1282
+ syncIntervalSeconds?: number;
1283
+ enabled?: boolean;
1284
+ displayName?: string;
1273
1285
  }
1274
1286
  interface Dashboard {
1275
1287
  widgets: Record<string, Widget>;
@@ -1296,7 +1308,7 @@ interface SyncState {
1296
1308
  declare const ACTIVE_SYNC_STATUSES: ReadonlySet<SyncStatus>;
1297
1309
  declare function isSyncActive(status: SyncStatus): boolean;
1298
1310
 
1299
- type WidgetSyncState = 'synced' | 'unsynced' | 'syncing' | 'stale' | 'error';
1311
+ type WidgetSyncState = 'fresh' | 'stale' | 'unsynced' | 'syncing' | 'failing';
1300
1312
  interface CachedWidget<TData = unknown> {
1301
1313
  widgetId: string;
1302
1314
  connectorId: string;
@@ -1347,7 +1359,35 @@ interface ServerStorage {
1347
1359
  markSyncFailed(error: string): Promise<void>;
1348
1360
  }
1349
1361
 
1350
- declare function resolveWidget(widgetId: string, widget: Widget, connectors: ConfiguredConnector[] | readonly string[] | undefined, storage: ServerStorage): Promise<CachedWidget | undefined>;
1362
+ declare function resolveWidget(widgetId: string, widget: Widget, connectors: readonly string[] | undefined, storage: ServerStorage): Promise<CachedWidget | undefined>;
1363
+
1364
+ /**
1365
+ * Map of resource name → Zod schema describing the raw API response shape
1366
+ * for that resource. Resource names must match the `resource` tag passed to
1367
+ * `request()` (see {@link BaseConnector.request}) so the shape-drift pipeline
1368
+ * can correlate observations with their declared shape.
1369
+ *
1370
+ * Consumed by:
1371
+ * - the cloud baseline generator, which walks this map at deploy time to
1372
+ * populate `connector_baselines`
1373
+ * - property tests in `@rawdash/connector-test-utils`, which fuzz against
1374
+ * each schema
1375
+ *
1376
+ * See `docs/authoring-a-connector.md` for the authoring guide.
1377
+ */
1378
+ type ConnectorSchemas = Readonly<Record<string, z.ZodType>>;
1379
+ /**
1380
+ * Compile-time contract every connector class must satisfy. Declaring
1381
+ * `static schemas` is mandatory — without it, the connector cannot be added
1382
+ * to a {@link ConnectorRegistry} and TypeScript will fail the build.
1383
+ */
1384
+ type ConnectorClass = {
1385
+ new (settings: never, creds?: never, ctx?: ConnectorContext): Connector;
1386
+ readonly credentials?: CredentialsSchema;
1387
+ readonly schemas: ConnectorSchemas;
1388
+ };
1389
+ type ConnectorRegistry = Record<string, ConnectorClass>;
1390
+ declare function instantiateConnector(entry: ConfiguredConnector, registry: ConnectorRegistry, secretsResolver?: SecretsResolver): Connector;
1351
1391
 
1352
1392
  declare function withAbortSignal(handle: StorageHandle, signal: AbortSignal): StorageHandle;
1353
1393
 
@@ -1357,6 +1397,7 @@ declare class InMemoryStorage implements ServerStorage {
1357
1397
  private metricStore;
1358
1398
  private edgeStore;
1359
1399
  private distributionStore;
1400
+ private lastWriteAt;
1360
1401
  private syncState;
1361
1402
  getStorageHandle(connectorId: string, options?: GetStorageHandleOptions): StorageHandle;
1362
1403
  private buildHandle;
@@ -1402,4 +1443,4 @@ type WireDashboard = z.infer<typeof wireDashboardSchema>;
1402
1443
  type WireConfig = z.infer<typeof wireConfigSchema>;
1403
1444
  declare function toWireConfig(config: DashboardConfig): WireConfig;
1404
1445
 
1405
- export { ACTIVE_SYNC_STATUSES, type AggFn, BaseConnector, type CachedWidget, type ChunkedSyncCursor, type ChunkedSyncOptions, type ComputedMetric, type ConfigFieldsSchema, type ConfiguredConnector, type Connector, type ConnectorContext, type ConnectorRequestOptions, type CredentialField, type CredentialsSchema, type Dashboard, type DashboardConfig, type DataSource, type Distribution, type DistributionQuery, type DistributionWidget, type Edge, type EdgeQuery, type Entity, type EntityQuery, EnvSecretsResolver, type Event, type EventQuery, type FetchPageResult, type FilterClause, type FilterCondition, type FilterOperator, type GetStorageHandleOptions, type GroupBy, type HealthResponse, InMemoryStorage, type InferCredentialInput, type InferCredentials, type JSONValue, type Metric, type MetricQuery, type MetricSample, type RetentionConfig, type RetentionDeletionPlan, type Secret, type SecretsResolver, type ServerDataSource, type ServerStorage, type Shape, type StatWidget, type StatusWidget, type StorageHandle, type SyncOptions, type SyncResult, type SyncState, type SyncStatus, type TimeseriesWidget, type TriggerSyncResponse, type Widget, type WidgetKind, type WidgetSyncState, type WidgetsListResponse, type WireConfig, type WireConnector, type WireDashboard, aggFnSchema, computeMetric, computeRetention, computedMetricSchema, defineConfig, defineConfigFields, defineConnector, defineDashboard, defineMetric, distributionWidgetSchema, extractSecretNames, filterClauseSchema, filterConditionSchema, filterOperatorSchema, getWidgetSchema, groupBySchema, isSecret, isSyncActive, paginateChunked, resolveSecrets, resolveWidget, secret, selectForDeletion, shapeSchema, statWidgetSchema, statusWidgetSchema, timeseriesWidgetSchema, toWireConfig, widgetSchema, widgetSchemas, wireConfigSchema, wireConnectorSchema, wireDashboardSchema, withAbortSignal };
1446
+ export { ACTIVE_SYNC_STATUSES, type AggFn, BaseConnector, type CachedWidget, type ChunkedSyncCursor, type ChunkedSyncOptions, type ComputedMetric, type ConfigFieldsSchema, type ConfiguredConnector, type Connector, type ConnectorClass, type ConnectorContext, type ConnectorHealth, type ConnectorRegistry, type ConnectorRequestOptions, type ConnectorSchemas, type CredentialField, type CredentialsSchema, type Dashboard, type DashboardConfig, type DataSource, type Distribution, type DistributionQuery, type DistributionWidget, type Edge, type EdgeQuery, type Entity, type EntityQuery, EnvSecretsResolver, type Event, type EventQuery, type FetchPageResult, type FilterClause, type FilterCondition, type FilterOperator, type GetStorageHandleOptions, type GroupBy, type HealthResponse, InMemoryStorage, type InferCredentialInput, type InferCredentials, type JSONValue, type Metric, type MetricQuery, type MetricSample, type RetentionConfig, type RetentionDeletionPlan, type Secret, type SecretsResolver, type ServerDataSource, type ServerStorage, type Shape, type StatWidget, type StatusWidget, type StorageHandle, type SyncOptions, type SyncResult, type SyncState, type SyncStatus, type TimeseriesWidget, type TriggerSyncResponse, type Widget, type WidgetKind, type WidgetSyncState, type WidgetsListResponse, type WireConfig, type WireConnector, type WireDashboard, aggFnSchema, computeMetric, computeRetention, computedMetricSchema, defineConfig, defineConfigFields, defineConnector, defineDashboard, defineMetric, distributionWidgetSchema, extractSecretNames, filterClauseSchema, filterConditionSchema, filterOperatorSchema, getWidgetSchema, groupBySchema, instantiateConnector, isSecret, isSyncActive, paginateChunked, resolveSecrets, resolveWidget, secret, selectForDeletion, shapeSchema, statWidgetSchema, statusWidgetSchema, timeseriesWidgetSchema, toWireConfig, widgetSchema, widgetSchemas, wireConfigSchema, wireConnectorSchema, wireDashboardSchema, withAbortSignal };
package/dist/index.js CHANGED
@@ -666,7 +666,7 @@ function defineDashboard(options) {
666
666
  }
667
667
  function defineMetric(options) {
668
668
  return {
669
- connectorId: options.connector.id,
669
+ connectorId: options.connector.name,
670
670
  shape: options.shape,
671
671
  name: options.name,
672
672
  entityType: options.entityType,
@@ -715,7 +715,36 @@ function validateConfig(config) {
715
715
  'defineConfig: config must include a "dashboards" record \u2014 did you mean to migrate from the old flat "widgets" shape?'
716
716
  );
717
717
  }
718
- const connectorIds = new Set(config.connectors.map((e) => e.connector.id));
718
+ if (!Array.isArray(config.connectors)) {
719
+ throw new Error('defineConfig: "connectors" must be an array');
720
+ }
721
+ const connectorNames = /* @__PURE__ */ new Set();
722
+ for (const entry of config.connectors) {
723
+ if (!entry || typeof entry !== "object") {
724
+ throw new Error(
725
+ 'defineConfig: every connector entry must be an object with "name", "connectorId", and "config"'
726
+ );
727
+ }
728
+ if (!entry.name) {
729
+ throw new Error('defineConfig: every connector entry must have a "name"');
730
+ }
731
+ if (!entry.connectorId) {
732
+ throw new Error(
733
+ `defineConfig: connector "${entry.name}" must have a "connectorId" (the connector type id)`
734
+ );
735
+ }
736
+ if (entry.config === null || typeof entry.config !== "object" || Array.isArray(entry.config)) {
737
+ throw new Error(
738
+ `defineConfig: connector "${entry.name}" must have a "config" object`
739
+ );
740
+ }
741
+ if (connectorNames.has(entry.name)) {
742
+ throw new Error(
743
+ `defineConfig: duplicate connector name "${entry.name}". Each instance must have a unique name.`
744
+ );
745
+ }
746
+ connectorNames.add(entry.name);
747
+ }
719
748
  for (const [dashboardKey, dashboard] of Object.entries(config.dashboards)) {
720
749
  if (!dashboard.widgets || typeof dashboard.widgets !== "object" || Array.isArray(dashboard.widgets)) {
721
750
  throw new Error(
@@ -738,7 +767,7 @@ function validateConfig(config) {
738
767
  continue;
739
768
  }
740
769
  const { connectorId, shape, fn } = widget.metric;
741
- if (!connectorIds.has(connectorId)) {
770
+ if (!connectorNames.has(connectorId)) {
742
771
  throw new Error(
743
772
  `${ref}: connector "${connectorId}" is not listed in connectors`
744
773
  );
@@ -1073,38 +1102,77 @@ async function computeMetric(storage, metric) {
1073
1102
  }
1074
1103
 
1075
1104
  // src/resolve-widget.ts
1076
- async function resolveWidget(widgetId, widget, connectors, storage) {
1077
- if (widget.kind === "status") {
1078
- return {
1079
- widgetId,
1080
- connectorId: widget.source,
1081
- data: null,
1082
- cachedAt: null
1083
- };
1105
+ var FAILING_CONNECTOR_STATUSES = /* @__PURE__ */ new Set(["error", "auth_failed", "paused"]);
1106
+ function deriveSyncStateFromHealth(health) {
1107
+ if (health.status === "syncing") {
1108
+ return "syncing";
1084
1109
  }
1085
- const { connectorId } = widget.metric;
1086
- if (connectors !== void 0 && !isAllowedConnector(connectors, connectorId)) {
1110
+ if (FAILING_CONNECTOR_STATUSES.has(health.status)) {
1111
+ return "failing";
1112
+ }
1113
+ if (!health.lastSyncAt) {
1114
+ return "unsynced";
1115
+ }
1116
+ const ageMs = Date.now() - new Date(health.lastSyncAt).getTime();
1117
+ const windowMs = 2 * health.syncIntervalSeconds * 1e3;
1118
+ return ageMs <= windowMs ? "fresh" : "stale";
1119
+ }
1120
+ function buildMetaFromHealth(health) {
1121
+ const meta = { connectorStatus: health.status };
1122
+ if (health.lastError) {
1123
+ meta["lastError"] = health.lastError;
1124
+ }
1125
+ return meta;
1126
+ }
1127
+ async function resolveWidget(widgetId, widget, connectors, storage) {
1128
+ const connectorId = widget.kind === "status" ? widget.source : widget.metric.connectorId;
1129
+ if (connectors !== void 0 && !connectors.includes(connectorId)) {
1087
1130
  return void 0;
1088
1131
  }
1089
1132
  const handle = storage.getStorageHandle(connectorId);
1090
- const data = await computeMetric(handle, widget.metric);
1133
+ const health = await handle.getHealth?.() ?? null;
1134
+ const data = widget.kind === "status" ? null : await computeMetric(handle, widget.metric);
1135
+ let syncState;
1136
+ let meta;
1137
+ if (health) {
1138
+ syncState = deriveSyncStateFromHealth(health);
1139
+ meta = buildMetaFromHealth(health);
1140
+ } else if (data === null || data === void 0) {
1141
+ syncState = "unsynced";
1142
+ } else {
1143
+ syncState = "fresh";
1144
+ }
1091
1145
  return {
1092
1146
  widgetId,
1093
1147
  connectorId,
1094
1148
  data,
1095
- cachedAt: (await storage.getSyncState()).lastSyncAt
1149
+ cachedAt: health?.lastSyncAt ?? null,
1150
+ syncState,
1151
+ meta
1096
1152
  };
1097
1153
  }
1098
- function isAllowedConnector(connectors, connectorId) {
1099
- if (connectors.length === 0) {
1100
- return false;
1154
+
1155
+ // src/registry.ts
1156
+ function instantiateConnector(entry, registry, secretsResolver) {
1157
+ const Cls = registry[entry.connectorId];
1158
+ if (!Cls) {
1159
+ throw new Error(
1160
+ `Unknown connector type "${entry.connectorId}" for instance "${entry.name}". Add it to the connectorRegistry.`
1161
+ );
1101
1162
  }
1102
- if (typeof connectors[0] === "string") {
1103
- return connectors.includes(connectorId);
1163
+ const credSchema = Cls.credentials;
1164
+ const settings = {};
1165
+ const creds = {};
1166
+ for (const [key, value] of Object.entries(entry.config)) {
1167
+ if (credSchema && Object.prototype.hasOwnProperty.call(credSchema, key)) {
1168
+ creds[key] = value;
1169
+ } else {
1170
+ settings[key] = value;
1171
+ }
1104
1172
  }
1105
- return connectors.some(
1106
- (e) => e.connector.id === connectorId
1107
- );
1173
+ return new Cls(settings, credSchema ? creds : void 0, {
1174
+ secretsResolver
1175
+ });
1108
1176
  }
1109
1177
 
1110
1178
  // src/storage-handle-guard.ts
@@ -1202,7 +1270,8 @@ function withAbortSignal(handle, signal) {
1202
1270
  queryEntities: (q) => handle.queryEntities(q),
1203
1271
  queryMetrics: (q) => handle.queryMetrics(q),
1204
1272
  traverse: (q) => handle.traverse(q),
1205
- queryDistributions: (q) => handle.queryDistributions(q)
1273
+ queryDistributions: (q) => handle.queryDistributions(q),
1274
+ ...handle.getHealth ? { getHealth: handle.getHealth.bind(handle) } : {}
1206
1275
  };
1207
1276
  }
1208
1277
 
@@ -1213,6 +1282,7 @@ var InMemoryStorage = class {
1213
1282
  metricStore = /* @__PURE__ */ new Map();
1214
1283
  edgeStore = /* @__PURE__ */ new Map();
1215
1284
  distributionStore = /* @__PURE__ */ new Map();
1285
+ lastWriteAt = /* @__PURE__ */ new Map();
1216
1286
  syncState = {
1217
1287
  status: "idle",
1218
1288
  queuedAt: null,
@@ -1225,6 +1295,9 @@ var InMemoryStorage = class {
1225
1295
  return options?.signal ? withAbortSignal(handle, options.signal) : handle;
1226
1296
  }
1227
1297
  buildHandle(connectorId) {
1298
+ const touch = () => {
1299
+ this.lastWriteAt.set(connectorId, (/* @__PURE__ */ new Date()).toISOString());
1300
+ };
1228
1301
  const getEntityMap = () => {
1229
1302
  if (!this.entityStore.has(connectorId)) {
1230
1303
  this.entityStore.set(connectorId, /* @__PURE__ */ new Map());
@@ -1268,24 +1341,29 @@ var InMemoryStorage = class {
1268
1341
  this.eventStore.set(connectorId, []);
1269
1342
  }
1270
1343
  this.eventStore.get(connectorId).push(e);
1344
+ touch();
1271
1345
  },
1272
1346
  entity: async (e) => {
1273
1347
  upsertEntities([e]);
1348
+ touch();
1274
1349
  },
1275
1350
  metric: async (m) => {
1276
1351
  if (!this.metricStore.has(connectorId)) {
1277
1352
  this.metricStore.set(connectorId, []);
1278
1353
  }
1279
1354
  this.metricStore.get(connectorId).push(m);
1355
+ touch();
1280
1356
  },
1281
1357
  edge: async (e) => {
1282
1358
  upsertEdges([e]);
1359
+ touch();
1283
1360
  },
1284
1361
  distribution: async (d) => {
1285
1362
  if (!this.distributionStore.has(connectorId)) {
1286
1363
  this.distributionStore.set(connectorId, []);
1287
1364
  }
1288
1365
  this.distributionStore.get(connectorId).push(d);
1366
+ touch();
1289
1367
  },
1290
1368
  events: async (es, scope) => {
1291
1369
  const names = new Set(scope?.names ?? es.map((e) => e.name));
@@ -1293,6 +1371,7 @@ var InMemoryStorage = class {
1293
1371
  (e) => !names.has(e.name)
1294
1372
  );
1295
1373
  this.eventStore.set(connectorId, [...kept, ...es]);
1374
+ touch();
1296
1375
  },
1297
1376
  entities: async (es, scope) => {
1298
1377
  const byType = getEntityMap();
@@ -1301,6 +1380,7 @@ var InMemoryStorage = class {
1301
1380
  byType.set(type, /* @__PURE__ */ new Map());
1302
1381
  }
1303
1382
  upsertEntities(es);
1383
+ touch();
1304
1384
  },
1305
1385
  metrics: async (ms, scope) => {
1306
1386
  const names = new Set(scope?.names ?? ms.map((m) => m.name));
@@ -1308,6 +1388,7 @@ var InMemoryStorage = class {
1308
1388
  (m) => !names.has(m.name)
1309
1389
  );
1310
1390
  this.metricStore.set(connectorId, [...kept, ...ms]);
1391
+ touch();
1311
1392
  },
1312
1393
  edges: async (es, scope) => {
1313
1394
  const kinds = new Set(scope?.kinds ?? es.map((e) => e.kind));
@@ -1316,6 +1397,7 @@ var InMemoryStorage = class {
1316
1397
  );
1317
1398
  this.edgeStore.set(connectorId, kept);
1318
1399
  upsertEdges(es);
1400
+ touch();
1319
1401
  },
1320
1402
  distributions: async (ds, scope) => {
1321
1403
  const names = new Set(scope?.names ?? ds.map((d) => d.name));
@@ -1323,6 +1405,7 @@ var InMemoryStorage = class {
1323
1405
  (d) => !names.has(d.name)
1324
1406
  );
1325
1407
  this.distributionStore.set(connectorId, [...kept, ...ds]);
1408
+ touch();
1326
1409
  },
1327
1410
  queryEvents: async (q) => {
1328
1411
  let results = this.eventStore.get(connectorId) ?? [];
@@ -1413,6 +1496,14 @@ var InMemoryStorage = class {
1413
1496
  `Unsupported shape for deleteOlderThan: ${String(shape)}`
1414
1497
  );
1415
1498
  }
1499
+ },
1500
+ getHealth: async () => {
1501
+ return {
1502
+ status: "idle",
1503
+ lastSyncAt: this.lastWriteAt.get(connectorId) ?? null,
1504
+ lastError: null,
1505
+ syncIntervalSeconds: 0
1506
+ };
1416
1507
  }
1417
1508
  };
1418
1509
  }
@@ -1485,13 +1576,13 @@ var wireConfigSchema = z3.object({
1485
1576
  });
1486
1577
  function toWireConfig(config) {
1487
1578
  return {
1488
- connectors: config.connectors.map(({ connector }) => ({
1489
- name: connector.id,
1490
- connectorId: connector.id,
1491
- displayName: connector.id,
1492
- config: connector.serializeConfig(),
1493
- syncIntervalSeconds: 300,
1494
- enabled: true
1579
+ connectors: config.connectors.map((entry) => ({
1580
+ name: entry.name,
1581
+ connectorId: entry.connectorId,
1582
+ displayName: entry.displayName ?? entry.name,
1583
+ config: entry.config,
1584
+ syncIntervalSeconds: entry.syncIntervalSeconds ?? 300,
1585
+ enabled: entry.enabled ?? true
1495
1586
  })),
1496
1587
  dashboards: Object.entries(config.dashboards).map(([id, dash]) => ({
1497
1588
  id,
@@ -1522,6 +1613,7 @@ export {
1522
1613
  filterOperatorSchema,
1523
1614
  getWidgetSchema,
1524
1615
  groupBySchema,
1616
+ instantiateConnector,
1525
1617
  isSecret,
1526
1618
  isSyncActive,
1527
1619
  paginateChunked,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../connector-shared/src/errors.ts","../../connector-shared/src/retry.ts","../../connector-shared/src/version.ts","../../connector-shared/src/request.ts","../../connector-shared/src/rate-limit.ts","../../connector-shared/src/pagination.ts","../src/secrets.ts","../src/connector.ts","../src/paginate-chunked.ts","../src/widget-schemas.ts","../src/config.ts","../src/engine.ts","../src/retention.ts","../src/config-fields.ts","../src/compute.ts","../src/resolve-widget.ts","../src/storage-handle-guard.ts","../src/in-memory-storage.ts","../src/wire-config.ts"],"sourcesContent":["import type { HttpResponse } from './types';\n\nexport type HttpErrorKind =\n | 'transient'\n | 'rate_limit'\n | 'auth'\n | 'upstream_bug'\n | 'client_bug';\n\nexport abstract class HttpClientError extends Error {\n abstract readonly kind: HttpErrorKind;\n readonly response?: HttpResponse;\n\n constructor(message: string, response?: HttpResponse) {\n super(message);\n this.name = new.target.name;\n this.response = response;\n }\n}\n\nexport class TransientError extends HttpClientError {\n readonly kind = 'transient' as const;\n}\n\nexport class RateLimitError extends HttpClientError {\n readonly kind = 'rate_limit' as const;\n readonly retryAfter?: Date;\n\n constructor(message: string, response?: HttpResponse, retryAfter?: Date) {\n super(message, response);\n this.retryAfter = retryAfter;\n }\n}\n\nexport class AuthError extends HttpClientError {\n readonly kind = 'auth' as const;\n}\n\nexport class UpstreamBugError extends HttpClientError {\n readonly kind = 'upstream_bug' as const;\n}\n\nexport class ClientBugError extends HttpClientError {\n readonly kind = 'client_bug' as const;\n}\n\nexport function classifyStatus(status: number): HttpErrorKind {\n if (status === 429) {\n return 'rate_limit';\n }\n if (status === 401 || status === 403) {\n return 'auth';\n }\n if (status === 408) {\n return 'transient';\n }\n if (status >= 500) {\n return 'upstream_bug';\n }\n if (status >= 400) {\n return 'client_bug';\n }\n return 'client_bug';\n}\n\nexport function errorForStatus(\n message: string,\n response: HttpResponse,\n retryAfter?: Date,\n): HttpClientError {\n const kind = classifyStatus(response.status);\n switch (kind) {\n case 'rate_limit':\n return new RateLimitError(message, response, retryAfter);\n case 'auth':\n return new AuthError(message, response);\n case 'transient':\n return new TransientError(message, response);\n case 'upstream_bug':\n return new UpstreamBugError(message, response);\n case 'client_bug':\n return new ClientBugError(message, response);\n }\n}\n","import { HttpClientError, RateLimitError, TransientError } from './errors';\n\nexport interface RetryPolicy {\n maxAttempts?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n retryOn?: (status: number | null, err?: Error) => boolean;\n}\n\nexport const defaultRetryOn = (status: number | null, err?: Error): boolean => {\n if (err instanceof RateLimitError) {\n return true;\n }\n if (err instanceof TransientError) {\n return true;\n }\n if (status === null) {\n return err instanceof Error && !(err instanceof HttpClientError);\n }\n if (status === 408 || status === 429) {\n return true;\n }\n if (status >= 500) {\n return true;\n }\n return false;\n};\n\nexport function backoffDelayMs(\n attempt: number,\n policy: Required<Pick<RetryPolicy, 'initialDelayMs' | 'maxDelayMs'>>,\n): number {\n const base = policy.initialDelayMs * 2 ** attempt;\n const jitter = base * 0.25 * Math.random();\n return Math.min(base + jitter, policy.maxDelayMs);\n}\n\nexport function parseRetryAfter(\n headerValue: string | null,\n now: Date = new Date(),\n): Date | undefined {\n if (!headerValue) {\n return undefined;\n }\n const trimmed = headerValue.trim();\n if (/^\\d+$/.test(trimmed)) {\n return new Date(now.getTime() + Number(trimmed) * 1000);\n }\n const parsed = Date.parse(trimmed);\n if (Number.isNaN(parsed)) {\n return undefined;\n }\n return new Date(parsed);\n}\n\nexport function 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","export const HTTP_CLIENT_VERSION = '0.0.0';\n\nexport const DEFAULT_USER_AGENT = `rawdash-connector/${HTTP_CLIENT_VERSION} (+https://rawdash.dev)`;\n","import {\n AuthError,\n ClientBugError,\n HttpClientError,\n RateLimitError,\n TransientError,\n UpstreamBugError,\n errorForStatus,\n} from './errors';\nimport { defaultRetryOn, parseRetryAfter, sleep } from './retry';\nimport type { FetchLike, HttpMethod, HttpRequest, HttpResponse } from './types';\nimport { DEFAULT_USER_AGENT } from './version';\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_ATTEMPTS = 3;\nconst DEFAULT_INITIAL_DELAY_MS = 1000;\nconst DEFAULT_MAX_DELAY_MS = 60_000;\nconst OBSERVER_TIMEOUT_MS = 250;\n\nexport interface RequestObservation {\n url: string;\n method: HttpMethod;\n status: number;\n resource: string;\n requestId: string;\n body: unknown;\n}\n\nexport type RequestObserver = (\n event: RequestObservation,\n) => void | Promise<void>;\n\nexport interface RequestOptions {\n fetch?: FetchLike;\n observer?: RequestObserver;\n resource: string;\n requestId?: string;\n}\n\nasync function notifyObserver(\n observer: RequestObserver,\n event: RequestObservation,\n): Promise<void> {\n let result: void | Promise<void>;\n try {\n result = observer(event);\n } catch (err) {\n console.warn('[connector-shared] request observer threw:', err);\n return;\n }\n if (!(result instanceof Promise)) {\n return;\n }\n const guarded = result.catch((err) => {\n console.warn('[connector-shared] request observer rejected:', err);\n });\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<void>((resolve) => {\n timer = setTimeout(resolve, OBSERVER_TIMEOUT_MS);\n });\n try {\n await Promise.race([guarded, timeout]);\n } finally {\n if (timer) {\n clearTimeout(timer);\n }\n }\n}\n\nfunction newRequestId(): string {\n const c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (c?.randomUUID) {\n return c.randomUUID();\n }\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction mergeHeaders(\n defaults: Record<string, string>,\n overrides: Record<string, string> | undefined,\n): Record<string, string> {\n const merged: Record<string, string> = {};\n for (const [k, v] of Object.entries(defaults)) {\n merged[k.toLowerCase()] = v;\n }\n if (overrides) {\n for (const [k, v] of Object.entries(overrides)) {\n merged[k.toLowerCase()] = v;\n }\n }\n return merged;\n}\n\nfunction linkTimeoutSignal(\n parent: AbortSignal | undefined,\n timeoutMs: number,\n): { signal: AbortSignal; cancel: () => void } {\n const controller = new AbortController();\n const onParentAbort = () => {\n controller.abort(parent?.reason);\n };\n if (parent) {\n if (parent.aborted) {\n controller.abort(parent.reason);\n } else {\n parent.addEventListener('abort', onParentAbort, { once: true });\n }\n }\n const timer = setTimeout(() => {\n controller.abort(new Error(`Request timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n return {\n signal: controller.signal,\n cancel: () => {\n clearTimeout(timer);\n if (parent) {\n parent.removeEventListener('abort', onParentAbort);\n }\n },\n };\n}\n\nasync function readBody(res: Response, parseJson: boolean): Promise<unknown> {\n if (res.status === 204 || res.status === 205) {\n return null;\n }\n const contentType = res.headers.get('content-type') ?? '';\n if (parseJson && contentType.includes('application/json')) {\n const text = await res.text();\n if (text.length === 0) {\n return null;\n }\n return JSON.parse(text);\n }\n return res.text();\n}\n\nexport async function request<T = unknown>(\n req: HttpRequest,\n options: RequestOptions,\n): Promise<HttpResponse<T>> {\n const fetchImpl: FetchLike = options.fetch ?? (globalThis.fetch as FetchLike);\n const retry = req.retry ?? {};\n const maxAttempts = retry.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;\n const initialDelayMs = retry.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS;\n const maxDelayMs = retry.maxDelayMs ?? DEFAULT_MAX_DELAY_MS;\n const retryOn = retry.retryOn ?? defaultRetryOn;\n const timeoutMs = req.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const parseJson = req.parseJson ?? true;\n\n const headers = mergeHeaders(\n {\n 'User-Agent': DEFAULT_USER_AGENT,\n Accept: 'application/json',\n },\n req.headers,\n );\n\n let lastErr: Error | undefined;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n req.signal?.throwIfAborted();\n\n const { signal, cancel } = linkTimeoutSignal(req.signal, timeoutMs);\n let res: Response;\n try {\n res = await fetchImpl(req.url, {\n method: req.method ?? 'GET',\n headers,\n body: req.body as RequestInit['body'],\n signal,\n });\n } catch (err) {\n cancel();\n if (req.signal?.aborted) {\n throw req.signal.reason ?? err;\n }\n const error = err instanceof Error ? err : new Error(String(err));\n lastErr = error;\n if (attempt < maxAttempts - 1 && retryOn(null, error)) {\n const delay = computeDelay(attempt, initialDelayMs, maxDelayMs);\n await sleep(delay, req.signal);\n continue;\n }\n throw new TransientError(error.message);\n }\n cancel();\n\n const body = await readBody(res, parseJson);\n const httpResponse: HttpResponse<T> = {\n status: res.status,\n headers: res.headers,\n body: body as T,\n };\n if (req.rateLimit) {\n const state = req.rateLimit.parse(res.headers);\n if (state) {\n httpResponse.rateLimitState = state;\n }\n }\n\n if (options.observer) {\n await notifyObserver(options.observer, {\n url: req.url,\n method: req.method ?? 'GET',\n status: res.status,\n resource: options.resource,\n requestId: options.requestId ?? newRequestId(),\n body,\n });\n }\n\n if (res.ok) {\n return httpResponse;\n }\n\n const retryAfter = parseRetryAfter(res.headers.get('retry-after'));\n const message = `HTTP ${res.status} ${res.statusText} for ${req.method ?? 'GET'} ${req.url}`;\n const err = errorForStatus(message, httpResponse, retryAfter);\n\n if (\n attempt < maxAttempts - 1 &&\n retryOn(res.status, err) &&\n !(err instanceof AuthError) &&\n !(err instanceof ClientBugError)\n ) {\n lastErr = err;\n let delay = computeDelay(attempt, initialDelayMs, maxDelayMs);\n if (err instanceof RateLimitError && retryAfter) {\n const wait = retryAfter.getTime() - Date.now();\n if (wait > 0) {\n delay = Math.min(wait, maxDelayMs);\n }\n }\n await sleep(delay, req.signal);\n continue;\n }\n\n throw err;\n }\n\n throw lastErr ?? new UpstreamBugError('Exhausted retry attempts');\n}\n\nfunction computeDelay(\n attempt: number,\n initialDelayMs: number,\n maxDelayMs: number,\n): number {\n const base = initialDelayMs * 2 ** attempt;\n const jitter = base * 0.25 * Math.random();\n return Math.min(base + jitter, maxDelayMs);\n}\n\nexport { HttpClientError };\n","export interface RateLimitState {\n remaining: number;\n resetAt: Date;\n}\n\nexport interface RateLimitPolicy {\n parse(headers: Headers): RateLimitState | null;\n}\n\nexport const githubRateLimit: RateLimitPolicy = {\n parse(h) {\n const remainingRaw = h.get('x-ratelimit-remaining');\n const resetRaw = h.get('x-ratelimit-reset');\n if (remainingRaw === null || resetRaw === null) {\n return null;\n }\n const remaining = Number(remainingRaw);\n const reset = Number(resetRaw);\n if (!Number.isFinite(remaining) || !Number.isFinite(reset) || reset < 0) {\n return null;\n }\n return { remaining, resetAt: new Date(reset * 1000) };\n },\n};\n\nexport const sentryRateLimit: RateLimitPolicy = {\n parse(h) {\n const concurrent = h.get('x-sentry-rate-limit-remaining');\n const reset = h.get('x-sentry-rate-limit-reset');\n if (concurrent === null || reset === null) {\n return null;\n }\n const remaining = Number(concurrent);\n const resetSec = Number(reset);\n if (\n !Number.isFinite(remaining) ||\n !Number.isFinite(resetSec) ||\n resetSec < 0\n ) {\n return null;\n }\n return { remaining, resetAt: new Date(resetSec * 1000) };\n },\n};\n\nexport const linearRateLimit: RateLimitPolicy = {\n parse(h) {\n const remainingRaw = h.get('x-ratelimit-requests-remaining');\n const resetRaw = h.get('x-ratelimit-requests-reset');\n if (remainingRaw === null) {\n return null;\n }\n const remaining = Number(remainingRaw);\n if (!Number.isFinite(remaining)) {\n return null;\n }\n let resetAt: Date;\n if (resetRaw !== null) {\n const reset = Number(resetRaw);\n if (!Number.isFinite(reset) || reset < 0) {\n return null;\n }\n resetAt = new Date(reset);\n } else {\n resetAt = new Date(Date.now() + 60_000);\n }\n return { remaining, resetAt };\n },\n};\n","import { request } from './request';\nimport type { HttpRequest } from './types';\n\nexport function parseLinkHeader(header: string | null): Record<string, string> {\n if (!header) {\n return {};\n }\n const result: Record<string, string> = {};\n for (const part of header.split(',')) {\n const match = part.match(/<([^>]+)>\\s*;\\s*rel=\"([^\"]+)\"/);\n if (match) {\n result[match[2]!] = match[1]!;\n }\n }\n return result;\n}\n\nexport async function* paginateLink<T>(\n initial: HttpRequest,\n parse: (body: unknown) => T[],\n options: { resource: string },\n): AsyncIterable<T> {\n let next: string | null = initial.url;\n while (next) {\n const res: Awaited<ReturnType<typeof request>> = await request(\n {\n ...initial,\n url: next,\n },\n { resource: options.resource },\n );\n for (const item of parse(res.body)) {\n yield item;\n }\n const links = parseLinkHeader(res.headers.get('link'));\n next = links['next'] ?? null;\n }\n}\n\nexport async function* paginateCursor<T>(\n initial: HttpRequest,\n parse: (body: unknown) => { items: T[]; nextCursor: string | null },\n buildNext: (req: HttpRequest, cursor: string) => HttpRequest,\n options: { resource: string },\n): AsyncIterable<T> {\n let req: HttpRequest = initial;\n while (true) {\n const res = await request(req, { resource: options.resource });\n const { items, nextCursor } = parse(res.body);\n for (const item of items) {\n yield item;\n }\n if (!nextCursor) {\n return;\n }\n req = buildNext(req, nextCursor);\n }\n}\n\nexport async function* paginatePage<T>(\n initial: HttpRequest,\n parse: (body: unknown) => { items: T[]; hasMore: boolean },\n buildPage: (req: HttpRequest, page: number) => HttpRequest,\n options: { resource: string },\n): AsyncIterable<T> {\n let page = 1;\n while (true) {\n const req = page === 1 ? initial : buildPage(initial, page);\n const res = await request(req, { resource: options.resource });\n const { items, hasMore } = parse(res.body);\n for (const item of items) {\n yield item;\n }\n if (!hasMore || items.length === 0) {\n return;\n }\n page++;\n }\n}\n","export type Secret = { $secret: string };\n\nexport function secret(name: string): Secret {\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 isSecret(value: unknown): value is Secret {\n return (\n typeof value === 'object' &&\n value !== null &&\n '$secret' in value &&\n typeof (value as Secret).$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 extractSecretNames(value: unknown): string[] {\n const names: string[] = [];\n const visit = (v: unknown): void => {\n if (isSecret(v)) {\n names.push(v.$secret);\n return;\n }\n if (v && typeof v === 'object') {\n if (Array.isArray(v)) {\n v.forEach(visit);\n } else {\n Object.values(v as Record<string, unknown>).forEach(visit);\n }\n }\n };\n visit(value);\n return [...new Set(names)];\n}\n\nexport function resolveSecrets<T>(obj: T, resolver: SecretsResolver): T {\n if (isSecret(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) => resolveSecrets(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: resolveSecrets(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 type HttpRequest,\n type HttpResponse,\n type RequestObserver,\n request as sharedRequest,\n} from '@rawdash/connector-shared';\n\nimport {\n EnvSecretsResolver,\n type Secret,\n type SecretsResolver,\n resolveSecrets,\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 MetricSample {\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: MetricSample): 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: MetricSample[], 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<MetricSample[]>;\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 CredentialField {\n description: string;\n auth?: 'none' | 'optional' | 'required';\n}\n\nexport type CredentialsSchema = Record<string, CredentialField>;\n\nexport type InferCredentials<TCreds extends CredentialsSchema> = {\n [K in keyof TCreds]: TCreds[K] extends { auth: 'required' }\n ? string\n : string | undefined;\n};\n\nexport type InferCredentialInput<TCreds extends CredentialsSchema> = {\n [K in keyof TCreds]: TCreds[K] extends { auth: 'required' }\n ? string | Secret\n : string | Secret | undefined;\n};\n\n// ---------------------------------------------------------------------------\n// Sync + Connector\n// ---------------------------------------------------------------------------\n\nexport interface SyncOptions {\n mode: 'full' | 'latest';\n since?: string;\n cursor?: unknown;\n}\n\nexport interface SyncResult {\n done: boolean;\n cursor?: unknown;\n transientError?: unknown;\n}\n\nexport interface Connector {\n readonly id: string;\n readonly credentials?: CredentialsSchema;\n serializeConfig(): Record<string, unknown>;\n sync(\n options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<SyncResult>;\n}\n\nexport interface ConnectorContext {\n observer?: RequestObserver;\n secretsResolver?: SecretsResolver;\n}\n\nexport interface ConnectorRequestOptions {\n resource: string;\n requestId?: string;\n}\n\nexport interface RetryPolicy {\n maxAttempts?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n signal?: AbortSignal;\n}\n\nexport abstract class BaseConnector<\n TSettings = unknown,\n TCreds extends CredentialsSchema = CredentialsSchema,\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 private ctx: ConnectorContext;\n\n constructor(\n settings: TSettings,\n creds?: InferCredentialInput<TCreds>,\n ctx?: ConnectorContext,\n ) {\n this.settings = settings;\n this.rawCredInput = creds;\n this.ctx = ctx ?? {};\n this.creds = creds\n ? (resolveSecrets(\n creds,\n this.ctx.secretsResolver ?? new EnvSecretsResolver(),\n ) as InferCredentials<TCreds>)\n : ({} as InferCredentials<TCreds>);\n }\n\n protected request<T = unknown>(\n req: HttpRequest,\n opts: ConnectorRequestOptions,\n ): Promise<HttpResponse<T>> {\n return sharedRequest<T>(req, {\n resource: opts.resource,\n requestId: opts.requestId,\n observer: this.ctx.observer,\n });\n }\n\n protected get<T = unknown>(\n url: string,\n opts: ConnectorRequestOptions & {\n headers?: Record<string, string>;\n signal?: AbortSignal;\n rateLimit?: HttpRequest['rateLimit'];\n },\n ): Promise<HttpResponse<T>> {\n return this.request<T>(\n {\n url,\n method: 'GET',\n headers: opts.headers,\n signal: opts.signal,\n rateLimit: opts.rateLimit,\n },\n { resource: opts.resource, requestId: opts.requestId },\n );\n }\n\n protected post<T = unknown>(\n url: string,\n opts: ConnectorRequestOptions & {\n body?: HttpRequest['body'];\n headers?: Record<string, string>;\n signal?: AbortSignal;\n rateLimit?: HttpRequest['rateLimit'];\n },\n ): Promise<HttpResponse<T>> {\n return this.request<T>(\n {\n url,\n method: 'POST',\n headers: opts.headers,\n body: opts.body,\n signal: opts.signal,\n rateLimit: opts.rateLimit,\n },\n { resource: opts.resource, requestId: opts.requestId },\n );\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?: RetryPolicy,\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 options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<SyncResult>;\n}\n\nexport function defineConnector<TSettings>() {\n return function <\n TCreds extends CredentialsSchema = Record<string, never>,\n >(def: {\n id: string;\n credentials?: TCreds;\n sync: (\n this: { settings: TSettings; creds: InferCredentials<TCreds> },\n options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ) => Promise<SyncResult>;\n }): {\n new (\n settings: TSettings,\n creds?: InferCredentialInput<TCreds>,\n ctx?: ConnectorContext,\n ): 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 options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<SyncResult> {\n return def.sync.call(\n { settings: this.settings, creds: this.creds },\n options,\n storage,\n signal,\n );\n }\n }\n\n return DynamicConnector as unknown as {\n new (\n settings: TSettings,\n creds?: InferCredentialInput<TCreds>,\n ctx?: ConnectorContext,\n ): Connector;\n readonly id: string;\n readonly credentials: TCreds | undefined;\n };\n };\n}\n","import type { SyncResult } from './connector';\n\nexport interface ChunkedSyncCursor<TPhase extends string, TPage> {\n phase: TPhase;\n page: TPage | null;\n}\n\nexport interface FetchPageResult<TPage> {\n items: unknown[];\n next: TPage | null;\n}\n\nexport interface ChunkedSyncOptions<TPhase extends string, TPage> {\n phases: readonly TPhase[];\n cursor: ChunkedSyncCursor<TPhase, TPage> | undefined;\n signal: AbortSignal | undefined;\n fetchPage: (\n phase: TPhase,\n page: TPage | null,\n signal: AbortSignal | undefined,\n ) => Promise<FetchPageResult<TPage>>;\n writeBatch: (\n phase: TPhase,\n items: unknown[],\n page: TPage | null,\n ) => Promise<void>;\n}\n\nexport async function paginateChunked<TPhase extends string, TPage>(\n opts: ChunkedSyncOptions<TPhase, TPage>,\n): Promise<SyncResult> {\n const { phases, cursor, signal, fetchPage, writeBatch } = opts;\n\n if (phases.length === 0) {\n return { done: true };\n }\n\n const resumeIdx = cursor ? phases.indexOf(cursor.phase) : -1;\n const hasKnownResumePhase = resumeIdx >= 0;\n const startIdx = hasKnownResumePhase ? resumeIdx : 0;\n\n for (let i = startIdx; i < phases.length; i++) {\n const phase = phases[i]!;\n let page: TPage | null =\n i === startIdx && hasKnownResumePhase ? cursor!.page : null;\n\n while (true) {\n if (signal?.aborted) {\n return {\n done: false,\n cursor: { phase, page } satisfies ChunkedSyncCursor<TPhase, TPage>,\n };\n }\n let items: unknown[];\n let next: TPage | null;\n try {\n ({ items, next } = await fetchPage(phase, page, signal));\n } catch (err) {\n if (\n signal?.aborted ||\n (err instanceof Error && err.name === 'AbortError')\n ) {\n return {\n done: false,\n cursor: { phase, page } satisfies ChunkedSyncCursor<TPhase, TPage>,\n };\n }\n return {\n done: false,\n cursor: { phase, page } satisfies ChunkedSyncCursor<TPhase, TPage>,\n transientError: err,\n };\n }\n try {\n await writeBatch(phase, items, page);\n } catch (err) {\n if (\n signal?.aborted ||\n (err instanceof Error && err.name === 'AbortError')\n ) {\n return {\n done: false,\n cursor: { phase, page } satisfies ChunkedSyncCursor<TPhase, TPage>,\n };\n }\n return {\n done: false,\n cursor: { phase, page } satisfies ChunkedSyncCursor<TPhase, TPage>,\n transientError: err,\n };\n }\n if (next === null) {\n break;\n }\n page = next;\n }\n }\n\n return { done: true };\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 computedMetricSchema = 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: computedMetricSchema.meta({\n label: 'Metric',\n description: 'Computed 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: computedMetricSchema.meta({\n label: 'Metric',\n description: 'Computed 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: computedMetricSchema.meta({\n label: 'Metric',\n description: 'Computed 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\n// ---------------------------------------------------------------------------\n\nexport interface Metric {\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 ComputedMetric {\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: ComputedMetric;\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: ComputedMetric;\n window: string;\n granularity?: 'hour' | 'day' | 'week';\n}\n\nexport interface DistributionWidget {\n kind: 'distribution';\n title: string;\n metric: ComputedMetric;\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 ConfiguredConnector {\n connector: Connector;\n}\n\nexport interface Dashboard {\n widgets: Record<string, Widget>;\n}\n\nexport interface DashboardConfig {\n connectors: ConfiguredConnector[];\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: Metric): ComputedMetric {\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","export type SyncStatus = 'idle' | 'queued' | 'running' | 'succeeded' | 'failed';\n\nexport interface SyncState {\n status: SyncStatus;\n queuedAt: string | null;\n startedAt: string | null;\n lastSyncAt: string | null;\n lastError: string | null;\n}\n\nexport const ACTIVE_SYNC_STATUSES: ReadonlySet<SyncStatus> = new Set([\n 'queued',\n 'running',\n]);\n\nexport function isSyncActive(status: SyncStatus): boolean {\n return ACTIVE_SYNC_STATUSES.has(status);\n}\n","import type {\n Distribution,\n Event,\n MetricSample,\n StorageHandle,\n} 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// RetentionDeletionPlan — rows eligible for deletion across time-series shapes\n// ---------------------------------------------------------------------------\n\nexport interface RetentionDeletionPlan {\n events: Event[];\n metrics: MetricSample[];\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<RetentionDeletionPlan> {\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 { ComputedMetric } from './config';\nimport type { StorageHandle } from './connector';\n\ntype FilterClause = NonNullable<ComputedMetric['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: ComputedMetric['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: ComputedMetric,\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: ComputedMetric,\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 { ConfiguredConnector, Widget } from './config';\nimport type { ServerStorage } from './server-storage';\nimport type { CachedWidget } from './wire';\n\nexport async function resolveWidget(\n widgetId: string,\n widget: Widget,\n connectors: ConfiguredConnector[] | readonly string[] | undefined,\n storage: ServerStorage,\n): Promise<CachedWidget | undefined> {\n if (widget.kind === 'status') {\n return {\n widgetId,\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 widgetId,\n connectorId,\n data,\n cachedAt: (await storage.getSyncState()).lastSyncAt,\n };\n}\n\nfunction isAllowedConnector(\n connectors: ConfiguredConnector[] | 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 ConfiguredConnector[]).some(\n (e) => e.connector.id === connectorId,\n );\n}\n","import type { StorageHandle } from './connector';\n\nexport function withAbortSignal(\n handle: StorageHandle,\n signal: AbortSignal,\n): StorageHandle {\n let warned = false;\n const warnOnce = (method: string): void => {\n if (warned) {\n return;\n }\n warned = true;\n console.warn(\n `[rawdash storage] dropping post-abort write '${method}' — connector continued writing after AbortSignal fired`,\n );\n };\n\n return {\n event: async (e) => {\n if (signal.aborted) {\n warnOnce('event');\n return;\n }\n await handle.event(e);\n },\n entity: async (e) => {\n if (signal.aborted) {\n warnOnce('entity');\n return;\n }\n await handle.entity(e);\n },\n metric: async (m) => {\n if (signal.aborted) {\n warnOnce('metric');\n return;\n }\n await handle.metric(m);\n },\n edge: async (e) => {\n if (signal.aborted) {\n warnOnce('edge');\n return;\n }\n await handle.edge(e);\n },\n distribution: async (d) => {\n if (signal.aborted) {\n warnOnce('distribution');\n return;\n }\n await handle.distribution(d);\n },\n events: async (es, scope) => {\n if (signal.aborted) {\n warnOnce('events');\n return;\n }\n await handle.events(es, scope);\n },\n entities: async (es, scope) => {\n if (signal.aborted) {\n warnOnce('entities');\n return;\n }\n await handle.entities(es, scope);\n },\n metrics: async (ms, scope) => {\n if (signal.aborted) {\n warnOnce('metrics');\n return;\n }\n await handle.metrics(ms, scope);\n },\n edges: async (es, scope) => {\n if (signal.aborted) {\n warnOnce('edges');\n return;\n }\n await handle.edges(es, scope);\n },\n distributions: async (ds, scope) => {\n if (signal.aborted) {\n warnOnce('distributions');\n return;\n }\n await handle.distributions(ds, scope);\n },\n deleteOlderThan: async (shape, tsUnixMs) => {\n if (signal.aborted) {\n warnOnce('deleteOlderThan');\n return { rowsDeleted: 0 };\n }\n return handle.deleteOlderThan(shape, tsUnixMs);\n },\n queryEvents: (q) => handle.queryEvents(q),\n getEntity: (type, id) => handle.getEntity(type, id),\n queryEntities: (q) => handle.queryEntities(q),\n queryMetrics: (q) => handle.queryMetrics(q),\n traverse: (q) => handle.traverse(q),\n queryDistributions: (q) => handle.queryDistributions(q),\n };\n}\n","import type {\n Distribution,\n DistributionQuery,\n Edge,\n EdgeQuery,\n Entity,\n EntityQuery,\n Event,\n EventQuery,\n MetricQuery,\n MetricSample,\n StorageHandle,\n} from './connector';\nimport type { SyncState } from './engine';\nimport type { GetStorageHandleOptions, ServerStorage } from './server-storage';\nimport { withAbortSignal } from './storage-handle-guard';\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, MetricSample[]>();\n private edgeStore = new Map<string, Edge[]>();\n private distributionStore = new Map<string, Distribution[]>();\n private syncState: SyncState = {\n status: 'idle',\n queuedAt: null,\n startedAt: null,\n lastSyncAt: null,\n lastError: null,\n };\n\n getStorageHandle(\n connectorId: string,\n options?: GetStorageHandleOptions,\n ): StorageHandle {\n const handle = this.buildHandle(connectorId);\n return options?.signal ? withAbortSignal(handle, options.signal) : handle;\n }\n\n private buildHandle(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 markSyncQueued(): Promise<boolean> {\n if (\n this.syncState.status === 'queued' ||\n this.syncState.status === 'running'\n ) {\n return false;\n }\n this.syncState = {\n ...this.syncState,\n status: 'queued',\n queuedAt: new Date().toISOString(),\n startedAt: null,\n };\n return true;\n }\n\n async markSyncRunning(): Promise<boolean> {\n if (this.syncState.status !== 'queued') {\n return false;\n }\n this.syncState = {\n ...this.syncState,\n status: 'running',\n startedAt: new Date().toISOString(),\n };\n return true;\n }\n\n async markSyncSucceeded(): Promise<void> {\n const now = new Date().toISOString();\n this.syncState = {\n status: 'succeeded',\n queuedAt: null,\n startedAt: null,\n lastSyncAt: now,\n lastError: null,\n };\n }\n\n async markSyncFailed(error: string): Promise<void> {\n this.syncState = {\n ...this.syncState,\n status: 'failed',\n queuedAt: null,\n startedAt: null,\n lastError: error,\n };\n }\n}\n","import { z } from 'zod';\n\nimport type { DashboardConfig } from './config';\n\nexport const wireConnectorSchema = z.object({\n name: z.string(),\n connectorId: z.string(),\n displayName: z.string().optional(),\n config: z.record(z.string(), z.unknown()),\n syncIntervalSeconds: z.number().optional(),\n enabled: z.boolean().optional(),\n});\n\nexport const wireDashboardSchema = z.object({\n id: z.string().optional(),\n name: z.string(),\n slug: z.string(),\n config: z.record(z.string(), z.unknown()),\n});\n\nexport const wireConfigSchema = z.object({\n connectors: z.array(wireConnectorSchema).optional(),\n dashboards: z.array(wireDashboardSchema).optional(),\n});\n\nexport type WireConnector = z.infer<typeof wireConnectorSchema>;\nexport type WireDashboard = z.infer<typeof wireDashboardSchema>;\nexport type WireConfig = z.infer<typeof wireConfigSchema>;\n\nexport function toWireConfig(config: DashboardConfig): WireConfig {\n return {\n connectors: config.connectors.map(({ connector }) => ({\n name: connector.id,\n connectorId: connector.id,\n displayName: connector.id,\n config: connector.serializeConfig(),\n syncIntervalSeconds: 300,\n enabled: true,\n })),\n dashboards: Object.entries(config.dashboards).map(([id, dash]) => ({\n id,\n name: id,\n slug: id,\n config: { widgets: dash.widgets },\n })),\n };\n}\n"],"mappings":"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","names":["err","z","z"]}
1
+ {"version":3,"sources":["../../connector-shared/src/errors.ts","../../connector-shared/src/retry.ts","../../connector-shared/src/version.ts","../../connector-shared/src/request.ts","../../connector-shared/src/rate-limit.ts","../../connector-shared/src/pagination.ts","../src/secrets.ts","../src/connector.ts","../src/paginate-chunked.ts","../src/widget-schemas.ts","../src/config.ts","../src/engine.ts","../src/retention.ts","../src/config-fields.ts","../src/compute.ts","../src/resolve-widget.ts","../src/registry.ts","../src/storage-handle-guard.ts","../src/in-memory-storage.ts","../src/wire-config.ts"],"sourcesContent":["import type { HttpResponse } from './types';\n\nexport type HttpErrorKind =\n | 'transient'\n | 'rate_limit'\n | 'auth'\n | 'upstream_bug'\n | 'client_bug';\n\nexport abstract class HttpClientError extends Error {\n abstract readonly kind: HttpErrorKind;\n readonly response?: HttpResponse;\n\n constructor(message: string, response?: HttpResponse) {\n super(message);\n this.name = new.target.name;\n this.response = response;\n }\n}\n\nexport class TransientError extends HttpClientError {\n readonly kind = 'transient' as const;\n}\n\nexport class RateLimitError extends HttpClientError {\n readonly kind = 'rate_limit' as const;\n readonly retryAfter?: Date;\n\n constructor(message: string, response?: HttpResponse, retryAfter?: Date) {\n super(message, response);\n this.retryAfter = retryAfter;\n }\n}\n\nexport class AuthError extends HttpClientError {\n readonly kind = 'auth' as const;\n}\n\nexport class UpstreamBugError extends HttpClientError {\n readonly kind = 'upstream_bug' as const;\n}\n\nexport class ClientBugError extends HttpClientError {\n readonly kind = 'client_bug' as const;\n}\n\nexport function classifyStatus(status: number): HttpErrorKind {\n if (status === 429) {\n return 'rate_limit';\n }\n if (status === 401 || status === 403) {\n return 'auth';\n }\n if (status === 408) {\n return 'transient';\n }\n if (status >= 500) {\n return 'upstream_bug';\n }\n if (status >= 400) {\n return 'client_bug';\n }\n return 'client_bug';\n}\n\nexport function errorForStatus(\n message: string,\n response: HttpResponse,\n retryAfter?: Date,\n): HttpClientError {\n const kind = classifyStatus(response.status);\n switch (kind) {\n case 'rate_limit':\n return new RateLimitError(message, response, retryAfter);\n case 'auth':\n return new AuthError(message, response);\n case 'transient':\n return new TransientError(message, response);\n case 'upstream_bug':\n return new UpstreamBugError(message, response);\n case 'client_bug':\n return new ClientBugError(message, response);\n }\n}\n","import { HttpClientError, RateLimitError, TransientError } from './errors';\n\nexport interface RetryPolicy {\n maxAttempts?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n retryOn?: (status: number | null, err?: Error) => boolean;\n}\n\nexport const defaultRetryOn = (status: number | null, err?: Error): boolean => {\n if (err instanceof RateLimitError) {\n return true;\n }\n if (err instanceof TransientError) {\n return true;\n }\n if (status === null) {\n return err instanceof Error && !(err instanceof HttpClientError);\n }\n if (status === 408 || status === 429) {\n return true;\n }\n if (status >= 500) {\n return true;\n }\n return false;\n};\n\nexport function backoffDelayMs(\n attempt: number,\n policy: Required<Pick<RetryPolicy, 'initialDelayMs' | 'maxDelayMs'>>,\n): number {\n const base = policy.initialDelayMs * 2 ** attempt;\n const jitter = base * 0.25 * Math.random();\n return Math.min(base + jitter, policy.maxDelayMs);\n}\n\nexport function parseRetryAfter(\n headerValue: string | null,\n now: Date = new Date(),\n): Date | undefined {\n if (!headerValue) {\n return undefined;\n }\n const trimmed = headerValue.trim();\n if (/^\\d+$/.test(trimmed)) {\n return new Date(now.getTime() + Number(trimmed) * 1000);\n }\n const parsed = Date.parse(trimmed);\n if (Number.isNaN(parsed)) {\n return undefined;\n }\n return new Date(parsed);\n}\n\nexport function 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","export const HTTP_CLIENT_VERSION = '0.0.0';\n\nexport const DEFAULT_USER_AGENT = `rawdash-connector/${HTTP_CLIENT_VERSION} (+https://rawdash.dev)`;\n","import {\n AuthError,\n ClientBugError,\n HttpClientError,\n RateLimitError,\n TransientError,\n UpstreamBugError,\n errorForStatus,\n} from './errors';\nimport { defaultRetryOn, parseRetryAfter, sleep } from './retry';\nimport type { FetchLike, HttpMethod, HttpRequest, HttpResponse } from './types';\nimport { DEFAULT_USER_AGENT } from './version';\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_ATTEMPTS = 3;\nconst DEFAULT_INITIAL_DELAY_MS = 1000;\nconst DEFAULT_MAX_DELAY_MS = 60_000;\nconst OBSERVER_TIMEOUT_MS = 250;\n\nexport interface RequestObservation {\n url: string;\n method: HttpMethod;\n status: number;\n resource: string;\n requestId: string;\n body: unknown;\n}\n\nexport type RequestObserver = (\n event: RequestObservation,\n) => void | Promise<void>;\n\nexport interface RequestOptions {\n fetch?: FetchLike;\n observer?: RequestObserver;\n resource: string;\n requestId?: string;\n}\n\nasync function notifyObserver(\n observer: RequestObserver,\n event: RequestObservation,\n): Promise<void> {\n let result: void | Promise<void>;\n try {\n result = observer(event);\n } catch (err) {\n console.warn('[connector-shared] request observer threw:', err);\n return;\n }\n if (!(result instanceof Promise)) {\n return;\n }\n const guarded = result.catch((err) => {\n console.warn('[connector-shared] request observer rejected:', err);\n });\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<void>((resolve) => {\n timer = setTimeout(resolve, OBSERVER_TIMEOUT_MS);\n });\n try {\n await Promise.race([guarded, timeout]);\n } finally {\n if (timer) {\n clearTimeout(timer);\n }\n }\n}\n\nfunction newRequestId(): string {\n const c = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (c?.randomUUID) {\n return c.randomUUID();\n }\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction mergeHeaders(\n defaults: Record<string, string>,\n overrides: Record<string, string> | undefined,\n): Record<string, string> {\n const merged: Record<string, string> = {};\n for (const [k, v] of Object.entries(defaults)) {\n merged[k.toLowerCase()] = v;\n }\n if (overrides) {\n for (const [k, v] of Object.entries(overrides)) {\n merged[k.toLowerCase()] = v;\n }\n }\n return merged;\n}\n\nfunction linkTimeoutSignal(\n parent: AbortSignal | undefined,\n timeoutMs: number,\n): { signal: AbortSignal; cancel: () => void } {\n const controller = new AbortController();\n const onParentAbort = () => {\n controller.abort(parent?.reason);\n };\n if (parent) {\n if (parent.aborted) {\n controller.abort(parent.reason);\n } else {\n parent.addEventListener('abort', onParentAbort, { once: true });\n }\n }\n const timer = setTimeout(() => {\n controller.abort(new Error(`Request timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n return {\n signal: controller.signal,\n cancel: () => {\n clearTimeout(timer);\n if (parent) {\n parent.removeEventListener('abort', onParentAbort);\n }\n },\n };\n}\n\nasync function readBody(res: Response, parseJson: boolean): Promise<unknown> {\n if (res.status === 204 || res.status === 205) {\n return null;\n }\n const contentType = res.headers.get('content-type') ?? '';\n if (parseJson && contentType.includes('application/json')) {\n const text = await res.text();\n if (text.length === 0) {\n return null;\n }\n return JSON.parse(text);\n }\n return res.text();\n}\n\nexport async function request<T = unknown>(\n req: HttpRequest,\n options: RequestOptions,\n): Promise<HttpResponse<T>> {\n const fetchImpl: FetchLike = options.fetch ?? (globalThis.fetch as FetchLike);\n const retry = req.retry ?? {};\n const maxAttempts = retry.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;\n const initialDelayMs = retry.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS;\n const maxDelayMs = retry.maxDelayMs ?? DEFAULT_MAX_DELAY_MS;\n const retryOn = retry.retryOn ?? defaultRetryOn;\n const timeoutMs = req.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const parseJson = req.parseJson ?? true;\n\n const headers = mergeHeaders(\n {\n 'User-Agent': DEFAULT_USER_AGENT,\n Accept: 'application/json',\n },\n req.headers,\n );\n\n let lastErr: Error | undefined;\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n req.signal?.throwIfAborted();\n\n const { signal, cancel } = linkTimeoutSignal(req.signal, timeoutMs);\n let res: Response;\n try {\n res = await fetchImpl(req.url, {\n method: req.method ?? 'GET',\n headers,\n body: req.body as RequestInit['body'],\n signal,\n });\n } catch (err) {\n cancel();\n if (req.signal?.aborted) {\n throw req.signal.reason ?? err;\n }\n const error = err instanceof Error ? err : new Error(String(err));\n lastErr = error;\n if (attempt < maxAttempts - 1 && retryOn(null, error)) {\n const delay = computeDelay(attempt, initialDelayMs, maxDelayMs);\n await sleep(delay, req.signal);\n continue;\n }\n throw new TransientError(error.message);\n }\n cancel();\n\n const body = await readBody(res, parseJson);\n const httpResponse: HttpResponse<T> = {\n status: res.status,\n headers: res.headers,\n body: body as T,\n };\n if (req.rateLimit) {\n const state = req.rateLimit.parse(res.headers);\n if (state) {\n httpResponse.rateLimitState = state;\n }\n }\n\n if (options.observer) {\n await notifyObserver(options.observer, {\n url: req.url,\n method: req.method ?? 'GET',\n status: res.status,\n resource: options.resource,\n requestId: options.requestId ?? newRequestId(),\n body,\n });\n }\n\n if (res.ok) {\n return httpResponse;\n }\n\n const retryAfter = parseRetryAfter(res.headers.get('retry-after'));\n const message = `HTTP ${res.status} ${res.statusText} for ${req.method ?? 'GET'} ${req.url}`;\n const err = errorForStatus(message, httpResponse, retryAfter);\n\n if (\n attempt < maxAttempts - 1 &&\n retryOn(res.status, err) &&\n !(err instanceof AuthError) &&\n !(err instanceof ClientBugError)\n ) {\n lastErr = err;\n let delay = computeDelay(attempt, initialDelayMs, maxDelayMs);\n if (err instanceof RateLimitError && retryAfter) {\n const wait = retryAfter.getTime() - Date.now();\n if (wait > 0) {\n delay = Math.min(wait, maxDelayMs);\n }\n }\n await sleep(delay, req.signal);\n continue;\n }\n\n throw err;\n }\n\n throw lastErr ?? new UpstreamBugError('Exhausted retry attempts');\n}\n\nfunction computeDelay(\n attempt: number,\n initialDelayMs: number,\n maxDelayMs: number,\n): number {\n const base = initialDelayMs * 2 ** attempt;\n const jitter = base * 0.25 * Math.random();\n return Math.min(base + jitter, maxDelayMs);\n}\n\nexport { HttpClientError };\n","export interface RateLimitState {\n remaining: number;\n resetAt: Date;\n}\n\nexport interface RateLimitPolicy {\n parse(headers: Headers): RateLimitState | null;\n}\n\nexport const githubRateLimit: RateLimitPolicy = {\n parse(h) {\n const remainingRaw = h.get('x-ratelimit-remaining');\n const resetRaw = h.get('x-ratelimit-reset');\n if (remainingRaw === null || resetRaw === null) {\n return null;\n }\n const remaining = Number(remainingRaw);\n const reset = Number(resetRaw);\n if (!Number.isFinite(remaining) || !Number.isFinite(reset) || reset < 0) {\n return null;\n }\n return { remaining, resetAt: new Date(reset * 1000) };\n },\n};\n\nexport const sentryRateLimit: RateLimitPolicy = {\n parse(h) {\n const concurrent = h.get('x-sentry-rate-limit-remaining');\n const reset = h.get('x-sentry-rate-limit-reset');\n if (concurrent === null || reset === null) {\n return null;\n }\n const remaining = Number(concurrent);\n const resetSec = Number(reset);\n if (\n !Number.isFinite(remaining) ||\n !Number.isFinite(resetSec) ||\n resetSec < 0\n ) {\n return null;\n }\n return { remaining, resetAt: new Date(resetSec * 1000) };\n },\n};\n\nexport const linearRateLimit: RateLimitPolicy = {\n parse(h) {\n const remainingRaw = h.get('x-ratelimit-requests-remaining');\n const resetRaw = h.get('x-ratelimit-requests-reset');\n if (remainingRaw === null) {\n return null;\n }\n const remaining = Number(remainingRaw);\n if (!Number.isFinite(remaining)) {\n return null;\n }\n let resetAt: Date;\n if (resetRaw !== null) {\n const reset = Number(resetRaw);\n if (!Number.isFinite(reset) || reset < 0) {\n return null;\n }\n resetAt = new Date(reset);\n } else {\n resetAt = new Date(Date.now() + 60_000);\n }\n return { remaining, resetAt };\n },\n};\n","import { request } from './request';\nimport type { HttpRequest } from './types';\n\nexport function parseLinkHeader(header: string | null): Record<string, string> {\n if (!header) {\n return {};\n }\n const result: Record<string, string> = {};\n for (const part of header.split(',')) {\n const match = part.match(/<([^>]+)>\\s*;\\s*rel=\"([^\"]+)\"/);\n if (match) {\n result[match[2]!] = match[1]!;\n }\n }\n return result;\n}\n\nexport async function* paginateLink<T>(\n initial: HttpRequest,\n parse: (body: unknown) => T[],\n options: { resource: string },\n): AsyncIterable<T> {\n let next: string | null = initial.url;\n while (next) {\n const res: Awaited<ReturnType<typeof request>> = await request(\n {\n ...initial,\n url: next,\n },\n { resource: options.resource },\n );\n for (const item of parse(res.body)) {\n yield item;\n }\n const links = parseLinkHeader(res.headers.get('link'));\n next = links['next'] ?? null;\n }\n}\n\nexport async function* paginateCursor<T>(\n initial: HttpRequest,\n parse: (body: unknown) => { items: T[]; nextCursor: string | null },\n buildNext: (req: HttpRequest, cursor: string) => HttpRequest,\n options: { resource: string },\n): AsyncIterable<T> {\n let req: HttpRequest = initial;\n while (true) {\n const res = await request(req, { resource: options.resource });\n const { items, nextCursor } = parse(res.body);\n for (const item of items) {\n yield item;\n }\n if (!nextCursor) {\n return;\n }\n req = buildNext(req, nextCursor);\n }\n}\n\nexport async function* paginatePage<T>(\n initial: HttpRequest,\n parse: (body: unknown) => { items: T[]; hasMore: boolean },\n buildPage: (req: HttpRequest, page: number) => HttpRequest,\n options: { resource: string },\n): AsyncIterable<T> {\n let page = 1;\n while (true) {\n const req = page === 1 ? initial : buildPage(initial, page);\n const res = await request(req, { resource: options.resource });\n const { items, hasMore } = parse(res.body);\n for (const item of items) {\n yield item;\n }\n if (!hasMore || items.length === 0) {\n return;\n }\n page++;\n }\n}\n","export type Secret = { $secret: string };\n\nexport function secret(name: string): Secret {\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 isSecret(value: unknown): value is Secret {\n return (\n typeof value === 'object' &&\n value !== null &&\n '$secret' in value &&\n typeof (value as Secret).$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 extractSecretNames(value: unknown): string[] {\n const names: string[] = [];\n const visit = (v: unknown): void => {\n if (isSecret(v)) {\n names.push(v.$secret);\n return;\n }\n if (v && typeof v === 'object') {\n if (Array.isArray(v)) {\n v.forEach(visit);\n } else {\n Object.values(v as Record<string, unknown>).forEach(visit);\n }\n }\n };\n visit(value);\n return [...new Set(names)];\n}\n\nexport function resolveSecrets<T>(obj: T, resolver: SecretsResolver): T {\n if (isSecret(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) => resolveSecrets(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: resolveSecrets(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 type HttpRequest,\n type HttpResponse,\n type RequestObserver,\n request as sharedRequest,\n} from '@rawdash/connector-shared';\n\nimport {\n EnvSecretsResolver,\n type Secret,\n type SecretsResolver,\n resolveSecrets,\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 MetricSample {\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: MetricSample): 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: MetricSample[], 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<MetricSample[]>;\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 getHealth?(): Promise<ConnectorHealth | null>;\n}\n\nexport interface ConnectorHealth {\n status: 'idle' | 'syncing' | 'error' | 'auth_failed' | 'paused';\n lastSyncAt: string | null;\n lastError: string | null;\n syncIntervalSeconds: number;\n}\n\n// ---------------------------------------------------------------------------\n// Credentials\n// ---------------------------------------------------------------------------\n\nexport interface CredentialField {\n description: string;\n auth?: 'none' | 'optional' | 'required';\n}\n\nexport type CredentialsSchema = Record<string, CredentialField>;\n\nexport type InferCredentials<TCreds extends CredentialsSchema> = {\n [K in keyof TCreds]: TCreds[K] extends { auth: 'required' }\n ? string\n : string | undefined;\n};\n\nexport type InferCredentialInput<TCreds extends CredentialsSchema> = {\n [K in keyof TCreds]: TCreds[K] extends { auth: 'required' }\n ? string | Secret\n : string | Secret | undefined;\n};\n\n// ---------------------------------------------------------------------------\n// Sync + Connector\n// ---------------------------------------------------------------------------\n\nexport interface SyncOptions {\n mode: 'full' | 'latest';\n since?: string;\n cursor?: unknown;\n}\n\nexport interface SyncResult {\n done: boolean;\n cursor?: unknown;\n transientError?: unknown;\n}\n\nexport interface Connector {\n readonly id: string;\n readonly credentials?: CredentialsSchema;\n serializeConfig(): Record<string, unknown>;\n sync(\n options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<SyncResult>;\n}\n\nexport interface ConnectorContext {\n observer?: RequestObserver;\n secretsResolver?: SecretsResolver;\n}\n\nexport interface ConnectorRequestOptions {\n resource: string;\n requestId?: string;\n}\n\nexport interface RetryPolicy {\n maxAttempts?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n signal?: AbortSignal;\n}\n\nexport abstract class BaseConnector<\n TSettings = unknown,\n TCreds extends CredentialsSchema = CredentialsSchema,\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 private ctx: ConnectorContext;\n\n constructor(\n settings: TSettings,\n creds?: InferCredentialInput<TCreds>,\n ctx?: ConnectorContext,\n ) {\n this.settings = settings;\n this.rawCredInput = creds;\n this.ctx = ctx ?? {};\n this.creds = creds\n ? (resolveSecrets(\n creds,\n this.ctx.secretsResolver ?? new EnvSecretsResolver(),\n ) as InferCredentials<TCreds>)\n : ({} as InferCredentials<TCreds>);\n }\n\n protected request<T = unknown>(\n req: HttpRequest,\n opts: ConnectorRequestOptions,\n ): Promise<HttpResponse<T>> {\n return sharedRequest<T>(req, {\n resource: opts.resource,\n requestId: opts.requestId,\n observer: this.ctx.observer,\n });\n }\n\n protected get<T = unknown>(\n url: string,\n opts: ConnectorRequestOptions & {\n headers?: Record<string, string>;\n signal?: AbortSignal;\n rateLimit?: HttpRequest['rateLimit'];\n },\n ): Promise<HttpResponse<T>> {\n return this.request<T>(\n {\n url,\n method: 'GET',\n headers: opts.headers,\n signal: opts.signal,\n rateLimit: opts.rateLimit,\n },\n { resource: opts.resource, requestId: opts.requestId },\n );\n }\n\n protected post<T = unknown>(\n url: string,\n opts: ConnectorRequestOptions & {\n body?: HttpRequest['body'];\n headers?: Record<string, string>;\n signal?: AbortSignal;\n rateLimit?: HttpRequest['rateLimit'];\n },\n ): Promise<HttpResponse<T>> {\n return this.request<T>(\n {\n url,\n method: 'POST',\n headers: opts.headers,\n body: opts.body,\n signal: opts.signal,\n rateLimit: opts.rateLimit,\n },\n { resource: opts.resource, requestId: opts.requestId },\n );\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?: RetryPolicy,\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 options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<SyncResult>;\n}\n\nexport function defineConnector<TSettings>() {\n return function <\n TCreds extends CredentialsSchema = Record<string, never>,\n >(def: {\n id: string;\n credentials?: TCreds;\n sync: (\n this: { settings: TSettings; creds: InferCredentials<TCreds> },\n options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ) => Promise<SyncResult>;\n }): {\n new (\n settings: TSettings,\n creds?: InferCredentialInput<TCreds>,\n ctx?: ConnectorContext,\n ): 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 options: SyncOptions,\n storage: StorageHandle,\n signal?: AbortSignal,\n ): Promise<SyncResult> {\n return def.sync.call(\n { settings: this.settings, creds: this.creds },\n options,\n storage,\n signal,\n );\n }\n }\n\n return DynamicConnector as unknown as {\n new (\n settings: TSettings,\n creds?: InferCredentialInput<TCreds>,\n ctx?: ConnectorContext,\n ): Connector;\n readonly id: string;\n readonly credentials: TCreds | undefined;\n };\n };\n}\n","import type { SyncResult } from './connector';\n\nexport interface ChunkedSyncCursor<TPhase extends string, TPage> {\n phase: TPhase;\n page: TPage | null;\n}\n\nexport interface FetchPageResult<TPage> {\n items: unknown[];\n next: TPage | null;\n}\n\nexport interface ChunkedSyncOptions<TPhase extends string, TPage> {\n phases: readonly TPhase[];\n cursor: ChunkedSyncCursor<TPhase, TPage> | undefined;\n signal: AbortSignal | undefined;\n fetchPage: (\n phase: TPhase,\n page: TPage | null,\n signal: AbortSignal | undefined,\n ) => Promise<FetchPageResult<TPage>>;\n writeBatch: (\n phase: TPhase,\n items: unknown[],\n page: TPage | null,\n ) => Promise<void>;\n}\n\nexport async function paginateChunked<TPhase extends string, TPage>(\n opts: ChunkedSyncOptions<TPhase, TPage>,\n): Promise<SyncResult> {\n const { phases, cursor, signal, fetchPage, writeBatch } = opts;\n\n if (phases.length === 0) {\n return { done: true };\n }\n\n const resumeIdx = cursor ? phases.indexOf(cursor.phase) : -1;\n const hasKnownResumePhase = resumeIdx >= 0;\n const startIdx = hasKnownResumePhase ? resumeIdx : 0;\n\n for (let i = startIdx; i < phases.length; i++) {\n const phase = phases[i]!;\n let page: TPage | null =\n i === startIdx && hasKnownResumePhase ? cursor!.page : null;\n\n while (true) {\n if (signal?.aborted) {\n return {\n done: false,\n cursor: { phase, page } satisfies ChunkedSyncCursor<TPhase, TPage>,\n };\n }\n let items: unknown[];\n let next: TPage | null;\n try {\n ({ items, next } = await fetchPage(phase, page, signal));\n } catch (err) {\n if (\n signal?.aborted ||\n (err instanceof Error && err.name === 'AbortError')\n ) {\n return {\n done: false,\n cursor: { phase, page } satisfies ChunkedSyncCursor<TPhase, TPage>,\n };\n }\n return {\n done: false,\n cursor: { phase, page } satisfies ChunkedSyncCursor<TPhase, TPage>,\n transientError: err,\n };\n }\n try {\n await writeBatch(phase, items, page);\n } catch (err) {\n if (\n signal?.aborted ||\n (err instanceof Error && err.name === 'AbortError')\n ) {\n return {\n done: false,\n cursor: { phase, page } satisfies ChunkedSyncCursor<TPhase, TPage>,\n };\n }\n return {\n done: false,\n cursor: { phase, page } satisfies ChunkedSyncCursor<TPhase, TPage>,\n transientError: err,\n };\n }\n if (next === null) {\n break;\n }\n page = next;\n }\n }\n\n return { done: true };\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 computedMetricSchema = 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: computedMetricSchema.meta({\n label: 'Metric',\n description: 'Computed 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: computedMetricSchema.meta({\n label: 'Metric',\n description: 'Computed 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: computedMetricSchema.meta({\n label: 'Metric',\n description: 'Computed 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 { 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\n// ---------------------------------------------------------------------------\n\nexport interface Metric {\n connector: { name: 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 ComputedMetric {\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: ComputedMetric;\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: ComputedMetric;\n window: string;\n granularity?: 'hour' | 'day' | 'week';\n}\n\nexport interface DistributionWidget {\n kind: 'distribution';\n title: string;\n metric: ComputedMetric;\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 ConfiguredConnector {\n name: string;\n connectorId: string;\n config: Record<string, unknown>;\n syncIntervalSeconds?: number;\n enabled?: boolean;\n displayName?: string;\n}\n\nexport interface Dashboard {\n widgets: Record<string, Widget>;\n}\n\nexport interface DashboardConfig {\n connectors: ConfiguredConnector[];\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: Metric): ComputedMetric {\n return {\n connectorId: options.connector.name,\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 if (!Array.isArray(config.connectors)) {\n throw new Error('defineConfig: \"connectors\" must be an array');\n }\n\n const connectorNames = new Set<string>();\n for (const entry of config.connectors) {\n if (!entry || typeof entry !== 'object') {\n throw new Error(\n 'defineConfig: every connector entry must be an object with \"name\", \"connectorId\", and \"config\"',\n );\n }\n if (!entry.name) {\n throw new Error('defineConfig: every connector entry must have a \"name\"');\n }\n if (!entry.connectorId) {\n throw new Error(\n `defineConfig: connector \"${entry.name}\" must have a \"connectorId\" (the connector type id)`,\n );\n }\n if (\n entry.config === null ||\n typeof entry.config !== 'object' ||\n Array.isArray(entry.config)\n ) {\n throw new Error(\n `defineConfig: connector \"${entry.name}\" must have a \"config\" object`,\n );\n }\n if (connectorNames.has(entry.name)) {\n throw new Error(\n `defineConfig: duplicate connector name \"${entry.name}\". Each instance must have a unique name.`,\n );\n }\n connectorNames.add(entry.name);\n }\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 (!connectorNames.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","export type SyncStatus = 'idle' | 'queued' | 'running' | 'succeeded' | 'failed';\n\nexport interface SyncState {\n status: SyncStatus;\n queuedAt: string | null;\n startedAt: string | null;\n lastSyncAt: string | null;\n lastError: string | null;\n}\n\nexport const ACTIVE_SYNC_STATUSES: ReadonlySet<SyncStatus> = new Set([\n 'queued',\n 'running',\n]);\n\nexport function isSyncActive(status: SyncStatus): boolean {\n return ACTIVE_SYNC_STATUSES.has(status);\n}\n","import type {\n Distribution,\n Event,\n MetricSample,\n StorageHandle,\n} 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// RetentionDeletionPlan — rows eligible for deletion across time-series shapes\n// ---------------------------------------------------------------------------\n\nexport interface RetentionDeletionPlan {\n events: Event[];\n metrics: MetricSample[];\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<RetentionDeletionPlan> {\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 { ComputedMetric } from './config';\nimport type { StorageHandle } from './connector';\n\ntype FilterClause = NonNullable<ComputedMetric['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: ComputedMetric['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: ComputedMetric,\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: ComputedMetric,\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 { Widget } from './config';\nimport type { ConnectorHealth } from './connector';\nimport type { ServerStorage } from './server-storage';\nimport type { CachedWidget, WidgetSyncState } from './wire';\n\nconst FAILING_CONNECTOR_STATUSES: ReadonlySet<ConnectorHealth['status']> =\n new Set(['error', 'auth_failed', 'paused']);\n\nfunction deriveSyncStateFromHealth(health: ConnectorHealth): WidgetSyncState {\n if (health.status === 'syncing') {\n return 'syncing';\n }\n if (FAILING_CONNECTOR_STATUSES.has(health.status)) {\n return 'failing';\n }\n if (!health.lastSyncAt) {\n return 'unsynced';\n }\n const ageMs = Date.now() - new Date(health.lastSyncAt).getTime();\n const windowMs = 2 * health.syncIntervalSeconds * 1000;\n return ageMs <= windowMs ? 'fresh' : 'stale';\n}\n\nfunction buildMetaFromHealth(health: ConnectorHealth): Record<string, unknown> {\n const meta: Record<string, unknown> = { connectorStatus: health.status };\n if (health.lastError) {\n meta['lastError'] = health.lastError;\n }\n return meta;\n}\n\nexport async function resolveWidget(\n widgetId: string,\n widget: Widget,\n connectors: readonly string[] | undefined,\n storage: ServerStorage,\n): Promise<CachedWidget | undefined> {\n const connectorId =\n widget.kind === 'status' ? widget.source : widget.metric.connectorId;\n if (connectors !== undefined && !connectors.includes(connectorId)) {\n return undefined;\n }\n const handle = storage.getStorageHandle(connectorId);\n const health = (await handle.getHealth?.()) ?? null;\n const data =\n widget.kind === 'status'\n ? null\n : await computeMetric(handle, widget.metric);\n\n let syncState: WidgetSyncState | undefined;\n let meta: Record<string, unknown> | undefined;\n if (health) {\n syncState = deriveSyncStateFromHealth(health);\n meta = buildMetaFromHealth(health);\n } else if (data === null || data === undefined) {\n syncState = 'unsynced';\n } else {\n syncState = 'fresh';\n }\n\n return {\n widgetId,\n connectorId,\n data,\n cachedAt: health?.lastSyncAt ?? null,\n syncState,\n meta,\n };\n}\n","import type { z } from 'zod';\n\nimport type { ConfiguredConnector } from './config';\nimport type {\n Connector,\n ConnectorContext,\n CredentialsSchema,\n} from './connector';\nimport type { SecretsResolver } from './secrets';\n\n/**\n * Map of resource name → Zod schema describing the raw API response shape\n * for that resource. Resource names must match the `resource` tag passed to\n * `request()` (see {@link BaseConnector.request}) so the shape-drift pipeline\n * can correlate observations with their declared shape.\n *\n * Consumed by:\n * - the cloud baseline generator, which walks this map at deploy time to\n * populate `connector_baselines`\n * - property tests in `@rawdash/connector-test-utils`, which fuzz against\n * each schema\n *\n * See `docs/authoring-a-connector.md` for the authoring guide.\n */\nexport type ConnectorSchemas = Readonly<Record<string, z.ZodType>>;\n\n/**\n * Compile-time contract every connector class must satisfy. Declaring\n * `static schemas` is mandatory — without it, the connector cannot be added\n * to a {@link ConnectorRegistry} and TypeScript will fail the build.\n */\nexport type ConnectorClass = {\n new (settings: never, creds?: never, ctx?: ConnectorContext): Connector;\n readonly credentials?: CredentialsSchema;\n readonly schemas: ConnectorSchemas;\n};\n\nexport type ConnectorRegistry = Record<string, ConnectorClass>;\n\nexport function instantiateConnector(\n entry: ConfiguredConnector,\n registry: ConnectorRegistry,\n secretsResolver?: SecretsResolver,\n): Connector {\n const Cls = registry[entry.connectorId];\n if (!Cls) {\n throw new Error(\n `Unknown connector type \"${entry.connectorId}\" for instance \"${entry.name}\". ` +\n `Add it to the connectorRegistry.`,\n );\n }\n const credSchema = Cls.credentials;\n const settings: Record<string, unknown> = {};\n const creds: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(entry.config)) {\n if (credSchema && Object.prototype.hasOwnProperty.call(credSchema, key)) {\n creds[key] = value;\n } else {\n settings[key] = value;\n }\n }\n return new Cls(settings as never, (credSchema ? creds : undefined) as never, {\n secretsResolver,\n });\n}\n","import type { StorageHandle } from './connector';\n\nexport function withAbortSignal(\n handle: StorageHandle,\n signal: AbortSignal,\n): StorageHandle {\n let warned = false;\n const warnOnce = (method: string): void => {\n if (warned) {\n return;\n }\n warned = true;\n console.warn(\n `[rawdash storage] dropping post-abort write '${method}' — connector continued writing after AbortSignal fired`,\n );\n };\n\n return {\n event: async (e) => {\n if (signal.aborted) {\n warnOnce('event');\n return;\n }\n await handle.event(e);\n },\n entity: async (e) => {\n if (signal.aborted) {\n warnOnce('entity');\n return;\n }\n await handle.entity(e);\n },\n metric: async (m) => {\n if (signal.aborted) {\n warnOnce('metric');\n return;\n }\n await handle.metric(m);\n },\n edge: async (e) => {\n if (signal.aborted) {\n warnOnce('edge');\n return;\n }\n await handle.edge(e);\n },\n distribution: async (d) => {\n if (signal.aborted) {\n warnOnce('distribution');\n return;\n }\n await handle.distribution(d);\n },\n events: async (es, scope) => {\n if (signal.aborted) {\n warnOnce('events');\n return;\n }\n await handle.events(es, scope);\n },\n entities: async (es, scope) => {\n if (signal.aborted) {\n warnOnce('entities');\n return;\n }\n await handle.entities(es, scope);\n },\n metrics: async (ms, scope) => {\n if (signal.aborted) {\n warnOnce('metrics');\n return;\n }\n await handle.metrics(ms, scope);\n },\n edges: async (es, scope) => {\n if (signal.aborted) {\n warnOnce('edges');\n return;\n }\n await handle.edges(es, scope);\n },\n distributions: async (ds, scope) => {\n if (signal.aborted) {\n warnOnce('distributions');\n return;\n }\n await handle.distributions(ds, scope);\n },\n deleteOlderThan: async (shape, tsUnixMs) => {\n if (signal.aborted) {\n warnOnce('deleteOlderThan');\n return { rowsDeleted: 0 };\n }\n return handle.deleteOlderThan(shape, tsUnixMs);\n },\n queryEvents: (q) => handle.queryEvents(q),\n getEntity: (type, id) => handle.getEntity(type, id),\n queryEntities: (q) => handle.queryEntities(q),\n queryMetrics: (q) => handle.queryMetrics(q),\n traverse: (q) => handle.traverse(q),\n queryDistributions: (q) => handle.queryDistributions(q),\n ...(handle.getHealth ? { getHealth: handle.getHealth.bind(handle) } : {}),\n };\n}\n","import type {\n ConnectorHealth,\n Distribution,\n DistributionQuery,\n Edge,\n EdgeQuery,\n Entity,\n EntityQuery,\n Event,\n EventQuery,\n MetricQuery,\n MetricSample,\n StorageHandle,\n} from './connector';\nimport type { SyncState } from './engine';\nimport type { GetStorageHandleOptions, ServerStorage } from './server-storage';\nimport { withAbortSignal } from './storage-handle-guard';\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, MetricSample[]>();\n private edgeStore = new Map<string, Edge[]>();\n private distributionStore = new Map<string, Distribution[]>();\n private lastWriteAt = new Map<string, string>();\n private syncState: SyncState = {\n status: 'idle',\n queuedAt: null,\n startedAt: null,\n lastSyncAt: null,\n lastError: null,\n };\n\n getStorageHandle(\n connectorId: string,\n options?: GetStorageHandleOptions,\n ): StorageHandle {\n const handle = this.buildHandle(connectorId);\n return options?.signal ? withAbortSignal(handle, options.signal) : handle;\n }\n\n private buildHandle(connectorId: string): StorageHandle {\n const touch = (): void => {\n this.lastWriteAt.set(connectorId, new Date().toISOString());\n };\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 touch();\n },\n\n entity: async (e) => {\n upsertEntities([e]);\n touch();\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 touch();\n },\n\n edge: async (e) => {\n upsertEdges([e]);\n touch();\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 touch();\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 touch();\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 touch();\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 touch();\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 touch();\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 touch();\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 getHealth: async (): Promise<ConnectorHealth> => {\n return {\n status: 'idle',\n lastSyncAt: this.lastWriteAt.get(connectorId) ?? null,\n lastError: null,\n syncIntervalSeconds: 0,\n };\n },\n };\n }\n\n async getSyncState(): Promise<SyncState> {\n return { ...this.syncState };\n }\n\n async markSyncQueued(): Promise<boolean> {\n if (\n this.syncState.status === 'queued' ||\n this.syncState.status === 'running'\n ) {\n return false;\n }\n this.syncState = {\n ...this.syncState,\n status: 'queued',\n queuedAt: new Date().toISOString(),\n startedAt: null,\n };\n return true;\n }\n\n async markSyncRunning(): Promise<boolean> {\n if (this.syncState.status !== 'queued') {\n return false;\n }\n this.syncState = {\n ...this.syncState,\n status: 'running',\n startedAt: new Date().toISOString(),\n };\n return true;\n }\n\n async markSyncSucceeded(): Promise<void> {\n const now = new Date().toISOString();\n this.syncState = {\n status: 'succeeded',\n queuedAt: null,\n startedAt: null,\n lastSyncAt: now,\n lastError: null,\n };\n }\n\n async markSyncFailed(error: string): Promise<void> {\n this.syncState = {\n ...this.syncState,\n status: 'failed',\n queuedAt: null,\n startedAt: null,\n lastError: error,\n };\n }\n}\n","import { z } from 'zod';\n\nimport type { DashboardConfig } from './config';\n\nexport const wireConnectorSchema = z.object({\n name: z.string(),\n connectorId: z.string(),\n displayName: z.string().optional(),\n config: z.record(z.string(), z.unknown()),\n syncIntervalSeconds: z.number().optional(),\n enabled: z.boolean().optional(),\n});\n\nexport const wireDashboardSchema = z.object({\n id: z.string().optional(),\n name: z.string(),\n slug: z.string(),\n config: z.record(z.string(), z.unknown()),\n});\n\nexport const wireConfigSchema = z.object({\n connectors: z.array(wireConnectorSchema).optional(),\n dashboards: z.array(wireDashboardSchema).optional(),\n});\n\nexport type WireConnector = z.infer<typeof wireConnectorSchema>;\nexport type WireDashboard = z.infer<typeof wireDashboardSchema>;\nexport type WireConfig = z.infer<typeof wireConfigSchema>;\n\nexport function toWireConfig(config: DashboardConfig): WireConfig {\n return {\n connectors: config.connectors.map((entry) => ({\n name: entry.name,\n connectorId: entry.connectorId,\n displayName: entry.displayName ?? entry.name,\n config: entry.config,\n syncIntervalSeconds: entry.syncIntervalSeconds ?? 300,\n enabled: entry.enabled ?? true,\n })),\n dashboards: Object.entries(config.dashboards).map(([id, dash]) => ({\n id,\n name: id,\n slug: id,\n config: { widgets: dash.widgets },\n })),\n };\n}\n"],"mappings":"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","names":["err","z","z"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rawdash/core",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "Rawdash core — headless dashboard backend primitives",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",