@thezelijah/majik-message 1.1.1 → 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.
@@ -7,12 +7,13 @@ import { EnvelopeCache, } from "./core/messages/envelope-cache";
7
7
  import { EncryptionEngine } from "./core/crypto/encryption-engine";
8
8
  import { KeyStore } from "./core/crypto/keystore";
9
9
  import { MajikContactDirectory, } from "./core/contacts/majik-contact-directory";
10
- import { arrayBufferToBase64, arrayToBase64, base64ToArrayBuffer, base64ToUtf8, utf8ToBase64, } from "./core/utils/utilities";
10
+ import { arrayBufferToBase64, arrayToBase64, base64ToArrayBuffer, base64ToUtf8, seedStringToArray, utf8ToBase64, } from "./core/utils/utilities";
11
11
  import { autoSaveMajikFileData, loadSavedMajikFileData, } from "./core/utils/majik-file-utils";
12
12
  import { randomBytes } from "@stablelib/random";
13
13
  import { clearAllBlobs, idbLoadBlob, idbSaveBlob, } from "./core/utils/idb-majik-system";
14
14
  import { MajikMessageChat } from "./core/database/chat/majik-message-chat";
15
15
  import { MajikCompressor } from "./core/compressor/majik-compressor";
16
+ import { MajikKey } from "@thezelijah/majik-key";
16
17
  export class MajikMessage {
17
18
  userProfile = "default";
18
19
  // Optional PIN protection (hashed). If set, UI should prompt for PIN to unlock.
@@ -114,37 +115,38 @@ export class MajikMessage {
114
115
  * Import an account from a mnemonic-encrypted backup blob and store it using `passphrase`.
115
116
  */
116
117
  async importAccountFromMnemonicBackup(backupBase64, mnemonic, passphrase, label) {
117
- const identity = await KeyStore.importIdentityFromMnemonicBackup(backupBase64, mnemonic, passphrase);
118
- const contact = new MajikContact({
119
- id: identity.id,
120
- publicKey: identity.publicKey,
121
- fingerprint: identity.fingerprint,
122
- meta: { label: label || "" },
123
- });
124
- if (!!this.getOwnAccountById(identity.id)) {
118
+ const mJSON = {
119
+ id: backupBase64,
120
+ seed: seedStringToArray(mnemonic),
121
+ phrase: passphrase,
122
+ };
123
+ const importedIdentity = await MajikKey.fromMnemonicJSON(mJSON, passphrase, label);
124
+ await KeyStore.addMajikKey(importedIdentity);
125
+ const accountContact = await importedIdentity.toContact().toJSON();
126
+ const contact = MajikContact.fromJSON(accountContact);
127
+ if (!!this.getOwnAccountById(importedIdentity.id)) {
125
128
  throw new Error("Account with the same ID already exists");
126
129
  }
127
130
  this.addOwnAccount(contact);
128
- return { id: identity.id, fingerprint: identity.fingerprint };
131
+ return {
132
+ id: importedIdentity.id,
133
+ fingerprint: importedIdentity.fingerprint,
134
+ };
129
135
  }
130
136
  /**
131
137
  * Create a new account deterministically from `mnemonic` and store it encrypted with `passphrase`.
132
138
  * Returns the created identity id (which equals fingerprint) and fingerprint.
133
139
  */
134
140
  async createAccountFromMnemonic(mnemonic, passphrase, label) {
135
- const identity = await KeyStore.createIdentityFromMnemonic(mnemonic, passphrase);
136
- const contact = new MajikContact({
137
- id: identity.id,
138
- publicKey: identity.publicKey,
139
- fingerprint: identity.fingerprint,
140
- meta: { label: label || "" },
141
- });
142
- const backup = await KeyStore.exportIdentityMnemonicBackup(identity.id, mnemonic);
141
+ const newAccount = await MajikKey.create(mnemonic, passphrase, label);
142
+ await KeyStore.addMajikKey(newAccount);
143
+ const accountContact = await newAccount.toContact().toJSON();
144
+ const contact = MajikContact.fromJSON(accountContact);
143
145
  this.addOwnAccount(contact);
144
146
  return {
145
- id: identity.id,
146
- fingerprint: identity.fingerprint,
147
- backup: backup,
147
+ id: newAccount.id,
148
+ fingerprint: newAccount.fingerprint,
149
+ backup: newAccount.backup,
148
150
  };
149
151
  }
150
152
  addOwnAccount(account) {
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.1",
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",
@@ -84,6 +88,7 @@
84
88
  "@stablelib/random": "^2.0.1",
85
89
  "@stablelib/sha256": "^2.0.1",
86
90
  "@stablelib/x25519": "^2.0.1",
91
+ "@thezelijah/majik-key": "^1.0.5",
87
92
  "@thezelijah/majik-user": "^1.0.0",
88
93
  "ed2curve": "^0.3.0",
89
94
  "fernet": "^0.3.3",
@@ -1,44 +0,0 @@
1
- /**
2
- * Target gender brackets for the audience.
3
- */
4
- export declare const UserGenderOptions: {
5
- readonly MALE: "Male";
6
- readonly FEMALE: "Female";
7
- readonly OTHER: "Other";
8
- };
9
- export type UserGenderOptions = (typeof UserGenderOptions)[keyof typeof UserGenderOptions];
10
- /**
11
- * Enum representing different types of social media platforms.
12
- */
13
- export declare const SocialLinkType: {
14
- readonly FACEBOOK: "Facebook";
15
- readonly X: "X";
16
- readonly TIKTOK: "Tik-Tok";
17
- readonly THREADS: "Threads";
18
- readonly INSTAGRAM: "Instagram";
19
- readonly YOUTUBE: "Youtube";
20
- readonly SPOTIFY: "Spotify";
21
- readonly APPLE_MUSIC: "Apple Music";
22
- readonly LINKEDIN: "LinkedIn";
23
- readonly WEBSITE: "Website URL";
24
- };
25
- export type SocialLinkType = (typeof SocialLinkType)[keyof typeof SocialLinkType];
26
- /** Payment methods accepted for the invoice */
27
- export declare const PaymentMethod: {
28
- /** Payment is made in cash */
29
- readonly CASH: "Cash";
30
- /** Payment is made via bank transfer or deposit */
31
- readonly BANK: "Bank";
32
- /** Payment is made via e-wallet transfer */
33
- readonly EWALLET: "E-Wallet";
34
- /** Payment is made using a check */
35
- readonly CHECK: "Check";
36
- };
37
- export type PaymentMethod = (typeof PaymentMethod)[keyof typeof PaymentMethod];
38
- export declare const Visibility: {
39
- readonly PRIVATE: "Private";
40
- readonly PUBLIC: "Public";
41
- readonly LIMITED: "Limited";
42
- readonly UNLISTED: "Unlisted";
43
- };
44
- export type Visibility = (typeof Visibility)[keyof typeof Visibility];
@@ -1,40 +0,0 @@
1
- /**
2
- * Target gender brackets for the audience.
3
- */
4
- export const UserGenderOptions = {
5
- MALE: 'Male',
6
- FEMALE: 'Female',
7
- OTHER: 'Other'
8
- };
9
- /**
10
- * Enum representing different types of social media platforms.
11
- */
12
- export const SocialLinkType = {
13
- FACEBOOK: 'Facebook',
14
- X: 'X',
15
- TIKTOK: 'Tik-Tok',
16
- THREADS: 'Threads',
17
- INSTAGRAM: 'Instagram',
18
- YOUTUBE: 'Youtube',
19
- SPOTIFY: 'Spotify',
20
- APPLE_MUSIC: 'Apple Music',
21
- LINKEDIN: 'LinkedIn',
22
- WEBSITE: 'Website URL'
23
- };
24
- /** Payment methods accepted for the invoice */
25
- export const PaymentMethod = {
26
- /** Payment is made in cash */
27
- CASH: 'Cash',
28
- /** Payment is made via bank transfer or deposit */
29
- BANK: 'Bank',
30
- /** Payment is made via e-wallet transfer */
31
- EWALLET: 'E-Wallet',
32
- /** Payment is made using a check */
33
- CHECK: 'Check'
34
- };
35
- export const Visibility = {
36
- PRIVATE: 'Private',
37
- PUBLIC: 'Public',
38
- LIMITED: 'Limited',
39
- UNLISTED: 'Unlisted'
40
- };
@@ -1,261 +0,0 @@
1
- import type { UserBasicInformation, FullName, Address, UserSettings, MajikUserJSON, SupabaseUser, YYYYMMDD } from "./types";
2
- import type { UserGenderOptions } from "./enums";
3
- export interface MajikUserData<TMetadata extends UserBasicInformation = UserBasicInformation> {
4
- id: string;
5
- email: string;
6
- displayName: string;
7
- hash: string;
8
- metadata: TMetadata;
9
- settings: UserSettings;
10
- createdAt: Date;
11
- lastUpdate: Date;
12
- }
13
- /**
14
- * Base user class for database persistence
15
- * Designed to be extended by subclasses with additional metadata
16
- */
17
- export declare class MajikUser<TMetadata extends UserBasicInformation = UserBasicInformation> {
18
- readonly id: string;
19
- protected _email: string;
20
- protected _displayName: string;
21
- protected _hash: string;
22
- protected _metadata: TMetadata;
23
- protected _settings: UserSettings;
24
- readonly createdAt: Date;
25
- protected _lastUpdate: Date;
26
- constructor(data: MajikUserData<TMetadata>);
27
- /**
28
- * Initialize a new user with email and display name
29
- * Generates a UUID for the id if unset and sets timestamps
30
- */
31
- static initialize<T extends MajikUser>(this: new (data: MajikUserData<any>) => T, email: string, displayName: string, id?: string): T;
32
- /**
33
- * Deserialize user from JSON object or JSON string
34
- */
35
- static fromJSON<T extends MajikUser>(this: new (data: MajikUserData<any>) => T, json: MajikUserJSON<any> | string): T;
36
- /**
37
- * Create MajikUser from Supabase User object
38
- * Maps Supabase user fields to MajikUser structure
39
- */
40
- static fromSupabase<T extends MajikUser>(this: new (data: MajikUserData<any>) => T, supabaseUser: SupabaseUser): T;
41
- get email(): string;
42
- get displayName(): string;
43
- get hash(): string;
44
- get metadata(): Readonly<TMetadata>;
45
- get settings(): Readonly<UserSettings>;
46
- get lastUpdate(): Date;
47
- /**
48
- * Get user's full name if available
49
- */
50
- get fullName(): string | null;
51
- get fullNameObject(): FullName | null;
52
- set fullNameObject(name: FullName);
53
- /**
54
- * Get user's formatted name (first + last)
55
- */
56
- get formattedName(): string;
57
- /**
58
- * Get user's first name if available
59
- */
60
- get firstName(): string | null;
61
- /**
62
- * Get user's last name if available
63
- */
64
- get lastName(): string | null;
65
- /**
66
- * Get user's gender
67
- */
68
- get gender(): string;
69
- /**
70
- * Calculate user's age from birthdate
71
- */
72
- get age(): number | null;
73
- /**
74
- * Get user's first name if available
75
- */
76
- get birthday(): YYYYMMDD | null;
77
- /**
78
- * Get user's full address if available
79
- */
80
- get address(): string | null;
81
- /**
82
- * Check if email is verified
83
- */
84
- get isEmailVerified(): boolean;
85
- /**
86
- * Check if phone is verified
87
- */
88
- get isPhoneVerified(): boolean;
89
- /**
90
- * Check if identity is verified
91
- */
92
- get isIdentityVerified(): boolean;
93
- /**
94
- * Check if all verification steps are complete
95
- */
96
- get isFullyVerified(): boolean;
97
- /**
98
- * Get user's initials from name or display name
99
- */
100
- get initials(): string;
101
- set email(value: string);
102
- set displayName(value: string);
103
- set hash(value: string);
104
- /**
105
- * Update user's full name
106
- */
107
- setName(name: FullName): void;
108
- /**
109
- * Update user's profile picture
110
- */
111
- setPicture(url: string): void;
112
- /**
113
- * Update user's phone number
114
- */
115
- setPhone(phone: string): void;
116
- /**
117
- * Update user's address
118
- */
119
- setAddress(address: Address): void;
120
- /**
121
- * Update user's birthdate
122
- * Accepts either YYYY-MM-DD string or Date object
123
- */
124
- setBirthdate(birthdate: YYYYMMDD | Date): void;
125
- /**
126
- * Update user's address
127
- */
128
- setGender(gender: UserGenderOptions): void;
129
- /**
130
- * Update user's bio
131
- */
132
- setBio(bio: string): void;
133
- /**
134
- * Update user's language preference
135
- */
136
- setLanguage(language: string): void;
137
- /**
138
- * Update user's timezone
139
- */
140
- setTimezone(timezone: string): void;
141
- /**
142
- * Add or update a social link
143
- */
144
- setSocialLink(platform: string, url: string): void;
145
- /**
146
- * Remove a social link
147
- */
148
- removeSocialLink(platform: string): void;
149
- /**
150
- * Update a specific metadata field
151
- */
152
- setMetadata(key: keyof TMetadata, value: TMetadata[typeof key]): void;
153
- /**
154
- * Merge multiple metadata fields
155
- */
156
- updateMetadata(updates: Partial<TMetadata>): void;
157
- /**
158
- * Mark email as verified
159
- */
160
- verifyEmail(): void;
161
- /**
162
- * Mark email as unverified
163
- */
164
- unverifyEmail(): void;
165
- /**
166
- * Mark phone as verified
167
- */
168
- verifyPhone(): void;
169
- /**
170
- * Mark phone as unverified
171
- */
172
- unverifyPhone(): void;
173
- /**
174
- * Mark identity as verified (KYC)
175
- */
176
- verifyIdentity(): void;
177
- /**
178
- * Mark identity as unverified
179
- */
180
- unverifyIdentity(): void;
181
- /**
182
- * Update a specific setting
183
- */
184
- setSetting(key: string, value: unknown): void;
185
- /**
186
- * Merge multiple settings
187
- */
188
- updateSettings(updates: Partial<UserSettings>): void;
189
- /**
190
- * Enable notifications
191
- */
192
- enableNotifications(): void;
193
- /**
194
- * Disable notifications
195
- */
196
- disableNotifications(): void;
197
- /**
198
- * Check if user is currently restricted
199
- */
200
- isCurrentlyRestricted(): boolean;
201
- /**
202
- * Restrict user until a specific date (or indefinitely)
203
- */
204
- restrict(until?: Date): void;
205
- /**
206
- * Remove restriction from user
207
- */
208
- unrestrict(): void;
209
- /**
210
- * Check if this user has the same ID as another user
211
- */
212
- equals(other: MajikUser): boolean;
213
- /**
214
- * Check if user has complete profile information
215
- */
216
- hasCompleteProfile(): boolean;
217
- /**
218
- * Get profile completion percentage (0-100)
219
- */
220
- getProfileCompletionPercentage(): number;
221
- validate(): {
222
- isValid: boolean;
223
- errors: string[];
224
- };
225
- /**
226
- * Create a shallow clone of the user
227
- */
228
- clone(): MajikUser<TMetadata>;
229
- /**
230
- * Get a supabase ready version of user data (metadata)
231
- */
232
- toSupabaseJSON(): Record<string, unknown>;
233
- /**
234
- * Get a sanitized version of user data (removes sensitive info)
235
- */
236
- toPublicJSON(): Record<string, unknown>;
237
- /**
238
- * Serialize user to JSON-compatible object
239
- */
240
- toJSON(): MajikUserJSON<TMetadata>;
241
- /**
242
- * Updates the lastUpdate timestamp
243
- */
244
- protected updateTimestamp(): void;
245
- /**
246
- * Validates email format
247
- */
248
- protected validateEmail(email: string): void;
249
- /**
250
- * Generate a cryptographically secure unique identifier
251
- */
252
- protected static generateID(): string;
253
- /**
254
- * Validate ID format
255
- */
256
- protected static validateID(id: string): boolean;
257
- /**
258
- * Hash an ID using SHA-256
259
- */
260
- protected static hashID(id: string): string;
261
- }