@wix/web5-core 1.63.12 → 1.63.13
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/cjs/hooks/useResolveShopifyEntityData.js +26 -3
- package/dist/cjs/hooks/useResolveShopifyEntityData.js.map +1 -1
- package/dist/esm/hooks/useResolveShopifyEntityData.js +26 -4
- package/dist/esm/hooks/useResolveShopifyEntityData.js.map +1 -1
- package/dist/types/hooks/useResolveShopifyEntityData.d.ts +9 -0
- package/dist/types/hooks/useResolveShopifyEntityData.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
|
+
exports.getShopifyLookup = getShopifyLookup;
|
|
4
5
|
exports.mergeShopifyEntityData = mergeShopifyEntityData;
|
|
5
6
|
exports.useResolveShopifyEntityData = useResolveShopifyEntityData;
|
|
6
7
|
var _react = require("react");
|
|
@@ -14,7 +15,11 @@ function cacheKey(entityType, entityId, variantId) {
|
|
|
14
15
|
}
|
|
15
16
|
function normalizeShopifyEntityType(entityType) {
|
|
16
17
|
const lower = entityType.toLowerCase();
|
|
17
|
-
|
|
18
|
+
// A variant is not a Storefront resource of its own — there is no
|
|
19
|
+
// `variantByHandle`. It is fetched as its parent product and then priced at
|
|
20
|
+
// the variant the lookup carries alongside, which is why `variant` and
|
|
21
|
+
// `product` normalize to the same query here rather than to two.
|
|
22
|
+
if (lower.includes('product') || lower.includes('variant')) {
|
|
18
23
|
return 'product';
|
|
19
24
|
}
|
|
20
25
|
if (lower.includes('collection')) {
|
|
@@ -50,15 +55,33 @@ function extractHandleFromUrl(url) {
|
|
|
50
55
|
}
|
|
51
56
|
return withoutLeadingSlash || undefined;
|
|
52
57
|
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* The `?variant=` the row's own URL already carries.
|
|
61
|
+
*
|
|
62
|
+
* A row that names a variant — whether the turn overlaid one onto a product or
|
|
63
|
+
* sent the variant as the entity itself — always links to it, because that is
|
|
64
|
+
* the URL a shopper has to land on. So when the row omits `variantId` as a
|
|
65
|
+
* field, the URL still says which child it means, and pricing the parent's
|
|
66
|
+
* default instead would contradict the link on the same card.
|
|
67
|
+
*/
|
|
68
|
+
function variantIdFromUrl(url) {
|
|
69
|
+
var _URLSearchParams$get;
|
|
70
|
+
const query = url == null ? void 0 : url.split('#')[0].split('?')[1];
|
|
71
|
+
if (!query) {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
return ((_URLSearchParams$get = new URLSearchParams(query).get('variant')) == null ? void 0 : _URLSearchParams$get.trim()) || undefined;
|
|
75
|
+
}
|
|
53
76
|
function getShopifyLookup(entity) {
|
|
54
|
-
var _entity$data, _entity$data2;
|
|
77
|
+
var _entity$data, _entity$data2, _entity$data3;
|
|
55
78
|
const entityType = normalizeShopifyEntityType(entity.entityType);
|
|
56
79
|
const urlHandle = extractHandleFromUrl((_entity$data = entity.data) == null ? void 0 : _entity$data.url);
|
|
57
80
|
const entityId = (entityType === 'product' || entityType === 'collection') && urlHandle ? urlHandle : entity.entityId;
|
|
58
81
|
return {
|
|
59
82
|
entityType,
|
|
60
83
|
entityId,
|
|
61
|
-
variantId: (_entity$data2 = entity.data) == null ? void 0 : _entity$data2.variantId
|
|
84
|
+
variantId: ((_entity$data2 = entity.data) == null ? void 0 : _entity$data2.variantId) ?? variantIdFromUrl((_entity$data3 = entity.data) == null ? void 0 : _entity$data3.url)
|
|
62
85
|
};
|
|
63
86
|
}
|
|
64
87
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","require","_shopifyStorefrontClient","_shopifyEntityResolver","_transformShopifyEntity","shopifyEntityCache","Map","cacheKey","entityType","entityId","variantId","normalizeShopifyEntityType","lower","toLowerCase","includes","extractHandleFromUrl","url","trimmed","trim","undefined","pathname","test","URL","withoutQuery","split","withoutLeadingSlash","replace","productsIndex","indexOf","slice","length","collectionsIndex","getShopifyLookup","entity","_entity$data","_entity$data2","urlHandle","data","mergeShopifyEntityData","existing","resolved","_existing$matchedOpti","title","imageUrl","matchedOptions","useResolveShopifyEntityData","entities","shopifyConfig","resolvedMap","setResolvedMap","useState","settled","setSettled","clientRef","useRef","configKeyRef","configKey","storeDomain","apiVersion","current","ShopifyStorefrontClient","entityIds","useMemo","map","e","lookup","join","useEffect","ignore","client","entityLookups","key","toFetch","filter","has","cached","forEach","item","get","set","fetchAll","Promise","allSettled","resolveShopifyEntity","itemData","transformShopifyEntityToItemData","finalMap","enrichedEntities","loading"],"sources":["../../../src/hooks/useResolveShopifyEntityData.ts"],"sourcesContent":["import { useState, useEffect, useMemo, useRef } from 'react';\nimport { ShopifyStorefrontClient } from '../services/shopify/shopifyStorefrontClient';\nimport { resolveShopifyEntity } from '../services/shopify/shopifyEntityResolver';\nimport { transformShopifyEntityToItemData } from '../services/shopify/transformShopifyEntity';\nimport type { ShopifyStorefrontConfig } from '../services/shopify/types';\nimport type { EntityItemData } from '../component/types';\n\n// Session-level cache: entityType:entityId:variantId → resolved EntityItemData\nconst shopifyEntityCache = new Map<string, EntityItemData>();\n\nfunction cacheKey(\n entityType: string,\n entityId: string,\n variantId?: string,\n): string {\n return `${entityType}:${entityId}:${variantId || ''}`;\n}\n\nfunction normalizeShopifyEntityType(entityType: string): string {\n const lower = entityType.toLowerCase();\n if (lower.includes('product')) {\n return 'product';\n }\n if (lower.includes('collection')) {\n return 'collection';\n }\n if (lower.includes('article') || lower.includes('blog')) {\n return 'article';\n }\n return entityType;\n}\n\nfunction extractHandleFromUrl(url: string | undefined): string | undefined {\n const trimmed = url?.trim();\n if (!trimmed) {\n return undefined;\n }\n\n let pathname = trimmed;\n try {\n if (/^https?:\\/\\//i.test(trimmed)) {\n pathname = new URL(trimmed).pathname;\n }\n } catch {\n pathname = trimmed;\n }\n\n const withoutQuery = pathname.split(/[?#]/)[0];\n const withoutLeadingSlash = withoutQuery.replace(/^\\/+/, '');\n const productsIndex = withoutLeadingSlash.indexOf('products/');\n if (productsIndex >= 0) {\n return withoutLeadingSlash.slice(productsIndex + 'products/'.length);\n }\n\n const collectionsIndex = withoutLeadingSlash.indexOf('collections/');\n if (collectionsIndex >= 0) {\n return withoutLeadingSlash.slice(\n collectionsIndex + 'collections/'.length,\n );\n }\n\n return withoutLeadingSlash || undefined;\n}\n\nfunction getShopifyLookup(entity: {\n entityId: string;\n entityType: string;\n data?: EntityItemData;\n}) {\n const entityType = normalizeShopifyEntityType(entity.entityType);\n const urlHandle = extractHandleFromUrl(entity.data?.url);\n const entityId =\n (entityType === 'product' || entityType === 'collection') && urlHandle\n ? urlHandle\n : entity.entityId;\n return { entityType, entityId, variantId: entity.data?.variantId };\n}\n\n/**\n * The turn owns WHICH thing to show; the live fetch owns VOLATILE FACTS about\n * it.\n *\n * Only the turn saw the shopper's question, so only it knows that the brown\n * variant was the one asked for — its `title`, `imageUrl`, `url`,\n * `matchedOptions` and `variantId` all describe that one variant and must\n * survive enrichment. Everything the Storefront answers with that can go stale\n * between the turn and the render — `price`, `compareAtPrice`, `available`,\n * `priceMin`, `priceMax` — comes from `resolved`.\n */\nexport function mergeShopifyEntityData(\n existing: EntityItemData | undefined,\n resolved: EntityItemData,\n): EntityItemData {\n if (!existing) {\n return resolved;\n }\n\n return {\n ...existing,\n ...resolved,\n url: existing.url || resolved.url,\n title: existing.title || resolved.title,\n imageUrl: existing.imageUrl || resolved.imageUrl,\n variantId: existing.variantId || resolved.variantId,\n matchedOptions: existing.matchedOptions?.length\n ? existing.matchedOptions\n : resolved.matchedOptions,\n };\n}\n\n/**\n * Shopify-specific implementation of the entity resolution pattern.\n *\n * Fetches entity data from the Shopify Storefront API (tokenless) and\n * transforms it to the standard EntityItemData shape.\n *\n * Designed to be plugged into ComponentDependencies.useResolveGenericEntityData.\n */\nexport function useResolveShopifyEntityData<\n TEntity extends {\n entityId: string;\n entityUrl: string;\n entityType: string;\n data?: EntityItemData;\n },\n>(\n entities: TEntity[],\n shopifyConfig: ShopifyStorefrontConfig,\n): { enrichedEntities: TEntity[]; loading: boolean } {\n const [resolvedMap, setResolvedMap] = useState<Map<string, EntityItemData>>(\n new Map(),\n );\n const [settled, setSettled] = useState(false);\n\n // Stable client reference — recreated only when config changes\n const clientRef = useRef<ShopifyStorefrontClient | null>(null);\n const configKeyRef = useRef('');\n const configKey = `${shopifyConfig.storeDomain}|${\n shopifyConfig.apiVersion || ''\n }`;\n\n if (!clientRef.current || configKeyRef.current !== configKey) {\n clientRef.current = new ShopifyStorefrontClient(shopifyConfig);\n configKeyRef.current = configKey;\n }\n\n const entityIds = useMemo(\n () =>\n entities\n .map((e) => {\n const lookup = getShopifyLookup(e);\n return `${e.entityType}:${e.entityId}:${cacheKey(\n lookup.entityType,\n lookup.entityId,\n lookup.variantId,\n )}`;\n })\n .join(','),\n [entities],\n );\n\n useEffect(() => {\n let ignore = false;\n const client = clientRef.current;\n\n if (!entities.length || !client || !shopifyConfig.storeDomain) {\n setSettled(true);\n return;\n }\n\n const entityLookups = entities.map((entity) => {\n const lookup = getShopifyLookup(entity);\n return {\n entity,\n lookup,\n // The variant is part of the key: the cached entry carries that\n // variant's live price, so two entities on the same product but\n // different variants must not share it.\n key: cacheKey(lookup.entityType, lookup.entityId, lookup.variantId),\n };\n });\n\n // Identify entities that need fetching. Payload data can provide the handle.\n const toFetch = entityLookups.filter(\n ({ key }) => !shopifyEntityCache.has(key),\n );\n\n // If everything is cached, resolve immediately\n if (toFetch.length === 0) {\n const cached = new Map<string, EntityItemData>();\n entityLookups.forEach(({ entity, key }) => {\n const item = shopifyEntityCache.get(key);\n if (item) {\n cached.set(entity.entityId, mergeShopifyEntityData(entity.data, item));\n }\n });\n setResolvedMap(cached);\n setSettled(true);\n return;\n }\n\n setSettled(false);\n\n const fetchAll = async () => {\n await Promise.allSettled(\n toFetch.map(async ({ entity, lookup, key }) => {\n const resolved = await resolveShopifyEntity(\n client,\n lookup.entityType,\n lookup.entityId,\n shopifyConfig,\n );\n if (resolved) {\n const itemData = transformShopifyEntityToItemData(\n resolved,\n lookup.entityType,\n lookup.variantId,\n );\n shopifyEntityCache.set(\n key,\n mergeShopifyEntityData(entity.data, itemData),\n );\n }\n }),\n );\n\n if (ignore) {\n return;\n }\n\n // Build the resolved map from cache\n const finalMap = new Map<string, EntityItemData>();\n entityLookups.forEach(({ entity, key }) => {\n const item = shopifyEntityCache.get(key);\n if (item) {\n finalMap.set(\n entity.entityId,\n mergeShopifyEntityData(entity.data, item),\n );\n }\n });\n\n setResolvedMap(finalMap);\n setSettled(true);\n };\n\n fetchAll();\n return () => {\n ignore = true;\n };\n }, [entityIds, shopifyConfig.storeDomain]);\n\n // Merge resolved data into entities\n const enrichedEntities = useMemo(() => {\n return entities.map((entity) => {\n const resolved = resolvedMap.get(entity.entityId);\n if (resolved) {\n return { ...entity, data: resolved };\n }\n return entity;\n });\n }, [entities, resolvedMap]);\n\n return { enrichedEntities, loading: !settled };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["_react","require","_shopifyStorefrontClient","_shopifyEntityResolver","_transformShopifyEntity","shopifyEntityCache","Map","cacheKey","entityType","entityId","variantId","normalizeShopifyEntityType","lower","toLowerCase","includes","extractHandleFromUrl","url","trimmed","trim","undefined","pathname","test","URL","withoutQuery","split","withoutLeadingSlash","replace","productsIndex","indexOf","slice","length","collectionsIndex","variantIdFromUrl","_URLSearchParams$get","query","URLSearchParams","get","getShopifyLookup","entity","_entity$data","_entity$data2","_entity$data3","urlHandle","data","mergeShopifyEntityData","existing","resolved","_existing$matchedOpti","title","imageUrl","matchedOptions","useResolveShopifyEntityData","entities","shopifyConfig","resolvedMap","setResolvedMap","useState","settled","setSettled","clientRef","useRef","configKeyRef","configKey","storeDomain","apiVersion","current","ShopifyStorefrontClient","entityIds","useMemo","map","e","lookup","join","useEffect","ignore","client","entityLookups","key","toFetch","filter","has","cached","forEach","item","set","fetchAll","Promise","allSettled","resolveShopifyEntity","itemData","transformShopifyEntityToItemData","finalMap","enrichedEntities","loading"],"sources":["../../../src/hooks/useResolveShopifyEntityData.ts"],"sourcesContent":["import { useState, useEffect, useMemo, useRef } from 'react';\nimport { ShopifyStorefrontClient } from '../services/shopify/shopifyStorefrontClient';\nimport { resolveShopifyEntity } from '../services/shopify/shopifyEntityResolver';\nimport { transformShopifyEntityToItemData } from '../services/shopify/transformShopifyEntity';\nimport type { ShopifyStorefrontConfig } from '../services/shopify/types';\nimport type { EntityItemData } from '../component/types';\n\n// Session-level cache: entityType:entityId:variantId → resolved EntityItemData\nconst shopifyEntityCache = new Map<string, EntityItemData>();\n\nfunction cacheKey(\n entityType: string,\n entityId: string,\n variantId?: string,\n): string {\n return `${entityType}:${entityId}:${variantId || ''}`;\n}\n\nfunction normalizeShopifyEntityType(entityType: string): string {\n const lower = entityType.toLowerCase();\n // A variant is not a Storefront resource of its own — there is no\n // `variantByHandle`. It is fetched as its parent product and then priced at\n // the variant the lookup carries alongside, which is why `variant` and\n // `product` normalize to the same query here rather than to two.\n if (lower.includes('product') || lower.includes('variant')) {\n return 'product';\n }\n if (lower.includes('collection')) {\n return 'collection';\n }\n if (lower.includes('article') || lower.includes('blog')) {\n return 'article';\n }\n return entityType;\n}\n\nfunction extractHandleFromUrl(url: string | undefined): string | undefined {\n const trimmed = url?.trim();\n if (!trimmed) {\n return undefined;\n }\n\n let pathname = trimmed;\n try {\n if (/^https?:\\/\\//i.test(trimmed)) {\n pathname = new URL(trimmed).pathname;\n }\n } catch {\n pathname = trimmed;\n }\n\n const withoutQuery = pathname.split(/[?#]/)[0];\n const withoutLeadingSlash = withoutQuery.replace(/^\\/+/, '');\n const productsIndex = withoutLeadingSlash.indexOf('products/');\n if (productsIndex >= 0) {\n return withoutLeadingSlash.slice(productsIndex + 'products/'.length);\n }\n\n const collectionsIndex = withoutLeadingSlash.indexOf('collections/');\n if (collectionsIndex >= 0) {\n return withoutLeadingSlash.slice(\n collectionsIndex + 'collections/'.length,\n );\n }\n\n return withoutLeadingSlash || undefined;\n}\n\n/**\n * The `?variant=` the row's own URL already carries.\n *\n * A row that names a variant — whether the turn overlaid one onto a product or\n * sent the variant as the entity itself — always links to it, because that is\n * the URL a shopper has to land on. So when the row omits `variantId` as a\n * field, the URL still says which child it means, and pricing the parent's\n * default instead would contradict the link on the same card.\n */\nfunction variantIdFromUrl(url: string | undefined): string | undefined {\n const query = url?.split('#')[0].split('?')[1];\n if (!query) {\n return undefined;\n }\n return new URLSearchParams(query).get('variant')?.trim() || undefined;\n}\n\nexport function getShopifyLookup(entity: {\n entityId: string;\n entityType: string;\n data?: EntityItemData;\n}) {\n const entityType = normalizeShopifyEntityType(entity.entityType);\n const urlHandle = extractHandleFromUrl(entity.data?.url);\n const entityId =\n (entityType === 'product' || entityType === 'collection') && urlHandle\n ? urlHandle\n : entity.entityId;\n return {\n entityType,\n entityId,\n variantId: entity.data?.variantId ?? variantIdFromUrl(entity.data?.url),\n };\n}\n\n/**\n * The turn owns WHICH thing to show; the live fetch owns VOLATILE FACTS about\n * it.\n *\n * Only the turn saw the shopper's question, so only it knows that the brown\n * variant was the one asked for — its `title`, `imageUrl`, `url`,\n * `matchedOptions` and `variantId` all describe that one variant and must\n * survive enrichment. Everything the Storefront answers with that can go stale\n * between the turn and the render — `price`, `compareAtPrice`, `available`,\n * `priceMin`, `priceMax` — comes from `resolved`.\n */\nexport function mergeShopifyEntityData(\n existing: EntityItemData | undefined,\n resolved: EntityItemData,\n): EntityItemData {\n if (!existing) {\n return resolved;\n }\n\n return {\n ...existing,\n ...resolved,\n url: existing.url || resolved.url,\n title: existing.title || resolved.title,\n imageUrl: existing.imageUrl || resolved.imageUrl,\n variantId: existing.variantId || resolved.variantId,\n matchedOptions: existing.matchedOptions?.length\n ? existing.matchedOptions\n : resolved.matchedOptions,\n };\n}\n\n/**\n * Shopify-specific implementation of the entity resolution pattern.\n *\n * Fetches entity data from the Shopify Storefront API (tokenless) and\n * transforms it to the standard EntityItemData shape.\n *\n * Designed to be plugged into ComponentDependencies.useResolveGenericEntityData.\n */\nexport function useResolveShopifyEntityData<\n TEntity extends {\n entityId: string;\n entityUrl: string;\n entityType: string;\n data?: EntityItemData;\n },\n>(\n entities: TEntity[],\n shopifyConfig: ShopifyStorefrontConfig,\n): { enrichedEntities: TEntity[]; loading: boolean } {\n const [resolvedMap, setResolvedMap] = useState<Map<string, EntityItemData>>(\n new Map(),\n );\n const [settled, setSettled] = useState(false);\n\n // Stable client reference — recreated only when config changes\n const clientRef = useRef<ShopifyStorefrontClient | null>(null);\n const configKeyRef = useRef('');\n const configKey = `${shopifyConfig.storeDomain}|${\n shopifyConfig.apiVersion || ''\n }`;\n\n if (!clientRef.current || configKeyRef.current !== configKey) {\n clientRef.current = new ShopifyStorefrontClient(shopifyConfig);\n configKeyRef.current = configKey;\n }\n\n const entityIds = useMemo(\n () =>\n entities\n .map((e) => {\n const lookup = getShopifyLookup(e);\n return `${e.entityType}:${e.entityId}:${cacheKey(\n lookup.entityType,\n lookup.entityId,\n lookup.variantId,\n )}`;\n })\n .join(','),\n [entities],\n );\n\n useEffect(() => {\n let ignore = false;\n const client = clientRef.current;\n\n if (!entities.length || !client || !shopifyConfig.storeDomain) {\n setSettled(true);\n return;\n }\n\n const entityLookups = entities.map((entity) => {\n const lookup = getShopifyLookup(entity);\n return {\n entity,\n lookup,\n // The variant is part of the key: the cached entry carries that\n // variant's live price, so two entities on the same product but\n // different variants must not share it.\n key: cacheKey(lookup.entityType, lookup.entityId, lookup.variantId),\n };\n });\n\n // Identify entities that need fetching. Payload data can provide the handle.\n const toFetch = entityLookups.filter(\n ({ key }) => !shopifyEntityCache.has(key),\n );\n\n // If everything is cached, resolve immediately\n if (toFetch.length === 0) {\n const cached = new Map<string, EntityItemData>();\n entityLookups.forEach(({ entity, key }) => {\n const item = shopifyEntityCache.get(key);\n if (item) {\n cached.set(entity.entityId, mergeShopifyEntityData(entity.data, item));\n }\n });\n setResolvedMap(cached);\n setSettled(true);\n return;\n }\n\n setSettled(false);\n\n const fetchAll = async () => {\n await Promise.allSettled(\n toFetch.map(async ({ entity, lookup, key }) => {\n const resolved = await resolveShopifyEntity(\n client,\n lookup.entityType,\n lookup.entityId,\n shopifyConfig,\n );\n if (resolved) {\n const itemData = transformShopifyEntityToItemData(\n resolved,\n lookup.entityType,\n lookup.variantId,\n );\n shopifyEntityCache.set(\n key,\n mergeShopifyEntityData(entity.data, itemData),\n );\n }\n }),\n );\n\n if (ignore) {\n return;\n }\n\n // Build the resolved map from cache\n const finalMap = new Map<string, EntityItemData>();\n entityLookups.forEach(({ entity, key }) => {\n const item = shopifyEntityCache.get(key);\n if (item) {\n finalMap.set(\n entity.entityId,\n mergeShopifyEntityData(entity.data, item),\n );\n }\n });\n\n setResolvedMap(finalMap);\n setSettled(true);\n };\n\n fetchAll();\n return () => {\n ignore = true;\n };\n }, [entityIds, shopifyConfig.storeDomain]);\n\n // Merge resolved data into entities\n const enrichedEntities = useMemo(() => {\n return entities.map((entity) => {\n const resolved = resolvedMap.get(entity.entityId);\n if (resolved) {\n return { ...entity, data: resolved };\n }\n return entity;\n });\n }, [entities, resolvedMap]);\n\n return { enrichedEntities, loading: !settled };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -9,7 +9,11 @@ function cacheKey(entityType, entityId, variantId) {
|
|
|
9
9
|
}
|
|
10
10
|
function normalizeShopifyEntityType(entityType) {
|
|
11
11
|
const lower = entityType.toLowerCase();
|
|
12
|
-
|
|
12
|
+
// A variant is not a Storefront resource of its own — there is no
|
|
13
|
+
// `variantByHandle`. It is fetched as its parent product and then priced at
|
|
14
|
+
// the variant the lookup carries alongside, which is why `variant` and
|
|
15
|
+
// `product` normalize to the same query here rather than to two.
|
|
16
|
+
if (lower.includes('product') || lower.includes('variant')) {
|
|
13
17
|
return 'product';
|
|
14
18
|
}
|
|
15
19
|
if (lower.includes('collection')) {
|
|
@@ -45,15 +49,33 @@ function extractHandleFromUrl(url) {
|
|
|
45
49
|
}
|
|
46
50
|
return withoutLeadingSlash || undefined;
|
|
47
51
|
}
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The `?variant=` the row's own URL already carries.
|
|
55
|
+
*
|
|
56
|
+
* A row that names a variant — whether the turn overlaid one onto a product or
|
|
57
|
+
* sent the variant as the entity itself — always links to it, because that is
|
|
58
|
+
* the URL a shopper has to land on. So when the row omits `variantId` as a
|
|
59
|
+
* field, the URL still says which child it means, and pricing the parent's
|
|
60
|
+
* default instead would contradict the link on the same card.
|
|
61
|
+
*/
|
|
62
|
+
function variantIdFromUrl(url) {
|
|
63
|
+
var _URLSearchParams$get;
|
|
64
|
+
const query = url == null ? void 0 : url.split('#')[0].split('?')[1];
|
|
65
|
+
if (!query) {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
return ((_URLSearchParams$get = new URLSearchParams(query).get('variant')) == null ? void 0 : _URLSearchParams$get.trim()) || undefined;
|
|
69
|
+
}
|
|
70
|
+
export function getShopifyLookup(entity) {
|
|
71
|
+
var _entity$data, _entity$data2, _entity$data3;
|
|
50
72
|
const entityType = normalizeShopifyEntityType(entity.entityType);
|
|
51
73
|
const urlHandle = extractHandleFromUrl((_entity$data = entity.data) == null ? void 0 : _entity$data.url);
|
|
52
74
|
const entityId = (entityType === 'product' || entityType === 'collection') && urlHandle ? urlHandle : entity.entityId;
|
|
53
75
|
return {
|
|
54
76
|
entityType,
|
|
55
77
|
entityId,
|
|
56
|
-
variantId: (_entity$data2 = entity.data) == null ? void 0 : _entity$data2.variantId
|
|
78
|
+
variantId: ((_entity$data2 = entity.data) == null ? void 0 : _entity$data2.variantId) ?? variantIdFromUrl((_entity$data3 = entity.data) == null ? void 0 : _entity$data3.url)
|
|
57
79
|
};
|
|
58
80
|
}
|
|
59
81
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useState","useEffect","useMemo","useRef","ShopifyStorefrontClient","resolveShopifyEntity","transformShopifyEntityToItemData","shopifyEntityCache","Map","cacheKey","entityType","entityId","variantId","normalizeShopifyEntityType","lower","toLowerCase","includes","extractHandleFromUrl","url","trimmed","trim","undefined","pathname","test","URL","withoutQuery","split","withoutLeadingSlash","replace","productsIndex","indexOf","slice","length","collectionsIndex","getShopifyLookup","entity","_entity$data","_entity$data2","urlHandle","data","mergeShopifyEntityData","existing","resolved","_existing$matchedOpti","title","imageUrl","matchedOptions","useResolveShopifyEntityData","entities","shopifyConfig","resolvedMap","setResolvedMap","settled","setSettled","clientRef","configKeyRef","configKey","storeDomain","apiVersion","current","entityIds","map","e","lookup","join","ignore","client","entityLookups","key","toFetch","filter","_ref","has","cached","forEach","_ref2","item","get","set","fetchAll","Promise","allSettled","_ref3","itemData","finalMap","_ref4","enrichedEntities","loading"],"sources":["../../../src/hooks/useResolveShopifyEntityData.ts"],"sourcesContent":["import { useState, useEffect, useMemo, useRef } from 'react';\nimport { ShopifyStorefrontClient } from '../services/shopify/shopifyStorefrontClient';\nimport { resolveShopifyEntity } from '../services/shopify/shopifyEntityResolver';\nimport { transformShopifyEntityToItemData } from '../services/shopify/transformShopifyEntity';\nimport type { ShopifyStorefrontConfig } from '../services/shopify/types';\nimport type { EntityItemData } from '../component/types';\n\n// Session-level cache: entityType:entityId:variantId → resolved EntityItemData\nconst shopifyEntityCache = new Map<string, EntityItemData>();\n\nfunction cacheKey(\n entityType: string,\n entityId: string,\n variantId?: string,\n): string {\n return `${entityType}:${entityId}:${variantId || ''}`;\n}\n\nfunction normalizeShopifyEntityType(entityType: string): string {\n const lower = entityType.toLowerCase();\n if (lower.includes('product')) {\n return 'product';\n }\n if (lower.includes('collection')) {\n return 'collection';\n }\n if (lower.includes('article') || lower.includes('blog')) {\n return 'article';\n }\n return entityType;\n}\n\nfunction extractHandleFromUrl(url: string | undefined): string | undefined {\n const trimmed = url?.trim();\n if (!trimmed) {\n return undefined;\n }\n\n let pathname = trimmed;\n try {\n if (/^https?:\\/\\//i.test(trimmed)) {\n pathname = new URL(trimmed).pathname;\n }\n } catch {\n pathname = trimmed;\n }\n\n const withoutQuery = pathname.split(/[?#]/)[0];\n const withoutLeadingSlash = withoutQuery.replace(/^\\/+/, '');\n const productsIndex = withoutLeadingSlash.indexOf('products/');\n if (productsIndex >= 0) {\n return withoutLeadingSlash.slice(productsIndex + 'products/'.length);\n }\n\n const collectionsIndex = withoutLeadingSlash.indexOf('collections/');\n if (collectionsIndex >= 0) {\n return withoutLeadingSlash.slice(\n collectionsIndex + 'collections/'.length,\n );\n }\n\n return withoutLeadingSlash || undefined;\n}\n\nfunction getShopifyLookup(entity: {\n entityId: string;\n entityType: string;\n data?: EntityItemData;\n}) {\n const entityType = normalizeShopifyEntityType(entity.entityType);\n const urlHandle = extractHandleFromUrl(entity.data?.url);\n const entityId =\n (entityType === 'product' || entityType === 'collection') && urlHandle\n ? urlHandle\n : entity.entityId;\n return { entityType, entityId, variantId: entity.data?.variantId };\n}\n\n/**\n * The turn owns WHICH thing to show; the live fetch owns VOLATILE FACTS about\n * it.\n *\n * Only the turn saw the shopper's question, so only it knows that the brown\n * variant was the one asked for — its `title`, `imageUrl`, `url`,\n * `matchedOptions` and `variantId` all describe that one variant and must\n * survive enrichment. Everything the Storefront answers with that can go stale\n * between the turn and the render — `price`, `compareAtPrice`, `available`,\n * `priceMin`, `priceMax` — comes from `resolved`.\n */\nexport function mergeShopifyEntityData(\n existing: EntityItemData | undefined,\n resolved: EntityItemData,\n): EntityItemData {\n if (!existing) {\n return resolved;\n }\n\n return {\n ...existing,\n ...resolved,\n url: existing.url || resolved.url,\n title: existing.title || resolved.title,\n imageUrl: existing.imageUrl || resolved.imageUrl,\n variantId: existing.variantId || resolved.variantId,\n matchedOptions: existing.matchedOptions?.length\n ? existing.matchedOptions\n : resolved.matchedOptions,\n };\n}\n\n/**\n * Shopify-specific implementation of the entity resolution pattern.\n *\n * Fetches entity data from the Shopify Storefront API (tokenless) and\n * transforms it to the standard EntityItemData shape.\n *\n * Designed to be plugged into ComponentDependencies.useResolveGenericEntityData.\n */\nexport function useResolveShopifyEntityData<\n TEntity extends {\n entityId: string;\n entityUrl: string;\n entityType: string;\n data?: EntityItemData;\n },\n>(\n entities: TEntity[],\n shopifyConfig: ShopifyStorefrontConfig,\n): { enrichedEntities: TEntity[]; loading: boolean } {\n const [resolvedMap, setResolvedMap] = useState<Map<string, EntityItemData>>(\n new Map(),\n );\n const [settled, setSettled] = useState(false);\n\n // Stable client reference — recreated only when config changes\n const clientRef = useRef<ShopifyStorefrontClient | null>(null);\n const configKeyRef = useRef('');\n const configKey = `${shopifyConfig.storeDomain}|${\n shopifyConfig.apiVersion || ''\n }`;\n\n if (!clientRef.current || configKeyRef.current !== configKey) {\n clientRef.current = new ShopifyStorefrontClient(shopifyConfig);\n configKeyRef.current = configKey;\n }\n\n const entityIds = useMemo(\n () =>\n entities\n .map((e) => {\n const lookup = getShopifyLookup(e);\n return `${e.entityType}:${e.entityId}:${cacheKey(\n lookup.entityType,\n lookup.entityId,\n lookup.variantId,\n )}`;\n })\n .join(','),\n [entities],\n );\n\n useEffect(() => {\n let ignore = false;\n const client = clientRef.current;\n\n if (!entities.length || !client || !shopifyConfig.storeDomain) {\n setSettled(true);\n return;\n }\n\n const entityLookups = entities.map((entity) => {\n const lookup = getShopifyLookup(entity);\n return {\n entity,\n lookup,\n // The variant is part of the key: the cached entry carries that\n // variant's live price, so two entities on the same product but\n // different variants must not share it.\n key: cacheKey(lookup.entityType, lookup.entityId, lookup.variantId),\n };\n });\n\n // Identify entities that need fetching. Payload data can provide the handle.\n const toFetch = entityLookups.filter(\n ({ key }) => !shopifyEntityCache.has(key),\n );\n\n // If everything is cached, resolve immediately\n if (toFetch.length === 0) {\n const cached = new Map<string, EntityItemData>();\n entityLookups.forEach(({ entity, key }) => {\n const item = shopifyEntityCache.get(key);\n if (item) {\n cached.set(entity.entityId, mergeShopifyEntityData(entity.data, item));\n }\n });\n setResolvedMap(cached);\n setSettled(true);\n return;\n }\n\n setSettled(false);\n\n const fetchAll = async () => {\n await Promise.allSettled(\n toFetch.map(async ({ entity, lookup, key }) => {\n const resolved = await resolveShopifyEntity(\n client,\n lookup.entityType,\n lookup.entityId,\n shopifyConfig,\n );\n if (resolved) {\n const itemData = transformShopifyEntityToItemData(\n resolved,\n lookup.entityType,\n lookup.variantId,\n );\n shopifyEntityCache.set(\n key,\n mergeShopifyEntityData(entity.data, itemData),\n );\n }\n }),\n );\n\n if (ignore) {\n return;\n }\n\n // Build the resolved map from cache\n const finalMap = new Map<string, EntityItemData>();\n entityLookups.forEach(({ entity, key }) => {\n const item = shopifyEntityCache.get(key);\n if (item) {\n finalMap.set(\n entity.entityId,\n mergeShopifyEntityData(entity.data, item),\n );\n }\n });\n\n setResolvedMap(finalMap);\n setSettled(true);\n };\n\n fetchAll();\n return () => {\n ignore = true;\n };\n }, [entityIds, shopifyConfig.storeDomain]);\n\n // Merge resolved data into entities\n const enrichedEntities = useMemo(() => {\n return entities.map((entity) => {\n const resolved = resolvedMap.get(entity.entityId);\n if (resolved) {\n return { ...entity, data: resolved };\n }\n return entity;\n });\n }, [entities, resolvedMap]);\n\n return { enrichedEntities, loading: !settled };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["useState","useEffect","useMemo","useRef","ShopifyStorefrontClient","resolveShopifyEntity","transformShopifyEntityToItemData","shopifyEntityCache","Map","cacheKey","entityType","entityId","variantId","normalizeShopifyEntityType","lower","toLowerCase","includes","extractHandleFromUrl","url","trimmed","trim","undefined","pathname","test","URL","withoutQuery","split","withoutLeadingSlash","replace","productsIndex","indexOf","slice","length","collectionsIndex","variantIdFromUrl","_URLSearchParams$get","query","URLSearchParams","get","getShopifyLookup","entity","_entity$data","_entity$data2","_entity$data3","urlHandle","data","mergeShopifyEntityData","existing","resolved","_existing$matchedOpti","title","imageUrl","matchedOptions","useResolveShopifyEntityData","entities","shopifyConfig","resolvedMap","setResolvedMap","settled","setSettled","clientRef","configKeyRef","configKey","storeDomain","apiVersion","current","entityIds","map","e","lookup","join","ignore","client","entityLookups","key","toFetch","filter","_ref","has","cached","forEach","_ref2","item","set","fetchAll","Promise","allSettled","_ref3","itemData","finalMap","_ref4","enrichedEntities","loading"],"sources":["../../../src/hooks/useResolveShopifyEntityData.ts"],"sourcesContent":["import { useState, useEffect, useMemo, useRef } from 'react';\nimport { ShopifyStorefrontClient } from '../services/shopify/shopifyStorefrontClient';\nimport { resolveShopifyEntity } from '../services/shopify/shopifyEntityResolver';\nimport { transformShopifyEntityToItemData } from '../services/shopify/transformShopifyEntity';\nimport type { ShopifyStorefrontConfig } from '../services/shopify/types';\nimport type { EntityItemData } from '../component/types';\n\n// Session-level cache: entityType:entityId:variantId → resolved EntityItemData\nconst shopifyEntityCache = new Map<string, EntityItemData>();\n\nfunction cacheKey(\n entityType: string,\n entityId: string,\n variantId?: string,\n): string {\n return `${entityType}:${entityId}:${variantId || ''}`;\n}\n\nfunction normalizeShopifyEntityType(entityType: string): string {\n const lower = entityType.toLowerCase();\n // A variant is not a Storefront resource of its own — there is no\n // `variantByHandle`. It is fetched as its parent product and then priced at\n // the variant the lookup carries alongside, which is why `variant` and\n // `product` normalize to the same query here rather than to two.\n if (lower.includes('product') || lower.includes('variant')) {\n return 'product';\n }\n if (lower.includes('collection')) {\n return 'collection';\n }\n if (lower.includes('article') || lower.includes('blog')) {\n return 'article';\n }\n return entityType;\n}\n\nfunction extractHandleFromUrl(url: string | undefined): string | undefined {\n const trimmed = url?.trim();\n if (!trimmed) {\n return undefined;\n }\n\n let pathname = trimmed;\n try {\n if (/^https?:\\/\\//i.test(trimmed)) {\n pathname = new URL(trimmed).pathname;\n }\n } catch {\n pathname = trimmed;\n }\n\n const withoutQuery = pathname.split(/[?#]/)[0];\n const withoutLeadingSlash = withoutQuery.replace(/^\\/+/, '');\n const productsIndex = withoutLeadingSlash.indexOf('products/');\n if (productsIndex >= 0) {\n return withoutLeadingSlash.slice(productsIndex + 'products/'.length);\n }\n\n const collectionsIndex = withoutLeadingSlash.indexOf('collections/');\n if (collectionsIndex >= 0) {\n return withoutLeadingSlash.slice(\n collectionsIndex + 'collections/'.length,\n );\n }\n\n return withoutLeadingSlash || undefined;\n}\n\n/**\n * The `?variant=` the row's own URL already carries.\n *\n * A row that names a variant — whether the turn overlaid one onto a product or\n * sent the variant as the entity itself — always links to it, because that is\n * the URL a shopper has to land on. So when the row omits `variantId` as a\n * field, the URL still says which child it means, and pricing the parent's\n * default instead would contradict the link on the same card.\n */\nfunction variantIdFromUrl(url: string | undefined): string | undefined {\n const query = url?.split('#')[0].split('?')[1];\n if (!query) {\n return undefined;\n }\n return new URLSearchParams(query).get('variant')?.trim() || undefined;\n}\n\nexport function getShopifyLookup(entity: {\n entityId: string;\n entityType: string;\n data?: EntityItemData;\n}) {\n const entityType = normalizeShopifyEntityType(entity.entityType);\n const urlHandle = extractHandleFromUrl(entity.data?.url);\n const entityId =\n (entityType === 'product' || entityType === 'collection') && urlHandle\n ? urlHandle\n : entity.entityId;\n return {\n entityType,\n entityId,\n variantId: entity.data?.variantId ?? variantIdFromUrl(entity.data?.url),\n };\n}\n\n/**\n * The turn owns WHICH thing to show; the live fetch owns VOLATILE FACTS about\n * it.\n *\n * Only the turn saw the shopper's question, so only it knows that the brown\n * variant was the one asked for — its `title`, `imageUrl`, `url`,\n * `matchedOptions` and `variantId` all describe that one variant and must\n * survive enrichment. Everything the Storefront answers with that can go stale\n * between the turn and the render — `price`, `compareAtPrice`, `available`,\n * `priceMin`, `priceMax` — comes from `resolved`.\n */\nexport function mergeShopifyEntityData(\n existing: EntityItemData | undefined,\n resolved: EntityItemData,\n): EntityItemData {\n if (!existing) {\n return resolved;\n }\n\n return {\n ...existing,\n ...resolved,\n url: existing.url || resolved.url,\n title: existing.title || resolved.title,\n imageUrl: existing.imageUrl || resolved.imageUrl,\n variantId: existing.variantId || resolved.variantId,\n matchedOptions: existing.matchedOptions?.length\n ? existing.matchedOptions\n : resolved.matchedOptions,\n };\n}\n\n/**\n * Shopify-specific implementation of the entity resolution pattern.\n *\n * Fetches entity data from the Shopify Storefront API (tokenless) and\n * transforms it to the standard EntityItemData shape.\n *\n * Designed to be plugged into ComponentDependencies.useResolveGenericEntityData.\n */\nexport function useResolveShopifyEntityData<\n TEntity extends {\n entityId: string;\n entityUrl: string;\n entityType: string;\n data?: EntityItemData;\n },\n>(\n entities: TEntity[],\n shopifyConfig: ShopifyStorefrontConfig,\n): { enrichedEntities: TEntity[]; loading: boolean } {\n const [resolvedMap, setResolvedMap] = useState<Map<string, EntityItemData>>(\n new Map(),\n );\n const [settled, setSettled] = useState(false);\n\n // Stable client reference — recreated only when config changes\n const clientRef = useRef<ShopifyStorefrontClient | null>(null);\n const configKeyRef = useRef('');\n const configKey = `${shopifyConfig.storeDomain}|${\n shopifyConfig.apiVersion || ''\n }`;\n\n if (!clientRef.current || configKeyRef.current !== configKey) {\n clientRef.current = new ShopifyStorefrontClient(shopifyConfig);\n configKeyRef.current = configKey;\n }\n\n const entityIds = useMemo(\n () =>\n entities\n .map((e) => {\n const lookup = getShopifyLookup(e);\n return `${e.entityType}:${e.entityId}:${cacheKey(\n lookup.entityType,\n lookup.entityId,\n lookup.variantId,\n )}`;\n })\n .join(','),\n [entities],\n );\n\n useEffect(() => {\n let ignore = false;\n const client = clientRef.current;\n\n if (!entities.length || !client || !shopifyConfig.storeDomain) {\n setSettled(true);\n return;\n }\n\n const entityLookups = entities.map((entity) => {\n const lookup = getShopifyLookup(entity);\n return {\n entity,\n lookup,\n // The variant is part of the key: the cached entry carries that\n // variant's live price, so two entities on the same product but\n // different variants must not share it.\n key: cacheKey(lookup.entityType, lookup.entityId, lookup.variantId),\n };\n });\n\n // Identify entities that need fetching. Payload data can provide the handle.\n const toFetch = entityLookups.filter(\n ({ key }) => !shopifyEntityCache.has(key),\n );\n\n // If everything is cached, resolve immediately\n if (toFetch.length === 0) {\n const cached = new Map<string, EntityItemData>();\n entityLookups.forEach(({ entity, key }) => {\n const item = shopifyEntityCache.get(key);\n if (item) {\n cached.set(entity.entityId, mergeShopifyEntityData(entity.data, item));\n }\n });\n setResolvedMap(cached);\n setSettled(true);\n return;\n }\n\n setSettled(false);\n\n const fetchAll = async () => {\n await Promise.allSettled(\n toFetch.map(async ({ entity, lookup, key }) => {\n const resolved = await resolveShopifyEntity(\n client,\n lookup.entityType,\n lookup.entityId,\n shopifyConfig,\n );\n if (resolved) {\n const itemData = transformShopifyEntityToItemData(\n resolved,\n lookup.entityType,\n lookup.variantId,\n );\n shopifyEntityCache.set(\n key,\n mergeShopifyEntityData(entity.data, itemData),\n );\n }\n }),\n );\n\n if (ignore) {\n return;\n }\n\n // Build the resolved map from cache\n const finalMap = new Map<string, EntityItemData>();\n entityLookups.forEach(({ entity, key }) => {\n const item = shopifyEntityCache.get(key);\n if (item) {\n finalMap.set(\n entity.entityId,\n mergeShopifyEntityData(entity.data, item),\n );\n }\n });\n\n setResolvedMap(finalMap);\n setSettled(true);\n };\n\n fetchAll();\n return () => {\n ignore = true;\n };\n }, [entityIds, shopifyConfig.storeDomain]);\n\n // Merge resolved data into entities\n const enrichedEntities = useMemo(() => {\n return entities.map((entity) => {\n const resolved = resolvedMap.get(entity.entityId);\n if (resolved) {\n return { ...entity, data: resolved };\n }\n return entity;\n });\n }, [entities, resolvedMap]);\n\n return { enrichedEntities, loading: !settled };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import type { ShopifyStorefrontConfig } from '../services/shopify/types';
|
|
2
2
|
import type { EntityItemData } from '../component/types';
|
|
3
|
+
export declare function getShopifyLookup(entity: {
|
|
4
|
+
entityId: string;
|
|
5
|
+
entityType: string;
|
|
6
|
+
data?: EntityItemData;
|
|
7
|
+
}): {
|
|
8
|
+
entityType: string;
|
|
9
|
+
entityId: string;
|
|
10
|
+
variantId: string | undefined;
|
|
11
|
+
};
|
|
3
12
|
/**
|
|
4
13
|
* The turn owns WHICH thing to show; the live fetch owns VOLATILE FACTS about
|
|
5
14
|
* it.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useResolveShopifyEntityData.d.ts","sourceRoot":"","sources":["../../../src/hooks/useResolveShopifyEntityData.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"useResolveShopifyEntityData.d.ts","sourceRoot":"","sources":["../../../src/hooks/useResolveShopifyEntityData.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAgFzD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,cAAc,CAAC;CACvB;;;;EAYA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,cAAc,GAAG,SAAS,EACpC,QAAQ,EAAE,cAAc,GACvB,cAAc,CAgBhB;AAED;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,SAAS;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,cAAc,CAAC;CACvB,EAED,QAAQ,EAAE,OAAO,EAAE,EACnB,aAAa,EAAE,uBAAuB,GACrC;IAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAwInD"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/web5-core",
|
|
3
3
|
"license": "MIT",
|
|
4
|
-
"version": "1.63.
|
|
4
|
+
"version": "1.63.13",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "tsachis",
|
|
7
7
|
"email": "tsachis@wix.com"
|
|
@@ -100,5 +100,5 @@
|
|
|
100
100
|
"wallaby": {
|
|
101
101
|
"autoDetect": true
|
|
102
102
|
},
|
|
103
|
-
"falconPackageHash": "
|
|
103
|
+
"falconPackageHash": "b1dae343a7e5206a65e694799d53a16d16e1f8b9bfa9eebec43fad45"
|
|
104
104
|
}
|