pulse-zax/packages/plugin-sdk/README.md

4.5 KiB

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:

{
  "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

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

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:

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

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.