UNPKG

@mulutime/plugin-sdk

Version:

SDK for developing MuluTime booking platform plugins

276 lines 10.6 kB
"use strict"; 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 __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createPlugin = exports.createManifest = exports.createEnhancedPlugin = exports.TemplateGenerator = exports.TestUtils = exports.BasePlugin = exports.PluginSDK = void 0; exports.initializePluginSDK = initializePluginSDK; // MuluTime Plugin SDK for external developers const ajv_1 = __importDefault(require("ajv")); // Import types from the shared types package const plugin_types_1 = require("@mulutime/plugin-types"); const helpers_1 = require("./helpers"); const testUtilities_1 = require("./testUtilities"); const pluginClients_1 = require("./pluginClients"); // ============================================================================= // PLUGIN SDK CLASS // ============================================================================= class PluginSDK { constructor(context) { this.context = context; this.ajv = new ajv_1.default(); // Create HTTP client with authentication this.httpClient = this.context.http; } // Logging utilities get logger() { return this.context.logger; } // Storage utilities get storage() { return this.context.storage; } // Expose setConfig utility if available async setConfig(config) { if (typeof this.context.setConfig === 'function') { await this.context.setConfig(config); } else { throw new Error('setConfig is not implemented in this context'); } } // API client utilities get api() { return this.context.api; } // Plugin configuration get config() { return this.context.config; } // Plugin permissions get permissions() { return this.context.permissions; } // HTTP client for external APIs get http() { return this.httpClient; } // Get plugin context getContext() { return this.context; } // Validate data against JSON schema validateSchema(data, schema) { const validate = this.ajv.compile(schema); const valid = validate(data); return { valid, errors: valid ? undefined : validate.errors?.map(err => err.message || 'Validation error') }; } // Check if plugin has permission hasPermission(permission) { return this.context.permissions.includes(permission); } // Require permission (throws if not available) requirePermission(permission) { if (!this.hasPermission(permission)) { throw new Error(`Plugin requires permission: ${permission}`); } } // Get user/organization context getUserId() { return this.context.userId; } getOrganizationId() { return this.context.organizationId; } // Make authenticated API calls to the booking system async callBookingAPI(endpoint, options = {}) { const { method = 'GET', data, params } = options; try { const response = await this.httpClient.request({ url: endpoint, method, data, params }); return response.data; } catch (error) { this.logger.error(`API call failed: ${endpoint}`, error); throw error; } } // Trigger a system event (if plugin has permission) async triggerEvent(eventType, data) { this.requirePermission(plugin_types_1.PluginPermission.SEND_NOTIFICATIONS); await this.callBookingAPI('/api/system/events', { method: 'POST', data: { eventType, data, source: this.context.pluginId } }); } // Action system utilities (initialize on demand) get actions() { if (!this.actionRegistry) { this.actionRegistry = (0, action_registry_1.createActionRegistry)(); this.actionExecutor = (0, action_executor_1.createActionExecutor)(this.actionRegistry); } return { registry: this.actionRegistry, executor: this.actionExecutor }; } } exports.PluginSDK = PluginSDK; // ============================================================================= // BASE PLUGIN CLASS // ============================================================================= class BasePlugin { constructor() { this.sdk = null; } // ---- Domain-specific (e.g. calendar) plugin methods ---- // Plugins can override these as needed. If not implemented, throw by default. async fetchExternalEvents(context) { throw new Error('fetchExternalEvents is not implemented for this plugin.'); } async createEvent(eventData, context) { throw new Error('createEvent is not implemented for this plugin.'); } // Initialize the plugin with SDK context and register actions initialize(context) { this.sdk = new PluginSDK(context); // Auto-register actions from decorators/metadata this.registerActions(); } // Register plugin actions with the action system registerActions() { if (!this.sdk) return; const actions = (0, action_registry_1.extractAllActions)(this.constructor); if (Object.keys(actions).length > 0) { this.sdk.actions.registry.registerPlugin(this.manifest.id, actions); } } // Get SDK instance getSDK() { if (!this.sdk) { throw new Error('Plugin not initialized. Call initialize() first.'); } return this.sdk; } // Default lifecycle implementations (can be overridden) async onInstall(context) { this.initialize(context); this.getSDK().logger.info('Plugin installed'); } async onUninstall(context) { this.initialize(context); this.getSDK().logger.info('Plugin uninstalled'); } async onUpdate(context, oldVersion) { this.initialize(context); this.getSDK().logger.info(`Plugin updated from ${oldVersion} to ${this.manifest.version}`); } async onActivate(context) { this.initialize(context); this.getSDK().logger.info('Plugin activated'); } async onDeactivate(context) { this.initialize(context); this.getSDK().logger.info('Plugin deactivated'); } // Default validation async validateConfig(config) { if (this.manifest.configSchema) { return this.getSDK().validateSchema(config, this.manifest.configSchema); } return { valid: true }; } // Get configuration schema getConfigSchema() { return this.manifest.configSchema; } // Default webhook handler async handleWebhook(context, payload) { this.initialize(context); this.getSDK().logger.warn('Webhook received but no handler implemented'); return { status: 'not_implemented' }; } } exports.BasePlugin = BasePlugin; // ============================================================================= // ACTION SYSTEM INTEGRATION // ============================================================================= // Export all action system components __exportStar(require("./actions"), exports); // Import action system for SDK integration const action_registry_1 = require("./actions/action-registry"); const action_executor_1 = require("./actions/action-executor"); // ============================================================================= // SDK INITIALIZATION // ============================================================================= async function initializePluginSDK(baseURL, pluginSecret) { const api = new pluginClients_1.PluginAPIClient(baseURL, pluginSecret); // Get context from API const contextResponse = await api.get('/api/plugin/v1/sdk/context'); if (!contextResponse.ok) { throw new Error(`Failed to initialize SDK: ${contextResponse.statusText}`); } const contextData = await contextResponse.json(); // Create SDK instances const storage = new pluginClients_1.PluginStorageClient(api); const logger = new pluginClients_1.PluginLoggerClient(api); // Create full context const context = { userId: contextData.userId, organizationId: contextData.organizationId, pluginId: contextData.pluginId, permissions: contextData.permissions || [], config: contextData.config || {}, storage, logger, api, http: contextData.http, errors: contextData.errors, systemBaseUrl: contextData.systemBaseUrl, apiToken: pluginSecret // Use plugin secret as token }; return new PluginSDK(context); } // ============================================================================= // EXPORTS // ============================================================================= exports.TestUtils = new testUtilities_1.PluginTestUtils(); exports.TemplateGenerator = helpers_1.PluginTemplateGenerator; var helpers_2 = require("./helpers"); Object.defineProperty(exports, "createEnhancedPlugin", { enumerable: true, get: function () { return helpers_2.createEnhancedPlugin; } }); Object.defineProperty(exports, "createManifest", { enumerable: true, get: function () { return helpers_2.createManifest; } }); Object.defineProperty(exports, "createPlugin", { enumerable: true, get: function () { return helpers_2.createPlugin; } }); // Re-export all types for easier access __exportStar(require("./types"), exports); __exportStar(require("./helpers"), exports); __exportStar(require("./testUtilities"), exports); __exportStar(require("./pluginClients"), exports); // Default export exports.default = PluginSDK; //# sourceMappingURL=index.js.map