@remit/data-ports 0.0.54 → 0.0.55

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/data-ports",
3
- "version": "0.0.54",
3
+ "version": "0.0.55",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
package/src/id.test.ts CHANGED
@@ -199,8 +199,34 @@ describe("deriveCalendarSuggestionId", () => {
199
199
  });
200
200
  });
201
201
 
202
+ describe("deriveThreadId", () => {
203
+ const ROOT = "<root@example.com>";
204
+
205
+ // #1017: the account is not part of the name, so every mailbox connected to
206
+ // one config resolves the same root header to one conversation. Keyed on the
207
+ // account, a reply sent from the second account opened a thread of its own.
208
+ it("gives one root header one thread across the accounts of a config", () => {
209
+ assert.equal(deriveThreadId("cfg-1", ROOT), deriveThreadId("cfg-1", ROOT));
210
+ });
211
+
212
+ it("separates two account configs holding the same conversation", () => {
213
+ assert.notEqual(
214
+ deriveThreadId("cfg-1", ROOT),
215
+ deriveThreadId("cfg-2", ROOT),
216
+ );
217
+ });
218
+
219
+ it("separates two conversations under one config", () => {
220
+ assert.notEqual(
221
+ deriveThreadId("cfg-1", ROOT),
222
+ deriveThreadId("cfg-1", "<other@example.com>"),
223
+ );
224
+ });
225
+ });
226
+
202
227
  describe("derived ids are stored primary keys: a changed value orphans every row already written and needs a migration, never a new expectation here", () => {
203
228
  const ACCOUNT = "account-golden";
229
+ const ACCOUNT_CONFIG = "account-config-golden";
204
230
  const MESSAGE = "message-golden";
205
231
  const MAILBOX = "mailbox-golden";
206
232
  const ABSENT_HEADER_SOURCE = {
@@ -259,10 +285,10 @@ describe("derived ids are stored primary keys: a changed value orphans every row
259
285
  );
260
286
  });
261
287
 
262
- it("deriveThreadId pins the thread primary key, lowercased root header included", () => {
288
+ it("deriveThreadId pins the thread primary key, keyed on the account config, lowercased root header included", () => {
263
289
  assert.equal(
264
- deriveThreadId(ACCOUNT, "<Golden.Root@Example.COM>"),
265
- "bcy76e2uat5yq3xd1p7j7z4pr",
290
+ deriveThreadId(ACCOUNT_CONFIG, "<Golden.Root@Example.COM>"),
291
+ "3tl03sgy85b60rfb15u6vtiex",
266
292
  );
267
293
  });
268
294
 
package/src/id.ts CHANGED
@@ -150,12 +150,22 @@ export const deriveCopyMessageId = (
150
150
  REMIT_NAMESPACE,
151
151
  );
152
152
 
153
+ /**
154
+ * Identity of a conversation (issue #1017). Keyed on the account config, not on
155
+ * the account: two mailboxes connected to one config hold the same conversation,
156
+ * and keying on the account gave each of them its own thread rooted at the same
157
+ * header — so a reply sent from the second account opened a conversation of one
158
+ * beside the one it answered.
159
+ *
160
+ * Messages stay per account (`deriveMessageId`). Each account keeps its own copy
161
+ * of a mail, and the copies meet in one thread through the shared root header.
162
+ */
153
163
  export const deriveThreadId = (
154
- accountId: string,
164
+ accountConfigId: string,
155
165
  rootMessageIdHeader: string,
156
166
  ): string =>
157
167
  base36uuidv5(
158
- `thread:${accountId}:${rootMessageIdHeader.toLowerCase()}`,
168
+ `thread:${accountConfigId}:${rootMessageIdHeader.toLowerCase()}`,
159
169
  REMIT_NAMESPACE,
160
170
  );
161
171