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