/**
* 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 is the SSOT `lib/slot-names.ts` — the exact ``
* calls scaffold-component renders (drift-tested against the real renderer).
* Until 2026-09-24 this file published `${module}.${entity}.list.before…` while
* the pages rendered `${entity}.header.actions`… — zero names in common, every
* dead (audit B-CRIT-05). Slot names carry NO module prefix.
*/
import type { ScaffoldExtensionConfigInput, GeneratedFile } from './types.js'
import { DEFAULT_SLOT_VIEWS, SLOT_SUFFIXES_BY_VIEW, slotCatalogue } from '../../../../../lib/slot-names.js'
import { toCamelCase } from '../../../../../lib/string-utils.js'
const OPTIONAL_VIEWS = (Object.keys(SLOT_SUFFIXES_BY_VIEW) as Array).filter(
(v) => !DEFAULT_SLOT_VIEWS.includes(v),
)
export function generate(spec: ScaffoldExtensionConfigInput): GeneratedFile[] {
const allSlots = spec.entities.flatMap((e) => slotCatalogue(e))
const jsDocLines = allSlots
.map((s) => ` * - '${s.name}' (${s.view} page): ${s.description}`)
.join('\n')
const optionalLines = OPTIONAL_VIEWS
.map((v) => ` * - ${v} page (when generated): ${SLOT_SUFFIXES_BY_VIEW[v].map((sfx) => `'{entity}.${sfx}'`).join(', ')}`)
.join('\n')
const slotEntries = allSlots.map((s) => ` '${s.name}': null,`).join('\n')
// A hyphenated module (`time-entry`) is not a valid identifier (audit B-WARN-17).
const configName = `${toCamelCase(spec.module)}Config`
const content = `import type { ExtensionConfig } from '@atlashub/smartstack';
/**
* Extension configuration for the ${spec.module} module.
*
* Slot catalog — the exact calls the generated pages render
* (SSOT: skills/lib/slot-names.ts, no module prefix):
${jsDocLines}
*
* Also rendered by the optional views:
${optionalLines}
*
* Add Fill components in your app entrypoint to inject content into any slot:
* {yourJsx}
*/
export const ${configName}: ExtensionConfig = {
slots: {
${slotEntries}
},
tableColumns: {},
formFields: {},
hooks: {},
};
`
return [{ path: `src/extensions/${spec.module}Extensions.ts`, content }]
}