@waffo/pancake-ts 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/index.cjs +16 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -1
- package/dist/index.d.ts +17 -1
- package/dist/index.js +16 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,17 @@ All notable changes to `@waffo/pancake-ts` will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.2.2] - 2026-04-03
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **Checkout idempotency** — Checkout methods (`anonymous.create()`, `authenticated.create()`, `createSession()`) now use time-windowed idempotency keys (60-second window) instead of fully deterministic keys. Previously, identical checkout params always produced the same `X-Idempotency-Key`, causing the gateway to return cached (and potentially expired) sessions. Now, same params within the same minute are still deduped (protects against network retries), but a new key is generated after the window elapses.
|
|
12
|
+
- **Timestamp consistency** — `Date.now()` is now called once per request and shared between signature timestamp and idempotency key calculation, eliminating a theoretical edge case where the two could land in different seconds.
|
|
13
|
+
|
|
14
|
+
### Internal
|
|
15
|
+
|
|
16
|
+
- **`PostOptions` interface** — Extracted inline `{ idempotencyWindow?: number }` into a named type in `types.ts` (not publicly exported).
|
|
17
|
+
|
|
7
18
|
## [0.2.1] - 2026-04-02
|
|
8
19
|
|
|
9
20
|
### Added
|
package/dist/index.cjs
CHANGED
|
@@ -222,18 +222,26 @@ var HttpClient = class {
|
|
|
222
222
|
*
|
|
223
223
|
* Behavior:
|
|
224
224
|
* - Generates a deterministic `X-Idempotency-Key` from `merchantId + path + body` (same request produces same key)
|
|
225
|
+
* - When `idempotencyWindow` is set, a floored timestamp is mixed into the key so identical params produce
|
|
226
|
+
* a new key after the window elapses (useful for checkout where repeated creation is intentional)
|
|
225
227
|
* - Auto-builds RSA-SHA256 signature (`X-Merchant-Id` / `X-Timestamp` / `X-Signature`)
|
|
226
228
|
* - Unwraps the response envelope: returns `data` on success, throws `WaffoPancakeError` on failure
|
|
227
229
|
*
|
|
228
230
|
* @param path - API path (e.g. `/v1/actions/store/create-store`)
|
|
229
231
|
* @param body - Request body object
|
|
232
|
+
* @param options - Optional settings
|
|
233
|
+
* @param options.idempotencyWindow - Time window in seconds for idempotency key rotation (e.g. 60 = per-minute dedup)
|
|
230
234
|
* @returns Parsed `data` field from the response
|
|
231
235
|
* @throws {WaffoPancakeError} When the API returns errors
|
|
232
236
|
*/
|
|
233
|
-
async post(path, body) {
|
|
237
|
+
async post(path, body, options) {
|
|
234
238
|
const bodyStr = JSON.stringify(body);
|
|
235
|
-
const
|
|
239
|
+
const now = Date.now();
|
|
240
|
+
const timestampSec = Math.floor(now / 1e3);
|
|
241
|
+
const timestamp = timestampSec.toString();
|
|
236
242
|
const signature = signRequest("POST", path, timestamp, bodyStr, this.privateKey);
|
|
243
|
+
const idempotencyBase = `${this.merchantId}:${path}:${bodyStr}`;
|
|
244
|
+
const idempotencyInput = options?.idempotencyWindow ? `${idempotencyBase}:${Math.floor(timestampSec / options.idempotencyWindow)}` : idempotencyBase;
|
|
237
245
|
const response = await this._fetch(`${this.baseUrl}${path}`, {
|
|
238
246
|
method: "POST",
|
|
239
247
|
headers: {
|
|
@@ -241,7 +249,7 @@ var HttpClient = class {
|
|
|
241
249
|
"X-Merchant-Id": this.merchantId,
|
|
242
250
|
"X-Timestamp": timestamp,
|
|
243
251
|
"X-Signature": signature,
|
|
244
|
-
"X-Idempotency-Key": (0, import_node_crypto2.createHash)("sha256").update(
|
|
252
|
+
"X-Idempotency-Key": (0, import_node_crypto2.createHash)("sha256").update(idempotencyInput).digest("hex")
|
|
245
253
|
},
|
|
246
254
|
body: bodyStr
|
|
247
255
|
});
|
|
@@ -528,7 +536,8 @@ var CheckoutAnonymousResource = class {
|
|
|
528
536
|
validateCheckoutCommon(params);
|
|
529
537
|
return this.http.post(
|
|
530
538
|
"/v1/actions/checkout/create-session",
|
|
531
|
-
params
|
|
539
|
+
params,
|
|
540
|
+
{ idempotencyWindow: 60 }
|
|
532
541
|
);
|
|
533
542
|
}
|
|
534
543
|
};
|
|
@@ -568,11 +577,11 @@ var CheckoutAuthenticatedResource = class {
|
|
|
568
577
|
this.http.post("/v1/actions/auth/issue-session-token", {
|
|
569
578
|
storeId: params.storeId,
|
|
570
579
|
buyerIdentity
|
|
571
|
-
}),
|
|
580
|
+
}, { idempotencyWindow: 60 }),
|
|
572
581
|
this.http.post("/v1/actions/checkout/create-session", {
|
|
573
582
|
...sessionFields,
|
|
574
583
|
buyerEmail: buyerEmail ?? buyerIdentity
|
|
575
|
-
})
|
|
584
|
+
}, { idempotencyWindow: 60 })
|
|
576
585
|
]);
|
|
577
586
|
return {
|
|
578
587
|
sessionId: sessionResult.sessionId,
|
|
@@ -615,7 +624,7 @@ var CheckoutResource = class {
|
|
|
615
624
|
* // Redirect to session.checkoutUrl
|
|
616
625
|
*/
|
|
617
626
|
async createSession(params) {
|
|
618
|
-
return this.http.post("/v1/actions/checkout/create-session", params);
|
|
627
|
+
return this.http.post("/v1/actions/checkout/create-session", params, { idempotencyWindow: 60 });
|
|
619
628
|
}
|
|
620
629
|
};
|
|
621
630
|
|