shogun-core 0.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.
Files changed (60) hide show
  1. package/README.md +71 -0
  2. package/dist/auth/credentialAuth.js +154 -0
  3. package/dist/auth/metamaskAuth.js +264 -0
  4. package/dist/auth/webauthnAuth.js +267 -0
  5. package/dist/config.js +39 -0
  6. package/dist/connector/metamask.js +262 -0
  7. package/dist/events.js +12 -0
  8. package/dist/gun/auth.js +523 -0
  9. package/dist/gun/errors.js +66 -0
  10. package/dist/gun/gun.js +331 -0
  11. package/dist/index.js +440 -0
  12. package/dist/mom/MOMClient.js +1253 -0
  13. package/dist/stealth/stealth.js +289 -0
  14. package/dist/storage/storage.js +93 -0
  15. package/dist/types/auth/credentialAuth.d.ts +56 -0
  16. package/dist/types/auth/metamaskAuth.d.ts +74 -0
  17. package/dist/types/auth/webauthnAuth.d.ts +83 -0
  18. package/dist/types/auth.js +1 -0
  19. package/dist/types/config.d.ts +39 -0
  20. package/dist/types/connector/metamask.d.ts +112 -0
  21. package/dist/types/events.d.ts +27 -0
  22. package/dist/types/gun/auth.d.ts +219 -0
  23. package/dist/types/gun/errors.d.ts +42 -0
  24. package/dist/types/gun/gun.d.ts +124 -0
  25. package/dist/types/gun.js +4 -0
  26. package/dist/types/index.d.ts +173 -0
  27. package/dist/types/mom/MOMClient.d.ts +217 -0
  28. package/dist/types/mom.js +29 -0
  29. package/dist/types/shogun.js +1 -0
  30. package/dist/types/stealth/stealth.d.ts +67 -0
  31. package/dist/types/storage/storage.d.ts +11 -0
  32. package/dist/types/token.js +1 -0
  33. package/dist/types/types/auth.d.ts +47 -0
  34. package/dist/types/types/gun.d.ts +73 -0
  35. package/dist/types/types/mom.d.ts +147 -0
  36. package/dist/types/types/shogun.d.ts +90 -0
  37. package/dist/types/types/token.d.ts +12 -0
  38. package/dist/types/utils/eventEmitter.d.ts +9 -0
  39. package/dist/types/utils/logger.d.ts +24 -0
  40. package/dist/types/utils/storageMock.d.ts +12 -0
  41. package/dist/types/utils/utility.d.ts +20 -0
  42. package/dist/types/utils/wait.d.ts +24 -0
  43. package/dist/types/wallet/gunWallet.d.ts +14 -0
  44. package/dist/types/wallet/hdWallet.d.ts +154 -0
  45. package/dist/types/wallet/walletManager-old.d.ts +70 -0
  46. package/dist/types/wallet/walletManager.d.ts +188 -0
  47. package/dist/types/webauthn/webauthn-gun.d.ts +1 -0
  48. package/dist/types/webauthn/webauthn.d.ts +52 -0
  49. package/dist/utils/eventEmitter.js +29 -0
  50. package/dist/utils/logger.js +39 -0
  51. package/dist/utils/storageMock.js +27 -0
  52. package/dist/utils/utility.js +32 -0
  53. package/dist/utils/wait.js +78 -0
  54. package/dist/wallet/gunWallet.js +14 -0
  55. package/dist/wallet/hdWallet.js +619 -0
  56. package/dist/wallet/walletManager-old.js +473 -0
  57. package/dist/wallet/walletManager.js +1226 -0
  58. package/dist/webauthn/webauthn-gun.js +115 -0
  59. package/dist/webauthn/webauthn.js +313 -0
  60. package/package.json +48 -0
@@ -0,0 +1,523 @@
1
+ /**
2
+ * Modulo di autenticazione OAuth per GunDB
3
+ *
4
+ * Implementa un sistema di autenticazione minimale ma completo
5
+ * compatibile con GunDB e il suo sistema SEA (Security, Encryption, Authorization).
6
+ *
7
+ * Fornisce funzionalità essenziali come:
8
+ * - Creazione di utenti
9
+ * - Login/Logout
10
+ * - Gestione delle sessioni
11
+ * - Recupero delle informazioni utente
12
+ * - Modifica delle credenziali
13
+ */
14
+ import { logDebug, logWarning } from "../utils/logger";
15
+ /**
16
+ * Errori specifici per l'autenticazione
17
+ */
18
+ export class AuthError extends Error {
19
+ constructor(message) {
20
+ super(message);
21
+ this.name = "AuthError";
22
+ }
23
+ }
24
+ export class InvalidCredentials extends AuthError {
25
+ constructor(message = "Credenziali non valide") {
26
+ super(message);
27
+ this.name = "InvalidCredentials";
28
+ }
29
+ }
30
+ export class UserExists extends AuthError {
31
+ constructor(message = "Utente già esistente") {
32
+ super(message);
33
+ this.name = "UserExists";
34
+ }
35
+ }
36
+ export class TimeoutError extends AuthError {
37
+ constructor(message = "Operazione scaduta") {
38
+ super(message);
39
+ this.name = "TimeoutError";
40
+ }
41
+ }
42
+ export class MultipleAuthError extends AuthError {
43
+ constructor(message = "Operazione di autenticazione già in corso") {
44
+ super(message);
45
+ this.name = "MultipleAuthError";
46
+ }
47
+ }
48
+ /**
49
+ * Utilità per verificare se si è in un ambiente web
50
+ */
51
+ const isPlatformWeb = () => {
52
+ return typeof window !== "undefined";
53
+ };
54
+ /**
55
+ * Attende il completamento di una promessa con timeout
56
+ */
57
+ async function timeoutAfter(promise, ms, error) {
58
+ if (ms <= 0)
59
+ return promise;
60
+ const timeout = new Promise((_, reject) => {
61
+ setTimeout(() => {
62
+ reject(error || new TimeoutError());
63
+ }, ms);
64
+ });
65
+ return Promise.race([promise, timeout]);
66
+ }
67
+ /**
68
+ * Core di autenticazione GUN
69
+ * Gestisce le operazioni di autenticazione a basso livello con GUN
70
+ */
71
+ export class GunAuthCore {
72
+ /**
73
+ * @param gun - Istanza GUN di riferimento
74
+ */
75
+ constructor(gun) {
76
+ /** Flag per indicare se è iscritto agli eventi di autenticazione */
77
+ this._subscribed = false;
78
+ /** Callback di autenticazione */
79
+ this._authCallbacks = [];
80
+ this.gun = gun;
81
+ }
82
+ /**
83
+ * Ottiene l'istanza predefinita di GunAuthCore
84
+ * @param gun - Istanza GUN opzionale
85
+ * @returns Istanza predefinita di GunAuthCore
86
+ */
87
+ static default(gun) {
88
+ if (!GunAuthCore._default) {
89
+ if (!gun && !GunAuthCore.defaultGun) {
90
+ throw new Error("Nessuna istanza GUN disponibile");
91
+ }
92
+ GunAuthCore._default = new GunAuthCore(gun || GunAuthCore.defaultGun);
93
+ }
94
+ return GunAuthCore._default;
95
+ }
96
+ /**
97
+ * Reimposta l'istanza predefinita
98
+ */
99
+ static resetDefault() {
100
+ GunAuthCore._default = undefined;
101
+ }
102
+ /**
103
+ * Effettua il logout dell'utente corrente
104
+ */
105
+ logout() {
106
+ const user = this.gun.user();
107
+ if (user && typeof user.leave === "function") {
108
+ user.leave();
109
+ }
110
+ this._authPromise = undefined;
111
+ if (this.delegate && typeof this.delegate.onLogout === 'function') {
112
+ this.delegate.onLogout();
113
+ }
114
+ logDebug("Utente disconnesso con successo");
115
+ }
116
+ /**
117
+ * Ottiene l'utente correntemente autenticato
118
+ */
119
+ user() {
120
+ const user = this.gun.user();
121
+ // Accesso alla proprietà 'is' attraverso cast
122
+ const is = user.is;
123
+ if (!is)
124
+ return undefined;
125
+ return user;
126
+ }
127
+ /**
128
+ * Ottiene la chiave pubblica dell'utente corrente
129
+ */
130
+ pub() {
131
+ // Accesso alla proprietà '_' attraverso cast
132
+ return this.user()?._?.sea?.pub;
133
+ }
134
+ /**
135
+ * Ottiene la coppia di chiavi dell'utente corrente
136
+ */
137
+ pair() {
138
+ // Accesso alla proprietà '_' attraverso cast
139
+ return this.user()?._?.sea;
140
+ }
141
+ /**
142
+ * Crea un nuovo utente
143
+ * @param creds Credenziali utente
144
+ * @param options Opzioni aggiuntive
145
+ */
146
+ async create(creds, options = {}) {
147
+ return this._executeAuthOperation(() => this._createUser(creds, options));
148
+ }
149
+ /**
150
+ * Effettua il login di un utente
151
+ * @param creds Credenziali utente o coppia di chiavi
152
+ * @param options Opzioni aggiuntive
153
+ */
154
+ async login(creds, options = {}) {
155
+ return this._executeAuthOperation(() => this._loginUser(creds, options));
156
+ }
157
+ /**
158
+ * Verifica se un utente esiste
159
+ * @param alias Nome utente da verificare
160
+ * @param options Opzioni aggiuntive
161
+ */
162
+ async exists(alias, options = {}) {
163
+ const pub = await this.getPub(alias, options);
164
+ return !!pub;
165
+ }
166
+ /**
167
+ * Ottiene la chiave pubblica associata a un nome utente
168
+ * @param alias Nome utente
169
+ * @param options Opzioni aggiuntive
170
+ */
171
+ async getPub(alias, options = {}) {
172
+ const { timeout = GunAuthCore.defaultExistsTimeout } = options;
173
+ const user = this.gun.user();
174
+ return new Promise((resolve, reject) => {
175
+ let resolved = false;
176
+ let timer = null;
177
+ const callback = (at) => {
178
+ if (resolved)
179
+ return;
180
+ resolved = true;
181
+ try {
182
+ if (!at) {
183
+ if (timer) {
184
+ clearTimeout(timer);
185
+ timer = null;
186
+ }
187
+ return resolve(undefined);
188
+ }
189
+ const pubs = Object.values(at);
190
+ if (!pubs.length) {
191
+ return resolve(undefined);
192
+ }
193
+ if (timer) {
194
+ clearTimeout(timer);
195
+ timer = null;
196
+ }
197
+ resolve(pubs[0]);
198
+ }
199
+ catch (err) {
200
+ reject(err instanceof Error ? err : new Error("Errore nel recupero della chiave pubblica"));
201
+ }
202
+ };
203
+ user.get("~@" + alias).once(callback);
204
+ if (timeout > 0) {
205
+ timer = setTimeout(() => {
206
+ if (!resolved) {
207
+ resolved = true;
208
+ resolve(undefined);
209
+ }
210
+ }, timeout);
211
+ }
212
+ });
213
+ }
214
+ /**
215
+ * Recupera un utente precedentemente autenticato dalla sessione
216
+ * @param options Opzioni aggiuntive
217
+ */
218
+ async recall(options = {}) {
219
+ return this._executeAuthOperation(() => this._recallSession(options));
220
+ }
221
+ /**
222
+ * Si sottoscrive agli eventi di autenticazione
223
+ * @param callback Funzione da chiamare quando l'utente viene autenticato
224
+ */
225
+ async on(callback) {
226
+ if (callback) {
227
+ this._addAuthCallback(callback);
228
+ }
229
+ if (this._authPromise) {
230
+ return this._authPromise;
231
+ }
232
+ return this._executeAuthOperation(() => this._handleAuthEvent());
233
+ }
234
+ /**
235
+ * Cambia la password di un utente
236
+ * @param creds Credenziali con la nuova password
237
+ * @param options Opzioni aggiuntive
238
+ */
239
+ async changePassword(creds, options = {}) {
240
+ return this._executeAuthOperation(() => this._createUser(creds, { ...options, changePass: true }));
241
+ }
242
+ /**
243
+ * Elimina un utente
244
+ * @param creds Credenziali dell'utente
245
+ * @param options Opzioni aggiuntive
246
+ */
247
+ async delete(creds, options = {}) {
248
+ return this._executeAuthOperation(() => this._deleteUser(creds, options));
249
+ }
250
+ /**
251
+ * Implementazione interna per la creazione di un utente
252
+ */
253
+ async _createUser({ alias, pass, newPass }, options) {
254
+ const { timeout = GunAuthCore.defaultTimeout, existsTimeout = GunAuthCore.defaultExistsTimeout } = options;
255
+ // Verifica se l'utente esiste già
256
+ if (alias) {
257
+ const exists = await this.exists(alias, { timeout: existsTimeout });
258
+ if (exists && !options.changePass) {
259
+ throw new UserExists();
260
+ }
261
+ }
262
+ return new Promise((resolve, reject) => {
263
+ const createOp = (callback) => {
264
+ try {
265
+ if (newPass && options.changePass) {
266
+ // Cambio password: dobbiamo fare un cast a any per evitare errori di tipo
267
+ const userRef = this.gun.user();
268
+ userRef.auth(alias, pass, (ack) => {
269
+ if (ack.err) {
270
+ return callback({ err: ack.err });
271
+ }
272
+ // Una volta autenticati, cambiamo la password
273
+ // Il secondo argomento è la nuova password, non è un callback
274
+ userRef.auth(newPass, (ack) => {
275
+ callback(ack);
276
+ });
277
+ });
278
+ }
279
+ else {
280
+ // Creazione utente standard
281
+ this.gun.user().create(alias, pass, callback);
282
+ }
283
+ }
284
+ catch (err) {
285
+ callback({ err: err instanceof Error ? err.message : String(err) });
286
+ }
287
+ };
288
+ try {
289
+ createOp((ack) => {
290
+ if (ack.err) {
291
+ return reject(this._parseGunError(ack.err));
292
+ }
293
+ // Utilizziamo un cast a any per accedere alla proprietà is
294
+ const userRef = this.gun.user();
295
+ const pub = ack.pub || (userRef.is?.pub);
296
+ if (!pub) {
297
+ return reject(new AuthError("Impossibile ottenere la chiave pubblica"));
298
+ }
299
+ // Se richiesto, memorizziamo la coppia di chiavi
300
+ if (options.storePair && this.delegate?.storePair) {
301
+ const pair = this.pair();
302
+ if (pair) {
303
+ this.delegate.storePair(this, pair).catch(err => {
304
+ logWarning("Errore durante il salvataggio delle chiavi: " + err.message);
305
+ });
306
+ }
307
+ }
308
+ resolve(pub);
309
+ });
310
+ }
311
+ catch (err) {
312
+ reject(err instanceof Error ? err : new Error(String(err)));
313
+ }
314
+ });
315
+ }
316
+ /**
317
+ * Implementazione interna per il login di un utente
318
+ */
319
+ async _loginUser(creds, options) {
320
+ const { timeout = GunAuthCore.defaultTimeout } = options;
321
+ const loginPromise = new Promise((resolve, reject) => {
322
+ try {
323
+ // Determina se stiamo usando credenziali o una coppia di chiavi
324
+ const isPair = 'pub' in creds && 'priv' in creds && !('alias' in creds);
325
+ const authCallback = (ack) => {
326
+ if (ack.err) {
327
+ reject(this._parseGunError(ack.err));
328
+ }
329
+ else {
330
+ const pub = ack.sea?.pub || this.pub();
331
+ if (!pub) {
332
+ reject(new AuthError("Login riuscito ma impossibile ottenere la chiave pubblica"));
333
+ }
334
+ else {
335
+ resolve(pub);
336
+ }
337
+ }
338
+ };
339
+ if (isPair) {
340
+ this.gun.user().auth(creds, authCallback);
341
+ }
342
+ else {
343
+ const { alias, pass } = creds;
344
+ this.gun.user().auth(alias, pass, authCallback);
345
+ }
346
+ }
347
+ catch (err) {
348
+ reject(err instanceof Error ? err : new Error(String(err)));
349
+ }
350
+ });
351
+ return timeout > 0 ? timeoutAfter(loginPromise, timeout) : loginPromise;
352
+ }
353
+ /**
354
+ * Implementazione interna per l'eliminazione di un utente
355
+ */
356
+ async _deleteUser({ alias, pass }, options) {
357
+ const { timeout = GunAuthCore.defaultTimeout } = options;
358
+ return new Promise((resolve, reject) => {
359
+ try {
360
+ this.gun.user().delete(alias, pass, (ack) => {
361
+ if (ack.err) {
362
+ reject(this._parseGunError(ack.err));
363
+ }
364
+ else {
365
+ resolve();
366
+ }
367
+ });
368
+ }
369
+ catch (err) {
370
+ reject(err instanceof Error ? err : new Error(String(err)));
371
+ }
372
+ });
373
+ }
374
+ /**
375
+ * Implementazione interna per il recupero della sessione
376
+ */
377
+ async _recallSession(options) {
378
+ const { timeout = GunAuthCore.defaultTimeout } = options;
379
+ // Se il delegato può recuperare la coppia di chiavi
380
+ if (this.delegate?.recallPair) {
381
+ const pair = await this.delegate.recallPair(this, options);
382
+ if (pair) {
383
+ // Autentica con la coppia di chiavi
384
+ return await this.login(pair, options);
385
+ }
386
+ }
387
+ // Altrimenti prova a recuperare la sessione dal browser
388
+ if (isPlatformWeb()) {
389
+ const recallAction = new Promise((resolve, reject) => {
390
+ try {
391
+ this.gun.user().recall({ sessionStorage: true }, (ack) => {
392
+ if (ack.err) {
393
+ reject(this._parseGunError(ack.err));
394
+ }
395
+ else if (ack.sea) {
396
+ resolve(ack.sea.pub);
397
+ }
398
+ else {
399
+ resolve(undefined);
400
+ }
401
+ });
402
+ }
403
+ catch (err) {
404
+ reject(err instanceof Error ? err : new Error(String(err)));
405
+ }
406
+ });
407
+ return timeout > 0 ?
408
+ timeoutAfter(recallAction, timeout, new TimeoutError("Timeout durante il recupero della sessione")) :
409
+ recallAction;
410
+ }
411
+ return undefined;
412
+ }
413
+ /**
414
+ * Gestisce gli eventi di autenticazione
415
+ */
416
+ async _handleAuthEvent() {
417
+ if (!this._subscribed) {
418
+ this._subscribeToAuthEvents();
419
+ }
420
+ // Se siamo già autenticati, restituisci subito la chiave pubblica
421
+ const currentPub = this.pub();
422
+ if (currentPub) {
423
+ return Promise.resolve(currentPub);
424
+ }
425
+ // Altrimenti crea una nuova promise che verrà risolta quando l'autenticazione avviene
426
+ return new Promise((resolve) => {
427
+ this._beginAuthPromise(resolve);
428
+ });
429
+ }
430
+ /**
431
+ * Si sottoscrive agli eventi di autenticazione
432
+ */
433
+ _subscribeToAuthEvents() {
434
+ if (this._subscribed)
435
+ return;
436
+ // Callback interno che risolve la promise di autenticazione
437
+ const callback = () => this._completeAuthPromise();
438
+ // Sottoscrizione all'evento 'auth' di GUN
439
+ this.gun.on('auth', callback);
440
+ this._subscribed = true;
441
+ }
442
+ /**
443
+ * Aggiunge un callback agli eventi di autenticazione
444
+ */
445
+ _addAuthCallback(callback) {
446
+ this._authCallbacks.push(callback);
447
+ // Se siamo già autenticati, esegui subito il callback
448
+ if (this.pub()) {
449
+ setTimeout(callback, 0);
450
+ }
451
+ }
452
+ /**
453
+ * Inizializza la promise di autenticazione
454
+ */
455
+ _beginAuthPromise(resolver) {
456
+ this._authResolver = resolver;
457
+ }
458
+ /**
459
+ * Completa la promise di autenticazione
460
+ */
461
+ _completeAuthPromise(pub) {
462
+ if (this._authResolver) {
463
+ const actualPub = pub || this.pub();
464
+ if (actualPub) {
465
+ this._authResolver(actualPub);
466
+ }
467
+ else {
468
+ this._authResolver("");
469
+ }
470
+ }
471
+ this._authResolver = undefined;
472
+ this._authPromise = undefined;
473
+ // Se disponiamo di un delegato, salviamo la coppia di chiavi
474
+ if (pub) {
475
+ if (this.delegate && typeof this.delegate.storePair === "function") {
476
+ const pair = this.pair();
477
+ if (pair) {
478
+ this.delegate.storePair(this, pair);
479
+ }
480
+ }
481
+ }
482
+ // Esegui tutti i callback di autenticazione
483
+ this._authCallbacks.forEach(cb => setTimeout(cb, 0));
484
+ }
485
+ /**
486
+ * Esegue un'operazione di autenticazione, impedendo operazioni simultanee
487
+ */
488
+ async _executeAuthOperation(operation) {
489
+ if (this._authOperation) {
490
+ throw new MultipleAuthError();
491
+ }
492
+ try {
493
+ const promise = operation();
494
+ this._authOperation = promise;
495
+ return await promise;
496
+ }
497
+ finally {
498
+ this._authOperation = undefined;
499
+ this._completeAuthPromise();
500
+ }
501
+ }
502
+ /**
503
+ * Converte gli errori di GUN in errori tipizzati
504
+ */
505
+ _parseGunError(error) {
506
+ switch (error) {
507
+ case "User already created!":
508
+ return new UserExists(error);
509
+ case "Wrong user or password.":
510
+ return new InvalidCredentials(error);
511
+ case "User is already being created or authenticated!":
512
+ return new MultipleAuthError(error);
513
+ default:
514
+ return new AuthError(error);
515
+ }
516
+ }
517
+ }
518
+ /** Timeout predefinito per le operazioni di autenticazione */
519
+ GunAuthCore.defaultTimeout = 10000;
520
+ /** Timeout predefinito per verificare l'esistenza di un utente */
521
+ GunAuthCore.defaultExistsTimeout = 3000;
522
+ // Per compatibilità retroattiva, manteniamo un alias
523
+ export const Auth = GunAuthCore;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Classi di errore per Gun e Auth
3
+ */
4
+ /**
5
+ * Errore di base per Gun
6
+ */
7
+ export class GunError extends Error {
8
+ constructor(message) {
9
+ super(message);
10
+ this.name = 'GunError';
11
+ }
12
+ }
13
+ /**
14
+ * Errore di autenticazione generico
15
+ */
16
+ export class AuthError extends GunError {
17
+ constructor(message) {
18
+ super(message);
19
+ this.name = 'AuthError';
20
+ }
21
+ }
22
+ /**
23
+ * Errore di credenziali non valide
24
+ */
25
+ export class InvalidCredentials extends AuthError {
26
+ constructor(message = 'Credenziali non valide') {
27
+ super(message);
28
+ this.name = 'InvalidCredentials';
29
+ }
30
+ }
31
+ /**
32
+ * Errore di utente già esistente
33
+ */
34
+ export class UserExists extends AuthError {
35
+ constructor(message = 'Utente già esistente') {
36
+ super(message);
37
+ this.name = 'UserExists';
38
+ }
39
+ }
40
+ /**
41
+ * Errore di timeout
42
+ */
43
+ export class TimeoutError extends GunError {
44
+ constructor(message = 'Timeout durante l\'operazione') {
45
+ super(message);
46
+ this.name = 'TimeoutError';
47
+ }
48
+ }
49
+ /**
50
+ * Errore di multiple autenticazioni
51
+ */
52
+ export class MultipleAuthError extends AuthError {
53
+ constructor(message = 'Autenticazione multipla in corso') {
54
+ super(message);
55
+ this.name = 'MultipleAuthError';
56
+ }
57
+ }
58
+ /** Base error related to the network. */
59
+ export class NetworkError extends GunError {
60
+ }
61
+ const withDefaultMessage = (args, defaultMessage) => {
62
+ if (args.length === 0 || args.length === 1 && !args[0]) {
63
+ args = [defaultMessage];
64
+ }
65
+ return args;
66
+ };