Skip to main content
Welcome. This site supports keyboard navigation and screen readers. Press ? at any time for keyboard shortcuts. Press [ to focus the sidebar, ] to focus the content. High-contrast themes are available via the toolbar.
serard@dev00:~/cv

The thesis in three sentences

The TypeScript ecosystem has templating tools (plop, hygen, nx generators), it has compiler-pipeline transformers (ts-patch, ttypescript, the TS Compiler API plugin surface), it has bundler-side codegen (unplugin, swc, esbuild plugins). It does not have what C# has had since 2020 with Roslyn ISourceGenerator and IIncrementalGenerator: a multi-stage feedback codegen pipeline where stage N observes stage N-1's output through a virtual filesystem, where convergence is reached by fixpoint instead of a hand-counted iteration limit, where the commit to disk is atomic and the contract is strictly additive. The library @frenchexdev/ts-codegen-pipeline is exactly that piece. This series introduces it, anchored on the canonical packages/sourcegen-example — a 10-stage industrial weaving of @Module × @Entity × @StateMachine that reaches its fixpoint in three iterations through a single deliberate backward-edge stage.

The framing matters and is stated once, here, to hold for the whole series: a TS source generator pipeline is not a templating engine and not a compiler transformer. It is a Roslyn-style multi-pass program that consumes decorated TypeScript classes, scans them through ts-morph, emits new TypeScript files into an in-memory mirror of the project, and converges to a fixpoint before a single atomic commit to disk. Every later article points back to this sentence when it claims the library does or does not behave like a Roslyn source generator.

Why publish this series now

Three reasons, in increasing strategic weight.

The first is that the library has reached a state where its semantics are stable and its example is industrial-grade. The example is not a hello-world: it weaves three decorator families across ten stages, exercises a real backward-edge fixpoint, emits template-literal types and discriminated transition unions, and ships 22 acceptance criteria across five Feature classes verified by twenty test files. The series can therefore be honest about what the library does — not aspirational, not a pitch, just a walk through what is already running in packages/sourcegen-example right now.

The second is that the gap in the TS ecosystem has stayed open longer than it should. Every TS team that has tried to ship a non-trivial codegen step has hit the same wall: plop templates do not understand the AST, ts-patch rewrites the compiler pipeline (and is therefore versioning-fragile), swc plugins live in Rust, nx generators are one-shot scaffolders. None of those provide the property that this library provides: that stage 0 can read what stage N emitted in iteration I-1 without writing to disk, and that the run as a whole either commits everything or commits nothing. Naming the gap and showing the library that fills it is overdue work.

The third is positional. The series sits between meta-ide-dsl (which proved a small TS meta-DSL could compile decorated spec.ts files into a VSCode extension) and microdsls-and-kernel (which decomposed that meta-DSL into a kernel and fourteen micro-DSLs). Both presuppose a codegen layer with the properties this series describes. Until now that layer was implicit; this series makes it explicit and gives later series a stable reference. When Ide.Dsl-TS lands as a third TS-side series in this constellation, its first article will say: built on @frenchexdev/ts-codegen-pipeline and link here.

How to read this series

Twelve articles, four implicit parts. The parts are designed so that a reader can stop after Part II and walk away with the engine's mental model; a reader who continues into Part III gets the example as curriculum, stage by stage; a reader who reads through Part IV sees the testing/CI story and the road forward.

Each article number corresponds to one FEAT-TSGEN-NN Feature declared in assets/features.ts. The series dog-foods the same Requirements DSL described in cmf-design article 13 and used by packages/sourcegen-example/requirements/ itself.

Part I — Positioning (1 article)

  1. The Roslyn-shaped gap in the TypeScript ecosystem. The ISourceGenerator mental model recalled; plop/hygen/nx/ts-patch/ttypescript compared and distinguished; the multi-stage feedback gap stated; the analogue table from the library README reproduced and discussed.

Part II — The engine (5 articles)

  1. The industrial weaving: a tour of the example. The vertical slice (ShopModule / User+Order+Product / OrderFsm); the 10-stage pipeline in narrative form; what "weaving three decorator families" means; the table that the rest of the series unpacks.
  2. VirtFS, fixpoint, and the backward edge. The in-memory ts-morph Project; fixpoint as termination; the three-iteration convergence walked stage by stage; why 00-entity.registry lex-sorting before 20-entity.repository forces a second iteration.
  3. Strictly additive: invariants under load. The SG0040 path-escape contract; SG0020 producer-divergence; prune-on-delete; how a ten-producer pipeline stays safe.
  4. Banners, hashes, and verify mode. The four-line banner; the content hash; deterministic byte-identical reruns; sourcegen verify as a CI primitive.
  5. Atomic commit: all-or-nothing disk safety. The .tmp-rename-purge sequence; mid-loop failure leaves disk untouched; what plop/hygen/nx cannot offer.

Part III — The example as curriculum (4 articles)

  1. Decorator families as tagged-union DSLs. @Module/@Entity/@StateMachine walked; the kind: discriminator as a DSL trait, not friction; the three shared scanners (scanEntities, scanModules, scanFsms).
  2. The entity-scaffolding quadruple: Repo + DTO + Mapper + Validator. Stages 20, 30, 50, 60 walked; the dependency chain (mapper reads dto, validator reads dto + fsm states); DistributiveOmit + Branded<T,B> + EntityId<K> as emitted constructs.
  3. FSM typed dispatch: state unions and Extract<Transition, { via: E }>['to']. Stages 40 and 70 walked; how a discriminated transition graph yields a typed dispatcher; the compiler narrows the destination state from the verb.
  4. Module wiring and the registry loop. Stages 10 and 80 walked; cross-module provides/requires resolution; cycle detection; the registry backward-edge loop closed against the iteration count.

Part IV — Verifiability and forward look (2 articles)

  1. Testing strategy: 22 ACs across 5 Features. The dog-fooded Feature / Requirement / @Verifies framework over the example; the 208-line industrial-sandbox.ts harness; idempotence, determinism, hand-edit detection, convergence as four asserted properties; sourcegen verify + tsc --noEmit on outDir as the CI pair.
  2. Lessons from Roslyn, and where this leads: Ide.Dsl-TS. What was borrowed (multi-pass mental model, AddSource API shape, determinism contract); what was deliberately not (no IIncrementalGenerator because TS has no Compilation to cache against; no syntax-tree visitors because ts-morph already covers that); the road to Ide.Dsl-TS and ontology-parameterized DSLs.

Reading paths

  • If you want positioning only: 01 → 12 reads as a 6 000-word essay on the gap, the library's response, and the lineage of decisions.
  • If you want the engine mental model: 02 → 03 → 04 → 05 → 06 is the engine path. After it the reader can pick up @frenchexdev/ts-codegen-pipeline, write a generator, and ship.
  • If you want the example stage by stage: 02 → 07 → 08 → 09 → 10 walks the canonical pipeline as a series of guided readings of source files.
  • If you want CI / verifiability: 03 → 05 → 11 is the shortest path through the determinism properties and how to assert them.
  • If you came from meta-ide-dsl or microdsls-and-kernel: read 01 for positioning, then jump to 11 — the testing chapter is where the dog-fooded Feature / Requirement framework loops back to the meta-IDE thread.

None of these paths is a "short version". Each holds the same register as microdsls-and-kernel and meta-ide-dsl. The series totals roughly 30 000 words.

Three claims this series will defend

Every article surfaces at least one of three load-bearing claims, and every claim is grounded against the running example rather than asserted by analogy with C#.

The first claim is that multi-stage feedback codegen is a missing primitive in the TS ecosystem — not just a missing tool, but a missing shape. Articles 01 and 12 carry it most directly, but every mechanics chapter reinforces it by showing a behaviour (cross-iteration handoff, atomic commit, strict additivity) that no other TS codegen tool supplies.

The second claim is that a Roslyn-style API can be carried over to TS without dragging in C#-specific assumptions. Articles 03–06 carry this load by exhibiting the engine's contracts and showing what was deliberately not borrowed (no Compilation object, no syntax-tree visitor, no two-tier SG/IIG split). The point is not that TS should be C# but that the multi-pass mental model is portable; the C#-specific machinery around it is not.

The third claim is that the additive-only contract is strong enough to make a ten-stage pipeline safe and weak enough to keep the library small. Articles 04, 06, and 11 carry this load. The library does not let user code be mutated; it does not let two producers disagree on the same path; it commits everything or nothing. Those three rules are the entire safety story, and they are sufficient.

What you will not find here

  • Implementation code outside the example. This is design-and-walk-through. The Requirements assets in assets/features.ts are the only TypeScript that type-checks standalone. The example package itself is read but not edited.
  • A published npm package walkthrough. The library is consumed as a workspace dependency from the example. Publishing posture is out of scope.
  • A comparison with non-TS codegen tooling. The Roslyn comparison is in scope because the library's mental model is borrowed from there. JetBrains MPS, Xtext, language-server-style codegen are out of scope and belong in microdsls-and-kernel.
  • Performance benchmarks. The library is fast enough on the canonical example; quantifying that on adversarial inputs is a future series.
  • meta-ide-dsl — the upstream design series for TS-side DSL tooling. The codegen layer this library provides is the substrate meta-ide-dsl presupposes.
  • microdsls-and-kernel — the DDD decomposition of the meta-DSL. Article 19 of that series (the Generator micro-DSL chapter) explicitly names @frenchexdev/ts-codegen-pipeline as the engine.
  • cmf-design — the same posture, content-management side, in C#.
  • distributed-task — a C# source generator series with similar shape; useful contrast for readers wondering what the TS port keeps and discards.
  • closing-the-loop — the requirements-driven dog-food loop the assets here participate in.
⬇ Download