@amplifyup/sdk 0.1.62 → 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,6 +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
  }
441
+ function isIdentifierKey(key) {
442
+ return IDENTIFIER_KEYS.has(key);
443
+ }
444
+ function isRecordList(value) {
445
+ if (!Array.isArray(value) || value.length === 0) return false;
446
+ const sample = value.find((item) => item != null);
447
+ if (sample === void 0) return false;
448
+ if (typeof sample !== "object" || Array.isArray(sample)) return false;
449
+ if (isPortableImageShape(sample)) return false;
450
+ if (sample.$$typeof) return false;
451
+ return true;
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
+ }
431
511
  function joinPath(prefix, key) {
432
512
  return prefix ? `${prefix}.${key}` : key;
433
513
  }
@@ -435,39 +515,101 @@ function emptyValue(raw) {
435
515
  if (raw === void 0) return null;
436
516
  return raw;
437
517
  }
438
- 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 || {};
439
532
  const input = source && typeof source === "object" && !Array.isArray(source) ? source : {};
440
533
  if (isBrandedFields(input)) {
441
534
  return input;
442
535
  }
443
536
  const out = {};
444
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
+ }
445
542
  const path = joinPath(prefix, key);
446
543
  if (isFieldEnvelope(raw)) {
447
- out[key] = { value: raw.value ?? null, name: raw.name || path };
544
+ const inner = raw.value;
545
+ if (isRecordList(inner)) {
546
+ const owner = ctx.owners?.(key);
547
+ out[key] = {
548
+ value: envelopeListRows(inner, owner),
549
+ name: raw.name || path
550
+ };
551
+ continue;
552
+ }
553
+ out[key] = withLeaf(
554
+ { value: raw.value ?? null, name: raw.name || path },
555
+ raw.ref ? { ref: raw.ref } : ctx
556
+ );
557
+ continue;
558
+ }
559
+ if (isRecordList(raw)) {
560
+ const owner = ctx.owners?.(key);
561
+ out[key] = { value: envelopeListRows(raw, owner), name: path };
448
562
  continue;
449
563
  }
450
564
  if (raw && typeof raw === "object" && !Array.isArray(raw) && !isPortableImageShape(raw) && !raw.$$typeof) {
451
- out[key] = toFieldEnvelopes(raw, path);
565
+ out[key] = toFieldEnvelopes(raw, path, ctx);
452
566
  continue;
453
567
  }
454
- out[key] = { value: emptyValue(raw), name: path };
568
+ out[key] = withLeaf({ value: emptyValue(raw), name: path }, ctx);
455
569
  }
456
570
  return brandFields(out);
457
571
  }
458
- function attachFieldEnvelopes(props) {
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
585
+ });
586
+ const row = fields;
587
+ if (typeof row.id !== "string") {
588
+ row.id = id;
589
+ }
590
+ return row;
591
+ }
592
+ function attachFieldEnvelopes(props, sources) {
459
593
  const raw = props && typeof props === "object" ? { ...props } : {};
460
594
  if (isBrandedFields(raw.fields)) return raw;
461
595
  const { fields: existing, ...content } = raw;
462
596
  const source = existing && typeof existing === "object" && !isFieldEnvelope(existing) ? existing : content;
463
- return { ...raw, fields: toFieldEnvelopes(source) };
597
+ return {
598
+ ...raw,
599
+ fields: toFieldEnvelopes(source, "", {
600
+ owners: (fieldName) => listOwnerForField(fieldName, source, sources)
601
+ })
602
+ };
464
603
  }
465
604
  function walkLayoutNodes(nodes) {
466
605
  if (!Array.isArray(nodes)) return;
467
606
  for (const node of nodes) {
468
607
  if (!node || typeof node !== "object") continue;
469
608
  const rec = node;
470
- rec.props = attachFieldEnvelopes(rec.props);
609
+ rec.props = attachFieldEnvelopes(rec.props, {
610
+ connections: rec.resources,
611
+ reads: rec.reads
612
+ });
471
613
  for (const slot of rec.slots || []) {
472
614
  walkLayoutNodes(slot.children);
473
615
  }
@@ -481,15 +623,36 @@ function envelopePageConfig(page) {
481
623
  }
482
624
  function collectFieldPatches(props) {
483
625
  const out = [];
626
+ const walkRows = (items) => {
627
+ for (const item of items) {
628
+ if (isBrandedFields(item) || item && typeof item === "object" && !Array.isArray(item) && !isFieldEnvelope(item)) {
629
+ walk(item, "");
630
+ }
631
+ }
632
+ };
484
633
  const walk = (obj, prefix) => {
485
634
  for (const [key, raw] of Object.entries(obj)) {
635
+ if (isIdentifierKey(key)) continue;
486
636
  if (key === "fields" && raw && typeof raw === "object" && !Array.isArray(raw) && !isFieldEnvelope(raw)) {
487
637
  walk(raw, prefix);
488
638
  continue;
489
639
  }
490
640
  const path = joinPath(prefix, key);
491
641
  if (isFieldEnvelope(raw)) {
492
- out.push({ name: raw.name || path, value: raw.value });
642
+ if (isRecordList(raw.value)) {
643
+ walkRows(raw.value);
644
+ continue;
645
+ }
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);
652
+ continue;
653
+ }
654
+ if (isRecordList(raw)) {
655
+ walkRows(raw);
493
656
  continue;
494
657
  }
495
658
  if (raw && typeof raw === "object" && !Array.isArray(raw) && !isPortableImageShape(raw) && !raw.$$typeof) {
@@ -3232,39 +3395,62 @@ var ComposerFieldStore = class {
3232
3395
  if (set.size === 0) this.listeners.delete(name);
3233
3396
  };
3234
3397
  }
3398
+ keys() {
3399
+ return [...this.values.keys()];
3400
+ }
3401
+ delete(name) {
3402
+ if (!name || !this.values.has(name)) return;
3403
+ this.values.delete(name);
3404
+ const set = this.listeners.get(name);
3405
+ if (!set) return;
3406
+ for (const fn of set) fn();
3407
+ }
3235
3408
  };
3236
3409
  var ComposerStoreContext = createContext(null);
3237
- function matchesNode(eventNodeId, layoutNodeId) {
3238
- if (eventNodeId && layoutNodeId && String(eventNodeId) !== String(layoutNodeId)) {
3239
- return false;
3240
- }
3241
- return true;
3410
+ var ComposerNodeContext = createContext(void 0);
3411
+ function applyComposerPatch(store, name, value, ref, layoutNodeId) {
3412
+ store.set(composerStoreKey(name, ref, layoutNodeId), value);
3242
3413
  }
3243
3414
  function ComposerProvider({
3244
- layoutNodeId,
3245
3415
  children
3246
3416
  }) {
3417
+ const existing = useContext(ComposerStoreContext);
3247
3418
  const storeRef = useRef(null);
3248
3419
  if (!storeRef.current) storeRef.current = new ComposerFieldStore();
3249
- const store = storeRef.current;
3420
+ const store = existing || storeRef.current;
3250
3421
  useEffect(() => {
3251
- const applyField = (fieldName, value, nodeId) => {
3422
+ if (existing) return;
3423
+ const applyField = (fieldName, value, nodeId, ref) => {
3252
3424
  if (!fieldName || typeof fieldName !== "string") return;
3253
- if (!matchesNode(nodeId, layoutNodeId)) return;
3254
- store.set(fieldName, value);
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);
3255
3428
  };
3256
3429
  const applyProps = (nextProps, nodeId) => {
3257
3430
  if (!nextProps || typeof nextProps !== "object" || Array.isArray(nextProps)) {
3258
3431
  return;
3259
3432
  }
3260
- if (!matchesNode(nodeId, layoutNodeId)) return;
3261
- for (const patch of collectFieldPatches(nextProps)) {
3262
- 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
+ );
3263
3444
  }
3264
3445
  };
3265
3446
  const onPatch = (event) => {
3266
3447
  const detail = event.detail || {};
3267
- applyField(detail.fieldName, detail.value, detail.layoutNodeId);
3448
+ applyField(
3449
+ detail.fieldName,
3450
+ detail.value,
3451
+ detail.layoutNodeId,
3452
+ detail.ref
3453
+ );
3268
3454
  };
3269
3455
  const onPropsPatch = (event) => {
3270
3456
  const detail = event.detail || {};
@@ -3276,7 +3462,12 @@ function ComposerProvider({
3276
3462
  return;
3277
3463
  }
3278
3464
  if (event.data?.type !== "AMPLIFYUP_FIELD_PATCH") return;
3279
- 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
+ );
3280
3471
  };
3281
3472
  window.addEventListener("amplifyup:field-patch", onPatch);
3282
3473
  window.addEventListener("amplifyup:props-patch", onPropsPatch);
@@ -3286,7 +3477,8 @@ function ComposerProvider({
3286
3477
  window.removeEventListener("amplifyup:props-patch", onPropsPatch);
3287
3478
  window.removeEventListener("message", onMessage);
3288
3479
  };
3289
- }, [layoutNodeId, store]);
3480
+ }, [existing, store]);
3481
+ if (existing) return /* @__PURE__ */ jsx(Fragment, { children });
3290
3482
  return /* @__PURE__ */ jsx(ComposerStoreContext.Provider, { value: store, children });
3291
3483
  }
3292
3484
  function MaybeComposerProvider({
@@ -3296,7 +3488,7 @@ function MaybeComposerProvider({
3296
3488
  }) {
3297
3489
  const content = useMemo(() => children, [children]);
3298
3490
  if (!enabled) return /* @__PURE__ */ jsx(Fragment, { children: content });
3299
- return /* @__PURE__ */ jsx(ComposerProvider, { layoutNodeId, children });
3491
+ return /* @__PURE__ */ jsx(ComposerProvider, { children: /* @__PURE__ */ jsx(ComposerNodeContext.Provider, { value: layoutNodeId, children }) });
3300
3492
  }
3301
3493
  createContext(null);
3302
3494
  var usePathname = null;
@@ -3773,7 +3965,7 @@ function AmplifyRendererInner({
3773
3965
  if (layoutTree.length === 0) {
3774
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." }) }) });
3775
3967
  }
3776
- return /* @__PURE__ */ jsx("main", { children: composerPreview || isComposerPreview() ? /* @__PURE__ */ jsx(
3968
+ return /* @__PURE__ */ jsx(ComposerProvider, { children: /* @__PURE__ */ jsx("main", { children: composerPreview || isComposerPreview() ? /* @__PURE__ */ jsx(
3777
3969
  "div",
3778
3970
  {
3779
3971
  "data-slot-id": "main",
@@ -3782,7 +3974,7 @@ function AmplifyRendererInner({
3782
3974
  "data-slot-empty": layoutTree.length === 0 ? "true" : void 0,
3783
3975
  children: layoutTree.map((node) => /* @__PURE__ */ jsx(Fragment$1, { children: renderNode(node) }, node.id))
3784
3976
  }
3785
- ) : 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)) }) });
3786
3978
  }
3787
3979
  var AmplifyRenderer = memo(AmplifyRendererInner);
3788
3980