@timeax/scaffold 0.0.9 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +17 -15
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +17 -15
- package/dist/cli.mjs.map +1 -1
- package/package.json +2 -1
- package/src/cli/main.ts +285 -286
package/dist/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schema/index.ts","../src/util/logger.ts","../src/util/fs-utils.ts","../src/core/config-loader.ts","../src/ast/parser.ts","../src/ast/format.ts","../src/core/structure-txt.ts","../src/core/resolve-structure.ts","../src/core/cache-manager.ts","../src/core/hook-runner.ts","../src/core/apply-structure.ts","../src/core/scan-structure.ts","../src/core/format.ts","../src/core/runner.ts","../src/core/watcher.ts","../src/core/init-scaffold.ts","../src/cli/main.ts"],"names":["fs","path","parent","logger","minimatch"],"mappings":"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","file":"cli.mjs","sourcesContent":["// src/schema/index.ts\r\nexport const SCAFFOLD_ROOT_DIR = '.scaffold';\r\nexport * from './structure';\r\nexport * from './hooks';\r\nexport * from './config';","// src/util/logger.ts\r\n\r\nexport type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug';\r\n\r\nexport interface LoggerOptions {\r\n level?: LogLevel;\r\n /**\r\n * Optional prefix string (e.g. \"[scaffold]\" or \"[group:app]\").\r\n */\r\n prefix?: string;\r\n}\r\n\r\n/**\r\n * Minimal ANSI color helpers (no external deps).\r\n */\r\nconst supportsColor =\r\n typeof process !== 'undefined' &&\r\n process.stdout &&\r\n process.stdout.isTTY &&\r\n process.env.NO_COLOR !== '1';\r\n\r\ntype ColorFn = (text: string) => string;\r\n\r\nfunction wrap(code: number): ColorFn {\r\n const open = `\\u001b[${code}m`;\r\n const close = `\\u001b[0m`;\r\n return (text: string) => (supportsColor ? `${open}${text}${close}` : text);\r\n}\r\n\r\nconst color = {\r\n red: wrap(31),\r\n yellow: wrap(33),\r\n green: wrap(32),\r\n cyan: wrap(36),\r\n magenta: wrap(35),\r\n dim: wrap(2),\r\n bold: wrap(1),\r\n gray: wrap(90),\r\n};\r\n\r\nfunction colorForLevel(level: LogLevel): ColorFn {\r\n switch (level) {\r\n case 'error':\r\n return color.red;\r\n case 'warn':\r\n return color.yellow;\r\n case 'info':\r\n return color.cyan;\r\n case 'debug':\r\n return color.gray;\r\n default:\r\n return (s) => s;\r\n }\r\n}\r\n\r\n/**\r\n * Minimal logger for @timeax/scaffold with colored output.\r\n */\r\nexport class Logger {\r\n private level: LogLevel;\r\n private prefix: string | undefined;\r\n\r\n constructor(options: LoggerOptions = {}) {\r\n this.level = options.level ?? 'info';\r\n this.prefix = options.prefix;\r\n }\r\n\r\n setLevel(level: LogLevel) {\r\n this.level = level;\r\n }\r\n\r\n getLevel(): LogLevel {\r\n return this.level;\r\n }\r\n\r\n /**\r\n * Create a child logger with an additional prefix.\r\n */\r\n child(prefix: string): Logger {\r\n const combined = this.prefix ? `${this.prefix}${prefix}` : prefix;\r\n return new Logger({ level: this.level, prefix: combined });\r\n }\r\n\r\n private formatMessage(msg: unknown, lvl: LogLevel): string {\r\n const text =\r\n typeof msg === 'string'\r\n ? msg\r\n : msg instanceof Error\r\n ? msg.message\r\n : String(msg);\r\n\r\n const levelColor = colorForLevel(lvl);\r\n const prefixColored = this.prefix\r\n ? color.magenta(this.prefix)\r\n : undefined;\r\n\r\n const textColored =\r\n lvl === 'debug' ? color.dim(text) : levelColor(text);\r\n\r\n if (prefixColored) {\r\n return `${prefixColored} ${textColored}`;\r\n }\r\n\r\n return textColored;\r\n }\r\n\r\n private shouldLog(targetLevel: LogLevel): boolean {\r\n const order: LogLevel[] = ['silent', 'error', 'warn', 'info', 'debug'];\r\n const currentIdx = order.indexOf(this.level);\r\n const targetIdx = order.indexOf(targetLevel);\r\n if (currentIdx === -1 || targetIdx === -1) return true;\r\n if (this.level === 'silent') return false;\r\n return targetIdx <= currentIdx || targetLevel === 'error';\r\n }\r\n\r\n error(msg: unknown, ...rest: unknown[]) {\r\n if (!this.shouldLog('error')) return;\r\n console.error(this.formatMessage(msg, 'error'), ...rest);\r\n }\r\n\r\n warn(msg: unknown, ...rest: unknown[]) {\r\n if (!this.shouldLog('warn')) return;\r\n console.warn(this.formatMessage(msg, 'warn'), ...rest);\r\n }\r\n\r\n info(msg: unknown, ...rest: unknown[]) {\r\n if (!this.shouldLog('info')) return;\r\n console.log(this.formatMessage(msg, 'info'), ...rest);\r\n }\r\n\r\n debug(msg: unknown, ...rest: unknown[]) {\r\n if (!this.shouldLog('debug')) return;\r\n console.debug(this.formatMessage(msg, 'debug'), ...rest);\r\n }\r\n}\r\n\r\n/**\r\n * Default process-wide logger used by CLI and core.\r\n * Level can be controlled via SCAFFOLD_LOG_LEVEL env.\r\n */\r\nexport const defaultLogger = new Logger({\r\n level: (process.env.SCAFFOLD_LOG_LEVEL as LogLevel | undefined) ?? 'info',\r\n prefix: '[scaffold]',\r\n});","// src/util/fs-utils.ts\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\n\r\n/**\r\n * Convert any path to a POSIX-style path with forward slashes.\r\n */\r\nexport function toPosixPath(p: string): string {\r\n return p.replace(/\\\\/g, '/');\r\n}\r\n\r\n/**\r\n * Ensure a directory exists (like mkdir -p).\r\n * Returns the absolute path of the directory.\r\n */\r\nexport function ensureDirSync(dirPath: string): string {\r\n if (!fs.existsSync(dirPath)) {\r\n fs.mkdirSync(dirPath, { recursive: true });\r\n }\r\n return dirPath;\r\n}\r\n\r\n/**\r\n * Synchronous check for file or directory existence.\r\n */\r\nexport function existsSync(targetPath: string): boolean {\r\n return fs.existsSync(targetPath);\r\n}\r\n\r\n/**\r\n * Read a file as UTF-8, returning null if it doesn't exist\r\n * or if an error occurs (no exceptions thrown).\r\n */\r\nexport function readFileSafeSync(filePath: string): string | null {\r\n try {\r\n return fs.readFileSync(filePath, 'utf8');\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Write a UTF-8 file, creating parent directories if needed.\r\n */\r\nexport function writeFileSafeSync(filePath: string, contents: string): void {\r\n const dir = path.dirname(filePath);\r\n ensureDirSync(dir);\r\n fs.writeFileSync(filePath, contents, 'utf8');\r\n}\r\n\r\n/**\r\n * Remove a file if it exists. Does nothing on error.\r\n */\r\nexport function removeFileSafeSync(filePath: string): void {\r\n try {\r\n if (fs.existsSync(filePath)) {\r\n fs.unlinkSync(filePath);\r\n }\r\n } catch {\r\n // ignore\r\n }\r\n}\r\n\r\n/**\r\n * Get file stats if they exist, otherwise null.\r\n */\r\nexport function statSafeSync(targetPath: string): fs.Stats | null {\r\n try {\r\n return fs.statSync(targetPath);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Resolve an absolute path from projectRoot + relative path,\r\n * and assert it stays within the project root.\r\n *\r\n * Throws if the resolved path escapes the project root.\r\n */\r\nexport function resolveProjectPath(projectRoot: string, relPath: string): string {\r\n const absRoot = path.resolve(projectRoot);\r\n const absTarget = path.resolve(absRoot, relPath);\r\n\r\n // Normalise for safety check\r\n const rootWithSep = absRoot.endsWith(path.sep) ? absRoot : absRoot + path.sep;\r\n if (!absTarget.startsWith(rootWithSep) && absTarget !== absRoot) {\r\n throw new Error(\r\n `Attempted to resolve path outside project root: ` +\r\n `root=\"${absRoot}\", target=\"${absTarget}\"`,\r\n );\r\n }\r\n\r\n return absTarget;\r\n}\r\n\r\n/**\r\n * Convert an absolute path back to a project-relative path.\r\n * Throws if the path is not under projectRoot.\r\n */\r\nexport function toProjectRelativePath(projectRoot: string, absolutePath: string): string {\r\n const absRoot = path.resolve(projectRoot);\r\n const absTarget = path.resolve(absolutePath);\r\n\r\n const rootWithSep = absRoot.endsWith(path.sep) ? absRoot : absRoot + path.sep;\r\n if (!absTarget.startsWith(rootWithSep) && absTarget !== absRoot) {\r\n throw new Error(\r\n `Path \"${absTarget}\" is not inside project root \"${absRoot}\".`,\r\n );\r\n }\r\n\r\n const rel = path.relative(absRoot, absTarget);\r\n return toPosixPath(rel);\r\n}\r\n\r\n/**\r\n * Check if `target` is inside (or equal to) `base` directory.\r\n */\r\nexport function isSubPath(base: string, target: string): boolean {\r\n const absBase = path.resolve(base);\r\n const absTarget = path.resolve(target);\r\n\r\n const baseWithSep = absBase.endsWith(path.sep) ? absBase : absBase + path.sep;\r\n return absTarget === absBase || absTarget.startsWith(baseWithSep);\r\n}","// src/core/config-loader.ts\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport os from 'os';\r\nimport crypto from 'crypto';\r\nimport { pathToFileURL } from 'url';\r\nimport { transform } from 'esbuild';\r\n\r\nimport { SCAFFOLD_ROOT_DIR, type ScaffoldConfig } from '../schema';\r\nimport { defaultLogger } from '../util/logger';\r\nimport { ensureDirSync } from '../util/fs-utils';\r\n\r\nconst logger = defaultLogger.child('[config]');\r\n\r\n\r\nexport interface LoadScaffoldConfigOptions {\r\n /**\r\n * Optional explicit scaffold directory path (absolute or relative to cwd).\r\n * If provided, this overrides config.root for locating the scaffold folder.\r\n */\r\n scaffoldDir?: string;\r\n\r\n /**\r\n * Optional explicit config file path (absolute or relative to cwd).\r\n * If not provided, we look for config.* inside the scaffoldDir.\r\n */\r\n configPath?: string;\r\n}\r\n\r\nexport interface LoadScaffoldConfigResult {\r\n /**\r\n * Parsed scaffold configuration.\r\n */\r\n config: ScaffoldConfig;\r\n\r\n /**\r\n * Absolute path to the scaffold directory (where config & *.txt live).\r\n */\r\n scaffoldDir: string;\r\n\r\n /**\r\n * Effective project root BASE where structures are applied.\r\n * This is derived from config.root + config.base.\r\n */\r\n projectRoot: string;\r\n}\r\n\r\n/**\r\n * Load scaffold configuration based on CWD + optional overrides + config.root/base.\r\n *\r\n * Resolution rules:\r\n * - configRoot:\r\n * - Start from cwd.\r\n * - Apply config.root (if defined) as a path relative to cwd.\r\n * - scaffoldDir:\r\n * - If options.scaffoldDir is provided → use it as-is (resolved from cwd).\r\n * - Else → <configRoot>/scaffold.\r\n * - projectRoot (base):\r\n * - If config.base is defined → resolve relative to configRoot.\r\n * - Else → configRoot.\r\n */\r\nexport async function loadScaffoldConfig(\r\n cwd: string,\r\n options: LoadScaffoldConfigOptions = {},\r\n): Promise<LoadScaffoldConfigResult> {\r\n const absCwd = path.resolve(cwd);\r\n\r\n // First pass: figure out an initial scaffold dir just to locate config.*\r\n const initialScaffoldDir = options.scaffoldDir\r\n ? path.resolve(absCwd, options.scaffoldDir)\r\n : path.join(absCwd, SCAFFOLD_ROOT_DIR);\r\n\r\n const configPath =\r\n options.configPath ?? resolveConfigPath(initialScaffoldDir);\r\n\r\n // Import config (supports .ts/.tsx via esbuild)\r\n const config = await importConfig(configPath);\r\n\r\n // Now compute configRoot (where scaffold/ lives by default)\r\n let configRoot = absCwd;\r\n if (config.root) {\r\n configRoot = path.resolve(absCwd, config.root);\r\n }\r\n\r\n // Final scaffoldDir (can still be overridden by CLI)\r\n const scaffoldDir = options.scaffoldDir\r\n ? path.resolve(absCwd, options.scaffoldDir)\r\n : path.join(configRoot, SCAFFOLD_ROOT_DIR);\r\n\r\n // projectRoot (base) is relative to configRoot\r\n const baseRoot = config.base\r\n ? path.resolve(configRoot, config.base)\r\n : configRoot;\r\n\r\n logger.debug(\r\n `Loaded config: configRoot=${configRoot}, baseRoot=${baseRoot}, scaffoldDir=${scaffoldDir}`,\r\n );\r\n\r\n return {\r\n config,\r\n scaffoldDir,\r\n projectRoot: baseRoot,\r\n };\r\n}\r\n\r\nfunction resolveConfigPath(scaffoldDir: string): string {\r\n const candidates = [\r\n 'config.ts',\r\n 'config.mts',\r\n 'config.mjs',\r\n 'config.js',\r\n 'config.cjs',\r\n ];\r\n\r\n for (const file of candidates) {\r\n const full = path.join(scaffoldDir, file);\r\n if (fs.existsSync(full)) {\r\n return full;\r\n }\r\n }\r\n\r\n throw new Error(\r\n `Could not find scaffold config in ${scaffoldDir}. Looked for: ${candidates.join(\r\n ', ',\r\n )}`,\r\n );\r\n}\r\n\r\n/**\r\n * Import a ScaffoldConfig from the given path.\r\n * - For .ts/.tsx we transpile with esbuild to ESM and load from a temp file.\r\n * - For .js/.mjs/.cjs we import directly.\r\n */\r\nasync function importConfig(configPath: string): Promise<ScaffoldConfig> {\r\n const ext = path.extname(configPath).toLowerCase();\r\n\r\n if (ext === '.ts' || ext === '.tsx') {\r\n return importTsConfig(configPath);\r\n }\r\n\r\n const url = pathToFileURL(configPath).href;\r\n const mod = await import(url);\r\n return (mod.default ?? mod) as ScaffoldConfig;\r\n}\r\n\r\n/**\r\n * Transpile a TS config file to ESM with esbuild and import the compiled file.\r\n * We cache based on (path + mtime) so changes invalidate the temp.\r\n */\r\nasync function importTsConfig(configPath: string): Promise<ScaffoldConfig> {\r\n const source = fs.readFileSync(configPath, 'utf8');\r\n const stat = fs.statSync(configPath);\r\n\r\n const hash = crypto\r\n .createHash('sha1')\r\n .update(configPath)\r\n .update(String(stat.mtimeMs))\r\n .digest('hex');\r\n\r\n const tmpDir = path.join(os.tmpdir(), 'timeax-scaffold-config');\r\n ensureDirSync(tmpDir);\r\n\r\n const tmpFile = path.join(tmpDir, `${hash}.mjs`);\r\n\r\n if (!fs.existsSync(tmpFile)) {\r\n const result = await transform(source, {\r\n loader: 'ts',\r\n format: 'esm',\r\n sourcemap: 'inline',\r\n target: 'ESNext',\r\n tsconfigRaw: {\r\n compilerOptions: {\r\n\r\n },\r\n },\r\n });\r\n\r\n fs.writeFileSync(tmpFile, result.code, 'utf8');\r\n }\r\n\r\n const url = pathToFileURL(tmpFile).href;\r\n const mod = await import(url);\r\n return (mod.default ?? mod) as ScaffoldConfig;\r\n}","// src/ast/parser.ts\r\n\r\nimport {toPosixPath} from '../util/fs-utils';\r\n\r\nexport type AstMode = 'strict' | 'loose';\r\n\r\nexport type DiagnosticSeverity = 'info' | 'warning' | 'error';\r\n\r\nexport interface Diagnostic {\r\n line: number; // 1-based\r\n column?: number; // 1-based (optional)\r\n message: string;\r\n severity: DiagnosticSeverity;\r\n code?: string;\r\n}\r\n\r\n/**\r\n * How a physical line in the text was classified.\r\n */\r\nexport type LineKind = 'blank' | 'comment' | 'entry';\r\n\r\nexport interface StructureAstLine {\r\n index: number; // 0-based\r\n lineNo: number; // 1-based\r\n raw: string;\r\n kind: LineKind;\r\n indentSpaces: number;\r\n content: string; // after leading whitespace (includes path+annotations+inline comment)\r\n}\r\n\r\n/**\r\n * AST node base for structure entries.\r\n */\r\ninterface AstNodeBase {\r\n type: 'dir' | 'file';\r\n /** The last segment name, e.g. \"schema/\" or \"index.ts\". */\r\n name: string;\r\n /** Depth level (0 = root, 1 = child of root, etc.). */\r\n depth: number;\r\n /** 1-based source line number. */\r\n line: number;\r\n /** Normalized POSIX path from root, e.g. \"src/schema/index.ts\" or \"src/schema/\". */\r\n path: string;\r\n /** Stub annotation, if any. */\r\n stub?: string;\r\n /** Include glob patterns, if any. */\r\n include?: string[];\r\n /** Exclude glob patterns, if any. */\r\n exclude?: string[];\r\n /** Parent node; null for roots. */\r\n parent: DirNode | null;\r\n}\r\n\r\nexport interface DirNode extends AstNodeBase {\r\n type: 'dir';\r\n children: AstNode[];\r\n}\r\n\r\nexport interface FileNode extends AstNodeBase {\r\n type: 'file';\r\n children?: undefined;\r\n}\r\n\r\nexport type AstNode = DirNode | FileNode;\r\n\r\nexport interface AstOptions {\r\n /**\r\n * Spaces per indent level.\r\n * Default: 2.\r\n */\r\n indentStep?: number;\r\n\r\n /**\r\n * Parser mode:\r\n * - \"strict\": mismatched indentation / impossible structures are errors.\r\n * - \"loose\" : tries to recover from bad indentation, demotes some issues to warnings.\r\n *\r\n * Default: \"loose\".\r\n */\r\n mode?: AstMode;\r\n}\r\n\r\n/**\r\n * Full AST result: nodes + per-line meta + diagnostics.\r\n */\r\nexport interface StructureAst {\r\n /** Root-level nodes (depth 0). */\r\n rootNodes: AstNode[];\r\n /** All lines as seen in the source file. */\r\n lines: StructureAstLine[];\r\n /** Collected diagnostics (errors + warnings + infos). */\r\n diagnostics: Diagnostic[];\r\n /** Resolved options used by the parser. */\r\n options: Required<AstOptions>;\r\n}\r\n\r\n/**\r\n * Main entry: parse a structure text into an AST tree with diagnostics.\r\n *\r\n * - Does NOT throw on parse errors.\r\n * - Always returns something (even if diagnostics contain errors).\r\n * - In \"loose\" mode, attempts to repair:\r\n * - odd/misaligned indentation → snapped via relative depth rules with warnings.\r\n * - large indent jumps → treated as \"one level deeper\" with warnings.\r\n * - children under files → attached to nearest viable ancestor with warnings.\r\n */\r\nexport function parseStructureAst(\r\n text: string,\r\n opts: AstOptions = {},\r\n): StructureAst {\r\n const indentStep = opts.indentStep ?? 2;\r\n const mode: AstMode = opts.mode ?? 'loose';\r\n\r\n const diagnostics: Diagnostic[] = [];\r\n const lines: StructureAstLine[] = [];\r\n\r\n const rawLines = text.split(/\\r?\\n/);\r\n\r\n // First pass: classify + measure indentation.\r\n for (let i = 0; i < rawLines.length; i++) {\r\n const raw = rawLines[i];\r\n const lineNo = i + 1;\r\n\r\n const m = raw.match(/^(\\s*)(.*)$/);\r\n const indentRaw = m ? m[1] : '';\r\n const content = m ? m[2] : '';\r\n\r\n const {indentSpaces, hasTabs} = measureIndent(indentRaw, indentStep);\r\n\r\n if (hasTabs) {\r\n diagnostics.push({\r\n line: lineNo,\r\n message:\r\n 'Tabs detected in indentation. Consider using spaces only for consistent levels.',\r\n severity: mode === 'strict' ? 'warning' : 'info',\r\n code: 'indent-tabs',\r\n });\r\n }\r\n\r\n const trimmed = content.trim();\r\n let kind: LineKind;\r\n if (!trimmed) {\r\n kind = 'blank';\r\n } else if (trimmed.startsWith('#') || trimmed.startsWith('//')) {\r\n kind = 'comment';\r\n } else {\r\n kind = 'entry';\r\n }\r\n\r\n lines.push({\r\n index: i,\r\n lineNo,\r\n raw,\r\n kind,\r\n indentSpaces,\r\n content,\r\n });\r\n }\r\n\r\n const rootNodes: AstNode[] = [];\r\n const stack: AstNode[] = []; // nodes by depth index (0 = level 0, 1 = level 1, ...)\r\n\r\n const depthCtx: DepthContext = {\r\n lastIndentSpaces: null,\r\n lastDepth: null,\r\n lastWasFile: false,\r\n };\r\n\r\n for (const line of lines) {\r\n if (line.kind !== 'entry') continue;\r\n\r\n const {entry, depth, diags} = parseEntryLine(\r\n line,\r\n indentStep,\r\n mode,\r\n depthCtx,\r\n );\r\n diagnostics.push(...diags);\r\n\r\n if (!entry) {\r\n continue;\r\n }\r\n\r\n attachNode(entry, depth, line, rootNodes, stack, diagnostics, mode);\r\n depthCtx.lastWasFile = !entry.isDir;\r\n }\r\n\r\n return {\r\n rootNodes,\r\n lines,\r\n diagnostics,\r\n options: {\r\n indentStep,\r\n mode,\r\n },\r\n };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal: indentation measurement & depth fixing (relative model)\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction measureIndent(rawIndent: string, indentStep: number): {\r\n indentSpaces: number;\r\n hasTabs: boolean;\r\n} {\r\n let spaces = 0;\r\n let hasTabs = false;\r\n\r\n for (const ch of rawIndent) {\r\n if (ch === ' ') {\r\n spaces += 1;\r\n } else if (ch === '\\t') {\r\n hasTabs = true;\r\n // Treat tab as one level to avoid chaos. This is arbitrary but stable-ish.\r\n spaces += indentStep;\r\n }\r\n }\r\n\r\n return {indentSpaces: spaces, hasTabs};\r\n}\r\n\r\ninterface DepthContext {\r\n lastIndentSpaces: number | null;\r\n lastDepth: number | null;\r\n lastWasFile: boolean;\r\n}\r\n\r\n/**\r\n * Compute logical depth using a relative algorithm:\r\n *\r\n * First entry line:\r\n * - depth = 0\r\n *\r\n * For each subsequent entry line:\r\n * Let prevSpaces = lastIndentSpaces, prevDepth = lastDepth.\r\n *\r\n * - if spaces > prevSpaces:\r\n * - if spaces > prevSpaces + indentStep → warn about a \"skip\"\r\n * - depth = prevDepth + 1\r\n *\r\n * - else if spaces === prevSpaces:\r\n * - depth = prevDepth\r\n *\r\n * - else (spaces < prevSpaces):\r\n * - diff = prevSpaces - spaces\r\n * - steps = round(diff / indentStep)\r\n * - if diff is not a clean multiple → warn about misalignment\r\n * - depth = max(prevDepth - steps, 0)\r\n */\r\nfunction computeDepth(\r\n line: StructureAstLine,\r\n indentStep: number,\r\n mode: AstMode,\r\n ctx: DepthContext,\r\n diagnostics: Diagnostic[],\r\n): number {\r\n let spaces = line.indentSpaces;\r\n if (spaces < 0) spaces = 0;\r\n\r\n let depth: number;\r\n\r\n if (ctx.lastIndentSpaces == null || ctx.lastDepth == null) {\r\n // First entry line: treat as root.\r\n depth = 0;\r\n } else {\r\n const prevSpaces = ctx.lastIndentSpaces;\r\n const prevDepth = ctx.lastDepth;\r\n\r\n if (spaces > prevSpaces) {\r\n const diff = spaces - prevSpaces;\r\n\r\n // NEW: indenting under a file → child-of-file-loose\r\n if (ctx.lastWasFile) {\r\n diagnostics.push({\r\n line: line.lineNo,\r\n message:\r\n 'Entry appears indented under a file; treating it as a sibling of the file instead of a child.',\r\n severity: mode === 'strict' ? 'error' : 'warning',\r\n code: 'child-of-file-loose',\r\n });\r\n\r\n // Treat as sibling of the file, not a child:\r\n depth = prevDepth;\r\n } else {\r\n if (diff > indentStep) {\r\n diagnostics.push({\r\n line: line.lineNo,\r\n message: `Indentation jumps from ${prevSpaces} to ${spaces} spaces; treating as one level deeper.`,\r\n severity: mode === 'strict' ? 'error' : 'warning',\r\n code: 'indent-skip-level',\r\n });\r\n }\r\n depth = prevDepth + 1;\r\n }\r\n } else if (spaces === prevSpaces) {\r\n depth = prevDepth;\r\n } else {\r\n const diff = prevSpaces - spaces;\r\n const steps = Math.round(diff / indentStep);\r\n\r\n if (diff % indentStep !== 0) {\r\n diagnostics.push({\r\n line: line.lineNo,\r\n message: `Indentation decreases from ${prevSpaces} to ${spaces} spaces, which is not a multiple of indent step (${indentStep}).`,\r\n severity: mode === 'strict' ? 'error' : 'warning',\r\n code: 'indent-misaligned',\r\n });\r\n }\r\n\r\n depth = Math.max(prevDepth - steps, 0);\r\n }\r\n }\r\n\r\n ctx.lastIndentSpaces = spaces;\r\n ctx.lastDepth = depth;\r\n\r\n return depth;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal: entry line parsing (path + annotations)\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface ParsedEntry {\r\n segmentName: string;\r\n isDir: boolean;\r\n stub?: string;\r\n include?: string[];\r\n exclude?: string[];\r\n}\r\n\r\n/**\r\n * Parse a single entry line into a ParsedEntry + depth.\r\n */\r\nfunction parseEntryLine(\r\n line: StructureAstLine,\r\n indentStep: number,\r\n mode: AstMode,\r\n ctx: DepthContext,\r\n): {\r\n entry: ParsedEntry | null;\r\n depth: number;\r\n diags: Diagnostic[];\r\n} {\r\n const diags: Diagnostic[] = [];\r\n const depth = computeDepth(line, indentStep, mode, ctx, diags);\r\n\r\n // Extract before inline comment\r\n const {contentWithoutComment} = extractInlineCommentParts(line.content);\r\n const trimmed = contentWithoutComment.trim();\r\n if (!trimmed) {\r\n // Structural line that became empty after stripping inline comment; treat as no-op.\r\n return {entry: null, depth, diags};\r\n }\r\n\r\n const parts = trimmed.split(/\\s+/);\r\n const pathToken = parts[0];\r\n const annotationTokens = parts.slice(1);\r\n\r\n // Path sanity checks\r\n if (pathToken.includes(':')) {\r\n diags.push({\r\n line: line.lineNo,\r\n message:\r\n 'Path token contains \":\" which is reserved for annotations. This is likely a mistake.',\r\n severity: mode === 'strict' ? 'error' : 'warning',\r\n code: 'path-colon',\r\n });\r\n }\r\n\r\n const isDir = pathToken.endsWith('/');\r\n const segmentName = pathToken;\r\n\r\n let stub: string | undefined;\r\n const include: string[] = [];\r\n const exclude: string[] = [];\r\n\r\n for (const token of annotationTokens) {\r\n if (token.startsWith('@stub:')) {\r\n stub = token.slice('@stub:'.length);\r\n } else if (token.startsWith('@include:')) {\r\n const val = token.slice('@include:'.length);\r\n if (val) {\r\n include.push(\r\n ...val\r\n .split(',')\r\n .map((s) => s.trim())\r\n .filter(Boolean),\r\n );\r\n }\r\n } else if (token.startsWith('@exclude:')) {\r\n const val = token.slice('@exclude:'.length);\r\n if (val) {\r\n exclude.push(\r\n ...val\r\n .split(',')\r\n .map((s) => s.trim())\r\n .filter(Boolean),\r\n );\r\n }\r\n } else if (token.startsWith('@')) {\r\n diags.push({\r\n line: line.lineNo,\r\n message: `Unknown annotation token \"${token}\".`,\r\n severity: 'info',\r\n code: 'unknown-annotation',\r\n });\r\n }\r\n }\r\n\r\n const entry: ParsedEntry = {\r\n segmentName,\r\n isDir,\r\n stub,\r\n include: include.length ? include : undefined,\r\n exclude: exclude.length ? exclude : undefined,\r\n };\r\n\r\n return {entry, depth, diags};\r\n}\r\n\r\nexport function mapThrough(content: string) {\r\n let cutIndex = -1;\r\n const len = content.length;\r\n\r\n for (let i = 0; i < len; i++) {\r\n const ch = content[i];\r\n const prev = i > 0 ? content[i - 1] : '';\r\n\r\n // Inline \"# ...\"\r\n if (ch === '#') {\r\n if (i === 0) {\r\n // full-line comment; not our case (we only call this for \"entry\" lines)\r\n continue;\r\n }\r\n if (prev === ' ' || prev === '\\t') {\r\n cutIndex = i;\r\n break;\r\n }\r\n }\r\n\r\n // Inline \"// ...\"\r\n if (\r\n ch === '/' &&\r\n i + 1 < len &&\r\n content[i + 1] === '/' &&\r\n (prev === ' ' || prev === '\\t')\r\n ) {\r\n cutIndex = i;\r\n break;\r\n }\r\n }\r\n\r\n return cutIndex;\r\n}\r\n\r\n/**\r\n * Extracts the inline comment portion (if any) from the content area (no leading indent).\r\n */\r\nexport function extractInlineCommentParts(content: string): {\r\n contentWithoutComment: string;\r\n inlineComment: string | null;\r\n} {\r\n const cutIndex = mapThrough(content);\r\n\r\n if (cutIndex === -1) {\r\n return {\r\n contentWithoutComment: content,\r\n inlineComment: null,\r\n };\r\n }\r\n\r\n return {\r\n contentWithoutComment: content.slice(0, cutIndex),\r\n inlineComment: content.slice(cutIndex),\r\n };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal: tree construction\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction attachNode(\r\n entry: ParsedEntry,\r\n depth: number,\r\n line: StructureAstLine,\r\n rootNodes: AstNode[],\r\n stack: AstNode[],\r\n diagnostics: Diagnostic[],\r\n mode: AstMode,\r\n): void {\r\n const lineNo = line.lineNo;\r\n\r\n // Pop stack until we’re at or above the desired depth.\r\n while (stack.length > depth) {\r\n stack.pop();\r\n }\r\n\r\n let parent: DirNode | null = null;\r\n if (depth > 0) {\r\n const candidate = stack[depth - 1];\r\n if (!candidate) {\r\n // Indented but no parent; in strict mode error, in loose mode, treat as root.\r\n diagnostics.push({\r\n line: lineNo,\r\n message: `Entry has indent depth ${depth} but no parent at depth ${\r\n depth - 1\r\n }. Treating as root.`,\r\n severity: mode === 'strict' ? 'error' : 'warning',\r\n code: 'missing-parent',\r\n });\r\n } else if (candidate.type === 'file') {\r\n // Child under file, impossible by design.\r\n if (mode === 'strict') {\r\n diagnostics.push({\r\n line: lineNo,\r\n message: `Cannot attach child under file \"${candidate.path}\".`,\r\n severity: 'error',\r\n code: 'child-of-file',\r\n });\r\n // Force it to root to at least keep the node.\r\n } else {\r\n diagnostics.push({\r\n line: lineNo,\r\n message: `Entry appears under file \"${candidate.path}\". Attaching as sibling at depth ${\r\n candidate.depth\r\n }.`,\r\n severity: 'warning',\r\n code: 'child-of-file-loose',\r\n });\r\n // Treat as sibling at candidate's depth.\r\n while (stack.length > candidate.depth) {\r\n stack.pop();\r\n }\r\n }\r\n } else {\r\n parent = candidate as DirNode;\r\n }\r\n }\r\n\r\n const parentPath = parent ? parent.path.replace(/\\/$/, '') : '';\r\n const normalizedSegment = toPosixPath(entry.segmentName.replace(/\\/+$/, ''));\r\n const fullPath = parentPath\r\n ? `${parentPath}/${normalizedSegment}${entry.isDir ? '/' : ''}`\r\n : `${normalizedSegment}${entry.isDir ? '/' : ''}`;\r\n\r\n const baseNode: AstNodeBase = {\r\n type: entry.isDir ? 'dir' : 'file',\r\n name: entry.segmentName,\r\n depth,\r\n line: lineNo,\r\n path: fullPath,\r\n parent,\r\n ...(entry.stub ? {stub: entry.stub} : {}),\r\n ...(entry.include ? {include: entry.include} : {}),\r\n ...(entry.exclude ? {exclude: entry.exclude} : {}),\r\n };\r\n\r\n if (entry.isDir) {\r\n const dirNode: DirNode = {\r\n ...baseNode,\r\n type: 'dir',\r\n children: [],\r\n };\r\n\r\n if (parent) {\r\n parent.children.push(dirNode);\r\n } else {\r\n rootNodes.push(dirNode);\r\n }\r\n\r\n // Ensure stack[depth] is this dir.\r\n while (stack.length > depth) {\r\n stack.pop();\r\n }\r\n stack[depth] = dirNode;\r\n } else {\r\n const fileNode: FileNode = {\r\n ...baseNode,\r\n type: 'file',\r\n };\r\n\r\n if (parent) {\r\n parent.children.push(fileNode);\r\n } else {\r\n rootNodes.push(fileNode);\r\n }\r\n\r\n // Files themselves are NOT placed on the stack to prevent children,\r\n // but attachNode will repair children-under-file in loose mode.\r\n }\r\n}","// src/ast/format.ts\r\n\r\nimport {\r\n parseStructureAst,\r\n type AstMode,\r\n type StructureAst,\r\n type AstNode, extractInlineCommentParts,\r\n} from './parser';\r\nimport {FormatConfig} from \"../schema\";\r\n\r\nexport interface FormatOptions extends FormatConfig {\r\n /**\r\n * Spaces per indent level for re-printing entries.\r\n * Defaults to 2.\r\n */\r\n indentStep?: number;\r\n\r\n /**\r\n * Parser mode to use for the AST.\r\n * - \"loose\": attempt to repair mis-indents / bad parents (default).\r\n * - \"strict\": report issues as errors, less repair.\r\n */\r\n mode?: AstMode;\r\n\r\n /**\r\n * Normalize newlines to the dominant style in the original text (LF vs. CRLF).\r\n * Defaults to true.\r\n */\r\n normalizeNewlines?: boolean;\r\n\r\n /**\r\n * Trim trailing whitespace on non-entry lines (comments / blanks).\r\n * Defaults to true.\r\n */\r\n trimTrailingWhitespace?: boolean;\r\n\r\n /**\r\n * Whether to normalize annotation ordering and spacing:\r\n * name @stub:... @include:... @exclude:...\r\n * Defaults to true.\r\n */\r\n normalizeAnnotations?: boolean;\r\n}\r\n\r\nexport interface FormatResult {\r\n /** Formatted text. */\r\n text: string;\r\n /** Underlying AST that was used. */\r\n ast: StructureAst;\r\n}\r\n\r\n/**\r\n * Smart formatter for scaffold structure files.\r\n *\r\n * - Uses the loose AST parser (parseStructureAst) to understand structure.\r\n * - Auto-fixes indentation based on tree depth (indentStep).\r\n * - Keeps **all** blank lines and full-line comments in place.\r\n * - Preserves inline comments (# / //) on entry lines.\r\n * - Canonicalizes annotation order (stub → include → exclude) if enabled.\r\n *\r\n * It does **not** throw on invalid input:\r\n * - parseStructureAst always returns an AST + diagnostics.\r\n * - If something is catastrophically off (entry/node counts mismatch),\r\n * it falls back to a minimal normalization pass.\r\n */\r\nexport function formatStructureText(\r\n text: string,\r\n options: FormatOptions = {},\r\n): FormatResult {\r\n const indentStep = options.indentStep ?? 2;\r\n const mode: AstMode = options.mode ?? 'loose';\r\n const normalizeNewlines =\r\n options.normalizeNewlines === undefined ? true : options.normalizeNewlines;\r\n const trimTrailingWhitespace =\r\n options.trimTrailingWhitespace === undefined\r\n ? true\r\n : options.trimTrailingWhitespace;\r\n const normalizeAnnotations =\r\n options.normalizeAnnotations === undefined\r\n ? true\r\n : options.normalizeAnnotations;\r\n\r\n // 1. Parse to our \"smart\" AST (non-throwing).\r\n const ast = parseStructureAst(text, {\r\n indentStep,\r\n mode,\r\n });\r\n\r\n const rawLines = text.split(/\\r?\\n/);\r\n const lineCount = rawLines.length;\r\n\r\n // Sanity check: AST lines length should match raw lines length.\r\n if (ast.lines.length !== lineCount) {\r\n return {\r\n text: basicNormalize(text, {normalizeNewlines, trimTrailingWhitespace}),\r\n ast,\r\n };\r\n }\r\n\r\n // 2. Collect entry line indices and inline comments from the original text.\r\n const entryLineIndexes: number[] = [];\r\n const inlineComments: (string | null)[] = [];\r\n\r\n for (let i = 0; i < lineCount; i++) {\r\n const lineMeta = ast.lines[i];\r\n if (lineMeta.kind === 'entry') {\r\n entryLineIndexes.push(i);\r\n const {inlineComment} = extractInlineCommentParts(lineMeta.content);\r\n inlineComments.push(inlineComment);\r\n }\r\n }\r\n\r\n // 3. Flatten AST nodes in depth-first order to get an ordered node list.\r\n const flattened: { node: AstNode; level: number }[] = [];\r\n flattenAstNodes(ast.rootNodes, 0, flattened);\r\n\r\n if (flattened.length !== entryLineIndexes.length) {\r\n // If counts don't match, something is inconsistent – do not risk corruption.\r\n return {\r\n text: basicNormalize(text, {normalizeNewlines, trimTrailingWhitespace}),\r\n ast,\r\n };\r\n }\r\n\r\n // 4. Build canonical entry lines from AST nodes.\r\n const canonicalEntryLines: string[] = flattened.map(({node, level}) =>\r\n formatAstNodeLine(node, level, indentStep, normalizeAnnotations),\r\n );\r\n\r\n // 5. Merge canonical entry lines + inline comments back into original structure.\r\n const resultLines: string[] = [];\r\n let entryIdx = 0;\r\n\r\n for (let i = 0; i < lineCount; i++) {\r\n const lineMeta = ast.lines[i];\r\n const originalLine = rawLines[i];\r\n\r\n if (lineMeta.kind === 'entry') {\r\n const base = canonicalEntryLines[entryIdx].replace(/[ \\t]+$/g, '');\r\n const inline = inlineComments[entryIdx];\r\n entryIdx++;\r\n\r\n if (inline) {\r\n // Always ensure a single space before the inline comment marker.\r\n resultLines.push(base + ' ' + inline);\r\n } else {\r\n resultLines.push(base);\r\n }\r\n } else {\r\n let out = originalLine;\r\n if (trimTrailingWhitespace) {\r\n out = out.replace(/[ \\t]+$/g, '');\r\n }\r\n resultLines.push(out);\r\n }\r\n }\r\n\r\n const eol = normalizeNewlines ? detectPreferredEol(text) : getRawEol(text);\r\n return {\r\n text: resultLines.join(eol),\r\n ast,\r\n };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal helpers\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Fallback: basic normalization when we can't safely map AST ↔ text.\r\n */\r\nfunction basicNormalize(\r\n text: string,\r\n opts: { normalizeNewlines: boolean; trimTrailingWhitespace: boolean },\r\n): string {\r\n const lines = text.split(/\\r?\\n/);\r\n const normalizedLines = opts.trimTrailingWhitespace\r\n ? lines.map((line) => line.replace(/[ \\t]+$/g, ''))\r\n : lines;\r\n\r\n const eol = opts.normalizeNewlines ? detectPreferredEol(text) : getRawEol(text);\r\n return normalizedLines.join(eol);\r\n}\r\n\r\n/**\r\n * Detect whether the file is more likely LF or CRLF and reuse that.\r\n * If mixed or no clear signal, default to \"\\n\".\r\n */\r\nfunction detectPreferredEol(text: string): string {\r\n const crlfCount = (text.match(/\\r\\n/g) || []).length;\r\n const lfCount = (text.match(/(?<!\\r)\\n/g) || []).length;\r\n\r\n if (crlfCount === 0 && lfCount === 0) {\r\n return '\\n';\r\n }\r\n\r\n if (crlfCount > lfCount) {\r\n return '\\r\\n';\r\n }\r\n\r\n return '\\n';\r\n}\r\n\r\n/**\r\n * If you really want the raw style, detect only CRLF vs. LF.\r\n */\r\nfunction getRawEol(text: string): string {\r\n return text.includes('\\r\\n') ? '\\r\\n' : '\\n';\r\n}\r\n\r\n/**\r\n * Flatten AST nodes into a depth-first list while tracking indent level.\r\n */\r\nfunction flattenAstNodes(\r\n nodes: AstNode[],\r\n level: number,\r\n out: { node: AstNode; level: number }[],\r\n): void {\r\n for (const node of nodes) {\r\n out.push({node, level});\r\n if (node.type === 'dir' && node.children && node.children.length) {\r\n flattenAstNodes(node.children, level + 1, out);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Format a single AST node into one canonical line.\r\n *\r\n * - Uses `level * indentStep` spaces as indentation.\r\n * - Uses the node's `name` as provided by the parser (e.g. \"src/\" or \"index.ts\").\r\n * - Annotations are printed in a stable order if normalizeAnnotations is true:\r\n * @stub:..., @include:..., @exclude:...\r\n */\r\nfunction formatAstNodeLine(\r\n node: AstNode,\r\n level: number,\r\n indentStep: number,\r\n normalizeAnnotations: boolean,\r\n): string {\r\n const indent = ' '.repeat(indentStep * level);\r\n const baseName = node.name;\r\n\r\n if (!normalizeAnnotations) {\r\n return indent + baseName;\r\n }\r\n\r\n const tokens: string[] = [];\r\n\r\n if (node.stub) {\r\n tokens.push(`@stub:${node.stub}`);\r\n }\r\n if (node.include && node.include.length > 0) {\r\n tokens.push(`@include:${node.include.join(',')}`);\r\n }\r\n if (node.exclude && node.exclude.length > 0) {\r\n tokens.push(`@exclude:${node.exclude.join(',')}`);\r\n }\r\n\r\n const annotations = tokens.length ? ' ' + tokens.join(' ') : '';\r\n return indent + baseName + annotations;\r\n}","// src/core/structure-txt.ts\r\n\r\nimport type {StructureEntry, DirEntry, FileEntry} from '../schema';\r\nimport {toPosixPath} from '../util/fs-utils';\r\nimport {mapThrough} from \"../ast\";\r\n\r\ninterface ParsedLine {\r\n lineNo: number;\r\n indentSpaces: number;\r\n rawPath: string;\r\n stub?: string;\r\n include?: string[];\r\n exclude?: string[];\r\n}\r\n\r\n/**\r\n * Strip inline comments from a content segment.\r\n *\r\n * Supports:\r\n * - \"index.ts # comment\"\r\n * - \"index.ts // comment\"\r\n *\r\n * Rules:\r\n * - We assume leading indentation has already been removed.\r\n * - Leading '#' or '//' (full-line comments) are handled BEFORE this function.\r\n * - A comment starts at the first '#' or '//' that is\r\n * preceded by whitespace (space or tab).\r\n */\r\nfunction stripInlineComment(content: string): string {\r\n const cutIndex = mapThrough(content);\r\n if (cutIndex === -1) {\r\n return content.trimEnd();\r\n }\r\n\r\n return content.slice(0, cutIndex).trimEnd();\r\n}\r\n\r\n/**\r\n * Parse a single non-empty, non-comment line into a ParsedLine.\r\n * Supports inline annotations:\r\n * - @stub:name\r\n * - @include:pattern,pattern2\r\n * - @exclude:pattern,pattern2\r\n */\r\nfunction parseLine(line: string, lineNo: number): ParsedLine | null {\r\n const match = line.match(/^(\\s*)(.*)$/);\r\n if (!match) return null;\r\n\r\n const indentSpaces = match[1].length;\r\n let rest = match[2];\r\n\r\n // If line (after indent) is empty, skip\r\n if (!rest.trim()) return null;\r\n\r\n // Full-line comments after indent\r\n const trimmedRest = rest.trimStart();\r\n if (trimmedRest.startsWith('#') || trimmedRest.startsWith('//')) {\r\n return null;\r\n }\r\n\r\n // Strip inline comments (# or //) before parsing tokens\r\n const stripped = stripInlineComment(rest);\r\n const trimmed = stripped.trim();\r\n if (!trimmed) return null;\r\n\r\n const parts = trimmed.split(/\\s+/);\r\n if (!parts.length) return null;\r\n\r\n const pathToken = parts[0];\r\n\r\n // 🚫 Reserve \":\" for annotations only – paths may not contain it.\r\n if (pathToken.includes(':')) {\r\n throw new Error(\r\n `structure.txt: \":\" is reserved for annotations (@stub:, @include:, etc). ` +\r\n `Invalid path \"${pathToken}\" on line ${lineNo}.`,\r\n );\r\n }\r\n\r\n let stub: string | undefined;\r\n const include: string[] = [];\r\n const exclude: string[] = [];\r\n\r\n for (const token of parts.slice(1)) {\r\n if (token.startsWith('@stub:')) {\r\n stub = token.slice('@stub:'.length);\r\n } else if (token.startsWith('@include:')) {\r\n const val = token.slice('@include:'.length);\r\n if (val) {\r\n include.push(\r\n ...val\r\n .split(',')\r\n .map((s) => s.trim())\r\n .filter(Boolean),\r\n );\r\n }\r\n } else if (token.startsWith('@exclude:')) {\r\n const val = token.slice('@exclude:'.length);\r\n if (val) {\r\n exclude.push(\r\n ...val\r\n .split(',')\r\n .map((s) => s.trim())\r\n .filter(Boolean),\r\n );\r\n }\r\n }\r\n }\r\n\r\n return {\r\n lineNo,\r\n indentSpaces,\r\n rawPath: pathToken,\r\n stub,\r\n include: include.length ? include : undefined,\r\n exclude: exclude.length ? exclude : undefined,\r\n };\r\n}\r\n\r\n/**\r\n * Convert a structure.txt content into a nested StructureEntry[].\r\n *\r\n * Rules:\r\n * - Indentation is **indentStep** spaces per level (default: 2).\r\n * - Indent must be a multiple of indentStep.\r\n * - You cannot \"skip\" levels (no jumping from level 0 to 2 directly).\r\n * - **Only directories can have children**:\r\n * - If you indent under a file, an error is thrown.\r\n * - Folders must end with \"/\" in the txt; paths are normalized to POSIX.\r\n */\r\nexport function parseStructureText(\r\n text: string,\r\n indentStep = 2,\r\n): StructureEntry[] {\r\n const lines = text.split(/\\r?\\n/);\r\n const parsed: ParsedLine[] = [];\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const lineNo = i + 1;\r\n const p = parseLine(lines[i], lineNo);\r\n if (p) parsed.push(p);\r\n }\r\n\r\n const rootEntries: StructureEntry[] = [];\r\n\r\n type StackItem = {\r\n level: number;\r\n entry: DirEntry | FileEntry;\r\n isDir: boolean;\r\n };\r\n\r\n const stack: StackItem[] = [];\r\n\r\n for (const p of parsed) {\r\n const {indentSpaces, lineNo} = p;\r\n\r\n if (indentSpaces % indentStep !== 0) {\r\n throw new Error(\r\n `structure.txt: Invalid indent on line ${lineNo}. ` +\r\n `Indent must be multiples of ${indentStep} spaces.`,\r\n );\r\n }\r\n\r\n const level = indentSpaces / indentStep;\r\n\r\n // Determine parent level and enforce no skipping\r\n if (level > stack.length) {\r\n // e.g. current stack depth 1, but line level=3 is invalid\r\n if (level !== stack.length + 1) {\r\n throw new Error(\r\n `structure.txt: Invalid indentation on line ${lineNo}. ` +\r\n `You cannot jump more than one level at a time. ` +\r\n `Previous depth: ${stack.length}, this line depth: ${level}.`,\r\n );\r\n }\r\n }\r\n\r\n // If this line is indented (level > 0), parent must exist and must be dir\r\n if (level > 0) {\r\n const parent = stack[level - 1]; // parent level is (level - 1)\r\n if (!parent) {\r\n throw new Error(\r\n `structure.txt: Indented entry without a parent on line ${lineNo}.`,\r\n );\r\n }\r\n if (!parent.isDir) {\r\n throw new Error(\r\n `structure.txt: Cannot indent under a file on line ${lineNo}. ` +\r\n `Files cannot have children. Parent: \"${parent.entry.path}\".`,\r\n );\r\n }\r\n }\r\n\r\n const isDir = p.rawPath.endsWith('/');\r\n const clean = p.rawPath.replace(/\\/$/, '');\r\n const basePath = toPosixPath(clean);\r\n\r\n // Pop stack until we are at the correct depth\r\n while (stack.length > level) {\r\n stack.pop();\r\n }\r\n\r\n const parent = stack[stack.length - 1]?.entry as DirEntry | undefined;\r\n const parentPath = parent ? parent.path.replace(/\\/$/, '') : '';\r\n\r\n const fullPath = parentPath\r\n ? `${parentPath}/${basePath}${isDir ? '/' : ''}`\r\n : `${basePath}${isDir ? '/' : ''}`;\r\n\r\n if (isDir) {\r\n const dirEntry: DirEntry = {\r\n type: 'dir',\r\n path: fullPath,\r\n children: [],\r\n ...(p.stub ? {stub: p.stub} : {}),\r\n ...(p.include ? {include: p.include} : {}),\r\n ...(p.exclude ? {exclude: p.exclude} : {}),\r\n };\r\n\r\n if (parent && parent.type === 'dir') {\r\n parent.children = parent.children ?? [];\r\n parent.children.push(dirEntry);\r\n } else if (!parent) {\r\n rootEntries.push(dirEntry);\r\n }\r\n\r\n stack.push({level, entry: dirEntry, isDir: true});\r\n } else {\r\n const fileEntry: FileEntry = {\r\n type: 'file',\r\n path: fullPath,\r\n ...(p.stub ? {stub: p.stub} : {}),\r\n ...(p.include ? {include: p.include} : {}),\r\n ...(p.exclude ? {exclude: p.exclude} : {}),\r\n };\r\n\r\n if (parent && parent.type === 'dir') {\r\n parent.children = parent.children ?? [];\r\n parent.children.push(fileEntry);\r\n } else if (!parent) {\r\n rootEntries.push(fileEntry);\r\n }\r\n\r\n // We still push files into the stack at this level so that\r\n // bad indentation under them can be detected and rejected.\r\n stack.push({level, entry: fileEntry, isDir: false});\r\n }\r\n }\r\n\r\n return rootEntries;\r\n}","// src/core/resolve-structure.ts\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport type {\r\n ScaffoldConfig,\r\n StructureEntry,\r\n StructureGroupConfig,\r\n} from '../schema';\r\nimport { parseStructureText } from './structure-txt';\r\nimport { defaultLogger } from '../util/logger';\r\n\r\nconst logger = defaultLogger.child('[structure]');\r\n\r\nexport function resolveGroupStructure(\r\n scaffoldDir: string,\r\n group: StructureGroupConfig,\r\n): StructureEntry[] {\r\n if (group.structure && group.structure.length) {\r\n logger.debug(`Using inline structure for group \"${group.name}\"`);\r\n return group.structure;\r\n }\r\n\r\n const fileName = group.structureFile ?? `${group.name}.txt`;\r\n const filePath = path.join(scaffoldDir, fileName);\r\n\r\n if (!fs.existsSync(filePath)) {\r\n throw new Error(\r\n `@timeax/scaffold: Group \"${group.name}\" has no structure. ` +\r\n `Expected file \"${fileName}\" in \"${scaffoldDir}\".`,\r\n );\r\n }\r\n\r\n logger.debug(`Reading structure for group \"${group.name}\" from ${filePath}`);\r\n const raw = fs.readFileSync(filePath, 'utf8');\r\n return parseStructureText(raw);\r\n}\r\n\r\n/**\r\n * Legacy single-structure mode (no groups defined).\r\n */\r\nexport function resolveSingleStructure(\r\n scaffoldDir: string,\r\n config: ScaffoldConfig,\r\n): StructureEntry[] {\r\n if (config.structure && config.structure.length) {\r\n logger.debug('Using inline single structure (no groups)');\r\n return config.structure;\r\n }\r\n\r\n const fileName = config.structureFile ?? 'structure.txt';\r\n const filePath = path.join(scaffoldDir, fileName);\r\n\r\n if (!fs.existsSync(filePath)) {\r\n throw new Error(\r\n `@timeax/scaffold: No structure defined. ` +\r\n `Expected \"${fileName}\" in \"${scaffoldDir}\".`,\r\n );\r\n }\r\n\r\n logger.debug(`Reading single structure from ${filePath}`);\r\n const raw = fs.readFileSync(filePath, 'utf8');\r\n return parseStructureText(raw);\r\n}","// src/core/cache-manager.ts\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport { ensureDirSync, toPosixPath } from '../util/fs-utils';\r\nimport { defaultLogger } from '../util/logger';\r\n\r\nconst logger = defaultLogger.child('[cache]');\r\n\r\nexport interface CacheEntry {\r\n /**\r\n * Path relative to the *project root* (global root), POSIX style.\r\n */\r\n path: string;\r\n\r\n createdAt: string;\r\n sizeAtCreate: number;\r\n createdByStub?: string;\r\n groupName?: string;\r\n groupRoot?: string;\r\n}\r\n\r\nexport interface CacheFile {\r\n version: 1;\r\n entries: Record<string, CacheEntry>;\r\n}\r\n\r\nconst DEFAULT_CACHE: CacheFile = {\r\n version: 1,\r\n entries: {},\r\n};\r\n\r\nexport class CacheManager {\r\n private cache: CacheFile = DEFAULT_CACHE;\r\n\r\n constructor(\r\n private readonly projectRoot: string,\r\n private readonly cacheFileRelPath: string,\r\n ) { }\r\n\r\n private get cachePathAbs(): string {\r\n return path.resolve(this.projectRoot, this.cacheFileRelPath);\r\n }\r\n\r\n load(): void {\r\n const cachePath = this.cachePathAbs;\r\n if (!fs.existsSync(cachePath)) {\r\n this.cache = { ...DEFAULT_CACHE, entries: {} };\r\n return;\r\n }\r\n\r\n try {\r\n const raw = fs.readFileSync(cachePath, 'utf8');\r\n const parsed = JSON.parse(raw) as CacheFile;\r\n if (parsed.version === 1 && parsed.entries) {\r\n this.cache = parsed;\r\n } else {\r\n logger.warn('Cache file version mismatch or invalid, resetting cache.');\r\n this.cache = { ...DEFAULT_CACHE, entries: {} };\r\n }\r\n } catch (err) {\r\n logger.warn('Failed to read cache file, resetting cache.', err);\r\n this.cache = { ...DEFAULT_CACHE, entries: {} };\r\n }\r\n }\r\n\r\n save(): void {\r\n const cachePath = this.cachePathAbs;\r\n const dir = path.dirname(cachePath);\r\n ensureDirSync(dir);\r\n fs.writeFileSync(cachePath, JSON.stringify(this.cache, null, 2), 'utf8');\r\n }\r\n\r\n get(relPath: string): CacheEntry | undefined {\r\n const key = toPosixPath(relPath);\r\n return this.cache.entries[key];\r\n }\r\n\r\n set(entry: CacheEntry): void {\r\n const key = toPosixPath(entry.path);\r\n this.cache.entries[key] = {\r\n ...entry,\r\n path: key,\r\n };\r\n }\r\n\r\n delete(relPath: string): void {\r\n const key = toPosixPath(relPath);\r\n delete this.cache.entries[key];\r\n }\r\n\r\n allPaths(): string[] {\r\n return Object.keys(this.cache.entries);\r\n }\r\n\r\n allEntries(): CacheEntry[] {\r\n return Object.values(this.cache.entries);\r\n }\r\n}","// src/core/hook-runner.ts\r\n\r\nimport { minimatch } from 'minimatch';\r\nimport type {\r\n ScaffoldConfig,\r\n HookContext,\r\n RegularHookKind,\r\n StubHookKind,\r\n StubConfig,\r\n RegularHookConfig,\r\n StubHookConfig,\r\n} from '../schema';\r\n\r\nfunction matchesFilter(\r\n pathRel: string,\r\n cfg: { include?: string[]; exclude?: string[]; files?: string[] },\r\n): boolean {\r\n const { include, exclude, files } = cfg;\r\n\r\n const patterns: string[] = [];\r\n if (include?.length) patterns.push(...include);\r\n if (files?.length) patterns.push(...files);\r\n\r\n if (patterns.length) {\r\n const ok = patterns.some((p) => minimatch(pathRel, p));\r\n if (!ok) return false;\r\n }\r\n\r\n if (exclude?.length) {\r\n const blocked = exclude.some((p) => minimatch(pathRel, p));\r\n if (blocked) return false;\r\n }\r\n\r\n return true;\r\n}\r\n\r\nexport class HookRunner {\r\n constructor(private readonly config: ScaffoldConfig) { }\r\n\r\n async runRegular(kind: RegularHookKind, ctx: HookContext): Promise<void> {\r\n const configs: RegularHookConfig[] = this.config.hooks?.[kind] ?? [];\r\n for (const cfg of configs) {\r\n if (!matchesFilter(ctx.targetPath, cfg)) continue;\r\n await cfg.fn(ctx);\r\n }\r\n }\r\n\r\n private getStubConfig(stubName?: string): StubConfig | undefined {\r\n if (!stubName) return undefined;\r\n return this.config.stubs?.[stubName];\r\n }\r\n\r\n async runStub(kind: StubHookKind, ctx: HookContext): Promise<void> {\r\n const stub = this.getStubConfig(ctx.stubName);\r\n if (!stub?.hooks) return;\r\n\r\n const configs: StubHookConfig[] =\r\n kind === 'preStub'\r\n ? stub.hooks.preStub ?? []\r\n : stub.hooks.postStub ?? [];\r\n\r\n for (const cfg of configs) {\r\n if (!matchesFilter(ctx.targetPath, cfg)) continue;\r\n await cfg.fn(ctx);\r\n }\r\n }\r\n\r\n async renderStubContent(ctx: HookContext): Promise<string | undefined> {\r\n const stub = this.getStubConfig(ctx.stubName);\r\n if (!stub?.getContent) return undefined;\r\n return stub.getContent(ctx);\r\n }\r\n}","// src/core/apply-structure.ts\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport type {\r\n ScaffoldConfig,\r\n StructureEntry,\r\n FileEntry,\r\n DirEntry,\r\n HookContext,\r\n} from '../schema';\r\nimport { CacheManager } from './cache-manager';\r\nimport { HookRunner } from './hook-runner';\r\nimport {\r\n ensureDirSync,\r\n statSafeSync,\r\n toProjectRelativePath,\r\n toPosixPath,\r\n} from '../util/fs-utils';\r\nimport type { Logger } from '../util/logger';\r\nimport { defaultLogger } from '../util/logger';\r\n\r\nexport interface InteractiveDeleteParams {\r\n absolutePath: string;\r\n relativePath: string; // project-root relative, POSIX\r\n size: number;\r\n createdByStub?: string;\r\n groupName?: string;\r\n}\r\n\r\nexport interface ApplyOptions {\r\n config: ScaffoldConfig;\r\n\r\n /**\r\n * Global project root for this run.\r\n */\r\n projectRoot: string;\r\n\r\n /**\r\n * Absolute directory where this structure group should be applied.\r\n * For grouped mode, this is projectRoot + group.root.\r\n * For single mode, this will simply be projectRoot.\r\n */\r\n baseDir: string;\r\n\r\n /**\r\n * Which structure entries to apply (already resolved from txt or inline).\r\n */\r\n structure: StructureEntry[];\r\n\r\n cache: CacheManager;\r\n hooks: HookRunner;\r\n\r\n /**\r\n * Optional group metadata (only set for groups).\r\n */\r\n groupName?: string;\r\n groupRoot?: string;\r\n\r\n /**\r\n * Optional override for deletion threshold.\r\n * Falls back to config.sizePromptThreshold or internal default.\r\n */\r\n sizePromptThreshold?: number;\r\n\r\n /**\r\n * Optional interactive delete callback.\r\n * Should ask the user and return 'delete' or 'keep'.\r\n */\r\n interactiveDelete?: (\r\n params: InteractiveDeleteParams,\r\n ) => Promise<'delete' | 'keep'>;\r\n\r\n /**\r\n * Optional logger; defaults to defaultLogger.child('[apply]').\r\n */\r\n logger?: Logger;\r\n}\r\n\r\nexport async function applyStructure(opts: ApplyOptions): Promise<void> {\r\n const {\r\n config,\r\n projectRoot,\r\n baseDir,\r\n structure,\r\n cache,\r\n hooks,\r\n groupName,\r\n groupRoot,\r\n sizePromptThreshold,\r\n interactiveDelete,\r\n } = opts;\r\n\r\n const logger =\r\n opts.logger ?? defaultLogger.child(groupName ? `[apply:${groupName}]` : '[apply]');\r\n\r\n const desiredPaths = new Set<string>(); // project-root relative, POSIX\r\n\r\n const threshold = sizePromptThreshold ?? config.sizePromptThreshold ?? 128 * 1024;\r\n\r\n async function walk(entry: StructureEntry, inheritedStub?: string): Promise<void> {\r\n const effectiveStub = entry.stub ?? inheritedStub;\r\n if (entry.type === 'dir') {\r\n await handleDir(entry as DirEntry, effectiveStub);\r\n } else {\r\n await handleFile(entry as FileEntry, effectiveStub);\r\n }\r\n }\r\n\r\n async function handleDir(entry: DirEntry, inheritedStub?: string): Promise<void> {\r\n const relFromBase = entry.path.replace(/^[./]+/, '');\r\n const absDir = path.resolve(baseDir, relFromBase);\r\n const relFromRoot = toPosixPath(\r\n toProjectRelativePath(projectRoot, absDir),\r\n );\r\n\r\n desiredPaths.add(relFromRoot);\r\n\r\n ensureDirSync(absDir);\r\n\r\n const nextStub = entry.stub ?? inheritedStub;\r\n\r\n if (entry.children) {\r\n for (const child of entry.children) {\r\n // eslint-disable-next-line no-await-in-loop\r\n await walk(child, nextStub);\r\n }\r\n }\r\n }\r\n\r\n async function handleFile(entry: FileEntry, inheritedStub?: string): Promise<void> {\r\n const relFromBase = entry.path.replace(/^[./]+/, '');\r\n const absFile = path.resolve(baseDir, relFromBase);\r\n const relFromRoot = toPosixPath(\r\n toProjectRelativePath(projectRoot, absFile),\r\n );\r\n\r\n desiredPaths.add(relFromRoot);\r\n\r\n const stubName = entry.stub ?? inheritedStub;\r\n\r\n const ctx: HookContext = {\r\n projectRoot,\r\n targetPath: relFromRoot,\r\n absolutePath: absFile,\r\n isDirectory: false,\r\n stubName,\r\n };\r\n\r\n // If file already exists, do not overwrite; just ensure hooks\r\n if (fs.existsSync(absFile)) {\r\n return;\r\n }\r\n\r\n await hooks.runRegular('preCreateFile', ctx);\r\n\r\n const dir = path.dirname(absFile);\r\n ensureDirSync(dir);\r\n\r\n if (stubName) {\r\n await hooks.runStub('preStub', ctx);\r\n }\r\n\r\n let content = '';\r\n const stubContent = await hooks.renderStubContent(ctx);\r\n if (typeof stubContent === 'string') {\r\n content = stubContent;\r\n }\r\n\r\n fs.writeFileSync(absFile, content, 'utf8');\r\n const stats = fs.statSync(absFile);\r\n\r\n cache.set({\r\n path: relFromRoot,\r\n createdAt: new Date().toISOString(),\r\n sizeAtCreate: stats.size,\r\n createdByStub: stubName,\r\n groupName,\r\n groupRoot,\r\n });\r\n\r\n logger.info(`created ${relFromRoot}`);\r\n\r\n if (stubName) {\r\n await hooks.runStub('postStub', ctx);\r\n }\r\n\r\n await hooks.runRegular('postCreateFile', ctx);\r\n }\r\n\r\n // 1) Create/update from structure\r\n for (const entry of structure) {\r\n // eslint-disable-next-line no-await-in-loop\r\n await walk(entry);\r\n }\r\n\r\n // 2) Handle deletions: any cached path not in desiredPaths\r\n for (const cachedPath of cache.allPaths()) {\r\n if (desiredPaths.has(cachedPath)) continue;\r\n\r\n const abs = path.resolve(projectRoot, cachedPath);\r\n const stats = statSafeSync(abs);\r\n\r\n if (!stats) {\r\n cache.delete(cachedPath);\r\n continue;\r\n }\r\n\r\n // Only handle files here; dirs are not tracked in cache.\r\n if (!stats.isFile()) {\r\n cache.delete(cachedPath);\r\n continue;\r\n }\r\n\r\n const entry = cache.get(cachedPath);\r\n const ctx: HookContext = {\r\n projectRoot,\r\n targetPath: cachedPath,\r\n absolutePath: abs,\r\n isDirectory: false,\r\n stubName: entry?.createdByStub,\r\n };\r\n\r\n await hooks.runRegular('preDeleteFile', ctx);\r\n\r\n let shouldDelete = true;\r\n if (stats.size > threshold && interactiveDelete) {\r\n const res = await interactiveDelete({\r\n absolutePath: abs,\r\n relativePath: cachedPath,\r\n size: stats.size,\r\n createdByStub: entry?.createdByStub,\r\n groupName: entry?.groupName,\r\n });\r\n\r\n if (res === 'keep') {\r\n shouldDelete = false;\r\n cache.delete(cachedPath); // user takes ownership\r\n logger.info(`keeping ${cachedPath} (removed from cache)`);\r\n }\r\n }\r\n\r\n if (shouldDelete) {\r\n try {\r\n fs.unlinkSync(abs);\r\n logger.info(`deleted ${cachedPath}`);\r\n } catch (err) {\r\n logger.warn(`failed to delete ${cachedPath}`, err);\r\n }\r\n\r\n cache.delete(cachedPath);\r\n await hooks.runRegular('postDeleteFile', ctx);\r\n }\r\n }\r\n}","// src/core/scan-structure.ts\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport { minimatch } from 'minimatch';\r\n\r\nimport {\r\n ScanStructureOptions,\r\n ScanFromConfigOptions,\r\n StructureGroupConfig,\r\n ScaffoldConfig,\r\n} from '../schema';\r\nimport { toPosixPath, ensureDirSync } from '../util/fs-utils';\r\nimport { loadScaffoldConfig } from './config-loader';\r\nimport { defaultLogger } from '../util/logger';\r\n\r\nconst logger = defaultLogger.child('[scan]');\r\n\r\nconst DEFAULT_IGNORE: string[] = [\r\n 'node_modules/**',\r\n '.git/**',\r\n 'dist/**',\r\n 'build/**',\r\n '.turbo/**',\r\n '.next/**',\r\n 'coverage/**',\r\n];\r\n\r\n/**\r\n * Generate a structure.txt-style tree from an existing directory.\r\n *\r\n * Indenting:\r\n * - 2 spaces per level.\r\n * - Directories suffixed with \"/\".\r\n * - No stub/include/exclude annotations are guessed (plain tree).\r\n */\r\nexport function scanDirectoryToStructureText(\r\n rootDir: string,\r\n options: ScanStructureOptions = {},\r\n): string {\r\n const absRoot = path.resolve(rootDir);\r\n const lines: string[] = [];\r\n\r\n const ignorePatterns = options.ignore ?? DEFAULT_IGNORE;\r\n const maxDepth = options.maxDepth ?? Infinity;\r\n\r\n function isIgnored(absPath: string): boolean {\r\n const rel = toPosixPath(path.relative(absRoot, absPath));\r\n if (!rel || rel === '.') return false;\r\n return ignorePatterns.some((pattern) =>\r\n minimatch(rel, pattern, { dot: true }),\r\n );\r\n }\r\n\r\n function walk(currentAbs: string, depth: number) {\r\n if (depth > maxDepth) return;\r\n\r\n let dirents: fs.Dirent[];\r\n try {\r\n dirents = fs.readdirSync(currentAbs, { withFileTypes: true });\r\n } catch {\r\n return;\r\n }\r\n\r\n // Sort: directories first, then files, both alphabetically\r\n dirents.sort((a, b) => {\r\n if (a.isDirectory() && !b.isDirectory()) return -1;\r\n if (!a.isDirectory() && b.isDirectory()) return 1;\r\n return a.name.localeCompare(b.name);\r\n });\r\n\r\n for (const dirent of dirents) {\r\n const name = dirent.name;\r\n const absPath = path.join(currentAbs, name);\r\n\r\n if (isIgnored(absPath)) continue;\r\n\r\n const indent = ' '.repeat(depth);\r\n if (dirent.isDirectory()) {\r\n lines.push(`${indent}${name}/`);\r\n walk(absPath, depth + 1);\r\n } else if (dirent.isFile()) {\r\n lines.push(`${indent}${name}`);\r\n }\r\n // symlinks etc. are skipped for now\r\n }\r\n }\r\n\r\n walk(absRoot, 0);\r\n return lines.join('\\n');\r\n}\r\n\r\n/**\r\n * Result of scanning based on the scaffold config.\r\n *\r\n * You can use `structureFilePath` + `text` to write out group structure files.\r\n */\r\nexport interface ScanFromConfigResult {\r\n groupName: string;\r\n groupRoot: string;\r\n structureFileName: string;\r\n structureFilePath: string;\r\n text: string;\r\n}\r\n\r\n/**\r\n * Scan the project using the scaffold config and its groups.\r\n *\r\n * - If `config.groups` exists and is non-empty:\r\n * - scans each group's `root` (relative to projectRoot)\r\n * - produces text suitable for that group's structure file\r\n * - Otherwise:\r\n * - scans the single `projectRoot` and produces text for a single structure file.\r\n *\r\n * NOTE: This function does NOT write files; it just returns what should be written.\r\n * The CLI (or caller) decides whether/where to save.\r\n */\r\nexport async function scanProjectFromConfig(\r\n cwd: string,\r\n options: ScanFromConfigOptions = {},\r\n): Promise<ScanFromConfigResult[]> {\r\n const { config, scaffoldDir, projectRoot } = await loadScaffoldConfig(cwd, {\r\n scaffoldDir: options.scaffoldDir,\r\n });\r\n\r\n const ignorePatterns = options.ignore ?? DEFAULT_IGNORE;\r\n const maxDepth = options.maxDepth ?? Infinity;\r\n const onlyGroups = options.groups;\r\n\r\n const results: ScanFromConfigResult[] = [];\r\n\r\n function scanGroup(\r\n cfg: ScaffoldConfig,\r\n group: StructureGroupConfig,\r\n ): ScanFromConfigResult {\r\n const rootAbs = path.resolve(projectRoot, group.root);\r\n const text = scanDirectoryToStructureText(rootAbs, {\r\n ignore: ignorePatterns,\r\n maxDepth,\r\n });\r\n\r\n const structureFileName = group.structureFile ?? `${group.name}.txt`;\r\n const structureFilePath = path.join(scaffoldDir, structureFileName);\r\n\r\n return {\r\n groupName: group.name,\r\n groupRoot: group.root,\r\n structureFileName,\r\n structureFilePath,\r\n text,\r\n };\r\n }\r\n\r\n if (config.groups && config.groups.length > 0) {\r\n logger.debug(\r\n `Scanning project from config with ${config.groups.length} group(s).`,\r\n );\r\n\r\n for (const group of config.groups) {\r\n if (onlyGroups && !onlyGroups.includes(group.name)) {\r\n continue;\r\n }\r\n const result = scanGroup(config, group);\r\n results.push(result);\r\n }\r\n } else {\r\n // Single-root mode: scan the whole projectRoot\r\n logger.debug('Scanning project in single-root mode (no groups).');\r\n\r\n const text = scanDirectoryToStructureText(projectRoot, {\r\n ignore: ignorePatterns,\r\n maxDepth,\r\n });\r\n\r\n const structureFileName = config.structureFile ?? 'structure.txt';\r\n const structureFilePath = path.join(scaffoldDir, structureFileName);\r\n\r\n results.push({\r\n groupName: 'default',\r\n groupRoot: '.',\r\n structureFileName,\r\n structureFilePath,\r\n text,\r\n });\r\n }\r\n\r\n return results;\r\n}\r\n\r\n/**\r\n * Convenience helper: write scan results to their structure files.\r\n *\r\n * This will ensure the scaffold directory exists and overwrite existing\r\n * structure files.\r\n */\r\nexport async function writeScannedStructuresFromConfig(\r\n cwd: string,\r\n options: ScanFromConfigOptions = {},\r\n): Promise<void> {\r\n const { scaffoldDir } = await loadScaffoldConfig(cwd, {\r\n scaffoldDir: options.scaffoldDir,\r\n });\r\n\r\n ensureDirSync(scaffoldDir);\r\n\r\n const results = await scanProjectFromConfig(cwd, options);\r\n\r\n for (const result of results) {\r\n fs.writeFileSync(result.structureFilePath, result.text, 'utf8');\r\n logger.info(\r\n `Wrote structure for group \"${result.groupName}\" to ${result.structureFilePath}`,\r\n );\r\n }\r\n}\r\n\r\n\r\n\r\nexport interface EnsureStructuresResult {\r\n created: string[];\r\n existing: string[];\r\n}\r\n\r\n/**\r\n * Ensure all structure files declared in the config exist.\r\n *\r\n * - Grouped mode: one file per group (group.structureFile || `${group.name}.txt`)\r\n * - Single-root mode: config.structureFile || \"structure.txt\"\r\n *\r\n * Existing files are left untouched. Only missing files are created with\r\n * a small header comment.\r\n */\r\nexport async function ensureStructureFilesFromConfig(\r\n cwd: string,\r\n options: { scaffoldDirOverride?: string } = {},\r\n): Promise<EnsureStructuresResult> {\r\n const { config, scaffoldDir } = await loadScaffoldConfig(cwd, {\r\n scaffoldDir: options.scaffoldDirOverride,\r\n });\r\n\r\n ensureDirSync(scaffoldDir);\r\n\r\n const created: string[] = [];\r\n const existing: string[] = [];\r\n\r\n const seen = new Set<string>();\r\n\r\n const ensureFile = (fileName: string) => {\r\n if (!fileName) return;\r\n\r\n const filePath = path.join(scaffoldDir, fileName);\r\n const key = path.resolve(filePath);\r\n\r\n if (seen.has(key)) return;\r\n seen.add(key);\r\n\r\n if (fs.existsSync(filePath)) {\r\n existing.push(filePath);\r\n return;\r\n }\r\n\r\n const header =\r\n `# ${fileName}\\n` +\r\n `# Structure file for @timeax/scaffold\\n` +\r\n `# Define your desired folders/files here.\\n`;\r\n\r\n fs.writeFileSync(filePath, header, 'utf8');\r\n created.push(filePath);\r\n };\r\n\r\n if (config.groups && config.groups.length > 0) {\r\n for (const group of config.groups) {\r\n const fileName = group.structureFile ?? `${group.name}.txt`;\r\n ensureFile(fileName);\r\n }\r\n } else {\r\n const fileName = config.structureFile ?? 'structure.txt';\r\n ensureFile(fileName);\r\n }\r\n\r\n logger.debug(\r\n `ensureStructureFilesFromConfig: created=${created.length}, existing=${existing.length}`,\r\n );\r\n\r\n return { created, existing };\r\n}","// src/core/format.ts\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport {formatStructureText} from '../ast';\r\nimport type {ScaffoldConfig, FormatConfig} from '../schema';\r\nimport {SCAFFOLD_ROOT_DIR} from '..';\r\n\r\ninterface FormatFromConfigOptions {\r\n /**\r\n * If true, force formatting even if config.format?.enabled === false.\r\n * This is what `--format` will use.\r\n */\r\n force?: boolean;\r\n}\r\n\r\n/**\r\n * Return the list of structure files we expect for this config.\r\n * (mirrors your scan / structures logic: groups vs single-root).\r\n */\r\nexport function getStructureFilesFromConfig(\r\n projectRoot: string,\r\n scaffoldDir: string,\r\n config: ScaffoldConfig,\r\n): string[] {\r\n const baseDir = path.resolve(projectRoot, scaffoldDir || SCAFFOLD_ROOT_DIR);\r\n\r\n const files: string[] = [];\r\n\r\n if (config.groups && config.groups.length > 0) {\r\n for (const group of config.groups) {\r\n const structureFile =\r\n group.structureFile && group.structureFile.trim().length\r\n ? group.structureFile\r\n : `${group.name}.txt`;\r\n\r\n files.push(path.join(baseDir, structureFile));\r\n }\r\n } else {\r\n const structureFile = config.structureFile || 'structure.txt';\r\n files.push(path.join(baseDir, structureFile));\r\n }\r\n\r\n return files;\r\n}\r\n\r\n/**\r\n * Format all existing structure files according to config.format.\r\n */\r\nexport async function formatStructureFilesFromConfig(\r\n projectRoot: string,\r\n scaffoldDir: string,\r\n config: ScaffoldConfig,\r\n opts: FormatFromConfigOptions = {},\r\n): Promise<void> {\r\n const formatCfg: FormatConfig | undefined = config.format;\r\n const enabled = !!(formatCfg?.enabled || opts.force);\r\n\r\n if (!enabled) return;\r\n\r\n const files = getStructureFilesFromConfig(projectRoot, scaffoldDir, config);\r\n\r\n const indentStep =\r\n formatCfg?.indentStep ?? config.indentStep ?? 2;\r\n\r\n const mode = formatCfg?.mode ?? 'loose';\r\n const sortEntries = !!formatCfg?.sortEntries;\r\n\r\n for (const filePath of files) {\r\n let text: string;\r\n try {\r\n text = fs.readFileSync(filePath, 'utf8');\r\n } catch {\r\n // Missing file is fine; we don't create it here.\r\n continue;\r\n }\r\n\r\n const {text: formatted} = formatStructureText(text, {\r\n indentStep,\r\n mode,\r\n sortEntries,\r\n });\r\n\r\n if (formatted !== text) {\r\n fs.writeFileSync(filePath, formatted, 'utf8');\r\n }\r\n }\r\n}","// src/core/runner.ts\r\n\r\nimport path from 'path';\r\nimport {loadScaffoldConfig} from './config-loader';\r\nimport {\r\n resolveGroupStructure,\r\n resolveSingleStructure,\r\n} from './resolve-structure';\r\nimport {CacheManager} from './cache-manager';\r\nimport {HookRunner} from './hook-runner';\r\nimport {applyStructure, type InteractiveDeleteParams} from './apply-structure';\r\nimport type {Logger} from '../util/logger';\r\nimport {defaultLogger} from '../util/logger';\r\nimport {formatStructureFilesFromConfig} from \"./format\";\r\n\r\nexport interface RunOptions {\r\n /**\r\n * Optional interactive delete callback; if omitted, deletions\r\n * above the size threshold will be skipped (kept + removed from cache).\r\n */\r\n interactiveDelete?: (\r\n params: InteractiveDeleteParams,\r\n ) => Promise<'delete' | 'keep'>;\r\n\r\n /**\r\n * Optional logger override.\r\n */\r\n logger?: Logger;\r\n\r\n /**\r\n * Optional overrides (e.g. allow CLI to point at a different scaffold dir).\r\n */\r\n scaffoldDir?: string;\r\n configPath?: string;\r\n /**\r\n * If true, force formatting even if config.format?.enabled === false.\r\n * This is what `--format` will use.\r\n */\r\n format?: boolean;\r\n}\r\n\r\n/**\r\n * Run scaffold once for the current working directory.\r\n */\r\nexport async function runOnce(cwd: string, options: RunOptions = {}): Promise<void> {\r\n const logger = options.logger ?? defaultLogger.child('[runner]');\r\n const {config, scaffoldDir, projectRoot} = await loadScaffoldConfig(cwd, {\r\n scaffoldDir: options.scaffoldDir,\r\n configPath: options.configPath,\r\n });\r\n\r\n await formatStructureFilesFromConfig(projectRoot, scaffoldDir, config, {force: options.format})\r\n\r\n const cachePath = config.cacheFile ?? '.scaffold-cache.json';\r\n const cache = new CacheManager(projectRoot, cachePath);\r\n cache.load();\r\n\r\n const hooks = new HookRunner(config);\r\n\r\n // Grouped mode\r\n if (config.groups && config.groups.length > 0) {\r\n for (const group of config.groups) {\r\n const groupRootAbs = path.resolve(projectRoot, group.root);\r\n const structure = resolveGroupStructure(scaffoldDir, group);\r\n\r\n const groupLogger = logger.child(`[group:${group.name}]`);\r\n\r\n // eslint-disable-next-line no-await-in-loop\r\n await applyStructure({\r\n config,\r\n projectRoot,\r\n baseDir: groupRootAbs,\r\n structure,\r\n cache,\r\n hooks,\r\n groupName: group.name,\r\n groupRoot: group.root,\r\n interactiveDelete: options.interactiveDelete,\r\n logger: groupLogger,\r\n });\r\n }\r\n } else {\r\n // Single-root mode\r\n const structure = resolveSingleStructure(scaffoldDir, config);\r\n const baseLogger = logger.child('[group:default]');\r\n\r\n await applyStructure({\r\n config,\r\n projectRoot,\r\n baseDir: projectRoot,\r\n structure,\r\n cache,\r\n hooks,\r\n groupName: 'default',\r\n groupRoot: '.',\r\n interactiveDelete: options.interactiveDelete,\r\n logger: baseLogger,\r\n });\r\n }\r\n\r\n cache.save();\r\n}","// src/core/watcher.ts\r\n\r\nimport path from 'path';\r\nimport chokidar from 'chokidar';\r\nimport {runOnce, type RunOptions} from './runner';\r\nimport {defaultLogger, type Logger} from '../util/logger';\r\nimport {SCAFFOLD_ROOT_DIR} from '..';\r\n\r\nexport interface WatchOptions extends RunOptions {\r\n /**\r\n * Debounce delay in milliseconds between detected changes\r\n * and a scaffold re-run.\r\n *\r\n * Default: 150 ms\r\n */\r\n debounceMs?: number;\r\n\r\n /**\r\n * Optional logger; falls back to defaultLogger.child('[watch]').\r\n */\r\n logger?: Logger;\r\n}\r\n\r\n/**\r\n * Watch the scaffold directory and re-run scaffold on changes.\r\n *\r\n * This watches:\r\n * - .scaffold/config.* files\r\n * - .scaffold/*.txt / *.tss / *.stx files (structures)\r\n *\r\n * CLI can call this when `--watch` is enabled.\r\n * Any `format` options in RunOptions are passed straight through to `runOnce`,\r\n * so formatting from config / CLI is applied on each re-run.\r\n */\r\nexport function watchScaffold(cwd: string, options: WatchOptions = {}): void {\r\n const logger = options.logger ?? defaultLogger.child('[watch]');\r\n\r\n const scaffoldDir = options.scaffoldDir\r\n ? path.resolve(cwd, options.scaffoldDir)\r\n : path.resolve(cwd, SCAFFOLD_ROOT_DIR);\r\n\r\n const debounceMs = options.debounceMs ?? 150;\r\n\r\n logger.info(`Watching scaffold directory: ${scaffoldDir}`);\r\n\r\n let timer: NodeJS.Timeout | undefined;\r\n let running = false;\r\n let pending = false;\r\n\r\n async function run() {\r\n if (running) {\r\n pending = true;\r\n return;\r\n }\r\n running = true;\r\n try {\r\n logger.info('Change detected → running scaffold...');\r\n await runOnce(cwd, {\r\n ...options,\r\n // we already resolved scaffoldDir for watcher; pass it down\r\n scaffoldDir,\r\n });\r\n logger.info('Scaffold run completed.');\r\n } catch (err) {\r\n logger.error('Scaffold run failed:', err);\r\n } finally {\r\n running = false;\r\n if (pending) {\r\n pending = false;\r\n timer = setTimeout(run, debounceMs);\r\n }\r\n }\r\n }\r\n\r\n function scheduleRun() {\r\n if (timer) clearTimeout(timer);\r\n timer = setTimeout(run, debounceMs);\r\n }\r\n\r\n const watcher = chokidar.watch(\r\n [\r\n // config files (ts/js/etc.)\r\n path.join(scaffoldDir, 'config.*'),\r\n\r\n // structure files: plain txt + our custom extensions\r\n path.join(scaffoldDir, '*.txt'),\r\n path.join(scaffoldDir, '*.tss'),\r\n path.join(scaffoldDir, '*.stx'),\r\n ],\r\n {\r\n ignoreInitial: false,\r\n },\r\n );\r\n\r\n watcher\r\n .on('add', (filePath) => {\r\n logger.debug(`File added: ${filePath}`);\r\n scheduleRun();\r\n })\r\n .on('change', (filePath) => {\r\n logger.debug(`File changed: ${filePath}`);\r\n scheduleRun();\r\n })\r\n .on('unlink', (filePath) => {\r\n logger.debug(`File removed: ${filePath}`);\r\n scheduleRun();\r\n })\r\n .on('error', (error) => {\r\n logger.error('Watcher error:', error);\r\n });\r\n\r\n // Initial run\r\n scheduleRun();\r\n}","// src/core/init-scaffold.ts\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport {ensureDirSync} from '../util/fs-utils';\r\nimport {defaultLogger} from '../util/logger';\r\nimport {SCAFFOLD_ROOT_DIR} from '../schema';\r\n\r\nconst logger = defaultLogger.child('[init]');\r\n\r\nexport interface InitScaffoldOptions {\r\n /**\r\n * Path to the scaffold directory (relative to cwd).\r\n * Default: \".scaffold\"\r\n */\r\n scaffoldDir?: string;\r\n\r\n /**\r\n * Overwrite existing config/structure files if they already exist.\r\n */\r\n force?: boolean;\r\n\r\n /**\r\n * Name of the config file inside the scaffold directory.\r\n * Default: \"config.ts\"\r\n */\r\n configFileName?: string;\r\n\r\n /**\r\n * Name of the default structure file inside the scaffold directory\r\n * for single-root mode.\r\n * Default: \"structure.txt\"\r\n */\r\n structureFileName?: string;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Default config + structure templates\r\n// ---------------------------------------------------------------------------\r\n\r\nconst DEFAULT_CONFIG_TS = `import type { ScaffoldConfig } from '@timeax/scaffold';\r\n\r\nconst config: ScaffoldConfig = {\r\n // Root for resolving the .scaffold folder & this config file.\r\n // By default, this is the directory where you run \\`scaffold\\`.\r\n // Example:\r\n // root: '.', // .scaffold at <cwd>/.scaffold\r\n // root: 'tools', // .scaffold at <cwd>/tools/.scaffold\r\n // root: '.',\r\n\r\n // Base directory where structures are applied and files/folders are created.\r\n // This is resolved relative to \\`root\\` above. Defaults to the same as root.\r\n // Example:\r\n // base: '.', // apply to <root>\r\n // base: 'src', // apply to <root>/src\r\n // base: '..', // apply to parent of <root>\r\n // base: '.',\r\n\r\n // Number of spaces per indent level in structure files (default: 2).\r\n // This also informs the formatter when indenting entries.\r\n // indentStep: 2,\r\n\r\n // Cache file path, relative to base.\r\n // cacheFile: '.scaffold-cache.json',\r\n\r\n // Formatting options for structure files.\r\n // These are used by:\r\n // - \\`scaffold --format\\` (forces formatting before apply)\r\n // - \\`scaffold --watch\\` when \\`formatOnWatch\\` is true\r\n //\r\n // format: {\r\n // // Enable config-driven formatting in general.\r\n // // \\`scaffold --format\\` always forces formatting even if this is false.\r\n // enabled: true,\r\n //\r\n // // Override indent step specifically for formatting (falls back to\r\n // // top-level \\`indentStep\\` if omitted).\r\n // indentStep: 2,\r\n //\r\n // // AST mode:\r\n // // - 'loose' (default): tries to repair mild indentation issues.\r\n // // - 'strict': mostly cosmetic changes (trims trailing whitespace, etc.).\r\n // mode: 'loose',\r\n //\r\n // // Sort non-comment entries lexicographically within their parent block.\r\n // // Comments and blank lines keep their relative positions.\r\n // sortEntries: true,\r\n //\r\n // // When running \\`scaffold --watch\\`, format structure files on each\r\n // // detected change before applying scaffold.\r\n // formatOnWatch: true,\r\n // },\r\n\r\n // --- Single-structure mode (simple) ---\r\n // structureFile: 'structure.txt',\r\n\r\n // --- Grouped mode (uncomment and adjust) ---\r\n // groups: [\r\n // { name: 'app', root: 'app', structureFile: 'app.txt' },\r\n // { name: 'frontend', root: 'resources/js', structureFile: 'frontend.txt' },\r\n // ],\r\n\r\n hooks: {\r\n // preCreateFile: [],\r\n // postCreateFile: [],\r\n // preDeleteFile: [],\r\n // postDeleteFile: [],\r\n },\r\n\r\n stubs: {\r\n // Example:\r\n // page: {\r\n // name: 'page',\r\n // getContent: (ctx) =>\r\n // \\`export default function Page() { return <div>\\${ctx.targetPath}</div>; }\\`,\r\n // },\r\n }\r\n};\r\n\r\nexport default config;\r\n`;\r\n\r\nconst DEFAULT_STRUCTURE_TXT = `# ${SCAFFOLD_ROOT_DIR}/structure.txt\r\n# Example structure definition.\r\n# - Indent with 2 spaces per level (or your configured indentStep)\r\n# - Directories must end with \"/\"\r\n# - Files do not\r\n# - Lines starting with \"#\" are comments and ignored by parser\r\n# - Inline comments are allowed after \"#\" or \"//\" separated by whitespace\r\n#\r\n# The formatter (when enabled via config.format or --format) will:\r\n# - Normalize indentation based on indentStep\r\n# - Preserve blank lines and comments\r\n# - Keep inline comments attached to their entries\r\n#\r\n# Example:\r\n# src/\r\n# index.ts\r\n`;\r\n\r\n/**\r\n * Initialize the scaffold directory and basic config/structure files.\r\n *\r\n * - Creates the scaffold directory if it doesn't exist.\r\n * - Writes a default config.ts if missing (or if force = true).\r\n * - Writes a default structure.txt if missing (or if force = true).\r\n */\r\nexport async function initScaffold(\r\n cwd: string,\r\n options: InitScaffoldOptions = {},\r\n): Promise<{\r\n scaffoldDir: string;\r\n configPath: string;\r\n structurePath: string;\r\n created: { config: boolean; structure: boolean };\r\n}> {\r\n const scaffoldDirRel = options.scaffoldDir ?? SCAFFOLD_ROOT_DIR;\r\n const scaffoldDirAbs = path.resolve(cwd, scaffoldDirRel);\r\n const configFileName = options.configFileName ?? 'config.ts';\r\n const structureFileName = options.structureFileName ?? 'structure.txt';\r\n\r\n ensureDirSync(scaffoldDirAbs);\r\n\r\n const configPath = path.join(scaffoldDirAbs, configFileName);\r\n const structurePath = path.join(scaffoldDirAbs, structureFileName);\r\n\r\n let createdConfig = false;\r\n let createdStructure = false;\r\n\r\n // config.ts\r\n if (fs.existsSync(configPath) && !options.force) {\r\n logger.info(\r\n `Config already exists at ${configPath} (use --force to overwrite).`,\r\n );\r\n } else {\r\n fs.writeFileSync(configPath, DEFAULT_CONFIG_TS, 'utf8');\r\n createdConfig = true;\r\n logger.info(\r\n `${fs.existsSync(configPath) ? 'Overwrote' : 'Created'} config at ${configPath}`,\r\n );\r\n }\r\n\r\n // structure.txt\r\n if (fs.existsSync(structurePath) && !options.force) {\r\n logger.info(\r\n `Structure file already exists at ${structurePath} (use --force to overwrite).`,\r\n );\r\n } else {\r\n fs.writeFileSync(structurePath, DEFAULT_STRUCTURE_TXT, 'utf8');\r\n createdStructure = true;\r\n logger.info(\r\n `${fs.existsSync(structurePath) ? 'Overwrote' : 'Created'} structure file at ${structurePath}`,\r\n );\r\n }\r\n\r\n return {\r\n scaffoldDir: scaffoldDirAbs,\r\n configPath,\r\n structurePath,\r\n created: {\r\n config: createdConfig,\r\n structure: createdStructure,\r\n },\r\n };\r\n}","#!/usr/bin/env node\r\n// noinspection RequiredAttributes\r\n\r\nimport readline from 'readline';\r\nimport path from 'path';\r\nimport fs from 'fs';\r\nimport { Command } from 'commander';\r\nimport { runOnce, RunOptions } from '../core/runner';\r\nimport { watchScaffold } from '../core/watcher';\r\nimport {\r\n ensureStructureFilesFromConfig,\r\n scanDirectoryToStructureText,\r\n writeScannedStructuresFromConfig,\r\n} from '../core/scan-structure';\r\nimport { initScaffold } from '../core/init-scaffold';\r\nimport {\r\n defaultLogger,\r\n Logger,\r\n\r\n} from '../util/logger';\r\nimport { ensureDirSync } from '../util/fs-utils';\r\nimport {SCAFFOLD_ROOT_DIR} from \"../schema\";\r\n\r\ninterface BaseCliOptions {\r\n config?: string;\r\n dir?: string;\r\n watch?: boolean;\r\n quiet?: boolean;\r\n debug?: boolean;\r\n}\r\n\r\ninterface ScanCliOptions {\r\n root?: string;\r\n out?: string;\r\n ignore?: string[];\r\n fromConfig?: boolean;\r\n groups?: string[];\r\n}\r\n\r\ninterface InitCliOptions {\r\n force?: boolean;\r\n}\r\n\r\n/**\r\n * Create a logger with the appropriate level from CLI flags.\r\n */\r\nfunction createCliLogger(opts: { quiet?: boolean; debug?: boolean }): Logger {\r\n if (opts.quiet) {\r\n defaultLogger.setLevel('silent');\r\n } else if (opts.debug) {\r\n defaultLogger.setLevel('debug');\r\n }\r\n return defaultLogger.child('[cli]');\r\n}\r\n\r\nfunction askYesNo(question: string): Promise<'delete' | 'keep'> {\r\n const rl = readline.createInterface({\r\n input: process.stdin,\r\n output: process.stdout,\r\n });\r\n\r\n return new Promise((resolve) => {\r\n rl.question(`${question} [y/N] `, (answer) => {\r\n rl.close();\r\n const val = answer.trim().toLowerCase();\r\n if (val === 'y' || val === 'yes') {\r\n resolve('delete');\r\n } else {\r\n resolve('keep');\r\n }\r\n });\r\n });\r\n}\r\n\r\nasync function handleRunCommand(cwd: string, baseOpts: BaseCliOptions) {\r\n const logger = createCliLogger(baseOpts);\r\n\r\n const configPath = baseOpts.config\r\n ? path.resolve(cwd, baseOpts.config)\r\n : undefined;\r\n const scaffoldDir = baseOpts.dir\r\n ? path.resolve(cwd, baseOpts.dir)\r\n : undefined;\r\n\r\n logger.debug(\r\n `Starting scaffold (cwd=${cwd}, config=${configPath ?? 'auto'}, dir=${scaffoldDir ?? 'scaffold/'\r\n }, watch=${baseOpts.watch ? 'yes' : 'no'})`,\r\n );\r\n\r\n const runnerOptions: RunOptions = {\r\n configPath,\r\n scaffoldDir,\r\n logger,\r\n interactiveDelete: async ({\r\n relativePath,\r\n size,\r\n createdByStub,\r\n groupName,\r\n }) => {\r\n const sizeKb = (size / 1024).toFixed(1);\r\n const stubInfo = createdByStub ? ` (stub: ${createdByStub})` : '';\r\n const groupInfo = groupName ? ` [group: ${groupName}]` : '';\r\n const question =\r\n `File \"${relativePath}\"${groupInfo} is ~${sizeKb}KB and no longer in structure${stubInfo}. Delete it?`;\r\n\r\n return askYesNo(question);\r\n },\r\n };\r\n\r\n if (baseOpts.watch) {\r\n // Watch mode – this will not return\r\n watchScaffold(cwd, runnerOptions);\r\n } else {\r\n await runOnce(cwd, runnerOptions);\r\n }\r\n}\r\n\r\nasync function handleScanCommand(\r\n cwd: string,\r\n scanOpts: ScanCliOptions,\r\n baseOpts: BaseCliOptions,\r\n) {\r\n const logger = createCliLogger(baseOpts);\r\n\r\n const useConfigMode =\r\n scanOpts.fromConfig || (!scanOpts.root && !scanOpts.out);\r\n\r\n if (useConfigMode) {\r\n logger.info('Scanning project using scaffold config/groups...');\r\n await writeScannedStructuresFromConfig(cwd, {\r\n ignore: scanOpts.ignore,\r\n groups: scanOpts.groups,\r\n });\r\n return;\r\n }\r\n\r\n // Manual single-root mode\r\n const rootDir = path.resolve(cwd, scanOpts.root ?? '.');\r\n const ignore = scanOpts.ignore ?? [];\r\n\r\n logger.info(`Scanning directory for structure: ${rootDir}`);\r\n const text = scanDirectoryToStructureText(rootDir, {\r\n ignore,\r\n });\r\n\r\n if (scanOpts.out) {\r\n const outPath = path.resolve(cwd, scanOpts.out);\r\n const dir = path.dirname(outPath);\r\n ensureDirSync(dir);\r\n fs.writeFileSync(outPath, text, 'utf8');\r\n logger.info(`Wrote structure to ${outPath}`);\r\n } else {\r\n process.stdout.write(text + '\\n');\r\n }\r\n}\r\n\r\nasync function handleInitCommand(\r\n cwd: string,\r\n initOpts: InitCliOptions,\r\n baseOpts: BaseCliOptions,\r\n) {\r\n const logger = createCliLogger(baseOpts);\r\n\r\n const scaffoldDirRel = baseOpts.dir ?? SCAFFOLD_ROOT_DIR;\r\n\r\n logger.info(`Initializing scaffold directory at \"${scaffoldDirRel}\"...`);\r\n\r\n const result = await initScaffold(cwd, {\r\n scaffoldDir: scaffoldDirRel,\r\n force: initOpts.force,\r\n });\r\n\r\n logger.info(\r\n `Done. Config: ${result.configPath}, Structure: ${result.structurePath}`,\r\n );\r\n}\r\n\r\n\r\nasync function handleStructuresCommand(\r\n cwd: string,\r\n baseOpts: BaseCliOptions,\r\n) {\r\n const logger = createCliLogger(baseOpts);\r\n\r\n logger.info('Ensuring structure files declared in config exist...');\r\n\r\n const { created, existing } = await ensureStructureFilesFromConfig(cwd, {\r\n scaffoldDirOverride: baseOpts.dir,\r\n });\r\n\r\n if (created.length === 0) {\r\n logger.info('All structure files already exist. Nothing to do.');\r\n } else {\r\n for (const filePath of created) {\r\n logger.info(`Created structure file: ${filePath}`);\r\n }\r\n }\r\n\r\n existing.forEach((p) => logger.debug(`Structure file already exists: ${p}`));\r\n}\r\n\r\nasync function main() {\r\n const cwd = process.cwd();\r\n\r\n const program = new Command();\r\n\r\n program\r\n .name('scaffold')\r\n .description('@timeax/scaffold – structure-based project scaffolding')\r\n // global-ish options used by base + scan + init\r\n .option('-c, --config <path>', 'Path to scaffold config file')\r\n .option('-d, --dir <path>', 'Path to scaffold directory (default: ./scaffold)')\r\n .option('-w, --watch', 'Watch scaffold directory for changes')\r\n .option('--quiet', 'Silence logs')\r\n .option('--debug', 'Enable debug logging');\r\n\r\n // scan subcommand\r\n program\r\n .command('scan')\r\n .description(\r\n 'Generate structure.txt-style output (config-aware by default, or manual root/out)',\r\n )\r\n .option(\r\n '--from-config',\r\n 'Scan based on scaffold config/groups and write structure files into scaffold/ (default if no root/out specified)',\r\n )\r\n .option(\r\n '-r, --root <path>',\r\n 'Root directory to scan (manual mode)',\r\n )\r\n .option(\r\n '-o, --out <path>',\r\n 'Output file path (manual mode)',\r\n )\r\n .option(\r\n '--ignore <patterns...>',\r\n 'Additional glob patterns to ignore (relative to root)',\r\n )\r\n .option(\r\n '--groups <names...>',\r\n 'Limit config-based scanning to specific groups (by name)',\r\n )\r\n .action(async (scanOpts: ScanCliOptions, cmd: Command) => {\r\n const baseOpts = cmd.parent?.opts<BaseCliOptions>() ?? {};\r\n await handleScanCommand(cwd, scanOpts, baseOpts);\r\n });\r\n\r\n // init subcommand\r\n program\r\n .command('init')\r\n .description('Initialize scaffold folder and config/structure files')\r\n .option(\r\n '--force',\r\n 'Overwrite existing config/structure files if they already exist',\r\n )\r\n .action(async (initOpts: InitCliOptions, cmd: Command) => {\r\n const baseOpts = cmd.parent?.opts<BaseCliOptions>() ?? {};\r\n await handleInitCommand(cwd, initOpts, baseOpts);\r\n });\r\n\r\n // Base command: run scaffold once or in watch mode\r\n program.action(async (opts: BaseCliOptions) => {\r\n await handleRunCommand(cwd, opts);\r\n });\r\n\r\n interface StructuresCliOptions { }\r\n\r\n program\r\n .command('structures')\r\n .description(\r\n 'Create missing structure files specified in the config (does not overwrite existing files)',\r\n )\r\n .action(async (_opts: StructuresCliOptions, cmd: Command) => {\r\n const baseOpts = cmd.parent?.opts<BaseCliOptions>() ?? {};\r\n await handleStructuresCommand(cwd, baseOpts);\r\n });\r\n\r\n await program.parseAsync(process.argv);\r\n}\r\n\r\n\r\n// Run and handle errors\r\nmain().catch((err) => {\r\n defaultLogger.error(err);\r\n process.exit(1);\r\n});"]}
|
|
1
|
+
{"version":3,"sources":["../src/schema/index.ts","../src/util/logger.ts","../src/util/fs-utils.ts","../src/core/config-loader.ts","../src/ast/parser.ts","../src/ast/format.ts","../src/core/structure-txt.ts","../src/core/resolve-structure.ts","../src/core/cache-manager.ts","../src/core/hook-runner.ts","../src/core/apply-structure.ts","../src/core/scan-structure.ts","../src/core/format.ts","../src/core/runner.ts","../src/core/watcher.ts","../src/core/init-scaffold.ts","../src/cli/main.ts"],"names":["fs","path","parent","logger","minimatch"],"mappings":"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","file":"cli.mjs","sourcesContent":["// src/schema/index.ts\r\nexport const SCAFFOLD_ROOT_DIR = '.scaffold';\r\nexport * from './structure';\r\nexport * from './hooks';\r\nexport * from './config';","// src/util/logger.ts\r\n\r\nexport type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug';\r\n\r\nexport interface LoggerOptions {\r\n level?: LogLevel;\r\n /**\r\n * Optional prefix string (e.g. \"[scaffold]\" or \"[group:app]\").\r\n */\r\n prefix?: string;\r\n}\r\n\r\n/**\r\n * Minimal ANSI color helpers (no external deps).\r\n */\r\nconst supportsColor =\r\n typeof process !== 'undefined' &&\r\n process.stdout &&\r\n process.stdout.isTTY &&\r\n process.env.NO_COLOR !== '1';\r\n\r\ntype ColorFn = (text: string) => string;\r\n\r\nfunction wrap(code: number): ColorFn {\r\n const open = `\\u001b[${code}m`;\r\n const close = `\\u001b[0m`;\r\n return (text: string) => (supportsColor ? `${open}${text}${close}` : text);\r\n}\r\n\r\nconst color = {\r\n red: wrap(31),\r\n yellow: wrap(33),\r\n green: wrap(32),\r\n cyan: wrap(36),\r\n magenta: wrap(35),\r\n dim: wrap(2),\r\n bold: wrap(1),\r\n gray: wrap(90),\r\n};\r\n\r\nfunction colorForLevel(level: LogLevel): ColorFn {\r\n switch (level) {\r\n case 'error':\r\n return color.red;\r\n case 'warn':\r\n return color.yellow;\r\n case 'info':\r\n return color.cyan;\r\n case 'debug':\r\n return color.gray;\r\n default:\r\n return (s) => s;\r\n }\r\n}\r\n\r\n/**\r\n * Minimal logger for @timeax/scaffold with colored output.\r\n */\r\nexport class Logger {\r\n private level: LogLevel;\r\n private prefix: string | undefined;\r\n\r\n constructor(options: LoggerOptions = {}) {\r\n this.level = options.level ?? 'info';\r\n this.prefix = options.prefix;\r\n }\r\n\r\n setLevel(level: LogLevel) {\r\n this.level = level;\r\n }\r\n\r\n getLevel(): LogLevel {\r\n return this.level;\r\n }\r\n\r\n /**\r\n * Create a child logger with an additional prefix.\r\n */\r\n child(prefix: string): Logger {\r\n const combined = this.prefix ? `${this.prefix}${prefix}` : prefix;\r\n return new Logger({ level: this.level, prefix: combined });\r\n }\r\n\r\n private formatMessage(msg: unknown, lvl: LogLevel): string {\r\n const text =\r\n typeof msg === 'string'\r\n ? msg\r\n : msg instanceof Error\r\n ? msg.message\r\n : String(msg);\r\n\r\n const levelColor = colorForLevel(lvl);\r\n const prefixColored = this.prefix\r\n ? color.magenta(this.prefix)\r\n : undefined;\r\n\r\n const textColored =\r\n lvl === 'debug' ? color.dim(text) : levelColor(text);\r\n\r\n if (prefixColored) {\r\n return `${prefixColored} ${textColored}`;\r\n }\r\n\r\n return textColored;\r\n }\r\n\r\n private shouldLog(targetLevel: LogLevel): boolean {\r\n const order: LogLevel[] = ['silent', 'error', 'warn', 'info', 'debug'];\r\n const currentIdx = order.indexOf(this.level);\r\n const targetIdx = order.indexOf(targetLevel);\r\n if (currentIdx === -1 || targetIdx === -1) return true;\r\n if (this.level === 'silent') return false;\r\n return targetIdx <= currentIdx || targetLevel === 'error';\r\n }\r\n\r\n error(msg: unknown, ...rest: unknown[]) {\r\n if (!this.shouldLog('error')) return;\r\n console.error(this.formatMessage(msg, 'error'), ...rest);\r\n }\r\n\r\n warn(msg: unknown, ...rest: unknown[]) {\r\n if (!this.shouldLog('warn')) return;\r\n console.warn(this.formatMessage(msg, 'warn'), ...rest);\r\n }\r\n\r\n info(msg: unknown, ...rest: unknown[]) {\r\n if (!this.shouldLog('info')) return;\r\n console.log(this.formatMessage(msg, 'info'), ...rest);\r\n }\r\n\r\n debug(msg: unknown, ...rest: unknown[]) {\r\n if (!this.shouldLog('debug')) return;\r\n console.debug(this.formatMessage(msg, 'debug'), ...rest);\r\n }\r\n}\r\n\r\n/**\r\n * Default process-wide logger used by CLI and core.\r\n * Level can be controlled via SCAFFOLD_LOG_LEVEL env.\r\n */\r\nexport const defaultLogger = new Logger({\r\n level: (process.env.SCAFFOLD_LOG_LEVEL as LogLevel | undefined) ?? 'info',\r\n prefix: '[scaffold]',\r\n});","// src/util/fs-utils.ts\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\n\r\n/**\r\n * Convert any path to a POSIX-style path with forward slashes.\r\n */\r\nexport function toPosixPath(p: string): string {\r\n return p.replace(/\\\\/g, '/');\r\n}\r\n\r\n/**\r\n * Ensure a directory exists (like mkdir -p).\r\n * Returns the absolute path of the directory.\r\n */\r\nexport function ensureDirSync(dirPath: string): string {\r\n if (!fs.existsSync(dirPath)) {\r\n fs.mkdirSync(dirPath, { recursive: true });\r\n }\r\n return dirPath;\r\n}\r\n\r\n/**\r\n * Synchronous check for file or directory existence.\r\n */\r\nexport function existsSync(targetPath: string): boolean {\r\n return fs.existsSync(targetPath);\r\n}\r\n\r\n/**\r\n * Read a file as UTF-8, returning null if it doesn't exist\r\n * or if an error occurs (no exceptions thrown).\r\n */\r\nexport function readFileSafeSync(filePath: string): string | null {\r\n try {\r\n return fs.readFileSync(filePath, 'utf8');\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Write a UTF-8 file, creating parent directories if needed.\r\n */\r\nexport function writeFileSafeSync(filePath: string, contents: string): void {\r\n const dir = path.dirname(filePath);\r\n ensureDirSync(dir);\r\n fs.writeFileSync(filePath, contents, 'utf8');\r\n}\r\n\r\n/**\r\n * Remove a file if it exists. Does nothing on error.\r\n */\r\nexport function removeFileSafeSync(filePath: string): void {\r\n try {\r\n if (fs.existsSync(filePath)) {\r\n fs.unlinkSync(filePath);\r\n }\r\n } catch {\r\n // ignore\r\n }\r\n}\r\n\r\n/**\r\n * Get file stats if they exist, otherwise null.\r\n */\r\nexport function statSafeSync(targetPath: string): fs.Stats | null {\r\n try {\r\n return fs.statSync(targetPath);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Resolve an absolute path from projectRoot + relative path,\r\n * and assert it stays within the project root.\r\n *\r\n * Throws if the resolved path escapes the project root.\r\n */\r\nexport function resolveProjectPath(projectRoot: string, relPath: string): string {\r\n const absRoot = path.resolve(projectRoot);\r\n const absTarget = path.resolve(absRoot, relPath);\r\n\r\n // Normalise for safety check\r\n const rootWithSep = absRoot.endsWith(path.sep) ? absRoot : absRoot + path.sep;\r\n if (!absTarget.startsWith(rootWithSep) && absTarget !== absRoot) {\r\n throw new Error(\r\n `Attempted to resolve path outside project root: ` +\r\n `root=\"${absRoot}\", target=\"${absTarget}\"`,\r\n );\r\n }\r\n\r\n return absTarget;\r\n}\r\n\r\n/**\r\n * Convert an absolute path back to a project-relative path.\r\n * Throws if the path is not under projectRoot.\r\n */\r\nexport function toProjectRelativePath(projectRoot: string, absolutePath: string): string {\r\n const absRoot = path.resolve(projectRoot);\r\n const absTarget = path.resolve(absolutePath);\r\n\r\n const rootWithSep = absRoot.endsWith(path.sep) ? absRoot : absRoot + path.sep;\r\n if (!absTarget.startsWith(rootWithSep) && absTarget !== absRoot) {\r\n throw new Error(\r\n `Path \"${absTarget}\" is not inside project root \"${absRoot}\".`,\r\n );\r\n }\r\n\r\n const rel = path.relative(absRoot, absTarget);\r\n return toPosixPath(rel);\r\n}\r\n\r\n/**\r\n * Check if `target` is inside (or equal to) `base` directory.\r\n */\r\nexport function isSubPath(base: string, target: string): boolean {\r\n const absBase = path.resolve(base);\r\n const absTarget = path.resolve(target);\r\n\r\n const baseWithSep = absBase.endsWith(path.sep) ? absBase : absBase + path.sep;\r\n return absTarget === absBase || absTarget.startsWith(baseWithSep);\r\n}","// src/core/config-loader.ts\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport os from 'os';\r\nimport crypto from 'crypto';\r\nimport { pathToFileURL } from 'url';\r\nimport { transform } from 'esbuild';\r\n\r\nimport { SCAFFOLD_ROOT_DIR, type ScaffoldConfig } from '../schema';\r\nimport { defaultLogger } from '../util/logger';\r\nimport { ensureDirSync } from '../util/fs-utils';\r\n\r\nconst logger = defaultLogger.child('[config]');\r\n\r\n\r\nexport interface LoadScaffoldConfigOptions {\r\n /**\r\n * Optional explicit scaffold directory path (absolute or relative to cwd).\r\n * If provided, this overrides config.root for locating the scaffold folder.\r\n */\r\n scaffoldDir?: string;\r\n\r\n /**\r\n * Optional explicit config file path (absolute or relative to cwd).\r\n * If not provided, we look for config.* inside the scaffoldDir.\r\n */\r\n configPath?: string;\r\n}\r\n\r\nexport interface LoadScaffoldConfigResult {\r\n /**\r\n * Parsed scaffold configuration.\r\n */\r\n config: ScaffoldConfig;\r\n\r\n /**\r\n * Absolute path to the scaffold directory (where config & *.txt live).\r\n */\r\n scaffoldDir: string;\r\n\r\n /**\r\n * Effective project root BASE where structures are applied.\r\n * This is derived from config.root + config.base.\r\n */\r\n projectRoot: string;\r\n}\r\n\r\n/**\r\n * Load scaffold configuration based on CWD + optional overrides + config.root/base.\r\n *\r\n * Resolution rules:\r\n * - configRoot:\r\n * - Start from cwd.\r\n * - Apply config.root (if defined) as a path relative to cwd.\r\n * - scaffoldDir:\r\n * - If options.scaffoldDir is provided → use it as-is (resolved from cwd).\r\n * - Else → <configRoot>/scaffold.\r\n * - projectRoot (base):\r\n * - If config.base is defined → resolve relative to configRoot.\r\n * - Else → configRoot.\r\n */\r\nexport async function loadScaffoldConfig(\r\n cwd: string,\r\n options: LoadScaffoldConfigOptions = {},\r\n): Promise<LoadScaffoldConfigResult> {\r\n const absCwd = path.resolve(cwd);\r\n\r\n // First pass: figure out an initial scaffold dir just to locate config.*\r\n const initialScaffoldDir = options.scaffoldDir\r\n ? path.resolve(absCwd, options.scaffoldDir)\r\n : path.join(absCwd, SCAFFOLD_ROOT_DIR);\r\n\r\n const configPath =\r\n options.configPath ?? resolveConfigPath(initialScaffoldDir);\r\n\r\n // Import config (supports .ts/.tsx via esbuild)\r\n const config = await importConfig(configPath);\r\n\r\n // Now compute configRoot (where scaffold/ lives by default)\r\n let configRoot = absCwd;\r\n if (config.root) {\r\n configRoot = path.resolve(absCwd, config.root);\r\n }\r\n\r\n // Final scaffoldDir (can still be overridden by CLI)\r\n const scaffoldDir = options.scaffoldDir\r\n ? path.resolve(absCwd, options.scaffoldDir)\r\n : path.join(configRoot, SCAFFOLD_ROOT_DIR);\r\n\r\n // projectRoot (base) is relative to configRoot\r\n const baseRoot = config.base\r\n ? path.resolve(configRoot, config.base)\r\n : configRoot;\r\n\r\n logger.debug(\r\n `Loaded config: configRoot=${configRoot}, baseRoot=${baseRoot}, scaffoldDir=${scaffoldDir}`,\r\n );\r\n\r\n return {\r\n config,\r\n scaffoldDir,\r\n projectRoot: baseRoot,\r\n };\r\n}\r\n\r\nfunction resolveConfigPath(scaffoldDir: string): string {\r\n const candidates = [\r\n 'config.ts',\r\n 'config.mts',\r\n 'config.mjs',\r\n 'config.js',\r\n 'config.cjs',\r\n ];\r\n\r\n for (const file of candidates) {\r\n const full = path.join(scaffoldDir, file);\r\n if (fs.existsSync(full)) {\r\n return full;\r\n }\r\n }\r\n\r\n throw new Error(\r\n `Could not find scaffold config in ${scaffoldDir}. Looked for: ${candidates.join(\r\n ', ',\r\n )}`,\r\n );\r\n}\r\n\r\n/**\r\n * Import a ScaffoldConfig from the given path.\r\n * - For .ts/.tsx we transpile with esbuild to ESM and load from a temp file.\r\n * - For .js/.mjs/.cjs we import directly.\r\n */\r\nasync function importConfig(configPath: string): Promise<ScaffoldConfig> {\r\n const ext = path.extname(configPath).toLowerCase();\r\n\r\n if (ext === '.ts' || ext === '.tsx') {\r\n return importTsConfig(configPath);\r\n }\r\n\r\n const url = pathToFileURL(configPath).href;\r\n const mod = await import(url);\r\n return (mod.default ?? mod) as ScaffoldConfig;\r\n}\r\n\r\n/**\r\n * Transpile a TS config file to ESM with esbuild and import the compiled file.\r\n * We cache based on (path + mtime) so changes invalidate the temp.\r\n */\r\nasync function importTsConfig(configPath: string): Promise<ScaffoldConfig> {\r\n const source = fs.readFileSync(configPath, 'utf8');\r\n const stat = fs.statSync(configPath);\r\n\r\n const hash = crypto\r\n .createHash('sha1')\r\n .update(configPath)\r\n .update(String(stat.mtimeMs))\r\n .digest('hex');\r\n\r\n const tmpDir = path.join(os.tmpdir(), 'timeax-scaffold-config');\r\n ensureDirSync(tmpDir);\r\n\r\n const tmpFile = path.join(tmpDir, `${hash}.mjs`);\r\n\r\n if (!fs.existsSync(tmpFile)) {\r\n const result = await transform(source, {\r\n loader: 'ts',\r\n format: 'esm',\r\n sourcemap: 'inline',\r\n target: 'ESNext',\r\n tsconfigRaw: {\r\n compilerOptions: {\r\n\r\n },\r\n },\r\n });\r\n\r\n fs.writeFileSync(tmpFile, result.code, 'utf8');\r\n }\r\n\r\n const url = pathToFileURL(tmpFile).href;\r\n const mod = await import(url);\r\n return (mod.default ?? mod) as ScaffoldConfig;\r\n}","// src/ast/parser.ts\r\n\r\nimport {toPosixPath} from '../util/fs-utils';\r\n\r\nexport type AstMode = 'strict' | 'loose';\r\n\r\nexport type DiagnosticSeverity = 'info' | 'warning' | 'error';\r\n\r\nexport interface Diagnostic {\r\n line: number; // 1-based\r\n column?: number; // 1-based (optional)\r\n message: string;\r\n severity: DiagnosticSeverity;\r\n code?: string;\r\n}\r\n\r\n/**\r\n * How a physical line in the text was classified.\r\n */\r\nexport type LineKind = 'blank' | 'comment' | 'entry';\r\n\r\nexport interface StructureAstLine {\r\n index: number; // 0-based\r\n lineNo: number; // 1-based\r\n raw: string;\r\n kind: LineKind;\r\n indentSpaces: number;\r\n content: string; // after leading whitespace (includes path+annotations+inline comment)\r\n}\r\n\r\n/**\r\n * AST node base for structure entries.\r\n */\r\ninterface AstNodeBase {\r\n type: 'dir' | 'file';\r\n /** The last segment name, e.g. \"schema/\" or \"index.ts\". */\r\n name: string;\r\n /** Depth level (0 = root, 1 = child of root, etc.). */\r\n depth: number;\r\n /** 1-based source line number. */\r\n line: number;\r\n /** Normalized POSIX path from root, e.g. \"src/schema/index.ts\" or \"src/schema/\". */\r\n path: string;\r\n /** Stub annotation, if any. */\r\n stub?: string;\r\n /** Include glob patterns, if any. */\r\n include?: string[];\r\n /** Exclude glob patterns, if any. */\r\n exclude?: string[];\r\n /** Parent node; null for roots. */\r\n parent: DirNode | null;\r\n}\r\n\r\nexport interface DirNode extends AstNodeBase {\r\n type: 'dir';\r\n children: AstNode[];\r\n}\r\n\r\nexport interface FileNode extends AstNodeBase {\r\n type: 'file';\r\n children?: undefined;\r\n}\r\n\r\nexport type AstNode = DirNode | FileNode;\r\n\r\nexport interface AstOptions {\r\n /**\r\n * Spaces per indent level.\r\n * Default: 2.\r\n */\r\n indentStep?: number;\r\n\r\n /**\r\n * Parser mode:\r\n * - \"strict\": mismatched indentation / impossible structures are errors.\r\n * - \"loose\" : tries to recover from bad indentation, demotes some issues to warnings.\r\n *\r\n * Default: \"loose\".\r\n */\r\n mode?: AstMode;\r\n}\r\n\r\n/**\r\n * Full AST result: nodes + per-line meta + diagnostics.\r\n */\r\nexport interface StructureAst {\r\n /** Root-level nodes (depth 0). */\r\n rootNodes: AstNode[];\r\n /** All lines as seen in the source file. */\r\n lines: StructureAstLine[];\r\n /** Collected diagnostics (errors + warnings + infos). */\r\n diagnostics: Diagnostic[];\r\n /** Resolved options used by the parser. */\r\n options: Required<AstOptions>;\r\n}\r\n\r\n/**\r\n * Main entry: parse a structure text into an AST tree with diagnostics.\r\n *\r\n * - Does NOT throw on parse errors.\r\n * - Always returns something (even if diagnostics contain errors).\r\n * - In \"loose\" mode, attempts to repair:\r\n * - odd/misaligned indentation → snapped via relative depth rules with warnings.\r\n * - large indent jumps → treated as \"one level deeper\" with warnings.\r\n * - children under files → attached to nearest viable ancestor with warnings.\r\n */\r\nexport function parseStructureAst(\r\n text: string,\r\n opts: AstOptions = {},\r\n): StructureAst {\r\n const indentStep = opts.indentStep ?? 2;\r\n const mode: AstMode = opts.mode ?? 'loose';\r\n\r\n const diagnostics: Diagnostic[] = [];\r\n const lines: StructureAstLine[] = [];\r\n\r\n const rawLines = text.split(/\\r?\\n/);\r\n\r\n // First pass: classify + measure indentation.\r\n for (let i = 0; i < rawLines.length; i++) {\r\n const raw = rawLines[i];\r\n const lineNo = i + 1;\r\n\r\n const m = raw.match(/^(\\s*)(.*)$/);\r\n const indentRaw = m ? m[1] : '';\r\n const content = m ? m[2] : '';\r\n\r\n const {indentSpaces, hasTabs} = measureIndent(indentRaw, indentStep);\r\n\r\n if (hasTabs) {\r\n diagnostics.push({\r\n line: lineNo,\r\n message:\r\n 'Tabs detected in indentation. Consider using spaces only for consistent levels.',\r\n severity: mode === 'strict' ? 'warning' : 'info',\r\n code: 'indent-tabs',\r\n });\r\n }\r\n\r\n const trimmed = content.trim();\r\n let kind: LineKind;\r\n if (!trimmed) {\r\n kind = 'blank';\r\n } else if (trimmed.startsWith('#') || trimmed.startsWith('//')) {\r\n kind = 'comment';\r\n } else {\r\n kind = 'entry';\r\n }\r\n\r\n lines.push({\r\n index: i,\r\n lineNo,\r\n raw,\r\n kind,\r\n indentSpaces,\r\n content,\r\n });\r\n }\r\n\r\n const rootNodes: AstNode[] = [];\r\n const stack: AstNode[] = []; // nodes by depth index (0 = level 0, 1 = level 1, ...)\r\n\r\n const depthCtx: DepthContext = {\r\n lastIndentSpaces: null,\r\n lastDepth: null,\r\n lastWasFile: false,\r\n };\r\n\r\n for (const line of lines) {\r\n if (line.kind !== 'entry') continue;\r\n\r\n const {entry, depth, diags} = parseEntryLine(\r\n line,\r\n indentStep,\r\n mode,\r\n depthCtx,\r\n );\r\n diagnostics.push(...diags);\r\n\r\n if (!entry) {\r\n continue;\r\n }\r\n\r\n attachNode(entry, depth, line, rootNodes, stack, diagnostics, mode);\r\n depthCtx.lastWasFile = !entry.isDir;\r\n }\r\n\r\n return {\r\n rootNodes,\r\n lines,\r\n diagnostics,\r\n options: {\r\n indentStep,\r\n mode,\r\n },\r\n };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal: indentation measurement & depth fixing (relative model)\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction measureIndent(rawIndent: string, indentStep: number): {\r\n indentSpaces: number;\r\n hasTabs: boolean;\r\n} {\r\n let spaces = 0;\r\n let hasTabs = false;\r\n\r\n for (const ch of rawIndent) {\r\n if (ch === ' ') {\r\n spaces += 1;\r\n } else if (ch === '\\t') {\r\n hasTabs = true;\r\n // Treat tab as one level to avoid chaos. This is arbitrary but stable-ish.\r\n spaces += indentStep;\r\n }\r\n }\r\n\r\n return {indentSpaces: spaces, hasTabs};\r\n}\r\n\r\ninterface DepthContext {\r\n lastIndentSpaces: number | null;\r\n lastDepth: number | null;\r\n lastWasFile: boolean;\r\n}\r\n\r\n/**\r\n * Compute logical depth using a relative algorithm:\r\n *\r\n * First entry line:\r\n * - depth = 0\r\n *\r\n * For each subsequent entry line:\r\n * Let prevSpaces = lastIndentSpaces, prevDepth = lastDepth.\r\n *\r\n * - if spaces > prevSpaces:\r\n * - if spaces > prevSpaces + indentStep → warn about a \"skip\"\r\n * - depth = prevDepth + 1\r\n *\r\n * - else if spaces === prevSpaces:\r\n * - depth = prevDepth\r\n *\r\n * - else (spaces < prevSpaces):\r\n * - diff = prevSpaces - spaces\r\n * - steps = round(diff / indentStep)\r\n * - if diff is not a clean multiple → warn about misalignment\r\n * - depth = max(prevDepth - steps, 0)\r\n */\r\nfunction computeDepth(\r\n line: StructureAstLine,\r\n indentStep: number,\r\n mode: AstMode,\r\n ctx: DepthContext,\r\n diagnostics: Diagnostic[],\r\n): number {\r\n let spaces = line.indentSpaces;\r\n if (spaces < 0) spaces = 0;\r\n\r\n let depth: number;\r\n\r\n if (ctx.lastIndentSpaces == null || ctx.lastDepth == null) {\r\n // First entry line: treat as root.\r\n depth = 0;\r\n } else {\r\n const prevSpaces = ctx.lastIndentSpaces;\r\n const prevDepth = ctx.lastDepth;\r\n\r\n if (spaces > prevSpaces) {\r\n const diff = spaces - prevSpaces;\r\n\r\n // NEW: indenting under a file → child-of-file-loose\r\n if (ctx.lastWasFile) {\r\n diagnostics.push({\r\n line: line.lineNo,\r\n message:\r\n 'Entry appears indented under a file; treating it as a sibling of the file instead of a child.',\r\n severity: mode === 'strict' ? 'error' : 'warning',\r\n code: 'child-of-file-loose',\r\n });\r\n\r\n // Treat as sibling of the file, not a child:\r\n depth = prevDepth;\r\n } else {\r\n if (diff > indentStep) {\r\n diagnostics.push({\r\n line: line.lineNo,\r\n message: `Indentation jumps from ${prevSpaces} to ${spaces} spaces; treating as one level deeper.`,\r\n severity: mode === 'strict' ? 'error' : 'warning',\r\n code: 'indent-skip-level',\r\n });\r\n }\r\n depth = prevDepth + 1;\r\n }\r\n } else if (spaces === prevSpaces) {\r\n depth = prevDepth;\r\n } else {\r\n const diff = prevSpaces - spaces;\r\n const steps = Math.round(diff / indentStep);\r\n\r\n if (diff % indentStep !== 0) {\r\n diagnostics.push({\r\n line: line.lineNo,\r\n message: `Indentation decreases from ${prevSpaces} to ${spaces} spaces, which is not a multiple of indent step (${indentStep}).`,\r\n severity: mode === 'strict' ? 'error' : 'warning',\r\n code: 'indent-misaligned',\r\n });\r\n }\r\n\r\n depth = Math.max(prevDepth - steps, 0);\r\n }\r\n }\r\n\r\n ctx.lastIndentSpaces = spaces;\r\n ctx.lastDepth = depth;\r\n\r\n return depth;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal: entry line parsing (path + annotations)\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface ParsedEntry {\r\n segmentName: string;\r\n isDir: boolean;\r\n stub?: string;\r\n include?: string[];\r\n exclude?: string[];\r\n}\r\n\r\n/**\r\n * Parse a single entry line into a ParsedEntry + depth.\r\n */\r\nfunction parseEntryLine(\r\n line: StructureAstLine,\r\n indentStep: number,\r\n mode: AstMode,\r\n ctx: DepthContext,\r\n): {\r\n entry: ParsedEntry | null;\r\n depth: number;\r\n diags: Diagnostic[];\r\n} {\r\n const diags: Diagnostic[] = [];\r\n const depth = computeDepth(line, indentStep, mode, ctx, diags);\r\n\r\n // Extract before inline comment\r\n const {contentWithoutComment} = extractInlineCommentParts(line.content);\r\n const trimmed = contentWithoutComment.trim();\r\n if (!trimmed) {\r\n // Structural line that became empty after stripping inline comment; treat as no-op.\r\n return {entry: null, depth, diags};\r\n }\r\n\r\n const parts = trimmed.split(/\\s+/);\r\n const pathToken = parts[0];\r\n const annotationTokens = parts.slice(1);\r\n\r\n // Path sanity checks\r\n if (pathToken.includes(':')) {\r\n diags.push({\r\n line: line.lineNo,\r\n message:\r\n 'Path token contains \":\" which is reserved for annotations. This is likely a mistake.',\r\n severity: mode === 'strict' ? 'error' : 'warning',\r\n code: 'path-colon',\r\n });\r\n }\r\n\r\n const isDir = pathToken.endsWith('/');\r\n const segmentName = pathToken;\r\n\r\n let stub: string | undefined;\r\n const include: string[] = [];\r\n const exclude: string[] = [];\r\n\r\n for (const token of annotationTokens) {\r\n if (token.startsWith('@stub:')) {\r\n stub = token.slice('@stub:'.length);\r\n } else if (token.startsWith('@include:')) {\r\n const val = token.slice('@include:'.length);\r\n if (val) {\r\n include.push(\r\n ...val\r\n .split(',')\r\n .map((s) => s.trim())\r\n .filter(Boolean),\r\n );\r\n }\r\n } else if (token.startsWith('@exclude:')) {\r\n const val = token.slice('@exclude:'.length);\r\n if (val) {\r\n exclude.push(\r\n ...val\r\n .split(',')\r\n .map((s) => s.trim())\r\n .filter(Boolean),\r\n );\r\n }\r\n } else if (token.startsWith('@')) {\r\n diags.push({\r\n line: line.lineNo,\r\n message: `Unknown annotation token \"${token}\".`,\r\n severity: 'info',\r\n code: 'unknown-annotation',\r\n });\r\n }\r\n }\r\n\r\n const entry: ParsedEntry = {\r\n segmentName,\r\n isDir,\r\n stub,\r\n include: include.length ? include : undefined,\r\n exclude: exclude.length ? exclude : undefined,\r\n };\r\n\r\n return {entry, depth, diags};\r\n}\r\n\r\nexport function mapThrough(content: string) {\r\n let cutIndex = -1;\r\n const len = content.length;\r\n\r\n for (let i = 0; i < len; i++) {\r\n const ch = content[i];\r\n const prev = i > 0 ? content[i - 1] : '';\r\n\r\n // Inline \"# ...\"\r\n if (ch === '#') {\r\n if (i === 0) {\r\n // full-line comment; not our case (we only call this for \"entry\" lines)\r\n continue;\r\n }\r\n if (prev === ' ' || prev === '\\t') {\r\n cutIndex = i;\r\n break;\r\n }\r\n }\r\n\r\n // Inline \"// ...\"\r\n if (\r\n ch === '/' &&\r\n i + 1 < len &&\r\n content[i + 1] === '/' &&\r\n (prev === ' ' || prev === '\\t')\r\n ) {\r\n cutIndex = i;\r\n break;\r\n }\r\n }\r\n\r\n return cutIndex;\r\n}\r\n\r\n/**\r\n * Extracts the inline comment portion (if any) from the content area (no leading indent).\r\n */\r\nexport function extractInlineCommentParts(content: string): {\r\n contentWithoutComment: string;\r\n inlineComment: string | null;\r\n} {\r\n const cutIndex = mapThrough(content);\r\n\r\n if (cutIndex === -1) {\r\n return {\r\n contentWithoutComment: content,\r\n inlineComment: null,\r\n };\r\n }\r\n\r\n return {\r\n contentWithoutComment: content.slice(0, cutIndex),\r\n inlineComment: content.slice(cutIndex),\r\n };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal: tree construction\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction attachNode(\r\n entry: ParsedEntry,\r\n depth: number,\r\n line: StructureAstLine,\r\n rootNodes: AstNode[],\r\n stack: AstNode[],\r\n diagnostics: Diagnostic[],\r\n mode: AstMode,\r\n): void {\r\n const lineNo = line.lineNo;\r\n\r\n // Pop stack until we’re at or above the desired depth.\r\n while (stack.length > depth) {\r\n stack.pop();\r\n }\r\n\r\n let parent: DirNode | null = null;\r\n if (depth > 0) {\r\n const candidate = stack[depth - 1];\r\n if (!candidate) {\r\n // Indented but no parent; in strict mode error, in loose mode, treat as root.\r\n diagnostics.push({\r\n line: lineNo,\r\n message: `Entry has indent depth ${depth} but no parent at depth ${\r\n depth - 1\r\n }. Treating as root.`,\r\n severity: mode === 'strict' ? 'error' : 'warning',\r\n code: 'missing-parent',\r\n });\r\n } else if (candidate.type === 'file') {\r\n // Child under file, impossible by design.\r\n if (mode === 'strict') {\r\n diagnostics.push({\r\n line: lineNo,\r\n message: `Cannot attach child under file \"${candidate.path}\".`,\r\n severity: 'error',\r\n code: 'child-of-file',\r\n });\r\n // Force it to root to at least keep the node.\r\n } else {\r\n diagnostics.push({\r\n line: lineNo,\r\n message: `Entry appears under file \"${candidate.path}\". Attaching as sibling at depth ${\r\n candidate.depth\r\n }.`,\r\n severity: 'warning',\r\n code: 'child-of-file-loose',\r\n });\r\n // Treat as sibling at candidate's depth.\r\n while (stack.length > candidate.depth) {\r\n stack.pop();\r\n }\r\n }\r\n } else {\r\n parent = candidate as DirNode;\r\n }\r\n }\r\n\r\n const parentPath = parent ? parent.path.replace(/\\/$/, '') : '';\r\n const normalizedSegment = toPosixPath(entry.segmentName.replace(/\\/+$/, ''));\r\n const fullPath = parentPath\r\n ? `${parentPath}/${normalizedSegment}${entry.isDir ? '/' : ''}`\r\n : `${normalizedSegment}${entry.isDir ? '/' : ''}`;\r\n\r\n const baseNode: AstNodeBase = {\r\n type: entry.isDir ? 'dir' : 'file',\r\n name: entry.segmentName,\r\n depth,\r\n line: lineNo,\r\n path: fullPath,\r\n parent,\r\n ...(entry.stub ? {stub: entry.stub} : {}),\r\n ...(entry.include ? {include: entry.include} : {}),\r\n ...(entry.exclude ? {exclude: entry.exclude} : {}),\r\n };\r\n\r\n if (entry.isDir) {\r\n const dirNode: DirNode = {\r\n ...baseNode,\r\n type: 'dir',\r\n children: [],\r\n };\r\n\r\n if (parent) {\r\n parent.children.push(dirNode);\r\n } else {\r\n rootNodes.push(dirNode);\r\n }\r\n\r\n // Ensure stack[depth] is this dir.\r\n while (stack.length > depth) {\r\n stack.pop();\r\n }\r\n stack[depth] = dirNode;\r\n } else {\r\n const fileNode: FileNode = {\r\n ...baseNode,\r\n type: 'file',\r\n };\r\n\r\n if (parent) {\r\n parent.children.push(fileNode);\r\n } else {\r\n rootNodes.push(fileNode);\r\n }\r\n\r\n // Files themselves are NOT placed on the stack to prevent children,\r\n // but attachNode will repair children-under-file in loose mode.\r\n }\r\n}","// src/ast/format.ts\r\n\r\nimport {\r\n parseStructureAst,\r\n type AstMode,\r\n type StructureAst,\r\n type AstNode, extractInlineCommentParts,\r\n} from './parser';\r\nimport {FormatConfig} from \"../schema\";\r\n\r\nexport interface FormatOptions extends FormatConfig {\r\n /**\r\n * Spaces per indent level for re-printing entries.\r\n * Defaults to 2.\r\n */\r\n indentStep?: number;\r\n\r\n /**\r\n * Parser mode to use for the AST.\r\n * - \"loose\": attempt to repair mis-indents / bad parents (default).\r\n * - \"strict\": report issues as errors, less repair.\r\n */\r\n mode?: AstMode;\r\n\r\n /**\r\n * Normalize newlines to the dominant style in the original text (LF vs. CRLF).\r\n * Defaults to true.\r\n */\r\n normalizeNewlines?: boolean;\r\n\r\n /**\r\n * Trim trailing whitespace on non-entry lines (comments / blanks).\r\n * Defaults to true.\r\n */\r\n trimTrailingWhitespace?: boolean;\r\n\r\n /**\r\n * Whether to normalize annotation ordering and spacing:\r\n * name @stub:... @include:... @exclude:...\r\n * Defaults to true.\r\n */\r\n normalizeAnnotations?: boolean;\r\n}\r\n\r\nexport interface FormatResult {\r\n /** Formatted text. */\r\n text: string;\r\n /** Underlying AST that was used. */\r\n ast: StructureAst;\r\n}\r\n\r\n/**\r\n * Smart formatter for scaffold structure files.\r\n *\r\n * - Uses the loose AST parser (parseStructureAst) to understand structure.\r\n * - Auto-fixes indentation based on tree depth (indentStep).\r\n * - Keeps **all** blank lines and full-line comments in place.\r\n * - Preserves inline comments (# / //) on entry lines.\r\n * - Canonicalizes annotation order (stub → include → exclude) if enabled.\r\n *\r\n * It does **not** throw on invalid input:\r\n * - parseStructureAst always returns an AST + diagnostics.\r\n * - If something is catastrophically off (entry/node counts mismatch),\r\n * it falls back to a minimal normalization pass.\r\n */\r\nexport function formatStructureText(\r\n text: string,\r\n options: FormatOptions = {},\r\n): FormatResult {\r\n const indentStep = options.indentStep ?? 2;\r\n const mode: AstMode = options.mode ?? 'loose';\r\n const normalizeNewlines =\r\n options.normalizeNewlines === undefined ? true : options.normalizeNewlines;\r\n const trimTrailingWhitespace =\r\n options.trimTrailingWhitespace === undefined\r\n ? true\r\n : options.trimTrailingWhitespace;\r\n const normalizeAnnotations =\r\n options.normalizeAnnotations === undefined\r\n ? true\r\n : options.normalizeAnnotations;\r\n\r\n // 1. Parse to our \"smart\" AST (non-throwing).\r\n const ast = parseStructureAst(text, {\r\n indentStep,\r\n mode,\r\n });\r\n\r\n const rawLines = text.split(/\\r?\\n/);\r\n const lineCount = rawLines.length;\r\n\r\n // Sanity check: AST lines length should match raw lines length.\r\n if (ast.lines.length !== lineCount) {\r\n return {\r\n text: basicNormalize(text, {normalizeNewlines, trimTrailingWhitespace}),\r\n ast,\r\n };\r\n }\r\n\r\n // 2. Collect entry line indices and inline comments from the original text.\r\n const entryLineIndexes: number[] = [];\r\n const inlineComments: (string | null)[] = [];\r\n\r\n for (let i = 0; i < lineCount; i++) {\r\n const lineMeta = ast.lines[i];\r\n if (lineMeta.kind === 'entry') {\r\n entryLineIndexes.push(i);\r\n const {inlineComment} = extractInlineCommentParts(lineMeta.content);\r\n inlineComments.push(inlineComment);\r\n }\r\n }\r\n\r\n // 3. Flatten AST nodes in depth-first order to get an ordered node list.\r\n const flattened: { node: AstNode; level: number }[] = [];\r\n flattenAstNodes(ast.rootNodes, 0, flattened);\r\n\r\n if (flattened.length !== entryLineIndexes.length) {\r\n // If counts don't match, something is inconsistent – do not risk corruption.\r\n return {\r\n text: basicNormalize(text, {normalizeNewlines, trimTrailingWhitespace}),\r\n ast,\r\n };\r\n }\r\n\r\n // 4. Build canonical entry lines from AST nodes.\r\n const canonicalEntryLines: string[] = flattened.map(({node, level}) =>\r\n formatAstNodeLine(node, level, indentStep, normalizeAnnotations),\r\n );\r\n\r\n // 5. Merge canonical entry lines + inline comments back into original structure.\r\n const resultLines: string[] = [];\r\n let entryIdx = 0;\r\n\r\n for (let i = 0; i < lineCount; i++) {\r\n const lineMeta = ast.lines[i];\r\n const originalLine = rawLines[i];\r\n\r\n if (lineMeta.kind === 'entry') {\r\n const base = canonicalEntryLines[entryIdx].replace(/[ \\t]+$/g, '');\r\n const inline = inlineComments[entryIdx];\r\n entryIdx++;\r\n\r\n if (inline) {\r\n // Always ensure a single space before the inline comment marker.\r\n resultLines.push(base + ' ' + inline);\r\n } else {\r\n resultLines.push(base);\r\n }\r\n } else {\r\n let out = originalLine;\r\n if (trimTrailingWhitespace) {\r\n out = out.replace(/[ \\t]+$/g, '');\r\n }\r\n resultLines.push(out);\r\n }\r\n }\r\n\r\n const eol = normalizeNewlines ? detectPreferredEol(text) : getRawEol(text);\r\n return {\r\n text: resultLines.join(eol),\r\n ast,\r\n };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal helpers\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Fallback: basic normalization when we can't safely map AST ↔ text.\r\n */\r\nfunction basicNormalize(\r\n text: string,\r\n opts: { normalizeNewlines: boolean; trimTrailingWhitespace: boolean },\r\n): string {\r\n const lines = text.split(/\\r?\\n/);\r\n const normalizedLines = opts.trimTrailingWhitespace\r\n ? lines.map((line) => line.replace(/[ \\t]+$/g, ''))\r\n : lines;\r\n\r\n const eol = opts.normalizeNewlines ? detectPreferredEol(text) : getRawEol(text);\r\n return normalizedLines.join(eol);\r\n}\r\n\r\n/**\r\n * Detect whether the file is more likely LF or CRLF and reuse that.\r\n * If mixed or no clear signal, default to \"\\n\".\r\n */\r\nfunction detectPreferredEol(text: string): string {\r\n const crlfCount = (text.match(/\\r\\n/g) || []).length;\r\n const lfCount = (text.match(/(?<!\\r)\\n/g) || []).length;\r\n\r\n if (crlfCount === 0 && lfCount === 0) {\r\n return '\\n';\r\n }\r\n\r\n if (crlfCount > lfCount) {\r\n return '\\r\\n';\r\n }\r\n\r\n return '\\n';\r\n}\r\n\r\n/**\r\n * If you really want the raw style, detect only CRLF vs. LF.\r\n */\r\nfunction getRawEol(text: string): string {\r\n return text.includes('\\r\\n') ? '\\r\\n' : '\\n';\r\n}\r\n\r\n/**\r\n * Flatten AST nodes into a depth-first list while tracking indent level.\r\n */\r\nfunction flattenAstNodes(\r\n nodes: AstNode[],\r\n level: number,\r\n out: { node: AstNode; level: number }[],\r\n): void {\r\n for (const node of nodes) {\r\n out.push({node, level});\r\n if (node.type === 'dir' && node.children && node.children.length) {\r\n flattenAstNodes(node.children, level + 1, out);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Format a single AST node into one canonical line.\r\n *\r\n * - Uses `level * indentStep` spaces as indentation.\r\n * - Uses the node's `name` as provided by the parser (e.g. \"src/\" or \"index.ts\").\r\n * - Annotations are printed in a stable order if normalizeAnnotations is true:\r\n * @stub:..., @include:..., @exclude:...\r\n */\r\nfunction formatAstNodeLine(\r\n node: AstNode,\r\n level: number,\r\n indentStep: number,\r\n normalizeAnnotations: boolean,\r\n): string {\r\n const indent = ' '.repeat(indentStep * level);\r\n const baseName = node.name;\r\n\r\n if (!normalizeAnnotations) {\r\n return indent + baseName;\r\n }\r\n\r\n const tokens: string[] = [];\r\n\r\n if (node.stub) {\r\n tokens.push(`@stub:${node.stub}`);\r\n }\r\n if (node.include && node.include.length > 0) {\r\n tokens.push(`@include:${node.include.join(',')}`);\r\n }\r\n if (node.exclude && node.exclude.length > 0) {\r\n tokens.push(`@exclude:${node.exclude.join(',')}`);\r\n }\r\n\r\n const annotations = tokens.length ? ' ' + tokens.join(' ') : '';\r\n return indent + baseName + annotations;\r\n}","// src/core/structure-txt.ts\r\n\r\nimport type {StructureEntry, DirEntry, FileEntry} from '../schema';\r\nimport {toPosixPath} from '../util/fs-utils';\r\nimport {mapThrough} from \"../ast\";\r\n\r\ninterface ParsedLine {\r\n lineNo: number;\r\n indentSpaces: number;\r\n rawPath: string;\r\n stub?: string;\r\n include?: string[];\r\n exclude?: string[];\r\n}\r\n\r\n/**\r\n * Strip inline comments from a content segment.\r\n *\r\n * Supports:\r\n * - \"index.ts # comment\"\r\n * - \"index.ts // comment\"\r\n *\r\n * Rules:\r\n * - We assume leading indentation has already been removed.\r\n * - Leading '#' or '//' (full-line comments) are handled BEFORE this function.\r\n * - A comment starts at the first '#' or '//' that is\r\n * preceded by whitespace (space or tab).\r\n */\r\nfunction stripInlineComment(content: string): string {\r\n const cutIndex = mapThrough(content);\r\n if (cutIndex === -1) {\r\n return content.trimEnd();\r\n }\r\n\r\n return content.slice(0, cutIndex).trimEnd();\r\n}\r\n\r\n/**\r\n * Parse a single non-empty, non-comment line into a ParsedLine.\r\n * Supports inline annotations:\r\n * - @stub:name\r\n * - @include:pattern,pattern2\r\n * - @exclude:pattern,pattern2\r\n */\r\nfunction parseLine(line: string, lineNo: number): ParsedLine | null {\r\n const match = line.match(/^(\\s*)(.*)$/);\r\n if (!match) return null;\r\n\r\n const indentSpaces = match[1].length;\r\n let rest = match[2];\r\n\r\n // If line (after indent) is empty, skip\r\n if (!rest.trim()) return null;\r\n\r\n // Full-line comments after indent\r\n const trimmedRest = rest.trimStart();\r\n if (trimmedRest.startsWith('#') || trimmedRest.startsWith('//')) {\r\n return null;\r\n }\r\n\r\n // Strip inline comments (# or //) before parsing tokens\r\n const stripped = stripInlineComment(rest);\r\n const trimmed = stripped.trim();\r\n if (!trimmed) return null;\r\n\r\n const parts = trimmed.split(/\\s+/);\r\n if (!parts.length) return null;\r\n\r\n const pathToken = parts[0];\r\n\r\n // 🚫 Reserve \":\" for annotations only – paths may not contain it.\r\n if (pathToken.includes(':')) {\r\n throw new Error(\r\n `structure.txt: \":\" is reserved for annotations (@stub:, @include:, etc). ` +\r\n `Invalid path \"${pathToken}\" on line ${lineNo}.`,\r\n );\r\n }\r\n\r\n let stub: string | undefined;\r\n const include: string[] = [];\r\n const exclude: string[] = [];\r\n\r\n for (const token of parts.slice(1)) {\r\n if (token.startsWith('@stub:')) {\r\n stub = token.slice('@stub:'.length);\r\n } else if (token.startsWith('@include:')) {\r\n const val = token.slice('@include:'.length);\r\n if (val) {\r\n include.push(\r\n ...val\r\n .split(',')\r\n .map((s) => s.trim())\r\n .filter(Boolean),\r\n );\r\n }\r\n } else if (token.startsWith('@exclude:')) {\r\n const val = token.slice('@exclude:'.length);\r\n if (val) {\r\n exclude.push(\r\n ...val\r\n .split(',')\r\n .map((s) => s.trim())\r\n .filter(Boolean),\r\n );\r\n }\r\n }\r\n }\r\n\r\n return {\r\n lineNo,\r\n indentSpaces,\r\n rawPath: pathToken,\r\n stub,\r\n include: include.length ? include : undefined,\r\n exclude: exclude.length ? exclude : undefined,\r\n };\r\n}\r\n\r\n/**\r\n * Convert a structure.txt content into a nested StructureEntry[].\r\n *\r\n * Rules:\r\n * - Indentation is **indentStep** spaces per level (default: 2).\r\n * - Indent must be a multiple of indentStep.\r\n * - You cannot \"skip\" levels (no jumping from level 0 to 2 directly).\r\n * - **Only directories can have children**:\r\n * - If you indent under a file, an error is thrown.\r\n * - Folders must end with \"/\" in the txt; paths are normalized to POSIX.\r\n */\r\nexport function parseStructureText(\r\n text: string,\r\n indentStep = 2,\r\n): StructureEntry[] {\r\n const lines = text.split(/\\r?\\n/);\r\n const parsed: ParsedLine[] = [];\r\n\r\n for (let i = 0; i < lines.length; i++) {\r\n const lineNo = i + 1;\r\n const p = parseLine(lines[i], lineNo);\r\n if (p) parsed.push(p);\r\n }\r\n\r\n const rootEntries: StructureEntry[] = [];\r\n\r\n type StackItem = {\r\n level: number;\r\n entry: DirEntry | FileEntry;\r\n isDir: boolean;\r\n };\r\n\r\n const stack: StackItem[] = [];\r\n\r\n for (const p of parsed) {\r\n const {indentSpaces, lineNo} = p;\r\n\r\n if (indentSpaces % indentStep !== 0) {\r\n throw new Error(\r\n `structure.txt: Invalid indent on line ${lineNo}. ` +\r\n `Indent must be multiples of ${indentStep} spaces.`,\r\n );\r\n }\r\n\r\n const level = indentSpaces / indentStep;\r\n\r\n // Determine parent level and enforce no skipping\r\n if (level > stack.length) {\r\n // e.g. current stack depth 1, but line level=3 is invalid\r\n if (level !== stack.length + 1) {\r\n throw new Error(\r\n `structure.txt: Invalid indentation on line ${lineNo}. ` +\r\n `You cannot jump more than one level at a time. ` +\r\n `Previous depth: ${stack.length}, this line depth: ${level}.`,\r\n );\r\n }\r\n }\r\n\r\n // If this line is indented (level > 0), parent must exist and must be dir\r\n if (level > 0) {\r\n const parent = stack[level - 1]; // parent level is (level - 1)\r\n if (!parent) {\r\n throw new Error(\r\n `structure.txt: Indented entry without a parent on line ${lineNo}.`,\r\n );\r\n }\r\n if (!parent.isDir) {\r\n throw new Error(\r\n `structure.txt: Cannot indent under a file on line ${lineNo}. ` +\r\n `Files cannot have children. Parent: \"${parent.entry.path}\".`,\r\n );\r\n }\r\n }\r\n\r\n const isDir = p.rawPath.endsWith('/');\r\n const clean = p.rawPath.replace(/\\/$/, '');\r\n const basePath = toPosixPath(clean);\r\n\r\n // Pop stack until we are at the correct depth\r\n while (stack.length > level) {\r\n stack.pop();\r\n }\r\n\r\n const parent = stack[stack.length - 1]?.entry as DirEntry | undefined;\r\n const parentPath = parent ? parent.path.replace(/\\/$/, '') : '';\r\n\r\n const fullPath = parentPath\r\n ? `${parentPath}/${basePath}${isDir ? '/' : ''}`\r\n : `${basePath}${isDir ? '/' : ''}`;\r\n\r\n if (isDir) {\r\n const dirEntry: DirEntry = {\r\n type: 'dir',\r\n path: fullPath,\r\n children: [],\r\n ...(p.stub ? {stub: p.stub} : {}),\r\n ...(p.include ? {include: p.include} : {}),\r\n ...(p.exclude ? {exclude: p.exclude} : {}),\r\n };\r\n\r\n if (parent && parent.type === 'dir') {\r\n parent.children = parent.children ?? [];\r\n parent.children.push(dirEntry);\r\n } else if (!parent) {\r\n rootEntries.push(dirEntry);\r\n }\r\n\r\n stack.push({level, entry: dirEntry, isDir: true});\r\n } else {\r\n const fileEntry: FileEntry = {\r\n type: 'file',\r\n path: fullPath,\r\n ...(p.stub ? {stub: p.stub} : {}),\r\n ...(p.include ? {include: p.include} : {}),\r\n ...(p.exclude ? {exclude: p.exclude} : {}),\r\n };\r\n\r\n if (parent && parent.type === 'dir') {\r\n parent.children = parent.children ?? [];\r\n parent.children.push(fileEntry);\r\n } else if (!parent) {\r\n rootEntries.push(fileEntry);\r\n }\r\n\r\n // We still push files into the stack at this level so that\r\n // bad indentation under them can be detected and rejected.\r\n stack.push({level, entry: fileEntry, isDir: false});\r\n }\r\n }\r\n\r\n return rootEntries;\r\n}","// src/core/resolve-structure.ts\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport type {\r\n ScaffoldConfig,\r\n StructureEntry,\r\n StructureGroupConfig,\r\n} from '../schema';\r\nimport { parseStructureText } from './structure-txt';\r\nimport { defaultLogger } from '../util/logger';\r\n\r\nconst logger = defaultLogger.child('[structure]');\r\n\r\nexport function resolveGroupStructure(\r\n scaffoldDir: string,\r\n group: StructureGroupConfig,\r\n): StructureEntry[] {\r\n if (group.structure && group.structure.length) {\r\n logger.debug(`Using inline structure for group \"${group.name}\"`);\r\n return group.structure;\r\n }\r\n\r\n const fileName = group.structureFile ?? `${group.name}.txt`;\r\n const filePath = path.join(scaffoldDir, fileName);\r\n\r\n if (!fs.existsSync(filePath)) {\r\n throw new Error(\r\n `@timeax/scaffold: Group \"${group.name}\" has no structure. ` +\r\n `Expected file \"${fileName}\" in \"${scaffoldDir}\".`,\r\n );\r\n }\r\n\r\n logger.debug(`Reading structure for group \"${group.name}\" from ${filePath}`);\r\n const raw = fs.readFileSync(filePath, 'utf8');\r\n return parseStructureText(raw);\r\n}\r\n\r\n/**\r\n * Legacy single-structure mode (no groups defined).\r\n */\r\nexport function resolveSingleStructure(\r\n scaffoldDir: string,\r\n config: ScaffoldConfig,\r\n): StructureEntry[] {\r\n if (config.structure && config.structure.length) {\r\n logger.debug('Using inline single structure (no groups)');\r\n return config.structure;\r\n }\r\n\r\n const fileName = config.structureFile ?? 'structure.txt';\r\n const filePath = path.join(scaffoldDir, fileName);\r\n\r\n if (!fs.existsSync(filePath)) {\r\n throw new Error(\r\n `@timeax/scaffold: No structure defined. ` +\r\n `Expected \"${fileName}\" in \"${scaffoldDir}\".`,\r\n );\r\n }\r\n\r\n logger.debug(`Reading single structure from ${filePath}`);\r\n const raw = fs.readFileSync(filePath, 'utf8');\r\n return parseStructureText(raw);\r\n}","// src/core/cache-manager.ts\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport { ensureDirSync, toPosixPath } from '../util/fs-utils';\r\nimport { defaultLogger } from '../util/logger';\r\n\r\nconst logger = defaultLogger.child('[cache]');\r\n\r\nexport interface CacheEntry {\r\n /**\r\n * Path relative to the *project root* (global root), POSIX style.\r\n */\r\n path: string;\r\n\r\n createdAt: string;\r\n sizeAtCreate: number;\r\n createdByStub?: string;\r\n groupName?: string;\r\n groupRoot?: string;\r\n}\r\n\r\nexport interface CacheFile {\r\n version: 1;\r\n entries: Record<string, CacheEntry>;\r\n}\r\n\r\nconst DEFAULT_CACHE: CacheFile = {\r\n version: 1,\r\n entries: {},\r\n};\r\n\r\nexport class CacheManager {\r\n private cache: CacheFile = DEFAULT_CACHE;\r\n\r\n constructor(\r\n private readonly projectRoot: string,\r\n private readonly cacheFileRelPath: string,\r\n ) { }\r\n\r\n private get cachePathAbs(): string {\r\n return path.resolve(this.projectRoot, this.cacheFileRelPath);\r\n }\r\n\r\n load(): void {\r\n const cachePath = this.cachePathAbs;\r\n if (!fs.existsSync(cachePath)) {\r\n this.cache = { ...DEFAULT_CACHE, entries: {} };\r\n return;\r\n }\r\n\r\n try {\r\n const raw = fs.readFileSync(cachePath, 'utf8');\r\n const parsed = JSON.parse(raw) as CacheFile;\r\n if (parsed.version === 1 && parsed.entries) {\r\n this.cache = parsed;\r\n } else {\r\n logger.warn('Cache file version mismatch or invalid, resetting cache.');\r\n this.cache = { ...DEFAULT_CACHE, entries: {} };\r\n }\r\n } catch (err) {\r\n logger.warn('Failed to read cache file, resetting cache.', err);\r\n this.cache = { ...DEFAULT_CACHE, entries: {} };\r\n }\r\n }\r\n\r\n save(): void {\r\n const cachePath = this.cachePathAbs;\r\n const dir = path.dirname(cachePath);\r\n ensureDirSync(dir);\r\n fs.writeFileSync(cachePath, JSON.stringify(this.cache, null, 2), 'utf8');\r\n }\r\n\r\n get(relPath: string): CacheEntry | undefined {\r\n const key = toPosixPath(relPath);\r\n return this.cache.entries[key];\r\n }\r\n\r\n set(entry: CacheEntry): void {\r\n const key = toPosixPath(entry.path);\r\n this.cache.entries[key] = {\r\n ...entry,\r\n path: key,\r\n };\r\n }\r\n\r\n delete(relPath: string): void {\r\n const key = toPosixPath(relPath);\r\n delete this.cache.entries[key];\r\n }\r\n\r\n allPaths(): string[] {\r\n return Object.keys(this.cache.entries);\r\n }\r\n\r\n allEntries(): CacheEntry[] {\r\n return Object.values(this.cache.entries);\r\n }\r\n}","// src/core/hook-runner.ts\r\n\r\nimport { minimatch } from 'minimatch';\r\nimport type {\r\n ScaffoldConfig,\r\n HookContext,\r\n RegularHookKind,\r\n StubHookKind,\r\n StubConfig,\r\n RegularHookConfig,\r\n StubHookConfig,\r\n} from '../schema';\r\n\r\nfunction matchesFilter(\r\n pathRel: string,\r\n cfg: { include?: string[]; exclude?: string[]; files?: string[] },\r\n): boolean {\r\n const { include, exclude, files } = cfg;\r\n\r\n const patterns: string[] = [];\r\n if (include?.length) patterns.push(...include);\r\n if (files?.length) patterns.push(...files);\r\n\r\n if (patterns.length) {\r\n const ok = patterns.some((p) => minimatch(pathRel, p));\r\n if (!ok) return false;\r\n }\r\n\r\n if (exclude?.length) {\r\n const blocked = exclude.some((p) => minimatch(pathRel, p));\r\n if (blocked) return false;\r\n }\r\n\r\n return true;\r\n}\r\n\r\nexport class HookRunner {\r\n constructor(private readonly config: ScaffoldConfig) { }\r\n\r\n async runRegular(kind: RegularHookKind, ctx: HookContext): Promise<void> {\r\n const configs: RegularHookConfig[] = this.config.hooks?.[kind] ?? [];\r\n for (const cfg of configs) {\r\n if (!matchesFilter(ctx.targetPath, cfg)) continue;\r\n await cfg.fn(ctx);\r\n }\r\n }\r\n\r\n private getStubConfig(stubName?: string): StubConfig | undefined {\r\n if (!stubName) return undefined;\r\n return this.config.stubs?.[stubName];\r\n }\r\n\r\n async runStub(kind: StubHookKind, ctx: HookContext): Promise<void> {\r\n const stub = this.getStubConfig(ctx.stubName);\r\n if (!stub?.hooks) return;\r\n\r\n const configs: StubHookConfig[] =\r\n kind === 'preStub'\r\n ? stub.hooks.preStub ?? []\r\n : stub.hooks.postStub ?? [];\r\n\r\n for (const cfg of configs) {\r\n if (!matchesFilter(ctx.targetPath, cfg)) continue;\r\n await cfg.fn(ctx);\r\n }\r\n }\r\n\r\n async renderStubContent(ctx: HookContext): Promise<string | undefined> {\r\n const stub = this.getStubConfig(ctx.stubName);\r\n if (!stub?.getContent) return undefined;\r\n return stub.getContent(ctx);\r\n }\r\n}","// src/core/apply-structure.ts\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport type {\r\n ScaffoldConfig,\r\n StructureEntry,\r\n FileEntry,\r\n DirEntry,\r\n HookContext,\r\n} from '../schema';\r\nimport { CacheManager } from './cache-manager';\r\nimport { HookRunner } from './hook-runner';\r\nimport {\r\n ensureDirSync,\r\n statSafeSync,\r\n toProjectRelativePath,\r\n toPosixPath,\r\n} from '../util/fs-utils';\r\nimport type { Logger } from '../util/logger';\r\nimport { defaultLogger } from '../util/logger';\r\n\r\nexport interface InteractiveDeleteParams {\r\n absolutePath: string;\r\n relativePath: string; // project-root relative, POSIX\r\n size: number;\r\n createdByStub?: string;\r\n groupName?: string;\r\n}\r\n\r\nexport interface ApplyOptions {\r\n config: ScaffoldConfig;\r\n\r\n /**\r\n * Global project root for this run.\r\n */\r\n projectRoot: string;\r\n\r\n /**\r\n * Absolute directory where this structure group should be applied.\r\n * For grouped mode, this is projectRoot + group.root.\r\n * For single mode, this will simply be projectRoot.\r\n */\r\n baseDir: string;\r\n\r\n /**\r\n * Which structure entries to apply (already resolved from txt or inline).\r\n */\r\n structure: StructureEntry[];\r\n\r\n cache: CacheManager;\r\n hooks: HookRunner;\r\n\r\n /**\r\n * Optional group metadata (only set for groups).\r\n */\r\n groupName?: string;\r\n groupRoot?: string;\r\n\r\n /**\r\n * Optional override for deletion threshold.\r\n * Falls back to config.sizePromptThreshold or internal default.\r\n */\r\n sizePromptThreshold?: number;\r\n\r\n /**\r\n * Optional interactive delete callback.\r\n * Should ask the user and return 'delete' or 'keep'.\r\n */\r\n interactiveDelete?: (\r\n params: InteractiveDeleteParams,\r\n ) => Promise<'delete' | 'keep'>;\r\n\r\n /**\r\n * Optional logger; defaults to defaultLogger.child('[apply]').\r\n */\r\n logger?: Logger;\r\n}\r\n\r\nexport async function applyStructure(opts: ApplyOptions): Promise<void> {\r\n const {\r\n config,\r\n projectRoot,\r\n baseDir,\r\n structure,\r\n cache,\r\n hooks,\r\n groupName,\r\n groupRoot,\r\n sizePromptThreshold,\r\n interactiveDelete,\r\n } = opts;\r\n\r\n const logger =\r\n opts.logger ?? defaultLogger.child(groupName ? `[apply:${groupName}]` : '[apply]');\r\n\r\n const desiredPaths = new Set<string>(); // project-root relative, POSIX\r\n\r\n const threshold = sizePromptThreshold ?? config.sizePromptThreshold ?? 128 * 1024;\r\n\r\n async function walk(entry: StructureEntry, inheritedStub?: string): Promise<void> {\r\n const effectiveStub = entry.stub ?? inheritedStub;\r\n if (entry.type === 'dir') {\r\n await handleDir(entry as DirEntry, effectiveStub);\r\n } else {\r\n await handleFile(entry as FileEntry, effectiveStub);\r\n }\r\n }\r\n\r\n async function handleDir(entry: DirEntry, inheritedStub?: string): Promise<void> {\r\n const relFromBase = entry.path.replace(/^[./]+/, '');\r\n const absDir = path.resolve(baseDir, relFromBase);\r\n const relFromRoot = toPosixPath(\r\n toProjectRelativePath(projectRoot, absDir),\r\n );\r\n\r\n desiredPaths.add(relFromRoot);\r\n\r\n ensureDirSync(absDir);\r\n\r\n const nextStub = entry.stub ?? inheritedStub;\r\n\r\n if (entry.children) {\r\n for (const child of entry.children) {\r\n // eslint-disable-next-line no-await-in-loop\r\n await walk(child, nextStub);\r\n }\r\n }\r\n }\r\n\r\n async function handleFile(entry: FileEntry, inheritedStub?: string): Promise<void> {\r\n const relFromBase = entry.path.replace(/^[./]+/, '');\r\n const absFile = path.resolve(baseDir, relFromBase);\r\n const relFromRoot = toPosixPath(\r\n toProjectRelativePath(projectRoot, absFile),\r\n );\r\n\r\n desiredPaths.add(relFromRoot);\r\n\r\n const stubName = entry.stub ?? inheritedStub;\r\n\r\n const ctx: HookContext = {\r\n projectRoot,\r\n targetPath: relFromRoot,\r\n absolutePath: absFile,\r\n isDirectory: false,\r\n stubName,\r\n };\r\n\r\n // If file already exists, do not overwrite; just ensure hooks\r\n if (fs.existsSync(absFile)) {\r\n return;\r\n }\r\n\r\n await hooks.runRegular('preCreateFile', ctx);\r\n\r\n const dir = path.dirname(absFile);\r\n ensureDirSync(dir);\r\n\r\n if (stubName) {\r\n await hooks.runStub('preStub', ctx);\r\n }\r\n\r\n let content = '';\r\n const stubContent = await hooks.renderStubContent(ctx);\r\n if (typeof stubContent === 'string') {\r\n content = stubContent;\r\n }\r\n\r\n fs.writeFileSync(absFile, content, 'utf8');\r\n const stats = fs.statSync(absFile);\r\n\r\n cache.set({\r\n path: relFromRoot,\r\n createdAt: new Date().toISOString(),\r\n sizeAtCreate: stats.size,\r\n createdByStub: stubName,\r\n groupName,\r\n groupRoot,\r\n });\r\n\r\n logger.info(`created ${relFromRoot}`);\r\n\r\n if (stubName) {\r\n await hooks.runStub('postStub', ctx);\r\n }\r\n\r\n await hooks.runRegular('postCreateFile', ctx);\r\n }\r\n\r\n // 1) Create/update from structure\r\n for (const entry of structure) {\r\n // eslint-disable-next-line no-await-in-loop\r\n await walk(entry);\r\n }\r\n\r\n // 2) Handle deletions: any cached path not in desiredPaths\r\n for (const cachedPath of cache.allPaths()) {\r\n if (desiredPaths.has(cachedPath)) continue;\r\n\r\n const abs = path.resolve(projectRoot, cachedPath);\r\n const stats = statSafeSync(abs);\r\n\r\n if (!stats) {\r\n cache.delete(cachedPath);\r\n continue;\r\n }\r\n\r\n // Only handle files here; dirs are not tracked in cache.\r\n if (!stats.isFile()) {\r\n cache.delete(cachedPath);\r\n continue;\r\n }\r\n\r\n const entry = cache.get(cachedPath);\r\n const ctx: HookContext = {\r\n projectRoot,\r\n targetPath: cachedPath,\r\n absolutePath: abs,\r\n isDirectory: false,\r\n stubName: entry?.createdByStub,\r\n };\r\n\r\n await hooks.runRegular('preDeleteFile', ctx);\r\n\r\n let shouldDelete = true;\r\n if (stats.size > threshold && interactiveDelete) {\r\n const res = await interactiveDelete({\r\n absolutePath: abs,\r\n relativePath: cachedPath,\r\n size: stats.size,\r\n createdByStub: entry?.createdByStub,\r\n groupName: entry?.groupName,\r\n });\r\n\r\n if (res === 'keep') {\r\n shouldDelete = false;\r\n cache.delete(cachedPath); // user takes ownership\r\n logger.info(`keeping ${cachedPath} (removed from cache)`);\r\n }\r\n }\r\n\r\n if (shouldDelete) {\r\n try {\r\n fs.unlinkSync(abs);\r\n logger.info(`deleted ${cachedPath}`);\r\n } catch (err) {\r\n logger.warn(`failed to delete ${cachedPath}`, err);\r\n }\r\n\r\n cache.delete(cachedPath);\r\n await hooks.runRegular('postDeleteFile', ctx);\r\n }\r\n }\r\n}","// src/core/scan-structure.ts\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport { minimatch } from 'minimatch';\r\n\r\nimport {\r\n ScanStructureOptions,\r\n ScanFromConfigOptions,\r\n StructureGroupConfig,\r\n ScaffoldConfig,\r\n} from '../schema';\r\nimport { toPosixPath, ensureDirSync } from '../util/fs-utils';\r\nimport { loadScaffoldConfig } from './config-loader';\r\nimport { defaultLogger } from '../util/logger';\r\n\r\nconst logger = defaultLogger.child('[scan]');\r\n\r\nconst DEFAULT_IGNORE: string[] = [\r\n 'node_modules/**',\r\n '.git/**',\r\n 'dist/**',\r\n 'build/**',\r\n '.turbo/**',\r\n '.next/**',\r\n 'coverage/**',\r\n];\r\n\r\n/**\r\n * Generate a structure.txt-style tree from an existing directory.\r\n *\r\n * Indenting:\r\n * - 2 spaces per level.\r\n * - Directories suffixed with \"/\".\r\n * - No stub/include/exclude annotations are guessed (plain tree).\r\n */\r\nexport function scanDirectoryToStructureText(\r\n rootDir: string,\r\n options: ScanStructureOptions = {},\r\n): string {\r\n const absRoot = path.resolve(rootDir);\r\n const lines: string[] = [];\r\n\r\n const ignorePatterns = options.ignore ?? DEFAULT_IGNORE;\r\n const maxDepth = options.maxDepth ?? Infinity;\r\n\r\n function isIgnored(absPath: string): boolean {\r\n const rel = toPosixPath(path.relative(absRoot, absPath));\r\n if (!rel || rel === '.') return false;\r\n return ignorePatterns.some((pattern) =>\r\n minimatch(rel, pattern, { dot: true }),\r\n );\r\n }\r\n\r\n function walk(currentAbs: string, depth: number) {\r\n if (depth > maxDepth) return;\r\n\r\n let dirents: fs.Dirent[];\r\n try {\r\n dirents = fs.readdirSync(currentAbs, { withFileTypes: true });\r\n } catch {\r\n return;\r\n }\r\n\r\n // Sort: directories first, then files, both alphabetically\r\n dirents.sort((a, b) => {\r\n if (a.isDirectory() && !b.isDirectory()) return -1;\r\n if (!a.isDirectory() && b.isDirectory()) return 1;\r\n return a.name.localeCompare(b.name);\r\n });\r\n\r\n for (const dirent of dirents) {\r\n const name = dirent.name;\r\n const absPath = path.join(currentAbs, name);\r\n\r\n if (isIgnored(absPath)) continue;\r\n\r\n const indent = ' '.repeat(depth);\r\n if (dirent.isDirectory()) {\r\n lines.push(`${indent}${name}/`);\r\n walk(absPath, depth + 1);\r\n } else if (dirent.isFile()) {\r\n lines.push(`${indent}${name}`);\r\n }\r\n // symlinks etc. are skipped for now\r\n }\r\n }\r\n\r\n walk(absRoot, 0);\r\n return lines.join('\\n');\r\n}\r\n\r\n/**\r\n * Result of scanning based on the scaffold config.\r\n *\r\n * You can use `structureFilePath` + `text` to write out group structure files.\r\n */\r\nexport interface ScanFromConfigResult {\r\n groupName: string;\r\n groupRoot: string;\r\n structureFileName: string;\r\n structureFilePath: string;\r\n text: string;\r\n}\r\n\r\n/**\r\n * Scan the project using the scaffold config and its groups.\r\n *\r\n * - If `config.groups` exists and is non-empty:\r\n * - scans each group's `root` (relative to projectRoot)\r\n * - produces text suitable for that group's structure file\r\n * - Otherwise:\r\n * - scans the single `projectRoot` and produces text for a single structure file.\r\n *\r\n * NOTE: This function does NOT write files; it just returns what should be written.\r\n * The CLI (or caller) decides whether/where to save.\r\n */\r\nexport async function scanProjectFromConfig(\r\n cwd: string,\r\n options: ScanFromConfigOptions = {},\r\n): Promise<ScanFromConfigResult[]> {\r\n const { config, scaffoldDir, projectRoot } = await loadScaffoldConfig(cwd, {\r\n scaffoldDir: options.scaffoldDir,\r\n });\r\n\r\n const ignorePatterns = options.ignore ?? DEFAULT_IGNORE;\r\n const maxDepth = options.maxDepth ?? Infinity;\r\n const onlyGroups = options.groups;\r\n\r\n const results: ScanFromConfigResult[] = [];\r\n\r\n function scanGroup(\r\n cfg: ScaffoldConfig,\r\n group: StructureGroupConfig,\r\n ): ScanFromConfigResult {\r\n const rootAbs = path.resolve(projectRoot, group.root);\r\n const text = scanDirectoryToStructureText(rootAbs, {\r\n ignore: ignorePatterns,\r\n maxDepth,\r\n });\r\n\r\n const structureFileName = group.structureFile ?? `${group.name}.txt`;\r\n const structureFilePath = path.join(scaffoldDir, structureFileName);\r\n\r\n return {\r\n groupName: group.name,\r\n groupRoot: group.root,\r\n structureFileName,\r\n structureFilePath,\r\n text,\r\n };\r\n }\r\n\r\n if (config.groups && config.groups.length > 0) {\r\n logger.debug(\r\n `Scanning project from config with ${config.groups.length} group(s).`,\r\n );\r\n\r\n for (const group of config.groups) {\r\n if (onlyGroups && !onlyGroups.includes(group.name)) {\r\n continue;\r\n }\r\n const result = scanGroup(config, group);\r\n results.push(result);\r\n }\r\n } else {\r\n // Single-root mode: scan the whole projectRoot\r\n logger.debug('Scanning project in single-root mode (no groups).');\r\n\r\n const text = scanDirectoryToStructureText(projectRoot, {\r\n ignore: ignorePatterns,\r\n maxDepth,\r\n });\r\n\r\n const structureFileName = config.structureFile ?? 'structure.txt';\r\n const structureFilePath = path.join(scaffoldDir, structureFileName);\r\n\r\n results.push({\r\n groupName: 'default',\r\n groupRoot: '.',\r\n structureFileName,\r\n structureFilePath,\r\n text,\r\n });\r\n }\r\n\r\n return results;\r\n}\r\n\r\n/**\r\n * Convenience helper: write scan results to their structure files.\r\n *\r\n * This will ensure the scaffold directory exists and overwrite existing\r\n * structure files.\r\n */\r\nexport async function writeScannedStructuresFromConfig(\r\n cwd: string,\r\n options: ScanFromConfigOptions = {},\r\n): Promise<void> {\r\n const { scaffoldDir } = await loadScaffoldConfig(cwd, {\r\n scaffoldDir: options.scaffoldDir,\r\n });\r\n\r\n ensureDirSync(scaffoldDir);\r\n\r\n const results = await scanProjectFromConfig(cwd, options);\r\n\r\n for (const result of results) {\r\n fs.writeFileSync(result.structureFilePath, result.text, 'utf8');\r\n logger.info(\r\n `Wrote structure for group \"${result.groupName}\" to ${result.structureFilePath}`,\r\n );\r\n }\r\n}\r\n\r\n\r\n\r\nexport interface EnsureStructuresResult {\r\n created: string[];\r\n existing: string[];\r\n}\r\n\r\n/**\r\n * Ensure all structure files declared in the config exist.\r\n *\r\n * - Grouped mode: one file per group (group.structureFile || `${group.name}.txt`)\r\n * - Single-root mode: config.structureFile || \"structure.txt\"\r\n *\r\n * Existing files are left untouched. Only missing files are created with\r\n * a small header comment.\r\n */\r\nexport async function ensureStructureFilesFromConfig(\r\n cwd: string,\r\n options: { scaffoldDirOverride?: string } = {},\r\n): Promise<EnsureStructuresResult> {\r\n const { config, scaffoldDir } = await loadScaffoldConfig(cwd, {\r\n scaffoldDir: options.scaffoldDirOverride,\r\n });\r\n\r\n ensureDirSync(scaffoldDir);\r\n\r\n const created: string[] = [];\r\n const existing: string[] = [];\r\n\r\n const seen = new Set<string>();\r\n\r\n const ensureFile = (fileName: string) => {\r\n if (!fileName) return;\r\n\r\n const filePath = path.join(scaffoldDir, fileName);\r\n const key = path.resolve(filePath);\r\n\r\n if (seen.has(key)) return;\r\n seen.add(key);\r\n\r\n if (fs.existsSync(filePath)) {\r\n existing.push(filePath);\r\n return;\r\n }\r\n\r\n const header =\r\n `# ${fileName}\\n` +\r\n `# Structure file for @timeax/scaffold\\n` +\r\n `# Define your desired folders/files here.\\n`;\r\n\r\n fs.writeFileSync(filePath, header, 'utf8');\r\n created.push(filePath);\r\n };\r\n\r\n if (config.groups && config.groups.length > 0) {\r\n for (const group of config.groups) {\r\n const fileName = group.structureFile ?? `${group.name}.txt`;\r\n ensureFile(fileName);\r\n }\r\n } else {\r\n const fileName = config.structureFile ?? 'structure.txt';\r\n ensureFile(fileName);\r\n }\r\n\r\n logger.debug(\r\n `ensureStructureFilesFromConfig: created=${created.length}, existing=${existing.length}`,\r\n );\r\n\r\n return { created, existing };\r\n}","// src/core/format.ts\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport {formatStructureText} from '../ast';\r\nimport type {ScaffoldConfig, FormatConfig} from '../schema';\r\nimport {SCAFFOLD_ROOT_DIR} from '..';\r\n\r\ninterface FormatFromConfigOptions {\r\n /**\r\n * If true, force formatting even if config.format?.enabled === false.\r\n * This is what `--format` will use.\r\n */\r\n force?: boolean;\r\n}\r\n\r\n/**\r\n * Return the list of structure files we expect for this config.\r\n * (mirrors your scan / structures logic: groups vs single-root).\r\n */\r\nexport function getStructureFilesFromConfig(\r\n projectRoot: string,\r\n scaffoldDir: string,\r\n config: ScaffoldConfig,\r\n): string[] {\r\n const baseDir = path.resolve(projectRoot, scaffoldDir || SCAFFOLD_ROOT_DIR);\r\n\r\n const files: string[] = [];\r\n\r\n if (config.groups && config.groups.length > 0) {\r\n for (const group of config.groups) {\r\n const structureFile =\r\n group.structureFile && group.structureFile.trim().length\r\n ? group.structureFile\r\n : `${group.name}.txt`;\r\n\r\n files.push(path.join(baseDir, structureFile));\r\n }\r\n } else {\r\n const structureFile = config.structureFile || 'structure.txt';\r\n files.push(path.join(baseDir, structureFile));\r\n }\r\n\r\n return files;\r\n}\r\n\r\n/**\r\n * Format all existing structure files according to config.format.\r\n */\r\nexport async function formatStructureFilesFromConfig(\r\n projectRoot: string,\r\n scaffoldDir: string,\r\n config: ScaffoldConfig,\r\n opts: FormatFromConfigOptions = {},\r\n): Promise<void> {\r\n const formatCfg: FormatConfig | undefined = config.format;\r\n const enabled = !!(formatCfg?.enabled || opts.force);\r\n\r\n if (!enabled) return;\r\n\r\n const files = getStructureFilesFromConfig(projectRoot, scaffoldDir, config);\r\n\r\n const indentStep =\r\n formatCfg?.indentStep ?? config.indentStep ?? 2;\r\n\r\n const mode = formatCfg?.mode ?? 'loose';\r\n const sortEntries = !!formatCfg?.sortEntries;\r\n\r\n for (const filePath of files) {\r\n let text: string;\r\n try {\r\n text = fs.readFileSync(filePath, 'utf8');\r\n } catch {\r\n // Missing file is fine; we don't create it here.\r\n continue;\r\n }\r\n\r\n const {text: formatted} = formatStructureText(text, {\r\n indentStep,\r\n mode,\r\n sortEntries,\r\n });\r\n\r\n if (formatted !== text) {\r\n fs.writeFileSync(filePath, formatted, 'utf8');\r\n }\r\n }\r\n}","// src/core/runner.ts\r\n\r\nimport path from 'path';\r\nimport {loadScaffoldConfig} from './config-loader';\r\nimport {\r\n resolveGroupStructure,\r\n resolveSingleStructure,\r\n} from './resolve-structure';\r\nimport {CacheManager} from './cache-manager';\r\nimport {HookRunner} from './hook-runner';\r\nimport {applyStructure, type InteractiveDeleteParams} from './apply-structure';\r\nimport type {Logger} from '../util/logger';\r\nimport {defaultLogger} from '../util/logger';\r\nimport {formatStructureFilesFromConfig} from \"./format\";\r\n\r\nexport interface RunOptions {\r\n /**\r\n * Optional interactive delete callback; if omitted, deletions\r\n * above the size threshold will be skipped (kept + removed from cache).\r\n */\r\n interactiveDelete?: (\r\n params: InteractiveDeleteParams,\r\n ) => Promise<'delete' | 'keep'>;\r\n\r\n /**\r\n * Optional logger override.\r\n */\r\n logger?: Logger;\r\n\r\n /**\r\n * Optional overrides (e.g. allow CLI to point at a different scaffold dir).\r\n */\r\n scaffoldDir?: string;\r\n configPath?: string;\r\n /**\r\n * If true, force formatting even if config.format?.enabled === false.\r\n * This is what `--format` will use.\r\n */\r\n format?: boolean;\r\n}\r\n\r\n/**\r\n * Run scaffold once for the current working directory.\r\n */\r\nexport async function runOnce(cwd: string, options: RunOptions = {}): Promise<void> {\r\n const logger = options.logger ?? defaultLogger.child('[runner]');\r\n const {config, scaffoldDir, projectRoot} = await loadScaffoldConfig(cwd, {\r\n scaffoldDir: options.scaffoldDir,\r\n configPath: options.configPath,\r\n });\r\n\r\n await formatStructureFilesFromConfig(projectRoot, scaffoldDir, config, {force: options.format})\r\n\r\n const cachePath = config.cacheFile ?? '.scaffold-cache.json';\r\n const cache = new CacheManager(projectRoot, cachePath);\r\n cache.load();\r\n\r\n const hooks = new HookRunner(config);\r\n\r\n // Grouped mode\r\n if (config.groups && config.groups.length > 0) {\r\n for (const group of config.groups) {\r\n const groupRootAbs = path.resolve(projectRoot, group.root);\r\n const structure = resolveGroupStructure(scaffoldDir, group);\r\n\r\n const groupLogger = logger.child(`[group:${group.name}]`);\r\n\r\n // eslint-disable-next-line no-await-in-loop\r\n await applyStructure({\r\n config,\r\n projectRoot,\r\n baseDir: groupRootAbs,\r\n structure,\r\n cache,\r\n hooks,\r\n groupName: group.name,\r\n groupRoot: group.root,\r\n interactiveDelete: options.interactiveDelete,\r\n logger: groupLogger,\r\n });\r\n }\r\n } else {\r\n // Single-root mode\r\n const structure = resolveSingleStructure(scaffoldDir, config);\r\n const baseLogger = logger.child('[group:default]');\r\n\r\n await applyStructure({\r\n config,\r\n projectRoot,\r\n baseDir: projectRoot,\r\n structure,\r\n cache,\r\n hooks,\r\n groupName: 'default',\r\n groupRoot: '.',\r\n interactiveDelete: options.interactiveDelete,\r\n logger: baseLogger,\r\n });\r\n }\r\n\r\n cache.save();\r\n}","// src/core/watcher.ts\r\n\r\nimport path from 'path';\r\nimport chokidar from 'chokidar';\r\nimport {runOnce, type RunOptions} from './runner';\r\nimport {defaultLogger, type Logger} from '../util/logger';\r\nimport {SCAFFOLD_ROOT_DIR} from '..';\r\n\r\nexport interface WatchOptions extends RunOptions {\r\n /**\r\n * Debounce delay in milliseconds between detected changes\r\n * and a scaffold re-run.\r\n *\r\n * Default: 150 ms\r\n */\r\n debounceMs?: number;\r\n\r\n /**\r\n * Optional logger; falls back to defaultLogger.child('[watch]').\r\n */\r\n logger?: Logger;\r\n}\r\n\r\n/**\r\n * Watch the scaffold directory and re-run scaffold on changes.\r\n *\r\n * This watches:\r\n * - .scaffold/config.* files\r\n * - .scaffold/*.txt / *.tss / *.stx files (structures)\r\n *\r\n * CLI can call this when `--watch` is enabled.\r\n * Any `format` options in RunOptions are passed straight through to `runOnce`,\r\n * so formatting from config / CLI is applied on each re-run.\r\n */\r\nexport function watchScaffold(cwd: string, options: WatchOptions = {}): void {\r\n const logger = options.logger ?? defaultLogger.child('[watch]');\r\n\r\n const scaffoldDir = options.scaffoldDir\r\n ? path.resolve(cwd, options.scaffoldDir)\r\n : path.resolve(cwd, SCAFFOLD_ROOT_DIR);\r\n\r\n const debounceMs = options.debounceMs ?? 150;\r\n\r\n logger.info(`Watching scaffold directory: ${scaffoldDir}`);\r\n\r\n let timer: NodeJS.Timeout | undefined;\r\n let running = false;\r\n let pending = false;\r\n\r\n async function run() {\r\n if (running) {\r\n pending = true;\r\n return;\r\n }\r\n running = true;\r\n try {\r\n logger.info('Change detected → running scaffold...');\r\n await runOnce(cwd, {\r\n ...options,\r\n // we already resolved scaffoldDir for watcher; pass it down\r\n scaffoldDir,\r\n });\r\n logger.info('Scaffold run completed.');\r\n } catch (err) {\r\n logger.error('Scaffold run failed:', err);\r\n } finally {\r\n running = false;\r\n if (pending) {\r\n pending = false;\r\n timer = setTimeout(run, debounceMs);\r\n }\r\n }\r\n }\r\n\r\n function scheduleRun() {\r\n if (timer) clearTimeout(timer);\r\n timer = setTimeout(run, debounceMs);\r\n }\r\n\r\n const watcher = chokidar.watch(\r\n [\r\n // config files (ts/js/etc.)\r\n path.join(scaffoldDir, 'config.*'),\r\n\r\n // structure files: plain txt + our custom extensions\r\n path.join(scaffoldDir, '*.txt'),\r\n path.join(scaffoldDir, '*.tss'),\r\n path.join(scaffoldDir, '*.stx'),\r\n ],\r\n {\r\n ignoreInitial: false,\r\n },\r\n );\r\n\r\n watcher\r\n .on('add', (filePath) => {\r\n logger.debug(`File added: ${filePath}`);\r\n scheduleRun();\r\n })\r\n .on('change', (filePath) => {\r\n logger.debug(`File changed: ${filePath}`);\r\n scheduleRun();\r\n })\r\n .on('unlink', (filePath) => {\r\n logger.debug(`File removed: ${filePath}`);\r\n scheduleRun();\r\n })\r\n .on('error', (error) => {\r\n logger.error('Watcher error:', error);\r\n });\r\n\r\n // Initial run\r\n scheduleRun();\r\n}","// src/core/init-scaffold.ts\r\n\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport {ensureDirSync} from '../util/fs-utils';\r\nimport {defaultLogger} from '../util/logger';\r\nimport {SCAFFOLD_ROOT_DIR} from '../schema';\r\n\r\nconst logger = defaultLogger.child('[init]');\r\n\r\nexport interface InitScaffoldOptions {\r\n /**\r\n * Path to the scaffold directory (relative to cwd).\r\n * Default: \".scaffold\"\r\n */\r\n scaffoldDir?: string;\r\n\r\n /**\r\n * Overwrite existing config/structure files if they already exist.\r\n */\r\n force?: boolean;\r\n\r\n /**\r\n * Name of the config file inside the scaffold directory.\r\n * Default: \"config.ts\"\r\n */\r\n configFileName?: string;\r\n\r\n /**\r\n * Name of the default structure file inside the scaffold directory\r\n * for single-root mode.\r\n * Default: \"structure.txt\"\r\n */\r\n structureFileName?: string;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Default config + structure templates\r\n// ---------------------------------------------------------------------------\r\n\r\nconst DEFAULT_CONFIG_TS = `import type { ScaffoldConfig } from '@timeax/scaffold';\r\n\r\nconst config: ScaffoldConfig = {\r\n // Root for resolving the .scaffold folder & this config file.\r\n // By default, this is the directory where you run \\`scaffold\\`.\r\n // Example:\r\n // root: '.', // .scaffold at <cwd>/.scaffold\r\n // root: 'tools', // .scaffold at <cwd>/tools/.scaffold\r\n // root: '.',\r\n\r\n // Base directory where structures are applied and files/folders are created.\r\n // This is resolved relative to \\`root\\` above. Defaults to the same as root.\r\n // Example:\r\n // base: '.', // apply to <root>\r\n // base: 'src', // apply to <root>/src\r\n // base: '..', // apply to parent of <root>\r\n // base: '.',\r\n\r\n // Number of spaces per indent level in structure files (default: 2).\r\n // This also informs the formatter when indenting entries.\r\n // indentStep: 2,\r\n\r\n // Cache file path, relative to base.\r\n // cacheFile: '.scaffold-cache.json',\r\n\r\n // Formatting options for structure files.\r\n // These are used by:\r\n // - \\`scaffold --format\\` (forces formatting before apply)\r\n // - \\`scaffold --watch\\` when \\`formatOnWatch\\` is true\r\n //\r\n // format: {\r\n // // Enable config-driven formatting in general.\r\n // // \\`scaffold --format\\` always forces formatting even if this is false.\r\n // enabled: true,\r\n //\r\n // // Override indent step specifically for formatting (falls back to\r\n // // top-level \\`indentStep\\` if omitted).\r\n // indentStep: 2,\r\n //\r\n // // AST mode:\r\n // // - 'loose' (default): tries to repair mild indentation issues.\r\n // // - 'strict': mostly cosmetic changes (trims trailing whitespace, etc.).\r\n // mode: 'loose',\r\n //\r\n // // Sort non-comment entries lexicographically within their parent block.\r\n // // Comments and blank lines keep their relative positions.\r\n // sortEntries: true,\r\n //\r\n // // When running \\`scaffold --watch\\`, format structure files on each\r\n // // detected change before applying scaffold.\r\n // formatOnWatch: true,\r\n // },\r\n\r\n // --- Single-structure mode (simple) ---\r\n // structureFile: 'structure.txt',\r\n\r\n // --- Grouped mode (uncomment and adjust) ---\r\n // groups: [\r\n // { name: 'app', root: 'app', structureFile: 'app.txt' },\r\n // { name: 'frontend', root: 'resources/js', structureFile: 'frontend.txt' },\r\n // ],\r\n\r\n hooks: {\r\n // preCreateFile: [],\r\n // postCreateFile: [],\r\n // preDeleteFile: [],\r\n // postDeleteFile: [],\r\n },\r\n\r\n stubs: {\r\n // Example:\r\n // page: {\r\n // name: 'page',\r\n // getContent: (ctx) =>\r\n // \\`export default function Page() { return <div>\\${ctx.targetPath}</div>; }\\`,\r\n // },\r\n }\r\n};\r\n\r\nexport default config;\r\n`;\r\n\r\nconst DEFAULT_STRUCTURE_TXT = `# ${SCAFFOLD_ROOT_DIR}/structure.txt\r\n# Example structure definition.\r\n# - Indent with 2 spaces per level (or your configured indentStep)\r\n# - Directories must end with \"/\"\r\n# - Files do not\r\n# - Lines starting with \"#\" are comments and ignored by parser\r\n# - Inline comments are allowed after \"#\" or \"//\" separated by whitespace\r\n#\r\n# The formatter (when enabled via config.format or --format) will:\r\n# - Normalize indentation based on indentStep\r\n# - Preserve blank lines and comments\r\n# - Keep inline comments attached to their entries\r\n#\r\n# Example:\r\n# src/\r\n# index.ts\r\n`;\r\n\r\n/**\r\n * Initialize the scaffold directory and basic config/structure files.\r\n *\r\n * - Creates the scaffold directory if it doesn't exist.\r\n * - Writes a default config.ts if missing (or if force = true).\r\n * - Writes a default structure.txt if missing (or if force = true).\r\n */\r\nexport async function initScaffold(\r\n cwd: string,\r\n options: InitScaffoldOptions = {},\r\n): Promise<{\r\n scaffoldDir: string;\r\n configPath: string;\r\n structurePath: string;\r\n created: { config: boolean; structure: boolean };\r\n}> {\r\n const scaffoldDirRel = options.scaffoldDir ?? SCAFFOLD_ROOT_DIR;\r\n const scaffoldDirAbs = path.resolve(cwd, scaffoldDirRel);\r\n const configFileName = options.configFileName ?? 'config.ts';\r\n const structureFileName = options.structureFileName ?? 'structure.txt';\r\n\r\n ensureDirSync(scaffoldDirAbs);\r\n\r\n const configPath = path.join(scaffoldDirAbs, configFileName);\r\n const structurePath = path.join(scaffoldDirAbs, structureFileName);\r\n\r\n let createdConfig = false;\r\n let createdStructure = false;\r\n\r\n // config.ts\r\n if (fs.existsSync(configPath) && !options.force) {\r\n logger.info(\r\n `Config already exists at ${configPath} (use --force to overwrite).`,\r\n );\r\n } else {\r\n fs.writeFileSync(configPath, DEFAULT_CONFIG_TS, 'utf8');\r\n createdConfig = true;\r\n logger.info(\r\n `${fs.existsSync(configPath) ? 'Overwrote' : 'Created'} config at ${configPath}`,\r\n );\r\n }\r\n\r\n // structure.txt\r\n if (fs.existsSync(structurePath) && !options.force) {\r\n logger.info(\r\n `Structure file already exists at ${structurePath} (use --force to overwrite).`,\r\n );\r\n } else {\r\n fs.writeFileSync(structurePath, DEFAULT_STRUCTURE_TXT, 'utf8');\r\n createdStructure = true;\r\n logger.info(\r\n `${fs.existsSync(structurePath) ? 'Overwrote' : 'Created'} structure file at ${structurePath}`,\r\n );\r\n }\r\n\r\n return {\r\n scaffoldDir: scaffoldDirAbs,\r\n configPath,\r\n structurePath,\r\n created: {\r\n config: createdConfig,\r\n structure: createdStructure,\r\n },\r\n };\r\n}","#!/usr/bin/env node\n// noinspection RequiredAttributes\n\nimport readline from \"readline\";\nimport path from \"path\";\nimport fs from \"fs\";\nimport { Command } from \"commander\";\nimport { runOnce, type RunOptions } from \"../core/runner\";\nimport { watchScaffold } from \"../core/watcher\";\nimport {\n ensureStructureFilesFromConfig,\n scanDirectoryToStructureText,\n writeScannedStructuresFromConfig,\n} from \"../core/scan-structure\";\nimport { initScaffold } from \"../core/init-scaffold\";\nimport { defaultLogger, type Logger } from \"../util/logger\";\nimport { ensureDirSync } from \"../util/fs-utils\";\nimport { SCAFFOLD_ROOT_DIR } from \"../schema\";\n\ninterface BaseCliOptions {\n config?: string;\n dir?: string;\n watch?: boolean;\n quiet?: boolean;\n debug?: boolean;\n}\n\ninterface ScanCliOptions {\n root?: string;\n out?: string;\n ignore?: string[];\n fromConfig?: boolean;\n groups?: string[];\n maxDepth?: number;\n}\n\ninterface InitCliOptions {\n force?: boolean;\n}\n\ninterface StructuresCliOptions {} // reserved for future options\n\n/**\n * Create a logger with the appropriate level from CLI flags.\n */\nfunction createCliLogger(opts: { quiet?: boolean; debug?: boolean }): Logger {\n if (opts.quiet) {\n defaultLogger.setLevel(\"silent\");\n } else if (opts.debug) {\n defaultLogger.setLevel(\"debug\");\n }\n return defaultLogger.child(\"[cli]\");\n}\n\nfunction askYesNo(question: string): Promise<\"delete\" | \"keep\"> {\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n rl.question(`${question} [y/N] `, (answer) => {\n rl.close();\n const val = answer.trim().toLowerCase();\n if (val === \"y\" || val === \"yes\") {\n resolve(\"delete\");\n } else {\n resolve(\"keep\");\n }\n });\n });\n}\n\nasync function handleRunCommand(cwd: string, baseOpts: BaseCliOptions) {\n const logger = createCliLogger(baseOpts);\n\n const configPath = baseOpts.config\n ? path.resolve(cwd, baseOpts.config)\n : undefined;\n\n // NOTE: scaffoldDir is optional – if omitted, runOnce/loadScaffoldConfig\n // will default to SCAFFOLD_ROOT_DIR.\n const scaffoldDir = baseOpts.dir\n ? path.resolve(cwd, baseOpts.dir)\n : undefined;\n\n const resolvedScaffoldDir =\n scaffoldDir ?? path.resolve(cwd, SCAFFOLD_ROOT_DIR);\n\n logger.debug(\n `Starting scaffold (cwd=${cwd}, config=${configPath ?? \"auto\"}, dir=${resolvedScaffoldDir}, watch=${baseOpts.watch ? \"yes\" : \"no\"})`,\n );\n\n const runnerOptions: RunOptions = {\n configPath,\n scaffoldDir,\n logger,\n interactiveDelete: async ({\n relativePath,\n size,\n createdByStub,\n groupName,\n }) => {\n const sizeKb = (size / 1024).toFixed(1);\n const stubInfo = createdByStub ? ` (stub: ${createdByStub})` : \"\";\n const groupInfo = groupName ? ` [group: ${groupName}]` : \"\";\n const question = `File \"${relativePath}\"${groupInfo} is ~${sizeKb}KB and no longer in structure${stubInfo}. Delete it?`;\n\n return askYesNo(question);\n },\n };\n\n if (baseOpts.watch) {\n // Watch mode – this will not return\n watchScaffold(cwd, runnerOptions);\n } else {\n await runOnce(cwd, runnerOptions);\n }\n}\n\nasync function handleScanCommand(\n cwd: string,\n scanOpts: ScanCliOptions,\n baseOpts: BaseCliOptions,\n) {\n const logger = createCliLogger(baseOpts);\n\n const useConfigMode =\n scanOpts.fromConfig || (!scanOpts.root && !scanOpts.out);\n\n if (useConfigMode) {\n logger.info(\"Scanning project using scaffold config/groups...\");\n await writeScannedStructuresFromConfig(cwd, {\n ignore: scanOpts.ignore,\n groups: scanOpts.groups,\n scaffoldDir: baseOpts.dir,\n maxDepth: scanOpts.maxDepth\n });\n return;\n }\n\n // Manual single-root mode\n const rootDir = path.resolve(cwd, scanOpts.root ?? \".\");\n const ignore = scanOpts.ignore ?? [];\n\n logger.info(`Scanning directory for structure: ${rootDir}`);\n const text = scanDirectoryToStructureText(rootDir, {\n ignore,\n });\n\n if (scanOpts.out) {\n const outPath = path.resolve(cwd, scanOpts.out);\n const dir = path.dirname(outPath);\n ensureDirSync(dir);\n fs.writeFileSync(outPath, text, \"utf8\");\n logger.info(`Wrote structure to ${outPath}`);\n } else {\n process.stdout.write(text + \"\\n\");\n }\n}\n\nasync function handleInitCommand(\n cwd: string,\n initOpts: InitCliOptions,\n baseOpts: BaseCliOptions,\n) {\n const logger = createCliLogger(baseOpts);\n\n const scaffoldDirRel = baseOpts.dir ?? SCAFFOLD_ROOT_DIR;\n\n logger.info(`Initializing scaffold directory at \"${scaffoldDirRel}\"...`);\n\n const result = await initScaffold(cwd, {\n scaffoldDir: scaffoldDirRel,\n force: initOpts.force,\n });\n\n logger.info(\n `Done. Config: ${result.configPath}, Structure: ${result.structurePath}`,\n );\n}\n\nasync function handleStructuresCommand(cwd: string, baseOpts: BaseCliOptions) {\n const logger = createCliLogger(baseOpts);\n\n logger.info(\"Ensuring structure files declared in config exist...\");\n\n const { created, existing } = await ensureStructureFilesFromConfig(cwd, {\n scaffoldDirOverride: baseOpts.dir,\n });\n\n if (created.length === 0) {\n logger.info(\"All structure files already exist. Nothing to do.\");\n } else {\n for (const filePath of created) {\n logger.info(`Created structure file: ${filePath}`);\n }\n }\n\n existing.forEach((p) => logger.debug(`Structure file already exists: ${p}`));\n}\n\nasync function main() {\n const cwd = process.cwd();\n\n const program = new Command();\n\n program\n .name(\"scaffold\")\n .description(\"@timeax/scaffold – structure-based project scaffolding\")\n // global-ish options used by base + scan + init + structures\n .option(\"-c, --config <path>\", \"Path to scaffold config file\")\n .option(\n \"-d, --dir <path>\",\n `Path to scaffold directory (default: ./${SCAFFOLD_ROOT_DIR})`,\n )\n .option(\"-w, --watch\", \"Watch scaffold directory for changes\")\n .option(\"--quiet\", \"Silence logs\")\n .option(\"--debug\", \"Enable debug logging\");\n\n // scan subcommand\n program\n .command(\"scan\")\n .description(\n \"Generate structure.txt-style output (config-aware by default, or manual root/out)\",\n )\n .option(\n \"--from-config\",\n `Scan based on scaffold config/groups and write structure files into ${SCAFFOLD_ROOT_DIR}/ (default if no root/out specified)`,\n )\n .option(\"-r, --root <path>\", \"Root directory to scan (manual mode)\")\n .option(\"-o, --out <path>\", \"Output file path (manual mode)\")\n .option(\"-d, --depth <number>\", \"Max directory depth to scan (default: infinity, 0 = only scan root dir\")\n .option(\n \"--ignore <patterns...>\",\n \"Additional glob patterns to ignore (relative to root)\",\n )\n .option(\n \"--groups <names...>\",\n \"Limit config-based scanning to specific groups (by name)\",\n )\n .action(async (scanOpts: ScanCliOptions, cmd: Command) => {\n const baseOpts = cmd.parent?.opts<BaseCliOptions>() ?? {};\n await handleScanCommand(cwd, scanOpts, baseOpts);\n });\n\n // init subcommand\n program\n .command(\"init\")\n .description(\n `Initialize ${SCAFFOLD_ROOT_DIR} folder and config/structure files`,\n )\n .option(\n \"--force\",\n \"Overwrite existing config/structure files if they already exist\",\n )\n .action(async (initOpts: InitCliOptions, cmd: Command) => {\n const baseOpts = cmd.parent?.opts<BaseCliOptions>() ?? {};\n await handleInitCommand(cwd, initOpts, baseOpts);\n });\n\n // structures subcommand\n program\n .command(\"structures\")\n .description(\n \"Create missing structure files specified in the config (does not overwrite existing files)\",\n )\n .action(async (_opts: StructuresCliOptions, cmd: Command) => {\n const baseOpts = cmd.parent?.opts<BaseCliOptions>() ?? {};\n await handleStructuresCommand(cwd, baseOpts);\n });\n\n // Base command: run scaffold once or in watch mode\n program.action(async (opts: BaseCliOptions) => {\n await handleRunCommand(cwd, opts);\n });\n\n await program.parseAsync(process.argv);\n}\n\n// Run and handle errors\nmain().catch((err) => {\n defaultLogger.error(err);\n process.exit(1);\n});\n"]}
|