@dukkan.one/app-sdk/idempotency
Idempotency-Key helpers, canonical JSON as the platform hashes it, and the inbox contract the receiver deduplicates on.
- الحزمة
@dukkan.one/app-sdk@0.3.0- مراجعة الواجهة
2026-09-10- الاستيراد
import { … } from "@dukkan.one/app-sdk/idempotency"
في هذه الصفحة
الدوال
canonicalJson#
Canonical JSON exactly as the platform hashes request bodies (packages/contracts/vectors/canonical-json.json): keys sorted at every depth, arrays in order, no whitespace. Useful to detect, client-side, that two payloads would collide on one key.
deterministicIdempotencyKey#
Deterministic key from your own entity identity, so a crashed process that
re-runs the same job sends the same key and gets the recorded result
instead of a second refund: deterministicIdempotencyKey("refund", orderId, jobId).
Namespaced and hashed, so the parts can be any length and never leak.
randomIdempotencyKey#
Random key for a write that has no natural identity (reused across the SDK's own retries).
requestHash#
sha256 of the canonical JSON of a payload: the value the platform compares when the same key arrives with a different body.
resolveIdempotencyKey#
Picks the key for a write: an explicit key, else a deterministic key from ref, else a random one.
الأصناف
MemoryInboxStore#
new MemoryInboxStore(options?
In-memory inbox for tests and single-process tools; bounded so it never grows forever.
| الاسم | النوع | الوصف |
|---|---|---|
insertIfNewمطلوب | (record: InboxRecord): Promise<boolean> | |
markFailedمطلوب | (eventId: string, error: string): Promise<void> | Called when a handler failed AFTER the event was recorded, so the app can keep the row visible for a replay instead of losing the event behind the dedupe. Optional; the receiver never throws past the acknowledgement. |
failuresمطلوب | (): Map<string, string> | Events whose handler failed, with the error message, for replays and assertions. |
sizeمطلوب | number | |
recordsمطلوب | (): InboxRecord[] |
الواجهات
IdempotencyOptions#
How a write chooses its Idempotency-Key: an explicit key, or parts that identify the write in your own system.
| الاسم | النوع | الوصف |
|---|---|---|
key | string | undefined | Explicit key; wins over |
ref | Array<string | number> | undefined | Parts that identify the write in YOUR system (an order id plus a job id, a queue message id...). The SDK derives a stable key from them. |
InboxRecord#
One accepted delivery as the receiver hands it to the inbox: the signed event id, the install and store, the topic, and the payload.
| الاسم | النوع | الوصف |
|---|---|---|
eventIdمطلوب | string | |
installIdمطلوب | string | |
storeIdمطلوب | string | |
topicمطلوب | string | |
sequenceمطلوب | number | |
occurredAtمطلوب | string | |
testمطلوب | boolean | |
payloadمطلوب | Record<string, unknown> | |
receivedAtمطلوب | string |
InboxStore#
Durable inbox the webhook receiver deduplicates on. insertIfNew must be
atomic (a unique index on the event id in SQL, a conditional put in KV).
| الاسم | النوع | الوصف |
|---|---|---|
insertIfNewمطلوب | (record: InboxRecord): Promise<boolean> | |
markFailed | ((eventId: string, error: string) => Promise<void>) | undefined | Called when a handler failed AFTER the event was recorded, so the app can keep the row visible for a replay instead of losing the event behind the dedupe. Optional; the receiver never throws past the acknowledgement. |
الثوابت
IDEMPOTENCY_KEY_MAX_LENGTH#
Idempotency-Key helpers (docs/reference/api#idempotency). The platform
remembers a key for 24 hours per install: the same key with the same body
replays the recorded response, the same key with a different body is a 409.