docs: document image tracing endpoint
This commit is contained in:
+11
-3
@@ -46,7 +46,8 @@ apps/web ──► apps/proxy ──► packages/tts ──► packages/shared
|
||||
### Edges
|
||||
|
||||
- **`apps/web` → `apps/proxy`** — calls `/search`, `/items/:id`,
|
||||
`/items/:id/file`, and `/asset` (CORS-safe asset proxy) over HTTP.
|
||||
`/items/:id/file`, `/asset` (CORS-safe asset proxy), and `/trace`
|
||||
(image → vector shape) over HTTP.
|
||||
- **`apps/web` → `packages/extract`** — uses `buildTree` / `collectRefs`
|
||||
to analyze a loaded `TTSMod` in the browser (tree sidebar + asset refs).
|
||||
- **`apps/proxy` → `packages/tts`** — calls `fetchMod` / `getFileName` to serve
|
||||
@@ -80,6 +81,9 @@ apps/web ──► apps/proxy ──► packages/tts ──► packages/shared
|
||||
| `@hono/node-server`| Node adapter for Hono | `apps/proxy` |
|
||||
| `@hono/cors` | CORS middleware | `apps/proxy` |
|
||||
| `bson` | BSON deserialization of TTS save files | `packages/tts` |
|
||||
| `@visioncortex/vtracer` | Raster-to-SVG vectorization (wasm) | `apps/proxy` |
|
||||
| `sharp` | Image decoding to RGBA | `apps/proxy` |
|
||||
| `svgpath` | SVG path parsing for traced shapes | `apps/proxy` |
|
||||
| `cheerio` | Workshop browse page scraping | `apps/proxy` |
|
||||
| `zod` | Runtime validation | `apps/proxy`, `packages/shared` |
|
||||
| `three` | 3D rendering | `apps/web` |
|
||||
@@ -91,7 +95,11 @@ apps/web ──► apps/proxy ──► packages/tts ──► packages/shared
|
||||
|
||||
- **`cheerio` is backend-only** — it never appears in `packages/extract`, which
|
||||
must stay isomorphic.
|
||||
- **`bson` is Node-only** — used by the fetcher, not the analysis layer.
|
||||
- **`bson` is Node-only** — used by the fetcher and the trace route, not the
|
||||
analysis layer.
|
||||
- **`@visioncortex/vtracer`, `sharp`, `svgpath` are backend-only** — the trace
|
||||
route lives in `apps/proxy`; they never appear in `packages/extract`, which
|
||||
must stay isomorphic.
|
||||
- **`packages/extract` has zero external runtime deps** — it relies only on
|
||||
platform `fetch` / `Blob`, keeping it portable to a future frontend.
|
||||
|
||||
@@ -107,7 +115,7 @@ apps/web ──► apps/proxy ──► packages/tts ──► packages/shared
|
||||
|
||||
- The proxy runs as a single Node process via `@hono/node-server`.
|
||||
- `apps/web` is a static Vite build served separately; during development it
|
||||
proxies `/search`, `/items`, `/health`, and `/asset` to the proxy.
|
||||
proxies `/search`, `/items`, `/health`, `/asset`, and `/trace` to the proxy.
|
||||
- `packages/extract` is published/consumed as a plain ESM module usable from a
|
||||
browser bundle or Node.
|
||||
- No shared state between requests; each request fetches fresh.
|
||||
@@ -158,3 +158,24 @@ browser. Routing asset fetches through the proxy makes them loadable.
|
||||
|
||||
**Alternatives considered:** Loading assets directly in the browser. Rejected —
|
||||
CORS failures on common Workshop hosts would break the viewers.
|
||||
|
||||
## D13 — Server-side image tracing to a mesh-ready shape
|
||||
|
||||
**Decision:** The proxy exposes `GET /trace?url=...`, which fetches an image,
|
||||
traces it into a vector shape, and returns the result BSON-encoded. Tracing is
|
||||
configurable: `mode` (`alpha` default, `bw`, `color`) selects how the region is
|
||||
derived, and `format` (`shape` default, `svg`) selects the response. The
|
||||
`shape` format returns a parsed `{ outline, holes }` polygon matching
|
||||
`@tts/mesh`'s `Shape` interface.
|
||||
|
||||
**Context:** The user wants to build a mesh from an image (e.g. a token or tile
|
||||
art) using `@tts/mesh`. vtracer only returns SVG, but the mesh package consumes
|
||||
`{ outline, holes }`. Tracing on the server keeps the SVG-to-shape parsing out
|
||||
of the browser and lets the BSON response carry a ready-to-extrude shape.
|
||||
`sharp` decodes the image to RGBA so alpha/luminance masks can be built before
|
||||
feeding vtracer's `convertPixels`.
|
||||
|
||||
**Alternatives considered:** Returning only the raw SVG and parsing in the web
|
||||
app near `@tts/mesh`; tracing by color only (no alpha). Rejected — server-side
|
||||
parsing yields a shape the mesh package can consume directly, and alpha-based
|
||||
tracing (the default) is the common case for token/tile art.
|
||||
@@ -63,6 +63,8 @@ tts-workshop/
|
||||
│ │ │ ├── search.ts # GET /search?q=...&page=1
|
||||
│ │ │ ├── items.ts # GET /items/:id, /items/:id/file
|
||||
│ │ │ ├── asset.ts # GET /asset?url=... (CORS-safe asset proxy)
|
||||
│ │ │ ├── trace.ts # GET /trace?url=... (image → vector shape)
|
||||
│ │ │ ├── svgShape.ts # parse vtracer SVG into { outline, holes }
|
||||
│ │ │ └── health.ts # GET /health
|
||||
│ │ └── env.ts # zod env validation
|
||||
│ └── web/
|
||||
@@ -202,6 +204,17 @@ Hono server exposing search + fetch.
|
||||
it back with a `Content-Type` header. Workshop hosts often omit CORS
|
||||
headers, which would block three.js loaders in the browser; routing through
|
||||
the proxy makes those assets loadable. Only `http(s)` URLs are allowed.
|
||||
- `routes/trace.ts`
|
||||
- `GET /trace?url=...&mode=alpha&threshold=128&format=shape` — fetch an
|
||||
image, trace it into a vector shape, and return the result BSON-encoded.
|
||||
`mode` is `alpha` (default), `bw`, or `color`; `format` is `shape`
|
||||
(default) or `svg`. `shape` returns a parsed `{ outline, holes }` polygon
|
||||
matching `@tts/mesh`'s `Shape` interface, ready to extrude.
|
||||
- `routes/svgShape.ts`
|
||||
- `parseSvgShape(svg)` — parse a vtracer SVG into a `TracedShape`
|
||||
(`{ outline, holes }`): flatten beziers to polylines, split subpaths into
|
||||
rings, classify by winding (CCW outline / CW hole), and assign holes to
|
||||
their containing outline.
|
||||
- `routes/health.ts`
|
||||
- `GET /health` — liveness.
|
||||
- `env.ts` — zod validation of `STEAM_API_KEY`, `PORT`.
|
||||
@@ -259,6 +272,7 @@ proxy API and `packages/extract` directly for analysis.
|
||||
| GET | `/items/:id` | Full parsed `TTSMod` (`?fileUrl=` skips key) | key* |
|
||||
| GET | `/items/:id/file` | Raw save bytes, filename from header | key* |
|
||||
| GET | `/asset?url=` | CORS-safe proxy for external assets | — |
|
||||
| GET | `/trace?url=&mode=&format=` | Trace an image into a vector shape (BSON) | — |
|
||||
|
||||
\* `STEAM_API_KEY` is optional; `/items/*` works without it when a `fileUrl`
|
||||
query param is supplied.
|
||||
@@ -275,12 +289,17 @@ query param is supplied.
|
||||
download BSON → parse → TTSMod
|
||||
↓
|
||||
packages/extract → flatten objects / extract refs / download assets
|
||||
↓
|
||||
/trace?url=... → sharp decode → vtracer → parse SVG → BSON shape
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `hono`, `@hono/node-server`, `@hono/cors` — server.
|
||||
- `bson` — BSON deserialization.
|
||||
- `bson` — BSON deserialization (save files + trace results).
|
||||
- `@visioncortex/vtracer` — raster-to-SVG vectorization (wasm).
|
||||
- `sharp` — image decoding to RGBA for tracing.
|
||||
- `svgpath` — SVG path parsing for traced shapes.
|
||||
- `cheerio` — Workshop browse page scraping (backend only).
|
||||
- `zod` — validation.
|
||||
- `react`, `react-dom`, `react-router-dom`, `zustand` — frontend.
|
||||
|
||||
Reference in New Issue
Block a user