From 36e26318cd014ba6586a5b7998c29ba8bbf5454c Mon Sep 17 00:00:00 2001 From: Amit Haridas Date: Tue, 14 Apr 2026 23:28:29 +0530 Subject: [PATCH] feat(plugins): add PluginAPI base class with no-op lifecycle Amit Haridas --- src/plugins/plugin-api.js | 23 +++++++++++++++++++++++ tests/plugin-api.test.js | 29 +++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/plugins/plugin-api.js create mode 100644 tests/plugin-api.test.js diff --git a/src/plugins/plugin-api.js b/src/plugins/plugin-api.js new file mode 100644 index 0000000..6b89d10 --- /dev/null +++ b/src/plugins/plugin-api.js @@ -0,0 +1,23 @@ +class PluginAPI { + /** + * Called when the plugin is discovered and loaded. + * Receives a scoped context object with APIs. + * @param {object} context - Plugin context (sidebar, commands, settings, etc.) + */ + init(context) { + this.context = context; + } + + /** Called when the plugin is activated (e.g., sidebar panel clicked). */ + activate() {} + + /** Called when the plugin is deactivated. */ + deactivate() {} + + /** Returns the parsed manifest.json for this plugin. */ + getManifest() { + return this._manifest || null; + } +} + +module.exports = { PluginAPI }; diff --git a/tests/plugin-api.test.js b/tests/plugin-api.test.js new file mode 100644 index 0000000..f83eabf --- /dev/null +++ b/tests/plugin-api.test.js @@ -0,0 +1,29 @@ +const { PluginAPI } = require('../src/plugins/plugin-api'); + +describe('PluginAPI', () => { + test('has default no-op lifecycle methods', () => { + const plugin = new PluginAPI(); + expect(() => plugin.init({})).not.toThrow(); + expect(() => plugin.activate()).not.toThrow(); + expect(() => plugin.deactivate()).not.toThrow(); + }); + + test('getManifest returns null by default', () => { + const plugin = new PluginAPI(); + expect(plugin.getManifest()).toBeNull(); + }); + + test('subclass can override init', () => { + let called = false; + class MyPlugin extends PluginAPI { + init(context) { + called = true; + this.context = context; + } + } + const p = new MyPlugin(); + p.init({ foo: 'bar' }); + expect(called).toBe(true); + expect(p.context.foo).toBe('bar'); + }); +});