@patch-adams/core 1.5.20 → 1.5.22

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/cli.js CHANGED
@@ -1774,8 +1774,8 @@ function generateLrsBridgeCode(options) {
1774
1774
  ', bravaisUserId=' + employeeData.bravaisUserId + ', tenantUrl=' + employeeData.tenantUrl
1775
1775
  : 'NO DATA'));
1776
1776
  if (employeeData && employeeData.email) {
1777
- actor.mbox = 'mailto:' + employeeData.email;
1778
- log('Enhanced actor with email:', employeeData.email);
1777
+ actor.mbox = 'mailto:' + employeeData.email.toLowerCase();
1778
+ log('Enhanced actor with email:', employeeData.email.toLowerCase());
1779
1779
 
1780
1780
  // Also update name if we got a better one
1781
1781
  if (employeeData.name && (!actor.name || actor.name === 'Unknown Learner')) {
@@ -1940,6 +1940,18 @@ function generateLrsBridgeCode(options) {
1940
1940
  return n === 'anonymous learner' || n === 'unknown learner' || n === 'anonymous' || n === 'unknown';
1941
1941
  }
1942
1942
 
1943
+ /**
1944
+ * Normalize actor IFI fields for consistent matching in Bravais Analytics.
1945
+ * Lowercases mbox email (RFC 5321: local-part is case-insensitive in practice).
1946
+ */
1947
+ function normalizeActor(actor) {
1948
+ if (!actor) return actor;
1949
+ if (actor.mbox && actor.mbox.indexOf('mailto:') === 0) {
1950
+ actor.mbox = 'mailto:' + actor.mbox.substring(7).toLowerCase();
1951
+ }
1952
+ return actor;
1953
+ }
1954
+
1943
1955
  /**
1944
1956
  * Persist actor to localStorage for cross-frame sharing.
1945
1957
  * Only stores non-anonymous actors.
@@ -1971,23 +1983,29 @@ function generateLrsBridgeCode(options) {
1971
1983
 
1972
1984
  /**
1973
1985
  * Get the best available actor for statement building.
1974
- * Priority: LRS.actor (if non-anonymous) > localStorage shared actor > LRS.actor > extractActor()
1986
+ * ALWAYS checks localStorage because the skin overlay in another frame
1987
+ * may have updated the actor AFTER this bridge instance initialized.
1988
+ * (e.g., user enters email in skin overlay \u2192 actor persisted to localStorage,
1989
+ * but the bridge in scormcontent/index.html already loaded a stale actor at init)
1975
1990
  */
1976
1991
  function getActor() {
1977
- // If current actor is non-anonymous, use it
1978
- if (LRS.actor && !isAnonymousActor(LRS.actor)) {
1979
- return LRS.actor;
1980
- }
1981
- // Check localStorage for actor set by another frame (e.g., skin overlay)
1992
+ // Always check localStorage for the freshest actor \u2014 it may have been
1993
+ // updated by the skin overlay in another frame since our init
1982
1994
  var shared = loadSharedActor();
1983
1995
  if (shared) {
1984
- // Update local actor so future calls are fast
1985
- LRS.actor = shared;
1986
- log('Actor loaded from cross-frame storage:', shared.name);
1987
- return shared;
1996
+ // Only update if different from current (avoid unnecessary log spam)
1997
+ if (!LRS.actor || LRS.actor.name !== shared.name ||
1998
+ (LRS.actor.account && shared.account && LRS.actor.account.name !== shared.account.name)) {
1999
+ log('Actor updated from cross-frame storage:', shared.name);
2000
+ }
2001
+ LRS.actor = normalizeActor(shared);
2002
+ return LRS.actor;
1988
2003
  }
1989
2004
  // Fallback to current actor or re-extract
1990
- return LRS.actor || extractActor();
2005
+ if (LRS.actor && !isAnonymousActor(LRS.actor)) {
2006
+ return normalizeActor(LRS.actor);
2007
+ }
2008
+ return normalizeActor(LRS.actor || extractActor());
1991
2009
  }
1992
2010
 
1993
2011
  /**
@@ -1997,7 +2015,9 @@ function generateLrsBridgeCode(options) {
1997
2015
  LRS.setActor = function(actor) {
1998
2016
  LRS.actor = actor;
1999
2017
  persistActor(actor);
2000
- // Also try to propagate to other frames in the hierarchy
2018
+
2019
+ // Propagate to ALL frames: walk UP parent chain AND DOWN into child iframes
2020
+ // UP: parent frames (e.g., if skin is in a child iframe)
2001
2021
  try {
2002
2022
  var w = window;
2003
2023
  for (var i = 0; i < 10; i++) {
@@ -2010,9 +2030,29 @@ function generateLrsBridgeCode(options) {
2010
2030
  w = w.parent;
2011
2031
  }
2012
2032
  } catch (e) {}
2033
+
2034
+ // DOWN: child iframes (e.g., scormcontent/index.html has its own bridge)
2035
+ function setActorInChildren(win) {
2036
+ try {
2037
+ var frames = win.frames;
2038
+ for (var j = 0; j < frames.length; j++) {
2039
+ try {
2040
+ if (frames[j].pa_patcher && frames[j].pa_patcher.lrs) {
2041
+ frames[j].pa_patcher.lrs.actor = actor;
2042
+ log('Actor propagated to child frame', j);
2043
+ }
2044
+ // Recurse into nested iframes
2045
+ setActorInChildren(frames[j]);
2046
+ } catch (e) { /* cross-origin child */ }
2047
+ }
2048
+ } catch (e) {}
2049
+ }
2050
+ setActorInChildren(window);
2051
+
2013
2052
  if (window.console && window.console.info) {
2014
2053
  console.info('[PA-LRS] Actor set:', actor.name,
2015
2054
  actor.mbox ? '(' + actor.mbox + ')' : '',
2055
+ actor.account ? '(account: ' + actor.account.name + ')' : '',
2016
2056
  '\u2014 shared across frames');
2017
2057
  }
2018
2058
  };
@@ -2027,9 +2067,9 @@ function generateLrsBridgeCode(options) {
2027
2067
  function finalizeActor(actor) {
2028
2068
  // Try to enhance actor with email if missing
2029
2069
  enhanceActorWithEmail(actor, function(enhancedActor) {
2030
- LRS.actor = enhancedActor;
2031
- persistActor(enhancedActor);
2032
- callback(enhancedActor);
2070
+ LRS.actor = normalizeActor(enhancedActor);
2071
+ persistActor(LRS.actor);
2072
+ callback(LRS.actor);
2033
2073
  });
2034
2074
  }
2035
2075