@commerce-blocks/sdk 2.0.0-alpha.3 → 2.0.2
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 +91 -24
- package/dist/index.d.ts +97 -37
- package/dist/index.js +1103 -896
- package/package.json +3 -8
package/README.md
CHANGED
|
@@ -40,31 +40,48 @@ collection.dispose()
|
|
|
40
40
|
|
|
41
41
|
## Configuration
|
|
42
42
|
|
|
43
|
-
| Option
|
|
44
|
-
|
|
|
45
|
-
| `token`
|
|
46
|
-
| `sorts`
|
|
47
|
-
| `facets`
|
|
48
|
-
| `attributes`
|
|
49
|
-
| `baseUrl`
|
|
50
|
-
| `fetch`
|
|
51
|
-
| `currency`
|
|
52
|
-
| `formatPrice`
|
|
53
|
-
| `swatches`
|
|
54
|
-
| `
|
|
55
|
-
| `
|
|
56
|
-
| `
|
|
57
|
-
| `
|
|
58
|
-
| `
|
|
59
|
-
| `
|
|
60
|
-
| `
|
|
61
|
-
| `
|
|
62
|
-
|
|
63
|
-
|
|
43
|
+
| Option | Type | Required | Description |
|
|
44
|
+
| --------------- | ------------------------------ | -------- | ------------------------------------ |
|
|
45
|
+
| `token` | `string` | Yes | Layers API public token |
|
|
46
|
+
| `sorts` | `Sort[]` | Yes | Sort options `{ name, code }` |
|
|
47
|
+
| `facets` | `Facet[]` | Yes | Facet fields `{ name, code }` |
|
|
48
|
+
| `attributes` | `string[]` | No | Product attributes to fetch |
|
|
49
|
+
| `baseUrl` | `string` | No | Custom API URL |
|
|
50
|
+
| `fetch` | `CustomFetch` | No | Custom fetch (SSR, testing) |
|
|
51
|
+
| `currency` | `string` | No | Currency for price formatting |
|
|
52
|
+
| `formatPrice` | `(amount, currency) => string` | No | Custom price formatter |
|
|
53
|
+
| `swatches` | `Swatch[]` | No | Color swatch definitions |
|
|
54
|
+
| `transforms` | `Transforms` | No | Post-process results (see below) |
|
|
55
|
+
| `filterAliases` | `FilterAliases` | No | URL-friendly filter key mapping |
|
|
56
|
+
| `cacheLimit` | `number` | No | Max entries in cache |
|
|
57
|
+
| `cacheLifetime` | `number` | No | TTL in milliseconds |
|
|
58
|
+
| `storage` | `StorageAdapter` | No | Custom storage adapter |
|
|
59
|
+
| `initialData` | `CacheData` | No | Pre-populate cache at init |
|
|
60
|
+
| `restoreCache` | `boolean` | No | Restore from storage (default: true) |
|
|
61
|
+
| `flags` | `Flags` | No | Feature flags (see below) |
|
|
62
|
+
|
|
63
|
+
### Flags
|
|
64
|
+
|
|
65
|
+
Control which product data the SDK requests from the API.
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
createClient({
|
|
69
|
+
// ...config
|
|
70
|
+
flags: { variants: true }, // opt-in for full variants array
|
|
71
|
+
})
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
| Flag | Default | Description |
|
|
75
|
+
| ---------- | ------- | ----------------------------------------------------------------------------- |
|
|
76
|
+
| `variants` | `false` | Request full variants array per product. Enable for PDPs or option selectors. |
|
|
77
|
+
|
|
78
|
+
By default, products are **shallow** — `variants` contains only the matched variant, and `price`/`compareAtPrice`/`featuredMedia`/`availableForSale` are sourced from `first_or_matched_variant`. This significantly reduces API payload size.
|
|
79
|
+
|
|
80
|
+
When `flags.variants` is `true`, the full `variants` array is requested and `selectedVariant` is looked up from it. Use this for product detail pages or cards with variant/option selectors.
|
|
64
81
|
|
|
65
82
|
## Controllers
|
|
66
83
|
|
|
67
|
-
All controllers (`collection`, `blocks`, `search`, `suggest`) follow the same pattern:
|
|
84
|
+
All controllers (`collection`, `blocks`, `search`, `suggest`, `searchContent`) follow the same pattern:
|
|
68
85
|
|
|
69
86
|
- **`state`** — a `ReadonlySignal<QueryState<T>>` with `{ data, error, isFetching }`
|
|
70
87
|
- **`execute()`** — runs the query, returns `Result<T, ClientError>`
|
|
@@ -210,6 +227,56 @@ suggest.dispose()
|
|
|
210
227
|
| `excludeQueries` | `string[]` | Custom strings to filter from suggestions |
|
|
211
228
|
| `signal` | `AbortSignal` | Shared abort signal (acts like `dispose()`) |
|
|
212
229
|
|
|
230
|
+
### Content Search
|
|
231
|
+
|
|
232
|
+
Search articles and other content types.
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
const content = client.searchContent({ query: 'styling tips' })
|
|
236
|
+
|
|
237
|
+
const { data } = await content.execute()
|
|
238
|
+
// data.articles, data.totalResults, data.page
|
|
239
|
+
|
|
240
|
+
await content.execute({ query: 'new arrivals', contentType: 'blog' })
|
|
241
|
+
await content.execute({ page: 2, temporary: true })
|
|
242
|
+
|
|
243
|
+
content.dispose()
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
| Option | Type | Description |
|
|
247
|
+
| ------------------ | ---------------- | ----------------------------------------- |
|
|
248
|
+
| `query` | `string` | Search query |
|
|
249
|
+
| `contentType` | `string` | Filter by content type |
|
|
250
|
+
| `page` | `number` | Page number |
|
|
251
|
+
| `limit` | `number` | Results per page |
|
|
252
|
+
| `tuning` | `SearchTuning` | Matching weight configuration |
|
|
253
|
+
| `signal` | `AbortSignal` | Abort signal |
|
|
254
|
+
| `transformRequest` | `(body) => body` | Custom request body transformation |
|
|
255
|
+
| `temporary` | `boolean` | Override without persisting for next call |
|
|
256
|
+
|
|
257
|
+
Result shape:
|
|
258
|
+
|
|
259
|
+
```typescript
|
|
260
|
+
interface SearchContentResult {
|
|
261
|
+
articles: Article[]
|
|
262
|
+
query: string
|
|
263
|
+
contentType: string | null
|
|
264
|
+
totalResults: number
|
|
265
|
+
page: number
|
|
266
|
+
resultsPerPage: number
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
interface Article {
|
|
270
|
+
title: string
|
|
271
|
+
handle: string
|
|
272
|
+
summary: string
|
|
273
|
+
author: string
|
|
274
|
+
tags: string[]
|
|
275
|
+
image: { url: string; width: number; height: number } | null
|
|
276
|
+
publishedAt: string
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
213
280
|
### Image Search
|
|
214
281
|
|
|
215
282
|
Upload an image, then search by it.
|
|
@@ -398,7 +465,7 @@ if (result.error) {
|
|
|
398
465
|
}
|
|
399
466
|
```
|
|
400
467
|
|
|
401
|
-
|
|
468
|
+
`isRetryable` classifies errors by tag, code, and status — use it standalone or as a `shouldRetry` predicate:
|
|
402
469
|
|
|
403
470
|
```typescript
|
|
404
471
|
import { isRetryable } from '@commerce-blocks/sdk'
|
|
@@ -417,7 +484,7 @@ The client exposes a reactive cache:
|
|
|
417
484
|
const { cache } = client
|
|
418
485
|
|
|
419
486
|
cache.get('cache-key') // CacheEntry<QueryResult> | null
|
|
420
|
-
cache.invalidate('browse
|
|
487
|
+
cache.invalidate('browse') // invalidate keys containing 'browse'
|
|
421
488
|
cache.persist() // save to storage
|
|
422
489
|
cache.restore() // restore from storage
|
|
423
490
|
cache.clear() // clear all
|
package/dist/index.d.ts
CHANGED
|
@@ -19,7 +19,6 @@ export declare interface ApiError {
|
|
|
19
19
|
readonly source: ApiSource;
|
|
20
20
|
readonly message: string;
|
|
21
21
|
readonly status?: number;
|
|
22
|
-
readonly retryable: boolean;
|
|
23
22
|
readonly retryAfterMs?: number;
|
|
24
23
|
readonly cause?: unknown;
|
|
25
24
|
}
|
|
@@ -34,6 +33,22 @@ declare interface ApiFetchConfig {
|
|
|
34
33
|
|
|
35
34
|
declare type ApiSource = 'layers';
|
|
36
35
|
|
|
36
|
+
export declare interface Article {
|
|
37
|
+
title: string;
|
|
38
|
+
handle: string;
|
|
39
|
+
summary: string;
|
|
40
|
+
author: string;
|
|
41
|
+
tags: string[];
|
|
42
|
+
image: ArticleImage | null;
|
|
43
|
+
publishedAt: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
declare interface ArticleImage {
|
|
47
|
+
url: string;
|
|
48
|
+
width: number;
|
|
49
|
+
height: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
37
52
|
export { batch }
|
|
38
53
|
|
|
39
54
|
declare interface BlocksContext {
|
|
@@ -76,8 +91,8 @@ export declare interface BlocksResult extends QueryResult {
|
|
|
76
91
|
}
|
|
77
92
|
|
|
78
93
|
declare interface Cache_2 {
|
|
79
|
-
get(key: string): CacheEntry<
|
|
80
|
-
set(key: string, result:
|
|
94
|
+
get(key: string): CacheEntry<CacheValue> | null;
|
|
95
|
+
set(key: string, result: CacheValue): void;
|
|
81
96
|
isExpired(key: string): boolean;
|
|
82
97
|
invalidate(pattern: string): void;
|
|
83
98
|
persist(): void;
|
|
@@ -88,11 +103,12 @@ declare interface Cache_2 {
|
|
|
88
103
|
};
|
|
89
104
|
}
|
|
90
105
|
|
|
91
|
-
declare type CacheData = Record<string,
|
|
106
|
+
declare type CacheData = Record<string, CacheValue>;
|
|
92
107
|
|
|
93
108
|
declare interface CacheEntry<T> {
|
|
94
109
|
data: T;
|
|
95
110
|
timestamp: number;
|
|
111
|
+
createdAt: number;
|
|
96
112
|
}
|
|
97
113
|
|
|
98
114
|
export declare interface CacheOptions {
|
|
@@ -103,6 +119,8 @@ export declare interface CacheOptions {
|
|
|
103
119
|
storageAdapter?: StorageAdapter;
|
|
104
120
|
}
|
|
105
121
|
|
|
122
|
+
declare type CacheValue = QueryResult | ContentResult;
|
|
123
|
+
|
|
106
124
|
export declare interface Client {
|
|
107
125
|
collection: (options: CollectionOptions) => CollectionController;
|
|
108
126
|
blocks: (options: BlocksOptions) => BlocksController;
|
|
@@ -110,6 +128,7 @@ export declare interface Client {
|
|
|
110
128
|
search: (options?: SearchQuery) => SearchController;
|
|
111
129
|
uploadImage: (options: UploadImageOptions) => UploadImageController;
|
|
112
130
|
searchByImage: (options: SearchByImageQuery) => SearchByImageController;
|
|
131
|
+
searchContent: (options?: SearchContentQuery) => SearchContentController;
|
|
113
132
|
config: ClientConfig;
|
|
114
133
|
cache: Cache_2;
|
|
115
134
|
}
|
|
@@ -117,17 +136,8 @@ export declare interface Client {
|
|
|
117
136
|
export declare interface ClientConfig extends ApiClientConfig {
|
|
118
137
|
includeMeta?: boolean;
|
|
119
138
|
currency?: string;
|
|
120
|
-
formatPrice?:
|
|
139
|
+
formatPrice?: FormatPriceFn;
|
|
121
140
|
swatches?: Swatch[];
|
|
122
|
-
options?: string[];
|
|
123
|
-
productMetafields?: {
|
|
124
|
-
namespace: string;
|
|
125
|
-
key: string;
|
|
126
|
-
}[];
|
|
127
|
-
variantMetafields?: {
|
|
128
|
-
namespace: string;
|
|
129
|
-
key: string;
|
|
130
|
-
}[];
|
|
131
141
|
cacheLimit?: number;
|
|
132
142
|
cacheLifetime?: number;
|
|
133
143
|
/** Custom storage adapter for cache persistence. Defaults to localStorage in browser. */
|
|
@@ -173,6 +183,39 @@ export declare interface ConfigError {
|
|
|
173
183
|
|
|
174
184
|
declare type ConfigErrorCode = 'MISSING_CONFIG' | 'INVALID_CONFIG';
|
|
175
185
|
|
|
186
|
+
declare interface ContentArticleRaw {
|
|
187
|
+
title: string;
|
|
188
|
+
handle: string;
|
|
189
|
+
summary_text: string;
|
|
190
|
+
author: string;
|
|
191
|
+
tags: string[];
|
|
192
|
+
image: {
|
|
193
|
+
url: string;
|
|
194
|
+
width: number;
|
|
195
|
+
height: number;
|
|
196
|
+
} | null;
|
|
197
|
+
published_at: string;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
declare interface ContentResult {
|
|
201
|
+
articles: unknown[];
|
|
202
|
+
query: string;
|
|
203
|
+
contentType: string | null;
|
|
204
|
+
totalResults: number;
|
|
205
|
+
page: number;
|
|
206
|
+
resultsPerPage: number;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
declare interface ContentSearchResponse {
|
|
210
|
+
results: ContentArticleRaw[];
|
|
211
|
+
query: string;
|
|
212
|
+
contentType: string | null;
|
|
213
|
+
totalResults: number;
|
|
214
|
+
totalPages: number;
|
|
215
|
+
page: number;
|
|
216
|
+
resultsPerPage: number;
|
|
217
|
+
}
|
|
218
|
+
|
|
176
219
|
export declare interface Controller<TData, TQuery = void> {
|
|
177
220
|
readonly state: ReadonlySignal<QueryState<TData>>;
|
|
178
221
|
execute(query?: TQuery): Promise<Result<TData, ClientError>>;
|
|
@@ -278,6 +321,8 @@ declare enum FilterOperator {
|
|
|
278
321
|
|
|
279
322
|
declare type FilterValue = string | number | boolean;
|
|
280
323
|
|
|
324
|
+
declare type FormatPriceFn = (amount: number, currencyCode: string) => string;
|
|
325
|
+
|
|
281
326
|
export declare function getClient(): Result<Client, ConfigError>;
|
|
282
327
|
|
|
283
328
|
export declare function gt(property: string, value: number): FilterExpression;
|
|
@@ -382,21 +427,10 @@ declare interface MatchedVariant extends LayersVariant {
|
|
|
382
427
|
rn?: number;
|
|
383
428
|
}
|
|
384
429
|
|
|
385
|
-
export declare interface Metafield extends MetafieldIdentifier {
|
|
386
|
-
value: string;
|
|
387
|
-
type: string;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
declare interface MetafieldIdentifier {
|
|
391
|
-
namespace: string;
|
|
392
|
-
key: string;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
430
|
export declare interface NetworkError {
|
|
396
431
|
readonly _tag: 'NetworkError';
|
|
397
432
|
readonly code: NetworkErrorCode;
|
|
398
433
|
readonly message: string;
|
|
399
|
-
readonly retryable: boolean;
|
|
400
434
|
readonly retryAfterMs?: number;
|
|
401
435
|
readonly cause?: unknown;
|
|
402
436
|
}
|
|
@@ -465,7 +499,7 @@ export declare interface PriceRangeData {
|
|
|
465
499
|
compareAtPriceRange: PriceRange | null;
|
|
466
500
|
}
|
|
467
501
|
|
|
468
|
-
export declare type Product
|
|
502
|
+
export declare type Product = ProductBase & Record<string, unknown>;
|
|
469
503
|
|
|
470
504
|
export declare interface ProductBase {
|
|
471
505
|
id: CommerceBlocksID;
|
|
@@ -479,8 +513,8 @@ export declare interface ProductBase {
|
|
|
479
513
|
tags: string[];
|
|
480
514
|
images: Image_2[];
|
|
481
515
|
featuredMedia: FeaturedMedia | null;
|
|
482
|
-
|
|
483
|
-
|
|
516
|
+
price: Price;
|
|
517
|
+
compareAtPrice: Price | null;
|
|
484
518
|
options: RichProductOption[];
|
|
485
519
|
selectedOptions: ProductOption[];
|
|
486
520
|
variants: ProductVariant[];
|
|
@@ -508,7 +542,7 @@ export declare interface ProductCardController {
|
|
|
508
542
|
setSelectedOptions(options: ProductOption[]): void;
|
|
509
543
|
setSelectedVariant(variantId: number): void;
|
|
510
544
|
setCarouselPosition(position: number): void;
|
|
511
|
-
subscribe(callback: (state: ProductCardState) => void):
|
|
545
|
+
subscribe(callback: (state: ProductCardState) => void): Unsubscribe;
|
|
512
546
|
dispose(): void;
|
|
513
547
|
}
|
|
514
548
|
|
|
@@ -582,17 +616,18 @@ declare interface ProductResult {
|
|
|
582
616
|
featured_media: FeaturedMedia_2 | null;
|
|
583
617
|
category: ProductCategory_2 | null;
|
|
584
618
|
tags: string[];
|
|
585
|
-
images
|
|
619
|
+
images?: ProductImage[];
|
|
586
620
|
collection_titles: string[];
|
|
587
621
|
metafields: Record<string, Record<string, unknown>>;
|
|
588
622
|
calculated: Record<string, unknown>;
|
|
589
|
-
|
|
623
|
+
options_v2: OptionV2[];
|
|
624
|
+
first_or_matched_variant: MatchedVariant;
|
|
625
|
+
price_range?: {
|
|
590
626
|
from: number;
|
|
591
627
|
to: number;
|
|
592
628
|
compare_at_price: number;
|
|
593
629
|
};
|
|
594
|
-
|
|
595
|
-
options_v2: OptionV2[];
|
|
630
|
+
variants?: LayersVariant[];
|
|
596
631
|
body_html?: string | null;
|
|
597
632
|
is_gift_card?: boolean | null;
|
|
598
633
|
has_variants_that_require_components?: boolean | null;
|
|
@@ -601,8 +636,6 @@ declare interface ProductResult {
|
|
|
601
636
|
created_at?: string;
|
|
602
637
|
updated_at?: string;
|
|
603
638
|
published_at?: string;
|
|
604
|
-
first_or_matched_variant?: MatchedVariant;
|
|
605
|
-
variants: LayersVariant[];
|
|
606
639
|
}
|
|
607
640
|
|
|
608
641
|
export declare interface ProductVariant {
|
|
@@ -658,6 +691,7 @@ declare type Result<T, E = Error> = {
|
|
|
658
691
|
};
|
|
659
692
|
|
|
660
693
|
export declare interface RichProductOption extends ProductOption {
|
|
694
|
+
code: string;
|
|
661
695
|
swatch?: Swatch;
|
|
662
696
|
}
|
|
663
697
|
|
|
@@ -672,6 +706,33 @@ export declare interface SearchByImageQuery extends QueryParams {
|
|
|
672
706
|
tuning?: SearchTuning;
|
|
673
707
|
}
|
|
674
708
|
|
|
709
|
+
export declare interface SearchContentController {
|
|
710
|
+
readonly state: ReadonlySignal<QueryState<SearchContentResult>>;
|
|
711
|
+
execute(query?: SearchContentQuery): Promise<Result<SearchContentResult, ClientError>>;
|
|
712
|
+
subscribe(callback: (state: QueryState<SearchContentResult>) => void): Unsubscribe;
|
|
713
|
+
dispose(): void;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
export declare interface SearchContentQuery {
|
|
717
|
+
query?: string;
|
|
718
|
+
contentType?: string;
|
|
719
|
+
page?: number;
|
|
720
|
+
limit?: number;
|
|
721
|
+
tuning?: SearchTuning;
|
|
722
|
+
signal?: AbortSignal;
|
|
723
|
+
transformRequest?: RequestTransformer;
|
|
724
|
+
temporary?: boolean;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
export declare interface SearchContentResult {
|
|
728
|
+
articles: Article[];
|
|
729
|
+
query: string;
|
|
730
|
+
contentType: string | null;
|
|
731
|
+
totalResults: number;
|
|
732
|
+
page: number;
|
|
733
|
+
resultsPerPage: number;
|
|
734
|
+
}
|
|
735
|
+
|
|
675
736
|
export declare interface SearchController {
|
|
676
737
|
readonly state: ReadonlySignal<QueryState<SearchResult>>;
|
|
677
738
|
prepare(query?: SearchQuery): Promise<Result<SearchPrepareResult, ClientError>>;
|
|
@@ -783,13 +844,12 @@ export declare interface Transforms {
|
|
|
783
844
|
block?: (result: BlocksResult, raw: LayersResponse & {
|
|
784
845
|
block?: BlocksInfo;
|
|
785
846
|
}) => BlocksResult;
|
|
847
|
+
searchContent?: (result: SearchContentResult, raw: ContentSearchResponse) => SearchContentResult;
|
|
786
848
|
filters?: (filters: unknown) => FilterGroup | undefined;
|
|
787
849
|
}
|
|
788
850
|
|
|
789
851
|
export declare type Unsubscribe = () => void;
|
|
790
852
|
|
|
791
|
-
declare type Unsubscribe_2 = () => void;
|
|
792
|
-
|
|
793
853
|
export declare interface UploadImageController {
|
|
794
854
|
readonly state: ReadonlySignal<QueryState<UploadImageResult>>;
|
|
795
855
|
subscribe(callback: (state: QueryState<UploadImageResult>) => void): Unsubscribe;
|