@pie-framework/pie-fixed-player-static 1.0.0-24d9476.1 → 1.0.0-351df72.1

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @pie-framework/pie-fixed-player-static
2
2
 
3
- Version: 1.0.0-24d9476.1
3
+ Version: 1.0.0-351df72.1
4
4
 
5
5
  Pre-bundled PIE fixed player with static element versions for production use.
6
6
 
@@ -9,12 +9,15 @@ in Pieoneer, use `pie-inline-player` instead.
9
9
 
10
10
  ## Included Elements
11
11
 
12
+ - @pie-element/drag-in-the-blank@8.1.0
13
+ - @pie-element/hotspot@9.1.0
14
+ - @pie-element/image-cloze-association@8.1.0
12
15
  - @pie-element/multiple-choice@11.1.0
13
16
 
14
17
  ## Installation
15
18
 
16
19
  ```bash
17
- npm install @pie-framework/pie-fixed-player-static@1.0.0-24d9476.1
20
+ npm install @pie-framework/pie-fixed-player-static@1.0.0-351df72.1
18
21
  ```
19
22
 
20
23
  ## Usage
@@ -41,8 +44,51 @@ npm install @pie-framework/pie-fixed-player-static@1.0.0-24d9476.1
41
44
  - `session` - Session data array
42
45
  - `add-correct-response` - Show correct answers
43
46
  - `external-style-urls` - Additional CSS URLs
47
+ - `loader-config` - Loader configuration (JSON string, see below)
44
48
  - Custom styling attributes
45
49
 
50
+ ## Loader Configuration
51
+
52
+ Control resource loading behavior and New Relic tracking via the `loader-config` attribute:
53
+
54
+ ```html
55
+ <pie-fixed-player
56
+ item-id="your-item-id"
57
+ loader-config='{"trackPageActions": true, "maxResourceRetries": 3}'>
58
+ </pie-fixed-player>
59
+ ```
60
+
61
+ **Options:**
62
+ - `trackPageActions` (boolean, default: false) - Enable New Relic instrumentation for module imports and resource loading
63
+ - `maxResourceRetries` (number, default: 3) - Maximum retry attempts for failed resources
64
+ - `resourceRetryDelay` (number, default: 500) - Initial delay in ms before retrying
65
+
66
+ **Global Configuration:**
67
+
68
+ Alternatively, set configuration globally before importing the package:
69
+
70
+ ```html
71
+ <script>
72
+ window.PIE_LOADER_CONFIG = {
73
+ trackPageActions: true,
74
+ maxResourceRetries: 3,
75
+ resourceRetryDelay: 500
76
+ };
77
+ </script>
78
+ <script type="module">
79
+ import '@pie-framework/pie-fixed-player-static';
80
+ </script>
81
+ ```
82
+
83
+ ## Resilient Loading
84
+
85
+ This package includes automatic retry logic for module imports and resource loading:
86
+
87
+ - **Module imports** (math-rendering, bundle, player): 4 attempts with exponential backoff (200ms, 400ms, 800ms)
88
+ - **Runtime resources** (images, audio, video): Configurable retry attempts with exponential backoff
89
+ - Console logging: warnings for retries, errors only for permanent failures
90
+ - New Relic tracking (when enabled): tracks import timing, retries, and failures
91
+
46
92
  ## Events
47
93
 
48
94
  - `load-complete` - Fired when item loads successfully
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  declare module '@pie-framework/pie-fixed-player-static' {
2
- // Add type definitions if needed
3
2
  export {};
4
3
  }
5
4
 
@@ -8,4 +7,30 @@ declare global {
8
7
  interface HTMLElementTagNameMap {
9
8
  'pie-fixed-player': HTMLElement;
10
9
  }
10
+
11
+ interface Window {
12
+ /**
13
+ * Global debug flag for PIE components
14
+ * Set to true to enable debug logging
15
+ */
16
+ PIE_DEBUG?: boolean;
17
+
18
+ /**
19
+ * Global loader configuration for PIE components
20
+ * Alternative to setting loader-config attribute on individual elements
21
+ */
22
+ PIE_LOADER_CONFIG?: {
23
+ trackPageActions?: boolean;
24
+ maxResourceRetries?: number;
25
+ resourceRetryDelay?: number;
26
+ };
27
+
28
+ /**
29
+ * New Relic Browser Agent
30
+ */
31
+ newrelic?: {
32
+ addPageAction(name: string, attributes?: Record<string, any>): void;
33
+ noticeError(error: Error, attributes?: Record<string, any>): void;
34
+ };
35
+ }
11
36
  }
package/dist/index.js CHANGED
@@ -5,33 +5,256 @@
5
5
  // Use async IIFE to ensure sequential loading without top-level await
6
6
  // (Top-level await has bundler compatibility issues with some build tools)
7
7
  (async function initializePieFixedPlayer() {
8
+
9
+ // Cache tracking enabled state to avoid repeated DOM queries and JSON parsing
10
+ let trackingEnabled = null;
11
+
12
+ const isTrackingEnabled = () => {
13
+ // Return cached value if already determined
14
+ if (trackingEnabled !== null) {
15
+ return trackingEnabled;
16
+ }
17
+
18
+ try {
19
+ // Check multiple sources for tracking configuration
20
+ // 1. Check if pie-fixed-player element exists with loader-config attribute
21
+ const playerElement = typeof document !== 'undefined' ? document.querySelector('pie-fixed-player') : null;
22
+ if (playerElement) {
23
+ const loaderConfigAttr = playerElement.getAttribute('loader-config');
24
+ if (loaderConfigAttr) {
25
+ try {
26
+ const loaderConfig = JSON.parse(loaderConfigAttr);
27
+ if (loaderConfig?.trackPageActions === true) {
28
+ trackingEnabled = true;
29
+ return true;
30
+ }
31
+ } catch {
32
+ // Invalid JSON, continue to other checks
33
+ }
34
+ }
35
+ }
36
+
37
+ // 2. Check for global PIE_LOADER_CONFIG
38
+ if (typeof window !== 'undefined' && window.PIE_LOADER_CONFIG?.trackPageActions === true) {
39
+ trackingEnabled = true;
40
+ return true;
41
+ }
42
+ } catch {
43
+ // DOM operations failed, disable tracking
44
+ }
45
+
46
+ // No tracking enabled or error occurred
47
+ trackingEnabled = false;
48
+ return false;
49
+ };
50
+
51
+ // Helper to track with New Relic if enabled
52
+ const trackNewRelicAction = (actionName, attributes) => {
53
+ if (!isTrackingEnabled() || typeof window === 'undefined' || !window.newrelic) {
54
+ return;
55
+ }
56
+
57
+ try {
58
+ window.newrelic.addPageAction(actionName, {
59
+ ...attributes,
60
+ component: 'pie-fixed-player-static',
61
+ timestamp: new Date().toISOString()
62
+ });
63
+ } catch (err) {
64
+ // Silently fail if New Relic throws - don't break the app
65
+ if (typeof window !== 'undefined' && window.PIE_DEBUG) {
66
+ console.debug('[pie-fixed-player-static] New Relic tracking failed:', err);
67
+ }
68
+ }
69
+ };
70
+
71
+ const trackNewRelicError = (error, attributes) => {
72
+ if (!isTrackingEnabled() || typeof window === 'undefined' || !window.newrelic) {
73
+ return;
74
+ }
75
+
76
+ try {
77
+ window.newrelic.noticeError(error, {
78
+ ...attributes,
79
+ component: 'pie-fixed-player-static'
80
+ });
81
+ } catch (err) {
82
+ // Silently fail if New Relic throws - don't break the app
83
+ if (typeof window !== 'undefined' && window.PIE_DEBUG) {
84
+ console.debug('[pie-fixed-player-static] New Relic error tracking failed:', err);
85
+ }
86
+ }
87
+ };
88
+
89
+ const importWithRetry = async (specifier, attempts = 3, baseDelayMs = 200) => {
90
+ const startTime = Date.now();
91
+ let lastError;
92
+
93
+ // Track import start (never throws due to internal try/catch)
94
+ trackNewRelicAction('pie-import-started', {
95
+ specifier,
96
+ maxAttempts: attempts
97
+ });
98
+
99
+ for (let attempt = 1; attempt <= attempts; attempt++) {
100
+ try {
101
+ // Safe debug logging
102
+ try {
103
+ if (typeof window !== 'undefined' && window.PIE_DEBUG) {
104
+ console.debug(`[pie-fixed-player-static] importWithRetry: attempt ${attempt} -> ${specifier}`);
105
+ }
106
+ } catch {
107
+ // Logging failed, continue anyway
108
+ }
109
+
110
+ const result = await import(specifier);
111
+
112
+ // Track successful import (never throws due to internal try/catch)
113
+ const duration = Date.now() - startTime;
114
+ trackNewRelicAction('pie-import-success', {
115
+ specifier,
116
+ attempt,
117
+ duration,
118
+ wasRetried: attempt > 1
119
+ });
120
+
121
+ return result;
122
+ } catch (err) {
123
+ lastError = err;
124
+ const isLastAttempt = attempt === attempts;
125
+
126
+ if (isLastAttempt) {
127
+ // Final attempt failed - safe error logging
128
+ try {
129
+ console.error(`[pie-fixed-player-static] Failed to load ${specifier} after ${attempts} attempts:`, err);
130
+ } catch {
131
+ // Even error logging failed, but continue
132
+ }
133
+
134
+ // Track final failure (never throws due to internal try/catch)
135
+ try {
136
+ const duration = Date.now() - startTime;
137
+ const errorMessage = err && err.message ? err.message : String(err || 'Unknown error');
138
+ trackNewRelicError(new Error(`Import failed: ${specifier}`), {
139
+ specifier,
140
+ attempts,
141
+ duration,
142
+ errorMessage
143
+ });
144
+ } catch {
145
+ // Tracking failed, continue anyway
146
+ }
147
+ } else {
148
+ // Intermediate failure - safe warning logging
149
+ try {
150
+ console.warn(`[pie-fixed-player-static] Import failed (attempt ${attempt}/${attempts}) for ${specifier}, will retry:`, err);
151
+ } catch {
152
+ // Logging failed, continue anyway
153
+ }
154
+
155
+ // Track retry attempt (never throws due to internal try/catch)
156
+ try {
157
+ const errorMessage = err && err.message ? err.message : String(err || 'Unknown error');
158
+ trackNewRelicAction('pie-import-retry', {
159
+ specifier,
160
+ attempt,
161
+ remainingAttempts: attempts - attempt,
162
+ errorMessage
163
+ });
164
+ } catch {
165
+ // Tracking failed, continue anyway
166
+ }
167
+
168
+ const delay = baseDelayMs * Math.pow(2, attempt - 1);
169
+
170
+ // Safe debug logging for retry
171
+ try {
172
+ if (typeof window !== 'undefined' && window.PIE_DEBUG) {
173
+ console.debug(`[pie-fixed-player-static] retrying ${specifier} in ${delay}ms`);
174
+ }
175
+ } catch {
176
+ // Logging failed, continue anyway
177
+ }
178
+
179
+ await new Promise((res) => setTimeout(res, delay));
180
+ }
181
+ }
182
+ }
183
+ throw lastError;
184
+ };
185
+ try {
186
+
187
+ // Initialize global debug flag from URL params (checked BEFORE any imports)
188
+ // Can also be set via: <script>window.PIE_DEBUG = true;</script> before importing this module
189
+ if (typeof window !== 'undefined' && typeof window.PIE_DEBUG === 'undefined') {
190
+ try {
191
+ const params = new URLSearchParams(window.location?.search || '');
192
+ const urlFlag = params.get('pie_debug') || params.get('PIE_DEBUG') || params.get('debug');
193
+ if (urlFlag != null) {
194
+ window.PIE_DEBUG = urlFlag === '' || String(urlFlag).toLowerCase() === 'true' || urlFlag === '1';
195
+ }
196
+ } catch {}
197
+ }
198
+
199
+ // Log debug state if enabled
8
200
  try {
9
- // 1. Dynamically import math-rendering module (bundled with package)
10
- const mathRenderingModule = await import('./math-rendering.js');
201
+ if (typeof window !== 'undefined' && window.PIE_DEBUG) {
202
+ console.debug('[pie-fixed-player-static] Debug logging enabled');
203
+ }
204
+ } catch {}
205
+
11
206
 
12
- // 2. Set globals BEFORE any PIE elements execute
207
+ // 2. Dynamically import math-rendering module (bundled with package)
208
+ const mathRenderingModule = await importWithRetry('./math-rendering.js', 4, 200);
209
+
210
+ // Set globals BEFORE any PIE elements execute
13
211
  if (typeof window !== 'undefined') {
14
212
  // Set BOTH globals:
15
213
  // - @pie-lib/math-rendering: Standard key used by pie-player
16
214
  // - _dll_pie_lib__math_rendering: SystemJS/DLL key used by IIFE bundles
17
215
  window['@pie-lib/math-rendering'] = mathRenderingModule._dll_pie_lib__math_rendering;
18
216
  window['_dll_pie_lib__math_rendering'] = mathRenderingModule._dll_pie_lib__math_rendering;
19
- console.log('[pie-fixed-player-static] Math rendering initialized (both globals set)');
217
+
218
+ // Debug logging (only if window.PIE_DEBUG is true)
219
+ try {
220
+ if (window.PIE_DEBUG) {
221
+ console.debug('[pie-fixed-player-static] Math rendering initialized (both globals set)');
222
+ }
223
+ } catch {}
20
224
  }
21
225
 
22
226
  // 3. NOW load PIE element bundles (IIFE) - these execute immediately
23
227
  // The IIFE must find math-rendering globals already set (which they now are)
24
- await import('./pie-elements-bundle-24d9476.js');
228
+ await importWithRetry('./pie-elements-bundle-351df72.js', 4, 200);
25
229
 
26
230
  // 4. Load pie-fixed-player custom element
27
- await import('./pie-fixed-player.js');
28
-
29
- // 5. Confirm ready
30
- if (typeof window !== 'undefined') {
31
- console.log('[pie-fixed-player-static] Package loaded. PIE elements available via window.pie');
231
+ await importWithRetry('./pie-fixed-player.js', 4, 200);
232
+
233
+ // 5. Mark load completion (performance tracking - never throws)
234
+ try {
235
+ if (typeof window !== 'undefined' && typeof window.performance !== 'undefined') {
236
+ window.performance.mark('PIE-Fixed-Player-Load-Complete');
237
+ }
238
+ } catch {
239
+ // Performance marking failed, continue anyway
240
+ }
241
+
242
+ // Confirm ready (debug logging - never throws)
243
+ try {
244
+ if (typeof window !== 'undefined' && window.PIE_DEBUG) {
245
+ console.debug('[pie-fixed-player-static] Package loaded. PIE elements available via window.pie');
246
+ }
247
+ } catch {
248
+ // Logging failed, continue anyway
32
249
  }
33
250
  } catch (error) {
34
- console.error('[pie-fixed-player-static] Failed to initialize:', error);
251
+ // Note: Individual import failures are already logged as errors above
252
+ // This catch provides a final safety net for unexpected errors
253
+ try {
254
+ console.error('[pie-fixed-player-static] Initialization failed - pie-fixed-player is not available. See errors above for details.');
255
+ } catch {
256
+ // Even final error logging failed - nothing more we can do
257
+ }
35
258
  }
36
259
  })();
37
260