Updaters take a storage object instead of touching the filesystem: a
publicStorage (what the site serves: data/, assets/) and a privateStorage
(updater state). Two implementations share one small interface
(exists / readJson / writeJson / readBytes / writeText / writeBytes):
- FilesystemStorage over a directory, used by npm run splatnet, so dist/
and storage/ end up exactly as they always have and the S3 sync is
untouched;
- BucketStorage over an R2 bucket binding (MemoryBucket in tests), with a
thin per-run cache: exists() lists a directory once and answers from
memory, readJson() parses a document once, and writeJson() skips the put
when the content is unchanged.
The updater base class and localization processor keep their original
structure with awaits added; the processor reads its document lazily and
writes once per update, as splatoon3.ink's does. Objects written to a
bucket carry the content type and cache-control the S3 sync used to apply.
Tests cover the storage contract (run against both implementations), the
BucketStorage cache behaviour, MemoryBucket's R2-style listing, the
localization processor, the updater base, and each concrete updater.
scripts/compare-data.mjs compares two data directories ignoring SplatNet's
random ordering and ICS timestamps.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The SplatNet client now uses the global fetch, matching splatoon3.ink.
Non-2xx responses throw with the status. getImage returns a Uint8Array
and getText serves the language-file utility, which no longer reaches
into the HTTP client. updateGear fetches Inkipedia directly. axios is
removed; the web build never used it.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Scope ESM to src/app, src/common, src/utility, and test with nested
package.json files, keeping .js filenames and leaving the web build alone.
regions.esm.js becomes regions.js. make-runnable is replaced by a small
action runner and module-alias by relative imports; both are removed.
npm scripts point at explicit entry files.
Output verified identical to the CommonJS run (differences are SplatNet's
own key and array ordering), and the Vue build and tests pass.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>