@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/index.mjs CHANGED
@@ -141,17 +141,42 @@ var AWSAdapter = class {
141
141
  };
142
142
  this.sendEvent("/v1/track", eventData);
143
143
  }
144
- identify(userId, traits) {
144
+ identify(userIdOrIdentifiers, traits = {}) {
145
145
  if (!this.initialized) {
146
146
  console.warn("AmplifyUp SDK: Not initialized. Call init() first.");
147
147
  return;
148
148
  }
149
+ const isMap = userIdOrIdentifiers !== null && typeof userIdOrIdentifiers === "object" && !Array.isArray(userIdOrIdentifiers);
150
+ const identifiers = isMap ? userIdOrIdentifiers : traits.identifiers;
151
+ const userId = isMap ? void 0 : String(userIdOrIdentifiers);
149
152
  const eventData = {
150
153
  type: "identify",
151
- userId,
152
154
  anonymousId: traits.instanceId,
153
155
  traits: {
154
- ...traits
156
+ ...traits,
157
+ ...identifiers ? { identifiers } : {}
158
+ },
159
+ ...identifiers ? { identifiers } : {},
160
+ ...userId ? { userId } : {},
161
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
162
+ };
163
+ this.sendEvent("/v1/track", eventData);
164
+ }
165
+ setProfileFields(fields, context = {}) {
166
+ if (!this.initialized) {
167
+ console.warn("AmplifyUp SDK: Not initialized. Call init() first.");
168
+ return;
169
+ }
170
+ const eventData = {
171
+ type: "set_fields",
172
+ anonymousId: context.instanceId,
173
+ fields,
174
+ traits: {
175
+ instanceId: context.instanceId,
176
+ trackingId: context.trackingId
177
+ },
178
+ properties: {
179
+ trackingId: context.trackingId
155
180
  },
156
181
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
157
182
  };
@@ -213,6 +238,7 @@ function clearIds() {
213
238
  var AWS_DEV_API = "https://api-dev.amplifyup.ai";
214
239
  var AWS_PROD_API = "https://api.amplifyup.ai";
215
240
  var PROD_ORCHESTRATOR = "https://amplifyup.ai";
241
+ var PROD_EDGE = "https://edge.amplifyup.ai";
216
242
  function isAmplifyUpTarget(value) {
217
243
  return value === "local" || value === "dev" || value === "production";
218
244
  }
@@ -248,6 +274,10 @@ function localAwsApiUrl() {
248
274
  const fromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_AMPLIFYUP_API_URL : void 0;
249
275
  return (fromEnv || AWS_DEV_API).replace(/\/$/, "");
250
276
  }
277
+ function localEdgeUrl() {
278
+ const fromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_EDGE_URL : void 0;
279
+ return (fromEnv || "http://localhost:8787").replace(/\/$/, "");
280
+ }
251
281
  function resolveAmplifyUpUrls(target) {
252
282
  if (target === "local") {
253
283
  const orchestratorUrl2 = localOrchestratorUrl();
@@ -258,18 +288,22 @@ function resolveAmplifyUpUrls(target) {
258
288
  orchestratorUrl: orchestratorUrl2,
259
289
  // Events + personalize → AWS development stack
260
290
  apiGatewayUrl,
261
- decisionApiUrl: `${apiGatewayUrl}/v1/personalize`
291
+ decisionApiUrl: `${apiGatewayUrl}/v1/personalize`,
292
+ edgeUrl: localEdgeUrl()
262
293
  };
263
294
  }
264
295
  const resolvedApi = typeof process !== "undefined" && process.env.NEXT_PUBLIC_AMPLIFYUP_API_URL?.replace(/\/$/, "") || AWS_PROD_API;
265
296
  const orchestratorFromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_ORCHESTRATOR_URL : void 0;
266
297
  const isLocalOrchestrator = !!orchestratorFromEnv && (orchestratorFromEnv.includes("localhost") || orchestratorFromEnv.includes("127.0.0.1"));
267
298
  const orchestratorUrl = isLocalOrchestrator || !orchestratorFromEnv ? PROD_ORCHESTRATOR : orchestratorFromEnv.replace(/\/$/, "");
299
+ const edgeFromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_EDGE_URL?.replace(/\/$/, "") : void 0;
300
+ const edgeUrl = edgeFromEnv && !edgeFromEnv.includes("localhost") && !edgeFromEnv.includes("127.0.0.1") ? edgeFromEnv : PROD_EDGE;
268
301
  return {
269
302
  target: "production",
270
303
  apiGatewayUrl: resolvedApi,
271
304
  orchestratorUrl,
272
- decisionApiUrl: `${resolvedApi}/v1/personalize`
305
+ decisionApiUrl: `${resolvedApi}/v1/personalize`,
306
+ edgeUrl
273
307
  };
274
308
  }
275
309
 
@@ -299,6 +333,177 @@ function isComposerPreview() {
299
333
  return false;
300
334
  }
301
335
 
336
+ // src/edge/normalizeRoute.ts
337
+ function normalizeRoute(route) {
338
+ let path = String(route || "").trim();
339
+ if (!path) return "/";
340
+ try {
341
+ if (/^https?:\/\//i.test(path)) {
342
+ path = new URL(path).pathname;
343
+ }
344
+ } catch {
345
+ }
346
+ const q = path.indexOf("?");
347
+ if (q >= 0) path = path.slice(0, q);
348
+ const h = path.indexOf("#");
349
+ if (h >= 0) path = path.slice(0, h);
350
+ if (!path.startsWith("/")) path = `/${path}`;
351
+ if (path.length > 1 && path.endsWith("/")) {
352
+ path = path.replace(/\/+$/, "");
353
+ }
354
+ return path || "/";
355
+ }
356
+
357
+ // src/edge/resolve.ts
358
+ var EdgeResolveError = class extends Error {
359
+ constructor(message, status, body) {
360
+ super(message);
361
+ this.name = "EdgeResolveError";
362
+ this.status = status;
363
+ this.body = body;
364
+ }
365
+ };
366
+ async function fetchEdgeResolve(options) {
367
+ const base = options.edgeUrl.replace(/\/+$/, "");
368
+ const route = normalizeRoute(options.route);
369
+ const params = new URLSearchParams({
370
+ route,
371
+ trackingId: options.trackingId
372
+ });
373
+ if (options.siteId) params.set("site", options.siteId);
374
+ if (options.anonId) params.set("anonId", options.anonId);
375
+ const fetchFn = options.fetch ?? globalThis.fetch.bind(globalThis);
376
+ const res = await fetchFn(`${base}/v1/resolve?${params.toString()}`, {
377
+ method: "GET",
378
+ headers: { Accept: "application/json" }
379
+ });
380
+ const body = await res.json().catch(() => ({}));
381
+ if (!res.ok) {
382
+ throw new EdgeResolveError(
383
+ (body && typeof body === "object" && "error" in body ? String(body.error) : `Edge resolve failed (${res.status})`) || `Edge resolve failed (${res.status})`,
384
+ res.status,
385
+ body
386
+ );
387
+ }
388
+ return body;
389
+ }
390
+
391
+ // src/edge/mapResolvedToPageConfig.ts
392
+ function mapResolvedComponent(node) {
393
+ const slots = [];
394
+ if (node.children) {
395
+ for (const [slotId, kids] of Object.entries(node.children)) {
396
+ slots.push({
397
+ slotId,
398
+ children: (kids || []).map(mapResolvedComponent)
399
+ });
400
+ }
401
+ }
402
+ return {
403
+ id: node.instanceId,
404
+ componentId: node.componentId,
405
+ props: { ...node.props || {} },
406
+ ...slots.length > 0 ? { slots } : {},
407
+ _contentSource: "edge"
408
+ };
409
+ }
410
+ function mapResolvedToPageConfig(payload) {
411
+ let layoutTree = [];
412
+ if (payload.tree && payload.tree.length > 0) {
413
+ layoutTree = payload.tree.map(mapResolvedComponent);
414
+ } else {
415
+ const zoneIds = Object.keys(payload.zones || {}).sort();
416
+ for (const zoneId of zoneIds) {
417
+ const roots = payload.zones[zoneId] || [];
418
+ layoutTree.push(...roots.map(mapResolvedComponent));
419
+ }
420
+ }
421
+ return {
422
+ id: `edge:${payload.siteId}:${payload.route}:v${payload.version}`,
423
+ route: payload.route,
424
+ title: "",
425
+ layoutTree,
426
+ meta: {
427
+ // Stash edge meta for diagnostics (not visitor-facing)
428
+ description: payload.meta?.degraded ? "degraded" : void 0
429
+ }
430
+ };
431
+ }
432
+ function collectDegraded(payload) {
433
+ if (payload.meta?.degraded) return true;
434
+ const walk = (nodes) => nodes.some(
435
+ (n) => !!n.degraded || (n.children ? Object.values(n.children).some((kids) => walk(kids || [])) : false)
436
+ );
437
+ if (payload.tree && walk(payload.tree)) return true;
438
+ return Object.values(payload.zones || {}).some((roots) => walk(roots || []));
439
+ }
440
+
441
+ // src/content/fetchContent.ts
442
+ async function fetchContent(options) {
443
+ const preview = options.preview ?? (typeof window !== "undefined" ? isComposerPreview() : false);
444
+ if (preview) {
445
+ try {
446
+ const page2 = await options.fetchOrchestratorPage(options.route, true);
447
+ return {
448
+ pageConfig: page2,
449
+ source: "orchestrator",
450
+ meta: { source: "orchestrator" },
451
+ error: null
452
+ };
453
+ } catch (err) {
454
+ return {
455
+ pageConfig: null,
456
+ source: "orchestrator",
457
+ meta: { source: "orchestrator" },
458
+ error: err instanceof Error ? err.message : "Failed to load preview"
459
+ };
460
+ }
461
+ }
462
+ try {
463
+ const payload = await fetchEdgeResolve({
464
+ edgeUrl: options.edgeUrl,
465
+ trackingId: options.trackingId,
466
+ route: options.route,
467
+ anonId: options.anonId,
468
+ siteId: options.siteId,
469
+ fetch: options.fetchFn
470
+ });
471
+ const pageConfig = mapResolvedToPageConfig(payload);
472
+ const degraded = collectDegraded(payload);
473
+ return {
474
+ pageConfig,
475
+ source: "edge",
476
+ meta: {
477
+ source: "edge",
478
+ version: payload.version,
479
+ siteId: payload.siteId,
480
+ variantKeys: payload.meta?.variantKeys,
481
+ degraded,
482
+ audienceLookup: payload.meta?.audienceLookup,
483
+ decideLookup: payload.meta?.decideLookup,
484
+ resolvedAt: payload.meta?.resolvedAt
485
+ },
486
+ error: null
487
+ };
488
+ } catch (err) {
489
+ if (err instanceof EdgeResolveError && err.status === 404) {
490
+ return {
491
+ pageConfig: null,
492
+ source: "edge",
493
+ meta: { source: "edge" },
494
+ error: null
495
+ // unpublished → site fallback, not an error banner
496
+ };
497
+ }
498
+ return {
499
+ pageConfig: null,
500
+ source: "edge",
501
+ meta: { source: "edge" },
502
+ error: err instanceof Error ? err.message : "Couldn't load page content."
503
+ };
504
+ }
505
+ }
506
+
302
507
  // src/index.ts
303
508
  var SESSION_IDLE_GAP_MS = 30 * 60 * 1e3;
304
509
  function readPreviewQueryOverrides() {
@@ -328,6 +533,8 @@ var AmplifyUpSDK = class {
328
533
  this.apiGatewayUrl = "";
329
534
  this.orchestratorUrl = "";
330
535
  this.decisionApiUrl = "";
536
+ this.edgeUrl = "";
537
+ this.siteId = "";
331
538
  this.target = "local";
332
539
  this.initialized = false;
333
540
  /** Prevents overlapping init() from React Strict Mode double-mount */
@@ -484,7 +691,8 @@ var AmplifyUpSDK = class {
484
691
  isInitialized: () => this.isInitialized(),
485
692
  page: (url, properties) => this.page(url, properties),
486
693
  track: (eventName, properties) => this.track(eventName, properties),
487
- identify: (userId, traits) => this.identify(userId, traits)
694
+ identify: (userIdOrIdentifiers, traits) => this.identify(userIdOrIdentifiers, traits),
695
+ setProfileFields: (fields) => this.setProfileFields(fields)
488
696
  };
489
697
  }
490
698
  async performInit(config) {
@@ -499,6 +707,8 @@ var AmplifyUpSDK = class {
499
707
  this.apiGatewayUrl = urls.apiGatewayUrl;
500
708
  this.orchestratorUrl = urls.orchestratorUrl;
501
709
  this.decisionApiUrl = urls.decisionApiUrl;
710
+ this.edgeUrl = urls.edgeUrl;
711
+ this.siteId = config.siteId || "";
502
712
  const previewOverrides = readPreviewQueryOverrides();
503
713
  if (previewOverrides.orchestratorUrl) {
504
714
  this.orchestratorUrl = previewOverrides.orchestratorUrl;
@@ -507,6 +717,7 @@ var AmplifyUpSDK = class {
507
717
  this.target = "production";
508
718
  this.apiGatewayUrl = prodUrls.apiGatewayUrl;
509
719
  this.decisionApiUrl = prodUrls.decisionApiUrl;
720
+ this.edgeUrl = prodUrls.edgeUrl;
510
721
  }
511
722
  }
512
723
  this.config = {
@@ -514,7 +725,8 @@ var AmplifyUpSDK = class {
514
725
  debug: config.debug ?? true,
515
726
  // Enable debug by default
516
727
  target: this.target,
517
- dev: config.dev
728
+ dev: config.dev,
729
+ ...config.siteId ? { siteId: config.siteId } : {}
518
730
  };
519
731
  try {
520
732
  const adapterConfig = {
@@ -912,12 +1124,17 @@ var AmplifyUpSDK = class {
912
1124
  });
913
1125
  }
914
1126
  /**
915
- * Identify user (when they sign up or log in)
1127
+ * Identify a visitor.
1128
+ * - identify('user_123') — bare string; server maps via org default type
1129
+ * - identify({ email: '...', crm_id: '...' }) — explicit types
1130
+ * - identify('user_123', traits) — legacy form
916
1131
  */
917
- identify(userId, traits) {
1132
+ identify(userIdOrIdentifiers, traits) {
918
1133
  if (this.isPreviewMode()) {
919
1134
  if (this.config?.debug) {
920
- console.log("AmplifyUp SDK: Identify tracking disabled in preview mode", { userId });
1135
+ console.log("AmplifyUp SDK: Identify tracking disabled in preview mode", {
1136
+ userIdOrIdentifiers
1137
+ });
921
1138
  }
922
1139
  return;
923
1140
  }
@@ -933,10 +1150,45 @@ var AmplifyUpSDK = class {
933
1150
  trackingId: this.config?.trackingId,
934
1151
  ...traits
935
1152
  };
936
- this.adapter.identify(userId, identifyTraits);
937
- setUserId(userId);
1153
+ this.adapter.identify(userIdOrIdentifiers, identifyTraits);
1154
+ if (typeof userIdOrIdentifiers === "string") {
1155
+ setUserId(userIdOrIdentifiers);
1156
+ }
1157
+ if (this.config?.debug) {
1158
+ console.log("AmplifyUp SDK: User identified", {
1159
+ userIdOrIdentifiers,
1160
+ instanceId
1161
+ });
1162
+ }
1163
+ }
1164
+ /**
1165
+ * Set profile fields (partial update). Omitted keys are left alone;
1166
+ * an explicit empty value clears the field.
1167
+ */
1168
+ setProfileFields(fields) {
1169
+ if (this.isPreviewMode()) {
1170
+ if (this.config?.debug) {
1171
+ console.log("AmplifyUp SDK: setProfileFields disabled in preview mode", {
1172
+ fields
1173
+ });
1174
+ }
1175
+ return;
1176
+ }
1177
+ if (!this.isInitialized()) {
1178
+ if (this.config?.debug) {
1179
+ console.warn("AmplifyUp SDK: Not initialized. setProfileFields not called.");
1180
+ }
1181
+ return;
1182
+ }
1183
+ const instanceId = getInstanceId();
1184
+ if (typeof this.adapter.setProfileFields === "function") {
1185
+ this.adapter.setProfileFields(fields, {
1186
+ instanceId: instanceId || void 0,
1187
+ trackingId: this.config?.trackingId
1188
+ });
1189
+ }
938
1190
  if (this.config?.debug) {
939
- console.log("AmplifyUp SDK: User identified", { userId, instanceId });
1191
+ console.log("AmplifyUp SDK: Profile fields set", { fields, instanceId });
940
1192
  }
941
1193
  }
942
1194
  /**
@@ -1111,6 +1363,18 @@ Available Console Commands:
1111
1363
  getDecisionApiUrl() {
1112
1364
  return this.decisionApiUrl || void 0;
1113
1365
  }
1366
+ /**
1367
+ * Get Edge Worker URL (production content resolve)
1368
+ */
1369
+ getEdgeUrl() {
1370
+ return this.edgeUrl || void 0;
1371
+ }
1372
+ /**
1373
+ * Optional site id from config (Edge can resolve via trackingId alone).
1374
+ */
1375
+ getSiteId() {
1376
+ return this.siteId || this.config?.siteId || void 0;
1377
+ }
1114
1378
  /**
1115
1379
  * Build API URL for fetching page config from the Layout Provider
1116
1380
  */
@@ -2393,7 +2657,8 @@ var trackClick = (elementId, elementText, properties) => getSDK().trackClick(ele
2393
2657
  var trackFormSubmit = (formId, formData) => getSDK().trackFormSubmit(formId, formData);
2394
2658
  var trackFormFieldInteraction = (fieldName, fieldValue) => getSDK().trackFormFieldInteraction(fieldName, fieldValue);
2395
2659
  var trackContentView = (contentId, contentType, properties) => getSDK().trackContentView(contentId, contentType, properties);
2396
- var identify = (userId, traits) => getSDK().identify(userId, traits);
2660
+ var identify = (userIdOrIdentifiers, traits) => getSDK().identify(userIdOrIdentifiers, traits);
2661
+ var setProfileFields = (fields) => getSDK().setProfileFields(fields);
2397
2662
  var trackContentEngagement = (contentId, engagementType) => getSDK().trackContentEngagement(contentId, engagementType);
2398
2663
  var reset = () => getSDK().reset();
2399
2664
  var getInstanceId2 = () => getSDK().getInstanceId();
@@ -2423,6 +2688,6 @@ var verifyAWSConnection = () => {
2423
2688
  };
2424
2689
  var index_default = getSDK();
2425
2690
 
2426
- export { AmplifyUpSDK, SESSION_IDLE_GAP_MS, buildLayoutProviderUrl, buildPageRenderUrl, cleanupEventTracking, index_default as default, fetchPageConfig, getDiagnostics, getInstanceId2 as getInstanceId, getOrchestratorUrl, getSDK, getStatus, getTarget, getTrackingId, getUserId2 as getUserId, identify, init, isAmplifyUpTarget, isComposerPreview, isPreviewRequest, normalizeAmplifyUpTarget, page, refreshEventTracking, reset, resolveAmplifyUpTarget, resolveAmplifyUpUrls, routeChange, setupComponentViewTracking, setupEventTracking, testTracking, track, trackClick, trackContentEngagement, trackContentView, trackFormFieldInteraction, trackFormSubmit, verifyAWSConnection };
2691
+ export { AmplifyUpSDK, EdgeResolveError, SESSION_IDLE_GAP_MS, buildLayoutProviderUrl, buildPageRenderUrl, cleanupEventTracking, index_default as default, fetchContent, fetchEdgeResolve, fetchPageConfig, getDiagnostics, getInstanceId2 as getInstanceId, getOrchestratorUrl, getSDK, getStatus, getTarget, getTrackingId, getUserId2 as getUserId, identify, init, isAmplifyUpTarget, isComposerPreview, isPreviewRequest, mapResolvedToPageConfig, normalizeAmplifyUpTarget, normalizeRoute, page, refreshEventTracking, reset, resolveAmplifyUpTarget, resolveAmplifyUpUrls, routeChange, setProfileFields, setupComponentViewTracking, setupEventTracking, testTracking, track, trackClick, trackContentEngagement, trackContentView, trackFormFieldInteraction, trackFormSubmit, verifyAWSConnection };
2427
2692
  //# sourceMappingURL=index.mjs.map
2428
2693
  //# sourceMappingURL=index.mjs.map