@swell/apps-sdk 1.0.127 → 1.0.129

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -67,6 +67,7 @@ __export(index_exports, {
67
67
  Swell: () => Swell,
68
68
  SwellBackendAPI: () => SwellBackendAPI,
69
69
  SwellError: () => SwellError,
70
+ SwellProduct: () => SwellProduct,
70
71
  SwellStorefrontCollection: () => SwellStorefrontCollection,
71
72
  SwellStorefrontPagination: () => SwellStorefrontPagination,
72
73
  SwellStorefrontRecord: () => SwellStorefrontRecord,
@@ -93,9 +94,6 @@ __export(index_exports, {
93
94
  getAllSections: () => getAllSections,
94
95
  getBlog: () => getBlog,
95
96
  getBlogs: () => getBlogs,
96
- getCategories: () => getCategories,
97
- getCategory: () => getCategory,
98
- getCategoryWithProducts: () => getCategoryWithProducts,
99
97
  getContentEntry: () => getContentEntry,
100
98
  getContentList: () => getContentList,
101
99
  getContentModel: () => getContentModel,
@@ -112,9 +110,6 @@ __export(index_exports, {
112
110
  getMenuItemValueId: () => getMenuItemValueId,
113
111
  getPage: () => getPage,
114
112
  getPageSections: () => getPageSections,
115
- getProduct: () => getProduct,
116
- getProducts: () => getProducts,
117
- getProductsFiltered: () => getProductsFiltered,
118
113
  getSectionGroupProp: () => getSectionGroupProp,
119
114
  getSectionSettingsFromProps: () => getSectionSettingsFromProps,
120
115
  getThemeSettingsFromProps: () => getThemeSettingsFromProps,
@@ -193,10 +188,151 @@ var import_lodash_es3 = require("lodash-es");
193
188
  var import_json52 = __toESM(require("json5"), 1);
194
189
 
195
190
  // src/resources.ts
196
- var import_lodash_es = require("lodash-es");
191
+ var import_lodash_es2 = require("lodash-es");
197
192
 
198
193
  // src/liquid/utils.ts
199
194
  var import_liquidjs = require("liquidjs");
195
+
196
+ // src/compatibility/shopify-objects/resource.ts
197
+ var import_lodash_es = require("lodash-es");
198
+ var ShopifyResource = class _ShopifyResource {
199
+ props;
200
+ stringProp;
201
+ linkProps;
202
+ constructor(props, stringProp, linkProps) {
203
+ this.props = props;
204
+ this.stringProp = stringProp;
205
+ this.linkProps = linkProps;
206
+ return new Proxy(props, {
207
+ get(target, prop, receiver) {
208
+ const instance = target;
209
+ switch (prop) {
210
+ case "toJSON":
211
+ return props;
212
+ case "clone":
213
+ return () => {
214
+ return new _ShopifyResource(
215
+ (0, import_lodash_es.cloneDeep)(props),
216
+ (0, import_lodash_es.cloneDeep)(stringProp),
217
+ (0, import_lodash_es.cloneDeep)(linkProps)
218
+ );
219
+ };
220
+ case "toString": {
221
+ if (stringProp) {
222
+ return () => {
223
+ return props[stringProp];
224
+ };
225
+ }
226
+ break;
227
+ }
228
+ case Symbol.toPrimitive: {
229
+ return () => {
230
+ let prop2 = stringProp;
231
+ if (typeof prop2 === "number") {
232
+ prop2 = prop2.toString();
233
+ }
234
+ return this.get?.(instance, prop2 || "handle", receiver);
235
+ };
236
+ }
237
+ default:
238
+ break;
239
+ }
240
+ const value = instance[prop];
241
+ if (value instanceof DeferredShopifyResource) {
242
+ const promise = value.resolve().then(
243
+ (value2) => {
244
+ instance[prop] = value2;
245
+ return value2;
246
+ },
247
+ (err) => {
248
+ console.log(err);
249
+ instance[prop] = null;
250
+ return null;
251
+ }
252
+ );
253
+ instance[prop] = promise;
254
+ return promise;
255
+ }
256
+ return value;
257
+ },
258
+ getPrototypeOf() {
259
+ return _ShopifyResource.prototype;
260
+ }
261
+ });
262
+ }
263
+ valueOf() {
264
+ if (this.stringProp) {
265
+ return this.props[this.stringProp];
266
+ }
267
+ return this;
268
+ }
269
+ // For typescript
270
+ clone() {
271
+ return new _ShopifyResource(this.props);
272
+ }
273
+ };
274
+ var DeferredShopifyResource = class {
275
+ handler;
276
+ result;
277
+ constructor(handler) {
278
+ this.result = void 0;
279
+ this.handler = handler;
280
+ }
281
+ async resolve() {
282
+ if (this.handler !== import_lodash_es.noop) {
283
+ const handler = this.handler;
284
+ this.handler = import_lodash_es.noop;
285
+ this.result = Promise.resolve().then(handler).then((value) => {
286
+ this.result = value;
287
+ return value;
288
+ });
289
+ }
290
+ return this.result;
291
+ }
292
+ };
293
+ function defer(handler) {
294
+ return new DeferredShopifyResource(handler);
295
+ }
296
+ function isResolvable(asyncProp) {
297
+ return isObject(asyncProp) && (isLikePromise(asyncProp) || typeof asyncProp._resolve === "function");
298
+ }
299
+ function isStorefrontResource(resource) {
300
+ return isObject(resource) && typeof resource._resolve === "function";
301
+ }
302
+ async function resolveAsyncProp(asyncProp) {
303
+ if (Array.isArray(asyncProp)) {
304
+ return Promise.all(
305
+ asyncProp.map(
306
+ (prop) => isStorefrontResource(prop) ? prop._resolve() : prop
307
+ )
308
+ );
309
+ }
310
+ if (isStorefrontResource(asyncProp)) {
311
+ return asyncProp._resolve();
312
+ }
313
+ return asyncProp;
314
+ }
315
+ function handleDeferredProp(asyncProp, handler) {
316
+ return resolveAsyncProp(asyncProp).then((value) => {
317
+ if (Array.isArray(asyncProp) && Array.isArray(value)) {
318
+ return handler(...value.map((prop) => prop || {}));
319
+ }
320
+ if (isResolvable(value)) {
321
+ return handleDeferredProp(value, handler);
322
+ }
323
+ return handler(value || {});
324
+ }).catch((err) => {
325
+ console.log(err);
326
+ return null;
327
+ });
328
+ }
329
+ function deferWith(asyncProp, handler) {
330
+ return new DeferredShopifyResource(
331
+ () => handleDeferredProp(asyncProp, handler)
332
+ );
333
+ }
334
+
335
+ // src/liquid/utils.ts
200
336
  var ForloopDrop = class extends import_liquidjs.Drop {
201
337
  i;
202
338
  length;
@@ -363,18 +499,24 @@ async function jsonStringifyAsync(input, space = 0) {
363
499
  async function resolveAllKeys(value, references = /* @__PURE__ */ new WeakSet()) {
364
500
  await forEachKeyDeep(value, async (key, value2) => {
365
501
  if (!isObject(value2)) {
366
- return;
502
+ return true;
367
503
  }
368
504
  const val = value2[key];
369
505
  if (isLikePromise(val)) {
370
506
  value2[key] = await val;
371
507
  await resolveAllKeys(value2[key], references);
372
508
  } else if (isObject(val)) {
509
+ if (val instanceof DeferredShopifyResource) {
510
+ value2[key] = await val.resolve();
511
+ await resolveAllKeys(value2[key], references);
512
+ return true;
513
+ }
373
514
  if (references.has(val)) {
374
515
  return false;
375
516
  }
376
517
  references.add(val);
377
518
  }
519
+ return true;
378
520
  });
379
521
  }
380
522
  async function forEachKeyDeep(obj, fn) {
@@ -492,12 +634,18 @@ var StorefrontResource = class {
492
634
  }
493
635
  return instance[prop];
494
636
  }
637
+ // add additional properties to the loaded result
638
+ _transformResult(result) {
639
+ return result;
640
+ }
495
641
  async _get(..._args) {
496
642
  if (this._getter) {
497
643
  const getter = this._getter.bind(
498
644
  this
499
645
  );
500
646
  return Promise.resolve().then(getter).then((result) => {
647
+ return this._transformResult(result);
648
+ }).then((result) => {
501
649
  this._result = result;
502
650
  if (result) {
503
651
  Object.assign(this, result);
@@ -573,6 +721,8 @@ var StorefrontResource = class {
573
721
  function cloneStorefrontResource(input) {
574
722
  const resourceName = input._resourceName;
575
723
  const clone = new StorefrontResource(input._getter);
724
+ clone._params = input._params;
725
+ clone._transformResult = input._transformResult.bind(clone);
576
726
  Object.defineProperty(clone.constructor, "name", {
577
727
  value: resourceName
578
728
  });
@@ -700,7 +850,7 @@ var SwellStorefrontCollection = class _SwellStorefrontCollection extends SwellSt
700
850
  this._getter
701
851
  );
702
852
  if (this._isResultResolved()) {
703
- cloned._result = (0, import_lodash_es.cloneDeep)(this._result);
853
+ cloned._result = (0, import_lodash_es2.cloneDeep)(this._result);
704
854
  }
705
855
  if (this._compatibilityProps) {
706
856
  cloned.setCompatibilityProps(this._compatibilityProps);
@@ -729,7 +879,7 @@ var SwellStorefrontCollection = class _SwellStorefrontCollection extends SwellSt
729
879
  }
730
880
  });
731
881
  if (this._isResultResolved()) {
732
- const result = (0, import_lodash_es.cloneDeep)(this._result);
882
+ const result = (0, import_lodash_es2.cloneDeep)(this._result);
733
883
  if (result) {
734
884
  const compatibilityProps = compatibilityGetter(result);
735
885
  Object.assign(cloned, result);
@@ -743,10 +893,12 @@ var SwellStorefrontCollection = class _SwellStorefrontCollection extends SwellSt
743
893
  };
744
894
  var SwellStorefrontRecord = class extends SwellStorefrontResource {
745
895
  _id;
896
+ _params;
746
897
  constructor(swell, collection, id, query = {}, getter) {
747
898
  super(swell, collection, getter);
748
899
  this._id = id;
749
900
  this._query = query;
901
+ this._params = {};
750
902
  if (!getter) {
751
903
  this._setGetter(this._defaultGetter());
752
904
  }
@@ -784,6 +936,8 @@ var SwellStorefrontRecord = class extends SwellStorefrontResource {
784
936
  ],
785
937
  getter
786
938
  ).then((result) => {
939
+ return this._transformResult(result);
940
+ }).then((result) => {
787
941
  this._result = result;
788
942
  if (result) {
789
943
  Object.assign(this, result);
@@ -893,145 +1047,6 @@ var SwellStorefrontPagination = class {
893
1047
  }
894
1048
  };
895
1049
 
896
- // src/compatibility/shopify-objects/resource.ts
897
- var import_lodash_es2 = require("lodash-es");
898
- var ShopifyResource = class _ShopifyResource {
899
- props;
900
- stringProp;
901
- linkProps;
902
- constructor(props, stringProp, linkProps) {
903
- this.props = props;
904
- this.stringProp = stringProp;
905
- this.linkProps = linkProps;
906
- return new Proxy(props, {
907
- get(target, prop, receiver) {
908
- const instance = target;
909
- switch (prop) {
910
- case "toJSON":
911
- return props;
912
- case "clone":
913
- return () => {
914
- return new _ShopifyResource(
915
- (0, import_lodash_es2.cloneDeep)(props),
916
- (0, import_lodash_es2.cloneDeep)(stringProp),
917
- (0, import_lodash_es2.cloneDeep)(linkProps)
918
- );
919
- };
920
- case "toString": {
921
- if (stringProp) {
922
- return () => {
923
- return props[stringProp];
924
- };
925
- }
926
- break;
927
- }
928
- case Symbol.toPrimitive: {
929
- return () => {
930
- let prop2 = stringProp;
931
- if (typeof prop2 === "number") {
932
- prop2 = prop2.toString();
933
- }
934
- return this.get?.(instance, prop2 || "handle", receiver);
935
- };
936
- }
937
- default:
938
- break;
939
- }
940
- const value = instance[prop];
941
- if (value instanceof DeferredShopifyResource) {
942
- const promise = value.resolve().then(
943
- (value2) => {
944
- instance[prop] = value2;
945
- return value2;
946
- },
947
- (err) => {
948
- console.log(err);
949
- instance[prop] = null;
950
- return null;
951
- }
952
- );
953
- instance[prop] = promise;
954
- return promise;
955
- }
956
- return value;
957
- },
958
- getPrototypeOf() {
959
- return _ShopifyResource.prototype;
960
- }
961
- });
962
- }
963
- valueOf() {
964
- if (this.stringProp) {
965
- return this.props[this.stringProp];
966
- }
967
- return this;
968
- }
969
- // For typescript
970
- clone() {
971
- return new _ShopifyResource(this.props);
972
- }
973
- };
974
- var DeferredShopifyResource = class {
975
- handler;
976
- result;
977
- constructor(handler) {
978
- this.result = void 0;
979
- this.handler = handler;
980
- }
981
- async resolve() {
982
- if (this.handler !== import_lodash_es2.noop) {
983
- const handler = this.handler;
984
- this.handler = import_lodash_es2.noop;
985
- this.result = Promise.resolve().then(handler).then((value) => {
986
- this.result = value;
987
- return value;
988
- });
989
- }
990
- return this.result;
991
- }
992
- };
993
- function defer(handler) {
994
- return new DeferredShopifyResource(handler);
995
- }
996
- function isResolvable(asyncProp) {
997
- return isObject(asyncProp) && (isLikePromise(asyncProp) || typeof asyncProp._resolve === "function");
998
- }
999
- function isStorefrontResource(resource) {
1000
- return isObject(resource) && typeof resource._resolve === "function";
1001
- }
1002
- async function resolveAsyncProp(asyncProp) {
1003
- if (Array.isArray(asyncProp)) {
1004
- return Promise.all(
1005
- asyncProp.map(
1006
- (prop) => isStorefrontResource(prop) ? prop._resolve() : prop
1007
- )
1008
- );
1009
- }
1010
- if (isStorefrontResource(asyncProp)) {
1011
- return asyncProp._resolve();
1012
- }
1013
- return asyncProp;
1014
- }
1015
- function handleDeferredProp(asyncProp, handler) {
1016
- return resolveAsyncProp(asyncProp).then((value) => {
1017
- if (Array.isArray(asyncProp) && Array.isArray(value)) {
1018
- return handler(...value.map((prop) => prop || {}));
1019
- }
1020
- if (isResolvable(value)) {
1021
- return handleDeferredProp(value, handler);
1022
- }
1023
- return handler(value || {});
1024
- }).catch((err) => {
1025
- console.log(err);
1026
- return null;
1027
- });
1028
- }
1029
- function deferWith(asyncProp, handler) {
1030
- return new DeferredShopifyResource(
1031
- () => handleDeferredProp(asyncProp, handler)
1032
- );
1033
- }
1034
-
1035
1050
  // src/constants.ts
1036
1051
  var FILE_DATA_INCLUDE_QUERY = {
1037
1052
  url: "/:themes:configs/{id}/file/data",
@@ -7116,50 +7131,213 @@ function buildStores(kvStore) {
7116
7131
  store: new CFWorkerKVKeyvAdapter(kvStore)
7117
7132
  })
7118
7133
  );
7119
- } else {
7120
- stores.push(new import_keyv.Keyv());
7134
+ } else {
7135
+ stores.push(new import_keyv.Keyv());
7136
+ }
7137
+ return stores;
7138
+ }
7139
+
7140
+ // src/cache/request-cache.ts
7141
+ var RequestCache = class extends Cache {
7142
+ constructor(options) {
7143
+ super({
7144
+ ...options
7145
+ });
7146
+ }
7147
+ };
7148
+
7149
+ // src/cache/resource-cache.ts
7150
+ var import_keyv2 = require("keyv");
7151
+ var ResourceCache = class extends Cache {
7152
+ constructor(options) {
7153
+ super({
7154
+ stores: buildStores2(),
7155
+ ...options
7156
+ });
7157
+ }
7158
+ };
7159
+ function buildStores2() {
7160
+ return [
7161
+ new import_keyv2.Keyv({
7162
+ // Disabling serialization allows for pure memo-ization of class instances
7163
+ // at the tradeoff of no support for compression.
7164
+ serialize: void 0,
7165
+ deserialize: void 0
7166
+ })
7167
+ ];
7168
+ }
7169
+
7170
+ // src/cache/theme-cache.ts
7171
+ var TTL = 90 * 24 * 60 * 60 * 1e3;
7172
+ var ThemeCache = class extends Cache {
7173
+ constructor(options) {
7174
+ super({
7175
+ ttl: TTL,
7176
+ ...options
7177
+ });
7178
+ }
7179
+ };
7180
+
7181
+ // src/resources/product_helpers.ts
7182
+ function calculateAddOptionsPrice(product, queryParams) {
7183
+ const { option_values = "" } = queryParams;
7184
+ const queryOptionValues = option_values;
7185
+ const optionValues = queryOptionValues.split(",");
7186
+ const addPrice = product.options?.reduce((acc, option) => {
7187
+ if (!option.active || !option.values || option.values.length <= 0) {
7188
+ return acc;
7189
+ }
7190
+ if (option.input_type !== "select") {
7191
+ return acc;
7192
+ }
7193
+ for (const value of option.values) {
7194
+ if (optionValues.includes(value.id)) {
7195
+ return acc + (value.price || 0);
7196
+ }
7197
+ }
7198
+ return acc + (option.values[0].price || 0);
7199
+ }, 0);
7200
+ return product.price + (addPrice || 0);
7201
+ }
7202
+ function calculateAddOptionsVariantPrice(product, variant, queryParams) {
7203
+ const { option_values = "" } = queryParams;
7204
+ const queryOptionValues = option_values;
7205
+ const optionValues = queryOptionValues.split(",");
7206
+ const addPrice = product.options?.reduce((acc, option) => {
7207
+ if (option.variant || // skip variant options
7208
+ !option.active || !option.values || option.values.length <= 0) {
7209
+ return acc;
7210
+ }
7211
+ if (option.input_type !== "select") {
7212
+ return acc;
7213
+ }
7214
+ for (const value of option.values) {
7215
+ if (optionValues.includes(value.id)) {
7216
+ return acc + (value.price || 0);
7217
+ }
7218
+ }
7219
+ return acc + (option.values[0].price || 0);
7220
+ }, 0);
7221
+ let price = product.price;
7222
+ if (variant.price !== null && variant.price !== void 0) {
7223
+ price = variant.price;
7224
+ }
7225
+ return price + (addPrice || 0);
7226
+ }
7227
+ function getAvailableVariants(product) {
7228
+ return (product.variants?.results?.slice()?.reverse() || []).filter(
7229
+ (variant) => variant.stock_status === "in_stock" || !variant.stock_status
7230
+ );
7231
+ }
7232
+ function getSelectedSwellVariant(product, queryParams) {
7233
+ const { variant: queryVariant, option_values } = queryParams;
7234
+ const queryOptionValues = option_values;
7235
+ const variants = getAvailableVariants(product);
7236
+ let selectedVariant = void 0;
7237
+ if (queryVariant) {
7238
+ selectedVariant = variants.find((variant) => variant.id === queryVariant);
7239
+ } else if (queryOptionValues) {
7240
+ const optionValues = queryOptionValues.split(",");
7241
+ selectedVariant = variants.find(
7242
+ (variant) => variant.option_value_ids.every(
7243
+ (optionValueId) => optionValues.includes(optionValueId)
7244
+ )
7245
+ );
7121
7246
  }
7122
- return stores;
7247
+ return selectedVariant || variants?.[0] || void 0;
7123
7248
  }
7124
-
7125
- // src/cache/request-cache.ts
7126
- var RequestCache = class extends Cache {
7127
- constructor(options) {
7128
- super({
7129
- ...options
7130
- });
7249
+ function getSelectedVariant(product, queryParams) {
7250
+ return getSelectedSwellVariant(
7251
+ product,
7252
+ queryParams
7253
+ );
7254
+ }
7255
+ function getSelectedOptionValues(product, queryParams) {
7256
+ const variant = getSelectedSwellVariant(product, queryParams);
7257
+ return getSelectedVariantOptionValues(product, variant, queryParams);
7258
+ }
7259
+ function getSelectedVariantOptionValues(product, variant, queryParams) {
7260
+ const { option_values = "" } = queryParams;
7261
+ const queryOptionValues = option_values;
7262
+ const optionValues = queryOptionValues.split(",");
7263
+ const selectedValues = variant ? [...variant.option_value_ids || []] : [];
7264
+ const values = [];
7265
+ for (const option of product.options || []) {
7266
+ if (option.active && option.values && option.values.length > 0 && option.input_type === "select") {
7267
+ let selectedByVariantId = "";
7268
+ let selectedByOptionId = "";
7269
+ for (const value of option.values) {
7270
+ if (selectedValues.includes(value.id)) {
7271
+ selectedByVariantId = value.id;
7272
+ break;
7273
+ }
7274
+ if (optionValues.includes(value.id)) {
7275
+ selectedByOptionId = value.id;
7276
+ }
7277
+ }
7278
+ values.push(
7279
+ selectedByVariantId || selectedByOptionId || option.values[0].id
7280
+ );
7281
+ }
7131
7282
  }
7132
- };
7283
+ return values;
7284
+ }
7133
7285
 
7134
- // src/cache/resource-cache.ts
7135
- var import_keyv2 = require("keyv");
7136
- var ResourceCache = class extends Cache {
7137
- constructor(options) {
7138
- super({
7139
- stores: buildStores2(),
7140
- ...options
7141
- });
7286
+ // src/resources/variant.ts
7287
+ function transformSwellVariant(params, product, variant) {
7288
+ if (!product) {
7289
+ return product;
7142
7290
  }
7143
- };
7144
- function buildStores2() {
7145
- return [
7146
- new import_keyv2.Keyv({
7147
- // Disabling serialization allows for pure memo-ization of class instances
7148
- // at the tradeoff of no support for compression.
7149
- serialize: void 0,
7150
- deserialize: void 0
7151
- })
7152
- ];
7291
+ if (!variant) {
7292
+ return variant;
7293
+ }
7294
+ return {
7295
+ ...variant,
7296
+ // add swell properties there
7297
+ price: calculateAddOptionsVariantPrice(product, variant, params),
7298
+ selected_option_values: getSelectedVariantOptionValues(
7299
+ product,
7300
+ variant,
7301
+ params
7302
+ )
7303
+ };
7153
7304
  }
7154
7305
 
7155
- // src/cache/theme-cache.ts
7156
- var TTL = 90 * 24 * 60 * 60 * 1e3;
7157
- var ThemeCache = class extends Cache {
7158
- constructor(options) {
7159
- super({
7160
- ttl: TTL,
7161
- ...options
7162
- });
7306
+ // src/resources/product.ts
7307
+ function transformSwellProduct(params, product) {
7308
+ if (!product) {
7309
+ return product;
7310
+ }
7311
+ const newProduct = {
7312
+ ...product,
7313
+ // add swell properties there
7314
+ price: calculateAddOptionsPrice(product, params),
7315
+ selected_option_values: getSelectedOptionValues(product, params)
7316
+ };
7317
+ if (Array.isArray(newProduct.variants?.results)) {
7318
+ newProduct.variants = {
7319
+ ...newProduct.variants,
7320
+ results: newProduct.variants.results.map(
7321
+ (variant) => transformSwellVariant(params, product, variant)
7322
+ )
7323
+ };
7324
+ }
7325
+ return newProduct;
7326
+ }
7327
+ var SwellProduct = class extends SwellStorefrontRecord {
7328
+ _params;
7329
+ constructor(swell, id, query = {}, getter) {
7330
+ super(swell, "products", id, query, getter);
7331
+ this._params = swell.queryParams;
7332
+ return this._getProxy();
7333
+ }
7334
+ // add swell properties to the resolved object
7335
+ _transformResult(result) {
7336
+ const res = transformSwellProduct(
7337
+ this._params,
7338
+ result
7339
+ );
7340
+ return res;
7163
7341
  }
7164
7342
  };
7165
7343
 
@@ -7598,39 +7776,6 @@ ${formattedMessage}`;
7598
7776
  }
7599
7777
  };
7600
7778
 
7601
- // src/products.ts
7602
- function getProducts(swell, query) {
7603
- return new SwellStorefrontCollection(swell, "products", query);
7604
- }
7605
- function getProduct(swell, id, query) {
7606
- return new SwellStorefrontRecord(swell, "products", id, query);
7607
- }
7608
- function getProductsFiltered(swell, {
7609
- search,
7610
- filter,
7611
- sort
7612
- }) {
7613
- return new SwellStorefrontCollection(swell, "products", {
7614
- search,
7615
- filter,
7616
- sort
7617
- });
7618
- }
7619
-
7620
- // src/categories.ts
7621
- function getCategories(swell, query) {
7622
- return new SwellStorefrontCollection(swell, "categories", query);
7623
- }
7624
- function getCategory(swell, id, query) {
7625
- return new SwellStorefrontRecord(swell, "categories", id, query);
7626
- }
7627
- async function getCategoryWithProducts(swell, id, query) {
7628
- const category = getCategory(swell, id, query);
7629
- const categoryId = await category.id;
7630
- category.products = getProducts(swell, { category: categoryId });
7631
- return category;
7632
- }
7633
-
7634
7779
  // src/content.ts
7635
7780
  function getContentModel(swell, name) {
7636
7781
  return swell.getCachedResource(
@@ -13741,6 +13886,9 @@ function ShopifyArticle(instance, blog, blogCategory) {
13741
13886
  "moderated?": false
13742
13887
  });
13743
13888
  }
13889
+ function isLikeShopifyArticle(value) {
13890
+ return typeof value === "object" && value !== null && Object.hasOwn(value, "title") && Object.hasOwn(value, "content") && Object.hasOwn(value, "comments") && Object.hasOwn(value, "moderated?") && Object.hasOwn(value, "published_at") && Object.hasOwn(value, "excerpt_or_content");
13891
+ }
13744
13892
 
13745
13893
  // src/compatibility/shopify-objects/blog.ts
13746
13894
  function ShopifyBlog(instance, blogCategory) {
@@ -13820,11 +13968,15 @@ function ShopifyVariant(instance, variant, productIn, depth = 0) {
13820
13968
  if (variant instanceof ShopifyResource) {
13821
13969
  return variant.clone();
13822
13970
  }
13971
+ let swellVariant = {};
13823
13972
  if (variant instanceof StorefrontResource) {
13824
13973
  variant = cloneStorefrontResource(variant);
13974
+ } else {
13975
+ swellVariant = { ...variant };
13825
13976
  }
13826
13977
  const product = productIn || variant.product || {};
13827
13978
  return new ShopifyResource({
13979
+ ...swellVariant,
13828
13980
  available: deferWith(
13829
13981
  variant,
13830
13982
  (variant2) => Boolean(variant2.stock_status === "in_stock" || !variant2.stock_status)
@@ -13870,25 +14022,19 @@ function ShopifyVariant(instance, variant, productIn, depth = 0) {
13870
14022
  metafields: {},
13871
14023
  next_incoming_date: void 0,
13872
14024
  options: getOptions(product, variant),
13873
- // @ts-expect-error: move this to swell product class
13874
- selected_option_values: deferWith(
13875
- [product, variant],
13876
- (product2, variant2) => getSelectedVariantOptionValues(
13877
- product2,
13878
- variant2,
13879
- instance.swell.queryParams
13880
- )
13881
- ),
13882
14025
  option1: getOptionByIndex(product, variant, 0),
13883
14026
  // Deprecated by Shopify
13884
14027
  option2: getOptionByIndex(product, variant, 1),
13885
14028
  // Deprecated by Shopify
13886
14029
  option3: getOptionByIndex(product, variant, 2),
13887
14030
  // Deprecated by Shopify
13888
- price: deferWith(
13889
- [product, variant],
13890
- (product2, variant2) => getVariantPrice(product2, variant2, instance.swell.queryParams)
13891
- ),
14031
+ price: deferWith([product, variant], (product2, variant2) => {
14032
+ let price = product2.price;
14033
+ if (variant2.price !== null && variant2.price !== void 0) {
14034
+ price = variant2.price;
14035
+ }
14036
+ return price;
14037
+ }),
13892
14038
  product: deferWith(product, (product2) => {
13893
14039
  return ShopifyProduct(
13894
14040
  instance,
@@ -13975,30 +14121,6 @@ function getOptionByIndex(product, variant, index) {
13975
14121
  }
13976
14122
  );
13977
14123
  }
13978
- function getVariantPrice(product, variant, queryParams) {
13979
- const { option_values: queryOptionValues = "" } = queryParams;
13980
- const optionValues = queryOptionValues.split(",");
13981
- const addPrice = product.options?.reduce((acc, option) => {
13982
- if (option.variant || // skip variant options
13983
- !option.active || !option.values || option.values.length <= 0) {
13984
- return acc;
13985
- }
13986
- if (option.input_type !== "select") {
13987
- return acc;
13988
- }
13989
- for (const value of option.values) {
13990
- if (optionValues.includes(value.id)) {
13991
- return acc + (value.price || 0);
13992
- }
13993
- }
13994
- return acc + (option.values[0].price || 0);
13995
- }, 0);
13996
- let price = product.price;
13997
- if (variant.price !== null && variant.price !== void 0) {
13998
- price = variant.price;
13999
- }
14000
- return price + (addPrice || 0);
14001
- }
14002
14124
 
14003
14125
  // src/compatibility/shopify-objects/product.ts
14004
14126
  function ShopifyProduct(instance, product, depth = 0) {
@@ -14038,7 +14160,7 @@ function ShopifyProduct(instance, product, depth = 0) {
14038
14160
  // not used
14039
14161
  first_available_variant: deferWith(product, (product2) => {
14040
14162
  const variant = getSelectedVariant(product2, {});
14041
- return ShopifyVariant(instance, variant || product2, product2, depth + 1);
14163
+ return variant ? ShopifyVariant(instance, variant, product2, depth + 1) : void 0;
14042
14164
  }),
14043
14165
  "gift_card?": deferWith(product, (product2) => product2.type === "giftcard"),
14044
14166
  handle: defer(() => product.slug),
@@ -14074,12 +14196,6 @@ function ShopifyProduct(instance, product, depth = 0) {
14074
14196
  }
14075
14197
  return product2.options.filter((option) => option.active && option.name).map((option) => option.name);
14076
14198
  }),
14077
- // all options values including non-variant
14078
- // @ts-expect-error: move this to swell product class
14079
- selected_option_values: deferWith(
14080
- product,
14081
- (product2) => getSelectedOptionValues(product2, instance.swell.queryParams)
14082
- ),
14083
14199
  options_by_name: deferWith(product, (product2) => {
14084
14200
  if (!Array.isArray(product2.options)) {
14085
14201
  return {};
@@ -14147,30 +14263,33 @@ function ShopifyProduct(instance, product, depth = 0) {
14147
14263
  });
14148
14264
  }
14149
14265
  ),
14150
- price: deferWith(
14151
- product,
14152
- (product2) => calculateAddOptionsPrice(product2, instance.swell.queryParams)
14153
- ),
14154
- price_max: deferWith(
14155
- product,
14156
- (product2) => product2.variants?.results?.reduce(
14266
+ price: deferWith(product, (product2) => product2.price),
14267
+ price_max: deferWith(product, (product2) => {
14268
+ if (!Array.isArray(product2.variants?.results)) {
14269
+ return product2.price;
14270
+ }
14271
+ return product2.variants.results.reduce(
14157
14272
  (max, variant) => Math.max(max, variant.price),
14158
14273
  0
14159
- )
14160
- ),
14161
- price_min: deferWith(
14162
- product,
14163
- (product2) => product2.variants?.results?.reduce(
14274
+ );
14275
+ }),
14276
+ price_min: deferWith(product, (product2) => {
14277
+ if (!Array.isArray(product2.variants?.results)) {
14278
+ return product2.price;
14279
+ }
14280
+ return product2.variants.results.reduce(
14164
14281
  (min, variant) => Math.min(min, variant.price),
14165
14282
  Infinity
14166
- )
14167
- ),
14168
- price_varies: deferWith(
14169
- product,
14170
- (product2) => product2.variants?.results?.some(
14283
+ );
14284
+ }),
14285
+ price_varies: deferWith(product, (product2) => {
14286
+ if (!Array.isArray(product2.variants?.results)) {
14287
+ return false;
14288
+ }
14289
+ return product2.variants.results.some(
14171
14290
  (variant) => variant.price !== product2.price
14172
- )
14173
- ),
14291
+ );
14292
+ }),
14174
14293
  published_at: deferWith(
14175
14294
  product,
14176
14295
  (product2) => product2.date_updated || product2.date_created
@@ -14179,6 +14298,8 @@ function ShopifyProduct(instance, product, depth = 0) {
14179
14298
  product,
14180
14299
  (product2) => product2.prices?.length > 0
14181
14300
  ),
14301
+ // ShopifyProduct does not have this property
14302
+ // @ts-expect-error property
14182
14303
  quantity_rule: deferWith(product, (product2) => {
14183
14304
  let inventory = product2.stock_level || 0;
14184
14305
  if (inventory < 0) {
@@ -14206,11 +14327,8 @@ function ShopifyProduct(instance, product, depth = 0) {
14206
14327
  selected_or_first_available_variant: deferWith(
14207
14328
  product,
14208
14329
  (product2) => {
14209
- let variant = getSelectedVariant(product2, instance.swell.queryParams);
14210
- if (!variant) {
14211
- variant = product2;
14212
- }
14213
- return ShopifyVariant(instance, variant, product2, depth + 1);
14330
+ const variant = getSelectedVariant(product2, instance.swell.queryParams);
14331
+ return variant ? ShopifyVariant(instance, variant, product2, depth + 1) : void 0;
14214
14332
  }
14215
14333
  ),
14216
14334
  selected_selling_plan: void 0,
@@ -14231,82 +14349,17 @@ function ShopifyProduct(instance, product, depth = 0) {
14231
14349
  ).reverse();
14232
14350
  return variants;
14233
14351
  }),
14352
+ variants_count: deferWith(product, (product2) => {
14353
+ return product2.variants?.count || 0;
14354
+ }),
14234
14355
  vendor: void 0
14235
14356
  });
14236
14357
  }
14237
14358
  function ShopifyProductOptionValue(values) {
14238
14359
  return new ShopifyResource(values, "name");
14239
14360
  }
14240
- function getSelectedVariant(product, queryParams) {
14241
- const { variant: queryVariant, option_values: queryOptionValues } = queryParams;
14242
- const variants = getAvailableVariants(product);
14243
- let selectedVariant = void 0;
14244
- if (queryVariant) {
14245
- selectedVariant = variants.find(
14246
- (variant) => variant.id === queryVariant
14247
- );
14248
- } else if (queryOptionValues) {
14249
- const optionValues = queryOptionValues.split(",");
14250
- selectedVariant = variants.find(
14251
- (variant) => variant.option_value_ids.every(
14252
- (optionValueId) => optionValues.includes(optionValueId)
14253
- )
14254
- );
14255
- }
14256
- return selectedVariant || variants?.[0] || void 0;
14257
- }
14258
- function getAvailableVariants(product) {
14259
- return (product.variants?.results?.slice()?.reverse() || []).filter(
14260
- (variant) => variant.stock_status === "in_stock" || !variant.stock_status
14261
- );
14262
- }
14263
- function calculateAddOptionsPrice(product, queryParams) {
14264
- const { option_values: queryOptionValues = "" } = queryParams;
14265
- const optionValues = queryOptionValues.split(",");
14266
- const addPrice = product.options?.reduce((acc, option) => {
14267
- if (!option.active || !option.values || option.values.length <= 0) {
14268
- return acc;
14269
- }
14270
- if (option.input_type !== "select") {
14271
- return acc;
14272
- }
14273
- for (const value of option.values) {
14274
- if (optionValues.includes(value.id)) {
14275
- return acc + (value.price || 0);
14276
- }
14277
- }
14278
- return acc + (option.values[0].price || 0);
14279
- }, 0);
14280
- return product.price + (addPrice || 0);
14281
- }
14282
- function getSelectedOptionValues(product, queryParams) {
14283
- const variant = getSelectedVariant(product, queryParams);
14284
- return getSelectedVariantOptionValues(product, variant, queryParams);
14285
- }
14286
- function getSelectedVariantOptionValues(product, variant, queryParams) {
14287
- const { option_values: queryOptionValues = "" } = queryParams;
14288
- const optionValues = queryOptionValues.split(",");
14289
- const selectedValues = variant ? [...variant.option_value_ids || []] : [];
14290
- const values = [];
14291
- for (const option of product.options || []) {
14292
- if (option.active && option.values?.length > 0 && option.input_type === "select") {
14293
- let selectedByVariantId = "";
14294
- let selectedByOptionId = "";
14295
- for (const value of option.values) {
14296
- if (selectedValues.includes(value.id)) {
14297
- selectedByVariantId = value.id;
14298
- break;
14299
- }
14300
- if (optionValues.includes(value.id)) {
14301
- selectedByOptionId = value.id;
14302
- }
14303
- }
14304
- values.push(
14305
- selectedByVariantId || selectedByOptionId || option.values[0].id
14306
- );
14307
- }
14308
- }
14309
- return values;
14361
+ function isLikeShopifyProduct(value) {
14362
+ return typeof value === "object" && value !== null && Object.hasOwn(value, "variants") && Object.hasOwn(value, "gift_card?") && Object.hasOwn(value, "price_varies") && Object.hasOwn(value, "has_only_default_variant");
14310
14363
  }
14311
14364
 
14312
14365
  // src/compatibility/shopify-objects/line_item.ts
@@ -17376,7 +17429,7 @@ var tags = {
17376
17429
  };
17377
17430
  function bindTags(liquidSwell) {
17378
17431
  Object.entries(tags).forEach(
17379
- ([tag, bind61]) => liquidSwell.registerTag(tag, bind61(liquidSwell))
17432
+ ([tag, bind62]) => liquidSwell.registerTag(tag, bind62(liquidSwell))
17380
17433
  );
17381
17434
  }
17382
17435
 
@@ -18198,8 +18251,86 @@ function bind59(_liquidSwell) {
18198
18251
  };
18199
18252
  }
18200
18253
 
18201
- // src/liquid/filters/inline_editable.ts
18254
+ // src/liquid/filters/shopify/structured_data.ts
18202
18255
  function bind60(_liquidSwell) {
18256
+ return async function filterStructuredData(input) {
18257
+ let value = input;
18258
+ if (value instanceof StorefrontResource) {
18259
+ value = await value.resolve();
18260
+ }
18261
+ await resolveAllKeys(value);
18262
+ if (isObject2(value)) {
18263
+ if (isLikeShopifyProduct(value)) {
18264
+ return JSON.stringify(
18265
+ value.variants_count > 0 ? convertToSchemaOrgProductGroup(value) : convertToSchemaOrgProduct(
18266
+ value,
18267
+ value
18268
+ )
18269
+ );
18270
+ }
18271
+ if (isLikeShopifyArticle(value)) {
18272
+ return JSON.stringify(convertToSchemaOrgArticle(value));
18273
+ }
18274
+ }
18275
+ return value;
18276
+ };
18277
+ }
18278
+ function convertToSchemaOrgArticle(article) {
18279
+ const schemaOrgArticle = {
18280
+ "@context": "https://schema.org",
18281
+ "@type": "Article",
18282
+ "@id": article.url,
18283
+ url: article.url,
18284
+ name: article.title,
18285
+ author: article.author,
18286
+ image: article.image?.src.url || void 0,
18287
+ abstract: article.excerpt,
18288
+ keywords: article.tags,
18289
+ articleBody: article.content,
18290
+ dateCreated: article.created_at,
18291
+ dateModified: article.updated_at,
18292
+ datePublished: article.published_at
18293
+ };
18294
+ return schemaOrgArticle;
18295
+ }
18296
+ function convertToSchemaOrgProduct(variant, product) {
18297
+ const schemaOrgProduct = {
18298
+ "@context": "https://schema.org",
18299
+ "@type": "Product",
18300
+ "@id": variant.url,
18301
+ url: variant.url,
18302
+ sku: variant.sku,
18303
+ name: variant.title,
18304
+ image: variant.featured_image?.src.url || void 0,
18305
+ keywords: product.tags,
18306
+ description: product.description,
18307
+ offers: {
18308
+ "@type": "Offer",
18309
+ availability: variant.available ? "https://schema.org/InStock" : "https://schema.org/OutOfStock",
18310
+ price: variant.price,
18311
+ priceCurrency: "USD"
18312
+ }
18313
+ };
18314
+ return schemaOrgProduct;
18315
+ }
18316
+ function convertToSchemaOrgProductGroup(product) {
18317
+ const schemaOrgProductGroup = {
18318
+ "@context": "https://schema.org",
18319
+ "@type": "ProductGroup",
18320
+ productGroupID: String(product.id),
18321
+ url: product.url,
18322
+ name: product.title,
18323
+ description: product.description,
18324
+ variesBy: product.options,
18325
+ hasVariant: product.variants.map(
18326
+ (variant) => convertToSchemaOrgProduct(variant, product)
18327
+ )
18328
+ };
18329
+ return schemaOrgProductGroup;
18330
+ }
18331
+
18332
+ // src/liquid/filters/inline_editable.ts
18333
+ function bind61(_liquidSwell) {
18203
18334
  return (value, key) => {
18204
18335
  if (typeof value === "object" && "value" in value) {
18205
18336
  value = value.value;
@@ -18258,8 +18389,9 @@ var filters = {
18258
18389
  payment_terms: bind57,
18259
18390
  placeholder_svg_tag: bind58,
18260
18391
  shopify_asset_url: bind59,
18392
+ structured_data: bind60,
18261
18393
  // Swell only
18262
- inline_editable: bind60
18394
+ inline_editable: bind61
18263
18395
  };
18264
18396
  function bindFilters(liquidSwell) {
18265
18397
  for (const [tag, handler] of Object.entries(filters)) {
@@ -18273,8 +18405,8 @@ function bindFilters(liquidSwell) {
18273
18405
  }
18274
18406
  }
18275
18407
  }
18276
- function bindWithResolvedProps(liquidSwell, bind61, resolve = []) {
18277
- const handler = bind61(liquidSwell);
18408
+ function bindWithResolvedProps(liquidSwell, bind62, resolve = []) {
18409
+ const handler = bind62(liquidSwell);
18278
18410
  if (!Array.isArray(resolve)) {
18279
18411
  return handler;
18280
18412
  }
@@ -20744,6 +20876,7 @@ function getResourceQuery(slug, query) {
20744
20876
  Swell,
20745
20877
  SwellBackendAPI,
20746
20878
  SwellError,
20879
+ SwellProduct,
20747
20880
  SwellStorefrontCollection,
20748
20881
  SwellStorefrontPagination,
20749
20882
  SwellStorefrontRecord,
@@ -20770,9 +20903,6 @@ function getResourceQuery(slug, query) {
20770
20903
  getAllSections,
20771
20904
  getBlog,
20772
20905
  getBlogs,
20773
- getCategories,
20774
- getCategory,
20775
- getCategoryWithProducts,
20776
20906
  getContentEntry,
20777
20907
  getContentList,
20778
20908
  getContentModel,
@@ -20789,9 +20919,6 @@ function getResourceQuery(slug, query) {
20789
20919
  getMenuItemValueId,
20790
20920
  getPage,
20791
20921
  getPageSections,
20792
- getProduct,
20793
- getProducts,
20794
- getProductsFiltered,
20795
20922
  getSectionGroupProp,
20796
20923
  getSectionSettingsFromProps,
20797
20924
  getThemeSettingsFromProps,