Architettura del monorepo
Un solo motore, tre front-end. La logica vive in packages/core,
TypeScript puro, zero dipendenze DOM o Node. Sopra quel core si appoggiano
il web app (browser), il CLI (Node) e, in futuro, un'app desktop (Electron
che wrappa il web build).
Struttura
embroidery-converter/
├── packages/
│ ├── core/ ← TUTTA la logica. TS strict, ZERO deps DOM/Node.
│ │ ├── src/
│ │ │ ├── ir.ts Intermediate Representation
│ │ │ ├── embcompress.ts Greg-Hus expand()/compress()
│ │ │ ├── readers/
│ │ │ │ ├── vip.ts (HUS body in VIP wrapper)
│ │ │ │ ├── zhs.ts
│ │ │ │ ├── pes.ts dst.ts jef.ts vp3.ts exp.ts ...
│ │ │ ├── writers/
│ │ │ │ ├── zhs.ts ← la gemma: nessun writer open ha mai toccato ZHS
│ │ │ │ ├── dst.ts pes.ts jef.ts vp3.ts exp.ts hus.ts vip.ts xxx.ts ...
│ │ │ ├── registry.ts estensione → reader/writer
│ │ │ └── index.ts convert(bytes, from, to) → bytes + warnings
│ │ └── test/ Vitest, round-trip vs ../../fixtures
│ └── cli/ ← Node CLI, usa core
│ └── src/index.ts embconv in.vip out.zhs | batch cartella
├── apps/
│ ├── web/ ← Astro. Drag-drop,Web Worker?, JSZip download.
│ │ └── src/ 100% client-side.
│ └── desktop/ ← (futuro) Electron. Carica apps/web/build e ci mette sopra batch native.
└── fixtures/ VIP/ZHS pairs e altri ground-truth IR condivisa
Il Pattern è modellato su EmbPattern di
pyembroidery, ma in TypeScript strict. Vedi la pagina
IR per il tipo esatto. È il contratto tra ogni reader e ogni writer.
Stack
- pnpm workspaces, TypeScript strict ovunque.
- Astro 6 per
apps/web: una landing con scrolltelling + pages/converte/docs. - tsup per buildare
coreecli. - Vitest per i test, con fixture presi da
/fixtures. - Niente backend. Il web app è statico, deployabile su Netlify / Cloudflare Pages / qualsiasi host.
Ordine di porting (cosa è stato portato per primo)
- EmbCompress
expand()+ reader VIP + writer ZHS + IR. → VIP→ZHS in TS, con test round-trip vsfixtures/. - Lettori: ZHS, PES, DST, VP3. (XXX, JEF, EXP arrivati dopo.)
- Scrittori: DST, PES (facili, ben documentati). Poi JEF, VP3, HUS, VIP, XXX.
- Web app: drag-drop + scarico singolo + Studio (coda + pannello).
- CLI batch. (Desktop è futuro.)
- Multi-colore / trim ZHS writing — solo dopo aver ottenuto sample
.zhscon trims (vedi ZHS).
Perché un monorepo
Perché la logica si scrive una volta sola. Aggiungere un formato al
core e lo stesso giorno web app, CLI e desktop lo sanno usare.
Aggiornare il core significa aggiornare tutto. È il pattern più pigro ed
efficiente per chi mantiene il progetto da solo.