@mastra/libsql 1.16.0 → 1.17.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createClient } from '@libsql/client';
2
2
  import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
3
- import { createVectorErrorId, AgentsStorage, AGENTS_SCHEMA, TABLE_AGENTS, AGENT_VERSIONS_SCHEMA, TABLE_AGENT_VERSIONS, createStorageErrorId, normalizePerPage, calculatePagination, BackgroundTasksStorage, TABLE_BACKGROUND_TASKS, TABLE_SCHEMAS, BlobStore, TABLE_SKILL_BLOBS, SKILL_BLOBS_SCHEMA, ChannelsStorage, TABLE_CHANNEL_INSTALLATIONS, TABLE_CHANNEL_CONFIG, DatasetsStorage, DATASETS_SCHEMA, TABLE_DATASETS, DATASET_ITEMS_SCHEMA, TABLE_DATASET_ITEMS, DATASET_VERSIONS_SCHEMA, TABLE_DATASET_VERSIONS, TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS, ensureDate, safelyParseJSON, hasErrorCode, ExperimentsStorage, EXPERIMENTS_SCHEMA, EXPERIMENT_RESULTS_SCHEMA, FavoritesStorage, FAVORITES_SCHEMA, TABLE_FAVORITES, TABLE_SKILLS, HarnessStorage, TABLE_HARNESS_SESSIONS, MCPClientsStorage, MCP_CLIENTS_SCHEMA, TABLE_MCP_CLIENTS, MCP_CLIENT_VERSIONS_SCHEMA, TABLE_MCP_CLIENT_VERSIONS, MCPServersStorage, MCP_SERVERS_SCHEMA, TABLE_MCP_SERVERS, MCP_SERVER_VERSIONS_SCHEMA, TABLE_MCP_SERVER_VERSIONS, MemoryStorage, TABLE_THREADS, TABLE_RESOURCES, TABLE_MESSAGES, OBSERVATIONAL_MEMORY_TABLE_SCHEMA, NotificationsStorage, TABLE_NOTIFICATIONS, ObservabilityStorage, TABLE_SPANS, SPAN_SCHEMA, listTracesArgsSchema, toTraceSpans, PromptBlocksStorage, PROMPT_BLOCKS_SCHEMA, TABLE_PROMPT_BLOCKS, PROMPT_BLOCK_VERSIONS_SCHEMA, TABLE_PROMPT_BLOCK_VERSIONS, SchedulesStorage, TABLE_SCHEDULE_TRIGGERS, TABLE_SCHEDULES, ScorerDefinitionsStorage, SCORER_DEFINITIONS_SCHEMA, TABLE_SCORER_DEFINITIONS, SCORER_DEFINITION_VERSIONS_SCHEMA, TABLE_SCORER_DEFINITION_VERSIONS, ScoresStorage, TABLE_SCORERS, SCORERS_SCHEMA, transformScoreRow, SkillsStorage, SKILLS_SCHEMA, SKILL_VERSIONS_SCHEMA, TABLE_SKILL_VERSIONS, ThreadStateStorage, TABLE_THREAD_STATE, THREAD_STATE_SCHEMA, ToolProviderConnectionsStorage, TOOL_PROVIDER_CONNECTIONS_SCHEMA, TABLE_TOOL_PROVIDER_CONNECTIONS, WorkflowsStorage, TABLE_WORKFLOW_SNAPSHOT, WorkspacesStorage, WORKSPACES_SCHEMA, TABLE_WORKSPACES, WORKSPACE_VERSIONS_SCHEMA, TABLE_WORKSPACE_VERSIONS, MastraCompositeStore, getSqlType, parseDuration, normalizeScheduleTarget, TraceStatus, mergeWorkflowStepResult } from '@mastra/core/storage';
3
+ import { createVectorErrorId, AgentsStorage, AGENTS_SCHEMA, TABLE_AGENTS, AGENT_VERSIONS_SCHEMA, TABLE_AGENT_VERSIONS, createStorageErrorId, normalizePerPage, calculatePagination, BackgroundTasksStorage, TABLE_BACKGROUND_TASKS, TABLE_SCHEMAS, BlobStore, TABLE_SKILL_BLOBS, SKILL_BLOBS_SCHEMA, ChannelsStorage, TABLE_CHANNEL_INSTALLATIONS, TABLE_CHANNEL_CONFIG, DatasetsStorage, DATASETS_SCHEMA, TABLE_DATASETS, DATASET_ITEMS_SCHEMA, TABLE_DATASET_ITEMS, DATASET_VERSIONS_SCHEMA, TABLE_DATASET_VERSIONS, TABLE_EXPERIMENTS, TABLE_EXPERIMENT_RESULTS, ensureDate, safelyParseJSON, hasErrorCode, ExperimentsStorage, EXPERIMENTS_SCHEMA, EXPERIMENT_RESULTS_SCHEMA, FavoritesStorage, FAVORITES_SCHEMA, TABLE_FAVORITES, TABLE_SKILLS, HarnessStorage, TABLE_HARNESS_SESSIONS, MCPClientsStorage, MCP_CLIENTS_SCHEMA, TABLE_MCP_CLIENTS, MCP_CLIENT_VERSIONS_SCHEMA, TABLE_MCP_CLIENT_VERSIONS, MCPServersStorage, MCP_SERVERS_SCHEMA, TABLE_MCP_SERVERS, MCP_SERVER_VERSIONS_SCHEMA, TABLE_MCP_SERVER_VERSIONS, MemoryStorage, TABLE_THREADS, TABLE_RESOURCES, TABLE_MESSAGES, OBSERVATIONAL_MEMORY_TABLE_SCHEMA, NotificationsStorage, TABLE_NOTIFICATIONS, ObservabilityStorage, TABLE_SPANS, SPAN_SCHEMA, listTracesArgsSchema, toTraceSpans, PromptBlocksStorage, PROMPT_BLOCKS_SCHEMA, TABLE_PROMPT_BLOCKS, PROMPT_BLOCK_VERSIONS_SCHEMA, TABLE_PROMPT_BLOCK_VERSIONS, SchedulesStorage, TABLE_SCHEDULE_TRIGGERS, TABLE_SCHEDULES, ScorerDefinitionsStorage, SCORER_DEFINITIONS_SCHEMA, TABLE_SCORER_DEFINITIONS, SCORER_DEFINITION_VERSIONS_SCHEMA, TABLE_SCORER_DEFINITION_VERSIONS, ScoresStorage, TABLE_SCORERS, SCORERS_SCHEMA, transformScoreRow, SkillsStorage, SKILLS_SCHEMA, SKILL_VERSIONS_SCHEMA, TABLE_SKILL_VERSIONS, ThreadStateStorage, TABLE_THREAD_STATE, THREAD_STATE_SCHEMA, ToolProviderConnectionsStorage, TOOL_PROVIDER_CONNECTIONS_SCHEMA, TABLE_TOOL_PROVIDER_CONNECTIONS, WorkflowsStorage, TABLE_WORKFLOW_SNAPSHOT, WorkspacesStorage, WORKSPACES_SCHEMA, TABLE_WORKSPACES, WORKSPACE_VERSIONS_SCHEMA, TABLE_WORKSPACE_VERSIONS, FactoryStorage, MastraCompositeStore, getSqlType, parseDuration, normalizeScheduleTarget, UniqueViolationError, TraceStatus, mergeWorkflowStepResult } from '@mastra/core/storage';
4
4
  import { parseSqlIdentifier, parseFieldKey } from '@mastra/core/utils';
5
5
  import { MastraVector, validateTopK, validateUpsertInput } from '@mastra/core/vector';
6
6
  import { BaseFilterTranslator } from '@mastra/core/vector/filter';
@@ -1196,26 +1196,28 @@ var LibSQLVector = class extends MastraVector {
1196
1196
  });
1197
1197
  }
1198
1198
  };
1199
+ var MAX_DEPTH = 100;
1199
1200
  var safeStringify = (value) => {
1200
1201
  const ancestors = /* @__PURE__ */ new Set();
1201
- const sanitize = (val) => {
1202
+ const sanitize = (val, depth = 0) => {
1202
1203
  if (val === null || val === void 0) return val;
1203
1204
  if (typeof val === "function") return void 0;
1204
1205
  if (typeof val === "symbol") return void 0;
1205
1206
  if (typeof val === "bigint") return val.toString();
1206
1207
  if (typeof val !== "object") return val;
1208
+ if (depth > MAX_DEPTH) return "[Max depth exceeded]";
1207
1209
  if (ancestors.has(val)) return void 0;
1208
1210
  if (typeof val.toJSON === "function") {
1209
- return sanitize(val.toJSON());
1211
+ return sanitize(val.toJSON(), depth + 1);
1210
1212
  }
1211
1213
  ancestors.add(val);
1212
1214
  try {
1213
1215
  if (Array.isArray(val)) {
1214
- return val.map((item) => sanitize(item));
1216
+ return val.map((item) => sanitize(item, depth + 1));
1215
1217
  }
1216
1218
  const result = {};
1217
1219
  for (const key of Object.keys(val)) {
1218
- const sanitized = sanitize(val[key]);
1220
+ const sanitized = sanitize(val[key], depth + 1);
1219
1221
  if (sanitized !== void 0) {
1220
1222
  result[key] = sanitized;
1221
1223
  }
@@ -13345,6 +13347,388 @@ var WorkspacesLibSQL = class extends WorkspacesStorage {
13345
13347
  };
13346
13348
  }
13347
13349
  };
13350
+ var IDENTIFIER_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
13351
+ var COLUMN_DDL = {
13352
+ text: "TEXT",
13353
+ bigint: "INTEGER",
13354
+ integer: "INTEGER",
13355
+ boolean: "INTEGER",
13356
+ json: "TEXT",
13357
+ timestamp: "TEXT",
13358
+ "uuid-pk": "TEXT"
13359
+ };
13360
+ function assertIdentifier(kind, name) {
13361
+ if (!IDENTIFIER_RE.test(name)) {
13362
+ throw new Error(`LibSQLFactoryStorage: invalid ${kind} identifier '${name}'`);
13363
+ }
13364
+ }
13365
+ function isUniqueViolation(error) {
13366
+ const message = error instanceof Error ? error.message : String(error);
13367
+ return message.includes("UNIQUE constraint failed") || message.includes("SQLITE_CONSTRAINT");
13368
+ }
13369
+ function primaryKeyOf(schema) {
13370
+ const pks = Object.entries(schema.columns).filter(([, spec]) => spec.type === "uuid-pk" || spec.primaryKey);
13371
+ if (pks.length !== 1) {
13372
+ throw new Error(
13373
+ `LibSQLFactoryStorage: collection '${schema.name}' must declare exactly one primary key (found ${pks.length})`
13374
+ );
13375
+ }
13376
+ return pks[0][0];
13377
+ }
13378
+ function assertUpsertConflict(schema, conflictKeys, row) {
13379
+ const keys = new Set(conflictKeys);
13380
+ if (keys.size !== conflictKeys.length || conflictKeys.some((key) => row[key] === void 0)) {
13381
+ throw new Error(
13382
+ `LibSQLFactoryStorage: upsert conflict keys for '${schema.name}' must be unique and present in the row`
13383
+ );
13384
+ }
13385
+ const primaryKey = primaryKeyOf(schema);
13386
+ const candidates = [{ columns: [primaryKey] }, ...schema.uniqueIndexes ?? []];
13387
+ const matches = candidates.some((candidate) => {
13388
+ if (candidate.columns.length !== keys.size || candidate.columns.some((column) => !keys.has(column))) return false;
13389
+ if ("whereNotNull" in candidate && candidate.whereNotNull && row[candidate.whereNotNull] == null) return false;
13390
+ if ("whereNull" in candidate && candidate.whereNull && row[candidate.whereNull] != null) return false;
13391
+ return true;
13392
+ });
13393
+ if (!matches) {
13394
+ throw new Error(
13395
+ `LibSQLFactoryStorage: upsert conflict keys [${conflictKeys.join(", ")}] do not match an applicable primary key or unique index on '${schema.name}'`
13396
+ );
13397
+ }
13398
+ }
13399
+ function serializeDefault(value) {
13400
+ if (typeof value === "string") return `'${value.replace(/'/g, "''")}'`;
13401
+ if (typeof value === "boolean") return value ? "1" : "0";
13402
+ return String(value);
13403
+ }
13404
+ var Mutex = class {
13405
+ #tail = Promise.resolve();
13406
+ run(fn) {
13407
+ const result = this.#tail.then(fn, fn);
13408
+ this.#tail = result.catch(() => {
13409
+ });
13410
+ return result;
13411
+ }
13412
+ };
13413
+ var LibSQLFactoryStorageOps = class {
13414
+ #client;
13415
+ #schemas;
13416
+ #writeMutex = new Mutex();
13417
+ constructor(client, schemas) {
13418
+ this.#client = client;
13419
+ this.#schemas = schemas;
13420
+ }
13421
+ #schema(collection) {
13422
+ const schema = this.#schemas.get(collection);
13423
+ if (!schema) {
13424
+ throw new Error(
13425
+ `LibSQLFactoryStorage: unknown collection '${collection}' \u2014 register it via ensureCollections() first`
13426
+ );
13427
+ }
13428
+ return schema;
13429
+ }
13430
+ #column(schema, column) {
13431
+ const spec = schema.columns[column];
13432
+ if (!spec) {
13433
+ throw new Error(`LibSQLFactoryStorage: unknown column '${column}' on collection '${schema.name}'`);
13434
+ }
13435
+ return spec;
13436
+ }
13437
+ #serialize(spec, value) {
13438
+ if (value === null || value === void 0) return null;
13439
+ switch (spec.type) {
13440
+ case "timestamp":
13441
+ return value instanceof Date ? value.toISOString() : String(value);
13442
+ case "boolean":
13443
+ return value ? 1 : 0;
13444
+ case "json":
13445
+ return JSON.stringify(value);
13446
+ case "bigint":
13447
+ case "integer":
13448
+ return Number(value);
13449
+ default:
13450
+ return String(value);
13451
+ }
13452
+ }
13453
+ #deserializeRow(schema, raw) {
13454
+ const row = {};
13455
+ for (const [name, spec] of Object.entries(schema.columns)) {
13456
+ const value = raw[name];
13457
+ if (value === null || value === void 0) {
13458
+ row[name] = null;
13459
+ continue;
13460
+ }
13461
+ switch (spec.type) {
13462
+ case "timestamp":
13463
+ row[name] = new Date(String(value));
13464
+ break;
13465
+ case "boolean":
13466
+ row[name] = Number(value) === 1;
13467
+ break;
13468
+ case "json":
13469
+ row[name] = JSON.parse(String(value));
13470
+ break;
13471
+ case "bigint":
13472
+ case "integer":
13473
+ row[name] = Number(value);
13474
+ break;
13475
+ default:
13476
+ row[name] = String(value);
13477
+ }
13478
+ }
13479
+ return row;
13480
+ }
13481
+ /** Builds `WHERE` SQL (without the keyword). `{}` yields a match-all clause. */
13482
+ #buildWhere(schema, where) {
13483
+ const clauses = [];
13484
+ const args = [];
13485
+ for (const [column, condition] of Object.entries(where)) {
13486
+ const spec = this.#column(schema, column);
13487
+ if (condition !== null && typeof condition === "object" && !(condition instanceof Date) && "in" in condition) {
13488
+ if (condition.in.length === 0) {
13489
+ clauses.push("1 = 0");
13490
+ continue;
13491
+ }
13492
+ const nonNull = condition.in.filter((value) => value !== null);
13493
+ const includesNull = nonNull.length !== condition.in.length;
13494
+ const inClause = nonNull.length > 0 ? `"${column}" IN (${nonNull.map(() => "?").join(", ")})` : void 0;
13495
+ clauses.push(
13496
+ inClause && includesNull ? `(${inClause} OR "${column}" IS NULL)` : inClause ?? `"${column}" IS NULL`
13497
+ );
13498
+ args.push(...nonNull.map((value) => this.#serialize(spec, value)));
13499
+ } else if (condition === null) {
13500
+ clauses.push(`"${column}" IS NULL`);
13501
+ } else {
13502
+ clauses.push(`"${column}" = ?`);
13503
+ args.push(this.#serialize(spec, condition));
13504
+ }
13505
+ }
13506
+ return { sql: clauses.length > 0 ? clauses.join(" AND ") : "1 = 1", args };
13507
+ }
13508
+ /** Keyset condition: rows strictly after `cursor.values` in the `orderBy` order. */
13509
+ #buildCursor(schema, orderBy, values) {
13510
+ if (values.length !== orderBy.length) {
13511
+ throw new Error(
13512
+ `LibSQLFactoryStorage: cursor has ${values.length} values but orderBy has ${orderBy.length} columns`
13513
+ );
13514
+ }
13515
+ const branches = [];
13516
+ const args = [];
13517
+ for (let i = 0; i < orderBy.length; i++) {
13518
+ const parts = [];
13519
+ for (let j = 0; j < i; j++) {
13520
+ const [column2] = orderBy[j];
13521
+ parts.push(`"${column2}" = ?`);
13522
+ args.push(this.#serialize(this.#column(schema, column2), values[j]));
13523
+ }
13524
+ const [column, dir] = orderBy[i];
13525
+ parts.push(`"${column}" ${dir === "desc" ? "<" : ">"} ?`);
13526
+ args.push(this.#serialize(this.#column(schema, column), values[i]));
13527
+ branches.push(`(${parts.join(" AND ")})`);
13528
+ }
13529
+ return { sql: `(${branches.join(" OR ")})`, args };
13530
+ }
13531
+ async #select(collection, where, opts) {
13532
+ const schema = this.#schema(collection);
13533
+ const filter = this.#buildWhere(schema, where);
13534
+ let sql = `SELECT * FROM "${schema.name}" WHERE ${filter.sql}`;
13535
+ const args = [...filter.args];
13536
+ if (opts?.cursor) {
13537
+ if (!opts.orderBy || opts.orderBy.length === 0) {
13538
+ throw new Error("LibSQLFactoryStorage: cursor pagination requires orderBy");
13539
+ }
13540
+ const cursor = this.#buildCursor(schema, opts.orderBy, opts.cursor.values);
13541
+ sql += ` AND ${cursor.sql}`;
13542
+ args.push(...cursor.args);
13543
+ }
13544
+ if (opts?.orderBy && opts.orderBy.length > 0) {
13545
+ const order = opts.orderBy.map(([column, dir]) => {
13546
+ this.#column(schema, column);
13547
+ return `"${column}" ${dir === "desc" ? "DESC" : "ASC"}`;
13548
+ }).join(", ");
13549
+ sql += ` ORDER BY ${order}`;
13550
+ }
13551
+ if (opts?.limit !== void 0) {
13552
+ sql += ` LIMIT ?`;
13553
+ args.push(opts.limit);
13554
+ }
13555
+ const result = await this.#client.execute({ sql, args });
13556
+ return result.rows.map((raw) => this.#deserializeRow(schema, raw));
13557
+ }
13558
+ async findOne(collection, where) {
13559
+ const rows = await this.#select(collection, where, { limit: 1 });
13560
+ return rows[0] ?? null;
13561
+ }
13562
+ async findMany(collection, where, opts) {
13563
+ return this.#select(collection, where, opts);
13564
+ }
13565
+ async insertOne(collection, row) {
13566
+ const schema = this.#schema(collection);
13567
+ const pk = primaryKeyOf(schema);
13568
+ const values = { ...row };
13569
+ if (schema.columns[pk].type === "uuid-pk" && values[pk] === void 0) {
13570
+ values[pk] = randomUUID();
13571
+ }
13572
+ const columns = Object.keys(values).filter((column) => values[column] !== void 0);
13573
+ for (const column of columns) this.#column(schema, column);
13574
+ const sql = `INSERT INTO "${schema.name}" (${columns.map((c) => `"${c}"`).join(", ")}) VALUES (${columns.map(() => "?").join(", ")})`;
13575
+ const args = columns.map((column) => this.#serialize(this.#column(schema, column), values[column]));
13576
+ try {
13577
+ await this.#client.execute({ sql, args });
13578
+ } catch (error) {
13579
+ if (isUniqueViolation(error)) throw new UniqueViolationError(collection, { cause: error });
13580
+ throw error;
13581
+ }
13582
+ const inserted = await this.findOne(collection, { [pk]: values[pk] });
13583
+ if (!inserted) throw new Error(`LibSQLFactoryStorage: failed to read back inserted row from '${collection}'`);
13584
+ return inserted;
13585
+ }
13586
+ async upsertOne(collection, conflictKeys, row) {
13587
+ const schema = this.#schema(collection);
13588
+ const pk = primaryKeyOf(schema);
13589
+ assertUpsertConflict(schema, conflictKeys, row);
13590
+ const keyWhere = Object.fromEntries(conflictKeys.map((key) => [key, row[key]]));
13591
+ let lastError;
13592
+ for (let attempt = 0; attempt < 2; attempt++) {
13593
+ const existing = await this.findOne(collection, keyWhere);
13594
+ if (existing) {
13595
+ const set = Object.fromEntries(
13596
+ Object.entries(row).filter(
13597
+ ([column, value]) => value !== void 0 && column !== pk && !conflictKeys.includes(column)
13598
+ )
13599
+ );
13600
+ if (Object.keys(set).length > 0) {
13601
+ await this.updateMany(collection, { [pk]: existing[pk] }, set);
13602
+ }
13603
+ const updated = await this.findOne(collection, { [pk]: existing[pk] });
13604
+ if (!updated) continue;
13605
+ return updated;
13606
+ }
13607
+ try {
13608
+ return await this.insertOne(collection, row);
13609
+ } catch (error) {
13610
+ if (!(error instanceof UniqueViolationError)) throw error;
13611
+ lastError = error;
13612
+ }
13613
+ }
13614
+ throw lastError ?? new Error(`LibSQLFactoryStorage: upsert into '${collection}' did not converge`);
13615
+ }
13616
+ async updateMany(collection, where, set) {
13617
+ const schema = this.#schema(collection);
13618
+ const columns = Object.keys(set).filter((column) => set[column] !== void 0);
13619
+ if (columns.length === 0) return 0;
13620
+ const filter = this.#buildWhere(schema, where);
13621
+ const sql = `UPDATE "${schema.name}" SET ${columns.map((c) => `"${c}" = ?`).join(", ")} WHERE ${filter.sql}`;
13622
+ const args = [...columns.map((column) => this.#serialize(this.#column(schema, column), set[column])), ...filter.args];
13623
+ const result = await this.#client.execute({ sql, args });
13624
+ return result.rowsAffected;
13625
+ }
13626
+ async deleteMany(collection, where) {
13627
+ const schema = this.#schema(collection);
13628
+ const filter = this.#buildWhere(schema, where);
13629
+ const result = await this.#client.execute({
13630
+ sql: `DELETE FROM "${schema.name}" WHERE ${filter.sql}`,
13631
+ args: filter.args
13632
+ });
13633
+ return result.rowsAffected;
13634
+ }
13635
+ async updateAtomic(collection, where, fn) {
13636
+ const schema = this.#schema(collection);
13637
+ const pk = primaryKeyOf(schema);
13638
+ return this.#writeMutex.run(async () => {
13639
+ const row = await this.findOne(collection, where);
13640
+ if (!row) return null;
13641
+ const patch = await fn(row);
13642
+ if (patch === null) return row;
13643
+ const pkWhere = { [pk]: row[pk] };
13644
+ await this.updateMany(collection, pkWhere, patch);
13645
+ return this.findOne(collection, pkWhere);
13646
+ });
13647
+ }
13648
+ };
13649
+ var LibSQLFactoryStorage = class extends FactoryStorage {
13650
+ ops;
13651
+ #client;
13652
+ #config;
13653
+ #schemas = /* @__PURE__ */ new Map();
13654
+ #mastraStorage;
13655
+ constructor(config) {
13656
+ super();
13657
+ this.#config = config;
13658
+ const isLocalDb = config.url.startsWith("file:") || config.url.includes(":memory:");
13659
+ this.#client = createClient({
13660
+ url: config.url,
13661
+ ...config.authToken ? { authToken: config.authToken } : {},
13662
+ ...isLocalDb ? { timeout: DEFAULT_CONNECTION_TIMEOUT_MS } : {}
13663
+ });
13664
+ this.ops = new LibSQLFactoryStorageOps(this.#client, this.#schemas);
13665
+ }
13666
+ getMastraStorage() {
13667
+ this.#mastraStorage ??= new LibSQLStore({
13668
+ id: this.#config.id ?? "libsql-factory",
13669
+ client: this.#client,
13670
+ ...this.#config.retention ? { retention: this.#config.retention } : {}
13671
+ });
13672
+ return this.#mastraStorage;
13673
+ }
13674
+ async initStorage() {
13675
+ await this.#client.execute("SELECT 1");
13676
+ }
13677
+ async ensureCollections(schemas) {
13678
+ for (const schema of schemas) {
13679
+ await this.#ensureCollection(schema);
13680
+ this.#schemas.set(schema.name, schema);
13681
+ }
13682
+ }
13683
+ async close() {
13684
+ this.#client.close();
13685
+ }
13686
+ authDatabase() {
13687
+ return { dialect: "libsql", client: this.#client };
13688
+ }
13689
+ #columnDdl(name, spec) {
13690
+ assertIdentifier("column", name);
13691
+ let ddl = `"${name}" ${COLUMN_DDL[spec.type]}`;
13692
+ if (spec.type === "uuid-pk" || spec.primaryKey) ddl += " PRIMARY KEY";
13693
+ if (!spec.nullable && spec.type !== "uuid-pk" && !spec.primaryKey) ddl += " NOT NULL";
13694
+ if (spec.default !== void 0) ddl += ` DEFAULT ${serializeDefault(spec.default)}`;
13695
+ return ddl;
13696
+ }
13697
+ async #ensureCollection(schema) {
13698
+ assertIdentifier("collection", schema.name);
13699
+ primaryKeyOf(schema);
13700
+ const columns = Object.entries(schema.columns).map(([name, spec]) => this.#columnDdl(name, spec));
13701
+ await this.#client.execute(`CREATE TABLE IF NOT EXISTS "${schema.name}" (${columns.join(", ")})`);
13702
+ const info = await this.#client.execute(`PRAGMA table_info("${schema.name}")`);
13703
+ const existing = new Set(info.rows.map((row) => String(row.name)));
13704
+ for (const [name, spec] of Object.entries(schema.columns)) {
13705
+ if (existing.has(name)) continue;
13706
+ await this.#client.execute(`ALTER TABLE "${schema.name}" ADD COLUMN ${this.#columnDdl(name, spec)}`);
13707
+ }
13708
+ for (const index of schema.uniqueIndexes ?? []) {
13709
+ assertIdentifier("index", index.name);
13710
+ index.columns.forEach((column) => assertIdentifier("column", column));
13711
+ let where = "";
13712
+ if (index.whereNotNull) {
13713
+ assertIdentifier("column", index.whereNotNull);
13714
+ where = ` WHERE "${index.whereNotNull}" IS NOT NULL`;
13715
+ } else if (index.whereNull) {
13716
+ assertIdentifier("column", index.whereNull);
13717
+ where = ` WHERE "${index.whereNull}" IS NULL`;
13718
+ }
13719
+ await this.#client.execute(
13720
+ `CREATE UNIQUE INDEX IF NOT EXISTS "${index.name}" ON "${schema.name}" (${index.columns.map((c) => `"${c}"`).join(", ")})${where}`
13721
+ );
13722
+ }
13723
+ for (const index of schema.indexes ?? []) {
13724
+ assertIdentifier("index", index.name);
13725
+ index.columns.forEach((column) => assertIdentifier("column", column));
13726
+ await this.#client.execute(
13727
+ `CREATE INDEX IF NOT EXISTS "${index.name}" ON "${schema.name}" (${index.columns.map((c) => `"${c}"`).join(", ")})`
13728
+ );
13729
+ }
13730
+ }
13731
+ };
13348
13732
 
13349
13733
  // src/storage/index.ts
13350
13734
  var DEFAULT_LOCAL_CACHE_SIZE = -16e3;
@@ -13628,6 +14012,6 @@ Example Complex Query:
13628
14012
  ]
13629
14013
  }`;
13630
14014
 
13631
- export { AgentsLibSQL, BackgroundTasksLibSQL, BlobsLibSQL, ChannelsLibSQL, DatasetsLibSQL, LibSQLStore as DefaultStorage, ExperimentsLibSQL, FavoritesLibSQL, HarnessLibSQL, LIBSQL_PROMPT, LibSQLStore, LibSQLVector, MCPClientsLibSQL, MCPServersLibSQL, MemoryLibSQL, NotificationsLibSQL, ObservabilityLibSQL, PromptBlocksLibSQL, SchedulesLibSQL, ScorerDefinitionsLibSQL, ScoresLibSQL, SkillsLibSQL, ThreadStateLibSQL, ToolProviderConnectionsLibSQL, WorkflowsLibSQL, WorkspacesLibSQL };
14015
+ export { AgentsLibSQL, BackgroundTasksLibSQL, BlobsLibSQL, ChannelsLibSQL, DatasetsLibSQL, LibSQLStore as DefaultStorage, ExperimentsLibSQL, FavoritesLibSQL, HarnessLibSQL, LIBSQL_PROMPT, LibSQLFactoryStorage, LibSQLStore, LibSQLVector, MCPClientsLibSQL, MCPServersLibSQL, MemoryLibSQL, NotificationsLibSQL, ObservabilityLibSQL, PromptBlocksLibSQL, SchedulesLibSQL, ScorerDefinitionsLibSQL, ScoresLibSQL, SkillsLibSQL, ThreadStateLibSQL, ToolProviderConnectionsLibSQL, WorkflowsLibSQL, WorkspacesLibSQL };
13632
14016
  //# sourceMappingURL=index.js.map
13633
14017
  //# sourceMappingURL=index.js.map