@swell/apps-sdk 1.0.142 → 1.0.143
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/LICENSE +22 -0
- package/README.md +304 -0
- package/dist/index.cjs +73 -29
- package/dist/index.cjs.map +3 -3
- package/dist/index.js +73 -29
- package/dist/index.js.map +3 -3
- package/dist/index.mjs +73 -29
- package/dist/index.mjs.map +3 -3
- package/dist/src/compatibility/shopify-objects/collection.d.ts +1 -1
- package/dist/src/resources/product.d.ts +13 -0
- package/dist/types/shopify.d.ts +3 -3
- package/package.json +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (c) 2025-present Swell Commerce Corp.
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
4
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
5
|
+
the Software without restriction, including without limitation the rights to use,
|
|
6
|
+
copy, modify, merge, publish, distribute, sublicense, sell and/or create
|
|
7
|
+
derivative works of the Software or any part thereof, and to permit persons to whom the
|
|
8
|
+
Software is furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The rights granted above may only be exercised to develop storefront apps that integrate
|
|
11
|
+
or interoperate with Swell software or services, and, if applicable, to
|
|
12
|
+
distribute, offer for sale or otherwise make available any such storefront apps via the Swell App Store. All other uses of the Software are strictly prohibited.
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be included in all
|
|
15
|
+
copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
|
|
19
|
+
A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
20
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
21
|
+
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
# Swell Apps SDK
|
|
2
|
+
|
|
3
|
+
The Swell Apps SDK is a TypeScript-based library designed to simplify the development of isomorphic Swell apps by providing streamlined API access, theme rendering capabilities, and comprehensive caching solutions.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
### Core functionality
|
|
8
|
+
- **Unified API access** - Seamless integration with both Swell Backend API and Storefront API
|
|
9
|
+
- **Authentication handling** - Automatic scoped access token management based on app permissions
|
|
10
|
+
- **Theme rendering** - Complete Shopify-compatible theme system with Liquid templating
|
|
11
|
+
- **Resource management** - Deferred loading of storefront resources (products, categories, etc.)
|
|
12
|
+
- **Caching system** - Multi-tier caching with Cloudflare KV integration
|
|
13
|
+
- **Shopify compatibility** - Full compatibility layer for migrating Shopify themes and apps
|
|
14
|
+
|
|
15
|
+
### Theme capabilities
|
|
16
|
+
- **Liquid templating** - Enhanced Liquid engine with Swell-specific objects and filters
|
|
17
|
+
- **Section rendering** - Dynamic section management with schema support
|
|
18
|
+
- **Settings resolution** - Automatic theme and section settings processing
|
|
19
|
+
- **Layout system** - Flexible layout rendering with section groups
|
|
20
|
+
- **Asset management** - Optimized asset loading and URL generation
|
|
21
|
+
- **Localization** - Multi-language support with translation rendering
|
|
22
|
+
|
|
23
|
+
### Developer experience
|
|
24
|
+
- **TypeScript support** - Full type safety with comprehensive type definitions
|
|
25
|
+
- **Isomorphic design** - Works seamlessly in both browser and server environments
|
|
26
|
+
- **Error handling** - Robust error management with detailed debugging information
|
|
27
|
+
- **Performance optimized** - Built-in caching and resource optimization
|
|
28
|
+
- **Extensible architecture** - Plugin system for custom resource types
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install @swell/apps-sdk
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Getting started
|
|
37
|
+
|
|
38
|
+
### Basic setup
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { Swell } from '@swell/apps-sdk';
|
|
42
|
+
|
|
43
|
+
// Initialize Swell instance in your app frontend
|
|
44
|
+
const swell = new Swell({
|
|
45
|
+
serverHeaders: context.request.headers, // Headers from worker environment
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Make backend API calls
|
|
49
|
+
const products = await swell.backend.get('/products');
|
|
50
|
+
|
|
51
|
+
// Make storefront API calls
|
|
52
|
+
const cart = await swell.storefront.get('/cart');
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Headers and app proxying
|
|
56
|
+
|
|
57
|
+
When your Swell app is deployed, it runs behind Swell's proxy infrastructure. The proxy automatically injects essential headers that contain authentication tokens, store configuration, and storefront context. These headers are critical for the SDK to function properly:
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// Headers passed from Swell's proxy contain:
|
|
61
|
+
// - swell-store-id: The store identifier
|
|
62
|
+
// - swell-public-key: Frontend API access key
|
|
63
|
+
// - swell-access-token: Backend API access token (scoped to app permissions)
|
|
64
|
+
// - swell-storefront-id: Current storefront instance
|
|
65
|
+
// - swell-environment-id: Environment (development, staging, production)
|
|
66
|
+
// - swell-theme-id: Active theme identifier
|
|
67
|
+
// - swell-storefront-context: Preloaded cart/account data
|
|
68
|
+
|
|
69
|
+
const swell = new Swell({
|
|
70
|
+
serverHeaders: context.request.headers, // Contains all proxy-injected headers
|
|
71
|
+
getCookie: (name) => getCookieValue(name),
|
|
72
|
+
setCookie: (name, value, options) => setCookieValue(name, value, options),
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Without these headers, the SDK cannot:
|
|
77
|
+
- Authenticate with Swell APIs
|
|
78
|
+
- Determine which store and storefront to operate on
|
|
79
|
+
- Access cached resources or maintain session state
|
|
80
|
+
- Render themes with proper configuration
|
|
81
|
+
|
|
82
|
+
The `serverHeaders` parameter should always be passed the complete headers object from your app's request context to ensure full functionality.
|
|
83
|
+
|
|
84
|
+
### Theme rendering
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
import { Swell, SwellTheme, SwellProduct } from '@swell/apps-sdk';
|
|
88
|
+
|
|
89
|
+
const swell = new Swell({
|
|
90
|
+
serverHeaders: context.request.headers,
|
|
91
|
+
...options,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// Initialize theme with optional configuration
|
|
95
|
+
const theme = new SwellTheme(swell, {
|
|
96
|
+
forms: formConfigs,
|
|
97
|
+
resources: customResources,
|
|
98
|
+
globals: additionalGlobals,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Fetch settings and set global context
|
|
102
|
+
await theme.initGlobals('product'); // page ID
|
|
103
|
+
|
|
104
|
+
// Create page data with deferred resource loading
|
|
105
|
+
const data = {
|
|
106
|
+
product: new SwellProduct(swell, context.params.id),
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
// Render theme page
|
|
110
|
+
const renderedPage = await theme.renderPage(data);
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## API reference
|
|
114
|
+
|
|
115
|
+
### Swell class
|
|
116
|
+
|
|
117
|
+
The main entry point for SDK functionality:
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
class Swell {
|
|
121
|
+
// API access
|
|
122
|
+
backend: SwellBackendAPI;
|
|
123
|
+
storefront: typeof SwellJS;
|
|
124
|
+
|
|
125
|
+
// Configuration
|
|
126
|
+
config: SwellAppConfig;
|
|
127
|
+
url: URL;
|
|
128
|
+
headers: Record<string, string>;
|
|
129
|
+
queryParams: ParsedQs;
|
|
130
|
+
|
|
131
|
+
// State
|
|
132
|
+
isEditor: boolean;
|
|
133
|
+
isPreview: boolean;
|
|
134
|
+
storefrontContext: SwellData;
|
|
135
|
+
|
|
136
|
+
// Methods
|
|
137
|
+
get<T>(url: string, query?: SwellData): Promise<T>;
|
|
138
|
+
post<T>(url: string, data: SwellData): Promise<T>;
|
|
139
|
+
put<T>(url: string, data: SwellData): Promise<T>;
|
|
140
|
+
delete<T>(url: string, data?: SwellData): Promise<T>;
|
|
141
|
+
getCachedResource<T>(key: string, args: unknown[], handler: () => T): Promise<T>;
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### SwellTheme class
|
|
146
|
+
|
|
147
|
+
Handles theme rendering and management:
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
class SwellTheme {
|
|
151
|
+
// Core properties
|
|
152
|
+
swell: Swell;
|
|
153
|
+
globals: ThemeGlobals;
|
|
154
|
+
liquidSwell: LiquidSwell;
|
|
155
|
+
|
|
156
|
+
// Methods
|
|
157
|
+
initGlobals(pageId: string, altTemplate?: string): Promise<void>;
|
|
158
|
+
renderPage(pageData?: SwellData, altTemplate?: string): Promise<string>;
|
|
159
|
+
renderSection(sectionId: string, pageData?: SwellData): Promise<string>;
|
|
160
|
+
renderLayout(layoutName?: string, data?: SwellData): Promise<string>;
|
|
161
|
+
getSectionSchema(sectionName: string): Promise<ThemeSectionSchema>;
|
|
162
|
+
setGlobals(globals: Partial<ThemeGlobals>): void;
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Resource classes
|
|
167
|
+
|
|
168
|
+
Built-in storefront resource classes for deferred loading:
|
|
169
|
+
|
|
170
|
+
#### Standard resources
|
|
171
|
+
- `SwellAccount` - Customer account management
|
|
172
|
+
- `SwellBlog` - Blog post content
|
|
173
|
+
- `SwellBlogCategory` - Blog categorization
|
|
174
|
+
- `SwellCart` - Shopping cart state
|
|
175
|
+
- `SwellCategory` - Product categories
|
|
176
|
+
- `SwellOrder` - Order information
|
|
177
|
+
- `SwellPage` - Static pages
|
|
178
|
+
- `SwellProduct` - Product details
|
|
179
|
+
- `SwellVariant` - Product variants
|
|
180
|
+
|
|
181
|
+
#### Primitive resources
|
|
182
|
+
- `SwellStorefrontCollection` - Collection results with pagination
|
|
183
|
+
- `SwellStorefrontRecord` - Individual records
|
|
184
|
+
- `SwellStorefrontSingleton` - Unique resources (cart, account)
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
// Create custom resource class
|
|
188
|
+
class MyAppCollection extends SwellStorefrontCollection {
|
|
189
|
+
constructor(swell: Swell, query: SwellData = {}) {
|
|
190
|
+
super(swell, 'my-app-collection', query);
|
|
191
|
+
return this._getProxy();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Usage in theme data
|
|
196
|
+
const data = {
|
|
197
|
+
myCollection: new MyAppCollection(swell, { limit: 20 }),
|
|
198
|
+
};
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Caching
|
|
202
|
+
|
|
203
|
+
### Memory caching
|
|
204
|
+
Resources are automatically cached in memory per worker instance:
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
// Cached resource with custom handler
|
|
208
|
+
const cachedData = await swell.getCachedResource(
|
|
209
|
+
'expensive-operation',
|
|
210
|
+
[param1, param2],
|
|
211
|
+
async () => {
|
|
212
|
+
return await performExpensiveOperation(param1, param2);
|
|
213
|
+
}
|
|
214
|
+
);
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Cloudflare KV caching
|
|
218
|
+
For production scalability, enable KV caching:
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
const swell = new Swell({
|
|
222
|
+
serverHeaders: context.request.headers,
|
|
223
|
+
workerEnv: context.locals.runtime.env, // Contains THEME KV binding
|
|
224
|
+
workerCtx: context.locals.runtime.ctx, // Worker context
|
|
225
|
+
});
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Cache invalidation
|
|
229
|
+
Caches are automatically invalidated based on:
|
|
230
|
+
- Session cookies (for cart/account data)
|
|
231
|
+
- Theme configuration versions
|
|
232
|
+
- Storefront environment changes
|
|
233
|
+
|
|
234
|
+
## Shopify compatibility
|
|
235
|
+
|
|
236
|
+
The SDK includes comprehensive Shopify compatibility for theme migration.
|
|
237
|
+
|
|
238
|
+
### Supported Shopify features
|
|
239
|
+
- **Template mapping** - Direct file path compatibility
|
|
240
|
+
- **Liquid objects** - Full object structure compatibility
|
|
241
|
+
- **Form handling** - Compatible form endpoints and validation
|
|
242
|
+
- **Section schemas** - Shopify section configuration format
|
|
243
|
+
- **Settings data** - `settings_data.json` and `settings_schema.json`
|
|
244
|
+
|
|
245
|
+
## Liquid templating
|
|
246
|
+
|
|
247
|
+
Enhanced Liquid templating with Swell-specific features. See [Swell Liquid documentation](https://developers.swell.is/storefronts/swell-liquid-reference) for details.
|
|
248
|
+
|
|
249
|
+
## Performance optimization
|
|
250
|
+
|
|
251
|
+
### Lazy loading
|
|
252
|
+
Resources are loaded only when accessed in templates:
|
|
253
|
+
|
|
254
|
+
```liquid
|
|
255
|
+
<!-- Product data is fetched only when this line executes -->
|
|
256
|
+
{{ product.name }}
|
|
257
|
+
|
|
258
|
+
<!-- Collection is fetched only when iteration begins -->
|
|
259
|
+
{% for item in collection.products %}
|
|
260
|
+
{{ item.name }}
|
|
261
|
+
{% endfor %}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## Development
|
|
265
|
+
|
|
266
|
+
### Building the SDK
|
|
267
|
+
```bash
|
|
268
|
+
# Install dependencies
|
|
269
|
+
npm install
|
|
270
|
+
|
|
271
|
+
# Build for production
|
|
272
|
+
npm run build
|
|
273
|
+
|
|
274
|
+
# Watch for changes
|
|
275
|
+
npm run watch
|
|
276
|
+
|
|
277
|
+
# Run tests
|
|
278
|
+
npm test
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Project structure
|
|
282
|
+
```
|
|
283
|
+
src/
|
|
284
|
+
├── api.ts # Core Swell class and API handling
|
|
285
|
+
├── theme.ts # SwellTheme class and rendering
|
|
286
|
+
├── resources.ts # Storefront resource classes
|
|
287
|
+
├── liquid/ # Liquid templating engine
|
|
288
|
+
├── compatibility/ # Shopify compatibility layer
|
|
289
|
+
├── cache/ # Caching implementations
|
|
290
|
+
├── utils/ # Utility functions
|
|
291
|
+
└── index.ts # Main exports
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## Resources
|
|
295
|
+
|
|
296
|
+
- [Swell Documentation](https://developers.swell.is/)
|
|
297
|
+
- [Apps Development Guide](https://developers.swell.is/apps/overview)
|
|
298
|
+
- [Proxima Example App](https://developers.swell.is/storefronts/proxima)
|
|
299
|
+
- [Swell Liquid Reference](https://developers.swell.is/storefronts/swell-liquid-reference)
|
|
300
|
+
- [GitHub Repository](https://github.com/swellstores/swell-apps-sdk)
|
|
301
|
+
|
|
302
|
+
## 📄 License
|
|
303
|
+
|
|
304
|
+
See the [LICENSE](LICENSE) file for details.
|
package/dist/index.cjs
CHANGED
|
@@ -7536,6 +7536,16 @@ function transformSwellVariant(params, product, variant) {
|
|
|
7536
7536
|
}
|
|
7537
7537
|
|
|
7538
7538
|
// src/resources/product.ts
|
|
7539
|
+
var SORT_OPTIONS = [
|
|
7540
|
+
{ value: "", name: "Featured" },
|
|
7541
|
+
{ value: "popularity", name: "Popularity", query: "popularity desc" },
|
|
7542
|
+
{ value: "price_asc", name: "Price, low to high", query: "price asc" },
|
|
7543
|
+
{ value: "price_desc", name: "Price, high to low", query: "price desc" },
|
|
7544
|
+
{ value: "date_asc", name: "Date, old to new", query: "date asc" },
|
|
7545
|
+
{ value: "date_desc", name: "Date, new to old", query: "date desc" },
|
|
7546
|
+
{ value: "name_asc", name: "Product name, A-Z", query: "name asc" },
|
|
7547
|
+
{ value: "name_desc", name: "Product name, Z-A", query: "name desc" }
|
|
7548
|
+
];
|
|
7539
7549
|
function transformSwellProduct(params, product) {
|
|
7540
7550
|
if (!product) {
|
|
7541
7551
|
return product;
|
|
@@ -7572,6 +7582,28 @@ var SwellProduct = class extends SwellStorefrontRecord {
|
|
|
7572
7582
|
return res;
|
|
7573
7583
|
}
|
|
7574
7584
|
};
|
|
7585
|
+
function productQueryWithFilters(swell, query = {}) {
|
|
7586
|
+
const sortBy = swell.queryParams.sort || "";
|
|
7587
|
+
const filters2 = Object.entries(swell.queryParams).reduce(
|
|
7588
|
+
(acc, [key, value]) => {
|
|
7589
|
+
if (key.startsWith("filter_")) {
|
|
7590
|
+
const qkey = key.replace("filter_", "");
|
|
7591
|
+
if (value?.gte !== void 0 || value?.lte !== void 0) {
|
|
7592
|
+
acc[qkey] = [value.gte || 0, value.lte || void 0];
|
|
7593
|
+
} else {
|
|
7594
|
+
acc[qkey] = value;
|
|
7595
|
+
}
|
|
7596
|
+
}
|
|
7597
|
+
return acc;
|
|
7598
|
+
},
|
|
7599
|
+
{}
|
|
7600
|
+
);
|
|
7601
|
+
return {
|
|
7602
|
+
sort: SORT_OPTIONS.find((option) => option.value === sortBy)?.query || void 0,
|
|
7603
|
+
$filters: filters2,
|
|
7604
|
+
...query
|
|
7605
|
+
};
|
|
7606
|
+
}
|
|
7575
7607
|
|
|
7576
7608
|
// src/api.ts
|
|
7577
7609
|
var DEFAULT_API_HOST = "https://api.schema.io";
|
|
@@ -15012,9 +15044,11 @@ function ShopifyCollection(instance, category) {
|
|
|
15012
15044
|
if (category instanceof StorefrontResource) {
|
|
15013
15045
|
category = cloneStorefrontResource(category);
|
|
15014
15046
|
}
|
|
15047
|
+
const productMapper = (product) => ShopifyProduct(instance, product);
|
|
15015
15048
|
const resolveProducts = makeProductsCollectionResolve(
|
|
15049
|
+
instance,
|
|
15016
15050
|
category,
|
|
15017
|
-
|
|
15051
|
+
productMapper
|
|
15018
15052
|
);
|
|
15019
15053
|
return new ShopifyResource({
|
|
15020
15054
|
all_products_count: defer(
|
|
@@ -15066,8 +15100,9 @@ function ShopifyCollection(instance, category) {
|
|
|
15066
15100
|
category,
|
|
15067
15101
|
(category2) => getFirstImage(instance, category2)
|
|
15068
15102
|
),
|
|
15069
|
-
filters:
|
|
15070
|
-
|
|
15103
|
+
filters: deferWith(
|
|
15104
|
+
category,
|
|
15105
|
+
(category2) => (category2?.filter_options ?? []).map(
|
|
15071
15106
|
(filter) => ShopifyFilter(instance, filter)
|
|
15072
15107
|
)
|
|
15073
15108
|
),
|
|
@@ -15077,9 +15112,7 @@ function ShopifyCollection(instance, category) {
|
|
|
15077
15112
|
metafields: {},
|
|
15078
15113
|
next_product: void 0,
|
|
15079
15114
|
previous_product: void 0,
|
|
15080
|
-
products:
|
|
15081
|
-
return (await resolveProducts())?.results ?? [];
|
|
15082
|
-
}),
|
|
15115
|
+
products: getProducts(instance, category, productMapper),
|
|
15083
15116
|
products_count: defer(
|
|
15084
15117
|
async () => (await resolveProducts())?.results?.length || 0
|
|
15085
15118
|
),
|
|
@@ -15118,28 +15151,35 @@ function convertToShopifySorting(value) {
|
|
|
15118
15151
|
return "manual";
|
|
15119
15152
|
}
|
|
15120
15153
|
}
|
|
15121
|
-
function
|
|
15122
|
-
|
|
15123
|
-
|
|
15124
|
-
|
|
15125
|
-
|
|
15126
|
-
|
|
15127
|
-
|
|
15128
|
-
|
|
15129
|
-
|
|
15130
|
-
|
|
15154
|
+
function getProducts(instance, object, mapper) {
|
|
15155
|
+
return deferWith(object, (object2) => {
|
|
15156
|
+
const { page, limit: limit2 } = instance.swell.queryParams;
|
|
15157
|
+
const categoryFilter = object2.id && object2.id !== "all" ? object2.id : void 0;
|
|
15158
|
+
const productQuery = categoryFilter ? { category: categoryFilter, $variants: true } : { $variants: true };
|
|
15159
|
+
const filterQuery = productQueryWithFilters(instance.swell, productQuery);
|
|
15160
|
+
const products = new SwellStorefrontCollection(
|
|
15161
|
+
instance.swell,
|
|
15162
|
+
"products",
|
|
15163
|
+
{
|
|
15164
|
+
page,
|
|
15165
|
+
limit: limit2,
|
|
15166
|
+
...filterQuery
|
|
15167
|
+
},
|
|
15168
|
+
async function() {
|
|
15169
|
+
return this._defaultGetter().call(this);
|
|
15131
15170
|
}
|
|
15132
|
-
|
|
15133
|
-
|
|
15134
|
-
|
|
15135
|
-
|
|
15136
|
-
};
|
|
15171
|
+
);
|
|
15172
|
+
return products._cloneWithCompatibilityResult(
|
|
15173
|
+
(products2) => {
|
|
15174
|
+
return { ...products2, results: products2.results.map(mapper) };
|
|
15137
15175
|
}
|
|
15138
|
-
|
|
15139
|
-
return null;
|
|
15176
|
+
);
|
|
15140
15177
|
});
|
|
15178
|
+
}
|
|
15179
|
+
function makeProductsCollectionResolve(instance, object, mapper) {
|
|
15180
|
+
const products = getProducts(instance, object, mapper);
|
|
15141
15181
|
async function resolveProducts() {
|
|
15142
|
-
const resolved = await
|
|
15182
|
+
const resolved = await products.resolve();
|
|
15143
15183
|
if (resolved && "_resolve" in resolved) {
|
|
15144
15184
|
return resolved._resolve();
|
|
15145
15185
|
}
|
|
@@ -15903,11 +15943,15 @@ function ShopifySearch(instance, search) {
|
|
|
15903
15943
|
if (search instanceof ShopifyResource) {
|
|
15904
15944
|
return search.clone();
|
|
15905
15945
|
}
|
|
15906
|
-
const resolveProducts = makeProductsCollectionResolve(
|
|
15907
|
-
|
|
15908
|
-
|
|
15909
|
-
|
|
15910
|
-
|
|
15946
|
+
const resolveProducts = makeProductsCollectionResolve(
|
|
15947
|
+
instance,
|
|
15948
|
+
search,
|
|
15949
|
+
(product) => {
|
|
15950
|
+
const shopifyProduct = ShopifyProduct(instance, product);
|
|
15951
|
+
shopifyProduct.object_type = "product";
|
|
15952
|
+
return shopifyProduct;
|
|
15953
|
+
}
|
|
15954
|
+
);
|
|
15911
15955
|
return new ShopifyResource({
|
|
15912
15956
|
default_sort_by: deferWith(
|
|
15913
15957
|
search,
|