@amplifyup/sdk 0.1.63 → 0.1.64

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
  }
@@ -430,21 +440,76 @@ function isPortableImageShape(value) {
430
440
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
431
441
  return "url" in value;
432
442
  }
433
- function isEntryRefItem(value) {
434
- if (!value || typeof value !== "object" || Array.isArray(value)) return false;
435
- 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;
443
+ function isIdentifierKey(key) {
444
+ return IDENTIFIER_KEYS.has(key);
437
445
  }
438
- function isRepeaterArray(value) {
446
+ function isRecordList(value) {
439
447
  if (!Array.isArray(value) || value.length === 0) return false;
440
448
  const sample = value.find((item) => item != null);
441
449
  if (sample === void 0) return false;
442
450
  if (typeof sample !== "object" || Array.isArray(sample)) return false;
443
451
  if (isPortableImageShape(sample)) return false;
444
- if (isEntryRefItem(sample)) return false;
445
452
  if (sample.$$typeof) return false;
446
453
  return true;
447
454
  }
455
+ function isFieldRef(value) {
456
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
457
+ const rec = value;
458
+ return typeof rec.providerId === "string" && !!rec.providerId && typeof rec.entity === "string" && !!rec.entity && typeof rec.id === "string" && !!rec.id;
459
+ }
460
+ function isListOwner(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;
464
+ }
465
+ function composerStoreKey(name, ref, layoutNodeId) {
466
+ if (isFieldRef(ref)) {
467
+ return `record:${ref.providerId}:${ref.entity}:${ref.id}:${name}`;
468
+ }
469
+ return layoutNodeId ? `page:${layoutNodeId}:${name}` : name;
470
+ }
471
+ function listOwnerFromConnection(conn) {
472
+ if (!conn || typeof conn !== "object") return void 0;
473
+ if (conn.mode === "query") {
474
+ const providerId = String(conn.spec?.providerId || "").trim();
475
+ const entity = String(conn.spec?.entity || "").trim();
476
+ return providerId && entity ? { providerId, entity } : void 0;
477
+ }
478
+ if (conn.mode === "item" || conn.mode === "items") {
479
+ const providerId = String(conn.providerId || "").trim();
480
+ const entity = String(conn.entity || "").trim();
481
+ return providerId && entity ? { providerId, entity } : void 0;
482
+ }
483
+ return void 0;
484
+ }
485
+ function listOwnerFromSpec(spec) {
486
+ const providerId = String(spec?.providerId || "").trim();
487
+ const entity = String(spec?.entity || "").trim();
488
+ return providerId && entity ? { providerId, entity } : void 0;
489
+ }
490
+ function isEnvelopeSources(value) {
491
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
492
+ const rec = value;
493
+ return rec.connections != null || rec.reads != null;
494
+ }
495
+ function normalizeEnvelopeSources(sources) {
496
+ if (!sources) return {};
497
+ if (isEnvelopeSources(sources) && !("mode" in sources)) {
498
+ return sources;
499
+ }
500
+ return { connections: sources };
501
+ }
502
+ function listOwnerForField(fieldName, props, sources) {
503
+ const { connections, reads } = normalizeEnvelopeSources(sources);
504
+ const resourceName = reads?.[fieldName]?.resource || fieldName;
505
+ const fromConn = listOwnerFromConnection(connections?.[resourceName]);
506
+ if (fromConn) return fromConn;
507
+ const paging = props?.[`${fieldName}Pagination`];
508
+ if (paging && typeof paging === "object" && !Array.isArray(paging)) {
509
+ return listOwnerFromSpec(paging.spec);
510
+ }
511
+ return void 0;
512
+ }
448
513
  function joinPath(prefix, key) {
449
514
  return prefix ? `${prefix}.${key}` : key;
450
515
  }
@@ -452,61 +517,101 @@ function emptyValue(raw) {
452
517
  if (raw === void 0) return null;
453
518
  return raw;
454
519
  }
455
- function toFieldEnvelopes(source, prefix = "") {
520
+ function rowId(raw) {
521
+ const candidates = [raw.id, raw._id, raw.docId, raw.key, raw._key];
522
+ for (const c of candidates) {
523
+ if (typeof c === "string" && c.trim()) return c;
524
+ }
525
+ return "";
526
+ }
527
+ function withLeaf(envelope, scope) {
528
+ if (isFieldRef(scope?.ref)) envelope.ref = scope.ref;
529
+ else if (scope?.readOnly) envelope.readOnly = true;
530
+ return envelope;
531
+ }
532
+ function toFieldEnvelopes(source, prefix = "", scope) {
533
+ const ctx = isFieldRef(scope) ? { ref: scope } : scope || {};
456
534
  const input = source && typeof source === "object" && !Array.isArray(source) ? source : {};
457
535
  if (isBrandedFields(input)) {
458
536
  return input;
459
537
  }
460
538
  const out = {};
461
539
  for (const [key, raw] of Object.entries(input)) {
540
+ if (isIdentifierKey(key) && (typeof raw === "string" || raw == null)) {
541
+ out[key] = raw ?? "";
542
+ continue;
543
+ }
462
544
  const path = joinPath(prefix, key);
463
545
  if (isFieldEnvelope(raw)) {
464
546
  const inner = raw.value;
465
- if (isRepeaterArray(inner)) {
547
+ if (isRecordList(inner)) {
548
+ const owner = ctx.owners?.(key);
466
549
  out[key] = {
467
- value: envelopeRepeaterItems(inner, raw.name || path),
550
+ value: envelopeListRows(inner, owner),
468
551
  name: raw.name || path
469
552
  };
470
553
  continue;
471
554
  }
472
- out[key] = { value: raw.value ?? null, name: raw.name || path };
555
+ out[key] = withLeaf(
556
+ { value: raw.value ?? null, name: raw.name || path },
557
+ raw.ref ? { ref: raw.ref } : ctx
558
+ );
473
559
  continue;
474
560
  }
475
- if (isRepeaterArray(raw)) {
476
- out[key] = { value: envelopeRepeaterItems(raw, path), name: path };
561
+ if (isRecordList(raw)) {
562
+ const owner = ctx.owners?.(key);
563
+ out[key] = { value: envelopeListRows(raw, owner), name: path };
477
564
  continue;
478
565
  }
479
566
  if (raw && typeof raw === "object" && !Array.isArray(raw) && !isPortableImageShape(raw) && !raw.$$typeof) {
480
- out[key] = toFieldEnvelopes(raw, path);
567
+ out[key] = toFieldEnvelopes(raw, path, ctx);
481
568
  continue;
482
569
  }
483
- out[key] = { value: emptyValue(raw), name: path };
570
+ out[key] = withLeaf({ value: emptyValue(raw), name: path }, ctx);
484
571
  }
485
572
  return brandFields(out);
486
573
  }
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);
574
+ function envelopeListRows(items, owner) {
575
+ return items.map((item) => envelopeListRow(item, owner));
576
+ }
577
+ function envelopeListRow(item, owner) {
578
+ if (isBrandedFields(item) && typeof item.id === "string") {
579
+ return item;
580
+ }
581
+ const raw = item && typeof item === "object" && !Array.isArray(item) ? item : {};
582
+ const id = rowId(raw);
583
+ const ref = isListOwner(owner) && id ? { providerId: owner.providerId, entity: owner.entity, id } : void 0;
584
+ const fields = toFieldEnvelopes(raw, "", {
585
+ ref,
586
+ readOnly: !ref
495
587
  });
588
+ const row = fields;
589
+ if (typeof row.id !== "string") {
590
+ row.id = id;
591
+ }
592
+ return row;
496
593
  }
497
- function attachFieldEnvelopes(props) {
594
+ function attachFieldEnvelopes(props, sources) {
498
595
  const raw = props && typeof props === "object" ? { ...props } : {};
499
596
  if (isBrandedFields(raw.fields)) return raw;
500
597
  const { fields: existing, ...content } = raw;
501
598
  const source = existing && typeof existing === "object" && !isFieldEnvelope(existing) ? existing : content;
502
- return { ...raw, fields: toFieldEnvelopes(source) };
599
+ return {
600
+ ...raw,
601
+ fields: toFieldEnvelopes(source, "", {
602
+ owners: (fieldName) => listOwnerForField(fieldName, source, sources)
603
+ })
604
+ };
503
605
  }
504
606
  function walkLayoutNodes(nodes) {
505
607
  if (!Array.isArray(nodes)) return;
506
608
  for (const node of nodes) {
507
609
  if (!node || typeof node !== "object") continue;
508
610
  const rec = node;
509
- rec.props = attachFieldEnvelopes(rec.props);
611
+ rec.props = attachFieldEnvelopes(rec.props, {
612
+ connections: rec.resources,
613
+ reads: rec.reads
614
+ });
510
615
  for (const slot of rec.slots || []) {
511
616
  walkLayoutNodes(slot.children);
512
617
  }
@@ -520,31 +625,36 @@ function envelopePageConfig(page) {
520
625
  }
521
626
  function collectFieldPatches(props) {
522
627
  const out = [];
523
- const walkRepeater = (items, prefix) => {
524
- items.forEach((item, i) => {
525
- const itemPath = joinPath(prefix, String(i));
628
+ const walkRows = (items) => {
629
+ for (const item of items) {
526
630
  if (isBrandedFields(item) || item && typeof item === "object" && !Array.isArray(item) && !isFieldEnvelope(item)) {
527
- walk(item, itemPath);
631
+ walk(item, "");
528
632
  }
529
- });
633
+ }
530
634
  };
531
635
  const walk = (obj, prefix) => {
532
636
  for (const [key, raw] of Object.entries(obj)) {
637
+ if (isIdentifierKey(key)) continue;
533
638
  if (key === "fields" && raw && typeof raw === "object" && !Array.isArray(raw) && !isFieldEnvelope(raw)) {
534
639
  walk(raw, prefix);
535
640
  continue;
536
641
  }
537
642
  const path = joinPath(prefix, key);
538
643
  if (isFieldEnvelope(raw)) {
539
- if (isRepeaterArray(raw.value)) {
540
- walkRepeater(raw.value, raw.name || path);
644
+ if (isRecordList(raw.value)) {
645
+ walkRows(raw.value);
541
646
  continue;
542
647
  }
543
- out.push({ name: raw.name || path, value: raw.value });
648
+ const patch = {
649
+ name: raw.name || path,
650
+ value: raw.value
651
+ };
652
+ if (raw.ref) patch.ref = raw.ref;
653
+ out.push(patch);
544
654
  continue;
545
655
  }
546
- if (isRepeaterArray(raw)) {
547
- walkRepeater(raw, path);
656
+ if (isRecordList(raw)) {
657
+ walkRows(raw);
548
658
  continue;
549
659
  }
550
660
  if (raw && typeof raw === "object" && !Array.isArray(raw) && !isPortableImageShape(raw) && !raw.$$typeof) {
@@ -3299,44 +3409,50 @@ var ComposerFieldStore = class {
3299
3409
  }
3300
3410
  };
3301
3411
  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;
3412
+ var ComposerNodeContext = react.createContext(void 0);
3413
+ function applyComposerPatch(store, name, value, ref, layoutNodeId) {
3414
+ store.set(composerStoreKey(name, ref, layoutNodeId), value);
3307
3415
  }
3308
3416
  function ComposerProvider({
3309
- layoutNodeId,
3310
3417
  children
3311
3418
  }) {
3419
+ const existing = react.useContext(ComposerStoreContext);
3312
3420
  const storeRef = react.useRef(null);
3313
3421
  if (!storeRef.current) storeRef.current = new ComposerFieldStore();
3314
- const store = storeRef.current;
3422
+ const store = existing || storeRef.current;
3315
3423
  react.useEffect(() => {
3316
- const applyField = (fieldName, value, nodeId) => {
3424
+ if (existing) return;
3425
+ const applyField = (fieldName, value, nodeId, ref) => {
3317
3426
  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
- }
3427
+ const fieldRef = isFieldRef(ref) ? ref : void 0;
3428
+ const layoutNodeId = typeof nodeId === "string" && nodeId ? nodeId : void 0;
3429
+ applyComposerPatch(store, fieldName, value, fieldRef, layoutNodeId);
3327
3430
  };
3328
3431
  const applyProps = (nextProps, nodeId) => {
3329
3432
  if (!nextProps || typeof nextProps !== "object" || Array.isArray(nextProps)) {
3330
3433
  return;
3331
3434
  }
3332
- if (!matchesNode(nodeId, layoutNodeId)) return;
3333
- for (const patch of collectFieldPatches(nextProps)) {
3334
- store.set(patch.name, patch.value);
3435
+ const layoutNodeId = typeof nodeId === "string" && nodeId ? nodeId : void 0;
3436
+ for (const patch of collectFieldPatches(
3437
+ nextProps
3438
+ )) {
3439
+ applyComposerPatch(
3440
+ store,
3441
+ patch.name,
3442
+ patch.value,
3443
+ patch.ref,
3444
+ patch.ref ? void 0 : layoutNodeId
3445
+ );
3335
3446
  }
3336
3447
  };
3337
3448
  const onPatch = (event) => {
3338
3449
  const detail = event.detail || {};
3339
- applyField(detail.fieldName, detail.value, detail.layoutNodeId);
3450
+ applyField(
3451
+ detail.fieldName,
3452
+ detail.value,
3453
+ detail.layoutNodeId,
3454
+ detail.ref
3455
+ );
3340
3456
  };
3341
3457
  const onPropsPatch = (event) => {
3342
3458
  const detail = event.detail || {};
@@ -3348,7 +3464,12 @@ function ComposerProvider({
3348
3464
  return;
3349
3465
  }
3350
3466
  if (event.data?.type !== "AMPLIFYUP_FIELD_PATCH") return;
3351
- applyField(event.data.fieldName, event.data.value, event.data.layoutNodeId);
3467
+ applyField(
3468
+ event.data.fieldName,
3469
+ event.data.value,
3470
+ event.data.layoutNodeId,
3471
+ event.data.ref
3472
+ );
3352
3473
  };
3353
3474
  window.addEventListener("amplifyup:field-patch", onPatch);
3354
3475
  window.addEventListener("amplifyup:props-patch", onPropsPatch);
@@ -3358,7 +3479,8 @@ function ComposerProvider({
3358
3479
  window.removeEventListener("amplifyup:props-patch", onPropsPatch);
3359
3480
  window.removeEventListener("message", onMessage);
3360
3481
  };
3361
- }, [layoutNodeId, store]);
3482
+ }, [existing, store]);
3483
+ if (existing) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
3362
3484
  return /* @__PURE__ */ jsxRuntime.jsx(ComposerStoreContext.Provider, { value: store, children });
3363
3485
  }
3364
3486
  function MaybeComposerProvider({
@@ -3368,7 +3490,7 @@ function MaybeComposerProvider({
3368
3490
  }) {
3369
3491
  const content = react.useMemo(() => children, [children]);
3370
3492
  if (!enabled) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: content });
3371
- return /* @__PURE__ */ jsxRuntime.jsx(ComposerProvider, { layoutNodeId, children });
3493
+ return /* @__PURE__ */ jsxRuntime.jsx(ComposerProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(ComposerNodeContext.Provider, { value: layoutNodeId, children }) });
3372
3494
  }
3373
3495
  react.createContext(null);
3374
3496
  var usePathname = null;
@@ -3845,7 +3967,7 @@ function AmplifyRendererInner({
3845
3967
  if (layoutTree.length === 0) {
3846
3968
  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
3969
  }
3848
- return /* @__PURE__ */ jsxRuntime.jsx("main", { children: composerPreview || isComposerPreview() ? /* @__PURE__ */ jsxRuntime.jsx(
3970
+ return /* @__PURE__ */ jsxRuntime.jsx(ComposerProvider, { children: /* @__PURE__ */ jsxRuntime.jsx("main", { children: composerPreview || isComposerPreview() ? /* @__PURE__ */ jsxRuntime.jsx(
3849
3971
  "div",
3850
3972
  {
3851
3973
  "data-slot-id": "main",
@@ -3854,7 +3976,7 @@ function AmplifyRendererInner({
3854
3976
  "data-slot-empty": layoutTree.length === 0 ? "true" : void 0,
3855
3977
  children: layoutTree.map((node) => /* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: renderNode(node) }, node.id))
3856
3978
  }
3857
- ) : layoutTree.map((node) => /* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: renderNode(node) }, node.id)) });
3979
+ ) : layoutTree.map((node) => /* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: renderNode(node) }, node.id)) }) });
3858
3980
  }
3859
3981
  var AmplifyRenderer = react.memo(AmplifyRendererInner);
3860
3982