@spree/sdk 0.6.7 → 0.6.9
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/README.md +28 -2
- package/dist/index.cjs +46 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -34
- package/dist/index.d.ts +22 -34
- package/dist/index.js +46 -41
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.cts +39 -34
- package/dist/types/index.d.ts +39 -34
- package/dist/zod/index.cjs +21 -39
- package/dist/zod/index.cjs.map +1 -1
- package/dist/zod/index.d.cts +20 -77
- package/dist/zod/index.d.ts +20 -77
- package/dist/zod/index.js +22 -39
- package/dist/zod/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -364,14 +364,37 @@ const completed = await client.store.orders.paymentSessions.complete(
|
|
|
364
364
|
console.log(completed.status); // 'completed'
|
|
365
365
|
```
|
|
366
366
|
|
|
367
|
+
### Markets
|
|
368
|
+
|
|
369
|
+
```typescript
|
|
370
|
+
// List all markets
|
|
371
|
+
const { data: markets } = await client.store.markets.list();
|
|
372
|
+
// [{ id: "mkt_xxx", name: "North America", currency: "USD", default_locale: "en", ... }]
|
|
373
|
+
|
|
374
|
+
// Get a single market
|
|
375
|
+
const market = await client.store.markets.get('mkt_xxx');
|
|
376
|
+
|
|
377
|
+
// Resolve which market applies for a country
|
|
378
|
+
const market = await client.store.markets.resolve('DE');
|
|
379
|
+
// => { id: "mkt_xxx", name: "Europe", currency: "EUR", default_locale: "de", ... }
|
|
380
|
+
|
|
381
|
+
// List countries in a market
|
|
382
|
+
const { data: countries } = await client.store.markets.countries.list('mkt_xxx');
|
|
383
|
+
|
|
384
|
+
// Get a country in a market (with states for address forms)
|
|
385
|
+
const country = await client.store.markets.countries.get('mkt_xxx', 'DE', {
|
|
386
|
+
expand: ['states'],
|
|
387
|
+
});
|
|
388
|
+
```
|
|
389
|
+
|
|
367
390
|
### Geography
|
|
368
391
|
|
|
369
392
|
```typescript
|
|
370
393
|
// List countries available for checkout
|
|
371
394
|
const { data: countries } = await client.store.countries.list();
|
|
372
395
|
|
|
373
|
-
// Get country by ISO code (
|
|
374
|
-
const usa = await client.store.countries.get('US');
|
|
396
|
+
// Get country by ISO code (with states)
|
|
397
|
+
const usa = await client.store.countries.get('US', { expand: ['states'] });
|
|
375
398
|
console.log(usa.states); // Array of states
|
|
376
399
|
```
|
|
377
400
|
|
|
@@ -501,6 +524,7 @@ The SDK uses a resource builder pattern for nested resources:
|
|
|
501
524
|
| `store.customer` | `addresses` | `list`, `get`, `create`, `update`, `delete`, `markAsDefault` |
|
|
502
525
|
| `store.customer` | `creditCards` | `list`, `get`, `delete` |
|
|
503
526
|
| `store.customer` | `giftCards` | `list`, `get` |
|
|
527
|
+
| `store.markets` | `countries` | `list`, `get` |
|
|
504
528
|
| `store.taxons` | `products` | `list` |
|
|
505
529
|
| `store.wishlists` | `items` | `create`, `update`, `delete` |
|
|
506
530
|
|
|
@@ -511,6 +535,7 @@ await client.store.orders.lineItems.create(orderId, params, options);
|
|
|
511
535
|
await client.store.orders.payments.list(orderId, options);
|
|
512
536
|
await client.store.orders.shipments.update(orderId, shipmentId, params, options);
|
|
513
537
|
await client.store.customer.addresses.list({}, options);
|
|
538
|
+
await client.store.markets.countries.list(marketId);
|
|
514
539
|
await client.store.taxons.products.list(taxonId, params, options);
|
|
515
540
|
await client.store.wishlists.items.create(wishlistId, params, options);
|
|
516
541
|
```
|
|
@@ -608,6 +633,7 @@ The SDK exports all Store API types:
|
|
|
608
633
|
- `StoreState` - State/province
|
|
609
634
|
- `StoreAddress` - Customer address
|
|
610
635
|
- `StoreCustomer` - Customer profile
|
|
636
|
+
- `StoreMarket` - Market configuration (currency, locales, countries)
|
|
611
637
|
- `StoreStore` - Store configuration
|
|
612
638
|
|
|
613
639
|
### Commerce Types
|
package/dist/index.cjs
CHANGED
|
@@ -21,20 +21,23 @@ function calculateDelay(attempt, config) {
|
|
|
21
21
|
function sleep(ms) {
|
|
22
22
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
23
23
|
}
|
|
24
|
-
function
|
|
25
|
-
|
|
24
|
+
function generateIdempotencyKey() {
|
|
25
|
+
return `spree-sdk-retry-${crypto.randomUUID()}`;
|
|
26
|
+
}
|
|
27
|
+
function shouldRetryOnStatus(method, status, config, hasIdempotencyKey) {
|
|
28
|
+
const isIdempotent = method === "GET" || method === "HEAD" || hasIdempotencyKey;
|
|
26
29
|
if (isIdempotent) {
|
|
27
30
|
return config.retryOnStatus.includes(status);
|
|
28
31
|
}
|
|
29
32
|
return status === 429;
|
|
30
33
|
}
|
|
31
|
-
function shouldRetryOnNetworkError(method, config) {
|
|
34
|
+
function shouldRetryOnNetworkError(method, config, hasIdempotencyKey) {
|
|
32
35
|
if (!config.retryOnNetworkError) return false;
|
|
33
|
-
return method === "GET" || method === "HEAD";
|
|
36
|
+
return method === "GET" || method === "HEAD" || hasIdempotencyKey;
|
|
34
37
|
}
|
|
35
38
|
function createRequestFn(config, basePath, auth, defaults) {
|
|
36
39
|
return async function request(method, path, options = {}) {
|
|
37
|
-
const { token, orderToken, headers = {}, body, params } = options;
|
|
40
|
+
const { token, orderToken, idempotencyKey, headers = {}, body, params } = options;
|
|
38
41
|
const locale = options.locale ?? defaults?.locale;
|
|
39
42
|
const currency = options.currency ?? defaults?.currency;
|
|
40
43
|
const country = options.country ?? defaults?.country;
|
|
@@ -50,14 +53,13 @@ function createRequestFn(config, basePath, auth, defaults) {
|
|
|
50
53
|
}
|
|
51
54
|
});
|
|
52
55
|
}
|
|
53
|
-
if (orderToken) {
|
|
54
|
-
url.searchParams.set("order_token", orderToken);
|
|
55
|
-
}
|
|
56
56
|
const requestHeaders = {
|
|
57
57
|
"Content-Type": "application/json",
|
|
58
|
-
[auth.headerName]: auth.headerValue,
|
|
59
58
|
...headers
|
|
60
59
|
};
|
|
60
|
+
if (auth.headerName && auth.headerValue) {
|
|
61
|
+
requestHeaders[auth.headerName] = auth.headerValue;
|
|
62
|
+
}
|
|
61
63
|
if (token) {
|
|
62
64
|
requestHeaders["Authorization"] = `Bearer ${token}`;
|
|
63
65
|
}
|
|
@@ -73,6 +75,12 @@ function createRequestFn(config, basePath, auth, defaults) {
|
|
|
73
75
|
if (country) {
|
|
74
76
|
requestHeaders["x-spree-country"] = country;
|
|
75
77
|
}
|
|
78
|
+
const isMutating = method !== "GET" && method !== "HEAD";
|
|
79
|
+
const effectiveIdempotencyKey = idempotencyKey ?? (isMutating && config.retryConfig ? generateIdempotencyKey() : void 0);
|
|
80
|
+
if (effectiveIdempotencyKey) {
|
|
81
|
+
requestHeaders["Idempotency-Key"] = effectiveIdempotencyKey;
|
|
82
|
+
}
|
|
83
|
+
const hasIdempotencyKey = !!effectiveIdempotencyKey;
|
|
76
84
|
const maxAttempts = config.retryConfig ? config.retryConfig.maxRetries + 1 : 1;
|
|
77
85
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
78
86
|
try {
|
|
@@ -83,7 +91,7 @@ function createRequestFn(config, basePath, auth, defaults) {
|
|
|
83
91
|
});
|
|
84
92
|
if (!response.ok) {
|
|
85
93
|
const isLastAttempt = attempt >= maxAttempts - 1;
|
|
86
|
-
if (!isLastAttempt && config.retryConfig && shouldRetryOnStatus(method, response.status, config.retryConfig)) {
|
|
94
|
+
if (!isLastAttempt && config.retryConfig && shouldRetryOnStatus(method, response.status, config.retryConfig, hasIdempotencyKey)) {
|
|
87
95
|
const retryAfter = response.headers.get("Retry-After");
|
|
88
96
|
const delay = retryAfter ? Math.min(parseInt(retryAfter, 10) * 1e3, config.retryConfig.maxDelay) : calculateDelay(attempt, config.retryConfig);
|
|
89
97
|
await sleep(delay);
|
|
@@ -101,7 +109,7 @@ function createRequestFn(config, basePath, auth, defaults) {
|
|
|
101
109
|
throw error;
|
|
102
110
|
}
|
|
103
111
|
const isLastAttempt = attempt >= maxAttempts - 1;
|
|
104
|
-
if (!isLastAttempt && config.retryConfig && shouldRetryOnNetworkError(method, config.retryConfig)) {
|
|
112
|
+
if (!isLastAttempt && config.retryConfig && shouldRetryOnNetworkError(method, config.retryConfig, hasIdempotencyKey)) {
|
|
105
113
|
const delay = calculateDelay(attempt, config.retryConfig);
|
|
106
114
|
await sleep(delay);
|
|
107
115
|
continue;
|
|
@@ -114,7 +122,7 @@ function createRequestFn(config, basePath, auth, defaults) {
|
|
|
114
122
|
}
|
|
115
123
|
|
|
116
124
|
// src/params.ts
|
|
117
|
-
var PASSTHROUGH_KEYS = /* @__PURE__ */ new Set(["page", "limit", "expand", "sort"]);
|
|
125
|
+
var PASSTHROUGH_KEYS = /* @__PURE__ */ new Set(["page", "limit", "expand", "sort", "fields"]);
|
|
118
126
|
function transformListParams(params) {
|
|
119
127
|
const result = {};
|
|
120
128
|
for (const [key, value] of Object.entries(params)) {
|
|
@@ -138,9 +146,12 @@ function transformListParams(params) {
|
|
|
138
146
|
}
|
|
139
147
|
|
|
140
148
|
// src/store-client.ts
|
|
141
|
-
function
|
|
142
|
-
if (!params
|
|
143
|
-
|
|
149
|
+
function getParams(params) {
|
|
150
|
+
if (!params) return void 0;
|
|
151
|
+
const result = {};
|
|
152
|
+
if (params.expand?.length) result.expand = params.expand.join(",");
|
|
153
|
+
if (params.fields?.length) result.fields = params.fields.join(",");
|
|
154
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
144
155
|
}
|
|
145
156
|
var StoreClient = class {
|
|
146
157
|
request;
|
|
@@ -165,15 +176,6 @@ var StoreClient = class {
|
|
|
165
176
|
refresh: (options) => this.request("POST", "/auth/refresh", options)
|
|
166
177
|
};
|
|
167
178
|
// ============================================
|
|
168
|
-
// Store
|
|
169
|
-
// ============================================
|
|
170
|
-
store = {
|
|
171
|
-
/**
|
|
172
|
-
* Get current store information
|
|
173
|
-
*/
|
|
174
|
-
get: (options) => this.request("GET", "/store", options)
|
|
175
|
-
};
|
|
176
|
-
// ============================================
|
|
177
179
|
// Products
|
|
178
180
|
// ============================================
|
|
179
181
|
products = {
|
|
@@ -182,14 +184,14 @@ var StoreClient = class {
|
|
|
182
184
|
*/
|
|
183
185
|
list: (params, options) => this.request("GET", "/products", {
|
|
184
186
|
...options,
|
|
185
|
-
params:
|
|
187
|
+
params: transformListParams({ ...params })
|
|
186
188
|
}),
|
|
187
189
|
/**
|
|
188
190
|
* Get a product by ID or slug
|
|
189
191
|
*/
|
|
190
192
|
get: (idOrSlug, params, options) => this.request("GET", `/products/${idOrSlug}`, {
|
|
191
193
|
...options,
|
|
192
|
-
params:
|
|
194
|
+
params: getParams(params)
|
|
193
195
|
}),
|
|
194
196
|
/**
|
|
195
197
|
* Get available filters for products
|
|
@@ -209,14 +211,14 @@ var StoreClient = class {
|
|
|
209
211
|
*/
|
|
210
212
|
list: (params, options) => this.request("GET", "/taxonomies", {
|
|
211
213
|
...options,
|
|
212
|
-
params
|
|
214
|
+
params: transformListParams({ ...params })
|
|
213
215
|
}),
|
|
214
216
|
/**
|
|
215
217
|
* Get a taxonomy by ID
|
|
216
218
|
*/
|
|
217
219
|
get: (id, params, options) => this.request("GET", `/taxonomies/${id}`, {
|
|
218
220
|
...options,
|
|
219
|
-
params:
|
|
221
|
+
params: getParams(params)
|
|
220
222
|
})
|
|
221
223
|
};
|
|
222
224
|
taxons = {
|
|
@@ -225,14 +227,14 @@ var StoreClient = class {
|
|
|
225
227
|
*/
|
|
226
228
|
list: (params, options) => this.request("GET", "/taxons", {
|
|
227
229
|
...options,
|
|
228
|
-
params:
|
|
230
|
+
params: transformListParams({ ...params })
|
|
229
231
|
}),
|
|
230
232
|
/**
|
|
231
233
|
* Get a taxon by ID or permalink
|
|
232
234
|
*/
|
|
233
235
|
get: (idOrPermalink, params, options) => this.request("GET", `/taxons/${idOrPermalink}`, {
|
|
234
236
|
...options,
|
|
235
|
-
params:
|
|
237
|
+
params: getParams(params)
|
|
236
238
|
}),
|
|
237
239
|
/**
|
|
238
240
|
* Nested resource: Products in a taxon
|
|
@@ -247,7 +249,7 @@ var StoreClient = class {
|
|
|
247
249
|
`/taxons/${taxonId}/products`,
|
|
248
250
|
{
|
|
249
251
|
...options,
|
|
250
|
-
params:
|
|
252
|
+
params: transformListParams({ ...params })
|
|
251
253
|
}
|
|
252
254
|
)
|
|
253
255
|
}
|
|
@@ -268,7 +270,7 @@ var StoreClient = class {
|
|
|
268
270
|
*/
|
|
269
271
|
get: (iso, params, options) => this.request("GET", `/countries/${iso}`, {
|
|
270
272
|
...options,
|
|
271
|
-
params:
|
|
273
|
+
params: getParams(params)
|
|
272
274
|
})
|
|
273
275
|
};
|
|
274
276
|
currencies = {
|
|
@@ -325,7 +327,7 @@ var StoreClient = class {
|
|
|
325
327
|
get: (marketId, iso, params, options) => this.request(
|
|
326
328
|
"GET",
|
|
327
329
|
`/markets/${marketId}/countries/${iso}`,
|
|
328
|
-
{ ...options, params:
|
|
330
|
+
{ ...options, params: getParams(params) }
|
|
329
331
|
)
|
|
330
332
|
}
|
|
331
333
|
};
|
|
@@ -362,7 +364,7 @@ var StoreClient = class {
|
|
|
362
364
|
*/
|
|
363
365
|
get: (idOrNumber, params, options) => this.request("GET", `/orders/${idOrNumber}`, {
|
|
364
366
|
...options,
|
|
365
|
-
params:
|
|
367
|
+
params: getParams(params)
|
|
366
368
|
}),
|
|
367
369
|
/**
|
|
368
370
|
* Update an order
|
|
@@ -580,7 +582,7 @@ var StoreClient = class {
|
|
|
580
582
|
list: (params, options) => this.request(
|
|
581
583
|
"GET",
|
|
582
584
|
"/customer/addresses",
|
|
583
|
-
{ ...options, params }
|
|
585
|
+
{ ...options, params: transformListParams({ ...params }) }
|
|
584
586
|
),
|
|
585
587
|
/**
|
|
586
588
|
* Get an address by ID
|
|
@@ -622,7 +624,7 @@ var StoreClient = class {
|
|
|
622
624
|
list: (params, options) => this.request(
|
|
623
625
|
"GET",
|
|
624
626
|
"/customer/credit_cards",
|
|
625
|
-
{ ...options, params }
|
|
627
|
+
{ ...options, params: transformListParams({ ...params }) }
|
|
626
628
|
),
|
|
627
629
|
/**
|
|
628
630
|
* Get a credit card by ID
|
|
@@ -644,7 +646,7 @@ var StoreClient = class {
|
|
|
644
646
|
list: (params, options) => this.request(
|
|
645
647
|
"GET",
|
|
646
648
|
"/customer/gift_cards",
|
|
647
|
-
{ ...options, params }
|
|
649
|
+
{ ...options, params: transformListParams({ ...params }) }
|
|
648
650
|
),
|
|
649
651
|
/**
|
|
650
652
|
* Get a gift card by ID
|
|
@@ -660,7 +662,7 @@ var StoreClient = class {
|
|
|
660
662
|
*/
|
|
661
663
|
list: (params, options) => this.request("GET", "/customer/orders", {
|
|
662
664
|
...options,
|
|
663
|
-
params:
|
|
665
|
+
params: transformListParams({ ...params })
|
|
664
666
|
})
|
|
665
667
|
},
|
|
666
668
|
/**
|
|
@@ -700,14 +702,14 @@ var StoreClient = class {
|
|
|
700
702
|
*/
|
|
701
703
|
list: (params, options) => this.request("GET", "/wishlists", {
|
|
702
704
|
...options,
|
|
703
|
-
params
|
|
705
|
+
params: transformListParams({ ...params })
|
|
704
706
|
}),
|
|
705
707
|
/**
|
|
706
708
|
* Get a wishlist by ID
|
|
707
709
|
*/
|
|
708
710
|
get: (id, params, options) => this.request("GET", `/wishlists/${id}`, {
|
|
709
711
|
...options,
|
|
710
|
-
params:
|
|
712
|
+
params: getParams(params)
|
|
711
713
|
}),
|
|
712
714
|
/**
|
|
713
715
|
* Create a wishlist
|
|
@@ -776,6 +778,9 @@ var SpreeClient = class {
|
|
|
776
778
|
admin;
|
|
777
779
|
_defaults;
|
|
778
780
|
constructor(config) {
|
|
781
|
+
if (!config.publishableKey && !config.secretKey) {
|
|
782
|
+
throw new Error("SpreeClient requires at least one of publishableKey or secretKey");
|
|
783
|
+
}
|
|
779
784
|
const baseUrl = config.baseUrl.replace(/\/$/, "");
|
|
780
785
|
const fetchFn = config.fetch || fetch.bind(globalThis);
|
|
781
786
|
this._defaults = {
|
|
@@ -799,7 +804,7 @@ var SpreeClient = class {
|
|
|
799
804
|
const storeRequestFn = createRequestFn(
|
|
800
805
|
requestConfig,
|
|
801
806
|
"/api/v3/store",
|
|
802
|
-
{ headerName: "x-spree-api-key", headerValue: config.publishableKey },
|
|
807
|
+
config.publishableKey ? { headerName: "x-spree-api-key", headerValue: config.publishableKey } : { headerName: "", headerValue: "" },
|
|
803
808
|
this._defaults
|
|
804
809
|
);
|
|
805
810
|
const adminRequestFn = createRequestFn(
|