shogun-core
Version:
SHOGUN CORE - Core library for Shogun Ecosystem
482 lines (481 loc) • 22.6 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
import { ShogunStorage } from '../storage/storage.js';
import { ErrorHandler } from '../utils/errorHandler.js';
import { WebauthnPlugin } from '../plugins/webauthn/webauthnPlugin.js';
import { Web3ConnectorPlugin } from '../plugins/web3/web3ConnectorPlugin.js';
import { NostrConnectorPlugin } from '../plugins/nostr/nostrConnectorPlugin.js';
import { ZkProofPlugin } from '../plugins/zkproof/zkProofPlugin.js';
import { DataBase, RxJS, derive } from '../gundb/db.js';
import { DataBaseHolster } from '../gundb/db-holster.js';
import { RxJSHolster } from '../gundb/rxjs-holster.js';
/**
* Handles initialization of ShogunCore components
*/
var CoreInitializer = /** @class */ (function () {
function CoreInitializer(core) {
this.core = core;
}
/**
* Initialize the Shogun SDK
* @param config - SDK Configuration object
* @description Creates a new instance of ShogunCore with the provided configuration.
* Initializes all required components including storage, event emitter, GunInstance connection,
* and plugin system.
*/
CoreInitializer.prototype.initialize = function (config) {
return __awaiter(this, void 0, void 0, function () {
var _this = this;
return __generator(this, function (_a) {
// Polyfill console for environments where it might be missing
if (typeof console === 'undefined') {
global.console = {
log: function () { },
warn: function () { },
error: function () { },
info: function () { },
debug: function () { },
};
}
// Initialize storage
this.core.storage = new ShogunStorage(config.silent);
// Setup error handler
ErrorHandler.addListener(function (error) {
_this.core.emit('error', {
action: error.code,
message: error.message,
type: error.type,
});
});
// Setup Gun instance
this.initializeGun(config);
// Setup Gun user
this.initializeGunUser();
// Setup Gun event forwarding
this.setupGunEventForwarding();
// Setup wallet derivation
this.setupWalletDerivation();
// Initialize RxJS (use appropriate implementation based on instance type)
if (config.holsterInstance) {
this.core.rx = new RxJSHolster(this.core.gun);
}
else {
this.core.rx = new RxJS(this.core.gun);
}
// Register built-in plugins
this.registerBuiltinPlugins(config);
// Initialize async components
this.initializeDb();
return [2 /*return*/];
});
});
};
/**
* Initialize Gun or Holster instance
*/
CoreInitializer.prototype.initializeGun = function (config) {
// Check if Holster instance is provided
if (config.holsterInstance) {
return this.initializeHolster(config);
}
// Otherwise, use Gun instance
try {
if (!config.gunInstance) {
throw new Error('Either gunInstance or holsterInstance is required but neither was provided');
}
// Validate Gun instance
if (typeof config.gunInstance !== 'object') {
throw new Error("Gun instance must be an object, received: ".concat(typeof config.gunInstance));
}
if (typeof config.gunInstance.user !== 'function') {
throw new Error("Gun instance is invalid: gun.user is not a function. Received gun.user type: ".concat(typeof config.gunInstance.user));
}
if (typeof config.gunInstance.get !== 'function') {
throw new Error("Gun instance is invalid: gun.get is not a function. Received gun.get type: ".concat(typeof config.gunInstance.get));
}
if (typeof config.gunInstance.on !== 'function') {
throw new Error("Gun instance is invalid: gun.on is not a function. Received gun.on type: ".concat(typeof config.gunInstance.on));
}
console.log('Using provided Gun instance:', config.gunInstance);
this.core._gun = config.gunInstance;
}
catch (error) {
if (typeof console !== 'undefined' && console.error) {
console.error('Error validating Gun instance:', error);
}
throw new Error("Failed to validate Gun instance: ".concat(error));
}
try {
// Get SEA from Gun instance or global
var sea = this.core._gun.SEA || null;
if (!sea) {
// Try to find SEA in various global locations
if (typeof window !== 'undefined' &&
window.Gun &&
window.Gun.SEA) {
sea = window.Gun.SEA;
}
else if (globalThis.Gun && globalThis.Gun.SEA) {
sea = globalThis.Gun.SEA;
}
else if (global.Gun && global.Gun.SEA) {
sea = global.Gun.SEA;
}
}
this.core.db = new DataBase(this.core._gun, this.core, sea);
return true;
}
catch (error) {
if (typeof console !== 'undefined' && console.error) {
console.error('Error initializing DataBase:', error);
}
throw new Error("Failed to initialize DataBase: ".concat(error));
}
};
/**
* Initialize Holster instance
*/
CoreInitializer.prototype.initializeHolster = function (config) {
try {
if (!config.holsterInstance) {
throw new Error('Holster instance is required but was not provided');
}
// Validate Holster instance
if (typeof config.holsterInstance !== 'object') {
throw new Error("Holster instance must be an object, received: ".concat(typeof config.holsterInstance));
}
if (typeof config.holsterInstance.user !== 'function') {
throw new Error("Holster instance is invalid: holster.user is not a function. Received holster.user type: ".concat(typeof config.holsterInstance.user));
}
if (typeof config.holsterInstance.get !== 'function') {
throw new Error("Holster instance is invalid: holster.get is not a function. Received holster.get type: ".concat(typeof config.holsterInstance.get));
}
console.log('Using provided Holster instance:', config.holsterInstance);
// Store holster instance in _gun for compatibility
this.core._gun = config.holsterInstance;
}
catch (error) {
if (typeof console !== 'undefined' && console.error) {
console.error('Error validating Holster instance:', error);
}
throw new Error("Failed to validate Holster instance: ".concat(error));
}
try {
// Get SEA from Holster instance or global
var sea = this.core._gun.SEA || null;
if (!sea) {
// Try to find SEA in various global locations
if (typeof window !== 'undefined' &&
window.Holster &&
window.Holster.SEA) {
sea = window.Holster.SEA;
}
else if (globalThis.Holster &&
globalThis.Holster.SEA) {
sea = globalThis.Holster.SEA;
}
else if (global.Holster && global.Holster.SEA) {
sea = global.Holster.SEA;
}
else if (globalThis.SEA) {
sea = globalThis.SEA;
}
}
this.core.db = new DataBaseHolster(this.core._gun, this.core, sea);
return true;
}
catch (error) {
if (typeof console !== 'undefined' && console.error) {
console.error('Error initializing DataBaseHolster:', error);
}
throw new Error("Failed to initialize DataBaseHolster: ".concat(error));
}
};
/**
* Check if we're using Holster instead of Gun
* Holster has a 'next' method that Gun doesn't have
*/
CoreInitializer.prototype.isHolster = function () {
// Check if gun has 'next' method (Holster-specific)
if (typeof this.core.gun.next === 'function') {
return true;
}
// Check if db is DataBaseHolster instance
if (this.core.db && this.core.db.constructor.name === 'DataBaseHolster') {
return true;
}
return false;
};
/**
* Initialize Gun/Holster user
*/
CoreInitializer.prototype.initializeGunUser = function () {
var _this = this;
try {
var userInstance = this.core.gun.user();
// Holster's recall() doesn't take options, Gun's does
if (typeof userInstance.recall === 'function') {
if (userInstance.recall.length > 0) {
// Gun API: recall takes options
this.core._user = userInstance.recall({ sessionStorage: true });
}
else {
// Holster API: recall takes no arguments
userInstance.recall();
this.core._user = userInstance.is ? userInstance : null;
}
}
else {
this.core._user = userInstance;
}
}
catch (error) {
if (typeof console !== 'undefined' && console.error) {
console.error('Error initializing user:', error);
}
throw new Error("Failed to initialize user: ".concat(error));
}
// Setup auth event listener
// Gun has native "auth" events, but Holster doesn't support global events
// Holster uses polling in DataBaseHolster.subscribeToAuthEvents() instead
if (this.isHolster()) {
// Holster doesn't support global "auth" events
// Auth events are handled via polling in DataBaseHolster
// The DataBaseHolster will emit auth events via its onAuth callbacks
if (typeof console !== 'undefined' && console.log) {
console.log('[CoreInitializer] Using Holster - auth events handled via DataBaseHolster polling');
}
}
else if (typeof this.core.gun.on === 'function') {
// Gun has native "auth" events
try {
this.core.gun.on('auth', function (user) {
var _a;
var userInstance = _this.core.gun.user();
if (typeof userInstance.recall === 'function') {
if (userInstance.recall.length > 0) {
_this.core._user = userInstance.recall({ sessionStorage: true });
}
else {
userInstance.recall();
_this.core._user = userInstance.is ? userInstance : null;
}
}
else {
_this.core._user = userInstance;
}
_this.core.emit('auth:login', {
userPub: user.pub || ((_a = user.is) === null || _a === void 0 ? void 0 : _a.pub),
method: 'password',
});
});
}
catch (error) {
// If gun.on("auth") fails, it might be because we're using Holster
// but the detection didn't work. Log and continue.
if (typeof console !== 'undefined' && console.warn) {
console.warn('[CoreInitializer] Failed to register auth event listener:', error);
}
}
}
};
/**
* Setup Gun event forwarding
*/
CoreInitializer.prototype.setupGunEventForwarding = function () {
var _this = this;
var gunEvents = ['gun:put', 'gun:get', 'gun:set', 'gun:remove'];
gunEvents.forEach(function (eventName) {
_this.core.db.on(eventName, function (data) {
_this.core.emit(eventName, data);
});
});
var peerEvents = [
'gun:peer:add',
'gun:peer:remove',
'gun:peer:connect',
'gun:peer:disconnect',
];
peerEvents.forEach(function (eventName) {
_this.core.db.on(eventName, function (data) {
_this.core.emit(eventName, data);
});
});
};
/**
* Setup wallet derivation
*/
CoreInitializer.prototype.setupWalletDerivation = function () {
var _this = this;
if (this.isHolster()) {
// For Holster, wallet derivation is handled via onAuth callbacks in DataBaseHolster
if (this.core.db && typeof this.core.db.onAuth === 'function') {
this.core.db.onAuth(function (user) { return __awaiter(_this, void 0, void 0, function () {
var priv, pub, _a;
var _b, _c;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
if (!user.is)
return [2 /*return*/];
priv = (_b = user.is) === null || _b === void 0 ? void 0 : _b.epriv;
pub = (_c = user.is) === null || _c === void 0 ? void 0 : _c.epub;
if (!(priv && pub)) return [3 /*break*/, 2];
_a = this.core;
return [4 /*yield*/, derive(priv, pub, {
includeSecp256k1Bitcoin: true,
includeSecp256k1Ethereum: true,
})];
case 1:
_a.wallets = _d.sent();
_d.label = 2;
case 2: return [2 /*return*/];
}
});
}); });
}
}
else if (typeof this.core.gun.on === 'function') {
// Gun has native "auth" events
try {
this.core.gun.on('auth', function (user) { return __awaiter(_this, void 0, void 0, function () {
var priv, pub, _a;
var _b, _c, _d, _e, _f, _g;
return __generator(this, function (_h) {
switch (_h.label) {
case 0:
if (!user.is)
return [2 /*return*/];
priv = ((_c = (_b = user._) === null || _b === void 0 ? void 0 : _b.sea) === null || _c === void 0 ? void 0 : _c.epriv) || ((_d = user.is) === null || _d === void 0 ? void 0 : _d.epriv);
pub = ((_f = (_e = user._) === null || _e === void 0 ? void 0 : _e.sea) === null || _f === void 0 ? void 0 : _f.epub) || ((_g = user.is) === null || _g === void 0 ? void 0 : _g.epub);
if (!(priv && pub)) return [3 /*break*/, 2];
_a = this.core;
return [4 /*yield*/, derive(priv, pub, {
includeSecp256k1Bitcoin: true,
includeSecp256k1Ethereum: true,
})];
case 1:
_a.wallets = _h.sent();
_h.label = 2;
case 2: return [2 /*return*/];
}
});
}); });
}
catch (error) {
// If gun.on("auth") fails, log and continue
if (typeof console !== 'undefined' && console.warn) {
console.warn('[CoreInitializer] Failed to register wallet derivation listener:', error);
}
}
}
};
/**
* Register built-in plugins based on configuration
*/
CoreInitializer.prototype.registerBuiltinPlugins = function (config) {
try {
// Register WebAuthn plugin if configuration is provided
if (config.webauthn) {
if (typeof console !== 'undefined' && console.warn) {
console.warn('WebAuthn plugin will be registered with provided configuration');
}
var webauthnPlugin = new WebauthnPlugin();
if (typeof webauthnPlugin.configure === 'function') {
webauthnPlugin.configure(config.webauthn);
}
this.core.pluginManager.register(webauthnPlugin);
}
// Register Web3 plugin if configuration is provided
if (config.web3) {
if (typeof console !== 'undefined' && console.warn) {
console.warn('Web3 plugin will be registered with provided configuration');
}
var web3Plugin = new Web3ConnectorPlugin();
if (typeof web3Plugin.configure === 'function') {
web3Plugin.configure(config.web3);
}
this.core.pluginManager.register(web3Plugin);
}
// Register Nostr plugin if configuration is provided
if (config.nostr) {
if (typeof console !== 'undefined' && console.warn) {
console.warn('Nostr plugin will be registered with provided configuration');
}
var nostrPlugin = new NostrConnectorPlugin();
if (typeof nostrPlugin.configure === 'function') {
nostrPlugin.configure(config.nostr);
}
this.core.pluginManager.register(nostrPlugin);
}
// Register ZK-Proof plugin if configuration is provided
if (config.zkproof) {
if (typeof console !== 'undefined' && console.warn) {
console.warn('ZK-Proof plugin will be registered with provided configuration');
}
var zkproofPlugin = new ZkProofPlugin(config.zkproof);
this.core.pluginManager.register(zkproofPlugin);
}
}
catch (error) {
if (typeof console !== 'undefined' && console.error) {
console.error('Error registering builtin plugins:', error);
}
}
};
/**
* Initialize async components
*/
CoreInitializer.prototype.initializeDb = function () {
try {
this.core.db.initialize();
this.core.emit('debug', {
action: 'core_initialized',
timestamp: Date.now(),
});
return true;
}
catch (error) {
if (typeof console !== 'undefined' && console.error) {
console.error('Error during Shogun Core initialization:', error);
}
return false;
}
};
return CoreInitializer;
}());
export { CoreInitializer };