@luceosports/play-rendering
v2.11.2
Published
Core canvas rendering library for the LuceoSports platform. Renders play JSON (players, lines, shapes, animations) onto an HTML5 canvas. Published as a UMD bundle via webpack. Consumed by the `animation-playback` and `drawing-animation` frontend submodule
Readme
@luceosports/play-rendering
Core canvas rendering library for the LuceoSports platform. Renders play JSON
(players, lines, shapes, animations) onto an HTML5 canvas. Published as a UMD
bundle via webpack. Consumed by the animation-playback and drawing-animation
frontend submodules.
Install
npm install @luceosports/play-renderingUsage
import { PlayModel, AnimationModel, PlayConstructData } from '@luceosports/play-rendering';
await PlayModel.init(); // load shared assets once
const play = new PlayModel(data, { width: 800 });
const ctx = canvas.getContext('2d')!;
const anim = new AnimationModel(ctx, play);
anim.start(onFinish, onProgress);The complete public type surface lives in src/play-rendering.ts (source) and
dist/types/play-rendering.d.ts (emitted). Anything not exported there is
internal — do not deep-import from dist/types/... subpaths.
Development
npm install # install deps
npm run build # webpack -> dist/play-rendering.js
npm run build:dev # webpack --mode=development
npm run build:types # rimraf dist/types && tsc && node scripts/prune-types.js
npm run check:types-fresh # verify committed dist/types matches a fresh emit
npm run lint # eslint
npm run lint:fix # eslint --fix
npm run verify:pack # build everything + npm pack, prints next stepsThere are no automated tests. Verification is via:
npx tsc --noEmit --emitDeclarationOnly false— type-check sourcenpm run lint- Building both consumer repos (
drawing-animation,animation-playback) against annpm link-ed copy of this lib
The Husky pre-commit hook runs lint-staged plus check:types-fresh. It will
reject any commit where dist/types/ would differ from a fresh build:types
emit — i.e. source changes that didn't regenerate the published types are
caught before they land.
Release process
Releases go directly from master to npm. The library is published as
@luceosports/play-rendering and the dist/ folder is the only thing
shipped in the tarball (controlled by "files": ["dist"] in package.json).
Step 1 — Merge work to master
If you've been working on a feature branch, fast-forward merge to master:
git checkout master
git pull
git merge --ff-only <feature-branch>Confirm working tree is clean before continuing.
Step 2 — Smoke-test the actual publishable tarball
npm run verify:packThat runs npm run build, npm run build:types, then npm pack. It prints the
absolute path to the produced .tgz plus copy-paste commands for installing
into the consumer repos. Run those commands and build each consumer:
cd ../drawing-animation
npm install --no-save "<path-to-tgz>"
npm run build
cd ../animation-playback
npm install --no-save "<path-to-tgz>"
npm run buildIf both build clean, the tarball is safe to publish. The point of this step
over npm link is that npm pack builds the exact tarball npm publish
would ship (respecting "files" and .npmignore), so it catches missing-dist
regressions that a symlinked dev install would mask.
After the smoke-test you can either re-link to keep editing locally:
cd ../drawing-animation && npm link @luceosports/play-rendering
cd ../animation-playback && npm link @luceosports/play-rendering…or leave them on the tarball install until you bump and publish.
Step 3 — Bump version
npm version <patch|minor|major>That edits package.json, creates a commit (default message is the new
version, e.g. 2.9.0), and creates an annotated git tag (v2.9.0).
Semver guidance for this library:
- patch — internal fixes, no public-API change. Bug fixes inside model methods, performance improvements, comment-only docs changes.
- minor — additive public-API change (new exported class/method) or cleanup that's transparent for the known consumers but technically shifts the type surface (e.g. a stricter return type on an existing method).
- major — breaking change to the exports from
src/play-rendering.ts: removed identifier, removed method, changed required parameter, return type widened in a way consumers can't handle. Per.claude/CLAUDE.md's rule: treatsrc/play-rendering.tsas a public contract.
Step 4 — Push commit + tag
git push --follow-tags--follow-tags pushes the v<version> tag along with the version-bump commit.
Step 5 — Publish to npm
You need an authenticated npm session with publish access to the @luceosports
scope. Check first:
npm whoamiIf that returns 401 your token in ~/.npmrc is expired. Re-authenticate via
npm login (browser flow) or by setting a fresh automation token from
npmjs.com/settings → Access Tokens.
A dry-run is cheap and surfaces what would upload:
npm publish --dry-runThe output lists every file going into the tarball plus the final shasum. When you're satisfied, do the real publish:
npm publishThat uploads to https://registry.npmjs.org/@luceosports/play-rendering/-/play-rendering-<version>.tgz
and updates the latest dist-tag. Published versions are effectively
permanent — npm unpublish only works for the first 72 hours and gets
increasingly restricted. Treat publish as irreversible.
Step 6 — Verify the publish landed
npm view @luceosports/play-rendering version
npm view @luceosports/play-rendering@<version> dist.shasumThe shasum should match what npm publish --dry-run reported in Step 5 — if it
does, what landed on npm is byte-identical to what you tested.
Step 7 — Update consumers
Bump the version range in each consumer's package.json and reinstall. For a
clean install (not symlinked), make sure any prior npm link is gone first.
# in each consumer repo:
npm install --save '@luceosports/play-rendering@^<new-version>'
npm run build # smoke-test against the published versionIf a consumer still has a leftover npm link symlink, npm install --save of
a real version replaces the symlink with the published tarball. The
package.json and package-lock.json diffs there should be:
package.json: bumped semver range (^2.8.0→^2.9.0)package-lock.json: new integrity hash + resolved URL pointing at registry.npmjs.org
Commit those in the consumer repo per its own convention.
Optional — pre-release / RC channel
For a soak period before promoting to latest, use the next dist-tag:
npm version prerelease --preid=rc # 2.9.0 -> 2.10.0-rc.0
git push --follow-tags
npm publish --tag next
# consumers opt in: npm install @luceosports/play-rendering@next
# after the soak:
npm dist-tag add @luceosports/play-rendering@<version> latestThis is overkill for the current scale (~2 known consumers, both maintained in this workspace). Skip unless you're shipping something risky enough to want a multi-day bake-in window.
Architecture pointers
- Source layout:
src/index.tsis the runtime entry (webpack reads it for the JS bundle);src/play-rendering.tsis the type entry (tscreads it for the published declarations). Both files must export the same identifier set — the consumer build (Phase 2 verification) catches drift; long-term the structuralconst X: { new (...): I } = XImplassignment insideplay-rendering.tscatches impl-vs-interface drift at compile time. - Pruning:
scripts/prune-types.jsruns aftertscand deletes anydist/types/*.d.tsfile the public entry can't reach. Without it,tscships ~200 internal layer/sport/trait declaration files that no consumer can ever import. - Curated classes:
PlayerModel,LineModel,ShapeModel,NoteModel,FrameModel,AnimationModel,PlayModel,Bezier— each has an explicit interface insrc/play-rendering.tsthat the impl class must satisfy. Adding a method to one of these requires updating the interface, rebuildingdist/types/, and committing both together.
License
ISC. See package.json.
