@swell/apps-sdk 1.0.150 → 1.0.152
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 +767 -185
- package/dist/index.cjs.map +4 -4
- package/dist/index.js +747 -185
- package/dist/index.js.map +4 -4
- package/dist/index.mjs +757 -185
- package/dist/index.mjs.map +4 -4
- package/dist/src/cache/cache-api-stub.d.ts +25 -0
- package/dist/src/cache/index.d.ts +2 -0
- package/dist/src/cache/worker-html-cache.d.ts +43 -0
- package/dist/src/compatibility/drops/all_products.d.ts +1 -1
- package/dist/src/compatibility/drops/articles.d.ts +1 -1
- package/dist/src/compatibility/drops/blogs.d.ts +1 -1
- package/dist/src/compatibility/drops/collections.d.ts +2 -3
- package/dist/src/compatibility/drops/images.d.ts +1 -1
- package/dist/src/compatibility/drops/pages.d.ts +2 -3
- package/dist/src/compatibility/shopify-objects/collections.d.ts +2 -2
- package/dist/src/content.d.ts +3 -3
- package/dist/src/index.d.ts +3 -0
- package/dist/src/liquid/filters/shopify/default_pagination.d.ts +1 -1
- package/dist/src/resources/account.d.ts +4 -4
- package/dist/src/resources/addresses.d.ts +7 -0
- package/dist/src/resources/blog.d.ts +5 -4
- package/dist/src/resources/blog_category.d.ts +5 -4
- package/dist/src/resources/cart.d.ts +4 -4
- package/dist/src/resources/categories.d.ts +7 -0
- package/dist/src/resources/category.d.ts +5 -4
- package/dist/src/resources/index.d.ts +18 -9
- package/dist/src/resources/order.d.ts +5 -4
- package/dist/src/resources/orders.d.ts +7 -0
- package/dist/src/resources/page.d.ts +5 -4
- package/dist/src/resources/predictive_search.d.ts +6 -0
- package/dist/src/resources/product.d.ts +5 -19
- package/dist/src/resources/product_helpers.d.ts +12 -2
- package/dist/src/resources/product_recommendations.d.ts +6 -0
- package/dist/src/resources/search.d.ts +6 -0
- package/dist/src/resources/subscription.d.ts +7 -0
- package/dist/src/resources/subscriptions.d.ts +7 -0
- package/dist/src/resources/swell_types.d.ts +66 -9
- package/dist/src/resources/variant.d.ts +8 -8
- package/dist/src/resources.d.ts +11 -12
- package/dist/types/shopify.d.ts +2 -2
- package/dist/types/swell.d.ts +3 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -41,72 +41,6 @@
|
|
|
41
41
|
var import_keyv = __require("keyv");
|
|
42
42
|
var import_cache_manager = __require("cache-manager");
|
|
43
43
|
|
|
44
|
-
// src/cache/cf-worker-kv-keyv-adapter.ts
|
|
45
|
-
var CFWorkerKVKeyvAdapter = class {
|
|
46
|
-
store;
|
|
47
|
-
namespace;
|
|
48
|
-
// magically passed in from Keyv
|
|
49
|
-
opts;
|
|
50
|
-
constructor(store) {
|
|
51
|
-
this.store = store;
|
|
52
|
-
this.opts = null;
|
|
53
|
-
this.namespace = "dummy";
|
|
54
|
-
}
|
|
55
|
-
async has(key) {
|
|
56
|
-
const stream = await this.store.get(key, "stream");
|
|
57
|
-
if (stream !== null) {
|
|
58
|
-
await stream.cancel();
|
|
59
|
-
return true;
|
|
60
|
-
}
|
|
61
|
-
return false;
|
|
62
|
-
}
|
|
63
|
-
async get(key) {
|
|
64
|
-
const value = await this.store.get(key);
|
|
65
|
-
return value !== null ? value : void 0;
|
|
66
|
-
}
|
|
67
|
-
set(key, value, ttl) {
|
|
68
|
-
if (typeof ttl === "number") {
|
|
69
|
-
ttl = Math.max(60, ttl / 1e3);
|
|
70
|
-
}
|
|
71
|
-
return this.store.put(key, value, { expirationTtl: ttl });
|
|
72
|
-
}
|
|
73
|
-
async delete(key) {
|
|
74
|
-
await this.store.delete(key);
|
|
75
|
-
return true;
|
|
76
|
-
}
|
|
77
|
-
async clear() {
|
|
78
|
-
let cursor = "";
|
|
79
|
-
let complete = false;
|
|
80
|
-
const prefix = `${this.namespace}:`;
|
|
81
|
-
do {
|
|
82
|
-
const response = await this.store.list({
|
|
83
|
-
prefix,
|
|
84
|
-
cursor: cursor || void 0
|
|
85
|
-
});
|
|
86
|
-
cursor = response.cursor ?? "";
|
|
87
|
-
complete = response.list_complete;
|
|
88
|
-
if (response.keys.length > 0) {
|
|
89
|
-
await Promise.all(
|
|
90
|
-
response.keys.map((key) => {
|
|
91
|
-
return this.store.delete(key.name);
|
|
92
|
-
})
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
} while (!complete);
|
|
96
|
-
}
|
|
97
|
-
on(_event, _listener) {
|
|
98
|
-
return this;
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
// src/utils/index.ts
|
|
103
|
-
var import_qs = __toESM(__require("qs"), 1);
|
|
104
|
-
var import_lodash_es3 = __require("lodash-es");
|
|
105
|
-
var import_json52 = __toESM(__require("json5"), 1);
|
|
106
|
-
|
|
107
|
-
// src/resources.ts
|
|
108
|
-
var import_lodash_es2 = __require("lodash-es");
|
|
109
|
-
|
|
110
44
|
// src/utils/logger.ts
|
|
111
45
|
var logLevels = {
|
|
112
46
|
error: 0,
|
|
@@ -198,6 +132,80 @@
|
|
|
198
132
|
return (hash >>> 0).toString(16);
|
|
199
133
|
}
|
|
200
134
|
|
|
135
|
+
// src/cache/cf-worker-kv-keyv-adapter.ts
|
|
136
|
+
var CFWorkerKVKeyvAdapter = class {
|
|
137
|
+
store;
|
|
138
|
+
namespace;
|
|
139
|
+
// magically passed in from Keyv
|
|
140
|
+
opts;
|
|
141
|
+
constructor(store) {
|
|
142
|
+
this.store = store;
|
|
143
|
+
this.opts = null;
|
|
144
|
+
this.namespace = "dummy";
|
|
145
|
+
}
|
|
146
|
+
async has(key) {
|
|
147
|
+
const stream = await this.store.get(key, "stream");
|
|
148
|
+
if (stream !== null) {
|
|
149
|
+
await stream.cancel();
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
async get(key) {
|
|
155
|
+
const trace = createTraceId();
|
|
156
|
+
logger.debug("[SDK] kv.get", { key, trace });
|
|
157
|
+
const value = await this.store.get(key);
|
|
158
|
+
const result = value !== null ? value : void 0;
|
|
159
|
+
logger.debug(`[SDK] kv.get ${value !== null ? "HIT" : "MISS"}`, {
|
|
160
|
+
key,
|
|
161
|
+
trace
|
|
162
|
+
});
|
|
163
|
+
return result;
|
|
164
|
+
}
|
|
165
|
+
set(key, value, ttl) {
|
|
166
|
+
if (typeof ttl === "number") {
|
|
167
|
+
ttl = Math.max(60, ttl / 1e3);
|
|
168
|
+
}
|
|
169
|
+
logger.debug("[SDK] kv.set", { key });
|
|
170
|
+
return this.store.put(key, value, { expirationTtl: ttl });
|
|
171
|
+
}
|
|
172
|
+
async delete(key) {
|
|
173
|
+
await this.store.delete(key);
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
async clear() {
|
|
177
|
+
let cursor = "";
|
|
178
|
+
let complete = false;
|
|
179
|
+
const prefix = `${this.namespace}:`;
|
|
180
|
+
do {
|
|
181
|
+
const response = await this.store.list({
|
|
182
|
+
prefix,
|
|
183
|
+
cursor: cursor || void 0
|
|
184
|
+
});
|
|
185
|
+
cursor = response.cursor ?? "";
|
|
186
|
+
complete = response.list_complete;
|
|
187
|
+
if (response.keys.length > 0) {
|
|
188
|
+
await Promise.all(
|
|
189
|
+
response.keys.map((key) => {
|
|
190
|
+
return this.store.delete(key.name);
|
|
191
|
+
})
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
} while (!complete);
|
|
195
|
+
}
|
|
196
|
+
on(_event, _listener) {
|
|
197
|
+
return this;
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// src/utils/index.ts
|
|
202
|
+
var import_qs = __toESM(__require("qs"), 1);
|
|
203
|
+
var import_lodash_es3 = __require("lodash-es");
|
|
204
|
+
var import_json52 = __toESM(__require("json5"), 1);
|
|
205
|
+
|
|
206
|
+
// src/resources.ts
|
|
207
|
+
var import_lodash_es2 = __require("lodash-es");
|
|
208
|
+
|
|
201
209
|
// src/liquid/utils.ts
|
|
202
210
|
var import_liquidjs = __require("liquidjs");
|
|
203
211
|
|
|
@@ -653,18 +661,12 @@
|
|
|
653
661
|
}
|
|
654
662
|
return instance[prop];
|
|
655
663
|
}
|
|
656
|
-
// add additional properties to the loaded result
|
|
657
|
-
_transformResult(result) {
|
|
658
|
-
return result;
|
|
659
|
-
}
|
|
660
664
|
async _get(..._args) {
|
|
661
665
|
if (this._getter) {
|
|
662
666
|
const getter = this._getter.bind(
|
|
663
667
|
this
|
|
664
668
|
);
|
|
665
669
|
return Promise.resolve().then(getter).then((result) => {
|
|
666
|
-
return this._transformResult(result);
|
|
667
|
-
}).then((result) => {
|
|
668
670
|
this._result = result ?? null;
|
|
669
671
|
if (result) {
|
|
670
672
|
Object.assign(this, result);
|
|
@@ -747,7 +749,6 @@
|
|
|
747
749
|
});
|
|
748
750
|
const clone = new ClonedClass(input._getter);
|
|
749
751
|
clone._params = input._params;
|
|
750
|
-
clone._transformResult = input._transformResult.bind(clone);
|
|
751
752
|
Object.defineProperty(clone, "_resourceName", {
|
|
752
753
|
value: resourceName
|
|
753
754
|
});
|
|
@@ -801,7 +802,11 @@
|
|
|
801
802
|
limit = DEFAULT_QUERY_PAGE_LIMIT;
|
|
802
803
|
name;
|
|
803
804
|
constructor(swell, collection, query = {}, getter) {
|
|
804
|
-
super(
|
|
805
|
+
super(
|
|
806
|
+
swell,
|
|
807
|
+
collection,
|
|
808
|
+
getter
|
|
809
|
+
);
|
|
805
810
|
this._query = this._initQuery(query);
|
|
806
811
|
if (!getter) {
|
|
807
812
|
this._setGetter(this._defaultGetter());
|
|
@@ -844,6 +849,7 @@
|
|
|
844
849
|
this._collection,
|
|
845
850
|
this._query,
|
|
846
851
|
this._swell.queryParams,
|
|
852
|
+
// TODO: consider to exlcude
|
|
847
853
|
this._getterHash
|
|
848
854
|
],
|
|
849
855
|
getter,
|
|
@@ -972,13 +978,12 @@
|
|
|
972
978
|
this._id,
|
|
973
979
|
this._query,
|
|
974
980
|
this._swell.queryParams,
|
|
981
|
+
// TODO: consider to exlcude
|
|
975
982
|
this._getterHash
|
|
976
983
|
],
|
|
977
984
|
getter,
|
|
978
985
|
isResourceCacheble(this._collection)
|
|
979
986
|
).then((result) => {
|
|
980
|
-
return this._transformResult(result);
|
|
981
|
-
}).then((result) => {
|
|
982
987
|
this._result = result;
|
|
983
988
|
if (result) {
|
|
984
989
|
Object.assign(this, result);
|
|
@@ -7202,8 +7207,6 @@
|
|
|
7202
7207
|
* This will always return the cached value immediately if exists
|
|
7203
7208
|
*/
|
|
7204
7209
|
async fetchSWR(key, fetchFn, ttl = DEFAULT_SWR_TTL, isCacheble = true) {
|
|
7205
|
-
const trace = createTraceId();
|
|
7206
|
-
logger.debug("[SDK] Cache fetch start", { key, trace });
|
|
7207
7210
|
const cacheValue = isCacheble ? await this.client.get(key) : void 0;
|
|
7208
7211
|
let promise = SWR_PROMISE_MAP.get(key);
|
|
7209
7212
|
if (promise === void 0) {
|
|
@@ -7211,7 +7214,6 @@
|
|
|
7211
7214
|
const isNull = value === null || value === void 0;
|
|
7212
7215
|
if (isCacheble) {
|
|
7213
7216
|
await this.client.set(key, isNull ? NULL_VALUE : value, ttl);
|
|
7214
|
-
logger.debug("[SDK] Cache update done", { key, trace });
|
|
7215
7217
|
}
|
|
7216
7218
|
return value;
|
|
7217
7219
|
}).finally(() => {
|
|
@@ -7223,12 +7225,9 @@
|
|
|
7223
7225
|
this.workerCtx.waitUntil(promise);
|
|
7224
7226
|
}
|
|
7225
7227
|
if (cacheValue !== void 0) {
|
|
7226
|
-
logger.debug("[SDK] Cache check done", { status: "HIT", key, trace });
|
|
7227
7228
|
return cacheValue === NULL_VALUE ? null : cacheValue;
|
|
7228
7229
|
}
|
|
7229
|
-
logger.debug("[SDK] Cache check done", { status: "MISS", key, trace });
|
|
7230
7230
|
const result = await promise;
|
|
7231
|
-
logger.debug("[SDK] Cache fetch end", { key, trace });
|
|
7232
7231
|
return result;
|
|
7233
7232
|
}
|
|
7234
7233
|
async get(key) {
|
|
@@ -7735,59 +7734,466 @@
|
|
|
7735
7734
|
}
|
|
7736
7735
|
};
|
|
7737
7736
|
|
|
7737
|
+
// src/cache/worker-html-cache.ts
|
|
7738
|
+
var CACHE_NAME2 = "swell-html-v1";
|
|
7739
|
+
var CACHE_KEY_ORIGIN2 = "https://cache.swell.store";
|
|
7740
|
+
var TTL_CONFIG = {
|
|
7741
|
+
DEFAULT: 300,
|
|
7742
|
+
// 5 minutes
|
|
7743
|
+
DEFAULT_SWR: 3600,
|
|
7744
|
+
// 1 hour stale-while-revalidate
|
|
7745
|
+
HOME: 300,
|
|
7746
|
+
// 5 minutes
|
|
7747
|
+
PRODUCT: 600,
|
|
7748
|
+
// 10 minutes
|
|
7749
|
+
COLLECTION: 900,
|
|
7750
|
+
// 15 minutes
|
|
7751
|
+
PAGE: 3600,
|
|
7752
|
+
// 1 hour
|
|
7753
|
+
BLOG: 1800
|
|
7754
|
+
// 30 minutes
|
|
7755
|
+
};
|
|
7756
|
+
var WorkerHtmlCache = class {
|
|
7757
|
+
epoch;
|
|
7758
|
+
constructor(epoch) {
|
|
7759
|
+
this.epoch = epoch;
|
|
7760
|
+
}
|
|
7761
|
+
async get(request) {
|
|
7762
|
+
const trace = createTraceId();
|
|
7763
|
+
if (request.method !== "GET") {
|
|
7764
|
+
logger.debug("[SDK Html-cache] non-cacheable", { trace });
|
|
7765
|
+
return { found: false, cacheable: false };
|
|
7766
|
+
}
|
|
7767
|
+
if (!this.isCacheable(request)) {
|
|
7768
|
+
logger.debug("[SDK Html-cache] non-cacheable", { trace });
|
|
7769
|
+
return { found: false, cacheable: false };
|
|
7770
|
+
}
|
|
7771
|
+
try {
|
|
7772
|
+
const cache = await caches.open(CACHE_NAME2 + this.epoch);
|
|
7773
|
+
const cacheKey = this.buildCacheKey(request);
|
|
7774
|
+
const cached = await cache.match(cacheKey);
|
|
7775
|
+
if (!cached) {
|
|
7776
|
+
logger.debug("[SDK Html-cache] cacheable, MISS", { trace });
|
|
7777
|
+
return { found: false, cacheable: true };
|
|
7778
|
+
}
|
|
7779
|
+
const age = this.getResponseAge(cached);
|
|
7780
|
+
const ttl = parseInt(cached.headers.get("X-Original-TTL") || "") || this.getTTLForRequest(request);
|
|
7781
|
+
const swr = parseInt(cached.headers.get("X-Original-SWR") || "") || TTL_CONFIG.DEFAULT_SWR;
|
|
7782
|
+
const isStale = age >= ttl;
|
|
7783
|
+
const isExpired = age >= ttl + swr;
|
|
7784
|
+
if (!isExpired) {
|
|
7785
|
+
logger.debug("[SDK Html-cache] cacheable, HIT", {
|
|
7786
|
+
stale: isStale,
|
|
7787
|
+
age,
|
|
7788
|
+
trace
|
|
7789
|
+
});
|
|
7790
|
+
const clientResponse = this.buildClientResponse(
|
|
7791
|
+
cached,
|
|
7792
|
+
ttl,
|
|
7793
|
+
swr,
|
|
7794
|
+
isStale,
|
|
7795
|
+
age
|
|
7796
|
+
);
|
|
7797
|
+
return {
|
|
7798
|
+
found: true,
|
|
7799
|
+
stale: isStale,
|
|
7800
|
+
response: clientResponse,
|
|
7801
|
+
cacheable: true,
|
|
7802
|
+
age: Math.floor(age)
|
|
7803
|
+
};
|
|
7804
|
+
}
|
|
7805
|
+
logger.debug("[SDK Html-cache] cacheable, hit, expired", { trace });
|
|
7806
|
+
return { found: false, cacheable: true };
|
|
7807
|
+
} catch (_) {
|
|
7808
|
+
logger.warn("[SDK Html-cache] no get support", { trace });
|
|
7809
|
+
return null;
|
|
7810
|
+
}
|
|
7811
|
+
}
|
|
7812
|
+
async put(request, response) {
|
|
7813
|
+
const trace = createTraceId();
|
|
7814
|
+
if (request.method !== "GET" || !response.ok) {
|
|
7815
|
+
logger.debug("[SDK Html-cache] put skipped", { trace });
|
|
7816
|
+
return;
|
|
7817
|
+
}
|
|
7818
|
+
if (!this.isCacheable(request) || !this.isResponseCacheable(response)) {
|
|
7819
|
+
logger.debug("[SDK Html-cache] put skipped, non-cacheable", {
|
|
7820
|
+
trace
|
|
7821
|
+
});
|
|
7822
|
+
return;
|
|
7823
|
+
}
|
|
7824
|
+
try {
|
|
7825
|
+
const cache = await caches.open(CACHE_NAME2 + this.epoch);
|
|
7826
|
+
const cacheKey = this.buildCacheKey(request);
|
|
7827
|
+
const ttl = this.getTTLForRequest(request);
|
|
7828
|
+
const swr = TTL_CONFIG.DEFAULT_SWR;
|
|
7829
|
+
const headers = new Headers(response.headers);
|
|
7830
|
+
const existingCacheControl = response.headers.get("Cache-Control");
|
|
7831
|
+
if (!existingCacheControl || existingCacheControl === "public") {
|
|
7832
|
+
const internalMaxAge = ttl + swr;
|
|
7833
|
+
headers.set("Cache-Control", `public, max-age=${internalMaxAge}`);
|
|
7834
|
+
}
|
|
7835
|
+
headers.set("X-Cache-Time", (/* @__PURE__ */ new Date()).toISOString());
|
|
7836
|
+
headers.set("X-Original-TTL", ttl.toString());
|
|
7837
|
+
headers.set("X-Original-SWR", swr.toString());
|
|
7838
|
+
const cacheableResponse = new Response(response.body, {
|
|
7839
|
+
status: response.status,
|
|
7840
|
+
statusText: response.statusText,
|
|
7841
|
+
headers
|
|
7842
|
+
});
|
|
7843
|
+
await cache.put(cacheKey, cacheableResponse);
|
|
7844
|
+
logger.debug("[SDK Html-cache] put done", { trace });
|
|
7845
|
+
} catch (_) {
|
|
7846
|
+
logger.warn("[SDK Html-cache] no put support", { trace });
|
|
7847
|
+
}
|
|
7848
|
+
}
|
|
7849
|
+
/**
|
|
7850
|
+
* Build client response with correct headers
|
|
7851
|
+
*/
|
|
7852
|
+
buildClientResponse(cachedResponse, ttl, swr, isStale, age) {
|
|
7853
|
+
const headers = new Headers(cachedResponse.headers);
|
|
7854
|
+
headers.set(
|
|
7855
|
+
"Cache-Control",
|
|
7856
|
+
`public, max-age=${ttl}, stale-while-revalidate=${swr}`
|
|
7857
|
+
);
|
|
7858
|
+
headers.set("X-Cache-Status", isStale ? "STALE" : "HIT");
|
|
7859
|
+
headers.set("X-Cache-Age", Math.floor(age).toString());
|
|
7860
|
+
headers.delete("X-Original-TTL");
|
|
7861
|
+
headers.delete("X-Original-SWR");
|
|
7862
|
+
return new Response(cachedResponse.body, {
|
|
7863
|
+
status: cachedResponse.status,
|
|
7864
|
+
statusText: cachedResponse.statusText,
|
|
7865
|
+
headers
|
|
7866
|
+
});
|
|
7867
|
+
}
|
|
7868
|
+
/**
|
|
7869
|
+
* Build cache key from request using two-level structure
|
|
7870
|
+
*/
|
|
7871
|
+
buildCacheKey(request) {
|
|
7872
|
+
const url = new URL(request.url);
|
|
7873
|
+
const versionHash = this.generateVersionHash(request.headers);
|
|
7874
|
+
const normalizedQuery = this.normalizeSearchParams(url.searchParams);
|
|
7875
|
+
const cacheKeyPath = `${versionHash}${url.pathname}`;
|
|
7876
|
+
const keyUrl = new URL(`${CACHE_KEY_ORIGIN2}${cacheKeyPath}`);
|
|
7877
|
+
if (normalizedQuery) {
|
|
7878
|
+
keyUrl.search = `?${normalizedQuery}`;
|
|
7879
|
+
}
|
|
7880
|
+
const sanitizedHeaders = this.sanitizeHeaders(request.headers);
|
|
7881
|
+
return new Request(keyUrl.toString(), {
|
|
7882
|
+
method: "GET",
|
|
7883
|
+
headers: sanitizedHeaders
|
|
7884
|
+
});
|
|
7885
|
+
}
|
|
7886
|
+
/**
|
|
7887
|
+
* Sanitize headers for cache operations - minimal whitelist approach
|
|
7888
|
+
*/
|
|
7889
|
+
sanitizeHeaders(originalHeaders) {
|
|
7890
|
+
const CACHE_RELEVANT_HEADERS = [
|
|
7891
|
+
// Content negotiation (affects response format)
|
|
7892
|
+
"accept",
|
|
7893
|
+
"accept-encoding",
|
|
7894
|
+
"accept-language",
|
|
7895
|
+
// Cache control directives from client/proxy
|
|
7896
|
+
"cache-control",
|
|
7897
|
+
"pragma",
|
|
7898
|
+
// Legacy cache control
|
|
7899
|
+
// Conditional request headers (for 304 responses)
|
|
7900
|
+
"if-none-match",
|
|
7901
|
+
"if-modified-since"
|
|
7902
|
+
];
|
|
7903
|
+
const sanitized = new Headers();
|
|
7904
|
+
CACHE_RELEVANT_HEADERS.forEach((header) => {
|
|
7905
|
+
const value = originalHeaders.get(header);
|
|
7906
|
+
if (value) {
|
|
7907
|
+
sanitized.set(header, value);
|
|
7908
|
+
}
|
|
7909
|
+
});
|
|
7910
|
+
return sanitized;
|
|
7911
|
+
}
|
|
7912
|
+
/**
|
|
7913
|
+
* Generate version hash from headers and cookies
|
|
7914
|
+
*/
|
|
7915
|
+
generateVersionHash(headers) {
|
|
7916
|
+
const swellData = this.extractSwellData(headers);
|
|
7917
|
+
const versionFactors = {
|
|
7918
|
+
store: headers.get("swell-storefront-id") || "",
|
|
7919
|
+
auth: headers.get("swell-access-token") || "",
|
|
7920
|
+
theme: headers.get("swell-theme-version-hash") || "",
|
|
7921
|
+
currency: swellData["swell-currency"] || "USD",
|
|
7922
|
+
locale: headers.get("x-locale") || headers.get("accept-language")?.split(",")[0] || "default",
|
|
7923
|
+
context: headers.get("swell-storefront-context"),
|
|
7924
|
+
epoch: this.epoch
|
|
7925
|
+
};
|
|
7926
|
+
return md5(JSON.stringify(versionFactors));
|
|
7927
|
+
}
|
|
7928
|
+
/**
|
|
7929
|
+
* Extract swell-data from cookies
|
|
7930
|
+
*/
|
|
7931
|
+
extractSwellData(headers) {
|
|
7932
|
+
const cookie = headers.get("cookie");
|
|
7933
|
+
if (!cookie) return {};
|
|
7934
|
+
const swellDataMatch = cookie.match(/swell-data=([^;]+)/);
|
|
7935
|
+
if (!swellDataMatch) return {};
|
|
7936
|
+
try {
|
|
7937
|
+
const parsed = JSON.parse(decodeURIComponent(swellDataMatch[1]));
|
|
7938
|
+
if (typeof parsed === "object" && parsed !== null) {
|
|
7939
|
+
return parsed;
|
|
7940
|
+
}
|
|
7941
|
+
return {};
|
|
7942
|
+
} catch {
|
|
7943
|
+
return {};
|
|
7944
|
+
}
|
|
7945
|
+
}
|
|
7946
|
+
isCacheable(request) {
|
|
7947
|
+
const url = new URL(request.url);
|
|
7948
|
+
const headers = request.headers;
|
|
7949
|
+
if (headers.get("swell-deployment-mode") === "editor") {
|
|
7950
|
+
return false;
|
|
7951
|
+
}
|
|
7952
|
+
const skipPaths = ["/checkout"];
|
|
7953
|
+
if (skipPaths.some((path) => url.pathname.startsWith(path))) {
|
|
7954
|
+
return false;
|
|
7955
|
+
}
|
|
7956
|
+
if (headers.get("cache-control")?.includes("no-cache")) {
|
|
7957
|
+
return false;
|
|
7958
|
+
}
|
|
7959
|
+
return true;
|
|
7960
|
+
}
|
|
7961
|
+
isResponseCacheable(response) {
|
|
7962
|
+
const contentType = response.headers.get("content-type");
|
|
7963
|
+
if (!contentType?.includes("text/html")) {
|
|
7964
|
+
return false;
|
|
7965
|
+
}
|
|
7966
|
+
const cacheControl = response.headers.get("cache-control");
|
|
7967
|
+
if (cacheControl?.includes("no-store") || cacheControl?.includes("private")) {
|
|
7968
|
+
return false;
|
|
7969
|
+
}
|
|
7970
|
+
return true;
|
|
7971
|
+
}
|
|
7972
|
+
getTTLForRequest(request) {
|
|
7973
|
+
const url = new URL(request.url);
|
|
7974
|
+
const path = url.pathname;
|
|
7975
|
+
if (path === "/") {
|
|
7976
|
+
return TTL_CONFIG.HOME;
|
|
7977
|
+
}
|
|
7978
|
+
if (path.startsWith("/products/")) {
|
|
7979
|
+
return TTL_CONFIG.PRODUCT;
|
|
7980
|
+
}
|
|
7981
|
+
if (path.startsWith("/categories/")) {
|
|
7982
|
+
return TTL_CONFIG.COLLECTION;
|
|
7983
|
+
}
|
|
7984
|
+
if (path.startsWith("/pages/")) {
|
|
7985
|
+
return TTL_CONFIG.PAGE;
|
|
7986
|
+
}
|
|
7987
|
+
if (path.startsWith("/blogs/")) {
|
|
7988
|
+
return TTL_CONFIG.BLOG;
|
|
7989
|
+
}
|
|
7990
|
+
return TTL_CONFIG.DEFAULT;
|
|
7991
|
+
}
|
|
7992
|
+
getResponseAge(response) {
|
|
7993
|
+
const cacheTime = response.headers.get("X-Cache-Time");
|
|
7994
|
+
if (!cacheTime) {
|
|
7995
|
+
return Infinity;
|
|
7996
|
+
}
|
|
7997
|
+
const cacheDate = new Date(cacheTime);
|
|
7998
|
+
if (isNaN(cacheDate.getTime())) {
|
|
7999
|
+
return Infinity;
|
|
8000
|
+
}
|
|
8001
|
+
const age = (Date.now() - cacheDate.getTime()) / 1e3;
|
|
8002
|
+
return Math.max(0, age);
|
|
8003
|
+
}
|
|
8004
|
+
getMaxAge(response) {
|
|
8005
|
+
const cacheControl = response.headers.get("Cache-Control");
|
|
8006
|
+
if (!cacheControl) {
|
|
8007
|
+
return TTL_CONFIG.DEFAULT;
|
|
8008
|
+
}
|
|
8009
|
+
const maxAgeMatch = cacheControl.match(/max-age=(\d+)/);
|
|
8010
|
+
if (maxAgeMatch) {
|
|
8011
|
+
return parseInt(maxAgeMatch[1], 10);
|
|
8012
|
+
}
|
|
8013
|
+
return TTL_CONFIG.DEFAULT;
|
|
8014
|
+
}
|
|
8015
|
+
getStaleWindow(response) {
|
|
8016
|
+
const cacheControl = response.headers.get("Cache-Control");
|
|
8017
|
+
if (!cacheControl) {
|
|
8018
|
+
return TTL_CONFIG.DEFAULT_SWR;
|
|
8019
|
+
}
|
|
8020
|
+
const swrMatch = cacheControl.match(/stale-while-revalidate=(\d+)/);
|
|
8021
|
+
if (swrMatch) {
|
|
8022
|
+
return parseInt(swrMatch[1], 10);
|
|
8023
|
+
}
|
|
8024
|
+
return TTL_CONFIG.DEFAULT_SWR;
|
|
8025
|
+
}
|
|
8026
|
+
/**
|
|
8027
|
+
* Normalize search params for cache key
|
|
8028
|
+
*/
|
|
8029
|
+
normalizeSearchParams(searchParams) {
|
|
8030
|
+
const ignoredParams = [
|
|
8031
|
+
"utm_source",
|
|
8032
|
+
"utm_medium",
|
|
8033
|
+
"utm_campaign",
|
|
8034
|
+
"utm_content",
|
|
8035
|
+
"utm_term",
|
|
8036
|
+
"fbclid",
|
|
8037
|
+
"gclid",
|
|
8038
|
+
"gbraid",
|
|
8039
|
+
"wbraid",
|
|
8040
|
+
"ref",
|
|
8041
|
+
"source",
|
|
8042
|
+
"mc_cid",
|
|
8043
|
+
"mc_eid"
|
|
8044
|
+
];
|
|
8045
|
+
const relevantParams = [];
|
|
8046
|
+
searchParams.forEach((value, key) => {
|
|
8047
|
+
if (!ignoredParams.includes(key)) {
|
|
8048
|
+
relevantParams.push(
|
|
8049
|
+
`${encodeURIComponent(key)}=${encodeURIComponent(value)}`
|
|
8050
|
+
);
|
|
8051
|
+
}
|
|
8052
|
+
});
|
|
8053
|
+
return relevantParams.sort().join("&");
|
|
8054
|
+
}
|
|
8055
|
+
};
|
|
8056
|
+
|
|
8057
|
+
// src/resources/addresses.ts
|
|
8058
|
+
var SwellAddresses = class extends SwellStorefrontCollection {
|
|
8059
|
+
constructor(swell, query) {
|
|
8060
|
+
const { page, limit: limit2 } = swell.queryParams;
|
|
8061
|
+
super(swell, "accounts:addresses", { page, limit: limit2, ...query }, function() {
|
|
8062
|
+
return this._swell.storefront.account.listAddresses(
|
|
8063
|
+
this._query
|
|
8064
|
+
);
|
|
8065
|
+
});
|
|
8066
|
+
}
|
|
8067
|
+
};
|
|
8068
|
+
|
|
8069
|
+
// src/resources/orders.ts
|
|
8070
|
+
var SwellOrders = class extends SwellStorefrontCollection {
|
|
8071
|
+
constructor(swell, query) {
|
|
8072
|
+
const { page, limit: limit2 } = swell.queryParams;
|
|
8073
|
+
super(swell, "accounts:orders", { page, limit: limit2, ...query }, function() {
|
|
8074
|
+
return this._swell.storefront.account.listOrders(this._query);
|
|
8075
|
+
});
|
|
8076
|
+
}
|
|
8077
|
+
};
|
|
8078
|
+
|
|
8079
|
+
// src/resources/subscriptions.ts
|
|
8080
|
+
var SwellSubscriptions = class extends SwellStorefrontCollection {
|
|
8081
|
+
constructor(swell, query) {
|
|
8082
|
+
const { page, limit: limit2 } = swell.queryParams;
|
|
8083
|
+
super(
|
|
8084
|
+
swell,
|
|
8085
|
+
"accounts:subscriptions",
|
|
8086
|
+
{ page, limit: limit2, ...query },
|
|
8087
|
+
function() {
|
|
8088
|
+
return this._swell.storefront.subscriptions.list(
|
|
8089
|
+
this._query
|
|
8090
|
+
);
|
|
8091
|
+
}
|
|
8092
|
+
);
|
|
8093
|
+
}
|
|
8094
|
+
};
|
|
8095
|
+
|
|
7738
8096
|
// src/resources/account.ts
|
|
7739
8097
|
var SwellAccount = class extends SwellStorefrontSingleton {
|
|
7740
|
-
constructor(swell
|
|
7741
|
-
super(swell, "account",
|
|
8098
|
+
constructor(swell) {
|
|
8099
|
+
super(swell, "account", async function() {
|
|
8100
|
+
const account = await this._defaultGetter().call(this);
|
|
8101
|
+
if (!account) {
|
|
8102
|
+
return null;
|
|
8103
|
+
}
|
|
8104
|
+
account.addresses = new SwellAddresses(
|
|
8105
|
+
this._swell
|
|
8106
|
+
);
|
|
8107
|
+
account.orders = new SwellOrders(
|
|
8108
|
+
this._swell
|
|
8109
|
+
);
|
|
8110
|
+
account.subscriptions = new SwellSubscriptions(
|
|
8111
|
+
this._swell
|
|
8112
|
+
);
|
|
8113
|
+
return account;
|
|
8114
|
+
});
|
|
7742
8115
|
return this._getProxy();
|
|
7743
8116
|
}
|
|
7744
8117
|
};
|
|
7745
8118
|
|
|
7746
8119
|
// src/resources/blog_category.ts
|
|
7747
8120
|
var SwellBlogCategory = class extends SwellStorefrontRecord {
|
|
7748
|
-
constructor(swell, id, query
|
|
7749
|
-
super(swell, "content/blog-categories", id, query,
|
|
8121
|
+
constructor(swell, id, query) {
|
|
8122
|
+
super(swell, "content/blog-categories", id, query, async function() {
|
|
8123
|
+
const category = await this._defaultGetter().call(this);
|
|
8124
|
+
if (!category) {
|
|
8125
|
+
return null;
|
|
8126
|
+
}
|
|
8127
|
+
category.blogs = new SwellStorefrontCollection(
|
|
8128
|
+
this._swell,
|
|
8129
|
+
"content/blogs",
|
|
8130
|
+
{
|
|
8131
|
+
category_id: category.id,
|
|
8132
|
+
expand: "author"
|
|
8133
|
+
}
|
|
8134
|
+
);
|
|
8135
|
+
return category;
|
|
8136
|
+
});
|
|
7750
8137
|
return this._getProxy();
|
|
7751
8138
|
}
|
|
7752
8139
|
};
|
|
7753
8140
|
|
|
7754
8141
|
// src/resources/blog.ts
|
|
7755
8142
|
var SwellBlog = class extends SwellStorefrontRecord {
|
|
7756
|
-
constructor(swell,
|
|
7757
|
-
super(swell, "content/blogs",
|
|
8143
|
+
constructor(swell, blogId, categoryId, query) {
|
|
8144
|
+
super(swell, "content/blogs", blogId, query, async function() {
|
|
8145
|
+
this._query = { ...this._query, expand: "author" };
|
|
8146
|
+
const blog = await this._defaultGetter().call(this);
|
|
8147
|
+
if (!blog) {
|
|
8148
|
+
return null;
|
|
8149
|
+
}
|
|
8150
|
+
if (categoryId) {
|
|
8151
|
+
blog.category = new SwellStorefrontRecord(
|
|
8152
|
+
this._swell,
|
|
8153
|
+
"content/blog-categories",
|
|
8154
|
+
categoryId
|
|
8155
|
+
);
|
|
8156
|
+
}
|
|
8157
|
+
return blog;
|
|
8158
|
+
});
|
|
7758
8159
|
return this._getProxy();
|
|
7759
8160
|
}
|
|
7760
8161
|
};
|
|
7761
8162
|
|
|
7762
8163
|
// src/resources/cart.ts
|
|
7763
8164
|
var SwellCart = class extends SwellStorefrontSingleton {
|
|
7764
|
-
constructor(swell
|
|
7765
|
-
super(swell, "cart"
|
|
7766
|
-
return this._getProxy();
|
|
7767
|
-
}
|
|
7768
|
-
};
|
|
7769
|
-
|
|
7770
|
-
// src/resources/category.ts
|
|
7771
|
-
var SwellCategory = class extends SwellStorefrontRecord {
|
|
7772
|
-
constructor(swell, id, query = {}, getter) {
|
|
7773
|
-
super(swell, "categories", id, query, getter);
|
|
7774
|
-
return this._getProxy();
|
|
7775
|
-
}
|
|
7776
|
-
};
|
|
7777
|
-
|
|
7778
|
-
// src/resources/order.ts
|
|
7779
|
-
var SwellOrder = class extends SwellStorefrontRecord {
|
|
7780
|
-
constructor(swell, id, query = {}, getter) {
|
|
7781
|
-
super(swell, "orders", id, query, getter);
|
|
8165
|
+
constructor(swell) {
|
|
8166
|
+
super(swell, "cart");
|
|
7782
8167
|
return this._getProxy();
|
|
7783
8168
|
}
|
|
7784
8169
|
};
|
|
7785
8170
|
|
|
7786
|
-
// src/resources/
|
|
7787
|
-
var
|
|
7788
|
-
constructor(swell,
|
|
7789
|
-
super(
|
|
7790
|
-
|
|
8171
|
+
// src/resources/categories.ts
|
|
8172
|
+
var SwellCategories = class extends SwellStorefrontCollection {
|
|
8173
|
+
constructor(swell, query) {
|
|
8174
|
+
super(
|
|
8175
|
+
swell,
|
|
8176
|
+
"categories",
|
|
8177
|
+
{
|
|
8178
|
+
limit: 100,
|
|
8179
|
+
top_id: null,
|
|
8180
|
+
...query
|
|
8181
|
+
},
|
|
8182
|
+
async function() {
|
|
8183
|
+
const categories = await this._defaultGetter().call(this);
|
|
8184
|
+
if (!categories) {
|
|
8185
|
+
return null;
|
|
8186
|
+
}
|
|
8187
|
+
for (const category of categories.results) {
|
|
8188
|
+
category.products = new SwellStorefrontCollection(
|
|
8189
|
+
this._swell,
|
|
8190
|
+
"products",
|
|
8191
|
+
{ category: category.id }
|
|
8192
|
+
);
|
|
8193
|
+
}
|
|
8194
|
+
return categories;
|
|
8195
|
+
}
|
|
8196
|
+
);
|
|
7791
8197
|
}
|
|
7792
8198
|
};
|
|
7793
8199
|
|
|
@@ -7947,6 +8353,143 @@
|
|
|
7947
8353
|
}
|
|
7948
8354
|
return selectedPlan || subscriptionPurchaseOption.plans[0];
|
|
7949
8355
|
}
|
|
8356
|
+
var SORT_OPTIONS = Object.freeze([
|
|
8357
|
+
{ value: "", name: "Featured" },
|
|
8358
|
+
{ value: "popularity", name: "Popularity", query: "popularity desc" },
|
|
8359
|
+
{ value: "price_asc", name: "Price, low to high", query: "price asc" },
|
|
8360
|
+
{ value: "price_desc", name: "Price, high to low", query: "price desc" },
|
|
8361
|
+
{ value: "date_asc", name: "Date, old to new", query: "date asc" },
|
|
8362
|
+
{ value: "date_desc", name: "Date, new to old", query: "date desc" },
|
|
8363
|
+
{ value: "name_asc", name: "Product name, A-Z", query: "name asc" },
|
|
8364
|
+
{ value: "name_desc", name: "Product name, Z-A", query: "name desc" }
|
|
8365
|
+
]);
|
|
8366
|
+
async function getProductFilters(swell, productQuery) {
|
|
8367
|
+
const sortBy = swell.queryParams.sort || "";
|
|
8368
|
+
const filterQuery = productQueryWithFilters(swell, productQuery);
|
|
8369
|
+
return {
|
|
8370
|
+
filter_options: await getProductFiltersByQuery(swell, filterQuery),
|
|
8371
|
+
sort: SORT_OPTIONS.find((option) => option.value === sortBy)?.value,
|
|
8372
|
+
sort_options: [...SORT_OPTIONS]
|
|
8373
|
+
};
|
|
8374
|
+
}
|
|
8375
|
+
async function getProductFiltersByQuery(swell, query = {}) {
|
|
8376
|
+
const filters2 = await swell.get("/products/:filters", {
|
|
8377
|
+
...query,
|
|
8378
|
+
sort: void 0
|
|
8379
|
+
}) || [];
|
|
8380
|
+
if (!Array.isArray(filters2)) {
|
|
8381
|
+
throw new Error("Product filters must be an array");
|
|
8382
|
+
}
|
|
8383
|
+
for (const filter of filters2) {
|
|
8384
|
+
filter.param_name = `filter_${filter.id}`;
|
|
8385
|
+
if (Array.isArray(filter.options)) {
|
|
8386
|
+
filter.active_options = [];
|
|
8387
|
+
filter.inactive_options = [];
|
|
8388
|
+
for (const option of filter.options) {
|
|
8389
|
+
const queryValue = swell.queryParams[filter.param_name];
|
|
8390
|
+
option.active = Array.isArray(queryValue) ? queryValue.includes(option.value) : queryValue === option.value;
|
|
8391
|
+
const list = option.active ? filter.active_options : filter.inactive_options;
|
|
8392
|
+
list.push(option);
|
|
8393
|
+
}
|
|
8394
|
+
}
|
|
8395
|
+
}
|
|
8396
|
+
return filters2;
|
|
8397
|
+
}
|
|
8398
|
+
function productQueryWithFilters(swell, query) {
|
|
8399
|
+
const filters2 = Object.keys(swell.queryParams).reduce(
|
|
8400
|
+
(acc, key) => {
|
|
8401
|
+
if (key.startsWith("filter_")) {
|
|
8402
|
+
const qkey = key.replace("filter_", "");
|
|
8403
|
+
const value = swell.queryParams[key];
|
|
8404
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value) && (value.gte !== void 0 || value.lte !== void 0)) {
|
|
8405
|
+
acc[qkey] = [value.gte || 0, value.lte || void 0];
|
|
8406
|
+
} else {
|
|
8407
|
+
acc[qkey] = value;
|
|
8408
|
+
}
|
|
8409
|
+
}
|
|
8410
|
+
return acc;
|
|
8411
|
+
},
|
|
8412
|
+
{}
|
|
8413
|
+
);
|
|
8414
|
+
const sortBy = swell.queryParams.sort || "";
|
|
8415
|
+
return {
|
|
8416
|
+
sort: SORT_OPTIONS.find((option) => option.value === sortBy)?.query || void 0,
|
|
8417
|
+
$filters: filters2,
|
|
8418
|
+
...query
|
|
8419
|
+
};
|
|
8420
|
+
}
|
|
8421
|
+
|
|
8422
|
+
// src/resources/category.ts
|
|
8423
|
+
var SwellCategory = class extends SwellStorefrontRecord {
|
|
8424
|
+
constructor(swell, id, query) {
|
|
8425
|
+
super(swell, "categories", id, query, async function() {
|
|
8426
|
+
let category = await this._defaultGetter().call(this);
|
|
8427
|
+
if (!category && this._id === "all") {
|
|
8428
|
+
category = {
|
|
8429
|
+
name: "Products",
|
|
8430
|
+
id: "all",
|
|
8431
|
+
slug: "all",
|
|
8432
|
+
filter_options: [],
|
|
8433
|
+
sort_options: []
|
|
8434
|
+
};
|
|
8435
|
+
}
|
|
8436
|
+
if (!category) {
|
|
8437
|
+
return null;
|
|
8438
|
+
}
|
|
8439
|
+
const productFilters = await getProductFilters(
|
|
8440
|
+
this._swell,
|
|
8441
|
+
category.id !== "all" ? { category: category.id, $variants: true } : { $variants: true }
|
|
8442
|
+
);
|
|
8443
|
+
Object.assign(category, productFilters);
|
|
8444
|
+
return category;
|
|
8445
|
+
});
|
|
8446
|
+
return this._getProxy();
|
|
8447
|
+
}
|
|
8448
|
+
};
|
|
8449
|
+
|
|
8450
|
+
// src/resources/order.ts
|
|
8451
|
+
var SwellOrder = class extends SwellStorefrontRecord {
|
|
8452
|
+
constructor(swell, id, query) {
|
|
8453
|
+
super(swell, "accounts:orders", id, query, function() {
|
|
8454
|
+
return this._swell.storefront.account.getOrder(this._id);
|
|
8455
|
+
});
|
|
8456
|
+
return this._getProxy();
|
|
8457
|
+
}
|
|
8458
|
+
};
|
|
8459
|
+
|
|
8460
|
+
// src/resources/page.ts
|
|
8461
|
+
var SwellPage = class extends SwellStorefrontRecord {
|
|
8462
|
+
constructor(swell, id, query) {
|
|
8463
|
+
super(swell, "content/pages", id, query);
|
|
8464
|
+
return this._getProxy();
|
|
8465
|
+
}
|
|
8466
|
+
};
|
|
8467
|
+
|
|
8468
|
+
// src/resources/predictive_search.ts
|
|
8469
|
+
var SwellPredictiveSearch = class extends StorefrontResource {
|
|
8470
|
+
constructor(swell, query) {
|
|
8471
|
+
super(async function() {
|
|
8472
|
+
const performed = String(query || "").length > 0;
|
|
8473
|
+
let products;
|
|
8474
|
+
if (performed) {
|
|
8475
|
+
products = new SwellStorefrontCollection(
|
|
8476
|
+
swell,
|
|
8477
|
+
"products",
|
|
8478
|
+
{
|
|
8479
|
+
search: query,
|
|
8480
|
+
limit: 10
|
|
8481
|
+
}
|
|
8482
|
+
);
|
|
8483
|
+
await products.resolve();
|
|
8484
|
+
}
|
|
8485
|
+
return {
|
|
8486
|
+
query,
|
|
8487
|
+
performed,
|
|
8488
|
+
products
|
|
8489
|
+
};
|
|
8490
|
+
});
|
|
8491
|
+
}
|
|
8492
|
+
};
|
|
7950
8493
|
|
|
7951
8494
|
// src/resources/variant.ts
|
|
7952
8495
|
function transformSwellVariant(params, product, variant) {
|
|
@@ -7966,27 +8509,30 @@
|
|
|
7966
8509
|
)
|
|
7967
8510
|
};
|
|
7968
8511
|
}
|
|
8512
|
+
var SwellVariant = class extends SwellStorefrontRecord {
|
|
8513
|
+
product;
|
|
8514
|
+
constructor(swell, product, id, query) {
|
|
8515
|
+
super(swell, "products:variants", id, query, async function() {
|
|
8516
|
+
const variant = await this._swell.get(
|
|
8517
|
+
"/products:variants/{id}",
|
|
8518
|
+
{ id: this._id }
|
|
8519
|
+
);
|
|
8520
|
+
return variant ?? null;
|
|
8521
|
+
});
|
|
8522
|
+
this.product = product;
|
|
8523
|
+
}
|
|
8524
|
+
};
|
|
7969
8525
|
|
|
7970
8526
|
// src/resources/product.ts
|
|
7971
|
-
var SORT_OPTIONS = [
|
|
7972
|
-
{ value: "", name: "Featured" },
|
|
7973
|
-
{ value: "popularity", name: "Popularity", query: "popularity desc" },
|
|
7974
|
-
{ value: "price_asc", name: "Price, low to high", query: "price asc" },
|
|
7975
|
-
{ value: "price_desc", name: "Price, high to low", query: "price desc" },
|
|
7976
|
-
{ value: "date_asc", name: "Date, old to new", query: "date asc" },
|
|
7977
|
-
{ value: "date_desc", name: "Date, new to old", query: "date desc" },
|
|
7978
|
-
{ value: "name_asc", name: "Product name, A-Z", query: "name asc" },
|
|
7979
|
-
{ value: "name_desc", name: "Product name, Z-A", query: "name desc" }
|
|
7980
|
-
];
|
|
7981
8527
|
function transformSwellProduct(params, product) {
|
|
7982
8528
|
if (!product) {
|
|
7983
|
-
return
|
|
8529
|
+
return null;
|
|
7984
8530
|
}
|
|
7985
8531
|
const newProduct = {
|
|
7986
8532
|
...product,
|
|
7987
8533
|
// add swell properties there
|
|
7988
8534
|
selected_option_values: getSelectedVariantOptionValues(product, params),
|
|
7989
|
-
purchase_options: getPurchaseOptions(product, params)
|
|
8535
|
+
purchase_options: getPurchaseOptions(product, params) ?? void 0
|
|
7990
8536
|
};
|
|
7991
8537
|
if (Array.isArray(newProduct.variants?.results)) {
|
|
7992
8538
|
newProduct.variants = {
|
|
@@ -7999,43 +8545,49 @@
|
|
|
7999
8545
|
return newProduct;
|
|
8000
8546
|
}
|
|
8001
8547
|
var SwellProduct = class extends SwellStorefrontRecord {
|
|
8002
|
-
|
|
8003
|
-
|
|
8004
|
-
super(swell, "products", id, query,
|
|
8005
|
-
|
|
8548
|
+
constructor(swell, id, query) {
|
|
8549
|
+
const params = swell.queryParams;
|
|
8550
|
+
super(swell, "products", id, query, async function() {
|
|
8551
|
+
const result = await this._defaultGetter().call(this);
|
|
8552
|
+
return transformSwellProduct(params, result);
|
|
8553
|
+
});
|
|
8006
8554
|
return this._getProxy();
|
|
8007
8555
|
}
|
|
8008
|
-
|
|
8009
|
-
|
|
8010
|
-
|
|
8011
|
-
|
|
8012
|
-
|
|
8013
|
-
);
|
|
8014
|
-
|
|
8556
|
+
};
|
|
8557
|
+
|
|
8558
|
+
// src/resources/product_recommendations.ts
|
|
8559
|
+
var SwellProductRecommendations = class extends SwellProduct {
|
|
8560
|
+
constructor(swell, id, query) {
|
|
8561
|
+
super(swell, id, { ...query, $recommendations: true });
|
|
8562
|
+
}
|
|
8563
|
+
};
|
|
8564
|
+
|
|
8565
|
+
// src/resources/search.ts
|
|
8566
|
+
var SwellSearch = class extends StorefrontResource {
|
|
8567
|
+
constructor(swell, query) {
|
|
8568
|
+
super(async () => {
|
|
8569
|
+
const performed = String(query || "").length > 0;
|
|
8570
|
+
const productFilters = await getProductFilters(
|
|
8571
|
+
swell,
|
|
8572
|
+
performed ? { search: query } : void 0
|
|
8573
|
+
);
|
|
8574
|
+
return {
|
|
8575
|
+
query,
|
|
8576
|
+
performed,
|
|
8577
|
+
...productFilters
|
|
8578
|
+
};
|
|
8579
|
+
});
|
|
8580
|
+
}
|
|
8581
|
+
};
|
|
8582
|
+
|
|
8583
|
+
// src/resources/subscription.ts
|
|
8584
|
+
var SwellSubscription = class extends SwellStorefrontRecord {
|
|
8585
|
+
constructor(swell, id, query) {
|
|
8586
|
+
super(swell, "accounts:subscriptions", id, query, function() {
|
|
8587
|
+
return this._swell.storefront.subscriptions.get(this._id, this._query);
|
|
8588
|
+
});
|
|
8015
8589
|
}
|
|
8016
8590
|
};
|
|
8017
|
-
function productQueryWithFilters(swell, query = {}) {
|
|
8018
|
-
const sortBy = swell.queryParams.sort || "";
|
|
8019
|
-
const filters2 = Object.entries(swell.queryParams).reduce(
|
|
8020
|
-
(acc, [key, value]) => {
|
|
8021
|
-
if (key.startsWith("filter_")) {
|
|
8022
|
-
const qkey = key.replace("filter_", "");
|
|
8023
|
-
if (value?.gte !== void 0 || value?.lte !== void 0) {
|
|
8024
|
-
acc[qkey] = [value.gte || 0, value.lte || void 0];
|
|
8025
|
-
} else {
|
|
8026
|
-
acc[qkey] = value;
|
|
8027
|
-
}
|
|
8028
|
-
}
|
|
8029
|
-
return acc;
|
|
8030
|
-
},
|
|
8031
|
-
{}
|
|
8032
|
-
);
|
|
8033
|
-
return {
|
|
8034
|
-
sort: SORT_OPTIONS.find((option) => option.value === sortBy)?.query || void 0,
|
|
8035
|
-
$filters: filters2,
|
|
8036
|
-
...query
|
|
8037
|
-
};
|
|
8038
|
-
}
|
|
8039
8591
|
|
|
8040
8592
|
// src/api.ts
|
|
8041
8593
|
var DEFAULT_API_HOST = "https://api.schema.io";
|
|
@@ -8329,13 +8881,19 @@
|
|
|
8329
8881
|
const storefrontRequest = storefront.request;
|
|
8330
8882
|
return (method, url, id, data, opt) => {
|
|
8331
8883
|
if (this.isStorefrontRequestCacheable(method, url, opt)) {
|
|
8332
|
-
|
|
8333
|
-
|
|
8334
|
-
|
|
8335
|
-
|
|
8336
|
-
|
|
8337
|
-
|
|
8338
|
-
|
|
8884
|
+
const key = getCacheKey("request", [
|
|
8885
|
+
this.instanceId,
|
|
8886
|
+
method,
|
|
8887
|
+
url,
|
|
8888
|
+
id,
|
|
8889
|
+
data,
|
|
8890
|
+
opt
|
|
8891
|
+
]);
|
|
8892
|
+
return this.getRequestCache().fetchSWR(key, () => {
|
|
8893
|
+
const requestUrl = id ? `${url}/${id}` : url;
|
|
8894
|
+
logger.debug("[SDK] Cacheable API request", { url: requestUrl, key });
|
|
8895
|
+
return storefrontRequest(method, url, id, data, opt);
|
|
8896
|
+
});
|
|
8339
8897
|
}
|
|
8340
8898
|
switch (method) {
|
|
8341
8899
|
case "delete":
|
|
@@ -8382,7 +8940,9 @@
|
|
|
8382
8940
|
};
|
|
8383
8941
|
function getCacheKey(key, args) {
|
|
8384
8942
|
if (Array.isArray(args) && args.length > 0) {
|
|
8385
|
-
|
|
8943
|
+
const fullKey = `${key}_${md5(JSON.stringify(args))}`;
|
|
8944
|
+
logger.debug(`[SDK] make cache key: ${fullKey}`);
|
|
8945
|
+
return fullKey;
|
|
8386
8946
|
}
|
|
8387
8947
|
return key;
|
|
8388
8948
|
}
|
|
@@ -15606,11 +16166,9 @@ ${formattedMessage}`;
|
|
|
15606
16166
|
return this._defaultGetter().call(this);
|
|
15607
16167
|
}
|
|
15608
16168
|
);
|
|
15609
|
-
return products._cloneWithCompatibilityResult(
|
|
15610
|
-
(
|
|
15611
|
-
|
|
15612
|
-
}
|
|
15613
|
-
);
|
|
16169
|
+
return products._cloneWithCompatibilityResult((products2) => {
|
|
16170
|
+
return { ...products2, results: products2.results.map(mapper) };
|
|
16171
|
+
});
|
|
15614
16172
|
});
|
|
15615
16173
|
}
|
|
15616
16174
|
function makeProductsCollectionResolve(instance, object, mapper) {
|
|
@@ -15627,19 +16185,24 @@ ${formattedMessage}`;
|
|
|
15627
16185
|
|
|
15628
16186
|
// src/compatibility/shopify-objects/collections.ts
|
|
15629
16187
|
function ShopifyCollections(instance, categories) {
|
|
15630
|
-
return new SwellStorefrontCollection(
|
|
15631
|
-
|
|
15632
|
-
|
|
15633
|
-
|
|
15634
|
-
|
|
15635
|
-
|
|
15636
|
-
|
|
15637
|
-
|
|
15638
|
-
|
|
15639
|
-
|
|
15640
|
-
|
|
15641
|
-
|
|
15642
|
-
|
|
16188
|
+
return new SwellStorefrontCollection(
|
|
16189
|
+
instance.swell,
|
|
16190
|
+
categories._collection,
|
|
16191
|
+
categories._query,
|
|
16192
|
+
async () => {
|
|
16193
|
+
const results = (await categories.results)?.map((category) => {
|
|
16194
|
+
return ShopifyCollection(instance, category);
|
|
16195
|
+
});
|
|
16196
|
+
return {
|
|
16197
|
+
page: categories.page ?? 1,
|
|
16198
|
+
count: categories.count ?? 0,
|
|
16199
|
+
results: results ?? [],
|
|
16200
|
+
page_count: categories.page_count ?? 0,
|
|
16201
|
+
limit: categories.limit,
|
|
16202
|
+
pages: categories.pages ?? {}
|
|
16203
|
+
};
|
|
16204
|
+
}
|
|
16205
|
+
);
|
|
15643
16206
|
}
|
|
15644
16207
|
|
|
15645
16208
|
// src/compatibility/shopify-objects/address.ts
|
|
@@ -16826,13 +17389,12 @@ ${formattedMessage}`;
|
|
|
16826
17389
|
var SwellImage = class extends StorefrontResource {
|
|
16827
17390
|
constructor(swell, name) {
|
|
16828
17391
|
super(async () => {
|
|
16829
|
-
const
|
|
17392
|
+
const file = await swell.get("/:files/:last", {
|
|
16830
17393
|
private: { $ne: true },
|
|
16831
17394
|
content_type: { $regex: "^image/" },
|
|
16832
17395
|
filename: name
|
|
16833
17396
|
});
|
|
16834
|
-
|
|
16835
|
-
if (file === null) {
|
|
17397
|
+
if (!file) {
|
|
16836
17398
|
return null;
|
|
16837
17399
|
}
|
|
16838
17400
|
return { file };
|