@raftlabs/raftstack 1.3.0 → 1.4.0
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/README.md +52 -12
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -40,6 +40,54 @@ The wizard will:
|
|
|
40
40
|
4. Set up CODEOWNERS for automatic PR reviewers
|
|
41
41
|
5. Generate all configuration files
|
|
42
42
|
|
|
43
|
+
## Getting Started
|
|
44
|
+
|
|
45
|
+
After installing RaftStack in your project, follow these steps:
|
|
46
|
+
|
|
47
|
+
### 1. Initialize RaftStack
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Run the interactive setup wizard
|
|
51
|
+
pnpm dlx @raftlabs/raftstack init
|
|
52
|
+
# or
|
|
53
|
+
npx @raftlabs/raftstack init
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 2. Initialize Claude Code (Optional)
|
|
57
|
+
|
|
58
|
+
If you use [Claude Code](https://claude.ai/code), initialize it to enable the bundled AI development skills:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
claude /init
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
This creates a `CLAUDE.md` file and enables the [Claude Code Skills](#claude-code-skills) that were copied to `.claude/skills/`.
|
|
65
|
+
|
|
66
|
+
### 3. Clean Up Before Committing
|
|
67
|
+
|
|
68
|
+
RaftStack creates `.backup` files for any existing configs it modifies. Remove these before your first commit:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Find and review backup files
|
|
72
|
+
find . -name "*.backup" -type f
|
|
73
|
+
|
|
74
|
+
# Remove backup files after reviewing
|
|
75
|
+
find . -name "*.backup" -type f -delete
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 4. Install Dependencies and Commit
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Install new dependencies added by RaftStack
|
|
82
|
+
pnpm install # or npm install / yarn
|
|
83
|
+
|
|
84
|
+
# Stage all changes
|
|
85
|
+
git add .
|
|
86
|
+
|
|
87
|
+
# Use the interactive commit wizard
|
|
88
|
+
pnpm commit
|
|
89
|
+
```
|
|
90
|
+
|
|
43
91
|
## What Gets Generated
|
|
44
92
|
|
|
45
93
|
### Git Hooks (via Husky)
|
|
@@ -139,19 +187,11 @@ Use during pilot rollout or ongoing maintenance to track team adoption.
|
|
|
139
187
|
|
|
140
188
|
## After Setup
|
|
141
189
|
|
|
142
|
-
|
|
143
|
-
```bash
|
|
144
|
-
pnpm install
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
2. **Make commits using the interactive wizard:**
|
|
148
|
-
```bash
|
|
149
|
-
pnpm commit
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
3. **Review the generated configuration** and customize as needed.
|
|
190
|
+
See [Getting Started](#getting-started) for the complete setup workflow. Once configured:
|
|
153
191
|
|
|
154
|
-
|
|
192
|
+
- **Make commits** using `pnpm commit` for the interactive wizard
|
|
193
|
+
- **Set up branch protection** on GitHub (see `.github/BRANCH_PROTECTION_SETUP.md`)
|
|
194
|
+
- **Review generated configs** and customize as needed
|
|
155
195
|
|
|
156
196
|
## Commit Convention
|
|
157
197
|
|
package/dist/cli.js
CHANGED
|
@@ -2426,7 +2426,7 @@ ${pc4.bold("Branches")}
|
|
|
2426
2426
|
// package.json
|
|
2427
2427
|
var package_default = {
|
|
2428
2428
|
name: "@raftlabs/raftstack",
|
|
2429
|
-
version: "1.
|
|
2429
|
+
version: "1.4.0",
|
|
2430
2430
|
description: "CLI tool for setting up Git hooks, commit conventions, and GitHub integration",
|
|
2431
2431
|
type: "module",
|
|
2432
2432
|
main: "./dist/index.js",
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/commands/init.ts","../src/prompts/index.ts","../src/utils/detect-project.ts","../src/utils/detect-package-manager.ts","../src/generators/husky.ts","../src/utils/file-system.ts","../src/generators/commitlint.ts","../src/generators/cz-git.ts","../src/generators/lint-staged.ts","../src/utils/package-json.ts","../src/generators/branch-validation.ts","../src/generators/pr-template.ts","../src/generators/github-workflows.ts","../src/generators/codeowners.ts","../src/generators/ai-review.ts","../src/generators/branch-protection.ts","../src/generators/contributing.ts","../src/generators/prettier.ts","../src/generators/claude-skills.ts","../src/generators/eslint.ts","../src/generators/quick-reference.ts","../src/utils/git.ts","../src/commands/setup-protection.ts","../src/commands/metrics.ts","../package.json"],"sourcesContent":["import { Command } from \"commander\";\nimport { runInit } from \"./commands/init.js\";\nimport { runSetupProtection } from \"./commands/setup-protection.js\";\nimport { runMetrics } from \"./commands/metrics.js\";\nimport pkg from \"../package.json\" assert { type: \"json\" };\n\nconst program = new Command();\n\nprogram\n .name(\"raftstack\")\n .description(\n \"CLI tool for setting up Git hooks, commit conventions, and GitHub integration\"\n )\n .version(pkg.version);\n\nprogram\n .command(\"init\")\n .description(\"Initialize RaftStack configuration in your project\")\n .action(async () => {\n await runInit(process.cwd());\n });\n\nprogram\n .command(\"setup-protection\")\n .description(\"Configure GitHub branch protection rules via API\")\n .action(async () => {\n await runSetupProtection(process.cwd());\n });\n\nprogram\n .command(\"metrics\")\n .description(\"Analyze repository compliance with RaftStack conventions\")\n .action(async () => {\n await runMetrics(process.cwd());\n });\n\nprogram.parse();\n","import * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport type { GeneratorResult, RaftStackConfig } from \"../types/config.js\";\nimport { collectConfig } from \"../prompts/index.js\";\nimport {\n generateHuskyHooks,\n generateCommitlint,\n generateCzGit,\n generateLintStaged,\n generateBranchValidation,\n generatePRTemplate,\n generateGitHubWorkflows,\n generateCodeowners,\n generateAIReview,\n generateBranchProtectionDocs,\n generateContributing,\n generatePrettier,\n generateClaudeSkills,\n generateQuickReference,\n} from \"../generators/index.js\";\nimport {\n mergeDevDependencies,\n mergeScripts,\n readPackageJson,\n writePackageJson,\n RAFTSTACK_DEV_DEPENDENCIES,\n} from \"../utils/package-json.js\";\nimport { isGitRepo } from \"../utils/git.js\";\n\n/**\n * Merge generator results\n */\nfunction mergeResults(results: GeneratorResult[]): GeneratorResult {\n return results.reduce(\n (acc, result) => ({\n created: [...acc.created, ...result.created],\n modified: [...acc.modified, ...result.modified],\n skipped: [...acc.skipped, ...result.skipped],\n backedUp: [...acc.backedUp, ...result.backedUp],\n }),\n { created: [], modified: [], skipped: [], backedUp: [] }\n );\n}\n\n/**\n * Update package.json with required scripts and dependencies\n */\nasync function updateProjectPackageJson(\n targetDir: string,\n _config: RaftStackConfig\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n try {\n let pkg = await readPackageJson(targetDir);\n\n // Add scripts\n const scripts: Record<string, string> = {\n prepare: \"husky\",\n commit: \"czg\",\n };\n\n pkg = mergeScripts(pkg, scripts, false);\n\n // Add dev dependencies\n pkg = mergeDevDependencies(pkg, RAFTSTACK_DEV_DEPENDENCIES);\n\n await writePackageJson(pkg, targetDir);\n result.modified.push(\"package.json\");\n } catch (error) {\n result.skipped.push(\"package.json (error updating)\");\n }\n\n return result;\n}\n\n/**\n * Run the init command\n */\nexport async function runInit(targetDir: string = process.cwd()): Promise<void> {\n // Check if this is a git repository\n const isRepo = await isGitRepo(targetDir);\n if (!isRepo) {\n p.log.warn(\n pc.yellow(\n \"This directory is not a git repository. Some features may not work correctly.\"\n )\n );\n const proceed = await p.confirm({\n message: \"Continue anyway?\",\n initialValue: false,\n });\n\n if (p.isCancel(proceed) || !proceed) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n }\n\n // Collect configuration from user\n const config = await collectConfig(targetDir);\n\n if (!config) {\n return;\n }\n\n // Generate files with progress spinner\n const spinner = p.spinner();\n spinner.start(\"Generating configuration files...\");\n\n const results: GeneratorResult[] = [];\n\n try {\n // Core Git hooks and commit conventions\n results.push(\n await generateHuskyHooks(targetDir, config.projectType, config.packageManager)\n );\n results.push(await generateCommitlint(targetDir, config.asanaBaseUrl));\n results.push(await generateCzGit(targetDir, config.asanaBaseUrl));\n results.push(\n await generateLintStaged(\n targetDir,\n config.projectType,\n config.usesEslint,\n config.usesPrettier,\n config.usesTypeScript\n )\n );\n results.push(await generateBranchValidation(targetDir));\n\n // Prettier (only if not already configured)\n if (!config.usesPrettier) {\n results.push(await generatePrettier(targetDir));\n }\n\n // GitHub integration\n results.push(await generatePRTemplate(targetDir, !!config.asanaBaseUrl));\n results.push(\n await generateGitHubWorkflows(\n targetDir,\n config.projectType,\n config.usesTypeScript,\n config.usesEslint,\n config.packageManager\n )\n );\n results.push(await generateCodeowners(targetDir, config.codeowners));\n results.push(await generateAIReview(targetDir, config.aiReviewTool));\n results.push(await generateBranchProtectionDocs(targetDir));\n\n // Documentation\n results.push(\n await generateContributing(targetDir, !!config.asanaBaseUrl, config.packageManager)\n );\n results.push(await generateQuickReference(targetDir, config.packageManager));\n\n // Claude Code skills for AI-assisted development\n results.push(await generateClaudeSkills(targetDir));\n\n // Update package.json\n results.push(await updateProjectPackageJson(targetDir, config));\n\n spinner.stop(\"Configuration files generated!\");\n } catch (error) {\n spinner.stop(\"Error generating files\");\n p.log.error(\n pc.red(\n `Error: ${error instanceof Error ? error.message : \"Unknown error\"}`\n )\n );\n process.exit(1);\n }\n\n // Merge all results\n const finalResult = mergeResults(results);\n\n // Show summary\n console.log();\n\n if (finalResult.created.length > 0) {\n p.log.success(pc.green(\"Created files:\"));\n for (const file of finalResult.created) {\n console.log(` ${pc.dim(\"+\")} ${file}`);\n }\n }\n\n if (finalResult.modified.length > 0) {\n console.log();\n p.log.info(pc.blue(\"Modified files:\"));\n for (const file of finalResult.modified) {\n console.log(` ${pc.dim(\"~\")} ${file}`);\n }\n }\n\n if (finalResult.skipped.length > 0) {\n console.log();\n p.log.warn(pc.yellow(\"Skipped (already exist):\"));\n for (const file of finalResult.skipped) {\n console.log(` ${pc.dim(\"-\")} ${file}`);\n }\n }\n\n if (finalResult.backedUp.length > 0) {\n console.log();\n p.log.info(pc.dim(\"Backed up files:\"));\n for (const file of finalResult.backedUp) {\n console.log(` ${pc.dim(\"→\")} ${file}`);\n }\n }\n\n // Show next steps\n console.log();\n p.note(\n [\n `${pc.cyan(\"1.\")} Run ${pc.yellow(config.packageManager.install)} to install dependencies`,\n `${pc.cyan(\"2.\")} Review the generated configuration files`,\n `${pc.cyan(\"3.\")} Use ${pc.yellow(`${config.packageManager.run} commit`)} for interactive commits`,\n `${pc.cyan(\"4.\")} Set up branch protection rules (see .github/BRANCH_PROTECTION_SETUP.md)`,\n ].join(\"\\n\"),\n \"Next Steps\"\n );\n\n p.outro(pc.green(\"RaftStack setup complete! Happy coding! 🚀\"));\n}\n","import * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport type {\n AIReviewTool,\n DetectionResult,\n PackageManager,\n PackageManagerInfo,\n ProjectType,\n RaftStackConfig,\n} from \"../types/config.js\";\nimport {\n detectProjectType,\n getProjectTypeDescription,\n hasTypeScript,\n hasEslint,\n hasPrettier,\n detectPackageManager,\n getPackageManagerInfo,\n getPackageManagerDescription,\n} from \"../utils/detect-project.js\";\n\n/**\n * Show welcome banner\n */\nexport function showWelcome(): void {\n console.log();\n p.intro(pc.bgCyan(pc.black(\" RaftStack \")));\n console.log(\n pc.dim(\" Setting up Git hooks, commit conventions, and GitHub integration\\n\")\n );\n}\n\n/**\n * Prompt for project type confirmation\n */\nexport async function promptProjectType(\n detection: DetectionResult\n): Promise<ProjectType> {\n const description = getProjectTypeDescription(detection.type);\n const confidenceText =\n detection.confidence === \"high\"\n ? pc.green(\"high confidence\")\n : detection.confidence === \"medium\"\n ? pc.yellow(\"medium confidence\")\n : pc.red(\"low confidence\");\n\n const confirmed = await p.confirm({\n message: `Detected ${pc.cyan(description)} (${confidenceText}). Is this correct?`,\n initialValue: true,\n });\n\n if (p.isCancel(confirmed)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n if (confirmed) {\n return detection.type;\n }\n\n const selected = await p.select({\n message: \"Select your project type:\",\n options: [\n { value: \"nx\", label: \"NX Monorepo\" },\n { value: \"turbo\", label: \"Turborepo\" },\n { value: \"pnpm-workspace\", label: \"pnpm Workspace\" },\n { value: \"single\", label: \"Single Package\" },\n ],\n });\n\n if (p.isCancel(selected)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n return selected as ProjectType;\n}\n\n/**\n * Prompt for Asana configuration\n */\nexport async function promptAsanaConfig(): Promise<string | undefined> {\n const useAsana = await p.confirm({\n message: \"Do you want to link commits to Asana tasks?\",\n initialValue: true,\n });\n\n if (p.isCancel(useAsana)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n if (!useAsana) {\n return undefined;\n }\n\n const baseUrl = await p.text({\n message: \"Enter your Asana workspace URL:\",\n placeholder: \"https://app.asana.com/0/workspace-id\",\n validate: (value) => {\n if (!value) return \"URL is required\";\n if (!value.startsWith(\"https://app.asana.com/\")) {\n return \"URL must start with https://app.asana.com/\";\n }\n return undefined;\n },\n });\n\n if (p.isCancel(baseUrl)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n return baseUrl;\n}\n\n/**\n * Prompt for AI review tool selection\n */\nexport async function promptAIReview(): Promise<AIReviewTool> {\n const selected = await p.select({\n message: \"Select an AI code review tool (optional):\",\n options: [\n {\n value: \"none\",\n label: \"None\",\n hint: \"Skip AI review setup\",\n },\n {\n value: \"coderabbit\",\n label: \"CodeRabbit\",\n hint: \"AI-powered code review\",\n },\n {\n value: \"copilot\",\n label: \"GitHub Copilot\",\n hint: \"GitHub's AI code review\",\n },\n ],\n });\n\n if (p.isCancel(selected)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n return selected as AIReviewTool;\n}\n\n/**\n * Prompt for CODEOWNERS\n */\nexport async function promptCodeowners(): Promise<string[]> {\n const addOwners = await p.confirm({\n message: \"Do you want to set up CODEOWNERS for automatic PR reviewers?\",\n initialValue: true,\n });\n\n if (p.isCancel(addOwners)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n if (!addOwners) {\n return [];\n }\n\n const owners = await p.text({\n message: \"Enter GitHub usernames (comma-separated):\",\n placeholder: \"@username1, @username2\",\n validate: (value) => {\n if (!value.trim()) return \"At least one username is required\";\n return undefined;\n },\n });\n\n if (p.isCancel(owners)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n return owners\n .split(\",\")\n .map((u) => u.trim())\n .filter(Boolean)\n .map((u) => (u.startsWith(\"@\") ? u : `@${u}`));\n}\n\n/**\n * Prompt for package manager selection\n */\nexport async function promptPackageManager(\n targetDir: string\n): Promise<PackageManagerInfo> {\n // Try to auto-detect from lockfiles\n const detected = detectPackageManager(targetDir);\n\n if (detected) {\n const description = getPackageManagerDescription(detected);\n p.log.info(`Detected ${pc.cyan(description)} from lockfile`);\n return detected;\n }\n\n // No lockfile found - prompt user to select\n p.log.warn(\"No package manager lockfile detected\");\n\n const selected = await p.select({\n message: \"Select your package manager:\",\n options: [\n {\n value: \"npm\",\n label: \"npm\",\n hint: \"Node Package Manager (default)\",\n },\n {\n value: \"pnpm\",\n label: \"pnpm\",\n hint: \"Performant npm\",\n },\n {\n value: \"yarn\",\n label: \"Yarn Classic (1.x)\",\n hint: \"Classic Yarn\",\n },\n {\n value: \"yarn-berry\",\n label: \"Yarn Berry (2+)\",\n hint: \"Modern Yarn\",\n },\n ],\n });\n\n if (p.isCancel(selected)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n return getPackageManagerInfo(selected as PackageManager);\n}\n\n/**\n * Show summary before generating files\n */\nexport async function promptConfirmation(\n config: RaftStackConfig\n): Promise<boolean> {\n console.log();\n p.note(\n [\n `${pc.cyan(\"Project Type:\")} ${getProjectTypeDescription(config.projectType)}`,\n `${pc.cyan(\"Package Manager:\")} ${getPackageManagerDescription(config.packageManager)}`,\n `${pc.cyan(\"TypeScript:\")} ${config.usesTypeScript ? \"Yes\" : \"No\"}`,\n `${pc.cyan(\"ESLint:\")} ${config.usesEslint ? \"Yes\" : \"No\"}`,\n `${pc.cyan(\"Prettier:\")} ${config.usesPrettier ? \"Yes\" : \"No\"}`,\n `${pc.cyan(\"Asana Integration:\")} ${config.asanaBaseUrl ? \"Yes\" : \"No\"}`,\n `${pc.cyan(\"AI Review:\")} ${config.aiReviewTool === \"none\" ? \"None\" : config.aiReviewTool}`,\n `${pc.cyan(\"CODEOWNERS:\")} ${config.codeowners.length > 0 ? config.codeowners.join(\", \") : \"None\"}`,\n ].join(\"\\n\"),\n \"Configuration Summary\"\n );\n\n const confirmed = await p.confirm({\n message: \"Generate configuration files?\",\n initialValue: true,\n });\n\n if (p.isCancel(confirmed)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n return confirmed;\n}\n\n/**\n * Run full prompt flow and collect configuration\n */\nexport async function collectConfig(\n targetDir: string = process.cwd()\n): Promise<RaftStackConfig | null> {\n showWelcome();\n\n // Detect project type\n const detection = await detectProjectType(targetDir);\n const projectType = await promptProjectType(detection);\n\n // Detect package manager\n const packageManager = await promptPackageManager(targetDir);\n\n // Detect existing tooling\n const usesTypeScript = await hasTypeScript(targetDir);\n const usesEslint = await hasEslint(targetDir);\n const usesPrettier = await hasPrettier(targetDir);\n\n // Collect user preferences\n const asanaBaseUrl = await promptAsanaConfig();\n const aiReviewTool = await promptAIReview();\n const codeowners = await promptCodeowners();\n\n const config: RaftStackConfig = {\n projectType,\n packageManager,\n asanaBaseUrl,\n aiReviewTool,\n codeowners,\n usesTypeScript,\n usesEslint,\n usesPrettier,\n };\n\n // Confirm before proceeding\n const confirmed = await promptConfirmation(config);\n\n if (!confirmed) {\n p.cancel(\"Setup cancelled.\");\n return null;\n }\n\n return config;\n}\n","import { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { DetectionResult, ProjectType } from \"../types/config.js\";\n\ninterface IndicatorCheck {\n file: string;\n type: ProjectType;\n confidence: \"high\" | \"medium\";\n}\n\nconst INDICATORS: IndicatorCheck[] = [\n { file: \"nx.json\", type: \"nx\", confidence: \"high\" },\n { file: \"turbo.json\", type: \"turbo\", confidence: \"high\" },\n { file: \"pnpm-workspace.yaml\", type: \"pnpm-workspace\", confidence: \"high\" },\n { file: \"lerna.json\", type: \"pnpm-workspace\", confidence: \"medium\" },\n];\n\n/**\n * Detect the project type based on configuration files\n */\nexport async function detectProjectType(\n targetDir: string = process.cwd()\n): Promise<DetectionResult> {\n const foundIndicators: string[] = [];\n let detectedType: ProjectType = \"single\";\n let confidence: \"high\" | \"medium\" | \"low\" = \"low\";\n\n for (const indicator of INDICATORS) {\n const filePath = join(targetDir, indicator.file);\n if (existsSync(filePath)) {\n foundIndicators.push(indicator.file);\n\n // First match with highest confidence wins\n if (\n confidence === \"low\" ||\n (confidence === \"medium\" && indicator.confidence === \"high\")\n ) {\n detectedType = indicator.type;\n confidence = indicator.confidence;\n }\n }\n }\n\n // If we found indicators but couldn't determine type, it's still better than nothing\n if (foundIndicators.length > 0 && confidence === \"low\") {\n confidence = \"medium\";\n }\n\n return {\n type: detectedType,\n confidence,\n indicators: foundIndicators,\n };\n}\n\n/**\n * Check if project uses TypeScript\n */\nexport async function hasTypeScript(\n targetDir: string = process.cwd()\n): Promise<boolean> {\n const tsConfigPath = join(targetDir, \"tsconfig.json\");\n return existsSync(tsConfigPath);\n}\n\n/**\n * Check if project uses ESLint\n */\nexport async function hasEslint(\n targetDir: string = process.cwd()\n): Promise<boolean> {\n const eslintFiles = [\n \".eslintrc\",\n \".eslintrc.js\",\n \".eslintrc.cjs\",\n \".eslintrc.json\",\n \".eslintrc.yaml\",\n \".eslintrc.yml\",\n \"eslint.config.js\",\n \"eslint.config.mjs\",\n \"eslint.config.cjs\",\n ];\n\n for (const file of eslintFiles) {\n if (existsSync(join(targetDir, file))) {\n return true;\n }\n }\n\n // Also check package.json for eslintConfig\n try {\n const pkgPath = join(targetDir, \"package.json\");\n if (existsSync(pkgPath)) {\n const content = await readFile(pkgPath, \"utf-8\");\n const pkg = JSON.parse(content);\n if (pkg.eslintConfig) {\n return true;\n }\n }\n } catch {\n // Ignore parse errors\n }\n\n return false;\n}\n\n/**\n * Check if project uses Prettier\n */\nexport async function hasPrettier(\n targetDir: string = process.cwd()\n): Promise<boolean> {\n const prettierFiles = [\n \".prettierrc\",\n \".prettierrc.js\",\n \".prettierrc.cjs\",\n \".prettierrc.json\",\n \".prettierrc.yaml\",\n \".prettierrc.yml\",\n \".prettierrc.toml\",\n \"prettier.config.js\",\n \"prettier.config.cjs\",\n \"prettier.config.mjs\",\n ];\n\n for (const file of prettierFiles) {\n if (existsSync(join(targetDir, file))) {\n return true;\n }\n }\n\n // Also check package.json for prettier config\n try {\n const pkgPath = join(targetDir, \"package.json\");\n if (existsSync(pkgPath)) {\n const content = await readFile(pkgPath, \"utf-8\");\n const pkg = JSON.parse(content);\n if (pkg.prettier) {\n return true;\n }\n }\n } catch {\n // Ignore parse errors\n }\n\n return false;\n}\n\n/**\n * Check if project uses React\n */\nexport async function hasReact(\n targetDir: string = process.cwd()\n): Promise<boolean> {\n try {\n const pkgPath = join(targetDir, \"package.json\");\n if (existsSync(pkgPath)) {\n const content = await readFile(pkgPath, \"utf-8\");\n const pkg = JSON.parse(content);\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n return \"react\" in deps || \"react-dom\" in deps;\n }\n } catch {\n // Ignore parse errors\n }\n return false;\n}\n\n/**\n * Get a human-readable description of the project type\n */\nexport function getProjectTypeDescription(type: ProjectType): string {\n switch (type) {\n case \"nx\":\n return \"NX Monorepo\";\n case \"turbo\":\n return \"Turborepo\";\n case \"pnpm-workspace\":\n return \"pnpm Workspace\";\n case \"single\":\n return \"Single Package\";\n }\n}\n\n/**\n * Re-export package manager detection utilities for convenience\n */\nexport {\n detectPackageManager,\n detectYarnVersion,\n getPackageManagerInfo,\n getPackageManagerDescription,\n PACKAGE_MANAGERS,\n} from \"./detect-package-manager.js\";\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { PackageManager, PackageManagerInfo, PackageJson } from \"../types/config.js\";\n\n/**\n * Package manager metadata and commands\n */\nexport const PACKAGE_MANAGERS: Record<PackageManager, PackageManagerInfo> = {\n npm: {\n name: \"npm\",\n install: \"npm install\",\n run: \"npm run\",\n exec: \"npx\",\n lockfile: \"package-lock.json\",\n installFrozen: \"npm ci\",\n needsSetupAction: false,\n cacheKey: \"npm-${{ hashFiles('**/package-lock.json') }}\",\n },\n pnpm: {\n name: \"pnpm\",\n install: \"pnpm install\",\n run: \"pnpm\",\n exec: \"pnpm dlx\",\n lockfile: \"pnpm-lock.yaml\",\n installFrozen: \"pnpm install --frozen-lockfile\",\n needsSetupAction: true,\n cacheKey: \"pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}\",\n },\n yarn: {\n name: \"yarn\",\n install: \"yarn install\",\n run: \"yarn\",\n exec: \"yarn\",\n lockfile: \"yarn.lock\",\n installFrozen: \"yarn install --frozen-lockfile\",\n needsSetupAction: false,\n cacheKey: \"yarn-${{ hashFiles('**/yarn.lock') }}\",\n },\n \"yarn-berry\": {\n name: \"yarn-berry\",\n install: \"yarn install\",\n run: \"yarn\",\n exec: \"yarn dlx\",\n lockfile: \"yarn.lock\",\n installFrozen: \"yarn install --immutable\",\n needsSetupAction: false,\n cacheKey: \"yarn-${{ hashFiles('**/yarn.lock') }}\",\n },\n};\n\n/**\n * Detect Yarn version from package.json packageManager field\n * @param targetDir Directory to check\n * @returns \"yarn\" for 1.x, \"yarn-berry\" for 2+, or null if not specified\n */\nexport function detectYarnVersion(targetDir: string): \"yarn\" | \"yarn-berry\" | null {\n const packageJsonPath = join(targetDir, \"package.json\");\n\n if (!existsSync(packageJsonPath)) {\n return null;\n }\n\n try {\n const packageJson: PackageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"));\n const packageManager = packageJson.packageManager as string | undefined;\n\n if (!packageManager) {\n return null;\n }\n\n // Parse packageManager field (e.g., \"yarn@3.6.0\", \"yarn@1.22.19\")\n const match = packageManager.match(/^yarn@(\\d+)\\./);\n if (match) {\n const majorVersion = Number.parseInt(match[1], 10);\n return majorVersion >= 2 ? \"yarn-berry\" : \"yarn\";\n }\n\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Detect package manager from lockfiles\n * Priority: pnpm-lock.yaml > yarn.lock > package-lock.json\n * @param targetDir Directory to check for lockfiles\n * @returns Detected package manager or null if no lockfile found\n */\nexport function detectPackageManager(targetDir: string): PackageManagerInfo | null {\n // Check pnpm first (highest priority)\n if (existsSync(join(targetDir, \"pnpm-lock.yaml\"))) {\n return PACKAGE_MANAGERS.pnpm;\n }\n\n // Check yarn second\n if (existsSync(join(targetDir, \"yarn.lock\"))) {\n const yarnVersion = detectYarnVersion(targetDir);\n\n // If packageManager field specifies version, use that\n if (yarnVersion === \"yarn-berry\") {\n return PACKAGE_MANAGERS[\"yarn-berry\"];\n }\n\n // Default to Yarn 1.x (classic)\n return PACKAGE_MANAGERS.yarn;\n }\n\n // Check npm last (lowest priority)\n if (existsSync(join(targetDir, \"package-lock.json\"))) {\n return PACKAGE_MANAGERS.npm;\n }\n\n // No lockfile found\n return null;\n}\n\n/**\n * Get package manager metadata by name\n * @param name Package manager name\n * @returns Package manager metadata\n */\nexport function getPackageManagerInfo(name: PackageManager): PackageManagerInfo {\n return PACKAGE_MANAGERS[name];\n}\n\n/**\n * Get human-readable description of package manager\n * @param pm Package manager info\n * @returns Human-readable description\n */\nexport function getPackageManagerDescription(pm: PackageManagerInfo): string {\n switch (pm.name) {\n case \"npm\":\n return \"npm (Node Package Manager)\";\n case \"pnpm\":\n return \"pnpm (Performant npm)\";\n case \"yarn\":\n return \"Yarn Classic (1.x)\";\n case \"yarn-berry\":\n return \"Yarn Berry (2+)\";\n default:\n return pm.name;\n }\n}\n","import { join } from \"node:path\";\nimport type { GeneratorResult, PackageManagerInfo, ProjectType } from \"../types/config.js\";\nimport { ensureDir, writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Generate Husky pre-commit hook\n */\nfunction getPreCommitHook(projectType: ProjectType, pm: PackageManagerInfo): string {\n // NX uses its own lint-staged orchestration\n if (projectType === \"nx\") {\n return `#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\n\n${pm.exec} lint-staged\n`;\n }\n\n return `#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\n\n${pm.exec} lint-staged\n`;\n}\n\n/**\n * Generate Husky commit-msg hook for commitlint\n */\nfunction getCommitMsgHook(pm: PackageManagerInfo): string {\n return `#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\n\n${pm.exec} --no -- commitlint --edit \"$1\"\n`;\n}\n\n/**\n * Generate Husky pre-push hook for branch validation\n */\nfunction getPrePushHook(pm: PackageManagerInfo): string {\n return `#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\n\n${pm.exec} validate-branch-name\n`;\n}\n\n/**\n * Generate all Husky hooks\n */\nexport async function generateHuskyHooks(\n targetDir: string,\n projectType: ProjectType,\n pm: PackageManagerInfo\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const huskyDir = join(targetDir, \".husky\");\n await ensureDir(huskyDir);\n\n // Pre-commit hook\n const preCommitPath = join(huskyDir, \"pre-commit\");\n const preCommitResult = await writeFileSafe(\n preCommitPath,\n getPreCommitHook(projectType, pm),\n { executable: true, backup: true }\n );\n if (preCommitResult.created) {\n result.created.push(\".husky/pre-commit\");\n if (preCommitResult.backedUp) {\n result.backedUp.push(preCommitResult.backedUp);\n }\n }\n\n // Commit-msg hook\n const commitMsgPath = join(huskyDir, \"commit-msg\");\n const commitMsgResult = await writeFileSafe(\n commitMsgPath,\n getCommitMsgHook(pm),\n { executable: true, backup: true }\n );\n if (commitMsgResult.created) {\n result.created.push(\".husky/commit-msg\");\n if (commitMsgResult.backedUp) {\n result.backedUp.push(commitMsgResult.backedUp);\n }\n }\n\n // Pre-push hook\n const prePushPath = join(huskyDir, \"pre-push\");\n const prePushResult = await writeFileSafe(prePushPath, getPrePushHook(pm), {\n executable: true,\n backup: true,\n });\n if (prePushResult.created) {\n result.created.push(\".husky/pre-push\");\n if (prePushResult.backedUp) {\n result.backedUp.push(prePushResult.backedUp);\n }\n }\n\n return result;\n}\n","import { existsSync } from \"node:fs\";\nimport {\n mkdir,\n readFile,\n writeFile,\n copyFile,\n chmod,\n} from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\n/**\n * Ensure a directory exists, creating it if necessary\n */\nexport async function ensureDir(dirPath: string): Promise<void> {\n if (!existsSync(dirPath)) {\n await mkdir(dirPath, { recursive: true });\n }\n}\n\n/**\n * Backup a file if it exists\n * Returns the backup path if a backup was created, null otherwise\n */\nexport async function backupFile(filePath: string): Promise<string | null> {\n if (!existsSync(filePath)) {\n return null;\n }\n\n const backupPath = `${filePath}.backup`;\n await copyFile(filePath, backupPath);\n return backupPath;\n}\n\n/**\n * Write a file safely with optional backup\n */\nexport async function writeFileSafe(\n filePath: string,\n content: string,\n options: {\n backup?: boolean;\n overwrite?: boolean;\n executable?: boolean;\n } = {}\n): Promise<{ created: boolean; backedUp: string | null }> {\n const { backup = true, overwrite = true, executable = false } = options;\n\n // Check if file exists\n const exists = existsSync(filePath);\n\n // If file exists and we shouldn't overwrite, skip\n if (exists && !overwrite) {\n return { created: false, backedUp: null };\n }\n\n // Backup existing file if requested\n let backedUp: string | null = null;\n if (exists && backup) {\n backedUp = await backupFile(filePath);\n }\n\n // Ensure directory exists\n await ensureDir(dirname(filePath));\n\n // Write the file\n await writeFile(filePath, content, \"utf-8\");\n\n // Make executable if requested\n if (executable) {\n await chmod(filePath, 0o755);\n }\n\n return { created: true, backedUp };\n}\n\n/**\n * Read a file, returning null if it doesn't exist\n */\nexport async function readFileSafe(filePath: string): Promise<string | null> {\n if (!existsSync(filePath)) {\n return null;\n }\n return readFile(filePath, \"utf-8\");\n}\n\n/**\n * Check if a file exists\n */\nexport function fileExists(filePath: string): boolean {\n return existsSync(filePath);\n}\n\n/**\n * Get relative path from target directory\n */\nexport function getRelativePath(\n filePath: string,\n targetDir: string = process.cwd()\n): string {\n if (filePath.startsWith(targetDir)) {\n return filePath.slice(targetDir.length + 1);\n }\n return filePath;\n}\n\n/**\n * Join paths and normalize\n */\nexport function joinPath(...paths: string[]): string {\n return join(...paths);\n}\n","import { join } from \"node:path\";\nimport type { GeneratorResult } from \"../types/config.js\";\nimport { writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Generate commitlint configuration\n * Note: Asana task link uses level 1 (warning) not level 2 (error)\n * Commits without task links will show a warning but won't be blocked\n */\nfunction getCommitlintConfig(asanaBaseUrl?: string): string {\n const baseConfig = `// @ts-check\n\n/** @type {import('@commitlint/types').UserConfig} */\nconst config = {\n extends: ['@commitlint/config-conventional'],\n rules: {\n // Type must be one of the conventional types\n 'type-enum': [\n 2,\n 'always',\n [\n 'feat', // New feature\n 'fix', // Bug fix\n 'docs', // Documentation changes\n 'style', // Code style changes (formatting, etc.)\n 'refactor', // Code refactoring\n 'perf', // Performance improvements\n 'test', // Adding or updating tests\n 'build', // Build system changes\n 'ci', // CI configuration changes\n 'chore', // Other changes (maintenance, etc.)\n 'revert', // Reverting changes\n ],\n ],\n // Subject should not be empty\n 'subject-empty': [2, 'never'],\n // Type should not be empty\n 'type-empty': [2, 'never'],\n // Subject should be lowercase\n 'subject-case': [2, 'always', 'lower-case'],\n // Header max length\n 'header-max-length': [2, 'always', 100],\n },`;\n\n if (asanaBaseUrl) {\n // Add Asana task link validation as a WARNING (level 1), not error (level 2)\n return `${baseConfig}\n plugins: [\n {\n rules: {\n 'asana-task-link': ({ body, footer }) => {\n const fullMessage = [body, footer].filter(Boolean).join('\\\\n');\n const asanaPattern = /https:\\\\/\\\\/app\\\\.asana\\\\.com\\\\/\\\\d+\\\\/\\\\d+\\\\/\\\\d+/;\n const hasAsanaLink = asanaPattern.test(fullMessage);\n return [\n hasAsanaLink,\n hasAsanaLink\n ? null\n : 'Consider adding an Asana task link in the commit body or footer (e.g., Task: https://app.asana.com/0/...)',\n ];\n },\n },\n },\n ],\n};\n\n// Enable the Asana task link rule as a WARNING (level 1)\n// Change to level 2 if you want to BLOCK commits without Asana links\nconfig.rules['asana-task-link'] = [1, 'always'];\n\nmodule.exports = config;\n`;\n }\n\n return `${baseConfig}\n};\n\nmodule.exports = config;\n`;\n}\n\n/**\n * Generate commitlint configuration file\n */\nexport async function generateCommitlint(\n targetDir: string,\n asanaBaseUrl?: string\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const configPath = join(targetDir, \"commitlint.config.js\");\n const writeResult = await writeFileSafe(\n configPath,\n getCommitlintConfig(asanaBaseUrl),\n { backup: true }\n );\n\n if (writeResult.created) {\n result.created.push(\"commitlint.config.js\");\n if (writeResult.backedUp) {\n result.backedUp.push(writeResult.backedUp);\n }\n }\n\n return result;\n}\n","import { join } from \"node:path\";\nimport type { GeneratorResult } from \"../types/config.js\";\nimport { writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Generate cz-git configuration\n */\nfunction getCzGitConfig(asanaBaseUrl?: string): string {\n const asanaSection = asanaBaseUrl\n ? `\n // Asana task reference settings\n allowCustomIssuePrefix: true,\n allowEmptyIssuePrefix: true,\n issuePrefixes: [\n { value: 'asana', name: 'asana: Link to Asana task' },\n { value: 'closes', name: 'closes: Close an issue' },\n { value: 'fixes', name: 'fixes: Fix an issue' },\n ],\n customIssuePrefixAlign: 'top',`\n : `\n allowCustomIssuePrefix: false,\n allowEmptyIssuePrefix: true,`;\n\n return `// @ts-check\n\n/** @type {import('cz-git').UserConfig} */\nmodule.exports = {\n extends: ['@commitlint/config-conventional'],\n prompt: {\n alias: {\n fd: 'docs: fix typos',\n ur: 'docs: update README',\n },\n messages: {\n type: \"Select the type of change you're committing:\",\n scope: 'Denote the scope of this change (optional):',\n customScope: 'Denote the scope of this change:',\n subject: 'Write a short, imperative description of the change:\\\\n',\n body: 'Provide a longer description of the change (optional). Use \"|\" to break new line:\\\\n',\n breaking: 'List any BREAKING CHANGES (optional). Use \"|\" to break new line:\\\\n',\n footerPrefixSelect: 'Select the ISSUES type of change (optional):',\n customFooterPrefix: 'Input ISSUES prefix:',\n footer: 'List any ISSUES affected by this change (optional). E.g.: #31, #34:\\\\n',\n confirmCommit: 'Are you sure you want to proceed with the commit above?',\n },\n types: [\n { value: 'feat', name: 'feat: ✨ A new feature', emoji: ':sparkles:' },\n { value: 'fix', name: 'fix: 🐛 A bug fix', emoji: ':bug:' },\n { value: 'docs', name: 'docs: 📝 Documentation changes', emoji: ':memo:' },\n { value: 'style', name: 'style: 💄 Code style changes', emoji: ':lipstick:' },\n { value: 'refactor', name: 'refactor: ♻️ Code refactoring', emoji: ':recycle:' },\n { value: 'perf', name: 'perf: ⚡️ Performance improvements', emoji: ':zap:' },\n { value: 'test', name: 'test: ✅ Adding or updating tests', emoji: ':white_check_mark:' },\n { value: 'build', name: 'build: 📦 Build system changes', emoji: ':package:' },\n { value: 'ci', name: 'ci: 🎡 CI configuration changes', emoji: ':ferris_wheel:' },\n { value: 'chore', name: 'chore: 🔧 Other changes', emoji: ':wrench:' },\n { value: 'revert', name: 'revert: ⏪ Reverting changes', emoji: ':rewind:' },\n ],\n useEmoji: true,\n emojiAlign: 'center',\n useAI: false,\n aiNumber: 1,\n themeColorCode: '',\n scopes: [],\n allowCustomScopes: true,\n allowEmptyScopes: true,\n customScopesAlign: 'bottom',\n customScopesAlias: 'custom',\n emptyScopesAlias: 'empty',\n upperCaseSubject: false,\n markBreakingChangeMode: false,\n allowBreakingChanges: ['feat', 'fix'],\n breaklineNumber: 100,\n breaklineChar: '|',\n skipQuestions: [],${asanaSection}\n confirmColorize: true,\n minSubjectLength: 0,\n defaultBody: '',\n defaultIssues: '',\n defaultScope: '',\n defaultSubject: '',\n },\n};\n`;\n}\n\n/**\n * Generate cz-git configuration file\n */\nexport async function generateCzGit(\n targetDir: string,\n asanaBaseUrl?: string\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const configPath = join(targetDir, \".czrc\");\n const writeResult = await writeFileSafe(\n configPath,\n JSON.stringify({ path: \"node_modules/cz-git\" }, null, 2) + \"\\n\",\n { backup: true }\n );\n\n if (writeResult.created) {\n result.created.push(\".czrc\");\n if (writeResult.backedUp) {\n result.backedUp.push(writeResult.backedUp);\n }\n }\n\n // Also generate the cz.config.js for more detailed config\n const czConfigPath = join(targetDir, \"cz.config.js\");\n const czConfigResult = await writeFileSafe(\n czConfigPath,\n getCzGitConfig(asanaBaseUrl),\n { backup: true }\n );\n\n if (czConfigResult.created) {\n result.created.push(\"cz.config.js\");\n if (czConfigResult.backedUp) {\n result.backedUp.push(czConfigResult.backedUp);\n }\n }\n\n return result;\n}\n","import { join } from \"node:path\";\nimport type { GeneratorResult, ProjectType } from \"../types/config.js\";\nimport { writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Generate lint-staged configuration based on project type\n */\nfunction getLintStagedConfig(\n projectType: ProjectType,\n usesEslint: boolean,\n usesPrettier: boolean,\n usesTypeScript: boolean\n): string {\n const rules: Record<string, string | string[]> = {};\n\n // TypeScript/JavaScript files\n if (usesTypeScript) {\n const tsCommands: string[] = [];\n if (usesEslint) {\n tsCommands.push(\"eslint --fix\");\n }\n if (usesPrettier) {\n tsCommands.push(\"prettier --write\");\n }\n if (tsCommands.length > 0) {\n rules[\"*.{ts,tsx}\"] = tsCommands;\n }\n }\n\n // JavaScript files\n const jsCommands: string[] = [];\n if (usesEslint) {\n jsCommands.push(\"eslint --fix\");\n }\n if (usesPrettier) {\n jsCommands.push(\"prettier --write\");\n }\n if (jsCommands.length > 0) {\n rules[\"*.{js,jsx,mjs,cjs}\"] = jsCommands;\n }\n\n // JSON, MD, YAML files (Prettier only)\n if (usesPrettier) {\n rules[\"*.{json,md,yaml,yml}\"] = \"prettier --write\";\n }\n\n // CSS/SCSS files\n if (usesPrettier) {\n rules[\"*.{css,scss,less}\"] = \"prettier --write\";\n }\n\n // NX-specific configuration\n if (projectType === \"nx\") {\n return `// @ts-check\n\n/**\n * @type {import('lint-staged').Config}\n */\nmodule.exports = {\n${Object.entries(rules)\n .map(([pattern, commands]) => {\n const cmdStr = Array.isArray(commands)\n ? JSON.stringify(commands)\n : JSON.stringify([commands]);\n return ` '${pattern}': ${cmdStr},`;\n })\n .join(\"\\n\")}\n};\n`;\n }\n\n // Standard configuration\n return `// @ts-check\n\n/**\n * @type {import('lint-staged').Config}\n */\nmodule.exports = {\n${Object.entries(rules)\n .map(([pattern, commands]) => {\n const cmdStr = Array.isArray(commands)\n ? JSON.stringify(commands)\n : JSON.stringify([commands]);\n return ` '${pattern}': ${cmdStr},`;\n })\n .join(\"\\n\")}\n};\n`;\n}\n\n/**\n * Generate lint-staged configuration file\n */\nexport async function generateLintStaged(\n targetDir: string,\n projectType: ProjectType,\n usesEslint: boolean,\n usesPrettier: boolean,\n usesTypeScript: boolean\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const configPath = join(targetDir, \".lintstagedrc.js\");\n const writeResult = await writeFileSafe(\n configPath,\n getLintStagedConfig(projectType, usesEslint, usesPrettier, usesTypeScript),\n { backup: true }\n );\n\n if (writeResult.created) {\n result.created.push(\".lintstagedrc.js\");\n if (writeResult.backedUp) {\n result.backedUp.push(writeResult.backedUp);\n }\n }\n\n return result;\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { PackageJson, PackageManagerInfo } from \"../types/config.js\";\n\n/**\n * Read package.json from a directory\n */\nexport async function readPackageJson(\n targetDir: string = process.cwd()\n): Promise<PackageJson> {\n const pkgPath = join(targetDir, \"package.json\");\n\n if (!existsSync(pkgPath)) {\n throw new Error(`No package.json found in ${targetDir}`);\n }\n\n const content = await readFile(pkgPath, \"utf-8\");\n return JSON.parse(content) as PackageJson;\n}\n\n/**\n * Write package.json to a directory\n */\nexport async function writePackageJson(\n pkg: PackageJson,\n targetDir: string = process.cwd()\n): Promise<void> {\n const pkgPath = join(targetDir, \"package.json\");\n const content = JSON.stringify(pkg, null, 2) + \"\\n\";\n await writeFile(pkgPath, content, \"utf-8\");\n}\n\n/**\n * Merge scripts into package.json without overwriting existing ones\n */\nexport function mergeScripts(\n pkg: PackageJson,\n scripts: Record<string, string>,\n overwrite: boolean = false\n): PackageJson {\n const existingScripts = pkg.scripts || {};\n const newScripts: Record<string, string> = { ...existingScripts };\n\n for (const [name, command] of Object.entries(scripts)) {\n if (overwrite || !existingScripts[name]) {\n newScripts[name] = command;\n }\n }\n\n return {\n ...pkg,\n scripts: newScripts,\n };\n}\n\n/**\n * Merge devDependencies into package.json\n */\nexport function mergeDevDependencies(\n pkg: PackageJson,\n deps: Record<string, string>\n): PackageJson {\n const existingDeps = pkg.devDependencies || {};\n\n return {\n ...pkg,\n devDependencies: {\n ...existingDeps,\n ...deps,\n },\n };\n}\n\n/**\n * Add a config section to package.json (e.g., lint-staged, validate-branch-name)\n */\nexport function addPackageJsonConfig<T>(\n pkg: PackageJson,\n key: string,\n config: T,\n overwrite: boolean = false\n): PackageJson {\n if (!overwrite && pkg[key]) {\n return pkg;\n }\n\n return {\n ...pkg,\n [key]: config,\n };\n}\n\n/**\n * Update package.json with multiple changes at once\n */\nexport async function updatePackageJson(\n targetDir: string,\n updater: (pkg: PackageJson) => PackageJson\n): Promise<PackageJson> {\n const pkg = await readPackageJson(targetDir);\n const updated = updater(pkg);\n await writePackageJson(updated, targetDir);\n return updated;\n}\n\n/**\n * Dependencies that RaftStack will install in the target project\n */\nexport const RAFTSTACK_DEV_DEPENDENCIES: Record<string, string> = {\n \"@commitlint/cli\": \"^18.0.0\",\n \"@commitlint/config-conventional\": \"^18.0.0\",\n \"cz-git\": \"^1.8.0\",\n czg: \"^1.8.0\",\n husky: \"^9.0.0\",\n \"lint-staged\": \"^15.0.0\",\n \"validate-branch-name\": \"^1.3.0\",\n};\n\n/**\n * Get package manager-specific scripts\n * This can be used in the future to add PM-specific setup scripts\n */\nexport function getPackageManagerScripts(\n _pm: PackageManagerInfo\n): Record<string, string> {\n // Currently, all package managers use the same scripts\n // This function is here for future extensibility if we need\n // different scripts for different package managers\n return {\n commit: \"czg\",\n prepare: \"husky\",\n };\n}\n","import type { GeneratorResult } from \"../types/config.js\";\nimport {\n addPackageJsonConfig,\n readPackageJson,\n writePackageJson,\n} from \"../utils/package-json.js\";\n\n/**\n * Branch naming pattern configuration\n */\ninterface BranchValidationConfig {\n pattern: string;\n errorMsg: string;\n}\n\n/**\n * Get the default branch validation configuration\n */\nfunction getBranchValidationConfig(): BranchValidationConfig {\n return {\n pattern:\n \"^(main|master|develop|staging|production)$|^(feature|fix|hotfix|bugfix|release|chore|docs|refactor|test|ci)\\\\/[a-z0-9._-]+$\",\n errorMsg:\n \"Branch name must follow pattern: feature/*, fix/*, hotfix/*, bugfix/*, release/*, chore/*, docs/*, refactor/*, test/*, ci/* or be main/master/develop/staging/production\",\n };\n}\n\n/**\n * Add validate-branch-name configuration to package.json\n */\nexport async function generateBranchValidation(\n targetDir: string\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n try {\n const pkg = await readPackageJson(targetDir);\n const config = getBranchValidationConfig();\n\n const updatedPkg = addPackageJsonConfig(\n pkg,\n \"validate-branch-name\",\n config,\n false // Don't overwrite if exists\n );\n\n // Check if we actually added something\n if (JSON.stringify(pkg) !== JSON.stringify(updatedPkg)) {\n await writePackageJson(updatedPkg, targetDir);\n result.modified.push(\"package.json (validate-branch-name)\");\n } else {\n result.skipped.push(\"validate-branch-name config (already exists)\");\n }\n } catch (error) {\n // If package.json doesn't exist or can't be read, skip\n result.skipped.push(\"validate-branch-name config (no package.json)\");\n }\n\n return result;\n}\n","import { join } from \"node:path\";\nimport type { GeneratorResult } from \"../types/config.js\";\nimport { ensureDir, writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Get the PR template content\n */\nfunction getPRTemplate(hasAsana: boolean): string {\n const asanaSection = hasAsana\n ? `## Asana Task\n<!-- Link to the Asana task -->\n- [ ] https://app.asana.com/0/...\n\n`\n : \"\";\n\n return `## Description\n<!-- Provide a brief description of the changes in this PR -->\n\n## Type of Change\n<!-- Mark the appropriate option with an \"x\" -->\n- [ ] 🐛 Bug fix (non-breaking change that fixes an issue)\n- [ ] ✨ New feature (non-breaking change that adds functionality)\n- [ ] 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)\n- [ ] 📝 Documentation update\n- [ ] 🔧 Configuration change\n- [ ] ♻️ Refactoring (no functional changes)\n- [ ] ✅ Test update\n\n${asanaSection}## Changes Made\n<!-- List the specific changes made in this PR -->\n-\n\n## Testing\n<!-- Describe how you tested your changes -->\n- [ ] Unit tests added/updated\n- [ ] Integration tests added/updated\n- [ ] Manual testing performed\n\n## Screenshots (if applicable)\n<!-- Add screenshots to help explain your changes -->\n\n## Checklist\n- [ ] My code follows the project's coding standards\n- [ ] I have performed a self-review of my code\n- [ ] I have commented my code, particularly in hard-to-understand areas\n- [ ] I have made corresponding changes to the documentation\n- [ ] My changes generate no new warnings\n- [ ] Any dependent changes have been merged and published\n\n## Additional Notes\n<!-- Add any additional information that reviewers should know -->\n`;\n}\n\n/**\n * Generate GitHub PR template\n */\nexport async function generatePRTemplate(\n targetDir: string,\n hasAsana: boolean\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const githubDir = join(targetDir, \".github\");\n await ensureDir(githubDir);\n\n const templatePath = join(githubDir, \"PULL_REQUEST_TEMPLATE.md\");\n const writeResult = await writeFileSafe(\n templatePath,\n getPRTemplate(hasAsana),\n { backup: true }\n );\n\n if (writeResult.created) {\n result.created.push(\".github/PULL_REQUEST_TEMPLATE.md\");\n if (writeResult.backedUp) {\n result.backedUp.push(writeResult.backedUp);\n }\n }\n\n return result;\n}\n","import { join } from \"node:path\";\nimport type { GeneratorResult, PackageManagerInfo, ProjectType } from \"../types/config.js\";\nimport { ensureDir, writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Get the PR checks workflow content\n */\nfunction getPRChecksWorkflow(\n projectType: ProjectType,\n usesTypeScript: boolean,\n usesEslint: boolean,\n pm: PackageManagerInfo\n): string {\n const steps: string[] = [];\n\n // Checkout\n steps.push(` - name: Checkout\n uses: actions/checkout@v4`);\n\n // Setup Node\n steps.push(`\n - name: Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: '20'`);\n\n // Setup pnpm (only if needed)\n if (pm.needsSetupAction) {\n steps.push(`\n - name: Setup pnpm\n uses: pnpm/action-setup@v3\n with:\n version: 9`);\n }\n\n // Install dependencies\n steps.push(`\n - name: Install dependencies\n run: ${pm.installFrozen}`);\n\n // TypeScript check\n if (usesTypeScript) {\n steps.push(`\n - name: Type check\n run: ${pm.run} typecheck`);\n }\n\n // ESLint\n if (usesEslint) {\n steps.push(`\n - name: Lint\n run: ${pm.run} lint`);\n }\n\n // Build (for NX/Turbo, use their commands)\n if (projectType === \"nx\") {\n steps.push(`\n - name: Build\n run: ${pm.run} nx affected --target=build --parallel=3`);\n } else if (projectType === \"turbo\") {\n steps.push(`\n - name: Build\n run: ${pm.run} turbo build`);\n } else {\n steps.push(`\n - name: Build\n run: ${pm.run} build`);\n }\n\n // Tests\n if (projectType === \"nx\") {\n steps.push(`\n - name: Test\n run: ${pm.run} nx affected --target=test --parallel=3`);\n } else if (projectType === \"turbo\") {\n steps.push(`\n - name: Test\n run: ${pm.run} turbo test`);\n } else {\n steps.push(`\n - name: Test\n run: ${pm.run} test`);\n }\n\n return `name: PR Checks\n\non:\n pull_request:\n branches: [main, master, develop]\n\nconcurrency:\n group: \\${{ github.workflow }}-\\${{ github.ref }}\n cancel-in-progress: true\n\njobs:\n check:\n name: Check\n runs-on: ubuntu-latest\n steps:\n${steps.join(\"\\n\")}\n`;\n}\n\n/**\n * Generate GitHub workflow files\n */\nexport async function generateGitHubWorkflows(\n targetDir: string,\n projectType: ProjectType,\n usesTypeScript: boolean,\n usesEslint: boolean,\n pm: PackageManagerInfo\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const workflowsDir = join(targetDir, \".github\", \"workflows\");\n await ensureDir(workflowsDir);\n\n // PR Checks workflow\n const prChecksPath = join(workflowsDir, \"pr-checks.yml\");\n const writeResult = await writeFileSafe(\n prChecksPath,\n getPRChecksWorkflow(projectType, usesTypeScript, usesEslint, pm),\n { backup: true }\n );\n\n if (writeResult.created) {\n result.created.push(\".github/workflows/pr-checks.yml\");\n if (writeResult.backedUp) {\n result.backedUp.push(writeResult.backedUp);\n }\n }\n\n return result;\n}\n","import { join } from \"node:path\";\nimport type { GeneratorResult } from \"../types/config.js\";\nimport { ensureDir, writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Get the CODEOWNERS content\n */\nfunction getCodeownersContent(owners: string[]): string {\n if (owners.length === 0) {\n return `# CODEOWNERS file\n# Learn about CODEOWNERS: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners\n\n# Default owners for everything in the repo\n# Uncomment and modify the line below to set default owners\n# * @owner1 @owner2\n`;\n }\n\n const ownersList = owners.join(\" \");\n\n return `# CODEOWNERS file\n# Learn about CODEOWNERS: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners\n\n# Default owners for everything in the repo\n* ${ownersList}\n\n# You can also specify owners for specific paths:\n# /docs/ @docs-team\n# /src/api/ @backend-team\n# /src/ui/ @frontend-team\n# *.ts @typescript-team\n`;\n}\n\n/**\n * Generate CODEOWNERS file\n */\nexport async function generateCodeowners(\n targetDir: string,\n owners: string[]\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const githubDir = join(targetDir, \".github\");\n await ensureDir(githubDir);\n\n const codeownersPath = join(githubDir, \"CODEOWNERS\");\n const writeResult = await writeFileSafe(\n codeownersPath,\n getCodeownersContent(owners),\n { backup: true }\n );\n\n if (writeResult.created) {\n result.created.push(\".github/CODEOWNERS\");\n if (writeResult.backedUp) {\n result.backedUp.push(writeResult.backedUp);\n }\n }\n\n return result;\n}\n","import { join } from \"node:path\";\nimport type { AIReviewTool, GeneratorResult } from \"../types/config.js\";\nimport { ensureDir, writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Get CodeRabbit configuration\n */\nfunction getCodeRabbitConfig(): string {\n return `# CodeRabbit Configuration\n# Learn more: https://docs.coderabbit.ai/guides/configure-coderabbit\n\nlanguage: \"en-US\"\n\nreviews:\n request_changes_workflow: true\n high_level_summary: true\n poem: false\n review_status: true\n collapse_walkthrough: false\n auto_review:\n enabled: true\n drafts: false\n\nchat:\n auto_reply: true\n`;\n}\n\n/**\n * Get GitHub Copilot PR review workflow\n */\nfunction getCopilotWorkflow(): string {\n return `name: Copilot Code Review\n\non:\n pull_request:\n types: [opened, synchronize, reopened]\n\npermissions:\n contents: read\n pull-requests: write\n\njobs:\n review:\n name: Copilot Review\n runs-on: ubuntu-latest\n steps:\n - name: Checkout\n uses: actions/checkout@v4\n\n # Note: GitHub Copilot code review is automatically enabled\n # when you have Copilot Enterprise. This workflow is a placeholder\n # for any additional AI review configuration you might need.\n\n - name: Add review comment\n uses: actions/github-script@v7\n with:\n script: |\n // GitHub Copilot will automatically review PRs if enabled\n // This is a placeholder for additional review logic\n console.log('Copilot review enabled for this repository');\n`;\n}\n\n/**\n * Generate AI review configuration\n */\nexport async function generateAIReview(\n targetDir: string,\n tool: AIReviewTool\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n if (tool === \"none\") {\n return result;\n }\n\n if (tool === \"coderabbit\") {\n const configPath = join(targetDir, \".coderabbit.yaml\");\n const writeResult = await writeFileSafe(configPath, getCodeRabbitConfig(), {\n backup: true,\n });\n\n if (writeResult.created) {\n result.created.push(\".coderabbit.yaml\");\n if (writeResult.backedUp) {\n result.backedUp.push(writeResult.backedUp);\n }\n }\n }\n\n if (tool === \"copilot\") {\n const workflowsDir = join(targetDir, \".github\", \"workflows\");\n await ensureDir(workflowsDir);\n\n const workflowPath = join(workflowsDir, \"copilot-review.yml\");\n const writeResult = await writeFileSafe(workflowPath, getCopilotWorkflow(), {\n backup: true,\n });\n\n if (writeResult.created) {\n result.created.push(\".github/workflows/copilot-review.yml\");\n if (writeResult.backedUp) {\n result.backedUp.push(writeResult.backedUp);\n }\n }\n }\n\n return result;\n}\n","import { join } from \"node:path\";\nimport type { GeneratorResult } from \"../types/config.js\";\nimport { ensureDir, writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Get branch protection setup documentation\n */\nfunction getBranchProtectionDocs(): string {\n return `# Branch Protection Setup Guide\n\nThis guide explains how to configure branch protection rules for your repository.\n\n## Quick Setup\n\nRun the automated setup command:\n\n\\`\\`\\`bash\nraftstack setup-protection\n\\`\\`\\`\n\nThis command supports:\n- **Multiple branches**: main, staging, production, development, etc.\n- **Merge strategies**: Rebase (recommended), squash, or merge commits\n- **Review requirements**: Configurable number of required approvals\n\n## Recommended Settings\n\n### For \\`main\\` / \\`master\\` branch:\n\n1. **Require a pull request before merging**\n - ✅ Require approvals: 1 (or more for larger teams)\n - ✅ Dismiss stale pull request approvals when new commits are pushed\n - ✅ Require review from Code Owners\n\n2. **Require status checks to pass before merging**\n - ✅ Require branches to be up to date before merging\n - Select required status checks:\n - \\`check\\` (from pr-checks.yml workflow)\n\n3. **Require conversation resolution before merging**\n - ✅ All conversations on code must be resolved\n\n4. **Do not allow bypassing the above settings**\n - ✅ Apply rules to administrators\n\n5. **Restrict who can push to matching branches**\n - Only allow merges through pull requests\n\n6. **Block force pushes**\n - ✅ Do not allow force pushes\n\n7. **Block deletions**\n - ✅ Do not allow this branch to be deleted\n\n## Manual Setup via GitHub UI\n\n1. Go to your repository on GitHub\n2. Click **Settings** > **Branches**\n3. Click **Add branch protection rule**\n4. Enter \\`main\\` (or \\`master\\`) as the branch name pattern\n5. Configure the settings as described above\n6. Click **Create** or **Save changes**\n\n## Automated Setup (Recommended)\n\nUse the \\`raftstack setup-protection\\` command to configure\nbranch protection rules automatically using the GitHub CLI.\n\nRequirements:\n- GitHub CLI (\\`gh\\`) installed and authenticated\n- Admin access to the repository\n\n\\`\\`\\`bash\nraftstack setup-protection\n\\`\\`\\`\n\n### Features\n\nThe setup command will:\n1. Prompt you to select branches to protect (main, staging, production, etc.)\n2. Let you choose a merge strategy (rebase, squash, or merge commits)\n3. Configure required review count\n4. Apply branch protection rules to all selected branches\n5. Set repository merge settings\n\n### Merge Strategy Recommendations\n\n| Strategy | Use Case |\n|----------|----------|\n| **Rebase** (recommended) | Clean linear history, easy to follow |\n| **Squash** | Single commit per PR, cleaner history |\n| **Merge commit** | Preserve all commits, show PR merge points |\n\n## Branch Naming Convention\n\nThis project enforces branch naming conventions via \\`validate-branch-name\\`.\n\nAllowed patterns:\n- \\`main\\`, \\`master\\`, \\`develop\\`, \\`staging\\`, \\`production\\`\n- \\`feature/*\\` - New features\n- \\`fix/*\\` or \\`bugfix/*\\` - Bug fixes\n- \\`hotfix/*\\` - Urgent fixes\n- \\`release/*\\` - Release preparation\n- \\`chore/*\\` - Maintenance tasks\n- \\`docs/*\\` - Documentation updates\n- \\`refactor/*\\` - Code refactoring\n- \\`test/*\\` - Test additions/updates\n- \\`ci/*\\` - CI/CD changes\n\nExamples:\n- \\`feature/user-authentication\\`\n- \\`fix/login-validation\\`\n- \\`hotfix/security-patch\\`\n- \\`release/v1.2.0\\`\n`;\n}\n\n/**\n * Generate branch protection documentation\n */\nexport async function generateBranchProtectionDocs(\n targetDir: string\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const docsDir = join(targetDir, \".github\");\n await ensureDir(docsDir);\n\n const docsPath = join(docsDir, \"BRANCH_PROTECTION_SETUP.md\");\n const writeResult = await writeFileSafe(docsPath, getBranchProtectionDocs(), {\n backup: true,\n });\n\n if (writeResult.created) {\n result.created.push(\".github/BRANCH_PROTECTION_SETUP.md\");\n if (writeResult.backedUp) {\n result.backedUp.push(writeResult.backedUp);\n }\n }\n\n return result;\n}\n","import { join } from \"node:path\";\nimport type { GeneratorResult, PackageManagerInfo } from \"../types/config.js\";\nimport { writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Get CONTRIBUTING.md content\n */\nfunction getContributingContent(hasAsana: boolean, pm: PackageManagerInfo): string {\n const asanaSection = hasAsana\n ? `\n## Linking to Asana\n\nWhen working on a task:\n1. Create a branch following the naming convention (e.g., \\`feature/task-description\\`)\n2. Include the Asana task link in your commit body or footer\n3. Reference the Asana task in your PR description\n\nExample commit:\n\\`\\`\\`\nfeat(auth): add password reset functionality\n\nImplement password reset flow with email verification.\n\nAsana: https://app.asana.com/0/workspace/task-id\n\\`\\`\\`\n`\n : \"\";\n\n return `# Contributing Guide\n\nThank you for your interest in contributing! This document outlines our development workflow and standards.\n\n## Getting Started\n\n1. Clone the repository\n2. Install dependencies: \\`${pm.install}\\`\n3. Create a new branch following our naming convention\n\n## Branch Naming Convention\n\nWe use structured branch names to keep our repository organized:\n\n| Prefix | Purpose | Example |\n|--------|---------|---------|\n| \\`feature/\\` | New features | \\`feature/user-authentication\\` |\n| \\`fix/\\` | Bug fixes | \\`fix/login-validation\\` |\n| \\`hotfix/\\` | Urgent fixes | \\`hotfix/security-patch\\` |\n| \\`bugfix/\\` | Bug fixes (alternative) | \\`bugfix/form-submission\\` |\n| \\`release/\\` | Release preparation | \\`release/v1.2.0\\` |\n| \\`chore/\\` | Maintenance tasks | \\`chore/update-dependencies\\` |\n| \\`docs/\\` | Documentation | \\`docs/api-reference\\` |\n| \\`refactor/\\` | Code refactoring | \\`refactor/auth-module\\` |\n| \\`test/\\` | Test additions | \\`test/user-service\\` |\n| \\`ci/\\` | CI/CD changes | \\`ci/github-actions\\` |\n\n## Commit Convention\n\nWe follow [Conventional Commits](https://www.conventionalcommits.org/). Use the interactive commit tool:\n\n\\`\\`\\`bash\n${pm.run} commit\n\\`\\`\\`\n\n### Commit Types\n\n| Type | Description |\n|------|-------------|\n| \\`feat\\` | New feature |\n| \\`fix\\` | Bug fix |\n| \\`docs\\` | Documentation changes |\n| \\`style\\` | Code style changes (formatting, etc.) |\n| \\`refactor\\` | Code refactoring |\n| \\`perf\\` | Performance improvements |\n| \\`test\\` | Adding or updating tests |\n| \\`build\\` | Build system changes |\n| \\`ci\\` | CI configuration changes |\n| \\`chore\\` | Other changes |\n| \\`revert\\` | Reverting changes |\n\n### Commit Message Format\n\n\\`\\`\\`\n<type>(<scope>): <subject>\n\n<body>\n\n<footer>\n\\`\\`\\`\n\nExample:\n\\`\\`\\`\nfeat(auth): add social login support\n\nImplement OAuth2 login for Google and GitHub providers.\nIncludes user profile sync and token refresh.\n\nCloses #123\n\\`\\`\\`\n${asanaSection}\n## Pull Request Process\n\n1. Ensure your branch is up to date with \\`main\\`/\\`master\\`\n2. Run tests and linting locally\n3. Create a pull request using the provided template\n4. Request review from code owners\n5. Address any feedback\n6. Merge once approved and all checks pass\n\n### PR Size Guidelines\n\nKeep pull requests small and focused for faster reviews:\n\n| Size | Lines Changed | Review Time |\n|------|---------------|-------------|\n| XS | 0-10 lines | Minutes |\n| S | 11-50 lines | < 30 min |\n| M | 51-200 lines | < 1 hour |\n| L | 201-400 lines | 1-2 hours |\n| XL | 400+ lines | Needs justification |\n\n**Target: < 400 lines per PR**\n\nIf your PR is large:\n- Consider splitting it into smaller, logical PRs\n- Explain in the description why it can't be split\n\n## Code Quality\n\nBefore committing, the following checks run automatically:\n\n- **Linting**: ESLint checks for code quality\n- **Formatting**: Prettier ensures consistent style\n- **Type checking**: TypeScript validates types\n- **Commit messages**: Commitlint validates format\n- **Branch names**: validate-branch-name checks naming\n\n## Questions?\n\nIf you have questions, please open an issue or reach out to the maintainers.\n`;\n}\n\n/**\n * Generate CONTRIBUTING.md\n */\nexport async function generateContributing(\n targetDir: string,\n hasAsana: boolean,\n pm: PackageManagerInfo\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const contributingPath = join(targetDir, \"CONTRIBUTING.md\");\n const writeResult = await writeFileSafe(\n contributingPath,\n getContributingContent(hasAsana, pm),\n { backup: true }\n );\n\n if (writeResult.created) {\n result.created.push(\"CONTRIBUTING.md\");\n if (writeResult.backedUp) {\n result.backedUp.push(writeResult.backedUp);\n }\n }\n\n return result;\n}\n","import { join } from \"node:path\";\nimport type { GeneratorResult } from \"../types/config.js\";\nimport { fileExists, writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Get Prettier configuration\n */\nfunction getPrettierConfig(): string {\n return JSON.stringify(\n {\n semi: true,\n singleQuote: true,\n tabWidth: 2,\n trailingComma: \"es5\",\n printWidth: 100,\n bracketSpacing: true,\n arrowParens: \"always\",\n endOfLine: \"lf\",\n },\n null,\n 2\n ) + \"\\n\";\n}\n\n/**\n * Get Prettier ignore file content\n */\nfunction getPrettierIgnore(): string {\n return `# Dependencies\nnode_modules/\n\n# Build output\ndist/\nbuild/\n.next/\nout/\n\n# Coverage\ncoverage/\n\n# IDE\n.idea/\n.vscode/\n\n# Generated files\n*.min.js\n*.min.css\npackage-lock.json\npnpm-lock.yaml\nyarn.lock\n\n# Other\n.git/\n`;\n}\n\n/**\n * Check if Prettier is already configured\n */\nfunction hasPrettierConfig(targetDir: string): boolean {\n const prettierFiles = [\n \".prettierrc\",\n \".prettierrc.js\",\n \".prettierrc.cjs\",\n \".prettierrc.json\",\n \".prettierrc.yaml\",\n \".prettierrc.yml\",\n \".prettierrc.toml\",\n \"prettier.config.js\",\n \"prettier.config.cjs\",\n \"prettier.config.mjs\",\n ];\n\n return prettierFiles.some((file) => fileExists(join(targetDir, file)));\n}\n\n/**\n * Generate Prettier configuration\n */\nexport async function generatePrettier(\n targetDir: string\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n // Skip if Prettier is already configured\n if (hasPrettierConfig(targetDir)) {\n result.skipped.push(\".prettierrc (already exists)\");\n return result;\n }\n\n // Create .prettierrc\n const configPath = join(targetDir, \".prettierrc\");\n const configResult = await writeFileSafe(configPath, getPrettierConfig(), {\n backup: true,\n });\n\n if (configResult.created) {\n result.created.push(\".prettierrc\");\n if (configResult.backedUp) {\n result.backedUp.push(configResult.backedUp);\n }\n }\n\n // Create .prettierignore\n const ignorePath = join(targetDir, \".prettierignore\");\n const ignoreResult = await writeFileSafe(ignorePath, getPrettierIgnore(), {\n backup: true,\n overwrite: false, // Don't overwrite existing ignore file\n });\n\n if (ignoreResult.created) {\n result.created.push(\".prettierignore\");\n if (ignoreResult.backedUp) {\n result.backedUp.push(ignoreResult.backedUp);\n }\n } else {\n result.skipped.push(\".prettierignore (already exists)\");\n }\n\n return result;\n}\n","import { existsSync } from \"node:fs\";\nimport { readdir, copyFile } from \"node:fs/promises\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { GeneratorResult } from \"../types/config.js\";\nimport { ensureDir, backupFile } from \"../utils/file-system.js\";\n\n/**\n * Get the path to the skills directory in the installed package\n */\nfunction getPackageSkillsDir(): string {\n // In ESM, we use import.meta.url to find the package location\n // tsup bundles everything into dist/cli.js, so we only need to go up 1 level\n const currentFilePath = fileURLToPath(import.meta.url);\n const packageRoot = join(dirname(currentFilePath), \"..\");\n return join(packageRoot, \".claude\", \"skills\");\n}\n\n/**\n * Recursively copy a directory\n */\nasync function copyDirectory(\n srcDir: string,\n destDir: string,\n result: GeneratorResult,\n baseDir: string\n): Promise<void> {\n await ensureDir(destDir);\n\n const entries = await readdir(srcDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = join(srcDir, entry.name);\n const destPath = join(destDir, entry.name);\n const relativePath = destPath.replace(baseDir + \"/\", \"\");\n\n if (entry.isDirectory()) {\n await copyDirectory(srcPath, destPath, result, baseDir);\n } else {\n // Check if destination exists\n if (existsSync(destPath)) {\n // Backup existing file\n const backupPath = await backupFile(destPath);\n if (backupPath) {\n result.backedUp.push(relativePath);\n }\n }\n\n // Copy the file\n await copyFile(srcPath, destPath);\n result.created.push(relativePath);\n }\n }\n}\n\n/**\n * Generate Claude Code skills by copying them to the target project\n *\n * This copies the bundled .claude/skills/ directory to the target project,\n * enabling AI-assisted code quality enforcement when using Claude Code.\n */\nexport async function generateClaudeSkills(\n targetDir: string\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const packageSkillsDir = getPackageSkillsDir();\n const targetSkillsDir = join(targetDir, \".claude\", \"skills\");\n\n // Check if source skills directory exists\n if (!existsSync(packageSkillsDir)) {\n // Skills not bundled (development mode or missing)\n console.warn(\n \"Warning: Skills directory not found in package. Skipping skills generation.\"\n );\n return result;\n }\n\n // Ensure target .claude directory exists\n await ensureDir(join(targetDir, \".claude\"));\n\n // Copy all skills\n await copyDirectory(packageSkillsDir, targetSkillsDir, result, targetDir);\n\n return result;\n}","import { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { GeneratorResult } from \"../types/config.js\";\nimport { writeFileSafe } from \"../utils/file-system.js\";\nimport { hasEslint } from \"../utils/detect-project.js\";\n\n/**\n * Check if project uses React\n */\nasync function hasReact(targetDir: string): Promise<boolean> {\n try {\n const pkgPath = join(targetDir, \"package.json\");\n if (existsSync(pkgPath)) {\n const content = await readFile(pkgPath, \"utf-8\");\n const pkg = JSON.parse(content);\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n return \"react\" in deps || \"react-dom\" in deps;\n }\n } catch {\n // Ignore parse errors\n }\n return false;\n}\n\n/**\n * Generate ESLint flat config content for TypeScript projects\n */\nfunction generateTsConfig(hasReactDep: boolean): string {\n if (hasReactDep) {\n return `import eslint from \"@eslint/js\";\nimport tseslint from \"typescript-eslint\";\nimport reactPlugin from \"eslint-plugin-react\";\nimport reactHooksPlugin from \"eslint-plugin-react-hooks\";\nimport globals from \"globals\";\n\nexport default tseslint.config(\n eslint.configs.recommended,\n ...tseslint.configs.recommended,\n {\n files: [\"**/*.{ts,tsx}\"],\n languageOptions: {\n parserOptions: {\n ecmaFeatures: {\n jsx: true,\n },\n },\n globals: {\n ...globals.browser,\n ...globals.node,\n },\n },\n plugins: {\n react: reactPlugin,\n \"react-hooks\": reactHooksPlugin,\n },\n rules: {\n // TypeScript rules\n \"@typescript-eslint/no-unused-vars\": [\"error\", { argsIgnorePattern: \"^_\" }],\n \"@typescript-eslint/no-explicit-any\": \"warn\",\n \"@typescript-eslint/consistent-type-imports\": \"error\",\n\n // React rules\n \"react/react-in-jsx-scope\": \"off\",\n \"react/prop-types\": \"off\",\n \"react-hooks/rules-of-hooks\": \"error\",\n \"react-hooks/exhaustive-deps\": \"warn\",\n\n // General rules\n \"no-console\": \"warn\",\n },\n settings: {\n react: {\n version: \"detect\",\n },\n },\n },\n {\n ignores: [\"node_modules\", \"dist\", \"build\", \".next\", \"coverage\"],\n }\n);\n`;\n }\n\n return `import eslint from \"@eslint/js\";\nimport tseslint from \"typescript-eslint\";\nimport globals from \"globals\";\n\nexport default tseslint.config(\n eslint.configs.recommended,\n ...tseslint.configs.recommended,\n {\n files: [\"**/*.{ts,tsx}\"],\n languageOptions: {\n globals: {\n ...globals.node,\n },\n },\n rules: {\n // TypeScript rules\n \"@typescript-eslint/no-unused-vars\": [\"error\", { argsIgnorePattern: \"^_\" }],\n \"@typescript-eslint/no-explicit-any\": \"warn\",\n \"@typescript-eslint/consistent-type-imports\": \"error\",\n\n // General rules\n \"no-console\": \"warn\",\n },\n },\n {\n ignores: [\"node_modules\", \"dist\", \"build\", \"coverage\"],\n }\n);\n`;\n}\n\n/**\n * Generate ESLint flat config content for JavaScript projects\n */\nfunction generateJsConfig(hasReactDep: boolean): string {\n if (hasReactDep) {\n return `import eslint from \"@eslint/js\";\nimport reactPlugin from \"eslint-plugin-react\";\nimport reactHooksPlugin from \"eslint-plugin-react-hooks\";\nimport globals from \"globals\";\n\nexport default [\n eslint.configs.recommended,\n {\n files: [\"**/*.{js,jsx}\"],\n languageOptions: {\n ecmaVersion: \"latest\",\n sourceType: \"module\",\n parserOptions: {\n ecmaFeatures: {\n jsx: true,\n },\n },\n globals: {\n ...globals.browser,\n ...globals.node,\n },\n },\n plugins: {\n react: reactPlugin,\n \"react-hooks\": reactHooksPlugin,\n },\n rules: {\n // React rules\n \"react/react-in-jsx-scope\": \"off\",\n \"react/prop-types\": \"warn\",\n \"react-hooks/rules-of-hooks\": \"error\",\n \"react-hooks/exhaustive-deps\": \"warn\",\n\n // General rules\n \"no-console\": \"warn\",\n \"no-unused-vars\": [\"error\", { argsIgnorePattern: \"^_\" }],\n },\n settings: {\n react: {\n version: \"detect\",\n },\n },\n },\n {\n ignores: [\"node_modules\", \"dist\", \"build\", \".next\", \"coverage\"],\n },\n];\n`;\n }\n\n return `import eslint from \"@eslint/js\";\nimport globals from \"globals\";\n\nexport default [\n eslint.configs.recommended,\n {\n files: [\"**/*.js\"],\n languageOptions: {\n ecmaVersion: \"latest\",\n sourceType: \"module\",\n globals: {\n ...globals.node,\n },\n },\n rules: {\n // General rules\n \"no-console\": \"warn\",\n \"no-unused-vars\": [\"error\", { argsIgnorePattern: \"^_\" }],\n },\n },\n {\n ignores: [\"node_modules\", \"dist\", \"build\", \"coverage\"],\n },\n];\n`;\n}\n\n/**\n * Get the ESLint dependencies to add to package.json\n */\nexport function getEslintDependencies(\n usesTypeScript: boolean,\n usesReact: boolean\n): Record<string, string> {\n const deps: Record<string, string> = {\n eslint: \"^9.0.0\",\n \"@eslint/js\": \"^9.0.0\",\n globals: \"^15.0.0\",\n };\n\n if (usesTypeScript) {\n deps[\"typescript-eslint\"] = \"^8.0.0\";\n }\n\n if (usesReact) {\n deps[\"eslint-plugin-react\"] = \"^7.35.0\";\n deps[\"eslint-plugin-react-hooks\"] = \"^5.0.0\";\n }\n\n return deps;\n}\n\n/**\n * Generate ESLint configuration file\n *\n * @param targetDir - The target directory to write to\n * @param usesTypeScript - Whether the project uses TypeScript\n * @param force - Force generation even if ESLint is already configured\n */\nexport async function generateEslint(\n targetDir: string,\n usesTypeScript: boolean,\n force: boolean = false\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n // Check if ESLint is already configured (unless force)\n if (!force && (await hasEslint(targetDir))) {\n result.skipped.push(\"eslint.config.js (ESLint already configured)\");\n return result;\n }\n\n // Detect React\n const usesReact = await hasReact(targetDir);\n\n // Generate appropriate config\n const config = usesTypeScript\n ? generateTsConfig(usesReact)\n : generateJsConfig(usesReact);\n\n // Write config file\n const configPath = join(targetDir, \"eslint.config.js\");\n const writeResult = await writeFileSafe(configPath, config);\n\n if (writeResult.backedUp) {\n result.backedUp.push(\"eslint.config.js\");\n }\n\n result.created.push(\"eslint.config.js\");\n\n return result;\n}\n","import { join } from \"node:path\";\nimport { writeFileSafe } from \"../utils/file-system.js\";\nimport type { GeneratorResult, PackageManagerInfo } from \"../types/config.js\";\n\n/**\n * Generate Quick Reference guide for developers\n */\nexport async function generateQuickReference(\n targetDir: string,\n pm: PackageManagerInfo\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const quickRefPath = join(targetDir, \".github\", \"QUICK_REFERENCE.md\");\n\n const content = `# RaftStack Quick Reference\n\n> One-page guide for the RaftStack Git workflow\n\n## 🚀 Daily Workflow\n\n### 1. Create a Branch\n\n\\`\\`\\`bash\n# Format: <type>/<short-description>\ngit checkout -b feature/user-authentication\ngit checkout -b bugfix/login-redirect\ngit checkout -b hotfix/payment-timeout\n\\`\\`\\`\n\n**Branch types:** \\`feature\\`, \\`bugfix\\`, \\`hotfix\\`, \\`chore\\`, \\`refactor\\`\n\n### 2. Make Commits\n\n\\`\\`\\`bash\n# Use the interactive commit tool\n${pm.run} commit\n\\`\\`\\`\n\nThis will prompt you for:\n- Type (feat, fix, docs, etc.)\n- Scope (optional)\n- Description\n- Body (optional)\n- **Task link (required)**\n\n### 3. Commit Message Format\n\n\\`\\`\\`\n✨ feat(auth): add user login form\n\n- Created LoginForm component\n- Added form validation\n- Integrated with API\n\nTask: https://app.asana.com/0/project/task\n\\`\\`\\`\n\n### 4. Create Pull Request\n\n\\`\\`\\`bash\ngit push -u origin feature/my-feature\n# Then create PR on GitHub\n\\`\\`\\`\n\n---\n\n## 📝 Commit Types\n\n| Type | Emoji | Use For |\n|------|-------|---------|\n| feat | ✨ | New feature |\n| fix | 🐛 | Bug fix |\n| docs | 📝 | Documentation |\n| style | 💄 | Formatting (no logic change) |\n| refactor | ♻️ | Code restructuring |\n| perf | ⚡ | Performance improvement |\n| test | ✅ | Adding tests |\n| build | 📦 | Build system changes |\n| ci | 👷 | CI configuration |\n| chore | 🔧 | Maintenance |\n\n---\n\n## ✅ PR Checklist\n\nBefore submitting:\n- [ ] Branch name follows convention\n- [ ] All commits have task links\n- [ ] Tests pass locally\n- [ ] PR description filled out\n- [ ] Size is reasonable (< 400 lines)\n\n---\n\n## 🔧 Useful Commands\n\n\\`\\`\\`bash\n# Interactive commit\n${pm.run} commit\n\n# Check compliance metrics\n${pm.exec} @raftlabs/raftstack metrics\n\n# Run linting\n${pm.run} lint\n\n# Run tests\n${pm.run} test\n\\`\\`\\`\n\n---\n\n## ❌ Common Mistakes\n\n| Wrong | Right |\n|-------|-------|\n| \\`Feature/UserAuth\\` | \\`feature/user-auth\\` |\n| \\`fixed bug\\` | \\`fix(auth): resolve login redirect\\` |\n| No task link | Always include \\`Task: <url>\\` |\n| 1000+ line PR | Split into smaller PRs |\n\n---\n\n## 📚 More Info\n\n- [CONTRIBUTING.md](../CONTRIBUTING.md) - Full contribution guide\n- [RaftStack Docs](https://github.com/Raft-Labs/raftstack) - CLI documentation\n\n---\n\n*Generated by RaftStack - Git workflow standardization for teams*\n`;\n\n const writeResult = await writeFileSafe(quickRefPath, content);\n\n if (writeResult.created) {\n if (writeResult.backedUp) {\n result.modified.push(\".github/QUICK_REFERENCE.md\");\n result.backedUp.push(\".github/QUICK_REFERENCE.md\");\n } else {\n result.created.push(\".github/QUICK_REFERENCE.md\");\n }\n } else {\n result.skipped.push(\".github/QUICK_REFERENCE.md\");\n }\n\n return result;\n}\n","import { execa } from \"execa\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/**\n * Check if directory is a git repository\n */\nexport async function isGitRepo(\n targetDir: string = process.cwd()\n): Promise<boolean> {\n // Quick check for .git directory\n if (existsSync(join(targetDir, \".git\"))) {\n return true;\n }\n\n // Fallback to git command (handles worktrees, etc.)\n try {\n await execa(\"git\", [\"rev-parse\", \"--git-dir\"], { cwd: targetDir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get the root directory of the git repository\n */\nexport async function getGitRoot(\n targetDir: string = process.cwd()\n): Promise<string | null> {\n try {\n const { stdout } = await execa(\"git\", [\"rev-parse\", \"--show-toplevel\"], {\n cwd: targetDir,\n });\n return stdout.trim();\n } catch {\n return null;\n }\n}\n\n/**\n * Get current branch name\n */\nexport async function getCurrentBranch(\n targetDir: string = process.cwd()\n): Promise<string | null> {\n try {\n const { stdout } = await execa(\"git\", [\"branch\", \"--show-current\"], {\n cwd: targetDir,\n });\n return stdout.trim() || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Check if gh CLI is available and authenticated\n */\nexport async function isGhCliAvailable(): Promise<boolean> {\n try {\n await execa(\"gh\", [\"auth\", \"status\"]);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get GitHub repository info (owner/repo)\n */\nexport async function getGitHubRepoInfo(\n targetDir: string = process.cwd()\n): Promise<{ owner: string; repo: string } | null> {\n try {\n const { stdout } = await execa(\"gh\", [\"repo\", \"view\", \"--json\", \"owner,name\"], {\n cwd: targetDir,\n });\n const data = JSON.parse(stdout);\n return {\n owner: data.owner.login,\n repo: data.name,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Initialize husky in the repository\n */\nexport async function initHusky(\n targetDir: string = process.cwd()\n): Promise<void> {\n await execa(\"npx\", [\"husky\", \"init\"], { cwd: targetDir });\n}\n\n/**\n * Run a git command\n */\nexport async function runGitCommand(\n args: string[],\n targetDir: string = process.cwd()\n): Promise<string> {\n const { stdout } = await execa(\"git\", args, { cwd: targetDir });\n return stdout;\n}\n","import * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { execa } from \"execa\";\nimport { isGhCliAvailable, getGitHubRepoInfo } from \"../utils/git.js\";\n\n/**\n * Merge strategy options\n */\nexport type MergeStrategy = \"rebase\" | \"squash\" | \"merge\";\n\n/**\n * Branch protection settings\n */\nexport interface BranchProtectionSettings {\n branch: string;\n requiredReviews: number;\n dismissStaleReviews: boolean;\n requireCodeOwners: boolean;\n requireStatusChecks: boolean;\n statusChecks: string[];\n requireConversationResolution: boolean;\n restrictPushes: boolean;\n blockForcePushes: boolean;\n blockDeletions: boolean;\n}\n\n/**\n * Repository settings for merge strategies\n */\nexport interface RepositorySettings {\n allowMergeCommit: boolean;\n allowSquashMerge: boolean;\n allowRebaseMerge: boolean;\n deleteBranchOnMerge: boolean;\n}\n\n/**\n * Default branch protection settings\n */\nfunction getDefaultSettings(branch: string): BranchProtectionSettings {\n return {\n branch,\n requiredReviews: 1,\n dismissStaleReviews: true,\n requireCodeOwners: true,\n requireStatusChecks: true,\n statusChecks: [\"check\"],\n requireConversationResolution: true,\n restrictPushes: false,\n blockForcePushes: true,\n blockDeletions: true,\n };\n}\n\n/**\n * Get repository settings based on merge strategy\n */\nfunction getMergeStrategySettings(strategy: MergeStrategy): RepositorySettings {\n switch (strategy) {\n case \"rebase\":\n return {\n allowMergeCommit: false,\n allowSquashMerge: false,\n allowRebaseMerge: true,\n deleteBranchOnMerge: true,\n };\n case \"squash\":\n return {\n allowMergeCommit: false,\n allowSquashMerge: true,\n allowRebaseMerge: false,\n deleteBranchOnMerge: true,\n };\n case \"merge\":\n return {\n allowMergeCommit: true,\n allowSquashMerge: false,\n allowRebaseMerge: false,\n deleteBranchOnMerge: true,\n };\n }\n}\n\n/**\n * Apply branch protection using gh CLI\n */\nasync function applyBranchProtection(\n owner: string,\n repo: string,\n settings: BranchProtectionSettings\n): Promise<void> {\n const args = [\n \"api\",\n \"-X\",\n \"PUT\",\n `/repos/${owner}/${repo}/branches/${settings.branch}/protection`,\n \"-f\",\n `required_pull_request_reviews[required_approving_review_count]=${settings.requiredReviews}`,\n \"-f\",\n `required_pull_request_reviews[dismiss_stale_reviews]=${settings.dismissStaleReviews}`,\n \"-f\",\n `required_pull_request_reviews[require_code_owner_reviews]=${settings.requireCodeOwners}`,\n \"-f\",\n `required_status_checks[strict]=true`,\n \"-f\",\n `enforce_admins=true`,\n \"-f\",\n `allow_force_pushes=${!settings.blockForcePushes}`,\n \"-f\",\n `allow_deletions=${!settings.blockDeletions}`,\n \"-f\",\n `required_conversation_resolution=${settings.requireConversationResolution}`,\n ];\n\n // Add status checks\n if (settings.requireStatusChecks && settings.statusChecks.length > 0) {\n for (const check of settings.statusChecks) {\n args.push(\"-f\", `required_status_checks[contexts][]=${check}`);\n }\n } else {\n args.push(\"-F\", \"required_status_checks=null\");\n }\n\n // Add restrictions (null means no restrictions beyond PRs)\n args.push(\"-F\", \"restrictions=null\");\n\n await execa(\"gh\", args);\n}\n\n/**\n * Apply repository merge settings using gh CLI\n */\nasync function applyMergeStrategy(\n owner: string,\n repo: string,\n settings: RepositorySettings\n): Promise<void> {\n const args = [\n \"api\",\n \"-X\",\n \"PATCH\",\n `/repos/${owner}/${repo}`,\n \"-f\",\n `allow_merge_commit=${settings.allowMergeCommit}`,\n \"-f\",\n `allow_squash_merge=${settings.allowSquashMerge}`,\n \"-f\",\n `allow_rebase_merge=${settings.allowRebaseMerge}`,\n \"-f\",\n `delete_branch_on_merge=${settings.deleteBranchOnMerge}`,\n ];\n\n await execa(\"gh\", args);\n}\n\n/**\n * Run the setup-protection command\n */\nexport async function runSetupProtection(\n targetDir: string = process.cwd()\n): Promise<void> {\n console.log();\n p.intro(pc.bgCyan(pc.black(\" Branch Protection Setup \")));\n\n // Check gh CLI\n const spinner = p.spinner();\n spinner.start(\"Checking GitHub CLI...\");\n\n const ghAvailable = await isGhCliAvailable();\n\n if (!ghAvailable) {\n spinner.stop(\"GitHub CLI not found or not authenticated\");\n console.log();\n p.log.error(pc.red(\"The GitHub CLI (gh) is required for this command.\"));\n p.log.info(\"Install it from: https://cli.github.com/\");\n p.log.info(\"Then run: gh auth login\");\n console.log();\n p.log.info(\n pc.dim(\n \"Alternatively, see .github/BRANCH_PROTECTION_SETUP.md for manual instructions.\"\n )\n );\n process.exit(1);\n }\n\n spinner.stop(\"GitHub CLI ready\");\n\n // Get repo info\n spinner.start(\"Getting repository info...\");\n const repoInfo = await getGitHubRepoInfo(targetDir);\n\n if (!repoInfo) {\n spinner.stop(\"Could not determine repository\");\n p.log.error(\n pc.red(\"Could not determine the GitHub repository for this directory.\")\n );\n p.log.info(\"Make sure you're in a git repository with a GitHub remote.\");\n process.exit(1);\n }\n\n spinner.stop(`Repository: ${pc.cyan(`${repoInfo.owner}/${repoInfo.repo}`)}`);\n\n // Ask which branches to protect\n const branches = await p.multiselect({\n message: \"Which branches need protection?\",\n options: [\n { value: \"main\", label: \"main\", hint: \"recommended\" },\n { value: \"master\", label: \"master\", hint: \"legacy default\" },\n { value: \"staging\", label: \"staging\", hint: \"staging environment\" },\n { value: \"production\", label: \"production\", hint: \"production environment\" },\n { value: \"development\", label: \"development\", hint: \"development branch\" },\n { value: \"develop\", label: \"develop\", hint: \"alternative dev branch\" },\n ],\n required: true,\n initialValues: [\"main\"],\n });\n\n if (p.isCancel(branches)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n // Ask for merge strategy\n const mergeStrategy = await p.select({\n message: \"Default merge strategy for PRs?\",\n options: [\n {\n value: \"rebase\",\n label: \"Rebase merge\",\n hint: \"recommended - clean linear history\",\n },\n {\n value: \"squash\",\n label: \"Squash merge\",\n hint: \"single commit per PR\",\n },\n {\n value: \"merge\",\n label: \"Merge commit\",\n hint: \"preserve all commits with merge commit\",\n },\n ],\n initialValue: \"rebase\",\n });\n\n if (p.isCancel(mergeStrategy)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n // Ask for number of required reviews\n const reviews = await p.text({\n message: \"How many approving reviews are required?\",\n placeholder: \"1\",\n initialValue: \"1\",\n validate: (value) => {\n const num = parseInt(value, 10);\n if (isNaN(num) || num < 0 || num > 6) {\n return \"Must be a number between 0 and 6\";\n }\n return undefined;\n },\n });\n\n if (p.isCancel(reviews)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n const requiredReviews = parseInt(reviews, 10);\n\n // Confirm settings\n const mergeStrategyLabels: Record<MergeStrategy, string> = {\n rebase: \"Rebase merge\",\n squash: \"Squash merge\",\n merge: \"Merge commit\",\n };\n\n console.log();\n p.note(\n [\n `${pc.cyan(\"Repository:\")} ${repoInfo.owner}/${repoInfo.repo}`,\n `${pc.cyan(\"Protected branches:\")} ${(branches as string[]).join(\", \")}`,\n `${pc.cyan(\"Merge strategy:\")} ${mergeStrategyLabels[mergeStrategy as MergeStrategy]}`,\n `${pc.cyan(\"Required reviews:\")} ${requiredReviews}`,\n `${pc.cyan(\"Dismiss stale reviews:\")} Yes`,\n `${pc.cyan(\"Require code owners:\")} Yes`,\n `${pc.cyan(\"Require status checks:\")} Yes`,\n `${pc.cyan(\"Block force pushes:\")} Yes`,\n `${pc.cyan(\"Block deletions:\")} Yes`,\n `${pc.cyan(\"Delete branch on merge:\")} Yes`,\n ].join(\"\\n\"),\n \"Branch Protection Settings\"\n );\n\n const confirmed = await p.confirm({\n message: \"Apply these branch protection rules?\",\n initialValue: true,\n });\n\n if (p.isCancel(confirmed) || !confirmed) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n // Apply merge strategy settings first\n spinner.start(\"Configuring merge strategy...\");\n\n try {\n const repoSettings = getMergeStrategySettings(mergeStrategy as MergeStrategy);\n await applyMergeStrategy(repoInfo.owner, repoInfo.repo, repoSettings);\n spinner.stop(\"Merge strategy configured!\");\n } catch (error) {\n spinner.stop(\"Failed to configure merge strategy\");\n const errorMsg = error instanceof Error ? error.message : \"Unknown error\";\n p.log.warn(pc.yellow(`Warning: Could not set merge strategy: ${errorMsg}`));\n p.log.info(pc.dim(\"Continuing with branch protection...\"));\n }\n\n // Apply branch protection for each branch\n const protectedBranches: string[] = [];\n const failedBranches: string[] = [];\n\n for (const branch of branches as string[]) {\n spinner.start(`Protecting branch: ${branch}...`);\n\n try {\n const settings = getDefaultSettings(branch);\n settings.requiredReviews = requiredReviews;\n\n await applyBranchProtection(repoInfo.owner, repoInfo.repo, settings);\n protectedBranches.push(branch);\n spinner.stop(`Protected: ${pc.green(branch)}`);\n } catch (error) {\n failedBranches.push(branch);\n spinner.stop(`Failed: ${pc.red(branch)}`);\n\n const errorMsg = error instanceof Error ? error.message : \"Unknown error\";\n p.log.warn(\n pc.yellow(\n `Could not protect ${branch}: ${errorMsg.includes(\"Branch not found\") ? \"branch does not exist\" : errorMsg}`\n )\n );\n }\n }\n\n // Show summary\n console.log();\n\n if (protectedBranches.length > 0) {\n p.log.success(\n pc.green(`Branch protection enabled for: ${pc.cyan(protectedBranches.join(\", \"))}`)\n );\n }\n\n if (failedBranches.length > 0) {\n p.log.warn(\n pc.yellow(\n `Could not protect: ${pc.red(failedBranches.join(\", \"))} (branches may not exist yet)`\n )\n );\n p.log.info(pc.dim(\"Create these branches first, then run this command again.\"));\n }\n\n if (protectedBranches.length > 0) {\n p.outro(pc.green(\"Setup complete!\"));\n } else {\n p.outro(pc.yellow(\"No branches were protected.\"));\n process.exit(1);\n }\n}\n","import { execa } from \"execa\";\nimport * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { isGitRepo } from \"../utils/git.js\";\n\ninterface MetricsResult {\n totalCommits: number;\n commitsWithTaskLinks: number;\n taskLinkCompliance: number;\n branchNames: string[];\n validBranches: number;\n invalidBranches: number;\n branchCompliance: number;\n}\n\n/**\n * Get commits from the last N days\n */\nasync function getRecentCommits(\n targetDir: string,\n days: number\n): Promise<string[]> {\n try {\n const { stdout } = await execa(\n \"git\",\n [\"log\", `--since=${days} days ago`, \"--oneline\", \"--no-merges\"],\n { cwd: targetDir }\n );\n return stdout.trim().split(\"\\n\").filter(Boolean);\n } catch {\n return [];\n }\n}\n\n/**\n * Get commit messages with full body\n */\nasync function getCommitMessages(\n targetDir: string,\n days: number\n): Promise<string[]> {\n try {\n const { stdout } = await execa(\n \"git\",\n [\n \"log\",\n `--since=${days} days ago`,\n \"--format=%B---COMMIT_SEPARATOR---\",\n \"--no-merges\",\n ],\n { cwd: targetDir }\n );\n return stdout.split(\"---COMMIT_SEPARATOR---\").filter((m) => m.trim());\n } catch {\n return [];\n }\n}\n\n/**\n * Get all branch names\n */\nasync function getBranchNames(targetDir: string): Promise<string[]> {\n try {\n const { stdout } = await execa(\n \"git\",\n [\"branch\", \"-a\", \"--format=%(refname:short)\"],\n { cwd: targetDir }\n );\n return stdout\n .trim()\n .split(\"\\n\")\n .filter(Boolean)\n .map((b) => b.replace(\"origin/\", \"\"))\n .filter((b, i, arr) => arr.indexOf(b) === i); // unique\n } catch {\n return [];\n }\n}\n\n/**\n * Validate branch name against convention\n */\nfunction isValidBranchName(name: string): boolean {\n const pattern =\n /^(main|staging|development|master)$|^(feature|bugfix|hotfix|chore|refactor)\\/[a-z0-9-]+$/;\n return pattern.test(name);\n}\n\n/**\n * Check if commit has task link\n */\nfunction hasTaskLink(message: string): boolean {\n return (\n message.includes(\"app.asana.com\") ||\n message.includes(\"Task:\") ||\n message.includes(\"task:\") ||\n message.includes(\"Closes #\") ||\n message.includes(\"Fixes #\")\n );\n}\n\n/**\n * Calculate metrics for the repository\n */\nasync function calculateMetrics(\n targetDir: string,\n days: number\n): Promise<MetricsResult> {\n const [commits, commitMessages, branches] = await Promise.all([\n getRecentCommits(targetDir, days),\n getCommitMessages(targetDir, days),\n getBranchNames(targetDir),\n ]);\n\n const commitsWithTaskLinks = commitMessages.filter(hasTaskLink).length;\n const validBranches = branches.filter(isValidBranchName);\n const invalidBranches = branches.filter((b) => !isValidBranchName(b));\n\n return {\n totalCommits: commits.length,\n commitsWithTaskLinks,\n taskLinkCompliance:\n commits.length > 0\n ? Math.round((commitsWithTaskLinks / commits.length) * 100)\n : 100,\n branchNames: branches,\n validBranches: validBranches.length,\n invalidBranches: invalidBranches.length,\n branchCompliance:\n branches.length > 0\n ? Math.round((validBranches.length / branches.length) * 100)\n : 100,\n };\n}\n\n/**\n * Format compliance percentage with color\n */\nfunction formatCompliance(percentage: number): string {\n if (percentage >= 90) return pc.green(`${percentage}%`);\n if (percentage >= 70) return pc.yellow(`${percentage}%`);\n return pc.red(`${percentage}%`);\n}\n\n/**\n * Run the metrics command\n */\nexport async function runMetrics(targetDir: string): Promise<void> {\n p.intro(pc.bgCyan(pc.black(\" RaftStack Metrics \")));\n\n if (!(await isGitRepo(targetDir))) {\n p.cancel(\"Not a git repository\");\n process.exit(1);\n }\n\n const daysOption = await p.select({\n message: \"Time period to analyze:\",\n options: [\n { value: 7, label: \"Last 7 days\" },\n { value: 14, label: \"Last 14 days\" },\n { value: 30, label: \"Last 30 days\" },\n { value: 90, label: \"Last 90 days\" },\n ],\n });\n\n if (p.isCancel(daysOption)) {\n p.cancel(\"Operation cancelled\");\n process.exit(0);\n }\n\n const days = daysOption as number;\n\n const spinner = p.spinner();\n spinner.start(\"Analyzing repository...\");\n\n const metrics = await calculateMetrics(targetDir, days);\n\n spinner.stop(\"Analysis complete\");\n\n p.note(\n `${pc.bold(\"Commits\")} (last ${days} days)\n Total: ${metrics.totalCommits}\n With task links: ${metrics.commitsWithTaskLinks}\n Compliance: ${formatCompliance(metrics.taskLinkCompliance)}\n\n${pc.bold(\"Branches\")}\n Total: ${metrics.branchNames.length}\n Valid naming: ${metrics.validBranches}\n Invalid naming: ${metrics.invalidBranches}\n Compliance: ${formatCompliance(metrics.branchCompliance)}`,\n \"Repository Metrics\"\n );\n\n if (metrics.invalidBranches > 0) {\n const invalidBranches = metrics.branchNames.filter(\n (b) => !isValidBranchName(b)\n );\n p.log.warn(\n `Invalid branch names:\\n ${invalidBranches.slice(0, 10).join(\"\\n \")}${\n invalidBranches.length > 10\n ? `\\n ... and ${invalidBranches.length - 10} more`\n : \"\"\n }`\n );\n }\n\n const overallCompliance = Math.round(\n (metrics.taskLinkCompliance + metrics.branchCompliance) / 2\n );\n\n if (overallCompliance >= 90) {\n p.outro(pc.green(\"✓ Excellent compliance! Keep up the good work.\"));\n } else if (overallCompliance >= 70) {\n p.outro(pc.yellow(\"⚠ Good progress, but there's room for improvement.\"));\n } else {\n p.outro(pc.red(\"✗ Compliance needs attention. Review the guidelines.\"));\n }\n}\n","{\n \"name\": \"@raftlabs/raftstack\",\n \"version\": \"1.3.0\",\n \"description\": \"CLI tool for setting up Git hooks, commit conventions, and GitHub integration\",\n \"type\": \"module\",\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"bin\": {\n \"raftstack\": \"./dist/cli.js\"\n },\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n }\n },\n \"files\": [\n \"dist\",\n \"templates\",\n \".claude/skills\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest\",\n \"test:run\": \"vitest run\",\n \"prepublishOnly\": \"pnpm build\",\n \"prepublish\": \"pnpm test:run && pnpm build\",\n \"pack:test\": \"pnpm pack --dry-run\",\n \"publish:test\": \"pnpm pack && tar -xvzf raftlabs-raftstack-*.tgz && rm -rf package raftlabs-raftstack-*.tgz\",\n \"release\": \"standard-version\",\n \"release:patch\": \"standard-version --release-as patch\",\n \"release:minor\": \"standard-version --release-as minor\",\n \"release:major\": \"standard-version --release-as major\",\n \"release:first\": \"standard-version --first-release\"\n },\n \"keywords\": [\n \"cli\",\n \"git-hooks\",\n \"husky\",\n \"commitlint\",\n \"lint-staged\",\n \"developer-experience\"\n ],\n \"author\": \"Aravind Jaimon <dev@aravindjaimon.com>\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/Raft-Labs/raftstack.git\"\n },\n \"homepage\": \"https://github.com/Raft-Labs/raftstack#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/Raft-Labs/raftstack/issues\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"registry\": \"https://registry.npmjs.org/\"\n },\n \"packageManager\": \"pnpm@10.23.0\",\n \"engines\": {\n \"node\": \">=18\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^20.10.0\",\n \"standard-version\": \"^9.5.0\",\n \"tsup\": \"^8.0.0\",\n \"typescript\": \"^5.3.0\",\n \"vitest\": \"^1.0.0\"\n },\n \"dependencies\": {\n \"@clack/prompts\": \"^0.7.0\",\n \"commander\": \"^12.0.0\",\n \"execa\": \"^8.0.0\",\n \"picocolors\": \"^1.0.0\"\n }\n}\n"],"mappings":"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","names":["p","pc","existsSync","join","join","existsSync","join","existsSync","readFile","join","existsSync","join","join","join","join","join","join","join","readFile","writeFile","existsSync","join","join","join","join","join","join","join","join","join","join","join","join","join","join","join","existsSync","copyFile","join","dirname","join","dirname","existsSync","copyFile","existsSync","readFile","join","join","join","existsSync","join","pc","spinner","p","pc","execa","execa","pc","spinner","execa","p","pc","execa","pc","spinner"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/commands/init.ts","../src/prompts/index.ts","../src/utils/detect-project.ts","../src/utils/detect-package-manager.ts","../src/generators/husky.ts","../src/utils/file-system.ts","../src/generators/commitlint.ts","../src/generators/cz-git.ts","../src/generators/lint-staged.ts","../src/utils/package-json.ts","../src/generators/branch-validation.ts","../src/generators/pr-template.ts","../src/generators/github-workflows.ts","../src/generators/codeowners.ts","../src/generators/ai-review.ts","../src/generators/branch-protection.ts","../src/generators/contributing.ts","../src/generators/prettier.ts","../src/generators/claude-skills.ts","../src/generators/eslint.ts","../src/generators/quick-reference.ts","../src/utils/git.ts","../src/commands/setup-protection.ts","../src/commands/metrics.ts","../package.json"],"sourcesContent":["import { Command } from \"commander\";\nimport { runInit } from \"./commands/init.js\";\nimport { runSetupProtection } from \"./commands/setup-protection.js\";\nimport { runMetrics } from \"./commands/metrics.js\";\nimport pkg from \"../package.json\" assert { type: \"json\" };\n\nconst program = new Command();\n\nprogram\n .name(\"raftstack\")\n .description(\n \"CLI tool for setting up Git hooks, commit conventions, and GitHub integration\"\n )\n .version(pkg.version);\n\nprogram\n .command(\"init\")\n .description(\"Initialize RaftStack configuration in your project\")\n .action(async () => {\n await runInit(process.cwd());\n });\n\nprogram\n .command(\"setup-protection\")\n .description(\"Configure GitHub branch protection rules via API\")\n .action(async () => {\n await runSetupProtection(process.cwd());\n });\n\nprogram\n .command(\"metrics\")\n .description(\"Analyze repository compliance with RaftStack conventions\")\n .action(async () => {\n await runMetrics(process.cwd());\n });\n\nprogram.parse();\n","import * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport type { GeneratorResult, RaftStackConfig } from \"../types/config.js\";\nimport { collectConfig } from \"../prompts/index.js\";\nimport {\n generateHuskyHooks,\n generateCommitlint,\n generateCzGit,\n generateLintStaged,\n generateBranchValidation,\n generatePRTemplate,\n generateGitHubWorkflows,\n generateCodeowners,\n generateAIReview,\n generateBranchProtectionDocs,\n generateContributing,\n generatePrettier,\n generateClaudeSkills,\n generateQuickReference,\n} from \"../generators/index.js\";\nimport {\n mergeDevDependencies,\n mergeScripts,\n readPackageJson,\n writePackageJson,\n RAFTSTACK_DEV_DEPENDENCIES,\n} from \"../utils/package-json.js\";\nimport { isGitRepo } from \"../utils/git.js\";\n\n/**\n * Merge generator results\n */\nfunction mergeResults(results: GeneratorResult[]): GeneratorResult {\n return results.reduce(\n (acc, result) => ({\n created: [...acc.created, ...result.created],\n modified: [...acc.modified, ...result.modified],\n skipped: [...acc.skipped, ...result.skipped],\n backedUp: [...acc.backedUp, ...result.backedUp],\n }),\n { created: [], modified: [], skipped: [], backedUp: [] }\n );\n}\n\n/**\n * Update package.json with required scripts and dependencies\n */\nasync function updateProjectPackageJson(\n targetDir: string,\n _config: RaftStackConfig\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n try {\n let pkg = await readPackageJson(targetDir);\n\n // Add scripts\n const scripts: Record<string, string> = {\n prepare: \"husky\",\n commit: \"czg\",\n };\n\n pkg = mergeScripts(pkg, scripts, false);\n\n // Add dev dependencies\n pkg = mergeDevDependencies(pkg, RAFTSTACK_DEV_DEPENDENCIES);\n\n await writePackageJson(pkg, targetDir);\n result.modified.push(\"package.json\");\n } catch (error) {\n result.skipped.push(\"package.json (error updating)\");\n }\n\n return result;\n}\n\n/**\n * Run the init command\n */\nexport async function runInit(targetDir: string = process.cwd()): Promise<void> {\n // Check if this is a git repository\n const isRepo = await isGitRepo(targetDir);\n if (!isRepo) {\n p.log.warn(\n pc.yellow(\n \"This directory is not a git repository. Some features may not work correctly.\"\n )\n );\n const proceed = await p.confirm({\n message: \"Continue anyway?\",\n initialValue: false,\n });\n\n if (p.isCancel(proceed) || !proceed) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n }\n\n // Collect configuration from user\n const config = await collectConfig(targetDir);\n\n if (!config) {\n return;\n }\n\n // Generate files with progress spinner\n const spinner = p.spinner();\n spinner.start(\"Generating configuration files...\");\n\n const results: GeneratorResult[] = [];\n\n try {\n // Core Git hooks and commit conventions\n results.push(\n await generateHuskyHooks(targetDir, config.projectType, config.packageManager)\n );\n results.push(await generateCommitlint(targetDir, config.asanaBaseUrl));\n results.push(await generateCzGit(targetDir, config.asanaBaseUrl));\n results.push(\n await generateLintStaged(\n targetDir,\n config.projectType,\n config.usesEslint,\n config.usesPrettier,\n config.usesTypeScript\n )\n );\n results.push(await generateBranchValidation(targetDir));\n\n // Prettier (only if not already configured)\n if (!config.usesPrettier) {\n results.push(await generatePrettier(targetDir));\n }\n\n // GitHub integration\n results.push(await generatePRTemplate(targetDir, !!config.asanaBaseUrl));\n results.push(\n await generateGitHubWorkflows(\n targetDir,\n config.projectType,\n config.usesTypeScript,\n config.usesEslint,\n config.packageManager\n )\n );\n results.push(await generateCodeowners(targetDir, config.codeowners));\n results.push(await generateAIReview(targetDir, config.aiReviewTool));\n results.push(await generateBranchProtectionDocs(targetDir));\n\n // Documentation\n results.push(\n await generateContributing(targetDir, !!config.asanaBaseUrl, config.packageManager)\n );\n results.push(await generateQuickReference(targetDir, config.packageManager));\n\n // Claude Code skills for AI-assisted development\n results.push(await generateClaudeSkills(targetDir));\n\n // Update package.json\n results.push(await updateProjectPackageJson(targetDir, config));\n\n spinner.stop(\"Configuration files generated!\");\n } catch (error) {\n spinner.stop(\"Error generating files\");\n p.log.error(\n pc.red(\n `Error: ${error instanceof Error ? error.message : \"Unknown error\"}`\n )\n );\n process.exit(1);\n }\n\n // Merge all results\n const finalResult = mergeResults(results);\n\n // Show summary\n console.log();\n\n if (finalResult.created.length > 0) {\n p.log.success(pc.green(\"Created files:\"));\n for (const file of finalResult.created) {\n console.log(` ${pc.dim(\"+\")} ${file}`);\n }\n }\n\n if (finalResult.modified.length > 0) {\n console.log();\n p.log.info(pc.blue(\"Modified files:\"));\n for (const file of finalResult.modified) {\n console.log(` ${pc.dim(\"~\")} ${file}`);\n }\n }\n\n if (finalResult.skipped.length > 0) {\n console.log();\n p.log.warn(pc.yellow(\"Skipped (already exist):\"));\n for (const file of finalResult.skipped) {\n console.log(` ${pc.dim(\"-\")} ${file}`);\n }\n }\n\n if (finalResult.backedUp.length > 0) {\n console.log();\n p.log.info(pc.dim(\"Backed up files:\"));\n for (const file of finalResult.backedUp) {\n console.log(` ${pc.dim(\"→\")} ${file}`);\n }\n }\n\n // Show next steps\n console.log();\n p.note(\n [\n `${pc.cyan(\"1.\")} Run ${pc.yellow(config.packageManager.install)} to install dependencies`,\n `${pc.cyan(\"2.\")} Review the generated configuration files`,\n `${pc.cyan(\"3.\")} Use ${pc.yellow(`${config.packageManager.run} commit`)} for interactive commits`,\n `${pc.cyan(\"4.\")} Set up branch protection rules (see .github/BRANCH_PROTECTION_SETUP.md)`,\n ].join(\"\\n\"),\n \"Next Steps\"\n );\n\n p.outro(pc.green(\"RaftStack setup complete! Happy coding! 🚀\"));\n}\n","import * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport type {\n AIReviewTool,\n DetectionResult,\n PackageManager,\n PackageManagerInfo,\n ProjectType,\n RaftStackConfig,\n} from \"../types/config.js\";\nimport {\n detectProjectType,\n getProjectTypeDescription,\n hasTypeScript,\n hasEslint,\n hasPrettier,\n detectPackageManager,\n getPackageManagerInfo,\n getPackageManagerDescription,\n} from \"../utils/detect-project.js\";\n\n/**\n * Show welcome banner\n */\nexport function showWelcome(): void {\n console.log();\n p.intro(pc.bgCyan(pc.black(\" RaftStack \")));\n console.log(\n pc.dim(\" Setting up Git hooks, commit conventions, and GitHub integration\\n\")\n );\n}\n\n/**\n * Prompt for project type confirmation\n */\nexport async function promptProjectType(\n detection: DetectionResult\n): Promise<ProjectType> {\n const description = getProjectTypeDescription(detection.type);\n const confidenceText =\n detection.confidence === \"high\"\n ? pc.green(\"high confidence\")\n : detection.confidence === \"medium\"\n ? pc.yellow(\"medium confidence\")\n : pc.red(\"low confidence\");\n\n const confirmed = await p.confirm({\n message: `Detected ${pc.cyan(description)} (${confidenceText}). Is this correct?`,\n initialValue: true,\n });\n\n if (p.isCancel(confirmed)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n if (confirmed) {\n return detection.type;\n }\n\n const selected = await p.select({\n message: \"Select your project type:\",\n options: [\n { value: \"nx\", label: \"NX Monorepo\" },\n { value: \"turbo\", label: \"Turborepo\" },\n { value: \"pnpm-workspace\", label: \"pnpm Workspace\" },\n { value: \"single\", label: \"Single Package\" },\n ],\n });\n\n if (p.isCancel(selected)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n return selected as ProjectType;\n}\n\n/**\n * Prompt for Asana configuration\n */\nexport async function promptAsanaConfig(): Promise<string | undefined> {\n const useAsana = await p.confirm({\n message: \"Do you want to link commits to Asana tasks?\",\n initialValue: true,\n });\n\n if (p.isCancel(useAsana)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n if (!useAsana) {\n return undefined;\n }\n\n const baseUrl = await p.text({\n message: \"Enter your Asana workspace URL:\",\n placeholder: \"https://app.asana.com/0/workspace-id\",\n validate: (value) => {\n if (!value) return \"URL is required\";\n if (!value.startsWith(\"https://app.asana.com/\")) {\n return \"URL must start with https://app.asana.com/\";\n }\n return undefined;\n },\n });\n\n if (p.isCancel(baseUrl)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n return baseUrl;\n}\n\n/**\n * Prompt for AI review tool selection\n */\nexport async function promptAIReview(): Promise<AIReviewTool> {\n const selected = await p.select({\n message: \"Select an AI code review tool (optional):\",\n options: [\n {\n value: \"none\",\n label: \"None\",\n hint: \"Skip AI review setup\",\n },\n {\n value: \"coderabbit\",\n label: \"CodeRabbit\",\n hint: \"AI-powered code review\",\n },\n {\n value: \"copilot\",\n label: \"GitHub Copilot\",\n hint: \"GitHub's AI code review\",\n },\n ],\n });\n\n if (p.isCancel(selected)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n return selected as AIReviewTool;\n}\n\n/**\n * Prompt for CODEOWNERS\n */\nexport async function promptCodeowners(): Promise<string[]> {\n const addOwners = await p.confirm({\n message: \"Do you want to set up CODEOWNERS for automatic PR reviewers?\",\n initialValue: true,\n });\n\n if (p.isCancel(addOwners)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n if (!addOwners) {\n return [];\n }\n\n const owners = await p.text({\n message: \"Enter GitHub usernames (comma-separated):\",\n placeholder: \"@username1, @username2\",\n validate: (value) => {\n if (!value.trim()) return \"At least one username is required\";\n return undefined;\n },\n });\n\n if (p.isCancel(owners)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n return owners\n .split(\",\")\n .map((u) => u.trim())\n .filter(Boolean)\n .map((u) => (u.startsWith(\"@\") ? u : `@${u}`));\n}\n\n/**\n * Prompt for package manager selection\n */\nexport async function promptPackageManager(\n targetDir: string\n): Promise<PackageManagerInfo> {\n // Try to auto-detect from lockfiles\n const detected = detectPackageManager(targetDir);\n\n if (detected) {\n const description = getPackageManagerDescription(detected);\n p.log.info(`Detected ${pc.cyan(description)} from lockfile`);\n return detected;\n }\n\n // No lockfile found - prompt user to select\n p.log.warn(\"No package manager lockfile detected\");\n\n const selected = await p.select({\n message: \"Select your package manager:\",\n options: [\n {\n value: \"npm\",\n label: \"npm\",\n hint: \"Node Package Manager (default)\",\n },\n {\n value: \"pnpm\",\n label: \"pnpm\",\n hint: \"Performant npm\",\n },\n {\n value: \"yarn\",\n label: \"Yarn Classic (1.x)\",\n hint: \"Classic Yarn\",\n },\n {\n value: \"yarn-berry\",\n label: \"Yarn Berry (2+)\",\n hint: \"Modern Yarn\",\n },\n ],\n });\n\n if (p.isCancel(selected)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n return getPackageManagerInfo(selected as PackageManager);\n}\n\n/**\n * Show summary before generating files\n */\nexport async function promptConfirmation(\n config: RaftStackConfig\n): Promise<boolean> {\n console.log();\n p.note(\n [\n `${pc.cyan(\"Project Type:\")} ${getProjectTypeDescription(config.projectType)}`,\n `${pc.cyan(\"Package Manager:\")} ${getPackageManagerDescription(config.packageManager)}`,\n `${pc.cyan(\"TypeScript:\")} ${config.usesTypeScript ? \"Yes\" : \"No\"}`,\n `${pc.cyan(\"ESLint:\")} ${config.usesEslint ? \"Yes\" : \"No\"}`,\n `${pc.cyan(\"Prettier:\")} ${config.usesPrettier ? \"Yes\" : \"No\"}`,\n `${pc.cyan(\"Asana Integration:\")} ${config.asanaBaseUrl ? \"Yes\" : \"No\"}`,\n `${pc.cyan(\"AI Review:\")} ${config.aiReviewTool === \"none\" ? \"None\" : config.aiReviewTool}`,\n `${pc.cyan(\"CODEOWNERS:\")} ${config.codeowners.length > 0 ? config.codeowners.join(\", \") : \"None\"}`,\n ].join(\"\\n\"),\n \"Configuration Summary\"\n );\n\n const confirmed = await p.confirm({\n message: \"Generate configuration files?\",\n initialValue: true,\n });\n\n if (p.isCancel(confirmed)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n return confirmed;\n}\n\n/**\n * Run full prompt flow and collect configuration\n */\nexport async function collectConfig(\n targetDir: string = process.cwd()\n): Promise<RaftStackConfig | null> {\n showWelcome();\n\n // Detect project type\n const detection = await detectProjectType(targetDir);\n const projectType = await promptProjectType(detection);\n\n // Detect package manager\n const packageManager = await promptPackageManager(targetDir);\n\n // Detect existing tooling\n const usesTypeScript = await hasTypeScript(targetDir);\n const usesEslint = await hasEslint(targetDir);\n const usesPrettier = await hasPrettier(targetDir);\n\n // Collect user preferences\n const asanaBaseUrl = await promptAsanaConfig();\n const aiReviewTool = await promptAIReview();\n const codeowners = await promptCodeowners();\n\n const config: RaftStackConfig = {\n projectType,\n packageManager,\n asanaBaseUrl,\n aiReviewTool,\n codeowners,\n usesTypeScript,\n usesEslint,\n usesPrettier,\n };\n\n // Confirm before proceeding\n const confirmed = await promptConfirmation(config);\n\n if (!confirmed) {\n p.cancel(\"Setup cancelled.\");\n return null;\n }\n\n return config;\n}\n","import { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { DetectionResult, ProjectType } from \"../types/config.js\";\n\ninterface IndicatorCheck {\n file: string;\n type: ProjectType;\n confidence: \"high\" | \"medium\";\n}\n\nconst INDICATORS: IndicatorCheck[] = [\n { file: \"nx.json\", type: \"nx\", confidence: \"high\" },\n { file: \"turbo.json\", type: \"turbo\", confidence: \"high\" },\n { file: \"pnpm-workspace.yaml\", type: \"pnpm-workspace\", confidence: \"high\" },\n { file: \"lerna.json\", type: \"pnpm-workspace\", confidence: \"medium\" },\n];\n\n/**\n * Detect the project type based on configuration files\n */\nexport async function detectProjectType(\n targetDir: string = process.cwd()\n): Promise<DetectionResult> {\n const foundIndicators: string[] = [];\n let detectedType: ProjectType = \"single\";\n let confidence: \"high\" | \"medium\" | \"low\" = \"low\";\n\n for (const indicator of INDICATORS) {\n const filePath = join(targetDir, indicator.file);\n if (existsSync(filePath)) {\n foundIndicators.push(indicator.file);\n\n // First match with highest confidence wins\n if (\n confidence === \"low\" ||\n (confidence === \"medium\" && indicator.confidence === \"high\")\n ) {\n detectedType = indicator.type;\n confidence = indicator.confidence;\n }\n }\n }\n\n // If we found indicators but couldn't determine type, it's still better than nothing\n if (foundIndicators.length > 0 && confidence === \"low\") {\n confidence = \"medium\";\n }\n\n return {\n type: detectedType,\n confidence,\n indicators: foundIndicators,\n };\n}\n\n/**\n * Check if project uses TypeScript\n */\nexport async function hasTypeScript(\n targetDir: string = process.cwd()\n): Promise<boolean> {\n const tsConfigPath = join(targetDir, \"tsconfig.json\");\n return existsSync(tsConfigPath);\n}\n\n/**\n * Check if project uses ESLint\n */\nexport async function hasEslint(\n targetDir: string = process.cwd()\n): Promise<boolean> {\n const eslintFiles = [\n \".eslintrc\",\n \".eslintrc.js\",\n \".eslintrc.cjs\",\n \".eslintrc.json\",\n \".eslintrc.yaml\",\n \".eslintrc.yml\",\n \"eslint.config.js\",\n \"eslint.config.mjs\",\n \"eslint.config.cjs\",\n ];\n\n for (const file of eslintFiles) {\n if (existsSync(join(targetDir, file))) {\n return true;\n }\n }\n\n // Also check package.json for eslintConfig\n try {\n const pkgPath = join(targetDir, \"package.json\");\n if (existsSync(pkgPath)) {\n const content = await readFile(pkgPath, \"utf-8\");\n const pkg = JSON.parse(content);\n if (pkg.eslintConfig) {\n return true;\n }\n }\n } catch {\n // Ignore parse errors\n }\n\n return false;\n}\n\n/**\n * Check if project uses Prettier\n */\nexport async function hasPrettier(\n targetDir: string = process.cwd()\n): Promise<boolean> {\n const prettierFiles = [\n \".prettierrc\",\n \".prettierrc.js\",\n \".prettierrc.cjs\",\n \".prettierrc.json\",\n \".prettierrc.yaml\",\n \".prettierrc.yml\",\n \".prettierrc.toml\",\n \"prettier.config.js\",\n \"prettier.config.cjs\",\n \"prettier.config.mjs\",\n ];\n\n for (const file of prettierFiles) {\n if (existsSync(join(targetDir, file))) {\n return true;\n }\n }\n\n // Also check package.json for prettier config\n try {\n const pkgPath = join(targetDir, \"package.json\");\n if (existsSync(pkgPath)) {\n const content = await readFile(pkgPath, \"utf-8\");\n const pkg = JSON.parse(content);\n if (pkg.prettier) {\n return true;\n }\n }\n } catch {\n // Ignore parse errors\n }\n\n return false;\n}\n\n/**\n * Check if project uses React\n */\nexport async function hasReact(\n targetDir: string = process.cwd()\n): Promise<boolean> {\n try {\n const pkgPath = join(targetDir, \"package.json\");\n if (existsSync(pkgPath)) {\n const content = await readFile(pkgPath, \"utf-8\");\n const pkg = JSON.parse(content);\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n return \"react\" in deps || \"react-dom\" in deps;\n }\n } catch {\n // Ignore parse errors\n }\n return false;\n}\n\n/**\n * Get a human-readable description of the project type\n */\nexport function getProjectTypeDescription(type: ProjectType): string {\n switch (type) {\n case \"nx\":\n return \"NX Monorepo\";\n case \"turbo\":\n return \"Turborepo\";\n case \"pnpm-workspace\":\n return \"pnpm Workspace\";\n case \"single\":\n return \"Single Package\";\n }\n}\n\n/**\n * Re-export package manager detection utilities for convenience\n */\nexport {\n detectPackageManager,\n detectYarnVersion,\n getPackageManagerInfo,\n getPackageManagerDescription,\n PACKAGE_MANAGERS,\n} from \"./detect-package-manager.js\";\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { PackageManager, PackageManagerInfo, PackageJson } from \"../types/config.js\";\n\n/**\n * Package manager metadata and commands\n */\nexport const PACKAGE_MANAGERS: Record<PackageManager, PackageManagerInfo> = {\n npm: {\n name: \"npm\",\n install: \"npm install\",\n run: \"npm run\",\n exec: \"npx\",\n lockfile: \"package-lock.json\",\n installFrozen: \"npm ci\",\n needsSetupAction: false,\n cacheKey: \"npm-${{ hashFiles('**/package-lock.json') }}\",\n },\n pnpm: {\n name: \"pnpm\",\n install: \"pnpm install\",\n run: \"pnpm\",\n exec: \"pnpm dlx\",\n lockfile: \"pnpm-lock.yaml\",\n installFrozen: \"pnpm install --frozen-lockfile\",\n needsSetupAction: true,\n cacheKey: \"pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}\",\n },\n yarn: {\n name: \"yarn\",\n install: \"yarn install\",\n run: \"yarn\",\n exec: \"yarn\",\n lockfile: \"yarn.lock\",\n installFrozen: \"yarn install --frozen-lockfile\",\n needsSetupAction: false,\n cacheKey: \"yarn-${{ hashFiles('**/yarn.lock') }}\",\n },\n \"yarn-berry\": {\n name: \"yarn-berry\",\n install: \"yarn install\",\n run: \"yarn\",\n exec: \"yarn dlx\",\n lockfile: \"yarn.lock\",\n installFrozen: \"yarn install --immutable\",\n needsSetupAction: false,\n cacheKey: \"yarn-${{ hashFiles('**/yarn.lock') }}\",\n },\n};\n\n/**\n * Detect Yarn version from package.json packageManager field\n * @param targetDir Directory to check\n * @returns \"yarn\" for 1.x, \"yarn-berry\" for 2+, or null if not specified\n */\nexport function detectYarnVersion(targetDir: string): \"yarn\" | \"yarn-berry\" | null {\n const packageJsonPath = join(targetDir, \"package.json\");\n\n if (!existsSync(packageJsonPath)) {\n return null;\n }\n\n try {\n const packageJson: PackageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"));\n const packageManager = packageJson.packageManager as string | undefined;\n\n if (!packageManager) {\n return null;\n }\n\n // Parse packageManager field (e.g., \"yarn@3.6.0\", \"yarn@1.22.19\")\n const match = packageManager.match(/^yarn@(\\d+)\\./);\n if (match) {\n const majorVersion = Number.parseInt(match[1], 10);\n return majorVersion >= 2 ? \"yarn-berry\" : \"yarn\";\n }\n\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Detect package manager from lockfiles\n * Priority: pnpm-lock.yaml > yarn.lock > package-lock.json\n * @param targetDir Directory to check for lockfiles\n * @returns Detected package manager or null if no lockfile found\n */\nexport function detectPackageManager(targetDir: string): PackageManagerInfo | null {\n // Check pnpm first (highest priority)\n if (existsSync(join(targetDir, \"pnpm-lock.yaml\"))) {\n return PACKAGE_MANAGERS.pnpm;\n }\n\n // Check yarn second\n if (existsSync(join(targetDir, \"yarn.lock\"))) {\n const yarnVersion = detectYarnVersion(targetDir);\n\n // If packageManager field specifies version, use that\n if (yarnVersion === \"yarn-berry\") {\n return PACKAGE_MANAGERS[\"yarn-berry\"];\n }\n\n // Default to Yarn 1.x (classic)\n return PACKAGE_MANAGERS.yarn;\n }\n\n // Check npm last (lowest priority)\n if (existsSync(join(targetDir, \"package-lock.json\"))) {\n return PACKAGE_MANAGERS.npm;\n }\n\n // No lockfile found\n return null;\n}\n\n/**\n * Get package manager metadata by name\n * @param name Package manager name\n * @returns Package manager metadata\n */\nexport function getPackageManagerInfo(name: PackageManager): PackageManagerInfo {\n return PACKAGE_MANAGERS[name];\n}\n\n/**\n * Get human-readable description of package manager\n * @param pm Package manager info\n * @returns Human-readable description\n */\nexport function getPackageManagerDescription(pm: PackageManagerInfo): string {\n switch (pm.name) {\n case \"npm\":\n return \"npm (Node Package Manager)\";\n case \"pnpm\":\n return \"pnpm (Performant npm)\";\n case \"yarn\":\n return \"Yarn Classic (1.x)\";\n case \"yarn-berry\":\n return \"Yarn Berry (2+)\";\n default:\n return pm.name;\n }\n}\n","import { join } from \"node:path\";\nimport type { GeneratorResult, PackageManagerInfo, ProjectType } from \"../types/config.js\";\nimport { ensureDir, writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Generate Husky pre-commit hook\n */\nfunction getPreCommitHook(projectType: ProjectType, pm: PackageManagerInfo): string {\n // NX uses its own lint-staged orchestration\n if (projectType === \"nx\") {\n return `#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\n\n${pm.exec} lint-staged\n`;\n }\n\n return `#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\n\n${pm.exec} lint-staged\n`;\n}\n\n/**\n * Generate Husky commit-msg hook for commitlint\n */\nfunction getCommitMsgHook(pm: PackageManagerInfo): string {\n return `#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\n\n${pm.exec} --no -- commitlint --edit \"$1\"\n`;\n}\n\n/**\n * Generate Husky pre-push hook for branch validation\n */\nfunction getPrePushHook(pm: PackageManagerInfo): string {\n return `#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\n\n${pm.exec} validate-branch-name\n`;\n}\n\n/**\n * Generate all Husky hooks\n */\nexport async function generateHuskyHooks(\n targetDir: string,\n projectType: ProjectType,\n pm: PackageManagerInfo\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const huskyDir = join(targetDir, \".husky\");\n await ensureDir(huskyDir);\n\n // Pre-commit hook\n const preCommitPath = join(huskyDir, \"pre-commit\");\n const preCommitResult = await writeFileSafe(\n preCommitPath,\n getPreCommitHook(projectType, pm),\n { executable: true, backup: true }\n );\n if (preCommitResult.created) {\n result.created.push(\".husky/pre-commit\");\n if (preCommitResult.backedUp) {\n result.backedUp.push(preCommitResult.backedUp);\n }\n }\n\n // Commit-msg hook\n const commitMsgPath = join(huskyDir, \"commit-msg\");\n const commitMsgResult = await writeFileSafe(\n commitMsgPath,\n getCommitMsgHook(pm),\n { executable: true, backup: true }\n );\n if (commitMsgResult.created) {\n result.created.push(\".husky/commit-msg\");\n if (commitMsgResult.backedUp) {\n result.backedUp.push(commitMsgResult.backedUp);\n }\n }\n\n // Pre-push hook\n const prePushPath = join(huskyDir, \"pre-push\");\n const prePushResult = await writeFileSafe(prePushPath, getPrePushHook(pm), {\n executable: true,\n backup: true,\n });\n if (prePushResult.created) {\n result.created.push(\".husky/pre-push\");\n if (prePushResult.backedUp) {\n result.backedUp.push(prePushResult.backedUp);\n }\n }\n\n return result;\n}\n","import { existsSync } from \"node:fs\";\nimport {\n mkdir,\n readFile,\n writeFile,\n copyFile,\n chmod,\n} from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\n\n/**\n * Ensure a directory exists, creating it if necessary\n */\nexport async function ensureDir(dirPath: string): Promise<void> {\n if (!existsSync(dirPath)) {\n await mkdir(dirPath, { recursive: true });\n }\n}\n\n/**\n * Backup a file if it exists\n * Returns the backup path if a backup was created, null otherwise\n */\nexport async function backupFile(filePath: string): Promise<string | null> {\n if (!existsSync(filePath)) {\n return null;\n }\n\n const backupPath = `${filePath}.backup`;\n await copyFile(filePath, backupPath);\n return backupPath;\n}\n\n/**\n * Write a file safely with optional backup\n */\nexport async function writeFileSafe(\n filePath: string,\n content: string,\n options: {\n backup?: boolean;\n overwrite?: boolean;\n executable?: boolean;\n } = {}\n): Promise<{ created: boolean; backedUp: string | null }> {\n const { backup = true, overwrite = true, executable = false } = options;\n\n // Check if file exists\n const exists = existsSync(filePath);\n\n // If file exists and we shouldn't overwrite, skip\n if (exists && !overwrite) {\n return { created: false, backedUp: null };\n }\n\n // Backup existing file if requested\n let backedUp: string | null = null;\n if (exists && backup) {\n backedUp = await backupFile(filePath);\n }\n\n // Ensure directory exists\n await ensureDir(dirname(filePath));\n\n // Write the file\n await writeFile(filePath, content, \"utf-8\");\n\n // Make executable if requested\n if (executable) {\n await chmod(filePath, 0o755);\n }\n\n return { created: true, backedUp };\n}\n\n/**\n * Read a file, returning null if it doesn't exist\n */\nexport async function readFileSafe(filePath: string): Promise<string | null> {\n if (!existsSync(filePath)) {\n return null;\n }\n return readFile(filePath, \"utf-8\");\n}\n\n/**\n * Check if a file exists\n */\nexport function fileExists(filePath: string): boolean {\n return existsSync(filePath);\n}\n\n/**\n * Get relative path from target directory\n */\nexport function getRelativePath(\n filePath: string,\n targetDir: string = process.cwd()\n): string {\n if (filePath.startsWith(targetDir)) {\n return filePath.slice(targetDir.length + 1);\n }\n return filePath;\n}\n\n/**\n * Join paths and normalize\n */\nexport function joinPath(...paths: string[]): string {\n return join(...paths);\n}\n","import { join } from \"node:path\";\nimport type { GeneratorResult } from \"../types/config.js\";\nimport { writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Generate commitlint configuration\n * Note: Asana task link uses level 1 (warning) not level 2 (error)\n * Commits without task links will show a warning but won't be blocked\n */\nfunction getCommitlintConfig(asanaBaseUrl?: string): string {\n const baseConfig = `// @ts-check\n\n/** @type {import('@commitlint/types').UserConfig} */\nconst config = {\n extends: ['@commitlint/config-conventional'],\n rules: {\n // Type must be one of the conventional types\n 'type-enum': [\n 2,\n 'always',\n [\n 'feat', // New feature\n 'fix', // Bug fix\n 'docs', // Documentation changes\n 'style', // Code style changes (formatting, etc.)\n 'refactor', // Code refactoring\n 'perf', // Performance improvements\n 'test', // Adding or updating tests\n 'build', // Build system changes\n 'ci', // CI configuration changes\n 'chore', // Other changes (maintenance, etc.)\n 'revert', // Reverting changes\n ],\n ],\n // Subject should not be empty\n 'subject-empty': [2, 'never'],\n // Type should not be empty\n 'type-empty': [2, 'never'],\n // Subject should be lowercase\n 'subject-case': [2, 'always', 'lower-case'],\n // Header max length\n 'header-max-length': [2, 'always', 100],\n },`;\n\n if (asanaBaseUrl) {\n // Add Asana task link validation as a WARNING (level 1), not error (level 2)\n return `${baseConfig}\n plugins: [\n {\n rules: {\n 'asana-task-link': ({ body, footer }) => {\n const fullMessage = [body, footer].filter(Boolean).join('\\\\n');\n const asanaPattern = /https:\\\\/\\\\/app\\\\.asana\\\\.com\\\\/\\\\d+\\\\/\\\\d+\\\\/\\\\d+/;\n const hasAsanaLink = asanaPattern.test(fullMessage);\n return [\n hasAsanaLink,\n hasAsanaLink\n ? null\n : 'Consider adding an Asana task link in the commit body or footer (e.g., Task: https://app.asana.com/0/...)',\n ];\n },\n },\n },\n ],\n};\n\n// Enable the Asana task link rule as a WARNING (level 1)\n// Change to level 2 if you want to BLOCK commits without Asana links\nconfig.rules['asana-task-link'] = [1, 'always'];\n\nmodule.exports = config;\n`;\n }\n\n return `${baseConfig}\n};\n\nmodule.exports = config;\n`;\n}\n\n/**\n * Generate commitlint configuration file\n */\nexport async function generateCommitlint(\n targetDir: string,\n asanaBaseUrl?: string\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const configPath = join(targetDir, \"commitlint.config.js\");\n const writeResult = await writeFileSafe(\n configPath,\n getCommitlintConfig(asanaBaseUrl),\n { backup: true }\n );\n\n if (writeResult.created) {\n result.created.push(\"commitlint.config.js\");\n if (writeResult.backedUp) {\n result.backedUp.push(writeResult.backedUp);\n }\n }\n\n return result;\n}\n","import { join } from \"node:path\";\nimport type { GeneratorResult } from \"../types/config.js\";\nimport { writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Generate cz-git configuration\n */\nfunction getCzGitConfig(asanaBaseUrl?: string): string {\n const asanaSection = asanaBaseUrl\n ? `\n // Asana task reference settings\n allowCustomIssuePrefix: true,\n allowEmptyIssuePrefix: true,\n issuePrefixes: [\n { value: 'asana', name: 'asana: Link to Asana task' },\n { value: 'closes', name: 'closes: Close an issue' },\n { value: 'fixes', name: 'fixes: Fix an issue' },\n ],\n customIssuePrefixAlign: 'top',`\n : `\n allowCustomIssuePrefix: false,\n allowEmptyIssuePrefix: true,`;\n\n return `// @ts-check\n\n/** @type {import('cz-git').UserConfig} */\nmodule.exports = {\n extends: ['@commitlint/config-conventional'],\n prompt: {\n alias: {\n fd: 'docs: fix typos',\n ur: 'docs: update README',\n },\n messages: {\n type: \"Select the type of change you're committing:\",\n scope: 'Denote the scope of this change (optional):',\n customScope: 'Denote the scope of this change:',\n subject: 'Write a short, imperative description of the change:\\\\n',\n body: 'Provide a longer description of the change (optional). Use \"|\" to break new line:\\\\n',\n breaking: 'List any BREAKING CHANGES (optional). Use \"|\" to break new line:\\\\n',\n footerPrefixSelect: 'Select the ISSUES type of change (optional):',\n customFooterPrefix: 'Input ISSUES prefix:',\n footer: 'List any ISSUES affected by this change (optional). E.g.: #31, #34:\\\\n',\n confirmCommit: 'Are you sure you want to proceed with the commit above?',\n },\n types: [\n { value: 'feat', name: 'feat: ✨ A new feature', emoji: ':sparkles:' },\n { value: 'fix', name: 'fix: 🐛 A bug fix', emoji: ':bug:' },\n { value: 'docs', name: 'docs: 📝 Documentation changes', emoji: ':memo:' },\n { value: 'style', name: 'style: 💄 Code style changes', emoji: ':lipstick:' },\n { value: 'refactor', name: 'refactor: ♻️ Code refactoring', emoji: ':recycle:' },\n { value: 'perf', name: 'perf: ⚡️ Performance improvements', emoji: ':zap:' },\n { value: 'test', name: 'test: ✅ Adding or updating tests', emoji: ':white_check_mark:' },\n { value: 'build', name: 'build: 📦 Build system changes', emoji: ':package:' },\n { value: 'ci', name: 'ci: 🎡 CI configuration changes', emoji: ':ferris_wheel:' },\n { value: 'chore', name: 'chore: 🔧 Other changes', emoji: ':wrench:' },\n { value: 'revert', name: 'revert: ⏪ Reverting changes', emoji: ':rewind:' },\n ],\n useEmoji: true,\n emojiAlign: 'center',\n useAI: false,\n aiNumber: 1,\n themeColorCode: '',\n scopes: [],\n allowCustomScopes: true,\n allowEmptyScopes: true,\n customScopesAlign: 'bottom',\n customScopesAlias: 'custom',\n emptyScopesAlias: 'empty',\n upperCaseSubject: false,\n markBreakingChangeMode: false,\n allowBreakingChanges: ['feat', 'fix'],\n breaklineNumber: 100,\n breaklineChar: '|',\n skipQuestions: [],${asanaSection}\n confirmColorize: true,\n minSubjectLength: 0,\n defaultBody: '',\n defaultIssues: '',\n defaultScope: '',\n defaultSubject: '',\n },\n};\n`;\n}\n\n/**\n * Generate cz-git configuration file\n */\nexport async function generateCzGit(\n targetDir: string,\n asanaBaseUrl?: string\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const configPath = join(targetDir, \".czrc\");\n const writeResult = await writeFileSafe(\n configPath,\n JSON.stringify({ path: \"node_modules/cz-git\" }, null, 2) + \"\\n\",\n { backup: true }\n );\n\n if (writeResult.created) {\n result.created.push(\".czrc\");\n if (writeResult.backedUp) {\n result.backedUp.push(writeResult.backedUp);\n }\n }\n\n // Also generate the cz.config.js for more detailed config\n const czConfigPath = join(targetDir, \"cz.config.js\");\n const czConfigResult = await writeFileSafe(\n czConfigPath,\n getCzGitConfig(asanaBaseUrl),\n { backup: true }\n );\n\n if (czConfigResult.created) {\n result.created.push(\"cz.config.js\");\n if (czConfigResult.backedUp) {\n result.backedUp.push(czConfigResult.backedUp);\n }\n }\n\n return result;\n}\n","import { join } from \"node:path\";\nimport type { GeneratorResult, ProjectType } from \"../types/config.js\";\nimport { writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Generate lint-staged configuration based on project type\n */\nfunction getLintStagedConfig(\n projectType: ProjectType,\n usesEslint: boolean,\n usesPrettier: boolean,\n usesTypeScript: boolean\n): string {\n const rules: Record<string, string | string[]> = {};\n\n // TypeScript/JavaScript files\n if (usesTypeScript) {\n const tsCommands: string[] = [];\n if (usesEslint) {\n tsCommands.push(\"eslint --fix\");\n }\n if (usesPrettier) {\n tsCommands.push(\"prettier --write\");\n }\n if (tsCommands.length > 0) {\n rules[\"*.{ts,tsx}\"] = tsCommands;\n }\n }\n\n // JavaScript files\n const jsCommands: string[] = [];\n if (usesEslint) {\n jsCommands.push(\"eslint --fix\");\n }\n if (usesPrettier) {\n jsCommands.push(\"prettier --write\");\n }\n if (jsCommands.length > 0) {\n rules[\"*.{js,jsx,mjs,cjs}\"] = jsCommands;\n }\n\n // JSON, MD, YAML files (Prettier only)\n if (usesPrettier) {\n rules[\"*.{json,md,yaml,yml}\"] = \"prettier --write\";\n }\n\n // CSS/SCSS files\n if (usesPrettier) {\n rules[\"*.{css,scss,less}\"] = \"prettier --write\";\n }\n\n // NX-specific configuration\n if (projectType === \"nx\") {\n return `// @ts-check\n\n/**\n * @type {import('lint-staged').Config}\n */\nmodule.exports = {\n${Object.entries(rules)\n .map(([pattern, commands]) => {\n const cmdStr = Array.isArray(commands)\n ? JSON.stringify(commands)\n : JSON.stringify([commands]);\n return ` '${pattern}': ${cmdStr},`;\n })\n .join(\"\\n\")}\n};\n`;\n }\n\n // Standard configuration\n return `// @ts-check\n\n/**\n * @type {import('lint-staged').Config}\n */\nmodule.exports = {\n${Object.entries(rules)\n .map(([pattern, commands]) => {\n const cmdStr = Array.isArray(commands)\n ? JSON.stringify(commands)\n : JSON.stringify([commands]);\n return ` '${pattern}': ${cmdStr},`;\n })\n .join(\"\\n\")}\n};\n`;\n}\n\n/**\n * Generate lint-staged configuration file\n */\nexport async function generateLintStaged(\n targetDir: string,\n projectType: ProjectType,\n usesEslint: boolean,\n usesPrettier: boolean,\n usesTypeScript: boolean\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const configPath = join(targetDir, \".lintstagedrc.js\");\n const writeResult = await writeFileSafe(\n configPath,\n getLintStagedConfig(projectType, usesEslint, usesPrettier, usesTypeScript),\n { backup: true }\n );\n\n if (writeResult.created) {\n result.created.push(\".lintstagedrc.js\");\n if (writeResult.backedUp) {\n result.backedUp.push(writeResult.backedUp);\n }\n }\n\n return result;\n}\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { PackageJson, PackageManagerInfo } from \"../types/config.js\";\n\n/**\n * Read package.json from a directory\n */\nexport async function readPackageJson(\n targetDir: string = process.cwd()\n): Promise<PackageJson> {\n const pkgPath = join(targetDir, \"package.json\");\n\n if (!existsSync(pkgPath)) {\n throw new Error(`No package.json found in ${targetDir}`);\n }\n\n const content = await readFile(pkgPath, \"utf-8\");\n return JSON.parse(content) as PackageJson;\n}\n\n/**\n * Write package.json to a directory\n */\nexport async function writePackageJson(\n pkg: PackageJson,\n targetDir: string = process.cwd()\n): Promise<void> {\n const pkgPath = join(targetDir, \"package.json\");\n const content = JSON.stringify(pkg, null, 2) + \"\\n\";\n await writeFile(pkgPath, content, \"utf-8\");\n}\n\n/**\n * Merge scripts into package.json without overwriting existing ones\n */\nexport function mergeScripts(\n pkg: PackageJson,\n scripts: Record<string, string>,\n overwrite: boolean = false\n): PackageJson {\n const existingScripts = pkg.scripts || {};\n const newScripts: Record<string, string> = { ...existingScripts };\n\n for (const [name, command] of Object.entries(scripts)) {\n if (overwrite || !existingScripts[name]) {\n newScripts[name] = command;\n }\n }\n\n return {\n ...pkg,\n scripts: newScripts,\n };\n}\n\n/**\n * Merge devDependencies into package.json\n */\nexport function mergeDevDependencies(\n pkg: PackageJson,\n deps: Record<string, string>\n): PackageJson {\n const existingDeps = pkg.devDependencies || {};\n\n return {\n ...pkg,\n devDependencies: {\n ...existingDeps,\n ...deps,\n },\n };\n}\n\n/**\n * Add a config section to package.json (e.g., lint-staged, validate-branch-name)\n */\nexport function addPackageJsonConfig<T>(\n pkg: PackageJson,\n key: string,\n config: T,\n overwrite: boolean = false\n): PackageJson {\n if (!overwrite && pkg[key]) {\n return pkg;\n }\n\n return {\n ...pkg,\n [key]: config,\n };\n}\n\n/**\n * Update package.json with multiple changes at once\n */\nexport async function updatePackageJson(\n targetDir: string,\n updater: (pkg: PackageJson) => PackageJson\n): Promise<PackageJson> {\n const pkg = await readPackageJson(targetDir);\n const updated = updater(pkg);\n await writePackageJson(updated, targetDir);\n return updated;\n}\n\n/**\n * Dependencies that RaftStack will install in the target project\n */\nexport const RAFTSTACK_DEV_DEPENDENCIES: Record<string, string> = {\n \"@commitlint/cli\": \"^18.0.0\",\n \"@commitlint/config-conventional\": \"^18.0.0\",\n \"cz-git\": \"^1.8.0\",\n czg: \"^1.8.0\",\n husky: \"^9.0.0\",\n \"lint-staged\": \"^15.0.0\",\n \"validate-branch-name\": \"^1.3.0\",\n};\n\n/**\n * Get package manager-specific scripts\n * This can be used in the future to add PM-specific setup scripts\n */\nexport function getPackageManagerScripts(\n _pm: PackageManagerInfo\n): Record<string, string> {\n // Currently, all package managers use the same scripts\n // This function is here for future extensibility if we need\n // different scripts for different package managers\n return {\n commit: \"czg\",\n prepare: \"husky\",\n };\n}\n","import type { GeneratorResult } from \"../types/config.js\";\nimport {\n addPackageJsonConfig,\n readPackageJson,\n writePackageJson,\n} from \"../utils/package-json.js\";\n\n/**\n * Branch naming pattern configuration\n */\ninterface BranchValidationConfig {\n pattern: string;\n errorMsg: string;\n}\n\n/**\n * Get the default branch validation configuration\n */\nfunction getBranchValidationConfig(): BranchValidationConfig {\n return {\n pattern:\n \"^(main|master|develop|staging|production)$|^(feature|fix|hotfix|bugfix|release|chore|docs|refactor|test|ci)\\\\/[a-z0-9._-]+$\",\n errorMsg:\n \"Branch name must follow pattern: feature/*, fix/*, hotfix/*, bugfix/*, release/*, chore/*, docs/*, refactor/*, test/*, ci/* or be main/master/develop/staging/production\",\n };\n}\n\n/**\n * Add validate-branch-name configuration to package.json\n */\nexport async function generateBranchValidation(\n targetDir: string\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n try {\n const pkg = await readPackageJson(targetDir);\n const config = getBranchValidationConfig();\n\n const updatedPkg = addPackageJsonConfig(\n pkg,\n \"validate-branch-name\",\n config,\n false // Don't overwrite if exists\n );\n\n // Check if we actually added something\n if (JSON.stringify(pkg) !== JSON.stringify(updatedPkg)) {\n await writePackageJson(updatedPkg, targetDir);\n result.modified.push(\"package.json (validate-branch-name)\");\n } else {\n result.skipped.push(\"validate-branch-name config (already exists)\");\n }\n } catch (error) {\n // If package.json doesn't exist or can't be read, skip\n result.skipped.push(\"validate-branch-name config (no package.json)\");\n }\n\n return result;\n}\n","import { join } from \"node:path\";\nimport type { GeneratorResult } from \"../types/config.js\";\nimport { ensureDir, writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Get the PR template content\n */\nfunction getPRTemplate(hasAsana: boolean): string {\n const asanaSection = hasAsana\n ? `## Asana Task\n<!-- Link to the Asana task -->\n- [ ] https://app.asana.com/0/...\n\n`\n : \"\";\n\n return `## Description\n<!-- Provide a brief description of the changes in this PR -->\n\n## Type of Change\n<!-- Mark the appropriate option with an \"x\" -->\n- [ ] 🐛 Bug fix (non-breaking change that fixes an issue)\n- [ ] ✨ New feature (non-breaking change that adds functionality)\n- [ ] 💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)\n- [ ] 📝 Documentation update\n- [ ] 🔧 Configuration change\n- [ ] ♻️ Refactoring (no functional changes)\n- [ ] ✅ Test update\n\n${asanaSection}## Changes Made\n<!-- List the specific changes made in this PR -->\n-\n\n## Testing\n<!-- Describe how you tested your changes -->\n- [ ] Unit tests added/updated\n- [ ] Integration tests added/updated\n- [ ] Manual testing performed\n\n## Screenshots (if applicable)\n<!-- Add screenshots to help explain your changes -->\n\n## Checklist\n- [ ] My code follows the project's coding standards\n- [ ] I have performed a self-review of my code\n- [ ] I have commented my code, particularly in hard-to-understand areas\n- [ ] I have made corresponding changes to the documentation\n- [ ] My changes generate no new warnings\n- [ ] Any dependent changes have been merged and published\n\n## Additional Notes\n<!-- Add any additional information that reviewers should know -->\n`;\n}\n\n/**\n * Generate GitHub PR template\n */\nexport async function generatePRTemplate(\n targetDir: string,\n hasAsana: boolean\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const githubDir = join(targetDir, \".github\");\n await ensureDir(githubDir);\n\n const templatePath = join(githubDir, \"PULL_REQUEST_TEMPLATE.md\");\n const writeResult = await writeFileSafe(\n templatePath,\n getPRTemplate(hasAsana),\n { backup: true }\n );\n\n if (writeResult.created) {\n result.created.push(\".github/PULL_REQUEST_TEMPLATE.md\");\n if (writeResult.backedUp) {\n result.backedUp.push(writeResult.backedUp);\n }\n }\n\n return result;\n}\n","import { join } from \"node:path\";\nimport type { GeneratorResult, PackageManagerInfo, ProjectType } from \"../types/config.js\";\nimport { ensureDir, writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Get the PR checks workflow content\n */\nfunction getPRChecksWorkflow(\n projectType: ProjectType,\n usesTypeScript: boolean,\n usesEslint: boolean,\n pm: PackageManagerInfo\n): string {\n const steps: string[] = [];\n\n // Checkout\n steps.push(` - name: Checkout\n uses: actions/checkout@v4`);\n\n // Setup Node\n steps.push(`\n - name: Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: '20'`);\n\n // Setup pnpm (only if needed)\n if (pm.needsSetupAction) {\n steps.push(`\n - name: Setup pnpm\n uses: pnpm/action-setup@v3\n with:\n version: 9`);\n }\n\n // Install dependencies\n steps.push(`\n - name: Install dependencies\n run: ${pm.installFrozen}`);\n\n // TypeScript check\n if (usesTypeScript) {\n steps.push(`\n - name: Type check\n run: ${pm.run} typecheck`);\n }\n\n // ESLint\n if (usesEslint) {\n steps.push(`\n - name: Lint\n run: ${pm.run} lint`);\n }\n\n // Build (for NX/Turbo, use their commands)\n if (projectType === \"nx\") {\n steps.push(`\n - name: Build\n run: ${pm.run} nx affected --target=build --parallel=3`);\n } else if (projectType === \"turbo\") {\n steps.push(`\n - name: Build\n run: ${pm.run} turbo build`);\n } else {\n steps.push(`\n - name: Build\n run: ${pm.run} build`);\n }\n\n // Tests\n if (projectType === \"nx\") {\n steps.push(`\n - name: Test\n run: ${pm.run} nx affected --target=test --parallel=3`);\n } else if (projectType === \"turbo\") {\n steps.push(`\n - name: Test\n run: ${pm.run} turbo test`);\n } else {\n steps.push(`\n - name: Test\n run: ${pm.run} test`);\n }\n\n return `name: PR Checks\n\non:\n pull_request:\n branches: [main, master, develop]\n\nconcurrency:\n group: \\${{ github.workflow }}-\\${{ github.ref }}\n cancel-in-progress: true\n\njobs:\n check:\n name: Check\n runs-on: ubuntu-latest\n steps:\n${steps.join(\"\\n\")}\n`;\n}\n\n/**\n * Generate GitHub workflow files\n */\nexport async function generateGitHubWorkflows(\n targetDir: string,\n projectType: ProjectType,\n usesTypeScript: boolean,\n usesEslint: boolean,\n pm: PackageManagerInfo\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const workflowsDir = join(targetDir, \".github\", \"workflows\");\n await ensureDir(workflowsDir);\n\n // PR Checks workflow\n const prChecksPath = join(workflowsDir, \"pr-checks.yml\");\n const writeResult = await writeFileSafe(\n prChecksPath,\n getPRChecksWorkflow(projectType, usesTypeScript, usesEslint, pm),\n { backup: true }\n );\n\n if (writeResult.created) {\n result.created.push(\".github/workflows/pr-checks.yml\");\n if (writeResult.backedUp) {\n result.backedUp.push(writeResult.backedUp);\n }\n }\n\n return result;\n}\n","import { join } from \"node:path\";\nimport type { GeneratorResult } from \"../types/config.js\";\nimport { ensureDir, writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Get the CODEOWNERS content\n */\nfunction getCodeownersContent(owners: string[]): string {\n if (owners.length === 0) {\n return `# CODEOWNERS file\n# Learn about CODEOWNERS: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners\n\n# Default owners for everything in the repo\n# Uncomment and modify the line below to set default owners\n# * @owner1 @owner2\n`;\n }\n\n const ownersList = owners.join(\" \");\n\n return `# CODEOWNERS file\n# Learn about CODEOWNERS: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners\n\n# Default owners for everything in the repo\n* ${ownersList}\n\n# You can also specify owners for specific paths:\n# /docs/ @docs-team\n# /src/api/ @backend-team\n# /src/ui/ @frontend-team\n# *.ts @typescript-team\n`;\n}\n\n/**\n * Generate CODEOWNERS file\n */\nexport async function generateCodeowners(\n targetDir: string,\n owners: string[]\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const githubDir = join(targetDir, \".github\");\n await ensureDir(githubDir);\n\n const codeownersPath = join(githubDir, \"CODEOWNERS\");\n const writeResult = await writeFileSafe(\n codeownersPath,\n getCodeownersContent(owners),\n { backup: true }\n );\n\n if (writeResult.created) {\n result.created.push(\".github/CODEOWNERS\");\n if (writeResult.backedUp) {\n result.backedUp.push(writeResult.backedUp);\n }\n }\n\n return result;\n}\n","import { join } from \"node:path\";\nimport type { AIReviewTool, GeneratorResult } from \"../types/config.js\";\nimport { ensureDir, writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Get CodeRabbit configuration\n */\nfunction getCodeRabbitConfig(): string {\n return `# CodeRabbit Configuration\n# Learn more: https://docs.coderabbit.ai/guides/configure-coderabbit\n\nlanguage: \"en-US\"\n\nreviews:\n request_changes_workflow: true\n high_level_summary: true\n poem: false\n review_status: true\n collapse_walkthrough: false\n auto_review:\n enabled: true\n drafts: false\n\nchat:\n auto_reply: true\n`;\n}\n\n/**\n * Get GitHub Copilot PR review workflow\n */\nfunction getCopilotWorkflow(): string {\n return `name: Copilot Code Review\n\non:\n pull_request:\n types: [opened, synchronize, reopened]\n\npermissions:\n contents: read\n pull-requests: write\n\njobs:\n review:\n name: Copilot Review\n runs-on: ubuntu-latest\n steps:\n - name: Checkout\n uses: actions/checkout@v4\n\n # Note: GitHub Copilot code review is automatically enabled\n # when you have Copilot Enterprise. This workflow is a placeholder\n # for any additional AI review configuration you might need.\n\n - name: Add review comment\n uses: actions/github-script@v7\n with:\n script: |\n // GitHub Copilot will automatically review PRs if enabled\n // This is a placeholder for additional review logic\n console.log('Copilot review enabled for this repository');\n`;\n}\n\n/**\n * Generate AI review configuration\n */\nexport async function generateAIReview(\n targetDir: string,\n tool: AIReviewTool\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n if (tool === \"none\") {\n return result;\n }\n\n if (tool === \"coderabbit\") {\n const configPath = join(targetDir, \".coderabbit.yaml\");\n const writeResult = await writeFileSafe(configPath, getCodeRabbitConfig(), {\n backup: true,\n });\n\n if (writeResult.created) {\n result.created.push(\".coderabbit.yaml\");\n if (writeResult.backedUp) {\n result.backedUp.push(writeResult.backedUp);\n }\n }\n }\n\n if (tool === \"copilot\") {\n const workflowsDir = join(targetDir, \".github\", \"workflows\");\n await ensureDir(workflowsDir);\n\n const workflowPath = join(workflowsDir, \"copilot-review.yml\");\n const writeResult = await writeFileSafe(workflowPath, getCopilotWorkflow(), {\n backup: true,\n });\n\n if (writeResult.created) {\n result.created.push(\".github/workflows/copilot-review.yml\");\n if (writeResult.backedUp) {\n result.backedUp.push(writeResult.backedUp);\n }\n }\n }\n\n return result;\n}\n","import { join } from \"node:path\";\nimport type { GeneratorResult } from \"../types/config.js\";\nimport { ensureDir, writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Get branch protection setup documentation\n */\nfunction getBranchProtectionDocs(): string {\n return `# Branch Protection Setup Guide\n\nThis guide explains how to configure branch protection rules for your repository.\n\n## Quick Setup\n\nRun the automated setup command:\n\n\\`\\`\\`bash\nraftstack setup-protection\n\\`\\`\\`\n\nThis command supports:\n- **Multiple branches**: main, staging, production, development, etc.\n- **Merge strategies**: Rebase (recommended), squash, or merge commits\n- **Review requirements**: Configurable number of required approvals\n\n## Recommended Settings\n\n### For \\`main\\` / \\`master\\` branch:\n\n1. **Require a pull request before merging**\n - ✅ Require approvals: 1 (or more for larger teams)\n - ✅ Dismiss stale pull request approvals when new commits are pushed\n - ✅ Require review from Code Owners\n\n2. **Require status checks to pass before merging**\n - ✅ Require branches to be up to date before merging\n - Select required status checks:\n - \\`check\\` (from pr-checks.yml workflow)\n\n3. **Require conversation resolution before merging**\n - ✅ All conversations on code must be resolved\n\n4. **Do not allow bypassing the above settings**\n - ✅ Apply rules to administrators\n\n5. **Restrict who can push to matching branches**\n - Only allow merges through pull requests\n\n6. **Block force pushes**\n - ✅ Do not allow force pushes\n\n7. **Block deletions**\n - ✅ Do not allow this branch to be deleted\n\n## Manual Setup via GitHub UI\n\n1. Go to your repository on GitHub\n2. Click **Settings** > **Branches**\n3. Click **Add branch protection rule**\n4. Enter \\`main\\` (or \\`master\\`) as the branch name pattern\n5. Configure the settings as described above\n6. Click **Create** or **Save changes**\n\n## Automated Setup (Recommended)\n\nUse the \\`raftstack setup-protection\\` command to configure\nbranch protection rules automatically using the GitHub CLI.\n\nRequirements:\n- GitHub CLI (\\`gh\\`) installed and authenticated\n- Admin access to the repository\n\n\\`\\`\\`bash\nraftstack setup-protection\n\\`\\`\\`\n\n### Features\n\nThe setup command will:\n1. Prompt you to select branches to protect (main, staging, production, etc.)\n2. Let you choose a merge strategy (rebase, squash, or merge commits)\n3. Configure required review count\n4. Apply branch protection rules to all selected branches\n5. Set repository merge settings\n\n### Merge Strategy Recommendations\n\n| Strategy | Use Case |\n|----------|----------|\n| **Rebase** (recommended) | Clean linear history, easy to follow |\n| **Squash** | Single commit per PR, cleaner history |\n| **Merge commit** | Preserve all commits, show PR merge points |\n\n## Branch Naming Convention\n\nThis project enforces branch naming conventions via \\`validate-branch-name\\`.\n\nAllowed patterns:\n- \\`main\\`, \\`master\\`, \\`develop\\`, \\`staging\\`, \\`production\\`\n- \\`feature/*\\` - New features\n- \\`fix/*\\` or \\`bugfix/*\\` - Bug fixes\n- \\`hotfix/*\\` - Urgent fixes\n- \\`release/*\\` - Release preparation\n- \\`chore/*\\` - Maintenance tasks\n- \\`docs/*\\` - Documentation updates\n- \\`refactor/*\\` - Code refactoring\n- \\`test/*\\` - Test additions/updates\n- \\`ci/*\\` - CI/CD changes\n\nExamples:\n- \\`feature/user-authentication\\`\n- \\`fix/login-validation\\`\n- \\`hotfix/security-patch\\`\n- \\`release/v1.2.0\\`\n`;\n}\n\n/**\n * Generate branch protection documentation\n */\nexport async function generateBranchProtectionDocs(\n targetDir: string\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const docsDir = join(targetDir, \".github\");\n await ensureDir(docsDir);\n\n const docsPath = join(docsDir, \"BRANCH_PROTECTION_SETUP.md\");\n const writeResult = await writeFileSafe(docsPath, getBranchProtectionDocs(), {\n backup: true,\n });\n\n if (writeResult.created) {\n result.created.push(\".github/BRANCH_PROTECTION_SETUP.md\");\n if (writeResult.backedUp) {\n result.backedUp.push(writeResult.backedUp);\n }\n }\n\n return result;\n}\n","import { join } from \"node:path\";\nimport type { GeneratorResult, PackageManagerInfo } from \"../types/config.js\";\nimport { writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Get CONTRIBUTING.md content\n */\nfunction getContributingContent(hasAsana: boolean, pm: PackageManagerInfo): string {\n const asanaSection = hasAsana\n ? `\n## Linking to Asana\n\nWhen working on a task:\n1. Create a branch following the naming convention (e.g., \\`feature/task-description\\`)\n2. Include the Asana task link in your commit body or footer\n3. Reference the Asana task in your PR description\n\nExample commit:\n\\`\\`\\`\nfeat(auth): add password reset functionality\n\nImplement password reset flow with email verification.\n\nAsana: https://app.asana.com/0/workspace/task-id\n\\`\\`\\`\n`\n : \"\";\n\n return `# Contributing Guide\n\nThank you for your interest in contributing! This document outlines our development workflow and standards.\n\n## Getting Started\n\n1. Clone the repository\n2. Install dependencies: \\`${pm.install}\\`\n3. Create a new branch following our naming convention\n\n## Branch Naming Convention\n\nWe use structured branch names to keep our repository organized:\n\n| Prefix | Purpose | Example |\n|--------|---------|---------|\n| \\`feature/\\` | New features | \\`feature/user-authentication\\` |\n| \\`fix/\\` | Bug fixes | \\`fix/login-validation\\` |\n| \\`hotfix/\\` | Urgent fixes | \\`hotfix/security-patch\\` |\n| \\`bugfix/\\` | Bug fixes (alternative) | \\`bugfix/form-submission\\` |\n| \\`release/\\` | Release preparation | \\`release/v1.2.0\\` |\n| \\`chore/\\` | Maintenance tasks | \\`chore/update-dependencies\\` |\n| \\`docs/\\` | Documentation | \\`docs/api-reference\\` |\n| \\`refactor/\\` | Code refactoring | \\`refactor/auth-module\\` |\n| \\`test/\\` | Test additions | \\`test/user-service\\` |\n| \\`ci/\\` | CI/CD changes | \\`ci/github-actions\\` |\n\n## Commit Convention\n\nWe follow [Conventional Commits](https://www.conventionalcommits.org/). Use the interactive commit tool:\n\n\\`\\`\\`bash\n${pm.run} commit\n\\`\\`\\`\n\n### Commit Types\n\n| Type | Description |\n|------|-------------|\n| \\`feat\\` | New feature |\n| \\`fix\\` | Bug fix |\n| \\`docs\\` | Documentation changes |\n| \\`style\\` | Code style changes (formatting, etc.) |\n| \\`refactor\\` | Code refactoring |\n| \\`perf\\` | Performance improvements |\n| \\`test\\` | Adding or updating tests |\n| \\`build\\` | Build system changes |\n| \\`ci\\` | CI configuration changes |\n| \\`chore\\` | Other changes |\n| \\`revert\\` | Reverting changes |\n\n### Commit Message Format\n\n\\`\\`\\`\n<type>(<scope>): <subject>\n\n<body>\n\n<footer>\n\\`\\`\\`\n\nExample:\n\\`\\`\\`\nfeat(auth): add social login support\n\nImplement OAuth2 login for Google and GitHub providers.\nIncludes user profile sync and token refresh.\n\nCloses #123\n\\`\\`\\`\n${asanaSection}\n## Pull Request Process\n\n1. Ensure your branch is up to date with \\`main\\`/\\`master\\`\n2. Run tests and linting locally\n3. Create a pull request using the provided template\n4. Request review from code owners\n5. Address any feedback\n6. Merge once approved and all checks pass\n\n### PR Size Guidelines\n\nKeep pull requests small and focused for faster reviews:\n\n| Size | Lines Changed | Review Time |\n|------|---------------|-------------|\n| XS | 0-10 lines | Minutes |\n| S | 11-50 lines | < 30 min |\n| M | 51-200 lines | < 1 hour |\n| L | 201-400 lines | 1-2 hours |\n| XL | 400+ lines | Needs justification |\n\n**Target: < 400 lines per PR**\n\nIf your PR is large:\n- Consider splitting it into smaller, logical PRs\n- Explain in the description why it can't be split\n\n## Code Quality\n\nBefore committing, the following checks run automatically:\n\n- **Linting**: ESLint checks for code quality\n- **Formatting**: Prettier ensures consistent style\n- **Type checking**: TypeScript validates types\n- **Commit messages**: Commitlint validates format\n- **Branch names**: validate-branch-name checks naming\n\n## Questions?\n\nIf you have questions, please open an issue or reach out to the maintainers.\n`;\n}\n\n/**\n * Generate CONTRIBUTING.md\n */\nexport async function generateContributing(\n targetDir: string,\n hasAsana: boolean,\n pm: PackageManagerInfo\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const contributingPath = join(targetDir, \"CONTRIBUTING.md\");\n const writeResult = await writeFileSafe(\n contributingPath,\n getContributingContent(hasAsana, pm),\n { backup: true }\n );\n\n if (writeResult.created) {\n result.created.push(\"CONTRIBUTING.md\");\n if (writeResult.backedUp) {\n result.backedUp.push(writeResult.backedUp);\n }\n }\n\n return result;\n}\n","import { join } from \"node:path\";\nimport type { GeneratorResult } from \"../types/config.js\";\nimport { fileExists, writeFileSafe } from \"../utils/file-system.js\";\n\n/**\n * Get Prettier configuration\n */\nfunction getPrettierConfig(): string {\n return JSON.stringify(\n {\n semi: true,\n singleQuote: true,\n tabWidth: 2,\n trailingComma: \"es5\",\n printWidth: 100,\n bracketSpacing: true,\n arrowParens: \"always\",\n endOfLine: \"lf\",\n },\n null,\n 2\n ) + \"\\n\";\n}\n\n/**\n * Get Prettier ignore file content\n */\nfunction getPrettierIgnore(): string {\n return `# Dependencies\nnode_modules/\n\n# Build output\ndist/\nbuild/\n.next/\nout/\n\n# Coverage\ncoverage/\n\n# IDE\n.idea/\n.vscode/\n\n# Generated files\n*.min.js\n*.min.css\npackage-lock.json\npnpm-lock.yaml\nyarn.lock\n\n# Other\n.git/\n`;\n}\n\n/**\n * Check if Prettier is already configured\n */\nfunction hasPrettierConfig(targetDir: string): boolean {\n const prettierFiles = [\n \".prettierrc\",\n \".prettierrc.js\",\n \".prettierrc.cjs\",\n \".prettierrc.json\",\n \".prettierrc.yaml\",\n \".prettierrc.yml\",\n \".prettierrc.toml\",\n \"prettier.config.js\",\n \"prettier.config.cjs\",\n \"prettier.config.mjs\",\n ];\n\n return prettierFiles.some((file) => fileExists(join(targetDir, file)));\n}\n\n/**\n * Generate Prettier configuration\n */\nexport async function generatePrettier(\n targetDir: string\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n // Skip if Prettier is already configured\n if (hasPrettierConfig(targetDir)) {\n result.skipped.push(\".prettierrc (already exists)\");\n return result;\n }\n\n // Create .prettierrc\n const configPath = join(targetDir, \".prettierrc\");\n const configResult = await writeFileSafe(configPath, getPrettierConfig(), {\n backup: true,\n });\n\n if (configResult.created) {\n result.created.push(\".prettierrc\");\n if (configResult.backedUp) {\n result.backedUp.push(configResult.backedUp);\n }\n }\n\n // Create .prettierignore\n const ignorePath = join(targetDir, \".prettierignore\");\n const ignoreResult = await writeFileSafe(ignorePath, getPrettierIgnore(), {\n backup: true,\n overwrite: false, // Don't overwrite existing ignore file\n });\n\n if (ignoreResult.created) {\n result.created.push(\".prettierignore\");\n if (ignoreResult.backedUp) {\n result.backedUp.push(ignoreResult.backedUp);\n }\n } else {\n result.skipped.push(\".prettierignore (already exists)\");\n }\n\n return result;\n}\n","import { existsSync } from \"node:fs\";\nimport { readdir, copyFile } from \"node:fs/promises\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { GeneratorResult } from \"../types/config.js\";\nimport { ensureDir, backupFile } from \"../utils/file-system.js\";\n\n/**\n * Get the path to the skills directory in the installed package\n */\nfunction getPackageSkillsDir(): string {\n // In ESM, we use import.meta.url to find the package location\n // tsup bundles everything into dist/cli.js, so we only need to go up 1 level\n const currentFilePath = fileURLToPath(import.meta.url);\n const packageRoot = join(dirname(currentFilePath), \"..\");\n return join(packageRoot, \".claude\", \"skills\");\n}\n\n/**\n * Recursively copy a directory\n */\nasync function copyDirectory(\n srcDir: string,\n destDir: string,\n result: GeneratorResult,\n baseDir: string\n): Promise<void> {\n await ensureDir(destDir);\n\n const entries = await readdir(srcDir, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = join(srcDir, entry.name);\n const destPath = join(destDir, entry.name);\n const relativePath = destPath.replace(baseDir + \"/\", \"\");\n\n if (entry.isDirectory()) {\n await copyDirectory(srcPath, destPath, result, baseDir);\n } else {\n // Check if destination exists\n if (existsSync(destPath)) {\n // Backup existing file\n const backupPath = await backupFile(destPath);\n if (backupPath) {\n result.backedUp.push(relativePath);\n }\n }\n\n // Copy the file\n await copyFile(srcPath, destPath);\n result.created.push(relativePath);\n }\n }\n}\n\n/**\n * Generate Claude Code skills by copying them to the target project\n *\n * This copies the bundled .claude/skills/ directory to the target project,\n * enabling AI-assisted code quality enforcement when using Claude Code.\n */\nexport async function generateClaudeSkills(\n targetDir: string\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const packageSkillsDir = getPackageSkillsDir();\n const targetSkillsDir = join(targetDir, \".claude\", \"skills\");\n\n // Check if source skills directory exists\n if (!existsSync(packageSkillsDir)) {\n // Skills not bundled (development mode or missing)\n console.warn(\n \"Warning: Skills directory not found in package. Skipping skills generation.\"\n );\n return result;\n }\n\n // Ensure target .claude directory exists\n await ensureDir(join(targetDir, \".claude\"));\n\n // Copy all skills\n await copyDirectory(packageSkillsDir, targetSkillsDir, result, targetDir);\n\n return result;\n}","import { existsSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { GeneratorResult } from \"../types/config.js\";\nimport { writeFileSafe } from \"../utils/file-system.js\";\nimport { hasEslint } from \"../utils/detect-project.js\";\n\n/**\n * Check if project uses React\n */\nasync function hasReact(targetDir: string): Promise<boolean> {\n try {\n const pkgPath = join(targetDir, \"package.json\");\n if (existsSync(pkgPath)) {\n const content = await readFile(pkgPath, \"utf-8\");\n const pkg = JSON.parse(content);\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n return \"react\" in deps || \"react-dom\" in deps;\n }\n } catch {\n // Ignore parse errors\n }\n return false;\n}\n\n/**\n * Generate ESLint flat config content for TypeScript projects\n */\nfunction generateTsConfig(hasReactDep: boolean): string {\n if (hasReactDep) {\n return `import eslint from \"@eslint/js\";\nimport tseslint from \"typescript-eslint\";\nimport reactPlugin from \"eslint-plugin-react\";\nimport reactHooksPlugin from \"eslint-plugin-react-hooks\";\nimport globals from \"globals\";\n\nexport default tseslint.config(\n eslint.configs.recommended,\n ...tseslint.configs.recommended,\n {\n files: [\"**/*.{ts,tsx}\"],\n languageOptions: {\n parserOptions: {\n ecmaFeatures: {\n jsx: true,\n },\n },\n globals: {\n ...globals.browser,\n ...globals.node,\n },\n },\n plugins: {\n react: reactPlugin,\n \"react-hooks\": reactHooksPlugin,\n },\n rules: {\n // TypeScript rules\n \"@typescript-eslint/no-unused-vars\": [\"error\", { argsIgnorePattern: \"^_\" }],\n \"@typescript-eslint/no-explicit-any\": \"warn\",\n \"@typescript-eslint/consistent-type-imports\": \"error\",\n\n // React rules\n \"react/react-in-jsx-scope\": \"off\",\n \"react/prop-types\": \"off\",\n \"react-hooks/rules-of-hooks\": \"error\",\n \"react-hooks/exhaustive-deps\": \"warn\",\n\n // General rules\n \"no-console\": \"warn\",\n },\n settings: {\n react: {\n version: \"detect\",\n },\n },\n },\n {\n ignores: [\"node_modules\", \"dist\", \"build\", \".next\", \"coverage\"],\n }\n);\n`;\n }\n\n return `import eslint from \"@eslint/js\";\nimport tseslint from \"typescript-eslint\";\nimport globals from \"globals\";\n\nexport default tseslint.config(\n eslint.configs.recommended,\n ...tseslint.configs.recommended,\n {\n files: [\"**/*.{ts,tsx}\"],\n languageOptions: {\n globals: {\n ...globals.node,\n },\n },\n rules: {\n // TypeScript rules\n \"@typescript-eslint/no-unused-vars\": [\"error\", { argsIgnorePattern: \"^_\" }],\n \"@typescript-eslint/no-explicit-any\": \"warn\",\n \"@typescript-eslint/consistent-type-imports\": \"error\",\n\n // General rules\n \"no-console\": \"warn\",\n },\n },\n {\n ignores: [\"node_modules\", \"dist\", \"build\", \"coverage\"],\n }\n);\n`;\n}\n\n/**\n * Generate ESLint flat config content for JavaScript projects\n */\nfunction generateJsConfig(hasReactDep: boolean): string {\n if (hasReactDep) {\n return `import eslint from \"@eslint/js\";\nimport reactPlugin from \"eslint-plugin-react\";\nimport reactHooksPlugin from \"eslint-plugin-react-hooks\";\nimport globals from \"globals\";\n\nexport default [\n eslint.configs.recommended,\n {\n files: [\"**/*.{js,jsx}\"],\n languageOptions: {\n ecmaVersion: \"latest\",\n sourceType: \"module\",\n parserOptions: {\n ecmaFeatures: {\n jsx: true,\n },\n },\n globals: {\n ...globals.browser,\n ...globals.node,\n },\n },\n plugins: {\n react: reactPlugin,\n \"react-hooks\": reactHooksPlugin,\n },\n rules: {\n // React rules\n \"react/react-in-jsx-scope\": \"off\",\n \"react/prop-types\": \"warn\",\n \"react-hooks/rules-of-hooks\": \"error\",\n \"react-hooks/exhaustive-deps\": \"warn\",\n\n // General rules\n \"no-console\": \"warn\",\n \"no-unused-vars\": [\"error\", { argsIgnorePattern: \"^_\" }],\n },\n settings: {\n react: {\n version: \"detect\",\n },\n },\n },\n {\n ignores: [\"node_modules\", \"dist\", \"build\", \".next\", \"coverage\"],\n },\n];\n`;\n }\n\n return `import eslint from \"@eslint/js\";\nimport globals from \"globals\";\n\nexport default [\n eslint.configs.recommended,\n {\n files: [\"**/*.js\"],\n languageOptions: {\n ecmaVersion: \"latest\",\n sourceType: \"module\",\n globals: {\n ...globals.node,\n },\n },\n rules: {\n // General rules\n \"no-console\": \"warn\",\n \"no-unused-vars\": [\"error\", { argsIgnorePattern: \"^_\" }],\n },\n },\n {\n ignores: [\"node_modules\", \"dist\", \"build\", \"coverage\"],\n },\n];\n`;\n}\n\n/**\n * Get the ESLint dependencies to add to package.json\n */\nexport function getEslintDependencies(\n usesTypeScript: boolean,\n usesReact: boolean\n): Record<string, string> {\n const deps: Record<string, string> = {\n eslint: \"^9.0.0\",\n \"@eslint/js\": \"^9.0.0\",\n globals: \"^15.0.0\",\n };\n\n if (usesTypeScript) {\n deps[\"typescript-eslint\"] = \"^8.0.0\";\n }\n\n if (usesReact) {\n deps[\"eslint-plugin-react\"] = \"^7.35.0\";\n deps[\"eslint-plugin-react-hooks\"] = \"^5.0.0\";\n }\n\n return deps;\n}\n\n/**\n * Generate ESLint configuration file\n *\n * @param targetDir - The target directory to write to\n * @param usesTypeScript - Whether the project uses TypeScript\n * @param force - Force generation even if ESLint is already configured\n */\nexport async function generateEslint(\n targetDir: string,\n usesTypeScript: boolean,\n force: boolean = false\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n // Check if ESLint is already configured (unless force)\n if (!force && (await hasEslint(targetDir))) {\n result.skipped.push(\"eslint.config.js (ESLint already configured)\");\n return result;\n }\n\n // Detect React\n const usesReact = await hasReact(targetDir);\n\n // Generate appropriate config\n const config = usesTypeScript\n ? generateTsConfig(usesReact)\n : generateJsConfig(usesReact);\n\n // Write config file\n const configPath = join(targetDir, \"eslint.config.js\");\n const writeResult = await writeFileSafe(configPath, config);\n\n if (writeResult.backedUp) {\n result.backedUp.push(\"eslint.config.js\");\n }\n\n result.created.push(\"eslint.config.js\");\n\n return result;\n}\n","import { join } from \"node:path\";\nimport { writeFileSafe } from \"../utils/file-system.js\";\nimport type { GeneratorResult, PackageManagerInfo } from \"../types/config.js\";\n\n/**\n * Generate Quick Reference guide for developers\n */\nexport async function generateQuickReference(\n targetDir: string,\n pm: PackageManagerInfo\n): Promise<GeneratorResult> {\n const result: GeneratorResult = {\n created: [],\n modified: [],\n skipped: [],\n backedUp: [],\n };\n\n const quickRefPath = join(targetDir, \".github\", \"QUICK_REFERENCE.md\");\n\n const content = `# RaftStack Quick Reference\n\n> One-page guide for the RaftStack Git workflow\n\n## 🚀 Daily Workflow\n\n### 1. Create a Branch\n\n\\`\\`\\`bash\n# Format: <type>/<short-description>\ngit checkout -b feature/user-authentication\ngit checkout -b bugfix/login-redirect\ngit checkout -b hotfix/payment-timeout\n\\`\\`\\`\n\n**Branch types:** \\`feature\\`, \\`bugfix\\`, \\`hotfix\\`, \\`chore\\`, \\`refactor\\`\n\n### 2. Make Commits\n\n\\`\\`\\`bash\n# Use the interactive commit tool\n${pm.run} commit\n\\`\\`\\`\n\nThis will prompt you for:\n- Type (feat, fix, docs, etc.)\n- Scope (optional)\n- Description\n- Body (optional)\n- **Task link (required)**\n\n### 3. Commit Message Format\n\n\\`\\`\\`\n✨ feat(auth): add user login form\n\n- Created LoginForm component\n- Added form validation\n- Integrated with API\n\nTask: https://app.asana.com/0/project/task\n\\`\\`\\`\n\n### 4. Create Pull Request\n\n\\`\\`\\`bash\ngit push -u origin feature/my-feature\n# Then create PR on GitHub\n\\`\\`\\`\n\n---\n\n## 📝 Commit Types\n\n| Type | Emoji | Use For |\n|------|-------|---------|\n| feat | ✨ | New feature |\n| fix | 🐛 | Bug fix |\n| docs | 📝 | Documentation |\n| style | 💄 | Formatting (no logic change) |\n| refactor | ♻️ | Code restructuring |\n| perf | ⚡ | Performance improvement |\n| test | ✅ | Adding tests |\n| build | 📦 | Build system changes |\n| ci | 👷 | CI configuration |\n| chore | 🔧 | Maintenance |\n\n---\n\n## ✅ PR Checklist\n\nBefore submitting:\n- [ ] Branch name follows convention\n- [ ] All commits have task links\n- [ ] Tests pass locally\n- [ ] PR description filled out\n- [ ] Size is reasonable (< 400 lines)\n\n---\n\n## 🔧 Useful Commands\n\n\\`\\`\\`bash\n# Interactive commit\n${pm.run} commit\n\n# Check compliance metrics\n${pm.exec} @raftlabs/raftstack metrics\n\n# Run linting\n${pm.run} lint\n\n# Run tests\n${pm.run} test\n\\`\\`\\`\n\n---\n\n## ❌ Common Mistakes\n\n| Wrong | Right |\n|-------|-------|\n| \\`Feature/UserAuth\\` | \\`feature/user-auth\\` |\n| \\`fixed bug\\` | \\`fix(auth): resolve login redirect\\` |\n| No task link | Always include \\`Task: <url>\\` |\n| 1000+ line PR | Split into smaller PRs |\n\n---\n\n## 📚 More Info\n\n- [CONTRIBUTING.md](../CONTRIBUTING.md) - Full contribution guide\n- [RaftStack Docs](https://github.com/Raft-Labs/raftstack) - CLI documentation\n\n---\n\n*Generated by RaftStack - Git workflow standardization for teams*\n`;\n\n const writeResult = await writeFileSafe(quickRefPath, content);\n\n if (writeResult.created) {\n if (writeResult.backedUp) {\n result.modified.push(\".github/QUICK_REFERENCE.md\");\n result.backedUp.push(\".github/QUICK_REFERENCE.md\");\n } else {\n result.created.push(\".github/QUICK_REFERENCE.md\");\n }\n } else {\n result.skipped.push(\".github/QUICK_REFERENCE.md\");\n }\n\n return result;\n}\n","import { execa } from \"execa\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/**\n * Check if directory is a git repository\n */\nexport async function isGitRepo(\n targetDir: string = process.cwd()\n): Promise<boolean> {\n // Quick check for .git directory\n if (existsSync(join(targetDir, \".git\"))) {\n return true;\n }\n\n // Fallback to git command (handles worktrees, etc.)\n try {\n await execa(\"git\", [\"rev-parse\", \"--git-dir\"], { cwd: targetDir });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get the root directory of the git repository\n */\nexport async function getGitRoot(\n targetDir: string = process.cwd()\n): Promise<string | null> {\n try {\n const { stdout } = await execa(\"git\", [\"rev-parse\", \"--show-toplevel\"], {\n cwd: targetDir,\n });\n return stdout.trim();\n } catch {\n return null;\n }\n}\n\n/**\n * Get current branch name\n */\nexport async function getCurrentBranch(\n targetDir: string = process.cwd()\n): Promise<string | null> {\n try {\n const { stdout } = await execa(\"git\", [\"branch\", \"--show-current\"], {\n cwd: targetDir,\n });\n return stdout.trim() || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Check if gh CLI is available and authenticated\n */\nexport async function isGhCliAvailable(): Promise<boolean> {\n try {\n await execa(\"gh\", [\"auth\", \"status\"]);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Get GitHub repository info (owner/repo)\n */\nexport async function getGitHubRepoInfo(\n targetDir: string = process.cwd()\n): Promise<{ owner: string; repo: string } | null> {\n try {\n const { stdout } = await execa(\"gh\", [\"repo\", \"view\", \"--json\", \"owner,name\"], {\n cwd: targetDir,\n });\n const data = JSON.parse(stdout);\n return {\n owner: data.owner.login,\n repo: data.name,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * Initialize husky in the repository\n */\nexport async function initHusky(\n targetDir: string = process.cwd()\n): Promise<void> {\n await execa(\"npx\", [\"husky\", \"init\"], { cwd: targetDir });\n}\n\n/**\n * Run a git command\n */\nexport async function runGitCommand(\n args: string[],\n targetDir: string = process.cwd()\n): Promise<string> {\n const { stdout } = await execa(\"git\", args, { cwd: targetDir });\n return stdout;\n}\n","import * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { execa } from \"execa\";\nimport { isGhCliAvailable, getGitHubRepoInfo } from \"../utils/git.js\";\n\n/**\n * Merge strategy options\n */\nexport type MergeStrategy = \"rebase\" | \"squash\" | \"merge\";\n\n/**\n * Branch protection settings\n */\nexport interface BranchProtectionSettings {\n branch: string;\n requiredReviews: number;\n dismissStaleReviews: boolean;\n requireCodeOwners: boolean;\n requireStatusChecks: boolean;\n statusChecks: string[];\n requireConversationResolution: boolean;\n restrictPushes: boolean;\n blockForcePushes: boolean;\n blockDeletions: boolean;\n}\n\n/**\n * Repository settings for merge strategies\n */\nexport interface RepositorySettings {\n allowMergeCommit: boolean;\n allowSquashMerge: boolean;\n allowRebaseMerge: boolean;\n deleteBranchOnMerge: boolean;\n}\n\n/**\n * Default branch protection settings\n */\nfunction getDefaultSettings(branch: string): BranchProtectionSettings {\n return {\n branch,\n requiredReviews: 1,\n dismissStaleReviews: true,\n requireCodeOwners: true,\n requireStatusChecks: true,\n statusChecks: [\"check\"],\n requireConversationResolution: true,\n restrictPushes: false,\n blockForcePushes: true,\n blockDeletions: true,\n };\n}\n\n/**\n * Get repository settings based on merge strategy\n */\nfunction getMergeStrategySettings(strategy: MergeStrategy): RepositorySettings {\n switch (strategy) {\n case \"rebase\":\n return {\n allowMergeCommit: false,\n allowSquashMerge: false,\n allowRebaseMerge: true,\n deleteBranchOnMerge: true,\n };\n case \"squash\":\n return {\n allowMergeCommit: false,\n allowSquashMerge: true,\n allowRebaseMerge: false,\n deleteBranchOnMerge: true,\n };\n case \"merge\":\n return {\n allowMergeCommit: true,\n allowSquashMerge: false,\n allowRebaseMerge: false,\n deleteBranchOnMerge: true,\n };\n }\n}\n\n/**\n * Apply branch protection using gh CLI\n */\nasync function applyBranchProtection(\n owner: string,\n repo: string,\n settings: BranchProtectionSettings\n): Promise<void> {\n const args = [\n \"api\",\n \"-X\",\n \"PUT\",\n `/repos/${owner}/${repo}/branches/${settings.branch}/protection`,\n \"-f\",\n `required_pull_request_reviews[required_approving_review_count]=${settings.requiredReviews}`,\n \"-f\",\n `required_pull_request_reviews[dismiss_stale_reviews]=${settings.dismissStaleReviews}`,\n \"-f\",\n `required_pull_request_reviews[require_code_owner_reviews]=${settings.requireCodeOwners}`,\n \"-f\",\n `required_status_checks[strict]=true`,\n \"-f\",\n `enforce_admins=true`,\n \"-f\",\n `allow_force_pushes=${!settings.blockForcePushes}`,\n \"-f\",\n `allow_deletions=${!settings.blockDeletions}`,\n \"-f\",\n `required_conversation_resolution=${settings.requireConversationResolution}`,\n ];\n\n // Add status checks\n if (settings.requireStatusChecks && settings.statusChecks.length > 0) {\n for (const check of settings.statusChecks) {\n args.push(\"-f\", `required_status_checks[contexts][]=${check}`);\n }\n } else {\n args.push(\"-F\", \"required_status_checks=null\");\n }\n\n // Add restrictions (null means no restrictions beyond PRs)\n args.push(\"-F\", \"restrictions=null\");\n\n await execa(\"gh\", args);\n}\n\n/**\n * Apply repository merge settings using gh CLI\n */\nasync function applyMergeStrategy(\n owner: string,\n repo: string,\n settings: RepositorySettings\n): Promise<void> {\n const args = [\n \"api\",\n \"-X\",\n \"PATCH\",\n `/repos/${owner}/${repo}`,\n \"-f\",\n `allow_merge_commit=${settings.allowMergeCommit}`,\n \"-f\",\n `allow_squash_merge=${settings.allowSquashMerge}`,\n \"-f\",\n `allow_rebase_merge=${settings.allowRebaseMerge}`,\n \"-f\",\n `delete_branch_on_merge=${settings.deleteBranchOnMerge}`,\n ];\n\n await execa(\"gh\", args);\n}\n\n/**\n * Run the setup-protection command\n */\nexport async function runSetupProtection(\n targetDir: string = process.cwd()\n): Promise<void> {\n console.log();\n p.intro(pc.bgCyan(pc.black(\" Branch Protection Setup \")));\n\n // Check gh CLI\n const spinner = p.spinner();\n spinner.start(\"Checking GitHub CLI...\");\n\n const ghAvailable = await isGhCliAvailable();\n\n if (!ghAvailable) {\n spinner.stop(\"GitHub CLI not found or not authenticated\");\n console.log();\n p.log.error(pc.red(\"The GitHub CLI (gh) is required for this command.\"));\n p.log.info(\"Install it from: https://cli.github.com/\");\n p.log.info(\"Then run: gh auth login\");\n console.log();\n p.log.info(\n pc.dim(\n \"Alternatively, see .github/BRANCH_PROTECTION_SETUP.md for manual instructions.\"\n )\n );\n process.exit(1);\n }\n\n spinner.stop(\"GitHub CLI ready\");\n\n // Get repo info\n spinner.start(\"Getting repository info...\");\n const repoInfo = await getGitHubRepoInfo(targetDir);\n\n if (!repoInfo) {\n spinner.stop(\"Could not determine repository\");\n p.log.error(\n pc.red(\"Could not determine the GitHub repository for this directory.\")\n );\n p.log.info(\"Make sure you're in a git repository with a GitHub remote.\");\n process.exit(1);\n }\n\n spinner.stop(`Repository: ${pc.cyan(`${repoInfo.owner}/${repoInfo.repo}`)}`);\n\n // Ask which branches to protect\n const branches = await p.multiselect({\n message: \"Which branches need protection?\",\n options: [\n { value: \"main\", label: \"main\", hint: \"recommended\" },\n { value: \"master\", label: \"master\", hint: \"legacy default\" },\n { value: \"staging\", label: \"staging\", hint: \"staging environment\" },\n { value: \"production\", label: \"production\", hint: \"production environment\" },\n { value: \"development\", label: \"development\", hint: \"development branch\" },\n { value: \"develop\", label: \"develop\", hint: \"alternative dev branch\" },\n ],\n required: true,\n initialValues: [\"main\"],\n });\n\n if (p.isCancel(branches)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n // Ask for merge strategy\n const mergeStrategy = await p.select({\n message: \"Default merge strategy for PRs?\",\n options: [\n {\n value: \"rebase\",\n label: \"Rebase merge\",\n hint: \"recommended - clean linear history\",\n },\n {\n value: \"squash\",\n label: \"Squash merge\",\n hint: \"single commit per PR\",\n },\n {\n value: \"merge\",\n label: \"Merge commit\",\n hint: \"preserve all commits with merge commit\",\n },\n ],\n initialValue: \"rebase\",\n });\n\n if (p.isCancel(mergeStrategy)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n // Ask for number of required reviews\n const reviews = await p.text({\n message: \"How many approving reviews are required?\",\n placeholder: \"1\",\n initialValue: \"1\",\n validate: (value) => {\n const num = parseInt(value, 10);\n if (isNaN(num) || num < 0 || num > 6) {\n return \"Must be a number between 0 and 6\";\n }\n return undefined;\n },\n });\n\n if (p.isCancel(reviews)) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n const requiredReviews = parseInt(reviews, 10);\n\n // Confirm settings\n const mergeStrategyLabels: Record<MergeStrategy, string> = {\n rebase: \"Rebase merge\",\n squash: \"Squash merge\",\n merge: \"Merge commit\",\n };\n\n console.log();\n p.note(\n [\n `${pc.cyan(\"Repository:\")} ${repoInfo.owner}/${repoInfo.repo}`,\n `${pc.cyan(\"Protected branches:\")} ${(branches as string[]).join(\", \")}`,\n `${pc.cyan(\"Merge strategy:\")} ${mergeStrategyLabels[mergeStrategy as MergeStrategy]}`,\n `${pc.cyan(\"Required reviews:\")} ${requiredReviews}`,\n `${pc.cyan(\"Dismiss stale reviews:\")} Yes`,\n `${pc.cyan(\"Require code owners:\")} Yes`,\n `${pc.cyan(\"Require status checks:\")} Yes`,\n `${pc.cyan(\"Block force pushes:\")} Yes`,\n `${pc.cyan(\"Block deletions:\")} Yes`,\n `${pc.cyan(\"Delete branch on merge:\")} Yes`,\n ].join(\"\\n\"),\n \"Branch Protection Settings\"\n );\n\n const confirmed = await p.confirm({\n message: \"Apply these branch protection rules?\",\n initialValue: true,\n });\n\n if (p.isCancel(confirmed) || !confirmed) {\n p.cancel(\"Setup cancelled.\");\n process.exit(0);\n }\n\n // Apply merge strategy settings first\n spinner.start(\"Configuring merge strategy...\");\n\n try {\n const repoSettings = getMergeStrategySettings(mergeStrategy as MergeStrategy);\n await applyMergeStrategy(repoInfo.owner, repoInfo.repo, repoSettings);\n spinner.stop(\"Merge strategy configured!\");\n } catch (error) {\n spinner.stop(\"Failed to configure merge strategy\");\n const errorMsg = error instanceof Error ? error.message : \"Unknown error\";\n p.log.warn(pc.yellow(`Warning: Could not set merge strategy: ${errorMsg}`));\n p.log.info(pc.dim(\"Continuing with branch protection...\"));\n }\n\n // Apply branch protection for each branch\n const protectedBranches: string[] = [];\n const failedBranches: string[] = [];\n\n for (const branch of branches as string[]) {\n spinner.start(`Protecting branch: ${branch}...`);\n\n try {\n const settings = getDefaultSettings(branch);\n settings.requiredReviews = requiredReviews;\n\n await applyBranchProtection(repoInfo.owner, repoInfo.repo, settings);\n protectedBranches.push(branch);\n spinner.stop(`Protected: ${pc.green(branch)}`);\n } catch (error) {\n failedBranches.push(branch);\n spinner.stop(`Failed: ${pc.red(branch)}`);\n\n const errorMsg = error instanceof Error ? error.message : \"Unknown error\";\n p.log.warn(\n pc.yellow(\n `Could not protect ${branch}: ${errorMsg.includes(\"Branch not found\") ? \"branch does not exist\" : errorMsg}`\n )\n );\n }\n }\n\n // Show summary\n console.log();\n\n if (protectedBranches.length > 0) {\n p.log.success(\n pc.green(`Branch protection enabled for: ${pc.cyan(protectedBranches.join(\", \"))}`)\n );\n }\n\n if (failedBranches.length > 0) {\n p.log.warn(\n pc.yellow(\n `Could not protect: ${pc.red(failedBranches.join(\", \"))} (branches may not exist yet)`\n )\n );\n p.log.info(pc.dim(\"Create these branches first, then run this command again.\"));\n }\n\n if (protectedBranches.length > 0) {\n p.outro(pc.green(\"Setup complete!\"));\n } else {\n p.outro(pc.yellow(\"No branches were protected.\"));\n process.exit(1);\n }\n}\n","import { execa } from \"execa\";\nimport * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { isGitRepo } from \"../utils/git.js\";\n\ninterface MetricsResult {\n totalCommits: number;\n commitsWithTaskLinks: number;\n taskLinkCompliance: number;\n branchNames: string[];\n validBranches: number;\n invalidBranches: number;\n branchCompliance: number;\n}\n\n/**\n * Get commits from the last N days\n */\nasync function getRecentCommits(\n targetDir: string,\n days: number\n): Promise<string[]> {\n try {\n const { stdout } = await execa(\n \"git\",\n [\"log\", `--since=${days} days ago`, \"--oneline\", \"--no-merges\"],\n { cwd: targetDir }\n );\n return stdout.trim().split(\"\\n\").filter(Boolean);\n } catch {\n return [];\n }\n}\n\n/**\n * Get commit messages with full body\n */\nasync function getCommitMessages(\n targetDir: string,\n days: number\n): Promise<string[]> {\n try {\n const { stdout } = await execa(\n \"git\",\n [\n \"log\",\n `--since=${days} days ago`,\n \"--format=%B---COMMIT_SEPARATOR---\",\n \"--no-merges\",\n ],\n { cwd: targetDir }\n );\n return stdout.split(\"---COMMIT_SEPARATOR---\").filter((m) => m.trim());\n } catch {\n return [];\n }\n}\n\n/**\n * Get all branch names\n */\nasync function getBranchNames(targetDir: string): Promise<string[]> {\n try {\n const { stdout } = await execa(\n \"git\",\n [\"branch\", \"-a\", \"--format=%(refname:short)\"],\n { cwd: targetDir }\n );\n return stdout\n .trim()\n .split(\"\\n\")\n .filter(Boolean)\n .map((b) => b.replace(\"origin/\", \"\"))\n .filter((b, i, arr) => arr.indexOf(b) === i); // unique\n } catch {\n return [];\n }\n}\n\n/**\n * Validate branch name against convention\n */\nfunction isValidBranchName(name: string): boolean {\n const pattern =\n /^(main|staging|development|master)$|^(feature|bugfix|hotfix|chore|refactor)\\/[a-z0-9-]+$/;\n return pattern.test(name);\n}\n\n/**\n * Check if commit has task link\n */\nfunction hasTaskLink(message: string): boolean {\n return (\n message.includes(\"app.asana.com\") ||\n message.includes(\"Task:\") ||\n message.includes(\"task:\") ||\n message.includes(\"Closes #\") ||\n message.includes(\"Fixes #\")\n );\n}\n\n/**\n * Calculate metrics for the repository\n */\nasync function calculateMetrics(\n targetDir: string,\n days: number\n): Promise<MetricsResult> {\n const [commits, commitMessages, branches] = await Promise.all([\n getRecentCommits(targetDir, days),\n getCommitMessages(targetDir, days),\n getBranchNames(targetDir),\n ]);\n\n const commitsWithTaskLinks = commitMessages.filter(hasTaskLink).length;\n const validBranches = branches.filter(isValidBranchName);\n const invalidBranches = branches.filter((b) => !isValidBranchName(b));\n\n return {\n totalCommits: commits.length,\n commitsWithTaskLinks,\n taskLinkCompliance:\n commits.length > 0\n ? Math.round((commitsWithTaskLinks / commits.length) * 100)\n : 100,\n branchNames: branches,\n validBranches: validBranches.length,\n invalidBranches: invalidBranches.length,\n branchCompliance:\n branches.length > 0\n ? Math.round((validBranches.length / branches.length) * 100)\n : 100,\n };\n}\n\n/**\n * Format compliance percentage with color\n */\nfunction formatCompliance(percentage: number): string {\n if (percentage >= 90) return pc.green(`${percentage}%`);\n if (percentage >= 70) return pc.yellow(`${percentage}%`);\n return pc.red(`${percentage}%`);\n}\n\n/**\n * Run the metrics command\n */\nexport async function runMetrics(targetDir: string): Promise<void> {\n p.intro(pc.bgCyan(pc.black(\" RaftStack Metrics \")));\n\n if (!(await isGitRepo(targetDir))) {\n p.cancel(\"Not a git repository\");\n process.exit(1);\n }\n\n const daysOption = await p.select({\n message: \"Time period to analyze:\",\n options: [\n { value: 7, label: \"Last 7 days\" },\n { value: 14, label: \"Last 14 days\" },\n { value: 30, label: \"Last 30 days\" },\n { value: 90, label: \"Last 90 days\" },\n ],\n });\n\n if (p.isCancel(daysOption)) {\n p.cancel(\"Operation cancelled\");\n process.exit(0);\n }\n\n const days = daysOption as number;\n\n const spinner = p.spinner();\n spinner.start(\"Analyzing repository...\");\n\n const metrics = await calculateMetrics(targetDir, days);\n\n spinner.stop(\"Analysis complete\");\n\n p.note(\n `${pc.bold(\"Commits\")} (last ${days} days)\n Total: ${metrics.totalCommits}\n With task links: ${metrics.commitsWithTaskLinks}\n Compliance: ${formatCompliance(metrics.taskLinkCompliance)}\n\n${pc.bold(\"Branches\")}\n Total: ${metrics.branchNames.length}\n Valid naming: ${metrics.validBranches}\n Invalid naming: ${metrics.invalidBranches}\n Compliance: ${formatCompliance(metrics.branchCompliance)}`,\n \"Repository Metrics\"\n );\n\n if (metrics.invalidBranches > 0) {\n const invalidBranches = metrics.branchNames.filter(\n (b) => !isValidBranchName(b)\n );\n p.log.warn(\n `Invalid branch names:\\n ${invalidBranches.slice(0, 10).join(\"\\n \")}${\n invalidBranches.length > 10\n ? `\\n ... and ${invalidBranches.length - 10} more`\n : \"\"\n }`\n );\n }\n\n const overallCompliance = Math.round(\n (metrics.taskLinkCompliance + metrics.branchCompliance) / 2\n );\n\n if (overallCompliance >= 90) {\n p.outro(pc.green(\"✓ Excellent compliance! Keep up the good work.\"));\n } else if (overallCompliance >= 70) {\n p.outro(pc.yellow(\"⚠ Good progress, but there's room for improvement.\"));\n } else {\n p.outro(pc.red(\"✗ Compliance needs attention. Review the guidelines.\"));\n }\n}\n","{\n \"name\": \"@raftlabs/raftstack\",\n \"version\": \"1.4.0\",\n \"description\": \"CLI tool for setting up Git hooks, commit conventions, and GitHub integration\",\n \"type\": \"module\",\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"bin\": {\n \"raftstack\": \"./dist/cli.js\"\n },\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n }\n },\n \"files\": [\n \"dist\",\n \"templates\",\n \".claude/skills\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest\",\n \"test:run\": \"vitest run\",\n \"prepublishOnly\": \"pnpm build\",\n \"prepublish\": \"pnpm test:run && pnpm build\",\n \"pack:test\": \"pnpm pack --dry-run\",\n \"publish:test\": \"pnpm pack && tar -xvzf raftlabs-raftstack-*.tgz && rm -rf package raftlabs-raftstack-*.tgz\",\n \"release\": \"standard-version\",\n \"release:patch\": \"standard-version --release-as patch\",\n \"release:minor\": \"standard-version --release-as minor\",\n \"release:major\": \"standard-version --release-as major\",\n \"release:first\": \"standard-version --first-release\"\n },\n \"keywords\": [\n \"cli\",\n \"git-hooks\",\n \"husky\",\n \"commitlint\",\n \"lint-staged\",\n \"developer-experience\"\n ],\n \"author\": \"Aravind Jaimon <dev@aravindjaimon.com>\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/Raft-Labs/raftstack.git\"\n },\n \"homepage\": \"https://github.com/Raft-Labs/raftstack#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/Raft-Labs/raftstack/issues\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"registry\": \"https://registry.npmjs.org/\"\n },\n \"packageManager\": \"pnpm@10.23.0\",\n \"engines\": {\n \"node\": \">=18\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^20.10.0\",\n \"standard-version\": \"^9.5.0\",\n \"tsup\": \"^8.0.0\",\n \"typescript\": \"^5.3.0\",\n \"vitest\": \"^1.0.0\"\n },\n \"dependencies\": {\n \"@clack/prompts\": \"^0.7.0\",\n \"commander\": \"^12.0.0\",\n \"execa\": \"^8.0.0\",\n \"picocolors\": \"^1.0.0\"\n }\n}\n"],"mappings":";;;AAAA,SAAS,eAAe;;;ACAxB,YAAYA,QAAO;AACnB,OAAOC,SAAQ;;;ACDf,YAAY,OAAO;AACnB,OAAO,QAAQ;;;ACDf,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,gBAAgB;AACzB,SAAS,QAAAC,aAAY;;;ACFrB,SAAS,YAAY,oBAAoB;AACzC,SAAS,YAAY;AAMd,IAAM,mBAA+D;AAAA,EAC1E,KAAK;AAAA,IACH,MAAM;AAAA,IACN,SAAS;AAAA,IACT,KAAK;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,UAAU;AAAA,EACZ;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,KAAK;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,UAAU;AAAA,EACZ;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,KAAK;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,UAAU;AAAA,EACZ;AAAA,EACA,cAAc;AAAA,IACZ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,KAAK;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,IACV,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,UAAU;AAAA,EACZ;AACF;AAOO,SAAS,kBAAkB,WAAiD;AACjF,QAAM,kBAAkB,KAAK,WAAW,cAAc;AAEtD,MAAI,CAAC,WAAW,eAAe,GAAG;AAChC,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,cAA2B,KAAK,MAAM,aAAa,iBAAiB,OAAO,CAAC;AAClF,UAAM,iBAAiB,YAAY;AAEnC,QAAI,CAAC,gBAAgB;AACnB,aAAO;AAAA,IACT;AAGA,UAAM,QAAQ,eAAe,MAAM,eAAe;AAClD,QAAI,OAAO;AACT,YAAM,eAAe,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE;AACjD,aAAO,gBAAgB,IAAI,eAAe;AAAA,IAC5C;AAEA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAQO,SAAS,qBAAqB,WAA8C;AAEjF,MAAI,WAAW,KAAK,WAAW,gBAAgB,CAAC,GAAG;AACjD,WAAO,iBAAiB;AAAA,EAC1B;AAGA,MAAI,WAAW,KAAK,WAAW,WAAW,CAAC,GAAG;AAC5C,UAAM,cAAc,kBAAkB,SAAS;AAG/C,QAAI,gBAAgB,cAAc;AAChC,aAAO,iBAAiB,YAAY;AAAA,IACtC;AAGA,WAAO,iBAAiB;AAAA,EAC1B;AAGA,MAAI,WAAW,KAAK,WAAW,mBAAmB,CAAC,GAAG;AACpD,WAAO,iBAAiB;AAAA,EAC1B;AAGA,SAAO;AACT;AAOO,SAAS,sBAAsB,MAA0C;AAC9E,SAAO,iBAAiB,IAAI;AAC9B;AAOO,SAAS,6BAA6B,IAAgC;AAC3E,UAAQ,GAAG,MAAM;AAAA,IACf,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO,GAAG;AAAA,EACd;AACF;;;ADrIA,IAAM,aAA+B;AAAA,EACnC,EAAE,MAAM,WAAW,MAAM,MAAM,YAAY,OAAO;AAAA,EAClD,EAAE,MAAM,cAAc,MAAM,SAAS,YAAY,OAAO;AAAA,EACxD,EAAE,MAAM,uBAAuB,MAAM,kBAAkB,YAAY,OAAO;AAAA,EAC1E,EAAE,MAAM,cAAc,MAAM,kBAAkB,YAAY,SAAS;AACrE;AAKA,eAAsB,kBACpB,YAAoB,QAAQ,IAAI,GACN;AAC1B,QAAM,kBAA4B,CAAC;AACnC,MAAI,eAA4B;AAChC,MAAI,aAAwC;AAE5C,aAAW,aAAa,YAAY;AAClC,UAAM,WAAWC,MAAK,WAAW,UAAU,IAAI;AAC/C,QAAIC,YAAW,QAAQ,GAAG;AACxB,sBAAgB,KAAK,UAAU,IAAI;AAGnC,UACE,eAAe,SACd,eAAe,YAAY,UAAU,eAAe,QACrD;AACA,uBAAe,UAAU;AACzB,qBAAa,UAAU;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,gBAAgB,SAAS,KAAK,eAAe,OAAO;AACtD,iBAAa;AAAA,EACf;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,YAAY;AAAA,EACd;AACF;AAKA,eAAsB,cACpB,YAAoB,QAAQ,IAAI,GACd;AAClB,QAAM,eAAeD,MAAK,WAAW,eAAe;AACpD,SAAOC,YAAW,YAAY;AAChC;AAKA,eAAsB,UACpB,YAAoB,QAAQ,IAAI,GACd;AAClB,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,aAAW,QAAQ,aAAa;AAC9B,QAAIA,YAAWD,MAAK,WAAW,IAAI,CAAC,GAAG;AACrC,aAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAI;AACF,UAAM,UAAUA,MAAK,WAAW,cAAc;AAC9C,QAAIC,YAAW,OAAO,GAAG;AACvB,YAAM,UAAU,MAAM,SAAS,SAAS,OAAO;AAC/C,YAAM,MAAM,KAAK,MAAM,OAAO;AAC9B,UAAI,IAAI,cAAc;AACpB,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAKA,eAAsB,YACpB,YAAoB,QAAQ,IAAI,GACd;AAClB,QAAM,gBAAgB;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,aAAW,QAAQ,eAAe;AAChC,QAAIA,YAAWD,MAAK,WAAW,IAAI,CAAC,GAAG;AACrC,aAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAI;AACF,UAAM,UAAUA,MAAK,WAAW,cAAc;AAC9C,QAAIC,YAAW,OAAO,GAAG;AACvB,YAAM,UAAU,MAAM,SAAS,SAAS,OAAO;AAC/C,YAAM,MAAM,KAAK,MAAM,OAAO;AAC9B,UAAI,IAAI,UAAU;AAChB,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAyBO,SAAS,0BAA0B,MAA2B;AACnE,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;;;AD/JO,SAAS,cAAoB;AAClC,UAAQ,IAAI;AACZ,EAAE,QAAM,GAAG,OAAO,GAAG,MAAM,aAAa,CAAC,CAAC;AAC1C,UAAQ;AAAA,IACN,GAAG,IAAI,sEAAsE;AAAA,EAC/E;AACF;AAKA,eAAsB,kBACpB,WACsB;AACtB,QAAM,cAAc,0BAA0B,UAAU,IAAI;AAC5D,QAAM,iBACJ,UAAU,eAAe,SACrB,GAAG,MAAM,iBAAiB,IAC1B,UAAU,eAAe,WACvB,GAAG,OAAO,mBAAmB,IAC7B,GAAG,IAAI,gBAAgB;AAE/B,QAAM,YAAY,MAAQ,UAAQ;AAAA,IAChC,SAAS,YAAY,GAAG,KAAK,WAAW,CAAC,KAAK,cAAc;AAAA,IAC5D,cAAc;AAAA,EAChB,CAAC;AAED,MAAM,WAAS,SAAS,GAAG;AACzB,IAAE,SAAO,kBAAkB;AAC3B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,WAAW;AACb,WAAO,UAAU;AAAA,EACnB;AAEA,QAAM,WAAW,MAAQ,SAAO;AAAA,IAC9B,SAAS;AAAA,IACT,SAAS;AAAA,MACP,EAAE,OAAO,MAAM,OAAO,cAAc;AAAA,MACpC,EAAE,OAAO,SAAS,OAAO,YAAY;AAAA,MACrC,EAAE,OAAO,kBAAkB,OAAO,iBAAiB;AAAA,MACnD,EAAE,OAAO,UAAU,OAAO,iBAAiB;AAAA,IAC7C;AAAA,EACF,CAAC;AAED,MAAM,WAAS,QAAQ,GAAG;AACxB,IAAE,SAAO,kBAAkB;AAC3B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,SAAO;AACT;AAKA,eAAsB,oBAAiD;AACrE,QAAM,WAAW,MAAQ,UAAQ;AAAA,IAC/B,SAAS;AAAA,IACT,cAAc;AAAA,EAChB,CAAC;AAED,MAAM,WAAS,QAAQ,GAAG;AACxB,IAAE,SAAO,kBAAkB;AAC3B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,MAAQ,OAAK;AAAA,IAC3B,SAAS;AAAA,IACT,aAAa;AAAA,IACb,UAAU,CAAC,UAAU;AACnB,UAAI,CAAC,MAAO,QAAO;AACnB,UAAI,CAAC,MAAM,WAAW,wBAAwB,GAAG;AAC/C,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AAED,MAAM,WAAS,OAAO,GAAG;AACvB,IAAE,SAAO,kBAAkB;AAC3B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,SAAO;AACT;AAKA,eAAsB,iBAAwC;AAC5D,QAAM,WAAW,MAAQ,SAAO;AAAA,IAC9B,SAAS;AAAA,IACT,SAAS;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF,CAAC;AAED,MAAM,WAAS,QAAQ,GAAG;AACxB,IAAE,SAAO,kBAAkB;AAC3B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,SAAO;AACT;AAKA,eAAsB,mBAAsC;AAC1D,QAAM,YAAY,MAAQ,UAAQ;AAAA,IAChC,SAAS;AAAA,IACT,cAAc;AAAA,EAChB,CAAC;AAED,MAAM,WAAS,SAAS,GAAG;AACzB,IAAE,SAAO,kBAAkB;AAC3B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,MAAI,CAAC,WAAW;AACd,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,SAAS,MAAQ,OAAK;AAAA,IAC1B,SAAS;AAAA,IACT,aAAa;AAAA,IACb,UAAU,CAAC,UAAU;AACnB,UAAI,CAAC,MAAM,KAAK,EAAG,QAAO;AAC1B,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AAED,MAAM,WAAS,MAAM,GAAG;AACtB,IAAE,SAAO,kBAAkB;AAC3B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,SAAO,OACJ,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO,EACd,IAAI,CAAC,MAAO,EAAE,WAAW,GAAG,IAAI,IAAI,IAAI,CAAC,EAAG;AACjD;AAKA,eAAsB,qBACpB,WAC6B;AAE7B,QAAM,WAAW,qBAAqB,SAAS;AAE/C,MAAI,UAAU;AACZ,UAAM,cAAc,6BAA6B,QAAQ;AACzD,IAAE,MAAI,KAAK,YAAY,GAAG,KAAK,WAAW,CAAC,gBAAgB;AAC3D,WAAO;AAAA,EACT;AAGA,EAAE,MAAI,KAAK,sCAAsC;AAEjD,QAAM,WAAW,MAAQ,SAAO;AAAA,IAC9B,SAAS;AAAA,IACT,SAAS;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF,CAAC;AAED,MAAM,WAAS,QAAQ,GAAG;AACxB,IAAE,SAAO,kBAAkB;AAC3B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,SAAO,sBAAsB,QAA0B;AACzD;AAKA,eAAsB,mBACpB,QACkB;AAClB,UAAQ,IAAI;AACZ,EAAE;AAAA,IACA;AAAA,MACE,GAAG,GAAG,KAAK,eAAe,CAAC,IAAI,0BAA0B,OAAO,WAAW,CAAC;AAAA,MAC5E,GAAG,GAAG,KAAK,kBAAkB,CAAC,IAAI,6BAA6B,OAAO,cAAc,CAAC;AAAA,MACrF,GAAG,GAAG,KAAK,aAAa,CAAC,IAAI,OAAO,iBAAiB,QAAQ,IAAI;AAAA,MACjE,GAAG,GAAG,KAAK,SAAS,CAAC,IAAI,OAAO,aAAa,QAAQ,IAAI;AAAA,MACzD,GAAG,GAAG,KAAK,WAAW,CAAC,IAAI,OAAO,eAAe,QAAQ,IAAI;AAAA,MAC7D,GAAG,GAAG,KAAK,oBAAoB,CAAC,IAAI,OAAO,eAAe,QAAQ,IAAI;AAAA,MACtE,GAAG,GAAG,KAAK,YAAY,CAAC,IAAI,OAAO,iBAAiB,SAAS,SAAS,OAAO,YAAY;AAAA,MACzF,GAAG,GAAG,KAAK,aAAa,CAAC,IAAI,OAAO,WAAW,SAAS,IAAI,OAAO,WAAW,KAAK,IAAI,IAAI,MAAM;AAAA,IACnG,EAAE,KAAK,IAAI;AAAA,IACX;AAAA,EACF;AAEA,QAAM,YAAY,MAAQ,UAAQ;AAAA,IAChC,SAAS;AAAA,IACT,cAAc;AAAA,EAChB,CAAC;AAED,MAAM,WAAS,SAAS,GAAG;AACzB,IAAE,SAAO,kBAAkB;AAC3B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,SAAO;AACT;AAKA,eAAsB,cACpB,YAAoB,QAAQ,IAAI,GACC;AACjC,cAAY;AAGZ,QAAM,YAAY,MAAM,kBAAkB,SAAS;AACnD,QAAM,cAAc,MAAM,kBAAkB,SAAS;AAGrD,QAAM,iBAAiB,MAAM,qBAAqB,SAAS;AAG3D,QAAM,iBAAiB,MAAM,cAAc,SAAS;AACpD,QAAM,aAAa,MAAM,UAAU,SAAS;AAC5C,QAAM,eAAe,MAAM,YAAY,SAAS;AAGhD,QAAM,eAAe,MAAM,kBAAkB;AAC7C,QAAM,eAAe,MAAM,eAAe;AAC1C,QAAM,aAAa,MAAM,iBAAiB;AAE1C,QAAM,SAA0B;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,QAAM,YAAY,MAAM,mBAAmB,MAAM;AAEjD,MAAI,CAAC,WAAW;AACd,IAAE,SAAO,kBAAkB;AAC3B,WAAO;AAAA,EACT;AAEA,SAAO;AACT;;;AG/TA,SAAS,QAAAC,aAAY;;;ACArB,SAAS,cAAAC,mBAAkB;AAC3B;AAAA,EACE;AAAA,EACA,YAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,SAAS,QAAAC,aAAY;AAK9B,eAAsB,UAAU,SAAgC;AAC9D,MAAI,CAACF,YAAW,OAAO,GAAG;AACxB,UAAM,MAAM,SAAS,EAAE,WAAW,KAAK,CAAC;AAAA,EAC1C;AACF;AAMA,eAAsB,WAAW,UAA0C;AACzE,MAAI,CAACA,YAAW,QAAQ,GAAG;AACzB,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,GAAG,QAAQ;AAC9B,QAAM,SAAS,UAAU,UAAU;AACnC,SAAO;AACT;AAKA,eAAsB,cACpB,UACA,SACA,UAII,CAAC,GACmD;AACxD,QAAM,EAAE,SAAS,MAAM,YAAY,MAAM,aAAa,MAAM,IAAI;AAGhE,QAAM,SAASA,YAAW,QAAQ;AAGlC,MAAI,UAAU,CAAC,WAAW;AACxB,WAAO,EAAE,SAAS,OAAO,UAAU,KAAK;AAAA,EAC1C;AAGA,MAAI,WAA0B;AAC9B,MAAI,UAAU,QAAQ;AACpB,eAAW,MAAM,WAAW,QAAQ;AAAA,EACtC;AAGA,QAAM,UAAU,QAAQ,QAAQ,CAAC;AAGjC,QAAM,UAAU,UAAU,SAAS,OAAO;AAG1C,MAAI,YAAY;AACd,UAAM,MAAM,UAAU,GAAK;AAAA,EAC7B;AAEA,SAAO,EAAE,SAAS,MAAM,SAAS;AACnC;AAeO,SAAS,WAAW,UAA2B;AACpD,SAAOG,YAAW,QAAQ;AAC5B;;;ADnFA,SAAS,iBAAiB,aAA0B,IAAgC;AAElF,MAAI,gBAAgB,MAAM;AACxB,WAAO;AAAA;AAAA;AAAA,EAGT,GAAG,IAAI;AAAA;AAAA,EAEP;AAEA,SAAO;AAAA;AAAA;AAAA,EAGP,GAAG,IAAI;AAAA;AAET;AAKA,SAAS,iBAAiB,IAAgC;AACxD,SAAO;AAAA;AAAA;AAAA,EAGP,GAAG,IAAI;AAAA;AAET;AAKA,SAAS,eAAe,IAAgC;AACtD,SAAO;AAAA;AAAA;AAAA,EAGP,GAAG,IAAI;AAAA;AAET;AAKA,eAAsB,mBACpB,WACA,aACA,IAC0B;AAC1B,QAAM,SAA0B;AAAA,IAC9B,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,IACX,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,EACb;AAEA,QAAM,WAAWC,MAAK,WAAW,QAAQ;AACzC,QAAM,UAAU,QAAQ;AAGxB,QAAM,gBAAgBA,MAAK,UAAU,YAAY;AACjD,QAAM,kBAAkB,MAAM;AAAA,IAC5B;AAAA,IACA,iBAAiB,aAAa,EAAE;AAAA,IAChC,EAAE,YAAY,MAAM,QAAQ,KAAK;AAAA,EACnC;AACA,MAAI,gBAAgB,SAAS;AAC3B,WAAO,QAAQ,KAAK,mBAAmB;AACvC,QAAI,gBAAgB,UAAU;AAC5B,aAAO,SAAS,KAAK,gBAAgB,QAAQ;AAAA,IAC/C;AAAA,EACF;AAGA,QAAM,gBAAgBA,MAAK,UAAU,YAAY;AACjD,QAAM,kBAAkB,MAAM;AAAA,IAC5B;AAAA,IACA,iBAAiB,EAAE;AAAA,IACnB,EAAE,YAAY,MAAM,QAAQ,KAAK;AAAA,EACnC;AACA,MAAI,gBAAgB,SAAS;AAC3B,WAAO,QAAQ,KAAK,mBAAmB;AACvC,QAAI,gBAAgB,UAAU;AAC5B,aAAO,SAAS,KAAK,gBAAgB,QAAQ;AAAA,IAC/C;AAAA,EACF;AAGA,QAAM,cAAcA,MAAK,UAAU,UAAU;AAC7C,QAAM,gBAAgB,MAAM,cAAc,aAAa,eAAe,EAAE,GAAG;AAAA,IACzE,YAAY;AAAA,IACZ,QAAQ;AAAA,EACV,CAAC;AACD,MAAI,cAAc,SAAS;AACzB,WAAO,QAAQ,KAAK,iBAAiB;AACrC,QAAI,cAAc,UAAU;AAC1B,aAAO,SAAS,KAAK,cAAc,QAAQ;AAAA,IAC7C;AAAA,EACF;AAEA,SAAO;AACT;;;AE1GA,SAAS,QAAAC,aAAY;AASrB,SAAS,oBAAoB,cAA+B;AAC1D,QAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkCnB,MAAI,cAAc;AAEhB,WAAO,GAAG,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0BtB;AAEA,SAAO,GAAG,UAAU;AAAA;AAAA;AAAA;AAAA;AAKtB;AAKA,eAAsB,mBACpB,WACA,cAC0B;AAC1B,QAAM,SAA0B;AAAA,IAC9B,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,IACX,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,EACb;AAEA,QAAM,aAAaC,MAAK,WAAW,sBAAsB;AACzD,QAAM,cAAc,MAAM;AAAA,IACxB;AAAA,IACA,oBAAoB,YAAY;AAAA,IAChC,EAAE,QAAQ,KAAK;AAAA,EACjB;AAEA,MAAI,YAAY,SAAS;AACvB,WAAO,QAAQ,KAAK,sBAAsB;AAC1C,QAAI,YAAY,UAAU;AACxB,aAAO,SAAS,KAAK,YAAY,QAAQ;AAAA,IAC3C;AAAA,EACF;AAEA,SAAO;AACT;;;AC9GA,SAAS,QAAAC,aAAY;AAOrB,SAAS,eAAe,cAA+B;AACrD,QAAM,eAAe,eACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oCAUA;AAAA;AAAA;AAIJ,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAmDe,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUpC;AAKA,eAAsB,cACpB,WACA,cAC0B;AAC1B,QAAM,SAA0B;AAAA,IAC9B,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,IACX,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,EACb;AAEA,QAAM,aAAaC,MAAK,WAAW,OAAO;AAC1C,QAAM,cAAc,MAAM;AAAA,IACxB;AAAA,IACA,KAAK,UAAU,EAAE,MAAM,sBAAsB,GAAG,MAAM,CAAC,IAAI;AAAA,IAC3D,EAAE,QAAQ,KAAK;AAAA,EACjB;AAEA,MAAI,YAAY,SAAS;AACvB,WAAO,QAAQ,KAAK,OAAO;AAC3B,QAAI,YAAY,UAAU;AACxB,aAAO,SAAS,KAAK,YAAY,QAAQ;AAAA,IAC3C;AAAA,EACF;AAGA,QAAM,eAAeA,MAAK,WAAW,cAAc;AACnD,QAAM,iBAAiB,MAAM;AAAA,IAC3B;AAAA,IACA,eAAe,YAAY;AAAA,IAC3B,EAAE,QAAQ,KAAK;AAAA,EACjB;AAEA,MAAI,eAAe,SAAS;AAC1B,WAAO,QAAQ,KAAK,cAAc;AAClC,QAAI,eAAe,UAAU;AAC3B,aAAO,SAAS,KAAK,eAAe,QAAQ;AAAA,IAC9C;AAAA,EACF;AAEA,SAAO;AACT;;;AClIA,SAAS,QAAAC,aAAY;AAOrB,SAAS,oBACP,aACA,YACA,cACA,gBACQ;AACR,QAAM,QAA2C,CAAC;AAGlD,MAAI,gBAAgB;AAClB,UAAM,aAAuB,CAAC;AAC9B,QAAI,YAAY;AACd,iBAAW,KAAK,cAAc;AAAA,IAChC;AACA,QAAI,cAAc;AAChB,iBAAW,KAAK,kBAAkB;AAAA,IACpC;AACA,QAAI,WAAW,SAAS,GAAG;AACzB,YAAM,YAAY,IAAI;AAAA,IACxB;AAAA,EACF;AAGA,QAAM,aAAuB,CAAC;AAC9B,MAAI,YAAY;AACd,eAAW,KAAK,cAAc;AAAA,EAChC;AACA,MAAI,cAAc;AAChB,eAAW,KAAK,kBAAkB;AAAA,EACpC;AACA,MAAI,WAAW,SAAS,GAAG;AACzB,UAAM,oBAAoB,IAAI;AAAA,EAChC;AAGA,MAAI,cAAc;AAChB,UAAM,sBAAsB,IAAI;AAAA,EAClC;AAGA,MAAI,cAAc;AAChB,UAAM,mBAAmB,IAAI;AAAA,EAC/B;AAGA,MAAI,gBAAgB,MAAM;AACxB,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMT,OAAO,QAAQ,KAAK,EACnB,IAAI,CAAC,CAAC,SAAS,QAAQ,MAAM;AAC5B,YAAM,SAAS,MAAM,QAAQ,QAAQ,IACjC,KAAK,UAAU,QAAQ,IACvB,KAAK,UAAU,CAAC,QAAQ,CAAC;AAC7B,aAAO,MAAM,OAAO,MAAM,MAAM;AAAA,IAClC,CAAC,EACA,KAAK,IAAI,CAAC;AAAA;AAAA;AAAA,EAGX;AAGA,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMP,OAAO,QAAQ,KAAK,EACnB,IAAI,CAAC,CAAC,SAAS,QAAQ,MAAM;AAC5B,UAAM,SAAS,MAAM,QAAQ,QAAQ,IACjC,KAAK,UAAU,QAAQ,IACvB,KAAK,UAAU,CAAC,QAAQ,CAAC;AAC7B,WAAO,MAAM,OAAO,MAAM,MAAM;AAAA,EAClC,CAAC,EACA,KAAK,IAAI,CAAC;AAAA;AAAA;AAGb;AAKA,eAAsB,mBACpB,WACA,aACA,YACA,cACA,gBAC0B;AAC1B,QAAM,SAA0B;AAAA,IAC9B,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,IACX,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,EACb;AAEA,QAAM,aAAaC,MAAK,WAAW,kBAAkB;AACrD,QAAM,cAAc,MAAM;AAAA,IACxB;AAAA,IACA,oBAAoB,aAAa,YAAY,cAAc,cAAc;AAAA,IACzE,EAAE,QAAQ,KAAK;AAAA,EACjB;AAEA,MAAI,YAAY,SAAS;AACvB,WAAO,QAAQ,KAAK,kBAAkB;AACtC,QAAI,YAAY,UAAU;AACxB,aAAO,SAAS,KAAK,YAAY,QAAQ;AAAA,IAC3C;AAAA,EACF;AAEA,SAAO;AACT;;;AC1HA,SAAS,YAAAC,WAAU,aAAAC,kBAAiB;AACpC,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,QAAAC,aAAY;AAMrB,eAAsB,gBACpB,YAAoB,QAAQ,IAAI,GACV;AACtB,QAAM,UAAUA,MAAK,WAAW,cAAc;AAE9C,MAAI,CAACD,YAAW,OAAO,GAAG;AACxB,UAAM,IAAI,MAAM,4BAA4B,SAAS,EAAE;AAAA,EACzD;AAEA,QAAM,UAAU,MAAMF,UAAS,SAAS,OAAO;AAC/C,SAAO,KAAK,MAAM,OAAO;AAC3B;AAKA,eAAsB,iBACpB,KACA,YAAoB,QAAQ,IAAI,GACjB;AACf,QAAM,UAAUG,MAAK,WAAW,cAAc;AAC9C,QAAM,UAAU,KAAK,UAAU,KAAK,MAAM,CAAC,IAAI;AAC/C,QAAMF,WAAU,SAAS,SAAS,OAAO;AAC3C;AAKO,SAAS,aACd,KACA,SACA,YAAqB,OACR;AACb,QAAM,kBAAkB,IAAI,WAAW,CAAC;AACxC,QAAM,aAAqC,EAAE,GAAG,gBAAgB;AAEhE,aAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,OAAO,GAAG;AACrD,QAAI,aAAa,CAAC,gBAAgB,IAAI,GAAG;AACvC,iBAAW,IAAI,IAAI;AAAA,IACrB;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS;AAAA,EACX;AACF;AAKO,SAAS,qBACd,KACA,MACa;AACb,QAAM,eAAe,IAAI,mBAAmB,CAAC;AAE7C,SAAO;AAAA,IACL,GAAG;AAAA,IACH,iBAAiB;AAAA,MACf,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AAAA,EACF;AACF;AAKO,SAAS,qBACd,KACA,KACA,QACA,YAAqB,OACR;AACb,MAAI,CAAC,aAAa,IAAI,GAAG,GAAG;AAC1B,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,CAAC,GAAG,GAAG;AAAA,EACT;AACF;AAkBO,IAAM,6BAAqD;AAAA,EAChE,mBAAmB;AAAA,EACnB,mCAAmC;AAAA,EACnC,UAAU;AAAA,EACV,KAAK;AAAA,EACL,OAAO;AAAA,EACP,eAAe;AAAA,EACf,wBAAwB;AAC1B;;;ACnGA,SAAS,4BAAoD;AAC3D,SAAO;AAAA,IACL,SACE;AAAA,IACF,UACE;AAAA,EACJ;AACF;AAKA,eAAsB,yBACpB,WAC0B;AAC1B,QAAM,SAA0B;AAAA,IAC9B,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,IACX,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,EACb;AAEA,MAAI;AACF,UAAM,MAAM,MAAM,gBAAgB,SAAS;AAC3C,UAAM,SAAS,0BAA0B;AAEzC,UAAM,aAAa;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,IACF;AAGA,QAAI,KAAK,UAAU,GAAG,MAAM,KAAK,UAAU,UAAU,GAAG;AACtD,YAAM,iBAAiB,YAAY,SAAS;AAC5C,aAAO,SAAS,KAAK,qCAAqC;AAAA,IAC5D,OAAO;AACL,aAAO,QAAQ,KAAK,8CAA8C;AAAA,IACpE;AAAA,EACF,SAAS,OAAO;AAEd,WAAO,QAAQ,KAAK,+CAA+C;AAAA,EACrE;AAEA,SAAO;AACT;;;AChEA,SAAS,QAAAG,aAAY;AAOrB,SAAS,cAAc,UAA2B;AAChD,QAAM,eAAe,WACjB;AAAA;AAAA;AAAA;AAAA,IAKA;AAEJ,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaP,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBd;AAKA,eAAsB,mBACpB,WACA,UAC0B;AAC1B,QAAM,SAA0B;AAAA,IAC9B,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,IACX,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,EACb;AAEA,QAAM,YAAYC,MAAK,WAAW,SAAS;AAC3C,QAAM,UAAU,SAAS;AAEzB,QAAM,eAAeA,MAAK,WAAW,0BAA0B;AAC/D,QAAM,cAAc,MAAM;AAAA,IACxB;AAAA,IACA,cAAc,QAAQ;AAAA,IACtB,EAAE,QAAQ,KAAK;AAAA,EACjB;AAEA,MAAI,YAAY,SAAS;AACvB,WAAO,QAAQ,KAAK,kCAAkC;AACtD,QAAI,YAAY,UAAU;AACxB,aAAO,SAAS,KAAK,YAAY,QAAQ;AAAA,IAC3C;AAAA,EACF;AAEA,SAAO;AACT;;;ACvFA,SAAS,QAAAC,cAAY;AAOrB,SAAS,oBACP,aACA,gBACA,YACA,IACQ;AACR,QAAM,QAAkB,CAAC;AAGzB,QAAM,KAAK;AAAA,kCACqB;AAGhC,QAAM,KAAK;AAAA;AAAA;AAAA;AAAA,6BAIgB;AAG3B,MAAI,GAAG,kBAAkB;AACvB,UAAM,KAAK;AAAA;AAAA;AAAA;AAAA,qBAIM;AAAA,EACnB;AAGA,QAAM,KAAK;AAAA;AAAA,eAEE,GAAG,aAAa,EAAE;AAG/B,MAAI,gBAAgB;AAClB,UAAM,KAAK;AAAA;AAAA,eAEA,GAAG,GAAG,YAAY;AAAA,EAC/B;AAGA,MAAI,YAAY;AACd,UAAM,KAAK;AAAA;AAAA,eAEA,GAAG,GAAG,OAAO;AAAA,EAC1B;AAGA,MAAI,gBAAgB,MAAM;AACxB,UAAM,KAAK;AAAA;AAAA,eAEA,GAAG,GAAG,0CAA0C;AAAA,EAC7D,WAAW,gBAAgB,SAAS;AAClC,UAAM,KAAK;AAAA;AAAA,eAEA,GAAG,GAAG,cAAc;AAAA,EACjC,OAAO;AACL,UAAM,KAAK;AAAA;AAAA,eAEA,GAAG,GAAG,QAAQ;AAAA,EAC3B;AAGA,MAAI,gBAAgB,MAAM;AACxB,UAAM,KAAK;AAAA;AAAA,eAEA,GAAG,GAAG,yCAAyC;AAAA,EAC5D,WAAW,gBAAgB,SAAS;AAClC,UAAM,KAAK;AAAA;AAAA,eAEA,GAAG,GAAG,aAAa;AAAA,EAChC,OAAO;AACL,UAAM,KAAK;AAAA;AAAA,eAEA,GAAG,GAAG,OAAO;AAAA,EAC1B;AAEA,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeP,MAAM,KAAK,IAAI,CAAC;AAAA;AAElB;AAKA,eAAsB,wBACpB,WACA,aACA,gBACA,YACA,IAC0B;AAC1B,QAAM,SAA0B;AAAA,IAC9B,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,IACX,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,EACb;AAEA,QAAM,eAAeC,OAAK,WAAW,WAAW,WAAW;AAC3D,QAAM,UAAU,YAAY;AAG5B,QAAM,eAAeA,OAAK,cAAc,eAAe;AACvD,QAAM,cAAc,MAAM;AAAA,IACxB;AAAA,IACA,oBAAoB,aAAa,gBAAgB,YAAY,EAAE;AAAA,IAC/D,EAAE,QAAQ,KAAK;AAAA,EACjB;AAEA,MAAI,YAAY,SAAS;AACvB,WAAO,QAAQ,KAAK,iCAAiC;AACrD,QAAI,YAAY,UAAU;AACxB,aAAO,SAAS,KAAK,YAAY,QAAQ;AAAA,IAC3C;AAAA,EACF;AAEA,SAAO;AACT;;;AC3IA,SAAS,QAAAC,cAAY;AAOrB,SAAS,qBAAqB,QAA0B;AACtD,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT;AAEA,QAAM,aAAa,OAAO,KAAK,GAAG;AAElC,SAAO;AAAA;AAAA;AAAA;AAAA,IAIL,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQd;AAKA,eAAsB,mBACpB,WACA,QAC0B;AAC1B,QAAM,SAA0B;AAAA,IAC9B,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,IACX,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,EACb;AAEA,QAAM,YAAYC,OAAK,WAAW,SAAS;AAC3C,QAAM,UAAU,SAAS;AAEzB,QAAM,iBAAiBA,OAAK,WAAW,YAAY;AACnD,QAAM,cAAc,MAAM;AAAA,IACxB;AAAA,IACA,qBAAqB,MAAM;AAAA,IAC3B,EAAE,QAAQ,KAAK;AAAA,EACjB;AAEA,MAAI,YAAY,SAAS;AACvB,WAAO,QAAQ,KAAK,oBAAoB;AACxC,QAAI,YAAY,UAAU;AACxB,aAAO,SAAS,KAAK,YAAY,QAAQ;AAAA,IAC3C;AAAA,EACF;AAEA,SAAO;AACT;;;AClEA,SAAS,QAAAC,cAAY;AAOrB,SAAS,sBAA8B;AACrC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBT;AAKA,SAAS,qBAA6B;AACpC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8BT;AAKA,eAAsB,iBACpB,WACA,MAC0B;AAC1B,QAAM,SAA0B;AAAA,IAC9B,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,IACX,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,EACb;AAEA,MAAI,SAAS,QAAQ;AACnB,WAAO;AAAA,EACT;AAEA,MAAI,SAAS,cAAc;AACzB,UAAM,aAAaC,OAAK,WAAW,kBAAkB;AACrD,UAAM,cAAc,MAAM,cAAc,YAAY,oBAAoB,GAAG;AAAA,MACzE,QAAQ;AAAA,IACV,CAAC;AAED,QAAI,YAAY,SAAS;AACvB,aAAO,QAAQ,KAAK,kBAAkB;AACtC,UAAI,YAAY,UAAU;AACxB,eAAO,SAAS,KAAK,YAAY,QAAQ;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AAEA,MAAI,SAAS,WAAW;AACtB,UAAM,eAAeA,OAAK,WAAW,WAAW,WAAW;AAC3D,UAAM,UAAU,YAAY;AAE5B,UAAM,eAAeA,OAAK,cAAc,oBAAoB;AAC5D,UAAM,cAAc,MAAM,cAAc,cAAc,mBAAmB,GAAG;AAAA,MAC1E,QAAQ;AAAA,IACV,CAAC;AAED,QAAI,YAAY,SAAS;AACvB,aAAO,QAAQ,KAAK,sCAAsC;AAC1D,UAAI,YAAY,UAAU;AACxB,eAAO,SAAS,KAAK,YAAY,QAAQ;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;AClHA,SAAS,QAAAC,cAAY;AAOrB,SAAS,0BAAkC;AACzC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2GT;AAKA,eAAsB,6BACpB,WAC0B;AAC1B,QAAM,SAA0B;AAAA,IAC9B,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,IACX,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,EACb;AAEA,QAAM,UAAUC,OAAK,WAAW,SAAS;AACzC,QAAM,UAAU,OAAO;AAEvB,QAAM,WAAWA,OAAK,SAAS,4BAA4B;AAC3D,QAAM,cAAc,MAAM,cAAc,UAAU,wBAAwB,GAAG;AAAA,IAC3E,QAAQ;AAAA,EACV,CAAC;AAED,MAAI,YAAY,SAAS;AACvB,WAAO,QAAQ,KAAK,oCAAoC;AACxD,QAAI,YAAY,UAAU;AACxB,aAAO,SAAS,KAAK,YAAY,QAAQ;AAAA,IAC3C;AAAA,EACF;AAEA,SAAO;AACT;;;AClJA,SAAS,QAAAC,cAAY;AAOrB,SAAS,uBAAuB,UAAmB,IAAgC;AACjF,QAAM,eAAe,WACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAiBA;AAEJ,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BAOoB,GAAG,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAyBrC,GAAG,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsCN,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0Cd;AAKA,eAAsB,qBACpB,WACA,UACA,IAC0B;AAC1B,QAAM,SAA0B;AAAA,IAC9B,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,IACX,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,EACb;AAEA,QAAM,mBAAmBC,OAAK,WAAW,iBAAiB;AAC1D,QAAM,cAAc,MAAM;AAAA,IACxB;AAAA,IACA,uBAAuB,UAAU,EAAE;AAAA,IACnC,EAAE,QAAQ,KAAK;AAAA,EACjB;AAEA,MAAI,YAAY,SAAS;AACvB,WAAO,QAAQ,KAAK,iBAAiB;AACrC,QAAI,YAAY,UAAU;AACxB,aAAO,SAAS,KAAK,YAAY,QAAQ;AAAA,IAC3C;AAAA,EACF;AAEA,SAAO;AACT;;;AC5KA,SAAS,QAAAC,cAAY;AAOrB,SAAS,oBAA4B;AACnC,SAAO,KAAK;AAAA,IACV;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,WAAW;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AACN;AAKA,SAAS,oBAA4B;AACnC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0BT;AAKA,SAAS,kBAAkB,WAA4B;AACrD,QAAM,gBAAgB;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO,cAAc,KAAK,CAAC,SAAS,WAAWC,OAAK,WAAW,IAAI,CAAC,CAAC;AACvE;AAKA,eAAsB,iBACpB,WAC0B;AAC1B,QAAM,SAA0B;AAAA,IAC9B,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,IACX,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,EACb;AAGA,MAAI,kBAAkB,SAAS,GAAG;AAChC,WAAO,QAAQ,KAAK,8BAA8B;AAClD,WAAO;AAAA,EACT;AAGA,QAAM,aAAaA,OAAK,WAAW,aAAa;AAChD,QAAM,eAAe,MAAM,cAAc,YAAY,kBAAkB,GAAG;AAAA,IACxE,QAAQ;AAAA,EACV,CAAC;AAED,MAAI,aAAa,SAAS;AACxB,WAAO,QAAQ,KAAK,aAAa;AACjC,QAAI,aAAa,UAAU;AACzB,aAAO,SAAS,KAAK,aAAa,QAAQ;AAAA,IAC5C;AAAA,EACF;AAGA,QAAM,aAAaA,OAAK,WAAW,iBAAiB;AACpD,QAAM,eAAe,MAAM,cAAc,YAAY,kBAAkB,GAAG;AAAA,IACxE,QAAQ;AAAA,IACR,WAAW;AAAA;AAAA,EACb,CAAC;AAED,MAAI,aAAa,SAAS;AACxB,WAAO,QAAQ,KAAK,iBAAiB;AACrC,QAAI,aAAa,UAAU;AACzB,aAAO,SAAS,KAAK,aAAa,QAAQ;AAAA,IAC5C;AAAA,EACF,OAAO;AACL,WAAO,QAAQ,KAAK,kCAAkC;AAAA,EACxD;AAEA,SAAO;AACT;;;AC7HA,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,SAAS,YAAAC,iBAAgB;AAClC,SAAS,QAAAC,QAAM,WAAAC,gBAAe;AAC9B,SAAS,qBAAqB;AAO9B,SAAS,sBAA8B;AAGrC,QAAM,kBAAkB,cAAc,YAAY,GAAG;AACrD,QAAM,cAAcC,OAAKC,SAAQ,eAAe,GAAG,IAAI;AACvD,SAAOD,OAAK,aAAa,WAAW,QAAQ;AAC9C;AAKA,eAAe,cACb,QACA,SACA,QACA,SACe;AACf,QAAM,UAAU,OAAO;AAEvB,QAAM,UAAU,MAAM,QAAQ,QAAQ,EAAE,eAAe,KAAK,CAAC;AAE7D,aAAW,SAAS,SAAS;AAC3B,UAAM,UAAUA,OAAK,QAAQ,MAAM,IAAI;AACvC,UAAM,WAAWA,OAAK,SAAS,MAAM,IAAI;AACzC,UAAM,eAAe,SAAS,QAAQ,UAAU,KAAK,EAAE;AAEvD,QAAI,MAAM,YAAY,GAAG;AACvB,YAAM,cAAc,SAAS,UAAU,QAAQ,OAAO;AAAA,IACxD,OAAO;AAEL,UAAIE,YAAW,QAAQ,GAAG;AAExB,cAAM,aAAa,MAAM,WAAW,QAAQ;AAC5C,YAAI,YAAY;AACd,iBAAO,SAAS,KAAK,YAAY;AAAA,QACnC;AAAA,MACF;AAGA,YAAMC,UAAS,SAAS,QAAQ;AAChC,aAAO,QAAQ,KAAK,YAAY;AAAA,IAClC;AAAA,EACF;AACF;AAQA,eAAsB,qBACpB,WAC0B;AAC1B,QAAM,SAA0B;AAAA,IAC9B,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,IACX,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,EACb;AAEA,QAAM,mBAAmB,oBAAoB;AAC7C,QAAM,kBAAkBH,OAAK,WAAW,WAAW,QAAQ;AAG3D,MAAI,CAACE,YAAW,gBAAgB,GAAG;AAEjC,YAAQ;AAAA,MACN;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAGA,QAAM,UAAUF,OAAK,WAAW,SAAS,CAAC;AAG1C,QAAM,cAAc,kBAAkB,iBAAiB,QAAQ,SAAS;AAExE,SAAO;AACT;;;AC1FA,SAAS,cAAAI,mBAAkB;AAC3B,SAAS,YAAAC,iBAAgB;AACzB,SAAS,QAAAC,cAAY;;;ACFrB,SAAS,QAAAC,cAAY;AAOrB,eAAsB,uBACpB,WACA,IAC0B;AAC1B,QAAM,SAA0B;AAAA,IAC9B,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,IACX,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,EACb;AAEA,QAAM,eAAeC,OAAK,WAAW,WAAW,oBAAoB;AAEpE,QAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBhB,GAAG,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA+DN,GAAG,GAAG;AAAA;AAAA;AAAA,EAGN,GAAG,IAAI;AAAA;AAAA;AAAA,EAGP,GAAG,GAAG;AAAA;AAAA;AAAA,EAGN,GAAG,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0BN,QAAM,cAAc,MAAM,cAAc,cAAc,OAAO;AAE7D,MAAI,YAAY,SAAS;AACvB,QAAI,YAAY,UAAU;AACxB,aAAO,SAAS,KAAK,4BAA4B;AACjD,aAAO,SAAS,KAAK,4BAA4B;AAAA,IACnD,OAAO;AACL,aAAO,QAAQ,KAAK,4BAA4B;AAAA,IAClD;AAAA,EACF,OAAO;AACL,WAAO,QAAQ,KAAK,4BAA4B;AAAA,EAClD;AAEA,SAAO;AACT;;;ACzJA,SAAS,aAAa;AACtB,SAAS,cAAAC,mBAAkB;AAC3B,SAAS,QAAAC,cAAY;AAKrB,eAAsB,UACpB,YAAoB,QAAQ,IAAI,GACd;AAElB,MAAID,YAAWC,OAAK,WAAW,MAAM,CAAC,GAAG;AACvC,WAAO;AAAA,EACT;AAGA,MAAI;AACF,UAAM,MAAM,OAAO,CAAC,aAAa,WAAW,GAAG,EAAE,KAAK,UAAU,CAAC;AACjE,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAqCA,eAAsB,mBAAqC;AACzD,MAAI;AACF,UAAM,MAAM,MAAM,CAAC,QAAQ,QAAQ,CAAC;AACpC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,eAAsB,kBACpB,YAAoB,QAAQ,IAAI,GACiB;AACjD,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM,MAAM,MAAM,CAAC,QAAQ,QAAQ,UAAU,YAAY,GAAG;AAAA,MAC7E,KAAK;AAAA,IACP,CAAC;AACD,UAAM,OAAO,KAAK,MAAM,MAAM;AAC9B,WAAO;AAAA,MACL,OAAO,KAAK,MAAM;AAAA,MAClB,MAAM,KAAK;AAAA,IACb;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;ArBtDA,SAAS,aAAa,SAA6C;AACjE,SAAO,QAAQ;AAAA,IACb,CAAC,KAAK,YAAY;AAAA,MAChB,SAAS,CAAC,GAAG,IAAI,SAAS,GAAG,OAAO,OAAO;AAAA,MAC3C,UAAU,CAAC,GAAG,IAAI,UAAU,GAAG,OAAO,QAAQ;AAAA,MAC9C,SAAS,CAAC,GAAG,IAAI,SAAS,GAAG,OAAO,OAAO;AAAA,MAC3C,UAAU,CAAC,GAAG,IAAI,UAAU,GAAG,OAAO,QAAQ;AAAA,IAChD;AAAA,IACA,EAAE,SAAS,CAAC,GAAG,UAAU,CAAC,GAAG,SAAS,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,EACzD;AACF;AAKA,eAAe,yBACb,WACA,SAC0B;AAC1B,QAAM,SAA0B;AAAA,IAC9B,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,IACX,SAAS,CAAC;AAAA,IACV,UAAU,CAAC;AAAA,EACb;AAEA,MAAI;AACF,QAAI,MAAM,MAAM,gBAAgB,SAAS;AAGzC,UAAM,UAAkC;AAAA,MACtC,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAEA,UAAM,aAAa,KAAK,SAAS,KAAK;AAGtC,UAAM,qBAAqB,KAAK,0BAA0B;AAE1D,UAAM,iBAAiB,KAAK,SAAS;AACrC,WAAO,SAAS,KAAK,cAAc;AAAA,EACrC,SAAS,OAAO;AACd,WAAO,QAAQ,KAAK,+BAA+B;AAAA,EACrD;AAEA,SAAO;AACT;AAKA,eAAsB,QAAQ,YAAoB,QAAQ,IAAI,GAAkB;AAE9E,QAAM,SAAS,MAAM,UAAU,SAAS;AACxC,MAAI,CAAC,QAAQ;AACX,IAAE,OAAI;AAAA,MACJC,IAAG;AAAA,QACD;AAAA,MACF;AAAA,IACF;AACA,UAAM,UAAU,MAAQ,WAAQ;AAAA,MAC9B,SAAS;AAAA,MACT,cAAc;AAAA,IAChB,CAAC;AAED,QAAM,YAAS,OAAO,KAAK,CAAC,SAAS;AACnC,MAAE,UAAO,kBAAkB;AAC3B,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAGA,QAAM,SAAS,MAAM,cAAc,SAAS;AAE5C,MAAI,CAAC,QAAQ;AACX;AAAA,EACF;AAGA,QAAMC,WAAY,WAAQ;AAC1B,EAAAA,SAAQ,MAAM,mCAAmC;AAEjD,QAAM,UAA6B,CAAC;AAEpC,MAAI;AAEF,YAAQ;AAAA,MACN,MAAM,mBAAmB,WAAW,OAAO,aAAa,OAAO,cAAc;AAAA,IAC/E;AACA,YAAQ,KAAK,MAAM,mBAAmB,WAAW,OAAO,YAAY,CAAC;AACrE,YAAQ,KAAK,MAAM,cAAc,WAAW,OAAO,YAAY,CAAC;AAChE,YAAQ;AAAA,MACN,MAAM;AAAA,QACJ;AAAA,QACA,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,MACT;AAAA,IACF;AACA,YAAQ,KAAK,MAAM,yBAAyB,SAAS,CAAC;AAGtD,QAAI,CAAC,OAAO,cAAc;AACxB,cAAQ,KAAK,MAAM,iBAAiB,SAAS,CAAC;AAAA,IAChD;AAGA,YAAQ,KAAK,MAAM,mBAAmB,WAAW,CAAC,CAAC,OAAO,YAAY,CAAC;AACvE,YAAQ;AAAA,MACN,MAAM;AAAA,QACJ;AAAA,QACA,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,MACT;AAAA,IACF;AACA,YAAQ,KAAK,MAAM,mBAAmB,WAAW,OAAO,UAAU,CAAC;AACnE,YAAQ,KAAK,MAAM,iBAAiB,WAAW,OAAO,YAAY,CAAC;AACnE,YAAQ,KAAK,MAAM,6BAA6B,SAAS,CAAC;AAG1D,YAAQ;AAAA,MACN,MAAM,qBAAqB,WAAW,CAAC,CAAC,OAAO,cAAc,OAAO,cAAc;AAAA,IACpF;AACA,YAAQ,KAAK,MAAM,uBAAuB,WAAW,OAAO,cAAc,CAAC;AAG3E,YAAQ,KAAK,MAAM,qBAAqB,SAAS,CAAC;AAGlD,YAAQ,KAAK,MAAM,yBAAyB,WAAW,MAAM,CAAC;AAE9D,IAAAA,SAAQ,KAAK,gCAAgC;AAAA,EAC/C,SAAS,OAAO;AACd,IAAAA,SAAQ,KAAK,wBAAwB;AACrC,IAAE,OAAI;AAAA,MACJD,IAAG;AAAA,QACD,UAAU,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AAAA,MACpE;AAAA,IACF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,cAAc,aAAa,OAAO;AAGxC,UAAQ,IAAI;AAEZ,MAAI,YAAY,QAAQ,SAAS,GAAG;AAClC,IAAE,OAAI,QAAQA,IAAG,MAAM,gBAAgB,CAAC;AACxC,eAAW,QAAQ,YAAY,SAAS;AACtC,cAAQ,IAAI,KAAKA,IAAG,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE;AAAA,IACxC;AAAA,EACF;AAEA,MAAI,YAAY,SAAS,SAAS,GAAG;AACnC,YAAQ,IAAI;AACZ,IAAE,OAAI,KAAKA,IAAG,KAAK,iBAAiB,CAAC;AACrC,eAAW,QAAQ,YAAY,UAAU;AACvC,cAAQ,IAAI,KAAKA,IAAG,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE;AAAA,IACxC;AAAA,EACF;AAEA,MAAI,YAAY,QAAQ,SAAS,GAAG;AAClC,YAAQ,IAAI;AACZ,IAAE,OAAI,KAAKA,IAAG,OAAO,0BAA0B,CAAC;AAChD,eAAW,QAAQ,YAAY,SAAS;AACtC,cAAQ,IAAI,KAAKA,IAAG,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE;AAAA,IACxC;AAAA,EACF;AAEA,MAAI,YAAY,SAAS,SAAS,GAAG;AACnC,YAAQ,IAAI;AACZ,IAAE,OAAI,KAAKA,IAAG,IAAI,kBAAkB,CAAC;AACrC,eAAW,QAAQ,YAAY,UAAU;AACvC,cAAQ,IAAI,KAAKA,IAAG,IAAI,QAAG,CAAC,IAAI,IAAI,EAAE;AAAA,IACxC;AAAA,EACF;AAGA,UAAQ,IAAI;AACZ,EAAE;AAAA,IACA;AAAA,MACE,GAAGA,IAAG,KAAK,IAAI,CAAC,QAAQA,IAAG,OAAO,OAAO,eAAe,OAAO,CAAC;AAAA,MAChE,GAAGA,IAAG,KAAK,IAAI,CAAC;AAAA,MAChB,GAAGA,IAAG,KAAK,IAAI,CAAC,QAAQA,IAAG,OAAO,GAAG,OAAO,eAAe,GAAG,SAAS,CAAC;AAAA,MACxE,GAAGA,IAAG,KAAK,IAAI,CAAC;AAAA,IAClB,EAAE,KAAK,IAAI;AAAA,IACX;AAAA,EACF;AAEA,EAAE,SAAMA,IAAG,MAAM,mDAA4C,CAAC;AAChE;;;AsBpOA,YAAYE,QAAO;AACnB,OAAOC,SAAQ;AACf,SAAS,SAAAC,cAAa;AAqCtB,SAAS,mBAAmB,QAA0C;AACpE,SAAO;AAAA,IACL;AAAA,IACA,iBAAiB;AAAA,IACjB,qBAAqB;AAAA,IACrB,mBAAmB;AAAA,IACnB,qBAAqB;AAAA,IACrB,cAAc,CAAC,OAAO;AAAA,IACtB,+BAA+B;AAAA,IAC/B,gBAAgB;AAAA,IAChB,kBAAkB;AAAA,IAClB,gBAAgB;AAAA,EAClB;AACF;AAKA,SAAS,yBAAyB,UAA6C;AAC7E,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,aAAO;AAAA,QACL,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,QAClB,qBAAqB;AAAA,MACvB;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,QAClB,qBAAqB;AAAA,MACvB;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,QAClB,kBAAkB;AAAA,QAClB,qBAAqB;AAAA,MACvB;AAAA,EACJ;AACF;AAKA,eAAe,sBACb,OACA,MACA,UACe;AACf,QAAM,OAAO;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,KAAK,IAAI,IAAI,aAAa,SAAS,MAAM;AAAA,IACnD;AAAA,IACA,kEAAkE,SAAS,eAAe;AAAA,IAC1F;AAAA,IACA,wDAAwD,SAAS,mBAAmB;AAAA,IACpF;AAAA,IACA,6DAA6D,SAAS,iBAAiB;AAAA,IACvF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,sBAAsB,CAAC,SAAS,gBAAgB;AAAA,IAChD;AAAA,IACA,mBAAmB,CAAC,SAAS,cAAc;AAAA,IAC3C;AAAA,IACA,oCAAoC,SAAS,6BAA6B;AAAA,EAC5E;AAGA,MAAI,SAAS,uBAAuB,SAAS,aAAa,SAAS,GAAG;AACpE,eAAW,SAAS,SAAS,cAAc;AACzC,WAAK,KAAK,MAAM,sCAAsC,KAAK,EAAE;AAAA,IAC/D;AAAA,EACF,OAAO;AACL,SAAK,KAAK,MAAM,6BAA6B;AAAA,EAC/C;AAGA,OAAK,KAAK,MAAM,mBAAmB;AAEnC,QAAMC,OAAM,MAAM,IAAI;AACxB;AAKA,eAAe,mBACb,OACA,MACA,UACe;AACf,QAAM,OAAO;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,KAAK,IAAI,IAAI;AAAA,IACvB;AAAA,IACA,sBAAsB,SAAS,gBAAgB;AAAA,IAC/C;AAAA,IACA,sBAAsB,SAAS,gBAAgB;AAAA,IAC/C;AAAA,IACA,sBAAsB,SAAS,gBAAgB;AAAA,IAC/C;AAAA,IACA,0BAA0B,SAAS,mBAAmB;AAAA,EACxD;AAEA,QAAMA,OAAM,MAAM,IAAI;AACxB;AAKA,eAAsB,mBACpB,YAAoB,QAAQ,IAAI,GACjB;AACf,UAAQ,IAAI;AACZ,EAAE,SAAMC,IAAG,OAAOA,IAAG,MAAM,2BAA2B,CAAC,CAAC;AAGxD,QAAMC,WAAY,WAAQ;AAC1B,EAAAA,SAAQ,MAAM,wBAAwB;AAEtC,QAAM,cAAc,MAAM,iBAAiB;AAE3C,MAAI,CAAC,aAAa;AAChB,IAAAA,SAAQ,KAAK,2CAA2C;AACxD,YAAQ,IAAI;AACZ,IAAE,OAAI,MAAMD,IAAG,IAAI,mDAAmD,CAAC;AACvE,IAAE,OAAI,KAAK,0CAA0C;AACrD,IAAE,OAAI,KAAK,yBAAyB;AACpC,YAAQ,IAAI;AACZ,IAAE,OAAI;AAAA,MACJA,IAAG;AAAA,QACD;AAAA,MACF;AAAA,IACF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,EAAAC,SAAQ,KAAK,kBAAkB;AAG/B,EAAAA,SAAQ,MAAM,4BAA4B;AAC1C,QAAM,WAAW,MAAM,kBAAkB,SAAS;AAElD,MAAI,CAAC,UAAU;AACb,IAAAA,SAAQ,KAAK,gCAAgC;AAC7C,IAAE,OAAI;AAAA,MACJD,IAAG,IAAI,+DAA+D;AAAA,IACxE;AACA,IAAE,OAAI,KAAK,4DAA4D;AACvE,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,EAAAC,SAAQ,KAAK,eAAeD,IAAG,KAAK,GAAG,SAAS,KAAK,IAAI,SAAS,IAAI,EAAE,CAAC,EAAE;AAG3E,QAAM,WAAW,MAAQ,eAAY;AAAA,IACnC,SAAS;AAAA,IACT,SAAS;AAAA,MACP,EAAE,OAAO,QAAQ,OAAO,QAAQ,MAAM,cAAc;AAAA,MACpD,EAAE,OAAO,UAAU,OAAO,UAAU,MAAM,iBAAiB;AAAA,MAC3D,EAAE,OAAO,WAAW,OAAO,WAAW,MAAM,sBAAsB;AAAA,MAClE,EAAE,OAAO,cAAc,OAAO,cAAc,MAAM,yBAAyB;AAAA,MAC3E,EAAE,OAAO,eAAe,OAAO,eAAe,MAAM,qBAAqB;AAAA,MACzE,EAAE,OAAO,WAAW,OAAO,WAAW,MAAM,yBAAyB;AAAA,IACvE;AAAA,IACA,UAAU;AAAA,IACV,eAAe,CAAC,MAAM;AAAA,EACxB,CAAC;AAED,MAAM,YAAS,QAAQ,GAAG;AACxB,IAAE,UAAO,kBAAkB;AAC3B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,gBAAgB,MAAQ,UAAO;AAAA,IACnC,SAAS;AAAA,IACT,SAAS;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,cAAc;AAAA,EAChB,CAAC;AAED,MAAM,YAAS,aAAa,GAAG;AAC7B,IAAE,UAAO,kBAAkB;AAC3B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,UAAU,MAAQ,QAAK;AAAA,IAC3B,SAAS;AAAA,IACT,aAAa;AAAA,IACb,cAAc;AAAA,IACd,UAAU,CAAC,UAAU;AACnB,YAAM,MAAM,SAAS,OAAO,EAAE;AAC9B,UAAI,MAAM,GAAG,KAAK,MAAM,KAAK,MAAM,GAAG;AACpC,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AAED,MAAM,YAAS,OAAO,GAAG;AACvB,IAAE,UAAO,kBAAkB;AAC3B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,kBAAkB,SAAS,SAAS,EAAE;AAG5C,QAAM,sBAAqD;AAAA,IACzD,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,OAAO;AAAA,EACT;AAEA,UAAQ,IAAI;AACZ,EAAE;AAAA,IACA;AAAA,MACE,GAAGA,IAAG,KAAK,aAAa,CAAC,IAAI,SAAS,KAAK,IAAI,SAAS,IAAI;AAAA,MAC5D,GAAGA,IAAG,KAAK,qBAAqB,CAAC,IAAK,SAAsB,KAAK,IAAI,CAAC;AAAA,MACtE,GAAGA,IAAG,KAAK,iBAAiB,CAAC,IAAI,oBAAoB,aAA8B,CAAC;AAAA,MACpF,GAAGA,IAAG,KAAK,mBAAmB,CAAC,IAAI,eAAe;AAAA,MAClD,GAAGA,IAAG,KAAK,wBAAwB,CAAC;AAAA,MACpC,GAAGA,IAAG,KAAK,sBAAsB,CAAC;AAAA,MAClC,GAAGA,IAAG,KAAK,wBAAwB,CAAC;AAAA,MACpC,GAAGA,IAAG,KAAK,qBAAqB,CAAC;AAAA,MACjC,GAAGA,IAAG,KAAK,kBAAkB,CAAC;AAAA,MAC9B,GAAGA,IAAG,KAAK,yBAAyB,CAAC;AAAA,IACvC,EAAE,KAAK,IAAI;AAAA,IACX;AAAA,EACF;AAEA,QAAM,YAAY,MAAQ,WAAQ;AAAA,IAChC,SAAS;AAAA,IACT,cAAc;AAAA,EAChB,CAAC;AAED,MAAM,YAAS,SAAS,KAAK,CAAC,WAAW;AACvC,IAAE,UAAO,kBAAkB;AAC3B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,EAAAC,SAAQ,MAAM,+BAA+B;AAE7C,MAAI;AACF,UAAM,eAAe,yBAAyB,aAA8B;AAC5E,UAAM,mBAAmB,SAAS,OAAO,SAAS,MAAM,YAAY;AACpE,IAAAA,SAAQ,KAAK,4BAA4B;AAAA,EAC3C,SAAS,OAAO;AACd,IAAAA,SAAQ,KAAK,oCAAoC;AACjD,UAAM,WAAW,iBAAiB,QAAQ,MAAM,UAAU;AAC1D,IAAE,OAAI,KAAKD,IAAG,OAAO,0CAA0C,QAAQ,EAAE,CAAC;AAC1E,IAAE,OAAI,KAAKA,IAAG,IAAI,sCAAsC,CAAC;AAAA,EAC3D;AAGA,QAAM,oBAA8B,CAAC;AACrC,QAAM,iBAA2B,CAAC;AAElC,aAAW,UAAU,UAAsB;AACzC,IAAAC,SAAQ,MAAM,sBAAsB,MAAM,KAAK;AAE/C,QAAI;AACF,YAAM,WAAW,mBAAmB,MAAM;AAC1C,eAAS,kBAAkB;AAE3B,YAAM,sBAAsB,SAAS,OAAO,SAAS,MAAM,QAAQ;AACnE,wBAAkB,KAAK,MAAM;AAC7B,MAAAA,SAAQ,KAAK,cAAcD,IAAG,MAAM,MAAM,CAAC,EAAE;AAAA,IAC/C,SAAS,OAAO;AACd,qBAAe,KAAK,MAAM;AAC1B,MAAAC,SAAQ,KAAK,WAAWD,IAAG,IAAI,MAAM,CAAC,EAAE;AAExC,YAAM,WAAW,iBAAiB,QAAQ,MAAM,UAAU;AAC1D,MAAE,OAAI;AAAA,QACJA,IAAG;AAAA,UACD,qBAAqB,MAAM,KAAK,SAAS,SAAS,kBAAkB,IAAI,0BAA0B,QAAQ;AAAA,QAC5G;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,UAAQ,IAAI;AAEZ,MAAI,kBAAkB,SAAS,GAAG;AAChC,IAAE,OAAI;AAAA,MACJA,IAAG,MAAM,kCAAkCA,IAAG,KAAK,kBAAkB,KAAK,IAAI,CAAC,CAAC,EAAE;AAAA,IACpF;AAAA,EACF;AAEA,MAAI,eAAe,SAAS,GAAG;AAC7B,IAAE,OAAI;AAAA,MACJA,IAAG;AAAA,QACD,sBAAsBA,IAAG,IAAI,eAAe,KAAK,IAAI,CAAC,CAAC;AAAA,MACzD;AAAA,IACF;AACA,IAAE,OAAI,KAAKA,IAAG,IAAI,2DAA2D,CAAC;AAAA,EAChF;AAEA,MAAI,kBAAkB,SAAS,GAAG;AAChC,IAAE,SAAMA,IAAG,MAAM,iBAAiB,CAAC;AAAA,EACrC,OAAO;AACL,IAAE,SAAMA,IAAG,OAAO,6BAA6B,CAAC;AAChD,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;AClXA,SAAS,SAAAE,cAAa;AACtB,YAAYC,QAAO;AACnB,OAAOC,SAAQ;AAgBf,eAAe,iBACb,WACA,MACmB;AACnB,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAMC;AAAA,MACvB;AAAA,MACA,CAAC,OAAO,WAAW,IAAI,aAAa,aAAa,aAAa;AAAA,MAC9D,EAAE,KAAK,UAAU;AAAA,IACnB;AACA,WAAO,OAAO,KAAK,EAAE,MAAM,IAAI,EAAE,OAAO,OAAO;AAAA,EACjD,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAKA,eAAe,kBACb,WACA,MACmB;AACnB,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAMA;AAAA,MACvB;AAAA,MACA;AAAA,QACE;AAAA,QACA,WAAW,IAAI;AAAA,QACf;AAAA,QACA;AAAA,MACF;AAAA,MACA,EAAE,KAAK,UAAU;AAAA,IACnB;AACA,WAAO,OAAO,MAAM,wBAAwB,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC;AAAA,EACtE,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAKA,eAAe,eAAe,WAAsC;AAClE,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAMA;AAAA,MACvB;AAAA,MACA,CAAC,UAAU,MAAM,2BAA2B;AAAA,MAC5C,EAAE,KAAK,UAAU;AAAA,IACnB;AACA,WAAO,OACJ,KAAK,EACL,MAAM,IAAI,EACV,OAAO,OAAO,EACd,IAAI,CAAC,MAAM,EAAE,QAAQ,WAAW,EAAE,CAAC,EACnC,OAAO,CAAC,GAAG,GAAG,QAAQ,IAAI,QAAQ,CAAC,MAAM,CAAC;AAAA,EAC/C,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAKA,SAAS,kBAAkB,MAAuB;AAChD,QAAM,UACJ;AACF,SAAO,QAAQ,KAAK,IAAI;AAC1B;AAKA,SAAS,YAAY,SAA0B;AAC7C,SACE,QAAQ,SAAS,eAAe,KAChC,QAAQ,SAAS,OAAO,KACxB,QAAQ,SAAS,OAAO,KACxB,QAAQ,SAAS,UAAU,KAC3B,QAAQ,SAAS,SAAS;AAE9B;AAKA,eAAe,iBACb,WACA,MACwB;AACxB,QAAM,CAAC,SAAS,gBAAgB,QAAQ,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC5D,iBAAiB,WAAW,IAAI;AAAA,IAChC,kBAAkB,WAAW,IAAI;AAAA,IACjC,eAAe,SAAS;AAAA,EAC1B,CAAC;AAED,QAAM,uBAAuB,eAAe,OAAO,WAAW,EAAE;AAChE,QAAM,gBAAgB,SAAS,OAAO,iBAAiB;AACvD,QAAM,kBAAkB,SAAS,OAAO,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;AAEpE,SAAO;AAAA,IACL,cAAc,QAAQ;AAAA,IACtB;AAAA,IACA,oBACE,QAAQ,SAAS,IACb,KAAK,MAAO,uBAAuB,QAAQ,SAAU,GAAG,IACxD;AAAA,IACN,aAAa;AAAA,IACb,eAAe,cAAc;AAAA,IAC7B,iBAAiB,gBAAgB;AAAA,IACjC,kBACE,SAAS,SAAS,IACd,KAAK,MAAO,cAAc,SAAS,SAAS,SAAU,GAAG,IACzD;AAAA,EACR;AACF;AAKA,SAAS,iBAAiB,YAA4B;AACpD,MAAI,cAAc,GAAI,QAAOC,IAAG,MAAM,GAAG,UAAU,GAAG;AACtD,MAAI,cAAc,GAAI,QAAOA,IAAG,OAAO,GAAG,UAAU,GAAG;AACvD,SAAOA,IAAG,IAAI,GAAG,UAAU,GAAG;AAChC;AAKA,eAAsB,WAAW,WAAkC;AACjE,EAAE,SAAMA,IAAG,OAAOA,IAAG,MAAM,qBAAqB,CAAC,CAAC;AAElD,MAAI,CAAE,MAAM,UAAU,SAAS,GAAI;AACjC,IAAE,UAAO,sBAAsB;AAC/B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,aAAa,MAAQ,UAAO;AAAA,IAChC,SAAS;AAAA,IACT,SAAS;AAAA,MACP,EAAE,OAAO,GAAG,OAAO,cAAc;AAAA,MACjC,EAAE,OAAO,IAAI,OAAO,eAAe;AAAA,MACnC,EAAE,OAAO,IAAI,OAAO,eAAe;AAAA,MACnC,EAAE,OAAO,IAAI,OAAO,eAAe;AAAA,IACrC;AAAA,EACF,CAAC;AAED,MAAM,YAAS,UAAU,GAAG;AAC1B,IAAE,UAAO,qBAAqB;AAC9B,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,OAAO;AAEb,QAAMC,WAAY,WAAQ;AAC1B,EAAAA,SAAQ,MAAM,yBAAyB;AAEvC,QAAM,UAAU,MAAM,iBAAiB,WAAW,IAAI;AAEtD,EAAAA,SAAQ,KAAK,mBAAmB;AAEhC,EAAE;AAAA,IACA,GAAGD,IAAG,KAAK,SAAS,CAAC,UAAU,IAAI;AAAA,WAC5B,QAAQ,YAAY;AAAA,qBACV,QAAQ,oBAAoB;AAAA,gBACjC,iBAAiB,QAAQ,kBAAkB,CAAC;AAAA;AAAA,EAE1DA,IAAG,KAAK,UAAU,CAAC;AAAA,WACV,QAAQ,YAAY,MAAM;AAAA,kBACnB,QAAQ,aAAa;AAAA,oBACnB,QAAQ,eAAe;AAAA,gBAC3B,iBAAiB,QAAQ,gBAAgB,CAAC;AAAA,IACtD;AAAA,EACF;AAEA,MAAI,QAAQ,kBAAkB,GAAG;AAC/B,UAAM,kBAAkB,QAAQ,YAAY;AAAA,MAC1C,CAAC,MAAM,CAAC,kBAAkB,CAAC;AAAA,IAC7B;AACA,IAAE,OAAI;AAAA,MACJ;AAAA,IAA4B,gBAAgB,MAAM,GAAG,EAAE,EAAE,KAAK,MAAM,CAAC,GACnE,gBAAgB,SAAS,KACrB;AAAA,YAAe,gBAAgB,SAAS,EAAE,UAC1C,EACN;AAAA,IACF;AAAA,EACF;AAEA,QAAM,oBAAoB,KAAK;AAAA,KAC5B,QAAQ,qBAAqB,QAAQ,oBAAoB;AAAA,EAC5D;AAEA,MAAI,qBAAqB,IAAI;AAC3B,IAAE,SAAMA,IAAG,MAAM,qDAAgD,CAAC;AAAA,EACpE,WAAW,qBAAqB,IAAI;AAClC,IAAE,SAAMA,IAAG,OAAO,yDAAoD,CAAC;AAAA,EACzE,OAAO;AACL,IAAE,SAAMA,IAAG,IAAI,2DAAsD,CAAC;AAAA,EACxE;AACF;;;ACzNA;AAAA,EACE,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,aAAe;AAAA,EACf,MAAQ;AAAA,EACR,MAAQ;AAAA,EACR,OAAS;AAAA,EACT,KAAO;AAAA,IACL,WAAa;AAAA,EACf;AAAA,EACA,SAAW;AAAA,IACT,KAAK;AAAA,MACH,OAAS;AAAA,MACT,QAAU;AAAA,IACZ;AAAA,EACF;AAAA,EACA,OAAS;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,SAAW;AAAA,IACT,OAAS;AAAA,IACT,KAAO;AAAA,IACP,WAAa;AAAA,IACb,MAAQ;AAAA,IACR,YAAY;AAAA,IACZ,gBAAkB;AAAA,IAClB,YAAc;AAAA,IACd,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,SAAW;AAAA,IACX,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,EACnB;AAAA,EACA,UAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,QAAU;AAAA,EACV,SAAW;AAAA,EACX,YAAc;AAAA,IACZ,MAAQ;AAAA,IACR,KAAO;AAAA,EACT;AAAA,EACA,UAAY;AAAA,EACZ,MAAQ;AAAA,IACN,KAAO;AAAA,EACT;AAAA,EACA,eAAiB;AAAA,IACf,QAAU;AAAA,IACV,UAAY;AAAA,EACd;AAAA,EACA,gBAAkB;AAAA,EAClB,SAAW;AAAA,IACT,MAAQ;AAAA,EACV;AAAA,EACA,iBAAmB;AAAA,IACjB,eAAe;AAAA,IACf,oBAAoB;AAAA,IACpB,MAAQ;AAAA,IACR,YAAc;AAAA,IACd,QAAU;AAAA,EACZ;AAAA,EACA,cAAgB;AAAA,IACd,kBAAkB;AAAA,IAClB,WAAa;AAAA,IACb,OAAS;AAAA,IACT,YAAc;AAAA,EAChB;AACF;;;AzBtEA,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,WAAW,EAChB;AAAA,EACC;AACF,EACC,QAAQ,gBAAI,OAAO;AAEtB,QACG,QAAQ,MAAM,EACd,YAAY,oDAAoD,EAChE,OAAO,YAAY;AAClB,QAAM,QAAQ,QAAQ,IAAI,CAAC;AAC7B,CAAC;AAEH,QACG,QAAQ,kBAAkB,EAC1B,YAAY,kDAAkD,EAC9D,OAAO,YAAY;AAClB,QAAM,mBAAmB,QAAQ,IAAI,CAAC;AACxC,CAAC;AAEH,QACG,QAAQ,SAAS,EACjB,YAAY,0DAA0D,EACtE,OAAO,YAAY;AAClB,QAAM,WAAW,QAAQ,IAAI,CAAC;AAChC,CAAC;AAEH,QAAQ,MAAM;","names":["p","pc","existsSync","join","join","existsSync","join","existsSync","readFile","join","existsSync","join","join","join","join","join","join","join","readFile","writeFile","existsSync","join","join","join","join","join","join","join","join","join","join","join","join","join","join","join","existsSync","copyFile","join","dirname","join","dirname","existsSync","copyFile","existsSync","readFile","join","join","join","existsSync","join","pc","spinner","p","pc","execa","execa","pc","spinner","execa","p","pc","execa","pc","spinner"]}
|