1.0.16 • Published 5 months ago

mint-nft-plugin v1.0.16

Weekly downloads
-
License
ISC
Repository
-
Last release
5 months ago

API City Plugin Setup Guide

This guide outlines the requirements and best practices for creating a plugin for API City.

Quick Start Example

Here's a minimal working plugin example:

import { BasePlugin, PluginContext } from "api-city-sdk";

class HelloPlugin extends BasePlugin {
  constructor() {
    super({
      name: "Hello Plugin",
      description: "A simple hello world plugin",
      version: "1.0.0",
      author: "Your Name",
      permissions: [],
      entryPoints: {
        main: "hello"  // This must match your base command
      }
    });
  }

  async initialize(context: PluginContext): Promise<void> {
    // Store context for later use
    this.context = context;
  }

  async handleCommand(command: string, args: string[]): Promise<void> {
    if (command !== "hello") {
      this.emit("message", { content: "Unknown command" });
      return;
    }

    const name = args[0] || "World";
    this.emit("message", { content: `Hello, ${name}!` });
  }

  getCommands(): { command: string; description: string; usage: string }[] {
    return [
      {
        command: "hello",              // Must match entryPoints.main
        description: "Say hello",
        usage: "/hello [name]"         // Always prefix with /
      }
    ];
  }
}

export = HelloPlugin;  // Must use this exact syntax

Core Requirements

1. Plugin Class Structure

import { BasePlugin, PluginContext } from "api-city-sdk";

class YourPlugin extends BasePlugin {
  constructor() {
    super({
      name: "Plugin Name",
      description: "Plugin Description",
      version: "1.0.0",
      author: "Author Name",
      permissions: [],
      entryPoints: {
        main: "commandName"
      }
    });
  }

  async initialize(context: PluginContext): Promise<void> {
    // Initialize your plugin
  }

  async handleCommand(command: string, args: string[]): Promise<void> {
    // Handle commands
  }

  getCommands(): { command: string; description: string; usage: string }[] {
    return [
      {
        command: "commandName",           // Base command without slash
        description: "Command description",
        usage: "/commandName <params>"    // Usage with slash
      }
    ];
  }
}

export = YourPlugin;  // Must use CommonJS export

2. Package Configuration

Create a package.json with:

{
  "name": "your-plugin-name",
  "version": "1.0.0",
  "type": "module",
  "main": "dist/index.cjs",
  "module": "dist/index.js",
  "types": "dist/index.d.ts",
  "exports": {
    ".": {
      "require": "./dist/index.cjs",
      "import": "./dist/index.js",
      "types": "./dist/index.d.ts"
    }
  }
}

3. Build Configuration

Create a build.js with:

import * as esbuild from "esbuild";

const sharedConfig = {
  entryPoints: ["src/index.ts"],
  bundle: true,
  minify: true,
  target: "es2020",
  platform: "node",
  sourcemap: true,
  treeShaking: true,
  external: [
    "@solana/web3.js",
    "@metaplex-foundation/umi",
    "@metaplex-foundation/umi-bundle-defaults",
    "@metaplex-foundation/mpl-core",
    "api-city-sdk"
  ]
};

await esbuild.build({
  ...sharedConfig,
  format: "esm",
  outfile: "dist/index.js",
});

await esbuild.build({
  ...sharedConfig,
  format: "cjs",
  outfile: "dist/index.cjs",
});

Command Handling Best Practices

  1. Command Validation

    async handleCommand(command: string, args: string[]): Promise<void> {
      // Always validate the base command first
      if (command !== "yourcommand") {
        this.emit("message", { content: "Unknown command" });
        return;
      }
    
      // Handle subcommands with a switch statement
      const subCommand = args[0] || "help";
      switch (subCommand) {
        case "help":
          this.emit("message", {
            content: `Available commands:
  • /yourcommand help: Show this help message
  • /yourcommand action : Do something` }); break;

     case "action":
       // Validate parameters
       if (args.length < 2) {
         this.emit("message", { content: "Missing parameters" });
         return;
       }
       // Handle the action
       break;
    
     default:
       this.emit("message", { content: "Unknown subcommand" });

    } }

  1. User Feedback

    // Success messages
    this.emit("message", { content: "Operation successful!" });
    
    // Error handling
    try {
      // Your code
    } catch (err: any) {
      console.error("Error:", err);
      this.emit("message", { content: `Error: ${err.message}` });
    }

Project Structure

your-plugin/
├── src/
│   └── index.ts         # Main plugin implementation
├── build.js            # Build configuration
├── package.json        # Package configuration
├── tsconfig.json       # TypeScript configuration
└── README.md          # Documentation

Testing Your Plugin

  1. Local Testing

    // test.js
    import YourPlugin from './dist/index.js';
    
    const plugin = new YourPlugin();
    
    // Mock the context
    const mockContext = {
      wallet: {
        publicKey: null,
        signTransaction: async (tx) => tx,
        connected: false
      }
    };
    
    // Test your commands
    async function test() {
      await plugin.initialize(mockContext);
      await plugin.handleCommand('yourcommand', ['help']);
    }
    
    // Mock the emit method
    YourPlugin.prototype.emit = (event, data) => {
      console.log(`[${event}] ${data.content}`);
    };
    
    test().catch(console.error);
  2. Run Tests

    npm run build
    node test.js

Important Guidelines

  1. Export Syntax

    • Use export = PluginClass (CommonJS style)
    • Don't mix named exports with module exports
    • Don't use export default
  2. Command Structure

    • Use static strings for commands, not class properties
    • Include proper command descriptions and usage strings
    • Always prefix usage examples with "/" but not the command itself
  3. Build Requirements

    • Build both ESM and CommonJS versions
    • Mark all SDK dependencies as external
    • Use Node.js platform in build config
  4. Plugin Service Integration

    • Implement all required BasePlugin methods
    • Properly handle command parsing and execution
    • Use the emit method for user feedback

Development Workflow

  1. Setup

    npm init
    npm install api-city-sdk @types/node typescript esbuild --save-dev
  2. Build

    npm run build
  3. Publish

    npm version patch
    npm publish
  4. Submit

    • Submit your plugin through the API City plugin submission interface
    • Ensure all commands are properly defined and documented
    • Test your plugin thoroughly before submission

Common Issues

  1. No Commands Found Error

    • Check if getCommands() returns the correct format
    • Verify export syntax is CommonJS style
    • Ensure build configuration is correct
  2. Build Errors

    • Make sure all dependencies are properly marked as external
    • Verify package.json has correct "type" and "exports" fields
    • Check for proper TypeScript configuration

Dependencies

Required peer dependencies:

{
  "api-city-sdk": "latest"
}

License

ISC

Browser Compatibility

Your plugin must work in both Node.js and browser environments since it will be loaded via CDN in the frontend. Ensure:

  1. Build Configuration

    // ESM build for browsers
    await esbuild.build({
      ...sharedConfig,
      format: "esm",
      platform: "browser",  // Important for CDN loading
      outfile: "dist/index.js",
    });
  2. Package Configuration

    {
      "browser": "dist/index.js",
      "exports": {
        ".": {
          "browser": "./dist/index.js",
          "require": "./dist/index.cjs",
          "import": "./dist/index.js"
        }
      }
    }
  3. Browser-Safe Code

    • Don't use Node.js-specific APIs (fs, path, etc.)
    • Handle browser-specific cases in your plugin
    • Test your plugin in both Node.js and browser environments
1.0.16

5 months ago

1.0.15

5 months ago

1.0.14

5 months ago

1.0.13

5 months ago

1.0.12

5 months ago

1.0.11

5 months ago

1.0.10

5 months ago

1.0.9

5 months ago

1.0.8

5 months ago

1.0.7

5 months ago

1.0.6

5 months ago

1.0.5

5 months ago

1.0.4

5 months ago

1.0.3

5 months ago

1.0.2

5 months ago

1.0.1

5 months ago

1.0.0

5 months ago