@majikah/majik-message 0.1.4 → 0.1.6
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/README.md +2 -2
- package/dist/core/database/thread/mail/majik-message-mail.d.ts +7 -0
- package/dist/core/database/thread/mail/majik-message-mail.js +36 -0
- package/dist/core/database/thread/majik-message-thread.d.ts +8 -6
- package/dist/core/database/thread/majik-message-thread.js +7 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
**Majik Message** is a secure messaging platform built on cryptographic identity. Your account *is* your encryption keys—no phone numbers, no passwords, just your 12-word seed phrase and complete privacy.
|
|
7
7
|
|
|
8
|
-
     [](https://opensource.org/licenses/Apache-2.0) 
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
|
|
@@ -534,7 +534,7 @@ All Majikah products share the same core principles: cryptographic identity, zer
|
|
|
534
534
|
### [Majik Key](https://majikah.solutions/sdk/majik-key)
|
|
535
535
|
**Majik Key** is a seed phrase account library for creating, managing, and parsing mnemonic-based cryptographic accounts (Majik Keys). Generate deterministic key pairs from BIP39 seed phrases with simple, developer-friendly APIs.
|
|
536
536
|
|
|
537
|
-
     [](https://opensource.org/licenses/Apache-2.0) 
|
|
538
538
|
|
|
539
539
|
[Read Docs](https://majikah.solutions/sdk/majik-key/docs)
|
|
540
540
|
[Official Repository](https://github.com/Majikah/majik-key)
|
|
@@ -56,6 +56,7 @@ export declare class MajikMessageMail {
|
|
|
56
56
|
get account(): MajikMessageAccountID;
|
|
57
57
|
get sender(): MajikMessagePublicKey;
|
|
58
58
|
get recipients(): readonly MajikMessagePublicKey[];
|
|
59
|
+
get participants(): readonly MajikMessagePublicKey[];
|
|
59
60
|
get timestamp(): Date;
|
|
60
61
|
get metadata(): Readonly<MailMetadata>;
|
|
61
62
|
get hash(): string;
|
|
@@ -133,6 +134,12 @@ export declare class MajikMessageMail {
|
|
|
133
134
|
* @returns true if successfully marked, false if already read
|
|
134
135
|
*/
|
|
135
136
|
markAsRead(recipientPublicKey: MajikMessagePublicKey): boolean;
|
|
137
|
+
/**
|
|
138
|
+
* Marks this mail as unread by removing a recipient from the read_by list.
|
|
139
|
+
* @param recipientPublicKey - The public key of the recipient marking as unread
|
|
140
|
+
* @returns true if successfully unmarked, false if wasn't read
|
|
141
|
+
*/
|
|
142
|
+
markAsUnread(recipientPublicKey: MajikMessagePublicKey): boolean;
|
|
136
143
|
/**
|
|
137
144
|
* Checks if a specific user has read this mail.
|
|
138
145
|
*/
|
|
@@ -77,6 +77,9 @@ export class MajikMessageMail {
|
|
|
77
77
|
get recipients() {
|
|
78
78
|
return [...this._recipients];
|
|
79
79
|
}
|
|
80
|
+
get participants() {
|
|
81
|
+
return [...this._recipients, this._sender];
|
|
82
|
+
}
|
|
80
83
|
get timestamp() {
|
|
81
84
|
return new Date(this._timestamp);
|
|
82
85
|
}
|
|
@@ -554,6 +557,39 @@ export class MajikMessageMail {
|
|
|
554
557
|
throw new MailOperationError(`Failed to mark as read: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
555
558
|
}
|
|
556
559
|
}
|
|
560
|
+
/**
|
|
561
|
+
* Marks this mail as unread by removing a recipient from the read_by list.
|
|
562
|
+
* @param recipientPublicKey - The public key of the recipient marking as unread
|
|
563
|
+
* @returns true if successfully unmarked, false if wasn't read
|
|
564
|
+
*/
|
|
565
|
+
markAsUnread(recipientPublicKey) {
|
|
566
|
+
try {
|
|
567
|
+
if (!recipientPublicKey ||
|
|
568
|
+
typeof recipientPublicKey !== "string" ||
|
|
569
|
+
recipientPublicKey.trim() === "") {
|
|
570
|
+
throw new MailValidationError("Recipient public key must be a non-empty string");
|
|
571
|
+
}
|
|
572
|
+
const trimmedKey = recipientPublicKey.trim();
|
|
573
|
+
// Verify recipient is in recipients list
|
|
574
|
+
if (!this._recipients.includes(trimmedKey)) {
|
|
575
|
+
throw new MailOperationError(`User ${trimmedKey} is not a recipient of this mail`);
|
|
576
|
+
}
|
|
577
|
+
// Check if not in read_by list (idempotent)
|
|
578
|
+
const readIndex = this._readBy.indexOf(trimmedKey);
|
|
579
|
+
if (readIndex === -1) {
|
|
580
|
+
return false; // Already unread
|
|
581
|
+
}
|
|
582
|
+
// Remove from read_by array
|
|
583
|
+
this._readBy.splice(readIndex, 1);
|
|
584
|
+
return true; // Successfully marked as unread
|
|
585
|
+
}
|
|
586
|
+
catch (error) {
|
|
587
|
+
if (error instanceof MajikMailError) {
|
|
588
|
+
throw error;
|
|
589
|
+
}
|
|
590
|
+
throw new MailOperationError(`Failed to mark as unread: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
557
593
|
/**
|
|
558
594
|
* Checks if a specific user has read this mail.
|
|
559
595
|
*/
|
|
@@ -13,7 +13,7 @@ export interface ThreadMetadata {
|
|
|
13
13
|
messageCount?: number;
|
|
14
14
|
}
|
|
15
15
|
export interface DeletionApproval {
|
|
16
|
-
publicKey:
|
|
16
|
+
publicKey: MajikMessagePublicKey;
|
|
17
17
|
approvalHash: string;
|
|
18
18
|
timestamp: Date;
|
|
19
19
|
}
|
|
@@ -49,6 +49,7 @@ export interface MajikMessageThreadSummary {
|
|
|
49
49
|
unread_count: number;
|
|
50
50
|
has_unread: boolean;
|
|
51
51
|
starred: boolean;
|
|
52
|
+
subject?: string;
|
|
52
53
|
}
|
|
53
54
|
export interface MajikMessageThreadJSON {
|
|
54
55
|
id: MajikMessageThreadID;
|
|
@@ -112,9 +113,10 @@ export declare class MajikMessageThread {
|
|
|
112
113
|
private static generateApprovalHash;
|
|
113
114
|
validate(): boolean;
|
|
114
115
|
close(): void;
|
|
115
|
-
|
|
116
|
+
hasDeletionApproval(publicKey: MajikMessagePublicKey): boolean;
|
|
117
|
+
requestDeletion(publicKey: MajikMessagePublicKey): void;
|
|
116
118
|
private updateDeletionStatus;
|
|
117
|
-
revokeDeletionRequest(publicKey:
|
|
119
|
+
revokeDeletionRequest(publicKey: MajikMessagePublicKey): void;
|
|
118
120
|
canBeDeleted(): boolean;
|
|
119
121
|
getDeletionProgress(): {
|
|
120
122
|
approved: number;
|
|
@@ -137,11 +139,11 @@ export declare class MajikMessageThread {
|
|
|
137
139
|
missingApprovals: string[];
|
|
138
140
|
duplicateApprovals: string[];
|
|
139
141
|
};
|
|
140
|
-
updateMetadata(metadata: Partial<ThreadMetadata>):
|
|
142
|
+
updateMetadata(metadata: Partial<ThreadMetadata>): this;
|
|
141
143
|
toJSON(): MajikMessageThreadJSON;
|
|
142
144
|
static fromJSON(json: MajikMessageThreadJSON | string): MajikMessageThread;
|
|
143
|
-
isOwner(publicKey:
|
|
144
|
-
isParticipant(publicKey:
|
|
145
|
+
isOwner(publicKey: MajikMessagePublicKey): boolean;
|
|
146
|
+
isParticipant(publicKey: MajikMessagePublicKey): boolean;
|
|
145
147
|
toString(): string;
|
|
146
148
|
/**
|
|
147
149
|
* Deduplicates and sorts participants to ensure consistent ordering
|
|
@@ -266,6 +266,11 @@ export class MajikMessageThread {
|
|
|
266
266
|
}
|
|
267
267
|
}
|
|
268
268
|
// ==================== Deletion Approval System ====================
|
|
269
|
+
hasDeletionApproval(publicKey) {
|
|
270
|
+
if (!this.isParticipant(publicKey))
|
|
271
|
+
return false;
|
|
272
|
+
return this._deletionApprovals.some((approval) => approval.publicKey === publicKey);
|
|
273
|
+
}
|
|
269
274
|
requestDeletion(publicKey) {
|
|
270
275
|
try {
|
|
271
276
|
// Validate public key is a participant
|
|
@@ -276,9 +281,7 @@ export class MajikMessageThread {
|
|
|
276
281
|
if (this._status === ThreadStatus.CLOSED) {
|
|
277
282
|
throw new OperationNotAllowedError("Cannot request deletion of a closed thread");
|
|
278
283
|
}
|
|
279
|
-
|
|
280
|
-
const existingApproval = this._deletionApprovals.find((approval) => approval.publicKey === publicKey);
|
|
281
|
-
if (existingApproval) {
|
|
284
|
+
if (this.hasDeletionApproval(publicKey)) {
|
|
282
285
|
throw new OperationNotAllowedError("This participant has already approved deletion");
|
|
283
286
|
}
|
|
284
287
|
// Create approval
|
|
@@ -451,6 +454,7 @@ export class MajikMessageThread {
|
|
|
451
454
|
...metadata,
|
|
452
455
|
lastActivity: new Date().toISOString(),
|
|
453
456
|
};
|
|
457
|
+
return this;
|
|
454
458
|
}
|
|
455
459
|
catch (error) {
|
|
456
460
|
if (error instanceof MajikThreadError) {
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@majikah/majik-message",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"description": "Encrypt and decrypt messages on any website or platform. Secure chats with keypairs and seed-based accounts. Open source.",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.6",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"author": "Zelijah",
|
|
8
8
|
"main": "./dist/index.js",
|