shogun-core 2.0.4 → 3.0.1
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 +150 -19
- package/dist/browser/shogun-core.js +3849 -2213
- package/dist/browser/shogun-core.js.map +1 -1
- package/dist/config/simplified-config.js +230 -0
- package/dist/core.js +50 -572
- package/dist/gundb/db.js +470 -238
- package/dist/gundb/index.js +4 -0
- package/dist/gundb/simple-api.js +438 -0
- package/dist/index.js +7 -1
- package/dist/managers/AuthManager.js +225 -0
- package/dist/managers/CoreInitializer.js +234 -0
- package/dist/managers/EventManager.js +67 -0
- package/dist/managers/PluginManager.js +296 -0
- package/dist/migration-test.js +91 -0
- package/dist/plugins/nostr/nostrConnectorPlugin.js +1 -1
- package/dist/plugins/oauth/oauthPlugin.js +1 -1
- package/dist/plugins/webauthn/webauthnPlugin.js +1 -1
- package/dist/types/config/simplified-config.d.ts +114 -0
- package/dist/types/core.d.ts +13 -42
- package/dist/types/gundb/db.d.ts +91 -13
- package/dist/types/gundb/index.d.ts +2 -0
- package/dist/types/gundb/rxjs.d.ts +3 -3
- package/dist/types/gundb/simple-api.d.ts +90 -0
- package/dist/types/gundb/types.d.ts +107 -1
- package/dist/types/index.d.ts +4 -2
- package/dist/types/interfaces/plugin.d.ts +105 -1
- package/dist/types/interfaces/shogun.d.ts +22 -16
- package/dist/types/managers/AuthManager.d.ts +72 -0
- package/dist/types/managers/CoreInitializer.d.ts +40 -0
- package/dist/types/managers/EventManager.d.ts +49 -0
- package/dist/types/managers/PluginManager.d.ts +145 -0
- package/dist/types/migration-test.d.ts +16 -0
- package/package.json +1 -1
package/dist/gundb/index.js
CHANGED
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simplified API layer to reduce complexity for common use cases
|
|
3
|
+
* Provides quick-start methods that wrap the full DataBase functionality
|
|
4
|
+
*/
|
|
5
|
+
import { DataBase } from "./db";
|
|
6
|
+
/**
|
|
7
|
+
* Simple API wrapper that provides common operations with minimal complexity
|
|
8
|
+
*/
|
|
9
|
+
export class SimpleGunAPI {
|
|
10
|
+
db;
|
|
11
|
+
constructor(db) {
|
|
12
|
+
this.db = db;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Quick data operations - simplified interface
|
|
16
|
+
*/
|
|
17
|
+
// Simple get - returns data directly or null
|
|
18
|
+
async get(path) {
|
|
19
|
+
try {
|
|
20
|
+
const result = await this.db.getData(path);
|
|
21
|
+
return result;
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
console.warn(`Failed to get data from ${path}:`, error);
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Simple put - returns success boolean
|
|
29
|
+
async put(path, data) {
|
|
30
|
+
try {
|
|
31
|
+
const result = await this.db.put(path, data);
|
|
32
|
+
return result.success;
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
console.warn(`Failed to put data to ${path}:`, error);
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Simple set - returns success boolean
|
|
40
|
+
async set(path, data) {
|
|
41
|
+
try {
|
|
42
|
+
const result = await this.db.set(path, data);
|
|
43
|
+
return result.success;
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
console.warn(`Failed to set data to ${path}:`, error);
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Simple remove - returns success boolean
|
|
51
|
+
async remove(path) {
|
|
52
|
+
try {
|
|
53
|
+
const result = await this.db.remove(path);
|
|
54
|
+
return result.success;
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
console.warn(`Failed to remove data from ${path}:`, error);
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Quick authentication - simplified interface
|
|
63
|
+
*/
|
|
64
|
+
// Simple login - returns user info or null
|
|
65
|
+
async login(username, password) {
|
|
66
|
+
try {
|
|
67
|
+
const result = await this.db.login(username, password);
|
|
68
|
+
if (result.success && result.userPub) {
|
|
69
|
+
return {
|
|
70
|
+
userPub: result.userPub,
|
|
71
|
+
username: result.username || username,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
console.warn(`Login failed for ${username}:`, error);
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// Simple signup - returns user info or null
|
|
82
|
+
async signup(username, password) {
|
|
83
|
+
try {
|
|
84
|
+
const result = await this.db.signUp(username, password);
|
|
85
|
+
if (result.success && result.userPub) {
|
|
86
|
+
return {
|
|
87
|
+
userPub: result.userPub,
|
|
88
|
+
username: result.username || username,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
console.warn(`Signup failed for ${username}:`, error);
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Simple logout
|
|
99
|
+
logout() {
|
|
100
|
+
this.db.logout();
|
|
101
|
+
}
|
|
102
|
+
// Simple check if logged in
|
|
103
|
+
isLoggedIn() {
|
|
104
|
+
return this.db.isLoggedIn();
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Quick user data operations - simplified interface
|
|
108
|
+
*/
|
|
109
|
+
// Simple user data get
|
|
110
|
+
async getUserData(path) {
|
|
111
|
+
try {
|
|
112
|
+
if (!this.isLoggedIn()) {
|
|
113
|
+
console.warn("User not logged in");
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
return (await this.db.getUserData(path));
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
console.warn(`Failed to get user data from ${path}:`, error);
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Simple user data put
|
|
124
|
+
async putUserData(path, data) {
|
|
125
|
+
try {
|
|
126
|
+
if (!this.isLoggedIn()) {
|
|
127
|
+
console.warn("User not logged in");
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
await this.db.putUserData(path, data);
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
console.warn(`Failed to put user data to ${path}:`, error);
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Simple user data set (alternative to put)
|
|
139
|
+
async setUserData(path, data) {
|
|
140
|
+
try {
|
|
141
|
+
if (!this.isLoggedIn()) {
|
|
142
|
+
console.warn("User not logged in");
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
// Use the user's gun instance directly for set operations
|
|
146
|
+
const user = this.db.getUser();
|
|
147
|
+
if (user && user.is) {
|
|
148
|
+
await new Promise((resolve, reject) => {
|
|
149
|
+
user.get(path).set(data, (ack) => {
|
|
150
|
+
if (ack.err) {
|
|
151
|
+
reject(new Error(ack.err));
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
resolve();
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
console.warn(`Failed to set user data to ${path}:`, error);
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// Simple user data remove
|
|
168
|
+
async removeUserData(path) {
|
|
169
|
+
try {
|
|
170
|
+
if (!this.isLoggedIn()) {
|
|
171
|
+
console.warn("User not logged in");
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
const user = this.db.getUser();
|
|
175
|
+
if (user && user.is) {
|
|
176
|
+
await new Promise((resolve, reject) => {
|
|
177
|
+
user.get(path).put(null, (ack) => {
|
|
178
|
+
if (ack.err) {
|
|
179
|
+
reject(new Error(ack.err));
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
resolve();
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
console.warn(`Failed to remove user data from ${path}:`, error);
|
|
192
|
+
return false;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Quick utility methods
|
|
197
|
+
*/
|
|
198
|
+
// Get current user info
|
|
199
|
+
getCurrentUser() {
|
|
200
|
+
const user = this.db.getCurrentUser();
|
|
201
|
+
if (user) {
|
|
202
|
+
return {
|
|
203
|
+
pub: user.pub,
|
|
204
|
+
username: user.username,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
// Check if user exists by alias
|
|
210
|
+
async userExists(alias) {
|
|
211
|
+
try {
|
|
212
|
+
const user = await this.db.getUserByAlias(alias);
|
|
213
|
+
return user !== null;
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
console.warn(`Failed to check if user exists: ${alias}`, error);
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// Get user by alias
|
|
221
|
+
async getUser(alias) {
|
|
222
|
+
try {
|
|
223
|
+
const user = await this.db.getUserByAlias(alias);
|
|
224
|
+
if (user) {
|
|
225
|
+
return {
|
|
226
|
+
userPub: user.userPub,
|
|
227
|
+
username: user.username,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
console.warn(`Failed to get user: ${alias}`, error);
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Advanced user space operations
|
|
239
|
+
*/
|
|
240
|
+
// Get all user data (returns user's entire data tree)
|
|
241
|
+
async getAllUserData() {
|
|
242
|
+
try {
|
|
243
|
+
if (!this.isLoggedIn()) {
|
|
244
|
+
console.warn("User not logged in");
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
const user = this.db.getUser();
|
|
248
|
+
if (user && user.is) {
|
|
249
|
+
const userData = await new Promise((resolve, reject) => {
|
|
250
|
+
user.once((data) => {
|
|
251
|
+
resolve(data);
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
return userData;
|
|
255
|
+
}
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
console.warn("Failed to get all user data:", error);
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// Update user profile (common use case)
|
|
264
|
+
async updateProfile(profileData) {
|
|
265
|
+
try {
|
|
266
|
+
if (!this.isLoggedIn()) {
|
|
267
|
+
console.warn("User not logged in");
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
return await this.putUserData("profile", profileData);
|
|
271
|
+
}
|
|
272
|
+
catch (error) {
|
|
273
|
+
console.warn("Failed to update profile:", error);
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
// Get user profile
|
|
278
|
+
async getProfile() {
|
|
279
|
+
try {
|
|
280
|
+
if (!this.isLoggedIn()) {
|
|
281
|
+
console.warn("User not logged in");
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
return await this.getUserData("profile");
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
console.warn("Failed to get profile:", error);
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
// Save user settings
|
|
292
|
+
async saveSettings(settings) {
|
|
293
|
+
try {
|
|
294
|
+
if (!this.isLoggedIn()) {
|
|
295
|
+
console.warn("User not logged in");
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
return await this.putUserData("settings", settings);
|
|
299
|
+
}
|
|
300
|
+
catch (error) {
|
|
301
|
+
console.warn("Failed to save settings:", error);
|
|
302
|
+
return false;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
// Get user settings
|
|
306
|
+
async getSettings() {
|
|
307
|
+
try {
|
|
308
|
+
if (!this.isLoggedIn()) {
|
|
309
|
+
console.warn("User not logged in");
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
return await this.getUserData("settings");
|
|
313
|
+
}
|
|
314
|
+
catch (error) {
|
|
315
|
+
console.warn("Failed to get settings:", error);
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
// Save user preferences
|
|
320
|
+
async savePreferences(preferences) {
|
|
321
|
+
try {
|
|
322
|
+
if (!this.isLoggedIn()) {
|
|
323
|
+
console.warn("User not logged in");
|
|
324
|
+
return false;
|
|
325
|
+
}
|
|
326
|
+
return await this.putUserData("preferences", preferences);
|
|
327
|
+
}
|
|
328
|
+
catch (error) {
|
|
329
|
+
console.warn("Failed to save preferences:", error);
|
|
330
|
+
return false;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
// Get user preferences
|
|
334
|
+
async getPreferences() {
|
|
335
|
+
try {
|
|
336
|
+
if (!this.isLoggedIn()) {
|
|
337
|
+
console.warn("User not logged in");
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
return await this.getUserData("preferences");
|
|
341
|
+
}
|
|
342
|
+
catch (error) {
|
|
343
|
+
console.warn("Failed to get preferences:", error);
|
|
344
|
+
return null;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
// Create a user collection (for storing multiple items)
|
|
348
|
+
async createCollection(collectionName, items) {
|
|
349
|
+
try {
|
|
350
|
+
if (!this.isLoggedIn()) {
|
|
351
|
+
console.warn("User not logged in");
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
return await this.putUserData(`collections/${collectionName}`, items);
|
|
355
|
+
}
|
|
356
|
+
catch (error) {
|
|
357
|
+
console.warn(`Failed to create collection ${collectionName}:`, error);
|
|
358
|
+
return false;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
// Add item to collection
|
|
362
|
+
async addToCollection(collectionName, itemId, item) {
|
|
363
|
+
try {
|
|
364
|
+
if (!this.isLoggedIn()) {
|
|
365
|
+
console.warn("User not logged in");
|
|
366
|
+
return false;
|
|
367
|
+
}
|
|
368
|
+
return await this.putUserData(`collections/${collectionName}/${itemId}`, item);
|
|
369
|
+
}
|
|
370
|
+
catch (error) {
|
|
371
|
+
console.warn(`Failed to add item to collection ${collectionName}:`, error);
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
// Get collection
|
|
376
|
+
async getCollection(collectionName) {
|
|
377
|
+
try {
|
|
378
|
+
if (!this.isLoggedIn()) {
|
|
379
|
+
console.warn("User not logged in");
|
|
380
|
+
return null;
|
|
381
|
+
}
|
|
382
|
+
return await this.getUserData(`collections/${collectionName}`);
|
|
383
|
+
}
|
|
384
|
+
catch (error) {
|
|
385
|
+
console.warn(`Failed to get collection ${collectionName}:`, error);
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
// Remove item from collection
|
|
390
|
+
async removeFromCollection(collectionName, itemId) {
|
|
391
|
+
try {
|
|
392
|
+
if (!this.isLoggedIn()) {
|
|
393
|
+
console.warn("User not logged in");
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
return await this.removeUserData(`collections/${collectionName}/${itemId}`);
|
|
397
|
+
}
|
|
398
|
+
catch (error) {
|
|
399
|
+
console.warn(`Failed to remove item from collection ${collectionName}:`, error);
|
|
400
|
+
return false;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Factory function to create a simple API instance
|
|
406
|
+
*/
|
|
407
|
+
export function createSimpleAPI(db) {
|
|
408
|
+
return new SimpleGunAPI(db);
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Quick start helper - creates a simple API with minimal configuration
|
|
412
|
+
*/
|
|
413
|
+
export class QuickStart {
|
|
414
|
+
db;
|
|
415
|
+
simpleAPI;
|
|
416
|
+
constructor(gunInstance, appScope = "shogun") {
|
|
417
|
+
this.db = new DataBase(gunInstance, appScope);
|
|
418
|
+
this.simpleAPI = new SimpleGunAPI(this.db);
|
|
419
|
+
}
|
|
420
|
+
// Initialize the database
|
|
421
|
+
async init() {
|
|
422
|
+
await this.db.initialize();
|
|
423
|
+
}
|
|
424
|
+
// Get the simple API
|
|
425
|
+
get api() {
|
|
426
|
+
return this.simpleAPI;
|
|
427
|
+
}
|
|
428
|
+
// Get the full database instance for advanced usage
|
|
429
|
+
get database() {
|
|
430
|
+
return this.db;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Global helper for quick setup
|
|
435
|
+
*/
|
|
436
|
+
export function quickStart(gunInstance, appScope) {
|
|
437
|
+
return new QuickStart(gunInstance, appScope);
|
|
438
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import { ShogunCore } from "./core";
|
|
2
2
|
import { SEA, RxJS, crypto, derive, GunErrors, DataBase } from "./gundb/db";
|
|
3
|
+
// Import Simple API and improved types
|
|
4
|
+
import { SimpleGunAPI, QuickStart, quickStart, createSimpleAPI, } from "./gundb";
|
|
3
5
|
// Import Gun as default export
|
|
4
6
|
import Gun from "./gundb/db";
|
|
5
7
|
export * from "./utils/errorHandler";
|
|
6
8
|
export * from "./plugins";
|
|
7
9
|
export * from "./interfaces/shogun";
|
|
8
|
-
|
|
10
|
+
// Export simplified configuration
|
|
11
|
+
export * from "./config/simplified-config";
|
|
12
|
+
export { SEA, RxJS, crypto, derive, GunErrors, DataBase,
|
|
13
|
+
// Simple API exports
|
|
14
|
+
SimpleGunAPI, QuickStart, quickStart, createSimpleAPI, };
|
|
9
15
|
export { Gun };
|
|
10
16
|
export { ShogunCore };
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { ErrorHandler, ErrorType } from "../utils/errorHandler";
|
|
2
|
+
/**
|
|
3
|
+
* Manages authentication operations for ShogunCore
|
|
4
|
+
*/
|
|
5
|
+
export class AuthManager {
|
|
6
|
+
core;
|
|
7
|
+
currentAuthMethod;
|
|
8
|
+
constructor(core) {
|
|
9
|
+
this.core = core;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Check if user is logged in
|
|
13
|
+
* @returns {boolean} True if user is logged in, false otherwise
|
|
14
|
+
* @description Verifies authentication status by checking GunInstance login state
|
|
15
|
+
* and presence of authentication credentials in storage
|
|
16
|
+
*/
|
|
17
|
+
isLoggedIn() {
|
|
18
|
+
return this.core.db.isLoggedIn();
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Perform user logout
|
|
22
|
+
* @description Logs out the current user from GunInstance and emits logout event.
|
|
23
|
+
* If user is not authenticated, the logout operation is ignored.
|
|
24
|
+
*/
|
|
25
|
+
logout() {
|
|
26
|
+
try {
|
|
27
|
+
if (!this.isLoggedIn()) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
this.core.db.logout();
|
|
31
|
+
this.core.emit("auth:logout");
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
ErrorHandler.handle(ErrorType.AUTHENTICATION, "LOGOUT_FAILED", error instanceof Error ? error.message : "Error during logout", error);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Authenticate user with username and password
|
|
39
|
+
* @param username - Username
|
|
40
|
+
* @param password - User password
|
|
41
|
+
* @returns {Promise<AuthResult>} Promise with authentication result
|
|
42
|
+
* @description Attempts to log in user with provided credentials.
|
|
43
|
+
* Emits login event on success.
|
|
44
|
+
*/
|
|
45
|
+
async login(username, password, pair) {
|
|
46
|
+
try {
|
|
47
|
+
if (!this.currentAuthMethod) {
|
|
48
|
+
this.currentAuthMethod = "password";
|
|
49
|
+
}
|
|
50
|
+
const result = await this.core.db.login(username, password, pair);
|
|
51
|
+
if (result.success) {
|
|
52
|
+
// Include SEA pair in the response
|
|
53
|
+
const seaPair = this.core.user?._?.sea;
|
|
54
|
+
if (seaPair) {
|
|
55
|
+
result.sea = seaPair;
|
|
56
|
+
}
|
|
57
|
+
this.core.emit("auth:login", {
|
|
58
|
+
userPub: result.userPub ?? "",
|
|
59
|
+
method: this.currentAuthMethod === "pair"
|
|
60
|
+
? "password"
|
|
61
|
+
: this.currentAuthMethod || "password",
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
result.error = result.error || "Wrong user or password";
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
ErrorHandler.handle(ErrorType.AUTHENTICATION, "LOGIN_FAILED", error.message ?? "Unknown error during login", error);
|
|
71
|
+
return {
|
|
72
|
+
success: false,
|
|
73
|
+
error: error.message ?? "Unknown error during login",
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Login with GunDB pair directly
|
|
79
|
+
* @param pair - GunDB SEA pair for authentication
|
|
80
|
+
* @returns {Promise<AuthResult>} Promise with authentication result
|
|
81
|
+
* @description Authenticates user using a GunDB pair directly.
|
|
82
|
+
* Emits login event on success.
|
|
83
|
+
*/
|
|
84
|
+
async loginWithPair(pair) {
|
|
85
|
+
try {
|
|
86
|
+
if (!pair || !pair.pub || !pair.priv || !pair.epub || !pair.epriv) {
|
|
87
|
+
return {
|
|
88
|
+
success: false,
|
|
89
|
+
error: "Invalid pair structure - missing required keys",
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Use the new loginWithPair method from GunInstance
|
|
93
|
+
const result = await this.core.db.login("", "", pair);
|
|
94
|
+
if (result.success) {
|
|
95
|
+
// Include SEA pair in the response
|
|
96
|
+
const seaPair = this.core.user?._?.sea;
|
|
97
|
+
if (seaPair) {
|
|
98
|
+
result.sea = seaPair;
|
|
99
|
+
}
|
|
100
|
+
this.currentAuthMethod = "pair";
|
|
101
|
+
this.core.emit("auth:login", {
|
|
102
|
+
userPub: result.userPub ?? "",
|
|
103
|
+
method: "password",
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
result.error =
|
|
108
|
+
result.error || "Authentication failed with provided pair";
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
ErrorHandler.handle(ErrorType.AUTHENTICATION, "PAIR_LOGIN_FAILED", error.message ?? "Unknown error during pair login", error);
|
|
114
|
+
return {
|
|
115
|
+
success: false,
|
|
116
|
+
error: error.message ?? "Unknown error during pair login",
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Register a new user with provided credentials
|
|
122
|
+
* @param username - Username
|
|
123
|
+
* @param password - Password
|
|
124
|
+
* @param email - Email (optional)
|
|
125
|
+
* @param pair - Pair of keys
|
|
126
|
+
* @returns {Promise<SignUpResult>} Registration result
|
|
127
|
+
* @description Creates a new user account with the provided credentials.
|
|
128
|
+
* Validates password requirements and emits signup event on success.
|
|
129
|
+
*/
|
|
130
|
+
async signUp(username, password, pair) {
|
|
131
|
+
try {
|
|
132
|
+
if (!this.core.db) {
|
|
133
|
+
throw new Error("Database not initialized");
|
|
134
|
+
}
|
|
135
|
+
// For password-based signup, ensure password is provided
|
|
136
|
+
if (!pair && (!password || password.trim() === "")) {
|
|
137
|
+
throw new Error("Password is required for password-based signup");
|
|
138
|
+
}
|
|
139
|
+
const result = await this.core.db.signUp(username, password || "", pair);
|
|
140
|
+
if (result.success) {
|
|
141
|
+
// Update current authentication method
|
|
142
|
+
this.currentAuthMethod = pair ? "web3" : "password";
|
|
143
|
+
this.core.emit("auth:signup", {
|
|
144
|
+
userPub: result.userPub,
|
|
145
|
+
username,
|
|
146
|
+
method: this.currentAuthMethod,
|
|
147
|
+
});
|
|
148
|
+
this.core.emit("debug", {
|
|
149
|
+
action: "signup_success",
|
|
150
|
+
userPub: result.userPub,
|
|
151
|
+
method: this.currentAuthMethod,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
this.core.emit("debug", {
|
|
156
|
+
action: "signup_failed",
|
|
157
|
+
error: result.error,
|
|
158
|
+
username,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
if (typeof console !== "undefined" && console.error) {
|
|
165
|
+
console.error(`Error during registration for user ${username}:`, error);
|
|
166
|
+
}
|
|
167
|
+
this.core.emit("debug", {
|
|
168
|
+
action: "signup_error",
|
|
169
|
+
error: error instanceof Error ? error.message : String(error),
|
|
170
|
+
username,
|
|
171
|
+
});
|
|
172
|
+
return {
|
|
173
|
+
success: false,
|
|
174
|
+
error: `Registration failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Set the current authentication method
|
|
180
|
+
* This is used by plugins to indicate which authentication method was used
|
|
181
|
+
* @param method The authentication method used
|
|
182
|
+
*/
|
|
183
|
+
setAuthMethod(method) {
|
|
184
|
+
this.currentAuthMethod = method;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Get the current authentication method
|
|
188
|
+
* @returns The current authentication method or undefined if not set
|
|
189
|
+
*/
|
|
190
|
+
getAuthMethod() {
|
|
191
|
+
return this.currentAuthMethod;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Get an authentication method plugin by type
|
|
195
|
+
* @param type The type of authentication method
|
|
196
|
+
* @returns The authentication plugin or undefined if not available
|
|
197
|
+
* This is a more modern approach to accessing authentication methods
|
|
198
|
+
*/
|
|
199
|
+
getAuthenticationMethod(type) {
|
|
200
|
+
switch (type) {
|
|
201
|
+
case "webauthn":
|
|
202
|
+
return this.core.getPlugin("WebAuthn");
|
|
203
|
+
case "web3":
|
|
204
|
+
return this.core.getPlugin("Web3");
|
|
205
|
+
case "nostr":
|
|
206
|
+
return this.core.getPlugin("Nostr");
|
|
207
|
+
case "oauth":
|
|
208
|
+
return this.core.getPlugin("OAuth");
|
|
209
|
+
case "password":
|
|
210
|
+
default:
|
|
211
|
+
return {
|
|
212
|
+
login: async (username, password) => {
|
|
213
|
+
return await this.login(username, password);
|
|
214
|
+
},
|
|
215
|
+
signUp: async (username, password, confirm) => {
|
|
216
|
+
// For password-based signup, validate password confirmation
|
|
217
|
+
if (confirm && password !== confirm) {
|
|
218
|
+
throw new Error("Password and confirm password do not match");
|
|
219
|
+
}
|
|
220
|
+
return await this.signUp(username, password);
|
|
221
|
+
},
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|