/** * Generic runtime index generator for lexicon packages. * * Produces the `index.ts` file containing factory constructor exports * (`createResource`, `createProperty`) and collision-safe re-exports. */ export interface RuntimeIndexConfig { /** Lexicon identifier: "aws", "terraform", etc. */ lexiconName: string; /** Optional re-exports of intrinsic functions. */ intrinsicReExports?: { names: string[]; from: string; }; /** Optional re-exports of pseudo-parameters. */ pseudoReExports?: { names: string[]; from: string; }; } export interface RuntimeIndexEntry { tsName: string; resourceType: string; attrs: Record; } export interface RuntimeIndexPropertyEntry { tsName: string; resourceType: string; } /** * Generate the runtime index.ts content with factory constructor exports. * * Phases: * 1. Banner + import createResource/createProperty * 2. Sort and emit resource exports * 3. Sort and emit property exports * 4. Collision-safe re-exports of intrinsics and pseudo-parameters */ export function generateRuntimeIndex( resources: RuntimeIndexEntry[], properties: RuntimeIndexPropertyEntry[], config: RuntimeIndexConfig, ): string { const lines: string[] = []; lines.push("// Code generated by chant generate. DO NOT EDIT."); lines.push('import { createResource, createProperty } from "./runtime";'); lines.push(""); // Sort and emit resource exports const sortedResources = [...resources].sort((a, b) => a.tsName.localeCompare(b.tsName)); for (const { tsName, resourceType, attrs } of sortedResources) { const attrsStr = JSON.stringify(attrs); lines.push( `export const ${tsName} = createResource(${JSON.stringify(resourceType)}, ${JSON.stringify(config.lexiconName)}, ${attrsStr});`, ); } lines.push(""); // Sort and emit property exports const sortedProperties = [...properties].sort((a, b) => a.tsName.localeCompare(b.tsName)); for (const { tsName, resourceType } of sortedProperties) { lines.push( `export const ${tsName} = createProperty(${JSON.stringify(resourceType)}, ${JSON.stringify(config.lexiconName)});`, ); } lines.push(""); // Collision-safe re-exports const allExportNames = new Set([ ...resources.map((e) => e.tsName), ...properties.map((e) => e.tsName), ]); lines.push("// Re-exports for convenience"); if (config.intrinsicReExports) { const safe = config.intrinsicReExports.names.filter((n) => !allExportNames.has(n)); if (safe.length > 0) { lines.push(`export { ${safe.join(", ")} } from ${JSON.stringify(config.intrinsicReExports.from)};`); } } if (config.pseudoReExports) { const safe = config.pseudoReExports.names.filter((n) => !allExportNames.has(n)); if (safe.length > 0) { lines.push(`export { ${safe.join(", ")} } from ${JSON.stringify(config.pseudoReExports.from)};`); } } lines.push(""); return lines.join("\n"); }