@mastra/dynamodb 0.0.0-taofeeqInngest-20250603090617 → 0.0.0-tsconfig-compile-20250703214351
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_tsup-dts-rollup.d.cts +1160 -0
- package/dist/_tsup-dts-rollup.d.ts +1160 -0
- package/dist/index.cjs +376 -102
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +352 -78
- package/package.json +31 -17
- package/src/storage/index.test.ts +311 -1
- package/src/storage/index.ts +419 -94
package/package.json
CHANGED
|
@@ -1,37 +1,51 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/dynamodb",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-tsconfig-compile-20250703214351",
|
|
4
4
|
"description": "DynamoDB storage adapter for Mastra",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"require": {
|
|
15
|
+
"types": "./dist/index.d.cts",
|
|
16
|
+
"default": "./dist/index.cjs"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"./package.json": "./package.json"
|
|
20
|
+
},
|
|
8
21
|
"files": [
|
|
9
22
|
"dist",
|
|
10
23
|
"src"
|
|
11
24
|
],
|
|
12
25
|
"dependencies": {
|
|
13
|
-
"@aws-sdk/client-dynamodb": "^3.
|
|
14
|
-
"@aws-sdk/lib-dynamodb": "^3.
|
|
15
|
-
"electrodb": "^3.4.
|
|
26
|
+
"@aws-sdk/client-dynamodb": "^3.839.0",
|
|
27
|
+
"@aws-sdk/lib-dynamodb": "^3.830.0",
|
|
28
|
+
"electrodb": "^3.4.3"
|
|
16
29
|
},
|
|
17
30
|
"peerDependencies": {
|
|
18
|
-
"@mastra/core": "
|
|
31
|
+
"@mastra/core": "0.0.0-tsconfig-compile-20250703214351"
|
|
19
32
|
},
|
|
20
33
|
"devDependencies": {
|
|
21
|
-
"@microsoft/api-extractor": "^7.52.
|
|
22
|
-
"@types/node": "^20.
|
|
23
|
-
"@vitest/coverage-v8": "3.
|
|
24
|
-
"@vitest/ui": "3.
|
|
25
|
-
"axios": "^1.
|
|
26
|
-
"eslint": "^9.
|
|
27
|
-
"tsup": "^8.
|
|
28
|
-
"typescript": "^5.8.
|
|
29
|
-
"vitest": "^3.
|
|
30
|
-
"@internal/lint": "0.0.0-
|
|
31
|
-
"@mastra/core": "0.0.0-
|
|
34
|
+
"@microsoft/api-extractor": "^7.52.8",
|
|
35
|
+
"@types/node": "^20.19.0",
|
|
36
|
+
"@vitest/coverage-v8": "3.2.3",
|
|
37
|
+
"@vitest/ui": "3.2.3",
|
|
38
|
+
"axios": "^1.10.0",
|
|
39
|
+
"eslint": "^9.29.0",
|
|
40
|
+
"tsup": "^8.5.0",
|
|
41
|
+
"typescript": "^5.8.3",
|
|
42
|
+
"vitest": "^3.2.4",
|
|
43
|
+
"@internal/lint": "0.0.0-tsconfig-compile-20250703214351",
|
|
44
|
+
"@mastra/core": "0.0.0-tsconfig-compile-20250703214351",
|
|
45
|
+
"@internal/storage-test-utils": "0.0.13"
|
|
32
46
|
},
|
|
33
47
|
"scripts": {
|
|
34
|
-
"build": "tsup src/index.ts --format esm,cjs --clean --treeshake=smallest --splitting",
|
|
48
|
+
"build": "tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting",
|
|
35
49
|
"dev": "tsup --watch",
|
|
36
50
|
"clean": "rm -rf dist",
|
|
37
51
|
"lint": "eslint .",
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
waitUntilTableExists,
|
|
12
12
|
waitUntilTableNotExists,
|
|
13
13
|
} from '@aws-sdk/client-dynamodb';
|
|
14
|
+
import { createSampleMessageV2, createSampleThread } from '@internal/storage-test-utils';
|
|
14
15
|
import type { MastraMessageV1, StorageThreadType, WorkflowRun, WorkflowRunState } from '@mastra/core';
|
|
15
16
|
import type { MastraMessageV2 } from '@mastra/core/agent';
|
|
16
17
|
import { TABLE_EVALS, TABLE_THREADS, TABLE_WORKFLOW_SNAPSHOT } from '@mastra/core/storage';
|
|
@@ -325,6 +326,7 @@ describe('DynamoDBStore Integration Tests', () => {
|
|
|
325
326
|
suspendedPaths: { test: [1] },
|
|
326
327
|
runId: 'test-run-large', // Use unique runId
|
|
327
328
|
timestamp: now,
|
|
329
|
+
status: 'success',
|
|
328
330
|
};
|
|
329
331
|
|
|
330
332
|
await expect(
|
|
@@ -387,6 +389,98 @@ describe('DynamoDBStore Integration Tests', () => {
|
|
|
387
389
|
expect(retrieved?.title).toBe('Updated Thread 2');
|
|
388
390
|
expect(retrieved?.metadata?.update).toBe(2);
|
|
389
391
|
});
|
|
392
|
+
|
|
393
|
+
test('getMessages should return the N most recent messages [v2 storage]', async () => {
|
|
394
|
+
const threadId = 'last-selector-thread';
|
|
395
|
+
const start = Date.now();
|
|
396
|
+
|
|
397
|
+
// Insert 10 messages with increasing timestamps
|
|
398
|
+
const messages: MastraMessageV2[] = Array.from({ length: 10 }, (_, i) => ({
|
|
399
|
+
id: `m-${i}`,
|
|
400
|
+
threadId,
|
|
401
|
+
resourceId: 'r',
|
|
402
|
+
content: { format: 2, parts: [{ type: 'text', text: `msg-${i}` }] },
|
|
403
|
+
createdAt: new Date(start + i), // 0..9 ms apart
|
|
404
|
+
role: 'user',
|
|
405
|
+
type: 'text',
|
|
406
|
+
}));
|
|
407
|
+
await store.saveMessages({ messages, format: 'v2' });
|
|
408
|
+
|
|
409
|
+
const last3 = await store.getMessages({
|
|
410
|
+
format: 'v2',
|
|
411
|
+
threadId,
|
|
412
|
+
selectBy: { last: 3 },
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
expect(last3).toHaveLength(3);
|
|
416
|
+
expect(last3.map(m => (m.content.parts[0] as { type: string; text: string }).text)).toEqual([
|
|
417
|
+
'msg-7',
|
|
418
|
+
'msg-8',
|
|
419
|
+
'msg-9',
|
|
420
|
+
]);
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
test('getMessages should return the N most recent messages [v1 storage]', async () => {
|
|
424
|
+
const threadId = 'last-selector-thread';
|
|
425
|
+
const start = Date.now();
|
|
426
|
+
|
|
427
|
+
// Insert 10 messages with increasing timestamps
|
|
428
|
+
const messages: MastraMessageV1[] = Array.from({ length: 10 }, (_, i) => ({
|
|
429
|
+
id: `m-${i}`,
|
|
430
|
+
threadId,
|
|
431
|
+
resourceId: 'r',
|
|
432
|
+
content: `msg-${i}`,
|
|
433
|
+
createdAt: new Date(start + i), // 0..9 ms apart
|
|
434
|
+
role: 'user',
|
|
435
|
+
type: 'text',
|
|
436
|
+
}));
|
|
437
|
+
await store.saveMessages({ messages });
|
|
438
|
+
|
|
439
|
+
const last3 = await store.getMessages({
|
|
440
|
+
threadId,
|
|
441
|
+
selectBy: { last: 3 },
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
expect(last3).toHaveLength(3);
|
|
445
|
+
expect(last3.map(m => m.content)).toEqual(['msg-7', 'msg-8', 'msg-9']);
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
test('should update thread updatedAt when a message is saved to it', async () => {
|
|
449
|
+
const thread: StorageThreadType = {
|
|
450
|
+
id: 'thread-update-test',
|
|
451
|
+
resourceId: 'resource-update',
|
|
452
|
+
title: 'Update Test Thread',
|
|
453
|
+
createdAt: new Date(),
|
|
454
|
+
updatedAt: new Date(),
|
|
455
|
+
metadata: { test: true },
|
|
456
|
+
};
|
|
457
|
+
await store.saveThread({ thread });
|
|
458
|
+
|
|
459
|
+
// Get the initial thread to capture the original updatedAt
|
|
460
|
+
const initialThread = await store.getThreadById({ threadId: thread.id });
|
|
461
|
+
expect(initialThread).toBeDefined();
|
|
462
|
+
const originalUpdatedAt = initialThread!.updatedAt;
|
|
463
|
+
|
|
464
|
+
// Wait a small amount to ensure different timestamp
|
|
465
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
466
|
+
|
|
467
|
+
// Create and save a message to the thread
|
|
468
|
+
const message: MastraMessageV1 = {
|
|
469
|
+
id: 'msg-update-test',
|
|
470
|
+
threadId: thread.id,
|
|
471
|
+
resourceId: 'resource-update',
|
|
472
|
+
content: 'Test message for update',
|
|
473
|
+
createdAt: new Date(),
|
|
474
|
+
role: 'user',
|
|
475
|
+
type: 'text',
|
|
476
|
+
};
|
|
477
|
+
await store.saveMessages({ messages: [message] });
|
|
478
|
+
|
|
479
|
+
// Retrieve the thread again and check that updatedAt was updated
|
|
480
|
+
const updatedThread = await store.getThreadById({ threadId: thread.id });
|
|
481
|
+
expect(updatedThread).toBeDefined();
|
|
482
|
+
expect(updatedThread!.updatedAt.getTime()).toBeGreaterThan(originalUpdatedAt.getTime());
|
|
483
|
+
});
|
|
390
484
|
});
|
|
391
485
|
|
|
392
486
|
describe('Batch Operations', () => {
|
|
@@ -462,6 +556,82 @@ describe('DynamoDBStore Integration Tests', () => {
|
|
|
462
556
|
expect(retrieved[0]?.content).toBe('Large Message 0');
|
|
463
557
|
expect(retrieved[29]?.content).toBe('Large Message 29');
|
|
464
558
|
});
|
|
559
|
+
|
|
560
|
+
test('should upsert messages: duplicate id+threadId results in update, not duplicate row', async () => {
|
|
561
|
+
const thread = await createSampleThread();
|
|
562
|
+
await store.saveThread({ thread });
|
|
563
|
+
const baseMessage = createSampleMessageV2({
|
|
564
|
+
threadId: thread.id,
|
|
565
|
+
createdAt: new Date(),
|
|
566
|
+
content: { content: 'Original' },
|
|
567
|
+
resourceId: thread.resourceId,
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
// Insert the message for the first time
|
|
571
|
+
await store.saveMessages({ messages: [baseMessage], format: 'v2' });
|
|
572
|
+
|
|
573
|
+
// // Insert again with the same id and threadId but different content
|
|
574
|
+
const updatedMessage = {
|
|
575
|
+
...createSampleMessageV2({
|
|
576
|
+
threadId: thread.id,
|
|
577
|
+
createdAt: new Date(),
|
|
578
|
+
content: { content: 'Updated' },
|
|
579
|
+
resourceId: thread.resourceId,
|
|
580
|
+
}),
|
|
581
|
+
id: baseMessage.id,
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
await store.saveMessages({ messages: [updatedMessage], format: 'v2' });
|
|
585
|
+
|
|
586
|
+
// Retrieve messages for the thread
|
|
587
|
+
const retrievedMessages = await store.getMessages({ threadId: thread.id, format: 'v2' });
|
|
588
|
+
|
|
589
|
+
// Only one message should exist for that id+threadId
|
|
590
|
+
expect(retrievedMessages.filter(m => m.id === baseMessage.id)).toHaveLength(1);
|
|
591
|
+
|
|
592
|
+
// The content should be the updated one
|
|
593
|
+
expect(retrievedMessages.find(m => m.id === baseMessage.id)?.content.content).toBe('Updated');
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
test('should upsert messages: duplicate id and different threadid', async () => {
|
|
597
|
+
const thread1 = await createSampleThread();
|
|
598
|
+
const thread2 = await createSampleThread();
|
|
599
|
+
await store.saveThread({ thread: thread1 });
|
|
600
|
+
await store.saveThread({ thread: thread2 });
|
|
601
|
+
|
|
602
|
+
const message = createSampleMessageV2({
|
|
603
|
+
threadId: thread1.id,
|
|
604
|
+
createdAt: new Date(),
|
|
605
|
+
content: { content: 'Thread1 Content' },
|
|
606
|
+
resourceId: thread1.resourceId,
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
// Insert message into thread1
|
|
610
|
+
await store.saveMessages({ messages: [message], format: 'v2' });
|
|
611
|
+
|
|
612
|
+
// Attempt to insert a message with the same id but different threadId
|
|
613
|
+
const conflictingMessage = {
|
|
614
|
+
...createSampleMessageV2({
|
|
615
|
+
threadId: thread2.id, // different thread
|
|
616
|
+
content: { content: 'Thread2 Content' },
|
|
617
|
+
resourceId: thread2.resourceId,
|
|
618
|
+
}),
|
|
619
|
+
id: message.id,
|
|
620
|
+
};
|
|
621
|
+
|
|
622
|
+
// Save should save the message to the new thread
|
|
623
|
+
await store.saveMessages({ messages: [conflictingMessage], format: 'v2' });
|
|
624
|
+
|
|
625
|
+
// Retrieve messages for both threads
|
|
626
|
+
const thread1Messages = await store.getMessages({ threadId: thread1.id, format: 'v2' });
|
|
627
|
+
const thread2Messages = await store.getMessages({ threadId: thread2.id, format: 'v2' });
|
|
628
|
+
|
|
629
|
+
// Thread 1 should NOT have the message with that id
|
|
630
|
+
expect(thread1Messages.find(m => m.id === message.id)).toBeUndefined();
|
|
631
|
+
|
|
632
|
+
// Thread 2 should have the message with that id
|
|
633
|
+
expect(thread2Messages.find(m => m.id === message.id)?.content.content).toBe('Thread2 Content');
|
|
634
|
+
});
|
|
465
635
|
});
|
|
466
636
|
|
|
467
637
|
describe('Single-Table Design', () => {
|
|
@@ -492,6 +662,7 @@ describe('DynamoDBStore Integration Tests', () => {
|
|
|
492
662
|
suspendedPaths: { test: [1] },
|
|
493
663
|
runId: 'mixed-run',
|
|
494
664
|
timestamp: Date.now(),
|
|
665
|
+
status: 'success',
|
|
495
666
|
};
|
|
496
667
|
await store.persistWorkflowSnapshot({ workflowName, runId: 'mixed-run', snapshot: workflowSnapshot });
|
|
497
668
|
|
|
@@ -589,6 +760,37 @@ describe('DynamoDBStore Integration Tests', () => {
|
|
|
589
760
|
expect(allTraces.length).toBe(3);
|
|
590
761
|
});
|
|
591
762
|
|
|
763
|
+
test('should handle Date objects for createdAt/updatedAt fields in batchTraceInsert', async () => {
|
|
764
|
+
// This test specifically verifies the bug from the issue where Date objects
|
|
765
|
+
// were passed instead of ISO strings and ElectroDB validation failed
|
|
766
|
+
const now = new Date();
|
|
767
|
+
const traceWithDateObjects = {
|
|
768
|
+
id: `trace-${randomUUID()}`,
|
|
769
|
+
parentSpanId: `span-${randomUUID()}`,
|
|
770
|
+
traceId: `traceid-${randomUUID()}`,
|
|
771
|
+
name: 'test-trace-with-dates',
|
|
772
|
+
scope: 'default-tracer',
|
|
773
|
+
kind: 1,
|
|
774
|
+
startTime: now.getTime(),
|
|
775
|
+
endTime: now.getTime() + 100,
|
|
776
|
+
status: JSON.stringify({ code: 0 }),
|
|
777
|
+
attributes: JSON.stringify({ key: 'value' }),
|
|
778
|
+
events: JSON.stringify([]),
|
|
779
|
+
links: JSON.stringify([]),
|
|
780
|
+
// These are Date objects, not ISO strings - this should be handled by ElectroDB attribute setters
|
|
781
|
+
createdAt: now,
|
|
782
|
+
updatedAt: now,
|
|
783
|
+
};
|
|
784
|
+
|
|
785
|
+
// This should not throw a validation error due to Date object type
|
|
786
|
+
await expect(store.batchTraceInsert({ records: [traceWithDateObjects] })).resolves.not.toThrow();
|
|
787
|
+
|
|
788
|
+
// Verify the trace was saved correctly
|
|
789
|
+
const allTraces = await store.getTraces({ name: 'test-trace-with-dates', page: 1, perPage: 10 });
|
|
790
|
+
expect(allTraces.length).toBe(1);
|
|
791
|
+
expect(allTraces[0].name).toBe('test-trace-with-dates');
|
|
792
|
+
});
|
|
793
|
+
|
|
592
794
|
test('should retrieve traces filtered by name using GSI', async () => {
|
|
593
795
|
const trace1 = sampleTrace('trace-filter-name', 'scope-X');
|
|
594
796
|
const trace2 = sampleTrace('trace-filter-name', 'scope-Y', Date.now() + 10);
|
|
@@ -670,6 +872,40 @@ describe('DynamoDBStore Integration Tests', () => {
|
|
|
670
872
|
};
|
|
671
873
|
};
|
|
672
874
|
|
|
875
|
+
test('should handle Date objects for createdAt/updatedAt fields in eval batchInsert', async () => {
|
|
876
|
+
// Test that eval entity properly handles Date objects in createdAt/updatedAt fields
|
|
877
|
+
const now = new Date();
|
|
878
|
+
const evalWithDateObjects = {
|
|
879
|
+
entity: 'eval',
|
|
880
|
+
agent_name: 'test-agent-dates',
|
|
881
|
+
input: 'Test input',
|
|
882
|
+
output: 'Test output',
|
|
883
|
+
result: JSON.stringify({ score: 0.95 }),
|
|
884
|
+
metric_name: 'test-metric',
|
|
885
|
+
instructions: 'Test instructions',
|
|
886
|
+
global_run_id: `global-${randomUUID()}`,
|
|
887
|
+
run_id: `run-${randomUUID()}`,
|
|
888
|
+
created_at: now, // Date object instead of ISO string
|
|
889
|
+
// These are Date objects, not ISO strings - should be handled by ElectroDB attribute setters
|
|
890
|
+
createdAt: now,
|
|
891
|
+
updatedAt: now,
|
|
892
|
+
metadata: JSON.stringify({ test: 'meta' }),
|
|
893
|
+
};
|
|
894
|
+
|
|
895
|
+
// This should not throw a validation error due to Date object type
|
|
896
|
+
await expect(
|
|
897
|
+
store.batchInsert({
|
|
898
|
+
tableName: TABLE_EVALS,
|
|
899
|
+
records: [evalWithDateObjects],
|
|
900
|
+
}),
|
|
901
|
+
).resolves.not.toThrow();
|
|
902
|
+
|
|
903
|
+
// Verify the eval was saved correctly
|
|
904
|
+
const evals = await store.getEvalsByAgentName('test-agent-dates');
|
|
905
|
+
expect(evals.length).toBe(1);
|
|
906
|
+
expect(evals[0].agentName).toBe('test-agent-dates');
|
|
907
|
+
});
|
|
908
|
+
|
|
673
909
|
test('should retrieve evals by agent name using GSI and filter by type', async () => {
|
|
674
910
|
const agent1 = 'eval-agent-1';
|
|
675
911
|
const agent2 = 'eval-agent-2';
|
|
@@ -741,6 +977,7 @@ describe('DynamoDBStore Integration Tests', () => {
|
|
|
741
977
|
suspendedPaths: {},
|
|
742
978
|
runId: runId,
|
|
743
979
|
timestamp: createdAt.getTime(),
|
|
980
|
+
status: 'success',
|
|
744
981
|
...(resourceId && { resourceId: resourceId }), // Conditionally add resourceId to snapshot
|
|
745
982
|
};
|
|
746
983
|
return {
|
|
@@ -781,6 +1018,53 @@ describe('DynamoDBStore Integration Tests', () => {
|
|
|
781
1018
|
expect(loadedSnapshot?.context).toEqual(snapshot.context);
|
|
782
1019
|
});
|
|
783
1020
|
|
|
1021
|
+
test('should allow updating an existing workflow snapshot', async () => {
|
|
1022
|
+
const wfName = 'update-test-wf';
|
|
1023
|
+
const runId = `run-${randomUUID()}`;
|
|
1024
|
+
|
|
1025
|
+
// Create initial snapshot
|
|
1026
|
+
const { snapshot: initialSnapshot } = sampleWorkflowSnapshot(wfName, runId);
|
|
1027
|
+
|
|
1028
|
+
await expect(
|
|
1029
|
+
store.persistWorkflowSnapshot({
|
|
1030
|
+
workflowName: wfName,
|
|
1031
|
+
runId: runId,
|
|
1032
|
+
snapshot: initialSnapshot,
|
|
1033
|
+
}),
|
|
1034
|
+
).resolves.not.toThrow();
|
|
1035
|
+
|
|
1036
|
+
// Create updated snapshot with different data
|
|
1037
|
+
const updatedSnapshot: WorkflowRunState = {
|
|
1038
|
+
...initialSnapshot,
|
|
1039
|
+
value: { currentState: 'completed' },
|
|
1040
|
+
context: {
|
|
1041
|
+
step1: { status: 'success', output: { data: 'updated-test' } },
|
|
1042
|
+
step2: { status: 'success', output: { data: 'new-step' } },
|
|
1043
|
+
input: { source: 'updated-test' },
|
|
1044
|
+
} as unknown as WorkflowRunState['context'],
|
|
1045
|
+
timestamp: Date.now(),
|
|
1046
|
+
};
|
|
1047
|
+
|
|
1048
|
+
// This should succeed (update existing snapshot)
|
|
1049
|
+
await expect(
|
|
1050
|
+
store.persistWorkflowSnapshot({
|
|
1051
|
+
workflowName: wfName,
|
|
1052
|
+
runId: runId,
|
|
1053
|
+
snapshot: updatedSnapshot,
|
|
1054
|
+
}),
|
|
1055
|
+
).resolves.not.toThrow();
|
|
1056
|
+
|
|
1057
|
+
// Verify the snapshot was updated
|
|
1058
|
+
const loadedSnapshot = await store.loadWorkflowSnapshot({
|
|
1059
|
+
workflowName: wfName,
|
|
1060
|
+
runId: runId,
|
|
1061
|
+
});
|
|
1062
|
+
|
|
1063
|
+
expect(loadedSnapshot?.runId).toEqual(updatedSnapshot.runId);
|
|
1064
|
+
expect(loadedSnapshot?.value).toEqual(updatedSnapshot.value);
|
|
1065
|
+
expect(loadedSnapshot?.context).toEqual(updatedSnapshot.context);
|
|
1066
|
+
});
|
|
1067
|
+
|
|
784
1068
|
test('getWorkflowRunById should retrieve correct run', async () => {
|
|
785
1069
|
const wfName = 'get-by-id-wf';
|
|
786
1070
|
const runId1 = `run-${randomUUID()}`;
|
|
@@ -1012,6 +1296,32 @@ describe('DynamoDBStore Integration Tests', () => {
|
|
|
1012
1296
|
}
|
|
1013
1297
|
});
|
|
1014
1298
|
|
|
1299
|
+
test('insert() should handle Date objects for createdAt/updatedAt fields', async () => {
|
|
1300
|
+
// Test that individual insert method properly handles Date objects in date fields
|
|
1301
|
+
const now = new Date();
|
|
1302
|
+
const recordWithDates = {
|
|
1303
|
+
id: `thread-${randomUUID()}`,
|
|
1304
|
+
resourceId: `resource-${randomUUID()}`,
|
|
1305
|
+
title: 'Thread with Date Objects',
|
|
1306
|
+
// These are Date objects, not ISO strings - should be handled by preprocessing
|
|
1307
|
+
createdAt: now,
|
|
1308
|
+
updatedAt: now,
|
|
1309
|
+
metadata: JSON.stringify({ test: 'with-dates' }),
|
|
1310
|
+
};
|
|
1311
|
+
|
|
1312
|
+
// This should not throw a validation error due to Date object type
|
|
1313
|
+
await expect(genericStore.insert({ tableName: TABLE_THREADS, record: recordWithDates })).resolves.not.toThrow();
|
|
1314
|
+
|
|
1315
|
+
// Verify the record was saved correctly
|
|
1316
|
+
const loaded = await genericStore.load<StorageThreadType>({
|
|
1317
|
+
tableName: TABLE_THREADS,
|
|
1318
|
+
keys: { id: recordWithDates.id },
|
|
1319
|
+
});
|
|
1320
|
+
expect(loaded).not.toBeNull();
|
|
1321
|
+
expect(loaded?.id).toBe(recordWithDates.id);
|
|
1322
|
+
expect(loaded?.title).toBe('Thread with Date Objects');
|
|
1323
|
+
});
|
|
1324
|
+
|
|
1015
1325
|
test('load() should return null for non-existent record', async () => {
|
|
1016
1326
|
// Use the genericStore instance
|
|
1017
1327
|
const loaded = await genericStore.load({ tableName: TABLE_THREADS, keys: { id: 'non-existent-generic' } });
|
|
@@ -1053,4 +1363,4 @@ describe('DynamoDBStore Integration Tests', () => {
|
|
|
1053
1363
|
).toBeNull();
|
|
1054
1364
|
});
|
|
1055
1365
|
}); // End Generic Storage Methods describe
|
|
1056
|
-
});
|
|
1366
|
+
});
|