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