@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.cjs CHANGED
@@ -468,7 +468,9 @@ var PatchAdamsConfigSchema = zod.z.object({
468
468
  /** Plugin configurations - each plugin is keyed by its name */
469
469
  plugins: PluginsConfigSchema,
470
470
  /** Optional skin name — adds 'pa-skinned' + skin class to <html>, loads skin CSS/JS after core files */
471
- skin: zod.z.string().min(1).optional()
471
+ skin: zod.z.string().min(1).optional(),
472
+ /** URL for server-controlled asset cache version (e.g., https://api.example.com/create/skin/version) */
473
+ assetVersionUrl: zod.z.string().url().optional()
472
474
  });
473
475
 
474
476
  // src/config/defaults.ts
@@ -612,7 +614,8 @@ html.${htmlClass}.${loadingClass} body {
612
614
  <script data-pa="css-before-loader">
613
615
  (function() {
614
616
  'use strict';
615
- var REMOTE_URL = "${remoteUrl}";
617
+ var v = window.__pa_v || '';
618
+ var REMOTE_URL = "${remoteUrl}" + (v ? "?v=" + v : "");
616
619
  var LOCAL_PATH = "${localPath}";
617
620
 
618
621
  function loadCSSSync(url) {
@@ -655,7 +658,7 @@ function generateCssAfterLoader(options) {
655
658
  <script data-pa="css-after-loader">
656
659
  (function() {
657
660
  'use strict';
658
- var REMOTE_URL = "${remoteUrl}";
661
+ var REMOTE_URL = "${remoteUrl}" + (window.__pa_v ? "?v=" + window.__pa_v : "");
659
662
  var LOCAL_PATH = "${localPath}";
660
663
  var TIMEOUT = ${timeout};
661
664
 
@@ -1784,8 +1787,8 @@ function generateLrsBridgeCode(options) {
1784
1787
  ', bravaisUserId=' + employeeData.bravaisUserId + ', tenantUrl=' + employeeData.tenantUrl
1785
1788
  : 'NO DATA'));
1786
1789
  if (employeeData && employeeData.email) {
1787
- actor.mbox = 'mailto:' + employeeData.email;
1788
- log('Enhanced actor with email:', employeeData.email);
1790
+ actor.mbox = 'mailto:' + employeeData.email.toLowerCase();
1791
+ log('Enhanced actor with email:', employeeData.email.toLowerCase());
1789
1792
 
1790
1793
  // Also update name if we got a better one
1791
1794
  if (employeeData.name && (!actor.name || actor.name === 'Unknown Learner')) {
@@ -1950,6 +1953,18 @@ function generateLrsBridgeCode(options) {
1950
1953
  return n === 'anonymous learner' || n === 'unknown learner' || n === 'anonymous' || n === 'unknown';
1951
1954
  }
1952
1955
 
1956
+ /**
1957
+ * Normalize actor IFI fields for consistent matching in Bravais Analytics.
1958
+ * Lowercases mbox email (RFC 5321: local-part is case-insensitive in practice).
1959
+ */
1960
+ function normalizeActor(actor) {
1961
+ if (!actor) return actor;
1962
+ if (actor.mbox && actor.mbox.indexOf('mailto:') === 0) {
1963
+ actor.mbox = 'mailto:' + actor.mbox.substring(7).toLowerCase();
1964
+ }
1965
+ return actor;
1966
+ }
1967
+
1953
1968
  /**
1954
1969
  * Persist actor to localStorage for cross-frame sharing.
1955
1970
  * Only stores non-anonymous actors.
@@ -1996,14 +2011,14 @@ function generateLrsBridgeCode(options) {
1996
2011
  (LRS.actor.account && shared.account && LRS.actor.account.name !== shared.account.name)) {
1997
2012
  log('Actor updated from cross-frame storage:', shared.name);
1998
2013
  }
1999
- LRS.actor = shared;
2000
- return shared;
2014
+ LRS.actor = normalizeActor(shared);
2015
+ return LRS.actor;
2001
2016
  }
2002
2017
  // Fallback to current actor or re-extract
2003
2018
  if (LRS.actor && !isAnonymousActor(LRS.actor)) {
2004
- return LRS.actor;
2019
+ return normalizeActor(LRS.actor);
2005
2020
  }
2006
- return LRS.actor || extractActor();
2021
+ return normalizeActor(LRS.actor || extractActor());
2007
2022
  }
2008
2023
 
2009
2024
  /**
@@ -2065,9 +2080,9 @@ function generateLrsBridgeCode(options) {
2065
2080
  function finalizeActor(actor) {
2066
2081
  // Try to enhance actor with email if missing
2067
2082
  enhanceActorWithEmail(actor, function(enhancedActor) {
2068
- LRS.actor = enhancedActor;
2069
- persistActor(enhancedActor);
2070
- callback(enhancedActor);
2083
+ LRS.actor = normalizeActor(enhancedActor);
2084
+ persistActor(LRS.actor);
2085
+ callback(LRS.actor);
2071
2086
  });
2072
2087
  }
2073
2088
 
@@ -5522,7 +5537,7 @@ function escapeJs(str) {
5522
5537
  return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r");
5523
5538
  }
5524
5539
  function generateJsBeforeLoader(options) {
5525
- const { remoteUrl, localPath, htmlClass, loadingClass, metadata, lrsBridge, skin } = options;
5540
+ const { remoteUrl, localPath, htmlClass, loadingClass, metadata, lrsBridge, skin, assetVersionUrl } = options;
5526
5541
  const lrsBridgeCode = generateLrsBridgeCode(lrsBridge);
5527
5542
  const courseLines = [];
5528
5543
  if (metadata) {
@@ -5625,7 +5640,22 @@ window.pa_patcher = window.pa_patcher || {
5625
5640
 
5626
5641
  (function() {
5627
5642
  'use strict';
5628
- var REMOTE_URL = "${remoteUrl}";
5643
+ // Fetch server-controlled cache version (sync, once)
5644
+ var ASSET_VERSION_URL = "${assetVersionUrl || ""}";
5645
+ window.__pa_v = '';
5646
+ if (ASSET_VERSION_URL) {
5647
+ try {
5648
+ var xhr = new XMLHttpRequest();
5649
+ xhr.open('GET', ASSET_VERSION_URL, false);
5650
+ xhr.timeout = 2000;
5651
+ xhr.send();
5652
+ if (xhr.status === 200) {
5653
+ window.__pa_v = JSON.parse(xhr.responseText).v || '1';
5654
+ }
5655
+ } catch(e) { window.__pa_v = '1'; }
5656
+ }
5657
+
5658
+ var REMOTE_URL = "${remoteUrl}" + (window.__pa_v ? "?v=" + window.__pa_v : "");
5629
5659
  var LOCAL_PATH = "${localPath}";
5630
5660
 
5631
5661
  function loadJSSync(url) {
@@ -5694,7 +5724,8 @@ function buildJsBeforeOptions(config, metadata) {
5694
5724
  loadingClass: config.loadingClass,
5695
5725
  metadata: metadata ?? null,
5696
5726
  lrsBridge,
5697
- skin: config.skin
5727
+ skin: config.skin,
5728
+ assetVersionUrl: config.assetVersionUrl
5698
5729
  };
5699
5730
  }
5700
5731
 
@@ -5705,7 +5736,7 @@ function generateJsAfterLoader(options) {
5705
5736
  <script data-pa="js-after-loader">
5706
5737
  (function() {
5707
5738
  'use strict';
5708
- var REMOTE_URL = "${remoteUrl}";
5739
+ var REMOTE_URL = "${remoteUrl}" + (window.__pa_v ? "?v=" + window.__pa_v : "");
5709
5740
  var LOCAL_PATH = "${localPath}";
5710
5741
  var TIMEOUT = ${timeout};
5711
5742
  var LOADING_CLASS = "${loadingClass}";
@@ -5815,7 +5846,7 @@ function generateSkinCssLoader(options) {
5815
5846
  <script data-pa="skin-css-loader">
5816
5847
  (function() {
5817
5848
  'use strict';
5818
- var REMOTE_URL = "${remoteUrl}";
5849
+ var REMOTE_URL = "${remoteUrl}" + (window.__pa_v ? "?v=" + window.__pa_v : "?v=" + Date.now().toString(36));
5819
5850
  var LOCAL_PATH = "${localPath}";
5820
5851
  var TIMEOUT = ${timeout};
5821
5852
 
@@ -5889,9 +5920,8 @@ function generateSkinCssLoader(options) {
5889
5920
  }
5890
5921
  function buildSkinCssOptions(config) {
5891
5922
  if (!config.skin) return null;
5892
- const cacheBuster = Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
5893
5923
  return {
5894
- remoteUrl: `${config.remoteDomain}/skin/${config.skin}/style.css?v=${cacheBuster}`,
5924
+ remoteUrl: `${config.remoteDomain}/skin/${config.skin}/style.css`,
5895
5925
  localPath: `skin/${config.skin}/style.css`,
5896
5926
  timeout: config.cssAfter.timeout
5897
5927
  // reuse cssAfter timeout
@@ -5905,7 +5935,7 @@ function generateSkinJsLoader(options) {
5905
5935
  <script data-pa="skin-js-loader">
5906
5936
  (function() {
5907
5937
  'use strict';
5908
- var REMOTE_URL = "${remoteUrl}";
5938
+ var REMOTE_URL = "${remoteUrl}" + (window.__pa_v ? "?v=" + window.__pa_v : "?v=" + Date.now().toString(36));
5909
5939
  var LOCAL_PATH = "${localPath}";
5910
5940
  var TIMEOUT = ${timeout};
5911
5941
 
@@ -5991,9 +6021,8 @@ function generateSkinJsLoader(options) {
5991
6021
  }
5992
6022
  function buildSkinJsOptions(config) {
5993
6023
  if (!config.skin) return null;
5994
- const cacheBuster = Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
5995
6024
  return {
5996
- remoteUrl: `${config.remoteDomain}/skin/${config.skin}/script.js?v=${cacheBuster}`,
6025
+ remoteUrl: `${config.remoteDomain}/skin/${config.skin}/script.js`,
5997
6026
  localPath: `skin/${config.skin}/script.js`,
5998
6027
  timeout: config.jsAfter.timeout
5999
6028
  // reuse jsAfter timeout