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).
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.
İ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:
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ı.
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 SAKLAcred tenant başına saklanır (apiKey + webhookSecret). Akış: OAuth Connect → Token Exchange.
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.
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)
}
}import { actionResponse } from '@restomenum/plugin-sdk';
res.json(actionResponse(true, 'İşlem tamam', { level: 'success', display: 'toast' }));Sözleşme: Action Ucu · Aksiyon Butonları.
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ı.