# Pulse Plugin SDK The official SDK for building Pulse plugins. This package provides TypeScript types and interfaces to extend Pulse with custom functionality. > [!NOTE] > Pulse plugins are an experimental feature and the SDK API may change in future releases. ## Creating a Plugin ### 1. Create Plugin Directory Create a plugin folder, e.g., `my-plugin`. ### 2. Initialize Package Run `bun init` to bootstrap your plugin. ### 3. Edit `package.json` Make sure your `package.json` includes the necessary fields. **Required fields:** - `name`: Plugin identifier - `version`: Semver version (e.g., `1.0.0`) - `pulse.entry`: Entry file (must be `.js`) - `pulse.author`: Plugin author name - `pulse.description`: Brief description **Optional fields:** - `pulse.homepage`: Plugin website/repository URL - `pulse.logo`: Logo image filename Example `package.json`: ```json { "name": "my-plugin", "version": "0.0.1", "module": "src/index.ts", "pulse": { "entry": "index.js", "author": "Me", "homepage": "https://some-page.com", "description": "This is my first Pulse plugin!", "logo": "https://some-page.com/logo.png" }, "type": "module", "scripts": { "build": "bun build src/index.ts --outdir dist --target bun --minify --format esm && cp package.json dist/" }, "devDependencies": { "@types/bun": "latest" }, "peerDependencies": { "typescript": "^5" } } ``` ### 4. Install SDK ```bash bun add @pulse/plugin-sdk ``` > [!NOTE] > The SDK is not published to any package registry. For now, you need to link it locally using `bun link`. ### 3. Edit Entry File ```typescript import type { PluginContext } from "@pulse/plugin-sdk"; const onLoad = (ctx: PluginContext) => { ctx.log("My Plugin loaded"); ctx.events.on("user:joined", ({ userId, username }) => { ctx.log(`User joined: ${username} (ID: ${userId})`); }); }; const onUnload = (ctx: PluginContext) => { ctx.log("My Plugin unloaded"); }; export { onLoad, onUnload }; ``` Compile to JavaScript before loading: ```bash bun run build ``` ## Lifecycle ### onLoad Called when the plugin is loaded. This is where you should: - Register event listeners - Register commands - Initialize resources - Set up external connections ### onUnload Called when the plugin is unloaded or the server shuts down. Use this to: - Clean up resources - Close connections - Save state **Note:** All event listeners and commands are automatically unregistered when the plugin unloads. ## Commands Plugins can register custom commands that users can execute. Commands can accept arguments and return results. ### Registering a Command ```typescript import type { PluginContext, TInvokerContext } from "@pulse/plugin-sdk"; const onLoad = (ctx: PluginContext) => { ctx.commands.register({ name: "greet", description: "Greet a user", args: [ { name: "username", type: "string", description: "The user to greet", required: true, sensitive: false, // set to true if the argument is sensitive (e.g., passwords), in the interface it will be shown as **** }, ], async executes(invokerCtx: TInvokerContext, args: { username: string }) { ctx.log(`Greeting ${args.username} invoked by user ${invokerCtx.userId}`); return "Hello, " + args.username + "!"; }, }); }; ``` ## Adding The Plugin to Pulse 1. Go to the Pulse data directory (usually `~/.config/pulse`). 2. Create a `plugins` folder if it doesn't exist. 3. Create a folder for your plugin (e.g., `my-plugin`). 4. Copy your compiled plugin files (e.g., from `dist/`) into the `my-plugin` folder. 5. Enable your plugin in the server settings under the "Plugins" section. 6. Restart Pulse or reload plugins from the admin panel. 7. Your plugin should now be loaded and active! ## Best Practices 1. **Always handle errors**: Wrap async operations in try-catch blocks 2. **Clean up resources**: Implement `onUnload` to prevent memory leaks 3. **Use TypeScript**: Get type safety and better IDE support 4. **Log appropriately**: Use `debug` for verbose info, `error` for failures 5. **Validate inputs**: Check command arguments before using them 6. **Version carefully**: Follow semver for plugin updates 7. **Prevent blocking operations**: Do NOT block the event loop with long-running tasks (example: using Bun.spawnSync). Use asynchronous methods instead. ## API Reference No documentation available yet. Use the types in `packages/plugin-sdk/src/index.ts` as a reference. ## License This SDK is part of the Pulse project. See the main repository for license information.