@asstio-dev/storefront 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -1
- package/dist/schema.d.ts +284 -1
- package/package.json +1 -1
- package/src/schema.d.ts +284 -1
package/README.md
CHANGED
|
@@ -75,6 +75,60 @@ for (const file of product?.files ?? []) console.log(file.filename, fileUrl(site
|
|
|
75
75
|
// A variant with hasOwnImages: false inherits: variant.hasOwnImages ? variant.images : product.images
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
+
`videoSources` returns `[]` for anything that is not a video, while `mediaUrl`/`pictureSources`/`fileUrl`/`posterUrl`
|
|
79
|
+
throw `MediaUrlError` when the descriptor cannot produce that URL — branch on `kind` before calling.
|
|
80
|
+
|
|
81
|
+
### Product content
|
|
82
|
+
|
|
83
|
+
`description` is **already sanitized** on the server: render `description.html` as-is — do not sanitize, escape or
|
|
84
|
+
re-parse it — and use `description.text` wherever you need plain text (a meta description, a snippet, an
|
|
85
|
+
`aria-label`). `shortDescription` is plain text. `brand.facet` is set when the brand shares a facet's source, so it
|
|
86
|
+
can link straight to a filtered listing; when it is `null`, render `brand.label` as plain text and never guess a
|
|
87
|
+
filter.
|
|
88
|
+
|
|
89
|
+
`attributes[]` arrives ordered and labelled for display. Branch on `type` (`text` | `html` | `number` | `bool` |
|
|
90
|
+
`list`): a list fills `values`, everything else fills `value`, and `html` fills `html` too — sanitized exactly like
|
|
91
|
+
`description.html`.
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
if (product.description) render(product.description.html); // as-is: sanitized server-side
|
|
95
|
+
for (const a of product.attributes) {
|
|
96
|
+
if (a.type === "html") render(a.html!); // sanitized like description.html
|
|
97
|
+
else if (a.values) render(a.values.join(", ")); // type: "list"
|
|
98
|
+
else render(a.value!); // text | number | bool
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
`facetKey` and `valueKeys` turn an attribute's values into filter links — `filter[facetKey]=valueKeys[i]`, aligned
|
|
103
|
+
index-for-index with `values` (or carrying the single `value`'s key). `valueKeys` is absent entirely when any one
|
|
104
|
+
value has no key of its own: a list is either fully linkable or not linkable at all.
|
|
105
|
+
|
|
106
|
+
`related[]` holds groups of cards already resolved for this market, and `bundle.components[]` the cards a bundle is
|
|
107
|
+
made of; both leave out anything that no longer exists or is not sold here.
|
|
108
|
+
|
|
109
|
+
### Search-as-you-type and search-in-facet
|
|
110
|
+
|
|
111
|
+
`/v1/search/suggest` answers three short lists for what the shopper has typed so far: up to 5 product cards
|
|
112
|
+
(matched on the product name), 5 categories (each with the `path` to show above it) and 10 values from the facets
|
|
113
|
+
whose panel is searchable. `q` is required and 1–100 characters — blank, missing or longer is a 400
|
|
114
|
+
(`INVALID_QUERY`), not a truncation the way a listing's `q` is.
|
|
115
|
+
|
|
116
|
+
`/v1/products/facets/{key}` is the search box inside one facet panel: the facet's values with the counts they have
|
|
117
|
+
in the same `filter[…]` context the listing is showing, so a count is what selecting that value would leave. Send
|
|
118
|
+
the panel's own filters with it, and omit `q` for the values as they are.
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
const { data: suggestions } = await storefront.GET("/v1/search/suggest", { params: { query: { q: typed } } });
|
|
122
|
+
const { data: brands } = await storefront.GET("/v1/products/facets/{key}", {
|
|
123
|
+
params: { path: { key: "varumarke" }, query: { q: typed, filter: filterQuery({ kon: ["dam"] }) } },
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The endpoint reads the facet's **1000 most common values** and matches `q` against those — label contains,
|
|
128
|
+
case-insensitively, or key prefix — returning at most 50. A facet with more distinct values than that is searched
|
|
129
|
+
over its top 1000; no regular expression ever reaches the search index. `key` has to be a `list` or `swatch` facet:
|
|
130
|
+
an unknown key is `FACET_NOT_FOUND` (404), and a range or toggle facet is `FACET_NOT_SEARCHABLE` (400).
|
|
131
|
+
|
|
78
132
|
## Headers
|
|
79
133
|
|
|
80
134
|
Every call the client makes carries these; you never set them by hand.
|
|
@@ -115,7 +169,8 @@ Every operation documents `400`, `401`, `403`, `404`, `429` and `503`; the entit
|
|
|
115
169
|
Codes you will meet: `SITE_KEY_MISSING`, `SITE_KEY_INVALID`, `SITE_INACTIVE`, `SECRET_KEY_FROM_BROWSER`,
|
|
116
170
|
`SITE_REGISTRY_WARMING`, `MARKET_UNKNOWN`, `RATE_LIMITED` (with `retryAfterSeconds`, plus a `Retry-After`
|
|
117
171
|
header), `PRODUCT_NOT_FOUND`, `COLLECTION_NOT_FOUND`, `INVALID_PAGE`, `INVALID_SINCE`, `INVALID_TYPE`,
|
|
118
|
-
`INDEX_UNAVAILABLE` (retry — a preview index is being rebuilt), `NOT_FOUND
|
|
172
|
+
`INDEX_UNAVAILABLE` (retry — a preview index is being rebuilt), `NOT_FOUND`, `INVALID_QUERY`,
|
|
173
|
+
`FACET_NOT_FOUND`, `FACET_NOT_SEARCHABLE`.
|
|
119
174
|
|
|
120
175
|
`SITE_REGISTRY_WARMING` and `INDEX_UNAVAILABLE` are retries, not bugs in your call.
|
|
121
176
|
|
|
@@ -140,6 +195,9 @@ form the API reads. `filterQuery()` is a thin helper that joins multi-select val
|
|
|
140
195
|
`/v1/sitemap` takes `type` (`product` | `collection`), `since` (ISO-8601, inclusive), `page` and `pageSize`
|
|
141
196
|
(max 1000, default 500).
|
|
142
197
|
|
|
198
|
+
`/v1/search/suggest` takes `q` only, and `/v1/products/facets/{key}` takes `q` plus the same `filter` object as a
|
|
199
|
+
listing — both are described under [Search-as-you-type and search-in-facet](#search-as-you-type-and-search-in-facet).
|
|
200
|
+
|
|
143
201
|
## Caching
|
|
144
202
|
|
|
145
203
|
Read responses carry an `ETag` and `Vary: X-Site-Key, X-Market, Accept-Language` — the answer depends on
|
package/dist/schema.d.ts
CHANGED
|
@@ -153,6 +153,23 @@ export interface paths {
|
|
|
153
153
|
patch?: never;
|
|
154
154
|
trace?: never;
|
|
155
155
|
};
|
|
156
|
+
"/v1/products/facets/{key}": {
|
|
157
|
+
parameters: {
|
|
158
|
+
query?: never;
|
|
159
|
+
header?: never;
|
|
160
|
+
path?: never;
|
|
161
|
+
cookie?: never;
|
|
162
|
+
};
|
|
163
|
+
/** Search within a facet: values whose label matches q, counted in this request's filter[...] context (spelled as on /products). Free text and collections are not applied. */
|
|
164
|
+
get: operations["SearchFacetValues"];
|
|
165
|
+
put?: never;
|
|
166
|
+
post?: never;
|
|
167
|
+
delete?: never;
|
|
168
|
+
options?: never;
|
|
169
|
+
head?: never;
|
|
170
|
+
patch?: never;
|
|
171
|
+
trace?: never;
|
|
172
|
+
};
|
|
156
173
|
"/v1/products/{slugOrId}": {
|
|
157
174
|
parameters: {
|
|
158
175
|
query?: never;
|
|
@@ -187,6 +204,23 @@ export interface paths {
|
|
|
187
204
|
patch?: never;
|
|
188
205
|
trace?: never;
|
|
189
206
|
};
|
|
207
|
+
"/v1/search/suggest": {
|
|
208
|
+
parameters: {
|
|
209
|
+
query?: never;
|
|
210
|
+
header?: never;
|
|
211
|
+
path?: never;
|
|
212
|
+
cookie?: never;
|
|
213
|
+
};
|
|
214
|
+
/** Search-as-you-type: products by name prefix, categories and facet values whose label starts with q. Market, assortment and language as /products. */
|
|
215
|
+
get: operations["Suggest"];
|
|
216
|
+
put?: never;
|
|
217
|
+
post?: never;
|
|
218
|
+
delete?: never;
|
|
219
|
+
options?: never;
|
|
220
|
+
head?: never;
|
|
221
|
+
patch?: never;
|
|
222
|
+
trace?: never;
|
|
223
|
+
};
|
|
190
224
|
"/v1/site": {
|
|
191
225
|
parameters: {
|
|
192
226
|
query?: never;
|
|
@@ -235,6 +269,27 @@ export interface components {
|
|
|
235
269
|
label: string;
|
|
236
270
|
value: string;
|
|
237
271
|
};
|
|
272
|
+
AttributeDto: {
|
|
273
|
+
facetKey: null | string;
|
|
274
|
+
html: null | string;
|
|
275
|
+
key: string;
|
|
276
|
+
label: string;
|
|
277
|
+
type: string;
|
|
278
|
+
value: null | string;
|
|
279
|
+
valueKeys: string[] | null;
|
|
280
|
+
values: string[] | null;
|
|
281
|
+
};
|
|
282
|
+
BrandDto: {
|
|
283
|
+
facet: null | components["schemas"]["FacetLinkDto"];
|
|
284
|
+
label: string;
|
|
285
|
+
};
|
|
286
|
+
BundleComponentDto: {
|
|
287
|
+
product: components["schemas"]["ProductCardDto"];
|
|
288
|
+
quantity: string;
|
|
289
|
+
};
|
|
290
|
+
BundleDto: {
|
|
291
|
+
components: components["schemas"]["BundleComponentDto"][];
|
|
292
|
+
};
|
|
238
293
|
CartDto: {
|
|
239
294
|
currency: string;
|
|
240
295
|
grandTotalInc: string;
|
|
@@ -251,10 +306,22 @@ export interface components {
|
|
|
251
306
|
id: string;
|
|
252
307
|
image: null | components["schemas"]["MediaDescriptorDto"];
|
|
253
308
|
price: components["schemas"]["PriceDto"];
|
|
254
|
-
|
|
309
|
+
product: components["schemas"]["CartLineProductDto"];
|
|
255
310
|
/** Format: int32 */
|
|
256
311
|
quantity: number | string;
|
|
257
312
|
sku: string;
|
|
313
|
+
variant: components["schemas"]["CartLineVariantDto"];
|
|
314
|
+
};
|
|
315
|
+
CartLineProductDto: {
|
|
316
|
+
id: string;
|
|
317
|
+
name: string;
|
|
318
|
+
slug: string;
|
|
319
|
+
};
|
|
320
|
+
CartLineVariantDto: {
|
|
321
|
+
id: string;
|
|
322
|
+
selectedOptions: {
|
|
323
|
+
[key: string]: string;
|
|
324
|
+
};
|
|
258
325
|
};
|
|
259
326
|
CategoryNodeDto: {
|
|
260
327
|
children: components["schemas"]["CategoryNodeDto"][];
|
|
@@ -298,6 +365,10 @@ export interface components {
|
|
|
298
365
|
slug: string;
|
|
299
366
|
url: string;
|
|
300
367
|
};
|
|
368
|
+
DescriptionDto: {
|
|
369
|
+
html: string;
|
|
370
|
+
text: string;
|
|
371
|
+
};
|
|
301
372
|
FacetDto: {
|
|
302
373
|
key: string;
|
|
303
374
|
label: string;
|
|
@@ -308,6 +379,10 @@ export interface components {
|
|
|
308
379
|
type: string;
|
|
309
380
|
values: components["schemas"]["FacetValueDto"][];
|
|
310
381
|
};
|
|
382
|
+
FacetLinkDto: {
|
|
383
|
+
key: string;
|
|
384
|
+
valueKey: string;
|
|
385
|
+
};
|
|
311
386
|
FacetValueDto: {
|
|
312
387
|
children: components["schemas"]["FacetValueDto"][] | null;
|
|
313
388
|
/** Format: int64 */
|
|
@@ -318,6 +393,10 @@ export interface components {
|
|
|
318
393
|
selected: boolean;
|
|
319
394
|
swatch: null | components["schemas"]["SwatchDto"];
|
|
320
395
|
};
|
|
396
|
+
FacetValuesResponse: {
|
|
397
|
+
facet: string;
|
|
398
|
+
values: components["schemas"]["FacetValueDto"][];
|
|
399
|
+
};
|
|
321
400
|
ListingResponse: {
|
|
322
401
|
appliedFilters: components["schemas"]["AppliedFilterDto"][];
|
|
323
402
|
facets: components["schemas"]["FacetDto"][];
|
|
@@ -414,6 +493,7 @@ export interface components {
|
|
|
414
493
|
vatRate: string;
|
|
415
494
|
};
|
|
416
495
|
ProductCardDto: {
|
|
496
|
+
brand: null | components["schemas"]["BrandDto"];
|
|
417
497
|
collections: string[];
|
|
418
498
|
id: string;
|
|
419
499
|
image: null | components["schemas"]["MediaDescriptorDto"];
|
|
@@ -421,6 +501,7 @@ export interface components {
|
|
|
421
501
|
name: string;
|
|
422
502
|
price: null | components["schemas"]["PriceDto"];
|
|
423
503
|
priceVaries: boolean;
|
|
504
|
+
shortDescription: null | string;
|
|
424
505
|
sku: string;
|
|
425
506
|
slug: string;
|
|
426
507
|
/** Format: date-time */
|
|
@@ -431,8 +512,12 @@ export interface components {
|
|
|
431
512
|
alternateUrls: {
|
|
432
513
|
[key: string]: string;
|
|
433
514
|
};
|
|
515
|
+
attributes: components["schemas"]["AttributeDto"][];
|
|
516
|
+
brand: null | components["schemas"]["BrandDto"];
|
|
517
|
+
bundle: null | components["schemas"]["BundleDto"];
|
|
434
518
|
categories: components["schemas"]["CategoryRefDto"][];
|
|
435
519
|
collections: components["schemas"]["CollectionRefDto"][];
|
|
520
|
+
description: null | components["schemas"]["DescriptionDto"];
|
|
436
521
|
files: components["schemas"]["MediaDescriptorDto"][];
|
|
437
522
|
id: string;
|
|
438
523
|
image: null | components["schemas"]["MediaDescriptorDto"];
|
|
@@ -441,7 +526,9 @@ export interface components {
|
|
|
441
526
|
name: string;
|
|
442
527
|
options: components["schemas"]["OptionDto"][];
|
|
443
528
|
redirectTo: null | string;
|
|
529
|
+
related: components["schemas"]["RelatedGroupDto"][];
|
|
444
530
|
seo: components["schemas"]["SeoDto"];
|
|
531
|
+
shortDescription: null | string;
|
|
445
532
|
sku: string;
|
|
446
533
|
slug: string;
|
|
447
534
|
/** Format: date-time */
|
|
@@ -457,12 +544,18 @@ export interface components {
|
|
|
457
544
|
min: string;
|
|
458
545
|
mode: string;
|
|
459
546
|
selected: null | components["schemas"]["RangeSelectionDto"];
|
|
547
|
+
step: null | string;
|
|
460
548
|
unit: null | string;
|
|
461
549
|
};
|
|
462
550
|
RangeSelectionDto: {
|
|
463
551
|
max: null | string;
|
|
464
552
|
min: null | string;
|
|
465
553
|
};
|
|
554
|
+
RelatedGroupDto: {
|
|
555
|
+
key: string;
|
|
556
|
+
label: string;
|
|
557
|
+
products: components["schemas"]["ProductCardDto"][];
|
|
558
|
+
};
|
|
466
559
|
SeoDto: {
|
|
467
560
|
description: null | string;
|
|
468
561
|
title: string;
|
|
@@ -532,6 +625,22 @@ export interface components {
|
|
|
532
625
|
/** @description Link to this code's documentation. */
|
|
533
626
|
type?: string;
|
|
534
627
|
};
|
|
628
|
+
SuggestCategoryDto: {
|
|
629
|
+
id: string;
|
|
630
|
+
name: string;
|
|
631
|
+
path: string[];
|
|
632
|
+
};
|
|
633
|
+
SuggestFacetValueDto: {
|
|
634
|
+
facet: string;
|
|
635
|
+
key: string;
|
|
636
|
+
label: string;
|
|
637
|
+
};
|
|
638
|
+
SuggestResponse: {
|
|
639
|
+
categories: components["schemas"]["SuggestCategoryDto"][];
|
|
640
|
+
facetValues: components["schemas"]["SuggestFacetValueDto"][];
|
|
641
|
+
products: components["schemas"]["ProductCardDto"][];
|
|
642
|
+
query: string;
|
|
643
|
+
};
|
|
535
644
|
SwatchDto: {
|
|
536
645
|
color: null | string;
|
|
537
646
|
image: null | components["schemas"]["MediaDescriptorDto"];
|
|
@@ -1630,6 +1739,96 @@ export interface operations {
|
|
|
1630
1739
|
};
|
|
1631
1740
|
};
|
|
1632
1741
|
};
|
|
1742
|
+
SearchFacetValues: {
|
|
1743
|
+
parameters: {
|
|
1744
|
+
query?: {
|
|
1745
|
+
/** @description Narrows to the values whose label contains q (case-insensitively) or whose key starts with it. Omit for the facet's values as they are. Matched against the 1000 most common values of the facet, in this API — at most 50 are returned. Present but blank is a 400 (INVALID_QUERY). */
|
|
1746
|
+
q?: string;
|
|
1747
|
+
/** @description The filter context the values are counted in, sent as filter[key]=value exactly as on /products: a count is what selecting that value would leave. This facet's own selection does not narrow it (the counts are disjunctive), and a key this site has no facet for is dropped silently. */
|
|
1748
|
+
filter?: {
|
|
1749
|
+
[key: string]: string;
|
|
1750
|
+
};
|
|
1751
|
+
};
|
|
1752
|
+
header: {
|
|
1753
|
+
/** @description Publishable, preview or secret site key. Required on every request; secret keys are server-side only. */
|
|
1754
|
+
"X-Site-Key": string;
|
|
1755
|
+
/** @description Market code (e.g. "se"). Omit for the site's default market. */
|
|
1756
|
+
"X-Market"?: string;
|
|
1757
|
+
/** @description BCP-47 language tag. Omit to use the market's language. */
|
|
1758
|
+
"Accept-Language"?: string;
|
|
1759
|
+
};
|
|
1760
|
+
path: {
|
|
1761
|
+
key: string;
|
|
1762
|
+
};
|
|
1763
|
+
cookie?: never;
|
|
1764
|
+
};
|
|
1765
|
+
requestBody?: never;
|
|
1766
|
+
responses: {
|
|
1767
|
+
/** @description OK */
|
|
1768
|
+
200: {
|
|
1769
|
+
headers: {
|
|
1770
|
+
[name: string]: unknown;
|
|
1771
|
+
};
|
|
1772
|
+
content: {
|
|
1773
|
+
"application/json": components["schemas"]["FacetValuesResponse"];
|
|
1774
|
+
};
|
|
1775
|
+
};
|
|
1776
|
+
/** @description problem+json. MARKET_UNKNOWN (no such market on this site), INVALID_PAGE, or INVALID_QUERY (q present but blank, or longer than 100 characters), or FACET_NOT_SEARCHABLE (the facet exists but has no list of values to search in: a range, a toggle or a tree). */
|
|
1777
|
+
400: {
|
|
1778
|
+
headers: {
|
|
1779
|
+
[name: string]: unknown;
|
|
1780
|
+
};
|
|
1781
|
+
content: {
|
|
1782
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
1783
|
+
};
|
|
1784
|
+
};
|
|
1785
|
+
/** @description problem+json. SITE_KEY_MISSING or SITE_KEY_INVALID. */
|
|
1786
|
+
401: {
|
|
1787
|
+
headers: {
|
|
1788
|
+
[name: string]: unknown;
|
|
1789
|
+
};
|
|
1790
|
+
content: {
|
|
1791
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
1792
|
+
};
|
|
1793
|
+
};
|
|
1794
|
+
/** @description problem+json. SECRET_KEY_FROM_BROWSER: a secret key was sent from a browser. */
|
|
1795
|
+
403: {
|
|
1796
|
+
headers: {
|
|
1797
|
+
[name: string]: unknown;
|
|
1798
|
+
};
|
|
1799
|
+
content: {
|
|
1800
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
1801
|
+
};
|
|
1802
|
+
};
|
|
1803
|
+
/** @description problem+json. FACET_NOT_FOUND, or SITE_INACTIVE when the site itself is not live. */
|
|
1804
|
+
404: {
|
|
1805
|
+
headers: {
|
|
1806
|
+
[name: string]: unknown;
|
|
1807
|
+
};
|
|
1808
|
+
content: {
|
|
1809
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
1810
|
+
};
|
|
1811
|
+
};
|
|
1812
|
+
/** @description problem+json. RATE_LIMITED; retryAfterSeconds and the Retry-After header say how long to wait. */
|
|
1813
|
+
429: {
|
|
1814
|
+
headers: {
|
|
1815
|
+
[name: string]: unknown;
|
|
1816
|
+
};
|
|
1817
|
+
content: {
|
|
1818
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
1819
|
+
};
|
|
1820
|
+
};
|
|
1821
|
+
/** @description problem+json. SITE_REGISTRY_WARMING or INDEX_UNAVAILABLE — retry, the request was not wrong. */
|
|
1822
|
+
503: {
|
|
1823
|
+
headers: {
|
|
1824
|
+
[name: string]: unknown;
|
|
1825
|
+
};
|
|
1826
|
+
content: {
|
|
1827
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
1828
|
+
};
|
|
1829
|
+
};
|
|
1830
|
+
};
|
|
1831
|
+
};
|
|
1633
1832
|
GetProduct: {
|
|
1634
1833
|
parameters: {
|
|
1635
1834
|
query?: never;
|
|
@@ -1805,6 +2004,90 @@ export interface operations {
|
|
|
1805
2004
|
};
|
|
1806
2005
|
};
|
|
1807
2006
|
};
|
|
2007
|
+
Suggest: {
|
|
2008
|
+
parameters: {
|
|
2009
|
+
query: {
|
|
2010
|
+
/** @description What the shopper has typed so far, 1–100 characters. Blank, missing or longer is a 400 (INVALID_QUERY) — unlike a listing's q, which is truncated. */
|
|
2011
|
+
q: string;
|
|
2012
|
+
};
|
|
2013
|
+
header: {
|
|
2014
|
+
/** @description Publishable, preview or secret site key. Required on every request; secret keys are server-side only. */
|
|
2015
|
+
"X-Site-Key": string;
|
|
2016
|
+
/** @description Market code (e.g. "se"). Omit for the site's default market. */
|
|
2017
|
+
"X-Market"?: string;
|
|
2018
|
+
/** @description BCP-47 language tag. Omit to use the market's language. */
|
|
2019
|
+
"Accept-Language"?: string;
|
|
2020
|
+
};
|
|
2021
|
+
path?: never;
|
|
2022
|
+
cookie?: never;
|
|
2023
|
+
};
|
|
2024
|
+
requestBody?: never;
|
|
2025
|
+
responses: {
|
|
2026
|
+
/** @description OK */
|
|
2027
|
+
200: {
|
|
2028
|
+
headers: {
|
|
2029
|
+
[name: string]: unknown;
|
|
2030
|
+
};
|
|
2031
|
+
content: {
|
|
2032
|
+
"application/json": components["schemas"]["SuggestResponse"];
|
|
2033
|
+
};
|
|
2034
|
+
};
|
|
2035
|
+
/** @description problem+json. MARKET_UNKNOWN (no such market on this site), INVALID_PAGE, or INVALID_QUERY (q missing, blank or longer than 100 characters). */
|
|
2036
|
+
400: {
|
|
2037
|
+
headers: {
|
|
2038
|
+
[name: string]: unknown;
|
|
2039
|
+
};
|
|
2040
|
+
content: {
|
|
2041
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
2042
|
+
};
|
|
2043
|
+
};
|
|
2044
|
+
/** @description problem+json. SITE_KEY_MISSING or SITE_KEY_INVALID. */
|
|
2045
|
+
401: {
|
|
2046
|
+
headers: {
|
|
2047
|
+
[name: string]: unknown;
|
|
2048
|
+
};
|
|
2049
|
+
content: {
|
|
2050
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
2051
|
+
};
|
|
2052
|
+
};
|
|
2053
|
+
/** @description problem+json. SECRET_KEY_FROM_BROWSER: a secret key was sent from a browser. */
|
|
2054
|
+
403: {
|
|
2055
|
+
headers: {
|
|
2056
|
+
[name: string]: unknown;
|
|
2057
|
+
};
|
|
2058
|
+
content: {
|
|
2059
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
2060
|
+
};
|
|
2061
|
+
};
|
|
2062
|
+
/** @description problem+json. SITE_INACTIVE, or NOT_FOUND for an unrouted path. */
|
|
2063
|
+
404: {
|
|
2064
|
+
headers: {
|
|
2065
|
+
[name: string]: unknown;
|
|
2066
|
+
};
|
|
2067
|
+
content: {
|
|
2068
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
2069
|
+
};
|
|
2070
|
+
};
|
|
2071
|
+
/** @description problem+json. RATE_LIMITED; retryAfterSeconds and the Retry-After header say how long to wait. */
|
|
2072
|
+
429: {
|
|
2073
|
+
headers: {
|
|
2074
|
+
[name: string]: unknown;
|
|
2075
|
+
};
|
|
2076
|
+
content: {
|
|
2077
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
2078
|
+
};
|
|
2079
|
+
};
|
|
2080
|
+
/** @description problem+json. SITE_REGISTRY_WARMING or INDEX_UNAVAILABLE — retry, the request was not wrong. */
|
|
2081
|
+
503: {
|
|
2082
|
+
headers: {
|
|
2083
|
+
[name: string]: unknown;
|
|
2084
|
+
};
|
|
2085
|
+
content: {
|
|
2086
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
2087
|
+
};
|
|
2088
|
+
};
|
|
2089
|
+
};
|
|
2090
|
+
};
|
|
1808
2091
|
GetSite: {
|
|
1809
2092
|
parameters: {
|
|
1810
2093
|
query?: never;
|
package/package.json
CHANGED
package/src/schema.d.ts
CHANGED
|
@@ -153,6 +153,23 @@ export interface paths {
|
|
|
153
153
|
patch?: never;
|
|
154
154
|
trace?: never;
|
|
155
155
|
};
|
|
156
|
+
"/v1/products/facets/{key}": {
|
|
157
|
+
parameters: {
|
|
158
|
+
query?: never;
|
|
159
|
+
header?: never;
|
|
160
|
+
path?: never;
|
|
161
|
+
cookie?: never;
|
|
162
|
+
};
|
|
163
|
+
/** Search within a facet: values whose label matches q, counted in this request's filter[...] context (spelled as on /products). Free text and collections are not applied. */
|
|
164
|
+
get: operations["SearchFacetValues"];
|
|
165
|
+
put?: never;
|
|
166
|
+
post?: never;
|
|
167
|
+
delete?: never;
|
|
168
|
+
options?: never;
|
|
169
|
+
head?: never;
|
|
170
|
+
patch?: never;
|
|
171
|
+
trace?: never;
|
|
172
|
+
};
|
|
156
173
|
"/v1/products/{slugOrId}": {
|
|
157
174
|
parameters: {
|
|
158
175
|
query?: never;
|
|
@@ -187,6 +204,23 @@ export interface paths {
|
|
|
187
204
|
patch?: never;
|
|
188
205
|
trace?: never;
|
|
189
206
|
};
|
|
207
|
+
"/v1/search/suggest": {
|
|
208
|
+
parameters: {
|
|
209
|
+
query?: never;
|
|
210
|
+
header?: never;
|
|
211
|
+
path?: never;
|
|
212
|
+
cookie?: never;
|
|
213
|
+
};
|
|
214
|
+
/** Search-as-you-type: products by name prefix, categories and facet values whose label starts with q. Market, assortment and language as /products. */
|
|
215
|
+
get: operations["Suggest"];
|
|
216
|
+
put?: never;
|
|
217
|
+
post?: never;
|
|
218
|
+
delete?: never;
|
|
219
|
+
options?: never;
|
|
220
|
+
head?: never;
|
|
221
|
+
patch?: never;
|
|
222
|
+
trace?: never;
|
|
223
|
+
};
|
|
190
224
|
"/v1/site": {
|
|
191
225
|
parameters: {
|
|
192
226
|
query?: never;
|
|
@@ -235,6 +269,27 @@ export interface components {
|
|
|
235
269
|
label: string;
|
|
236
270
|
value: string;
|
|
237
271
|
};
|
|
272
|
+
AttributeDto: {
|
|
273
|
+
facetKey: null | string;
|
|
274
|
+
html: null | string;
|
|
275
|
+
key: string;
|
|
276
|
+
label: string;
|
|
277
|
+
type: string;
|
|
278
|
+
value: null | string;
|
|
279
|
+
valueKeys: string[] | null;
|
|
280
|
+
values: string[] | null;
|
|
281
|
+
};
|
|
282
|
+
BrandDto: {
|
|
283
|
+
facet: null | components["schemas"]["FacetLinkDto"];
|
|
284
|
+
label: string;
|
|
285
|
+
};
|
|
286
|
+
BundleComponentDto: {
|
|
287
|
+
product: components["schemas"]["ProductCardDto"];
|
|
288
|
+
quantity: string;
|
|
289
|
+
};
|
|
290
|
+
BundleDto: {
|
|
291
|
+
components: components["schemas"]["BundleComponentDto"][];
|
|
292
|
+
};
|
|
238
293
|
CartDto: {
|
|
239
294
|
currency: string;
|
|
240
295
|
grandTotalInc: string;
|
|
@@ -251,10 +306,22 @@ export interface components {
|
|
|
251
306
|
id: string;
|
|
252
307
|
image: null | components["schemas"]["MediaDescriptorDto"];
|
|
253
308
|
price: components["schemas"]["PriceDto"];
|
|
254
|
-
|
|
309
|
+
product: components["schemas"]["CartLineProductDto"];
|
|
255
310
|
/** Format: int32 */
|
|
256
311
|
quantity: number | string;
|
|
257
312
|
sku: string;
|
|
313
|
+
variant: components["schemas"]["CartLineVariantDto"];
|
|
314
|
+
};
|
|
315
|
+
CartLineProductDto: {
|
|
316
|
+
id: string;
|
|
317
|
+
name: string;
|
|
318
|
+
slug: string;
|
|
319
|
+
};
|
|
320
|
+
CartLineVariantDto: {
|
|
321
|
+
id: string;
|
|
322
|
+
selectedOptions: {
|
|
323
|
+
[key: string]: string;
|
|
324
|
+
};
|
|
258
325
|
};
|
|
259
326
|
CategoryNodeDto: {
|
|
260
327
|
children: components["schemas"]["CategoryNodeDto"][];
|
|
@@ -298,6 +365,10 @@ export interface components {
|
|
|
298
365
|
slug: string;
|
|
299
366
|
url: string;
|
|
300
367
|
};
|
|
368
|
+
DescriptionDto: {
|
|
369
|
+
html: string;
|
|
370
|
+
text: string;
|
|
371
|
+
};
|
|
301
372
|
FacetDto: {
|
|
302
373
|
key: string;
|
|
303
374
|
label: string;
|
|
@@ -308,6 +379,10 @@ export interface components {
|
|
|
308
379
|
type: string;
|
|
309
380
|
values: components["schemas"]["FacetValueDto"][];
|
|
310
381
|
};
|
|
382
|
+
FacetLinkDto: {
|
|
383
|
+
key: string;
|
|
384
|
+
valueKey: string;
|
|
385
|
+
};
|
|
311
386
|
FacetValueDto: {
|
|
312
387
|
children: components["schemas"]["FacetValueDto"][] | null;
|
|
313
388
|
/** Format: int64 */
|
|
@@ -318,6 +393,10 @@ export interface components {
|
|
|
318
393
|
selected: boolean;
|
|
319
394
|
swatch: null | components["schemas"]["SwatchDto"];
|
|
320
395
|
};
|
|
396
|
+
FacetValuesResponse: {
|
|
397
|
+
facet: string;
|
|
398
|
+
values: components["schemas"]["FacetValueDto"][];
|
|
399
|
+
};
|
|
321
400
|
ListingResponse: {
|
|
322
401
|
appliedFilters: components["schemas"]["AppliedFilterDto"][];
|
|
323
402
|
facets: components["schemas"]["FacetDto"][];
|
|
@@ -414,6 +493,7 @@ export interface components {
|
|
|
414
493
|
vatRate: string;
|
|
415
494
|
};
|
|
416
495
|
ProductCardDto: {
|
|
496
|
+
brand: null | components["schemas"]["BrandDto"];
|
|
417
497
|
collections: string[];
|
|
418
498
|
id: string;
|
|
419
499
|
image: null | components["schemas"]["MediaDescriptorDto"];
|
|
@@ -421,6 +501,7 @@ export interface components {
|
|
|
421
501
|
name: string;
|
|
422
502
|
price: null | components["schemas"]["PriceDto"];
|
|
423
503
|
priceVaries: boolean;
|
|
504
|
+
shortDescription: null | string;
|
|
424
505
|
sku: string;
|
|
425
506
|
slug: string;
|
|
426
507
|
/** Format: date-time */
|
|
@@ -431,8 +512,12 @@ export interface components {
|
|
|
431
512
|
alternateUrls: {
|
|
432
513
|
[key: string]: string;
|
|
433
514
|
};
|
|
515
|
+
attributes: components["schemas"]["AttributeDto"][];
|
|
516
|
+
brand: null | components["schemas"]["BrandDto"];
|
|
517
|
+
bundle: null | components["schemas"]["BundleDto"];
|
|
434
518
|
categories: components["schemas"]["CategoryRefDto"][];
|
|
435
519
|
collections: components["schemas"]["CollectionRefDto"][];
|
|
520
|
+
description: null | components["schemas"]["DescriptionDto"];
|
|
436
521
|
files: components["schemas"]["MediaDescriptorDto"][];
|
|
437
522
|
id: string;
|
|
438
523
|
image: null | components["schemas"]["MediaDescriptorDto"];
|
|
@@ -441,7 +526,9 @@ export interface components {
|
|
|
441
526
|
name: string;
|
|
442
527
|
options: components["schemas"]["OptionDto"][];
|
|
443
528
|
redirectTo: null | string;
|
|
529
|
+
related: components["schemas"]["RelatedGroupDto"][];
|
|
444
530
|
seo: components["schemas"]["SeoDto"];
|
|
531
|
+
shortDescription: null | string;
|
|
445
532
|
sku: string;
|
|
446
533
|
slug: string;
|
|
447
534
|
/** Format: date-time */
|
|
@@ -457,12 +544,18 @@ export interface components {
|
|
|
457
544
|
min: string;
|
|
458
545
|
mode: string;
|
|
459
546
|
selected: null | components["schemas"]["RangeSelectionDto"];
|
|
547
|
+
step: null | string;
|
|
460
548
|
unit: null | string;
|
|
461
549
|
};
|
|
462
550
|
RangeSelectionDto: {
|
|
463
551
|
max: null | string;
|
|
464
552
|
min: null | string;
|
|
465
553
|
};
|
|
554
|
+
RelatedGroupDto: {
|
|
555
|
+
key: string;
|
|
556
|
+
label: string;
|
|
557
|
+
products: components["schemas"]["ProductCardDto"][];
|
|
558
|
+
};
|
|
466
559
|
SeoDto: {
|
|
467
560
|
description: null | string;
|
|
468
561
|
title: string;
|
|
@@ -532,6 +625,22 @@ export interface components {
|
|
|
532
625
|
/** @description Link to this code's documentation. */
|
|
533
626
|
type?: string;
|
|
534
627
|
};
|
|
628
|
+
SuggestCategoryDto: {
|
|
629
|
+
id: string;
|
|
630
|
+
name: string;
|
|
631
|
+
path: string[];
|
|
632
|
+
};
|
|
633
|
+
SuggestFacetValueDto: {
|
|
634
|
+
facet: string;
|
|
635
|
+
key: string;
|
|
636
|
+
label: string;
|
|
637
|
+
};
|
|
638
|
+
SuggestResponse: {
|
|
639
|
+
categories: components["schemas"]["SuggestCategoryDto"][];
|
|
640
|
+
facetValues: components["schemas"]["SuggestFacetValueDto"][];
|
|
641
|
+
products: components["schemas"]["ProductCardDto"][];
|
|
642
|
+
query: string;
|
|
643
|
+
};
|
|
535
644
|
SwatchDto: {
|
|
536
645
|
color: null | string;
|
|
537
646
|
image: null | components["schemas"]["MediaDescriptorDto"];
|
|
@@ -1630,6 +1739,96 @@ export interface operations {
|
|
|
1630
1739
|
};
|
|
1631
1740
|
};
|
|
1632
1741
|
};
|
|
1742
|
+
SearchFacetValues: {
|
|
1743
|
+
parameters: {
|
|
1744
|
+
query?: {
|
|
1745
|
+
/** @description Narrows to the values whose label contains q (case-insensitively) or whose key starts with it. Omit for the facet's values as they are. Matched against the 1000 most common values of the facet, in this API — at most 50 are returned. Present but blank is a 400 (INVALID_QUERY). */
|
|
1746
|
+
q?: string;
|
|
1747
|
+
/** @description The filter context the values are counted in, sent as filter[key]=value exactly as on /products: a count is what selecting that value would leave. This facet's own selection does not narrow it (the counts are disjunctive), and a key this site has no facet for is dropped silently. */
|
|
1748
|
+
filter?: {
|
|
1749
|
+
[key: string]: string;
|
|
1750
|
+
};
|
|
1751
|
+
};
|
|
1752
|
+
header: {
|
|
1753
|
+
/** @description Publishable, preview or secret site key. Required on every request; secret keys are server-side only. */
|
|
1754
|
+
"X-Site-Key": string;
|
|
1755
|
+
/** @description Market code (e.g. "se"). Omit for the site's default market. */
|
|
1756
|
+
"X-Market"?: string;
|
|
1757
|
+
/** @description BCP-47 language tag. Omit to use the market's language. */
|
|
1758
|
+
"Accept-Language"?: string;
|
|
1759
|
+
};
|
|
1760
|
+
path: {
|
|
1761
|
+
key: string;
|
|
1762
|
+
};
|
|
1763
|
+
cookie?: never;
|
|
1764
|
+
};
|
|
1765
|
+
requestBody?: never;
|
|
1766
|
+
responses: {
|
|
1767
|
+
/** @description OK */
|
|
1768
|
+
200: {
|
|
1769
|
+
headers: {
|
|
1770
|
+
[name: string]: unknown;
|
|
1771
|
+
};
|
|
1772
|
+
content: {
|
|
1773
|
+
"application/json": components["schemas"]["FacetValuesResponse"];
|
|
1774
|
+
};
|
|
1775
|
+
};
|
|
1776
|
+
/** @description problem+json. MARKET_UNKNOWN (no such market on this site), INVALID_PAGE, or INVALID_QUERY (q present but blank, or longer than 100 characters), or FACET_NOT_SEARCHABLE (the facet exists but has no list of values to search in: a range, a toggle or a tree). */
|
|
1777
|
+
400: {
|
|
1778
|
+
headers: {
|
|
1779
|
+
[name: string]: unknown;
|
|
1780
|
+
};
|
|
1781
|
+
content: {
|
|
1782
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
1783
|
+
};
|
|
1784
|
+
};
|
|
1785
|
+
/** @description problem+json. SITE_KEY_MISSING or SITE_KEY_INVALID. */
|
|
1786
|
+
401: {
|
|
1787
|
+
headers: {
|
|
1788
|
+
[name: string]: unknown;
|
|
1789
|
+
};
|
|
1790
|
+
content: {
|
|
1791
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
1792
|
+
};
|
|
1793
|
+
};
|
|
1794
|
+
/** @description problem+json. SECRET_KEY_FROM_BROWSER: a secret key was sent from a browser. */
|
|
1795
|
+
403: {
|
|
1796
|
+
headers: {
|
|
1797
|
+
[name: string]: unknown;
|
|
1798
|
+
};
|
|
1799
|
+
content: {
|
|
1800
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
1801
|
+
};
|
|
1802
|
+
};
|
|
1803
|
+
/** @description problem+json. FACET_NOT_FOUND, or SITE_INACTIVE when the site itself is not live. */
|
|
1804
|
+
404: {
|
|
1805
|
+
headers: {
|
|
1806
|
+
[name: string]: unknown;
|
|
1807
|
+
};
|
|
1808
|
+
content: {
|
|
1809
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
1810
|
+
};
|
|
1811
|
+
};
|
|
1812
|
+
/** @description problem+json. RATE_LIMITED; retryAfterSeconds and the Retry-After header say how long to wait. */
|
|
1813
|
+
429: {
|
|
1814
|
+
headers: {
|
|
1815
|
+
[name: string]: unknown;
|
|
1816
|
+
};
|
|
1817
|
+
content: {
|
|
1818
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
1819
|
+
};
|
|
1820
|
+
};
|
|
1821
|
+
/** @description problem+json. SITE_REGISTRY_WARMING or INDEX_UNAVAILABLE — retry, the request was not wrong. */
|
|
1822
|
+
503: {
|
|
1823
|
+
headers: {
|
|
1824
|
+
[name: string]: unknown;
|
|
1825
|
+
};
|
|
1826
|
+
content: {
|
|
1827
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
1828
|
+
};
|
|
1829
|
+
};
|
|
1830
|
+
};
|
|
1831
|
+
};
|
|
1633
1832
|
GetProduct: {
|
|
1634
1833
|
parameters: {
|
|
1635
1834
|
query?: never;
|
|
@@ -1805,6 +2004,90 @@ export interface operations {
|
|
|
1805
2004
|
};
|
|
1806
2005
|
};
|
|
1807
2006
|
};
|
|
2007
|
+
Suggest: {
|
|
2008
|
+
parameters: {
|
|
2009
|
+
query: {
|
|
2010
|
+
/** @description What the shopper has typed so far, 1–100 characters. Blank, missing or longer is a 400 (INVALID_QUERY) — unlike a listing's q, which is truncated. */
|
|
2011
|
+
q: string;
|
|
2012
|
+
};
|
|
2013
|
+
header: {
|
|
2014
|
+
/** @description Publishable, preview or secret site key. Required on every request; secret keys are server-side only. */
|
|
2015
|
+
"X-Site-Key": string;
|
|
2016
|
+
/** @description Market code (e.g. "se"). Omit for the site's default market. */
|
|
2017
|
+
"X-Market"?: string;
|
|
2018
|
+
/** @description BCP-47 language tag. Omit to use the market's language. */
|
|
2019
|
+
"Accept-Language"?: string;
|
|
2020
|
+
};
|
|
2021
|
+
path?: never;
|
|
2022
|
+
cookie?: never;
|
|
2023
|
+
};
|
|
2024
|
+
requestBody?: never;
|
|
2025
|
+
responses: {
|
|
2026
|
+
/** @description OK */
|
|
2027
|
+
200: {
|
|
2028
|
+
headers: {
|
|
2029
|
+
[name: string]: unknown;
|
|
2030
|
+
};
|
|
2031
|
+
content: {
|
|
2032
|
+
"application/json": components["schemas"]["SuggestResponse"];
|
|
2033
|
+
};
|
|
2034
|
+
};
|
|
2035
|
+
/** @description problem+json. MARKET_UNKNOWN (no such market on this site), INVALID_PAGE, or INVALID_QUERY (q missing, blank or longer than 100 characters). */
|
|
2036
|
+
400: {
|
|
2037
|
+
headers: {
|
|
2038
|
+
[name: string]: unknown;
|
|
2039
|
+
};
|
|
2040
|
+
content: {
|
|
2041
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
2042
|
+
};
|
|
2043
|
+
};
|
|
2044
|
+
/** @description problem+json. SITE_KEY_MISSING or SITE_KEY_INVALID. */
|
|
2045
|
+
401: {
|
|
2046
|
+
headers: {
|
|
2047
|
+
[name: string]: unknown;
|
|
2048
|
+
};
|
|
2049
|
+
content: {
|
|
2050
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
2051
|
+
};
|
|
2052
|
+
};
|
|
2053
|
+
/** @description problem+json. SECRET_KEY_FROM_BROWSER: a secret key was sent from a browser. */
|
|
2054
|
+
403: {
|
|
2055
|
+
headers: {
|
|
2056
|
+
[name: string]: unknown;
|
|
2057
|
+
};
|
|
2058
|
+
content: {
|
|
2059
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
2060
|
+
};
|
|
2061
|
+
};
|
|
2062
|
+
/** @description problem+json. SITE_INACTIVE, or NOT_FOUND for an unrouted path. */
|
|
2063
|
+
404: {
|
|
2064
|
+
headers: {
|
|
2065
|
+
[name: string]: unknown;
|
|
2066
|
+
};
|
|
2067
|
+
content: {
|
|
2068
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
2069
|
+
};
|
|
2070
|
+
};
|
|
2071
|
+
/** @description problem+json. RATE_LIMITED; retryAfterSeconds and the Retry-After header say how long to wait. */
|
|
2072
|
+
429: {
|
|
2073
|
+
headers: {
|
|
2074
|
+
[name: string]: unknown;
|
|
2075
|
+
};
|
|
2076
|
+
content: {
|
|
2077
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
2078
|
+
};
|
|
2079
|
+
};
|
|
2080
|
+
/** @description problem+json. SITE_REGISTRY_WARMING or INDEX_UNAVAILABLE — retry, the request was not wrong. */
|
|
2081
|
+
503: {
|
|
2082
|
+
headers: {
|
|
2083
|
+
[name: string]: unknown;
|
|
2084
|
+
};
|
|
2085
|
+
content: {
|
|
2086
|
+
"application/problem+json": components["schemas"]["StorefrontProblem"];
|
|
2087
|
+
};
|
|
2088
|
+
};
|
|
2089
|
+
};
|
|
2090
|
+
};
|
|
1808
2091
|
GetSite: {
|
|
1809
2092
|
parameters: {
|
|
1810
2093
|
query?: never;
|