@patch-adams/core 1.5.21 → 1.5.23

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
@@ -458,7 +458,9 @@ var PatchAdamsConfigSchema = z.object({
458
458
  /** Plugin configurations - each plugin is keyed by its name */
459
459
  plugins: PluginsConfigSchema,
460
460
  /** Optional skin name — adds 'pa-skinned' + skin class to <html>, loads skin CSS/JS after core files */
461
- skin: z.string().min(1).optional()
461
+ skin: z.string().min(1).optional(),
462
+ /** URL for server-controlled asset cache version (e.g., https://api.example.com/create/skin/version) */
463
+ assetVersionUrl: z.string().url().optional()
462
464
  });
463
465
 
464
466
  // src/config/defaults.ts
@@ -602,7 +604,8 @@ html.${htmlClass}.${loadingClass} body {
602
604
  <script data-pa="css-before-loader">
603
605
  (function() {
604
606
  'use strict';
605
- var REMOTE_URL = "${remoteUrl}";
607
+ var v = window.__pa_v || '';
608
+ var REMOTE_URL = "${remoteUrl}" + (v ? "?v=" + v : "");
606
609
  var LOCAL_PATH = "${localPath}";
607
610
 
608
611
  function loadCSSSync(url) {
@@ -645,7 +648,7 @@ function generateCssAfterLoader(options) {
645
648
  <script data-pa="css-after-loader">
646
649
  (function() {
647
650
  'use strict';
648
- var REMOTE_URL = "${remoteUrl}";
651
+ var REMOTE_URL = "${remoteUrl}" + (window.__pa_v ? "?v=" + window.__pa_v : "");
649
652
  var LOCAL_PATH = "${localPath}";
650
653
  var TIMEOUT = ${timeout};
651
654
 
@@ -1774,8 +1777,8 @@ function generateLrsBridgeCode(options) {
1774
1777
  ', bravaisUserId=' + employeeData.bravaisUserId + ', tenantUrl=' + employeeData.tenantUrl
1775
1778
  : 'NO DATA'));
1776
1779
  if (employeeData && employeeData.email) {
1777
- actor.mbox = 'mailto:' + employeeData.email;
1778
- log('Enhanced actor with email:', employeeData.email);
1780
+ actor.mbox = 'mailto:' + employeeData.email.toLowerCase();
1781
+ log('Enhanced actor with email:', employeeData.email.toLowerCase());
1779
1782
 
1780
1783
  // Also update name if we got a better one
1781
1784
  if (employeeData.name && (!actor.name || actor.name === 'Unknown Learner')) {
@@ -1940,6 +1943,18 @@ function generateLrsBridgeCode(options) {
1940
1943
  return n === 'anonymous learner' || n === 'unknown learner' || n === 'anonymous' || n === 'unknown';
1941
1944
  }
1942
1945
 
1946
+ /**
1947
+ * Normalize actor IFI fields for consistent matching in Bravais Analytics.
1948
+ * Lowercases mbox email (RFC 5321: local-part is case-insensitive in practice).
1949
+ */
1950
+ function normalizeActor(actor) {
1951
+ if (!actor) return actor;
1952
+ if (actor.mbox && actor.mbox.indexOf('mailto:') === 0) {
1953
+ actor.mbox = 'mailto:' + actor.mbox.substring(7).toLowerCase();
1954
+ }
1955
+ return actor;
1956
+ }
1957
+
1943
1958
  /**
1944
1959
  * Persist actor to localStorage for cross-frame sharing.
1945
1960
  * Only stores non-anonymous actors.
@@ -1986,14 +2001,14 @@ function generateLrsBridgeCode(options) {
1986
2001
  (LRS.actor.account && shared.account && LRS.actor.account.name !== shared.account.name)) {
1987
2002
  log('Actor updated from cross-frame storage:', shared.name);
1988
2003
  }
1989
- LRS.actor = shared;
1990
- return shared;
2004
+ LRS.actor = normalizeActor(shared);
2005
+ return LRS.actor;
1991
2006
  }
1992
2007
  // Fallback to current actor or re-extract
1993
2008
  if (LRS.actor && !isAnonymousActor(LRS.actor)) {
1994
- return LRS.actor;
2009
+ return normalizeActor(LRS.actor);
1995
2010
  }
1996
- return LRS.actor || extractActor();
2011
+ return normalizeActor(LRS.actor || extractActor());
1997
2012
  }
1998
2013
 
1999
2014
  /**
@@ -2055,9 +2070,9 @@ function generateLrsBridgeCode(options) {
2055
2070
  function finalizeActor(actor) {
2056
2071
  // Try to enhance actor with email if missing
2057
2072
  enhanceActorWithEmail(actor, function(enhancedActor) {
2058
- LRS.actor = enhancedActor;
2059
- persistActor(enhancedActor);
2060
- callback(enhancedActor);
2073
+ LRS.actor = normalizeActor(enhancedActor);
2074
+ persistActor(LRS.actor);
2075
+ callback(LRS.actor);
2061
2076
  });
2062
2077
  }
2063
2078
 
@@ -5512,7 +5527,7 @@ function escapeJs(str) {
5512
5527
  return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r");
5513
5528
  }
5514
5529
  function generateJsBeforeLoader(options) {
5515
- const { remoteUrl, localPath, htmlClass, loadingClass, metadata, lrsBridge, skin } = options;
5530
+ const { remoteUrl, localPath, htmlClass, loadingClass, metadata, lrsBridge, skin, assetVersionUrl } = options;
5516
5531
  const lrsBridgeCode = generateLrsBridgeCode(lrsBridge);
5517
5532
  const courseLines = [];
5518
5533
  if (metadata) {
@@ -5615,7 +5630,22 @@ window.pa_patcher = window.pa_patcher || {
5615
5630
 
5616
5631
  (function() {
5617
5632
  'use strict';
5618
- var REMOTE_URL = "${remoteUrl}";
5633
+ // Fetch server-controlled cache version (sync, once)
5634
+ var ASSET_VERSION_URL = "${assetVersionUrl || ""}";
5635
+ window.__pa_v = '';
5636
+ if (ASSET_VERSION_URL) {
5637
+ try {
5638
+ var xhr = new XMLHttpRequest();
5639
+ xhr.open('GET', ASSET_VERSION_URL, false);
5640
+ xhr.timeout = 2000;
5641
+ xhr.send();
5642
+ if (xhr.status === 200) {
5643
+ window.__pa_v = JSON.parse(xhr.responseText).v || '1';
5644
+ }
5645
+ } catch(e) { window.__pa_v = '1'; }
5646
+ }
5647
+
5648
+ var REMOTE_URL = "${remoteUrl}" + (window.__pa_v ? "?v=" + window.__pa_v : "");
5619
5649
  var LOCAL_PATH = "${localPath}";
5620
5650
 
5621
5651
  function loadJSSync(url) {
@@ -5684,7 +5714,8 @@ function buildJsBeforeOptions(config, metadata) {
5684
5714
  loadingClass: config.loadingClass,
5685
5715
  metadata: metadata ?? null,
5686
5716
  lrsBridge,
5687
- skin: config.skin
5717
+ skin: config.skin,
5718
+ assetVersionUrl: config.assetVersionUrl
5688
5719
  };
5689
5720
  }
5690
5721
 
@@ -5695,7 +5726,7 @@ function generateJsAfterLoader(options) {
5695
5726
  <script data-pa="js-after-loader">
5696
5727
  (function() {
5697
5728
  'use strict';
5698
- var REMOTE_URL = "${remoteUrl}";
5729
+ var REMOTE_URL = "${remoteUrl}" + (window.__pa_v ? "?v=" + window.__pa_v : "");
5699
5730
  var LOCAL_PATH = "${localPath}";
5700
5731
  var TIMEOUT = ${timeout};
5701
5732
  var LOADING_CLASS = "${loadingClass}";
@@ -5805,7 +5836,7 @@ function generateSkinCssLoader(options) {
5805
5836
  <script data-pa="skin-css-loader">
5806
5837
  (function() {
5807
5838
  'use strict';
5808
- var REMOTE_URL = "${remoteUrl}";
5839
+ var REMOTE_URL = "${remoteUrl}" + (window.__pa_v ? "?v=" + window.__pa_v : "?v=" + Date.now().toString(36));
5809
5840
  var LOCAL_PATH = "${localPath}";
5810
5841
  var TIMEOUT = ${timeout};
5811
5842
 
@@ -5879,9 +5910,8 @@ function generateSkinCssLoader(options) {
5879
5910
  }
5880
5911
  function buildSkinCssOptions(config) {
5881
5912
  if (!config.skin) return null;
5882
- const cacheBuster = Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
5883
5913
  return {
5884
- remoteUrl: `${config.remoteDomain}/skin/${config.skin}/style.css?v=${cacheBuster}`,
5914
+ remoteUrl: `${config.remoteDomain}/skin/${config.skin}/style.css`,
5885
5915
  localPath: `skin/${config.skin}/style.css`,
5886
5916
  timeout: config.cssAfter.timeout
5887
5917
  // reuse cssAfter timeout
@@ -5895,7 +5925,7 @@ function generateSkinJsLoader(options) {
5895
5925
  <script data-pa="skin-js-loader">
5896
5926
  (function() {
5897
5927
  'use strict';
5898
- var REMOTE_URL = "${remoteUrl}";
5928
+ var REMOTE_URL = "${remoteUrl}" + (window.__pa_v ? "?v=" + window.__pa_v : "?v=" + Date.now().toString(36));
5899
5929
  var LOCAL_PATH = "${localPath}";
5900
5930
  var TIMEOUT = ${timeout};
5901
5931
 
@@ -5981,9 +6011,8 @@ function generateSkinJsLoader(options) {
5981
6011
  }
5982
6012
  function buildSkinJsOptions(config) {
5983
6013
  if (!config.skin) return null;
5984
- const cacheBuster = Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
5985
6014
  return {
5986
- remoteUrl: `${config.remoteDomain}/skin/${config.skin}/script.js?v=${cacheBuster}`,
6015
+ remoteUrl: `${config.remoteDomain}/skin/${config.skin}/script.js`,
5987
6016
  localPath: `skin/${config.skin}/script.js`,
5988
6017
  timeout: config.jsAfter.timeout
5989
6018
  // reuse jsAfter timeout