@mastra/upstash 0.1.5 → 0.1.6-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,18 +1,18 @@
1
1
 
2
- > @mastra/upstash@0.1.5-alpha.2 build /home/runner/work/mastra/mastra/stores/upstash
2
+ > @mastra/upstash@0.1.6-alpha.1 build /home/runner/work/mastra/mastra/stores/upstash
3
3
  > tsup src/index.ts --format esm --experimental-dts --clean --treeshake
4
4
 
5
5
  CLI Building entry: src/index.ts
6
6
  CLI Using tsconfig: tsconfig.json
7
7
  CLI tsup v8.3.6
8
8
  TSC Build start
9
- TSC ⚡️ Build success in 8405ms
9
+ TSC ⚡️ Build success in 8433ms
10
10
  DTS Build start
11
11
  CLI Target: es2022
12
12
  Analysis will use the bundled TypeScript version 5.7.3
13
13
  Writing package typings: /home/runner/work/mastra/mastra/stores/upstash/dist/_tsup-dts-rollup.d.ts
14
- DTS ⚡️ Build success in 6810ms
14
+ DTS ⚡️ Build success in 6040ms
15
15
  CLI Cleaning output folder
16
16
  ESM Build start
17
- ESM dist/index.js 16.11 KB
18
- ESM ⚡️ Build success in 633ms
17
+ ESM dist/index.js 15.98 KB
18
+ ESM ⚡️ Build success in 577ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @mastra/upstash
2
2
 
3
+ ## 0.1.6-alpha.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [0d185b1]
8
+ - Updated dependencies [ed55f1d]
9
+ - Updated dependencies [8d13b14]
10
+ - Updated dependencies [3ee4831]
11
+ - Updated dependencies [108793c]
12
+ - Updated dependencies [5f28f44]
13
+ - @mastra/core@0.4.3-alpha.1
14
+
15
+ ## 0.1.6-alpha.0
16
+
17
+ ### Patch Changes
18
+
19
+ - Updated dependencies [06aa827]
20
+ - @mastra/core@0.4.3-alpha.0
21
+
3
22
  ## 0.1.5
4
23
 
5
24
  ### Patch Changes
@@ -1,16 +1,16 @@
1
1
  import { BaseFilterTranslator } from '@mastra/core/filter';
2
- import { EvalRow } from '@mastra/core/storage';
3
- import { Filter } from '@mastra/core/filter';
2
+ import type { EvalRow } from '@mastra/core/storage';
3
+ import type { Filter } from '@mastra/core/filter';
4
4
  import { MastraStorage } from '@mastra/core/storage';
5
5
  import { MastraVector } from '@mastra/core/vector';
6
- import { MessageType } from '@mastra/core/memory';
7
- import { OperatorSupport } from '@mastra/core/filter';
6
+ import type { MessageType } from '@mastra/core/memory';
7
+ import type { OperatorSupport } from '@mastra/core/filter';
8
8
  import type { QueryResult } from '@mastra/core/vector';
9
- import { StorageColumn } from '@mastra/core/storage';
10
- import { StorageGetMessagesArg } from '@mastra/core/storage';
11
- import { StorageThreadType } from '@mastra/core/memory';
12
- import { TABLE_NAMES } from '@mastra/core/storage';
13
- import { WorkflowRunState } from '@mastra/core/workflows';
9
+ import type { StorageColumn } from '@mastra/core/storage';
10
+ import type { StorageGetMessagesArg } from '@mastra/core/storage';
11
+ import type { StorageThreadType } from '@mastra/core/memory';
12
+ import type { TABLE_NAMES } from '@mastra/core/storage';
13
+ import type { WorkflowRunState } from '@mastra/core/workflows';
14
14
 
15
15
  declare interface UpstashConfig {
16
16
  url: string;
@@ -34,12 +34,12 @@ export declare class UpstashFilterTranslator extends BaseFilterTranslator {
34
34
  }
35
35
 
36
36
  declare class UpstashStore extends MastraStorage {
37
- batchInsert({ tableName, records }: {
37
+ batchInsert(_input: {
38
38
  tableName: TABLE_NAMES;
39
39
  records: Record<string, any>[];
40
40
  }): Promise<void>;
41
- getEvalsByAgentName(agentName: string, type?: 'test' | 'live'): Promise<EvalRow[]>;
42
- getTraces({ name, scope, page, perPage, attributes, }: {
41
+ getEvalsByAgentName(_agentName: string, _type?: 'test' | 'live'): Promise<EvalRow[]>;
42
+ getTraces(_input: {
43
43
  name?: string;
44
44
  scope?: string;
45
45
  page: number;
package/dist/index.js CHANGED
@@ -1,6 +1,4 @@
1
- import '@mastra/core/memory';
2
1
  import { MastraStorage } from '@mastra/core/storage';
3
- import '@mastra/core/workflows';
4
2
  import { Redis } from '@upstash/redis';
5
3
  import { MastraVector } from '@mastra/core/vector';
6
4
  import { Index } from '@upstash/vector';
@@ -8,19 +6,13 @@ import { BaseFilterTranslator } from '@mastra/core/filter';
8
6
 
9
7
  // src/storage/index.ts
10
8
  var UpstashStore = class extends MastraStorage {
11
- batchInsert({ tableName, records }) {
9
+ batchInsert(_input) {
12
10
  throw new Error("Method not implemented.");
13
11
  }
14
- getEvalsByAgentName(agentName, type) {
12
+ getEvalsByAgentName(_agentName, _type) {
15
13
  throw new Error("Method not implemented.");
16
14
  }
17
- getTraces({
18
- name,
19
- scope,
20
- page,
21
- perPage,
22
- attributes
23
- }) {
15
+ getTraces(_input) {
24
16
  throw new Error("Method not implemented.");
25
17
  }
26
18
  redis;
@@ -0,0 +1,6 @@
1
+ import { createConfig } from '@internal/lint/eslint';
2
+
3
+ const config = await createConfig();
4
+
5
+ /** @type {import("eslint").Linter.Config[]} */
6
+ export default [...config];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/upstash",
3
- "version": "0.1.5",
3
+ "version": "0.1.6-alpha.1",
4
4
  "description": "Upstash provider for Mastra - includes both vector and db storage capabilities",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -17,20 +17,23 @@
17
17
  "dependencies": {
18
18
  "@upstash/redis": "^1.28.3",
19
19
  "@upstash/vector": "^1.1.7",
20
- "@mastra/core": "^0.4.2"
20
+ "@mastra/core": "^0.4.3-alpha.1"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@microsoft/api-extractor": "^7.49.2",
24
24
  "@types/node": "^22.13.1",
25
25
  "tsup": "^8.0.1",
26
26
  "typescript": "^5.7.3",
27
- "vitest": "^3.0.4"
27
+ "vitest": "^3.0.4",
28
+ "eslint": "^9.20.1",
29
+ "@internal/lint": "0.0.0"
28
30
  },
29
31
  "scripts": {
30
32
  "pretest": "docker compose up -d",
31
33
  "test": "vitest run",
32
34
  "posttest": "docker compose down",
33
35
  "build": "tsup src/index.ts --format esm --experimental-dts --clean --treeshake",
34
- "build:watch": "pnpm build --watch"
36
+ "build:watch": "pnpm build --watch",
37
+ "lint": "eslint ."
35
38
  }
36
39
  }
@@ -1,12 +1,7 @@
1
- import { type StorageThreadType, type MessageType } from '@mastra/core/memory';
2
- import {
3
- MastraStorage,
4
- type TABLE_NAMES,
5
- type StorageColumn,
6
- type StorageGetMessagesArg,
7
- type EvalRow,
8
- } from '@mastra/core/storage';
9
- import { type WorkflowRunState } from '@mastra/core/workflows';
1
+ import type { StorageThreadType, MessageType } from '@mastra/core/memory';
2
+ import { MastraStorage } from '@mastra/core/storage';
3
+ import type { TABLE_NAMES, StorageColumn, StorageGetMessagesArg, EvalRow } from '@mastra/core/storage';
4
+ import type { WorkflowRunState } from '@mastra/core/workflows';
10
5
  import { Redis } from '@upstash/redis';
11
6
 
12
7
  export interface UpstashConfig {
@@ -15,19 +10,13 @@ export interface UpstashConfig {
15
10
  }
16
11
 
17
12
  export class UpstashStore extends MastraStorage {
18
- batchInsert({ tableName, records }: { tableName: TABLE_NAMES; records: Record<string, any>[] }): Promise<void> {
13
+ batchInsert(_input: { tableName: TABLE_NAMES; records: Record<string, any>[] }): Promise<void> {
19
14
  throw new Error('Method not implemented.');
20
15
  }
21
- getEvalsByAgentName(agentName: string, type?: 'test' | 'live'): Promise<EvalRow[]> {
16
+ getEvalsByAgentName(_agentName: string, _type?: 'test' | 'live'): Promise<EvalRow[]> {
22
17
  throw new Error('Method not implemented.');
23
18
  }
24
- getTraces({
25
- name,
26
- scope,
27
- page,
28
- perPage,
29
- attributes,
30
- }: {
19
+ getTraces(_input: {
31
20
  name?: string;
32
21
  scope?: string;
33
22
  page: number;
@@ -3,379 +3,385 @@ import { describe, it, expect, beforeAll, beforeEach, afterAll } from 'vitest';
3
3
 
4
4
  import { UpstashStore } from './index';
5
5
 
6
- describe('UpstashStore', () => {
7
- let store: UpstashStore;
8
- const testTableName = 'test_table';
9
- const testTableName2 = 'test_table2';
10
-
11
- beforeAll(async () => {
12
- store = new UpstashStore({
13
- url: 'http://localhost:8079',
14
- token: 'test_token',
15
- });
16
- await store.init();
17
- });
18
-
19
- afterAll(async () => {
20
- // Clean up test tables
21
- await store.clearTable({ tableName: testTableName });
22
- await store.clearTable({ tableName: testTableName2 });
23
- await store.clearTable({ tableName: MastraStorage.TABLE_THREADS });
24
- await store.clearTable({ tableName: MastraStorage.TABLE_MESSAGES });
25
- });
26
-
27
- describe('Table Operations', () => {
28
- it('should create a new table with schema', async () => {
29
- await store.createTable({
30
- tableName: testTableName,
31
- schema: {
32
- id: { type: 'text', primaryKey: true },
33
- data: { type: 'text', nullable: true },
34
- },
35
- });
36
-
37
- // Verify table exists by inserting and retrieving data
38
- await store.insert({
39
- tableName: testTableName,
40
- record: { id: 'test1', data: 'test-data' },
6
+ describe(
7
+ 'UpstashStore',
8
+ () => {
9
+ let store: UpstashStore;
10
+ const testTableName = 'test_table';
11
+ const testTableName2 = 'test_table2';
12
+
13
+ beforeAll(async () => {
14
+ store = new UpstashStore({
15
+ url: 'http://localhost:8079',
16
+ token: 'test_token',
41
17
  });
18
+ await store.init();
19
+ });
42
20
 
43
- const result = await store.load({ tableName: testTableName, keys: { id: 'test1' } });
44
- expect(result).toBeTruthy();
21
+ afterAll(async () => {
22
+ // Clean up test tables
23
+ await store.clearTable({ tableName: testTableName });
24
+ await store.clearTable({ tableName: testTableName2 });
25
+ await store.clearTable({ tableName: MastraStorage.TABLE_THREADS });
26
+ await store.clearTable({ tableName: MastraStorage.TABLE_MESSAGES });
45
27
  });
46
28
 
47
- it('should handle multiple table creation', async () => {
48
- await store.createTable({
49
- tableName: testTableName2,
50
- schema: {
51
- id: { type: 'text', primaryKey: true },
52
- data: { type: 'text', nullable: true },
53
- },
54
- });
29
+ describe('Table Operations', () => {
30
+ it('should create a new table with schema', async () => {
31
+ await store.createTable({
32
+ tableName: testTableName,
33
+ schema: {
34
+ id: { type: 'text', primaryKey: true },
35
+ data: { type: 'text', nullable: true },
36
+ },
37
+ });
38
+
39
+ // Verify table exists by inserting and retrieving data
40
+ await store.insert({
41
+ tableName: testTableName,
42
+ record: { id: 'test1', data: 'test-data' },
43
+ });
55
44
 
56
- // Verify both tables work independently
57
- await store.insert({
58
- tableName: testTableName2,
59
- record: { id: 'test2', data: 'test-data-2' },
45
+ const result = await store.load({ tableName: testTableName, keys: { id: 'test1' } });
46
+ expect(result).toBeTruthy();
60
47
  });
61
48
 
62
- const result = await store.load({ tableName: testTableName2, keys: { id: 'test2' } });
63
- expect(result).toBeTruthy();
64
- });
65
- });
49
+ it('should handle multiple table creation', async () => {
50
+ await store.createTable({
51
+ tableName: testTableName2,
52
+ schema: {
53
+ id: { type: 'text', primaryKey: true },
54
+ data: { type: 'text', nullable: true },
55
+ },
56
+ });
66
57
 
67
- describe('Thread Operations', () => {
68
- beforeEach(async () => {
69
- await store.clearTable({ tableName: MastraStorage.TABLE_THREADS });
70
- });
58
+ // Verify both tables work independently
59
+ await store.insert({
60
+ tableName: testTableName2,
61
+ record: { id: 'test2', data: 'test-data-2' },
62
+ });
71
63
 
72
- it('should create and retrieve a thread', async () => {
73
- const now = new Date();
74
- const thread = {
75
- id: 'thread-1',
76
- resourceId: 'resource-1',
77
- title: 'Test Thread',
78
- createdAt: now,
79
- updatedAt: now,
80
- metadata: { key: 'value' },
81
- };
82
-
83
- const savedThread = await store.saveThread({ thread });
84
- expect(savedThread).toEqual(thread);
85
-
86
- const retrievedThread = await store.getThreadById({ threadId: thread.id });
87
- expect(retrievedThread).toEqual({
88
- ...thread,
89
- createdAt: new Date(now.toISOString()),
90
- updatedAt: new Date(now.toISOString()),
64
+ const result = await store.load({ tableName: testTableName2, keys: { id: 'test2' } });
65
+ expect(result).toBeTruthy();
91
66
  });
92
67
  });
93
68
 
94
- it('should return null for non-existent thread', async () => {
95
- const result = await store.getThreadById({ threadId: 'non-existent' });
96
- expect(result).toBeNull();
97
- });
69
+ describe('Thread Operations', () => {
70
+ beforeEach(async () => {
71
+ await store.clearTable({ tableName: MastraStorage.TABLE_THREADS });
72
+ });
98
73
 
99
- it('should get threads by resource ID', async () => {
100
- const resourceId = 'resource-1';
101
- const threads = [
102
- {
74
+ it('should create and retrieve a thread', async () => {
75
+ const now = new Date();
76
+ const thread = {
103
77
  id: 'thread-1',
104
- resourceId,
105
- title: 'Thread 1',
106
- createdAt: new Date(),
107
- updatedAt: new Date(),
108
- metadata: {},
109
- },
110
- {
111
- id: 'thread-2',
112
- resourceId,
113
- title: 'Thread 2',
114
- createdAt: new Date(),
115
- updatedAt: new Date(),
116
- metadata: {},
117
- },
118
- ];
119
-
120
- await Promise.all(threads.map(thread => store.saveThread({ thread })));
121
-
122
- const retrievedThreads = await store.getThreadsByResourceId({ resourceId });
123
- expect(retrievedThreads).toHaveLength(2);
124
- expect(retrievedThreads.map(t => t.id)).toEqual(expect.arrayContaining(['thread-1', 'thread-2']));
125
- });
126
-
127
- it('should update thread metadata', async () => {
128
- const thread = {
129
- id: 'thread-1',
130
- resourceId: 'resource-1',
131
- title: 'Test Thread',
132
- createdAt: new Date(),
133
- updatedAt: new Date(),
134
- metadata: { initial: 'value' },
135
- };
136
-
137
- await store.saveThread({ thread });
138
-
139
- const updatedThread = await store.updateThread({
140
- id: thread.id,
141
- title: 'Updated Title',
142
- metadata: { updated: 'value' },
78
+ resourceId: 'resource-1',
79
+ title: 'Test Thread',
80
+ createdAt: now,
81
+ updatedAt: now,
82
+ metadata: { key: 'value' },
83
+ };
84
+
85
+ const savedThread = await store.saveThread({ thread });
86
+ expect(savedThread).toEqual(thread);
87
+
88
+ const retrievedThread = await store.getThreadById({ threadId: thread.id });
89
+ expect(retrievedThread).toEqual({
90
+ ...thread,
91
+ createdAt: new Date(now.toISOString()),
92
+ updatedAt: new Date(now.toISOString()),
93
+ });
143
94
  });
144
95
 
145
- expect(updatedThread.title).toBe('Updated Title');
146
- expect(updatedThread.metadata).toEqual({
147
- initial: 'value',
148
- updated: 'value',
96
+ it('should return null for non-existent thread', async () => {
97
+ const result = await store.getThreadById({ threadId: 'non-existent' });
98
+ expect(result).toBeNull();
149
99
  });
150
- });
151
- });
152
100
 
153
- describe('Date Handling', () => {
154
- beforeEach(async () => {
155
- await store.clearTable({ tableName: MastraStorage.TABLE_THREADS });
156
- });
101
+ it('should get threads by resource ID', async () => {
102
+ const resourceId = 'resource-1';
103
+ const threads = [
104
+ {
105
+ id: 'thread-1',
106
+ resourceId,
107
+ title: 'Thread 1',
108
+ createdAt: new Date(),
109
+ updatedAt: new Date(),
110
+ metadata: {},
111
+ },
112
+ {
113
+ id: 'thread-2',
114
+ resourceId,
115
+ title: 'Thread 2',
116
+ createdAt: new Date(),
117
+ updatedAt: new Date(),
118
+ metadata: {},
119
+ },
120
+ ];
157
121
 
158
- it('should handle Date objects in thread operations', async () => {
159
- const now = new Date();
160
- const thread = {
161
- id: 'thread-1',
162
- resourceId: 'resource-1',
163
- title: 'Test Thread',
164
- createdAt: now,
165
- updatedAt: now,
166
- metadata: {},
167
- };
168
-
169
- await store.saveThread({ thread });
170
- const retrievedThread = await store.getThreadById({ threadId: thread.id });
171
- expect(retrievedThread?.createdAt).toBeInstanceOf(Date);
172
- expect(retrievedThread?.updatedAt).toBeInstanceOf(Date);
173
- expect(retrievedThread?.createdAt.toISOString()).toBe(now.toISOString());
174
- expect(retrievedThread?.updatedAt.toISOString()).toBe(now.toISOString());
175
- });
122
+ await Promise.all(threads.map(thread => store.saveThread({ thread })));
176
123
 
177
- it('should handle ISO string dates in thread operations', async () => {
178
- const now = new Date();
179
- const thread = {
180
- id: 'thread-2',
181
- resourceId: 'resource-1',
182
- title: 'Test Thread',
183
- createdAt: now.toISOString(),
184
- updatedAt: now.toISOString(),
185
- metadata: {},
186
- };
187
-
188
- await store.saveThread({ thread: thread as any });
189
- const retrievedThread = await store.getThreadById({ threadId: thread.id });
190
- expect(retrievedThread?.createdAt).toBeInstanceOf(Date);
191
- expect(retrievedThread?.updatedAt).toBeInstanceOf(Date);
192
- expect(retrievedThread?.createdAt.toISOString()).toBe(now.toISOString());
193
- expect(retrievedThread?.updatedAt.toISOString()).toBe(now.toISOString());
194
- });
124
+ const retrievedThreads = await store.getThreadsByResourceId({ resourceId });
125
+ expect(retrievedThreads).toHaveLength(2);
126
+ expect(retrievedThreads.map(t => t.id)).toEqual(expect.arrayContaining(['thread-1', 'thread-2']));
127
+ });
195
128
 
196
- it('should handle mixed date formats in thread operations', async () => {
197
- const now = new Date();
198
- const thread = {
199
- id: 'thread-3',
200
- resourceId: 'resource-1',
201
- title: 'Test Thread',
202
- createdAt: now,
203
- updatedAt: now.toISOString(),
204
- metadata: {},
205
- };
206
-
207
- await store.saveThread({ thread: thread as any });
208
- const retrievedThread = await store.getThreadById({ threadId: thread.id });
209
- expect(retrievedThread?.createdAt).toBeInstanceOf(Date);
210
- expect(retrievedThread?.updatedAt).toBeInstanceOf(Date);
211
- expect(retrievedThread?.createdAt.toISOString()).toBe(now.toISOString());
212
- expect(retrievedThread?.updatedAt.toISOString()).toBe(now.toISOString());
129
+ it('should update thread metadata', async () => {
130
+ const thread = {
131
+ id: 'thread-1',
132
+ resourceId: 'resource-1',
133
+ title: 'Test Thread',
134
+ createdAt: new Date(),
135
+ updatedAt: new Date(),
136
+ metadata: { initial: 'value' },
137
+ };
138
+
139
+ await store.saveThread({ thread });
140
+
141
+ const updatedThread = await store.updateThread({
142
+ id: thread.id,
143
+ title: 'Updated Title',
144
+ metadata: { updated: 'value' },
145
+ });
146
+
147
+ expect(updatedThread.title).toBe('Updated Title');
148
+ expect(updatedThread.metadata).toEqual({
149
+ initial: 'value',
150
+ updated: 'value',
151
+ });
152
+ });
213
153
  });
214
154
 
215
- it('should handle date serialization in getThreadsByResourceId', async () => {
216
- const now = new Date();
217
- const threads = [
218
- {
155
+ describe('Date Handling', () => {
156
+ beforeEach(async () => {
157
+ await store.clearTable({ tableName: MastraStorage.TABLE_THREADS });
158
+ });
159
+
160
+ it('should handle Date objects in thread operations', async () => {
161
+ const now = new Date();
162
+ const thread = {
219
163
  id: 'thread-1',
220
164
  resourceId: 'resource-1',
221
- title: 'Thread 1',
165
+ title: 'Test Thread',
222
166
  createdAt: now,
223
- updatedAt: now.toISOString(),
167
+ updatedAt: now,
224
168
  metadata: {},
225
- },
226
- {
169
+ };
170
+
171
+ await store.saveThread({ thread });
172
+ const retrievedThread = await store.getThreadById({ threadId: thread.id });
173
+ expect(retrievedThread?.createdAt).toBeInstanceOf(Date);
174
+ expect(retrievedThread?.updatedAt).toBeInstanceOf(Date);
175
+ expect(retrievedThread?.createdAt.toISOString()).toBe(now.toISOString());
176
+ expect(retrievedThread?.updatedAt.toISOString()).toBe(now.toISOString());
177
+ });
178
+
179
+ it('should handle ISO string dates in thread operations', async () => {
180
+ const now = new Date();
181
+ const thread = {
227
182
  id: 'thread-2',
228
183
  resourceId: 'resource-1',
229
- title: 'Thread 2',
184
+ title: 'Test Thread',
230
185
  createdAt: now.toISOString(),
231
- updatedAt: now,
186
+ updatedAt: now.toISOString(),
232
187
  metadata: {},
233
- },
234
- ];
235
-
236
- await Promise.all(threads.map(thread => store.saveThread({ thread: thread as any })));
237
-
238
- const retrievedThreads = await store.getThreadsByResourceId({ resourceId: 'resource-1' });
239
- expect(retrievedThreads).toHaveLength(2);
240
- retrievedThreads.forEach(thread => {
241
- expect(thread.createdAt).toBeInstanceOf(Date);
242
- expect(thread.updatedAt).toBeInstanceOf(Date);
243
- expect(thread.createdAt.toISOString()).toBe(now.toISOString());
244
- expect(thread.updatedAt.toISOString()).toBe(now.toISOString());
188
+ };
189
+
190
+ await store.saveThread({ thread: thread as any });
191
+ const retrievedThread = await store.getThreadById({ threadId: thread.id });
192
+ expect(retrievedThread?.createdAt).toBeInstanceOf(Date);
193
+ expect(retrievedThread?.updatedAt).toBeInstanceOf(Date);
194
+ expect(retrievedThread?.createdAt.toISOString()).toBe(now.toISOString());
195
+ expect(retrievedThread?.updatedAt.toISOString()).toBe(now.toISOString());
245
196
  });
246
- });
247
- });
248
-
249
- describe('Message Operations', () => {
250
- const threadId = 'test-thread';
251
-
252
- beforeEach(async () => {
253
- await store.clearTable({ tableName: MastraStorage.TABLE_MESSAGES });
254
- await store.clearTable({ tableName: MastraStorage.TABLE_THREADS });
255
197
 
256
- // Create a test thread
257
- await store.saveThread({
258
- thread: {
259
- id: threadId,
198
+ it('should handle mixed date formats in thread operations', async () => {
199
+ const now = new Date();
200
+ const thread = {
201
+ id: 'thread-3',
260
202
  resourceId: 'resource-1',
261
203
  title: 'Test Thread',
262
- createdAt: new Date(),
263
- updatedAt: new Date(),
204
+ createdAt: now,
205
+ updatedAt: now.toISOString(),
264
206
  metadata: {},
265
- },
207
+ };
208
+
209
+ await store.saveThread({ thread: thread as any });
210
+ const retrievedThread = await store.getThreadById({ threadId: thread.id });
211
+ expect(retrievedThread?.createdAt).toBeInstanceOf(Date);
212
+ expect(retrievedThread?.updatedAt).toBeInstanceOf(Date);
213
+ expect(retrievedThread?.createdAt.toISOString()).toBe(now.toISOString());
214
+ expect(retrievedThread?.updatedAt.toISOString()).toBe(now.toISOString());
266
215
  });
267
- });
268
216
 
269
- it('should save and retrieve messages in order', async () => {
270
- const messages = [
271
- {
272
- id: 'msg-1',
273
- threadId,
274
- role: 'user',
275
- type: 'text',
276
- content: [{ type: 'text', text: 'First' }],
277
- createdAt: new Date().toISOString(),
278
- },
279
- {
280
- id: 'msg-2',
281
- threadId,
282
- role: 'assistant',
283
- type: 'text',
284
- content: [{ type: 'text', text: 'Second' }],
285
- createdAt: new Date().toISOString(),
286
- },
287
- {
288
- id: 'msg-3',
289
- threadId,
290
- role: 'user',
291
- type: 'text',
292
- content: [{ type: 'text', text: 'Third' }],
293
- createdAt: new Date().toISOString(),
294
- },
295
- ];
296
-
297
- await store.saveMessages({ messages });
298
-
299
- const retrievedMessages = await store.getMessages({ threadId });
300
- expect(retrievedMessages).toHaveLength(3);
301
- expect(retrievedMessages.map(m => m.content[0].text)).toEqual(['First', 'Second', 'Third']);
217
+ it('should handle date serialization in getThreadsByResourceId', async () => {
218
+ const now = new Date();
219
+ const threads = [
220
+ {
221
+ id: 'thread-1',
222
+ resourceId: 'resource-1',
223
+ title: 'Thread 1',
224
+ createdAt: now,
225
+ updatedAt: now.toISOString(),
226
+ metadata: {},
227
+ },
228
+ {
229
+ id: 'thread-2',
230
+ resourceId: 'resource-1',
231
+ title: 'Thread 2',
232
+ createdAt: now.toISOString(),
233
+ updatedAt: now,
234
+ metadata: {},
235
+ },
236
+ ];
237
+
238
+ await Promise.all(threads.map(thread => store.saveThread({ thread: thread as any })));
239
+
240
+ const retrievedThreads = await store.getThreadsByResourceId({ resourceId: 'resource-1' });
241
+ expect(retrievedThreads).toHaveLength(2);
242
+ retrievedThreads.forEach(thread => {
243
+ expect(thread.createdAt).toBeInstanceOf(Date);
244
+ expect(thread.updatedAt).toBeInstanceOf(Date);
245
+ expect(thread.createdAt.toISOString()).toBe(now.toISOString());
246
+ expect(thread.updatedAt.toISOString()).toBe(now.toISOString());
247
+ });
248
+ });
302
249
  });
303
250
 
304
- it('should handle empty message array', async () => {
305
- const result = await store.saveMessages({ messages: [] });
306
- expect(result).toEqual([]);
307
- });
251
+ describe('Message Operations', () => {
252
+ const threadId = 'test-thread';
253
+
254
+ beforeEach(async () => {
255
+ await store.clearTable({ tableName: MastraStorage.TABLE_MESSAGES });
256
+ await store.clearTable({ tableName: MastraStorage.TABLE_THREADS });
257
+
258
+ // Create a test thread
259
+ await store.saveThread({
260
+ thread: {
261
+ id: threadId,
262
+ resourceId: 'resource-1',
263
+ title: 'Test Thread',
264
+ createdAt: new Date(),
265
+ updatedAt: new Date(),
266
+ metadata: {},
267
+ },
268
+ });
269
+ });
308
270
 
309
- it('should handle messages with complex content', async () => {
310
- const messages = [
311
- {
312
- id: 'msg-1',
313
- threadId,
314
- role: 'user',
315
- type: 'text',
316
- content: [
317
- { type: 'text', text: 'Message with' },
318
- { type: 'code', text: 'code block', language: 'typescript' },
319
- { type: 'text', text: 'and more text' },
320
- ],
321
- createdAt: new Date().toISOString(),
322
- },
323
- ];
324
-
325
- await store.saveMessages({ messages });
326
-
327
- const retrievedMessages = await store.getMessages({ threadId });
328
- expect(retrievedMessages[0].content).toEqual(messages[0].content);
329
- });
330
- });
271
+ it('should save and retrieve messages in order', async () => {
272
+ const messages = [
273
+ {
274
+ id: 'msg-1',
275
+ threadId,
276
+ role: 'user',
277
+ type: 'text',
278
+ content: [{ type: 'text', text: 'First' }],
279
+ createdAt: new Date().toISOString(),
280
+ },
281
+ {
282
+ id: 'msg-2',
283
+ threadId,
284
+ role: 'assistant',
285
+ type: 'text',
286
+ content: [{ type: 'text', text: 'Second' }],
287
+ createdAt: new Date().toISOString(),
288
+ },
289
+ {
290
+ id: 'msg-3',
291
+ threadId,
292
+ role: 'user',
293
+ type: 'text',
294
+ content: [{ type: 'text', text: 'Third' }],
295
+ createdAt: new Date().toISOString(),
296
+ },
297
+ ];
331
298
 
332
- describe('Workflow Operations', () => {
333
- const testNamespace = 'test';
334
- const testWorkflow = 'test-workflow';
335
- const testRunId = 'test-run';
299
+ await store.saveMessages({ messages });
336
300
 
337
- beforeEach(async () => {
338
- await store.clearTable({ tableName: MastraStorage.TABLE_WORKFLOW_SNAPSHOT });
339
- });
301
+ const retrievedMessages = await store.getMessages({ threadId });
302
+ expect(retrievedMessages).toHaveLength(3);
303
+ expect(retrievedMessages.map(m => m.content[0].text)).toEqual(['First', 'Second', 'Third']);
304
+ });
305
+
306
+ it('should handle empty message array', async () => {
307
+ const result = await store.saveMessages({ messages: [] });
308
+ expect(result).toEqual([]);
309
+ });
340
310
 
341
- it('should persist and load workflow snapshots', async () => {
342
- const mockSnapshot = {
343
- value: { step1: 'completed' },
344
- context: {
345
- stepResults: {
346
- step1: { status: 'success', payload: { result: 'done' } },
311
+ it('should handle messages with complex content', async () => {
312
+ const messages = [
313
+ {
314
+ id: 'msg-1',
315
+ threadId,
316
+ role: 'user',
317
+ type: 'text',
318
+ content: [
319
+ { type: 'text', text: 'Message with' },
320
+ { type: 'code', text: 'code block', language: 'typescript' },
321
+ { type: 'text', text: 'and more text' },
322
+ ],
323
+ createdAt: new Date().toISOString(),
347
324
  },
348
- attempts: {},
349
- triggerData: {},
350
- },
351
- runId: testRunId,
352
- activePaths: [],
353
- timestamp: Date.now(),
354
- };
355
-
356
- await store.persistWorkflowSnapshot({
357
- namespace: testNamespace,
358
- workflowName: testWorkflow,
359
- runId: testRunId,
360
- snapshot: mockSnapshot,
325
+ ];
326
+
327
+ await store.saveMessages({ messages });
328
+
329
+ const retrievedMessages = await store.getMessages({ threadId });
330
+ expect(retrievedMessages[0].content).toEqual(messages[0].content);
361
331
  });
332
+ });
333
+
334
+ describe('Workflow Operations', () => {
335
+ const testNamespace = 'test';
336
+ const testWorkflow = 'test-workflow';
337
+ const testRunId = 'test-run';
362
338
 
363
- const loadedSnapshot = await store.loadWorkflowSnapshot({
364
- namespace: testNamespace,
365
- workflowName: testWorkflow,
366
- runId: testRunId,
339
+ beforeEach(async () => {
340
+ await store.clearTable({ tableName: MastraStorage.TABLE_WORKFLOW_SNAPSHOT });
367
341
  });
368
342
 
369
- expect(loadedSnapshot).toEqual(mockSnapshot);
370
- });
343
+ it('should persist and load workflow snapshots', async () => {
344
+ const mockSnapshot = {
345
+ value: { step1: 'completed' },
346
+ context: {
347
+ stepResults: {
348
+ step1: { status: 'success', payload: { result: 'done' } },
349
+ },
350
+ attempts: {},
351
+ triggerData: {},
352
+ },
353
+ runId: testRunId,
354
+ activePaths: [],
355
+ timestamp: Date.now(),
356
+ };
357
+
358
+ await store.persistWorkflowSnapshot({
359
+ namespace: testNamespace,
360
+ workflowName: testWorkflow,
361
+ runId: testRunId,
362
+ snapshot: mockSnapshot,
363
+ });
364
+
365
+ const loadedSnapshot = await store.loadWorkflowSnapshot({
366
+ namespace: testNamespace,
367
+ workflowName: testWorkflow,
368
+ runId: testRunId,
369
+ });
370
+
371
+ expect(loadedSnapshot).toEqual(mockSnapshot);
372
+ });
371
373
 
372
- it('should return null for non-existent snapshot', async () => {
373
- const result = await store.loadWorkflowSnapshot({
374
- namespace: testNamespace,
375
- workflowName: 'non-existent',
376
- runId: 'non-existent',
374
+ it('should return null for non-existent snapshot', async () => {
375
+ const result = await store.loadWorkflowSnapshot({
376
+ namespace: testNamespace,
377
+ workflowName: 'non-existent',
378
+ runId: 'non-existent',
379
+ });
380
+ expect(result).toBeNull();
377
381
  });
378
- expect(result).toBeNull();
379
382
  });
380
- });
381
- });
383
+ },
384
+ {
385
+ timeout: 30000,
386
+ },
387
+ );
@@ -1,4 +1,5 @@
1
- import { BaseFilterTranslator, type Filter, type FieldCondition, type OperatorSupport } from '@mastra/core/filter';
1
+ import { BaseFilterTranslator } from '@mastra/core/filter';
2
+ import type { Filter, FieldCondition, OperatorSupport } from '@mastra/core/filter';
2
3
 
3
4
  export class UpstashFilterTranslator extends BaseFilterTranslator {
4
5
  protected override getSupportedOperators(): OperatorSupport {
@@ -1,4 +1,4 @@
1
- import { describe, it, expect, beforeAll, afterAll, beforeEach, test } from 'vitest';
1
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
2
2
 
3
3
  import { UpstashVector } from './';
4
4