@remit/mailbox-service 0.0.13 → 0.0.15

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remit/mailbox-service",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -9,6 +9,7 @@ import type {
9
9
  IThreadMessageRepository,
10
10
  ThreadMessageItem,
11
11
  } from "@remit/data-ports";
12
+ import { MessageSystemFlag } from "@remit/domain-enums";
12
13
  import type { ManagedConnectionFactory } from "./connection-factory.js";
13
14
  import { MessageSyncService } from "./message-sync.js";
14
15
  import type { ImapEnvelope } from "./types.js";
@@ -129,3 +130,28 @@ describe("message sync maps IMAP flags onto the created ThreadMessage", () => {
129
130
  assert.equal(input.hasStars, true);
130
131
  });
131
132
  });
133
+
134
+ // #79: the mapping above was correct and still shipped broken. The sync path
135
+ // compares a server flag list against these members, so what they hold has to
136
+ // be the spelling IMAP puts on the wire — a leading backslash and all. The
137
+ // published images carried `Flagged`, the member's *name*, because the emitter
138
+ // that generates them was installed unpatched and ate the escape. Every
139
+ // comparison then quietly stopped matching: mail flagged on the server arrived
140
+ // unstarred, and a star set in the app went out as a custom keyword no other
141
+ // client reads. Asserted against literals rather than the enum, because the
142
+ // enum is the thing under test.
143
+ describe("the generated flag members carry the IMAP wire spelling", () => {
144
+ test("system flags keep their leading backslash", () => {
145
+ assert.equal(MessageSystemFlag.Flagged, "\\Flagged");
146
+ assert.equal(MessageSystemFlag.Seen, "\\Seen");
147
+ assert.equal(MessageSystemFlag.Answered, "\\Answered");
148
+ assert.equal(MessageSystemFlag.Deleted, "\\Deleted");
149
+ assert.equal(MessageSystemFlag.Draft, "\\Draft");
150
+ });
151
+
152
+ test("a member's name is never its value", () => {
153
+ for (const [name, value] of Object.entries(MessageSystemFlag)) {
154
+ assert.notEqual(value, name);
155
+ }
156
+ });
157
+ });
@@ -135,15 +135,6 @@ describe("parseChangeCursor / formatChangeCursor", () => {
135
135
  assert.equal(parseChangeCursor("abc").modseq, 0n);
136
136
  assert.equal(parseChangeCursor("500:abc").modseq, 500n);
137
137
  });
138
-
139
- it("survives a numeric column value", () => {
140
- // SQLite hands back a number whatever the declared column type.
141
- assert.deepEqual(parseChangeCursor(900 as unknown as string), {
142
- modseq: 900n,
143
- group: 0n,
144
- uid: 0,
145
- });
146
- });
147
138
  });
148
139
 
149
140
  describe("dropAppliedPrefix", () => {
@@ -95,10 +95,7 @@ export interface ChangeCursor {
95
95
  * would not fit.
96
96
  */
97
97
  export const parseChangeCursor = (raw: string | undefined): ChangeCursor => {
98
- // SQLite gives a numeric column back as a number whatever the declared
99
- // type, so normalize before parsing rather than trusting the static type.
100
- const text = raw === undefined || raw === null ? "" : String(raw);
101
- const [left, right] = text.split(":");
98
+ const [left, right] = (raw ?? "").split(":");
102
99
 
103
100
  if (right === undefined) {
104
101
  return { modseq: parseModseq(left), group: 0n, uid: 0 };