From 4538b1d93f815d5c2a022e7f8b3672b574d970ce Mon Sep 17 00:00:00 2001 From: Ry Racherbaumer Date: Fri, 19 Jul 2024 15:11:35 -0500 Subject: [PATCH 1/5] Upgrade dexie --- packages/react-sdk/package.json | 2 +- yarn.lock | 21 +++++---------------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/packages/react-sdk/package.json b/packages/react-sdk/package.json index 67d99bc9..9286ac93 100644 --- a/packages/react-sdk/package.json +++ b/packages/react-sdk/package.json @@ -74,7 +74,7 @@ "@xmtp/content-type-text": "^1.0.0", "async-mutex": "^0.5.0", "date-fns": "^3.6.0", - "dexie": "^3.2.6", + "dexie": "^4.0.8", "dexie-react-hooks": "^1.1.7", "uuid": "^10.0.0", "zod": "^3.23.8" diff --git a/yarn.lock b/yarn.lock index b4e9d21f..0649327c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5965,7 +5965,7 @@ __metadata: "@xmtp/xmtp-js": "npm:^12.0.0" async-mutex: "npm:^0.5.0" date-fns: "npm:^3.6.0" - dexie: "npm:^3.2.6" + dexie: "npm:^4.0.8" dexie-react-hooks: "npm:^1.1.7" eslint: "npm:^8.57.0" eslint-config-xmtp-web: "workspace:*" @@ -8117,12 +8117,10 @@ __metadata: languageName: node linkType: hard -"dexie@npm:^3.2.6": - version: 3.2.6 - resolution: "dexie@npm:3.2.6" - dependencies: - karma-safari-launcher: "npm:^1.0.0" - checksum: 10/ab80f3b612c7c60ff8b60b2c0da7bd77aeec538f6be965c00523adc4cf17863a9513d71ff2a5dba7671985a7e10ff46ff9d53f300e058423da07da5aefbff49c +"dexie@npm:^4.0.8": + version: 4.0.8 + resolution: "dexie@npm:4.0.8" + checksum: 10/1aa04bdba2f9d7ee0cd7b2bf2df8e7c25a486f58ece7cefc850a5cacf66e7a1a86a3f2f5a0e42ef980051a0c87d061131afe62bcfaeca8aa42305422e5af4e16 languageName: node linkType: hard @@ -11986,15 +11984,6 @@ __metadata: languageName: node linkType: hard -"karma-safari-launcher@npm:^1.0.0": - version: 1.0.0 - resolution: "karma-safari-launcher@npm:1.0.0" - peerDependencies: - karma: ">=0.9" - checksum: 10/09de8a231035c147c22c4106137594e5285e21e5d9f56d12a25563975b410363997947a7e8b5fdbfa0b8ba6f4f120b08a8f2777a28212c410d99b2e30c2eecb8 - languageName: node - linkType: hard - "keccak@npm:^3.0.3": version: 3.0.4 resolution: "keccak@npm:3.0.4" From 003d141970c44a6ab94bd5067cba81be90944cb7 Mon Sep 17 00:00:00 2001 From: Ry Racherbaumer Date: Fri, 19 Jul 2024 15:16:21 -0500 Subject: [PATCH 2/5] Remove dexie DB versioning --- apps/react/src/controllers/AppController.tsx | 6 +----- packages/react-sdk/src/contexts/XMTPContext.test.tsx | 5 ++--- packages/react-sdk/src/contexts/XMTPContext.tsx | 11 +---------- packages/react-sdk/src/helpers/caching/db.ts | 5 +---- 4 files changed, 5 insertions(+), 22 deletions(-) diff --git a/apps/react/src/controllers/AppController.tsx b/apps/react/src/controllers/AppController.tsx index 803b039e..a8eed881 100644 --- a/apps/react/src/controllers/AppController.tsx +++ b/apps/react/src/controllers/AppController.tsx @@ -7,8 +7,6 @@ import { import { WalletProvider } from "../contexts/WalletContext"; import { App } from "../components/App"; -const DB_VERSION = 1; - const contentTypeConfigs = [ attachmentContentTypeConfig, reactionContentTypeConfig, @@ -17,9 +15,7 @@ const contentTypeConfigs = [ export const AppController: React.FC = () => ( - + diff --git a/packages/react-sdk/src/contexts/XMTPContext.test.tsx b/packages/react-sdk/src/contexts/XMTPContext.test.tsx index 7113ac79..92bab4d0 100644 --- a/packages/react-sdk/src/contexts/XMTPContext.test.tsx +++ b/packages/react-sdk/src/contexts/XMTPContext.test.tsx @@ -5,14 +5,13 @@ import type { XMTPProviderProps } from "@/contexts/XMTPContext"; import { XMTPProvider } from "@/contexts/XMTPContext"; type TestWrapperProps = PropsWithChildren & - Pick; + Pick; const TestWrapper: React.FC = ({ contentTypeConfigs, children, - dbVersion, }) => ( - + {children} ); diff --git a/packages/react-sdk/src/contexts/XMTPContext.tsx b/packages/react-sdk/src/contexts/XMTPContext.tsx index 7e6ae339..e932aa7b 100644 --- a/packages/react-sdk/src/contexts/XMTPContext.tsx +++ b/packages/react-sdk/src/contexts/XMTPContext.tsx @@ -65,20 +65,12 @@ export type XMTPProviderProps = React.PropsWithChildren & { * processing of messages */ contentTypeConfigs?: ContentTypeConfiguration[]; - /** - * Database version to use for the local cache - * - * This number should be incremented when adding support for additional - * content types - */ - dbVersion?: number; }; export const XMTPProvider: React.FC = ({ children, client: initialClient, contentTypeConfigs, - dbVersion, }) => { const [client, setClient] = useState(initialClient); @@ -112,9 +104,8 @@ export const XMTPProvider: React.FC = ({ getDbInstance({ db: initialDb, contentTypeConfigs, - version: dbVersion, }), - [dbVersion, contentTypeConfigs], + [contentTypeConfigs], ); // memo-ize the context value to prevent unnecessary re-renders diff --git a/packages/react-sdk/src/helpers/caching/db.ts b/packages/react-sdk/src/helpers/caching/db.ts index 4dd86c23..7a7a87ed 100644 --- a/packages/react-sdk/src/helpers/caching/db.ts +++ b/packages/react-sdk/src/helpers/caching/db.ts @@ -60,7 +60,6 @@ export type ContentTypeMessageProcessors = { export type GetDBInstanceOptions = { db?: Dexie; contentTypeConfigs?: ContentTypeConfiguration[]; - version?: number; }; /** @@ -80,9 +79,7 @@ export const getDbInstance = (options?: GetDBInstanceOptions) => { {} as Record, ); - const version = options?.version ?? 1; - - db.version(version).stores({ + db.version(1).stores({ ...customSchema, conversations: ` ++id, From b5dd0a8e7da0296610ef2996008dff27e35d3e41 Mon Sep 17 00:00:00 2001 From: Ry Racherbaumer Date: Fri, 19 Jul 2024 15:38:14 -0500 Subject: [PATCH 3/5] Create forty-radios-scream.md --- .changeset/forty-radios-scream.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/forty-radios-scream.md diff --git a/.changeset/forty-radios-scream.md b/.changeset/forty-radios-scream.md new file mode 100644 index 00000000..64c4416a --- /dev/null +++ b/.changeset/forty-radios-scream.md @@ -0,0 +1,5 @@ +--- +"@xmtp/react-sdk": major +--- + +Upgrade dexie, remove DB versioning From ff793e2f383f7e2970d13da490c5d9938f4fa562 Mon Sep 17 00:00:00 2001 From: Ry Racherbaumer Date: Mon, 22 Jul 2024 10:46:11 -0500 Subject: [PATCH 4/5] Refactor cached conversation types --- .../caching/contentTypes/reaction.test.ts | 6 +-- .../caching/contentTypes/reply.test.ts | 6 +-- .../src/helpers/caching/conversations.test.ts | 19 ++++---- .../src/helpers/caching/conversations.ts | 44 +++++++++---------- .../src/helpers/caching/messages.test.ts | 19 ++++---- .../react-sdk/src/hooks/useConversation.ts | 3 +- .../react-sdk/src/hooks/useMessage.test.tsx | 16 +++---- packages/react-sdk/src/index.ts | 1 - 8 files changed, 56 insertions(+), 58 deletions(-) diff --git a/packages/react-sdk/src/helpers/caching/contentTypes/reaction.test.ts b/packages/react-sdk/src/helpers/caching/contentTypes/reaction.test.ts index d33cd82a..88cf5180 100644 --- a/packages/react-sdk/src/helpers/caching/contentTypes/reaction.test.ts +++ b/packages/react-sdk/src/helpers/caching/contentTypes/reaction.test.ts @@ -20,7 +20,7 @@ import { getMessageByXmtpID, } from "@/helpers/caching/messages"; import { getDbInstance, clearCache } from "@/helpers/caching/db"; -import type { CachedConversationWithId } from "@/helpers/caching/conversations"; +import type { CachedConversation } from "@/helpers/caching/conversations"; import { createRandomWallet } from "@/helpers/testing"; const testWallet = createRandomWallet(); @@ -91,7 +91,7 @@ describe("ContentTypeReaction", () => { topic: "testTopic", peerAddress: "testPeerAddress", walletAddress: testWallet.account.address, - } satisfies CachedConversationWithId; + } satisfies CachedConversation; const testTextMessage = { id: 1, walletAddress: testWallet.account.address, @@ -201,7 +201,7 @@ describe("ContentTypeReaction", () => { topic: "testTopic", peerAddress: "testPeerAddress", walletAddress: testWallet.account.address, - } satisfies CachedConversationWithId; + } satisfies CachedConversation; const testMessage = { id: 1, walletAddress: testWallet.account.address, diff --git a/packages/react-sdk/src/helpers/caching/contentTypes/reply.test.ts b/packages/react-sdk/src/helpers/caching/contentTypes/reply.test.ts index b6dadcf8..a76acb1a 100644 --- a/packages/react-sdk/src/helpers/caching/contentTypes/reply.test.ts +++ b/packages/react-sdk/src/helpers/caching/contentTypes/reply.test.ts @@ -17,7 +17,7 @@ import { getMessageByXmtpID, } from "@/helpers/caching/messages"; import { getDbInstance, clearCache } from "@/helpers/caching/db"; -import type { CachedConversationWithId } from "@/helpers/caching/conversations"; +import type { CachedConversation } from "@/helpers/caching/conversations"; import { createRandomWallet } from "@/helpers/testing"; const testWallet = createRandomWallet(); @@ -53,7 +53,7 @@ describe("ContentTypeReply", () => { topic: "testTopic", peerAddress: "testPeerAddress", walletAddress: testWallet.account.address, - } satisfies CachedConversationWithId; + } satisfies CachedConversation; const testTextMessage = { id: 1, walletAddress: testWallet.account.address, @@ -130,7 +130,7 @@ describe("ContentTypeReply", () => { topic: "testTopic", peerAddress: "testPeerAddress", walletAddress: testWallet.account.address, - } satisfies CachedConversationWithId; + } satisfies CachedConversation; const testMessage = { id: 1, walletAddress: testWallet.account.address, diff --git a/packages/react-sdk/src/helpers/caching/conversations.test.ts b/packages/react-sdk/src/helpers/caching/conversations.test.ts index 4d17c81c..8edc74d5 100644 --- a/packages/react-sdk/src/helpers/caching/conversations.test.ts +++ b/packages/react-sdk/src/helpers/caching/conversations.test.ts @@ -13,10 +13,7 @@ import { updateConversation, updateConversationMetadata, } from "@/helpers/caching/conversations"; -import type { - CachedConversation, - CachedConversationWithId, -} from "@/helpers/caching/conversations"; +import type { CachedConversation } from "@/helpers/caching/conversations"; import { adjustDate } from "@/helpers/adjustDate"; import { createRandomWallet } from "@/helpers/testing"; @@ -75,7 +72,7 @@ describe("getCachedConversationBy", () => { topic: "testTopic", peerAddress: "testPeerAddress", walletAddress: "testWalletAddress", - } satisfies CachedConversationWithId; + } satisfies CachedConversation; const cachedConversation = await saveConversation(testConversation, db); const conversation = await getCachedConversationBy( "testWalletAddress", @@ -146,7 +143,7 @@ describe("updateConversation", () => { topic: "testTopic", peerAddress: "testPeerAddress", walletAddress: "testWalletAddress", - } satisfies CachedConversationWithId; + } satisfies CachedConversation; const cachedConversation = await saveConversation(testConversation, db); expect(cachedConversation).toEqual(testConversation); @@ -185,7 +182,7 @@ describe("updateConversationMetadata", () => { topic: "testTopic", peerAddress: "testPeerAddress", walletAddress: "testWalletAddress", - } satisfies CachedConversationWithId; + } satisfies CachedConversation; const cachedConversation = await saveConversation(testConversation, db); expect(cachedConversation).toEqual(testConversation); @@ -218,7 +215,7 @@ describe("setConversationUpdatedAt", () => { topic: "testTopic", peerAddress: "testPeerAddress", walletAddress: "testWalletAddress", - } satisfies CachedConversationWithId; + } satisfies CachedConversation; const cachedConversation = await saveConversation(testConversation, db); expect(cachedConversation.updatedAt).toEqual(createdAt); @@ -246,7 +243,7 @@ describe("hasConversationTopic", () => { topic: "testTopic", peerAddress: "testPeerAddress", walletAddress: "testWalletAddress", - } satisfies CachedConversationWithId; + } satisfies CachedConversation; const cachedConversation = await saveConversation(testConversation, db); expect(cachedConversation).toEqual(testConversation); @@ -273,7 +270,7 @@ describe("saveConversation", () => { topic: "testTopic", peerAddress: "testPeerAddress", walletAddress: "testWalletAddress", - } satisfies CachedConversationWithId; + } satisfies CachedConversation; const cachedConversation = await saveConversation(testConversation, db); expect(cachedConversation).toEqual(testConversation); }); @@ -281,6 +278,7 @@ describe("saveConversation", () => { it("should return a duplicate conversation", async () => { const createdAt = new Date(); const testConversation = { + id: 1, createdAt, updatedAt: createdAt, isReady: false, @@ -292,7 +290,6 @@ describe("saveConversation", () => { expect(cachedConversation).toEqual(testConversation); const cachedConversation2 = await saveConversation(testConversation, db); expect(cachedConversation2).toEqual(testConversation); - expect(cachedConversation2.id).toBe(cachedConversation.id); }); }); diff --git a/packages/react-sdk/src/helpers/caching/conversations.ts b/packages/react-sdk/src/helpers/caching/conversations.ts index fb5bcd89..316ee35a 100644 --- a/packages/react-sdk/src/helpers/caching/conversations.ts +++ b/packages/react-sdk/src/helpers/caching/conversations.ts @@ -7,7 +7,7 @@ import type { ContentTypeMetadata, ContentTypeMetadataValues } from "./db"; export type CachedConversation = { context?: InvitationContext; createdAt: Date; - id?: number; + id: number; isReady: boolean; lastSyncedAt?: Date; metadata?: M; @@ -27,13 +27,13 @@ type ToFunctionArgs = { type GetCachedConversationBy = ( ...args: [string, ...ToFunctionArgs, Dexie] -) => Promise; - -export type CachedConversationsTable = Table; +) => Promise; -export type CachedConversationWithId = CachedConversation & { - id: number; -}; +export type CachedConversationsTable = Table< + CachedConversation, + number, + Omit +>; /** * Retrieve a cached conversation by a given key and value @@ -55,7 +55,7 @@ export const getCachedConversationBy: GetCachedConversationBy = async ( [key]: value, }) .first(); - return conversation ? (conversation as CachedConversationWithId) : undefined; + return conversation; }; /** @@ -177,15 +177,16 @@ export const hasConversationTopic = async ( export const toCachedConversation = ( conversation: Conversation, walletAddress: string, -) => ({ - context: conversation.context, - createdAt: conversation.createdAt, - isReady: false, - peerAddress: conversation.peerAddress, - topic: conversation.topic, - updatedAt: conversation.createdAt, - walletAddress, -}); +) => + ({ + context: conversation.context, + createdAt: conversation.createdAt, + isReady: false, + peerAddress: conversation.peerAddress, + topic: conversation.topic, + updatedAt: conversation.createdAt, + walletAddress, + }) satisfies Omit; const saveConversationMutex = new Mutex(); @@ -195,7 +196,7 @@ const saveConversationMutex = new Mutex(); * @returns The saved cached conversation with ID */ export const saveConversation = async ( - conversation: CachedConversation, + conversation: Omit, db: Dexie, ) => // ensure that only 1 conversation is saved at a time to prevent duplicates @@ -210,11 +211,10 @@ export const saveConversation = async ( .first(); if (existing) { - return existing as CachedConversationWithId; + return existing; } - // eslint-disable-next-line no-param-reassign - conversation.id = await conversations.add(conversation); + const id = await conversations.add(conversation); - return conversation as CachedConversationWithId; + return { ...conversation, id }; }); diff --git a/packages/react-sdk/src/helpers/caching/messages.test.ts b/packages/react-sdk/src/helpers/caching/messages.test.ts index d0d5baa4..dcf1b962 100644 --- a/packages/react-sdk/src/helpers/caching/messages.test.ts +++ b/packages/react-sdk/src/helpers/caching/messages.test.ts @@ -311,10 +311,10 @@ describe("prepareMessageForSending", () => { client, content: "test", contentType: ContentTypeText.toString(), - conversation: toCachedConversation( - conversation, - testWallet1.account.address, - ), + conversation: { + ...toCachedConversation(conversation, testWallet1.account.address), + id: 1, + }, }); expect(message.content).toBe("test"); @@ -338,10 +338,10 @@ describe("prepareMessageForSending", () => { const { message, preparedMessage } = await prepareMessageForSending({ client, content: "test", - conversation: toCachedConversation( - conversation, - testWallet1.account.address, - ), + conversation: { + ...toCachedConversation(conversation, testWallet1.account.address), + id: 1, + }, }); expect(message.content).toBe("test"); @@ -936,6 +936,7 @@ describe("reprocessMessage", () => { const testClient = await Client.create(testWallet1, { env: "local" }); const createdAt = new Date(); const testConversation = { + id: 1, createdAt, updatedAt: createdAt, isReady: false, @@ -998,6 +999,7 @@ describe("reprocessMessage", () => { const testClient = await Client.create(testWallet1, { env: "local" }); const createdAt = new Date(); const testConversation = { + id: 1, createdAt, updatedAt: createdAt, isReady: false, @@ -1048,6 +1050,7 @@ describe("processUnprocessedMessages", () => { const createdAt = new Date(); const sentAt = adjustDate(createdAt, 1000); const testConversation = { + id: 1, createdAt, updatedAt: createdAt, isReady: false, diff --git a/packages/react-sdk/src/hooks/useConversation.ts b/packages/react-sdk/src/hooks/useConversation.ts index 6f4a5f67..877a1002 100644 --- a/packages/react-sdk/src/hooks/useConversation.ts +++ b/packages/react-sdk/src/hooks/useConversation.ts @@ -1,6 +1,5 @@ import { useCallback } from "react"; import { getLastMessage as _getLastMessage } from "@/helpers/caching/messages"; -import type { CachedConversation } from "@/helpers/caching/conversations"; import { getCachedConversationByTopic, getConversationByTopic, @@ -19,7 +18,7 @@ export const useConversationInternal = () => { const { db } = useDb(); const saveConversation = useCallback( - (conversation: CachedConversation) => + (conversation: Parameters[0]) => client ? _saveConversation(conversation, db) : undefined, [client, db], ); diff --git a/packages/react-sdk/src/hooks/useMessage.test.tsx b/packages/react-sdk/src/hooks/useMessage.test.tsx index b2df679d..4ebc627f 100644 --- a/packages/react-sdk/src/hooks/useMessage.test.tsx +++ b/packages/react-sdk/src/hooks/useMessage.test.tsx @@ -109,10 +109,10 @@ describe("useMessage", () => { testWallet2.account.address, undefined, ); - const testConversation = toCachedConversation( - conversation, - testWallet1.account.address, - ); + const testConversation = { + ...toCachedConversation(conversation, testWallet1.account.address), + id: 1, + }; const testError = new Error("testError"); const sendMock = vi.fn().mockRejectedValueOnce(testError); const onErrorMock = vi.fn(); @@ -175,10 +175,10 @@ describe("useMessage", () => { testWallet2.account.address, undefined, ); - const testConversation = toCachedConversation( - conversation, - testWallet1.account.address, - ); + const testConversation = { + ...toCachedConversation(conversation, testWallet1.account.address), + id: 1, + }; const sentAt = new Date(); const sendMock = vi.fn().mockImplementation(() => ({ id: 1, diff --git a/packages/react-sdk/src/index.ts b/packages/react-sdk/src/index.ts index 593f28a6..f19b52a8 100644 --- a/packages/react-sdk/src/index.ts +++ b/packages/react-sdk/src/index.ts @@ -16,7 +16,6 @@ export { useStreamConversations } from "./hooks/useStreamConversations"; export type { CachedConversation, - CachedConversationWithId, CachedConversationsTable, } from "./helpers/caching/conversations"; export { From 85802e844573bb90d8730d88a1efe7fce1eda6a7 Mon Sep 17 00:00:00 2001 From: Ry Racherbaumer Date: Mon, 22 Jul 2024 12:23:42 -0500 Subject: [PATCH 5/5] Refactor cached messages types --- .../caching/contentTypes/attachment.test.ts | 12 +++--- .../caching/contentTypes/reaction.test.ts | 10 ++--- .../caching/contentTypes/reply.test.ts | 20 ++++----- .../src/helpers/caching/contentTypes/reply.ts | 3 +- packages/react-sdk/src/helpers/caching/db.ts | 7 +++- .../src/helpers/caching/messages.test.ts | 1 + .../react-sdk/src/helpers/caching/messages.ts | 41 +++++++++++-------- packages/react-sdk/src/hooks/useMessage.ts | 16 +++++--- packages/react-sdk/src/hooks/useMessages.ts | 5 +-- .../src/hooks/useResendMessage.test.ts | 6 +-- .../react-sdk/src/hooks/useResendMessage.ts | 6 +-- .../src/hooks/useStartConversation.test.ts | 4 +- packages/react-sdk/src/index.ts | 1 - 13 files changed, 72 insertions(+), 60 deletions(-) diff --git a/packages/react-sdk/src/helpers/caching/contentTypes/attachment.test.ts b/packages/react-sdk/src/helpers/caching/contentTypes/attachment.test.ts index 932727da..e90bd91c 100644 --- a/packages/react-sdk/src/helpers/caching/contentTypes/attachment.test.ts +++ b/packages/react-sdk/src/helpers/caching/contentTypes/attachment.test.ts @@ -15,7 +15,7 @@ import { hasAttachment, attachmentContentTypeConfig, } from "./attachment"; -import { type CachedMessageWithId } from "@/helpers/caching/messages"; +import { type CachedMessage } from "@/helpers/caching/messages"; import { createRandomWallet } from "@/helpers/testing"; const testWallet = createRandomWallet(); @@ -53,7 +53,7 @@ describe("ContentTypeRemoteAttachment caching", () => { senderAddress: "testWalletAddress", uuid: "testUuid", xmtpID: "testXmtpId", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; const attachment = getAttachment(testMessage); expect(attachment).toEqual(testContent); @@ -82,7 +82,7 @@ describe("ContentTypeRemoteAttachment caching", () => { senderAddress: "testWalletAddress", uuid: "testUuid", xmtpID: "testXmtpId", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; const attachment2 = getAttachment(testMessage2); expect(attachment2).toEqual(testContent2); @@ -101,7 +101,7 @@ describe("ContentTypeRemoteAttachment caching", () => { senderAddress: "testWalletAddress", uuid: "testUuid", xmtpID: "testXmtpId", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; const attachment3 = getAttachment(testMessage3); expect(attachment3).toBeUndefined(); @@ -129,7 +129,7 @@ describe("ContentTypeRemoteAttachment caching", () => { senderAddress: "testWalletAddress", uuid: "testUuid", xmtpID: "testXmtpId", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; const attachment = hasAttachment(testMessage); expect(attachment).toBe(true); @@ -148,7 +148,7 @@ describe("ContentTypeRemoteAttachment caching", () => { senderAddress: "testWalletAddress", uuid: "testUuid", xmtpID: "testXmtpId", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; const attachment2 = hasAttachment(testMessage2); expect(attachment2).toBe(false); diff --git a/packages/react-sdk/src/helpers/caching/contentTypes/reaction.test.ts b/packages/react-sdk/src/helpers/caching/contentTypes/reaction.test.ts index 88cf5180..a7288407 100644 --- a/packages/react-sdk/src/helpers/caching/contentTypes/reaction.test.ts +++ b/packages/react-sdk/src/helpers/caching/contentTypes/reaction.test.ts @@ -16,7 +16,7 @@ import { } from "./reaction"; import { saveMessage, - type CachedMessageWithId, + type CachedMessage, getMessageByXmtpID, } from "@/helpers/caching/messages"; import { getDbInstance, clearCache } from "@/helpers/caching/db"; @@ -106,7 +106,7 @@ describe("ContentTypeReaction", () => { senderAddress: "testWalletAddress", uuid: "testUuid1", xmtpID: "testXmtpId1", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; await saveMessage(testTextMessage, db); @@ -131,7 +131,7 @@ describe("ContentTypeReaction", () => { senderAddress: "testWalletAddress", uuid: "testUuid2", xmtpID: "testXmtpId2", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; const updateConversationMetadata = vi.fn(); await processReaction({ @@ -173,7 +173,7 @@ describe("ContentTypeReaction", () => { senderAddress: "testWalletAddress", uuid: "testUuid3", xmtpID: "testXmtpId3", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; await processReaction({ client: testClient, @@ -216,7 +216,7 @@ describe("ContentTypeReaction", () => { senderAddress: "testWalletAddress", uuid: "testUuid", xmtpID: "testXmtpId", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; const updateConversationMetadata = vi.fn(); await processReaction({ diff --git a/packages/react-sdk/src/helpers/caching/contentTypes/reply.test.ts b/packages/react-sdk/src/helpers/caching/contentTypes/reply.test.ts index a76acb1a..29ea7464 100644 --- a/packages/react-sdk/src/helpers/caching/contentTypes/reply.test.ts +++ b/packages/react-sdk/src/helpers/caching/contentTypes/reply.test.ts @@ -13,7 +13,7 @@ import { } from "./reply"; import { saveMessage, - type CachedMessageWithId, + type CachedMessage, getMessageByXmtpID, } from "@/helpers/caching/messages"; import { getDbInstance, clearCache } from "@/helpers/caching/db"; @@ -68,7 +68,7 @@ describe("ContentTypeReply", () => { senderAddress: "testWalletAddress", uuid: "testUuid1", xmtpID: "testXmtpId1", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; await saveMessage(testTextMessage, db); @@ -92,7 +92,7 @@ describe("ContentTypeReply", () => { senderAddress: "testWalletAddress", uuid: "testUuid2", xmtpID: "testXmtpId2", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; await saveMessage(testReplyMessage, db); @@ -145,7 +145,7 @@ describe("ContentTypeReply", () => { senderAddress: "testWalletAddress", uuid: "testUuid", xmtpID: "testXmtpId", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; const updateConversationMetadata = vi.fn(); await processReply({ @@ -175,7 +175,7 @@ describe("ContentTypeReply", () => { senderAddress: "testWalletAddress", uuid: "testUuid1", xmtpID: "testXmtpId1", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; const originalMessageFromReply = await getOriginalMessageFromReply( testTextMessage, @@ -201,7 +201,7 @@ describe("ContentTypeReply", () => { senderAddress: "testWalletAddress", uuid: "testUuid2", xmtpID: "testXmtpId2", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; const originalMessageFromReply2 = await getOriginalMessageFromReply( testReplyMessage, @@ -227,7 +227,7 @@ describe("ContentTypeReply", () => { senderAddress: "testWalletAddress", uuid: "testUuid1", xmtpID: "testXmtpId1", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; const replies = await getReplies(testTextMessage, db); expect(replies).toEqual([]); @@ -250,7 +250,7 @@ describe("ContentTypeReply", () => { senderAddress: "testWalletAddress", uuid: "testUuid1", xmtpID: "testXmtpId1", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; const testReplyMessage1 = { id: 2, @@ -270,7 +270,7 @@ describe("ContentTypeReply", () => { senderAddress: "testWalletAddress", uuid: "testUuid2", xmtpID: "testXmtpId2", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; await saveMessage(testReplyMessage1, db); @@ -292,7 +292,7 @@ describe("ContentTypeReply", () => { senderAddress: "testWalletAddress", uuid: "testUuid3", xmtpID: "testXmtpId3", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; await saveMessage(testReplyMessage2, db); diff --git a/packages/react-sdk/src/helpers/caching/contentTypes/reply.ts b/packages/react-sdk/src/helpers/caching/contentTypes/reply.ts index d3247c4a..e5398b05 100644 --- a/packages/react-sdk/src/helpers/caching/contentTypes/reply.ts +++ b/packages/react-sdk/src/helpers/caching/contentTypes/reply.ts @@ -5,7 +5,6 @@ import { z } from "zod"; import { ContentTypeId } from "@xmtp/content-type-primitives"; import type { CachedMessage, - CachedMessageWithId, CachedMessagesTable, } from "@/helpers/caching/messages"; import type { @@ -75,7 +74,7 @@ export const getReplies = async (message: CachedMessage, db: Dexie) => { .where("xmtpID") .anyOf(replies.map((reply) => reply.xmtpID)) .sortBy("sentAt"); - return replyMessages as CachedMessageWithId[]; + return replyMessages; } return []; }; diff --git a/packages/react-sdk/src/helpers/caching/db.ts b/packages/react-sdk/src/helpers/caching/db.ts index 7a7a87ed..bc132df2 100644 --- a/packages/react-sdk/src/helpers/caching/db.ts +++ b/packages/react-sdk/src/helpers/caching/db.ts @@ -1,7 +1,10 @@ import Dexie from "dexie"; import type { Client } from "@xmtp/xmtp-js"; import type { ContentCodec } from "@xmtp/content-type-primitives"; -import type { CachedMessage } from "@/helpers/caching/messages"; +import type { + CachedMessage, + CachedMessageWithOptionalId, +} from "@/helpers/caching/messages"; import type { CachedConversation } from "./conversations"; import { textContentTypeConfig } from "./contentTypes/text"; @@ -32,7 +35,7 @@ export type ContentTypeMessageProcessor = (options: { client: Client; conversation: CachedConversation; db: Dexie; - message: CachedMessage; + message: CachedMessageWithOptionalId; processors?: ContentTypeMessageProcessors; updateConversationMetadata: ( data: ContentTypeMetadataValues, diff --git a/packages/react-sdk/src/helpers/caching/messages.test.ts b/packages/react-sdk/src/helpers/caching/messages.test.ts index dcf1b962..1915e560 100644 --- a/packages/react-sdk/src/helpers/caching/messages.test.ts +++ b/packages/react-sdk/src/helpers/caching/messages.test.ts @@ -126,6 +126,7 @@ describe("saveMessage", () => { it("should return a duplicate message", async () => { const testMessage = { + id: 1, walletAddress: "testWalletAddress", conversationTopic: "testTopic", content: "test", diff --git a/packages/react-sdk/src/helpers/caching/messages.ts b/packages/react-sdk/src/helpers/caching/messages.ts index c01d9555..faff88bf 100644 --- a/packages/react-sdk/src/helpers/caching/messages.ts +++ b/packages/react-sdk/src/helpers/caching/messages.ts @@ -32,7 +32,7 @@ export type CachedMessage = { conversationTopic: string; hasLoadError: boolean; hasSendError: boolean; - id?: number; + id: number; isSending: boolean; metadata?: M; senderAddress: string; @@ -44,12 +44,19 @@ export type CachedMessage = { xmtpID: string; }; -export type CachedMessagesTable = Table; - -export type CachedMessageWithId = CachedMessage & { - id: number; +export type CachedMessageWithOptionalId = Omit< + CachedMessage, + "id" +> & { + id?: CachedMessage["id"]; }; +export type CachedMessagesTable = Table< + CachedMessage, + number, + Omit, "id"> +>; + /** * Converts a DecodedMessage from the XMTP network to its cached format * @@ -83,7 +90,7 @@ export const toCachedMessage = ( uuid: v4(), walletAddress, xmtpID: message.id, - } satisfies CachedMessage; + } satisfies Omit; }; /** @@ -96,7 +103,7 @@ export const toCachedMessage = ( export const getMessageByXmtpID = async (xmtpID: string, db: Dexie) => { const messages = db.table("messages") as CachedMessagesTable; const message = await messages.where("xmtpID").equals(xmtpID).first(); - return message ? (message as CachedMessageWithId) : undefined; + return message; }; export type SaveMessageOptions = Omit< @@ -109,7 +116,10 @@ export type SaveMessageOptions = Omit< * * @returns The newly cached message, or an already existing cached message */ -export const saveMessage = async (message: CachedMessage, db: Dexie) => { +export const saveMessage = async ( + message: Omit, + db: Dexie, +) => { const messages = db.table("messages") as CachedMessagesTable; // check if message already exists @@ -117,7 +127,7 @@ export const saveMessage = async (message: CachedMessage, db: Dexie) => { if (existing) { // return the existing message - return existing as CachedMessageWithId; + return existing; } const id = await messages.add(message); @@ -131,10 +141,7 @@ export const saveMessage = async (message: CachedMessage, db: Dexie) => { /** * Remove a message from the cache */ -export const deleteMessage = async ( - message: CachedMessageWithId, - db: Dexie, -) => { +export const deleteMessage = async (message: CachedMessage, db: Dexie) => { const messagesTable = db.table("messages") as CachedMessagesTable; // make sure message exists @@ -208,7 +215,7 @@ export const prepareMessageForSending = async ({ conversation, sendOptions, }: PrepareMessageOptions): Promise<{ - message: CachedMessage; + message: Omit; preparedMessage: Awaited>; }> => { const networkConversation = await getConversationByTopic( @@ -244,7 +251,7 @@ export const prepareMessageForSending = async ({ uuid: v4(), walletAddress: client.address, xmtpID: await preparedMessage.messageID(), - } satisfies CachedMessage; + } satisfies Omit; return { message, @@ -275,7 +282,7 @@ export type ProcessMessageOptions = { client?: Client; conversation: CachedConversation; db: Dexie; - message: CachedMessage; + message: CachedMessageWithOptionalId; namespaces: Record; processors: ContentTypeMessageProcessors; validators: ContentTypeMessageValidators; @@ -322,7 +329,7 @@ export const processMessage = async ( removeExisting = false, ): Promise<{ status: ProcessStatus; - message: CachedMessage; + message: CachedMessageWithOptionalId; }> => { // client is required if (!client) { diff --git a/packages/react-sdk/src/hooks/useMessage.ts b/packages/react-sdk/src/hooks/useMessage.ts index abe16f4d..94d0e4b8 100644 --- a/packages/react-sdk/src/hooks/useMessage.ts +++ b/packages/react-sdk/src/hooks/useMessage.ts @@ -13,7 +13,7 @@ import { } from "@/helpers/caching/messages"; import type { CachedMessage, - CachedMessageWithId, + ProcessMessageOptions, } from "@/helpers/caching/messages"; import { getConversationByTopic, @@ -39,7 +39,10 @@ export const useMessage = () => { const { db } = useDb(); const processMessage = useCallback( - async (conversation: CachedConversation, message: CachedMessage) => + async ( + conversation: ProcessMessageOptions["conversation"], + message: ProcessMessageOptions["message"], + ) => _processMessage({ client, conversation, @@ -145,7 +148,10 @@ export const useMessage = () => { // before updating, make sure the message was added to cache if (message.id) { - await updateMessageAfterSending(message, sentMessage.sent); + await updateMessageAfterSending( + message as CachedMessage, + sentMessage.sent, + ); } return { @@ -155,7 +161,7 @@ export const useMessage = () => { } catch (e) { // before updating, make sure the message is in the cache if (message.id) { - await updateMessage(message, { + await updateMessage(message as CachedMessage, { hasSendError: true, sendOptions: finalSendOptions, }); @@ -185,7 +191,7 @@ export const useMessage = () => { * @returns The sent message, or `undefined` if there's no XMTP client */ const resendMessage = useCallback( - async (message: CachedMessageWithId) => { + async (message: CachedMessage) => { if (!message.hasSendError) { throw new Error( "Resending a message that hasn't failed to send is not allowed", diff --git a/packages/react-sdk/src/hooks/useMessages.ts b/packages/react-sdk/src/hooks/useMessages.ts index f2f3707b..e9a3fd91 100644 --- a/packages/react-sdk/src/hooks/useMessages.ts +++ b/packages/react-sdk/src/hooks/useMessages.ts @@ -3,7 +3,6 @@ import { useCallback, useEffect, useRef, useState } from "react"; import { min, subSeconds } from "date-fns"; import type { OnError } from "../sharedTypes"; import { useCachedMessages } from "./useCachedMessages"; -import type { CachedMessageWithId } from "@/helpers/caching/messages"; import { toCachedMessage } from "@/helpers/caching/messages"; import { getConversationByTopic } from "@/helpers/caching/conversations"; import type { CachedConversation } from "@/helpers/caching/conversations"; @@ -37,9 +36,7 @@ export const useMessages = ( const [error, setError] = useState(null); const { processMessage } = useMessage(); const { updateConversation } = useConversationInternal(); - const messages = useCachedMessages( - conversation.topic, - ) as CachedMessageWithId[]; + const messages = useCachedMessages(conversation.topic); const { client } = useClient(); // to prevent messages from being fetched multiple times const loadingRef = useRef(false); diff --git a/packages/react-sdk/src/hooks/useResendMessage.test.ts b/packages/react-sdk/src/hooks/useResendMessage.test.ts index 40c5ef77..6ab1836a 100644 --- a/packages/react-sdk/src/hooks/useResendMessage.test.ts +++ b/packages/react-sdk/src/hooks/useResendMessage.test.ts @@ -2,7 +2,7 @@ import { it, expect, describe, vi, beforeEach } from "vitest"; import { act, renderHook, waitFor } from "@testing-library/react"; import { ContentTypeText } from "@xmtp/content-type-text"; import { useResendMessage } from "@/hooks/useResendMessage"; -import type { CachedMessageWithId } from "@/helpers/caching/messages"; +import type { CachedMessage } from "@/helpers/caching/messages"; const resendMock = vi.hoisted(() => vi.fn()); @@ -39,7 +39,7 @@ describe("useResendMessage", () => { uuid: "testUuid", walletAddress: "testWalletAddress", xmtpID: "testXmtpId", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; const { result } = renderHook(() => useResendMessage({ @@ -77,7 +77,7 @@ describe("useResendMessage", () => { uuid: "testUuid", walletAddress: "testWalletAddress", xmtpID: "testXmtpId", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; const { result } = renderHook(() => useResendMessage({ diff --git a/packages/react-sdk/src/hooks/useResendMessage.ts b/packages/react-sdk/src/hooks/useResendMessage.ts index 65189dd9..c1ec74dc 100644 --- a/packages/react-sdk/src/hooks/useResendMessage.ts +++ b/packages/react-sdk/src/hooks/useResendMessage.ts @@ -1,7 +1,7 @@ import { useCallback, useState } from "react"; import { useMessage } from "@/hooks/useMessage"; import type { UseSendMessageOptions } from "@/hooks/useSendMessage"; -import type { CachedMessageWithId } from "@/helpers/caching/messages"; +import type { CachedMessage } from "@/helpers/caching/messages"; /** * This hook can be used to resend a previously failed message, or cancel it. @@ -15,7 +15,7 @@ export const useResendMessage = (options?: UseSendMessageOptions) => { const { onError, onSuccess } = options ?? {}; const resend = useCallback( - async (message: CachedMessageWithId) => { + async (message: CachedMessage) => { setIsLoading(true); setError(null); @@ -36,7 +36,7 @@ export const useResendMessage = (options?: UseSendMessageOptions) => { ); const cancel = useCallback( - async (message: CachedMessageWithId) => { + async (message: CachedMessage) => { try { await deleteMessage(message); } catch (e) { diff --git a/packages/react-sdk/src/hooks/useStartConversation.test.ts b/packages/react-sdk/src/hooks/useStartConversation.test.ts index 09bc5f8c..a320a900 100644 --- a/packages/react-sdk/src/hooks/useStartConversation.test.ts +++ b/packages/react-sdk/src/hooks/useStartConversation.test.ts @@ -7,7 +7,7 @@ import { toCachedConversation, type CachedConversation, } from "@/helpers/caching/conversations"; -import type { CachedMessageWithId } from "@/helpers/caching/messages"; +import type { CachedMessage } from "@/helpers/caching/messages"; const useClientMock = vi.hoisted(() => vi.fn()); const sendMessageMock = vi.hoisted(() => vi.fn()); @@ -255,7 +255,7 @@ describe("useStartConversation", () => { walletAddress: "testWalletAddress", uuid: "testUuid", xmtpID: "testXmtpId", - } satisfies CachedMessageWithId; + } satisfies CachedMessage; saveConversationMock.mockResolvedValueOnce(savedConversation); sendMessageMock.mockResolvedValueOnce({ cachedMessage: savedMessage, diff --git a/packages/react-sdk/src/index.ts b/packages/react-sdk/src/index.ts index f19b52a8..fd336fb7 100644 --- a/packages/react-sdk/src/index.ts +++ b/packages/react-sdk/src/index.ts @@ -42,7 +42,6 @@ export { useStreamMessages } from "./hooks/useStreamMessages"; export type { CachedMessage, - CachedMessageWithId, CachedMessagesTable, ProcessUnprocessedMessagesOptions, } from "./helpers/caching/messages";