import type { UserChoices } from "./prompts.js"; import type { LocalePlan } from "./locale-plan.js"; /** A single injection into a shared file at an anchor point. */ export interface Injection { /** Target file path relative to project root */ file: string; /** Anchor comment string to locate in the target file */ anchor: string; /** Content to insert */ content: string; /** * Where to insert relative to the anchor line. * - "before": insert content on the line before the anchor (default) * - "after": insert content on the line after the anchor * - "replace": replace the range between `anchor` (start) and the * corresponding `:end` anchor. The anchor must end with `:start` * and a sibling anchor ending with `:end` must exist. */ position?: "before" | "after" | "replace"; } /** Definition of a single feature's contribution to the generated project. */ export interface FeatureDefinition { /** Feature key (matches constants.ts value or internal name) */ name: string; /** Injection instructions for shared/base files */ injections: Injection[]; /** Other feature names this feature depends on (optional) */ dependencies?: string[]; /** * Post-processing hook for complex transformations that cannot be expressed * as simple file copies or anchor injections (e.g. i18n page patching). */ postProcess?: (targetDir: string, choices: UserChoices, localePlan?: LocalePlan) => Promise; } /** * A function that returns a FeatureDefinition based on user choices. * This allows injections to be conditional on other choices. */ export type FeatureModule = (choices: UserChoices, localePlan?: LocalePlan) => FeatureDefinition; /** * Apply a list of injections to files in the target directory. * * Injections are grouped by target file and applied in array order. * For "before"/"after" modes the content is inserted relative to the anchor * line. For "replace" mode, the content replaces everything between the * `:start` and `:end` anchors (exclusive — the anchor lines themselves are * also removed). */ export declare function applyInjections(targetDir: string, injections: Injection[]): Promise; /** * Remove all remaining `@slot:` anchor lines from files in the target * directory. Call this after all injections have been applied so that * unused anchors don't appear in the generated project. */ export declare function cleanAnchors(targetDir: string, files: string[]): Promise; /** * Copy a feature's files into the target directory. * `featureFilesDir` is the absolute path to the feature's `files/` directory. * Each file inside mirrors the project directory structure. */ export declare function copyFeatureFiles(featureFilesDir: string, targetDir: string): Promise; /** * Resolve which features are selected based on UserChoices. * Handles special cases like the footer pseudo-feature. */ export declare function resolveSelectedFeatures(choices: UserChoices, featureModules: Record, localePlan?: LocalePlan): FeatureDefinition[]; /** * Validate that all feature dependencies are satisfied. * Throws if a selected feature depends on one that isn't selected. */ export declare function validateDependencies(features: FeatureDefinition[], allSelectedNames: Set): void; /** * Files that may contain injection anchors and need cleaning. * * EMPTY as of the minimal-scaffold cutover (epic zudolab/zudo-doc#2651, * Wave 6 #2660). Every anchor target this list used to name — * `src/styles/global.css`'s `@slot:global-css:*` comments, * `pages/lib/_body-end-islands.tsx`, `src/config/settings-types.ts` — is * GONE from `templates/base/` (the package now owns chrome/islands/settings * types entirely; see `templates/base/src/styles/global.css`'s fixed * ~20-line `@import` chain). Feature modules are pure settings-field * emission + genuine file copies now (see `src/features/*.ts`) — none of * them call `applyInjections` with a real anchor anymore. The * `Injection`/`applyInjections`/`cleanAnchors` machinery below is kept as * infrastructure for a future feature that genuinely needs it (e.g. an * eventual host-side extension point), not because anything uses it today. */ export declare const ANCHOR_FILES: string[]; /** * Main composition entry point. Orchestrates the full feature composition * pipeline for a generated project. * * 1. Resolve selected features * 2. Validate dependencies * 3. Copy feature files * 4. Apply all injections * 5. Run post-processing hooks * 6. Clean up unused anchors */ export declare function composeFeatures(targetDir: string, choices: UserChoices, featureModules: Record, featuresDir: string, localePlan?: LocalePlan): Promise;