Files
ps5upload/client/eslint.config.mjs
T
phantomptrandClaude Opus 5.5 99dda9acb8 console page: build, shell, controller navigation
The page the helper serves on the PS5 itself: client/src/console/ built by
vite.console.config.ts into one self-contained dist-console/index.html
(script and styles inlined, safari13, 253 KiB raw / 84.5 KiB gzip; the
build fails over 450 KiB raw or 150 KiB gzip). payload/Makefile gzips it
into build/webui_page.c and the helper serves it at GET /, with
GET /api/token for the per-start token.

- Shell: top bar (logo, console chip from /api/status), rail of the
  implemented sections (Home, Files, Settings placeholders), hint bar
  showing only verified bindings, reload banner on a 401.
- nav.ts: spatial focus (aligned neighbours first), the R11 default input
  table (keyboard + Gamepad "standard", all unverified), D-pad repeat.
- api.ts: token fetched once, X-PS5U-Token on every POST, 401 → expired.
- strings.ts: cw_* keys from all 21 locales via build-console-strings.mjs
  (vm-eval like the i18n gate), English fallback.
- CI: client npm ci before every make payload.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RxCGb8Asp1A1AQYiv1kbgS
2026-10-17 05:23:26 -07:00

122 lines
4.0 KiB
JavaScript

import js from "@eslint/js";
import reactHooks from "eslint-plugin-react-hooks";
import tseslint from "typescript-eslint";
import localRules from "./eslint-rules/no-untranslated-jsx.mjs";
import requireAssertOk from "./eslint-rules/require-assert-ok.mjs";
const browserGlobals = {
AbortController: "readonly",
Blob: "readonly",
CustomEvent: "readonly",
Event: "readonly",
EventSource: "readonly",
File: "readonly",
FormData: "readonly",
HTMLAnchorElement: "readonly",
HTMLElement: "readonly",
Image: "readonly",
KeyboardEvent: "readonly",
MouseEvent: "readonly",
RequestInit: "readonly",
Response: "readonly",
URL: "readonly",
URLSearchParams: "readonly",
console: "readonly",
crypto: "readonly",
document: "readonly",
fetch: "readonly",
localStorage: "readonly",
navigator: "readonly",
setInterval: "readonly",
setTimeout: "readonly",
clearInterval: "readonly",
clearTimeout: "readonly",
window: "readonly",
};
export default tseslint.config(
{
ignores: [
"dist/**",
"dist-console/**",
"node_modules/**",
"src-tauri/**",
"coverage/**",
"vite.config.ts",
// Build-time scripts run in Node, not the browser, so the
// browser-globals config here gives false positives ("console"
// unknown). They're tooling, not shipped code.
"scripts/**",
// Plain-ES5 boot guard served as-is, outside the TS/ESM toolchain.
"public/**",
],
},
js.configs.recommended,
...tseslint.configs.recommended,
{
files: ["src/**/*.{ts,tsx}"],
languageOptions: {
ecmaVersion: "latest",
sourceType: "module",
globals: browserGlobals,
},
plugins: {
"react-hooks": reactHooks,
local: {
rules: { ...localRules.rules, ...requireAssertOk.rules },
},
},
rules: {
...reactHooks.configs.recommended.rules,
"react-hooks/immutability": "off",
"react-hooks/set-state-in-effect": "off",
// No BigInt literals. The build targets safari13 (see vite.config.ts)
// so the app survives old Android System WebViews, and BigInt is ES2020
// that — unlike `?.` or `??=` — CANNOT be down-levelled. Rolldown emits
// the literal as-is with a TOLERATED_TRANSFORM warning, which is easy to
// miss because the build still succeeds; on a WebView without BigInt it
// is a parse-time SyntaxError for the whole chunk, so it takes out the
// entire bundle rather than the one feature that used it.
//
// This has been walked into twice (lib/wakeState.ts, then
// screens/Profile). Both times the fix was exact string arithmetic,
// which is what this rule points you at.
"no-restricted-syntax": [
"error",
{
selector: "Literal[bigint]",
message:
"BigInt literals cannot be down-levelled for the safari13 build target and will break the whole bundle on old WebViews. Use string arithmetic instead (see decimalToHex in screens/Profile, or lib/wakeState).",
},
],
// Enforcement gate: every user-visible string must go through
// useTr()/tr(). The locale-parity gate (scripts/i18n-coverage.mjs)
// can only see keys that already exist — this catches strings
// before they ever become (missing) keys. See
// eslint-rules/no-untranslated-jsx.mjs. "error" because the
// existing backlog (178 strings) has been fully extracted — a
// new hardcoded string is now a build failure, not a warning.
"local/no-untranslated-jsx": "error",
// A refused action must not read as success — see the rule header.
"local/require-assert-ok": "error",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
caughtErrorsIgnorePattern: "^_",
},
],
},
},
{
files: ["src/**/*.test.{ts,tsx}"],
languageOptions: {
globals: {
...browserGlobals,
},
},
},
);