@managesales/storefront 1.1.0 → 1.2.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
@@ -3,6 +3,35 @@
3
3
  All notable changes to `@managesales/storefront`. This project adheres to
4
4
  [Semantic Versioning](https://semver.org).
5
5
 
6
+ ## 1.2.0 — 2026-07-21
7
+
8
+ ### Added
9
+ - **`discounts` namespace** — `client.discounts.validate(code, { subtotal | items, customerId? })`
10
+ previews a discount code against a cart *before* creating a checkout session. Returns
11
+ `{ valid: true, discountId, code, label, amount, freeShipping }` or
12
+ `{ valid: false, reason }` with a customer-safe explanation — no try/catch needed for
13
+ "invalid code" UI states. Validation never consumes coupon usage.
14
+ - **`client.discounts.automatic()`** — lists the store's active automatic promotions
15
+ (`AutomaticPromotion[]`: title, type, value, minimums, end date) for display, e.g. promo
16
+ banners. Coupon codes are never exposed by this endpoint.
17
+ - **`checkout.applyGiftCard(checkoutId, code)`** — applies a gift card to an open checkout
18
+ session (the backend endpoint existed; the SDK now exposes it).
19
+ - **`couponCode` option at checkout creation** — `checkout.create(items, { couponCode })` and
20
+ `cart.checkout({ couponCode })` apply the code server-side in the same round-trip as session
21
+ creation.
22
+
23
+ ### Fixed
24
+ - **`checkout.applyCoupon` sent the wrong field name and always failed.** The request body was
25
+ `{ couponCode }`, but the API accepts `{ code }` and rejects unknown fields — every
26
+ `applyCoupon` call returned a 400. It now sends `{ code }`.
27
+ - **`CheckoutSession` type now matches the actual API response.** The session's real fields are
28
+ `lines`, `discountAmount`, `discountCode`, `discountLabel`, `taxAmount`, `shippingAmount`,
29
+ `giftCardAmount`, `availableShippingMethods`, etc. The previously-declared `items`, `tax`,
30
+ `discount`, and `couponCode` members were never populated at runtime; they remain as optional
31
+ `@deprecated` aliases so existing code still compiles. `shipping` was previously typed as a
32
+ number but is actually the shipping *address object* on the wire — it is now typed correctly
33
+ (`CheckoutShippingAddress`).
34
+
6
35
  ## 1.1.0 — 2026-07-11
7
36
 
8
37
  ### Added
package/README.md CHANGED
@@ -80,10 +80,15 @@ client.products.search(query, params?) // full-text search
80
80
  client.collections.list(params?)
81
81
  client.collections.get(idOrSlug) // collection + its products
82
82
 
83
+ // Discounts (public)
84
+ client.discounts.validate(code, { subtotal | items }) // preview a code before checkout
85
+ client.discounts.automatic() // active automatic promotions (for banners)
86
+
83
87
  // Cart & checkout (public)
84
- client.checkout.create(lineItems) // start a checkout from line items
88
+ client.checkout.create(lineItems, { couponCode? }) // start a checkout from line items
85
89
  client.checkout.get(checkoutId)
86
90
  client.checkout.applyCoupon(checkoutId, code)
91
+ client.checkout.applyGiftCard(checkoutId, code)
87
92
  client.checkout.complete(checkoutId, payment?)
88
93
  client.cart.create() / client.cart.current() // stateful cart — see Stateful cart
89
94
  client.cart.recover(token) // rebuild a checkout from a recovery link
@@ -161,26 +166,56 @@ const summer = await client.collections.get("summer-sale");
161
166
  console.log(summer.name, summer.products.length); // collection + its products
162
167
  ```
163
168
 
169
+ ## Discounts
170
+
171
+ Preview a discount code against the customer's cart **before** creating a checkout session — ideal
172
+ for a "promo code" field with instant feedback. Validation never consumes the coupon's usage:
173
+
174
+ ```ts
175
+ const check = await client.discounts.validate("SAVE10", { subtotal: 68 });
176
+ // or derive the subtotal from line items:
177
+ // await client.discounts.validate("SAVE10", { items: [{ quantity: 2, unitPrice: 24.99 }] });
178
+
179
+ if (check.valid) {
180
+ console.log(`${check.label} — saves ${check.amount}`); // "Summer Sale (SAVE10) — saves 6.80"
181
+ } else {
182
+ console.log(check.reason); // customer-safe, e.g. "Minimum order amount of 50 required"
183
+ }
184
+ ```
185
+
186
+ Show the store's running automatic promotions (no code needed to redeem — great for banners):
187
+
188
+ ```ts
189
+ const promos = await client.discounts.automatic();
190
+ // [{ id, title: "Free shipping over $100", type: "free_shipping", value: 0, minOrderAmount: 100, ... }]
191
+ ```
192
+
164
193
  ## Cart & checkout
165
194
 
166
- Assemble line items in your UI, create a checkout session, optionally apply a coupon, then complete
167
- it:
195
+ Assemble line items in your UI, create a checkout session, optionally apply a coupon or gift card,
196
+ then complete it:
168
197
 
169
198
  ```ts
170
- // 1. Create a checkout from line items
171
- const session = await client.checkout.create([
172
- { productId: "prod_123", variantId: "var_456", productName: "Blue T-Shirt", quantity: 2, unitPrice: 24.99 },
173
- { productId: "prod_789", productName: "Canvas Tote", quantity: 1, unitPrice: 18 },
174
- ]);
199
+ // 1. Create a checkout from line items — optionally applying a coupon in the same call
200
+ const session = await client.checkout.create(
201
+ [
202
+ { productId: "prod_123", variantId: "var_456", productName: "Blue T-Shirt", quantity: 2, unitPrice: 24.99 },
203
+ { productId: "prod_789", productName: "Canvas Tote", quantity: 1, unitPrice: 18 },
204
+ ],
205
+ { couponCode: "SAVE10" },
206
+ );
175
207
 
176
208
  // 2. Re-fetch a session (e.g. after a reload)
177
209
  const current = await client.checkout.get(session.id);
178
210
 
179
- // 3. Apply a coupon
211
+ // 3. Apply (or change) a coupon on an open session
180
212
  const discounted = await client.checkout.applyCoupon(session.id, "SAVE10");
181
- console.log(discounted.discount, discounted.total);
213
+ console.log(discounted.discountAmount, discounted.total);
214
+
215
+ // 4. Apply a gift card
216
+ const withGiftCard = await client.checkout.applyGiftCard(session.id, "GC-XXXX-XXXX");
182
217
 
183
- // 4. Complete the purchase
218
+ // 5. Complete the purchase
184
219
  const order = await client.checkout.complete(session.id, {
185
220
  paymentMethod: "card",
186
221
  token: "tok_visa_xxx",
@@ -221,9 +256,9 @@ cart.updateLineItem(cart.lines[0].id, 5); // set a line's quantity (quantity <=
221
256
  cart.removeLineItem(cart.lines[0].id);
222
257
  cart.clear();
223
258
 
224
- // Turn the cart directly into a checkout session
225
- const session = await cart.checkout({ clearOnSuccess: true });
226
- console.log(session.id, session.total);
259
+ // Turn the cart directly into a checkout session — optionally with a coupon
260
+ const session = await cart.checkout({ clearOnSuccess: true, couponCode: "SAVE10" });
261
+ console.log(session.id, session.discountAmount, session.total);
227
262
  ```
228
263
 
229
264
  By default the cart is persisted to `localStorage` under a per-workspace key, so `client.cart.current()`
package/dist/index.cjs CHANGED
@@ -152,10 +152,22 @@ function createStorefrontClient(config) {
152
152
  return request("GET", `/storefront-api/collections/${idOrSlug}`);
153
153
  }
154
154
  };
155
+ const discounts = {
156
+ /** Preview a discount code against a cart before checkout. Never consumes usage. */
157
+ async validate(code, input) {
158
+ return request("POST", "/storefront-api/discounts/validate", { body: { code, ...input || {} } });
159
+ },
160
+ /** Active automatic promotions for display (codes are never exposed) */
161
+ async automatic() {
162
+ return request("GET", "/storefront-api/discounts/automatic");
163
+ }
164
+ };
155
165
  const checkout = {
156
166
  /** Create a checkout session from cart items */
157
- async create(items) {
158
- return request("POST", "/checkout", { body: { lines: items } });
167
+ async create(items, opts) {
168
+ const body = { lines: items };
169
+ if (opts && opts.couponCode) body.couponCode = opts.couponCode;
170
+ return request("POST", "/checkout", { body });
159
171
  },
160
172
  /** Retrieve an existing checkout session */
161
173
  async get(checkoutId) {
@@ -163,7 +175,11 @@ function createStorefrontClient(config) {
163
175
  },
164
176
  /** Apply a coupon or discount code */
165
177
  async applyCoupon(checkoutId, couponCode) {
166
- return request("POST", `/checkout/${checkoutId}/coupon`, { body: { couponCode } });
178
+ return request("POST", `/checkout/${checkoutId}/coupon`, { body: { code: couponCode } });
179
+ },
180
+ /** Apply a gift card to the checkout */
181
+ async applyGiftCard(checkoutId, code) {
182
+ return request("POST", `/checkout/${checkoutId}/gift-card`, { body: { code } });
167
183
  },
168
184
  /** Complete checkout — process payment and create order */
169
185
  async complete(checkoutId, payment) {
@@ -394,7 +410,8 @@ function createStorefrontClient(config) {
394
410
  quantity: l.quantity,
395
411
  unitPrice: l.unitPrice,
396
412
  imageUrl: l.imageUrl
397
- }))
413
+ })),
414
+ opts && opts.couponCode ? { couponCode: opts.couponCode } : void 0
398
415
  );
399
416
  if (opts && opts.clearOnSuccess) cartObj.clear();
400
417
  return session;
@@ -437,6 +454,7 @@ function createStorefrontClient(config) {
437
454
  store,
438
455
  products,
439
456
  collections,
457
+ discounts,
440
458
  checkout,
441
459
  auth,
442
460
  customer,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;AAqSO,IAAM,eAAA,GAAN,cAA8B,KAAA,CAAM;AAAA,EAKzC,WAAA,CAAY,MAAA,EAAgB,IAAA,EAAc,OAAA,EAAiB,OAAA,EAAmB;AAC5E,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AACF;AAIO,SAAS,uBAAuB,MAAA,EAA0B;AAC/D,EAAA,MAAM,UAAU,MAAA,CAAO,MAAA,IAAU,8DAAA,EAAgE,OAAA,CAAQ,OAAO,EAAE,CAAA;AAClH,EAAA,MAAM,UAAU,MAAA,CAAO,WAAA,IAAe,UAAA,CAAW,KAAA,CAAM,KAAK,UAAU,CAAA;AACtE,EAAA,IAAI,WAAA,GAA6B,IAAA;AACjC,EAAA,IAAI,YAAA,GAA8B,IAAA;AAIlC,EAAA,MAAM,cAAA,GAAiB;AAAA,IACrB,OAAA,EAAS,CAAA;AAAA,IACT,WAAA,EAAa,GAAA;AAAA,IACb,UAAA,EAAY,GAAA;AAAA,IACZ,aAAA,EAAe,CAAC,GAAA,EAAK,GAAA,EAAK,KAAK,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG;AAAA,GACnD;AACA,EAAA,MAAM,KACJ,MAAA,CAAO,KAAA,KAAU,KAAA,GACb,EAAE,GAAG,cAAA,EAAgB,OAAA,EAAS,CAAA,EAAE,GAChC,EAAE,GAAG,cAAA,EAAgB,GAAI,MAAA,CAAO,KAAA,IAAS,EAAC,EAAG;AACnD,EAAA,MAAM,6BAAa,IAAI,GAAA,CAAI,CAAC,KAAA,EAAO,MAAM,CAAC,CAAA;AAC1C,EAAA,MAAM,KAAA,GAAQ,CAAC,EAAA,KAAe,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AACpF,EAAA,SAAS,QAAQ,OAAA,EAAyB;AACxC,IAAA,OAAO,KAAK,GAAA,CAAI,EAAA,CAAG,UAAA,EAAY,IAAA,CAAK,MAAM,IAAA,CAAK,MAAA,EAAO,GAAI,EAAA,CAAG,cAAc,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAO,CAAC,CAAC,CAAA;AAAA,EAClG;AAIA,EAAA,eAAe,OAAA,CACb,MAAA,EACA,IAAA,EACA,OAAA,EAKY;AACZ,IAAA,MAAM,MAAM,IAAI,GAAA,CAAI,GAAG,MAAM,CAAA,EAAG,IAAI,CAAA,CAAE,CAAA;AACtC,IAAA,IAAI,SAAS,MAAA,EAAQ;AACnB,MAAA,KAAA,MAAW,CAAC,GAAG,CAAC,CAAA,IAAK,OAAO,OAAA,CAAQ,OAAA,CAAQ,MAAM,CAAA,EAAG;AACnD,QAAA,IAAI,CAAA,KAAM,MAAA,IAAa,CAAA,KAAM,IAAA,EAAM,GAAA,CAAI,aAAa,GAAA,CAAI,CAAA,EAAG,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,MACtE;AAAA,IACF;AAEA,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,kBAAkB,MAAA,CAAO;AAAA,KAC3B;AAEA,IAAA,IAAI,OAAA,EAAS,QAAQ,WAAA,EAAa;AAChC,MAAA,OAAA,CAAQ,eAAe,CAAA,GAAI,CAAA,OAAA,EAAU,WAAW,CAAA,CAAA;AAAA,IAClD;AAEA,IAAA,IAAI,SAAS,IAAA,EAAM;AACjB,MAAA,OAAA,CAAQ,cAAc,CAAA,GAAI,kBAAA;AAAA,IAC5B;AAEA,IAAA,MAAM,YAAA,GAA4B;AAAA,MAChC,MAAA;AAAA,MACA,OAAA;AAAA,MACA,MAAM,OAAA,EAAS,IAAA,GAAO,KAAK,SAAA,CAAU,OAAA,CAAQ,IAAI,CAAA,GAAI;AAAA,KACvD;AAEA,IAAA,IAAI,OAAA,GAAU,CAAA;AACd,IAAA,IAAI,GAAA;AACJ,IAAA,OAAO,IAAA,EAAM;AACX,MAAA,IAAI;AACF,QAAA,GAAA,GAAM,MAAM,OAAA,CAAQ,GAAA,CAAI,QAAA,IAAY,YAAY,CAAA;AAAA,MAClD,SAAS,GAAA,EAAK;AACZ,QAAA,IAAI,OAAA,GAAU,GAAG,OAAA,EAAS;AACxB,UAAA,MAAM,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAC,CAAA;AAC5B,UAAA,OAAA,EAAA;AACA,UAAA;AAAA,QACF;AACA,QAAA,MAAM,GAAA;AAAA,MACR;AACA,MAAA,IAAI,OAAA,GAAU,EAAA,CAAG,OAAA,IAAW,EAAA,CAAG,aAAA,CAAc,QAAA,CAAS,GAAA,CAAI,MAAM,CAAA,IAAK,UAAA,CAAW,GAAA,CAAI,MAAM,CAAA,EAAG;AAC3F,QAAA,MAAM,KAAK,MAAA,CAAO,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,aAAa,CAAC,CAAA;AAChD,QAAA,MAAM,KAAA,CAAM,MAAA,CAAO,QAAA,CAAS,EAAE,CAAA,IAAK,EAAA,GAAK,CAAA,GAAI,EAAA,GAAK,GAAA,GAAO,OAAA,CAAQ,OAAO,CAAC,CAAA;AACxE,QAAA,OAAA,EAAA;AACA,QAAA;AAAA,MACF;AACA,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,GAAA,CAAI,MAAA,KAAW,GAAA,IAAO,OAAA,EAAS,QAAQ,YAAA,EAAc;AACvD,MAAA,MAAM,SAAA,GAAY,MAAM,cAAA,EAAe;AACvC,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,OAAA,CAAQ,eAAe,CAAA,GAAI,CAAA,OAAA,EAAU,WAAW,CAAA,CAAA;AAChD,QAAA,MAAM,KAAA,GAAQ,MAAM,OAAA,CAAQ,GAAA,CAAI,UAAS,EAAG;AAAA,UAC1C,MAAA;AAAA,UACA,OAAA;AAAA,UACA,MAAM,OAAA,EAAS,IAAA,GAAO,KAAK,SAAA,CAAU,OAAA,CAAQ,IAAI,CAAA,GAAI;AAAA,SACtD,CAAA;AACD,QAAA,IAAI,CAAC,KAAA,CAAM,EAAA,EAAI,MAAM,MAAM,WAAW,KAAK,CAAA;AAC3C,QAAA,OAAO,KAAA,CAAM,MAAA,KAAW,GAAA,GAAO,MAAA,GAAkB,MAAM,IAAA,EAAK;AAAA,MAC9D;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,GAAA,CAAI,EAAA,EAAI,MAAM,MAAM,WAAW,GAAG,CAAA;AACvC,IAAA,OAAO,GAAA,CAAI,MAAA,KAAW,GAAA,GAAO,MAAA,GAAkB,IAAI,IAAA,EAAK;AAAA,EAC1D;AAEA,EAAA,eAAe,WAAW,GAAA,EAAyC;AACjE,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,MAAA,OAAO,IAAI,eAAA;AAAA,QACT,GAAA,CAAI,MAAA;AAAA,QACJ,IAAA,CAAK,IAAA,IAAQ,IAAA,CAAK,KAAA,IAAS,SAAA;AAAA,QAC3B,IAAA,CAAK,WAAW,GAAA,CAAI,UAAA;AAAA,QACpB;AAAA,OACF;AAAA,IACF,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,IAAI,eAAA,CAAgB,GAAA,CAAI,MAAA,EAAQ,SAAA,EAAW,IAAI,UAAU,CAAA;AAAA,IAClE;AAAA,EACF;AAEA,EAAA,eAAe,cAAA,GAAmC;AAChD,IAAA,IAAI,CAAC,cAAc,OAAO,KAAA;AAC1B,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,MAAM,OAAA,CAAQ,CAAA,EAAG,MAAM,CAAA,wBAAA,CAAA,EAA4B;AAAA,QAC7D,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS;AAAA,UACP,cAAA,EAAgB,kBAAA;AAAA,UAChB,kBAAkB,MAAA,CAAO;AAAA,SAC3B;AAAA,QACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,cAAc;AAAA,OACtC,CAAA;AACD,MAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,QAAA,WAAA,GAAc,IAAA;AACd,QAAA,YAAA,GAAe,IAAA;AACf,QAAA,OAAO,KAAA;AAAA,MACT;AACA,MAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,MAAA,WAAA,GAAc,IAAA,CAAK,WAAA;AACnB,MAAA,YAAA,GAAe,IAAA,CAAK,YAAA;AACpB,MAAA,OAAO,IAAA;AAAA,IACT,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAIA,EAAA,MAAM,KAAA,GAAQ;AAAA;AAAA,IAEZ,MAAM,OAAA,GAAgC;AACpC,MAAA,OAAO,OAAA,CAAQ,OAAO,yBAAyB,CAAA;AAAA,IACjD;AAAA,GACF;AAEA,EAAA,MAAM,QAAA,GAAW;AAAA;AAAA,IAEf,MAAM,KAAK,MAAA,EAA0D;AACnE,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,0BAAA,EAA4B,EAAE,QAAQ,CAAA;AAAA,IAC9D,CAAA;AAAA;AAAA,IAEA,MAAM,IAAI,QAAA,EAAoC;AAC5C,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,CAAA,yBAAA,EAA4B,QAAQ,CAAA,CAAE,CAAA;AAAA,IAC9D,CAAA;AAAA;AAAA,IAEA,MAAM,MAAA,CAAO,KAAA,EAAe,MAAA,EAA0D;AACpF,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,wBAAA,EAA0B,EAAE,MAAA,EAAQ,EAAE,GAAG,MAAA,EAAQ,CAAA,EAAG,KAAA,EAAM,EAAG,CAAA;AAAA,IACrF;AAAA,GACF;AAEA,EAAA,MAAM,WAAA,GAAc;AAAA;AAAA,IAElB,MAAM,KAAK,MAAA,EAA6D;AACtE,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,6BAAA,EAA+B,EAAE,QAAQ,CAAA;AAAA,IACjE,CAAA;AAAA;AAAA,IAEA,MAAM,IAAI,QAAA,EAAiE;AACzE,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,CAAA,4BAAA,EAA+B,QAAQ,CAAA,CAAE,CAAA;AAAA,IACjE;AAAA,GACF;AAEA,EAAA,MAAM,QAAA,GAAW;AAAA;AAAA,IAEf,MAAM,OAAO,KAAA,EAAqD;AAChE,MAAA,OAAO,OAAA,CAAQ,QAAQ,WAAA,EAAa,EAAE,MAAM,EAAE,KAAA,EAAO,KAAA,EAAM,EAAG,CAAA;AAAA,IAChE,CAAA;AAAA;AAAA,IAEA,MAAM,IAAI,UAAA,EAA8C;AACtD,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,CAAA,UAAA,EAAa,UAAU,CAAA,CAAE,CAAA;AAAA,IACjD,CAAA;AAAA;AAAA,IAEA,MAAM,WAAA,CAAY,UAAA,EAAoB,UAAA,EAA8C;AAClF,MAAA,OAAO,OAAA,CAAQ,MAAA,EAAQ,CAAA,UAAA,EAAa,UAAU,CAAA,OAAA,CAAA,EAAW,EAAE,IAAA,EAAM,EAAE,UAAA,EAAW,EAAG,CAAA;AAAA,IACnF,CAAA;AAAA;AAAA,IAEA,MAAM,QAAA,CAAS,UAAA,EAAoB,OAAA,EAAmD;AACpF,MAAA,OAAO,OAAA,CAAQ,QAAQ,CAAA,UAAA,EAAa,UAAU,aAAa,EAAE,IAAA,EAAM,SAAS,CAAA;AAAA,IAC9E;AAAA,GACF;AAEA,EAAA,MAAM,IAAA,GAAO;AAAA;AAAA,IAEX,MAAM,SAAS,IAAA,EAKU;AACvB,MAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAqB,MAAA,EAAQ,6BAA6B,EAAE,IAAA,EAAM,MAAM,CAAA;AAC9F,MAAA,WAAA,GAAc,OAAA,CAAQ,WAAA;AACtB,MAAA,YAAA,GAAe,OAAA,CAAQ,YAAA;AACvB,MAAA,OAAO,OAAA;AAAA,IACT,CAAA;AAAA;AAAA,IAEA,MAAM,KAAA,CAAM,KAAA,EAAe,QAAA,EAAwC;AACjE,MAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAqB,MAAA,EAAQ,wBAAA,EAA0B;AAAA,QAC3E,IAAA,EAAM,EAAE,KAAA,EAAO,QAAA;AAAS,OACzB,CAAA;AACD,MAAA,WAAA,GAAc,OAAA,CAAQ,WAAA;AACtB,MAAA,YAAA,GAAe,OAAA,CAAQ,YAAA;AACvB,MAAA,OAAO,OAAA;AAAA,IACT,CAAA;AAAA;AAAA,IAEA,MAAM,gBAAgB,OAAA,EAAuC;AAC3D,MAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAqB,MAAA,EAAQ,yBAAA,EAA2B;AAAA,QAC5E,IAAA,EAAM,EAAE,OAAA;AAAQ,OACjB,CAAA;AACD,MAAA,WAAA,GAAc,OAAA,CAAQ,WAAA;AACtB,MAAA,YAAA,GAAe,OAAA,CAAQ,YAAA;AACvB,MAAA,OAAO,OAAA;AAAA,IACT,CAAA;AAAA;AAAA,IAEA,MAAM,MAAA,GAAwB;AAC5B,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,IAAI;AACF,UAAA,MAAM,QAAQ,MAAA,EAAQ,yBAAA,EAA2B,EAAE,IAAA,EAAM,MAAM,CAAA;AAAA,QACjE,CAAA,CAAA,MAAQ;AAAA,QAA6B;AAAA,MACvC;AACA,MAAA,WAAA,GAAc,IAAA;AACd,MAAA,YAAA,GAAe,IAAA;AAAA,IACjB,CAAA;AAAA;AAAA,IAEA,MAAM,OAAA,GAA4B;AAChC,MAAA,OAAO,cAAA,EAAe;AAAA,IACxB,CAAA;AAAA;AAAA,IAEA,eAAA,GAA2B;AACzB,MAAA,OAAO,WAAA,KAAgB,IAAA;AAAA,IACzB,CAAA;AAAA;AAAA,IAEA,SAAA,CAAU,QAAgB,OAAA,EAAuB;AAC/C,MAAA,WAAA,GAAc,MAAA;AACd,MAAA,YAAA,GAAe,OAAA;AAAA,IACjB;AAAA,GACF;AAEA,EAAA,MAAM,QAAA,GAAW;AAAA;AAAA,IAEf,MAAM,EAAA,GAAwB;AAC5B,MAAA,OAAO,QAAQ,KAAA,EAAO,qBAAA,EAAuB,EAAE,IAAA,EAAM,MAAM,CAAA;AAAA,IAC7D,CAAA;AAAA;AAAA,IAEA,MAAM,OAAO,MAAA,EAAwD;AACnE,MAAA,MAAM,EAAA,GAAK,MAAM,OAAA,CAAkB,KAAA,EAAO,uBAAuB,EAAE,IAAA,EAAM,MAAM,CAAA;AAC/E,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,CAAA,yBAAA,EAA4B,EAAA,CAAG,EAAE,WAAW,EAAE,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAM,CAAA;AAAA,IAC1F,CAAA;AAAA;AAAA,IAEA,MAAM,SAAA,GAAgC;AACpC,MAAA,MAAM,EAAA,GAAK,MAAM,OAAA,CAAkB,KAAA,EAAO,uBAAuB,EAAE,IAAA,EAAM,MAAM,CAAA;AAC/E,MAAA,OAAO,OAAA,CAAQ,OAAO,CAAA,yBAAA,EAA4B,EAAA,CAAG,EAAE,CAAA,UAAA,CAAA,EAAc,EAAE,IAAA,EAAM,IAAA,EAAM,CAAA;AAAA,IACrF;AAAA,GACF;AAEA,EAAA,MAAM,IAAA,GAAO;AAAA;AAAA,IAEX,MAAM,KAAK,MAAA,EAA+E;AACxF,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,4BAAA,EAA8B,EAAE,QAAQ,CAAA;AAAA,IAChE,CAAA;AAAA;AAAA,IAEA,MAAM,IAAI,IAAA,EAAiC;AACzC,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,CAAA,2BAAA,EAA8B,IAAI,CAAA,CAAE,CAAA;AAAA,IAC5D;AAAA,GACF;AAEA,EAAA,MAAM,QAAA,GAAW;AAAA;AAAA,IAEf,MAAM,QAAA,GAAuC;AAC3C,MAAA,OAAO,OAAA,CAAQ,OAAO,2BAA2B,CAAA;AAAA,IACnD,CAAA;AAAA;AAAA,IAEA,MAAM,KAAA,GAAuE;AAC3E,MAAA,OAAO,OAAA,CAAQ,OAAO,wBAAwB,CAAA;AAAA,IAChD,CAAA;AAAA;AAAA,IAEA,MAAM,aAAa,MAAA,EAIK;AACtB,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,+BAAA,EAAiC,EAAE,QAAQ,CAAA;AAAA,IACnE,CAAA;AAAA;AAAA,IAEA,MAAM,KAAK,IAAA,EAMU;AACnB,MAAA,OAAO,QAAQ,MAAA,EAAQ,uBAAA,EAAyB,EAAE,IAAA,EAAM,MAAM,CAAA;AAAA,IAChE;AAAA,GACF;AAEA,EAAA,MAAM,KAAA,GAAQ;AAAA;AAAA,IAEZ,MAAM,IAAI,QAAA,EAA2C;AACnD,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,CAAA,cAAA,EAAiB,QAAQ,CAAA,CAAE,CAAA;AAAA,IACnD,CAAA;AAAA;AAAA,IAEA,MAAM,MAAA,CAAO,MAAA,EAAgB,IAAA,EAAwD;AACnF,MAAA,OAAO,OAAA,CAAQ,QAAQ,CAAA,cAAA,EAAiB,MAAM,WAAW,EAAE,IAAA,EAAM,MAAM,CAAA;AAAA,IACzE,CAAA;AAAA;AAAA,IAEA,MAAM,UAAA,CAAW,MAAA,EAAgB,IAAA,EAAsC;AACrE,MAAA,MAAM,QAAA,GAAW,IAAI,QAAA,EAAS;AAC9B,MAAA,QAAA,CAAS,MAAA,CAAO,QAAQ,IAAI,CAAA;AAC5B,MAAA,MAAM,MAAM,MAAM,OAAA,CAAQ,GAAG,MAAM,CAAA,cAAA,EAAiB,MAAM,CAAA,OAAA,CAAA,EAAW;AAAA,QACnE,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS,EAAE,gBAAA,EAAkB,MAAA,CAAO,WAAA,EAAY;AAAA,QAChD,IAAA,EAAM;AAAA,OACP,CAAA;AACD,MAAA,IAAI,CAAC,GAAA,CAAI,EAAA,EAAI,MAAM,MAAM,WAAW,GAAG,CAAA;AACvC,MAAA,OAAO,IAAI,IAAA,EAAK;AAAA,IAClB;AAAA,GACF;AAIA,EAAA,MAAM,QAAA,GAAW,sBAAsB,MAAA,CAAO,WAAA;AAC9C,EAAA,MAAM,QAAQ,MAAM;AAClB,IAAA,IAAI;AACF,MAAA,OAAO,MAAA,CAAO,WAAA,KAAgB,KAAA,IAAS,OAAO,YAAA,KAAiB,WAAA;AAAA,IACjE,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF,CAAA;AACA,EAAA,MAAM,WAAW,MAAwB;AACvC,IAAA,IAAI,CAAC,KAAA,EAAM,EAAG,OAAO,IAAA;AACrB,IAAA,IAAI;AACF,MAAA,MAAM,CAAA,GAAI,YAAA,CAAa,OAAA,CAAQ,QAAQ,CAAA;AACvC,MAAA,OAAO,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,GAAI,IAAA;AAAA,IAC7B,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF,CAAA;AACA,EAAA,MAAM,QAAA,GAAW,CAAC,EAAA,KAAwB;AACxC,IAAA,IAAI,CAAC,OAAM,EAAG;AACd,IAAA,IAAI;AACF,MAAA,YAAA,CAAa,OAAA,CAAQ,QAAA,EAAU,IAAA,CAAK,SAAA,CAAU,EAAE,CAAC,CAAA;AAAA,IACnD,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF,CAAA;AACA,EAAA,IAAI,SAAA,GAAY,CAAA;AAChB,EAAA,MAAM,QAAQ,CAAC,CAAA,KACb,OAAO,MAAA,KAAW,eAAe,MAAA,CAAO,UAAA,GAAa,CAAA,GAAI,MAAA,CAAO,YAAW,GAAI,CAAA,GAAI,KAAK,GAAA,EAAI,GAAI,MAAM,EAAE,SAAA;AAC1G,EAAA,MAAM,MAAA,GAAS,MAAA,iBAAc,IAAI,IAAA,IAAO,WAAA,EAAY;AACpD,EAAA,MAAM,SAAA,GAAY,OAAkB,EAAE,EAAA,EAAI,MAAM,OAAO,CAAA,EAAG,KAAA,EAAO,IAAI,SAAA,EAAW,MAAA,EAAO,EAAG,SAAA,EAAW,QAAO,EAAE,CAAA;AAE9G,EAAA,SAAS,SAAS,KAAA,EAAkC;AAClD,IAAA,MAAM,UAAU,MAAM;AACpB,MAAA,KAAA,CAAM,YAAY,MAAA,EAAO;AACzB,MAAA,QAAA,CAAS,KAAK,CAAA;AAAA,IAChB,CAAA;AACA,IAAA,MAAM,OAAA,GAA0B;AAAA,MAC9B,IAAI,EAAA,GAAK;AACP,QAAA,OAAO,KAAA,CAAM,EAAA;AAAA,MACf,CAAA;AAAA,MACA,IAAI,KAAA,GAAQ;AACV,QAAA,OAAO,KAAA,CAAM,KAAA;AAAA,MACf,CAAA;AAAA,MACA,IAAI,SAAA,GAAY;AACd,QAAA,OAAO,KAAA,CAAM,MAAM,MAAA,CAAO,CAAC,GAAG,CAAA,KAAM,CAAA,GAAI,CAAA,CAAE,QAAA,EAAU,CAAC,CAAA;AAAA,MACvD,CAAA;AAAA,MACA,IAAI,QAAA,GAAW;AACb,QAAA,OAAO,KAAA,CAAM,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,CAAA,CAAE,SAAA,GAAY,CAAA,CAAE,QAAA,EAAU,CAAC,CAAA;AAAA,MACrE,CAAA;AAAA;AAAA;AAAA,MAGA,MAAM,YAAY,KAAA,EAAsD;AACtE,QAAA,IAAI,IAAA;AACJ,QAAA,IAAI,KAAA,CAAM,SAAA,IAAa,IAAA,IAAQ,KAAA,CAAM,WAAA,EAAa;AAChD,UAAA,IAAA,GAAO;AAAA,YACL,EAAA,EAAI,MAAM,OAAO,CAAA;AAAA,YACjB,WAAW,KAAA,CAAM,SAAA;AAAA,YACjB,WAAW,KAAA,CAAM,SAAA;AAAA,YACjB,UAAU,KAAA,CAAM,QAAA;AAAA,YAChB,WAAW,KAAA,CAAM,SAAA;AAAA,YACjB,aAAa,KAAA,CAAM,WAAA;AAAA,YACnB,UAAU,KAAA,CAAM;AAAA,WAClB;AAAA,QACF,CAAA,MAAO;AACL,UAAA,MAAM,CAAA,GAAI,MAAM,QAAA,CAAS,GAAA,CAAI,MAAM,SAAS,CAAA;AAC5C,UAAA,MAAM,IAAI,KAAA,CAAM,SAAA,IAAa,KAAA,CAAM,OAAA,CAAQ,EAAE,QAAQ,CAAA,GAAI,CAAA,CAAE,QAAA,CAAS,KAAK,CAAC,CAAA,KAAM,EAAE,EAAA,KAAO,KAAA,CAAM,SAAS,CAAA,GAAI,MAAA;AAC5G,UAAA,IAAA,GAAO;AAAA,YACL,EAAA,EAAI,MAAM,OAAO,CAAA;AAAA,YACjB,WAAW,KAAA,CAAM,SAAA;AAAA,YACjB,WAAW,KAAA,CAAM,SAAA;AAAA,YACjB,UAAU,KAAA,CAAM,QAAA;AAAA,YAChB,WAAW,CAAA,IAAK,CAAA,CAAE,SAAS,IAAA,GAAO,CAAA,CAAE,QAAQ,CAAA,CAAE,KAAA;AAAA,YAC9C,aAAa,CAAA,CAAE,IAAA;AAAA,YACf,QAAA,EAAU,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,MAAM,CAAA,IAAK,CAAA,CAAE,MAAA,CAAO,MAAA,GAAS,CAAA,GAAI,CAAA,CAAE,MAAA,CAAO,CAAC,EAAE,GAAA,GAAM;AAAA,WAC/E;AAAA,QACF;AACA,QAAA,MAAM,QAAA,GAAW,KAAA,CAAM,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,SAAA,KAAc,IAAA,CAAK,SAAA,IAAa,CAAA,CAAE,SAAA,KAAc,KAAK,SAAS,CAAA;AACzG,QAAA,IAAI,QAAA,EAAU,QAAA,CAAS,QAAA,IAAY,IAAA,CAAK,QAAA;AAAA,aACnC,KAAA,CAAM,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA;AAC1B,QAAA,OAAA,EAAQ;AACR,QAAA,OAAO,OAAA;AAAA,MACT,CAAA;AAAA,MACA,cAAA,CAAe,QAAgB,QAAA,EAAkC;AAC/D,QAAA,MAAM,CAAA,GAAI,MAAM,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,MAAM,CAAA;AACjD,QAAA,IAAI,CAAA,EAAG;AACL,UAAA,IAAI,QAAA,IAAY,CAAA,EAAG,KAAA,CAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,MAAM,CAAA;AAAA,iBACnE,QAAA,GAAW,QAAA;AAClB,UAAA,OAAA,EAAQ;AAAA,QACV;AACA,QAAA,OAAO,OAAA;AAAA,MACT,CAAA;AAAA,MACA,eAAe,MAAA,EAAgC;AAC7C,QAAA,KAAA,CAAM,KAAA,GAAQ,MAAM,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,MAAM,CAAA;AACvD,QAAA,OAAA,EAAQ;AACR,QAAA,OAAO,OAAA;AAAA,MACT,CAAA;AAAA,MACA,KAAA,GAAwB;AACtB,QAAA,KAAA,CAAM,QAAQ,EAAC;AACf,QAAA,OAAA,EAAQ;AACR,QAAA,OAAO,OAAA;AAAA,MACT,CAAA;AAAA,MACA,MAAM,SAAS,IAAA,EAA+D;AAC5E,QAAA,MAAM,OAAA,GAAU,MAAM,QAAA,CAAS,MAAA;AAAA,UAC7B,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,YACtB,WAAW,CAAA,CAAE,SAAA;AAAA,YACb,WAAW,CAAA,CAAE,SAAA;AAAA,YACb,aAAa,CAAA,CAAE,WAAA;AAAA,YACf,UAAU,CAAA,CAAE,QAAA;AAAA,YACZ,WAAW,CAAA,CAAE,SAAA;AAAA,YACb,UAAU,CAAA,CAAE;AAAA,WACd,CAAE;AAAA,SACJ;AACA,QAAA,IAAI,IAAA,IAAQ,IAAA,CAAK,cAAA,EAAgB,OAAA,CAAQ,KAAA,EAAM;AAC/C,QAAA,OAAO,OAAA;AAAA,MACT;AAAA,KACF;AACA,IAAA,OAAO,OAAA;AAAA,EACT;AAEA,EAAA,MAAM,IAAA,GAAO;AAAA;AAAA,IAEX,MAAA,GAAyB;AACvB,MAAA,MAAM,KAAK,SAAA,EAAU;AACrB,MAAA,QAAA,CAAS,EAAE,CAAA;AACX,MAAA,OAAO,SAAS,EAAE,CAAA;AAAA,IACpB,CAAA;AAAA;AAAA,IAEA,OAAA,GAA0B;AACxB,MAAA,OAAO,QAAA,CAAS,QAAA,EAAS,IAAK,SAAA,EAAW,CAAA;AAAA,IAC3C,CAAA;AAAA;AAAA,IAEA,MAAM,QAAQ,KAAA,EAAyC;AACrD,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,CAAA,yBAAA,EAA4B,KAAK,CAAA,CAAE,CAAA;AAAA,IAC3D;AAAA,GACF;AAKA,EAAA,MAAM,MAAA,GAAS;AAAA;AAAA,IAEb,IAAA,EAAM,CAAC,MAAA,KAA2D,QAAA,CAAS,OAAO,MAAM;AAAA,GAC1F;AAGA,EAAA,MAAM,SAAA,GAAY;AAAA,IAChB,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,iBAAiB,IAAA,CAAK,eAAA;AAAA,IACtB,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,iBAAiB,IAAA,CAAK,eAAA;AAAA,IACtB,WAAW,IAAA,CAAK,SAAA;AAAA,IAChB,IAAI,QAAA,CAAS,EAAA;AAAA,IACb,QAAQ,QAAA,CAAS,MAAA;AAAA,IACjB,WAAW,QAAA,CAAS;AAAA,GACtB;AAIA,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA;AAAA,IACA,QAAA;AAAA,IACA,IAAA;AAAA,IACA,QAAA;AAAA,IACA,IAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA;AAAA,IACA,IAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF;AACF","file":"index.cjs","sourcesContent":["/**\n * ManageSales Storefront SDK\n * --------------------------\n * Resource-based client for building online storefronts.\n * Works with any framework: Next.js, Remix, Nuxt, Astro, plain HTML.\n *\n * Usage:\n * import { createStorefrontClient } from \"./managesales-storefront\";\n * const client = createStorefrontClient({ workspaceId: \"<workspace_id>\" });\n * const products = await client.products.list();\n */\n\n// ── Types ──────────────────────────────────────────────────────────\n\nexport interface RetryConfig {\n /** Max retry attempts for a failed request (default: 2) */\n retries?: number;\n /** Base delay in ms used for exponential backoff (default: 300) */\n baseDelayMs?: number;\n /** Upper bound for any single backoff delay, in ms (default: 4000) */\n maxDelayMs?: number;\n /** HTTP status codes that are retried, GET/HEAD only (default: [408,425,429,500,502,503,504]) */\n retryOnStatus?: number[];\n}\n\nexport interface StorefrontConfig {\n /** Your workspace ID (required) */\n workspaceId: string;\n /** API base URL — defaults to production */\n apiUrl?: string;\n /** Custom fetch implementation (for SSR / edge) */\n customFetch?: typeof fetch;\n /** Default locale for content */\n locale?: string;\n /**\n * Retry behavior for transient failures (network errors, and 5xx/408/425/429\n * responses on idempotent GET/HEAD requests). Pass `false` to disable retries\n * entirely. Defaults to 2 retries with exponential backoff.\n */\n retry?: RetryConfig | false;\n /**\n * Persist the stateful cart (`client.cart`) to `localStorage` so it survives\n * page reloads. Defaults to `true`. Has no effect in environments without\n * `localStorage` (e.g. Node/SSR) — the cart simply stays in-memory.\n */\n persistCart?: boolean;\n}\n\nexport interface ListParams {\n page?: number;\n limit?: number;\n search?: string;\n sort?: string;\n order?: \"asc\" | \"desc\";\n [key: string]: unknown;\n}\n\nexport interface PaginatedResponse<T> {\n data: T[];\n total: number;\n page: number;\n limit: number;\n totalPages: number;\n}\n\n// ── Product types ──\n\nexport interface Product {\n id: string;\n name: string;\n slug: string;\n description: string;\n status: string;\n price: number;\n compareAtPrice?: number;\n currency: string;\n images: ProductImage[];\n variants: ProductVariant[];\n category?: { id: string; name: string };\n brand?: { id: string; name: string };\n tags: string[];\n metadata: Record<string, unknown>;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface ProductImage {\n id: string;\n url: string;\n alt: string;\n position: number;\n}\n\nexport interface ProductVariant {\n id: string;\n name: string;\n sku: string;\n price: number;\n compareAtPrice?: number;\n inventory: number;\n options: Record<string, string>;\n}\n\n// ── Collection types ──\n\nexport interface Collection {\n id: string;\n name: string;\n slug: string;\n description: string;\n image?: string;\n productCount: number;\n}\n\n// ── Cart & Checkout types ──\n\nexport interface CheckoutLineItem {\n productId: string;\n variantId?: string;\n productName: string;\n quantity: number;\n unitPrice: number;\n imageUrl?: string;\n}\n\nexport interface CheckoutSession {\n id: string;\n status: \"open\" | \"completed\" | \"expired\";\n items: CheckoutLineItem[];\n subtotal: number;\n tax: number;\n shipping: number;\n discount: number;\n total: number;\n currency: string;\n couponCode?: string;\n}\n\nexport interface CartLine {\n id: string;\n productId: string;\n variantId?: string;\n quantity: number;\n unitPrice: number;\n productName: string;\n imageUrl?: string;\n}\n\nexport interface CartState {\n id: string;\n lines: CartLine[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface AddCartLineItemInput {\n productId: string;\n variantId?: string;\n quantity: number;\n /** Skip the `products.get` price lookup by supplying these directly */\n unitPrice?: number;\n productName?: string;\n imageUrl?: string;\n}\n\nexport interface StorefrontCart {\n readonly id: string;\n readonly lines: CartLine[];\n readonly itemCount: number;\n readonly subtotal: number;\n /** Adds a line item. Supplying `unitPrice` also requires `productName`, otherwise this falls through to a `products.get` network lookup. */\n addLineItem(input: AddCartLineItemInput): Promise<StorefrontCart>;\n updateLineItem(lineId: string, quantity: number): StorefrontCart;\n removeLineItem(lineId: string): StorefrontCart;\n clear(): StorefrontCart;\n checkout(opts?: { clearOnSuccess?: boolean }): Promise<CheckoutSession>;\n}\n\nexport interface Order {\n id: string;\n orderNumber: string;\n status: string;\n total: number;\n currency: string;\n items: OrderItem[];\n createdAt: string;\n}\n\nexport interface OrderItem {\n productId: string;\n name: string;\n quantity: number;\n price: number;\n}\n\n// ── Customer types ──\n\nexport interface Customer {\n id: string;\n email: string;\n name: string;\n phone?: string;\n createdAt: string;\n}\n\nexport interface AuthSession {\n customer: Customer;\n accessToken: string;\n refreshToken: string;\n}\n\nexport interface Address {\n id: string;\n label?: string;\n line1: string;\n line2?: string;\n city: string;\n state: string;\n postalCode: string;\n country: string;\n isDefault: boolean;\n}\n\n// ── Blog types ──\n\nexport interface BlogPost {\n id: string;\n title: string;\n slug: string;\n excerpt: string;\n content: string;\n coverImage?: string;\n tags: string[];\n publishedAt: string;\n}\n\n// ── Booking types ──\n\nexport interface BookableService {\n id: string;\n name: string;\n duration: number;\n price: number;\n description: string;\n}\n\nexport interface TimeSlot {\n start: string;\n end: string;\n available: boolean;\n}\n\nexport interface Booking {\n id: string;\n serviceId: string;\n date: string;\n startTime: string;\n endTime: string;\n status: string;\n customer: { name: string; email: string };\n}\n\n// ── Form types ──\n\nexport interface FormDefinition {\n id: string;\n title: string;\n description: string;\n fields: FormField[];\n}\n\nexport interface FormField {\n id: string;\n type: string;\n label: string;\n required: boolean;\n options?: string[];\n placeholder?: string;\n}\n\n// ── Store config ──\n\nexport interface StoreConfig {\n name: string;\n slug: string;\n logo?: string;\n theme: Record<string, unknown>;\n currency: string;\n locale: string;\n}\n\n// ── SDK Error ──\n\nexport class StorefrontError extends Error {\n status: number;\n code: string;\n details?: unknown;\n\n constructor(status: number, code: string, message: string, details?: unknown) {\n super(message);\n this.name = \"StorefrontError\";\n this.status = status;\n this.code = code;\n this.details = details;\n }\n}\n\n// ── Core client ────────────────────────────────────────────────────\n\nexport function createStorefrontClient(config: StorefrontConfig) {\n const apiUrl = (config.apiUrl ?? \"https://managesales-backend-phase1test.up.railway.app/api/v1\").replace(/\\/$/, \"\");\n const fetchFn = config.customFetch ?? globalThis.fetch.bind(globalThis);\n let accessToken: string | null = null;\n let refreshToken: string | null = null;\n\n // ── Retry configuration ──\n\n const RETRY_DEFAULTS = {\n retries: 2,\n baseDelayMs: 300,\n maxDelayMs: 4000,\n retryOnStatus: [408, 425, 429, 500, 502, 503, 504],\n };\n const rc =\n config.retry === false\n ? { ...RETRY_DEFAULTS, retries: 0 }\n : { ...RETRY_DEFAULTS, ...(config.retry || {}) };\n const IDEMPOTENT = new Set([\"GET\", \"HEAD\"]);\n const sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n function backoff(attempt: number): number {\n return Math.min(rc.maxDelayMs, Math.round(Math.random() * rc.baseDelayMs * Math.pow(2, attempt)));\n }\n\n // ── Internal helpers ──\n\n async function request<T>(\n method: string,\n path: string,\n options?: {\n body?: unknown;\n params?: Record<string, unknown>;\n auth?: boolean;\n },\n ): Promise<T> {\n const url = new URL(`${apiUrl}${path}`);\n if (options?.params) {\n for (const [k, v] of Object.entries(options.params)) {\n if (v !== undefined && v !== null) url.searchParams.set(k, String(v));\n }\n }\n\n const headers: Record<string, string> = {\n \"X-Workspace-Id\": config.workspaceId,\n };\n\n if (options?.auth && accessToken) {\n headers[\"Authorization\"] = `Bearer ${accessToken}`;\n }\n\n if (options?.body) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const fetchOptions: RequestInit = {\n method,\n headers,\n body: options?.body ? JSON.stringify(options.body) : undefined,\n };\n\n let attempt = 0;\n let res: Response;\n while (true) {\n try {\n res = await fetchFn(url.toString(), fetchOptions);\n } catch (err) {\n if (attempt < rc.retries) {\n await sleep(backoff(attempt));\n attempt++;\n continue;\n }\n throw err;\n }\n if (attempt < rc.retries && rc.retryOnStatus.includes(res.status) && IDEMPOTENT.has(method)) {\n const ra = Number(res.headers.get(\"retry-after\"));\n await sleep(Number.isFinite(ra) && ra > 0 ? ra * 1000 : backoff(attempt));\n attempt++;\n continue;\n }\n break;\n }\n\n // Auto-refresh on 401\n if (res.status === 401 && options?.auth && refreshToken) {\n const refreshed = await refreshSession();\n if (refreshed) {\n headers[\"Authorization\"] = `Bearer ${accessToken}`;\n const retry = await fetchFn(url.toString(), {\n method,\n headers,\n body: options?.body ? JSON.stringify(options.body) : undefined,\n });\n if (!retry.ok) throw await parseError(retry);\n return retry.status === 204 ? (undefined as T) : retry.json();\n }\n }\n\n if (!res.ok) throw await parseError(res);\n return res.status === 204 ? (undefined as T) : res.json();\n }\n\n async function parseError(res: Response): Promise<StorefrontError> {\n try {\n const body = await res.json();\n return new StorefrontError(\n res.status,\n body.code ?? body.error ?? \"UNKNOWN\",\n body.message ?? res.statusText,\n body,\n );\n } catch {\n return new StorefrontError(res.status, \"UNKNOWN\", res.statusText);\n }\n }\n\n async function refreshSession(): Promise<boolean> {\n if (!refreshToken) return false;\n try {\n const res = await fetchFn(`${apiUrl}/storefront/auth/refresh`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Workspace-Id\": config.workspaceId,\n },\n body: JSON.stringify({ refreshToken }),\n });\n if (!res.ok) {\n accessToken = null;\n refreshToken = null;\n return false;\n }\n const data = await res.json();\n accessToken = data.accessToken;\n refreshToken = data.refreshToken;\n return true;\n } catch {\n return false;\n }\n }\n\n // ── Resource namespaces ──────────────────────────────────────────\n\n const store = {\n /** Resolve store config by workspace (returns theme, branding, currency) */\n async resolve(): Promise<StoreConfig> {\n return request(\"GET\", \"/storefront-api/resolve\");\n },\n };\n\n const products = {\n /** List published products with pagination and filters */\n async list(params?: ListParams): Promise<PaginatedResponse<Product>> {\n return request(\"GET\", \"/storefront-api/products\", { params });\n },\n /** Get a single product by ID or slug */\n async get(idOrSlug: string): Promise<Product> {\n return request(\"GET\", `/storefront-api/products/${idOrSlug}`);\n },\n /** Search products (shorthand for list with search param) */\n async search(query: string, params?: ListParams): Promise<PaginatedResponse<Product>> {\n return request(\"GET\", \"/storefront-api/search\", { params: { ...params, q: query } });\n },\n };\n\n const collections = {\n /** List published collections */\n async list(params?: ListParams): Promise<PaginatedResponse<Collection>> {\n return request(\"GET\", \"/storefront-api/collections\", { params });\n },\n /** Get a collection with its products */\n async get(idOrSlug: string): Promise<Collection & { products: Product[] }> {\n return request(\"GET\", `/storefront-api/collections/${idOrSlug}`);\n },\n };\n\n const checkout = {\n /** Create a checkout session from cart items */\n async create(items: CheckoutLineItem[]): Promise<CheckoutSession> {\n return request(\"POST\", \"/checkout\", { body: { lines: items } });\n },\n /** Retrieve an existing checkout session */\n async get(checkoutId: string): Promise<CheckoutSession> {\n return request(\"GET\", `/checkout/${checkoutId}`);\n },\n /** Apply a coupon or discount code */\n async applyCoupon(checkoutId: string, couponCode: string): Promise<CheckoutSession> {\n return request(\"POST\", `/checkout/${checkoutId}/coupon`, { body: { couponCode } });\n },\n /** Complete checkout — process payment and create order */\n async complete(checkoutId: string, payment?: Record<string, unknown>): Promise<Order> {\n return request(\"POST\", `/checkout/${checkoutId}/complete`, { body: payment });\n },\n };\n\n const auth = {\n /** Register a new customer account */\n async register(data: {\n email: string;\n password: string;\n name: string;\n phone?: string;\n }): Promise<AuthSession> {\n const session = await request<AuthSession>(\"POST\", \"/storefront/auth/register\", { body: data });\n accessToken = session.accessToken;\n refreshToken = session.refreshToken;\n return session;\n },\n /** Log in with email + password */\n async login(email: string, password: string): Promise<AuthSession> {\n const session = await request<AuthSession>(\"POST\", \"/storefront/auth/login\", {\n body: { email, password },\n });\n accessToken = session.accessToken;\n refreshToken = session.refreshToken;\n return session;\n },\n /** Log in with Google ID token */\n async loginWithGoogle(idToken: string): Promise<AuthSession> {\n const session = await request<AuthSession>(\"POST\", \"/storefront/auth/google\", {\n body: { idToken },\n });\n accessToken = session.accessToken;\n refreshToken = session.refreshToken;\n return session;\n },\n /** Log out and clear local session */\n async logout(): Promise<void> {\n if (accessToken) {\n try {\n await request(\"POST\", \"/storefront/auth/logout\", { auth: true });\n } catch { /* ignore logout errors */ }\n }\n accessToken = null;\n refreshToken = null;\n },\n /** Refresh the access token */\n async refresh(): Promise<boolean> {\n return refreshSession();\n },\n /** Check if client has a valid session */\n isAuthenticated(): boolean {\n return accessToken !== null;\n },\n /** Manually set tokens (e.g., from SSR or cookie restoration) */\n setTokens(access: string, refresh: string): void {\n accessToken = access;\n refreshToken = refresh;\n },\n };\n\n const customer = {\n /** Get current customer profile */\n async me(): Promise<Customer> {\n return request(\"GET\", \"/storefront/auth/me\", { auth: true });\n },\n /** Get customer's order history */\n async orders(params?: ListParams): Promise<PaginatedResponse<Order>> {\n const me = await request<Customer>(\"GET\", \"/storefront/auth/me\", { auth: true });\n return request(\"GET\", `/storefront-api/customer/${me.id}/orders`, { params, auth: true });\n },\n /** Get customer's saved addresses */\n async addresses(): Promise<Address[]> {\n const me = await request<Customer>(\"GET\", \"/storefront/auth/me\", { auth: true });\n return request(\"GET\", `/storefront-api/customer/${me.id}/addresses`, { auth: true });\n },\n };\n\n const blog = {\n /** List published blog posts */\n async list(params?: ListParams & { tags?: string }): Promise<PaginatedResponse<BlogPost>> {\n return request(\"GET\", \"/storefront-api/blog/posts\", { params });\n },\n /** Get a blog post by slug */\n async get(slug: string): Promise<BlogPost> {\n return request(\"GET\", `/storefront-api/blog/posts/${slug}`);\n },\n };\n\n const bookings = {\n /** List bookable services */\n async services(): Promise<BookableService[]> {\n return request(\"GET\", \"/bookings-public/services\");\n },\n /** List bookable staff */\n async staff(): Promise<Array<{ id: string; name: string; avatar?: string }>> {\n return request(\"GET\", \"/bookings-public/staff\");\n },\n /** Check available time slots */\n async availability(params: {\n serviceId: string;\n date: string;\n staffId?: string;\n }): Promise<TimeSlot[]> {\n return request(\"GET\", \"/bookings-public/availability\", { params });\n },\n /** Create a booking */\n async book(data: {\n serviceId: string;\n date: string;\n startTime: string;\n staffId?: string;\n customer: { name: string; email: string; phone?: string };\n }): Promise<Booking> {\n return request(\"POST\", \"/bookings-public/book\", { body: data });\n },\n };\n\n const forms = {\n /** Get a published form by ID or slug */\n async get(idOrSlug: string): Promise<FormDefinition> {\n return request(\"GET\", `/public/forms/${idOrSlug}`);\n },\n /** Submit form response */\n async submit(formId: string, data: Record<string, unknown>): Promise<{ id: string }> {\n return request(\"POST\", `/public/forms/${formId}/submit`, { body: data });\n },\n /** Upload file for a form file field */\n async uploadFile(formId: string, file: File): Promise<{ url: string }> {\n const formData = new FormData();\n formData.append(\"file\", file);\n const res = await fetchFn(`${apiUrl}/public/forms/${formId}/upload`, {\n method: \"POST\",\n headers: { \"X-Workspace-Id\": config.workspaceId },\n body: formData,\n });\n if (!res.ok) throw await parseError(res);\n return res.json();\n },\n };\n\n // ── Stateful cart (client-side, localStorage-persisted) ──\n\n const CART_KEY = \"managesales_cart_\" + config.workspaceId;\n const hasLS = () => {\n try {\n return config.persistCart !== false && typeof localStorage !== \"undefined\";\n } catch {\n return false;\n }\n };\n const loadCart = (): CartState | null => {\n if (!hasLS()) return null;\n try {\n const s = localStorage.getItem(CART_KEY);\n return s ? JSON.parse(s) : null;\n } catch {\n return null;\n }\n };\n const saveCart = (st: CartState): void => {\n if (!hasLS()) return;\n try {\n localStorage.setItem(CART_KEY, JSON.stringify(st));\n } catch {\n /* ignore persistence errors (quota, privacy mode, etc.) */\n }\n };\n let __lineSeq = 0;\n const genId = (p: string): string =>\n typeof crypto !== \"undefined\" && crypto.randomUUID ? p + crypto.randomUUID() : p + Date.now() + \"_\" + ++__lineSeq;\n const nowIso = (): string => new Date().toISOString();\n const freshCart = (): CartState => ({ id: genId(\"cart_\"), lines: [], createdAt: nowIso(), updatedAt: nowIso() });\n\n function makeCart(state: CartState): StorefrontCart {\n const persist = () => {\n state.updatedAt = nowIso();\n saveCart(state);\n };\n const cartObj: StorefrontCart = {\n get id() {\n return state.id;\n },\n get lines() {\n return state.lines;\n },\n get itemCount() {\n return state.lines.reduce((n, l) => n + l.quantity, 0);\n },\n get subtotal() {\n return state.lines.reduce((s, l) => s + l.unitPrice * l.quantity, 0);\n },\n // Supplying unitPrice alone does not skip the lookup — productName must also be\n // provided, otherwise this falls through to the products.get() network lookup below.\n async addLineItem(input: AddCartLineItemInput): Promise<StorefrontCart> {\n let line: CartLine;\n if (input.unitPrice != null && input.productName) {\n line = {\n id: genId(\"line_\"),\n productId: input.productId,\n variantId: input.variantId,\n quantity: input.quantity,\n unitPrice: input.unitPrice,\n productName: input.productName,\n imageUrl: input.imageUrl,\n };\n } else {\n const p = await products.get(input.productId);\n const v = input.variantId && Array.isArray(p.variants) ? p.variants.find((x) => x.id === input.variantId) : undefined;\n line = {\n id: genId(\"line_\"),\n productId: input.productId,\n variantId: input.variantId,\n quantity: input.quantity,\n unitPrice: v && v.price != null ? v.price : p.price,\n productName: p.name,\n imageUrl: Array.isArray(p.images) && p.images.length > 0 ? p.images[0].url : undefined,\n };\n }\n const existing = state.lines.find((l) => l.productId === line.productId && l.variantId === line.variantId);\n if (existing) existing.quantity += line.quantity;\n else state.lines.push(line);\n persist();\n return cartObj;\n },\n updateLineItem(lineId: string, quantity: number): StorefrontCart {\n const l = state.lines.find((x) => x.id === lineId);\n if (l) {\n if (quantity <= 0) state.lines = state.lines.filter((x) => x.id !== lineId);\n else l.quantity = quantity;\n persist();\n }\n return cartObj;\n },\n removeLineItem(lineId: string): StorefrontCart {\n state.lines = state.lines.filter((x) => x.id !== lineId);\n persist();\n return cartObj;\n },\n clear(): StorefrontCart {\n state.lines = [];\n persist();\n return cartObj;\n },\n async checkout(opts?: { clearOnSuccess?: boolean }): Promise<CheckoutSession> {\n const session = await checkout.create(\n state.lines.map((l) => ({\n productId: l.productId,\n variantId: l.variantId,\n productName: l.productName,\n quantity: l.quantity,\n unitPrice: l.unitPrice,\n imageUrl: l.imageUrl,\n })),\n );\n if (opts && opts.clearOnSuccess) cartObj.clear();\n return session;\n },\n };\n return cartObj;\n }\n\n const cart = {\n /** Create a new, empty cart (replaces any persisted cart) */\n create(): StorefrontCart {\n const st = freshCart();\n saveCart(st);\n return makeCart(st);\n },\n /** Get the current cart — loaded from storage if persisted, otherwise a fresh one */\n current(): StorefrontCart {\n return makeCart(loadCart() || freshCart());\n },\n /** Recover an abandoned cart by recovery token */\n async recover(token: string): Promise<CheckoutSession> {\n return request(\"GET\", `/abandoned-carts/recover/${token}`);\n },\n };\n\n // ── Alias namespaces (convenience wrappers over existing methods) ──\n\n /** Alias for `client.customer.orders` — order history for the logged-in customer */\n const orders = {\n /** Get customer's order history (delegates to `customer.orders`) */\n list: (params?: ListParams): Promise<PaginatedResponse<Order>> => customer.orders(params),\n };\n\n /** Convenience namespace bundling `auth` + `customer` under one name */\n const customers = {\n login: auth.login,\n register: auth.register,\n loginWithGoogle: auth.loginWithGoogle,\n logout: auth.logout,\n isAuthenticated: auth.isAuthenticated,\n setTokens: auth.setTokens,\n me: customer.me,\n orders: customer.orders,\n addresses: customer.addresses,\n };\n\n // ── Public API ───────────────────────────────────────────────────\n\n return {\n store,\n products,\n collections,\n checkout,\n auth,\n customer,\n blog,\n bookings,\n forms,\n cart,\n orders,\n customers,\n };\n}\n\n// ── Type export for TypeScript users ──\n\nexport type StorefrontClient = ReturnType<typeof createStorefrontClient>;\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;AAqXO,IAAM,eAAA,GAAN,cAA8B,KAAA,CAAM;AAAA,EAKzC,WAAA,CAAY,MAAA,EAAgB,IAAA,EAAc,OAAA,EAAiB,OAAA,EAAmB;AAC5E,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AACF;AAIO,SAAS,uBAAuB,MAAA,EAA0B;AAC/D,EAAA,MAAM,UAAU,MAAA,CAAO,MAAA,IAAU,8DAAA,EAAgE,OAAA,CAAQ,OAAO,EAAE,CAAA;AAClH,EAAA,MAAM,UAAU,MAAA,CAAO,WAAA,IAAe,UAAA,CAAW,KAAA,CAAM,KAAK,UAAU,CAAA;AACtE,EAAA,IAAI,WAAA,GAA6B,IAAA;AACjC,EAAA,IAAI,YAAA,GAA8B,IAAA;AAIlC,EAAA,MAAM,cAAA,GAAiB;AAAA,IACrB,OAAA,EAAS,CAAA;AAAA,IACT,WAAA,EAAa,GAAA;AAAA,IACb,UAAA,EAAY,GAAA;AAAA,IACZ,aAAA,EAAe,CAAC,GAAA,EAAK,GAAA,EAAK,KAAK,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG;AAAA,GACnD;AACA,EAAA,MAAM,KACJ,MAAA,CAAO,KAAA,KAAU,KAAA,GACb,EAAE,GAAG,cAAA,EAAgB,OAAA,EAAS,CAAA,EAAE,GAChC,EAAE,GAAG,cAAA,EAAgB,GAAI,MAAA,CAAO,KAAA,IAAS,EAAC,EAAG;AACnD,EAAA,MAAM,6BAAa,IAAI,GAAA,CAAI,CAAC,KAAA,EAAO,MAAM,CAAC,CAAA;AAC1C,EAAA,MAAM,KAAA,GAAQ,CAAC,EAAA,KAAe,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY,UAAA,CAAW,OAAA,EAAS,EAAE,CAAC,CAAA;AACpF,EAAA,SAAS,QAAQ,OAAA,EAAyB;AACxC,IAAA,OAAO,KAAK,GAAA,CAAI,EAAA,CAAG,UAAA,EAAY,IAAA,CAAK,MAAM,IAAA,CAAK,MAAA,EAAO,GAAI,EAAA,CAAG,cAAc,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,OAAO,CAAC,CAAC,CAAA;AAAA,EAClG;AAIA,EAAA,eAAe,OAAA,CACb,MAAA,EACA,IAAA,EACA,OAAA,EAKY;AACZ,IAAA,MAAM,MAAM,IAAI,GAAA,CAAI,GAAG,MAAM,CAAA,EAAG,IAAI,CAAA,CAAE,CAAA;AACtC,IAAA,IAAI,SAAS,MAAA,EAAQ;AACnB,MAAA,KAAA,MAAW,CAAC,GAAG,CAAC,CAAA,IAAK,OAAO,OAAA,CAAQ,OAAA,CAAQ,MAAM,CAAA,EAAG;AACnD,QAAA,IAAI,CAAA,KAAM,MAAA,IAAa,CAAA,KAAM,IAAA,EAAM,GAAA,CAAI,aAAa,GAAA,CAAI,CAAA,EAAG,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,MACtE;AAAA,IACF;AAEA,IAAA,MAAM,OAAA,GAAkC;AAAA,MACtC,kBAAkB,MAAA,CAAO;AAAA,KAC3B;AAEA,IAAA,IAAI,OAAA,EAAS,QAAQ,WAAA,EAAa;AAChC,MAAA,OAAA,CAAQ,eAAe,CAAA,GAAI,CAAA,OAAA,EAAU,WAAW,CAAA,CAAA;AAAA,IAClD;AAEA,IAAA,IAAI,SAAS,IAAA,EAAM;AACjB,MAAA,OAAA,CAAQ,cAAc,CAAA,GAAI,kBAAA;AAAA,IAC5B;AAEA,IAAA,MAAM,YAAA,GAA4B;AAAA,MAChC,MAAA;AAAA,MACA,OAAA;AAAA,MACA,MAAM,OAAA,EAAS,IAAA,GAAO,KAAK,SAAA,CAAU,OAAA,CAAQ,IAAI,CAAA,GAAI;AAAA,KACvD;AAEA,IAAA,IAAI,OAAA,GAAU,CAAA;AACd,IAAA,IAAI,GAAA;AACJ,IAAA,OAAO,IAAA,EAAM;AACX,MAAA,IAAI;AACF,QAAA,GAAA,GAAM,MAAM,OAAA,CAAQ,GAAA,CAAI,QAAA,IAAY,YAAY,CAAA;AAAA,MAClD,SAAS,GAAA,EAAK;AACZ,QAAA,IAAI,OAAA,GAAU,GAAG,OAAA,EAAS;AACxB,UAAA,MAAM,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAC,CAAA;AAC5B,UAAA,OAAA,EAAA;AACA,UAAA;AAAA,QACF;AACA,QAAA,MAAM,GAAA;AAAA,MACR;AACA,MAAA,IAAI,OAAA,GAAU,EAAA,CAAG,OAAA,IAAW,EAAA,CAAG,aAAA,CAAc,QAAA,CAAS,GAAA,CAAI,MAAM,CAAA,IAAK,UAAA,CAAW,GAAA,CAAI,MAAM,CAAA,EAAG;AAC3F,QAAA,MAAM,KAAK,MAAA,CAAO,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,aAAa,CAAC,CAAA;AAChD,QAAA,MAAM,KAAA,CAAM,MAAA,CAAO,QAAA,CAAS,EAAE,CAAA,IAAK,EAAA,GAAK,CAAA,GAAI,EAAA,GAAK,GAAA,GAAO,OAAA,CAAQ,OAAO,CAAC,CAAA;AACxE,QAAA,OAAA,EAAA;AACA,QAAA;AAAA,MACF;AACA,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,GAAA,CAAI,MAAA,KAAW,GAAA,IAAO,OAAA,EAAS,QAAQ,YAAA,EAAc;AACvD,MAAA,MAAM,SAAA,GAAY,MAAM,cAAA,EAAe;AACvC,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,OAAA,CAAQ,eAAe,CAAA,GAAI,CAAA,OAAA,EAAU,WAAW,CAAA,CAAA;AAChD,QAAA,MAAM,KAAA,GAAQ,MAAM,OAAA,CAAQ,GAAA,CAAI,UAAS,EAAG;AAAA,UAC1C,MAAA;AAAA,UACA,OAAA;AAAA,UACA,MAAM,OAAA,EAAS,IAAA,GAAO,KAAK,SAAA,CAAU,OAAA,CAAQ,IAAI,CAAA,GAAI;AAAA,SACtD,CAAA;AACD,QAAA,IAAI,CAAC,KAAA,CAAM,EAAA,EAAI,MAAM,MAAM,WAAW,KAAK,CAAA;AAC3C,QAAA,OAAO,KAAA,CAAM,MAAA,KAAW,GAAA,GAAO,MAAA,GAAkB,MAAM,IAAA,EAAK;AAAA,MAC9D;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,GAAA,CAAI,EAAA,EAAI,MAAM,MAAM,WAAW,GAAG,CAAA;AACvC,IAAA,OAAO,GAAA,CAAI,MAAA,KAAW,GAAA,GAAO,MAAA,GAAkB,IAAI,IAAA,EAAK;AAAA,EAC1D;AAEA,EAAA,eAAe,WAAW,GAAA,EAAyC;AACjE,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,MAAA,OAAO,IAAI,eAAA;AAAA,QACT,GAAA,CAAI,MAAA;AAAA,QACJ,IAAA,CAAK,IAAA,IAAQ,IAAA,CAAK,KAAA,IAAS,SAAA;AAAA,QAC3B,IAAA,CAAK,WAAW,GAAA,CAAI,UAAA;AAAA,QACpB;AAAA,OACF;AAAA,IACF,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,IAAI,eAAA,CAAgB,GAAA,CAAI,MAAA,EAAQ,SAAA,EAAW,IAAI,UAAU,CAAA;AAAA,IAClE;AAAA,EACF;AAEA,EAAA,eAAe,cAAA,GAAmC;AAChD,IAAA,IAAI,CAAC,cAAc,OAAO,KAAA;AAC1B,IAAA,IAAI;AACF,MAAA,MAAM,GAAA,GAAM,MAAM,OAAA,CAAQ,CAAA,EAAG,MAAM,CAAA,wBAAA,CAAA,EAA4B;AAAA,QAC7D,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS;AAAA,UACP,cAAA,EAAgB,kBAAA;AAAA,UAChB,kBAAkB,MAAA,CAAO;AAAA,SAC3B;AAAA,QACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,cAAc;AAAA,OACtC,CAAA;AACD,MAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,QAAA,WAAA,GAAc,IAAA;AACd,QAAA,YAAA,GAAe,IAAA;AACf,QAAA,OAAO,KAAA;AAAA,MACT;AACA,MAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,MAAA,WAAA,GAAc,IAAA,CAAK,WAAA;AACnB,MAAA,YAAA,GAAe,IAAA,CAAK,YAAA;AACpB,MAAA,OAAO,IAAA;AAAA,IACT,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAIA,EAAA,MAAM,KAAA,GAAQ;AAAA;AAAA,IAEZ,MAAM,OAAA,GAAgC;AACpC,MAAA,OAAO,OAAA,CAAQ,OAAO,yBAAyB,CAAA;AAAA,IACjD;AAAA,GACF;AAEA,EAAA,MAAM,QAAA,GAAW;AAAA;AAAA,IAEf,MAAM,KAAK,MAAA,EAA0D;AACnE,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,0BAAA,EAA4B,EAAE,QAAQ,CAAA;AAAA,IAC9D,CAAA;AAAA;AAAA,IAEA,MAAM,IAAI,QAAA,EAAoC;AAC5C,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,CAAA,yBAAA,EAA4B,QAAQ,CAAA,CAAE,CAAA;AAAA,IAC9D,CAAA;AAAA;AAAA,IAEA,MAAM,MAAA,CAAO,KAAA,EAAe,MAAA,EAA0D;AACpF,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,wBAAA,EAA0B,EAAE,MAAA,EAAQ,EAAE,GAAG,MAAA,EAAQ,CAAA,EAAG,KAAA,EAAM,EAAG,CAAA;AAAA,IACrF;AAAA,GACF;AAEA,EAAA,MAAM,WAAA,GAAc;AAAA;AAAA,IAElB,MAAM,KAAK,MAAA,EAA6D;AACtE,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,6BAAA,EAA+B,EAAE,QAAQ,CAAA;AAAA,IACjE,CAAA;AAAA;AAAA,IAEA,MAAM,IAAI,QAAA,EAAiE;AACzE,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,CAAA,4BAAA,EAA+B,QAAQ,CAAA,CAAE,CAAA;AAAA,IACjE;AAAA,GACF;AAEA,EAAA,MAAM,SAAA,GAAY;AAAA;AAAA,IAEhB,MAAM,QAAA,CAAS,IAAA,EAAc,KAAA,EAAoE;AAC/F,MAAA,OAAO,OAAA,CAAQ,MAAA,EAAQ,oCAAA,EAAsC,EAAE,IAAA,EAAM,EAAE,IAAA,EAAM,GAAI,KAAA,IAAS,EAAC,EAAG,EAAG,CAAA;AAAA,IACnG,CAAA;AAAA;AAAA,IAEA,MAAM,SAAA,GAA2C;AAC/C,MAAA,OAAO,OAAA,CAAQ,OAAO,qCAAqC,CAAA;AAAA,IAC7D;AAAA,GACF;AAEA,EAAA,MAAM,QAAA,GAAW;AAAA;AAAA,IAEf,MAAM,MAAA,CAAO,KAAA,EAA2B,IAAA,EAAwD;AAC9F,MAAA,MAAM,IAAA,GAAgC,EAAE,KAAA,EAAO,KAAA,EAAM;AACrD,MAAA,IAAI,IAAA,IAAQ,IAAA,CAAK,UAAA,EAAY,IAAA,CAAK,aAAa,IAAA,CAAK,UAAA;AACpD,MAAA,OAAO,OAAA,CAAQ,MAAA,EAAQ,WAAA,EAAa,EAAE,MAAM,CAAA;AAAA,IAC9C,CAAA;AAAA;AAAA,IAEA,MAAM,IAAI,UAAA,EAA8C;AACtD,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,CAAA,UAAA,EAAa,UAAU,CAAA,CAAE,CAAA;AAAA,IACjD,CAAA;AAAA;AAAA,IAEA,MAAM,WAAA,CAAY,UAAA,EAAoB,UAAA,EAA8C;AAClF,MAAA,OAAO,OAAA,CAAQ,MAAA,EAAQ,CAAA,UAAA,EAAa,UAAU,CAAA,OAAA,CAAA,EAAW,EAAE,IAAA,EAAM,EAAE,IAAA,EAAM,UAAA,EAAW,EAAG,CAAA;AAAA,IACzF,CAAA;AAAA;AAAA,IAEA,MAAM,aAAA,CAAc,UAAA,EAAoB,IAAA,EAAwC;AAC9E,MAAA,OAAO,OAAA,CAAQ,MAAA,EAAQ,CAAA,UAAA,EAAa,UAAU,CAAA,UAAA,CAAA,EAAc,EAAE,IAAA,EAAM,EAAE,IAAA,EAAK,EAAG,CAAA;AAAA,IAChF,CAAA;AAAA;AAAA,IAEA,MAAM,QAAA,CAAS,UAAA,EAAoB,OAAA,EAAmD;AACpF,MAAA,OAAO,OAAA,CAAQ,QAAQ,CAAA,UAAA,EAAa,UAAU,aAAa,EAAE,IAAA,EAAM,SAAS,CAAA;AAAA,IAC9E;AAAA,GACF;AAEA,EAAA,MAAM,IAAA,GAAO;AAAA;AAAA,IAEX,MAAM,SAAS,IAAA,EAKU;AACvB,MAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAqB,MAAA,EAAQ,6BAA6B,EAAE,IAAA,EAAM,MAAM,CAAA;AAC9F,MAAA,WAAA,GAAc,OAAA,CAAQ,WAAA;AACtB,MAAA,YAAA,GAAe,OAAA,CAAQ,YAAA;AACvB,MAAA,OAAO,OAAA;AAAA,IACT,CAAA;AAAA;AAAA,IAEA,MAAM,KAAA,CAAM,KAAA,EAAe,QAAA,EAAwC;AACjE,MAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAqB,MAAA,EAAQ,wBAAA,EAA0B;AAAA,QAC3E,IAAA,EAAM,EAAE,KAAA,EAAO,QAAA;AAAS,OACzB,CAAA;AACD,MAAA,WAAA,GAAc,OAAA,CAAQ,WAAA;AACtB,MAAA,YAAA,GAAe,OAAA,CAAQ,YAAA;AACvB,MAAA,OAAO,OAAA;AAAA,IACT,CAAA;AAAA;AAAA,IAEA,MAAM,gBAAgB,OAAA,EAAuC;AAC3D,MAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAqB,MAAA,EAAQ,yBAAA,EAA2B;AAAA,QAC5E,IAAA,EAAM,EAAE,OAAA;AAAQ,OACjB,CAAA;AACD,MAAA,WAAA,GAAc,OAAA,CAAQ,WAAA;AACtB,MAAA,YAAA,GAAe,OAAA,CAAQ,YAAA;AACvB,MAAA,OAAO,OAAA;AAAA,IACT,CAAA;AAAA;AAAA,IAEA,MAAM,MAAA,GAAwB;AAC5B,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,IAAI;AACF,UAAA,MAAM,QAAQ,MAAA,EAAQ,yBAAA,EAA2B,EAAE,IAAA,EAAM,MAAM,CAAA;AAAA,QACjE,CAAA,CAAA,MAAQ;AAAA,QAA6B;AAAA,MACvC;AACA,MAAA,WAAA,GAAc,IAAA;AACd,MAAA,YAAA,GAAe,IAAA;AAAA,IACjB,CAAA;AAAA;AAAA,IAEA,MAAM,OAAA,GAA4B;AAChC,MAAA,OAAO,cAAA,EAAe;AAAA,IACxB,CAAA;AAAA;AAAA,IAEA,eAAA,GAA2B;AACzB,MAAA,OAAO,WAAA,KAAgB,IAAA;AAAA,IACzB,CAAA;AAAA;AAAA,IAEA,SAAA,CAAU,QAAgB,OAAA,EAAuB;AAC/C,MAAA,WAAA,GAAc,MAAA;AACd,MAAA,YAAA,GAAe,OAAA;AAAA,IACjB;AAAA,GACF;AAEA,EAAA,MAAM,QAAA,GAAW;AAAA;AAAA,IAEf,MAAM,EAAA,GAAwB;AAC5B,MAAA,OAAO,QAAQ,KAAA,EAAO,qBAAA,EAAuB,EAAE,IAAA,EAAM,MAAM,CAAA;AAAA,IAC7D,CAAA;AAAA;AAAA,IAEA,MAAM,OAAO,MAAA,EAAwD;AACnE,MAAA,MAAM,EAAA,GAAK,MAAM,OAAA,CAAkB,KAAA,EAAO,uBAAuB,EAAE,IAAA,EAAM,MAAM,CAAA;AAC/E,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,CAAA,yBAAA,EAA4B,EAAA,CAAG,EAAE,WAAW,EAAE,MAAA,EAAQ,IAAA,EAAM,IAAA,EAAM,CAAA;AAAA,IAC1F,CAAA;AAAA;AAAA,IAEA,MAAM,SAAA,GAAgC;AACpC,MAAA,MAAM,EAAA,GAAK,MAAM,OAAA,CAAkB,KAAA,EAAO,uBAAuB,EAAE,IAAA,EAAM,MAAM,CAAA;AAC/E,MAAA,OAAO,OAAA,CAAQ,OAAO,CAAA,yBAAA,EAA4B,EAAA,CAAG,EAAE,CAAA,UAAA,CAAA,EAAc,EAAE,IAAA,EAAM,IAAA,EAAM,CAAA;AAAA,IACrF;AAAA,GACF;AAEA,EAAA,MAAM,IAAA,GAAO;AAAA;AAAA,IAEX,MAAM,KAAK,MAAA,EAA+E;AACxF,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,4BAAA,EAA8B,EAAE,QAAQ,CAAA;AAAA,IAChE,CAAA;AAAA;AAAA,IAEA,MAAM,IAAI,IAAA,EAAiC;AACzC,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,CAAA,2BAAA,EAA8B,IAAI,CAAA,CAAE,CAAA;AAAA,IAC5D;AAAA,GACF;AAEA,EAAA,MAAM,QAAA,GAAW;AAAA;AAAA,IAEf,MAAM,QAAA,GAAuC;AAC3C,MAAA,OAAO,OAAA,CAAQ,OAAO,2BAA2B,CAAA;AAAA,IACnD,CAAA;AAAA;AAAA,IAEA,MAAM,KAAA,GAAuE;AAC3E,MAAA,OAAO,OAAA,CAAQ,OAAO,wBAAwB,CAAA;AAAA,IAChD,CAAA;AAAA;AAAA,IAEA,MAAM,aAAa,MAAA,EAIK;AACtB,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,+BAAA,EAAiC,EAAE,QAAQ,CAAA;AAAA,IACnE,CAAA;AAAA;AAAA,IAEA,MAAM,KAAK,IAAA,EAMU;AACnB,MAAA,OAAO,QAAQ,MAAA,EAAQ,uBAAA,EAAyB,EAAE,IAAA,EAAM,MAAM,CAAA;AAAA,IAChE;AAAA,GACF;AAEA,EAAA,MAAM,KAAA,GAAQ;AAAA;AAAA,IAEZ,MAAM,IAAI,QAAA,EAA2C;AACnD,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,CAAA,cAAA,EAAiB,QAAQ,CAAA,CAAE,CAAA;AAAA,IACnD,CAAA;AAAA;AAAA,IAEA,MAAM,MAAA,CAAO,MAAA,EAAgB,IAAA,EAAwD;AACnF,MAAA,OAAO,OAAA,CAAQ,QAAQ,CAAA,cAAA,EAAiB,MAAM,WAAW,EAAE,IAAA,EAAM,MAAM,CAAA;AAAA,IACzE,CAAA;AAAA;AAAA,IAEA,MAAM,UAAA,CAAW,MAAA,EAAgB,IAAA,EAAsC;AACrE,MAAA,MAAM,QAAA,GAAW,IAAI,QAAA,EAAS;AAC9B,MAAA,QAAA,CAAS,MAAA,CAAO,QAAQ,IAAI,CAAA;AAC5B,MAAA,MAAM,MAAM,MAAM,OAAA,CAAQ,GAAG,MAAM,CAAA,cAAA,EAAiB,MAAM,CAAA,OAAA,CAAA,EAAW;AAAA,QACnE,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS,EAAE,gBAAA,EAAkB,MAAA,CAAO,WAAA,EAAY;AAAA,QAChD,IAAA,EAAM;AAAA,OACP,CAAA;AACD,MAAA,IAAI,CAAC,GAAA,CAAI,EAAA,EAAI,MAAM,MAAM,WAAW,GAAG,CAAA;AACvC,MAAA,OAAO,IAAI,IAAA,EAAK;AAAA,IAClB;AAAA,GACF;AAIA,EAAA,MAAM,QAAA,GAAW,sBAAsB,MAAA,CAAO,WAAA;AAC9C,EAAA,MAAM,QAAQ,MAAM;AAClB,IAAA,IAAI;AACF,MAAA,OAAO,MAAA,CAAO,WAAA,KAAgB,KAAA,IAAS,OAAO,YAAA,KAAiB,WAAA;AAAA,IACjE,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF,CAAA;AACA,EAAA,MAAM,WAAW,MAAwB;AACvC,IAAA,IAAI,CAAC,KAAA,EAAM,EAAG,OAAO,IAAA;AACrB,IAAA,IAAI;AACF,MAAA,MAAM,CAAA,GAAI,YAAA,CAAa,OAAA,CAAQ,QAAQ,CAAA;AACvC,MAAA,OAAO,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,GAAI,IAAA;AAAA,IAC7B,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF,CAAA;AACA,EAAA,MAAM,QAAA,GAAW,CAAC,EAAA,KAAwB;AACxC,IAAA,IAAI,CAAC,OAAM,EAAG;AACd,IAAA,IAAI;AACF,MAAA,YAAA,CAAa,OAAA,CAAQ,QAAA,EAAU,IAAA,CAAK,SAAA,CAAU,EAAE,CAAC,CAAA;AAAA,IACnD,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF,CAAA;AACA,EAAA,IAAI,SAAA,GAAY,CAAA;AAChB,EAAA,MAAM,QAAQ,CAAC,CAAA,KACb,OAAO,MAAA,KAAW,eAAe,MAAA,CAAO,UAAA,GAAa,CAAA,GAAI,MAAA,CAAO,YAAW,GAAI,CAAA,GAAI,KAAK,GAAA,EAAI,GAAI,MAAM,EAAE,SAAA;AAC1G,EAAA,MAAM,MAAA,GAAS,MAAA,iBAAc,IAAI,IAAA,IAAO,WAAA,EAAY;AACpD,EAAA,MAAM,SAAA,GAAY,OAAkB,EAAE,EAAA,EAAI,MAAM,OAAO,CAAA,EAAG,KAAA,EAAO,IAAI,SAAA,EAAW,MAAA,EAAO,EAAG,SAAA,EAAW,QAAO,EAAE,CAAA;AAE9G,EAAA,SAAS,SAAS,KAAA,EAAkC;AAClD,IAAA,MAAM,UAAU,MAAM;AACpB,MAAA,KAAA,CAAM,YAAY,MAAA,EAAO;AACzB,MAAA,QAAA,CAAS,KAAK,CAAA;AAAA,IAChB,CAAA;AACA,IAAA,MAAM,OAAA,GAA0B;AAAA,MAC9B,IAAI,EAAA,GAAK;AACP,QAAA,OAAO,KAAA,CAAM,EAAA;AAAA,MACf,CAAA;AAAA,MACA,IAAI,KAAA,GAAQ;AACV,QAAA,OAAO,KAAA,CAAM,KAAA;AAAA,MACf,CAAA;AAAA,MACA,IAAI,SAAA,GAAY;AACd,QAAA,OAAO,KAAA,CAAM,MAAM,MAAA,CAAO,CAAC,GAAG,CAAA,KAAM,CAAA,GAAI,CAAA,CAAE,QAAA,EAAU,CAAC,CAAA;AAAA,MACvD,CAAA;AAAA,MACA,IAAI,QAAA,GAAW;AACb,QAAA,OAAO,KAAA,CAAM,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,CAAA,CAAE,SAAA,GAAY,CAAA,CAAE,QAAA,EAAU,CAAC,CAAA;AAAA,MACrE,CAAA;AAAA;AAAA;AAAA,MAGA,MAAM,YAAY,KAAA,EAAsD;AACtE,QAAA,IAAI,IAAA;AACJ,QAAA,IAAI,KAAA,CAAM,SAAA,IAAa,IAAA,IAAQ,KAAA,CAAM,WAAA,EAAa;AAChD,UAAA,IAAA,GAAO;AAAA,YACL,EAAA,EAAI,MAAM,OAAO,CAAA;AAAA,YACjB,WAAW,KAAA,CAAM,SAAA;AAAA,YACjB,WAAW,KAAA,CAAM,SAAA;AAAA,YACjB,UAAU,KAAA,CAAM,QAAA;AAAA,YAChB,WAAW,KAAA,CAAM,SAAA;AAAA,YACjB,aAAa,KAAA,CAAM,WAAA;AAAA,YACnB,UAAU,KAAA,CAAM;AAAA,WAClB;AAAA,QACF,CAAA,MAAO;AACL,UAAA,MAAM,CAAA,GAAI,MAAM,QAAA,CAAS,GAAA,CAAI,MAAM,SAAS,CAAA;AAC5C,UAAA,MAAM,IAAI,KAAA,CAAM,SAAA,IAAa,KAAA,CAAM,OAAA,CAAQ,EAAE,QAAQ,CAAA,GAAI,CAAA,CAAE,QAAA,CAAS,KAAK,CAAC,CAAA,KAAM,EAAE,EAAA,KAAO,KAAA,CAAM,SAAS,CAAA,GAAI,MAAA;AAC5G,UAAA,IAAA,GAAO;AAAA,YACL,EAAA,EAAI,MAAM,OAAO,CAAA;AAAA,YACjB,WAAW,KAAA,CAAM,SAAA;AAAA,YACjB,WAAW,KAAA,CAAM,SAAA;AAAA,YACjB,UAAU,KAAA,CAAM,QAAA;AAAA,YAChB,WAAW,CAAA,IAAK,CAAA,CAAE,SAAS,IAAA,GAAO,CAAA,CAAE,QAAQ,CAAA,CAAE,KAAA;AAAA,YAC9C,aAAa,CAAA,CAAE,IAAA;AAAA,YACf,QAAA,EAAU,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,MAAM,CAAA,IAAK,CAAA,CAAE,MAAA,CAAO,MAAA,GAAS,CAAA,GAAI,CAAA,CAAE,MAAA,CAAO,CAAC,EAAE,GAAA,GAAM;AAAA,WAC/E;AAAA,QACF;AACA,QAAA,MAAM,QAAA,GAAW,KAAA,CAAM,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,SAAA,KAAc,IAAA,CAAK,SAAA,IAAa,CAAA,CAAE,SAAA,KAAc,KAAK,SAAS,CAAA;AACzG,QAAA,IAAI,QAAA,EAAU,QAAA,CAAS,QAAA,IAAY,IAAA,CAAK,QAAA;AAAA,aACnC,KAAA,CAAM,KAAA,CAAM,IAAA,CAAK,IAAI,CAAA;AAC1B,QAAA,OAAA,EAAQ;AACR,QAAA,OAAO,OAAA;AAAA,MACT,CAAA;AAAA,MACA,cAAA,CAAe,QAAgB,QAAA,EAAkC;AAC/D,QAAA,MAAM,CAAA,GAAI,MAAM,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,MAAM,CAAA;AACjD,QAAA,IAAI,CAAA,EAAG;AACL,UAAA,IAAI,QAAA,IAAY,CAAA,EAAG,KAAA,CAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAO,MAAM,CAAA;AAAA,iBACnE,QAAA,GAAW,QAAA;AAClB,UAAA,OAAA,EAAQ;AAAA,QACV;AACA,QAAA,OAAO,OAAA;AAAA,MACT,CAAA;AAAA,MACA,eAAe,MAAA,EAAgC;AAC7C,QAAA,KAAA,CAAM,KAAA,GAAQ,MAAM,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,MAAM,CAAA;AACvD,QAAA,OAAA,EAAQ;AACR,QAAA,OAAO,OAAA;AAAA,MACT,CAAA;AAAA,MACA,KAAA,GAAwB;AACtB,QAAA,KAAA,CAAM,QAAQ,EAAC;AACf,QAAA,OAAA,EAAQ;AACR,QAAA,OAAO,OAAA;AAAA,MACT,CAAA;AAAA,MACA,MAAM,SAAS,IAAA,EAAoF;AACjG,QAAA,MAAM,OAAA,GAAU,MAAM,QAAA,CAAS,MAAA;AAAA,UAC7B,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,YACtB,WAAW,CAAA,CAAE,SAAA;AAAA,YACb,WAAW,CAAA,CAAE,SAAA;AAAA,YACb,aAAa,CAAA,CAAE,WAAA;AAAA,YACf,UAAU,CAAA,CAAE,QAAA;AAAA,YACZ,WAAW,CAAA,CAAE,SAAA;AAAA,YACb,UAAU,CAAA,CAAE;AAAA,WACd,CAAE,CAAA;AAAA,UACF,QAAQ,IAAA,CAAK,UAAA,GAAa,EAAE,UAAA,EAAY,IAAA,CAAK,YAAW,GAAI;AAAA,SAC9D;AACA,QAAA,IAAI,IAAA,IAAQ,IAAA,CAAK,cAAA,EAAgB,OAAA,CAAQ,KAAA,EAAM;AAC/C,QAAA,OAAO,OAAA;AAAA,MACT;AAAA,KACF;AACA,IAAA,OAAO,OAAA;AAAA,EACT;AAEA,EAAA,MAAM,IAAA,GAAO;AAAA;AAAA,IAEX,MAAA,GAAyB;AACvB,MAAA,MAAM,KAAK,SAAA,EAAU;AACrB,MAAA,QAAA,CAAS,EAAE,CAAA;AACX,MAAA,OAAO,SAAS,EAAE,CAAA;AAAA,IACpB,CAAA;AAAA;AAAA,IAEA,OAAA,GAA0B;AACxB,MAAA,OAAO,QAAA,CAAS,QAAA,EAAS,IAAK,SAAA,EAAW,CAAA;AAAA,IAC3C,CAAA;AAAA;AAAA,IAEA,MAAM,QAAQ,KAAA,EAAyC;AACrD,MAAA,OAAO,OAAA,CAAQ,KAAA,EAAO,CAAA,yBAAA,EAA4B,KAAK,CAAA,CAAE,CAAA;AAAA,IAC3D;AAAA,GACF;AAKA,EAAA,MAAM,MAAA,GAAS;AAAA;AAAA,IAEb,IAAA,EAAM,CAAC,MAAA,KAA2D,QAAA,CAAS,OAAO,MAAM;AAAA,GAC1F;AAGA,EAAA,MAAM,SAAA,GAAY;AAAA,IAChB,OAAO,IAAA,CAAK,KAAA;AAAA,IACZ,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,iBAAiB,IAAA,CAAK,eAAA;AAAA,IACtB,QAAQ,IAAA,CAAK,MAAA;AAAA,IACb,iBAAiB,IAAA,CAAK,eAAA;AAAA,IACtB,WAAW,IAAA,CAAK,SAAA;AAAA,IAChB,IAAI,QAAA,CAAS,EAAA;AAAA,IACb,QAAQ,QAAA,CAAS,MAAA;AAAA,IACjB,WAAW,QAAA,CAAS;AAAA,GACtB;AAIA,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,QAAA;AAAA,IACA,WAAA;AAAA,IACA,SAAA;AAAA,IACA,QAAA;AAAA,IACA,IAAA;AAAA,IACA,QAAA;AAAA,IACA,IAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA;AAAA,IACA,IAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF;AACF","file":"index.cjs","sourcesContent":["/**\n * ManageSales Storefront SDK\n * --------------------------\n * Resource-based client for building online storefronts.\n * Works with any framework: Next.js, Remix, Nuxt, Astro, plain HTML.\n *\n * Usage:\n * import { createStorefrontClient } from \"./managesales-storefront\";\n * const client = createStorefrontClient({ workspaceId: \"<workspace_id>\" });\n * const products = await client.products.list();\n */\n\n// ── Types ──────────────────────────────────────────────────────────\n\nexport interface RetryConfig {\n /** Max retry attempts for a failed request (default: 2) */\n retries?: number;\n /** Base delay in ms used for exponential backoff (default: 300) */\n baseDelayMs?: number;\n /** Upper bound for any single backoff delay, in ms (default: 4000) */\n maxDelayMs?: number;\n /** HTTP status codes that are retried, GET/HEAD only (default: [408,425,429,500,502,503,504]) */\n retryOnStatus?: number[];\n}\n\nexport interface StorefrontConfig {\n /** Your workspace ID (required) */\n workspaceId: string;\n /** API base URL — defaults to production */\n apiUrl?: string;\n /** Custom fetch implementation (for SSR / edge) */\n customFetch?: typeof fetch;\n /** Default locale for content */\n locale?: string;\n /**\n * Retry behavior for transient failures (network errors, and 5xx/408/425/429\n * responses on idempotent GET/HEAD requests). Pass `false` to disable retries\n * entirely. Defaults to 2 retries with exponential backoff.\n */\n retry?: RetryConfig | false;\n /**\n * Persist the stateful cart (`client.cart`) to `localStorage` so it survives\n * page reloads. Defaults to `true`. Has no effect in environments without\n * `localStorage` (e.g. Node/SSR) — the cart simply stays in-memory.\n */\n persistCart?: boolean;\n}\n\nexport interface ListParams {\n page?: number;\n limit?: number;\n search?: string;\n sort?: string;\n order?: \"asc\" | \"desc\";\n [key: string]: unknown;\n}\n\nexport interface PaginatedResponse<T> {\n data: T[];\n total: number;\n page: number;\n limit: number;\n totalPages: number;\n}\n\n// ── Product types ──\n\nexport interface Product {\n id: string;\n name: string;\n slug: string;\n description: string;\n status: string;\n price: number;\n compareAtPrice?: number;\n currency: string;\n images: ProductImage[];\n variants: ProductVariant[];\n category?: { id: string; name: string };\n brand?: { id: string; name: string };\n tags: string[];\n metadata: Record<string, unknown>;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface ProductImage {\n id: string;\n url: string;\n alt: string;\n position: number;\n}\n\nexport interface ProductVariant {\n id: string;\n name: string;\n sku: string;\n price: number;\n compareAtPrice?: number;\n inventory: number;\n options: Record<string, string>;\n}\n\n// ── Collection types ──\n\nexport interface Collection {\n id: string;\n name: string;\n slug: string;\n description: string;\n image?: string;\n productCount: number;\n}\n\n// ── Cart & Checkout types ──\n\nexport interface CheckoutLineItem {\n productId: string;\n variantId?: string;\n productName: string;\n quantity: number;\n unitPrice: number;\n imageUrl?: string;\n}\n\nexport interface CheckoutSessionLine {\n productId?: string;\n variantId?: string;\n productName: string;\n sku?: string;\n imageUrl?: string;\n quantity: number;\n unitPrice: number;\n}\n\nexport interface ShippingMethod {\n id: string;\n name: string;\n price: number;\n estimatedDays?: string;\n}\n\nexport interface CheckoutShippingAddress {\n name?: string;\n phone?: string;\n address?: string;\n city?: string;\n region?: string;\n country?: string;\n postalCode?: string;\n}\n\nexport interface CheckoutSession {\n id: string;\n status: \"open\" | \"completed\" | \"expired\";\n lines: CheckoutSessionLine[];\n subtotal: number;\n discountAmount: number;\n discountCode?: string;\n discountLabel?: string;\n taxAmount: number;\n taxLabel?: string;\n shippingAmount: number;\n shippingMethodId?: string;\n shippingMethodName?: string;\n shipping?: CheckoutShippingAddress;\n giftCardAmount?: number;\n giftCardCode?: string;\n availableShippingMethods?: ShippingMethod[];\n total: number;\n currency: string;\n createdAt?: string;\n /** @deprecated Never populated by the API — use `lines` */\n items?: CheckoutLineItem[];\n /** @deprecated Never populated by the API — use `taxAmount` */\n tax?: number;\n /** @deprecated Never populated by the API — use `discountAmount` */\n discount?: number;\n /** @deprecated Never populated by the API — use `discountCode` */\n couponCode?: string;\n}\n\nexport interface CartLine {\n id: string;\n productId: string;\n variantId?: string;\n quantity: number;\n unitPrice: number;\n productName: string;\n imageUrl?: string;\n}\n\nexport interface CartState {\n id: string;\n lines: CartLine[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface AddCartLineItemInput {\n productId: string;\n variantId?: string;\n quantity: number;\n /** Skip the `products.get` price lookup by supplying these directly */\n unitPrice?: number;\n productName?: string;\n imageUrl?: string;\n}\n\nexport interface StorefrontCart {\n readonly id: string;\n readonly lines: CartLine[];\n readonly itemCount: number;\n readonly subtotal: number;\n /** Adds a line item. Supplying `unitPrice` also requires `productName`, otherwise this falls through to a `products.get` network lookup. */\n addLineItem(input: AddCartLineItemInput): Promise<StorefrontCart>;\n updateLineItem(lineId: string, quantity: number): StorefrontCart;\n removeLineItem(lineId: string): StorefrontCart;\n clear(): StorefrontCart;\n checkout(opts?: { clearOnSuccess?: boolean; couponCode?: string }): Promise<CheckoutSession>;\n}\n\nexport interface Order {\n id: string;\n orderNumber: string;\n status: string;\n total: number;\n currency: string;\n items: OrderItem[];\n createdAt: string;\n}\n\nexport interface OrderItem {\n productId: string;\n name: string;\n quantity: number;\n price: number;\n}\n\n// ── Discount types ──\n\nexport interface DiscountValidationInput {\n /** Cart subtotal; omit when supplying `items` */\n subtotal?: number;\n items?: Array<{ productId?: string; variantId?: string; quantity: number; unitPrice: number }>;\n /** Known customer id — enables per-customer limit checks */\n customerId?: string;\n}\n\nexport interface DiscountValidationResult {\n valid: boolean;\n discountId?: string;\n code?: string;\n label?: string;\n amount?: number;\n freeShipping?: boolean;\n /** Present when `valid` is false — customer-safe explanation */\n reason?: string;\n}\n\nexport interface AutomaticPromotion {\n id: string;\n title: string;\n type: \"percentage\" | \"fixed_amount\" | \"buy_x_get_y\" | \"free_shipping\";\n value: number;\n minOrderAmount?: number | null;\n minQuantity?: number | null;\n endsAt?: string | null;\n}\n\nexport interface CreateCheckoutOptions {\n /** Coupon code applied server-side at session creation */\n couponCode?: string;\n}\n\n// ── Customer types ──\n\nexport interface Customer {\n id: string;\n email: string;\n name: string;\n phone?: string;\n createdAt: string;\n}\n\nexport interface AuthSession {\n customer: Customer;\n accessToken: string;\n refreshToken: string;\n}\n\nexport interface Address {\n id: string;\n label?: string;\n line1: string;\n line2?: string;\n city: string;\n state: string;\n postalCode: string;\n country: string;\n isDefault: boolean;\n}\n\n// ── Blog types ──\n\nexport interface BlogPost {\n id: string;\n title: string;\n slug: string;\n excerpt: string;\n content: string;\n coverImage?: string;\n tags: string[];\n publishedAt: string;\n}\n\n// ── Booking types ──\n\nexport interface BookableService {\n id: string;\n name: string;\n duration: number;\n price: number;\n description: string;\n}\n\nexport interface TimeSlot {\n start: string;\n end: string;\n available: boolean;\n}\n\nexport interface Booking {\n id: string;\n serviceId: string;\n date: string;\n startTime: string;\n endTime: string;\n status: string;\n customer: { name: string; email: string };\n}\n\n// ── Form types ──\n\nexport interface FormDefinition {\n id: string;\n title: string;\n description: string;\n fields: FormField[];\n}\n\nexport interface FormField {\n id: string;\n type: string;\n label: string;\n required: boolean;\n options?: string[];\n placeholder?: string;\n}\n\n// ── Store config ──\n\nexport interface StoreConfig {\n name: string;\n slug: string;\n logo?: string;\n theme: Record<string, unknown>;\n currency: string;\n locale: string;\n}\n\n// ── SDK Error ──\n\nexport class StorefrontError extends Error {\n status: number;\n code: string;\n details?: unknown;\n\n constructor(status: number, code: string, message: string, details?: unknown) {\n super(message);\n this.name = \"StorefrontError\";\n this.status = status;\n this.code = code;\n this.details = details;\n }\n}\n\n// ── Core client ────────────────────────────────────────────────────\n\nexport function createStorefrontClient(config: StorefrontConfig) {\n const apiUrl = (config.apiUrl ?? \"https://managesales-backend-phase1test.up.railway.app/api/v1\").replace(/\\/$/, \"\");\n const fetchFn = config.customFetch ?? globalThis.fetch.bind(globalThis);\n let accessToken: string | null = null;\n let refreshToken: string | null = null;\n\n // ── Retry configuration ──\n\n const RETRY_DEFAULTS = {\n retries: 2,\n baseDelayMs: 300,\n maxDelayMs: 4000,\n retryOnStatus: [408, 425, 429, 500, 502, 503, 504],\n };\n const rc =\n config.retry === false\n ? { ...RETRY_DEFAULTS, retries: 0 }\n : { ...RETRY_DEFAULTS, ...(config.retry || {}) };\n const IDEMPOTENT = new Set([\"GET\", \"HEAD\"]);\n const sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n function backoff(attempt: number): number {\n return Math.min(rc.maxDelayMs, Math.round(Math.random() * rc.baseDelayMs * Math.pow(2, attempt)));\n }\n\n // ── Internal helpers ──\n\n async function request<T>(\n method: string,\n path: string,\n options?: {\n body?: unknown;\n params?: Record<string, unknown>;\n auth?: boolean;\n },\n ): Promise<T> {\n const url = new URL(`${apiUrl}${path}`);\n if (options?.params) {\n for (const [k, v] of Object.entries(options.params)) {\n if (v !== undefined && v !== null) url.searchParams.set(k, String(v));\n }\n }\n\n const headers: Record<string, string> = {\n \"X-Workspace-Id\": config.workspaceId,\n };\n\n if (options?.auth && accessToken) {\n headers[\"Authorization\"] = `Bearer ${accessToken}`;\n }\n\n if (options?.body) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const fetchOptions: RequestInit = {\n method,\n headers,\n body: options?.body ? JSON.stringify(options.body) : undefined,\n };\n\n let attempt = 0;\n let res: Response;\n while (true) {\n try {\n res = await fetchFn(url.toString(), fetchOptions);\n } catch (err) {\n if (attempt < rc.retries) {\n await sleep(backoff(attempt));\n attempt++;\n continue;\n }\n throw err;\n }\n if (attempt < rc.retries && rc.retryOnStatus.includes(res.status) && IDEMPOTENT.has(method)) {\n const ra = Number(res.headers.get(\"retry-after\"));\n await sleep(Number.isFinite(ra) && ra > 0 ? ra * 1000 : backoff(attempt));\n attempt++;\n continue;\n }\n break;\n }\n\n // Auto-refresh on 401\n if (res.status === 401 && options?.auth && refreshToken) {\n const refreshed = await refreshSession();\n if (refreshed) {\n headers[\"Authorization\"] = `Bearer ${accessToken}`;\n const retry = await fetchFn(url.toString(), {\n method,\n headers,\n body: options?.body ? JSON.stringify(options.body) : undefined,\n });\n if (!retry.ok) throw await parseError(retry);\n return retry.status === 204 ? (undefined as T) : retry.json();\n }\n }\n\n if (!res.ok) throw await parseError(res);\n return res.status === 204 ? (undefined as T) : res.json();\n }\n\n async function parseError(res: Response): Promise<StorefrontError> {\n try {\n const body = await res.json();\n return new StorefrontError(\n res.status,\n body.code ?? body.error ?? \"UNKNOWN\",\n body.message ?? res.statusText,\n body,\n );\n } catch {\n return new StorefrontError(res.status, \"UNKNOWN\", res.statusText);\n }\n }\n\n async function refreshSession(): Promise<boolean> {\n if (!refreshToken) return false;\n try {\n const res = await fetchFn(`${apiUrl}/storefront/auth/refresh`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Workspace-Id\": config.workspaceId,\n },\n body: JSON.stringify({ refreshToken }),\n });\n if (!res.ok) {\n accessToken = null;\n refreshToken = null;\n return false;\n }\n const data = await res.json();\n accessToken = data.accessToken;\n refreshToken = data.refreshToken;\n return true;\n } catch {\n return false;\n }\n }\n\n // ── Resource namespaces ──────────────────────────────────────────\n\n const store = {\n /** Resolve store config by workspace (returns theme, branding, currency) */\n async resolve(): Promise<StoreConfig> {\n return request(\"GET\", \"/storefront-api/resolve\");\n },\n };\n\n const products = {\n /** List published products with pagination and filters */\n async list(params?: ListParams): Promise<PaginatedResponse<Product>> {\n return request(\"GET\", \"/storefront-api/products\", { params });\n },\n /** Get a single product by ID or slug */\n async get(idOrSlug: string): Promise<Product> {\n return request(\"GET\", `/storefront-api/products/${idOrSlug}`);\n },\n /** Search products (shorthand for list with search param) */\n async search(query: string, params?: ListParams): Promise<PaginatedResponse<Product>> {\n return request(\"GET\", \"/storefront-api/search\", { params: { ...params, q: query } });\n },\n };\n\n const collections = {\n /** List published collections */\n async list(params?: ListParams): Promise<PaginatedResponse<Collection>> {\n return request(\"GET\", \"/storefront-api/collections\", { params });\n },\n /** Get a collection with its products */\n async get(idOrSlug: string): Promise<Collection & { products: Product[] }> {\n return request(\"GET\", `/storefront-api/collections/${idOrSlug}`);\n },\n };\n\n const discounts = {\n /** Preview a discount code against a cart before checkout. Never consumes usage. */\n async validate(code: string, input?: DiscountValidationInput): Promise<DiscountValidationResult> {\n return request(\"POST\", \"/storefront-api/discounts/validate\", { body: { code, ...(input || {}) } });\n },\n /** Active automatic promotions for display (codes are never exposed) */\n async automatic(): Promise<AutomaticPromotion[]> {\n return request(\"GET\", \"/storefront-api/discounts/automatic\");\n },\n };\n\n const checkout = {\n /** Create a checkout session from cart items */\n async create(items: CheckoutLineItem[], opts?: CreateCheckoutOptions): Promise<CheckoutSession> {\n const body: Record<string, unknown> = { lines: items };\n if (opts && opts.couponCode) body.couponCode = opts.couponCode;\n return request(\"POST\", \"/checkout\", { body });\n },\n /** Retrieve an existing checkout session */\n async get(checkoutId: string): Promise<CheckoutSession> {\n return request(\"GET\", `/checkout/${checkoutId}`);\n },\n /** Apply a coupon or discount code */\n async applyCoupon(checkoutId: string, couponCode: string): Promise<CheckoutSession> {\n return request(\"POST\", `/checkout/${checkoutId}/coupon`, { body: { code: couponCode } });\n },\n /** Apply a gift card to the checkout */\n async applyGiftCard(checkoutId: string, code: string): Promise<CheckoutSession> {\n return request(\"POST\", `/checkout/${checkoutId}/gift-card`, { body: { code } });\n },\n /** Complete checkout — process payment and create order */\n async complete(checkoutId: string, payment?: Record<string, unknown>): Promise<Order> {\n return request(\"POST\", `/checkout/${checkoutId}/complete`, { body: payment });\n },\n };\n\n const auth = {\n /** Register a new customer account */\n async register(data: {\n email: string;\n password: string;\n name: string;\n phone?: string;\n }): Promise<AuthSession> {\n const session = await request<AuthSession>(\"POST\", \"/storefront/auth/register\", { body: data });\n accessToken = session.accessToken;\n refreshToken = session.refreshToken;\n return session;\n },\n /** Log in with email + password */\n async login(email: string, password: string): Promise<AuthSession> {\n const session = await request<AuthSession>(\"POST\", \"/storefront/auth/login\", {\n body: { email, password },\n });\n accessToken = session.accessToken;\n refreshToken = session.refreshToken;\n return session;\n },\n /** Log in with Google ID token */\n async loginWithGoogle(idToken: string): Promise<AuthSession> {\n const session = await request<AuthSession>(\"POST\", \"/storefront/auth/google\", {\n body: { idToken },\n });\n accessToken = session.accessToken;\n refreshToken = session.refreshToken;\n return session;\n },\n /** Log out and clear local session */\n async logout(): Promise<void> {\n if (accessToken) {\n try {\n await request(\"POST\", \"/storefront/auth/logout\", { auth: true });\n } catch { /* ignore logout errors */ }\n }\n accessToken = null;\n refreshToken = null;\n },\n /** Refresh the access token */\n async refresh(): Promise<boolean> {\n return refreshSession();\n },\n /** Check if client has a valid session */\n isAuthenticated(): boolean {\n return accessToken !== null;\n },\n /** Manually set tokens (e.g., from SSR or cookie restoration) */\n setTokens(access: string, refresh: string): void {\n accessToken = access;\n refreshToken = refresh;\n },\n };\n\n const customer = {\n /** Get current customer profile */\n async me(): Promise<Customer> {\n return request(\"GET\", \"/storefront/auth/me\", { auth: true });\n },\n /** Get customer's order history */\n async orders(params?: ListParams): Promise<PaginatedResponse<Order>> {\n const me = await request<Customer>(\"GET\", \"/storefront/auth/me\", { auth: true });\n return request(\"GET\", `/storefront-api/customer/${me.id}/orders`, { params, auth: true });\n },\n /** Get customer's saved addresses */\n async addresses(): Promise<Address[]> {\n const me = await request<Customer>(\"GET\", \"/storefront/auth/me\", { auth: true });\n return request(\"GET\", `/storefront-api/customer/${me.id}/addresses`, { auth: true });\n },\n };\n\n const blog = {\n /** List published blog posts */\n async list(params?: ListParams & { tags?: string }): Promise<PaginatedResponse<BlogPost>> {\n return request(\"GET\", \"/storefront-api/blog/posts\", { params });\n },\n /** Get a blog post by slug */\n async get(slug: string): Promise<BlogPost> {\n return request(\"GET\", `/storefront-api/blog/posts/${slug}`);\n },\n };\n\n const bookings = {\n /** List bookable services */\n async services(): Promise<BookableService[]> {\n return request(\"GET\", \"/bookings-public/services\");\n },\n /** List bookable staff */\n async staff(): Promise<Array<{ id: string; name: string; avatar?: string }>> {\n return request(\"GET\", \"/bookings-public/staff\");\n },\n /** Check available time slots */\n async availability(params: {\n serviceId: string;\n date: string;\n staffId?: string;\n }): Promise<TimeSlot[]> {\n return request(\"GET\", \"/bookings-public/availability\", { params });\n },\n /** Create a booking */\n async book(data: {\n serviceId: string;\n date: string;\n startTime: string;\n staffId?: string;\n customer: { name: string; email: string; phone?: string };\n }): Promise<Booking> {\n return request(\"POST\", \"/bookings-public/book\", { body: data });\n },\n };\n\n const forms = {\n /** Get a published form by ID or slug */\n async get(idOrSlug: string): Promise<FormDefinition> {\n return request(\"GET\", `/public/forms/${idOrSlug}`);\n },\n /** Submit form response */\n async submit(formId: string, data: Record<string, unknown>): Promise<{ id: string }> {\n return request(\"POST\", `/public/forms/${formId}/submit`, { body: data });\n },\n /** Upload file for a form file field */\n async uploadFile(formId: string, file: File): Promise<{ url: string }> {\n const formData = new FormData();\n formData.append(\"file\", file);\n const res = await fetchFn(`${apiUrl}/public/forms/${formId}/upload`, {\n method: \"POST\",\n headers: { \"X-Workspace-Id\": config.workspaceId },\n body: formData,\n });\n if (!res.ok) throw await parseError(res);\n return res.json();\n },\n };\n\n // ── Stateful cart (client-side, localStorage-persisted) ──\n\n const CART_KEY = \"managesales_cart_\" + config.workspaceId;\n const hasLS = () => {\n try {\n return config.persistCart !== false && typeof localStorage !== \"undefined\";\n } catch {\n return false;\n }\n };\n const loadCart = (): CartState | null => {\n if (!hasLS()) return null;\n try {\n const s = localStorage.getItem(CART_KEY);\n return s ? JSON.parse(s) : null;\n } catch {\n return null;\n }\n };\n const saveCart = (st: CartState): void => {\n if (!hasLS()) return;\n try {\n localStorage.setItem(CART_KEY, JSON.stringify(st));\n } catch {\n /* ignore persistence errors (quota, privacy mode, etc.) */\n }\n };\n let __lineSeq = 0;\n const genId = (p: string): string =>\n typeof crypto !== \"undefined\" && crypto.randomUUID ? p + crypto.randomUUID() : p + Date.now() + \"_\" + ++__lineSeq;\n const nowIso = (): string => new Date().toISOString();\n const freshCart = (): CartState => ({ id: genId(\"cart_\"), lines: [], createdAt: nowIso(), updatedAt: nowIso() });\n\n function makeCart(state: CartState): StorefrontCart {\n const persist = () => {\n state.updatedAt = nowIso();\n saveCart(state);\n };\n const cartObj: StorefrontCart = {\n get id() {\n return state.id;\n },\n get lines() {\n return state.lines;\n },\n get itemCount() {\n return state.lines.reduce((n, l) => n + l.quantity, 0);\n },\n get subtotal() {\n return state.lines.reduce((s, l) => s + l.unitPrice * l.quantity, 0);\n },\n // Supplying unitPrice alone does not skip the lookup — productName must also be\n // provided, otherwise this falls through to the products.get() network lookup below.\n async addLineItem(input: AddCartLineItemInput): Promise<StorefrontCart> {\n let line: CartLine;\n if (input.unitPrice != null && input.productName) {\n line = {\n id: genId(\"line_\"),\n productId: input.productId,\n variantId: input.variantId,\n quantity: input.quantity,\n unitPrice: input.unitPrice,\n productName: input.productName,\n imageUrl: input.imageUrl,\n };\n } else {\n const p = await products.get(input.productId);\n const v = input.variantId && Array.isArray(p.variants) ? p.variants.find((x) => x.id === input.variantId) : undefined;\n line = {\n id: genId(\"line_\"),\n productId: input.productId,\n variantId: input.variantId,\n quantity: input.quantity,\n unitPrice: v && v.price != null ? v.price : p.price,\n productName: p.name,\n imageUrl: Array.isArray(p.images) && p.images.length > 0 ? p.images[0].url : undefined,\n };\n }\n const existing = state.lines.find((l) => l.productId === line.productId && l.variantId === line.variantId);\n if (existing) existing.quantity += line.quantity;\n else state.lines.push(line);\n persist();\n return cartObj;\n },\n updateLineItem(lineId: string, quantity: number): StorefrontCart {\n const l = state.lines.find((x) => x.id === lineId);\n if (l) {\n if (quantity <= 0) state.lines = state.lines.filter((x) => x.id !== lineId);\n else l.quantity = quantity;\n persist();\n }\n return cartObj;\n },\n removeLineItem(lineId: string): StorefrontCart {\n state.lines = state.lines.filter((x) => x.id !== lineId);\n persist();\n return cartObj;\n },\n clear(): StorefrontCart {\n state.lines = [];\n persist();\n return cartObj;\n },\n async checkout(opts?: { clearOnSuccess?: boolean; couponCode?: string }): Promise<CheckoutSession> {\n const session = await checkout.create(\n state.lines.map((l) => ({\n productId: l.productId,\n variantId: l.variantId,\n productName: l.productName,\n quantity: l.quantity,\n unitPrice: l.unitPrice,\n imageUrl: l.imageUrl,\n })),\n opts && opts.couponCode ? { couponCode: opts.couponCode } : undefined,\n );\n if (opts && opts.clearOnSuccess) cartObj.clear();\n return session;\n },\n };\n return cartObj;\n }\n\n const cart = {\n /** Create a new, empty cart (replaces any persisted cart) */\n create(): StorefrontCart {\n const st = freshCart();\n saveCart(st);\n return makeCart(st);\n },\n /** Get the current cart — loaded from storage if persisted, otherwise a fresh one */\n current(): StorefrontCart {\n return makeCart(loadCart() || freshCart());\n },\n /** Recover an abandoned cart by recovery token */\n async recover(token: string): Promise<CheckoutSession> {\n return request(\"GET\", `/abandoned-carts/recover/${token}`);\n },\n };\n\n // ── Alias namespaces (convenience wrappers over existing methods) ──\n\n /** Alias for `client.customer.orders` — order history for the logged-in customer */\n const orders = {\n /** Get customer's order history (delegates to `customer.orders`) */\n list: (params?: ListParams): Promise<PaginatedResponse<Order>> => customer.orders(params),\n };\n\n /** Convenience namespace bundling `auth` + `customer` under one name */\n const customers = {\n login: auth.login,\n register: auth.register,\n loginWithGoogle: auth.loginWithGoogle,\n logout: auth.logout,\n isAuthenticated: auth.isAuthenticated,\n setTokens: auth.setTokens,\n me: customer.me,\n orders: customer.orders,\n addresses: customer.addresses,\n };\n\n // ── Public API ───────────────────────────────────────────────────\n\n return {\n store,\n products,\n collections,\n discounts,\n checkout,\n auth,\n customer,\n blog,\n bookings,\n forms,\n cart,\n orders,\n customers,\n };\n}\n\n// ── Type export for TypeScript users ──\n\nexport type StorefrontClient = ReturnType<typeof createStorefrontClient>;\n"]}
package/dist/index.d.cts CHANGED
@@ -111,16 +111,57 @@ interface CheckoutLineItem {
111
111
  unitPrice: number;
112
112
  imageUrl?: string;
113
113
  }
114
+ interface CheckoutSessionLine {
115
+ productId?: string;
116
+ variantId?: string;
117
+ productName: string;
118
+ sku?: string;
119
+ imageUrl?: string;
120
+ quantity: number;
121
+ unitPrice: number;
122
+ }
123
+ interface ShippingMethod {
124
+ id: string;
125
+ name: string;
126
+ price: number;
127
+ estimatedDays?: string;
128
+ }
129
+ interface CheckoutShippingAddress {
130
+ name?: string;
131
+ phone?: string;
132
+ address?: string;
133
+ city?: string;
134
+ region?: string;
135
+ country?: string;
136
+ postalCode?: string;
137
+ }
114
138
  interface CheckoutSession {
115
139
  id: string;
116
140
  status: "open" | "completed" | "expired";
117
- items: CheckoutLineItem[];
141
+ lines: CheckoutSessionLine[];
118
142
  subtotal: number;
119
- tax: number;
120
- shipping: number;
121
- discount: number;
143
+ discountAmount: number;
144
+ discountCode?: string;
145
+ discountLabel?: string;
146
+ taxAmount: number;
147
+ taxLabel?: string;
148
+ shippingAmount: number;
149
+ shippingMethodId?: string;
150
+ shippingMethodName?: string;
151
+ shipping?: CheckoutShippingAddress;
152
+ giftCardAmount?: number;
153
+ giftCardCode?: string;
154
+ availableShippingMethods?: ShippingMethod[];
122
155
  total: number;
123
156
  currency: string;
157
+ createdAt?: string;
158
+ /** @deprecated Never populated by the API — use `lines` */
159
+ items?: CheckoutLineItem[];
160
+ /** @deprecated Never populated by the API — use `taxAmount` */
161
+ tax?: number;
162
+ /** @deprecated Never populated by the API — use `discountAmount` */
163
+ discount?: number;
164
+ /** @deprecated Never populated by the API — use `discountCode` */
124
165
  couponCode?: string;
125
166
  }
126
167
  interface CartLine {
@@ -159,6 +200,7 @@ interface StorefrontCart {
159
200
  clear(): StorefrontCart;
160
201
  checkout(opts?: {
161
202
  clearOnSuccess?: boolean;
203
+ couponCode?: string;
162
204
  }): Promise<CheckoutSession>;
163
205
  }
164
206
  interface Order {
@@ -176,6 +218,41 @@ interface OrderItem {
176
218
  quantity: number;
177
219
  price: number;
178
220
  }
221
+ interface DiscountValidationInput {
222
+ /** Cart subtotal; omit when supplying `items` */
223
+ subtotal?: number;
224
+ items?: Array<{
225
+ productId?: string;
226
+ variantId?: string;
227
+ quantity: number;
228
+ unitPrice: number;
229
+ }>;
230
+ /** Known customer id — enables per-customer limit checks */
231
+ customerId?: string;
232
+ }
233
+ interface DiscountValidationResult {
234
+ valid: boolean;
235
+ discountId?: string;
236
+ code?: string;
237
+ label?: string;
238
+ amount?: number;
239
+ freeShipping?: boolean;
240
+ /** Present when `valid` is false — customer-safe explanation */
241
+ reason?: string;
242
+ }
243
+ interface AutomaticPromotion {
244
+ id: string;
245
+ title: string;
246
+ type: "percentage" | "fixed_amount" | "buy_x_get_y" | "free_shipping";
247
+ value: number;
248
+ minOrderAmount?: number | null;
249
+ minQuantity?: number | null;
250
+ endsAt?: string | null;
251
+ }
252
+ interface CreateCheckoutOptions {
253
+ /** Coupon code applied server-side at session creation */
254
+ couponCode?: string;
255
+ }
179
256
  interface Customer {
180
257
  id: string;
181
258
  email: string;
@@ -282,13 +359,21 @@ declare function createStorefrontClient(config: StorefrontConfig): {
282
359
  products: Product[];
283
360
  }>;
284
361
  };
362
+ discounts: {
363
+ /** Preview a discount code against a cart before checkout. Never consumes usage. */
364
+ validate(code: string, input?: DiscountValidationInput): Promise<DiscountValidationResult>;
365
+ /** Active automatic promotions for display (codes are never exposed) */
366
+ automatic(): Promise<AutomaticPromotion[]>;
367
+ };
285
368
  checkout: {
286
369
  /** Create a checkout session from cart items */
287
- create(items: CheckoutLineItem[]): Promise<CheckoutSession>;
370
+ create(items: CheckoutLineItem[], opts?: CreateCheckoutOptions): Promise<CheckoutSession>;
288
371
  /** Retrieve an existing checkout session */
289
372
  get(checkoutId: string): Promise<CheckoutSession>;
290
373
  /** Apply a coupon or discount code */
291
374
  applyCoupon(checkoutId: string, couponCode: string): Promise<CheckoutSession>;
375
+ /** Apply a gift card to the checkout */
376
+ applyGiftCard(checkoutId: string, code: string): Promise<CheckoutSession>;
292
377
  /** Complete checkout — process payment and create order */
293
378
  complete(checkoutId: string, payment?: Record<string, unknown>): Promise<Order>;
294
379
  };
@@ -400,4 +485,4 @@ declare function createStorefrontClient(config: StorefrontConfig): {
400
485
  };
401
486
  type StorefrontClient = ReturnType<typeof createStorefrontClient>;
402
487
 
403
- export { type AddCartLineItemInput, type Address, type AuthSession, type BlogPost, type BookableService, type Booking, type CartLine, type CartState, type CheckoutLineItem, type CheckoutSession, type Collection, type Customer, type FormDefinition, type FormField, type ListParams, type Order, type OrderItem, type PaginatedResponse, type Product, type ProductImage, type ProductVariant, type RetryConfig, type StoreConfig, type StorefrontCart, type StorefrontClient, type StorefrontConfig, StorefrontError, type TimeSlot, createStorefrontClient };
488
+ export { type AddCartLineItemInput, type Address, type AuthSession, type AutomaticPromotion, type BlogPost, type BookableService, type Booking, type CartLine, type CartState, type CheckoutLineItem, type CheckoutSession, type CheckoutSessionLine, type CheckoutShippingAddress, type Collection, type CreateCheckoutOptions, type Customer, type DiscountValidationInput, type DiscountValidationResult, type FormDefinition, type FormField, type ListParams, type Order, type OrderItem, type PaginatedResponse, type Product, type ProductImage, type ProductVariant, type RetryConfig, type ShippingMethod, type StoreConfig, type StorefrontCart, type StorefrontClient, type StorefrontConfig, StorefrontError, type TimeSlot, createStorefrontClient };
package/dist/index.d.ts CHANGED
@@ -111,16 +111,57 @@ interface CheckoutLineItem {
111
111
  unitPrice: number;
112
112
  imageUrl?: string;
113
113
  }
114
+ interface CheckoutSessionLine {
115
+ productId?: string;
116
+ variantId?: string;
117
+ productName: string;
118
+ sku?: string;
119
+ imageUrl?: string;
120
+ quantity: number;
121
+ unitPrice: number;
122
+ }
123
+ interface ShippingMethod {
124
+ id: string;
125
+ name: string;
126
+ price: number;
127
+ estimatedDays?: string;
128
+ }
129
+ interface CheckoutShippingAddress {
130
+ name?: string;
131
+ phone?: string;
132
+ address?: string;
133
+ city?: string;
134
+ region?: string;
135
+ country?: string;
136
+ postalCode?: string;
137
+ }
114
138
  interface CheckoutSession {
115
139
  id: string;
116
140
  status: "open" | "completed" | "expired";
117
- items: CheckoutLineItem[];
141
+ lines: CheckoutSessionLine[];
118
142
  subtotal: number;
119
- tax: number;
120
- shipping: number;
121
- discount: number;
143
+ discountAmount: number;
144
+ discountCode?: string;
145
+ discountLabel?: string;
146
+ taxAmount: number;
147
+ taxLabel?: string;
148
+ shippingAmount: number;
149
+ shippingMethodId?: string;
150
+ shippingMethodName?: string;
151
+ shipping?: CheckoutShippingAddress;
152
+ giftCardAmount?: number;
153
+ giftCardCode?: string;
154
+ availableShippingMethods?: ShippingMethod[];
122
155
  total: number;
123
156
  currency: string;
157
+ createdAt?: string;
158
+ /** @deprecated Never populated by the API — use `lines` */
159
+ items?: CheckoutLineItem[];
160
+ /** @deprecated Never populated by the API — use `taxAmount` */
161
+ tax?: number;
162
+ /** @deprecated Never populated by the API — use `discountAmount` */
163
+ discount?: number;
164
+ /** @deprecated Never populated by the API — use `discountCode` */
124
165
  couponCode?: string;
125
166
  }
126
167
  interface CartLine {
@@ -159,6 +200,7 @@ interface StorefrontCart {
159
200
  clear(): StorefrontCart;
160
201
  checkout(opts?: {
161
202
  clearOnSuccess?: boolean;
203
+ couponCode?: string;
162
204
  }): Promise<CheckoutSession>;
163
205
  }
164
206
  interface Order {
@@ -176,6 +218,41 @@ interface OrderItem {
176
218
  quantity: number;
177
219
  price: number;
178
220
  }
221
+ interface DiscountValidationInput {
222
+ /** Cart subtotal; omit when supplying `items` */
223
+ subtotal?: number;
224
+ items?: Array<{
225
+ productId?: string;
226
+ variantId?: string;
227
+ quantity: number;
228
+ unitPrice: number;
229
+ }>;
230
+ /** Known customer id — enables per-customer limit checks */
231
+ customerId?: string;
232
+ }
233
+ interface DiscountValidationResult {
234
+ valid: boolean;
235
+ discountId?: string;
236
+ code?: string;
237
+ label?: string;
238
+ amount?: number;
239
+ freeShipping?: boolean;
240
+ /** Present when `valid` is false — customer-safe explanation */
241
+ reason?: string;
242
+ }
243
+ interface AutomaticPromotion {
244
+ id: string;
245
+ title: string;
246
+ type: "percentage" | "fixed_amount" | "buy_x_get_y" | "free_shipping";
247
+ value: number;
248
+ minOrderAmount?: number | null;
249
+ minQuantity?: number | null;
250
+ endsAt?: string | null;
251
+ }
252
+ interface CreateCheckoutOptions {
253
+ /** Coupon code applied server-side at session creation */
254
+ couponCode?: string;
255
+ }
179
256
  interface Customer {
180
257
  id: string;
181
258
  email: string;
@@ -282,13 +359,21 @@ declare function createStorefrontClient(config: StorefrontConfig): {
282
359
  products: Product[];
283
360
  }>;
284
361
  };
362
+ discounts: {
363
+ /** Preview a discount code against a cart before checkout. Never consumes usage. */
364
+ validate(code: string, input?: DiscountValidationInput): Promise<DiscountValidationResult>;
365
+ /** Active automatic promotions for display (codes are never exposed) */
366
+ automatic(): Promise<AutomaticPromotion[]>;
367
+ };
285
368
  checkout: {
286
369
  /** Create a checkout session from cart items */
287
- create(items: CheckoutLineItem[]): Promise<CheckoutSession>;
370
+ create(items: CheckoutLineItem[], opts?: CreateCheckoutOptions): Promise<CheckoutSession>;
288
371
  /** Retrieve an existing checkout session */
289
372
  get(checkoutId: string): Promise<CheckoutSession>;
290
373
  /** Apply a coupon or discount code */
291
374
  applyCoupon(checkoutId: string, couponCode: string): Promise<CheckoutSession>;
375
+ /** Apply a gift card to the checkout */
376
+ applyGiftCard(checkoutId: string, code: string): Promise<CheckoutSession>;
292
377
  /** Complete checkout — process payment and create order */
293
378
  complete(checkoutId: string, payment?: Record<string, unknown>): Promise<Order>;
294
379
  };
@@ -400,4 +485,4 @@ declare function createStorefrontClient(config: StorefrontConfig): {
400
485
  };
401
486
  type StorefrontClient = ReturnType<typeof createStorefrontClient>;
402
487
 
403
- export { type AddCartLineItemInput, type Address, type AuthSession, type BlogPost, type BookableService, type Booking, type CartLine, type CartState, type CheckoutLineItem, type CheckoutSession, type Collection, type Customer, type FormDefinition, type FormField, type ListParams, type Order, type OrderItem, type PaginatedResponse, type Product, type ProductImage, type ProductVariant, type RetryConfig, type StoreConfig, type StorefrontCart, type StorefrontClient, type StorefrontConfig, StorefrontError, type TimeSlot, createStorefrontClient };
488
+ export { type AddCartLineItemInput, type Address, type AuthSession, type AutomaticPromotion, type BlogPost, type BookableService, type Booking, type CartLine, type CartState, type CheckoutLineItem, type CheckoutSession, type CheckoutSessionLine, type CheckoutShippingAddress, type Collection, type CreateCheckoutOptions, type Customer, type DiscountValidationInput, type DiscountValidationResult, type FormDefinition, type FormField, type ListParams, type Order, type OrderItem, type PaginatedResponse, type Product, type ProductImage, type ProductVariant, type RetryConfig, type ShippingMethod, type StoreConfig, type StorefrontCart, type StorefrontClient, type StorefrontConfig, StorefrontError, type TimeSlot, createStorefrontClient };
package/dist/index.js CHANGED
@@ -150,10 +150,22 @@ function createStorefrontClient(config) {
150
150
  return request("GET", `/storefront-api/collections/${idOrSlug}`);
151
151
  }
152
152
  };
153
+ const discounts = {
154
+ /** Preview a discount code against a cart before checkout. Never consumes usage. */
155
+ async validate(code, input) {
156
+ return request("POST", "/storefront-api/discounts/validate", { body: { code, ...input || {} } });
157
+ },
158
+ /** Active automatic promotions for display (codes are never exposed) */
159
+ async automatic() {
160
+ return request("GET", "/storefront-api/discounts/automatic");
161
+ }
162
+ };
153
163
  const checkout = {
154
164
  /** Create a checkout session from cart items */
155
- async create(items) {
156
- return request("POST", "/checkout", { body: { lines: items } });
165
+ async create(items, opts) {
166
+ const body = { lines: items };
167
+ if (opts && opts.couponCode) body.couponCode = opts.couponCode;
168
+ return request("POST", "/checkout", { body });
157
169
  },
158
170
  /** Retrieve an existing checkout session */
159
171
  async get(checkoutId) {
@@ -161,7 +173,11 @@ function createStorefrontClient(config) {
161
173
  },
162
174
  /** Apply a coupon or discount code */
163
175
  async applyCoupon(checkoutId, couponCode) {
164
- return request("POST", `/checkout/${checkoutId}/coupon`, { body: { couponCode } });
176
+ return request("POST", `/checkout/${checkoutId}/coupon`, { body: { code: couponCode } });
177
+ },
178
+ /** Apply a gift card to the checkout */
179
+ async applyGiftCard(checkoutId, code) {
180
+ return request("POST", `/checkout/${checkoutId}/gift-card`, { body: { code } });
165
181
  },
166
182
  /** Complete checkout — process payment and create order */
167
183
  async complete(checkoutId, payment) {
@@ -392,7 +408,8 @@ function createStorefrontClient(config) {
392
408
  quantity: l.quantity,
393
409
  unitPrice: l.unitPrice,
394
410
  imageUrl: l.imageUrl
395
- }))
411
+ })),
412
+ opts && opts.couponCode ? { couponCode: opts.couponCode } : void 0
396
413
  );
397
414
  if (opts && opts.clearOnSuccess) cartObj.clear();
398
415
  return session;
@@ -435,6 +452,7 @@ function createStorefrontClient(config) {
435
452
  store,
436
453
  products,
437
454
  collections,
455
+ discounts,
438
456
  checkout,
439
457
  auth,
440
458
  customer,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * ManageSales Storefront SDK\n * --------------------------\n * Resource-based client for building online storefronts.\n * Works with any framework: Next.js, Remix, Nuxt, Astro, plain HTML.\n *\n * Usage:\n * import { createStorefrontClient } from \"./managesales-storefront\";\n * const client = createStorefrontClient({ workspaceId: \"<workspace_id>\" });\n * const products = await client.products.list();\n */\n\n// ── Types ──────────────────────────────────────────────────────────\n\nexport interface RetryConfig {\n /** Max retry attempts for a failed request (default: 2) */\n retries?: number;\n /** Base delay in ms used for exponential backoff (default: 300) */\n baseDelayMs?: number;\n /** Upper bound for any single backoff delay, in ms (default: 4000) */\n maxDelayMs?: number;\n /** HTTP status codes that are retried, GET/HEAD only (default: [408,425,429,500,502,503,504]) */\n retryOnStatus?: number[];\n}\n\nexport interface StorefrontConfig {\n /** Your workspace ID (required) */\n workspaceId: string;\n /** API base URL — defaults to production */\n apiUrl?: string;\n /** Custom fetch implementation (for SSR / edge) */\n customFetch?: typeof fetch;\n /** Default locale for content */\n locale?: string;\n /**\n * Retry behavior for transient failures (network errors, and 5xx/408/425/429\n * responses on idempotent GET/HEAD requests). Pass `false` to disable retries\n * entirely. Defaults to 2 retries with exponential backoff.\n */\n retry?: RetryConfig | false;\n /**\n * Persist the stateful cart (`client.cart`) to `localStorage` so it survives\n * page reloads. Defaults to `true`. Has no effect in environments without\n * `localStorage` (e.g. Node/SSR) — the cart simply stays in-memory.\n */\n persistCart?: boolean;\n}\n\nexport interface ListParams {\n page?: number;\n limit?: number;\n search?: string;\n sort?: string;\n order?: \"asc\" | \"desc\";\n [key: string]: unknown;\n}\n\nexport interface PaginatedResponse<T> {\n data: T[];\n total: number;\n page: number;\n limit: number;\n totalPages: number;\n}\n\n// ── Product types ──\n\nexport interface Product {\n id: string;\n name: string;\n slug: string;\n description: string;\n status: string;\n price: number;\n compareAtPrice?: number;\n currency: string;\n images: ProductImage[];\n variants: ProductVariant[];\n category?: { id: string; name: string };\n brand?: { id: string; name: string };\n tags: string[];\n metadata: Record<string, unknown>;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface ProductImage {\n id: string;\n url: string;\n alt: string;\n position: number;\n}\n\nexport interface ProductVariant {\n id: string;\n name: string;\n sku: string;\n price: number;\n compareAtPrice?: number;\n inventory: number;\n options: Record<string, string>;\n}\n\n// ── Collection types ──\n\nexport interface Collection {\n id: string;\n name: string;\n slug: string;\n description: string;\n image?: string;\n productCount: number;\n}\n\n// ── Cart & Checkout types ──\n\nexport interface CheckoutLineItem {\n productId: string;\n variantId?: string;\n productName: string;\n quantity: number;\n unitPrice: number;\n imageUrl?: string;\n}\n\nexport interface CheckoutSession {\n id: string;\n status: \"open\" | \"completed\" | \"expired\";\n items: CheckoutLineItem[];\n subtotal: number;\n tax: number;\n shipping: number;\n discount: number;\n total: number;\n currency: string;\n couponCode?: string;\n}\n\nexport interface CartLine {\n id: string;\n productId: string;\n variantId?: string;\n quantity: number;\n unitPrice: number;\n productName: string;\n imageUrl?: string;\n}\n\nexport interface CartState {\n id: string;\n lines: CartLine[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface AddCartLineItemInput {\n productId: string;\n variantId?: string;\n quantity: number;\n /** Skip the `products.get` price lookup by supplying these directly */\n unitPrice?: number;\n productName?: string;\n imageUrl?: string;\n}\n\nexport interface StorefrontCart {\n readonly id: string;\n readonly lines: CartLine[];\n readonly itemCount: number;\n readonly subtotal: number;\n /** Adds a line item. Supplying `unitPrice` also requires `productName`, otherwise this falls through to a `products.get` network lookup. */\n addLineItem(input: AddCartLineItemInput): Promise<StorefrontCart>;\n updateLineItem(lineId: string, quantity: number): StorefrontCart;\n removeLineItem(lineId: string): StorefrontCart;\n clear(): StorefrontCart;\n checkout(opts?: { clearOnSuccess?: boolean }): Promise<CheckoutSession>;\n}\n\nexport interface Order {\n id: string;\n orderNumber: string;\n status: string;\n total: number;\n currency: string;\n items: OrderItem[];\n createdAt: string;\n}\n\nexport interface OrderItem {\n productId: string;\n name: string;\n quantity: number;\n price: number;\n}\n\n// ── Customer types ──\n\nexport interface Customer {\n id: string;\n email: string;\n name: string;\n phone?: string;\n createdAt: string;\n}\n\nexport interface AuthSession {\n customer: Customer;\n accessToken: string;\n refreshToken: string;\n}\n\nexport interface Address {\n id: string;\n label?: string;\n line1: string;\n line2?: string;\n city: string;\n state: string;\n postalCode: string;\n country: string;\n isDefault: boolean;\n}\n\n// ── Blog types ──\n\nexport interface BlogPost {\n id: string;\n title: string;\n slug: string;\n excerpt: string;\n content: string;\n coverImage?: string;\n tags: string[];\n publishedAt: string;\n}\n\n// ── Booking types ──\n\nexport interface BookableService {\n id: string;\n name: string;\n duration: number;\n price: number;\n description: string;\n}\n\nexport interface TimeSlot {\n start: string;\n end: string;\n available: boolean;\n}\n\nexport interface Booking {\n id: string;\n serviceId: string;\n date: string;\n startTime: string;\n endTime: string;\n status: string;\n customer: { name: string; email: string };\n}\n\n// ── Form types ──\n\nexport interface FormDefinition {\n id: string;\n title: string;\n description: string;\n fields: FormField[];\n}\n\nexport interface FormField {\n id: string;\n type: string;\n label: string;\n required: boolean;\n options?: string[];\n placeholder?: string;\n}\n\n// ── Store config ──\n\nexport interface StoreConfig {\n name: string;\n slug: string;\n logo?: string;\n theme: Record<string, unknown>;\n currency: string;\n locale: string;\n}\n\n// ── SDK Error ──\n\nexport class StorefrontError extends Error {\n status: number;\n code: string;\n details?: unknown;\n\n constructor(status: number, code: string, message: string, details?: unknown) {\n super(message);\n this.name = \"StorefrontError\";\n this.status = status;\n this.code = code;\n this.details = details;\n }\n}\n\n// ── Core client ────────────────────────────────────────────────────\n\nexport function createStorefrontClient(config: StorefrontConfig) {\n const apiUrl = (config.apiUrl ?? \"https://managesales-backend-phase1test.up.railway.app/api/v1\").replace(/\\/$/, \"\");\n const fetchFn = config.customFetch ?? globalThis.fetch.bind(globalThis);\n let accessToken: string | null = null;\n let refreshToken: string | null = null;\n\n // ── Retry configuration ──\n\n const RETRY_DEFAULTS = {\n retries: 2,\n baseDelayMs: 300,\n maxDelayMs: 4000,\n retryOnStatus: [408, 425, 429, 500, 502, 503, 504],\n };\n const rc =\n config.retry === false\n ? { ...RETRY_DEFAULTS, retries: 0 }\n : { ...RETRY_DEFAULTS, ...(config.retry || {}) };\n const IDEMPOTENT = new Set([\"GET\", \"HEAD\"]);\n const sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n function backoff(attempt: number): number {\n return Math.min(rc.maxDelayMs, Math.round(Math.random() * rc.baseDelayMs * Math.pow(2, attempt)));\n }\n\n // ── Internal helpers ──\n\n async function request<T>(\n method: string,\n path: string,\n options?: {\n body?: unknown;\n params?: Record<string, unknown>;\n auth?: boolean;\n },\n ): Promise<T> {\n const url = new URL(`${apiUrl}${path}`);\n if (options?.params) {\n for (const [k, v] of Object.entries(options.params)) {\n if (v !== undefined && v !== null) url.searchParams.set(k, String(v));\n }\n }\n\n const headers: Record<string, string> = {\n \"X-Workspace-Id\": config.workspaceId,\n };\n\n if (options?.auth && accessToken) {\n headers[\"Authorization\"] = `Bearer ${accessToken}`;\n }\n\n if (options?.body) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const fetchOptions: RequestInit = {\n method,\n headers,\n body: options?.body ? JSON.stringify(options.body) : undefined,\n };\n\n let attempt = 0;\n let res: Response;\n while (true) {\n try {\n res = await fetchFn(url.toString(), fetchOptions);\n } catch (err) {\n if (attempt < rc.retries) {\n await sleep(backoff(attempt));\n attempt++;\n continue;\n }\n throw err;\n }\n if (attempt < rc.retries && rc.retryOnStatus.includes(res.status) && IDEMPOTENT.has(method)) {\n const ra = Number(res.headers.get(\"retry-after\"));\n await sleep(Number.isFinite(ra) && ra > 0 ? ra * 1000 : backoff(attempt));\n attempt++;\n continue;\n }\n break;\n }\n\n // Auto-refresh on 401\n if (res.status === 401 && options?.auth && refreshToken) {\n const refreshed = await refreshSession();\n if (refreshed) {\n headers[\"Authorization\"] = `Bearer ${accessToken}`;\n const retry = await fetchFn(url.toString(), {\n method,\n headers,\n body: options?.body ? JSON.stringify(options.body) : undefined,\n });\n if (!retry.ok) throw await parseError(retry);\n return retry.status === 204 ? (undefined as T) : retry.json();\n }\n }\n\n if (!res.ok) throw await parseError(res);\n return res.status === 204 ? (undefined as T) : res.json();\n }\n\n async function parseError(res: Response): Promise<StorefrontError> {\n try {\n const body = await res.json();\n return new StorefrontError(\n res.status,\n body.code ?? body.error ?? \"UNKNOWN\",\n body.message ?? res.statusText,\n body,\n );\n } catch {\n return new StorefrontError(res.status, \"UNKNOWN\", res.statusText);\n }\n }\n\n async function refreshSession(): Promise<boolean> {\n if (!refreshToken) return false;\n try {\n const res = await fetchFn(`${apiUrl}/storefront/auth/refresh`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Workspace-Id\": config.workspaceId,\n },\n body: JSON.stringify({ refreshToken }),\n });\n if (!res.ok) {\n accessToken = null;\n refreshToken = null;\n return false;\n }\n const data = await res.json();\n accessToken = data.accessToken;\n refreshToken = data.refreshToken;\n return true;\n } catch {\n return false;\n }\n }\n\n // ── Resource namespaces ──────────────────────────────────────────\n\n const store = {\n /** Resolve store config by workspace (returns theme, branding, currency) */\n async resolve(): Promise<StoreConfig> {\n return request(\"GET\", \"/storefront-api/resolve\");\n },\n };\n\n const products = {\n /** List published products with pagination and filters */\n async list(params?: ListParams): Promise<PaginatedResponse<Product>> {\n return request(\"GET\", \"/storefront-api/products\", { params });\n },\n /** Get a single product by ID or slug */\n async get(idOrSlug: string): Promise<Product> {\n return request(\"GET\", `/storefront-api/products/${idOrSlug}`);\n },\n /** Search products (shorthand for list with search param) */\n async search(query: string, params?: ListParams): Promise<PaginatedResponse<Product>> {\n return request(\"GET\", \"/storefront-api/search\", { params: { ...params, q: query } });\n },\n };\n\n const collections = {\n /** List published collections */\n async list(params?: ListParams): Promise<PaginatedResponse<Collection>> {\n return request(\"GET\", \"/storefront-api/collections\", { params });\n },\n /** Get a collection with its products */\n async get(idOrSlug: string): Promise<Collection & { products: Product[] }> {\n return request(\"GET\", `/storefront-api/collections/${idOrSlug}`);\n },\n };\n\n const checkout = {\n /** Create a checkout session from cart items */\n async create(items: CheckoutLineItem[]): Promise<CheckoutSession> {\n return request(\"POST\", \"/checkout\", { body: { lines: items } });\n },\n /** Retrieve an existing checkout session */\n async get(checkoutId: string): Promise<CheckoutSession> {\n return request(\"GET\", `/checkout/${checkoutId}`);\n },\n /** Apply a coupon or discount code */\n async applyCoupon(checkoutId: string, couponCode: string): Promise<CheckoutSession> {\n return request(\"POST\", `/checkout/${checkoutId}/coupon`, { body: { couponCode } });\n },\n /** Complete checkout — process payment and create order */\n async complete(checkoutId: string, payment?: Record<string, unknown>): Promise<Order> {\n return request(\"POST\", `/checkout/${checkoutId}/complete`, { body: payment });\n },\n };\n\n const auth = {\n /** Register a new customer account */\n async register(data: {\n email: string;\n password: string;\n name: string;\n phone?: string;\n }): Promise<AuthSession> {\n const session = await request<AuthSession>(\"POST\", \"/storefront/auth/register\", { body: data });\n accessToken = session.accessToken;\n refreshToken = session.refreshToken;\n return session;\n },\n /** Log in with email + password */\n async login(email: string, password: string): Promise<AuthSession> {\n const session = await request<AuthSession>(\"POST\", \"/storefront/auth/login\", {\n body: { email, password },\n });\n accessToken = session.accessToken;\n refreshToken = session.refreshToken;\n return session;\n },\n /** Log in with Google ID token */\n async loginWithGoogle(idToken: string): Promise<AuthSession> {\n const session = await request<AuthSession>(\"POST\", \"/storefront/auth/google\", {\n body: { idToken },\n });\n accessToken = session.accessToken;\n refreshToken = session.refreshToken;\n return session;\n },\n /** Log out and clear local session */\n async logout(): Promise<void> {\n if (accessToken) {\n try {\n await request(\"POST\", \"/storefront/auth/logout\", { auth: true });\n } catch { /* ignore logout errors */ }\n }\n accessToken = null;\n refreshToken = null;\n },\n /** Refresh the access token */\n async refresh(): Promise<boolean> {\n return refreshSession();\n },\n /** Check if client has a valid session */\n isAuthenticated(): boolean {\n return accessToken !== null;\n },\n /** Manually set tokens (e.g., from SSR or cookie restoration) */\n setTokens(access: string, refresh: string): void {\n accessToken = access;\n refreshToken = refresh;\n },\n };\n\n const customer = {\n /** Get current customer profile */\n async me(): Promise<Customer> {\n return request(\"GET\", \"/storefront/auth/me\", { auth: true });\n },\n /** Get customer's order history */\n async orders(params?: ListParams): Promise<PaginatedResponse<Order>> {\n const me = await request<Customer>(\"GET\", \"/storefront/auth/me\", { auth: true });\n return request(\"GET\", `/storefront-api/customer/${me.id}/orders`, { params, auth: true });\n },\n /** Get customer's saved addresses */\n async addresses(): Promise<Address[]> {\n const me = await request<Customer>(\"GET\", \"/storefront/auth/me\", { auth: true });\n return request(\"GET\", `/storefront-api/customer/${me.id}/addresses`, { auth: true });\n },\n };\n\n const blog = {\n /** List published blog posts */\n async list(params?: ListParams & { tags?: string }): Promise<PaginatedResponse<BlogPost>> {\n return request(\"GET\", \"/storefront-api/blog/posts\", { params });\n },\n /** Get a blog post by slug */\n async get(slug: string): Promise<BlogPost> {\n return request(\"GET\", `/storefront-api/blog/posts/${slug}`);\n },\n };\n\n const bookings = {\n /** List bookable services */\n async services(): Promise<BookableService[]> {\n return request(\"GET\", \"/bookings-public/services\");\n },\n /** List bookable staff */\n async staff(): Promise<Array<{ id: string; name: string; avatar?: string }>> {\n return request(\"GET\", \"/bookings-public/staff\");\n },\n /** Check available time slots */\n async availability(params: {\n serviceId: string;\n date: string;\n staffId?: string;\n }): Promise<TimeSlot[]> {\n return request(\"GET\", \"/bookings-public/availability\", { params });\n },\n /** Create a booking */\n async book(data: {\n serviceId: string;\n date: string;\n startTime: string;\n staffId?: string;\n customer: { name: string; email: string; phone?: string };\n }): Promise<Booking> {\n return request(\"POST\", \"/bookings-public/book\", { body: data });\n },\n };\n\n const forms = {\n /** Get a published form by ID or slug */\n async get(idOrSlug: string): Promise<FormDefinition> {\n return request(\"GET\", `/public/forms/${idOrSlug}`);\n },\n /** Submit form response */\n async submit(formId: string, data: Record<string, unknown>): Promise<{ id: string }> {\n return request(\"POST\", `/public/forms/${formId}/submit`, { body: data });\n },\n /** Upload file for a form file field */\n async uploadFile(formId: string, file: File): Promise<{ url: string }> {\n const formData = new FormData();\n formData.append(\"file\", file);\n const res = await fetchFn(`${apiUrl}/public/forms/${formId}/upload`, {\n method: \"POST\",\n headers: { \"X-Workspace-Id\": config.workspaceId },\n body: formData,\n });\n if (!res.ok) throw await parseError(res);\n return res.json();\n },\n };\n\n // ── Stateful cart (client-side, localStorage-persisted) ──\n\n const CART_KEY = \"managesales_cart_\" + config.workspaceId;\n const hasLS = () => {\n try {\n return config.persistCart !== false && typeof localStorage !== \"undefined\";\n } catch {\n return false;\n }\n };\n const loadCart = (): CartState | null => {\n if (!hasLS()) return null;\n try {\n const s = localStorage.getItem(CART_KEY);\n return s ? JSON.parse(s) : null;\n } catch {\n return null;\n }\n };\n const saveCart = (st: CartState): void => {\n if (!hasLS()) return;\n try {\n localStorage.setItem(CART_KEY, JSON.stringify(st));\n } catch {\n /* ignore persistence errors (quota, privacy mode, etc.) */\n }\n };\n let __lineSeq = 0;\n const genId = (p: string): string =>\n typeof crypto !== \"undefined\" && crypto.randomUUID ? p + crypto.randomUUID() : p + Date.now() + \"_\" + ++__lineSeq;\n const nowIso = (): string => new Date().toISOString();\n const freshCart = (): CartState => ({ id: genId(\"cart_\"), lines: [], createdAt: nowIso(), updatedAt: nowIso() });\n\n function makeCart(state: CartState): StorefrontCart {\n const persist = () => {\n state.updatedAt = nowIso();\n saveCart(state);\n };\n const cartObj: StorefrontCart = {\n get id() {\n return state.id;\n },\n get lines() {\n return state.lines;\n },\n get itemCount() {\n return state.lines.reduce((n, l) => n + l.quantity, 0);\n },\n get subtotal() {\n return state.lines.reduce((s, l) => s + l.unitPrice * l.quantity, 0);\n },\n // Supplying unitPrice alone does not skip the lookup — productName must also be\n // provided, otherwise this falls through to the products.get() network lookup below.\n async addLineItem(input: AddCartLineItemInput): Promise<StorefrontCart> {\n let line: CartLine;\n if (input.unitPrice != null && input.productName) {\n line = {\n id: genId(\"line_\"),\n productId: input.productId,\n variantId: input.variantId,\n quantity: input.quantity,\n unitPrice: input.unitPrice,\n productName: input.productName,\n imageUrl: input.imageUrl,\n };\n } else {\n const p = await products.get(input.productId);\n const v = input.variantId && Array.isArray(p.variants) ? p.variants.find((x) => x.id === input.variantId) : undefined;\n line = {\n id: genId(\"line_\"),\n productId: input.productId,\n variantId: input.variantId,\n quantity: input.quantity,\n unitPrice: v && v.price != null ? v.price : p.price,\n productName: p.name,\n imageUrl: Array.isArray(p.images) && p.images.length > 0 ? p.images[0].url : undefined,\n };\n }\n const existing = state.lines.find((l) => l.productId === line.productId && l.variantId === line.variantId);\n if (existing) existing.quantity += line.quantity;\n else state.lines.push(line);\n persist();\n return cartObj;\n },\n updateLineItem(lineId: string, quantity: number): StorefrontCart {\n const l = state.lines.find((x) => x.id === lineId);\n if (l) {\n if (quantity <= 0) state.lines = state.lines.filter((x) => x.id !== lineId);\n else l.quantity = quantity;\n persist();\n }\n return cartObj;\n },\n removeLineItem(lineId: string): StorefrontCart {\n state.lines = state.lines.filter((x) => x.id !== lineId);\n persist();\n return cartObj;\n },\n clear(): StorefrontCart {\n state.lines = [];\n persist();\n return cartObj;\n },\n async checkout(opts?: { clearOnSuccess?: boolean }): Promise<CheckoutSession> {\n const session = await checkout.create(\n state.lines.map((l) => ({\n productId: l.productId,\n variantId: l.variantId,\n productName: l.productName,\n quantity: l.quantity,\n unitPrice: l.unitPrice,\n imageUrl: l.imageUrl,\n })),\n );\n if (opts && opts.clearOnSuccess) cartObj.clear();\n return session;\n },\n };\n return cartObj;\n }\n\n const cart = {\n /** Create a new, empty cart (replaces any persisted cart) */\n create(): StorefrontCart {\n const st = freshCart();\n saveCart(st);\n return makeCart(st);\n },\n /** Get the current cart — loaded from storage if persisted, otherwise a fresh one */\n current(): StorefrontCart {\n return makeCart(loadCart() || freshCart());\n },\n /** Recover an abandoned cart by recovery token */\n async recover(token: string): Promise<CheckoutSession> {\n return request(\"GET\", `/abandoned-carts/recover/${token}`);\n },\n };\n\n // ── Alias namespaces (convenience wrappers over existing methods) ──\n\n /** Alias for `client.customer.orders` — order history for the logged-in customer */\n const orders = {\n /** Get customer's order history (delegates to `customer.orders`) */\n list: (params?: ListParams): Promise<PaginatedResponse<Order>> => customer.orders(params),\n };\n\n /** Convenience namespace bundling `auth` + `customer` under one name */\n const customers = {\n login: auth.login,\n register: auth.register,\n loginWithGoogle: auth.loginWithGoogle,\n logout: auth.logout,\n isAuthenticated: auth.isAuthenticated,\n setTokens: auth.setTokens,\n me: customer.me,\n orders: customer.orders,\n addresses: customer.addresses,\n };\n\n // ── Public API ───────────────────────────────────────────────────\n\n return {\n store,\n products,\n collections,\n checkout,\n auth,\n customer,\n blog,\n bookings,\n forms,\n cart,\n orders,\n customers,\n };\n}\n\n// ── Type export for TypeScript users ──\n\nexport type StorefrontClient = ReturnType<typeof createStorefrontClient>;\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * ManageSales Storefront SDK\n * --------------------------\n * Resource-based client for building online storefronts.\n * Works with any framework: Next.js, Remix, Nuxt, Astro, plain HTML.\n *\n * Usage:\n * import { createStorefrontClient } from \"./managesales-storefront\";\n * const client = createStorefrontClient({ workspaceId: \"<workspace_id>\" });\n * const products = await client.products.list();\n */\n\n// ── Types ──────────────────────────────────────────────────────────\n\nexport interface RetryConfig {\n /** Max retry attempts for a failed request (default: 2) */\n retries?: number;\n /** Base delay in ms used for exponential backoff (default: 300) */\n baseDelayMs?: number;\n /** Upper bound for any single backoff delay, in ms (default: 4000) */\n maxDelayMs?: number;\n /** HTTP status codes that are retried, GET/HEAD only (default: [408,425,429,500,502,503,504]) */\n retryOnStatus?: number[];\n}\n\nexport interface StorefrontConfig {\n /** Your workspace ID (required) */\n workspaceId: string;\n /** API base URL — defaults to production */\n apiUrl?: string;\n /** Custom fetch implementation (for SSR / edge) */\n customFetch?: typeof fetch;\n /** Default locale for content */\n locale?: string;\n /**\n * Retry behavior for transient failures (network errors, and 5xx/408/425/429\n * responses on idempotent GET/HEAD requests). Pass `false` to disable retries\n * entirely. Defaults to 2 retries with exponential backoff.\n */\n retry?: RetryConfig | false;\n /**\n * Persist the stateful cart (`client.cart`) to `localStorage` so it survives\n * page reloads. Defaults to `true`. Has no effect in environments without\n * `localStorage` (e.g. Node/SSR) — the cart simply stays in-memory.\n */\n persistCart?: boolean;\n}\n\nexport interface ListParams {\n page?: number;\n limit?: number;\n search?: string;\n sort?: string;\n order?: \"asc\" | \"desc\";\n [key: string]: unknown;\n}\n\nexport interface PaginatedResponse<T> {\n data: T[];\n total: number;\n page: number;\n limit: number;\n totalPages: number;\n}\n\n// ── Product types ──\n\nexport interface Product {\n id: string;\n name: string;\n slug: string;\n description: string;\n status: string;\n price: number;\n compareAtPrice?: number;\n currency: string;\n images: ProductImage[];\n variants: ProductVariant[];\n category?: { id: string; name: string };\n brand?: { id: string; name: string };\n tags: string[];\n metadata: Record<string, unknown>;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface ProductImage {\n id: string;\n url: string;\n alt: string;\n position: number;\n}\n\nexport interface ProductVariant {\n id: string;\n name: string;\n sku: string;\n price: number;\n compareAtPrice?: number;\n inventory: number;\n options: Record<string, string>;\n}\n\n// ── Collection types ──\n\nexport interface Collection {\n id: string;\n name: string;\n slug: string;\n description: string;\n image?: string;\n productCount: number;\n}\n\n// ── Cart & Checkout types ──\n\nexport interface CheckoutLineItem {\n productId: string;\n variantId?: string;\n productName: string;\n quantity: number;\n unitPrice: number;\n imageUrl?: string;\n}\n\nexport interface CheckoutSessionLine {\n productId?: string;\n variantId?: string;\n productName: string;\n sku?: string;\n imageUrl?: string;\n quantity: number;\n unitPrice: number;\n}\n\nexport interface ShippingMethod {\n id: string;\n name: string;\n price: number;\n estimatedDays?: string;\n}\n\nexport interface CheckoutShippingAddress {\n name?: string;\n phone?: string;\n address?: string;\n city?: string;\n region?: string;\n country?: string;\n postalCode?: string;\n}\n\nexport interface CheckoutSession {\n id: string;\n status: \"open\" | \"completed\" | \"expired\";\n lines: CheckoutSessionLine[];\n subtotal: number;\n discountAmount: number;\n discountCode?: string;\n discountLabel?: string;\n taxAmount: number;\n taxLabel?: string;\n shippingAmount: number;\n shippingMethodId?: string;\n shippingMethodName?: string;\n shipping?: CheckoutShippingAddress;\n giftCardAmount?: number;\n giftCardCode?: string;\n availableShippingMethods?: ShippingMethod[];\n total: number;\n currency: string;\n createdAt?: string;\n /** @deprecated Never populated by the API — use `lines` */\n items?: CheckoutLineItem[];\n /** @deprecated Never populated by the API — use `taxAmount` */\n tax?: number;\n /** @deprecated Never populated by the API — use `discountAmount` */\n discount?: number;\n /** @deprecated Never populated by the API — use `discountCode` */\n couponCode?: string;\n}\n\nexport interface CartLine {\n id: string;\n productId: string;\n variantId?: string;\n quantity: number;\n unitPrice: number;\n productName: string;\n imageUrl?: string;\n}\n\nexport interface CartState {\n id: string;\n lines: CartLine[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface AddCartLineItemInput {\n productId: string;\n variantId?: string;\n quantity: number;\n /** Skip the `products.get` price lookup by supplying these directly */\n unitPrice?: number;\n productName?: string;\n imageUrl?: string;\n}\n\nexport interface StorefrontCart {\n readonly id: string;\n readonly lines: CartLine[];\n readonly itemCount: number;\n readonly subtotal: number;\n /** Adds a line item. Supplying `unitPrice` also requires `productName`, otherwise this falls through to a `products.get` network lookup. */\n addLineItem(input: AddCartLineItemInput): Promise<StorefrontCart>;\n updateLineItem(lineId: string, quantity: number): StorefrontCart;\n removeLineItem(lineId: string): StorefrontCart;\n clear(): StorefrontCart;\n checkout(opts?: { clearOnSuccess?: boolean; couponCode?: string }): Promise<CheckoutSession>;\n}\n\nexport interface Order {\n id: string;\n orderNumber: string;\n status: string;\n total: number;\n currency: string;\n items: OrderItem[];\n createdAt: string;\n}\n\nexport interface OrderItem {\n productId: string;\n name: string;\n quantity: number;\n price: number;\n}\n\n// ── Discount types ──\n\nexport interface DiscountValidationInput {\n /** Cart subtotal; omit when supplying `items` */\n subtotal?: number;\n items?: Array<{ productId?: string; variantId?: string; quantity: number; unitPrice: number }>;\n /** Known customer id — enables per-customer limit checks */\n customerId?: string;\n}\n\nexport interface DiscountValidationResult {\n valid: boolean;\n discountId?: string;\n code?: string;\n label?: string;\n amount?: number;\n freeShipping?: boolean;\n /** Present when `valid` is false — customer-safe explanation */\n reason?: string;\n}\n\nexport interface AutomaticPromotion {\n id: string;\n title: string;\n type: \"percentage\" | \"fixed_amount\" | \"buy_x_get_y\" | \"free_shipping\";\n value: number;\n minOrderAmount?: number | null;\n minQuantity?: number | null;\n endsAt?: string | null;\n}\n\nexport interface CreateCheckoutOptions {\n /** Coupon code applied server-side at session creation */\n couponCode?: string;\n}\n\n// ── Customer types ──\n\nexport interface Customer {\n id: string;\n email: string;\n name: string;\n phone?: string;\n createdAt: string;\n}\n\nexport interface AuthSession {\n customer: Customer;\n accessToken: string;\n refreshToken: string;\n}\n\nexport interface Address {\n id: string;\n label?: string;\n line1: string;\n line2?: string;\n city: string;\n state: string;\n postalCode: string;\n country: string;\n isDefault: boolean;\n}\n\n// ── Blog types ──\n\nexport interface BlogPost {\n id: string;\n title: string;\n slug: string;\n excerpt: string;\n content: string;\n coverImage?: string;\n tags: string[];\n publishedAt: string;\n}\n\n// ── Booking types ──\n\nexport interface BookableService {\n id: string;\n name: string;\n duration: number;\n price: number;\n description: string;\n}\n\nexport interface TimeSlot {\n start: string;\n end: string;\n available: boolean;\n}\n\nexport interface Booking {\n id: string;\n serviceId: string;\n date: string;\n startTime: string;\n endTime: string;\n status: string;\n customer: { name: string; email: string };\n}\n\n// ── Form types ──\n\nexport interface FormDefinition {\n id: string;\n title: string;\n description: string;\n fields: FormField[];\n}\n\nexport interface FormField {\n id: string;\n type: string;\n label: string;\n required: boolean;\n options?: string[];\n placeholder?: string;\n}\n\n// ── Store config ──\n\nexport interface StoreConfig {\n name: string;\n slug: string;\n logo?: string;\n theme: Record<string, unknown>;\n currency: string;\n locale: string;\n}\n\n// ── SDK Error ──\n\nexport class StorefrontError extends Error {\n status: number;\n code: string;\n details?: unknown;\n\n constructor(status: number, code: string, message: string, details?: unknown) {\n super(message);\n this.name = \"StorefrontError\";\n this.status = status;\n this.code = code;\n this.details = details;\n }\n}\n\n// ── Core client ────────────────────────────────────────────────────\n\nexport function createStorefrontClient(config: StorefrontConfig) {\n const apiUrl = (config.apiUrl ?? \"https://managesales-backend-phase1test.up.railway.app/api/v1\").replace(/\\/$/, \"\");\n const fetchFn = config.customFetch ?? globalThis.fetch.bind(globalThis);\n let accessToken: string | null = null;\n let refreshToken: string | null = null;\n\n // ── Retry configuration ──\n\n const RETRY_DEFAULTS = {\n retries: 2,\n baseDelayMs: 300,\n maxDelayMs: 4000,\n retryOnStatus: [408, 425, 429, 500, 502, 503, 504],\n };\n const rc =\n config.retry === false\n ? { ...RETRY_DEFAULTS, retries: 0 }\n : { ...RETRY_DEFAULTS, ...(config.retry || {}) };\n const IDEMPOTENT = new Set([\"GET\", \"HEAD\"]);\n const sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n function backoff(attempt: number): number {\n return Math.min(rc.maxDelayMs, Math.round(Math.random() * rc.baseDelayMs * Math.pow(2, attempt)));\n }\n\n // ── Internal helpers ──\n\n async function request<T>(\n method: string,\n path: string,\n options?: {\n body?: unknown;\n params?: Record<string, unknown>;\n auth?: boolean;\n },\n ): Promise<T> {\n const url = new URL(`${apiUrl}${path}`);\n if (options?.params) {\n for (const [k, v] of Object.entries(options.params)) {\n if (v !== undefined && v !== null) url.searchParams.set(k, String(v));\n }\n }\n\n const headers: Record<string, string> = {\n \"X-Workspace-Id\": config.workspaceId,\n };\n\n if (options?.auth && accessToken) {\n headers[\"Authorization\"] = `Bearer ${accessToken}`;\n }\n\n if (options?.body) {\n headers[\"Content-Type\"] = \"application/json\";\n }\n\n const fetchOptions: RequestInit = {\n method,\n headers,\n body: options?.body ? JSON.stringify(options.body) : undefined,\n };\n\n let attempt = 0;\n let res: Response;\n while (true) {\n try {\n res = await fetchFn(url.toString(), fetchOptions);\n } catch (err) {\n if (attempt < rc.retries) {\n await sleep(backoff(attempt));\n attempt++;\n continue;\n }\n throw err;\n }\n if (attempt < rc.retries && rc.retryOnStatus.includes(res.status) && IDEMPOTENT.has(method)) {\n const ra = Number(res.headers.get(\"retry-after\"));\n await sleep(Number.isFinite(ra) && ra > 0 ? ra * 1000 : backoff(attempt));\n attempt++;\n continue;\n }\n break;\n }\n\n // Auto-refresh on 401\n if (res.status === 401 && options?.auth && refreshToken) {\n const refreshed = await refreshSession();\n if (refreshed) {\n headers[\"Authorization\"] = `Bearer ${accessToken}`;\n const retry = await fetchFn(url.toString(), {\n method,\n headers,\n body: options?.body ? JSON.stringify(options.body) : undefined,\n });\n if (!retry.ok) throw await parseError(retry);\n return retry.status === 204 ? (undefined as T) : retry.json();\n }\n }\n\n if (!res.ok) throw await parseError(res);\n return res.status === 204 ? (undefined as T) : res.json();\n }\n\n async function parseError(res: Response): Promise<StorefrontError> {\n try {\n const body = await res.json();\n return new StorefrontError(\n res.status,\n body.code ?? body.error ?? \"UNKNOWN\",\n body.message ?? res.statusText,\n body,\n );\n } catch {\n return new StorefrontError(res.status, \"UNKNOWN\", res.statusText);\n }\n }\n\n async function refreshSession(): Promise<boolean> {\n if (!refreshToken) return false;\n try {\n const res = await fetchFn(`${apiUrl}/storefront/auth/refresh`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Workspace-Id\": config.workspaceId,\n },\n body: JSON.stringify({ refreshToken }),\n });\n if (!res.ok) {\n accessToken = null;\n refreshToken = null;\n return false;\n }\n const data = await res.json();\n accessToken = data.accessToken;\n refreshToken = data.refreshToken;\n return true;\n } catch {\n return false;\n }\n }\n\n // ── Resource namespaces ──────────────────────────────────────────\n\n const store = {\n /** Resolve store config by workspace (returns theme, branding, currency) */\n async resolve(): Promise<StoreConfig> {\n return request(\"GET\", \"/storefront-api/resolve\");\n },\n };\n\n const products = {\n /** List published products with pagination and filters */\n async list(params?: ListParams): Promise<PaginatedResponse<Product>> {\n return request(\"GET\", \"/storefront-api/products\", { params });\n },\n /** Get a single product by ID or slug */\n async get(idOrSlug: string): Promise<Product> {\n return request(\"GET\", `/storefront-api/products/${idOrSlug}`);\n },\n /** Search products (shorthand for list with search param) */\n async search(query: string, params?: ListParams): Promise<PaginatedResponse<Product>> {\n return request(\"GET\", \"/storefront-api/search\", { params: { ...params, q: query } });\n },\n };\n\n const collections = {\n /** List published collections */\n async list(params?: ListParams): Promise<PaginatedResponse<Collection>> {\n return request(\"GET\", \"/storefront-api/collections\", { params });\n },\n /** Get a collection with its products */\n async get(idOrSlug: string): Promise<Collection & { products: Product[] }> {\n return request(\"GET\", `/storefront-api/collections/${idOrSlug}`);\n },\n };\n\n const discounts = {\n /** Preview a discount code against a cart before checkout. Never consumes usage. */\n async validate(code: string, input?: DiscountValidationInput): Promise<DiscountValidationResult> {\n return request(\"POST\", \"/storefront-api/discounts/validate\", { body: { code, ...(input || {}) } });\n },\n /** Active automatic promotions for display (codes are never exposed) */\n async automatic(): Promise<AutomaticPromotion[]> {\n return request(\"GET\", \"/storefront-api/discounts/automatic\");\n },\n };\n\n const checkout = {\n /** Create a checkout session from cart items */\n async create(items: CheckoutLineItem[], opts?: CreateCheckoutOptions): Promise<CheckoutSession> {\n const body: Record<string, unknown> = { lines: items };\n if (opts && opts.couponCode) body.couponCode = opts.couponCode;\n return request(\"POST\", \"/checkout\", { body });\n },\n /** Retrieve an existing checkout session */\n async get(checkoutId: string): Promise<CheckoutSession> {\n return request(\"GET\", `/checkout/${checkoutId}`);\n },\n /** Apply a coupon or discount code */\n async applyCoupon(checkoutId: string, couponCode: string): Promise<CheckoutSession> {\n return request(\"POST\", `/checkout/${checkoutId}/coupon`, { body: { code: couponCode } });\n },\n /** Apply a gift card to the checkout */\n async applyGiftCard(checkoutId: string, code: string): Promise<CheckoutSession> {\n return request(\"POST\", `/checkout/${checkoutId}/gift-card`, { body: { code } });\n },\n /** Complete checkout — process payment and create order */\n async complete(checkoutId: string, payment?: Record<string, unknown>): Promise<Order> {\n return request(\"POST\", `/checkout/${checkoutId}/complete`, { body: payment });\n },\n };\n\n const auth = {\n /** Register a new customer account */\n async register(data: {\n email: string;\n password: string;\n name: string;\n phone?: string;\n }): Promise<AuthSession> {\n const session = await request<AuthSession>(\"POST\", \"/storefront/auth/register\", { body: data });\n accessToken = session.accessToken;\n refreshToken = session.refreshToken;\n return session;\n },\n /** Log in with email + password */\n async login(email: string, password: string): Promise<AuthSession> {\n const session = await request<AuthSession>(\"POST\", \"/storefront/auth/login\", {\n body: { email, password },\n });\n accessToken = session.accessToken;\n refreshToken = session.refreshToken;\n return session;\n },\n /** Log in with Google ID token */\n async loginWithGoogle(idToken: string): Promise<AuthSession> {\n const session = await request<AuthSession>(\"POST\", \"/storefront/auth/google\", {\n body: { idToken },\n });\n accessToken = session.accessToken;\n refreshToken = session.refreshToken;\n return session;\n },\n /** Log out and clear local session */\n async logout(): Promise<void> {\n if (accessToken) {\n try {\n await request(\"POST\", \"/storefront/auth/logout\", { auth: true });\n } catch { /* ignore logout errors */ }\n }\n accessToken = null;\n refreshToken = null;\n },\n /** Refresh the access token */\n async refresh(): Promise<boolean> {\n return refreshSession();\n },\n /** Check if client has a valid session */\n isAuthenticated(): boolean {\n return accessToken !== null;\n },\n /** Manually set tokens (e.g., from SSR or cookie restoration) */\n setTokens(access: string, refresh: string): void {\n accessToken = access;\n refreshToken = refresh;\n },\n };\n\n const customer = {\n /** Get current customer profile */\n async me(): Promise<Customer> {\n return request(\"GET\", \"/storefront/auth/me\", { auth: true });\n },\n /** Get customer's order history */\n async orders(params?: ListParams): Promise<PaginatedResponse<Order>> {\n const me = await request<Customer>(\"GET\", \"/storefront/auth/me\", { auth: true });\n return request(\"GET\", `/storefront-api/customer/${me.id}/orders`, { params, auth: true });\n },\n /** Get customer's saved addresses */\n async addresses(): Promise<Address[]> {\n const me = await request<Customer>(\"GET\", \"/storefront/auth/me\", { auth: true });\n return request(\"GET\", `/storefront-api/customer/${me.id}/addresses`, { auth: true });\n },\n };\n\n const blog = {\n /** List published blog posts */\n async list(params?: ListParams & { tags?: string }): Promise<PaginatedResponse<BlogPost>> {\n return request(\"GET\", \"/storefront-api/blog/posts\", { params });\n },\n /** Get a blog post by slug */\n async get(slug: string): Promise<BlogPost> {\n return request(\"GET\", `/storefront-api/blog/posts/${slug}`);\n },\n };\n\n const bookings = {\n /** List bookable services */\n async services(): Promise<BookableService[]> {\n return request(\"GET\", \"/bookings-public/services\");\n },\n /** List bookable staff */\n async staff(): Promise<Array<{ id: string; name: string; avatar?: string }>> {\n return request(\"GET\", \"/bookings-public/staff\");\n },\n /** Check available time slots */\n async availability(params: {\n serviceId: string;\n date: string;\n staffId?: string;\n }): Promise<TimeSlot[]> {\n return request(\"GET\", \"/bookings-public/availability\", { params });\n },\n /** Create a booking */\n async book(data: {\n serviceId: string;\n date: string;\n startTime: string;\n staffId?: string;\n customer: { name: string; email: string; phone?: string };\n }): Promise<Booking> {\n return request(\"POST\", \"/bookings-public/book\", { body: data });\n },\n };\n\n const forms = {\n /** Get a published form by ID or slug */\n async get(idOrSlug: string): Promise<FormDefinition> {\n return request(\"GET\", `/public/forms/${idOrSlug}`);\n },\n /** Submit form response */\n async submit(formId: string, data: Record<string, unknown>): Promise<{ id: string }> {\n return request(\"POST\", `/public/forms/${formId}/submit`, { body: data });\n },\n /** Upload file for a form file field */\n async uploadFile(formId: string, file: File): Promise<{ url: string }> {\n const formData = new FormData();\n formData.append(\"file\", file);\n const res = await fetchFn(`${apiUrl}/public/forms/${formId}/upload`, {\n method: \"POST\",\n headers: { \"X-Workspace-Id\": config.workspaceId },\n body: formData,\n });\n if (!res.ok) throw await parseError(res);\n return res.json();\n },\n };\n\n // ── Stateful cart (client-side, localStorage-persisted) ──\n\n const CART_KEY = \"managesales_cart_\" + config.workspaceId;\n const hasLS = () => {\n try {\n return config.persistCart !== false && typeof localStorage !== \"undefined\";\n } catch {\n return false;\n }\n };\n const loadCart = (): CartState | null => {\n if (!hasLS()) return null;\n try {\n const s = localStorage.getItem(CART_KEY);\n return s ? JSON.parse(s) : null;\n } catch {\n return null;\n }\n };\n const saveCart = (st: CartState): void => {\n if (!hasLS()) return;\n try {\n localStorage.setItem(CART_KEY, JSON.stringify(st));\n } catch {\n /* ignore persistence errors (quota, privacy mode, etc.) */\n }\n };\n let __lineSeq = 0;\n const genId = (p: string): string =>\n typeof crypto !== \"undefined\" && crypto.randomUUID ? p + crypto.randomUUID() : p + Date.now() + \"_\" + ++__lineSeq;\n const nowIso = (): string => new Date().toISOString();\n const freshCart = (): CartState => ({ id: genId(\"cart_\"), lines: [], createdAt: nowIso(), updatedAt: nowIso() });\n\n function makeCart(state: CartState): StorefrontCart {\n const persist = () => {\n state.updatedAt = nowIso();\n saveCart(state);\n };\n const cartObj: StorefrontCart = {\n get id() {\n return state.id;\n },\n get lines() {\n return state.lines;\n },\n get itemCount() {\n return state.lines.reduce((n, l) => n + l.quantity, 0);\n },\n get subtotal() {\n return state.lines.reduce((s, l) => s + l.unitPrice * l.quantity, 0);\n },\n // Supplying unitPrice alone does not skip the lookup — productName must also be\n // provided, otherwise this falls through to the products.get() network lookup below.\n async addLineItem(input: AddCartLineItemInput): Promise<StorefrontCart> {\n let line: CartLine;\n if (input.unitPrice != null && input.productName) {\n line = {\n id: genId(\"line_\"),\n productId: input.productId,\n variantId: input.variantId,\n quantity: input.quantity,\n unitPrice: input.unitPrice,\n productName: input.productName,\n imageUrl: input.imageUrl,\n };\n } else {\n const p = await products.get(input.productId);\n const v = input.variantId && Array.isArray(p.variants) ? p.variants.find((x) => x.id === input.variantId) : undefined;\n line = {\n id: genId(\"line_\"),\n productId: input.productId,\n variantId: input.variantId,\n quantity: input.quantity,\n unitPrice: v && v.price != null ? v.price : p.price,\n productName: p.name,\n imageUrl: Array.isArray(p.images) && p.images.length > 0 ? p.images[0].url : undefined,\n };\n }\n const existing = state.lines.find((l) => l.productId === line.productId && l.variantId === line.variantId);\n if (existing) existing.quantity += line.quantity;\n else state.lines.push(line);\n persist();\n return cartObj;\n },\n updateLineItem(lineId: string, quantity: number): StorefrontCart {\n const l = state.lines.find((x) => x.id === lineId);\n if (l) {\n if (quantity <= 0) state.lines = state.lines.filter((x) => x.id !== lineId);\n else l.quantity = quantity;\n persist();\n }\n return cartObj;\n },\n removeLineItem(lineId: string): StorefrontCart {\n state.lines = state.lines.filter((x) => x.id !== lineId);\n persist();\n return cartObj;\n },\n clear(): StorefrontCart {\n state.lines = [];\n persist();\n return cartObj;\n },\n async checkout(opts?: { clearOnSuccess?: boolean; couponCode?: string }): Promise<CheckoutSession> {\n const session = await checkout.create(\n state.lines.map((l) => ({\n productId: l.productId,\n variantId: l.variantId,\n productName: l.productName,\n quantity: l.quantity,\n unitPrice: l.unitPrice,\n imageUrl: l.imageUrl,\n })),\n opts && opts.couponCode ? { couponCode: opts.couponCode } : undefined,\n );\n if (opts && opts.clearOnSuccess) cartObj.clear();\n return session;\n },\n };\n return cartObj;\n }\n\n const cart = {\n /** Create a new, empty cart (replaces any persisted cart) */\n create(): StorefrontCart {\n const st = freshCart();\n saveCart(st);\n return makeCart(st);\n },\n /** Get the current cart — loaded from storage if persisted, otherwise a fresh one */\n current(): StorefrontCart {\n return makeCart(loadCart() || freshCart());\n },\n /** Recover an abandoned cart by recovery token */\n async recover(token: string): Promise<CheckoutSession> {\n return request(\"GET\", `/abandoned-carts/recover/${token}`);\n },\n };\n\n // ── Alias namespaces (convenience wrappers over existing methods) ──\n\n /** Alias for `client.customer.orders` — order history for the logged-in customer */\n const orders = {\n /** Get customer's order history (delegates to `customer.orders`) */\n list: (params?: ListParams): Promise<PaginatedResponse<Order>> => customer.orders(params),\n };\n\n /** Convenience namespace bundling `auth` + `customer` under one name */\n const customers = {\n login: auth.login,\n register: auth.register,\n loginWithGoogle: auth.loginWithGoogle,\n logout: auth.logout,\n isAuthenticated: auth.isAuthenticated,\n setTokens: auth.setTokens,\n me: customer.me,\n orders: customer.orders,\n addresses: customer.addresses,\n };\n\n // ── Public API ───────────────────────────────────────────────────\n\n return {\n store,\n products,\n collections,\n discounts,\n checkout,\n auth,\n customer,\n blog,\n bookings,\n forms,\n cart,\n orders,\n customers,\n };\n}\n\n// ── Type export for TypeScript users ──\n\nexport type StorefrontClient = ReturnType<typeof createStorefrontClient>;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@managesales/storefront",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Resource-based TypeScript client for building storefronts on the ManageSales Storefront API. Zero runtime dependencies, built-in auth and token refresh.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",