4 Commits

Author SHA1 Message Date
Georges-Antoine Assi
c8055ac973 Address self-review on patcher PR
- patcher.js resolves rom-patcher-js from both the relocated sibling
  layout (docker/Dockerfile) and the plain node_modules layout (root
  Dockerfile), so both build flows work without a manual copy
- apply_patch wraps the node subprocess in asyncio.wait_for with a
  timeout and kills it on expiry; a semaphore bounds concurrency, and the
  endpoint rejects oversized ROM/patch files to avoid OOM
- report the patch source-checksum validation result via an
  X-Patch-Validated header; the patcher UI warns on a mismatch
- return a generic "Patching failed" detail to clients and log the real
  error server-side, so node/RomPatcher.js paths don't leak

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 21:07:27 -04:00
Georges-Antoine Assi
a3176494c9 Patcher backend refinements, dep cleanup, regenerated types
- Move default_category_for_non_nested validator onto RomFileSchema so
  top-level files default to category "game" (the v2 patcher's base-file
  filter relies on this).
- Use Annotated Body() in the patch endpoint; check patcher output via
  anyio async Path.
- Drop the now-unused client-side rom-patcher and vite-plugin-static-copy
  (patching is server-side); simplify the Storybook plugin filter.
- Regenerate frontend OpenAPI types.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 09:17:52 -04:00
Georges-Antoine Assi
1ee4682845 feat: drive frontend patcher via server-side endpoint, isolate Node deps
- Rewrite frontend/src/views/Patcher.vue around library ROM/patch pickers
  (v-autocomplete with debounced search) and call POST /api/roms/{id}/patch
  with responseType: blob; download and/or re-upload the patched output.
- Drop the rom-patcher npm dep and vite-plugin-static-copy from the frontend;
  remove the now-unused web worker, type decls, and viteStaticCopy plugin.
- Move the Node patcher into a self-contained npm project at
  backend/utils/rom_patcher/ (dir uses underscore so it's a valid Python
  package). Patcher.js loads RomPatcher.js from its sibling node_modules.
- Extract the heavy subprocess logic into backend/utils/rom_patcher/patcher.py
  (apply_patch, PatcherError, SUPPORTED_PATCH_EXTENSIONS); slim patch.py to
  HTTP/DB plumbing and fix a stale .parent.parent path.
- Wire up Docker: dev Dockerfile installs the new npm project; prod
  Dockerfile adds a backend-node-build stage and copies rom-patcher-js into
  the production image; install nodejs at runtime.
- Add new patcher i18n keys to en_US (other locales fall back).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 07:39:31 -04:00
Claude
1398aa09cf Add server-side ROM patching endpoint using RomPatcher.js
Introduces POST /api/roms/{id}/patch that applies patch files to ROM files
server-side, enabling third-party apps to request ROM patching using games
and patches already in the library without needing client-side JS support.

- backend/utils/patcher.js: Node.js helper that loads RomPatcher.js and
  applies a patch file to a ROM, writing the result to an output path
- backend/endpoints/roms/patch.py: FastAPI endpoint that looks up ROM and
  patch files by ID, invokes the Node.js patcher via subprocess, and
  streams the patched ROM back as a download
- Supports all 9 patch formats: IPS, UPS, BPS, PPF, RUP, APS, BDF, PMSR, VCDIFF
- Requires roms.read scope for authentication
- Temp files are cleaned up via Starlette BackgroundTask after response

https://claude.ai/code/session_01HS6ZvAiBjmLPVB3gGw8eEt
2026-04-06 22:22:40 +00:00