@namiml/sdk-core 3.4.12-dev.202610062108 → 3.4.12-dev.202610081956

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.cjs CHANGED
@@ -106,7 +106,7 @@ const {
106
106
  // version — stamped by scripts/version.sh
107
107
  NAMI_SDK_VERSION: exports.NAMI_SDK_VERSION = "3.4.12",
108
108
  // full package version including dev suffix — stamped by scripts/version.sh
109
- NAMI_SDK_PACKAGE_VERSION: exports.NAMI_SDK_PACKAGE_VERSION = "3.4.12-dev.202610062108",
109
+ NAMI_SDK_PACKAGE_VERSION: exports.NAMI_SDK_PACKAGE_VERSION = "3.4.12-dev.202610081956",
110
110
  // environments
111
111
  PRODUCTION: exports.PRODUCTION = "production", DEVELOPMENT: exports.DEVELOPMENT = "development",
112
112
  // error messages
@@ -65607,8 +65607,32 @@ class NamiFlow extends BasicNamiFlow {
65607
65607
  this.purchasedSku = normalizePurchasedSku(data.sku);
65608
65608
  }
65609
65609
  }
65610
- triggerActions(actionId, component, data) {
65610
+ /**
65611
+ * True when a tap belongs to a screen the flow has already left.
65612
+ *
65613
+ * A button is dispatched by the screen that rendered it, but {@link lifecycles} resolves
65614
+ * against whatever step is current when the tap is PROCESSED. A screen that advances itself
65615
+ * — `__appear__` authoring `after: flowNav` — moves the step out from under an in-flight tap,
65616
+ * so the outgoing screen's button would run the INCOMING step's actions for the same button
65617
+ * id. Observed live on NFL Vizio: "skip intro" on the Welcome screen ran the next screen's
65618
+ * `flowExit` instead of its own `flowNav`, and the analytics it emitted carried the old
65619
+ * button's `{{ buttonText }}` against the new screen's `{{ pageId }}` (NAM-4395).
65620
+ *
65621
+ * Only drops when BOTH ids are known and differ: a caller that supplies no screen id, or a
65622
+ * step with no screen of its own (entry/branch/exit), keeps the previous behaviour.
65623
+ */
65624
+ isStaleTap(actionId, screenId) {
65625
+ const currentScreen = this.currentFlowStep?.screen;
65626
+ if (!screenId || !currentScreen || screenId === currentScreen)
65627
+ return false;
65628
+ this.flowLog(`dropping stale tap ${actionId} from screen ${screenId} — the flow is on ${currentScreen} (NAM-4395)`);
65629
+ logger.info(`Ignoring "${actionId}" from a screen the flow has already left (${screenId} -> ${currentScreen})`);
65630
+ return true;
65631
+ }
65632
+ triggerActions(actionId, component, data, screenId) {
65611
65633
  this.captureBuySkuData(actionId, data);
65634
+ if (this.isStaleTap(actionId, screenId))
65635
+ return;
65612
65636
  const lifecycles = this.lifecycles(actionId);
65613
65637
  if (!lifecycles)
65614
65638
  return;
@@ -65639,8 +65663,10 @@ class NamiFlow extends BasicNamiFlow {
65639
65663
  }));
65640
65664
  }
65641
65665
  }
65642
- triggerBeforeActions(actionId, component, data) {
65666
+ triggerBeforeActions(actionId, component, data, screenId) {
65643
65667
  this.captureBuySkuData(actionId, data);
65668
+ if (this.isStaleTap(actionId, screenId))
65669
+ return;
65644
65670
  const lifecycles = this.lifecycles(actionId);
65645
65671
  if (!lifecycles)
65646
65672
  return;
@@ -65649,8 +65675,10 @@ class NamiFlow extends BasicNamiFlow {
65649
65675
  cycle.before?.forEach((action) => this.shouldRun(action) && this.performAction(action, data));
65650
65676
  }
65651
65677
  }
65652
- triggerAfterActions(actionId, component, data) {
65678
+ triggerAfterActions(actionId, component, data, screenId) {
65653
65679
  this.captureBuySkuData(actionId, data);
65680
+ if (this.isStaleTap(actionId, screenId))
65681
+ return;
65654
65682
  const lifecycles = this.lifecycles(actionId);
65655
65683
  if (!lifecycles)
65656
65684
  return;
package/dist/index.d.ts CHANGED
@@ -2452,10 +2452,25 @@ declare class NamiFlow extends BasicNamiFlow {
2452
2452
  * has no `__buy_sku__` lifecycles of its own.
2453
2453
  */
2454
2454
  private captureBuySkuData;
2455
- triggerActions(actionId: string, component?: any, data?: Record<string, any>): void;
2455
+ /**
2456
+ * True when a tap belongs to a screen the flow has already left.
2457
+ *
2458
+ * A button is dispatched by the screen that rendered it, but {@link lifecycles} resolves
2459
+ * against whatever step is current when the tap is PROCESSED. A screen that advances itself
2460
+ * — `__appear__` authoring `after: flowNav` — moves the step out from under an in-flight tap,
2461
+ * so the outgoing screen's button would run the INCOMING step's actions for the same button
2462
+ * id. Observed live on NFL Vizio: "skip intro" on the Welcome screen ran the next screen's
2463
+ * `flowExit` instead of its own `flowNav`, and the analytics it emitted carried the old
2464
+ * button's `{{ buttonText }}` against the new screen's `{{ pageId }}` (NAM-4395).
2465
+ *
2466
+ * Only drops when BOTH ids are known and differ: a caller that supplies no screen id, or a
2467
+ * step with no screen of its own (entry/branch/exit), keeps the previous behaviour.
2468
+ */
2469
+ isStaleTap(actionId: string, screenId?: string): boolean;
2470
+ triggerActions(actionId: string, component?: any, data?: Record<string, any>, screenId?: string): void;
2456
2471
  executeFullLifecycles(lifecycles: NamiFlowOn[], data?: Record<string, any>): void;
2457
- triggerBeforeActions(actionId: string, component?: any, data?: Record<string, any>): void;
2458
- triggerAfterActions(actionId: string, component?: any, data?: Record<string, any>): void;
2472
+ triggerBeforeActions(actionId: string, component?: any, data?: Record<string, any>, screenId?: string): void;
2473
+ triggerAfterActions(actionId: string, component?: any, data?: Record<string, any>, screenId?: string): void;
2459
2474
  currentStepHasHoistedPrimaryActions(actionId: string): boolean;
2460
2475
  private shouldRun;
2461
2476
  private performAction;
package/dist/index.mjs CHANGED
@@ -104,7 +104,7 @@ const {
104
104
  // version — stamped by scripts/version.sh
105
105
  NAMI_SDK_VERSION = "3.4.12",
106
106
  // full package version including dev suffix — stamped by scripts/version.sh
107
- NAMI_SDK_PACKAGE_VERSION = "3.4.12-dev.202610062108",
107
+ NAMI_SDK_PACKAGE_VERSION = "3.4.12-dev.202610081956",
108
108
  // environments
109
109
  PRODUCTION = "production", DEVELOPMENT = "development",
110
110
  // error messages
@@ -65605,8 +65605,32 @@ class NamiFlow extends BasicNamiFlow {
65605
65605
  this.purchasedSku = normalizePurchasedSku(data.sku);
65606
65606
  }
65607
65607
  }
65608
- triggerActions(actionId, component, data) {
65608
+ /**
65609
+ * True when a tap belongs to a screen the flow has already left.
65610
+ *
65611
+ * A button is dispatched by the screen that rendered it, but {@link lifecycles} resolves
65612
+ * against whatever step is current when the tap is PROCESSED. A screen that advances itself
65613
+ * — `__appear__` authoring `after: flowNav` — moves the step out from under an in-flight tap,
65614
+ * so the outgoing screen's button would run the INCOMING step's actions for the same button
65615
+ * id. Observed live on NFL Vizio: "skip intro" on the Welcome screen ran the next screen's
65616
+ * `flowExit` instead of its own `flowNav`, and the analytics it emitted carried the old
65617
+ * button's `{{ buttonText }}` against the new screen's `{{ pageId }}` (NAM-4395).
65618
+ *
65619
+ * Only drops when BOTH ids are known and differ: a caller that supplies no screen id, or a
65620
+ * step with no screen of its own (entry/branch/exit), keeps the previous behaviour.
65621
+ */
65622
+ isStaleTap(actionId, screenId) {
65623
+ const currentScreen = this.currentFlowStep?.screen;
65624
+ if (!screenId || !currentScreen || screenId === currentScreen)
65625
+ return false;
65626
+ this.flowLog(`dropping stale tap ${actionId} from screen ${screenId} — the flow is on ${currentScreen} (NAM-4395)`);
65627
+ logger.info(`Ignoring "${actionId}" from a screen the flow has already left (${screenId} -> ${currentScreen})`);
65628
+ return true;
65629
+ }
65630
+ triggerActions(actionId, component, data, screenId) {
65609
65631
  this.captureBuySkuData(actionId, data);
65632
+ if (this.isStaleTap(actionId, screenId))
65633
+ return;
65610
65634
  const lifecycles = this.lifecycles(actionId);
65611
65635
  if (!lifecycles)
65612
65636
  return;
@@ -65637,8 +65661,10 @@ class NamiFlow extends BasicNamiFlow {
65637
65661
  }));
65638
65662
  }
65639
65663
  }
65640
- triggerBeforeActions(actionId, component, data) {
65664
+ triggerBeforeActions(actionId, component, data, screenId) {
65641
65665
  this.captureBuySkuData(actionId, data);
65666
+ if (this.isStaleTap(actionId, screenId))
65667
+ return;
65642
65668
  const lifecycles = this.lifecycles(actionId);
65643
65669
  if (!lifecycles)
65644
65670
  return;
@@ -65647,8 +65673,10 @@ class NamiFlow extends BasicNamiFlow {
65647
65673
  cycle.before?.forEach((action) => this.shouldRun(action) && this.performAction(action, data));
65648
65674
  }
65649
65675
  }
65650
- triggerAfterActions(actionId, component, data) {
65676
+ triggerAfterActions(actionId, component, data, screenId) {
65651
65677
  this.captureBuySkuData(actionId, data);
65678
+ if (this.isStaleTap(actionId, screenId))
65679
+ return;
65652
65680
  const lifecycles = this.lifecycles(actionId);
65653
65681
  if (!lifecycles)
65654
65682
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@namiml/sdk-core",
3
- "version": "3.4.12-dev.202610062108",
3
+ "version": "3.4.12-dev.202610081956",
4
4
  "description": "Platform-agnostic core for the Nami SDK — business logic, API, types, and state management",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",