@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/index.cjs CHANGED
@@ -397,10 +397,11 @@ function generateLrsBridgeCode(options) {
397
397
  const employeeApiEndpoint = options.employeeApiEndpoint || "";
398
398
  return `
399
399
  // ==========================================================================
400
- // PATCH-ADAMS LRS BRIDGE v2.1.0
400
+ // PATCH-ADAMS LRS BRIDGE v2.2.0
401
401
  // Full xAPI support with direct LRS communication for Rise courses
402
- // ALL statements use COURSE as main object for Analytics searchability
402
+ // ALL statements use DOCUMENT as main object for Bravais aggregation
403
403
  // Activity type (video, assessment, etc.) stored in object.definition.type
404
+ // Page/lesson info stored in context.extensions for navigation tracking
404
405
  // ==========================================================================
405
406
  (function() {
406
407
  'use strict';
@@ -1569,6 +1570,132 @@ function generateLrsBridgeCode(options) {
1569
1570
  return null;
1570
1571
  }
1571
1572
 
1573
+ // Store for document API data
1574
+ var documentApiData = null;
1575
+ var documentApiFetched = false;
1576
+
1577
+ /**
1578
+ * Fetch document metadata from Bravais API to get GUIDs
1579
+ * Endpoint: /api/v3/documents/{documentId}
1580
+ */
1581
+ function fetchDocumentMetadata(documentId, callback) {
1582
+ if (!documentId) {
1583
+ callback(null);
1584
+ return;
1585
+ }
1586
+
1587
+ if (documentApiFetched) {
1588
+ callback(documentApiData);
1589
+ return;
1590
+ }
1591
+
1592
+ // Detect Bravais core URL
1593
+ var coreUrl = null;
1594
+ var urlsToCheck = [window.location.href, document.referrer];
1595
+
1596
+ try {
1597
+ var win = window;
1598
+ for (var i = 0; i < 10; i++) {
1599
+ if (win.parent && win.parent !== win) {
1600
+ win = win.parent;
1601
+ try {
1602
+ urlsToCheck.push(win.location.href);
1603
+ } catch (e) { break; }
1604
+ } else { break; }
1605
+ }
1606
+ } catch (e) {}
1607
+
1608
+ for (var j = 0; j < urlsToCheck.length; j++) {
1609
+ var match = urlsToCheck[j].match(/(https?:\\/\\/core-[a-zA-Z0-9_-]+\\.bravais\\.com)/);
1610
+ if (match) {
1611
+ coreUrl = match[1];
1612
+ break;
1613
+ }
1614
+ }
1615
+
1616
+ if (!coreUrl) {
1617
+ log('No Bravais core URL detected for document metadata fetch');
1618
+ documentApiFetched = true;
1619
+ callback(null);
1620
+ return;
1621
+ }
1622
+
1623
+ var apiUrl = coreUrl + '/api/v3/documents/' + documentId;
1624
+ log('Fetching document metadata from:', apiUrl);
1625
+
1626
+ var xhr = new XMLHttpRequest();
1627
+ xhr.open('GET', apiUrl, true);
1628
+ xhr.withCredentials = true;
1629
+ xhr.setRequestHeader('Accept', 'application/json');
1630
+
1631
+ xhr.onreadystatechange = function() {
1632
+ if (xhr.readyState === 4) {
1633
+ documentApiFetched = true;
1634
+ log('Document API response status:', xhr.status);
1635
+ if (xhr.status >= 200 && xhr.status < 300) {
1636
+ try {
1637
+ documentApiData = JSON.parse(xhr.responseText);
1638
+ log('Document metadata received:', documentApiData);
1639
+ callback(documentApiData);
1640
+ } catch (e) {
1641
+ warn('Error parsing document metadata:', e);
1642
+ callback(null);
1643
+ }
1644
+ } else {
1645
+ log('Document metadata fetch failed. Status:', xhr.status);
1646
+ callback(null);
1647
+ }
1648
+ }
1649
+ };
1650
+
1651
+ xhr.onerror = function() {
1652
+ documentApiFetched = true;
1653
+ log('Network error fetching document metadata');
1654
+ callback(null);
1655
+ };
1656
+
1657
+ try {
1658
+ xhr.send();
1659
+ } catch (e) {
1660
+ documentApiFetched = true;
1661
+ warn('Error sending document request:', e);
1662
+ callback(null);
1663
+ }
1664
+ }
1665
+
1666
+ /**
1667
+ * Update course info with data from document API
1668
+ */
1669
+ function updateCourseInfoFromApi(docData) {
1670
+ if (!docData || !LRS.courseInfo) return;
1671
+
1672
+ // Document GUID
1673
+ if (docData.guid && !LRS.courseInfo.guid) {
1674
+ LRS.courseInfo.guid = docData.guid;
1675
+ LRS.courseInfo.id = 'http://xyleme.com/bravais/document/' + docData.guid;
1676
+ log('Updated course guid from API:', docData.guid);
1677
+ }
1678
+
1679
+ // Version GUID from latestVersion
1680
+ if (docData.latestVersion && docData.latestVersion.guid && !LRS.courseInfo.versionGuid) {
1681
+ LRS.courseInfo.versionGuid = docData.latestVersion.guid;
1682
+ log('Updated version guid from API:', docData.latestVersion.guid);
1683
+ }
1684
+
1685
+ // Other metadata
1686
+ if (docData.name && LRS.courseInfo.title === 'Rise Course') {
1687
+ LRS.courseInfo.title = docData.name;
1688
+ }
1689
+ if (docData.format) {
1690
+ LRS.courseInfo.format = docData.format;
1691
+ }
1692
+ if (docData.resourceType) {
1693
+ LRS.courseInfo.resourceType = docData.resourceType;
1694
+ }
1695
+
1696
+ log('Course info updated from API:', LRS.courseInfo);
1697
+ }
1698
+
1572
1699
  /**
1573
1700
  * Extract Bravais document ID from URL
1574
1701
  * Pattern: /api/shared/.../files/{documentId}/scormcontent/
@@ -2269,24 +2396,41 @@ function generateLrsBridgeCode(options) {
2269
2396
  sendStatement(statement);
2270
2397
  };
2271
2398
 
2272
- // Content/Page viewed
2399
+ // Content/Page viewed - uses document as object for Bravais aggregation
2273
2400
  LRS.contentOpened = function(data) {
2274
2401
  if (!TRACK_NAVIGATION) return;
2275
2402
 
2276
- // Build page-level activity object for Xyleme format
2277
- var pageObject = buildPageActivityObject({
2278
- pageGuid: data.pageGuid || data.lessonId,
2279
- name: data.title || 'Page',
2280
- type: 'page'
2281
- });
2282
-
2283
2403
  var result = null;
2284
2404
  if (data.duration) {
2285
2405
  result = { duration: data.duration };
2286
2406
  }
2287
2407
 
2288
- // Use 'opened' verb for Xyleme compatibility (ActivityStrea.ms)
2289
- var statement = buildStatementXyleme('opened', pageObject, result);
2408
+ // Extract clean page/lesson ID from Rise hash paths
2409
+ var lessonId = data.pageGuid || data.lessonId || '';
2410
+ if (lessonId.indexOf('#/lessons/') === 0) {
2411
+ lessonId = lessonId.substring(10); // Remove '#/lessons/'
2412
+ } else if (lessonId.indexOf('#/') === 0) {
2413
+ lessonId = lessonId.substring(2); // Remove '#/'
2414
+ }
2415
+
2416
+ // Add page info to context extensions (not as main object)
2417
+ var additionalContext = {
2418
+ extensions: {
2419
+ pageId: lessonId || 'home',
2420
+ pageTitle: data.title || 'Page',
2421
+ pageUrl: data.url || window.location.href
2422
+ }
2423
+ };
2424
+
2425
+ // Use document as main object (required for Bravais aggregation)
2426
+ // Use 'experienced' verb which is standard xAPI for viewing content
2427
+ var statement = buildStatement(
2428
+ 'experienced',
2429
+ 'http://xyleme.com/bravais/activities/document',
2430
+ { event: 'page_viewed', pageId: lessonId },
2431
+ result,
2432
+ additionalContext
2433
+ );
2290
2434
  sendStatement(statement);
2291
2435
  };
2292
2436
 
@@ -2786,7 +2930,7 @@ function generateLrsBridgeCode(options) {
2786
2930
  // ========================================================================
2787
2931
 
2788
2932
  function init() {
2789
- log('Initializing LRS bridge v2.0.0...');
2933
+ log('Initializing LRS bridge v2.2.0...');
2790
2934
 
2791
2935
  // Extract course info early
2792
2936
  extractCourseInfo();
@@ -2820,8 +2964,11 @@ function generateLrsBridgeCode(options) {
2820
2964
  setupQuizInterceptors();
2821
2965
  setupInteractionInterceptors();
2822
2966
 
2823
- // Send course launched event after a short delay to allow actor fetch
2824
- setTimeout(function() {
2967
+ // Fetch document metadata from API to get GUIDs (async)
2968
+ // Then send course launched event
2969
+ var documentId = LRS.courseInfo ? LRS.courseInfo.documentId : null;
2970
+
2971
+ function sendLaunchEvents() {
2825
2972
  if (TRACK_NAVIGATION) {
2826
2973
  LRS.courseLaunched();
2827
2974
  LRS.contentOpened({
@@ -2830,7 +2977,21 @@ function generateLrsBridgeCode(options) {
2830
2977
  action: 'launched'
2831
2978
  });
2832
2979
  }
2833
- }, 500);
2980
+ }
2981
+
2982
+ if (documentId && !LRS.courseInfo.guid) {
2983
+ // Try to fetch GUIDs from API before sending statements
2984
+ fetchDocumentMetadata(documentId, function(docData) {
2985
+ if (docData) {
2986
+ updateCourseInfoFromApi(docData);
2987
+ }
2988
+ // Send launch events after API fetch (success or failure)
2989
+ setTimeout(sendLaunchEvents, 100);
2990
+ });
2991
+ } else {
2992
+ // Already have GUID or no document ID - send after short delay
2993
+ setTimeout(sendLaunchEvents, 500);
2994
+ }
2834
2995
 
2835
2996
  // Setup beforeunload to send terminated
2836
2997
  window.addEventListener('beforeunload', function() {