Developer documentation

Plugin SDK reference

Build, package, and ship a plugin to the Aeonzap marketplace using @aeonzap/plugin-sdk.

Overview

The @aeonzap/plugin-sdk package gives you a typed entrypoint, a manifest builder, and lifecycle hooks. A plugin is a single npm package that exports a default plugin definition. The runtime loads the package inside an isolated worker, hands it a scoped client, and routes events to your handlers based on the manifest you declare.

Install

npm install @aeonzap/plugin-sdk
npm install --save-dev @aeonzap/plugin-cli

Manifest fields

Every plugin ships a manifest. The CLI validates it before publish. Unknown fields are rejected so your plugin keeps working when the SDK adds new ones.

FieldTypeRequiredDescription
idstringyesReverse-DNS identifier, e.g. com.acme.reviews
namestringyesHuman-readable name shown in the marketplace
versionsemveryesPlugin version. Marketplace enforces semver.
scopesstring[]yesCapabilities you request from the merchant
settingsJSONSchemanoSchema rendered as a config form
iconstringnoPath to a 256x256 PNG inside your package
pricingobjectnofree | one_time | subscription | usage

definePlugin

The default export of your plugin must be the result of definePlugin. The function is purely descriptive — no side effects run at import time.

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

export default definePlugin({
  id: 'com.acme.reviews',
  name: 'Acme Reviews',
  version: '1.0.0',
  scopes: ['orders.read', 'customers.read', 'storefront.blocks.write'],
  settings: {
    type: 'object',
    properties: {
      autoPublish: { type: 'boolean', default: false },
      minRating: { type: 'integer', minimum: 1, maximum: 5, default: 3 },
    },
  },
  hooks: {
    install: async (ctx) => ctx.log.info('reviews installed'),
    configure: async (ctx, settings) => ctx.kv.put('settings', settings),
    uninstall: async (ctx) => ctx.kv.clear(),
  },
  events: {
    'order.fulfilled': async (ctx, evt) => {
      await ctx.email.send({ to: evt.customer.email, template: 'review-request' });
    },
  },
});

Lifecycle hooks

  • install — fires once when a merchant installs the plugin. Allocate KV keys, register webhooks, seed defaults.
  • configure — fires every time settings change. Re-validate, re-subscribe, refresh caches.
  • uninstall — fires when a merchant removes the plugin. You have 60 seconds to clean up; after that the worker is force-killed.

Settings schema

Settings use JSON Schema draft 2020-12. The dashboard renders forms automatically — string, number, boolean, enum, and nested objects all map to native controls. Use format: "secret" to render a masked field that is encrypted at rest.

Scopes

Scopes follow a resource.verb shape. Merchants see the full list before install and can revoke individual scopes later.

ScopeGrants
orders.readRead order objects via the inbound API
orders.writeCreate and update orders
customers.readRead customer profiles
products.writeCreate, update, archive products
storefront.blocks.writeRegister and update storefront blocks
notifications.sendSend email, SMS, WhatsApp, push to merchant customers

Sample plugin in 50 lines

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

export default definePlugin({
  id: 'com.acme.lowstock',
  name: 'Low Stock Alerts',
  version: '0.1.0',
  scopes: ['products.read', 'notifications.send'],
  settings: {
    type: 'object',
    properties: {
      threshold: { type: 'integer', minimum: 1, default: 5 },
      channel: { type: 'string', enum: ['email', 'whatsapp'], default: 'email' },
    },
  },
  hooks: {
    install: async (ctx) => {
      await ctx.kv.put('seen', {});
    },
  },
  events: {
    'product.inventory.updated': async (ctx, evt) => {
      const { threshold, channel } = await ctx.settings.get();
      if (evt.inventory.available > threshold) return;
      const seen: Record<string, number> = await ctx.kv.get('seen');
      if (seen[evt.product.id] === evt.inventory.available) return;
      seen[evt.product.id] = evt.inventory.available;
      await ctx.kv.put('seen', seen);
      await ctx.notify.send({
        channel,
        to: 'merchant',
        template: 'low-stock',
        data: {
          product: evt.product.title,
          left: evt.inventory.available,
        },
      });
    },
  },
});

Publishing

Run aeonzap publish from the package root. The CLI bundles your code with esbuild, signs the artifact, and uploads it to the marketplace queue. Reviews typically clear in under 24 hours.