@amplifyup/sdk 0.1.74 → 0.1.76

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,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
- import { L as LayoutComponentProps, P as PageConfig } from './types-BGZYaFxP.mjs';
4
+ import { L as LayoutComponentProps, P as PageConfig } from './types-D4TSd2Yt.mjs';
5
5
 
6
6
  interface AmplifyRendererProps {
7
7
  /**
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
- import { L as LayoutComponentProps, P as PageConfig } from './types-BGZYaFxP.js';
4
+ import { L as LayoutComponentProps, P as PageConfig } from './types-D4TSd2Yt.js';
5
5
 
6
6
  interface AmplifyRendererProps {
7
7
  /**
@@ -13,7 +13,121 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
13
13
  throw Error('Dynamic require of "' + x + '" is not supported');
14
14
  });
15
15
 
16
+ // src/storage.ts
17
+ var INSTANCE_ID_KEY = "amplifyup_instance_id";
18
+ var USER_ID_KEY = "amplifyup_user_id";
19
+ var SESSION_ID_KEY = "amplifyup_session_id";
20
+ var SESSION_ACTIVITY_KEY = "amplifyup_session_activity";
21
+ var VISITOR_FIRST_SEEN_KEY = "amplifyup_visitor_first_seen";
22
+ var ANON_COOKIE_NAME = "amplifyup_anon_id";
23
+ var SESSION_COOKIE_NAME = "amplifyup_session_id";
24
+ var SESSION_IDLE_GAP_MS = 30 * 60 * 1e3;
25
+ function generateGuid() {
26
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
27
+ return crypto.randomUUID();
28
+ }
29
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
30
+ const r = Math.random() * 16 | 0;
31
+ const v = c === "x" ? r : r & 3 | 8;
32
+ return v.toString(16);
33
+ });
34
+ }
35
+ function readCookie(name) {
36
+ if (typeof document === "undefined") return null;
37
+ const parts = document.cookie.split(";");
38
+ for (const part of parts) {
39
+ const idx = part.indexOf("=");
40
+ if (idx === -1) continue;
41
+ if (part.slice(0, idx).trim() !== name) continue;
42
+ const value = part.slice(idx + 1).trim();
43
+ try {
44
+ return value ? decodeURIComponent(value) : null;
45
+ } catch {
46
+ return value || null;
47
+ }
48
+ }
49
+ return null;
50
+ }
51
+ function writeCookie(name, value, maxAgeSeconds = 31536e3) {
52
+ if (typeof document === "undefined") return;
53
+ document.cookie = `${name}=${encodeURIComponent(value)}; Path=/; Max-Age=${maxAgeSeconds}; SameSite=Lax`;
54
+ }
55
+ function getInstanceId() {
56
+ if (typeof window === "undefined") {
57
+ return "";
58
+ }
59
+ const fromCookie = readCookie(ANON_COOKIE_NAME);
60
+ const fromLs = localStorage.getItem(INSTANCE_ID_KEY);
61
+ const instanceId = fromLs || fromCookie || `browser_${generateGuid()}`;
62
+ if (fromLs !== instanceId) {
63
+ localStorage.setItem(INSTANCE_ID_KEY, instanceId);
64
+ }
65
+ if (fromCookie !== instanceId) {
66
+ writeCookie(ANON_COOKIE_NAME, instanceId);
67
+ }
68
+ return instanceId;
69
+ }
70
+ function getUserId() {
71
+ if (typeof window === "undefined") {
72
+ return null;
73
+ }
74
+ return localStorage.getItem(USER_ID_KEY);
75
+ }
76
+ function getSessionId() {
77
+ if (typeof window === "undefined") {
78
+ return "";
79
+ }
80
+ const now = Date.now();
81
+ const lastActivity = Number(localStorage.getItem(SESSION_ACTIVITY_KEY) || 0);
82
+ const fromCookie = readCookie(SESSION_COOKIE_NAME);
83
+ const fromLs = localStorage.getItem(SESSION_ID_KEY);
84
+ let sessionId = fromLs || fromCookie || "";
85
+ if (!sessionId || lastActivity > 0 && now - lastActivity >= SESSION_IDLE_GAP_MS) {
86
+ sessionId = generateGuid();
87
+ }
88
+ localStorage.setItem(SESSION_ID_KEY, sessionId);
89
+ localStorage.setItem(SESSION_ACTIVITY_KEY, String(now));
90
+ writeCookie(SESSION_COOKIE_NAME, sessionId, Math.floor(SESSION_IDLE_GAP_MS / 1e3));
91
+ return sessionId;
92
+ }
93
+ function getVisitorFirstSeenAt() {
94
+ if (typeof window === "undefined") {
95
+ return null;
96
+ }
97
+ try {
98
+ const existing = localStorage.getItem(VISITOR_FIRST_SEEN_KEY);
99
+ if (existing) return existing;
100
+ const firstSeenAt = (/* @__PURE__ */ new Date()).toISOString();
101
+ localStorage.setItem(VISITOR_FIRST_SEEN_KEY, firstSeenAt);
102
+ return firstSeenAt;
103
+ } catch {
104
+ return null;
105
+ }
106
+ }
107
+ function setUserId(userId) {
108
+ if (typeof window === "undefined") {
109
+ return;
110
+ }
111
+ localStorage.setItem(USER_ID_KEY, userId);
112
+ }
113
+ function clearIds() {
114
+ if (typeof window === "undefined") {
115
+ return;
116
+ }
117
+ localStorage.removeItem(INSTANCE_ID_KEY);
118
+ localStorage.removeItem(USER_ID_KEY);
119
+ localStorage.removeItem(SESSION_ID_KEY);
120
+ localStorage.removeItem(SESSION_ACTIVITY_KEY);
121
+ localStorage.removeItem(VISITOR_FIRST_SEEN_KEY);
122
+ document.cookie = `${ANON_COOKIE_NAME}=; Path=/; Max-Age=0; SameSite=Lax`;
123
+ document.cookie = `${SESSION_COOKIE_NAME}=; Path=/; Max-Age=0; SameSite=Lax`;
124
+ }
125
+
16
126
  // src/adapters/aws.ts
127
+ function visitorContext() {
128
+ const firstSeenAt = getVisitorFirstSeenAt();
129
+ return firstSeenAt ? { firstSeenAt } : void 0;
130
+ }
17
131
  var AWSAdapter = class {
18
132
  constructor() {
19
133
  this.initialized = false;
@@ -53,7 +167,9 @@ var AWSAdapter = class {
53
167
  console.warn("AmplifyUp SDK: AWS configuration missing");
54
168
  return;
55
169
  }
56
- const url = `${this.apiGatewayUrl}${endpoint}`;
170
+ const trackingId = eventData?.trackingId || this.config?.trackingId;
171
+ const query = trackingId ? `?tid=${encodeURIComponent(trackingId)}` : "";
172
+ const url = `${this.apiGatewayUrl}${endpoint}${query}`;
57
173
  try {
58
174
  const response = await fetch(url, {
59
175
  method: "POST",
@@ -115,7 +231,8 @@ var AWSAdapter = class {
115
231
  page: {
116
232
  path: properties.path || properties.url,
117
233
  referrer: properties.referrer
118
- }
234
+ },
235
+ visitor: visitorContext()
119
236
  },
120
237
  timestamp: properties.timestamp || (/* @__PURE__ */ new Date()).toISOString()
121
238
  };
@@ -153,7 +270,8 @@ var AWSAdapter = class {
153
270
  ...properties
154
271
  },
155
272
  context: {
156
- url: properties.url || (typeof window !== "undefined" ? window.location.href : "")
273
+ url: properties.url || (typeof window !== "undefined" ? window.location.href : ""),
274
+ visitor: visitorContext()
157
275
  },
158
276
  timestamp: properties.timestamp || (/* @__PURE__ */ new Date()).toISOString()
159
277
  };
@@ -209,100 +327,6 @@ var AWSAdapter = class {
209
327
  }
210
328
  };
211
329
 
212
- // src/storage.ts
213
- var INSTANCE_ID_KEY = "amplifyup_instance_id";
214
- var USER_ID_KEY = "amplifyup_user_id";
215
- var SESSION_ID_KEY = "amplifyup_session_id";
216
- var SESSION_ACTIVITY_KEY = "amplifyup_session_activity";
217
- var ANON_COOKIE_NAME = "amplifyup_anon_id";
218
- var SESSION_COOKIE_NAME = "amplifyup_session_id";
219
- var SESSION_IDLE_GAP_MS = 30 * 60 * 1e3;
220
- function generateGuid() {
221
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
222
- return crypto.randomUUID();
223
- }
224
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
225
- const r = Math.random() * 16 | 0;
226
- const v = c === "x" ? r : r & 3 | 8;
227
- return v.toString(16);
228
- });
229
- }
230
- function readCookie(name) {
231
- if (typeof document === "undefined") return null;
232
- const parts = document.cookie.split(";");
233
- for (const part of parts) {
234
- const idx = part.indexOf("=");
235
- if (idx === -1) continue;
236
- if (part.slice(0, idx).trim() !== name) continue;
237
- const value = part.slice(idx + 1).trim();
238
- try {
239
- return value ? decodeURIComponent(value) : null;
240
- } catch {
241
- return value || null;
242
- }
243
- }
244
- return null;
245
- }
246
- function writeCookie(name, value, maxAgeSeconds = 31536e3) {
247
- if (typeof document === "undefined") return;
248
- document.cookie = `${name}=${encodeURIComponent(value)}; Path=/; Max-Age=${maxAgeSeconds}; SameSite=Lax`;
249
- }
250
- function getInstanceId() {
251
- if (typeof window === "undefined") {
252
- return "";
253
- }
254
- const fromCookie = readCookie(ANON_COOKIE_NAME);
255
- const fromLs = localStorage.getItem(INSTANCE_ID_KEY);
256
- const instanceId = fromLs || fromCookie || `browser_${generateGuid()}`;
257
- if (fromLs !== instanceId) {
258
- localStorage.setItem(INSTANCE_ID_KEY, instanceId);
259
- }
260
- if (fromCookie !== instanceId) {
261
- writeCookie(ANON_COOKIE_NAME, instanceId);
262
- }
263
- return instanceId;
264
- }
265
- function getUserId() {
266
- if (typeof window === "undefined") {
267
- return null;
268
- }
269
- return localStorage.getItem(USER_ID_KEY);
270
- }
271
- function getSessionId() {
272
- if (typeof window === "undefined") {
273
- return "";
274
- }
275
- const now = Date.now();
276
- const lastActivity = Number(localStorage.getItem(SESSION_ACTIVITY_KEY) || 0);
277
- const fromCookie = readCookie(SESSION_COOKIE_NAME);
278
- const fromLs = localStorage.getItem(SESSION_ID_KEY);
279
- let sessionId = fromLs || fromCookie || "";
280
- if (!sessionId || lastActivity > 0 && now - lastActivity >= SESSION_IDLE_GAP_MS) {
281
- sessionId = generateGuid();
282
- }
283
- localStorage.setItem(SESSION_ID_KEY, sessionId);
284
- localStorage.setItem(SESSION_ACTIVITY_KEY, String(now));
285
- writeCookie(SESSION_COOKIE_NAME, sessionId, Math.floor(SESSION_IDLE_GAP_MS / 1e3));
286
- return sessionId;
287
- }
288
- function setUserId(userId) {
289
- if (typeof window === "undefined") {
290
- return;
291
- }
292
- localStorage.setItem(USER_ID_KEY, userId);
293
- }
294
- function clearIds() {
295
- if (typeof window === "undefined") {
296
- return;
297
- }
298
- localStorage.removeItem(INSTANCE_ID_KEY);
299
- localStorage.removeItem(USER_ID_KEY);
300
- localStorage.removeItem(SESSION_ID_KEY);
301
- localStorage.removeItem(SESSION_ACTIVITY_KEY);
302
- document.cookie = `${ANON_COOKIE_NAME}=; Path=/; Max-Age=0; SameSite=Lax`;
303
- document.cookie = `${SESSION_COOKIE_NAME}=; Path=/; Max-Age=0; SameSite=Lax`;
304
- }
305
-
306
330
  // src/targets.ts
307
331
  var AWS_DEV_API = "https://api-dev.amplifyup.ai";
308
332
  var AWS_PROD_API = "https://api.amplifyup.ai";
@@ -808,6 +832,7 @@ function applyPageContext(input, opts) {
808
832
  }
809
833
  const pageFields = {};
810
834
  for (const pf of opts.pageData?.pageFields || []) {
835
+ if (pf.dataType === "taxonomy") continue;
811
836
  if (pf.source === "static") {
812
837
  if (pf.value !== void 0) pageFields[pf.key] = pf.value;
813
838
  continue;
@@ -830,6 +855,7 @@ function applyPageContext(input, opts) {
830
855
  function staticPageFieldsFromSnapshot(pageData) {
831
856
  const pageFields = {};
832
857
  for (const pf of pageData?.pageFields || []) {
858
+ if (pf.dataType === "taxonomy") continue;
833
859
  if (pf.source === "static" && pf.value !== void 0) {
834
860
  pageFields[pf.key] = pf.value;
835
861
  }
@@ -847,6 +873,11 @@ function attachStaticPageContext(pageData, pageRoute) {
847
873
  pageRoute: pageRoute || ""
848
874
  };
849
875
  }
876
+ function withPageTaxonomies(properties, taxonomies) {
877
+ if (!taxonomies || Object.keys(taxonomies).length === 0) return properties;
878
+ const page = properties.page && typeof properties.page === "object" && !Array.isArray(properties.page) ? properties.page : { fields: {} };
879
+ return { ...properties, page: { ...page, taxonomies } };
880
+ }
850
881
  function mergeEventContext(properties, attached) {
851
882
  if (!attached) return properties;
852
883
  return {
@@ -916,6 +947,27 @@ function hydratePageResourceProps(props, fields) {
916
947
  return out;
917
948
  }
918
949
 
950
+ // src/edge/normalizeRoute.ts
951
+ function normalizeRoute(route) {
952
+ let path = String(route || "").trim();
953
+ if (!path) return "/";
954
+ try {
955
+ if (/^https?:\/\//i.test(path)) {
956
+ path = new URL(path).pathname;
957
+ }
958
+ } catch {
959
+ }
960
+ const q = path.indexOf("?");
961
+ if (q >= 0) path = path.slice(0, q);
962
+ const h = path.indexOf("#");
963
+ if (h >= 0) path = path.slice(0, h);
964
+ if (!path.startsWith("/")) path = `/${path}`;
965
+ if (path.length > 1 && path.endsWith("/")) {
966
+ path = path.replace(/\/+$/, "");
967
+ }
968
+ return path || "/";
969
+ }
970
+
919
971
  // src/page-resource-runtime.ts
920
972
  var pageResourceFields = null;
921
973
  function setPageResourceFields(fields) {
@@ -1009,6 +1061,7 @@ function dedupeLayoutProviderFetch(key, fetchFn) {
1009
1061
  }
1010
1062
 
1011
1063
  // src/index.ts
1064
+ var PAGE_VIEW_HOLD_MS = 1500;
1012
1065
  var DWELL_ACTIVITY_IDLE_MS = 2 * 60 * 1e3;
1013
1066
  var DWELL_POLL_MS = 5e3;
1014
1067
  function readPreviewQueryOverrides() {
@@ -1082,6 +1135,12 @@ var AmplifyUpSDK = class {
1082
1135
  this.resolvedPageResource = null;
1083
1136
  this.resolvedPageRoute = "";
1084
1137
  this.resolvedRouteParams = {};
1138
+ /** Path whose delivery response is in flight; page_view for it is held. */
1139
+ this.pendingResolvePath = null;
1140
+ this.heldPageView = null;
1141
+ this.resolvedPageTaxonomies = null;
1142
+ /** Path the taxonomies above were resolved for. */
1143
+ this.resolvedTaxonomiesPath = null;
1085
1144
  this.historyHooksInstalled = false;
1086
1145
  this.pageEngagementState = {
1087
1146
  reached: /* @__PURE__ */ new Set(),
@@ -1612,8 +1671,10 @@ var AmplifyUpSDK = class {
1612
1671
  * Apply published pageData (from /v1/resolve) so field validation and
1613
1672
  * mapped page fields can run.
1614
1673
  */
1615
- applyResolvedPageData(pageData, pageRoute, routeParams, pageResources) {
1674
+ applyResolvedPageData(pageData, pageRoute, routeParams, pageResources, pageTaxonomies) {
1616
1675
  this.resolvedPageData = pageData || null;
1676
+ this.resolvedPageTaxonomies = pageTaxonomies || null;
1677
+ this.resolvedTaxonomiesPath = this.pendingResolvePath;
1617
1678
  if (pageRoute) this.resolvedPageRoute = pageRoute;
1618
1679
  if (routeParams) this.resolvedRouteParams = routeParams;
1619
1680
  const firstResourceName = pageData?.resources?.[0]?.name;
@@ -1647,6 +1708,28 @@ var AmplifyUpSDK = class {
1647
1708
  getAttachedPageContext() {
1648
1709
  return this.attachedPageContext;
1649
1710
  }
1711
+ /**
1712
+ * The page's delivery response for `path` is on its way. A page_view for the
1713
+ * same path waits for it (up to PAGE_VIEW_HOLD_MS) so it carries the page's
1714
+ * taxonomies.
1715
+ */
1716
+ beginPageResolve(path) {
1717
+ this.pendingResolvePath = normalizeRoute(path);
1718
+ this.resolvedPageTaxonomies = null;
1719
+ this.resolvedTaxonomiesPath = null;
1720
+ }
1721
+ endPageResolve(path) {
1722
+ if (this.pendingResolvePath !== normalizeRoute(path)) return;
1723
+ this.pendingResolvePath = null;
1724
+ this.flushHeldPageView();
1725
+ }
1726
+ flushHeldPageView() {
1727
+ const held = this.heldPageView;
1728
+ if (!held) return;
1729
+ clearTimeout(held.timer);
1730
+ this.heldPageView = null;
1731
+ this.sendPageView(held.url, held.properties);
1732
+ }
1650
1733
  /**
1651
1734
  * Track a page view
1652
1735
  */
@@ -1657,6 +1740,21 @@ var AmplifyUpSDK = class {
1657
1740
  if (!this.isInitialized()) {
1658
1741
  return;
1659
1742
  }
1743
+ this.lastTrackedPath = url;
1744
+ if (this.pendingResolvePath && this.pendingResolvePath === normalizeRoute(url)) {
1745
+ this.flushHeldPageView();
1746
+ this.heldPageView = {
1747
+ url,
1748
+ properties,
1749
+ timer: setTimeout(() => this.flushHeldPageView(), PAGE_VIEW_HOLD_MS)
1750
+ };
1751
+ return;
1752
+ }
1753
+ this.flushHeldPageView();
1754
+ this.sendPageView(url, properties);
1755
+ }
1756
+ sendPageView(url, properties) {
1757
+ const taxonomies = this.resolvedTaxonomiesPath && this.resolvedTaxonomiesPath === normalizeRoute(url) ? this.resolvedPageTaxonomies : null;
1660
1758
  const instanceId = getInstanceId();
1661
1759
  const sessionId = getSessionId();
1662
1760
  const pageProperties = {
@@ -1668,10 +1766,9 @@ var AmplifyUpSDK = class {
1668
1766
  sessionId,
1669
1767
  trackingId: this.config?.trackingId,
1670
1768
  // Timestamp is included in event payload
1671
- ...mergeEventContext(properties || {}, this.attachedPageContext)
1769
+ ...withPageTaxonomies(mergeEventContext(properties || {}, this.attachedPageContext), taxonomies)
1672
1770
  };
1673
1771
  this.adapter.page(pageProperties);
1674
- this.lastTrackedPath = url;
1675
1772
  }
1676
1773
  /**
1677
1774
  * Track an event