PageSourceSearch

https://www.nasm.org/scripts/initializers/pdp.js

js nasm.org collected 2026-09-24 08:33:24 UTC 4,523 bytes, 126 lines download raw bytes

1/* eslint-disable import/no-cycle */
2/* eslint-disable import/prefer-default-export */
3
4import { initializers } from '@dropins/tools/initializer.js';
5import { Image, provider as UI } from '@dropins/tools/components.js';
6import {
7  initialize,
8  setEndpoint,
9  setFetchGraphQlHeaders,
10  fetchProductData,
11} from '@dropins/storefront-pdp/api.js';
12import { initializeDropin } from './index.js';
13import {
14  fetchPlaceholders,
15  commerceEndpointWithQueryParams,
16  getOptionsUIDsFromUrl,
17  getSkuFromUrl,
18  loadErrorPage,
19} from '../commerce.js';
20import { getHeaders } from '../configs.js';
21
22export const IMAGES_SIZES = {
23  width: 960,
24  height: 1191,
25};
26
27await initializeDropin(async () => {
28  // Set Fetch Endpoint (Service)
29  setEndpoint(await commerceEndpointWithQueryParams());
30
31  // Set Fetch Headers (Service)
32  setFetchGraphQlHeaders((prev) => ({
33    ...prev,
34    ...getHeaders('cs'),
35    nasmprice: 'all',
36  }));
37
38  const sku = await getSkuFromUrl();
39  const optionsUIDs = getOptionsUIDsFromUrl();
40
41  const [product, labels] = await Promise.all([
42    fetchProductData(sku, { optionsUIDs, skipTransform: true }).then(preloadImageMiddleware),
43    fetchPlaceholders(),
44  ]);
45
46  if (!product?.sku) {
47    // Don't load error page in authoring environment (Universal Editor)
48    // Template/default pages won't have product data and should display empty preview
49    if (!window.xwalk?.isAuthorEnv) {
50      return loadErrorPage();
51    }
52    // In authoring environment, return early without error to allow content tree to display
53    return null;
54  }
55
56  const langDefinitions = {
57    default: {
58      ...labels,
59    },
60  };
61
62  const models = {
63    ProductDetails: {
64      initialData: { ...product },
65      transformer: (rawProduct) => {
66        if (!rawProduct) return null;
67
68        // Helper function to get attribute value by name
69        const getAttributeValue = (attributeName) => {
70          const attr = rawProduct.attributes?.find((a) => a.name === attributeName);
71          return attr?.value || '';
72        };
73
74        // Add custom fields to the transformed product
75        return {
76          videos: rawProduct.videos || [],
77          vimeo_video: getAttributeValue('vimeo_video'), // Include vimeo video URL
78          vanity_url: getAttributeValue('vanity_url'), // Include vimeo video URL
79          eyebrowSuggestLabel: getAttributeValue('eyebrow_suggest_label'),
80          promotionEndDate: getAttributeValue('promotion_end_date'),
81          promotionStartDate: getAttributeValue('promotion_start_date'),
82          promotionLabel: getAttributeValue('promotion_label'),
83          productTitleLine2: getAttributeValue('product_title_line_2'),
84          pdpType: getAttributeValue('pdp_type'),
85          badge: getAttributeValue('badge'),
86          promotionCountdownLabel: getAttributeValue('promotion_countdown_label'),
87          marketing_product_name: getAttributeValue('marketing_product_name'), // Include marketing product name for display
88          child_eyebrow_label: getAttributeValue('child_eyebrow_label'), // Include child eyebrow label for payment plans
89          child_marketing_product_name: getAttributeValue('child_marketing_product_name'), // Include child marketing product name for payment plans
90          highlight_child_sku: getAttributeValue('highlight_child_sku'), // Include highlight_child_sku for matrix product highlighting
91          nasm_price: rawProduct.nasm_price || [], // Include nasm_price data for bundle products
92          default_instalment: getAttributeValue('default_instalment'), // Include default_instalment for bundle pricing
93          additionalCourseDetails: getAttributeValue('additional_course_details'), // New virtual bundles: "Included in this bundle" source (replaces group options)
94          mapped_products: getAttributeValue('mapped_products'), // Include mapped_products for matrix products
95          plp_price: getAttributeValue('plp_price'), // Include plp_price for subscription products
96        };
97      },
98    },
99  };
100
101  // Initialize Dropins
102  return initializers.mountImmediately(initialize, {
103    sku,
104    optionsUIDs,
105    langDefinitions,
106    models,
107    acdl: true,
108    persistURLParams: true,
109  });
110})();
111
112async function preloadImageMiddleware(data) {
113  const image = data?.images?.[0]?.url?.replace(/^https?:/, '');
114
115  if (image) {
116    await UI.render(Image, {
117      src: image,
118      ...IMAGES_SIZES.mobile,
119      params: {
120        ...IMAGES_SIZES,
121      },
122      loading: 'eager',
123    })(document.createElement('div'));
124  }
125  return data;
126}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.