@amplifyup/sdk 0.1.0 → 0.1.2

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,3 +1,4 @@
1
+ 'use client';
1
2
  import { createContext, useState, useEffect, useContext } from 'react';
2
3
  import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
3
4
 
@@ -176,6 +177,16 @@ var AWSAdapter = class {
176
177
  // src/storage.ts
177
178
  var INSTANCE_ID_KEY = "amplifyup_instance_id";
178
179
  var USER_ID_KEY = "amplifyup_user_id";
180
+ function generateGuid() {
181
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
182
+ return crypto.randomUUID();
183
+ }
184
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
185
+ const r = Math.random() * 16 | 0;
186
+ const v = c === "x" ? r : r & 3 | 8;
187
+ return v.toString(16);
188
+ });
189
+ }
179
190
  function getInstanceId() {
180
191
  if (typeof window === "undefined") {
181
192
  return "";
@@ -184,7 +195,7 @@ function getInstanceId() {
184
195
  if (stored) {
185
196
  return stored;
186
197
  }
187
- const instanceId = `anon_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
198
+ const instanceId = `browser_${generateGuid()}`;
188
199
  localStorage.setItem(INSTANCE_ID_KEY, instanceId);
189
200
  return instanceId;
190
201
  }
@@ -208,9 +219,69 @@ function clearIds() {
208
219
  localStorage.removeItem(USER_ID_KEY);
209
220
  }
210
221
 
222
+ // src/targets.ts
223
+ var AWS_DEV_API = "https://api-dev.amplifyup.ai";
224
+ var AWS_PROD_API = "https://api.amplifyup.ai";
225
+ var PROD_ORCHESTRATOR = "https://amplifyup.ai";
226
+ function isAmplifyUpTarget(value) {
227
+ return value === "local" || value === "dev" || value === "production";
228
+ }
229
+ function normalizeAmplifyUpTarget(value) {
230
+ return value === "dev" ? "local" : value;
231
+ }
232
+ function resolveAmplifyUpTarget(options) {
233
+ if (options?.configTarget && isAmplifyUpTarget(options.configTarget)) {
234
+ return normalizeAmplifyUpTarget(options.configTarget);
235
+ }
236
+ if (options?.configDev === true) {
237
+ return "local";
238
+ }
239
+ const envTarget = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_AMPLIFYUP_TARGET : void 0;
240
+ if (isAmplifyUpTarget(envTarget)) {
241
+ return normalizeAmplifyUpTarget(envTarget);
242
+ }
243
+ if (typeof window !== "undefined") {
244
+ const host = window.location.hostname;
245
+ if (host === "localhost" || host === "127.0.0.1") {
246
+ return "local";
247
+ }
248
+ }
249
+ return "production";
250
+ }
251
+ function localOrchestratorUrl() {
252
+ const fromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_ORCHESTRATOR_URL : void 0;
253
+ return (fromEnv || "http://localhost:5001").replace(/\/$/, "");
254
+ }
255
+ function localAwsApiUrl() {
256
+ const fromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_AMPLIFYUP_API_URL : void 0;
257
+ return (fromEnv || AWS_DEV_API).replace(/\/$/, "");
258
+ }
259
+ function resolveAmplifyUpUrls(target) {
260
+ if (target === "local") {
261
+ const orchestratorUrl2 = localOrchestratorUrl();
262
+ const apiGatewayUrl = localAwsApiUrl();
263
+ return {
264
+ target: "local",
265
+ // Layouts / site config / composer APIs → local orchestrator + Neon
266
+ orchestratorUrl: orchestratorUrl2,
267
+ // Events + personalize → AWS development stack
268
+ apiGatewayUrl,
269
+ decisionApiUrl: `${apiGatewayUrl}/v1/personalize`
270
+ };
271
+ }
272
+ const resolvedApi = typeof process !== "undefined" && process.env.NEXT_PUBLIC_AMPLIFYUP_API_URL?.replace(/\/$/, "") || AWS_PROD_API;
273
+ const orchestratorFromEnv = typeof process !== "undefined" ? process.env.NEXT_PUBLIC_ORCHESTRATOR_URL : void 0;
274
+ const isLocalOrchestrator = !!orchestratorFromEnv && (orchestratorFromEnv.includes("localhost") || orchestratorFromEnv.includes("127.0.0.1"));
275
+ const orchestratorUrl = isLocalOrchestrator || !orchestratorFromEnv ? PROD_ORCHESTRATOR : orchestratorFromEnv.replace(/\/$/, "");
276
+ return {
277
+ target: "production",
278
+ apiGatewayUrl: resolvedApi,
279
+ orchestratorUrl,
280
+ decisionApiUrl: `${resolvedApi}/v1/personalize`
281
+ };
282
+ }
283
+
211
284
  // src/index.ts
212
- var PROD_API_URL = "https://api.amplifyup.ai" ;
213
- var PROD_ORCHESTRATOR_URL = "https://amplifyup.ai" ;
214
285
  var AmplifyUpSDK = class {
215
286
  constructor(adapter) {
216
287
  this.config = null;
@@ -218,7 +289,12 @@ var AmplifyUpSDK = class {
218
289
  this.apiGatewayUrl = "";
219
290
  this.orchestratorUrl = "";
220
291
  this.decisionApiUrl = "";
292
+ this.target = "local";
221
293
  this.initialized = false;
294
+ /** Prevents overlapping init() from React Strict Mode double-mount */
295
+ this.initPromise = null;
296
+ /** Ensures auto page() on init fires once per page load */
297
+ this.initialPageSent = false;
222
298
  this.highlightingEnabled = false;
223
299
  this.componentRegistry = [];
224
300
  this.messageListener = null;
@@ -301,46 +377,41 @@ var AmplifyUpSDK = class {
301
377
  }
302
378
  return false;
303
379
  }
304
- /**
305
- * Get production URLs
306
- *
307
- * URLs are baked in at build time via tsup.config.ts
308
- *
309
- * API Gateway endpoints:
310
- * - /v1/track - Event tracking (ingestion)
311
- * - /v1/page - Page view tracking (ingestion)
312
- * - /v1/personalize - Decision engine (personalization)
313
- */
314
- getProductionUrls() {
315
- return {
316
- apiGatewayUrl: PROD_API_URL,
317
- orchestratorUrl: PROD_ORCHESTRATOR_URL,
318
- decisionApiUrl: `${PROD_API_URL}/v1/personalize`
319
- };
320
- }
321
380
  /**
322
381
  * Initialize the SDK
323
- * Automatically reads env vars and sets up tracking
382
+ * Resolves local | dev | production targets for ingestion + personalization URLs.
324
383
  */
325
384
  async init(config) {
385
+ if (this.initialized && this.adapter?.isInitialized()) {
386
+ return;
387
+ }
388
+ if (this.initPromise) {
389
+ return this.initPromise;
390
+ }
391
+ this.initPromise = this.performInit(config);
392
+ try {
393
+ await this.initPromise;
394
+ } finally {
395
+ this.initPromise = null;
396
+ }
397
+ }
398
+ async performInit(config) {
326
399
  if (!this.adapter) {
327
400
  this.adapter = new AWSAdapter();
328
401
  }
329
- const isLocalhost = typeof window !== "undefined" && (window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1");
330
- if (isLocalhost || config.dev === true) {
331
- this.apiGatewayUrl = "http://localhost:5001/api";
332
- this.orchestratorUrl = "http://localhost:5001";
333
- this.decisionApiUrl = "http://localhost:5001/api/v1/personalize";
334
- } else {
335
- const urls = this.getProductionUrls();
336
- this.apiGatewayUrl = urls.apiGatewayUrl;
337
- this.orchestratorUrl = urls.orchestratorUrl;
338
- this.decisionApiUrl = urls.decisionApiUrl;
339
- }
402
+ this.target = resolveAmplifyUpTarget({
403
+ configTarget: config.target,
404
+ configDev: config.dev
405
+ });
406
+ const urls = resolveAmplifyUpUrls(this.target);
407
+ this.apiGatewayUrl = urls.apiGatewayUrl;
408
+ this.orchestratorUrl = urls.orchestratorUrl;
409
+ this.decisionApiUrl = urls.decisionApiUrl;
340
410
  this.config = {
341
411
  trackingId: config.trackingId,
342
412
  debug: config.debug ?? true,
343
413
  // Enable debug by default
414
+ target: this.target,
344
415
  dev: config.dev
345
416
  };
346
417
  try {
@@ -357,6 +428,7 @@ var AmplifyUpSDK = class {
357
428
  getInstanceId: () => this.getInstanceId(),
358
429
  getUserId: () => this.getUserId(),
359
430
  getTrackingId: () => this.getTrackingId(),
431
+ getTarget: () => this.getTarget(),
360
432
  getDiagnostics: () => this.getDiagnostics(),
361
433
  getStatus: () => {
362
434
  console.log(this.getStatus());
@@ -377,7 +449,7 @@ var AmplifyUpSDK = class {
377
449
  };
378
450
  if (this.config?.debug) {
379
451
  console.log("AmplifyUp SDK: Diagnostic methods available on window.AmplifyUp");
380
- console.log("Try: AmplifyUp.getStatus() or AmplifyUp.verifyAWSConnection()");
452
+ console.log("Try: AmplifyUp.getStatus() or AmplifyUp.testTracking()");
381
453
  }
382
454
  }
383
455
  this.clearTrackingIntervals();
@@ -389,11 +461,20 @@ var AmplifyUpSDK = class {
389
461
  if (this.isPreviewMode()) {
390
462
  return;
391
463
  }
392
- const url = window.location.pathname;
393
- this.page(url);
464
+ if (!this.initialPageSent) {
465
+ this.initialPageSent = true;
466
+ const url = window.location.pathname;
467
+ this.page(url);
468
+ }
394
469
  }
395
470
  if (this.config?.debug && this.initialized) {
396
- console.log("AmplifyUp SDK: Initialized successfully", { trackingId: config.trackingId });
471
+ console.log("AmplifyUp SDK: Initialized successfully", {
472
+ trackingId: config.trackingId,
473
+ target: this.target,
474
+ apiGatewayUrl: this.apiGatewayUrl,
475
+ orchestratorUrl: this.orchestratorUrl,
476
+ decisionApiUrl: this.decisionApiUrl || "(orchestrator fallback)"
477
+ });
397
478
  }
398
479
  } catch (error) {
399
480
  console.error("AmplifyUp SDK: Initialization failed", error);
@@ -594,6 +675,7 @@ var AmplifyUpSDK = class {
594
675
  instanceId,
595
676
  userId,
596
677
  trackingId: this.config?.trackingId,
678
+ target: this.target,
597
679
  config: {
598
680
  apiGatewayUrl: this.apiGatewayUrl,
599
681
  decisionApiUrl: this.decisionApiUrl,
@@ -602,6 +684,9 @@ var AmplifyUpSDK = class {
602
684
  }
603
685
  };
604
686
  }
687
+ getTarget() {
688
+ return this.target;
689
+ }
605
690
  /**
606
691
  * Test tracking by sending a test event
607
692
  */
@@ -659,6 +744,7 @@ var AmplifyUpSDK = class {
659
744
  AmplifyUp SDK Status:
660
745
  \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501
661
746
  Initialized: ${diag.initialized ? "\u2705 Yes" : "\u274C No"}
747
+ Target: ${diag.target}
662
748
  Instance ID: ${diag.instanceId}
663
749
  User ID: ${diag.userId || "Not identified"}
664
750
  Tracking ID: ${diag.trackingId || "Not set"}
@@ -670,11 +756,11 @@ Config:
670
756
  API Gateway: ${this.apiGatewayUrl || "Not set (required)"}
671
757
  Decision API: ${this.decisionApiUrl || "Not set (using Orchestrator fallback)"}
672
758
  Orchestrator: ${this.orchestratorUrl || "Not set"}
673
- Debug: ${diag.config.debug ? "Enabled" : "Disabled"}
674
759
 
675
760
  Available Console Commands:
676
761
  AmplifyUp.getStatus() - Show this status
677
762
  AmplifyUp.getDiagnostics() - Get full diagnostic object
763
+ AmplifyUp.getTarget() - Current environment target
678
764
  AmplifyUp.getInstanceId() - Get instance ID (browser/session ID)
679
765
  AmplifyUp.getUserId() - Get user ID if identified
680
766
  AmplifyUp.testTracking() - Send a test event
@@ -1683,19 +1769,31 @@ function AmplifyRenderer({
1683
1769
  }
1684
1770
 
1685
1771
  // src/server.tsx
1686
- async function fetchPageConfigServer(route, trackingId, preview = false) {
1687
- const sdk = getSDK();
1688
- const orchestratorUrl = typeof process !== "undefined" && process.env.NEXT_PUBLIC_ORCHESTRATOR_URL || "http://localhost:5001";
1689
- const originalConfig = sdk.config;
1690
- sdk.config = {
1691
- trackingId,
1692
- orchestratorUrl
1693
- };
1772
+ async function fetchPageConfigServer(route, trackingId, preview = false, options) {
1773
+ const target = resolveAmplifyUpTarget({
1774
+ configTarget: options?.target
1775
+ });
1776
+ const { orchestratorUrl } = resolveAmplifyUpUrls(target);
1777
+ const params = new URLSearchParams({
1778
+ route,
1779
+ trackingId
1780
+ });
1781
+ if (preview) {
1782
+ params.set("preview", "true");
1783
+ }
1784
+ const url = `${orchestratorUrl}/api/layout/provider?${params.toString()}`;
1694
1785
  try {
1695
- const page = await sdk.fetchPageConfig(route, preview);
1696
- return page;
1697
- } finally {
1698
- sdk.config = originalConfig;
1786
+ const res = await fetch(url, {
1787
+ cache: "no-store",
1788
+ headers: { Accept: "application/json" }
1789
+ });
1790
+ if (!res.ok) {
1791
+ return null;
1792
+ }
1793
+ const data = await res.json();
1794
+ return data.page || null;
1795
+ } catch {
1796
+ return null;
1699
1797
  }
1700
1798
  }
1701
1799
  var ComponentContext = createContext(null);
@@ -1883,14 +1981,21 @@ function AmplifyUpProvider({ children, config }) {
1883
1981
  }
1884
1982
  }, [nextPathname]);
1885
1983
  useEffect(() => {
1984
+ let cancelled = false;
1886
1985
  const sdk = getSDK();
1887
1986
  sdk.init(config).then(() => {
1888
- setInitialized(true);
1987
+ if (!cancelled) {
1988
+ setInitialized(true);
1989
+ }
1889
1990
  }).catch((err) => {
1991
+ if (cancelled) return;
1890
1992
  console.error("Failed to initialize AmplifyUp SDK:", err);
1891
1993
  setError("Failed to initialize tracking");
1892
1994
  setLoading(false);
1893
1995
  });
1996
+ return () => {
1997
+ cancelled = true;
1998
+ };
1894
1999
  }, []);
1895
2000
  useEffect(() => {
1896
2001
  if (!initialized) return;