The site is served by Cloudflare Pages now, so the job that synced the
built dist/ to the public bucket is no longer used.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
It existed to copy dist/ and storage/ between the container and object
storage. Writes now go to storage directly (a directory locally, R2
bindings in the Worker), and a fresh npm run splatnet rebuilds every
public file from SplatNet, so nothing needs a download either. Drops the
sync scripts, the AWS S3 variables from .env.example, and the
@aws-sdk/client-s3, s3-sync-client, and mime-types dependencies.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Every component now declares its prop types (vue/require-prop-types),
which was the bulk of what was left. The rest are one-off fixes:
- two <template> wrappers with no directive are removed (no-lone-template);
- the region dropdown's loop variable no longer shadows the region prop
(no-template-shadow);
- the Splatfest winner bar renders the winning team's name as a real
<span> inside the translated sentence instead of injecting markup with
v-html (no-v-html).
The lint workflow's --max-warnings 0 now passes.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
updateAll() only runs the updaters now. The local (Node) flavour, which
also uploads to S3 when configured, lives in src/app/local.js next to the
filesystem storage wiring, and the entry points call that. The storage
barrel no longer re-exports FilesystemStorage. With both gone, the
updater tree bundles for a non-Node target with no unresolved imports.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
utilities.js is the filesystem helper module the posters still use, and
the schedules updater only needed the time helper from it. With the
helper in its own module the updater import graph no longer pulls in
node:fs, which is what the Worker bundle needs. Also applies the
remaining ESLint fixes outside src/web.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Copied from splatoon3.ink: lint on pushes to main and on pull requests,
failing on any warning, and npm run lint-fix to apply fixes locally.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The updaters run in the container today and in a Worker next, and
@sentry/node cannot be bundled into a Worker. Both @sentry/node and
@sentry/cloudflare are built on @sentry/core, where captureException
lives, so the updater base class imports from core and lands on whichever
client the entry point initialized. The Node entry point keeps
initializing @sentry/node; the Worker will use @sentry/cloudflare.
The two packages must stay on the same version: Sentry keys its global
carrier by version, and a split silently drops events. A test pins the
routing.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Formatting only (template indentation, attribute order, self-closing
tags, semicolons, trailing commas), from `eslint --fix src/web`. These
rules come from vue2-recommended, which the previous config also extended;
vue-cli-service lint used to apply them silently on save.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ESLint moves to a flat config (eslint.config.mjs) with the same rules,
run directly by npm run lint; @vue/cli-plugin-eslint is dropped since the
Vue build does not need it. With a parser that understands import
attributes, the bundled data files (brands, skills, gear, finalFest,
shiftyStations) are imported with `with { type: 'json' }`, which Node and
the Workers bundler both support, instead of being read through node:fs.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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>