/** * cli:scaffold-extension-config — generate.ts * * Emits an ExtensionConfig for a module, listing every slot that the scaffolded * components publish via ``. Clients (or other extensions) * fill these slots with ``. * * ExtensionConfig type comes from `@atlashub/smartstack` (npm). * * The slot catalog below mirrors the exact `` calls emitted by * `frontend/component` generator. Renaming slots in one place without the other * breaks composition silently. */ import type { ScaffoldExtensionConfigInput, GeneratedFile } from './types.js' interface SlotDescriptor { name: string description: string contextShape: string } function buildSlots(module: string, entity: string): SlotDescriptor[] { const eLower = entity.charAt(0).toLowerCase() + entity.slice(1) const base = `${module}.${eLower}` return [ { name: `${base}.list.before`, description: `Rendered above the ${entity} list table.`, contextShape: `{}` }, { name: `${base}.list.after`, description: `Rendered below the ${entity} list table.`, contextShape: `{}` }, { name: `${base}.detail.before`, description: `Rendered at the top of the ${entity} detail page.`, contextShape: `{ data: ${entity} }` }, { name: `${base}.detail.after`, description: `Rendered at the bottom of the ${entity} detail page.`, contextShape: `{ data: ${entity} }` }, { name: `${base}.form.fields.before`, description: `Injects form fields before the scaffolded ones.`, contextShape: `{ formData: ${entity}FormData, onChange: (field, value) => void }` }, { name: `${base}.form.fields.after`, description: `Injects form fields after the scaffolded ones.`, contextShape: `{ formData: ${entity}FormData, onChange: (field, value) => void }` }, ] } export function generate(spec: ScaffoldExtensionConfigInput): GeneratedFile[] { const allSlots = spec.entities.flatMap(e => buildSlots(spec.module, e)) const jsDocLines = allSlots .map(s => ` * - '${s.name}': ${s.description}\n * context: ${s.contextShape}`) .join('\n') const slotEntries = allSlots.map(s => ` '${s.name}': null,`).join('\n') const content = `import type { ExtensionConfig } from '@atlashub/smartstack'; /** * Extension configuration for the ${spec.module} module. * * Slot catalog (each call below must match exactly): ${jsDocLines} * * Add Fill components in your app entrypoint to inject content into any slot: * {yourJsx} */ export const ${spec.module}Config: ExtensionConfig = { slots: { ${slotEntries} }, tableColumns: {}, formFields: {}, hooks: {}, }; ` return [{ path: `src/extensions/${spec.module}Extensions.ts`, content }] }