summaryrefslogtreecommitdiff
path: root/node_modules/@jet-app/app-store/tmp/src/common/builders/url-mapping.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/@jet-app/app-store/tmp/src/common/builders/url-mapping.js')
-rw-r--r--node_modules/@jet-app/app-store/tmp/src/common/builders/url-mapping.js627
1 files changed, 627 insertions, 0 deletions
diff --git a/node_modules/@jet-app/app-store/tmp/src/common/builders/url-mapping.js b/node_modules/@jet-app/app-store/tmp/src/common/builders/url-mapping.js
new file mode 100644
index 0000000..fdaa85b
--- /dev/null
+++ b/node_modules/@jet-app/app-store/tmp/src/common/builders/url-mapping.js
@@ -0,0 +1,627 @@
+import { isNothing, isSome } from "@jet/environment/types/optional";
+import * as mediaAPI from "@apple-media-services/media-api";
+import * as serverData from "../../foundation/json-parsing/server-data";
+import * as mediaDataFetching from "../../foundation/media/data-fetching";
+import * as urlBuilder from "../../foundation/media/url-builder";
+import { Host, Parameters, Path, previewHosts, ProductPageParameters } from "../../foundation/network/url-constants";
+import { configureMediaRequestForGameRecommendations } from "../../gameservicesui/src/foundation/media-api/requests/game-recommendations";
+import * as client from "../../foundation/wrappers/client";
+import { isAdPlacementEnabled } from "../ads/ad-common";
+import * as appPromotionsCommon from "../app-promotions/app-promotions-common";
+import * as privacySuppression from "../privacy/privacy-suppression";
+import * as productPageVariants from "../product-page/product-page-variants";
+import * as mediaRequestUtils from "./url-mapping-utils";
+import { addDeveloperRequestProperties, makeDeveloperRequest } from "../developer/developer-request";
+import { isReviewSummaryEnabled } from "../product-page/reviews";
+import { isProductAccessibilityLabelsEnabled, shouldSuppressAccessibilityLabelsForAdamId, shouldSuppressAccessibilityLabelsForBundleId, } from "../accessibility/accessibility-common";
+import { buildArticlePageRequest } from "../today/article-request";
+import { makeRoutableArticlePageIntent } from "../../api/intents/routable-article-page-intent";
+import { getLocale } from "../locale";
+import { shouldUsePrerenderedIconArtwork } from "../content/content";
+import { AppEventsAttributes } from "../../gameservicesui/src/foundation/media-api/requests/recommendation-request-types";
+import { MediaApiConfiguration } from "../../gameservicesui/src/foundation/media-api/media-api-configuration";
+const appsResourceAttributes = [
+ "description",
+ "fileSizeByDevice",
+ "messagesScreenshots",
+ "minimumOSVersion",
+ "privacyPolicyUrl",
+ "promotionalText",
+ "screenshotsByType",
+ "supportsFunCamera",
+ "supportURLForLanguage",
+ "versionHistory",
+ "videoPreviewsByType",
+ "websiteUrl",
+ "expectedReleaseDateDisplayFormat",
+ "requirementsByDeviceFamily",
+ "remoteControllerRequirement",
+ "backgroundAssetsInfo",
+ "backgroundAssetsInfoWithOptional",
+ "supportsSharePlay",
+ "installSizeByDeviceInBytes",
+ "miniGamesDeepLink",
+ "gameDisplayName",
+];
+// exporting this will be bad in the long run
+// adding for <rdar://problem/39578622> Catagories: Games results in cannot connect to app store.
+// should be removed when we stop handling media api urls in the router
+export function isMediaUrl(objectGraph, url) {
+ const host = url.host;
+ if (serverData.isNull(host)) {
+ return false;
+ }
+ const mediaApiHosts = [
+ objectGraph.bag.mediaHost,
+ objectGraph.bag.mediaEdgeHost(objectGraph),
+ objectGraph.bag.mediaEdgeSearchHost,
+ ];
+ for (const mediaApiHost of mediaApiHosts) {
+ if (serverData.isNull(mediaApiHost)) {
+ continue;
+ }
+ if (host.indexOf(mediaApiHost) !== -1) {
+ return true;
+ }
+ }
+ return false;
+}
+export function hrefToRoutableUrl(objectGraph, href, additionalQueryParams) {
+ if (isNothing(href)) {
+ return undefined;
+ }
+ if (preprocessor.GAMES_TARGET) {
+ const request = new mediaAPI.Request(objectGraph, href);
+ if (isSome(additionalQueryParams)) {
+ for (const [key, value] of Object.entries(additionalQueryParams)) {
+ request.addingQuery(key, value);
+ }
+ }
+ return mediaAPI.buildURLFromRequest(new MediaApiConfiguration(objectGraph), request).toString();
+ }
+ else {
+ const request = new mediaDataFetching.Request(objectGraph, href).addingQueryValues(additionalQueryParams);
+ return urlBuilder.buildURLFromRequest(objectGraph, request).toString();
+ }
+}
+// region Grouping
+export function mediaApiGroupingURLFromHref(objectGraph, href) {
+ const attributes = [
+ "editorialArtwork",
+ "editorialVideo",
+ "isAppleWatchSupported",
+ "requiredCapabilities",
+ "minimumOSVersion",
+ "expectedReleaseDateDisplayFormat",
+ ];
+ if (objectGraph.appleSilicon.isSupportEnabled) {
+ attributes.push("macRequiredCapabilities");
+ }
+ if (objectGraph.client.isMac) {
+ attributes.push("hasMacIPAPackage");
+ }
+ if (objectGraph.bag.enableUpdatedAgeRatings) {
+ attributes.push("ageRating");
+ }
+ if (shouldUsePrerenderedIconArtwork(objectGraph)) {
+ attributes.push("iconArtwork");
+ }
+ // <rdar://problem/56198088> Catalyst apps have clickable 'get' button on 10.14.
+ // - minimumOSVersion required to filter catalyst apps from groupings.
+ const mediaApiRequest = new mediaDataFetching.Request(objectGraph, href)
+ .includingAttributes(attributes)
+ .includingAgeRestrictions()
+ .includingMacOSCompatibleIOSAppsWhenSupported();
+ if (appPromotionsCommon.appEventsAreEnabled(objectGraph)) {
+ mediaApiRequest.enablingFeature("appEvents");
+ mediaApiRequest.includingScopedAttributes("app-events", AppEventsAttributes);
+ mediaApiRequest.includingScopedRelationships("app-events", ["app"]);
+ mediaApiRequest.includingScopedRelationships("editorial-item-shelves", ["app-events"]);
+ }
+ const context = mediaDataFetching.defaultGroupingContextForClient(objectGraph);
+ if (serverData.isDefinedNonNull(context)) {
+ mediaApiRequest.addingQuery("contexts", context);
+ }
+ return mediaApiRequest;
+}
+// endregion
+// region Editorial Stories
+export function mappedMediaApiEditorialItemURL(objectGraph, url, isIncomingURL) {
+ const pathComponents = url.pathComponents();
+ if (pathComponents.indexOf("story") < 0 &&
+ pathComponents.indexOf("editorialItem") < 0 &&
+ pathComponents.indexOf("viewEditorialItem") < 0 &&
+ url.host !== Host.spamBlockingExtensions &&
+ url.host !== Host.sharePlayApps &&
+ url.host !== Host.buddyOnboarding) {
+ throw new Error(`Unable to map ${url.build()} to a media api url`);
+ }
+ let editorialItemId;
+ if (url.host === Host.spamBlockingExtensions) {
+ // Populate editorial item ID for spam blocking extensions.
+ editorialItemId = objectGraph.props.asString("spamBlockingExtensionsEditorialItemID");
+ }
+ else if (url.host === Host.sharePlayApps) {
+ editorialItemId = objectGraph.bag.sharePlayAppsEditorialItemId;
+ }
+ else if (url.host === Host.buddyOnboarding) {
+ editorialItemId = objectGraph.bag.buddyOnboardingEditorialItemId;
+ }
+ else {
+ // Otherwise extract the ID from the URL.
+ editorialItemId = extractedIdFromURL(url);
+ }
+ if (!serverData.isNumber(editorialItemId)) {
+ throw new Error(`Unable to map ${url.build()} to a media api url`);
+ }
+ if (!serverData.isNumber(editorialItemId)) {
+ throw new Error(`Unable to map ${url} to a media api url`);
+ }
+ const mediaApiRequest = buildArticlePageRequest(objectGraph, makeRoutableArticlePageIntent({
+ ...getLocale(objectGraph),
+ id: editorialItemId,
+ }), isIncomingURL);
+ const editorialCardId = url.query[Parameters.editorialCardId];
+ if (serverData.isDefinedNonNullNonEmpty(editorialCardId)) {
+ mediaApiRequest.withFilter("canvas:cardId", editorialCardId);
+ }
+ const previewParam = url.query[Parameters.preview];
+ if (previewHosts.has(url.host) && (previewParam === null || previewParam === void 0 ? void 0 : previewParam.length) > 0) {
+ mediaApiRequest.addingQuery("preview", previewParam);
+ mediaApiRequest.isStorePreviewRequest = true;
+ }
+ return mediaApiRequest.attributingTo(url.build());
+}
+// endregion
+// region Product
+const entityIdRegex = /id([0-9]+)\/?$/i;
+export function extractedIdFromURL(url) {
+ // 1. Look at the query parameter for the id
+ let extractedId = url.query["id"];
+ // 2. Consider the last path component /id<id>
+ const pathName = url.pathname;
+ if (serverData.isNull(extractedId) && (pathName === null || pathName === void 0 ? void 0 : pathName.length) > 0) {
+ const match = entityIdRegex.exec(pathName);
+ if (match && match.length > 1) {
+ extractedId = match[1];
+ }
+ }
+ // 3. At this point, if the ID is not found, try looking for /<id> instead, since this is what the last path
+ // component looks like in QA now.
+ if (!serverData.isNumber(extractedId)) {
+ const pathComponents = url.pathComponents();
+ if (serverData.isDefinedNonNullNonEmpty(pathComponents)) {
+ extractedId = pathComponents[pathComponents.length - 1];
+ }
+ }
+ return extractedId;
+}
+const productRedirectionTable = {
+ "915249334": "1462947752", // rdar://49929244 (SAD: Redirect from the old 2nd party Shortcuts product page to the new 1st party page on iOS 13)
+};
+export function mappedMediaApiProductURL(objectGraph, url, includeUnlistedApps = false) {
+ var _a, _b;
+ let productId = extractedIdFromURL(url);
+ if (!serverData.isNumber(productId)) {
+ throw new Error(`Unable to map ${url.build()} to a media api url`);
+ }
+ // Redirect to a different product if needed
+ if (productId in productRedirectionTable) {
+ productId = productRedirectionTable[productId];
+ }
+ let resourceType = "apps";
+ let attributes = appsResourceAttributes;
+ let relationships = [];
+ if (preprocessor.GAMES_TARGET) {
+ relationships = ["alternate-apps"];
+ }
+ else {
+ relationships = [
+ "customers-also-bought-apps",
+ "reviews",
+ "app-bundles",
+ "top-in-apps",
+ "related-editorial-items",
+ "alternate-apps",
+ ];
+ }
+ const pathComponents = (_a = url.pathname) === null || _a === void 0 ? void 0 : _a.split("/");
+ const isBundle = isSome(pathComponents) && pathComponents.includes(Path.productBundle);
+ if (isBundle) {
+ resourceType = "app-bundles";
+ attributes = [
+ "screenshotsByType",
+ "videoPreviewsByType",
+ "minimumOSVersion",
+ "requirementsByDeviceFamily",
+ "remoteControllerRequirement",
+ ];
+ relationships = ["apps", "reviews", "related-editorial-items"];
+ }
+ if (!preprocessor.GAMES_TARGET) {
+ relationships.push("developer-other-apps");
+ }
+ if (objectGraph.bag.enablePrivacyNutritionLabels &&
+ !privacySuppression.shouldSuppressPrivacyInformationForAdamId(objectGraph, productId)) {
+ attributes.push("privacy");
+ }
+ if (isProductAccessibilityLabelsEnabled(objectGraph) &&
+ !shouldSuppressAccessibilityLabelsForAdamId(objectGraph, productId)) {
+ attributes.push("accessibility");
+ }
+ if (objectGraph.appleSilicon.isSupportEnabled) {
+ attributes.push("macRequiredCapabilities");
+ }
+ if (objectGraph.client.isMac) {
+ attributes.push("hasMacIPAPackage");
+ }
+ if (objectGraph.bag.enableUpdatedAgeRatings) {
+ attributes.push("ageRating");
+ }
+ if (shouldUsePrerenderedIconArtwork(objectGraph)) {
+ attributes.push("iconArtwork");
+ }
+ if (objectGraph.bag.enableLicenses) {
+ attributes.push("licenses");
+ }
+ // TODO <rdar://problem/49763626> Product Page should not request developer information if supportsArcade is false
+ // We need to pipe the supportsArcade information from the sidepack, through the lockup, to the productPage action URL
+ // until then, isArcade will always be null.
+ // If no arcade affiliation is specified, or the product definitely isArcade, fetch the developer genre.
+ const isArcade = serverData.asBoolean(url.query[Parameters.isArcade]);
+ if (isArcade === null || isArcade) {
+ attributes.push("minPlayers", "maxPlayers", "editorialVideo");
+ relationships.push("developer");
+ }
+ if (objectGraph.client.isVision) {
+ attributes.push("compatibilityControllerRequirement");
+ attributes.push("isHighMotion");
+ if (objectGraph.featureFlags.isEnabled("spatial_controllers_2025A")) {
+ attributes.push("spatialControllerRequirement");
+ }
+ }
+ if (objectGraph.bag.enableSellerInfo) {
+ attributes.push("sellerInfo");
+ }
+ // Extends the API to include Internet Content Provider Info
+ if (objectGraph.bag.enableSellerICPAnnotation) {
+ attributes.push("internetContentProviderInfo");
+ }
+ // Extends the API to include supported Game Center features.
+ if (objectGraph.bag.gameCenterExtendSupportedFeatures) {
+ attributes.push("supportedGameCenterFeatures");
+ }
+ // Extends the API to include Review Summary
+ if (isReviewSummaryEnabled(objectGraph)) {
+ relationships.push("review-summary");
+ }
+ if (preprocessor.GAMES_TARGET) {
+ attributes.push("gamesUrl");
+ attributes.push("isEligibleForGamesApp");
+ }
+ const mediaApiRequest = new mediaDataFetching.Request(objectGraph)
+ .withIdOfType(productId, resourceType)
+ .includingAdditionalPlatforms(mediaDataFetching.defaultAdditionalPlatformsForClient(objectGraph))
+ .includingAgeRestrictions()
+ .includingRelationships(relationships)
+ .includingAttributes(attributes)
+ .includingMacOSCompatibleIOSAppsWhenSupported(true)
+ .usingCustomAttributes(productPageVariants.shouldFetchCustomAttributes(objectGraph))
+ .includingViews(["categorizations"]);
+ if (!preprocessor.GAMES_TARGET) {
+ mediaApiRequest.addingRelationshipLimit("reviews", mediaDataFetching.defaultProductPageReviewsLimitForClient(objectGraph));
+ }
+ if (preprocessor.GAMES_TARGET) {
+ mediaApiRequest.includingScopedRelationships("apps", ["activities", "challenges"]);
+ mediaApiRequest.includingViews(["customers-also-bought-games", "developer-other-games"]);
+ mediaApiRequest.enablingFeature("unlistedApps");
+ if (objectGraph.debugSettings.enableHighlightsFromProductPageResponse) {
+ configureMediaRequestForGameRecommendations(mediaApiRequest);
+ }
+ }
+ if (((_b = url.query[Parameters.productVariantID]) === null || _b === void 0 ? void 0 : _b.length) > 0) {
+ mediaApiRequest.addingQuery(Parameters.productVariantID, url.query[Parameters.productVariantID]);
+ }
+ // If a `minExternalVersionId` is specified, pass this through to the MAPI request
+ const minExternalVersionId = url.query[ProductPageParameters.minExternalVersionId];
+ if (serverData.isDefinedNonNull(minExternalVersionId)) {
+ mediaApiRequest.addingQuery(ProductPageParameters.minExternalVersionId, minExternalVersionId);
+ }
+ // Disabling for bundles due to rdar://78542145 ([REG] Pre-Prod JS: SkySeed: App bundle product page does not load)
+ if (appPromotionsCommon.appEventsAreEnabled(objectGraph) && !isBundle) {
+ if (!appPromotionsCommon.appContingentItemsAreEnabled(objectGraph)) {
+ mediaApiRequest.includingScopedRelationships("apps", ["app-events"]);
+ }
+ mediaApiRequest.includingScopedAttributes("app-events", AppEventsAttributes);
+ mediaApiRequest.includingScopedAvailableIn("app-events", ["future"]);
+ }
+ if (appPromotionsCommon.appContingentItemsAreEnabled(objectGraph)) {
+ mediaRequestUtils.configureContingentItemsForMediaRequest(mediaApiRequest);
+ }
+ if (appPromotionsCommon.appOfferItemsAreEnabled(objectGraph)) {
+ mediaRequestUtils.configureOfferItemsForMediaRequest(mediaApiRequest);
+ }
+ if (isAdPlacementEnabled(objectGraph, "productPageYMAL")) {
+ mediaApiRequest.enablingFeature("cabAdSupport");
+ }
+ if (includeUnlistedApps) {
+ mediaApiRequest.enablingFeature("unlistedApps");
+ }
+ if (!appPromotionsCommon.appContingentItemsAreEnabled(objectGraph)) {
+ mediaApiRequest.includingRelationships(["merchandised-in-apps"]);
+ }
+ return mediaApiRequest.attributingTo(url.build());
+}
+// endregion
+// region Developer
+export function mediaApiDeveloperURLFromHref(objectGraph, href) {
+ const mediaApiRequest = new mediaDataFetching.Request(objectGraph, href);
+ return addDeveloperRequestProperties(objectGraph, mediaApiRequest);
+}
+export function mappedMediaApiDeveloperURL(objectGraph, url) {
+ const developerId = extractedIdFromURL(url);
+ if (!serverData.isNumber(developerId)) {
+ throw new Error(`Unable to map ${url.build()} to a media api url`);
+ }
+ return makeDeveloperRequest(objectGraph, developerId);
+}
+// endregion
+// region Charts
+/**
+ * Creates a Media API request for one or more charts using provided critera.
+ * @param objectGraph The App Store object graph.
+ * @param genreId The genre for the chart request.
+ * @param charts The list of charts for the request.
+ * @param ageBandId The age band to include in the request.
+ * @param clientIdentifier The identifier of the current client.
+ * @returns A Media API request for one or more charts using provided critera.
+ */
+export function mediaApiChartRequestForGenre(objectGraph, genreId, charts, ageBandId = null, clientIdentifier = objectGraph.host.clientIdentifier) {
+ const attributes = ["isAppleWatchSupported", "requiredCapabilities", "minimumOSVersion"];
+ if (objectGraph.appleSilicon.isSupportEnabled) {
+ attributes.push("macRequiredCapabilities");
+ }
+ if (objectGraph.client.isMac) {
+ attributes.push("hasMacIPAPackage");
+ }
+ const mediaApiRequest = new mediaDataFetching.Request(objectGraph)
+ .forType("charts")
+ .addingQuery("genre", genreId)
+ .includingAttributes(attributes)
+ .addingQuery("types", "apps")
+ .includingMacOSCompatibleIOSAppsWhenSupported(true)
+ .includingAdditionalPlatforms(mediaDataFetching.defaultAdditionalPlatformsForClient(objectGraph))
+ .usingCustomAttributes(productPageVariants.shouldFetchCustomAttributes(objectGraph));
+ if (serverData.isDefinedNonNullNonEmpty(charts)) {
+ mediaApiRequest.addingQuery(Parameters.charts, charts);
+ }
+ if (clientIdentifier === client.watchIdentifier) {
+ mediaApiRequest.addingContext("watch");
+ }
+ else if (clientIdentifier === client.messagesIdentifier) {
+ mediaApiRequest.addingContext("messages");
+ }
+ if (objectGraph.appleSilicon.isSupportEnabled) {
+ mediaApiRequest.includingAdditionalPlatforms(["iphone", "ipad"]);
+ }
+ if (isSome(ageBandId)) {
+ mediaApiRequest.addingQuery(Parameters.ages, ageBandId);
+ }
+ return mediaApiRequest;
+}
+export function mediaApiChartsRequest(objectGraph, genreId, ageBandId = null) {
+ let request = new mediaDataFetching.Request(objectGraph)
+ .forType("charts")
+ .addingQuery("types", "apps")
+ .addingQuery("genre", genreId)
+ .includingMacOSCompatibleIOSAppsWhenSupported(true);
+ if (ageBandId) {
+ request = request.addingQuery("ages", ageBandId);
+ }
+ if (objectGraph.appleSilicon.isSupportEnabled) {
+ request = request.includingAdditionalPlatforms(["iphone", "ipad"]);
+ }
+ return request;
+}
+// endregion
+// region Lookups
+export function lookupURLForProductId(objectGraph, productId, isPurchasesProduct, productVariantID, isBundle, includeUnlistedApps) {
+ const attributes = appsResourceAttributes;
+ if (objectGraph.bag.enablePrivacyNutritionLabels &&
+ !privacySuppression.shouldSuppressPrivacyInformationForAdamId(objectGraph, productId)) {
+ attributes.push("privacy");
+ // The "web" client needs the full privacy information in the initial page load;
+ // unlike other platforms, it does not load the full details on a separate page
+ if (objectGraph.client.isWeb) {
+ attributes.push("privacyDetails");
+ }
+ }
+ if (isProductAccessibilityLabelsEnabled(objectGraph) &&
+ !shouldSuppressAccessibilityLabelsForAdamId(objectGraph, productId)) {
+ attributes.push("accessibility");
+ // The web client requires complete accessibility information on initial page load.
+ // Unlike other platforms that load full details on separate pages,
+ // the web client displays this information in a modal overlay.
+ if (objectGraph.client.isWeb) {
+ attributes.push("accessibilityDetails");
+ }
+ }
+ if (objectGraph.appleSilicon.isSupportEnabled) {
+ attributes.push("macRequiredCapabilities");
+ }
+ if (objectGraph.client.isMac) {
+ attributes.push("hasMacIPAPackage");
+ }
+ if (objectGraph.client.isVision) {
+ attributes.push("compatibilityControllerRequirement");
+ attributes.push("isHighMotion");
+ if (objectGraph.featureFlags.isEnabled("spatial_controllers_2025A")) {
+ attributes.push("spatialControllerRequirement");
+ }
+ }
+ if (objectGraph.bag.enableUpdatedAgeRatings) {
+ attributes.push("ageRating");
+ }
+ if (shouldUsePrerenderedIconArtwork(objectGraph)) {
+ attributes.push("iconArtwork");
+ }
+ if (objectGraph.bag.enableLicenses) {
+ attributes.push("licenses");
+ }
+ // Extends the API to include supported Game Center features.
+ if (objectGraph.bag.gameCenterExtendSupportedFeatures) {
+ attributes.push("supportedGameCenterFeatures");
+ }
+ const mediaApiRequest = new mediaDataFetching.Request(objectGraph)
+ .withIdOfType(productId, "apps")
+ .includingAdditionalPlatforms(mediaDataFetching.defaultAdditionalPlatformsForClient(objectGraph))
+ .includingAttributes(attributes)
+ .includingRelationships([
+ "developer",
+ "customers-also-bought-apps",
+ "developer-other-apps",
+ "reviews",
+ "app-bundles",
+ "top-in-apps",
+ "related-editorial-items",
+ "alternate-apps",
+ ])
+ .addingRelationshipLimit("reviews", mediaDataFetching.defaultProductPageReviewsLimitForClient(objectGraph))
+ .includingMacOSCompatibleIOSAppsWhenSupported(true)
+ .usingCustomAttributes(productPageVariants.shouldFetchCustomAttributes(objectGraph));
+ if (objectGraph.client.isWeb) {
+ // Ensure that the "web" client fully hydrates all PDP shelves
+ mediaApiRequest
+ .includingScopedSparseLimit("apps:customers-also-bought-apps", 40)
+ .includingScopedSparseLimit("apps:developer-other-apps", 40)
+ .includingScopedSparseLimit("apps:related-editorial-items", 40);
+ // Ensures web can render the DSA information in the annotation shelf
+ if (objectGraph.bag.enableSellerInfo) {
+ attributes.push("sellerInfo");
+ }
+ }
+ if (isPurchasesProduct) {
+ mediaApiRequest.addingQuery("availability", "redownload");
+ }
+ if (isSome(productVariantID)) {
+ mediaApiRequest.addingQuery(Parameters.productVariantID, productVariantID);
+ }
+ if (includeUnlistedApps) {
+ mediaApiRequest.enablingFeature("unlistedApps");
+ }
+ // Disabling for bundles due to rdar://78542145 ([REG] Pre-Prod JS: SkySeed: App bundle product page does not load)
+ if (appPromotionsCommon.appEventsAreEnabled(objectGraph) && !isBundle) {
+ if (!appPromotionsCommon.appContingentItemsAreEnabled(objectGraph)) {
+ mediaApiRequest.includingScopedRelationships("apps", ["app-events"]);
+ }
+ mediaApiRequest.includingScopedAttributes("app-events", AppEventsAttributes);
+ mediaApiRequest.includingScopedAvailableIn("app-events", ["future"]);
+ }
+ if (appPromotionsCommon.appContingentItemsAreEnabled(objectGraph)) {
+ mediaRequestUtils.configureContingentItemsForMediaRequest(mediaApiRequest);
+ }
+ if (appPromotionsCommon.appOfferItemsAreEnabled(objectGraph)) {
+ mediaRequestUtils.configureOfferItemsForMediaRequest(mediaApiRequest);
+ }
+ if (!appPromotionsCommon.appContingentItemsAreEnabled(objectGraph)) {
+ mediaApiRequest.includingRelationships(["merchandised-in-apps"]);
+ }
+ // Extends the API to include Review Summary
+ if (isReviewSummaryEnabled(objectGraph)) {
+ mediaApiRequest.includingRelationships(["review-summary"]);
+ }
+ if (isAdPlacementEnabled(objectGraph, "productPageYMAL")) {
+ mediaApiRequest.enablingFeature("cabAdSupport");
+ }
+ if (objectGraph.client.isMac) {
+ attributes.push("hasMacIPAPackage");
+ }
+ return mediaApiRequest;
+}
+export function lookupURLForBundleId(objectGraph, bundleId, productVariantID, includeUnlistedApps) {
+ const attributes = appsResourceAttributes;
+ if (objectGraph.bag.enablePrivacyNutritionLabels &&
+ !privacySuppression.shouldSuppressPrivacyInformationForBundleId(objectGraph, bundleId)) {
+ attributes.push("privacy");
+ }
+ if (isProductAccessibilityLabelsEnabled(objectGraph) &&
+ !shouldSuppressAccessibilityLabelsForBundleId(objectGraph, bundleId)) {
+ attributes.push("accessibility");
+ }
+ if (objectGraph.appleSilicon.isSupportEnabled) {
+ attributes.push("macRequiredCapabilities");
+ }
+ if (objectGraph.client.isMac) {
+ attributes.push("hasMacIPAPackage");
+ }
+ if (objectGraph.client.isVision) {
+ attributes.push("compatibilityControllerRequirement");
+ attributes.push("isHighMotion");
+ if (objectGraph.featureFlags.isEnabled("spatial_controllers_2025A")) {
+ attributes.push("spatialControllerRequirement");
+ }
+ }
+ if (objectGraph.bag.enableUpdatedAgeRatings) {
+ attributes.push("ageRating");
+ }
+ if (shouldUsePrerenderedIconArtwork(objectGraph)) {
+ attributes.push("iconArtwork");
+ }
+ if (objectGraph.bag.enableLicenses) {
+ attributes.push("licenses");
+ }
+ const mediaApiRequest = new mediaDataFetching.Request(objectGraph)
+ .forType("apps")
+ .withFilter("bundleId", bundleId)
+ .includingAdditionalPlatforms(mediaDataFetching.defaultAdditionalPlatformsForClient(objectGraph))
+ .includingRelationships([
+ "developer",
+ "customers-also-bought-apps",
+ "developer-other-apps",
+ "reviews",
+ "app-bundles",
+ "top-in-apps",
+ "related-editorial-items",
+ "alternate-apps",
+ ])
+ .includingAttributes(attributes)
+ .addingRelationshipLimit("reviews", mediaDataFetching.defaultProductPageReviewsLimitForClient(objectGraph))
+ .includingMacOSCompatibleIOSAppsWhenSupported(true)
+ .usingCustomAttributes(productPageVariants.shouldFetchCustomAttributes(objectGraph));
+ if (isSome(productVariantID)) {
+ mediaApiRequest.addingQuery(Parameters.productVariantID, productVariantID);
+ }
+ if (isAdPlacementEnabled(objectGraph, "productPageYMAL")) {
+ mediaApiRequest.enablingFeature("cabAdSupport");
+ }
+ if (includeUnlistedApps) {
+ mediaApiRequest.enablingFeature("unlistedApps");
+ }
+ if (appPromotionsCommon.appContingentItemsAreEnabled(objectGraph)) {
+ mediaApiRequest.includingViews(["standalone-merchandised-in-apps"]);
+ }
+ else {
+ mediaApiRequest.includingRelationships(["merchandised-in-apps"]);
+ }
+ if (objectGraph.client.isMac) {
+ attributes.push("hasMacIPAPackage");
+ }
+ return mediaApiRequest;
+}
+export function mediaApiProductSeeAllRequest(objectGraph, productId, relationship) {
+ const mediaApiRequest = new mediaDataFetching.Request(objectGraph)
+ .withIdOfType(productId, "apps")
+ .includingAdditionalPlatforms(mediaDataFetching.defaultAdditionalPlatformsForClient(objectGraph))
+ .usingCustomAttributes(productPageVariants.shouldFetchCustomAttributes(objectGraph))
+ .includingRelationships([relationship, "apps", "developer"])
+ .includingScopedSparseLimit(`apps:${relationship}`, 20);
+ if (appPromotionsCommon.appContingentItemsAreEnabled(objectGraph)) {
+ mediaRequestUtils.configureContingentItemsForMediaRequest(mediaApiRequest);
+ }
+ if (appPromotionsCommon.appOfferItemsAreEnabled(objectGraph)) {
+ mediaRequestUtils.configureOfferItemsForMediaRequest(mediaApiRequest);
+ }
+ return mediaApiRequest;
+}
+// endregion
+//# sourceMappingURL=url-mapping.js.map \ No newline at end of file