--- status: draft last_updated: 2026-05-19 --- # Build & Distribution Package structure, exports map, dependencies, and platform targets. ## Package Structure ``` @alkdev/flowgraph/ ├── src/ │ ├── component/ # ujsx workflow components │ │ ├── operation.ts # component │ │ ├── sequential.ts # component │ │ ├── parallel.ts # component │ │ ├── conditional.ts # component │ │ └── index.ts │ ├── host/ │ │ ├── graphology.ts # GraphologyHostConfig │ │ ├── reactive.ts # ReactiveHostConfig │ │ └── index.ts │ ├── schema/ │ │ ├── enums.ts # CallStatus, EdgeType, NodeCategory, NodeStatus │ │ ├── node.ts # OperationNodeAttrs, CallNodeAttrs │ │ ├── edge.ts # TypedEdgeAttrs, CallEdgeAttrs, TemplateEdgeAttrs │ │ ├── graph.ts # SerializedGraph, FlowGraphSerialized │ │ └── index.ts │ ├── graph/ │ │ ├── construction.ts # FlowGraph class (fromSpecs, fromCallEvents, fromJSON, etc.) │ │ ├── validation.ts # validateSchema, validateGraph, validate │ │ ├── queries.ts # topologicalOrder, hasCycles, ancestors, descendants, etc. │ │ ├── mutation.ts # addNode, addEdge, updateNodeStatus, removeNode, etc. │ │ └── index.ts │ ├── reactive/ │ │ ├── workflow.ts # WorkflowReactiveRoot (signal-backed execution) │ │ ├── node-status.ts # Signal, computed preconditions │ │ └── index.ts │ ├── analysis/ │ │ ├── type-compat.ts # typeCompat, buildTypeEdges, analyzeTypeCompat │ │ ├── workflow.ts # validateTemplate, validatePreconditions │ │ ├── defaults.ts # resolveDefaults for CallStatus, EdgeType, etc. │ │ └── index.ts │ ├── error/ │ │ └── index.ts # FlowgraphError hierarchy │ └── index.ts # Barrel export ├── test/ │ ├── graph/ │ │ ├── construction.test.ts │ │ ├── validation.test.ts │ │ ├── queries.test.ts │ │ └── mutation.test.ts │ ├── schema/ │ │ └── enums.test.ts │ ├── analysis/ │ │ ├── type-compat.test.ts │ │ └── workflow.test.ts │ ├── component/ │ │ └── components.test.ts │ ├── host/ │ │ ├── graphology.test.ts │ │ └── reactive.test.ts │ └── error/ │ └── errors.test.ts ├── package.json ├── tsconfig.json ├── tsup.config.ts ├── vitest.config.ts └── AGENTS.md ``` ## Package JSON ```json { "name": "@alkdev/flowgraph", "version": "0.1.0", "type": "module", "exports": { ".": { "import": "./dist/index.js", "require": "./dist/index.cjs" }, "./component": { "import": "./dist/component/index.js", "require": "./dist/component/index.cjs" }, "./host": { "import": "./dist/host/index.js", "require": "./dist/host/index.cjs" }, "./schema": { "import": "./dist/schema/index.js", "require": "./dist/schema/index.cjs" }, "./graph": { "import": "./dist/graph/index.js", "require": "./dist/graph/index.cjs" }, "./reactive": { "import": "./dist/reactive/index.js", "require": "./dist/reactive/index.cjs" }, "./analysis": { "import": "./dist/analysis/index.js", "require": "./dist/analysis/index.cjs" }, "./error": { "import": "./dist/error/index.js", "require": "./dist/error/index.cjs" } }, "typesVersions": { "*": { "component": ["./dist/component/index.d.ts"], "host": ["./dist/host/index.d.ts"], "schema": ["./dist/schema/index.d.ts"], "graph": ["./dist/graph/index.d.ts"], "reactive": ["./dist/reactive/index.d.ts"], "analysis": ["./dist/analysis/index.d.ts"], "error": ["./dist/error/index.d.ts"] } } } ``` ## Exports Map Following the taskgraph pattern, each module has a sub-path export: | Sub-path | Content | Use case | |----------|---------|----------| | `@alkdev/flowgraph` | Barrel export (everything) | Full import | | `@alkdev/flowgraph/component` | ``, ``, ``, `` | Template authoring | | `@alkdev/flowgraph/host` | `GraphologyHostConfig`, `ReactiveHostConfig` | ujsx HostConfig implementations | | `@alkdev/flowgraph/schema` | TypeBox schemas, enums, types | Schema-only import (no graph dependency) | | `@alkdev/flowgraph/graph` | `FlowGraph` class, construction, mutation, queries | Core graph operations | | `@alkdev/flowgraph/reactive` | `WorkflowReactiveRoot`, signal-based execution | Runtime execution | | `@alkdev/flowgraph/analysis` | `typeCompat`, `validateTemplate`, ordering functions | Analysis and validation | | `@alkdev/flowgraph/error` | Error classes | Error handling | ## Dependencies ### Production Dependencies ```json { "dependencies": { "@alkdev/typebox": "workspace:*", "@alkdev/ujsx": "workspace:*", "@preact/signals-core": "^1.x", "graphology": "^0.25", "graphology-dag": "^0.4" }, "peerDependencies": { "@alkdev/operations": "workspace:*" } } ``` | Package | Role | Why | |---------|------|-----| | `@alkdev/typebox` | Schema definitions, validation, `Value.Check`, `Value.Errors` | Direct dependency — all schemas are TypeBox | | `@alkdev/ujsx` | UNode, HostConfig, createRoot, h(), ReactiveRoot | Direct dependency — workflow templates are ujsx trees | | `@preact/signals-core` | `signal`, `computed`, `effect`, `batch` | Transitive via ujsx, re-exported for flowgraph's reactive layer | | `graphology` | `DirectedGraph` data structure | Core graph engine — same as taskgraph | | `graphology-dag` | `topologicalSort`, `hasCycle`, `parallelGroups` | DAG-specific algorithms | | `@alkdev/operations` | `OperationSpec`, `CallEventMap`, `CallStatus` | Peer dependency — type imports only, no runtime dependency | ### Why `@alkdev/operations` is a Peer Dependency Flowgraph imports `OperationSpec`, `CallEventMap`, and `CallStatus` types from `@alkdev/operations`, but does not depend on the runtime (registry, call handler, pending request map). Making it a peer dependency: 1. Avoids circular dependency concerns (operations doesn't depend on flowgraph) 2. Allows flowgraph to work with any version of operations that provides the right types 3. Reduces bundle size for consumers that don't use operations ### Why `@preact/signals-core` via `@alkdev/ujsx` Flowgraph's reactive layer uses `signal()`, `computed()`, and `effect()` from `@preact/signals-core`. These are re-exported from `@alkdev/ujsx/reactive` so consumers don't need to import directly from Preact. If ujsx ever changes its reactive primitive library, only ujsx's re-export needs updating. ## Build Configuration ### tsup.config.ts Following taskgraph's build pattern: ```typescript import { defineConfig } from "tsup"; export default defineConfig({ entry: { index: "src/index.ts", component: "src/component/index.ts", host: "src/host/index.ts", schema: "src/schema/index.ts", graph: "src/graph/index.ts", reactive: "src/reactive/index.ts", analysis: "src/analysis/index.ts", error: "src/error/index.ts", }, format: ["esm", "cjs"], dts: true, clean: true, splitting: true, sourcemap: true, }); ``` - **ESM + CJS dual output** — matches all sibling packages - **Code splitting** — enables tree-shaking for sub-path imports - **Source maps** — for debugging - **Type declarations** — `.d.ts` files for all exports ### tsconfig.json ```json { "compilerOptions": { "target": "ES2022", "module": "Node16", "moduleResolution": "Node16", "strict": true, "declaration": true, "declarationMap": true, "sourceMap": true, "outDir": "./dist", "rootDir": "./src", "types": ["vitest/globals"] }, "include": ["src/**/*.ts"], "exclude": ["node_modules", "dist", "test"] } ``` Matches the tsconfig pattern of all `@alkdev` packages: ES2022 target, Node16 module resolution, strict mode. ### vitest.config.ts ```typescript import { defineConfig } from "vitest/config"; export default defineConfig({ test: { globals: true, }, }); ``` ## Platform Targets Following taskgraph's philosophy: **pure JavaScript, no native addons**. | Platform | Support Level | Notes | |----------|---------------|-------| | Node.js | Primary | All dependencies are pure JS | | Deno | Compatible | ESM-first, no Node-specific APIs used | | Bun | Compatible | All dependencies are Bun-compatible | | Browser | Compatible | graphology and signals-core work in browsers | The library has no native dependencies, no filesystem access, and no Node-specific APIs (no `fs`, `path`, `child_process`, etc.). This makes it platform-agnostic. ## Tree-Shaking The sub-path export structure enables effective tree-shaking: - Consumers using only `@alkdev/flowgraph/schema` don't pull in the graph engine or ujsx - Consumers using only `@alkdev/flowgraph/analysis` don't pull in the reactive layer - Consumers using `@alkdev/flowgraph/component` get ujsx but not graphology (templates can be defined without importing the graph engine) The barrel export (`@alkdev/flowgraph`) re-exports everything for convenience, but consumers concerned about bundle size should use sub-path imports. ## Constraints - **No filesystem access** — flowgraph is a pure computation library. Persistence is the hub's concern. - **No network access** — no HTTP clients, WebSocket connections, or Redis clients. All data comes in through constructor arguments. - **`@alkdev/operations` is a peer dependency** — type imports only, no runtime dependency on the operations registry or call protocol. - **ESM-first** — the package is authored in ESM with CJS output generated by tsup. All internal imports use `.js` extensions for Node16 module resolution. - **Code splitting enabled** — tsup's `splitting: true` enables optimal code splitting for sub-path imports. - **Vitest for testing** — following the monorepo convention. ## References - Taskgraph build configuration: `@alkdev/taskgraph_ts/tsup.config.ts`, `@alkdev/taskgraph_ts/tsconfig.json` - ujsx build configuration: `@alkdev/ujsx/tsup.config.ts` - graphology: https://github.com/graphology/graphology - graphology-dag: https://github.com/graphology/graphology-dag