@thezelijah/majik-message 1.0.10 → 1.0.11

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.
@@ -52,6 +52,16 @@ export declare class MajikMessageChat {
52
52
  * @throws Error if validation or compression fails
53
53
  */
54
54
  static create(account: MajikMessageIdentity, message: string, recipients: string[], expiresInMs?: number): Promise<MajikMessageChat>;
55
+ /**
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
59
+ */
60
+ static generateConversationID(message: MajikMessageChatJSON): Promise<string>;
61
+ /**
62
+ * Get all participants for a message (sender + recipients)
63
+ */
64
+ getParticipants(): MajikMessagePublicKey[];
55
65
  isExpired(): boolean;
56
66
  canBeDeleted(): boolean;
57
67
  getReadPercentage(): number;
@@ -1,5 +1,6 @@
1
+ import { hash } from "@stablelib/sha256";
1
2
  import { MajikCompressor } from "../../compressor/majik-compressor";
2
- import { autogenerateID } from "../../utils/utilities";
3
+ import { arrayToBase64, autogenerateID } from "../../utils/utilities";
3
4
  /**
4
5
  * Represents a temporary, compressed message with automatic expiration.
5
6
  * Messages are automatically compressed on creation and stored in Redis by default.
@@ -148,6 +149,40 @@ export class MajikMessageChat {
148
149
  }
149
150
  return new MajikMessageChat(autogenerateID(), accountID, compressedMessage, senderID.trim(), recipients.map((r) => r.trim()).filter((r) => r !== ""), now.toISOString(), expiresAt.toISOString(), []);
150
151
  }
152
+ // ============= STATIC HELPER METHODS =============
153
+ /**
154
+ * Generate a deterministic conversation ID from a message
155
+ * Automatically includes sender and all recipients, normalized by alphabetical order
156
+ * then hashes with SHA-256 and encodes as base64
157
+ */
158
+ static async generateConversationID(message) {
159
+ const parsedMessage = this.fromJSON(message);
160
+ // Get all participants (sender + recipients)
161
+ const participants = new Set();
162
+ participants.add(parsedMessage.getSender());
163
+ parsedMessage.getRecipients().forEach((r) => participants.add(r));
164
+ // Sort alphabetically to ensure same conversation ID regardless of order
165
+ const sorted = Array.from(participants).sort();
166
+ // Join with delimiter
167
+ const combined = sorted.join("|");
168
+ // Convert to bytes
169
+ const encoder = new TextEncoder();
170
+ const data = encoder.encode(combined);
171
+ const hashedID = hash(data);
172
+ const hashBase64 = arrayToBase64(hashedID);
173
+ return `conv_${hashBase64}`;
174
+ }
175
+ /**
176
+ * Get all participants for a message (sender + recipients)
177
+ */
178
+ getParticipants() {
179
+ const participants = new Set();
180
+ // Add sender
181
+ participants.add(this.getSender());
182
+ // Add all recipients
183
+ this.getRecipients().forEach((r) => participants.add(r));
184
+ return Array.from(participants).sort();
185
+ }
151
186
  // ============= EXPIRATION METHODS =============
152
187
  isExpired() {
153
188
  const now = new Date();
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.10",
5
+ "version": "1.0.11",
6
6
  "license": "Apache-2.0",
7
7
  "author": "Zelijah",
8
8
  "main": "./dist/index.js",