@amplifyup/sdk 0.1.67 → 0.1.69

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,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
- import { L as LayoutComponentProps, P as PageConfig } from './types-C32MgOiv.mjs';
4
+ import { L as LayoutComponentProps, P as PageConfig } from './types-CGeBbx84.mjs';
5
5
 
6
6
  interface AmplifyRendererProps {
7
7
  /**
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
- import { L as LayoutComponentProps, P as PageConfig } from './types-C32MgOiv.js';
4
+ import { L as LayoutComponentProps, P as PageConfig } from './types-CGeBbx84.js';
5
5
 
6
6
  interface AmplifyRendererProps {
7
7
  /**
@@ -436,6 +436,13 @@ function isFieldEnvelope(value) {
436
436
  const rec = value;
437
437
  return typeof rec.name === "string" && "value" in rec && !("url" in rec);
438
438
  }
439
+ var OBJECT_FIELD_KINDS = /* @__PURE__ */ new Set(["object", "array", "list"]);
440
+ function isLeafFieldKind(kind) {
441
+ if (typeof kind !== "string") return false;
442
+ const normalized = kind.trim().toLowerCase();
443
+ if (!normalized) return false;
444
+ return !OBJECT_FIELD_KINDS.has(normalized);
445
+ }
439
446
  function isPageResourceSentinel(value) {
440
447
  return !!value && typeof value === "object" && !Array.isArray(value) && typeof value.__amplifyupPageResource === "string";
441
448
  }
@@ -572,6 +579,10 @@ function toFieldEnvelopes(source, prefix = "", scope) {
572
579
  out[key] = { value: envelopeListRows(raw, owner), name: path };
573
580
  continue;
574
581
  }
582
+ if (ctx.leaf?.(path)) {
583
+ out[key] = withLeaf({ value: emptyValue(raw), name: path }, ctx);
584
+ continue;
585
+ }
575
586
  if (raw && typeof raw === "object" && !Array.isArray(raw) && !isPortableImageShape(raw) && !raw.$$typeof) {
576
587
  out[key] = toFieldEnvelopes(raw, path, ctx);
577
588
  continue;
@@ -600,15 +611,33 @@ function envelopeListRow(item, owner) {
600
611
  }
601
612
  return row;
602
613
  }
614
+ var warnedMissingFieldKind = /* @__PURE__ */ new Set();
615
+ function warnMissingFieldKind(fieldName) {
616
+ if (process.env.NODE_ENV === "production") return;
617
+ if (warnedMissingFieldKind.has(fieldName)) return;
618
+ warnedMissingFieldKind.add(fieldName);
619
+ console.warn(
620
+ `[AmplifyUp SDK] Field "${fieldName}" has no schema kind; using value-shape detection. Republish the component definition so its fields carry a type.`
621
+ );
622
+ }
603
623
  function attachFieldEnvelopes(props, sources) {
604
624
  const raw = props && typeof props === "object" ? { ...props } : {};
605
625
  if (isBrandedFields(raw.fields)) return raw;
606
626
  const { fields: existing, ...content } = raw;
607
627
  const source = existing && typeof existing === "object" && !isFieldEnvelope(existing) ? existing : content;
628
+ const { reads } = normalizeEnvelopeSources(sources);
629
+ if (reads) {
630
+ for (const [fieldName, read] of Object.entries(reads)) {
631
+ if (!read?.kind) warnMissingFieldKind(fieldName);
632
+ }
633
+ }
608
634
  return {
609
635
  ...raw,
610
636
  fields: toFieldEnvelopes(source, "", {
611
- owners: (fieldName) => listOwnerForField(fieldName, source, sources)
637
+ owners: (fieldName) => listOwnerForField(fieldName, source, sources),
638
+ // Top-level field paths equal field names; nested paths have no schema
639
+ // entry and fall back to shape-based handling.
640
+ leaf: (path) => isLeafFieldKind(reads?.[path]?.kind)
612
641
  })
613
642
  };
614
643
  }
@@ -855,6 +884,8 @@ function hydrateFieldsBag(bag, fields) {
855
884
  if (val && typeof val === "object" && !Array.isArray(val) && typeof val.name === "string" && "value" in val && !("url" in val)) {
856
885
  const env = val;
857
886
  out[key] = {
887
+ // Keep ref / readOnly / source — dropping them severs the write target.
888
+ ...val,
858
889
  name: env.name,
859
890
  value: isPageResourceSentinel2(env.value) ? hydratePageResourceValue(env.value, fields) : env.value
860
891
  };
@@ -936,6 +967,46 @@ function sdkDebugOnce(key, ...args) {
936
967
  console.log(...args);
937
968
  }
938
969
 
970
+ // src/content/layoutProviderCache.ts
971
+ var SETTLED_TTL_MS = 5e3;
972
+ var inflight = /* @__PURE__ */ new Map();
973
+ var settled = /* @__PURE__ */ new Map();
974
+ function layoutProviderCacheKey(opts) {
975
+ const route = (opts.route || "/").split("?")[0] || "/";
976
+ return [
977
+ route,
978
+ opts.trackingId || "",
979
+ opts.instanceId || "",
980
+ opts.preview ? "1" : "0",
981
+ opts.working ? "1" : "0",
982
+ opts.zoneId || "",
983
+ opts.compositionId || ""
984
+ ].join("|");
985
+ }
986
+ function getSettledLayoutProvider(key) {
987
+ const entry = settled.get(key);
988
+ if (!entry) return void 0;
989
+ if (Date.now() - entry.at > SETTLED_TTL_MS) {
990
+ settled.delete(key);
991
+ return void 0;
992
+ }
993
+ return entry.value;
994
+ }
995
+ function dedupeLayoutProviderFetch(key, fetchFn) {
996
+ const cached = getSettledLayoutProvider(key);
997
+ if (cached !== void 0) return Promise.resolve(cached);
998
+ const existing = inflight.get(key);
999
+ if (existing) return existing;
1000
+ const pending = fetchFn().then((value) => {
1001
+ settled.set(key, { value, at: Date.now() });
1002
+ return value;
1003
+ }).finally(() => {
1004
+ inflight.delete(key);
1005
+ });
1006
+ inflight.set(key, pending);
1007
+ return pending;
1008
+ }
1009
+
939
1010
  // src/index.ts
940
1011
  var DWELL_ACTIVITY_IDLE_MS = 2 * 60 * 1e3;
941
1012
  var DWELL_POLL_MS = 5e3;
@@ -1977,6 +2048,32 @@ Available Console Commands:
1977
2048
  */
1978
2049
  async fetchPageConfig(route, preview = false) {
1979
2050
  const url = this.buildLayoutProviderUrl(route, preview);
2051
+ const pageSearch = typeof window !== "undefined" ? new URLSearchParams(window.location.search) : null;
2052
+ const cacheKey = layoutProviderCacheKey({
2053
+ route,
2054
+ trackingId: this.getTrackingId(),
2055
+ instanceId: getInstanceId(),
2056
+ preview,
2057
+ working: pageSearch ? isWorkingContentRequest(pageSearch) : false,
2058
+ zoneId: pageSearch?.get("zoneId"),
2059
+ compositionId: pageSearch?.get("compositionId")
2060
+ });
2061
+ return dedupeLayoutProviderFetch(cacheKey, async () => {
2062
+ const startedAt = Date.now();
2063
+ sdkDebug("[AmplifyUp SDK] layout/provider request", {
2064
+ route,
2065
+ at: new Date(startedAt).toISOString()
2066
+ });
2067
+ const page = await this.fetchPageConfigUncached(url);
2068
+ sdkDebug("[AmplifyUp SDK] layout/provider response", {
2069
+ route,
2070
+ durationMs: Date.now() - startedAt,
2071
+ hasPage: !!page
2072
+ });
2073
+ return page;
2074
+ });
2075
+ }
2076
+ async fetchPageConfigUncached(url) {
1980
2077
  const response = await fetch(url);
1981
2078
  if (!response.ok) {
1982
2079
  if (response.status === 404) {
@@ -2335,6 +2432,12 @@ Available Console Commands:
2335
2432
  );
2336
2433
  return;
2337
2434
  }
2435
+ if (event.data?.type === "AMPLIFYUP_LAYOUT_PATCH") {
2436
+ window.dispatchEvent(
2437
+ new CustomEvent("amplifyup:layout-patch", { detail: event.data })
2438
+ );
2439
+ return;
2440
+ }
2338
2441
  if (event.data?.type === "COMPONENT_DELETABLE_STATUS") {
2339
2442
  const { componentId, deletable, nodeId } = event.data;
2340
2443
  const element = document.querySelector(`[data-component-id="${componentId}"]`);
@@ -3375,6 +3478,16 @@ function getSDK(adapter) {
3375
3478
  var trackContentView = (contentId, contentType, properties) => getSDK().trackContentView(contentId, contentType, properties);
3376
3479
  var refreshEventTracking = () => getSDK().refreshEventTracking();
3377
3480
  getSDK();
3481
+ function useComposerPreviewFlag(force = false) {
3482
+ const [detected, setDetected] = react.useState(false);
3483
+ react.useEffect(() => {
3484
+ if (!force && isComposerPreview()) setDetected(true);
3485
+ }, [force]);
3486
+ return force || detected;
3487
+ }
3488
+ react.createContext({
3489
+ ready: true
3490
+ });
3378
3491
 
3379
3492
  // src/composer-store.ts
3380
3493
  var ComposerFieldStore = class {
@@ -3591,16 +3704,9 @@ function NodeWithFields({
3591
3704
  renderComponent,
3592
3705
  composerPreview
3593
3706
  }) {
3594
- return /* @__PURE__ */ jsxRuntime.jsx(
3595
- MaybeComposerProvider,
3596
- {
3597
- enabled: !!(composerPreview || isComposerPreview()),
3598
- layoutNodeId: nodeId,
3599
- children: renderComponent(componentId, props, slots, {
3600
- layoutNodeId: nodeId
3601
- })
3602
- }
3603
- );
3707
+ return /* @__PURE__ */ jsxRuntime.jsx(MaybeComposerProvider, { enabled: !!composerPreview, layoutNodeId: nodeId, children: renderComponent(componentId, props, slots, {
3708
+ layoutNodeId: nodeId
3709
+ }) });
3604
3710
  }
3605
3711
  function AmplifyRendererInner({
3606
3712
  renderComponent,
@@ -3611,6 +3717,7 @@ function AmplifyRendererInner({
3611
3717
  composerPreview
3612
3718
  }) {
3613
3719
  const clientHook = useAmplifyUp();
3720
+ const composerPreviewFlag = useComposerPreviewFlag(!!composerPreview);
3614
3721
  const pageConfig = serverPageConfig || clientHook.pageConfig || null;
3615
3722
  const loading = serverPageConfig ? false : clientHook.loading;
3616
3723
  const error = serverPageConfig ? null : clientHook.error;
@@ -3963,7 +4070,7 @@ function AmplifyRendererInner({
3963
4070
  props: nodeRenderProps(node),
3964
4071
  slots: slotsToPass,
3965
4072
  renderComponent,
3966
- composerPreview
4073
+ composerPreview: composerPreviewFlag
3967
4074
  }
3968
4075
  )
3969
4076
  }
@@ -3976,12 +4083,13 @@ function AmplifyRendererInner({
3976
4083
  if (layoutTree.length === 0) {
3977
4084
  return /* @__PURE__ */ jsxRuntime.jsx("main", { children: emptyComponent || /* @__PURE__ */ jsxRuntime.jsx("div", { className: "container mx-auto px-4 py-16", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground", children: "No content configured for this page." }) }) });
3978
4085
  }
3979
- return /* @__PURE__ */ jsxRuntime.jsx(ComposerProvider, { children: /* @__PURE__ */ jsxRuntime.jsx("main", { children: composerPreview || isComposerPreview() ? /* @__PURE__ */ jsxRuntime.jsx(
4086
+ return /* @__PURE__ */ jsxRuntime.jsx(ComposerProvider, { children: /* @__PURE__ */ jsxRuntime.jsx("main", { children: composerPreviewFlag ? /* @__PURE__ */ jsxRuntime.jsx(
3980
4087
  "div",
3981
4088
  {
3982
4089
  "data-slot-id": "main",
3983
4090
  "data-amplifyup-slot": "main",
3984
4091
  "data-slot-source": "page",
4092
+ "data-slot-state": layoutTree.length === 0 ? "empty" : "filled",
3985
4093
  "data-slot-empty": layoutTree.length === 0 ? "true" : void 0,
3986
4094
  children: layoutTree.map((node) => /* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: renderNode(node) }, node.id))
3987
4095
  }