@amplifyup/sdk 0.1.63 → 0.1.65

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.
@@ -409,6 +409,16 @@ function isComposerPreview() {
409
409
 
410
410
  // src/field-envelope.ts
411
411
  var FIELDS_BRAND = Symbol("amplifyup.fields");
412
+ var IDENTIFIER_KEYS = /* @__PURE__ */ new Set([
413
+ "id",
414
+ "_id",
415
+ "slug",
416
+ "key",
417
+ "_key",
418
+ "docId",
419
+ "_type",
420
+ "type"
421
+ ]);
412
422
  function isBrandedFields(value) {
413
423
  return !!value && typeof value === "object" && FIELDS_BRAND in value;
414
424
  }
@@ -426,25 +436,85 @@ function isFieldEnvelope(value) {
426
436
  const rec = value;
427
437
  return typeof rec.name === "string" && "value" in rec && !("url" in rec);
428
438
  }
429
- function isPortableImageShape(value) {
430
- if (!value || typeof value !== "object" || Array.isArray(value)) return false;
431
- return "url" in value;
439
+ function isPageResourceSentinel(value) {
440
+ return !!value && typeof value === "object" && !Array.isArray(value) && typeof value.__amplifyupPageResource === "string";
432
441
  }
433
- function isEntryRefItem(value) {
442
+ function isPortableImageShape(value) {
434
443
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
444
+ if ("url" in value) return true;
435
445
  const rec = value;
436
- return typeof rec.id === "string" && rec.id.trim().length > 0 || typeof rec._id === "string" && rec._id.trim().length > 0 || typeof rec.docId === "string" && rec.docId.trim().length > 0;
446
+ return rec._type === "image" || rec.asset != null;
437
447
  }
438
- function isRepeaterArray(value) {
448
+ function isIdentifierKey(key) {
449
+ return IDENTIFIER_KEYS.has(key);
450
+ }
451
+ function isRecordList(value) {
439
452
  if (!Array.isArray(value) || value.length === 0) return false;
440
453
  const sample = value.find((item) => item != null);
441
454
  if (sample === void 0) return false;
442
455
  if (typeof sample !== "object" || Array.isArray(sample)) return false;
443
456
  if (isPortableImageShape(sample)) return false;
444
- if (isEntryRefItem(sample)) return false;
445
457
  if (sample.$$typeof) return false;
446
458
  return true;
447
459
  }
460
+ function isFieldRef(value) {
461
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
462
+ const rec = value;
463
+ return typeof rec.providerId === "string" && !!rec.providerId && typeof rec.entity === "string" && !!rec.entity && typeof rec.id === "string" && !!rec.id;
464
+ }
465
+ function isListOwner(value) {
466
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
467
+ const rec = value;
468
+ return typeof rec.providerId === "string" && !!rec.providerId && typeof rec.entity === "string" && !!rec.entity;
469
+ }
470
+ function composerStoreKey(name, ref, layoutNodeId) {
471
+ if (isFieldRef(ref)) {
472
+ return `record:${ref.providerId}:${ref.entity}:${ref.id}:${name}`;
473
+ }
474
+ return layoutNodeId ? `page:${layoutNodeId}:${name}` : name;
475
+ }
476
+ function listOwnerFromConnection(conn) {
477
+ if (!conn || typeof conn !== "object") return void 0;
478
+ if (conn.mode === "query") {
479
+ const providerId = String(conn.spec?.providerId || "").trim();
480
+ const entity = String(conn.spec?.entity || "").trim();
481
+ return providerId && entity ? { providerId, entity } : void 0;
482
+ }
483
+ if (conn.mode === "item" || conn.mode === "items") {
484
+ const providerId = String(conn.providerId || "").trim();
485
+ const entity = String(conn.entity || "").trim();
486
+ return providerId && entity ? { providerId, entity } : void 0;
487
+ }
488
+ return void 0;
489
+ }
490
+ function listOwnerFromSpec(spec) {
491
+ const providerId = String(spec?.providerId || "").trim();
492
+ const entity = String(spec?.entity || "").trim();
493
+ return providerId && entity ? { providerId, entity } : void 0;
494
+ }
495
+ function isEnvelopeSources(value) {
496
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
497
+ const rec = value;
498
+ return rec.connections != null || rec.reads != null;
499
+ }
500
+ function normalizeEnvelopeSources(sources) {
501
+ if (!sources) return {};
502
+ if (isEnvelopeSources(sources) && !("mode" in sources)) {
503
+ return sources;
504
+ }
505
+ return { connections: sources };
506
+ }
507
+ function listOwnerForField(fieldName, props, sources) {
508
+ const { connections, reads } = normalizeEnvelopeSources(sources);
509
+ const resourceName = reads?.[fieldName]?.resource || fieldName;
510
+ const fromConn = listOwnerFromConnection(connections?.[resourceName]);
511
+ if (fromConn) return fromConn;
512
+ const paging = props?.[`${fieldName}Pagination`];
513
+ if (paging && typeof paging === "object" && !Array.isArray(paging)) {
514
+ return listOwnerFromSpec(paging.spec);
515
+ }
516
+ return void 0;
517
+ }
448
518
  function joinPath(prefix, key) {
449
519
  return prefix ? `${prefix}.${key}` : key;
450
520
  }
@@ -452,61 +522,105 @@ function emptyValue(raw) {
452
522
  if (raw === void 0) return null;
453
523
  return raw;
454
524
  }
455
- function toFieldEnvelopes(source, prefix = "") {
525
+ function rowId(raw) {
526
+ const candidates = [raw.id, raw._id, raw.docId, raw.key, raw._key];
527
+ for (const c of candidates) {
528
+ if (typeof c === "string" && c.trim()) return c;
529
+ }
530
+ return "";
531
+ }
532
+ function withLeaf(envelope, scope) {
533
+ if (isFieldRef(scope?.ref)) envelope.ref = scope.ref;
534
+ else if (scope?.readOnly) envelope.readOnly = true;
535
+ return envelope;
536
+ }
537
+ function toFieldEnvelopes(source, prefix = "", scope) {
538
+ const ctx = isFieldRef(scope) ? { ref: scope } : scope || {};
456
539
  const input = source && typeof source === "object" && !Array.isArray(source) ? source : {};
457
540
  if (isBrandedFields(input)) {
458
541
  return input;
459
542
  }
460
543
  const out = {};
461
544
  for (const [key, raw] of Object.entries(input)) {
545
+ if (isIdentifierKey(key) && (typeof raw === "string" || raw == null)) {
546
+ out[key] = raw ?? "";
547
+ continue;
548
+ }
462
549
  const path = joinPath(prefix, key);
550
+ if (isPageResourceSentinel(raw)) {
551
+ out[key] = withLeaf({ value: raw, name: path }, ctx);
552
+ continue;
553
+ }
463
554
  if (isFieldEnvelope(raw)) {
464
555
  const inner = raw.value;
465
- if (isRepeaterArray(inner)) {
556
+ if (isRecordList(inner)) {
557
+ const owner = ctx.owners?.(key);
466
558
  out[key] = {
467
- value: envelopeRepeaterItems(inner, raw.name || path),
559
+ value: envelopeListRows(inner, owner),
468
560
  name: raw.name || path
469
561
  };
470
562
  continue;
471
563
  }
472
- out[key] = { value: raw.value ?? null, name: raw.name || path };
564
+ out[key] = withLeaf(
565
+ { value: raw.value ?? null, name: raw.name || path },
566
+ raw.ref ? { ref: raw.ref } : ctx
567
+ );
473
568
  continue;
474
569
  }
475
- if (isRepeaterArray(raw)) {
476
- out[key] = { value: envelopeRepeaterItems(raw, path), name: path };
570
+ if (isRecordList(raw)) {
571
+ const owner = ctx.owners?.(key);
572
+ out[key] = { value: envelopeListRows(raw, owner), name: path };
477
573
  continue;
478
574
  }
479
575
  if (raw && typeof raw === "object" && !Array.isArray(raw) && !isPortableImageShape(raw) && !raw.$$typeof) {
480
- out[key] = toFieldEnvelopes(raw, path);
576
+ out[key] = toFieldEnvelopes(raw, path, ctx);
481
577
  continue;
482
578
  }
483
- out[key] = { value: emptyValue(raw), name: path };
579
+ out[key] = withLeaf({ value: emptyValue(raw), name: path }, ctx);
484
580
  }
485
581
  return brandFields(out);
486
582
  }
487
- function envelopeRepeaterItems(items, prefix) {
488
- return items.map((item, i) => {
489
- const path = joinPath(prefix, String(i));
490
- if (isBrandedFields(item)) return item;
491
- if (item && typeof item === "object" && !Array.isArray(item)) {
492
- return toFieldEnvelopes(item, path);
493
- }
494
- return toFieldEnvelopes({}, path);
583
+ function envelopeListRows(items, owner) {
584
+ return items.map((item) => envelopeListRow(item, owner));
585
+ }
586
+ function envelopeListRow(item, owner) {
587
+ if (isBrandedFields(item) && typeof item.id === "string") {
588
+ return item;
589
+ }
590
+ const raw = item && typeof item === "object" && !Array.isArray(item) ? item : {};
591
+ const id = rowId(raw);
592
+ const ref = isListOwner(owner) && id ? { providerId: owner.providerId, entity: owner.entity, id } : void 0;
593
+ const fields = toFieldEnvelopes(raw, "", {
594
+ ref,
595
+ readOnly: !ref
495
596
  });
597
+ const row = fields;
598
+ if (typeof row.id !== "string") {
599
+ row.id = id;
600
+ }
601
+ return row;
496
602
  }
497
- function attachFieldEnvelopes(props) {
603
+ function attachFieldEnvelopes(props, sources) {
498
604
  const raw = props && typeof props === "object" ? { ...props } : {};
499
605
  if (isBrandedFields(raw.fields)) return raw;
500
606
  const { fields: existing, ...content } = raw;
501
607
  const source = existing && typeof existing === "object" && !isFieldEnvelope(existing) ? existing : content;
502
- return { ...raw, fields: toFieldEnvelopes(source) };
608
+ return {
609
+ ...raw,
610
+ fields: toFieldEnvelopes(source, "", {
611
+ owners: (fieldName) => listOwnerForField(fieldName, source, sources)
612
+ })
613
+ };
503
614
  }
504
615
  function walkLayoutNodes(nodes) {
505
616
  if (!Array.isArray(nodes)) return;
506
617
  for (const node of nodes) {
507
618
  if (!node || typeof node !== "object") continue;
508
619
  const rec = node;
509
- rec.props = attachFieldEnvelopes(rec.props);
620
+ rec.props = attachFieldEnvelopes(rec.props, {
621
+ connections: rec.resources,
622
+ reads: rec.reads
623
+ });
510
624
  for (const slot of rec.slots || []) {
511
625
  walkLayoutNodes(slot.children);
512
626
  }
@@ -520,31 +634,36 @@ function envelopePageConfig(page) {
520
634
  }
521
635
  function collectFieldPatches(props) {
522
636
  const out = [];
523
- const walkRepeater = (items, prefix) => {
524
- items.forEach((item, i) => {
525
- const itemPath = joinPath(prefix, String(i));
637
+ const walkRows = (items) => {
638
+ for (const item of items) {
526
639
  if (isBrandedFields(item) || item && typeof item === "object" && !Array.isArray(item) && !isFieldEnvelope(item)) {
527
- walk(item, itemPath);
640
+ walk(item, "");
528
641
  }
529
- });
642
+ }
530
643
  };
531
644
  const walk = (obj, prefix) => {
532
645
  for (const [key, raw] of Object.entries(obj)) {
646
+ if (isIdentifierKey(key)) continue;
533
647
  if (key === "fields" && raw && typeof raw === "object" && !Array.isArray(raw) && !isFieldEnvelope(raw)) {
534
648
  walk(raw, prefix);
535
649
  continue;
536
650
  }
537
651
  const path = joinPath(prefix, key);
538
652
  if (isFieldEnvelope(raw)) {
539
- if (isRepeaterArray(raw.value)) {
540
- walkRepeater(raw.value, raw.name || path);
653
+ if (isRecordList(raw.value)) {
654
+ walkRows(raw.value);
541
655
  continue;
542
656
  }
543
- out.push({ name: raw.name || path, value: raw.value });
657
+ const patch = {
658
+ name: raw.name || path,
659
+ value: raw.value
660
+ };
661
+ if (raw.ref) patch.ref = raw.ref;
662
+ out.push(patch);
544
663
  continue;
545
664
  }
546
- if (isRepeaterArray(raw)) {
547
- walkRepeater(raw, path);
665
+ if (isRecordList(raw)) {
666
+ walkRows(raw);
548
667
  continue;
549
668
  }
550
669
  if (raw && typeof raw === "object" && !Array.isArray(raw) && !isPortableImageShape(raw) && !raw.$$typeof) {
@@ -709,7 +828,7 @@ function mergeEventContext(properties, attached) {
709
828
  };
710
829
  }
711
830
  var PAGE_RESOURCE_MARKER = "__amplifyupPageResource";
712
- function isPageResourceSentinel(value) {
831
+ function isPageResourceSentinel2(value) {
713
832
  return !!value && typeof value === "object" && !Array.isArray(value) && typeof value[PAGE_RESOURCE_MARKER] === "string";
714
833
  }
715
834
  function getByDotPath(source, path) {
@@ -725,7 +844,7 @@ function getByDotPath(source, path) {
725
844
  return cur;
726
845
  }
727
846
  function hydratePageResourceValue(value, fields) {
728
- if (!isPageResourceSentinel(value)) return value;
847
+ if (!isPageResourceSentinel2(value)) return value;
729
848
  if (!fields) return null;
730
849
  if (value.path) return getByDotPath(fields, value.path) ?? null;
731
850
  return fields;
@@ -737,7 +856,7 @@ function hydrateFieldsBag(bag, fields) {
737
856
  const env = val;
738
857
  out[key] = {
739
858
  name: env.name,
740
- value: isPageResourceSentinel(env.value) ? hydratePageResourceValue(env.value, fields) : env.value
859
+ value: isPageResourceSentinel2(env.value) ? hydratePageResourceValue(env.value, fields) : env.value
741
860
  };
742
861
  continue;
743
862
  }
@@ -745,7 +864,7 @@ function hydrateFieldsBag(bag, fields) {
745
864
  out[key] = hydrateFieldsBag(val, fields);
746
865
  continue;
747
866
  }
748
- out[key] = isPageResourceSentinel(val) ? hydratePageResourceValue(val, fields) : val;
867
+ out[key] = isPageResourceSentinel2(val) ? hydratePageResourceValue(val, fields) : val;
749
868
  }
750
869
  return out;
751
870
  }
@@ -758,7 +877,7 @@ function hydratePageResourceProps(props, fields) {
758
877
  }
759
878
  for (const [key, val] of Object.entries(out)) {
760
879
  if (key === "fields") continue;
761
- if (isPageResourceSentinel(val)) {
880
+ if (isPageResourceSentinel2(val)) {
762
881
  out[key] = hydratePageResourceValue(val, fields);
763
882
  }
764
883
  }
@@ -3299,44 +3418,50 @@ var ComposerFieldStore = class {
3299
3418
  }
3300
3419
  };
3301
3420
  var ComposerStoreContext = react.createContext(null);
3302
- function matchesNode(eventNodeId, layoutNodeId) {
3303
- if (eventNodeId && layoutNodeId && String(eventNodeId) !== String(layoutNodeId)) {
3304
- return false;
3305
- }
3306
- return true;
3421
+ var ComposerNodeContext = react.createContext(void 0);
3422
+ function applyComposerPatch(store, name, value, ref, layoutNodeId) {
3423
+ store.set(composerStoreKey(name, ref, layoutNodeId), value);
3307
3424
  }
3308
3425
  function ComposerProvider({
3309
- layoutNodeId,
3310
3426
  children
3311
3427
  }) {
3428
+ const existing = react.useContext(ComposerStoreContext);
3312
3429
  const storeRef = react.useRef(null);
3313
3430
  if (!storeRef.current) storeRef.current = new ComposerFieldStore();
3314
- const store = storeRef.current;
3431
+ const store = existing || storeRef.current;
3315
3432
  react.useEffect(() => {
3316
- const applyField = (fieldName, value, nodeId) => {
3433
+ if (existing) return;
3434
+ const applyField = (fieldName, value, nodeId, ref) => {
3317
3435
  if (!fieldName || typeof fieldName !== "string") return;
3318
- if (!matchesNode(nodeId, layoutNodeId)) return;
3319
- store.set(fieldName, value);
3320
- if (value && typeof value === "object") {
3321
- for (const patch of collectFieldPatches(
3322
- toFieldEnvelopes({ [fieldName]: value })
3323
- )) {
3324
- store.set(patch.name, patch.value);
3325
- }
3326
- }
3436
+ const fieldRef = isFieldRef(ref) ? ref : void 0;
3437
+ const layoutNodeId = typeof nodeId === "string" && nodeId ? nodeId : void 0;
3438
+ applyComposerPatch(store, fieldName, value, fieldRef, layoutNodeId);
3327
3439
  };
3328
3440
  const applyProps = (nextProps, nodeId) => {
3329
3441
  if (!nextProps || typeof nextProps !== "object" || Array.isArray(nextProps)) {
3330
3442
  return;
3331
3443
  }
3332
- if (!matchesNode(nodeId, layoutNodeId)) return;
3333
- for (const patch of collectFieldPatches(nextProps)) {
3334
- store.set(patch.name, patch.value);
3444
+ const layoutNodeId = typeof nodeId === "string" && nodeId ? nodeId : void 0;
3445
+ for (const patch of collectFieldPatches(
3446
+ nextProps
3447
+ )) {
3448
+ applyComposerPatch(
3449
+ store,
3450
+ patch.name,
3451
+ patch.value,
3452
+ patch.ref,
3453
+ patch.ref ? void 0 : layoutNodeId
3454
+ );
3335
3455
  }
3336
3456
  };
3337
3457
  const onPatch = (event) => {
3338
3458
  const detail = event.detail || {};
3339
- applyField(detail.fieldName, detail.value, detail.layoutNodeId);
3459
+ applyField(
3460
+ detail.fieldName,
3461
+ detail.value,
3462
+ detail.layoutNodeId,
3463
+ detail.ref
3464
+ );
3340
3465
  };
3341
3466
  const onPropsPatch = (event) => {
3342
3467
  const detail = event.detail || {};
@@ -3348,7 +3473,12 @@ function ComposerProvider({
3348
3473
  return;
3349
3474
  }
3350
3475
  if (event.data?.type !== "AMPLIFYUP_FIELD_PATCH") return;
3351
- applyField(event.data.fieldName, event.data.value, event.data.layoutNodeId);
3476
+ applyField(
3477
+ event.data.fieldName,
3478
+ event.data.value,
3479
+ event.data.layoutNodeId,
3480
+ event.data.ref
3481
+ );
3352
3482
  };
3353
3483
  window.addEventListener("amplifyup:field-patch", onPatch);
3354
3484
  window.addEventListener("amplifyup:props-patch", onPropsPatch);
@@ -3358,7 +3488,8 @@ function ComposerProvider({
3358
3488
  window.removeEventListener("amplifyup:props-patch", onPropsPatch);
3359
3489
  window.removeEventListener("message", onMessage);
3360
3490
  };
3361
- }, [layoutNodeId, store]);
3491
+ }, [existing, store]);
3492
+ if (existing) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
3362
3493
  return /* @__PURE__ */ jsxRuntime.jsx(ComposerStoreContext.Provider, { value: store, children });
3363
3494
  }
3364
3495
  function MaybeComposerProvider({
@@ -3368,7 +3499,7 @@ function MaybeComposerProvider({
3368
3499
  }) {
3369
3500
  const content = react.useMemo(() => children, [children]);
3370
3501
  if (!enabled) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: content });
3371
- return /* @__PURE__ */ jsxRuntime.jsx(ComposerProvider, { layoutNodeId, children });
3502
+ return /* @__PURE__ */ jsxRuntime.jsx(ComposerProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(ComposerNodeContext.Provider, { value: layoutNodeId, children }) });
3372
3503
  }
3373
3504
  react.createContext(null);
3374
3505
  var usePathname = null;
@@ -3845,7 +3976,7 @@ function AmplifyRendererInner({
3845
3976
  if (layoutTree.length === 0) {
3846
3977
  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." }) }) });
3847
3978
  }
3848
- return /* @__PURE__ */ jsxRuntime.jsx("main", { children: composerPreview || isComposerPreview() ? /* @__PURE__ */ jsxRuntime.jsx(
3979
+ return /* @__PURE__ */ jsxRuntime.jsx(ComposerProvider, { children: /* @__PURE__ */ jsxRuntime.jsx("main", { children: composerPreview || isComposerPreview() ? /* @__PURE__ */ jsxRuntime.jsx(
3849
3980
  "div",
3850
3981
  {
3851
3982
  "data-slot-id": "main",
@@ -3854,7 +3985,7 @@ function AmplifyRendererInner({
3854
3985
  "data-slot-empty": layoutTree.length === 0 ? "true" : void 0,
3855
3986
  children: layoutTree.map((node) => /* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: renderNode(node) }, node.id))
3856
3987
  }
3857
- ) : layoutTree.map((node) => /* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: renderNode(node) }, node.id)) });
3988
+ ) : layoutTree.map((node) => /* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: renderNode(node) }, node.id)) }) });
3858
3989
  }
3859
3990
  var AmplifyRenderer = react.memo(AmplifyRendererInner);
3860
3991