@mastra/cloudflare-d1 0.0.0-switch-to-core-20250424015131 → 0.0.0-taofeeqInngest-20250603090617
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 +60 -14
- package/dist/_tsup-dts-rollup.d.ts +60 -14
- package/dist/index.cjs +194 -63
- package/dist/index.d.cts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +194 -63
- package/package.json +9 -6
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import type { D1Database as D1Database_2 } from '@cloudflare/workers-types';
|
|
2
2
|
import type { EvalRow } from '@mastra/core/storage';
|
|
3
|
+
import type { MastraMessageV1 } from '@mastra/core/memory';
|
|
4
|
+
import type { MastraMessageV2 } from '@mastra/core/memory';
|
|
5
|
+
import type { MastraMessageV2 as MastraMessageV2_2 } from '@mastra/core';
|
|
3
6
|
import { MastraStorage } from '@mastra/core/storage';
|
|
4
|
-
import type { MessageType } from '@mastra/core/memory';
|
|
5
7
|
import type { StorageColumn } from '@mastra/core/storage';
|
|
6
8
|
import type { StorageGetMessagesArg } from '@mastra/core/storage';
|
|
7
9
|
import type { StorageThreadType } from '@mastra/core/memory';
|
|
8
10
|
import type { TABLE_NAMES } from '@mastra/core/storage';
|
|
11
|
+
import type { WorkflowRun } from '@mastra/core/storage';
|
|
9
12
|
import type { WorkflowRuns } from '@mastra/core/storage';
|
|
10
13
|
import type { WorkflowRunState } from '@mastra/core/workflows';
|
|
11
14
|
import type { WorkflowRunState as WorkflowRunState_2 } from '@mastra/core';
|
|
12
15
|
|
|
13
|
-
export declare const
|
|
16
|
+
export declare const checkWorkflowSnapshot: (snapshot: WorkflowRunState_2 | string, stepId: string, status: string) => void;
|
|
17
|
+
|
|
18
|
+
export declare const createSampleMessage: (threadId: string, parts?: MastraMessageV2_2["content"]["parts"]) => MastraMessageV2_2;
|
|
14
19
|
|
|
15
20
|
export declare const createSampleThread: () => {
|
|
16
21
|
id: string;
|
|
@@ -51,7 +56,11 @@ export declare const createSampleTrace: (name: string, scope?: string, attribute
|
|
|
51
56
|
createdAt: string;
|
|
52
57
|
};
|
|
53
58
|
|
|
54
|
-
export declare const createSampleWorkflowSnapshot: (threadId: string) =>
|
|
59
|
+
export declare const createSampleWorkflowSnapshot: (threadId: string, status: string, createdAt?: Date) => {
|
|
60
|
+
snapshot: WorkflowRunState_2;
|
|
61
|
+
runId: string;
|
|
62
|
+
stepId: string;
|
|
63
|
+
};
|
|
55
64
|
|
|
56
65
|
export declare function createSqlBuilder(): SqlBuilder;
|
|
57
66
|
|
|
@@ -84,7 +93,6 @@ declare class D1Store extends MastraStorage {
|
|
|
84
93
|
constructor(config: D1StoreConfig);
|
|
85
94
|
private getTableName;
|
|
86
95
|
private formatSqlParams;
|
|
87
|
-
private createIndexIfNotExists;
|
|
88
96
|
private executeWorkersBindingQuery;
|
|
89
97
|
private executeRestQuery;
|
|
90
98
|
/**
|
|
@@ -131,10 +139,20 @@ declare class D1Store extends MastraStorage {
|
|
|
131
139
|
deleteThread({ threadId }: {
|
|
132
140
|
threadId: string;
|
|
133
141
|
}): Promise<void>;
|
|
134
|
-
saveMessages(
|
|
135
|
-
messages:
|
|
136
|
-
|
|
137
|
-
|
|
142
|
+
saveMessages(args: {
|
|
143
|
+
messages: MastraMessageV1[];
|
|
144
|
+
format?: undefined | 'v1';
|
|
145
|
+
}): Promise<MastraMessageV1[]>;
|
|
146
|
+
saveMessages(args: {
|
|
147
|
+
messages: MastraMessageV2[];
|
|
148
|
+
format: 'v2';
|
|
149
|
+
}): Promise<MastraMessageV2[]>;
|
|
150
|
+
getMessages(args: StorageGetMessagesArg & {
|
|
151
|
+
format?: 'v1';
|
|
152
|
+
}): Promise<MastraMessageV1[]>;
|
|
153
|
+
getMessages(args: StorageGetMessagesArg & {
|
|
154
|
+
format: 'v2';
|
|
155
|
+
}): Promise<MastraMessageV2[]>;
|
|
138
156
|
persistWorkflowSnapshot({ workflowName, runId, snapshot, }: {
|
|
139
157
|
workflowName: string;
|
|
140
158
|
runId: string;
|
|
@@ -153,21 +171,30 @@ declare class D1Store extends MastraStorage {
|
|
|
153
171
|
tableName: TABLE_NAMES;
|
|
154
172
|
records: Record<string, any>[];
|
|
155
173
|
}): Promise<void>;
|
|
156
|
-
getTraces({ name, scope, page, perPage, attributes, }: {
|
|
174
|
+
getTraces({ name, scope, page, perPage, attributes, fromDate, toDate, }: {
|
|
157
175
|
name?: string;
|
|
158
176
|
scope?: string;
|
|
159
177
|
page: number;
|
|
160
178
|
perPage: number;
|
|
161
179
|
attributes?: Record<string, string>;
|
|
180
|
+
fromDate?: Date;
|
|
181
|
+
toDate?: Date;
|
|
162
182
|
}): Promise<Record<string, any>[]>;
|
|
163
183
|
getEvalsByAgentName(agentName: string, type?: 'test' | 'live'): Promise<EvalRow[]>;
|
|
164
|
-
|
|
184
|
+
private parseWorkflowRun;
|
|
185
|
+
private hasColumn;
|
|
186
|
+
getWorkflowRuns({ workflowName, fromDate, toDate, limit, offset, resourceId, }?: {
|
|
165
187
|
workflowName?: string;
|
|
166
188
|
fromDate?: Date;
|
|
167
189
|
toDate?: Date;
|
|
168
190
|
limit?: number;
|
|
169
191
|
offset?: number;
|
|
192
|
+
resourceId?: string;
|
|
170
193
|
}): Promise<WorkflowRuns>;
|
|
194
|
+
getWorkflowRunById({ runId, workflowName, }: {
|
|
195
|
+
runId: string;
|
|
196
|
+
workflowName?: string;
|
|
197
|
+
}): Promise<WorkflowRun | null>;
|
|
171
198
|
/**
|
|
172
199
|
* Close the database connection
|
|
173
200
|
* No explicit cleanup needed for D1 in either REST or Workers Binding mode
|
|
@@ -196,9 +223,30 @@ declare interface D1WorkersConfig {
|
|
|
196
223
|
export { D1WorkersConfig }
|
|
197
224
|
export { D1WorkersConfig as D1WorkersConfig_alias_1 }
|
|
198
225
|
|
|
226
|
+
/**
|
|
227
|
+
* Parses and returns a valid SQL SELECT column identifier.
|
|
228
|
+
* Allows a single identifier (letters, numbers, underscores), or '*', optionally with 'AS alias'.
|
|
229
|
+
*
|
|
230
|
+
* @param column - The column identifier string to parse.
|
|
231
|
+
* @returns The validated column identifier as a branded type.
|
|
232
|
+
* @throws {Error} If invalid.
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* const col = parseSelectIdentifier('user_id'); // Ok
|
|
236
|
+
* parseSelectIdentifier('user_id AS uid'); // Ok
|
|
237
|
+
* parseSelectIdentifier('*'); // Ok
|
|
238
|
+
* parseSelectIdentifier('user id'); // Throws error
|
|
239
|
+
*/
|
|
240
|
+
export declare function parseSelectIdentifier(column: string): SelectIdentifier;
|
|
241
|
+
|
|
199
242
|
export declare const retryUntil: <T>(fn: () => Promise<T>, condition: (result: T) => boolean, timeout?: number, // REST API needs longer timeout due to higher latency
|
|
200
243
|
interval?: number) => Promise<T>;
|
|
201
244
|
|
|
245
|
+
/** Represents a validated SQL SELECT column identifier (or '*', optionally with 'AS alias'). */
|
|
246
|
+
declare type SelectIdentifier = string & {
|
|
247
|
+
__brand: 'SelectIdentifier';
|
|
248
|
+
};
|
|
249
|
+
|
|
202
250
|
/**
|
|
203
251
|
* SQL Builder class for constructing type-safe SQL queries
|
|
204
252
|
* This helps create maintainable and secure SQL queries with proper parameter handling
|
|
@@ -226,6 +274,7 @@ export declare class SqlBuilder {
|
|
|
226
274
|
orderBy(column: string, direction?: 'ASC' | 'DESC'): SqlBuilder;
|
|
227
275
|
limit(count: number): SqlBuilder;
|
|
228
276
|
offset(count: number): SqlBuilder;
|
|
277
|
+
count(): SqlBuilder;
|
|
229
278
|
/**
|
|
230
279
|
* Insert a row, or update specific columns on conflict (upsert).
|
|
231
280
|
* @param table Table name
|
|
@@ -261,7 +310,6 @@ export declare class SqlBuilder {
|
|
|
261
310
|
* @returns The builder instance
|
|
262
311
|
*/
|
|
263
312
|
createIndex(indexName: string, tableName: string, columnName: string, indexType?: string): SqlBuilder;
|
|
264
|
-
raw(sql: string, ...params: SqlParam[]): SqlBuilder;
|
|
265
313
|
/**
|
|
266
314
|
* Add a LIKE condition to the query
|
|
267
315
|
* @param column The column to check
|
|
@@ -299,7 +347,7 @@ export declare type SqlParam = string | number | boolean | null | undefined;
|
|
|
299
347
|
/**
|
|
300
348
|
* Interface for SQL query options with generic type support
|
|
301
349
|
*/
|
|
302
|
-
declare interface SqlQueryOptions {
|
|
350
|
+
export declare interface SqlQueryOptions {
|
|
303
351
|
/** SQL query to execute */
|
|
304
352
|
sql: string;
|
|
305
353
|
/** Parameters to bind to the query */
|
|
@@ -307,7 +355,5 @@ declare interface SqlQueryOptions {
|
|
|
307
355
|
/** Whether to return only the first result */
|
|
308
356
|
first?: boolean;
|
|
309
357
|
}
|
|
310
|
-
export { SqlQueryOptions }
|
|
311
|
-
export { SqlQueryOptions as SqlQueryOptions_alias_1 }
|
|
312
358
|
|
|
313
359
|
export { }
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import type { D1Database as D1Database_2 } from '@cloudflare/workers-types';
|
|
2
2
|
import type { EvalRow } from '@mastra/core/storage';
|
|
3
|
+
import type { MastraMessageV1 } from '@mastra/core/memory';
|
|
4
|
+
import type { MastraMessageV2 } from '@mastra/core/memory';
|
|
5
|
+
import type { MastraMessageV2 as MastraMessageV2_2 } from '@mastra/core';
|
|
3
6
|
import { MastraStorage } from '@mastra/core/storage';
|
|
4
|
-
import type { MessageType } from '@mastra/core/memory';
|
|
5
7
|
import type { StorageColumn } from '@mastra/core/storage';
|
|
6
8
|
import type { StorageGetMessagesArg } from '@mastra/core/storage';
|
|
7
9
|
import type { StorageThreadType } from '@mastra/core/memory';
|
|
8
10
|
import type { TABLE_NAMES } from '@mastra/core/storage';
|
|
11
|
+
import type { WorkflowRun } from '@mastra/core/storage';
|
|
9
12
|
import type { WorkflowRuns } from '@mastra/core/storage';
|
|
10
13
|
import type { WorkflowRunState } from '@mastra/core/workflows';
|
|
11
14
|
import type { WorkflowRunState as WorkflowRunState_2 } from '@mastra/core';
|
|
12
15
|
|
|
13
|
-
export declare const
|
|
16
|
+
export declare const checkWorkflowSnapshot: (snapshot: WorkflowRunState_2 | string, stepId: string, status: string) => void;
|
|
17
|
+
|
|
18
|
+
export declare const createSampleMessage: (threadId: string, parts?: MastraMessageV2_2["content"]["parts"]) => MastraMessageV2_2;
|
|
14
19
|
|
|
15
20
|
export declare const createSampleThread: () => {
|
|
16
21
|
id: string;
|
|
@@ -51,7 +56,11 @@ export declare const createSampleTrace: (name: string, scope?: string, attribute
|
|
|
51
56
|
createdAt: string;
|
|
52
57
|
};
|
|
53
58
|
|
|
54
|
-
export declare const createSampleWorkflowSnapshot: (threadId: string) =>
|
|
59
|
+
export declare const createSampleWorkflowSnapshot: (threadId: string, status: string, createdAt?: Date) => {
|
|
60
|
+
snapshot: WorkflowRunState_2;
|
|
61
|
+
runId: string;
|
|
62
|
+
stepId: string;
|
|
63
|
+
};
|
|
55
64
|
|
|
56
65
|
export declare function createSqlBuilder(): SqlBuilder;
|
|
57
66
|
|
|
@@ -84,7 +93,6 @@ declare class D1Store extends MastraStorage {
|
|
|
84
93
|
constructor(config: D1StoreConfig);
|
|
85
94
|
private getTableName;
|
|
86
95
|
private formatSqlParams;
|
|
87
|
-
private createIndexIfNotExists;
|
|
88
96
|
private executeWorkersBindingQuery;
|
|
89
97
|
private executeRestQuery;
|
|
90
98
|
/**
|
|
@@ -131,10 +139,20 @@ declare class D1Store extends MastraStorage {
|
|
|
131
139
|
deleteThread({ threadId }: {
|
|
132
140
|
threadId: string;
|
|
133
141
|
}): Promise<void>;
|
|
134
|
-
saveMessages(
|
|
135
|
-
messages:
|
|
136
|
-
|
|
137
|
-
|
|
142
|
+
saveMessages(args: {
|
|
143
|
+
messages: MastraMessageV1[];
|
|
144
|
+
format?: undefined | 'v1';
|
|
145
|
+
}): Promise<MastraMessageV1[]>;
|
|
146
|
+
saveMessages(args: {
|
|
147
|
+
messages: MastraMessageV2[];
|
|
148
|
+
format: 'v2';
|
|
149
|
+
}): Promise<MastraMessageV2[]>;
|
|
150
|
+
getMessages(args: StorageGetMessagesArg & {
|
|
151
|
+
format?: 'v1';
|
|
152
|
+
}): Promise<MastraMessageV1[]>;
|
|
153
|
+
getMessages(args: StorageGetMessagesArg & {
|
|
154
|
+
format: 'v2';
|
|
155
|
+
}): Promise<MastraMessageV2[]>;
|
|
138
156
|
persistWorkflowSnapshot({ workflowName, runId, snapshot, }: {
|
|
139
157
|
workflowName: string;
|
|
140
158
|
runId: string;
|
|
@@ -153,21 +171,30 @@ declare class D1Store extends MastraStorage {
|
|
|
153
171
|
tableName: TABLE_NAMES;
|
|
154
172
|
records: Record<string, any>[];
|
|
155
173
|
}): Promise<void>;
|
|
156
|
-
getTraces({ name, scope, page, perPage, attributes, }: {
|
|
174
|
+
getTraces({ name, scope, page, perPage, attributes, fromDate, toDate, }: {
|
|
157
175
|
name?: string;
|
|
158
176
|
scope?: string;
|
|
159
177
|
page: number;
|
|
160
178
|
perPage: number;
|
|
161
179
|
attributes?: Record<string, string>;
|
|
180
|
+
fromDate?: Date;
|
|
181
|
+
toDate?: Date;
|
|
162
182
|
}): Promise<Record<string, any>[]>;
|
|
163
183
|
getEvalsByAgentName(agentName: string, type?: 'test' | 'live'): Promise<EvalRow[]>;
|
|
164
|
-
|
|
184
|
+
private parseWorkflowRun;
|
|
185
|
+
private hasColumn;
|
|
186
|
+
getWorkflowRuns({ workflowName, fromDate, toDate, limit, offset, resourceId, }?: {
|
|
165
187
|
workflowName?: string;
|
|
166
188
|
fromDate?: Date;
|
|
167
189
|
toDate?: Date;
|
|
168
190
|
limit?: number;
|
|
169
191
|
offset?: number;
|
|
192
|
+
resourceId?: string;
|
|
170
193
|
}): Promise<WorkflowRuns>;
|
|
194
|
+
getWorkflowRunById({ runId, workflowName, }: {
|
|
195
|
+
runId: string;
|
|
196
|
+
workflowName?: string;
|
|
197
|
+
}): Promise<WorkflowRun | null>;
|
|
171
198
|
/**
|
|
172
199
|
* Close the database connection
|
|
173
200
|
* No explicit cleanup needed for D1 in either REST or Workers Binding mode
|
|
@@ -196,9 +223,30 @@ declare interface D1WorkersConfig {
|
|
|
196
223
|
export { D1WorkersConfig }
|
|
197
224
|
export { D1WorkersConfig as D1WorkersConfig_alias_1 }
|
|
198
225
|
|
|
226
|
+
/**
|
|
227
|
+
* Parses and returns a valid SQL SELECT column identifier.
|
|
228
|
+
* Allows a single identifier (letters, numbers, underscores), or '*', optionally with 'AS alias'.
|
|
229
|
+
*
|
|
230
|
+
* @param column - The column identifier string to parse.
|
|
231
|
+
* @returns The validated column identifier as a branded type.
|
|
232
|
+
* @throws {Error} If invalid.
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* const col = parseSelectIdentifier('user_id'); // Ok
|
|
236
|
+
* parseSelectIdentifier('user_id AS uid'); // Ok
|
|
237
|
+
* parseSelectIdentifier('*'); // Ok
|
|
238
|
+
* parseSelectIdentifier('user id'); // Throws error
|
|
239
|
+
*/
|
|
240
|
+
export declare function parseSelectIdentifier(column: string): SelectIdentifier;
|
|
241
|
+
|
|
199
242
|
export declare const retryUntil: <T>(fn: () => Promise<T>, condition: (result: T) => boolean, timeout?: number, // REST API needs longer timeout due to higher latency
|
|
200
243
|
interval?: number) => Promise<T>;
|
|
201
244
|
|
|
245
|
+
/** Represents a validated SQL SELECT column identifier (or '*', optionally with 'AS alias'). */
|
|
246
|
+
declare type SelectIdentifier = string & {
|
|
247
|
+
__brand: 'SelectIdentifier';
|
|
248
|
+
};
|
|
249
|
+
|
|
202
250
|
/**
|
|
203
251
|
* SQL Builder class for constructing type-safe SQL queries
|
|
204
252
|
* This helps create maintainable and secure SQL queries with proper parameter handling
|
|
@@ -226,6 +274,7 @@ export declare class SqlBuilder {
|
|
|
226
274
|
orderBy(column: string, direction?: 'ASC' | 'DESC'): SqlBuilder;
|
|
227
275
|
limit(count: number): SqlBuilder;
|
|
228
276
|
offset(count: number): SqlBuilder;
|
|
277
|
+
count(): SqlBuilder;
|
|
229
278
|
/**
|
|
230
279
|
* Insert a row, or update specific columns on conflict (upsert).
|
|
231
280
|
* @param table Table name
|
|
@@ -261,7 +310,6 @@ export declare class SqlBuilder {
|
|
|
261
310
|
* @returns The builder instance
|
|
262
311
|
*/
|
|
263
312
|
createIndex(indexName: string, tableName: string, columnName: string, indexType?: string): SqlBuilder;
|
|
264
|
-
raw(sql: string, ...params: SqlParam[]): SqlBuilder;
|
|
265
313
|
/**
|
|
266
314
|
* Add a LIKE condition to the query
|
|
267
315
|
* @param column The column to check
|
|
@@ -299,7 +347,7 @@ export declare type SqlParam = string | number | boolean | null | undefined;
|
|
|
299
347
|
/**
|
|
300
348
|
* Interface for SQL query options with generic type support
|
|
301
349
|
*/
|
|
302
|
-
declare interface SqlQueryOptions {
|
|
350
|
+
export declare interface SqlQueryOptions {
|
|
303
351
|
/** SQL query to execute */
|
|
304
352
|
sql: string;
|
|
305
353
|
/** Parameters to bind to the query */
|
|
@@ -307,7 +355,5 @@ declare interface SqlQueryOptions {
|
|
|
307
355
|
/** Whether to return only the first result */
|
|
308
356
|
first?: boolean;
|
|
309
357
|
}
|
|
310
|
-
export { SqlQueryOptions }
|
|
311
|
-
export { SqlQueryOptions as SqlQueryOptions_alias_1 }
|
|
312
358
|
|
|
313
359
|
export { }
|
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 = [],
|
|
@@ -496,7 +508,8 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
496
508
|
try {
|
|
497
509
|
await this.executeQuery({ sql, params });
|
|
498
510
|
} catch (error) {
|
|
499
|
-
|
|
511
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
512
|
+
this.logger.error(`Error inserting into ${fullTableName}:`, { message });
|
|
500
513
|
throw new Error(`Failed to insert into ${fullTableName}: ${error}`);
|
|
501
514
|
}
|
|
502
515
|
}
|
|
@@ -594,7 +607,8 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
594
607
|
await this.executeQuery({ sql, params });
|
|
595
608
|
return thread;
|
|
596
609
|
} catch (error) {
|
|
597
|
-
|
|
610
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
611
|
+
this.logger.error(`Error saving thread to ${fullTableName}:`, { message });
|
|
598
612
|
throw error;
|
|
599
613
|
}
|
|
600
614
|
}
|
|
@@ -628,7 +642,8 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
628
642
|
updatedAt: /* @__PURE__ */ new Date()
|
|
629
643
|
};
|
|
630
644
|
} catch (error) {
|
|
631
|
-
|
|
645
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
646
|
+
this.logger.error("Error updating thread:", { message });
|
|
632
647
|
throw error;
|
|
633
648
|
}
|
|
634
649
|
}
|
|
@@ -649,8 +664,8 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
649
664
|
throw new Error(`Failed to delete thread ${threadId}: ${error}`);
|
|
650
665
|
}
|
|
651
666
|
}
|
|
652
|
-
|
|
653
|
-
|
|
667
|
+
async saveMessages(args) {
|
|
668
|
+
const { messages, format = "v1" } = args;
|
|
654
669
|
if (messages.length === 0) return [];
|
|
655
670
|
try {
|
|
656
671
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -672,7 +687,7 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
672
687
|
content: typeof message.content === "string" ? message.content : JSON.stringify(message.content),
|
|
673
688
|
createdAt: createdAt.toISOString(),
|
|
674
689
|
role: message.role,
|
|
675
|
-
type: message.type
|
|
690
|
+
type: message.type || "v2"
|
|
676
691
|
};
|
|
677
692
|
});
|
|
678
693
|
await this.batchInsert({
|
|
@@ -680,13 +695,19 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
680
695
|
records: messagesToInsert
|
|
681
696
|
});
|
|
682
697
|
this.logger.debug(`Saved ${messages.length} messages`);
|
|
683
|
-
|
|
698
|
+
const list = new agent.MessageList().add(messages, "memory");
|
|
699
|
+
if (format === `v2`) return list.get.all.v2();
|
|
700
|
+
return list.get.all.v1();
|
|
684
701
|
} catch (error) {
|
|
685
702
|
this.logger.error("Error saving messages:", { message: error instanceof Error ? error.message : String(error) });
|
|
686
703
|
throw error;
|
|
687
704
|
}
|
|
688
705
|
}
|
|
689
|
-
async getMessages({
|
|
706
|
+
async getMessages({
|
|
707
|
+
threadId,
|
|
708
|
+
selectBy,
|
|
709
|
+
format
|
|
710
|
+
}) {
|
|
690
711
|
const fullTableName = this.getTableName(storage.TABLE_MESSAGES);
|
|
691
712
|
const limit = typeof selectBy?.last === "number" ? selectBy.last : 40;
|
|
692
713
|
const include = selectBy?.include || [];
|
|
@@ -710,7 +731,7 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
710
731
|
m.role,
|
|
711
732
|
m.type,
|
|
712
733
|
m.createdAt,
|
|
713
|
-
m.thread_id AS
|
|
734
|
+
m.thread_id AS threadId
|
|
714
735
|
FROM ordered_messages m
|
|
715
736
|
WHERE m.id IN (${includeIds.map(() => "?").join(",")})
|
|
716
737
|
OR EXISTS (
|
|
@@ -737,7 +758,7 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
737
758
|
if (Array.isArray(includeResult)) messages.push(...includeResult);
|
|
738
759
|
}
|
|
739
760
|
const excludeIds = messages.map((m) => m.id);
|
|
740
|
-
let query = createSqlBuilder().select(["id", "content", "role", "type",
|
|
761
|
+
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);
|
|
741
762
|
const { sql, params } = query.build();
|
|
742
763
|
const result = await this.executeQuery({ sql, params });
|
|
743
764
|
if (Array.isArray(result)) messages.push(...result);
|
|
@@ -751,12 +772,15 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
751
772
|
const processedMessages = messages.map((message) => {
|
|
752
773
|
const processedMsg = {};
|
|
753
774
|
for (const [key, value] of Object.entries(message)) {
|
|
775
|
+
if (key === `type` && value === `v2`) continue;
|
|
754
776
|
processedMsg[key] = this.deserializeValue(value);
|
|
755
777
|
}
|
|
756
778
|
return processedMsg;
|
|
757
779
|
});
|
|
758
780
|
this.logger.debug(`Retrieved ${messages.length} messages for thread ${threadId}`);
|
|
759
|
-
|
|
781
|
+
const list = new agent.MessageList().add(processedMessages, "memory");
|
|
782
|
+
if (format === `v2`) return list.get.all.v2();
|
|
783
|
+
return list.get.all.v1();
|
|
760
784
|
} catch (error) {
|
|
761
785
|
this.logger.error("Error retrieving messages for thread", {
|
|
762
786
|
threadId,
|
|
@@ -862,7 +886,9 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
862
886
|
scope,
|
|
863
887
|
page,
|
|
864
888
|
perPage,
|
|
865
|
-
attributes
|
|
889
|
+
attributes,
|
|
890
|
+
fromDate,
|
|
891
|
+
toDate
|
|
866
892
|
}) {
|
|
867
893
|
const fullTableName = this.getTableName(storage.TABLE_TRACES);
|
|
868
894
|
try {
|
|
@@ -878,6 +904,12 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
878
904
|
query.jsonLike("attributes", key, value);
|
|
879
905
|
}
|
|
880
906
|
}
|
|
907
|
+
if (fromDate) {
|
|
908
|
+
query.andWhere("createdAt >= ?", fromDate instanceof Date ? fromDate.toISOString() : fromDate);
|
|
909
|
+
}
|
|
910
|
+
if (toDate) {
|
|
911
|
+
query.andWhere("createdAt <= ?", toDate instanceof Date ? toDate.toISOString() : toDate);
|
|
912
|
+
}
|
|
881
913
|
query.orderBy("startTime", "DESC").limit(perPage).offset((page - 1) * perPage);
|
|
882
914
|
const { sql, params } = query.build();
|
|
883
915
|
const results = await this.executeQuery({ sql, params });
|
|
@@ -929,8 +961,107 @@ var D1Store = class extends storage.MastraStorage {
|
|
|
929
961
|
return [];
|
|
930
962
|
}
|
|
931
963
|
}
|
|
932
|
-
|
|
933
|
-
|
|
964
|
+
parseWorkflowRun(row) {
|
|
965
|
+
let parsedSnapshot = row.snapshot;
|
|
966
|
+
if (typeof parsedSnapshot === "string") {
|
|
967
|
+
try {
|
|
968
|
+
parsedSnapshot = JSON.parse(row.snapshot);
|
|
969
|
+
} catch (e) {
|
|
970
|
+
console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
return {
|
|
974
|
+
workflowName: row.workflow_name,
|
|
975
|
+
runId: row.run_id,
|
|
976
|
+
snapshot: parsedSnapshot,
|
|
977
|
+
createdAt: this.ensureDate(row.createdAt),
|
|
978
|
+
updatedAt: this.ensureDate(row.updatedAt),
|
|
979
|
+
resourceId: row.resourceId
|
|
980
|
+
};
|
|
981
|
+
}
|
|
982
|
+
async hasColumn(table, column) {
|
|
983
|
+
const sql = `PRAGMA table_info(${table});`;
|
|
984
|
+
const result = await this.executeQuery({ sql, params: [] });
|
|
985
|
+
if (!result || !Array.isArray(result)) return false;
|
|
986
|
+
return result.some((col) => col.name === column || col.name === column.toLowerCase());
|
|
987
|
+
}
|
|
988
|
+
async getWorkflowRuns({
|
|
989
|
+
workflowName,
|
|
990
|
+
fromDate,
|
|
991
|
+
toDate,
|
|
992
|
+
limit,
|
|
993
|
+
offset,
|
|
994
|
+
resourceId
|
|
995
|
+
} = {}) {
|
|
996
|
+
const fullTableName = this.getTableName(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
997
|
+
try {
|
|
998
|
+
const builder = createSqlBuilder().select().from(fullTableName);
|
|
999
|
+
const countBuilder = createSqlBuilder().count().from(fullTableName);
|
|
1000
|
+
if (workflowName) builder.whereAnd("workflow_name = ?", workflowName);
|
|
1001
|
+
if (resourceId) {
|
|
1002
|
+
const hasResourceId = await this.hasColumn(fullTableName, "resourceId");
|
|
1003
|
+
if (hasResourceId) {
|
|
1004
|
+
builder.whereAnd("resourceId = ?", resourceId);
|
|
1005
|
+
countBuilder.whereAnd("resourceId = ?", resourceId);
|
|
1006
|
+
} else {
|
|
1007
|
+
console.warn(`[${fullTableName}] resourceId column not found. Skipping resourceId filter.`);
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
if (fromDate) {
|
|
1011
|
+
builder.whereAnd("createdAt >= ?", fromDate instanceof Date ? fromDate.toISOString() : fromDate);
|
|
1012
|
+
countBuilder.whereAnd("createdAt >= ?", fromDate instanceof Date ? fromDate.toISOString() : fromDate);
|
|
1013
|
+
}
|
|
1014
|
+
if (toDate) {
|
|
1015
|
+
builder.whereAnd("createdAt <= ?", toDate instanceof Date ? toDate.toISOString() : toDate);
|
|
1016
|
+
countBuilder.whereAnd("createdAt <= ?", toDate instanceof Date ? toDate.toISOString() : toDate);
|
|
1017
|
+
}
|
|
1018
|
+
builder.orderBy("createdAt", "DESC");
|
|
1019
|
+
if (typeof limit === "number") builder.limit(limit);
|
|
1020
|
+
if (typeof offset === "number") builder.offset(offset);
|
|
1021
|
+
const { sql, params } = builder.build();
|
|
1022
|
+
let total = 0;
|
|
1023
|
+
if (limit !== void 0 && offset !== void 0) {
|
|
1024
|
+
const { sql: countSql, params: countParams } = countBuilder.build();
|
|
1025
|
+
const countResult = await this.executeQuery({ sql: countSql, params: countParams, first: true });
|
|
1026
|
+
total = Number(countResult?.count ?? 0);
|
|
1027
|
+
}
|
|
1028
|
+
const results = await this.executeQuery({ sql, params });
|
|
1029
|
+
const runs = (isArrayOfRecords(results) ? results : []).map((row) => this.parseWorkflowRun(row));
|
|
1030
|
+
return { runs, total: total || runs.length };
|
|
1031
|
+
} catch (error) {
|
|
1032
|
+
this.logger.error("Error getting workflow runs:", {
|
|
1033
|
+
message: error instanceof Error ? error.message : String(error)
|
|
1034
|
+
});
|
|
1035
|
+
throw error;
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
async getWorkflowRunById({
|
|
1039
|
+
runId,
|
|
1040
|
+
workflowName
|
|
1041
|
+
}) {
|
|
1042
|
+
const fullTableName = this.getTableName(storage.TABLE_WORKFLOW_SNAPSHOT);
|
|
1043
|
+
try {
|
|
1044
|
+
const conditions = [];
|
|
1045
|
+
const params = [];
|
|
1046
|
+
if (runId) {
|
|
1047
|
+
conditions.push("run_id = ?");
|
|
1048
|
+
params.push(runId);
|
|
1049
|
+
}
|
|
1050
|
+
if (workflowName) {
|
|
1051
|
+
conditions.push("workflow_name = ?");
|
|
1052
|
+
params.push(workflowName);
|
|
1053
|
+
}
|
|
1054
|
+
const whereClause = conditions.length > 0 ? "WHERE " + conditions.join(" AND ") : "";
|
|
1055
|
+
const sql = `SELECT * FROM ${fullTableName} ${whereClause} ORDER BY createdAt DESC LIMIT 1`;
|
|
1056
|
+
const result = await this.executeQuery({ sql, params, first: true });
|
|
1057
|
+
if (!result) return null;
|
|
1058
|
+
return this.parseWorkflowRun(result);
|
|
1059
|
+
} catch (error) {
|
|
1060
|
+
this.logger.error("Error getting workflow run by ID:", {
|
|
1061
|
+
message: error instanceof Error ? error.message : String(error)
|
|
1062
|
+
});
|
|
1063
|
+
throw error;
|
|
1064
|
+
}
|
|
934
1065
|
}
|
|
935
1066
|
/**
|
|
936
1067
|
* Close the database connection
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { MessageList } from '@mastra/core/agent';
|
|
1
2
|
import { MastraStorage, TABLE_THREADS, TABLE_MESSAGES, TABLE_WORKFLOW_SNAPSHOT, TABLE_TRACES, TABLE_EVALS } from '@mastra/core/storage';
|
|
2
3
|
import Cloudflare from 'cloudflare';
|
|
4
|
+
import { parseSqlIdentifier } from '@mastra/core/utils';
|
|
3
5
|
|
|
4
6
|
// src/storage/index.ts
|
|
5
|
-
|
|
6
|
-
// src/storage/sql-builder.ts
|
|
7
7
|
var SqlBuilder = class {
|
|
8
8
|
sql = "";
|
|
9
9
|
params = [];
|
|
@@ -13,12 +13,15 @@ var SqlBuilder = class {
|
|
|
13
13
|
if (!columns || Array.isArray(columns) && columns.length === 0) {
|
|
14
14
|
this.sql = "SELECT *";
|
|
15
15
|
} else {
|
|
16
|
-
|
|
16
|
+
const cols = Array.isArray(columns) ? columns : [columns];
|
|
17
|
+
const parsedCols = cols.map((col) => parseSelectIdentifier(col));
|
|
18
|
+
this.sql = `SELECT ${parsedCols.join(", ")}`;
|
|
17
19
|
}
|
|
18
20
|
return this;
|
|
19
21
|
}
|
|
20
22
|
from(table) {
|
|
21
|
-
|
|
23
|
+
const parsedTableName = parseSqlIdentifier(table, "table name");
|
|
24
|
+
this.sql += ` FROM ${parsedTableName}`;
|
|
22
25
|
return this;
|
|
23
26
|
}
|
|
24
27
|
/**
|
|
@@ -55,7 +58,11 @@ var SqlBuilder = class {
|
|
|
55
58
|
return this;
|
|
56
59
|
}
|
|
57
60
|
orderBy(column, direction = "ASC") {
|
|
58
|
-
|
|
61
|
+
const parsedColumn = parseSqlIdentifier(column, "column name");
|
|
62
|
+
if (!["ASC", "DESC"].includes(direction)) {
|
|
63
|
+
throw new Error(`Invalid sort direction: ${direction}`);
|
|
64
|
+
}
|
|
65
|
+
this.sql += ` ORDER BY ${parsedColumn} ${direction}`;
|
|
59
66
|
return this;
|
|
60
67
|
}
|
|
61
68
|
limit(count) {
|
|
@@ -68,6 +75,10 @@ var SqlBuilder = class {
|
|
|
68
75
|
this.params.push(count);
|
|
69
76
|
return this;
|
|
70
77
|
}
|
|
78
|
+
count() {
|
|
79
|
+
this.sql += "SELECT COUNT(*) AS count";
|
|
80
|
+
return this;
|
|
81
|
+
}
|
|
71
82
|
/**
|
|
72
83
|
* Insert a row, or update specific columns on conflict (upsert).
|
|
73
84
|
* @param table Table name
|
|
@@ -77,27 +88,33 @@ var SqlBuilder = class {
|
|
|
77
88
|
* @param updateMap Object mapping columns to update to their new value (e.g. { name: 'excluded.name' })
|
|
78
89
|
*/
|
|
79
90
|
insert(table, columns, values, conflictColumns, updateMap) {
|
|
80
|
-
const
|
|
91
|
+
const parsedTableName = parseSqlIdentifier(table, "table name");
|
|
92
|
+
const parsedColumns = columns.map((col) => parseSqlIdentifier(col, "column name"));
|
|
93
|
+
const placeholders = parsedColumns.map(() => "?").join(", ");
|
|
81
94
|
if (conflictColumns && updateMap) {
|
|
95
|
+
const parsedConflictColumns = conflictColumns.map((col) => parseSqlIdentifier(col, "column name"));
|
|
82
96
|
const updateClause = Object.entries(updateMap).map(([col, expr]) => `${col} = ${expr}`).join(", ");
|
|
83
|
-
this.sql = `INSERT INTO ${
|
|
97
|
+
this.sql = `INSERT INTO ${parsedTableName} (${parsedColumns.join(", ")}) VALUES (${placeholders}) ON CONFLICT(${parsedConflictColumns.join(", ")}) DO UPDATE SET ${updateClause}`;
|
|
84
98
|
this.params.push(...values);
|
|
85
99
|
return this;
|
|
86
100
|
}
|
|
87
|
-
this.sql = `INSERT INTO ${
|
|
101
|
+
this.sql = `INSERT INTO ${parsedTableName} (${parsedColumns.join(", ")}) VALUES (${placeholders})`;
|
|
88
102
|
this.params.push(...values);
|
|
89
103
|
return this;
|
|
90
104
|
}
|
|
91
105
|
// Update operations
|
|
92
106
|
update(table, columns, values) {
|
|
93
|
-
const
|
|
94
|
-
|
|
107
|
+
const parsedTableName = parseSqlIdentifier(table, "table name");
|
|
108
|
+
const parsedColumns = columns.map((col) => parseSqlIdentifier(col, "column name"));
|
|
109
|
+
const setClause = parsedColumns.map((col) => `${col} = ?`).join(", ");
|
|
110
|
+
this.sql = `UPDATE ${parsedTableName} SET ${setClause}`;
|
|
95
111
|
this.params.push(...values);
|
|
96
112
|
return this;
|
|
97
113
|
}
|
|
98
114
|
// Delete operations
|
|
99
115
|
delete(table) {
|
|
100
|
-
|
|
116
|
+
const parsedTableName = parseSqlIdentifier(table, "table name");
|
|
117
|
+
this.sql = `DELETE FROM ${parsedTableName}`;
|
|
101
118
|
return this;
|
|
102
119
|
}
|
|
103
120
|
/**
|
|
@@ -108,9 +125,16 @@ var SqlBuilder = class {
|
|
|
108
125
|
* @returns The builder instance
|
|
109
126
|
*/
|
|
110
127
|
createTable(table, columnDefinitions, tableConstraints) {
|
|
111
|
-
const
|
|
128
|
+
const parsedTableName = parseSqlIdentifier(table, "table name");
|
|
129
|
+
const parsedColumnDefinitions = columnDefinitions.map((def) => {
|
|
130
|
+
const colName = def.split(/\s+/)[0];
|
|
131
|
+
if (!colName) throw new Error("Empty column name in definition");
|
|
132
|
+
parseSqlIdentifier(colName, "column name");
|
|
133
|
+
return def;
|
|
134
|
+
});
|
|
135
|
+
const columns = parsedColumnDefinitions.join(", ");
|
|
112
136
|
const constraints = tableConstraints && tableConstraints.length > 0 ? ", " + tableConstraints.join(", ") : "";
|
|
113
|
-
this.sql = `CREATE TABLE IF NOT EXISTS ${
|
|
137
|
+
this.sql = `CREATE TABLE IF NOT EXISTS ${parsedTableName} (${columns}${constraints})`;
|
|
114
138
|
return this;
|
|
115
139
|
}
|
|
116
140
|
/**
|
|
@@ -133,13 +157,10 @@ var SqlBuilder = class {
|
|
|
133
157
|
* @returns The builder instance
|
|
134
158
|
*/
|
|
135
159
|
createIndex(indexName, tableName, columnName, indexType = "") {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
raw(sql, ...params) {
|
|
141
|
-
this.sql = sql;
|
|
142
|
-
this.params.push(...params);
|
|
160
|
+
const parsedIndexName = parseSqlIdentifier(indexName, "index name");
|
|
161
|
+
const parsedTableName = parseSqlIdentifier(tableName, "table name");
|
|
162
|
+
const parsedColumnName = parseSqlIdentifier(columnName, "column name");
|
|
163
|
+
this.sql = `CREATE ${indexType ? indexType + " " : ""}INDEX IF NOT EXISTS ${parsedIndexName} ON ${parsedTableName}(${parsedColumnName})`;
|
|
143
164
|
return this;
|
|
144
165
|
}
|
|
145
166
|
/**
|
|
@@ -149,11 +170,12 @@ var SqlBuilder = class {
|
|
|
149
170
|
* @param exact If true, will not add % wildcards
|
|
150
171
|
*/
|
|
151
172
|
like(column, value, exact = false) {
|
|
173
|
+
const parsedColumnName = parseSqlIdentifier(column, "column name");
|
|
152
174
|
const likeValue = exact ? value : `%${value}%`;
|
|
153
175
|
if (this.whereAdded) {
|
|
154
|
-
this.sql += ` AND ${
|
|
176
|
+
this.sql += ` AND ${parsedColumnName} LIKE ?`;
|
|
155
177
|
} else {
|
|
156
|
-
this.sql += ` WHERE ${
|
|
178
|
+
this.sql += ` WHERE ${parsedColumnName} LIKE ?`;
|
|
157
179
|
this.whereAdded = true;
|
|
158
180
|
}
|
|
159
181
|
this.params.push(likeValue);
|
|
@@ -166,11 +188,13 @@ var SqlBuilder = class {
|
|
|
166
188
|
* @param value The value to match
|
|
167
189
|
*/
|
|
168
190
|
jsonLike(column, key, value) {
|
|
169
|
-
const
|
|
191
|
+
const parsedColumnName = parseSqlIdentifier(column, "column name");
|
|
192
|
+
const parsedKey = parseSqlIdentifier(key, "key name");
|
|
193
|
+
const jsonPattern = `%"${parsedKey}":"${value}"%`;
|
|
170
194
|
if (this.whereAdded) {
|
|
171
|
-
this.sql += ` AND ${
|
|
195
|
+
this.sql += ` AND ${parsedColumnName} LIKE ?`;
|
|
172
196
|
} else {
|
|
173
|
-
this.sql += ` WHERE ${
|
|
197
|
+
this.sql += ` WHERE ${parsedColumnName} LIKE ?`;
|
|
174
198
|
this.whereAdded = true;
|
|
175
199
|
}
|
|
176
200
|
this.params.push(jsonPattern);
|
|
@@ -200,6 +224,15 @@ var SqlBuilder = class {
|
|
|
200
224
|
function createSqlBuilder() {
|
|
201
225
|
return new SqlBuilder();
|
|
202
226
|
}
|
|
227
|
+
var SQL_IDENTIFIER_PATTERN = /^[a-zA-Z0-9_]+(\s+AS\s+[a-zA-Z0-9_]+)?$/;
|
|
228
|
+
function parseSelectIdentifier(column) {
|
|
229
|
+
if (column !== "*" && !SQL_IDENTIFIER_PATTERN.test(column)) {
|
|
230
|
+
throw new Error(
|
|
231
|
+
`Invalid column name: "${column}". Must be "*" or a valid identifier (letters, numbers, underscores), optionally with "AS alias".`
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
return column;
|
|
235
|
+
}
|
|
203
236
|
|
|
204
237
|
// src/storage/index.ts
|
|
205
238
|
function isArrayOfRecords(value) {
|
|
@@ -218,6 +251,9 @@ var D1Store = class extends MastraStorage {
|
|
|
218
251
|
*/
|
|
219
252
|
constructor(config) {
|
|
220
253
|
super({ name: "D1" });
|
|
254
|
+
if (config.tablePrefix && !/^[a-zA-Z0-9_]*$/.test(config.tablePrefix)) {
|
|
255
|
+
throw new Error("Invalid tablePrefix: only letters, numbers, and underscores are allowed.");
|
|
256
|
+
}
|
|
221
257
|
this.tablePrefix = config.tablePrefix || "";
|
|
222
258
|
if ("binding" in config) {
|
|
223
259
|
if (!config.binding) {
|
|
@@ -244,30 +280,6 @@ var D1Store = class extends MastraStorage {
|
|
|
244
280
|
formatSqlParams(params) {
|
|
245
281
|
return params.map((p) => p === void 0 || p === null ? null : p);
|
|
246
282
|
}
|
|
247
|
-
// Helper method to create SQL indexes for better query performance
|
|
248
|
-
async createIndexIfNotExists(tableName, columnName, indexType = "") {
|
|
249
|
-
const fullTableName = this.getTableName(tableName);
|
|
250
|
-
const indexName = `idx_${tableName}_${columnName}`;
|
|
251
|
-
try {
|
|
252
|
-
const checkQuery = createSqlBuilder().checkIndexExists(indexName, fullTableName);
|
|
253
|
-
const { sql: checkSql, params: checkParams } = checkQuery.build();
|
|
254
|
-
const indexExists = await this.executeQuery({
|
|
255
|
-
sql: checkSql,
|
|
256
|
-
params: checkParams,
|
|
257
|
-
first: true
|
|
258
|
-
});
|
|
259
|
-
if (!indexExists) {
|
|
260
|
-
const createQuery = createSqlBuilder().createIndex(indexName, fullTableName, columnName, indexType);
|
|
261
|
-
const { sql: createSql, params: createParams } = createQuery.build();
|
|
262
|
-
await this.executeQuery({ sql: createSql, params: createParams });
|
|
263
|
-
this.logger.debug(`Created index ${indexName} on ${fullTableName}(${columnName})`);
|
|
264
|
-
}
|
|
265
|
-
} catch (error) {
|
|
266
|
-
this.logger.error(`Error creating index on ${fullTableName}(${columnName}):`, {
|
|
267
|
-
message: error instanceof Error ? error.message : String(error)
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
283
|
async executeWorkersBindingQuery({
|
|
272
284
|
sql,
|
|
273
285
|
params = [],
|
|
@@ -490,7 +502,8 @@ var D1Store = class extends MastraStorage {
|
|
|
490
502
|
try {
|
|
491
503
|
await this.executeQuery({ sql, params });
|
|
492
504
|
} catch (error) {
|
|
493
|
-
|
|
505
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
506
|
+
this.logger.error(`Error inserting into ${fullTableName}:`, { message });
|
|
494
507
|
throw new Error(`Failed to insert into ${fullTableName}: ${error}`);
|
|
495
508
|
}
|
|
496
509
|
}
|
|
@@ -588,7 +601,8 @@ var D1Store = class extends MastraStorage {
|
|
|
588
601
|
await this.executeQuery({ sql, params });
|
|
589
602
|
return thread;
|
|
590
603
|
} catch (error) {
|
|
591
|
-
|
|
604
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
605
|
+
this.logger.error(`Error saving thread to ${fullTableName}:`, { message });
|
|
592
606
|
throw error;
|
|
593
607
|
}
|
|
594
608
|
}
|
|
@@ -622,7 +636,8 @@ var D1Store = class extends MastraStorage {
|
|
|
622
636
|
updatedAt: /* @__PURE__ */ new Date()
|
|
623
637
|
};
|
|
624
638
|
} catch (error) {
|
|
625
|
-
|
|
639
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
640
|
+
this.logger.error("Error updating thread:", { message });
|
|
626
641
|
throw error;
|
|
627
642
|
}
|
|
628
643
|
}
|
|
@@ -643,8 +658,8 @@ var D1Store = class extends MastraStorage {
|
|
|
643
658
|
throw new Error(`Failed to delete thread ${threadId}: ${error}`);
|
|
644
659
|
}
|
|
645
660
|
}
|
|
646
|
-
|
|
647
|
-
|
|
661
|
+
async saveMessages(args) {
|
|
662
|
+
const { messages, format = "v1" } = args;
|
|
648
663
|
if (messages.length === 0) return [];
|
|
649
664
|
try {
|
|
650
665
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -666,7 +681,7 @@ var D1Store = class extends MastraStorage {
|
|
|
666
681
|
content: typeof message.content === "string" ? message.content : JSON.stringify(message.content),
|
|
667
682
|
createdAt: createdAt.toISOString(),
|
|
668
683
|
role: message.role,
|
|
669
|
-
type: message.type
|
|
684
|
+
type: message.type || "v2"
|
|
670
685
|
};
|
|
671
686
|
});
|
|
672
687
|
await this.batchInsert({
|
|
@@ -674,13 +689,19 @@ var D1Store = class extends MastraStorage {
|
|
|
674
689
|
records: messagesToInsert
|
|
675
690
|
});
|
|
676
691
|
this.logger.debug(`Saved ${messages.length} messages`);
|
|
677
|
-
|
|
692
|
+
const list = new MessageList().add(messages, "memory");
|
|
693
|
+
if (format === `v2`) return list.get.all.v2();
|
|
694
|
+
return list.get.all.v1();
|
|
678
695
|
} catch (error) {
|
|
679
696
|
this.logger.error("Error saving messages:", { message: error instanceof Error ? error.message : String(error) });
|
|
680
697
|
throw error;
|
|
681
698
|
}
|
|
682
699
|
}
|
|
683
|
-
async getMessages({
|
|
700
|
+
async getMessages({
|
|
701
|
+
threadId,
|
|
702
|
+
selectBy,
|
|
703
|
+
format
|
|
704
|
+
}) {
|
|
684
705
|
const fullTableName = this.getTableName(TABLE_MESSAGES);
|
|
685
706
|
const limit = typeof selectBy?.last === "number" ? selectBy.last : 40;
|
|
686
707
|
const include = selectBy?.include || [];
|
|
@@ -704,7 +725,7 @@ var D1Store = class extends MastraStorage {
|
|
|
704
725
|
m.role,
|
|
705
726
|
m.type,
|
|
706
727
|
m.createdAt,
|
|
707
|
-
m.thread_id AS
|
|
728
|
+
m.thread_id AS threadId
|
|
708
729
|
FROM ordered_messages m
|
|
709
730
|
WHERE m.id IN (${includeIds.map(() => "?").join(",")})
|
|
710
731
|
OR EXISTS (
|
|
@@ -731,7 +752,7 @@ var D1Store = class extends MastraStorage {
|
|
|
731
752
|
if (Array.isArray(includeResult)) messages.push(...includeResult);
|
|
732
753
|
}
|
|
733
754
|
const excludeIds = messages.map((m) => m.id);
|
|
734
|
-
let query = createSqlBuilder().select(["id", "content", "role", "type",
|
|
755
|
+
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);
|
|
735
756
|
const { sql, params } = query.build();
|
|
736
757
|
const result = await this.executeQuery({ sql, params });
|
|
737
758
|
if (Array.isArray(result)) messages.push(...result);
|
|
@@ -745,12 +766,15 @@ var D1Store = class extends MastraStorage {
|
|
|
745
766
|
const processedMessages = messages.map((message) => {
|
|
746
767
|
const processedMsg = {};
|
|
747
768
|
for (const [key, value] of Object.entries(message)) {
|
|
769
|
+
if (key === `type` && value === `v2`) continue;
|
|
748
770
|
processedMsg[key] = this.deserializeValue(value);
|
|
749
771
|
}
|
|
750
772
|
return processedMsg;
|
|
751
773
|
});
|
|
752
774
|
this.logger.debug(`Retrieved ${messages.length} messages for thread ${threadId}`);
|
|
753
|
-
|
|
775
|
+
const list = new MessageList().add(processedMessages, "memory");
|
|
776
|
+
if (format === `v2`) return list.get.all.v2();
|
|
777
|
+
return list.get.all.v1();
|
|
754
778
|
} catch (error) {
|
|
755
779
|
this.logger.error("Error retrieving messages for thread", {
|
|
756
780
|
threadId,
|
|
@@ -856,7 +880,9 @@ var D1Store = class extends MastraStorage {
|
|
|
856
880
|
scope,
|
|
857
881
|
page,
|
|
858
882
|
perPage,
|
|
859
|
-
attributes
|
|
883
|
+
attributes,
|
|
884
|
+
fromDate,
|
|
885
|
+
toDate
|
|
860
886
|
}) {
|
|
861
887
|
const fullTableName = this.getTableName(TABLE_TRACES);
|
|
862
888
|
try {
|
|
@@ -872,6 +898,12 @@ var D1Store = class extends MastraStorage {
|
|
|
872
898
|
query.jsonLike("attributes", key, value);
|
|
873
899
|
}
|
|
874
900
|
}
|
|
901
|
+
if (fromDate) {
|
|
902
|
+
query.andWhere("createdAt >= ?", fromDate instanceof Date ? fromDate.toISOString() : fromDate);
|
|
903
|
+
}
|
|
904
|
+
if (toDate) {
|
|
905
|
+
query.andWhere("createdAt <= ?", toDate instanceof Date ? toDate.toISOString() : toDate);
|
|
906
|
+
}
|
|
875
907
|
query.orderBy("startTime", "DESC").limit(perPage).offset((page - 1) * perPage);
|
|
876
908
|
const { sql, params } = query.build();
|
|
877
909
|
const results = await this.executeQuery({ sql, params });
|
|
@@ -923,8 +955,107 @@ var D1Store = class extends MastraStorage {
|
|
|
923
955
|
return [];
|
|
924
956
|
}
|
|
925
957
|
}
|
|
926
|
-
|
|
927
|
-
|
|
958
|
+
parseWorkflowRun(row) {
|
|
959
|
+
let parsedSnapshot = row.snapshot;
|
|
960
|
+
if (typeof parsedSnapshot === "string") {
|
|
961
|
+
try {
|
|
962
|
+
parsedSnapshot = JSON.parse(row.snapshot);
|
|
963
|
+
} catch (e) {
|
|
964
|
+
console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
return {
|
|
968
|
+
workflowName: row.workflow_name,
|
|
969
|
+
runId: row.run_id,
|
|
970
|
+
snapshot: parsedSnapshot,
|
|
971
|
+
createdAt: this.ensureDate(row.createdAt),
|
|
972
|
+
updatedAt: this.ensureDate(row.updatedAt),
|
|
973
|
+
resourceId: row.resourceId
|
|
974
|
+
};
|
|
975
|
+
}
|
|
976
|
+
async hasColumn(table, column) {
|
|
977
|
+
const sql = `PRAGMA table_info(${table});`;
|
|
978
|
+
const result = await this.executeQuery({ sql, params: [] });
|
|
979
|
+
if (!result || !Array.isArray(result)) return false;
|
|
980
|
+
return result.some((col) => col.name === column || col.name === column.toLowerCase());
|
|
981
|
+
}
|
|
982
|
+
async getWorkflowRuns({
|
|
983
|
+
workflowName,
|
|
984
|
+
fromDate,
|
|
985
|
+
toDate,
|
|
986
|
+
limit,
|
|
987
|
+
offset,
|
|
988
|
+
resourceId
|
|
989
|
+
} = {}) {
|
|
990
|
+
const fullTableName = this.getTableName(TABLE_WORKFLOW_SNAPSHOT);
|
|
991
|
+
try {
|
|
992
|
+
const builder = createSqlBuilder().select().from(fullTableName);
|
|
993
|
+
const countBuilder = createSqlBuilder().count().from(fullTableName);
|
|
994
|
+
if (workflowName) builder.whereAnd("workflow_name = ?", workflowName);
|
|
995
|
+
if (resourceId) {
|
|
996
|
+
const hasResourceId = await this.hasColumn(fullTableName, "resourceId");
|
|
997
|
+
if (hasResourceId) {
|
|
998
|
+
builder.whereAnd("resourceId = ?", resourceId);
|
|
999
|
+
countBuilder.whereAnd("resourceId = ?", resourceId);
|
|
1000
|
+
} else {
|
|
1001
|
+
console.warn(`[${fullTableName}] resourceId column not found. Skipping resourceId filter.`);
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
if (fromDate) {
|
|
1005
|
+
builder.whereAnd("createdAt >= ?", fromDate instanceof Date ? fromDate.toISOString() : fromDate);
|
|
1006
|
+
countBuilder.whereAnd("createdAt >= ?", fromDate instanceof Date ? fromDate.toISOString() : fromDate);
|
|
1007
|
+
}
|
|
1008
|
+
if (toDate) {
|
|
1009
|
+
builder.whereAnd("createdAt <= ?", toDate instanceof Date ? toDate.toISOString() : toDate);
|
|
1010
|
+
countBuilder.whereAnd("createdAt <= ?", toDate instanceof Date ? toDate.toISOString() : toDate);
|
|
1011
|
+
}
|
|
1012
|
+
builder.orderBy("createdAt", "DESC");
|
|
1013
|
+
if (typeof limit === "number") builder.limit(limit);
|
|
1014
|
+
if (typeof offset === "number") builder.offset(offset);
|
|
1015
|
+
const { sql, params } = builder.build();
|
|
1016
|
+
let total = 0;
|
|
1017
|
+
if (limit !== void 0 && offset !== void 0) {
|
|
1018
|
+
const { sql: countSql, params: countParams } = countBuilder.build();
|
|
1019
|
+
const countResult = await this.executeQuery({ sql: countSql, params: countParams, first: true });
|
|
1020
|
+
total = Number(countResult?.count ?? 0);
|
|
1021
|
+
}
|
|
1022
|
+
const results = await this.executeQuery({ sql, params });
|
|
1023
|
+
const runs = (isArrayOfRecords(results) ? results : []).map((row) => this.parseWorkflowRun(row));
|
|
1024
|
+
return { runs, total: total || runs.length };
|
|
1025
|
+
} catch (error) {
|
|
1026
|
+
this.logger.error("Error getting workflow runs:", {
|
|
1027
|
+
message: error instanceof Error ? error.message : String(error)
|
|
1028
|
+
});
|
|
1029
|
+
throw error;
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
async getWorkflowRunById({
|
|
1033
|
+
runId,
|
|
1034
|
+
workflowName
|
|
1035
|
+
}) {
|
|
1036
|
+
const fullTableName = this.getTableName(TABLE_WORKFLOW_SNAPSHOT);
|
|
1037
|
+
try {
|
|
1038
|
+
const conditions = [];
|
|
1039
|
+
const params = [];
|
|
1040
|
+
if (runId) {
|
|
1041
|
+
conditions.push("run_id = ?");
|
|
1042
|
+
params.push(runId);
|
|
1043
|
+
}
|
|
1044
|
+
if (workflowName) {
|
|
1045
|
+
conditions.push("workflow_name = ?");
|
|
1046
|
+
params.push(workflowName);
|
|
1047
|
+
}
|
|
1048
|
+
const whereClause = conditions.length > 0 ? "WHERE " + conditions.join(" AND ") : "";
|
|
1049
|
+
const sql = `SELECT * FROM ${fullTableName} ${whereClause} ORDER BY createdAt DESC LIMIT 1`;
|
|
1050
|
+
const result = await this.executeQuery({ sql, params, first: true });
|
|
1051
|
+
if (!result) return null;
|
|
1052
|
+
return this.parseWorkflowRun(result);
|
|
1053
|
+
} catch (error) {
|
|
1054
|
+
this.logger.error("Error getting workflow run by ID:", {
|
|
1055
|
+
message: error instanceof Error ? error.message : String(error)
|
|
1056
|
+
});
|
|
1057
|
+
throw error;
|
|
1058
|
+
}
|
|
928
1059
|
}
|
|
929
1060
|
/**
|
|
930
1061
|
* Close the database connection
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/cloudflare-d1",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-taofeeqInngest-20250603090617",
|
|
4
4
|
"description": "D1 provider for Mastra - includes db storage capabilities",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -22,20 +22,23 @@
|
|
|
22
22
|
"./package.json": "./package.json"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"cloudflare": "^4.1.0"
|
|
26
|
-
"@mastra/core": "0.0.0-switch-to-core-20250424015131"
|
|
25
|
+
"cloudflare": "^4.1.0"
|
|
27
26
|
},
|
|
28
27
|
"devDependencies": {
|
|
29
28
|
"@cloudflare/workers-types": "^4.20250417.0",
|
|
30
|
-
"@microsoft/api-extractor": "^7.52.
|
|
29
|
+
"@microsoft/api-extractor": "^7.52.5",
|
|
31
30
|
"@types/node": "^20.17.27",
|
|
32
31
|
"dotenv": "^16.4.7",
|
|
33
32
|
"eslint": "^9.23.0",
|
|
34
33
|
"miniflare": "^4.20250410.1",
|
|
35
34
|
"tsup": "^8.4.0",
|
|
36
35
|
"typescript": "^5.8.2",
|
|
37
|
-
"vitest": "^3.
|
|
38
|
-
"@
|
|
36
|
+
"vitest": "^3.1.2",
|
|
37
|
+
"@mastra/core": "0.0.0-taofeeqInngest-20250603090617",
|
|
38
|
+
"@internal/lint": "0.0.0-taofeeqInngest-20250603090617"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"@mastra/core": "^0.10.0-alpha.0"
|
|
39
42
|
},
|
|
40
43
|
"scripts": {
|
|
41
44
|
"build": "tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting",
|