@waffo/pancake-ts 0.7.0 → 0.8.0

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 CHANGED
@@ -4,6 +4,39 @@ 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.8.0] - 2026-05-17
8
+
9
+ ### Fixed
10
+
11
+ - **GraphQL queries actually return data.** Prior versions assumed a double-wrapped envelope (`{data:{data,errors,warnings}}`) and stripped one layer too many, so `result.data` was always `undefined` regardless of what the server returned. The wire is in fact the standard single-layer GraphQL envelope (`{data, errors?, warnings?}`); the SDK now returns it verbatim.
12
+ - **GraphQL queries no longer carry `X-Idempotency-Key`.** Queries are read-only; the gateway was caching them for 24h and serving stale snapshots on subsequent identical requests. Side-effect-free queries now hit the live DB on every call.
13
+ - **REST `warnings` are no longer dropped.** Every REST action endpoint can return `warnings: Notice[]` (handbook `command-layer.md`); prior `HttpClient.post()` returned only the unwrapped `data` field, throwing away migration `aiHint` notices like `update-store`'s `webhookSettings field ignored → Switch to client.webhooks.add/update/remove`.
14
+
15
+ ### Changed
16
+
17
+ - **Resource method return types widened** from `Promise<X>` to `Promise<X & { warnings?: Notice[] }>` for every REST action method (`stores`, `storeMerchants`, `onetimeProducts`, `subscriptionProducts`, `subscriptionProductGroups`, `orders`, `checkout.*`, `webhooks.add/update/remove`, `auth.issueSessionToken`, `buyer.cancelSubscription / cancelOnetimeOrder / reactivateSubscription / createRefundTicket / resubmitRefundTicket`). Existing destructuring (`const { store } = await client.stores.create(...)`) keeps working; add `warnings` to the destructure to read advisories.
18
+ - **Transport refactored**: `HttpClient.post<T>()` now returns the parsed envelope plus HTTP status (`PostResult<T> = { status, data, errors?, warnings? }`) without throwing on `errors[]`. Throw / unwrap / warnings handling moved to the resource layer via the internal `unwrapAction` helper. GraphQL resources return the envelope verbatim.
19
+ - **`GraphQLResource.query` and `BuyerGraphQL.query` pass `noIdempotency: true`** to the transport (suppresses `X-Idempotency-Key`).
20
+
21
+ ### Added
22
+
23
+ - **`Notice` type** (`{ message, layer, aiHint? }`) — unified shape used by both REST and GraphQL `errors[]` / `warnings[]`. Exported from `index.ts`.
24
+ - **`Envelope<T>` / `PostResult<T>` types** — transport-level envelope (and `PostResult` adds HTTP `status`). Exported for advanced callers.
25
+ - **`GraphQLResponse.errors[].layer?`** — optional field carrying which service stage produced the error (`"graphql"`, `"gateway"`).
26
+ - **`PostOptions.noIdempotency`** — boolean to suppress the `X-Idempotency-Key` header on a per-call basis.
27
+ - **README "Warnings (Migration Notices)" section** with REST + GraphQL examples and explicit guidance for LLM/agent consumers to act on `aiHint`.
28
+
29
+ ### Deprecated
30
+
31
+ - **`ApiError`, `ApiResponse`, `ApiSuccessResponse`, `ApiErrorResponse`** — kept as type aliases for backwards compatibility; prefer `Notice` and the new `Envelope<T>` / `PostResult<T>`.
32
+
33
+ ### Migration
34
+
35
+ - **Most callers need no changes.** Destructuring (`const { store } = ...`) still works; the new `warnings` field is optional and untouched code ignores it.
36
+ - **GraphQL callers**: if you have hacks that read `(result as any).stores` directly (bypassing the broken `result.data`), revert to `result.data.stores` — the bug that motivated the hack is gone.
37
+ - **LLM/agent consumers**: read `result.warnings?.[].aiHint` on every action — that's where the platform team puts canonical migration instructions when an API evolves (e.g. `update-store`'s deprecated `webhookSettings` field).
38
+ - **Direct `HttpClient.post` consumers** (rare; `HttpClient` is internal but reachable): return type changed from `T` to `PostResult<T>`; access `.data` to get the unwrapped payload, inspect `.errors` / `.warnings` directly. The transport no longer throws on `errors[]`.
39
+
7
40
  ## [0.7.0] - 2026-05-11
8
41
 
9
42
  ### Changed
package/README.md CHANGED
@@ -305,6 +305,32 @@ const detail = await client.graphql.query({
305
305
 
306
306
  See [GraphQL Guide](docs/graphql-guide.md) for filters, analytics queries, delivery logs, and more.
307
307
 
308
+ ## Warnings (Migration Notices)
309
+
310
+ Every successful REST action and GraphQL query may carry a `warnings` array alongside the data. Warnings describe non-fatal advisories the server wants you to act on — typically deprecated parameters, fields scheduled for removal, or new APIs you should switch to. Each `Notice` has `message` (human-readable), `layer` (which service produced it), and `aiHint` (a structured migration instruction aimed at LLM consumers).
311
+
312
+ ```typescript
313
+ // REST action — warnings spread onto the result alongside the typed payload
314
+ const { store, warnings } = await client.stores.update({
315
+ id: "STO_xxx",
316
+ webhookSettings: { ... }, // deprecated input
317
+ });
318
+ if (warnings) {
319
+ for (const w of warnings) {
320
+ console.warn(`[${w.layer}] ${w.message}`, w.aiHint);
321
+ // e.g. layer=store, aiHint="Switch to client.webhooks.add / update / remove"
322
+ }
323
+ }
324
+
325
+ // GraphQL — warnings sit on the envelope alongside data and errors
326
+ const result = await client.graphql.query<StoresQuery>({
327
+ query: `query { stores { id } }`,
328
+ });
329
+ result.warnings?.forEach(w => console.warn(w.message, w.aiHint));
330
+ ```
331
+
332
+ **LLM/agent consumers**: always check `aiHint` on every warning — it is the canonical migration instruction (npm package, version, method name, endpoint path) the platform team intends for you to follow when the underlying API evolves.
333
+
308
334
  ## Programmatic Store & Product Management
309
335
 
310
336
  > Most merchants manage stores and products in the [Dashboard](https://pancake.waffo.ai/dashboard). The following APIs are for merchants who need programmatic automation.
package/dist/index.cjs CHANGED
@@ -65,12 +65,10 @@ var BuyerHttpClient = class {
65
65
  this._fetch = config.fetch ?? globalThis.fetch.bind(globalThis);
66
66
  }
67
67
  /**
68
- * Send a Bearer-authenticated POST request and return the parsed `data` field.
68
+ * Send a Bearer-authenticated POST and return the full envelope plus HTTP status.
69
69
  *
70
- * @param path - API path
71
- * @param body - Request body object
72
- * @returns Parsed `data` field from the response
73
- * @throws {WaffoPancakeError} When the API returns errors
70
+ * Does NOT throw on `errors[]` or non-2xx status — caller inspects the result.
71
+ * Throws {@link WaffoPancakeError} only when the response body is not valid JSON.
74
72
  */
75
73
  async post(path, body) {
76
74
  const response = await this._fetch(`${this.baseUrl}${path}`, {
@@ -81,11 +79,13 @@ var BuyerHttpClient = class {
81
79
  },
82
80
  body: JSON.stringify(body)
83
81
  });
84
- const result = await response.json();
85
- if ("errors" in result && result.errors) {
86
- throw new WaffoPancakeError(response.status, result.errors);
82
+ let envelope;
83
+ try {
84
+ envelope = await response.json();
85
+ } catch {
86
+ throw new WaffoPancakeError(response.status, [{ message: `Non-JSON response from ${path}`, layer: "sdk" }]);
87
87
  }
88
- return result.data;
88
+ return { status: response.status, ...envelope };
89
89
  }
90
90
  };
91
91
 
@@ -201,48 +201,64 @@ var HttpClient = class {
201
201
  this._fetch = config.fetch ?? globalThis.fetch.bind(globalThis);
202
202
  }
203
203
  /**
204
- * Send a signed POST request and return the parsed `data` field.
204
+ * Send a signed POST and return the full envelope plus HTTP status.
205
205
  *
206
206
  * Behavior:
207
- * - Generates a deterministic `X-Idempotency-Key` from `merchantId + path + body` (same request produces same key)
208
- * - When `idempotencyWindow` is set, a floored timestamp is mixed into the key so identical params produce
209
- * a new key after the window elapses (useful for checkout where repeated creation is intentional)
210
- * - Auto-builds RSA-SHA256 signature (`X-Merchant-Id` / `X-Timestamp` / `X-Signature`)
211
- * - Unwraps the response envelope: returns `data` on success, throws `WaffoPancakeError` on failure
212
- *
213
- * @param path - API path (e.g. `/v1/actions/store/create-store`)
207
+ * - Builds RSA-SHA256 signature (`X-Merchant-Id` / `X-Timestamp` / `X-Signature`)
208
+ * - Attaches `X-Idempotency-Key` (deterministic `sha256(merchantId + path + body)`)
209
+ * unless `options.noIdempotency` is set
210
+ * - When `options.idempotencyWindow` is set, a floored timestamp is mixed into the
211
+ * key so identical params produce a new key after the window elapses
212
+ * - Does NOT throw on `errors[]` or non-2xx status — caller inspects the result
213
+ * - Throws {@link WaffoPancakeError} only on transport failures (non-JSON body)
214
+ *
215
+ * @param path - API path (e.g. `/v1/actions/store/create-store`, `/v1/graphql`)
214
216
  * @param body - Request body object
215
217
  * @param options - Optional settings
216
- * @param options.idempotencyWindow - Time window in seconds for idempotency key rotation (e.g. 60 = per-minute dedup)
217
- * @returns Parsed `data` field from the response
218
- * @throws {WaffoPancakeError} When the API returns errors
218
+ * @returns Parsed envelope with HTTP status
219
+ * @throws {WaffoPancakeError} When the response body is not valid JSON
219
220
  */
220
221
  async post(path, body, options) {
221
222
  const bodyStr = JSON.stringify(body);
222
- const now = Date.now();
223
- const timestampSec = Math.floor(now / 1e3);
223
+ const timestampSec = Math.floor(Date.now() / 1e3);
224
224
  const timestamp = timestampSec.toString();
225
225
  const signature = signRequest("POST", path, timestamp, bodyStr, this.privateKey);
226
- const idempotencyBase = `${this.merchantId}:${path}:${bodyStr}`;
227
- const idempotencyInput = options?.idempotencyWindow ? `${idempotencyBase}:${Math.floor(timestampSec / options.idempotencyWindow)}` : idempotencyBase;
226
+ const headers = {
227
+ "Content-Type": "application/json",
228
+ "X-Merchant-Id": this.merchantId,
229
+ "X-Timestamp": timestamp,
230
+ "X-Signature": signature
231
+ };
232
+ if (!options?.noIdempotency) {
233
+ headers["X-Idempotency-Key"] = computeIdempotencyKey(this.merchantId, path, bodyStr, timestampSec, options);
234
+ }
228
235
  const response = await this._fetch(`${this.baseUrl}${path}`, {
229
236
  method: "POST",
230
- headers: {
231
- "Content-Type": "application/json",
232
- "X-Merchant-Id": this.merchantId,
233
- "X-Timestamp": timestamp,
234
- "X-Signature": signature,
235
- "X-Idempotency-Key": (0, import_node_crypto2.createHash)("sha256").update(idempotencyInput).digest("hex")
236
- },
237
+ headers,
237
238
  body: bodyStr
238
239
  });
239
- const result = await response.json();
240
- if ("errors" in result && result.errors) {
241
- throw new WaffoPancakeError(response.status, result.errors);
240
+ let envelope;
241
+ try {
242
+ envelope = await response.json();
243
+ } catch {
244
+ throw new WaffoPancakeError(response.status, [{ message: `Non-JSON response from ${path}`, layer: "sdk" }]);
242
245
  }
243
- return result.data;
246
+ return { status: response.status, ...envelope };
244
247
  }
245
248
  };
249
+ function computeIdempotencyKey(merchantId, path, bodyStr, timestampSec, options) {
250
+ const base = `${merchantId}:${path}:${bodyStr}`;
251
+ const input = options?.idempotencyWindow ? `${base}:${Math.floor(timestampSec / options.idempotencyWindow)}` : base;
252
+ return (0, import_node_crypto2.createHash)("sha256").update(input).digest("hex");
253
+ }
254
+
255
+ // src/resources/internal.ts
256
+ function unwrapAction(r) {
257
+ if (r.errors?.length) {
258
+ throw new WaffoPancakeError(r.status, r.errors);
259
+ }
260
+ return { ...r.data, ...r.warnings ? { warnings: r.warnings } : {} };
261
+ }
246
262
 
247
263
  // src/validation.ts
248
264
  var SHORT_ID_REGEX = /^[A-Z]{2,5}_[0-9A-Za-z]{22}$/;
@@ -377,7 +393,7 @@ var AuthResource = class {
377
393
  validateShortId("productId", params.productId, "PROD");
378
394
  }
379
395
  validateRequired("buyerIdentity", params.buyerIdentity);
380
- return this.http.post("/v1/actions/auth/issue-session-token", params);
396
+ return unwrapAction(await this.http.post("/v1/actions/auth/issue-session-token", params));
381
397
  }
382
398
  };
383
399
 
@@ -401,7 +417,7 @@ var BuyerSession = class {
401
417
  */
402
418
  async cancelSubscription(params) {
403
419
  validateShortId("orderId", params.orderId, "ORD");
404
- return this.http.post("/v1/actions/subscription-order/cancel-order", params);
420
+ return unwrapAction(await this.http.post("/v1/actions/subscription-order/cancel-order", params));
405
421
  }
406
422
  /**
407
423
  * Cancel a one-time order (only while payment is still pending).
@@ -414,7 +430,7 @@ var BuyerSession = class {
414
430
  */
415
431
  async cancelOnetimeOrder(params) {
416
432
  validateShortId("orderId", params.orderId, "ORD");
417
- return this.http.post("/v1/actions/onetime-order/cancel-order", params);
433
+ return unwrapAction(await this.http.post("/v1/actions/onetime-order/cancel-order", params));
418
434
  }
419
435
  /**
420
436
  * Reactivate a subscription that is in `canceling` status.
@@ -428,7 +444,7 @@ var BuyerSession = class {
428
444
  */
429
445
  async reactivateSubscription(params) {
430
446
  validateShortId("orderId", params.orderId, "ORD");
431
- return this.http.post("/v1/actions/subscription-order/reactivate-order", params);
447
+ return unwrapAction(await this.http.post("/v1/actions/subscription-order/reactivate-order", params));
432
448
  }
433
449
  /**
434
450
  * Submit a refund request for a payment.
@@ -448,7 +464,7 @@ var BuyerSession = class {
448
464
  validateRequired("reason", params.reason);
449
465
  validateAmountString("requestedAmount.amount", params.requestedAmount.amount);
450
466
  validateCurrencyCode("requestedAmount.currency", params.requestedAmount.currency);
451
- return this.http.post("/v1/actions/refund-ticket/create-ticket", params);
467
+ return unwrapAction(await this.http.post("/v1/actions/refund-ticket/create-ticket", params));
452
468
  }
453
469
  /**
454
470
  * Resubmit a previously rejected refund ticket with updated details.
@@ -470,7 +486,7 @@ var BuyerSession = class {
470
486
  validateRequired("reason", params.reason);
471
487
  validateAmountString("requestedAmount.amount", params.requestedAmount.amount);
472
488
  validateCurrencyCode("requestedAmount.currency", params.requestedAmount.currency);
473
- return this.http.post("/v1/actions/refund-ticket/resubmit-ticket", params);
489
+ return unwrapAction(await this.http.post("/v1/actions/refund-ticket/resubmit-ticket", params));
474
490
  }
475
491
  };
476
492
  var BuyerGraphQL = class {
@@ -490,7 +506,8 @@ var BuyerGraphQL = class {
490
506
  */
491
507
  async query(params) {
492
508
  validateRequired("query", params.query);
493
- return this.http.post("/v1/graphql", params);
509
+ const result = await this.http.post("/v1/graphql", params);
510
+ return { data: result.data, errors: result.errors, warnings: result.warnings };
494
511
  }
495
512
  };
496
513
 
@@ -523,7 +540,9 @@ var CheckoutAnonymousResource = class {
523
540
  */
524
541
  async create(params) {
525
542
  validateCheckoutCommon(params);
526
- return this.http.post("/v1/actions/checkout/create-session", params, { idempotencyWindow: 60 });
543
+ return unwrapAction(
544
+ await this.http.post("/v1/actions/checkout/create-session", params, { idempotencyWindow: 60 })
545
+ );
527
546
  }
528
547
  };
529
548
 
@@ -570,12 +589,16 @@ var CheckoutAuthenticatedResource = class {
570
589
  ),
571
590
  this.http.post("/v1/actions/checkout/create-session", sessionParams, { idempotencyWindow: 60 })
572
591
  ]);
592
+ const token = unwrapAction(tokenResult);
593
+ const session = unwrapAction(sessionResult);
594
+ const warnings = [...token.warnings ?? [], ...session.warnings ?? []];
573
595
  return {
574
- sessionId: sessionResult.sessionId,
575
- checkoutUrl: `${sessionResult.checkoutUrl}#token=${tokenResult.token}`,
576
- expiresAt: sessionResult.expiresAt,
577
- token: tokenResult.token,
578
- tokenExpiresAt: tokenResult.expiresAt
596
+ sessionId: session.sessionId,
597
+ checkoutUrl: `${session.checkoutUrl}#token=${token.token}`,
598
+ expiresAt: session.expiresAt,
599
+ token: token.token,
600
+ tokenExpiresAt: token.expiresAt,
601
+ ...warnings.length > 0 ? { warnings } : {}
579
602
  };
580
603
  }
581
604
  };
@@ -609,7 +632,9 @@ var CheckoutResource = class {
609
632
  * // Redirect to session.checkoutUrl
610
633
  */
611
634
  async createSession(params) {
612
- return this.http.post("/v1/actions/checkout/create-session", params, { idempotencyWindow: 60 });
635
+ return unwrapAction(
636
+ await this.http.post("/v1/actions/checkout/create-session", params, { idempotencyWindow: 60 })
637
+ );
613
638
  }
614
639
  };
615
640
 
@@ -638,7 +663,8 @@ var GraphQLResource = class {
638
663
  */
639
664
  async query(params) {
640
665
  validateRequired("query", params.query);
641
- return this.http.post("/v1/graphql", params);
666
+ const result = await this.http.post("/v1/graphql", params, { noIdempotency: true });
667
+ return { data: result.data, errors: result.errors, warnings: result.warnings };
642
668
  }
643
669
  };
644
670
 
@@ -664,7 +690,7 @@ var OnetimeProductsResource = class {
664
690
  validateShortId("storeId", params.storeId, "STO");
665
691
  validateRequired("name", params.name);
666
692
  validatePrices("prices", params.prices);
667
- return this.http.post("/v1/actions/onetime-product/create-product", params);
693
+ return unwrapAction(await this.http.post("/v1/actions/onetime-product/create-product", params));
668
694
  }
669
695
  /**
670
696
  * Update a one-time product. Creates a new version; skips if unchanged.
@@ -690,7 +716,7 @@ var OnetimeProductsResource = class {
690
716
  validateShortId("id", params.id, "PROD");
691
717
  if (params.name !== void 0) validateRequired("name", params.name);
692
718
  if (params.prices) validatePrices("prices", params.prices);
693
- return this.http.post("/v1/actions/onetime-product/update-product", params);
719
+ return unwrapAction(await this.http.post("/v1/actions/onetime-product/update-product", params));
694
720
  }
695
721
  /**
696
722
  * Publish a one-time product's test version to production.
@@ -703,7 +729,7 @@ var OnetimeProductsResource = class {
703
729
  */
704
730
  async publish(params) {
705
731
  validateShortId("id", params.id, "PROD");
706
- return this.http.post("/v1/actions/onetime-product/publish-product", params);
732
+ return unwrapAction(await this.http.post("/v1/actions/onetime-product/publish-product", params));
707
733
  }
708
734
  /**
709
735
  * Update a one-time product's status (active/inactive).
@@ -720,7 +746,7 @@ var OnetimeProductsResource = class {
720
746
  async updateStatus(params) {
721
747
  validateShortId("id", params.id, "PROD");
722
748
  validateEnum("status", params.status, ["active", "inactive"]);
723
- return this.http.post("/v1/actions/onetime-product/update-status", params);
749
+ return unwrapAction(await this.http.post("/v1/actions/onetime-product/update-status", params));
724
750
  }
725
751
  };
726
752
 
@@ -746,7 +772,7 @@ var OrdersResource = class {
746
772
  */
747
773
  async cancelSubscription(params) {
748
774
  validateShortId("orderId", params.orderId, "ORD");
749
- return this.http.post("/v1/actions/subscription-order/cancel-order", params);
775
+ return unwrapAction(await this.http.post("/v1/actions/subscription-order/cancel-order", params));
750
776
  }
751
777
  };
752
778
 
@@ -772,7 +798,7 @@ var StoreMerchantsResource = class {
772
798
  validateShortId("storeId", params.storeId, "STO");
773
799
  validateRequired("email", params.email);
774
800
  validateEnum("role", params.role, ["admin", "member"]);
775
- return this.http.post("/v1/actions/store-merchant/add-merchant", params);
801
+ return unwrapAction(await this.http.post("/v1/actions/store-merchant/add-merchant", params));
776
802
  }
777
803
  /**
778
804
  * Remove a merchant from a store.
@@ -789,7 +815,7 @@ var StoreMerchantsResource = class {
789
815
  async remove(params) {
790
816
  validateShortId("storeId", params.storeId, "STO");
791
817
  validateShortId("merchantId", params.merchantId, "MER");
792
- return this.http.post("/v1/actions/store-merchant/remove-merchant", params);
818
+ return unwrapAction(await this.http.post("/v1/actions/store-merchant/remove-merchant", params));
793
819
  }
794
820
  /**
795
821
  * Update a merchant's role in a store.
@@ -808,7 +834,7 @@ var StoreMerchantsResource = class {
808
834
  validateShortId("storeId", params.storeId, "STO");
809
835
  validateShortId("merchantId", params.merchantId, "MER");
810
836
  validateEnum("role", params.role, ["admin", "member"]);
811
- return this.http.post("/v1/actions/store-merchant/update-role", params);
837
+ return unwrapAction(await this.http.post("/v1/actions/store-merchant/update-role", params));
812
838
  }
813
839
  };
814
840
 
@@ -828,7 +854,7 @@ var StoresResource = class {
828
854
  */
829
855
  async create(params) {
830
856
  validateRequired("name", params.name);
831
- return this.http.post("/v1/actions/store/create-store", params);
857
+ return unwrapAction(await this.http.post("/v1/actions/store/create-store", params));
832
858
  }
833
859
  /**
834
860
  * Update an existing store's settings.
@@ -860,7 +886,7 @@ var StoresResource = class {
860
886
  */
861
887
  async update(params) {
862
888
  validateShortId("id", params.id, "STO");
863
- return this.http.post("/v1/actions/store/update-store", params);
889
+ return unwrapAction(await this.http.post("/v1/actions/store/update-store", params));
864
890
  }
865
891
  /**
866
892
  * Soft-delete a store. Only the owner can delete.
@@ -873,7 +899,7 @@ var StoresResource = class {
873
899
  */
874
900
  async delete(params) {
875
901
  validateShortId("id", params.id, "STO");
876
- return this.http.post("/v1/actions/store/delete-store", params);
902
+ return unwrapAction(await this.http.post("/v1/actions/store/delete-store", params));
877
903
  }
878
904
  };
879
905
 
@@ -899,7 +925,9 @@ var SubscriptionProductGroupsResource = class {
899
925
  async create(params) {
900
926
  validateShortId("storeId", params.storeId, "STO");
901
927
  validateRequired("name", params.name);
902
- return this.http.post("/v1/actions/subscription-product-group/create-group", params);
928
+ return unwrapAction(
929
+ await this.http.post("/v1/actions/subscription-product-group/create-group", params)
930
+ );
903
931
  }
904
932
  /**
905
933
  * Update a subscription product group. `productIds` is a full replacement.
@@ -915,7 +943,9 @@ var SubscriptionProductGroupsResource = class {
915
943
  */
916
944
  async update(params) {
917
945
  validateRequired("id", params.id);
918
- return this.http.post("/v1/actions/subscription-product-group/update-group", params);
946
+ return unwrapAction(
947
+ await this.http.post("/v1/actions/subscription-product-group/update-group", params)
948
+ );
919
949
  }
920
950
  /**
921
951
  * Hard-delete a subscription product group.
@@ -928,7 +958,9 @@ var SubscriptionProductGroupsResource = class {
928
958
  */
929
959
  async delete(params) {
930
960
  validateRequired("id", params.id);
931
- return this.http.post("/v1/actions/subscription-product-group/delete-group", params);
961
+ return unwrapAction(
962
+ await this.http.post("/v1/actions/subscription-product-group/delete-group", params)
963
+ );
932
964
  }
933
965
  /**
934
966
  * Publish a test-environment group to production (upsert).
@@ -941,7 +973,9 @@ var SubscriptionProductGroupsResource = class {
941
973
  */
942
974
  async publish(params) {
943
975
  validateRequired("id", params.id);
944
- return this.http.post("/v1/actions/subscription-product-group/publish-group", params);
976
+ return unwrapAction(
977
+ await this.http.post("/v1/actions/subscription-product-group/publish-group", params)
978
+ );
945
979
  }
946
980
  };
947
981
 
@@ -969,7 +1003,9 @@ var SubscriptionProductsResource = class {
969
1003
  validateRequired("name", params.name);
970
1004
  validateEnum("billingPeriod", params.billingPeriod, ["weekly", "monthly", "quarterly", "yearly"]);
971
1005
  validatePrices("prices", params.prices);
972
- return this.http.post("/v1/actions/subscription-product/create-product", params);
1006
+ return unwrapAction(
1007
+ await this.http.post("/v1/actions/subscription-product/create-product", params)
1008
+ );
973
1009
  }
974
1010
  /**
975
1011
  * Update a subscription product. Creates a new version; skips if unchanged.
@@ -998,7 +1034,9 @@ var SubscriptionProductsResource = class {
998
1034
  if (params.billingPeriod !== void 0)
999
1035
  validateEnum("billingPeriod", params.billingPeriod, ["weekly", "monthly", "quarterly", "yearly"]);
1000
1036
  if (params.prices) validatePrices("prices", params.prices);
1001
- return this.http.post("/v1/actions/subscription-product/update-product", params);
1037
+ return unwrapAction(
1038
+ await this.http.post("/v1/actions/subscription-product/update-product", params)
1039
+ );
1002
1040
  }
1003
1041
  /**
1004
1042
  * Publish a subscription product's test version to production.
@@ -1011,7 +1049,9 @@ var SubscriptionProductsResource = class {
1011
1049
  */
1012
1050
  async publish(params) {
1013
1051
  validateShortId("id", params.id, "PROD");
1014
- return this.http.post("/v1/actions/subscription-product/publish-product", params);
1052
+ return unwrapAction(
1053
+ await this.http.post("/v1/actions/subscription-product/publish-product", params)
1054
+ );
1015
1055
  }
1016
1056
  /**
1017
1057
  * Update a subscription product's status (active/inactive).
@@ -1028,7 +1068,9 @@ var SubscriptionProductsResource = class {
1028
1068
  async updateStatus(params) {
1029
1069
  validateShortId("id", params.id, "PROD");
1030
1070
  validateEnum("status", params.status, ["active", "inactive"]);
1031
- return this.http.post("/v1/actions/subscription-product/update-status", params);
1071
+ return unwrapAction(
1072
+ await this.http.post("/v1/actions/subscription-product/update-status", params)
1073
+ );
1032
1074
  }
1033
1075
  };
1034
1076
 
@@ -1185,7 +1227,7 @@ var WebhooksResource = class {
1185
1227
  validateShortId("storeId", params.storeId, "STO");
1186
1228
  validateRequired("channel", params.channel);
1187
1229
  validateRequired("url", params.url);
1188
- return this.http.post("/v1/actions/store/add-webhook", params);
1230
+ return unwrapAction(await this.http.post("/v1/actions/store/add-webhook", params));
1189
1231
  }
1190
1232
  /**
1191
1233
  * Update an existing webhook (only `url`, `events`, and `secret` are mutable).
@@ -1205,7 +1247,7 @@ var WebhooksResource = class {
1205
1247
  */
1206
1248
  async update(params) {
1207
1249
  validateRequired("id", params.id);
1208
- return this.http.post("/v1/actions/store/update-webhook", params);
1250
+ return unwrapAction(await this.http.post("/v1/actions/store/update-webhook", params));
1209
1251
  }
1210
1252
  /**
1211
1253
  * Hard-delete a webhook. Historical `webhook_deliveries` rows are retained
@@ -1219,7 +1261,7 @@ var WebhooksResource = class {
1219
1261
  */
1220
1262
  async remove(params) {
1221
1263
  validateRequired("id", params.id);
1222
- return this.http.post("/v1/actions/store/remove-webhook", params);
1264
+ return unwrapAction(await this.http.post("/v1/actions/store/remove-webhook", params));
1223
1265
  }
1224
1266
  /**
1225
1267
  * Verify and parse an incoming webhook event.