| name | compiler-workflows |
| description | Write workflows using imperative TypeScript with the Flowcraft Compiler. Covers @flow and @step annotations, control flow patterns, subflows, configuration, and build tool integration. Use when the user mentions the compiler, imperative workflows, @flow, @step, or wants to write workflows without manually constructing graphs. |
Compiler Workflows (Alpha)
Flowcraft's compiler transforms imperative TypeScript into declarative blueprints at build time. Write familiar async functions with control flow — the compiler generates the graph.
[!WARNING]
The compiler is in alpha. Contributions are welcome.
Quick start
Installation
npm install --save-dev @flowcraft/compiler
Write a workflow
export async function myWorkflow(input: string) {
const data = await fetchData(input)
const result = await processData(data)
return result
}
async function fetchData(input: string) {
return fetch(`/api/data?q=${input}`).then((r) => r.json())
}
async function processData(data: unknown) {
return { processed: true, data }
}
Execute
import { FlowRuntime } from 'flowcraft'
import manifest from './generated/manifest'
const runtime = new FlowRuntime()
const result = await runtime.run(manifest['myWorkflow'], { input: 'hello' })
The Golden Rules
- **Mark orchestrators with
/** @flow \*/** — Functions that define workflow orchestration
- **Mark durable operations with
/** @step \*/** — Async operations that should be retried/tracked
- Never await plain async functions — The compiler errors if you await a non-
@step function
Supported Control Flow
| Pattern | Syntax | Compiles to |
|---|
| Sequential | await stepA(); await stepB() | Linear nodes with edges |
| Conditional | if/else with @step calls | Conditional edges with actions |
| Switch | switch(val) { case ... } with @step calls | Conditional multi-branch |
| Loops | for/while/do-while with @step calls | Loop controller node |
| Fallbacks | try/catch/finally with @step calls | Fallback/finally node routing |
| Parallelism | Promise.all([...]), Promise.allSettled([...]), Promise.race([...]) | Fan-out/fan-in with join |
| Subflows | await otherFlow(input) | Subflow node |
Configuration
Create flowcraft.config.ts:
import { defineConfig } from '@flowcraft/compiler'
export default defineConfig({
entryPoints: ['./src/workflows/**/*.ts'],
manifestPath: './src/generated/manifest.ts',
tsConfigPath: './tsconfig.json',
})
Build Tool Integration
Compilation happens automatically with plugins:
import flowcraft from '@flowcraft/plugin-vite'
export default {
plugins: [flowcraft()],
}
Available plugins: Vite, Next.js, Nuxt, Astro, esbuild, tsup.
Unsupported Syntax
- Complex variable re-assignments within loops
- Dynamic function calls or
eval
- Generator functions or async generators
- Class methods as steps (use standalone functions)
Runtime compilation (compileCode)
For testing, REPL environments, or low-frequency runtime configuration, use compileCode() to compile raw TypeScript strings into blueprints:
import { compileCode } from '@flowcraft/compiler'
const { blueprint, diagnostics } = compileCode(
`
/** @flow */
export async function myFlow() {
const data = await fetchData()
return await processData(data)
}
/** @step */
async function fetchData() { return { value: 42 } }
/** @step */
async function processData(d: any) { return { result: d.value * 2 } }
`,
{ id: 'myFlow' },
)
Note: compileCode() writes temporary files and spins up a full compiler instance per call. For production, always use pre-compiled builds via compileProject() or framework plugins.
Advanced topics