Jiffoo Docs

Plugin SDK

Current SDK surface and plugin manifest contract for Jiffoo Mall plugins

Plugin SDK Reference

@jiffoo/plugin-sdk is the supported package for building Jiffoo Mall plugins. It shares the same manifest contract as the platform installer, so manifest.json validation is consistent between local SDK tooling and Admin upload.

Installation

npm install @jiffoo/plugin-sdk

Core Exports

  • definePlugin(): declare plugin metadata and collect routes/hooks
  • createRoute(): create route definitions with the current (path, handler, options) signature
  • createHook(): create event hooks with the current (event, handler, options) signature
  • createContextMiddleware(): extract platform headers into req.pluginContext
  • createSignatureMiddleware() / verifySignature(): verify signed platform requests
  • defineLifecycleHooks(): expose POST /__lifecycle/:hookName handlers for external-http plugins
  • validateManifest(): validate manifest.json against the shared authoritative contract

Manifest Contract

interface PluginManifest {
  schemaVersion: 1;
  slug: string;
  name: string;
  version: string;
  description: string;
  runtimeType: 'internal-fastify' | 'external-http';
  permissions: string[];
  entryModule?: string;
  externalBaseUrl?: string;
  category?: PluginCategory;
  capabilities?: string[];
  minApiVersion?: string;
  sdkVersion?: string;
  requiredApiVersion?: { min?: string; max?: string; exact?: string };
  lifecycle?: {
    onInstall?: boolean;
    onEnable?: boolean;
    onDisable?: boolean;
    onUninstall?: boolean;
    onUpgrade?: boolean;
  };
  themeExtensions?: {
    blocks?: Array<{
      extensionId: string;
      name: string;
      schema?: Record<string, unknown>;
      dataEndpoint?: string;
    }>;
    embeds?: Array<{
      extensionId: string;
      name: string;
      targetPosition: 'head-end' | 'body-end';
      schema?: Record<string, unknown>;
      dataEndpoint?: string;
    }>;
  };
}

Contract notes:

  • entryModule is required for internal-fastify
  • externalBaseUrl is required for external-http
  • minApiVersion is the platform-facing compatibility floor
  • requiredApiVersion is optional structured compatibility metadata used by SDK helpers
  • sdkVersion, version, and requiredApiVersion.* use strict validation

Define a Plugin

import { definePlugin } from '@jiffoo/plugin-sdk';

export const plugin = definePlugin({
  schemaVersion: 1,
  slug: 'my-plugin',
  name: 'My Plugin',
  version: '1.0.0',
  description: 'Example Jiffoo plugin',
  runtimeType: 'external-http',
  externalBaseUrl: 'https://my-plugin.example.com',
  permissions: [],
  category: 'integration',
  capabilities: ['webhook.receive'],
  minApiVersion: 'v1',
  sdkVersion: '1.2.0',
});

Routes and Hooks

import { createHook, createRoute } from '@jiffoo/plugin-sdk';

const syncRoute = createRoute(
  '/api/sync',
  async (_req, res) => {
    res.json({ success: true });
  },
  { method: 'POST', requiresAuth: true }
);

const orderCreatedHook = createHook(
  'order.created',
  async (payload) => {
    console.log('New order', payload);
  },
  { priority: 10 }
);

plugin.addRoute(syncRoute);
plugin.addHook(orderCreatedHook);

Lifecycle Hooks

import { defineLifecycleHooks } from '@jiffoo/plugin-sdk';

const lifecycle = defineLifecycleHooks({
  onInstall: async (context) => {
    console.log(`Install ${context.installationId}`);
  },
  onUpgrade: async (context) => {
    console.log(`Upgrade from ${context.previousVersion}`);
  },
});

Mount it at POST /__lifecycle/:hookName and declare the matching booleans in manifest.json.

Local Validation

import { validateManifest } from '@jiffoo/plugin-sdk';

const result = validateManifest({
  schemaVersion: 1,
  slug: 'my-plugin',
  name: 'My Plugin',
  version: '1.0.0',
  description: 'Example plugin',
  runtimeType: 'external-http',
  externalBaseUrl: 'https://my-plugin.example.com',
  permissions: [],
});

if (!result.valid) {
  console.error(result.errors);
}

Or via CLI:

npx @jiffoo/plugin-sdk validate --manifest ./manifest.json

Compatibility Metadata

Use minApiVersion when you want the platform to enforce a minimum supported API version during install or enable. Use requiredApiVersion only when you need the SDK’s semver-based compatibility helpers for external tooling.

On this page