5.6 KiB
5.6 KiB
Codebase simplification and design patterns
This doc summarizes recent improvements and suggested next steps for readability, extension, and consistency.
Done
1. Single place for template/reachability (DRY)
- Added
lib/graph/templateRefs.ts:isReachable,resolveExtendsRef,getTemplateRefs. - Refactored
config/renderingLogic.tsanduseRenderingNodeState.tsto use these helpers instead of duplicating the same logic. - Pattern: Extract shared pure helpers into a small lib module; keep call sites thin and consistent.
2. Naming and comments
- Renamed
outputMenuRegistry.tsx→outputMenuHandlers.tsx(no registry, only helpers). - Updated
rendering.tsandsourceRenderingLogic.ts: output menu is described as coming from the node descriptor (getOutputMenuContent), not a separate registry. - Documented
NodeMenubar: extra content can come from props or from the descriptor (getNodeMenuExtraContent). - Documented
nodeTypes.ts: clarifies React Flow types vs node type id (nodeRegistry).
3. Central pipeline entry
- rendering.ts documents the 3-step pipeline, how to add a source/output type, and points to
templateRefs.tsfor shared helpers.
4. Rendering signatures (pure module)
- Added
lib/graph/renderingSignatures.ts:buildConnectedNodeIds,buildSourceSignatures(connectedNodeIds + all five signatures + sourceSignature). - Refactored
useRenderingNodeStateto callbuildSourceSignaturesin a single useMemo; hook is shorter and signature logic is testable in isolation.
5. Canvas split
- CanvasContextMenuContent (
app/canvas/CanvasContextMenuContent.tsx): context menu content (Create Node grouped by classification, Paste). CanvasPage passesonCreateNodeandonPaste. - useCanvasConnectionPath (
app/canvas/useCanvasConnectionPath.ts): all connection-path state and callbacks (updating/trigger/paused/error node ids, path node ids, start/end update, add/remove paused/error). CanvasPage calls the hook withedgesand passes the result into FlowContext.
6. useCanvasGraph and canvas graph utils
- canvasGraphUtils.ts:
getExampleGraph(),getInitialGraph(projectId)(load from storage or return example). Example nodes/edges live here. - useCanvasGraph(projectId): wraps
useGraphStateWithHistorywith initial graph fromgetInitialGraph(projectId)and debounced save to storage whenprojectIdis set. CanvasPage uses this instead of inline state + persistence.
7. Config types registry
- configTypes.ts:
configTypeRegistry(Map),registerConfigType(type),getConfigTypes(),getConfigTypeIds(),registerBuiltinConfigTypes(). Built-in types are inBUILTIN_CONFIG_TYPESand registered at app init.getConfigType(id)looks up in the registry;getConfigTypeId(data)uses registered ids. ConfigNode usesgetConfigTypes()instead ofCONFIG_TYPES. New output types can callregisterConfigType()without editing the core array.
8. Consistent NodeLike / EdgeLike
- templateRefs.ts:
NodeLikeincludestype?: string; both types documented. Single source of truth for minimal node/edge shape in the graph lib. - sourceRenderingLogic: context uses
NodeLike[]andEdgeLike[]from templateRefs. - renderingSignatures: imports and re-exports
NodeLike/EdgeLikefrom templateRefs; no local duplicate types. - config/renderingLogic: uses context nodes/edges directly (no casts);
setVarInContext(src: NodeLike). - useRenderingNodeState: casts to
NodeLike[]/EdgeLike[]when callingbuildSourceSignatures(types from renderingSignatures).
9. Graph state, connection state, and node display state
- lib/graph/state.ts: Central state contracts and flow doc.
- GraphState – in-memory nodes + edges (useGraphStateWithHistory, persisted by useCanvasGraph).
- ConnectionPathState – type describing the slice that drives edge status and path animation (trigger/updating/paused/error sets).
- NodeDisplayStatus –
'initial' | 'loading' | 'success' | 'error'for node UI; getNodeDisplayStatus({ loading, error, hasContent }). - StoredGraphState – shape for save/load (version + nodes + edges).
- FlowContext: Module doc splits value into (1) Graph state, (2) Connection path state, (3) UI state. Same flat props, clearer sections.
- useGraphStateWithHistory: JSDoc explains history (past/future), setNodes vs setNodesSilent, setStateImmediate.
- projectGraphStorage: Uses StoredGraphState from state.ts; re-exports type. Doc references state flow.
- useRenderingNodeState: Returns displayStatus (for NodeStatusIndicator/empty/error UI) and lifecycle (updating/error/paused for useSyncConnectionStatus). Hook calls useSyncConnectionStatus(id, state.lifecycle). Type includes RenderingNodeLifecycle.
- RenderingNode: Uses state.displayStatus for NodeStatusIndicator instead of computing status locally.
- nodeLifecycle and connectionStatus: Docs reference state.ts for overall state flow.
Design patterns in use
| Pattern | Where |
|---|---|
| Registry | nodeRegistry, sourceRenderingLogic |
| Builder | nodeTypeBuilder (descriptor per node type) |
| Pipeline | Resolve → Render → Display (rendering.ts) |
| Strategy | Source logic per node type; output menu per descriptor |
| Shared helpers | templateRefs, outputMenuHandlers, renderingUtils |
Suggested next steps
- CanvasPage: Optional further split (e.g. move connection validation or node/edge change handlers into a hook) if the file grows again.