@copytrade/unified-broker
Version:
Unified broker interface library for Indian stock market brokers with plugin architecture
233 lines • 8.75 kB
JavaScript
;
/**
* Broker Registry - Core component for dynamic broker registration
* Enables plugin-based architecture for publishable broker library
*/
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.brokerRegistry = exports.BrokerRegistry = void 0;
class BrokerRegistry {
constructor(config = {}) {
this.plugins = new Map();
this.instances = new Map();
this.accountInstances = new Map(); // Per-account instances
this.config = {
autoLoad: true,
pluginPaths: [],
enabledBrokers: [],
...config
};
}
static getInstance(config) {
if (!BrokerRegistry.instance) {
BrokerRegistry.instance = new BrokerRegistry(config);
}
return BrokerRegistry.instance;
}
/**
* Register a broker plugin
* @param plugin - Broker plugin configuration
*/
registerPlugin(plugin) {
const normalizedName = plugin.name.toLowerCase();
// Validate plugin
if (!plugin.createInstance || typeof plugin.createInstance !== 'function') {
throw new Error(`Invalid plugin: ${plugin.name}. createInstance must be a function.`);
}
// Check if broker is enabled (if enabledBrokers is specified)
if (this.config.enabledBrokers && this.config.enabledBrokers.length > 0) {
if (!this.config.enabledBrokers.includes(normalizedName)) {
console.log(`🚫 Broker plugin '${plugin.name}' is disabled by configuration`);
return;
}
}
this.plugins.set(normalizedName, plugin);
console.log(`✅ Registered broker plugin: ${plugin.name} v${plugin.version}`);
}
/**
* Unregister a broker plugin
* @param brokerName - Name of the broker to unregister
*/
unregisterPlugin(brokerName) {
const normalizedName = brokerName.toLowerCase();
this.plugins.delete(normalizedName);
this.instances.delete(normalizedName);
// Remove all account instances for this broker
const keysToDelete = Array.from(this.accountInstances.keys())
.filter(key => key.startsWith(`${normalizedName}_`));
keysToDelete.forEach(key => this.accountInstances.delete(key));
console.log(`🗑️ Unregistered broker plugin: ${brokerName}`);
}
/**
* Create a broker instance
* @param brokerName - Name of the broker
* @returns IBrokerService instance
*/
createBroker(brokerName) {
const normalizedName = brokerName.toLowerCase();
const plugin = this.plugins.get(normalizedName);
if (!plugin) {
const availableBrokers = this.getAvailableBrokers();
throw new Error(`Broker '${brokerName}' is not registered. Available brokers: ${availableBrokers.join(', ')}`);
}
try {
const instance = plugin.createInstance();
console.log(`🏭 Created broker instance: ${brokerName}`);
return instance;
}
catch (error) {
throw new Error(`Failed to create broker instance '${brokerName}': ${error.message}`);
}
}
/**
* Get or create a singleton broker instance
* @param brokerName - Name of the broker
* @returns IBrokerService instance
* @deprecated Use getBrokerForAccount instead for account-specific instances
*/
getBroker(brokerName) {
const normalizedName = brokerName.toLowerCase();
if (!this.instances.has(normalizedName)) {
const instance = this.createBroker(normalizedName);
this.instances.set(normalizedName, instance);
}
return this.instances.get(normalizedName);
}
/**
* Get or create a broker instance for a specific account
* This ensures each account has its own isolated broker service instance
* @param brokerName - Name of the broker
* @param accountId - Account ID for isolation
* @returns IBrokerService instance
*/
getBrokerForAccount(brokerName, accountId) {
const normalizedName = brokerName.toLowerCase();
const accountKey = `${normalizedName}_${accountId}`;
if (!this.accountInstances.has(accountKey)) {
const instance = this.createBroker(normalizedName);
this.accountInstances.set(accountKey, instance);
console.log(`🏭 Created isolated broker instance for ${brokerName} account ${accountId}`);
}
return this.accountInstances.get(accountKey);
}
/**
* Remove broker instance for a specific account
* @param brokerName - Name of the broker
* @param accountId - Account ID
*/
removeBrokerForAccount(brokerName, accountId) {
const normalizedName = brokerName.toLowerCase();
const accountKey = `${normalizedName}_${accountId}`;
if (this.accountInstances.has(accountKey)) {
this.accountInstances.delete(accountKey);
console.log(`🗑️ Removed broker instance for ${brokerName} account ${accountId}`);
}
}
/**
* Get list of available broker names
* @returns Array of broker names
*/
getAvailableBrokers() {
return Array.from(this.plugins.keys());
}
/**
* Get list of registered plugins with metadata
* @returns Array of plugin information
*/
getRegisteredPlugins() {
return Array.from(this.plugins.values()).map(plugin => ({
name: plugin.name,
version: plugin.version,
...(plugin.description && { description: plugin.description })
}));
}
/**
* Check if a broker is available
* @param brokerName - Name of the broker
* @returns true if broker is available
*/
isBrokerAvailable(brokerName) {
return this.plugins.has(brokerName.toLowerCase());
}
/**
* Clear all instances (useful for testing)
*/
clearInstances() {
this.instances.clear();
this.accountInstances.clear();
}
/**
* Reset the registry (useful for testing)
*/
reset() {
this.plugins.clear();
this.instances.clear();
this.accountInstances.clear();
}
/**
* Load broker plugins from specified paths
* @param paths - Array of paths to load plugins from
*/
async loadPlugins(paths = []) {
const pluginPaths = [...this.config.pluginPaths || [], ...paths];
for (const path of pluginPaths) {
try {
const plugin = await Promise.resolve(`${path}`).then(s => __importStar(require(s)));
if (plugin.default && typeof plugin.default.register === 'function') {
plugin.default.register(this);
}
}
catch (error) {
console.warn(`⚠️ Failed to load plugin from ${path}: ${error.message}`);
}
}
}
/**
* Get configuration
*/
getConfig() {
return { ...this.config };
}
/**
* Update configuration
*/
updateConfig(newConfig) {
this.config = { ...this.config, ...newConfig };
}
}
exports.BrokerRegistry = BrokerRegistry;
// Export singleton instance for convenience
exports.brokerRegistry = BrokerRegistry.getInstance();
//# sourceMappingURL=BrokerRegistry.js.map