@patch-adams/core 1.3.3 → 1.3.6

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
@@ -733,10 +733,11 @@ function generateLrsBridgeCode(options) {
733
733
  const employeeApiEndpoint = options.employeeApiEndpoint || "";
734
734
  return `
735
735
  // ==========================================================================
736
- // PATCH-ADAMS LRS BRIDGE v2.1.0
736
+ // PATCH-ADAMS LRS BRIDGE v2.2.0
737
737
  // Full xAPI support with direct LRS communication for Rise courses
738
- // ALL statements use COURSE as main object for Analytics searchability
738
+ // ALL statements use DOCUMENT as main object for Bravais aggregation
739
739
  // Activity type (video, assessment, etc.) stored in object.definition.type
740
+ // Page/lesson info stored in context.extensions for navigation tracking
740
741
  // ==========================================================================
741
742
  (function() {
742
743
  'use strict';
@@ -1905,6 +1906,132 @@ function generateLrsBridgeCode(options) {
1905
1906
  return null;
1906
1907
  }
1907
1908
 
1909
+ // Store for document API data
1910
+ var documentApiData = null;
1911
+ var documentApiFetched = false;
1912
+
1913
+ /**
1914
+ * Fetch document metadata from Bravais API to get GUIDs
1915
+ * Endpoint: /api/v3/documents/{documentId}
1916
+ */
1917
+ function fetchDocumentMetadata(documentId, callback) {
1918
+ if (!documentId) {
1919
+ callback(null);
1920
+ return;
1921
+ }
1922
+
1923
+ if (documentApiFetched) {
1924
+ callback(documentApiData);
1925
+ return;
1926
+ }
1927
+
1928
+ // Detect Bravais core URL
1929
+ var coreUrl = null;
1930
+ var urlsToCheck = [window.location.href, document.referrer];
1931
+
1932
+ try {
1933
+ var win = window;
1934
+ for (var i = 0; i < 10; i++) {
1935
+ if (win.parent && win.parent !== win) {
1936
+ win = win.parent;
1937
+ try {
1938
+ urlsToCheck.push(win.location.href);
1939
+ } catch (e) { break; }
1940
+ } else { break; }
1941
+ }
1942
+ } catch (e) {}
1943
+
1944
+ for (var j = 0; j < urlsToCheck.length; j++) {
1945
+ var match = urlsToCheck[j].match(/(https?:\\/\\/core-[a-zA-Z0-9_-]+\\.bravais\\.com)/);
1946
+ if (match) {
1947
+ coreUrl = match[1];
1948
+ break;
1949
+ }
1950
+ }
1951
+
1952
+ if (!coreUrl) {
1953
+ log('No Bravais core URL detected for document metadata fetch');
1954
+ documentApiFetched = true;
1955
+ callback(null);
1956
+ return;
1957
+ }
1958
+
1959
+ var apiUrl = coreUrl + '/api/v3/documents/' + documentId;
1960
+ log('Fetching document metadata from:', apiUrl);
1961
+
1962
+ var xhr = new XMLHttpRequest();
1963
+ xhr.open('GET', apiUrl, true);
1964
+ xhr.withCredentials = true;
1965
+ xhr.setRequestHeader('Accept', 'application/json');
1966
+
1967
+ xhr.onreadystatechange = function() {
1968
+ if (xhr.readyState === 4) {
1969
+ documentApiFetched = true;
1970
+ log('Document API response status:', xhr.status);
1971
+ if (xhr.status >= 200 && xhr.status < 300) {
1972
+ try {
1973
+ documentApiData = JSON.parse(xhr.responseText);
1974
+ log('Document metadata received:', documentApiData);
1975
+ callback(documentApiData);
1976
+ } catch (e) {
1977
+ warn('Error parsing document metadata:', e);
1978
+ callback(null);
1979
+ }
1980
+ } else {
1981
+ log('Document metadata fetch failed. Status:', xhr.status);
1982
+ callback(null);
1983
+ }
1984
+ }
1985
+ };
1986
+
1987
+ xhr.onerror = function() {
1988
+ documentApiFetched = true;
1989
+ log('Network error fetching document metadata');
1990
+ callback(null);
1991
+ };
1992
+
1993
+ try {
1994
+ xhr.send();
1995
+ } catch (e) {
1996
+ documentApiFetched = true;
1997
+ warn('Error sending document request:', e);
1998
+ callback(null);
1999
+ }
2000
+ }
2001
+
2002
+ /**
2003
+ * Update course info with data from document API
2004
+ */
2005
+ function updateCourseInfoFromApi(docData) {
2006
+ if (!docData || !LRS.courseInfo) return;
2007
+
2008
+ // Document GUID
2009
+ if (docData.guid && !LRS.courseInfo.guid) {
2010
+ LRS.courseInfo.guid = docData.guid;
2011
+ LRS.courseInfo.id = 'http://xyleme.com/bravais/document/' + docData.guid;
2012
+ log('Updated course guid from API:', docData.guid);
2013
+ }
2014
+
2015
+ // Version GUID from latestVersion
2016
+ if (docData.latestVersion && docData.latestVersion.guid && !LRS.courseInfo.versionGuid) {
2017
+ LRS.courseInfo.versionGuid = docData.latestVersion.guid;
2018
+ log('Updated version guid from API:', docData.latestVersion.guid);
2019
+ }
2020
+
2021
+ // Other metadata
2022
+ if (docData.name && LRS.courseInfo.title === 'Rise Course') {
2023
+ LRS.courseInfo.title = docData.name;
2024
+ }
2025
+ if (docData.format) {
2026
+ LRS.courseInfo.format = docData.format;
2027
+ }
2028
+ if (docData.resourceType) {
2029
+ LRS.courseInfo.resourceType = docData.resourceType;
2030
+ }
2031
+
2032
+ log('Course info updated from API:', LRS.courseInfo);
2033
+ }
2034
+
1908
2035
  /**
1909
2036
  * Extract Bravais document ID from URL
1910
2037
  * Pattern: /api/shared/.../files/{documentId}/scormcontent/
@@ -2605,24 +2732,41 @@ function generateLrsBridgeCode(options) {
2605
2732
  sendStatement(statement);
2606
2733
  };
2607
2734
 
2608
- // Content/Page viewed
2735
+ // Content/Page viewed - uses document as object for Bravais aggregation
2609
2736
  LRS.contentOpened = function(data) {
2610
2737
  if (!TRACK_NAVIGATION) return;
2611
2738
 
2612
- // Build page-level activity object for Xyleme format
2613
- var pageObject = buildPageActivityObject({
2614
- pageGuid: data.pageGuid || data.lessonId,
2615
- name: data.title || 'Page',
2616
- type: 'page'
2617
- });
2618
-
2619
2739
  var result = null;
2620
2740
  if (data.duration) {
2621
2741
  result = { duration: data.duration };
2622
2742
  }
2623
2743
 
2624
- // Use 'opened' verb for Xyleme compatibility (ActivityStrea.ms)
2625
- var statement = buildStatementXyleme('opened', pageObject, result);
2744
+ // Extract clean page/lesson ID from Rise hash paths
2745
+ var lessonId = data.pageGuid || data.lessonId || '';
2746
+ if (lessonId.indexOf('#/lessons/') === 0) {
2747
+ lessonId = lessonId.substring(10); // Remove '#/lessons/'
2748
+ } else if (lessonId.indexOf('#/') === 0) {
2749
+ lessonId = lessonId.substring(2); // Remove '#/'
2750
+ }
2751
+
2752
+ // Add page info to context extensions (not as main object)
2753
+ var additionalContext = {
2754
+ extensions: {
2755
+ pageId: lessonId || 'home',
2756
+ pageTitle: data.title || 'Page',
2757
+ pageUrl: data.url || window.location.href
2758
+ }
2759
+ };
2760
+
2761
+ // Use document as main object (required for Bravais aggregation)
2762
+ // Use 'experienced' verb which is standard xAPI for viewing content
2763
+ var statement = buildStatement(
2764
+ 'experienced',
2765
+ 'http://xyleme.com/bravais/activities/document',
2766
+ { event: 'page_viewed', pageId: lessonId },
2767
+ result,
2768
+ additionalContext
2769
+ );
2626
2770
  sendStatement(statement);
2627
2771
  };
2628
2772
 
@@ -3122,7 +3266,7 @@ function generateLrsBridgeCode(options) {
3122
3266
  // ========================================================================
3123
3267
 
3124
3268
  function init() {
3125
- log('Initializing LRS bridge v2.0.0...');
3269
+ log('Initializing LRS bridge v2.2.0...');
3126
3270
 
3127
3271
  // Extract course info early
3128
3272
  extractCourseInfo();
@@ -3156,8 +3300,11 @@ function generateLrsBridgeCode(options) {
3156
3300
  setupQuizInterceptors();
3157
3301
  setupInteractionInterceptors();
3158
3302
 
3159
- // Send course launched event after a short delay to allow actor fetch
3160
- setTimeout(function() {
3303
+ // Fetch document metadata from API to get GUIDs (async)
3304
+ // Then send course launched event
3305
+ var documentId = LRS.courseInfo ? LRS.courseInfo.documentId : null;
3306
+
3307
+ function sendLaunchEvents() {
3161
3308
  if (TRACK_NAVIGATION) {
3162
3309
  LRS.courseLaunched();
3163
3310
  LRS.contentOpened({
@@ -3166,7 +3313,21 @@ function generateLrsBridgeCode(options) {
3166
3313
  action: 'launched'
3167
3314
  });
3168
3315
  }
3169
- }, 500);
3316
+ }
3317
+
3318
+ if (documentId && !LRS.courseInfo.guid) {
3319
+ // Try to fetch GUIDs from API before sending statements
3320
+ fetchDocumentMetadata(documentId, function(docData) {
3321
+ if (docData) {
3322
+ updateCourseInfoFromApi(docData);
3323
+ }
3324
+ // Send launch events after API fetch (success or failure)
3325
+ setTimeout(sendLaunchEvents, 100);
3326
+ });
3327
+ } else {
3328
+ // Already have GUID or no document ID - send after short delay
3329
+ setTimeout(sendLaunchEvents, 500);
3330
+ }
3170
3331
 
3171
3332
  // Setup beforeunload to send terminated
3172
3333
  window.addEventListener('beforeunload', function() {