@patch-adams/core 1.4.30 → 1.4.31

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
@@ -4130,58 +4130,101 @@ function generateLrsBridgeCode(options) {
4130
4130
  if (isUnknown) {
4131
4131
  log('Actor is Unknown Learner - SCORM API likely not available yet, polling for it...');
4132
4132
  var scormPollCount = 0;
4133
- var scormMaxPolls = 20; // wait up to 20 seconds
4133
+ var scormMaxPolls = 30; // wait up to 30 seconds
4134
+ var scormResolved = false;
4135
+
4136
+ // Helper: search all possible locations for SCORM API
4137
+ function findScormApiAnywhere() {
4138
+ // 1. Search parent frame hierarchy (standard approach)
4139
+ var api2004 = findAPIInFrameHierarchy('API_1484_11', 10);
4140
+ if (api2004) return { api: api2004.api, type: '2004', source: 'parent-chain level ' + api2004.level };
4141
+ var api12 = findAPIInFrameHierarchy('API', 10);
4142
+ if (api12) return { api: api12.api, type: '1.2', source: 'parent-chain level ' + api12.level };
4143
+
4144
+ // 2. Check window.opener and its parent hierarchy (LMS opens content in popup)
4145
+ try {
4146
+ if (window.opener && window.opener !== window) {
4147
+ // Direct check on opener
4148
+ if (window.opener.API_1484_11) return { api: window.opener.API_1484_11, type: '2004', source: 'window.opener' };
4149
+ if (window.opener.API) return { api: window.opener.API, type: '1.2', source: 'window.opener' };
4150
+ // Check opener's parent chain
4151
+ var openerWin = window.opener;
4152
+ var openerLevel = 0;
4153
+ while (openerLevel < 10) {
4154
+ try {
4155
+ if (openerWin.API_1484_11) return { api: openerWin.API_1484_11, type: '2004', source: 'opener-chain level ' + openerLevel };
4156
+ if (openerWin.API) return { api: openerWin.API, type: '1.2', source: 'opener-chain level ' + openerLevel };
4157
+ if (openerWin.parent && openerWin.parent !== openerWin) { openerWin = openerWin.parent; openerLevel++; }
4158
+ else break;
4159
+ } catch(e) { break; }
4160
+ }
4161
+ }
4162
+ } catch(e) { /* cross-origin opener */ }
4163
+
4164
+ // 3. Check for global LMS functions (Bravais/Xyleme mock API)
4165
+ try {
4166
+ if (typeof window.LMSInitialize === 'function') {
4167
+ return { api: { LMSInitialize: window.LMSInitialize, LMSGetValue: window.LMSGetValue, LMSSetValue: window.LMSSetValue, LMSCommit: window.LMSCommit, LMSFinish: window.LMSFinish, LMSGetLastError: window.LMSGetLastError, LMSGetErrorString: window.LMSGetErrorString }, type: '1.2', source: 'global-functions' };
4168
+ }
4169
+ } catch(e) {}
4170
+ try {
4171
+ if (window.parent && window.parent !== window && typeof window.parent.LMSInitialize === 'function') {
4172
+ return { api: { LMSInitialize: window.parent.LMSInitialize, LMSGetValue: window.parent.LMSGetValue, LMSSetValue: window.parent.LMSSetValue, LMSCommit: window.parent.LMSCommit, LMSFinish: window.parent.LMSFinish, LMSGetLastError: window.parent.LMSGetLastError, LMSGetErrorString: window.parent.LMSGetErrorString }, type: '1.2', source: 'parent-global-functions' };
4173
+ }
4174
+ } catch(e) {}
4175
+
4176
+ return null;
4177
+ }
4178
+
4179
+ function onScormApiFound(result, pollNum) {
4180
+ if (scormResolved) return;
4181
+ scormResolved = true;
4182
+
4183
+ LRS.scormApi = result.api;
4184
+ LRS.scormApiFound = true;
4185
+ LRS.scormApiType = result.type;
4186
+
4187
+ // Read learner_id for diagnostics
4188
+ var scormLearnerId = 'n/a', scormLearnerName = 'n/a';
4189
+ try {
4190
+ if (result.type === '2004') {
4191
+ scormLearnerId = result.api.GetValue('cmi.learner_id');
4192
+ scormLearnerName = result.api.GetValue('cmi.learner_name');
4193
+ } else {
4194
+ scormLearnerId = result.api.LMSGetValue('cmi.core.student_id');
4195
+ scormLearnerName = result.api.LMSGetValue('cmi.core.student_name');
4196
+ }
4197
+ } catch(e) { scormLearnerId = 'error'; scormLearnerName = 'error'; }
4198
+ console.info('[PA-LRS] SCORM API found (poll ' + pollNum + ', source=' + result.source +
4199
+ ', type=' + result.type + '): learner_id=' + scormLearnerId + ', learner_name=' + scormLearnerName);
4200
+
4201
+ // refreshActor re-reads learner_id from SCORM and runs employee lookup
4202
+ LRS.refreshActor(function(refreshedActor) {
4203
+ if (window.console && window.console.info) {
4204
+ console.info('[PA-LRS] Actor resolved (after SCORM wait, poll ' + pollNum + '): name=' +
4205
+ (refreshedActor ? refreshedActor.name : 'none') +
4206
+ ', mbox=' + (refreshedActor ? refreshedActor.mbox : 'none') +
4207
+ ', account=' + (refreshedActor && refreshedActor.account ? refreshedActor.account.name : 'none'));
4208
+ }
4209
+ actorReady = true;
4210
+ tryLaunchEvents();
4211
+ });
4212
+ }
4134
4213
 
4135
4214
  var scormPollTimer = setInterval(function() {
4215
+ if (scormResolved) { clearInterval(scormPollTimer); return; }
4136
4216
  scormPollCount++;
4137
4217
 
4138
- // Search parent frames for SCORM API (not just current window)
4139
- var api2004 = findAPIInFrameHierarchy('API_1484_11', 10);
4140
- var api12 = !api2004 ? findAPIInFrameHierarchy('API', 10) : null;
4141
- var foundApi = api2004 || api12;
4218
+ var result = findScormApiAnywhere();
4142
4219
 
4143
- if (foundApi) {
4220
+ if (result) {
4144
4221
  clearInterval(scormPollTimer);
4145
- var foundType = api2004 ? '2004' : '1.2';
4146
- log('SCORM API found on poll ' + scormPollCount + ' at level ' + foundApi.level);
4147
-
4148
- // Update LRS SCORM API reference
4149
- if (!LRS.scormApi) {
4150
- LRS.scormApi = foundApi.api;
4151
- LRS.scormApiFound = true;
4152
- LRS.scormApiType = foundType;
4153
- }
4154
-
4155
- // Read learner_id right now for diagnostics
4156
- var scormLearnerId = 'n/a', scormLearnerName = 'n/a';
4157
- try {
4158
- if (foundType === '2004') {
4159
- scormLearnerId = foundApi.api.GetValue('cmi.learner_id');
4160
- scormLearnerName = foundApi.api.GetValue('cmi.learner_name');
4161
- } else {
4162
- scormLearnerId = foundApi.api.LMSGetValue('cmi.core.student_id');
4163
- scormLearnerName = foundApi.api.LMSGetValue('cmi.core.student_name');
4164
- }
4165
- } catch(e) { scormLearnerId = 'error'; scormLearnerName = 'error'; }
4166
- console.info('[PA-LRS] SCORM API found (poll ' + scormPollCount + ', type=' + foundType +
4167
- ', level=' + foundApi.level + '): learner_id=' + scormLearnerId + ', learner_name=' + scormLearnerName);
4168
-
4169
- // refreshActor re-reads learner_id from SCORM and runs employee lookup
4170
- LRS.refreshActor(function(refreshedActor) {
4171
- if (window.console && window.console.info) {
4172
- console.info('[PA-LRS] Actor resolved (after SCORM wait, poll ' + scormPollCount + '): name=' +
4173
- (refreshedActor ? refreshedActor.name : 'none') +
4174
- ', mbox=' + (refreshedActor ? refreshedActor.mbox : 'none') +
4175
- ', account=' + (refreshedActor && refreshedActor.account ? refreshedActor.account.name : 'none'));
4176
- }
4177
- actorReady = true;
4178
- tryLaunchEvents();
4179
- });
4222
+ onScormApiFound(result, scormPollCount);
4180
4223
  } else if (scormPollCount >= scormMaxPolls) {
4181
4224
  clearInterval(scormPollTimer);
4182
4225
  log('SCORM API not found after ' + scormMaxPolls + 's, proceeding with Unknown Learner');
4183
4226
  if (window.console && window.console.info) {
4184
- console.info('[PA-LRS] Actor resolved (timeout): name=' + (actor ? actor.name : 'none') +
4227
+ console.info('[PA-LRS] Actor resolved (timeout ' + scormMaxPolls + 's): name=' + (actor ? actor.name : 'none') +
4185
4228
  ', account=' + (actor && actor.account ? actor.account.name : 'none'));
4186
4229
  }
4187
4230
  actorReady = true;