shogun-core 1.1.4 → 1.2.2

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.
Files changed (82) hide show
  1. package/README.md +61 -1327
  2. package/dist/browser/shogun-core.js +1 -1
  3. package/dist/browser/shogun-core.js.LICENSE.txt +0 -9
  4. package/dist/browser/shogun-core.light.js +1 -1
  5. package/dist/browser/shogun-core.vendors.light.js +1 -1
  6. package/dist/browser.js +27 -11
  7. package/dist/core.js +603 -0
  8. package/dist/{gun → gundb}/crypto.js +38 -8
  9. package/dist/gundb/gun.js +676 -0
  10. package/dist/{gun → gundb}/index.js +0 -5
  11. package/dist/{gun → gundb}/utils.js +6 -0
  12. package/dist/index.js +1 -807
  13. package/dist/plugins/index.js +15 -28
  14. package/dist/plugins/{stealth → nostr}/index.js +3 -4
  15. package/dist/plugins/nostr/nostrConnector.js +656 -0
  16. package/dist/plugins/nostr/nostrConnectorPlugin.js +259 -0
  17. package/dist/plugins/{metamask → web3}/index.js +2 -2
  18. package/dist/plugins/{metamask/metamask.js → web3/web3Connector.js} +8 -8
  19. package/dist/plugins/{metamask/metamaskPlugin.js → web3/web3ConnectorPlugin.js} +32 -42
  20. package/dist/plugins/webauthn/webauthnPlugin.js +4 -0
  21. package/dist/types/browser.d.ts +9 -4
  22. package/dist/types/core.d.ts +221 -0
  23. package/dist/types/{gun → gundb}/crypto.d.ts +20 -5
  24. package/dist/types/{gun → gundb}/gun.d.ts +56 -28
  25. package/dist/types/gundb/index.d.ts +1 -0
  26. package/dist/types/{gun → gundb}/utils.d.ts +1 -0
  27. package/dist/types/index.d.ts +1 -282
  28. package/dist/types/plugins/index.d.ts +7 -10
  29. package/dist/types/plugins/nostr/index.d.ts +3 -0
  30. package/dist/types/plugins/nostr/nostrConnector.d.ts +111 -0
  31. package/dist/types/plugins/nostr/nostrConnectorPlugin.d.ts +87 -0
  32. package/dist/types/plugins/nostr/types.d.ts +122 -0
  33. package/dist/types/plugins/web3/index.d.ts +3 -0
  34. package/dist/types/plugins/{metamask → web3}/types.d.ts +4 -4
  35. package/dist/types/plugins/{metamask/metamask.d.ts → web3/web3Connector.d.ts} +7 -7
  36. package/dist/types/plugins/{metamask/metamaskPlugin.d.ts → web3/web3ConnectorPlugin.d.ts} +4 -4
  37. package/dist/types/shogun.js +40 -15
  38. package/dist/types/types/shogun.d.ts +67 -67
  39. package/dist/types/utils/errorHandler.d.ts +39 -36
  40. package/dist/types/utils/utility.d.ts +0 -4
  41. package/dist/utils/errorHandler.js +43 -40
  42. package/dist/utils/utility.js +0 -8
  43. package/package.json +2 -2
  44. package/dist/config.js +0 -18
  45. package/dist/gun/gun.js +0 -542
  46. package/dist/plugins/stealth/stealth.js +0 -176
  47. package/dist/plugins/stealth/stealthPlugin.js +0 -113
  48. package/dist/plugins/stealth/types.js +0 -2
  49. package/dist/plugins/utils/stubs/didStub.js +0 -35
  50. package/dist/plugins/utils/stubs/stealthStub.js +0 -35
  51. package/dist/plugins/utils/stubs/webauthnStub.js +0 -29
  52. package/dist/plugins/wallet/index.js +0 -20
  53. package/dist/plugins/wallet/types.js +0 -15
  54. package/dist/plugins/wallet/walletManager.js +0 -1832
  55. package/dist/plugins/wallet/walletPlugin.js +0 -236
  56. package/dist/types/config.d.ts +0 -15
  57. package/dist/types/gun/index.d.ts +0 -6
  58. package/dist/types/gun/types.d.ts +0 -2
  59. package/dist/types/plugins/metamask/index.d.ts +0 -3
  60. package/dist/types/plugins/stealth/index.d.ts +0 -3
  61. package/dist/types/plugins/stealth/stealth.d.ts +0 -93
  62. package/dist/types/plugins/stealth/stealthPlugin.d.ts +0 -60
  63. package/dist/types/plugins/stealth/types.d.ts +0 -93
  64. package/dist/types/plugins/utils/stubs/didStub.d.ts +0 -15
  65. package/dist/types/plugins/utils/stubs/stealthStub.d.ts +0 -15
  66. package/dist/types/plugins/utils/stubs/webauthnStub.d.ts +0 -13
  67. package/dist/types/plugins/wallet/index.d.ts +0 -3
  68. package/dist/types/plugins/wallet/types.d.ts +0 -167
  69. package/dist/types/plugins/wallet/walletManager.d.ts +0 -306
  70. package/dist/types/plugins/wallet/walletPlugin.d.ts +0 -126
  71. package/dist/types/utils/stubs/didStub.d.ts +0 -15
  72. package/dist/types/utils/stubs/stealthStub.d.ts +0 -15
  73. package/dist/types/utils/stubs/webauthnStub.d.ts +0 -13
  74. package/dist/utils/stubs/didStub.js +0 -35
  75. package/dist/utils/stubs/stealthStub.js +0 -35
  76. package/dist/utils/stubs/webauthnStub.js +0 -29
  77. /package/dist/{gun → gundb}/errors.js +0 -0
  78. /package/dist/{gun → gundb}/rxjs-integration.js +0 -0
  79. /package/dist/{gun → plugins/nostr}/types.js +0 -0
  80. /package/dist/plugins/{metamask → web3}/types.js +0 -0
  81. /package/dist/types/{gun → gundb}/errors.d.ts +0 -0
  82. /package/dist/types/{gun → gundb}/rxjs-integration.d.ts +0 -0
@@ -0,0 +1,676 @@
1
+ "use strict";
2
+ /**
3
+ * GunDB class with enhanced features:
4
+ * - Dynamic peer linking
5
+ * - Support for remove/unset operations
6
+ * - Direct authentication through Gun.user()
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.GunDB = void 0;
43
+ const logger_1 = require("../utils/logger");
44
+ const errorHandler_1 = require("../utils/errorHandler");
45
+ const rxjs_integration_1 = require("./rxjs-integration");
46
+ const GunErrors = __importStar(require("./errors"));
47
+ const crypto = __importStar(require("./crypto"));
48
+ const utils = __importStar(require("./utils"));
49
+ class GunDB {
50
+ gun;
51
+ user = null;
52
+ crypto;
53
+ utils;
54
+ node;
55
+ onAuthCallbacks = [];
56
+ // Integrated modules
57
+ _rxjs;
58
+ constructor(gun, appScope = "shogun") {
59
+ (0, logger_1.log)("Initializing GunDB");
60
+ // Validate Gun instance
61
+ if (!gun) {
62
+ throw new Error("Gun instance is required but was not provided");
63
+ }
64
+ if (typeof gun !== "object") {
65
+ throw new Error(`Gun instance must be an object, received: ${typeof gun}`);
66
+ }
67
+ if (typeof gun.user !== "function") {
68
+ throw new Error(`Gun instance is invalid: gun.user is not a function. Received gun.user type: ${typeof gun.user}`);
69
+ }
70
+ if (typeof gun.get !== "function") {
71
+ throw new Error(`Gun instance is invalid: gun.get is not a function. Received gun.get type: ${typeof gun.get}`);
72
+ }
73
+ if (typeof gun.on !== "function") {
74
+ throw new Error(`Gun instance is invalid: gun.on is not a function. Received gun.on type: ${typeof gun.on}`);
75
+ }
76
+ this.gun = gun;
77
+ try {
78
+ this.user = this.gun.user().recall({ sessionStorage: true });
79
+ }
80
+ catch (error) {
81
+ (0, logger_1.logError)("Error initializing Gun user:", error);
82
+ throw new Error(`Failed to initialize Gun user: ${error}`);
83
+ }
84
+ this.subscribeToAuthEvents();
85
+ // bind crypto and utils
86
+ this.crypto = crypto;
87
+ this.utils = utils;
88
+ this.node = this.gun.get(appScope);
89
+ }
90
+ subscribeToAuthEvents() {
91
+ this.gun.on("auth", (ack) => {
92
+ (0, logger_1.log)("Auth event received:", ack);
93
+ if (ack.err) {
94
+ errorHandler_1.ErrorHandler.handle(errorHandler_1.ErrorType.GUN, "AUTH_EVENT_ERROR", ack.err, new Error(ack.err));
95
+ }
96
+ else {
97
+ this.notifyAuthListeners(ack.sea?.pub || "");
98
+ }
99
+ });
100
+ }
101
+ notifyAuthListeners(pub) {
102
+ const user = this.gun.user();
103
+ this.onAuthCallbacks.forEach((cb) => cb(user));
104
+ }
105
+ /**
106
+ * Adds a new peer to the network
107
+ * @param peer URL of the peer to add
108
+ */
109
+ addPeer(peer) {
110
+ this.gun.opt({ peers: [peer] });
111
+ (0, logger_1.log)(`Added new peer: ${peer}`);
112
+ }
113
+ /**
114
+ * Removes a peer from the network
115
+ * @param peer URL of the peer to remove
116
+ */
117
+ removePeer(peer) {
118
+ try {
119
+ // Get current peers from Gun instance
120
+ const gunOpts = this.gun._.opt;
121
+ if (gunOpts && gunOpts.peers) {
122
+ // Remove the peer from the peers object
123
+ delete gunOpts.peers[peer];
124
+ // Also try to close the connection if it exists
125
+ const peerConnection = gunOpts.peers[peer];
126
+ if (peerConnection && typeof peerConnection.close === "function") {
127
+ peerConnection.close();
128
+ }
129
+ (0, logger_1.log)(`Removed peer: ${peer}`);
130
+ }
131
+ else {
132
+ (0, logger_1.log)(`Peer not found in current connections: ${peer}`);
133
+ }
134
+ }
135
+ catch (error) {
136
+ (0, logger_1.logError)(`Error removing peer ${peer}:`, error);
137
+ }
138
+ }
139
+ /**
140
+ * Gets the list of currently connected peers
141
+ * @returns Array of peer URLs
142
+ */
143
+ getCurrentPeers() {
144
+ try {
145
+ const gunOpts = this.gun._.opt;
146
+ if (gunOpts && gunOpts.peers) {
147
+ return Object.keys(gunOpts.peers).filter((peer) => {
148
+ const peerObj = gunOpts.peers[peer];
149
+ // Check if peer is actually connected (not just configured)
150
+ return peerObj && peerObj.wire && peerObj.wire.hied !== "bye";
151
+ });
152
+ }
153
+ return [];
154
+ }
155
+ catch (error) {
156
+ (0, logger_1.logError)("Error getting current peers:", error);
157
+ return [];
158
+ }
159
+ }
160
+ /**
161
+ * Gets the list of all configured peers (connected and disconnected)
162
+ * @returns Array of peer URLs
163
+ */
164
+ getAllConfiguredPeers() {
165
+ try {
166
+ const gunOpts = this.gun._.opt;
167
+ if (gunOpts && gunOpts.peers) {
168
+ return Object.keys(gunOpts.peers);
169
+ }
170
+ return [];
171
+ }
172
+ catch (error) {
173
+ (0, logger_1.logError)("Error getting configured peers:", error);
174
+ return [];
175
+ }
176
+ }
177
+ /**
178
+ * Gets detailed information about all peers
179
+ * @returns Object with peer information
180
+ */
181
+ getPeerInfo() {
182
+ try {
183
+ const gunOpts = this.gun._.opt;
184
+ const peerInfo = {};
185
+ if (gunOpts && gunOpts.peers) {
186
+ Object.keys(gunOpts.peers).forEach((peer) => {
187
+ const peerObj = gunOpts.peers[peer];
188
+ const isConnected = peerObj && peerObj.wire && peerObj.wire.hied !== "bye";
189
+ const status = isConnected
190
+ ? "connected"
191
+ : peerObj && peerObj.wire
192
+ ? "disconnected"
193
+ : "not_initialized";
194
+ peerInfo[peer] = {
195
+ connected: isConnected,
196
+ status: status,
197
+ };
198
+ });
199
+ }
200
+ return peerInfo;
201
+ }
202
+ catch (error) {
203
+ (0, logger_1.logError)("Error getting peer info:", error);
204
+ return {};
205
+ }
206
+ }
207
+ /**
208
+ * Reconnects to a specific peer
209
+ * @param peer URL of the peer to reconnect
210
+ */
211
+ reconnectToPeer(peer) {
212
+ try {
213
+ // First remove the peer
214
+ this.removePeer(peer);
215
+ // Wait a moment then add it back
216
+ setTimeout(() => {
217
+ this.addPeer(peer);
218
+ (0, logger_1.log)(`Reconnected to peer: ${peer}`);
219
+ }, 1000);
220
+ }
221
+ catch (error) {
222
+ (0, logger_1.logError)(`Error reconnecting to peer ${peer}:`, error);
223
+ }
224
+ }
225
+ /**
226
+ * Clears all peers and optionally adds new ones
227
+ * @param newPeers Optional array of new peers to add
228
+ */
229
+ resetPeers(newPeers) {
230
+ try {
231
+ const gunOpts = this.gun._.opt;
232
+ if (gunOpts && gunOpts.peers) {
233
+ // Clear all existing peers
234
+ Object.keys(gunOpts.peers).forEach((peer) => {
235
+ this.removePeer(peer);
236
+ });
237
+ // Add new peers if provided
238
+ if (newPeers && newPeers.length > 0) {
239
+ newPeers.forEach((peer) => {
240
+ this.addPeer(peer);
241
+ });
242
+ }
243
+ (0, logger_1.log)(`Reset peers. New peers: ${newPeers ? newPeers.join(", ") : "none"}`);
244
+ }
245
+ }
246
+ catch (error) {
247
+ (0, logger_1.logError)("Error resetting peers:", error);
248
+ }
249
+ }
250
+ /**
251
+ * Registers an authentication callback
252
+ * @param callback Function to call on auth events
253
+ * @returns Function to unsubscribe the callback
254
+ */
255
+ onAuth(callback) {
256
+ this.onAuthCallbacks.push(callback);
257
+ const user = this.gun.user();
258
+ if (user && user.is)
259
+ callback(user);
260
+ return () => {
261
+ const i = this.onAuthCallbacks.indexOf(callback);
262
+ if (i !== -1)
263
+ this.onAuthCallbacks.splice(i, 1);
264
+ };
265
+ }
266
+ /**
267
+ * Gets the Gun instance
268
+ * @returns Gun instance
269
+ */
270
+ getGun() {
271
+ return this.gun;
272
+ }
273
+ /**
274
+ * Gets the current user instance
275
+ * @returns User instance
276
+ */
277
+ getUser() {
278
+ return this.gun.user();
279
+ }
280
+ /**
281
+ * Gets a node at the specified path
282
+ * @param path Path to the node
283
+ * @returns Gun node
284
+ */
285
+ get(path) {
286
+ return this.gun.get(path);
287
+ }
288
+ /**
289
+ * Puts data at the specified path
290
+ * @param path Path to store data
291
+ * @param data Data to store
292
+ * @returns Promise resolving to operation result
293
+ */
294
+ async put(path, data) {
295
+ return new Promise((resolve) => {
296
+ this.gun.get(path).put(data, (ack) => {
297
+ resolve(ack.err ? { success: false, error: ack.err } : { success: true });
298
+ });
299
+ });
300
+ }
301
+ /**
302
+ * Sets data at the specified path
303
+ * @param path Path to store data
304
+ * @param data Data to store
305
+ * @returns Promise resolving to operation result
306
+ */
307
+ async set(path, data) {
308
+ return new Promise((resolve) => {
309
+ this.gun.get(path).set(data, (ack) => {
310
+ resolve(ack.err ? { success: false, error: ack.err } : { success: true });
311
+ });
312
+ });
313
+ }
314
+ /**
315
+ * Removes data at the specified path
316
+ * @param path Path to remove
317
+ * @returns Promise resolving to operation result
318
+ */
319
+ async remove(path) {
320
+ return new Promise((resolve) => {
321
+ this.gun.get(path).put(null, (ack) => {
322
+ resolve(ack.err ? { success: false, error: ack.err } : { success: true });
323
+ });
324
+ });
325
+ }
326
+ /**
327
+ * Signs up a new user using direct Gun authentication
328
+ * @param username Username
329
+ * @param password Password
330
+ * @returns Promise resolving to signup result
331
+ */
332
+ async signUp(username, password) {
333
+ (0, logger_1.log)("Attempting user registration:", username);
334
+ try {
335
+ // Validate credentials
336
+ if (password.length < 8) {
337
+ const err = "Passwords must be more than 8 characters long!";
338
+ (0, logger_1.log)(err);
339
+ return { success: false, error: err };
340
+ }
341
+ if (username.length < 1) {
342
+ const err = "Username must be more than 0 characters long!";
343
+ (0, logger_1.log)(err);
344
+ return { success: false, error: err };
345
+ }
346
+ // Create user directly with Gun
347
+ const createResult = await new Promise((resolve) => {
348
+ this.gun.user().create(username, password, (ack) => {
349
+ if (ack.err) {
350
+ (0, logger_1.logError)(`User creation error: ${ack.err}`);
351
+ resolve({ success: false, error: ack.err });
352
+ }
353
+ else {
354
+ (0, logger_1.log)(`User created successfully: ${username}`);
355
+ resolve({ success: true, pub: ack.pub });
356
+ }
357
+ });
358
+ });
359
+ if (!createResult.success) {
360
+ return createResult;
361
+ }
362
+ // Store user metadata with improved safety
363
+ try {
364
+ const user = this.gun.get(createResult.pub).put({
365
+ username: username,
366
+ pub: createResult.pub,
367
+ });
368
+ this.gun.get("users").set(user);
369
+ }
370
+ catch (metadataError) {
371
+ (0, logger_1.logError)(`Warning: Could not store user metadata: ${metadataError}`);
372
+ // Continue with login attempt even if metadata storage fails
373
+ }
374
+ // Login after creation
375
+ (0, logger_1.log)(`Attempting login after registration for: ${username}`);
376
+ try {
377
+ const loginResult = await this.login(username, password);
378
+ if (!loginResult.success) {
379
+ (0, logger_1.logError)(`Login after registration failed: ${loginResult.error}`);
380
+ return {
381
+ success: false,
382
+ error: `Registration completed but login failed: ${loginResult.error}`,
383
+ };
384
+ }
385
+ (0, logger_1.log)(`Login after registration successful for: ${username}`);
386
+ return loginResult;
387
+ }
388
+ catch (loginError) {
389
+ (0, logger_1.logError)(`Exception during post-registration login: ${loginError}`);
390
+ return {
391
+ success: false,
392
+ error: "Exception during post-registration login",
393
+ };
394
+ }
395
+ }
396
+ catch (error) {
397
+ (0, logger_1.logError)(`Unexpected error during registration flow: ${error}`);
398
+ return {
399
+ success: false,
400
+ error: `Unexpected error during registration: ${error}`,
401
+ };
402
+ }
403
+ }
404
+ /**
405
+ * Logs in a user using direct Gun authentication
406
+ * @param username Username
407
+ * @param password Password
408
+ * @param callback Optional callback for login result
409
+ * @returns Promise resolving to login result
410
+ */
411
+ async login(username, password, callback) {
412
+ (0, logger_1.log)(`Attempting login for user: ${username}`);
413
+ try {
414
+ // Authenticate with Gun directly
415
+ const authResult = await new Promise((resolve) => {
416
+ this.gun.user().auth(username, password, (ack) => {
417
+ if (ack.err) {
418
+ (0, logger_1.logError)(`Login error for ${username}: ${ack.err}`);
419
+ resolve({ success: false, error: ack.err });
420
+ }
421
+ else {
422
+ (0, logger_1.log)(`Login successful for: ${username}`);
423
+ resolve({ success: true, ack });
424
+ }
425
+ });
426
+ });
427
+ if (!authResult.success) {
428
+ const result = { success: false, error: authResult.error };
429
+ if (callback)
430
+ callback(result);
431
+ return result;
432
+ }
433
+ const userPub = this.gun.user().is?.pub;
434
+ // Update users collection if needed - improved null safety
435
+ try {
436
+ let userExists = false;
437
+ // Check if user already exists in the collection
438
+ await new Promise((resolve) => {
439
+ this.gun
440
+ .get("users")
441
+ .map()
442
+ .once((userData, key) => {
443
+ if (userData && userData.pub === userPub) {
444
+ userExists = true;
445
+ }
446
+ });
447
+ // Give it a moment to check all users
448
+ setTimeout(() => resolve(), 100);
449
+ });
450
+ // Only add user if not already in collection
451
+ if (!userExists && userPub) {
452
+ const newUser = this.gun.get(userPub).put({
453
+ username: username,
454
+ pub: userPub,
455
+ });
456
+ this.gun.get("users").set(newUser);
457
+ }
458
+ }
459
+ catch (collectionError) {
460
+ // Log but don't fail the login for collection errors
461
+ (0, logger_1.logError)(`Warning: Could not update user collection: ${collectionError}`);
462
+ }
463
+ (0, logger_1.log)(`Login successful for: ${username} (${userPub})`);
464
+ this._savePair();
465
+ const result = {
466
+ success: true,
467
+ userPub,
468
+ username,
469
+ };
470
+ if (callback)
471
+ callback(result);
472
+ return result;
473
+ }
474
+ catch (error) {
475
+ (0, logger_1.logError)(`Exception during login for ${username}: ${error}`);
476
+ const result = { success: false, error: String(error) };
477
+ if (callback)
478
+ callback(result);
479
+ return result;
480
+ }
481
+ }
482
+ _savePair() {
483
+ try {
484
+ const pair = this.gun.user()?._?.sea;
485
+ if (pair && typeof localStorage !== "undefined") {
486
+ localStorage.setItem("pair", JSON.stringify(pair));
487
+ }
488
+ }
489
+ catch (error) {
490
+ console.error("Error saving auth pair:", error);
491
+ }
492
+ }
493
+ /**
494
+ * Logs out the current user using direct Gun authentication
495
+ */
496
+ logout() {
497
+ try {
498
+ // Check if the user is actually logged in before attempting to logout
499
+ if (!this.isLoggedIn()) {
500
+ (0, logger_1.log)("No user logged in, skipping logout");
501
+ return;
502
+ }
503
+ // Direct logout using Gun
504
+ this.gun.user().leave();
505
+ (0, logger_1.log)("Logout completed");
506
+ }
507
+ catch (error) {
508
+ (0, logger_1.logError)("Error during logout:", error);
509
+ }
510
+ }
511
+ /**
512
+ * Checks if a user is currently logged in
513
+ * @returns True if logged in
514
+ */
515
+ isLoggedIn() {
516
+ return !!this.gun.user()?.is?.pub;
517
+ }
518
+ /**
519
+ * Gets the current user
520
+ * @returns Current user object or null
521
+ */
522
+ getCurrentUser() {
523
+ const pub = this.gun.user()?.is?.pub;
524
+ return pub ? { pub, user: this.gun.user() } : null;
525
+ }
526
+ /**
527
+ * Accesses the RxJS module for reactive programming
528
+ * @returns GunRxJS instance
529
+ */
530
+ rx() {
531
+ if (!this._rxjs) {
532
+ this._rxjs = new rxjs_integration_1.GunRxJS(this.gun);
533
+ }
534
+ return this._rxjs;
535
+ }
536
+ /**
537
+ * Sets up security questions and password hint
538
+ * @param username Username
539
+ * @param password Current password
540
+ * @param hint Password hint
541
+ * @param securityQuestions Array of security questions
542
+ * @param securityAnswers Array of answers to security questions
543
+ * @returns Promise resolving with the operation result
544
+ */
545
+ async setPasswordHint(username, password, hint, securityQuestions, securityAnswers) {
546
+ (0, logger_1.log)("Setting password hint for:", username);
547
+ // Verify that the user is authenticated
548
+ const loginResult = await this.login(username, password);
549
+ if (!loginResult.success) {
550
+ return { success: false, error: "Authentication failed" };
551
+ }
552
+ try {
553
+ // Generate a proof of work from security question answers
554
+ const proofOfWork = (await this.crypto.hashText(securityAnswers.join("|")));
555
+ // Encrypt the password hint with the proof of work
556
+ // The PoW (a string) is used as the encryption key
557
+ const encryptedHint = await this.crypto.encrypt(hint, proofOfWork);
558
+ // Save security questions and encrypted hint
559
+ await this.saveUserData("security", {
560
+ questions: securityQuestions,
561
+ hint: encryptedHint,
562
+ });
563
+ return { success: true };
564
+ }
565
+ catch (error) {
566
+ (0, logger_1.logError)("Error setting password hint:", error);
567
+ return { success: false, error: String(error) };
568
+ }
569
+ }
570
+ /**
571
+ * Recovers password hint using security question answers
572
+ * @param username Username
573
+ * @param securityAnswers Array of answers to security questions
574
+ * @returns Promise resolving with the password hint
575
+ */
576
+ async forgotPassword(username, securityAnswers) {
577
+ (0, logger_1.log)("Attempting password recovery for:", username);
578
+ try {
579
+ // Verify the user exists
580
+ const user = this.gun.user().recall({ sessionStorage: true });
581
+ if (!user || !user.is) {
582
+ return { success: false, error: "User not found" };
583
+ }
584
+ // Retrieve security questions and encrypted hint
585
+ const securityData = await this.getUserData("security");
586
+ if (!securityData || !securityData.hint) {
587
+ return {
588
+ success: false,
589
+ error: "No password hint found",
590
+ };
591
+ }
592
+ // Decrypt the password hint with the proof of work
593
+ const hint = await this.crypto.decrypt(securityData.hint, (await this.crypto.hashText(securityAnswers.join("|"))));
594
+ if (hint === undefined) {
595
+ return {
596
+ success: false,
597
+ error: "Incorrect answers to security questions",
598
+ };
599
+ }
600
+ return { success: true, hint: hint };
601
+ }
602
+ catch (error) {
603
+ (0, logger_1.logError)("Error recovering password hint:", error);
604
+ return { success: false, error: String(error) };
605
+ }
606
+ }
607
+ /**
608
+ * Hashes text with Gun.SEA
609
+ * @param text Text to hash
610
+ * @returns Promise that resolves with the hashed text
611
+ */
612
+ async hashText(text) {
613
+ return this.crypto.hashText(text);
614
+ }
615
+ /**
616
+ * Encrypts data with Gun.SEA
617
+ * @param data Data to encrypt
618
+ * @param key Encryption key
619
+ * @returns Promise that resolves with the encrypted data
620
+ */
621
+ async encrypt(data, key) {
622
+ return this.crypto.encrypt(data, key);
623
+ }
624
+ /**
625
+ * Decrypts data with Gun.SEA
626
+ * @param encryptedData Encrypted data
627
+ * @param key Decryption key
628
+ * @returns Promise that resolves with the decrypted data
629
+ */
630
+ async decrypt(encryptedData, key) {
631
+ return this.crypto.decrypt(encryptedData, key);
632
+ }
633
+ /**
634
+ * Saves user data at the specified path
635
+ * @param path Path to save the data
636
+ * @param data Data to save
637
+ * @returns Promise that resolves when the data is saved
638
+ */
639
+ async saveUserData(path, data) {
640
+ return new Promise((resolve, reject) => {
641
+ const user = this.gun.user();
642
+ if (!user.is) {
643
+ reject(new Error("User not authenticated"));
644
+ return;
645
+ }
646
+ user.get(path).put(data, (ack) => {
647
+ if (ack.err) {
648
+ reject(new Error(ack.err));
649
+ }
650
+ else {
651
+ resolve();
652
+ }
653
+ });
654
+ });
655
+ }
656
+ /**
657
+ * Gets user data from the specified path
658
+ * @param path Path to get the data from
659
+ * @returns Promise that resolves with the data
660
+ */
661
+ async getUserData(path) {
662
+ return new Promise((resolve) => {
663
+ const user = this.gun.user();
664
+ if (!user.is) {
665
+ resolve(null);
666
+ return;
667
+ }
668
+ user.get(path).once((data) => {
669
+ resolve(data);
670
+ });
671
+ });
672
+ }
673
+ // Errors
674
+ static Errors = GunErrors;
675
+ }
676
+ exports.GunDB = GunDB;
@@ -1,9 +1,4 @@
1
1
  "use strict";
2
- /**
3
- * Gun module for Shogun
4
- * Provides the main interface for interacting with GunDB
5
- * with all modules integrated into the main class
6
- */
7
2
  Object.defineProperty(exports, "__esModule", { value: true });
8
3
  exports.GunDB = void 0;
9
4
  // Export the main class
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getArrayFromIndexedObject = exports.getIndexedObjectFromArray = exports.qs = exports.getSet = exports.getUUID = exports.getTargetPub = exports.getPub = exports.getId = void 0;
4
+ exports.app_scoped = app_scoped;
4
5
  /**
5
6
  * Extracts the ID of a Gun node
6
7
  * @param node - Gun node object containing metadata
@@ -88,3 +89,8 @@ const getArrayFromIndexedObject = (indexedObj) => {
88
89
  return Object.values(indexedObj);
89
90
  };
90
91
  exports.getArrayFromIndexedObject = getArrayFromIndexedObject;
92
+ function app_scoped(string, scope) {
93
+ if (scope.length > 0)
94
+ return `${scope}-${string}`;
95
+ return string;
96
+ }