/** * TypeScript declaration file generator — produces index.d.ts with all * GitLab CI entity classes. */ import type { GitLabParseResult } from "./parse"; import { gitlabShortName } from "./parse"; import type { NamingStrategy } from "./naming"; import { propertyTypeName, extractDefName } from "./naming"; import { writeResourceClass, writePropertyClass, writeEnumType, type DtsProperty, type DtsAttribute, } from "@intentius/chant/codegen/generate-typescript"; interface ResourceEntry { tsName: string; properties: DtsProperty[]; attributes: DtsAttribute[]; remap: Map; } interface EnumEntry { tsName: string; values: string[]; } /** * Generate the complete .d.ts file content. */ export function generateTypeScriptDeclarations( results: GitLabParseResult[], naming: NamingStrategy, ): string { const lines: string[] = []; lines.push("// Code generated by chant gitlab generate. DO NOT EDIT."); const resources: ResourceEntry[] = []; const enums: EnumEntry[] = []; for (const r of results) { const typeName = r.resource.typeName; const tsName = naming.resolve(typeName); if (!tsName) continue; const shortName = gitlabShortName(typeName); const remap = new Map(); for (const pt of r.propertyTypes) { const defName = extractDefName(pt.name, shortName); remap.set(pt.name, propertyTypeName(tsName, defName)); } for (const e of r.enums) { const defName = extractDefName(e.name, shortName); remap.set(e.name, propertyTypeName(tsName, defName)); } const dtsProps: DtsProperty[] = r.resource.properties.map((p) => ({ name: p.name, type: p.tsType, required: p.required, description: p.description, })); const dtsAttrs: DtsAttribute[] = r.resource.attributes.map((a) => ({ name: a.name, type: a.tsType, })); resources.push({ tsName, properties: dtsProps, attributes: dtsAttrs, remap }); for (const alias of naming.aliases(typeName)) { resources.push({ tsName: alias, properties: dtsProps, attributes: dtsAttrs, remap }); } for (const e of r.enums) { const defName = extractDefName(e.name, shortName); const eName = propertyTypeName(tsName, defName); enums.push({ tsName: eName, values: e.values }); } } // Sort alphabetically resources.sort((a, b) => a.tsName.localeCompare(b.tsName)); enums.sort((a, b) => a.tsName.localeCompare(b.tsName)); // Resource classes (all CI entities use writeResourceClass since they're // all top-level — the "property" distinction is only in the registry) lines.push(""); lines.push("// --- CI Entity classes ---"); for (const re of resources) { writeResourceClass(lines, re.tsName, re.properties, re.attributes, re.remap); } // Enum types if (enums.length > 0) { lines.push(""); lines.push("// --- Enum types ---"); for (const ee of enums) { writeEnumType(lines, ee.tsName, ee.values); } } // Static content lines.push(""); lines.push(staticTypeScript()); lines.push(""); return lines.join("\n"); } function staticTypeScript(): string { const lines: string[] = []; lines.push("// --- CI/CD Variables ---"); lines.push(""); lines.push("export declare const CI: {"); const ciVars = [ "CommitBranch", "CommitRef", "CommitSha", "CommitTag", "DefaultBranch", "Environment", "JobId", "JobName", "JobStage", "MergeRequestIid", "PipelineId", "PipelineSource", "ProjectDir", "ProjectId", "ProjectName", "ProjectPath", "Registry", "RegistryImage", ]; for (const v of ciVars) { lines.push(` readonly ${v}: string;`); } lines.push("};"); return lines.join("\n"); }