@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.js CHANGED
@@ -724,10 +724,11 @@ function generateLrsBridgeCode(options) {
724
724
  const employeeApiEndpoint = options.employeeApiEndpoint || "";
725
725
  return `
726
726
  // ==========================================================================
727
- // PATCH-ADAMS LRS BRIDGE v2.1.0
727
+ // PATCH-ADAMS LRS BRIDGE v2.2.0
728
728
  // Full xAPI support with direct LRS communication for Rise courses
729
- // ALL statements use COURSE as main object for Analytics searchability
729
+ // ALL statements use DOCUMENT as main object for Bravais aggregation
730
730
  // Activity type (video, assessment, etc.) stored in object.definition.type
731
+ // Page/lesson info stored in context.extensions for navigation tracking
731
732
  // ==========================================================================
732
733
  (function() {
733
734
  'use strict';
@@ -1896,6 +1897,132 @@ function generateLrsBridgeCode(options) {
1896
1897
  return null;
1897
1898
  }
1898
1899
 
1900
+ // Store for document API data
1901
+ var documentApiData = null;
1902
+ var documentApiFetched = false;
1903
+
1904
+ /**
1905
+ * Fetch document metadata from Bravais API to get GUIDs
1906
+ * Endpoint: /api/v3/documents/{documentId}
1907
+ */
1908
+ function fetchDocumentMetadata(documentId, callback) {
1909
+ if (!documentId) {
1910
+ callback(null);
1911
+ return;
1912
+ }
1913
+
1914
+ if (documentApiFetched) {
1915
+ callback(documentApiData);
1916
+ return;
1917
+ }
1918
+
1919
+ // Detect Bravais core URL
1920
+ var coreUrl = null;
1921
+ var urlsToCheck = [window.location.href, document.referrer];
1922
+
1923
+ try {
1924
+ var win = window;
1925
+ for (var i = 0; i < 10; i++) {
1926
+ if (win.parent && win.parent !== win) {
1927
+ win = win.parent;
1928
+ try {
1929
+ urlsToCheck.push(win.location.href);
1930
+ } catch (e) { break; }
1931
+ } else { break; }
1932
+ }
1933
+ } catch (e) {}
1934
+
1935
+ for (var j = 0; j < urlsToCheck.length; j++) {
1936
+ var match = urlsToCheck[j].match(/(https?:\\/\\/core-[a-zA-Z0-9_-]+\\.bravais\\.com)/);
1937
+ if (match) {
1938
+ coreUrl = match[1];
1939
+ break;
1940
+ }
1941
+ }
1942
+
1943
+ if (!coreUrl) {
1944
+ log('No Bravais core URL detected for document metadata fetch');
1945
+ documentApiFetched = true;
1946
+ callback(null);
1947
+ return;
1948
+ }
1949
+
1950
+ var apiUrl = coreUrl + '/api/v3/documents/' + documentId;
1951
+ log('Fetching document metadata from:', apiUrl);
1952
+
1953
+ var xhr = new XMLHttpRequest();
1954
+ xhr.open('GET', apiUrl, true);
1955
+ xhr.withCredentials = true;
1956
+ xhr.setRequestHeader('Accept', 'application/json');
1957
+
1958
+ xhr.onreadystatechange = function() {
1959
+ if (xhr.readyState === 4) {
1960
+ documentApiFetched = true;
1961
+ log('Document API response status:', xhr.status);
1962
+ if (xhr.status >= 200 && xhr.status < 300) {
1963
+ try {
1964
+ documentApiData = JSON.parse(xhr.responseText);
1965
+ log('Document metadata received:', documentApiData);
1966
+ callback(documentApiData);
1967
+ } catch (e) {
1968
+ warn('Error parsing document metadata:', e);
1969
+ callback(null);
1970
+ }
1971
+ } else {
1972
+ log('Document metadata fetch failed. Status:', xhr.status);
1973
+ callback(null);
1974
+ }
1975
+ }
1976
+ };
1977
+
1978
+ xhr.onerror = function() {
1979
+ documentApiFetched = true;
1980
+ log('Network error fetching document metadata');
1981
+ callback(null);
1982
+ };
1983
+
1984
+ try {
1985
+ xhr.send();
1986
+ } catch (e) {
1987
+ documentApiFetched = true;
1988
+ warn('Error sending document request:', e);
1989
+ callback(null);
1990
+ }
1991
+ }
1992
+
1993
+ /**
1994
+ * Update course info with data from document API
1995
+ */
1996
+ function updateCourseInfoFromApi(docData) {
1997
+ if (!docData || !LRS.courseInfo) return;
1998
+
1999
+ // Document GUID
2000
+ if (docData.guid && !LRS.courseInfo.guid) {
2001
+ LRS.courseInfo.guid = docData.guid;
2002
+ LRS.courseInfo.id = 'http://xyleme.com/bravais/document/' + docData.guid;
2003
+ log('Updated course guid from API:', docData.guid);
2004
+ }
2005
+
2006
+ // Version GUID from latestVersion
2007
+ if (docData.latestVersion && docData.latestVersion.guid && !LRS.courseInfo.versionGuid) {
2008
+ LRS.courseInfo.versionGuid = docData.latestVersion.guid;
2009
+ log('Updated version guid from API:', docData.latestVersion.guid);
2010
+ }
2011
+
2012
+ // Other metadata
2013
+ if (docData.name && LRS.courseInfo.title === 'Rise Course') {
2014
+ LRS.courseInfo.title = docData.name;
2015
+ }
2016
+ if (docData.format) {
2017
+ LRS.courseInfo.format = docData.format;
2018
+ }
2019
+ if (docData.resourceType) {
2020
+ LRS.courseInfo.resourceType = docData.resourceType;
2021
+ }
2022
+
2023
+ log('Course info updated from API:', LRS.courseInfo);
2024
+ }
2025
+
1899
2026
  /**
1900
2027
  * Extract Bravais document ID from URL
1901
2028
  * Pattern: /api/shared/.../files/{documentId}/scormcontent/
@@ -2596,24 +2723,41 @@ function generateLrsBridgeCode(options) {
2596
2723
  sendStatement(statement);
2597
2724
  };
2598
2725
 
2599
- // Content/Page viewed
2726
+ // Content/Page viewed - uses document as object for Bravais aggregation
2600
2727
  LRS.contentOpened = function(data) {
2601
2728
  if (!TRACK_NAVIGATION) return;
2602
2729
 
2603
- // Build page-level activity object for Xyleme format
2604
- var pageObject = buildPageActivityObject({
2605
- pageGuid: data.pageGuid || data.lessonId,
2606
- name: data.title || 'Page',
2607
- type: 'page'
2608
- });
2609
-
2610
2730
  var result = null;
2611
2731
  if (data.duration) {
2612
2732
  result = { duration: data.duration };
2613
2733
  }
2614
2734
 
2615
- // Use 'opened' verb for Xyleme compatibility (ActivityStrea.ms)
2616
- var statement = buildStatementXyleme('opened', pageObject, result);
2735
+ // Extract clean page/lesson ID from Rise hash paths
2736
+ var lessonId = data.pageGuid || data.lessonId || '';
2737
+ if (lessonId.indexOf('#/lessons/') === 0) {
2738
+ lessonId = lessonId.substring(10); // Remove '#/lessons/'
2739
+ } else if (lessonId.indexOf('#/') === 0) {
2740
+ lessonId = lessonId.substring(2); // Remove '#/'
2741
+ }
2742
+
2743
+ // Add page info to context extensions (not as main object)
2744
+ var additionalContext = {
2745
+ extensions: {
2746
+ pageId: lessonId || 'home',
2747
+ pageTitle: data.title || 'Page',
2748
+ pageUrl: data.url || window.location.href
2749
+ }
2750
+ };
2751
+
2752
+ // Use document as main object (required for Bravais aggregation)
2753
+ // Use 'experienced' verb which is standard xAPI for viewing content
2754
+ var statement = buildStatement(
2755
+ 'experienced',
2756
+ 'http://xyleme.com/bravais/activities/document',
2757
+ { event: 'page_viewed', pageId: lessonId },
2758
+ result,
2759
+ additionalContext
2760
+ );
2617
2761
  sendStatement(statement);
2618
2762
  };
2619
2763
 
@@ -3113,7 +3257,7 @@ function generateLrsBridgeCode(options) {
3113
3257
  // ========================================================================
3114
3258
 
3115
3259
  function init() {
3116
- log('Initializing LRS bridge v2.0.0...');
3260
+ log('Initializing LRS bridge v2.2.0...');
3117
3261
 
3118
3262
  // Extract course info early
3119
3263
  extractCourseInfo();
@@ -3147,8 +3291,11 @@ function generateLrsBridgeCode(options) {
3147
3291
  setupQuizInterceptors();
3148
3292
  setupInteractionInterceptors();
3149
3293
 
3150
- // Send course launched event after a short delay to allow actor fetch
3151
- setTimeout(function() {
3294
+ // Fetch document metadata from API to get GUIDs (async)
3295
+ // Then send course launched event
3296
+ var documentId = LRS.courseInfo ? LRS.courseInfo.documentId : null;
3297
+
3298
+ function sendLaunchEvents() {
3152
3299
  if (TRACK_NAVIGATION) {
3153
3300
  LRS.courseLaunched();
3154
3301
  LRS.contentOpened({
@@ -3157,7 +3304,21 @@ function generateLrsBridgeCode(options) {
3157
3304
  action: 'launched'
3158
3305
  });
3159
3306
  }
3160
- }, 500);
3307
+ }
3308
+
3309
+ if (documentId && !LRS.courseInfo.guid) {
3310
+ // Try to fetch GUIDs from API before sending statements
3311
+ fetchDocumentMetadata(documentId, function(docData) {
3312
+ if (docData) {
3313
+ updateCourseInfoFromApi(docData);
3314
+ }
3315
+ // Send launch events after API fetch (success or failure)
3316
+ setTimeout(sendLaunchEvents, 100);
3317
+ });
3318
+ } else {
3319
+ // Already have GUID or no document ID - send after short delay
3320
+ setTimeout(sendLaunchEvents, 500);
3321
+ }
3161
3322
 
3162
3323
  // Setup beforeunload to send terminated
3163
3324
  window.addEventListener('beforeunload', function() {