Skip to content
This repository has been archived by the owner on Oct 10, 2024. It is now read-only.

Commit

Permalink
fix: normalize reaction encoding, support legacy form
Browse files Browse the repository at this point in the history
  • Loading branch information
dmccartney committed Sep 5, 2023
1 parent 363e82c commit ae64489
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 18 deletions.
40 changes: 40 additions & 0 deletions packages/content-type-reaction/src/Reaction.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,46 @@ describe("ReactionContentType", () => {
expect(ContentTypeReaction.versionMinor).toBe(0);
});

it("supports canonical and legacy form", async () => {
let codec = new ReactionCodec();

// This is how clients send reactions now.
let canonicalEncoded = {
type: ContentTypeReaction,
content: new TextEncoder().encode(
JSON.stringify({
action: "added",
content: "smile",
reference: "abc123",
schema: "shortcode",
}),
),
};

// Previously, some clients sent reactions like this.
// So we test here to make sure we can still decode them.
let legacyEncoded = {
type: ContentTypeReaction,
parameters: {
action: "added",
reference: "abc123",
schema: "shortcode",
},
content: new TextEncoder().encode("smile"),
};

let canonical = codec.decode(canonicalEncoded as any);
let legacy = codec.decode(legacyEncoded as any);
expect(canonical.action).toBe("added");
expect(legacy.action).toBe("added");
expect(canonical.content).toBe("smile");
expect(legacy.content).toBe("smile");
expect(canonical.reference).toBe("abc123");
expect(legacy.reference).toBe("abc123");
expect(canonical.schema).toBe("shortcode");
expect(legacy.schema).toBe("shortcode");
});

it("can send a reaction", async () => {
const aliceWallet = Wallet.createRandom();
const aliceClient = await Client.create(aliceWallet, { env: "local" });
Expand Down
45 changes: 28 additions & 17 deletions packages/content-type-reaction/src/Reaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ export type Reaction = {
schema: "unicode" | "shortcode" | "custom";
};

export type ReactionParameters = Pick<
Reaction,
"action" | "reference" | "schema"
type LegacyReactionParameters = Pick<
Reaction,
"action" | "reference" | "schema"
> & {
encoding: "UTF-8";
};
Expand All @@ -39,29 +39,40 @@ export class ReactionCodec implements ContentCodec<Reaction> {
return ContentTypeReaction;
}

encode(content: Reaction): EncodedContent<ReactionParameters> {
encode(reaction: Reaction): EncodedContent {
const { action, reference, schema, content } = reaction;
return {
type: ContentTypeReaction,
parameters: {
encoding: "UTF-8",
action: content.action,
reference: content.reference,
schema: content.schema,
},
content: new TextEncoder().encode(content.content),
parameters: {},
content: new TextEncoder().encode(
JSON.stringify({ action, reference, schema, content }),
),
};
}

decode(content: EncodedContent<ReactionParameters>): Reaction {
const { encoding } = content.parameters;
decode(content: EncodedContent): Reaction {
let text = new TextDecoder().decode(content.content);

// First try to decode it in the canonical form.
try {
const reaction = JSON.parse(text);
const { action, reference, schema, content } = reaction;
return { action, reference, schema, content };
} catch (e) {
// ignore, fall through to legacy decoding
}

// If that fails, try to decode it in the legacy form.
let parameters = content.parameters as LegacyReactionParameters;
const { encoding } = parameters;
if (encoding && encoding !== "UTF-8") {
throw new Error(`unrecognized encoding ${encoding as string}`);
}
return {
action: content.parameters.action,
reference: content.parameters.reference,
schema: content.parameters.schema,
content: new TextDecoder().decode(content.content),
action: parameters.action,
reference: parameters.reference,
schema: parameters.schema,
content: text,
};
}
}
2 changes: 1 addition & 1 deletion packages/content-type-reaction/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { ReactionCodec, ContentTypeReaction } from "./Reaction";
export type { Reaction, ReactionParameters } from "./Reaction";
export type { Reaction } from "./Reaction";

0 comments on commit ae64489

Please sign in to comment.