refactoring

This commit is contained in:
2026-03-12 17:23:47 +01:00
parent f5b12949d3
commit bfd1a40332
13 changed files with 179 additions and 120 deletions

View File

@@ -144,7 +144,27 @@ async function renderWireframe(content: string, options?: RenderOptions): Promis
return svg
}
export const CONFIG_TYPES: ConfigType[] = [
/** Registry for config (output) types. Built-in types register in registerBuiltinConfigTypes(). */
const configTypeRegistry = new Map<string, ConfigType>()
export function registerConfigType(type: ConfigType): void {
if (configTypeRegistry.has(type.id)) {
console.warn(`[configTypes] Overwriting config type: ${type.id}`)
}
configTypeRegistry.set(type.id, type)
}
/** All registered config types (for type selector, etc.). */
export function getConfigTypes(): ConfigType[] {
return Array.from(configTypeRegistry.values())
}
/** All registered config type ids. */
export function getConfigTypeIds(): string[] {
return Array.from(configTypeRegistry.keys())
}
const BUILTIN_CONFIG_TYPES: ConfigType[] = [
{
id: 'plantuml',
label: 'Diagram',
@@ -220,11 +240,17 @@ export const CONFIG_TYPES: ConfigType[] = [
},
]
export const CONFIG_TYPE_IDS = CONFIG_TYPES.map((t) => t.id)
export const DEFAULT_CONFIG_TYPE_ID: ConfigTypeId = 'plantuml'
export function getConfigType(id: ConfigTypeId): ConfigType {
const t = CONFIG_TYPES.find((c) => c.id === id)
/** Register built-in config types (plantuml, markdown, wireframe). Call once at app init. */
export function registerBuiltinConfigTypes(): void {
for (const t of BUILTIN_CONFIG_TYPES) {
registerConfigType(t)
}
}
export function getConfigType(id: string): ConfigType {
const t = configTypeRegistry.get(id)
if (!t) throw new Error(`Unknown config type: ${id}`)
return t
}
@@ -264,9 +290,9 @@ export function getConfigContent(data: Record<string, unknown> | undefined): str
return typeof content === 'string' ? content : ''
}
/** Config type id from data (default plantuml). */
/** Config type id from data (default plantuml). Uses registered ids. */
export function getConfigTypeId(data: Record<string, unknown> | undefined): ConfigTypeId {
if (!data || data.configType == null) return 'plantuml'
const id = data.configType
return CONFIG_TYPE_IDS.includes(id as ConfigTypeId) ? (id as ConfigTypeId) : 'plantuml'
const id = String(data.configType)
return configTypeRegistry.has(id) ? (id as ConfigTypeId) : 'plantuml'
}

View File

@@ -22,7 +22,7 @@
*
* ## Implementing a new output type
* - Add a config type (or equivalent) fulfilling `IOutputTypeRenderer`.
* - Register in CONFIG_TYPES and use `getConfigType(id)` in the resolve step.
* - Call registerConfigType(type) (e.g. from registerBuiltinConfigTypes) and use getConfigType(id) in the resolve step.
*
* ## Shared helpers
* - templateRefs.ts: isReachable, resolveExtendsRef, getTemplateRefs (Nunjucks extends/include/import).

View File

@@ -1,14 +1,13 @@
/**
* Pure functions to build "connected node ids" and source signatures for the
* rendering pipeline. Used by useRenderingNodeState so the hook stays thin and
* this logic is testable in isolation.
* this logic is testable in isolation. Uses NodeLike/EdgeLike from templateRefs.
*/
import { getConfigContent } from '@/lib/graph/rendering'
import { isReachable, resolveExtendsRef, getTemplateRefs } from '@/lib/graph/templateRefs'
import { isReachable, resolveExtendsRef, getTemplateRefs, type NodeLike, type EdgeLike } from '@/lib/graph/templateRefs'
export type NodeLike = { id: string; type?: string; data?: unknown }
export type EdgeLike = { source: string; target: string }
export type { NodeLike, EdgeLike } from '@/lib/graph/templateRefs'
/**
* Collects all node ids that affect the render: direct incoming nodes plus

View File

@@ -7,17 +7,18 @@
*/
import type { ConfigTypeId } from './configTypes'
import type { NodeLike, EdgeLike } from './templateRefs'
export type { OutputMenuDescriptor, OutputMenuItemDescriptor, OutputMenuAction } from './configTypes'
/** Context passed into the resolve step (graph, source id, callbacks). See {@link IRenderingContext}. */
export type SourceRenderingLogicContext = {
nodes: { id: string; type?: string; data?: unknown }[]
edges: { id: string; source: string; target: string }[]
nodes: NodeLike[]
edges: EdgeLike[]
sourceNodeId: string
renderNodeId: string
viewportWidth?: number
viewportHeight?: number
setNodes?: (updater: (nodes: { id: string; type?: string; data?: unknown }[]) => { id: string; type?: string; data?: unknown }[]) => void
setNodes?: (updater: (nodes: NodeLike[]) => NodeLike[]) => void
aiConnection?: unknown
onStreamingStart?: () => void
onStreamingChunk?: (chunk: string) => void

View File

@@ -4,8 +4,11 @@
* so template parsing and "connected configs" stay in one place.
*/
/** Minimal edge shape for graph helpers (reachability, path, signatures). */
export type EdgeLike = { source: string; target: string }
export type NodeLike = { id: string; data?: unknown }
/** Minimal node shape for graph helpers (resolve refs, signatures). */
export type NodeLike = { id: string; type?: string; data?: unknown }
/** BFS: is target reachable from start following directed edges? */
export function isReachable(