@swell/apps-sdk 1.0.140 → 1.0.142

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
@@ -90,6 +90,7 @@ __export(index_exports, {
90
90
  adaptShopifyMenuData: () => adaptShopifyMenuData,
91
91
  arrayToObject: () => arrayToObject,
92
92
  cloneStorefrontResource: () => cloneStorefrontResource,
93
+ configureSdkLogger: () => configureSdkLogger,
93
94
  deferMenuItemUrlAndResource: () => deferMenuItemUrlAndResource,
94
95
  dehydrateSwellRefsInStorefrontResources: () => dehydrateSwellRefsInStorefrontResources,
95
96
  extractSettingsFromForm: () => extractSettingsFromForm,
@@ -213,6 +214,97 @@ var import_json52 = __toESM(require("json5"), 1);
213
214
  // src/resources.ts
214
215
  var import_lodash_es2 = require("lodash-es");
215
216
 
217
+ // src/utils/logger.ts
218
+ var logLevels = {
219
+ error: 0,
220
+ warn: 1,
221
+ info: 2,
222
+ debug: 3
223
+ };
224
+ var currentLogLevel = "warn";
225
+ var currentTimestampFormat = "off";
226
+ var isStructured = false;
227
+ function configureSdkLogger(config = {}) {
228
+ if (config.level && logLevels[config.level] !== void 0) {
229
+ currentLogLevel = config.level;
230
+ }
231
+ if (config.timestamp) {
232
+ currentTimestampFormat = config.timestamp;
233
+ }
234
+ if (typeof config.structured === "boolean") {
235
+ isStructured = config.structured;
236
+ }
237
+ }
238
+ function getTimestamp() {
239
+ if (currentTimestampFormat === "iso") {
240
+ return (/* @__PURE__ */ new Date()).toISOString();
241
+ }
242
+ if (currentTimestampFormat === "unix") {
243
+ return Date.now();
244
+ }
245
+ return void 0;
246
+ }
247
+ function formatArgs(args) {
248
+ const timestamp = getTimestamp();
249
+ if (!isStructured) {
250
+ return timestamp !== void 0 ? [...args, `(${timestamp})`] : args;
251
+ }
252
+ let message = "";
253
+ let context = {};
254
+ const messageParts = [];
255
+ for (const arg of args) {
256
+ if (arg instanceof Error) {
257
+ context.error = {
258
+ name: arg.name,
259
+ message: arg.message,
260
+ stack: arg.stack
261
+ };
262
+ } else if (typeof arg === "object" && arg !== null && !Array.isArray(arg) && Object.getPrototypeOf(arg) === Object.prototype) {
263
+ Object.assign(context, arg);
264
+ } else {
265
+ messageParts.push(arg);
266
+ }
267
+ }
268
+ message = messageParts.map((part) => typeof part === "object" ? JSON.stringify(part) : part).join(" ");
269
+ const finalLogObject = {
270
+ message,
271
+ ...context,
272
+ ...timestamp && { timestamp }
273
+ };
274
+ return [finalLogObject];
275
+ }
276
+ var logger = {
277
+ error: (...args) => {
278
+ console.error(...formatArgs(args));
279
+ },
280
+ warn: (...args) => {
281
+ if (logLevels[currentLogLevel] >= logLevels.warn) {
282
+ console.warn(...formatArgs(args));
283
+ }
284
+ },
285
+ info: (...args) => {
286
+ if (logLevels[currentLogLevel] >= logLevels.info) {
287
+ console.info(...formatArgs(args));
288
+ }
289
+ },
290
+ debug: (...args) => {
291
+ if (logLevels[currentLogLevel] >= logLevels.debug) {
292
+ console.debug(...formatArgs(args));
293
+ }
294
+ }
295
+ };
296
+ function createTraceId(data) {
297
+ if (data === void 0) {
298
+ return Math.random().toString(36).substring(2, 10);
299
+ }
300
+ let hash = 5381;
301
+ for (let i = 0; i < data.length; i++) {
302
+ const char = data.charCodeAt(i);
303
+ hash = (hash << 5) + hash + char;
304
+ }
305
+ return (hash >>> 0).toString(16);
306
+ }
307
+
216
308
  // src/liquid/utils.ts
217
309
  var import_liquidjs = require("liquidjs");
218
310
 
@@ -608,7 +700,7 @@ var StorefrontResource = class {
608
700
  return instance[prop];
609
701
  }
610
702
  instance._result = instance._get().catch((err) => {
611
- console.log(err);
703
+ logger.error(err);
612
704
  return instance._getCollectionResultOrProp(instance, prop);
613
705
  });
614
706
  }
@@ -616,7 +708,7 @@ var StorefrontResource = class {
616
708
  return instance._result.then(() => {
617
709
  return instance._getCollectionResultOrProp(instance, prop);
618
710
  }).catch((err) => {
619
- console.log(err);
711
+ logger.error(err);
620
712
  return null;
621
713
  });
622
714
  }
@@ -675,7 +767,7 @@ var StorefrontResource = class {
675
767
  }
676
768
  return result;
677
769
  }).catch((err) => {
678
- console.log(err);
770
+ logger.error(err);
679
771
  return null;
680
772
  });
681
773
  }
@@ -853,7 +945,7 @@ var SwellStorefrontCollection = class _SwellStorefrontCollection extends SwellSt
853
945
  }
854
946
  return result;
855
947
  }).catch((err) => {
856
- console.log(err);
948
+ logger.error(err);
857
949
  return null;
858
950
  });
859
951
  }
@@ -967,7 +1059,7 @@ var SwellStorefrontRecord = class extends SwellStorefrontResource {
967
1059
  }
968
1060
  return result;
969
1061
  }).catch((err) => {
970
- console.log(err);
1062
+ logger.error(err);
971
1063
  return null;
972
1064
  });
973
1065
  }
@@ -1001,15 +1093,25 @@ var SwellStorefrontSingleton = class extends SwellStorefrontResource {
1001
1093
  }
1002
1094
  async _get() {
1003
1095
  if (this._getter) {
1096
+ const trace = createTraceId();
1097
+ logger.debug("[SDK] Resource fetch start", {
1098
+ resource: this.constructor.name,
1099
+ hash: this._getterHash,
1100
+ trace
1101
+ });
1004
1102
  const getter = this._getter.bind(this);
1005
1103
  this._result = Promise.resolve().then(getter).then((result) => {
1104
+ logger.debug("[SDK] Resource fetch end", {
1105
+ hash: this._getterHash,
1106
+ trace
1107
+ });
1006
1108
  this._result = result;
1007
1109
  if (result) {
1008
1110
  Object.assign(this, result);
1009
1111
  }
1010
1112
  return result;
1011
1113
  }).catch((err) => {
1012
- console.log(err);
1114
+ logger.error(err, { trace });
1013
1115
  return null;
1014
1116
  });
1015
1117
  }
@@ -7093,6 +7195,7 @@ var DEFAULT_OPTIONS = Object.freeze({
7093
7195
  ttl: DEFAULT_TTL
7094
7196
  });
7095
7197
  var NULL_VALUE = "__NULL__";
7198
+ var SWR_PROMISE_MAP = /* @__PURE__ */ new Map();
7096
7199
  var Cache = class {
7097
7200
  client;
7098
7201
  workerCtx;
@@ -7114,19 +7217,31 @@ var Cache = class {
7114
7217
  * This will always return the cached value immediately if exists
7115
7218
  */
7116
7219
  async fetchSWR(key, fetchFn, ttl = DEFAULT_SWR_TTL) {
7220
+ const trace = createTraceId();
7221
+ logger.debug("[SDK] Cache fetch start", { key, trace });
7117
7222
  const cacheValue = await this.client.get(key);
7118
- const promiseValue = Promise.resolve().then(fetchFn).then(resolveAsyncResources).then(async (value) => {
7119
- const isNull = value === null || value === void 0;
7120
- await this.client.set(key, isNull ? NULL_VALUE : value, ttl);
7121
- return value;
7122
- });
7123
- if (this.workerCtx?.waitUntil) {
7124
- this.workerCtx.waitUntil(promiseValue);
7223
+ let promise = SWR_PROMISE_MAP.get(key);
7224
+ if (promise === void 0) {
7225
+ promise = Promise.resolve().then(fetchFn).then(resolveAsyncResources).then(async (value) => {
7226
+ const isNull = value === null || value === void 0;
7227
+ await this.client.set(key, isNull ? NULL_VALUE : value, ttl);
7228
+ logger.debug("[SDK] Cache update done", { key, trace });
7229
+ return value;
7230
+ }).finally(() => {
7231
+ SWR_PROMISE_MAP.delete(key);
7232
+ });
7233
+ SWR_PROMISE_MAP.set(key, promise);
7234
+ }
7235
+ if (typeof this.workerCtx?.waitUntil === "function") {
7236
+ this.workerCtx.waitUntil(promise);
7125
7237
  }
7126
7238
  if (cacheValue !== void 0) {
7239
+ logger.debug("[SDK] Cache check done", { status: "HIT", key, trace });
7127
7240
  return cacheValue === NULL_VALUE ? null : cacheValue;
7128
7241
  }
7129
- const result = await promiseValue;
7242
+ logger.debug("[SDK] Cache check done", { status: "MISS", key, trace });
7243
+ const result = await promise;
7244
+ logger.debug("[SDK] Cache fetch end", { key, trace });
7130
7245
  return result;
7131
7246
  }
7132
7247
  async get(key) {
@@ -7501,8 +7616,12 @@ var Swell = class _Swell {
7501
7616
  queryParams,
7502
7617
  workerEnv,
7503
7618
  workerCtx,
7619
+ logger: loggerConfig,
7504
7620
  ...clientProps
7505
7621
  } = params;
7622
+ if (loggerConfig) {
7623
+ configureSdkLogger(loggerConfig);
7624
+ }
7506
7625
  this.url = url instanceof URL ? url : new URL(url || "");
7507
7626
  this.config = config;
7508
7627
  this.shopifyCompatibilityConfig = shopifyCompatibilityConfig;
@@ -7512,7 +7631,9 @@ var Swell = class _Swell {
7512
7631
  this.workerCtx = workerCtx;
7513
7632
  this.workerEnv = workerEnv;
7514
7633
  this.resourceLoadingIndicator = params.resourceLoadingIndicator;
7515
- console.log(`KV cache: ${this.workerEnv?.THEME ? "enabled" : "disabled"}`);
7634
+ logger.info(
7635
+ `[SDK] KV cache: ${this.workerEnv?.THEME ? "enabled" : "disabled"}`
7636
+ );
7516
7637
  if (serverHeaders) {
7517
7638
  const { headers: headers2, swellHeaders: swellHeaders2 } = _Swell.formatHeaders(serverHeaders);
7518
7639
  this.headers = headers2;
@@ -7626,7 +7747,7 @@ var Swell = class _Swell {
7626
7747
  if (err instanceof Error) {
7627
7748
  err.message = `Swell: unable to load settings (${err.message})`;
7628
7749
  }
7629
- console.error(err);
7750
+ logger.error(err);
7630
7751
  }
7631
7752
  return this.storefront.settings.get();
7632
7753
  }
@@ -7709,7 +7830,9 @@ var Swell = class _Swell {
7709
7830
  decodeURIComponent(this.swellHeaders["storefront-context"])
7710
7831
  );
7711
7832
  } catch (error) {
7712
- console.error("Failed to parse swell-storefront-context. Ignoring...");
7833
+ logger.error(
7834
+ "[SDK] Failed to parse swell-storefront-context. Ignoring..."
7835
+ );
7713
7836
  }
7714
7837
  }
7715
7838
  return storefrontContext;
@@ -7739,7 +7862,7 @@ var Swell = class _Swell {
7739
7862
  return this.getRequestCache().fetchSWR(
7740
7863
  getCacheKey("request", [this.instanceId, method, url, id, data, opt]),
7741
7864
  () => {
7742
- console.log("Storefront request", { method, url, id, data });
7865
+ logger.info("[SDK] Storefront request", { method, url, id, data });
7743
7866
  return storefrontRequest(method, url, id, data, opt);
7744
7867
  }
7745
7868
  );
@@ -7763,7 +7886,7 @@ var Swell = class _Swell {
7763
7886
  */
7764
7887
  getResourceCache() {
7765
7888
  let cache = resourceCaches.get(this.instanceId);
7766
- if (!cache) {
7889
+ if (cache === void 0) {
7767
7890
  cache = new ResourceCache({
7768
7891
  kvStore: this.workerEnv?.THEME,
7769
7892
  workerCtx: this.workerCtx
@@ -7777,7 +7900,7 @@ var Swell = class _Swell {
7777
7900
  */
7778
7901
  getRequestCache() {
7779
7902
  let cache = requestCaches.get(this.instanceId);
7780
- if (!cache) {
7903
+ if (cache === void 0) {
7781
7904
  cache = new RequestCache({
7782
7905
  kvStore: this.workerEnv?.THEME,
7783
7906
  workerCtx: this.workerCtx
@@ -7830,6 +7953,11 @@ var SwellBackendAPI = class {
7830
7953
  }
7831
7954
  const endpointUrl = String(url).startsWith("/") ? url.substring(1) : url;
7832
7955
  const requestUrl = `${this.apiHost}/${endpointUrl}${query}`;
7956
+ const trace = createTraceId();
7957
+ logger.debug("[SDK] Backend request start", {
7958
+ query: `/${endpointUrl}${query}`,
7959
+ trace
7960
+ });
7833
7961
  const response = await fetch(requestUrl, requestOptions);
7834
7962
  const responseText = await response.text();
7835
7963
  let result;
@@ -7838,6 +7966,10 @@ var SwellBackendAPI = class {
7838
7966
  } catch {
7839
7967
  result = String(responseText || "").trim();
7840
7968
  }
7969
+ logger.debug("[SDK] Backend request end", {
7970
+ status: response.status,
7971
+ trace
7972
+ });
7841
7973
  if (response.status > 299) {
7842
7974
  throw new SwellError(result, {
7843
7975
  status: response.status,
@@ -8725,11 +8857,11 @@ function getRandomId() {
8725
8857
  }
8726
8858
 
8727
8859
  // src/menus.ts
8728
- var import_lodash_es11 = require("lodash-es");
8860
+ var import_lodash_es12 = require("lodash-es");
8729
8861
 
8730
8862
  // src/theme.ts
8731
8863
  var import_json56 = __toESM(require("json5"), 1);
8732
- var import_lodash_es10 = require("lodash-es");
8864
+ var import_lodash_es11 = require("lodash-es");
8733
8865
 
8734
8866
  // src/compatibility/shopify.ts
8735
8867
  var import_lodash_es7 = require("lodash-es");
@@ -17549,7 +17681,7 @@ var tags = {
17549
17681
  };
17550
17682
  function bindTags(liquidSwell) {
17551
17683
  Object.entries(tags).forEach(
17552
- ([tag, bind62]) => liquidSwell.registerTag(tag, bind62(liquidSwell))
17684
+ ([tag, bind63]) => liquidSwell.registerTag(tag, bind63(liquidSwell))
17553
17685
  );
17554
17686
  }
17555
17687
 
@@ -17833,8 +17965,16 @@ var format_address_default = {
17833
17965
  ]
17834
17966
  };
17835
17967
 
17836
- // src/liquid/filters/image_tag.ts
17968
+ // src/liquid/filters/handleize.ts
17969
+ var import_lodash_es10 = require("lodash-es");
17837
17970
  function bind40(_liquidSwell) {
17971
+ return function filterHandleize(handle) {
17972
+ return (0, import_lodash_es10.kebabCase)(handle);
17973
+ };
17974
+ }
17975
+
17976
+ // src/liquid/filters/image_tag.ts
17977
+ function bind41(_liquidSwell) {
17838
17978
  return function filterImageTag(imageUrl, ...params) {
17839
17979
  imageUrl = String(imageUrl || "");
17840
17980
  let {
@@ -17998,7 +18138,7 @@ var filterDefinition = {
17998
18138
  var image_url_default = filterDefinition;
17999
18139
 
18000
18140
  // src/liquid/filters/inline_asset_content.ts
18001
- function bind41(liquidSwell) {
18141
+ function bind42(liquidSwell) {
18002
18142
  return async (assetPath) => {
18003
18143
  const config = await liquidSwell.theme.getThemeConfig(
18004
18144
  `theme/assets/${assetPath}`
@@ -18008,14 +18148,14 @@ function bind41(liquidSwell) {
18008
18148
  }
18009
18149
 
18010
18150
  // src/liquid/filters/json.ts
18011
- function bind42(_liquidSwell) {
18151
+ function bind43(_liquidSwell) {
18012
18152
  return async function filterJson(input, space = 0) {
18013
18153
  return jsonStringifyAsync(input, space);
18014
18154
  };
18015
18155
  }
18016
18156
 
18017
18157
  // src/liquid/filters/json_pretty.ts
18018
- function bind43(_liquidSwell) {
18158
+ function bind44(_liquidSwell) {
18019
18159
  return async function filterJsonPretty(input, space = 2) {
18020
18160
  const output = await jsonStringifyAsync(input, space);
18021
18161
  return `<pre>${output}</pre>`;
@@ -18032,7 +18172,7 @@ function getCountryCode(localCode) {
18032
18172
  return localCode.toUpperCase();
18033
18173
  }
18034
18174
  }
18035
- function bind44(_liquidSwell) {
18175
+ function bind45(_liquidSwell) {
18036
18176
  return (localeCode) => {
18037
18177
  if (typeof localeCode !== "string") {
18038
18178
  return flags.US;
@@ -18043,7 +18183,7 @@ function bind44(_liquidSwell) {
18043
18183
  }
18044
18184
 
18045
18185
  // src/liquid/filters/money.ts
18046
- function bind45(liquidSwell) {
18186
+ function bind46(liquidSwell) {
18047
18187
  return function filterMoney(value) {
18048
18188
  const amount = value instanceof MoneyDrop ? value.toFloat() : Number(value || 0);
18049
18189
  return liquidSwell.renderCurrency(amount);
@@ -18051,7 +18191,7 @@ function bind45(liquidSwell) {
18051
18191
  }
18052
18192
 
18053
18193
  // src/liquid/filters/money_with_currency.ts
18054
- function bind46(liquidSwell) {
18194
+ function bind47(liquidSwell) {
18055
18195
  return function filterMoneyWithCurrency(value) {
18056
18196
  const { currency } = liquidSwell.theme.swell.getStorefrontLocalization();
18057
18197
  const amount = value instanceof MoneyDrop ? value.toFloat() : Number(value || 0);
@@ -18060,7 +18200,7 @@ function bind46(liquidSwell) {
18060
18200
  }
18061
18201
 
18062
18202
  // src/liquid/filters/money_without_currency.ts
18063
- function bind47(liquidSwell) {
18203
+ function bind48(liquidSwell) {
18064
18204
  return function filterMoneyWithoutCurrency(value) {
18065
18205
  const amount = value instanceof MoneyDrop ? value.toFloat() : Number(value || 0);
18066
18206
  return liquidSwell.renderCurrency(amount).replace(/[^0-9.,]/g, "");
@@ -18068,7 +18208,7 @@ function bind47(liquidSwell) {
18068
18208
  }
18069
18209
 
18070
18210
  // src/liquid/filters/money_without_trailing_zeros.ts
18071
- function bind48(liquidSwell) {
18211
+ function bind49(liquidSwell) {
18072
18212
  return function filterMoneyWithoutTrailingZeros(value) {
18073
18213
  const amount = value instanceof MoneyDrop ? value.toFloat() : Number(value || 0);
18074
18214
  return liquidSwell.renderCurrency(amount).split(".")[0].split(",")[0];
@@ -18076,21 +18216,21 @@ function bind48(liquidSwell) {
18076
18216
  }
18077
18217
 
18078
18218
  // src/liquid/filters/script_tag.ts
18079
- function bind49(_liquidSwell) {
18219
+ function bind50(_liquidSwell) {
18080
18220
  return function filterScriptTag(assetUrl) {
18081
18221
  return `<script src="${assetUrl}" type="text/javascript"></script>`;
18082
18222
  };
18083
18223
  }
18084
18224
 
18085
18225
  // src/liquid/filters/stylesheet_tag.ts
18086
- function bind50(_liquidSwell) {
18226
+ function bind51(_liquidSwell) {
18087
18227
  return function filterStyleSheetTag(assetUrl) {
18088
18228
  return `<link href="${assetUrl}" rel="stylesheet" type="text/css" media="all" />`;
18089
18229
  };
18090
18230
  }
18091
18231
 
18092
18232
  // src/liquid/filters/time_tag.ts
18093
- function bind51(_liquidSwell) {
18233
+ function bind52(_liquidSwell) {
18094
18234
  const dateFilter = bind33(_liquidSwell);
18095
18235
  return (dateValue, ...params) => {
18096
18236
  const date = ensureDate(dateValue);
@@ -18101,7 +18241,7 @@ function bind51(_liquidSwell) {
18101
18241
  }
18102
18242
 
18103
18243
  // src/liquid/filters/translate.ts
18104
- function bind52(liquidSwell) {
18244
+ function bind53(liquidSwell) {
18105
18245
  return async function filterTranslate(key, params) {
18106
18246
  const props = params && paramsToProps(params);
18107
18247
  const str = await liquidSwell.renderTranslation(key, props);
@@ -18110,7 +18250,7 @@ function bind52(liquidSwell) {
18110
18250
  }
18111
18251
 
18112
18252
  // src/liquid/filters/where.ts
18113
- function bind53(_liquidSwell) {
18253
+ function bind54(_liquidSwell) {
18114
18254
  return function* filterWhere(arr, property, expected) {
18115
18255
  const results = [];
18116
18256
  const list = yield resolveEnumerable(arr);
@@ -18164,7 +18304,7 @@ function getSizesFromParam(param) {
18164
18304
  height: height ? Number(height) : void 0
18165
18305
  };
18166
18306
  }
18167
- function bind54(liquidSwell) {
18307
+ function bind55(liquidSwell) {
18168
18308
  return async function filterAssetImgUrl(assetPath, size = "small") {
18169
18309
  const imageUrl = await liquidSwell.getAssetUrl(assetPath).then((url) => url || "");
18170
18310
  const sizes = getSizesFromParam(size);
@@ -18180,7 +18320,7 @@ function bind54(liquidSwell) {
18180
18320
  }
18181
18321
 
18182
18322
  // src/liquid/filters/shopify/hex_to_rgba.ts
18183
- function bind55(_liquidSwell) {
18323
+ function bind56(_liquidSwell) {
18184
18324
  return (color, alpha) => {
18185
18325
  return ThemeColor.get(color).rgba(alpha || 1);
18186
18326
  };
@@ -18200,14 +18340,14 @@ var item_count_for_variant_default = {
18200
18340
  };
18201
18341
 
18202
18342
  // src/liquid/filters/shopify/payment_button.ts
18203
- function bind56(_liquidSwell) {
18343
+ function bind57(_liquidSwell) {
18204
18344
  return (form) => {
18205
18345
  return null;
18206
18346
  };
18207
18347
  }
18208
18348
 
18209
18349
  // src/liquid/filters/shopify/payment_terms.ts
18210
- function bind57(_liquidSwell) {
18350
+ function bind58(_liquidSwell) {
18211
18351
  return (form) => {
18212
18352
  return null;
18213
18353
  };
@@ -18309,7 +18449,7 @@ var svgs = {
18309
18449
  var placeholder_svgs_default = svgs;
18310
18450
 
18311
18451
  // src/liquid/filters/shopify/placeholder_svg_tag.ts
18312
- function bind58(_liquidSwell) {
18452
+ function bind59(_liquidSwell) {
18313
18453
  return function filterPlaceholderSvgTag(name, className) {
18314
18454
  const svg = placeholder_svgs_default[name];
18315
18455
  if (typeof svg === "object" && svg !== null) {
@@ -18320,7 +18460,7 @@ function bind58(_liquidSwell) {
18320
18460
  }
18321
18461
 
18322
18462
  // src/liquid/filters/shopify/shopify_asset_url.ts
18323
- function bind59(_liquidSwell) {
18463
+ function bind60(_liquidSwell) {
18324
18464
  return function filterShopifyAssetUrl(input) {
18325
18465
  if (typeof input === "string") {
18326
18466
  switch (input) {
@@ -18345,7 +18485,7 @@ function bind59(_liquidSwell) {
18345
18485
  }
18346
18486
 
18347
18487
  // src/liquid/filters/shopify/structured_data.ts
18348
- function bind60(_liquidSwell) {
18488
+ function bind61(_liquidSwell) {
18349
18489
  return async function filterStructuredData(input) {
18350
18490
  let value = input;
18351
18491
  if (value instanceof StorefrontResource) {
@@ -18423,7 +18563,7 @@ function convertToSchemaOrgProductGroup(product) {
18423
18563
  }
18424
18564
 
18425
18565
  // src/liquid/filters/inline_editable.ts
18426
- function bind61(_liquidSwell) {
18566
+ function bind62(_liquidSwell) {
18427
18567
  return (value, key) => {
18428
18568
  if (typeof value === "object" && "value" in value) {
18429
18569
  value = value.value;
@@ -18457,34 +18597,37 @@ var filters = {
18457
18597
  font_modify: bind38,
18458
18598
  font_url: bind39,
18459
18599
  format_address: format_address_default,
18460
- image_tag: bind40,
18600
+ handle: bind40,
18601
+ // alias
18602
+ handleize: bind40,
18603
+ image_tag: bind41,
18461
18604
  image_url: image_url_default,
18462
- inline_asset_content: bind41,
18463
- json: bind42,
18464
- json_pretty: bind43,
18465
- locale_flag: bind44,
18466
- money: bind45,
18467
- money_with_currency: bind46,
18468
- money_without_currency: bind47,
18469
- money_without_trailing_zeros: bind48,
18470
- script_tag: bind49,
18471
- stylesheet_tag: bind50,
18472
- time_tag: bind51,
18473
- translate: bind52,
18474
- t: bind52,
18605
+ inline_asset_content: bind42,
18606
+ json: bind43,
18607
+ json_pretty: bind44,
18608
+ locale_flag: bind45,
18609
+ money: bind46,
18610
+ money_with_currency: bind47,
18611
+ money_without_currency: bind48,
18612
+ money_without_trailing_zeros: bind49,
18613
+ script_tag: bind50,
18614
+ stylesheet_tag: bind51,
18615
+ time_tag: bind52,
18616
+ translate: bind53,
18617
+ t: bind53,
18475
18618
  // alias
18476
- where: bind53,
18619
+ where: bind54,
18477
18620
  // Shopify compatibility only
18478
- asset_img_url: bind54,
18479
- hex_to_rgba: bind55,
18621
+ asset_img_url: bind55,
18622
+ hex_to_rgba: bind56,
18480
18623
  item_count_for_variant: item_count_for_variant_default,
18481
- payment_button: bind56,
18482
- payment_terms: bind57,
18483
- placeholder_svg_tag: bind58,
18484
- shopify_asset_url: bind59,
18485
- structured_data: bind60,
18624
+ payment_button: bind57,
18625
+ payment_terms: bind58,
18626
+ placeholder_svg_tag: bind59,
18627
+ shopify_asset_url: bind60,
18628
+ structured_data: bind61,
18486
18629
  // Swell only
18487
- inline_editable: bind61
18630
+ inline_editable: bind62
18488
18631
  };
18489
18632
  function bindFilters(liquidSwell) {
18490
18633
  for (const [tag, handler] of Object.entries(filters)) {
@@ -18498,8 +18641,8 @@ function bindFilters(liquidSwell) {
18498
18641
  }
18499
18642
  }
18500
18643
  }
18501
- function bindWithResolvedProps(liquidSwell, bind62, resolve = []) {
18502
- const handler = bind62(liquidSwell);
18644
+ function bindWithResolvedProps(liquidSwell, bind63, resolve = []) {
18645
+ const handler = bind63(liquidSwell);
18503
18646
  if (!Array.isArray(resolve)) {
18504
18647
  return handler;
18505
18648
  }
@@ -19243,9 +19386,14 @@ var SwellTheme3 = class {
19243
19386
  }
19244
19387
  async initGlobals(pageId, altTemplate) {
19245
19388
  this.pageId = pageId;
19389
+ const trace = createTraceId();
19390
+ logger.debug("[SDK] Theme init start", { page: pageId, trace });
19246
19391
  await this.themeLoader.init(this.themeConfigs || void 0);
19392
+ logger.debug("[SDK] ThemeLoader init done", { page: pageId, trace });
19247
19393
  const { store, session, menus, geo, configs } = await this.getSettingsAndConfigs();
19394
+ logger.debug("[SDK] Theme settings load done", { page: pageId, trace });
19248
19395
  const { settings, request, page, cart, account, customer } = await this.resolvePageData(store, configs, pageId, altTemplate);
19396
+ logger.debug("[SDK] Theme page data load done", { page: pageId, trace });
19249
19397
  this.page = page;
19250
19398
  const globals = {
19251
19399
  ...this.globalData,
@@ -19272,6 +19420,7 @@ var SwellTheme3 = class {
19272
19420
  if (this.shopifyCompatibility) {
19273
19421
  this.shopifyCompatibility.adaptQueryParams();
19274
19422
  }
19423
+ logger.debug("[SDK] Theme init end", { page: pageId, trace });
19275
19424
  }
19276
19425
  setGlobals(globals) {
19277
19426
  if (this.shopifyCompatibility) {
@@ -19304,7 +19453,7 @@ var SwellTheme3 = class {
19304
19453
  try {
19305
19454
  configValue = import_json56.default.parse(config.file_data);
19306
19455
  } catch (err) {
19307
- console.error(`Error parsing ${configName} config: ${err}`);
19456
+ logger.error(`Error parsing config`, err, { configName });
19308
19457
  configValue = {};
19309
19458
  }
19310
19459
  acc[configName] = configValue;
@@ -19391,7 +19540,7 @@ var SwellTheme3 = class {
19391
19540
  templateConfig?.file_data || "{}"
19392
19541
  );
19393
19542
  } catch (err) {
19394
- console.warn(err);
19543
+ logger.warn(err);
19395
19544
  }
19396
19545
  if (pageSchema?.page) {
19397
19546
  const {
@@ -19591,7 +19740,7 @@ var SwellTheme3 = class {
19591
19740
  return languageConfig;
19592
19741
  }
19593
19742
  const localeShortCode = locale.split("-")[0];
19594
- return (0, import_lodash_es10.reduce)(
19743
+ return (0, import_lodash_es11.reduce)(
19595
19744
  languageConfig,
19596
19745
  (acc, value, key) => {
19597
19746
  if (isObject2(value)) {
@@ -19615,15 +19764,15 @@ var SwellTheme3 = class {
19615
19764
  const translationEnd = translationParts.pop();
19616
19765
  const translationPath = translationParts.join(".");
19617
19766
  const translationConfigGlobal = this.globals.language;
19618
- acc[key] = (0, import_lodash_es10.get)(
19767
+ acc[key] = (0, import_lodash_es11.get)(
19619
19768
  translationConfigGlobal,
19620
19769
  `${translationPath}.$locale.${locale}.${translationEnd}`
19621
- ) || (0, import_lodash_es10.get)(
19770
+ ) || (0, import_lodash_es11.get)(
19622
19771
  translationConfigGlobal,
19623
19772
  `${translationPath}.$locale.${localeShortCode}.${translationEnd}`
19624
- ) || (0, import_lodash_es10.get)(translationConfigGlobal, translationKey) || value;
19773
+ ) || (0, import_lodash_es11.get)(translationConfigGlobal, translationKey) || value;
19625
19774
  } else {
19626
- acc[key] = (0, import_lodash_es10.get)(languageConfig, `$locale.${locale}.${key}`) || (0, import_lodash_es10.get)(languageConfig, `$locale.${localeShortCode}.${key}`) || value;
19775
+ acc[key] = (0, import_lodash_es11.get)(languageConfig, `$locale.${locale}.${key}`) || (0, import_lodash_es11.get)(languageConfig, `$locale.${localeShortCode}.${key}`) || value;
19627
19776
  }
19628
19777
  }
19629
19778
  return acc;
@@ -19696,7 +19845,7 @@ var SwellTheme3 = class {
19696
19845
  try {
19697
19846
  return import_json56.default.parse(localeConfig?.file_data || "{}");
19698
19847
  } catch (err) {
19699
- console.warn(err);
19848
+ logger.warn(err);
19700
19849
  }
19701
19850
  }
19702
19851
  return {};
@@ -19865,10 +20014,20 @@ var SwellTheme3 = class {
19865
20014
  return "";
19866
20015
  }
19867
20016
  template = unescapeLiquidSyntax(template);
20017
+ const trace = createTraceId();
19868
20018
  try {
19869
- return await this.liquidSwell.parseAndRender(template, data);
20019
+ logger.debug("[SDK] Render template start", {
20020
+ config: config.name,
20021
+ trace
20022
+ });
20023
+ const result = await this.liquidSwell.parseAndRender(template, data);
20024
+ logger.debug("[SDK] Render template end", {
20025
+ config: config.name,
20026
+ trace
20027
+ });
20028
+ return result;
19870
20029
  } catch (err) {
19871
- console.error(err);
20030
+ logger.error(err);
19872
20031
  return `<!-- template render error: ${err.message} -->`;
19873
20032
  }
19874
20033
  }
@@ -19876,7 +20035,7 @@ var SwellTheme3 = class {
19876
20035
  try {
19877
20036
  return await this.liquidSwell.parseAndRender(templateString, data);
19878
20037
  } catch (err) {
19879
- console.error(err);
20038
+ logger.error(err);
19880
20039
  return "";
19881
20040
  }
19882
20041
  }
@@ -19900,7 +20059,7 @@ var SwellTheme3 = class {
19900
20059
  );
19901
20060
  }
19902
20061
  } catch (err) {
19903
- console.warn(err);
20062
+ logger.warn(err);
19904
20063
  return void 0;
19905
20064
  }
19906
20065
  } else if (config?.file_path?.endsWith(".liquid")) {
@@ -19953,11 +20112,10 @@ var SwellTheme3 = class {
19953
20112
  try {
19954
20113
  return import_json56.default.parse(content);
19955
20114
  } catch (err) {
19956
- console.log(
19957
- "Unable to render theme template",
19958
- config.file_path,
20115
+ logger.error("[SDK] Unable to render theme template", {
20116
+ file: config.file_path,
19959
20117
  content
19960
- );
20118
+ });
19961
20119
  throw new PageError(err);
19962
20120
  }
19963
20121
  }
@@ -20214,7 +20372,7 @@ ${this.shopifyCompatibility.getContentForHeader()}`;
20214
20372
  try {
20215
20373
  schema = import_json56.default.parse(resolvedConfig?.file_data) || void 0;
20216
20374
  } catch (err) {
20217
- console.warn(err);
20375
+ logger.warn(err);
20218
20376
  }
20219
20377
  }
20220
20378
  return schema;
@@ -20411,8 +20569,8 @@ ${this.shopifyCompatibility.getContentForHeader()}`;
20411
20569
  const keyParts = key?.split(".") || [];
20412
20570
  const keyName = keyParts.pop() || "";
20413
20571
  const keyPath = keyParts.join(".");
20414
- const langObject = (0, import_lodash_es10.get)(langConfig, keyPath);
20415
- let localeValue = (0, import_lodash_es10.get)(langObject?.[localeCode], keyName) || (0, import_lodash_es10.get)(langObject?.[localeCode.split("-")[0]], keyName) || langObject?.[keyName];
20572
+ const langObject = (0, import_lodash_es11.get)(langConfig, keyPath);
20573
+ let localeValue = (0, import_lodash_es11.get)(langObject?.[localeCode], keyName) || (0, import_lodash_es11.get)(langObject?.[localeCode.split("-")[0]], keyName) || langObject?.[keyName];
20416
20574
  if (data?.count !== void 0 && localeValue?.one) {
20417
20575
  localeValue = data.count === 1 ? localeValue.one : localeValue.other;
20418
20576
  }
@@ -20491,7 +20649,7 @@ function fillDefaultThemeSettings(themeSettings, editorSchemaSettings) {
20491
20649
  }
20492
20650
  }
20493
20651
  function resolveThemeSettings(theme, themeSettings, editorSchemaSettings) {
20494
- const settings = (0, import_lodash_es10.cloneDeep)(themeSettings);
20652
+ const settings = (0, import_lodash_es11.cloneDeep)(themeSettings);
20495
20653
  if (settings.$locale) {
20496
20654
  const { locale } = theme.swell.getStorefrontLocalization();
20497
20655
  const localeConfig = settings.$locale[locale] || {};
@@ -20501,16 +20659,16 @@ function resolveThemeSettings(theme, themeSettings, editorSchemaSettings) {
20501
20659
  }
20502
20660
  }
20503
20661
  }
20504
- (0, import_lodash_es10.each)(settings, (value, key) => {
20662
+ (0, import_lodash_es11.each)(settings, (value, key) => {
20505
20663
  const setting = (editorSchemaSettings && findEditorSetting(editorSchemaSettings, key)) ?? null;
20506
20664
  if (isObject2(value) && !(value instanceof StorefrontResource)) {
20507
20665
  switch (setting?.type) {
20508
20666
  case "color_scheme_group": {
20509
- (0, import_lodash_es10.each)(value, (scheme, schemeId) => {
20667
+ (0, import_lodash_es11.each)(value, (scheme, schemeId) => {
20510
20668
  if (isObject2(scheme) && typeof scheme.settings === "object" && scheme.settings) {
20511
20669
  const settings2 = scheme.settings;
20512
- (0, import_lodash_es10.each)(settings2, (colorValue, colorId) => {
20513
- const fieldDef = (0, import_lodash_es10.find)(setting.fields, { id: colorId });
20670
+ (0, import_lodash_es11.each)(settings2, (colorValue, colorId) => {
20671
+ const fieldDef = (0, import_lodash_es11.find)(setting.fields, { id: colorId });
20514
20672
  if (fieldDef?.type === "color" && colorValue) {
20515
20673
  scheme.id = schemeId;
20516
20674
  settings2[colorId] = new ThemeColor(colorValue);
@@ -20561,7 +20719,7 @@ function resolveThemeSettings(theme, themeSettings, editorSchemaSettings) {
20561
20719
  }
20562
20720
  function findThemeSettingsByType(type, themeSettings, editorSchemaSettings) {
20563
20721
  const foundSettings = [];
20564
- (0, import_lodash_es10.each)(themeSettings, (value, key) => {
20722
+ (0, import_lodash_es11.each)(themeSettings, (value, key) => {
20565
20723
  if (isObject2(value) && !(value instanceof ThemeFont) && !(value instanceof StorefrontResource)) {
20566
20724
  foundSettings.push(
20567
20725
  ...findThemeSettingsByType(type, value, editorSchemaSettings)
@@ -20604,7 +20762,7 @@ function parseJsonConfig(config) {
20604
20762
  try {
20605
20763
  return import_json56.default.parse(config?.file_data || "{}");
20606
20764
  } catch (err) {
20607
- console.warn(err);
20765
+ logger.warn(err);
20608
20766
  return {};
20609
20767
  }
20610
20768
  }
@@ -20692,13 +20850,20 @@ async function resolveMenuItems(theme, menuItems, options) {
20692
20850
  async function resolveMenuItemUrlAndResource(theme, item, options) {
20693
20851
  if (!item) return { url: "#invalid-link-item" };
20694
20852
  if (typeof item === "object" && item !== null) {
20695
- let { url, resource } = await getMenuItemUrlAndResource(theme, item);
20696
- const endsWithSlash = url.slice(-1) === "/";
20697
- if (options?.trailingSlash && !endsWithSlash && url.length > 1) {
20698
- url = url + "/";
20699
- }
20700
- if (!options?.trailingSlash && endsWithSlash && url.length > 1) {
20701
- url = url.slice(0, -1);
20853
+ const { url: itemUrl, resource } = await getMenuItemUrlAndResource(
20854
+ theme,
20855
+ item
20856
+ );
20857
+ let url = itemUrl;
20858
+ if (url.length > 1) {
20859
+ const endsWithSlash = url.endsWith("/");
20860
+ if (options?.trailingSlash) {
20861
+ if (!endsWithSlash) {
20862
+ url = url + "/";
20863
+ }
20864
+ } else if (endsWithSlash) {
20865
+ url = url.slice(0, -1);
20866
+ }
20702
20867
  }
20703
20868
  return { url, resource };
20704
20869
  } else {
@@ -20723,7 +20888,7 @@ function isChildItemActive(items) {
20723
20888
  }
20724
20889
  function getMenuItemValueId(value) {
20725
20890
  const fallback = typeof value === "string" ? value : "";
20726
- const slug = (0, import_lodash_es11.get)(value, "id", (0, import_lodash_es11.get)(value, "slug", fallback)) || "";
20891
+ const slug = (0, import_lodash_es12.get)(value, "id", (0, import_lodash_es12.get)(value, "slug", fallback)) || "";
20727
20892
  return slug;
20728
20893
  }
20729
20894
  async function getMenuItemUrlAndResource(theme, menuItem) {
@@ -20740,43 +20905,40 @@ async function getMenuItemUrlAndResource(theme, menuItem) {
20740
20905
  return {
20741
20906
  url: getMenuItemStorefrontUrl(theme, "index")
20742
20907
  };
20743
- case "category" /* Category */:
20908
+ case "category" /* Category */: {
20744
20909
  if (!id) {
20745
20910
  return {
20746
20911
  url: getMenuItemStorefrontUrl(theme, "categories/index")
20747
20912
  };
20748
20913
  }
20749
- return await deferMenuItemUrlAndResource(
20750
- theme,
20751
- "categories/category",
20752
- id
20753
- );
20754
- case "product" /* Product */:
20914
+ return deferMenuItemUrlAndResource(theme, "categories/category", id);
20915
+ }
20916
+ case "product" /* Product */: {
20755
20917
  if (!id) {
20756
20918
  return {
20757
20919
  url: getMenuItemStorefrontUrl(theme, "products/index")
20758
20920
  };
20759
20921
  }
20760
- return await deferMenuItemUrlAndResource(theme, "products/product", id);
20922
+ return deferMenuItemUrlAndResource(theme, "products/product", id);
20923
+ }
20924
+ case "product_list" /* ProductList */:
20925
+ return {
20926
+ url: getMenuItemStorefrontUrl(theme, "products/index")
20927
+ };
20761
20928
  case "page" /* Page */:
20762
- return await deferMenuItemUrlAndResource(theme, "pages/page", id);
20929
+ return deferMenuItemUrlAndResource(theme, "pages/page", id);
20763
20930
  case "blog" /* Blog */:
20764
- return await deferMenuItemUrlAndResource(
20765
- theme,
20766
- "blogs/blog",
20767
- id,
20768
- async (blog) => {
20769
- const blogCategory = new SwellStorefrontRecord(
20770
- theme.swell,
20771
- "content/blog-categories",
20772
- blog.category_id
20773
- );
20774
- return blogCategory.slug;
20775
- }
20776
- );
20931
+ return deferMenuItemUrlAndResource(theme, "blogs/blog", id, (blog) => {
20932
+ const blogCategory = new SwellStorefrontRecord(
20933
+ theme.swell,
20934
+ "content/blog-categories",
20935
+ blog.category_id
20936
+ );
20937
+ return blogCategory.slug;
20938
+ });
20777
20939
  case "blog_category" /* BlogCategory */:
20778
- return await deferMenuItemUrlAndResource(theme, "blogs/category", id);
20779
- case "content_list" /* ContentList */:
20940
+ return deferMenuItemUrlAndResource(theme, "blogs/category", id);
20941
+ case "content_list" /* ContentList */: {
20780
20942
  if (model) {
20781
20943
  const slug = model?.replace("content/", "");
20782
20944
  return {
@@ -20785,10 +20947,11 @@ async function getMenuItemUrlAndResource(theme, menuItem) {
20785
20947
  };
20786
20948
  }
20787
20949
  break;
20788
- case "content" /* Content */:
20950
+ }
20951
+ case "content" /* Content */: {
20789
20952
  if (model) {
20790
20953
  const collectionSlug = model?.replace("content/", "");
20791
- return await deferMenuItemUrlAndResource(
20954
+ return deferMenuItemUrlAndResource(
20792
20955
  theme,
20793
20956
  "content/content",
20794
20957
  id,
@@ -20796,6 +20959,7 @@ async function getMenuItemUrlAndResource(theme, menuItem) {
20796
20959
  );
20797
20960
  }
20798
20961
  break;
20962
+ }
20799
20963
  case "search" /* Search */:
20800
20964
  return {
20801
20965
  url: getMenuItemStorefrontUrl(theme, "search")
@@ -21075,6 +21239,7 @@ function getResourceQuery(slug, query) {
21075
21239
  adaptShopifyMenuData,
21076
21240
  arrayToObject,
21077
21241
  cloneStorefrontResource,
21242
+ configureSdkLogger,
21078
21243
  deferMenuItemUrlAndResource,
21079
21244
  dehydrateSwellRefsInStorefrontResources,
21080
21245
  extractSettingsFromForm,