coursecode 0.1.17 → 0.1.18

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.
@@ -525,12 +525,12 @@ When cloud meta tags are present, they **always win** — even if `course-config
525
525
  | Utility | Config Key | Meta Tag | Transport | Events |
526
526
  |---------|-----------|----------|-----------|--------|
527
527
  | `error-reporter.js` | `environment.errorReporting` | `cc-error-endpoint` | POST per error (60s dedup) | `*:error` (14 event types) |
528
- | `data-reporter.js` | `environment.dataReporting` | `cc-data-endpoint` | Batched POST + `sendBeacon` on unload | `assessment:submitted`, `objective:updated`, `interaction:recorded` |
528
+ | `data-reporter.js` | `environment.dataReporting` | `cc-data-endpoint` | Batched POST + `sendBeacon` on unload | `assessment:submitted`, `objective:updated`, `interaction:recorded`, `course:statusChanged`, `channel:message` |
529
529
  | `course-channel.js` | `environment.channel` | `cc-channel-endpoint` + `cc-channel-id` | POST to send, SSE to receive | `channel:message`, `channel:connected`, `channel:disconnected` |
530
530
 
531
531
  **Error Reporter** — Subscribes to all `*:error` events, deduplicates by domain+operation+message (60s window), POSTs to endpoint. Optional `enableUserReports: true` adds "Report Issue" to settings menu. `submitUserReport()` for programmatic user reports.
532
532
 
533
- **Data Reporter** — Queues assessment/objective/interaction records, flushes on batch size (default 10) or timer (default 30s). `sendBeacon` fallback on page unload.
533
+ **Data Reporter** — Queues assessment/objective/interaction/session/channel records, flushes on batch size (default 10) or timer (default 30s). `sendBeacon` fallback on page unload. Also listens to `course:statusChanged` (queues a `session` record on completion) and `channel:message` (queues a `channel` record). Exposes `CourseCode.reportData(type, data)` for course authors to send custom event types.
534
534
 
535
535
  **Course Channel** — Generic pub/sub pipe. `sendChannelMessage(data)` POSTs any JSON to `endpoint/channelId`. SSE listener on same URL bridges incoming messages to EventBus. Exponential backoff reconnect (1s → 30s cap). Content-agnostic — the relay is a dumb fan-out router.
536
536
 
@@ -48,7 +48,7 @@ import { logger } from './utilities/logger.js';
48
48
  import { iconManager } from './utilities/icons.js';
49
49
  import { breakpointManager } from './utilities/breakpoint-manager.js';
50
50
  import { initErrorReporter } from './utilities/error-reporter.js';
51
- import { initDataReporter } from './utilities/data-reporter.js';
51
+ import { initDataReporter, reportData } from './utilities/data-reporter.js';
52
52
  import { initCourseChannel } from './utilities/course-channel.js';
53
53
  import { canvasSlide } from './utilities/canvas-slide.js';
54
54
 
@@ -98,7 +98,10 @@ window.CourseCode = {
98
98
 
99
99
  // Core
100
100
  eventBus,
101
- courseConfig
101
+ courseConfig,
102
+
103
+ // Data reporting public API
104
+ reportData,
102
105
  };
103
106
 
104
107
  // --- Conditional Automation Module Loading ---
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * Data Reporter - Optional external learning data reporting via webhook
3
3
  *
4
- * Batches important learning records (assessments, objectives, interactions) and
5
- * sends them to a configured endpoint. Works across all LMS formats.
4
+ * Batches important learning records (assessments, objectives, interactions,
5
+ * session completion, channel messages, and custom events) and sends them
6
+ * to a configured endpoint. Works across all LMS formats.
6
7
  *
7
8
  * Configuration in course-config.js:
8
9
  * environment: {
@@ -13,6 +14,9 @@
13
14
  * includeContext: true // Include course metadata (default: true)
14
15
  * }
15
16
  * }
17
+ *
18
+ * Public API:
19
+ * CourseCode.reportData(type, data) — Queue a custom record for reporting
16
20
  */
17
21
 
18
22
  import { eventBus } from '../core/event-bus.js';
@@ -39,7 +43,7 @@ const DEFAULT_FLUSH_INTERVAL = 30000; // 30 seconds
39
43
 
40
44
  /**
41
45
  * Queue a record for batched sending
42
- * @param {string} type - Record type: 'assessment', 'objective', 'interaction', 'session'
46
+ * @param {string} type - Record type (assessment, objective, interaction, session, channel, or custom)
43
47
  * @param {Object} data - Record data
44
48
  */
45
49
  function queueRecord(type, data) {
@@ -230,6 +234,26 @@ function handleInteractionRecorded(interaction) {
230
234
  });
231
235
  }
232
236
 
237
+ /**
238
+ * Handle course completion / status change
239
+ * Only reports when the course reaches 'completed' status.
240
+ */
241
+ function handleCourseStatusChanged({ completionStatus, successStatus }) {
242
+ if (completionStatus !== 'completed') return;
243
+
244
+ queueRecord('session', {
245
+ completionStatus,
246
+ successStatus: successStatus || 'unknown'
247
+ });
248
+ }
249
+
250
+ /**
251
+ * Handle incoming channel messages — log them as 'channel' records
252
+ */
253
+ function handleChannelMessage(data) {
254
+ queueRecord('channel', data);
255
+ }
256
+
233
257
  /**
234
258
  * Handle session termination - flush remaining records
235
259
  */
@@ -282,10 +306,12 @@ export function initDataReporter(courseConfig) {
282
306
 
283
307
  logger.info('[DataReporter] Initialized with endpoint:', config.endpoint);
284
308
 
285
- // Subscribe to important events
309
+ // Subscribe to learning events
286
310
  eventBus.on('assessment:submitted', handleAssessmentSubmitted);
287
311
  eventBus.on('objective:updated', handleObjectiveUpdated);
288
312
  eventBus.on('interaction:recorded', handleInteractionRecorded);
313
+ eventBus.on('course:statusChanged', handleCourseStatusChanged);
314
+ eventBus.on('channel:message', handleChannelMessage);
289
315
  eventBus.on('session:beforeTerminate', handleBeforeTerminate);
290
316
 
291
317
  // Emergency flush on page hide (catches tab close, navigation away)
@@ -294,3 +320,23 @@ export function initDataReporter(courseConfig) {
294
320
  window.addEventListener('beforeunload', emergencyFlush);
295
321
  }
296
322
  }
323
+
324
+ /**
325
+ * Public API: Queue a custom data record for reporting.
326
+ * Exposed on window.CourseCode.reportData so course authors can send
327
+ * arbitrary events to the configured data endpoint.
328
+ *
329
+ * @param {string} type - Record type name (e.g. 'custom-metric', 'survey-response')
330
+ * @param {Object} data - Record data payload
331
+ */
332
+ export function reportData(type, data) {
333
+ if (!type || typeof type !== 'string') {
334
+ logger.warn('[DataReporter] reportData: type must be a non-empty string');
335
+ return;
336
+ }
337
+ if (!data || typeof data !== 'object') {
338
+ logger.warn('[DataReporter] reportData: data must be an object');
339
+ return;
340
+ }
341
+ queueRecord(type, data);
342
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coursecode",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "description": "Multi-format course authoring framework with CLI tools (SCORM 2004, SCORM 1.2, cmi5, LTI 1.3)",
5
5
  "type": "module",
6
6
  "bin": {