@putiikkipalvelu/storefront-sdk 0.2.2 → 0.2.3
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/dist/index.cjs +55 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -10
- package/dist/index.d.ts +32 -10
- package/dist/index.js +44 -21
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -611,13 +611,19 @@ function createCartResource(fetcher) {
|
|
|
611
611
|
}
|
|
612
612
|
|
|
613
613
|
// src/resources/shipping.ts
|
|
614
|
+
function calculateCartWeight(items) {
|
|
615
|
+
return items.reduce((total, item) => {
|
|
616
|
+
const itemWeight = _nullishCoalesce(_nullishCoalesce(_optionalChain([item, 'access', _8 => _8.variation, 'optionalAccess', _9 => _9.weight]), () => ( item.product.weight)), () => ( 0.5));
|
|
617
|
+
return total + itemWeight * item.cartQuantity;
|
|
618
|
+
}, 0);
|
|
619
|
+
}
|
|
614
620
|
function createShippingResource(fetcher) {
|
|
615
621
|
return {
|
|
616
622
|
/**
|
|
617
623
|
* Get all available shipment methods for the store.
|
|
618
624
|
* Returns methods without pickup locations - use `getWithLocations` for postal code specific data.
|
|
619
625
|
*
|
|
620
|
-
* @param options - Fetch options
|
|
626
|
+
* @param options - Fetch options including optional cartItems for weight-based filtering
|
|
621
627
|
* @returns Available shipment methods
|
|
622
628
|
*
|
|
623
629
|
* @example
|
|
@@ -628,22 +634,34 @@ function createShippingResource(fetcher) {
|
|
|
628
634
|
* console.log(`${method.name}: ${method.price / 100}€`);
|
|
629
635
|
* });
|
|
630
636
|
* ```
|
|
637
|
+
*
|
|
638
|
+
* @example Weight-based filtering
|
|
639
|
+
* ```typescript
|
|
640
|
+
* // Pass cart items - SDK calculates weight automatically
|
|
641
|
+
* const { shipmentMethods } = await client.shipping.getMethods({
|
|
642
|
+
* cartItems: cartItems
|
|
643
|
+
* });
|
|
644
|
+
* ```
|
|
631
645
|
*/
|
|
632
646
|
async getMethods(options) {
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
647
|
+
const params = new URLSearchParams();
|
|
648
|
+
if (_optionalChain([options, 'optionalAccess', _10 => _10.cartItems, 'optionalAccess', _11 => _11.length])) {
|
|
649
|
+
const cartWeight = calculateCartWeight(options.cartItems);
|
|
650
|
+
params.set("cartWeight", cartWeight.toString());
|
|
651
|
+
}
|
|
652
|
+
const queryString = params.toString();
|
|
653
|
+
const url = `/api/storefront/v1/shipment-methods${queryString ? `?${queryString}` : ""}`;
|
|
654
|
+
return fetcher.request(url, {
|
|
655
|
+
method: "GET",
|
|
656
|
+
...options
|
|
657
|
+
});
|
|
640
658
|
},
|
|
641
659
|
/**
|
|
642
660
|
* Get shipment methods with pickup locations for a specific postal code.
|
|
643
661
|
* Calls the Shipit API to fetch nearby pickup points (parcel lockers, etc.)
|
|
644
662
|
*
|
|
645
663
|
* @param postalCode - Customer's postal code (e.g., "00100")
|
|
646
|
-
* @param options - Fetch options
|
|
664
|
+
* @param options - Fetch options including optional cartItems for weight-based filtering
|
|
647
665
|
* @returns Shipment methods and nearby pickup locations with pricing
|
|
648
666
|
*
|
|
649
667
|
* @example
|
|
@@ -659,23 +677,28 @@ function createShippingResource(fetcher) {
|
|
|
659
677
|
* });
|
|
660
678
|
* ```
|
|
661
679
|
*
|
|
662
|
-
* @example
|
|
680
|
+
* @example Weight-based filtering with postal code
|
|
663
681
|
* ```typescript
|
|
664
|
-
* const { pricedLocations } = await client.shipping.getWithLocations(
|
|
665
|
-
*
|
|
666
|
-
*
|
|
667
|
-
* loc => loc.carrier === "Posti"
|
|
682
|
+
* const { shipmentMethods, pricedLocations } = await client.shipping.getWithLocations(
|
|
683
|
+
* "00100",
|
|
684
|
+
* { cartItems: cartItems }
|
|
668
685
|
* );
|
|
686
|
+
*
|
|
687
|
+
* // Only shows methods that support the cart's total weight
|
|
669
688
|
* ```
|
|
670
689
|
*/
|
|
671
690
|
async getWithLocations(postalCode, options) {
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
)
|
|
691
|
+
const params = new URLSearchParams();
|
|
692
|
+
if (_optionalChain([options, 'optionalAccess', _12 => _12.cartItems, 'optionalAccess', _13 => _13.length])) {
|
|
693
|
+
const cartWeight = calculateCartWeight(options.cartItems);
|
|
694
|
+
params.set("cartWeight", cartWeight.toString());
|
|
695
|
+
}
|
|
696
|
+
const queryString = params.toString();
|
|
697
|
+
const url = `/api/storefront/v1/shipment-methods/${encodeURIComponent(postalCode)}${queryString ? `?${queryString}` : ""}`;
|
|
698
|
+
return fetcher.request(url, {
|
|
699
|
+
method: "GET",
|
|
700
|
+
...options
|
|
701
|
+
});
|
|
679
702
|
}
|
|
680
703
|
};
|
|
681
704
|
}
|
|
@@ -753,7 +776,7 @@ function createCustomerResource(fetcher) {
|
|
|
753
776
|
*/
|
|
754
777
|
async login(email, password, options, fetchOptions) {
|
|
755
778
|
const headers = {};
|
|
756
|
-
if (_optionalChain([options, 'optionalAccess',
|
|
779
|
+
if (_optionalChain([options, 'optionalAccess', _14 => _14.cartId])) {
|
|
757
780
|
headers["x-cart-id"] = options.cartId;
|
|
758
781
|
}
|
|
759
782
|
return fetcher.request(
|
|
@@ -1222,10 +1245,10 @@ function createOrderResource(fetcher) {
|
|
|
1222
1245
|
function createCheckoutResource(fetcher) {
|
|
1223
1246
|
function buildCheckoutHeaders(options) {
|
|
1224
1247
|
const headers = {};
|
|
1225
|
-
if (_optionalChain([options, 'optionalAccess',
|
|
1248
|
+
if (_optionalChain([options, 'optionalAccess', _15 => _15.cartId])) {
|
|
1226
1249
|
headers["x-cart-id"] = options.cartId;
|
|
1227
1250
|
}
|
|
1228
|
-
if (_optionalChain([options, 'optionalAccess',
|
|
1251
|
+
if (_optionalChain([options, 'optionalAccess', _16 => _16.sessionId])) {
|
|
1229
1252
|
headers["x-session-id"] = options.sessionId;
|
|
1230
1253
|
}
|
|
1231
1254
|
return headers;
|
|
@@ -1289,7 +1312,7 @@ function createCheckoutResource(fetcher) {
|
|
|
1289
1312
|
method: "POST",
|
|
1290
1313
|
body,
|
|
1291
1314
|
headers: {
|
|
1292
|
-
..._optionalChain([options, 'optionalAccess',
|
|
1315
|
+
..._optionalChain([options, 'optionalAccess', _17 => _17.headers]),
|
|
1293
1316
|
...headers
|
|
1294
1317
|
},
|
|
1295
1318
|
...options
|
|
@@ -1367,7 +1390,7 @@ function createCheckoutResource(fetcher) {
|
|
|
1367
1390
|
method: "POST",
|
|
1368
1391
|
body,
|
|
1369
1392
|
headers: {
|
|
1370
|
-
..._optionalChain([options, 'optionalAccess',
|
|
1393
|
+
..._optionalChain([options, 'optionalAccess', _18 => _18.headers]),
|
|
1371
1394
|
...headers
|
|
1372
1395
|
},
|
|
1373
1396
|
...options
|
|
@@ -1458,7 +1481,7 @@ function calculateCartWithCampaigns(items, campaigns) {
|
|
|
1458
1481
|
const priceInfo = getPriceInfo(product, variation);
|
|
1459
1482
|
return total + priceInfo.effectivePrice * cartQuantity;
|
|
1460
1483
|
}, 0);
|
|
1461
|
-
if (!_optionalChain([buyXPayYCampaign, 'optionalAccess',
|
|
1484
|
+
if (!_optionalChain([buyXPayYCampaign, 'optionalAccess', _19 => _19.BuyXPayYCampaign])) {
|
|
1462
1485
|
const calculatedItems2 = items.map((item) => ({
|
|
1463
1486
|
item,
|
|
1464
1487
|
paidQuantity: item.cartQuantity,
|
|
@@ -1483,7 +1506,7 @@ function calculateCartWithCampaigns(items, campaigns) {
|
|
|
1483
1506
|
);
|
|
1484
1507
|
const eligibleUnits = items.flatMap((item) => {
|
|
1485
1508
|
const { product, variation } = item;
|
|
1486
|
-
const itemCategories = _optionalChain([product, 'access',
|
|
1509
|
+
const itemCategories = _optionalChain([product, 'access', _20 => _20.categories, 'optionalAccess', _21 => _21.map, 'call', _22 => _22((cat) => cat.id)]) || [];
|
|
1487
1510
|
const isEligible = itemCategories.some(
|
|
1488
1511
|
(id) => applicableCategoryIds.has(id)
|
|
1489
1512
|
);
|
|
@@ -1492,7 +1515,7 @@ function calculateCartWithCampaigns(items, campaigns) {
|
|
|
1492
1515
|
return Array.from({ length: item.cartQuantity }, () => ({
|
|
1493
1516
|
price: priceInfo.effectivePrice,
|
|
1494
1517
|
productId: product.id,
|
|
1495
|
-
variationId: _optionalChain([variation, 'optionalAccess',
|
|
1518
|
+
variationId: _optionalChain([variation, 'optionalAccess', _23 => _23.id]),
|
|
1496
1519
|
originalItem: item
|
|
1497
1520
|
}));
|
|
1498
1521
|
}
|
|
@@ -1530,7 +1553,7 @@ function calculateCartWithCampaigns(items, campaigns) {
|
|
|
1530
1553
|
freeCountMap.set(key, (freeCountMap.get(key) || 0) + 1);
|
|
1531
1554
|
}
|
|
1532
1555
|
const calculatedItems = items.map((item) => {
|
|
1533
|
-
const key = `${item.product.id}${_optionalChain([item, 'access',
|
|
1556
|
+
const key = `${item.product.id}${_optionalChain([item, 'access', _24 => _24.variation, 'optionalAccess', _25 => _25.id]) ? `_${item.variation.id}` : ""}`;
|
|
1534
1557
|
const freeQuantity = freeCountMap.get(key) || 0;
|
|
1535
1558
|
const paidQuantity = item.cartQuantity - freeQuantity;
|
|
1536
1559
|
return {
|
|
@@ -1551,7 +1574,7 @@ function calculateCartWithCampaigns(items, campaigns) {
|
|
|
1551
1574
|
};
|
|
1552
1575
|
}
|
|
1553
1576
|
function calculateFreeShipping(cartTotal, campaign) {
|
|
1554
|
-
if (!_optionalChain([campaign, 'optionalAccess',
|
|
1577
|
+
if (!_optionalChain([campaign, 'optionalAccess', _26 => _26.FreeShippingCampaign])) {
|
|
1555
1578
|
return {
|
|
1556
1579
|
isEligible: false,
|
|
1557
1580
|
minimumSpend: 0,
|
|
@@ -1561,7 +1584,7 @@ function calculateFreeShipping(cartTotal, campaign) {
|
|
|
1561
1584
|
const minimumSpend = campaign.FreeShippingCampaign.minimumSpend;
|
|
1562
1585
|
const isEligible = cartTotal >= minimumSpend;
|
|
1563
1586
|
const remainingAmount = isEligible ? 0 : minimumSpend - cartTotal;
|
|
1564
|
-
const eligibleShipmentMethodIds = _optionalChain([campaign, 'access',
|
|
1587
|
+
const eligibleShipmentMethodIds = _optionalChain([campaign, 'access', _27 => _27.FreeShippingCampaign, 'access', _28 => _28.shipmentMethods, 'optionalAccess', _29 => _29.map, 'call', _30 => _30(
|
|
1565
1588
|
(method) => method.id
|
|
1566
1589
|
)]);
|
|
1567
1590
|
return {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["d:\\Projektit\\Verkkokaupat\\putiikkipalvelu-sdk\\dist\\index.cjs"],"names":[],"mappings":"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AA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,YAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,YAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"D:\\Projektit\\Verkkokaupat\\putiikkipalvelu-sdk\\dist\\index.cjs","sourcesContent":[null]}
|
|
1
|
+
{"version":3,"sources":["d:\\Projektit\\Verkkokaupat\\putiikkipalvelu-sdk\\dist\\index.cjs"],"names":[],"mappings":"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AA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,YAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,YAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"D:\\Projektit\\Verkkokaupat\\putiikkipalvelu-sdk\\dist\\index.cjs","sourcesContent":[null]}
|
package/dist/index.d.cts
CHANGED
|
@@ -184,8 +184,10 @@ interface ShipitShippingMethod {
|
|
|
184
184
|
length: number;
|
|
185
185
|
/** Package width in cm */
|
|
186
186
|
width: number;
|
|
187
|
-
/** Package weight in kg */
|
|
187
|
+
/** Package weight in kg @deprecated Use maxWeight instead */
|
|
188
188
|
weight: number;
|
|
189
|
+
/** Maximum package weight in kg for this shipping tier */
|
|
190
|
+
maxWeight: number;
|
|
189
191
|
/** Service type */
|
|
190
192
|
type: string;
|
|
191
193
|
/** Shipit price in cents */
|
|
@@ -275,6 +277,8 @@ interface ProductVariationListing {
|
|
|
275
277
|
* Full product variation (for product detail page)
|
|
276
278
|
*/
|
|
277
279
|
interface ProductVariation extends ProductVariationListing {
|
|
280
|
+
/** Variation weight in kg (null = use product weight) */
|
|
281
|
+
weight: number | null;
|
|
278
282
|
/** Available quantity (null = unlimited) */
|
|
279
283
|
quantity: number | null;
|
|
280
284
|
/** Stock keeping unit */
|
|
@@ -323,6 +327,8 @@ interface Product {
|
|
|
323
327
|
* Used by: /product/{slug}
|
|
324
328
|
*/
|
|
325
329
|
interface ProductDetail extends Omit<Product, "variations"> {
|
|
330
|
+
/** Product weight in kg (for shipping calculations) */
|
|
331
|
+
weight: number;
|
|
326
332
|
/** Stock keeping unit */
|
|
327
333
|
sku: string | null;
|
|
328
334
|
/** SEO meta title */
|
|
@@ -1699,6 +1705,13 @@ type CartResource = ReturnType<typeof createCartResource>;
|
|
|
1699
1705
|
* Methods for fetching shipment methods and pickup locations.
|
|
1700
1706
|
*/
|
|
1701
1707
|
|
|
1708
|
+
/**
|
|
1709
|
+
* Options for fetching shipment methods with weight-based filtering
|
|
1710
|
+
*/
|
|
1711
|
+
interface GetMethodsOptions extends FetchOptions {
|
|
1712
|
+
/** Cart items - weight will be calculated automatically */
|
|
1713
|
+
cartItems?: CartItem[];
|
|
1714
|
+
}
|
|
1702
1715
|
/**
|
|
1703
1716
|
* Shipping resource for fetching shipment methods and pickup locations
|
|
1704
1717
|
*/
|
|
@@ -1707,7 +1720,7 @@ declare function createShippingResource(fetcher: Fetcher): {
|
|
|
1707
1720
|
* Get all available shipment methods for the store.
|
|
1708
1721
|
* Returns methods without pickup locations - use `getWithLocations` for postal code specific data.
|
|
1709
1722
|
*
|
|
1710
|
-
* @param options - Fetch options
|
|
1723
|
+
* @param options - Fetch options including optional cartItems for weight-based filtering
|
|
1711
1724
|
* @returns Available shipment methods
|
|
1712
1725
|
*
|
|
1713
1726
|
* @example
|
|
@@ -1718,14 +1731,22 @@ declare function createShippingResource(fetcher: Fetcher): {
|
|
|
1718
1731
|
* console.log(`${method.name}: ${method.price / 100}€`);
|
|
1719
1732
|
* });
|
|
1720
1733
|
* ```
|
|
1734
|
+
*
|
|
1735
|
+
* @example Weight-based filtering
|
|
1736
|
+
* ```typescript
|
|
1737
|
+
* // Pass cart items - SDK calculates weight automatically
|
|
1738
|
+
* const { shipmentMethods } = await client.shipping.getMethods({
|
|
1739
|
+
* cartItems: cartItems
|
|
1740
|
+
* });
|
|
1741
|
+
* ```
|
|
1721
1742
|
*/
|
|
1722
|
-
getMethods(options?:
|
|
1743
|
+
getMethods(options?: GetMethodsOptions): Promise<ShipmentMethodsResponse>;
|
|
1723
1744
|
/**
|
|
1724
1745
|
* Get shipment methods with pickup locations for a specific postal code.
|
|
1725
1746
|
* Calls the Shipit API to fetch nearby pickup points (parcel lockers, etc.)
|
|
1726
1747
|
*
|
|
1727
1748
|
* @param postalCode - Customer's postal code (e.g., "00100")
|
|
1728
|
-
* @param options - Fetch options
|
|
1749
|
+
* @param options - Fetch options including optional cartItems for weight-based filtering
|
|
1729
1750
|
* @returns Shipment methods and nearby pickup locations with pricing
|
|
1730
1751
|
*
|
|
1731
1752
|
* @example
|
|
@@ -1741,16 +1762,17 @@ declare function createShippingResource(fetcher: Fetcher): {
|
|
|
1741
1762
|
* });
|
|
1742
1763
|
* ```
|
|
1743
1764
|
*
|
|
1744
|
-
* @example
|
|
1765
|
+
* @example Weight-based filtering with postal code
|
|
1745
1766
|
* ```typescript
|
|
1746
|
-
* const { pricedLocations } = await client.shipping.getWithLocations(
|
|
1747
|
-
*
|
|
1748
|
-
*
|
|
1749
|
-
* loc => loc.carrier === "Posti"
|
|
1767
|
+
* const { shipmentMethods, pricedLocations } = await client.shipping.getWithLocations(
|
|
1768
|
+
* "00100",
|
|
1769
|
+
* { cartItems: cartItems }
|
|
1750
1770
|
* );
|
|
1771
|
+
*
|
|
1772
|
+
* // Only shows methods that support the cart's total weight
|
|
1751
1773
|
* ```
|
|
1752
1774
|
*/
|
|
1753
|
-
getWithLocations(postalCode: string, options?:
|
|
1775
|
+
getWithLocations(postalCode: string, options?: GetMethodsOptions): Promise<ShipmentMethodsWithLocationsResponse>;
|
|
1754
1776
|
};
|
|
1755
1777
|
/**
|
|
1756
1778
|
* Type for the shipping resource
|
package/dist/index.d.ts
CHANGED
|
@@ -184,8 +184,10 @@ interface ShipitShippingMethod {
|
|
|
184
184
|
length: number;
|
|
185
185
|
/** Package width in cm */
|
|
186
186
|
width: number;
|
|
187
|
-
/** Package weight in kg */
|
|
187
|
+
/** Package weight in kg @deprecated Use maxWeight instead */
|
|
188
188
|
weight: number;
|
|
189
|
+
/** Maximum package weight in kg for this shipping tier */
|
|
190
|
+
maxWeight: number;
|
|
189
191
|
/** Service type */
|
|
190
192
|
type: string;
|
|
191
193
|
/** Shipit price in cents */
|
|
@@ -275,6 +277,8 @@ interface ProductVariationListing {
|
|
|
275
277
|
* Full product variation (for product detail page)
|
|
276
278
|
*/
|
|
277
279
|
interface ProductVariation extends ProductVariationListing {
|
|
280
|
+
/** Variation weight in kg (null = use product weight) */
|
|
281
|
+
weight: number | null;
|
|
278
282
|
/** Available quantity (null = unlimited) */
|
|
279
283
|
quantity: number | null;
|
|
280
284
|
/** Stock keeping unit */
|
|
@@ -323,6 +327,8 @@ interface Product {
|
|
|
323
327
|
* Used by: /product/{slug}
|
|
324
328
|
*/
|
|
325
329
|
interface ProductDetail extends Omit<Product, "variations"> {
|
|
330
|
+
/** Product weight in kg (for shipping calculations) */
|
|
331
|
+
weight: number;
|
|
326
332
|
/** Stock keeping unit */
|
|
327
333
|
sku: string | null;
|
|
328
334
|
/** SEO meta title */
|
|
@@ -1699,6 +1705,13 @@ type CartResource = ReturnType<typeof createCartResource>;
|
|
|
1699
1705
|
* Methods for fetching shipment methods and pickup locations.
|
|
1700
1706
|
*/
|
|
1701
1707
|
|
|
1708
|
+
/**
|
|
1709
|
+
* Options for fetching shipment methods with weight-based filtering
|
|
1710
|
+
*/
|
|
1711
|
+
interface GetMethodsOptions extends FetchOptions {
|
|
1712
|
+
/** Cart items - weight will be calculated automatically */
|
|
1713
|
+
cartItems?: CartItem[];
|
|
1714
|
+
}
|
|
1702
1715
|
/**
|
|
1703
1716
|
* Shipping resource for fetching shipment methods and pickup locations
|
|
1704
1717
|
*/
|
|
@@ -1707,7 +1720,7 @@ declare function createShippingResource(fetcher: Fetcher): {
|
|
|
1707
1720
|
* Get all available shipment methods for the store.
|
|
1708
1721
|
* Returns methods without pickup locations - use `getWithLocations` for postal code specific data.
|
|
1709
1722
|
*
|
|
1710
|
-
* @param options - Fetch options
|
|
1723
|
+
* @param options - Fetch options including optional cartItems for weight-based filtering
|
|
1711
1724
|
* @returns Available shipment methods
|
|
1712
1725
|
*
|
|
1713
1726
|
* @example
|
|
@@ -1718,14 +1731,22 @@ declare function createShippingResource(fetcher: Fetcher): {
|
|
|
1718
1731
|
* console.log(`${method.name}: ${method.price / 100}€`);
|
|
1719
1732
|
* });
|
|
1720
1733
|
* ```
|
|
1734
|
+
*
|
|
1735
|
+
* @example Weight-based filtering
|
|
1736
|
+
* ```typescript
|
|
1737
|
+
* // Pass cart items - SDK calculates weight automatically
|
|
1738
|
+
* const { shipmentMethods } = await client.shipping.getMethods({
|
|
1739
|
+
* cartItems: cartItems
|
|
1740
|
+
* });
|
|
1741
|
+
* ```
|
|
1721
1742
|
*/
|
|
1722
|
-
getMethods(options?:
|
|
1743
|
+
getMethods(options?: GetMethodsOptions): Promise<ShipmentMethodsResponse>;
|
|
1723
1744
|
/**
|
|
1724
1745
|
* Get shipment methods with pickup locations for a specific postal code.
|
|
1725
1746
|
* Calls the Shipit API to fetch nearby pickup points (parcel lockers, etc.)
|
|
1726
1747
|
*
|
|
1727
1748
|
* @param postalCode - Customer's postal code (e.g., "00100")
|
|
1728
|
-
* @param options - Fetch options
|
|
1749
|
+
* @param options - Fetch options including optional cartItems for weight-based filtering
|
|
1729
1750
|
* @returns Shipment methods and nearby pickup locations with pricing
|
|
1730
1751
|
*
|
|
1731
1752
|
* @example
|
|
@@ -1741,16 +1762,17 @@ declare function createShippingResource(fetcher: Fetcher): {
|
|
|
1741
1762
|
* });
|
|
1742
1763
|
* ```
|
|
1743
1764
|
*
|
|
1744
|
-
* @example
|
|
1765
|
+
* @example Weight-based filtering with postal code
|
|
1745
1766
|
* ```typescript
|
|
1746
|
-
* const { pricedLocations } = await client.shipping.getWithLocations(
|
|
1747
|
-
*
|
|
1748
|
-
*
|
|
1749
|
-
* loc => loc.carrier === "Posti"
|
|
1767
|
+
* const { shipmentMethods, pricedLocations } = await client.shipping.getWithLocations(
|
|
1768
|
+
* "00100",
|
|
1769
|
+
* { cartItems: cartItems }
|
|
1750
1770
|
* );
|
|
1771
|
+
*
|
|
1772
|
+
* // Only shows methods that support the cart's total weight
|
|
1751
1773
|
* ```
|
|
1752
1774
|
*/
|
|
1753
|
-
getWithLocations(postalCode: string, options?:
|
|
1775
|
+
getWithLocations(postalCode: string, options?: GetMethodsOptions): Promise<ShipmentMethodsWithLocationsResponse>;
|
|
1754
1776
|
};
|
|
1755
1777
|
/**
|
|
1756
1778
|
* Type for the shipping resource
|
package/dist/index.js
CHANGED
|
@@ -611,13 +611,19 @@ function createCartResource(fetcher) {
|
|
|
611
611
|
}
|
|
612
612
|
|
|
613
613
|
// src/resources/shipping.ts
|
|
614
|
+
function calculateCartWeight(items) {
|
|
615
|
+
return items.reduce((total, item) => {
|
|
616
|
+
const itemWeight = item.variation?.weight ?? item.product.weight ?? 0.5;
|
|
617
|
+
return total + itemWeight * item.cartQuantity;
|
|
618
|
+
}, 0);
|
|
619
|
+
}
|
|
614
620
|
function createShippingResource(fetcher) {
|
|
615
621
|
return {
|
|
616
622
|
/**
|
|
617
623
|
* Get all available shipment methods for the store.
|
|
618
624
|
* Returns methods without pickup locations - use `getWithLocations` for postal code specific data.
|
|
619
625
|
*
|
|
620
|
-
* @param options - Fetch options
|
|
626
|
+
* @param options - Fetch options including optional cartItems for weight-based filtering
|
|
621
627
|
* @returns Available shipment methods
|
|
622
628
|
*
|
|
623
629
|
* @example
|
|
@@ -628,22 +634,34 @@ function createShippingResource(fetcher) {
|
|
|
628
634
|
* console.log(`${method.name}: ${method.price / 100}€`);
|
|
629
635
|
* });
|
|
630
636
|
* ```
|
|
637
|
+
*
|
|
638
|
+
* @example Weight-based filtering
|
|
639
|
+
* ```typescript
|
|
640
|
+
* // Pass cart items - SDK calculates weight automatically
|
|
641
|
+
* const { shipmentMethods } = await client.shipping.getMethods({
|
|
642
|
+
* cartItems: cartItems
|
|
643
|
+
* });
|
|
644
|
+
* ```
|
|
631
645
|
*/
|
|
632
646
|
async getMethods(options) {
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
647
|
+
const params = new URLSearchParams();
|
|
648
|
+
if (options?.cartItems?.length) {
|
|
649
|
+
const cartWeight = calculateCartWeight(options.cartItems);
|
|
650
|
+
params.set("cartWeight", cartWeight.toString());
|
|
651
|
+
}
|
|
652
|
+
const queryString = params.toString();
|
|
653
|
+
const url = `/api/storefront/v1/shipment-methods${queryString ? `?${queryString}` : ""}`;
|
|
654
|
+
return fetcher.request(url, {
|
|
655
|
+
method: "GET",
|
|
656
|
+
...options
|
|
657
|
+
});
|
|
640
658
|
},
|
|
641
659
|
/**
|
|
642
660
|
* Get shipment methods with pickup locations for a specific postal code.
|
|
643
661
|
* Calls the Shipit API to fetch nearby pickup points (parcel lockers, etc.)
|
|
644
662
|
*
|
|
645
663
|
* @param postalCode - Customer's postal code (e.g., "00100")
|
|
646
|
-
* @param options - Fetch options
|
|
664
|
+
* @param options - Fetch options including optional cartItems for weight-based filtering
|
|
647
665
|
* @returns Shipment methods and nearby pickup locations with pricing
|
|
648
666
|
*
|
|
649
667
|
* @example
|
|
@@ -659,23 +677,28 @@ function createShippingResource(fetcher) {
|
|
|
659
677
|
* });
|
|
660
678
|
* ```
|
|
661
679
|
*
|
|
662
|
-
* @example
|
|
680
|
+
* @example Weight-based filtering with postal code
|
|
663
681
|
* ```typescript
|
|
664
|
-
* const { pricedLocations } = await client.shipping.getWithLocations(
|
|
665
|
-
*
|
|
666
|
-
*
|
|
667
|
-
* loc => loc.carrier === "Posti"
|
|
682
|
+
* const { shipmentMethods, pricedLocations } = await client.shipping.getWithLocations(
|
|
683
|
+
* "00100",
|
|
684
|
+
* { cartItems: cartItems }
|
|
668
685
|
* );
|
|
686
|
+
*
|
|
687
|
+
* // Only shows methods that support the cart's total weight
|
|
669
688
|
* ```
|
|
670
689
|
*/
|
|
671
690
|
async getWithLocations(postalCode, options) {
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
)
|
|
691
|
+
const params = new URLSearchParams();
|
|
692
|
+
if (options?.cartItems?.length) {
|
|
693
|
+
const cartWeight = calculateCartWeight(options.cartItems);
|
|
694
|
+
params.set("cartWeight", cartWeight.toString());
|
|
695
|
+
}
|
|
696
|
+
const queryString = params.toString();
|
|
697
|
+
const url = `/api/storefront/v1/shipment-methods/${encodeURIComponent(postalCode)}${queryString ? `?${queryString}` : ""}`;
|
|
698
|
+
return fetcher.request(url, {
|
|
699
|
+
method: "GET",
|
|
700
|
+
...options
|
|
701
|
+
});
|
|
679
702
|
}
|
|
680
703
|
};
|
|
681
704
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/errors.ts","../src/utils/fetch.ts","../src/resources/store.ts","../src/resources/products.ts","../src/resources/categories.ts","../src/resources/cart.ts","../src/resources/shipping.ts","../src/resources/customer.ts","../src/resources/order.ts","../src/resources/checkout.ts","../src/client.ts","../src/utils/pricing.ts","../src/utils/cart-calculations.ts"],"sourcesContent":["/**\n * Base error class for all Storefront API errors\n */\nexport class StorefrontError extends Error {\n public readonly status: number;\n public readonly code: string;\n\n constructor(message: string, status: number, code: string) {\n super(message);\n this.name = \"StorefrontError\";\n this.status = status;\n this.code = code;\n\n // Maintains proper stack trace in V8 environments\n const ErrorWithCapture = Error as typeof Error & {\n captureStackTrace?: (target: object, constructor: Function) => void;\n };\n if (ErrorWithCapture.captureStackTrace) {\n ErrorWithCapture.captureStackTrace(this, StorefrontError);\n }\n }\n}\n\n/**\n * Error thrown when API returns 401 Unauthorized\n */\nexport class AuthError extends StorefrontError {\n constructor(message: string = \"Invalid or missing API key\") {\n super(message, 401, \"UNAUTHORIZED\");\n this.name = \"AuthError\";\n }\n}\n\n/**\n * Error thrown when API returns 429 Too Many Requests\n */\nexport class RateLimitError extends StorefrontError {\n public readonly retryAfter: number | null;\n\n constructor(message: string = \"Rate limit exceeded\", retryAfter: number | null = null) {\n super(message, 429, \"RATE_LIMIT_EXCEEDED\");\n this.name = \"RateLimitError\";\n this.retryAfter = retryAfter;\n }\n}\n\n/**\n * Error thrown when a requested resource is not found (404)\n */\nexport class NotFoundError extends StorefrontError {\n constructor(message: string = \"Resource not found\") {\n super(message, 404, \"NOT_FOUND\");\n this.name = \"NotFoundError\";\n }\n}\n\n/**\n * Error thrown when request validation fails (400)\n */\nexport class ValidationError extends StorefrontError {\n constructor(message: string = \"Validation failed\") {\n super(message, 400, \"VALIDATION_ERROR\");\n this.name = \"ValidationError\";\n }\n}\n\n/**\n * Error thrown when login fails due to unverified email\n * Contains customerId for resending verification email\n */\nexport class VerificationRequiredError extends StorefrontError {\n public readonly requiresVerification: true = true;\n public readonly customerId: string;\n\n constructor(message: string, customerId: string) {\n super(message, 403, \"VERIFICATION_REQUIRED\");\n this.name = \"VerificationRequiredError\";\n this.customerId = customerId;\n }\n}\n","import type { FetchOptions } from \"../types/index.js\";\r\nimport {\r\n StorefrontError,\r\n AuthError,\r\n RateLimitError,\r\n NotFoundError,\r\n ValidationError,\r\n VerificationRequiredError,\r\n} from \"./errors.js\";\r\n\r\n// SDK version - will be replaced during build or read from package.json\r\nconst SDK_VERSION = \"0.1.0\";\r\n\r\nexport interface FetcherConfig {\r\n apiKey: string;\r\n baseUrl: string;\r\n timeout?: number;\r\n}\r\n\r\nexport interface RequestOptions extends FetchOptions {\r\n method?: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\";\r\n body?: unknown;\r\n params?: Record<string, string | number | boolean | undefined>;\r\n}\r\n\r\n/**\r\n * Fetcher instance type returned by createFetcher\r\n */\r\nexport type Fetcher = ReturnType<typeof createFetcher>;\r\n\r\n/**\r\n * Create a configured fetcher instance for making API requests\r\n */\r\nexport function createFetcher(config: FetcherConfig) {\r\n const { apiKey, baseUrl, timeout = 30000 } = config;\r\n\r\n /**\r\n * Make an authenticated request to the Storefront API\r\n */\r\n async function request<T>(endpoint: string, options: RequestOptions = {}): Promise<T> {\r\n const { method = \"GET\", body, params, signal, headers = {}, cache, ...frameworkOptions } = options;\r\n\r\n // Build URL with query parameters\r\n // Ensure baseUrl ends with / for proper URL resolution\r\n const normalizedBase = baseUrl.endsWith(\"/\") ? baseUrl : `${baseUrl}/`;\r\n // Remove leading slash from endpoint to avoid URL resolution issues\r\n const normalizedEndpoint = endpoint.startsWith(\"/\") ? endpoint.slice(1) : endpoint;\r\n const url = new URL(normalizedEndpoint, normalizedBase);\r\n\r\n if (params) {\r\n for (const [key, value] of Object.entries(params)) {\r\n if (value !== undefined) {\r\n url.searchParams.set(key, String(value));\r\n }\r\n }\r\n }\r\n\r\n // Create abort controller for timeout\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), timeout);\r\n\r\n // Combine signals if provided\r\n const combinedSignal = signal\r\n ? AbortSignal.any([signal, controller.signal])\r\n : controller.signal;\r\n\r\n try {\r\n const fetchOptions: RequestInit & Record<string, unknown> = {\r\n method,\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n \"x-api-key\": apiKey,\r\n \"x-sdk-version\": SDK_VERSION,\r\n ...headers,\r\n },\r\n body: body ? JSON.stringify(body) : undefined,\r\n signal: combinedSignal,\r\n cache,\r\n // Spread framework-specific options (e.g., Next.js `next`, or any other)\r\n ...frameworkOptions,\r\n };\r\n\r\n const response = await fetch(url.toString(), fetchOptions);\r\n\r\n clearTimeout(timeoutId);\r\n\r\n // Handle error responses\r\n if (!response.ok) {\r\n await handleErrorResponse(response);\r\n }\r\n\r\n // Parse response\r\n const data = await response.json();\r\n return data as T;\r\n } catch (error) {\r\n clearTimeout(timeoutId);\r\n\r\n // Re-throw SDK errors\r\n if (error instanceof StorefrontError) {\r\n throw error;\r\n }\r\n\r\n // Handle abort/timeout\r\n if (error instanceof Error && error.name === \"AbortError\") {\r\n throw new StorefrontError(\"Request timed out\", 408, \"TIMEOUT\");\r\n }\r\n\r\n // Handle network errors\r\n throw new StorefrontError(\r\n error instanceof Error ? error.message : \"Network error\",\r\n 0,\r\n \"NETWORK_ERROR\"\r\n );\r\n }\r\n }\r\n\r\n return { request };\r\n}\r\n\r\n/**\r\n * Error response JSON structure\r\n */\r\ninterface ErrorResponseJson {\r\n error?: string;\r\n requiresVerification?: boolean;\r\n customerId?: string;\r\n}\r\n\r\n/**\r\n * Handle non-2xx responses and throw appropriate errors\r\n */\r\nasync function handleErrorResponse(response: Response): Promise<never> {\r\n let errorData: ErrorResponseJson = {};\r\n\r\n try {\r\n const json: unknown = await response.json();\r\n if (json && typeof json === \"object\") {\r\n errorData = json as ErrorResponseJson;\r\n }\r\n } catch {\r\n // Response body is not JSON\r\n }\r\n\r\n const message = errorData.error || response.statusText || \"Request failed\";\r\n\r\n // Check for verification required error (can be 400 or 403)\r\n if (errorData.requiresVerification && errorData.customerId) {\r\n throw new VerificationRequiredError(message, errorData.customerId);\r\n }\r\n\r\n switch (response.status) {\r\n case 401:\r\n throw new AuthError(message);\r\n\r\n case 404:\r\n throw new NotFoundError(message);\r\n\r\n case 429: {\r\n const retryAfter = response.headers.get(\"Retry-After\");\r\n throw new RateLimitError(message, retryAfter ? parseInt(retryAfter, 10) : null);\r\n }\r\n\r\n case 400:\r\n throw new ValidationError(message);\r\n\r\n default:\r\n throw new StorefrontError(message, response.status, \"API_ERROR\");\r\n }\r\n}\r\n","import type { FetchOptions, StoreConfig } from \"../types/index.js\";\r\nimport type { Fetcher } from \"../utils/fetch.js\";\r\n\r\n/**\r\n * Store resource for fetching store configuration\r\n */\r\nexport function createStoreResource(fetcher: Fetcher) {\r\n return {\r\n /**\r\n * Get the complete store configuration including settings, SEO, payments, campaigns, and features.\r\n *\r\n * @example Basic usage\r\n * ```typescript\r\n * const config = await client.store.getConfig();\r\n * console.log(config.store.name);\r\n * console.log(config.seo.seoTitle);\r\n * console.log(config.campaigns);\r\n * ```\r\n *\r\n * @example Next.js - with caching\r\n * ```typescript\r\n * const config = await client.store.getConfig({\r\n * next: { revalidate: 300, tags: ['store-config'] }\r\n * });\r\n * ```\r\n *\r\n * @example Nuxt - wrap with useAsyncData\r\n * ```typescript\r\n * const { data: config } = await useAsyncData(\r\n * 'store-config',\r\n * () => client.store.getConfig()\r\n * );\r\n * ```\r\n *\r\n * @example Standard fetch caching\r\n * ```typescript\r\n * const config = await client.store.getConfig({\r\n * cache: 'force-cache'\r\n * });\r\n * ```\r\n */\r\n async getConfig(options?: FetchOptions): Promise<StoreConfig> {\r\n return fetcher.request<StoreConfig>(\"/api/storefront/v1/store-config\", {\r\n ...options,\r\n });\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Type for the store resource\r\n */\r\nexport type StoreResource = ReturnType<typeof createStoreResource>;\r\n","import type {\r\n FetchOptions,\r\n Product,\r\n ProductDetail,\r\n ProductListResponse,\r\n ProductCountResponse,\r\n ProductListParams,\r\n} from \"../types/index.js\";\r\nimport type { Fetcher } from \"../utils/fetch.js\";\r\n\r\n/**\r\n * Products resource for fetching product data\r\n */\r\nexport function createProductsResource(fetcher: Fetcher) {\r\n return {\r\n /**\r\n * Get latest products ordered by creation date (newest first).\r\n *\r\n * @param take - Number of products to return (required, must be >= 1)\r\n * @param options - Fetch options (caching, headers, etc.)\r\n * @returns Array of products\r\n *\r\n * @example Basic usage\r\n * ```typescript\r\n * const products = await client.products.latest(6);\r\n * ```\r\n *\r\n * @example Next.js - with caching\r\n * ```typescript\r\n * const products = await client.products.latest(6, {\r\n * next: { revalidate: 3600, tags: ['products'] }\r\n * });\r\n * ```\r\n */\r\n async latest(take: number, options?: FetchOptions): Promise<Product[]> {\r\n return fetcher.request<Product[]>(\"/api/storefront/v1/latest-products\", {\r\n params: { take },\r\n ...options,\r\n });\r\n },\r\n\r\n /**\r\n * Get a single product by its URL slug.\r\n *\r\n * @param slug - Product URL slug\r\n * @param options - Fetch options (caching, headers, etc.)\r\n * @returns Full product details including categories and variations\r\n * @throws NotFoundError if product doesn't exist or is not visible\r\n *\r\n * @example Basic usage\r\n * ```typescript\r\n * const product = await client.products.getBySlug('my-product');\r\n * console.log(product.name, product.categories);\r\n * ```\r\n *\r\n * @example Next.js - with caching\r\n * ```typescript\r\n * const product = await client.products.getBySlug('my-product', {\r\n * next: { revalidate: 3600, tags: ['product', 'my-product'] }\r\n * });\r\n * ```\r\n */\r\n async getBySlug(\r\n slug: string,\r\n options?: FetchOptions\r\n ): Promise<ProductDetail> {\r\n return fetcher.request<ProductDetail>(\r\n `/api/storefront/v1/product/${encodeURIComponent(slug)}`,\r\n {\r\n ...options,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Get total product count, optionally filtered by category.\r\n *\r\n * @param slugs - Optional category slugs to filter by\r\n * @param options - Fetch options (caching, headers, etc.)\r\n * @returns Object with count property\r\n *\r\n * @example Get total count\r\n * ```typescript\r\n * const { count } = await client.products.count();\r\n * console.log(`Total products: ${count}`);\r\n * ```\r\n *\r\n * @example Get count for specific category\r\n * ```typescript\r\n * const { count } = await client.products.count(['shoes']);\r\n * console.log(`Products in shoes: ${count}`);\r\n * ```\r\n */\r\n async count(\r\n slugs?: string[],\r\n options?: FetchOptions\r\n ): Promise<ProductCountResponse> {\r\n const searchParams = new URLSearchParams();\r\n if (slugs?.length) {\r\n slugs.forEach((s) => searchParams.append(\"slugs\", s));\r\n }\r\n const query = searchParams.toString();\r\n const endpoint = `/api/storefront/v1/products-count${query ? `?${query}` : \"\"}`;\r\n\r\n return fetcher.request<ProductCountResponse>(endpoint, {\r\n ...options,\r\n });\r\n },\r\n\r\n /**\r\n * Get sorted products with pagination.\r\n * Uses optimized sorting with pre-computed effective prices.\r\n *\r\n * @param params - Query parameters (slugs, page, pageSize, sort)\r\n * @param options - Fetch options (caching, headers, etc.)\r\n * @returns Products list with totalCount for pagination\r\n *\r\n * @example Basic usage\r\n * ```typescript\r\n * const { products, totalCount } = await client.products.sorted({\r\n * page: 1,\r\n * pageSize: 12,\r\n * sort: 'newest'\r\n * });\r\n * ```\r\n *\r\n * @example Filter by category\r\n * ```typescript\r\n * const { products, totalCount } = await client.products.sorted({\r\n * slugs: ['shoes', 'clothing'],\r\n * page: 1,\r\n * pageSize: 24,\r\n * sort: 'price_asc'\r\n * });\r\n * ```\r\n *\r\n * @example Real-time data (no cache)\r\n * ```typescript\r\n * const data = await client.products.sorted(\r\n * { page: 1, pageSize: 12 },\r\n * { cache: 'no-store' }\r\n * );\r\n * ```\r\n */\r\n async sorted(\r\n params: ProductListParams = {},\r\n options?: FetchOptions\r\n ): Promise<ProductListResponse> {\r\n const searchParams = new URLSearchParams();\r\n if (params.page) searchParams.set(\"page\", params.page.toString());\r\n if (params.pageSize)\r\n searchParams.set(\"pageSize\", params.pageSize.toString());\r\n if (params.sort) searchParams.set(\"sort\", params.sort);\r\n if (params.slugs?.length) {\r\n params.slugs.forEach((s) => searchParams.append(\"slugs\", s));\r\n }\r\n const query = searchParams.toString();\r\n const endpoint = `/api/storefront/v1/sorted-products${query ? `?${query}` : \"\"}`;\r\n\r\n return fetcher.request<ProductListResponse>(endpoint, {\r\n ...options,\r\n });\r\n },\r\n\r\n /**\r\n * Get filtered products with pagination.\r\n * Similar to sorted() but without totalCount in response.\r\n * Useful for sitemaps and bulk fetches.\r\n *\r\n * @param params - Query parameters (slugs, page, pageSize, sort)\r\n * @param options - Fetch options (caching, headers, etc.)\r\n * @returns Products list with category name\r\n *\r\n * @example Fetch all products for sitemap\r\n * ```typescript\r\n * const { products } = await client.products.filtered({\r\n * slugs: ['all-products'],\r\n * page: 1,\r\n * pageSize: 1000\r\n * });\r\n * ```\r\n */\r\n async filtered(\r\n params: ProductListParams = {},\r\n options?: FetchOptions\r\n ): Promise<Omit<ProductListResponse, \"totalCount\">> {\r\n const searchParams = new URLSearchParams();\r\n if (params.page) searchParams.set(\"page\", params.page.toString());\r\n if (params.pageSize)\r\n searchParams.set(\"pageSize\", params.pageSize.toString());\r\n if (params.sort) searchParams.set(\"sort\", params.sort);\r\n if (params.slugs?.length) {\r\n params.slugs.forEach((s) => searchParams.append(\"slugs\", s));\r\n }\r\n const query = searchParams.toString();\r\n const endpoint = `/api/storefront/v1/filtered-products${query ? `?${query}` : \"\"}`;\r\n\r\n return fetcher.request<Omit<ProductListResponse, \"totalCount\">>(\r\n endpoint,\r\n {\r\n ...options,\r\n }\r\n );\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Type for the products resource\r\n */\r\nexport type ProductsResource = ReturnType<typeof createProductsResource>;\r\n","import type { FetchOptions, Category, CategoryResponse } from \"../types/index.js\";\r\nimport type { Fetcher } from \"../utils/fetch.js\";\r\n\r\n/**\r\n * Categories resource for fetching category data\r\n */\r\nexport function createCategoriesResource(fetcher: Fetcher) {\r\n return {\r\n /**\r\n * Get all top-level categories with nested children.\r\n * Returns a hierarchical tree of categories (up to 5 levels deep).\r\n *\r\n * @param options - Fetch options (caching, headers, etc.)\r\n * @returns Array of top-level categories with nested children\r\n *\r\n * @example Basic usage\r\n * ```typescript\r\n * const categories = await client.categories.list();\r\n * categories.forEach(cat => {\r\n * console.log(cat.name, cat.children.length);\r\n * });\r\n * ```\r\n *\r\n * @example Next.js - with caching\r\n * ```typescript\r\n * const categories = await client.categories.list({\r\n * next: { revalidate: 3600, tags: ['categories'] }\r\n * });\r\n * ```\r\n */\r\n async list(options?: FetchOptions): Promise<Category[]> {\r\n return fetcher.request<Category[]>(\"/api/storefront/v1/categories\", {\r\n ...options,\r\n });\r\n },\r\n\r\n /**\r\n * Get a single category by its URL slug.\r\n *\r\n * @param slug - Category URL slug\r\n * @param options - Fetch options (caching, headers, etc.)\r\n * @returns Category data\r\n * @throws NotFoundError if category doesn't exist\r\n *\r\n * @example Basic usage\r\n * ```typescript\r\n * const { category } = await client.categories.getBySlug('shoes');\r\n * console.log(category.name);\r\n * ```\r\n *\r\n * @example Next.js - with caching\r\n * ```typescript\r\n * const { category } = await client.categories.getBySlug('shoes', {\r\n * next: { revalidate: 86400, tags: ['category', 'shoes'] }\r\n * });\r\n * ```\r\n */\r\n async getBySlug(\r\n slug: string,\r\n options?: FetchOptions\r\n ): Promise<CategoryResponse> {\r\n return fetcher.request<CategoryResponse>(\r\n `/api/storefront/v1/categories/${encodeURIComponent(slug)}`,\r\n {\r\n ...options,\r\n }\r\n );\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Type for the categories resource\r\n */\r\nexport type CategoriesResource = ReturnType<typeof createCategoriesResource>;\r\n","/**\r\n * Cart Resource\r\n *\r\n * Methods for managing the shopping cart stored in Redis.\r\n * Supports both guest carts (via cartId) and authenticated user carts (via sessionId).\r\n */\r\n\r\nimport type {\r\n FetchOptions,\r\n CartResponse,\r\n CartValidationResponse,\r\n CartSessionOptions,\r\n AddToCartParams,\r\n UpdateCartQuantityParams,\r\n RemoveFromCartParams,\r\n} from \"../types/index.js\";\r\nimport type { Fetcher } from \"../utils/fetch.js\";\r\n\r\n/**\r\n * Build headers object for cart operations\r\n */\r\nfunction buildCartHeaders(options?: CartSessionOptions): Record<string, string> {\r\n const headers: Record<string, string> = {};\r\n if (options?.cartId) {\r\n headers[\"x-cart-id\"] = options.cartId;\r\n }\r\n if (options?.sessionId) {\r\n headers[\"x-session-id\"] = options.sessionId;\r\n }\r\n return headers;\r\n}\r\n\r\n/**\r\n * Cart resource for managing shopping cart\r\n */\r\nexport function createCartResource(fetcher: Fetcher) {\r\n return {\r\n /**\r\n * Fetch the current cart contents.\r\n *\r\n * @param options - Cart session options (cartId for guests, sessionId for logged-in users)\r\n * @param fetchOptions - Fetch options (caching, headers, etc.)\r\n * @returns Cart items and cartId (for guests)\r\n *\r\n * @example Guest user\r\n * ```typescript\r\n * const cartId = localStorage.getItem('cart-id');\r\n * const { items, cartId: newCartId } = await client.cart.get({ cartId });\r\n * ```\r\n *\r\n * @example Logged-in user\r\n * ```typescript\r\n * const { items } = await client.cart.get({ sessionId });\r\n * ```\r\n */\r\n async get(\r\n options?: CartSessionOptions,\r\n fetchOptions?: FetchOptions\r\n ): Promise<CartResponse> {\r\n return fetcher.request<CartResponse>(\"/api/storefront/v1/cart\", {\r\n method: \"GET\",\r\n headers: buildCartHeaders(options),\r\n ...fetchOptions,\r\n });\r\n },\r\n\r\n /**\r\n * Add an item to the cart.\r\n * If the item already exists, quantity is incremented.\r\n *\r\n * @param params - Add to cart parameters\r\n * @param fetchOptions - Fetch options\r\n * @returns Updated cart with new cartId for guests\r\n * @throws ValidationError if quantity exceeds available stock\r\n *\r\n * @example Add product\r\n * ```typescript\r\n * const { items, cartId } = await client.cart.addItem({\r\n * cartId: existingCartId,\r\n * productId: 'prod_123',\r\n * quantity: 2\r\n * });\r\n * // Save cartId for future requests\r\n * localStorage.setItem('cart-id', cartId);\r\n * ```\r\n *\r\n * @example Add product with variation\r\n * ```typescript\r\n * const { items, cartId } = await client.cart.addItem({\r\n * cartId,\r\n * productId: 'prod_123',\r\n * variationId: 'var_456',\r\n * quantity: 1\r\n * });\r\n * ```\r\n */\r\n async addItem(\r\n params: AddToCartParams,\r\n fetchOptions?: FetchOptions\r\n ): Promise<CartResponse> {\r\n const { cartId, sessionId, ...body } = params;\r\n return fetcher.request<CartResponse>(\"/api/storefront/v1/cart\", {\r\n method: \"POST\",\r\n headers: buildCartHeaders({ sessionId }),\r\n body: {\r\n cartId,\r\n ...body,\r\n },\r\n ...fetchOptions,\r\n });\r\n },\r\n\r\n /**\r\n * Update item quantity by delta (atomic operation).\r\n * Use positive delta to increase, negative to decrease.\r\n * Minimum quantity is 1 (use removeItem to delete).\r\n *\r\n * @param params - Update quantity parameters\r\n * @param fetchOptions - Fetch options\r\n * @returns Updated cart\r\n * @throws NotFoundError if item not in cart or quantity would go below 1\r\n *\r\n * @example Increment quantity\r\n * ```typescript\r\n * const { items } = await client.cart.updateQuantity({\r\n * cartId,\r\n * productId: 'prod_123',\r\n * delta: 1\r\n * });\r\n * ```\r\n *\r\n * @example Decrement quantity\r\n * ```typescript\r\n * const { items } = await client.cart.updateQuantity({\r\n * cartId,\r\n * productId: 'prod_123',\r\n * variationId: 'var_456',\r\n * delta: -1\r\n * });\r\n * ```\r\n */\r\n async updateQuantity(\r\n params: UpdateCartQuantityParams,\r\n fetchOptions?: FetchOptions\r\n ): Promise<CartResponse> {\r\n const { cartId, sessionId, ...body } = params;\r\n return fetcher.request<CartResponse>(\"/api/storefront/v1/cart\", {\r\n method: \"PATCH\",\r\n headers: buildCartHeaders({ sessionId }),\r\n body: {\r\n cartId,\r\n ...body,\r\n },\r\n ...fetchOptions,\r\n });\r\n },\r\n\r\n /**\r\n * Remove an item from the cart.\r\n *\r\n * @param params - Remove from cart parameters\r\n * @param fetchOptions - Fetch options\r\n * @returns Updated cart\r\n *\r\n * @example Remove product\r\n * ```typescript\r\n * const { items } = await client.cart.removeItem({\r\n * cartId,\r\n * productId: 'prod_123'\r\n * });\r\n * ```\r\n *\r\n * @example Remove variation\r\n * ```typescript\r\n * const { items } = await client.cart.removeItem({\r\n * cartId,\r\n * productId: 'prod_123',\r\n * variationId: 'var_456'\r\n * });\r\n * ```\r\n */\r\n async removeItem(\r\n params: RemoveFromCartParams,\r\n fetchOptions?: FetchOptions\r\n ): Promise<CartResponse> {\r\n const { cartId, sessionId, ...body } = params;\r\n return fetcher.request<CartResponse>(\"/api/storefront/v1/cart\", {\r\n method: \"DELETE\",\r\n headers: buildCartHeaders({ sessionId }),\r\n body: {\r\n cartId,\r\n ...body,\r\n },\r\n ...fetchOptions,\r\n });\r\n },\r\n\r\n /**\r\n * Validate cart before checkout.\r\n * Checks product availability, stock levels, and prices.\r\n * Auto-fixes issues (removes unavailable items, adjusts quantities).\r\n *\r\n * @param options - Cart session options\r\n * @param fetchOptions - Fetch options\r\n * @returns Validated cart with change metadata\r\n *\r\n * @example Validate before checkout\r\n * ```typescript\r\n * const { items, hasChanges, changes } = await client.cart.validate({ cartId });\r\n *\r\n * if (hasChanges) {\r\n * if (changes.removedItems > 0) {\r\n * notify('Some items were removed (out of stock)');\r\n * }\r\n * if (changes.quantityAdjusted > 0) {\r\n * notify('Some quantities were adjusted');\r\n * }\r\n * if (changes.priceChanged > 0) {\r\n * notify('Some prices have changed');\r\n * }\r\n * }\r\n * ```\r\n */\r\n async validate(\r\n options?: CartSessionOptions,\r\n fetchOptions?: FetchOptions\r\n ): Promise<CartValidationResponse> {\r\n return fetcher.request<CartValidationResponse>(\r\n \"/api/storefront/v1/cart/validate\",\r\n {\r\n method: \"GET\",\r\n headers: buildCartHeaders(options),\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Type for the cart resource\r\n */\r\nexport type CartResource = ReturnType<typeof createCartResource>;\r\n","/**\r\n * Shipping Resource\r\n *\r\n * Methods for fetching shipment methods and pickup locations.\r\n */\r\n\r\nimport type {\r\n FetchOptions,\r\n ShipmentMethodsResponse,\r\n ShipmentMethodsWithLocationsResponse,\r\n} from \"../types/index.js\";\r\nimport type { Fetcher } from \"../utils/fetch.js\";\r\n\r\n/**\r\n * Shipping resource for fetching shipment methods and pickup locations\r\n */\r\nexport function createShippingResource(fetcher: Fetcher) {\r\n return {\r\n /**\r\n * Get all available shipment methods for the store.\r\n * Returns methods without pickup locations - use `getWithLocations` for postal code specific data.\r\n *\r\n * @param options - Fetch options (caching, headers, etc.)\r\n * @returns Available shipment methods\r\n *\r\n * @example\r\n * ```typescript\r\n * const { shipmentMethods } = await client.shipping.getMethods();\r\n *\r\n * shipmentMethods.forEach(method => {\r\n * console.log(`${method.name}: ${method.price / 100}€`);\r\n * });\r\n * ```\r\n */\r\n async getMethods(options?: FetchOptions): Promise<ShipmentMethodsResponse> {\r\n return fetcher.request<ShipmentMethodsResponse>(\r\n \"/api/storefront/v1/shipment-methods\",\r\n {\r\n method: \"GET\",\r\n ...options,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Get shipment methods with pickup locations for a specific postal code.\r\n * Calls the Shipit API to fetch nearby pickup points (parcel lockers, etc.)\r\n *\r\n * @param postalCode - Customer's postal code (e.g., \"00100\")\r\n * @param options - Fetch options (caching, headers, etc.)\r\n * @returns Shipment methods and nearby pickup locations with pricing\r\n *\r\n * @example\r\n * ```typescript\r\n * const { shipmentMethods, pricedLocations } = await client.shipping.getWithLocations(\"00100\");\r\n *\r\n * // Show pickup locations\r\n * pricedLocations.forEach(location => {\r\n * console.log(`${location.name} - ${location.carrier}`);\r\n * console.log(` ${location.address1}, ${location.city}`);\r\n * console.log(` ${location.distanceInKilometers.toFixed(1)} km away`);\r\n * console.log(` Price: ${(location.merchantPrice ?? 0) / 100}€`);\r\n * });\r\n * ```\r\n *\r\n * @example Filter by carrier\r\n * ```typescript\r\n * const { pricedLocations } = await client.shipping.getWithLocations(\"00100\");\r\n *\r\n * const postiLocations = pricedLocations.filter(\r\n * loc => loc.carrier === \"Posti\"\r\n * );\r\n * ```\r\n */\r\n async getWithLocations(\r\n postalCode: string,\r\n options?: FetchOptions\r\n ): Promise<ShipmentMethodsWithLocationsResponse> {\r\n return fetcher.request<ShipmentMethodsWithLocationsResponse>(\r\n `/api/storefront/v1/shipment-methods/${encodeURIComponent(postalCode)}`,\r\n {\r\n method: \"GET\",\r\n ...options,\r\n }\r\n );\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Type for the shipping resource\r\n */\r\nexport type ShippingResource = ReturnType<typeof createShippingResource>;\r\n","/**\r\n * Customer Resource\r\n *\r\n * Methods for customer authentication and account management.\r\n * Supports session-based authentication with the x-session-id header.\r\n */\r\n\r\nimport type {\r\n FetchOptions,\r\n RegisterData,\r\n RegisterResponse,\r\n LoginOptions,\r\n LoginResponse,\r\n LogoutResponse,\r\n GetUserResponse,\r\n VerifyEmailResponse,\r\n ResendVerificationResponse,\r\n UpdateProfileData,\r\n UpdateProfileResponse,\r\n DeleteAccountResponse,\r\n GetOrdersResponse,\r\n WishlistResponse,\r\n AddToWishlistResponse,\r\n RemoveFromWishlistResponse,\r\n ForgotPasswordResponse,\r\n ResetPasswordResponse,\r\n} from \"../types/index.js\";\r\nimport type { Fetcher } from \"../utils/fetch.js\";\r\n\r\n/**\r\n * Build headers for authenticated customer requests\r\n */\r\nfunction buildSessionHeaders(sessionId: string): Record<string, string> {\r\n return { \"x-session-id\": sessionId };\r\n}\r\n\r\n/**\r\n * Customer resource for authentication and account management\r\n */\r\nexport function createCustomerResource(fetcher: Fetcher) {\r\n return {\r\n /**\r\n * Register a new customer account.\r\n * A verification email is sent automatically by the server.\r\n * The customer must verify their email before logging in.\r\n *\r\n * @param data - Registration data (firstName, lastName, email, password)\r\n * @param fetchOptions - Fetch options\r\n * @returns Created customer data and success message\r\n *\r\n * @example\r\n * ```typescript\r\n * const { customer, message } = await client.customer.register({\r\n * firstName: 'John',\r\n * lastName: 'Doe',\r\n * email: 'john@example.com',\r\n * password: 'securePassword123'\r\n * });\r\n *\r\n * // Verification email is sent automatically by the server\r\n * console.log('Account created:', message);\r\n * ```\r\n */\r\n async register(\r\n data: RegisterData,\r\n fetchOptions?: FetchOptions\r\n ): Promise<RegisterResponse> {\r\n return fetcher.request<RegisterResponse>(\r\n \"/api/storefront/v1/customer/(auth)/register\",\r\n {\r\n method: \"POST\",\r\n body: data,\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Log in an existing customer.\r\n * Returns a session ID that must be stored and passed to authenticated endpoints.\r\n *\r\n * @param email - Customer's email address\r\n * @param password - Customer's password\r\n * @param options - Login options (optional cartId for cart merging)\r\n * @param fetchOptions - Fetch options\r\n * @returns Session ID and customer data\r\n * @throws ValidationError if email is not verified (check error for requiresVerification)\r\n *\r\n * @example\r\n * ```typescript\r\n * try {\r\n * const { sessionId, customer, expiresAt } = await client.customer.login(\r\n * 'john@example.com',\r\n * 'securePassword123',\r\n * { cartId: guestCartId } // Optional: merge guest cart\r\n * );\r\n *\r\n * // Store sessionId in a cookie\r\n * cookies().set('session-id', sessionId, {\r\n * httpOnly: true,\r\n * expires: new Date(expiresAt)\r\n * });\r\n * } catch (error) {\r\n * if (error.requiresVerification) {\r\n * // Prompt user to verify email\r\n * await client.customer.resendVerification(error.customerId);\r\n * }\r\n * }\r\n * ```\r\n */\r\n async login(\r\n email: string,\r\n password: string,\r\n options?: LoginOptions,\r\n fetchOptions?: FetchOptions\r\n ): Promise<LoginResponse> {\r\n const headers: Record<string, string> = {};\r\n if (options?.cartId) {\r\n headers[\"x-cart-id\"] = options.cartId;\r\n }\r\n\r\n return fetcher.request<LoginResponse>(\r\n \"/api/storefront/v1/customer/(auth)/login\",\r\n {\r\n method: \"POST\",\r\n body: { email, password },\r\n headers,\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Log out the current customer and invalidate their session.\r\n * If the customer had items in their cart, they are migrated to a new guest cart.\r\n *\r\n * @param sessionId - The customer's session ID\r\n * @param fetchOptions - Fetch options\r\n * @returns Logout confirmation with optional new guest cart ID\r\n *\r\n * @example\r\n * ```typescript\r\n * const { cartId } = await client.customer.logout(sessionId);\r\n *\r\n * // Clear session cookie\r\n * cookies().delete('session-id');\r\n *\r\n * // If cart was migrated, store the new guest cart ID\r\n * if (cartId) {\r\n * cookies().set('cart-id', cartId);\r\n * }\r\n * ```\r\n */\r\n async logout(\r\n sessionId: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<LogoutResponse> {\r\n return fetcher.request<LogoutResponse>(\r\n \"/api/storefront/v1/customer/(auth)/logout\",\r\n {\r\n method: \"POST\",\r\n headers: buildSessionHeaders(sessionId),\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Get the currently authenticated customer's profile.\r\n *\r\n * @param sessionId - The customer's session ID\r\n * @param fetchOptions - Fetch options\r\n * @returns Current customer data\r\n * @throws AuthError if session is invalid or expired\r\n *\r\n * @example\r\n * ```typescript\r\n * const sessionId = cookies().get('session-id')?.value;\r\n * if (sessionId) {\r\n * const { customer } = await client.customer.getUser(sessionId);\r\n * console.log(`Welcome back, ${customer.firstName}!`);\r\n * }\r\n * ```\r\n */\r\n async getUser(\r\n sessionId: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<GetUserResponse> {\r\n return fetcher.request<GetUserResponse>(\r\n \"/api/storefront/v1/customer/(auth)/get-user\",\r\n {\r\n method: \"GET\",\r\n headers: buildSessionHeaders(sessionId),\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Verify a customer's email address using the token sent during registration.\r\n *\r\n * @param token - Email verification token\r\n * @param fetchOptions - Fetch options\r\n * @returns Verification confirmation\r\n * @throws ValidationError if token is invalid or expired\r\n *\r\n * @example\r\n * ```typescript\r\n * // Token comes from the verification email link\r\n * const token = searchParams.get('token');\r\n *\r\n * const { message } = await client.customer.verifyEmail(token);\r\n * console.log(message); // \"Email verified successfully. You can now log in.\"\r\n * ```\r\n */\r\n async verifyEmail(\r\n token: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<VerifyEmailResponse> {\r\n return fetcher.request<VerifyEmailResponse>(\r\n \"/api/storefront/v1/customer/(auth)/verify-email\",\r\n {\r\n method: \"GET\",\r\n params: { token },\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Resend the verification email for an unverified customer.\r\n * A new verification email is sent automatically by the server.\r\n *\r\n * @param customerId - The customer's ID (from failed login response)\r\n * @param fetchOptions - Fetch options\r\n * @returns Success message\r\n * @throws ValidationError if customer is already verified or not found\r\n *\r\n * @example\r\n * ```typescript\r\n * // After login fails with requiresVerification\r\n * const { message } = await client.customer.resendVerification(customerId);\r\n *\r\n * // Verification email is sent automatically by the server\r\n * console.log(message); // \"Verification email sent.\"\r\n * ```\r\n */\r\n async resendVerification(\r\n customerId: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<ResendVerificationResponse> {\r\n return fetcher.request<ResendVerificationResponse>(\r\n \"/api/storefront/v1/customer/(auth)/resend-verification\",\r\n {\r\n method: \"POST\",\r\n body: { customerId },\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Request a password reset for a customer account.\r\n * The server sends a password reset email directly to the customer.\r\n * Returns success even if email doesn't exist (to prevent email enumeration).\r\n *\r\n * Note: The reset token is never exposed to the client for security.\r\n * The email is sent server-side with the reset link.\r\n *\r\n * @param email - Customer's email address\r\n * @param fetchOptions - Fetch options\r\n * @returns Generic success message (same whether email exists or not)\r\n *\r\n * @example\r\n * ```typescript\r\n * const response = await client.customer.forgotPassword('john@example.com');\r\n *\r\n * // Always show same message to user (email sent server-side)\r\n * console.log(response.message);\r\n * // \"If an account exists with that email, password reset instructions have been sent.\"\r\n * ```\r\n */\r\n async forgotPassword(\r\n email: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<ForgotPasswordResponse> {\r\n return fetcher.request<ForgotPasswordResponse>(\r\n \"/api/storefront/v1/customer/(auth)/forgot-password\",\r\n {\r\n method: \"POST\",\r\n body: { email },\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Reset a customer's password using a valid reset token.\r\n * The token is sent via email by the forgotPassword endpoint.\r\n * After successful reset, all existing sessions are invalidated.\r\n *\r\n * @param token - Password reset token (from email link)\r\n * @param password - New password (minimum 8 characters)\r\n * @param fetchOptions - Fetch options\r\n * @returns Success confirmation\r\n * @throws ValidationError if token is invalid or expired\r\n *\r\n * @example\r\n * ```typescript\r\n * // Token comes from the reset email link\r\n * const token = searchParams.get('token');\r\n *\r\n * try {\r\n * const { message } = await client.customer.resetPassword(token, newPassword);\r\n * console.log(message); // \"Password reset successful...\"\r\n *\r\n * // Redirect to login page\r\n * redirect('/login?reset=success');\r\n * } catch (error) {\r\n * if (error instanceof ValidationError) {\r\n * // Token invalid or expired\r\n * console.error('Please request a new password reset');\r\n * }\r\n * }\r\n * ```\r\n */\r\n async resetPassword(\r\n token: string,\r\n password: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<ResetPasswordResponse> {\r\n return fetcher.request<ResetPasswordResponse>(\r\n \"/api/storefront/v1/customer/(auth)/reset-password\",\r\n {\r\n method: \"POST\",\r\n body: { token, password },\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n // =========================================================================\r\n // Profile Management Methods\r\n // =========================================================================\r\n\r\n /**\r\n * Update the authenticated customer's profile.\r\n *\r\n * @param sessionId - The customer's session ID\r\n * @param data - Profile data to update (firstName, lastName, email)\r\n * @param fetchOptions - Fetch options\r\n * @returns Updated customer data\r\n * @throws AuthError if session is invalid\r\n * @throws ValidationError if email is already taken by another customer\r\n *\r\n * @example\r\n * ```typescript\r\n * const { customer } = await client.customer.updateProfile(sessionId, {\r\n * firstName: 'Jane',\r\n * lastName: 'Smith',\r\n * email: 'jane.smith@example.com'\r\n * });\r\n *\r\n * console.log('Profile updated:', customer.email);\r\n * ```\r\n */\r\n async updateProfile(\r\n sessionId: string,\r\n data: UpdateProfileData,\r\n fetchOptions?: FetchOptions\r\n ): Promise<UpdateProfileResponse> {\r\n return fetcher.request<UpdateProfileResponse>(\r\n \"/api/storefront/v1/customer/edit-user\",\r\n {\r\n method: \"PATCH\",\r\n headers: buildSessionHeaders(sessionId),\r\n body: data,\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Delete the authenticated customer's account.\r\n * This action is permanent and cannot be undone.\r\n * All associated data (sessions, wishlist, etc.) will be deleted.\r\n *\r\n * @param sessionId - The customer's session ID\r\n * @param fetchOptions - Fetch options\r\n * @returns Deletion confirmation\r\n * @throws AuthError if session is invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * // Confirm with user before calling\r\n * if (confirm('Are you sure you want to delete your account?')) {\r\n * await client.customer.deleteAccount(sessionId);\r\n *\r\n * // Clear session cookie\r\n * cookies().delete('session-id');\r\n *\r\n * // Redirect to home page\r\n * redirect('/');\r\n * }\r\n * ```\r\n */\r\n async deleteAccount(\r\n sessionId: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<DeleteAccountResponse> {\r\n return fetcher.request<DeleteAccountResponse>(\r\n \"/api/storefront/v1/customer/delete-user\",\r\n {\r\n method: \"DELETE\",\r\n headers: buildSessionHeaders(sessionId),\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Get the customer's order history.\r\n * Returns all orders with line items and product details.\r\n *\r\n * @param sessionId - The customer's session ID\r\n * @param customerId - The customer's ID\r\n * @param fetchOptions - Fetch options\r\n * @returns List of customer orders\r\n *\r\n * @example\r\n * ```typescript\r\n * const { orders } = await client.customer.getOrders(sessionId, customerId);\r\n *\r\n * orders.forEach(order => {\r\n * console.log(`Order #${order.orderNumber}: ${order.status}`);\r\n * order.OrderLineItems.forEach(item => {\r\n * console.log(` - ${item.name} x${item.quantity}`);\r\n * });\r\n * });\r\n * ```\r\n */\r\n async getOrders(\r\n sessionId: string,\r\n customerId: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<GetOrdersResponse> {\r\n return fetcher.request<GetOrdersResponse>(\r\n `/api/storefront/v1/customer/get-orders/${customerId}`,\r\n {\r\n method: \"GET\",\r\n headers: buildSessionHeaders(sessionId),\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n // =========================================================================\r\n // Wishlist (Nested Resource)\r\n // =========================================================================\r\n\r\n /**\r\n * Wishlist management methods.\r\n * Access via `client.customer.wishlist.get()`, `.add()`, `.remove()`.\r\n */\r\n wishlist: {\r\n /**\r\n * Get the customer's wishlist.\r\n * Returns all wishlist items with product and variation details.\r\n *\r\n * @param sessionId - The customer's session ID\r\n * @param fetchOptions - Fetch options\r\n * @returns Wishlist items with product details\r\n * @throws AuthError if session is invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * const { items } = await client.customer.wishlist.get(sessionId);\r\n *\r\n * items.forEach(item => {\r\n * console.log(`${item.product.name} - $${item.product.price / 100}`);\r\n * if (item.variation) {\r\n * const options = item.variation.options\r\n * .map(o => `${o.optionType.name}: ${o.value}`)\r\n * .join(', ');\r\n * console.log(` Variant: ${options}`);\r\n * }\r\n * });\r\n * ```\r\n */\r\n async get(\r\n sessionId: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<WishlistResponse> {\r\n return fetcher.request<WishlistResponse>(\r\n \"/api/storefront/v1/customer/wishlist\",\r\n {\r\n method: \"GET\",\r\n headers: buildSessionHeaders(sessionId),\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Add a product to the customer's wishlist.\r\n *\r\n * @param sessionId - The customer's session ID\r\n * @param productId - The product ID to add\r\n * @param variationId - Optional variation ID (for products with variations)\r\n * @param fetchOptions - Fetch options\r\n * @returns Success message\r\n * @throws AuthError if session is invalid\r\n * @throws ValidationError if product already in wishlist\r\n *\r\n * @example\r\n * ```typescript\r\n * // Add a simple product\r\n * await client.customer.wishlist.add(sessionId, 'prod_123');\r\n *\r\n * // Add a product with a specific variation\r\n * await client.customer.wishlist.add(sessionId, 'prod_123', 'var_456');\r\n * ```\r\n */\r\n async add(\r\n sessionId: string,\r\n productId: string,\r\n variationId?: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<AddToWishlistResponse> {\r\n return fetcher.request<AddToWishlistResponse>(\r\n \"/api/storefront/v1/customer/wishlist\",\r\n {\r\n method: \"POST\",\r\n headers: buildSessionHeaders(sessionId),\r\n body: { productId, variationId },\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Remove a product from the customer's wishlist.\r\n *\r\n * @param sessionId - The customer's session ID\r\n * @param productId - The product ID to remove\r\n * @param variationId - Optional variation ID (must match if item was added with variation)\r\n * @param fetchOptions - Fetch options\r\n * @returns Success message\r\n * @throws AuthError if session is invalid\r\n * @throws NotFoundError if item not in wishlist\r\n *\r\n * @example\r\n * ```typescript\r\n * // Remove a simple product\r\n * await client.customer.wishlist.remove(sessionId, 'prod_123');\r\n *\r\n * // Remove a specific variation\r\n * await client.customer.wishlist.remove(sessionId, 'prod_123', 'var_456');\r\n * ```\r\n */\r\n async remove(\r\n sessionId: string,\r\n productId: string,\r\n variationId?: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<RemoveFromWishlistResponse> {\r\n return fetcher.request<RemoveFromWishlistResponse>(\r\n \"/api/storefront/v1/customer/wishlist\",\r\n {\r\n method: \"DELETE\",\r\n headers: buildSessionHeaders(sessionId),\r\n body: { productId, variationId },\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Type for the customer resource\r\n */\r\nexport type CustomerResource = ReturnType<typeof createCustomerResource>;\r\n","import type { FetchOptions, Order } from \"../types/index.js\";\r\nimport type { Fetcher } from \"../utils/fetch.js\";\r\n\r\n/**\r\n * Order resource for fetching order details\r\n *\r\n * Used for order confirmation pages and viewing order details.\r\n * For customer order history, use the customer.getOrders() method instead.\r\n */\r\nexport function createOrderResource(fetcher: Fetcher) {\r\n return {\r\n /**\r\n * Get order details by ID.\r\n *\r\n * Retrieves complete order information including line items,\r\n * customer data, and shipment method with tracking info.\r\n *\r\n * @param orderId - The order ID to fetch\r\n * @param options - Fetch options (caching, headers, etc.)\r\n * @returns Complete order details\r\n * @throws NotFoundError if order doesn't exist or belongs to different store\r\n *\r\n * @example Basic usage (order confirmation page)\r\n * ```typescript\r\n * const order = await client.order.get(orderId);\r\n * console.log(`Order #${order.orderNumber} - ${order.status}`);\r\n * console.log(`Total: ${order.totalAmount / 100} EUR`);\r\n * ```\r\n *\r\n * @example Next.js - with caching\r\n * ```typescript\r\n * const order = await client.order.get(orderId, {\r\n * next: { revalidate: 60, tags: ['order', orderId] }\r\n * });\r\n * ```\r\n *\r\n * @example Display line items\r\n * ```typescript\r\n * const order = await client.order.get(orderId);\r\n * order.OrderLineItems.forEach(item => {\r\n * if (item.itemType !== 'SHIPPING') {\r\n * console.log(`${item.name} x${item.quantity} = ${item.totalAmount / 100} EUR`);\r\n * }\r\n * });\r\n * ```\r\n *\r\n * @example Show tracking info\r\n * ```typescript\r\n * const order = await client.order.get(orderId);\r\n * if (order.orderShipmentMethod?.trackingNumber) {\r\n * console.log(`Tracking: ${order.orderShipmentMethod.trackingNumber}`);\r\n * order.orderShipmentMethod.trackingUrls?.forEach(url => {\r\n * console.log(`Track at: ${url}`);\r\n * });\r\n * }\r\n * ```\r\n */\r\n async get(orderId: string, options?: FetchOptions): Promise<Order> {\r\n return fetcher.request<Order>(\r\n `/api/storefront/v1/order/${encodeURIComponent(orderId)}`,\r\n {\r\n ...options,\r\n }\r\n );\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Type for the order resource\r\n */\r\nexport type OrderResource = ReturnType<typeof createOrderResource>;\r\n","import type {\r\n FetchOptions,\r\n CheckoutParams,\r\n StripeCheckoutResponse,\r\n PaytrailCheckoutResponse,\r\n} from \"../types/index.js\";\r\nimport type { Fetcher } from \"../utils/fetch.js\";\r\n\r\n/**\r\n * Extended options for checkout requests\r\n *\r\n * Checkout requires cart and session context via headers.\r\n */\r\nexport interface CheckoutOptions extends FetchOptions {\r\n /**\r\n * Cart ID for guest checkout.\r\n * Pass this when the user is not logged in.\r\n */\r\n cartId?: string;\r\n /**\r\n * Session ID for authenticated checkout.\r\n * Pass this when the user is logged in.\r\n */\r\n sessionId?: string;\r\n}\r\n\r\n/**\r\n * Checkout resource for payment processing\r\n *\r\n * Handles both Stripe and Paytrail payment providers.\r\n */\r\nexport function createCheckoutResource(fetcher: Fetcher) {\r\n /**\r\n * Build headers with cart/session context\r\n */\r\n function buildCheckoutHeaders(options?: CheckoutOptions): Record<string, string> {\r\n const headers: Record<string, string> = {};\r\n if (options?.cartId) {\r\n headers[\"x-cart-id\"] = options.cartId;\r\n }\r\n if (options?.sessionId) {\r\n headers[\"x-session-id\"] = options.sessionId;\r\n }\r\n return headers;\r\n }\r\n\r\n /**\r\n * Build checkout request body\r\n */\r\n function buildCheckoutBody(params: CheckoutParams) {\r\n return {\r\n orderId: params.orderId,\r\n chosenShipmentMethod: params.shipmentMethod,\r\n customerData: params.customerData,\r\n successUrl: params.successUrl,\r\n cancelUrl: params.cancelUrl,\r\n };\r\n }\r\n\r\n return {\r\n /**\r\n * Create a Stripe checkout session.\r\n *\r\n * Redirects the user to Stripe's hosted checkout page.\r\n * Cart items are validated and stock is reserved on the server.\r\n *\r\n * @param params - Checkout parameters (customer data, shipping, URLs)\r\n * @param options - Checkout options including cart/session context\r\n * @returns URL to redirect user to Stripe checkout\r\n * @throws ValidationError for invalid data or empty cart\r\n * @throws StorefrontError for inventory issues\r\n *\r\n * @example Basic usage with redirect\r\n * ```typescript\r\n * const { url } = await client.checkout.stripe({\r\n * customerData: {\r\n * first_name: \"John\",\r\n * last_name: \"Doe\",\r\n * email: \"john@example.com\",\r\n * address: \"123 Main St\",\r\n * postal_code: \"00100\",\r\n * city: \"Helsinki\",\r\n * phone: \"+358401234567\"\r\n * },\r\n * shipmentMethod: {\r\n * shipmentMethodId: \"ship_123\",\r\n * pickupId: null\r\n * },\r\n * orderId: \"order_abc123\",\r\n * successUrl: \"https://mystore.com/success\",\r\n * cancelUrl: \"https://mystore.com/cancel\"\r\n * }, {\r\n * cartId: \"cart_xyz\", // For guest users\r\n * sessionId: \"sess_123\" // For logged-in users\r\n * });\r\n *\r\n * // Redirect to Stripe\r\n * window.location.href = url;\r\n * ```\r\n */\r\n async stripe(\r\n params: CheckoutParams,\r\n options?: CheckoutOptions\r\n ): Promise<StripeCheckoutResponse> {\r\n const headers = buildCheckoutHeaders(options);\r\n const body = buildCheckoutBody(params);\r\n\r\n return fetcher.request<StripeCheckoutResponse>(\r\n \"/api/storefront/v1/payments/stripe/checkout\",\r\n {\r\n method: \"POST\",\r\n body,\r\n headers: {\r\n ...options?.headers,\r\n ...headers,\r\n },\r\n ...options,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Create a Paytrail checkout session.\r\n *\r\n * Returns payment providers for Finnish payment methods.\r\n * Cart items are validated and stock is reserved on the server.\r\n *\r\n * @param params - Checkout parameters (customer data, shipping, URLs)\r\n * @param options - Checkout options including cart/session context\r\n * @returns Paytrail response with available payment providers\r\n * @throws ValidationError for invalid data or empty cart\r\n * @throws StorefrontError for inventory issues\r\n *\r\n * @example Display payment providers\r\n * ```typescript\r\n * const response = await client.checkout.paytrail({\r\n * customerData: {\r\n * first_name: \"Matti\",\r\n * last_name: \"Meikäläinen\",\r\n * email: \"matti@example.fi\",\r\n * address: \"Mannerheimintie 1\",\r\n * postal_code: \"00100\",\r\n * city: \"Helsinki\",\r\n * phone: \"+358401234567\"\r\n * },\r\n * shipmentMethod: {\r\n * shipmentMethodId: \"ship_123\",\r\n * pickupId: \"pickup_456\" // For pickup points\r\n * },\r\n * orderId: \"order_abc123\",\r\n * successUrl: \"https://mystore.com/success\",\r\n * cancelUrl: \"https://mystore.com/cancel\"\r\n * }, {\r\n * cartId: \"cart_xyz\"\r\n * });\r\n *\r\n * // Group providers by type\r\n * const banks = response.providers.filter(p => p.group === \"bank\");\r\n * const mobile = response.providers.filter(p => p.group === \"mobile\");\r\n * const cards = response.providers.filter(p => p.group === \"creditcard\");\r\n * ```\r\n *\r\n * @example Submit payment form\r\n * ```typescript\r\n * const provider = response.providers.find(p => p.id === \"nordea\");\r\n *\r\n * // Create and submit a form\r\n * const form = document.createElement(\"form\");\r\n * form.method = \"POST\";\r\n * form.action = provider.url;\r\n *\r\n * provider.parameters.forEach(({ name, value }) => {\r\n * const input = document.createElement(\"input\");\r\n * input.type = \"hidden\";\r\n * input.name = name;\r\n * input.value = value;\r\n * form.appendChild(input);\r\n * });\r\n *\r\n * document.body.appendChild(form);\r\n * form.submit();\r\n * ```\r\n */\r\n async paytrail(\r\n params: CheckoutParams,\r\n options?: CheckoutOptions\r\n ): Promise<PaytrailCheckoutResponse> {\r\n const headers = buildCheckoutHeaders(options);\r\n const body = buildCheckoutBody(params);\r\n\r\n return fetcher.request<PaytrailCheckoutResponse>(\r\n \"/api/storefront/v1/payments/paytrail/checkout\",\r\n {\r\n method: \"POST\",\r\n body,\r\n headers: {\r\n ...options?.headers,\r\n ...headers,\r\n },\r\n ...options,\r\n }\r\n );\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Type for the checkout resource\r\n */\r\nexport type CheckoutResource = ReturnType<typeof createCheckoutResource>;\r\n","import type { StorefrontClientConfig } from \"./types/index.js\";\nimport { createFetcher } from \"./utils/fetch.js\";\nimport { createStoreResource, type StoreResource } from \"./resources/store.js\";\nimport {\n createProductsResource,\n type ProductsResource,\n} from \"./resources/products.js\";\nimport {\n createCategoriesResource,\n type CategoriesResource,\n} from \"./resources/categories.js\";\nimport { createCartResource, type CartResource } from \"./resources/cart.js\";\nimport {\n createShippingResource,\n type ShippingResource,\n} from \"./resources/shipping.js\";\nimport {\n createCustomerResource,\n type CustomerResource,\n} from \"./resources/customer.js\";\nimport {\n createOrderResource,\n type OrderResource,\n} from \"./resources/order.js\";\nimport {\n createCheckoutResource,\n type CheckoutResource,\n} from \"./resources/checkout.js\";\n\n/**\n * The Storefront API client\n */\nexport interface StorefrontClient {\n /**\n * The base URL for API requests\n */\n readonly baseUrl: string;\n\n /**\n * Store configuration resource\n */\n readonly store: StoreResource;\n\n /**\n * Products resource\n */\n readonly products: ProductsResource;\n\n /**\n * Categories resource\n */\n readonly categories: CategoriesResource;\n\n /**\n * Cart resource\n */\n readonly cart: CartResource;\n\n /**\n * Shipping resource\n */\n readonly shipping: ShippingResource;\n\n /**\n * Customer authentication and account management resource\n */\n readonly customer: CustomerResource;\n\n /**\n * Order resource for fetching order details\n */\n readonly order: OrderResource;\n\n /**\n * Checkout resource for payment processing\n */\n readonly checkout: CheckoutResource;\n}\n\n/**\n * Create a new Storefront API client\n */\nexport function createStorefrontClient(config: StorefrontClientConfig): StorefrontClient {\n if (!config.apiKey) {\n throw new Error(\"apiKey is required\");\n }\n if (!config.baseUrl) {\n throw new Error(\"baseUrl is required\");\n }\n\n // Ensure baseUrl doesn't have trailing slash\n const baseUrl = config.baseUrl.replace(/\\/$/, \"\");\n\n // Create the fetcher for making authenticated requests\n const fetcher = createFetcher({\n apiKey: config.apiKey,\n baseUrl,\n timeout: config.timeout,\n });\n\n return {\n baseUrl,\n store: createStoreResource(fetcher),\n products: createProductsResource(fetcher),\n categories: createCategoriesResource(fetcher),\n cart: createCartResource(fetcher),\n shipping: createShippingResource(fetcher),\n customer: createCustomerResource(fetcher),\n order: createOrderResource(fetcher),\n checkout: createCheckoutResource(fetcher),\n };\n}\n","/**\r\n * Pricing Utilities\r\n *\r\n * Helper functions for calculating prices with sale logic.\r\n */\r\n\r\nimport type { ProductDetail, ProductVariation } from \"../types/products.js\";\r\nimport type { PriceInfo } from \"../types/cart.js\";\r\n\r\n/**\r\n * Check if a sale is currently active based on start and end dates.\r\n *\r\n * @param startDate - Sale start date (ISO string, Date, null, or undefined)\r\n * @param endDate - Sale end date (ISO string, Date, null, or undefined)\r\n * @returns true if the sale is currently active\r\n *\r\n * @example\r\n * ```typescript\r\n * // No dates = always active\r\n * isSaleActive(null, null); // true\r\n *\r\n * // Only start date = active if past start\r\n * isSaleActive(\"2024-01-01\", null); // true if today >= Jan 1\r\n *\r\n * // Both dates = active if within range\r\n * isSaleActive(\"2024-01-01\", \"2024-12-31\"); // true if within range\r\n * ```\r\n */\r\nexport function isSaleActive(\r\n startDate: Date | string | null | undefined,\r\n endDate: Date | string | null | undefined\r\n): boolean {\r\n // If no dates are set, sale is considered active\r\n if (!startDate && !endDate) {\r\n return true;\r\n }\r\n\r\n const now = new Date();\r\n const start = startDate ? new Date(startDate) : null;\r\n const end = endDate ? new Date(endDate) : null;\r\n\r\n // If only start date is set\r\n if (start && !end) {\r\n return now >= start;\r\n }\r\n\r\n // If only end date is set\r\n if (!start && end) {\r\n return now <= end;\r\n }\r\n\r\n // If both dates are set\r\n if (start && end) {\r\n return now >= start && now <= end;\r\n }\r\n\r\n return true;\r\n}\r\n\r\n/**\r\n * Get price information for a product or variation.\r\n * Returns the effective price (sale or regular) and sale status.\r\n * All prices are in cents.\r\n *\r\n * @param product - The product to get price info for\r\n * @param variation - Optional variation (takes precedence over product price)\r\n * @returns Price information with effective price, original price, and sale status\r\n *\r\n * @example\r\n * ```typescript\r\n * // Product without variation\r\n * const priceInfo = getPriceInfo(product);\r\n * console.log(priceInfo.effectivePrice); // 1990 (cents)\r\n * console.log(priceInfo.isOnSale); // true\r\n *\r\n * // Product with selected variation\r\n * const priceInfo = getPriceInfo(product, selectedVariation);\r\n * ```\r\n */\r\nexport function getPriceInfo(\r\n product: ProductDetail,\r\n variation?: ProductVariation\r\n): PriceInfo {\r\n if (variation) {\r\n // Use variation pricing\r\n const isOnSale =\r\n isSaleActive(variation.saleStartDate, variation.saleEndDate) &&\r\n variation.salePrice !== null;\r\n\r\n const originalPrice = variation.price ?? product.price;\r\n const effectivePrice = isOnSale\r\n ? (variation.salePrice ?? originalPrice)\r\n : originalPrice;\r\n\r\n return {\r\n effectivePrice,\r\n originalPrice,\r\n isOnSale,\r\n salePercent: isOnSale ? (variation.salePercent ?? null) : null,\r\n };\r\n }\r\n\r\n // Use product pricing\r\n const isOnSale =\r\n isSaleActive(product.saleStartDate, product.saleEndDate) &&\r\n product.salePrice !== null;\r\n\r\n const originalPrice = product.price;\r\n const effectivePrice = isOnSale\r\n ? (product.salePrice ?? originalPrice)\r\n : originalPrice;\r\n\r\n return {\r\n effectivePrice,\r\n originalPrice,\r\n isOnSale,\r\n salePercent: isOnSale ? (product.salePercent ?? null) : null,\r\n };\r\n}\r\n","/**\r\n * Cart Calculation Utilities\r\n *\r\n * Functions for calculating cart totals with campaign discounts.\r\n */\r\n\r\nimport type { CartItem } from \"../types/cart.js\";\r\nimport type { Campaign } from \"../types/storeconfig.js\";\r\nimport type {\r\n CalculatedCartItem,\r\n FreeShippingStatus,\r\n CartCalculationResult,\r\n} from \"../types/cart.js\";\r\nimport { getPriceInfo } from \"./pricing.js\";\r\n\r\n/**\r\n * Internal type for tracking eligible units in Buy X Pay Y campaigns\r\n */\r\ninterface EligibleUnit {\r\n price: number;\r\n productId: string;\r\n variationId?: string;\r\n originalItem: CartItem;\r\n}\r\n\r\n/**\r\n * Calculate cart totals with campaign discounts applied.\r\n *\r\n * Supports two campaign types:\r\n * - **FREE_SHIPPING**: Free shipping when cart total exceeds minimum spend\r\n * - **BUY_X_PAY_Y**: Buy X items, pay for Y (e.g., Buy 3 Pay 2 = 1 free item)\r\n *\r\n * @param items - Cart items to calculate\r\n * @param campaigns - Active campaigns to apply\r\n * @returns Calculation result with totals, savings, and free shipping status\r\n *\r\n * @example\r\n * ```typescript\r\n * const result = calculateCartWithCampaigns(cartItems, activeCampaigns);\r\n *\r\n * console.log(result.cartTotal); // 4990 (cents)\r\n * console.log(result.totalSavings); // 1990 (cents)\r\n * console.log(result.freeShipping.isEligible); // true\r\n *\r\n * // Render calculated items\r\n * result.calculatedItems.forEach(({ item, paidQuantity, freeQuantity }) => {\r\n * console.log(`${item.product.name}: ${paidQuantity} paid, ${freeQuantity} free`);\r\n * });\r\n * ```\r\n */\r\nexport function calculateCartWithCampaigns(\r\n items: CartItem[],\r\n campaigns: Campaign[]\r\n): CartCalculationResult {\r\n // Find applicable campaigns\r\n const freeShippingCampaign = campaigns.find(\r\n (c) => c.type === \"FREE_SHIPPING\" && c.isActive\r\n );\r\n const buyXPayYCampaign = campaigns.find(\r\n (c) => c.type === \"BUY_X_PAY_Y\" && c.isActive\r\n );\r\n\r\n // Calculate original total (without campaign discounts)\r\n const originalTotal = items.reduce((total, { product, variation, cartQuantity }) => {\r\n const priceInfo = getPriceInfo(product, variation);\r\n return total + priceInfo.effectivePrice * cartQuantity;\r\n }, 0);\r\n\r\n // No Buy X Pay Y campaign - return items as-is\r\n if (!buyXPayYCampaign?.BuyXPayYCampaign) {\r\n const calculatedItems = items.map((item) => ({\r\n item,\r\n paidQuantity: item.cartQuantity,\r\n freeQuantity: 0,\r\n totalQuantity: item.cartQuantity,\r\n }));\r\n\r\n const freeShipping = calculateFreeShipping(\r\n originalTotal,\r\n freeShippingCampaign\r\n );\r\n\r\n return {\r\n calculatedItems,\r\n cartTotal: originalTotal,\r\n originalTotal,\r\n totalSavings: 0,\r\n freeShipping,\r\n };\r\n }\r\n\r\n // Apply Buy X Pay Y campaign\r\n const { buyQuantity, payQuantity, applicableCategories } =\r\n buyXPayYCampaign.BuyXPayYCampaign;\r\n const applicableCategoryIds = new Set(\r\n applicableCategories.map((c) => c.id)\r\n );\r\n\r\n // Find all individual units eligible for the campaign\r\n const eligibleUnits: EligibleUnit[] = items.flatMap((item) => {\r\n const { product, variation } = item;\r\n const itemCategories = product.categories?.map((cat) => cat.id) || [];\r\n\r\n // Check if any of the product's categories are in the campaign's list\r\n const isEligible = itemCategories.some((id) =>\r\n applicableCategoryIds.has(id)\r\n );\r\n\r\n if (isEligible) {\r\n const priceInfo = getPriceInfo(product, variation);\r\n\r\n // Create an entry for each single unit of the item\r\n return Array.from({ length: item.cartQuantity }, () => ({\r\n price: priceInfo.effectivePrice,\r\n productId: product.id,\r\n variationId: variation?.id,\r\n originalItem: item,\r\n }));\r\n }\r\n\r\n return [];\r\n });\r\n\r\n // Not enough eligible items - return original quantities\r\n if (eligibleUnits.length < buyQuantity) {\r\n const calculatedItems = items.map((item) => ({\r\n item,\r\n paidQuantity: item.cartQuantity,\r\n freeQuantity: 0,\r\n totalQuantity: item.cartQuantity,\r\n }));\r\n\r\n const freeShipping = calculateFreeShipping(\r\n originalTotal,\r\n freeShippingCampaign\r\n );\r\n\r\n return {\r\n calculatedItems,\r\n cartTotal: originalTotal,\r\n originalTotal,\r\n totalSavings: 0,\r\n freeShipping,\r\n };\r\n }\r\n\r\n // Sort by price to find the cheapest items to make free\r\n eligibleUnits.sort((a, b) => a.price - b.price);\r\n\r\n const numToMakeFree = buyQuantity - payQuantity;\r\n const itemsToMakeFree = eligibleUnits.slice(0, numToMakeFree);\r\n\r\n // Calculate total savings from free items\r\n const totalSavings = itemsToMakeFree.reduce(\r\n (sum, item) => sum + item.price,\r\n 0\r\n );\r\n\r\n // Create a map to count how many units of each product/variation should be free\r\n const freeCountMap = new Map<string, number>();\r\n for (const freebie of itemsToMakeFree) {\r\n const key = `${freebie.productId}${freebie.variationId ? `_${freebie.variationId}` : \"\"}`;\r\n freeCountMap.set(key, (freeCountMap.get(key) || 0) + 1);\r\n }\r\n\r\n // Calculate paid and free quantities for each item\r\n const calculatedItems: CalculatedCartItem[] = items.map((item) => {\r\n const key = `${item.product.id}${item.variation?.id ? `_${item.variation.id}` : \"\"}`;\r\n const freeQuantity = freeCountMap.get(key) || 0;\r\n const paidQuantity = item.cartQuantity - freeQuantity;\r\n\r\n return {\r\n item,\r\n paidQuantity: Math.max(0, paidQuantity),\r\n freeQuantity,\r\n totalQuantity: item.cartQuantity,\r\n };\r\n });\r\n\r\n // Calculate final cart total after Buy X Pay Y discounts\r\n const cartTotal = originalTotal - totalSavings;\r\n\r\n // Calculate free shipping using the final cart total\r\n const freeShipping = calculateFreeShipping(cartTotal, freeShippingCampaign);\r\n\r\n return {\r\n calculatedItems,\r\n cartTotal,\r\n originalTotal,\r\n totalSavings,\r\n freeShipping,\r\n };\r\n}\r\n\r\n/**\r\n * Calculate free shipping eligibility\r\n */\r\nfunction calculateFreeShipping(\r\n cartTotal: number,\r\n campaign?: Campaign\r\n): FreeShippingStatus {\r\n if (!campaign?.FreeShippingCampaign) {\r\n return {\r\n isEligible: false,\r\n minimumSpend: 0,\r\n remainingAmount: 0,\r\n };\r\n }\r\n\r\n const minimumSpend = campaign.FreeShippingCampaign.minimumSpend;\r\n const isEligible = cartTotal >= minimumSpend;\r\n const remainingAmount = isEligible ? 0 : minimumSpend - cartTotal;\r\n\r\n // Extract eligible shipment method IDs from the campaign\r\n const eligibleShipmentMethodIds = campaign.FreeShippingCampaign.shipmentMethods?.map(\r\n (method) => method.id\r\n );\r\n\r\n return {\r\n isEligible,\r\n minimumSpend,\r\n remainingAmount,\r\n campaignName: campaign.name,\r\n eligibleShipmentMethodIds,\r\n };\r\n}\r\n"],"mappings":"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","names":["isOnSale","originalPrice","effectivePrice","calculatedItems","freeShipping"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/errors.ts","../src/utils/fetch.ts","../src/resources/store.ts","../src/resources/products.ts","../src/resources/categories.ts","../src/resources/cart.ts","../src/resources/shipping.ts","../src/resources/customer.ts","../src/resources/order.ts","../src/resources/checkout.ts","../src/client.ts","../src/utils/pricing.ts","../src/utils/cart-calculations.ts"],"sourcesContent":["/**\n * Base error class for all Storefront API errors\n */\nexport class StorefrontError extends Error {\n public readonly status: number;\n public readonly code: string;\n\n constructor(message: string, status: number, code: string) {\n super(message);\n this.name = \"StorefrontError\";\n this.status = status;\n this.code = code;\n\n // Maintains proper stack trace in V8 environments\n const ErrorWithCapture = Error as typeof Error & {\n captureStackTrace?: (target: object, constructor: Function) => void;\n };\n if (ErrorWithCapture.captureStackTrace) {\n ErrorWithCapture.captureStackTrace(this, StorefrontError);\n }\n }\n}\n\n/**\n * Error thrown when API returns 401 Unauthorized\n */\nexport class AuthError extends StorefrontError {\n constructor(message: string = \"Invalid or missing API key\") {\n super(message, 401, \"UNAUTHORIZED\");\n this.name = \"AuthError\";\n }\n}\n\n/**\n * Error thrown when API returns 429 Too Many Requests\n */\nexport class RateLimitError extends StorefrontError {\n public readonly retryAfter: number | null;\n\n constructor(message: string = \"Rate limit exceeded\", retryAfter: number | null = null) {\n super(message, 429, \"RATE_LIMIT_EXCEEDED\");\n this.name = \"RateLimitError\";\n this.retryAfter = retryAfter;\n }\n}\n\n/**\n * Error thrown when a requested resource is not found (404)\n */\nexport class NotFoundError extends StorefrontError {\n constructor(message: string = \"Resource not found\") {\n super(message, 404, \"NOT_FOUND\");\n this.name = \"NotFoundError\";\n }\n}\n\n/**\n * Error thrown when request validation fails (400)\n */\nexport class ValidationError extends StorefrontError {\n constructor(message: string = \"Validation failed\") {\n super(message, 400, \"VALIDATION_ERROR\");\n this.name = \"ValidationError\";\n }\n}\n\n/**\n * Error thrown when login fails due to unverified email\n * Contains customerId for resending verification email\n */\nexport class VerificationRequiredError extends StorefrontError {\n public readonly requiresVerification: true = true;\n public readonly customerId: string;\n\n constructor(message: string, customerId: string) {\n super(message, 403, \"VERIFICATION_REQUIRED\");\n this.name = \"VerificationRequiredError\";\n this.customerId = customerId;\n }\n}\n","import type { FetchOptions } from \"../types/index.js\";\r\nimport {\r\n StorefrontError,\r\n AuthError,\r\n RateLimitError,\r\n NotFoundError,\r\n ValidationError,\r\n VerificationRequiredError,\r\n} from \"./errors.js\";\r\n\r\n// SDK version - will be replaced during build or read from package.json\r\nconst SDK_VERSION = \"0.1.0\";\r\n\r\nexport interface FetcherConfig {\r\n apiKey: string;\r\n baseUrl: string;\r\n timeout?: number;\r\n}\r\n\r\nexport interface RequestOptions extends FetchOptions {\r\n method?: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"PATCH\";\r\n body?: unknown;\r\n params?: Record<string, string | number | boolean | undefined>;\r\n}\r\n\r\n/**\r\n * Fetcher instance type returned by createFetcher\r\n */\r\nexport type Fetcher = ReturnType<typeof createFetcher>;\r\n\r\n/**\r\n * Create a configured fetcher instance for making API requests\r\n */\r\nexport function createFetcher(config: FetcherConfig) {\r\n const { apiKey, baseUrl, timeout = 30000 } = config;\r\n\r\n /**\r\n * Make an authenticated request to the Storefront API\r\n */\r\n async function request<T>(endpoint: string, options: RequestOptions = {}): Promise<T> {\r\n const { method = \"GET\", body, params, signal, headers = {}, cache, ...frameworkOptions } = options;\r\n\r\n // Build URL with query parameters\r\n // Ensure baseUrl ends with / for proper URL resolution\r\n const normalizedBase = baseUrl.endsWith(\"/\") ? baseUrl : `${baseUrl}/`;\r\n // Remove leading slash from endpoint to avoid URL resolution issues\r\n const normalizedEndpoint = endpoint.startsWith(\"/\") ? endpoint.slice(1) : endpoint;\r\n const url = new URL(normalizedEndpoint, normalizedBase);\r\n\r\n if (params) {\r\n for (const [key, value] of Object.entries(params)) {\r\n if (value !== undefined) {\r\n url.searchParams.set(key, String(value));\r\n }\r\n }\r\n }\r\n\r\n // Create abort controller for timeout\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), timeout);\r\n\r\n // Combine signals if provided\r\n const combinedSignal = signal\r\n ? AbortSignal.any([signal, controller.signal])\r\n : controller.signal;\r\n\r\n try {\r\n const fetchOptions: RequestInit & Record<string, unknown> = {\r\n method,\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n \"x-api-key\": apiKey,\r\n \"x-sdk-version\": SDK_VERSION,\r\n ...headers,\r\n },\r\n body: body ? JSON.stringify(body) : undefined,\r\n signal: combinedSignal,\r\n cache,\r\n // Spread framework-specific options (e.g., Next.js `next`, or any other)\r\n ...frameworkOptions,\r\n };\r\n\r\n const response = await fetch(url.toString(), fetchOptions);\r\n\r\n clearTimeout(timeoutId);\r\n\r\n // Handle error responses\r\n if (!response.ok) {\r\n await handleErrorResponse(response);\r\n }\r\n\r\n // Parse response\r\n const data = await response.json();\r\n return data as T;\r\n } catch (error) {\r\n clearTimeout(timeoutId);\r\n\r\n // Re-throw SDK errors\r\n if (error instanceof StorefrontError) {\r\n throw error;\r\n }\r\n\r\n // Handle abort/timeout\r\n if (error instanceof Error && error.name === \"AbortError\") {\r\n throw new StorefrontError(\"Request timed out\", 408, \"TIMEOUT\");\r\n }\r\n\r\n // Handle network errors\r\n throw new StorefrontError(\r\n error instanceof Error ? error.message : \"Network error\",\r\n 0,\r\n \"NETWORK_ERROR\"\r\n );\r\n }\r\n }\r\n\r\n return { request };\r\n}\r\n\r\n/**\r\n * Error response JSON structure\r\n */\r\ninterface ErrorResponseJson {\r\n error?: string;\r\n requiresVerification?: boolean;\r\n customerId?: string;\r\n}\r\n\r\n/**\r\n * Handle non-2xx responses and throw appropriate errors\r\n */\r\nasync function handleErrorResponse(response: Response): Promise<never> {\r\n let errorData: ErrorResponseJson = {};\r\n\r\n try {\r\n const json: unknown = await response.json();\r\n if (json && typeof json === \"object\") {\r\n errorData = json as ErrorResponseJson;\r\n }\r\n } catch {\r\n // Response body is not JSON\r\n }\r\n\r\n const message = errorData.error || response.statusText || \"Request failed\";\r\n\r\n // Check for verification required error (can be 400 or 403)\r\n if (errorData.requiresVerification && errorData.customerId) {\r\n throw new VerificationRequiredError(message, errorData.customerId);\r\n }\r\n\r\n switch (response.status) {\r\n case 401:\r\n throw new AuthError(message);\r\n\r\n case 404:\r\n throw new NotFoundError(message);\r\n\r\n case 429: {\r\n const retryAfter = response.headers.get(\"Retry-After\");\r\n throw new RateLimitError(message, retryAfter ? parseInt(retryAfter, 10) : null);\r\n }\r\n\r\n case 400:\r\n throw new ValidationError(message);\r\n\r\n default:\r\n throw new StorefrontError(message, response.status, \"API_ERROR\");\r\n }\r\n}\r\n","import type { FetchOptions, StoreConfig } from \"../types/index.js\";\r\nimport type { Fetcher } from \"../utils/fetch.js\";\r\n\r\n/**\r\n * Store resource for fetching store configuration\r\n */\r\nexport function createStoreResource(fetcher: Fetcher) {\r\n return {\r\n /**\r\n * Get the complete store configuration including settings, SEO, payments, campaigns, and features.\r\n *\r\n * @example Basic usage\r\n * ```typescript\r\n * const config = await client.store.getConfig();\r\n * console.log(config.store.name);\r\n * console.log(config.seo.seoTitle);\r\n * console.log(config.campaigns);\r\n * ```\r\n *\r\n * @example Next.js - with caching\r\n * ```typescript\r\n * const config = await client.store.getConfig({\r\n * next: { revalidate: 300, tags: ['store-config'] }\r\n * });\r\n * ```\r\n *\r\n * @example Nuxt - wrap with useAsyncData\r\n * ```typescript\r\n * const { data: config } = await useAsyncData(\r\n * 'store-config',\r\n * () => client.store.getConfig()\r\n * );\r\n * ```\r\n *\r\n * @example Standard fetch caching\r\n * ```typescript\r\n * const config = await client.store.getConfig({\r\n * cache: 'force-cache'\r\n * });\r\n * ```\r\n */\r\n async getConfig(options?: FetchOptions): Promise<StoreConfig> {\r\n return fetcher.request<StoreConfig>(\"/api/storefront/v1/store-config\", {\r\n ...options,\r\n });\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Type for the store resource\r\n */\r\nexport type StoreResource = ReturnType<typeof createStoreResource>;\r\n","import type {\r\n FetchOptions,\r\n Product,\r\n ProductDetail,\r\n ProductListResponse,\r\n ProductCountResponse,\r\n ProductListParams,\r\n} from \"../types/index.js\";\r\nimport type { Fetcher } from \"../utils/fetch.js\";\r\n\r\n/**\r\n * Products resource for fetching product data\r\n */\r\nexport function createProductsResource(fetcher: Fetcher) {\r\n return {\r\n /**\r\n * Get latest products ordered by creation date (newest first).\r\n *\r\n * @param take - Number of products to return (required, must be >= 1)\r\n * @param options - Fetch options (caching, headers, etc.)\r\n * @returns Array of products\r\n *\r\n * @example Basic usage\r\n * ```typescript\r\n * const products = await client.products.latest(6);\r\n * ```\r\n *\r\n * @example Next.js - with caching\r\n * ```typescript\r\n * const products = await client.products.latest(6, {\r\n * next: { revalidate: 3600, tags: ['products'] }\r\n * });\r\n * ```\r\n */\r\n async latest(take: number, options?: FetchOptions): Promise<Product[]> {\r\n return fetcher.request<Product[]>(\"/api/storefront/v1/latest-products\", {\r\n params: { take },\r\n ...options,\r\n });\r\n },\r\n\r\n /**\r\n * Get a single product by its URL slug.\r\n *\r\n * @param slug - Product URL slug\r\n * @param options - Fetch options (caching, headers, etc.)\r\n * @returns Full product details including categories and variations\r\n * @throws NotFoundError if product doesn't exist or is not visible\r\n *\r\n * @example Basic usage\r\n * ```typescript\r\n * const product = await client.products.getBySlug('my-product');\r\n * console.log(product.name, product.categories);\r\n * ```\r\n *\r\n * @example Next.js - with caching\r\n * ```typescript\r\n * const product = await client.products.getBySlug('my-product', {\r\n * next: { revalidate: 3600, tags: ['product', 'my-product'] }\r\n * });\r\n * ```\r\n */\r\n async getBySlug(\r\n slug: string,\r\n options?: FetchOptions\r\n ): Promise<ProductDetail> {\r\n return fetcher.request<ProductDetail>(\r\n `/api/storefront/v1/product/${encodeURIComponent(slug)}`,\r\n {\r\n ...options,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Get total product count, optionally filtered by category.\r\n *\r\n * @param slugs - Optional category slugs to filter by\r\n * @param options - Fetch options (caching, headers, etc.)\r\n * @returns Object with count property\r\n *\r\n * @example Get total count\r\n * ```typescript\r\n * const { count } = await client.products.count();\r\n * console.log(`Total products: ${count}`);\r\n * ```\r\n *\r\n * @example Get count for specific category\r\n * ```typescript\r\n * const { count } = await client.products.count(['shoes']);\r\n * console.log(`Products in shoes: ${count}`);\r\n * ```\r\n */\r\n async count(\r\n slugs?: string[],\r\n options?: FetchOptions\r\n ): Promise<ProductCountResponse> {\r\n const searchParams = new URLSearchParams();\r\n if (slugs?.length) {\r\n slugs.forEach((s) => searchParams.append(\"slugs\", s));\r\n }\r\n const query = searchParams.toString();\r\n const endpoint = `/api/storefront/v1/products-count${query ? `?${query}` : \"\"}`;\r\n\r\n return fetcher.request<ProductCountResponse>(endpoint, {\r\n ...options,\r\n });\r\n },\r\n\r\n /**\r\n * Get sorted products with pagination.\r\n * Uses optimized sorting with pre-computed effective prices.\r\n *\r\n * @param params - Query parameters (slugs, page, pageSize, sort)\r\n * @param options - Fetch options (caching, headers, etc.)\r\n * @returns Products list with totalCount for pagination\r\n *\r\n * @example Basic usage\r\n * ```typescript\r\n * const { products, totalCount } = await client.products.sorted({\r\n * page: 1,\r\n * pageSize: 12,\r\n * sort: 'newest'\r\n * });\r\n * ```\r\n *\r\n * @example Filter by category\r\n * ```typescript\r\n * const { products, totalCount } = await client.products.sorted({\r\n * slugs: ['shoes', 'clothing'],\r\n * page: 1,\r\n * pageSize: 24,\r\n * sort: 'price_asc'\r\n * });\r\n * ```\r\n *\r\n * @example Real-time data (no cache)\r\n * ```typescript\r\n * const data = await client.products.sorted(\r\n * { page: 1, pageSize: 12 },\r\n * { cache: 'no-store' }\r\n * );\r\n * ```\r\n */\r\n async sorted(\r\n params: ProductListParams = {},\r\n options?: FetchOptions\r\n ): Promise<ProductListResponse> {\r\n const searchParams = new URLSearchParams();\r\n if (params.page) searchParams.set(\"page\", params.page.toString());\r\n if (params.pageSize)\r\n searchParams.set(\"pageSize\", params.pageSize.toString());\r\n if (params.sort) searchParams.set(\"sort\", params.sort);\r\n if (params.slugs?.length) {\r\n params.slugs.forEach((s) => searchParams.append(\"slugs\", s));\r\n }\r\n const query = searchParams.toString();\r\n const endpoint = `/api/storefront/v1/sorted-products${query ? `?${query}` : \"\"}`;\r\n\r\n return fetcher.request<ProductListResponse>(endpoint, {\r\n ...options,\r\n });\r\n },\r\n\r\n /**\r\n * Get filtered products with pagination.\r\n * Similar to sorted() but without totalCount in response.\r\n * Useful for sitemaps and bulk fetches.\r\n *\r\n * @param params - Query parameters (slugs, page, pageSize, sort)\r\n * @param options - Fetch options (caching, headers, etc.)\r\n * @returns Products list with category name\r\n *\r\n * @example Fetch all products for sitemap\r\n * ```typescript\r\n * const { products } = await client.products.filtered({\r\n * slugs: ['all-products'],\r\n * page: 1,\r\n * pageSize: 1000\r\n * });\r\n * ```\r\n */\r\n async filtered(\r\n params: ProductListParams = {},\r\n options?: FetchOptions\r\n ): Promise<Omit<ProductListResponse, \"totalCount\">> {\r\n const searchParams = new URLSearchParams();\r\n if (params.page) searchParams.set(\"page\", params.page.toString());\r\n if (params.pageSize)\r\n searchParams.set(\"pageSize\", params.pageSize.toString());\r\n if (params.sort) searchParams.set(\"sort\", params.sort);\r\n if (params.slugs?.length) {\r\n params.slugs.forEach((s) => searchParams.append(\"slugs\", s));\r\n }\r\n const query = searchParams.toString();\r\n const endpoint = `/api/storefront/v1/filtered-products${query ? `?${query}` : \"\"}`;\r\n\r\n return fetcher.request<Omit<ProductListResponse, \"totalCount\">>(\r\n endpoint,\r\n {\r\n ...options,\r\n }\r\n );\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Type for the products resource\r\n */\r\nexport type ProductsResource = ReturnType<typeof createProductsResource>;\r\n","import type { FetchOptions, Category, CategoryResponse } from \"../types/index.js\";\r\nimport type { Fetcher } from \"../utils/fetch.js\";\r\n\r\n/**\r\n * Categories resource for fetching category data\r\n */\r\nexport function createCategoriesResource(fetcher: Fetcher) {\r\n return {\r\n /**\r\n * Get all top-level categories with nested children.\r\n * Returns a hierarchical tree of categories (up to 5 levels deep).\r\n *\r\n * @param options - Fetch options (caching, headers, etc.)\r\n * @returns Array of top-level categories with nested children\r\n *\r\n * @example Basic usage\r\n * ```typescript\r\n * const categories = await client.categories.list();\r\n * categories.forEach(cat => {\r\n * console.log(cat.name, cat.children.length);\r\n * });\r\n * ```\r\n *\r\n * @example Next.js - with caching\r\n * ```typescript\r\n * const categories = await client.categories.list({\r\n * next: { revalidate: 3600, tags: ['categories'] }\r\n * });\r\n * ```\r\n */\r\n async list(options?: FetchOptions): Promise<Category[]> {\r\n return fetcher.request<Category[]>(\"/api/storefront/v1/categories\", {\r\n ...options,\r\n });\r\n },\r\n\r\n /**\r\n * Get a single category by its URL slug.\r\n *\r\n * @param slug - Category URL slug\r\n * @param options - Fetch options (caching, headers, etc.)\r\n * @returns Category data\r\n * @throws NotFoundError if category doesn't exist\r\n *\r\n * @example Basic usage\r\n * ```typescript\r\n * const { category } = await client.categories.getBySlug('shoes');\r\n * console.log(category.name);\r\n * ```\r\n *\r\n * @example Next.js - with caching\r\n * ```typescript\r\n * const { category } = await client.categories.getBySlug('shoes', {\r\n * next: { revalidate: 86400, tags: ['category', 'shoes'] }\r\n * });\r\n * ```\r\n */\r\n async getBySlug(\r\n slug: string,\r\n options?: FetchOptions\r\n ): Promise<CategoryResponse> {\r\n return fetcher.request<CategoryResponse>(\r\n `/api/storefront/v1/categories/${encodeURIComponent(slug)}`,\r\n {\r\n ...options,\r\n }\r\n );\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Type for the categories resource\r\n */\r\nexport type CategoriesResource = ReturnType<typeof createCategoriesResource>;\r\n","/**\r\n * Cart Resource\r\n *\r\n * Methods for managing the shopping cart stored in Redis.\r\n * Supports both guest carts (via cartId) and authenticated user carts (via sessionId).\r\n */\r\n\r\nimport type {\r\n FetchOptions,\r\n CartResponse,\r\n CartValidationResponse,\r\n CartSessionOptions,\r\n AddToCartParams,\r\n UpdateCartQuantityParams,\r\n RemoveFromCartParams,\r\n} from \"../types/index.js\";\r\nimport type { Fetcher } from \"../utils/fetch.js\";\r\n\r\n/**\r\n * Build headers object for cart operations\r\n */\r\nfunction buildCartHeaders(options?: CartSessionOptions): Record<string, string> {\r\n const headers: Record<string, string> = {};\r\n if (options?.cartId) {\r\n headers[\"x-cart-id\"] = options.cartId;\r\n }\r\n if (options?.sessionId) {\r\n headers[\"x-session-id\"] = options.sessionId;\r\n }\r\n return headers;\r\n}\r\n\r\n/**\r\n * Cart resource for managing shopping cart\r\n */\r\nexport function createCartResource(fetcher: Fetcher) {\r\n return {\r\n /**\r\n * Fetch the current cart contents.\r\n *\r\n * @param options - Cart session options (cartId for guests, sessionId for logged-in users)\r\n * @param fetchOptions - Fetch options (caching, headers, etc.)\r\n * @returns Cart items and cartId (for guests)\r\n *\r\n * @example Guest user\r\n * ```typescript\r\n * const cartId = localStorage.getItem('cart-id');\r\n * const { items, cartId: newCartId } = await client.cart.get({ cartId });\r\n * ```\r\n *\r\n * @example Logged-in user\r\n * ```typescript\r\n * const { items } = await client.cart.get({ sessionId });\r\n * ```\r\n */\r\n async get(\r\n options?: CartSessionOptions,\r\n fetchOptions?: FetchOptions\r\n ): Promise<CartResponse> {\r\n return fetcher.request<CartResponse>(\"/api/storefront/v1/cart\", {\r\n method: \"GET\",\r\n headers: buildCartHeaders(options),\r\n ...fetchOptions,\r\n });\r\n },\r\n\r\n /**\r\n * Add an item to the cart.\r\n * If the item already exists, quantity is incremented.\r\n *\r\n * @param params - Add to cart parameters\r\n * @param fetchOptions - Fetch options\r\n * @returns Updated cart with new cartId for guests\r\n * @throws ValidationError if quantity exceeds available stock\r\n *\r\n * @example Add product\r\n * ```typescript\r\n * const { items, cartId } = await client.cart.addItem({\r\n * cartId: existingCartId,\r\n * productId: 'prod_123',\r\n * quantity: 2\r\n * });\r\n * // Save cartId for future requests\r\n * localStorage.setItem('cart-id', cartId);\r\n * ```\r\n *\r\n * @example Add product with variation\r\n * ```typescript\r\n * const { items, cartId } = await client.cart.addItem({\r\n * cartId,\r\n * productId: 'prod_123',\r\n * variationId: 'var_456',\r\n * quantity: 1\r\n * });\r\n * ```\r\n */\r\n async addItem(\r\n params: AddToCartParams,\r\n fetchOptions?: FetchOptions\r\n ): Promise<CartResponse> {\r\n const { cartId, sessionId, ...body } = params;\r\n return fetcher.request<CartResponse>(\"/api/storefront/v1/cart\", {\r\n method: \"POST\",\r\n headers: buildCartHeaders({ sessionId }),\r\n body: {\r\n cartId,\r\n ...body,\r\n },\r\n ...fetchOptions,\r\n });\r\n },\r\n\r\n /**\r\n * Update item quantity by delta (atomic operation).\r\n * Use positive delta to increase, negative to decrease.\r\n * Minimum quantity is 1 (use removeItem to delete).\r\n *\r\n * @param params - Update quantity parameters\r\n * @param fetchOptions - Fetch options\r\n * @returns Updated cart\r\n * @throws NotFoundError if item not in cart or quantity would go below 1\r\n *\r\n * @example Increment quantity\r\n * ```typescript\r\n * const { items } = await client.cart.updateQuantity({\r\n * cartId,\r\n * productId: 'prod_123',\r\n * delta: 1\r\n * });\r\n * ```\r\n *\r\n * @example Decrement quantity\r\n * ```typescript\r\n * const { items } = await client.cart.updateQuantity({\r\n * cartId,\r\n * productId: 'prod_123',\r\n * variationId: 'var_456',\r\n * delta: -1\r\n * });\r\n * ```\r\n */\r\n async updateQuantity(\r\n params: UpdateCartQuantityParams,\r\n fetchOptions?: FetchOptions\r\n ): Promise<CartResponse> {\r\n const { cartId, sessionId, ...body } = params;\r\n return fetcher.request<CartResponse>(\"/api/storefront/v1/cart\", {\r\n method: \"PATCH\",\r\n headers: buildCartHeaders({ sessionId }),\r\n body: {\r\n cartId,\r\n ...body,\r\n },\r\n ...fetchOptions,\r\n });\r\n },\r\n\r\n /**\r\n * Remove an item from the cart.\r\n *\r\n * @param params - Remove from cart parameters\r\n * @param fetchOptions - Fetch options\r\n * @returns Updated cart\r\n *\r\n * @example Remove product\r\n * ```typescript\r\n * const { items } = await client.cart.removeItem({\r\n * cartId,\r\n * productId: 'prod_123'\r\n * });\r\n * ```\r\n *\r\n * @example Remove variation\r\n * ```typescript\r\n * const { items } = await client.cart.removeItem({\r\n * cartId,\r\n * productId: 'prod_123',\r\n * variationId: 'var_456'\r\n * });\r\n * ```\r\n */\r\n async removeItem(\r\n params: RemoveFromCartParams,\r\n fetchOptions?: FetchOptions\r\n ): Promise<CartResponse> {\r\n const { cartId, sessionId, ...body } = params;\r\n return fetcher.request<CartResponse>(\"/api/storefront/v1/cart\", {\r\n method: \"DELETE\",\r\n headers: buildCartHeaders({ sessionId }),\r\n body: {\r\n cartId,\r\n ...body,\r\n },\r\n ...fetchOptions,\r\n });\r\n },\r\n\r\n /**\r\n * Validate cart before checkout.\r\n * Checks product availability, stock levels, and prices.\r\n * Auto-fixes issues (removes unavailable items, adjusts quantities).\r\n *\r\n * @param options - Cart session options\r\n * @param fetchOptions - Fetch options\r\n * @returns Validated cart with change metadata\r\n *\r\n * @example Validate before checkout\r\n * ```typescript\r\n * const { items, hasChanges, changes } = await client.cart.validate({ cartId });\r\n *\r\n * if (hasChanges) {\r\n * if (changes.removedItems > 0) {\r\n * notify('Some items were removed (out of stock)');\r\n * }\r\n * if (changes.quantityAdjusted > 0) {\r\n * notify('Some quantities were adjusted');\r\n * }\r\n * if (changes.priceChanged > 0) {\r\n * notify('Some prices have changed');\r\n * }\r\n * }\r\n * ```\r\n */\r\n async validate(\r\n options?: CartSessionOptions,\r\n fetchOptions?: FetchOptions\r\n ): Promise<CartValidationResponse> {\r\n return fetcher.request<CartValidationResponse>(\r\n \"/api/storefront/v1/cart/validate\",\r\n {\r\n method: \"GET\",\r\n headers: buildCartHeaders(options),\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Type for the cart resource\r\n */\r\nexport type CartResource = ReturnType<typeof createCartResource>;\r\n","/**\r\n * Shipping Resource\r\n *\r\n * Methods for fetching shipment methods and pickup locations.\r\n */\r\n\r\nimport type {\r\n FetchOptions,\r\n ShipmentMethodsResponse,\r\n ShipmentMethodsWithLocationsResponse,\r\n CartItem,\r\n} from \"../types/index.js\";\r\nimport type { Fetcher } from \"../utils/fetch.js\";\r\n\r\n/**\r\n * Calculate total cart weight from cart items\r\n */\r\nfunction calculateCartWeight(items: CartItem[]): number {\r\n return items.reduce((total, item) => {\r\n const itemWeight = item.variation?.weight ?? item.product.weight ?? 0.5;\r\n return total + itemWeight * item.cartQuantity;\r\n }, 0);\r\n}\r\n\r\n/**\r\n * Options for fetching shipment methods with weight-based filtering\r\n */\r\nexport interface GetMethodsOptions extends FetchOptions {\r\n /** Cart items - weight will be calculated automatically */\r\n cartItems?: CartItem[];\r\n}\r\n\r\n/**\r\n * Shipping resource for fetching shipment methods and pickup locations\r\n */\r\nexport function createShippingResource(fetcher: Fetcher) {\r\n return {\r\n /**\r\n * Get all available shipment methods for the store.\r\n * Returns methods without pickup locations - use `getWithLocations` for postal code specific data.\r\n *\r\n * @param options - Fetch options including optional cartItems for weight-based filtering\r\n * @returns Available shipment methods\r\n *\r\n * @example\r\n * ```typescript\r\n * const { shipmentMethods } = await client.shipping.getMethods();\r\n *\r\n * shipmentMethods.forEach(method => {\r\n * console.log(`${method.name}: ${method.price / 100}€`);\r\n * });\r\n * ```\r\n *\r\n * @example Weight-based filtering\r\n * ```typescript\r\n * // Pass cart items - SDK calculates weight automatically\r\n * const { shipmentMethods } = await client.shipping.getMethods({\r\n * cartItems: cartItems\r\n * });\r\n * ```\r\n */\r\n async getMethods(\r\n options?: GetMethodsOptions\r\n ): Promise<ShipmentMethodsResponse> {\r\n const params = new URLSearchParams();\r\n if (options?.cartItems?.length) {\r\n const cartWeight = calculateCartWeight(options.cartItems);\r\n params.set(\"cartWeight\", cartWeight.toString());\r\n }\r\n const queryString = params.toString();\r\n const url = `/api/storefront/v1/shipment-methods${queryString ? `?${queryString}` : \"\"}`;\r\n\r\n return fetcher.request<ShipmentMethodsResponse>(url, {\r\n method: \"GET\",\r\n ...options,\r\n });\r\n },\r\n\r\n /**\r\n * Get shipment methods with pickup locations for a specific postal code.\r\n * Calls the Shipit API to fetch nearby pickup points (parcel lockers, etc.)\r\n *\r\n * @param postalCode - Customer's postal code (e.g., \"00100\")\r\n * @param options - Fetch options including optional cartItems for weight-based filtering\r\n * @returns Shipment methods and nearby pickup locations with pricing\r\n *\r\n * @example\r\n * ```typescript\r\n * const { shipmentMethods, pricedLocations } = await client.shipping.getWithLocations(\"00100\");\r\n *\r\n * // Show pickup locations\r\n * pricedLocations.forEach(location => {\r\n * console.log(`${location.name} - ${location.carrier}`);\r\n * console.log(` ${location.address1}, ${location.city}`);\r\n * console.log(` ${location.distanceInKilometers.toFixed(1)} km away`);\r\n * console.log(` Price: ${(location.merchantPrice ?? 0) / 100}€`);\r\n * });\r\n * ```\r\n *\r\n * @example Weight-based filtering with postal code\r\n * ```typescript\r\n * const { shipmentMethods, pricedLocations } = await client.shipping.getWithLocations(\r\n * \"00100\",\r\n * { cartItems: cartItems }\r\n * );\r\n *\r\n * // Only shows methods that support the cart's total weight\r\n * ```\r\n */\r\n async getWithLocations(\r\n postalCode: string,\r\n options?: GetMethodsOptions\r\n ): Promise<ShipmentMethodsWithLocationsResponse> {\r\n const params = new URLSearchParams();\r\n if (options?.cartItems?.length) {\r\n const cartWeight = calculateCartWeight(options.cartItems);\r\n params.set(\"cartWeight\", cartWeight.toString());\r\n }\r\n const queryString = params.toString();\r\n const url = `/api/storefront/v1/shipment-methods/${encodeURIComponent(postalCode)}${queryString ? `?${queryString}` : \"\"}`;\r\n\r\n return fetcher.request<ShipmentMethodsWithLocationsResponse>(url, {\r\n method: \"GET\",\r\n ...options,\r\n });\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Type for the shipping resource\r\n */\r\nexport type ShippingResource = ReturnType<typeof createShippingResource>;\r\n","/**\r\n * Customer Resource\r\n *\r\n * Methods for customer authentication and account management.\r\n * Supports session-based authentication with the x-session-id header.\r\n */\r\n\r\nimport type {\r\n FetchOptions,\r\n RegisterData,\r\n RegisterResponse,\r\n LoginOptions,\r\n LoginResponse,\r\n LogoutResponse,\r\n GetUserResponse,\r\n VerifyEmailResponse,\r\n ResendVerificationResponse,\r\n UpdateProfileData,\r\n UpdateProfileResponse,\r\n DeleteAccountResponse,\r\n GetOrdersResponse,\r\n WishlistResponse,\r\n AddToWishlistResponse,\r\n RemoveFromWishlistResponse,\r\n ForgotPasswordResponse,\r\n ResetPasswordResponse,\r\n} from \"../types/index.js\";\r\nimport type { Fetcher } from \"../utils/fetch.js\";\r\n\r\n/**\r\n * Build headers for authenticated customer requests\r\n */\r\nfunction buildSessionHeaders(sessionId: string): Record<string, string> {\r\n return { \"x-session-id\": sessionId };\r\n}\r\n\r\n/**\r\n * Customer resource for authentication and account management\r\n */\r\nexport function createCustomerResource(fetcher: Fetcher) {\r\n return {\r\n /**\r\n * Register a new customer account.\r\n * A verification email is sent automatically by the server.\r\n * The customer must verify their email before logging in.\r\n *\r\n * @param data - Registration data (firstName, lastName, email, password)\r\n * @param fetchOptions - Fetch options\r\n * @returns Created customer data and success message\r\n *\r\n * @example\r\n * ```typescript\r\n * const { customer, message } = await client.customer.register({\r\n * firstName: 'John',\r\n * lastName: 'Doe',\r\n * email: 'john@example.com',\r\n * password: 'securePassword123'\r\n * });\r\n *\r\n * // Verification email is sent automatically by the server\r\n * console.log('Account created:', message);\r\n * ```\r\n */\r\n async register(\r\n data: RegisterData,\r\n fetchOptions?: FetchOptions\r\n ): Promise<RegisterResponse> {\r\n return fetcher.request<RegisterResponse>(\r\n \"/api/storefront/v1/customer/(auth)/register\",\r\n {\r\n method: \"POST\",\r\n body: data,\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Log in an existing customer.\r\n * Returns a session ID that must be stored and passed to authenticated endpoints.\r\n *\r\n * @param email - Customer's email address\r\n * @param password - Customer's password\r\n * @param options - Login options (optional cartId for cart merging)\r\n * @param fetchOptions - Fetch options\r\n * @returns Session ID and customer data\r\n * @throws ValidationError if email is not verified (check error for requiresVerification)\r\n *\r\n * @example\r\n * ```typescript\r\n * try {\r\n * const { sessionId, customer, expiresAt } = await client.customer.login(\r\n * 'john@example.com',\r\n * 'securePassword123',\r\n * { cartId: guestCartId } // Optional: merge guest cart\r\n * );\r\n *\r\n * // Store sessionId in a cookie\r\n * cookies().set('session-id', sessionId, {\r\n * httpOnly: true,\r\n * expires: new Date(expiresAt)\r\n * });\r\n * } catch (error) {\r\n * if (error.requiresVerification) {\r\n * // Prompt user to verify email\r\n * await client.customer.resendVerification(error.customerId);\r\n * }\r\n * }\r\n * ```\r\n */\r\n async login(\r\n email: string,\r\n password: string,\r\n options?: LoginOptions,\r\n fetchOptions?: FetchOptions\r\n ): Promise<LoginResponse> {\r\n const headers: Record<string, string> = {};\r\n if (options?.cartId) {\r\n headers[\"x-cart-id\"] = options.cartId;\r\n }\r\n\r\n return fetcher.request<LoginResponse>(\r\n \"/api/storefront/v1/customer/(auth)/login\",\r\n {\r\n method: \"POST\",\r\n body: { email, password },\r\n headers,\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Log out the current customer and invalidate their session.\r\n * If the customer had items in their cart, they are migrated to a new guest cart.\r\n *\r\n * @param sessionId - The customer's session ID\r\n * @param fetchOptions - Fetch options\r\n * @returns Logout confirmation with optional new guest cart ID\r\n *\r\n * @example\r\n * ```typescript\r\n * const { cartId } = await client.customer.logout(sessionId);\r\n *\r\n * // Clear session cookie\r\n * cookies().delete('session-id');\r\n *\r\n * // If cart was migrated, store the new guest cart ID\r\n * if (cartId) {\r\n * cookies().set('cart-id', cartId);\r\n * }\r\n * ```\r\n */\r\n async logout(\r\n sessionId: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<LogoutResponse> {\r\n return fetcher.request<LogoutResponse>(\r\n \"/api/storefront/v1/customer/(auth)/logout\",\r\n {\r\n method: \"POST\",\r\n headers: buildSessionHeaders(sessionId),\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Get the currently authenticated customer's profile.\r\n *\r\n * @param sessionId - The customer's session ID\r\n * @param fetchOptions - Fetch options\r\n * @returns Current customer data\r\n * @throws AuthError if session is invalid or expired\r\n *\r\n * @example\r\n * ```typescript\r\n * const sessionId = cookies().get('session-id')?.value;\r\n * if (sessionId) {\r\n * const { customer } = await client.customer.getUser(sessionId);\r\n * console.log(`Welcome back, ${customer.firstName}!`);\r\n * }\r\n * ```\r\n */\r\n async getUser(\r\n sessionId: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<GetUserResponse> {\r\n return fetcher.request<GetUserResponse>(\r\n \"/api/storefront/v1/customer/(auth)/get-user\",\r\n {\r\n method: \"GET\",\r\n headers: buildSessionHeaders(sessionId),\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Verify a customer's email address using the token sent during registration.\r\n *\r\n * @param token - Email verification token\r\n * @param fetchOptions - Fetch options\r\n * @returns Verification confirmation\r\n * @throws ValidationError if token is invalid or expired\r\n *\r\n * @example\r\n * ```typescript\r\n * // Token comes from the verification email link\r\n * const token = searchParams.get('token');\r\n *\r\n * const { message } = await client.customer.verifyEmail(token);\r\n * console.log(message); // \"Email verified successfully. You can now log in.\"\r\n * ```\r\n */\r\n async verifyEmail(\r\n token: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<VerifyEmailResponse> {\r\n return fetcher.request<VerifyEmailResponse>(\r\n \"/api/storefront/v1/customer/(auth)/verify-email\",\r\n {\r\n method: \"GET\",\r\n params: { token },\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Resend the verification email for an unverified customer.\r\n * A new verification email is sent automatically by the server.\r\n *\r\n * @param customerId - The customer's ID (from failed login response)\r\n * @param fetchOptions - Fetch options\r\n * @returns Success message\r\n * @throws ValidationError if customer is already verified or not found\r\n *\r\n * @example\r\n * ```typescript\r\n * // After login fails with requiresVerification\r\n * const { message } = await client.customer.resendVerification(customerId);\r\n *\r\n * // Verification email is sent automatically by the server\r\n * console.log(message); // \"Verification email sent.\"\r\n * ```\r\n */\r\n async resendVerification(\r\n customerId: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<ResendVerificationResponse> {\r\n return fetcher.request<ResendVerificationResponse>(\r\n \"/api/storefront/v1/customer/(auth)/resend-verification\",\r\n {\r\n method: \"POST\",\r\n body: { customerId },\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Request a password reset for a customer account.\r\n * The server sends a password reset email directly to the customer.\r\n * Returns success even if email doesn't exist (to prevent email enumeration).\r\n *\r\n * Note: The reset token is never exposed to the client for security.\r\n * The email is sent server-side with the reset link.\r\n *\r\n * @param email - Customer's email address\r\n * @param fetchOptions - Fetch options\r\n * @returns Generic success message (same whether email exists or not)\r\n *\r\n * @example\r\n * ```typescript\r\n * const response = await client.customer.forgotPassword('john@example.com');\r\n *\r\n * // Always show same message to user (email sent server-side)\r\n * console.log(response.message);\r\n * // \"If an account exists with that email, password reset instructions have been sent.\"\r\n * ```\r\n */\r\n async forgotPassword(\r\n email: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<ForgotPasswordResponse> {\r\n return fetcher.request<ForgotPasswordResponse>(\r\n \"/api/storefront/v1/customer/(auth)/forgot-password\",\r\n {\r\n method: \"POST\",\r\n body: { email },\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Reset a customer's password using a valid reset token.\r\n * The token is sent via email by the forgotPassword endpoint.\r\n * After successful reset, all existing sessions are invalidated.\r\n *\r\n * @param token - Password reset token (from email link)\r\n * @param password - New password (minimum 8 characters)\r\n * @param fetchOptions - Fetch options\r\n * @returns Success confirmation\r\n * @throws ValidationError if token is invalid or expired\r\n *\r\n * @example\r\n * ```typescript\r\n * // Token comes from the reset email link\r\n * const token = searchParams.get('token');\r\n *\r\n * try {\r\n * const { message } = await client.customer.resetPassword(token, newPassword);\r\n * console.log(message); // \"Password reset successful...\"\r\n *\r\n * // Redirect to login page\r\n * redirect('/login?reset=success');\r\n * } catch (error) {\r\n * if (error instanceof ValidationError) {\r\n * // Token invalid or expired\r\n * console.error('Please request a new password reset');\r\n * }\r\n * }\r\n * ```\r\n */\r\n async resetPassword(\r\n token: string,\r\n password: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<ResetPasswordResponse> {\r\n return fetcher.request<ResetPasswordResponse>(\r\n \"/api/storefront/v1/customer/(auth)/reset-password\",\r\n {\r\n method: \"POST\",\r\n body: { token, password },\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n // =========================================================================\r\n // Profile Management Methods\r\n // =========================================================================\r\n\r\n /**\r\n * Update the authenticated customer's profile.\r\n *\r\n * @param sessionId - The customer's session ID\r\n * @param data - Profile data to update (firstName, lastName, email)\r\n * @param fetchOptions - Fetch options\r\n * @returns Updated customer data\r\n * @throws AuthError if session is invalid\r\n * @throws ValidationError if email is already taken by another customer\r\n *\r\n * @example\r\n * ```typescript\r\n * const { customer } = await client.customer.updateProfile(sessionId, {\r\n * firstName: 'Jane',\r\n * lastName: 'Smith',\r\n * email: 'jane.smith@example.com'\r\n * });\r\n *\r\n * console.log('Profile updated:', customer.email);\r\n * ```\r\n */\r\n async updateProfile(\r\n sessionId: string,\r\n data: UpdateProfileData,\r\n fetchOptions?: FetchOptions\r\n ): Promise<UpdateProfileResponse> {\r\n return fetcher.request<UpdateProfileResponse>(\r\n \"/api/storefront/v1/customer/edit-user\",\r\n {\r\n method: \"PATCH\",\r\n headers: buildSessionHeaders(sessionId),\r\n body: data,\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Delete the authenticated customer's account.\r\n * This action is permanent and cannot be undone.\r\n * All associated data (sessions, wishlist, etc.) will be deleted.\r\n *\r\n * @param sessionId - The customer's session ID\r\n * @param fetchOptions - Fetch options\r\n * @returns Deletion confirmation\r\n * @throws AuthError if session is invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * // Confirm with user before calling\r\n * if (confirm('Are you sure you want to delete your account?')) {\r\n * await client.customer.deleteAccount(sessionId);\r\n *\r\n * // Clear session cookie\r\n * cookies().delete('session-id');\r\n *\r\n * // Redirect to home page\r\n * redirect('/');\r\n * }\r\n * ```\r\n */\r\n async deleteAccount(\r\n sessionId: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<DeleteAccountResponse> {\r\n return fetcher.request<DeleteAccountResponse>(\r\n \"/api/storefront/v1/customer/delete-user\",\r\n {\r\n method: \"DELETE\",\r\n headers: buildSessionHeaders(sessionId),\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Get the customer's order history.\r\n * Returns all orders with line items and product details.\r\n *\r\n * @param sessionId - The customer's session ID\r\n * @param customerId - The customer's ID\r\n * @param fetchOptions - Fetch options\r\n * @returns List of customer orders\r\n *\r\n * @example\r\n * ```typescript\r\n * const { orders } = await client.customer.getOrders(sessionId, customerId);\r\n *\r\n * orders.forEach(order => {\r\n * console.log(`Order #${order.orderNumber}: ${order.status}`);\r\n * order.OrderLineItems.forEach(item => {\r\n * console.log(` - ${item.name} x${item.quantity}`);\r\n * });\r\n * });\r\n * ```\r\n */\r\n async getOrders(\r\n sessionId: string,\r\n customerId: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<GetOrdersResponse> {\r\n return fetcher.request<GetOrdersResponse>(\r\n `/api/storefront/v1/customer/get-orders/${customerId}`,\r\n {\r\n method: \"GET\",\r\n headers: buildSessionHeaders(sessionId),\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n // =========================================================================\r\n // Wishlist (Nested Resource)\r\n // =========================================================================\r\n\r\n /**\r\n * Wishlist management methods.\r\n * Access via `client.customer.wishlist.get()`, `.add()`, `.remove()`.\r\n */\r\n wishlist: {\r\n /**\r\n * Get the customer's wishlist.\r\n * Returns all wishlist items with product and variation details.\r\n *\r\n * @param sessionId - The customer's session ID\r\n * @param fetchOptions - Fetch options\r\n * @returns Wishlist items with product details\r\n * @throws AuthError if session is invalid\r\n *\r\n * @example\r\n * ```typescript\r\n * const { items } = await client.customer.wishlist.get(sessionId);\r\n *\r\n * items.forEach(item => {\r\n * console.log(`${item.product.name} - $${item.product.price / 100}`);\r\n * if (item.variation) {\r\n * const options = item.variation.options\r\n * .map(o => `${o.optionType.name}: ${o.value}`)\r\n * .join(', ');\r\n * console.log(` Variant: ${options}`);\r\n * }\r\n * });\r\n * ```\r\n */\r\n async get(\r\n sessionId: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<WishlistResponse> {\r\n return fetcher.request<WishlistResponse>(\r\n \"/api/storefront/v1/customer/wishlist\",\r\n {\r\n method: \"GET\",\r\n headers: buildSessionHeaders(sessionId),\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Add a product to the customer's wishlist.\r\n *\r\n * @param sessionId - The customer's session ID\r\n * @param productId - The product ID to add\r\n * @param variationId - Optional variation ID (for products with variations)\r\n * @param fetchOptions - Fetch options\r\n * @returns Success message\r\n * @throws AuthError if session is invalid\r\n * @throws ValidationError if product already in wishlist\r\n *\r\n * @example\r\n * ```typescript\r\n * // Add a simple product\r\n * await client.customer.wishlist.add(sessionId, 'prod_123');\r\n *\r\n * // Add a product with a specific variation\r\n * await client.customer.wishlist.add(sessionId, 'prod_123', 'var_456');\r\n * ```\r\n */\r\n async add(\r\n sessionId: string,\r\n productId: string,\r\n variationId?: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<AddToWishlistResponse> {\r\n return fetcher.request<AddToWishlistResponse>(\r\n \"/api/storefront/v1/customer/wishlist\",\r\n {\r\n method: \"POST\",\r\n headers: buildSessionHeaders(sessionId),\r\n body: { productId, variationId },\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Remove a product from the customer's wishlist.\r\n *\r\n * @param sessionId - The customer's session ID\r\n * @param productId - The product ID to remove\r\n * @param variationId - Optional variation ID (must match if item was added with variation)\r\n * @param fetchOptions - Fetch options\r\n * @returns Success message\r\n * @throws AuthError if session is invalid\r\n * @throws NotFoundError if item not in wishlist\r\n *\r\n * @example\r\n * ```typescript\r\n * // Remove a simple product\r\n * await client.customer.wishlist.remove(sessionId, 'prod_123');\r\n *\r\n * // Remove a specific variation\r\n * await client.customer.wishlist.remove(sessionId, 'prod_123', 'var_456');\r\n * ```\r\n */\r\n async remove(\r\n sessionId: string,\r\n productId: string,\r\n variationId?: string,\r\n fetchOptions?: FetchOptions\r\n ): Promise<RemoveFromWishlistResponse> {\r\n return fetcher.request<RemoveFromWishlistResponse>(\r\n \"/api/storefront/v1/customer/wishlist\",\r\n {\r\n method: \"DELETE\",\r\n headers: buildSessionHeaders(sessionId),\r\n body: { productId, variationId },\r\n ...fetchOptions,\r\n }\r\n );\r\n },\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Type for the customer resource\r\n */\r\nexport type CustomerResource = ReturnType<typeof createCustomerResource>;\r\n","import type { FetchOptions, Order } from \"../types/index.js\";\r\nimport type { Fetcher } from \"../utils/fetch.js\";\r\n\r\n/**\r\n * Order resource for fetching order details\r\n *\r\n * Used for order confirmation pages and viewing order details.\r\n * For customer order history, use the customer.getOrders() method instead.\r\n */\r\nexport function createOrderResource(fetcher: Fetcher) {\r\n return {\r\n /**\r\n * Get order details by ID.\r\n *\r\n * Retrieves complete order information including line items,\r\n * customer data, and shipment method with tracking info.\r\n *\r\n * @param orderId - The order ID to fetch\r\n * @param options - Fetch options (caching, headers, etc.)\r\n * @returns Complete order details\r\n * @throws NotFoundError if order doesn't exist or belongs to different store\r\n *\r\n * @example Basic usage (order confirmation page)\r\n * ```typescript\r\n * const order = await client.order.get(orderId);\r\n * console.log(`Order #${order.orderNumber} - ${order.status}`);\r\n * console.log(`Total: ${order.totalAmount / 100} EUR`);\r\n * ```\r\n *\r\n * @example Next.js - with caching\r\n * ```typescript\r\n * const order = await client.order.get(orderId, {\r\n * next: { revalidate: 60, tags: ['order', orderId] }\r\n * });\r\n * ```\r\n *\r\n * @example Display line items\r\n * ```typescript\r\n * const order = await client.order.get(orderId);\r\n * order.OrderLineItems.forEach(item => {\r\n * if (item.itemType !== 'SHIPPING') {\r\n * console.log(`${item.name} x${item.quantity} = ${item.totalAmount / 100} EUR`);\r\n * }\r\n * });\r\n * ```\r\n *\r\n * @example Show tracking info\r\n * ```typescript\r\n * const order = await client.order.get(orderId);\r\n * if (order.orderShipmentMethod?.trackingNumber) {\r\n * console.log(`Tracking: ${order.orderShipmentMethod.trackingNumber}`);\r\n * order.orderShipmentMethod.trackingUrls?.forEach(url => {\r\n * console.log(`Track at: ${url}`);\r\n * });\r\n * }\r\n * ```\r\n */\r\n async get(orderId: string, options?: FetchOptions): Promise<Order> {\r\n return fetcher.request<Order>(\r\n `/api/storefront/v1/order/${encodeURIComponent(orderId)}`,\r\n {\r\n ...options,\r\n }\r\n );\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Type for the order resource\r\n */\r\nexport type OrderResource = ReturnType<typeof createOrderResource>;\r\n","import type {\r\n FetchOptions,\r\n CheckoutParams,\r\n StripeCheckoutResponse,\r\n PaytrailCheckoutResponse,\r\n} from \"../types/index.js\";\r\nimport type { Fetcher } from \"../utils/fetch.js\";\r\n\r\n/**\r\n * Extended options for checkout requests\r\n *\r\n * Checkout requires cart and session context via headers.\r\n */\r\nexport interface CheckoutOptions extends FetchOptions {\r\n /**\r\n * Cart ID for guest checkout.\r\n * Pass this when the user is not logged in.\r\n */\r\n cartId?: string;\r\n /**\r\n * Session ID for authenticated checkout.\r\n * Pass this when the user is logged in.\r\n */\r\n sessionId?: string;\r\n}\r\n\r\n/**\r\n * Checkout resource for payment processing\r\n *\r\n * Handles both Stripe and Paytrail payment providers.\r\n */\r\nexport function createCheckoutResource(fetcher: Fetcher) {\r\n /**\r\n * Build headers with cart/session context\r\n */\r\n function buildCheckoutHeaders(options?: CheckoutOptions): Record<string, string> {\r\n const headers: Record<string, string> = {};\r\n if (options?.cartId) {\r\n headers[\"x-cart-id\"] = options.cartId;\r\n }\r\n if (options?.sessionId) {\r\n headers[\"x-session-id\"] = options.sessionId;\r\n }\r\n return headers;\r\n }\r\n\r\n /**\r\n * Build checkout request body\r\n */\r\n function buildCheckoutBody(params: CheckoutParams) {\r\n return {\r\n orderId: params.orderId,\r\n chosenShipmentMethod: params.shipmentMethod,\r\n customerData: params.customerData,\r\n successUrl: params.successUrl,\r\n cancelUrl: params.cancelUrl,\r\n };\r\n }\r\n\r\n return {\r\n /**\r\n * Create a Stripe checkout session.\r\n *\r\n * Redirects the user to Stripe's hosted checkout page.\r\n * Cart items are validated and stock is reserved on the server.\r\n *\r\n * @param params - Checkout parameters (customer data, shipping, URLs)\r\n * @param options - Checkout options including cart/session context\r\n * @returns URL to redirect user to Stripe checkout\r\n * @throws ValidationError for invalid data or empty cart\r\n * @throws StorefrontError for inventory issues\r\n *\r\n * @example Basic usage with redirect\r\n * ```typescript\r\n * const { url } = await client.checkout.stripe({\r\n * customerData: {\r\n * first_name: \"John\",\r\n * last_name: \"Doe\",\r\n * email: \"john@example.com\",\r\n * address: \"123 Main St\",\r\n * postal_code: \"00100\",\r\n * city: \"Helsinki\",\r\n * phone: \"+358401234567\"\r\n * },\r\n * shipmentMethod: {\r\n * shipmentMethodId: \"ship_123\",\r\n * pickupId: null\r\n * },\r\n * orderId: \"order_abc123\",\r\n * successUrl: \"https://mystore.com/success\",\r\n * cancelUrl: \"https://mystore.com/cancel\"\r\n * }, {\r\n * cartId: \"cart_xyz\", // For guest users\r\n * sessionId: \"sess_123\" // For logged-in users\r\n * });\r\n *\r\n * // Redirect to Stripe\r\n * window.location.href = url;\r\n * ```\r\n */\r\n async stripe(\r\n params: CheckoutParams,\r\n options?: CheckoutOptions\r\n ): Promise<StripeCheckoutResponse> {\r\n const headers = buildCheckoutHeaders(options);\r\n const body = buildCheckoutBody(params);\r\n\r\n return fetcher.request<StripeCheckoutResponse>(\r\n \"/api/storefront/v1/payments/stripe/checkout\",\r\n {\r\n method: \"POST\",\r\n body,\r\n headers: {\r\n ...options?.headers,\r\n ...headers,\r\n },\r\n ...options,\r\n }\r\n );\r\n },\r\n\r\n /**\r\n * Create a Paytrail checkout session.\r\n *\r\n * Returns payment providers for Finnish payment methods.\r\n * Cart items are validated and stock is reserved on the server.\r\n *\r\n * @param params - Checkout parameters (customer data, shipping, URLs)\r\n * @param options - Checkout options including cart/session context\r\n * @returns Paytrail response with available payment providers\r\n * @throws ValidationError for invalid data or empty cart\r\n * @throws StorefrontError for inventory issues\r\n *\r\n * @example Display payment providers\r\n * ```typescript\r\n * const response = await client.checkout.paytrail({\r\n * customerData: {\r\n * first_name: \"Matti\",\r\n * last_name: \"Meikäläinen\",\r\n * email: \"matti@example.fi\",\r\n * address: \"Mannerheimintie 1\",\r\n * postal_code: \"00100\",\r\n * city: \"Helsinki\",\r\n * phone: \"+358401234567\"\r\n * },\r\n * shipmentMethod: {\r\n * shipmentMethodId: \"ship_123\",\r\n * pickupId: \"pickup_456\" // For pickup points\r\n * },\r\n * orderId: \"order_abc123\",\r\n * successUrl: \"https://mystore.com/success\",\r\n * cancelUrl: \"https://mystore.com/cancel\"\r\n * }, {\r\n * cartId: \"cart_xyz\"\r\n * });\r\n *\r\n * // Group providers by type\r\n * const banks = response.providers.filter(p => p.group === \"bank\");\r\n * const mobile = response.providers.filter(p => p.group === \"mobile\");\r\n * const cards = response.providers.filter(p => p.group === \"creditcard\");\r\n * ```\r\n *\r\n * @example Submit payment form\r\n * ```typescript\r\n * const provider = response.providers.find(p => p.id === \"nordea\");\r\n *\r\n * // Create and submit a form\r\n * const form = document.createElement(\"form\");\r\n * form.method = \"POST\";\r\n * form.action = provider.url;\r\n *\r\n * provider.parameters.forEach(({ name, value }) => {\r\n * const input = document.createElement(\"input\");\r\n * input.type = \"hidden\";\r\n * input.name = name;\r\n * input.value = value;\r\n * form.appendChild(input);\r\n * });\r\n *\r\n * document.body.appendChild(form);\r\n * form.submit();\r\n * ```\r\n */\r\n async paytrail(\r\n params: CheckoutParams,\r\n options?: CheckoutOptions\r\n ): Promise<PaytrailCheckoutResponse> {\r\n const headers = buildCheckoutHeaders(options);\r\n const body = buildCheckoutBody(params);\r\n\r\n return fetcher.request<PaytrailCheckoutResponse>(\r\n \"/api/storefront/v1/payments/paytrail/checkout\",\r\n {\r\n method: \"POST\",\r\n body,\r\n headers: {\r\n ...options?.headers,\r\n ...headers,\r\n },\r\n ...options,\r\n }\r\n );\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Type for the checkout resource\r\n */\r\nexport type CheckoutResource = ReturnType<typeof createCheckoutResource>;\r\n","import type { StorefrontClientConfig } from \"./types/index.js\";\nimport { createFetcher } from \"./utils/fetch.js\";\nimport { createStoreResource, type StoreResource } from \"./resources/store.js\";\nimport {\n createProductsResource,\n type ProductsResource,\n} from \"./resources/products.js\";\nimport {\n createCategoriesResource,\n type CategoriesResource,\n} from \"./resources/categories.js\";\nimport { createCartResource, type CartResource } from \"./resources/cart.js\";\nimport {\n createShippingResource,\n type ShippingResource,\n} from \"./resources/shipping.js\";\nimport {\n createCustomerResource,\n type CustomerResource,\n} from \"./resources/customer.js\";\nimport {\n createOrderResource,\n type OrderResource,\n} from \"./resources/order.js\";\nimport {\n createCheckoutResource,\n type CheckoutResource,\n} from \"./resources/checkout.js\";\n\n/**\n * The Storefront API client\n */\nexport interface StorefrontClient {\n /**\n * The base URL for API requests\n */\n readonly baseUrl: string;\n\n /**\n * Store configuration resource\n */\n readonly store: StoreResource;\n\n /**\n * Products resource\n */\n readonly products: ProductsResource;\n\n /**\n * Categories resource\n */\n readonly categories: CategoriesResource;\n\n /**\n * Cart resource\n */\n readonly cart: CartResource;\n\n /**\n * Shipping resource\n */\n readonly shipping: ShippingResource;\n\n /**\n * Customer authentication and account management resource\n */\n readonly customer: CustomerResource;\n\n /**\n * Order resource for fetching order details\n */\n readonly order: OrderResource;\n\n /**\n * Checkout resource for payment processing\n */\n readonly checkout: CheckoutResource;\n}\n\n/**\n * Create a new Storefront API client\n */\nexport function createStorefrontClient(config: StorefrontClientConfig): StorefrontClient {\n if (!config.apiKey) {\n throw new Error(\"apiKey is required\");\n }\n if (!config.baseUrl) {\n throw new Error(\"baseUrl is required\");\n }\n\n // Ensure baseUrl doesn't have trailing slash\n const baseUrl = config.baseUrl.replace(/\\/$/, \"\");\n\n // Create the fetcher for making authenticated requests\n const fetcher = createFetcher({\n apiKey: config.apiKey,\n baseUrl,\n timeout: config.timeout,\n });\n\n return {\n baseUrl,\n store: createStoreResource(fetcher),\n products: createProductsResource(fetcher),\n categories: createCategoriesResource(fetcher),\n cart: createCartResource(fetcher),\n shipping: createShippingResource(fetcher),\n customer: createCustomerResource(fetcher),\n order: createOrderResource(fetcher),\n checkout: createCheckoutResource(fetcher),\n };\n}\n","/**\r\n * Pricing Utilities\r\n *\r\n * Helper functions for calculating prices with sale logic.\r\n */\r\n\r\nimport type { ProductDetail, ProductVariation } from \"../types/products.js\";\r\nimport type { PriceInfo } from \"../types/cart.js\";\r\n\r\n/**\r\n * Check if a sale is currently active based on start and end dates.\r\n *\r\n * @param startDate - Sale start date (ISO string, Date, null, or undefined)\r\n * @param endDate - Sale end date (ISO string, Date, null, or undefined)\r\n * @returns true if the sale is currently active\r\n *\r\n * @example\r\n * ```typescript\r\n * // No dates = always active\r\n * isSaleActive(null, null); // true\r\n *\r\n * // Only start date = active if past start\r\n * isSaleActive(\"2024-01-01\", null); // true if today >= Jan 1\r\n *\r\n * // Both dates = active if within range\r\n * isSaleActive(\"2024-01-01\", \"2024-12-31\"); // true if within range\r\n * ```\r\n */\r\nexport function isSaleActive(\r\n startDate: Date | string | null | undefined,\r\n endDate: Date | string | null | undefined\r\n): boolean {\r\n // If no dates are set, sale is considered active\r\n if (!startDate && !endDate) {\r\n return true;\r\n }\r\n\r\n const now = new Date();\r\n const start = startDate ? new Date(startDate) : null;\r\n const end = endDate ? new Date(endDate) : null;\r\n\r\n // If only start date is set\r\n if (start && !end) {\r\n return now >= start;\r\n }\r\n\r\n // If only end date is set\r\n if (!start && end) {\r\n return now <= end;\r\n }\r\n\r\n // If both dates are set\r\n if (start && end) {\r\n return now >= start && now <= end;\r\n }\r\n\r\n return true;\r\n}\r\n\r\n/**\r\n * Get price information for a product or variation.\r\n * Returns the effective price (sale or regular) and sale status.\r\n * All prices are in cents.\r\n *\r\n * @param product - The product to get price info for\r\n * @param variation - Optional variation (takes precedence over product price)\r\n * @returns Price information with effective price, original price, and sale status\r\n *\r\n * @example\r\n * ```typescript\r\n * // Product without variation\r\n * const priceInfo = getPriceInfo(product);\r\n * console.log(priceInfo.effectivePrice); // 1990 (cents)\r\n * console.log(priceInfo.isOnSale); // true\r\n *\r\n * // Product with selected variation\r\n * const priceInfo = getPriceInfo(product, selectedVariation);\r\n * ```\r\n */\r\nexport function getPriceInfo(\r\n product: ProductDetail,\r\n variation?: ProductVariation\r\n): PriceInfo {\r\n if (variation) {\r\n // Use variation pricing\r\n const isOnSale =\r\n isSaleActive(variation.saleStartDate, variation.saleEndDate) &&\r\n variation.salePrice !== null;\r\n\r\n const originalPrice = variation.price ?? product.price;\r\n const effectivePrice = isOnSale\r\n ? (variation.salePrice ?? originalPrice)\r\n : originalPrice;\r\n\r\n return {\r\n effectivePrice,\r\n originalPrice,\r\n isOnSale,\r\n salePercent: isOnSale ? (variation.salePercent ?? null) : null,\r\n };\r\n }\r\n\r\n // Use product pricing\r\n const isOnSale =\r\n isSaleActive(product.saleStartDate, product.saleEndDate) &&\r\n product.salePrice !== null;\r\n\r\n const originalPrice = product.price;\r\n const effectivePrice = isOnSale\r\n ? (product.salePrice ?? originalPrice)\r\n : originalPrice;\r\n\r\n return {\r\n effectivePrice,\r\n originalPrice,\r\n isOnSale,\r\n salePercent: isOnSale ? (product.salePercent ?? null) : null,\r\n };\r\n}\r\n","/**\r\n * Cart Calculation Utilities\r\n *\r\n * Functions for calculating cart totals with campaign discounts.\r\n */\r\n\r\nimport type { CartItem } from \"../types/cart.js\";\r\nimport type { Campaign } from \"../types/storeconfig.js\";\r\nimport type {\r\n CalculatedCartItem,\r\n FreeShippingStatus,\r\n CartCalculationResult,\r\n} from \"../types/cart.js\";\r\nimport { getPriceInfo } from \"./pricing.js\";\r\n\r\n/**\r\n * Internal type for tracking eligible units in Buy X Pay Y campaigns\r\n */\r\ninterface EligibleUnit {\r\n price: number;\r\n productId: string;\r\n variationId?: string;\r\n originalItem: CartItem;\r\n}\r\n\r\n/**\r\n * Calculate cart totals with campaign discounts applied.\r\n *\r\n * Supports two campaign types:\r\n * - **FREE_SHIPPING**: Free shipping when cart total exceeds minimum spend\r\n * - **BUY_X_PAY_Y**: Buy X items, pay for Y (e.g., Buy 3 Pay 2 = 1 free item)\r\n *\r\n * @param items - Cart items to calculate\r\n * @param campaigns - Active campaigns to apply\r\n * @returns Calculation result with totals, savings, and free shipping status\r\n *\r\n * @example\r\n * ```typescript\r\n * const result = calculateCartWithCampaigns(cartItems, activeCampaigns);\r\n *\r\n * console.log(result.cartTotal); // 4990 (cents)\r\n * console.log(result.totalSavings); // 1990 (cents)\r\n * console.log(result.freeShipping.isEligible); // true\r\n *\r\n * // Render calculated items\r\n * result.calculatedItems.forEach(({ item, paidQuantity, freeQuantity }) => {\r\n * console.log(`${item.product.name}: ${paidQuantity} paid, ${freeQuantity} free`);\r\n * });\r\n * ```\r\n */\r\nexport function calculateCartWithCampaigns(\r\n items: CartItem[],\r\n campaigns: Campaign[]\r\n): CartCalculationResult {\r\n // Find applicable campaigns\r\n const freeShippingCampaign = campaigns.find(\r\n (c) => c.type === \"FREE_SHIPPING\" && c.isActive\r\n );\r\n const buyXPayYCampaign = campaigns.find(\r\n (c) => c.type === \"BUY_X_PAY_Y\" && c.isActive\r\n );\r\n\r\n // Calculate original total (without campaign discounts)\r\n const originalTotal = items.reduce((total, { product, variation, cartQuantity }) => {\r\n const priceInfo = getPriceInfo(product, variation);\r\n return total + priceInfo.effectivePrice * cartQuantity;\r\n }, 0);\r\n\r\n // No Buy X Pay Y campaign - return items as-is\r\n if (!buyXPayYCampaign?.BuyXPayYCampaign) {\r\n const calculatedItems = items.map((item) => ({\r\n item,\r\n paidQuantity: item.cartQuantity,\r\n freeQuantity: 0,\r\n totalQuantity: item.cartQuantity,\r\n }));\r\n\r\n const freeShipping = calculateFreeShipping(\r\n originalTotal,\r\n freeShippingCampaign\r\n );\r\n\r\n return {\r\n calculatedItems,\r\n cartTotal: originalTotal,\r\n originalTotal,\r\n totalSavings: 0,\r\n freeShipping,\r\n };\r\n }\r\n\r\n // Apply Buy X Pay Y campaign\r\n const { buyQuantity, payQuantity, applicableCategories } =\r\n buyXPayYCampaign.BuyXPayYCampaign;\r\n const applicableCategoryIds = new Set(\r\n applicableCategories.map((c) => c.id)\r\n );\r\n\r\n // Find all individual units eligible for the campaign\r\n const eligibleUnits: EligibleUnit[] = items.flatMap((item) => {\r\n const { product, variation } = item;\r\n const itemCategories = product.categories?.map((cat) => cat.id) || [];\r\n\r\n // Check if any of the product's categories are in the campaign's list\r\n const isEligible = itemCategories.some((id) =>\r\n applicableCategoryIds.has(id)\r\n );\r\n\r\n if (isEligible) {\r\n const priceInfo = getPriceInfo(product, variation);\r\n\r\n // Create an entry for each single unit of the item\r\n return Array.from({ length: item.cartQuantity }, () => ({\r\n price: priceInfo.effectivePrice,\r\n productId: product.id,\r\n variationId: variation?.id,\r\n originalItem: item,\r\n }));\r\n }\r\n\r\n return [];\r\n });\r\n\r\n // Not enough eligible items - return original quantities\r\n if (eligibleUnits.length < buyQuantity) {\r\n const calculatedItems = items.map((item) => ({\r\n item,\r\n paidQuantity: item.cartQuantity,\r\n freeQuantity: 0,\r\n totalQuantity: item.cartQuantity,\r\n }));\r\n\r\n const freeShipping = calculateFreeShipping(\r\n originalTotal,\r\n freeShippingCampaign\r\n );\r\n\r\n return {\r\n calculatedItems,\r\n cartTotal: originalTotal,\r\n originalTotal,\r\n totalSavings: 0,\r\n freeShipping,\r\n };\r\n }\r\n\r\n // Sort by price to find the cheapest items to make free\r\n eligibleUnits.sort((a, b) => a.price - b.price);\r\n\r\n const numToMakeFree = buyQuantity - payQuantity;\r\n const itemsToMakeFree = eligibleUnits.slice(0, numToMakeFree);\r\n\r\n // Calculate total savings from free items\r\n const totalSavings = itemsToMakeFree.reduce(\r\n (sum, item) => sum + item.price,\r\n 0\r\n );\r\n\r\n // Create a map to count how many units of each product/variation should be free\r\n const freeCountMap = new Map<string, number>();\r\n for (const freebie of itemsToMakeFree) {\r\n const key = `${freebie.productId}${freebie.variationId ? `_${freebie.variationId}` : \"\"}`;\r\n freeCountMap.set(key, (freeCountMap.get(key) || 0) + 1);\r\n }\r\n\r\n // Calculate paid and free quantities for each item\r\n const calculatedItems: CalculatedCartItem[] = items.map((item) => {\r\n const key = `${item.product.id}${item.variation?.id ? `_${item.variation.id}` : \"\"}`;\r\n const freeQuantity = freeCountMap.get(key) || 0;\r\n const paidQuantity = item.cartQuantity - freeQuantity;\r\n\r\n return {\r\n item,\r\n paidQuantity: Math.max(0, paidQuantity),\r\n freeQuantity,\r\n totalQuantity: item.cartQuantity,\r\n };\r\n });\r\n\r\n // Calculate final cart total after Buy X Pay Y discounts\r\n const cartTotal = originalTotal - totalSavings;\r\n\r\n // Calculate free shipping using the final cart total\r\n const freeShipping = calculateFreeShipping(cartTotal, freeShippingCampaign);\r\n\r\n return {\r\n calculatedItems,\r\n cartTotal,\r\n originalTotal,\r\n totalSavings,\r\n freeShipping,\r\n };\r\n}\r\n\r\n/**\r\n * Calculate free shipping eligibility\r\n */\r\nfunction calculateFreeShipping(\r\n cartTotal: number,\r\n campaign?: Campaign\r\n): FreeShippingStatus {\r\n if (!campaign?.FreeShippingCampaign) {\r\n return {\r\n isEligible: false,\r\n minimumSpend: 0,\r\n remainingAmount: 0,\r\n };\r\n }\r\n\r\n const minimumSpend = campaign.FreeShippingCampaign.minimumSpend;\r\n const isEligible = cartTotal >= minimumSpend;\r\n const remainingAmount = isEligible ? 0 : minimumSpend - cartTotal;\r\n\r\n // Extract eligible shipment method IDs from the campaign\r\n const eligibleShipmentMethodIds = campaign.FreeShippingCampaign.shipmentMethods?.map(\r\n (method) => method.id\r\n );\r\n\r\n return {\r\n isEligible,\r\n minimumSpend,\r\n remainingAmount,\r\n campaignName: campaign.name,\r\n eligibleShipmentMethodIds,\r\n };\r\n}\r\n"],"mappings":"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","names":["isOnSale","originalPrice","effectivePrice","calculatedItems","freeShipping"]}
|