From ba6e885732f7730174e9e0c421fe851290d71e5c Mon Sep 17 00:00:00 2001 From: Sushant Ipte Date: Fri, 5 Jun 2026 00:17:04 +0530 Subject: [PATCH] chore: prepare @scormflow/* packages for npm publish - Bump all four packages to 0.0.1 - Add publishConfig (public access + provenance) to each package - Add repository, homepage, bugs, keywords to each package.json so the npm listing renders correctly - Add root MIT LICENSE + monorepo README (already npm-facing) - Add per-package LICENSE and README files so each npm page shows real content for v0.0.1 (player and react are explicitly flagged as pre-release namespace claims; sdk and types are functional) Co-Authored-By: Claude Opus 4.7 (1M context) --- LICENSE | 21 +++ README.md | 323 +++++++++++++++++++++++++++++++++++ packages/player/LICENSE | 21 +++ packages/player/README.md | 36 ++++ packages/player/package.json | 36 +++- packages/react/LICENSE | 21 +++ packages/react/README.md | 66 +++++++ packages/react/package.json | 38 ++++- packages/sdk/LICENSE | 21 +++ packages/sdk/README.md | 64 +++++++ packages/sdk/package.json | 37 +++- packages/types/LICENSE | 21 +++ packages/types/README.md | 21 +++ packages/types/package.json | 32 +++- 14 files changed, 743 insertions(+), 15 deletions(-) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 packages/player/LICENSE create mode 100644 packages/player/README.md create mode 100644 packages/react/LICENSE create mode 100644 packages/react/README.md create mode 100644 packages/sdk/LICENSE create mode 100644 packages/sdk/README.md create mode 100644 packages/types/LICENSE create mode 100644 packages/types/README.md diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..937eb11 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 ScormFlow contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..670f809 --- /dev/null +++ b/README.md @@ -0,0 +1,323 @@ +# ScormFlow Client + +> **TypeScript SDK, iframe player, and React components for SCORM, xAPI, and cmi5.** +> Pluggable transport — works with the [`@scormflow/server`](https://github.com/scormflow/scorm-engine) backend, your own backend, or fully client-side via LocalStorage. End-to-end typed. + +[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) +[![npm](https://img.shields.io/npm/v/@scormflow/sdk.svg?label=%40scormflow%2Fsdk)](https://www.npmjs.com/package/@scormflow/sdk) +[![npm](https://img.shields.io/npm/v/@scormflow/react.svg?label=%40scormflow%2Freact)](https://www.npmjs.com/package/@scormflow/react) +[![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178c6)](tsconfig.base.json) + +--- + +## What is ScormFlow Client? + +A small family of npm packages for running SCORM, xAPI, and cmi5 content inside any modern web app. The packages are designed to be **plug-and-play and decoupled** — you can use the React component, drop down to the player, or just import the SDK. You can wire them to our backend, your backend, or skip the backend entirely and persist learner state in `localStorage`. + +If you're building an LMS, an internal training portal, a compliance app, a course preview tool, or anything that needs to host a SCORM/xAPI/cmi5 package and track progress — this is the toolkit. + +### Highlights + +- **Three packages, one stack** — `sdk`, `player`, `react`. Use one, two, or all three. +- **Pluggable transport** — `RestTransport`, `LocalStorageTransport`, `MemoryTransport` ship in the box. Bring your own (Firebase, Supabase, GraphQL, gRPC) by implementing one interface. +- **End-to-end typed** — types are generated from the backend's OpenAPI spec and published as [`@scormflow/types`](packages/types). No drift between server and client. +- **Standards-first** — SCORM 1.2, SCORM 2004, xAPI, and cmi5 share one normalized runtime surface. +- **Framework-agnostic core** — the SDK has zero React/Vue/Angular dependencies. The React package is opt-in. +- **Tiny** — target sizes: SDK < 10 KB gz, Player < 20 KB gz, React < 15 KB gz. ESM + CJS dual-build, fully tree-shakeable. + +--- + +## Packages + +| Package | What it is | npm | +|---------|------------|-----| +| [`@scormflow/sdk`](packages/sdk) | Framework-agnostic TypeScript client. Pluggable `ScormTransport` + REST / LocalStorage / Memory transports. | [`@scormflow/sdk`](https://www.npmjs.com/package/@scormflow/sdk) | +| [`@scormflow/player`](packages/player) | Iframe player + runtime bridge. Injects `window.API` (SCORM 1.2) and `window.API_1484_11` (SCORM 2004). Vanilla JS, no React required. | [`@scormflow/player`](https://www.npmjs.com/package/@scormflow/player) | +| [`@scormflow/react`](packages/react) | React hooks + `` component + ``. | [`@scormflow/react`](https://www.npmjs.com/package/@scormflow/react) | +| [`@scormflow/types`](packages/types) | TypeScript types generated from the backend's OpenAPI spec. | [`@scormflow/types`](https://www.npmjs.com/package/@scormflow/types) | + +--- + +## Install + +Pick the package that matches how you're embedding SCORM. The React package depends on the SDK and the player — install just `@scormflow/react` if you're building a React app: + +```bash +npm install @scormflow/react +# or +pnpm add @scormflow/react +# or +yarn add @scormflow/react +``` + +Other entrypoints: + +```bash +# Vanilla / non-React app +npm install @scormflow/sdk @scormflow/player + +# SDK only (write your own UI) +npm install @scormflow/sdk +``` + +Requirements: Node ≥ 20 for tooling. The runtime works in any evergreen browser. + +--- + +## Quick Start + +### 1. React + our backend + +```tsx +import { + ScormProvider, + ScormPlayer, + ScormClient, + RestTransport, +} from '@scormflow/react'; + +const client = new ScormClient({ + transport: new RestTransport({ + baseUrl: 'https://your-engine.example.com', + apiKey: process.env.NEXT_PUBLIC_SCORMFLOW_KEY!, + }), +}); + +export default function CoursePage({ attemptId }: { attemptId: string }) { + return ( + + console.log('done', r)} + onProgress={(p) => console.log('progress', p)} + /> + + ); +} +``` + +### 2. React + no backend (LocalStorage) + +For demos, previews, offline learning, or "open the .zip and just play it" embeds. + +```tsx +import { + ScormProvider, + ScormPlayer, + ScormClient, + LocalStorageTransport, +} from '@scormflow/react'; + +const client = new ScormClient({ + transport: new LocalStorageTransport({ namespace: 'demo' }), +}); + + + + +``` + +### 3. Vanilla JS — drop-in player + +```ts +import { mountScormPlayer } from '@scormflow/player'; +import { ScormClient, RestTransport } from '@scormflow/sdk'; + +const client = new ScormClient({ + transport: new RestTransport({ baseUrl, apiKey }), +}); + +const player = mountScormPlayer({ + container: '#scorm-root', + attemptId: 'attempt_abc', + client, + onComplete: (result) => console.log(result), +}); +``` + +### 4. Bring your own backend + +Implement the `ScormTransport` interface against Firebase, Supabase, GraphQL, gRPC, or anything else. The player and React layer depend only on this interface — never on the REST transport. + +```ts +import type { ScormTransport } from '@scormflow/sdk'; + +class MyFirebaseTransport implements ScormTransport { + async initialize(attemptId: string) { /* ... */ } + async commit(attemptId: string, values: Record) { /* ... */ } + async terminate(attemptId: string, values?: Record) { /* ... */ } +} + +const client = new ScormClient({ transport: new MyFirebaseTransport(db) }); +``` + +--- + +## Transports + +A `ScormTransport` is the bridge between the in-browser runtime and wherever you want learner state to live. The SDK ships three; you can write your own. + +| Transport | Use case | Backend required? | +|-----------|----------|-------------------| +| `RestTransport` | Default. Talks to a `@scormflow/server` backend. | Yes | +| `LocalStorageTransport` | Browser-only persistence. Demos, offline learning, embedded courses, previews. | No | +| `MemoryTransport` | Tests and ephemeral previews. State vanishes on refresh. | No | + +The runtime surface (`initialize`, `commit`, `terminate`) works with **any** transport. Course management, attempt lifecycle, and analytics are REST-transport-only — they only make sense when you're using the server. + +--- + +## React API + +```tsx +// Provider + + + + +// Drop-in player + ...} + onProgress={(progress) => ...} + onError={(err) => ...} + className="w-full h-screen" +/> + +// Hooks +const { progress, status, score, suspend, resume } = useScorm(attemptId); +const { course, isLoading } = useCourse(courseId); +const { stats } = useCourseAnalytics(courseId); +const { upload, isUploading, progress } = useScormUpload(); +``` + +--- + +## SDK API (excerpt) + +```ts +import { ScormClient, RestTransport } from '@scormflow/sdk'; + +const client = new ScormClient({ + transport: new RestTransport({ baseUrl, apiKey }), +}); + +// REST-transport-only +const course = await client.courses.upload(file); +const attempt = await client.attempts.start({ courseId, learnerId }); +const stats = await client.analytics.forCourse(courseId); + +// Any transport (used by the player) +await client.runtime.initialize(attempt.id); +await client.runtime.commit(attempt.id, { 'cmi.score.raw': '85' }); +await client.runtime.terminate(attempt.id); +``` + +Errors are typed: `ScormHttpError`, `ScormNetworkError`, `ScormTimeoutError`, `ScormAbortError`. Retries with exponential backoff are built in for idempotent operations. + +--- + +## How it fits together + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Your app (React / Next.js / Vite / vanilla) │ +│ │ +│ @scormflow/react ──► @scormflow/player ──► │ +│ ▲ (iframe + window.API) │ +│ │ │ +│ @scormflow/sdk ◄── ScormTransport ──► Backend │ +│ (any) │ +└─────────────────────────────────────────────────────────────┘ +``` + +- The runtime bridge is a **clean-room implementation** of the SCORM 1.2 and 2004 JavaScript APIs. No third-party SCORM libraries are bundled. +- Because we follow the spec, **any spec-compliant course works** — including content authored with pipwerks, scorm-again, Captivate, Storyline, Lectora, iSpring, Articulate Rise, etc. We don't maintain a compatibility matrix; the spec is the contract. + +--- + +## Roadmap + +Checkboxes reflect the actual state of `main`. Source of truth for scope: [`../scope.md`](../scope.md). + +### Phase 1 — MVP +- [x] Monorepo (pnpm workspaces) + TypeScript strict +- [x] `@scormflow/types` package + generation from OpenAPI +- [x] `@scormflow/sdk` package skeleton (ESM + CJS + .d.ts) +- [x] `ScormTransport` interface +- [x] `RestTransport` implementation +- [x] `LocalStorageTransport` implementation +- [x] `MemoryTransport` implementation +- [x] HTTP client with retry + exponential backoff +- [x] Typed error hierarchy (`ScormError`, `ScormHttpError`, `ScormNetworkError`, ...) +- [x] Unit tests (Vitest) for transports + HTTP client +- [ ] `ScormClient` top-level facade (`courses` / `attempts` / `runtime` / `analytics`) +- [ ] Automatic token refresh on `RestTransport` +- [ ] Request / response interceptors +- [ ] `@scormflow/player` — iframe mount + runtime injection (`window.API` / `window.API_1484_11`) +- [ ] Player: commit debouncing + `beforeunload` auto-save with `keepalive` +- [ ] Player: SCORM 1.2 CMI surface +- [ ] Player: SCORM 2004 CMI surface +- [ ] `@scormflow/react` — `ScormProvider` context +- [ ] `@scormflow/react` — `` component +- [ ] `@scormflow/react` — `useScorm`, `useCourse`, `useCourseAnalytics`, `useScormUpload` hooks +- [ ] Player UI (header, footer, progress bar, loading + error states, CSS-variable theming) +- [ ] Examples: `nextjs-app`, `vite-react`, `vanilla-html` +- [ ] First npm release for all four packages + +### Phase 2 — Strong differentiators +- [ ] Offline mode — IndexedDB statement queue + reconciliation +- [ ] xAPI client surface (statements, state, activity profile) +- [ ] cmi5 client surface (launch URL parsing, AU lifecycle) +- [ ] Vue adapter — `@scormflow/vue` +- [ ] Svelte adapter — `@scormflow/svelte` +- [ ] CLI tool — `npx scormflow validate course.zip`, `extract`, `create`, `preview` +- [ ] Analytics widgets — pre-built React dashboard components +- [ ] Certificate viewer — `` + +### Phase 3 — Category-defining +- [ ] Session replay viewer (``) +- [ ] AI insights widgets (BYO provider + key) +- [ ] A11y — keyboard nav, screen reader announcements, focus management +- [ ] i18n — built-in locale support for player UI +- [ ] Course version diff viewer +- [ ] Universal content gateway client (SCORM / xAPI / cmi5 / H5P / HTML / video / PDF) + +--- + +## Development + +```bash +pnpm install +pnpm types:generate # regenerate @scormflow/types from ../scorm-engine/openapi/openapi.yaml +pnpm build # build all packages +pnpm dev # watch all packages in parallel +pnpm typecheck +pnpm test +``` + +Each package has its own `build`, `dev`, `typecheck`, `test` scripts that the root delegates to via `pnpm -r --filter './packages/*'`. + +--- + +## Contributing + +Issues and PRs welcome. Before opening a PR: + +- Run `pnpm typecheck && pnpm test` at the root. +- Match the existing style. +- New SDK surface area should ship with a test. +- The OpenAPI spec lives in the backend repo — if you need a type that doesn't exist yet, open a PR there first and we'll regenerate. + +--- + +## License + +MIT — see [LICENSE](LICENSE). + +## Related repos + +- [`scorm-engine`](https://github.com/scormflow/scorm-engine) — the backend. Headless runtime engine, REST API, built-in LRS (planned), analytics. +- [`scorm-engine-demo`](https://github.com/scormflow/scorm-engine-demo) — reference LMS built on both repos (planned). diff --git a/packages/player/LICENSE b/packages/player/LICENSE new file mode 100644 index 0000000..937eb11 --- /dev/null +++ b/packages/player/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 ScormFlow contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/player/README.md b/packages/player/README.md new file mode 100644 index 0000000..ea1e23f --- /dev/null +++ b/packages/player/README.md @@ -0,0 +1,36 @@ +# @scormflow/player + +> Iframe-based SCORM player and runtime bridge for the browser. Clean-room implementation of the SCORM 1.2 and 2004 JavaScript APIs. + +```bash +npm install @scormflow/player @scormflow/sdk +``` + +## Status + +**Pre-release — `0.0.1` is a namespace claim, not a working build.** The implementation is in progress; track [the roadmap](https://github.com/scormflow/scorm-engine-client#roadmap) for shipping milestones. + +## Planned usage + +```ts +import { mountScormPlayer } from '@scormflow/player'; +import { ScormClient, RestTransport } from '@scormflow/sdk'; + +const client = new ScormClient({ + transport: new RestTransport({ baseUrl, apiKey }), +}); + +const player = mountScormPlayer({ + container: '#scorm-root', + attemptId: 'attempt_abc', + client, + onComplete: (result) => console.log(result), + onProgress: (progress) => console.log(progress), +}); +``` + +The player mounts an iframe, loads the SCO launch URL, and injects `window.API` (SCORM 1.2) and `window.API_1484_11` (SCORM 2004) — wired to whatever `ScormTransport` you configured. + +## License + +MIT diff --git a/packages/player/package.json b/packages/player/package.json index 2d5b547..85a3c3d 100644 --- a/packages/player/package.json +++ b/packages/player/package.json @@ -1,7 +1,7 @@ { "name": "@scormflow/player", - "version": "0.0.0", - "description": "Iframe-based SCORM player and runtime bridge for the browser.", + "version": "0.0.1", + "description": "Iframe-based SCORM player and runtime bridge for the browser. Clean-room implementation of the SCORM 1.2 and 2004 JavaScript APIs.", "license": "MIT", "type": "module", "main": "./dist/index.js", @@ -13,12 +13,40 @@ "require": "./dist/index.cjs" } }, - "files": ["dist", "src"], + "repository": { + "type": "git", + "url": "git+https://github.com/scormflow/scorm-engine-client.git", + "directory": "packages/player" + }, + "homepage": "https://github.com/scormflow/scorm-engine-client/tree/main/packages/player#readme", + "bugs": { + "url": "https://github.com/scormflow/scorm-engine-client/issues" + }, + "keywords": [ + "scorm", + "scorm-1-2", + "scorm-2004", + "scorm-player", + "xapi", + "cmi5", + "elearning", + "iframe-player", + "runtime-bridge" + ], + "publishConfig": { + "access": "public", + "provenance": true + }, + "engines": { + "node": ">=20" + }, + "files": ["dist", "src", "README.md", "LICENSE"], "scripts": { "build": "tsup src/index.ts --format esm,cjs --dts --clean --sourcemap", "dev": "tsup src/index.ts --format esm,cjs --dts --watch", "typecheck": "tsc --noEmit", - "test": "vitest run --passWithNoTests" + "test": "vitest run --passWithNoTests", + "prepublishOnly": "pnpm run typecheck && pnpm run build" }, "dependencies": { "@scormflow/sdk": "workspace:*" diff --git a/packages/react/LICENSE b/packages/react/LICENSE new file mode 100644 index 0000000..937eb11 --- /dev/null +++ b/packages/react/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 ScormFlow contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/react/README.md b/packages/react/README.md new file mode 100644 index 0000000..7534bae --- /dev/null +++ b/packages/react/README.md @@ -0,0 +1,66 @@ +# @scormflow/react + +> React hooks and `` component for ScormFlow. Drop-in SCORM, xAPI, and cmi5 support for any React app. + +```bash +npm install @scormflow/react +``` + +Peer deps: `react >= 18`, `react-dom >= 18`. + +## Status + +**Pre-release — `0.0.1` is a namespace claim, not a working build.** The implementation is in progress; track [the roadmap](https://github.com/scormflow/scorm-engine-client#roadmap) for shipping milestones. + +## Planned usage + +```tsx +import { + ScormProvider, + ScormPlayer, + ScormClient, + RestTransport, +} from '@scormflow/react'; + +const client = new ScormClient({ + transport: new RestTransport({ + baseUrl: 'https://your-engine.example.com', + apiKey: process.env.NEXT_PUBLIC_SCORMFLOW_KEY!, + }), +}); + +export default function CoursePage({ attemptId }: { attemptId: string }) { + return ( + + console.log('done', r)} + /> + + ); +} +``` + +### No backend? Use LocalStorage + +```tsx +import { ScormProvider, ScormPlayer, ScormClient, LocalStorageTransport } from '@scormflow/react'; + +const client = new ScormClient({ transport: new LocalStorageTransport() }); + + + + +``` + +## Planned hooks + +- `useScorm(attemptId)` — runtime state for an attempt +- `useCourse(courseId)` — course metadata +- `useCourseAnalytics(courseId)` — live analytics +- `useScormUpload()` — upload with progress + +## License + +MIT diff --git a/packages/react/package.json b/packages/react/package.json index 528bf53..b2ba80d 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,7 +1,7 @@ { "name": "@scormflow/react", - "version": "0.0.0", - "description": "React hooks and component for ScormFlow.", + "version": "0.0.1", + "description": "React hooks and component for ScormFlow. Drop-in SCORM, xAPI, and cmi5 support for any React app.", "license": "MIT", "type": "module", "main": "./dist/index.js", @@ -13,12 +13,42 @@ "require": "./dist/index.cjs" } }, - "files": ["dist", "src"], + "repository": { + "type": "git", + "url": "git+https://github.com/scormflow/scorm-engine-client.git", + "directory": "packages/react" + }, + "homepage": "https://github.com/scormflow/scorm-engine-client/tree/main/packages/react#readme", + "bugs": { + "url": "https://github.com/scormflow/scorm-engine-client/issues" + }, + "keywords": [ + "scorm", + "scorm-1-2", + "scorm-2004", + "xapi", + "cmi5", + "elearning", + "react", + "react-hooks", + "react-component", + "scorm-player" + ], + "publishConfig": { + "access": "public", + "provenance": true + }, + "engines": { + "node": ">=20" + }, + "sideEffects": false, + "files": ["dist", "src", "README.md", "LICENSE"], "scripts": { "build": "tsup src/index.ts --format esm,cjs --dts --clean --sourcemap --external react", "dev": "tsup src/index.ts --format esm,cjs --dts --watch --external react", "typecheck": "tsc --noEmit", - "test": "vitest run --passWithNoTests" + "test": "vitest run --passWithNoTests", + "prepublishOnly": "pnpm run typecheck && pnpm run build" }, "peerDependencies": { "react": ">=18", diff --git a/packages/sdk/LICENSE b/packages/sdk/LICENSE new file mode 100644 index 0000000..937eb11 --- /dev/null +++ b/packages/sdk/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 ScormFlow contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/sdk/README.md b/packages/sdk/README.md new file mode 100644 index 0000000..d42bd80 --- /dev/null +++ b/packages/sdk/README.md @@ -0,0 +1,64 @@ +# @scormflow/sdk + +> Framework-agnostic TypeScript client for SCORM, xAPI, and cmi5. Pluggable transport — works with the [`scorm-engine`](https://github.com/scormflow/scorm-engine) backend, your own backend, or fully client-side via LocalStorage. + +```bash +npm install @scormflow/sdk +``` + +## Quick start + +```ts +import { ScormClient, RestTransport } from '@scormflow/sdk'; + +const client = new ScormClient({ + transport: new RestTransport({ + baseUrl: 'https://your-engine.example.com', + apiKey: process.env.SCORMFLOW_KEY!, + }), +}); + +await client.runtime.initialize(attemptId); +await client.runtime.commit(attemptId, { 'cmi.score.raw': '85' }); +await client.runtime.terminate(attemptId); +``` + +## Transports + +| Transport | Use case | Backend required? | +|-----------|----------|-------------------| +| `RestTransport` | Default. Talks to a `scorm-engine` backend. | Yes | +| `LocalStorageTransport` | Browser-only persistence. Demos, offline learning, previews. | No | +| `MemoryTransport` | Tests and ephemeral previews. | No | + +Bring your own by implementing the `ScormTransport` interface. + +```ts +import type { ScormTransport } from '@scormflow/sdk'; + +class MyFirebaseTransport implements ScormTransport { + async initialize(attemptId: string) { /* ... */ } + async commit(attemptId: string, values: Record) { /* ... */ } + async terminate(attemptId: string, values?: Record) { /* ... */ } +} +``` + +## Errors + +Typed error hierarchy: + +- `ScormError` — base +- `ScormHttpError` — non-2xx response, includes status + body +- `ScormNetworkError` — fetch / connection failure +- `ScormTimeoutError` — request exceeded timeout +- `ScormAbortError` — caller cancelled the request + +Retries with exponential backoff are built in for idempotent operations on retryable HTTP status codes. + +## Status + +`0.0.1` — pre-1.0, API will churn. See the [roadmap](https://github.com/scormflow/scorm-engine-client#roadmap) for what's shipped and what's planned. + +## License + +MIT diff --git a/packages/sdk/package.json b/packages/sdk/package.json index e89329f..95a2de7 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,7 +1,7 @@ { "name": "@scormflow/sdk", - "version": "0.0.0", - "description": "Framework-agnostic TypeScript client for the ScormFlow runtime engine.", + "version": "0.0.1", + "description": "Framework-agnostic TypeScript client for the ScormFlow runtime engine. Pluggable ScormTransport (REST, LocalStorage, Memory, bring your own).", "license": "MIT", "type": "module", "main": "./dist/index.js", @@ -13,12 +13,41 @@ "require": "./dist/index.cjs" } }, - "files": ["dist", "src"], + "repository": { + "type": "git", + "url": "git+https://github.com/scormflow/scorm-engine-client.git", + "directory": "packages/sdk" + }, + "homepage": "https://github.com/scormflow/scorm-engine-client/tree/main/packages/sdk#readme", + "bugs": { + "url": "https://github.com/scormflow/scorm-engine-client/issues" + }, + "keywords": [ + "scorm", + "scorm-1-2", + "scorm-2004", + "xapi", + "cmi5", + "elearning", + "sdk", + "typescript", + "client", + "pluggable-transport" + ], + "publishConfig": { + "access": "public", + "provenance": true + }, + "engines": { + "node": ">=20" + }, + "files": ["dist", "src", "README.md", "LICENSE"], "scripts": { "build": "tsup src/index.ts --format esm,cjs --dts --clean --sourcemap", "dev": "tsup src/index.ts --format esm,cjs --dts --watch", "typecheck": "tsc --noEmit", - "test": "vitest run" + "test": "vitest run", + "prepublishOnly": "pnpm run typecheck && pnpm run test && pnpm run build" }, "dependencies": { "@scormflow/types": "workspace:*" diff --git a/packages/types/LICENSE b/packages/types/LICENSE new file mode 100644 index 0000000..937eb11 --- /dev/null +++ b/packages/types/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 ScormFlow contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/types/README.md b/packages/types/README.md new file mode 100644 index 0000000..de8cc6e --- /dev/null +++ b/packages/types/README.md @@ -0,0 +1,21 @@ +# @scormflow/types + +TypeScript types generated from the ScormFlow OpenAPI spec. + +```bash +npm install @scormflow/types +``` + +This package contains type definitions only — no runtime. It is used internally by [`@scormflow/sdk`](https://www.npmjs.com/package/@scormflow/sdk) and is exposed in case you need the raw API types for your own integration. + +```ts +import type { components, paths } from '@scormflow/types'; + +type Course = components['schemas']['Course']; +``` + +Part of the [ScormFlow Client](https://github.com/scormflow/scorm-engine-client) monorepo. Backend: [`scorm-engine`](https://github.com/scormflow/scorm-engine). + +## License + +MIT diff --git a/packages/types/package.json b/packages/types/package.json index 154eac4..ba147e3 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@scormflow/types", - "version": "0.0.0", + "version": "0.0.1", "description": "TypeScript types generated from the ScormFlow OpenAPI spec.", "license": "MIT", "type": "module", @@ -12,11 +12,37 @@ "import": "./dist/index.js" } }, - "files": ["dist", "src"], + "repository": { + "type": "git", + "url": "git+https://github.com/scormflow/scorm-engine-client.git", + "directory": "packages/types" + }, + "homepage": "https://github.com/scormflow/scorm-engine-client/tree/main/packages/types#readme", + "bugs": { + "url": "https://github.com/scormflow/scorm-engine-client/issues" + }, + "keywords": [ + "scorm", + "xapi", + "cmi5", + "elearning", + "typescript", + "openapi", + "types" + ], + "publishConfig": { + "access": "public", + "provenance": true + }, + "engines": { + "node": ">=20" + }, + "files": ["dist", "src", "README.md", "LICENSE"], "scripts": { "build": "tsup src/index.ts --format esm --dts --clean", "dev": "tsup src/index.ts --format esm --dts --watch", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit", + "prepublishOnly": "pnpm run typecheck && pnpm run build" }, "devDependencies": { "tsup": "^8.3.0",