@mastra/libsql 0.10.2-alpha.0 → 0.10.2-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.
@@ -1,23 +1,23 @@
1
1
 
2
- > @mastra/libsql@0.10.2-alpha.0 build /home/runner/work/mastra/mastra/stores/libsql
2
+ > @mastra/libsql@0.10.2-alpha.1 build /home/runner/work/mastra/mastra/stores/libsql
3
3
  > tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting
4
4
 
5
5
  CLI Building entry: src/index.ts
6
6
  CLI Using tsconfig: tsconfig.json
7
7
  CLI tsup v8.5.0
8
8
  TSC Build start
9
- TSC ⚡️ Build success in 9535ms
9
+ TSC ⚡️ Build success in 10122ms
10
10
  DTS Build start
11
11
  CLI Target: es2022
12
12
  Analysis will use the bundled TypeScript version 5.8.3
13
13
  Writing package typings: /home/runner/work/mastra/mastra/stores/libsql/dist/_tsup-dts-rollup.d.ts
14
14
  Analysis will use the bundled TypeScript version 5.8.3
15
15
  Writing package typings: /home/runner/work/mastra/mastra/stores/libsql/dist/_tsup-dts-rollup.d.cts
16
- DTS ⚡️ Build success in 9079ms
16
+ DTS ⚡️ Build success in 11851ms
17
17
  CLI Cleaning output folder
18
18
  ESM Build start
19
19
  CJS Build start
20
- ESM dist/index.js 55.48 KB
21
- ESM ⚡️ Build success in 980ms
22
- CJS dist/index.cjs 55.76 KB
23
- CJS ⚡️ Build success in 980ms
20
+ ESM dist/index.js 57.43 KB
21
+ ESM ⚡️ Build success in 1740ms
22
+ CJS dist/index.cjs 57.72 KB
23
+ CJS ⚡️ Build success in 1740ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @mastra/libsql
2
2
 
3
+ ## 0.10.2-alpha.1
4
+
5
+ ### Patch Changes
6
+
7
+ - dffb67b: updated stores to add alter table and change tests
8
+ - Updated dependencies [f6fd25f]
9
+ - Updated dependencies [dffb67b]
10
+ - Updated dependencies [f1309d3]
11
+ - Updated dependencies [f7f8293]
12
+ - @mastra/core@0.10.4-alpha.1
13
+
3
14
  ## 0.10.2-alpha.0
4
15
 
5
16
  ### Patch Changes
@@ -89,6 +89,18 @@ declare class LibSQLStore extends MastraStorage {
89
89
  tableName: TABLE_NAMES;
90
90
  schema: Record<string, StorageColumn>;
91
91
  }): Promise<void>;
92
+ protected getSqlType(type: StorageColumn['type']): string;
93
+ /**
94
+ * Alters table schema to add columns if they don't exist
95
+ * @param tableName Name of the table
96
+ * @param schema Schema of the table
97
+ * @param ifNotExists Array of column names to add if they don't exist
98
+ */
99
+ alterTable({ tableName, schema, ifNotExists, }: {
100
+ tableName: TABLE_NAMES;
101
+ schema: Record<string, StorageColumn>;
102
+ ifNotExists: string[];
103
+ }): Promise<void>;
92
104
  clearTable({ tableName }: {
93
105
  tableName: TABLE_NAMES;
94
106
  }): Promise<void>;
@@ -89,6 +89,18 @@ declare class LibSQLStore extends MastraStorage {
89
89
  tableName: TABLE_NAMES;
90
90
  schema: Record<string, StorageColumn>;
91
91
  }): Promise<void>;
92
+ protected getSqlType(type: StorageColumn['type']): string;
93
+ /**
94
+ * Alters table schema to add columns if they don't exist
95
+ * @param tableName Name of the table
96
+ * @param schema Schema of the table
97
+ * @param ifNotExists Array of column names to add if they don't exist
98
+ */
99
+ alterTable({ tableName, schema, ifNotExists, }: {
100
+ tableName: TABLE_NAMES;
101
+ schema: Record<string, StorageColumn>;
102
+ ifNotExists: string[];
103
+ }): Promise<void>;
92
104
  clearTable({ tableName }: {
93
105
  tableName: TABLE_NAMES;
94
106
  }): Promise<void>;
package/dist/index.cjs CHANGED
@@ -851,6 +851,52 @@ var LibSQLStore = class extends storage.MastraStorage {
851
851
  throw error;
852
852
  }
853
853
  }
854
+ getSqlType(type) {
855
+ switch (type) {
856
+ case "bigint":
857
+ return "INTEGER";
858
+ // SQLite uses INTEGER for all integer sizes
859
+ case "jsonb":
860
+ return "TEXT";
861
+ // Store JSON as TEXT in SQLite
862
+ default:
863
+ return super.getSqlType(type);
864
+ }
865
+ }
866
+ /**
867
+ * Alters table schema to add columns if they don't exist
868
+ * @param tableName Name of the table
869
+ * @param schema Schema of the table
870
+ * @param ifNotExists Array of column names to add if they don't exist
871
+ */
872
+ async alterTable({
873
+ tableName,
874
+ schema,
875
+ ifNotExists
876
+ }) {
877
+ const parsedTableName = utils.parseSqlIdentifier(tableName, "table name");
878
+ try {
879
+ const pragmaQuery = `PRAGMA table_info(${parsedTableName})`;
880
+ const result = await this.client.execute(pragmaQuery);
881
+ const existingColumnNames = new Set(result.rows.map((row) => row.name.toLowerCase()));
882
+ for (const columnName of ifNotExists) {
883
+ if (!existingColumnNames.has(columnName.toLowerCase()) && schema[columnName]) {
884
+ const columnDef = schema[columnName];
885
+ const sqlType = this.getSqlType(columnDef.type);
886
+ const nullable = columnDef.nullable === false ? "NOT NULL" : "";
887
+ const defaultValue = columnDef.nullable === false ? this.getDefaultValue(columnDef.type) : "";
888
+ const alterSql = `ALTER TABLE ${parsedTableName} ADD COLUMN "${columnName}" ${sqlType} ${nullable} ${defaultValue}`.trim();
889
+ await this.client.execute(alterSql);
890
+ this.logger?.debug?.(`Added column ${columnName} to table ${parsedTableName}`);
891
+ }
892
+ }
893
+ } catch (error) {
894
+ this.logger?.error?.(
895
+ `Error altering table ${tableName}: ${error instanceof Error ? error.message : String(error)}`
896
+ );
897
+ throw new Error(`Failed to alter table ${tableName}: ${error}`);
898
+ }
899
+ }
854
900
  async clearTable({ tableName }) {
855
901
  const parsedTableName = utils.parseSqlIdentifier(tableName, "table name");
856
902
  try {
@@ -1076,6 +1122,10 @@ var LibSQLStore = class extends storage.MastraStorage {
1076
1122
  return updatedThread;
1077
1123
  }
1078
1124
  async deleteThread({ threadId }) {
1125
+ await this.client.execute({
1126
+ sql: `DELETE FROM ${storage.TABLE_MESSAGES} WHERE thread_id = ?`,
1127
+ args: [threadId]
1128
+ });
1079
1129
  await this.client.execute({
1080
1130
  sql: `DELETE FROM ${storage.TABLE_THREADS} WHERE id = ?`,
1081
1131
  args: [threadId]
@@ -1092,7 +1142,8 @@ var LibSQLStore = class extends storage.MastraStorage {
1092
1142
  content,
1093
1143
  role: row.role,
1094
1144
  createdAt: new Date(row.createdAt),
1095
- threadId: row.thread_id
1145
+ threadId: row.thread_id,
1146
+ resourceId: row.resourceId
1096
1147
  };
1097
1148
  if (row.type && row.type !== `v2`) result.type = row.type;
1098
1149
  return result;
package/dist/index.js CHANGED
@@ -849,6 +849,52 @@ var LibSQLStore = class extends MastraStorage {
849
849
  throw error;
850
850
  }
851
851
  }
852
+ getSqlType(type) {
853
+ switch (type) {
854
+ case "bigint":
855
+ return "INTEGER";
856
+ // SQLite uses INTEGER for all integer sizes
857
+ case "jsonb":
858
+ return "TEXT";
859
+ // Store JSON as TEXT in SQLite
860
+ default:
861
+ return super.getSqlType(type);
862
+ }
863
+ }
864
+ /**
865
+ * Alters table schema to add columns if they don't exist
866
+ * @param tableName Name of the table
867
+ * @param schema Schema of the table
868
+ * @param ifNotExists Array of column names to add if they don't exist
869
+ */
870
+ async alterTable({
871
+ tableName,
872
+ schema,
873
+ ifNotExists
874
+ }) {
875
+ const parsedTableName = parseSqlIdentifier(tableName, "table name");
876
+ try {
877
+ const pragmaQuery = `PRAGMA table_info(${parsedTableName})`;
878
+ const result = await this.client.execute(pragmaQuery);
879
+ const existingColumnNames = new Set(result.rows.map((row) => row.name.toLowerCase()));
880
+ for (const columnName of ifNotExists) {
881
+ if (!existingColumnNames.has(columnName.toLowerCase()) && schema[columnName]) {
882
+ const columnDef = schema[columnName];
883
+ const sqlType = this.getSqlType(columnDef.type);
884
+ const nullable = columnDef.nullable === false ? "NOT NULL" : "";
885
+ const defaultValue = columnDef.nullable === false ? this.getDefaultValue(columnDef.type) : "";
886
+ const alterSql = `ALTER TABLE ${parsedTableName} ADD COLUMN "${columnName}" ${sqlType} ${nullable} ${defaultValue}`.trim();
887
+ await this.client.execute(alterSql);
888
+ this.logger?.debug?.(`Added column ${columnName} to table ${parsedTableName}`);
889
+ }
890
+ }
891
+ } catch (error) {
892
+ this.logger?.error?.(
893
+ `Error altering table ${tableName}: ${error instanceof Error ? error.message : String(error)}`
894
+ );
895
+ throw new Error(`Failed to alter table ${tableName}: ${error}`);
896
+ }
897
+ }
852
898
  async clearTable({ tableName }) {
853
899
  const parsedTableName = parseSqlIdentifier(tableName, "table name");
854
900
  try {
@@ -1074,6 +1120,10 @@ var LibSQLStore = class extends MastraStorage {
1074
1120
  return updatedThread;
1075
1121
  }
1076
1122
  async deleteThread({ threadId }) {
1123
+ await this.client.execute({
1124
+ sql: `DELETE FROM ${TABLE_MESSAGES} WHERE thread_id = ?`,
1125
+ args: [threadId]
1126
+ });
1077
1127
  await this.client.execute({
1078
1128
  sql: `DELETE FROM ${TABLE_THREADS} WHERE id = ?`,
1079
1129
  args: [threadId]
@@ -1090,7 +1140,8 @@ var LibSQLStore = class extends MastraStorage {
1090
1140
  content,
1091
1141
  role: row.role,
1092
1142
  createdAt: new Date(row.createdAt),
1093
- threadId: row.thread_id
1143
+ threadId: row.thread_id,
1144
+ resourceId: row.resourceId
1094
1145
  };
1095
1146
  if (row.type && row.type !== `v2`) result.type = row.type;
1096
1147
  return result;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/libsql",
3
- "version": "0.10.2-alpha.0",
3
+ "version": "0.10.2-alpha.1",
4
4
  "description": "Libsql provider for Mastra - includes both vector and db storage capabilities",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -28,10 +28,10 @@
28
28
  "eslint": "^9.28.0",
29
29
  "tsup": "^8.5.0",
30
30
  "typescript": "^5.8.3",
31
- "vitest": "^3.1.2",
32
- "@internal/lint": "0.0.10",
33
- "@mastra/core": "0.10.4-alpha.0",
34
- "@internal/storage-test-utils": "0.0.6"
31
+ "vitest": "^3.2.2",
32
+ "@mastra/core": "0.10.4-alpha.1",
33
+ "@internal/storage-test-utils": "0.0.6",
34
+ "@internal/lint": "0.0.10"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "@mastra/core": "^0.10.2-alpha.0"
@@ -3,8 +3,9 @@ import {
3
3
  createSampleEval,
4
4
  createSampleTraceForDB,
5
5
  createSampleThread,
6
- createSampleMessage,
7
6
  createTestSuite,
7
+ createSampleMessageV1,
8
+ resetRole,
8
9
  } from '@internal/storage-test-utils';
9
10
  import type { MastraMessageV1, StorageThreadType } from '@mastra/core';
10
11
  import { Mastra } from '@mastra/core/mastra';
@@ -243,16 +244,14 @@ describe('LibSQLStore Pagination Features', () => {
243
244
 
244
245
  describe('getMessages with pagination', () => {
245
246
  it('should return paginated messages with total count', async () => {
247
+ resetRole();
246
248
  const threadData = createSampleThread();
247
249
  threadData.resourceId = 'resource-msg-pagination';
248
250
  const thread = await store.saveThread({ thread: threadData as StorageThreadType });
249
251
 
250
252
  const messageRecords: MastraMessageV1[] = [];
251
253
  for (let i = 0; i < 15; i++) {
252
- messageRecords.push({
253
- ...createSampleMessage(thread.id),
254
- content: [{ type: 'text', text: `Message ${i + 1}` }],
255
- } as MastraMessageV1);
254
+ messageRecords.push(createSampleMessageV1({ threadId: thread.id, content: `Message ${i + 1}` }));
256
255
  }
257
256
  await store.saveMessages({ messages: messageRecords });
258
257
 
@@ -300,17 +299,21 @@ describe('LibSQLStore Pagination Features', () => {
300
299
 
301
300
  // Ensure timestamps are distinct for reliable sorting by creating them with a slight delay for testing clarity
302
301
  const messagesToSave: MastraMessageV1[] = [];
303
- messagesToSave.push(createSampleMessage(thread.id, dayBeforeYesterday));
302
+ messagesToSave.push(
303
+ createSampleMessageV1({ threadId: thread.id, content: 'Message 1', createdAt: dayBeforeYesterday }),
304
+ );
304
305
  await new Promise(r => setTimeout(r, 5));
305
- messagesToSave.push(createSampleMessage(thread.id, dayBeforeYesterday));
306
+ messagesToSave.push(
307
+ createSampleMessageV1({ threadId: thread.id, content: 'Message 2', createdAt: dayBeforeYesterday }),
308
+ );
306
309
  await new Promise(r => setTimeout(r, 5));
307
- messagesToSave.push(createSampleMessage(thread.id, yesterday));
310
+ messagesToSave.push(createSampleMessageV1({ threadId: thread.id, content: 'Message 3', createdAt: yesterday }));
308
311
  await new Promise(r => setTimeout(r, 5));
309
- messagesToSave.push(createSampleMessage(thread.id, yesterday));
312
+ messagesToSave.push(createSampleMessageV1({ threadId: thread.id, content: 'Message 4', createdAt: yesterday }));
310
313
  await new Promise(r => setTimeout(r, 5));
311
- messagesToSave.push(createSampleMessage(thread.id, now));
314
+ messagesToSave.push(createSampleMessageV1({ threadId: thread.id, content: 'Message 5', createdAt: now }));
312
315
  await new Promise(r => setTimeout(r, 5));
313
- messagesToSave.push(createSampleMessage(thread.id, now));
316
+ messagesToSave.push(createSampleMessageV1({ threadId: thread.id, content: 'Message 6', createdAt: now }));
314
317
 
315
318
  await store.saveMessages({ messages: messagesToSave, format: 'v1' });
316
319
  // Total 6 messages: 2 now, 2 yesterday, 2 dayBeforeYesterday (oldest to newest)
@@ -125,6 +125,63 @@ export class LibSQLStore extends MastraStorage {
125
125
  }
126
126
  }
127
127
 
128
+ protected getSqlType(type: StorageColumn['type']): string {
129
+ switch (type) {
130
+ case 'bigint':
131
+ return 'INTEGER'; // SQLite uses INTEGER for all integer sizes
132
+ case 'jsonb':
133
+ return 'TEXT'; // Store JSON as TEXT in SQLite
134
+ default:
135
+ return super.getSqlType(type);
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Alters table schema to add columns if they don't exist
141
+ * @param tableName Name of the table
142
+ * @param schema Schema of the table
143
+ * @param ifNotExists Array of column names to add if they don't exist
144
+ */
145
+ async alterTable({
146
+ tableName,
147
+ schema,
148
+ ifNotExists,
149
+ }: {
150
+ tableName: TABLE_NAMES;
151
+ schema: Record<string, StorageColumn>;
152
+ ifNotExists: string[];
153
+ }): Promise<void> {
154
+ const parsedTableName = parseSqlIdentifier(tableName, 'table name');
155
+
156
+ try {
157
+ // 1. Get existing columns using PRAGMA
158
+ const pragmaQuery = `PRAGMA table_info(${parsedTableName})`;
159
+ const result = await this.client.execute(pragmaQuery);
160
+ const existingColumnNames = new Set(result.rows.map((row: any) => row.name.toLowerCase()));
161
+
162
+ // 2. Add missing columns
163
+ for (const columnName of ifNotExists) {
164
+ if (!existingColumnNames.has(columnName.toLowerCase()) && schema[columnName]) {
165
+ const columnDef = schema[columnName];
166
+ const sqlType = this.getSqlType(columnDef.type); // ensure this exists or implement
167
+ const nullable = columnDef.nullable === false ? 'NOT NULL' : '';
168
+ // In SQLite, you must provide a DEFAULT if adding a NOT NULL column to a non-empty table
169
+ const defaultValue = columnDef.nullable === false ? this.getDefaultValue(columnDef.type) : '';
170
+ const alterSql =
171
+ `ALTER TABLE ${parsedTableName} ADD COLUMN "${columnName}" ${sqlType} ${nullable} ${defaultValue}`.trim();
172
+
173
+ await this.client.execute(alterSql);
174
+ this.logger?.debug?.(`Added column ${columnName} to table ${parsedTableName}`);
175
+ }
176
+ }
177
+ } catch (error) {
178
+ this.logger?.error?.(
179
+ `Error altering table ${tableName}: ${error instanceof Error ? error.message : String(error)}`,
180
+ );
181
+ throw new Error(`Failed to alter table ${tableName}: ${error}`);
182
+ }
183
+ }
184
+
128
185
  async clearTable({ tableName }: { tableName: TABLE_NAMES }): Promise<void> {
129
186
  const parsedTableName = parseSqlIdentifier(tableName, 'table name');
130
187
  try {
@@ -414,11 +471,17 @@ export class LibSQLStore extends MastraStorage {
414
471
  }
415
472
 
416
473
  async deleteThread({ threadId }: { threadId: string }): Promise<void> {
474
+ // Delete messages for this thread (manual step)
475
+ await this.client.execute({
476
+ sql: `DELETE FROM ${TABLE_MESSAGES} WHERE thread_id = ?`,
477
+ args: [threadId],
478
+ });
479
+
417
480
  await this.client.execute({
418
481
  sql: `DELETE FROM ${TABLE_THREADS} WHERE id = ?`,
419
482
  args: [threadId],
420
483
  });
421
- // Messages will be automatically deleted due to CASCADE constraint
484
+ // TODO: Need to check if CASCADE is enabled so that messages will be automatically deleted due to CASCADE constraint
422
485
  }
423
486
 
424
487
  private parseRow(row: any): MastraMessageV2 {
@@ -434,6 +497,7 @@ export class LibSQLStore extends MastraStorage {
434
497
  role: row.role,
435
498
  createdAt: new Date(row.createdAt as string),
436
499
  threadId: row.thread_id,
500
+ resourceId: row.resourceId,
437
501
  } as MastraMessageV2;
438
502
  if (row.type && row.type !== `v2`) result.type = row.type;
439
503
  return result;