@mastra/cloudflare-d1 0.0.0-trigger-playground-ui-package-20250506151043 → 0.0.0-tsconfig-compile-20250703214351

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.cjs CHANGED
@@ -1,15 +1,16 @@
1
1
  'use strict';
2
2
 
3
+ var agent = require('@mastra/core/agent');
4
+ var error = require('@mastra/core/error');
3
5
  var storage = require('@mastra/core/storage');
4
6
  var Cloudflare = require('cloudflare');
7
+ var utils = require('@mastra/core/utils');
5
8
 
6
9
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
7
10
 
8
11
  var Cloudflare__default = /*#__PURE__*/_interopDefault(Cloudflare);
9
12
 
10
13
  // src/storage/index.ts
11
-
12
- // src/storage/sql-builder.ts
13
14
  var SqlBuilder = class {
14
15
  sql = "";
15
16
  params = [];
@@ -19,12 +20,15 @@ var SqlBuilder = class {
19
20
  if (!columns || Array.isArray(columns) && columns.length === 0) {
20
21
  this.sql = "SELECT *";
21
22
  } else {
22
- this.sql = `SELECT ${Array.isArray(columns) ? columns.join(", ") : columns}`;
23
+ const cols = Array.isArray(columns) ? columns : [columns];
24
+ const parsedCols = cols.map((col) => parseSelectIdentifier(col));
25
+ this.sql = `SELECT ${parsedCols.join(", ")}`;
23
26
  }
24
27
  return this;
25
28
  }
26
29
  from(table) {
27
- this.sql += ` FROM ${table}`;
30
+ const parsedTableName = utils.parseSqlIdentifier(table, "table name");
31
+ this.sql += ` FROM ${parsedTableName}`;
28
32
  return this;
29
33
  }
30
34
  /**
@@ -61,7 +65,11 @@ var SqlBuilder = class {
61
65
  return this;
62
66
  }
63
67
  orderBy(column, direction = "ASC") {
64
- this.sql += ` ORDER BY ${column} ${direction}`;
68
+ const parsedColumn = utils.parseSqlIdentifier(column, "column name");
69
+ if (!["ASC", "DESC"].includes(direction)) {
70
+ throw new Error(`Invalid sort direction: ${direction}`);
71
+ }
72
+ this.sql += ` ORDER BY ${parsedColumn} ${direction}`;
65
73
  return this;
66
74
  }
67
75
  limit(count) {
@@ -87,27 +95,33 @@ var SqlBuilder = class {
87
95
  * @param updateMap Object mapping columns to update to their new value (e.g. { name: 'excluded.name' })
88
96
  */
89
97
  insert(table, columns, values, conflictColumns, updateMap) {
90
- const placeholders = columns.map(() => "?").join(", ");
98
+ const parsedTableName = utils.parseSqlIdentifier(table, "table name");
99
+ const parsedColumns = columns.map((col) => utils.parseSqlIdentifier(col, "column name"));
100
+ const placeholders = parsedColumns.map(() => "?").join(", ");
91
101
  if (conflictColumns && updateMap) {
102
+ const parsedConflictColumns = conflictColumns.map((col) => utils.parseSqlIdentifier(col, "column name"));
92
103
  const updateClause = Object.entries(updateMap).map(([col, expr]) => `${col} = ${expr}`).join(", ");
93
- this.sql = `INSERT INTO ${table} (${columns.join(", ")}) VALUES (${placeholders}) ON CONFLICT(${conflictColumns.join(", ")}) DO UPDATE SET ${updateClause}`;
104
+ this.sql = `INSERT INTO ${parsedTableName} (${parsedColumns.join(", ")}) VALUES (${placeholders}) ON CONFLICT(${parsedConflictColumns.join(", ")}) DO UPDATE SET ${updateClause}`;
94
105
  this.params.push(...values);
95
106
  return this;
96
107
  }
97
- this.sql = `INSERT INTO ${table} (${columns.join(", ")}) VALUES (${placeholders})`;
108
+ this.sql = `INSERT INTO ${parsedTableName} (${parsedColumns.join(", ")}) VALUES (${placeholders})`;
98
109
  this.params.push(...values);
99
110
  return this;
100
111
  }
101
112
  // Update operations
102
113
  update(table, columns, values) {
103
- const setClause = columns.map((col) => `${col} = ?`).join(", ");
104
- this.sql = `UPDATE ${table} SET ${setClause}`;
114
+ const parsedTableName = utils.parseSqlIdentifier(table, "table name");
115
+ const parsedColumns = columns.map((col) => utils.parseSqlIdentifier(col, "column name"));
116
+ const setClause = parsedColumns.map((col) => `${col} = ?`).join(", ");
117
+ this.sql = `UPDATE ${parsedTableName} SET ${setClause}`;
105
118
  this.params.push(...values);
106
119
  return this;
107
120
  }
108
121
  // Delete operations
109
122
  delete(table) {
110
- this.sql = `DELETE FROM ${table}`;
123
+ const parsedTableName = utils.parseSqlIdentifier(table, "table name");
124
+ this.sql = `DELETE FROM ${parsedTableName}`;
111
125
  return this;
112
126
  }
113
127
  /**
@@ -118,9 +132,16 @@ var SqlBuilder = class {
118
132
  * @returns The builder instance
119
133
  */
120
134
  createTable(table, columnDefinitions, tableConstraints) {
121
- const columns = columnDefinitions.join(", ");
135
+ const parsedTableName = utils.parseSqlIdentifier(table, "table name");
136
+ const parsedColumnDefinitions = columnDefinitions.map((def) => {
137
+ const colName = def.split(/\s+/)[0];
138
+ if (!colName) throw new Error("Empty column name in definition");
139
+ utils.parseSqlIdentifier(colName, "column name");
140
+ return def;
141
+ });
142
+ const columns = parsedColumnDefinitions.join(", ");
122
143
  const constraints = tableConstraints && tableConstraints.length > 0 ? ", " + tableConstraints.join(", ") : "";
123
- this.sql = `CREATE TABLE IF NOT EXISTS ${table} (${columns}${constraints})`;
144
+ this.sql = `CREATE TABLE IF NOT EXISTS ${parsedTableName} (${columns}${constraints})`;
124
145
  return this;
125
146
  }
126
147
  /**
@@ -143,13 +164,10 @@ var SqlBuilder = class {
143
164
  * @returns The builder instance
144
165
  */
145
166
  createIndex(indexName, tableName, columnName, indexType = "") {
146
- this.sql = `CREATE ${indexType ? indexType + " " : ""}INDEX IF NOT EXISTS ${indexName} ON ${tableName}(${columnName})`;
147
- return this;
148
- }
149
- // Raw SQL with params
150
- raw(sql, ...params) {
151
- this.sql = sql;
152
- this.params.push(...params);
167
+ const parsedIndexName = utils.parseSqlIdentifier(indexName, "index name");
168
+ const parsedTableName = utils.parseSqlIdentifier(tableName, "table name");
169
+ const parsedColumnName = utils.parseSqlIdentifier(columnName, "column name");
170
+ this.sql = `CREATE ${indexType ? indexType + " " : ""}INDEX IF NOT EXISTS ${parsedIndexName} ON ${parsedTableName}(${parsedColumnName})`;
153
171
  return this;
154
172
  }
155
173
  /**
@@ -159,11 +177,12 @@ var SqlBuilder = class {
159
177
  * @param exact If true, will not add % wildcards
160
178
  */
161
179
  like(column, value, exact = false) {
180
+ const parsedColumnName = utils.parseSqlIdentifier(column, "column name");
162
181
  const likeValue = exact ? value : `%${value}%`;
163
182
  if (this.whereAdded) {
164
- this.sql += ` AND ${column} LIKE ?`;
183
+ this.sql += ` AND ${parsedColumnName} LIKE ?`;
165
184
  } else {
166
- this.sql += ` WHERE ${column} LIKE ?`;
185
+ this.sql += ` WHERE ${parsedColumnName} LIKE ?`;
167
186
  this.whereAdded = true;
168
187
  }
169
188
  this.params.push(likeValue);
@@ -176,11 +195,13 @@ var SqlBuilder = class {
176
195
  * @param value The value to match
177
196
  */
178
197
  jsonLike(column, key, value) {
179
- const jsonPattern = `%"${key}":"${value}"%`;
198
+ const parsedColumnName = utils.parseSqlIdentifier(column, "column name");
199
+ const parsedKey = utils.parseSqlIdentifier(key, "key name");
200
+ const jsonPattern = `%"${parsedKey}":"${value}"%`;
180
201
  if (this.whereAdded) {
181
- this.sql += ` AND ${column} LIKE ?`;
202
+ this.sql += ` AND ${parsedColumnName} LIKE ?`;
182
203
  } else {
183
- this.sql += ` WHERE ${column} LIKE ?`;
204
+ this.sql += ` WHERE ${parsedColumnName} LIKE ?`;
184
205
  this.whereAdded = true;
185
206
  }
186
207
  this.params.push(jsonPattern);
@@ -210,6 +231,15 @@ var SqlBuilder = class {
210
231
  function createSqlBuilder() {
211
232
  return new SqlBuilder();
212
233
  }
234
+ var SQL_IDENTIFIER_PATTERN = /^[a-zA-Z0-9_]+(\s+AS\s+[a-zA-Z0-9_]+)?$/;
235
+ function parseSelectIdentifier(column) {
236
+ if (column !== "*" && !SQL_IDENTIFIER_PATTERN.test(column)) {
237
+ throw new Error(
238
+ `Invalid column name: "${column}". Must be "*" or a valid identifier (letters, numbers, underscores), optionally with "AS alias".`
239
+ );
240
+ }
241
+ return column;
242
+ }
213
243
 
214
244
  // src/storage/index.ts
215
245
  function isArrayOfRecords(value) {
@@ -227,24 +257,39 @@ var D1Store = class extends storage.MastraStorage {
227
257
  * @param config Configuration for D1 access (either REST API or Workers Binding API)
228
258
  */
229
259
  constructor(config) {
230
- super({ name: "D1" });
231
- this.tablePrefix = config.tablePrefix || "";
232
- if ("binding" in config) {
233
- if (!config.binding) {
234
- throw new Error("D1 binding is required when using Workers Binding API");
260
+ try {
261
+ super({ name: "D1" });
262
+ if (config.tablePrefix && !/^[a-zA-Z0-9_]*$/.test(config.tablePrefix)) {
263
+ throw new Error("Invalid tablePrefix: only letters, numbers, and underscores are allowed.");
235
264
  }
236
- this.binding = config.binding;
237
- this.logger.info("Using D1 Workers Binding API");
238
- } else {
239
- if (!config.accountId || !config.databaseId || !config.apiToken) {
240
- throw new Error("accountId, databaseId, and apiToken are required when using REST API");
265
+ this.tablePrefix = config.tablePrefix || "";
266
+ if ("binding" in config) {
267
+ if (!config.binding) {
268
+ throw new Error("D1 binding is required when using Workers Binding API");
269
+ }
270
+ this.binding = config.binding;
271
+ this.logger.info("Using D1 Workers Binding API");
272
+ } else {
273
+ if (!config.accountId || !config.databaseId || !config.apiToken) {
274
+ throw new Error("accountId, databaseId, and apiToken are required when using REST API");
275
+ }
276
+ this.accountId = config.accountId;
277
+ this.databaseId = config.databaseId;
278
+ this.client = new Cloudflare__default.default({
279
+ apiToken: config.apiToken
280
+ });
281
+ this.logger.info("Using D1 REST API");
241
282
  }
242
- this.accountId = config.accountId;
243
- this.databaseId = config.databaseId;
244
- this.client = new Cloudflare__default.default({
245
- apiToken: config.apiToken
246
- });
247
- this.logger.info("Using D1 REST API");
283
+ } catch (error$1) {
284
+ throw new error.MastraError(
285
+ {
286
+ id: "CLOUDFLARE_D1_STORAGE_INITIALIZATION_ERROR",
287
+ domain: error.ErrorDomain.STORAGE,
288
+ category: error.ErrorCategory.SYSTEM,
289
+ text: "Error initializing D1Store"
290
+ },
291
+ error$1
292
+ );
248
293
  }
249
294
  }
250
295
  // Helper method to get the full table name with prefix
@@ -254,30 +299,6 @@ var D1Store = class extends storage.MastraStorage {
254
299
  formatSqlParams(params) {
255
300
  return params.map((p) => p === void 0 || p === null ? null : p);
256
301
  }
257
- // Helper method to create SQL indexes for better query performance
258
- async createIndexIfNotExists(tableName, columnName, indexType = "") {
259
- const fullTableName = this.getTableName(tableName);
260
- const indexName = `idx_${tableName}_${columnName}`;
261
- try {
262
- const checkQuery = createSqlBuilder().checkIndexExists(indexName, fullTableName);
263
- const { sql: checkSql, params: checkParams } = checkQuery.build();
264
- const indexExists = await this.executeQuery({
265
- sql: checkSql,
266
- params: checkParams,
267
- first: true
268
- });
269
- if (!indexExists) {
270
- const createQuery = createSqlBuilder().createIndex(indexName, fullTableName, columnName, indexType);
271
- const { sql: createSql, params: createParams } = createQuery.build();
272
- await this.executeQuery({ sql: createSql, params: createParams });
273
- this.logger.debug(`Created index ${indexName} on ${fullTableName}(${columnName})`);
274
- }
275
- } catch (error) {
276
- this.logger.error(`Error creating index on ${fullTableName}(${columnName}):`, {
277
- message: error instanceof Error ? error.message : String(error)
278
- });
279
- }
280
- }
281
302
  async executeWorkersBindingQuery({
282
303
  sql,
283
304
  params = [],
@@ -381,34 +402,25 @@ var D1Store = class extends storage.MastraStorage {
381
402
  throw new Error(`D1 query error: ${error.message}`);
382
403
  }
383
404
  }
384
- // Helper to convert storage type to SQL type
385
- getSqlType(type) {
386
- switch (type) {
387
- case "text":
388
- return "TEXT";
389
- case "timestamp":
390
- return "TIMESTAMP";
391
- case "integer":
392
- return "INTEGER";
393
- case "bigint":
394
- return "INTEGER";
395
- // SQLite doesn't have a separate BIGINT type
396
- case "jsonb":
397
- return "TEXT";
398
- // Store JSON as TEXT in SQLite
399
- default:
400
- return "TEXT";
405
+ // Helper to get existing table columns
406
+ async getTableColumns(tableName) {
407
+ try {
408
+ const sql = `PRAGMA table_info(${tableName})`;
409
+ const result = await this.executeQuery({ sql, params: [] });
410
+ if (!result || !Array.isArray(result)) {
411
+ return [];
412
+ }
413
+ return result.map((row) => ({
414
+ name: row.name,
415
+ type: row.type
416
+ }));
417
+ } catch (error) {
418
+ this.logger.error(`Error getting table columns for ${tableName}:`, {
419
+ message: error instanceof Error ? error.message : String(error)
420
+ });
421
+ return [];
401
422
  }
402
423
  }
403
- ensureDate(date) {
404
- if (!date) return void 0;
405
- return date instanceof Date ? date : new Date(date);
406
- }
407
- serializeDate(date) {
408
- if (!date) return void 0;
409
- const dateObj = this.ensureDate(date);
410
- return dateObj?.toISOString();
411
- }
412
424
  // Helper to serialize objects to JSON strings
413
425
  serializeValue(value) {
414
426
  if (value === null || value === void 0) return null;
@@ -442,6 +454,18 @@ var D1Store = class extends storage.MastraStorage {
442
454
  }
443
455
  return value;
444
456
  }
457
+ getSqlType(type) {
458
+ switch (type) {
459
+ case "bigint":
460
+ return "INTEGER";
461
+ // SQLite uses INTEGER for all integer sizes
462
+ case "jsonb":
463
+ return "TEXT";
464
+ // Store JSON as TEXT in SQLite
465
+ default:
466
+ return super.getSqlType(type);
467
+ }
468
+ }
445
469
  async createTable({
446
470
  tableName,
447
471
  schema
@@ -457,16 +481,64 @@ var D1Store = class extends storage.MastraStorage {
457
481
  if (tableName === storage.TABLE_WORKFLOW_SNAPSHOT) {
458
482
  tableConstraints.push("UNIQUE (workflow_name, run_id)");
459
483
  }
460
- const query = createSqlBuilder().createTable(fullTableName, columnDefinitions, tableConstraints);
461
- const { sql, params } = query.build();
462
484
  try {
485
+ const query = createSqlBuilder().createTable(fullTableName, columnDefinitions, tableConstraints);
486
+ const { sql, params } = query.build();
463
487
  await this.executeQuery({ sql, params });
464
488
  this.logger.debug(`Created table ${fullTableName}`);
465
- } catch (error) {
489
+ } catch (error$1) {
466
490
  this.logger.error(`Error creating table ${fullTableName}:`, {
467
- message: error instanceof Error ? error.message : String(error)
491
+ message: error$1 instanceof Error ? error$1.message : String(error$1)
468
492
  });
469
- throw new Error(`Failed to create table ${fullTableName}: ${error}`);
493
+ throw new error.MastraError(
494
+ {
495
+ id: "CLOUDFLARE_D1_STORAGE_CREATE_TABLE_ERROR",
496
+ domain: error.ErrorDomain.STORAGE,
497
+ category: error.ErrorCategory.THIRD_PARTY,
498
+ text: `Failed to create table ${fullTableName}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
499
+ details: { tableName }
500
+ },
501
+ error$1
502
+ );
503
+ }
504
+ }
505
+ /**
506
+ * Alters table schema to add columns if they don't exist
507
+ * @param tableName Name of the table
508
+ * @param schema Schema of the table
509
+ * @param ifNotExists Array of column names to add if they don't exist
510
+ */
511
+ async alterTable({
512
+ tableName,
513
+ schema,
514
+ ifNotExists
515
+ }) {
516
+ const fullTableName = this.getTableName(tableName);
517
+ try {
518
+ const existingColumns = await this.getTableColumns(fullTableName);
519
+ const existingColumnNames = new Set(existingColumns.map((col) => col.name.toLowerCase()));
520
+ for (const columnName of ifNotExists) {
521
+ if (!existingColumnNames.has(columnName.toLowerCase()) && schema[columnName]) {
522
+ const columnDef = schema[columnName];
523
+ const sqlType = this.getSqlType(columnDef.type);
524
+ const nullable = columnDef.nullable === false ? "NOT NULL" : "";
525
+ const defaultValue = columnDef.nullable === false ? this.getDefaultValue(columnDef.type) : "";
526
+ const alterSql = `ALTER TABLE ${fullTableName} ADD COLUMN ${columnName} ${sqlType} ${nullable} ${defaultValue}`.trim();
527
+ await this.executeQuery({ sql: alterSql, params: [] });
528
+ this.logger.debug(`Added column ${columnName} to table ${fullTableName}`);
529
+ }
530
+ }
531
+ } catch (error$1) {
532
+ throw new error.MastraError(
533
+ {
534
+ id: "CLOUDFLARE_D1_STORAGE_ALTER_TABLE_ERROR",
535
+ domain: error.ErrorDomain.STORAGE,
536
+ category: error.ErrorCategory.THIRD_PARTY,
537
+ text: `Failed to alter table ${fullTableName}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
538
+ details: { tableName }
539
+ },
540
+ error$1
541
+ );
470
542
  }
471
543
  }
472
544
  async clearTable({ tableName }) {
@@ -476,11 +548,17 @@ var D1Store = class extends storage.MastraStorage {
476
548
  const { sql, params } = query.build();
477
549
  await this.executeQuery({ sql, params });
478
550
  this.logger.debug(`Cleared table ${fullTableName}`);
479
- } catch (error) {
480
- this.logger.error(`Error clearing table ${fullTableName}:`, {
481
- message: error instanceof Error ? error.message : String(error)
482
- });
483
- throw new Error(`Failed to clear table ${fullTableName}: ${error}`);
551
+ } catch (error$1) {
552
+ throw new error.MastraError(
553
+ {
554
+ id: "CLOUDFLARE_D1_STORAGE_CLEAR_TABLE_ERROR",
555
+ domain: error.ErrorDomain.STORAGE,
556
+ category: error.ErrorCategory.THIRD_PARTY,
557
+ text: `Failed to clear table ${fullTableName}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
558
+ details: { tableName }
559
+ },
560
+ error$1
561
+ );
484
562
  }
485
563
  }
486
564
  async processRecord(record) {
@@ -499,10 +577,17 @@ var D1Store = class extends storage.MastraStorage {
499
577
  const { sql, params } = query.build();
500
578
  try {
501
579
  await this.executeQuery({ sql, params });
502
- } catch (error) {
503
- const message = error instanceof Error ? error.message : String(error);
504
- this.logger.error(`Error inserting into ${fullTableName}:`, { message });
505
- throw new Error(`Failed to insert into ${fullTableName}: ${error}`);
580
+ } catch (error$1) {
581
+ throw new error.MastraError(
582
+ {
583
+ id: "CLOUDFLARE_D1_STORAGE_INSERT_ERROR",
584
+ domain: error.ErrorDomain.STORAGE,
585
+ category: error.ErrorCategory.THIRD_PARTY,
586
+ text: `Failed to insert into ${fullTableName}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
587
+ details: { tableName }
588
+ },
589
+ error$1
590
+ );
506
591
  }
507
592
  }
508
593
  async load({ tableName, keys }) {
@@ -527,11 +612,17 @@ var D1Store = class extends storage.MastraStorage {
527
612
  processedResult[key] = this.deserializeValue(value);
528
613
  }
529
614
  return processedResult;
530
- } catch (error) {
531
- this.logger.error(`Error loading from ${fullTableName}:`, {
532
- message: error instanceof Error ? error.message : String(error)
533
- });
534
- return null;
615
+ } catch (error$1) {
616
+ throw new error.MastraError(
617
+ {
618
+ id: "CLOUDFLARE_D1_STORAGE_LOAD_ERROR",
619
+ domain: error.ErrorDomain.STORAGE,
620
+ category: error.ErrorCategory.THIRD_PARTY,
621
+ text: `Failed to load from ${fullTableName}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
622
+ details: { tableName }
623
+ },
624
+ error$1
625
+ );
535
626
  }
536
627
  }
537
628
  async getThreadById({ threadId }) {
@@ -547,13 +638,25 @@ var D1Store = class extends storage.MastraStorage {
547
638
  updatedAt: this.ensureDate(thread.updatedAt),
548
639
  metadata: typeof thread.metadata === "string" ? JSON.parse(thread.metadata || "{}") : thread.metadata || {}
549
640
  };
550
- } catch (error) {
551
- this.logger.error(`Error processing thread ${threadId}:`, {
552
- message: error instanceof Error ? error.message : String(error)
553
- });
641
+ } catch (error$1) {
642
+ const mastraError = new error.MastraError(
643
+ {
644
+ id: "CLOUDFLARE_D1_STORAGE_GET_THREAD_BY_ID_ERROR",
645
+ domain: error.ErrorDomain.STORAGE,
646
+ category: error.ErrorCategory.THIRD_PARTY,
647
+ text: `Error processing thread ${threadId}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
648
+ details: { threadId }
649
+ },
650
+ error$1
651
+ );
652
+ this.logger?.error(mastraError.toString());
653
+ this.logger?.trackException(mastraError);
554
654
  return null;
555
655
  }
556
656
  }
657
+ /**
658
+ * @deprecated use getThreadsByResourceIdPaginated instead
659
+ */
557
660
  async getThreadsByResourceId({ resourceId }) {
558
661
  const fullTableName = this.getTableName(storage.TABLE_THREADS);
559
662
  try {
@@ -566,13 +669,67 @@ var D1Store = class extends storage.MastraStorage {
566
669
  updatedAt: this.ensureDate(thread.updatedAt),
567
670
  metadata: typeof thread.metadata === "string" ? JSON.parse(thread.metadata || "{}") : thread.metadata || {}
568
671
  }));
569
- } catch (error) {
570
- this.logger.error(`Error getting threads by resourceId ${resourceId}:`, {
571
- message: error instanceof Error ? error.message : String(error)
572
- });
672
+ } catch (error$1) {
673
+ const mastraError = new error.MastraError(
674
+ {
675
+ id: "CLOUDFLARE_D1_STORAGE_GET_THREADS_BY_RESOURCE_ID_ERROR",
676
+ domain: error.ErrorDomain.STORAGE,
677
+ category: error.ErrorCategory.THIRD_PARTY,
678
+ text: `Error getting threads by resourceId ${resourceId}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
679
+ details: { resourceId }
680
+ },
681
+ error$1
682
+ );
683
+ this.logger?.error(mastraError.toString());
684
+ this.logger?.trackException(mastraError);
573
685
  return [];
574
686
  }
575
687
  }
688
+ async getThreadsByResourceIdPaginated(args) {
689
+ const { resourceId, page, perPage } = args;
690
+ const fullTableName = this.getTableName(storage.TABLE_THREADS);
691
+ const mapRowToStorageThreadType = (row) => ({
692
+ ...row,
693
+ createdAt: this.ensureDate(row.createdAt),
694
+ updatedAt: this.ensureDate(row.updatedAt),
695
+ metadata: typeof row.metadata === "string" ? JSON.parse(row.metadata || "{}") : row.metadata || {}
696
+ });
697
+ try {
698
+ const countQuery = createSqlBuilder().count().from(fullTableName).where("resourceId = ?", resourceId);
699
+ const countResult = await this.executeQuery(countQuery.build());
700
+ const total = Number(countResult?.[0]?.count ?? 0);
701
+ const selectQuery = createSqlBuilder().select("*").from(fullTableName).where("resourceId = ?", resourceId).orderBy("createdAt", "DESC").limit(perPage).offset(page * perPage);
702
+ const results = await this.executeQuery(selectQuery.build());
703
+ const threads = results.map(mapRowToStorageThreadType);
704
+ return {
705
+ threads,
706
+ total,
707
+ page,
708
+ perPage,
709
+ hasMore: page * perPage + threads.length < total
710
+ };
711
+ } catch (error$1) {
712
+ const mastraError = new error.MastraError(
713
+ {
714
+ id: "CLOUDFLARE_D1_STORAGE_GET_THREADS_BY_RESOURCE_ID_PAGINATED_ERROR",
715
+ domain: error.ErrorDomain.STORAGE,
716
+ category: error.ErrorCategory.THIRD_PARTY,
717
+ text: `Error getting threads by resourceId ${resourceId}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
718
+ details: { resourceId }
719
+ },
720
+ error$1
721
+ );
722
+ this.logger?.error(mastraError.toString());
723
+ this.logger?.trackException(mastraError);
724
+ return {
725
+ threads: [],
726
+ total: 0,
727
+ page,
728
+ perPage,
729
+ hasMore: false
730
+ };
731
+ }
732
+ }
576
733
  async saveThread({ thread }) {
577
734
  const fullTableName = this.getTableName(storage.TABLE_THREADS);
578
735
  const threadToSave = {
@@ -598,10 +755,17 @@ var D1Store = class extends storage.MastraStorage {
598
755
  try {
599
756
  await this.executeQuery({ sql, params });
600
757
  return thread;
601
- } catch (error) {
602
- const message = error instanceof Error ? error.message : String(error);
603
- this.logger.error(`Error saving thread to ${fullTableName}:`, { message });
604
- throw error;
758
+ } catch (error$1) {
759
+ throw new error.MastraError(
760
+ {
761
+ id: "CLOUDFLARE_D1_STORAGE_SAVE_THREAD_ERROR",
762
+ domain: error.ErrorDomain.STORAGE,
763
+ category: error.ErrorCategory.THIRD_PARTY,
764
+ text: `Failed to save thread to ${fullTableName}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
765
+ details: { threadId: thread.id }
766
+ },
767
+ error$1
768
+ );
605
769
  }
606
770
  }
607
771
  async updateThread({
@@ -610,19 +774,19 @@ var D1Store = class extends storage.MastraStorage {
610
774
  metadata
611
775
  }) {
612
776
  const thread = await this.getThreadById({ threadId: id });
613
- if (!thread) {
614
- throw new Error(`Thread ${id} not found`);
615
- }
616
- const fullTableName = this.getTableName(storage.TABLE_THREADS);
617
- const mergedMetadata = {
618
- ...typeof thread.metadata === "string" ? JSON.parse(thread.metadata) : thread.metadata,
619
- ...metadata
620
- };
621
- const columns = ["title", "metadata", "updatedAt"];
622
- const values = [title, JSON.stringify(mergedMetadata), (/* @__PURE__ */ new Date()).toISOString()];
623
- const query = createSqlBuilder().update(fullTableName, columns, values).where("id = ?", id);
624
- const { sql, params } = query.build();
625
777
  try {
778
+ if (!thread) {
779
+ throw new Error(`Thread ${id} not found`);
780
+ }
781
+ const fullTableName = this.getTableName(storage.TABLE_THREADS);
782
+ const mergedMetadata = {
783
+ ...typeof thread.metadata === "string" ? JSON.parse(thread.metadata) : thread.metadata,
784
+ ...metadata
785
+ };
786
+ const columns = ["title", "metadata", "updatedAt"];
787
+ const values = [title, JSON.stringify(mergedMetadata), (/* @__PURE__ */ new Date()).toISOString()];
788
+ const query = createSqlBuilder().update(fullTableName, columns, values).where("id = ?", id);
789
+ const { sql, params } = query.build();
626
790
  await this.executeQuery({ sql, params });
627
791
  return {
628
792
  ...thread,
@@ -633,10 +797,17 @@ var D1Store = class extends storage.MastraStorage {
633
797
  },
634
798
  updatedAt: /* @__PURE__ */ new Date()
635
799
  };
636
- } catch (error) {
637
- const message = error instanceof Error ? error.message : String(error);
638
- this.logger.error("Error updating thread:", { message });
639
- throw error;
800
+ } catch (error$1) {
801
+ throw new error.MastraError(
802
+ {
803
+ id: "CLOUDFLARE_D1_STORAGE_UPDATE_THREAD_ERROR",
804
+ domain: error.ErrorDomain.STORAGE,
805
+ category: error.ErrorCategory.THIRD_PARTY,
806
+ text: `Failed to update thread ${id}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
807
+ details: { threadId: id }
808
+ },
809
+ error$1
810
+ );
640
811
  }
641
812
  }
642
813
  async deleteThread({ threadId }) {
@@ -649,18 +820,25 @@ var D1Store = class extends storage.MastraStorage {
649
820
  const deleteMessagesQuery = createSqlBuilder().delete(messagesTableName).where("thread_id = ?", threadId);
650
821
  const { sql: messagesSql, params: messagesParams } = deleteMessagesQuery.build();
651
822
  await this.executeQuery({ sql: messagesSql, params: messagesParams });
652
- } catch (error) {
653
- this.logger.error(`Error deleting thread ${threadId}:`, {
654
- message: error instanceof Error ? error.message : String(error)
655
- });
656
- throw new Error(`Failed to delete thread ${threadId}: ${error}`);
823
+ } catch (error$1) {
824
+ throw new error.MastraError(
825
+ {
826
+ id: "CLOUDFLARE_D1_STORAGE_DELETE_THREAD_ERROR",
827
+ domain: error.ErrorDomain.STORAGE,
828
+ category: error.ErrorCategory.THIRD_PARTY,
829
+ text: `Failed to delete thread ${threadId}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
830
+ details: { threadId }
831
+ },
832
+ error$1
833
+ );
657
834
  }
658
835
  }
659
- // Thread and message management methods
660
- async saveMessages({ messages }) {
836
+ async saveMessages(args) {
837
+ const { messages, format = "v1" } = args;
661
838
  if (messages.length === 0) return [];
662
839
  try {
663
840
  const now = /* @__PURE__ */ new Date();
841
+ const threadId = messages[0]?.threadId;
664
842
  for (const [i, message] of messages.entries()) {
665
843
  if (!message.id) throw new Error(`Message at index ${i} missing id`);
666
844
  if (!message.threadId) throw new Error(`Message at index ${i} missing threadId`);
@@ -679,36 +857,49 @@ var D1Store = class extends storage.MastraStorage {
679
857
  content: typeof message.content === "string" ? message.content : JSON.stringify(message.content),
680
858
  createdAt: createdAt.toISOString(),
681
859
  role: message.role,
682
- type: message.type
860
+ type: message.type || "v2",
861
+ resourceId: message.resourceId
683
862
  };
684
863
  });
685
- await this.batchInsert({
686
- tableName: storage.TABLE_MESSAGES,
687
- records: messagesToInsert
688
- });
864
+ await Promise.all([
865
+ this.batchUpsert({
866
+ tableName: storage.TABLE_MESSAGES,
867
+ records: messagesToInsert
868
+ }),
869
+ // Update thread's updatedAt timestamp
870
+ this.executeQuery({
871
+ sql: `UPDATE ${this.getTableName(storage.TABLE_THREADS)} SET updatedAt = ? WHERE id = ?`,
872
+ params: [now.toISOString(), threadId]
873
+ })
874
+ ]);
689
875
  this.logger.debug(`Saved ${messages.length} messages`);
690
- return messages;
691
- } catch (error) {
692
- this.logger.error("Error saving messages:", { message: error instanceof Error ? error.message : String(error) });
693
- throw error;
876
+ const list = new agent.MessageList().add(messages, "memory");
877
+ if (format === `v2`) return list.get.all.v2();
878
+ return list.get.all.v1();
879
+ } catch (error$1) {
880
+ throw new error.MastraError(
881
+ {
882
+ id: "CLOUDFLARE_D1_STORAGE_SAVE_MESSAGES_ERROR",
883
+ domain: error.ErrorDomain.STORAGE,
884
+ category: error.ErrorCategory.THIRD_PARTY,
885
+ text: `Failed to save messages: ${error$1 instanceof Error ? error$1.message : String(error$1)}`
886
+ },
887
+ error$1
888
+ );
694
889
  }
695
890
  }
696
- async getMessages({ threadId, selectBy }) {
697
- const fullTableName = this.getTableName(storage.TABLE_MESSAGES);
698
- const limit = typeof selectBy?.last === "number" ? selectBy.last : 40;
699
- const include = selectBy?.include || [];
700
- const messages = [];
701
- try {
702
- if (include.length) {
703
- const prevMax = Math.max(...include.map((i) => i.withPreviousMessages || 0));
704
- const nextMax = Math.max(...include.map((i) => i.withNextMessages || 0));
705
- const includeIds = include.map((i) => i.id);
706
- const sql2 = `
891
+ async _getIncludedMessages(threadId, selectBy) {
892
+ const include = selectBy?.include;
893
+ if (!include) return null;
894
+ const prevMax = Math.max(...include.map((i) => i.withPreviousMessages || 0));
895
+ const nextMax = Math.max(...include.map((i) => i.withNextMessages || 0));
896
+ const includeIds = include.map((i) => i.id);
897
+ const sql = `
707
898
  WITH ordered_messages AS (
708
899
  SELECT
709
900
  *,
710
901
  ROW_NUMBER() OVER (ORDER BY createdAt DESC) AS row_num
711
- FROM ${fullTableName}
902
+ FROM ${this.getTableName(storage.TABLE_MESSAGES)}
712
903
  WHERE thread_id = ?
713
904
  )
714
905
  SELECT
@@ -717,7 +908,7 @@ var D1Store = class extends storage.MastraStorage {
717
908
  m.role,
718
909
  m.type,
719
910
  m.createdAt,
720
- m.thread_id AS "threadId"
911
+ m.thread_id AS threadId
721
912
  FROM ordered_messages m
722
913
  WHERE m.id IN (${includeIds.map(() => "?").join(",")})
723
914
  OR EXISTS (
@@ -731,20 +922,38 @@ var D1Store = class extends storage.MastraStorage {
731
922
  )
732
923
  ORDER BY m.createdAt DESC
733
924
  `;
734
- const params2 = [
735
- threadId,
736
- ...includeIds,
737
- // for m.id IN (...)
738
- ...includeIds,
739
- // for target.id IN (...)
740
- prevMax,
741
- nextMax
742
- ];
743
- const includeResult = await this.executeQuery({ sql: sql2, params: params2 });
925
+ const params = [
926
+ threadId,
927
+ ...includeIds,
928
+ // for m.id IN (...)
929
+ ...includeIds,
930
+ // for target.id IN (...)
931
+ prevMax,
932
+ nextMax
933
+ ];
934
+ const messages = await this.executeQuery({ sql, params });
935
+ return messages;
936
+ }
937
+ async getMessages({
938
+ threadId,
939
+ selectBy,
940
+ format
941
+ }) {
942
+ const fullTableName = this.getTableName(storage.TABLE_MESSAGES);
943
+ const limit = this.resolveMessageLimit({ last: selectBy?.last, defaultLimit: 40 });
944
+ const include = selectBy?.include || [];
945
+ const messages = [];
946
+ try {
947
+ if (include.length) {
948
+ const includeResult = await this._getIncludedMessages(threadId, selectBy);
744
949
  if (Array.isArray(includeResult)) messages.push(...includeResult);
745
950
  }
746
951
  const excludeIds = messages.map((m) => m.id);
747
- let query = createSqlBuilder().select(["id", "content", "role", "type", '"createdAt"', 'thread_id AS "threadId"']).from(fullTableName).where("thread_id = ?", threadId).andWhere(`id NOT IN (${excludeIds.map(() => "?").join(",")})`, ...excludeIds).orderBy("createdAt", "DESC").limit(limit);
952
+ const query = createSqlBuilder().select(["id", "content", "role", "type", "createdAt", "thread_id AS threadId"]).from(fullTableName).where("thread_id = ?", threadId);
953
+ if (excludeIds.length > 0) {
954
+ query.andWhere(`id NOT IN (${excludeIds.map(() => "?").join(",")})`, ...excludeIds);
955
+ }
956
+ query.orderBy("createdAt", "DESC").limit(limit);
748
957
  const { sql, params } = query.build();
749
958
  const result = await this.executeQuery({ sql, params });
750
959
  if (Array.isArray(result)) messages.push(...result);
@@ -758,18 +967,92 @@ var D1Store = class extends storage.MastraStorage {
758
967
  const processedMessages = messages.map((message) => {
759
968
  const processedMsg = {};
760
969
  for (const [key, value] of Object.entries(message)) {
970
+ if (key === `type` && value === `v2`) continue;
761
971
  processedMsg[key] = this.deserializeValue(value);
762
972
  }
763
973
  return processedMsg;
764
974
  });
765
975
  this.logger.debug(`Retrieved ${messages.length} messages for thread ${threadId}`);
766
- return processedMessages;
767
- } catch (error) {
768
- this.logger.error("Error retrieving messages for thread", {
769
- threadId,
770
- message: error instanceof Error ? error.message : String(error)
771
- });
772
- return [];
976
+ const list = new agent.MessageList().add(processedMessages, "memory");
977
+ if (format === `v2`) return list.get.all.v2();
978
+ return list.get.all.v1();
979
+ } catch (error$1) {
980
+ const mastraError = new error.MastraError(
981
+ {
982
+ id: "CLOUDFLARE_D1_STORAGE_GET_MESSAGES_ERROR",
983
+ domain: error.ErrorDomain.STORAGE,
984
+ category: error.ErrorCategory.THIRD_PARTY,
985
+ text: `Failed to retrieve messages for thread ${threadId}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
986
+ details: { threadId }
987
+ },
988
+ error$1
989
+ );
990
+ this.logger?.error(mastraError.toString());
991
+ this.logger?.trackException(mastraError);
992
+ throw mastraError;
993
+ }
994
+ }
995
+ async getMessagesPaginated({
996
+ threadId,
997
+ selectBy,
998
+ format
999
+ }) {
1000
+ const { dateRange, page = 0, perPage = 40 } = selectBy?.pagination || {};
1001
+ const { start: fromDate, end: toDate } = dateRange || {};
1002
+ const fullTableName = this.getTableName(storage.TABLE_MESSAGES);
1003
+ const messages = [];
1004
+ try {
1005
+ if (selectBy?.include?.length) {
1006
+ const includeResult = await this._getIncludedMessages(threadId, selectBy);
1007
+ if (Array.isArray(includeResult)) messages.push(...includeResult);
1008
+ }
1009
+ const countQuery = createSqlBuilder().count().from(fullTableName).where("thread_id = ?", threadId);
1010
+ if (fromDate) {
1011
+ countQuery.andWhere("createdAt >= ?", this.serializeDate(fromDate));
1012
+ }
1013
+ if (toDate) {
1014
+ countQuery.andWhere("createdAt <= ?", this.serializeDate(toDate));
1015
+ }
1016
+ const countResult = await this.executeQuery(countQuery.build());
1017
+ const total = Number(countResult[0]?.count ?? 0);
1018
+ const query = createSqlBuilder().select(["id", "content", "role", "type", "createdAt", "thread_id AS threadId"]).from(fullTableName).where("thread_id = ?", threadId);
1019
+ if (fromDate) {
1020
+ query.andWhere("createdAt >= ?", this.serializeDate(fromDate));
1021
+ }
1022
+ if (toDate) {
1023
+ query.andWhere("createdAt <= ?", this.serializeDate(toDate));
1024
+ }
1025
+ query.orderBy("createdAt", "DESC").limit(perPage).offset(page * perPage);
1026
+ const results = await this.executeQuery(query.build());
1027
+ const list = new agent.MessageList().add(results, "memory");
1028
+ messages.push(...format === `v2` ? list.get.all.v2() : list.get.all.v1());
1029
+ return {
1030
+ messages,
1031
+ total,
1032
+ page,
1033
+ perPage,
1034
+ hasMore: page * perPage + messages.length < total
1035
+ };
1036
+ } catch (error$1) {
1037
+ const mastraError = new error.MastraError(
1038
+ {
1039
+ id: "CLOUDFLARE_D1_STORAGE_GET_MESSAGES_PAGINATED_ERROR",
1040
+ domain: error.ErrorDomain.STORAGE,
1041
+ category: error.ErrorCategory.THIRD_PARTY,
1042
+ text: `Failed to retrieve messages for thread ${threadId}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
1043
+ details: { threadId }
1044
+ },
1045
+ error$1
1046
+ );
1047
+ this.logger?.error(mastraError.toString());
1048
+ this.logger?.trackException(mastraError);
1049
+ return {
1050
+ messages: [],
1051
+ total: 0,
1052
+ page,
1053
+ perPage,
1054
+ hasMore: false
1055
+ };
773
1056
  }
774
1057
  }
775
1058
  async persistWorkflowSnapshot({
@@ -806,24 +1089,43 @@ var D1Store = class extends storage.MastraStorage {
806
1089
  const { sql, params } = query.build();
807
1090
  try {
808
1091
  await this.executeQuery({ sql, params });
809
- } catch (error) {
810
- this.logger.error("Error persisting workflow snapshot:", {
811
- message: error instanceof Error ? error.message : String(error)
812
- });
813
- throw error;
1092
+ } catch (error$1) {
1093
+ throw new error.MastraError(
1094
+ {
1095
+ id: "CLOUDFLARE_D1_STORAGE_PERSIST_WORKFLOW_SNAPSHOT_ERROR",
1096
+ domain: error.ErrorDomain.STORAGE,
1097
+ category: error.ErrorCategory.THIRD_PARTY,
1098
+ text: `Failed to persist workflow snapshot: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
1099
+ details: { workflowName, runId }
1100
+ },
1101
+ error$1
1102
+ );
814
1103
  }
815
1104
  }
816
1105
  async loadWorkflowSnapshot(params) {
817
1106
  const { workflowName, runId } = params;
818
1107
  this.logger.debug("Loading workflow snapshot", { workflowName, runId });
819
- const d = await this.load({
820
- tableName: storage.TABLE_WORKFLOW_SNAPSHOT,
821
- keys: {
822
- workflow_name: workflowName,
823
- run_id: runId
824
- }
825
- });
826
- return d ? d.snapshot : null;
1108
+ try {
1109
+ const d = await this.load({
1110
+ tableName: storage.TABLE_WORKFLOW_SNAPSHOT,
1111
+ keys: {
1112
+ workflow_name: workflowName,
1113
+ run_id: runId
1114
+ }
1115
+ });
1116
+ return d ? d.snapshot : null;
1117
+ } catch (error$1) {
1118
+ throw new error.MastraError(
1119
+ {
1120
+ id: "CLOUDFLARE_D1_STORAGE_LOAD_WORKFLOW_SNAPSHOT_ERROR",
1121
+ domain: error.ErrorDomain.STORAGE,
1122
+ category: error.ErrorCategory.THIRD_PARTY,
1123
+ text: `Failed to load workflow snapshot: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
1124
+ details: { workflowName, runId }
1125
+ },
1126
+ error$1
1127
+ );
1128
+ }
827
1129
  }
828
1130
  /**
829
1131
  * Insert multiple records in a batch operation
@@ -857,13 +1159,77 @@ var D1Store = class extends storage.MastraStorage {
857
1159
  );
858
1160
  }
859
1161
  this.logger.debug(`Successfully batch inserted ${records.length} records into ${tableName}`);
860
- } catch (error) {
861
- this.logger.error(`Error batch inserting into ${tableName}:`, {
862
- message: error instanceof Error ? error.message : String(error)
863
- });
864
- throw new Error(`Failed to batch insert into ${tableName}: ${error}`);
1162
+ } catch (error$1) {
1163
+ throw new error.MastraError(
1164
+ {
1165
+ id: "CLOUDFLARE_D1_STORAGE_BATCH_INSERT_ERROR",
1166
+ domain: error.ErrorDomain.STORAGE,
1167
+ category: error.ErrorCategory.THIRD_PARTY,
1168
+ text: `Failed to batch insert into ${tableName}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
1169
+ details: { tableName }
1170
+ },
1171
+ error$1
1172
+ );
865
1173
  }
866
1174
  }
1175
+ /**
1176
+ * Upsert multiple records in a batch operation
1177
+ * @param tableName The table to insert into
1178
+ * @param records The records to insert
1179
+ */
1180
+ async batchUpsert({
1181
+ tableName,
1182
+ records
1183
+ }) {
1184
+ if (records.length === 0) return;
1185
+ const fullTableName = this.getTableName(tableName);
1186
+ try {
1187
+ const batchSize = 50;
1188
+ for (let i = 0; i < records.length; i += batchSize) {
1189
+ const batch = records.slice(i, i + batchSize);
1190
+ const recordsToInsert = batch;
1191
+ if (recordsToInsert.length > 0) {
1192
+ const firstRecord = recordsToInsert[0];
1193
+ const columns = Object.keys(firstRecord || {});
1194
+ for (const record of recordsToInsert) {
1195
+ const values = columns.map((col) => {
1196
+ if (!record) return null;
1197
+ const value = typeof col === "string" ? record[col] : null;
1198
+ return this.serializeValue(value);
1199
+ });
1200
+ const recordToUpsert = columns.reduce(
1201
+ (acc, col) => {
1202
+ if (col !== "createdAt") acc[col] = `excluded.${col}`;
1203
+ return acc;
1204
+ },
1205
+ {}
1206
+ );
1207
+ const query = createSqlBuilder().insert(fullTableName, columns, values, ["id"], recordToUpsert);
1208
+ const { sql, params } = query.build();
1209
+ await this.executeQuery({ sql, params });
1210
+ }
1211
+ }
1212
+ this.logger.debug(
1213
+ `Processed batch ${Math.floor(i / batchSize) + 1} of ${Math.ceil(records.length / batchSize)}`
1214
+ );
1215
+ }
1216
+ this.logger.debug(`Successfully batch upserted ${records.length} records into ${tableName}`);
1217
+ } catch (error$1) {
1218
+ throw new error.MastraError(
1219
+ {
1220
+ id: "CLOUDFLARE_D1_STORAGE_BATCH_UPSERT_ERROR",
1221
+ domain: error.ErrorDomain.STORAGE,
1222
+ category: error.ErrorCategory.THIRD_PARTY,
1223
+ text: `Failed to batch upsert into ${tableName}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
1224
+ details: { tableName }
1225
+ },
1226
+ error$1
1227
+ );
1228
+ }
1229
+ }
1230
+ /**
1231
+ * @deprecated use getTracesPaginated instead
1232
+ */
867
1233
  async getTraces({
868
1234
  name,
869
1235
  scope,
@@ -893,22 +1259,108 @@ var D1Store = class extends storage.MastraStorage {
893
1259
  if (toDate) {
894
1260
  query.andWhere("createdAt <= ?", toDate instanceof Date ? toDate.toISOString() : toDate);
895
1261
  }
896
- query.orderBy("startTime", "DESC").limit(perPage).offset((page - 1) * perPage);
1262
+ query.orderBy("startTime", "DESC").limit(perPage).offset(page * perPage);
897
1263
  const { sql, params } = query.build();
898
1264
  const results = await this.executeQuery({ sql, params });
899
- return isArrayOfRecords(results) ? results.map((trace) => ({
900
- ...trace,
901
- attributes: this.deserializeValue(trace.attributes, "jsonb"),
902
- status: this.deserializeValue(trace.status, "jsonb"),
903
- events: this.deserializeValue(trace.events, "jsonb"),
904
- links: this.deserializeValue(trace.links, "jsonb"),
905
- other: this.deserializeValue(trace.other, "jsonb")
906
- })) : [];
907
- } catch (error) {
908
- this.logger.error("Error getting traces:", { message: error instanceof Error ? error.message : String(error) });
1265
+ return isArrayOfRecords(results) ? results.map(
1266
+ (trace) => ({
1267
+ ...trace,
1268
+ attributes: this.deserializeValue(trace.attributes, "jsonb"),
1269
+ status: this.deserializeValue(trace.status, "jsonb"),
1270
+ events: this.deserializeValue(trace.events, "jsonb"),
1271
+ links: this.deserializeValue(trace.links, "jsonb"),
1272
+ other: this.deserializeValue(trace.other, "jsonb")
1273
+ })
1274
+ ) : [];
1275
+ } catch (error$1) {
1276
+ const mastraError = new error.MastraError(
1277
+ {
1278
+ id: "CLOUDFLARE_D1_STORAGE_GET_TRACES_ERROR",
1279
+ domain: error.ErrorDomain.STORAGE,
1280
+ category: error.ErrorCategory.THIRD_PARTY,
1281
+ text: `Failed to retrieve traces: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
1282
+ details: {
1283
+ name: name ?? "",
1284
+ scope: scope ?? ""
1285
+ }
1286
+ },
1287
+ error$1
1288
+ );
1289
+ this.logger?.error(mastraError.toString());
1290
+ this.logger?.trackException(mastraError);
909
1291
  return [];
910
1292
  }
911
1293
  }
1294
+ async getTracesPaginated(args) {
1295
+ const { name, scope, page, perPage, attributes, fromDate, toDate } = args;
1296
+ const fullTableName = this.getTableName(storage.TABLE_TRACES);
1297
+ try {
1298
+ const dataQuery = createSqlBuilder().select("*").from(fullTableName).where("1=1");
1299
+ const countQuery = createSqlBuilder().count().from(fullTableName).where("1=1");
1300
+ if (name) {
1301
+ dataQuery.andWhere("name LIKE ?", `%${name}%`);
1302
+ countQuery.andWhere("name LIKE ?", `%${name}%`);
1303
+ }
1304
+ if (scope) {
1305
+ dataQuery.andWhere("scope = ?", scope);
1306
+ countQuery.andWhere("scope = ?", scope);
1307
+ }
1308
+ if (attributes && Object.keys(attributes).length > 0) {
1309
+ for (const [key, value] of Object.entries(attributes)) {
1310
+ dataQuery.jsonLike("attributes", key, value);
1311
+ countQuery.jsonLike("attributes", key, value);
1312
+ }
1313
+ }
1314
+ if (fromDate) {
1315
+ const fromDateStr = fromDate instanceof Date ? fromDate.toISOString() : fromDate;
1316
+ dataQuery.andWhere("createdAt >= ?", fromDateStr);
1317
+ countQuery.andWhere("createdAt >= ?", fromDateStr);
1318
+ }
1319
+ if (toDate) {
1320
+ const toDateStr = toDate instanceof Date ? toDate.toISOString() : toDate;
1321
+ dataQuery.andWhere("createdAt <= ?", toDateStr);
1322
+ countQuery.andWhere("createdAt <= ?", toDateStr);
1323
+ }
1324
+ const countResult = await this.executeQuery(countQuery.build());
1325
+ const total = Number(countResult?.[0]?.count ?? 0);
1326
+ dataQuery.orderBy("startTime", "DESC").limit(perPage).offset(page * perPage);
1327
+ const results = await this.executeQuery(dataQuery.build());
1328
+ const traces = isArrayOfRecords(results) ? results.map(
1329
+ (trace) => ({
1330
+ ...trace,
1331
+ attributes: this.deserializeValue(trace.attributes, "jsonb"),
1332
+ status: this.deserializeValue(trace.status, "jsonb"),
1333
+ events: this.deserializeValue(trace.events, "jsonb"),
1334
+ links: this.deserializeValue(trace.links, "jsonb"),
1335
+ other: this.deserializeValue(trace.other, "jsonb")
1336
+ })
1337
+ ) : [];
1338
+ return {
1339
+ traces,
1340
+ total,
1341
+ page,
1342
+ perPage,
1343
+ hasMore: page * perPage + traces.length < total
1344
+ };
1345
+ } catch (error$1) {
1346
+ const mastraError = new error.MastraError(
1347
+ {
1348
+ id: "CLOUDFLARE_D1_STORAGE_GET_TRACES_ERROR",
1349
+ domain: error.ErrorDomain.STORAGE,
1350
+ category: error.ErrorCategory.THIRD_PARTY,
1351
+ text: `Failed to retrieve traces: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
1352
+ details: { name: name ?? "", scope: scope ?? "" }
1353
+ },
1354
+ error$1
1355
+ );
1356
+ this.logger?.error(mastraError.toString());
1357
+ this.logger?.trackException(mastraError);
1358
+ return { traces: [], total: 0, page, perPage, hasMore: false };
1359
+ }
1360
+ }
1361
+ /**
1362
+ * @deprecated use getEvals instead
1363
+ */
912
1364
  async getEvalsByAgentName(agentName, type) {
913
1365
  const fullTableName = this.getTableName(storage.TABLE_EVALS);
914
1366
  try {
@@ -937,13 +1389,109 @@ var D1Store = class extends storage.MastraStorage {
937
1389
  testInfo
938
1390
  };
939
1391
  }) : [];
940
- } catch (error) {
941
- this.logger.error(`Error getting evals for agent ${agentName}:`, {
942
- message: error instanceof Error ? error.message : String(error)
943
- });
1392
+ } catch (error$1) {
1393
+ const mastraError = new error.MastraError(
1394
+ {
1395
+ id: "CLOUDFLARE_D1_STORAGE_GET_EVALS_ERROR",
1396
+ domain: error.ErrorDomain.STORAGE,
1397
+ category: error.ErrorCategory.THIRD_PARTY,
1398
+ text: `Failed to retrieve evals for agent ${agentName}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
1399
+ details: { agentName }
1400
+ },
1401
+ error$1
1402
+ );
1403
+ this.logger?.error(mastraError.toString());
1404
+ this.logger?.trackException(mastraError);
944
1405
  return [];
945
1406
  }
946
1407
  }
1408
+ async getEvals(options) {
1409
+ const { agentName, type, page = 0, perPage = 40, fromDate, toDate } = options || {};
1410
+ const fullTableName = this.getTableName(storage.TABLE_EVALS);
1411
+ const conditions = [];
1412
+ const queryParams = [];
1413
+ if (agentName) {
1414
+ conditions.push(`agent_name = ?`);
1415
+ queryParams.push(agentName);
1416
+ }
1417
+ if (type === "test") {
1418
+ conditions.push(`(test_info IS NOT NULL AND json_extract(test_info, '$.testPath') IS NOT NULL)`);
1419
+ } else if (type === "live") {
1420
+ conditions.push(`(test_info IS NULL OR json_extract(test_info, '$.testPath') IS NULL)`);
1421
+ }
1422
+ if (fromDate) {
1423
+ conditions.push(`createdAt >= ?`);
1424
+ queryParams.push(this.serializeDate(fromDate));
1425
+ }
1426
+ if (toDate) {
1427
+ conditions.push(`createdAt <= ?`);
1428
+ queryParams.push(this.serializeDate(toDate));
1429
+ }
1430
+ const countQueryBuilder = createSqlBuilder().count().from(fullTableName);
1431
+ if (conditions.length > 0) {
1432
+ countQueryBuilder.where(conditions.join(" AND "), ...queryParams);
1433
+ }
1434
+ const { sql: countSql, params: countParams } = countQueryBuilder.build();
1435
+ try {
1436
+ const countResult = await this.executeQuery({ sql: countSql, params: countParams, first: true });
1437
+ const total = Number(countResult?.count || 0);
1438
+ const currentOffset = page * perPage;
1439
+ if (total === 0) {
1440
+ return {
1441
+ evals: [],
1442
+ total: 0,
1443
+ page,
1444
+ perPage,
1445
+ hasMore: false
1446
+ };
1447
+ }
1448
+ const dataQueryBuilder = createSqlBuilder().select("*").from(fullTableName);
1449
+ if (conditions.length > 0) {
1450
+ dataQueryBuilder.where(conditions.join(" AND "), ...queryParams);
1451
+ }
1452
+ dataQueryBuilder.orderBy("createdAt", "DESC").limit(perPage).offset(currentOffset);
1453
+ const { sql: dataSql, params: dataParams } = dataQueryBuilder.build();
1454
+ const rows = await this.executeQuery({ sql: dataSql, params: dataParams });
1455
+ const evals = (isArrayOfRecords(rows) ? rows : []).map((row) => {
1456
+ const result = this.deserializeValue(row.result);
1457
+ const testInfo = row.test_info ? this.deserializeValue(row.test_info) : void 0;
1458
+ if (!result || typeof result !== "object" || !("score" in result)) {
1459
+ throw new Error(`Invalid MetricResult format: ${JSON.stringify(result)}`);
1460
+ }
1461
+ return {
1462
+ input: row.input,
1463
+ output: row.output,
1464
+ result,
1465
+ agentName: row.agent_name,
1466
+ metricName: row.metric_name,
1467
+ instructions: row.instructions,
1468
+ testInfo,
1469
+ globalRunId: row.global_run_id,
1470
+ runId: row.run_id,
1471
+ createdAt: row.createdAt
1472
+ };
1473
+ });
1474
+ const hasMore = currentOffset + evals.length < total;
1475
+ return {
1476
+ evals,
1477
+ total,
1478
+ page,
1479
+ perPage,
1480
+ hasMore
1481
+ };
1482
+ } catch (error$1) {
1483
+ throw new error.MastraError(
1484
+ {
1485
+ id: "CLOUDFLARE_D1_STORAGE_GET_EVALS_ERROR",
1486
+ domain: error.ErrorDomain.STORAGE,
1487
+ category: error.ErrorCategory.THIRD_PARTY,
1488
+ text: `Failed to retrieve evals for agent ${agentName}: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
1489
+ details: { agentName: agentName ?? "", type: type ?? "" }
1490
+ },
1491
+ error$1
1492
+ );
1493
+ }
1494
+ }
947
1495
  parseWorkflowRun(row) {
948
1496
  let parsedSnapshot = row.snapshot;
949
1497
  if (typeof parsedSnapshot === "string") {
@@ -1011,11 +1559,17 @@ var D1Store = class extends storage.MastraStorage {
1011
1559
  const results = await this.executeQuery({ sql, params });
1012
1560
  const runs = (isArrayOfRecords(results) ? results : []).map((row) => this.parseWorkflowRun(row));
1013
1561
  return { runs, total: total || runs.length };
1014
- } catch (error) {
1015
- this.logger.error("Error getting workflow runs:", {
1016
- message: error instanceof Error ? error.message : String(error)
1017
- });
1018
- throw error;
1562
+ } catch (error$1) {
1563
+ throw new error.MastraError(
1564
+ {
1565
+ id: "CLOUDFLARE_D1_STORAGE_GET_WORKFLOW_RUNS_ERROR",
1566
+ domain: error.ErrorDomain.STORAGE,
1567
+ category: error.ErrorCategory.THIRD_PARTY,
1568
+ text: `Failed to retrieve workflow runs: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
1569
+ details: { workflowName: workflowName ?? "", resourceId: resourceId ?? "" }
1570
+ },
1571
+ error$1
1572
+ );
1019
1573
  }
1020
1574
  }
1021
1575
  async getWorkflowRunById({
@@ -1039,11 +1593,17 @@ var D1Store = class extends storage.MastraStorage {
1039
1593
  const result = await this.executeQuery({ sql, params, first: true });
1040
1594
  if (!result) return null;
1041
1595
  return this.parseWorkflowRun(result);
1042
- } catch (error) {
1043
- this.logger.error("Error getting workflow run by ID:", {
1044
- message: error instanceof Error ? error.message : String(error)
1045
- });
1046
- throw error;
1596
+ } catch (error$1) {
1597
+ throw new error.MastraError(
1598
+ {
1599
+ id: "CLOUDFLARE_D1_STORAGE_GET_WORKFLOW_RUN_BY_ID_ERROR",
1600
+ domain: error.ErrorDomain.STORAGE,
1601
+ category: error.ErrorCategory.THIRD_PARTY,
1602
+ text: `Failed to retrieve workflow run by ID: ${error$1 instanceof Error ? error$1.message : String(error$1)}`,
1603
+ details: { runId, workflowName: workflowName ?? "" }
1604
+ },
1605
+ error$1
1606
+ );
1047
1607
  }
1048
1608
  }
1049
1609
  /**
@@ -1053,6 +1613,10 @@ var D1Store = class extends storage.MastraStorage {
1053
1613
  async close() {
1054
1614
  this.logger.debug("Closing D1 connection");
1055
1615
  }
1616
+ async updateMessages(_args) {
1617
+ this.logger.error("updateMessages is not yet implemented in CloudflareD1Store");
1618
+ throw new Error("Method not implemented");
1619
+ }
1056
1620
  };
1057
1621
 
1058
1622
  exports.D1Store = D1Store;