@restomenum/plugin-sdk

Restomenum eklenti platformu için resmi TypeScript SDK'sı. Webhook imza doğrulama, OAuth token exchange, tipli Callback API istemcisi, event/scope katalogu ve tipler — tek pakette. Node 20+ (global fetch), sıfır runtime bağımlılığı (yalnız node:crypto).

Kurulum

npm install @restomenum/plugin-sdk

SDK; manuel imza/HTTP yazımını ortadan kaldırır ve OAuth Connect, token exchange, webhook ve Data API sözleşmelerini tipli olarak sunar.

Webhook imza doğrulama

İmza ham gövde üzerinden doğrulanır (JSON.parse edilmiş değil), ±5 dk replay penceresi, timing-safe. Geçersizse 401 dön.

import { verifyWebhookSignature } from '@restomenum/plugin-sdk';

// Express (ham gövdeyi sakla: app.use(express.json({ verify: (req, _res, buf) => { req.rawBody = buf } })))
const ok = verifyWebhookSignature(req.rawBody.toString('utf8'), req.headers['x-restomenum-signature'], webhookSecret);
if (!ok) return res.status(401).json({ error: 'invalid_signature' });

Hazır Express middleware — imza + şekil doğrulamayı otomatik yapar:

expressWebhook
import { expressWebhook } from '@restomenum/plugin-sdk';

app.post('/webhook', express.json({ verify: (req, _r, buf) => { (req as any).rawBody = buf; } }),
  expressWebhook(
    { getSecret: (tenantId) => store.webhookSecretFor(tenantId) },   // senkron/async
    async (envelope) => {
      // imza + şekil doğrulandı; envelope = { id, type, tenantId, occurredAt, data }
      if (envelope.type === 'table.created') await handle(envelope.data);
      // yanıt yazmazsan otomatik 200 { ok:true }
    },
  ),
);

Ayrıntı: İmza Şeması (HMAC) · /webhook Alıcı.

OAuth token exchange

import { exchangeCode } from '@restomenum/plugin-sdk';

const cred = await exchangeCode(
  { code, clientId, clientSecret },
  { environment: 'sandbox' }, // veya { baseUrl }
);
// cred = { tenantId, apiKey, webhookSecret, scopes }  → tenant başına SAKLA

cred tenant başına saklanır (apiKey + webhookSecret). Akış: OAuth ConnectToken Exchange.

Callback API istemcisi (tipli)

import { RestomenumClient } from '@restomenum/plugin-sdk';

const client = new RestomenumClient({ apiKey: cred.apiKey, environment: 'production' });

const packets = await client.packets.open();
const packet  = await client.packets.get('packetId');
const products = await client.products.list();          // { data, truncated?, total? }
const customer = await client.customers.get('custId');  // PII consent kuralı sunucuda uygulanır

// Müşteri listesi — cursor pagination (offset YOK):
for await (const c of client.customers.listAll(200)) {
  // tüm müşteriler, sayfa sayfa otomatik
}

Kaynak grupları: packets, tables, products, categories, paymentMethods, ingredients, users, customers. Tümü: Data API.

Hata yönetimi

REST hata kodları ApiError'a çevrilir; OAuth hataları OAuthError; imza SignatureError.

import { ApiError } from '@restomenum/plugin-sdk';
try {
  await client.packets.get('yok');
} catch (e) {
  if (e instanceof ApiError) {
    console.log(e.status, e.code);          // 404, "plugin.packets.notFound"
    if (e.status === 429) wait(e.retryAfterSec); // Retry-After (sn)
  }
}

Action (buton/hook) yanıtı

import { actionResponse } from '@restomenum/plugin-sdk';
res.json(actionResponse(true, 'İşlem tamam', { level: 'success', display: 'toast' }));

Sözleşme: Action Ucu · Aksiyon Butonları.

Katalog & tipler

import { EVENT_TYPES, SCOPES, PII_SCOPES, isPiiScope, isEventType } from '@restomenum/plugin-sdk';
import type { EventType, Scope, WebhookEnvelope, Customer, Packet, ActionRequest } from '@restomenum/plugin-sdk';

Geçerli değerler: Event Kataloğu · Scope Referansı.

Manifest'i AI ile oluşturmak/düzenlemek mi istersin? Remote MCP ile Claude'a bağlan, eklentini sohbetle yönet.