Skip to content

Epic Stack catch-up 4/7: LiteFS 2 + multi-region cache + asset fallthrough #27

Description

@cursor

Parent issue: #23

Parent: search for issue titled “Epic Stack catch-up: tracking”. Prefer packages 1–3 already on dev, but this can proceed if those PRs are not in the way.

Goal

Port LiteFS 2.x, restore multi-region-safe SQLite cache writes, and stop missing hashed assets from falling through to the app. Pin Docker/CI Prisma generate to the local v6 binary.

This site currently has a single Fly region (bos). Still do this so a second region does not corrupt the cache, and so LiteFS APIs match current litefs-js.

Upstream

Do this

Branch off origin/dev. PR into dev.

1. litefs-js 2.x

  • Bump litefs-js from ^1.1.2 to ^2.0.2 (or current 2.x matching Epic Stack)
  • Rewrite app/utils/litefs.server.ts to match upstream (named exports from litefs-js and litefs-js/remixnot litefs-js/remix.js)

Upstream file: https://github.com/epicweb-dev/epic-stack/blob/main/app/utils/litefs.server.ts

Fix any import breakage in files that imported removed paths. Do not change LiteFS behavior in fly.toml / other/litefs.yml unless required to compile.

2. Multi-region-safe cache

Replace app/utils/cache.server.ts logic with upstream’s version, adapting import paths to this repo’s route filenames:

This repo still uses remix-flat-routes names:

  • app/routes/admin+/cache_.sqlite.server.ts (not app/routes/admin/cache/sqlite.server.ts)

Required behaviors from upstream:

  • Throw if CACHE_DATABASE_PATH is unset
  • Only CREATE TABLE on the primary (getInstanceInfoSync)
  • fs.rmSync(..., { force: true }) instead of unlink that can throw ENOENT
  • set / delete: if primary, write locally; if replica, fire-and-forget updatePrimaryCacheValue

Read this repo’s admin cache server module and wire the same function. If the helper lives in cache_.sqlite.server.ts, import that — do not rename admin routes (package 7).

3. Asset fallthrough

In server/index.ts, change production static assets to:

express.static('build/client/assets', {
  immutable: true,
  maxAge: '1y',
  fallthrough: false,
})

Do not migrate the server to server/app.ts or Express 5 in this PR (package 5).

4. Prisma generate pin

In other/Dockerfile, change RUN npx prisma generate to RUN npm exec prisma generate.

Do not drop the COPY ... /myapp/server-build line here (package 5). Do not change app = or region.

Files allowed

  • package.json / package-lock.json (only litefs-js and types if needed)
  • app/utils/litefs.server.ts
  • app/utils/cache.server.ts
  • app/routes/admin+/cache_.sqlite.server.ts (and sibling admin cache files only if imports require it)
  • server/index.ts (fallthrough only)
  • other/Dockerfile (npm exec prisma generate only)
  • Tests/mocks that import cache/litefs if they break

Do not

  • Do not bump Express, Vite, Sentry, Prisma major, or React Router
  • Do not delete other/build-server.ts or server-build
  • Do not restructure admin+ folders
  • Do not edit dashboard+ or fly.toml app/region
  • Do not copy Epic Stack fly.toml

Acceptance

  • litefs-js is 2.x; litefs.server.ts imports from litefs-js/remix
  • Cache writes on replicas go through the primary update helper
  • /assets static middleware has fallthrough: false
  • Dockerfile uses npm exec prisma generate
  • npm run typecheck and npm run test -- --run pass
  • PR targets dev

Staging smoke (human)

  • Staging boots; /resources/healthcheck is OK
  • Login still works (session cookie / LiteFS)
  • Admin cache page still loads if you use it
  • A missing hashed /assets/... URL should 404, not HTML

PR target: dev (never main). Implement only this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions