@amplifyup/sdk 0.1.22 → 0.1.24

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.
package/dist/react.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  'use client';
2
- import { createContext, useState, useEffect, useContext, Fragment as Fragment$1 } from 'react';
2
+ import { createContext, useState, useEffect, useContext, Fragment as Fragment$1, Component } from 'react';
3
3
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
4
+ import { marked } from 'marked';
4
5
 
5
6
  /* @amplifyup/sdk - https://amplifyup.ai */
6
7
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
@@ -151,17 +152,42 @@ var AWSAdapter = class {
151
152
  };
152
153
  this.sendEvent("/v1/track", eventData);
153
154
  }
154
- identify(userId, traits) {
155
+ identify(userIdOrIdentifiers, traits = {}) {
155
156
  if (!this.initialized) {
156
157
  console.warn("AmplifyUp SDK: Not initialized. Call init() first.");
157
158
  return;
158
159
  }
160
+ const isMap = userIdOrIdentifiers !== null && typeof userIdOrIdentifiers === "object" && !Array.isArray(userIdOrIdentifiers);
161
+ const identifiers = isMap ? userIdOrIdentifiers : traits.identifiers;
162
+ const userId = isMap ? void 0 : String(userIdOrIdentifiers);
159
163
  const eventData = {
160
164
  type: "identify",
161
- userId,
162
165
  anonymousId: traits.instanceId,
163
166
  traits: {
164
- ...traits
167
+ ...traits,
168
+ ...identifiers ? { identifiers } : {}
169
+ },
170
+ ...identifiers ? { identifiers } : {},
171
+ ...userId ? { userId } : {},
172
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
173
+ };
174
+ this.sendEvent("/v1/track", eventData);
175
+ }
176
+ setProfileFields(fields, context = {}) {
177
+ if (!this.initialized) {
178
+ console.warn("AmplifyUp SDK: Not initialized. Call init() first.");
179
+ return;
180
+ }
181
+ const eventData = {
182
+ type: "set_fields",
183
+ anonymousId: context.instanceId,
184
+ fields,
185
+ traits: {
186
+ instanceId: context.instanceId,
187
+ trackingId: context.trackingId
188
+ },
189
+ properties: {
190
+ trackingId: context.trackingId
165
191
  },
166
192
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
167
193
  };
@@ -223,6 +249,7 @@ function clearIds() {
223
249
  var AWS_DEV_API = "https://api-dev.amplifyup.ai";
224
250
  var AWS_PROD_API = "https://api.amplifyup.ai";
225
251
  var PROD_ORCHESTRATOR = "https://amplifyup.ai";
252
+ var PROD_EDGE = "https://edge.amplifyup.ai";
226
253
  function isAmplifyUpTarget(value) {
227
254
  return value === "local" || value === "dev" || value === "production";
228
255
  }
@@ -258,6 +285,10 @@ function localAwsApiUrl() {
258
285
  const fromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_AMPLIFYUP_API_URL : void 0;
259
286
  return (fromEnv || AWS_DEV_API).replace(/\/$/, "");
260
287
  }
288
+ function localEdgeUrl() {
289
+ const fromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_EDGE_URL : void 0;
290
+ return (fromEnv || "http://localhost:8787").replace(/\/$/, "");
291
+ }
261
292
  function resolveAmplifyUpUrls(target) {
262
293
  if (target === "local") {
263
294
  const orchestratorUrl2 = localOrchestratorUrl();
@@ -268,18 +299,22 @@ function resolveAmplifyUpUrls(target) {
268
299
  orchestratorUrl: orchestratorUrl2,
269
300
  // Events + personalize → AWS development stack
270
301
  apiGatewayUrl,
271
- decisionApiUrl: `${apiGatewayUrl}/v1/personalize`
302
+ decisionApiUrl: `${apiGatewayUrl}/v1/personalize`,
303
+ edgeUrl: localEdgeUrl()
272
304
  };
273
305
  }
274
306
  const resolvedApi = typeof process !== "undefined" && process.env.NEXT_PUBLIC_AMPLIFYUP_API_URL?.replace(/\/$/, "") || AWS_PROD_API;
275
307
  const orchestratorFromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_ORCHESTRATOR_URL : void 0;
276
308
  const isLocalOrchestrator = !!orchestratorFromEnv && (orchestratorFromEnv.includes("localhost") || orchestratorFromEnv.includes("127.0.0.1"));
277
309
  const orchestratorUrl = isLocalOrchestrator || !orchestratorFromEnv ? PROD_ORCHESTRATOR : orchestratorFromEnv.replace(/\/$/, "");
310
+ const edgeFromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_EDGE_URL?.replace(/\/$/, "") : void 0;
311
+ const edgeUrl = edgeFromEnv && !edgeFromEnv.includes("localhost") && !edgeFromEnv.includes("127.0.0.1") ? edgeFromEnv : PROD_EDGE;
278
312
  return {
279
313
  target: "production",
280
314
  apiGatewayUrl: resolvedApi,
281
315
  orchestratorUrl,
282
- decisionApiUrl: `${resolvedApi}/v1/personalize`
316
+ decisionApiUrl: `${resolvedApi}/v1/personalize`,
317
+ edgeUrl
283
318
  };
284
319
  }
285
320
 
@@ -309,6 +344,177 @@ function isComposerPreview() {
309
344
  return false;
310
345
  }
311
346
 
347
+ // src/edge/normalizeRoute.ts
348
+ function normalizeRoute(route) {
349
+ let path = String(route || "").trim();
350
+ if (!path) return "/";
351
+ try {
352
+ if (/^https?:\/\//i.test(path)) {
353
+ path = new URL(path).pathname;
354
+ }
355
+ } catch {
356
+ }
357
+ const q = path.indexOf("?");
358
+ if (q >= 0) path = path.slice(0, q);
359
+ const h = path.indexOf("#");
360
+ if (h >= 0) path = path.slice(0, h);
361
+ if (!path.startsWith("/")) path = `/${path}`;
362
+ if (path.length > 1 && path.endsWith("/")) {
363
+ path = path.replace(/\/+$/, "");
364
+ }
365
+ return path || "/";
366
+ }
367
+
368
+ // src/edge/resolve.ts
369
+ var EdgeResolveError = class extends Error {
370
+ constructor(message, status, body) {
371
+ super(message);
372
+ this.name = "EdgeResolveError";
373
+ this.status = status;
374
+ this.body = body;
375
+ }
376
+ };
377
+ async function fetchEdgeResolve(options) {
378
+ const base = options.edgeUrl.replace(/\/+$/, "");
379
+ const route = normalizeRoute(options.route);
380
+ const params = new URLSearchParams({
381
+ route,
382
+ trackingId: options.trackingId
383
+ });
384
+ if (options.siteId) params.set("site", options.siteId);
385
+ if (options.anonId) params.set("anonId", options.anonId);
386
+ const fetchFn = options.fetch ?? globalThis.fetch.bind(globalThis);
387
+ const res = await fetchFn(`${base}/v1/resolve?${params.toString()}`, {
388
+ method: "GET",
389
+ headers: { Accept: "application/json" }
390
+ });
391
+ const body = await res.json().catch(() => ({}));
392
+ if (!res.ok) {
393
+ throw new EdgeResolveError(
394
+ (body && typeof body === "object" && "error" in body ? String(body.error) : `Edge resolve failed (${res.status})`) || `Edge resolve failed (${res.status})`,
395
+ res.status,
396
+ body
397
+ );
398
+ }
399
+ return body;
400
+ }
401
+
402
+ // src/edge/mapResolvedToPageConfig.ts
403
+ function mapResolvedComponent(node) {
404
+ const slots = [];
405
+ if (node.children) {
406
+ for (const [slotId, kids] of Object.entries(node.children)) {
407
+ slots.push({
408
+ slotId,
409
+ children: (kids || []).map(mapResolvedComponent)
410
+ });
411
+ }
412
+ }
413
+ return {
414
+ id: node.instanceId,
415
+ componentId: node.componentId,
416
+ props: { ...node.props || {} },
417
+ ...slots.length > 0 ? { slots } : {},
418
+ _contentSource: "edge"
419
+ };
420
+ }
421
+ function mapResolvedToPageConfig(payload) {
422
+ let layoutTree = [];
423
+ if (payload.tree && payload.tree.length > 0) {
424
+ layoutTree = payload.tree.map(mapResolvedComponent);
425
+ } else {
426
+ const zoneIds = Object.keys(payload.zones || {}).sort();
427
+ for (const zoneId of zoneIds) {
428
+ const roots = payload.zones[zoneId] || [];
429
+ layoutTree.push(...roots.map(mapResolvedComponent));
430
+ }
431
+ }
432
+ return {
433
+ id: `edge:${payload.siteId}:${payload.route}:v${payload.version}`,
434
+ route: payload.route,
435
+ title: "",
436
+ layoutTree,
437
+ meta: {
438
+ // Stash edge meta for diagnostics (not visitor-facing)
439
+ description: payload.meta?.degraded ? "degraded" : void 0
440
+ }
441
+ };
442
+ }
443
+ function collectDegraded(payload) {
444
+ if (payload.meta?.degraded) return true;
445
+ const walk = (nodes) => nodes.some(
446
+ (n) => !!n.degraded || (n.children ? Object.values(n.children).some((kids) => walk(kids || [])) : false)
447
+ );
448
+ if (payload.tree && walk(payload.tree)) return true;
449
+ return Object.values(payload.zones || {}).some((roots) => walk(roots || []));
450
+ }
451
+
452
+ // src/content/fetchContent.ts
453
+ async function fetchContent(options) {
454
+ const preview = options.preview ?? (typeof window !== "undefined" ? isComposerPreview() : false);
455
+ if (preview) {
456
+ try {
457
+ const page = await options.fetchOrchestratorPage(options.route, true);
458
+ return {
459
+ pageConfig: page,
460
+ source: "orchestrator",
461
+ meta: { source: "orchestrator" },
462
+ error: null
463
+ };
464
+ } catch (err) {
465
+ return {
466
+ pageConfig: null,
467
+ source: "orchestrator",
468
+ meta: { source: "orchestrator" },
469
+ error: err instanceof Error ? err.message : "Failed to load preview"
470
+ };
471
+ }
472
+ }
473
+ try {
474
+ const payload = await fetchEdgeResolve({
475
+ edgeUrl: options.edgeUrl,
476
+ trackingId: options.trackingId,
477
+ route: options.route,
478
+ anonId: options.anonId,
479
+ siteId: options.siteId,
480
+ fetch: options.fetchFn
481
+ });
482
+ const pageConfig = mapResolvedToPageConfig(payload);
483
+ const degraded = collectDegraded(payload);
484
+ return {
485
+ pageConfig,
486
+ source: "edge",
487
+ meta: {
488
+ source: "edge",
489
+ version: payload.version,
490
+ siteId: payload.siteId,
491
+ variantKeys: payload.meta?.variantKeys,
492
+ degraded,
493
+ audienceLookup: payload.meta?.audienceLookup,
494
+ decideLookup: payload.meta?.decideLookup,
495
+ resolvedAt: payload.meta?.resolvedAt
496
+ },
497
+ error: null
498
+ };
499
+ } catch (err) {
500
+ if (err instanceof EdgeResolveError && err.status === 404) {
501
+ return {
502
+ pageConfig: null,
503
+ source: "edge",
504
+ meta: { source: "edge" },
505
+ error: null
506
+ // unpublished → site fallback, not an error banner
507
+ };
508
+ }
509
+ return {
510
+ pageConfig: null,
511
+ source: "edge",
512
+ meta: { source: "edge" },
513
+ error: err instanceof Error ? err.message : "Couldn't load page content."
514
+ };
515
+ }
516
+ }
517
+
312
518
  // src/index.ts
313
519
  var SESSION_IDLE_GAP_MS = 30 * 60 * 1e3;
314
520
  function readPreviewQueryOverrides() {
@@ -338,6 +544,8 @@ var AmplifyUpSDK = class {
338
544
  this.apiGatewayUrl = "";
339
545
  this.orchestratorUrl = "";
340
546
  this.decisionApiUrl = "";
547
+ this.edgeUrl = "";
548
+ this.siteId = "";
341
549
  this.target = "local";
342
550
  this.initialized = false;
343
551
  /** Prevents overlapping init() from React Strict Mode double-mount */
@@ -494,7 +702,8 @@ var AmplifyUpSDK = class {
494
702
  isInitialized: () => this.isInitialized(),
495
703
  page: (url, properties) => this.page(url, properties),
496
704
  track: (eventName, properties) => this.track(eventName, properties),
497
- identify: (userId, traits) => this.identify(userId, traits)
705
+ identify: (userIdOrIdentifiers, traits) => this.identify(userIdOrIdentifiers, traits),
706
+ setProfileFields: (fields) => this.setProfileFields(fields)
498
707
  };
499
708
  }
500
709
  async performInit(config) {
@@ -509,6 +718,8 @@ var AmplifyUpSDK = class {
509
718
  this.apiGatewayUrl = urls.apiGatewayUrl;
510
719
  this.orchestratorUrl = urls.orchestratorUrl;
511
720
  this.decisionApiUrl = urls.decisionApiUrl;
721
+ this.edgeUrl = urls.edgeUrl;
722
+ this.siteId = config.siteId || "";
512
723
  const previewOverrides = readPreviewQueryOverrides();
513
724
  if (previewOverrides.orchestratorUrl) {
514
725
  this.orchestratorUrl = previewOverrides.orchestratorUrl;
@@ -517,6 +728,7 @@ var AmplifyUpSDK = class {
517
728
  this.target = "production";
518
729
  this.apiGatewayUrl = prodUrls.apiGatewayUrl;
519
730
  this.decisionApiUrl = prodUrls.decisionApiUrl;
731
+ this.edgeUrl = prodUrls.edgeUrl;
520
732
  }
521
733
  }
522
734
  this.config = {
@@ -524,7 +736,8 @@ var AmplifyUpSDK = class {
524
736
  debug: config.debug ?? true,
525
737
  // Enable debug by default
526
738
  target: this.target,
527
- dev: config.dev
739
+ dev: config.dev,
740
+ ...config.siteId ? { siteId: config.siteId } : {}
528
741
  };
529
742
  try {
530
743
  const adapterConfig = {
@@ -922,12 +1135,17 @@ var AmplifyUpSDK = class {
922
1135
  });
923
1136
  }
924
1137
  /**
925
- * Identify user (when they sign up or log in)
1138
+ * Identify a visitor.
1139
+ * - identify('user_123') — bare string; server maps via org default type
1140
+ * - identify({ email: '...', crm_id: '...' }) — explicit types
1141
+ * - identify('user_123', traits) — legacy form
926
1142
  */
927
- identify(userId, traits) {
1143
+ identify(userIdOrIdentifiers, traits) {
928
1144
  if (this.isPreviewMode()) {
929
1145
  if (this.config?.debug) {
930
- console.log("AmplifyUp SDK: Identify tracking disabled in preview mode", { userId });
1146
+ console.log("AmplifyUp SDK: Identify tracking disabled in preview mode", {
1147
+ userIdOrIdentifiers
1148
+ });
931
1149
  }
932
1150
  return;
933
1151
  }
@@ -943,10 +1161,45 @@ var AmplifyUpSDK = class {
943
1161
  trackingId: this.config?.trackingId,
944
1162
  ...traits
945
1163
  };
946
- this.adapter.identify(userId, identifyTraits);
947
- setUserId(userId);
1164
+ this.adapter.identify(userIdOrIdentifiers, identifyTraits);
1165
+ if (typeof userIdOrIdentifiers === "string") {
1166
+ setUserId(userIdOrIdentifiers);
1167
+ }
948
1168
  if (this.config?.debug) {
949
- console.log("AmplifyUp SDK: User identified", { userId, instanceId });
1169
+ console.log("AmplifyUp SDK: User identified", {
1170
+ userIdOrIdentifiers,
1171
+ instanceId
1172
+ });
1173
+ }
1174
+ }
1175
+ /**
1176
+ * Set profile fields (partial update). Omitted keys are left alone;
1177
+ * an explicit empty value clears the field.
1178
+ */
1179
+ setProfileFields(fields) {
1180
+ if (this.isPreviewMode()) {
1181
+ if (this.config?.debug) {
1182
+ console.log("AmplifyUp SDK: setProfileFields disabled in preview mode", {
1183
+ fields
1184
+ });
1185
+ }
1186
+ return;
1187
+ }
1188
+ if (!this.isInitialized()) {
1189
+ if (this.config?.debug) {
1190
+ console.warn("AmplifyUp SDK: Not initialized. setProfileFields not called.");
1191
+ }
1192
+ return;
1193
+ }
1194
+ const instanceId = getInstanceId();
1195
+ if (typeof this.adapter.setProfileFields === "function") {
1196
+ this.adapter.setProfileFields(fields, {
1197
+ instanceId: instanceId || void 0,
1198
+ trackingId: this.config?.trackingId
1199
+ });
1200
+ }
1201
+ if (this.config?.debug) {
1202
+ console.log("AmplifyUp SDK: Profile fields set", { fields, instanceId });
950
1203
  }
951
1204
  }
952
1205
  /**
@@ -1121,6 +1374,18 @@ Available Console Commands:
1121
1374
  getDecisionApiUrl() {
1122
1375
  return this.decisionApiUrl || void 0;
1123
1376
  }
1377
+ /**
1378
+ * Get Edge Worker URL (production content resolve)
1379
+ */
1380
+ getEdgeUrl() {
1381
+ return this.edgeUrl || void 0;
1382
+ }
1383
+ /**
1384
+ * Optional site id from config (Edge can resolve via trackingId alone).
1385
+ */
1386
+ getSiteId() {
1387
+ return this.siteId || this.config?.siteId || void 0;
1388
+ }
1124
1389
  /**
1125
1390
  * Build API URL for fetching page config from the Layout Provider
1126
1391
  */
@@ -2395,6 +2660,53 @@ function getSDK(adapter) {
2395
2660
  var trackContentView = (contentId, contentType, properties) => getSDK().trackContentView(contentId, contentType, properties);
2396
2661
  var refreshEventTracking = () => getSDK().refreshEventTracking();
2397
2662
  getSDK();
2663
+ var ComponentRenderBoundary = class extends Component {
2664
+ constructor() {
2665
+ super(...arguments);
2666
+ this.state = { error: null };
2667
+ }
2668
+ static getDerivedStateFromError(error) {
2669
+ return { error };
2670
+ }
2671
+ componentDidCatch(error) {
2672
+ console.error(
2673
+ `[AmplifyRenderer] "${this.props.componentId}" (${this.props.nodeId}) threw while rendering:`,
2674
+ error
2675
+ );
2676
+ }
2677
+ render() {
2678
+ if (this.state.error) {
2679
+ if (process.env.NODE_ENV !== "production") {
2680
+ return /* @__PURE__ */ jsxs(
2681
+ "div",
2682
+ {
2683
+ "data-amplifyup-render-error": "",
2684
+ "data-component-id": this.props.componentId,
2685
+ "data-node-id": this.props.nodeId,
2686
+ style: {
2687
+ margin: "1rem 0",
2688
+ padding: "0.75rem 1rem",
2689
+ border: "1px solid #fca5a5",
2690
+ borderRadius: "0.5rem",
2691
+ background: "#fef2f2",
2692
+ color: "#991b1b",
2693
+ fontSize: "0.875rem"
2694
+ },
2695
+ children: [
2696
+ 'Component "',
2697
+ this.props.componentId,
2698
+ '" failed to render:',
2699
+ " ",
2700
+ this.state.error.message
2701
+ ]
2702
+ }
2703
+ );
2704
+ }
2705
+ return null;
2706
+ }
2707
+ return this.props.children;
2708
+ }
2709
+ };
2398
2710
  function AmplifyRenderer({
2399
2711
  renderComponent,
2400
2712
  pageConfig: serverPageConfig,
@@ -2407,6 +2719,7 @@ function AmplifyRenderer({
2407
2719
  const pageConfig = serverPageConfig || clientHook.pageConfig || null;
2408
2720
  const loading = serverPageConfig ? false : clientHook.loading;
2409
2721
  const error = serverPageConfig ? null : clientHook.error;
2722
+ const contentSource = clientHook.source;
2410
2723
  const [variantCache, setVariantCache] = useState({});
2411
2724
  useEffect(() => {
2412
2725
  if (typeof window !== "undefined") {
@@ -2548,6 +2861,9 @@ function AmplifyRenderer({
2548
2861
  }, [pageConfig]);
2549
2862
  useEffect(() => {
2550
2863
  if (!pageConfig?.layoutTree || !pageConfig.layoutId) return;
2864
+ const roots = pageConfig.layoutTree;
2865
+ const fromEdge = contentSource === "edge" || roots.some((n) => n._contentSource === "edge");
2866
+ if (fromEdge) return;
2551
2867
  const sdk = getSDK();
2552
2868
  const instanceId = sdk.getInstanceId();
2553
2869
  const decisionApiUrl = sdk.getDecisionApiUrl();
@@ -2642,7 +2958,7 @@ function AmplifyRenderer({
2642
2958
  setVariantCache(newCache);
2643
2959
  };
2644
2960
  fetchVariants();
2645
- }, [pageConfig?.layoutTree, pageConfig?.layoutId, pageConfig?.route]);
2961
+ }, [pageConfig?.layoutTree, pageConfig?.layoutId, pageConfig?.route, contentSource]);
2646
2962
  if (loading) {
2647
2963
  return /* @__PURE__ */ jsx(Fragment, { children: loadingComponent || /* @__PURE__ */ jsx("div", { className: "min-h-screen bg-gray-50", children: /* @__PURE__ */ jsx("div", { className: "container mx-auto px-4 py-16", children: /* @__PURE__ */ jsxs("div", { className: "animate-pulse", children: [
2648
2964
  /* @__PURE__ */ jsx("div", { className: "h-8 bg-gray-200 rounded w-1/4 mb-4" }),
@@ -2747,11 +3063,20 @@ function AmplifyRenderer({
2747
3063
  const slotsToPass = Object.keys(slotChildren).length > 0 ? slotChildren : void 0;
2748
3064
  console.log(`[AmplifyRenderer] Calling renderComponent for ${node.componentId}`, {
2749
3065
  hasSlots: !!slotsToPass,
2750
- slotKeys: slotsToPass ? Object.keys(slotsToPass) : []
3066
+ slotKeys: slotsToPass ? Object.keys(slotsToPass) : [],
3067
+ propKeys: Object.keys(node.props || {}),
3068
+ props: node.props || {}
2751
3069
  });
2752
- return /* @__PURE__ */ jsx("div", { "data-node-id": node.id, "data-amplifyup-node": "", children: renderComponent(node.componentId, node.props || {}, slotsToPass, {
2753
- layoutNodeId: node.id
2754
- }) });
3070
+ return /* @__PURE__ */ jsx("div", { "data-node-id": node.id, "data-amplifyup-node": "", children: /* @__PURE__ */ jsx(
3071
+ ComponentRenderBoundary,
3072
+ {
3073
+ componentId: node.componentId,
3074
+ nodeId: node.id,
3075
+ children: renderComponent(node.componentId, node.props || {}, slotsToPass, {
3076
+ layoutNodeId: node.id
3077
+ })
3078
+ }
3079
+ ) });
2755
3080
  };
2756
3081
  const rawTree = pageConfig.layoutTree;
2757
3082
  const layoutTree = Array.isArray(rawTree) ? rawTree : rawTree && typeof rawTree === "object" && rawTree.componentId ? [rawTree] : [];
@@ -2843,28 +3168,38 @@ async function fetchPageConfigServer(route, trackingId, preview = false, options
2843
3168
  const target = resolveAmplifyUpTarget({
2844
3169
  configTarget: options?.target
2845
3170
  });
2846
- const { orchestratorUrl } = resolveAmplifyUpUrls(target);
2847
- const params = new URLSearchParams({
2848
- route,
2849
- trackingId
2850
- });
2851
- if (preview) {
2852
- params.set("preview", "true");
2853
- }
2854
- const url = `${orchestratorUrl}/api/layout/provider?${params.toString()}`;
2855
- try {
2856
- const res = await fetch(url, {
2857
- cache: "no-store",
2858
- headers: { Accept: "application/json" }
3171
+ const { orchestratorUrl, edgeUrl } = resolveAmplifyUpUrls(target);
3172
+ const previewFlag = preview || (options?.searchParams ? isPreviewRequest(options.searchParams) : false);
3173
+ const fetchOrchestratorPage = async (pageRoute, isPreview) => {
3174
+ const params = new URLSearchParams({
3175
+ route: pageRoute,
3176
+ trackingId
2859
3177
  });
2860
- if (!res.ok) {
3178
+ if (isPreview) params.set("preview", "true");
3179
+ const url = `${orchestratorUrl}/api/layout/provider?${params.toString()}`;
3180
+ try {
3181
+ const res = await fetch(url, {
3182
+ cache: "no-store",
3183
+ headers: { Accept: "application/json" }
3184
+ });
3185
+ if (!res.ok) return null;
3186
+ const data = await res.json();
3187
+ return data.page || null;
3188
+ } catch {
2861
3189
  return null;
2862
3190
  }
2863
- const data = await res.json();
2864
- return data.page || null;
2865
- } catch {
2866
- return null;
2867
- }
3191
+ };
3192
+ const result = await fetchContent({
3193
+ route,
3194
+ trackingId,
3195
+ anonId: options?.anonId,
3196
+ siteId: options?.siteId,
3197
+ preview: previewFlag,
3198
+ orchestratorUrl,
3199
+ edgeUrl,
3200
+ fetchOrchestratorPage
3201
+ });
3202
+ return result.pageConfig;
2868
3203
  }
2869
3204
  var ComponentContext = createContext(null);
2870
3205
  function ComponentContextProvider({
@@ -2987,6 +3322,25 @@ function Slot({
2987
3322
  }
2988
3323
  );
2989
3324
  }
3325
+ function formatFieldValue(value) {
3326
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
3327
+ return String(value);
3328
+ }
3329
+ if (Array.isArray(value)) {
3330
+ const parts = value.map((item) => {
3331
+ if (typeof item === "string") return item;
3332
+ if (item && typeof item === "object" && "children" in item && Array.isArray(item.children)) {
3333
+ return item.children.map((c) => typeof c?.text === "string" ? c.text : "").join("");
3334
+ }
3335
+ return "";
3336
+ }).filter(Boolean);
3337
+ if (parts.length > 0) return parts.join(" ");
3338
+ }
3339
+ if (value && typeof value === "object") {
3340
+ return "";
3341
+ }
3342
+ return "";
3343
+ }
2990
3344
  function Field({
2991
3345
  name,
2992
3346
  fallback,
@@ -3005,7 +3359,51 @@ function Field({
3005
3359
  if (render) {
3006
3360
  return /* @__PURE__ */ jsx("span", { className, children: render(fieldValue) });
3007
3361
  }
3008
- return /* @__PURE__ */ jsx("span", { className, children: String(fieldValue) });
3362
+ const text = formatFieldValue(fieldValue);
3363
+ if (!text) {
3364
+ return fallback ? /* @__PURE__ */ jsx("span", { className, children: fallback }) : null;
3365
+ }
3366
+ return /* @__PURE__ */ jsx("span", { className, children: text });
3367
+ }
3368
+ function markdownToHtml(markdown) {
3369
+ try {
3370
+ const result = marked.parse(markdown, { async: false });
3371
+ return typeof result === "string" ? result : "";
3372
+ } catch {
3373
+ return markdown;
3374
+ }
3375
+ }
3376
+ function RichText({
3377
+ name,
3378
+ fallback,
3379
+ className,
3380
+ as: Tag = "div"
3381
+ }) {
3382
+ const context = useContext(ComponentContext);
3383
+ if (!context) {
3384
+ console.warn(`[AmplifyUp SDK] RichText "${name}" used outside ComponentContextProvider`);
3385
+ return fallback ? /* @__PURE__ */ jsx(Fragment, { children: fallback }) : null;
3386
+ }
3387
+ const fieldValue = context.props?.[name];
3388
+ if (fieldValue === void 0 || fieldValue === null || fieldValue === "") {
3389
+ return fallback ? /* @__PURE__ */ jsx(Tag, { className, children: fallback }) : null;
3390
+ }
3391
+ let html = "";
3392
+ if (typeof fieldValue === "string") {
3393
+ const trimmed = fieldValue.trim();
3394
+ if (trimmed.startsWith("<") && trimmed.includes(">")) {
3395
+ html = fieldValue;
3396
+ } else {
3397
+ html = markdownToHtml(fieldValue);
3398
+ }
3399
+ } else {
3400
+ const text = formatFieldValue(fieldValue);
3401
+ html = text ? markdownToHtml(text) : "";
3402
+ }
3403
+ if (!html) {
3404
+ return fallback ? /* @__PURE__ */ jsx(Tag, { className, children: fallback }) : null;
3405
+ }
3406
+ return /* @__PURE__ */ jsx(Tag, { className, dangerouslySetInnerHTML: { __html: html } });
3009
3407
  }
3010
3408
  var usePathname = null;
3011
3409
  if (typeof window !== "undefined") {
@@ -3023,6 +3421,8 @@ function AmplifyUpProvider({ children, config }) {
3023
3421
  const [pageConfig, setPageConfig] = useState(null);
3024
3422
  const [loading, setLoading] = useState(true);
3025
3423
  const [error, setError] = useState(null);
3424
+ const [source, setSource] = useState(null);
3425
+ const [meta, setMeta] = useState(null);
3026
3426
  const getActualRoute = () => {
3027
3427
  if (typeof window === "undefined") return "";
3028
3428
  const currentPath = window.location.pathname;
@@ -3088,10 +3488,10 @@ function AmplifyUpProvider({ children, config }) {
3088
3488
  return () => {
3089
3489
  cancelled = true;
3090
3490
  };
3091
- }, [config.trackingId, config.target, config.debug, config.dev]);
3491
+ }, [config.trackingId, config.target, config.debug, config.dev, config.siteId]);
3092
3492
  useEffect(() => {
3093
3493
  if (!initialized) return;
3094
- const fetchConfig = async () => {
3494
+ const load = async () => {
3095
3495
  try {
3096
3496
  setLoading(true);
3097
3497
  setError(null);
@@ -3102,29 +3502,57 @@ function AmplifyUpProvider({ children, config }) {
3102
3502
  }
3103
3503
  const sdk = getSDK();
3104
3504
  sdk.routeChange(actualRoute);
3105
- const isPreviewContext = isComposerPreview();
3106
- const page = await sdk.fetchPageConfig(actualRoute, isPreviewContext);
3107
- if (!page) {
3505
+ const preview = isComposerPreview();
3506
+ const edgeUrl = sdk.getEdgeUrl();
3507
+ const orchestratorUrl = sdk.getOrchestratorUrl();
3508
+ const trackingId = sdk.getTrackingId();
3509
+ if (!trackingId || !orchestratorUrl || !edgeUrl) {
3510
+ setError("SDK not initialized");
3511
+ setLoading(false);
3512
+ return;
3513
+ }
3514
+ const result = await fetchContent({
3515
+ route: actualRoute,
3516
+ trackingId,
3517
+ anonId: sdk.getInstanceId(),
3518
+ siteId: sdk.getSiteId() || null,
3519
+ preview,
3520
+ orchestratorUrl,
3521
+ edgeUrl,
3522
+ fetchOrchestratorPage: (route, isPreview) => sdk.fetchPageConfig(route, isPreview)
3523
+ });
3524
+ setSource(result.source);
3525
+ setMeta(result.meta);
3526
+ setError(result.error);
3527
+ if (!result.pageConfig) {
3108
3528
  setPageConfig({
3109
3529
  id: "default",
3110
3530
  route: actualRoute,
3111
3531
  title: "Page Not Configured",
3112
- description: "This page has not been configured in the orchestrator yet.",
3532
+ description: "This page has not been published yet.",
3113
3533
  layoutTree: []
3114
3534
  });
3115
3535
  } else {
3116
- setPageConfig(page);
3536
+ setPageConfig(result.pageConfig);
3117
3537
  }
3118
3538
  } catch (err) {
3119
3539
  console.error("Error fetching page config:", err);
3120
3540
  setError(err instanceof Error ? err.message : "Unknown error");
3541
+ setSource(null);
3542
+ setMeta(null);
3121
3543
  } finally {
3122
3544
  setLoading(false);
3123
3545
  }
3124
3546
  };
3125
- fetchConfig();
3547
+ void load();
3126
3548
  }, [pathname, initialized]);
3127
- return /* @__PURE__ */ jsx(AmplifyUpContext.Provider, { value: { pageConfig, loading, error }, children });
3549
+ return /* @__PURE__ */ jsx(
3550
+ AmplifyUpContext.Provider,
3551
+ {
3552
+ value: { pageConfig, loading, error, source, meta },
3553
+ children
3554
+ }
3555
+ );
3128
3556
  }
3129
3557
  function useAmplifyUp() {
3130
3558
  const context = useContext(AmplifyUpContext);
@@ -3134,6 +3562,6 @@ function useAmplifyUp() {
3134
3562
  return context;
3135
3563
  }
3136
3564
 
3137
- export { AmplifyPageContent, AmplifyRenderer, AmplifyUpProvider, ComponentContextProvider, Field, Slot, fetchPageConfigServer, isComposerPreview, isPreviewRequest, useAmplifyUp };
3565
+ export { AmplifyPageContent, AmplifyRenderer, AmplifyUpProvider, ComponentContextProvider, Field, RichText, Slot, fetchPageConfigServer, isComposerPreview, isPreviewRequest, useAmplifyUp };
3138
3566
  //# sourceMappingURL=react.mjs.map
3139
3567
  //# sourceMappingURL=react.mjs.map