@thezelijah/majik-message 1.1.2 → 1.1.3

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.
@@ -57,7 +57,6 @@ export function deriveKeyFromMnemonic(mnemonic, salt, iterations = 200000, keyLe
57
57
  return deriveKey(SHA256, m, salt, iterations, keyLen);
58
58
  }
59
59
  export function x25519SharedSecret(privRaw, pubRaw) {
60
- // Use @stablelib/x25519 for scalar multiplication / shared secret
61
60
  const priv = new Uint8Array(privRaw);
62
61
  const pub = new Uint8Array(pubRaw);
63
62
  if (x25519.scalarMult) {
@@ -1,6 +1,8 @@
1
1
  import { ThreadStatus } from "./enums";
2
- import { ISODateString, MajikMessagePublicKey, MajikMessageThreadID } from "../../types";
2
+ import { ISODateString, MajikMessageAccountID, MajikMessagePublicKey, MajikMessageThreadID } from "../../types";
3
3
  import { MajikUserID } from "@thezelijah/majik-user";
4
+ import { MajikMessageMailJSON } from "./mail/majik-message-mail";
5
+ import { MajikMessageIdentity } from "../system/identity";
4
6
  export interface ThreadMetadata {
5
7
  title?: string;
6
8
  subject?: string;
@@ -17,7 +19,7 @@ export interface DeletionApproval {
17
19
  }
18
20
  export interface MajikMessageThreadAnalytics {
19
21
  threadID: MajikMessageThreadID;
20
- owner: string;
22
+ owner: MajikMessageAccountID;
21
23
  userID: MajikUserID;
22
24
  participantCount: number;
23
25
  messageCount: number;
@@ -28,6 +30,7 @@ export interface MajikMessageThreadAnalytics {
28
30
  tags: string[];
29
31
  category: string | undefined;
30
32
  priority: string | undefined;
33
+ starred: boolean;
31
34
  deletionStatus: {
32
35
  isPendingDeletion: boolean;
33
36
  isMarkedForDeletion: boolean;
@@ -36,16 +39,28 @@ export interface MajikMessageThreadAnalytics {
36
39
  totalParticipants: number;
37
40
  };
38
41
  }
42
+ export interface MajikMessageThreadSummary {
43
+ id: MajikMessageThreadID;
44
+ participants: MajikMessagePublicKey[];
45
+ participant_count: number;
46
+ latest_message: MajikMessageMailJSON;
47
+ latest_message_timestamp: ISODateString;
48
+ total_messages: number;
49
+ unread_count: number;
50
+ has_unread: boolean;
51
+ starred: boolean;
52
+ }
39
53
  export interface MajikMessageThreadJSON {
40
54
  id: MajikMessageThreadID;
41
- user_id: string;
42
- owner: MajikMessagePublicKey;
55
+ user_id: MajikUserID;
56
+ owner: MajikMessageAccountID;
43
57
  metadata: ThreadMetadata;
44
58
  timestamp: ISODateString;
45
59
  participants: string[];
46
60
  status: ThreadStatus;
47
61
  hash: string;
48
- deletion_approvals?: DeletionApproval[];
62
+ deletion_approvals: DeletionApproval[];
63
+ starred: boolean;
49
64
  }
50
65
  export declare class MajikThreadError extends Error {
51
66
  code: string;
@@ -67,6 +82,7 @@ export declare class MajikMessageThread {
67
82
  private _status;
68
83
  private readonly _hash;
69
84
  private _deletionApprovals;
85
+ private _starred;
70
86
  private constructor();
71
87
  get id(): MajikMessageThreadID;
72
88
  get userID(): MajikUserID;
@@ -77,7 +93,21 @@ export declare class MajikMessageThread {
77
93
  get status(): ThreadStatus;
78
94
  get hash(): string;
79
95
  get deletionApprovals(): readonly DeletionApproval[];
80
- static create(userID: MajikUserID, owner: MajikMessagePublicKey, participants: MajikMessagePublicKey[], metadata?: ThreadMetadata): MajikMessageThread;
96
+ get starred(): boolean;
97
+ static create(userID: MajikUserID, owner: MajikMessageIdentity, participants: MajikMessagePublicKey[], metadata?: ThreadMetadata): MajikMessageThread;
98
+ /**
99
+ * Stars the thread for the user
100
+ */
101
+ star(): void;
102
+ /**
103
+ * Unstars the thread for the user
104
+ */
105
+ unstar(): void;
106
+ /**
107
+ * Toggles the starred status of the thread
108
+ * @returns The new starred state
109
+ */
110
+ toggleStar(): boolean;
81
111
  private static generateHash;
82
112
  private static generateApprovalHash;
83
113
  validate(): boolean;
@@ -1,5 +1,4 @@
1
1
  import { v4 as uuidv4 } from "uuid";
2
- import * as crypto from "crypto";
3
2
  import { ThreadStatus } from "./enums";
4
3
  import { sha256 } from "../../crypto/crypto-provider";
5
4
  // ==================== Custom Errors ====================
@@ -27,15 +26,16 @@ export class OperationNotAllowedError extends MajikThreadError {
27
26
  export class MajikMessageThread {
28
27
  _id;
29
28
  _userID;
30
- _owner; // Owner's public key
29
+ _owner; // Owner's identity account ID
31
30
  _metadata;
32
31
  _timestamp;
33
32
  _participants;
34
33
  _status;
35
34
  _hash;
36
35
  _deletionApprovals;
36
+ _starred;
37
37
  // ==================== Private Constructor ====================
38
- constructor(id, userID, owner, metadata, timestamp, participants, status, hash, deletionApprovals = []) {
38
+ constructor(id, userID, owner, metadata, timestamp, participants, status, hash, deletionApprovals = [], starred = false) {
39
39
  this._id = id;
40
40
  this._userID = userID;
41
41
  this._owner = owner;
@@ -45,6 +45,7 @@ export class MajikMessageThread {
45
45
  this._status = status;
46
46
  this._hash = hash;
47
47
  this._deletionApprovals = deletionApprovals;
48
+ this._starred = starred;
48
49
  // Validate on construction
49
50
  this.validate();
50
51
  }
@@ -76,6 +77,9 @@ export class MajikMessageThread {
76
77
  get deletionApprovals() {
77
78
  return [...this._deletionApprovals];
78
79
  }
80
+ get starred() {
81
+ return this._starred;
82
+ }
79
83
  // ==================== Static Create Method ====================
80
84
  static create(userID, owner, participants, metadata = {}) {
81
85
  try {
@@ -88,7 +92,7 @@ export class MajikMessageThread {
88
92
  }
89
93
  // Normalize participants (deduplicate + sort)
90
94
  const uniqueParticipants = MajikMessageThread.normalizeParticipants([
91
- owner,
95
+ owner.publicKey,
92
96
  ...participants,
93
97
  ]);
94
98
  // Validate all participants
@@ -104,7 +108,7 @@ export class MajikMessageThread {
104
108
  const status = ThreadStatus.ONGOING;
105
109
  // Generate hash
106
110
  const hash = MajikMessageThread.generateHash(userID, timestamp, id, uniqueParticipants);
107
- return new MajikMessageThread(id, userID, owner, metadata, timestamp, uniqueParticipants, status, hash, []);
111
+ return new MajikMessageThread(id, userID, owner.id, metadata, timestamp, uniqueParticipants, status, hash, []);
108
112
  }
109
113
  catch (error) {
110
114
  if (error instanceof MajikThreadError) {
@@ -113,6 +117,54 @@ export class MajikMessageThread {
113
117
  throw new MajikThreadError(`Failed to create MajikMessageThread: ${error instanceof Error ? error.message : "Unknown error"}`, "CREATE_FAILED");
114
118
  }
115
119
  }
120
+ // ==================== Star Management ====================
121
+ /**
122
+ * Stars the thread for the user
123
+ */
124
+ star() {
125
+ try {
126
+ if (this._starred) {
127
+ throw new OperationNotAllowedError("Thread is already starred");
128
+ }
129
+ this._starred = true;
130
+ }
131
+ catch (error) {
132
+ if (error instanceof MajikThreadError) {
133
+ throw error;
134
+ }
135
+ throw new MajikThreadError(`Failed to star thread: ${error instanceof Error ? error.message : "Unknown error"}`, "STAR_FAILED");
136
+ }
137
+ }
138
+ /**
139
+ * Unstars the thread for the user
140
+ */
141
+ unstar() {
142
+ try {
143
+ if (!this._starred) {
144
+ throw new OperationNotAllowedError("Thread is not starred");
145
+ }
146
+ this._starred = false;
147
+ }
148
+ catch (error) {
149
+ if (error instanceof MajikThreadError) {
150
+ throw error;
151
+ }
152
+ throw new MajikThreadError(`Failed to unstar thread: ${error instanceof Error ? error.message : "Unknown error"}`, "UNSTAR_FAILED");
153
+ }
154
+ }
155
+ /**
156
+ * Toggles the starred status of the thread
157
+ * @returns The new starred state
158
+ */
159
+ toggleStar() {
160
+ if (this._starred) {
161
+ this.unstar();
162
+ }
163
+ else {
164
+ this.star();
165
+ }
166
+ return this._starred;
167
+ }
116
168
  // ==================== Hash Generation ====================
117
169
  static generateHash(userID, timestamp, id, participants) {
118
170
  // Normalize participants (they should already be normalized, but ensure consistency)
@@ -124,7 +176,7 @@ export class MajikMessageThread {
124
176
  }
125
177
  static generateApprovalHash(publicKey, threadID, timestamp) {
126
178
  const dataString = `${publicKey}:${threadID}:${timestamp.toISOString()}`;
127
- return crypto.createHash("sha256").update(dataString).digest("hex");
179
+ return sha256(dataString);
128
180
  }
129
181
  // ==================== Validation ====================
130
182
  validate() {
@@ -422,10 +474,13 @@ export class MajikMessageThread {
422
474
  participants: [...this._participants],
423
475
  status: this._status,
424
476
  hash: this._hash,
425
- deletion_approvals: this._deletionApprovals.map((approval) => ({
426
- ...approval,
427
- timestamp: approval.timestamp,
428
- })),
477
+ deletion_approvals: this._deletionApprovals.length > 0
478
+ ? this._deletionApprovals.map((approval) => ({
479
+ ...approval,
480
+ timestamp: approval.timestamp,
481
+ }))
482
+ : [],
483
+ starred: this._starred,
429
484
  };
430
485
  }
431
486
  static fromJSON(json) {
@@ -441,7 +496,7 @@ export class MajikMessageThread {
441
496
  ...approval,
442
497
  timestamp: new Date(approval.timestamp),
443
498
  }));
444
- return new MajikMessageThread(data.id, data.user_id, data.owner, data.metadata, timestamp, data.participants, data.status, data.hash, deletionApprovals);
499
+ return new MajikMessageThread(data.id, data.user_id, data.owner, data.metadata, timestamp, data.participants, data.status, data.hash, deletionApprovals, data.starred);
445
500
  }
446
501
  catch (error) {
447
502
  if (error instanceof MajikThreadError) {
@@ -527,6 +582,7 @@ export class MajikMessageThread {
527
582
  ...approval,
528
583
  timestamp: approval.timestamp,
529
584
  })),
585
+ starred: this._starred,
530
586
  };
531
587
  // If we're auto-closing and status changed, actually update the instance
532
588
  if (autoClose &&
@@ -575,6 +631,7 @@ export class MajikMessageThread {
575
631
  approvedCount: this._deletionApprovals.length,
576
632
  totalParticipants: this._participants.length,
577
633
  },
634
+ starred: this._starred,
578
635
  };
579
636
  }
580
637
  }
package/dist/index.d.ts CHANGED
@@ -15,3 +15,6 @@ export * from "./core/database/chat/majik-message-chat";
15
15
  export type * from "./core/database/chat/types";
16
16
  export * from "./core/database/system/identity";
17
17
  export * from "./core/compressor/majik-compressor";
18
+ export * from "./core/database/thread/majik-message-thread";
19
+ export * from "./core/database/thread/mail/majik-message-mail";
20
+ export * from "./core/database/thread/enums";
package/dist/index.js CHANGED
@@ -13,3 +13,6 @@ export * from "./core/utils/utilities";
13
13
  export * from "./core/database/chat/majik-message-chat";
14
14
  export * from "./core/database/system/identity";
15
15
  export * from "./core/compressor/majik-compressor";
16
+ export * from "./core/database/thread/majik-message-thread";
17
+ export * from "./core/database/thread/mail/majik-message-mail";
18
+ export * from "./core/database/thread/enums";
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.1.2",
5
+ "version": "1.1.3",
6
6
  "license": "Apache-2.0",
7
7
  "author": "Zelijah",
8
8
  "main": "./dist/index.js",
@@ -15,6 +15,10 @@
15
15
  "type": "git",
16
16
  "url": "git+https://github.com/jedlsf/majik-message.git"
17
17
  },
18
+ "funding": {
19
+ "type": "github",
20
+ "url": "https://github.com/sponsors/jedlsf"
21
+ },
18
22
  "keywords": [
19
23
  "majik",
20
24
  "majik-message",