scorm-again

repository·master·Indexed 43 days ago

https://github.com/jcputney/scorm-again

A modern JavaScript runtime library for SCORM 1.2 and SCORM 2004 (version 3.3.8). It is designed to be LMS-agnostic and supports advanced features including cross-frame communication, offline data synchronization, and full SCORM 2004 sequencing with activity trees, rule parsing, and state persistence.

Tokens
182.4K
Snippets
422
Records
539
Agent score
55%

What's inside scorm-again

  1. Overview of scorm-again

    master

    scorm-again is a modern, fully-tested JavaScript runtime for SCORM 1.2 and SCORM 2004. It acts as a bridge between SCORM content and a Learning Management System (LMS) by implementing the SCORM API specifications.

    Key characteristics:

    • LMS-Agnostic: It can run without a backing LMS by logging function calls and data instead of committing them.
    • Modular Architecture: It separates core APIs (Scorm12API and Scorm2004API) from service layers like HTTP communication, validation, and data serialization.
    • TypeScript Native: Includes comprehensive type definitions for type safety and IDE support.
  2. Understand the docs-site directory layout

    master

    The documentation site is built with VitePress and follows this structure:

    • docs/: Contains the documentation pages, served at /scorm-again/docs/.
    • index.md: The landing page of the site.
    • demo.md: The index for interactive demos.
    • public/: Contains static assets. This includes the demo/ harness pages, where the CI process drops the built library into public/demo/dist/.
    • .vitepress/config.ts: The central configuration file for navigation, sidebars, search, and theme settings.
  3. Enable SCORM 2004 Sequencing

    master

    v3.0.0 introduces a complete implementation of SCORM 2004 4th Edition sequencing. If you provide a sequencing configuration object, the engine manages:

    • Activity tree management
    • Navigation requests (e.g., continue, previous, choice, jump)
    • Sequencing rules (pre/post/exit conditions)
    • Rollup rules for status propagation
    • Global objectives across SCOs
    • Selection and randomization

    Note: If you do not configure the sequencing setting, the behavior remains unchanged from v2.6.5.

  4. Configure SCORM 2004 Global Objectives

    master

    SCORM 2004 supports global objectives that persist across SCO transitions and can be shared between activities via objective mappings.

    To use them, include host-defined objective IDs in the globalObjectiveIds array within the Settings object. Note that you should not duplicate target IDs from the activity tree's mapInfo entries in this array.

    For LMS integration, structured commits include a synchronized globalObjectives snapshot. You must persist this snapshot per registration and restore it using restoreGlobalObjectiveSnapshot() before initial delivery.

    const api = new Scorm2004API({
      renderCommonCommitFields: true,
      // Only host-defined rows exposed directly to CMI belong here.
      globalObjectiveIds: ['host_defined_objective'],
      sequencing: {
        // ... sequencing configuration with mapInfo
      }
    });
  5. How SCORM 1.2 Multi-SCO support works

    master

    Since SCORM 1.2 lacks a native sequencing specification, navigation between SCOs must be managed by the LMS. The scorm-again utilities provide three core building blocks to facilitate this:

    1. State Tracking: Uses ScoStateTracker to monitor completion, scores, and time spent for each individual SCO.
    2. Navigation: Uses Scorm12Sequencer to determine the next or previous SCO and handle exit actions.
    3. Rollup: Uses CourseRollupCalculator to aggregate individual SCO data into course-level metrics (e.g., total course score and overall completion status).

    In a typical architecture, the Scorm12API communicates with the SCO content (running in an iframe) via postMessage or direct calls. The Scorm12Sequencer updates the ScoStateTracker during LMSCommit or LMSFinish events, and the CourseRollupCalculator derives the final course state from that tracked data.

  6. Follow naming conventions for TypeScript entities

    master

    Use the following casing rules to maintain consistency:

    • PascalCase: Class names, interfaces, and type aliases.
    • camelCase: Variables, functions, and method names.
    • UPPER_SNAKE_CASE: Constants and enum values.

    Special Prefix Rules:

    • Prefix interfaces with I when they define a contract for a class (e.g., IBaseAPI).
    • Prefix private class members with an underscore (e.g., _checkObjectHasProperty).
  7. Understand the SCORM offline data flow

    master

    The system uses a queued synchronization model to handle intermittent connectivity:

    1. User Interaction: Occurs within the course (WebView).
    2. API Call: The course calls the SCORM API.
    3. Library Logic: The scorm-again library checks connectivity:
      • Online: Sends data to the LMS immediately via the configured lmsCommitUrl.
      • Offline: Queues the data in localStorage.
    4. Reconnection: When NetInfo detects the device is back online, the library auto-syncs the queued data.
    5. UI Feedback: The library emits sync events (e.g., OfflineDataSyncing, OfflineDataSynced) via postMessage to the React Native layer to update the UI (e.g., showing a sync indicator).
  8. Configure SCORM 2004 Sequencing via Activity Tree

    master

    The Activity Tree defines the structure and behavior of a course. Each node in the tree represents an activity and contains configuration for sequencing, controls, and rollup rules.

    Key properties for each activity node include:

    • id: Unique activity identifier.
    • title: Display name.
    • isVisible: Whether the activity appears in navigation.
    • isActive: Whether the activity is currently active.
    • isSuspended: Whether the activity is currently suspended.
    • attemptLimit: Maximum allowed attempts (null for unlimited).
    • children: An array of nested activity objects.
    • sequencingRules, sequencingControls, rollupRules: Configuration objects defining how the activity behaves within the course flow.
    {
      id: "root",
      title: "Course Title",
      isVisible: true,
      isActive: false,
      isSuspended: false,
      attemptLimit: null,
      children: [
        {
          id: "module-1",
          title: "Module 1",
          children: [...],
          sequencingRules: {...},
          sequencingControls: {...},
          rollupRules: {...},
          objectives: [...]
        }
      ],
      sequencingControls: {...},
      sequencingRules: {...},
      rollupRules: {...}
    }
  9. Key features of scorm-again

    master

    scorm-again provides several advanced features for SCORM implementations:

    • SCORM 2004 Sequencing: Full support for navigation requests (start, continue, previous, choice, jump, exit, suspend, etc.), activity tree management, sequencing rules (pre-condition, post-condition, exit), and rollup rules.
    • Cross-Frame Communication: Allows running SCORM content in sandboxed iframes while communicating with the SCORM API in the parent frame. This supports cross-origin iframes and provides synchronous API behavior with asynchronous cache updates.
    • Offline Support: Automatically stores and synchronizes SCORM data when connectivity is lost, making it suitable for mobile and remote learning.
    • Synchronous Commits: Implements blocking commits that return actual LMS success/failure responses to prevent data loss.
    • Event System: Provides listeners to track all API interactions for monitoring or custom UI.
    • Multiple Data Formats: Supports JSON, flattened, and parameter-based data commit formats.
  10. Understand the Offline Data Sync Lifecycle

    master

    When the device regains connectivity, the OfflineStorageService.sync() process is triggered. The lifecycle follows these steps:

    1. Detection: NetInfo detects an online status and dispatches a scorm-again:network-status event with { online: true }.
    2. Initialization: OfflineStorageService.sync() is called, emitting an OfflineDataSyncing event. The WebView receives a postMessage({ type: 'sync', status: 'start' }) to update the UI (e.g., setting isSyncing to true).
    3. Execution: The service retrieves queued commits from localStorage and attempts to send HTTP requests to the LMS.
    4. Resolution:
      • On Success: localStorage is cleared, and an OfflineDataSynced event is emitted. The WebView receives postMessage({ type: 'sync', status: 'success' }) to update the UI and notify the user.
      • On Error: Data is retained in localStorage, and an OfflineDataSyncFailed event is emitted. The WebView receives postMessage({ type: 'sync', status: 'error' }) to notify the user. The system will retry later.
    ### Offline Data Sync (Coming Back Online)
    

    NetInfo detects online │ └─► Dispatch 'scorm-again:network-status' { online: true } │ └─► OfflineStorageService.sync() │ ├─► Emit 'OfflineDataSyncing' event │ │ │ └─► postMessage({ type: 'sync', status: 'start' }) │ └─► setIsSyncing(true) │ ├─► Retrieve queued commits from localStorage ├─► Send HTTP requests to LMS │ ├─► On success: │ ├─► Clear localStorage │ ├─► Emit 'OfflineDataSynced' event │ │ │ │ │ └─► postMessage({ type: 'sync', status: 'success' }) │ │ ├─► setIsSyncing(false) │ │ └─► Alert.alert('Sync Complete') │ └─► Return success │ └─► On error: ├─► Keep data in localStorage ├─► Emit 'OfflineDataSyncFailed' event │ │ │ └─► postMessage({ type: 'sync', status: 'error' }) │ ├─► setIsSyncing(false) │ └─► Alert.alert('Sync Failed') └─► Retry later

  11. Understand the Player Wrapper architecture

    master

    A SCORM player wrapper is a UI layer that orchestrates the relationship between the SCO content and the LMS backend.

    Core Components

    • Content Frame: An iframe where the SCO runs.
    • Navigation Controls: Buttons for prev, next, and exit.
    • Course Menu: A Table of Contents (TOC) that displays SCO status indicators.
    • Progress Display: Visual indicators for completion percentage and scores.

    Data and Event Flow

    1. API Calls: The SCO (inside the iframe) calls methods like LMSSetValue on the window.API object.
    2. Event Emission: scorm-again intercepts these calls and fires events (e.g., LMSSetValue).
    3. UI Update: The Player Wrapper listens for these events via api.on() and updates the UI state (Menu, Progress Bar, Navigation) and persists data to the backend or localStorage.
    4. Backend Sync: The SCORM API handles the HTTP communication to the LMS backend.
  12. Determine SCORM Entry Mode

    master

    When launching a SCORM session, the cmi.entry value (the entry mode) is determined by whether previous state exists and how the last session ended.

    Logic Flow:

    1. No previous state: Always set entry = "ab-initio".
    2. Has previous state:
      • If the last exit was "suspend": Set entry = "resume".
      • If the last exit was NOT "suspend": Set entry = "ab-initio" (or "" for SCORM 2004 review mode).