@swell/apps-sdk 1.0.161 → 1.0.163
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 +134 -95
- package/dist/index.cjs.map +3 -3
- package/dist/index.js +132 -95
- package/dist/index.js.map +3 -3
- package/dist/index.mjs +133 -95
- package/dist/index.mjs.map +3 -3
- package/dist/src/api.d.ts +4 -0
- package/dist/src/cache/cache.d.ts +10 -1
- package/dist/src/cache/html-cache/html-cache-factory.d.ts +3 -2
- package/dist/src/cache/html-cache/html-cache.d.ts +41 -5
- package/dist/src/cache/html-cache/index.d.ts +2 -2
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -7172,6 +7172,7 @@ var DEFAULT_OPTIONS = Object.freeze({
|
|
|
7172
7172
|
});
|
|
7173
7173
|
var NULL_VALUE = "__NULL__";
|
|
7174
7174
|
var SWR_PROMISE_MAP = /* @__PURE__ */ new Map();
|
|
7175
|
+
var FETCH_PROMISE_MAP = /* @__PURE__ */ new Map();
|
|
7175
7176
|
var Cache = class {
|
|
7176
7177
|
client;
|
|
7177
7178
|
workerCtx;
|
|
@@ -7184,8 +7185,30 @@ var Cache = class {
|
|
|
7184
7185
|
...options
|
|
7185
7186
|
});
|
|
7186
7187
|
}
|
|
7187
|
-
|
|
7188
|
-
|
|
7188
|
+
/**
|
|
7189
|
+
* Always fetches fresh data and updates cache
|
|
7190
|
+
* Deduplicates concurrent requests with the same key
|
|
7191
|
+
*
|
|
7192
|
+
* @param key Cache key
|
|
7193
|
+
* @param fetchFn Function to fetch fresh data
|
|
7194
|
+
* @param ttl Time to live in milliseconds (default: DEFAULT_SWR_TTL)
|
|
7195
|
+
* @param isCacheable Whether to store result in cache (default: true)
|
|
7196
|
+
*/
|
|
7197
|
+
async fetch(key, fetchFn, ttl = DEFAULT_SWR_TTL, isCacheable = true) {
|
|
7198
|
+
let promise = FETCH_PROMISE_MAP.get(key);
|
|
7199
|
+
if (!promise) {
|
|
7200
|
+
promise = Promise.resolve().then(fetchFn).then(resolveAsyncResources).then(async (value) => {
|
|
7201
|
+
const isNull = value === null || value === void 0;
|
|
7202
|
+
if (isCacheable) {
|
|
7203
|
+
await this.client.set(key, isNull ? NULL_VALUE : value, ttl);
|
|
7204
|
+
}
|
|
7205
|
+
return value;
|
|
7206
|
+
}).finally(() => {
|
|
7207
|
+
FETCH_PROMISE_MAP.delete(key);
|
|
7208
|
+
});
|
|
7209
|
+
FETCH_PROMISE_MAP.set(key, promise);
|
|
7210
|
+
}
|
|
7211
|
+
return await promise;
|
|
7189
7212
|
}
|
|
7190
7213
|
/**
|
|
7191
7214
|
* Fetch cache using SWR (stale-while-revalidate)
|
|
@@ -8293,18 +8316,24 @@ var Swell = class _Swell {
|
|
|
8293
8316
|
}
|
|
8294
8317
|
return params;
|
|
8295
8318
|
}
|
|
8319
|
+
/**
|
|
8320
|
+
* Checks if cache bypass is requested via X-Cache-Bypass header
|
|
8321
|
+
*/
|
|
8322
|
+
shouldBypassCache() {
|
|
8323
|
+
return this.headers?.["x-cache-bypass"] === "revalidation";
|
|
8324
|
+
}
|
|
8296
8325
|
/**
|
|
8297
8326
|
* Fetches a resource.
|
|
8298
8327
|
* First attempts to fetch from cache.
|
|
8299
8328
|
*/
|
|
8300
8329
|
async getCachedResource(key, args, handler, isCacheble = true) {
|
|
8301
8330
|
const cacheKey = getCacheKey(key, [this.instanceId, args]);
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
handler,
|
|
8305
|
-
|
|
8306
|
-
isCacheble
|
|
8307
|
-
|
|
8331
|
+
const cache = this.getResourceCache();
|
|
8332
|
+
if (this.shouldBypassCache()) {
|
|
8333
|
+
return cache.fetch(cacheKey, handler, void 0, isCacheble);
|
|
8334
|
+
} else {
|
|
8335
|
+
return cache.fetchSWR(cacheKey, handler, void 0, isCacheble);
|
|
8336
|
+
}
|
|
8308
8337
|
}
|
|
8309
8338
|
async getAppSettings() {
|
|
8310
8339
|
const settings = await this.get(
|
|
@@ -8471,11 +8500,17 @@ var Swell = class _Swell {
|
|
|
8471
8500
|
data,
|
|
8472
8501
|
opt
|
|
8473
8502
|
]);
|
|
8474
|
-
|
|
8503
|
+
const cache = this.getRequestCache();
|
|
8504
|
+
const fetchFn = () => {
|
|
8475
8505
|
const requestUrl = id ? `${url}/${id}` : url;
|
|
8476
8506
|
logger.debug("[SDK] Cacheable API request", { url: requestUrl, key });
|
|
8477
8507
|
return storefrontRequest(method, url, id, data, opt);
|
|
8478
|
-
}
|
|
8508
|
+
};
|
|
8509
|
+
if (this.shouldBypassCache()) {
|
|
8510
|
+
return cache.fetch(key, fetchFn);
|
|
8511
|
+
} else {
|
|
8512
|
+
return cache.fetchSWR(key, fetchFn);
|
|
8513
|
+
}
|
|
8479
8514
|
}
|
|
8480
8515
|
switch (method) {
|
|
8481
8516
|
case "delete":
|
|
@@ -15874,7 +15909,7 @@ function ShopifyAddress(instance, address, account) {
|
|
|
15874
15909
|
function joinAddressLines(...props) {
|
|
15875
15910
|
return props.filter(Boolean).join("\n");
|
|
15876
15911
|
}
|
|
15877
|
-
function ShopifyCountry(
|
|
15912
|
+
function ShopifyCountry(_instance, countryCode) {
|
|
15878
15913
|
const currencyCode = getCurrencyByCountry(countryCode) || "USD";
|
|
15879
15914
|
return new ShopifyResource(
|
|
15880
15915
|
{
|
|
@@ -16207,7 +16242,7 @@ async function resolveLastOrder(instance, account) {
|
|
|
16207
16242
|
}
|
|
16208
16243
|
|
|
16209
16244
|
// src/compatibility/shopify-objects/font.ts
|
|
16210
|
-
function ShopifyFont(
|
|
16245
|
+
function ShopifyFont(_instance, font) {
|
|
16211
16246
|
if (font instanceof ShopifyResource) {
|
|
16212
16247
|
return font.clone();
|
|
16213
16248
|
}
|
|
@@ -16218,7 +16253,7 @@ function ShopifyFont(_instance2, font) {
|
|
|
16218
16253
|
family: font.family,
|
|
16219
16254
|
style: font.style,
|
|
16220
16255
|
"system?": font.system,
|
|
16221
|
-
variants: font.variants.map((variant) => ShopifyFont(
|
|
16256
|
+
variants: font.variants.map((variant) => ShopifyFont(_instance, variant)),
|
|
16222
16257
|
weight: font.weight
|
|
16223
16258
|
});
|
|
16224
16259
|
}
|
|
@@ -16231,7 +16266,7 @@ var SHOPIFY_FORMS = {
|
|
|
16231
16266
|
})
|
|
16232
16267
|
}
|
|
16233
16268
|
};
|
|
16234
|
-
function ShopifyForm(
|
|
16269
|
+
function ShopifyForm(_instance, form) {
|
|
16235
16270
|
if (form instanceof ShopifyResource) {
|
|
16236
16271
|
return form.clone();
|
|
16237
16272
|
}
|
|
@@ -16528,7 +16563,7 @@ function ShopifyRecommendations(instance, product) {
|
|
|
16528
16563
|
}
|
|
16529
16564
|
|
|
16530
16565
|
// src/compatibility/shopify-objects/page.ts
|
|
16531
|
-
function ShopifyPage(
|
|
16566
|
+
function ShopifyPage(_instance, page) {
|
|
16532
16567
|
if (page instanceof ShopifyResource) {
|
|
16533
16568
|
return page.clone();
|
|
16534
16569
|
}
|
|
@@ -17740,7 +17775,7 @@ ${injects.join("\n")}</script>`;
|
|
|
17740
17775
|
};
|
|
17741
17776
|
|
|
17742
17777
|
// src/compatibility/shopify-objects/template.ts
|
|
17743
|
-
function ShopifyTemplate(
|
|
17778
|
+
function ShopifyTemplate(_instance, template) {
|
|
17744
17779
|
return new ShopifyResource(
|
|
17745
17780
|
{
|
|
17746
17781
|
directory: template.path,
|
|
@@ -20680,12 +20715,7 @@ var SwellTheme3 = class {
|
|
|
20680
20715
|
// Default value (always StorefrontResource)
|
|
20681
20716
|
() => this.fetchCart()
|
|
20682
20717
|
),
|
|
20683
|
-
this.
|
|
20684
|
-
"account",
|
|
20685
|
-
() => this.fetchAccount(),
|
|
20686
|
-
() => null,
|
|
20687
|
-
false
|
|
20688
|
-
)
|
|
20718
|
+
this.fetchAccount()
|
|
20689
20719
|
]);
|
|
20690
20720
|
if (!cart) {
|
|
20691
20721
|
throw new Error("Failed to fetch cart");
|
|
@@ -22323,42 +22353,27 @@ function getResourceQuery(slug, query) {
|
|
|
22323
22353
|
|
|
22324
22354
|
// src/cache/html-cache/html-cache.ts
|
|
22325
22355
|
var CACHE_KEY_ORIGIN = "https://cache.swell.store";
|
|
22326
|
-
var
|
|
22327
|
-
|
|
22328
|
-
|
|
22329
|
-
|
|
22330
|
-
|
|
22331
|
-
|
|
22332
|
-
|
|
22333
|
-
|
|
22334
|
-
SWR: 60 * 60 * 24 * 7
|
|
22335
|
-
// 1 week
|
|
22336
|
-
},
|
|
22337
|
-
PREVIEW: {
|
|
22338
|
-
DEFAULT: 10,
|
|
22339
|
-
HOME: 10,
|
|
22340
|
-
PRODUCT: 10,
|
|
22341
|
-
COLLECTION: 10,
|
|
22342
|
-
PAGE: 10,
|
|
22343
|
-
BLOG: 10,
|
|
22344
|
-
SWR: 60 * 60 * 24 * 7
|
|
22345
|
-
// 1 week
|
|
22346
|
-
}
|
|
22356
|
+
var DEFAULT_CACHE_RULES = {
|
|
22357
|
+
defaults: {
|
|
22358
|
+
live: { ttl: 20, swr: 60 * 60 * 24 * 7 },
|
|
22359
|
+
// 20s TTL, 1 week SWR
|
|
22360
|
+
preview: { ttl: 10, swr: 60 * 60 * 24 * 7 }
|
|
22361
|
+
// 10s TTL, 1 week SWR
|
|
22362
|
+
},
|
|
22363
|
+
pathRules: [{ path: "/checkout/*", skip: true }]
|
|
22347
22364
|
};
|
|
22348
22365
|
var HtmlCache = class {
|
|
22349
22366
|
epoch;
|
|
22350
22367
|
backend;
|
|
22351
|
-
|
|
22368
|
+
cacheRules;
|
|
22369
|
+
constructor(epoch, backend, cacheRules = DEFAULT_CACHE_RULES) {
|
|
22352
22370
|
this.epoch = epoch;
|
|
22353
22371
|
this.backend = backend;
|
|
22372
|
+
this.cacheRules = cacheRules;
|
|
22354
22373
|
}
|
|
22355
22374
|
async get(request) {
|
|
22356
22375
|
const trace = createTraceId();
|
|
22357
|
-
if (request
|
|
22358
|
-
logger.debug("[SDK Html-cache] non-cacheable method", { trace });
|
|
22359
|
-
return { found: false, cacheable: false };
|
|
22360
|
-
}
|
|
22361
|
-
if (!this.isCacheable(request)) {
|
|
22376
|
+
if (!this.canReadFromCache(request)) {
|
|
22362
22377
|
logger.debug("[SDK Html-cache] non-cacheable request", { trace });
|
|
22363
22378
|
return { found: false, cacheable: false };
|
|
22364
22379
|
}
|
|
@@ -22426,31 +22441,27 @@ var HtmlCache = class {
|
|
|
22426
22441
|
}
|
|
22427
22442
|
async put(request, response) {
|
|
22428
22443
|
const trace = createTraceId();
|
|
22429
|
-
if (request
|
|
22430
|
-
logger.debug("[SDK Html-cache] put skipped, invalid method or response", {
|
|
22431
|
-
trace
|
|
22432
|
-
});
|
|
22433
|
-
return;
|
|
22434
|
-
}
|
|
22435
|
-
if (!this.isCacheable(request) || !this.isResponseCacheable(response)) {
|
|
22444
|
+
if (!this.canWriteToCache(request, response)) {
|
|
22436
22445
|
logger.debug("[SDK Html-cache] put skipped, non-cacheable", { trace });
|
|
22437
22446
|
return;
|
|
22438
22447
|
}
|
|
22439
22448
|
try {
|
|
22440
|
-
let lowercaseHeaders2 = function(headers2) {
|
|
22441
|
-
const out = {};
|
|
22442
|
-
headers2.forEach((value, key) => {
|
|
22443
|
-
out[key.toLowerCase()] = value;
|
|
22444
|
-
});
|
|
22445
|
-
return out;
|
|
22446
|
-
};
|
|
22447
|
-
var lowercaseHeaders = lowercaseHeaders2;
|
|
22448
22449
|
const cacheKey = this.buildCacheKey(request);
|
|
22449
22450
|
const ttl = this.getTTLForRequest(request);
|
|
22450
22451
|
const swr = this.getSWRForRequest(request);
|
|
22451
22452
|
const body = await response.text();
|
|
22453
|
+
if (!body || body.trim().length === 0) {
|
|
22454
|
+
logger.warn(
|
|
22455
|
+
"[SDK Html-cache] put skipped, empty or minimal response body",
|
|
22456
|
+
{
|
|
22457
|
+
trace,
|
|
22458
|
+
bodyLength: body.length
|
|
22459
|
+
}
|
|
22460
|
+
);
|
|
22461
|
+
return;
|
|
22462
|
+
}
|
|
22452
22463
|
const cacheTimeISO = (/* @__PURE__ */ new Date()).toISOString();
|
|
22453
|
-
const headers =
|
|
22464
|
+
const headers = this.normalizeHeaders(response.headers);
|
|
22454
22465
|
const entry = {
|
|
22455
22466
|
status: response.status,
|
|
22456
22467
|
statusText: response.statusText,
|
|
@@ -22484,14 +22495,13 @@ var HtmlCache = class {
|
|
|
22484
22495
|
});
|
|
22485
22496
|
}
|
|
22486
22497
|
}
|
|
22487
|
-
|
|
22488
|
-
const
|
|
22489
|
-
return (
|
|
22498
|
+
canReadFromCache(request) {
|
|
22499
|
+
const method = request.method.toUpperCase();
|
|
22500
|
+
return (method === "GET" || method === "HEAD") && this.isRequestCacheable(request);
|
|
22490
22501
|
}
|
|
22491
|
-
|
|
22492
|
-
|
|
22493
|
-
|
|
22494
|
-
return this.isResponseCacheable(response);
|
|
22502
|
+
canWriteToCache(request, response) {
|
|
22503
|
+
const method = request.method.toUpperCase();
|
|
22504
|
+
return method === "GET" && response.ok && this.isRequestCacheable(request) && this.isResponseCacheable(response);
|
|
22495
22505
|
}
|
|
22496
22506
|
createRevalidationRequest(request) {
|
|
22497
22507
|
const headers = new Headers(request.headers);
|
|
@@ -22507,7 +22517,7 @@ var HtmlCache = class {
|
|
|
22507
22517
|
}
|
|
22508
22518
|
buildClientResponse(entry, isStale, age) {
|
|
22509
22519
|
const headers = new Headers(entry.headers);
|
|
22510
|
-
headers.set("Cache-Control", "public, max-age=
|
|
22520
|
+
headers.set("Cache-Control", "public, max-age=1, must-revalidate");
|
|
22511
22521
|
headers.set(
|
|
22512
22522
|
"Cloudflare-CDN-Cache-Control",
|
|
22513
22523
|
`public, s-maxage=${entry.ttl}, stale-while-revalidate=${entry.swr}, stale-if-error=60`
|
|
@@ -22602,6 +22612,7 @@ var HtmlCache = class {
|
|
|
22602
22612
|
const accept = headers.get("accept") || "";
|
|
22603
22613
|
const versionFactors = {
|
|
22604
22614
|
store: headers.get("swell-storefront-id") || "",
|
|
22615
|
+
app: (headers.get("swell-app-id") || "") + "@" + (swellData["swell-app-version"] || ""),
|
|
22605
22616
|
auth: headers.get("swell-access-token") || "",
|
|
22606
22617
|
theme: headers.get("swell-theme-version-hash") || "",
|
|
22607
22618
|
modified: headers.get("swell-cache-modified") || "",
|
|
@@ -22624,11 +22635,16 @@ var HtmlCache = class {
|
|
|
22624
22635
|
return {};
|
|
22625
22636
|
}
|
|
22626
22637
|
}
|
|
22627
|
-
|
|
22638
|
+
isRequestCacheable(request) {
|
|
22628
22639
|
const url = new URL(request.url);
|
|
22629
22640
|
if (request.headers.get("swell-deployment-mode") === "editor") return false;
|
|
22630
|
-
|
|
22631
|
-
|
|
22641
|
+
if (this.cacheRules.pathRules) {
|
|
22642
|
+
for (const rule of this.cacheRules.pathRules) {
|
|
22643
|
+
if (this.pathMatches(rule.path, url.pathname) && rule.skip) {
|
|
22644
|
+
return false;
|
|
22645
|
+
}
|
|
22646
|
+
}
|
|
22647
|
+
}
|
|
22632
22648
|
if (request.headers.get("cache-control")?.includes("no-cache"))
|
|
22633
22649
|
return false;
|
|
22634
22650
|
return true;
|
|
@@ -22644,24 +22660,33 @@ var HtmlCache = class {
|
|
|
22644
22660
|
}
|
|
22645
22661
|
getDeploymentMode(headers) {
|
|
22646
22662
|
const mode = headers.get("swell-deployment-mode");
|
|
22647
|
-
return mode === "preview"
|
|
22663
|
+
return mode === "preview" ? "preview" : "live";
|
|
22648
22664
|
}
|
|
22649
22665
|
getTTLForRequest(request) {
|
|
22650
22666
|
const url = new URL(request.url);
|
|
22651
22667
|
const mode = this.getDeploymentMode(request.headers);
|
|
22652
|
-
if (
|
|
22653
|
-
|
|
22654
|
-
|
|
22655
|
-
|
|
22656
|
-
|
|
22657
|
-
|
|
22658
|
-
|
|
22659
|
-
|
|
22668
|
+
if (this.cacheRules.pathRules) {
|
|
22669
|
+
for (const rule of this.cacheRules.pathRules) {
|
|
22670
|
+
if (this.pathMatches(rule.path, url.pathname) && rule.ttl !== void 0) {
|
|
22671
|
+
return rule.ttl;
|
|
22672
|
+
}
|
|
22673
|
+
}
|
|
22674
|
+
}
|
|
22675
|
+
const defaults = this.cacheRules.defaults?.[mode];
|
|
22676
|
+
return defaults?.ttl ?? DEFAULT_CACHE_RULES.defaults[mode].ttl;
|
|
22660
22677
|
}
|
|
22661
22678
|
getSWRForRequest(request) {
|
|
22679
|
+
const url = new URL(request.url);
|
|
22662
22680
|
const mode = this.getDeploymentMode(request.headers);
|
|
22663
|
-
if (
|
|
22664
|
-
|
|
22681
|
+
if (this.cacheRules.pathRules) {
|
|
22682
|
+
for (const rule of this.cacheRules.pathRules) {
|
|
22683
|
+
if (this.pathMatches(rule.path, url.pathname) && rule.swr !== void 0) {
|
|
22684
|
+
return rule.swr;
|
|
22685
|
+
}
|
|
22686
|
+
}
|
|
22687
|
+
}
|
|
22688
|
+
const defaults = this.cacheRules.defaults?.[mode];
|
|
22689
|
+
return defaults?.swr ?? DEFAULT_CACHE_RULES.defaults[mode].swr;
|
|
22665
22690
|
}
|
|
22666
22691
|
getEntryAge(entry) {
|
|
22667
22692
|
const t = Date.parse(entry.cacheTimeISO);
|
|
@@ -22669,6 +22694,22 @@ var HtmlCache = class {
|
|
|
22669
22694
|
const age = (Date.now() - t) / 1e3;
|
|
22670
22695
|
return age < 0 ? 0 : age;
|
|
22671
22696
|
}
|
|
22697
|
+
/**
|
|
22698
|
+
* Converts wildcard pattern to regex and tests against path.
|
|
22699
|
+
* - * matches any characters except /
|
|
22700
|
+
* - ** matches any characters including /
|
|
22701
|
+
*/
|
|
22702
|
+
pathMatches(pattern, path) {
|
|
22703
|
+
const regex = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "___DOUBLE_STAR___").replace(/\*/g, "[^/]*").replace(/___DOUBLE_STAR___/g, ".*");
|
|
22704
|
+
return new RegExp(`^${regex}$`).test(path);
|
|
22705
|
+
}
|
|
22706
|
+
normalizeHeaders(headers) {
|
|
22707
|
+
const normalized = {};
|
|
22708
|
+
headers.forEach((value, key) => {
|
|
22709
|
+
normalized[key.toLowerCase()] = value;
|
|
22710
|
+
});
|
|
22711
|
+
return normalized;
|
|
22712
|
+
}
|
|
22672
22713
|
normalizeSearchParams(searchParams) {
|
|
22673
22714
|
const ignoredParams = [
|
|
22674
22715
|
"utm_source",
|
|
@@ -22837,7 +22878,6 @@ var WorkerCacheBackend = class {
|
|
|
22837
22878
|
statusText: entry.statusText,
|
|
22838
22879
|
headers
|
|
22839
22880
|
});
|
|
22840
|
-
await cache.delete(request);
|
|
22841
22881
|
await cache.put(request, response);
|
|
22842
22882
|
}
|
|
22843
22883
|
async delete(key) {
|
|
@@ -22848,18 +22888,15 @@ var WorkerCacheBackend = class {
|
|
|
22848
22888
|
};
|
|
22849
22889
|
|
|
22850
22890
|
// src/cache/html-cache/html-cache-factory.ts
|
|
22851
|
-
|
|
22852
|
-
function getHtmlCache(env) {
|
|
22891
|
+
function getHtmlCache(env, cacheRules) {
|
|
22853
22892
|
const epoch = env?.HTML_CACHE_EPOCH;
|
|
22854
22893
|
if (typeof epoch !== "string" || !epoch) return null;
|
|
22855
|
-
if (_instance) return _instance;
|
|
22856
22894
|
const kv = env?.NAMESPACE;
|
|
22895
|
+
const rules = cacheRules || env?.HTML_CACHE_RULES;
|
|
22857
22896
|
if (env?.HTML_CACHE_BACKEND !== "worker" && kv) {
|
|
22858
|
-
|
|
22859
|
-
return _instance;
|
|
22897
|
+
return new HtmlCache(epoch, new KVCacheBackend(kv), rules);
|
|
22860
22898
|
}
|
|
22861
|
-
|
|
22862
|
-
return _instance;
|
|
22899
|
+
return new HtmlCache(epoch, new WorkerCacheBackend(epoch), rules);
|
|
22863
22900
|
}
|
|
22864
22901
|
export {
|
|
22865
22902
|
AccountAddressesResource,
|
|
@@ -22874,6 +22911,7 @@ export {
|
|
|
22874
22911
|
CartResource,
|
|
22875
22912
|
CategoriesResource,
|
|
22876
22913
|
CategoryResource,
|
|
22914
|
+
DEFAULT_CACHE_RULES,
|
|
22877
22915
|
DEFAULT_QUERY_PAGE_LIMIT,
|
|
22878
22916
|
DeferredShopifyResource,
|
|
22879
22917
|
FILE_DATA_INCLUDE_QUERY,
|