@rawdash/adapter-libsql 0.28.0 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Client } from '@libsql/client/web';
2
- import { ServerStorage, GetStorageHandleOptions, StorageHandle, ConnectorHealth, SyncState } from '@rawdash/core';
2
+ import { ServerStorage, GetStorageHandleOptions, StorageHandle, ConnectorHealth, SyncState, SyncSchedulingState, MarkConnectorSyncSucceededOptions } from '@rawdash/core';
3
3
 
4
4
  declare function initLibsqlSchema(client: Client): Promise<void>;
5
5
  interface LibsqlStorageOptions {
@@ -18,9 +18,11 @@ declare class LibsqlStorage implements ServerStorage {
18
18
  private buildHandle;
19
19
  getHealth(_connectorId: string): Promise<ConnectorHealth | null>;
20
20
  getSyncState(): Promise<SyncState>;
21
+ getConnectorSyncState(connectorId: string): Promise<SyncSchedulingState>;
21
22
  markSyncQueued(): Promise<boolean>;
22
23
  markSyncRunning(): Promise<boolean>;
23
24
  markSyncSucceeded(): Promise<void>;
25
+ markConnectorSyncSucceeded(connectorId: string, options?: MarkConnectorSyncSucceededOptions): Promise<void>;
24
26
  markSyncFailed(error: string): Promise<void>;
25
27
  close(): Promise<void>;
26
28
  }
package/dist/index.js CHANGED
@@ -45,12 +45,24 @@ var MIGRATIONS = [
45
45
  "CREATE TABLE `rollups` (\n `connector_id` text NOT NULL,\n `resource` text NOT NULL,\n `field` text DEFAULT '' NOT NULL,\n `granularity` text NOT NULL,\n `dims_key` text DEFAULT '' NOT NULL,\n `dims` text DEFAULT '{}' NOT NULL,\n `bucket_start` integer NOT NULL,\n `partials` text NOT NULL,\n PRIMARY KEY(`connector_id`, `resource`, `field`, `granularity`, `dims_key`, `bucket_start`)\n);",
46
46
  "CREATE INDEX `rollups_conn_resource_field` ON `rollups` (`connector_id`,`resource`,`field`);"
47
47
  ]
48
+ },
49
+ {
50
+ tag: "0004_neat_swarm",
51
+ statements: [
52
+ "CREATE TABLE `connector_sync_state` (\n `connector_id` text PRIMARY KEY NOT NULL,\n `last_sync_at` text,\n `last_backfill_at` text\n);"
53
+ ]
48
54
  }
49
55
  ];
50
56
 
51
57
  // src/migrate.ts
52
58
  var SCHEMA_MIGRATIONS_TABLE = "schema_migrations";
53
59
  var LEGACY_BASELINE_TABLE = "events";
60
+ var LEGACY_BASELINE_TAGS = /* @__PURE__ */ new Set([
61
+ "0000_nosy_wendell_vaughn",
62
+ "0001_clumsy_siren",
63
+ "0002_milky_echo",
64
+ "0003_milky_morbius"
65
+ ]);
54
66
  async function tableExists(client, name) {
55
67
  const result = await client.execute({
56
68
  sql: "SELECT name FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1",
@@ -94,12 +106,14 @@ async function applyMigrations(client, opts = {}) {
94
106
  if (hasLegacySchema) {
95
107
  const now = Date.now();
96
108
  for (const migration of MIGRATIONS) {
109
+ if (!LEGACY_BASELINE_TAGS.has(migration.tag)) {
110
+ continue;
111
+ }
97
112
  await client.execute({
98
113
  sql: `INSERT OR IGNORE INTO ${SCHEMA_MIGRATIONS_TABLE} (tag, applied_at) VALUES (?, ?)`,
99
114
  args: [migration.tag, now]
100
115
  });
101
116
  }
102
- return;
103
117
  }
104
118
  }
105
119
  let applied = await readAppliedTags(client);
@@ -327,13 +341,14 @@ var LibsqlStorage = class {
327
341
  const names = Array.from(
328
342
  new Set(scope?.names ?? ms.map((m) => m.name))
329
343
  );
344
+ const window = scope?.replaceWindow;
330
345
  const stmts = [];
331
346
  if (names.length > 0) {
332
- stmts.push(
333
- toBatchStmt(
334
- db.deleteFrom("metrics").where("connector_id", "=", connectorId).where("name", "in", names).compile()
335
- )
336
- );
347
+ let del = db.deleteFrom("metrics").where("connector_id", "=", connectorId).where("name", "in", names);
348
+ if (window) {
349
+ del = del.where("ts", ">=", window.start).where("ts", "<=", window.end);
350
+ }
351
+ stmts.push(toBatchStmt(del.compile()));
337
352
  }
338
353
  if (ms.length > 0) {
339
354
  stmts.push(
@@ -387,13 +402,14 @@ var LibsqlStorage = class {
387
402
  const names = Array.from(
388
403
  new Set(scope?.names ?? ds.map((d) => d.name))
389
404
  );
405
+ const window = scope?.replaceWindow;
390
406
  const stmts = [];
391
407
  if (names.length > 0) {
392
- stmts.push(
393
- toBatchStmt(
394
- db.deleteFrom("distributions").where("connector_id", "=", connectorId).where("name", "in", names).compile()
395
- )
396
- );
408
+ let del = db.deleteFrom("distributions").where("connector_id", "=", connectorId).where("name", "in", names);
409
+ if (window) {
410
+ del = del.where("ts", ">=", window.start).where("ts", "<=", window.end);
411
+ }
412
+ stmts.push(toBatchStmt(del.compile()));
397
413
  }
398
414
  if (ds.length > 0) {
399
415
  stmts.push(
@@ -696,6 +712,17 @@ var LibsqlStorage = class {
696
712
  lastError: r.last_error
697
713
  };
698
714
  }
715
+ async getConnectorSyncState(connectorId) {
716
+ if (this.initError !== null) {
717
+ return { lastSyncAt: null, lastBackfillAt: null };
718
+ }
719
+ await this.ready;
720
+ const r = await this.db.selectFrom("connector_sync_state").select(["last_sync_at", "last_backfill_at"]).where("connector_id", "=", connectorId).limit(1).executeTakeFirst();
721
+ return {
722
+ lastSyncAt: r?.last_sync_at ?? null,
723
+ lastBackfillAt: r?.last_backfill_at ?? null
724
+ };
725
+ }
699
726
  async markSyncQueued() {
700
727
  await this.ready;
701
728
  const r = await this.db.updateTable("sync_state").set({
@@ -720,6 +747,20 @@ var LibsqlStorage = class {
720
747
  last_error: null
721
748
  }).where("id", "=", SYNC_STATE_ID).execute();
722
749
  }
750
+ async markConnectorSyncSucceeded(connectorId, options) {
751
+ await this.ready;
752
+ const now = (/* @__PURE__ */ new Date()).toISOString();
753
+ await this.db.insertInto("connector_sync_state").values({
754
+ connector_id: connectorId,
755
+ last_sync_at: now,
756
+ last_backfill_at: options?.backfillDue ? now : null
757
+ }).onConflict(
758
+ (oc) => oc.column("connector_id").doUpdateSet({
759
+ last_sync_at: now,
760
+ ...options?.backfillDue ? { last_backfill_at: now } : {}
761
+ })
762
+ ).execute();
763
+ }
723
764
  async markSyncFailed(error) {
724
765
  await this.ready;
725
766
  await this.db.updateTable("sync_state").set({
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/libsql-storage.ts","../src/migrations-bundle.ts","../src/migrate.ts"],"sourcesContent":["import type { Client, InValue } from '@libsql/client/web';\nimport type {\n ConnectorHealth,\n Distribution,\n DistributionQuery,\n Edge,\n EdgeQuery,\n Entity,\n EntityQuery,\n Event,\n EventQuery,\n GetStorageHandleOptions,\n Granularity,\n JSONValue,\n MetricQuery,\n MetricSample,\n RollupBucket,\n RollupPartials,\n RollupQuery,\n ServerStorage,\n StorageHandle,\n SyncState,\n} from '@rawdash/core';\nimport {\n dimsKey,\n healthStatusFromSyncStatus,\n withAbortSignal,\n} from '@rawdash/core';\nimport { type CompiledQuery, type Insertable, Kysely, sql } from 'kysely';\nimport { LibsqlDialect } from 'kysely-libsql';\n\nimport type {\n Database,\n EdgesTable,\n EntitiesTable,\n EventsTable,\n MetricsTable,\n RollupsTable,\n} from './db-schema';\nimport { applyMigrations } from './migrate';\n\ntype Attrs = Record<string, JSONValue>;\n\nconst SYNC_STATE_ID = 1;\n\nexport async function initLibsqlSchema(client: Client): Promise<void> {\n await applyMigrations(client, { assumeLegacyBaselineIfEventsExists: true });\n await client.execute({\n sql: \"INSERT OR IGNORE INTO sync_state (id, status, queued_at, started_at, last_sync_at, last_error) VALUES (?, 'idle', NULL, NULL, NULL, NULL)\",\n args: [SYNC_STATE_ID],\n });\n}\n\nfunction parseJson<T>(value: unknown, fallback: T): T {\n if (typeof value !== 'string') {\n return fallback;\n }\n try {\n return JSON.parse(value) as T;\n } catch {\n return fallback;\n }\n}\n\nfunction createDb(client: Client): Kysely<Database> {\n return new Kysely<Database>({\n dialect: new LibsqlDialect({ client }),\n });\n}\n\nfunction toBatchStmt(q: CompiledQuery): { sql: string; args: InValue[] } {\n return { sql: q.sql, args: q.parameters as InValue[] };\n}\n\nexport interface LibsqlStorageOptions {\n client: Client;\n initSchema?: boolean;\n}\n\nexport class LibsqlStorage implements ServerStorage {\n private client: Client;\n private db: Kysely<Database>;\n private ready: Promise<void>;\n private initError: string | null = null;\n\n constructor(options: LibsqlStorageOptions) {\n this.client = options.client;\n this.db = createDb(options.client);\n this.ready = options.initSchema === false ? Promise.resolve() : this.init();\n }\n\n private async init(): Promise<void> {\n try {\n await initLibsqlSchema(this.client);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n this.initError = `init failed: ${message}`;\n throw err;\n }\n }\n\n async waitUntilReady(): Promise<void> {\n return this.ready;\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 ready = this.ready;\n const db = this.db;\n const client = this.client;\n\n const eventRow = (e: Event): Insertable<EventsTable> => ({\n connector_id: connectorId,\n name: e.name,\n start_ts: e.start_ts,\n end_ts: e.end_ts,\n attributes: JSON.stringify(e.attributes),\n });\n\n const entityRow = (e: Entity): Insertable<EntitiesTable> => ({\n connector_id: connectorId,\n type: e.type,\n id: e.id,\n attributes: JSON.stringify(e.attributes),\n updated_at: e.updated_at,\n });\n\n const metricRow = (m: MetricSample): Insertable<MetricsTable> => ({\n connector_id: connectorId,\n name: m.name,\n ts: m.ts,\n value: m.value,\n attributes: JSON.stringify(m.attributes),\n });\n\n const edgeRow = (e: Edge): Insertable<EdgesTable> => ({\n connector_id: connectorId,\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 attributes: JSON.stringify(e.attributes),\n updated_at: e.updated_at,\n });\n\n const distributionRow = (d: Distribution) => ({\n connector_id: connectorId,\n name: d.name,\n ts: d.ts,\n kind: d.kind,\n data: JSON.stringify(d.data),\n attributes: JSON.stringify(d.attributes),\n });\n\n const rollupRow = (b: RollupBucket): Insertable<RollupsTable> => ({\n connector_id: connectorId,\n resource: b.resource,\n field: b.field,\n granularity: b.granularity,\n dims_key: dimsKey(b.dims),\n dims: JSON.stringify(b.dims),\n bucket_start: b.bucketStart,\n partials: JSON.stringify(b.partials),\n });\n\n return {\n event: async (e) => {\n await ready;\n await db.insertInto('events').values(eventRow(e)).execute();\n },\n\n entity: async (e) => {\n await ready;\n await db\n .insertInto('entities')\n .values(entityRow(e))\n .onConflict((oc) =>\n oc.columns(['connector_id', 'type', 'id']).doUpdateSet({\n attributes: (eb) => eb.ref('excluded.attributes'),\n updated_at: (eb) => eb.ref('excluded.updated_at'),\n }),\n )\n .execute();\n },\n\n metric: async (m) => {\n await ready;\n await db.insertInto('metrics').values(metricRow(m)).execute();\n },\n\n edge: async (e) => {\n await ready;\n await db\n .insertInto('edges')\n .values(edgeRow(e))\n .onConflict((oc) =>\n oc\n .columns([\n 'connector_id',\n 'from_type',\n 'from_id',\n 'kind',\n 'to_type',\n 'to_id',\n ])\n .doUpdateSet({\n attributes: (eb) => eb.ref('excluded.attributes'),\n updated_at: (eb) => eb.ref('excluded.updated_at'),\n }),\n )\n .execute();\n },\n\n distribution: async (d) => {\n await ready;\n await db\n .insertInto('distributions')\n .values(distributionRow(d))\n .execute();\n },\n\n events: async (es, scope) => {\n await ready;\n const names = Array.from(\n new Set(scope?.names ?? es.map((e) => e.name)),\n );\n const stmts: { sql: string; args: InValue[] }[] = [];\n if (names.length > 0) {\n stmts.push(\n toBatchStmt(\n db\n .deleteFrom('events')\n .where('connector_id', '=', connectorId)\n .where('name', 'in', names)\n .compile(),\n ),\n );\n }\n if (es.length > 0) {\n stmts.push(\n toBatchStmt(\n db.insertInto('events').values(es.map(eventRow)).compile(),\n ),\n );\n }\n if (stmts.length > 0) {\n await client.batch(stmts, 'write');\n }\n },\n\n entities: async (es, scope) => {\n await ready;\n const types = Array.from(\n new Set(scope?.types ?? es.map((e) => e.type)),\n );\n const stmts: { sql: string; args: InValue[] }[] = [];\n if (types.length > 0) {\n stmts.push(\n toBatchStmt(\n db\n .deleteFrom('entities')\n .where('connector_id', '=', connectorId)\n .where('type', 'in', types)\n .compile(),\n ),\n );\n }\n if (es.length > 0) {\n stmts.push(\n toBatchStmt(\n db\n .insertInto('entities')\n .values(es.map(entityRow))\n .onConflict((oc) =>\n oc.columns(['connector_id', 'type', 'id']).doUpdateSet({\n attributes: (eb) => eb.ref('excluded.attributes'),\n updated_at: (eb) => eb.ref('excluded.updated_at'),\n }),\n )\n .compile(),\n ),\n );\n }\n if (stmts.length > 0) {\n await client.batch(stmts, 'write');\n }\n },\n\n metrics: async (ms, scope) => {\n await ready;\n const names = Array.from(\n new Set(scope?.names ?? ms.map((m) => m.name)),\n );\n const stmts: { sql: string; args: InValue[] }[] = [];\n if (names.length > 0) {\n stmts.push(\n toBatchStmt(\n db\n .deleteFrom('metrics')\n .where('connector_id', '=', connectorId)\n .where('name', 'in', names)\n .compile(),\n ),\n );\n }\n if (ms.length > 0) {\n stmts.push(\n toBatchStmt(\n db.insertInto('metrics').values(ms.map(metricRow)).compile(),\n ),\n );\n }\n if (stmts.length > 0) {\n await client.batch(stmts, 'write');\n }\n },\n\n edges: async (es, scope) => {\n await ready;\n const kinds = Array.from(\n new Set(scope?.kinds ?? es.map((e) => e.kind)),\n );\n const stmts: { sql: string; args: InValue[] }[] = [];\n if (kinds.length > 0) {\n stmts.push(\n toBatchStmt(\n db\n .deleteFrom('edges')\n .where('connector_id', '=', connectorId)\n .where('kind', 'in', kinds)\n .compile(),\n ),\n );\n }\n if (es.length > 0) {\n stmts.push(\n toBatchStmt(\n db\n .insertInto('edges')\n .values(es.map(edgeRow))\n .onConflict((oc) =>\n oc\n .columns([\n 'connector_id',\n 'from_type',\n 'from_id',\n 'kind',\n 'to_type',\n 'to_id',\n ])\n .doUpdateSet({\n attributes: (eb) => eb.ref('excluded.attributes'),\n updated_at: (eb) => eb.ref('excluded.updated_at'),\n }),\n )\n .compile(),\n ),\n );\n }\n if (stmts.length > 0) {\n await client.batch(stmts, 'write');\n }\n },\n\n distributions: async (ds, scope) => {\n await ready;\n const names = Array.from(\n new Set(scope?.names ?? ds.map((d) => d.name)),\n );\n const stmts: { sql: string; args: InValue[] }[] = [];\n if (names.length > 0) {\n stmts.push(\n toBatchStmt(\n db\n .deleteFrom('distributions')\n .where('connector_id', '=', connectorId)\n .where('name', 'in', names)\n .compile(),\n ),\n );\n }\n if (ds.length > 0) {\n stmts.push(\n toBatchStmt(\n db\n .insertInto('distributions')\n .values(ds.map(distributionRow))\n .compile(),\n ),\n );\n }\n if (stmts.length > 0) {\n await client.batch(stmts, 'write');\n }\n },\n\n queryEvents: async (q: EventQuery) => {\n await ready;\n let qb = db\n .selectFrom('events')\n .select(['name', 'start_ts', 'end_ts', 'attributes'])\n .where('connector_id', '=', connectorId);\n if (q.name !== undefined) {\n qb = qb.where('name', '=', q.name);\n }\n if (q.start !== undefined) {\n qb = qb.where('start_ts', '>=', q.start);\n }\n if (q.end !== undefined) {\n qb = qb.where('start_ts', '<=', q.end);\n }\n const rows = await qb.execute();\n return rows.map(\n (r): Event => ({\n name: r.name,\n start_ts: Number(r.start_ts),\n end_ts: r.end_ts === null ? null : Number(r.end_ts),\n attributes: parseJson<Attrs>(r.attributes, {}),\n }),\n );\n },\n\n getEntity: async (type, id) => {\n await ready;\n const r = await db\n .selectFrom('entities')\n .select(['type', 'id', 'attributes', 'updated_at'])\n .where('connector_id', '=', connectorId)\n .where('type', '=', type)\n .where('id', '=', id)\n .limit(1)\n .executeTakeFirst();\n if (!r) {\n return null;\n }\n return {\n type: r.type,\n id: r.id,\n attributes: parseJson<Attrs>(r.attributes, {}),\n updated_at: Number(r.updated_at),\n };\n },\n\n queryEntities: async (q: EntityQuery) => {\n await ready;\n const rows = await db\n .selectFrom('entities')\n .select(['type', 'id', 'attributes', 'updated_at'])\n .where('connector_id', '=', connectorId)\n .where('type', '=', q.type)\n .execute();\n return rows.map(\n (r): Entity => ({\n type: r.type,\n id: r.id,\n attributes: parseJson<Attrs>(r.attributes, {}),\n updated_at: Number(r.updated_at),\n }),\n );\n },\n\n queryMetrics: async (q: MetricQuery) => {\n await ready;\n let qb = db\n .selectFrom('metrics')\n .select(['name', 'ts', 'value', 'attributes'])\n .where('connector_id', '=', connectorId);\n if (q.name !== undefined) {\n qb = qb.where('name', '=', q.name);\n }\n if (q.start !== undefined) {\n qb = qb.where('ts', '>=', q.start);\n }\n if (q.end !== undefined) {\n qb = qb.where('ts', '<=', q.end);\n }\n const rows = await qb.execute();\n return rows.map(\n (r): MetricSample => ({\n name: r.name,\n ts: Number(r.ts),\n value: Number(r.value),\n attributes: parseJson<Attrs>(r.attributes, {}),\n }),\n );\n },\n\n traverse: async (q: EdgeQuery) => {\n await ready;\n let qb = db\n .selectFrom('edges')\n .select([\n 'from_type',\n 'from_id',\n 'kind',\n 'to_type',\n 'to_id',\n 'attributes',\n 'updated_at',\n ])\n .where('connector_id', '=', connectorId);\n if (q.fromType !== undefined) {\n qb = qb.where('from_type', '=', q.fromType);\n }\n if (q.fromId !== undefined) {\n qb = qb.where('from_id', '=', q.fromId);\n }\n if (q.kind !== undefined) {\n qb = qb.where('kind', '=', q.kind);\n }\n if (q.toType !== undefined) {\n qb = qb.where('to_type', '=', q.toType);\n }\n if (q.toId !== undefined) {\n qb = qb.where('to_id', '=', q.toId);\n }\n const rows = await qb.execute();\n return rows.map(\n (r): Edge => ({\n from_type: r.from_type,\n from_id: r.from_id,\n kind: r.kind,\n to_type: r.to_type,\n to_id: r.to_id,\n attributes: parseJson<Attrs>(r.attributes, {}),\n updated_at: Number(r.updated_at),\n }),\n );\n },\n\n queryDistributions: async (q: DistributionQuery) => {\n await ready;\n let qb = db\n .selectFrom('distributions')\n .select(['name', 'ts', 'kind', 'data', 'attributes'])\n .where('connector_id', '=', connectorId);\n if (q.name !== undefined) {\n qb = qb.where('name', '=', q.name);\n }\n if (q.start !== undefined) {\n qb = qb.where('ts', '>=', q.start);\n }\n if (q.end !== undefined) {\n qb = qb.where('ts', '<=', q.end);\n }\n const rows = await qb.execute();\n return rows.map((r) => {\n const base = {\n name: r.name,\n ts: Number(r.ts),\n attributes: parseJson<Attrs>(r.attributes, {}),\n };\n const data = parseJson<Distribution['data']>(r.data, {\n count: 0,\n sum: 0,\n } as unknown as Distribution['data']);\n if (r.kind === 'histogram') {\n return { ...base, kind: 'histogram', data } as Distribution;\n }\n if (r.kind === 'summary') {\n return { ...base, kind: 'summary', data } as Distribution;\n }\n throw new Error(\n `Unknown distribution kind: ${r.kind} (name=${base.name})`,\n );\n });\n },\n\n deleteOlderThan: async (shape, tsUnixMs) => {\n await ready;\n if (shape === 'events') {\n const r = await db\n .deleteFrom('events')\n .where('connector_id', '=', connectorId)\n .where('start_ts', '<', tsUnixMs)\n .executeTakeFirst();\n return { rowsDeleted: Number(r.numDeletedRows) };\n }\n if (shape === 'metrics') {\n const r = await db\n .deleteFrom('metrics')\n .where('connector_id', '=', connectorId)\n .where('ts', '<', tsUnixMs)\n .executeTakeFirst();\n return { rowsDeleted: Number(r.numDeletedRows) };\n }\n if (shape === 'distributions') {\n const r = await db\n .deleteFrom('distributions')\n .where('connector_id', '=', connectorId)\n .where('ts', '<', tsUnixMs)\n .executeTakeFirst();\n return { rowsDeleted: Number(r.numDeletedRows) };\n }\n throw new Error(\n `Unsupported shape for deleteOlderThan: ${String(shape)}`,\n );\n },\n\n writeRollups: async (buckets) => {\n await ready;\n if (buckets.length === 0) {\n return;\n }\n const stmts = buckets.map((b) =>\n toBatchStmt(\n db\n .insertInto('rollups')\n .values(rollupRow(b))\n .onConflict((oc) =>\n oc\n .columns([\n 'connector_id',\n 'resource',\n 'field',\n 'granularity',\n 'dims_key',\n 'bucket_start',\n ])\n .doUpdateSet({\n dims: (eb) => eb.ref('excluded.dims'),\n partials: (eb) => eb.ref('excluded.partials'),\n }),\n )\n .compile(),\n ),\n );\n await client.batch(stmts, 'write');\n },\n\n queryRollups: async (q: RollupQuery) => {\n await ready;\n let qb = db\n .selectFrom('rollups')\n .select([\n 'resource',\n 'field',\n 'granularity',\n 'dims',\n 'bucket_start',\n 'partials',\n ])\n .where('connector_id', '=', connectorId)\n .where('resource', '=', q.resource);\n if (q.field !== undefined) {\n qb = qb.where('field', '=', q.field);\n }\n if (q.granularity !== undefined) {\n qb = qb.where('granularity', '=', q.granularity);\n }\n if (q.start !== undefined) {\n qb = qb.where('bucket_start', '>=', q.start);\n }\n if (q.end !== undefined) {\n qb = qb.where('bucket_start', '<', q.end);\n }\n const rows = await qb.execute();\n return rows.map(\n (r): RollupBucket => ({\n resource: r.resource,\n field: r.field,\n granularity: r.granularity as Granularity,\n dims: parseJson<Record<string, JSONValue>>(r.dims, {}),\n bucketStart: Number(r.bucket_start),\n partials: parseJson<RollupPartials>(r.partials, {\n count: 0,\n numericCount: 0,\n sum: 0,\n min: null,\n max: null,\n firstTs: null,\n firstValue: null,\n latestTs: null,\n latestValue: null,\n }),\n }),\n );\n },\n\n getRollupWatermark: async (resource: string) => {\n await ready;\n const r = await db\n .selectFrom('rollup_watermarks')\n .select(['watermark'])\n .where('connector_id', '=', connectorId)\n .where('resource', '=', resource)\n .limit(1)\n .executeTakeFirst();\n return r ? Number(r.watermark) : null;\n },\n\n setRollupWatermark: async (resource: string, tsUnixMs: number) => {\n await ready;\n await db\n .insertInto('rollup_watermarks')\n .values({ connector_id: connectorId, resource, watermark: tsUnixMs })\n .onConflict((oc) =>\n oc.columns(['connector_id', 'resource']).doUpdateSet({\n watermark: sql<number>`max(rollup_watermarks.watermark, excluded.watermark)`,\n }),\n )\n .execute();\n },\n };\n }\n\n async getHealth(_connectorId: string): Promise<ConnectorHealth | null> {\n const sync = await this.getSyncState();\n if (sync.status !== 'failed') {\n return null;\n }\n return {\n status: healthStatusFromSyncStatus(sync.status),\n lastSyncAt: sync.lastSyncAt,\n lastError: sync.lastError,\n syncIntervalSeconds: 0,\n };\n }\n\n async getSyncState(): Promise<SyncState> {\n if (this.initError !== null) {\n return {\n status: 'failed',\n queuedAt: null,\n startedAt: null,\n lastSyncAt: null,\n lastError: this.initError,\n };\n }\n await this.ready;\n const r = await this.db\n .selectFrom('sync_state')\n .select([\n 'status',\n 'queued_at',\n 'started_at',\n 'last_sync_at',\n 'last_error',\n ])\n .where('id', '=', SYNC_STATE_ID)\n .limit(1)\n .executeTakeFirst();\n if (!r) {\n return {\n status: 'idle',\n queuedAt: null,\n startedAt: null,\n lastSyncAt: null,\n lastError: null,\n };\n }\n return {\n status: r.status as SyncState['status'],\n queuedAt: r.queued_at,\n startedAt: r.started_at,\n lastSyncAt: r.last_sync_at,\n lastError: r.last_error,\n };\n }\n\n async markSyncQueued(): Promise<boolean> {\n await this.ready;\n const r = await this.db\n .updateTable('sync_state')\n .set({\n status: 'queued',\n queued_at: new Date().toISOString(),\n started_at: null,\n })\n .where('id', '=', SYNC_STATE_ID)\n .where('status', 'not in', ['queued', 'running'])\n .executeTakeFirst();\n return Number(r.numUpdatedRows) > 0;\n }\n\n async markSyncRunning(): Promise<boolean> {\n await this.ready;\n const r = await this.db\n .updateTable('sync_state')\n .set({ status: 'running', started_at: new Date().toISOString() })\n .where('id', '=', SYNC_STATE_ID)\n .where('status', '=', 'queued')\n .executeTakeFirst();\n return Number(r.numUpdatedRows) > 0;\n }\n\n async markSyncSucceeded(): Promise<void> {\n await this.ready;\n await this.db\n .updateTable('sync_state')\n .set({\n status: 'succeeded',\n queued_at: null,\n started_at: null,\n last_sync_at: new Date().toISOString(),\n last_error: null,\n })\n .where('id', '=', SYNC_STATE_ID)\n .execute();\n }\n\n async markSyncFailed(error: string): Promise<void> {\n await this.ready;\n await this.db\n .updateTable('sync_state')\n .set({\n status: 'failed',\n queued_at: null,\n started_at: null,\n last_error: error,\n })\n .where('id', '=', SYNC_STATE_ID)\n .execute();\n }\n\n async close(): Promise<void> {\n await this.ready.catch(() => undefined);\n this.client.close();\n }\n}\n","// AUTO-GENERATED by scripts/bundle-migrations.ts — do not edit by hand.\n// Regenerate with: pnpm db:bundle (or pnpm db:generate).\n\nexport interface BundledMigration {\n tag: string;\n statements: string[];\n}\n\nexport const MIGRATIONS: readonly BundledMigration[] = [\n {\n tag: '0000_nosy_wendell_vaughn',\n statements: [\n \"CREATE TABLE `distributions` (\\n\\t`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,\\n\\t`connector_id` text NOT NULL,\\n\\t`name` text NOT NULL,\\n\\t`ts` integer NOT NULL,\\n\\t`kind` text NOT NULL,\\n\\t`data` text NOT NULL,\\n\\t`attributes` text DEFAULT '{}' NOT NULL\\n);\",\n 'CREATE INDEX `distributions_conn_name_ts` ON `distributions` (`connector_id`,`name`,`ts`);',\n \"CREATE TABLE `edges` (\\n\\t`connector_id` text NOT NULL,\\n\\t`from_type` text NOT NULL,\\n\\t`from_id` text NOT NULL,\\n\\t`kind` text NOT NULL,\\n\\t`to_type` text NOT NULL,\\n\\t`to_id` text NOT NULL,\\n\\t`attributes` text DEFAULT '{}' NOT NULL,\\n\\t`updated_at` integer NOT NULL,\\n\\tPRIMARY KEY(`connector_id`, `from_type`, `from_id`, `kind`, `to_type`, `to_id`)\\n);\",\n 'CREATE INDEX `edges_conn_kind` ON `edges` (`connector_id`,`kind`);',\n 'CREATE INDEX `edges_conn_from` ON `edges` (`connector_id`,`from_type`,`from_id`);',\n \"CREATE TABLE `entities` (\\n\\t`connector_id` text NOT NULL,\\n\\t`type` text NOT NULL,\\n\\t`id` text NOT NULL,\\n\\t`attributes` text DEFAULT '{}' NOT NULL,\\n\\t`updated_at` integer NOT NULL,\\n\\tPRIMARY KEY(`connector_id`, `type`, `id`)\\n);\",\n 'CREATE INDEX `entities_conn_type` ON `entities` (`connector_id`,`type`);',\n \"CREATE TABLE `events` (\\n\\t`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,\\n\\t`connector_id` text NOT NULL,\\n\\t`name` text NOT NULL,\\n\\t`start_ts` integer NOT NULL,\\n\\t`end_ts` integer,\\n\\t`attributes` text DEFAULT '{}' NOT NULL\\n);\",\n 'CREATE INDEX `events_conn_name_start` ON `events` (`connector_id`,`name`,`start_ts`);',\n \"CREATE TABLE `metrics` (\\n\\t`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,\\n\\t`connector_id` text NOT NULL,\\n\\t`name` text NOT NULL,\\n\\t`ts` integer NOT NULL,\\n\\t`value` real NOT NULL,\\n\\t`attributes` text DEFAULT '{}' NOT NULL\\n);\",\n 'CREATE INDEX `metrics_conn_name_ts` ON `metrics` (`connector_id`,`name`,`ts`);',\n ],\n },\n {\n tag: '0001_clumsy_siren',\n statements: [\n 'CREATE TABLE `sync_state` (\\n\\t`id` integer PRIMARY KEY NOT NULL,\\n\\t`status` text NOT NULL,\\n\\t`last_sync_at` text,\\n\\t`last_error` text\\n);',\n ],\n },\n {\n tag: '0002_milky_echo',\n statements: [\n 'ALTER TABLE `sync_state` ADD `queued_at` text;',\n 'ALTER TABLE `sync_state` ADD `started_at` text;',\n ],\n },\n {\n tag: '0003_milky_morbius',\n statements: [\n 'CREATE TABLE `rollup_watermarks` (\\n\\t`connector_id` text NOT NULL,\\n\\t`resource` text NOT NULL,\\n\\t`watermark` integer NOT NULL,\\n\\tPRIMARY KEY(`connector_id`, `resource`)\\n);',\n \"CREATE TABLE `rollups` (\\n\\t`connector_id` text NOT NULL,\\n\\t`resource` text NOT NULL,\\n\\t`field` text DEFAULT '' NOT NULL,\\n\\t`granularity` text NOT NULL,\\n\\t`dims_key` text DEFAULT '' NOT NULL,\\n\\t`dims` text DEFAULT '{}' NOT NULL,\\n\\t`bucket_start` integer NOT NULL,\\n\\t`partials` text NOT NULL,\\n\\tPRIMARY KEY(`connector_id`, `resource`, `field`, `granularity`, `dims_key`, `bucket_start`)\\n);\",\n 'CREATE INDEX `rollups_conn_resource_field` ON `rollups` (`connector_id`,`resource`,`field`);',\n ],\n },\n] as const;\n","import type { Client, InStatement } from '@libsql/client/web';\n\nimport { MIGRATIONS } from './migrations-bundle';\n\nconst SCHEMA_MIGRATIONS_TABLE = 'schema_migrations';\n\nconst LEGACY_BASELINE_TABLE = 'events';\n\nasync function tableExists(client: Client, name: string): Promise<boolean> {\n const result = await client.execute({\n sql: \"SELECT name FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1\",\n args: [name],\n });\n return result.rows.length > 0;\n}\n\nasync function readAppliedTags(client: Client): Promise<Set<string>> {\n const result = await client.execute(\n `SELECT tag FROM ${SCHEMA_MIGRATIONS_TABLE}`,\n );\n return new Set(result.rows.map((r) => String(r['tag'])));\n}\n\nexport interface ApplyMigrationsOptions {\n assumeLegacyBaselineIfEventsExists?: boolean;\n}\n\nexport async function migrateIfNeeded(\n client: Client,\n opts: ApplyMigrationsOptions = {},\n): Promise<void> {\n const latest = MIGRATIONS[MIGRATIONS.length - 1];\n if (latest === undefined) {\n return;\n }\n try {\n const result = await client.execute({\n sql: `SELECT 1 FROM ${SCHEMA_MIGRATIONS_TABLE} WHERE tag = ? LIMIT 1`,\n args: [latest.tag],\n });\n if (result.rows.length > 0) {\n return;\n }\n } catch {\n // schema_migrations table doesn't exist yet — fall through to apply.\n }\n await applyMigrations(client, opts);\n}\n\nexport async function applyMigrations(\n client: Client,\n opts: ApplyMigrationsOptions = {},\n): Promise<void> {\n const hadSchemaTable = await tableExists(client, SCHEMA_MIGRATIONS_TABLE);\n\n await client.execute(\n `CREATE TABLE IF NOT EXISTS ${SCHEMA_MIGRATIONS_TABLE} (\n tag TEXT PRIMARY KEY,\n applied_at INTEGER NOT NULL\n )`,\n );\n\n if (!hadSchemaTable && opts.assumeLegacyBaselineIfEventsExists === true) {\n const hasLegacySchema = await tableExists(client, LEGACY_BASELINE_TABLE);\n if (hasLegacySchema) {\n const now = Date.now();\n for (const migration of MIGRATIONS) {\n await client.execute({\n sql: `INSERT OR IGNORE INTO ${SCHEMA_MIGRATIONS_TABLE} (tag, applied_at) VALUES (?, ?)`,\n args: [migration.tag, now],\n });\n }\n return;\n }\n }\n\n let applied = await readAppliedTags(client);\n\n for (const migration of MIGRATIONS) {\n if (applied.has(migration.tag)) {\n continue;\n }\n const batch: InStatement[] = [\n {\n sql: `INSERT INTO ${SCHEMA_MIGRATIONS_TABLE} (tag, applied_at) VALUES (?, ?)`,\n args: [migration.tag, Date.now()],\n },\n ...migration.statements,\n ];\n try {\n await client.batch(batch, 'write');\n } catch (err) {\n applied = await readAppliedTags(client);\n if (!applied.has(migration.tag)) {\n throw err;\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/libsql-storage.ts","../src/migrations-bundle.ts","../src/migrate.ts"],"sourcesContent":["import type { Client, InValue } from '@libsql/client/web';\nimport type {\n ConnectorHealth,\n Distribution,\n DistributionQuery,\n Edge,\n EdgeQuery,\n Entity,\n EntityQuery,\n Event,\n EventQuery,\n GetStorageHandleOptions,\n Granularity,\n JSONValue,\n MarkConnectorSyncSucceededOptions,\n MetricQuery,\n MetricSample,\n RollupBucket,\n RollupPartials,\n RollupQuery,\n ServerStorage,\n StorageHandle,\n SyncSchedulingState,\n SyncState,\n} from '@rawdash/core';\nimport {\n dimsKey,\n healthStatusFromSyncStatus,\n withAbortSignal,\n} from '@rawdash/core';\nimport { type CompiledQuery, type Insertable, Kysely, sql } from 'kysely';\nimport { LibsqlDialect } from 'kysely-libsql';\n\nimport type {\n Database,\n EdgesTable,\n EntitiesTable,\n EventsTable,\n MetricsTable,\n RollupsTable,\n} from './db-schema';\nimport { applyMigrations } from './migrate';\n\ntype Attrs = Record<string, JSONValue>;\n\nconst SYNC_STATE_ID = 1;\n\nexport async function initLibsqlSchema(client: Client): Promise<void> {\n await applyMigrations(client, { assumeLegacyBaselineIfEventsExists: true });\n await client.execute({\n sql: \"INSERT OR IGNORE INTO sync_state (id, status, queued_at, started_at, last_sync_at, last_error) VALUES (?, 'idle', NULL, NULL, NULL, NULL)\",\n args: [SYNC_STATE_ID],\n });\n}\n\nfunction parseJson<T>(value: unknown, fallback: T): T {\n if (typeof value !== 'string') {\n return fallback;\n }\n try {\n return JSON.parse(value) as T;\n } catch {\n return fallback;\n }\n}\n\nfunction createDb(client: Client): Kysely<Database> {\n return new Kysely<Database>({\n dialect: new LibsqlDialect({ client }),\n });\n}\n\nfunction toBatchStmt(q: CompiledQuery): { sql: string; args: InValue[] } {\n return { sql: q.sql, args: q.parameters as InValue[] };\n}\n\nexport interface LibsqlStorageOptions {\n client: Client;\n initSchema?: boolean;\n}\n\nexport class LibsqlStorage implements ServerStorage {\n private client: Client;\n private db: Kysely<Database>;\n private ready: Promise<void>;\n private initError: string | null = null;\n\n constructor(options: LibsqlStorageOptions) {\n this.client = options.client;\n this.db = createDb(options.client);\n this.ready = options.initSchema === false ? Promise.resolve() : this.init();\n }\n\n private async init(): Promise<void> {\n try {\n await initLibsqlSchema(this.client);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n this.initError = `init failed: ${message}`;\n throw err;\n }\n }\n\n async waitUntilReady(): Promise<void> {\n return this.ready;\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 ready = this.ready;\n const db = this.db;\n const client = this.client;\n\n const eventRow = (e: Event): Insertable<EventsTable> => ({\n connector_id: connectorId,\n name: e.name,\n start_ts: e.start_ts,\n end_ts: e.end_ts,\n attributes: JSON.stringify(e.attributes),\n });\n\n const entityRow = (e: Entity): Insertable<EntitiesTable> => ({\n connector_id: connectorId,\n type: e.type,\n id: e.id,\n attributes: JSON.stringify(e.attributes),\n updated_at: e.updated_at,\n });\n\n const metricRow = (m: MetricSample): Insertable<MetricsTable> => ({\n connector_id: connectorId,\n name: m.name,\n ts: m.ts,\n value: m.value,\n attributes: JSON.stringify(m.attributes),\n });\n\n const edgeRow = (e: Edge): Insertable<EdgesTable> => ({\n connector_id: connectorId,\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 attributes: JSON.stringify(e.attributes),\n updated_at: e.updated_at,\n });\n\n const distributionRow = (d: Distribution) => ({\n connector_id: connectorId,\n name: d.name,\n ts: d.ts,\n kind: d.kind,\n data: JSON.stringify(d.data),\n attributes: JSON.stringify(d.attributes),\n });\n\n const rollupRow = (b: RollupBucket): Insertable<RollupsTable> => ({\n connector_id: connectorId,\n resource: b.resource,\n field: b.field,\n granularity: b.granularity,\n dims_key: dimsKey(b.dims),\n dims: JSON.stringify(b.dims),\n bucket_start: b.bucketStart,\n partials: JSON.stringify(b.partials),\n });\n\n return {\n event: async (e) => {\n await ready;\n await db.insertInto('events').values(eventRow(e)).execute();\n },\n\n entity: async (e) => {\n await ready;\n await db\n .insertInto('entities')\n .values(entityRow(e))\n .onConflict((oc) =>\n oc.columns(['connector_id', 'type', 'id']).doUpdateSet({\n attributes: (eb) => eb.ref('excluded.attributes'),\n updated_at: (eb) => eb.ref('excluded.updated_at'),\n }),\n )\n .execute();\n },\n\n metric: async (m) => {\n await ready;\n await db.insertInto('metrics').values(metricRow(m)).execute();\n },\n\n edge: async (e) => {\n await ready;\n await db\n .insertInto('edges')\n .values(edgeRow(e))\n .onConflict((oc) =>\n oc\n .columns([\n 'connector_id',\n 'from_type',\n 'from_id',\n 'kind',\n 'to_type',\n 'to_id',\n ])\n .doUpdateSet({\n attributes: (eb) => eb.ref('excluded.attributes'),\n updated_at: (eb) => eb.ref('excluded.updated_at'),\n }),\n )\n .execute();\n },\n\n distribution: async (d) => {\n await ready;\n await db\n .insertInto('distributions')\n .values(distributionRow(d))\n .execute();\n },\n\n events: async (es, scope) => {\n await ready;\n const names = Array.from(\n new Set(scope?.names ?? es.map((e) => e.name)),\n );\n const stmts: { sql: string; args: InValue[] }[] = [];\n if (names.length > 0) {\n stmts.push(\n toBatchStmt(\n db\n .deleteFrom('events')\n .where('connector_id', '=', connectorId)\n .where('name', 'in', names)\n .compile(),\n ),\n );\n }\n if (es.length > 0) {\n stmts.push(\n toBatchStmt(\n db.insertInto('events').values(es.map(eventRow)).compile(),\n ),\n );\n }\n if (stmts.length > 0) {\n await client.batch(stmts, 'write');\n }\n },\n\n entities: async (es, scope) => {\n await ready;\n const types = Array.from(\n new Set(scope?.types ?? es.map((e) => e.type)),\n );\n const stmts: { sql: string; args: InValue[] }[] = [];\n if (types.length > 0) {\n stmts.push(\n toBatchStmt(\n db\n .deleteFrom('entities')\n .where('connector_id', '=', connectorId)\n .where('type', 'in', types)\n .compile(),\n ),\n );\n }\n if (es.length > 0) {\n stmts.push(\n toBatchStmt(\n db\n .insertInto('entities')\n .values(es.map(entityRow))\n .onConflict((oc) =>\n oc.columns(['connector_id', 'type', 'id']).doUpdateSet({\n attributes: (eb) => eb.ref('excluded.attributes'),\n updated_at: (eb) => eb.ref('excluded.updated_at'),\n }),\n )\n .compile(),\n ),\n );\n }\n if (stmts.length > 0) {\n await client.batch(stmts, 'write');\n }\n },\n\n metrics: async (ms, scope) => {\n await ready;\n const names = Array.from(\n new Set(scope?.names ?? ms.map((m) => m.name)),\n );\n const window = scope?.replaceWindow;\n const stmts: { sql: string; args: InValue[] }[] = [];\n if (names.length > 0) {\n let del = db\n .deleteFrom('metrics')\n .where('connector_id', '=', connectorId)\n .where('name', 'in', names);\n if (window) {\n del = del\n .where('ts', '>=', window.start)\n .where('ts', '<=', window.end);\n }\n stmts.push(toBatchStmt(del.compile()));\n }\n if (ms.length > 0) {\n stmts.push(\n toBatchStmt(\n db.insertInto('metrics').values(ms.map(metricRow)).compile(),\n ),\n );\n }\n if (stmts.length > 0) {\n await client.batch(stmts, 'write');\n }\n },\n\n edges: async (es, scope) => {\n await ready;\n const kinds = Array.from(\n new Set(scope?.kinds ?? es.map((e) => e.kind)),\n );\n const stmts: { sql: string; args: InValue[] }[] = [];\n if (kinds.length > 0) {\n stmts.push(\n toBatchStmt(\n db\n .deleteFrom('edges')\n .where('connector_id', '=', connectorId)\n .where('kind', 'in', kinds)\n .compile(),\n ),\n );\n }\n if (es.length > 0) {\n stmts.push(\n toBatchStmt(\n db\n .insertInto('edges')\n .values(es.map(edgeRow))\n .onConflict((oc) =>\n oc\n .columns([\n 'connector_id',\n 'from_type',\n 'from_id',\n 'kind',\n 'to_type',\n 'to_id',\n ])\n .doUpdateSet({\n attributes: (eb) => eb.ref('excluded.attributes'),\n updated_at: (eb) => eb.ref('excluded.updated_at'),\n }),\n )\n .compile(),\n ),\n );\n }\n if (stmts.length > 0) {\n await client.batch(stmts, 'write');\n }\n },\n\n distributions: async (ds, scope) => {\n await ready;\n const names = Array.from(\n new Set(scope?.names ?? ds.map((d) => d.name)),\n );\n const window = scope?.replaceWindow;\n const stmts: { sql: string; args: InValue[] }[] = [];\n if (names.length > 0) {\n let del = db\n .deleteFrom('distributions')\n .where('connector_id', '=', connectorId)\n .where('name', 'in', names);\n if (window) {\n del = del\n .where('ts', '>=', window.start)\n .where('ts', '<=', window.end);\n }\n stmts.push(toBatchStmt(del.compile()));\n }\n if (ds.length > 0) {\n stmts.push(\n toBatchStmt(\n db\n .insertInto('distributions')\n .values(ds.map(distributionRow))\n .compile(),\n ),\n );\n }\n if (stmts.length > 0) {\n await client.batch(stmts, 'write');\n }\n },\n\n queryEvents: async (q: EventQuery) => {\n await ready;\n let qb = db\n .selectFrom('events')\n .select(['name', 'start_ts', 'end_ts', 'attributes'])\n .where('connector_id', '=', connectorId);\n if (q.name !== undefined) {\n qb = qb.where('name', '=', q.name);\n }\n if (q.start !== undefined) {\n qb = qb.where('start_ts', '>=', q.start);\n }\n if (q.end !== undefined) {\n qb = qb.where('start_ts', '<=', q.end);\n }\n const rows = await qb.execute();\n return rows.map(\n (r): Event => ({\n name: r.name,\n start_ts: Number(r.start_ts),\n end_ts: r.end_ts === null ? null : Number(r.end_ts),\n attributes: parseJson<Attrs>(r.attributes, {}),\n }),\n );\n },\n\n getEntity: async (type, id) => {\n await ready;\n const r = await db\n .selectFrom('entities')\n .select(['type', 'id', 'attributes', 'updated_at'])\n .where('connector_id', '=', connectorId)\n .where('type', '=', type)\n .where('id', '=', id)\n .limit(1)\n .executeTakeFirst();\n if (!r) {\n return null;\n }\n return {\n type: r.type,\n id: r.id,\n attributes: parseJson<Attrs>(r.attributes, {}),\n updated_at: Number(r.updated_at),\n };\n },\n\n queryEntities: async (q: EntityQuery) => {\n await ready;\n const rows = await db\n .selectFrom('entities')\n .select(['type', 'id', 'attributes', 'updated_at'])\n .where('connector_id', '=', connectorId)\n .where('type', '=', q.type)\n .execute();\n return rows.map(\n (r): Entity => ({\n type: r.type,\n id: r.id,\n attributes: parseJson<Attrs>(r.attributes, {}),\n updated_at: Number(r.updated_at),\n }),\n );\n },\n\n queryMetrics: async (q: MetricQuery) => {\n await ready;\n let qb = db\n .selectFrom('metrics')\n .select(['name', 'ts', 'value', 'attributes'])\n .where('connector_id', '=', connectorId);\n if (q.name !== undefined) {\n qb = qb.where('name', '=', q.name);\n }\n if (q.start !== undefined) {\n qb = qb.where('ts', '>=', q.start);\n }\n if (q.end !== undefined) {\n qb = qb.where('ts', '<=', q.end);\n }\n const rows = await qb.execute();\n return rows.map(\n (r): MetricSample => ({\n name: r.name,\n ts: Number(r.ts),\n value: Number(r.value),\n attributes: parseJson<Attrs>(r.attributes, {}),\n }),\n );\n },\n\n traverse: async (q: EdgeQuery) => {\n await ready;\n let qb = db\n .selectFrom('edges')\n .select([\n 'from_type',\n 'from_id',\n 'kind',\n 'to_type',\n 'to_id',\n 'attributes',\n 'updated_at',\n ])\n .where('connector_id', '=', connectorId);\n if (q.fromType !== undefined) {\n qb = qb.where('from_type', '=', q.fromType);\n }\n if (q.fromId !== undefined) {\n qb = qb.where('from_id', '=', q.fromId);\n }\n if (q.kind !== undefined) {\n qb = qb.where('kind', '=', q.kind);\n }\n if (q.toType !== undefined) {\n qb = qb.where('to_type', '=', q.toType);\n }\n if (q.toId !== undefined) {\n qb = qb.where('to_id', '=', q.toId);\n }\n const rows = await qb.execute();\n return rows.map(\n (r): Edge => ({\n from_type: r.from_type,\n from_id: r.from_id,\n kind: r.kind,\n to_type: r.to_type,\n to_id: r.to_id,\n attributes: parseJson<Attrs>(r.attributes, {}),\n updated_at: Number(r.updated_at),\n }),\n );\n },\n\n queryDistributions: async (q: DistributionQuery) => {\n await ready;\n let qb = db\n .selectFrom('distributions')\n .select(['name', 'ts', 'kind', 'data', 'attributes'])\n .where('connector_id', '=', connectorId);\n if (q.name !== undefined) {\n qb = qb.where('name', '=', q.name);\n }\n if (q.start !== undefined) {\n qb = qb.where('ts', '>=', q.start);\n }\n if (q.end !== undefined) {\n qb = qb.where('ts', '<=', q.end);\n }\n const rows = await qb.execute();\n return rows.map((r) => {\n const base = {\n name: r.name,\n ts: Number(r.ts),\n attributes: parseJson<Attrs>(r.attributes, {}),\n };\n const data = parseJson<Distribution['data']>(r.data, {\n count: 0,\n sum: 0,\n } as unknown as Distribution['data']);\n if (r.kind === 'histogram') {\n return { ...base, kind: 'histogram', data } as Distribution;\n }\n if (r.kind === 'summary') {\n return { ...base, kind: 'summary', data } as Distribution;\n }\n throw new Error(\n `Unknown distribution kind: ${r.kind} (name=${base.name})`,\n );\n });\n },\n\n deleteOlderThan: async (shape, tsUnixMs) => {\n await ready;\n if (shape === 'events') {\n const r = await db\n .deleteFrom('events')\n .where('connector_id', '=', connectorId)\n .where('start_ts', '<', tsUnixMs)\n .executeTakeFirst();\n return { rowsDeleted: Number(r.numDeletedRows) };\n }\n if (shape === 'metrics') {\n const r = await db\n .deleteFrom('metrics')\n .where('connector_id', '=', connectorId)\n .where('ts', '<', tsUnixMs)\n .executeTakeFirst();\n return { rowsDeleted: Number(r.numDeletedRows) };\n }\n if (shape === 'distributions') {\n const r = await db\n .deleteFrom('distributions')\n .where('connector_id', '=', connectorId)\n .where('ts', '<', tsUnixMs)\n .executeTakeFirst();\n return { rowsDeleted: Number(r.numDeletedRows) };\n }\n throw new Error(\n `Unsupported shape for deleteOlderThan: ${String(shape)}`,\n );\n },\n\n writeRollups: async (buckets) => {\n await ready;\n if (buckets.length === 0) {\n return;\n }\n const stmts = buckets.map((b) =>\n toBatchStmt(\n db\n .insertInto('rollups')\n .values(rollupRow(b))\n .onConflict((oc) =>\n oc\n .columns([\n 'connector_id',\n 'resource',\n 'field',\n 'granularity',\n 'dims_key',\n 'bucket_start',\n ])\n .doUpdateSet({\n dims: (eb) => eb.ref('excluded.dims'),\n partials: (eb) => eb.ref('excluded.partials'),\n }),\n )\n .compile(),\n ),\n );\n await client.batch(stmts, 'write');\n },\n\n queryRollups: async (q: RollupQuery) => {\n await ready;\n let qb = db\n .selectFrom('rollups')\n .select([\n 'resource',\n 'field',\n 'granularity',\n 'dims',\n 'bucket_start',\n 'partials',\n ])\n .where('connector_id', '=', connectorId)\n .where('resource', '=', q.resource);\n if (q.field !== undefined) {\n qb = qb.where('field', '=', q.field);\n }\n if (q.granularity !== undefined) {\n qb = qb.where('granularity', '=', q.granularity);\n }\n if (q.start !== undefined) {\n qb = qb.where('bucket_start', '>=', q.start);\n }\n if (q.end !== undefined) {\n qb = qb.where('bucket_start', '<', q.end);\n }\n const rows = await qb.execute();\n return rows.map(\n (r): RollupBucket => ({\n resource: r.resource,\n field: r.field,\n granularity: r.granularity as Granularity,\n dims: parseJson<Record<string, JSONValue>>(r.dims, {}),\n bucketStart: Number(r.bucket_start),\n partials: parseJson<RollupPartials>(r.partials, {\n count: 0,\n numericCount: 0,\n sum: 0,\n min: null,\n max: null,\n firstTs: null,\n firstValue: null,\n latestTs: null,\n latestValue: null,\n }),\n }),\n );\n },\n\n getRollupWatermark: async (resource: string) => {\n await ready;\n const r = await db\n .selectFrom('rollup_watermarks')\n .select(['watermark'])\n .where('connector_id', '=', connectorId)\n .where('resource', '=', resource)\n .limit(1)\n .executeTakeFirst();\n return r ? Number(r.watermark) : null;\n },\n\n setRollupWatermark: async (resource: string, tsUnixMs: number) => {\n await ready;\n await db\n .insertInto('rollup_watermarks')\n .values({ connector_id: connectorId, resource, watermark: tsUnixMs })\n .onConflict((oc) =>\n oc.columns(['connector_id', 'resource']).doUpdateSet({\n watermark: sql<number>`max(rollup_watermarks.watermark, excluded.watermark)`,\n }),\n )\n .execute();\n },\n };\n }\n\n async getHealth(_connectorId: string): Promise<ConnectorHealth | null> {\n const sync = await this.getSyncState();\n if (sync.status !== 'failed') {\n return null;\n }\n return {\n status: healthStatusFromSyncStatus(sync.status),\n lastSyncAt: sync.lastSyncAt,\n lastError: sync.lastError,\n syncIntervalSeconds: 0,\n };\n }\n\n async getSyncState(): Promise<SyncState> {\n if (this.initError !== null) {\n return {\n status: 'failed',\n queuedAt: null,\n startedAt: null,\n lastSyncAt: null,\n lastError: this.initError,\n };\n }\n await this.ready;\n const r = await this.db\n .selectFrom('sync_state')\n .select([\n 'status',\n 'queued_at',\n 'started_at',\n 'last_sync_at',\n 'last_error',\n ])\n .where('id', '=', SYNC_STATE_ID)\n .limit(1)\n .executeTakeFirst();\n if (!r) {\n return {\n status: 'idle',\n queuedAt: null,\n startedAt: null,\n lastSyncAt: null,\n lastError: null,\n };\n }\n return {\n status: r.status as SyncState['status'],\n queuedAt: r.queued_at,\n startedAt: r.started_at,\n lastSyncAt: r.last_sync_at,\n lastError: r.last_error,\n };\n }\n\n async getConnectorSyncState(\n connectorId: string,\n ): Promise<SyncSchedulingState> {\n if (this.initError !== null) {\n return { lastSyncAt: null, lastBackfillAt: null };\n }\n await this.ready;\n const r = await this.db\n .selectFrom('connector_sync_state')\n .select(['last_sync_at', 'last_backfill_at'])\n .where('connector_id', '=', connectorId)\n .limit(1)\n .executeTakeFirst();\n return {\n lastSyncAt: r?.last_sync_at ?? null,\n lastBackfillAt: r?.last_backfill_at ?? null,\n };\n }\n\n async markSyncQueued(): Promise<boolean> {\n await this.ready;\n const r = await this.db\n .updateTable('sync_state')\n .set({\n status: 'queued',\n queued_at: new Date().toISOString(),\n started_at: null,\n })\n .where('id', '=', SYNC_STATE_ID)\n .where('status', 'not in', ['queued', 'running'])\n .executeTakeFirst();\n return Number(r.numUpdatedRows) > 0;\n }\n\n async markSyncRunning(): Promise<boolean> {\n await this.ready;\n const r = await this.db\n .updateTable('sync_state')\n .set({ status: 'running', started_at: new Date().toISOString() })\n .where('id', '=', SYNC_STATE_ID)\n .where('status', '=', 'queued')\n .executeTakeFirst();\n return Number(r.numUpdatedRows) > 0;\n }\n\n async markSyncSucceeded(): Promise<void> {\n await this.ready;\n await this.db\n .updateTable('sync_state')\n .set({\n status: 'succeeded',\n queued_at: null,\n started_at: null,\n last_sync_at: new Date().toISOString(),\n last_error: null,\n })\n .where('id', '=', SYNC_STATE_ID)\n .execute();\n }\n\n async markConnectorSyncSucceeded(\n connectorId: string,\n options?: MarkConnectorSyncSucceededOptions,\n ): Promise<void> {\n await this.ready;\n const now = new Date().toISOString();\n await this.db\n .insertInto('connector_sync_state')\n .values({\n connector_id: connectorId,\n last_sync_at: now,\n last_backfill_at: options?.backfillDue ? now : null,\n })\n .onConflict((oc) =>\n oc.column('connector_id').doUpdateSet({\n last_sync_at: now,\n ...(options?.backfillDue ? { last_backfill_at: now } : {}),\n }),\n )\n .execute();\n }\n\n async markSyncFailed(error: string): Promise<void> {\n await this.ready;\n await this.db\n .updateTable('sync_state')\n .set({\n status: 'failed',\n queued_at: null,\n started_at: null,\n last_error: error,\n })\n .where('id', '=', SYNC_STATE_ID)\n .execute();\n }\n\n async close(): Promise<void> {\n await this.ready.catch(() => undefined);\n this.client.close();\n }\n}\n","// AUTO-GENERATED by scripts/bundle-migrations.ts — do not edit by hand.\n// Regenerate with: pnpm db:bundle (or pnpm db:generate).\n\nexport interface BundledMigration {\n tag: string;\n statements: string[];\n}\n\nexport const MIGRATIONS: readonly BundledMigration[] = [\n {\n tag: '0000_nosy_wendell_vaughn',\n statements: [\n \"CREATE TABLE `distributions` (\\n\\t`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,\\n\\t`connector_id` text NOT NULL,\\n\\t`name` text NOT NULL,\\n\\t`ts` integer NOT NULL,\\n\\t`kind` text NOT NULL,\\n\\t`data` text NOT NULL,\\n\\t`attributes` text DEFAULT '{}' NOT NULL\\n);\",\n 'CREATE INDEX `distributions_conn_name_ts` ON `distributions` (`connector_id`,`name`,`ts`);',\n \"CREATE TABLE `edges` (\\n\\t`connector_id` text NOT NULL,\\n\\t`from_type` text NOT NULL,\\n\\t`from_id` text NOT NULL,\\n\\t`kind` text NOT NULL,\\n\\t`to_type` text NOT NULL,\\n\\t`to_id` text NOT NULL,\\n\\t`attributes` text DEFAULT '{}' NOT NULL,\\n\\t`updated_at` integer NOT NULL,\\n\\tPRIMARY KEY(`connector_id`, `from_type`, `from_id`, `kind`, `to_type`, `to_id`)\\n);\",\n 'CREATE INDEX `edges_conn_kind` ON `edges` (`connector_id`,`kind`);',\n 'CREATE INDEX `edges_conn_from` ON `edges` (`connector_id`,`from_type`,`from_id`);',\n \"CREATE TABLE `entities` (\\n\\t`connector_id` text NOT NULL,\\n\\t`type` text NOT NULL,\\n\\t`id` text NOT NULL,\\n\\t`attributes` text DEFAULT '{}' NOT NULL,\\n\\t`updated_at` integer NOT NULL,\\n\\tPRIMARY KEY(`connector_id`, `type`, `id`)\\n);\",\n 'CREATE INDEX `entities_conn_type` ON `entities` (`connector_id`,`type`);',\n \"CREATE TABLE `events` (\\n\\t`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,\\n\\t`connector_id` text NOT NULL,\\n\\t`name` text NOT NULL,\\n\\t`start_ts` integer NOT NULL,\\n\\t`end_ts` integer,\\n\\t`attributes` text DEFAULT '{}' NOT NULL\\n);\",\n 'CREATE INDEX `events_conn_name_start` ON `events` (`connector_id`,`name`,`start_ts`);',\n \"CREATE TABLE `metrics` (\\n\\t`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,\\n\\t`connector_id` text NOT NULL,\\n\\t`name` text NOT NULL,\\n\\t`ts` integer NOT NULL,\\n\\t`value` real NOT NULL,\\n\\t`attributes` text DEFAULT '{}' NOT NULL\\n);\",\n 'CREATE INDEX `metrics_conn_name_ts` ON `metrics` (`connector_id`,`name`,`ts`);',\n ],\n },\n {\n tag: '0001_clumsy_siren',\n statements: [\n 'CREATE TABLE `sync_state` (\\n\\t`id` integer PRIMARY KEY NOT NULL,\\n\\t`status` text NOT NULL,\\n\\t`last_sync_at` text,\\n\\t`last_error` text\\n);',\n ],\n },\n {\n tag: '0002_milky_echo',\n statements: [\n 'ALTER TABLE `sync_state` ADD `queued_at` text;',\n 'ALTER TABLE `sync_state` ADD `started_at` text;',\n ],\n },\n {\n tag: '0003_milky_morbius',\n statements: [\n 'CREATE TABLE `rollup_watermarks` (\\n\\t`connector_id` text NOT NULL,\\n\\t`resource` text NOT NULL,\\n\\t`watermark` integer NOT NULL,\\n\\tPRIMARY KEY(`connector_id`, `resource`)\\n);',\n \"CREATE TABLE `rollups` (\\n\\t`connector_id` text NOT NULL,\\n\\t`resource` text NOT NULL,\\n\\t`field` text DEFAULT '' NOT NULL,\\n\\t`granularity` text NOT NULL,\\n\\t`dims_key` text DEFAULT '' NOT NULL,\\n\\t`dims` text DEFAULT '{}' NOT NULL,\\n\\t`bucket_start` integer NOT NULL,\\n\\t`partials` text NOT NULL,\\n\\tPRIMARY KEY(`connector_id`, `resource`, `field`, `granularity`, `dims_key`, `bucket_start`)\\n);\",\n 'CREATE INDEX `rollups_conn_resource_field` ON `rollups` (`connector_id`,`resource`,`field`);',\n ],\n },\n {\n tag: '0004_neat_swarm',\n statements: [\n 'CREATE TABLE `connector_sync_state` (\\n\\t`connector_id` text PRIMARY KEY NOT NULL,\\n\\t`last_sync_at` text,\\n\\t`last_backfill_at` text\\n);',\n ],\n },\n] as const;\n","import type { Client, InStatement } from '@libsql/client/web';\n\nimport { MIGRATIONS } from './migrations-bundle';\n\nconst SCHEMA_MIGRATIONS_TABLE = 'schema_migrations';\n\nconst LEGACY_BASELINE_TABLE = 'events';\n\nconst LEGACY_BASELINE_TAGS: ReadonlySet<string> = new Set([\n '0000_nosy_wendell_vaughn',\n '0001_clumsy_siren',\n '0002_milky_echo',\n '0003_milky_morbius',\n]);\n\nasync function tableExists(client: Client, name: string): Promise<boolean> {\n const result = await client.execute({\n sql: \"SELECT name FROM sqlite_master WHERE type = 'table' AND name = ? LIMIT 1\",\n args: [name],\n });\n return result.rows.length > 0;\n}\n\nasync function readAppliedTags(client: Client): Promise<Set<string>> {\n const result = await client.execute(\n `SELECT tag FROM ${SCHEMA_MIGRATIONS_TABLE}`,\n );\n return new Set(result.rows.map((r) => String(r['tag'])));\n}\n\nexport interface ApplyMigrationsOptions {\n assumeLegacyBaselineIfEventsExists?: boolean;\n}\n\nexport async function migrateIfNeeded(\n client: Client,\n opts: ApplyMigrationsOptions = {},\n): Promise<void> {\n const latest = MIGRATIONS[MIGRATIONS.length - 1];\n if (latest === undefined) {\n return;\n }\n try {\n const result = await client.execute({\n sql: `SELECT 1 FROM ${SCHEMA_MIGRATIONS_TABLE} WHERE tag = ? LIMIT 1`,\n args: [latest.tag],\n });\n if (result.rows.length > 0) {\n return;\n }\n } catch {\n // schema_migrations table doesn't exist yet — fall through to apply.\n }\n await applyMigrations(client, opts);\n}\n\nexport async function applyMigrations(\n client: Client,\n opts: ApplyMigrationsOptions = {},\n): Promise<void> {\n const hadSchemaTable = await tableExists(client, SCHEMA_MIGRATIONS_TABLE);\n\n await client.execute(\n `CREATE TABLE IF NOT EXISTS ${SCHEMA_MIGRATIONS_TABLE} (\n tag TEXT PRIMARY KEY,\n applied_at INTEGER NOT NULL\n )`,\n );\n\n if (!hadSchemaTable && opts.assumeLegacyBaselineIfEventsExists === true) {\n const hasLegacySchema = await tableExists(client, LEGACY_BASELINE_TABLE);\n if (hasLegacySchema) {\n const now = Date.now();\n for (const migration of MIGRATIONS) {\n if (!LEGACY_BASELINE_TAGS.has(migration.tag)) {\n continue;\n }\n await client.execute({\n sql: `INSERT OR IGNORE INTO ${SCHEMA_MIGRATIONS_TABLE} (tag, applied_at) VALUES (?, ?)`,\n args: [migration.tag, now],\n });\n }\n }\n }\n\n let applied = await readAppliedTags(client);\n\n for (const migration of MIGRATIONS) {\n if (applied.has(migration.tag)) {\n continue;\n }\n const batch: InStatement[] = [\n {\n sql: `INSERT INTO ${SCHEMA_MIGRATIONS_TABLE} (tag, applied_at) VALUES (?, ?)`,\n args: [migration.tag, Date.now()],\n },\n ...migration.statements,\n ];\n try {\n await client.batch(batch, 'write');\n } catch (err) {\n applied = await readAppliedTags(client);\n if (!applied.has(migration.tag)) {\n throw err;\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,5 @@
1
+ CREATE TABLE `connector_sync_state` (
2
+ `connector_id` text PRIMARY KEY NOT NULL,
3
+ `last_sync_at` text,
4
+ `last_backfill_at` text
5
+ );
@@ -0,0 +1,555 @@
1
+ {
2
+ "version": "6",
3
+ "dialect": "sqlite",
4
+ "id": "3b316d13-aecc-4474-a718-69a5a9676f9a",
5
+ "prevId": "edb3272f-ace9-4f1d-8314-b68c06354d00",
6
+ "tables": {
7
+ "connector_sync_state": {
8
+ "name": "connector_sync_state",
9
+ "columns": {
10
+ "connector_id": {
11
+ "name": "connector_id",
12
+ "type": "text",
13
+ "primaryKey": true,
14
+ "notNull": true,
15
+ "autoincrement": false
16
+ },
17
+ "last_sync_at": {
18
+ "name": "last_sync_at",
19
+ "type": "text",
20
+ "primaryKey": false,
21
+ "notNull": false,
22
+ "autoincrement": false
23
+ },
24
+ "last_backfill_at": {
25
+ "name": "last_backfill_at",
26
+ "type": "text",
27
+ "primaryKey": false,
28
+ "notNull": false,
29
+ "autoincrement": false
30
+ }
31
+ },
32
+ "indexes": {},
33
+ "foreignKeys": {},
34
+ "compositePrimaryKeys": {},
35
+ "uniqueConstraints": {},
36
+ "checkConstraints": {}
37
+ },
38
+ "distributions": {
39
+ "name": "distributions",
40
+ "columns": {
41
+ "id": {
42
+ "name": "id",
43
+ "type": "integer",
44
+ "primaryKey": true,
45
+ "notNull": true,
46
+ "autoincrement": true
47
+ },
48
+ "connector_id": {
49
+ "name": "connector_id",
50
+ "type": "text",
51
+ "primaryKey": false,
52
+ "notNull": true,
53
+ "autoincrement": false
54
+ },
55
+ "name": {
56
+ "name": "name",
57
+ "type": "text",
58
+ "primaryKey": false,
59
+ "notNull": true,
60
+ "autoincrement": false
61
+ },
62
+ "ts": {
63
+ "name": "ts",
64
+ "type": "integer",
65
+ "primaryKey": false,
66
+ "notNull": true,
67
+ "autoincrement": false
68
+ },
69
+ "kind": {
70
+ "name": "kind",
71
+ "type": "text",
72
+ "primaryKey": false,
73
+ "notNull": true,
74
+ "autoincrement": false
75
+ },
76
+ "data": {
77
+ "name": "data",
78
+ "type": "text",
79
+ "primaryKey": false,
80
+ "notNull": true,
81
+ "autoincrement": false
82
+ },
83
+ "attributes": {
84
+ "name": "attributes",
85
+ "type": "text",
86
+ "primaryKey": false,
87
+ "notNull": true,
88
+ "autoincrement": false,
89
+ "default": "'{}'"
90
+ }
91
+ },
92
+ "indexes": {
93
+ "distributions_conn_name_ts": {
94
+ "name": "distributions_conn_name_ts",
95
+ "columns": ["connector_id", "name", "ts"],
96
+ "isUnique": false
97
+ }
98
+ },
99
+ "foreignKeys": {},
100
+ "compositePrimaryKeys": {},
101
+ "uniqueConstraints": {},
102
+ "checkConstraints": {}
103
+ },
104
+ "edges": {
105
+ "name": "edges",
106
+ "columns": {
107
+ "connector_id": {
108
+ "name": "connector_id",
109
+ "type": "text",
110
+ "primaryKey": false,
111
+ "notNull": true,
112
+ "autoincrement": false
113
+ },
114
+ "from_type": {
115
+ "name": "from_type",
116
+ "type": "text",
117
+ "primaryKey": false,
118
+ "notNull": true,
119
+ "autoincrement": false
120
+ },
121
+ "from_id": {
122
+ "name": "from_id",
123
+ "type": "text",
124
+ "primaryKey": false,
125
+ "notNull": true,
126
+ "autoincrement": false
127
+ },
128
+ "kind": {
129
+ "name": "kind",
130
+ "type": "text",
131
+ "primaryKey": false,
132
+ "notNull": true,
133
+ "autoincrement": false
134
+ },
135
+ "to_type": {
136
+ "name": "to_type",
137
+ "type": "text",
138
+ "primaryKey": false,
139
+ "notNull": true,
140
+ "autoincrement": false
141
+ },
142
+ "to_id": {
143
+ "name": "to_id",
144
+ "type": "text",
145
+ "primaryKey": false,
146
+ "notNull": true,
147
+ "autoincrement": false
148
+ },
149
+ "attributes": {
150
+ "name": "attributes",
151
+ "type": "text",
152
+ "primaryKey": false,
153
+ "notNull": true,
154
+ "autoincrement": false,
155
+ "default": "'{}'"
156
+ },
157
+ "updated_at": {
158
+ "name": "updated_at",
159
+ "type": "integer",
160
+ "primaryKey": false,
161
+ "notNull": true,
162
+ "autoincrement": false
163
+ }
164
+ },
165
+ "indexes": {
166
+ "edges_conn_kind": {
167
+ "name": "edges_conn_kind",
168
+ "columns": ["connector_id", "kind"],
169
+ "isUnique": false
170
+ },
171
+ "edges_conn_from": {
172
+ "name": "edges_conn_from",
173
+ "columns": ["connector_id", "from_type", "from_id"],
174
+ "isUnique": false
175
+ }
176
+ },
177
+ "foreignKeys": {},
178
+ "compositePrimaryKeys": {
179
+ "edges_connector_id_from_type_from_id_kind_to_type_to_id_pk": {
180
+ "columns": [
181
+ "connector_id",
182
+ "from_type",
183
+ "from_id",
184
+ "kind",
185
+ "to_type",
186
+ "to_id"
187
+ ],
188
+ "name": "edges_connector_id_from_type_from_id_kind_to_type_to_id_pk"
189
+ }
190
+ },
191
+ "uniqueConstraints": {},
192
+ "checkConstraints": {}
193
+ },
194
+ "entities": {
195
+ "name": "entities",
196
+ "columns": {
197
+ "connector_id": {
198
+ "name": "connector_id",
199
+ "type": "text",
200
+ "primaryKey": false,
201
+ "notNull": true,
202
+ "autoincrement": false
203
+ },
204
+ "type": {
205
+ "name": "type",
206
+ "type": "text",
207
+ "primaryKey": false,
208
+ "notNull": true,
209
+ "autoincrement": false
210
+ },
211
+ "id": {
212
+ "name": "id",
213
+ "type": "text",
214
+ "primaryKey": false,
215
+ "notNull": true,
216
+ "autoincrement": false
217
+ },
218
+ "attributes": {
219
+ "name": "attributes",
220
+ "type": "text",
221
+ "primaryKey": false,
222
+ "notNull": true,
223
+ "autoincrement": false,
224
+ "default": "'{}'"
225
+ },
226
+ "updated_at": {
227
+ "name": "updated_at",
228
+ "type": "integer",
229
+ "primaryKey": false,
230
+ "notNull": true,
231
+ "autoincrement": false
232
+ }
233
+ },
234
+ "indexes": {
235
+ "entities_conn_type": {
236
+ "name": "entities_conn_type",
237
+ "columns": ["connector_id", "type"],
238
+ "isUnique": false
239
+ }
240
+ },
241
+ "foreignKeys": {},
242
+ "compositePrimaryKeys": {
243
+ "entities_connector_id_type_id_pk": {
244
+ "columns": ["connector_id", "type", "id"],
245
+ "name": "entities_connector_id_type_id_pk"
246
+ }
247
+ },
248
+ "uniqueConstraints": {},
249
+ "checkConstraints": {}
250
+ },
251
+ "events": {
252
+ "name": "events",
253
+ "columns": {
254
+ "id": {
255
+ "name": "id",
256
+ "type": "integer",
257
+ "primaryKey": true,
258
+ "notNull": true,
259
+ "autoincrement": true
260
+ },
261
+ "connector_id": {
262
+ "name": "connector_id",
263
+ "type": "text",
264
+ "primaryKey": false,
265
+ "notNull": true,
266
+ "autoincrement": false
267
+ },
268
+ "name": {
269
+ "name": "name",
270
+ "type": "text",
271
+ "primaryKey": false,
272
+ "notNull": true,
273
+ "autoincrement": false
274
+ },
275
+ "start_ts": {
276
+ "name": "start_ts",
277
+ "type": "integer",
278
+ "primaryKey": false,
279
+ "notNull": true,
280
+ "autoincrement": false
281
+ },
282
+ "end_ts": {
283
+ "name": "end_ts",
284
+ "type": "integer",
285
+ "primaryKey": false,
286
+ "notNull": false,
287
+ "autoincrement": false
288
+ },
289
+ "attributes": {
290
+ "name": "attributes",
291
+ "type": "text",
292
+ "primaryKey": false,
293
+ "notNull": true,
294
+ "autoincrement": false,
295
+ "default": "'{}'"
296
+ }
297
+ },
298
+ "indexes": {
299
+ "events_conn_name_start": {
300
+ "name": "events_conn_name_start",
301
+ "columns": ["connector_id", "name", "start_ts"],
302
+ "isUnique": false
303
+ }
304
+ },
305
+ "foreignKeys": {},
306
+ "compositePrimaryKeys": {},
307
+ "uniqueConstraints": {},
308
+ "checkConstraints": {}
309
+ },
310
+ "metrics": {
311
+ "name": "metrics",
312
+ "columns": {
313
+ "id": {
314
+ "name": "id",
315
+ "type": "integer",
316
+ "primaryKey": true,
317
+ "notNull": true,
318
+ "autoincrement": true
319
+ },
320
+ "connector_id": {
321
+ "name": "connector_id",
322
+ "type": "text",
323
+ "primaryKey": false,
324
+ "notNull": true,
325
+ "autoincrement": false
326
+ },
327
+ "name": {
328
+ "name": "name",
329
+ "type": "text",
330
+ "primaryKey": false,
331
+ "notNull": true,
332
+ "autoincrement": false
333
+ },
334
+ "ts": {
335
+ "name": "ts",
336
+ "type": "integer",
337
+ "primaryKey": false,
338
+ "notNull": true,
339
+ "autoincrement": false
340
+ },
341
+ "value": {
342
+ "name": "value",
343
+ "type": "real",
344
+ "primaryKey": false,
345
+ "notNull": true,
346
+ "autoincrement": false
347
+ },
348
+ "attributes": {
349
+ "name": "attributes",
350
+ "type": "text",
351
+ "primaryKey": false,
352
+ "notNull": true,
353
+ "autoincrement": false,
354
+ "default": "'{}'"
355
+ }
356
+ },
357
+ "indexes": {
358
+ "metrics_conn_name_ts": {
359
+ "name": "metrics_conn_name_ts",
360
+ "columns": ["connector_id", "name", "ts"],
361
+ "isUnique": false
362
+ }
363
+ },
364
+ "foreignKeys": {},
365
+ "compositePrimaryKeys": {},
366
+ "uniqueConstraints": {},
367
+ "checkConstraints": {}
368
+ },
369
+ "rollup_watermarks": {
370
+ "name": "rollup_watermarks",
371
+ "columns": {
372
+ "connector_id": {
373
+ "name": "connector_id",
374
+ "type": "text",
375
+ "primaryKey": false,
376
+ "notNull": true,
377
+ "autoincrement": false
378
+ },
379
+ "resource": {
380
+ "name": "resource",
381
+ "type": "text",
382
+ "primaryKey": false,
383
+ "notNull": true,
384
+ "autoincrement": false
385
+ },
386
+ "watermark": {
387
+ "name": "watermark",
388
+ "type": "integer",
389
+ "primaryKey": false,
390
+ "notNull": true,
391
+ "autoincrement": false
392
+ }
393
+ },
394
+ "indexes": {},
395
+ "foreignKeys": {},
396
+ "compositePrimaryKeys": {
397
+ "rollup_watermarks_connector_id_resource_pk": {
398
+ "columns": ["connector_id", "resource"],
399
+ "name": "rollup_watermarks_connector_id_resource_pk"
400
+ }
401
+ },
402
+ "uniqueConstraints": {},
403
+ "checkConstraints": {}
404
+ },
405
+ "rollups": {
406
+ "name": "rollups",
407
+ "columns": {
408
+ "connector_id": {
409
+ "name": "connector_id",
410
+ "type": "text",
411
+ "primaryKey": false,
412
+ "notNull": true,
413
+ "autoincrement": false
414
+ },
415
+ "resource": {
416
+ "name": "resource",
417
+ "type": "text",
418
+ "primaryKey": false,
419
+ "notNull": true,
420
+ "autoincrement": false
421
+ },
422
+ "field": {
423
+ "name": "field",
424
+ "type": "text",
425
+ "primaryKey": false,
426
+ "notNull": true,
427
+ "autoincrement": false,
428
+ "default": "''"
429
+ },
430
+ "granularity": {
431
+ "name": "granularity",
432
+ "type": "text",
433
+ "primaryKey": false,
434
+ "notNull": true,
435
+ "autoincrement": false
436
+ },
437
+ "dims_key": {
438
+ "name": "dims_key",
439
+ "type": "text",
440
+ "primaryKey": false,
441
+ "notNull": true,
442
+ "autoincrement": false,
443
+ "default": "''"
444
+ },
445
+ "dims": {
446
+ "name": "dims",
447
+ "type": "text",
448
+ "primaryKey": false,
449
+ "notNull": true,
450
+ "autoincrement": false,
451
+ "default": "'{}'"
452
+ },
453
+ "bucket_start": {
454
+ "name": "bucket_start",
455
+ "type": "integer",
456
+ "primaryKey": false,
457
+ "notNull": true,
458
+ "autoincrement": false
459
+ },
460
+ "partials": {
461
+ "name": "partials",
462
+ "type": "text",
463
+ "primaryKey": false,
464
+ "notNull": true,
465
+ "autoincrement": false
466
+ }
467
+ },
468
+ "indexes": {
469
+ "rollups_conn_resource_field": {
470
+ "name": "rollups_conn_resource_field",
471
+ "columns": ["connector_id", "resource", "field"],
472
+ "isUnique": false
473
+ }
474
+ },
475
+ "foreignKeys": {},
476
+ "compositePrimaryKeys": {
477
+ "rollups_connector_id_resource_field_granularity_dims_key_bucket_start_pk": {
478
+ "columns": [
479
+ "connector_id",
480
+ "resource",
481
+ "field",
482
+ "granularity",
483
+ "dims_key",
484
+ "bucket_start"
485
+ ],
486
+ "name": "rollups_connector_id_resource_field_granularity_dims_key_bucket_start_pk"
487
+ }
488
+ },
489
+ "uniqueConstraints": {},
490
+ "checkConstraints": {}
491
+ },
492
+ "sync_state": {
493
+ "name": "sync_state",
494
+ "columns": {
495
+ "id": {
496
+ "name": "id",
497
+ "type": "integer",
498
+ "primaryKey": true,
499
+ "notNull": true,
500
+ "autoincrement": false
501
+ },
502
+ "status": {
503
+ "name": "status",
504
+ "type": "text",
505
+ "primaryKey": false,
506
+ "notNull": true,
507
+ "autoincrement": false
508
+ },
509
+ "queued_at": {
510
+ "name": "queued_at",
511
+ "type": "text",
512
+ "primaryKey": false,
513
+ "notNull": false,
514
+ "autoincrement": false
515
+ },
516
+ "started_at": {
517
+ "name": "started_at",
518
+ "type": "text",
519
+ "primaryKey": false,
520
+ "notNull": false,
521
+ "autoincrement": false
522
+ },
523
+ "last_sync_at": {
524
+ "name": "last_sync_at",
525
+ "type": "text",
526
+ "primaryKey": false,
527
+ "notNull": false,
528
+ "autoincrement": false
529
+ },
530
+ "last_error": {
531
+ "name": "last_error",
532
+ "type": "text",
533
+ "primaryKey": false,
534
+ "notNull": false,
535
+ "autoincrement": false
536
+ }
537
+ },
538
+ "indexes": {},
539
+ "foreignKeys": {},
540
+ "compositePrimaryKeys": {},
541
+ "uniqueConstraints": {},
542
+ "checkConstraints": {}
543
+ }
544
+ },
545
+ "views": {},
546
+ "enums": {},
547
+ "_meta": {
548
+ "schemas": {},
549
+ "tables": {},
550
+ "columns": {}
551
+ },
552
+ "internal": {
553
+ "indexes": {}
554
+ }
555
+ }
@@ -29,6 +29,13 @@
29
29
  "when": 1781148513026,
30
30
  "tag": "0003_milky_morbius",
31
31
  "breakpoints": true
32
+ },
33
+ {
34
+ "idx": 4,
35
+ "version": "6",
36
+ "when": 1782705831411,
37
+ "tag": "0004_neat_swarm",
38
+ "breakpoints": true
32
39
  }
33
40
  ]
34
41
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rawdash/adapter-libsql",
3
- "version": "0.28.0",
3
+ "version": "0.29.0",
4
4
  "description": "Rawdash libSQL/Turso storage adapter",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -25,7 +25,7 @@
25
25
  "dependencies": {
26
26
  "kysely": "^0.29.0",
27
27
  "kysely-libsql": "^0.7.0",
28
- "@rawdash/core": "0.28.0"
28
+ "@rawdash/core": "0.29.0"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "@libsql/client": ">=0.14.0 <1.0.0"