@thezelijah/majik-message 1.0.12 → 1.0.13

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.
@@ -15,9 +15,11 @@ export declare class MajikMessageChat {
15
15
  private timestamp;
16
16
  private expires_at;
17
17
  private read_by;
18
+ private conversation_id;
18
19
  private static readonly MAX_MESSAGE_LENGTH;
19
- constructor(id: MajikMessageChatID, account: MajikMessageAccountID, message: string, sender: MajikMessagePublicKey, recipients: MajikMessagePublicKey[], timestamp: string, expires_at: string, read_by?: string[]);
20
+ constructor(id: MajikMessageChatID, account: MajikMessageAccountID, message: string, sender: MajikMessagePublicKey, recipients: MajikMessagePublicKey[], timestamp: string, expires_at: string, read_by?: string[], conversation_id?: string);
20
21
  getID(): string;
22
+ getConversationID(): string;
21
23
  get account(): MajikMessageAccountID;
22
24
  set account(account: MajikMessageIdentity);
23
25
  /**
@@ -53,17 +55,16 @@ export declare class MajikMessageChat {
53
55
  */
54
56
  static create(account: MajikMessageIdentity, message: string, recipients: string[], expiresInMs?: number): Promise<MajikMessageChat>;
55
57
  /**
56
- * Generate a deterministic conversation ID from a message
57
- * Automatically includes sender and all recipients, normalized by alphabetical order
58
- * then hashes with SHA-256 and encodes as base64
58
+ * Generate a deterministic conversation ID from a message JSON
59
+ * Reads sender and recipients directly from JSON without parsing
59
60
  */
60
- static generateConversationID(message: MajikMessageChatJSON): Promise<string>;
61
+ static generateConversationID(message: MajikMessageChatJSON): string;
61
62
  /**
62
63
  * Generate a deterministic conversation ID from a message
63
64
  * Automatically includes sender and all recipients, normalized by alphabetical order
64
65
  * then hashes with SHA-256 and encodes as base64
65
66
  */
66
- generateConversationID(): Promise<string>;
67
+ generateConversationID(): string;
67
68
  /**
68
69
  * Get all participants for a message (sender + recipients)
69
70
  */
@@ -15,9 +15,10 @@ export class MajikMessageChat {
15
15
  timestamp;
16
16
  expires_at;
17
17
  read_by;
18
+ conversation_id;
18
19
  // Maximum allowed length for the compressed message string
19
20
  static MAX_MESSAGE_LENGTH = 10000;
20
- constructor(id, account, message, sender, recipients, timestamp, expires_at, read_by = []) {
21
+ constructor(id, account, message, sender, recipients, timestamp, expires_at, read_by = [], conversation_id) {
21
22
  this.validateID(id);
22
23
  this.validateAccount(account);
23
24
  this.validateMessage(message);
@@ -34,11 +35,15 @@ export class MajikMessageChat {
34
35
  this.timestamp = timestamp;
35
36
  this.expires_at = expires_at;
36
37
  this.read_by = [...read_by]; // Clone to prevent external mutation
38
+ this.conversation_id = conversation_id || this.generateConversationID();
37
39
  }
38
40
  // ============= GETTERS =============
39
41
  getID() {
40
42
  return this.id;
41
43
  }
44
+ getConversationID() {
45
+ return this.conversation_id;
46
+ }
42
47
  get account() {
43
48
  return this._account;
44
49
  }
@@ -152,16 +157,14 @@ export class MajikMessageChat {
152
157
  }
153
158
  // ============= STATIC HELPER METHODS =============
154
159
  /**
155
- * Generate a deterministic conversation ID from a message
156
- * Automatically includes sender and all recipients, normalized by alphabetical order
157
- * then hashes with SHA-256 and encodes as base64
160
+ * Generate a deterministic conversation ID from a message JSON
161
+ * Reads sender and recipients directly from JSON without parsing
158
162
  */
159
- static async generateConversationID(message) {
160
- const parsedMessage = this.fromJSON(message);
161
- // Get all participants (sender + recipients)
163
+ static generateConversationID(message) {
164
+ // Get all participants (sender + recipients) directly from JSON
162
165
  const participants = new Set();
163
- participants.add(parsedMessage.getSender());
164
- parsedMessage.getRecipients().forEach((r) => participants.add(r));
166
+ participants.add(message.sender);
167
+ message.recipients.forEach((r) => participants.add(r));
165
168
  // Sort alphabetically to ensure same conversation ID regardless of order
166
169
  const sorted = Array.from(participants).sort();
167
170
  // Join with delimiter
@@ -178,7 +181,7 @@ export class MajikMessageChat {
178
181
  * Automatically includes sender and all recipients, normalized by alphabetical order
179
182
  * then hashes with SHA-256 and encodes as base64
180
183
  */
181
- async generateConversationID() {
184
+ generateConversationID() {
182
185
  // Get all participants (sender + recipients)
183
186
  const participants = new Set();
184
187
  participants.add(this.getSender());
@@ -257,6 +260,7 @@ export class MajikMessageChat {
257
260
  throw new Error("Cannot add sender as a recipient");
258
261
  }
259
262
  this.recipients.push(trimmedId);
263
+ this.conversation_id = this.generateConversationID();
260
264
  }
261
265
  removeRecipient(recipientId) {
262
266
  if (!recipientId ||
@@ -278,6 +282,7 @@ export class MajikMessageChat {
278
282
  if (this.recipients.length === 0) {
279
283
  throw new Error("Cannot remove last recipient: message must have at least one recipient");
280
284
  }
285
+ this.conversation_id = this.generateConversationID();
281
286
  }
282
287
  hasRecipient(recipientId) {
283
288
  if (!recipientId || typeof recipientId !== "string") {
@@ -342,6 +347,7 @@ export class MajikMessageChat {
342
347
  toJSON() {
343
348
  return {
344
349
  id: this.id,
350
+ conversation_id: this.conversation_id,
345
351
  account: this.account,
346
352
  message: this.message,
347
353
  sender: this.sender,
@@ -356,7 +362,7 @@ export class MajikMessageChat {
356
362
  if (!this.isValidJSON(rawParse)) {
357
363
  throw new Error("Invalid JSON: missing required fields or invalid types");
358
364
  }
359
- return new MajikMessageChat(rawParse.id, rawParse.account, rawParse.message, rawParse.sender, rawParse.recipients || [], rawParse.timestamp, rawParse.expires_at, rawParse.read_by || []);
365
+ return new MajikMessageChat(rawParse.id, rawParse.account, rawParse.message, rawParse.sender, rawParse.recipients || [], rawParse.timestamp, rawParse.expires_at, rawParse.read_by || [], rawParse?.conversation_id);
360
366
  }
361
367
  // ============= REDIS METHODS =============
362
368
  // Generate Redis key
@@ -1,6 +1,7 @@
1
1
  import { MajikMessageAccountID, MajikMessageChatID, MajikMessagePublicKey } from "../../types";
2
2
  export interface MajikMessageChatJSON {
3
3
  id: MajikMessageChatID;
4
+ conversation_id: string;
4
5
  account: MajikMessageAccountID;
5
6
  message: string;
6
7
  sender: MajikMessagePublicKey;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@thezelijah/majik-message",
3
3
  "type": "module",
4
4
  "description": "Encrypt and decrypt messages on any website. Secure chats with keypairs and seed-based accounts. Open source.",
5
- "version": "1.0.12",
5
+ "version": "1.0.13",
6
6
  "license": "Apache-2.0",
7
7
  "author": "Zelijah",
8
8
  "main": "./dist/index.js",