@amplifyup/sdk 0.1.43 → 0.1.45

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.
@@ -1,4 +1,4 @@
1
- import { f as AmplifyUpTarget } from './types-DUP8Lb7R.mjs';
1
+ import { i as AmplifyUpTarget } from './types-NdLzHxZo.mjs';
2
2
 
3
3
  /**
4
4
  * On-request variant selection (tier 3).
@@ -1,4 +1,4 @@
1
- import { f as AmplifyUpTarget } from './types-DUP8Lb7R.js';
1
+ import { i as AmplifyUpTarget } from './types-NdLzHxZo.js';
2
2
 
3
3
  /**
4
4
  * On-request variant selection (tier 3).
package/dist/react.d.mts CHANGED
@@ -1,9 +1,9 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { P as PageConfig, c as AmplifyUpConfig, e as AmplifyPageContextInput, C as ContentSource, A as AmplifyContentMeta } from './types-NdLzHxZo.mjs';
3
+ export { Z as ZoneConfig } from './types-NdLzHxZo.mjs';
2
4
  import React, { ReactNode } from 'react';
3
- import { P as PageConfig, b as AmplifyUpConfig, C as ContentSource, A as AmplifyContentMeta } from './types-DUP8Lb7R.mjs';
4
- export { Z as ZoneConfig } from './types-DUP8Lb7R.mjs';
5
5
  export { AmplifyRenderer } from './AmplifyRenderer.mjs';
6
- export { Q as QueryContentError, e as QueryContentOptions, k as QueryFilter, l as QueryFilterOp, i as QueryPagination, h as QueryResult, m as QuerySort, j as QuerySpec, S as SelectVariantsError, a as SelectVariantsOptions, b as SelectVariantsResult, n as nextPageSpec, q as queryContent, d as searchSpec, s as selectVariants } from './query-CraXKhi7.mjs';
6
+ export { Q as QueryContentError, e as QueryContentOptions, k as QueryFilter, l as QueryFilterOp, i as QueryPagination, h as QueryResult, m as QuerySort, j as QuerySpec, S as SelectVariantsError, a as SelectVariantsOptions, b as SelectVariantsResult, n as nextPageSpec, q as queryContent, d as searchSpec, s as selectVariants } from './query-2-zPPrMI.mjs';
7
7
  export { i as isComposerPreview, a as isPreviewRequest, b as isWorkingContentRequest } from './preview-_vHmzRen.mjs';
8
8
  export { fetchPageConfigServer } from './server.mjs';
9
9
  import './reservedRoutes-aGgViBDM.mjs';
@@ -137,8 +137,13 @@ interface AmplifyUpContextType {
137
137
  interface AmplifyUpProviderProps {
138
138
  children: ReactNode;
139
139
  config: AmplifyUpConfig;
140
+ /**
141
+ * Required when this page uses Composer "From page" components.
142
+ * Pass at provider/init so the first paint and first page view include fields.
143
+ */
144
+ pageContext?: AmplifyPageContextInput;
140
145
  }
141
- declare function AmplifyUpProvider({ children, config }: AmplifyUpProviderProps): react_jsx_runtime.JSX.Element;
146
+ declare function AmplifyUpProvider({ children, config, pageContext, }: AmplifyUpProviderProps): react_jsx_runtime.JSX.Element;
142
147
  declare function useAmplifyUp(): AmplifyUpContextType;
143
148
 
144
149
  export { AmplifyContentMeta, AmplifyPageContent, AmplifyUpProvider, ComponentContextProvider, ContentSource, Field, Image, PageConfig, RichText, Slot, useAmplifyUp, useComponentProps, useLiveComposerProps };
package/dist/react.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { P as PageConfig, c as AmplifyUpConfig, e as AmplifyPageContextInput, C as ContentSource, A as AmplifyContentMeta } from './types-NdLzHxZo.js';
3
+ export { Z as ZoneConfig } from './types-NdLzHxZo.js';
2
4
  import React, { ReactNode } from 'react';
3
- import { P as PageConfig, b as AmplifyUpConfig, C as ContentSource, A as AmplifyContentMeta } from './types-DUP8Lb7R.js';
4
- export { Z as ZoneConfig } from './types-DUP8Lb7R.js';
5
5
  export { AmplifyRenderer } from './AmplifyRenderer.js';
6
- export { Q as QueryContentError, e as QueryContentOptions, k as QueryFilter, l as QueryFilterOp, i as QueryPagination, h as QueryResult, m as QuerySort, j as QuerySpec, S as SelectVariantsError, a as SelectVariantsOptions, b as SelectVariantsResult, n as nextPageSpec, q as queryContent, d as searchSpec, s as selectVariants } from './query-BMsorj0k.js';
6
+ export { Q as QueryContentError, e as QueryContentOptions, k as QueryFilter, l as QueryFilterOp, i as QueryPagination, h as QueryResult, m as QuerySort, j as QuerySpec, S as SelectVariantsError, a as SelectVariantsOptions, b as SelectVariantsResult, n as nextPageSpec, q as queryContent, d as searchSpec, s as selectVariants } from './query-CFpvzSZT.js';
7
7
  export { i as isComposerPreview, a as isPreviewRequest, b as isWorkingContentRequest } from './preview-_vHmzRen.js';
8
8
  export { fetchPageConfigServer } from './server.js';
9
9
  import './reservedRoutes-aGgViBDM.js';
@@ -137,8 +137,13 @@ interface AmplifyUpContextType {
137
137
  interface AmplifyUpProviderProps {
138
138
  children: ReactNode;
139
139
  config: AmplifyUpConfig;
140
+ /**
141
+ * Required when this page uses Composer "From page" components.
142
+ * Pass at provider/init so the first paint and first page view include fields.
143
+ */
144
+ pageContext?: AmplifyPageContextInput;
140
145
  }
141
- declare function AmplifyUpProvider({ children, config }: AmplifyUpProviderProps): react_jsx_runtime.JSX.Element;
146
+ declare function AmplifyUpProvider({ children, config, pageContext, }: AmplifyUpProviderProps): react_jsx_runtime.JSX.Element;
142
147
  declare function useAmplifyUp(): AmplifyUpContextType;
143
148
 
144
149
  export { AmplifyContentMeta, AmplifyPageContent, AmplifyUpProvider, ComponentContextProvider, ContentSource, Field, Image, PageConfig, RichText, Slot, useAmplifyUp, useComponentProps, useLiveComposerProps };
package/dist/react.js CHANGED
@@ -411,6 +411,205 @@ function isComposerPreview() {
411
411
  return false;
412
412
  }
413
413
 
414
+ // src/page-context.ts
415
+ function extractRouteParams(pattern, url) {
416
+ const patternParts = String(pattern || "").split("/").filter(Boolean);
417
+ const urlParts = String(url || "").split("?")[0].split("#")[0].split("/").filter(Boolean);
418
+ if (patternParts.length !== urlParts.length) return {};
419
+ const params = {};
420
+ for (let i = 0; i < patternParts.length; i++) {
421
+ const part = patternParts[i];
422
+ if (part.startsWith(":")) {
423
+ params[part.slice(1)] = urlParts[i];
424
+ }
425
+ }
426
+ return params;
427
+ }
428
+ var defaultLog = {
429
+ warn: (...args) => {
430
+ if (typeof console !== "undefined") console.warn(...args);
431
+ }
432
+ };
433
+ function coerceField(def, raw, log) {
434
+ if (raw == null) return void 0;
435
+ if (def.multiValue) {
436
+ const list = Array.isArray(raw) ? raw : [raw];
437
+ const out = [];
438
+ for (const item of list) {
439
+ const coerced = coerceScalar(def, item, log);
440
+ if (coerced !== void 0) out.push(coerced);
441
+ }
442
+ return out;
443
+ }
444
+ return coerceScalar(def, raw, log);
445
+ }
446
+ function coerceScalar(def, raw, log) {
447
+ switch (def.dataType) {
448
+ case "string":
449
+ if (typeof raw === "string") return raw;
450
+ if (typeof raw === "number" || typeof raw === "boolean") return String(raw);
451
+ log.warn(`AmplifyUp: dropped field "${def.key}" (expected string)`);
452
+ return void 0;
453
+ case "number": {
454
+ if (typeof raw === "number" && Number.isFinite(raw)) return raw;
455
+ if (typeof raw === "string" && raw.trim() !== "" && Number.isFinite(Number(raw))) {
456
+ return Number(raw);
457
+ }
458
+ log.warn(`AmplifyUp: dropped field "${def.key}" (expected number)`);
459
+ return void 0;
460
+ }
461
+ case "boolean": {
462
+ if (typeof raw === "boolean") return raw;
463
+ if (raw === "true") return true;
464
+ if (raw === "false") return false;
465
+ log.warn(`AmplifyUp: dropped field "${def.key}" (expected boolean)`);
466
+ return void 0;
467
+ }
468
+ case "date": {
469
+ if (typeof raw === "string" && !Number.isNaN(Date.parse(raw))) return raw;
470
+ log.warn(`AmplifyUp: dropped field "${def.key}" (expected date)`);
471
+ return void 0;
472
+ }
473
+ default:
474
+ return void 0;
475
+ }
476
+ }
477
+ function applyPageContext(input, opts) {
478
+ const log = opts.log || defaultLog;
479
+ const key = String(input.key || "").trim();
480
+ if (!key || !input.resourceType) {
481
+ log.warn("AmplifyUp: pageContext needs resourceType and key");
482
+ return null;
483
+ }
484
+ const resource = opts.pageData?.resources?.[0];
485
+ if (resource && resource.type && resource.type !== input.resourceType) {
486
+ log.warn(
487
+ `AmplifyUp: pageContext resourceType "${input.resourceType}" does not match page resource "${resource.type}"`
488
+ );
489
+ return null;
490
+ }
491
+ const fieldDefs = resource?.fields || [];
492
+ const defByKey = new Map(fieldDefs.map((f) => [f.key, f]));
493
+ const rawFields = input.fields && typeof input.fields === "object" ? input.fields : {};
494
+ const fields = {};
495
+ if (fieldDefs.length === 0) {
496
+ Object.assign(fields, rawFields);
497
+ } else {
498
+ for (const [k, v] of Object.entries(rawFields)) {
499
+ const def = defByKey.get(k);
500
+ if (!def) {
501
+ log.warn(`AmplifyUp: unknown resource field "${k}" dropped`);
502
+ continue;
503
+ }
504
+ const coerced = coerceField(def, v, log);
505
+ if (coerced !== void 0) fields[k] = coerced;
506
+ }
507
+ }
508
+ const params = { ...opts.routeParams || {} };
509
+ const mapping = resource?.urlParamMapping;
510
+ let resourceKey = key;
511
+ if (mapping) {
512
+ const fromUrl = params[mapping.param];
513
+ const fromField = fields[mapping.field];
514
+ if (fromUrl) resourceKey = String(fromUrl);
515
+ if (fromUrl && fromField != null && String(fromField) !== String(fromUrl)) {
516
+ log.warn(
517
+ `AmplifyUp: resource key mismatch \u2014 URL :${mapping.param} is "${fromUrl}" but ${mapping.field} is "${String(fromField)}". Using the URL param.`
518
+ );
519
+ }
520
+ }
521
+ const pageFields = {};
522
+ for (const pf of opts.pageData?.pageFields || []) {
523
+ if (pf.source === "static") {
524
+ if (pf.value !== void 0) pageFields[pf.key] = pf.value;
525
+ continue;
526
+ }
527
+ if (pf.source === "mapped" && pf.resource && pf.field) {
528
+ pageFields[pf.key] = fields[pf.field];
529
+ }
530
+ }
531
+ return {
532
+ resource: {
533
+ type: input.resourceType,
534
+ key: resourceKey,
535
+ params,
536
+ fields
537
+ },
538
+ page: { fields: pageFields },
539
+ pageRoute: opts.pageRoute || ""
540
+ };
541
+ }
542
+ function staticPageFieldsFromSnapshot(pageData) {
543
+ const pageFields = {};
544
+ for (const pf of pageData?.pageFields || []) {
545
+ if (pf.source === "static" && pf.value !== void 0) {
546
+ pageFields[pf.key] = pf.value;
547
+ }
548
+ }
549
+ return pageFields;
550
+ }
551
+ function attachStaticPageContext(pageData, pageRoute) {
552
+ if (!pageData) return null;
553
+ const fields = staticPageFieldsFromSnapshot(pageData);
554
+ const hasStatic = Object.keys(fields).length > 0;
555
+ const hasRoute = !!pageRoute;
556
+ if (!hasStatic && !hasRoute) return null;
557
+ return {
558
+ page: { fields },
559
+ pageRoute: pageRoute || ""
560
+ };
561
+ }
562
+ function mergeEventContext(properties, attached) {
563
+ if (!attached) return properties;
564
+ return {
565
+ ...properties,
566
+ ...attached.resource ? { resource: attached.resource } : {},
567
+ page: attached.page,
568
+ ...attached.pageRoute ? { pageRoute: attached.pageRoute } : {}
569
+ };
570
+ }
571
+ var PAGE_RESOURCE_MARKER = "__amplifyupPageResource";
572
+ function isPageResourceSentinel(value) {
573
+ return !!value && typeof value === "object" && !Array.isArray(value) && typeof value[PAGE_RESOURCE_MARKER] === "string";
574
+ }
575
+ function getByDotPath(source, path) {
576
+ if (!path) return source;
577
+ const parts = path.split(".").filter(Boolean);
578
+ let cur = source;
579
+ for (const part of parts) {
580
+ if (cur == null || typeof cur !== "object" || Array.isArray(cur)) {
581
+ return void 0;
582
+ }
583
+ cur = cur[part];
584
+ }
585
+ return cur;
586
+ }
587
+ function hydratePageResourceValue(value, fields) {
588
+ if (!isPageResourceSentinel(value)) return value;
589
+ if (!fields) return null;
590
+ if (value.path) return getByDotPath(fields, value.path) ?? null;
591
+ return fields;
592
+ }
593
+ function hydratePageResourceProps(props, fields) {
594
+ const source = props && typeof props === "object" ? props : {};
595
+ const out = { ...source };
596
+ for (const [key, val] of Object.entries(out)) {
597
+ if (isPageResourceSentinel(val)) {
598
+ out[key] = hydratePageResourceValue(val, fields);
599
+ }
600
+ }
601
+ return out;
602
+ }
603
+
604
+ // src/page-resource-runtime.ts
605
+ var pageResourceFields = null;
606
+ function setPageResourceFields(fields) {
607
+ pageResourceFields = fields && typeof fields === "object" ? fields : null;
608
+ }
609
+ function getPageResourceFields() {
610
+ return pageResourceFields;
611
+ }
612
+
414
613
  // src/edge/normalizeRoute.ts
415
614
  function normalizeRoute(route) {
416
615
  let path = String(route || "").trim();
@@ -530,7 +729,8 @@ function mapResolvedToPageConfig(payload) {
530
729
  // Stash edge meta for diagnostics (not visitor-facing)
531
730
  description: payload.meta?.degraded ? "degraded" : void 0
532
731
  },
533
- ...payload.eventTracking && payload.eventTracking.length > 0 ? { eventTracking: payload.eventTracking } : {}
732
+ ...payload.eventTracking && payload.eventTracking.length > 0 ? { eventTracking: payload.eventTracking } : {},
733
+ ...payload.pageData ? { pageData: payload.pageData } : {}
534
734
  };
535
735
  }
536
736
  function collectDegraded(payload) {
@@ -820,6 +1020,11 @@ var AmplifyUpSDK = class {
820
1020
  this.pageEngagementActive = false;
821
1021
  /** Path of the last page() / routeChange — avoids duplicate SPA fires. */
822
1022
  this.lastTrackedPath = null;
1023
+ this.pendingPageContext = null;
1024
+ this.attachedPageContext = null;
1025
+ this.resolvedPageData = null;
1026
+ this.resolvedPageRoute = "";
1027
+ this.resolvedRouteParams = {};
823
1028
  this.historyHooksInstalled = false;
824
1029
  this.pageEngagementState = {
825
1030
  reached: /* @__PURE__ */ new Set(),
@@ -982,8 +1187,13 @@ var AmplifyUpSDK = class {
982
1187
  // Enable debug by default
983
1188
  target: this.target,
984
1189
  dev: config.dev,
985
- ...config.siteId ? { siteId: config.siteId } : {}
1190
+ ...config.siteId ? { siteId: config.siteId } : {},
1191
+ ...config.pageContext ? { pageContext: config.pageContext } : {}
986
1192
  };
1193
+ if (config.pageContext) {
1194
+ this.pendingPageContext = config.pageContext;
1195
+ this.recomputeAttachedContext();
1196
+ }
987
1197
  try {
988
1198
  const adapterConfig = {
989
1199
  ...this.config,
@@ -1340,6 +1550,44 @@ var AmplifyUpSDK = class {
1340
1550
  this.componentViewObservers.forEach((obs) => obs.disconnect());
1341
1551
  this.componentViewObservers = [];
1342
1552
  }
1553
+ /**
1554
+ * Set resource context for this page. Prefer passing `pageContext` on
1555
+ * AmplifyUpProvider / init — required for components using From page.
1556
+ * Late calls still attach to subsequent events (not a second page view).
1557
+ */
1558
+ setPageContext(input) {
1559
+ this.pendingPageContext = input;
1560
+ this.recomputeAttachedContext();
1561
+ }
1562
+ /**
1563
+ * Apply published pageData (from /v1/resolve) so field validation and
1564
+ * mapped page fields can run.
1565
+ */
1566
+ applyResolvedPageData(pageData, pageRoute, routeParams) {
1567
+ this.resolvedPageData = pageData || null;
1568
+ if (pageRoute) this.resolvedPageRoute = pageRoute;
1569
+ if (routeParams) this.resolvedRouteParams = routeParams;
1570
+ this.recomputeAttachedContext();
1571
+ }
1572
+ recomputeAttachedContext() {
1573
+ if (!this.pendingPageContext) {
1574
+ this.attachedPageContext = attachStaticPageContext(
1575
+ this.resolvedPageData,
1576
+ this.resolvedPageRoute
1577
+ );
1578
+ setPageResourceFields(null);
1579
+ return;
1580
+ }
1581
+ this.attachedPageContext = applyPageContext(this.pendingPageContext, {
1582
+ pageData: this.resolvedPageData,
1583
+ routeParams: this.resolvedRouteParams,
1584
+ pageRoute: this.resolvedPageRoute
1585
+ });
1586
+ setPageResourceFields(this.attachedPageContext?.resource?.fields || null);
1587
+ }
1588
+ getAttachedPageContext() {
1589
+ return this.attachedPageContext;
1590
+ }
1343
1591
  /**
1344
1592
  * Track a page view
1345
1593
  */
@@ -1361,7 +1609,7 @@ var AmplifyUpSDK = class {
1361
1609
  sessionId,
1362
1610
  trackingId: this.config?.trackingId,
1363
1611
  // Timestamp is included in event payload
1364
- ...properties
1612
+ ...mergeEventContext(properties || {}, this.attachedPageContext)
1365
1613
  };
1366
1614
  this.adapter.page(pageProperties);
1367
1615
  this.lastTrackedPath = url;
@@ -1385,7 +1633,7 @@ var AmplifyUpSDK = class {
1385
1633
  url: typeof window !== "undefined" ? window.location.href : void 0,
1386
1634
  path: properties?.path || (typeof window !== "undefined" ? window.location.pathname : void 0),
1387
1635
  // Timestamp is included in event payload
1388
- ...properties
1636
+ ...mergeEventContext(properties || {}, this.attachedPageContext)
1389
1637
  };
1390
1638
  if (!trackProperties.path && typeof window !== "undefined") {
1391
1639
  trackProperties.path = window.location.pathname;
@@ -3138,7 +3386,10 @@ function ComponentContextProvider({
3138
3386
  layoutNodeId,
3139
3387
  componentId
3140
3388
  }) {
3141
- const liveProps = useLiveComposerProps(layoutNodeId, props || {});
3389
+ const liveProps = useLiveComposerProps(
3390
+ layoutNodeId,
3391
+ hydratePageResourceProps(props || {}, getPageResourceFields())
3392
+ );
3142
3393
  return /* @__PURE__ */ jsxRuntime.jsx(
3143
3394
  ComponentContext.Provider,
3144
3395
  {
@@ -4341,7 +4592,11 @@ if (typeof window !== "undefined") {
4341
4592
  }
4342
4593
  }
4343
4594
  var AmplifyUpContext = React.createContext(null);
4344
- function AmplifyUpProvider({ children, config }) {
4595
+ function AmplifyUpProvider({
4596
+ children,
4597
+ config,
4598
+ pageContext
4599
+ }) {
4345
4600
  const [initialized, setInitialized] = React.useState(false);
4346
4601
  const [pageConfig, setPageConfig] = React.useState(null);
4347
4602
  const [loading, setLoading] = React.useState(true);
@@ -4400,7 +4655,10 @@ function AmplifyUpProvider({ children, config }) {
4400
4655
  React.useEffect(() => {
4401
4656
  let cancelled = false;
4402
4657
  const sdk = getSDK();
4403
- sdk.init(config).then(() => {
4658
+ sdk.init({
4659
+ ...config,
4660
+ ...pageContext ? { pageContext } : {}
4661
+ }).then(() => {
4404
4662
  if (!cancelled) {
4405
4663
  setInitialized(true);
4406
4664
  }
@@ -4413,7 +4671,11 @@ function AmplifyUpProvider({ children, config }) {
4413
4671
  return () => {
4414
4672
  cancelled = true;
4415
4673
  };
4416
- }, [config.trackingId, config.target, config.debug, config.dev, config.siteId]);
4674
+ }, [config.trackingId, config.target, config.debug, config.dev, config.siteId, pageContext]);
4675
+ React.useEffect(() => {
4676
+ if (!initialized || !pageContext) return;
4677
+ getSDK().setPageContext(pageContext);
4678
+ }, [initialized, pageContext]);
4417
4679
  React.useEffect(() => {
4418
4680
  if (!initialized) return;
4419
4681
  let cancelled = false;
@@ -4488,6 +4750,11 @@ function AmplifyUpProvider({ children, config }) {
4488
4750
  });
4489
4751
  } else {
4490
4752
  setPageConfig(result.pageConfig);
4753
+ sdk.applyResolvedPageData(
4754
+ result.pageConfig.pageData || null,
4755
+ result.pageConfig.route,
4756
+ extractRouteParams(result.pageConfig.route, actualRoute)
4757
+ );
4491
4758
  }
4492
4759
  } catch (err) {
4493
4760
  if (cancelled) return;