@mastra/cloudflare-d1 0.0.0-vnextWorkflows-20250422142014 → 0.0.0-workflow-deno-20250616115451
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/_tsup-dts-rollup.d.cts +113 -43
- package/dist/_tsup-dts-rollup.d.ts +113 -43
- package/dist/index.cjs +514 -123
- package/dist/index.d.cts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +514 -123
- package/package.json +17 -13
package/dist/index.cjs
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var agent = require('@mastra/core/agent');
|
|
3
4
|
var storage = require('@mastra/core/storage');
|
|
4
5
|
var Cloudflare = require('cloudflare');
|
|
6
|
+
var utils = require('@mastra/core/utils');
|
|
5
7
|
|
|
6
8
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
9
|
|
|
8
10
|
var Cloudflare__default = /*#__PURE__*/_interopDefault(Cloudflare);
|
|
9
11
|
|
|
10
12
|
// src/storage/index.ts
|
|
11
|
-
|
|
12
|
-
// src/storage/sql-builder.ts
|
|
13
13
|
var SqlBuilder = class {
|
|
14
14
|
sql = "";
|
|
15
15
|
params = [];
|
|
@@ -19,12 +19,15 @@ var SqlBuilder = class {
|
|
|
19
19
|
if (!columns || Array.isArray(columns) && columns.length === 0) {
|
|
20
20
|
this.sql = "SELECT *";
|
|
21
21
|
} else {
|
|
22
|
-
|
|
22
|
+
const cols = Array.isArray(columns) ? columns : [columns];
|
|
23
|
+
const parsedCols = cols.map((col) => parseSelectIdentifier(col));
|
|
24
|
+
this.sql = `SELECT ${parsedCols.join(", ")}`;
|
|
23
25
|
}
|
|
24
26
|
return this;
|
|
25
27
|
}
|
|
26
28
|
from(table) {
|
|
27
|
-
|
|
29
|
+
const parsedTableName = utils.parseSqlIdentifier(table, "table name");
|
|
30
|
+
this.sql += ` FROM ${parsedTableName}`;
|
|
28
31
|
return this;
|
|
29
32
|
}
|
|
30
33
|
/**
|
|
@@ -61,7 +64,11 @@ var SqlBuilder = class {
|
|
|
61
64
|
return this;
|
|
62
65
|
}
|
|
63
66
|
orderBy(column, direction = "ASC") {
|
|
64
|
-
|
|
67
|
+
const parsedColumn = utils.parseSqlIdentifier(column, "column name");
|
|
68
|
+
if (!["ASC", "DESC"].includes(direction)) {
|
|
69
|
+
throw new Error(`Invalid sort direction: ${direction}`);
|
|
70
|
+
}
|
|
71
|
+
this.sql += ` ORDER BY ${parsedColumn} ${direction}`;
|
|
65
72
|
return this;
|
|
66
73
|
}
|
|
67
74
|
limit(count) {
|
|
@@ -74,6 +81,10 @@ var SqlBuilder = class {
|
|
|
74
81
|
this.params.push(count);
|
|
75
82
|
return this;
|
|
76
83
|
}
|
|
84
|
+
count() {
|
|
85
|
+
this.sql += "SELECT COUNT(*) AS count";
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
77
88
|
/**
|
|
78
89
|
* Insert a row, or update specific columns on conflict (upsert).
|
|
79
90
|
* @param table Table name
|
|
@@ -83,27 +94,33 @@ var SqlBuilder = class {
|
|
|
83
94
|
* @param updateMap Object mapping columns to update to their new value (e.g. { name: 'excluded.name' })
|
|
84
95
|
*/
|
|
85
96
|
insert(table, columns, values, conflictColumns, updateMap) {
|
|
86
|
-
const
|
|
97
|
+
const parsedTableName = utils.parseSqlIdentifier(table, "table name");
|
|
98
|
+
const parsedColumns = columns.map((col) => utils.parseSqlIdentifier(col, "column name"));
|
|
99
|
+
const placeholders = parsedColumns.map(() => "?").join(", ");
|
|
87
100
|
if (conflictColumns && updateMap) {
|
|
101
|
+
const parsedConflictColumns = conflictColumns.map((col) => utils.parseSqlIdentifier(col, "column name"));
|
|
88
102
|
const updateClause = Object.entries(updateMap).map(([col, expr]) => `${col} = ${expr}`).join(", ");
|
|
89
|
-
this.sql = `INSERT INTO ${
|
|
103
|
+
this.sql = `INSERT INTO ${parsedTableName} (${parsedColumns.join(", ")}) VALUES (${placeholders}) ON CONFLICT(${parsedConflictColumns.join(", ")}) DO UPDATE SET ${updateClause}`;
|
|
90
104
|
this.params.push(...values);
|
|
91
105
|
return this;
|
|
92
106
|
}
|
|
93
|
-
this.sql = `INSERT INTO ${
|
|
107
|
+
this.sql = `INSERT INTO ${parsedTableName} (${parsedColumns.join(", ")}) VALUES (${placeholders})`;
|
|
94
108
|
this.params.push(...values);
|
|
95
109
|
return this;
|
|
96
110
|
}
|
|
97
111
|
// Update operations
|
|
98
112
|
update(table, columns, values) {
|
|
99
|
-
const
|
|
100
|
-
|
|
113
|
+
const parsedTableName = utils.parseSqlIdentifier(table, "table name");
|
|
114
|
+
const parsedColumns = columns.map((col) => utils.parseSqlIdentifier(col, "column name"));
|
|
115
|
+
const setClause = parsedColumns.map((col) => `${col} = ?`).join(", ");
|
|
116
|
+
this.sql = `UPDATE ${parsedTableName} SET ${setClause}`;
|
|
101
117
|
this.params.push(...values);
|
|
102
118
|
return this;
|
|
103
119
|
}
|
|
104
120
|
// Delete operations
|
|
105
121
|
delete(table) {
|
|
106
|
-
|
|
122
|
+
const parsedTableName = utils.parseSqlIdentifier(table, "table name");
|
|
123
|
+
this.sql = `DELETE FROM ${parsedTableName}`;
|
|
107
124
|
return this;
|
|
108
125
|
}
|
|
109
126
|
/**
|
|
@@ -114,9 +131,16 @@ var SqlBuilder = class {
|
|
|
114
131
|
* @returns The builder instance
|
|
115
132
|
*/
|
|
116
133
|
createTable(table, columnDefinitions, tableConstraints) {
|
|
117
|
-
const
|
|
134
|
+
const parsedTableName = utils.parseSqlIdentifier(table, "table name");
|
|
135
|
+
const parsedColumnDefinitions = columnDefinitions.map((def) => {
|
|
136
|
+
const colName = def.split(/\s+/)[0];
|
|
137
|
+
if (!colName) throw new Error("Empty column name in definition");
|
|
138
|
+
utils.parseSqlIdentifier(colName, "column name");
|
|
139
|
+
return def;
|
|
140
|
+
});
|
|
141
|
+
const columns = parsedColumnDefinitions.join(", ");
|
|
118
142
|
const constraints = tableConstraints && tableConstraints.length > 0 ? ", " + tableConstraints.join(", ") : "";
|
|
119
|
-
this.sql = `CREATE TABLE IF NOT EXISTS ${
|
|
143
|
+
this.sql = `CREATE TABLE IF NOT EXISTS ${parsedTableName} (${columns}${constraints})`;
|
|
120
144
|
return this;
|
|
121
145
|
}
|
|
122
146
|
/**
|
|
@@ -139,13 +163,10 @@ var SqlBuilder = class {
|
|
|
139
163
|
* @returns The builder instance
|
|
140
164
|
*/
|
|
141
165
|
createIndex(indexName, tableName, columnName, indexType = "") {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
raw(sql, ...params) {
|
|
147
|
-
this.sql = sql;
|
|
148
|
-
this.params.push(...params);
|
|
166
|
+
const parsedIndexName = utils.parseSqlIdentifier(indexName, "index name");
|
|
167
|
+
const parsedTableName = utils.parseSqlIdentifier(tableName, "table name");
|
|
168
|
+
const parsedColumnName = utils.parseSqlIdentifier(columnName, "column name");
|
|
169
|
+
this.sql = `CREATE ${indexType ? indexType + " " : ""}INDEX IF NOT EXISTS ${parsedIndexName} ON ${parsedTableName}(${parsedColumnName})`;
|
|
149
170
|
return this;
|
|
150
171
|
}
|
|
151
172
|
/**
|
|
@@ -155,11 +176,12 @@ var SqlBuilder = class {
|
|
|
155
176
|
* @param exact If true, will not add % wildcards
|
|
156
177
|
*/
|
|
157
178
|
like(column, value, exact = false) {
|
|
179
|
+
const parsedColumnName = utils.parseSqlIdentifier(column, "column name");
|
|
158
180
|
const likeValue = exact ? value : `%${value}%`;
|
|
159
181
|
if (this.whereAdded) {
|
|
160
|
-
this.sql += ` AND ${
|
|
182
|
+
this.sql += ` AND ${parsedColumnName} LIKE ?`;
|
|
161
183
|
} else {
|
|
162
|
-
this.sql += ` WHERE ${
|
|
184
|
+
this.sql += ` WHERE ${parsedColumnName} LIKE ?`;
|
|
163
185
|
this.whereAdded = true;
|
|
164
186
|
}
|
|
165
187
|
this.params.push(likeValue);
|
|
@@ -172,11 +194,13 @@ var SqlBuilder = class {
|
|
|
172
194
|
* @param value The value to match
|
|
173
195
|
*/
|
|
174
196
|
jsonLike(column, key, value) {
|
|
175
|
-
const
|
|
197
|
+
const parsedColumnName = utils.parseSqlIdentifier(column, "column name");
|
|
198
|
+
const parsedKey = utils.parseSqlIdentifier(key, "key name");
|
|
199
|
+
const jsonPattern = `%"${parsedKey}":"${value}"%`;
|
|
176
200
|
if (this.whereAdded) {
|
|
177
|
-
this.sql += ` AND ${
|
|
201
|
+
this.sql += ` AND ${parsedColumnName} LIKE ?`;
|
|
178
202
|
} else {
|
|
179
|
-
this.sql += ` WHERE ${
|
|
203
|
+
this.sql += ` WHERE ${parsedColumnName} LIKE ?`;
|
|
180
204
|
this.whereAdded = true;
|
|
181
205
|
}
|
|
182
206
|
this.params.push(jsonPattern);
|
|
@@ -206,6 +230,15 @@ var SqlBuilder = class {
|
|
|
206
230
|
function createSqlBuilder() {
|
|
207
231
|
return new SqlBuilder();
|
|
208
232
|
}
|
|
233
|
+
var SQL_IDENTIFIER_PATTERN = /^[a-zA-Z0-9_]+(\s+AS\s+[a-zA-Z0-9_]+)?$/;
|
|
234
|
+
function parseSelectIdentifier(column) {
|
|
235
|
+
if (column !== "*" && !SQL_IDENTIFIER_PATTERN.test(column)) {
|
|
236
|
+
throw new Error(
|
|
237
|
+
`Invalid column name: "${column}". Must be "*" or a valid identifier (letters, numbers, underscores), optionally with "AS alias".`
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
return column;
|
|
241
|
+
}
|
|
209
242
|
|
|
210
243
|
// src/storage/index.ts
|
|
211
244
|
function isArrayOfRecords(value) {
|
|
@@ -224,6 +257,9 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
224
257
|
*/
|
|
225
258
|
constructor(config) {
|
|
226
259
|
super({ name: "D1" });
|
|
260
|
+
if (config.tablePrefix && !/^[a-zA-Z0-9_]*$/.test(config.tablePrefix)) {
|
|
261
|
+
throw new Error("Invalid tablePrefix: only letters, numbers, and underscores are allowed.");
|
|
262
|
+
}
|
|
227
263
|
this.tablePrefix = config.tablePrefix || "";
|
|
228
264
|
if ("binding" in config) {
|
|
229
265
|
if (!config.binding) {
|
|
@@ -250,30 +286,6 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
250
286
|
formatSqlParams(params) {
|
|
251
287
|
return params.map((p) => p === void 0 || p === null ? null : p);
|
|
252
288
|
}
|
|
253
|
-
// Helper method to create SQL indexes for better query performance
|
|
254
|
-
async createIndexIfNotExists(tableName, columnName, indexType = "") {
|
|
255
|
-
const fullTableName = this.getTableName(tableName);
|
|
256
|
-
const indexName = `idx_${tableName}_${columnName}`;
|
|
257
|
-
try {
|
|
258
|
-
const checkQuery = createSqlBuilder().checkIndexExists(indexName, fullTableName);
|
|
259
|
-
const { sql: checkSql, params: checkParams } = checkQuery.build();
|
|
260
|
-
const indexExists = await this.executeQuery({
|
|
261
|
-
sql: checkSql,
|
|
262
|
-
params: checkParams,
|
|
263
|
-
first: true
|
|
264
|
-
});
|
|
265
|
-
if (!indexExists) {
|
|
266
|
-
const createQuery = createSqlBuilder().createIndex(indexName, fullTableName, columnName, indexType);
|
|
267
|
-
const { sql: createSql, params: createParams } = createQuery.build();
|
|
268
|
-
await this.executeQuery({ sql: createSql, params: createParams });
|
|
269
|
-
this.logger.debug(`Created index ${indexName} on ${fullTableName}(${columnName})`);
|
|
270
|
-
}
|
|
271
|
-
} catch (error) {
|
|
272
|
-
this.logger.error(`Error creating index on ${fullTableName}(${columnName}):`, {
|
|
273
|
-
message: error instanceof Error ? error.message : String(error)
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
289
|
async executeWorkersBindingQuery({
|
|
278
290
|
sql,
|
|
279
291
|
params = [],
|
|
@@ -377,34 +389,25 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
377
389
|
throw new Error(`D1 query error: ${error.message}`);
|
|
378
390
|
}
|
|
379
391
|
}
|
|
380
|
-
// Helper to
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
return
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
392
|
+
// Helper to get existing table columns
|
|
393
|
+
async getTableColumns(tableName) {
|
|
394
|
+
try {
|
|
395
|
+
const sql = `PRAGMA table_info(${tableName})`;
|
|
396
|
+
const result = await this.executeQuery({ sql, params: [] });
|
|
397
|
+
if (!result || !Array.isArray(result)) {
|
|
398
|
+
return [];
|
|
399
|
+
}
|
|
400
|
+
return result.map((row) => ({
|
|
401
|
+
name: row.name,
|
|
402
|
+
type: row.type
|
|
403
|
+
}));
|
|
404
|
+
} catch (error) {
|
|
405
|
+
this.logger.error(`Error getting table columns for ${tableName}:`, {
|
|
406
|
+
message: error instanceof Error ? error.message : String(error)
|
|
407
|
+
});
|
|
408
|
+
return [];
|
|
397
409
|
}
|
|
398
410
|
}
|
|
399
|
-
ensureDate(date) {
|
|
400
|
-
if (!date) return void 0;
|
|
401
|
-
return date instanceof Date ? date : new Date(date);
|
|
402
|
-
}
|
|
403
|
-
serializeDate(date) {
|
|
404
|
-
if (!date) return void 0;
|
|
405
|
-
const dateObj = this.ensureDate(date);
|
|
406
|
-
return dateObj?.toISOString();
|
|
407
|
-
}
|
|
408
411
|
// Helper to serialize objects to JSON strings
|
|
409
412
|
serializeValue(value) {
|
|
410
413
|
if (value === null || value === void 0) return null;
|
|
@@ -438,6 +441,18 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
438
441
|
}
|
|
439
442
|
return value;
|
|
440
443
|
}
|
|
444
|
+
getSqlType(type) {
|
|
445
|
+
switch (type) {
|
|
446
|
+
case "bigint":
|
|
447
|
+
return "INTEGER";
|
|
448
|
+
// SQLite uses INTEGER for all integer sizes
|
|
449
|
+
case "jsonb":
|
|
450
|
+
return "TEXT";
|
|
451
|
+
// Store JSON as TEXT in SQLite
|
|
452
|
+
default:
|
|
453
|
+
return super.getSqlType(type);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
441
456
|
async createTable({
|
|
442
457
|
tableName,
|
|
443
458
|
schema
|
|
@@ -465,6 +480,39 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
465
480
|
throw new Error(`Failed to create table ${fullTableName}: ${error}`);
|
|
466
481
|
}
|
|
467
482
|
}
|
|
483
|
+
/**
|
|
484
|
+
* Alters table schema to add columns if they don't exist
|
|
485
|
+
* @param tableName Name of the table
|
|
486
|
+
* @param schema Schema of the table
|
|
487
|
+
* @param ifNotExists Array of column names to add if they don't exist
|
|
488
|
+
*/
|
|
489
|
+
async alterTable({
|
|
490
|
+
tableName,
|
|
491
|
+
schema,
|
|
492
|
+
ifNotExists
|
|
493
|
+
}) {
|
|
494
|
+
const fullTableName = this.getTableName(tableName);
|
|
495
|
+
try {
|
|
496
|
+
const existingColumns = await this.getTableColumns(fullTableName);
|
|
497
|
+
const existingColumnNames = new Set(existingColumns.map((col) => col.name.toLowerCase()));
|
|
498
|
+
for (const columnName of ifNotExists) {
|
|
499
|
+
if (!existingColumnNames.has(columnName.toLowerCase()) && schema[columnName]) {
|
|
500
|
+
const columnDef = schema[columnName];
|
|
501
|
+
const sqlType = this.getSqlType(columnDef.type);
|
|
502
|
+
const nullable = columnDef.nullable === false ? "NOT NULL" : "";
|
|
503
|
+
const defaultValue = columnDef.nullable === false ? this.getDefaultValue(columnDef.type) : "";
|
|
504
|
+
const alterSql = `ALTER TABLE ${fullTableName} ADD COLUMN ${columnName} ${sqlType} ${nullable} ${defaultValue}`.trim();
|
|
505
|
+
await this.executeQuery({ sql: alterSql, params: [] });
|
|
506
|
+
this.logger.debug(`Added column ${columnName} to table ${fullTableName}`);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
} catch (error) {
|
|
510
|
+
this.logger.error(`Error altering table ${fullTableName}:`, {
|
|
511
|
+
message: error instanceof Error ? error.message : String(error)
|
|
512
|
+
});
|
|
513
|
+
throw new Error(`Failed to alter table ${fullTableName}: ${error}`);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
468
516
|
async clearTable({ tableName }) {
|
|
469
517
|
const fullTableName = this.getTableName(tableName);
|
|
470
518
|
try {
|
|
@@ -496,7 +544,8 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
496
544
|
try {
|
|
497
545
|
await this.executeQuery({ sql, params });
|
|
498
546
|
} catch (error) {
|
|
499
|
-
|
|
547
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
548
|
+
this.logger.error(`Error inserting into ${fullTableName}:`, { message });
|
|
500
549
|
throw new Error(`Failed to insert into ${fullTableName}: ${error}`);
|
|
501
550
|
}
|
|
502
551
|
}
|
|
@@ -549,6 +598,9 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
549
598
|
return null;
|
|
550
599
|
}
|
|
551
600
|
}
|
|
601
|
+
/**
|
|
602
|
+
* @deprecated use getThreadsByResourceIdPaginated instead
|
|
603
|
+
*/
|
|
552
604
|
async getThreadsByResourceId({ resourceId }) {
|
|
553
605
|
const fullTableName = this.getTableName(storage.TABLE_THREADS);
|
|
554
606
|
try {
|
|
@@ -568,6 +620,29 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
568
620
|
return [];
|
|
569
621
|
}
|
|
570
622
|
}
|
|
623
|
+
async getThreadsByResourceIdPaginated(args) {
|
|
624
|
+
const { resourceId, page, perPage } = args;
|
|
625
|
+
const fullTableName = this.getTableName(storage.TABLE_THREADS);
|
|
626
|
+
const mapRowToStorageThreadType = (row) => ({
|
|
627
|
+
...row,
|
|
628
|
+
createdAt: this.ensureDate(row.createdAt),
|
|
629
|
+
updatedAt: this.ensureDate(row.updatedAt),
|
|
630
|
+
metadata: typeof row.metadata === "string" ? JSON.parse(row.metadata || "{}") : row.metadata || {}
|
|
631
|
+
});
|
|
632
|
+
const countQuery = createSqlBuilder().count().from(fullTableName).where("resourceId = ?", resourceId);
|
|
633
|
+
const countResult = await this.executeQuery(countQuery.build());
|
|
634
|
+
const total = Number(countResult?.[0]?.count ?? 0);
|
|
635
|
+
const selectQuery = createSqlBuilder().select("*").from(fullTableName).where("resourceId = ?", resourceId).orderBy("createdAt", "DESC").limit(perPage).offset(page * perPage);
|
|
636
|
+
const results = await this.executeQuery(selectQuery.build());
|
|
637
|
+
const threads = results.map(mapRowToStorageThreadType);
|
|
638
|
+
return {
|
|
639
|
+
threads,
|
|
640
|
+
total,
|
|
641
|
+
page,
|
|
642
|
+
perPage,
|
|
643
|
+
hasMore: page * perPage + threads.length < total
|
|
644
|
+
};
|
|
645
|
+
}
|
|
571
646
|
async saveThread({ thread }) {
|
|
572
647
|
const fullTableName = this.getTableName(storage.TABLE_THREADS);
|
|
573
648
|
const threadToSave = {
|
|
@@ -594,7 +669,8 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
594
669
|
await this.executeQuery({ sql, params });
|
|
595
670
|
return thread;
|
|
596
671
|
} catch (error) {
|
|
597
|
-
|
|
672
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
673
|
+
this.logger.error(`Error saving thread to ${fullTableName}:`, { message });
|
|
598
674
|
throw error;
|
|
599
675
|
}
|
|
600
676
|
}
|
|
@@ -628,7 +704,8 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
628
704
|
updatedAt: /* @__PURE__ */ new Date()
|
|
629
705
|
};
|
|
630
706
|
} catch (error) {
|
|
631
|
-
|
|
707
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
708
|
+
this.logger.error("Error updating thread:", { message });
|
|
632
709
|
throw error;
|
|
633
710
|
}
|
|
634
711
|
}
|
|
@@ -649,11 +726,12 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
649
726
|
throw new Error(`Failed to delete thread ${threadId}: ${error}`);
|
|
650
727
|
}
|
|
651
728
|
}
|
|
652
|
-
|
|
653
|
-
|
|
729
|
+
async saveMessages(args) {
|
|
730
|
+
const { messages, format = "v1" } = args;
|
|
654
731
|
if (messages.length === 0) return [];
|
|
655
732
|
try {
|
|
656
733
|
const now = /* @__PURE__ */ new Date();
|
|
734
|
+
const threadId = messages[0]?.threadId;
|
|
657
735
|
for (const [i, message] of messages.entries()) {
|
|
658
736
|
if (!message.id) throw new Error(`Message at index ${i} missing id`);
|
|
659
737
|
if (!message.threadId) throw new Error(`Message at index ${i} missing threadId`);
|
|
@@ -672,36 +750,42 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
672
750
|
content: typeof message.content === "string" ? message.content : JSON.stringify(message.content),
|
|
673
751
|
createdAt: createdAt.toISOString(),
|
|
674
752
|
role: message.role,
|
|
675
|
-
type: message.type
|
|
753
|
+
type: message.type || "v2",
|
|
754
|
+
resourceId: message.resourceId
|
|
676
755
|
};
|
|
677
756
|
});
|
|
678
|
-
await
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
757
|
+
await Promise.all([
|
|
758
|
+
this.batchInsert({
|
|
759
|
+
tableName: storage.TABLE_MESSAGES,
|
|
760
|
+
records: messagesToInsert
|
|
761
|
+
}),
|
|
762
|
+
// Update thread's updatedAt timestamp
|
|
763
|
+
this.executeQuery({
|
|
764
|
+
sql: `UPDATE ${this.getTableName(storage.TABLE_THREADS)} SET updatedAt = ? WHERE id = ?`,
|
|
765
|
+
params: [now.toISOString(), threadId]
|
|
766
|
+
})
|
|
767
|
+
]);
|
|
682
768
|
this.logger.debug(`Saved ${messages.length} messages`);
|
|
683
|
-
|
|
769
|
+
const list = new agent.MessageList().add(messages, "memory");
|
|
770
|
+
if (format === `v2`) return list.get.all.v2();
|
|
771
|
+
return list.get.all.v1();
|
|
684
772
|
} catch (error) {
|
|
685
773
|
this.logger.error("Error saving messages:", { message: error instanceof Error ? error.message : String(error) });
|
|
686
774
|
throw error;
|
|
687
775
|
}
|
|
688
776
|
}
|
|
689
|
-
async
|
|
690
|
-
const
|
|
691
|
-
|
|
692
|
-
const
|
|
693
|
-
const
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
const prevMax = Math.max(...include.map((i) => i.withPreviousMessages || 0));
|
|
697
|
-
const nextMax = Math.max(...include.map((i) => i.withNextMessages || 0));
|
|
698
|
-
const includeIds = include.map((i) => i.id);
|
|
699
|
-
const sql2 = `
|
|
777
|
+
async _getIncludedMessages(threadId, selectBy) {
|
|
778
|
+
const include = selectBy?.include;
|
|
779
|
+
if (!include) return null;
|
|
780
|
+
const prevMax = Math.max(...include.map((i) => i.withPreviousMessages || 0));
|
|
781
|
+
const nextMax = Math.max(...include.map((i) => i.withNextMessages || 0));
|
|
782
|
+
const includeIds = include.map((i) => i.id);
|
|
783
|
+
const sql = `
|
|
700
784
|
WITH ordered_messages AS (
|
|
701
785
|
SELECT
|
|
702
786
|
*,
|
|
703
787
|
ROW_NUMBER() OVER (ORDER BY createdAt DESC) AS row_num
|
|
704
|
-
FROM ${
|
|
788
|
+
FROM ${this.getTableName(storage.TABLE_MESSAGES)}
|
|
705
789
|
WHERE thread_id = ?
|
|
706
790
|
)
|
|
707
791
|
SELECT
|
|
@@ -710,7 +794,7 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
710
794
|
m.role,
|
|
711
795
|
m.type,
|
|
712
796
|
m.createdAt,
|
|
713
|
-
m.thread_id AS
|
|
797
|
+
m.thread_id AS threadId
|
|
714
798
|
FROM ordered_messages m
|
|
715
799
|
WHERE m.id IN (${includeIds.map(() => "?").join(",")})
|
|
716
800
|
OR EXISTS (
|
|
@@ -724,20 +808,38 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
724
808
|
)
|
|
725
809
|
ORDER BY m.createdAt DESC
|
|
726
810
|
`;
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
811
|
+
const params = [
|
|
812
|
+
threadId,
|
|
813
|
+
...includeIds,
|
|
814
|
+
// for m.id IN (...)
|
|
815
|
+
...includeIds,
|
|
816
|
+
// for target.id IN (...)
|
|
817
|
+
prevMax,
|
|
818
|
+
nextMax
|
|
819
|
+
];
|
|
820
|
+
const messages = await this.executeQuery({ sql, params });
|
|
821
|
+
return messages;
|
|
822
|
+
}
|
|
823
|
+
async getMessages({
|
|
824
|
+
threadId,
|
|
825
|
+
selectBy,
|
|
826
|
+
format
|
|
827
|
+
}) {
|
|
828
|
+
const fullTableName = this.getTableName(storage.TABLE_MESSAGES);
|
|
829
|
+
const limit = typeof selectBy?.last === "number" ? selectBy.last : 40;
|
|
830
|
+
const include = selectBy?.include || [];
|
|
831
|
+
const messages = [];
|
|
832
|
+
try {
|
|
833
|
+
if (include.length) {
|
|
834
|
+
const includeResult = await this._getIncludedMessages(threadId, selectBy);
|
|
737
835
|
if (Array.isArray(includeResult)) messages.push(...includeResult);
|
|
738
836
|
}
|
|
739
837
|
const excludeIds = messages.map((m) => m.id);
|
|
740
|
-
|
|
838
|
+
const query = createSqlBuilder().select(["id", "content", "role", "type", "createdAt", "thread_id AS threadId"]).from(fullTableName).where("thread_id = ?", threadId);
|
|
839
|
+
if (excludeIds.length > 0) {
|
|
840
|
+
query.andWhere(`id NOT IN (${excludeIds.map(() => "?").join(",")})`, ...excludeIds);
|
|
841
|
+
}
|
|
842
|
+
query.orderBy("createdAt", "DESC").limit(limit);
|
|
741
843
|
const { sql, params } = query.build();
|
|
742
844
|
const result = await this.executeQuery({ sql, params });
|
|
743
845
|
if (Array.isArray(result)) messages.push(...result);
|
|
@@ -751,12 +853,15 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
751
853
|
const processedMessages = messages.map((message) => {
|
|
752
854
|
const processedMsg = {};
|
|
753
855
|
for (const [key, value] of Object.entries(message)) {
|
|
856
|
+
if (key === `type` && value === `v2`) continue;
|
|
754
857
|
processedMsg[key] = this.deserializeValue(value);
|
|
755
858
|
}
|
|
756
859
|
return processedMsg;
|
|
757
860
|
});
|
|
758
861
|
this.logger.debug(`Retrieved ${messages.length} messages for thread ${threadId}`);
|
|
759
|
-
|
|
862
|
+
const list = new agent.MessageList().add(processedMessages, "memory");
|
|
863
|
+
if (format === `v2`) return list.get.all.v2();
|
|
864
|
+
return list.get.all.v1();
|
|
760
865
|
} catch (error) {
|
|
761
866
|
this.logger.error("Error retrieving messages for thread", {
|
|
762
867
|
threadId,
|
|
@@ -765,6 +870,47 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
765
870
|
return [];
|
|
766
871
|
}
|
|
767
872
|
}
|
|
873
|
+
async getMessagesPaginated({
|
|
874
|
+
threadId,
|
|
875
|
+
selectBy,
|
|
876
|
+
format
|
|
877
|
+
}) {
|
|
878
|
+
const { dateRange, page = 0, perPage = 40 } = selectBy?.pagination || {};
|
|
879
|
+
const { start: fromDate, end: toDate } = dateRange || {};
|
|
880
|
+
const fullTableName = this.getTableName(storage.TABLE_MESSAGES);
|
|
881
|
+
const messages = [];
|
|
882
|
+
if (selectBy?.include?.length) {
|
|
883
|
+
const includeResult = await this._getIncludedMessages(threadId, selectBy);
|
|
884
|
+
if (Array.isArray(includeResult)) messages.push(...includeResult);
|
|
885
|
+
}
|
|
886
|
+
const countQuery = createSqlBuilder().count().from(fullTableName).where("thread_id = ?", threadId);
|
|
887
|
+
if (fromDate) {
|
|
888
|
+
countQuery.andWhere("createdAt >= ?", this.serializeDate(fromDate));
|
|
889
|
+
}
|
|
890
|
+
if (toDate) {
|
|
891
|
+
countQuery.andWhere("createdAt <= ?", this.serializeDate(toDate));
|
|
892
|
+
}
|
|
893
|
+
const countResult = await this.executeQuery(countQuery.build());
|
|
894
|
+
const total = Number(countResult[0]?.count ?? 0);
|
|
895
|
+
const query = createSqlBuilder().select(["id", "content", "role", "type", "createdAt", "thread_id AS threadId"]).from(fullTableName).where("thread_id = ?", threadId);
|
|
896
|
+
if (fromDate) {
|
|
897
|
+
query.andWhere("createdAt >= ?", this.serializeDate(fromDate));
|
|
898
|
+
}
|
|
899
|
+
if (toDate) {
|
|
900
|
+
query.andWhere("createdAt <= ?", this.serializeDate(toDate));
|
|
901
|
+
}
|
|
902
|
+
query.orderBy("createdAt", "DESC").limit(perPage).offset(page * perPage);
|
|
903
|
+
const results = await this.executeQuery(query.build());
|
|
904
|
+
const list = new agent.MessageList().add(results, "memory");
|
|
905
|
+
messages.push(...format === `v2` ? list.get.all.v2() : list.get.all.v1());
|
|
906
|
+
return {
|
|
907
|
+
messages,
|
|
908
|
+
total,
|
|
909
|
+
page,
|
|
910
|
+
perPage,
|
|
911
|
+
hasMore: page * perPage + messages.length < total
|
|
912
|
+
};
|
|
913
|
+
}
|
|
768
914
|
async persistWorkflowSnapshot({
|
|
769
915
|
workflowName,
|
|
770
916
|
runId,
|
|
@@ -857,12 +1003,17 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
857
1003
|
throw new Error(`Failed to batch insert into ${tableName}: ${error}`);
|
|
858
1004
|
}
|
|
859
1005
|
}
|
|
1006
|
+
/**
|
|
1007
|
+
* @deprecated use getTracesPaginated instead
|
|
1008
|
+
*/
|
|
860
1009
|
async getTraces({
|
|
861
1010
|
name,
|
|
862
1011
|
scope,
|
|
863
1012
|
page,
|
|
864
1013
|
perPage,
|
|
865
|
-
attributes
|
|
1014
|
+
attributes,
|
|
1015
|
+
fromDate,
|
|
1016
|
+
toDate
|
|
866
1017
|
}) {
|
|
867
1018
|
const fullTableName = this.getTableName(storage.TABLE_TRACES);
|
|
868
1019
|
try {
|
|
@@ -878,22 +1029,89 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
878
1029
|
query.jsonLike("attributes", key, value);
|
|
879
1030
|
}
|
|
880
1031
|
}
|
|
881
|
-
|
|
1032
|
+
if (fromDate) {
|
|
1033
|
+
query.andWhere("createdAt >= ?", fromDate instanceof Date ? fromDate.toISOString() : fromDate);
|
|
1034
|
+
}
|
|
1035
|
+
if (toDate) {
|
|
1036
|
+
query.andWhere("createdAt <= ?", toDate instanceof Date ? toDate.toISOString() : toDate);
|
|
1037
|
+
}
|
|
1038
|
+
query.orderBy("startTime", "DESC").limit(perPage).offset(page * perPage);
|
|
882
1039
|
const { sql, params } = query.build();
|
|
883
1040
|
const results = await this.executeQuery({ sql, params });
|
|
884
|
-
return isArrayOfRecords(results) ? results.map(
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
1041
|
+
return isArrayOfRecords(results) ? results.map(
|
|
1042
|
+
(trace) => ({
|
|
1043
|
+
...trace,
|
|
1044
|
+
attributes: this.deserializeValue(trace.attributes, "jsonb"),
|
|
1045
|
+
status: this.deserializeValue(trace.status, "jsonb"),
|
|
1046
|
+
events: this.deserializeValue(trace.events, "jsonb"),
|
|
1047
|
+
links: this.deserializeValue(trace.links, "jsonb"),
|
|
1048
|
+
other: this.deserializeValue(trace.other, "jsonb")
|
|
1049
|
+
})
|
|
1050
|
+
) : [];
|
|
892
1051
|
} catch (error) {
|
|
893
1052
|
this.logger.error("Error getting traces:", { message: error instanceof Error ? error.message : String(error) });
|
|
894
1053
|
return [];
|
|
895
1054
|
}
|
|
896
1055
|
}
|
|
1056
|
+
async getTracesPaginated(args) {
|
|
1057
|
+
const { name, scope, page, perPage, attributes, fromDate, toDate } = args;
|
|
1058
|
+
const fullTableName = this.getTableName(storage.TABLE_TRACES);
|
|
1059
|
+
try {
|
|
1060
|
+
const dataQuery = createSqlBuilder().select("*").from(fullTableName).where("1=1");
|
|
1061
|
+
const countQuery = createSqlBuilder().count().from(fullTableName).where("1=1");
|
|
1062
|
+
if (name) {
|
|
1063
|
+
dataQuery.andWhere("name LIKE ?", `%${name}%`);
|
|
1064
|
+
countQuery.andWhere("name LIKE ?", `%${name}%`);
|
|
1065
|
+
}
|
|
1066
|
+
if (scope) {
|
|
1067
|
+
dataQuery.andWhere("scope = ?", scope);
|
|
1068
|
+
countQuery.andWhere("scope = ?", scope);
|
|
1069
|
+
}
|
|
1070
|
+
if (attributes && Object.keys(attributes).length > 0) {
|
|
1071
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
1072
|
+
dataQuery.jsonLike("attributes", key, value);
|
|
1073
|
+
countQuery.jsonLike("attributes", key, value);
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
if (fromDate) {
|
|
1077
|
+
const fromDateStr = fromDate instanceof Date ? fromDate.toISOString() : fromDate;
|
|
1078
|
+
dataQuery.andWhere("createdAt >= ?", fromDateStr);
|
|
1079
|
+
countQuery.andWhere("createdAt >= ?", fromDateStr);
|
|
1080
|
+
}
|
|
1081
|
+
if (toDate) {
|
|
1082
|
+
const toDateStr = toDate instanceof Date ? toDate.toISOString() : toDate;
|
|
1083
|
+
dataQuery.andWhere("createdAt <= ?", toDateStr);
|
|
1084
|
+
countQuery.andWhere("createdAt <= ?", toDateStr);
|
|
1085
|
+
}
|
|
1086
|
+
const countResult = await this.executeQuery(countQuery.build());
|
|
1087
|
+
const total = Number(countResult?.[0]?.count ?? 0);
|
|
1088
|
+
dataQuery.orderBy("startTime", "DESC").limit(perPage).offset(page * perPage);
|
|
1089
|
+
const results = await this.executeQuery(dataQuery.build());
|
|
1090
|
+
const traces = isArrayOfRecords(results) ? results.map(
|
|
1091
|
+
(trace) => ({
|
|
1092
|
+
...trace,
|
|
1093
|
+
attributes: this.deserializeValue(trace.attributes, "jsonb"),
|
|
1094
|
+
status: this.deserializeValue(trace.status, "jsonb"),
|
|
1095
|
+
events: this.deserializeValue(trace.events, "jsonb"),
|
|
1096
|
+
links: this.deserializeValue(trace.links, "jsonb"),
|
|
1097
|
+
other: this.deserializeValue(trace.other, "jsonb")
|
|
1098
|
+
})
|
|
1099
|
+
) : [];
|
|
1100
|
+
return {
|
|
1101
|
+
traces,
|
|
1102
|
+
total,
|
|
1103
|
+
page,
|
|
1104
|
+
perPage,
|
|
1105
|
+
hasMore: page * perPage + traces.length < total
|
|
1106
|
+
};
|
|
1107
|
+
} catch (error) {
|
|
1108
|
+
this.logger.error("Error getting traces:", { message: error instanceof Error ? error.message : String(error) });
|
|
1109
|
+
return { traces: [], total: 0, page, perPage, hasMore: false };
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
/**
|
|
1113
|
+
* @deprecated use getEvals instead
|
|
1114
|
+
*/
|
|
897
1115
|
async getEvalsByAgentName(agentName, type) {
|
|
898
1116
|
const fullTableName = this.getTableName(storage.TABLE_EVALS);
|
|
899
1117
|
try {
|
|
@@ -929,8 +1147,181 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
929
1147
|
return [];
|
|
930
1148
|
}
|
|
931
1149
|
}
|
|
932
|
-
|
|
933
|
-
|
|
1150
|
+
async getEvals(options) {
|
|
1151
|
+
const { agentName, type, page = 0, perPage = 40, fromDate, toDate } = options || {};
|
|
1152
|
+
const fullTableName = this.getTableName(storage.TABLE_EVALS);
|
|
1153
|
+
const conditions = [];
|
|
1154
|
+
const queryParams = [];
|
|
1155
|
+
if (agentName) {
|
|
1156
|
+
conditions.push(`agent_name = ?`);
|
|
1157
|
+
queryParams.push(agentName);
|
|
1158
|
+
}
|
|
1159
|
+
if (type === "test") {
|
|
1160
|
+
conditions.push(`(test_info IS NOT NULL AND json_extract(test_info, '$.testPath') IS NOT NULL)`);
|
|
1161
|
+
} else if (type === "live") {
|
|
1162
|
+
conditions.push(`(test_info IS NULL OR json_extract(test_info, '$.testPath') IS NULL)`);
|
|
1163
|
+
}
|
|
1164
|
+
if (fromDate) {
|
|
1165
|
+
conditions.push(`createdAt >= ?`);
|
|
1166
|
+
queryParams.push(this.serializeDate(fromDate));
|
|
1167
|
+
}
|
|
1168
|
+
if (toDate) {
|
|
1169
|
+
conditions.push(`createdAt <= ?`);
|
|
1170
|
+
queryParams.push(this.serializeDate(toDate));
|
|
1171
|
+
}
|
|
1172
|
+
const countQueryBuilder = createSqlBuilder().count().from(fullTableName);
|
|
1173
|
+
if (conditions.length > 0) {
|
|
1174
|
+
countQueryBuilder.where(conditions.join(" AND "), ...queryParams);
|
|
1175
|
+
}
|
|
1176
|
+
const { sql: countSql, params: countParams } = countQueryBuilder.build();
|
|
1177
|
+
const countResult = await this.executeQuery({ sql: countSql, params: countParams, first: true });
|
|
1178
|
+
const total = Number(countResult?.count || 0);
|
|
1179
|
+
const currentOffset = page * perPage;
|
|
1180
|
+
if (total === 0) {
|
|
1181
|
+
return {
|
|
1182
|
+
evals: [],
|
|
1183
|
+
total: 0,
|
|
1184
|
+
page,
|
|
1185
|
+
perPage,
|
|
1186
|
+
hasMore: false
|
|
1187
|
+
};
|
|
1188
|
+
}
|
|
1189
|
+
const dataQueryBuilder = createSqlBuilder().select("*").from(fullTableName);
|
|
1190
|
+
if (conditions.length > 0) {
|
|
1191
|
+
dataQueryBuilder.where(conditions.join(" AND "), ...queryParams);
|
|
1192
|
+
}
|
|
1193
|
+
dataQueryBuilder.orderBy("createdAt", "DESC").limit(perPage).offset(currentOffset);
|
|
1194
|
+
const { sql: dataSql, params: dataParams } = dataQueryBuilder.build();
|
|
1195
|
+
const rows = await this.executeQuery({ sql: dataSql, params: dataParams });
|
|
1196
|
+
const evals = (isArrayOfRecords(rows) ? rows : []).map((row) => {
|
|
1197
|
+
const result = this.deserializeValue(row.result);
|
|
1198
|
+
const testInfo = row.test_info ? this.deserializeValue(row.test_info) : void 0;
|
|
1199
|
+
if (!result || typeof result !== "object" || !("score" in result)) {
|
|
1200
|
+
throw new Error(`Invalid MetricResult format: ${JSON.stringify(result)}`);
|
|
1201
|
+
}
|
|
1202
|
+
return {
|
|
1203
|
+
input: row.input,
|
|
1204
|
+
output: row.output,
|
|
1205
|
+
result,
|
|
1206
|
+
agentName: row.agent_name,
|
|
1207
|
+
metricName: row.metric_name,
|
|
1208
|
+
instructions: row.instructions,
|
|
1209
|
+
testInfo,
|
|
1210
|
+
globalRunId: row.global_run_id,
|
|
1211
|
+
runId: row.run_id,
|
|
1212
|
+
createdAt: row.createdAt
|
|
1213
|
+
};
|
|
1214
|
+
});
|
|
1215
|
+
const hasMore = currentOffset + evals.length < total;
|
|
1216
|
+
return {
|
|
1217
|
+
evals,
|
|
1218
|
+
total,
|
|
1219
|
+
page,
|
|
1220
|
+
perPage,
|
|
1221
|
+
hasMore
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1224
|
+
parseWorkflowRun(row) {
|
|
1225
|
+
let parsedSnapshot = row.snapshot;
|
|
1226
|
+
if (typeof parsedSnapshot === "string") {
|
|
1227
|
+
try {
|
|
1228
|
+
parsedSnapshot = JSON.parse(row.snapshot);
|
|
1229
|
+
} catch (e) {
|
|
1230
|
+
console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
return {
|
|
1234
|
+
workflowName: row.workflow_name,
|
|
1235
|
+
runId: row.run_id,
|
|
1236
|
+
snapshot: parsedSnapshot,
|
|
1237
|
+
createdAt: this.ensureDate(row.createdAt),
|
|
1238
|
+
updatedAt: this.ensureDate(row.updatedAt),
|
|
1239
|
+
resourceId: row.resourceId
|
|
1240
|
+
};
|
|
1241
|
+
}
|
|
1242
|
+
async hasColumn(table, column) {
|
|
1243
|
+
const sql = `PRAGMA table_info(${table});`;
|
|
1244
|
+
const result = await this.executeQuery({ sql, params: [] });
|
|
1245
|
+
if (!result || !Array.isArray(result)) return false;
|
|
1246
|
+
return result.some((col) => col.name === column || col.name === column.toLowerCase());
|
|
1247
|
+
}
|
|
1248
|
+
async getWorkflowRuns({
|
|
1249
|
+
workflowName,
|
|
1250
|
+
fromDate,
|
|
1251
|
+
toDate,
|
|
1252
|
+
limit,
|
|
1253
|
+
offset,
|
|
1254
|
+
resourceId
|
|
1255
|
+
} = {}) {
|
|
1256
|
+
const fullTableName = this.getTableName(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1257
|
+
try {
|
|
1258
|
+
const builder = createSqlBuilder().select().from(fullTableName);
|
|
1259
|
+
const countBuilder = createSqlBuilder().count().from(fullTableName);
|
|
1260
|
+
if (workflowName) builder.whereAnd("workflow_name = ?", workflowName);
|
|
1261
|
+
if (resourceId) {
|
|
1262
|
+
const hasResourceId = await this.hasColumn(fullTableName, "resourceId");
|
|
1263
|
+
if (hasResourceId) {
|
|
1264
|
+
builder.whereAnd("resourceId = ?", resourceId);
|
|
1265
|
+
countBuilder.whereAnd("resourceId = ?", resourceId);
|
|
1266
|
+
} else {
|
|
1267
|
+
console.warn(`[${fullTableName}] resourceId column not found. Skipping resourceId filter.`);
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
if (fromDate) {
|
|
1271
|
+
builder.whereAnd("createdAt >= ?", fromDate instanceof Date ? fromDate.toISOString() : fromDate);
|
|
1272
|
+
countBuilder.whereAnd("createdAt >= ?", fromDate instanceof Date ? fromDate.toISOString() : fromDate);
|
|
1273
|
+
}
|
|
1274
|
+
if (toDate) {
|
|
1275
|
+
builder.whereAnd("createdAt <= ?", toDate instanceof Date ? toDate.toISOString() : toDate);
|
|
1276
|
+
countBuilder.whereAnd("createdAt <= ?", toDate instanceof Date ? toDate.toISOString() : toDate);
|
|
1277
|
+
}
|
|
1278
|
+
builder.orderBy("createdAt", "DESC");
|
|
1279
|
+
if (typeof limit === "number") builder.limit(limit);
|
|
1280
|
+
if (typeof offset === "number") builder.offset(offset);
|
|
1281
|
+
const { sql, params } = builder.build();
|
|
1282
|
+
let total = 0;
|
|
1283
|
+
if (limit !== void 0 && offset !== void 0) {
|
|
1284
|
+
const { sql: countSql, params: countParams } = countBuilder.build();
|
|
1285
|
+
const countResult = await this.executeQuery({ sql: countSql, params: countParams, first: true });
|
|
1286
|
+
total = Number(countResult?.count ?? 0);
|
|
1287
|
+
}
|
|
1288
|
+
const results = await this.executeQuery({ sql, params });
|
|
1289
|
+
const runs = (isArrayOfRecords(results) ? results : []).map((row) => this.parseWorkflowRun(row));
|
|
1290
|
+
return { runs, total: total || runs.length };
|
|
1291
|
+
} catch (error) {
|
|
1292
|
+
this.logger.error("Error getting workflow runs:", {
|
|
1293
|
+
message: error instanceof Error ? error.message : String(error)
|
|
1294
|
+
});
|
|
1295
|
+
throw error;
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
async getWorkflowRunById({
|
|
1299
|
+
runId,
|
|
1300
|
+
workflowName
|
|
1301
|
+
}) {
|
|
1302
|
+
const fullTableName = this.getTableName(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1303
|
+
try {
|
|
1304
|
+
const conditions = [];
|
|
1305
|
+
const params = [];
|
|
1306
|
+
if (runId) {
|
|
1307
|
+
conditions.push("run_id = ?");
|
|
1308
|
+
params.push(runId);
|
|
1309
|
+
}
|
|
1310
|
+
if (workflowName) {
|
|
1311
|
+
conditions.push("workflow_name = ?");
|
|
1312
|
+
params.push(workflowName);
|
|
1313
|
+
}
|
|
1314
|
+
const whereClause = conditions.length > 0 ? "WHERE " + conditions.join(" AND ") : "";
|
|
1315
|
+
const sql = `SELECT * FROM ${fullTableName} ${whereClause} ORDER BY createdAt DESC LIMIT 1`;
|
|
1316
|
+
const result = await this.executeQuery({ sql, params, first: true });
|
|
1317
|
+
if (!result) return null;
|
|
1318
|
+
return this.parseWorkflowRun(result);
|
|
1319
|
+
} catch (error) {
|
|
1320
|
+
this.logger.error("Error getting workflow run by ID:", {
|
|
1321
|
+
message: error instanceof Error ? error.message : String(error)
|
|
1322
|
+
});
|
|
1323
|
+
throw error;
|
|
1324
|
+
}
|
|
934
1325
|
}
|
|
935
1326
|
/**
|
|
936
1327
|
* Close the database connection
|