Files
WRNexusJS/packages/compiler/src/component-contract.ts
T
2026-08-01 01:09:58 +05:30

88 lines
2.7 KiB
TypeScript

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>" : "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),
})),
};
}