import type { PageAst } from "@wrnexus/syntax"; export interface ComponentContractMetadata { name: string; kind: PageAst["kind"]; props: Array<{ name: string; type: string; required: boolean; default?: string; options?: string[]; }>; outputs: Array<{ name: string; payloadName?: string; payloadType?: string }>; functions: Array<{ name: string; runtime: string; async: boolean; parameters: Array<{ name: string; type: string; optional: boolean }>; returnType: string; }>; states: Array<{ name: string; runtime: string; type: string; initializer: string }>; computed: Array<{ name: string; type: string; expression: string }>; imports: Array<{ source: string; typeOnly: boolean; defaultImport?: string; namedImports: string[]; }>; } function unionOptions(type: string | undefined): string[] | undefined { if (!type || !type.includes("|")) return undefined; const values = type .split("|") .map((part) => part.trim()) .filter((part) => /^(?:"[^"]*"|'[^']*')$/.test(part)) .map((part) => part.slice(1, -1)); return values.length ? values : undefined; } export function createComponentContract(ast: PageAst): ComponentContractMetadata { return { name: ast.name, kind: ast.kind, props: ast.props.map((prop) => ({ name: prop.name, type: prop.valueType ?? "unknown", required: prop.required, ...(prop.default !== "undefined" ? { default: prop.default } : {}), ...(unionOptions(prop.valueType) ? { options: unionOptions(prop.valueType) } : {}), })), outputs: ast.outputs.map((output) => ({ name: output.name, ...(output.payload ? { payloadName: output.payload.name, payloadType: output.payload.valueType } : {}), })), functions: ast.runtimeFunctions.map((fn) => ({ name: fn.name, runtime: fn.runtime, async: fn.async, parameters: fn.parameters.map((param) => ({ name: param.name, type: param.valueType ?? "unknown", optional: param.optional, })), returnType: fn.returnType ?? (fn.async ? "Promise" : "unknown"), })), states: ast.states.map((state) => ({ name: state.name, runtime: state.runtime, type: state.valueType ?? "unknown", initializer: state.expr, })), computed: ast.computed.map((entry) => ({ name: entry.name, type: entry.valueType ?? "unknown", expression: entry.expr, })), imports: ast.structuredImports.map((entry) => ({ source: entry.source, typeOnly: entry.typeOnly, ...(entry.defaultImport ? { defaultImport: entry.defaultImport } : {}), namedImports: entry.namedImports.map((named) => named.local), })), }; }