BLOBBO/scripts/ts-resolve.mjs
Claude 324d7d4568 Lane I: asset runtime — manifest, registry, slot hooks, IndexedDB overrides
Custom GLBs drop into 14 named slots without code changes; an empty manifest
produces today's game by construction (the fallback builders are the original
code moved into a closure, and an empty registry returns the caller's own
object by identity).

- src/assets/{slots,manifest,idb,registry,blobBody}.ts — schema + validation,
  GLTF cache with per-instance material cloning, fit nodes, IndexedDB override
  layer, paintability report.
- Slot hooks in createBlob, parts, cannon, greybox, puddles, ghost. Mesh-only:
  no collider, physics or logic line is touched. Animated sub-parts (plate cap,
  belt chevrons, fan blades, cannon pivot) stay procedural so a custom model
  cannot stop them moving.
- public/assets/ — the build had NO asset copy step at all, so every asset URL
  would have 404'd in production. public/ is vite's default publicDir, so this
  needs no vite.config change.
- Tests: 63 headless checks + a farm-GLB audit that fires PaintSkin's own
  raycast against the fitted body.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 11:37:08 +10:00

26 lines
881 B
JavaScript

/**
* Node resolve hook so the repo's extensionless TS imports (`./manifest`) work
* under `node --experimental-strip-types`, which otherwise demands a real file
* extension. Vite resolves these at build time; node does not.
*
* node --import ./scripts/ts-resolve.mjs --experimental-strip-types src/assets/manifest.test.ts
*/
import { registerHooks } from 'node:module'
import { existsSync } from 'node:fs'
import { fileURLToPath } from 'node:url'
registerHooks({
resolve(specifier, context, next) {
try {
return next(specifier, context)
} catch (err) {
if (!specifier.startsWith('.') || !context.parentURL) throw err
for (const ext of ['.ts', '/index.ts']) {
const url = new URL(specifier + ext, context.parentURL)
if (existsSync(fileURLToPath(url))) return next(specifier + ext, context)
}
throw err
}
},
})