shogun-core 3.3.4 → 3.3.5
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/dist/browser/defaultVendors-node_modules_shogun-ipfs_node_modules_axios_index_js.shogun-core.js +4073 -2
- package/dist/browser/defaultVendors-node_modules_shogun-ipfs_node_modules_axios_index_js.shogun-core.js.map +1 -0
- package/dist/browser/shogun-core.js +597 -343
- package/dist/browser/shogun-core.js.map +1 -1
- package/dist/ship/examples/identity-cli.js +12 -4
- package/dist/ship/examples/vault-cli.js +2 -2
- package/dist/ship/implementation/SHIP_06.js +574 -289
- package/dist/ship/interfaces/ISHIP_06.js +135 -85
- package/dist/src/gundb/db.js +7 -49
- package/dist/types/ship/implementation/SHIP_06.d.ts +90 -55
- package/dist/types/ship/interfaces/ISHIP_06.d.ts +383 -231
- package/package.json +2 -8
- package/dist/ship/examples/ephemeral-cli.js +0 -234
- package/dist/ship/implementation/SHIP_07.js +0 -635
- package/dist/ship/interfaces/ISHIP_07.js +0 -194
- package/dist/types/ship/examples/ephemeral-cli.d.ts +0 -13
- package/dist/types/ship/implementation/SHIP_07.d.ts +0 -101
- package/dist/types/ship/interfaces/ISHIP_07.d.ts +0 -522
|
@@ -168632,7 +168632,7 @@ function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf
|
|
|
168632
168632
|
var fs = __webpack_require__(Object(function webpackMissingModule() { var e = new Error("Cannot find module 'fs'"); e.code = 'MODULE_NOT_FOUND'; throw e; }()));
|
|
168633
168633
|
var path = __webpack_require__(/*! path */ "./node_modules/path-browserify/index.js");
|
|
168634
168634
|
var asyncSeries = __webpack_require__(/*! async/series */ "./node_modules/shogun-ipfs/node_modules/async/series.js");
|
|
168635
|
-
var zlib = __webpack_require__(
|
|
168635
|
+
var zlib = __webpack_require__(/*! zlib */ "?25c3");
|
|
168636
168636
|
var _require = __webpack_require__(/*! triple-beam */ "./node_modules/shogun-ipfs/node_modules/triple-beam/index.js"),
|
|
168637
168637
|
MESSAGE = _require.MESSAGE;
|
|
168638
168638
|
var _require2 = __webpack_require__(/*! readable-stream */ "./node_modules/shogun-ipfs/node_modules/readable-stream/readable-browser.js"),
|
|
@@ -208850,356 +208850,642 @@ SHIP_05.NODES = {
|
|
|
208850
208850
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
|
208851
208851
|
|
|
208852
208852
|
"use strict";
|
|
208853
|
+
/* provided dependency */ var Buffer = __webpack_require__(/*! buffer */ "./node_modules/buffer/index.js")["Buffer"];
|
|
208853
208854
|
|
|
208854
208855
|
/**
|
|
208855
|
-
* SHIP-06:
|
|
208856
|
+
* SHIP-06: Secure Vault Implementation
|
|
208856
208857
|
*
|
|
208857
|
-
*
|
|
208858
|
-
* 1. Standalone: new SHIP_06(gunPeers[], roomId) - NO authentication!
|
|
208859
|
-
* - Uses ShogunCore internally with silent: true, disableAutoRecall: true
|
|
208860
|
-
* - Zero logs, zero storage, pure relay communication
|
|
208861
|
-
* - Room hashed with Web Crypto API SHA-256 for deterministic IDs
|
|
208858
|
+
* Vault crittografato decentralizzato che dipende da SHIP-00 per l'identità.
|
|
208862
208859
|
*
|
|
208863
|
-
*
|
|
208864
|
-
*
|
|
208865
|
-
*
|
|
208860
|
+
* Dipendenze:
|
|
208861
|
+
* - SHIP-00 (Identity & Authentication) - per gestione utenti e chiavi
|
|
208862
|
+
* - GunDB - per storage decentralizzato P2P
|
|
208863
|
+
* - SEA - per crittografia AES-256-GCM
|
|
208866
208864
|
*
|
|
208867
|
-
*
|
|
208868
|
-
* - Gun Relay for P2P communication (no WebRTC complexity!)
|
|
208869
|
-
* - SEA for ephemeral key generation and ECDH encryption
|
|
208870
|
-
* - Pure relay mode: radisk: false, localStorage: false, multicast: false
|
|
208865
|
+
* Ispirato a: https://github.com/draeder/gunsafe
|
|
208871
208866
|
*/
|
|
208872
208867
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
208873
208868
|
exports.SHIP_06 = void 0;
|
|
208874
|
-
const core_1 = __webpack_require__(/*! ../../src/core */ "./src/core.ts"); // ← Import diretto, NON da index!
|
|
208875
208869
|
// ============================================================================
|
|
208876
|
-
// IMPLEMENTATION
|
|
208870
|
+
// IMPLEMENTATION
|
|
208877
208871
|
// ============================================================================
|
|
208872
|
+
/**
|
|
208873
|
+
* SHIP-06 Reference Implementation
|
|
208874
|
+
*
|
|
208875
|
+
* Questa implementazione dipende da ISHIP_00 per tutte le operazioni di identità.
|
|
208876
|
+
* Si concentra esclusivamente sulla logica del vault crittografato.
|
|
208877
|
+
*/
|
|
208878
208878
|
class SHIP_06 {
|
|
208879
|
-
|
|
208880
|
-
|
|
208881
|
-
|
|
208882
|
-
|
|
208883
|
-
|
|
208884
|
-
|
|
208885
|
-
this.
|
|
208886
|
-
this.myPair = null;
|
|
208879
|
+
/**
|
|
208880
|
+
* Constructor
|
|
208881
|
+
* @param identity ISHIP_00 instance for identity operations
|
|
208882
|
+
* @param vaultNodeName Optional custom vault node name
|
|
208883
|
+
*/
|
|
208884
|
+
constructor(identity, vaultNodeName) {
|
|
208885
|
+
this.initialized = false;
|
|
208887
208886
|
// Gun nodes
|
|
208888
|
-
this.
|
|
208889
|
-
this.
|
|
208890
|
-
this.
|
|
208891
|
-
|
|
208892
|
-
|
|
208893
|
-
// Peers
|
|
208894
|
-
this.peers = new Map();
|
|
208895
|
-
// Event handlers
|
|
208896
|
-
this.messageHandlers = [];
|
|
208897
|
-
this.encryptedMessageHandlers = [];
|
|
208898
|
-
this.peerSeenHandlers = [];
|
|
208899
|
-
this.peerLeftHandlers = [];
|
|
208900
|
-
// Heartbeat & cleanup
|
|
208901
|
-
this.heartbeatInterval = null;
|
|
208902
|
-
this.processedMessages = new Set();
|
|
208903
|
-
this.roomId = roomId;
|
|
208904
|
-
this.config = {
|
|
208905
|
-
debug: config?.debug || false,
|
|
208906
|
-
timeout: 30000,
|
|
208907
|
-
};
|
|
208908
|
-
if (Array.isArray(identityOrPeers)) {
|
|
208909
|
-
// STANDALONE MODE - ShogunCore with silent mode
|
|
208910
|
-
const shogunCore = new core_1.ShogunCore({
|
|
208911
|
-
gunOptions: {
|
|
208912
|
-
peers: identityOrPeers,
|
|
208913
|
-
radisk: false,
|
|
208914
|
-
localStorage: false,
|
|
208915
|
-
multicast: false,
|
|
208916
|
-
axe: false,
|
|
208917
|
-
},
|
|
208918
|
-
silent: true,
|
|
208919
|
-
disableAutoRecall: true,
|
|
208920
|
-
});
|
|
208921
|
-
this.gun = shogunCore.db.gun;
|
|
208922
|
-
this.sea = shogunCore.db.sea;
|
|
208923
|
-
this.identity = null;
|
|
208924
|
-
}
|
|
208925
|
-
else {
|
|
208926
|
-
// WITH IDENTITY MODE - use existing Gun from SHIP-00
|
|
208927
|
-
if (!identityOrPeers.isLoggedIn()) {
|
|
208928
|
-
throw new Error("User must be authenticated via SHIP-00");
|
|
208929
|
-
}
|
|
208930
|
-
this.identity = identityOrPeers;
|
|
208931
|
-
const shogun = identityOrPeers.getShogun();
|
|
208932
|
-
this.gun = shogun.db.gun;
|
|
208887
|
+
this.vaultNode = null;
|
|
208888
|
+
this.recordsNode = null;
|
|
208889
|
+
this.metadataNode = null;
|
|
208890
|
+
if (!identity.isLoggedIn()) {
|
|
208891
|
+
throw new Error("User must be authenticated via SHIP-00 before using SHIP-06");
|
|
208933
208892
|
}
|
|
208893
|
+
this.identity = identity;
|
|
208894
|
+
this.vaultNodeName = vaultNodeName || SHIP_06.DEFAULT_NODE_NAME;
|
|
208895
|
+
console.log("✅ SHIP-06 initialized");
|
|
208934
208896
|
}
|
|
208897
|
+
/**
|
|
208898
|
+
* Get identity provider
|
|
208899
|
+
*/
|
|
208935
208900
|
getIdentity() {
|
|
208936
|
-
if (!this.identity) {
|
|
208937
|
-
throw new Error("No identity - SHIP-06 running in standalone mode");
|
|
208938
|
-
}
|
|
208939
208901
|
return this.identity;
|
|
208940
208902
|
}
|
|
208941
|
-
|
|
208942
|
-
|
|
208903
|
+
// ========================================================================
|
|
208904
|
+
// INITIALIZATION
|
|
208905
|
+
// ========================================================================
|
|
208906
|
+
/**
|
|
208907
|
+
* Initialize vault
|
|
208908
|
+
*/
|
|
208909
|
+
async initialize() {
|
|
208910
|
+
if (this.initialized) {
|
|
208911
|
+
console.warn("⚠️ Vault already initialized");
|
|
208943
208912
|
return;
|
|
208944
|
-
// Generate ephemeral pair
|
|
208945
|
-
this.myPair = await this.sea.pair();
|
|
208946
|
-
if (!this.myPair) {
|
|
208947
|
-
throw new Error("Failed to generate SEA pair");
|
|
208948
|
-
}
|
|
208949
|
-
this.myAddress = this.myPair.pub.substring(0, 16);
|
|
208950
|
-
// Hash room ID DETERMINISTICAMENTE - Simple SHA256 hash
|
|
208951
|
-
if (this.identity) {
|
|
208952
|
-
const shogun = this.identity.getShogun();
|
|
208953
|
-
this.swarmId = await shogun.db.crypto.hashText(this.roomId);
|
|
208954
208913
|
}
|
|
208955
|
-
|
|
208956
|
-
//
|
|
208957
|
-
|
|
208958
|
-
|
|
208959
|
-
|
|
208960
|
-
|
|
208961
|
-
|
|
208962
|
-
|
|
208963
|
-
|
|
208964
|
-
|
|
208965
|
-
|
|
208966
|
-
|
|
208914
|
+
try {
|
|
208915
|
+
// Get Gun instance from identity
|
|
208916
|
+
const shogun = this.identity.getShogun();
|
|
208917
|
+
if (!shogun || !shogun.db) {
|
|
208918
|
+
throw new Error("Cannot access ShogunCore from identity");
|
|
208919
|
+
}
|
|
208920
|
+
const gun = shogun.db.gun;
|
|
208921
|
+
if (!gun) {
|
|
208922
|
+
throw new Error("Cannot access GunDB");
|
|
208923
|
+
}
|
|
208924
|
+
// Get user node
|
|
208925
|
+
const userNode = gun.user();
|
|
208926
|
+
if (!userNode || !userNode.is) {
|
|
208927
|
+
throw new Error("User not authenticated in Gun");
|
|
208928
|
+
}
|
|
208929
|
+
// Setup vault nodes
|
|
208930
|
+
this.vaultNode = userNode.get(this.vaultNodeName);
|
|
208931
|
+
this.recordsNode = this.vaultNode.get("records");
|
|
208932
|
+
this.metadataNode = this.vaultNode.get("metadata");
|
|
208933
|
+
// Initialize metadata
|
|
208934
|
+
const existingMetadata = await this.metadataNode.then();
|
|
208935
|
+
if (!existingMetadata || !existingMetadata.version) {
|
|
208936
|
+
await this.metadataNode.put({
|
|
208937
|
+
version: SHIP_06.VAULT_VERSION,
|
|
208938
|
+
created: Date.now().toString(),
|
|
208939
|
+
recordCount: "0",
|
|
208940
|
+
}).then();
|
|
208941
|
+
console.log("📦 Vault metadata initialized");
|
|
208967
208942
|
}
|
|
208968
208943
|
else {
|
|
208969
|
-
|
|
208970
|
-
let hash = "";
|
|
208971
|
-
for (let i = 0; i < this.roomId.length; i++) {
|
|
208972
|
-
hash += this.roomId.charCodeAt(i).toString(16);
|
|
208973
|
-
}
|
|
208974
|
-
this.swarmId = hash;
|
|
208944
|
+
console.log("📦 Existing vault found");
|
|
208975
208945
|
}
|
|
208946
|
+
this.initialized = true;
|
|
208947
|
+
console.log("✅ Vault initialized successfully");
|
|
208976
208948
|
}
|
|
208977
|
-
|
|
208978
|
-
console.
|
|
208979
|
-
|
|
208980
|
-
}
|
|
208981
|
-
// Setup Gun nodes
|
|
208982
|
-
this.roomNode = this.gun.get("ephemeral").get(this.swarmId);
|
|
208983
|
-
this.presenceNode = this.roomNode.get("presence");
|
|
208984
|
-
this.messagesNode = this.roomNode.get("messages");
|
|
208985
|
-
// Announce presence
|
|
208986
|
-
await this.announcePresence();
|
|
208987
|
-
// Start listening
|
|
208988
|
-
this.listenForPeers();
|
|
208989
|
-
this.listenForMessages();
|
|
208990
|
-
// Start heartbeat
|
|
208991
|
-
this.startHeartbeat();
|
|
208992
|
-
this.connected = true;
|
|
208993
|
-
}
|
|
208994
|
-
disconnect() {
|
|
208995
|
-
if (this.heartbeatInterval) {
|
|
208996
|
-
clearInterval(this.heartbeatInterval);
|
|
208997
|
-
}
|
|
208998
|
-
if (this.presenceNode && this.myAddress) {
|
|
208999
|
-
this.presenceNode.get(this.myAddress).put(null);
|
|
208949
|
+
catch (error) {
|
|
208950
|
+
console.error("❌ Error initializing vault:", error);
|
|
208951
|
+
throw error;
|
|
209000
208952
|
}
|
|
209001
|
-
this.connected = false;
|
|
209002
|
-
}
|
|
209003
|
-
isConnected() {
|
|
209004
|
-
return this.connected;
|
|
209005
208953
|
}
|
|
209006
|
-
|
|
209007
|
-
|
|
209008
|
-
|
|
209009
|
-
|
|
209010
|
-
return this.
|
|
208954
|
+
/**
|
|
208955
|
+
* Check if vault is initialized
|
|
208956
|
+
*/
|
|
208957
|
+
isInitialized() {
|
|
208958
|
+
return this.initialized;
|
|
209011
208959
|
}
|
|
209012
208960
|
// ========================================================================
|
|
209013
|
-
//
|
|
208961
|
+
// CRUD OPERATIONS
|
|
209014
208962
|
// ========================================================================
|
|
209015
|
-
|
|
209016
|
-
|
|
209017
|
-
|
|
209018
|
-
|
|
209019
|
-
|
|
209020
|
-
|
|
209021
|
-
|
|
209022
|
-
|
|
209023
|
-
|
|
209024
|
-
|
|
209025
|
-
|
|
209026
|
-
|
|
209027
|
-
|
|
209028
|
-
|
|
209029
|
-
|
|
209030
|
-
|
|
209031
|
-
|
|
209032
|
-
|
|
209033
|
-
|
|
209034
|
-
|
|
209035
|
-
|
|
209036
|
-
|
|
209037
|
-
|
|
209038
|
-
|
|
209039
|
-
|
|
208963
|
+
/**
|
|
208964
|
+
* Store encrypted record in vault
|
|
208965
|
+
*/
|
|
208966
|
+
async put(name, data, metadata) {
|
|
208967
|
+
if (!this.initialized) {
|
|
208968
|
+
return { success: false, error: "Vault not initialized" };
|
|
208969
|
+
}
|
|
208970
|
+
if (!name || name.trim() === "") {
|
|
208971
|
+
return { success: false, error: "Record name cannot be empty" };
|
|
208972
|
+
}
|
|
208973
|
+
try {
|
|
208974
|
+
// Get crypto and key pair
|
|
208975
|
+
const shogun = this.identity.getShogun();
|
|
208976
|
+
const crypto = shogun?.db?.crypto;
|
|
208977
|
+
const pair = this.identity.getKeyPair();
|
|
208978
|
+
if (!crypto || !pair) {
|
|
208979
|
+
return { success: false, error: "Cannot access encryption" };
|
|
208980
|
+
}
|
|
208981
|
+
// Encrypt data
|
|
208982
|
+
const dataString = JSON.stringify(data);
|
|
208983
|
+
const encryptedData = await crypto.encrypt(dataString, pair.epriv);
|
|
208984
|
+
// Encrypt metadata if provided
|
|
208985
|
+
let encryptedMetadata;
|
|
208986
|
+
if (metadata) {
|
|
208987
|
+
const metadataString = JSON.stringify(metadata);
|
|
208988
|
+
encryptedMetadata = await crypto.encrypt(metadataString, pair.epriv);
|
|
208989
|
+
}
|
|
208990
|
+
// Create encrypted record
|
|
208991
|
+
const record = {
|
|
208992
|
+
data: encryptedData,
|
|
208993
|
+
created: Date.now().toString(),
|
|
208994
|
+
updated: Date.now().toString(),
|
|
208995
|
+
deleted: false,
|
|
208996
|
+
metadata: encryptedMetadata,
|
|
208997
|
+
};
|
|
208998
|
+
// Store in vault
|
|
208999
|
+
await this.recordsNode.get(name).put(record).then();
|
|
209000
|
+
// Update vault metadata
|
|
209001
|
+
await this.updateRecordCount();
|
|
209002
|
+
console.log(`✅ Record stored: ${name}`);
|
|
209003
|
+
return {
|
|
209004
|
+
success: true,
|
|
209005
|
+
recordName: name,
|
|
209006
|
+
};
|
|
209007
|
+
}
|
|
209008
|
+
catch (error) {
|
|
209009
|
+
console.error("❌ Error storing record:", error);
|
|
209010
|
+
return {
|
|
209011
|
+
success: false,
|
|
209012
|
+
error: error.message,
|
|
209013
|
+
};
|
|
209014
|
+
}
|
|
209040
209015
|
}
|
|
209041
|
-
|
|
209042
|
-
|
|
209043
|
-
|
|
209016
|
+
/**
|
|
209017
|
+
* Retrieve and decrypt record from vault
|
|
209018
|
+
*/
|
|
209019
|
+
async get(name, options) {
|
|
209020
|
+
if (!this.initialized) {
|
|
209021
|
+
console.error("❌ Vault not initialized");
|
|
209022
|
+
return null;
|
|
209044
209023
|
}
|
|
209045
|
-
|
|
209046
|
-
|
|
209047
|
-
|
|
209024
|
+
try {
|
|
209025
|
+
// Retrieve encrypted record
|
|
209026
|
+
const encryptedRecord = await this.recordsNode.get(name).then();
|
|
209027
|
+
if (!encryptedRecord || !encryptedRecord.data) {
|
|
209028
|
+
return null;
|
|
209048
209029
|
}
|
|
209049
|
-
|
|
209050
|
-
|
|
209030
|
+
// Check if deleted (unless includeDeleted)
|
|
209031
|
+
if (encryptedRecord.deleted && !options?.includeDeleted) {
|
|
209032
|
+
return null;
|
|
209051
209033
|
}
|
|
209052
|
-
|
|
209053
|
-
const
|
|
209054
|
-
|
|
209055
|
-
|
|
209056
|
-
|
|
209057
|
-
|
|
209058
|
-
|
|
209059
|
-
|
|
209060
|
-
|
|
209061
|
-
|
|
209062
|
-
|
|
209063
|
-
|
|
209034
|
+
// Get crypto and key pair
|
|
209035
|
+
const shogun = this.identity.getShogun();
|
|
209036
|
+
const crypto = shogun?.db?.crypto;
|
|
209037
|
+
const pair = this.identity.getKeyPair();
|
|
209038
|
+
if (!crypto || !pair) {
|
|
209039
|
+
console.error("❌ Cannot access encryption");
|
|
209040
|
+
return null;
|
|
209041
|
+
}
|
|
209042
|
+
// Decrypt data
|
|
209043
|
+
const decryptedDataString = await crypto.decrypt(encryptedRecord.data, pair.epriv);
|
|
209044
|
+
// Try to parse JSON, if it fails, use the string as-is
|
|
209045
|
+
let decryptedData;
|
|
209046
|
+
try {
|
|
209047
|
+
decryptedData = JSON.parse(decryptedDataString);
|
|
209048
|
+
}
|
|
209049
|
+
catch (parseError) {
|
|
209050
|
+
// If JSON.parse fails, the data is likely a plain string
|
|
209051
|
+
// This can happen if the data was already a string value
|
|
209052
|
+
decryptedData = decryptedDataString;
|
|
209053
|
+
}
|
|
209054
|
+
// Decrypt metadata if present
|
|
209055
|
+
let decryptedMetadata;
|
|
209056
|
+
if (encryptedRecord.metadata) {
|
|
209057
|
+
try {
|
|
209058
|
+
const metadataString = await crypto.decrypt(encryptedRecord.metadata, pair.epriv);
|
|
209059
|
+
decryptedMetadata = JSON.parse(metadataString);
|
|
209064
209060
|
}
|
|
209061
|
+
catch (error) {
|
|
209062
|
+
// Metadata decryption failed, continue without it
|
|
209063
|
+
console.warn("⚠️ Could not decrypt metadata");
|
|
209064
|
+
}
|
|
209065
|
+
}
|
|
209066
|
+
// Create vault record
|
|
209067
|
+
const vaultRecord = {
|
|
209068
|
+
name,
|
|
209069
|
+
data: decryptedData,
|
|
209070
|
+
created: parseInt(encryptedRecord.created),
|
|
209071
|
+
updated: parseInt(encryptedRecord.updated),
|
|
209072
|
+
deleted: encryptedRecord.deleted,
|
|
209073
|
+
metadata: decryptedMetadata,
|
|
209074
|
+
};
|
|
209075
|
+
return vaultRecord;
|
|
209076
|
+
}
|
|
209077
|
+
catch (error) {
|
|
209078
|
+
console.error("❌ Error retrieving record:", error);
|
|
209079
|
+
return null;
|
|
209080
|
+
}
|
|
209081
|
+
}
|
|
209082
|
+
/**
|
|
209083
|
+
* Delete record from vault (soft delete)
|
|
209084
|
+
*/
|
|
209085
|
+
async delete(name) {
|
|
209086
|
+
if (!this.initialized) {
|
|
209087
|
+
return { success: false, error: "Vault not initialized" };
|
|
209088
|
+
}
|
|
209089
|
+
try {
|
|
209090
|
+
if (name) {
|
|
209091
|
+
// Delete specific record (soft delete)
|
|
209092
|
+
const existingRecord = await this.recordsNode.get(name).then();
|
|
209093
|
+
if (!existingRecord) {
|
|
209094
|
+
return { success: false, error: `Record ${name} not found` };
|
|
209095
|
+
}
|
|
209096
|
+
// Mark as deleted
|
|
209097
|
+
await this.recordsNode.get(name).get("deleted").put(true).then();
|
|
209098
|
+
await this.recordsNode.get(name).get("updated").put(Date.now().toString()).then();
|
|
209099
|
+
console.log(`🗑️ Record soft-deleted: ${name}`);
|
|
209100
|
+
return {
|
|
209101
|
+
success: true,
|
|
209102
|
+
recordName: name,
|
|
209103
|
+
};
|
|
209065
209104
|
}
|
|
209066
209105
|
else {
|
|
209067
|
-
|
|
209068
|
-
|
|
209069
|
-
|
|
209070
|
-
|
|
209071
|
-
|
|
209072
|
-
|
|
209106
|
+
// Delete all records (soft delete)
|
|
209107
|
+
const allRecords = await this.list({ includeDeleted: false });
|
|
209108
|
+
let deletedCount = 0;
|
|
209109
|
+
for (const recordName of allRecords) {
|
|
209110
|
+
const result = await this.delete(recordName);
|
|
209111
|
+
if (result.success) {
|
|
209112
|
+
deletedCount++;
|
|
209113
|
+
}
|
|
209073
209114
|
}
|
|
209115
|
+
console.log(`🗑️ ${deletedCount} records soft-deleted`);
|
|
209116
|
+
return {
|
|
209117
|
+
success: true,
|
|
209118
|
+
recordCount: deletedCount,
|
|
209119
|
+
};
|
|
209074
209120
|
}
|
|
209075
|
-
}
|
|
209121
|
+
}
|
|
209122
|
+
catch (error) {
|
|
209123
|
+
console.error("❌ Error deleting record:", error);
|
|
209124
|
+
return {
|
|
209125
|
+
success: false,
|
|
209126
|
+
error: error.message,
|
|
209127
|
+
};
|
|
209128
|
+
}
|
|
209129
|
+
}
|
|
209130
|
+
/**
|
|
209131
|
+
* List all record names in vault
|
|
209132
|
+
*/
|
|
209133
|
+
async list(options) {
|
|
209134
|
+
if (!this.initialized) {
|
|
209135
|
+
console.error("❌ Vault not initialized");
|
|
209136
|
+
return [];
|
|
209137
|
+
}
|
|
209138
|
+
try {
|
|
209139
|
+
return new Promise((resolve) => {
|
|
209140
|
+
const recordNames = [];
|
|
209141
|
+
this.recordsNode.map().once(async (record, key) => {
|
|
209142
|
+
// Skip metadata
|
|
209143
|
+
if (!record || typeof record !== "object" || key === "_") {
|
|
209144
|
+
return;
|
|
209145
|
+
}
|
|
209146
|
+
// Skip deleted records (unless includeDeleted)
|
|
209147
|
+
if (record.deleted && !options?.includeDeleted) {
|
|
209148
|
+
return;
|
|
209149
|
+
}
|
|
209150
|
+
// Apply filters if provided
|
|
209151
|
+
if (options?.filterByType || options?.filterByTag) {
|
|
209152
|
+
try {
|
|
209153
|
+
// Need to decrypt metadata to filter
|
|
209154
|
+
const shogun = this.identity.getShogun();
|
|
209155
|
+
const crypto = shogun?.db?.crypto;
|
|
209156
|
+
const pair = this.identity.getKeyPair();
|
|
209157
|
+
if (crypto && pair && record.metadata) {
|
|
209158
|
+
const metadataString = await crypto.decrypt(record.metadata, pair.epriv);
|
|
209159
|
+
const metadata = JSON.parse(metadataString);
|
|
209160
|
+
// Filter by type
|
|
209161
|
+
if (options.filterByType && metadata.type !== options.filterByType) {
|
|
209162
|
+
return;
|
|
209163
|
+
}
|
|
209164
|
+
// Filter by tag
|
|
209165
|
+
if (options.filterByTag) {
|
|
209166
|
+
if (!metadata.tags || !metadata.tags.includes(options.filterByTag)) {
|
|
209167
|
+
return;
|
|
209168
|
+
}
|
|
209169
|
+
}
|
|
209170
|
+
}
|
|
209171
|
+
}
|
|
209172
|
+
catch (error) {
|
|
209173
|
+
// Decryption failed, skip
|
|
209174
|
+
return;
|
|
209175
|
+
}
|
|
209176
|
+
}
|
|
209177
|
+
recordNames.push(key);
|
|
209178
|
+
});
|
|
209179
|
+
// Wait for Gun to return all records
|
|
209180
|
+
setTimeout(() => {
|
|
209181
|
+
// Sort if requested
|
|
209182
|
+
if (options?.sortBy) {
|
|
209183
|
+
// For now, just sort by name
|
|
209184
|
+
recordNames.sort();
|
|
209185
|
+
if (options.sortDesc) {
|
|
209186
|
+
recordNames.reverse();
|
|
209187
|
+
}
|
|
209188
|
+
}
|
|
209189
|
+
resolve(recordNames);
|
|
209190
|
+
}, 1000);
|
|
209191
|
+
});
|
|
209192
|
+
}
|
|
209193
|
+
catch (error) {
|
|
209194
|
+
console.error("❌ Error listing records:", error);
|
|
209195
|
+
return [];
|
|
209196
|
+
}
|
|
209197
|
+
}
|
|
209198
|
+
/**
|
|
209199
|
+
* Check if record exists
|
|
209200
|
+
*/
|
|
209201
|
+
async exists(name) {
|
|
209202
|
+
const record = await this.get(name);
|
|
209203
|
+
return record !== null;
|
|
209204
|
+
}
|
|
209205
|
+
/**
|
|
209206
|
+
* Update existing record
|
|
209207
|
+
*/
|
|
209208
|
+
async update(name, data) {
|
|
209209
|
+
if (!this.initialized) {
|
|
209210
|
+
return { success: false, error: "Vault not initialized" };
|
|
209211
|
+
}
|
|
209212
|
+
try {
|
|
209213
|
+
// Check if record exists
|
|
209214
|
+
const existingRecord = await this.get(name);
|
|
209215
|
+
if (!existingRecord) {
|
|
209216
|
+
return { success: false, error: `Record ${name} not found` };
|
|
209217
|
+
}
|
|
209218
|
+
// Keep existing metadata
|
|
209219
|
+
return await this.put(name, data, existingRecord.metadata);
|
|
209220
|
+
}
|
|
209221
|
+
catch (error) {
|
|
209222
|
+
console.error("❌ Error updating record:", error);
|
|
209223
|
+
return {
|
|
209224
|
+
success: false,
|
|
209225
|
+
error: error.message,
|
|
209226
|
+
};
|
|
209227
|
+
}
|
|
209076
209228
|
}
|
|
209077
209229
|
// ========================================================================
|
|
209078
|
-
//
|
|
209230
|
+
// BACKUP & RESTORE
|
|
209079
209231
|
// ========================================================================
|
|
209080
|
-
|
|
209081
|
-
|
|
209082
|
-
|
|
209083
|
-
|
|
209084
|
-
if (this.
|
|
209085
|
-
|
|
209086
|
-
return;
|
|
209232
|
+
/**
|
|
209233
|
+
* Export entire vault (encrypted)
|
|
209234
|
+
*/
|
|
209235
|
+
async export(password, options) {
|
|
209236
|
+
if (!this.initialized) {
|
|
209237
|
+
throw new Error("Vault not initialized");
|
|
209087
209238
|
}
|
|
209088
|
-
|
|
209089
|
-
|
|
209090
|
-
|
|
209091
|
-
|
|
209092
|
-
|
|
209093
|
-
|
|
209094
|
-
|
|
209095
|
-
|
|
209096
|
-
|
|
209097
|
-
|
|
209098
|
-
|
|
209099
|
-
timestamp: Date.now(),
|
|
209100
|
-
type: "broadcast",
|
|
209239
|
+
try {
|
|
209240
|
+
// Get all records
|
|
209241
|
+
const recordNames = await this.list({
|
|
209242
|
+
includeDeleted: options?.includeDeleted || false,
|
|
209243
|
+
filterByTag: options?.filterByTag,
|
|
209244
|
+
filterByType: options?.filterByType,
|
|
209245
|
+
});
|
|
209246
|
+
const records = {};
|
|
209247
|
+
for (const name of recordNames) {
|
|
209248
|
+
const record = await this.get(name, {
|
|
209249
|
+
includeDeleted: options?.includeDeleted || false,
|
|
209101
209250
|
});
|
|
209251
|
+
if (record) {
|
|
209252
|
+
records[name] = record;
|
|
209253
|
+
}
|
|
209102
209254
|
}
|
|
209103
|
-
|
|
209104
|
-
|
|
209105
|
-
|
|
209106
|
-
|
|
209107
|
-
|
|
209108
|
-
|
|
209109
|
-
|
|
209110
|
-
|
|
209111
|
-
|
|
209112
|
-
|
|
209113
|
-
|
|
209114
|
-
|
|
209115
|
-
|
|
209116
|
-
|
|
209117
|
-
|
|
209118
|
-
|
|
209119
|
-
|
|
209120
|
-
|
|
209121
|
-
|
|
209122
|
-
|
|
209123
|
-
|
|
209124
|
-
|
|
209125
|
-
|
|
209255
|
+
// Create export data
|
|
209256
|
+
const exportData = {
|
|
209257
|
+
version: SHIP_06.VAULT_VERSION,
|
|
209258
|
+
exportedAt: Date.now(),
|
|
209259
|
+
exportedBy: this.identity.getCurrentUser()?.pub,
|
|
209260
|
+
recordCount: Object.keys(records).length,
|
|
209261
|
+
records,
|
|
209262
|
+
};
|
|
209263
|
+
// Serialize to JSON
|
|
209264
|
+
const jsonString = options?.pretty
|
|
209265
|
+
? JSON.stringify(exportData, null, 2)
|
|
209266
|
+
: JSON.stringify(exportData);
|
|
209267
|
+
// Optionally encrypt with password
|
|
209268
|
+
if (password) {
|
|
209269
|
+
const crypto = this.identity.shogun?.db?.crypto;
|
|
209270
|
+
if (!crypto) {
|
|
209271
|
+
throw new Error("Cannot access crypto");
|
|
209272
|
+
}
|
|
209273
|
+
const encryptedJson = await crypto.encrypt(jsonString, password);
|
|
209274
|
+
const base64 = Buffer.from(encryptedJson).toString("base64");
|
|
209275
|
+
console.log(`✅ Vault exported (encrypted, ${base64.length} chars)`);
|
|
209276
|
+
return base64;
|
|
209277
|
+
}
|
|
209278
|
+
// Otherwise, return as base64
|
|
209279
|
+
const base64 = Buffer.from(jsonString).toString("base64");
|
|
209280
|
+
console.log(`✅ Vault exported (${base64.length} chars)`);
|
|
209281
|
+
return base64;
|
|
209282
|
+
}
|
|
209283
|
+
catch (error) {
|
|
209284
|
+
console.error("❌ Error exporting vault:", error);
|
|
209285
|
+
throw error;
|
|
209286
|
+
}
|
|
209126
209287
|
}
|
|
209127
|
-
|
|
209128
|
-
|
|
209129
|
-
|
|
209130
|
-
|
|
209131
|
-
|
|
209132
|
-
|
|
209133
|
-
|
|
209134
|
-
|
|
209135
|
-
|
|
209136
|
-
|
|
209137
|
-
|
|
209138
|
-
|
|
209139
|
-
|
|
209140
|
-
|
|
209141
|
-
|
|
209142
|
-
|
|
209143
|
-
|
|
209144
|
-
|
|
209145
|
-
|
|
209146
|
-
|
|
209288
|
+
/**
|
|
209289
|
+
* Import vault from backup
|
|
209290
|
+
*/
|
|
209291
|
+
async import(backupData, password, options) {
|
|
209292
|
+
if (!this.initialized) {
|
|
209293
|
+
return { success: false, error: "Vault not initialized" };
|
|
209294
|
+
}
|
|
209295
|
+
try {
|
|
209296
|
+
// Decode base64
|
|
209297
|
+
let jsonString = Buffer.from(backupData, "base64").toString("utf-8");
|
|
209298
|
+
// Decrypt if password provided
|
|
209299
|
+
if (password) {
|
|
209300
|
+
const crypto = this.identity.shogun?.db?.crypto;
|
|
209301
|
+
if (!crypto) {
|
|
209302
|
+
return { success: false, error: "Cannot access crypto" };
|
|
209303
|
+
}
|
|
209304
|
+
jsonString = await crypto.decrypt(jsonString, password);
|
|
209305
|
+
}
|
|
209306
|
+
// Parse JSON
|
|
209307
|
+
const importData = JSON.parse(jsonString);
|
|
209308
|
+
// Validate version
|
|
209309
|
+
if (importData.version !== SHIP_06.VAULT_VERSION) {
|
|
209310
|
+
console.warn(`⚠️ Version mismatch: ${importData.version} vs ${SHIP_06.VAULT_VERSION}`);
|
|
209311
|
+
}
|
|
209312
|
+
// Import records
|
|
209313
|
+
let importedCount = 0;
|
|
209314
|
+
let skippedCount = 0;
|
|
209315
|
+
for (const [name, record] of Object.entries(importData.records)) {
|
|
209316
|
+
const vaultRecord = record;
|
|
209317
|
+
// Skip deleted records if requested
|
|
209318
|
+
if (options?.skipDeleted && vaultRecord.deleted) {
|
|
209319
|
+
skippedCount++;
|
|
209320
|
+
continue;
|
|
209147
209321
|
}
|
|
209148
|
-
if (
|
|
209149
|
-
|
|
209150
|
-
|
|
209151
|
-
|
|
209152
|
-
|
|
209153
|
-
|
|
209154
|
-
|
|
209155
|
-
|
|
209156
|
-
|
|
209157
|
-
|
|
209158
|
-
|
|
209159
|
-
|
|
209160
|
-
|
|
209161
|
-
|
|
209162
|
-
|
|
209163
|
-
|
|
209164
|
-
|
|
209165
|
-
|
|
209166
|
-
|
|
209167
|
-
|
|
209322
|
+
// Check if exists (if merge mode)
|
|
209323
|
+
const exists = await this.exists(name);
|
|
209324
|
+
if (exists) {
|
|
209325
|
+
if (options?.overwrite) {
|
|
209326
|
+
// Overwrite existing
|
|
209327
|
+
await this.put(name, vaultRecord.data, vaultRecord.metadata);
|
|
209328
|
+
importedCount++;
|
|
209329
|
+
}
|
|
209330
|
+
else if (!options?.merge) {
|
|
209331
|
+
// Skip if not merge and not overwrite
|
|
209332
|
+
skippedCount++;
|
|
209333
|
+
continue;
|
|
209334
|
+
}
|
|
209335
|
+
else {
|
|
209336
|
+
// Merge mode: skip existing
|
|
209337
|
+
skippedCount++;
|
|
209338
|
+
continue;
|
|
209339
|
+
}
|
|
209340
|
+
}
|
|
209341
|
+
else {
|
|
209342
|
+
// Import new record
|
|
209343
|
+
await this.put(name, vaultRecord.data, vaultRecord.metadata);
|
|
209344
|
+
importedCount++;
|
|
209168
209345
|
}
|
|
209169
209346
|
}
|
|
209170
|
-
|
|
209347
|
+
console.log(`✅ Vault imported: ${importedCount} records (${skippedCount} skipped)`);
|
|
209348
|
+
return {
|
|
209349
|
+
success: true,
|
|
209350
|
+
recordCount: importedCount,
|
|
209351
|
+
};
|
|
209352
|
+
}
|
|
209353
|
+
catch (error) {
|
|
209354
|
+
console.error("❌ Error importing vault:", error);
|
|
209355
|
+
return {
|
|
209356
|
+
success: false,
|
|
209357
|
+
error: error.message,
|
|
209358
|
+
};
|
|
209359
|
+
}
|
|
209171
209360
|
}
|
|
209172
209361
|
// ========================================================================
|
|
209173
|
-
//
|
|
209362
|
+
// UTILITIES
|
|
209174
209363
|
// ========================================================================
|
|
209175
|
-
|
|
209176
|
-
|
|
209177
|
-
|
|
209178
|
-
|
|
209179
|
-
this.
|
|
209180
|
-
|
|
209181
|
-
|
|
209182
|
-
|
|
209183
|
-
|
|
209184
|
-
|
|
209185
|
-
|
|
209364
|
+
/**
|
|
209365
|
+
* Get vault statistics
|
|
209366
|
+
*/
|
|
209367
|
+
async getStats() {
|
|
209368
|
+
if (!this.initialized) {
|
|
209369
|
+
throw new Error("Vault not initialized");
|
|
209370
|
+
}
|
|
209371
|
+
try {
|
|
209372
|
+
const allRecords = await this.list({ includeDeleted: true });
|
|
209373
|
+
const activeRecords = await this.list({ includeDeleted: false });
|
|
209374
|
+
// Get metadata
|
|
209375
|
+
const metadata = await this.metadataNode.then();
|
|
209376
|
+
const stats = {
|
|
209377
|
+
totalRecords: allRecords.length,
|
|
209378
|
+
activeRecords: activeRecords.length,
|
|
209379
|
+
deletedRecords: allRecords.length - activeRecords.length,
|
|
209380
|
+
totalSize: 0, // TODO: Calculate actual size
|
|
209381
|
+
created: metadata?.created ? parseInt(metadata.created) : Date.now(),
|
|
209382
|
+
lastModified: Date.now(),
|
|
209383
|
+
recordsByType: {},
|
|
209384
|
+
};
|
|
209385
|
+
// Count by type
|
|
209386
|
+
for (const name of activeRecords) {
|
|
209387
|
+
const record = await this.get(name);
|
|
209388
|
+
if (record && record.metadata?.type) {
|
|
209389
|
+
const type = record.metadata.type;
|
|
209390
|
+
stats.recordsByType[type] = (stats.recordsByType[type] || 0) + 1;
|
|
209391
|
+
}
|
|
209392
|
+
}
|
|
209393
|
+
return stats;
|
|
209394
|
+
}
|
|
209395
|
+
catch (error) {
|
|
209396
|
+
console.error("❌ Error getting stats:", error);
|
|
209397
|
+
throw error;
|
|
209398
|
+
}
|
|
209186
209399
|
}
|
|
209187
|
-
|
|
209188
|
-
|
|
209400
|
+
/**
|
|
209401
|
+
* Clear all records (soft delete all)
|
|
209402
|
+
*/
|
|
209403
|
+
async clear() {
|
|
209404
|
+
return await this.delete(); // Delete without name = delete all
|
|
209189
209405
|
}
|
|
209190
|
-
|
|
209191
|
-
|
|
209406
|
+
/**
|
|
209407
|
+
* Compact vault (remove deleted records permanently)
|
|
209408
|
+
*/
|
|
209409
|
+
async compact() {
|
|
209410
|
+
if (!this.initialized) {
|
|
209411
|
+
return { success: false, error: "Vault not initialized" };
|
|
209412
|
+
}
|
|
209413
|
+
try {
|
|
209414
|
+
// Get all deleted records
|
|
209415
|
+
const allRecords = await this.list({ includeDeleted: true });
|
|
209416
|
+
let compactedCount = 0;
|
|
209417
|
+
for (const name of allRecords) {
|
|
209418
|
+
const record = await this.get(name, { includeDeleted: true });
|
|
209419
|
+
if (record && record.deleted) {
|
|
209420
|
+
// Permanently remove
|
|
209421
|
+
await this.recordsNode.get(name).put(null).then();
|
|
209422
|
+
compactedCount++;
|
|
209423
|
+
}
|
|
209424
|
+
}
|
|
209425
|
+
// Update metadata
|
|
209426
|
+
await this.updateRecordCount();
|
|
209427
|
+
console.log(`✅ Vault compacted: ${compactedCount} records permanently removed`);
|
|
209428
|
+
return {
|
|
209429
|
+
success: true,
|
|
209430
|
+
recordCount: compactedCount,
|
|
209431
|
+
};
|
|
209432
|
+
}
|
|
209433
|
+
catch (error) {
|
|
209434
|
+
console.error("❌ Error compacting vault:", error);
|
|
209435
|
+
return {
|
|
209436
|
+
success: false,
|
|
209437
|
+
error: error.message,
|
|
209438
|
+
};
|
|
209439
|
+
}
|
|
209192
209440
|
}
|
|
209193
|
-
|
|
209194
|
-
|
|
209195
|
-
|
|
209196
|
-
|
|
209441
|
+
/**
|
|
209442
|
+
* Search records by content
|
|
209443
|
+
*/
|
|
209444
|
+
async search(query) {
|
|
209445
|
+
if (!this.initialized) {
|
|
209446
|
+
return [];
|
|
209447
|
+
}
|
|
209448
|
+
try {
|
|
209449
|
+
const allRecords = await this.list({ includeDeleted: false });
|
|
209450
|
+
const matches = [];
|
|
209451
|
+
for (const name of allRecords) {
|
|
209452
|
+
const record = await this.get(name);
|
|
209453
|
+
if (record) {
|
|
209454
|
+
// Search in data (converted to string)
|
|
209455
|
+
const dataString = JSON.stringify(record.data).toLowerCase();
|
|
209456
|
+
const queryLower = query.toLowerCase();
|
|
209457
|
+
if (dataString.includes(queryLower) || name.toLowerCase().includes(queryLower)) {
|
|
209458
|
+
matches.push(name);
|
|
209459
|
+
}
|
|
209460
|
+
}
|
|
209461
|
+
}
|
|
209462
|
+
return matches;
|
|
209463
|
+
}
|
|
209464
|
+
catch (error) {
|
|
209465
|
+
console.error("❌ Error searching records:", error);
|
|
209466
|
+
return [];
|
|
209467
|
+
}
|
|
209197
209468
|
}
|
|
209198
|
-
|
|
209199
|
-
|
|
209469
|
+
// ========================================================================
|
|
209470
|
+
// PRIVATE HELPERS
|
|
209471
|
+
// ========================================================================
|
|
209472
|
+
/**
|
|
209473
|
+
* Update record count in metadata
|
|
209474
|
+
*/
|
|
209475
|
+
async updateRecordCount() {
|
|
209476
|
+
try {
|
|
209477
|
+
const activeRecords = await this.list({ includeDeleted: false });
|
|
209478
|
+
await this.metadataNode.get("recordCount").put(activeRecords.length.toString()).then();
|
|
209479
|
+
}
|
|
209480
|
+
catch (error) {
|
|
209481
|
+
console.error("❌ Error updating record count:", error);
|
|
209482
|
+
}
|
|
209200
209483
|
}
|
|
209201
209484
|
}
|
|
209202
209485
|
exports.SHIP_06 = SHIP_06;
|
|
209486
|
+
// Constants
|
|
209487
|
+
SHIP_06.VAULT_VERSION = "1.0.0";
|
|
209488
|
+
SHIP_06.DEFAULT_NODE_NAME = "vault";
|
|
209203
209489
|
|
|
209204
209490
|
|
|
209205
209491
|
/***/ }),
|
|
@@ -211002,9 +211288,6 @@ class DataBase {
|
|
|
211002
211288
|
this.user = this.gun.user().recall({ sessionStorage: true });
|
|
211003
211289
|
}
|
|
211004
211290
|
else {
|
|
211005
|
-
if (!this.silent && !this.disableAutoRecall) {
|
|
211006
|
-
console.log("No pair found in sessionStorage, using gun.user()");
|
|
211007
|
-
}
|
|
211008
211291
|
this.user = this.gun.user();
|
|
211009
211292
|
}
|
|
211010
211293
|
this.subscribeToAuthEvents();
|
|
@@ -211053,7 +211336,6 @@ class DataBase {
|
|
|
211053
211336
|
*/
|
|
211054
211337
|
addPeer(peer) {
|
|
211055
211338
|
this.gun.opt({ peers: [peer] });
|
|
211056
|
-
console.log(`Added new peer: ${peer}`);
|
|
211057
211339
|
}
|
|
211058
211340
|
/**
|
|
211059
211341
|
* Removes a peer from the network
|
|
@@ -211071,10 +211353,9 @@ class DataBase {
|
|
|
211071
211353
|
if (peerConnection && typeof peerConnection.close === "function") {
|
|
211072
211354
|
peerConnection.close();
|
|
211073
211355
|
}
|
|
211074
|
-
console.log(`Removed peer: ${peer}`);
|
|
211075
211356
|
}
|
|
211076
211357
|
else {
|
|
211077
|
-
console.
|
|
211358
|
+
console.error(`Peer not found in current connections: ${peer}`);
|
|
211078
211359
|
}
|
|
211079
211360
|
}
|
|
211080
211361
|
catch (error) {
|
|
@@ -211159,7 +211440,6 @@ class DataBase {
|
|
|
211159
211440
|
this.removePeer(peer);
|
|
211160
211441
|
// Add it back immediately instead of with timeout
|
|
211161
211442
|
this.addPeer(peer);
|
|
211162
|
-
console.log(`Reconnected to peer: ${peer}`);
|
|
211163
211443
|
}
|
|
211164
211444
|
catch (error) {
|
|
211165
211445
|
console.error(`Error reconnecting to peer ${peer}:`, error);
|
|
@@ -211183,7 +211463,6 @@ class DataBase {
|
|
|
211183
211463
|
this.addPeer(peer);
|
|
211184
211464
|
});
|
|
211185
211465
|
}
|
|
211186
|
-
console.log(`Gun database reset with ${newPeers ? newPeers.length : 0} peers: ${newPeers ? newPeers.join(", ") : "none"}`);
|
|
211187
211466
|
}
|
|
211188
211467
|
}
|
|
211189
211468
|
catch (error) {
|
|
@@ -211420,7 +211699,6 @@ class DataBase {
|
|
|
211420
211699
|
else {
|
|
211421
211700
|
const recallResult = userInstance;
|
|
211422
211701
|
}
|
|
211423
|
-
// console.log("recallResult", recallResult);
|
|
211424
211702
|
}
|
|
211425
211703
|
catch (recallError) {
|
|
211426
211704
|
console.error("Error during recall:", recallError);
|
|
@@ -211464,7 +211742,6 @@ class DataBase {
|
|
|
211464
211742
|
try {
|
|
211465
211743
|
const currentUser = this.gun.user();
|
|
211466
211744
|
if (!currentUser || !currentUser.is) {
|
|
211467
|
-
console.log("No user logged in, skipping logout");
|
|
211468
211745
|
return;
|
|
211469
211746
|
}
|
|
211470
211747
|
// Log out user
|
|
@@ -211623,7 +211900,6 @@ class DataBase {
|
|
|
211623
211900
|
});
|
|
211624
211901
|
}
|
|
211625
211902
|
else {
|
|
211626
|
-
console.log(`User created successfully with userPub: ${userPub}`);
|
|
211627
211903
|
resolve({ success: true, userPub: userPub });
|
|
211628
211904
|
}
|
|
211629
211905
|
}
|
|
@@ -211659,7 +211935,6 @@ class DataBase {
|
|
|
211659
211935
|
}
|
|
211660
211936
|
if (pair) {
|
|
211661
211937
|
this.gun.user().auth(pair, (ack) => {
|
|
211662
|
-
console.log(`Pair authentication after creation result:`, ack);
|
|
211663
211938
|
if (ack.err) {
|
|
211664
211939
|
console.error(`Authentication after creation failed: ${ack.err}`);
|
|
211665
211940
|
resolve({ success: false, error: ack.err });
|
|
@@ -211669,9 +211944,6 @@ class DataBase {
|
|
|
211669
211944
|
setTimeout(() => {
|
|
211670
211945
|
// Extract userPub from multiple possible sources
|
|
211671
211946
|
const userPub = ack.pub || this.gun.user().is?.pub || ack.user?.pub;
|
|
211672
|
-
console.log(`Extracted userPub after pair auth: ${userPub}`);
|
|
211673
|
-
console.log(`User object after pair auth:`, this.gun.user());
|
|
211674
|
-
console.log(`User.is after pair auth:`, this.gun.user().is);
|
|
211675
211947
|
if (!userPub) {
|
|
211676
211948
|
console.error("Authentication successful but no userPub found");
|
|
211677
211949
|
resolve({
|
|
@@ -211688,7 +211960,6 @@ class DataBase {
|
|
|
211688
211960
|
}
|
|
211689
211961
|
else {
|
|
211690
211962
|
this.gun.user().auth(normalizedUsername, password, (ack) => {
|
|
211691
|
-
console.log(`Password authentication after creation result:`, ack);
|
|
211692
211963
|
if (ack.err) {
|
|
211693
211964
|
console.error(`Authentication after creation failed: ${ack.err}`);
|
|
211694
211965
|
resolve({ success: false, error: ack.err });
|
|
@@ -211698,9 +211969,6 @@ class DataBase {
|
|
|
211698
211969
|
setTimeout(() => {
|
|
211699
211970
|
// Extract userPub from multiple possible sources
|
|
211700
211971
|
const userPub = ack.pub || this.gun.user().is?.pub || ack.user?.pub;
|
|
211701
|
-
console.log(`Extracted userPub after password auth: ${userPub}`);
|
|
211702
|
-
console.log(`User object after password auth:`, this.gun.user());
|
|
211703
|
-
console.log(`User.is after password auth:`, this.gun.user().is);
|
|
211704
211972
|
if (!userPub) {
|
|
211705
211973
|
console.error("Authentication successful but no userPub found");
|
|
211706
211974
|
resolve({
|
|
@@ -211764,7 +212032,6 @@ class DataBase {
|
|
|
211764
212032
|
this.user = this.gun.user();
|
|
211765
212033
|
// Run post-authentication tasks
|
|
211766
212034
|
try {
|
|
211767
|
-
console.log(`Running post-auth setup with userPub: ${authResult.userPub}`);
|
|
211768
212035
|
const postAuthResult = await this.runPostAuthOnAuthResult(username, authResult.userPub, authResult);
|
|
211769
212036
|
// Return the post-auth result which includes the complete user data
|
|
211770
212037
|
return postAuthResult;
|
|
@@ -211821,7 +212088,6 @@ class DataBase {
|
|
|
211821
212088
|
// For pair-based authentication, we don't need to call gun.user().create()
|
|
211822
212089
|
// because the pair already contains the cryptographic credentials
|
|
211823
212090
|
// We just need to validate that the pair is valid and return success
|
|
211824
|
-
console.log(`User created successfully with pair for: ${normalizedUsername}`);
|
|
211825
212091
|
resolve({ success: true, userPub: pair.pub });
|
|
211826
212092
|
});
|
|
211827
212093
|
}
|
|
@@ -211854,7 +212120,6 @@ class DataBase {
|
|
|
211854
212120
|
if (normalizedUsername.length === 0) {
|
|
211855
212121
|
throw new Error("Username cannot be empty");
|
|
211856
212122
|
}
|
|
211857
|
-
console.log(`Setting up user profile for ${normalizedUsername} with userPub: ${userPub}`);
|
|
211858
212123
|
const existingUser = await this.gun.get(userPub).then();
|
|
211859
212124
|
const isNewUser = !existingUser || !existingUser.alias;
|
|
211860
212125
|
// const isNewUser = true;
|
|
@@ -211932,7 +212197,6 @@ class DataBase {
|
|
|
211932
212197
|
if (!userMetadataResult) {
|
|
211933
212198
|
return false;
|
|
211934
212199
|
}
|
|
211935
|
-
console.log(`Comprehensive user tracking setup completed for ${username}`);
|
|
211936
212200
|
return true;
|
|
211937
212201
|
}
|
|
211938
212202
|
catch (error) {
|
|
@@ -211955,7 +212219,6 @@ class DataBase {
|
|
|
211955
212219
|
return false;
|
|
211956
212220
|
}
|
|
211957
212221
|
else {
|
|
211958
|
-
console.log(`Alias index created: ~@${username} -> ${userPub}`);
|
|
211959
212222
|
return true;
|
|
211960
212223
|
}
|
|
211961
212224
|
}
|
|
@@ -211979,7 +212242,6 @@ class DataBase {
|
|
|
211979
212242
|
return false;
|
|
211980
212243
|
}
|
|
211981
212244
|
else {
|
|
211982
|
-
console.log(`Username mapping created: ${username} -> ${userPub}`);
|
|
211983
212245
|
return true;
|
|
211984
212246
|
}
|
|
211985
212247
|
}
|
|
@@ -212010,7 +212272,6 @@ class DataBase {
|
|
|
212010
212272
|
return false;
|
|
212011
212273
|
}
|
|
212012
212274
|
else {
|
|
212013
|
-
console.log(`User registry created: ${userPub}`);
|
|
212014
212275
|
return true;
|
|
212015
212276
|
}
|
|
212016
212277
|
}
|
|
@@ -212034,7 +212295,6 @@ class DataBase {
|
|
|
212034
212295
|
return false;
|
|
212035
212296
|
}
|
|
212036
212297
|
else {
|
|
212037
|
-
console.log(`Reverse lookup created: ${userPub} -> ${username}`);
|
|
212038
212298
|
return true;
|
|
212039
212299
|
}
|
|
212040
212300
|
}
|
|
@@ -212054,7 +212314,6 @@ class DataBase {
|
|
|
212054
212314
|
return false;
|
|
212055
212315
|
}
|
|
212056
212316
|
else {
|
|
212057
|
-
console.log(`Epub index created: ${epub} -> ${userPub}`);
|
|
212058
212317
|
return true;
|
|
212059
212318
|
}
|
|
212060
212319
|
}
|
|
@@ -212080,7 +212339,6 @@ class DataBase {
|
|
|
212080
212339
|
return false;
|
|
212081
212340
|
}
|
|
212082
212341
|
else {
|
|
212083
|
-
console.log(`User metadata created for ${userPub}`);
|
|
212084
212342
|
return true;
|
|
212085
212343
|
}
|
|
212086
212344
|
}
|
|
@@ -212114,7 +212372,7 @@ class DataBase {
|
|
|
212114
212372
|
}
|
|
212115
212373
|
}
|
|
212116
212374
|
catch (error) {
|
|
212117
|
-
console.
|
|
212375
|
+
console.error(`GunDB alias lookup failed for ${normalizedAlias}:`, error);
|
|
212118
212376
|
}
|
|
212119
212377
|
// Method 2: Try username mapping (usernames/alias -> userPub)
|
|
212120
212378
|
try {
|
|
@@ -212130,7 +212388,7 @@ class DataBase {
|
|
|
212130
212388
|
}
|
|
212131
212389
|
}
|
|
212132
212390
|
catch (error) {
|
|
212133
|
-
console.
|
|
212391
|
+
console.error(`Username mapping lookup failed for ${normalizedAlias}:`, error);
|
|
212134
212392
|
}
|
|
212135
212393
|
return null;
|
|
212136
212394
|
}
|
|
@@ -212163,7 +212421,7 @@ class DataBase {
|
|
|
212163
212421
|
}
|
|
212164
212422
|
}
|
|
212165
212423
|
catch (error) {
|
|
212166
|
-
console.
|
|
212424
|
+
console.error(`User registry lookup failed for ${userPub}:`, error);
|
|
212167
212425
|
}
|
|
212168
212426
|
// Method 2: Try user's own node
|
|
212169
212427
|
try {
|
|
@@ -212179,7 +212437,7 @@ class DataBase {
|
|
|
212179
212437
|
}
|
|
212180
212438
|
}
|
|
212181
212439
|
catch (error) {
|
|
212182
|
-
console.
|
|
212440
|
+
console.error(`User node lookup failed for ${userPub}:`, error);
|
|
212183
212441
|
}
|
|
212184
212442
|
return null;
|
|
212185
212443
|
}
|
|
@@ -212263,14 +212521,14 @@ class DataBase {
|
|
|
212263
212521
|
.then();
|
|
212264
212522
|
}
|
|
212265
212523
|
catch (error) {
|
|
212266
|
-
console.
|
|
212524
|
+
console.error(`Failed to update lastSeen in user registry:`, error);
|
|
212267
212525
|
}
|
|
212268
212526
|
// Update in user's own node
|
|
212269
212527
|
try {
|
|
212270
212528
|
await this.gun.get(userPub).get("lastSeen").put(timestamp).then();
|
|
212271
212529
|
}
|
|
212272
212530
|
catch (error) {
|
|
212273
|
-
console.
|
|
212531
|
+
console.error(`Failed to update lastSeen in user node:`, error);
|
|
212274
212532
|
}
|
|
212275
212533
|
}
|
|
212276
212534
|
catch (error) {
|
|
@@ -212282,10 +212540,8 @@ class DataBase {
|
|
|
212282
212540
|
*/
|
|
212283
212541
|
async performAuthentication(username, password, pair) {
|
|
212284
212542
|
return new Promise((resolve) => {
|
|
212285
|
-
console.log(`Attempting authentication for user: ${username}`);
|
|
212286
212543
|
if (pair) {
|
|
212287
212544
|
this.gun.user().auth(pair, (ack) => {
|
|
212288
|
-
console.log(`Pair authentication result:`, ack);
|
|
212289
212545
|
if (ack.err) {
|
|
212290
212546
|
console.error(`Login error for ${username}: ${ack.err}`);
|
|
212291
212547
|
resolve({ success: false, error: ack.err });
|
|
@@ -212297,7 +212553,6 @@ class DataBase {
|
|
|
212297
212553
|
}
|
|
212298
212554
|
else {
|
|
212299
212555
|
this.gun.user().auth(username, password, (ack) => {
|
|
212300
|
-
console.log(`Password authentication result:`, ack);
|
|
212301
212556
|
if (ack.err) {
|
|
212302
212557
|
console.error(`Login error for ${username}: ${ack.err}`);
|
|
212303
212558
|
resolve({ success: false, error: ack.err });
|
|
@@ -212346,9 +212601,6 @@ class DataBase {
|
|
|
212346
212601
|
if (!alias) {
|
|
212347
212602
|
alias = username;
|
|
212348
212603
|
}
|
|
212349
|
-
console.log(`Login authentication successful, extracted userPub: ${userPub}`);
|
|
212350
|
-
console.log(`User object:`, this.gun.user());
|
|
212351
|
-
console.log(`User.is:`, this.gun.user().is);
|
|
212352
212604
|
if (!userPub) {
|
|
212353
212605
|
return {
|
|
212354
212606
|
success: false,
|
|
@@ -212514,7 +212766,6 @@ class DataBase {
|
|
|
212514
212766
|
if (!userPub) {
|
|
212515
212767
|
return { success: false, error: "User not found" };
|
|
212516
212768
|
}
|
|
212517
|
-
// console.log(`Found user public key for password recovery: ${userPub}`);
|
|
212518
212769
|
// Access the user's security data directly from their public key node
|
|
212519
212770
|
const securityData = await this.node.get(userPub)
|
|
212520
212771
|
.get("security")
|
|
@@ -212730,14 +212981,7 @@ exports.DataBase = DataBase;
|
|
|
212730
212981
|
// Errors
|
|
212731
212982
|
DataBase.Errors = GunErrors;
|
|
212732
212983
|
const createGun = (config, silent) => {
|
|
212733
|
-
if (!silent) {
|
|
212734
|
-
console.log("Creating Gun instance with config:", config);
|
|
212735
|
-
console.log("Config peers:", config?.peers);
|
|
212736
|
-
}
|
|
212737
212984
|
const gunInstance = (0, gun_1.default)(config);
|
|
212738
|
-
if (!silent) {
|
|
212739
|
-
console.log("Created Gun instance:", gunInstance);
|
|
212740
|
-
}
|
|
212741
212985
|
return gunInstance;
|
|
212742
212986
|
};
|
|
212743
212987
|
exports.createGun = createGun;
|
|
@@ -220391,6 +220635,16 @@ function generateDeterministicPassword(salt) {
|
|
|
220391
220635
|
|
|
220392
220636
|
/***/ }),
|
|
220393
220637
|
|
|
220638
|
+
/***/ "?25c3":
|
|
220639
|
+
/*!**********************!*\
|
|
220640
|
+
!*** zlib (ignored) ***!
|
|
220641
|
+
\**********************/
|
|
220642
|
+
/***/ (() => {
|
|
220643
|
+
|
|
220644
|
+
/* (ignored) */
|
|
220645
|
+
|
|
220646
|
+
/***/ }),
|
|
220647
|
+
|
|
220394
220648
|
/***/ "?3fc0":
|
|
220395
220649
|
/*!************************!*\
|
|
220396
220650
|
!*** crypto (ignored) ***!
|