@salesforce/storefront-next-runtime 1.0.0-alpha.0 → 1.0.0-alpha.1
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/ComponentContext.js +199 -4
- package/dist/ComponentContext.js.map +1 -1
- package/dist/DesignComponent.js +2 -2
- package/dist/DesignRegion.js +2 -2
- package/dist/RegionContext.js +9 -0
- package/dist/RegionContext.js.map +1 -0
- package/dist/component.types.d.ts +1 -1
- package/dist/config.d.ts +6 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -1
- package/dist/config.js.map +1 -1
- package/dist/data-store.d.ts +3 -3
- package/dist/data-store.d.ts.map +1 -1
- package/dist/defaults.d.ts +106 -0
- package/dist/defaults.d.ts.map +1 -0
- package/dist/defaults.js +67 -0
- package/dist/defaults.js.map +1 -0
- package/dist/design-data.d.ts +10 -332
- package/dist/design-data.d.ts.map +1 -1
- package/dist/design-data.js +67 -23
- package/dist/design-data.js.map +1 -1
- package/dist/design-react-core.d.ts +5 -15
- package/dist/design-react-core.d.ts.map +1 -1
- package/dist/design-react-core.js +2 -2
- package/dist/design-react.d.ts +2 -2
- package/dist/design.d.ts +2 -2
- package/dist/scapi.d.ts.map +1 -1
- package/dist/security-react.d.ts +34 -0
- package/dist/security-react.d.ts.map +1 -0
- package/dist/security-react.js +21 -0
- package/dist/security-react.js.map +1 -0
- package/dist/security.d.ts +61 -0
- package/dist/security.d.ts.map +1 -0
- package/dist/security.js +304 -0
- package/dist/security.js.map +1 -0
- package/dist/site-context.d.ts +2 -2
- package/dist/types3.d.ts +1 -35
- package/dist/types3.d.ts.map +1 -1
- package/package.json +15 -2
- package/dist/DesignFrame.js +0 -204
- package/dist/DesignFrame.js.map +0 -1
package/dist/design-data.js
CHANGED
|
@@ -875,26 +875,34 @@ function validateRule(rule, locale, context) {
|
|
|
875
875
|
* Builds a component's `data` map by walking each attribute definition and
|
|
876
876
|
* picking the first non-undefined value in priority order:
|
|
877
877
|
*
|
|
878
|
-
* active-locale content → fallback
|
|
878
|
+
* active-locale content → fallback content → attrDef.defaultValue
|
|
879
|
+
*
|
|
880
|
+
* The fallback bucket is selected whole-blob style (matching SCAPI/SFRA's
|
|
881
|
+
* `__data` resolution): the site-default-locale bucket if it carries any
|
|
882
|
+
* content, otherwise the literal-default ("default") bucket. Buckets are not
|
|
883
|
+
* per-key merged with each other — only the active-locale bucket layers
|
|
884
|
+
* per-key on top of the chosen fallback (preserving today's locale override
|
|
885
|
+
* semantics).
|
|
879
886
|
*
|
|
880
887
|
* If none of those have a value the attribute is omitted from the result.
|
|
881
888
|
*
|
|
882
889
|
* When no `typeDefs` are supplied, we fall back to the legacy behavior:
|
|
883
|
-
* `{ ...nodeData, ...
|
|
890
|
+
* `{ ...nodeData, ...fallbackContent, ...localeContent }`. This keeps
|
|
884
891
|
* already-deployed manifests rendering until the manifest builder starts
|
|
885
892
|
* emitting `componentTypes`.
|
|
886
893
|
*/
|
|
887
|
-
function composeComponentData({ nodeData, defaultContent, localeContent, typeDefs }) {
|
|
894
|
+
function composeComponentData({ nodeData, literalDefaultContent, defaultContent, localeContent, typeDefs }) {
|
|
895
|
+
const fallbackContent = Object.keys(defaultContent).length > 0 ? defaultContent : literalDefaultContent;
|
|
888
896
|
if (!typeDefs || Object.keys(typeDefs).length === 0) return {
|
|
889
897
|
...nodeData ?? {},
|
|
890
|
-
...
|
|
898
|
+
...fallbackContent,
|
|
891
899
|
...localeContent
|
|
892
900
|
};
|
|
893
901
|
const result = {};
|
|
894
902
|
for (const attrId of Object.keys(typeDefs)) {
|
|
895
903
|
const def = typeDefs[attrId];
|
|
896
904
|
if (Object.prototype.hasOwnProperty.call(localeContent, attrId)) result[attrId] = localeContent[attrId];
|
|
897
|
-
else if (Object.prototype.hasOwnProperty.call(
|
|
905
|
+
else if (Object.prototype.hasOwnProperty.call(fallbackContent, attrId)) result[attrId] = fallbackContent[attrId];
|
|
898
906
|
else if (def.defaultValue !== void 0) result[attrId] = def.defaultValue;
|
|
899
907
|
}
|
|
900
908
|
return result;
|
|
@@ -948,12 +956,14 @@ function processPage(page, processorContext) {
|
|
|
948
956
|
isVisible = false;
|
|
949
957
|
}
|
|
950
958
|
}
|
|
959
|
+
const literalDefaultContent = componentInfo?.content?.default ?? {};
|
|
951
960
|
const defaultContent = componentInfo?.content?.[processorContext.defaultLocale] ?? {};
|
|
952
961
|
const localeContent = componentInfo?.content?.[processorContext.locale] ?? {};
|
|
953
962
|
const isLocalized = Boolean(componentInfo?.content?.[processorContext.locale]);
|
|
954
963
|
const typeDefs = processorContext.componentTypes?.[ctx.node.typeId]?.attributeDefinitions;
|
|
955
964
|
const composedData = composeComponentData({
|
|
956
965
|
nodeData: ctx.node.data,
|
|
966
|
+
literalDefaultContent,
|
|
957
967
|
defaultContent,
|
|
958
968
|
localeContent,
|
|
959
969
|
typeDefs
|
|
@@ -1068,18 +1078,43 @@ const ContentAssignmentResolvers = new Map([["product", (key) => ({
|
|
|
1068
1078
|
//#endregion
|
|
1069
1079
|
//#region src/design/data/manifest/resolve-dynamic-page-id.ts
|
|
1070
1080
|
/**
|
|
1081
|
+
* Looks up a single content assignment in the site manifest using the
|
|
1082
|
+
* resolver registered for the given identifier type, returning the first
|
|
1083
|
+
* matching `contentId` across the resolver's ordered key list. Returns
|
|
1084
|
+
* `null` when the identifier type has no resolver, or no key in the list
|
|
1085
|
+
* has an assignment for the requested aspect type.
|
|
1086
|
+
*/
|
|
1087
|
+
function lookupContentAssignment(id, identifierType, aspectType, siteManifest) {
|
|
1088
|
+
const lookup = ContentAssignmentResolvers.get(identifierType)?.(id, siteManifest);
|
|
1089
|
+
if (!lookup) return null;
|
|
1090
|
+
for (const key of lookup.keys) {
|
|
1091
|
+
const assignment = siteManifest?.contentObjectAssignments?.[aspectType]?.[lookup.objectType]?.[key];
|
|
1092
|
+
if (assignment) return assignment.contentId;
|
|
1093
|
+
}
|
|
1094
|
+
return null;
|
|
1095
|
+
}
|
|
1096
|
+
/**
|
|
1071
1097
|
* Converts a product or category identifier into a page ID by looking up
|
|
1072
1098
|
* content assignments in the site manifest. For categories, the lookup
|
|
1073
1099
|
* traverses the category hierarchy from the given category up to the root,
|
|
1074
1100
|
* returning the first matching assignment.
|
|
1075
1101
|
*
|
|
1076
|
-
*
|
|
1077
|
-
*
|
|
1102
|
+
* When the identifier type is `'product'` and no assignment is found, an
|
|
1103
|
+
* optional `categoryId` may be supplied as a fallback. The fallback is only
|
|
1104
|
+
* awaited and consulted after the product lookup misses, so callers that
|
|
1105
|
+
* resolve the product's category lazily (e.g. via a SCAPI request) don't
|
|
1106
|
+
* pay for the round trip on the happy path.
|
|
1107
|
+
*
|
|
1108
|
+
* Returns `null` if no content assignment is found for the identifier
|
|
1109
|
+
* (and the optional category fallback, when provided), or if the identifier
|
|
1110
|
+
* type has no registered resolver.
|
|
1078
1111
|
*
|
|
1079
1112
|
* @param options - The resolution options.
|
|
1080
1113
|
* @param options.id - The identifier to resolve (product ID, category ID, or page ID).
|
|
1081
1114
|
* @param options.identifierType - The type of identifier: `'product'`, `'category'`, or `'page'`.
|
|
1115
|
+
* @param options.aspectType - The aspect type to look up (e.g. `'pdp'`, `'plp'`).
|
|
1082
1116
|
* @param options.siteManifest - The site manifest containing content assignments and category hierarchy.
|
|
1117
|
+
* @param options.categoryId - Optional fallback category ID (or a Promise resolving to one) used only when `identifierType` is `'product'` and the product lookup misses.
|
|
1083
1118
|
* @returns The resolved page ID, or `null` if no assignment was found.
|
|
1084
1119
|
*
|
|
1085
1120
|
* @example
|
|
@@ -1104,25 +1139,31 @@ const ContentAssignmentResolvers = new Map([["product", (key) => ({
|
|
|
1104
1139
|
* };
|
|
1105
1140
|
*
|
|
1106
1141
|
* // Direct match
|
|
1107
|
-
* resolveDynamicPageId({ id: 'mens-shoes', identifierType: 'category', siteManifest });
|
|
1142
|
+
* await resolveDynamicPageId({ id: 'mens-shoes', identifierType: 'category', aspectType: 'plp', siteManifest });
|
|
1108
1143
|
* // => 'page-mens-shoes-plp'
|
|
1109
1144
|
*
|
|
1110
1145
|
* // Inherited from parent category
|
|
1111
|
-
* resolveDynamicPageId({ id: 'mens-running-shoes', identifierType: 'category', siteManifest });
|
|
1146
|
+
* await resolveDynamicPageId({ id: 'mens-running-shoes', identifierType: 'category', aspectType: 'plp', siteManifest });
|
|
1112
1147
|
* // => 'page-mens-shoes-plp' (found via parent traversal)
|
|
1113
1148
|
*
|
|
1114
|
-
* //
|
|
1115
|
-
* resolveDynamicPageId({
|
|
1116
|
-
*
|
|
1149
|
+
* // Product missing but a category fallback is provided
|
|
1150
|
+
* await resolveDynamicPageId({
|
|
1151
|
+
* id: 'unknown-product',
|
|
1152
|
+
* identifierType: 'product',
|
|
1153
|
+
* aspectType: 'plp',
|
|
1154
|
+
* siteManifest,
|
|
1155
|
+
* categoryId: 'mens-running-shoes',
|
|
1156
|
+
* });
|
|
1157
|
+
* // => 'page-mens-shoes-plp'
|
|
1117
1158
|
* ```
|
|
1118
1159
|
*/
|
|
1119
|
-
function resolveDynamicPageId({ id, identifierType, siteManifest, aspectType }) {
|
|
1120
|
-
const
|
|
1121
|
-
if (
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
return
|
|
1160
|
+
async function resolveDynamicPageId({ id, identifierType, siteManifest, aspectType, categoryId }) {
|
|
1161
|
+
const direct = lookupContentAssignment(id, identifierType, aspectType, siteManifest);
|
|
1162
|
+
if (direct) return direct;
|
|
1163
|
+
if (identifierType !== "product" || categoryId == null) return null;
|
|
1164
|
+
const resolvedCategoryId = await categoryId;
|
|
1165
|
+
if (!resolvedCategoryId) return null;
|
|
1166
|
+
return lookupContentAssignment(resolvedCategoryId, "category", aspectType, siteManifest);
|
|
1126
1167
|
}
|
|
1127
1168
|
|
|
1128
1169
|
//#endregion
|
|
@@ -1274,6 +1315,7 @@ function applyPageMetadataOverlay(variation, locale) {
|
|
|
1274
1315
|
* @param options.manifestStorage - Storage implementation for fetching manifests.
|
|
1275
1316
|
* @param options.contextResolver - Optional async function that returns the shopper's qualifier context. Only called if a visibility rule needs it.
|
|
1276
1317
|
* @param options.aspectType - The aspect type to resolve the page for when the identifier type is `'product'` or `'category'`.
|
|
1318
|
+
* @param options.categoryId - Optional fallback category ID (or a Promise resolving to one) used only when `identifierType` is `'product'` and the product has no content assignment for the requested aspect type. The promise is awaited lazily — the happy path never pays for it.
|
|
1277
1319
|
* @param options.pruneInvisible - When `true` (default), invisible and overflow components are removed. When `false`, they are kept but marked `visible: false` for design/preview mode.
|
|
1278
1320
|
* @returns The fully resolved and filtered page, or `null`.
|
|
1279
1321
|
*
|
|
@@ -1311,21 +1353,23 @@ function applyPageMetadataOverlay(variation, locale) {
|
|
|
1311
1353
|
* }
|
|
1312
1354
|
* ```
|
|
1313
1355
|
*/
|
|
1314
|
-
async function resolvePage({ id, identifierType, aspectType, locale, defaultLocale, manifestStorage, contextResolver, attrCtx, pruneInvisible = true }) {
|
|
1356
|
+
async function resolvePage({ id, identifierType, aspectType, categoryId, locale, defaultLocale, manifestStorage, contextResolver, attrCtx, pruneInvisible = true }) {
|
|
1315
1357
|
let resolvedId = null;
|
|
1316
1358
|
if (ContentAssignmentResolvers.has(identifierType)) {
|
|
1317
1359
|
const siteManifest = await manifestStorage.getSiteManifest();
|
|
1318
1360
|
RequiredError.assert(aspectType, `Aspect type is required for identifier type ${identifierType}`, (v) => !v);
|
|
1319
|
-
resolvedId = resolveDynamicPageId({
|
|
1361
|
+
resolvedId = await resolveDynamicPageId({
|
|
1320
1362
|
id,
|
|
1321
1363
|
identifierType,
|
|
1322
1364
|
aspectType,
|
|
1323
|
-
siteManifest
|
|
1365
|
+
siteManifest,
|
|
1366
|
+
categoryId
|
|
1324
1367
|
});
|
|
1325
1368
|
} else resolvedId = id;
|
|
1326
1369
|
if (!resolvedId) return null;
|
|
1327
1370
|
const pageManifest = await manifestStorage.getPageManifest(resolvedId);
|
|
1328
1371
|
if (!pageManifest) return null;
|
|
1372
|
+
if (pageManifest.context?.dataBindings?.length > 0) return null;
|
|
1329
1373
|
const pageResults = await getPageFromManifest(pageManifest, {
|
|
1330
1374
|
contextResolver,
|
|
1331
1375
|
locale
|
|
@@ -1351,5 +1395,5 @@ async function resolvePage({ id, identifierType, aspectType, locale, defaultLoca
|
|
|
1351
1395
|
}
|
|
1352
1396
|
|
|
1353
1397
|
//#endregion
|
|
1354
|
-
export {
|
|
1398
|
+
export { RequiredError, processPage, resolvePage, transformComponent, transformPage, transformRegion, validateRule };
|
|
1355
1399
|
//# sourceMappingURL=design-data.js.map
|