@mastra/dynamodb 0.12.0 → 0.13.0-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.
package/dist/index.cjs CHANGED
@@ -974,7 +974,7 @@ var DynamoDBStore = class extends storage.MastraStorage {
974
974
  metadata: thread.metadata ? JSON.stringify(thread.metadata) : void 0
975
975
  };
976
976
  try {
977
- await this.service.entities.thread.create(threadData).go();
977
+ await this.service.entities.thread.upsert(threadData).go();
978
978
  return {
979
979
  id: thread.id,
980
980
  resourceId: thread.resourceId,
package/dist/index.js CHANGED
@@ -972,7 +972,7 @@ var DynamoDBStore = class extends MastraStorage {
972
972
  metadata: thread.metadata ? JSON.stringify(thread.metadata) : void 0
973
973
  };
974
974
  try {
975
- await this.service.entities.thread.create(threadData).go();
975
+ await this.service.entities.thread.upsert(threadData).go();
976
976
  return {
977
977
  id: thread.id,
978
978
  resourceId: thread.resourceId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/dynamodb",
3
- "version": "0.12.0",
3
+ "version": "0.13.0-alpha.1",
4
4
  "description": "DynamoDB storage adapter for Mastra",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -23,8 +23,8 @@
23
23
  "src"
24
24
  ],
25
25
  "dependencies": {
26
- "@aws-sdk/client-dynamodb": "^3.828.0",
27
- "@aws-sdk/lib-dynamodb": "^3.830.0",
26
+ "@aws-sdk/client-dynamodb": "^3.840.0",
27
+ "@aws-sdk/lib-dynamodb": "^3.840.0",
28
28
  "electrodb": "^3.4.3"
29
29
  },
30
30
  "peerDependencies": {
@@ -39,10 +39,10 @@
39
39
  "eslint": "^9.29.0",
40
40
  "tsup": "^8.5.0",
41
41
  "typescript": "^5.8.3",
42
- "vitest": "^3.2.3",
43
- "@internal/lint": "0.0.14",
44
- "@internal/storage-test-utils": "0.0.10",
45
- "@mastra/core": "0.10.7"
42
+ "vitest": "^3.2.4",
43
+ "@internal/lint": "0.0.17",
44
+ "@internal/storage-test-utils": "0.0.13",
45
+ "@mastra/core": "0.10.11-alpha.2"
46
46
  },
47
47
  "scripts": {
48
48
  "build": "tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting",
@@ -481,6 +481,123 @@ describe('DynamoDBStore Integration Tests', () => {
481
481
  expect(updatedThread).toBeDefined();
482
482
  expect(updatedThread!.updatedAt.getTime()).toBeGreaterThan(originalUpdatedAt.getTime());
483
483
  });
484
+
485
+ test('saveThread upsert: should create new thread when thread does not exist', async () => {
486
+ const threadId = `upsert-new-${randomUUID()}`;
487
+ const now = new Date();
488
+ const thread: StorageThreadType = {
489
+ id: threadId,
490
+ resourceId: 'resource-upsert-new',
491
+ title: 'New Thread via Upsert',
492
+ createdAt: now,
493
+ updatedAt: now,
494
+ metadata: { operation: 'create', test: true },
495
+ };
496
+
497
+ // Save the thread (should create new)
498
+ await expect(store.saveThread({ thread })).resolves.not.toThrow();
499
+
500
+ // Verify the thread was created
501
+ const retrieved = await store.getThreadById({ threadId });
502
+ expect(retrieved).toBeDefined();
503
+ expect(retrieved?.id).toBe(threadId);
504
+ expect(retrieved?.title).toBe('New Thread via Upsert');
505
+ expect(retrieved?.resourceId).toBe('resource-upsert-new');
506
+ expect(retrieved?.metadata).toEqual({ operation: 'create', test: true });
507
+ });
508
+
509
+ test('saveThread upsert: should update existing thread when thread already exists', async () => {
510
+ const threadId = `upsert-update-${randomUUID()}`;
511
+ const initialCreatedAt = new Date();
512
+
513
+ // Create initial thread
514
+ const initialThread: StorageThreadType = {
515
+ id: threadId,
516
+ resourceId: 'resource-upsert-initial',
517
+ title: 'Initial Thread Title',
518
+ createdAt: initialCreatedAt,
519
+ updatedAt: initialCreatedAt,
520
+ metadata: { operation: 'initial', version: 1 },
521
+ };
522
+ await store.saveThread({ thread: initialThread });
523
+
524
+ // Wait a small amount to ensure different timestamp
525
+ await new Promise(resolve => setTimeout(resolve, 100));
526
+
527
+ // Update the thread with same ID but different data
528
+ const updatedThread: StorageThreadType = {
529
+ id: threadId,
530
+ resourceId: 'resource-upsert-updated',
531
+ title: 'Updated Thread Title',
532
+ createdAt: initialCreatedAt, // Keep original creation time
533
+ updatedAt: new Date(), // New update time
534
+ metadata: { operation: 'update', version: 2 },
535
+ };
536
+ await expect(store.saveThread({ thread: updatedThread })).resolves.not.toThrow();
537
+
538
+ // Verify the thread was updated
539
+ const retrieved = await store.getThreadById({ threadId });
540
+ expect(retrieved).toBeDefined();
541
+ expect(retrieved?.id).toBe(threadId);
542
+ expect(retrieved?.title).toBe('Updated Thread Title');
543
+ expect(retrieved?.resourceId).toBe('resource-upsert-updated');
544
+ expect(retrieved?.metadata).toEqual({ operation: 'update', version: 2 });
545
+
546
+ // updatedAt should be newer than the initial creation time
547
+ expect(retrieved?.updatedAt.getTime()).toBeGreaterThan(initialCreatedAt.getTime());
548
+ // createdAt should remain exactly equal to the initial creation time
549
+ expect(retrieved?.createdAt.getTime()).toBe(initialCreatedAt.getTime());
550
+ });
551
+
552
+ test('saveThread upsert: should handle complex metadata updates', async () => {
553
+ const threadId = `upsert-metadata-${randomUUID()}`;
554
+ const initialMetadata = {
555
+ user: 'initial-user',
556
+ tags: ['initial', 'test'],
557
+ count: 1,
558
+ };
559
+
560
+ // Create initial thread with complex metadata
561
+ const initialThread: StorageThreadType = {
562
+ id: threadId,
563
+ resourceId: 'resource-metadata-test',
564
+ title: 'Metadata Test Thread',
565
+ createdAt: new Date(),
566
+ updatedAt: new Date(),
567
+ metadata: initialMetadata,
568
+ };
569
+ await store.saveThread({ thread: initialThread });
570
+
571
+ // Wait a small amount to ensure different timestamp
572
+ await new Promise(resolve => setTimeout(resolve, 100));
573
+
574
+ // Update with completely different metadata structure
575
+ const updatedMetadata = {
576
+ user: 'updated-user',
577
+ settings: { theme: 'light', language: 'ja', notifications: true },
578
+ tags: ['updated', 'upsert', 'complex'],
579
+ count: 5,
580
+ newField: { nested: { deeply: 'value' } },
581
+ };
582
+
583
+ const updatedThread: StorageThreadType = {
584
+ id: threadId,
585
+ resourceId: 'resource-metadata-test',
586
+ title: 'Updated Metadata Thread',
587
+ createdAt: initialThread.createdAt,
588
+ updatedAt: new Date(),
589
+ metadata: updatedMetadata,
590
+ };
591
+ await expect(store.saveThread({ thread: updatedThread })).resolves.not.toThrow();
592
+
593
+ // Verify the metadata was completely replaced
594
+ const retrieved = await store.getThreadById({ threadId });
595
+ expect(retrieved).toBeDefined();
596
+ expect(retrieved?.metadata).toEqual(updatedMetadata);
597
+ expect(retrieved?.metadata?.user).toBe('updated-user');
598
+ expect(retrieved?.metadata?.tags).toEqual(['updated', 'upsert', 'complex']);
599
+ expect(retrieved?.title).toBe('Updated Metadata Thread');
600
+ });
484
601
  });
485
602
 
486
603
  describe('Batch Operations', () => {
@@ -1363,4 +1480,4 @@ describe('DynamoDBStore Integration Tests', () => {
1363
1480
  ).toBeNull();
1364
1481
  });
1365
1482
  }); // End Generic Storage Methods describe
1366
- }); // End Main Describe
1483
+ });
@@ -598,7 +598,7 @@ export class DynamoDBStore extends MastraStorage {
598
598
  };
599
599
 
600
600
  try {
601
- await this.service.entities.thread.create(threadData).go();
601
+ await this.service.entities.thread.upsert(threadData).go();
602
602
 
603
603
  return {
604
604
  id: thread.id,