From 21ec6e2abd6340af3e77907dac43c7aaec0919d9 Mon Sep 17 00:00:00 2001 From: daria-github Date: Tue, 13 Jun 2023 16:33:52 -0700 Subject: [PATCH 1/8] initial codec types and interfaces --- example/src/test_utils.ts | 32 ++++++++ example/src/tests.ts | 19 ++++- src/lib/Client.ts | 153 ++++++++++++++++++++++++++++++++++---- 3 files changed, 186 insertions(+), 18 deletions(-) create mode 100644 example/src/test_utils.ts diff --git a/example/src/test_utils.ts b/example/src/test_utils.ts new file mode 100644 index 000000000..248d7c711 --- /dev/null +++ b/example/src/test_utils.ts @@ -0,0 +1,32 @@ +import { ContentTypeID, EncodedContent } from "../../src/lib/Client"; + +export class NumberCodec { + contentType: { + id(): string; + authorityID: string; + typeID: string; + versionMajor: number; + versionMinor: number; + }; + + constructor() { + this.contentType = new ContentTypeID({ + authorityID: "example.com", + typeID: "number", + versionMajor: 1, + versionMinor: 1, + }); + } + + encode(content: T) { + let encodedContent = new EncodedContent(); + encodedContent.type = this.contentType; + encodedContent.version = this.contentType.versionMajor; + encodedContent.content = JSON.stringify(content); + return encodedContent; + } + + decode(encodedContent: EncodedContent) { + return JSON.parse(encodedContent.content); + } +} diff --git a/example/src/tests.ts b/example/src/tests.ts index 24b268eb0..4f1759e2b 100644 --- a/example/src/tests.ts +++ b/example/src/tests.ts @@ -1,6 +1,6 @@ -import { Wallet } from "ethers"; -import { Client } from "xmtp-react-native-sdk"; import * as XMTP from "../../src/index"; +import { CodecRegistry } from "../../src/lib/Client"; +import { NumberCodec } from "./test_utils"; function sleep(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); @@ -63,3 +63,18 @@ test("canMessage", async () => { const canMessage = await bob.canMessage(alice.address); return canMessage; }); + +test("can register, encode, and decode a number codec", async () => { + const numberCodec = new NumberCodec(); + + const registry = new CodecRegistry(); + registry.register(numberCodec); + + // Could just pull directly from numberCodec, but pulling from registry for this test so its extraction is part of this test. + const id = numberCodec.contentType.id(); + const codec = registry.codecs[id]; + const encodedContent = codec.encode(3.14); + + const decodedContent = encodedContent.decoded(registry); + return decodedContent === 3.14; +}); diff --git a/src/lib/Client.ts b/src/lib/Client.ts index b856ef248..6fe42b69a 100644 --- a/src/lib/Client.ts +++ b/src/lib/Client.ts @@ -48,9 +48,7 @@ export class Client { return new Client(address); } - async canMessage( - peerAddress: string - ): Promise { + async canMessage(peerAddress: string): Promise { return await XMTPModule.canMessage(this.address, peerAddress); } @@ -66,18 +64,141 @@ export class Client { before?: Date | undefined, after?: Date | undefined ): Promise { - try { - return await XMTPModule.listBatchMessages( - this.address, - topics, - conversationIDs, - limit, - before, - after - ); - } catch (e) { - console.info("ERROR in listBatchMessages", e); - return []; - } + try { + return await XMTPModule.listBatchMessages( + this.address, + topics, + conversationIDs, + limit, + before, + after + ); + } catch (e) { + console.info("ERROR in listBatchMessages", e); + return []; + } } } + +/* + * + * This ContentTypeID class represents a content type identifier. + * + * @param {string} authorityID - The authority that defined the content type. + * @param {string} typeID - The unique ID for the content type within the authority, e.g. "number" + * @param {number} versionMajor - The major version number of the content type. + * @param {number} versionMinor - The minor version number of the content type. + * + * @returns {string} The full content type ID in the format: + * : + */ + +export class ContentTypeID { + authorityID: string; + typeID: string; + versionMajor: number; + versionMinor: number; + constructor({ authorityID, typeID, versionMajor, versionMinor }) { + this.authorityID = authorityID; + this.typeID = typeID; + this.versionMajor = versionMajor; + this.versionMinor = versionMinor; + } + + id() { + return `${this.authorityID}:${this.typeID}`; + } +} + +/* + * CodecRegistry + * + * A registry for content codecs. Allows registering codecs by id + * and looking them up. + * + */ +export class CodecRegistry { + codecs: { [key: string]: ContentCodecInterface }; + + constructor() { + /* + * An object mapping content type IDs to + * codec instances. + */ + this.codecs = {}; + } + + /* + * Registers a content codec. + * + * @param {ContentCodecInterface} codec - This is the codec instance to register. + */ + register(codec: ContentCodecInterface) { + const contentType = codec.contentType.id(); + this.codecs[contentType] = codec; + } + + /* + * Finds a registered codec by content type ID. + * + * @param {string} contentTypeID - The id to look up. + * @returns {ContentCodecInterface | undefined} The found codec, or undefined if not found. + */ + find(contentTypeID: string) { + return this.codecs[contentTypeID]; + } +} + +/* + * + * An error class for codec-related errors during decoding. + * + * @param {string} message - The error message. + */ + +export class CodecError extends Error { + constructor(message: "invalidContent" | "codecNotFound") { + super(message); + this.name = message; + } +} + +/* + * + * Represents encoded content along with metadata. + * + * @param {ContentTypeID | {}} type - The contentTypeID or object for this content. + * @param {number} version - The version of the encoding format. + * @param {string} content - The encoded content data. + * + * @returns {T} The decoded content (else an error will be thrown) + */ + +export class EncodedContent { + type: ContentTypeID | {}; + version: number; + content: string; + + decoded(registry: CodecRegistry) { + const id = (this.type as ContentTypeID).id(); + const codec = registry.find(id); + if (!codec) throw new CodecError("codecNotFound"); + if (codec.decode(this)) return codec.decode(this); + throw new CodecError("invalidContent"); + } +} + +/* + * + * Codecs encode and decode content, and this is the interface for ContentCodecs within this app. + * + * @param {ContentTypeID} contentType - The content type this codec handles. + * @param {} encode(content) - Encodes the given content and returns an EncodedContent. + * @param {} decode(content) - Decodes the given EncodedContent and returns the original content. + */ + +interface ContentCodecInterface { + contentType: ContentTypeID; + encode(content: T): EncodedContent; + decode(content: EncodedContent): T; +} From b55fe621ac3213d398070bfccda19df9686182da Mon Sep 17 00:00:00 2001 From: daria-github Date: Tue, 13 Jun 2023 16:34:56 -0700 Subject: [PATCH 2/8] removed comment --- example/src/tests.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/example/src/tests.ts b/example/src/tests.ts index 4f1759e2b..10a808f7e 100644 --- a/example/src/tests.ts +++ b/example/src/tests.ts @@ -70,7 +70,6 @@ test("can register, encode, and decode a number codec", async () => { const registry = new CodecRegistry(); registry.register(numberCodec); - // Could just pull directly from numberCodec, but pulling from registry for this test so its extraction is part of this test. const id = numberCodec.contentType.id(); const codec = registry.codecs[id]; const encodedContent = codec.encode(3.14); From a9c055add8d57064c477a70cb095a0ad473ac961 Mon Sep 17 00:00:00 2001 From: daria-github Date: Wed, 14 Jun 2023 12:08:46 -0700 Subject: [PATCH 3/8] reorganized classes, updated tests, added metadata --- example/src/test_utils.ts | 23 +++++-- example/src/tests.ts | 100 +++++++++++++++++++++---------- src/XMTP.enums.ts | 6 ++ src/XMTP.types.ts | 21 +++++++ src/lib/Client.ts | 123 -------------------------------------- src/lib/CodecError.ts | 13 ++++ src/lib/CodecRegistry.ts | 62 +++++++++++++++++++ src/lib/ContentTypeID.ts | 29 +++++++++ 8 files changed, 218 insertions(+), 159 deletions(-) create mode 100644 src/XMTP.enums.ts create mode 100644 src/lib/CodecError.ts create mode 100644 src/lib/CodecRegistry.ts create mode 100644 src/lib/ContentTypeID.ts diff --git a/example/src/test_utils.ts b/example/src/test_utils.ts index 248d7c711..19435c2e2 100644 --- a/example/src/test_utils.ts +++ b/example/src/test_utils.ts @@ -1,4 +1,7 @@ -import { ContentTypeID, EncodedContent } from "../../src/lib/Client"; +import { EncodedContent } from "../../src/XMTP.types"; +import { CodecError } from "../../src/lib/CodecError"; +import { ContentTypeID } from "../../src/lib/ContentTypeID"; +import { Compression } from "../../src/XMTP.enums"; export class NumberCodec { contentType: { @@ -19,14 +22,22 @@ export class NumberCodec { } encode(content: T) { - let encodedContent = new EncodedContent(); - encodedContent.type = this.contentType; - encodedContent.version = this.contentType.versionMajor; - encodedContent.content = JSON.stringify(content); + const encodedContent = { + type: this.contentType, + content: JSON.stringify(content), + compression: Compression.COMPRESSION_DEFLATE, + fallback: "fallbackText", + }; + return encodedContent; } decode(encodedContent: EncodedContent) { - return JSON.parse(encodedContent.content); + try { + const decodedContent = JSON.parse(encodedContent.content); + return decodedContent; + } catch { + throw new CodecError("invalidContent"); + } } } diff --git a/example/src/tests.ts b/example/src/tests.ts index 10a808f7e..d708e839b 100644 --- a/example/src/tests.ts +++ b/example/src/tests.ts @@ -1,5 +1,7 @@ import * as XMTP from "../../src/index"; -import { CodecRegistry } from "../../src/lib/Client"; +import { CodecRegistry } from "../../src/lib/CodecRegistry"; +import { CodecError } from "../../src/lib/CodecError"; + import { NumberCodec } from "./test_utils"; function sleep(ms: number) { @@ -26,43 +28,43 @@ test("can make a client", async () => { return client.address.length > 0; }); -test("can message a client", async () => { - const bob = await XMTP.Client.createRandom("local"); - const alice = await XMTP.Client.createRandom("local"); +// test("can message a client", async () => { +// const bob = await XMTP.Client.createRandom("local"); +// const alice = await XMTP.Client.createRandom("local"); - if (bob.address === alice.address) { - throw new Error("bob and alice should be different"); - } +// if (bob.address === alice.address) { +// throw new Error("bob and alice should be different"); +// } - const bobConversation = await bob.conversations.newConversation( - alice.address - ); +// const bobConversation = await bob.conversations.newConversation( +// alice.address +// ); - const aliceConversation = (await alice.conversations.list())[0]; - if (!aliceConversation) { - throw new Error("aliceConversation should exist"); - } +// const aliceConversation = (await alice.conversations.list())[0]; +// if (!aliceConversation) { +// throw new Error("aliceConversation should exist"); +// } - await bobConversation.send("hello world"); +// await bobConversation.send("hello world"); - const messages = await aliceConversation.messages(); +// const messages = await aliceConversation.messages(); - if (messages.length !== 1) { - throw Error("No message"); - } +// if (messages.length !== 1) { +// throw Error("No message"); +// } - const message = messages[0]; +// const message = messages[0]; - return message.content === "hello world"; -}); +// return message.content === "hello world"; +// }); -test("canMessage", async () => { - const bob = await XMTP.Client.createRandom("local"); - const alice = await XMTP.Client.createRandom("local"); +// test("canMessage", async () => { +// const bob = await XMTP.Client.createRandom("local"); +// const alice = await XMTP.Client.createRandom("local"); - const canMessage = await bob.canMessage(alice.address); - return canMessage; -}); +// const canMessage = await bob.canMessage(alice.address); +// return canMessage; +// }); test("can register, encode, and decode a number codec", async () => { const numberCodec = new NumberCodec(); @@ -71,9 +73,47 @@ test("can register, encode, and decode a number codec", async () => { registry.register(numberCodec); const id = numberCodec.contentType.id(); - const codec = registry.codecs[id]; + const codec = registry.find(id); + const encodedContent = codec.encode(3.14); + const decodedContent = codec.decode(encodedContent); - const decodedContent = encodedContent.decoded(registry); return decodedContent === 3.14; }); + +test("throws an error if codec is not found in registry", async () => { + const numberCodec = new NumberCodec(); + const registry = new CodecRegistry(); + registry.register(numberCodec); + + try { + const id = "invalidId"; + registry.find(id); + } catch (e) { + return (e as CodecError).message === "codecNotFound"; + } + return false; +}); + +test("throws an error if codec is invalid when decoding", async () => { + const numberCodec = new NumberCodec(); + const registry = new CodecRegistry(); + registry.register(numberCodec); + + try { + const id = numberCodec.contentType.id(); + const codec = registry.find(id); + + const encodedContent = codec.encode(3.14); + const invalidContentToDecode = { + ...encodedContent, + // @ts-ignore + content: { key1: "This cannot be parsed" }, + }; + // @ts-ignore + codec.decode(invalidContentToDecode); + } catch (e) { + return (e as CodecError).message === "invalidContent"; + } + return false; +}); diff --git a/src/XMTP.enums.ts b/src/XMTP.enums.ts new file mode 100644 index 000000000..caeaa49c1 --- /dev/null +++ b/src/XMTP.enums.ts @@ -0,0 +1,6 @@ +// Recognized compression algorithms +// protolint:disable ENUM_FIELD_NAMES_ZERO_VALUE_END_WITH +export enum Compression { + COMPRESSION_DEFLATE = 0, + COMPRESSION_GZIP = 1, +} diff --git a/src/XMTP.types.ts b/src/XMTP.types.ts index 9562227ea..481ee808a 100644 --- a/src/XMTP.types.ts +++ b/src/XMTP.types.ts @@ -1,3 +1,6 @@ +import { Compression } from "./XMTP.enums"; +import { ContentTypeID } from "./lib/ContentTypeID"; + export type ChangeEventPayload = { value: string; }; @@ -5,3 +8,21 @@ export type ChangeEventPayload = { export type XMTPViewProps = { name: string; }; + +/* + * EncodedContent + * + * Represents encoded content and its metadata. + * + * @param {ContentTypeID | {}} type - The content type ID or object for this content. + * @param {string} content - The encoded content data. + * @param {Compression} compression - The compression algorithm used, if any. + * @param {string} fallback - A fallback representation of the content, if any. + */ + +export type EncodedContent = { + type: ContentTypeID | {}; + content: string; + compression?: Compression; + fallback?: string; +}; diff --git a/src/lib/Client.ts b/src/lib/Client.ts index 6fe42b69a..a83d4353e 100644 --- a/src/lib/Client.ts +++ b/src/lib/Client.ts @@ -79,126 +79,3 @@ export class Client { } } } - -/* - * - * This ContentTypeID class represents a content type identifier. - * - * @param {string} authorityID - The authority that defined the content type. - * @param {string} typeID - The unique ID for the content type within the authority, e.g. "number" - * @param {number} versionMajor - The major version number of the content type. - * @param {number} versionMinor - The minor version number of the content type. - * - * @returns {string} The full content type ID in the format: - * : - */ - -export class ContentTypeID { - authorityID: string; - typeID: string; - versionMajor: number; - versionMinor: number; - constructor({ authorityID, typeID, versionMajor, versionMinor }) { - this.authorityID = authorityID; - this.typeID = typeID; - this.versionMajor = versionMajor; - this.versionMinor = versionMinor; - } - - id() { - return `${this.authorityID}:${this.typeID}`; - } -} - -/* - * CodecRegistry - * - * A registry for content codecs. Allows registering codecs by id - * and looking them up. - * - */ -export class CodecRegistry { - codecs: { [key: string]: ContentCodecInterface }; - - constructor() { - /* - * An object mapping content type IDs to - * codec instances. - */ - this.codecs = {}; - } - - /* - * Registers a content codec. - * - * @param {ContentCodecInterface} codec - This is the codec instance to register. - */ - register(codec: ContentCodecInterface) { - const contentType = codec.contentType.id(); - this.codecs[contentType] = codec; - } - - /* - * Finds a registered codec by content type ID. - * - * @param {string} contentTypeID - The id to look up. - * @returns {ContentCodecInterface | undefined} The found codec, or undefined if not found. - */ - find(contentTypeID: string) { - return this.codecs[contentTypeID]; - } -} - -/* - * - * An error class for codec-related errors during decoding. - * - * @param {string} message - The error message. - */ - -export class CodecError extends Error { - constructor(message: "invalidContent" | "codecNotFound") { - super(message); - this.name = message; - } -} - -/* - * - * Represents encoded content along with metadata. - * - * @param {ContentTypeID | {}} type - The contentTypeID or object for this content. - * @param {number} version - The version of the encoding format. - * @param {string} content - The encoded content data. - * - * @returns {T} The decoded content (else an error will be thrown) - */ - -export class EncodedContent { - type: ContentTypeID | {}; - version: number; - content: string; - - decoded(registry: CodecRegistry) { - const id = (this.type as ContentTypeID).id(); - const codec = registry.find(id); - if (!codec) throw new CodecError("codecNotFound"); - if (codec.decode(this)) return codec.decode(this); - throw new CodecError("invalidContent"); - } -} - -/* - * - * Codecs encode and decode content, and this is the interface for ContentCodecs within this app. - * - * @param {ContentTypeID} contentType - The content type this codec handles. - * @param {} encode(content) - Encodes the given content and returns an EncodedContent. - * @param {} decode(content) - Decodes the given EncodedContent and returns the original content. - */ - -interface ContentCodecInterface { - contentType: ContentTypeID; - encode(content: T): EncodedContent; - decode(content: EncodedContent): T; -} diff --git a/src/lib/CodecError.ts b/src/lib/CodecError.ts new file mode 100644 index 000000000..c7e1cfbf7 --- /dev/null +++ b/src/lib/CodecError.ts @@ -0,0 +1,13 @@ +/* + * + * An error class for codec-related errors when searching the registry. + * + * @param {string} message - The error message. + */ + +export class CodecError extends Error { + constructor(message: "invalidContent" | "codecNotFound") { + super(message); + this.name = message; + } +} diff --git a/src/lib/CodecRegistry.ts b/src/lib/CodecRegistry.ts new file mode 100644 index 000000000..f209e8376 --- /dev/null +++ b/src/lib/CodecRegistry.ts @@ -0,0 +1,62 @@ +import { EncodedContent } from "../XMTP.types"; +import { CodecError } from "./CodecError"; +import { ContentTypeID } from "./ContentTypeID"; + +/* + * + * Codecs encode and decode content, and this is the interface for ContentCodecs within this app. + * + * @param {ContentTypeID} contentType - The content type this codec handles. + * @param {} encode(content) - Encodes the given content and returns an EncodedContent. + * @param {} decode(content) - Decodes the given EncodedContent and returns the original content. + */ + +interface ContentCodecInterface { + contentType: ContentTypeID; + encode(content: T): EncodedContent; + decode(content: EncodedContent): T; +} + +/* + * CodecRegistry + * + * A registry for content codecs. Allows registering codecs by id + * and looking them up. + * + */ +export class CodecRegistry { + codecs: { [key: string]: ContentCodecInterface }; + + constructor() { + /* + * An object mapping content type IDs to + * codec instances. + */ + this.codecs = {}; + } + + /* + * Registers a content codec. + * + * @param {ContentCodecInterface} codec - This is the codec instance to register. + */ + register(codec: ContentCodecInterface) { + const contentType = codec.contentType.id(); + this.codecs[contentType] = codec; + } + + /* + * Finds a registered codec by content type ID. + * + * @param {string} contentTypeID - The id to look up. + * @returns {ContentCodecInterface} The found codec, or an error is thrown if not found. + */ + find(contentTypeID: string) { + const codec = this.codecs[contentTypeID]; + if (!codec) { + throw new CodecError("codecNotFound"); + } else { + return codec; + } + } +} diff --git a/src/lib/ContentTypeID.ts b/src/lib/ContentTypeID.ts new file mode 100644 index 000000000..651e6af5d --- /dev/null +++ b/src/lib/ContentTypeID.ts @@ -0,0 +1,29 @@ +/* + * + * This ContentTypeID class represents a content type identifier. + * + * @param {string} authorityID - The authority that defined the content type. + * @param {string} typeID - The unique ID for the content type within the authority, e.g. "number" + * @param {number} versionMajor - The major version number of the content type. + * @param {number} versionMinor - The minor version number of the content type. + * + * @returns {string} The full content type ID in the format: + * : + */ + +export class ContentTypeID { + authorityID: string; + typeID: string; + versionMajor: number; + versionMinor: number; + constructor({ authorityID, typeID, versionMajor, versionMinor }) { + this.authorityID = authorityID; + this.typeID = typeID; + this.versionMajor = versionMajor; + this.versionMinor = versionMinor; + } + + id() { + return `${this.authorityID}:${this.typeID}`; + } +} From 865a321f539e654ce36564981570a8a164203db4 Mon Sep 17 00:00:00 2001 From: daria-github Date: Wed, 14 Jun 2023 12:19:05 -0700 Subject: [PATCH 4/8] reenabled old tests --- example/src/tests.ts | 54 ++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/example/src/tests.ts b/example/src/tests.ts index d708e839b..c55234f86 100644 --- a/example/src/tests.ts +++ b/example/src/tests.ts @@ -28,43 +28,43 @@ test("can make a client", async () => { return client.address.length > 0; }); -// test("can message a client", async () => { -// const bob = await XMTP.Client.createRandom("local"); -// const alice = await XMTP.Client.createRandom("local"); +test("can message a client", async () => { + const bob = await XMTP.Client.createRandom("local"); + const alice = await XMTP.Client.createRandom("local"); -// if (bob.address === alice.address) { -// throw new Error("bob and alice should be different"); -// } + if (bob.address === alice.address) { + throw new Error("bob and alice should be different"); + } -// const bobConversation = await bob.conversations.newConversation( -// alice.address -// ); + const bobConversation = await bob.conversations.newConversation( + alice.address + ); -// const aliceConversation = (await alice.conversations.list())[0]; -// if (!aliceConversation) { -// throw new Error("aliceConversation should exist"); -// } + const aliceConversation = (await alice.conversations.list())[0]; + if (!aliceConversation) { + throw new Error("aliceConversation should exist"); + } -// await bobConversation.send("hello world"); + await bobConversation.send("hello world"); -// const messages = await aliceConversation.messages(); + const messages = await aliceConversation.messages(); -// if (messages.length !== 1) { -// throw Error("No message"); -// } + if (messages.length !== 1) { + throw Error("No message"); + } -// const message = messages[0]; + const message = messages[0]; -// return message.content === "hello world"; -// }); + return message.content === "hello world"; +}); -// test("canMessage", async () => { -// const bob = await XMTP.Client.createRandom("local"); -// const alice = await XMTP.Client.createRandom("local"); +test("canMessage", async () => { + const bob = await XMTP.Client.createRandom("local"); + const alice = await XMTP.Client.createRandom("local"); -// const canMessage = await bob.canMessage(alice.address); -// return canMessage; -// }); + const canMessage = await bob.canMessage(alice.address); + return canMessage; +}); test("can register, encode, and decode a number codec", async () => { const numberCodec = new NumberCodec(); From 7078f7a9d778c51f5d3b35dda3a4a495ee6ceb3f Mon Sep 17 00:00:00 2001 From: daria-github Date: Wed, 14 Jun 2023 12:35:25 -0700 Subject: [PATCH 5/8] undo linting on client class --- src/lib/Client.ts | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/lib/Client.ts b/src/lib/Client.ts index a83d4353e..b856ef248 100644 --- a/src/lib/Client.ts +++ b/src/lib/Client.ts @@ -48,7 +48,9 @@ export class Client { return new Client(address); } - async canMessage(peerAddress: string): Promise { + async canMessage( + peerAddress: string + ): Promise { return await XMTPModule.canMessage(this.address, peerAddress); } @@ -64,18 +66,18 @@ export class Client { before?: Date | undefined, after?: Date | undefined ): Promise { - try { - return await XMTPModule.listBatchMessages( - this.address, - topics, - conversationIDs, - limit, - before, - after - ); - } catch (e) { - console.info("ERROR in listBatchMessages", e); - return []; - } + try { + return await XMTPModule.listBatchMessages( + this.address, + topics, + conversationIDs, + limit, + before, + after + ); + } catch (e) { + console.info("ERROR in listBatchMessages", e); + return []; + } } } From 260283faf12f5e51edd7479a6fdac30ea31726b0 Mon Sep 17 00:00:00 2001 From: daria-github Date: Wed, 14 Jun 2023 15:09:09 -0700 Subject: [PATCH 6/8] updated expected content type --- example/src/test_utils.ts | 9 ++++----- example/src/tests.ts | 12 +++++++----- src/XMTP.enums.ts | 6 ------ src/XMTP.types.ts | 10 +++------- src/lib/CodecRegistry.ts | 2 +- 5 files changed, 15 insertions(+), 24 deletions(-) delete mode 100644 src/XMTP.enums.ts diff --git a/example/src/test_utils.ts b/example/src/test_utils.ts index 19435c2e2..40abc8129 100644 --- a/example/src/test_utils.ts +++ b/example/src/test_utils.ts @@ -1,7 +1,6 @@ import { EncodedContent } from "../../src/XMTP.types"; import { CodecError } from "../../src/lib/CodecError"; import { ContentTypeID } from "../../src/lib/ContentTypeID"; -import { Compression } from "../../src/XMTP.enums"; export class NumberCodec { contentType: { @@ -21,11 +20,10 @@ export class NumberCodec { }); } - encode(content: T) { + encode(content: Uint8Array) { const encodedContent = { type: this.contentType, - content: JSON.stringify(content), - compression: Compression.COMPRESSION_DEFLATE, + content: Buffer.from(JSON.stringify(content)), fallback: "fallbackText", }; @@ -34,7 +32,8 @@ export class NumberCodec { decode(encodedContent: EncodedContent) { try { - const decodedContent = JSON.parse(encodedContent.content); + const contentToDecode = encodedContent.content.toString(); + const decodedContent = JSON.parse(contentToDecode); return decodedContent; } catch { throw new CodecError("invalidContent"); diff --git a/example/src/tests.ts b/example/src/tests.ts index c55234f86..b5128eb4c 100644 --- a/example/src/tests.ts +++ b/example/src/tests.ts @@ -1,5 +1,8 @@ import * as XMTP from "../../src/index"; -import { CodecRegistry } from "../../src/lib/CodecRegistry"; +import { + CodecRegistry, + ContentCodecInterface, +} from "../../src/lib/CodecRegistry"; import { CodecError } from "../../src/lib/CodecError"; import { NumberCodec } from "./test_utils"; @@ -70,7 +73,7 @@ test("can register, encode, and decode a number codec", async () => { const numberCodec = new NumberCodec(); const registry = new CodecRegistry(); - registry.register(numberCodec); + registry.register(numberCodec as ContentCodecInterface); const id = numberCodec.contentType.id(); const codec = registry.find(id); @@ -84,7 +87,7 @@ test("can register, encode, and decode a number codec", async () => { test("throws an error if codec is not found in registry", async () => { const numberCodec = new NumberCodec(); const registry = new CodecRegistry(); - registry.register(numberCodec); + registry.register(numberCodec as ContentCodecInterface); try { const id = "invalidId"; @@ -98,7 +101,7 @@ test("throws an error if codec is not found in registry", async () => { test("throws an error if codec is invalid when decoding", async () => { const numberCodec = new NumberCodec(); const registry = new CodecRegistry(); - registry.register(numberCodec); + registry.register(numberCodec as ContentCodecInterface); try { const id = numberCodec.contentType.id(); @@ -107,7 +110,6 @@ test("throws an error if codec is invalid when decoding", async () => { const encodedContent = codec.encode(3.14); const invalidContentToDecode = { ...encodedContent, - // @ts-ignore content: { key1: "This cannot be parsed" }, }; // @ts-ignore diff --git a/src/XMTP.enums.ts b/src/XMTP.enums.ts deleted file mode 100644 index caeaa49c1..000000000 --- a/src/XMTP.enums.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Recognized compression algorithms -// protolint:disable ENUM_FIELD_NAMES_ZERO_VALUE_END_WITH -export enum Compression { - COMPRESSION_DEFLATE = 0, - COMPRESSION_GZIP = 1, -} diff --git a/src/XMTP.types.ts b/src/XMTP.types.ts index 481ee808a..5026a50d8 100644 --- a/src/XMTP.types.ts +++ b/src/XMTP.types.ts @@ -1,4 +1,3 @@ -import { Compression } from "./XMTP.enums"; import { ContentTypeID } from "./lib/ContentTypeID"; export type ChangeEventPayload = { @@ -10,19 +9,16 @@ export type XMTPViewProps = { }; /* - * EncodedContent * * Represents encoded content and its metadata. * - * @param {ContentTypeID | {}} type - The content type ID or object for this content. + * @param {ContentTypeID} type - The content type ID for this content. * @param {string} content - The encoded content data. - * @param {Compression} compression - The compression algorithm used, if any. * @param {string} fallback - A fallback representation of the content, if any. */ export type EncodedContent = { - type: ContentTypeID | {}; - content: string; - compression?: Compression; + type: ContentTypeID; + content: Uint8Array; fallback?: string; }; diff --git a/src/lib/CodecRegistry.ts b/src/lib/CodecRegistry.ts index f209e8376..d7e95823f 100644 --- a/src/lib/CodecRegistry.ts +++ b/src/lib/CodecRegistry.ts @@ -11,7 +11,7 @@ import { ContentTypeID } from "./ContentTypeID"; * @param {} decode(content) - Decodes the given EncodedContent and returns the original content. */ -interface ContentCodecInterface { +export interface ContentCodecInterface { contentType: ContentTypeID; encode(content: T): EncodedContent; decode(content: EncodedContent): T; From ae874759e35e40ccc68876c2a512e43493a8d3c7 Mon Sep 17 00:00:00 2001 From: Daria J <35409260+daria-github@users.noreply.github.com> Date: Wed, 14 Jun 2023 15:17:17 -0700 Subject: [PATCH 7/8] update type in docs Co-authored-by: Pat Nakajima --- src/XMTP.types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/XMTP.types.ts b/src/XMTP.types.ts index 5026a50d8..74a82a130 100644 --- a/src/XMTP.types.ts +++ b/src/XMTP.types.ts @@ -13,7 +13,7 @@ export type XMTPViewProps = { * Represents encoded content and its metadata. * * @param {ContentTypeID} type - The content type ID for this content. - * @param {string} content - The encoded content data. + * @param {Uint8Array} content - The encoded content data. * @param {string} fallback - A fallback representation of the content, if any. */ From f4786bf5cf0398996cb9e7e7db06dc7e0156d2f9 Mon Sep 17 00:00:00 2001 From: Daria J <35409260+daria-github@users.noreply.github.com> Date: Wed, 14 Jun 2023 15:17:51 -0700 Subject: [PATCH 8/8] add param field Co-authored-by: Pat Nakajima --- src/XMTP.types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/XMTP.types.ts b/src/XMTP.types.ts index 74a82a130..3b1312587 100644 --- a/src/XMTP.types.ts +++ b/src/XMTP.types.ts @@ -19,6 +19,7 @@ export type XMTPViewProps = { export type EncodedContent = { type: ContentTypeID; + parameters: { [key: string]: [value: string] }? , content: Uint8Array; fallback?: string; };