aispritejs 0.5.5 → 0.5.7

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/llms-full.txt CHANGED
@@ -14,7 +14,7 @@ The short index lives at `llms.txt` (see https://llmstxt.org/).
14
14
  # aispritejs
15
15
 
16
16
  [![npm version](https://img.shields.io/npm/v/aispritejs.svg)](https://www.npmjs.com/package/aispritejs)
17
- [![CI](https://github.com/yshengliao/aispritejs/actions/workflows/ci.yml/badge.svg)](https://github.com/yshengliao/aispritejs/actions/workflows/ci.yml)
17
+ [![CI](https://github.com/islumina/aispritejs/actions/workflows/ci.yml/badge.svg)](https://github.com/islumina/aispritejs/actions/workflows/ci.yml)
18
18
  [![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE)
19
19
  [![AI Generated](https://img.shields.io/badge/AI_Generated-Claude_Code_Opus_4.8-blueviolet.svg)](https://www.anthropic.com/claude-code)
20
20
  [![繁體中文](https://img.shields.io/badge/lang-繁體中文-red.svg)](README_ZHTW.md)
@@ -25,6 +25,8 @@ The short index lives at `llms.txt` (see https://llmstxt.org/).
25
25
 
26
26
  Part of the **ai\*js** family: zero cross-package dependencies, framework-agnostic core, AI-readable docs.
27
27
 
28
+ > **Status: 0.5.7 — aligned with the ai\*js family version line.** Renderer-agnostic core plus `/pixi`, `/atlas`, `/schema` subpaths; hardened atlas/graph validation. See [CHANGELOG.md](CHANGELOG.md) for history.
29
+
28
30
  ## Why aispritejs
29
31
 
30
32
  - **Input-driven, not name-driven.** You set parameters (`speed=4`, `isGrounded=false`, `fireTrigger("jump")`), not animation names. Visual transitions live in data, decoupled from game code.
@@ -269,9 +271,7 @@ pnpm example:explosion # 6-frame play-once FX via the /pixi adapter
269
271
 
270
272
  ## Status
271
273
 
272
- **v0.1.3 — docs patch.** Adds a "When you DON'T need aispritejs" threshold and a complete, runnable 6-frame explosion (play-once FX) quickstart for the `/pixi` adapter; no source or API changes. v0.1.0 shipped all roadmap modules (1–4): the renderer-agnostic core (`.`), the PixiJS v8 adapter (`aispritejs/pixi`), the atlas parser (`aispritejs/atlas`), and the JSON Schema (`aispritejs/schema`); v0.1.1 added OIDC/SLSA publish provenance and v0.1.2 hardened validation — compile-time rejection of non-finite `speed` / `duration` / `defaultFrameDuration`, plus a runtime clamp of non-finite or non-positive `dt` (`dt <= 0`) to `0` in `update()`. See [CHANGELOG.md](CHANGELOG.md) for the full history. Zero runtime dependencies; the root import graph contains no `pixi.js`; `pixi.js` is an optional, type-only peer used only by the `/pixi` subpath.
273
-
274
- `aispritejs` is the newest package in the **ai\*js** family and follows its **own independent version line** — the `0.1.x` series reflects this package's own maturation, not alignment with any sibling's version number. Low usage in a given game (e.g. one built on static sprites) is expected, not a defect.
274
+ **Aligned with the ai\*js family version line.** The package version is synchronised with the shared family version (`0.5.x` — the banner above and [CHANGELOG.md](CHANGELOG.md) carry the exact release). All four roadmap modules are live: the renderer-agnostic core (`.`), the PixiJS v8 adapter (`aispritejs/pixi`), the atlas parser (`aispritejs/atlas`), and the JSON Schema (`aispritejs/schema`). Prior hardening waves delivered compile-time rejection of non-finite `speed` / `duration` / `defaultFrameDuration`, runtime clamping of non-finite or non-positive `dt` to `0` in `update()`, and named-error coverage for hostile atlas shapes. Zero runtime dependencies; the root import graph contains no `pixi.js`; `pixi.js` is an optional, type-only peer used only by the `/pixi` subpath.
275
275
 
276
276
  ## Roadmap
277
277
 
@@ -294,6 +294,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
294
294
 
295
295
  ## [Unreleased]
296
296
 
297
+ ## [0.5.7] - 2026-06-10
298
+
299
+ ### Fixed
300
+
301
+ - **`/pixi` adapter prototype-key lookup** — the missing-texture guard now uses `Object.hasOwn` instead of the `in` operator (mirroring the core's 0.5.x hasOwn fixes), so atlas frame keys like `"constructor"` / `"toString"` no longer resolve through `Object.prototype`. (Review wave 2026-06-10, SPR-S-01.)
302
+ - A `when` array containing `null` / non-object entries is rejected by `parseAtlas` with `InvalidAtlasError` instead of crashing later in compilation with a bare `TypeError`. (SPR-S-02.)
303
+ - An input `default` whose runtime type contradicts the declared `type` (e.g. `{ "type": "number", "default": "5" }`) is rejected with `InvalidGraphError` instead of being silently adopted into the input store. (SPR-S-03.)
304
+ - The internal signal's `clear()` (and therefore `dispose()`) now runs each listener's cleanup, detaching abort hooks from caller-owned `AbortSignal`s — a long-lived signal no longer accumulates dead listeners. (SPR-R-01.)
305
+
306
+ ### Changed
307
+
308
+ - **Code splitting enabled (`tsup splitting: true`)** — each subpath bundle previously inlined its own copy of the shared core, so an `InvalidGraphError` thrown via `aispritejs/atlas`'s `loadAtlas` failed `instanceof` checks against the root export. Shared chunks restore cross-subpath class identity; the new `verify:dist` smoke asserts it (ESM + CJS). `check:size` now measures each entry's transitive chunk closure (index 4,175 / pixi 4,852 / atlas 5,216 B gzip measured; ~350 B of that is this wave's validation/cleanup code).
309
+ - Supply-chain and release hardening: CI/publish actions SHA-pinned, npm CLI pinned (`11.16.0`), `permissions: contents: read` on CI, job timeouts, `npm publish --ignore-scripts`, manual dispatch defaults to dry-run, new `verify:docs` banner gate, two-stage typecheck (tests are now type-checked), `llms-full.txt` embeds `STABILITY.md`.
310
+
311
+ ### Docs
312
+
313
+ - README `## Status` section rewritten: the version line now tracks the ai\*js family (the previous "own independent version line" claim was stale); normalised status banners added (EN + ZHTW); the compiled state's `frameKeys` alias contract documented (don't mutate atlas animations while a machine is live).
314
+
315
+ ## [0.5.6] - 2026-06-09
316
+
317
+ ### Added
318
+
319
+ - `PixiSpriteAnimator` now exposes `onComplete` / `onStateChange`, delegating directly to the core animator.
320
+
297
321
  ## [0.5.5] - 2026-06-08
298
322
 
299
323
  ### Changed
@@ -433,12 +457,74 @@ parser, and JSON Schema (roadmap modules 1–4).
433
457
  / lines (above the family floor of 95 / 90 / 100 / 100). Core gzip ≈ 3.5 KB.
434
458
  - OIDC + SLSA provenance publish on tag-push.
435
459
 
436
- [Unreleased]: https://github.com/islumina/aispritejs/compare/v0.5.5...HEAD
460
+ [Unreleased]: https://github.com/islumina/aispritejs/compare/v0.5.6...HEAD
461
+ [0.5.6]: https://github.com/islumina/aispritejs/compare/v0.5.5...v0.5.6
437
462
  [0.5.5]: https://github.com/islumina/aispritejs/releases/tag/v0.5.5
438
- [0.1.3]: https://github.com/yshengliao/aispritejs/compare/v0.1.2...v0.1.3
439
- [0.1.2]: https://github.com/yshengliao/aispritejs/compare/v0.1.1...v0.1.2
440
- [0.1.1]: https://github.com/yshengliao/aispritejs/compare/v0.1.0...v0.1.1
441
- [0.1.0]: https://github.com/yshengliao/aispritejs/releases/tag/v0.1.0
463
+ [0.1.3]: https://github.com/islumina/aispritejs/compare/v0.1.2...v0.1.3
464
+ [0.1.2]: https://github.com/islumina/aispritejs/compare/v0.1.1...v0.1.2
465
+ [0.1.1]: https://github.com/islumina/aispritejs/compare/v0.1.0...v0.1.1
466
+ [0.1.0]: https://github.com/islumina/aispritejs/releases/tag/v0.1.0
467
+
468
+ ---
469
+
470
+ <!-- ===== STABILITY.md ===== -->
471
+
472
+ # Stability
473
+
474
+ This document defines the stability tier of every public symbol exported by
475
+ `aispritejs`. Tiers govern what breaks may occur in future minor / major bumps.
476
+ The public API freezes at 1.0.0.
477
+
478
+ ## Stable (since 0.1.0)
479
+
480
+ Fully stable. Breaking changes only at a major version bump (1.0+).
481
+
482
+ - **Factory** — `createSpriteAnimator(graph)`.
483
+ - **`SpriteAnimator` methods** — `setInput`, `fireTrigger`, `update`, `reset`,
484
+ `dispose`, `onStateChange`, `onComplete`.
485
+ - **`SpriteAnimator` accessors** — `activeState`, `activeFrameKey`,
486
+ `activeFrameIndex`, `disposed`.
487
+ - **Error classes** — `InvalidGraphError`, `UnknownInputError`,
488
+ `InputTypeError`, `SpriteAnimatorDisposedError`.
489
+ - **Types** — `SpriteGraph`, `InputDef` (`NumberInputDef` / `BooleanInputDef` /
490
+ `TriggerInputDef`), `StateDef`, `TransitionDef`, `TransitionCondition`,
491
+ `ConditionOp`, `FrameTiming`, `StateChangeHandler`, `CompleteHandler`,
492
+ `ListenerOptions`, `Unsubscribe`.
493
+ - **`aispritejs/pixi`** — `createPixiSpriteAnimator(sprite, graph, textures,
494
+ options?)` binding the core to a PixiJS v8 `Sprite`, honouring per-frame
495
+ `duration` and the atlas `anchor` (`texture.defaultAnchor`).
496
+ `MissingTextureError`, `PixiSpriteAnimator`, `PixiSpriteAnimatorOptions`,
497
+ `TextureMap`. `pixi.js` is an **optional**, type-only `peerDependency`,
498
+ imported only by this subpath.
499
+ - **`aispritejs/atlas`** — `parseAtlas(atlas, control?)`,
500
+ `loadAtlas(atlas, control?)`, `InvalidAtlasError`, `SpriteControl`. Consumes a
501
+ PixiJS-v8 atlas, ignores any foreign event-driven `states` block, and fails
502
+ fast. JSON Schema shipped at `schemas/aispritejs-graph.schema.json` (exported
503
+ as `aispritejs/schema`). Pure, zero-dependency.
504
+
505
+ ### Behavioural contract (stable)
506
+
507
+ These semantics are part of the stable surface and are pinned by tests:
508
+
509
+ - `update(dt)` order: advance `dt × speed` (negative clamps to `0`) → evaluate
510
+ transitions → compute frame → `onComplete` then `onEnd`.
511
+ - Transition resolution: `priority` desc, then declared order; first *effective*
512
+ transition wins. A self-targeting transition is effective only if it consumes
513
+ a Trigger.
514
+ - Triggers persist until consumed; one fire causes at most one transition.
515
+ - Non-looping clips hold the last frame and fire `onComplete` exactly once;
516
+ looping clips wrap and never complete.
517
+ - `defaultFrameDuration` is `100` ms; `speed` defaults to `1`.
518
+ - Determinism: identical input + `dt` sequences ⇒ identical frame sequences.
519
+
520
+ ## Experimental
521
+
522
+ None as of 0.1.0.
523
+
524
+ ## Draft (planned, not implemented)
525
+
526
+ All roadmap modules (1–4) are implemented. No draft APIs outstanding; the next
527
+ milestone is the 1.0.0 public-API freeze.
442
528
 
443
529
  ---
444
530
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aispritejs",
3
- "version": "0.5.5",
3
+ "version": "0.5.7",
4
4
  "description": "Input-driven, renderer-agnostic 2D sprite animation runtime — a tiny, Rive-like visual state machine driven by Number / Boolean / Trigger inputs. JSON transition graph, deterministic update(dt), zero runtime dependencies. Browser / Node / Bun / Deno / WebView / Worker friendly.",
5
5
  "keywords": [
6
6
  "sprite",
@@ -66,15 +66,17 @@
66
66
  "test:watch": "vitest",
67
67
  "lint": "biome check src test",
68
68
  "format": "biome format --write src test",
69
- "typecheck": "tsc --noEmit",
69
+ "typecheck": "tsc --noEmit && tsc -p tsconfig.test.json --noEmit",
70
+ "verify:docs": "node scripts/verify-docs.mjs",
70
71
  "verify:exports": "node scripts/verify-exports.mjs",
72
+ "verify:dist": "node scripts/check-dist-subpaths.mjs",
71
73
  "check:size": "node scripts/check-size.mjs",
72
74
  "build:llms": "node scripts/build-llms-full.mjs",
73
75
  "verify:llms": "node scripts/build-llms-full.mjs --check",
74
76
  "coverage": "vitest run --coverage",
75
77
  "example:platformer": "tsx examples/01-platformer-inputs/index.ts",
76
78
  "example:explosion": "tsx examples/02-explosion-pixi/index.ts",
77
- "prepublishOnly": "pnpm typecheck && pnpm lint && pnpm coverage && pnpm build && pnpm verify:exports && pnpm verify:llms && pnpm check:size"
79
+ "prepublishOnly": "pnpm typecheck && pnpm lint && pnpm verify:docs && pnpm coverage && pnpm build && pnpm verify:dist && pnpm verify:exports && pnpm verify:llms && pnpm check:size"
78
80
  },
79
81
  "peerDependencies": {
80
82
  "pixi.js": "^8.0.0"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://github.com/yshengliao/aispritejs/schemas/aispritejs-graph.schema.json",
3
+ "$id": "https://github.com/islumina/aispritejs/schemas/aispritejs-graph.schema.json",
4
4
  "title": "aispritejs input-driven sprite graph",
5
5
  "description": "The aispritejs control graph augmenting a PixiJS-v8-native atlas. The universal `animations` / `frames` blocks plus the input-driven `inputs` / `states` / `transitions`. A foreign event-driven `states` block (the FSM `{ initial, definitions }` shape) is NOT described here and is ignored by the parser. The parser mirrors these constraints in code (fail-fast); this file is the canonical spec for editors and external validation.",
6
6
  "type": "object",