ai-spec-dev 0.1.0 → 0.17.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.
Files changed (60) hide show
  1. package/.claude/settings.local.json +18 -0
  2. package/README.md +1215 -146
  3. package/RELEASE_LOG.md +1489 -0
  4. package/cli/index.ts +1981 -0
  5. package/cli/welcome.ts +151 -0
  6. package/core/code-generator.ts +757 -0
  7. package/core/combined-generator.ts +63 -0
  8. package/core/constitution-consolidator.ts +141 -0
  9. package/core/constitution-generator.ts +89 -0
  10. package/core/context-loader.ts +453 -0
  11. package/core/contract-bridge.ts +217 -0
  12. package/core/dsl-extractor.ts +337 -0
  13. package/core/dsl-types.ts +166 -0
  14. package/core/dsl-validator.ts +450 -0
  15. package/core/error-feedback.ts +354 -0
  16. package/core/frontend-context-loader.ts +602 -0
  17. package/core/global-constitution.ts +88 -0
  18. package/core/key-store.ts +49 -0
  19. package/core/knowledge-memory.ts +171 -0
  20. package/core/mock-server-generator.ts +571 -0
  21. package/core/openapi-exporter.ts +361 -0
  22. package/core/requirement-decomposer.ts +198 -0
  23. package/core/reviewer.ts +259 -0
  24. package/core/spec-assessor.ts +99 -0
  25. package/core/spec-generator.ts +428 -0
  26. package/core/spec-refiner.ts +89 -0
  27. package/core/spec-updater.ts +227 -0
  28. package/core/spec-versioning.ts +213 -0
  29. package/core/task-generator.ts +174 -0
  30. package/core/test-generator.ts +273 -0
  31. package/core/workspace-loader.ts +256 -0
  32. package/dist/cli/index.js +6717 -672
  33. package/dist/cli/index.js.map +1 -1
  34. package/dist/cli/index.mjs +6717 -670
  35. package/dist/cli/index.mjs.map +1 -1
  36. package/dist/index.d.mts +147 -27
  37. package/dist/index.d.ts +147 -27
  38. package/dist/index.js +2337 -286
  39. package/dist/index.js.map +1 -1
  40. package/dist/index.mjs +2329 -285
  41. package/dist/index.mjs.map +1 -1
  42. package/git/worktree.ts +109 -0
  43. package/index.ts +9 -0
  44. package/package.json +4 -28
  45. package/prompts/codegen.prompt.ts +259 -0
  46. package/prompts/consolidate.prompt.ts +73 -0
  47. package/prompts/constitution.prompt.ts +63 -0
  48. package/prompts/decompose.prompt.ts +168 -0
  49. package/prompts/dsl.prompt.ts +203 -0
  50. package/prompts/frontend-spec.prompt.ts +191 -0
  51. package/prompts/global-constitution.prompt.ts +61 -0
  52. package/prompts/spec-assess.prompt.ts +53 -0
  53. package/prompts/spec.prompt.ts +102 -0
  54. package/prompts/tasks.prompt.ts +35 -0
  55. package/prompts/testgen.prompt.ts +84 -0
  56. package/prompts/update.prompt.ts +131 -0
  57. package/purpose.docx +0 -0
  58. package/purpose.md +444 -0
  59. package/tsconfig.json +14 -0
  60. package/tsup.config.ts +10 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../cli/index.ts","../../core/spec-generator.ts","../../prompts/spec.prompt.ts","../../core/context-loader.ts","../../node_modules/glob/node_modules/balanced-match/src/index.ts","../../node_modules/glob/node_modules/brace-expansion/src/index.ts","../../node_modules/glob/node_modules/minimatch/src/assert-valid-pattern.ts","../../node_modules/glob/node_modules/minimatch/src/brace-expressions.ts","../../node_modules/glob/node_modules/minimatch/src/unescape.ts","../../node_modules/glob/node_modules/minimatch/src/ast.ts","../../node_modules/glob/node_modules/minimatch/src/escape.ts","../../node_modules/glob/node_modules/minimatch/src/index.ts","../../node_modules/glob/src/glob.ts","../../node_modules/glob/node_modules/lru-cache/src/index.ts","../../node_modules/glob/node_modules/path-scurry/src/index.ts","../../node_modules/glob/node_modules/minipass/src/index.ts","../../node_modules/glob/src/pattern.ts","../../node_modules/glob/src/ignore.ts","../../node_modules/glob/src/processor.ts","../../node_modules/glob/src/walker.ts","../../node_modules/glob/src/has-magic.ts","../../node_modules/glob/src/index.ts","../../core/spec-refiner.ts","../../core/code-generator.ts","../../prompts/codegen.prompt.ts","../../core/task-generator.ts","../../prompts/tasks.prompt.ts","../../core/reviewer.ts","../../git/worktree.ts","../../core/constitution-generator.ts","../../prompts/constitution.prompt.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport * as path from \"path\";\nimport * as fs from \"fs-extra\";\nimport chalk from \"chalk\";\nimport * as dotenv from \"dotenv\";\nimport { input, confirm, select, checkbox } from \"@inquirer/prompts\";\n\ndotenv.config();\n\nimport {\n SpecGenerator,\n createProvider,\n DEFAULT_MODELS,\n ENV_KEY_MAP,\n SUPPORTED_PROVIDERS,\n PROVIDER_CATALOG,\n AIProvider,\n} from \"../core/spec-generator\";\nimport { ContextLoader } from \"../core/context-loader\";\nimport { SpecRefiner } from \"../core/spec-refiner\";\nimport { CodeGenerator, CodeGenMode } from \"../core/code-generator\";\nimport { CodeReviewer } from \"../core/reviewer\";\nimport { GitWorktreeManager } from \"../git/worktree\";\nimport { ConstitutionGenerator, CONSTITUTION_FILE, printConstitutionHint } from \"../core/constitution-generator\";\nimport { TaskGenerator, printTasks } from \"../core/task-generator\";\n\n// ─── Config File ──────────────────────────────────────────────────────────────\n\ninterface AiSpecConfig {\n provider?: string;\n model?: string;\n codegen?: CodeGenMode;\n codegenProvider?: string;\n codegenModel?: string;\n}\n\nconst CONFIG_FILE = \".ai-spec.json\";\n\nasync function loadConfig(dir: string): Promise<AiSpecConfig> {\n const p = path.join(dir, CONFIG_FILE);\n if (await fs.pathExists(p)) {\n return fs.readJson(p);\n }\n return {};\n}\n\n// ─── API Key Resolution ────────────────────────────────────────────────────────\n\nasync function resolveApiKey(\n providerName: string,\n cliKey?: string\n): Promise<string> {\n if (cliKey) return cliKey;\n\n const envVar = ENV_KEY_MAP[providerName];\n if (envVar && process.env[envVar]) return process.env[envVar]!;\n\n // Interactive prompt as last resort\n return input({\n message: `Enter your ${providerName} API key (or set ${envVar} env var):`,\n validate: (v) => v.trim().length > 0 || \"API key cannot be empty\",\n });\n}\n\n// ─── Banner ───────────────────────────────────────────────────────────────────\n\nfunction printBanner(opts: {\n specProvider: string;\n specModel: string;\n codegenMode: string;\n codegenProvider: string;\n codegenModel: string;\n}) {\n console.log(chalk.blue(\"\\n\" + \"─\".repeat(52)));\n console.log(chalk.bold(\" ai-spec — AI-driven Development Orchestrator\"));\n console.log(chalk.blue(\"─\".repeat(52)));\n console.log(chalk.gray(` Spec : ${opts.specProvider} / ${opts.specModel}`));\n console.log(\n chalk.gray(\n ` Codegen : ${opts.codegenMode} (${opts.codegenProvider} / ${opts.codegenModel})`\n )\n );\n console.log(chalk.blue(\"─\".repeat(52) + \"\\n\"));\n}\n\n// ─── Program ──────────────────────────────────────────────────────────────────\n\nconst program = new Command();\n\nprogram\n .name(\"ai-spec\")\n .description(\"AI-driven Development Orchestrator — spec, generate, review\")\n .version(\"0.2.0\");\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Command: create\n// ═══════════════════════════════════════════════════════════════════════════════\n\nprogram\n .command(\"create\")\n .description(\"Generate a feature spec and kick off code generation\")\n .argument(\"[idea]\", \"Feature idea in natural language (prompted if omitted)\")\n .option(\n \"--provider <name>\",\n `AI provider for spec generation (${SUPPORTED_PROVIDERS.join(\"|\")})`,\n undefined\n )\n .option(\"--model <name>\", \"Model name for spec generation\")\n .option(\"-k, --key <apiKey>\", \"API key (overrides env var)\")\n .option(\n \"--codegen <mode>\",\n \"Code generation mode: claude-code | api | plan\",\n undefined\n )\n .option(\n \"--codegen-provider <name>\",\n \"AI provider for code generation (defaults to --provider)\"\n )\n .option(\"--codegen-model <name>\", \"Model for code generation\")\n .option(\"--codegen-key <key>\", \"API key for code generation (if different)\")\n .option(\"--skip-worktree\", \"Skip git worktree creation\")\n .option(\"--skip-review\", \"Skip automated code review\")\n .option(\"--skip-tasks\", \"Skip task generation (just generate spec)\")\n .option(\"--auto\", \"Run claude non-interactively via -p flag (saves tokens)\")\n .action(async (idea: string | undefined, opts) => {\n const currentDir = process.cwd();\n const config = await loadConfig(currentDir);\n\n // ── Resolve idea ──────────────────────────────────────────────────────────\n if (!idea) {\n idea = await input({\n message: \"What feature do you want to build?\",\n validate: (v) => v.trim().length > 0 || \"Please describe your feature\",\n });\n }\n\n // ── Resolve spec provider ─────────────────────────────────────────────────\n const specProviderName = opts.provider || config.provider || \"gemini\";\n const specModelName =\n opts.model || config.model || DEFAULT_MODELS[specProviderName];\n const specApiKey = await resolveApiKey(specProviderName, opts.key);\n\n // ── Resolve codegen ───────────────────────────────────────────────────────\n const codegenMode: CodeGenMode =\n (opts.codegen as CodeGenMode) || config.codegen || \"claude-code\";\n const codegenProviderName =\n opts.codegenProvider || config.codegenProvider || specProviderName;\n const codegenModelName =\n opts.codegenModel ||\n config.codegenModel ||\n DEFAULT_MODELS[codegenProviderName];\n const codegenApiKey =\n codegenProviderName === specProviderName\n ? specApiKey\n : await resolveApiKey(codegenProviderName, opts.codegenKey);\n\n printBanner({\n specProvider: specProviderName,\n specModel: specModelName,\n codegenMode,\n codegenProvider: codegenProviderName,\n codegenModel: codegenModelName,\n });\n\n // ── Step 1: Context ───────────────────────────────────────────────────────\n console.log(chalk.blue(\"[1/6] Loading project context...\"));\n const loader = new ContextLoader(currentDir);\n const context = await loader.loadProjectContext();\n console.log(chalk.gray(` Tech stack : ${context.techStack.join(\", \") || \"unknown\"}`));\n console.log(chalk.gray(` Dependencies: ${context.dependencies.length} packages`));\n console.log(chalk.gray(` API files : ${context.apiStructure.length} files`));\n if (context.schema) {\n console.log(chalk.gray(` Prisma schema: found`));\n }\n if (context.constitution) {\n console.log(chalk.green(` Constitution : found (.ai-spec-constitution.md)`));\n } else {\n printConstitutionHint(false);\n }\n\n // ── Step 2: Spec Generation ───────────────────────────────────────────────\n console.log(chalk.blue(`\\n[2/6] Generating spec with ${specProviderName}/${specModelName}...`));\n const specProvider = createProvider(specProviderName, specApiKey, specModelName);\n const generator = new SpecGenerator(specProvider);\n let initialSpec: string;\n try {\n initialSpec = await generator.generateSpec(idea, context);\n console.log(chalk.green(\" ✔ Initial spec generated.\"));\n } catch (err) {\n console.error(chalk.red(\" ✘ Spec generation failed:\"), err);\n process.exit(1);\n }\n\n // ── Step 3: Interactive Refinement ────────────────────────────────────────\n console.log(chalk.blue(\"\\n[3/6] Interactive spec refinement...\"));\n const refiner = new SpecRefiner(specProvider);\n const finalSpec = await refiner.refineLoop(initialSpec);\n\n // ── Step 4: Git Worktree ──────────────────────────────────────────────────\n let workingDir = currentDir;\n if (!opts.skipWorktree) {\n console.log(chalk.blue(\"\\n[4/6] Setting up git worktree...\"));\n const worktreeManager = new GitWorktreeManager(currentDir);\n const worktreePath = await worktreeManager.createWorktree(idea);\n if (worktreePath) workingDir = worktreePath;\n } else {\n console.log(chalk.gray(\"[4/6] Skipping worktree (--skip-worktree).\"));\n }\n\n // ── Step 5: Save Spec + Generate Tasks ───────────────────────────────────\n const specsDir = path.join(workingDir, \"specs\");\n await fs.ensureDir(specsDir);\n const specFile = path.join(specsDir, `feature-${Date.now()}.md`);\n await fs.writeFile(specFile, finalSpec, \"utf-8\");\n console.log(chalk.green(`\\n[5/6] ✔ Spec saved: ${specFile}`));\n\n if (!opts.skipTasks) {\n console.log(chalk.blue(`\\n Generating implementation tasks...`));\n try {\n const taskGen = new TaskGenerator(specProvider);\n const tasks = await taskGen.generateTasks(finalSpec, context);\n if (tasks.length > 0) {\n const sorted = taskGen.sortByLayer(tasks);\n const tasksFile = await taskGen.saveTasks(sorted, specFile);\n printTasks(sorted);\n console.log(chalk.green(` ✔ Tasks saved: ${tasksFile}`));\n } else {\n console.log(chalk.yellow(\" ⚠ Could not parse tasks from AI response.\"));\n }\n } catch (err) {\n console.log(chalk.yellow(` ⚠ Task generation failed: ${(err as Error).message}`));\n }\n }\n\n // ── Step 6: Code Generation ───────────────────────────────────────────────\n console.log(chalk.blue(`\\n[6/6] Code generation (mode: ${codegenMode})...`));\n const codegenProvider =\n codegenProviderName === specProviderName && codegenApiKey === specApiKey\n ? specProvider\n : createProvider(codegenProviderName, codegenApiKey, codegenModelName);\n\n const codegen = new CodeGenerator(codegenProvider, codegenMode);\n await codegen.generateCode(specFile, workingDir, context, { auto: opts.auto });\n\n // ── Step 7: Code Review ───────────────────────────────────────────────────\n if (!opts.skipReview) {\n console.log(chalk.blue(\"\\n[7/7] Automated code review...\"));\n const reviewer = new CodeReviewer(specProvider);\n const savedSpec = await fs.readFile(specFile, \"utf-8\");\n const originalDir = process.cwd();\n try {\n process.chdir(workingDir);\n await reviewer.reviewCode(savedSpec);\n } finally {\n process.chdir(originalDir);\n }\n }\n\n // ── Done ──────────────────────────────────────────────────────────────────\n console.log(chalk.bold.green(\"\\n✔ All done!\"));\n console.log(chalk.gray(` Spec : ${specFile}`));\n console.log(chalk.gray(` Working dir : ${workingDir}`));\n if (workingDir !== currentDir) {\n console.log(chalk.gray(` Run \\`cd ${workingDir}\\` to enter the worktree.`));\n }\n });\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Command: review\n// ═══════════════════════════════════════════════════════════════════════════════\n\nprogram\n .command(\"review\")\n .description(\"Run AI code review on current git diff against a spec\")\n .argument(\"[specFile]\", \"Path to spec file (auto-detects latest in specs/ if omitted)\")\n .option(\n \"--provider <name>\",\n `AI provider (${SUPPORTED_PROVIDERS.join(\"|\")})`,\n undefined\n )\n .option(\"--model <name>\", \"Model name\")\n .option(\"-k, --key <apiKey>\", \"API key\")\n .action(async (specFile: string | undefined, opts) => {\n const currentDir = process.cwd();\n const config = await loadConfig(currentDir);\n\n const providerName = opts.provider || config.provider || \"gemini\";\n const modelName = opts.model || config.model || DEFAULT_MODELS[providerName];\n const apiKey = await resolveApiKey(providerName, opts.key);\n\n const provider = createProvider(providerName, apiKey, modelName);\n const reviewer = new CodeReviewer(provider);\n\n let specContent = \"\";\n\n if (specFile && (await fs.pathExists(specFile))) {\n specContent = await fs.readFile(specFile, \"utf-8\");\n console.log(chalk.gray(`Using spec: ${specFile}`));\n } else {\n // Auto-detect the latest spec in specs/\n const specsDir = path.join(currentDir, \"specs\");\n if (await fs.pathExists(specsDir)) {\n const files = (await fs.readdir(specsDir))\n .filter((f) => f.endsWith(\".md\"))\n .sort()\n .reverse();\n if (files.length > 0) {\n const latest = path.join(specsDir, files[0]);\n specContent = await fs.readFile(latest, \"utf-8\");\n console.log(chalk.gray(`Auto-detected spec: specs/${files[0]}`));\n }\n }\n }\n\n if (!specContent) {\n console.log(chalk.yellow(\"No spec file found. Running review without spec context.\"));\n }\n\n await reviewer.reviewCode(specContent);\n });\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Command: init — generate Project Constitution\n// ═══════════════════════════════════════════════════════════════════════════════\n\nprogram\n .command(\"init\")\n .description(`Analyze codebase and generate Project Constitution (${CONSTITUTION_FILE})`)\n .option(\n \"--provider <name>\",\n `AI provider (${SUPPORTED_PROVIDERS.join(\"|\")})`,\n undefined\n )\n .option(\"--model <name>\", \"Model name\")\n .option(\"-k, --key <apiKey>\", \"API key\")\n .option(\"--force\", \"Overwrite existing constitution\")\n .action(async (opts) => {\n const currentDir = process.cwd();\n const config = await loadConfig(currentDir);\n const constitutionPath = path.join(currentDir, CONSTITUTION_FILE);\n\n if (!opts.force && (await fs.pathExists(constitutionPath))) {\n console.log(chalk.yellow(`\\n ${CONSTITUTION_FILE} already exists.`));\n console.log(chalk.gray(\" Use --force to overwrite it.\"));\n console.log(chalk.gray(` Or edit it directly: ${constitutionPath}`));\n return;\n }\n\n const providerName = opts.provider || config.provider || \"gemini\";\n const modelName = opts.model || config.model || DEFAULT_MODELS[providerName];\n const apiKey = await resolveApiKey(providerName, opts.key);\n\n console.log(chalk.blue(\"\\n─── Generating Project Constitution ─────────────\"));\n console.log(chalk.gray(` Provider: ${providerName}/${modelName}`));\n console.log(chalk.gray(\" Analyzing codebase...\"));\n\n const provider = createProvider(providerName, apiKey, modelName);\n const generator = new ConstitutionGenerator(provider);\n\n let constitution: string;\n try {\n constitution = await generator.generate(currentDir);\n } catch (err) {\n console.error(chalk.red(\" ✘ Failed to generate constitution:\"), err);\n process.exit(1);\n }\n\n const saved = await generator.saveConstitution(currentDir, constitution);\n console.log(chalk.green(`\\n ✔ Constitution saved: ${saved}`));\n console.log(chalk.gray(\" This file will be automatically used in all future `ai-spec create` runs.\"));\n console.log(chalk.gray(\" Edit it to add custom rules or red lines for your project.\\n\"));\n console.log(chalk.bold(\" Preview:\"));\n console.log(chalk.gray(constitution.split(\"\\n\").slice(0, 15).join(\"\\n\")));\n if (constitution.split(\"\\n\").length > 15) {\n console.log(chalk.gray(` ... (${constitution.split(\"\\n\").length} lines total)`));\n }\n });\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Command: config\n// ═══════════════════════════════════════════════════════════════════════════════\n\nprogram\n .command(\"config\")\n .description(`Set default configuration for this project (saved to ${CONFIG_FILE})`)\n .option(\"--provider <name>\", \"Default AI provider for spec generation\")\n .option(\"--model <name>\", \"Default model for spec generation\")\n .option(\n \"--codegen <mode>\",\n \"Default code generation mode (claude-code|api|plan)\"\n )\n .option(\"--codegen-provider <name>\", \"Default provider for code generation\")\n .option(\"--codegen-model <name>\", \"Default model for code generation\")\n .option(\"--show\", \"Print current configuration\")\n .option(\"--reset\", \"Reset configuration to empty\")\n .action(async (opts) => {\n const currentDir = process.cwd();\n const configPath = path.join(currentDir, CONFIG_FILE);\n\n if (opts.reset) {\n await fs.writeJson(configPath, {}, { spaces: 2 });\n console.log(chalk.green(`✔ Config reset: ${configPath}`));\n return;\n }\n\n const existing: AiSpecConfig = await loadConfig(currentDir);\n\n if (opts.show) {\n if (Object.keys(existing).length === 0) {\n console.log(chalk.gray(\"No config file found. Using built-in defaults.\"));\n } else {\n console.log(chalk.bold(`${configPath}:`));\n console.log(JSON.stringify(existing, null, 2));\n }\n return;\n }\n\n const updated: AiSpecConfig = { ...existing };\n if (opts.provider) updated.provider = opts.provider;\n if (opts.model) updated.model = opts.model;\n if (opts.codegen) updated.codegen = opts.codegen as CodeGenMode;\n if (opts.codegenProvider) updated.codegenProvider = opts.codegenProvider;\n if (opts.codegenModel) updated.codegenModel = opts.codegenModel;\n\n await fs.writeJson(configPath, updated, { spaces: 2 });\n console.log(chalk.green(`✔ Config saved to ${configPath}`));\n console.log(JSON.stringify(updated, null, 2));\n });\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Command: model — interactive model switcher\n// ═══════════════════════════════════════════════════════════════════════════════\n\nprogram\n .command(\"model\")\n .description(\"Interactively switch the active AI provider/model and save to .ai-spec.json\")\n .option(\"--list\", \"List all available providers and models\")\n .action(async (opts) => {\n const currentDir = process.cwd();\n const configPath = path.join(currentDir, CONFIG_FILE);\n\n // ── --list: just print the catalog ────────────────────────────────────────\n if (opts.list) {\n console.log(chalk.bold(\"\\nAvailable providers & models:\\n\"));\n for (const [key, meta] of Object.entries(PROVIDER_CATALOG)) {\n console.log(\n ` ${chalk.bold.cyan(key.padEnd(10))} ${chalk.white(meta.displayName)}`\n );\n console.log(chalk.gray(` ${meta.description}`));\n console.log(\n chalk.gray(\n ` env: ${meta.envKey} | models: ${meta.models.join(\", \")}`\n )\n );\n console.log();\n }\n return;\n }\n\n const existing: AiSpecConfig = await loadConfig(currentDir);\n\n console.log(chalk.blue(\"\\n─── Model Switcher ─────────────────────────────\"));\n if (Object.keys(existing).length > 0) {\n console.log(\n chalk.gray(\n ` Current: spec=${existing.provider ?? \"gemini\"}/${existing.model ?? DEFAULT_MODELS[existing.provider ?? \"gemini\"]}` +\n (existing.codegenProvider\n ? ` codegen=${existing.codegenProvider}/${existing.codegenModel ?? \"\"}`\n : \"\")\n )\n );\n }\n console.log();\n\n // ── What to configure ─────────────────────────────────────────────────────\n const target = await select({\n message: \"Configure model for:\",\n choices: [\n { name: \"Spec generation (used for spec writing & refinement)\", value: \"spec\" },\n { name: \"Code generation (used when --codegen api is active)\", value: \"codegen\" },\n { name: \"Both (same provider/model for all tasks)\", value: \"both\" },\n ],\n });\n\n // ── Helper: pick provider + model ─────────────────────────────────────────\n async function pickProviderAndModel(label: string): Promise<{ provider: string; model: string }> {\n const providerKey = await select({\n message: `${label} — select provider:`,\n choices: Object.entries(PROVIDER_CATALOG).map(([key, meta]) => ({\n name: `${meta.displayName.padEnd(22)} ${chalk.gray(meta.description)}`,\n value: key,\n short: meta.displayName,\n })),\n });\n\n const meta = PROVIDER_CATALOG[providerKey];\n const modelChoices = [\n ...meta.models.map((m) => ({ name: m, value: m })),\n { name: chalk.italic(\"✎ Enter custom model name...\"), value: \"__custom__\" },\n ];\n\n let chosenModel = await select({\n message: `${label} — select model (${meta.displayName}):`,\n choices: modelChoices,\n });\n\n if (chosenModel === \"__custom__\") {\n chosenModel = await input({\n message: \"Enter model name:\",\n validate: (v) => v.trim().length > 0 || \"Model name cannot be empty\",\n });\n }\n\n return { provider: providerKey, model: chosenModel };\n }\n\n // ── Run picker(s) ─────────────────────────────────────────────────────────\n const updated: AiSpecConfig = { ...existing };\n\n if (target === \"spec\" || target === \"both\") {\n const { provider, model } = await pickProviderAndModel(\"Spec\");\n updated.provider = provider;\n updated.model = model;\n }\n\n if (target === \"codegen\" || target === \"both\") {\n if (target === \"both\") {\n updated.codegenProvider = updated.provider;\n updated.codegenModel = updated.model;\n } else {\n const { provider, model } = await pickProviderAndModel(\"Codegen\");\n updated.codegenProvider = provider;\n updated.codegenModel = model;\n }\n\n // claude-code 模式只支持 Claude provider。\n // 如果选了非 claude provider,自动把 codegen 模式改为 api。\n const effectiveCodegenProvider = updated.codegenProvider ?? updated.provider ?? \"gemini\";\n if (effectiveCodegenProvider !== \"claude\") {\n if (!updated.codegen || updated.codegen === \"claude-code\") {\n updated.codegen = \"api\";\n console.log(\n chalk.yellow(\n `\\n ⚠ provider \"${effectiveCodegenProvider}\" 不支持 \"claude-code\" 模式。`\n )\n );\n console.log(chalk.gray(` 已自动将 codegen 模式设为 \"api\"。`));\n }\n }\n }\n\n // ── Confirm & save ────────────────────────────────────────────────────────\n console.log(chalk.blue(\"\\n Preview:\"));\n console.log(chalk.gray(` spec → ${updated.provider}/${updated.model}`));\n if (updated.codegenProvider) {\n console.log(\n chalk.gray(\n ` codegen → ${updated.codegenProvider}/${updated.codegenModel} (mode: ${updated.codegen ?? \"claude-code\"})`\n )\n );\n }\n\n const ok = await confirm({ message: \"Save to .ai-spec.json?\", default: true });\n if (!ok) {\n console.log(chalk.gray(\" Cancelled.\"));\n return;\n }\n\n await fs.writeJson(configPath, updated, { spaces: 2 });\n console.log(chalk.green(`\\n ✔ Saved to ${configPath}`));\n\n // Remind about env var if not set\n const providerToCheck = updated.provider ?? \"gemini\";\n const envKey = ENV_KEY_MAP[providerToCheck];\n if (envKey && !process.env[envKey]) {\n console.log(\n chalk.yellow(\n ` ⚠ Remember to set ${envKey} in your environment or .env file.`\n )\n );\n }\n });\n\nprogram.parse();\n","import { GoogleGenerativeAI } from \"@google/generative-ai\";\nimport Anthropic from \"@anthropic-ai/sdk\";\nimport OpenAI from \"openai\";\nimport { ProxyAgent } from \"undici\";\nimport { specPrompt } from \"../prompts/spec.prompt\";\nimport { ProjectContext } from \"./context-loader\";\n\n// ─── Proxy Helper ─────────────────────────────────────────────────────────────\n// 仅用于 Gemini:其他 SDK(Anthropic / OpenAI)会自动读取 HTTPS_PROXY。\n// Gemini SDK 使用 Node.js 原生 fetch(undici),不会自动读代理环境变量,\n// 需要手动创建 ProxyAgent 并通过 fetchOptions 注入。\n// 这是 in-process 级别的配置,完全不影响 execSync 启动的子进程(如 claude CLI)。\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction geminiRequestOptions(): any {\n const proxyUrl =\n process.env.GEMINI_PROXY ||\n process.env.HTTPS_PROXY ||\n process.env.https_proxy ||\n process.env.HTTP_PROXY ||\n process.env.http_proxy;\n\n if (!proxyUrl) return undefined;\n // fetchOptions.dispatcher は型定義(v0.21)に未記載だが runtime では動作する\n return { fetchOptions: { dispatcher: new ProxyAgent(proxyUrl) } };\n}\n\n// ─── Provider Interface ────────────────────────────────────────────────────────\n\nexport interface AIProvider {\n generate(prompt: string, systemInstruction?: string): Promise<string>;\n readonly providerName: string;\n readonly modelName: string;\n}\n\n// ─── Provider Catalog ─────────────────────────────────────────────────────────\n// Single source of truth for all supported providers and their models.\n\nexport interface ProviderMeta {\n /** Human-readable display name */\n displayName: string;\n /** Short description shown in model picker */\n description: string;\n /** Available models (first is the default) */\n models: string[];\n /** Environment variable name for the API key */\n envKey: string;\n /**\n * Base URL for OpenAI-compatible providers.\n * Undefined means the provider has its own SDK (Gemini / Claude).\n */\n baseURL?: string;\n}\n\nexport const PROVIDER_CATALOG: Record<string, ProviderMeta> = {\n // ── International ──────────────────────────────────────────────────────────\n gemini: {\n displayName: \"Google Gemini\",\n description: \"Google AI Studio — Gemini 2.5 / 1.5 series\",\n models: [\n \"gemini-2.5-flash\",\n \"gemini-2.5-pro\",\n \"gemini-1.5-pro\",\n \"gemini-1.5-flash\",\n ],\n envKey: \"GEMINI_API_KEY\",\n },\n claude: {\n displayName: \"Anthropic Claude\",\n description: \"Anthropic — Claude 4.x series\",\n models: [\n \"claude-sonnet-4-6\",\n \"claude-opus-4-6\",\n \"claude-haiku-4-5\",\n ],\n envKey: \"ANTHROPIC_API_KEY\",\n },\n openai: {\n displayName: \"OpenAI\",\n description: \"OpenAI — GPT-4o / o1 series\",\n models: [\"gpt-4o\", \"gpt-4o-mini\", \"gpt-4-turbo\", \"o1-mini\"],\n envKey: \"OPENAI_API_KEY\",\n baseURL: \"https://api.openai.com/v1\",\n },\n\n // ── Chinese Models (OpenAI-compatible) ────────────────────────────────────\n qwen: {\n displayName: \"通义千问 (Qwen)\",\n description: \"阿里云百炼 DashScope — qwen-max / plus / turbo\",\n models: [\n \"qwen-max\",\n \"qwen-max-latest\",\n \"qwen-plus\",\n \"qwen-plus-latest\",\n \"qwen-turbo\",\n \"qwen-long\",\n ],\n envKey: \"DASHSCOPE_API_KEY\",\n baseURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n },\n minimax: {\n displayName: \"MiniMax\",\n description: \"MiniMax AI — MiniMax-Text-01 / abab series\",\n models: [\n \"MiniMax-Text-01\",\n \"abab6.5s-chat\",\n \"abab6.5g-chat\",\n \"abab5.5-chat\",\n ],\n envKey: \"MINIMAX_API_KEY\",\n baseURL: \"https://api.minimax.chat/v1\",\n },\n glm: {\n displayName: \"智谱 GLM (Zhipu AI)\",\n description: \"智谱 AI — GLM-4 plus / flash / air series\",\n models: [\n \"glm-4-plus\",\n \"glm-4\",\n \"glm-4-flash\",\n \"glm-4-air\",\n \"glm-4-airx\",\n \"glm-4-long\",\n ],\n envKey: \"ZHIPU_API_KEY\",\n baseURL: \"https://open.bigmodel.cn/api/paas/v4/\",\n },\n};\n\n// Derived convenience maps (kept for backward compatibility)\nexport const SUPPORTED_PROVIDERS = Object.keys(PROVIDER_CATALOG);\n\nexport const DEFAULT_MODELS: Record<string, string> = Object.fromEntries(\n Object.entries(PROVIDER_CATALOG).map(([k, v]) => [k, v.models[0]])\n);\n\nexport const ENV_KEY_MAP: Record<string, string> = Object.fromEntries(\n Object.entries(PROVIDER_CATALOG).map(([k, v]) => [k, v.envKey])\n);\n\n// ─── Gemini Provider ───────────────────────────────────────────────────────────\n\nexport class GeminiProvider implements AIProvider {\n private genAI: GoogleGenerativeAI;\n readonly providerName = \"gemini\";\n readonly modelName: string;\n\n constructor(apiKey: string, modelName = PROVIDER_CATALOG.gemini.models[0]) {\n this.genAI = new GoogleGenerativeAI(apiKey);\n this.modelName = modelName;\n }\n\n async generate(prompt: string, systemInstruction?: string): Promise<string> {\n const model = this.genAI.getGenerativeModel(\n { model: this.modelName, ...(systemInstruction ? { systemInstruction } : {}) },\n geminiRequestOptions()\n );\n const result = await model.generateContent(prompt);\n return result.response.text();\n }\n}\n\n// ─── Claude Provider ───────────────────────────────────────────────────────────\n\nexport class ClaudeProvider implements AIProvider {\n private client: Anthropic;\n readonly providerName = \"claude\";\n readonly modelName: string;\n\n constructor(apiKey: string, modelName = PROVIDER_CATALOG.claude.models[0]) {\n this.client = new Anthropic({ apiKey });\n this.modelName = modelName;\n }\n\n async generate(prompt: string, systemInstruction?: string): Promise<string> {\n const message = await this.client.messages.create({\n model: this.modelName,\n max_tokens: 8192,\n ...(systemInstruction ? { system: systemInstruction } : {}),\n messages: [{ role: \"user\", content: prompt }],\n });\n const block = message.content[0];\n if (block.type === \"text\") return block.text;\n throw new Error(\"Unexpected response type from Claude API\");\n }\n}\n\n// ─── OpenAI-Compatible Provider ───────────────────────────────────────────────\n// Handles OpenAI, Qwen, MiniMax, and GLM — all expose the same chat/completions API.\n\nexport class OpenAICompatibleProvider implements AIProvider {\n protected client: OpenAI;\n readonly providerName: string;\n readonly modelName: string;\n\n constructor(\n providerName: string,\n apiKey: string,\n modelName: string,\n baseURL?: string\n ) {\n this.providerName = providerName;\n this.modelName = modelName;\n this.client = new OpenAI({\n apiKey,\n ...(baseURL ? { baseURL } : {}),\n });\n }\n\n async generate(prompt: string, systemInstruction?: string): Promise<string> {\n const messages: OpenAI.Chat.ChatCompletionMessageParam[] = [];\n if (systemInstruction) {\n messages.push({ role: \"system\", content: systemInstruction });\n }\n messages.push({ role: \"user\", content: prompt });\n\n const completion = await this.client.chat.completions.create({\n model: this.modelName,\n messages,\n });\n return completion.choices[0].message.content ?? \"\";\n }\n}\n\n// ─── Factory ──────────────────────────────────────────────────────────────────\n\nexport function createProvider(\n providerName: string,\n apiKey: string,\n modelName?: string\n): AIProvider {\n const meta = PROVIDER_CATALOG[providerName];\n if (!meta) {\n throw new Error(\n `Unknown provider: \"${providerName}\". Valid options: ${SUPPORTED_PROVIDERS.join(\", \")}`\n );\n }\n\n const model = modelName || meta.models[0];\n\n switch (providerName) {\n case \"gemini\":\n return new GeminiProvider(apiKey, model);\n case \"claude\":\n return new ClaudeProvider(apiKey, model);\n // All OpenAI-compatible providers (openai, qwen, minimax, glm)\n default:\n return new OpenAICompatibleProvider(providerName, apiKey, model, meta.baseURL);\n }\n}\n\n// ─── Spec Generator ───────────────────────────────────────────────────────────\n\nexport class SpecGenerator {\n constructor(private provider: AIProvider) {}\n\n async generateSpec(idea: string, context?: ProjectContext): Promise<string> {\n const parts: string[] = [idea];\n\n if (context) {\n // Constitution is highest priority — put it first so the AI respects it\n if (context.constitution) {\n parts.push(\n `\\n\\n=== 项目宪法 (Project Constitution — MUST follow these rules) ===\\n${context.constitution}`\n );\n }\n\n parts.push(`\\n\\n=== 项目上下文 (Project Context) ===`);\n if (context.techStack.length > 0) {\n parts.push(`技术栈: ${context.techStack.join(\", \")}`);\n }\n if (context.dependencies.length > 0) {\n parts.push(`主要依赖: ${context.dependencies.slice(0, 25).join(\", \")}`);\n }\n if (context.apiStructure.length > 0) {\n parts.push(\n `\\n现有 API 文件:\\n${context.apiStructure\n .slice(0, 10)\n .map((f) => ` - ${f}`)\n .join(\"\\n\")}`\n );\n }\n if (context.routeSummary) {\n parts.push(`\\n路由结构(摘要):\\n${context.routeSummary}`);\n }\n if (context.schema) {\n parts.push(`\\n数据库 Schema (Prisma):\\n${context.schema.slice(0, 3000)}`);\n }\n }\n\n return this.provider.generate(parts.join(\"\\n\"), specPrompt);\n }\n}\n","export const specPrompt = `You are an expert Software Architect. Your task is to convert the user's raw feature idea into a structured, detailed, and immediately actionable Markdown specification.\n\nThe spec MUST be written in Chinese (中文). Be comprehensive but focused — every section should contain practical, project-specific information derived from the provided project context.\n\nUse the EXACT following template structure:\n\n---\n\n# Feature Spec: {功能名称}\n\n## 1. 功能概述 (Overview)\n用 2-3 句话简洁说明这个功能是什么,以及它解决的核心问题。\n\n## 2. 背景与动机 (Background)\n- 当前存在什么问题或缺失?\n- 为什么现在需要构建这个功能?\n- 对用户/业务的价值是什么?\n\n## 3. 用户故事 (User Stories)\n- 作为 **[用户角色]**,我希望 **[完成某操作]**,以便 **[获得某价值]**\n(列出 2-4 个核心用户故事,覆盖主要使用场景)\n\n## 4. 功能需求 (Functional Requirements)\n\n### 4.1 核心功能\n- [ ] 需求 1:详细描述期望行为\n- [ ] 需求 2:详细描述期望行为\n\n### 4.2 边界条件与错误处理\n- 输入验证规则(字段类型、长度、格式要求)\n- 错误场景及对应的处理策略\n- 权限控制要求(哪些角色可以访问)\n\n## 5. API 设计 (API Design)\n\n### 接口列表\n| Method | Endpoint | Auth Required | Description |\n|--------|----------|:-------------:|-------------|\n| POST | /api/... | ✅ | 创建... |\n| GET | /api/... | ✅ | 获取... |\n\n### 请求/响应示例\n\n**[接口名称]**\n\n\\`\\`\\`\nPOST /api/example\nAuthorization: Bearer {token}\nContent-Type: application/json\n\\`\\`\\`\n\n请求体:\n\\`\\`\\`json\n{\n \"field1\": \"string\",\n \"field2\": 0\n}\n\\`\\`\\`\n\n成功响应 (200):\n\\`\\`\\`json\n{\n \"code\": 0,\n \"message\": \"success\",\n \"data\": {}\n}\n\\`\\`\\`\n\n错误响应:\n\\`\\`\\`json\n{\n \"code\": 40001,\n \"message\": \"错误描述\"\n}\n\\`\\`\\`\n\n## 6. 数据模型 (Data Model)\n描述需要新增或修改的数据库表/字段(使用 Prisma Schema 格式)。\n\n\\`\\`\\`prisma\nmodel ExampleModel {\n id Int @id @default(autoincrement())\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\\`\\`\\`\n\n## 7. 非功能性需求 (Non-functional Requirements)\n- **性能**: 接口响应时间要求,并发量预估\n- **安全**: 认证授权机制,敏感数据的处理方式\n- **可靠性**: 幂等性要求,重试策略\n- **可维护性**: 日志记录要求,监控指标\n\n## 8. 实施要点 (Implementation Notes)\n- **集成点**: 需要与哪些现有模块、服务或外部 API 交互\n- **实施顺序**: 建议的开发步骤(例:数据模型 → 服务层 → 控制器 → 路由 → 测试)\n- **技术注意事项**: 潜在的技术难点,推荐的库或实现方案\n- **测试要点**: 关键的单元测试和集成测试场景\n\n---\n\n根据用户的想法和项目上下文生成上述完整 Spec。确保 API 设计与现有项目的路由风格、错误码规范保持一致,数据模型与现有 Prisma Schema 协调。`;\n","import * as fs from \"fs-extra\";\nimport * as path from \"path\";\nimport { glob } from \"glob\";\n\nexport interface ProjectContext {\n techStack: string[];\n fileStructure: string[];\n dependencies: string[];\n apiStructure: string[];\n schema?: string;\n routeSummary?: string;\n /** Contents of .ai-spec-constitution.md if present */\n constitution?: string;\n /** Extracted error handling patterns from source */\n errorPatterns?: string;\n}\n\nconst STACK_MAP: Record<string, string> = {\n react: \"React\",\n vue: \"Vue\",\n \"next\": \"Next.js\",\n \"nuxt\": \"Nuxt.js\",\n express: \"Express\",\n koa: \"Koa\",\n fastify: \"Fastify\",\n \"@nestjs/core\": \"NestJS\",\n prisma: \"Prisma\",\n mongoose: \"Mongoose\",\n typeorm: \"TypeORM\",\n sequelize: \"Sequelize\",\n tailwindcss: \"Tailwind CSS\",\n typescript: \"TypeScript\",\n \"@supabase/supabase-js\": \"Supabase\",\n \"socket.io\": \"Socket.IO\",\n redis: \"Redis\",\n bull: \"Bull (Queue)\",\n \"@prisma/client\": \"Prisma\",\n};\n\nexport class ContextLoader {\n constructor(private projectRoot: string) {}\n\n async loadProjectContext(): Promise<ProjectContext> {\n const context: ProjectContext = {\n techStack: [],\n fileStructure: [],\n dependencies: [],\n apiStructure: [],\n };\n\n try {\n await this.loadPackageJson(context);\n await this.loadPrismaSchema(context);\n await this.loadFileStructure(context);\n await this.loadApiStructure(context);\n await this.loadConstitution(context);\n await this.loadErrorPatterns(context);\n } catch (e) {\n console.warn(\"Warning: Could not load full project context.\", e);\n }\n\n return context;\n }\n\n private async loadPackageJson(context: ProjectContext): Promise<void> {\n const pkgPath = path.join(this.projectRoot, \"package.json\");\n if (!(await fs.pathExists(pkgPath))) return;\n\n const pkg = await fs.readJson(pkgPath);\n const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };\n context.dependencies = Object.keys(allDeps);\n\n const detectedStack = new Set<string>();\n for (const [key, name] of Object.entries(STACK_MAP)) {\n if (context.dependencies.some((d) => d === key || d.startsWith(key + \"/\"))) {\n detectedStack.add(name as string);\n }\n }\n context.techStack = Array.from(detectedStack);\n }\n\n private async loadPrismaSchema(context: ProjectContext): Promise<void> {\n const schemaPath = path.join(this.projectRoot, \"prisma\", \"schema.prisma\");\n if (await fs.pathExists(schemaPath)) {\n context.schema = await fs.readFile(schemaPath, \"utf-8\");\n }\n }\n\n private async loadFileStructure(context: ProjectContext): Promise<void> {\n const files = await glob(\"**/*\", {\n cwd: this.projectRoot,\n ignore: [\n \"node_modules/**\",\n \"dist/**\",\n \".git/**\",\n \"coverage/**\",\n \"*.lock\",\n \".DS_Store\",\n ],\n nodir: false,\n maxDepth: 3,\n });\n context.fileStructure = files.slice(0, 60);\n }\n\n private async loadConstitution(context: ProjectContext): Promise<void> {\n const filePath = path.join(this.projectRoot, \".ai-spec-constitution.md\");\n if (await fs.pathExists(filePath)) {\n context.constitution = await fs.readFile(filePath, \"utf-8\");\n }\n }\n\n private async loadErrorPatterns(context: ProjectContext): Promise<void> {\n // Look for error handler middleware or error code files\n const errorFiles = await glob(\n \"src/**/{error,errors,errorHandler,errorCodes,error-handler,error-codes}.{ts,js}\",\n { cwd: this.projectRoot }\n );\n const middlewareErrors = await glob(\"src/**/middleware/**/{error,notFound}.{ts,js}\", {\n cwd: this.projectRoot,\n });\n const allErrorFiles = [...new Set([...errorFiles, ...middlewareErrors])].slice(0, 3);\n\n if (allErrorFiles.length === 0) return;\n\n const parts: string[] = [];\n for (const f of allErrorFiles) {\n try {\n const content = await fs.readFile(path.join(this.projectRoot, f), \"utf-8\");\n parts.push(`// ${f}\\n${content.slice(0, 800)}`);\n } catch {\n // skip\n }\n }\n if (parts.length > 0) {\n context.errorPatterns = parts.join(\"\\n\\n\");\n }\n }\n\n private async loadApiStructure(context: ProjectContext): Promise<void> {\n const apiFiles = await glob(\n \"src/**/{routes,controllers,api,router,middleware}/**/*.{ts,js}\",\n {\n cwd: this.projectRoot,\n ignore: [\"**/*.test.*\", \"**/*.spec.*\"],\n }\n );\n\n // Also check common flat structures\n const rootApiFiles = await glob(\"src/{routes,controllers,router}.{ts,js}\", {\n cwd: this.projectRoot,\n });\n\n context.apiStructure = [...new Set([...apiFiles, ...rootApiFiles])];\n\n // Build route summary: read first 60 lines of each route file\n if (context.apiStructure.length > 0) {\n const summaryParts: string[] = [];\n for (const filePath of context.apiStructure.slice(0, 8)) {\n const fullPath = path.join(this.projectRoot, filePath);\n try {\n const content = await fs.readFile(fullPath, \"utf-8\");\n const preview = content.split(\"\\n\").slice(0, 60).join(\"\\n\");\n summaryParts.push(`\\`\\`\\`\\n// ${filePath}\\n${preview}\\n\\`\\`\\``);\n } catch {\n // skip unreadable files\n }\n }\n if (summaryParts.length > 0) {\n context.routeSummary = summaryParts.join(\"\\n\\n\");\n }\n }\n }\n}\n","export const balanced = (\n a: string | RegExp,\n b: string | RegExp,\n str: string,\n) => {\n const ma = a instanceof RegExp ? maybeMatch(a, str) : a\n const mb = b instanceof RegExp ? maybeMatch(b, str) : b\n\n const r = ma !== null && mb != null && range(ma, mb, str)\n\n return (\n r && {\n start: r[0],\n end: r[1],\n pre: str.slice(0, r[0]),\n body: str.slice(r[0] + ma.length, r[1]),\n post: str.slice(r[1] + mb.length),\n }\n )\n}\n\nconst maybeMatch = (reg: RegExp, str: string) => {\n const m = str.match(reg)\n return m ? m[0] : null\n}\n\nexport const range = (\n a: string,\n b: string,\n str: string,\n): undefined | [number, number] => {\n let begs: number[],\n beg: number | undefined,\n left: number,\n right: number | undefined = undefined,\n result: undefined | [number, number]\n let ai = str.indexOf(a)\n let bi = str.indexOf(b, ai + 1)\n let i = ai\n\n if (ai >= 0 && bi > 0) {\n if (a === b) {\n return [ai, bi]\n }\n begs = []\n left = str.length\n\n while (i >= 0 && !result) {\n if (i === ai) {\n begs.push(i)\n ai = str.indexOf(a, i + 1)\n } else if (begs.length === 1) {\n const r = begs.pop()\n if (r !== undefined) result = [r, bi]\n } else {\n beg = begs.pop()\n if (beg !== undefined && beg < left) {\n left = beg\n right = bi\n }\n\n bi = str.indexOf(b, i + 1)\n }\n\n i = ai < bi && ai >= 0 ? ai : bi\n }\n\n if (begs.length && right !== undefined) {\n result = [left, right]\n }\n }\n\n return result\n}\n","import { balanced } from 'balanced-match'\n\nconst escSlash = '\\0SLASH' + Math.random() + '\\0'\nconst escOpen = '\\0OPEN' + Math.random() + '\\0'\nconst escClose = '\\0CLOSE' + Math.random() + '\\0'\nconst escComma = '\\0COMMA' + Math.random() + '\\0'\nconst escPeriod = '\\0PERIOD' + Math.random() + '\\0'\nconst escSlashPattern = new RegExp(escSlash, 'g')\nconst escOpenPattern = new RegExp(escOpen, 'g')\nconst escClosePattern = new RegExp(escClose, 'g')\nconst escCommaPattern = new RegExp(escComma, 'g')\nconst escPeriodPattern = new RegExp(escPeriod, 'g')\nconst slashPattern = /\\\\\\\\/g\nconst openPattern = /\\\\{/g\nconst closePattern = /\\\\}/g\nconst commaPattern = /\\\\,/g\nconst periodPattern = /\\\\./g\n\nexport const EXPANSION_MAX = 100_000\n\nfunction numeric(str: string) {\n return !isNaN(str as any) ? parseInt(str, 10) : str.charCodeAt(0)\n}\n\nfunction escapeBraces(str: string) {\n return str\n .replace(slashPattern, escSlash)\n .replace(openPattern, escOpen)\n .replace(closePattern, escClose)\n .replace(commaPattern, escComma)\n .replace(periodPattern, escPeriod)\n}\n\nfunction unescapeBraces(str: string) {\n return str\n .replace(escSlashPattern, '\\\\')\n .replace(escOpenPattern, '{')\n .replace(escClosePattern, '}')\n .replace(escCommaPattern, ',')\n .replace(escPeriodPattern, '.')\n}\n\n/**\n * Basically just str.split(\",\"), but handling cases\n * where we have nested braced sections, which should be\n * treated as individual members, like {a,{b,c},d}\n */\nfunction parseCommaParts(str: string) {\n if (!str) {\n return ['']\n }\n\n const parts: string[] = []\n const m = balanced('{', '}', str)\n\n if (!m) {\n return str.split(',')\n }\n\n const { pre, body, post } = m\n const p = pre.split(',')\n\n p[p.length - 1] += '{' + body + '}'\n const postParts = parseCommaParts(post)\n if (post.length) {\n ;(p[p.length - 1] as string) += postParts.shift()\n p.push.apply(p, postParts)\n }\n\n parts.push.apply(parts, p)\n\n return parts\n}\n\nexport type BraceExpansionOptions = {\n max?: number\n}\n\nexport function expand(str: string, options: BraceExpansionOptions = {}) {\n if (!str) {\n return []\n }\n\n const { max = EXPANSION_MAX } = options\n\n // I don't know why Bash 4.3 does this, but it does.\n // Anything starting with {} will have the first two bytes preserved\n // but *only* at the top level, so {},a}b will not expand to anything,\n // but a{},b}c will be expanded to [a}c,abc].\n // One could argue that this is a bug in Bash, but since the goal of\n // this module is to match Bash's rules, we escape a leading {}\n if (str.slice(0, 2) === '{}') {\n str = '\\\\{\\\\}' + str.slice(2)\n }\n\n return expand_(escapeBraces(str), max, true).map(unescapeBraces)\n}\n\nfunction embrace(str: string) {\n return '{' + str + '}'\n}\n\nfunction isPadded(el: string) {\n return /^-?0\\d/.test(el)\n}\n\nfunction lte(i: number, y: number) {\n return i <= y\n}\n\nfunction gte(i: number, y: number) {\n return i >= y\n}\n\nfunction expand_(str: string, max: number, isTop: boolean): string[] {\n /** @type {string[]} */\n const expansions: string[] = []\n\n const m = balanced('{', '}', str)\n if (!m) return [str]\n\n // no need to expand pre, since it is guaranteed to be free of brace-sets\n const pre = m.pre\n const post: string[] = m.post.length ? expand_(m.post, max, false) : ['']\n\n if (/\\$$/.test(m.pre)) {\n for (let k = 0; k < post.length && k < max; k++) {\n const expansion = pre + '{' + m.body + '}' + post[k]\n expansions.push(expansion)\n }\n } else {\n const isNumericSequence = /^-?\\d+\\.\\.-?\\d+(?:\\.\\.-?\\d+)?$/.test(m.body)\n const isAlphaSequence = /^[a-zA-Z]\\.\\.[a-zA-Z](?:\\.\\.-?\\d+)?$/.test(\n m.body,\n )\n const isSequence = isNumericSequence || isAlphaSequence\n const isOptions = m.body.indexOf(',') >= 0\n if (!isSequence && !isOptions) {\n // {a},b}\n if (m.post.match(/,(?!,).*\\}/)) {\n str = m.pre + '{' + m.body + escClose + m.post\n return expand_(str, max, true)\n }\n return [str]\n }\n\n let n: string[]\n if (isSequence) {\n n = m.body.split(/\\.\\./)\n } else {\n n = parseCommaParts(m.body)\n if (n.length === 1 && n[0] !== undefined) {\n // x{{a,b}}y ==> x{a}y x{b}y\n n = expand_(n[0], max, false).map(embrace)\n //XXX is this necessary? Can't seem to hit it in tests.\n /* c8 ignore start */\n if (n.length === 1) {\n return post.map(p => m.pre + n[0] + p)\n }\n /* c8 ignore stop */\n }\n }\n\n // at this point, n is the parts, and we know it's not a comma set\n // with a single entry.\n let N: string[]\n\n if (isSequence && n[0] !== undefined && n[1] !== undefined) {\n const x = numeric(n[0])\n const y = numeric(n[1])\n const width = Math.max(n[0].length, n[1].length)\n let incr =\n n.length === 3 && n[2] !== undefined ? Math.abs(numeric(n[2])) : 1\n let test = lte\n const reverse = y < x\n if (reverse) {\n incr *= -1\n test = gte\n }\n const pad = n.some(isPadded)\n\n N = []\n\n for (let i = x; test(i, y); i += incr) {\n let c\n if (isAlphaSequence) {\n c = String.fromCharCode(i)\n if (c === '\\\\') {\n c = ''\n }\n } else {\n c = String(i)\n if (pad) {\n const need = width - c.length\n if (need > 0) {\n const z = new Array(need + 1).join('0')\n if (i < 0) {\n c = '-' + z + c.slice(1)\n } else {\n c = z + c\n }\n }\n }\n }\n N.push(c)\n }\n } else {\n N = []\n\n for (let j = 0; j < n.length; j++) {\n N.push.apply(N, expand_(n[j] as string, max, false))\n }\n }\n\n for (let j = 0; j < N.length; j++) {\n for (let k = 0; k < post.length && expansions.length < max; k++) {\n const expansion = pre + N[j] + post[k]\n if (!isTop || isSequence || expansion) {\n expansions.push(expansion)\n }\n }\n }\n }\n\n return expansions\n}\n","const MAX_PATTERN_LENGTH = 1024 * 64\nexport const assertValidPattern: (pattern: any) => void = (\n pattern: any,\n): asserts pattern is string => {\n if (typeof pattern !== 'string') {\n throw new TypeError('invalid pattern')\n }\n\n if (pattern.length > MAX_PATTERN_LENGTH) {\n throw new TypeError('pattern is too long')\n }\n}\n","// translate the various posix character classes into unicode properties\n// this works across all unicode locales\n\n// { <posix class>: [<translation>, /u flag required, negated]\nconst posixClasses: { [k: string]: [e: string, u: boolean, n?: boolean] } =\n {\n '[:alnum:]': ['\\\\p{L}\\\\p{Nl}\\\\p{Nd}', true],\n '[:alpha:]': ['\\\\p{L}\\\\p{Nl}', true],\n '[:ascii:]': ['\\\\x' + '00-\\\\x' + '7f', false],\n '[:blank:]': ['\\\\p{Zs}\\\\t', true],\n '[:cntrl:]': ['\\\\p{Cc}', true],\n '[:digit:]': ['\\\\p{Nd}', true],\n '[:graph:]': ['\\\\p{Z}\\\\p{C}', true, true],\n '[:lower:]': ['\\\\p{Ll}', true],\n '[:print:]': ['\\\\p{C}', true],\n '[:punct:]': ['\\\\p{P}', true],\n '[:space:]': ['\\\\p{Z}\\\\t\\\\r\\\\n\\\\v\\\\f', true],\n '[:upper:]': ['\\\\p{Lu}', true],\n '[:word:]': ['\\\\p{L}\\\\p{Nl}\\\\p{Nd}\\\\p{Pc}', true],\n '[:xdigit:]': ['A-Fa-f0-9', false],\n }\n\n// only need to escape a few things inside of brace expressions\n// escapes: [ \\ ] -\nconst braceEscape = (s: string) => s.replace(/[[\\]\\\\-]/g, '\\\\$&')\n// escape all regexp magic characters\nconst regexpEscape = (s: string) =>\n s.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&')\n\n// everything has already been escaped, we just have to join\nconst rangesToString = (ranges: string[]): string => ranges.join('')\n\nexport type ParseClassResult = [\n src: string,\n uFlag: boolean,\n consumed: number,\n hasMagic: boolean,\n]\n\n// takes a glob string at a posix brace expression, and returns\n// an equivalent regular expression source, and boolean indicating\n// whether the /u flag needs to be applied, and the number of chars\n// consumed to parse the character class.\n// This also removes out of order ranges, and returns ($.) if the\n// entire class just no good.\nexport const parseClass = (\n glob: string,\n position: number,\n): ParseClassResult => {\n const pos = position\n /* c8 ignore start */\n if (glob.charAt(pos) !== '[') {\n throw new Error('not in a brace expression')\n }\n /* c8 ignore stop */\n const ranges: string[] = []\n const negs: string[] = []\n\n let i = pos + 1\n let sawStart = false\n let uflag = false\n let escaping = false\n let negate = false\n let endPos = pos\n let rangeStart = ''\n WHILE: while (i < glob.length) {\n const c = glob.charAt(i)\n if ((c === '!' || c === '^') && i === pos + 1) {\n negate = true\n i++\n continue\n }\n\n if (c === ']' && sawStart && !escaping) {\n endPos = i + 1\n break\n }\n\n sawStart = true\n if (c === '\\\\') {\n if (!escaping) {\n escaping = true\n i++\n continue\n }\n // escaped \\ char, fall through and treat like normal char\n }\n if (c === '[' && !escaping) {\n // either a posix class, a collation equivalent, or just a [\n for (const [cls, [unip, u, neg]] of Object.entries(posixClasses)) {\n if (glob.startsWith(cls, i)) {\n // invalid, [a-[] is fine, but not [a-[:alpha]]\n if (rangeStart) {\n return ['$.', false, glob.length - pos, true]\n }\n i += cls.length\n if (neg) negs.push(unip)\n else ranges.push(unip)\n uflag = uflag || u\n continue WHILE\n }\n }\n }\n\n // now it's just a normal character, effectively\n escaping = false\n if (rangeStart) {\n // throw this range away if it's not valid, but others\n // can still match.\n if (c > rangeStart) {\n ranges.push(braceEscape(rangeStart) + '-' + braceEscape(c))\n } else if (c === rangeStart) {\n ranges.push(braceEscape(c))\n }\n rangeStart = ''\n i++\n continue\n }\n\n // now might be the start of a range.\n // can be either c-d or c-] or c<more...>] or c] at this point\n if (glob.startsWith('-]', i + 1)) {\n ranges.push(braceEscape(c + '-'))\n i += 2\n continue\n }\n if (glob.startsWith('-', i + 1)) {\n rangeStart = c\n i += 2\n continue\n }\n\n // not the start of a range, just a single character\n ranges.push(braceEscape(c))\n i++\n }\n\n if (endPos < i) {\n // didn't see the end of the class, not a valid class,\n // but might still be valid as a literal match.\n return ['', false, 0, false]\n }\n\n // if we got no ranges and no negates, then we have a range that\n // cannot possibly match anything, and that poisons the whole glob\n if (!ranges.length && !negs.length) {\n return ['$.', false, glob.length - pos, true]\n }\n\n // if we got one positive range, and it's a single character, then that's\n // not actually a magic pattern, it's just that one literal character.\n // we should not treat that as \"magic\", we should just return the literal\n // character. [_] is a perfectly valid way to escape glob magic chars.\n if (\n negs.length === 0 &&\n ranges.length === 1 &&\n /^\\\\?.$/.test(ranges[0]) &&\n !negate\n ) {\n const r = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0]\n return [regexpEscape(r), false, endPos - pos, false]\n }\n\n const sranges = '[' + (negate ? '^' : '') + rangesToString(ranges) + ']'\n const snegs = '[' + (negate ? '' : '^') + rangesToString(negs) + ']'\n const comb =\n ranges.length && negs.length ? '(' + sranges + '|' + snegs + ')'\n : ranges.length ? sranges\n : snegs\n\n return [comb, uflag, endPos - pos, true]\n}\n","import { MinimatchOptions } from './index.js'\n\n/**\n * Un-escape a string that has been escaped with {@link escape}.\n *\n * If the {@link MinimatchOptions.windowsPathsNoEscape} option is used, then\n * square-bracket escapes are removed, but not backslash escapes.\n *\n * For example, it will turn the string `'[*]'` into `*`, but it will not\n * turn `'\\\\*'` into `'*'`, because `\\` is a path separator in\n * `windowsPathsNoEscape` mode.\n *\n * When `windowsPathsNoEscape` is not set, then both square-bracket escapes and\n * backslash escapes are removed.\n *\n * Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot be escaped\n * or unescaped.\n *\n * When `magicalBraces` is not set, escapes of braces (`{` and `}`) will not be\n * unescaped.\n */\n\nexport const unescape = (\n s: string,\n {\n windowsPathsNoEscape = false,\n magicalBraces = true,\n }: Pick<MinimatchOptions, 'windowsPathsNoEscape' | 'magicalBraces'> = {},\n) => {\n if (magicalBraces) {\n return windowsPathsNoEscape ?\n s.replace(/\\[([^\\/\\\\])\\]/g, '$1')\n : s\n .replace(/((?!\\\\).|^)\\[([^\\/\\\\])\\]/g, '$1$2')\n .replace(/\\\\([^\\/])/g, '$1')\n }\n return windowsPathsNoEscape ?\n s.replace(/\\[([^\\/\\\\{}])\\]/g, '$1')\n : s\n .replace(/((?!\\\\).|^)\\[([^\\/\\\\{}])\\]/g, '$1$2')\n .replace(/\\\\([^\\/{}])/g, '$1')\n}\n","// parse a single path portion\n\nimport { parseClass } from './brace-expressions.js'\nimport { MinimatchOptions, MMRegExp } from './index.js'\nimport { unescape } from './unescape.js'\n\n// classes [] are handled by the parseClass method\n// for positive extglobs, we sub-parse the contents, and combine,\n// with the appropriate regexp close.\n// for negative extglobs, we sub-parse the contents, but then\n// have to include the rest of the pattern, then the parent, etc.,\n// as the thing that cannot be because RegExp negative lookaheads\n// are different from globs.\n//\n// So for example:\n// a@(i|w!(x|y)z|j)b => ^a(i|w((!?(x|y)zb).*)z|j)b$\n// 1 2 3 4 5 6 1 2 3 46 5 6\n//\n// Assembling the extglob requires not just the negated patterns themselves,\n// but also anything following the negative patterns up to the boundary\n// of the current pattern, plus anything following in the parent pattern.\n//\n//\n// So, first, we parse the string into an AST of extglobs, without turning\n// anything into regexps yet.\n//\n// ['a', {@ [['i'], ['w', {!['x', 'y']}, 'z'], ['j']]}, 'b']\n//\n// Then, for all the negative extglobs, we append whatever comes after in\n// each parent as their tail\n//\n// ['a', {@ [['i'], ['w', {!['x', 'y'], 'z', 'b'}, 'z'], ['j']]}, 'b']\n//\n// Lastly, we turn each of these pieces into a regexp, and join\n//\n// v----- .* because there's more following,\n// v v otherwise, .+ because it must be\n// v v *something* there.\n// ['^a', {@ ['i', 'w(?:(!?(?:x|y).*zb$).*)z', 'j' ]}, 'b$']\n// copy what follows into here--^^^^^\n// ['^a', '(?:i|w(?:(?!(?:x|y).*zb$).*)z|j)', 'b$']\n// ['^a(?:i|w(?:(?!(?:x|y).*zb$).*)z|j)b$']\n\nexport type ExtglobType = '!' | '?' | '+' | '*' | '@'\nconst types = new Set<ExtglobType>(['!', '?', '+', '*', '@'])\nconst isExtglobType = (c: string): c is ExtglobType =>\n types.has(c as ExtglobType)\n\n// Patterns that get prepended to bind to the start of either the\n// entire string, or just a single path portion, to prevent dots\n// and/or traversal patterns, when needed.\n// Exts don't need the ^ or / bit, because the root binds that already.\nconst startNoTraversal = '(?!(?:^|/)\\\\.\\\\.?(?:$|/))'\nconst startNoDot = '(?!\\\\.)'\n\n// characters that indicate a start of pattern needs the \"no dots\" bit,\n// because a dot *might* be matched. ( is not in the list, because in\n// the case of a child extglob, it will handle the prevention itself.\nconst addPatternStart = new Set(['[', '.'])\n// cases where traversal is A-OK, no dot prevention needed\nconst justDots = new Set(['..', '.'])\nconst reSpecials = new Set('().*{}+?[]^$\\\\!')\nconst regExpEscape = (s: string) =>\n s.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&')\n\n// any single thing other than /\nconst qmark = '[^/]'\n\n// * => any number of characters\nconst star = qmark + '*?'\n// use + when we need to ensure that *something* matches, because the * is\n// the only thing in the path portion.\nconst starNoEmpty = qmark + '+?'\n\n// remove the \\ chars that we added if we end up doing a nonmagic compare\n// const deslash = (s: string) => s.replace(/\\\\(.)/g, '$1')\n\nexport class AST {\n type: ExtglobType | null\n readonly #root: AST\n\n #hasMagic?: boolean\n #uflag: boolean = false\n #parts: (string | AST)[] = []\n readonly #parent?: AST\n readonly #parentIndex: number\n #negs: AST[]\n #filledNegs: boolean = false\n #options: MinimatchOptions\n #toString?: string\n // set to true if it's an extglob with no children\n // (which really means one child of '')\n #emptyExt: boolean = false\n\n constructor(\n type: ExtglobType | null,\n parent?: AST,\n options: MinimatchOptions = {},\n ) {\n this.type = type\n // extglobs are inherently magical\n if (type) this.#hasMagic = true\n this.#parent = parent\n this.#root = this.#parent ? this.#parent.#root : this\n this.#options = this.#root === this ? options : this.#root.#options\n this.#negs = this.#root === this ? [] : this.#root.#negs\n if (type === '!' && !this.#root.#filledNegs) this.#negs.push(this)\n this.#parentIndex = this.#parent ? this.#parent.#parts.length : 0\n }\n\n get hasMagic(): boolean | undefined {\n /* c8 ignore start */\n if (this.#hasMagic !== undefined) return this.#hasMagic\n /* c8 ignore stop */\n for (const p of this.#parts) {\n if (typeof p === 'string') continue\n if (p.type || p.hasMagic) return (this.#hasMagic = true)\n }\n // note: will be undefined until we generate the regexp src and find out\n return this.#hasMagic\n }\n\n // reconstructs the pattern\n toString(): string {\n if (this.#toString !== undefined) return this.#toString\n if (!this.type) {\n return (this.#toString = this.#parts.map(p => String(p)).join(''))\n } else {\n return (this.#toString =\n this.type + '(' + this.#parts.map(p => String(p)).join('|') + ')')\n }\n }\n\n #fillNegs() {\n /* c8 ignore start */\n if (this !== this.#root) throw new Error('should only call on root')\n if (this.#filledNegs) return this\n /* c8 ignore stop */\n\n // call toString() once to fill this out\n this.toString()\n this.#filledNegs = true\n let n: AST | undefined\n while ((n = this.#negs.pop())) {\n if (n.type !== '!') continue\n // walk up the tree, appending everthing that comes AFTER parentIndex\n let p: AST | undefined = n\n let pp = p.#parent\n while (pp) {\n for (\n let i = p.#parentIndex + 1;\n !pp.type && i < pp.#parts.length;\n i++\n ) {\n for (const part of n.#parts) {\n /* c8 ignore start */\n if (typeof part === 'string') {\n throw new Error('string part in extglob AST??')\n }\n /* c8 ignore stop */\n part.copyIn(pp.#parts[i])\n }\n }\n p = pp\n pp = p.#parent\n }\n }\n return this\n }\n\n push(...parts: (string | AST)[]) {\n for (const p of parts) {\n if (p === '') continue\n /* c8 ignore start */\n if (\n typeof p !== 'string' &&\n !(p instanceof AST && p.#parent === this)\n ) {\n throw new Error('invalid part: ' + p)\n }\n /* c8 ignore stop */\n this.#parts.push(p)\n }\n }\n\n toJSON() {\n const ret: any[] =\n this.type === null ?\n this.#parts\n .slice()\n .map(p => (typeof p === 'string' ? p : p.toJSON()))\n : [this.type, ...this.#parts.map(p => (p as AST).toJSON())]\n if (this.isStart() && !this.type) ret.unshift([])\n if (\n this.isEnd() &&\n (this === this.#root ||\n (this.#root.#filledNegs && this.#parent?.type === '!'))\n ) {\n ret.push({})\n }\n return ret\n }\n\n isStart(): boolean {\n if (this.#root === this) return true\n // if (this.type) return !!this.#parent?.isStart()\n if (!this.#parent?.isStart()) return false\n if (this.#parentIndex === 0) return true\n // if everything AHEAD of this is a negation, then it's still the \"start\"\n const p = this.#parent\n for (let i = 0; i < this.#parentIndex; i++) {\n const pp = p.#parts[i]\n if (!(pp instanceof AST && pp.type === '!')) {\n return false\n }\n }\n return true\n }\n\n isEnd(): boolean {\n if (this.#root === this) return true\n if (this.#parent?.type === '!') return true\n if (!this.#parent?.isEnd()) return false\n if (!this.type) return this.#parent?.isEnd()\n // if not root, it'll always have a parent\n /* c8 ignore start */\n const pl = this.#parent ? this.#parent.#parts.length : 0\n /* c8 ignore stop */\n return this.#parentIndex === pl - 1\n }\n\n copyIn(part: AST | string) {\n if (typeof part === 'string') this.push(part)\n else this.push(part.clone(this))\n }\n\n clone(parent: AST) {\n const c = new AST(this.type, parent)\n for (const p of this.#parts) {\n c.copyIn(p)\n }\n return c\n }\n\n static #parseAST(\n str: string,\n ast: AST,\n pos: number,\n opt: MinimatchOptions,\n ): number {\n let escaping = false\n let inBrace = false\n let braceStart = -1\n let braceNeg = false\n if (ast.type === null) {\n // outside of a extglob, append until we find a start\n let i = pos\n let acc = ''\n while (i < str.length) {\n const c = str.charAt(i++)\n // still accumulate escapes at this point, but we do ignore\n // starts that are escaped\n if (escaping || c === '\\\\') {\n escaping = !escaping\n acc += c\n continue\n }\n\n if (inBrace) {\n if (i === braceStart + 1) {\n if (c === '^' || c === '!') {\n braceNeg = true\n }\n } else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {\n inBrace = false\n }\n acc += c\n continue\n } else if (c === '[') {\n inBrace = true\n braceStart = i\n braceNeg = false\n acc += c\n continue\n }\n\n if (!opt.noext && isExtglobType(c) && str.charAt(i) === '(') {\n ast.push(acc)\n acc = ''\n const ext = new AST(c, ast)\n i = AST.#parseAST(str, ext, i, opt)\n ast.push(ext)\n continue\n }\n acc += c\n }\n ast.push(acc)\n return i\n }\n\n // some kind of extglob, pos is at the (\n // find the next | or )\n let i = pos + 1\n let part = new AST(null, ast)\n const parts: AST[] = []\n let acc = ''\n while (i < str.length) {\n const c = str.charAt(i++)\n // still accumulate escapes at this point, but we do ignore\n // starts that are escaped\n if (escaping || c === '\\\\') {\n escaping = !escaping\n acc += c\n continue\n }\n\n if (inBrace) {\n if (i === braceStart + 1) {\n if (c === '^' || c === '!') {\n braceNeg = true\n }\n } else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {\n inBrace = false\n }\n acc += c\n continue\n } else if (c === '[') {\n inBrace = true\n braceStart = i\n braceNeg = false\n acc += c\n continue\n }\n\n if (isExtglobType(c) && str.charAt(i) === '(') {\n part.push(acc)\n acc = ''\n const ext = new AST(c, part)\n part.push(ext)\n i = AST.#parseAST(str, ext, i, opt)\n continue\n }\n if (c === '|') {\n part.push(acc)\n acc = ''\n parts.push(part)\n part = new AST(null, ast)\n continue\n }\n if (c === ')') {\n if (acc === '' && ast.#parts.length === 0) {\n ast.#emptyExt = true\n }\n part.push(acc)\n acc = ''\n ast.push(...parts, part)\n return i\n }\n acc += c\n }\n\n // unfinished extglob\n // if we got here, it was a malformed extglob! not an extglob, but\n // maybe something else in there.\n ast.type = null\n ast.#hasMagic = undefined\n ast.#parts = [str.substring(pos - 1)]\n return i\n }\n\n static fromGlob(pattern: string, options: MinimatchOptions = {}) {\n const ast = new AST(null, undefined, options)\n AST.#parseAST(pattern, ast, 0, options)\n return ast\n }\n\n // returns the regular expression if there's magic, or the unescaped\n // string if not.\n toMMPattern(): MMRegExp | string {\n // should only be called on root\n /* c8 ignore start */\n if (this !== this.#root) return this.#root.toMMPattern()\n /* c8 ignore stop */\n const glob = this.toString()\n const [re, body, hasMagic, uflag] = this.toRegExpSource()\n // if we're in nocase mode, and not nocaseMagicOnly, then we do\n // still need a regular expression if we have to case-insensitively\n // match capital/lowercase characters.\n const anyMagic =\n hasMagic ||\n this.#hasMagic ||\n (this.#options.nocase &&\n !this.#options.nocaseMagicOnly &&\n glob.toUpperCase() !== glob.toLowerCase())\n if (!anyMagic) {\n return body\n }\n\n const flags = (this.#options.nocase ? 'i' : '') + (uflag ? 'u' : '')\n return Object.assign(new RegExp(`^${re}$`, flags), {\n _src: re,\n _glob: glob,\n })\n }\n\n get options() {\n return this.#options\n }\n\n // returns the string match, the regexp source, whether there's magic\n // in the regexp (so a regular expression is required) and whether or\n // not the uflag is needed for the regular expression (for posix classes)\n // TODO: instead of injecting the start/end at this point, just return\n // the BODY of the regexp, along with the start/end portions suitable\n // for binding the start/end in either a joined full-path makeRe context\n // (where we bind to (^|/), or a standalone matchPart context (where\n // we bind to ^, and not /). Otherwise slashes get duped!\n //\n // In part-matching mode, the start is:\n // - if not isStart: nothing\n // - if traversal possible, but not allowed: ^(?!\\.\\.?$)\n // - if dots allowed or not possible: ^\n // - if dots possible and not allowed: ^(?!\\.)\n // end is:\n // - if not isEnd(): nothing\n // - else: $\n //\n // In full-path matching mode, we put the slash at the START of the\n // pattern, so start is:\n // - if first pattern: same as part-matching mode\n // - if not isStart(): nothing\n // - if traversal possible, but not allowed: /(?!\\.\\.?(?:$|/))\n // - if dots allowed or not possible: /\n // - if dots possible and not allowed: /(?!\\.)\n // end is:\n // - if last pattern, same as part-matching mode\n // - else nothing\n //\n // Always put the (?:$|/) on negated tails, though, because that has to be\n // there to bind the end of the negated pattern portion, and it's easier to\n // just stick it in now rather than try to inject it later in the middle of\n // the pattern.\n //\n // We can just always return the same end, and leave it up to the caller\n // to know whether it's going to be used joined or in parts.\n // And, if the start is adjusted slightly, can do the same there:\n // - if not isStart: nothing\n // - if traversal possible, but not allowed: (?:/|^)(?!\\.\\.?$)\n // - if dots allowed or not possible: (?:/|^)\n // - if dots possible and not allowed: (?:/|^)(?!\\.)\n //\n // But it's better to have a simpler binding without a conditional, for\n // performance, so probably better to return both start options.\n //\n // Then the caller just ignores the end if it's not the first pattern,\n // and the start always gets applied.\n //\n // But that's always going to be $ if it's the ending pattern, or nothing,\n // so the caller can just attach $ at the end of the pattern when building.\n //\n // So the todo is:\n // - better detect what kind of start is needed\n // - return both flavors of starting pattern\n // - attach $ at the end of the pattern when creating the actual RegExp\n //\n // Ah, but wait, no, that all only applies to the root when the first pattern\n // is not an extglob. If the first pattern IS an extglob, then we need all\n // that dot prevention biz to live in the extglob portions, because eg\n // +(*|.x*) can match .xy but not .yx.\n //\n // So, return the two flavors if it's #root and the first child is not an\n // AST, otherwise leave it to the child AST to handle it, and there,\n // use the (?:^|/) style of start binding.\n //\n // Even simplified further:\n // - Since the start for a join is eg /(?!\\.) and the start for a part\n // is ^(?!\\.), we can just prepend (?!\\.) to the pattern (either root\n // or start or whatever) and prepend ^ or / at the Regexp construction.\n toRegExpSource(\n allowDot?: boolean,\n ): [re: string, body: string, hasMagic: boolean, uflag: boolean] {\n const dot = allowDot ?? !!this.#options.dot\n if (this.#root === this) this.#fillNegs()\n if (!this.type) {\n const noEmpty =\n this.isStart() &&\n this.isEnd() &&\n !this.#parts.some(s => typeof s !== 'string')\n const src = this.#parts\n .map(p => {\n const [re, _, hasMagic, uflag] =\n typeof p === 'string' ?\n AST.#parseGlob(p, this.#hasMagic, noEmpty)\n : p.toRegExpSource(allowDot)\n this.#hasMagic = this.#hasMagic || hasMagic\n this.#uflag = this.#uflag || uflag\n return re\n })\n .join('')\n\n let start = ''\n if (this.isStart()) {\n if (typeof this.#parts[0] === 'string') {\n // this is the string that will match the start of the pattern,\n // so we need to protect against dots and such.\n\n // '.' and '..' cannot match unless the pattern is that exactly,\n // even if it starts with . or dot:true is set.\n const dotTravAllowed =\n this.#parts.length === 1 && justDots.has(this.#parts[0])\n if (!dotTravAllowed) {\n const aps = addPatternStart\n // check if we have a possibility of matching . or ..,\n // and prevent that.\n const needNoTrav =\n // dots are allowed, and the pattern starts with [ or .\n (dot && aps.has(src.charAt(0))) ||\n // the pattern starts with \\., and then [ or .\n (src.startsWith('\\\\.') && aps.has(src.charAt(2))) ||\n // the pattern starts with \\.\\., and then [ or .\n (src.startsWith('\\\\.\\\\.') && aps.has(src.charAt(4)))\n // no need to prevent dots if it can't match a dot, or if a\n // sub-pattern will be preventing it anyway.\n const needNoDot = !dot && !allowDot && aps.has(src.charAt(0))\n\n start =\n needNoTrav ? startNoTraversal\n : needNoDot ? startNoDot\n : ''\n }\n }\n }\n\n // append the \"end of path portion\" pattern to negation tails\n let end = ''\n if (\n this.isEnd() &&\n this.#root.#filledNegs &&\n this.#parent?.type === '!'\n ) {\n end = '(?:$|\\\\/)'\n }\n const final = start + src + end\n return [\n final,\n unescape(src),\n (this.#hasMagic = !!this.#hasMagic),\n this.#uflag,\n ]\n }\n\n // We need to calculate the body *twice* if it's a repeat pattern\n // at the start, once in nodot mode, then again in dot mode, so a\n // pattern like *(?) can match 'x.y'\n\n const repeated = this.type === '*' || this.type === '+'\n // some kind of extglob\n const start = this.type === '!' ? '(?:(?!(?:' : '(?:'\n let body = this.#partsToRegExp(dot)\n\n if (this.isStart() && this.isEnd() && !body && this.type !== '!') {\n // invalid extglob, has to at least be *something* present, if it's\n // the entire path portion.\n const s = this.toString()\n this.#parts = [s]\n this.type = null\n this.#hasMagic = undefined\n return [s, unescape(this.toString()), false, false]\n }\n\n // XXX abstract out this map method\n let bodyDotAllowed =\n !repeated || allowDot || dot || !startNoDot ?\n ''\n : this.#partsToRegExp(true)\n if (bodyDotAllowed === body) {\n bodyDotAllowed = ''\n }\n if (bodyDotAllowed) {\n body = `(?:${body})(?:${bodyDotAllowed})*?`\n }\n\n // an empty !() is exactly equivalent to a starNoEmpty\n let final = ''\n if (this.type === '!' && this.#emptyExt) {\n final = (this.isStart() && !dot ? startNoDot : '') + starNoEmpty\n } else {\n const close =\n this.type === '!' ?\n // !() must match something,but !(x) can match ''\n '))' +\n (this.isStart() && !dot && !allowDot ? startNoDot : '') +\n star +\n ')'\n : this.type === '@' ? ')'\n : this.type === '?' ? ')?'\n : this.type === '+' && bodyDotAllowed ? ')'\n : this.type === '*' && bodyDotAllowed ? `)?`\n : `)${this.type}`\n final = start + body + close\n }\n return [\n final,\n unescape(body),\n (this.#hasMagic = !!this.#hasMagic),\n this.#uflag,\n ]\n }\n\n #partsToRegExp(dot: boolean) {\n return this.#parts\n .map(p => {\n // extglob ASTs should only contain parent ASTs\n /* c8 ignore start */\n if (typeof p === 'string') {\n throw new Error('string type in extglob ast??')\n }\n /* c8 ignore stop */\n // can ignore hasMagic, because extglobs are already always magic\n const [re, _, _hasMagic, uflag] = p.toRegExpSource(dot)\n this.#uflag = this.#uflag || uflag\n return re\n })\n .filter(p => !(this.isStart() && this.isEnd()) || !!p)\n .join('|')\n }\n\n static #parseGlob(\n glob: string,\n hasMagic: boolean | undefined,\n noEmpty: boolean = false,\n ): [re: string, body: string, hasMagic: boolean, uflag: boolean] {\n let escaping = false\n let re = ''\n let uflag = false\n // multiple stars that aren't globstars coalesce into one *\n let inStar = false\n for (let i = 0; i < glob.length; i++) {\n const c = glob.charAt(i)\n if (escaping) {\n escaping = false\n re += (reSpecials.has(c) ? '\\\\' : '') + c\n continue\n }\n if (c === '*') {\n if (inStar) continue\n inStar = true\n re += noEmpty && /^[*]+$/.test(glob) ? starNoEmpty : star\n hasMagic = true\n continue\n } else {\n inStar = false\n }\n if (c === '\\\\') {\n if (i === glob.length - 1) {\n re += '\\\\\\\\'\n } else {\n escaping = true\n }\n continue\n }\n if (c === '[') {\n const [src, needUflag, consumed, magic] = parseClass(glob, i)\n if (consumed) {\n re += src\n uflag = uflag || needUflag\n i += consumed - 1\n hasMagic = hasMagic || magic\n continue\n }\n }\n if (c === '?') {\n re += qmark\n hasMagic = true\n continue\n }\n re += regExpEscape(c)\n }\n return [re, unescape(glob), !!hasMagic, uflag]\n }\n}\n","import { MinimatchOptions } from './index.js'\n\n/**\n * Escape all magic characters in a glob pattern.\n *\n * If the {@link MinimatchOptions.windowsPathsNoEscape}\n * option is used, then characters are escaped by wrapping in `[]`, because\n * a magic character wrapped in a character class can only be satisfied by\n * that exact character. In this mode, `\\` is _not_ escaped, because it is\n * not interpreted as a magic character, but instead as a path separator.\n *\n * If the {@link MinimatchOptions.magicalBraces} option is used,\n * then braces (`{` and `}`) will be escaped.\n */\nexport const escape = (\n s: string,\n {\n windowsPathsNoEscape = false,\n magicalBraces = false,\n }: Pick<MinimatchOptions, 'windowsPathsNoEscape' | 'magicalBraces'> = {},\n) => {\n // don't need to escape +@! because we escape the parens\n // that make those magic, and escaping ! as [!] isn't valid,\n // because [!]] is a valid glob class meaning not ']'.\n if (magicalBraces) {\n return windowsPathsNoEscape ?\n s.replace(/[?*()[\\]{}]/g, '[$&]')\n : s.replace(/[?*()[\\]\\\\{}]/g, '\\\\$&')\n }\n return windowsPathsNoEscape ?\n s.replace(/[?*()[\\]]/g, '[$&]')\n : s.replace(/[?*()[\\]\\\\]/g, '\\\\$&')\n}\n","import { expand } from 'brace-expansion'\nimport { assertValidPattern } from './assert-valid-pattern.js'\nimport { AST, ExtglobType } from './ast.js'\nimport { escape } from './escape.js'\nimport { unescape } from './unescape.js'\n\nexport type Platform =\n | 'aix'\n | 'android'\n | 'darwin'\n | 'freebsd'\n | 'haiku'\n | 'linux'\n | 'openbsd'\n | 'sunos'\n | 'win32'\n | 'cygwin'\n | 'netbsd'\n\nexport interface MinimatchOptions {\n /** do not expand `{x,y}` style braces */\n nobrace?: boolean\n /** do not treat patterns starting with `#` as a comment */\n nocomment?: boolean\n /** do not treat patterns starting with `!` as a negation */\n nonegate?: boolean\n /** print LOTS of debugging output */\n debug?: boolean\n /** treat `**` the same as `*` */\n noglobstar?: boolean\n /** do not expand extglobs like `+(a|b)` */\n noext?: boolean\n /** return the pattern if nothing matches */\n nonull?: boolean\n /** treat `\\\\` as a path separator, not an escape character */\n windowsPathsNoEscape?: boolean\n /**\n * inverse of {@link MinimatchOptions.windowsPathsNoEscape}\n * @deprecated\n */\n allowWindowsEscape?: boolean\n /**\n * Compare a partial path to a pattern. As long as the parts\n * of the path that are present are not contradicted by the\n * pattern, it will be treated as a match. This is useful in\n * applications where you're walking through a folder structure,\n * and don't yet have the full path, but want to ensure that you\n * do not walk down paths that can never be a match.\n */\n partial?: boolean\n /** allow matches that start with `.` even if the pattern does not */\n dot?: boolean\n /** ignore case */\n nocase?: boolean\n /** ignore case only in wildcard patterns */\n nocaseMagicOnly?: boolean\n /** consider braces to be \"magic\" for the purpose of `hasMagic` */\n magicalBraces?: boolean\n /**\n * If set, then patterns without slashes will be matched\n * against the basename of the path if it contains slashes.\n * For example, `a?b` would match the path `/xyz/123/acb`, but\n * not `/xyz/acb/123`.\n */\n matchBase?: boolean\n /** invert the results of negated matches */\n flipNegate?: boolean\n /** do not collapse multiple `/` into a single `/` */\n preserveMultipleSlashes?: boolean\n /**\n * A number indicating the level of optimization that should be done\n * to the pattern prior to parsing and using it for matches.\n */\n optimizationLevel?: number\n /** operating system platform */\n platform?: Platform\n /**\n * When a pattern starts with a UNC path or drive letter, and in\n * `nocase:true` mode, do not convert the root portions of the\n * pattern into a case-insensitive regular expression, and instead\n * leave them as strings.\n *\n * This is the default when the platform is `win32` and\n * `nocase:true` is set.\n */\n windowsNoMagicRoot?: boolean\n /**\n * max number of `{...}` patterns to expand. Default 100_000.\n */\n braceExpandMax?: number\n}\n\nexport const minimatch = (\n p: string,\n pattern: string,\n options: MinimatchOptions = {},\n) => {\n assertValidPattern(pattern)\n\n // shortcut: comments match nothing.\n if (!options.nocomment && pattern.charAt(0) === '#') {\n return false\n }\n\n return new Minimatch(pattern, options).match(p)\n}\n\n// Optimized checking for the most common glob patterns.\nconst starDotExtRE = /^\\*+([^+@!?\\*\\[\\(]*)$/\nconst starDotExtTest = (ext: string) => (f: string) =>\n !f.startsWith('.') && f.endsWith(ext)\nconst starDotExtTestDot = (ext: string) => (f: string) => f.endsWith(ext)\nconst starDotExtTestNocase = (ext: string) => {\n ext = ext.toLowerCase()\n return (f: string) => !f.startsWith('.') && f.toLowerCase().endsWith(ext)\n}\nconst starDotExtTestNocaseDot = (ext: string) => {\n ext = ext.toLowerCase()\n return (f: string) => f.toLowerCase().endsWith(ext)\n}\nconst starDotStarRE = /^\\*+\\.\\*+$/\nconst starDotStarTest = (f: string) =>\n !f.startsWith('.') && f.includes('.')\nconst starDotStarTestDot = (f: string) =>\n f !== '.' && f !== '..' && f.includes('.')\nconst dotStarRE = /^\\.\\*+$/\nconst dotStarTest = (f: string) =>\n f !== '.' && f !== '..' && f.startsWith('.')\nconst starRE = /^\\*+$/\nconst starTest = (f: string) => f.length !== 0 && !f.startsWith('.')\nconst starTestDot = (f: string) =>\n f.length !== 0 && f !== '.' && f !== '..'\nconst qmarksRE = /^\\?+([^+@!?\\*\\[\\(]*)?$/\nconst qmarksTestNocase = ([$0, ext = '']: RegExpMatchArray) => {\n const noext = qmarksTestNoExt([$0])\n if (!ext) return noext\n ext = ext.toLowerCase()\n return (f: string) => noext(f) && f.toLowerCase().endsWith(ext)\n}\nconst qmarksTestNocaseDot = ([$0, ext = '']: RegExpMatchArray) => {\n const noext = qmarksTestNoExtDot([$0])\n if (!ext) return noext\n ext = ext.toLowerCase()\n return (f: string) => noext(f) && f.toLowerCase().endsWith(ext)\n}\nconst qmarksTestDot = ([$0, ext = '']: RegExpMatchArray) => {\n const noext = qmarksTestNoExtDot([$0])\n return !ext ? noext : (f: string) => noext(f) && f.endsWith(ext)\n}\nconst qmarksTest = ([$0, ext = '']: RegExpMatchArray) => {\n const noext = qmarksTestNoExt([$0])\n return !ext ? noext : (f: string) => noext(f) && f.endsWith(ext)\n}\nconst qmarksTestNoExt = ([$0]: RegExpMatchArray) => {\n const len = $0.length\n return (f: string) => f.length === len && !f.startsWith('.')\n}\nconst qmarksTestNoExtDot = ([$0]: RegExpMatchArray) => {\n const len = $0.length\n return (f: string) => f.length === len && f !== '.' && f !== '..'\n}\n\n/* c8 ignore start */\nconst defaultPlatform: Platform = (\n typeof process === 'object' && process ?\n (typeof process.env === 'object' &&\n process.env &&\n process.env.__MINIMATCH_TESTING_PLATFORM__) ||\n process.platform\n : 'posix') as Platform\n\nexport type Sep = '\\\\' | '/'\n\nconst path: { [k: string]: { sep: Sep } } = {\n win32: { sep: '\\\\' },\n posix: { sep: '/' },\n}\n/* c8 ignore stop */\n\nexport const sep =\n defaultPlatform === 'win32' ? path.win32.sep : path.posix.sep\nminimatch.sep = sep\n\nexport const GLOBSTAR = Symbol('globstar **')\nminimatch.GLOBSTAR = GLOBSTAR\n\n// any single thing other than /\n// don't need to escape / when using new RegExp()\nconst qmark = '[^/]'\n\n// * => any number of characters\nconst star = qmark + '*?'\n\n// ** when dots are allowed. Anything goes, except .. and .\n// not (^ or / followed by one or two dots followed by $ or /),\n// followed by anything, any number of times.\nconst twoStarDot = '(?:(?!(?:\\\\/|^)(?:\\\\.{1,2})($|\\\\/)).)*?'\n\n// not a ^ or / followed by a dot,\n// followed by anything, any number of times.\nconst twoStarNoDot = '(?:(?!(?:\\\\/|^)\\\\.).)*?'\n\nexport const filter =\n (pattern: string, options: MinimatchOptions = {}) =>\n (p: string) =>\n minimatch(p, pattern, options)\nminimatch.filter = filter\n\nconst ext = (a: MinimatchOptions, b: MinimatchOptions = {}) =>\n Object.assign({}, a, b)\n\nexport const defaults = (def: MinimatchOptions): typeof minimatch => {\n if (!def || typeof def !== 'object' || !Object.keys(def).length) {\n return minimatch\n }\n\n const orig = minimatch\n\n const m = (p: string, pattern: string, options: MinimatchOptions = {}) =>\n orig(p, pattern, ext(def, options))\n\n return Object.assign(m, {\n Minimatch: class Minimatch extends orig.Minimatch {\n constructor(pattern: string, options: MinimatchOptions = {}) {\n super(pattern, ext(def, options))\n }\n static defaults(options: MinimatchOptions) {\n return orig.defaults(ext(def, options)).Minimatch\n }\n },\n\n AST: class AST extends orig.AST {\n /* c8 ignore start */\n constructor(\n type: ExtglobType | null,\n parent?: AST,\n options: MinimatchOptions = {},\n ) {\n super(type, parent, ext(def, options))\n }\n /* c8 ignore stop */\n\n static fromGlob(pattern: string, options: MinimatchOptions = {}) {\n return orig.AST.fromGlob(pattern, ext(def, options))\n }\n },\n\n unescape: (\n s: string,\n options: Pick<\n MinimatchOptions,\n 'windowsPathsNoEscape' | 'magicalBraces'\n > = {},\n ) => orig.unescape(s, ext(def, options)),\n\n escape: (\n s: string,\n options: Pick<\n MinimatchOptions,\n 'windowsPathsNoEscape' | 'magicalBraces'\n > = {},\n ) => orig.escape(s, ext(def, options)),\n\n filter: (pattern: string, options: MinimatchOptions = {}) =>\n orig.filter(pattern, ext(def, options)),\n\n defaults: (options: MinimatchOptions) =>\n orig.defaults(ext(def, options)),\n\n makeRe: (pattern: string, options: MinimatchOptions = {}) =>\n orig.makeRe(pattern, ext(def, options)),\n\n braceExpand: (pattern: string, options: MinimatchOptions = {}) =>\n orig.braceExpand(pattern, ext(def, options)),\n\n match: (\n list: string[],\n pattern: string,\n options: MinimatchOptions = {},\n ) => orig.match(list, pattern, ext(def, options)),\n\n sep: orig.sep,\n GLOBSTAR: GLOBSTAR as typeof GLOBSTAR,\n })\n}\nminimatch.defaults = defaults\n\n// Brace expansion:\n// a{b,c}d -> abd acd\n// a{b,}c -> abc ac\n// a{0..3}d -> a0d a1d a2d a3d\n// a{b,c{d,e}f}g -> abg acdfg acefg\n// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg\n//\n// Invalid sets are not expanded.\n// a{2..}b -> a{2..}b\n// a{b}c -> a{b}c\nexport const braceExpand = (\n pattern: string,\n options: MinimatchOptions = {},\n) => {\n assertValidPattern(pattern)\n\n // Thanks to Yeting Li <https://github.com/yetingli> for\n // improving this regexp to avoid a ReDOS vulnerability.\n if (options.nobrace || !/\\{(?:(?!\\{).)*\\}/.test(pattern)) {\n // shortcut. no need to expand.\n return [pattern]\n }\n\n return expand(pattern, { max: options.braceExpandMax })\n}\nminimatch.braceExpand = braceExpand\n\n// parse a component of the expanded set.\n// At this point, no pattern may contain \"/\" in it\n// so we're going to return a 2d array, where each entry is the full\n// pattern, split on '/', and then turned into a regular expression.\n// A regexp is made at the end which joins each array with an\n// escaped /, and another full one which joins each regexp with |.\n//\n// Following the lead of Bash 4.1, note that \"**\" only has special meaning\n// when it is the *only* thing in a path portion. Otherwise, any series\n// of * is equivalent to a single *. Globstar behavior is enabled by\n// default, and can be disabled by setting options.noglobstar.\n\nexport const makeRe = (pattern: string, options: MinimatchOptions = {}) =>\n new Minimatch(pattern, options).makeRe()\nminimatch.makeRe = makeRe\n\nexport const match = (\n list: string[],\n pattern: string,\n options: MinimatchOptions = {},\n) => {\n const mm = new Minimatch(pattern, options)\n list = list.filter(f => mm.match(f))\n if (mm.options.nonull && !list.length) {\n list.push(pattern)\n }\n return list\n}\nminimatch.match = match\n\n// replace stuff like \\* with *\nconst globMagic = /[?*]|[+@!]\\(.*?\\)|\\[|\\]/\nconst regExpEscape = (s: string) =>\n s.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&')\n\nexport type MMRegExp = RegExp & {\n _src?: string\n _glob?: string\n}\n\nexport type ParseReturnFiltered = string | MMRegExp | typeof GLOBSTAR\nexport type ParseReturn = ParseReturnFiltered | false\n\nexport class Minimatch {\n options: MinimatchOptions\n set: ParseReturnFiltered[][]\n pattern: string\n\n windowsPathsNoEscape: boolean\n nonegate: boolean\n negate: boolean\n comment: boolean\n empty: boolean\n preserveMultipleSlashes: boolean\n partial: boolean\n globSet: string[]\n globParts: string[][]\n nocase: boolean\n\n isWindows: boolean\n platform: Platform\n windowsNoMagicRoot: boolean\n\n regexp: false | null | MMRegExp\n constructor(pattern: string, options: MinimatchOptions = {}) {\n assertValidPattern(pattern)\n\n options = options || {}\n this.options = options\n this.pattern = pattern\n this.platform = options.platform || defaultPlatform\n this.isWindows = this.platform === 'win32'\n // avoid the annoying deprecation flag lol\n const awe = ('allowWindow' + 'sEscape') as keyof MinimatchOptions\n this.windowsPathsNoEscape =\n !!options.windowsPathsNoEscape || options[awe] === false\n if (this.windowsPathsNoEscape) {\n this.pattern = this.pattern.replace(/\\\\/g, '/')\n }\n this.preserveMultipleSlashes = !!options.preserveMultipleSlashes\n this.regexp = null\n this.negate = false\n this.nonegate = !!options.nonegate\n this.comment = false\n this.empty = false\n this.partial = !!options.partial\n this.nocase = !!this.options.nocase\n this.windowsNoMagicRoot =\n options.windowsNoMagicRoot !== undefined ?\n options.windowsNoMagicRoot\n : !!(this.isWindows && this.nocase)\n\n this.globSet = []\n this.globParts = []\n this.set = []\n\n // make the set of regexps etc.\n this.make()\n }\n\n hasMagic(): boolean {\n if (this.options.magicalBraces && this.set.length > 1) {\n return true\n }\n for (const pattern of this.set) {\n for (const part of pattern) {\n if (typeof part !== 'string') return true\n }\n }\n return false\n }\n\n debug(..._: any[]) {}\n\n make() {\n const pattern = this.pattern\n const options = this.options\n\n // empty patterns and comments match nothing.\n if (!options.nocomment && pattern.charAt(0) === '#') {\n this.comment = true\n return\n }\n\n if (!pattern) {\n this.empty = true\n return\n }\n\n // step 1: figure out negation, etc.\n this.parseNegate()\n\n // step 2: expand braces\n this.globSet = [...new Set(this.braceExpand())]\n\n if (options.debug) {\n this.debug = (...args: any[]) => console.error(...args)\n }\n\n this.debug(this.pattern, this.globSet)\n\n // step 3: now we have a set, so turn each one into a series of\n // path-portion matching patterns.\n // These will be regexps, except in the case of \"**\", which is\n // set to the GLOBSTAR object for globstar behavior,\n // and will not contain any / characters\n //\n // First, we preprocess to make the glob pattern sets a bit simpler\n // and deduped. There are some perf-killing patterns that can cause\n // problems with a glob walk, but we can simplify them down a bit.\n const rawGlobParts = this.globSet.map(s => this.slashSplit(s))\n this.globParts = this.preprocess(rawGlobParts)\n this.debug(this.pattern, this.globParts)\n\n // glob --> regexps\n let set = this.globParts.map((s, _, __) => {\n if (this.isWindows && this.windowsNoMagicRoot) {\n // check if it's a drive or unc path.\n const isUNC =\n s[0] === '' &&\n s[1] === '' &&\n (s[2] === '?' || !globMagic.test(s[2])) &&\n !globMagic.test(s[3])\n const isDrive = /^[a-z]:/i.test(s[0])\n if (isUNC) {\n return [\n ...s.slice(0, 4),\n ...s.slice(4).map(ss => this.parse(ss)),\n ]\n } else if (isDrive) {\n return [s[0], ...s.slice(1).map(ss => this.parse(ss))]\n }\n }\n return s.map(ss => this.parse(ss))\n })\n\n this.debug(this.pattern, set)\n\n // filter out everything that didn't compile properly.\n this.set = set.filter(\n s => s.indexOf(false) === -1,\n ) as ParseReturnFiltered[][]\n\n // do not treat the ? in UNC paths as magic\n if (this.isWindows) {\n for (let i = 0; i < this.set.length; i++) {\n const p = this.set[i]\n if (\n p[0] === '' &&\n p[1] === '' &&\n this.globParts[i][2] === '?' &&\n typeof p[3] === 'string' &&\n /^[a-z]:$/i.test(p[3])\n ) {\n p[2] = '?'\n }\n }\n }\n\n this.debug(this.pattern, this.set)\n }\n\n // various transforms to equivalent pattern sets that are\n // faster to process in a filesystem walk. The goal is to\n // eliminate what we can, and push all ** patterns as far\n // to the right as possible, even if it increases the number\n // of patterns that we have to process.\n preprocess(globParts: string[][]) {\n // if we're not in globstar mode, then turn ** into *\n if (this.options.noglobstar) {\n for (let i = 0; i < globParts.length; i++) {\n for (let j = 0; j < globParts[i].length; j++) {\n if (globParts[i][j] === '**') {\n globParts[i][j] = '*'\n }\n }\n }\n }\n\n const { optimizationLevel = 1 } = this.options\n\n if (optimizationLevel >= 2) {\n // aggressive optimization for the purpose of fs walking\n globParts = this.firstPhasePreProcess(globParts)\n globParts = this.secondPhasePreProcess(globParts)\n } else if (optimizationLevel >= 1) {\n // just basic optimizations to remove some .. parts\n globParts = this.levelOneOptimize(globParts)\n } else {\n // just collapse multiple ** portions into one\n globParts = this.adjascentGlobstarOptimize(globParts)\n }\n\n return globParts\n }\n\n // just get rid of adjascent ** portions\n adjascentGlobstarOptimize(globParts: string[][]) {\n return globParts.map(parts => {\n let gs: number = -1\n while (-1 !== (gs = parts.indexOf('**', gs + 1))) {\n let i = gs\n while (parts[i + 1] === '**') {\n i++\n }\n if (i !== gs) {\n parts.splice(gs, i - gs)\n }\n }\n return parts\n })\n }\n\n // get rid of adjascent ** and resolve .. portions\n levelOneOptimize(globParts: string[][]) {\n return globParts.map(parts => {\n parts = parts.reduce((set: string[], part) => {\n const prev = set[set.length - 1]\n if (part === '**' && prev === '**') {\n return set\n }\n if (part === '..') {\n if (prev && prev !== '..' && prev !== '.' && prev !== '**') {\n set.pop()\n return set\n }\n }\n set.push(part)\n return set\n }, [])\n return parts.length === 0 ? [''] : parts\n })\n }\n\n levelTwoFileOptimize(parts: string | string[]) {\n if (!Array.isArray(parts)) {\n parts = this.slashSplit(parts)\n }\n let didSomething: boolean = false\n do {\n didSomething = false\n // <pre>/<e>/<rest> -> <pre>/<rest>\n if (!this.preserveMultipleSlashes) {\n for (let i = 1; i < parts.length - 1; i++) {\n const p = parts[i]\n // don't squeeze out UNC patterns\n if (i === 1 && p === '' && parts[0] === '') continue\n if (p === '.' || p === '') {\n didSomething = true\n parts.splice(i, 1)\n i--\n }\n }\n if (\n parts[0] === '.' &&\n parts.length === 2 &&\n (parts[1] === '.' || parts[1] === '')\n ) {\n didSomething = true\n parts.pop()\n }\n }\n\n // <pre>/<p>/../<rest> -> <pre>/<rest>\n let dd: number = 0\n while (-1 !== (dd = parts.indexOf('..', dd + 1))) {\n const p = parts[dd - 1]\n if (p && p !== '.' && p !== '..' && p !== '**') {\n didSomething = true\n parts.splice(dd - 1, 2)\n dd -= 2\n }\n }\n } while (didSomething)\n return parts.length === 0 ? [''] : parts\n }\n\n // First phase: single-pattern processing\n // <pre> is 1 or more portions\n // <rest> is 1 or more portions\n // <p> is any portion other than ., .., '', or **\n // <e> is . or ''\n //\n // **/.. is *brutal* for filesystem walking performance, because\n // it effectively resets the recursive walk each time it occurs,\n // and ** cannot be reduced out by a .. pattern part like a regexp\n // or most strings (other than .., ., and '') can be.\n //\n // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}\n // <pre>/<e>/<rest> -> <pre>/<rest>\n // <pre>/<p>/../<rest> -> <pre>/<rest>\n // **/**/<rest> -> **/<rest>\n //\n // **/*/<rest> -> */**/<rest> <== not valid because ** doesn't follow\n // this WOULD be allowed if ** did follow symlinks, or * didn't\n firstPhasePreProcess(globParts: string[][]) {\n let didSomething = false\n do {\n didSomething = false\n // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}\n for (let parts of globParts) {\n let gs: number = -1\n while (-1 !== (gs = parts.indexOf('**', gs + 1))) {\n let gss: number = gs\n while (parts[gss + 1] === '**') {\n // <pre>/**/**/<rest> -> <pre>/**/<rest>\n gss++\n }\n // eg, if gs is 2 and gss is 4, that means we have 3 **\n // parts, and can remove 2 of them.\n if (gss > gs) {\n parts.splice(gs + 1, gss - gs)\n }\n\n let next = parts[gs + 1]\n const p = parts[gs + 2]\n const p2 = parts[gs + 3]\n if (next !== '..') continue\n if (\n !p ||\n p === '.' ||\n p === '..' ||\n !p2 ||\n p2 === '.' ||\n p2 === '..'\n ) {\n continue\n }\n didSomething = true\n // edit parts in place, and push the new one\n parts.splice(gs, 1)\n const other = parts.slice(0)\n other[gs] = '**'\n globParts.push(other)\n gs--\n }\n\n // <pre>/<e>/<rest> -> <pre>/<rest>\n if (!this.preserveMultipleSlashes) {\n for (let i = 1; i < parts.length - 1; i++) {\n const p = parts[i]\n // don't squeeze out UNC patterns\n if (i === 1 && p === '' && parts[0] === '') continue\n if (p === '.' || p === '') {\n didSomething = true\n parts.splice(i, 1)\n i--\n }\n }\n if (\n parts[0] === '.' &&\n parts.length === 2 &&\n (parts[1] === '.' || parts[1] === '')\n ) {\n didSomething = true\n parts.pop()\n }\n }\n\n // <pre>/<p>/../<rest> -> <pre>/<rest>\n let dd: number = 0\n while (-1 !== (dd = parts.indexOf('..', dd + 1))) {\n const p = parts[dd - 1]\n if (p && p !== '.' && p !== '..' && p !== '**') {\n didSomething = true\n const needDot = dd === 1 && parts[dd + 1] === '**'\n const splin = needDot ? ['.'] : []\n parts.splice(dd - 1, 2, ...splin)\n if (parts.length === 0) parts.push('')\n dd -= 2\n }\n }\n }\n } while (didSomething)\n\n return globParts\n }\n\n // second phase: multi-pattern dedupes\n // {<pre>/*/<rest>,<pre>/<p>/<rest>} -> <pre>/*/<rest>\n // {<pre>/<rest>,<pre>/<rest>} -> <pre>/<rest>\n // {<pre>/**/<rest>,<pre>/<rest>} -> <pre>/**/<rest>\n //\n // {<pre>/**/<rest>,<pre>/**/<p>/<rest>} -> <pre>/**/<rest>\n // ^-- not valid because ** doens't follow symlinks\n secondPhasePreProcess(globParts: string[][]): string[][] {\n for (let i = 0; i < globParts.length - 1; i++) {\n for (let j = i + 1; j < globParts.length; j++) {\n const matched = this.partsMatch(\n globParts[i],\n globParts[j],\n !this.preserveMultipleSlashes,\n )\n if (matched) {\n globParts[i] = []\n globParts[j] = matched\n break\n }\n }\n }\n return globParts.filter(gs => gs.length)\n }\n\n partsMatch(\n a: string[],\n b: string[],\n emptyGSMatch: boolean = false,\n ): false | string[] {\n let ai = 0\n let bi = 0\n let result: string[] = []\n let which: string = ''\n while (ai < a.length && bi < b.length) {\n if (a[ai] === b[bi]) {\n result.push(which === 'b' ? b[bi] : a[ai])\n ai++\n bi++\n } else if (emptyGSMatch && a[ai] === '**' && b[bi] === a[ai + 1]) {\n result.push(a[ai])\n ai++\n } else if (emptyGSMatch && b[bi] === '**' && a[ai] === b[bi + 1]) {\n result.push(b[bi])\n bi++\n } else if (\n a[ai] === '*' &&\n b[bi] &&\n (this.options.dot || !b[bi].startsWith('.')) &&\n b[bi] !== '**'\n ) {\n if (which === 'b') return false\n which = 'a'\n result.push(a[ai])\n ai++\n bi++\n } else if (\n b[bi] === '*' &&\n a[ai] &&\n (this.options.dot || !a[ai].startsWith('.')) &&\n a[ai] !== '**'\n ) {\n if (which === 'a') return false\n which = 'b'\n result.push(b[bi])\n ai++\n bi++\n } else {\n return false\n }\n }\n // if we fall out of the loop, it means they two are identical\n // as long as their lengths match\n return a.length === b.length && result\n }\n\n parseNegate() {\n if (this.nonegate) return\n\n const pattern = this.pattern\n let negate = false\n let negateOffset = 0\n\n for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {\n negate = !negate\n negateOffset++\n }\n\n if (negateOffset) this.pattern = pattern.slice(negateOffset)\n this.negate = negate\n }\n\n // set partial to true to test if, for example,\n // \"/a/b\" matches the start of \"/*/b/*/d\"\n // Partial means, if you run out of file before you run\n // out of pattern, then that's fine, as long as all\n // the parts match.\n matchOne(\n file: string[],\n pattern: ParseReturn[],\n partial: boolean = false,\n ) {\n const options = this.options\n\n // UNC paths like //?/X:/... can match X:/... and vice versa\n // Drive letters in absolute drive or unc paths are always compared\n // case-insensitively.\n if (this.isWindows) {\n const fileDrive =\n typeof file[0] === 'string' && /^[a-z]:$/i.test(file[0])\n const fileUNC =\n !fileDrive &&\n file[0] === '' &&\n file[1] === '' &&\n file[2] === '?' &&\n /^[a-z]:$/i.test(file[3])\n\n const patternDrive =\n typeof pattern[0] === 'string' && /^[a-z]:$/i.test(pattern[0])\n const patternUNC =\n !patternDrive &&\n pattern[0] === '' &&\n pattern[1] === '' &&\n pattern[2] === '?' &&\n typeof pattern[3] === 'string' &&\n /^[a-z]:$/i.test(pattern[3])\n\n const fdi =\n fileUNC ? 3\n : fileDrive ? 0\n : undefined\n const pdi =\n patternUNC ? 3\n : patternDrive ? 0\n : undefined\n if (typeof fdi === 'number' && typeof pdi === 'number') {\n const [fd, pd]: [string, string] = [\n file[fdi],\n pattern[pdi] as string,\n ]\n if (fd.toLowerCase() === pd.toLowerCase()) {\n pattern[pdi] = fd\n if (pdi > fdi) {\n pattern = pattern.slice(pdi)\n } else if (fdi > pdi) {\n file = file.slice(fdi)\n }\n }\n }\n }\n\n // resolve and reduce . and .. portions in the file as well.\n // don't need to do the second phase, because it's only one string[]\n const { optimizationLevel = 1 } = this.options\n if (optimizationLevel >= 2) {\n file = this.levelTwoFileOptimize(file)\n }\n\n this.debug('matchOne', this, { file, pattern })\n this.debug('matchOne', file.length, pattern.length)\n\n for (\n var fi = 0, pi = 0, fl = file.length, pl = pattern.length;\n fi < fl && pi < pl;\n fi++, pi++\n ) {\n this.debug('matchOne loop')\n var p = pattern[pi]\n var f = file[fi]\n\n this.debug(pattern, p, f)\n\n // should be impossible.\n // some invalid regexp stuff in the set.\n /* c8 ignore start */\n if (p === false) {\n return false\n }\n /* c8 ignore stop */\n\n if (p === GLOBSTAR) {\n this.debug('GLOBSTAR', [pattern, p, f])\n\n // \"**\"\n // a/**/b/**/c would match the following:\n // a/b/x/y/z/c\n // a/x/y/z/b/c\n // a/b/x/b/x/c\n // a/b/c\n // To do this, take the rest of the pattern after\n // the **, and see if it would match the file remainder.\n // If so, return success.\n // If not, the ** \"swallows\" a segment, and try again.\n // This is recursively awful.\n //\n // a/**/b/**/c matching a/b/x/y/z/c\n // - a matches a\n // - doublestar\n // - matchOne(b/x/y/z/c, b/**/c)\n // - b matches b\n // - doublestar\n // - matchOne(x/y/z/c, c) -> no\n // - matchOne(y/z/c, c) -> no\n // - matchOne(z/c, c) -> no\n // - matchOne(c, c) yes, hit\n var fr = fi\n var pr = pi + 1\n if (pr === pl) {\n this.debug('** at the end')\n // a ** at the end will just swallow the rest.\n // We have found a match.\n // however, it will not swallow /.x, unless\n // options.dot is set.\n // . and .. are *never* matched by **, for explosively\n // exponential reasons.\n for (; fi < fl; fi++) {\n if (\n file[fi] === '.' ||\n file[fi] === '..' ||\n (!options.dot && file[fi].charAt(0) === '.')\n )\n return false\n }\n return true\n }\n\n // ok, let's see if we can swallow whatever we can.\n while (fr < fl) {\n var swallowee = file[fr]\n\n this.debug('\\nglobstar while', file, fr, pattern, pr, swallowee)\n\n // XXX remove this slice. Just pass the start index.\n if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {\n this.debug('globstar found match!', fr, fl, swallowee)\n // found a match.\n return true\n } else {\n // can't swallow \".\" or \"..\" ever.\n // can only swallow \".foo\" when explicitly asked.\n if (\n swallowee === '.' ||\n swallowee === '..' ||\n (!options.dot && swallowee.charAt(0) === '.')\n ) {\n this.debug('dot detected!', file, fr, pattern, pr)\n break\n }\n\n // ** swallows a segment, and continue.\n this.debug('globstar swallow a segment, and continue')\n fr++\n }\n }\n\n // no match was found.\n // However, in partial mode, we can't say this is necessarily over.\n /* c8 ignore start */\n if (partial) {\n // ran out of file\n this.debug('\\n>>> no match, partial?', file, fr, pattern, pr)\n if (fr === fl) {\n return true\n }\n }\n /* c8 ignore stop */\n return false\n }\n\n // something other than **\n // non-magic patterns just have to match exactly\n // patterns with magic have been turned into regexps.\n let hit: boolean\n if (typeof p === 'string') {\n hit = f === p\n this.debug('string match', p, f, hit)\n } else {\n hit = p.test(f)\n this.debug('pattern match', p, f, hit)\n }\n\n if (!hit) return false\n }\n\n // Note: ending in / means that we'll get a final \"\"\n // at the end of the pattern. This can only match a\n // corresponding \"\" at the end of the file.\n // If the file ends in /, then it can only match a\n // a pattern that ends in /, unless the pattern just\n // doesn't have any more for it. But, a/b/ should *not*\n // match \"a/b/*\", even though \"\" matches against the\n // [^/]*? pattern, except in partial mode, where it might\n // simply not be reached yet.\n // However, a/b/ should still satisfy a/*\n\n // now either we fell off the end of the pattern, or we're done.\n if (fi === fl && pi === pl) {\n // ran out of pattern and filename at the same time.\n // an exact hit!\n return true\n } else if (fi === fl) {\n // ran out of file, but still had pattern left.\n // this is ok if we're doing the match as part of\n // a glob fs traversal.\n return partial\n } else if (pi === pl) {\n // ran out of pattern, still have file left.\n // this is only acceptable if we're on the very last\n // empty segment of a file with a trailing slash.\n // a/* should match a/b/\n return fi === fl - 1 && file[fi] === ''\n\n /* c8 ignore start */\n } else {\n // should be unreachable.\n throw new Error('wtf?')\n }\n /* c8 ignore stop */\n }\n\n braceExpand() {\n return braceExpand(this.pattern, this.options)\n }\n\n parse(pattern: string): ParseReturn {\n assertValidPattern(pattern)\n\n const options = this.options\n\n // shortcuts\n if (pattern === '**') return GLOBSTAR\n if (pattern === '') return ''\n\n // far and away, the most common glob pattern parts are\n // *, *.*, and *.<ext> Add a fast check method for those.\n let m: RegExpMatchArray | null\n let fastTest: null | ((f: string) => boolean) = null\n if ((m = pattern.match(starRE))) {\n fastTest = options.dot ? starTestDot : starTest\n } else if ((m = pattern.match(starDotExtRE))) {\n fastTest = (\n options.nocase ?\n options.dot ?\n starDotExtTestNocaseDot\n : starDotExtTestNocase\n : options.dot ? starDotExtTestDot\n : starDotExtTest)(m[1])\n } else if ((m = pattern.match(qmarksRE))) {\n fastTest = (\n options.nocase ?\n options.dot ?\n qmarksTestNocaseDot\n : qmarksTestNocase\n : options.dot ? qmarksTestDot\n : qmarksTest)(m)\n } else if ((m = pattern.match(starDotStarRE))) {\n fastTest = options.dot ? starDotStarTestDot : starDotStarTest\n } else if ((m = pattern.match(dotStarRE))) {\n fastTest = dotStarTest\n }\n\n const re = AST.fromGlob(pattern, this.options).toMMPattern()\n if (fastTest && typeof re === 'object') {\n // Avoids overriding in frozen environments\n Reflect.defineProperty(re, 'test', { value: fastTest })\n }\n return re\n }\n\n makeRe() {\n if (this.regexp || this.regexp === false) return this.regexp\n\n // at this point, this.set is a 2d array of partial\n // pattern strings, or \"**\".\n //\n // It's better to use .match(). This function shouldn't\n // be used, really, but it's pretty convenient sometimes,\n // when you just want to work with a regex.\n const set = this.set\n\n if (!set.length) {\n this.regexp = false\n return this.regexp\n }\n const options = this.options\n\n const twoStar =\n options.noglobstar ? star\n : options.dot ? twoStarDot\n : twoStarNoDot\n const flags = new Set(options.nocase ? ['i'] : [])\n\n // regexpify non-globstar patterns\n // if ** is only item, then we just do one twoStar\n // if ** is first, and there are more, prepend (\\/|twoStar\\/)? to next\n // if ** is last, append (\\/twoStar|) to previous\n // if ** is in the middle, append (\\/|\\/twoStar\\/) to previous\n // then filter out GLOBSTAR symbols\n let re = set\n .map(pattern => {\n const pp: (string | typeof GLOBSTAR)[] = pattern.map(p => {\n if (p instanceof RegExp) {\n for (const f of p.flags.split('')) flags.add(f)\n }\n return (\n typeof p === 'string' ? regExpEscape(p)\n : p === GLOBSTAR ? GLOBSTAR\n : p._src\n )\n }) as (string | typeof GLOBSTAR)[]\n pp.forEach((p, i) => {\n const next = pp[i + 1]\n const prev = pp[i - 1]\n if (p !== GLOBSTAR || prev === GLOBSTAR) {\n return\n }\n if (prev === undefined) {\n if (next !== undefined && next !== GLOBSTAR) {\n pp[i + 1] = '(?:\\\\/|' + twoStar + '\\\\/)?' + next\n } else {\n pp[i] = twoStar\n }\n } else if (next === undefined) {\n pp[i - 1] = prev + '(?:\\\\/|\\\\/' + twoStar + ')?'\n } else if (next !== GLOBSTAR) {\n pp[i - 1] = prev + '(?:\\\\/|\\\\/' + twoStar + '\\\\/)' + next\n pp[i + 1] = GLOBSTAR\n }\n })\n const filtered = pp.filter(p => p !== GLOBSTAR)\n\n // For partial matches, we need to make the pattern match\n // any prefix of the full path. We do this by generating\n // alternative patterns that match progressively longer prefixes.\n if (this.partial && filtered.length >= 1) {\n const prefixes: string[] = []\n for (let i = 1; i <= filtered.length; i++) {\n prefixes.push(filtered.slice(0, i).join('/'))\n }\n return '(?:' + prefixes.join('|') + ')'\n }\n\n return filtered.join('/')\n })\n .join('|')\n\n // need to wrap in parens if we had more than one thing with |,\n // otherwise only the first will be anchored to ^ and the last to $\n const [open, close] = set.length > 1 ? ['(?:', ')'] : ['', '']\n // must match entire pattern\n // ending in a * or ** will make it less strict.\n re = '^' + open + re + close + '$'\n\n // In partial mode, '/' should always match as it's a valid prefix for any pattern\n if (this.partial) {\n re = '^(?:\\\\/|' + open + re.slice(1, -1) + close + ')$'\n }\n\n // can match anything, as long as it's not this.\n if (this.negate) re = '^(?!' + re + ').+$'\n\n try {\n this.regexp = new RegExp(re, [...flags].join(''))\n /* c8 ignore start */\n } catch (ex) {\n // should be impossible\n this.regexp = false\n }\n /* c8 ignore stop */\n return this.regexp\n }\n\n slashSplit(p: string) {\n // if p starts with // on windows, we preserve that\n // so that UNC paths aren't broken. Otherwise, any number of\n // / characters are coalesced into one, unless\n // preserveMultipleSlashes is set to true.\n if (this.preserveMultipleSlashes) {\n return p.split('/')\n } else if (this.isWindows && /^\\/\\/[^\\/]+/.test(p)) {\n // add an extra '' for the one we lose\n return ['', ...p.split(/\\/+/)]\n } else {\n return p.split(/\\/+/)\n }\n }\n\n match(f: string, partial = this.partial) {\n this.debug('match', f, this.pattern)\n // short-circuit in the case of busted things.\n // comments, etc.\n if (this.comment) {\n return false\n }\n if (this.empty) {\n return f === ''\n }\n\n if (f === '/' && partial) {\n return true\n }\n\n const options = this.options\n\n // windows: need to use /, not \\\n if (this.isWindows) {\n f = f.split('\\\\').join('/')\n }\n\n // treat the test path as a set of pathparts.\n const ff = this.slashSplit(f)\n this.debug(this.pattern, 'split', ff)\n\n // just ONE of the pattern sets in this.set needs to match\n // in order for it to be valid. If negating, then just one\n // match means that we have failed.\n // Either way, return on the first hit.\n\n const set = this.set\n this.debug(this.pattern, 'set', set)\n\n // Find the basename of the path by looking for the last non-empty segment\n let filename: string = ff[ff.length - 1]\n if (!filename) {\n for (let i = ff.length - 2; !filename && i >= 0; i--) {\n filename = ff[i]\n }\n }\n\n for (let i = 0; i < set.length; i++) {\n const pattern = set[i]\n let file = ff\n if (options.matchBase && pattern.length === 1) {\n file = [filename]\n }\n const hit = this.matchOne(file, pattern, partial)\n if (hit) {\n if (options.flipNegate) {\n return true\n }\n return !this.negate\n }\n }\n\n // didn't get any hits. this is success if it's a negative\n // pattern, failure otherwise.\n if (options.flipNegate) {\n return false\n }\n return this.negate\n }\n\n static defaults(def: MinimatchOptions) {\n return minimatch.defaults(def).Minimatch\n }\n}\n/* c8 ignore start */\nexport { AST } from './ast.js'\nexport { escape } from './escape.js'\nexport { unescape } from './unescape.js'\n/* c8 ignore stop */\nminimatch.AST = AST\nminimatch.Minimatch = Minimatch\nminimatch.escape = escape\nminimatch.unescape = unescape\n","import { Minimatch, MinimatchOptions } from 'minimatch'\nimport { Minipass } from 'minipass'\nimport { fileURLToPath } from 'node:url'\nimport {\n FSOption,\n Path,\n PathScurry,\n PathScurryDarwin,\n PathScurryPosix,\n PathScurryWin32,\n} from 'path-scurry'\nimport { IgnoreLike } from './ignore.js'\nimport { Pattern } from './pattern.js'\nimport { GlobStream, GlobWalker } from './walker.js'\n\nexport type MatchSet = Minimatch['set']\nexport type GlobParts = Exclude<Minimatch['globParts'], undefined>\n\n// if no process global, just call it linux.\n// so we default to case-sensitive, / separators\nconst defaultPlatform: NodeJS.Platform =\n (\n typeof process === 'object' &&\n process &&\n typeof process.platform === 'string'\n ) ?\n process.platform\n : 'linux'\n\n/**\n * A `GlobOptions` object may be provided to any of the exported methods, and\n * must be provided to the `Glob` constructor.\n *\n * All options are optional, boolean, and false by default, unless otherwise\n * noted.\n *\n * All resolved options are added to the Glob object as properties.\n *\n * If you are running many `glob` operations, you can pass a Glob object as the\n * `options` argument to a subsequent operation to share the previously loaded\n * cache.\n */\nexport interface GlobOptions {\n /**\n * Set to `true` to always receive absolute paths for\n * matched files. Set to `false` to always return relative paths.\n *\n * When this option is not set, absolute paths are returned for patterns\n * that are absolute, and otherwise paths are returned that are relative\n * to the `cwd` setting.\n *\n * This does _not_ make an extra system call to get\n * the realpath, it only does string path resolution.\n *\n * Conflicts with {@link withFileTypes}\n */\n absolute?: boolean\n\n /**\n * Set to false to enable {@link windowsPathsNoEscape}\n *\n * @deprecated\n */\n allowWindowsEscape?: boolean\n\n /**\n * The current working directory in which to search. Defaults to\n * `process.cwd()`.\n *\n * May be eiher a string path or a `file://` URL object or string.\n */\n cwd?: string | URL\n\n /**\n * Include `.dot` files in normal matches and `globstar`\n * matches. Note that an explicit dot in a portion of the pattern\n * will always match dot files.\n */\n dot?: boolean\n\n /**\n * Prepend all relative path strings with `./` (or `.\\` on Windows).\n *\n * Without this option, returned relative paths are \"bare\", so instead of\n * returning `'./foo/bar'`, they are returned as `'foo/bar'`.\n *\n * Relative patterns starting with `'../'` are not prepended with `./`, even\n * if this option is set.\n */\n dotRelative?: boolean\n\n /**\n * Follow symlinked directories when expanding `**`\n * patterns. This can result in a lot of duplicate references in\n * the presence of cyclic links, and make performance quite bad.\n *\n * By default, a `**` in a pattern will follow 1 symbolic link if\n * it is not the first item in the pattern, or none if it is the\n * first item in the pattern, following the same behavior as Bash.\n */\n follow?: boolean\n\n /**\n * string or string[], or an object with `ignored` and `childrenIgnored`\n * methods.\n *\n * If a string or string[] is provided, then this is treated as a glob\n * pattern or array of glob patterns to exclude from matches. To ignore all\n * children within a directory, as well as the entry itself, append `'/**'`\n * to the ignore pattern.\n *\n * **Note** `ignore` patterns are _always_ in `dot:true` mode, regardless of\n * any other settings.\n *\n * If an object is provided that has `ignored(path)` and/or\n * `childrenIgnored(path)` methods, then these methods will be called to\n * determine whether any Path is a match or if its children should be\n * traversed, respectively.\n */\n ignore?: string | string[] | IgnoreLike\n\n /**\n * Treat brace expansion like `{a,b}` as a \"magic\" pattern. Has no\n * effect if {@link nobrace} is set.\n *\n * Only has effect on the {@link hasMagic} function.\n */\n magicalBraces?: boolean\n\n /**\n * Add a `/` character to directory matches. Note that this requires\n * additional stat calls in some cases.\n */\n mark?: boolean\n\n /**\n * Perform a basename-only match if the pattern does not contain any slash\n * characters. That is, `*.js` would be treated as equivalent to\n * `**\\/*.js`, matching all js files in all directories.\n */\n matchBase?: boolean\n\n /**\n * Limit the directory traversal to a given depth below the cwd.\n * Note that this does NOT prevent traversal to sibling folders,\n * root patterns, and so on. It only limits the maximum folder depth\n * that the walk will descend, relative to the cwd.\n */\n maxDepth?: number\n\n /**\n * Do not expand `{a,b}` and `{1..3}` brace sets.\n */\n nobrace?: boolean\n\n /**\n * Perform a case-insensitive match. This defaults to `true` on macOS and\n * Windows systems, and `false` on all others.\n *\n * **Note** `nocase` should only be explicitly set when it is\n * known that the filesystem's case sensitivity differs from the\n * platform default. If set `true` on case-sensitive file\n * systems, or `false` on case-insensitive file systems, then the\n * walk may return more or less results than expected.\n */\n nocase?: boolean\n\n /**\n * Do not match directories, only files. (Note: to match\n * _only_ directories, put a `/` at the end of the pattern.)\n */\n nodir?: boolean\n\n /**\n * Do not match \"extglob\" patterns such as `+(a|b)`.\n */\n noext?: boolean\n\n /**\n * Do not match `**` against multiple filenames. (Ie, treat it as a normal\n * `*` instead.)\n *\n * Conflicts with {@link matchBase}\n */\n noglobstar?: boolean\n\n /**\n * Defaults to value of `process.platform` if available, or `'linux'` if\n * not. Setting `platform:'win32'` on non-Windows systems may cause strange\n * behavior.\n */\n platform?: NodeJS.Platform\n\n /**\n * Set to true to call `fs.realpath` on all of the\n * results. In the case of an entry that cannot be resolved, the\n * entry is omitted. This incurs a slight performance penalty, of\n * course, because of the added system calls.\n */\n realpath?: boolean\n\n /**\n *\n * A string path resolved against the `cwd` option, which\n * is used as the starting point for absolute patterns that start\n * with `/`, (but not drive letters or UNC paths on Windows).\n *\n * Note that this _doesn't_ necessarily limit the walk to the\n * `root` directory, and doesn't affect the cwd starting point for\n * non-absolute patterns. A pattern containing `..` will still be\n * able to traverse out of the root directory, if it is not an\n * actual root directory on the filesystem, and any non-absolute\n * patterns will be matched in the `cwd`. For example, the\n * pattern `/../*` with `{root:'/some/path'}` will return all\n * files in `/some`, not all files in `/some/path`. The pattern\n * `*` with `{root:'/some/path'}` will return all the entries in\n * the cwd, not the entries in `/some/path`.\n *\n * To start absolute and non-absolute patterns in the same\n * path, you can use `{root:''}`. However, be aware that on\n * Windows systems, a pattern like `x:/*` or `//host/share/*` will\n * _always_ start in the `x:/` or `//host/share` directory,\n * regardless of the `root` setting.\n */\n root?: string\n\n /**\n * A [PathScurry](http://npm.im/path-scurry) object used\n * to traverse the file system. If the `nocase` option is set\n * explicitly, then any provided `scurry` object must match this\n * setting.\n */\n scurry?: PathScurry\n\n /**\n * Call `lstat()` on all entries, whether required or not to determine\n * if it's a valid match. When used with {@link withFileTypes}, this means\n * that matches will include data such as modified time, permissions, and\n * so on. Note that this will incur a performance cost due to the added\n * system calls.\n */\n stat?: boolean\n\n /**\n * An AbortSignal which will cancel the Glob walk when\n * triggered.\n */\n signal?: AbortSignal\n\n /**\n * Use `\\\\` as a path separator _only_, and\n * _never_ as an escape character. If set, all `\\\\` characters are\n * replaced with `/` in the pattern.\n *\n * Note that this makes it **impossible** to match against paths\n * containing literal glob pattern characters, but allows matching\n * with patterns constructed using `path.join()` and\n * `path.resolve()` on Windows platforms, mimicking the (buggy!)\n * behavior of Glob v7 and before on Windows. Please use with\n * caution, and be mindful of [the caveat below about Windows\n * paths](#windows). (For legacy reasons, this is also set if\n * `allowWindowsEscape` is set to the exact value `false`.)\n */\n windowsPathsNoEscape?: boolean\n\n /**\n * Return [PathScurry](http://npm.im/path-scurry)\n * `Path` objects instead of strings. These are similar to a\n * NodeJS `Dirent` object, but with additional methods and\n * properties.\n *\n * Conflicts with {@link absolute}\n */\n withFileTypes?: boolean\n\n /**\n * An fs implementation to override some or all of the defaults. See\n * http://npm.im/path-scurry for details about what can be overridden.\n */\n fs?: FSOption\n\n /**\n * Just passed along to Minimatch. Note that this makes all pattern\n * matching operations slower and *extremely* noisy.\n */\n debug?: boolean\n\n /**\n * Return `/` delimited paths, even on Windows.\n *\n * On posix systems, this has no effect. But, on Windows, it means that\n * paths will be `/` delimited, and absolute paths will be their full\n * resolved UNC forms, eg instead of `'C:\\\\foo\\\\bar'`, it would return\n * `'//?/C:/foo/bar'`\n */\n posix?: boolean\n\n /**\n * Do not match any children of any matches. For example, the pattern\n * `**\\/foo` would match `a/foo`, but not `a/foo/b/foo` in this mode.\n *\n * This is especially useful for cases like \"find all `node_modules`\n * folders, but not the ones in `node_modules`\".\n *\n * In order to support this, the `Ignore` implementation must support an\n * `add(pattern: string)` method. If using the default `Ignore` class, then\n * this is fine, but if this is set to `false`, and a custom `Ignore` is\n * provided that does not have an `add()` method, then it will throw an\n * error.\n *\n * **Caveat** It *only* ignores matches that would be a descendant of a\n * previous match, and only if that descendant is matched *after* the\n * ancestor is encountered. Since the file system walk happens in\n * indeterminate order, it's possible that a match will already be added\n * before its ancestor, if multiple or braced patterns are used.\n *\n * For example:\n *\n * ```ts\n * const results = await glob([\n * // likely to match first, since it's just a stat\n * 'a/b/c/d/e/f',\n *\n * // this pattern is more complicated! It must to various readdir()\n * // calls and test the results against a regular expression, and that\n * // is certainly going to take a little bit longer.\n * //\n * // So, later on, it encounters a match at 'a/b/c/d/e', but it's too\n * // late to ignore a/b/c/d/e/f, because it's already been emitted.\n * 'a/[bdf]/?/[a-z]/*',\n * ], { includeChildMatches: false })\n * ```\n *\n * It's best to only set this to `false` if you can be reasonably sure that\n * no components of the pattern will potentially match one another's file\n * system descendants, or if the occasional included child entry will not\n * cause problems.\n *\n * @default true\n */\n includeChildMatches?: boolean\n\n /**\n * max number of `{...}` patterns to expand. Default `1_000`.\n *\n * Note: this is much less than minimatch's default of `100_000`,\n * because Glob has higher memory requirements due to walking\n * the file system tree.\n */\n braceExpandMax?: number\n}\n\nexport type GlobOptionsWithFileTypesTrue = GlobOptions & {\n withFileTypes: true\n // string options not relevant if returning Path objects.\n absolute?: undefined\n mark?: undefined\n posix?: undefined\n}\n\nexport type GlobOptionsWithFileTypesFalse = GlobOptions & {\n withFileTypes?: false\n}\n\nexport type GlobOptionsWithFileTypesUnset = GlobOptions & {\n withFileTypes?: undefined\n}\n\nexport type Result<Opts> =\n Opts extends GlobOptionsWithFileTypesTrue ? Path\n : Opts extends GlobOptionsWithFileTypesFalse ? string\n : Opts extends GlobOptionsWithFileTypesUnset ? string\n : string | Path\nexport type Results<Opts> = Result<Opts>[]\n\nexport type FileTypes<Opts> =\n Opts extends GlobOptionsWithFileTypesTrue ? true\n : Opts extends GlobOptionsWithFileTypesFalse ? false\n : Opts extends GlobOptionsWithFileTypesUnset ? false\n : boolean\n\n/**\n * An object that can perform glob pattern traversals.\n */\nexport class Glob<Opts extends GlobOptions> implements GlobOptions {\n absolute?: boolean\n cwd: string\n root?: string\n dot: boolean\n dotRelative: boolean\n follow: boolean\n ignore?: string | string[] | IgnoreLike\n magicalBraces: boolean\n mark?: boolean\n matchBase: boolean\n maxDepth: number\n nobrace: boolean\n nocase: boolean\n nodir: boolean\n noext: boolean\n noglobstar: boolean\n pattern: string[]\n platform: NodeJS.Platform\n realpath: boolean\n scurry: PathScurry\n stat: boolean\n signal?: AbortSignal\n windowsPathsNoEscape: boolean\n withFileTypes: FileTypes<Opts>\n includeChildMatches: boolean\n\n /**\n * The options provided to the constructor.\n */\n opts: Opts\n\n /**\n * An array of parsed immutable {@link Pattern} objects.\n */\n patterns: Pattern[]\n\n /**\n * All options are stored as properties on the `Glob` object.\n *\n * See {@link GlobOptions} for full options descriptions.\n *\n * Note that a previous `Glob` object can be passed as the\n * `GlobOptions` to another `Glob` instantiation to re-use settings\n * and caches with a new pattern.\n *\n * Traversal functions can be called multiple times to run the walk\n * again.\n */\n constructor(pattern: string | string[], opts: Opts) {\n /* c8 ignore start */\n if (!opts) throw new TypeError('glob options required')\n /* c8 ignore stop */\n this.withFileTypes = !!opts.withFileTypes as FileTypes<Opts>\n this.signal = opts.signal\n this.follow = !!opts.follow\n this.dot = !!opts.dot\n this.dotRelative = !!opts.dotRelative\n this.nodir = !!opts.nodir\n this.mark = !!opts.mark\n if (!opts.cwd) {\n this.cwd = ''\n } else if (opts.cwd instanceof URL || opts.cwd.startsWith('file://')) {\n opts.cwd = fileURLToPath(opts.cwd)\n }\n this.cwd = opts.cwd || ''\n this.root = opts.root\n this.magicalBraces = !!opts.magicalBraces\n this.nobrace = !!opts.nobrace\n this.noext = !!opts.noext\n this.realpath = !!opts.realpath\n this.absolute = opts.absolute\n this.includeChildMatches = opts.includeChildMatches !== false\n\n this.noglobstar = !!opts.noglobstar\n this.matchBase = !!opts.matchBase\n this.maxDepth =\n typeof opts.maxDepth === 'number' ? opts.maxDepth : Infinity\n this.stat = !!opts.stat\n this.ignore = opts.ignore\n\n if (this.withFileTypes && this.absolute !== undefined) {\n throw new Error('cannot set absolute and withFileTypes:true')\n }\n\n if (typeof pattern === 'string') {\n pattern = [pattern]\n }\n\n this.windowsPathsNoEscape =\n !!opts.windowsPathsNoEscape ||\n (opts as { allowWindowsEscape?: boolean }).allowWindowsEscape ===\n false\n\n if (this.windowsPathsNoEscape) {\n pattern = pattern.map(p => p.replace(/\\\\/g, '/'))\n }\n\n if (this.matchBase) {\n if (opts.noglobstar) {\n throw new TypeError('base matching requires globstar')\n }\n pattern = pattern.map(p => (p.includes('/') ? p : `./**/${p}`))\n }\n\n this.pattern = pattern\n\n this.platform = opts.platform || defaultPlatform\n this.opts = { ...opts, platform: this.platform }\n if (opts.scurry) {\n this.scurry = opts.scurry\n if (\n opts.nocase !== undefined &&\n opts.nocase !== opts.scurry.nocase\n ) {\n throw new Error('nocase option contradicts provided scurry option')\n }\n } else {\n const Scurry =\n opts.platform === 'win32' ? PathScurryWin32\n : opts.platform === 'darwin' ? PathScurryDarwin\n : opts.platform ? PathScurryPosix\n : PathScurry\n this.scurry = new Scurry(this.cwd, {\n nocase: opts.nocase,\n fs: opts.fs,\n })\n }\n this.nocase = this.scurry.nocase\n\n // If you do nocase:true on a case-sensitive file system, then\n // we need to use regexps instead of strings for non-magic\n // path portions, because statting `aBc` won't return results\n // for the file `AbC` for example.\n const nocaseMagicOnly =\n this.platform === 'darwin' || this.platform === 'win32'\n\n const mmo: MinimatchOptions = {\n braceExpandMax: 10_000,\n ...opts,\n dot: this.dot,\n matchBase: this.matchBase,\n nobrace: this.nobrace,\n // default nocase based on platform\n nocase: this.nocase,\n nocaseMagicOnly,\n nocomment: true,\n noext: this.noext,\n nonegate: true,\n optimizationLevel: 2,\n platform: this.platform,\n windowsPathsNoEscape: this.windowsPathsNoEscape,\n debug: !!this.opts.debug,\n }\n\n const mms = this.pattern.map(p => new Minimatch(p, mmo))\n const [matchSet, globParts] = mms.reduce(\n (set: [MatchSet, GlobParts], m) => {\n set[0].push(...m.set)\n set[1].push(...m.globParts)\n return set\n },\n [[], []],\n )\n this.patterns = matchSet.map((set, i) => {\n const g = globParts[i]\n /* c8 ignore start */\n if (!g) throw new Error('invalid pattern object')\n /* c8 ignore stop */\n return new Pattern(set, g, 0, this.platform)\n })\n }\n\n /**\n * Returns a Promise that resolves to the results array.\n */\n async walk(): Promise<Results<Opts>>\n async walk(): Promise<(string | Path)[]> {\n // Walkers always return array of Path objects, so we just have to\n // coerce them into the right shape. It will have already called\n // realpath() if the option was set to do so, so we know that's cached.\n // start out knowing the cwd, at least\n return [\n ...(await new GlobWalker(this.patterns, this.scurry.cwd, {\n ...this.opts,\n maxDepth:\n this.maxDepth !== Infinity ?\n this.maxDepth + this.scurry.cwd.depth()\n : Infinity,\n platform: this.platform,\n nocase: this.nocase,\n includeChildMatches: this.includeChildMatches,\n }).walk()),\n ]\n }\n\n /**\n * synchronous {@link Glob.walk}\n */\n walkSync(): Results<Opts>\n walkSync(): (string | Path)[] {\n return [\n ...new GlobWalker(this.patterns, this.scurry.cwd, {\n ...this.opts,\n maxDepth:\n this.maxDepth !== Infinity ?\n this.maxDepth + this.scurry.cwd.depth()\n : Infinity,\n platform: this.platform,\n nocase: this.nocase,\n includeChildMatches: this.includeChildMatches,\n }).walkSync(),\n ]\n }\n\n /**\n * Stream results asynchronously.\n */\n stream(): Minipass<Result<Opts>, Result<Opts>>\n stream(): Minipass<string | Path, string | Path> {\n return new GlobStream(this.patterns, this.scurry.cwd, {\n ...this.opts,\n maxDepth:\n this.maxDepth !== Infinity ?\n this.maxDepth + this.scurry.cwd.depth()\n : Infinity,\n platform: this.platform,\n nocase: this.nocase,\n includeChildMatches: this.includeChildMatches,\n }).stream()\n }\n\n /**\n * Stream results synchronously.\n */\n streamSync(): Minipass<Result<Opts>, Result<Opts>>\n streamSync(): Minipass<string | Path, string | Path> {\n return new GlobStream(this.patterns, this.scurry.cwd, {\n ...this.opts,\n maxDepth:\n this.maxDepth !== Infinity ?\n this.maxDepth + this.scurry.cwd.depth()\n : Infinity,\n platform: this.platform,\n nocase: this.nocase,\n includeChildMatches: this.includeChildMatches,\n }).streamSync()\n }\n\n /**\n * Default sync iteration function. Returns a Generator that\n * iterates over the results.\n */\n iterateSync(): Generator<Result<Opts>, void, void> {\n return this.streamSync()[Symbol.iterator]()\n }\n [Symbol.iterator]() {\n return this.iterateSync()\n }\n\n /**\n * Default async iteration function. Returns an AsyncGenerator that\n * iterates over the results.\n */\n iterate(): AsyncGenerator<Result<Opts>, void, void> {\n return this.stream()[Symbol.asyncIterator]()\n }\n [Symbol.asyncIterator]() {\n return this.iterate()\n }\n}\n","/**\n * @module LRUCache\n */\n\n// module-private names and types\n// this provides the default Perf object source.\n// it can be passed in via configuration to override it\n// for a single LRU object.\nexport type Perf = { now: () => number }\nconst defaultPerf: Perf =\n (\n typeof performance === 'object' &&\n performance &&\n typeof performance.now === 'function'\n ) ?\n performance\n : Date\n\nconst warned = new Set<string>()\n\n// either a function or a class\ntype ForC = ((...a: any[]) => any) | { new (...a: any[]): any }\n\n/* c8 ignore start */\nconst PROCESS = (\n typeof process === 'object' && !!process ?\n process\n : {}) as { [k: string]: any }\n/* c8 ignore start */\n\nconst emitWarning = (\n msg: string,\n type: string,\n code: string,\n fn: ForC,\n) => {\n typeof PROCESS.emitWarning === 'function' ?\n PROCESS.emitWarning(msg, type, code, fn)\n : console.error(`[${code}] ${type}: ${msg}`)\n}\n\nlet AC = globalThis.AbortController\nlet AS = globalThis.AbortSignal\n\n/* c8 ignore start */\nif (typeof AC === 'undefined') {\n //@ts-ignore\n AS = class AbortSignal {\n onabort?: (...a: any[]) => any\n _onabort: ((...a: any[]) => any)[] = []\n reason?: any\n aborted: boolean = false\n addEventListener(_: string, fn: (...a: any[]) => any) {\n this._onabort.push(fn)\n }\n }\n //@ts-ignore\n AC = class AbortController {\n constructor() {\n warnACPolyfill()\n }\n signal = new AS()\n abort(reason: any) {\n if (this.signal.aborted) return\n //@ts-ignore\n this.signal.reason = reason\n //@ts-ignore\n this.signal.aborted = true\n //@ts-ignore\n for (const fn of this.signal._onabort) {\n fn(reason)\n }\n this.signal.onabort?.(reason)\n }\n }\n let printACPolyfillWarning =\n PROCESS.env?.LRU_CACHE_IGNORE_AC_WARNING !== '1'\n const warnACPolyfill = () => {\n if (!printACPolyfillWarning) return\n printACPolyfillWarning = false\n emitWarning(\n 'AbortController is not defined. If using lru-cache in ' +\n 'node 14, load an AbortController polyfill from the ' +\n '`node-abort-controller` package. A minimal polyfill is ' +\n 'provided for use by LRUCache.fetch(), but it should not be ' +\n 'relied upon in other contexts (eg, passing it to other APIs that ' +\n 'use AbortController/AbortSignal might have undesirable effects). ' +\n 'You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.',\n 'NO_ABORT_CONTROLLER',\n 'ENOTSUP',\n warnACPolyfill,\n )\n }\n}\n/* c8 ignore stop */\n\nconst shouldWarn = (code: string) => !warned.has(code)\n\nconst TYPE = Symbol('type')\nexport type PosInt = number & { [TYPE]: 'Positive Integer' }\nexport type Index = number & { [TYPE]: 'LRUCache Index' }\n\nconst isPosInt = (n: any): n is PosInt =>\n n && n === Math.floor(n) && n > 0 && isFinite(n)\n\nexport type UintArray = Uint8Array | Uint16Array | Uint32Array\nexport type NumberArray = UintArray | number[]\n\n/* c8 ignore start */\n// This is a little bit ridiculous, tbh.\n// The maximum array length is 2^32-1 or thereabouts on most JS impls.\n// And well before that point, you're caching the entire world, I mean,\n// that's ~32GB of just integers for the next/prev links, plus whatever\n// else to hold that many keys and values. Just filling the memory with\n// zeroes at init time is brutal when you get that big.\n// But why not be complete?\n// Maybe in the future, these limits will have expanded.\nconst getUintArray = (max: number) =>\n !isPosInt(max) ? null\n : max <= Math.pow(2, 8) ? Uint8Array\n : max <= Math.pow(2, 16) ? Uint16Array\n : max <= Math.pow(2, 32) ? Uint32Array\n : max <= Number.MAX_SAFE_INTEGER ? ZeroArray\n : null\n/* c8 ignore stop */\n\nclass ZeroArray extends Array<number> {\n constructor(size: number) {\n super(size)\n this.fill(0)\n }\n}\nexport type { ZeroArray }\nexport type { Stack }\n\nexport type StackLike = Stack | Index[]\nclass Stack {\n heap: NumberArray\n length: number\n // private constructor\n static #constructing: boolean = false\n static create(max: number): StackLike {\n const HeapCls = getUintArray(max)\n if (!HeapCls) return []\n Stack.#constructing = true\n const s = new Stack(max, HeapCls)\n Stack.#constructing = false\n return s\n }\n constructor(max: number, HeapCls: { new (n: number): NumberArray }) {\n /* c8 ignore start */\n if (!Stack.#constructing) {\n throw new TypeError('instantiate Stack using Stack.create(n)')\n }\n /* c8 ignore stop */\n this.heap = new HeapCls(max)\n this.length = 0\n }\n push(n: Index) {\n this.heap[this.length++] = n\n }\n pop(): Index {\n return this.heap[--this.length] as Index\n }\n}\n\n/**\n * Promise representing an in-progress {@link LRUCache#fetch} call\n */\nexport type BackgroundFetch<V> = Promise<V | undefined> & {\n __returned: BackgroundFetch<V> | undefined\n __abortController: AbortController\n __staleWhileFetching: V | undefined\n}\n\nexport type DisposeTask<K, V> = [\n value: V,\n key: K,\n reason: LRUCache.DisposeReason,\n]\n\nexport namespace LRUCache {\n /**\n * An integer greater than 0, reflecting the calculated size of items\n */\n export type Size = number\n\n /**\n * Integer greater than 0, representing some number of milliseconds, or the\n * time at which a TTL started counting from.\n */\n export type Milliseconds = number\n\n /**\n * An integer greater than 0, reflecting a number of items\n */\n export type Count = number\n\n /**\n * The reason why an item was removed from the cache, passed\n * to the {@link Disposer} methods.\n *\n * - `evict`: The item was evicted because it is the least recently used,\n * and the cache is full.\n * - `set`: A new value was set, overwriting the old value being disposed.\n * - `delete`: The item was explicitly deleted, either by calling\n * {@link LRUCache#delete}, {@link LRUCache#clear}, or\n * {@link LRUCache#set} with an undefined value.\n * - `expire`: The item was removed due to exceeding its TTL.\n * - `fetch`: A {@link OptionsBase#fetchMethod} operation returned\n * `undefined` or was aborted, causing the item to be deleted.\n */\n export type DisposeReason =\n | 'evict'\n | 'set'\n | 'delete'\n | 'expire'\n | 'fetch'\n /**\n * A method called upon item removal, passed as the\n * {@link OptionsBase.dispose} and/or\n * {@link OptionsBase.disposeAfter} options.\n */\n export type Disposer<K, V> = (\n value: V,\n key: K,\n reason: DisposeReason,\n ) => void\n\n /**\n * The reason why an item was added to the cache, passed\n * to the {@link Inserter} methods.\n *\n * - `add`: the item was not found in the cache, and was added\n * - `update`: the item was in the cache, with the same value provided\n * - `replace`: the item was in the cache, and replaced\n */\n export type InsertReason = 'add' | 'update' | 'replace'\n\n /**\n * A method called upon item insertion, passed as the\n * {@link OptionsBase.insert}\n */\n export type Inserter<K, V> = (\n value: V,\n key: K,\n reason: InsertReason,\n ) => void\n\n /**\n * A function that returns the effective calculated size\n * of an entry in the cache.\n */\n export type SizeCalculator<K, V> = (value: V, key: K) => Size\n\n /**\n * Options provided to the\n * {@link OptionsBase.fetchMethod} function.\n */\n export interface FetcherOptions<K, V, FC = unknown> {\n signal: AbortSignal\n options: FetcherFetchOptions<K, V, FC>\n /**\n * Object provided in the {@link FetchOptions.context} option to\n * {@link LRUCache#fetch}\n */\n context: FC\n }\n\n /**\n * Occasionally, it may be useful to track the internal behavior of the\n * cache, particularly for logging, debugging, or for behavior within the\n * `fetchMethod`. To do this, you can pass a `status` object to the\n * {@link LRUCache#fetch}, {@link LRUCache#get}, {@link LRUCache#set},\n * {@link LRUCache#memo}, and {@link LRUCache#has} methods.\n *\n * The `status` option should be a plain JavaScript object. The following\n * fields will be set on it appropriately, depending on the situation.\n */\n export interface Status<V> {\n /**\n * The status of a set() operation.\n *\n * - add: the item was not found in the cache, and was added\n * - update: the item was in the cache, with the same value provided\n * - replace: the item was in the cache, and replaced\n * - miss: the item was not added to the cache for some reason\n */\n set?: 'add' | 'update' | 'replace' | 'miss'\n\n /**\n * the ttl stored for the item, or undefined if ttls are not used.\n */\n ttl?: Milliseconds\n\n /**\n * the start time for the item, or undefined if ttls are not used.\n */\n start?: Milliseconds\n\n /**\n * The timestamp used for TTL calculation\n */\n now?: Milliseconds\n\n /**\n * the remaining ttl for the item, or undefined if ttls are not used.\n */\n remainingTTL?: Milliseconds\n\n /**\n * The calculated size for the item, if sizes are used.\n */\n entrySize?: Size\n\n /**\n * The total calculated size of the cache, if sizes are used.\n */\n totalCalculatedSize?: Size\n\n /**\n * A flag indicating that the item was not stored, due to exceeding the\n * {@link OptionsBase.maxEntrySize}\n */\n maxEntrySizeExceeded?: true\n\n /**\n * The old value, specified in the case of `set:'update'` or\n * `set:'replace'`\n */\n oldValue?: V\n\n /**\n * The results of a {@link LRUCache#has} operation\n *\n * - hit: the item was found in the cache\n * - stale: the item was found in the cache, but is stale\n * - miss: the item was not found in the cache\n */\n has?: 'hit' | 'stale' | 'miss'\n\n /**\n * The status of a {@link LRUCache#fetch} operation.\n * Note that this can change as the underlying fetch() moves through\n * various states.\n *\n * - inflight: there is another fetch() for this key which is in process\n * - get: there is no {@link OptionsBase.fetchMethod}, so\n * {@link LRUCache#get} was called.\n * - miss: the item is not in cache, and will be fetched.\n * - hit: the item is in the cache, and was resolved immediately.\n * - stale: the item is in the cache, but stale.\n * - refresh: the item is in the cache, and not stale, but\n * {@link FetchOptions.forceRefresh} was specified.\n */\n fetch?: 'get' | 'inflight' | 'miss' | 'hit' | 'stale' | 'refresh'\n\n /**\n * The {@link OptionsBase.fetchMethod} was called\n */\n fetchDispatched?: true\n\n /**\n * The cached value was updated after a successful call to\n * {@link OptionsBase.fetchMethod}\n */\n fetchUpdated?: true\n\n /**\n * The reason for a fetch() rejection. Either the error raised by the\n * {@link OptionsBase.fetchMethod}, or the reason for an\n * AbortSignal.\n */\n fetchError?: Error\n\n /**\n * The fetch received an abort signal\n */\n fetchAborted?: true\n\n /**\n * The abort signal received was ignored, and the fetch was allowed to\n * continue.\n */\n fetchAbortIgnored?: true\n\n /**\n * The fetchMethod promise resolved successfully\n */\n fetchResolved?: true\n\n /**\n * The fetchMethod promise was rejected\n */\n fetchRejected?: true\n\n /**\n * The status of a {@link LRUCache#get} operation.\n *\n * - fetching: The item is currently being fetched. If a previous value\n * is present and allowed, that will be returned.\n * - stale: The item is in the cache, and is stale.\n * - hit: the item is in the cache\n * - miss: the item is not in the cache\n */\n get?: 'stale' | 'hit' | 'miss'\n\n /**\n * A fetch or get operation returned a stale value.\n */\n returnedStale?: true\n }\n\n /**\n * options which override the options set in the LRUCache constructor\n * when calling {@link LRUCache#fetch}.\n *\n * This is the union of {@link GetOptions} and {@link SetOptions}, plus\n * {@link OptionsBase.noDeleteOnFetchRejection},\n * {@link OptionsBase.allowStaleOnFetchRejection},\n * {@link FetchOptions.forceRefresh}, and\n * {@link FetcherOptions.context}\n *\n * Any of these may be modified in the {@link OptionsBase.fetchMethod}\n * function, but the {@link GetOptions} fields will of course have no\n * effect, as the {@link LRUCache#get} call already happened by the time\n * the fetchMethod is called.\n */\n export interface FetcherFetchOptions<K, V, FC = unknown>\n extends Pick<\n OptionsBase<K, V, FC>,\n | 'allowStale'\n | 'updateAgeOnGet'\n | 'noDeleteOnStaleGet'\n | 'sizeCalculation'\n | 'ttl'\n | 'noDisposeOnSet'\n | 'noUpdateTTL'\n | 'noDeleteOnFetchRejection'\n | 'allowStaleOnFetchRejection'\n | 'ignoreFetchAbort'\n | 'allowStaleOnFetchAbort'\n > {\n status?: Status<V>\n size?: Size\n }\n\n /**\n * Options that may be passed to the {@link LRUCache#fetch} method.\n */\n export interface FetchOptions<K, V, FC>\n extends FetcherFetchOptions<K, V, FC> {\n /**\n * Set to true to force a re-load of the existing data, even if it\n * is not yet stale.\n */\n forceRefresh?: boolean\n /**\n * Context provided to the {@link OptionsBase.fetchMethod} as\n * the {@link FetcherOptions.context} param.\n *\n * If the FC type is specified as unknown (the default),\n * undefined or void, then this is optional. Otherwise, it will\n * be required.\n */\n context?: FC\n signal?: AbortSignal\n status?: Status<V>\n }\n /**\n * Options provided to {@link LRUCache#fetch} when the FC type is something\n * other than `unknown`, `undefined`, or `void`\n */\n export interface FetchOptionsWithContext<K, V, FC>\n extends FetchOptions<K, V, FC> {\n context: FC\n }\n /**\n * Options provided to {@link LRUCache#fetch} when the FC type is\n * `undefined` or `void`\n */\n export interface FetchOptionsNoContext<K, V>\n extends FetchOptions<K, V, undefined> {\n context?: undefined\n }\n\n export interface MemoOptions<K, V, FC = unknown>\n extends Pick<\n OptionsBase<K, V, FC>,\n | 'allowStale'\n | 'updateAgeOnGet'\n | 'noDeleteOnStaleGet'\n | 'sizeCalculation'\n | 'ttl'\n | 'noDisposeOnSet'\n | 'noUpdateTTL'\n | 'noDeleteOnFetchRejection'\n | 'allowStaleOnFetchRejection'\n | 'ignoreFetchAbort'\n | 'allowStaleOnFetchAbort'\n > {\n /**\n * Set to true to force a re-load of the existing data, even if it\n * is not yet stale.\n */\n forceRefresh?: boolean\n /**\n * Context provided to the {@link OptionsBase.memoMethod} as\n * the {@link MemoizerOptions.context} param.\n *\n * If the FC type is specified as unknown (the default),\n * undefined or void, then this is optional. Otherwise, it will\n * be required.\n */\n context?: FC\n status?: Status<V>\n }\n /**\n * Options provided to {@link LRUCache#memo} when the FC type is something\n * other than `unknown`, `undefined`, or `void`\n */\n export interface MemoOptionsWithContext<K, V, FC>\n extends MemoOptions<K, V, FC> {\n context: FC\n }\n /**\n * Options provided to {@link LRUCache#memo} when the FC type is\n * `undefined` or `void`\n */\n export interface MemoOptionsNoContext<K, V>\n extends MemoOptions<K, V, undefined> {\n context?: undefined\n }\n\n /**\n * Options provided to the\n * {@link OptionsBase.memoMethod} function.\n */\n export interface MemoizerOptions<K, V, FC = unknown> {\n options: MemoizerMemoOptions<K, V, FC>\n /**\n * Object provided in the {@link MemoOptions.context} option to\n * {@link LRUCache#memo}\n */\n context: FC\n }\n\n /**\n * options which override the options set in the LRUCache constructor\n * when calling {@link LRUCache#memo}.\n *\n * This is the union of {@link GetOptions} and {@link SetOptions}, plus\n * {@link MemoOptions.forceRefresh}, and\n * {@link MemoOptions.context}\n *\n * Any of these may be modified in the {@link OptionsBase.memoMethod}\n * function, but the {@link GetOptions} fields will of course have no\n * effect, as the {@link LRUCache#get} call already happened by the time\n * the memoMethod is called.\n */\n export interface MemoizerMemoOptions<K, V, FC = unknown>\n extends Pick<\n OptionsBase<K, V, FC>,\n | 'allowStale'\n | 'updateAgeOnGet'\n | 'noDeleteOnStaleGet'\n | 'sizeCalculation'\n | 'ttl'\n | 'noDisposeOnSet'\n | 'noUpdateTTL'\n > {\n status?: Status<V>\n size?: Size\n start?: Milliseconds\n }\n\n /**\n * Options that may be passed to the {@link LRUCache#has} method.\n */\n export interface HasOptions<K, V, FC>\n extends Pick<OptionsBase<K, V, FC>, 'updateAgeOnHas'> {\n status?: Status<V>\n }\n\n /**\n * Options that may be passed to the {@link LRUCache#get} method.\n */\n export interface GetOptions<K, V, FC>\n extends Pick<\n OptionsBase<K, V, FC>,\n 'allowStale' | 'updateAgeOnGet' | 'noDeleteOnStaleGet'\n > {\n status?: Status<V>\n }\n\n /**\n * Options that may be passed to the {@link LRUCache#peek} method.\n */\n export interface PeekOptions<K, V, FC>\n extends Pick<OptionsBase<K, V, FC>, 'allowStale'> {}\n\n /**\n * Options that may be passed to the {@link LRUCache#set} method.\n */\n export interface SetOptions<K, V, FC>\n extends Pick<\n OptionsBase<K, V, FC>,\n 'sizeCalculation' | 'ttl' | 'noDisposeOnSet' | 'noUpdateTTL'\n > {\n /**\n * If size tracking is enabled, then setting an explicit size\n * in the {@link LRUCache#set} call will prevent calling the\n * {@link OptionsBase.sizeCalculation} function.\n */\n size?: Size\n /**\n * If TTL tracking is enabled, then setting an explicit start\n * time in the {@link LRUCache#set} call will override the\n * default time from `performance.now()` or `Date.now()`.\n *\n * Note that it must be a valid value for whichever time-tracking\n * method is in use.\n */\n start?: Milliseconds\n status?: Status<V>\n }\n\n /**\n * The type signature for the {@link OptionsBase.fetchMethod} option.\n */\n export type Fetcher<K, V, FC = unknown> = (\n key: K,\n staleValue: V | undefined,\n options: FetcherOptions<K, V, FC>,\n ) => Promise<V | undefined | void> | V | undefined | void\n\n /**\n * the type signature for the {@link OptionsBase.memoMethod} option.\n */\n export type Memoizer<K, V, FC = unknown> = (\n key: K,\n staleValue: V | undefined,\n options: MemoizerOptions<K, V, FC>,\n ) => V\n\n /**\n * Options which may be passed to the {@link LRUCache} constructor.\n *\n * Most of these may be overridden in the various options that use\n * them.\n *\n * Despite all being technically optional, the constructor requires that\n * a cache is at minimum limited by one or more of {@link OptionsBase.max},\n * {@link OptionsBase.ttl}, or {@link OptionsBase.maxSize}.\n *\n * If {@link OptionsBase.ttl} is used alone, then it is strongly advised\n * (and in fact required by the type definitions here) that the cache\n * also set {@link OptionsBase.ttlAutopurge}, to prevent potentially\n * unbounded storage.\n *\n * All options are also available on the {@link LRUCache} instance, making\n * it safe to pass an LRUCache instance as the options argumemnt to\n * make another empty cache of the same type.\n *\n * Some options are marked as read-only, because changing them after\n * instantiation is not safe. Changing any of the other options will of\n * course only have an effect on subsequent method calls.\n */\n export interface OptionsBase<K, V, FC> {\n /**\n * The maximum number of items to store in the cache before evicting\n * old entries. This is read-only on the {@link LRUCache} instance,\n * and may not be overridden.\n *\n * If set, then storage space will be pre-allocated at construction\n * time, and the cache will perform significantly faster.\n *\n * Note that significantly fewer items may be stored, if\n * {@link OptionsBase.maxSize} and/or {@link OptionsBase.ttl} are also\n * set.\n *\n * **It is strongly recommended to set a `max` to prevent unbounded growth\n * of the cache.**\n */\n max?: Count\n\n /**\n * Max time in milliseconds for items to live in cache before they are\n * considered stale. Note that stale items are NOT preemptively removed by\n * default, and MAY live in the cache, contributing to its LRU max, long\n * after they have expired, unless {@link OptionsBase.ttlAutopurge} is\n * set.\n *\n * If set to `0` (the default value), then that means \"do not track\n * TTL\", not \"expire immediately\".\n *\n * Also, as this cache is optimized for LRU/MRU operations, some of\n * the staleness/TTL checks will reduce performance, as they will incur\n * overhead by deleting items.\n *\n * This is not primarily a TTL cache, and does not make strong TTL\n * guarantees. There is no pre-emptive pruning of expired items, but you\n * _may_ set a TTL on the cache, and it will treat expired items as missing\n * when they are fetched, and delete them.\n *\n * Optional, but must be a non-negative integer in ms if specified.\n *\n * This may be overridden by passing an options object to `cache.set()`.\n *\n * At least one of `max`, `maxSize`, or `TTL` is required. This must be a\n * positive integer if set.\n *\n * Even if ttl tracking is enabled, **it is strongly recommended to set a\n * `max` to prevent unbounded growth of the cache.**\n *\n * If ttl tracking is enabled, and `max` and `maxSize` are not set,\n * and `ttlAutopurge` is not set, then a warning will be emitted\n * cautioning about the potential for unbounded memory consumption.\n * (The TypeScript definitions will also discourage this.)\n */\n ttl?: Milliseconds\n\n /**\n * Minimum amount of time in ms in which to check for staleness.\n * Defaults to 1, which means that the current time is checked\n * at most once per millisecond.\n *\n * Set to 0 to check the current time every time staleness is tested.\n * (This reduces performance, and is theoretically unnecessary.)\n *\n * Setting this to a higher value will improve performance somewhat\n * while using ttl tracking, albeit at the expense of keeping stale\n * items around a bit longer than their TTLs would indicate.\n *\n * @default 1\n */\n ttlResolution?: Milliseconds\n\n /**\n * Preemptively remove stale items from the cache.\n *\n * Note that this may *significantly* degrade performance, especially if\n * the cache is storing a large number of items. It is almost always best\n * to just leave the stale items in the cache, and let them fall out as new\n * items are added.\n *\n * Note that this means that {@link OptionsBase.allowStale} is a bit\n * pointless, as stale items will be deleted almost as soon as they\n * expire.\n *\n * Use with caution!\n */\n ttlAutopurge?: boolean\n\n /**\n * When using time-expiring entries with `ttl`, setting this to `true` will\n * make each item's age reset to 0 whenever it is retrieved from cache with\n * {@link LRUCache#get}, causing it to not expire. (It can still fall out\n * of cache based on recency of use, of course.)\n *\n * Has no effect if {@link OptionsBase.ttl} is not set.\n *\n * This may be overridden by passing an options object to `cache.get()`.\n */\n updateAgeOnGet?: boolean\n\n /**\n * When using time-expiring entries with `ttl`, setting this to `true` will\n * make each item's age reset to 0 whenever its presence in the cache is\n * checked with {@link LRUCache#has}, causing it to not expire. (It can\n * still fall out of cache based on recency of use, of course.)\n *\n * Has no effect if {@link OptionsBase.ttl} is not set.\n */\n updateAgeOnHas?: boolean\n\n /**\n * Allow {@link LRUCache#get} and {@link LRUCache#fetch} calls to return\n * stale data, if available.\n *\n * By default, if you set `ttl`, stale items will only be deleted from the\n * cache when you `get(key)`. That is, it's not preemptively pruning items,\n * unless {@link OptionsBase.ttlAutopurge} is set.\n *\n * If you set `allowStale:true`, it'll return the stale value *as well as*\n * deleting it. If you don't set this, then it'll return `undefined` when\n * you try to get a stale entry.\n *\n * Note that when a stale entry is fetched, _even if it is returned due to\n * `allowStale` being set_, it is removed from the cache immediately. You\n * can suppress this behavior by setting\n * {@link OptionsBase.noDeleteOnStaleGet}, either in the constructor, or in\n * the options provided to {@link LRUCache#get}.\n *\n * This may be overridden by passing an options object to `cache.get()`.\n * The `cache.has()` method will always return `false` for stale items.\n *\n * Only relevant if a ttl is set.\n */\n allowStale?: boolean\n\n /**\n * Function that is called on items when they are dropped from the\n * cache, as `dispose(value, key, reason)`.\n *\n * This can be handy if you want to close file descriptors or do\n * other cleanup tasks when items are no longer stored in the cache.\n *\n * **NOTE**: It is called _before_ the item has been fully removed\n * from the cache, so if you want to put it right back in, you need\n * to wait until the next tick. If you try to add it back in during\n * the `dispose()` function call, it will break things in subtle and\n * weird ways.\n *\n * Unlike several other options, this may _not_ be overridden by\n * passing an option to `set()`, for performance reasons.\n *\n * The `reason` will be one of the following strings, corresponding\n * to the reason for the item's deletion:\n *\n * - `evict` Item was evicted to make space for a new addition\n * - `set` Item was overwritten by a new value\n * - `expire` Item expired its TTL\n * - `fetch` Item was deleted due to a failed or aborted fetch, or a\n * fetchMethod returning `undefined.\n * - `delete` Item was removed by explicit `cache.delete(key)`,\n * `cache.clear()`, or `cache.set(key, undefined)`.\n */\n dispose?: Disposer<K, V>\n\n /**\n * Function that is called when new items are inserted into the cache,\n * as `onInsert(value, key, reason)`.\n *\n * This can be useful if you need to perform actions when an item is\n * added, such as logging or tracking insertions.\n *\n * Unlike some other options, this may _not_ be overridden by passing\n * an option to `set()`, for performance and consistency reasons.\n */\n onInsert?: Inserter<K, V>\n\n /**\n * The same as {@link OptionsBase.dispose}, but called *after* the entry\n * is completely removed and the cache is once again in a clean state.\n *\n * It is safe to add an item right back into the cache at this point.\n * However, note that it is *very* easy to inadvertently create infinite\n * recursion this way.\n */\n disposeAfter?: Disposer<K, V>\n\n /**\n * Set to true to suppress calling the\n * {@link OptionsBase.dispose} function if the entry key is\n * still accessible within the cache.\n *\n * This may be overridden by passing an options object to\n * {@link LRUCache#set}.\n *\n * Only relevant if `dispose` or `disposeAfter` are set.\n */\n noDisposeOnSet?: boolean\n\n /**\n * Boolean flag to tell the cache to not update the TTL when setting a new\n * value for an existing key (ie, when updating a value rather than\n * inserting a new value). Note that the TTL value is _always_ set (if\n * provided) when adding a new entry into the cache.\n *\n * Has no effect if a {@link OptionsBase.ttl} is not set.\n *\n * May be passed as an option to {@link LRUCache#set}.\n */\n noUpdateTTL?: boolean\n\n /**\n * Set to a positive integer to track the sizes of items added to the\n * cache, and automatically evict items in order to stay below this size.\n * Note that this may result in fewer than `max` items being stored.\n *\n * Attempting to add an item to the cache whose calculated size is greater\n * that this amount will be a no-op. The item will not be cached, and no\n * other items will be evicted.\n *\n * Optional, must be a positive integer if provided.\n *\n * Sets `maxEntrySize` to the same value, unless a different value is\n * provided for `maxEntrySize`.\n *\n * At least one of `max`, `maxSize`, or `TTL` is required. This must be a\n * positive integer if set.\n *\n * Even if size tracking is enabled, **it is strongly recommended to set a\n * `max` to prevent unbounded growth of the cache.**\n *\n * Note also that size tracking can negatively impact performance,\n * though for most cases, only minimally.\n */\n maxSize?: Size\n\n /**\n * The maximum allowed size for any single item in the cache.\n *\n * If a larger item is passed to {@link LRUCache#set} or returned by a\n * {@link OptionsBase.fetchMethod} or {@link OptionsBase.memoMethod}, then\n * it will not be stored in the cache.\n *\n * Attempting to add an item whose calculated size is greater than\n * this amount will not cache the item or evict any old items, but\n * WILL delete an existing value if one is already present.\n *\n * Optional, must be a positive integer if provided. Defaults to\n * the value of `maxSize` if provided.\n */\n maxEntrySize?: Size\n\n /**\n * A function that returns a number indicating the item's size.\n *\n * Requires {@link OptionsBase.maxSize} to be set.\n *\n * If not provided, and {@link OptionsBase.maxSize} or\n * {@link OptionsBase.maxEntrySize} are set, then all\n * {@link LRUCache#set} calls **must** provide an explicit\n * {@link SetOptions.size} or sizeCalculation param.\n */\n sizeCalculation?: SizeCalculator<K, V>\n\n /**\n * Method that provides the implementation for {@link LRUCache#fetch}\n *\n * ```ts\n * fetchMethod(key, staleValue, { signal, options, context })\n * ```\n *\n * If `fetchMethod` is not provided, then `cache.fetch(key)` is equivalent\n * to `Promise.resolve(cache.get(key))`.\n *\n * If at any time, `signal.aborted` is set to `true`, or if the\n * `signal.onabort` method is called, or if it emits an `'abort'` event\n * which you can listen to with `addEventListener`, then that means that\n * the fetch should be abandoned. This may be passed along to async\n * functions aware of AbortController/AbortSignal behavior.\n *\n * The `fetchMethod` should **only** return `undefined` or a Promise\n * resolving to `undefined` if the AbortController signaled an `abort`\n * event. In all other cases, it should return or resolve to a value\n * suitable for adding to the cache.\n *\n * The `options` object is a union of the options that may be provided to\n * `set()` and `get()`. If they are modified, then that will result in\n * modifying the settings to `cache.set()` when the value is resolved, and\n * in the case of\n * {@link OptionsBase.noDeleteOnFetchRejection} and\n * {@link OptionsBase.allowStaleOnFetchRejection}, the handling of\n * `fetchMethod` failures.\n *\n * For example, a DNS cache may update the TTL based on the value returned\n * from a remote DNS server by changing `options.ttl` in the `fetchMethod`.\n */\n fetchMethod?: Fetcher<K, V, FC>\n\n /**\n * Method that provides the implementation for {@link LRUCache#memo}\n */\n memoMethod?: Memoizer<K, V, FC>\n\n /**\n * Set to true to suppress the deletion of stale data when a\n * {@link OptionsBase.fetchMethod} returns a rejected promise.\n */\n noDeleteOnFetchRejection?: boolean\n\n /**\n * Do not delete stale items when they are retrieved with\n * {@link LRUCache#get}.\n *\n * Note that the `get` return value will still be `undefined`\n * unless {@link OptionsBase.allowStale} is true.\n *\n * When using time-expiring entries with `ttl`, by default stale\n * items will be removed from the cache when the key is accessed\n * with `cache.get()`.\n *\n * Setting this option will cause stale items to remain in the cache, until\n * they are explicitly deleted with `cache.delete(key)`, or retrieved with\n * `noDeleteOnStaleGet` set to `false`.\n *\n * This may be overridden by passing an options object to `cache.get()`.\n *\n * Only relevant if a ttl is used.\n */\n noDeleteOnStaleGet?: boolean\n\n /**\n * Set to true to allow returning stale data when a\n * {@link OptionsBase.fetchMethod} throws an error or returns a rejected\n * promise.\n *\n * This differs from using {@link OptionsBase.allowStale} in that stale\n * data will ONLY be returned in the case that the {@link LRUCache#fetch}\n * fails, not any other times.\n *\n * If a `fetchMethod` fails, and there is no stale value available, the\n * `fetch()` will resolve to `undefined`. Ie, all `fetchMethod` errors are\n * suppressed.\n *\n * Implies `noDeleteOnFetchRejection`.\n *\n * This may be set in calls to `fetch()`, or defaulted on the constructor,\n * or overridden by modifying the options object in the `fetchMethod`.\n */\n allowStaleOnFetchRejection?: boolean\n\n /**\n * Set to true to return a stale value from the cache when the\n * `AbortSignal` passed to the {@link OptionsBase.fetchMethod} dispatches\n * an `'abort'` event, whether user-triggered, or due to internal cache\n * behavior.\n *\n * Unless {@link OptionsBase.ignoreFetchAbort} is also set, the underlying\n * {@link OptionsBase.fetchMethod} will still be considered canceled, and\n * any value it returns will be ignored and not cached.\n *\n * Caveat: since fetches are aborted when a new value is explicitly\n * set in the cache, this can lead to fetch returning a stale value,\n * since that was the fallback value _at the moment the `fetch()` was\n * initiated_, even though the new updated value is now present in\n * the cache.\n *\n * For example:\n *\n * ```ts\n * const cache = new LRUCache<string, any>({\n * ttl: 100,\n * fetchMethod: async (url, oldValue, { signal }) => {\n * const res = await fetch(url, { signal })\n * return await res.json()\n * }\n * })\n * cache.set('https://example.com/', { some: 'data' })\n * // 100ms go by...\n * const result = cache.fetch('https://example.com/')\n * cache.set('https://example.com/', { other: 'thing' })\n * console.log(await result) // { some: 'data' }\n * console.log(cache.get('https://example.com/')) // { other: 'thing' }\n * ```\n */\n allowStaleOnFetchAbort?: boolean\n\n /**\n * Set to true to ignore the `abort` event emitted by the `AbortSignal`\n * object passed to {@link OptionsBase.fetchMethod}, and still cache the\n * resulting resolution value, as long as it is not `undefined`.\n *\n * When used on its own, this means aborted {@link LRUCache#fetch} calls\n * are not immediately resolved or rejected when they are aborted, and\n * instead take the full time to await.\n *\n * When used with {@link OptionsBase.allowStaleOnFetchAbort}, aborted\n * {@link LRUCache#fetch} calls will resolve immediately to their stale\n * cached value or `undefined`, and will continue to process and eventually\n * update the cache when they resolve, as long as the resulting value is\n * not `undefined`, thus supporting a \"return stale on timeout while\n * refreshing\" mechanism by passing `AbortSignal.timeout(n)` as the signal.\n *\n * For example:\n *\n * ```ts\n * const c = new LRUCache({\n * ttl: 100,\n * ignoreFetchAbort: true,\n * allowStaleOnFetchAbort: true,\n * fetchMethod: async (key, oldValue, { signal }) => {\n * // note: do NOT pass the signal to fetch()!\n * // let's say this fetch can take a long time.\n * const res = await fetch(`https://slow-backend-server/${key}`)\n * return await res.json()\n * },\n * })\n *\n * // this will return the stale value after 100ms, while still\n * // updating in the background for next time.\n * const val = await c.fetch('key', { signal: AbortSignal.timeout(100) })\n * ```\n *\n * **Note**: regardless of this setting, an `abort` event _is still\n * emitted on the `AbortSignal` object_, so may result in invalid results\n * when passed to other underlying APIs that use AbortSignals.\n *\n * This may be overridden in the {@link OptionsBase.fetchMethod} or the\n * call to {@link LRUCache#fetch}.\n */\n ignoreFetchAbort?: boolean\n\n /**\n * In some cases, you may want to swap out the performance/Date object\n * used for TTL tracking. This should almost certainly NOT be done in\n * production environments!\n *\n * This value defaults to `global.performance` if it has a `now()` method,\n * or the `global.Date` object otherwise.\n */\n perf?: Perf\n }\n\n export interface OptionsMaxLimit<K, V, FC>\n extends OptionsBase<K, V, FC> {\n max: Count\n }\n export interface OptionsTTLLimit<K, V, FC>\n extends OptionsBase<K, V, FC> {\n ttl: Milliseconds\n ttlAutopurge: boolean\n }\n export interface OptionsSizeLimit<K, V, FC>\n extends OptionsBase<K, V, FC> {\n maxSize: Size\n }\n\n /**\n * The valid safe options for the {@link LRUCache} constructor\n */\n export type Options<K, V, FC> =\n | OptionsMaxLimit<K, V, FC>\n | OptionsSizeLimit<K, V, FC>\n | OptionsTTLLimit<K, V, FC>\n\n /**\n * Entry objects used by {@link LRUCache#load} and {@link LRUCache#dump},\n * and returned by {@link LRUCache#info}.\n */\n export interface Entry<V> {\n value: V\n ttl?: Milliseconds\n size?: Size\n start?: Milliseconds\n }\n}\n\n/**\n * Default export, the thing you're using this module to get.\n *\n * The `K` and `V` types define the key and value types, respectively. The\n * optional `FC` type defines the type of the `context` object passed to\n * `cache.fetch()` and `cache.memo()`.\n *\n * Keys and values **must not** be `null` or `undefined`.\n *\n * All properties from the options object (with the exception of `max`,\n * `maxSize`, `fetchMethod`, `memoMethod`, `dispose` and `disposeAfter`) are\n * added as normal public members. (The listed options are read-only getters.)\n *\n * Changing any of these will alter the defaults for subsequent method calls.\n */\nexport class LRUCache<K extends {}, V extends {}, FC = unknown> {\n // options that cannot be changed without disaster\n readonly #max: LRUCache.Count\n readonly #maxSize: LRUCache.Size\n readonly #dispose?: LRUCache.Disposer<K, V>\n readonly #onInsert?: LRUCache.Inserter<K, V>\n readonly #disposeAfter?: LRUCache.Disposer<K, V>\n readonly #fetchMethod?: LRUCache.Fetcher<K, V, FC>\n readonly #memoMethod?: LRUCache.Memoizer<K, V, FC>\n readonly #perf: Perf\n\n /**\n * {@link LRUCache.OptionsBase.perf}\n */\n get perf() {\n return this.#perf\n }\n\n /**\n * {@link LRUCache.OptionsBase.ttl}\n */\n ttl: LRUCache.Milliseconds\n\n /**\n * {@link LRUCache.OptionsBase.ttlResolution}\n */\n ttlResolution: LRUCache.Milliseconds\n /**\n * {@link LRUCache.OptionsBase.ttlAutopurge}\n */\n ttlAutopurge: boolean\n /**\n * {@link LRUCache.OptionsBase.updateAgeOnGet}\n */\n updateAgeOnGet: boolean\n /**\n * {@link LRUCache.OptionsBase.updateAgeOnHas}\n */\n updateAgeOnHas: boolean\n /**\n * {@link LRUCache.OptionsBase.allowStale}\n */\n allowStale: boolean\n\n /**\n * {@link LRUCache.OptionsBase.noDisposeOnSet}\n */\n noDisposeOnSet: boolean\n /**\n * {@link LRUCache.OptionsBase.noUpdateTTL}\n */\n noUpdateTTL: boolean\n /**\n * {@link LRUCache.OptionsBase.maxEntrySize}\n */\n maxEntrySize: LRUCache.Size\n /**\n * {@link LRUCache.OptionsBase.sizeCalculation}\n */\n sizeCalculation?: LRUCache.SizeCalculator<K, V>\n /**\n * {@link LRUCache.OptionsBase.noDeleteOnFetchRejection}\n */\n noDeleteOnFetchRejection: boolean\n /**\n * {@link LRUCache.OptionsBase.noDeleteOnStaleGet}\n */\n noDeleteOnStaleGet: boolean\n /**\n * {@link LRUCache.OptionsBase.allowStaleOnFetchAbort}\n */\n allowStaleOnFetchAbort: boolean\n /**\n * {@link LRUCache.OptionsBase.allowStaleOnFetchRejection}\n */\n allowStaleOnFetchRejection: boolean\n /**\n * {@link LRUCache.OptionsBase.ignoreFetchAbort}\n */\n ignoreFetchAbort: boolean\n\n // computed properties\n #size: LRUCache.Count\n #calculatedSize: LRUCache.Size\n #keyMap: Map<K, Index>\n #keyList: (K | undefined)[]\n #valList: (V | BackgroundFetch<V> | undefined)[]\n #next: NumberArray\n #prev: NumberArray\n #head: Index\n #tail: Index\n #free: StackLike\n #disposed?: DisposeTask<K, V>[]\n #sizes?: ZeroArray\n #starts?: ZeroArray\n #ttls?: ZeroArray\n #autopurgeTimers?: (undefined | ReturnType<typeof setTimeout>)[]\n\n #hasDispose: boolean\n #hasFetchMethod: boolean\n #hasDisposeAfter: boolean\n #hasOnInsert: boolean\n\n /**\n * Do not call this method unless you need to inspect the\n * inner workings of the cache. If anything returned by this\n * object is modified in any way, strange breakage may occur.\n *\n * These fields are private for a reason!\n *\n * @internal\n */\n static unsafeExposeInternals<\n K extends {},\n V extends {},\n FC extends unknown = unknown,\n >(c: LRUCache<K, V, FC>) {\n return {\n // properties\n starts: c.#starts,\n ttls: c.#ttls,\n autopurgeTimers: c.#autopurgeTimers,\n sizes: c.#sizes,\n keyMap: c.#keyMap as Map<K, number>,\n keyList: c.#keyList,\n valList: c.#valList,\n next: c.#next,\n prev: c.#prev,\n get head() {\n return c.#head\n },\n get tail() {\n return c.#tail\n },\n free: c.#free,\n // methods\n isBackgroundFetch: (p: any) => c.#isBackgroundFetch(p),\n backgroundFetch: (\n k: K,\n index: number | undefined,\n options: LRUCache.FetchOptions<K, V, FC>,\n context: any,\n ): BackgroundFetch<V> =>\n c.#backgroundFetch(\n k,\n index as Index | undefined,\n options,\n context,\n ),\n moveToTail: (index: number): void => c.#moveToTail(index as Index),\n indexes: (options?: { allowStale: boolean }) => c.#indexes(options),\n rindexes: (options?: { allowStale: boolean }) =>\n c.#rindexes(options),\n isStale: (index: number | undefined) => c.#isStale(index as Index),\n }\n }\n\n // Protected read-only members\n\n /**\n * {@link LRUCache.OptionsBase.max} (read-only)\n */\n get max(): LRUCache.Count {\n return this.#max\n }\n /**\n * {@link LRUCache.OptionsBase.maxSize} (read-only)\n */\n get maxSize(): LRUCache.Count {\n return this.#maxSize\n }\n /**\n * The total computed size of items in the cache (read-only)\n */\n get calculatedSize(): LRUCache.Size {\n return this.#calculatedSize\n }\n /**\n * The number of items stored in the cache (read-only)\n */\n get size(): LRUCache.Count {\n return this.#size\n }\n /**\n * {@link LRUCache.OptionsBase.fetchMethod} (read-only)\n */\n get fetchMethod(): LRUCache.Fetcher<K, V, FC> | undefined {\n return this.#fetchMethod\n }\n get memoMethod(): LRUCache.Memoizer<K, V, FC> | undefined {\n return this.#memoMethod\n }\n /**\n * {@link LRUCache.OptionsBase.dispose} (read-only)\n */\n get dispose() {\n return this.#dispose\n }\n /**\n * {@link LRUCache.OptionsBase.onInsert} (read-only)\n */\n get onInsert() {\n return this.#onInsert\n }\n /**\n * {@link LRUCache.OptionsBase.disposeAfter} (read-only)\n */\n get disposeAfter() {\n return this.#disposeAfter\n }\n\n constructor(options: LRUCache.Options<K, V, FC> | LRUCache<K, V, FC>) {\n const {\n max = 0,\n ttl,\n ttlResolution = 1,\n ttlAutopurge,\n updateAgeOnGet,\n updateAgeOnHas,\n allowStale,\n dispose,\n onInsert,\n disposeAfter,\n noDisposeOnSet,\n noUpdateTTL,\n maxSize = 0,\n maxEntrySize = 0,\n sizeCalculation,\n fetchMethod,\n memoMethod,\n noDeleteOnFetchRejection,\n noDeleteOnStaleGet,\n allowStaleOnFetchRejection,\n allowStaleOnFetchAbort,\n ignoreFetchAbort,\n perf,\n } = options\n\n if (perf !== undefined) {\n if (typeof perf?.now !== 'function') {\n throw new TypeError(\n 'perf option must have a now() method if specified',\n )\n }\n }\n\n this.#perf = perf ?? defaultPerf\n\n if (max !== 0 && !isPosInt(max)) {\n throw new TypeError('max option must be a nonnegative integer')\n }\n\n const UintArray = max ? getUintArray(max) : Array\n if (!UintArray) {\n throw new Error('invalid max value: ' + max)\n }\n\n this.#max = max\n this.#maxSize = maxSize\n this.maxEntrySize = maxEntrySize || this.#maxSize\n this.sizeCalculation = sizeCalculation\n if (this.sizeCalculation) {\n if (!this.#maxSize && !this.maxEntrySize) {\n throw new TypeError(\n 'cannot set sizeCalculation without setting maxSize or maxEntrySize',\n )\n }\n if (typeof this.sizeCalculation !== 'function') {\n throw new TypeError('sizeCalculation set to non-function')\n }\n }\n\n if (memoMethod !== undefined && typeof memoMethod !== 'function') {\n throw new TypeError('memoMethod must be a function if defined')\n }\n this.#memoMethod = memoMethod\n\n if (fetchMethod !== undefined && typeof fetchMethod !== 'function') {\n throw new TypeError('fetchMethod must be a function if specified')\n }\n this.#fetchMethod = fetchMethod\n this.#hasFetchMethod = !!fetchMethod\n\n this.#keyMap = new Map()\n this.#keyList = new Array(max).fill(undefined)\n this.#valList = new Array(max).fill(undefined)\n this.#next = new UintArray(max)\n this.#prev = new UintArray(max)\n this.#head = 0 as Index\n this.#tail = 0 as Index\n this.#free = Stack.create(max)\n this.#size = 0\n this.#calculatedSize = 0\n\n if (typeof dispose === 'function') {\n this.#dispose = dispose\n }\n if (typeof onInsert === 'function') {\n this.#onInsert = onInsert\n }\n if (typeof disposeAfter === 'function') {\n this.#disposeAfter = disposeAfter\n this.#disposed = []\n } else {\n this.#disposeAfter = undefined\n this.#disposed = undefined\n }\n this.#hasDispose = !!this.#dispose\n this.#hasOnInsert = !!this.#onInsert\n this.#hasDisposeAfter = !!this.#disposeAfter\n\n this.noDisposeOnSet = !!noDisposeOnSet\n this.noUpdateTTL = !!noUpdateTTL\n this.noDeleteOnFetchRejection = !!noDeleteOnFetchRejection\n this.allowStaleOnFetchRejection = !!allowStaleOnFetchRejection\n this.allowStaleOnFetchAbort = !!allowStaleOnFetchAbort\n this.ignoreFetchAbort = !!ignoreFetchAbort\n\n // NB: maxEntrySize is set to maxSize if it's set\n if (this.maxEntrySize !== 0) {\n if (this.#maxSize !== 0) {\n if (!isPosInt(this.#maxSize)) {\n throw new TypeError(\n 'maxSize must be a positive integer if specified',\n )\n }\n }\n if (!isPosInt(this.maxEntrySize)) {\n throw new TypeError(\n 'maxEntrySize must be a positive integer if specified',\n )\n }\n this.#initializeSizeTracking()\n }\n\n this.allowStale = !!allowStale\n this.noDeleteOnStaleGet = !!noDeleteOnStaleGet\n this.updateAgeOnGet = !!updateAgeOnGet\n this.updateAgeOnHas = !!updateAgeOnHas\n this.ttlResolution =\n isPosInt(ttlResolution) || ttlResolution === 0 ? ttlResolution : 1\n this.ttlAutopurge = !!ttlAutopurge\n this.ttl = ttl || 0\n if (this.ttl) {\n if (!isPosInt(this.ttl)) {\n throw new TypeError('ttl must be a positive integer if specified')\n }\n this.#initializeTTLTracking()\n }\n\n // do not allow completely unbounded caches\n if (this.#max === 0 && this.ttl === 0 && this.#maxSize === 0) {\n throw new TypeError(\n 'At least one of max, maxSize, or ttl is required',\n )\n }\n if (!this.ttlAutopurge && !this.#max && !this.#maxSize) {\n const code = 'LRU_CACHE_UNBOUNDED'\n if (shouldWarn(code)) {\n warned.add(code)\n const msg =\n 'TTL caching without ttlAutopurge, max, or maxSize can ' +\n 'result in unbounded memory consumption.'\n emitWarning(msg, 'UnboundedCacheWarning', code, LRUCache)\n }\n }\n }\n\n /**\n * Return the number of ms left in the item's TTL. If item is not in cache,\n * returns `0`. Returns `Infinity` if item is in cache without a defined TTL.\n */\n getRemainingTTL(key: K) {\n return this.#keyMap.has(key) ? Infinity : 0\n }\n\n #initializeTTLTracking() {\n const ttls = new ZeroArray(this.#max)\n const starts = new ZeroArray(this.#max)\n this.#ttls = ttls\n this.#starts = starts\n const purgeTimers =\n this.ttlAutopurge ?\n new Array<undefined | ReturnType<typeof setTimeout>>(this.#max)\n : undefined\n this.#autopurgeTimers = purgeTimers\n\n this.#setItemTTL = (index, ttl, start = this.#perf.now()) => {\n starts[index] = ttl !== 0 ? start : 0\n ttls[index] = ttl\n // clear out the purge timer if we're setting TTL to 0, and\n // previously had a ttl purge timer running, so it doesn't\n // fire unnecessarily.\n if (purgeTimers?.[index]) {\n clearTimeout(purgeTimers[index])\n purgeTimers[index] = undefined\n }\n if (ttl !== 0 && purgeTimers) {\n const t = setTimeout(() => {\n if (this.#isStale(index)) {\n this.#delete(this.#keyList[index] as K, 'expire')\n }\n }, ttl + 1)\n // unref() not supported on all platforms\n /* c8 ignore start */\n if (t.unref) {\n t.unref()\n }\n /* c8 ignore stop */\n purgeTimers[index] = t\n }\n }\n\n this.#updateItemAge = index => {\n starts[index] = ttls[index] !== 0 ? this.#perf.now() : 0\n }\n\n this.#statusTTL = (status, index) => {\n if (ttls[index]) {\n const ttl = ttls[index]\n const start = starts[index]\n /* c8 ignore next */\n if (!ttl || !start) return\n status.ttl = ttl\n status.start = start\n status.now = cachedNow || getNow()\n const age = status.now - start\n status.remainingTTL = ttl - age\n }\n }\n\n // debounce calls to perf.now() to 1s so we're not hitting\n // that costly call repeatedly.\n let cachedNow = 0\n const getNow = () => {\n const n = this.#perf.now()\n if (this.ttlResolution > 0) {\n cachedNow = n\n const t = setTimeout(() => (cachedNow = 0), this.ttlResolution)\n // not available on all platforms\n /* c8 ignore start */\n if (t.unref) {\n t.unref()\n }\n /* c8 ignore stop */\n }\n return n\n }\n\n this.getRemainingTTL = key => {\n const index = this.#keyMap.get(key)\n if (index === undefined) {\n return 0\n }\n const ttl = ttls[index]\n const start = starts[index]\n if (!ttl || !start) {\n return Infinity\n }\n const age = (cachedNow || getNow()) - start\n return ttl - age\n }\n\n this.#isStale = index => {\n const s = starts[index]\n const t = ttls[index]\n return !!t && !!s && (cachedNow || getNow()) - s > t\n }\n }\n\n // conditionally set private methods related to TTL\n #updateItemAge: (index: Index) => void = () => {}\n #statusTTL: (status: LRUCache.Status<V>, index: Index) => void = () => {}\n #setItemTTL: (\n index: Index,\n ttl: LRUCache.Milliseconds,\n start?: LRUCache.Milliseconds,\n // ignore because we never call this if we're not already in TTL mode\n /* c8 ignore start */\n ) => void = () => {}\n /* c8 ignore stop */\n\n #isStale: (index: Index) => boolean = () => false\n\n #initializeSizeTracking() {\n const sizes = new ZeroArray(this.#max)\n this.#calculatedSize = 0\n this.#sizes = sizes\n this.#removeItemSize = index => {\n this.#calculatedSize -= sizes[index] as number\n sizes[index] = 0\n }\n this.#requireSize = (k, v, size, sizeCalculation) => {\n // provisionally accept background fetches.\n // actual value size will be checked when they return.\n if (this.#isBackgroundFetch(v)) {\n return 0\n }\n if (!isPosInt(size)) {\n if (sizeCalculation) {\n if (typeof sizeCalculation !== 'function') {\n throw new TypeError('sizeCalculation must be a function')\n }\n size = sizeCalculation(v, k)\n if (!isPosInt(size)) {\n throw new TypeError(\n 'sizeCalculation return invalid (expect positive integer)',\n )\n }\n } else {\n throw new TypeError(\n 'invalid size value (must be positive integer). ' +\n 'When maxSize or maxEntrySize is used, sizeCalculation ' +\n 'or size must be set.',\n )\n }\n }\n return size\n }\n this.#addItemSize = (\n index: Index,\n size: LRUCache.Size,\n status?: LRUCache.Status<V>,\n ) => {\n sizes[index] = size\n if (this.#maxSize) {\n const maxSize = this.#maxSize - (sizes[index] as number)\n while (this.#calculatedSize > maxSize) {\n this.#evict(true)\n }\n }\n this.#calculatedSize += sizes[index] as number\n if (status) {\n status.entrySize = size\n status.totalCalculatedSize = this.#calculatedSize\n }\n }\n }\n\n #removeItemSize: (index: Index) => void = _i => {}\n #addItemSize: (\n index: Index,\n size: LRUCache.Size,\n status?: LRUCache.Status<V>,\n ) => void = (_i, _s, _st) => {}\n #requireSize: (\n k: K,\n v: V | BackgroundFetch<V>,\n size?: LRUCache.Size,\n sizeCalculation?: LRUCache.SizeCalculator<K, V>,\n ) => LRUCache.Size = (\n _k: K,\n _v: V | BackgroundFetch<V>,\n size?: LRUCache.Size,\n sizeCalculation?: LRUCache.SizeCalculator<K, V>,\n ) => {\n if (size || sizeCalculation) {\n throw new TypeError(\n 'cannot set size without setting maxSize or maxEntrySize on cache',\n )\n }\n return 0\n };\n\n *#indexes({ allowStale = this.allowStale } = {}) {\n if (this.#size) {\n for (let i = this.#tail; true; ) {\n if (!this.#isValidIndex(i)) {\n break\n }\n if (allowStale || !this.#isStale(i)) {\n yield i\n }\n if (i === this.#head) {\n break\n } else {\n i = this.#prev[i] as Index\n }\n }\n }\n }\n\n *#rindexes({ allowStale = this.allowStale } = {}) {\n if (this.#size) {\n for (let i = this.#head; true; ) {\n if (!this.#isValidIndex(i)) {\n break\n }\n if (allowStale || !this.#isStale(i)) {\n yield i\n }\n if (i === this.#tail) {\n break\n } else {\n i = this.#next[i] as Index\n }\n }\n }\n }\n\n #isValidIndex(index: Index) {\n return (\n index !== undefined &&\n this.#keyMap.get(this.#keyList[index] as K) === index\n )\n }\n\n /**\n * Return a generator yielding `[key, value]` pairs,\n * in order from most recently used to least recently used.\n */\n *entries() {\n for (const i of this.#indexes()) {\n if (\n this.#valList[i] !== undefined &&\n this.#keyList[i] !== undefined &&\n !this.#isBackgroundFetch(this.#valList[i])\n ) {\n yield [this.#keyList[i], this.#valList[i]] as [K, V]\n }\n }\n }\n\n /**\n * Inverse order version of {@link LRUCache.entries}\n *\n * Return a generator yielding `[key, value]` pairs,\n * in order from least recently used to most recently used.\n */\n *rentries() {\n for (const i of this.#rindexes()) {\n if (\n this.#valList[i] !== undefined &&\n this.#keyList[i] !== undefined &&\n !this.#isBackgroundFetch(this.#valList[i])\n ) {\n yield [this.#keyList[i], this.#valList[i]]\n }\n }\n }\n\n /**\n * Return a generator yielding the keys in the cache,\n * in order from most recently used to least recently used.\n */\n *keys() {\n for (const i of this.#indexes()) {\n const k = this.#keyList[i]\n if (k !== undefined && !this.#isBackgroundFetch(this.#valList[i])) {\n yield k\n }\n }\n }\n\n /**\n * Inverse order version of {@link LRUCache.keys}\n *\n * Return a generator yielding the keys in the cache,\n * in order from least recently used to most recently used.\n */\n *rkeys() {\n for (const i of this.#rindexes()) {\n const k = this.#keyList[i]\n if (k !== undefined && !this.#isBackgroundFetch(this.#valList[i])) {\n yield k\n }\n }\n }\n\n /**\n * Return a generator yielding the values in the cache,\n * in order from most recently used to least recently used.\n */\n *values() {\n for (const i of this.#indexes()) {\n const v = this.#valList[i]\n if (v !== undefined && !this.#isBackgroundFetch(this.#valList[i])) {\n yield this.#valList[i] as V\n }\n }\n }\n\n /**\n * Inverse order version of {@link LRUCache.values}\n *\n * Return a generator yielding the values in the cache,\n * in order from least recently used to most recently used.\n */\n *rvalues() {\n for (const i of this.#rindexes()) {\n const v = this.#valList[i]\n if (v !== undefined && !this.#isBackgroundFetch(this.#valList[i])) {\n yield this.#valList[i]\n }\n }\n }\n\n /**\n * Iterating over the cache itself yields the same results as\n * {@link LRUCache.entries}\n */\n [Symbol.iterator]() {\n return this.entries()\n }\n\n /**\n * A String value that is used in the creation of the default string\n * description of an object. Called by the built-in method\n * `Object.prototype.toString`.\n */\n [Symbol.toStringTag] = 'LRUCache'\n\n /**\n * Find a value for which the supplied fn method returns a truthy value,\n * similar to `Array.find()`. fn is called as `fn(value, key, cache)`.\n */\n find(\n fn: (v: V, k: K, self: LRUCache<K, V, FC>) => boolean,\n getOptions: LRUCache.GetOptions<K, V, FC> = {},\n ) {\n for (const i of this.#indexes()) {\n const v = this.#valList[i]\n const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v\n if (value === undefined) continue\n if (fn(value, this.#keyList[i] as K, this)) {\n return this.get(this.#keyList[i] as K, getOptions)\n }\n }\n }\n\n /**\n * Call the supplied function on each item in the cache, in order from most\n * recently used to least recently used.\n *\n * `fn` is called as `fn(value, key, cache)`.\n *\n * If `thisp` is provided, function will be called in the `this`-context of\n * the provided object, or the cache if no `thisp` object is provided.\n *\n * Does not update age or recenty of use, or iterate over stale values.\n */\n forEach(\n fn: (v: V, k: K, self: LRUCache<K, V, FC>) => any,\n thisp: any = this,\n ) {\n for (const i of this.#indexes()) {\n const v = this.#valList[i]\n const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v\n if (value === undefined) continue\n fn.call(thisp, value, this.#keyList[i] as K, this)\n }\n }\n\n /**\n * The same as {@link LRUCache.forEach} but items are iterated over in\n * reverse order. (ie, less recently used items are iterated over first.)\n */\n rforEach(\n fn: (v: V, k: K, self: LRUCache<K, V, FC>) => any,\n thisp: any = this,\n ) {\n for (const i of this.#rindexes()) {\n const v = this.#valList[i]\n const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v\n if (value === undefined) continue\n fn.call(thisp, value, this.#keyList[i] as K, this)\n }\n }\n\n /**\n * Delete any stale entries. Returns true if anything was removed,\n * false otherwise.\n */\n purgeStale() {\n let deleted = false\n for (const i of this.#rindexes({ allowStale: true })) {\n if (this.#isStale(i)) {\n this.#delete(this.#keyList[i] as K, 'expire')\n deleted = true\n }\n }\n return deleted\n }\n\n /**\n * Get the extended info about a given entry, to get its value, size, and\n * TTL info simultaneously. Returns `undefined` if the key is not present.\n *\n * Unlike {@link LRUCache#dump}, which is designed to be portable and survive\n * serialization, the `start` value is always the current timestamp, and the\n * `ttl` is a calculated remaining time to live (negative if expired).\n *\n * Always returns stale values, if their info is found in the cache, so be\n * sure to check for expirations (ie, a negative {@link LRUCache.Entry#ttl})\n * if relevant.\n */\n info(key: K): LRUCache.Entry<V> | undefined {\n const i = this.#keyMap.get(key)\n if (i === undefined) return undefined\n const v = this.#valList[i]\n /* c8 ignore start - this isn't tested for the info function,\n * but it's the same logic as found in other places. */\n const value: V | undefined =\n this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v\n if (value === undefined) return undefined\n /* c8 ignore end */\n const entry: LRUCache.Entry<V> = { value }\n if (this.#ttls && this.#starts) {\n const ttl = this.#ttls[i]\n const start = this.#starts[i]\n if (ttl && start) {\n const remain = ttl - (this.#perf.now() - start)\n entry.ttl = remain\n entry.start = Date.now()\n }\n }\n if (this.#sizes) {\n entry.size = this.#sizes[i]\n }\n return entry\n }\n\n /**\n * Return an array of [key, {@link LRUCache.Entry}] tuples which can be\n * passed to {@link LRUCache#load}.\n *\n * The `start` fields are calculated relative to a portable `Date.now()`\n * timestamp, even if `performance.now()` is available.\n *\n * Stale entries are always included in the `dump`, even if\n * {@link LRUCache.OptionsBase.allowStale} is false.\n *\n * Note: this returns an actual array, not a generator, so it can be more\n * easily passed around.\n */\n dump() {\n const arr: [K, LRUCache.Entry<V>][] = []\n for (const i of this.#indexes({ allowStale: true })) {\n const key = this.#keyList[i]\n const v = this.#valList[i]\n const value: V | undefined =\n this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v\n if (value === undefined || key === undefined) continue\n const entry: LRUCache.Entry<V> = { value }\n if (this.#ttls && this.#starts) {\n entry.ttl = this.#ttls[i]\n // always dump the start relative to a portable timestamp\n // it's ok for this to be a bit slow, it's a rare operation.\n const age = this.#perf.now() - (this.#starts[i] as number)\n entry.start = Math.floor(Date.now() - age)\n }\n if (this.#sizes) {\n entry.size = this.#sizes[i]\n }\n arr.unshift([key, entry])\n }\n return arr\n }\n\n /**\n * Reset the cache and load in the items in entries in the order listed.\n *\n * The shape of the resulting cache may be different if the same options are\n * not used in both caches.\n *\n * The `start` fields are assumed to be calculated relative to a portable\n * `Date.now()` timestamp, even if `performance.now()` is available.\n */\n load(arr: [K, LRUCache.Entry<V>][]) {\n this.clear()\n for (const [key, entry] of arr) {\n if (entry.start) {\n // entry.start is a portable timestamp, but we may be using\n // node's performance.now(), so calculate the offset, so that\n // we get the intended remaining TTL, no matter how long it's\n // been on ice.\n //\n // it's ok for this to be a bit slow, it's a rare operation.\n const age = Date.now() - entry.start\n entry.start = this.#perf.now() - age\n }\n this.set(key, entry.value, entry)\n }\n }\n\n /**\n * Add a value to the cache.\n *\n * Note: if `undefined` is specified as a value, this is an alias for\n * {@link LRUCache#delete}\n *\n * Fields on the {@link LRUCache.SetOptions} options param will override\n * their corresponding values in the constructor options for the scope\n * of this single `set()` operation.\n *\n * If `start` is provided, then that will set the effective start\n * time for the TTL calculation. Note that this must be a previous\n * value of `performance.now()` if supported, or a previous value of\n * `Date.now()` if not.\n *\n * Options object may also include `size`, which will prevent\n * calling the `sizeCalculation` function and just use the specified\n * number if it is a positive integer, and `noDisposeOnSet` which\n * will prevent calling a `dispose` function in the case of\n * overwrites.\n *\n * If the `size` (or return value of `sizeCalculation`) for a given\n * entry is greater than `maxEntrySize`, then the item will not be\n * added to the cache.\n *\n * Will update the recency of the entry.\n *\n * If the value is `undefined`, then this is an alias for\n * `cache.delete(key)`. `undefined` is never stored in the cache.\n */\n set(\n k: K,\n v: V | BackgroundFetch<V> | undefined,\n setOptions: LRUCache.SetOptions<K, V, FC> = {},\n ) {\n if (v === undefined) {\n this.delete(k)\n return this\n }\n const {\n ttl = this.ttl,\n start,\n noDisposeOnSet = this.noDisposeOnSet,\n sizeCalculation = this.sizeCalculation,\n status,\n } = setOptions\n let { noUpdateTTL = this.noUpdateTTL } = setOptions\n\n const size = this.#requireSize(\n k,\n v,\n setOptions.size || 0,\n sizeCalculation,\n )\n // if the item doesn't fit, don't do anything\n // NB: maxEntrySize set to maxSize by default\n if (this.maxEntrySize && size > this.maxEntrySize) {\n if (status) {\n status.set = 'miss'\n status.maxEntrySizeExceeded = true\n }\n // have to delete, in case something is there already.\n this.#delete(k, 'set')\n return this\n }\n let index = this.#size === 0 ? undefined : this.#keyMap.get(k)\n if (index === undefined) {\n // addition\n index = (\n this.#size === 0 ? this.#tail\n : this.#free.length !== 0 ? this.#free.pop()\n : this.#size === this.#max ? this.#evict(false)\n : this.#size) as Index\n this.#keyList[index] = k\n this.#valList[index] = v\n this.#keyMap.set(k, index)\n this.#next[this.#tail] = index\n this.#prev[index] = this.#tail\n this.#tail = index\n this.#size++\n this.#addItemSize(index, size, status)\n if (status) status.set = 'add'\n noUpdateTTL = false\n if (this.#hasOnInsert) {\n this.#onInsert?.(v as V, k, 'add')\n }\n } else {\n // update\n this.#moveToTail(index)\n const oldVal = this.#valList[index] as V | BackgroundFetch<V>\n if (v !== oldVal) {\n if (this.#hasFetchMethod && this.#isBackgroundFetch(oldVal)) {\n oldVal.__abortController.abort(new Error('replaced'))\n const { __staleWhileFetching: s } = oldVal\n if (s !== undefined && !noDisposeOnSet) {\n if (this.#hasDispose) {\n this.#dispose?.(s as V, k, 'set')\n }\n if (this.#hasDisposeAfter) {\n this.#disposed?.push([s as V, k, 'set'])\n }\n }\n } else if (!noDisposeOnSet) {\n if (this.#hasDispose) {\n this.#dispose?.(oldVal as V, k, 'set')\n }\n if (this.#hasDisposeAfter) {\n this.#disposed?.push([oldVal as V, k, 'set'])\n }\n }\n this.#removeItemSize(index)\n this.#addItemSize(index, size, status)\n this.#valList[index] = v\n if (status) {\n status.set = 'replace'\n const oldValue =\n oldVal && this.#isBackgroundFetch(oldVal) ?\n oldVal.__staleWhileFetching\n : oldVal\n if (oldValue !== undefined) status.oldValue = oldValue\n }\n } else if (status) {\n status.set = 'update'\n }\n\n if (this.#hasOnInsert) {\n this.onInsert?.(v as V, k, v === oldVal ? 'update' : 'replace')\n }\n }\n if (ttl !== 0 && !this.#ttls) {\n this.#initializeTTLTracking()\n }\n if (this.#ttls) {\n if (!noUpdateTTL) {\n this.#setItemTTL(index, ttl, start)\n }\n if (status) this.#statusTTL(status, index)\n }\n if (!noDisposeOnSet && this.#hasDisposeAfter && this.#disposed) {\n const dt = this.#disposed\n let task: DisposeTask<K, V> | undefined\n while ((task = dt?.shift())) {\n this.#disposeAfter?.(...task)\n }\n }\n return this\n }\n\n /**\n * Evict the least recently used item, returning its value or\n * `undefined` if cache is empty.\n */\n pop(): V | undefined {\n try {\n while (this.#size) {\n const val = this.#valList[this.#head]\n this.#evict(true)\n if (this.#isBackgroundFetch(val)) {\n if (val.__staleWhileFetching) {\n return val.__staleWhileFetching\n }\n } else if (val !== undefined) {\n return val\n }\n }\n } finally {\n if (this.#hasDisposeAfter && this.#disposed) {\n const dt = this.#disposed\n let task: DisposeTask<K, V> | undefined\n while ((task = dt?.shift())) {\n this.#disposeAfter?.(...task)\n }\n }\n }\n }\n\n #evict(free: boolean) {\n const head = this.#head\n const k = this.#keyList[head] as K\n const v = this.#valList[head] as V\n if (this.#hasFetchMethod && this.#isBackgroundFetch(v)) {\n v.__abortController.abort(new Error('evicted'))\n } else if (this.#hasDispose || this.#hasDisposeAfter) {\n if (this.#hasDispose) {\n this.#dispose?.(v, k, 'evict')\n }\n if (this.#hasDisposeAfter) {\n this.#disposed?.push([v, k, 'evict'])\n }\n }\n this.#removeItemSize(head)\n if (this.#autopurgeTimers?.[head]) {\n clearTimeout(this.#autopurgeTimers[head])\n this.#autopurgeTimers[head] = undefined\n }\n // if we aren't about to use the index, then null these out\n if (free) {\n this.#keyList[head] = undefined\n this.#valList[head] = undefined\n this.#free.push(head)\n }\n if (this.#size === 1) {\n this.#head = this.#tail = 0 as Index\n this.#free.length = 0\n } else {\n this.#head = this.#next[head] as Index\n }\n this.#keyMap.delete(k)\n this.#size--\n return head\n }\n\n /**\n * Check if a key is in the cache, without updating the recency of use.\n * Will return false if the item is stale, even though it is technically\n * in the cache.\n *\n * Check if a key is in the cache, without updating the recency of\n * use. Age is updated if {@link LRUCache.OptionsBase.updateAgeOnHas} is set\n * to `true` in either the options or the constructor.\n *\n * Will return `false` if the item is stale, even though it is technically in\n * the cache. The difference can be determined (if it matters) by using a\n * `status` argument, and inspecting the `has` field.\n *\n * Will not update item age unless\n * {@link LRUCache.OptionsBase.updateAgeOnHas} is set.\n */\n has(k: K, hasOptions: LRUCache.HasOptions<K, V, FC> = {}) {\n const { updateAgeOnHas = this.updateAgeOnHas, status } = hasOptions\n const index = this.#keyMap.get(k)\n if (index !== undefined) {\n const v = this.#valList[index]\n if (\n this.#isBackgroundFetch(v) &&\n v.__staleWhileFetching === undefined\n ) {\n return false\n }\n if (!this.#isStale(index)) {\n if (updateAgeOnHas) {\n this.#updateItemAge(index)\n }\n if (status) {\n status.has = 'hit'\n this.#statusTTL(status, index)\n }\n return true\n } else if (status) {\n status.has = 'stale'\n this.#statusTTL(status, index)\n }\n } else if (status) {\n status.has = 'miss'\n }\n return false\n }\n\n /**\n * Like {@link LRUCache#get} but doesn't update recency or delete stale\n * items.\n *\n * Returns `undefined` if the item is stale, unless\n * {@link LRUCache.OptionsBase.allowStale} is set.\n */\n peek(k: K, peekOptions: LRUCache.PeekOptions<K, V, FC> = {}) {\n const { allowStale = this.allowStale } = peekOptions\n const index = this.#keyMap.get(k)\n if (index === undefined || (!allowStale && this.#isStale(index))) {\n return\n }\n const v = this.#valList[index]\n // either stale and allowed, or forcing a refresh of non-stale value\n return this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v\n }\n\n #backgroundFetch(\n k: K,\n index: Index | undefined,\n options: LRUCache.FetchOptions<K, V, FC>,\n context: any,\n ): BackgroundFetch<V> {\n const v = index === undefined ? undefined : this.#valList[index]\n if (this.#isBackgroundFetch(v)) {\n return v\n }\n\n const ac = new AC()\n const { signal } = options\n // when/if our AC signals, then stop listening to theirs.\n signal?.addEventListener('abort', () => ac.abort(signal.reason), {\n signal: ac.signal,\n })\n\n const fetchOpts = {\n signal: ac.signal,\n options,\n context,\n }\n\n const cb = (v: V | undefined, updateCache = false): V | undefined => {\n const { aborted } = ac.signal\n const ignoreAbort = options.ignoreFetchAbort && v !== undefined\n const proceed = options.ignoreFetchAbort ||\n !!(options.allowStaleOnFetchAbort && v !== undefined)\n if (options.status) {\n if (aborted && !updateCache) {\n options.status.fetchAborted = true\n options.status.fetchError = ac.signal.reason\n if (ignoreAbort) options.status.fetchAbortIgnored = true\n } else {\n options.status.fetchResolved = true\n }\n }\n if (aborted && !ignoreAbort && !updateCache) {\n return fetchFail(ac.signal.reason, proceed)\n }\n // either we didn't abort, and are still here, or we did, and ignored\n const bf = p as BackgroundFetch<V>\n // if nothing else has been written there but we're set to update the\n // cache and ignore the abort, or if it's still pending on this specific\n // background request, then write it to the cache.\n const vl = this.#valList[index as Index]\n if (vl === p || (ignoreAbort && updateCache && vl === undefined)) {\n if (v === undefined) {\n if (bf.__staleWhileFetching !== undefined) {\n this.#valList[index as Index] = bf.__staleWhileFetching\n } else {\n this.#delete(k, 'fetch')\n }\n } else {\n if (options.status) options.status.fetchUpdated = true\n this.set(k, v, fetchOpts.options)\n }\n }\n return v\n }\n\n const eb = (er: any) => {\n if (options.status) {\n options.status.fetchRejected = true\n options.status.fetchError = er\n }\n // do not pass go, do not collect $200\n return fetchFail(er, false)\n }\n\n const fetchFail = (er: any, proceed: boolean): V | undefined => {\n const { aborted } = ac.signal\n const allowStaleAborted = aborted && options.allowStaleOnFetchAbort\n const allowStale =\n allowStaleAborted || options.allowStaleOnFetchRejection\n const noDelete = allowStale || options.noDeleteOnFetchRejection\n const bf = p as BackgroundFetch<V>\n if (this.#valList[index as Index] === p) {\n // if we allow stale on fetch rejections, then we need to ensure that\n // the stale value is not removed from the cache when the fetch fails.\n const del = !noDelete ||\n !proceed && bf.__staleWhileFetching === undefined\n if (del) {\n this.#delete(k, 'fetch')\n } else if (!allowStaleAborted) {\n // still replace the *promise* with the stale value,\n // since we are done with the promise at this point.\n // leave it untouched if we're still waiting for an\n // aborted background fetch that hasn't yet returned.\n this.#valList[index as Index] = bf.__staleWhileFetching\n }\n }\n if (allowStale) {\n if (options.status && bf.__staleWhileFetching !== undefined) {\n options.status.returnedStale = true\n }\n return bf.__staleWhileFetching\n } else if (bf.__returned === bf) {\n throw er\n }\n }\n\n const pcall = (\n res: (v: V | undefined) => void,\n rej: (e: any) => void,\n ) => {\n const fmp = this.#fetchMethod?.(k, v, fetchOpts)\n if (fmp && fmp instanceof Promise) {\n fmp.then(v => res(v === undefined ? undefined : v), rej)\n }\n // ignored, we go until we finish, regardless.\n // defer check until we are actually aborting,\n // so fetchMethod can override.\n ac.signal.addEventListener('abort', () => {\n if (!options.ignoreFetchAbort || options.allowStaleOnFetchAbort) {\n res(undefined)\n // when it eventually resolves, update the cache.\n if (options.allowStaleOnFetchAbort) {\n res = v => cb(v, true)\n }\n }\n })\n }\n\n if (options.status) options.status.fetchDispatched = true\n const p = new Promise(pcall).then(cb, eb)\n const bf: BackgroundFetch<V> = Object.assign(p, {\n __abortController: ac,\n __staleWhileFetching: v,\n __returned: undefined,\n })\n\n if (index === undefined) {\n // internal, don't expose status.\n this.set(k, bf, { ...fetchOpts.options, status: undefined })\n index = this.#keyMap.get(k)\n } else {\n this.#valList[index] = bf\n }\n return bf\n }\n\n #isBackgroundFetch(p: any): p is BackgroundFetch<V> {\n if (!this.#hasFetchMethod) return false\n const b = p as BackgroundFetch<V>\n return (\n !!b &&\n b instanceof Promise &&\n b.hasOwnProperty('__staleWhileFetching') &&\n b.__abortController instanceof AC\n )\n }\n\n /**\n * Make an asynchronous cached fetch using the\n * {@link LRUCache.OptionsBase.fetchMethod} function.\n *\n * If the value is in the cache and not stale, then the returned\n * Promise resolves to the value.\n *\n * If not in the cache, or beyond its TTL staleness, then\n * `fetchMethod(key, staleValue, { options, signal, context })` is\n * called, and the value returned will be added to the cache once\n * resolved.\n *\n * If called with `allowStale`, and an asynchronous fetch is\n * currently in progress to reload a stale value, then the former\n * stale value will be returned.\n *\n * If called with `forceRefresh`, then the cached item will be\n * re-fetched, even if it is not stale. However, if `allowStale` is also\n * set, then the old value will still be returned. This is useful\n * in cases where you want to force a reload of a cached value. If\n * a background fetch is already in progress, then `forceRefresh`\n * has no effect.\n *\n * If multiple fetches for the same key are issued, then they will all be\n * coalesced into a single call to fetchMethod.\n *\n * Note that this means that handling options such as\n * {@link LRUCache.OptionsBase.allowStaleOnFetchAbort},\n * {@link LRUCache.FetchOptions.signal},\n * and {@link LRUCache.OptionsBase.allowStaleOnFetchRejection} will be\n * determined by the FIRST fetch() call for a given key.\n *\n * This is a known (fixable) shortcoming which will be addresed on when\n * someone complains about it, as the fix would involve added complexity and\n * may not be worth the costs for this edge case.\n *\n * If {@link LRUCache.OptionsBase.fetchMethod} is not specified, then this is\n * effectively an alias for `Promise.resolve(cache.get(key))`.\n *\n * When the fetch method resolves to a value, if the fetch has not\n * been aborted due to deletion, eviction, or being overwritten,\n * then it is added to the cache using the options provided.\n *\n * If the key is evicted or deleted before the `fetchMethod`\n * resolves, then the AbortSignal passed to the `fetchMethod` will\n * receive an `abort` event, and the promise returned by `fetch()`\n * will reject with the reason for the abort.\n *\n * If a `signal` is passed to the `fetch()` call, then aborting the\n * signal will abort the fetch and cause the `fetch()` promise to\n * reject with the reason provided.\n *\n * **Setting `context`**\n *\n * If an `FC` type is set to a type other than `unknown`, `void`, or\n * `undefined` in the {@link LRUCache} constructor, then all\n * calls to `cache.fetch()` _must_ provide a `context` option. If\n * set to `undefined` or `void`, then calls to fetch _must not_\n * provide a `context` option.\n *\n * The `context` param allows you to provide arbitrary data that\n * might be relevant in the course of fetching the data. It is only\n * relevant for the course of a single `fetch()` operation, and\n * discarded afterwards.\n *\n * **Note: `fetch()` calls are inflight-unique**\n *\n * If you call `fetch()` multiple times with the same key value,\n * then every call after the first will resolve on the same\n * promise<sup>1</sup>,\n * _even if they have different settings that would otherwise change\n * the behavior of the fetch_, such as `noDeleteOnFetchRejection`\n * or `ignoreFetchAbort`.\n *\n * In most cases, this is not a problem (in fact, only fetching\n * something once is what you probably want, if you're caching in\n * the first place). If you are changing the fetch() options\n * dramatically between runs, there's a good chance that you might\n * be trying to fit divergent semantics into a single object, and\n * would be better off with multiple cache instances.\n *\n * **1**: Ie, they're not the \"same Promise\", but they resolve at\n * the same time, because they're both waiting on the same\n * underlying fetchMethod response.\n */\n\n fetch(\n k: K,\n fetchOptions: unknown extends FC ? LRUCache.FetchOptions<K, V, FC>\n : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V>\n : LRUCache.FetchOptionsWithContext<K, V, FC>,\n ): Promise<undefined | V>\n\n // this overload not allowed if context is required\n fetch(\n k: unknown extends FC ? K\n : FC extends undefined | void ? K\n : never,\n fetchOptions?: unknown extends FC ? LRUCache.FetchOptions<K, V, FC>\n : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V>\n : never,\n ): Promise<undefined | V>\n\n async fetch(\n k: K,\n fetchOptions: LRUCache.FetchOptions<K, V, FC> = {},\n ): Promise<undefined | V> {\n const {\n // get options\n allowStale = this.allowStale,\n updateAgeOnGet = this.updateAgeOnGet,\n noDeleteOnStaleGet = this.noDeleteOnStaleGet,\n // set options\n ttl = this.ttl,\n noDisposeOnSet = this.noDisposeOnSet,\n size = 0,\n sizeCalculation = this.sizeCalculation,\n noUpdateTTL = this.noUpdateTTL,\n // fetch exclusive options\n noDeleteOnFetchRejection = this.noDeleteOnFetchRejection,\n allowStaleOnFetchRejection = this.allowStaleOnFetchRejection,\n ignoreFetchAbort = this.ignoreFetchAbort,\n allowStaleOnFetchAbort = this.allowStaleOnFetchAbort,\n context,\n forceRefresh = false,\n status,\n signal,\n } = fetchOptions\n\n if (!this.#hasFetchMethod) {\n if (status) status.fetch = 'get'\n return this.get(k, {\n allowStale,\n updateAgeOnGet,\n noDeleteOnStaleGet,\n status,\n })\n }\n\n const options = {\n allowStale,\n updateAgeOnGet,\n noDeleteOnStaleGet,\n ttl,\n noDisposeOnSet,\n size,\n sizeCalculation,\n noUpdateTTL,\n noDeleteOnFetchRejection,\n allowStaleOnFetchRejection,\n allowStaleOnFetchAbort,\n ignoreFetchAbort,\n status,\n signal,\n }\n\n let index = this.#keyMap.get(k)\n if (index === undefined) {\n if (status) status.fetch = 'miss'\n const p = this.#backgroundFetch(k, index, options, context)\n return (p.__returned = p)\n } else {\n // in cache, maybe already fetching\n const v = this.#valList[index]\n if (this.#isBackgroundFetch(v)) {\n const stale = allowStale && v.__staleWhileFetching !== undefined\n if (status) {\n status.fetch = 'inflight'\n if (stale) status.returnedStale = true\n }\n return stale ? v.__staleWhileFetching : (v.__returned = v)\n }\n\n // if we force a refresh, that means do NOT serve the cached value,\n // unless we are already in the process of refreshing the cache.\n const isStale = this.#isStale(index)\n if (!forceRefresh && !isStale) {\n if (status) status.fetch = 'hit'\n this.#moveToTail(index)\n if (updateAgeOnGet) {\n this.#updateItemAge(index)\n }\n if (status) this.#statusTTL(status, index)\n return v\n }\n\n // ok, it is stale or a forced refresh, and not already fetching.\n // refresh the cache.\n const p = this.#backgroundFetch(k, index, options, context)\n const hasStale = p.__staleWhileFetching !== undefined\n const staleVal = hasStale && allowStale\n if (status) {\n status.fetch = isStale ? 'stale' : 'refresh'\n if (staleVal && isStale) status.returnedStale = true\n }\n return staleVal ? p.__staleWhileFetching : (p.__returned = p)\n }\n }\n\n /**\n * In some cases, `cache.fetch()` may resolve to `undefined`, either because\n * a {@link LRUCache.OptionsBase#fetchMethod} was not provided (turning\n * `cache.fetch(k)` into just an async wrapper around `cache.get(k)`) or\n * because `ignoreFetchAbort` was specified (either to the constructor or\n * in the {@link LRUCache.FetchOptions}). Also, the\n * {@link LRUCache.OptionsBase.fetchMethod} may return `undefined` or `void`, making\n * the test even more complicated.\n *\n * Because inferring the cases where `undefined` might be returned are so\n * cumbersome, but testing for `undefined` can also be annoying, this method\n * can be used, which will reject if `this.fetch()` resolves to undefined.\n */\n forceFetch(\n k: K,\n fetchOptions: unknown extends FC ? LRUCache.FetchOptions<K, V, FC>\n : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V>\n : LRUCache.FetchOptionsWithContext<K, V, FC>,\n ): Promise<V>\n // this overload not allowed if context is required\n forceFetch(\n k: unknown extends FC ? K\n : FC extends undefined | void ? K\n : never,\n fetchOptions?: unknown extends FC ? LRUCache.FetchOptions<K, V, FC>\n : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V>\n : never,\n ): Promise<V>\n async forceFetch(\n k: K,\n fetchOptions: LRUCache.FetchOptions<K, V, FC> = {},\n ): Promise<V> {\n const v = await this.fetch(\n k,\n fetchOptions as unknown extends FC ? LRUCache.FetchOptions<K, V, FC>\n : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V>\n : LRUCache.FetchOptionsWithContext<K, V, FC>,\n )\n if (v === undefined) throw new Error('fetch() returned undefined')\n return v\n }\n\n /**\n * If the key is found in the cache, then this is equivalent to\n * {@link LRUCache#get}. If not, in the cache, then calculate the value using\n * the {@link LRUCache.OptionsBase.memoMethod}, and add it to the cache.\n *\n * If an `FC` type is set to a type other than `unknown`, `void`, or\n * `undefined` in the LRUCache constructor, then all calls to `cache.memo()`\n * _must_ provide a `context` option. If set to `undefined` or `void`, then\n * calls to memo _must not_ provide a `context` option.\n *\n * The `context` param allows you to provide arbitrary data that might be\n * relevant in the course of fetching the data. It is only relevant for the\n * course of a single `memo()` operation, and discarded afterwards.\n */\n memo(\n k: K,\n memoOptions: unknown extends FC ? LRUCache.MemoOptions<K, V, FC>\n : FC extends undefined | void ? LRUCache.MemoOptionsNoContext<K, V>\n : LRUCache.MemoOptionsWithContext<K, V, FC>,\n ): V\n // this overload not allowed if context is required\n memo(\n k: unknown extends FC ? K\n : FC extends undefined | void ? K\n : never,\n memoOptions?: unknown extends FC ? LRUCache.MemoOptions<K, V, FC>\n : FC extends undefined | void ? LRUCache.MemoOptionsNoContext<K, V>\n : never,\n ): V\n memo(k: K, memoOptions: LRUCache.MemoOptions<K, V, FC> = {}) {\n const memoMethod = this.#memoMethod\n if (!memoMethod) {\n throw new Error('no memoMethod provided to constructor')\n }\n const { context, forceRefresh, ...options } = memoOptions\n const v = this.get(k, options)\n if (!forceRefresh && v !== undefined) return v\n const vv = memoMethod(k, v, {\n options,\n context,\n } as LRUCache.MemoizerOptions<K, V, FC>)\n this.set(k, vv, options)\n return vv\n }\n\n /**\n * Return a value from the cache. Will update the recency of the cache\n * entry found.\n *\n * If the key is not found, get() will return `undefined`.\n */\n get(k: K, getOptions: LRUCache.GetOptions<K, V, FC> = {}) {\n const {\n allowStale = this.allowStale,\n updateAgeOnGet = this.updateAgeOnGet,\n noDeleteOnStaleGet = this.noDeleteOnStaleGet,\n status,\n } = getOptions\n const index = this.#keyMap.get(k)\n if (index !== undefined) {\n const value = this.#valList[index]\n const fetching = this.#isBackgroundFetch(value)\n if (status) this.#statusTTL(status, index)\n if (this.#isStale(index)) {\n if (status) status.get = 'stale'\n // delete only if not an in-flight background fetch\n if (!fetching) {\n if (!noDeleteOnStaleGet) {\n this.#delete(k, 'expire')\n }\n if (status && allowStale) status.returnedStale = true\n return allowStale ? value : undefined\n } else {\n if (\n status &&\n allowStale &&\n value.__staleWhileFetching !== undefined\n ) {\n status.returnedStale = true\n }\n return allowStale ? value.__staleWhileFetching : undefined\n }\n } else {\n if (status) status.get = 'hit'\n // if we're currently fetching it, we don't actually have it yet\n // it's not stale, which means this isn't a staleWhileRefetching.\n // If it's not stale, and fetching, AND has a __staleWhileFetching\n // value, then that means the user fetched with {forceRefresh:true},\n // so it's safe to return that value.\n if (fetching) {\n return value.__staleWhileFetching\n }\n this.#moveToTail(index)\n if (updateAgeOnGet) {\n this.#updateItemAge(index)\n }\n return value\n }\n } else if (status) {\n status.get = 'miss'\n }\n }\n\n #connect(p: Index, n: Index) {\n this.#prev[n] = p\n this.#next[p] = n\n }\n\n #moveToTail(index: Index): void {\n // if tail already, nothing to do\n // if head, move head to next[index]\n // else\n // move next[prev[index]] to next[index] (head has no prev)\n // move prev[next[index]] to prev[index]\n // prev[index] = tail\n // next[tail] = index\n // tail = index\n if (index !== this.#tail) {\n if (index === this.#head) {\n this.#head = this.#next[index] as Index\n } else {\n this.#connect(\n this.#prev[index] as Index,\n this.#next[index] as Index,\n )\n }\n this.#connect(this.#tail, index)\n this.#tail = index\n }\n }\n\n /**\n * Deletes a key out of the cache.\n *\n * Returns true if the key was deleted, false otherwise.\n */\n delete(k: K) {\n return this.#delete(k, 'delete')\n }\n\n #delete(k: K, reason: LRUCache.DisposeReason) {\n let deleted = false\n if (this.#size !== 0) {\n const index = this.#keyMap.get(k)\n if (index !== undefined) {\n if (this.#autopurgeTimers?.[index]) {\n clearTimeout(this.#autopurgeTimers?.[index])\n this.#autopurgeTimers[index] = undefined\n }\n deleted = true\n if (this.#size === 1) {\n this.#clear(reason)\n } else {\n this.#removeItemSize(index)\n const v = this.#valList[index]\n if (this.#isBackgroundFetch(v)) {\n v.__abortController.abort(new Error('deleted'))\n } else if (this.#hasDispose || this.#hasDisposeAfter) {\n if (this.#hasDispose) {\n this.#dispose?.(v as V, k, reason)\n }\n if (this.#hasDisposeAfter) {\n this.#disposed?.push([v as V, k, reason])\n }\n }\n this.#keyMap.delete(k)\n this.#keyList[index] = undefined\n this.#valList[index] = undefined\n if (index === this.#tail) {\n this.#tail = this.#prev[index] as Index\n } else if (index === this.#head) {\n this.#head = this.#next[index] as Index\n } else {\n const pi = this.#prev[index] as number\n this.#next[pi] = this.#next[index] as number\n const ni = this.#next[index] as number\n this.#prev[ni] = this.#prev[index] as number\n }\n this.#size--\n this.#free.push(index)\n }\n }\n }\n if (this.#hasDisposeAfter && this.#disposed?.length) {\n const dt = this.#disposed\n let task: DisposeTask<K, V> | undefined\n while ((task = dt?.shift())) {\n this.#disposeAfter?.(...task)\n }\n }\n return deleted\n }\n\n /**\n * Clear the cache entirely, throwing away all values.\n */\n clear() {\n return this.#clear('delete')\n }\n #clear(reason: LRUCache.DisposeReason) {\n for (const index of this.#rindexes({ allowStale: true })) {\n const v = this.#valList[index]\n if (this.#isBackgroundFetch(v)) {\n v.__abortController.abort(new Error('deleted'))\n } else {\n const k = this.#keyList[index]\n if (this.#hasDispose) {\n this.#dispose?.(v as V, k as K, reason)\n }\n if (this.#hasDisposeAfter) {\n this.#disposed?.push([v as V, k as K, reason])\n }\n }\n }\n\n this.#keyMap.clear()\n this.#valList.fill(undefined)\n this.#keyList.fill(undefined)\n if (this.#ttls && this.#starts) {\n this.#ttls.fill(0)\n this.#starts.fill(0)\n for (const t of this.#autopurgeTimers ?? []) {\n if (t !== undefined) clearTimeout(t)\n }\n this.#autopurgeTimers?.fill(undefined)\n }\n if (this.#sizes) {\n this.#sizes.fill(0)\n }\n this.#head = 0 as Index\n this.#tail = 0 as Index\n this.#free.length = 0\n this.#calculatedSize = 0\n this.#size = 0\n if (this.#hasDisposeAfter && this.#disposed) {\n const dt = this.#disposed\n let task: DisposeTask<K, V> | undefined\n while ((task = dt?.shift())) {\n this.#disposeAfter?.(...task)\n }\n }\n }\n}\n","import { LRUCache } from 'lru-cache'\nimport { posix, win32 } from 'node:path'\n\nimport { fileURLToPath } from 'node:url'\n\nimport {\n lstatSync,\n readdir as readdirCB,\n readdirSync,\n readlinkSync,\n realpathSync as rps,\n} from 'fs'\nimport * as actualFS from 'node:fs'\n\nconst realpathSync = rps.native\n// TODO: test perf of fs/promises realpath vs realpathCB,\n// since the promises one uses realpath.native\n\nimport { lstat, readdir, readlink, realpath } from 'node:fs/promises'\n\nimport { Minipass } from 'minipass'\nimport type { Dirent, Stats } from 'node:fs'\n\n/**\n * An object that will be used to override the default `fs`\n * methods. Any methods that are not overridden will use Node's\n * built-in implementations.\n *\n * - lstatSync\n * - readdir (callback `withFileTypes` Dirent variant, used for\n * readdirCB and most walks)\n * - readdirSync\n * - readlinkSync\n * - realpathSync\n * - promises: Object containing the following async methods:\n * - lstat\n * - readdir (Dirent variant only)\n * - readlink\n * - realpath\n */\nexport interface FSOption {\n lstatSync?: (path: string) => Stats\n readdir?: (\n path: string,\n options: { withFileTypes: true },\n cb: (er: NodeJS.ErrnoException | null, entries?: Dirent[]) => any,\n ) => void\n readdirSync?: (\n path: string,\n options: { withFileTypes: true },\n ) => Dirent[]\n readlinkSync?: (path: string) => string\n realpathSync?: (path: string) => string\n promises?: {\n lstat?: (path: string) => Promise<Stats>\n readdir?: (\n path: string,\n options: { withFileTypes: true },\n ) => Promise<Dirent[]>\n readlink?: (path: string) => Promise<string>\n realpath?: (path: string) => Promise<string>\n [k: string]: any\n }\n [k: string]: any\n}\n\ninterface FSValue {\n lstatSync: (path: string) => Stats\n readdir: (\n path: string,\n options: { withFileTypes: true },\n cb: (er: NodeJS.ErrnoException | null, entries?: Dirent[]) => any,\n ) => void\n readdirSync: (path: string, options: { withFileTypes: true }) => Dirent[]\n readlinkSync: (path: string) => string\n realpathSync: (path: string) => string\n promises: {\n lstat: (path: string) => Promise<Stats>\n readdir: (\n path: string,\n options: { withFileTypes: true },\n ) => Promise<Dirent[]>\n readlink: (path: string) => Promise<string>\n realpath: (path: string) => Promise<string>\n [k: string]: any\n }\n [k: string]: any\n}\n\nconst defaultFS: FSValue = {\n lstatSync,\n readdir: readdirCB,\n readdirSync,\n readlinkSync,\n realpathSync,\n promises: {\n lstat,\n readdir,\n readlink,\n realpath,\n },\n}\n\n// if they just gave us require('fs') then use our default\nconst fsFromOption = (fsOption?: FSOption): FSValue =>\n !fsOption || fsOption === defaultFS || fsOption === actualFS ?\n defaultFS\n : {\n ...defaultFS,\n ...fsOption,\n promises: {\n ...defaultFS.promises,\n ...(fsOption.promises || {}),\n },\n }\n\n// turn something like //?/c:/ into c:\\\nconst uncDriveRegexp = /^\\\\\\\\\\?\\\\([a-z]:)\\\\?$/i\nconst uncToDrive = (rootPath: string): string =>\n rootPath.replace(/\\//g, '\\\\').replace(uncDriveRegexp, '$1\\\\')\n\n// windows paths are separated by either / or \\\nconst eitherSep = /[\\\\\\/]/\n\nconst UNKNOWN = 0 // may not even exist, for all we know\nconst IFIFO = 0b0001\nconst IFCHR = 0b0010\nconst IFDIR = 0b0100\nconst IFBLK = 0b0110\nconst IFREG = 0b1000\nconst IFLNK = 0b1010\nconst IFSOCK = 0b1100\nconst IFMT = 0b1111\n\nexport type Type =\n | 'Unknown'\n | 'FIFO'\n | 'CharacterDevice'\n | 'Directory'\n | 'BlockDevice'\n | 'File'\n | 'SymbolicLink'\n | 'Socket'\n\n// mask to unset low 4 bits\nconst IFMT_UNKNOWN = ~IFMT\n\n// set after successfully calling readdir() and getting entries.\nconst READDIR_CALLED = 0b0000_0001_0000\n// set after a successful lstat()\nconst LSTAT_CALLED = 0b0000_0010_0000\n// set if an entry (or one of its parents) is definitely not a dir\nconst ENOTDIR = 0b0000_0100_0000\n// set if an entry (or one of its parents) does not exist\n// (can also be set on lstat errors like EACCES or ENAMETOOLONG)\nconst ENOENT = 0b0000_1000_0000\n// cannot have child entries -- also verify &IFMT is either IFDIR or IFLNK\n// set if we fail to readlink\nconst ENOREADLINK = 0b0001_0000_0000\n// set if we know realpath() will fail\nconst ENOREALPATH = 0b0010_0000_0000\n\nconst ENOCHILD = ENOTDIR | ENOENT | ENOREALPATH\nconst TYPEMASK = 0b0011_1111_1111\n\nconst entToType = (s: Dirent | Stats) =>\n s.isFile() ? IFREG\n : s.isDirectory() ? IFDIR\n : s.isSymbolicLink() ? IFLNK\n : s.isCharacterDevice() ? IFCHR\n : s.isBlockDevice() ? IFBLK\n : s.isSocket() ? IFSOCK\n : s.isFIFO() ? IFIFO\n : UNKNOWN\n\n// normalize unicode path names\nconst normalizeCache = new LRUCache<string, string>({ max: 2 ** 12 })\nconst normalize = (s: string) => {\n const c = normalizeCache.get(s)\n if (c) return c\n const n = s.normalize('NFKD')\n normalizeCache.set(s, n)\n return n\n}\n\nconst normalizeNocaseCache = new LRUCache<string, string>({ max: 2 ** 12 })\nconst normalizeNocase = (s: string) => {\n const c = normalizeNocaseCache.get(s)\n if (c) return c\n const n = normalize(s.toLowerCase())\n normalizeNocaseCache.set(s, n)\n return n\n}\n\n/**\n * Options that may be provided to the Path constructor\n */\nexport interface PathOpts {\n fullpath?: string\n relative?: string\n relativePosix?: string\n parent?: PathBase\n /**\n * See {@link FSOption}\n */\n fs?: FSOption\n}\n\n/**\n * An LRUCache for storing resolved path strings or Path objects.\n * @internal\n */\nexport class ResolveCache extends LRUCache<string, string> {\n constructor() {\n super({ max: 256 })\n }\n}\n\n// In order to prevent blowing out the js heap by allocating hundreds of\n// thousands of Path entries when walking extremely large trees, the \"children\"\n// in this tree are represented by storing an array of Path entries in an\n// LRUCache, indexed by the parent. At any time, Path.children() may return an\n// empty array, indicating that it doesn't know about any of its children, and\n// thus has to rebuild that cache. This is fine, it just means that we don't\n// benefit as much from having the cached entries, but huge directory walks\n// don't blow out the stack, and smaller ones are still as fast as possible.\n//\n//It does impose some complexity when building up the readdir data, because we\n//need to pass a reference to the children array that we started with.\n\n/**\n * an LRUCache for storing child entries.\n * @internal\n */\nexport class ChildrenCache extends LRUCache<PathBase, Children> {\n constructor(maxSize: number = 16 * 1024) {\n super({\n maxSize,\n // parent + children\n sizeCalculation: a => a.length + 1,\n })\n }\n}\n\n/**\n * Array of Path objects, plus a marker indicating the first provisional entry\n *\n * @internal\n */\nexport type Children = PathBase[] & { provisional: number }\n\nconst setAsCwd = Symbol('PathScurry setAsCwd')\n\n/**\n * Path objects are sort of like a super-powered\n * {@link https://nodejs.org/docs/latest/api/fs.html#class-fsdirent fs.Dirent}\n *\n * Each one represents a single filesystem entry on disk, which may or may not\n * exist. It includes methods for reading various types of information via\n * lstat, readlink, and readdir, and caches all information to the greatest\n * degree possible.\n *\n * Note that fs operations that would normally throw will instead return an\n * \"empty\" value. This is in order to prevent excessive overhead from error\n * stack traces.\n */\nexport abstract class PathBase implements Dirent {\n /**\n * the basename of this path\n *\n * **Important**: *always* test the path name against any test string\n * usingthe {@link isNamed} method, and not by directly comparing this\n * string. Otherwise, unicode path strings that the system sees as identical\n * will not be properly treated as the same path, leading to incorrect\n * behavior and possible security issues.\n */\n name: string\n /**\n * the Path entry corresponding to the path root.\n *\n * @internal\n */\n root: PathBase\n /**\n * All roots found within the current PathScurry family\n *\n * @internal\n */\n roots: { [k: string]: PathBase }\n /**\n * a reference to the parent path, or undefined in the case of root entries\n *\n * @internal\n */\n parent?: PathBase\n /**\n * boolean indicating whether paths are compared case-insensitively\n * @internal\n */\n nocase: boolean\n\n /**\n * boolean indicating that this path is the current working directory\n * of the PathScurry collection that contains it.\n */\n isCWD: boolean = false\n\n /**\n * the string or regexp used to split paths. On posix, it is `'/'`, and on\n * windows it is a RegExp matching either `'/'` or `'\\\\'`\n */\n abstract splitSep: string | RegExp\n /**\n * The path separator string to use when joining paths\n */\n abstract sep: string\n\n // potential default fs override\n #fs: FSValue\n\n // Stats fields\n #dev?: number\n get dev() {\n return this.#dev\n }\n #mode?: number\n get mode() {\n return this.#mode\n }\n #nlink?: number\n get nlink() {\n return this.#nlink\n }\n #uid?: number\n get uid() {\n return this.#uid\n }\n #gid?: number\n get gid() {\n return this.#gid\n }\n #rdev?: number\n get rdev() {\n return this.#rdev\n }\n #blksize?: number\n get blksize() {\n return this.#blksize\n }\n #ino?: number\n get ino() {\n return this.#ino\n }\n #size?: number\n get size() {\n return this.#size\n }\n #blocks?: number\n get blocks() {\n return this.#blocks\n }\n #atimeMs?: number\n get atimeMs() {\n return this.#atimeMs\n }\n #mtimeMs?: number\n get mtimeMs() {\n return this.#mtimeMs\n }\n #ctimeMs?: number\n get ctimeMs() {\n return this.#ctimeMs\n }\n #birthtimeMs?: number\n get birthtimeMs() {\n return this.#birthtimeMs\n }\n #atime?: Date\n get atime() {\n return this.#atime\n }\n #mtime?: Date\n get mtime() {\n return this.#mtime\n }\n #ctime?: Date\n get ctime() {\n return this.#ctime\n }\n #birthtime?: Date\n get birthtime() {\n return this.#birthtime\n }\n\n #matchName: string\n #depth?: number\n #fullpath?: string\n #fullpathPosix?: string\n #relative?: string\n #relativePosix?: string\n #type: number\n #children: ChildrenCache\n #linkTarget?: PathBase\n #realpath?: PathBase\n\n /**\n * This property is for compatibility with the Dirent class as of\n * Node v20, where Dirent['parentPath'] refers to the path of the\n * directory that was passed to readdir. For root entries, it's the path\n * to the entry itself.\n */\n get parentPath(): string {\n return (this.parent || this).fullpath()\n }\n\n /* c8 ignore start */\n /**\n * Deprecated alias for Dirent['parentPath'] Somewhat counterintuitively,\n * this property refers to the *parent* path, not the path object itself.\n *\n * @deprecated\n */\n get path(): string {\n return this.parentPath\n }\n /* c8 ignore stop */\n\n /**\n * Do not create new Path objects directly. They should always be accessed\n * via the PathScurry class or other methods on the Path class.\n *\n * @internal\n */\n constructor(\n name: string,\n type: number = UNKNOWN,\n root: PathBase | undefined,\n roots: { [k: string]: PathBase },\n nocase: boolean,\n children: ChildrenCache,\n opts: PathOpts,\n ) {\n this.name = name\n this.#matchName = nocase ? normalizeNocase(name) : normalize(name)\n this.#type = type & TYPEMASK\n this.nocase = nocase\n this.roots = roots\n this.root = root || this\n this.#children = children\n this.#fullpath = opts.fullpath\n this.#relative = opts.relative\n this.#relativePosix = opts.relativePosix\n this.parent = opts.parent\n if (this.parent) {\n this.#fs = this.parent.#fs\n } else {\n this.#fs = fsFromOption(opts.fs)\n }\n }\n\n /**\n * Returns the depth of the Path object from its root.\n *\n * For example, a path at `/foo/bar` would have a depth of 2.\n */\n depth(): number {\n if (this.#depth !== undefined) return this.#depth\n if (!this.parent) return (this.#depth = 0)\n return (this.#depth = this.parent.depth() + 1)\n }\n\n /**\n * @internal\n */\n abstract getRootString(path: string): string\n /**\n * @internal\n */\n abstract getRoot(rootPath: string): PathBase\n /**\n * @internal\n */\n abstract newChild(name: string, type?: number, opts?: PathOpts): PathBase\n\n /**\n * @internal\n */\n childrenCache() {\n return this.#children\n }\n\n /**\n * Get the Path object referenced by the string path, resolved from this Path\n */\n resolve(path?: string): PathBase {\n if (!path) {\n return this\n }\n const rootPath = this.getRootString(path)\n const dir = path.substring(rootPath.length)\n const dirParts = dir.split(this.splitSep)\n const result: PathBase =\n rootPath ?\n this.getRoot(rootPath).#resolveParts(dirParts)\n : this.#resolveParts(dirParts)\n return result\n }\n\n #resolveParts(dirParts: string[]) {\n let p: PathBase = this\n for (const part of dirParts) {\n p = p.child(part)\n }\n return p\n }\n\n /**\n * Returns the cached children Path objects, if still available. If they\n * have fallen out of the cache, then returns an empty array, and resets the\n * READDIR_CALLED bit, so that future calls to readdir() will require an fs\n * lookup.\n *\n * @internal\n */\n children(): Children {\n const cached = this.#children.get(this)\n if (cached) {\n return cached\n }\n const children: Children = Object.assign([], { provisional: 0 })\n this.#children.set(this, children)\n this.#type &= ~READDIR_CALLED\n return children\n }\n\n /**\n * Resolves a path portion and returns or creates the child Path.\n *\n * Returns `this` if pathPart is `''` or `'.'`, or `parent` if pathPart is\n * `'..'`.\n *\n * This should not be called directly. If `pathPart` contains any path\n * separators, it will lead to unsafe undefined behavior.\n *\n * Use `Path.resolve()` instead.\n *\n * @internal\n */\n child(pathPart: string, opts?: PathOpts): PathBase {\n if (pathPart === '' || pathPart === '.') {\n return this\n }\n if (pathPart === '..') {\n return this.parent || this\n }\n\n // find the child\n const children = this.children()\n const name =\n this.nocase ? normalizeNocase(pathPart) : normalize(pathPart)\n for (const p of children) {\n if (p.#matchName === name) {\n return p\n }\n }\n\n // didn't find it, create provisional child, since it might not\n // actually exist. If we know the parent isn't a dir, then\n // in fact it CAN'T exist.\n const s = this.parent ? this.sep : ''\n const fullpath =\n this.#fullpath ? this.#fullpath + s + pathPart : undefined\n const pchild = this.newChild(pathPart, UNKNOWN, {\n ...opts,\n parent: this,\n fullpath,\n })\n\n if (!this.canReaddir()) {\n pchild.#type |= ENOENT\n }\n\n // don't have to update provisional, because if we have real children,\n // then provisional is set to children.length, otherwise a lower number\n children.push(pchild)\n return pchild\n }\n\n /**\n * The relative path from the cwd. If it does not share an ancestor with\n * the cwd, then this ends up being equivalent to the fullpath()\n */\n relative(): string {\n if (this.isCWD) return ''\n if (this.#relative !== undefined) {\n return this.#relative\n }\n const name = this.name\n const p = this.parent\n if (!p) {\n return (this.#relative = this.name)\n }\n const pv = p.relative()\n return pv + (!pv || !p.parent ? '' : this.sep) + name\n }\n\n /**\n * The relative path from the cwd, using / as the path separator.\n * If it does not share an ancestor with\n * the cwd, then this ends up being equivalent to the fullpathPosix()\n * On posix systems, this is identical to relative().\n */\n relativePosix(): string {\n if (this.sep === '/') return this.relative()\n if (this.isCWD) return ''\n if (this.#relativePosix !== undefined) return this.#relativePosix\n const name = this.name\n const p = this.parent\n if (!p) {\n return (this.#relativePosix = this.fullpathPosix())\n }\n const pv = p.relativePosix()\n return pv + (!pv || !p.parent ? '' : '/') + name\n }\n\n /**\n * The fully resolved path string for this Path entry\n */\n fullpath(): string {\n if (this.#fullpath !== undefined) {\n return this.#fullpath\n }\n const name = this.name\n const p = this.parent\n if (!p) {\n return (this.#fullpath = this.name)\n }\n const pv = p.fullpath()\n const fp = pv + (!p.parent ? '' : this.sep) + name\n return (this.#fullpath = fp)\n }\n\n /**\n * On platforms other than windows, this is identical to fullpath.\n *\n * On windows, this is overridden to return the forward-slash form of the\n * full UNC path.\n */\n fullpathPosix(): string {\n if (this.#fullpathPosix !== undefined) return this.#fullpathPosix\n if (this.sep === '/') return (this.#fullpathPosix = this.fullpath())\n if (!this.parent) {\n const p = this.fullpath().replace(/\\\\/g, '/')\n if (/^[a-z]:\\//i.test(p)) {\n return (this.#fullpathPosix = `//?/${p}`)\n } else {\n return (this.#fullpathPosix = p)\n }\n }\n const p = this.parent\n const pfpp = p.fullpathPosix()\n const fpp = pfpp + (!pfpp || !p.parent ? '' : '/') + this.name\n return (this.#fullpathPosix = fpp)\n }\n\n /**\n * Is the Path of an unknown type?\n *\n * Note that we might know *something* about it if there has been a previous\n * filesystem operation, for example that it does not exist, or is not a\n * link, or whether it has child entries.\n */\n isUnknown(): boolean {\n return (this.#type & IFMT) === UNKNOWN\n }\n\n isType(type: Type): boolean {\n return this[`is${type}`]()\n }\n\n getType(): Type {\n return (\n this.isUnknown() ? 'Unknown'\n : this.isDirectory() ? 'Directory'\n : this.isFile() ? 'File'\n : this.isSymbolicLink() ? 'SymbolicLink'\n : this.isFIFO() ? 'FIFO'\n : this.isCharacterDevice() ? 'CharacterDevice'\n : this.isBlockDevice() ? 'BlockDevice'\n : /* c8 ignore start */ this.isSocket() ? 'Socket'\n : 'Unknown'\n )\n /* c8 ignore stop */\n }\n\n /**\n * Is the Path a regular file?\n */\n isFile(): boolean {\n return (this.#type & IFMT) === IFREG\n }\n\n /**\n * Is the Path a directory?\n */\n isDirectory(): boolean {\n return (this.#type & IFMT) === IFDIR\n }\n\n /**\n * Is the path a character device?\n */\n isCharacterDevice(): boolean {\n return (this.#type & IFMT) === IFCHR\n }\n\n /**\n * Is the path a block device?\n */\n isBlockDevice(): boolean {\n return (this.#type & IFMT) === IFBLK\n }\n\n /**\n * Is the path a FIFO pipe?\n */\n isFIFO(): boolean {\n return (this.#type & IFMT) === IFIFO\n }\n\n /**\n * Is the path a socket?\n */\n isSocket(): boolean {\n return (this.#type & IFMT) === IFSOCK\n }\n\n /**\n * Is the path a symbolic link?\n */\n isSymbolicLink(): boolean {\n return (this.#type & IFLNK) === IFLNK\n }\n\n /**\n * Return the entry if it has been subject of a successful lstat, or\n * undefined otherwise.\n *\n * Does not read the filesystem, so an undefined result *could* simply\n * mean that we haven't called lstat on it.\n */\n lstatCached(): PathBase | undefined {\n return this.#type & LSTAT_CALLED ? this : undefined\n }\n\n /**\n * Return the cached link target if the entry has been the subject of a\n * successful readlink, or undefined otherwise.\n *\n * Does not read the filesystem, so an undefined result *could* just mean we\n * don't have any cached data. Only use it if you are very sure that a\n * readlink() has been called at some point.\n */\n readlinkCached(): PathBase | undefined {\n return this.#linkTarget\n }\n\n /**\n * Returns the cached realpath target if the entry has been the subject\n * of a successful realpath, or undefined otherwise.\n *\n * Does not read the filesystem, so an undefined result *could* just mean we\n * don't have any cached data. Only use it if you are very sure that a\n * realpath() has been called at some point.\n */\n realpathCached(): PathBase | undefined {\n return this.#realpath\n }\n\n /**\n * Returns the cached child Path entries array if the entry has been the\n * subject of a successful readdir(), or [] otherwise.\n *\n * Does not read the filesystem, so an empty array *could* just mean we\n * don't have any cached data. Only use it if you are very sure that a\n * readdir() has been called recently enough to still be valid.\n */\n readdirCached(): PathBase[] {\n const children = this.children()\n return children.slice(0, children.provisional)\n }\n\n /**\n * Return true if it's worth trying to readlink. Ie, we don't (yet) have\n * any indication that readlink will definitely fail.\n *\n * Returns false if the path is known to not be a symlink, if a previous\n * readlink failed, or if the entry does not exist.\n */\n canReadlink(): boolean {\n if (this.#linkTarget) return true\n if (!this.parent) return false\n // cases where it cannot possibly succeed\n const ifmt = this.#type & IFMT\n return !(\n (ifmt !== UNKNOWN && ifmt !== IFLNK) ||\n this.#type & ENOREADLINK ||\n this.#type & ENOENT\n )\n }\n\n /**\n * Return true if readdir has previously been successfully called on this\n * path, indicating that cachedReaddir() is likely valid.\n */\n calledReaddir(): boolean {\n return !!(this.#type & READDIR_CALLED)\n }\n\n /**\n * Returns true if the path is known to not exist. That is, a previous lstat\n * or readdir failed to verify its existence when that would have been\n * expected, or a parent entry was marked either enoent or enotdir.\n */\n isENOENT(): boolean {\n return !!(this.#type & ENOENT)\n }\n\n /**\n * Return true if the path is a match for the given path name. This handles\n * case sensitivity and unicode normalization.\n *\n * Note: even on case-sensitive systems, it is **not** safe to test the\n * equality of the `.name` property to determine whether a given pathname\n * matches, due to unicode normalization mismatches.\n *\n * Always use this method instead of testing the `path.name` property\n * directly.\n */\n isNamed(n: string): boolean {\n return !this.nocase ?\n this.#matchName === normalize(n)\n : this.#matchName === normalizeNocase(n)\n }\n\n /**\n * Return the Path object corresponding to the target of a symbolic link.\n *\n * If the Path is not a symbolic link, or if the readlink call fails for any\n * reason, `undefined` is returned.\n *\n * Result is cached, and thus may be outdated if the filesystem is mutated.\n */\n async readlink(): Promise<PathBase | undefined> {\n const target = this.#linkTarget\n if (target) {\n return target\n }\n if (!this.canReadlink()) {\n return undefined\n }\n /* c8 ignore start */\n // already covered by the canReadlink test, here for ts grumples\n if (!this.parent) {\n return undefined\n }\n /* c8 ignore stop */\n try {\n const read = await this.#fs.promises.readlink(this.fullpath())\n const linkTarget = (await this.parent.realpath())?.resolve(read)\n if (linkTarget) {\n return (this.#linkTarget = linkTarget)\n }\n } catch (er) {\n this.#readlinkFail((er as NodeJS.ErrnoException).code)\n return undefined\n }\n }\n\n /**\n * Synchronous {@link PathBase.readlink}\n */\n readlinkSync(): PathBase | undefined {\n const target = this.#linkTarget\n if (target) {\n return target\n }\n if (!this.canReadlink()) {\n return undefined\n }\n /* c8 ignore start */\n // already covered by the canReadlink test, here for ts grumples\n if (!this.parent) {\n return undefined\n }\n /* c8 ignore stop */\n try {\n const read = this.#fs.readlinkSync(this.fullpath())\n const linkTarget = this.parent.realpathSync()?.resolve(read)\n if (linkTarget) {\n return (this.#linkTarget = linkTarget)\n }\n } catch (er) {\n this.#readlinkFail((er as NodeJS.ErrnoException).code)\n return undefined\n }\n }\n\n #readdirSuccess(children: Children) {\n // succeeded, mark readdir called bit\n this.#type |= READDIR_CALLED\n // mark all remaining provisional children as ENOENT\n for (let p = children.provisional; p < children.length; p++) {\n const c = children[p]\n if (c) c.#markENOENT()\n }\n }\n\n #markENOENT() {\n // mark as UNKNOWN and ENOENT\n if (this.#type & ENOENT) return\n this.#type = (this.#type | ENOENT) & IFMT_UNKNOWN\n this.#markChildrenENOENT()\n }\n\n #markChildrenENOENT() {\n // all children are provisional and do not exist\n const children = this.children()\n children.provisional = 0\n for (const p of children) {\n p.#markENOENT()\n }\n }\n\n #markENOREALPATH() {\n this.#type |= ENOREALPATH\n this.#markENOTDIR()\n }\n\n // save the information when we know the entry is not a dir\n #markENOTDIR() {\n // entry is not a directory, so any children can't exist.\n // this *should* be impossible, since any children created\n // after it's been marked ENOTDIR should be marked ENOENT,\n // so it won't even get to this point.\n /* c8 ignore start */\n if (this.#type & ENOTDIR) return\n /* c8 ignore stop */\n let t = this.#type\n // this could happen if we stat a dir, then delete it,\n // then try to read it or one of its children.\n if ((t & IFMT) === IFDIR) t &= IFMT_UNKNOWN\n this.#type = t | ENOTDIR\n this.#markChildrenENOENT()\n }\n\n #readdirFail(code: string = '') {\n // markENOTDIR and markENOENT also set provisional=0\n if (code === 'ENOTDIR' || code === 'EPERM') {\n this.#markENOTDIR()\n } else if (code === 'ENOENT') {\n this.#markENOENT()\n } else {\n this.children().provisional = 0\n }\n }\n\n #lstatFail(code: string = '') {\n // Windows just raises ENOENT in this case, disable for win CI\n /* c8 ignore start */\n if (code === 'ENOTDIR') {\n // already know it has a parent by this point\n const p = this.parent as PathBase\n p.#markENOTDIR()\n } else if (code === 'ENOENT') {\n /* c8 ignore stop */\n this.#markENOENT()\n }\n }\n\n #readlinkFail(code: string = '') {\n let ter = this.#type\n ter |= ENOREADLINK\n if (code === 'ENOENT') ter |= ENOENT\n // windows gets a weird error when you try to readlink a file\n if (code === 'EINVAL' || code === 'UNKNOWN') {\n // exists, but not a symlink, we don't know WHAT it is, so remove\n // all IFMT bits.\n ter &= IFMT_UNKNOWN\n }\n this.#type = ter\n // windows just gets ENOENT in this case. We do cover the case,\n // just disabled because it's impossible on Windows CI\n /* c8 ignore start */\n if (code === 'ENOTDIR' && this.parent) {\n this.parent.#markENOTDIR()\n }\n /* c8 ignore stop */\n }\n\n #readdirAddChild(e: Dirent, c: Children) {\n return (\n this.#readdirMaybePromoteChild(e, c) ||\n this.#readdirAddNewChild(e, c)\n )\n }\n\n #readdirAddNewChild(e: Dirent, c: Children): PathBase {\n // alloc new entry at head, so it's never provisional\n const type = entToType(e)\n const child = this.newChild(e.name, type, { parent: this })\n const ifmt = child.#type & IFMT\n if (ifmt !== IFDIR && ifmt !== IFLNK && ifmt !== UNKNOWN) {\n child.#type |= ENOTDIR\n }\n c.unshift(child)\n c.provisional++\n return child\n }\n\n #readdirMaybePromoteChild(e: Dirent, c: Children): PathBase | undefined {\n for (let p = c.provisional; p < c.length; p++) {\n const pchild = c[p]\n const name =\n this.nocase ? normalizeNocase(e.name) : normalize(e.name)\n if (name !== pchild!.#matchName) {\n continue\n }\n\n return this.#readdirPromoteChild(e, pchild!, p, c)\n }\n }\n\n #readdirPromoteChild(\n e: Dirent,\n p: PathBase,\n index: number,\n c: Children,\n ): PathBase {\n const v = p.name\n // retain any other flags, but set ifmt from dirent\n p.#type = (p.#type & IFMT_UNKNOWN) | entToType(e)\n // case sensitivity fixing when we learn the true name.\n if (v !== e.name) p.name = e.name\n\n // just advance provisional index (potentially off the list),\n // otherwise we have to splice/pop it out and re-insert at head\n if (index !== c.provisional) {\n if (index === c.length - 1) c.pop()\n else c.splice(index, 1)\n c.unshift(p)\n }\n c.provisional++\n return p\n }\n\n /**\n * Call lstat() on this Path, and update all known information that can be\n * determined.\n *\n * Note that unlike `fs.lstat()`, the returned value does not contain some\n * information, such as `mode`, `dev`, `nlink`, and `ino`. If that\n * information is required, you will need to call `fs.lstat` yourself.\n *\n * If the Path refers to a nonexistent file, or if the lstat call fails for\n * any reason, `undefined` is returned. Otherwise the updated Path object is\n * returned.\n *\n * Results are cached, and thus may be out of date if the filesystem is\n * mutated.\n */\n async lstat(): Promise<PathBase | undefined> {\n if ((this.#type & ENOENT) === 0) {\n try {\n this.#applyStat(await this.#fs.promises.lstat(this.fullpath()))\n return this\n } catch (er) {\n this.#lstatFail((er as NodeJS.ErrnoException).code)\n }\n }\n }\n\n /**\n * synchronous {@link PathBase.lstat}\n */\n lstatSync(): PathBase | undefined {\n if ((this.#type & ENOENT) === 0) {\n try {\n this.#applyStat(this.#fs.lstatSync(this.fullpath()))\n return this\n } catch (er) {\n this.#lstatFail((er as NodeJS.ErrnoException).code)\n }\n }\n }\n\n #applyStat(st: Stats) {\n const {\n atime,\n atimeMs,\n birthtime,\n birthtimeMs,\n blksize,\n blocks,\n ctime,\n ctimeMs,\n dev,\n gid,\n ino,\n mode,\n mtime,\n mtimeMs,\n nlink,\n rdev,\n size,\n uid,\n } = st\n this.#atime = atime\n this.#atimeMs = atimeMs\n this.#birthtime = birthtime\n this.#birthtimeMs = birthtimeMs\n this.#blksize = blksize\n this.#blocks = blocks\n this.#ctime = ctime\n this.#ctimeMs = ctimeMs\n this.#dev = dev\n this.#gid = gid\n this.#ino = ino\n this.#mode = mode\n this.#mtime = mtime\n this.#mtimeMs = mtimeMs\n this.#nlink = nlink\n this.#rdev = rdev\n this.#size = size\n this.#uid = uid\n const ifmt = entToType(st)\n // retain any other flags, but set the ifmt\n this.#type = (this.#type & IFMT_UNKNOWN) | ifmt | LSTAT_CALLED\n if (ifmt !== UNKNOWN && ifmt !== IFDIR && ifmt !== IFLNK) {\n this.#type |= ENOTDIR\n }\n }\n\n #onReaddirCB: ((\n er: NodeJS.ErrnoException | null,\n entries: Path[],\n ) => any)[] = []\n #readdirCBInFlight: boolean = false\n #callOnReaddirCB(children: Path[]) {\n this.#readdirCBInFlight = false\n const cbs = this.#onReaddirCB.slice()\n this.#onReaddirCB.length = 0\n cbs.forEach(cb => cb(null, children))\n }\n\n /**\n * Standard node-style callback interface to get list of directory entries.\n *\n * If the Path cannot or does not contain any children, then an empty array\n * is returned.\n *\n * Results are cached, and thus may be out of date if the filesystem is\n * mutated.\n *\n * @param cb The callback called with (er, entries). Note that the `er`\n * param is somewhat extraneous, as all readdir() errors are handled and\n * simply result in an empty set of entries being returned.\n * @param allowZalgo Boolean indicating that immediately known results should\n * *not* be deferred with `queueMicrotask`. Defaults to `false`. Release\n * zalgo at your peril, the dark pony lord is devious and unforgiving.\n */\n readdirCB(\n cb: (er: NodeJS.ErrnoException | null, entries: PathBase[]) => any,\n allowZalgo: boolean = false,\n ): void {\n if (!this.canReaddir()) {\n if (allowZalgo) cb(null, [])\n else queueMicrotask(() => cb(null, []))\n return\n }\n\n const children = this.children()\n if (this.calledReaddir()) {\n const c = children.slice(0, children.provisional)\n if (allowZalgo) cb(null, c)\n else queueMicrotask(() => cb(null, c))\n return\n }\n\n // don't have to worry about zalgo at this point.\n this.#onReaddirCB.push(cb)\n if (this.#readdirCBInFlight) {\n return\n }\n this.#readdirCBInFlight = true\n\n // else read the directory, fill up children\n // de-provisionalize any provisional children.\n const fullpath = this.fullpath()\n this.#fs.readdir(fullpath, { withFileTypes: true }, (er, entries) => {\n if (er) {\n this.#readdirFail((er as NodeJS.ErrnoException).code)\n children.provisional = 0\n } else {\n // if we didn't get an error, we always get entries.\n //@ts-ignore\n for (const e of entries) {\n this.#readdirAddChild(e, children)\n }\n this.#readdirSuccess(children)\n }\n this.#callOnReaddirCB(children.slice(0, children.provisional))\n return\n })\n }\n\n #asyncReaddirInFlight?: Promise<void>\n\n /**\n * Return an array of known child entries.\n *\n * If the Path cannot or does not contain any children, then an empty array\n * is returned.\n *\n * Results are cached, and thus may be out of date if the filesystem is\n * mutated.\n */\n async readdir(): Promise<PathBase[]> {\n if (!this.canReaddir()) {\n return []\n }\n\n const children = this.children()\n if (this.calledReaddir()) {\n return children.slice(0, children.provisional)\n }\n\n // else read the directory, fill up children\n // de-provisionalize any provisional children.\n const fullpath = this.fullpath()\n if (this.#asyncReaddirInFlight) {\n await this.#asyncReaddirInFlight\n } else {\n /* c8 ignore start */\n let resolve: () => void = () => {}\n /* c8 ignore stop */\n this.#asyncReaddirInFlight = new Promise<void>(\n res => (resolve = res),\n )\n try {\n for (const e of await this.#fs.promises.readdir(fullpath, {\n withFileTypes: true,\n })) {\n this.#readdirAddChild(e, children)\n }\n this.#readdirSuccess(children)\n } catch (er) {\n this.#readdirFail((er as NodeJS.ErrnoException).code)\n children.provisional = 0\n }\n this.#asyncReaddirInFlight = undefined\n resolve()\n }\n return children.slice(0, children.provisional)\n }\n\n /**\n * synchronous {@link PathBase.readdir}\n */\n readdirSync(): PathBase[] {\n if (!this.canReaddir()) {\n return []\n }\n\n const children = this.children()\n if (this.calledReaddir()) {\n return children.slice(0, children.provisional)\n }\n\n // else read the directory, fill up children\n // de-provisionalize any provisional children.\n const fullpath = this.fullpath()\n try {\n for (const e of this.#fs.readdirSync(fullpath, {\n withFileTypes: true,\n })) {\n this.#readdirAddChild(e, children)\n }\n this.#readdirSuccess(children)\n } catch (er) {\n this.#readdirFail((er as NodeJS.ErrnoException).code)\n children.provisional = 0\n }\n return children.slice(0, children.provisional)\n }\n\n canReaddir() {\n if (this.#type & ENOCHILD) return false\n const ifmt = IFMT & this.#type\n // we always set ENOTDIR when setting IFMT, so should be impossible\n /* c8 ignore start */\n if (!(ifmt === UNKNOWN || ifmt === IFDIR || ifmt === IFLNK)) {\n return false\n }\n /* c8 ignore stop */\n return true\n }\n\n shouldWalk(\n dirs: Set<PathBase | undefined>,\n walkFilter?: (e: PathBase) => boolean,\n ): boolean {\n return (\n (this.#type & IFDIR) === IFDIR &&\n !(this.#type & ENOCHILD) &&\n !dirs.has(this) &&\n (!walkFilter || walkFilter(this))\n )\n }\n\n /**\n * Return the Path object corresponding to path as resolved\n * by realpath(3).\n *\n * If the realpath call fails for any reason, `undefined` is returned.\n *\n * Result is cached, and thus may be outdated if the filesystem is mutated.\n * On success, returns a Path object.\n */\n async realpath(): Promise<PathBase | undefined> {\n if (this.#realpath) return this.#realpath\n if ((ENOREALPATH | ENOREADLINK | ENOENT) & this.#type) return undefined\n try {\n const rp = await this.#fs.promises.realpath(this.fullpath())\n return (this.#realpath = this.resolve(rp))\n } catch (_) {\n this.#markENOREALPATH()\n }\n }\n\n /**\n * Synchronous {@link realpath}\n */\n realpathSync(): PathBase | undefined {\n if (this.#realpath) return this.#realpath\n if ((ENOREALPATH | ENOREADLINK | ENOENT) & this.#type) return undefined\n try {\n const rp = this.#fs.realpathSync(this.fullpath())\n return (this.#realpath = this.resolve(rp))\n } catch (_) {\n this.#markENOREALPATH()\n }\n }\n\n /**\n * Internal method to mark this Path object as the scurry cwd,\n * called by {@link PathScurry#chdir}\n *\n * @internal\n */\n [setAsCwd](oldCwd: PathBase): void {\n if (oldCwd === this) return\n oldCwd.isCWD = false\n this.isCWD = true\n\n const changed = new Set<PathBase>([])\n let rp = []\n let p: PathBase = this\n while (p && p.parent) {\n changed.add(p)\n p.#relative = rp.join(this.sep)\n p.#relativePosix = rp.join('/')\n p = p.parent\n rp.push('..')\n }\n // now un-memoize parents of old cwd\n p = oldCwd\n while (p && p.parent && !changed.has(p)) {\n p.#relative = undefined\n p.#relativePosix = undefined\n p = p.parent\n }\n }\n}\n\n/**\n * Path class used on win32 systems\n *\n * Uses `'\\\\'` as the path separator for returned paths, either `'\\\\'` or `'/'`\n * as the path separator for parsing paths.\n */\nexport class PathWin32 extends PathBase {\n /**\n * Separator for generating path strings.\n */\n sep: '\\\\' = '\\\\'\n /**\n * Separator for parsing path strings.\n */\n splitSep: RegExp = eitherSep\n\n /**\n * Do not create new Path objects directly. They should always be accessed\n * via the PathScurry class or other methods on the Path class.\n *\n * @internal\n */\n constructor(\n name: string,\n type: number = UNKNOWN,\n root: PathBase | undefined,\n roots: { [k: string]: PathBase },\n nocase: boolean,\n children: ChildrenCache,\n opts: PathOpts,\n ) {\n super(name, type, root, roots, nocase, children, opts)\n }\n\n /**\n * @internal\n */\n newChild(name: string, type: number = UNKNOWN, opts: PathOpts = {}) {\n return new PathWin32(\n name,\n type,\n this.root,\n this.roots,\n this.nocase,\n this.childrenCache(),\n opts,\n )\n }\n\n /**\n * @internal\n */\n getRootString(path: string): string {\n return win32.parse(path).root\n }\n\n /**\n * @internal\n */\n getRoot(rootPath: string): PathBase {\n rootPath = uncToDrive(rootPath.toUpperCase())\n if (rootPath === this.root.name) {\n return this.root\n }\n // ok, not that one, check if it matches another we know about\n for (const [compare, root] of Object.entries(this.roots)) {\n if (this.sameRoot(rootPath, compare)) {\n return (this.roots[rootPath] = root)\n }\n }\n // otherwise, have to create a new one.\n return (this.roots[rootPath] = new PathScurryWin32(\n rootPath,\n this,\n ).root)\n }\n\n /**\n * @internal\n */\n sameRoot(rootPath: string, compare: string = this.root.name): boolean {\n // windows can (rarely) have case-sensitive filesystem, but\n // UNC and drive letters are always case-insensitive, and canonically\n // represented uppercase.\n rootPath = rootPath\n .toUpperCase()\n .replace(/\\//g, '\\\\')\n .replace(uncDriveRegexp, '$1\\\\')\n return rootPath === compare\n }\n}\n\n/**\n * Path class used on all posix systems.\n *\n * Uses `'/'` as the path separator.\n */\nexport class PathPosix extends PathBase {\n /**\n * separator for parsing path strings\n */\n splitSep: '/' = '/'\n /**\n * separator for generating path strings\n */\n sep: '/' = '/'\n\n /**\n * Do not create new Path objects directly. They should always be accessed\n * via the PathScurry class or other methods on the Path class.\n *\n * @internal\n */\n constructor(\n name: string,\n type: number = UNKNOWN,\n root: PathBase | undefined,\n roots: { [k: string]: PathBase },\n nocase: boolean,\n children: ChildrenCache,\n opts: PathOpts,\n ) {\n super(name, type, root, roots, nocase, children, opts)\n }\n\n /**\n * @internal\n */\n getRootString(path: string): string {\n return path.startsWith('/') ? '/' : ''\n }\n\n /**\n * @internal\n */\n getRoot(_rootPath: string): PathBase {\n return this.root\n }\n\n /**\n * @internal\n */\n newChild(name: string, type: number = UNKNOWN, opts: PathOpts = {}) {\n return new PathPosix(\n name,\n type,\n this.root,\n this.roots,\n this.nocase,\n this.childrenCache(),\n opts,\n )\n }\n}\n\n/**\n * Options that may be provided to the PathScurry constructor\n */\nexport interface PathScurryOpts {\n /**\n * perform case-insensitive path matching. Default based on platform\n * subclass.\n */\n nocase?: boolean\n /**\n * Number of Path entries to keep in the cache of Path child references.\n *\n * Setting this higher than 65536 will dramatically increase the data\n * consumption and construction time overhead of each PathScurry.\n *\n * Setting this value to 256 or lower will significantly reduce the data\n * consumption and construction time overhead, but may also reduce resolve()\n * and readdir() performance on large filesystems.\n *\n * Default `16384`.\n */\n childrenCacheSize?: number\n /**\n * An object that overrides the built-in functions from the fs and\n * fs/promises modules.\n *\n * See {@link FSOption}\n */\n fs?: FSOption\n}\n\n/**\n * The base class for all PathScurry classes, providing the interface for path\n * resolution and filesystem operations.\n *\n * Typically, you should *not* instantiate this class directly, but rather one\n * of the platform-specific classes, or the exported {@link PathScurry} which\n * defaults to the current platform.\n */\nexport abstract class PathScurryBase {\n /**\n * The root Path entry for the current working directory of this Scurry\n */\n root: PathBase\n /**\n * The string path for the root of this Scurry's current working directory\n */\n rootPath: string\n /**\n * A collection of all roots encountered, referenced by rootPath\n */\n roots: { [k: string]: PathBase }\n /**\n * The Path entry corresponding to this PathScurry's current working directory.\n */\n cwd: PathBase\n #resolveCache: ResolveCache\n #resolvePosixCache: ResolveCache\n #children: ChildrenCache\n /**\n * Perform path comparisons case-insensitively.\n *\n * Defaults true on Darwin and Windows systems, false elsewhere.\n */\n nocase: boolean\n\n /**\n * The path separator used for parsing paths\n *\n * `'/'` on Posix systems, either `'/'` or `'\\\\'` on Windows\n */\n abstract sep: string | RegExp\n\n #fs: FSValue\n\n /**\n * This class should not be instantiated directly.\n *\n * Use PathScurryWin32, PathScurryDarwin, PathScurryPosix, or PathScurry\n *\n * @internal\n */\n constructor(\n cwd: URL | string = process.cwd(),\n pathImpl: typeof win32 | typeof posix,\n sep: string | RegExp,\n {\n nocase,\n childrenCacheSize = 16 * 1024,\n fs = defaultFS,\n }: PathScurryOpts = {},\n ) {\n this.#fs = fsFromOption(fs)\n if (cwd instanceof URL || cwd.startsWith('file://')) {\n cwd = fileURLToPath(cwd)\n }\n // resolve and split root, and then add to the store.\n // this is the only time we call path.resolve()\n const cwdPath = pathImpl.resolve(cwd)\n this.roots = Object.create(null)\n this.rootPath = this.parseRootPath(cwdPath)\n this.#resolveCache = new ResolveCache()\n this.#resolvePosixCache = new ResolveCache()\n this.#children = new ChildrenCache(childrenCacheSize)\n\n const split = cwdPath.substring(this.rootPath.length).split(sep)\n // resolve('/') leaves '', splits to [''], we don't want that.\n if (split.length === 1 && !split[0]) {\n split.pop()\n }\n /* c8 ignore start */\n if (nocase === undefined) {\n throw new TypeError(\n 'must provide nocase setting to PathScurryBase ctor',\n )\n }\n /* c8 ignore stop */\n this.nocase = nocase\n this.root = this.newRoot(this.#fs)\n this.roots[this.rootPath] = this.root\n let prev: PathBase = this.root\n let len = split.length - 1\n const joinSep = pathImpl.sep\n let abs = this.rootPath\n let sawFirst = false\n for (const part of split) {\n const l = len--\n prev = prev.child(part, {\n relative: new Array(l).fill('..').join(joinSep),\n relativePosix: new Array(l).fill('..').join('/'),\n fullpath: (abs += (sawFirst ? '' : joinSep) + part),\n })\n sawFirst = true\n }\n this.cwd = prev\n }\n\n /**\n * Get the depth of a provided path, string, or the cwd\n */\n depth(path: Path | string = this.cwd): number {\n if (typeof path === 'string') {\n path = this.cwd.resolve(path)\n }\n return path.depth()\n }\n\n /**\n * Parse the root portion of a path string\n *\n * @internal\n */\n abstract parseRootPath(dir: string): string\n /**\n * create a new Path to use as root during construction.\n *\n * @internal\n */\n abstract newRoot(fs: FSValue): PathBase\n /**\n * Determine whether a given path string is absolute\n */\n abstract isAbsolute(p: string): boolean\n\n /**\n * Return the cache of child entries. Exposed so subclasses can create\n * child Path objects in a platform-specific way.\n *\n * @internal\n */\n childrenCache() {\n return this.#children\n }\n\n /**\n * Resolve one or more path strings to a resolved string\n *\n * Same interface as require('path').resolve.\n *\n * Much faster than path.resolve() when called multiple times for the same\n * path, because the resolved Path objects are cached. Much slower\n * otherwise.\n */\n resolve(...paths: string[]): string {\n // first figure out the minimum number of paths we have to test\n // we always start at cwd, but any absolutes will bump the start\n let r = ''\n for (let i = paths.length - 1; i >= 0; i--) {\n const p = paths[i]\n if (!p || p === '.') continue\n r = r ? `${p}/${r}` : p\n if (this.isAbsolute(p)) {\n break\n }\n }\n const cached = this.#resolveCache.get(r)\n if (cached !== undefined) {\n return cached\n }\n const result = this.cwd.resolve(r).fullpath()\n this.#resolveCache.set(r, result)\n return result\n }\n\n /**\n * Resolve one or more path strings to a resolved string, returning\n * the posix path. Identical to .resolve() on posix systems, but on\n * windows will return a forward-slash separated UNC path.\n *\n * Same interface as require('path').resolve.\n *\n * Much faster than path.resolve() when called multiple times for the same\n * path, because the resolved Path objects are cached. Much slower\n * otherwise.\n */\n resolvePosix(...paths: string[]): string {\n // first figure out the minimum number of paths we have to test\n // we always start at cwd, but any absolutes will bump the start\n let r = ''\n for (let i = paths.length - 1; i >= 0; i--) {\n const p = paths[i]\n if (!p || p === '.') continue\n r = r ? `${p}/${r}` : p\n if (this.isAbsolute(p)) {\n break\n }\n }\n const cached = this.#resolvePosixCache.get(r)\n if (cached !== undefined) {\n return cached\n }\n const result = this.cwd.resolve(r).fullpathPosix()\n this.#resolvePosixCache.set(r, result)\n return result\n }\n\n /**\n * find the relative path from the cwd to the supplied path string or entry\n */\n relative(entry: PathBase | string = this.cwd): string {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n }\n return entry.relative()\n }\n\n /**\n * find the relative path from the cwd to the supplied path string or\n * entry, using / as the path delimiter, even on Windows.\n */\n relativePosix(entry: PathBase | string = this.cwd): string {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n }\n return entry.relativePosix()\n }\n\n /**\n * Return the basename for the provided string or Path object\n */\n basename(entry: PathBase | string = this.cwd): string {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n }\n return entry.name\n }\n\n /**\n * Return the dirname for the provided string or Path object\n */\n dirname(entry: PathBase | string = this.cwd): string {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n }\n return (entry.parent || entry).fullpath()\n }\n\n /**\n * Return an array of known child entries.\n *\n * First argument may be either a string, or a Path object.\n *\n * If the Path cannot or does not contain any children, then an empty array\n * is returned.\n *\n * Results are cached, and thus may be out of date if the filesystem is\n * mutated.\n *\n * Unlike `fs.readdir()`, the `withFileTypes` option defaults to `true`. Set\n * `{ withFileTypes: false }` to return strings.\n */\n\n readdir(): Promise<PathBase[]>\n readdir(opts: { withFileTypes: true }): Promise<PathBase[]>\n readdir(opts: { withFileTypes: false }): Promise<string[]>\n readdir(opts: { withFileTypes: boolean }): Promise<PathBase[] | string[]>\n readdir(entry: PathBase | string): Promise<PathBase[]>\n readdir(\n entry: PathBase | string,\n opts: { withFileTypes: true },\n ): Promise<PathBase[]>\n readdir(\n entry: PathBase | string,\n opts: { withFileTypes: false },\n ): Promise<string[]>\n readdir(\n entry: PathBase | string,\n opts: { withFileTypes: boolean },\n ): Promise<PathBase[] | string[]>\n async readdir(\n entry: PathBase | string | { withFileTypes: boolean } = this.cwd,\n opts: { withFileTypes: boolean } = {\n withFileTypes: true,\n },\n ): Promise<PathBase[] | string[]> {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n opts = entry\n entry = this.cwd\n }\n const { withFileTypes } = opts\n if (!entry.canReaddir()) {\n return []\n } else {\n const p = await entry.readdir()\n return withFileTypes ? p : p.map(e => e.name)\n }\n }\n\n /**\n * synchronous {@link PathScurryBase.readdir}\n */\n readdirSync(): PathBase[]\n readdirSync(opts: { withFileTypes: true }): PathBase[]\n readdirSync(opts: { withFileTypes: false }): string[]\n readdirSync(opts: { withFileTypes: boolean }): PathBase[] | string[]\n readdirSync(entry: PathBase | string): PathBase[]\n readdirSync(\n entry: PathBase | string,\n opts: { withFileTypes: true },\n ): PathBase[]\n readdirSync(\n entry: PathBase | string,\n opts: { withFileTypes: false },\n ): string[]\n readdirSync(\n entry: PathBase | string,\n opts: { withFileTypes: boolean },\n ): PathBase[] | string[]\n readdirSync(\n entry: PathBase | string | { withFileTypes: boolean } = this.cwd,\n opts: { withFileTypes: boolean } = {\n withFileTypes: true,\n },\n ): PathBase[] | string[] {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n opts = entry\n entry = this.cwd\n }\n const { withFileTypes = true } = opts\n if (!entry.canReaddir()) {\n return []\n } else if (withFileTypes) {\n return entry.readdirSync()\n } else {\n return entry.readdirSync().map(e => e.name)\n }\n }\n\n /**\n * Call lstat() on the string or Path object, and update all known\n * information that can be determined.\n *\n * Note that unlike `fs.lstat()`, the returned value does not contain some\n * information, such as `mode`, `dev`, `nlink`, and `ino`. If that\n * information is required, you will need to call `fs.lstat` yourself.\n *\n * If the Path refers to a nonexistent file, or if the lstat call fails for\n * any reason, `undefined` is returned. Otherwise the updated Path object is\n * returned.\n *\n * Results are cached, and thus may be out of date if the filesystem is\n * mutated.\n */\n async lstat(\n entry: string | PathBase = this.cwd,\n ): Promise<PathBase | undefined> {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n }\n return entry.lstat()\n }\n\n /**\n * synchronous {@link PathScurryBase.lstat}\n */\n lstatSync(entry: string | PathBase = this.cwd): PathBase | undefined {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n }\n return entry.lstatSync()\n }\n\n /**\n * Return the Path object or string path corresponding to the target of a\n * symbolic link.\n *\n * If the path is not a symbolic link, or if the readlink call fails for any\n * reason, `undefined` is returned.\n *\n * Result is cached, and thus may be outdated if the filesystem is mutated.\n *\n * `{withFileTypes}` option defaults to `false`.\n *\n * On success, returns a Path object if `withFileTypes` option is true,\n * otherwise a string.\n */\n readlink(): Promise<string | undefined>\n readlink(opt: { withFileTypes: false }): Promise<string | undefined>\n readlink(opt: { withFileTypes: true }): Promise<PathBase | undefined>\n readlink(opt: {\n withFileTypes: boolean\n }): Promise<PathBase | string | undefined>\n readlink(\n entry: string | PathBase,\n opt?: { withFileTypes: false },\n ): Promise<string | undefined>\n readlink(\n entry: string | PathBase,\n opt: { withFileTypes: true },\n ): Promise<PathBase | undefined>\n readlink(\n entry: string | PathBase,\n opt: { withFileTypes: boolean },\n ): Promise<string | PathBase | undefined>\n async readlink(\n entry: string | PathBase | { withFileTypes: boolean } = this.cwd,\n { withFileTypes }: { withFileTypes: boolean } = {\n withFileTypes: false,\n },\n ): Promise<string | PathBase | undefined> {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n withFileTypes = entry.withFileTypes\n entry = this.cwd\n }\n const e = await entry.readlink()\n return withFileTypes ? e : e?.fullpath()\n }\n\n /**\n * synchronous {@link PathScurryBase.readlink}\n */\n readlinkSync(): string | undefined\n readlinkSync(opt: { withFileTypes: false }): string | undefined\n readlinkSync(opt: { withFileTypes: true }): PathBase | undefined\n readlinkSync(opt: {\n withFileTypes: boolean\n }): PathBase | string | undefined\n readlinkSync(\n entry: string | PathBase,\n opt?: { withFileTypes: false },\n ): string | undefined\n readlinkSync(\n entry: string | PathBase,\n opt: { withFileTypes: true },\n ): PathBase | undefined\n readlinkSync(\n entry: string | PathBase,\n opt: { withFileTypes: boolean },\n ): string | PathBase | undefined\n readlinkSync(\n entry: string | PathBase | { withFileTypes: boolean } = this.cwd,\n { withFileTypes }: { withFileTypes: boolean } = {\n withFileTypes: false,\n },\n ): string | PathBase | undefined {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n withFileTypes = entry.withFileTypes\n entry = this.cwd\n }\n const e = entry.readlinkSync()\n return withFileTypes ? e : e?.fullpath()\n }\n\n /**\n * Return the Path object or string path corresponding to path as resolved\n * by realpath(3).\n *\n * If the realpath call fails for any reason, `undefined` is returned.\n *\n * Result is cached, and thus may be outdated if the filesystem is mutated.\n *\n * `{withFileTypes}` option defaults to `false`.\n *\n * On success, returns a Path object if `withFileTypes` option is true,\n * otherwise a string.\n */\n realpath(): Promise<string | undefined>\n realpath(opt: { withFileTypes: false }): Promise<string | undefined>\n realpath(opt: { withFileTypes: true }): Promise<PathBase | undefined>\n realpath(opt: {\n withFileTypes: boolean\n }): Promise<PathBase | string | undefined>\n realpath(\n entry: string | PathBase,\n opt?: { withFileTypes: false },\n ): Promise<string | undefined>\n realpath(\n entry: string | PathBase,\n opt: { withFileTypes: true },\n ): Promise<PathBase | undefined>\n realpath(\n entry: string | PathBase,\n opt: { withFileTypes: boolean },\n ): Promise<string | PathBase | undefined>\n async realpath(\n entry: string | PathBase | { withFileTypes: boolean } = this.cwd,\n { withFileTypes }: { withFileTypes: boolean } = {\n withFileTypes: false,\n },\n ): Promise<string | PathBase | undefined> {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n withFileTypes = entry.withFileTypes\n entry = this.cwd\n }\n const e = await entry.realpath()\n return withFileTypes ? e : e?.fullpath()\n }\n\n realpathSync(): string | undefined\n realpathSync(opt: { withFileTypes: false }): string | undefined\n realpathSync(opt: { withFileTypes: true }): PathBase | undefined\n realpathSync(opt: {\n withFileTypes: boolean\n }): PathBase | string | undefined\n realpathSync(\n entry: string | PathBase,\n opt?: { withFileTypes: false },\n ): string | undefined\n realpathSync(\n entry: string | PathBase,\n opt: { withFileTypes: true },\n ): PathBase | undefined\n realpathSync(\n entry: string | PathBase,\n opt: { withFileTypes: boolean },\n ): string | PathBase | undefined\n realpathSync(\n entry: string | PathBase | { withFileTypes: boolean } = this.cwd,\n { withFileTypes }: { withFileTypes: boolean } = {\n withFileTypes: false,\n },\n ): string | PathBase | undefined {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n withFileTypes = entry.withFileTypes\n entry = this.cwd\n }\n const e = entry.realpathSync()\n return withFileTypes ? e : e?.fullpath()\n }\n\n /**\n * Asynchronously walk the directory tree, returning an array of\n * all path strings or Path objects found.\n *\n * Note that this will be extremely memory-hungry on large filesystems.\n * In such cases, it may be better to use the stream or async iterator\n * walk implementation.\n */\n walk(): Promise<PathBase[]>\n walk(\n opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset,\n ): Promise<PathBase[]>\n walk(opts: WalkOptionsWithFileTypesFalse): Promise<string[]>\n walk(opts: WalkOptions): Promise<string[] | PathBase[]>\n walk(entry: string | PathBase): Promise<PathBase[]>\n walk(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset,\n ): Promise<PathBase[]>\n walk(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesFalse,\n ): Promise<string[]>\n walk(\n entry: string | PathBase,\n opts: WalkOptions,\n ): Promise<PathBase[] | string[]>\n async walk(\n entry: string | PathBase | WalkOptions = this.cwd,\n opts: WalkOptions = {},\n ): Promise<PathBase[] | string[]> {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n opts = entry\n entry = this.cwd\n }\n const {\n withFileTypes = true,\n follow = false,\n filter,\n walkFilter,\n } = opts\n const results: (string | PathBase)[] = []\n if (!filter || filter(entry)) {\n results.push(withFileTypes ? entry : entry.fullpath())\n }\n const dirs = new Set<PathBase>()\n const walk = (\n dir: PathBase,\n cb: (er?: NodeJS.ErrnoException) => void,\n ) => {\n dirs.add(dir)\n dir.readdirCB((er, entries) => {\n /* c8 ignore start */\n if (er) {\n return cb(er)\n }\n /* c8 ignore stop */\n let len = entries.length\n if (!len) return cb()\n const next = () => {\n if (--len === 0) {\n cb()\n }\n }\n for (const e of entries) {\n if (!filter || filter(e)) {\n results.push(withFileTypes ? e : e.fullpath())\n }\n if (follow && e.isSymbolicLink()) {\n e.realpath()\n .then(r => (r?.isUnknown() ? r.lstat() : r))\n .then(r =>\n r?.shouldWalk(dirs, walkFilter) ? walk(r, next) : next(),\n )\n } else {\n if (e.shouldWalk(dirs, walkFilter)) {\n walk(e, next)\n } else {\n next()\n }\n }\n }\n }, true) // zalgooooooo\n }\n\n const start = entry\n return new Promise<PathBase[] | string[]>((res, rej) => {\n walk(start, er => {\n /* c8 ignore start */\n if (er) return rej(er)\n /* c8 ignore stop */\n res(results as PathBase[] | string[])\n })\n })\n }\n\n /**\n * Synchronously walk the directory tree, returning an array of\n * all path strings or Path objects found.\n *\n * Note that this will be extremely memory-hungry on large filesystems.\n * In such cases, it may be better to use the stream or async iterator\n * walk implementation.\n */\n walkSync(): PathBase[]\n walkSync(\n opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset,\n ): PathBase[]\n walkSync(opts: WalkOptionsWithFileTypesFalse): string[]\n walkSync(opts: WalkOptions): string[] | PathBase[]\n walkSync(entry: string | PathBase): PathBase[]\n walkSync(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesUnset | WalkOptionsWithFileTypesTrue,\n ): PathBase[]\n walkSync(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesFalse,\n ): string[]\n walkSync(\n entry: string | PathBase,\n opts: WalkOptions,\n ): PathBase[] | string[]\n walkSync(\n entry: string | PathBase | WalkOptions = this.cwd,\n opts: WalkOptions = {},\n ): PathBase[] | string[] {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n opts = entry\n entry = this.cwd\n }\n const {\n withFileTypes = true,\n follow = false,\n filter,\n walkFilter,\n } = opts\n const results: (string | PathBase)[] = []\n if (!filter || filter(entry)) {\n results.push(withFileTypes ? entry : entry.fullpath())\n }\n const dirs = new Set<PathBase>([entry])\n for (const dir of dirs) {\n const entries = dir.readdirSync()\n for (const e of entries) {\n if (!filter || filter(e)) {\n results.push(withFileTypes ? e : e.fullpath())\n }\n let r: PathBase | undefined = e\n if (e.isSymbolicLink()) {\n if (!(follow && (r = e.realpathSync()))) continue\n if (r.isUnknown()) r.lstatSync()\n }\n if (r.shouldWalk(dirs, walkFilter)) {\n dirs.add(r)\n }\n }\n }\n return results as string[] | PathBase[]\n }\n\n /**\n * Support for `for await`\n *\n * Alias for {@link PathScurryBase.iterate}\n *\n * Note: As of Node 19, this is very slow, compared to other methods of\n * walking. Consider using {@link PathScurryBase.stream} if memory overhead\n * and backpressure are concerns, or {@link PathScurryBase.walk} if not.\n */\n [Symbol.asyncIterator]() {\n return this.iterate()\n }\n\n /**\n * Async generator form of {@link PathScurryBase.walk}\n *\n * Note: As of Node 19, this is very slow, compared to other methods of\n * walking, especially if most/all of the directory tree has been previously\n * walked. Consider using {@link PathScurryBase.stream} if memory overhead\n * and backpressure are concerns, or {@link PathScurryBase.walk} if not.\n */\n iterate(): AsyncGenerator<PathBase, void, void>\n iterate(\n opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset,\n ): AsyncGenerator<PathBase, void, void>\n iterate(\n opts: WalkOptionsWithFileTypesFalse,\n ): AsyncGenerator<string, void, void>\n iterate(opts: WalkOptions): AsyncGenerator<string | PathBase, void, void>\n iterate(entry: string | PathBase): AsyncGenerator<PathBase, void, void>\n iterate(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset,\n ): AsyncGenerator<PathBase, void, void>\n iterate(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesFalse,\n ): AsyncGenerator<string, void, void>\n iterate(\n entry: string | PathBase,\n opts: WalkOptions,\n ): AsyncGenerator<PathBase | string, void, void>\n iterate(\n entry: string | PathBase | WalkOptions = this.cwd,\n options: WalkOptions = {},\n ): AsyncGenerator<PathBase | string, void, void> {\n // iterating async over the stream is significantly more performant,\n // especially in the warm-cache scenario, because it buffers up directory\n // entries in the background instead of waiting for a yield for each one.\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n options = entry\n entry = this.cwd\n }\n return this.stream(entry, options)[Symbol.asyncIterator]()\n }\n\n /**\n * Iterating over a PathScurry performs a synchronous walk.\n *\n * Alias for {@link PathScurryBase.iterateSync}\n */\n [Symbol.iterator]() {\n return this.iterateSync()\n }\n\n iterateSync(): Generator<PathBase, void, void>\n iterateSync(\n opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset,\n ): Generator<PathBase, void, void>\n iterateSync(\n opts: WalkOptionsWithFileTypesFalse,\n ): Generator<string, void, void>\n iterateSync(opts: WalkOptions): Generator<string | PathBase, void, void>\n iterateSync(entry: string | PathBase): Generator<PathBase, void, void>\n iterateSync(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset,\n ): Generator<PathBase, void, void>\n iterateSync(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesFalse,\n ): Generator<string, void, void>\n iterateSync(\n entry: string | PathBase,\n opts: WalkOptions,\n ): Generator<PathBase | string, void, void>\n *iterateSync(\n entry: string | PathBase | WalkOptions = this.cwd,\n opts: WalkOptions = {},\n ): Generator<PathBase | string, void, void> {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n opts = entry\n entry = this.cwd\n }\n const {\n withFileTypes = true,\n follow = false,\n filter,\n walkFilter,\n } = opts\n if (!filter || filter(entry)) {\n yield withFileTypes ? entry : entry.fullpath()\n }\n const dirs = new Set<PathBase>([entry])\n for (const dir of dirs) {\n const entries = dir.readdirSync()\n for (const e of entries) {\n if (!filter || filter(e)) {\n yield withFileTypes ? e : e.fullpath()\n }\n let r: PathBase | undefined = e\n if (e.isSymbolicLink()) {\n if (!(follow && (r = e.realpathSync()))) continue\n if (r.isUnknown()) r.lstatSync()\n }\n if (r.shouldWalk(dirs, walkFilter)) {\n dirs.add(r)\n }\n }\n }\n }\n\n /**\n * Stream form of {@link PathScurryBase.walk}\n *\n * Returns a Minipass stream that emits {@link PathBase} objects by default,\n * or strings if `{ withFileTypes: false }` is set in the options.\n */\n stream(): Minipass<PathBase>\n stream(\n opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset,\n ): Minipass<PathBase>\n stream(opts: WalkOptionsWithFileTypesFalse): Minipass<string>\n stream(opts: WalkOptions): Minipass<string | PathBase>\n stream(entry: string | PathBase): Minipass<PathBase>\n stream(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesUnset | WalkOptionsWithFileTypesTrue,\n ): Minipass<PathBase>\n stream(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesFalse,\n ): Minipass<string>\n stream(\n entry: string | PathBase,\n opts: WalkOptions,\n ): Minipass<string> | Minipass<PathBase>\n stream(\n entry: string | PathBase | WalkOptions = this.cwd,\n opts: WalkOptions = {},\n ): Minipass<string> | Minipass<PathBase> {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n opts = entry\n entry = this.cwd\n }\n const {\n withFileTypes = true,\n follow = false,\n filter,\n walkFilter,\n } = opts\n const results = new Minipass<string | PathBase>({ objectMode: true })\n if (!filter || filter(entry)) {\n results.write(withFileTypes ? entry : entry.fullpath())\n }\n const dirs = new Set<PathBase>()\n const queue: PathBase[] = [entry]\n let processing = 0\n const process = () => {\n let paused = false\n while (!paused) {\n const dir = queue.shift()\n if (!dir) {\n if (processing === 0) results.end()\n return\n }\n\n processing++\n dirs.add(dir)\n\n const onReaddir = (\n er: null | NodeJS.ErrnoException,\n entries: PathBase[],\n didRealpaths: boolean = false,\n ) => {\n /* c8 ignore start */\n if (er) return results.emit('error', er)\n /* c8 ignore stop */\n if (follow && !didRealpaths) {\n const promises: Promise<PathBase | undefined>[] = []\n for (const e of entries) {\n if (e.isSymbolicLink()) {\n promises.push(\n e\n .realpath()\n .then((r: PathBase | undefined) =>\n r?.isUnknown() ? r.lstat() : r,\n ),\n )\n }\n }\n if (promises.length) {\n Promise.all(promises).then(() =>\n onReaddir(null, entries, true),\n )\n return\n }\n }\n\n for (const e of entries) {\n if (e && (!filter || filter(e))) {\n if (!results.write(withFileTypes ? e : e.fullpath())) {\n paused = true\n }\n }\n }\n\n processing--\n for (const e of entries) {\n const r = e.realpathCached() || e\n if (r.shouldWalk(dirs, walkFilter)) {\n queue.push(r)\n }\n }\n if (paused && !results.flowing) {\n results.once('drain', process)\n } else if (!sync) {\n process()\n }\n }\n\n // zalgo containment\n let sync = true\n dir.readdirCB(onReaddir, true)\n sync = false\n }\n }\n process()\n return results as Minipass<string> | Minipass<PathBase>\n }\n\n /**\n * Synchronous form of {@link PathScurryBase.stream}\n *\n * Returns a Minipass stream that emits {@link PathBase} objects by default,\n * or strings if `{ withFileTypes: false }` is set in the options.\n *\n * Will complete the walk in a single tick if the stream is consumed fully.\n * Otherwise, will pause as needed for stream backpressure.\n */\n streamSync(): Minipass<PathBase>\n streamSync(\n opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset,\n ): Minipass<PathBase>\n streamSync(opts: WalkOptionsWithFileTypesFalse): Minipass<string>\n streamSync(opts: WalkOptions): Minipass<string | PathBase>\n streamSync(entry: string | PathBase): Minipass<PathBase>\n streamSync(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesUnset | WalkOptionsWithFileTypesTrue,\n ): Minipass<PathBase>\n streamSync(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesFalse,\n ): Minipass<string>\n streamSync(\n entry: string | PathBase,\n opts: WalkOptions,\n ): Minipass<string> | Minipass<PathBase>\n streamSync(\n entry: string | PathBase | WalkOptions = this.cwd,\n opts: WalkOptions = {},\n ): Minipass<string> | Minipass<PathBase> {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n opts = entry\n entry = this.cwd\n }\n const {\n withFileTypes = true,\n follow = false,\n filter,\n walkFilter,\n } = opts\n const results = new Minipass<string | PathBase>({ objectMode: true })\n const dirs = new Set<PathBase>()\n if (!filter || filter(entry)) {\n results.write(withFileTypes ? entry : entry.fullpath())\n }\n const queue: PathBase[] = [entry]\n let processing = 0\n const process = () => {\n let paused = false\n while (!paused) {\n const dir = queue.shift()\n if (!dir) {\n if (processing === 0) results.end()\n return\n }\n processing++\n dirs.add(dir)\n\n const entries = dir.readdirSync()\n for (const e of entries) {\n if (!filter || filter(e)) {\n if (!results.write(withFileTypes ? e : e.fullpath())) {\n paused = true\n }\n }\n }\n processing--\n for (const e of entries) {\n let r: PathBase | undefined = e\n if (e.isSymbolicLink()) {\n if (!(follow && (r = e.realpathSync()))) continue\n if (r.isUnknown()) r.lstatSync()\n }\n if (r.shouldWalk(dirs, walkFilter)) {\n queue.push(r)\n }\n }\n }\n if (paused && !results.flowing) results.once('drain', process)\n }\n process()\n return results as Minipass<string> | Minipass<PathBase>\n }\n\n chdir(path: string | Path = this.cwd) {\n const oldCwd = this.cwd\n this.cwd = typeof path === 'string' ? this.cwd.resolve(path) : path\n this.cwd[setAsCwd](oldCwd)\n }\n}\n\n/**\n * Options provided to all walk methods.\n */\nexport interface WalkOptions {\n /**\n * Return results as {@link PathBase} objects rather than strings.\n * When set to false, results are fully resolved paths, as returned by\n * {@link PathBase.fullpath}.\n * @default true\n */\n withFileTypes?: boolean\n\n /**\n * Attempt to read directory entries from symbolic links. Otherwise, only\n * actual directories are traversed. Regardless of this setting, a given\n * target path will only ever be walked once, meaning that a symbolic link\n * to a previously traversed directory will never be followed.\n *\n * Setting this imposes a slight performance penalty, because `readlink`\n * must be called on all symbolic links encountered, in order to avoid\n * infinite cycles.\n * @default false\n */\n follow?: boolean\n\n /**\n * Only return entries where the provided function returns true.\n *\n * This will not prevent directories from being traversed, even if they do\n * not pass the filter, though it will prevent directories themselves from\n * being included in the result set. See {@link walkFilter}\n *\n * Asynchronous functions are not supported here.\n *\n * By default, if no filter is provided, all entries and traversed\n * directories are included.\n */\n filter?: (entry: PathBase) => boolean\n\n /**\n * Only traverse directories (and in the case of {@link follow} being set to\n * true, symbolic links to directories) if the provided function returns\n * true.\n *\n * This will not prevent directories from being included in the result set,\n * even if they do not pass the supplied filter function. See {@link filter}\n * to do that.\n *\n * Asynchronous functions are not supported here.\n */\n walkFilter?: (entry: PathBase) => boolean\n}\n\nexport type WalkOptionsWithFileTypesUnset = WalkOptions & {\n withFileTypes?: undefined\n}\nexport type WalkOptionsWithFileTypesTrue = WalkOptions & {\n withFileTypes: true\n}\nexport type WalkOptionsWithFileTypesFalse = WalkOptions & {\n withFileTypes: false\n}\n\n/**\n * Windows implementation of {@link PathScurryBase}\n *\n * Defaults to case insensitve, uses `'\\\\'` to generate path strings. Uses\n * {@link PathWin32} for Path objects.\n */\nexport class PathScurryWin32 extends PathScurryBase {\n /**\n * separator for generating path strings\n */\n sep: '\\\\' = '\\\\'\n\n constructor(\n cwd: URL | string = process.cwd(),\n opts: PathScurryOpts = {},\n ) {\n const { nocase = true } = opts\n super(cwd, win32, '\\\\', { ...opts, nocase })\n this.nocase = nocase\n for (let p: PathBase | undefined = this.cwd; p; p = p.parent) {\n p.nocase = this.nocase\n }\n }\n\n /**\n * @internal\n */\n parseRootPath(dir: string): string {\n // if the path starts with a single separator, it's not a UNC, and we'll\n // just get separator as the root, and driveFromUNC will return \\\n // In that case, mount \\ on the root from the cwd.\n return win32.parse(dir).root.toUpperCase()\n }\n\n /**\n * @internal\n */\n newRoot(fs: FSValue) {\n return new PathWin32(\n this.rootPath,\n IFDIR,\n undefined,\n this.roots,\n this.nocase,\n this.childrenCache(),\n { fs },\n )\n }\n\n /**\n * Return true if the provided path string is an absolute path\n */\n isAbsolute(p: string): boolean {\n return (\n p.startsWith('/') || p.startsWith('\\\\') || /^[a-z]:(\\/|\\\\)/i.test(p)\n )\n }\n}\n\n/**\n * {@link PathScurryBase} implementation for all posix systems other than Darwin.\n *\n * Defaults to case-sensitive matching, uses `'/'` to generate path strings.\n *\n * Uses {@link PathPosix} for Path objects.\n */\nexport class PathScurryPosix extends PathScurryBase {\n /**\n * separator for generating path strings\n */\n sep: '/' = '/'\n constructor(\n cwd: URL | string = process.cwd(),\n opts: PathScurryOpts = {},\n ) {\n const { nocase = false } = opts\n super(cwd, posix, '/', { ...opts, nocase })\n this.nocase = nocase\n }\n\n /**\n * @internal\n */\n parseRootPath(_dir: string): string {\n return '/'\n }\n\n /**\n * @internal\n */\n newRoot(fs: FSValue) {\n return new PathPosix(\n this.rootPath,\n IFDIR,\n undefined,\n this.roots,\n this.nocase,\n this.childrenCache(),\n { fs },\n )\n }\n\n /**\n * Return true if the provided path string is an absolute path\n */\n isAbsolute(p: string): boolean {\n return p.startsWith('/')\n }\n}\n\n/**\n * {@link PathScurryBase} implementation for Darwin (macOS) systems.\n *\n * Defaults to case-insensitive matching, uses `'/'` for generating path\n * strings.\n *\n * Uses {@link PathPosix} for Path objects.\n */\nexport class PathScurryDarwin extends PathScurryPosix {\n constructor(\n cwd: URL | string = process.cwd(),\n opts: PathScurryOpts = {},\n ) {\n const { nocase = true } = opts\n super(cwd, { ...opts, nocase })\n }\n}\n\n/**\n * Default {@link PathBase} implementation for the current platform.\n *\n * {@link PathWin32} on Windows systems, {@link PathPosix} on all others.\n */\nexport const Path = process.platform === 'win32' ? PathWin32 : PathPosix\nexport type Path = PathBase | InstanceType<typeof Path>\n\n/**\n * Default {@link PathScurryBase} implementation for the current platform.\n *\n * {@link PathScurryWin32} on Windows systems, {@link PathScurryDarwin} on\n * Darwin (macOS) systems, {@link PathScurryPosix} on all others.\n */\nexport const PathScurry:\n | typeof PathScurryWin32\n | typeof PathScurryDarwin\n | typeof PathScurryPosix =\n process.platform === 'win32' ? PathScurryWin32\n : process.platform === 'darwin' ? PathScurryDarwin\n : PathScurryPosix\nexport type PathScurry = PathScurryBase | InstanceType<typeof PathScurry>\n","const proc =\n typeof process === 'object' && process\n ? process\n : {\n stdout: null,\n stderr: null,\n }\nimport { EventEmitter } from 'node:events'\nimport Stream from 'node:stream'\nimport { StringDecoder } from 'node:string_decoder'\n\n/**\n * Same as StringDecoder, but exposing the `lastNeed` flag on the type\n */\ntype SD = StringDecoder & { lastNeed: boolean }\n\nexport type { SD, Pipe, PipeProxyErrors }\n\n/**\n * Return true if the argument is a Minipass stream, Node stream, or something\n * else that Minipass can interact with.\n */\nexport const isStream = (\n s: any\n): s is Minipass.Readable | Minipass.Writable =>\n !!s &&\n typeof s === 'object' &&\n (s instanceof Minipass ||\n s instanceof Stream ||\n isReadable(s) ||\n isWritable(s))\n\n/**\n * Return true if the argument is a valid {@link Minipass.Readable}\n */\nexport const isReadable = (s: any): s is Minipass.Readable =>\n !!s &&\n typeof s === 'object' &&\n s instanceof EventEmitter &&\n typeof (s as Minipass.Readable).pipe === 'function' &&\n // node core Writable streams have a pipe() method, but it throws\n (s as Minipass.Readable).pipe !== Stream.Writable.prototype.pipe\n\n/**\n * Return true if the argument is a valid {@link Minipass.Writable}\n */\nexport const isWritable = (s: any): s is Minipass.Readable =>\n !!s &&\n typeof s === 'object' &&\n s instanceof EventEmitter &&\n typeof (s as Minipass.Writable).write === 'function' &&\n typeof (s as Minipass.Writable).end === 'function'\n\nconst EOF = Symbol('EOF')\nconst MAYBE_EMIT_END = Symbol('maybeEmitEnd')\nconst EMITTED_END = Symbol('emittedEnd')\nconst EMITTING_END = Symbol('emittingEnd')\nconst EMITTED_ERROR = Symbol('emittedError')\nconst CLOSED = Symbol('closed')\nconst READ = Symbol('read')\nconst FLUSH = Symbol('flush')\nconst FLUSHCHUNK = Symbol('flushChunk')\nconst ENCODING = Symbol('encoding')\nconst DECODER = Symbol('decoder')\nconst FLOWING = Symbol('flowing')\nconst PAUSED = Symbol('paused')\nconst RESUME = Symbol('resume')\nconst BUFFER = Symbol('buffer')\nconst PIPES = Symbol('pipes')\nconst BUFFERLENGTH = Symbol('bufferLength')\nconst BUFFERPUSH = Symbol('bufferPush')\nconst BUFFERSHIFT = Symbol('bufferShift')\nconst OBJECTMODE = Symbol('objectMode')\n// internal event when stream is destroyed\nconst DESTROYED = Symbol('destroyed')\n// internal event when stream has an error\nconst ERROR = Symbol('error')\nconst EMITDATA = Symbol('emitData')\nconst EMITEND = Symbol('emitEnd')\nconst EMITEND2 = Symbol('emitEnd2')\nconst ASYNC = Symbol('async')\nconst ABORT = Symbol('abort')\nconst ABORTED = Symbol('aborted')\nconst SIGNAL = Symbol('signal')\nconst DATALISTENERS = Symbol('dataListeners')\nconst DISCARDED = Symbol('discarded')\n\nconst defer = (fn: (...a: any[]) => any) => Promise.resolve().then(fn)\nconst nodefer = (fn: (...a: any[]) => any) => fn()\n\n// events that mean 'the stream is over'\n// these are treated specially, and re-emitted\n// if they are listened for after emitting.\ntype EndishEvent = 'end' | 'finish' | 'prefinish'\nconst isEndish = (ev: any): ev is EndishEvent =>\n ev === 'end' || ev === 'finish' || ev === 'prefinish'\n\nconst isArrayBufferLike = (b: any): b is ArrayBufferLike =>\n b instanceof ArrayBuffer ||\n (!!b &&\n typeof b === 'object' &&\n b.constructor &&\n b.constructor.name === 'ArrayBuffer' &&\n b.byteLength >= 0)\n\nconst isArrayBufferView = (b: any): b is ArrayBufferView =>\n !Buffer.isBuffer(b) && ArrayBuffer.isView(b)\n\n/**\n * Options that may be passed to stream.pipe()\n */\nexport interface PipeOptions {\n /**\n * end the destination stream when the source stream ends\n */\n end?: boolean\n /**\n * proxy errors from the source stream to the destination stream\n */\n proxyErrors?: boolean\n}\n\n/**\n * Internal class representing a pipe to a destination stream.\n *\n * @internal\n */\nclass Pipe<T extends unknown> {\n src: Minipass<T>\n dest: Minipass<any, T>\n opts: PipeOptions\n ondrain: () => any\n constructor(\n src: Minipass<T>,\n dest: Minipass.Writable,\n opts: PipeOptions\n ) {\n this.src = src\n this.dest = dest as Minipass<any, T>\n this.opts = opts\n this.ondrain = () => src[RESUME]()\n this.dest.on('drain', this.ondrain)\n }\n unpipe() {\n this.dest.removeListener('drain', this.ondrain)\n }\n // only here for the prototype\n /* c8 ignore start */\n proxyErrors(_er: any) {}\n /* c8 ignore stop */\n end() {\n this.unpipe()\n if (this.opts.end) this.dest.end()\n }\n}\n\n/**\n * Internal class representing a pipe to a destination stream where\n * errors are proxied.\n *\n * @internal\n */\nclass PipeProxyErrors<T> extends Pipe<T> {\n unpipe() {\n this.src.removeListener('error', this.proxyErrors)\n super.unpipe()\n }\n constructor(\n src: Minipass<T>,\n dest: Minipass.Writable,\n opts: PipeOptions\n ) {\n super(src, dest, opts)\n this.proxyErrors = (er: Error) => this.dest.emit('error', er)\n src.on('error', this.proxyErrors)\n }\n}\n\nexport namespace Minipass {\n /**\n * Encoding used to create a stream that outputs strings rather than\n * Buffer objects.\n */\n export type Encoding = BufferEncoding | 'buffer' | null\n\n /**\n * Any stream that Minipass can pipe into\n */\n export type Writable =\n | Minipass<any, any, any>\n | NodeJS.WriteStream\n | (NodeJS.WriteStream & { fd: number })\n | (EventEmitter & {\n end(): any\n write(chunk: any, ...args: any[]): any\n })\n\n /**\n * Any stream that can be read from\n */\n export type Readable =\n | Minipass<any, any, any>\n | NodeJS.ReadStream\n | (NodeJS.ReadStream & { fd: number })\n | (EventEmitter & {\n pause(): any\n resume(): any\n pipe(...destArgs: any[]): any\n })\n\n /**\n * Utility type that can be iterated sync or async\n */\n export type DualIterable<T> = Iterable<T> & AsyncIterable<T>\n\n type EventArguments = Record<string | symbol, unknown[]>\n\n /**\n * The listing of events that a Minipass class can emit.\n * Extend this when extending the Minipass class, and pass as\n * the third template argument. The key is the name of the event,\n * and the value is the argument list.\n *\n * Any undeclared events will still be allowed, but the handler will get\n * arguments as `unknown[]`.\n */\n export interface Events<RType extends any = Buffer>\n extends EventArguments {\n readable: []\n data: [chunk: RType]\n error: [er: unknown]\n abort: [reason: unknown]\n drain: []\n resume: []\n end: []\n finish: []\n prefinish: []\n close: []\n [DESTROYED]: [er?: unknown]\n [ERROR]: [er: unknown]\n }\n\n /**\n * String or buffer-like data that can be joined and sliced\n */\n export type ContiguousData =\n | Buffer\n | ArrayBufferLike\n | ArrayBufferView\n | string\n export type BufferOrString = Buffer | string\n\n /**\n * Options passed to the Minipass constructor.\n */\n export type SharedOptions = {\n /**\n * Defer all data emission and other events until the end of the\n * current tick, similar to Node core streams\n */\n async?: boolean\n /**\n * A signal which will abort the stream\n */\n signal?: AbortSignal\n /**\n * Output string encoding. Set to `null` or `'buffer'` (or omit) to\n * emit Buffer objects rather than strings.\n *\n * Conflicts with `objectMode`\n */\n encoding?: BufferEncoding | null | 'buffer'\n /**\n * Output data exactly as it was written, supporting non-buffer/string\n * data (such as arbitrary objects, falsey values, etc.)\n *\n * Conflicts with `encoding`\n */\n objectMode?: boolean\n }\n\n /**\n * Options for a string encoded output\n */\n export type EncodingOptions = SharedOptions & {\n encoding: BufferEncoding\n objectMode?: false\n }\n\n /**\n * Options for contiguous data buffer output\n */\n export type BufferOptions = SharedOptions & {\n encoding?: null | 'buffer'\n objectMode?: false\n }\n\n /**\n * Options for objectMode arbitrary output\n */\n export type ObjectModeOptions = SharedOptions & {\n objectMode: true\n encoding?: null\n }\n\n /**\n * Utility type to determine allowed options based on read type\n */\n export type Options<T> =\n | ObjectModeOptions\n | (T extends string\n ? EncodingOptions\n : T extends Buffer\n ? BufferOptions\n : SharedOptions)\n}\n\nconst isObjectModeOptions = (\n o: Minipass.SharedOptions\n): o is Minipass.ObjectModeOptions => !!o.objectMode\n\nconst isEncodingOptions = (\n o: Minipass.SharedOptions\n): o is Minipass.EncodingOptions =>\n !o.objectMode && !!o.encoding && o.encoding !== 'buffer'\n\n/**\n * Main export, the Minipass class\n *\n * `RType` is the type of data emitted, defaults to Buffer\n *\n * `WType` is the type of data to be written, if RType is buffer or string,\n * then any {@link Minipass.ContiguousData} is allowed.\n *\n * `Events` is the set of event handler signatures that this object\n * will emit, see {@link Minipass.Events}\n */\nexport class Minipass<\n RType extends unknown = Buffer,\n WType extends unknown = RType extends Minipass.BufferOrString\n ? Minipass.ContiguousData\n : RType,\n Events extends Minipass.Events<RType> = Minipass.Events<RType>\n >\n extends EventEmitter\n implements Minipass.DualIterable<RType>\n{\n [FLOWING]: boolean = false;\n [PAUSED]: boolean = false;\n [PIPES]: Pipe<RType>[] = [];\n [BUFFER]: RType[] = [];\n [OBJECTMODE]: boolean;\n [ENCODING]: BufferEncoding | null;\n [ASYNC]: boolean;\n [DECODER]: SD | null;\n [EOF]: boolean = false;\n [EMITTED_END]: boolean = false;\n [EMITTING_END]: boolean = false;\n [CLOSED]: boolean = false;\n [EMITTED_ERROR]: unknown = null;\n [BUFFERLENGTH]: number = 0;\n [DESTROYED]: boolean = false;\n [SIGNAL]?: AbortSignal;\n [ABORTED]: boolean = false;\n [DATALISTENERS]: number = 0;\n [DISCARDED]: boolean = false\n\n /**\n * true if the stream can be written\n */\n writable: boolean = true\n /**\n * true if the stream can be read\n */\n readable: boolean = true\n\n /**\n * If `RType` is Buffer, then options do not need to be provided.\n * Otherwise, an options object must be provided to specify either\n * {@link Minipass.SharedOptions.objectMode} or\n * {@link Minipass.SharedOptions.encoding}, as appropriate.\n */\n constructor(\n ...args:\n | [Minipass.ObjectModeOptions]\n | (RType extends Buffer\n ? [] | [Minipass.Options<RType>]\n : [Minipass.Options<RType>])\n ) {\n const options: Minipass.Options<RType> = (args[0] ||\n {}) as Minipass.Options<RType>\n super()\n if (options.objectMode && typeof options.encoding === 'string') {\n throw new TypeError(\n 'Encoding and objectMode may not be used together'\n )\n }\n if (isObjectModeOptions(options)) {\n this[OBJECTMODE] = true\n this[ENCODING] = null\n } else if (isEncodingOptions(options)) {\n this[ENCODING] = options.encoding\n this[OBJECTMODE] = false\n } else {\n this[OBJECTMODE] = false\n this[ENCODING] = null\n }\n this[ASYNC] = !!options.async\n this[DECODER] = this[ENCODING]\n ? (new StringDecoder(this[ENCODING]) as SD)\n : null\n\n //@ts-ignore - private option for debugging and testing\n if (options && options.debugExposeBuffer === true) {\n Object.defineProperty(this, 'buffer', { get: () => this[BUFFER] })\n }\n //@ts-ignore - private option for debugging and testing\n if (options && options.debugExposePipes === true) {\n Object.defineProperty(this, 'pipes', { get: () => this[PIPES] })\n }\n\n const { signal } = options\n if (signal) {\n this[SIGNAL] = signal\n if (signal.aborted) {\n this[ABORT]()\n } else {\n signal.addEventListener('abort', () => this[ABORT]())\n }\n }\n }\n\n /**\n * The amount of data stored in the buffer waiting to be read.\n *\n * For Buffer strings, this will be the total byte length.\n * For string encoding streams, this will be the string character length,\n * according to JavaScript's `string.length` logic.\n * For objectMode streams, this is a count of the items waiting to be\n * emitted.\n */\n get bufferLength() {\n return this[BUFFERLENGTH]\n }\n\n /**\n * The `BufferEncoding` currently in use, or `null`\n */\n get encoding() {\n return this[ENCODING]\n }\n\n /**\n * @deprecated - This is a read only property\n */\n set encoding(_enc) {\n throw new Error('Encoding must be set at instantiation time')\n }\n\n /**\n * @deprecated - Encoding may only be set at instantiation time\n */\n setEncoding(_enc: Minipass.Encoding) {\n throw new Error('Encoding must be set at instantiation time')\n }\n\n /**\n * True if this is an objectMode stream\n */\n get objectMode() {\n return this[OBJECTMODE]\n }\n\n /**\n * @deprecated - This is a read-only property\n */\n set objectMode(_om) {\n throw new Error('objectMode must be set at instantiation time')\n }\n\n /**\n * true if this is an async stream\n */\n get ['async'](): boolean {\n return this[ASYNC]\n }\n /**\n * Set to true to make this stream async.\n *\n * Once set, it cannot be unset, as this would potentially cause incorrect\n * behavior. Ie, a sync stream can be made async, but an async stream\n * cannot be safely made sync.\n */\n set ['async'](a: boolean) {\n this[ASYNC] = this[ASYNC] || !!a\n }\n\n // drop everything and get out of the flow completely\n [ABORT]() {\n this[ABORTED] = true\n this.emit('abort', this[SIGNAL]?.reason)\n this.destroy(this[SIGNAL]?.reason)\n }\n\n /**\n * True if the stream has been aborted.\n */\n get aborted() {\n return this[ABORTED]\n }\n /**\n * No-op setter. Stream aborted status is set via the AbortSignal provided\n * in the constructor options.\n */\n set aborted(_) {}\n\n /**\n * Write data into the stream\n *\n * If the chunk written is a string, and encoding is not specified, then\n * `utf8` will be assumed. If the stream encoding matches the encoding of\n * a written string, and the state of the string decoder allows it, then\n * the string will be passed through to either the output or the internal\n * buffer without any processing. Otherwise, it will be turned into a\n * Buffer object for processing into the desired encoding.\n *\n * If provided, `cb` function is called immediately before return for\n * sync streams, or on next tick for async streams, because for this\n * base class, a chunk is considered \"processed\" once it is accepted\n * and either emitted or buffered. That is, the callback does not indicate\n * that the chunk has been eventually emitted, though of course child\n * classes can override this function to do whatever processing is required\n * and call `super.write(...)` only once processing is completed.\n */\n write(chunk: WType, cb?: () => void): boolean\n write(\n chunk: WType,\n encoding?: Minipass.Encoding,\n cb?: () => void\n ): boolean\n write(\n chunk: WType,\n encoding?: Minipass.Encoding | (() => void),\n cb?: () => void\n ): boolean {\n if (this[ABORTED]) return false\n if (this[EOF]) throw new Error('write after end')\n\n if (this[DESTROYED]) {\n this.emit(\n 'error',\n Object.assign(\n new Error('Cannot call write after a stream was destroyed'),\n { code: 'ERR_STREAM_DESTROYED' }\n )\n )\n return true\n }\n\n if (typeof encoding === 'function') {\n cb = encoding\n encoding = 'utf8'\n }\n\n if (!encoding) encoding = 'utf8'\n\n const fn = this[ASYNC] ? defer : nodefer\n\n // convert array buffers and typed array views into buffers\n // at some point in the future, we may want to do the opposite!\n // leave strings and buffers as-is\n // anything is only allowed if in object mode, so throw\n if (!this[OBJECTMODE] && !Buffer.isBuffer(chunk)) {\n if (isArrayBufferView(chunk)) {\n //@ts-ignore - sinful unsafe type changing\n chunk = Buffer.from(\n chunk.buffer,\n chunk.byteOffset,\n chunk.byteLength\n )\n } else if (isArrayBufferLike(chunk)) {\n //@ts-ignore - sinful unsafe type changing\n chunk = Buffer.from(chunk)\n } else if (typeof chunk !== 'string') {\n throw new Error(\n 'Non-contiguous data written to non-objectMode stream'\n )\n }\n }\n\n // handle object mode up front, since it's simpler\n // this yields better performance, fewer checks later.\n if (this[OBJECTMODE]) {\n // maybe impossible?\n /* c8 ignore start */\n if (this[FLOWING] && this[BUFFERLENGTH] !== 0) this[FLUSH](true)\n /* c8 ignore stop */\n\n if (this[FLOWING]) this.emit('data', chunk as unknown as RType)\n else this[BUFFERPUSH](chunk as unknown as RType)\n\n if (this[BUFFERLENGTH] !== 0) this.emit('readable')\n\n if (cb) fn(cb)\n\n return this[FLOWING]\n }\n\n // at this point the chunk is a buffer or string\n // don't buffer it up or send it to the decoder\n if (!(chunk as Minipass.BufferOrString).length) {\n if (this[BUFFERLENGTH] !== 0) this.emit('readable')\n if (cb) fn(cb)\n return this[FLOWING]\n }\n\n // fast-path writing strings of same encoding to a stream with\n // an empty buffer, skipping the buffer/decoder dance\n if (\n typeof chunk === 'string' &&\n // unless it is a string already ready for us to use\n !(encoding === this[ENCODING] && !this[DECODER]?.lastNeed)\n ) {\n //@ts-ignore - sinful unsafe type change\n chunk = Buffer.from(chunk, encoding)\n }\n\n if (Buffer.isBuffer(chunk) && this[ENCODING]) {\n //@ts-ignore - sinful unsafe type change\n chunk = this[DECODER].write(chunk)\n }\n\n // Note: flushing CAN potentially switch us into not-flowing mode\n if (this[FLOWING] && this[BUFFERLENGTH] !== 0) this[FLUSH](true)\n\n if (this[FLOWING]) this.emit('data', chunk as unknown as RType)\n else this[BUFFERPUSH](chunk as unknown as RType)\n\n if (this[BUFFERLENGTH] !== 0) this.emit('readable')\n\n if (cb) fn(cb)\n\n return this[FLOWING]\n }\n\n /**\n * Low-level explicit read method.\n *\n * In objectMode, the argument is ignored, and one item is returned if\n * available.\n *\n * `n` is the number of bytes (or in the case of encoding streams,\n * characters) to consume. If `n` is not provided, then the entire buffer\n * is returned, or `null` is returned if no data is available.\n *\n * If `n` is greater that the amount of data in the internal buffer,\n * then `null` is returned.\n */\n read(n?: number | null): RType | null {\n if (this[DESTROYED]) return null\n this[DISCARDED] = false\n\n if (\n this[BUFFERLENGTH] === 0 ||\n n === 0 ||\n (n && n > this[BUFFERLENGTH])\n ) {\n this[MAYBE_EMIT_END]()\n return null\n }\n\n if (this[OBJECTMODE]) n = null\n\n if (this[BUFFER].length > 1 && !this[OBJECTMODE]) {\n // not object mode, so if we have an encoding, then RType is string\n // otherwise, must be Buffer\n this[BUFFER] = [\n (this[ENCODING]\n ? this[BUFFER].join('')\n : Buffer.concat(\n this[BUFFER] as Buffer[],\n this[BUFFERLENGTH]\n )) as RType,\n ]\n }\n\n const ret = this[READ](n || null, this[BUFFER][0] as RType)\n this[MAYBE_EMIT_END]()\n return ret\n }\n\n [READ](n: number | null, chunk: RType) {\n if (this[OBJECTMODE]) this[BUFFERSHIFT]()\n else {\n const c = chunk as Minipass.BufferOrString\n if (n === c.length || n === null) this[BUFFERSHIFT]()\n else if (typeof c === 'string') {\n this[BUFFER][0] = c.slice(n) as RType\n chunk = c.slice(0, n) as RType\n this[BUFFERLENGTH] -= n\n } else {\n this[BUFFER][0] = c.subarray(n) as RType\n chunk = c.subarray(0, n) as RType\n this[BUFFERLENGTH] -= n\n }\n }\n\n this.emit('data', chunk)\n\n if (!this[BUFFER].length && !this[EOF]) this.emit('drain')\n\n return chunk\n }\n\n /**\n * End the stream, optionally providing a final write.\n *\n * See {@link Minipass#write} for argument descriptions\n */\n end(cb?: () => void): this\n end(chunk: WType, cb?: () => void): this\n end(chunk: WType, encoding?: Minipass.Encoding, cb?: () => void): this\n end(\n chunk?: WType | (() => void),\n encoding?: Minipass.Encoding | (() => void),\n cb?: () => void\n ): this {\n if (typeof chunk === 'function') {\n cb = chunk as () => void\n chunk = undefined\n }\n if (typeof encoding === 'function') {\n cb = encoding\n encoding = 'utf8'\n }\n if (chunk !== undefined) this.write(chunk, encoding)\n if (cb) this.once('end', cb)\n this[EOF] = true\n this.writable = false\n\n // if we haven't written anything, then go ahead and emit,\n // even if we're not reading.\n // we'll re-emit if a new 'end' listener is added anyway.\n // This makes MP more suitable to write-only use cases.\n if (this[FLOWING] || !this[PAUSED]) this[MAYBE_EMIT_END]()\n return this\n }\n\n // don't let the internal resume be overwritten\n [RESUME]() {\n if (this[DESTROYED]) return\n\n if (!this[DATALISTENERS] && !this[PIPES].length) {\n this[DISCARDED] = true\n }\n this[PAUSED] = false\n this[FLOWING] = true\n this.emit('resume')\n if (this[BUFFER].length) this[FLUSH]()\n else if (this[EOF]) this[MAYBE_EMIT_END]()\n else this.emit('drain')\n }\n\n /**\n * Resume the stream if it is currently in a paused state\n *\n * If called when there are no pipe destinations or `data` event listeners,\n * this will place the stream in a \"discarded\" state, where all data will\n * be thrown away. The discarded state is removed if a pipe destination or\n * data handler is added, if pause() is called, or if any synchronous or\n * asynchronous iteration is started.\n */\n resume() {\n return this[RESUME]()\n }\n\n /**\n * Pause the stream\n */\n pause() {\n this[FLOWING] = false\n this[PAUSED] = true\n this[DISCARDED] = false\n }\n\n /**\n * true if the stream has been forcibly destroyed\n */\n get destroyed() {\n return this[DESTROYED]\n }\n\n /**\n * true if the stream is currently in a flowing state, meaning that\n * any writes will be immediately emitted.\n */\n get flowing() {\n return this[FLOWING]\n }\n\n /**\n * true if the stream is currently in a paused state\n */\n get paused() {\n return this[PAUSED]\n }\n\n [BUFFERPUSH](chunk: RType) {\n if (this[OBJECTMODE]) this[BUFFERLENGTH] += 1\n else this[BUFFERLENGTH] += (chunk as Minipass.BufferOrString).length\n this[BUFFER].push(chunk)\n }\n\n [BUFFERSHIFT](): RType {\n if (this[OBJECTMODE]) this[BUFFERLENGTH] -= 1\n else\n this[BUFFERLENGTH] -= (\n this[BUFFER][0] as Minipass.BufferOrString\n ).length\n return this[BUFFER].shift() as RType\n }\n\n [FLUSH](noDrain: boolean = false) {\n do {} while (\n this[FLUSHCHUNK](this[BUFFERSHIFT]()) &&\n this[BUFFER].length\n )\n\n if (!noDrain && !this[BUFFER].length && !this[EOF]) this.emit('drain')\n }\n\n [FLUSHCHUNK](chunk: RType) {\n this.emit('data', chunk)\n return this[FLOWING]\n }\n\n /**\n * Pipe all data emitted by this stream into the destination provided.\n *\n * Triggers the flow of data.\n */\n pipe<W extends Minipass.Writable>(dest: W, opts?: PipeOptions): W {\n if (this[DESTROYED]) return dest\n this[DISCARDED] = false\n\n const ended = this[EMITTED_END]\n opts = opts || {}\n if (dest === proc.stdout || dest === proc.stderr) opts.end = false\n else opts.end = opts.end !== false\n opts.proxyErrors = !!opts.proxyErrors\n\n // piping an ended stream ends immediately\n if (ended) {\n if (opts.end) dest.end()\n } else {\n // \"as\" here just ignores the WType, which pipes don't care about,\n // since they're only consuming from us, and writing to the dest\n this[PIPES].push(\n !opts.proxyErrors\n ? new Pipe<RType>(this as Minipass<RType>, dest, opts)\n : new PipeProxyErrors<RType>(this as Minipass<RType>, dest, opts)\n )\n if (this[ASYNC]) defer(() => this[RESUME]())\n else this[RESUME]()\n }\n\n return dest\n }\n\n /**\n * Fully unhook a piped destination stream.\n *\n * If the destination stream was the only consumer of this stream (ie,\n * there are no other piped destinations or `'data'` event listeners)\n * then the flow of data will stop until there is another consumer or\n * {@link Minipass#resume} is explicitly called.\n */\n unpipe<W extends Minipass.Writable>(dest: W) {\n const p = this[PIPES].find(p => p.dest === dest)\n if (p) {\n if (this[PIPES].length === 1) {\n if (this[FLOWING] && this[DATALISTENERS] === 0) {\n this[FLOWING] = false\n }\n this[PIPES] = []\n } else this[PIPES].splice(this[PIPES].indexOf(p), 1)\n p.unpipe()\n }\n }\n\n /**\n * Alias for {@link Minipass#on}\n */\n addListener<Event extends keyof Events>(\n ev: Event,\n handler: (...args: Events[Event]) => any\n ): this {\n return this.on(ev, handler)\n }\n\n /**\n * Mostly identical to `EventEmitter.on`, with the following\n * behavior differences to prevent data loss and unnecessary hangs:\n *\n * - Adding a 'data' event handler will trigger the flow of data\n *\n * - Adding a 'readable' event handler when there is data waiting to be read\n * will cause 'readable' to be emitted immediately.\n *\n * - Adding an 'endish' event handler ('end', 'finish', etc.) which has\n * already passed will cause the event to be emitted immediately and all\n * handlers removed.\n *\n * - Adding an 'error' event handler after an error has been emitted will\n * cause the event to be re-emitted immediately with the error previously\n * raised.\n */\n on<Event extends keyof Events>(\n ev: Event,\n handler: (...args: Events[Event]) => any\n ): this {\n const ret = super.on(\n ev as string | symbol,\n handler as (...a: any[]) => any\n )\n if (ev === 'data') {\n this[DISCARDED] = false\n this[DATALISTENERS]++\n if (!this[PIPES].length && !this[FLOWING]) {\n this[RESUME]()\n }\n } else if (ev === 'readable' && this[BUFFERLENGTH] !== 0) {\n super.emit('readable')\n } else if (isEndish(ev) && this[EMITTED_END]) {\n super.emit(ev)\n this.removeAllListeners(ev)\n } else if (ev === 'error' && this[EMITTED_ERROR]) {\n const h = handler as (...a: Events['error']) => any\n if (this[ASYNC]) defer(() => h.call(this, this[EMITTED_ERROR]))\n else h.call(this, this[EMITTED_ERROR])\n }\n return ret\n }\n\n /**\n * Alias for {@link Minipass#off}\n */\n removeListener<Event extends keyof Events>(\n ev: Event,\n handler: (...args: Events[Event]) => any\n ) {\n return this.off(ev, handler)\n }\n\n /**\n * Mostly identical to `EventEmitter.off`\n *\n * If a 'data' event handler is removed, and it was the last consumer\n * (ie, there are no pipe destinations or other 'data' event listeners),\n * then the flow of data will stop until there is another consumer or\n * {@link Minipass#resume} is explicitly called.\n */\n off<Event extends keyof Events>(\n ev: Event,\n handler: (...args: Events[Event]) => any\n ) {\n const ret = super.off(\n ev as string | symbol,\n handler as (...a: any[]) => any\n )\n // if we previously had listeners, and now we don't, and we don't\n // have any pipes, then stop the flow, unless it's been explicitly\n // put in a discarded flowing state via stream.resume().\n if (ev === 'data') {\n this[DATALISTENERS] = this.listeners('data').length\n if (\n this[DATALISTENERS] === 0 &&\n !this[DISCARDED] &&\n !this[PIPES].length\n ) {\n this[FLOWING] = false\n }\n }\n return ret\n }\n\n /**\n * Mostly identical to `EventEmitter.removeAllListeners`\n *\n * If all 'data' event handlers are removed, and they were the last consumer\n * (ie, there are no pipe destinations), then the flow of data will stop\n * until there is another consumer or {@link Minipass#resume} is explicitly\n * called.\n */\n removeAllListeners<Event extends keyof Events>(ev?: Event) {\n const ret = super.removeAllListeners(ev as string | symbol | undefined)\n if (ev === 'data' || ev === undefined) {\n this[DATALISTENERS] = 0\n if (!this[DISCARDED] && !this[PIPES].length) {\n this[FLOWING] = false\n }\n }\n return ret\n }\n\n /**\n * true if the 'end' event has been emitted\n */\n get emittedEnd() {\n return this[EMITTED_END]\n }\n\n [MAYBE_EMIT_END]() {\n if (\n !this[EMITTING_END] &&\n !this[EMITTED_END] &&\n !this[DESTROYED] &&\n this[BUFFER].length === 0 &&\n this[EOF]\n ) {\n this[EMITTING_END] = true\n this.emit('end')\n this.emit('prefinish')\n this.emit('finish')\n if (this[CLOSED]) this.emit('close')\n this[EMITTING_END] = false\n }\n }\n\n /**\n * Mostly identical to `EventEmitter.emit`, with the following\n * behavior differences to prevent data loss and unnecessary hangs:\n *\n * If the stream has been destroyed, and the event is something other\n * than 'close' or 'error', then `false` is returned and no handlers\n * are called.\n *\n * If the event is 'end', and has already been emitted, then the event\n * is ignored. If the stream is in a paused or non-flowing state, then\n * the event will be deferred until data flow resumes. If the stream is\n * async, then handlers will be called on the next tick rather than\n * immediately.\n *\n * If the event is 'close', and 'end' has not yet been emitted, then\n * the event will be deferred until after 'end' is emitted.\n *\n * If the event is 'error', and an AbortSignal was provided for the stream,\n * and there are no listeners, then the event is ignored, matching the\n * behavior of node core streams in the presense of an AbortSignal.\n *\n * If the event is 'finish' or 'prefinish', then all listeners will be\n * removed after emitting the event, to prevent double-firing.\n */\n emit<Event extends keyof Events>(\n ev: Event,\n ...args: Events[Event]\n ): boolean {\n const data = args[0]\n // error and close are only events allowed after calling destroy()\n if (\n ev !== 'error' &&\n ev !== 'close' &&\n ev !== DESTROYED &&\n this[DESTROYED]\n ) {\n return false\n } else if (ev === 'data') {\n return !this[OBJECTMODE] && !data\n ? false\n : this[ASYNC]\n ? (defer(() => this[EMITDATA](data as RType)), true)\n : this[EMITDATA](data as RType)\n } else if (ev === 'end') {\n return this[EMITEND]()\n } else if (ev === 'close') {\n this[CLOSED] = true\n // don't emit close before 'end' and 'finish'\n if (!this[EMITTED_END] && !this[DESTROYED]) return false\n const ret = super.emit('close')\n this.removeAllListeners('close')\n return ret\n } else if (ev === 'error') {\n this[EMITTED_ERROR] = data\n super.emit(ERROR, data)\n const ret =\n !this[SIGNAL] || this.listeners('error').length\n ? super.emit('error', data)\n : false\n this[MAYBE_EMIT_END]()\n return ret\n } else if (ev === 'resume') {\n const ret = super.emit('resume')\n this[MAYBE_EMIT_END]()\n return ret\n } else if (ev === 'finish' || ev === 'prefinish') {\n const ret = super.emit(ev)\n this.removeAllListeners(ev)\n return ret\n }\n\n // Some other unknown event\n const ret = super.emit(ev as string, ...args)\n this[MAYBE_EMIT_END]()\n return ret\n }\n\n [EMITDATA](data: RType) {\n for (const p of this[PIPES]) {\n if (p.dest.write(data as RType) === false) this.pause()\n }\n const ret = this[DISCARDED] ? false : super.emit('data', data)\n this[MAYBE_EMIT_END]()\n return ret\n }\n\n [EMITEND]() {\n if (this[EMITTED_END]) return false\n\n this[EMITTED_END] = true\n this.readable = false\n return this[ASYNC]\n ? (defer(() => this[EMITEND2]()), true)\n : this[EMITEND2]()\n }\n\n [EMITEND2]() {\n if (this[DECODER]) {\n const data = this[DECODER].end()\n if (data) {\n for (const p of this[PIPES]) {\n p.dest.write(data as RType)\n }\n if (!this[DISCARDED]) super.emit('data', data)\n }\n }\n\n for (const p of this[PIPES]) {\n p.end()\n }\n const ret = super.emit('end')\n this.removeAllListeners('end')\n return ret\n }\n\n /**\n * Return a Promise that resolves to an array of all emitted data once\n * the stream ends.\n */\n async collect(): Promise<RType[] & { dataLength: number }> {\n const buf: RType[] & { dataLength: number } = Object.assign([], {\n dataLength: 0,\n })\n if (!this[OBJECTMODE]) buf.dataLength = 0\n // set the promise first, in case an error is raised\n // by triggering the flow here.\n const p = this.promise()\n this.on('data', c => {\n buf.push(c)\n if (!this[OBJECTMODE])\n buf.dataLength += (c as Minipass.BufferOrString).length\n })\n await p\n return buf\n }\n\n /**\n * Return a Promise that resolves to the concatenation of all emitted data\n * once the stream ends.\n *\n * Not allowed on objectMode streams.\n */\n async concat(): Promise<RType> {\n if (this[OBJECTMODE]) {\n throw new Error('cannot concat in objectMode')\n }\n const buf = await this.collect()\n return (\n this[ENCODING]\n ? buf.join('')\n : Buffer.concat(buf as Buffer[], buf.dataLength)\n ) as RType\n }\n\n /**\n * Return a void Promise that resolves once the stream ends.\n */\n async promise(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n this.on(DESTROYED, () => reject(new Error('stream destroyed')))\n this.on('error', er => reject(er))\n this.on('end', () => resolve())\n })\n }\n\n /**\n * Asynchronous `for await of` iteration.\n *\n * This will continue emitting all chunks until the stream terminates.\n */\n [Symbol.asyncIterator](): AsyncGenerator<RType, void, void> {\n // set this up front, in case the consumer doesn't call next()\n // right away.\n this[DISCARDED] = false\n let stopped = false\n const stop = async (): Promise<IteratorReturnResult<void>> => {\n this.pause()\n stopped = true\n return { value: undefined, done: true }\n }\n const next = (): Promise<IteratorResult<RType, void>> => {\n if (stopped) return stop()\n const res = this.read()\n if (res !== null) return Promise.resolve({ done: false, value: res })\n\n if (this[EOF]) return stop()\n\n let resolve!: (res: IteratorResult<RType>) => void\n let reject!: (er: unknown) => void\n const onerr = (er: unknown) => {\n this.off('data', ondata)\n this.off('end', onend)\n this.off(DESTROYED, ondestroy)\n stop()\n reject(er)\n }\n const ondata = (value: RType) => {\n this.off('error', onerr)\n this.off('end', onend)\n this.off(DESTROYED, ondestroy)\n this.pause()\n resolve({ value, done: !!this[EOF] })\n }\n const onend = () => {\n this.off('error', onerr)\n this.off('data', ondata)\n this.off(DESTROYED, ondestroy)\n stop()\n resolve({ done: true, value: undefined })\n }\n const ondestroy = () => onerr(new Error('stream destroyed'))\n return new Promise<IteratorResult<RType>>((res, rej) => {\n reject = rej\n resolve = res\n this.once(DESTROYED, ondestroy)\n this.once('error', onerr)\n this.once('end', onend)\n this.once('data', ondata)\n })\n }\n\n return {\n next,\n throw: stop,\n return: stop,\n [Symbol.asyncIterator]() {\n return this\n },\n [Symbol.asyncDispose]: async () => {},\n }\n }\n\n /**\n * Synchronous `for of` iteration.\n *\n * The iteration will terminate when the internal buffer runs out, even\n * if the stream has not yet terminated.\n */\n [Symbol.iterator](): Generator<RType, void, void> {\n // set this up front, in case the consumer doesn't call next()\n // right away.\n this[DISCARDED] = false\n let stopped = false\n const stop = (): IteratorReturnResult<void> => {\n this.pause()\n this.off(ERROR, stop)\n this.off(DESTROYED, stop)\n this.off('end', stop)\n stopped = true\n return { done: true, value: undefined }\n }\n\n const next = (): IteratorResult<RType, void> => {\n if (stopped) return stop()\n const value = this.read()\n return value === null ? stop() : { done: false, value }\n }\n\n this.once('end', stop)\n this.once(ERROR, stop)\n this.once(DESTROYED, stop)\n\n return {\n next,\n throw: stop,\n return: stop,\n [Symbol.iterator]() {\n return this\n },\n [Symbol.dispose]: () => {},\n }\n }\n\n /**\n * Destroy a stream, preventing it from being used for any further purpose.\n *\n * If the stream has a `close()` method, then it will be called on\n * destruction.\n *\n * After destruction, any attempt to write data, read data, or emit most\n * events will be ignored.\n *\n * If an error argument is provided, then it will be emitted in an\n * 'error' event.\n */\n destroy(er?: unknown) {\n if (this[DESTROYED]) {\n if (er) this.emit('error', er)\n else this.emit(DESTROYED)\n return this\n }\n\n this[DESTROYED] = true\n this[DISCARDED] = true\n\n // throw away all buffered data, it's never coming out\n this[BUFFER].length = 0\n this[BUFFERLENGTH] = 0\n\n const wc = this as Minipass<RType, WType, Events> & {\n close?: () => void\n }\n if (typeof wc.close === 'function' && !this[CLOSED]) wc.close()\n\n if (er) this.emit('error', er)\n // if no error to emit, still reject pending promises\n else this.emit(DESTROYED)\n\n return this\n }\n\n /**\n * Alias for {@link isStream}\n *\n * Former export location, maintained for backwards compatibility.\n *\n * @deprecated\n */\n static get isStream() {\n return isStream\n }\n}\n","// this is just a very light wrapper around 2 arrays with an offset index\n\nimport { GLOBSTAR } from 'minimatch'\nexport type MMPattern = string | RegExp | typeof GLOBSTAR\n\n// an array of length >= 1\nexport type PatternList = [p: MMPattern, ...rest: MMPattern[]]\nexport type UNCPatternList = [\n p0: '',\n p1: '',\n p2: string,\n p3: string,\n ...rest: MMPattern[],\n]\nexport type DrivePatternList = [p0: string, ...rest: MMPattern[]]\nexport type AbsolutePatternList = [p0: '', ...rest: MMPattern[]]\nexport type GlobList = [p: string, ...rest: string[]]\n\nconst isPatternList = (pl: MMPattern[]): pl is PatternList =>\n pl.length >= 1\nconst isGlobList = (gl: string[]): gl is GlobList => gl.length >= 1\n\nconst customInspect = Symbol.for('nodejs.util.inspect.custom')\n\n/**\n * An immutable-ish view on an array of glob parts and their parsed\n * results\n */\nexport class Pattern {\n readonly #patternList: PatternList\n readonly #globList: GlobList\n readonly #index: number\n readonly length: number\n readonly #platform: NodeJS.Platform\n #rest?: Pattern | null\n #globString?: string\n #isDrive?: boolean\n #isUNC?: boolean\n #isAbsolute?: boolean\n #followGlobstar: boolean = true\n\n constructor(\n patternList: MMPattern[],\n globList: string[],\n index: number,\n platform: NodeJS.Platform,\n ) {\n if (!isPatternList(patternList)) {\n throw new TypeError('empty pattern list')\n }\n if (!isGlobList(globList)) {\n throw new TypeError('empty glob list')\n }\n if (globList.length !== patternList.length) {\n throw new TypeError('mismatched pattern list and glob list lengths')\n }\n this.length = patternList.length\n if (index < 0 || index >= this.length) {\n throw new TypeError('index out of range')\n }\n this.#patternList = patternList\n this.#globList = globList\n this.#index = index\n this.#platform = platform\n\n // normalize root entries of absolute patterns on initial creation.\n if (this.#index === 0) {\n // c: => ['c:/']\n // C:/ => ['C:/']\n // C:/x => ['C:/', 'x']\n // //host/share => ['//host/share/']\n // //host/share/ => ['//host/share/']\n // //host/share/x => ['//host/share/', 'x']\n // /etc => ['/', 'etc']\n // / => ['/']\n if (this.isUNC()) {\n // '' / '' / 'host' / 'share'\n const [p0, p1, p2, p3, ...prest] = this.#patternList\n const [g0, g1, g2, g3, ...grest] = this.#globList\n if (prest[0] === '') {\n // ends in /\n prest.shift()\n grest.shift()\n }\n const p = [p0, p1, p2, p3, ''].join('/')\n const g = [g0, g1, g2, g3, ''].join('/')\n this.#patternList = [p, ...prest]\n this.#globList = [g, ...grest]\n this.length = this.#patternList.length\n } else if (this.isDrive() || this.isAbsolute()) {\n const [p1, ...prest] = this.#patternList\n const [g1, ...grest] = this.#globList\n if (prest[0] === '') {\n // ends in /\n prest.shift()\n grest.shift()\n }\n const p = (p1 as string) + '/'\n const g = g1 + '/'\n this.#patternList = [p, ...prest]\n this.#globList = [g, ...grest]\n this.length = this.#patternList.length\n }\n }\n }\n\n [customInspect]() {\n return 'Pattern <' + this.#globList.slice(this.#index).join('/') + '>'\n }\n\n /**\n * The first entry in the parsed list of patterns\n */\n pattern(): MMPattern {\n return this.#patternList[this.#index] as MMPattern\n }\n\n /**\n * true of if pattern() returns a string\n */\n isString(): boolean {\n return typeof this.#patternList[this.#index] === 'string'\n }\n /**\n * true of if pattern() returns GLOBSTAR\n */\n isGlobstar(): boolean {\n return this.#patternList[this.#index] === GLOBSTAR\n }\n /**\n * true if pattern() returns a regexp\n */\n isRegExp(): boolean {\n return this.#patternList[this.#index] instanceof RegExp\n }\n\n /**\n * The /-joined set of glob parts that make up this pattern\n */\n globString(): string {\n return (this.#globString =\n this.#globString ||\n (this.#index === 0 ?\n this.isAbsolute() ?\n this.#globList[0] + this.#globList.slice(1).join('/')\n : this.#globList.join('/')\n : this.#globList.slice(this.#index).join('/')))\n }\n\n /**\n * true if there are more pattern parts after this one\n */\n hasMore(): boolean {\n return this.length > this.#index + 1\n }\n\n /**\n * The rest of the pattern after this part, or null if this is the end\n */\n rest(): Pattern | null {\n if (this.#rest !== undefined) return this.#rest\n if (!this.hasMore()) return (this.#rest = null)\n this.#rest = new Pattern(\n this.#patternList,\n this.#globList,\n this.#index + 1,\n this.#platform,\n )\n this.#rest.#isAbsolute = this.#isAbsolute\n this.#rest.#isUNC = this.#isUNC\n this.#rest.#isDrive = this.#isDrive\n return this.#rest\n }\n\n /**\n * true if the pattern represents a //unc/path/ on windows\n */\n isUNC(): boolean {\n const pl = this.#patternList\n return this.#isUNC !== undefined ?\n this.#isUNC\n : (this.#isUNC =\n this.#platform === 'win32' &&\n this.#index === 0 &&\n pl[0] === '' &&\n pl[1] === '' &&\n typeof pl[2] === 'string' &&\n !!pl[2] &&\n typeof pl[3] === 'string' &&\n !!pl[3])\n }\n\n // pattern like C:/...\n // split = ['C:', ...]\n // XXX: would be nice to handle patterns like `c:*` to test the cwd\n // in c: for *, but I don't know of a way to even figure out what that\n // cwd is without actually chdir'ing into it?\n /**\n * True if the pattern starts with a drive letter on Windows\n */\n isDrive(): boolean {\n const pl = this.#patternList\n return this.#isDrive !== undefined ?\n this.#isDrive\n : (this.#isDrive =\n this.#platform === 'win32' &&\n this.#index === 0 &&\n this.length > 1 &&\n typeof pl[0] === 'string' &&\n /^[a-z]:$/i.test(pl[0]))\n }\n\n // pattern = '/' or '/...' or '/x/...'\n // split = ['', ''] or ['', ...] or ['', 'x', ...]\n // Drive and UNC both considered absolute on windows\n /**\n * True if the pattern is rooted on an absolute path\n */\n isAbsolute(): boolean {\n const pl = this.#patternList\n return this.#isAbsolute !== undefined ?\n this.#isAbsolute\n : (this.#isAbsolute =\n (pl[0] === '' && pl.length > 1) ||\n this.isDrive() ||\n this.isUNC())\n }\n\n /**\n * consume the root of the pattern, and return it\n */\n root(): string {\n const p = this.#patternList[0]\n return (\n typeof p === 'string' && this.isAbsolute() && this.#index === 0\n ) ?\n p\n : ''\n }\n\n /**\n * Check to see if the current globstar pattern is allowed to follow\n * a symbolic link.\n */\n checkFollowGlobstar(): boolean {\n return !(\n this.#index === 0 ||\n !this.isGlobstar() ||\n !this.#followGlobstar\n )\n }\n\n /**\n * Mark that the current globstar pattern is following a symbolic link\n */\n markFollowGlobstar(): boolean {\n if (this.#index === 0 || !this.isGlobstar() || !this.#followGlobstar)\n return false\n this.#followGlobstar = false\n return true\n }\n}\n","// give it a pattern, and it'll be able to tell you if\n// a given path should be ignored.\n// Ignoring a path ignores its children if the pattern ends in /**\n// Ignores are always parsed in dot:true mode\n\nimport { Minimatch, MinimatchOptions } from 'minimatch'\nimport { Path } from 'path-scurry'\nimport { Pattern } from './pattern.js'\nimport { GlobWalkerOpts } from './walker.js'\n\nexport interface IgnoreLike {\n ignored?: (p: Path) => boolean\n childrenIgnored?: (p: Path) => boolean\n add?: (ignore: string) => void\n}\n\nconst defaultPlatform: NodeJS.Platform =\n (\n typeof process === 'object' &&\n process &&\n typeof process.platform === 'string'\n ) ?\n process.platform\n : 'linux'\n\n/**\n * Class used to process ignored patterns\n */\nexport class Ignore implements IgnoreLike {\n relative: Minimatch[]\n relativeChildren: Minimatch[]\n absolute: Minimatch[]\n absoluteChildren: Minimatch[]\n platform: NodeJS.Platform\n mmopts: MinimatchOptions\n\n constructor(\n ignored: string[],\n {\n nobrace,\n nocase,\n noext,\n noglobstar,\n platform = defaultPlatform,\n }: GlobWalkerOpts,\n ) {\n this.relative = []\n this.absolute = []\n this.relativeChildren = []\n this.absoluteChildren = []\n this.platform = platform\n this.mmopts = {\n dot: true,\n nobrace,\n nocase,\n noext,\n noglobstar,\n optimizationLevel: 2,\n platform,\n nocomment: true,\n nonegate: true,\n }\n for (const ign of ignored) this.add(ign)\n }\n\n add(ign: string) {\n // this is a little weird, but it gives us a clean set of optimized\n // minimatch matchers, without getting tripped up if one of them\n // ends in /** inside a brace section, and it's only inefficient at\n // the start of the walk, not along it.\n // It'd be nice if the Pattern class just had a .test() method, but\n // handling globstars is a bit of a pita, and that code already lives\n // in minimatch anyway.\n // Another way would be if maybe Minimatch could take its set/globParts\n // as an option, and then we could at least just use Pattern to test\n // for absolute-ness.\n // Yet another way, Minimatch could take an array of glob strings, and\n // a cwd option, and do the right thing.\n const mm = new Minimatch(ign, this.mmopts)\n for (let i = 0; i < mm.set.length; i++) {\n const parsed = mm.set[i]\n const globParts = mm.globParts[i]\n /* c8 ignore start */\n if (!parsed || !globParts) {\n throw new Error('invalid pattern object')\n }\n // strip off leading ./ portions\n // https://github.com/isaacs/node-glob/issues/570\n while (parsed[0] === '.' && globParts[0] === '.') {\n parsed.shift()\n globParts.shift()\n }\n /* c8 ignore stop */\n const p = new Pattern(parsed, globParts, 0, this.platform)\n const m = new Minimatch(p.globString(), this.mmopts)\n const children = globParts[globParts.length - 1] === '**'\n const absolute = p.isAbsolute()\n if (absolute) this.absolute.push(m)\n else this.relative.push(m)\n if (children) {\n if (absolute) this.absoluteChildren.push(m)\n else this.relativeChildren.push(m)\n }\n }\n }\n\n ignored(p: Path): boolean {\n const fullpath = p.fullpath()\n const fullpaths = `${fullpath}/`\n const relative = p.relative() || '.'\n const relatives = `${relative}/`\n for (const m of this.relative) {\n if (m.match(relative) || m.match(relatives)) return true\n }\n for (const m of this.absolute) {\n if (m.match(fullpath) || m.match(fullpaths)) return true\n }\n return false\n }\n\n childrenIgnored(p: Path): boolean {\n const fullpath = p.fullpath() + '/'\n const relative = (p.relative() || '.') + '/'\n for (const m of this.relativeChildren) {\n if (m.match(relative)) return true\n }\n for (const m of this.absoluteChildren) {\n if (m.match(fullpath)) return true\n }\n return false\n }\n}\n","// synchronous utility for filtering entries and calculating subwalks\n\nimport { GLOBSTAR, MMRegExp } from 'minimatch'\nimport { Path } from 'path-scurry'\nimport { MMPattern, Pattern } from './pattern.js'\nimport { GlobWalkerOpts } from './walker.js'\n\n/**\n * A cache of which patterns have been processed for a given Path\n */\nexport class HasWalkedCache {\n store: Map<string, Set<string>>\n constructor(store: Map<string, Set<string>> = new Map()) {\n this.store = store\n }\n copy() {\n return new HasWalkedCache(new Map(this.store))\n }\n hasWalked(target: Path, pattern: Pattern) {\n return this.store.get(target.fullpath())?.has(pattern.globString())\n }\n storeWalked(target: Path, pattern: Pattern) {\n const fullpath = target.fullpath()\n const cached = this.store.get(fullpath)\n if (cached) cached.add(pattern.globString())\n else this.store.set(fullpath, new Set([pattern.globString()]))\n }\n}\n\n/**\n * A record of which paths have been matched in a given walk step,\n * and whether they only are considered a match if they are a directory,\n * and whether their absolute or relative path should be returned.\n */\nexport class MatchRecord {\n store: Map<Path, number> = new Map()\n add(target: Path, absolute: boolean, ifDir: boolean) {\n const n = (absolute ? 2 : 0) | (ifDir ? 1 : 0)\n const current = this.store.get(target)\n this.store.set(target, current === undefined ? n : n & current)\n }\n // match, absolute, ifdir\n entries(): [Path, boolean, boolean][] {\n return [...this.store.entries()].map(([path, n]) => [\n path,\n !!(n & 2),\n !!(n & 1),\n ])\n }\n}\n\n/**\n * A collection of patterns that must be processed in a subsequent step\n * for a given path.\n */\nexport class SubWalks {\n store: Map<Path, Pattern[]> = new Map()\n add(target: Path, pattern: Pattern) {\n if (!target.canReaddir()) {\n return\n }\n const subs = this.store.get(target)\n if (subs) {\n if (!subs.find(p => p.globString() === pattern.globString())) {\n subs.push(pattern)\n }\n } else this.store.set(target, [pattern])\n }\n get(target: Path): Pattern[] {\n const subs = this.store.get(target)\n /* c8 ignore start */\n if (!subs) {\n throw new Error('attempting to walk unknown path')\n }\n /* c8 ignore stop */\n return subs\n }\n entries(): [Path, Pattern[]][] {\n return this.keys().map(k => [k, this.store.get(k) as Pattern[]])\n }\n keys(): Path[] {\n return [...this.store.keys()].filter(t => t.canReaddir())\n }\n}\n\n/**\n * The class that processes patterns for a given path.\n *\n * Handles child entry filtering, and determining whether a path's\n * directory contents must be read.\n */\nexport class Processor {\n hasWalkedCache: HasWalkedCache\n matches = new MatchRecord()\n subwalks = new SubWalks()\n patterns?: Pattern[]\n follow: boolean\n dot: boolean\n opts: GlobWalkerOpts\n\n constructor(opts: GlobWalkerOpts, hasWalkedCache?: HasWalkedCache) {\n this.opts = opts\n this.follow = !!opts.follow\n this.dot = !!opts.dot\n this.hasWalkedCache =\n hasWalkedCache ? hasWalkedCache.copy() : new HasWalkedCache()\n }\n\n processPatterns(target: Path, patterns: Pattern[]) {\n this.patterns = patterns\n const processingSet: [Path, Pattern][] = patterns.map(p => [target, p])\n\n // map of paths to the magic-starting subwalks they need to walk\n // first item in patterns is the filter\n\n for (let [t, pattern] of processingSet) {\n this.hasWalkedCache.storeWalked(t, pattern)\n\n const root = pattern.root()\n const absolute = pattern.isAbsolute() && this.opts.absolute !== false\n\n // start absolute patterns at root\n if (root) {\n t = t.resolve(\n root === '/' && this.opts.root !== undefined ?\n this.opts.root\n : root,\n )\n const rest = pattern.rest()\n if (!rest) {\n this.matches.add(t, true, false)\n continue\n } else {\n pattern = rest\n }\n }\n\n if (t.isENOENT()) continue\n\n let p: MMPattern\n let rest: Pattern | null\n let changed = false\n while (\n typeof (p = pattern.pattern()) === 'string' &&\n (rest = pattern.rest())\n ) {\n const c = t.resolve(p)\n t = c\n pattern = rest\n changed = true\n }\n p = pattern.pattern()\n rest = pattern.rest()\n if (changed) {\n if (this.hasWalkedCache.hasWalked(t, pattern)) continue\n this.hasWalkedCache.storeWalked(t, pattern)\n }\n\n // now we have either a final string for a known entry,\n // more strings for an unknown entry,\n // or a pattern starting with magic, mounted on t.\n if (typeof p === 'string') {\n // must not be final entry, otherwise we would have\n // concatenated it earlier.\n const ifDir = p === '..' || p === '' || p === '.'\n this.matches.add(t.resolve(p), absolute, ifDir)\n continue\n } else if (p === GLOBSTAR) {\n // if no rest, match and subwalk pattern\n // if rest, process rest and subwalk pattern\n // if it's a symlink, but we didn't get here by way of a\n // globstar match (meaning it's the first time THIS globstar\n // has traversed a symlink), then we follow it. Otherwise, stop.\n if (\n !t.isSymbolicLink() ||\n this.follow ||\n pattern.checkFollowGlobstar()\n ) {\n this.subwalks.add(t, pattern)\n }\n const rp = rest?.pattern()\n const rrest = rest?.rest()\n if (!rest || ((rp === '' || rp === '.') && !rrest)) {\n // only HAS to be a dir if it ends in **/ or **/.\n // but ending in ** will match files as well.\n this.matches.add(t, absolute, rp === '' || rp === '.')\n } else {\n if (rp === '..') {\n // this would mean you're matching **/.. at the fs root,\n // and no thanks, I'm not gonna test that specific case.\n /* c8 ignore start */\n const tp = t.parent || t\n /* c8 ignore stop */\n if (!rrest) this.matches.add(tp, absolute, true)\n else if (!this.hasWalkedCache.hasWalked(tp, rrest)) {\n this.subwalks.add(tp, rrest)\n }\n }\n }\n } else if (p instanceof RegExp) {\n this.subwalks.add(t, pattern)\n }\n }\n\n return this\n }\n\n subwalkTargets(): Path[] {\n return this.subwalks.keys()\n }\n\n child() {\n return new Processor(this.opts, this.hasWalkedCache)\n }\n\n // return a new Processor containing the subwalks for each\n // child entry, and a set of matches, and\n // a hasWalkedCache that's a copy of this one\n // then we're going to call\n filterEntries(parent: Path, entries: Path[]): Processor {\n const patterns = this.subwalks.get(parent)\n // put matches and entry walks into the results processor\n const results = this.child()\n for (const e of entries) {\n for (const pattern of patterns) {\n const absolute = pattern.isAbsolute()\n const p = pattern.pattern()\n const rest = pattern.rest()\n if (p === GLOBSTAR) {\n results.testGlobstar(e, pattern, rest, absolute)\n } else if (p instanceof RegExp) {\n results.testRegExp(e, p, rest, absolute)\n } else {\n results.testString(e, p, rest, absolute)\n }\n }\n }\n return results\n }\n\n testGlobstar(\n e: Path,\n pattern: Pattern,\n rest: Pattern | null,\n absolute: boolean,\n ) {\n if (this.dot || !e.name.startsWith('.')) {\n if (!pattern.hasMore()) {\n this.matches.add(e, absolute, false)\n }\n if (e.canReaddir()) {\n // if we're in follow mode or it's not a symlink, just keep\n // testing the same pattern. If there's more after the globstar,\n // then this symlink consumes the globstar. If not, then we can\n // follow at most ONE symlink along the way, so we mark it, which\n // also checks to ensure that it wasn't already marked.\n if (this.follow || !e.isSymbolicLink()) {\n this.subwalks.add(e, pattern)\n } else if (e.isSymbolicLink()) {\n if (rest && pattern.checkFollowGlobstar()) {\n this.subwalks.add(e, rest)\n } else if (pattern.markFollowGlobstar()) {\n this.subwalks.add(e, pattern)\n }\n }\n }\n }\n // if the NEXT thing matches this entry, then also add\n // the rest.\n if (rest) {\n const rp = rest.pattern()\n if (\n typeof rp === 'string' &&\n // dots and empty were handled already\n rp !== '..' &&\n rp !== '' &&\n rp !== '.'\n ) {\n this.testString(e, rp, rest.rest(), absolute)\n } else if (rp === '..') {\n /* c8 ignore start */\n const ep = e.parent || e\n /* c8 ignore stop */\n this.subwalks.add(ep, rest)\n } else if (rp instanceof RegExp) {\n this.testRegExp(e, rp, rest.rest(), absolute)\n }\n }\n }\n\n testRegExp(\n e: Path,\n p: MMRegExp,\n rest: Pattern | null,\n absolute: boolean,\n ) {\n if (!p.test(e.name)) return\n if (!rest) {\n this.matches.add(e, absolute, false)\n } else {\n this.subwalks.add(e, rest)\n }\n }\n\n testString(e: Path, p: string, rest: Pattern | null, absolute: boolean) {\n // should never happen?\n if (!e.isNamed(p)) return\n if (!rest) {\n this.matches.add(e, absolute, false)\n } else {\n this.subwalks.add(e, rest)\n }\n }\n}\n","/**\n * Single-use utility classes to provide functionality to the {@link Glob}\n * methods.\n *\n * @module\n */\nimport { Minipass } from 'minipass'\nimport { Path } from 'path-scurry'\nimport { Ignore, IgnoreLike } from './ignore.js'\n\n// XXX can we somehow make it so that it NEVER processes a given path more than\n// once, enough that the match set tracking is no longer needed? that'd speed\n// things up a lot. Or maybe bring back nounique, and skip it in that case?\n\n// a single minimatch set entry with 1 or more parts\nimport { Pattern } from './pattern.js'\nimport { Processor } from './processor.js'\n\nexport interface GlobWalkerOpts {\n absolute?: boolean\n allowWindowsEscape?: boolean\n cwd?: string | URL\n dot?: boolean\n dotRelative?: boolean\n follow?: boolean\n ignore?: string | string[] | IgnoreLike\n mark?: boolean\n matchBase?: boolean\n // Note: maxDepth here means \"maximum actual Path.depth()\",\n // not \"maximum depth beyond cwd\"\n maxDepth?: number\n nobrace?: boolean\n nocase?: boolean\n nodir?: boolean\n noext?: boolean\n noglobstar?: boolean\n platform?: NodeJS.Platform\n posix?: boolean\n realpath?: boolean\n root?: string\n stat?: boolean\n signal?: AbortSignal\n windowsPathsNoEscape?: boolean\n withFileTypes?: boolean\n includeChildMatches?: boolean\n}\n\nexport type GWOFileTypesTrue = GlobWalkerOpts & {\n withFileTypes: true\n}\nexport type GWOFileTypesFalse = GlobWalkerOpts & {\n withFileTypes: false\n}\nexport type GWOFileTypesUnset = GlobWalkerOpts & {\n withFileTypes?: undefined\n}\n\nexport type Result<O extends GlobWalkerOpts> =\n O extends GWOFileTypesTrue ? Path\n : O extends GWOFileTypesFalse ? string\n : O extends GWOFileTypesUnset ? string\n : Path | string\n\nexport type Matches<O extends GlobWalkerOpts> =\n O extends GWOFileTypesTrue ? Set<Path>\n : O extends GWOFileTypesFalse ? Set<string>\n : O extends GWOFileTypesUnset ? Set<string>\n : Set<Path | string>\n\nexport type MatchStream<O extends GlobWalkerOpts> = Minipass<\n Result<O>,\n Result<O>\n>\n\nconst makeIgnore = (\n ignore: string | string[] | IgnoreLike,\n opts: GlobWalkerOpts,\n): IgnoreLike =>\n typeof ignore === 'string' ? new Ignore([ignore], opts)\n : Array.isArray(ignore) ? new Ignore(ignore, opts)\n : ignore\n\n/**\n * basic walking utilities that all the glob walker types use\n */\nexport abstract class GlobUtil<O extends GlobWalkerOpts = GlobWalkerOpts> {\n path: Path\n patterns: Pattern[]\n opts: O\n seen: Set<Path> = new Set<Path>()\n paused: boolean = false\n aborted: boolean = false\n #onResume: (() => any)[] = []\n #ignore?: IgnoreLike\n #sep: '\\\\' | '/'\n signal?: AbortSignal\n maxDepth: number\n includeChildMatches: boolean\n\n constructor(patterns: Pattern[], path: Path, opts: O)\n constructor(patterns: Pattern[], path: Path, opts: O) {\n this.patterns = patterns\n this.path = path\n this.opts = opts\n this.#sep = !opts.posix && opts.platform === 'win32' ? '\\\\' : '/'\n this.includeChildMatches = opts.includeChildMatches !== false\n if (opts.ignore || !this.includeChildMatches) {\n this.#ignore = makeIgnore(opts.ignore ?? [], opts)\n if (\n !this.includeChildMatches &&\n typeof this.#ignore.add !== 'function'\n ) {\n const m = 'cannot ignore child matches, ignore lacks add() method.'\n throw new Error(m)\n }\n }\n // ignore, always set with maxDepth, but it's optional on the\n // GlobOptions type\n /* c8 ignore start */\n this.maxDepth = opts.maxDepth || Infinity\n /* c8 ignore stop */\n if (opts.signal) {\n this.signal = opts.signal\n this.signal.addEventListener('abort', () => {\n this.#onResume.length = 0\n })\n }\n }\n\n #ignored(path: Path): boolean {\n return this.seen.has(path) || !!this.#ignore?.ignored?.(path)\n }\n #childrenIgnored(path: Path): boolean {\n return !!this.#ignore?.childrenIgnored?.(path)\n }\n\n // backpressure mechanism\n pause() {\n this.paused = true\n }\n resume() {\n /* c8 ignore start */\n if (this.signal?.aborted) return\n /* c8 ignore stop */\n this.paused = false\n let fn: (() => any) | undefined = undefined\n while (!this.paused && (fn = this.#onResume.shift())) {\n fn()\n }\n }\n onResume(fn: () => any) {\n if (this.signal?.aborted) return\n /* c8 ignore start */\n if (!this.paused) {\n fn()\n } else {\n /* c8 ignore stop */\n this.#onResume.push(fn)\n }\n }\n\n // do the requisite realpath/stat checking, and return the path\n // to add or undefined to filter it out.\n async matchCheck(e: Path, ifDir: boolean): Promise<Path | undefined> {\n if (ifDir && this.opts.nodir) return undefined\n let rpc: Path | undefined\n if (this.opts.realpath) {\n rpc = e.realpathCached() || (await e.realpath())\n if (!rpc) return undefined\n e = rpc\n }\n const needStat = e.isUnknown() || this.opts.stat\n const s = needStat ? await e.lstat() : e\n if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) {\n const target = await s.realpath()\n /* c8 ignore start */\n if (target && (target.isUnknown() || this.opts.stat)) {\n await target.lstat()\n }\n /* c8 ignore stop */\n }\n return this.matchCheckTest(s, ifDir)\n }\n\n matchCheckTest(e: Path | undefined, ifDir: boolean): Path | undefined {\n return (\n e &&\n (this.maxDepth === Infinity || e.depth() <= this.maxDepth) &&\n (!ifDir || e.canReaddir()) &&\n (!this.opts.nodir || !e.isDirectory()) &&\n (!this.opts.nodir ||\n !this.opts.follow ||\n !e.isSymbolicLink() ||\n !e.realpathCached()?.isDirectory()) &&\n !this.#ignored(e)\n ) ?\n e\n : undefined\n }\n\n matchCheckSync(e: Path, ifDir: boolean): Path | undefined {\n if (ifDir && this.opts.nodir) return undefined\n let rpc: Path | undefined\n if (this.opts.realpath) {\n rpc = e.realpathCached() || e.realpathSync()\n if (!rpc) return undefined\n e = rpc\n }\n const needStat = e.isUnknown() || this.opts.stat\n const s = needStat ? e.lstatSync() : e\n if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) {\n const target = s.realpathSync()\n if (target && (target?.isUnknown() || this.opts.stat)) {\n target.lstatSync()\n }\n }\n return this.matchCheckTest(s, ifDir)\n }\n\n abstract matchEmit(p: Result<O>): void\n abstract matchEmit(p: string | Path): void\n\n matchFinish(e: Path, absolute: boolean) {\n if (this.#ignored(e)) return\n // we know we have an ignore if this is false, but TS doesn't\n if (!this.includeChildMatches && this.#ignore?.add) {\n const ign = `${e.relativePosix()}/**`\n this.#ignore.add(ign)\n }\n const abs =\n this.opts.absolute === undefined ? absolute : this.opts.absolute\n this.seen.add(e)\n const mark = this.opts.mark && e.isDirectory() ? this.#sep : ''\n // ok, we have what we need!\n if (this.opts.withFileTypes) {\n this.matchEmit(e)\n } else if (abs) {\n const abs = this.opts.posix ? e.fullpathPosix() : e.fullpath()\n this.matchEmit(abs + mark)\n } else {\n const rel = this.opts.posix ? e.relativePosix() : e.relative()\n const pre =\n this.opts.dotRelative && !rel.startsWith('..' + this.#sep) ?\n '.' + this.#sep\n : ''\n this.matchEmit(!rel ? '.' + mark : pre + rel + mark)\n }\n }\n\n async match(e: Path, absolute: boolean, ifDir: boolean): Promise<void> {\n const p = await this.matchCheck(e, ifDir)\n if (p) this.matchFinish(p, absolute)\n }\n\n matchSync(e: Path, absolute: boolean, ifDir: boolean): void {\n const p = this.matchCheckSync(e, ifDir)\n if (p) this.matchFinish(p, absolute)\n }\n\n walkCB(target: Path, patterns: Pattern[], cb: () => any) {\n /* c8 ignore start */\n if (this.signal?.aborted) cb()\n /* c8 ignore stop */\n this.walkCB2(target, patterns, new Processor(this.opts), cb)\n }\n\n walkCB2(\n target: Path,\n patterns: Pattern[],\n processor: Processor,\n cb: () => any,\n ) {\n if (this.#childrenIgnored(target)) return cb()\n if (this.signal?.aborted) cb()\n if (this.paused) {\n this.onResume(() => this.walkCB2(target, patterns, processor, cb))\n return\n }\n processor.processPatterns(target, patterns)\n\n // done processing. all of the above is sync, can be abstracted out.\n // subwalks is a map of paths to the entry filters they need\n // matches is a map of paths to [absolute, ifDir] tuples.\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n tasks++\n this.match(m, absolute, ifDir).then(() => next())\n }\n\n for (const t of processor.subwalkTargets()) {\n if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {\n continue\n }\n tasks++\n const childrenCached = t.readdirCached()\n if (t.calledReaddir())\n this.walkCB3(t, childrenCached, processor, next)\n else {\n t.readdirCB(\n (_, entries) => this.walkCB3(t, entries, processor, next),\n true,\n )\n }\n }\n\n next()\n }\n\n walkCB3(\n target: Path,\n entries: Path[],\n processor: Processor,\n cb: () => any,\n ) {\n processor = processor.filterEntries(target, entries)\n\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n tasks++\n this.match(m, absolute, ifDir).then(() => next())\n }\n for (const [target, patterns] of processor.subwalks.entries()) {\n tasks++\n this.walkCB2(target, patterns, processor.child(), next)\n }\n\n next()\n }\n\n walkCBSync(target: Path, patterns: Pattern[], cb: () => any) {\n /* c8 ignore start */\n if (this.signal?.aborted) cb()\n /* c8 ignore stop */\n this.walkCB2Sync(target, patterns, new Processor(this.opts), cb)\n }\n\n walkCB2Sync(\n target: Path,\n patterns: Pattern[],\n processor: Processor,\n cb: () => any,\n ) {\n if (this.#childrenIgnored(target)) return cb()\n if (this.signal?.aborted) cb()\n if (this.paused) {\n this.onResume(() =>\n this.walkCB2Sync(target, patterns, processor, cb),\n )\n return\n }\n processor.processPatterns(target, patterns)\n\n // done processing. all of the above is sync, can be abstracted out.\n // subwalks is a map of paths to the entry filters they need\n // matches is a map of paths to [absolute, ifDir] tuples.\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n this.matchSync(m, absolute, ifDir)\n }\n\n for (const t of processor.subwalkTargets()) {\n if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {\n continue\n }\n tasks++\n const children = t.readdirSync()\n this.walkCB3Sync(t, children, processor, next)\n }\n\n next()\n }\n\n walkCB3Sync(\n target: Path,\n entries: Path[],\n processor: Processor,\n cb: () => any,\n ) {\n processor = processor.filterEntries(target, entries)\n\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n this.matchSync(m, absolute, ifDir)\n }\n for (const [target, patterns] of processor.subwalks.entries()) {\n tasks++\n this.walkCB2Sync(target, patterns, processor.child(), next)\n }\n\n next()\n }\n}\n\nexport class GlobWalker<\n O extends GlobWalkerOpts = GlobWalkerOpts,\n> extends GlobUtil<O> {\n matches = new Set<Result<O>>()\n\n constructor(patterns: Pattern[], path: Path, opts: O) {\n super(patterns, path, opts)\n }\n\n matchEmit(e: Result<O>): void {\n this.matches.add(e)\n }\n\n async walk(): Promise<Set<Result<O>>> {\n if (this.signal?.aborted) throw this.signal.reason\n if (this.path.isUnknown()) {\n await this.path.lstat()\n }\n await new Promise((res, rej) => {\n this.walkCB(this.path, this.patterns, () => {\n if (this.signal?.aborted) {\n rej(this.signal.reason)\n } else {\n res(this.matches)\n }\n })\n })\n return this.matches\n }\n\n walkSync(): Set<Result<O>> {\n if (this.signal?.aborted) throw this.signal.reason\n if (this.path.isUnknown()) {\n this.path.lstatSync()\n }\n // nothing for the callback to do, because this never pauses\n this.walkCBSync(this.path, this.patterns, () => {\n if (this.signal?.aborted) throw this.signal.reason\n })\n return this.matches\n }\n}\n\nexport class GlobStream<\n O extends GlobWalkerOpts = GlobWalkerOpts,\n> extends GlobUtil<O> {\n results: Minipass<Result<O>, Result<O>>\n\n constructor(patterns: Pattern[], path: Path, opts: O) {\n super(patterns, path, opts)\n this.results = new Minipass<Result<O>, Result<O>>({\n signal: this.signal,\n objectMode: true,\n })\n this.results.on('drain', () => this.resume())\n this.results.on('resume', () => this.resume())\n }\n\n matchEmit(e: Result<O>): void {\n this.results.write(e)\n if (!this.results.flowing) this.pause()\n }\n\n stream(): MatchStream<O> {\n const target = this.path\n if (target.isUnknown()) {\n target.lstat().then(() => {\n this.walkCB(target, this.patterns, () => this.results.end())\n })\n } else {\n this.walkCB(target, this.patterns, () => this.results.end())\n }\n return this.results\n }\n\n streamSync(): MatchStream<O> {\n if (this.path.isUnknown()) {\n this.path.lstatSync()\n }\n this.walkCBSync(this.path, this.patterns, () => this.results.end())\n return this.results\n }\n}\n","import { Minimatch } from 'minimatch'\nimport { GlobOptions } from './glob.js'\n\n/**\n * Return true if the patterns provided contain any magic glob characters,\n * given the options provided.\n *\n * Brace expansion is not considered \"magic\" unless the `magicalBraces` option\n * is set, as brace expansion just turns one string into an array of strings.\n * So a pattern like `'x{a,b}y'` would return `false`, because `'xay'` and\n * `'xby'` both do not contain any magic glob characters, and it's treated the\n * same as if you had called it on `['xay', 'xby']`. When `magicalBraces:true`\n * is in the options, brace expansion _is_ treated as a pattern having magic.\n */\nexport const hasMagic = (\n pattern: string | string[],\n options: GlobOptions = {},\n): boolean => {\n if (!Array.isArray(pattern)) {\n pattern = [pattern]\n }\n for (const p of pattern) {\n if (new Minimatch(p, options).hasMagic()) return true\n }\n return false\n}\n","import { escape, unescape } from 'minimatch'\nimport { Minipass } from 'minipass'\nimport { Path } from 'path-scurry'\nimport type {\n GlobOptions,\n GlobOptionsWithFileTypesFalse,\n GlobOptionsWithFileTypesTrue,\n GlobOptionsWithFileTypesUnset,\n} from './glob.js'\nimport { Glob } from './glob.js'\nimport { hasMagic } from './has-magic.js'\n\nexport { escape, unescape } from 'minimatch'\nexport type {\n FSOption,\n Path,\n WalkOptions,\n WalkOptionsWithFileTypesTrue,\n WalkOptionsWithFileTypesUnset,\n} from 'path-scurry'\nexport { Glob } from './glob.js'\nexport type {\n GlobOptions,\n GlobOptionsWithFileTypesFalse,\n GlobOptionsWithFileTypesTrue,\n GlobOptionsWithFileTypesUnset,\n} from './glob.js'\nexport { hasMagic } from './has-magic.js'\nexport { Ignore } from './ignore.js'\nexport type { IgnoreLike } from './ignore.js'\nexport type { MatchStream } from './walker.js'\n\n/**\n * Syncronous form of {@link globStream}. Will read all the matches as fast as\n * you consume them, even all in a single tick if you consume them immediately,\n * but will still respond to backpressure if they're not consumed immediately.\n */\nexport function globStreamSync(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesTrue,\n): Minipass<Path, Path>\nexport function globStreamSync(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesFalse,\n): Minipass<string, string>\nexport function globStreamSync(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesUnset,\n): Minipass<string, string>\nexport function globStreamSync(\n pattern: string | string[],\n options: GlobOptions,\n): Minipass<Path, Path> | Minipass<string, string>\nexport function globStreamSync(\n pattern: string | string[],\n options: GlobOptions = {},\n) {\n return new Glob(pattern, options).streamSync()\n}\n\n/**\n * Return a stream that emits all the strings or `Path` objects and\n * then emits `end` when completed.\n */\nexport function globStream(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesFalse,\n): Minipass<string, string>\nexport function globStream(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesTrue,\n): Minipass<Path, Path>\nexport function globStream(\n pattern: string | string[],\n options?: GlobOptionsWithFileTypesUnset | undefined,\n): Minipass<string, string>\nexport function globStream(\n pattern: string | string[],\n options: GlobOptions,\n): Minipass<Path, Path> | Minipass<string, string>\nexport function globStream(\n pattern: string | string[],\n options: GlobOptions = {},\n) {\n return new Glob(pattern, options).stream()\n}\n\n/**\n * Synchronous form of {@link glob}\n */\nexport function globSync(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesFalse,\n): string[]\nexport function globSync(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesTrue,\n): Path[]\nexport function globSync(\n pattern: string | string[],\n options?: GlobOptionsWithFileTypesUnset | undefined,\n): string[]\nexport function globSync(\n pattern: string | string[],\n options: GlobOptions,\n): Path[] | string[]\nexport function globSync(\n pattern: string | string[],\n options: GlobOptions = {},\n) {\n return new Glob(pattern, options).walkSync()\n}\n\n/**\n * Perform an asynchronous glob search for the pattern(s) specified. Returns\n * [Path](https://isaacs.github.io/path-scurry/classes/PathBase) objects if the\n * {@link withFileTypes} option is set to `true`. See {@link GlobOptions} for\n * full option descriptions.\n */\nasync function glob_(\n pattern: string | string[],\n options?: GlobOptionsWithFileTypesUnset | undefined,\n): Promise<string[]>\nasync function glob_(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesTrue,\n): Promise<Path[]>\nasync function glob_(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesFalse,\n): Promise<string[]>\nasync function glob_(\n pattern: string | string[],\n options: GlobOptions,\n): Promise<Path[] | string[]>\nasync function glob_(\n pattern: string | string[],\n options: GlobOptions = {},\n) {\n return new Glob(pattern, options).walk()\n}\n\n/**\n * Return a sync iterator for walking glob pattern matches.\n */\nexport function globIterateSync(\n pattern: string | string[],\n options?: GlobOptionsWithFileTypesUnset | undefined,\n): Generator<string, void, void>\nexport function globIterateSync(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesTrue,\n): Generator<Path, void, void>\nexport function globIterateSync(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesFalse,\n): Generator<string, void, void>\nexport function globIterateSync(\n pattern: string | string[],\n options: GlobOptions,\n): Generator<Path, void, void> | Generator<string, void, void>\nexport function globIterateSync(\n pattern: string | string[],\n options: GlobOptions = {},\n) {\n return new Glob(pattern, options).iterateSync()\n}\n\n/**\n * Return an async iterator for walking glob pattern matches.\n */\nexport function globIterate(\n pattern: string | string[],\n options?: GlobOptionsWithFileTypesUnset | undefined,\n): AsyncGenerator<string, void, void>\nexport function globIterate(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesTrue,\n): AsyncGenerator<Path, void, void>\nexport function globIterate(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesFalse,\n): AsyncGenerator<string, void, void>\nexport function globIterate(\n pattern: string | string[],\n options: GlobOptions,\n): AsyncGenerator<Path, void, void> | AsyncGenerator<string, void, void>\nexport function globIterate(\n pattern: string | string[],\n options: GlobOptions = {},\n) {\n return new Glob(pattern, options).iterate()\n}\n\n// aliases: glob.sync.stream() glob.stream.sync() glob.sync() etc\nexport const streamSync = globStreamSync\nexport const stream = Object.assign(globStream, { sync: globStreamSync })\nexport const iterateSync = globIterateSync\nexport const iterate = Object.assign(globIterate, {\n sync: globIterateSync,\n})\nexport const sync = Object.assign(globSync, {\n stream: globStreamSync,\n iterate: globIterateSync,\n})\n\nexport const glob = Object.assign(glob_, {\n glob: glob_,\n globSync,\n sync,\n globStream,\n stream,\n globStreamSync,\n streamSync,\n globIterate,\n iterate,\n globIterateSync,\n iterateSync,\n Glob,\n hasMagic,\n escape,\n unescape,\n})\nglob.glob = glob\n","import { editor, confirm, select } from \"@inquirer/prompts\";\nimport chalk from \"chalk\";\nimport { AIProvider } from \"./spec-generator\";\n\nexport class SpecRefiner {\n constructor(private provider: AIProvider) {}\n\n async refineLoop(initialSpec: string): Promise<string> {\n let currentSpec = initialSpec;\n let round = 1;\n\n while (true) {\n console.log(chalk.cyan(`\\n─── Spec Review (Round ${round}) ─────────────────`));\n console.log(chalk.gray(\" Opening spec in editor. Save and close to continue.\"));\n\n // Open spec in editor for user to review/edit\n currentSpec = await editor({\n message: \"Review and edit the spec:\",\n default: currentSpec,\n postfix: \".md\",\n waitForUserInput: false,\n });\n\n console.log(chalk.green(\" ✔ Spec saved.\"));\n\n // Ask what to do next\n const action = await select({\n message: \"What would you like to do?\",\n choices: [\n { name: \"✅ Finalize — proceed to code generation\", value: \"finalize\" },\n { name: \"🤖 AI Polish — let AI improve clarity & completeness\", value: \"ai\" },\n { name: \"✏️ Edit again — continue editing\", value: \"edit\" },\n ],\n });\n\n if (action === \"finalize\") {\n break;\n }\n\n if (action === \"ai\") {\n console.log(chalk.blue(` AI (${this.provider.providerName}/${this.provider.modelName}) is polishing the spec...`));\n try {\n const improved = await this.provider.generate(\n `Review the following feature spec and improve it for clarity, completeness, and technical feasibility.\nKeep the same structure and language (Chinese). Fix any gaps in API design, missing error cases, or vague requirements.\nOutput ONLY the improved markdown spec, nothing else.\n\n${currentSpec}`,\n \"You are a Senior Tech Lead doing a spec review. Output only the improved Markdown.\"\n );\n\n console.log(chalk.yellow(\"\\n AI has suggested improvements. Opening diff in editor...\"));\n const acceptImproved = await confirm({\n message: \"Accept AI improvements? (opens editor so you can review first)\",\n default: true,\n });\n\n if (acceptImproved) {\n // Let user review AI's version before accepting\n currentSpec = await editor({\n message: \"Review AI-improved spec (edit if needed, then save):\",\n default: improved,\n postfix: \".md\",\n waitForUserInput: false,\n });\n console.log(chalk.green(\" ✔ AI-improved spec accepted.\"));\n } else {\n console.log(chalk.gray(\" AI improvements discarded. Keeping your version.\"));\n }\n } catch (err) {\n console.error(chalk.red(\" AI improvement failed:\"), err);\n console.log(chalk.gray(\" Continuing with current spec.\"));\n }\n }\n\n round++;\n }\n\n return currentSpec;\n }\n}\n","import chalk from \"chalk\";\nimport { execSync } from \"child_process\";\nimport * as path from \"path\";\nimport * as fs from \"fs-extra\";\nimport { AIProvider } from \"./spec-generator\";\nimport { ProjectContext } from \"./context-loader\";\nimport { codeGenSystemPrompt } from \"../prompts/codegen.prompt\";\nimport { SpecTask, loadTasksForSpec } from \"./task-generator\";\n\nexport type CodeGenMode = \"claude-code\" | \"api\" | \"plan\";\n\n// ─── RTK Helper ────────────────────────────────────────────────────────────────\n// RTK (Rust Token Killer) saves tokens by filtering verbose CLI output.\n// When available, prefix 'claude' with 'rtk' for token savings.\n\nfunction isRtkAvailable(): boolean {\n try {\n execSync(\"rtk --version\", { stdio: \"ignore\" });\n return true;\n } catch {\n return false;\n }\n}\n\ninterface FileAction {\n file: string;\n action: \"create\" | \"modify\";\n description: string;\n}\n\n// ─── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction stripCodeFences(output: string): string {\n // Remove ```lang ... ``` wrapping if present\n const fenced = output.match(/^```(?:\\w+)?\\n([\\s\\S]*?)```\\s*$/m);\n if (fenced) return fenced[1].trim();\n const lines = output.split(\"\\n\");\n if (lines[0].startsWith(\"```\")) lines.shift();\n if (lines[lines.length - 1].trim() === \"```\") lines.pop();\n return lines.join(\"\\n\").trim();\n}\n\nfunction parseJsonArray(text: string): FileAction[] {\n // Try a JSON code fence first\n const fenced = text.match(/```(?:json)?\\n(\\[[\\s\\S]*?\\])\\n```/);\n const raw = fenced ? fenced[1] : text.match(/\\[[\\s\\S]*?\\]/)?.[0] ?? \"\";\n try {\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed)) return parsed as FileAction[];\n } catch {\n // fall through\n }\n return [];\n}\n\n// ─── CodeGenerator ────────────────────────────────────────────────────────────\n\nexport interface CodeGenOptions {\n /** Run claude non-interactively via -p flag (saves tokens, good for automation) */\n auto?: boolean;\n}\n\nexport class CodeGenerator {\n constructor(\n private provider: AIProvider,\n private mode: CodeGenMode = \"claude-code\"\n ) {}\n\n async generateCode(\n specFilePath: string,\n workingDir: string,\n context?: ProjectContext,\n options: CodeGenOptions = {}\n ): Promise<void> {\n let effectiveMode = this.mode;\n\n if (effectiveMode === \"claude-code\" && this.provider.providerName !== \"claude\") {\n console.log(\n chalk.yellow(\n `\\n ⚠ codegen 模式 \"claude-code\" 需要 Claude,但当前 provider 是 \"${this.provider.providerName}\"。`\n )\n );\n console.log(chalk.gray(` 自动切换到 \"api\" 模式(使用 ${this.provider.providerName}/${this.provider.modelName} 生成代码)。`));\n console.log(chalk.gray(` 提示:运行 \\`ai-spec config --codegen api\\` 可固化此设置。\\n`));\n effectiveMode = \"api\";\n }\n\n switch (effectiveMode) {\n case \"claude-code\":\n return this.runClaudeCode(specFilePath, workingDir, options);\n case \"api\":\n return this.runApiMode(specFilePath, workingDir, context);\n case \"plan\":\n return this.runPlanMode(specFilePath);\n }\n }\n\n // ── Mode: claude-code ──────────────────────────────────────────────────────\n\n private isClaudeCLIAvailable(): boolean {\n try {\n execSync(\"claude --version\", { stdio: \"ignore\" });\n return true;\n } catch {\n return false;\n }\n }\n\n private async runClaudeCode(\n specFilePath: string,\n workingDir: string,\n options: CodeGenOptions = {}\n ): Promise<void> {\n console.log(chalk.blue(\"\\n─── Code Generation: Claude Code CLI ───────────\"));\n\n if (!this.isClaudeCLIAvailable()) {\n console.log(chalk.yellow(\" ⚠️ Claude Code CLI not found. Falling back to plan mode.\"));\n console.log(chalk.gray(\" Install: npm install -g @anthropic-ai/claude-code\"));\n return this.runPlanMode(specFilePath);\n }\n\n // Load tasks if available — build a richer, structured prompt\n const tasks = await loadTasksForSpec(specFilePath);\n const taskSection = tasks && tasks.length > 0\n ? `\\n\\n== Implementation Tasks (implement in order) ==\\n${tasks\n .map((t) => `${t.id} [${t.layer}] ${t.title}\\n Files: ${t.filesToTouch.join(\", \")}\\n Criteria: ${t.acceptanceCriteria.join(\"; \")}`)\n .join(\"\\n\")}`\n : \"\";\n\n const promptContent = `Please read the spec file at ${specFilePath} and implement all the requirements. Create or modify files as necessary.${taskSection}`;\n const promptFile = path.join(workingDir, \".claude-prompt.txt\");\n await fs.writeFile(promptFile, promptContent, \"utf-8\");\n\n // RTK awareness: use 'rtk claude' if rtk is available for token savings\n const rtkAvailable = isRtkAvailable();\n const claudeCmd = rtkAvailable ? \"rtk claude\" : \"claude\";\n if (rtkAvailable) {\n console.log(chalk.green(\" ✓ RTK detected — using rtk claude for token savings\"));\n }\n\n if (options.auto) {\n // Non-interactive mode: pipe the prompt via -p flag (saves significant tokens)\n console.log(chalk.cyan(` 🤖 Auto mode: running claude -p (non-interactive)...`));\n console.log(chalk.gray(` Spec: ${specFilePath}`));\n if (tasks) console.log(chalk.gray(` Tasks: ${tasks.length} tasks loaded`));\n try {\n execSync(`${claudeCmd} -p \"${promptContent.replace(/\"/g, '\\\\\"')}\"`, {\n cwd: workingDir,\n stdio: \"inherit\",\n });\n console.log(chalk.green(\"\\n ✔ Claude Code completed.\"));\n } catch {\n console.log(chalk.yellow(\"\\n Claude Code exited. Check output above.\"));\n }\n } else {\n // Interactive mode — launch session, user takes over\n console.log(chalk.cyan(` 🚀 Launching ${claudeCmd} in: ${workingDir}`));\n console.log(chalk.gray(` Spec: ${specFilePath}`));\n if (tasks) console.log(chalk.gray(` Tasks: ${tasks.length} tasks loaded into .claude-prompt.txt`));\n console.log(chalk.gray(\" Prompt pre-loaded in .claude-prompt.txt\\n\"));\n try {\n execSync(claudeCmd, { cwd: workingDir, stdio: \"inherit\" });\n console.log(chalk.green(\"\\n ✔ Claude Code session completed.\"));\n } catch {\n console.log(chalk.yellow(\"\\n Claude Code session ended. Continuing workflow.\"));\n }\n }\n }\n\n // ── Mode: api ─────────────────────────────────────────────────────────────\n\n private async runApiMode(\n specFilePath: string,\n workingDir: string,\n context?: ProjectContext\n ): Promise<void> {\n console.log(\n chalk.blue(\n `\\n─── Code Generation: API (${this.provider.providerName}/${this.provider.modelName}) ───`\n )\n );\n\n const spec = await fs.readFile(specFilePath, \"utf-8\");\n const constitutionSection = context?.constitution\n ? `\\n=== Project Constitution (MUST follow) ===\\n${context.constitution.slice(0, 2000)}\\n`\n : \"\";\n const contextSummary = context\n ? `Tech Stack: ${context.techStack.join(\", \")}\\nExisting files: ${context.fileStructure.slice(0, 20).join(\", \")}`\n : \"\";\n\n // Use tasks if available for finer-grained generation\n const tasks = await loadTasksForSpec(specFilePath);\n if (tasks && tasks.length > 0) {\n return this.runApiModeWithTasks(spec, tasks, workingDir, constitutionSection);\n }\n\n // Fallback: plan-then-generate\n console.log(chalk.gray(\" [1/2] Planning implementation files...\"));\n\n const planPrompt = `Based on the feature spec and project context below, list ALL files that need to be created or modified.\n\n=== Feature Spec ===\n${spec}\n${constitutionSection}\n=== Project Context ===\n${contextSummary}\n\nOutput ONLY a valid JSON array:\n[\n {\"file\": \"src/controllers/userController.ts\", \"action\": \"create\", \"description\": \"Handle user CRUD operations\"},\n {\"file\": \"src/routes/client/index.ts\", \"action\": \"modify\", \"description\": \"Register new routes\"}\n]`;\n\n let filePlan: FileAction[] = [];\n try {\n const planResponse = await this.provider.generate(planPrompt, codeGenSystemPrompt);\n filePlan = parseJsonArray(planResponse);\n } catch (err) {\n console.error(chalk.red(\" Failed to generate file plan:\"), err);\n }\n\n if (filePlan.length === 0) {\n console.log(chalk.yellow(\" Could not determine file plan. Falling back to plan mode.\"));\n return this.runPlanMode(specFilePath);\n }\n\n console.log(chalk.cyan(`\\n Plan: ${filePlan.length} file(s) to process`));\n filePlan.forEach((item) => {\n const icon = item.action === \"create\" ? chalk.green(\"+\") : chalk.yellow(\"~\");\n console.log(` ${icon} ${item.file}: ${chalk.gray(item.description)}`);\n });\n\n await this.generateFiles(filePlan, spec, workingDir, constitutionSection);\n }\n\n private async runApiModeWithTasks(\n spec: string,\n tasks: SpecTask[],\n workingDir: string,\n constitutionSection: string\n ): Promise<void> {\n console.log(chalk.cyan(`\\n Task-based generation: ${tasks.length} tasks`));\n\n let totalSuccess = 0;\n let totalFiles = 0;\n\n for (const task of tasks) {\n console.log(chalk.bold(`\\n → ${task.id} [${task.layer}] ${task.title}`));\n\n if (task.filesToTouch.length === 0) {\n console.log(chalk.gray(\" No files specified, skipping.\"));\n continue;\n }\n\n const filePlan: FileAction[] = task.filesToTouch.map((f) => ({\n file: f,\n action: \"create\" as const,\n description: task.description,\n }));\n\n const taskContext = `Task: ${task.id} — ${task.title}\\n${task.description}\\nAcceptance: ${task.acceptanceCriteria.join(\"; \")}`;\n const { success, total } = await this.generateFiles(\n filePlan,\n `${spec}\\n\\n=== Current Task ===\\n${taskContext}`,\n workingDir,\n constitutionSection\n );\n totalSuccess += success;\n totalFiles += total;\n }\n\n console.log(\n chalk.bold(\n `\\n ${totalSuccess === totalFiles ? chalk.green(\"✔\") : chalk.yellow(\"!\")} Task-based generation: ${totalSuccess}/${totalFiles} files written across ${tasks.length} tasks.`\n )\n );\n }\n\n private async generateFiles(\n filePlan: FileAction[],\n spec: string,\n workingDir: string,\n constitutionSection: string\n ): Promise<{ success: number; total: number }> {\n console.log(chalk.gray(`\\n Generating ${filePlan.length} file(s)...`));\n let successCount = 0;\n\n for (const item of filePlan) {\n const fullPath = path.join(workingDir, item.file);\n let existingContent = \"\";\n\n if (await fs.pathExists(fullPath)) {\n existingContent = await fs.readFile(fullPath, \"utf-8\");\n }\n\n const codePrompt = `Implement this file.\n\nFile: ${item.file}\nPurpose: ${item.description}\n\n=== Feature Spec ===\n${spec}\n${constitutionSection}\n=== ${existingContent ? \"Existing content (modify and return the complete file)\" : \"Create this file from scratch\"} ===\n${existingContent || \"Output only the complete file content.\"}`;\n\n process.stdout.write(` ${existingContent ? chalk.yellow(\"~\") : chalk.green(\"+\")} ${chalk.bold(item.file)}... `);\n try {\n const raw = await this.provider.generate(codePrompt, codeGenSystemPrompt);\n const fileContent = stripCodeFences(raw);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, fileContent, \"utf-8\");\n console.log(chalk.green(\"✔\"));\n successCount++;\n } catch (err) {\n console.log(chalk.red(\"✘\"));\n console.error(chalk.red(` Error: ${(err as Error).message}`));\n }\n }\n\n console.log(\n chalk.bold(\n ` ${successCount === filePlan.length ? chalk.green(\"✔\") : chalk.yellow(\"!\")} ${successCount}/${filePlan.length} files written.`\n )\n );\n return { success: successCount, total: filePlan.length };\n }\n\n // ── Mode: plan ─────────────────────────────────────────────────────────────\n\n private async runPlanMode(specFilePath: string): Promise<void> {\n console.log(chalk.blue(\"\\n─── Implementation Plan ─────────────────────────\"));\n\n const spec = await fs.readFile(specFilePath, \"utf-8\");\n const plan = await this.provider.generate(\n `Create a detailed, step-by-step implementation plan for the following feature spec.\nBe specific about:\n- Which files to create or modify\n- Key functions/classes to implement\n- Data flow and integration points\n- Suggested implementation order\n\n${spec}`,\n \"You are a senior developer creating an actionable implementation guide.\"\n );\n\n console.log(chalk.cyan(\"\\n\") + plan);\n }\n}\n","export const codeGenSystemPrompt = `You are a Senior Full-Stack Developer implementing features based on provided specifications.\n\nRules:\n1. Follow the existing project's code conventions, naming patterns, and file structure exactly\n2. Write complete, production-ready code — no placeholders, no TODOs, no stub implementations\n3. Include proper error handling, input validation, and logging\n4. Output ONLY raw code content — NO markdown fences, NO explanations, NO comments outside the code\n5. Match the imports, exports, and module patterns visible in the existing codebase\n6. Do not add unnecessary dependencies — reuse what is already in the project\n7. If modifying an existing file, preserve all unchanged code exactly`;\n\nexport const reviewSystemPrompt = `You are a Senior Software Architect conducting a thorough code review. Your review should be structured, constructive, and specific.\n\nAlways format your review with these exact sections:\n\n## ✅ 优点 (What's Good)\nList specific things done well.\n\n## ⚠️ 问题 (Issues Found)\nList bugs, security issues, or spec deviations with line references.\n\n## 💡 改进建议 (Suggestions)\nActionable improvements that would elevate code quality.\n\n## 📊 总体评价 (Overall Assessment)\nScore: X/10 — One-paragraph summary.\n\nBe specific. Reference actual code, not vague principles.`;\n","import chalk from \"chalk\";\nimport * as fs from \"fs-extra\";\nimport * as path from \"path\";\nimport { AIProvider } from \"./spec-generator\";\nimport { ProjectContext } from \"./context-loader\";\nimport { tasksSystemPrompt } from \"../prompts/tasks.prompt\";\n\nexport type TaskLayer = \"data\" | \"infra\" | \"service\" | \"api\" | \"test\";\nexport type TaskPriority = \"high\" | \"medium\" | \"low\";\n\nexport interface SpecTask {\n id: string;\n title: string;\n description: string;\n layer: TaskLayer;\n filesToTouch: string[];\n acceptanceCriteria: string[];\n dependencies: string[];\n priority: TaskPriority;\n}\n\nconst LAYER_ORDER: Record<TaskLayer, number> = {\n data: 0,\n infra: 1,\n service: 2,\n api: 3,\n test: 4,\n};\n\nexport class TaskGenerator {\n constructor(private provider: AIProvider) {}\n\n async generateTasks(spec: string, context?: ProjectContext): Promise<SpecTask[]> {\n const contextSummary = context\n ? `\\n=== Project Context ===\\nTech: ${context.techStack.join(\", \")}\\nFiles: ${context.fileStructure.slice(0, 20).join(\", \")}\\n`\n : \"\";\n\n const prompt = `${spec}${contextSummary}`;\n const raw = await this.provider.generate(prompt, tasksSystemPrompt);\n\n return parseTasks(raw);\n }\n\n async saveTasks(tasks: SpecTask[], specFilePath: string): Promise<string> {\n const dir = path.dirname(specFilePath);\n const base = path.basename(specFilePath, \".md\");\n const tasksFile = path.join(dir, `${base}-tasks.json`);\n await fs.writeJson(tasksFile, tasks, { spaces: 2 });\n return tasksFile;\n }\n\n sortByLayer(tasks: SpecTask[]): SpecTask[] {\n return [...tasks].sort((a, b) => {\n const layerDiff = (LAYER_ORDER[a.layer] ?? 99) - (LAYER_ORDER[b.layer] ?? 99);\n if (layerDiff !== 0) return layerDiff;\n return a.id.localeCompare(b.id);\n });\n }\n}\n\nfunction parseTasks(raw: string): SpecTask[] {\n // Try JSON code fence first\n const fenced = raw.match(/```(?:json)?\\n(\\[[\\s\\S]*?\\])\\n```/);\n const jsonStr = fenced ? fenced[1] : (raw.match(/\\[[\\s\\S]*\\]/)?.[0] ?? \"\");\n try {\n const parsed = JSON.parse(jsonStr);\n if (Array.isArray(parsed)) return parsed as SpecTask[];\n } catch {\n // fall through\n }\n return [];\n}\n\nexport function printTasks(tasks: SpecTask[]): void {\n const layerColors: Record<TaskLayer, chalk.Chalk> = {\n data: chalk.magenta,\n infra: chalk.gray,\n service: chalk.blue,\n api: chalk.cyan,\n test: chalk.green,\n };\n\n console.log(chalk.bold(`\\n Tasks (${tasks.length}):`));\n for (const task of tasks) {\n const color = layerColors[task.layer] ?? chalk.white;\n const badge = color(`[${task.layer}]`);\n const prio = task.priority === \"high\" ? chalk.red(\"●\") : task.priority === \"medium\" ? chalk.yellow(\"●\") : chalk.gray(\"●\");\n console.log(` ${prio} ${chalk.bold(task.id)} ${badge} ${task.title}`);\n }\n}\n\nexport async function loadTasksForSpec(specFilePath: string): Promise<SpecTask[] | null> {\n const base = path.basename(specFilePath, \".md\");\n const dir = path.dirname(specFilePath);\n const tasksFile = path.join(dir, `${base}-tasks.json`);\n if (await fs.pathExists(tasksFile)) {\n return fs.readJson(tasksFile);\n }\n return null;\n}\n","export const tasksSystemPrompt = `You are a Senior Software Architect. Decompose the provided Feature Spec into an ordered list of discrete implementation tasks.\n\nOutput ONLY a valid JSON array. No markdown fences, no explanation.\n\nEach task object must have these exact fields:\n{\n \"id\": \"TASK-001\", // sequential, zero-padded\n \"title\": \"...\", // short action phrase, e.g. \"Add UserFavorite Prisma model\"\n \"description\": \"...\", // 1-2 sentences, specific and actionable\n \"layer\": \"data|service|api|test|infra\", // implementation layer\n \"filesToTouch\": [\"...\"], // specific file paths relative to project root\n \"acceptanceCriteria\": [\"...\"], // verifiable completion conditions\n \"dependencies\": [\"TASK-001\"], // task ids that must complete first (empty array if none)\n \"priority\": \"high|medium|low\"\n}\n\nLayer ordering guidance (implement in this order):\n1. \"data\" — DB schema changes, migrations, seed data\n2. \"infra\" — config, env vars, external service setup\n3. \"service\" — business logic, service classes\n4. \"api\" — controllers, routes, middleware, validators\n5. \"test\" — unit tests, integration tests\n\nRules:\n- Be specific about filesToTouch — use exact paths from the project context\n- acceptanceCriteria must be verifiable (not vague like \"works correctly\")\n- dependencies must reflect real implementation order\n- Aim for 4-10 tasks total — not too granular, not too coarse\n- Each task should be completable in one focused coding session`;\n","import chalk from \"chalk\";\nimport { execSync } from \"child_process\";\nimport { AIProvider } from \"./spec-generator\";\nimport { reviewSystemPrompt } from \"../prompts/codegen.prompt\";\n\nexport class CodeReviewer {\n constructor(private provider: AIProvider) {}\n\n private getGitDiff(): string {\n try {\n // Try staged first, then HEAD diff, then unstaged\n let diff = execSync(\"git diff --cached\", { encoding: \"utf-8\" });\n if (!diff.trim()) diff = execSync(\"git diff HEAD\", { encoding: \"utf-8\" });\n if (!diff.trim()) diff = execSync(\"git diff\", { encoding: \"utf-8\" });\n return diff;\n } catch {\n return \"\";\n }\n }\n\n private getDiffStats(diff: string): { files: number; added: number; removed: number } {\n const lines = diff.split(\"\\n\");\n return {\n files: lines.filter((l) => l.startsWith(\"diff --git\")).length,\n added: lines.filter((l) => l.startsWith(\"+\") && !l.startsWith(\"+++\")).length,\n removed: lines.filter((l) => l.startsWith(\"-\") && !l.startsWith(\"---\")).length,\n };\n }\n\n async reviewCode(specContent: string): Promise<string> {\n console.log(chalk.cyan(\"\\n─── Automated Code Review ───────────────────────\"));\n\n const diff = this.getGitDiff();\n if (!diff.trim()) {\n console.log(\n chalk.yellow(\" No git diff found. Stage or commit changes first, then run review.\")\n );\n console.log(chalk.gray(\" Tip: run `git add .` then `ai-spec review` to review your work.\"));\n return \"No changes\";\n }\n\n const { files, added, removed } = this.getDiffStats(diff);\n console.log(\n chalk.gray(` Diff: ${files} file(s), ${chalk.green(\"+\" + added)} ${chalk.red(\"-\" + removed)}`)\n );\n console.log(\n chalk.blue(` Reviewing with ${this.provider.providerName}/${this.provider.modelName}...`)\n );\n\n const prompt = `Conduct a code review for the following change.\n\n=== Feature Spec (what should be implemented) ===\n${specContent || \"(No spec provided — review for general code quality, patterns, and correctness)\"}\n\n=== Git Diff (what was actually implemented) ===\n${diff.slice(0, 10000)}`;\n\n const reviewResult = await this.provider.generate(prompt, reviewSystemPrompt);\n\n console.log(chalk.cyan(\"\\n─── Review Result ───────────────────────────────\"));\n console.log(reviewResult);\n console.log(chalk.cyan(\"─────────────────────────────────────────────────\\n\"));\n\n return reviewResult;\n }\n}\n","import { execSync } from \"child_process\";\nimport * as path from \"path\";\nimport * as fs from \"fs-extra\";\nimport chalk from \"chalk\";\nexport class GitWorktreeManager { constructor(private baseDir: string) {} private isGitRepo(): boolean { try { execSync(\"git rev-parse --is-inside-work-tree\", { cwd: this.baseDir, stdio: \"ignore\" }); return true; } catch { return false; } } private sanitizeFeatureName(idea: string): string { return idea.toLowerCase().replace(/[^a-z0-9]+/g, \"-\").replace(/^-+|-+$/g, \"\").substring(0, 30) || `feature-${Date.now()}`; } async createWorktree(idea: string): Promise<string | null> { if (!this.isGitRepo()) { console.log(chalk.yellow(\"⚠️ Not a git repository. Skipping worktree creation.\")); return null; } const featureName = this.sanitizeFeatureName(idea); const branchName = `feature/${featureName}`; const repoName = path.basename(this.baseDir); const worktreePath = path.resolve(this.baseDir, \"..\", `${repoName}-${featureName}`); console.log(chalk.cyan(`\\n--- Setting up Git Worktree ---`)); if (await fs.pathExists(worktreePath)) { console.log(chalk.yellow(`⚠️ Worktree directory already exists at: ${worktreePath}`)); return worktreePath; } try { let branchExists = false; try { execSync(`git show-ref --verify refs/heads/${branchName}`, { cwd: this.baseDir, stdio: \"ignore\" }); branchExists = true; } catch {} console.log(chalk.gray(`Creating worktree at: ${worktreePath}`)); if (branchExists) { execSync(`git worktree add \"${worktreePath}\" ${branchName}`, { cwd: this.baseDir, stdio: \"inherit\" }); } else { execSync(`git worktree add -b ${branchName} \"${worktreePath}\"`, { cwd: this.baseDir, stdio: \"inherit\" }); } console.log(chalk.green(`✔ Worktree successfully created and isolated on branch '${branchName}'`)); return worktreePath; } catch (error) { console.error(chalk.red(\"Failed to create git worktree:\"), error); return null; } } }\n","import chalk from \"chalk\";\nimport * as fs from \"fs-extra\";\nimport * as path from \"path\";\nimport { AIProvider } from \"./spec-generator\";\nimport { ContextLoader, ProjectContext } from \"./context-loader\";\nimport { constitutionSystemPrompt } from \"../prompts/constitution.prompt\";\n\nexport const CONSTITUTION_FILE = \".ai-spec-constitution.md\";\n\nexport class ConstitutionGenerator {\n constructor(private provider: AIProvider) {}\n\n async generate(projectRoot: string): Promise<string> {\n const loader = new ContextLoader(projectRoot);\n const context = await loader.loadProjectContext();\n\n const prompt = buildConstitutionPrompt(context, projectRoot);\n return this.provider.generate(prompt, constitutionSystemPrompt);\n }\n\n async saveConstitution(projectRoot: string, content: string): Promise<string> {\n const filePath = path.join(projectRoot, CONSTITUTION_FILE);\n await fs.writeFile(filePath, content, \"utf-8\");\n return filePath;\n }\n}\n\nfunction buildConstitutionPrompt(context: ProjectContext, projectRoot: string): string {\n const parts: string[] = [\n \"Analyze this project and generate its Project Constitution.\\n\",\n `=== Tech Stack ===\\n${context.techStack.join(\", \") || \"unknown\"}\\n`,\n `=== Dependencies (top 30) ===\\n${context.dependencies.slice(0, 30).join(\", \")}\\n`,\n ];\n\n if (context.apiStructure.length > 0) {\n parts.push(`=== API/Route Files ===\\n${context.apiStructure.join(\"\\n\")}\\n`);\n }\n\n if (context.routeSummary) {\n parts.push(`=== Route Code Samples ===\\n${context.routeSummary}\\n`);\n }\n\n if (context.schema) {\n parts.push(`=== Prisma Schema ===\\n${context.schema.slice(0, 4000)}\\n`);\n }\n\n if (context.errorPatterns) {\n parts.push(`=== Error Handling Patterns ===\\n${context.errorPatterns}\\n`);\n }\n\n return parts.join(\"\\n\");\n}\n\nexport async function loadConstitution(projectRoot: string): Promise<string | undefined> {\n const filePath = path.join(projectRoot, CONSTITUTION_FILE);\n if (await fs.pathExists(filePath)) {\n return fs.readFile(filePath, \"utf-8\");\n }\n return undefined;\n}\n\nexport function printConstitutionHint(exists: boolean): void {\n if (!exists) {\n console.log(\n chalk.yellow(\n \" ⚡ Tip: Run `ai-spec init` to generate a Project Constitution for better spec quality.\"\n )\n );\n }\n}\n","export const constitutionSystemPrompt = `You are a Senior Software Architect. Analyze the provided project codebase context and generate a concise \"Project Constitution\" — a living document that captures the architectural rules, conventions, and red lines that ALL future feature specs and code generation MUST follow.\n\nOutput a Markdown document with EXACTLY these sections. Be specific and derive rules directly from the observed codebase — no generic advice.\n\n---\n\n# Project Constitution\n\n## 1. 架构规则 (Architecture Rules)\n列出项目的核心架构模式和强制约束(从代码中提取,而非通用建议)。\n- 分层架构规则(如:routes → controllers → services → DB)\n- 禁止跨层直接调用的规则\n- 模块组织规范\n\n## 2. 命名规范 (Naming Conventions)\n- 文件命名规则(驼峰/下划线/kebab)\n- 变量、函数、类的命名模式\n- 路由路径的命名规范\n\n## 3. API 规范 (API Patterns)\n- 路由前缀规则(如 /api/v1/client/... vs /api/v1/admin/...)\n- 统一响应结构模板(code/message/data 格式)\n- 错误码规范(已有的错误码范围和含义)\n- 认证/鉴权模式(middleware 名称和使用位置)\n\n## 4. 数据层规范 (Data Layer Rules)\n- ORM/数据库访问规则(仅通过 service 层访问?直接用 Prisma/Mongoose?)\n- 已有的数据模型命名规范\n- 事务处理模式\n\n## 5. 错误处理规范 (Error Handling Patterns)\n- 统一错误处理 middleware 的使用规则\n- 错误抛出和捕获的模式\n- 已知错误码列表(从代码中提取)\n\n## 6. 禁区 (Red Lines — Never Violate)\n明确列出绝对不能做的事情(从现有代码/架构推断):\n- [ ] 禁止 ...\n- [ ] 禁止 ...\n\n## 7. 测试规范 (Testing Rules)\n- 测试文件存放位置\n- 必须覆盖的测试场景类型\n- 测试框架和工具\n\n---\n\nBe concise. Each rule must be specific enough to enforce, not a vague principle.`;\n"],"mappings":"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","names":["path","fs","import_chalk","import_prompts","k","v","Anthropic","OpenAI","fs","import_node_url","balanced","a","b","str","ma","maybeMatch","mb","range","reg","m","begs","beg","left","right","result","ai","bi","i","r","escSlash","escOpen","escClose","escComma","escPeriod","escSlashPattern","escOpenPattern","escClosePattern","escCommaPattern","escPeriodPattern","slashPattern","openPattern","closePattern","commaPattern","periodPattern","EXPANSION_MAX","numeric","escapeBraces","unescapeBraces","parseCommaParts","parts","pre","body","post","p","postParts","expand","options","max","expand_","embrace","isPadded","el","lte","y","gte","isTop","expansions","k","expansion","isNumericSequence","isAlphaSequence","isSequence","isOptions","n","N","x","width","incr","test","pad","c","need","z","j","assertValidPattern","pattern","posixClasses","braceEscape","s","regexpEscape","rangesToString","ranges","parseClass","glob","position","pos","negs","sawStart","uflag","escaping","negate","endPos","rangeStart","WHILE","cls","unip","u","neg","sranges","snegs","unescape","windowsPathsNoEscape","magicalBraces","types","isExtglobType","startNoTraversal","startNoDot","addPatternStart","justDots","reSpecials","regExpEscape","qmark","star","starNoEmpty","AST","_AST","#root","#hasMagic","#uflag","#parts","#parent","#parentIndex","#negs","#filledNegs","#options","#toString","#emptyExt","type","parent","#fillNegs","pp","part","ret","pl","#parseAST","ast","opt","inBrace","braceStart","braceNeg","acc","ext","re","hasMagic","flags","allowDot","dot","noEmpty","src","_","#parseGlob","start","aps","needNoTrav","needNoDot","end","repeated","#partsToRegExp","bodyDotAllowed","final","close","_hasMagic","inStar","needUflag","consumed","magic","escape","minimatch","Minimatch","starDotExtRE","starDotExtTest","f","starDotExtTestDot","starDotExtTestNocase","starDotExtTestNocaseDot","starDotStarRE","starDotStarTest","starDotStarTestDot","dotStarRE","dotStarTest","starRE","starTest","starTestDot","qmarksRE","qmarksTestNocase","$0","noext","qmarksTestNoExt","qmarksTestNocaseDot","qmarksTestNoExtDot","qmarksTestDot","qmarksTest","len","defaultPlatform","path","sep","GLOBSTAR","twoStarDot","twoStarNoDot","filter","defaults","def","orig","list","braceExpand","makeRe","match","mm","globMagic","awe","args","rawGlobParts","set","__","isUNC","isDrive","ss","globParts","optimizationLevel","gs","prev","didSomething","dd","gss","next","p2","other","splin","matched","emptyGSMatch","which","negateOffset","file","partial","fileDrive","fileUNC","patternDrive","patternUNC","fdi","pdi","fd","pd","fi","pi","fl","fr","pr","swallowee","hit","fastTest","twoStar","filtered","prefixes","open","ff","filename","defaultPerf","warned","PROCESS","emitWarning","msg","code","fn","AC","AS","warnACPolyfill","reason","printACPolyfillWarning","shouldWarn","isPosInt","getUintArray","ZeroArray","size","Stack","_Stack","#constructing","HeapCls","LRUCache","_LRUCache","#max","#maxSize","#dispose","#onInsert","#disposeAfter","#fetchMethod","#memoMethod","#perf","#size","#calculatedSize","#keyMap","#keyList","#valList","#next","#prev","#head","#tail","#free","#disposed","#sizes","#starts","#ttls","#autopurgeTimers","#hasDispose","#hasFetchMethod","#hasDisposeAfter","#hasOnInsert","#isBackgroundFetch","index","context","#backgroundFetch","#moveToTail","#indexes","#rindexes","#isStale","ttl","ttlResolution","ttlAutopurge","updateAgeOnGet","updateAgeOnHas","allowStale","dispose","onInsert","disposeAfter","noDisposeOnSet","noUpdateTTL","maxSize","maxEntrySize","sizeCalculation","fetchMethod","memoMethod","noDeleteOnFetchRejection","noDeleteOnStaleGet","allowStaleOnFetchRejection","allowStaleOnFetchAbort","ignoreFetchAbort","perf","UintArray","#initializeSizeTracking","#initializeTTLTracking","key","ttls","starts","purgeTimers","#setItemTTL","t","#delete","#updateItemAge","#statusTTL","status","cachedNow","getNow","age","sizes","#removeItemSize","#requireSize","v","#addItemSize","#evict","_i","_s","_st","_k","_v","#isValidIndex","getOptions","value","thisp","deleted","entry","remain","arr","setOptions","oldVal","oldValue","dt","task","val","free","head","hasOptions","peekOptions","ac","signal","fetchOpts","cb","updateCache","aborted","ignoreAbort","proceed","fetchFail","bf","vl","eb","er","allowStaleAborted","noDelete","pcall","res","rej","fmp","fetchOptions","forceRefresh","stale","isStale","staleVal","memoOptions","vv","fetching","#connect","#clear","ni","proc","isStream","Minipass","Stream","isReadable","isWritable","EventEmitter","EOF","MAYBE_EMIT_END","EMITTED_END","EMITTING_END","EMITTED_ERROR","CLOSED","READ","FLUSH","FLUSHCHUNK","ENCODING","DECODER","FLOWING","PAUSED","RESUME","BUFFER","PIPES","BUFFERLENGTH","BUFFERPUSH","BUFFERSHIFT","OBJECTMODE","DESTROYED","ERROR","EMITDATA","EMITEND","EMITEND2","ASYNC","ABORT","ABORTED","SIGNAL","DATALISTENERS","DISCARDED","defer","nodefer","isEndish","ev","isArrayBufferLike","isArrayBufferView","Pipe","dest","opts","_er","PipeProxyErrors","isObjectModeOptions","o","isEncodingOptions","StringDecoder","_enc","_om","chunk","encoding","noDrain","ended","handler","h","data","buf","resolve","reject","stopped","stop","onerr","ondata","onend","ondestroy","wc","realpathSync","rps","defaultFS","lstatSync","readdirCB","readdirSync","readlinkSync","lstat","readdir","readlink","realpath","fsFromOption","fsOption","actualFS","uncDriveRegexp","uncToDrive","rootPath","eitherSep","UNKNOWN","IFIFO","IFCHR","IFDIR","IFBLK","IFREG","IFLNK","IFSOCK","IFMT","IFMT_UNKNOWN","READDIR_CALLED","LSTAT_CALLED","ENOTDIR","ENOENT","ENOREADLINK","ENOREALPATH","ENOCHILD","TYPEMASK","entToType","normalizeCache","L","normalize","normalizeNocaseCache","normalizeNocase","ResolveCache","ChildrenCache","setAsCwd","PathBase","#fs","#dev","#mode","#nlink","#uid","#gid","#rdev","#blksize","#ino","#blocks","#atimeMs","#mtimeMs","#ctimeMs","#birthtimeMs","#atime","#mtime","#ctime","#birthtime","#matchName","#depth","#fullpath","#fullpathPosix","#relative","#relativePosix","#type","#children","#linkTarget","#realpath","name","root","roots","nocase","children","dirParts","#resolveParts","cached","pathPart","fullpath","pchild","pv","fp","pfpp","fpp","ifmt","target","read","linkTarget","#readlinkFail","#readdirSuccess","#markENOENT","#markChildrenENOENT","#markENOREALPATH","#markENOTDIR","#readdirFail","#lstatFail","ter","#readdirAddChild","e","#readdirMaybePromoteChild","#readdirAddNewChild","child","#readdirPromoteChild","#applyStat","st","atime","atimeMs","birthtime","birthtimeMs","blksize","blocks","ctime","ctimeMs","dev","gid","ino","mode","mtime","mtimeMs","nlink","rdev","uid","#onReaddirCB","#readdirCBInFlight","#callOnReaddirCB","cbs","allowZalgo","entries","#asyncReaddirInFlight","dirs","walkFilter","rp","oldCwd","changed","PathWin32","_PathWin32","win32","compare","PathScurryWin32","PathPosix","_PathPosix","_rootPath","PathScurryBase","#resolveCache","#resolvePosixCache","cwd","pathImpl","childrenCacheSize","fs","fileURLToPath","cwdPath","split","joinSep","abs","sawFirst","l","paths","withFileTypes","follow","results","walk","dir","queue","processing","process","paused","onReaddir","didRealpaths","promises","sync","PathScurryPosix","posix","_dir","PathScurryDarwin","Path","PathScurry","isPatternList","isGlobList","gl","customInspect","Pattern","_Pattern","#patternList","#globList","#index","#platform","#rest","#globString","#isDrive","#isUNC","#isAbsolute","#followGlobstar","patternList","globList","platform","p0","p1","p3","prest","g0","g1","g2","g3","grest","g","Ignore","ignored","nobrace","noglobstar","ign","parsed","absolute","fullpaths","relative","relatives","HasWalkedCache","_HasWalkedCache","store","MatchRecord","ifDir","current","SubWalks","subs","Processor","_Processor","hasWalkedCache","patterns","processingSet","rest","rrest","tp","ep","makeIgnore","ignore","GlobUtil","#onResume","#ignore","#sep","#ignored","#childrenIgnored","rpc","mark","rel","processor","tasks","childrenCached","GlobWalker","GlobStream","Glob","Scurry","nocaseMagicOnly","mmo","mms","matchSet","globStreamSync","globStream","globSync","glob_","globIterateSync","globIterate","streamSync","stream","iterateSync","iterate","chalk","import_chalk","path","fs","import_chalk","fs","path","chalk","chalk","import_chalk","import_child_process","chalk","import_child_process","path","fs","import_chalk","chalk","import_chalk","fs","path","chalk","v","chalk","config","meta"]}
1
+ {"version":3,"sources":["../../prompts/codegen.prompt.ts","../../core/workspace-loader.ts","../../cli/index.ts","../../core/spec-generator.ts","../../prompts/spec.prompt.ts","../../core/context-loader.ts","../../node_modules/glob/node_modules/balanced-match/src/index.ts","../../node_modules/glob/node_modules/brace-expansion/src/index.ts","../../node_modules/glob/node_modules/minimatch/src/assert-valid-pattern.ts","../../node_modules/glob/node_modules/minimatch/src/brace-expressions.ts","../../node_modules/glob/node_modules/minimatch/src/unescape.ts","../../node_modules/glob/node_modules/minimatch/src/ast.ts","../../node_modules/glob/node_modules/minimatch/src/escape.ts","../../node_modules/glob/node_modules/minimatch/src/index.ts","../../node_modules/glob/src/glob.ts","../../node_modules/glob/node_modules/lru-cache/src/index.ts","../../node_modules/glob/node_modules/path-scurry/src/index.ts","../../node_modules/glob/node_modules/minipass/src/index.ts","../../node_modules/glob/src/pattern.ts","../../node_modules/glob/src/ignore.ts","../../node_modules/glob/src/processor.ts","../../node_modules/glob/src/walker.ts","../../node_modules/glob/src/has-magic.ts","../../node_modules/glob/src/index.ts","../../core/global-constitution.ts","../../core/spec-refiner.ts","../../core/spec-versioning.ts","../../core/code-generator.ts","../../core/task-generator.ts","../../prompts/tasks.prompt.ts","../../core/dsl-extractor.ts","../../core/dsl-validator.ts","../../prompts/dsl.prompt.ts","../../core/frontend-context-loader.ts","../../core/reviewer.ts","../../git/worktree.ts","../../core/constitution-generator.ts","../../prompts/constitution.prompt.ts","../../core/constitution-consolidator.ts","../../prompts/consolidate.prompt.ts","../../core/combined-generator.ts","../../core/test-generator.ts","../../prompts/testgen.prompt.ts","../../core/error-feedback.ts","../../core/spec-assessor.ts","../../prompts/spec-assess.prompt.ts","../../core/knowledge-memory.ts","../../core/key-store.ts","../../cli/welcome.ts","../../prompts/global-constitution.prompt.ts","../../prompts/decompose.prompt.ts","../../core/requirement-decomposer.ts","../../core/contract-bridge.ts","../../prompts/frontend-spec.prompt.ts","../../core/mock-server-generator.ts","../../core/spec-updater.ts","../../prompts/update.prompt.ts","../../core/openapi-exporter.ts"],"sourcesContent":["export const codeGenSystemPrompt = `You are a Senior Full-Stack Developer implementing features based on provided specifications.\n\nRules:\n1. Follow the existing project's code conventions, naming patterns, and file structure exactly\n2. Write complete, production-ready code — no placeholders, no TODOs, no stub implementations\n3. Include proper error handling, input validation, and logging\n4. Output ONLY raw code content — NO markdown fences, NO explanations, NO comments outside the code\n5. Match the imports, exports, and module patterns visible in the existing codebase\n6. If modifying an existing file, preserve all unchanged code exactly — return the FULL file content with only the new additions merged in\n\nCRITICAL — Dependency Hallucination Prevention (MUST follow):\n7. You will be given an \"=== Installed Packages ===\" section listing ALL packages available in this project.\n NEVER import or use ANY package, library, or module that does not appear in that list.\n This includes (but is not limited to): i18n libraries, UI component libraries, utility libraries, state management libraries.\n If a feature would normally need a missing library, implement the equivalent functionality using only what IS installed.\n Violating this rule will break the project and is unacceptable.\n\nCRITICAL — File Reuse Rules:\n8. NEVER create a new file if an existing file serves the same purpose. Check the shared config file list before planning any new file.\n9. i18n / locale files: ONLY add translation keys if an i18n file already exists in the project. If no i18n/locale files are listed in \"Installed Packages\" or shared config files, do NOT add any i18n code.\n10. constants / enums files: ALWAYS add new values to the EXISTING constants or enums file. Never create a new parallel file.\n11. When in doubt: prefer \"modify existing\" over \"create new\".\n\nCRITICAL — Component Reuse (MUST follow):\n12. Before writing any UI component or element: check the \"Existing reusable components\" list in the context.\n If a component serving the same purpose already exists in src/components/, import and use it — do NOT create a duplicate.\n13. Check the \"Existing page examples\" for how the project's UI library components (e.g. antd, element-plus, arco-design) are actually used.\n Copy those exact component names and import patterns. Do NOT use generic HTML elements where the UI library already provides a component.\n\nCRITICAL — Frontend Architecture Layer Separation (MUST follow):\n14. State management stores (Pinia, Vuex, Redux, Zustand) MUST NOT make HTTP requests directly.\n Stores call functions from the API layer (src/api/ or src/apis/). The API layer makes HTTP requests.\n If the existing store patterns in the context show no HTTP calls, do not add any.\n13. API files import the HTTP client using ONLY the exact import line shown in \"HTTP client import\" in the context.\n NEVER invent a different import path (e.g., '@/utils/request', '@/utils/http') unless that exact path appears in the provided context.\n\nCRITICAL — Learn conventions from examples, do not invent them:\n15. The \"=== Existing Shared Config Files ===\" section below shows real files from the project.\n Study them carefully and match their exact structure, naming conventions, and patterns.\n - Router files: replicate the exact same file structure, path naming, and registration approach you see.\n - Store files: replicate the exact module pattern shown.\n - Do NOT apply generic framework defaults (e.g., Vue Router docs examples) if the project shows a different convention.\n - If you see a modules/ directory pattern in the examples, follow it. If you see a flat file pattern, follow that instead.\n The examples are ground truth. Your prior knowledge about \"typical\" project layouts is secondary.\n\nCRITICAL — Route/Store index registration (MUST follow):\n16. When creating a new route module file (e.g., src/router/routes/taskManagement.ts), you MUST ALSO update\n the corresponding index file (src/router/routes/index.ts) to import the new module and add it to the export array.\n This is non-negotiable. A route module that is not registered in the index will never be loaded.\n Pattern: add \"import taskManagement from './taskManagement'\" at the top and \"taskManagement\" inside the \"export default [...]\".\n\nCRITICAL — Cross-file function name consistency (MUST follow):\n17. When you see an \"=== Files Already Generated in This Run ===\" section, those file contents are the AUTHORITATIVE source\n of truth for exported function/variable names.\n NEVER rename, guess, or substitute alternative names. If the file exports \"getTaskList\", import \"getTaskList\" — not \"getTasks\".\n If no such section is present, derive function names strictly from the DSL endpoint IDs shown in the spec.`;\n\n// ─── Go Codegen System Prompt ─────────────────────────────────────────────────\n\nexport const codeGenGoSystemPrompt = `You are a Senior Go Developer implementing features based on provided specifications.\n\nRules:\n1. Follow standard Go project layout (cmd/, internal/, pkg/, api/). Match whatever layout already exists in the project.\n2. Write idiomatic Go — use named return errors, defer for cleanup, context propagation, structured logging (slog or zap if present).\n3. Write complete, production-ready code — no placeholders, no TODOs, no stub implementations.\n4. Output ONLY raw Go code — NO markdown fences, NO explanations.\n5. Use Go modules (go.mod already exists). Never add a dependency without checking go.mod first.\n6. Error handling: always return errors up the call stack. Never ignore errors with _.\n7. If modifying an existing file, preserve all unchanged code exactly — return the FULL file content.\n8. HTTP handlers: match the existing router pattern (net/http ServeMux, gorilla/mux, chi, gin, echo — use whatever is in go.mod).\n9. Tests: use the standard testing package + testify/assert if already in go.mod.\n\nCRITICAL — File Reuse Rules:\n10. NEVER create a parallel package if an existing one serves the purpose.\n11. Register routes/handlers in the EXISTING router setup file.\n12. Add new model structs to the EXISTING models file if one exists.`;\n\n// ─── Python Codegen System Prompt ─────────────────────────────────────────────\n\nexport const codeGenPythonSystemPrompt = `You are a Senior Python Developer implementing features based on provided specifications.\n\nRules:\n1. Follow PEP 8 and PEP 20. Match the code style visible in the existing codebase.\n2. Detect and match the existing framework: FastAPI, Flask, Django, or plain scripts.\n3. Write complete, production-ready code — no placeholders, no TODOs, no stub implementations.\n4. Output ONLY raw Python code — NO markdown fences, NO explanations.\n5. Use type annotations (Python 3.10+ style). Use Pydantic models if FastAPI is detected.\n6. Error handling: raise HTTPException (FastAPI/Flask) or domain exceptions — never swallow errors.\n7. If modifying an existing file, preserve all unchanged code exactly — return the FULL file content.\n8. Dependency management: only use packages already in requirements.txt / pyproject.toml.\n9. FastAPI: use APIRouter for new endpoints and include it in the main app router.\n10. Django: follow MVT pattern, register URLs in urls.py.\n\nCRITICAL — File Reuse Rules:\n11. NEVER create a parallel module if an existing one serves the purpose.\n12. Register new routes/views in the EXISTING urls.py / router.py.\n13. Add new models to the EXISTING models.py if it exists — do not create a parallel models file.`;\n\n// ─── Java Codegen System Prompt ───────────────────────────────────────────────\n\nexport const codeGenJavaSystemPrompt = `You are a Senior Java Developer implementing features based on provided specifications.\n\nRules:\n1. Detect and match the existing framework: Spring Boot, Micronaut, or Quarkus.\n2. Follow standard layered architecture: Controller → Service → Repository. Match existing package names.\n3. Write complete, production-ready code — no placeholders, no TODOs.\n4. Output ONLY raw Java code — NO markdown fences, NO explanations.\n5. Use constructor injection (@Autowired on constructor, not field injection).\n6. Exception handling: use @ControllerAdvice / @ExceptionHandler if already present. Never swallow exceptions.\n7. If modifying an existing file, preserve all unchanged code exactly — return the FULL file content.\n8. Use Lombok if already in pom.xml / build.gradle (@Data, @Builder, etc.).\n\nCRITICAL — File Reuse Rules:\n9. Register new endpoints in the EXISTING Controller class if one covers the same resource.\n10. Add new repository methods to the EXISTING Repository interface — never create a parallel one.`;\n\n// ─── Rust Codegen System Prompt ───────────────────────────────────────────────\n\nexport const codeGenRustSystemPrompt = `You are a Senior Rust Developer implementing features based on provided specifications.\n\nRules:\n1. Detect and match the existing web framework: Axum, Actix-web, Warp, or Rocket.\n2. Write idiomatic Rust — use Result<T,E> everywhere, no unwrap() in production paths, use ? operator.\n3. Write complete, production-ready code — no placeholders, no TODOs.\n4. Output ONLY raw Rust code — NO markdown fences, NO explanations.\n5. Follow existing module structure (mod declarations in lib.rs / main.rs).\n6. Use existing crates from Cargo.toml only — do not add new dependencies.\n7. If modifying an existing file, preserve all unchanged code exactly — return the FULL file content.\n8. Async: use tokio if already in Cargo.toml. Match existing async patterns.\n\nCRITICAL — File Reuse Rules:\n9. Register new routes in the EXISTING router setup (match pattern in main.rs or router.rs).\n10. Add new model structs to the EXISTING models.rs / types.rs — never create a parallel file.`;\n\n// ─── PHP Codegen System Prompt ────────────────────────────────────────────────\n\nexport const codeGenPhpSystemPrompt = `You are a Senior PHP Developer implementing features based on provided specifications.\n\nRules:\n1. Detect and match the existing framework: Lumen, Laravel, or plain PHP. Follow its directory conventions (app/Http/Controllers, app/Models, routes/web.php / routes/api.php).\n2. Write clean, PSR-12 compliant PHP 8.x code. Use typed properties, constructor promotion, named arguments, and match expressions where appropriate.\n3. Write complete, production-ready code — no placeholders, no TODOs, no stub implementations.\n4. Output ONLY raw PHP code — NO markdown fences, NO explanations.\n5. Use Eloquent ORM if already present. Never introduce raw SQL when Eloquent is available.\n6. Lumen: register routes in routes/web.php or routes/api.php. Laravel: use resource controllers and Route::apiResource where suitable.\n7. Error handling: throw proper HTTP exceptions (e.g. Illuminate\\\\Http\\\\Exceptions\\\\HttpResponseException) and return JSON responses consistently.\n8. If modifying an existing file, preserve all unchanged code exactly — return the FULL file content.\n9. Only use Composer packages already listed in composer.json — never add new dependencies.\n\nCRITICAL — File Reuse Rules:\n10. Register new routes in the EXISTING routes/api.php (or routes/web.php) — never create a parallel routes file.\n11. Add new Eloquent model methods to the EXISTING Model class — never create a parallel model file.\n12. Add new service methods to the EXISTING service class if one already covers the same resource.`;\n\n/**\n * Pick the appropriate codegen system prompt based on detected repo language.\n */\nexport function getCodeGenSystemPrompt(repoType?: string): string {\n switch (repoType) {\n case \"go\": return codeGenGoSystemPrompt;\n case \"python\": return codeGenPythonSystemPrompt;\n case \"java\": return codeGenJavaSystemPrompt;\n case \"rust\": return codeGenRustSystemPrompt;\n case \"php\": return codeGenPhpSystemPrompt;\n default: return codeGenSystemPrompt;\n }\n}\n\nexport const reviewSystemPrompt = `You are a Senior Software Architect conducting a thorough code review. Your review should be structured, constructive, and specific.\n\nAlways format your review with these exact sections:\n\n## ✅ 优点 (What's Good)\nList specific things done well.\n\n## ⚠️ 问题 (Issues Found)\nList bugs, security issues, or spec deviations with line references.\n\n## 💡 改进建议 (Suggestions)\nActionable improvements that would elevate code quality.\n\n## 📊 总体评价 (Overall Assessment)\nScore: X/10 — One-paragraph summary.\n\nBe specific. Reference actual code, not vague principles.`;\n\n// ─── Two-pass review prompts ───────────────────────────────────────────────────\n\n/**\n * Pass 1 — Architecture review.\n * Focuses on design-level correctness: spec compliance, layer separation, API contract.\n * Deliberately ignores micro-level implementation details.\n */\nexport const reviewArchitectureSystemPrompt = `You are a Senior Software Architect reviewing the HIGH-LEVEL design of a code change.\n\nFocus ONLY on:\n1. **Spec compliance** — Does the implementation match the spec? Are there missing or extra endpoints/components?\n2. **Layer separation** — Does each layer have the right responsibilities? (e.g., no business logic in controllers, no HTTP in stores)\n3. **API contract** — Are request/response shapes correct? Are all error codes from the spec implemented?\n4. **Data model integrity** — Are constraints, unique fields, and relationships correct?\n5. **Security posture** — Are auth checks applied to the right endpoints? Any obvious missing auth?\n\nDO NOT comment on:\n- Code style, naming conventions, formatting\n- Minor implementation details (variable names, inline comments)\n- Performance micro-optimizations\n\nFormat:\n\n## 🏗 架构合规性 (Spec Compliance)\nDoes the implementation match the spec? List any missing or wrong endpoints/components.\n\n## 🔀 层职责分离 (Layer Separation)\nAny layer boundary violations?\n\n## 🔒 安全与权限 (Security & Auth)\nAny missing auth checks, exposed data, or privilege issues?\n\n## 📋 架构评分 (Architecture Score)\nScore: X/10 — One short paragraph.\n\nBe specific. Reference file names or endpoint paths.`;\n\n/**\n * Pass 2 — Implementation review.\n * Focuses on code-level quality: validation, error handling, edge cases, patterns.\n * Receives the architecture review from Pass 1 as additional context.\n */\nexport const reviewImplementationSystemPrompt = `You are a Senior Engineer reviewing the IMPLEMENTATION DETAILS of a code change.\n\nAn architecture review has already been completed (provided as context). Do NOT repeat its findings.\n\nFocus ONLY on:\n1. **Input validation** — Are all inputs validated before use? Missing length/format/type checks?\n2. **Error handling** — Are all error paths handled? Any unhandled promise rejections or uncaught exceptions?\n3. **Edge cases** — Null/undefined handling, empty arrays, boundary conditions?\n4. **Code patterns** — DRY violations, overly complex logic that could be simplified, missing abstractions?\n5. **Past issue recurrence** — Does the code repeat any known patterns flagged in previous reviews (provided as history context)?\n\nDO NOT repeat architecture-level findings already covered in the architecture review.\n\nFormat:\n\n## ✅ 优点 (What's Good)\nSpecific implementation strengths.\n\n## ⚠️ 问题 (Issues Found)\nBugs, missing validation, error handling gaps — with file:line references where possible.\n\n## 🔁 历史问题复现 (Recurring Issues)\nAny issues that appeared in past reviews and are still present? (Only if history context is provided)\n\n## 💡 改进建议 (Suggestions)\nActionable, concrete improvements.\n\n## 📊 综合评分 (Final Score)\nScore: X/10 — Combined architecture + implementation assessment in one paragraph.\n\nBe specific. Reference actual code, not vague principles.`;\n","import * as fs from \"fs-extra\";\nimport * as path from \"path\";\nimport { glob } from \"glob\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type RepoType =\n | \"node-express\"\n | \"node-koa\"\n | \"react\"\n | \"next\"\n | \"vue\"\n | \"react-native\"\n | \"go\"\n | \"python\"\n | \"java\"\n | \"rust\"\n | \"php\"\n | \"unknown\";\n\nexport type RepoRole = \"backend\" | \"frontend\" | \"mobile\" | \"shared\";\n\nexport interface RepoConfig {\n name: string;\n /** Relative path from workspace root (the directory containing .ai-spec-workspace.json) */\n path: string;\n type: RepoType;\n role: RepoRole;\n /** Contents of .ai-spec-constitution.md, loaded at runtime */\n constitution?: string;\n}\n\nexport interface WorkspaceConfig {\n name: string;\n repos: RepoConfig[];\n}\n\nexport const WORKSPACE_CONFIG_FILE = \".ai-spec-workspace.json\";\n\n// ─── Type Detection ───────────────────────────────────────────────────────────\n\n/**\n * Detect the repo type and role from its package.json dependencies.\n */\nexport async function detectRepoType(\n repoAbsPath: string\n): Promise<{ type: RepoType; role: RepoRole }> {\n // ── Non-Node language detection (check before package.json) ──────────────\n if (await fs.pathExists(path.join(repoAbsPath, \"go.mod\"))) {\n return { type: \"go\", role: \"backend\" };\n }\n if (await fs.pathExists(path.join(repoAbsPath, \"composer.json\"))) {\n return { type: \"php\", role: \"backend\" };\n }\n if (await fs.pathExists(path.join(repoAbsPath, \"Cargo.toml\"))) {\n return { type: \"rust\", role: \"backend\" };\n }\n if (\n (await fs.pathExists(path.join(repoAbsPath, \"pom.xml\"))) ||\n (await fs.pathExists(path.join(repoAbsPath, \"build.gradle\"))) ||\n (await fs.pathExists(path.join(repoAbsPath, \"build.gradle.kts\")))\n ) {\n return { type: \"java\", role: \"backend\" };\n }\n if (\n (await fs.pathExists(path.join(repoAbsPath, \"requirements.txt\"))) ||\n (await fs.pathExists(path.join(repoAbsPath, \"pyproject.toml\"))) ||\n (await fs.pathExists(path.join(repoAbsPath, \"setup.py\")))\n ) {\n return { type: \"python\", role: \"backend\" };\n }\n\n // ── Node.js detection via package.json ────────────────────────────────────\n const pkgPath = path.join(repoAbsPath, \"package.json\");\n if (!(await fs.pathExists(pkgPath))) {\n return { type: \"unknown\", role: \"shared\" };\n }\n\n let pkg: Record<string, unknown> = {};\n try {\n pkg = await fs.readJson(pkgPath);\n } catch {\n return { type: \"unknown\", role: \"shared\" };\n }\n\n const deps = {\n ...((pkg.dependencies as Record<string, string>) ?? {}),\n ...((pkg.devDependencies as Record<string, string>) ?? {}),\n };\n const depKeys = Object.keys(deps);\n\n const has = (...names: string[]) => names.some((n) => depKeys.includes(n));\n\n if (has(\"react-native\", \"expo\")) {\n return { type: \"react-native\", role: \"mobile\" };\n }\n if (has(\"next\")) {\n return { type: \"next\", role: \"frontend\" };\n }\n if (has(\"react\")) {\n return { type: \"react\", role: \"frontend\" };\n }\n if (has(\"vue\", \"@vue/cli-service\")) {\n return { type: \"vue\", role: \"frontend\" };\n }\n if (has(\"koa\", \"@koa/router\")) {\n return { type: \"node-koa\", role: \"backend\" };\n }\n if (\n has(\"express\", \"@nestjs/core\", \"fastify\", \"hapi\") ||\n has(\"prisma\", \"@prisma/client\", \"mongoose\", \"typeorm\", \"sequelize\")\n ) {\n return { type: \"node-express\", role: \"backend\" };\n }\n\n return { type: \"unknown\", role: \"shared\" };\n}\n\n// ─── WorkspaceLoader ─────────────────────────────────────────────────────────\n\nexport class WorkspaceLoader {\n constructor(private workspaceRoot: string) {}\n\n /**\n * Load and validate .ai-spec-workspace.json from the workspace root.\n * Returns null if the file does not exist (graceful degradation).\n */\n async load(): Promise<WorkspaceConfig | null> {\n const configPath = path.join(this.workspaceRoot, WORKSPACE_CONFIG_FILE);\n if (!(await fs.pathExists(configPath))) {\n return null;\n }\n\n let raw: unknown;\n try {\n raw = await fs.readJson(configPath);\n } catch (err) {\n throw new Error(\n `Failed to parse ${WORKSPACE_CONFIG_FILE}: ${(err as Error).message}`\n );\n }\n\n if (\n typeof raw !== \"object\" ||\n raw === null ||\n !(\"name\" in raw) ||\n !(\"repos\" in raw)\n ) {\n throw new Error(\n `${WORKSPACE_CONFIG_FILE} is missing required fields: name, repos`\n );\n }\n\n const config = raw as WorkspaceConfig;\n\n if (!Array.isArray(config.repos) || config.repos.length === 0) {\n throw new Error(`${WORKSPACE_CONFIG_FILE}: repos must be a non-empty array`);\n }\n\n // Load constitutions at runtime\n const resolvedRepos = await this.resolveRepoPaths(config);\n return { ...config, repos: resolvedRepos };\n }\n\n /**\n * Scan sibling directories for repos by looking for package.json.\n * Auto-detects type and role from dependencies.\n */\n async autoDetect(names?: string[]): Promise<RepoConfig[]> {\n const entries = await fs.readdir(this.workspaceRoot);\n const repos: RepoConfig[] = [];\n\n for (const entry of entries) {\n const absPath = path.join(this.workspaceRoot, entry);\n const stat = await fs.stat(absPath).catch(() => null);\n if (!stat || !stat.isDirectory()) continue;\n if (entry.startsWith(\".\") || entry === \"node_modules\") continue;\n if (names && !names.includes(entry)) continue;\n\n // Accept any recognizable project (package.json, go.mod, Cargo.toml, pom.xml, etc.)\n const hasManifest =\n (await fs.pathExists(path.join(absPath, \"package.json\"))) ||\n (await fs.pathExists(path.join(absPath, \"go.mod\"))) ||\n (await fs.pathExists(path.join(absPath, \"Cargo.toml\"))) ||\n (await fs.pathExists(path.join(absPath, \"pom.xml\"))) ||\n (await fs.pathExists(path.join(absPath, \"build.gradle\"))) ||\n (await fs.pathExists(path.join(absPath, \"requirements.txt\"))) ||\n (await fs.pathExists(path.join(absPath, \"pyproject.toml\"))) ||\n (await fs.pathExists(path.join(absPath, \"composer.json\")));\n if (!hasManifest) continue;\n\n const { type, role } = await detectRepoType(absPath);\n repos.push({ name: entry, path: entry, type, role });\n }\n\n return repos;\n }\n\n /**\n * Resolve relative paths to absolute and load constitutions.\n */\n async resolveRepoPaths(config: WorkspaceConfig): Promise<RepoConfig[]> {\n const resolved: RepoConfig[] = [];\n\n for (const repo of config.repos) {\n const absPath = path.resolve(this.workspaceRoot, repo.path);\n let constitution: string | undefined;\n\n const constitutionFile = path.join(absPath, \".ai-spec-constitution.md\");\n if (await fs.pathExists(constitutionFile)) {\n constitution = await fs.readFile(constitutionFile, \"utf-8\");\n }\n\n resolved.push({ ...repo, constitution });\n }\n\n return resolved;\n }\n\n /**\n * Save a workspace config to disk.\n */\n async save(config: WorkspaceConfig): Promise<string> {\n const configPath = path.join(this.workspaceRoot, WORKSPACE_CONFIG_FILE);\n // Strip runtime-loaded constitutions before saving\n const toSave: WorkspaceConfig = {\n name: config.name,\n repos: config.repos.map(({ constitution: _c, ...rest }) => rest),\n };\n await fs.writeJson(configPath, toSave, { spaces: 2 });\n return configPath;\n }\n\n /**\n * Resolve the absolute path of a repo given its config.\n */\n resolveAbsPath(repo: RepoConfig): string {\n return path.resolve(this.workspaceRoot, repo.path);\n }\n\n /**\n * Find which repos are backend (contract providers) and which depend on them.\n */\n static getProcessingOrder(repos: RepoConfig[]): RepoConfig[] {\n // Backends first, then frontends/mobile, then shared\n const roleOrder: Record<RepoRole, number> = {\n backend: 0,\n shared: 1,\n frontend: 2,\n mobile: 3,\n };\n return [...repos].sort(\n (a, b) => roleOrder[a.role] - roleOrder[b.role]\n );\n }\n}\n","#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport * as path from \"path\";\nimport * as fs from \"fs-extra\";\nimport chalk from \"chalk\";\nimport * as dotenv from \"dotenv\";\nimport { input, confirm, select, checkbox } from \"@inquirer/prompts\";\n\ndotenv.config();\n\nimport {\n SpecGenerator,\n createProvider,\n DEFAULT_MODELS,\n ENV_KEY_MAP,\n SUPPORTED_PROVIDERS,\n PROVIDER_CATALOG,\n AIProvider,\n} from \"../core/spec-generator\";\nimport { ContextLoader, isFrontendDeps } from \"../core/context-loader\";\nimport { SpecRefiner } from \"../core/spec-refiner\";\nimport { CodeGenerator, CodeGenMode } from \"../core/code-generator\";\nimport { CodeReviewer } from \"../core/reviewer\";\nimport { GitWorktreeManager } from \"../git/worktree\";\nimport { ConstitutionGenerator, CONSTITUTION_FILE, printConstitutionHint } from \"../core/constitution-generator\";\nimport { ConstitutionConsolidator } from \"../core/constitution-consolidator\";\nimport { TaskGenerator, printTasks } from \"../core/task-generator\";\nimport { generateSpecWithTasks } from \"../core/combined-generator\";\nimport {\n slugify,\n findLatestVersion,\n nextVersionPath,\n computeDiff,\n printDiff,\n printDiffSummary,\n} from \"../core/spec-versioning\";\nimport { DslExtractor } from \"../core/dsl-extractor\";\nimport { TestGenerator } from \"../core/test-generator\";\nimport { runErrorFeedback } from \"../core/error-feedback\";\nimport { assessSpec, printSpecAssessment } from \"../core/spec-assessor\";\nimport { accumulateReviewKnowledge } from \"../core/knowledge-memory\";\nimport {\n WorkspaceLoader,\n WorkspaceConfig,\n RepoConfig,\n WORKSPACE_CONFIG_FILE,\n detectRepoType,\n} from \"../core/workspace-loader\";\nimport {\n loadGlobalConstitution,\n saveGlobalConstitution,\n GLOBAL_CONSTITUTION_FILE,\n} from \"../core/global-constitution\";\nimport { getSavedKey, saveKey, clearAllKeys, clearKey, KEY_STORE_FILE } from \"../core/key-store\";\nimport { printWelcome } from \"./welcome\";\nimport {\n globalConstitutionSystemPrompt,\n buildGlobalConstitutionPrompt,\n} from \"../prompts/global-constitution.prompt\";\nimport { RequirementDecomposer, DecompositionResult, RepoRequirement } from \"../core/requirement-decomposer\";\nimport { buildFrontendApiContract, buildContractContextSection } from \"../core/contract-bridge\";\nimport { loadFrontendContext, buildFrontendContextSection } from \"../core/frontend-context-loader\";\nimport { buildFrontendSpecPrompt, frontendSpecSystemPrompt } from \"../prompts/frontend-spec.prompt\";\nimport { SpecDSL } from \"../core/dsl-types\";\nimport { generateMockAssets, findLatestDslFile } from \"../core/mock-server-generator\";\nimport { SpecUpdater } from \"../core/spec-updater\";\nimport { exportOpenApi } from \"../core/openapi-exporter\";\n\n// ─── Config File ──────────────────────────────────────────────────────────────\n\ninterface AiSpecConfig {\n provider?: string;\n model?: string;\n codegen?: CodeGenMode;\n codegenProvider?: string;\n codegenModel?: string;\n}\n\nconst CONFIG_FILE = \".ai-spec.json\";\n\nasync function loadConfig(dir: string): Promise<AiSpecConfig> {\n const p = path.join(dir, CONFIG_FILE);\n if (await fs.pathExists(p)) {\n return fs.readJson(p);\n }\n return {};\n}\n\n// ─── API Key Resolution ────────────────────────────────────────────────────────\n\nasync function resolveApiKey(\n providerName: string,\n cliKey?: string\n): Promise<string> {\n if (cliKey) return cliKey;\n\n const envVar = ENV_KEY_MAP[providerName];\n if (envVar && process.env[envVar]) return process.env[envVar]!;\n\n // Check saved key and offer reuse\n const savedKey = await getSavedKey(providerName);\n if (savedKey) {\n const masked = savedKey.slice(0, 6) + \"...\" + savedKey.slice(-4);\n const choice = await select({\n message: `${providerName} API key (saved: ${masked}):`,\n choices: [\n { name: \"Use saved key\", value: \"reuse\" },\n { name: \"Enter a new key\", value: \"new\" },\n ],\n });\n if (choice === \"reuse\") return savedKey;\n }\n\n // Fresh input — save for next time\n const newKey = await input({\n message: `Enter your ${providerName} API key${envVar ? ` (or set ${envVar} env var)` : \"\"}:`,\n validate: (v) => v.trim().length > 0 || \"API key cannot be empty\",\n });\n await saveKey(providerName, newKey.trim());\n console.log(chalk.gray(` Key saved to ${KEY_STORE_FILE}`));\n return newKey.trim();\n}\n\n// ─── Banner ───────────────────────────────────────────────────────────────────\n\nfunction printBanner(opts: {\n specProvider: string;\n specModel: string;\n codegenMode: string;\n codegenProvider: string;\n codegenModel: string;\n}) {\n console.log(chalk.blue(\"\\n\" + \"─\".repeat(52)));\n console.log(chalk.bold(\" ai-spec — AI-driven Development Orchestrator\"));\n console.log(chalk.blue(\"─\".repeat(52)));\n console.log(chalk.gray(` Spec : ${opts.specProvider} / ${opts.specModel}`));\n console.log(\n chalk.gray(\n ` Codegen : ${opts.codegenMode} (${opts.codegenProvider} / ${opts.codegenModel})`\n )\n );\n console.log(chalk.blue(\"─\".repeat(52) + \"\\n\"));\n}\n\n// ─── Program ──────────────────────────────────────────────────────────────────\n\nconst program = new Command();\n\nprogram\n .name(\"ai-spec\")\n .description(\"AI-driven Development Orchestrator — spec, generate, review\")\n .version(\"0.14.1\");\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Command: create\n// ═══════════════════════════════════════════════════════════════════════════════\n\nprogram\n .command(\"create\")\n .description(\"Generate a feature spec and kick off code generation\")\n .argument(\"[idea]\", \"Feature idea in natural language (prompted if omitted)\")\n .option(\n \"--provider <name>\",\n `AI provider for spec generation (${SUPPORTED_PROVIDERS.join(\"|\")})`,\n undefined\n )\n .option(\"--model <name>\", \"Model name for spec generation\")\n .option(\"-k, --key <apiKey>\", \"API key (overrides env var)\")\n .option(\n \"--codegen <mode>\",\n \"Code generation mode: claude-code | api | plan\",\n undefined\n )\n .option(\n \"--codegen-provider <name>\",\n \"AI provider for code generation (defaults to --provider)\"\n )\n .option(\"--codegen-model <name>\", \"Model for code generation\")\n .option(\"--codegen-key <key>\", \"API key for code generation (if different)\")\n .option(\"--skip-worktree\", \"Skip git worktree creation (auto-set for frontend projects)\")\n .option(\"--worktree\", \"Force git worktree creation even for frontend projects\")\n .option(\"--skip-review\", \"Skip automated code review\")\n .option(\"--skip-tasks\", \"Skip task generation (just generate spec)\")\n .option(\"--auto\", \"Run claude non-interactively via -p flag (saves tokens)\")\n .option(\"--fast\", \"Skip interactive spec refinement, proceed immediately with initial spec\")\n .option(\"--resume\", \"Resume an interrupted run — skip tasks already marked as done\")\n .option(\"--skip-dsl\", \"Skip DSL extraction step\")\n .option(\"--skip-tests\", \"Skip test skeleton generation\")\n .option(\"--skip-error-feedback\", \"Skip error feedback loop (test/lint auto-fix)\")\n .option(\"--tdd\", \"TDD mode: generate failing tests first, then generate implementation to pass them\")\n .option(\"--skip-assessment\", \"Skip spec quality pre-assessment before the Approval Gate\")\n .action(async (idea: string | undefined, opts) => {\n const currentDir = process.cwd();\n const config = await loadConfig(currentDir);\n\n // ── Resolve idea ──────────────────────────────────────────────────────────\n if (!idea) {\n idea = await input({\n message: \"What feature do you want to build?\",\n validate: (v) => v.trim().length > 0 || \"Please describe your feature\",\n });\n }\n\n // ── Detect workspace mode ─────────────────────────────────────────────────\n const workspaceLoader = new WorkspaceLoader(currentDir);\n const workspaceConfig = await workspaceLoader.load();\n\n if (workspaceConfig) {\n console.log(chalk.cyan(`\\n[Workspace] Detected workspace: ${workspaceConfig.name}`));\n console.log(chalk.gray(` Repos: ${workspaceConfig.repos.map((r) => r.name).join(\", \")}`));\n await runMultiRepoPipeline(idea!, workspaceConfig, opts, currentDir, config);\n return;\n }\n\n // ── Resolve spec provider ─────────────────────────────────────────────────\n const specProviderName = opts.provider || config.provider || \"gemini\";\n const specModelName =\n opts.model || config.model || DEFAULT_MODELS[specProviderName];\n const specApiKey = await resolveApiKey(specProviderName, opts.key);\n\n // ── Resolve codegen ───────────────────────────────────────────────────────\n const codegenMode: CodeGenMode =\n (opts.codegen as CodeGenMode) || config.codegen || \"claude-code\";\n const codegenProviderName =\n opts.codegenProvider || config.codegenProvider || specProviderName;\n const codegenModelName =\n opts.codegenModel ||\n config.codegenModel ||\n DEFAULT_MODELS[codegenProviderName];\n const codegenApiKey =\n codegenProviderName === specProviderName\n ? specApiKey\n : await resolveApiKey(codegenProviderName, opts.codegenKey);\n\n printBanner({\n specProvider: specProviderName,\n specModel: specModelName,\n codegenMode,\n codegenProvider: codegenProviderName,\n codegenModel: codegenModelName,\n });\n\n // ── Step 1: Context ───────────────────────────────────────────────────────\n console.log(chalk.blue(\"[1/6] Loading project context...\"));\n const loader = new ContextLoader(currentDir);\n const context = await loader.loadProjectContext();\n const { type: detectedRepoType } = await detectRepoType(currentDir);\n console.log(chalk.gray(` Tech stack : ${context.techStack.join(\", \") || \"unknown\"} [${detectedRepoType}]`));\n console.log(chalk.gray(` Dependencies: ${context.dependencies.length} packages`));\n console.log(chalk.gray(` API files : ${context.apiStructure.length} files`));\n if (context.schema) {\n console.log(chalk.gray(` Prisma schema: found`));\n }\n if (context.constitution) {\n console.log(chalk.green(` Constitution : found (.ai-spec-constitution.md)`));\n } else {\n // Auto-run init: generate constitution before proceeding\n console.log(chalk.yellow(\" Constitution : not found — auto-generating...\"));\n try {\n const constitutionGen = new ConstitutionGenerator(\n createProvider(specProviderName, specApiKey, specModelName)\n );\n const constitutionContent = await constitutionGen.generate(currentDir);\n await constitutionGen.saveConstitution(currentDir, constitutionContent);\n context.constitution = constitutionContent;\n console.log(chalk.green(` Constitution : ✔ generated and saved (.ai-spec-constitution.md)`));\n } catch (err) {\n console.log(chalk.yellow(` Constitution : ⚠ auto-generation failed (${(err as Error).message}), continuing without it.`));\n }\n }\n\n // ── Step 2: Spec + Tasks Generation (single AI call) ─────────────────────\n console.log(chalk.blue(`\\n[2/6] Generating spec with ${specProviderName}/${specModelName}...`));\n const specProvider = createProvider(specProviderName, specApiKey, specModelName);\n\n let initialSpec: string;\n let initialTasks: import(\"../core/task-generator\").SpecTask[] = [];\n\n try {\n if (opts.skipTasks) {\n // Tasks skipped: use SpecGenerator alone\n const generator = new SpecGenerator(specProvider);\n initialSpec = await generator.generateSpec(idea, context);\n console.log(chalk.green(\" ✔ Spec generated.\"));\n } else {\n // Combined: spec + tasks in one call\n const result = await generateSpecWithTasks(specProvider, idea, context);\n initialSpec = result.spec;\n initialTasks = result.tasks;\n console.log(chalk.green(` ✔ Spec generated.`));\n if (initialTasks.length > 0) {\n console.log(chalk.green(` ✔ ${initialTasks.length} tasks generated (combined call).`));\n } else {\n console.log(chalk.yellow(\" ⚠ Tasks not parsed from response — will retry separately after refinement.\"));\n }\n }\n } catch (err) {\n console.error(chalk.red(\" ✘ Spec generation failed:\"), err);\n process.exit(1);\n }\n\n // ── Step 3: Interactive Refinement ────────────────────────────────────────\n let finalSpec: string;\n if (opts.fast) {\n console.log(chalk.gray(\"\\n[3/6] Skipping refinement (--fast).\"));\n finalSpec = initialSpec;\n } else {\n console.log(chalk.blue(\"\\n[3/6] Interactive spec refinement...\"));\n const refiner = new SpecRefiner(specProvider);\n finalSpec = await refiner.refineLoop(initialSpec);\n }\n\n // Compute slug once — used in Approval Gate diff preview and versioned file save\n const featureSlug = slugify(idea!);\n\n // ── Step 3.4: Spec Quality Pre-Assessment ────────────────────────────────\n // Advisory only — never blocks the flow. Skipped in --auto mode and with --skip-assessment.\n if (!opts.auto && !opts.skipAssessment) {\n console.log(chalk.blue(\"\\n[3.4/6] Spec quality assessment...\"));\n const assessment = await assessSpec(specProvider, finalSpec, context.constitution ?? undefined);\n if (assessment) {\n printSpecAssessment(assessment);\n } else {\n console.log(chalk.gray(\" (Assessment skipped — AI call failed or timed out)\"));\n }\n }\n\n // ── Step 3.5: Approval Gate ───────────────────────────────────────────────\n if (!opts.auto) {\n console.log(chalk.blue(\"\\n[3.5/6] Approval Gate — review before code generation\"));\n\n // Show spec stats\n const specLines = finalSpec.split(\"\\n\").length;\n const specWords = finalSpec.split(/\\s+/).length;\n const taskCountHint = initialTasks.length > 0 ? ` Tasks generated : ${initialTasks.length}` : \"\";\n console.log(chalk.gray(` Spec length : ${specLines} lines / ${specWords} words`));\n if (taskCountHint) console.log(chalk.gray(taskCountHint));\n\n // Show diff vs previous version if one exists\n const previewSpecsDir = path.join(currentDir, \"specs\");\n const slug = featureSlug;\n const prevVersion = await findLatestVersion(previewSpecsDir, slug);\n if (prevVersion) {\n console.log(chalk.gray(` Previous version: v${prevVersion.version} (${prevVersion.filePath})`));\n const diff = computeDiff(prevVersion.content, finalSpec);\n console.log(chalk.cyan(\"\\n ── Changes vs previous version ──────────────\"));\n printDiffSummary(diff, `v${prevVersion.version} → v${prevVersion.version + 1}`);\n printDiff(diff);\n console.log(chalk.cyan(\" ────────────────────────────────────────────\"));\n }\n\n const gate = await select({\n message: \"Ready to proceed to code generation?\",\n choices: [\n { name: \"✅ Proceed — start code generation\", value: \"proceed\" },\n { name: \"📋 View full spec\", value: \"view\" },\n { name: \"❌ Abort\", value: \"abort\" },\n ],\n });\n\n if (gate === \"view\") {\n console.log(chalk.cyan(\"\\n\" + \"─\".repeat(52)));\n console.log(finalSpec);\n console.log(chalk.cyan(\"─\".repeat(52) + \"\\n\"));\n\n const confirm2 = await select({\n message: \"Proceed to code generation?\",\n choices: [\n { name: \"✅ Proceed\", value: \"proceed\" },\n { name: \"❌ Abort\", value: \"abort\" },\n ],\n });\n if (confirm2 === \"abort\") {\n console.log(chalk.yellow(\" Aborted. Spec was NOT saved.\"));\n process.exit(0);\n }\n } else if (gate === \"abort\") {\n console.log(chalk.yellow(\" Aborted. Spec was NOT saved.\"));\n process.exit(0);\n }\n\n console.log(chalk.green(\" ✔ Approved — continuing to code generation.\"));\n } else {\n console.log(chalk.gray(\"[3.5/6] Approval Gate: skipped (--auto).\"));\n }\n\n // ── Step 3.8: DSL Extraction + Validation ─────────────────────────────────\n // Runs after approval, before worktree, so the DSL is saved alongside the spec.\n // We extract from finalSpec (already approved). The DSL file is saved in Step 5.\n let extractedDsl: import(\"../core/dsl-types\").SpecDSL | null = null;\n\n if (opts.skipDsl) {\n console.log(chalk.gray(\"\\n[DSL] Skipped (--skip-dsl).\"));\n } else {\n console.log(chalk.blue(\"\\n[DSL] Extracting structured DSL from spec...\"));\n console.log(chalk.gray(` Provider: ${specProviderName}/${specModelName}`));\n try {\n const isFrontend = isFrontendDeps(context.dependencies);\n if (isFrontend) console.log(chalk.gray(\" Frontend project detected — using ComponentSpec extractor\"));\n const dslExtractor = new DslExtractor(specProvider);\n extractedDsl = await dslExtractor.extract(finalSpec, { auto: opts.auto, isFrontend });\n if (extractedDsl) {\n console.log(chalk.green(\" ✔ DSL extracted and validated.\"));\n } else {\n console.log(chalk.yellow(\" ⚠ DSL skipped — codegen will use Spec + Tasks only.\"));\n }\n } catch (err) {\n // Unexpected error (not user abort — that would have called process.exit)\n console.log(chalk.yellow(` ⚠ DSL extraction error: ${(err as Error).message} — continuing without DSL.`));\n }\n }\n\n // ── Step 4: Git Worktree ──────────────────────────────────────────────────\n // Frontend projects (React / Vue / Next / React-Native) work directly on a\n // feature branch — no worktree needed. node_modules is not copied into\n // worktrees by default, so running the dev server would break.\n // Auto-skip unless the user explicitly passes --worktree.\n const isFrontendProject = isFrontendDeps(context.dependencies ?? []);\n const skipWorktree = opts.worktree\n ? false\n : opts.skipWorktree || isFrontendProject;\n\n let workingDir = currentDir;\n if (!skipWorktree) {\n console.log(chalk.blue(\"\\n[4/6] Setting up git worktree...\"));\n const worktreeManager = new GitWorktreeManager(currentDir);\n const worktreePath = await worktreeManager.createWorktree(idea);\n if (worktreePath) workingDir = worktreePath;\n } else {\n const reason = opts.worktree\n ? \"\"\n : isFrontendProject\n ? \" (frontend project — use --worktree to override)\"\n : \" (--skip-worktree)\";\n console.log(chalk.gray(`[4/6] Skipping worktree${reason}.`));\n }\n\n // ── Step 5: Save Spec (versioned) + Generate Tasks ────────────────────────\n const specsDir = path.join(workingDir, \"specs\");\n await fs.ensureDir(specsDir);\n\n const { filePath: specFile, version: specVersion } = await nextVersionPath(specsDir, featureSlug);\n await fs.writeFile(specFile, finalSpec, \"utf-8\");\n console.log(chalk.green(`\\n[5/6] ✔ Spec saved: ${specFile}`) + chalk.gray(` (v${specVersion})`));\n\n // Save DSL alongside the spec if extraction succeeded\n let savedDslFile: string | null = null;\n if (extractedDsl) {\n const dslExtractor = new DslExtractor(specProvider);\n savedDslFile = await dslExtractor.saveDsl(extractedDsl, specFile);\n console.log(chalk.green(` ✔ DSL saved : ${savedDslFile}`));\n }\n\n if (!opts.skipTasks) {\n const taskGen = new TaskGenerator(specProvider);\n let tasksToSave = initialTasks;\n\n // If combined call didn't produce tasks (parse failed), retry as a separate call\n if (tasksToSave.length === 0) {\n console.log(chalk.blue(`\\n Generating tasks (separate call)...`));\n try {\n tasksToSave = await taskGen.generateTasks(finalSpec, context);\n } catch (err) {\n console.log(chalk.yellow(` ⚠ Task generation failed: ${(err as Error).message}`));\n }\n }\n\n if (tasksToSave.length > 0) {\n const sorted = taskGen.sortByLayer(tasksToSave);\n const tasksFile = await taskGen.saveTasks(sorted, specFile);\n printTasks(sorted);\n console.log(chalk.green(` ✔ Tasks saved: ${tasksFile}`));\n } else {\n console.log(chalk.yellow(\" ⚠ No tasks generated — code generation will use fallback file planning.\"));\n }\n }\n\n // ── Step 6: Code Generation ───────────────────────────────────────────────\n console.log(chalk.blue(`\\n[6/6] Code generation (mode: ${codegenMode})...`));\n const codegenProvider =\n codegenProviderName === specProviderName && codegenApiKey === specApiKey\n ? specProvider\n : createProvider(codegenProviderName, codegenApiKey, codegenModelName);\n\n // ── TDD: generate failing tests BEFORE implementation ────────────────────\n let generatedTestFiles: string[] = [];\n if (opts.tdd && extractedDsl) {\n console.log(chalk.cyan(\"\\n[TDD] Generating pre-implementation tests (will fail until code is written)...\"));\n const testGen = new TestGenerator(codegenProvider);\n generatedTestFiles = await testGen.generateTdd(extractedDsl, workingDir);\n }\n\n const codegen = new CodeGenerator(codegenProvider, codegenMode);\n const generatedFiles = await codegen.generateCode(specFile, workingDir, context, {\n auto: opts.auto,\n resume: opts.resume,\n dslFilePath: savedDslFile ?? undefined,\n repoType: detectedRepoType,\n });\n\n // ── Step 7: Test Skeleton Generation (skipped in TDD mode — tests already written) ──\n if (opts.tdd) {\n console.log(chalk.gray(\"\\n[7/9] TDD mode — test files already written pre-implementation.\"));\n } else if (opts.skipTests) {\n console.log(chalk.gray(\"\\n[7/9] Skipping test generation (--skip-tests).\"));\n } else if (!extractedDsl) {\n console.log(chalk.gray(\"\\n[7/9] Skipping test generation (no DSL available).\"));\n } else {\n console.log(chalk.blue(`\\n[7/9] Test skeleton generation...`));\n const testGen = new TestGenerator(codegenProvider);\n generatedTestFiles = await testGen.generate(extractedDsl, workingDir);\n }\n\n // ── Step 8: Error Feedback Loop ───────────────────────────────────────────\n // In TDD mode, the error feedback loop is the primary driver:\n // it runs tests, collects failures, and fixes implementation until tests pass.\n if (opts.skipErrorFeedback) {\n console.log(chalk.gray(\"[8/9] Skipping error feedback (--skip-error-feedback).\"));\n } else {\n if (opts.tdd) {\n console.log(chalk.cyan(\"[8/9] TDD mode — error feedback loop driving implementation to pass tests...\"));\n }\n await runErrorFeedback(codegenProvider, workingDir, extractedDsl, {\n maxCycles: opts.tdd ? 3 : 2, // TDD gets one extra cycle\n });\n }\n\n // ── Step 9: Code Review ───────────────────────────────────────────────────\n let reviewResult = \"\";\n if (!opts.skipReview) {\n console.log(chalk.blue(\"\\n[9/9] Automated code review (2-pass: architecture + implementation)...\"));\n const reviewer = new CodeReviewer(specProvider, currentDir);\n const savedSpec = await fs.readFile(specFile, \"utf-8\");\n\n if (codegenMode === \"api\" && generatedFiles.length > 0) {\n // api mode: review the generated files directly (no git diff available)\n reviewResult = await reviewer.reviewFiles(savedSpec, generatedFiles, workingDir, specFile);\n } else {\n // claude-code / plan mode: review via git diff\n const originalDir = process.cwd();\n try {\n process.chdir(workingDir);\n reviewResult = await reviewer.reviewCode(savedSpec, specFile);\n } finally {\n process.chdir(originalDir);\n }\n }\n\n // Knowledge Memory: extract lessons from review and append to constitution §9\n await accumulateReviewKnowledge(specProvider, currentDir, reviewResult);\n }\n\n // ── Done ──────────────────────────────────────────────────────────────────\n console.log(chalk.bold.green(\"\\n✔ All done!\"));\n console.log(chalk.gray(` Spec : ${specFile}`));\n if (savedDslFile) console.log(chalk.gray(` DSL : ${savedDslFile}`));\n if (generatedTestFiles.length > 0) {\n console.log(chalk.gray(` Tests : ${generatedTestFiles.length} skeleton file(s) generated`));\n }\n console.log(chalk.gray(` Working dir : ${workingDir}`));\n if (workingDir !== currentDir) {\n console.log(chalk.gray(` Run \\`cd ${workingDir}\\` to enter the worktree.`));\n }\n });\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Command: review\n// ═══════════════════════════════════════════════════════════════════════════════\n\nprogram\n .command(\"review\")\n .description(\"Run AI code review on current git diff against a spec\")\n .argument(\"[specFile]\", \"Path to spec file (auto-detects latest in specs/ if omitted)\")\n .option(\n \"--provider <name>\",\n `AI provider (${SUPPORTED_PROVIDERS.join(\"|\")})`,\n undefined\n )\n .option(\"--model <name>\", \"Model name\")\n .option(\"-k, --key <apiKey>\", \"API key\")\n .action(async (specFile: string | undefined, opts) => {\n const currentDir = process.cwd();\n const config = await loadConfig(currentDir);\n\n const providerName = opts.provider || config.provider || \"gemini\";\n const modelName = opts.model || config.model || DEFAULT_MODELS[providerName];\n const apiKey = await resolveApiKey(providerName, opts.key);\n\n const provider = createProvider(providerName, apiKey, modelName);\n const reviewer = new CodeReviewer(provider, currentDir);\n\n let specContent = \"\";\n let resolvedSpecFile: string | undefined;\n\n if (specFile && (await fs.pathExists(specFile))) {\n specContent = await fs.readFile(specFile, \"utf-8\");\n resolvedSpecFile = specFile;\n console.log(chalk.gray(`Using spec: ${specFile}`));\n } else {\n // Auto-detect the latest spec in specs/\n const specsDir = path.join(currentDir, \"specs\");\n if (await fs.pathExists(specsDir)) {\n const files = (await fs.readdir(specsDir))\n .filter((f) => f.endsWith(\".md\"))\n .sort()\n .reverse();\n if (files.length > 0) {\n const latest = path.join(specsDir, files[0]);\n specContent = await fs.readFile(latest, \"utf-8\");\n resolvedSpecFile = latest;\n console.log(chalk.gray(`Auto-detected spec: specs/${files[0]}`));\n }\n }\n }\n\n if (!specContent) {\n console.log(chalk.yellow(\"No spec file found. Running review without spec context.\"));\n }\n\n await reviewer.reviewCode(specContent, resolvedSpecFile);\n await reviewer.printScoreTrend();\n });\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Command: init — generate Project Constitution\n// ═══════════════════════════════════════════════════════════════════════════════\n\nprogram\n .command(\"init\")\n .description(`Analyze codebase and generate Project Constitution (${CONSTITUTION_FILE})`)\n .option(\n \"--provider <name>\",\n `AI provider (${SUPPORTED_PROVIDERS.join(\"|\")})`,\n undefined\n )\n .option(\"--model <name>\", \"Model name\")\n .option(\"-k, --key <apiKey>\", \"API key\")\n .option(\"--force\", \"Overwrite existing constitution\")\n .option(\n \"--global\",\n `Generate a Global Constitution (~/${GLOBAL_CONSTITUTION_FILE}) instead of a project-level one`\n )\n .option(\"--consolidate\", \"Consolidate §9 accumulated lessons into §1–§8 core rules (prune & rebase)\")\n .option(\"--dry-run\", \"Preview consolidation result without writing (use with --consolidate)\")\n .action(async (opts) => {\n const currentDir = process.cwd();\n const config = await loadConfig(currentDir);\n\n const providerName = opts.provider || config.provider || \"gemini\";\n const modelName = opts.model || config.model || DEFAULT_MODELS[providerName];\n const apiKey = await resolveApiKey(providerName, opts.key);\n const provider = createProvider(providerName, apiKey, modelName);\n\n // ── Consolidate mode ─────────────────────────────────────────────────\n if (opts.consolidate) {\n const consolidator = new ConstitutionConsolidator(provider);\n try {\n const result = await consolidator.consolidate(currentDir, {\n dryRun: opts.dryRun,\n auto: opts.auto,\n });\n if (result.written) {\n console.log(chalk.blue(\"\\n Summary:\"));\n console.log(chalk.gray(` Lines : ${result.before.totalLines} → ${result.after.totalLines} (${result.before.totalLines - result.after.totalLines > 0 ? \"-\" : \"+\"}${Math.abs(result.before.totalLines - result.after.totalLines)})`));\n console.log(chalk.gray(` §9 : ${result.before.lessonCount} → ${result.after.lessonCount} lessons remaining`));\n if (result.backupPath) {\n console.log(chalk.gray(` Backup: ${path.basename(result.backupPath)}`));\n }\n }\n } catch (err) {\n console.error(chalk.red(` ✘ Consolidation failed: ${(err as Error).message}`));\n process.exit(1);\n }\n return;\n }\n\n // ── Global constitution mode ──────────────────────────────────────────\n if (opts.global) {\n const existing = await loadGlobalConstitution([currentDir]);\n if (existing && !opts.force) {\n console.log(chalk.yellow(`\\n Global constitution already exists at: ${existing.source}`));\n console.log(chalk.gray(\" Use --force to overwrite it.\"));\n return;\n }\n\n console.log(chalk.blue(\"\\n─── Generating Global Constitution ──────────────\"));\n console.log(chalk.gray(` Provider: ${providerName}/${modelName}`));\n console.log(chalk.gray(\" Scanning repos in workspace...\"));\n\n // Build per-repo summaries from sibling directories\n const loader = new ContextLoader(currentDir);\n const ctx = await loader.loadProjectContext();\n const summary = [\n `Tech stack: ${ctx.techStack.join(\", \") || \"unknown\"}`,\n `Dependencies: ${ctx.dependencies.slice(0, 20).join(\", \")}`,\n ].join(\"\\n\");\n\n const prompt = buildGlobalConstitutionPrompt([{ name: path.basename(currentDir), summary }]);\n let globalConstitution: string;\n try {\n globalConstitution = await provider.generate(prompt, globalConstitutionSystemPrompt);\n } catch (err) {\n console.error(chalk.red(\" ✘ Failed to generate global constitution:\"), err);\n process.exit(1);\n }\n\n const saved = await saveGlobalConstitution(globalConstitution, currentDir);\n console.log(chalk.green(`\\n ✔ Global constitution saved: ${saved}`));\n console.log(chalk.gray(\" This will be automatically merged into all project constitutions in this workspace.\"));\n console.log(chalk.gray(\" Project-level rules always override global rules.\\n\"));\n console.log(chalk.bold(\" Preview:\"));\n console.log(chalk.gray(globalConstitution.split(\"\\n\").slice(0, 12).join(\"\\n\")));\n if (globalConstitution.split(\"\\n\").length > 12) {\n console.log(chalk.gray(` ... (${globalConstitution.split(\"\\n\").length} lines total)`));\n }\n return;\n }\n\n // ── Project constitution mode (default) ───────────────────────────────\n const constitutionPath = path.join(currentDir, CONSTITUTION_FILE);\n\n if (!opts.force && (await fs.pathExists(constitutionPath))) {\n console.log(chalk.yellow(`\\n ${CONSTITUTION_FILE} already exists.`));\n console.log(chalk.gray(\" Use --force to overwrite it.\"));\n console.log(chalk.gray(` Or edit it directly: ${constitutionPath}`));\n return;\n }\n\n console.log(chalk.blue(\"\\n─── Generating Project Constitution ─────────────\"));\n console.log(chalk.gray(` Provider: ${providerName}/${modelName}`));\n console.log(chalk.gray(\" Analyzing codebase...\"));\n\n const generator = new ConstitutionGenerator(provider);\n\n let constitution: string;\n try {\n constitution = await generator.generate(currentDir);\n } catch (err) {\n console.error(chalk.red(\" ✘ Failed to generate constitution:\"), err);\n process.exit(1);\n }\n\n const saved = await generator.saveConstitution(currentDir, constitution);\n\n // Note if a global constitution will also be applied\n const globalResult = await loadGlobalConstitution([path.dirname(currentDir)]);\n if (globalResult) {\n console.log(chalk.cyan(`\\n ℹ Global constitution detected: ${globalResult.source}`));\n console.log(chalk.gray(\" It will be merged with this project constitution at runtime.\"));\n console.log(chalk.gray(\" Project rules take priority over global rules.\"));\n }\n\n console.log(chalk.green(`\\n ✔ Constitution saved: ${saved}`));\n console.log(chalk.gray(\" This file will be automatically used in all future `ai-spec create` runs.\"));\n console.log(chalk.gray(\" Edit it to add custom rules or red lines for your project.\\n\"));\n console.log(chalk.bold(\" Preview:\"));\n console.log(chalk.gray(constitution.split(\"\\n\").slice(0, 15).join(\"\\n\")));\n if (constitution.split(\"\\n\").length > 15) {\n console.log(chalk.gray(` ... (${constitution.split(\"\\n\").length} lines total)`));\n }\n });\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Command: config\n// ═══════════════════════════════════════════════════════════════════════════════\n\nprogram\n .command(\"config\")\n .description(`Set default configuration for this project (saved to ${CONFIG_FILE})`)\n .option(\"--provider <name>\", \"Default AI provider for spec generation\")\n .option(\"--model <name>\", \"Default model for spec generation\")\n .option(\n \"--codegen <mode>\",\n \"Default code generation mode (claude-code|api|plan)\"\n )\n .option(\"--codegen-provider <name>\", \"Default provider for code generation\")\n .option(\"--codegen-model <name>\", \"Default model for code generation\")\n .option(\"--show\", \"Print current configuration\")\n .option(\"--reset\", \"Reset configuration to empty\")\n .option(\"--clear-keys\", \"Delete all saved API keys from ~/.ai-spec-keys.json\")\n .option(\"--clear-key <provider>\", \"Delete saved API key for a specific provider\")\n .option(\"--list-keys\", \"Show which providers have a saved key\")\n .action(async (opts) => {\n const currentDir = process.cwd();\n const configPath = path.join(currentDir, CONFIG_FILE);\n\n if (opts.clearKeys) {\n await clearAllKeys();\n console.log(chalk.green(`✔ All saved API keys cleared.`));\n return;\n }\n\n if (opts.clearKey) {\n await clearKey(opts.clearKey);\n console.log(chalk.green(`✔ Saved key for \"${opts.clearKey}\" removed.`));\n return;\n }\n\n if (opts.listKeys) {\n const store: Record<string, string> = await fs.readJson(KEY_STORE_FILE).catch(() => ({}));\n const providers = Object.keys(store);\n if (providers.length === 0) {\n console.log(chalk.gray(\"No saved API keys.\"));\n } else {\n console.log(chalk.bold(\"Saved API keys:\"));\n for (const p of providers) {\n const k = store[p];\n console.log(chalk.gray(` ${p}: ${k.slice(0, 6)}...${k.slice(-4)}`));\n }\n console.log(chalk.gray(`\\nFile: ${KEY_STORE_FILE}`));\n }\n return;\n }\n\n if (opts.reset) {\n await fs.writeJson(configPath, {}, { spaces: 2 });\n console.log(chalk.green(`✔ Config reset: ${configPath}`));\n return;\n }\n\n const existing: AiSpecConfig = await loadConfig(currentDir);\n\n if (opts.show) {\n if (Object.keys(existing).length === 0) {\n console.log(chalk.gray(\"No config file found. Using built-in defaults.\"));\n } else {\n console.log(chalk.bold(`${configPath}:`));\n console.log(JSON.stringify(existing, null, 2));\n }\n return;\n }\n\n const updated: AiSpecConfig = { ...existing };\n if (opts.provider) updated.provider = opts.provider;\n if (opts.model) updated.model = opts.model;\n if (opts.codegen) updated.codegen = opts.codegen as CodeGenMode;\n if (opts.codegenProvider) updated.codegenProvider = opts.codegenProvider;\n if (opts.codegenModel) updated.codegenModel = opts.codegenModel;\n\n await fs.writeJson(configPath, updated, { spaces: 2 });\n console.log(chalk.green(`✔ Config saved to ${configPath}`));\n console.log(JSON.stringify(updated, null, 2));\n });\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Command: model — interactive model switcher\n// ═══════════════════════════════════════════════════════════════════════════════\n\nprogram\n .command(\"model\")\n .description(\"Interactively switch the active AI provider/model and save to .ai-spec.json\")\n .option(\"--list\", \"List all available providers and models\")\n .action(async (opts) => {\n const currentDir = process.cwd();\n const configPath = path.join(currentDir, CONFIG_FILE);\n\n // ── --list: just print the catalog ────────────────────────────────────────\n if (opts.list) {\n console.log(chalk.bold(\"\\nAvailable providers & models:\\n\"));\n for (const [key, meta] of Object.entries(PROVIDER_CATALOG)) {\n console.log(\n ` ${chalk.bold.cyan(key.padEnd(10))} ${chalk.white(meta.displayName)}`\n );\n console.log(chalk.gray(` ${meta.description}`));\n console.log(\n chalk.gray(\n ` env: ${meta.envKey} | models: ${meta.models.join(\", \")}`\n )\n );\n console.log();\n }\n return;\n }\n\n const existing: AiSpecConfig = await loadConfig(currentDir);\n\n console.log(chalk.blue(\"\\n─── Model Switcher ─────────────────────────────\"));\n if (Object.keys(existing).length > 0) {\n console.log(\n chalk.gray(\n ` Current: spec=${existing.provider ?? \"gemini\"}/${existing.model ?? DEFAULT_MODELS[existing.provider ?? \"gemini\"]}` +\n (existing.codegenProvider\n ? ` codegen=${existing.codegenProvider}/${existing.codegenModel ?? \"\"}`\n : \"\")\n )\n );\n }\n console.log();\n\n // ── What to configure ─────────────────────────────────────────────────────\n const target = await select({\n message: \"Configure model for:\",\n choices: [\n { name: \"Spec generation (used for spec writing & refinement)\", value: \"spec\" },\n { name: \"Code generation (used when --codegen api is active)\", value: \"codegen\" },\n { name: \"Both (same provider/model for all tasks)\", value: \"both\" },\n ],\n });\n\n // ── Helper: pick provider + model ─────────────────────────────────────────\n async function pickProviderAndModel(label: string): Promise<{ provider: string; model: string }> {\n const providerKey = await select({\n message: `${label} — select provider:`,\n choices: Object.entries(PROVIDER_CATALOG).map(([key, meta]) => ({\n name: `${meta.displayName.padEnd(22)} ${chalk.gray(meta.description)}`,\n value: key,\n short: meta.displayName,\n })),\n });\n\n const meta = PROVIDER_CATALOG[providerKey];\n const modelChoices = [\n ...meta.models.map((m) => ({ name: m, value: m })),\n { name: chalk.italic(\"✎ Enter custom model name...\"), value: \"__custom__\" },\n ];\n\n let chosenModel = await select({\n message: `${label} — select model (${meta.displayName}):`,\n choices: modelChoices,\n });\n\n if (chosenModel === \"__custom__\") {\n chosenModel = await input({\n message: \"Enter model name:\",\n validate: (v) => v.trim().length > 0 || \"Model name cannot be empty\",\n });\n }\n\n return { provider: providerKey, model: chosenModel };\n }\n\n // ── Run picker(s) ─────────────────────────────────────────────────────────\n const updated: AiSpecConfig = { ...existing };\n\n if (target === \"spec\" || target === \"both\") {\n const { provider, model } = await pickProviderAndModel(\"Spec\");\n updated.provider = provider;\n updated.model = model;\n }\n\n if (target === \"codegen\" || target === \"both\") {\n if (target === \"both\") {\n updated.codegenProvider = updated.provider;\n updated.codegenModel = updated.model;\n } else {\n const { provider, model } = await pickProviderAndModel(\"Codegen\");\n updated.codegenProvider = provider;\n updated.codegenModel = model;\n }\n\n // claude-code 模式只支持 Claude provider。\n // 如果选了非 claude provider,自动把 codegen 模式改为 api。\n const effectiveCodegenProvider = updated.codegenProvider ?? updated.provider ?? \"gemini\";\n if (effectiveCodegenProvider !== \"claude\") {\n if (!updated.codegen || updated.codegen === \"claude-code\") {\n updated.codegen = \"api\";\n console.log(\n chalk.yellow(\n `\\n ⚠ provider \"${effectiveCodegenProvider}\" 不支持 \"claude-code\" 模式。`\n )\n );\n console.log(chalk.gray(` 已自动将 codegen 模式设为 \"api\"。`));\n }\n }\n }\n\n // ── Confirm & save ────────────────────────────────────────────────────────\n console.log(chalk.blue(\"\\n Preview:\"));\n console.log(chalk.gray(` spec → ${updated.provider}/${updated.model}`));\n if (updated.codegenProvider) {\n console.log(\n chalk.gray(\n ` codegen → ${updated.codegenProvider}/${updated.codegenModel} (mode: ${updated.codegen ?? \"claude-code\"})`\n )\n );\n }\n\n const ok = await confirm({ message: \"Save to .ai-spec.json?\", default: true });\n if (!ok) {\n console.log(chalk.gray(\" Cancelled.\"));\n return;\n }\n\n await fs.writeJson(configPath, updated, { spaces: 2 });\n console.log(chalk.green(`\\n ✔ Saved to ${configPath}`));\n\n // Remind about env var if not set\n const providerToCheck = updated.provider ?? \"gemini\";\n const envKey = ENV_KEY_MAP[providerToCheck];\n if (envKey && !process.env[envKey]) {\n console.log(\n chalk.yellow(\n ` ⚠ Remember to set ${envKey} in your environment or .env file.`\n )\n );\n }\n });\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Multi-Repo Pipeline\n// ═══════════════════════════════════════════════════════════════════════════════\n\n/**\n * Run a single repo through the full spec→dsl→worktree→codegen→tests→review pipeline.\n * Returns the extracted DSL (or null) for contract bridging.\n */\nasync function runSingleRepoPipelineInWorkspace(opts: {\n idea: string;\n specProvider: ReturnType<typeof createProvider>;\n specProviderName: string;\n specModelName: string;\n codegenProvider: ReturnType<typeof createProvider>;\n codegenMode: CodeGenMode;\n repoAbsPath: string;\n repoName: string;\n cliOpts: Record<string, unknown>;\n contractContextSection?: string;\n}): Promise<{ dsl: SpecDSL | null; specFile: string | null }> {\n const {\n idea,\n specProvider,\n specProviderName,\n specModelName,\n codegenProvider,\n codegenMode,\n repoAbsPath,\n repoName,\n cliOpts,\n contractContextSection,\n } = opts;\n\n console.log(chalk.blue(`\\n [${repoName}] Loading project context...`));\n const loader = new ContextLoader(repoAbsPath);\n let context = await loader.loadProjectContext();\n\n // Detect repo language so the correct codegen system prompt is used\n const { type: detectedRepoType } = await detectRepoType(repoAbsPath);\n\n console.log(chalk.gray(` Tech stack: ${context.techStack.join(\", \") || \"unknown\"} [${detectedRepoType}]`));\n console.log(chalk.gray(` Dependencies: ${context.dependencies.length} packages`));\n\n if (!context.constitution) {\n console.log(chalk.yellow(` Constitution: not found — auto-generating...`));\n try {\n const constitutionGen = new ConstitutionGenerator(specProvider);\n const constitutionContent = await constitutionGen.generate(repoAbsPath);\n await constitutionGen.saveConstitution(repoAbsPath, constitutionContent);\n context.constitution = constitutionContent;\n console.log(chalk.green(` Constitution: generated`));\n } catch (err) {\n console.log(chalk.yellow(` Constitution: auto-generation failed (${(err as Error).message}), continuing.`));\n }\n } else {\n console.log(chalk.green(` Constitution: found`));\n }\n\n // Build the spec idea: inject contract context if available\n let fullIdea = idea;\n if (contractContextSection) {\n fullIdea = `${idea}\\n\\n${contractContextSection}`;\n }\n\n console.log(chalk.blue(` [${repoName}] Generating spec...`));\n let finalSpec: string;\n try {\n const result = await generateSpecWithTasks(specProvider, fullIdea, context);\n finalSpec = result.spec;\n console.log(chalk.green(` Spec generated.`));\n } catch (err) {\n console.error(chalk.red(` Spec generation failed: ${(err as Error).message}`));\n return { dsl: null, specFile: null };\n }\n\n // DSL Extraction\n let extractedDsl: SpecDSL | null = null;\n if (!cliOpts.skipDsl) {\n console.log(chalk.blue(` [${repoName}] Extracting DSL...`));\n try {\n const dslExtractor = new DslExtractor(specProvider);\n const repoIsFrontend = isFrontendDeps(context.dependencies);\n extractedDsl = await dslExtractor.extract(finalSpec, { auto: true, isFrontend: repoIsFrontend });\n if (extractedDsl) {\n console.log(chalk.green(` DSL extracted.`));\n }\n } catch (err) {\n console.log(chalk.yellow(` DSL extraction failed: ${(err as Error).message}`));\n }\n }\n\n // Git Worktree — auto-skip for frontend repos\n const isFrontendRepo = isFrontendDeps(context.dependencies ?? []);\n const skipWorktreeForRepo = cliOpts.worktree\n ? false\n : cliOpts.skipWorktree || isFrontendRepo;\n\n let workingDir = repoAbsPath;\n if (!skipWorktreeForRepo) {\n console.log(chalk.blue(` [${repoName}] Setting up git worktree...`));\n try {\n const worktreeManager = new GitWorktreeManager(repoAbsPath);\n const worktreePath = await worktreeManager.createWorktree(idea);\n if (worktreePath) workingDir = worktreePath;\n } catch (err) {\n console.log(chalk.yellow(` Worktree setup failed: ${(err as Error).message}. Using main branch.`));\n }\n } else {\n console.log(chalk.gray(` [${repoName}] Skipping worktree${isFrontendRepo ? \" (frontend repo)\" : \"\"}.`));\n }\n\n // Save Spec\n const specsDir = path.join(workingDir, \"specs\");\n await fs.ensureDir(specsDir);\n const featureSlug = slugify(idea);\n const { filePath: specFile } = await nextVersionPath(specsDir, featureSlug);\n await fs.writeFile(specFile, finalSpec, \"utf-8\");\n console.log(chalk.green(` Spec saved: ${path.relative(repoAbsPath, specFile)}`));\n\n let savedDslFile: string | null = null;\n if (extractedDsl) {\n const dslExtractorForSave = new DslExtractor(specProvider);\n savedDslFile = await dslExtractorForSave.saveDsl(extractedDsl, specFile);\n console.log(chalk.green(` DSL saved: ${path.relative(repoAbsPath, savedDslFile)}`));\n }\n\n // Code Generation\n console.log(chalk.blue(` [${repoName}] Running code generation (mode: ${codegenMode})...`));\n try {\n const codegen = new CodeGenerator(codegenProvider, codegenMode);\n await codegen.generateCode(specFile, workingDir, context, {\n auto: true,\n dslFilePath: savedDslFile ?? undefined,\n repoType: detectedRepoType,\n });\n console.log(chalk.green(` Code generation complete.`));\n } catch (err) {\n console.log(chalk.yellow(` Code generation failed: ${(err as Error).message}`));\n }\n\n // Test Generation\n if (!cliOpts.skipTests && extractedDsl) {\n console.log(chalk.blue(` [${repoName}] Generating test skeletons...`));\n try {\n const testGen = new TestGenerator(codegenProvider);\n const testFiles = await testGen.generate(extractedDsl, workingDir);\n console.log(chalk.green(` ${testFiles.length} test file(s) generated.`));\n } catch (err) {\n console.log(chalk.yellow(` Test generation failed: ${(err as Error).message}`));\n }\n }\n\n // Error Feedback\n if (!cliOpts.skipErrorFeedback) {\n try {\n await runErrorFeedback(codegenProvider, workingDir, extractedDsl, { maxCycles: 1 });\n } catch (err) {\n console.log(chalk.yellow(` Error feedback failed: ${(err as Error).message}`));\n }\n }\n\n // Code Review\n if (!cliOpts.skipReview) {\n console.log(chalk.blue(` [${repoName}] Running code review...`));\n try {\n const reviewer = new CodeReviewer(specProvider);\n const reviewResult = await reviewer.reviewCode(finalSpec);\n await accumulateReviewKnowledge(specProvider, repoAbsPath, reviewResult);\n console.log(chalk.green(` Code review complete.`));\n } catch (err) {\n console.log(chalk.yellow(` Code review failed: ${(err as Error).message}`));\n }\n }\n\n return { dsl: extractedDsl, specFile };\n}\n\n/**\n * Multi-repo pipeline: decompose → order repos → run each repo in order → bridge contracts.\n */\nasync function runMultiRepoPipeline(\n idea: string,\n workspace: WorkspaceConfig,\n opts: Record<string, unknown>,\n currentDir: string,\n config: AiSpecConfig\n): Promise<void> {\n // ── Resolve providers ──────────────────────────────────────────────────────\n const specProviderName = (opts.provider as string) || config.provider || \"gemini\";\n const specModelName = (opts.model as string) || config.model || DEFAULT_MODELS[specProviderName];\n const specApiKey = await resolveApiKey(specProviderName, opts.key as string | undefined);\n const specProvider = createProvider(specProviderName, specApiKey, specModelName);\n\n const codegenMode: CodeGenMode = ((opts.codegen as string) as CodeGenMode) || config.codegen || \"claude-code\";\n const codegenProviderName = (opts.codegenProvider as string) || config.codegenProvider || specProviderName;\n const codegenModelName = (opts.codegenModel as string) || config.codegenModel || DEFAULT_MODELS[codegenProviderName];\n const codegenApiKey =\n codegenProviderName === specProviderName\n ? specApiKey\n : await resolveApiKey(codegenProviderName, opts.codegenKey as string | undefined);\n const codegenProvider =\n codegenProviderName === specProviderName && codegenApiKey === specApiKey\n ? specProvider\n : createProvider(codegenProviderName, codegenApiKey, codegenModelName);\n\n printBanner({\n specProvider: specProviderName,\n specModel: specModelName,\n codegenMode,\n codegenProvider: codegenProviderName,\n codegenModel: codegenModelName,\n });\n\n const workspaceLoader = new WorkspaceLoader(currentDir);\n\n // ── Step 1: Load per-repo contexts ─────────────────────────────────────────\n console.log(chalk.blue(\"\\n[W1] Loading per-repo contexts...\"));\n const contexts = new Map<string, import(\"../core/context-loader\").ProjectContext>();\n const frontendContexts = new Map<string, import(\"../core/frontend-context-loader\").FrontendContext>();\n\n for (const repo of workspace.repos) {\n const repoAbsPath = workspaceLoader.resolveAbsPath(repo);\n try {\n const loader = new ContextLoader(repoAbsPath);\n const ctx = await loader.loadProjectContext();\n contexts.set(repo.name, ctx);\n\n // Load frontend context for frontend/mobile repos\n if (repo.role === \"frontend\" || repo.role === \"mobile\") {\n const fctx = await loadFrontendContext(repoAbsPath);\n frontendContexts.set(repo.name, fctx);\n console.log(chalk.gray(` ${repo.name}: ${fctx.framework} / ${fctx.httpClient} / hooks:${fctx.hookFiles.length} stores:${fctx.storeFiles.length}`));\n } else {\n console.log(chalk.gray(` ${repo.name}: ${ctx.techStack.join(\", \") || \"unknown\"} (${ctx.dependencies.length} deps)`));\n }\n } catch (err) {\n console.log(chalk.yellow(` ${repo.name}: context load failed — ${(err as Error).message}`));\n }\n }\n\n // ── Step 2: Decompose requirement ─────────────────────────────────────────\n console.log(chalk.blue(\"\\n[W2] Decomposing requirement across repos...\"));\n const decomposer = new RequirementDecomposer(specProvider);\n let decomposition: DecompositionResult;\n\n try {\n decomposition = await decomposer.decompose(idea, workspace, contexts, frontendContexts);\n console.log(chalk.green(` Summary: ${decomposition.summary}`));\n console.log(chalk.gray(` Repos affected: ${decomposition.repos.map((r) => r.repoName).join(\", \")}`));\n if (decomposition.coordinationNotes) {\n console.log(chalk.gray(` Coordination: ${decomposition.coordinationNotes}`));\n }\n } catch (err) {\n console.error(chalk.red(` Decomposition failed: ${(err as Error).message}`));\n console.log(chalk.yellow(\" Falling back to running all repos independently.\"));\n // Fallback: create basic requirements for all repos\n decomposition = {\n originalRequirement: idea,\n summary: idea,\n coordinationNotes: \"\",\n repos: workspace.repos.map((repo) => ({\n repoName: repo.name,\n role: repo.role,\n specIdea: idea,\n isContractProvider: repo.role === \"backend\",\n dependsOnRepos: repo.role !== \"backend\" ? workspace.repos.filter((r) => r.role === \"backend\").map((r) => r.name) : [],\n uxDecisions: null,\n })),\n };\n }\n\n // ── Step 3: Show decomposition preview + confirmation ─────────────────────\n if (!opts.auto) {\n console.log(chalk.cyan(\"\\n[W3] Decomposition Preview:\"));\n console.log(chalk.cyan(\"─\".repeat(52)));\n for (const r of decomposition.repos) {\n console.log(chalk.bold(` ${r.repoName} (${r.role})`));\n console.log(chalk.gray(` ${r.specIdea.slice(0, 150)}${r.specIdea.length > 150 ? \"...\" : \"\"}`));\n if (r.uxDecisions) {\n const ux = r.uxDecisions;\n const uxSummary = [\n ux.throttleMs ? `throttle ${ux.throttleMs}ms` : \"\",\n ux.debounceMs ? `debounce ${ux.debounceMs}ms` : \"\",\n ux.optimisticUpdate ? \"optimistic-update\" : \"\",\n ux.errorRollback ? \"rollback\" : \"\",\n ]\n .filter(Boolean)\n .join(\", \");\n if (uxSummary) console.log(chalk.cyan(` UX: ${uxSummary}`));\n }\n if (r.dependsOnRepos.length > 0) {\n console.log(chalk.gray(` Depends on: ${r.dependsOnRepos.join(\", \")}`));\n }\n }\n console.log(chalk.cyan(\"─\".repeat(52)));\n\n const gate = await select({\n message: \"Proceed with multi-repo pipeline?\",\n choices: [\n { name: \"Proceed — run all repos\", value: \"proceed\" },\n { name: \"Abort\", value: \"abort\" },\n ],\n });\n\n if (gate === \"abort\") {\n console.log(chalk.yellow(\" Aborted.\"));\n process.exit(0);\n }\n }\n\n // ── Step 4: Sort repos by dependency order ─────────────────────────────────\n const sortedRepoRequirements = RequirementDecomposer.sortByDependency(decomposition.repos);\n\n // Contract accumulator: repoName → extracted DSL\n const contractDsls = new Map<string, SpecDSL>();\n\n // ── Step 5: Run each repo's pipeline ──────────────────────────────────────\n console.log(chalk.blue(`\\n[W4] Running pipeline for ${sortedRepoRequirements.length} repo(s)...`));\n\n const results: Array<{\n repoName: string;\n status: \"success\" | \"failed\" | \"skipped\";\n specFile: string | null;\n dsl: SpecDSL | null;\n }> = [];\n\n for (const repoReq of sortedRepoRequirements) {\n // Find repo config in workspace\n const repoConfig = workspace.repos.find((r) => r.name === repoReq.repoName);\n if (!repoConfig) {\n console.log(chalk.yellow(` Skipping ${repoReq.repoName} — not found in workspace config.`));\n results.push({ repoName: repoReq.repoName, status: \"skipped\", specFile: null, dsl: null });\n continue;\n }\n\n const repoAbsPath = workspaceLoader.resolveAbsPath(repoConfig);\n\n console.log(chalk.bold.blue(`\\n ── ${repoReq.repoName} (${repoReq.role}) ──────────────────────`));\n\n // Build contract context from upstream repos\n let contractContextSection: string | undefined;\n if (repoReq.dependsOnRepos.length > 0) {\n const contractParts: string[] = [];\n for (const depName of repoReq.dependsOnRepos) {\n const depDsl = contractDsls.get(depName);\n if (depDsl) {\n console.log(chalk.gray(` Using API contract from: ${depName}`));\n const contract = buildFrontendApiContract(depDsl);\n contractParts.push(buildContractContextSection(contract));\n }\n }\n if (contractParts.length > 0) {\n contractContextSection = contractParts.join(\"\\n\\n\");\n }\n }\n\n // For frontend repos, also load frontend context and inject UX decisions\n let specIdea = repoReq.specIdea;\n if (\n (repoReq.role === \"frontend\" || repoReq.role === \"mobile\") &&\n repoReq.uxDecisions\n ) {\n const frontendCtx = await loadFrontendContext(repoAbsPath);\n const frontendCtxSection = buildFrontendContextSection(frontendCtx);\n\n specIdea = buildFrontendSpecPrompt({\n specIdea: repoReq.specIdea,\n apiContractSection: contractContextSection,\n uxDecisions: repoReq.uxDecisions,\n frontendContext: frontendCtx,\n });\n\n // contractContextSection is already injected via buildFrontendSpecPrompt\n contractContextSection = undefined;\n\n console.log(chalk.gray(` Frontend context: ${frontendCtx.framework} / ${frontendCtx.httpClient} / ${frontendCtx.uiLibrary}`));\n }\n\n try {\n const { dsl, specFile } = await runSingleRepoPipelineInWorkspace({\n idea: specIdea,\n specProvider,\n specProviderName,\n specModelName,\n codegenProvider,\n codegenMode,\n repoAbsPath,\n repoName: repoReq.repoName,\n cliOpts: opts,\n contractContextSection,\n });\n\n // Store DSL for downstream repos if this is a contract provider\n if (repoReq.isContractProvider && dsl) {\n contractDsls.set(repoReq.repoName, dsl);\n console.log(chalk.green(` Contract stored for downstream repos.`));\n }\n\n results.push({ repoName: repoReq.repoName, status: \"success\", specFile, dsl });\n console.log(chalk.green(` ✔ ${repoReq.repoName} complete`));\n } catch (err) {\n console.error(chalk.red(` ✘ ${repoReq.repoName} failed: ${(err as Error).message}`));\n results.push({ repoName: repoReq.repoName, status: \"failed\", specFile: null, dsl: null });\n // Continue — don't abort other repos\n }\n }\n\n // ── Done ──────────────────────────────────────────────────────────────────\n console.log(chalk.bold.green(\"\\n✔ Multi-repo pipeline complete!\"));\n console.log(chalk.gray(` Workspace: ${workspace.name}`));\n console.log(chalk.gray(` Requirement: ${idea}`));\n console.log();\n for (const r of results) {\n const icon = r.status === \"success\" ? chalk.green(\"✔\") : r.status === \"failed\" ? chalk.red(\"✘\") : chalk.gray(\"−\");\n const specInfo = r.specFile ? chalk.gray(` → ${r.specFile}`) : \"\";\n console.log(` ${icon} ${r.repoName} (${r.status})${specInfo}`);\n }\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Command: workspace\n// ═══════════════════════════════════════════════════════════════════════════════\n\nconst workspaceCmd = program\n .command(\"workspace\")\n .description(\"Manage multi-repo workspace configuration\");\n\n// workspace init\nworkspaceCmd\n .command(\"init\")\n .description(`Interactive workspace setup — creates ${WORKSPACE_CONFIG_FILE}`)\n .action(async () => {\n const currentDir = process.cwd();\n const configPath = path.join(currentDir, WORKSPACE_CONFIG_FILE);\n\n if (await fs.pathExists(configPath)) {\n const overwrite = await confirm({\n message: `${WORKSPACE_CONFIG_FILE} already exists. Overwrite?`,\n default: false,\n });\n if (!overwrite) {\n console.log(chalk.gray(\" Cancelled.\"));\n return;\n }\n }\n\n console.log(chalk.blue(\"\\n─── Workspace Setup ────────────────────────────\"));\n\n const workspaceName = await input({\n message: \"Workspace name:\",\n validate: (v) => v.trim().length > 0 || \"Name cannot be empty\",\n });\n\n const repos: RepoConfig[] = [];\n\n // ── Auto-scan option ──────────────────────────────────────────────────────\n const useAutoScan = await confirm({\n message: \"Auto-scan sibling directories for repos?\",\n default: true,\n });\n\n if (useAutoScan) {\n const workspaceLoader = new WorkspaceLoader(currentDir);\n const detected = await workspaceLoader.autoDetect();\n\n if (detected.length === 0) {\n console.log(chalk.yellow(\" No recognizable repos found in sibling directories.\"));\n } else {\n console.log(chalk.cyan(\"\\n Detected repos:\"));\n for (const r of detected) {\n console.log(chalk.gray(` - ${r.name}: ${r.role} (${r.type}) at ${r.path}`));\n }\n\n const keepAll = await confirm({\n message: `Include all ${detected.length} detected repo(s)?`,\n default: true,\n });\n\n if (keepAll) {\n repos.push(...detected);\n } else {\n // Let user cherry-pick\n for (const r of detected) {\n const keep = await confirm({\n message: `Include \"${r.name}\" (${r.role}, ${r.type})?`,\n default: true,\n });\n if (keep) repos.push(r);\n }\n }\n console.log(chalk.green(` ✔ ${repos.length} repo(s) added from auto-scan.`));\n }\n }\n\n // ── Manual add (always offered after auto-scan) ───────────────────────────\n const repoTypeChoices = [\n { name: \"node-express (Node.js/Express backend)\", value: \"node-express\" },\n { name: \"node-koa (Node.js/Koa backend)\", value: \"node-koa\" },\n { name: \"go (Go backend)\", value: \"go\" },\n { name: \"python (Python backend)\", value: \"python\" },\n { name: \"java (Java/Spring backend)\", value: \"java\" },\n { name: \"rust (Rust backend)\", value: \"rust\" },\n { name: \"php (PHP/Lumen/Laravel backend)\", value: \"php\" },\n { name: \"react (React frontend)\", value: \"react\" },\n { name: \"next (Next.js)\", value: \"next\" },\n { name: \"vue (Vue frontend)\", value: \"vue\" },\n { name: \"react-native (React Native mobile)\", value: \"react-native\" },\n { name: \"unknown\", value: \"unknown\" },\n ];\n\n let addMore = await confirm({\n message: repos.length > 0 ? \"Manually add more repos?\" : \"Add repos manually?\",\n default: repos.length === 0,\n });\n\n while (addMore) {\n console.log(chalk.cyan(`\\n Adding repo #${repos.length + 1}`));\n\n const repoName = await input({\n message: \"Repo name (e.g. api, web, app):\",\n validate: (v) => {\n if (!v.trim()) return \"Name cannot be empty\";\n if (repos.some((r) => r.name === v.trim())) return \"Name already used\";\n return true;\n },\n });\n\n const repoPath = await input({\n message: `Relative path to \"${repoName}\" from here (default: ./${repoName}):`,\n default: `./${repoName}`,\n });\n\n // Try to auto-detect type\n const absPath = path.resolve(currentDir, repoPath);\n let detectedType = \"unknown\";\n let detectedRole = \"shared\";\n\n if (await fs.pathExists(absPath)) {\n const { type, role } = await detectRepoType(absPath);\n detectedType = type;\n detectedRole = role;\n console.log(chalk.gray(` Auto-detected: type=${type}, role=${role}`));\n } else {\n console.log(chalk.yellow(` Path \"${absPath}\" not found — type/role will be manual.`));\n }\n\n const repoType = await select({\n message: `Repo type for \"${repoName}\":`,\n choices: repoTypeChoices,\n default: detectedType,\n });\n\n const repoRole = await select({\n message: `Repo role for \"${repoName}\":`,\n choices: [\n { name: \"backend\", value: \"backend\" },\n { name: \"frontend\", value: \"frontend\" },\n { name: \"mobile\", value: \"mobile\" },\n { name: \"shared\", value: \"shared\" },\n ],\n default: detectedRole,\n });\n\n repos.push({\n name: repoName,\n path: repoPath,\n type: repoType as RepoConfig[\"type\"],\n role: repoRole as RepoConfig[\"role\"],\n });\n\n console.log(chalk.green(` ✔ Added: ${repoName} (${repoRole}, ${repoType})`));\n\n addMore = await confirm({\n message: \"Add another repo?\",\n default: false,\n });\n }\n\n const workspaceConfig: WorkspaceConfig = { name: workspaceName, repos };\n\n // Show summary\n console.log(chalk.cyan(\"\\n Workspace summary:\"));\n console.log(chalk.gray(` Name: ${workspaceName}`));\n for (const r of repos) {\n console.log(chalk.gray(` - ${r.name}: ${r.role} (${r.type}) at ${r.path}`));\n }\n\n const ok = await confirm({ message: `Save to ${WORKSPACE_CONFIG_FILE}?`, default: true });\n if (!ok) {\n console.log(chalk.gray(\" Cancelled.\"));\n return;\n }\n\n const loader = new WorkspaceLoader(currentDir);\n const saved = await loader.save(workspaceConfig);\n console.log(chalk.green(`\\n ✔ Workspace saved: ${saved}`));\n console.log(chalk.gray(` Run \\`ai-spec create \"your feature\"\\` — workspace mode will activate automatically.`));\n });\n\n// workspace status\nworkspaceCmd\n .command(\"status\")\n .description(\"Show current workspace configuration\")\n .action(async () => {\n const currentDir = process.cwd();\n const loader = new WorkspaceLoader(currentDir);\n const config = await loader.load();\n\n if (!config) {\n console.log(chalk.yellow(`No ${WORKSPACE_CONFIG_FILE} found in ${currentDir}`));\n console.log(chalk.gray(\" Run `ai-spec workspace init` to create one.\"));\n return;\n }\n\n console.log(chalk.bold(`\\nWorkspace: ${config.name}`));\n console.log(chalk.gray(` Config: ${path.join(currentDir, WORKSPACE_CONFIG_FILE)}`));\n console.log(chalk.gray(` Repos (${config.repos.length}):\\n`));\n\n for (const repo of config.repos) {\n const absPath = loader.resolveAbsPath(repo);\n const exists = await fs.pathExists(absPath);\n const status = exists ? chalk.green(\"found\") : chalk.red(\"not found\");\n\n console.log(\n ` ${chalk.bold(repo.name.padEnd(12))} ${repo.role.padEnd(10)} ${repo.type.padEnd(16)} ${status}`\n );\n console.log(chalk.gray(` path: ${absPath}`));\n if (repo.constitution) {\n console.log(chalk.green(` constitution: found`));\n }\n }\n });\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Command: update — Incremental spec + code update pipeline\n// ═══════════════════════════════════════════════════════════════════════════════\n\nprogram\n .command(\"update\")\n .description(\"Update an existing spec with a change request, re-extract DSL, and identify affected files\")\n .argument(\"[change]\", \"Change description (prompted if omitted)\")\n .option(\"--provider <name>\", `AI provider (${SUPPORTED_PROVIDERS.join(\"|\")})`, undefined)\n .option(\"--model <name>\", \"Model name\")\n .option(\"-k, --key <apiKey>\", \"API key\")\n .option(\"--spec <path>\", \"Path to the existing spec file (auto-detected if omitted)\")\n .option(\"--codegen\", \"Regenerate affected files automatically after updating spec\")\n .option(\"--codegen-provider <name>\", \"Provider for code generation\")\n .option(\"--codegen-model <name>\", \"Model for code generation\")\n .option(\"--codegen-key <key>\", \"API key for code generation\")\n .option(\"--skip-affected\", \"Skip identifying affected files\")\n .action(async (change: string | undefined, opts) => {\n const currentDir = process.cwd();\n const config = await loadConfig(currentDir);\n\n // ── Resolve change ────────────────────────────────────────────────────────\n if (!change) {\n change = await input({\n message: \"Describe the change you want to make:\",\n validate: (v) => v.trim().length > 0 || \"Change description cannot be empty\",\n });\n }\n\n // ── Resolve provider ──────────────────────────────────────────────────────\n const providerName = opts.provider || config.provider || \"gemini\";\n const modelName = opts.model || config.model || DEFAULT_MODELS[providerName];\n const apiKey = await resolveApiKey(providerName, opts.key);\n const provider = createProvider(providerName, apiKey, modelName);\n\n console.log(chalk.blue(\"\\n─── ai-spec update ─────────────────────────────\"));\n console.log(chalk.gray(` Provider: ${providerName}/${modelName}`));\n\n // ── Find existing spec ────────────────────────────────────────────────────\n let specPath: string | null = opts.spec ?? null;\n if (!specPath) {\n const specsDir = path.join(currentDir, \"specs\");\n const latest = await SpecUpdater.findLatestSpec(specsDir);\n if (!latest) {\n console.error(chalk.red(\" No spec files found in specs/. Run `ai-spec create` first or use --spec <path>.\"));\n process.exit(1);\n }\n specPath = latest.filePath;\n console.log(chalk.gray(` Using spec: ${path.relative(currentDir, specPath)} (v${latest.version})`));\n }\n\n // ── Load context ──────────────────────────────────────────────────────────\n console.log(chalk.gray(\" Loading project context...\"));\n const loader = new ContextLoader(currentDir);\n const context = await loader.loadProjectContext();\n\n // ── Detect repo type ──────────────────────────────────────────────────────\n const { detectRepoType: _detectRepoType } = await import(\"../core/workspace-loader\");\n const { type: repoType } = await _detectRepoType(currentDir);\n\n // ── Run update ────────────────────────────────────────────────────────────\n const updater = new SpecUpdater(provider);\n let result;\n try {\n result = await updater.update(change!, specPath, currentDir, context, {\n skipAffectedFiles: opts.skipAffected,\n repoType,\n });\n } catch (err) {\n console.error(chalk.red(` Update failed: ${(err as Error).message}`));\n process.exit(1);\n }\n\n console.log(chalk.green(`\\n ✔ Spec updated → v${result.newVersion}: ${path.relative(currentDir, result.newSpecPath)}`));\n if (result.newDslPath) {\n console.log(chalk.green(` ✔ DSL updated: ${path.relative(currentDir, result.newDslPath)}`));\n }\n\n // ── Show affected files ───────────────────────────────────────────────────\n if (result.affectedFiles.length > 0) {\n console.log(chalk.cyan(\"\\n Affected files:\"));\n for (const f of result.affectedFiles) {\n const icon = f.action === \"create\" ? chalk.green(\"+\") : chalk.yellow(\"~\");\n console.log(` ${icon} ${f.file}: ${chalk.gray(f.description)}`);\n }\n }\n\n // ── Optional: regenerate affected files ───────────────────────────────────\n if (opts.codegen && result.affectedFiles.length > 0) {\n const codegenProviderName = opts.codegenProvider || config.codegenProvider || providerName;\n const codegenModelName = opts.codegenModel || config.codegenModel || DEFAULT_MODELS[codegenProviderName];\n const codegenApiKey = opts.codegenKey ?? (codegenProviderName === providerName ? apiKey : await resolveApiKey(codegenProviderName, opts.codegenKey));\n const codegenProvider = createProvider(codegenProviderName, codegenApiKey, codegenModelName);\n\n console.log(chalk.blue(\"\\n Regenerating affected files...\"));\n const codeGenerator = new CodeGenerator(codegenProvider, \"api\");\n\n const specContent = await fs.readFile(result.newSpecPath, \"utf-8\");\n const constitutionSection = context.constitution\n ? `\\n=== Project Constitution (MUST follow) ===\\n${context.constitution.slice(0, 2000)}\\n`\n : \"\";\n const dslSection = result.updatedDsl\n ? `\\n=== DSL Context ===\\n${JSON.stringify(result.updatedDsl, null, 2).slice(0, 3000)}\\n`\n : \"\";\n\n for (const affected of result.affectedFiles) {\n const fullPath = path.join(currentDir, affected.file);\n let existing = \"\";\n try { existing = await fs.readFile(fullPath, \"utf-8\"); } catch { /* new file */ }\n\n const codePrompt = `Apply this change to the file.\n\nChange: ${change}\nFile: ${affected.file}\nPurpose: ${affected.description}\n\n=== Feature Spec (updated) ===\n${specContent}\n${constitutionSection}${dslSection}\n=== ${existing ? \"Current File (return the FULL updated content)\" : \"New File\"} ===\n${existing || \"Create from scratch.\"}`;\n\n process.stdout.write(` ${existing ? chalk.yellow(\"~\") : chalk.green(\"+\")} ${affected.file}... `);\n try {\n const { getCodeGenSystemPrompt: _getPrompt } = await import(\"../prompts/codegen.prompt\");\n const raw = await codegenProvider.generate(codePrompt, _getPrompt(repoType));\n const content = raw.replace(/^```\\w*\\n?/gm, \"\").replace(/\\n?```$/gm, \"\").trim();\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, content, \"utf-8\");\n console.log(chalk.green(\"✔\"));\n } catch (err) {\n console.log(chalk.red(`✘ ${(err as Error).message}`));\n }\n }\n }\n\n // ── Hints ─────────────────────────────────────────────────────────────────\n if (!opts.codegen && result.affectedFiles.length > 0) {\n console.log(chalk.blue(\"\\n Next steps:\"));\n console.log(chalk.gray(` • Re-run with --codegen to regenerate affected files automatically`));\n console.log(chalk.gray(` • Or update files manually based on the affected files list above`));\n console.log(chalk.gray(` • Run \\`ai-spec mock\\` to refresh the mock server with the new DSL`));\n }\n });\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Command: export — Export DSL to OpenAPI / other formats\n// ═══════════════════════════════════════════════════════════════════════════════\n\nprogram\n .command(\"export\")\n .description(\"Export the latest DSL to OpenAPI 3.1.0 (YAML or JSON)\")\n .option(\"--openapi\", \"Export as OpenAPI 3.1.0 (default behaviour)\")\n .option(\"--format <fmt>\", \"Output format: yaml | json (default: yaml)\", \"yaml\")\n .option(\"--output <path>\", \"Output file path (default: openapi.yaml)\")\n .option(\"--server <url>\", \"API server URL in the OpenAPI document (default: http://localhost:3000)\")\n .option(\"--dsl <path>\", \"Path to a specific .dsl.json file (auto-detected if omitted)\")\n .action(async (opts) => {\n const currentDir = process.cwd();\n\n // ── Find DSL ──────────────────────────────────────────────────────────────\n let dslPath: string | null = opts.dsl ?? null;\n if (!dslPath) {\n dslPath = await findLatestDslFile(currentDir);\n if (!dslPath) {\n console.error(chalk.red(\" No .dsl.json file found. Run `ai-spec create` first or use --dsl <path>.\"));\n process.exit(1);\n }\n console.log(chalk.gray(` Using DSL: ${path.relative(currentDir, dslPath)}`));\n }\n\n let dsl: SpecDSL;\n try {\n dsl = await fs.readJson(dslPath);\n } catch (err) {\n console.error(chalk.red(` Failed to read DSL: ${(err as Error).message}`));\n process.exit(1);\n }\n\n // ── Export ────────────────────────────────────────────────────────────────\n console.log(chalk.blue(\"\\n─── ai-spec export ─────────────────────────────\"));\n\n const format = (opts.format === \"json\" ? \"json\" : \"yaml\") as \"yaml\" | \"json\";\n const serverUrl = opts.server || \"http://localhost:3000\";\n\n try {\n const outputPath = await exportOpenApi(dsl, currentDir, {\n format,\n serverUrl,\n outputPath: opts.output,\n });\n const rel = path.relative(currentDir, outputPath);\n console.log(chalk.green(` ✔ OpenAPI ${format.toUpperCase()} exported: ${rel}`));\n console.log(chalk.gray(` Feature : ${dsl.feature.title}`));\n console.log(chalk.gray(` Endpoints: ${dsl.endpoints.length}`));\n console.log(chalk.gray(` Models : ${dsl.models.length}`));\n console.log(chalk.gray(` Server : ${serverUrl}`));\n console.log(chalk.blue(\"\\n Next steps:\"));\n console.log(chalk.gray(` • Import ${rel} into Postman / Insomnia / Swagger UI`));\n console.log(chalk.gray(` • Use openapi-generator to generate client SDKs`));\n } catch (err) {\n console.error(chalk.red(` Export failed: ${(err as Error).message}`));\n process.exit(1);\n }\n });\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Command: mock — Generate mock server, proxy config, and MSW handlers from DSL\n// ═══════════════════════════════════════════════════════════════════════════════\n\nprogram\n .command(\"mock\")\n .description(\"Generate a standalone mock server + proxy config from the latest DSL\")\n .option(\"--port <n>\", \"Mock server port (default: 3001)\", \"3001\")\n .option(\"--msw\", \"Also generate MSW (Mock Service Worker) handlers at src/mocks/\")\n .option(\"--proxy\", \"Also generate frontend proxy config snippet\")\n .option(\"--dsl <path>\", \"Path to a specific .dsl.json file (auto-detected if omitted)\")\n .option(\n \"--workspace\",\n \"Generate mock assets for all backend repos in the workspace\"\n )\n .action(async (opts) => {\n const currentDir = process.cwd();\n const port = parseInt(opts.port, 10) || 3001;\n\n console.log(chalk.blue(\"\\n─── ai-spec mock ───────────────────────────────\"));\n\n // ── Workspace mode ────────────────────────────────────────────────────────\n if (opts.workspace) {\n const workspaceLoader = new WorkspaceLoader(currentDir);\n const workspaceConfig = await workspaceLoader.load();\n if (!workspaceConfig) {\n console.error(chalk.red(` No ${WORKSPACE_CONFIG_FILE} found. Run \\`ai-spec workspace init\\` first.`));\n process.exit(1);\n }\n\n const backendRepos = workspaceConfig.repos.filter((r) => r.role === \"backend\");\n if (backendRepos.length === 0) {\n console.log(chalk.yellow(\" No backend repos found in workspace.\"));\n return;\n }\n\n for (const repo of backendRepos) {\n const repoAbsPath = workspaceLoader.resolveAbsPath(repo);\n console.log(chalk.cyan(`\\n Repo: ${repo.name} (${repoAbsPath})`));\n\n const dslFile = await findLatestDslFile(repoAbsPath);\n if (!dslFile) {\n console.log(chalk.yellow(` No DSL file found — skipping.`));\n continue;\n }\n\n const dsl: SpecDSL = await fs.readJson(dslFile);\n const result = await generateMockAssets(dsl, repoAbsPath, {\n port,\n msw: opts.msw,\n proxy: opts.proxy,\n });\n\n for (const f of result.files) {\n console.log(chalk.green(` ✔ ${f.path}`));\n console.log(chalk.gray(` ${f.description}`));\n }\n }\n return;\n }\n\n // ── Single-repo mode ──────────────────────────────────────────────────────\n let dslPath: string | null = opts.dsl ?? null;\n\n if (!dslPath) {\n dslPath = await findLatestDslFile(currentDir);\n if (!dslPath) {\n console.error(\n chalk.red(\n \" No .dsl.json file found in .ai-spec/. Run `ai-spec create` first or use --dsl <path>.\"\n )\n );\n process.exit(1);\n }\n console.log(chalk.gray(` Using DSL: ${path.relative(currentDir, dslPath)}`));\n }\n\n let dsl: SpecDSL;\n try {\n dsl = await fs.readJson(dslPath);\n } catch (err) {\n console.error(chalk.red(` Failed to read DSL file: ${(err as Error).message}`));\n process.exit(1);\n }\n\n const result = await generateMockAssets(dsl, currentDir, {\n port,\n msw: opts.msw,\n proxy: opts.proxy,\n });\n\n console.log(chalk.green(`\\n ✔ Mock assets generated (${result.files.length} file(s)):`));\n for (const f of result.files) {\n console.log(chalk.green(` ${f.path}`));\n console.log(chalk.gray(` ${f.description}`));\n }\n\n console.log(chalk.blue(\"\\n─── Quick start ────────────────────────────────\"));\n console.log(chalk.white(` 1. Install express (if not already):`));\n console.log(chalk.gray(` npm install --save-dev express`));\n console.log(chalk.white(` 2. Start mock server:`));\n console.log(chalk.gray(` node mock/server.js`));\n console.log(chalk.white(` 3. Configure your frontend to proxy API calls to:`));\n console.log(chalk.gray(` http://localhost:${port}`));\n if (opts.proxy) {\n console.log(chalk.gray(` (See the generated proxy config file for framework-specific instructions)`));\n }\n if (opts.msw) {\n console.log(chalk.white(` 4. MSW: import and start the worker in your app entry:`));\n console.log(chalk.gray(` import { worker } from './mocks/browser';`));\n console.log(chalk.gray(` if (process.env.NODE_ENV === 'development') worker.start();`));\n }\n });\n\n// Show welcome screen when invoked with no arguments\nif (process.argv.length <= 2) {\n (async () => {\n const currentDir = process.cwd();\n const config = await loadConfig(currentDir);\n await printWelcome(currentDir, config);\n })();\n} else {\n program.parse();\n}\n","import { GoogleGenerativeAI } from \"@google/generative-ai\";\nimport Anthropic from \"@anthropic-ai/sdk\";\nimport OpenAI from \"openai\";\nimport axios from \"axios\";\nimport { ProxyAgent } from \"undici\";\nimport { specPrompt } from \"../prompts/spec.prompt\";\nimport { ProjectContext } from \"./context-loader\";\n\n// ─── Proxy Helper ─────────────────────────────────────────────────────────────\n// 仅用于 Gemini:其他 SDK(Anthropic / OpenAI)会自动读取 HTTPS_PROXY。\n// Gemini SDK 使用 Node.js 原生 fetch(undici),不会自动读代理环境变量,\n// 需要手动创建 ProxyAgent 并通过 fetchOptions 注入。\n// 这是 in-process 级别的配置,完全不影响 execSync 启动的子进程(如 claude CLI)。\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction geminiRequestOptions(): any {\n const proxyUrl =\n process.env.GEMINI_PROXY ||\n process.env.HTTPS_PROXY ||\n process.env.https_proxy ||\n process.env.HTTP_PROXY ||\n process.env.http_proxy;\n\n if (!proxyUrl) return undefined;\n // fetchOptions.dispatcher は型定義(v0.21)に未記載だが runtime では動作する\n return { fetchOptions: { dispatcher: new ProxyAgent(proxyUrl) } };\n}\n\n// ─── Provider Interface ────────────────────────────────────────────────────────\n\nexport interface AIProvider {\n generate(prompt: string, systemInstruction?: string): Promise<string>;\n readonly providerName: string;\n readonly modelName: string;\n}\n\n// ─── Provider Catalog ─────────────────────────────────────────────────────────\n// Single source of truth for all supported providers and their models.\n\nexport interface ProviderMeta {\n /** Human-readable display name */\n displayName: string;\n /** Short description shown in model picker */\n description: string;\n /** Available models (first is the default) */\n models: string[];\n /** Environment variable name for the API key */\n envKey: string;\n /**\n * Base URL for OpenAI-compatible providers.\n * Undefined means the provider has its own SDK (Gemini / Claude).\n */\n baseURL?: string;\n /**\n * Role to use for system instructions.\n * OpenAI o1/o3 use \"developer\" instead of \"system\".\n * Default: \"system\"\n */\n systemRole?: \"system\" | \"developer\";\n /**\n * Extra body params injected into every chat completion request.\n * e.g. Qwen3 needs { enable_thinking: false } to suppress CoT noise.\n */\n extraBody?: Record<string, unknown>;\n}\n\nexport const PROVIDER_CATALOG: Record<string, ProviderMeta> = {\n // ── International ──────────────────────────────────────────────────────────\n mimo: {\n displayName: \"MiMo (Xiaomi)\",\n description: \"小米 MiMo — mimo-v2-pro (Anthropic-compatible API)\",\n models: [\"mimo-v2-pro\"],\n envKey: \"MIMO_API_KEY\",\n // baseURL not used — MiMo has a dedicated provider class\n },\n gemini: {\n displayName: \"Google Gemini\",\n description: \"Google AI Studio — Gemini 2.5 / 2.0 series\",\n models: [\n \"gemini-2.5-pro\",\n \"gemini-2.5-flash\",\n \"gemini-2.0-flash\",\n \"gemini-2.0-flash-lite\",\n \"gemini-1.5-pro\",\n \"gemini-1.5-flash\",\n ],\n envKey: \"GEMINI_API_KEY\",\n },\n claude: {\n displayName: \"Anthropic Claude\",\n description: \"Anthropic — Claude 4.x / 3.7 series\",\n models: [\n \"claude-opus-4-6\",\n \"claude-sonnet-4-6\",\n \"claude-haiku-4-5\",\n \"claude-3-7-sonnet-20250219\",\n ],\n envKey: \"ANTHROPIC_API_KEY\",\n },\n openai: {\n displayName: \"OpenAI\",\n description: \"OpenAI — o3 / GPT-4o series\",\n models: [\n \"o3\",\n \"o3-mini\",\n \"o1\",\n \"o1-mini\",\n \"gpt-4o\",\n \"gpt-4o-mini\",\n ],\n envKey: \"OPENAI_API_KEY\",\n baseURL: \"https://api.openai.com/v1\",\n },\n deepseek: {\n displayName: \"DeepSeek\",\n description: \"DeepSeek — V3 (chat) / R1 (reasoning)\",\n models: [\n \"deepseek-chat\", // DeepSeek-V3\n \"deepseek-reasoner\", // DeepSeek-R1\n ],\n envKey: \"DEEPSEEK_API_KEY\",\n baseURL: \"https://api.deepseek.com/v1\",\n },\n\n // ── Chinese Models (OpenAI-compatible) ────────────────────────────────────\n qwen: {\n displayName: \"通义千问 (Qwen)\",\n description: \"阿里云百炼 — Qwen3 / Qwen2.5 series\",\n models: [\n \"qwen3-235b-a22b\", // Qwen3 MoE flagship (supports thinking mode)\n \"qwen3-72b\",\n \"qwen3-32b\",\n \"qwen3-8b\",\n \"qwen-max\",\n \"qwen-max-latest\",\n \"qwen-plus\",\n \"qwen-long\",\n ],\n envKey: \"DASHSCOPE_API_KEY\",\n baseURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n // Qwen3 models enable thinking (CoT) by default, which pollutes structured outputs.\n // Disable it so JSON/Markdown responses stay clean.\n extraBody: { enable_thinking: false },\n },\n glm: {\n displayName: \"智谱 GLM (Zhipu AI)\",\n description: \"智谱 AI — GLM-5 / GLM-4 series + Z1 reasoning\",\n models: [\n \"glm-5\", // GLM-5 flagship (如不可用请确认最新 model ID)\n \"glm-5-flash\",\n \"glm-z1\", // GLM-Z1 reasoning model\n \"glm-z1-flash\",\n \"glm-4-plus\",\n \"glm-4-flash\",\n \"glm-4-long\",\n ],\n envKey: \"ZHIPU_API_KEY\",\n baseURL: \"https://open.bigmodel.cn/api/paas/v4/\",\n },\n minimax: {\n displayName: \"MiniMax\",\n description: \"MiniMax AI — MiniMax-Text-2.7 / Text-01 series\",\n models: [\n \"MiniMax-Text-2.7\", // MiniMax 最新旗舰 (如不可用请确认最新 model ID)\n \"MiniMax-Text-01\",\n \"abab6.5s-chat\",\n ],\n envKey: \"MINIMAX_API_KEY\",\n baseURL: \"https://api.minimax.chat/v1\",\n },\n doubao: {\n displayName: \"豆包 Doubao (ByteDance)\",\n description: \"火山引擎 Ark — Doubao Pro/Lite series\",\n models: [\n \"doubao-pro-256k\",\n \"doubao-pro-128k\",\n \"doubao-pro-32k\",\n \"doubao-lite-128k\",\n \"doubao-lite-32k\",\n ],\n envKey: \"ARK_API_KEY\",\n baseURL: \"https://ark.cn-beijing.volces.com/api/v3\",\n },\n};\n\n// Derived convenience maps (kept for backward compatibility)\nexport const SUPPORTED_PROVIDERS = Object.keys(PROVIDER_CATALOG);\n\nexport const DEFAULT_MODELS: Record<string, string> = Object.fromEntries(\n Object.entries(PROVIDER_CATALOG).map(([k, v]) => [k, v.models[0]])\n);\n\nexport const ENV_KEY_MAP: Record<string, string> = Object.fromEntries(\n Object.entries(PROVIDER_CATALOG).map(([k, v]) => [k, v.envKey])\n);\n\n// ─── Gemini Provider ───────────────────────────────────────────────────────────\n\nexport class GeminiProvider implements AIProvider {\n private genAI: GoogleGenerativeAI;\n readonly providerName = \"gemini\";\n readonly modelName: string;\n\n constructor(apiKey: string, modelName = PROVIDER_CATALOG.gemini.models[0]) {\n this.genAI = new GoogleGenerativeAI(apiKey);\n this.modelName = modelName;\n }\n\n async generate(prompt: string, systemInstruction?: string): Promise<string> {\n const model = this.genAI.getGenerativeModel(\n { model: this.modelName, ...(systemInstruction ? { systemInstruction } : {}) },\n geminiRequestOptions()\n );\n const result = await model.generateContent(prompt);\n return result.response.text();\n }\n}\n\n// ─── Claude Provider ───────────────────────────────────────────────────────────\n\nexport class ClaudeProvider implements AIProvider {\n private client: Anthropic;\n readonly providerName = \"claude\";\n readonly modelName: string;\n\n constructor(apiKey: string, modelName = PROVIDER_CATALOG.claude.models[0]) {\n this.client = new Anthropic({ apiKey });\n this.modelName = modelName;\n }\n\n async generate(prompt: string, systemInstruction?: string): Promise<string> {\n const message = await this.client.messages.create({\n model: this.modelName,\n max_tokens: 8192,\n ...(systemInstruction ? { system: systemInstruction } : {}),\n messages: [{ role: \"user\", content: prompt }],\n });\n const block = message.content[0];\n if (block.type === \"text\") return block.text;\n throw new Error(\"Unexpected response type from Claude API\");\n }\n}\n\n// ─── OpenAI-Compatible Provider ───────────────────────────────────────────────\n// Handles OpenAI, DeepSeek, Qwen, MiniMax, GLM, Doubao — all expose the same API.\n\nexport class OpenAICompatibleProvider implements AIProvider {\n protected client: OpenAI;\n readonly providerName: string;\n readonly modelName: string;\n private systemRole: \"system\" | \"developer\";\n private extraBody?: Record<string, unknown>;\n\n constructor(\n providerName: string,\n apiKey: string,\n modelName: string,\n baseURL?: string,\n systemRole: \"system\" | \"developer\" = \"system\",\n extraBody?: Record<string, unknown>\n ) {\n this.providerName = providerName;\n this.modelName = modelName;\n this.systemRole = systemRole;\n this.extraBody = extraBody;\n this.client = new OpenAI({\n apiKey,\n ...(baseURL ? { baseURL } : {}),\n });\n }\n\n async generate(prompt: string, systemInstruction?: string): Promise<string> {\n const messages: OpenAI.Chat.ChatCompletionMessageParam[] = [];\n\n if (systemInstruction) {\n // o1/o3 require \"developer\" role; gpt-4o/gpt-4-turbo use \"system\"\n // Auto-detect: if model starts with \"o1\" or \"o3\", use developer role\n const isOSeries = /^o[13]/.test(this.modelName);\n const role = isOSeries ? \"developer\" : this.systemRole;\n messages.push({ role, content: systemInstruction } as OpenAI.Chat.ChatCompletionMessageParam);\n }\n messages.push({ role: \"user\", content: prompt });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const completion = await (this.client.chat.completions.create as any)({\n model: this.modelName,\n messages,\n ...(this.extraBody ? { extra_body: this.extraBody } : {}),\n });\n\n return (completion.choices[0].message.content as string) ?? \"\";\n }\n}\n\n// ─── MiMo Provider ─────────────────────────────────────────────────────────────\n// MiMo uses the Anthropic messages format but with a different base URL\n// and a custom \"api-key\" auth header (not \"x-api-key\" / \"Authorization: Bearer\").\n// The Anthropic SDK does not support custom auth headers, so we call the API\n// directly via axios.\n\nexport class MiMoProvider implements AIProvider {\n readonly providerName = \"mimo\";\n readonly modelName: string;\n private apiKey: string;\n private readonly baseUrl = \"https://api.xiaomimimo.com/anthropic/v1/messages\";\n\n constructor(apiKey: string, modelName = PROVIDER_CATALOG.mimo.models[0]) {\n this.apiKey = apiKey;\n this.modelName = modelName;\n }\n\n async generate(prompt: string, systemInstruction?: string): Promise<string> {\n const body: Record<string, unknown> = {\n model: this.modelName,\n max_tokens: 16384,\n messages: [{ role: \"user\", content: [{ type: \"text\", text: prompt }] }],\n top_p: 0.95,\n stream: false,\n temperature: 1.0,\n stop_sequences: null,\n };\n\n if (systemInstruction) {\n body.system = systemInstruction;\n }\n\n const response = await axios.post(this.baseUrl, body, {\n headers: {\n \"api-key\": this.apiKey,\n \"Content-Type\": \"application/json\",\n },\n });\n\n // Response follows Anthropic format: { content: [{ type: \"text\"|\"thinking\", ... }] }\n // MiMo may return a \"thinking\" block before the actual \"text\" block — skip it.\n const data = response.data as { stop_reason?: string; content?: Array<{ type: string; text?: string; thinking?: string }> };\n const blocks = data?.content ?? [];\n\n const textBlock = blocks.find((b) => b.type === \"text\");\n if (textBlock?.text) return textBlock.text;\n\n // If stop_reason is max_tokens, the model was cut off mid-generation (thinking block only)\n if (data?.stop_reason === \"max_tokens\") {\n throw new Error(`MiMo response truncated (max_tokens reached). The prompt may be too long. Try a shorter spec or switch to a model with larger context.`);\n }\n\n throw new Error(`Unexpected MiMo response: ${JSON.stringify(response.data).slice(0, 200)}`);\n }\n}\n\n// ─── Factory ──────────────────────────────────────────────────────────────────\n\nexport function createProvider(\n providerName: string,\n apiKey: string,\n modelName?: string\n): AIProvider {\n const meta = PROVIDER_CATALOG[providerName];\n if (!meta) {\n throw new Error(\n `Unknown provider: \"${providerName}\". Valid options: ${SUPPORTED_PROVIDERS.join(\", \")}`\n );\n }\n\n const model = modelName || meta.models[0];\n\n switch (providerName) {\n case \"gemini\":\n return new GeminiProvider(apiKey, model);\n case \"claude\":\n return new ClaudeProvider(apiKey, model);\n case \"mimo\":\n return new MiMoProvider(apiKey, model);\n // All OpenAI-compatible providers: openai, deepseek, qwen, glm, minimax, doubao\n default:\n return new OpenAICompatibleProvider(\n providerName,\n apiKey,\n model,\n meta.baseURL,\n meta.systemRole ?? \"system\",\n meta.extraBody\n );\n }\n}\n\n// ─── Spec Generator ───────────────────────────────────────────────────────────\n\nexport class SpecGenerator {\n constructor(private provider: AIProvider) {}\n\n async generateSpec(idea: string, context?: ProjectContext): Promise<string> {\n const parts: string[] = [idea];\n\n if (context) {\n // Constitution is highest priority — put it first so the AI respects it\n if (context.constitution) {\n parts.push(\n `\\n\\n=== 项目宪法 (Project Constitution — MUST follow these rules) ===\\n${context.constitution}`\n );\n }\n\n parts.push(`\\n\\n=== 项目上下文 (Project Context) ===`);\n if (context.techStack.length > 0) {\n parts.push(`技术栈: ${context.techStack.join(\", \")}`);\n }\n if (context.dependencies.length > 0) {\n parts.push(`主要依赖: ${context.dependencies.slice(0, 25).join(\", \")}`);\n }\n if (context.apiStructure.length > 0) {\n parts.push(\n `\\n现有 API 文件:\\n${context.apiStructure\n .slice(0, 10)\n .map((f) => ` - ${f}`)\n .join(\"\\n\")}`\n );\n }\n if (context.routeSummary) {\n parts.push(`\\n路由结构(摘要):\\n${context.routeSummary}`);\n }\n if (context.schema) {\n parts.push(`\\n数据库 Schema (Prisma):\\n${context.schema.slice(0, 3000)}`);\n }\n }\n\n return this.provider.generate(parts.join(\"\\n\"), specPrompt);\n }\n}\n","export const specPrompt = `You are an expert Software Architect. Your task is to convert the user's raw feature idea into a structured, detailed, and immediately actionable Markdown specification.\n\nThe spec MUST be written in Chinese (中文). Be comprehensive but focused — every section should contain practical, project-specific information derived from the provided project context.\n\nUse the EXACT following template structure:\n\n---\n\n# Feature Spec: {功能名称}\n\n## 1. 功能概述 (Overview)\n用 2-3 句话简洁说明这个功能是什么,以及它解决的核心问题。\n\n## 2. 背景与动机 (Background)\n- 当前存在什么问题或缺失?\n- 为什么现在需要构建这个功能?\n- 对用户/业务的价值是什么?\n\n## 3. 用户故事 (User Stories)\n- 作为 **[用户角色]**,我希望 **[完成某操作]**,以便 **[获得某价值]**\n(列出 2-4 个核心用户故事,覆盖主要使用场景)\n\n## 4. 功能需求 (Functional Requirements)\n\n### 4.1 核心功能\n- [ ] 需求 1:详细描述期望行为\n- [ ] 需求 2:详细描述期望行为\n\n### 4.2 边界条件与错误处理\n- 输入验证规则(字段类型、长度、格式要求)\n- 错误场景及对应的处理策略\n- 权限控制要求(哪些角色可以访问)\n\n## 5. API 设计 (API Design)\n\n### 接口列表\n| Method | Endpoint | Auth Required | Description |\n|--------|----------|:-------------:|-------------|\n| POST | /api/... | ✅ | 创建... |\n| GET | /api/... | ✅ | 获取... |\n\n### 请求/响应示例\n\n**[接口名称]**\n\n\\`\\`\\`\nPOST /api/example\nAuthorization: Bearer {token}\nContent-Type: application/json\n\\`\\`\\`\n\n请求体:\n\\`\\`\\`json\n{\n \"field1\": \"string\",\n \"field2\": 0\n}\n\\`\\`\\`\n\n成功响应 (200):\n\\`\\`\\`json\n{\n \"code\": 0,\n \"message\": \"success\",\n \"data\": {}\n}\n\\`\\`\\`\n\n错误响应:\n\\`\\`\\`json\n{\n \"code\": 40001,\n \"message\": \"错误描述\"\n}\n\\`\\`\\`\n\n## 6. 数据模型 (Data Model)\n描述需要新增或修改的数据库表/字段(使用 Prisma Schema 格式)。\n\n\\`\\`\\`prisma\nmodel ExampleModel {\n id Int @id @default(autoincrement())\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n}\n\\`\\`\\`\n\n## 7. 非功能性需求 (Non-functional Requirements)\n- **性能**: 接口响应时间要求,并发量预估\n- **安全**: 认证授权机制,敏感数据的处理方式\n- **可靠性**: 幂等性要求,重试策略\n- **可维护性**: 日志记录要求,监控指标\n\n## 8. 实施要点 (Implementation Notes)\n- **集成点**: 需要与哪些现有模块、服务或外部 API 交互\n- **实施顺序**: 建议的开发步骤(例:数据模型 → 服务层 → 控制器 → 路由 → 测试)\n- **技术注意事项**: 潜在的技术难点,推荐的库或实现方案\n- **测试要点**: 关键的单元测试和集成测试场景\n\n---\n\n根据用户的想法和项目上下文生成上述完整 Spec。确保 API 设计与现有项目的路由风格、错误码规范保持一致,数据模型与现有 Prisma Schema 协调。`;\n","import * as fs from \"fs-extra\";\nimport * as path from \"path\";\nimport { glob } from \"glob\";\nimport { loadGlobalConstitution, mergeConstitutions } from \"./global-constitution\";\n\nexport interface SharedConfigFile {\n /** Relative path from project root */\n path: string;\n /** First 80 lines of the file */\n preview: string;\n /** Inferred category */\n category: \"i18n\" | \"constants\" | \"enums\" | \"config\" | \"route-index\" | \"store-index\" | \"other\";\n}\n\nexport interface ProjectContext {\n techStack: string[];\n fileStructure: string[];\n dependencies: string[];\n apiStructure: string[];\n schema?: string;\n routeSummary?: string;\n /**\n * Effective constitution injected into prompts.\n * If a global constitution was found it is merged in here (global first, project overrides).\n */\n constitution?: string;\n /** Extracted error handling patterns from source */\n errorPatterns?: string;\n /**\n * Singleton/append-only config files that MUST be modified in-place,\n * never recreated as a new parallel file (i18n, constants, enums, config indices, etc.)\n */\n sharedConfigFiles?: SharedConfigFile[];\n}\n\n/**\n * Single source of truth for what counts as a \"frontend\" project.\n * Import this constant (and isFrontendDeps) everywhere instead of\n * repeating the inline array — one place to add Svelte, Solid, Qwik, etc.\n */\nexport const FRONTEND_FRAMEWORKS = [\"react\", \"vue\", \"next\", \"nuxt\", \"react-native\", \"expo\", \"svelte\", \"solid-js\", \"qwik\"] as const;\n\n/**\n * Returns true if any of the given dependency keys is a recognised frontend framework.\n * Works on the raw key list from package.json / context.dependencies.\n */\nexport function isFrontendDeps(deps: string[]): boolean {\n return deps.some((d) => (FRONTEND_FRAMEWORKS as readonly string[]).includes(d));\n}\n\nconst STACK_MAP: Record<string, string> = {\n react: \"React\",\n vue: \"Vue\",\n \"next\": \"Next.js\",\n \"nuxt\": \"Nuxt.js\",\n express: \"Express\",\n koa: \"Koa\",\n fastify: \"Fastify\",\n \"@nestjs/core\": \"NestJS\",\n prisma: \"Prisma\",\n mongoose: \"Mongoose\",\n typeorm: \"TypeORM\",\n sequelize: \"Sequelize\",\n tailwindcss: \"Tailwind CSS\",\n typescript: \"TypeScript\",\n \"@supabase/supabase-js\": \"Supabase\",\n \"socket.io\": \"Socket.IO\",\n redis: \"Redis\",\n bull: \"Bull (Queue)\",\n \"@prisma/client\": \"Prisma\",\n};\n\nexport class ContextLoader {\n constructor(private projectRoot: string) {}\n\n async loadProjectContext(): Promise<ProjectContext> {\n const context: ProjectContext = {\n techStack: [],\n fileStructure: [],\n dependencies: [],\n apiStructure: [],\n };\n\n try {\n // PHP projects use composer.json instead of package.json\n const isPhp = await fs.pathExists(path.join(this.projectRoot, \"composer.json\"));\n const isJava =\n (await fs.pathExists(path.join(this.projectRoot, \"pom.xml\"))) ||\n (await fs.pathExists(path.join(this.projectRoot, \"build.gradle\"))) ||\n (await fs.pathExists(path.join(this.projectRoot, \"build.gradle.kts\")));\n if (isPhp) {\n await this.loadComposerJson(context);\n await this.loadPhpRoutes(context);\n } else if (isJava) {\n await this.loadMavenOrGradle(context);\n await this.loadJavaApiStructure(context);\n } else {\n await this.loadPackageJson(context);\n await this.loadPrismaSchema(context);\n }\n await this.loadFileStructure(context);\n await this.loadApiStructure(context);\n await this.loadConstitution(context);\n await this.loadErrorPatterns(context);\n await this.loadSharedConfigFiles(context);\n } catch (e) {\n console.warn(\"Warning: Could not load full project context.\", e);\n }\n\n return context;\n }\n\n /** Load PHP project context from composer.json */\n private async loadComposerJson(context: ProjectContext): Promise<void> {\n const composerPath = path.join(this.projectRoot, \"composer.json\");\n let composer: Record<string, unknown> = {};\n try {\n composer = await fs.readJson(composerPath);\n } catch {\n return;\n }\n\n const require = (composer.require as Record<string, string>) ?? {};\n const requireDev = (composer[\"require-dev\"] as Record<string, string>) ?? {};\n context.dependencies = [...Object.keys(require), ...Object.keys(requireDev)];\n\n const stack = new Set<string>();\n stack.add(\"PHP\");\n if (require[\"laravel/lumen-framework\"]) stack.add(\"Lumen\");\n if (require[\"laravel/framework\"]) stack.add(\"Laravel\");\n if (require[\"symfony/framework-bundle\"]) stack.add(\"Symfony\");\n if (require[\"slim/slim\"]) stack.add(\"Slim\");\n if (require[\"illuminate/database\"] || require[\"laravel/lumen-framework\"]) stack.add(\"Eloquent ORM\");\n if (require[\"doctrine/orm\"]) stack.add(\"Doctrine ORM\");\n if (require[\"tymon/jwt-auth\"]) stack.add(\"JWT Auth\");\n if (require[\"league/fractal\"] || require[\"spatie/laravel-fractal\"]) stack.add(\"Fractal (Transformers)\");\n\n // PHP version\n const phpVersion = require[\"php\"];\n if (phpVersion) stack.add(`PHP ${phpVersion}`);\n\n context.techStack = Array.from(stack);\n }\n\n /**\n * Load PHP route files (routes/api.php, routes/web.php) as routeSummary.\n * Lumen uses these files to register API endpoints.\n */\n private async loadPhpRoutes(context: ProjectContext): Promise<void> {\n const routeFiles = [\"routes/api.php\", \"routes/web.php\"];\n const parts: string[] = [];\n\n for (const rel of routeFiles) {\n const fullPath = path.join(this.projectRoot, rel);\n if (!(await fs.pathExists(fullPath))) continue;\n try {\n const content = await fs.readFile(fullPath, \"utf-8\");\n parts.push(`// ${rel}\\n${content.slice(0, 1500)}`);\n } catch {\n // skip\n }\n }\n\n if (parts.length > 0) {\n context.routeSummary = parts.join(\"\\n\\n\");\n }\n\n // Also scan app/Http/Controllers for API structure\n const controllerFiles = await glob(\"app/Http/Controllers/**/*.php\", {\n cwd: this.projectRoot,\n ignore: [\"vendor/**\"],\n });\n context.apiStructure = controllerFiles.slice(0, 20);\n }\n\n /** Load Java project context from pom.xml or build.gradle */\n private async loadMavenOrGradle(context: ProjectContext): Promise<void> {\n const pomPath = path.join(this.projectRoot, \"pom.xml\");\n const gradlePath = path.join(this.projectRoot, \"build.gradle\");\n const gradleKtsPath = path.join(this.projectRoot, \"build.gradle.kts\");\n\n const stack = new Set<string>([\"Java\"]);\n const deps: string[] = [];\n\n if (await fs.pathExists(pomPath)) {\n try {\n const xml = await fs.readFile(pomPath, \"utf-8\");\n // Extract all <artifactId> values (skip the root artifact itself)\n const artifactIds = [...xml.matchAll(/<artifactId>([^<]+)<\\/artifactId>/g)]\n .map((m) => m[1].trim())\n .filter((id, i) => i > 0); // skip first = the project itself\n deps.push(...artifactIds);\n\n // Detect Java version\n const javaVerMatch = xml.match(/<maven\\.compiler\\.source>(\\d+)<\\/maven\\.compiler\\.source>/);\n if (javaVerMatch) stack.add(`Java ${javaVerMatch[1]}`);\n\n // Detect common frameworks\n if (deps.some((d) => d.includes(\"spring-boot\"))) stack.add(\"Spring Boot\");\n if (deps.some((d) => d.includes(\"spring-web\") || d.includes(\"spring-webmvc\"))) stack.add(\"Spring MVC\");\n if (deps.some((d) => d.includes(\"mybatis\"))) stack.add(\"MyBatis\");\n if (deps.some((d) => d.includes(\"hibernate\") || d.includes(\"spring-data-jpa\"))) stack.add(\"JPA/Hibernate\");\n if (deps.some((d) => d.includes(\"dubbo\"))) stack.add(\"Dubbo\");\n if (deps.some((d) => d.includes(\"rocketmq\"))) stack.add(\"RocketMQ\");\n if (deps.some((d) => d.includes(\"kafka\"))) stack.add(\"Kafka\");\n if (deps.some((d) => d.includes(\"redis\"))) stack.add(\"Redis\");\n if (deps.some((d) => d.includes(\"lombok\"))) stack.add(\"Lombok\");\n if (deps.some((d) => d.includes(\"feign\") || d.includes(\"openfeign\"))) stack.add(\"OpenFeign\");\n if (deps.some((d) => d.includes(\"nacos\"))) stack.add(\"Nacos\");\n if (deps.some((d) => d.includes(\"sentinel\"))) stack.add(\"Sentinel\");\n } catch { /* ignore */ }\n } else {\n // Gradle — just mark as Gradle project; deep dep parsing is complex\n const gradleFile = (await fs.pathExists(gradleKtsPath)) ? gradleKtsPath : gradlePath;\n try {\n const content = await fs.readFile(gradleFile, \"utf-8\");\n // Extract simple dependency strings like: implementation 'group:artifact:version'\n const depMatches = [...content.matchAll(/['\"]([a-zA-Z0-9._-]+):([a-zA-Z0-9._-]+):[^'\"]+['\"]/g)];\n deps.push(...depMatches.map((m) => m[2]));\n if (deps.some((d) => d.includes(\"spring-boot\"))) stack.add(\"Spring Boot\");\n if (deps.some((d) => d.includes(\"mybatis\"))) stack.add(\"MyBatis\");\n } catch { /* ignore */ }\n }\n\n context.techStack = Array.from(stack);\n context.dependencies = [...new Set(deps)];\n }\n\n /** Scan Java controller files for API structure */\n private async loadJavaApiStructure(context: ProjectContext): Promise<void> {\n const controllerFiles = await glob(\"**/src/main/java/**/*Controller.java\", {\n cwd: this.projectRoot,\n ignore: [\"**/target/**\"],\n });\n context.apiStructure = controllerFiles.slice(0, 30);\n\n // Also pick up routes from application.properties/yml if present\n const propFiles = await glob(\"**/src/main/resources/application.{properties,yml,yaml}\", {\n cwd: this.projectRoot,\n ignore: [\"**/target/**\"],\n });\n if (propFiles.length > 0 && !context.routeSummary) {\n const parts: string[] = [];\n for (const f of propFiles.slice(0, 2)) {\n try {\n const content = await fs.readFile(path.join(this.projectRoot, f), \"utf-8\");\n parts.push(`// ${f}\\n${content.slice(0, 800)}`);\n } catch { /* skip */ }\n }\n if (parts.length > 0) context.routeSummary = parts.join(\"\\n\\n\");\n }\n }\n\n private async loadPackageJson(context: ProjectContext): Promise<void> {\n const pkgPath = path.join(this.projectRoot, \"package.json\");\n if (!(await fs.pathExists(pkgPath))) return;\n\n const pkg = await fs.readJson(pkgPath);\n const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };\n context.dependencies = Object.keys(allDeps);\n\n const detectedStack = new Set<string>();\n for (const [key, name] of Object.entries(STACK_MAP)) {\n if (context.dependencies.some((d) => d === key || d.startsWith(key + \"/\"))) {\n detectedStack.add(name as string);\n }\n }\n context.techStack = Array.from(detectedStack);\n }\n\n private async loadPrismaSchema(context: ProjectContext): Promise<void> {\n const schemaPath = path.join(this.projectRoot, \"prisma\", \"schema.prisma\");\n if (await fs.pathExists(schemaPath)) {\n context.schema = await fs.readFile(schemaPath, \"utf-8\");\n }\n }\n\n private async loadFileStructure(context: ProjectContext): Promise<void> {\n const files = await glob(\"**/*\", {\n cwd: this.projectRoot,\n ignore: [\n \"node_modules/**\",\n \"vendor/**\",\n \"dist/**\",\n \"build/**\",\n \".git/**\",\n \"coverage/**\",\n \"*.lock\",\n \".DS_Store\",\n \"**/*.min.js\",\n \"**/*.map\",\n ],\n nodir: false,\n maxDepth: 5,\n });\n context.fileStructure = files.slice(0, 120);\n }\n\n private async loadConstitution(context: ProjectContext): Promise<void> {\n // Project-level constitution\n const projectFile = path.join(this.projectRoot, \".ai-spec-constitution.md\");\n const projectConstitution = (await fs.pathExists(projectFile))\n ? await fs.readFile(projectFile, \"utf-8\")\n : undefined;\n\n // Global constitution — search workspace root (parent of projectRoot) then home dir\n const workspaceRoot = path.dirname(this.projectRoot);\n const globalResult = await loadGlobalConstitution([workspaceRoot]);\n\n if (globalResult) {\n // Merge: global baseline + project override\n context.constitution = mergeConstitutions(globalResult.content, projectConstitution);\n } else if (projectConstitution) {\n context.constitution = projectConstitution;\n }\n }\n\n private async loadErrorPatterns(context: ProjectContext): Promise<void> {\n // Look for error handler middleware or error code files\n const errorFiles = await glob(\n \"src/**/{error,errors,errorHandler,errorCodes,error-handler,error-codes}.{ts,js}\",\n { cwd: this.projectRoot }\n );\n const middlewareErrors = await glob(\"src/**/middleware/**/{error,notFound}.{ts,js}\", {\n cwd: this.projectRoot,\n });\n // PHP / Lumen exception handlers\n const phpErrorFiles = await glob(\n \"app/Exceptions/{Handler,ErrorHandler}.php\",\n { cwd: this.projectRoot, ignore: [\"vendor/**\"] }\n );\n const allErrorFiles = [...new Set([...errorFiles, ...middlewareErrors, ...phpErrorFiles])].slice(0, 3);\n\n if (allErrorFiles.length === 0) return;\n\n const parts: string[] = [];\n for (const f of allErrorFiles) {\n try {\n const content = await fs.readFile(path.join(this.projectRoot, f), \"utf-8\");\n parts.push(`// ${f}\\n${content.slice(0, 800)}`);\n } catch {\n // skip\n }\n }\n if (parts.length > 0) {\n context.errorPatterns = parts.join(\"\\n\\n\");\n }\n }\n\n /**\n * Scan for \"singleton\" config files that should never be duplicated.\n * These are append-only files: i18n bundles, constants, enums, config indices.\n */\n private async loadSharedConfigFiles(context: ProjectContext): Promise<void> {\n const patterns: Array<{ glob: string; category: SharedConfigFile[\"category\"] }> = [\n // i18n / locales\n { glob: \"src/locales/**/*.{json,ts,js}\", category: \"i18n\" },\n { glob: \"src/i18n/**/*.{json,ts,js}\", category: \"i18n\" },\n { glob: \"locales/**/*.{json,ts,js}\", category: \"i18n\" },\n { glob: \"public/locales/**/*.{json,ts,js}\", category: \"i18n\" },\n // constants / enums\n { glob: \"src/constants/**/*.{ts,js}\", category: \"constants\" },\n { glob: \"src/enums/**/*.{ts,js}\", category: \"enums\" },\n { glob: \"src/**/constants.{ts,js}\", category: \"constants\" },\n { glob: \"src/**/enums.{ts,js}\", category: \"enums\" },\n // config\n { glob: \"src/config/**/*.{ts,js}\", category: \"config\" },\n // ── Route registration files ────────────────────────────────────────────\n // Node.js / Express\n { glob: \"src/routes/**/index.{ts,js}\", category: \"route-index\" },\n { glob: \"src/routes/index.{ts,js}\", category: \"route-index\" },\n // Vue Router — root index and modules pattern\n { glob: \"src/router/index.{ts,js}\", category: \"route-index\" },\n { glob: \"src/router/routes.{ts,js}\", category: \"route-index\" },\n { glob: \"src/router/modules/**/*.{ts,js}\", category: \"route-index\" },\n // React Router — standalone routes file or App entry\n { glob: \"src/routes.{ts,tsx,js,jsx}\", category: \"route-index\" },\n { glob: \"src/router.{ts,tsx,js,jsx}\", category: \"route-index\" },\n // PHP (Lumen / Laravel)\n { glob: \"routes/api.php\", category: \"route-index\" },\n { glob: \"routes/web.php\", category: \"route-index\" },\n // ── Store registration files ────────────────────────────────────────────\n // Pinia / Vuex index\n { glob: \"src/stores/index.{ts,js}\", category: \"store-index\" },\n { glob: \"src/store/index.{ts,js}\", category: \"store-index\" },\n { glob: \"src/store/modules/index.{ts,js}\", category: \"store-index\" },\n // Redux root reducer / store setup\n { glob: \"src/store/rootReducer.{ts,js}\", category: \"store-index\" },\n { glob: \"src/store/store.{ts,js}\", category: \"store-index\" },\n { glob: \"src/app/store.{ts,js}\", category: \"store-index\" },\n ];\n\n const seen = new Set<string>();\n const results: SharedConfigFile[] = [];\n\n for (const { glob: pattern, category } of patterns) {\n const files = await glob(pattern, {\n cwd: this.projectRoot,\n ignore: [\"node_modules/**\", \"dist/**\", \"**/*.test.*\", \"**/*.spec.*\"],\n });\n for (const filePath of files) {\n if (seen.has(filePath)) continue;\n seen.add(filePath);\n try {\n const content = await fs.readFile(path.join(this.projectRoot, filePath), \"utf-8\");\n const preview = content.split(\"\\n\").slice(0, 120).join(\"\\n\");\n results.push({ path: filePath, preview, category });\n } catch {\n // skip unreadable\n }\n }\n }\n\n if (results.length > 0) {\n context.sharedConfigFiles = results;\n }\n }\n\n private async loadApiStructure(context: ProjectContext): Promise<void> {\n const apiFiles = await glob(\n \"src/**/{routes,controllers,api,router,middleware}/**/*.{ts,js}\",\n {\n cwd: this.projectRoot,\n ignore: [\"**/*.test.*\", \"**/*.spec.*\"],\n }\n );\n\n // Also check common flat structures\n const rootApiFiles = await glob(\"src/{routes,controllers,router}.{ts,js}\", {\n cwd: this.projectRoot,\n });\n\n context.apiStructure = [...new Set([...apiFiles, ...rootApiFiles])];\n\n // Build route summary: read first 60 lines of each route file\n if (context.apiStructure.length > 0) {\n const summaryParts: string[] = [];\n for (const filePath of context.apiStructure.slice(0, 8)) {\n const fullPath = path.join(this.projectRoot, filePath);\n try {\n const content = await fs.readFile(fullPath, \"utf-8\");\n const preview = content.split(\"\\n\").slice(0, 60).join(\"\\n\");\n summaryParts.push(`\\`\\`\\`\\n// ${filePath}\\n${preview}\\n\\`\\`\\``);\n } catch {\n // skip unreadable files\n }\n }\n if (summaryParts.length > 0) {\n context.routeSummary = summaryParts.join(\"\\n\\n\");\n }\n }\n }\n}\n","export const balanced = (\n a: string | RegExp,\n b: string | RegExp,\n str: string,\n) => {\n const ma = a instanceof RegExp ? maybeMatch(a, str) : a\n const mb = b instanceof RegExp ? maybeMatch(b, str) : b\n\n const r = ma !== null && mb != null && range(ma, mb, str)\n\n return (\n r && {\n start: r[0],\n end: r[1],\n pre: str.slice(0, r[0]),\n body: str.slice(r[0] + ma.length, r[1]),\n post: str.slice(r[1] + mb.length),\n }\n )\n}\n\nconst maybeMatch = (reg: RegExp, str: string) => {\n const m = str.match(reg)\n return m ? m[0] : null\n}\n\nexport const range = (\n a: string,\n b: string,\n str: string,\n): undefined | [number, number] => {\n let begs: number[],\n beg: number | undefined,\n left: number,\n right: number | undefined = undefined,\n result: undefined | [number, number]\n let ai = str.indexOf(a)\n let bi = str.indexOf(b, ai + 1)\n let i = ai\n\n if (ai >= 0 && bi > 0) {\n if (a === b) {\n return [ai, bi]\n }\n begs = []\n left = str.length\n\n while (i >= 0 && !result) {\n if (i === ai) {\n begs.push(i)\n ai = str.indexOf(a, i + 1)\n } else if (begs.length === 1) {\n const r = begs.pop()\n if (r !== undefined) result = [r, bi]\n } else {\n beg = begs.pop()\n if (beg !== undefined && beg < left) {\n left = beg\n right = bi\n }\n\n bi = str.indexOf(b, i + 1)\n }\n\n i = ai < bi && ai >= 0 ? ai : bi\n }\n\n if (begs.length && right !== undefined) {\n result = [left, right]\n }\n }\n\n return result\n}\n","import { balanced } from 'balanced-match'\n\nconst escSlash = '\\0SLASH' + Math.random() + '\\0'\nconst escOpen = '\\0OPEN' + Math.random() + '\\0'\nconst escClose = '\\0CLOSE' + Math.random() + '\\0'\nconst escComma = '\\0COMMA' + Math.random() + '\\0'\nconst escPeriod = '\\0PERIOD' + Math.random() + '\\0'\nconst escSlashPattern = new RegExp(escSlash, 'g')\nconst escOpenPattern = new RegExp(escOpen, 'g')\nconst escClosePattern = new RegExp(escClose, 'g')\nconst escCommaPattern = new RegExp(escComma, 'g')\nconst escPeriodPattern = new RegExp(escPeriod, 'g')\nconst slashPattern = /\\\\\\\\/g\nconst openPattern = /\\\\{/g\nconst closePattern = /\\\\}/g\nconst commaPattern = /\\\\,/g\nconst periodPattern = /\\\\./g\n\nexport const EXPANSION_MAX = 100_000\n\nfunction numeric(str: string) {\n return !isNaN(str as any) ? parseInt(str, 10) : str.charCodeAt(0)\n}\n\nfunction escapeBraces(str: string) {\n return str\n .replace(slashPattern, escSlash)\n .replace(openPattern, escOpen)\n .replace(closePattern, escClose)\n .replace(commaPattern, escComma)\n .replace(periodPattern, escPeriod)\n}\n\nfunction unescapeBraces(str: string) {\n return str\n .replace(escSlashPattern, '\\\\')\n .replace(escOpenPattern, '{')\n .replace(escClosePattern, '}')\n .replace(escCommaPattern, ',')\n .replace(escPeriodPattern, '.')\n}\n\n/**\n * Basically just str.split(\",\"), but handling cases\n * where we have nested braced sections, which should be\n * treated as individual members, like {a,{b,c},d}\n */\nfunction parseCommaParts(str: string) {\n if (!str) {\n return ['']\n }\n\n const parts: string[] = []\n const m = balanced('{', '}', str)\n\n if (!m) {\n return str.split(',')\n }\n\n const { pre, body, post } = m\n const p = pre.split(',')\n\n p[p.length - 1] += '{' + body + '}'\n const postParts = parseCommaParts(post)\n if (post.length) {\n ;(p[p.length - 1] as string) += postParts.shift()\n p.push.apply(p, postParts)\n }\n\n parts.push.apply(parts, p)\n\n return parts\n}\n\nexport type BraceExpansionOptions = {\n max?: number\n}\n\nexport function expand(str: string, options: BraceExpansionOptions = {}) {\n if (!str) {\n return []\n }\n\n const { max = EXPANSION_MAX } = options\n\n // I don't know why Bash 4.3 does this, but it does.\n // Anything starting with {} will have the first two bytes preserved\n // but *only* at the top level, so {},a}b will not expand to anything,\n // but a{},b}c will be expanded to [a}c,abc].\n // One could argue that this is a bug in Bash, but since the goal of\n // this module is to match Bash's rules, we escape a leading {}\n if (str.slice(0, 2) === '{}') {\n str = '\\\\{\\\\}' + str.slice(2)\n }\n\n return expand_(escapeBraces(str), max, true).map(unescapeBraces)\n}\n\nfunction embrace(str: string) {\n return '{' + str + '}'\n}\n\nfunction isPadded(el: string) {\n return /^-?0\\d/.test(el)\n}\n\nfunction lte(i: number, y: number) {\n return i <= y\n}\n\nfunction gte(i: number, y: number) {\n return i >= y\n}\n\nfunction expand_(str: string, max: number, isTop: boolean): string[] {\n /** @type {string[]} */\n const expansions: string[] = []\n\n const m = balanced('{', '}', str)\n if (!m) return [str]\n\n // no need to expand pre, since it is guaranteed to be free of brace-sets\n const pre = m.pre\n const post: string[] = m.post.length ? expand_(m.post, max, false) : ['']\n\n if (/\\$$/.test(m.pre)) {\n for (let k = 0; k < post.length && k < max; k++) {\n const expansion = pre + '{' + m.body + '}' + post[k]\n expansions.push(expansion)\n }\n } else {\n const isNumericSequence = /^-?\\d+\\.\\.-?\\d+(?:\\.\\.-?\\d+)?$/.test(m.body)\n const isAlphaSequence = /^[a-zA-Z]\\.\\.[a-zA-Z](?:\\.\\.-?\\d+)?$/.test(\n m.body,\n )\n const isSequence = isNumericSequence || isAlphaSequence\n const isOptions = m.body.indexOf(',') >= 0\n if (!isSequence && !isOptions) {\n // {a},b}\n if (m.post.match(/,(?!,).*\\}/)) {\n str = m.pre + '{' + m.body + escClose + m.post\n return expand_(str, max, true)\n }\n return [str]\n }\n\n let n: string[]\n if (isSequence) {\n n = m.body.split(/\\.\\./)\n } else {\n n = parseCommaParts(m.body)\n if (n.length === 1 && n[0] !== undefined) {\n // x{{a,b}}y ==> x{a}y x{b}y\n n = expand_(n[0], max, false).map(embrace)\n //XXX is this necessary? Can't seem to hit it in tests.\n /* c8 ignore start */\n if (n.length === 1) {\n return post.map(p => m.pre + n[0] + p)\n }\n /* c8 ignore stop */\n }\n }\n\n // at this point, n is the parts, and we know it's not a comma set\n // with a single entry.\n let N: string[]\n\n if (isSequence && n[0] !== undefined && n[1] !== undefined) {\n const x = numeric(n[0])\n const y = numeric(n[1])\n const width = Math.max(n[0].length, n[1].length)\n let incr =\n n.length === 3 && n[2] !== undefined ? Math.abs(numeric(n[2])) : 1\n let test = lte\n const reverse = y < x\n if (reverse) {\n incr *= -1\n test = gte\n }\n const pad = n.some(isPadded)\n\n N = []\n\n for (let i = x; test(i, y); i += incr) {\n let c\n if (isAlphaSequence) {\n c = String.fromCharCode(i)\n if (c === '\\\\') {\n c = ''\n }\n } else {\n c = String(i)\n if (pad) {\n const need = width - c.length\n if (need > 0) {\n const z = new Array(need + 1).join('0')\n if (i < 0) {\n c = '-' + z + c.slice(1)\n } else {\n c = z + c\n }\n }\n }\n }\n N.push(c)\n }\n } else {\n N = []\n\n for (let j = 0; j < n.length; j++) {\n N.push.apply(N, expand_(n[j] as string, max, false))\n }\n }\n\n for (let j = 0; j < N.length; j++) {\n for (let k = 0; k < post.length && expansions.length < max; k++) {\n const expansion = pre + N[j] + post[k]\n if (!isTop || isSequence || expansion) {\n expansions.push(expansion)\n }\n }\n }\n }\n\n return expansions\n}\n","const MAX_PATTERN_LENGTH = 1024 * 64\nexport const assertValidPattern: (pattern: any) => void = (\n pattern: any,\n): asserts pattern is string => {\n if (typeof pattern !== 'string') {\n throw new TypeError('invalid pattern')\n }\n\n if (pattern.length > MAX_PATTERN_LENGTH) {\n throw new TypeError('pattern is too long')\n }\n}\n","// translate the various posix character classes into unicode properties\n// this works across all unicode locales\n\n// { <posix class>: [<translation>, /u flag required, negated]\nconst posixClasses: { [k: string]: [e: string, u: boolean, n?: boolean] } =\n {\n '[:alnum:]': ['\\\\p{L}\\\\p{Nl}\\\\p{Nd}', true],\n '[:alpha:]': ['\\\\p{L}\\\\p{Nl}', true],\n '[:ascii:]': ['\\\\x' + '00-\\\\x' + '7f', false],\n '[:blank:]': ['\\\\p{Zs}\\\\t', true],\n '[:cntrl:]': ['\\\\p{Cc}', true],\n '[:digit:]': ['\\\\p{Nd}', true],\n '[:graph:]': ['\\\\p{Z}\\\\p{C}', true, true],\n '[:lower:]': ['\\\\p{Ll}', true],\n '[:print:]': ['\\\\p{C}', true],\n '[:punct:]': ['\\\\p{P}', true],\n '[:space:]': ['\\\\p{Z}\\\\t\\\\r\\\\n\\\\v\\\\f', true],\n '[:upper:]': ['\\\\p{Lu}', true],\n '[:word:]': ['\\\\p{L}\\\\p{Nl}\\\\p{Nd}\\\\p{Pc}', true],\n '[:xdigit:]': ['A-Fa-f0-9', false],\n }\n\n// only need to escape a few things inside of brace expressions\n// escapes: [ \\ ] -\nconst braceEscape = (s: string) => s.replace(/[[\\]\\\\-]/g, '\\\\$&')\n// escape all regexp magic characters\nconst regexpEscape = (s: string) =>\n s.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&')\n\n// everything has already been escaped, we just have to join\nconst rangesToString = (ranges: string[]): string => ranges.join('')\n\nexport type ParseClassResult = [\n src: string,\n uFlag: boolean,\n consumed: number,\n hasMagic: boolean,\n]\n\n// takes a glob string at a posix brace expression, and returns\n// an equivalent regular expression source, and boolean indicating\n// whether the /u flag needs to be applied, and the number of chars\n// consumed to parse the character class.\n// This also removes out of order ranges, and returns ($.) if the\n// entire class just no good.\nexport const parseClass = (\n glob: string,\n position: number,\n): ParseClassResult => {\n const pos = position\n /* c8 ignore start */\n if (glob.charAt(pos) !== '[') {\n throw new Error('not in a brace expression')\n }\n /* c8 ignore stop */\n const ranges: string[] = []\n const negs: string[] = []\n\n let i = pos + 1\n let sawStart = false\n let uflag = false\n let escaping = false\n let negate = false\n let endPos = pos\n let rangeStart = ''\n WHILE: while (i < glob.length) {\n const c = glob.charAt(i)\n if ((c === '!' || c === '^') && i === pos + 1) {\n negate = true\n i++\n continue\n }\n\n if (c === ']' && sawStart && !escaping) {\n endPos = i + 1\n break\n }\n\n sawStart = true\n if (c === '\\\\') {\n if (!escaping) {\n escaping = true\n i++\n continue\n }\n // escaped \\ char, fall through and treat like normal char\n }\n if (c === '[' && !escaping) {\n // either a posix class, a collation equivalent, or just a [\n for (const [cls, [unip, u, neg]] of Object.entries(posixClasses)) {\n if (glob.startsWith(cls, i)) {\n // invalid, [a-[] is fine, but not [a-[:alpha]]\n if (rangeStart) {\n return ['$.', false, glob.length - pos, true]\n }\n i += cls.length\n if (neg) negs.push(unip)\n else ranges.push(unip)\n uflag = uflag || u\n continue WHILE\n }\n }\n }\n\n // now it's just a normal character, effectively\n escaping = false\n if (rangeStart) {\n // throw this range away if it's not valid, but others\n // can still match.\n if (c > rangeStart) {\n ranges.push(braceEscape(rangeStart) + '-' + braceEscape(c))\n } else if (c === rangeStart) {\n ranges.push(braceEscape(c))\n }\n rangeStart = ''\n i++\n continue\n }\n\n // now might be the start of a range.\n // can be either c-d or c-] or c<more...>] or c] at this point\n if (glob.startsWith('-]', i + 1)) {\n ranges.push(braceEscape(c + '-'))\n i += 2\n continue\n }\n if (glob.startsWith('-', i + 1)) {\n rangeStart = c\n i += 2\n continue\n }\n\n // not the start of a range, just a single character\n ranges.push(braceEscape(c))\n i++\n }\n\n if (endPos < i) {\n // didn't see the end of the class, not a valid class,\n // but might still be valid as a literal match.\n return ['', false, 0, false]\n }\n\n // if we got no ranges and no negates, then we have a range that\n // cannot possibly match anything, and that poisons the whole glob\n if (!ranges.length && !negs.length) {\n return ['$.', false, glob.length - pos, true]\n }\n\n // if we got one positive range, and it's a single character, then that's\n // not actually a magic pattern, it's just that one literal character.\n // we should not treat that as \"magic\", we should just return the literal\n // character. [_] is a perfectly valid way to escape glob magic chars.\n if (\n negs.length === 0 &&\n ranges.length === 1 &&\n /^\\\\?.$/.test(ranges[0]) &&\n !negate\n ) {\n const r = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0]\n return [regexpEscape(r), false, endPos - pos, false]\n }\n\n const sranges = '[' + (negate ? '^' : '') + rangesToString(ranges) + ']'\n const snegs = '[' + (negate ? '' : '^') + rangesToString(negs) + ']'\n const comb =\n ranges.length && negs.length ? '(' + sranges + '|' + snegs + ')'\n : ranges.length ? sranges\n : snegs\n\n return [comb, uflag, endPos - pos, true]\n}\n","import { MinimatchOptions } from './index.js'\n\n/**\n * Un-escape a string that has been escaped with {@link escape}.\n *\n * If the {@link MinimatchOptions.windowsPathsNoEscape} option is used, then\n * square-bracket escapes are removed, but not backslash escapes.\n *\n * For example, it will turn the string `'[*]'` into `*`, but it will not\n * turn `'\\\\*'` into `'*'`, because `\\` is a path separator in\n * `windowsPathsNoEscape` mode.\n *\n * When `windowsPathsNoEscape` is not set, then both square-bracket escapes and\n * backslash escapes are removed.\n *\n * Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot be escaped\n * or unescaped.\n *\n * When `magicalBraces` is not set, escapes of braces (`{` and `}`) will not be\n * unescaped.\n */\n\nexport const unescape = (\n s: string,\n {\n windowsPathsNoEscape = false,\n magicalBraces = true,\n }: Pick<MinimatchOptions, 'windowsPathsNoEscape' | 'magicalBraces'> = {},\n) => {\n if (magicalBraces) {\n return windowsPathsNoEscape ?\n s.replace(/\\[([^\\/\\\\])\\]/g, '$1')\n : s\n .replace(/((?!\\\\).|^)\\[([^\\/\\\\])\\]/g, '$1$2')\n .replace(/\\\\([^\\/])/g, '$1')\n }\n return windowsPathsNoEscape ?\n s.replace(/\\[([^\\/\\\\{}])\\]/g, '$1')\n : s\n .replace(/((?!\\\\).|^)\\[([^\\/\\\\{}])\\]/g, '$1$2')\n .replace(/\\\\([^\\/{}])/g, '$1')\n}\n","// parse a single path portion\n\nimport { parseClass } from './brace-expressions.js'\nimport { MinimatchOptions, MMRegExp } from './index.js'\nimport { unescape } from './unescape.js'\n\n// classes [] are handled by the parseClass method\n// for positive extglobs, we sub-parse the contents, and combine,\n// with the appropriate regexp close.\n// for negative extglobs, we sub-parse the contents, but then\n// have to include the rest of the pattern, then the parent, etc.,\n// as the thing that cannot be because RegExp negative lookaheads\n// are different from globs.\n//\n// So for example:\n// a@(i|w!(x|y)z|j)b => ^a(i|w((!?(x|y)zb).*)z|j)b$\n// 1 2 3 4 5 6 1 2 3 46 5 6\n//\n// Assembling the extglob requires not just the negated patterns themselves,\n// but also anything following the negative patterns up to the boundary\n// of the current pattern, plus anything following in the parent pattern.\n//\n//\n// So, first, we parse the string into an AST of extglobs, without turning\n// anything into regexps yet.\n//\n// ['a', {@ [['i'], ['w', {!['x', 'y']}, 'z'], ['j']]}, 'b']\n//\n// Then, for all the negative extglobs, we append whatever comes after in\n// each parent as their tail\n//\n// ['a', {@ [['i'], ['w', {!['x', 'y'], 'z', 'b'}, 'z'], ['j']]}, 'b']\n//\n// Lastly, we turn each of these pieces into a regexp, and join\n//\n// v----- .* because there's more following,\n// v v otherwise, .+ because it must be\n// v v *something* there.\n// ['^a', {@ ['i', 'w(?:(!?(?:x|y).*zb$).*)z', 'j' ]}, 'b$']\n// copy what follows into here--^^^^^\n// ['^a', '(?:i|w(?:(?!(?:x|y).*zb$).*)z|j)', 'b$']\n// ['^a(?:i|w(?:(?!(?:x|y).*zb$).*)z|j)b$']\n\nexport type ExtglobType = '!' | '?' | '+' | '*' | '@'\nconst types = new Set<ExtglobType>(['!', '?', '+', '*', '@'])\nconst isExtglobType = (c: string): c is ExtglobType =>\n types.has(c as ExtglobType)\n\n// Patterns that get prepended to bind to the start of either the\n// entire string, or just a single path portion, to prevent dots\n// and/or traversal patterns, when needed.\n// Exts don't need the ^ or / bit, because the root binds that already.\nconst startNoTraversal = '(?!(?:^|/)\\\\.\\\\.?(?:$|/))'\nconst startNoDot = '(?!\\\\.)'\n\n// characters that indicate a start of pattern needs the \"no dots\" bit,\n// because a dot *might* be matched. ( is not in the list, because in\n// the case of a child extglob, it will handle the prevention itself.\nconst addPatternStart = new Set(['[', '.'])\n// cases where traversal is A-OK, no dot prevention needed\nconst justDots = new Set(['..', '.'])\nconst reSpecials = new Set('().*{}+?[]^$\\\\!')\nconst regExpEscape = (s: string) =>\n s.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&')\n\n// any single thing other than /\nconst qmark = '[^/]'\n\n// * => any number of characters\nconst star = qmark + '*?'\n// use + when we need to ensure that *something* matches, because the * is\n// the only thing in the path portion.\nconst starNoEmpty = qmark + '+?'\n\n// remove the \\ chars that we added if we end up doing a nonmagic compare\n// const deslash = (s: string) => s.replace(/\\\\(.)/g, '$1')\n\nexport class AST {\n type: ExtglobType | null\n readonly #root: AST\n\n #hasMagic?: boolean\n #uflag: boolean = false\n #parts: (string | AST)[] = []\n readonly #parent?: AST\n readonly #parentIndex: number\n #negs: AST[]\n #filledNegs: boolean = false\n #options: MinimatchOptions\n #toString?: string\n // set to true if it's an extglob with no children\n // (which really means one child of '')\n #emptyExt: boolean = false\n\n constructor(\n type: ExtglobType | null,\n parent?: AST,\n options: MinimatchOptions = {},\n ) {\n this.type = type\n // extglobs are inherently magical\n if (type) this.#hasMagic = true\n this.#parent = parent\n this.#root = this.#parent ? this.#parent.#root : this\n this.#options = this.#root === this ? options : this.#root.#options\n this.#negs = this.#root === this ? [] : this.#root.#negs\n if (type === '!' && !this.#root.#filledNegs) this.#negs.push(this)\n this.#parentIndex = this.#parent ? this.#parent.#parts.length : 0\n }\n\n get hasMagic(): boolean | undefined {\n /* c8 ignore start */\n if (this.#hasMagic !== undefined) return this.#hasMagic\n /* c8 ignore stop */\n for (const p of this.#parts) {\n if (typeof p === 'string') continue\n if (p.type || p.hasMagic) return (this.#hasMagic = true)\n }\n // note: will be undefined until we generate the regexp src and find out\n return this.#hasMagic\n }\n\n // reconstructs the pattern\n toString(): string {\n if (this.#toString !== undefined) return this.#toString\n if (!this.type) {\n return (this.#toString = this.#parts.map(p => String(p)).join(''))\n } else {\n return (this.#toString =\n this.type + '(' + this.#parts.map(p => String(p)).join('|') + ')')\n }\n }\n\n #fillNegs() {\n /* c8 ignore start */\n if (this !== this.#root) throw new Error('should only call on root')\n if (this.#filledNegs) return this\n /* c8 ignore stop */\n\n // call toString() once to fill this out\n this.toString()\n this.#filledNegs = true\n let n: AST | undefined\n while ((n = this.#negs.pop())) {\n if (n.type !== '!') continue\n // walk up the tree, appending everthing that comes AFTER parentIndex\n let p: AST | undefined = n\n let pp = p.#parent\n while (pp) {\n for (\n let i = p.#parentIndex + 1;\n !pp.type && i < pp.#parts.length;\n i++\n ) {\n for (const part of n.#parts) {\n /* c8 ignore start */\n if (typeof part === 'string') {\n throw new Error('string part in extglob AST??')\n }\n /* c8 ignore stop */\n part.copyIn(pp.#parts[i])\n }\n }\n p = pp\n pp = p.#parent\n }\n }\n return this\n }\n\n push(...parts: (string | AST)[]) {\n for (const p of parts) {\n if (p === '') continue\n /* c8 ignore start */\n if (\n typeof p !== 'string' &&\n !(p instanceof AST && p.#parent === this)\n ) {\n throw new Error('invalid part: ' + p)\n }\n /* c8 ignore stop */\n this.#parts.push(p)\n }\n }\n\n toJSON() {\n const ret: any[] =\n this.type === null ?\n this.#parts\n .slice()\n .map(p => (typeof p === 'string' ? p : p.toJSON()))\n : [this.type, ...this.#parts.map(p => (p as AST).toJSON())]\n if (this.isStart() && !this.type) ret.unshift([])\n if (\n this.isEnd() &&\n (this === this.#root ||\n (this.#root.#filledNegs && this.#parent?.type === '!'))\n ) {\n ret.push({})\n }\n return ret\n }\n\n isStart(): boolean {\n if (this.#root === this) return true\n // if (this.type) return !!this.#parent?.isStart()\n if (!this.#parent?.isStart()) return false\n if (this.#parentIndex === 0) return true\n // if everything AHEAD of this is a negation, then it's still the \"start\"\n const p = this.#parent\n for (let i = 0; i < this.#parentIndex; i++) {\n const pp = p.#parts[i]\n if (!(pp instanceof AST && pp.type === '!')) {\n return false\n }\n }\n return true\n }\n\n isEnd(): boolean {\n if (this.#root === this) return true\n if (this.#parent?.type === '!') return true\n if (!this.#parent?.isEnd()) return false\n if (!this.type) return this.#parent?.isEnd()\n // if not root, it'll always have a parent\n /* c8 ignore start */\n const pl = this.#parent ? this.#parent.#parts.length : 0\n /* c8 ignore stop */\n return this.#parentIndex === pl - 1\n }\n\n copyIn(part: AST | string) {\n if (typeof part === 'string') this.push(part)\n else this.push(part.clone(this))\n }\n\n clone(parent: AST) {\n const c = new AST(this.type, parent)\n for (const p of this.#parts) {\n c.copyIn(p)\n }\n return c\n }\n\n static #parseAST(\n str: string,\n ast: AST,\n pos: number,\n opt: MinimatchOptions,\n ): number {\n let escaping = false\n let inBrace = false\n let braceStart = -1\n let braceNeg = false\n if (ast.type === null) {\n // outside of a extglob, append until we find a start\n let i = pos\n let acc = ''\n while (i < str.length) {\n const c = str.charAt(i++)\n // still accumulate escapes at this point, but we do ignore\n // starts that are escaped\n if (escaping || c === '\\\\') {\n escaping = !escaping\n acc += c\n continue\n }\n\n if (inBrace) {\n if (i === braceStart + 1) {\n if (c === '^' || c === '!') {\n braceNeg = true\n }\n } else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {\n inBrace = false\n }\n acc += c\n continue\n } else if (c === '[') {\n inBrace = true\n braceStart = i\n braceNeg = false\n acc += c\n continue\n }\n\n if (!opt.noext && isExtglobType(c) && str.charAt(i) === '(') {\n ast.push(acc)\n acc = ''\n const ext = new AST(c, ast)\n i = AST.#parseAST(str, ext, i, opt)\n ast.push(ext)\n continue\n }\n acc += c\n }\n ast.push(acc)\n return i\n }\n\n // some kind of extglob, pos is at the (\n // find the next | or )\n let i = pos + 1\n let part = new AST(null, ast)\n const parts: AST[] = []\n let acc = ''\n while (i < str.length) {\n const c = str.charAt(i++)\n // still accumulate escapes at this point, but we do ignore\n // starts that are escaped\n if (escaping || c === '\\\\') {\n escaping = !escaping\n acc += c\n continue\n }\n\n if (inBrace) {\n if (i === braceStart + 1) {\n if (c === '^' || c === '!') {\n braceNeg = true\n }\n } else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {\n inBrace = false\n }\n acc += c\n continue\n } else if (c === '[') {\n inBrace = true\n braceStart = i\n braceNeg = false\n acc += c\n continue\n }\n\n if (isExtglobType(c) && str.charAt(i) === '(') {\n part.push(acc)\n acc = ''\n const ext = new AST(c, part)\n part.push(ext)\n i = AST.#parseAST(str, ext, i, opt)\n continue\n }\n if (c === '|') {\n part.push(acc)\n acc = ''\n parts.push(part)\n part = new AST(null, ast)\n continue\n }\n if (c === ')') {\n if (acc === '' && ast.#parts.length === 0) {\n ast.#emptyExt = true\n }\n part.push(acc)\n acc = ''\n ast.push(...parts, part)\n return i\n }\n acc += c\n }\n\n // unfinished extglob\n // if we got here, it was a malformed extglob! not an extglob, but\n // maybe something else in there.\n ast.type = null\n ast.#hasMagic = undefined\n ast.#parts = [str.substring(pos - 1)]\n return i\n }\n\n static fromGlob(pattern: string, options: MinimatchOptions = {}) {\n const ast = new AST(null, undefined, options)\n AST.#parseAST(pattern, ast, 0, options)\n return ast\n }\n\n // returns the regular expression if there's magic, or the unescaped\n // string if not.\n toMMPattern(): MMRegExp | string {\n // should only be called on root\n /* c8 ignore start */\n if (this !== this.#root) return this.#root.toMMPattern()\n /* c8 ignore stop */\n const glob = this.toString()\n const [re, body, hasMagic, uflag] = this.toRegExpSource()\n // if we're in nocase mode, and not nocaseMagicOnly, then we do\n // still need a regular expression if we have to case-insensitively\n // match capital/lowercase characters.\n const anyMagic =\n hasMagic ||\n this.#hasMagic ||\n (this.#options.nocase &&\n !this.#options.nocaseMagicOnly &&\n glob.toUpperCase() !== glob.toLowerCase())\n if (!anyMagic) {\n return body\n }\n\n const flags = (this.#options.nocase ? 'i' : '') + (uflag ? 'u' : '')\n return Object.assign(new RegExp(`^${re}$`, flags), {\n _src: re,\n _glob: glob,\n })\n }\n\n get options() {\n return this.#options\n }\n\n // returns the string match, the regexp source, whether there's magic\n // in the regexp (so a regular expression is required) and whether or\n // not the uflag is needed for the regular expression (for posix classes)\n // TODO: instead of injecting the start/end at this point, just return\n // the BODY of the regexp, along with the start/end portions suitable\n // for binding the start/end in either a joined full-path makeRe context\n // (where we bind to (^|/), or a standalone matchPart context (where\n // we bind to ^, and not /). Otherwise slashes get duped!\n //\n // In part-matching mode, the start is:\n // - if not isStart: nothing\n // - if traversal possible, but not allowed: ^(?!\\.\\.?$)\n // - if dots allowed or not possible: ^\n // - if dots possible and not allowed: ^(?!\\.)\n // end is:\n // - if not isEnd(): nothing\n // - else: $\n //\n // In full-path matching mode, we put the slash at the START of the\n // pattern, so start is:\n // - if first pattern: same as part-matching mode\n // - if not isStart(): nothing\n // - if traversal possible, but not allowed: /(?!\\.\\.?(?:$|/))\n // - if dots allowed or not possible: /\n // - if dots possible and not allowed: /(?!\\.)\n // end is:\n // - if last pattern, same as part-matching mode\n // - else nothing\n //\n // Always put the (?:$|/) on negated tails, though, because that has to be\n // there to bind the end of the negated pattern portion, and it's easier to\n // just stick it in now rather than try to inject it later in the middle of\n // the pattern.\n //\n // We can just always return the same end, and leave it up to the caller\n // to know whether it's going to be used joined or in parts.\n // And, if the start is adjusted slightly, can do the same there:\n // - if not isStart: nothing\n // - if traversal possible, but not allowed: (?:/|^)(?!\\.\\.?$)\n // - if dots allowed or not possible: (?:/|^)\n // - if dots possible and not allowed: (?:/|^)(?!\\.)\n //\n // But it's better to have a simpler binding without a conditional, for\n // performance, so probably better to return both start options.\n //\n // Then the caller just ignores the end if it's not the first pattern,\n // and the start always gets applied.\n //\n // But that's always going to be $ if it's the ending pattern, or nothing,\n // so the caller can just attach $ at the end of the pattern when building.\n //\n // So the todo is:\n // - better detect what kind of start is needed\n // - return both flavors of starting pattern\n // - attach $ at the end of the pattern when creating the actual RegExp\n //\n // Ah, but wait, no, that all only applies to the root when the first pattern\n // is not an extglob. If the first pattern IS an extglob, then we need all\n // that dot prevention biz to live in the extglob portions, because eg\n // +(*|.x*) can match .xy but not .yx.\n //\n // So, return the two flavors if it's #root and the first child is not an\n // AST, otherwise leave it to the child AST to handle it, and there,\n // use the (?:^|/) style of start binding.\n //\n // Even simplified further:\n // - Since the start for a join is eg /(?!\\.) and the start for a part\n // is ^(?!\\.), we can just prepend (?!\\.) to the pattern (either root\n // or start or whatever) and prepend ^ or / at the Regexp construction.\n toRegExpSource(\n allowDot?: boolean,\n ): [re: string, body: string, hasMagic: boolean, uflag: boolean] {\n const dot = allowDot ?? !!this.#options.dot\n if (this.#root === this) this.#fillNegs()\n if (!this.type) {\n const noEmpty =\n this.isStart() &&\n this.isEnd() &&\n !this.#parts.some(s => typeof s !== 'string')\n const src = this.#parts\n .map(p => {\n const [re, _, hasMagic, uflag] =\n typeof p === 'string' ?\n AST.#parseGlob(p, this.#hasMagic, noEmpty)\n : p.toRegExpSource(allowDot)\n this.#hasMagic = this.#hasMagic || hasMagic\n this.#uflag = this.#uflag || uflag\n return re\n })\n .join('')\n\n let start = ''\n if (this.isStart()) {\n if (typeof this.#parts[0] === 'string') {\n // this is the string that will match the start of the pattern,\n // so we need to protect against dots and such.\n\n // '.' and '..' cannot match unless the pattern is that exactly,\n // even if it starts with . or dot:true is set.\n const dotTravAllowed =\n this.#parts.length === 1 && justDots.has(this.#parts[0])\n if (!dotTravAllowed) {\n const aps = addPatternStart\n // check if we have a possibility of matching . or ..,\n // and prevent that.\n const needNoTrav =\n // dots are allowed, and the pattern starts with [ or .\n (dot && aps.has(src.charAt(0))) ||\n // the pattern starts with \\., and then [ or .\n (src.startsWith('\\\\.') && aps.has(src.charAt(2))) ||\n // the pattern starts with \\.\\., and then [ or .\n (src.startsWith('\\\\.\\\\.') && aps.has(src.charAt(4)))\n // no need to prevent dots if it can't match a dot, or if a\n // sub-pattern will be preventing it anyway.\n const needNoDot = !dot && !allowDot && aps.has(src.charAt(0))\n\n start =\n needNoTrav ? startNoTraversal\n : needNoDot ? startNoDot\n : ''\n }\n }\n }\n\n // append the \"end of path portion\" pattern to negation tails\n let end = ''\n if (\n this.isEnd() &&\n this.#root.#filledNegs &&\n this.#parent?.type === '!'\n ) {\n end = '(?:$|\\\\/)'\n }\n const final = start + src + end\n return [\n final,\n unescape(src),\n (this.#hasMagic = !!this.#hasMagic),\n this.#uflag,\n ]\n }\n\n // We need to calculate the body *twice* if it's a repeat pattern\n // at the start, once in nodot mode, then again in dot mode, so a\n // pattern like *(?) can match 'x.y'\n\n const repeated = this.type === '*' || this.type === '+'\n // some kind of extglob\n const start = this.type === '!' ? '(?:(?!(?:' : '(?:'\n let body = this.#partsToRegExp(dot)\n\n if (this.isStart() && this.isEnd() && !body && this.type !== '!') {\n // invalid extglob, has to at least be *something* present, if it's\n // the entire path portion.\n const s = this.toString()\n this.#parts = [s]\n this.type = null\n this.#hasMagic = undefined\n return [s, unescape(this.toString()), false, false]\n }\n\n // XXX abstract out this map method\n let bodyDotAllowed =\n !repeated || allowDot || dot || !startNoDot ?\n ''\n : this.#partsToRegExp(true)\n if (bodyDotAllowed === body) {\n bodyDotAllowed = ''\n }\n if (bodyDotAllowed) {\n body = `(?:${body})(?:${bodyDotAllowed})*?`\n }\n\n // an empty !() is exactly equivalent to a starNoEmpty\n let final = ''\n if (this.type === '!' && this.#emptyExt) {\n final = (this.isStart() && !dot ? startNoDot : '') + starNoEmpty\n } else {\n const close =\n this.type === '!' ?\n // !() must match something,but !(x) can match ''\n '))' +\n (this.isStart() && !dot && !allowDot ? startNoDot : '') +\n star +\n ')'\n : this.type === '@' ? ')'\n : this.type === '?' ? ')?'\n : this.type === '+' && bodyDotAllowed ? ')'\n : this.type === '*' && bodyDotAllowed ? `)?`\n : `)${this.type}`\n final = start + body + close\n }\n return [\n final,\n unescape(body),\n (this.#hasMagic = !!this.#hasMagic),\n this.#uflag,\n ]\n }\n\n #partsToRegExp(dot: boolean) {\n return this.#parts\n .map(p => {\n // extglob ASTs should only contain parent ASTs\n /* c8 ignore start */\n if (typeof p === 'string') {\n throw new Error('string type in extglob ast??')\n }\n /* c8 ignore stop */\n // can ignore hasMagic, because extglobs are already always magic\n const [re, _, _hasMagic, uflag] = p.toRegExpSource(dot)\n this.#uflag = this.#uflag || uflag\n return re\n })\n .filter(p => !(this.isStart() && this.isEnd()) || !!p)\n .join('|')\n }\n\n static #parseGlob(\n glob: string,\n hasMagic: boolean | undefined,\n noEmpty: boolean = false,\n ): [re: string, body: string, hasMagic: boolean, uflag: boolean] {\n let escaping = false\n let re = ''\n let uflag = false\n // multiple stars that aren't globstars coalesce into one *\n let inStar = false\n for (let i = 0; i < glob.length; i++) {\n const c = glob.charAt(i)\n if (escaping) {\n escaping = false\n re += (reSpecials.has(c) ? '\\\\' : '') + c\n continue\n }\n if (c === '*') {\n if (inStar) continue\n inStar = true\n re += noEmpty && /^[*]+$/.test(glob) ? starNoEmpty : star\n hasMagic = true\n continue\n } else {\n inStar = false\n }\n if (c === '\\\\') {\n if (i === glob.length - 1) {\n re += '\\\\\\\\'\n } else {\n escaping = true\n }\n continue\n }\n if (c === '[') {\n const [src, needUflag, consumed, magic] = parseClass(glob, i)\n if (consumed) {\n re += src\n uflag = uflag || needUflag\n i += consumed - 1\n hasMagic = hasMagic || magic\n continue\n }\n }\n if (c === '?') {\n re += qmark\n hasMagic = true\n continue\n }\n re += regExpEscape(c)\n }\n return [re, unescape(glob), !!hasMagic, uflag]\n }\n}\n","import { MinimatchOptions } from './index.js'\n\n/**\n * Escape all magic characters in a glob pattern.\n *\n * If the {@link MinimatchOptions.windowsPathsNoEscape}\n * option is used, then characters are escaped by wrapping in `[]`, because\n * a magic character wrapped in a character class can only be satisfied by\n * that exact character. In this mode, `\\` is _not_ escaped, because it is\n * not interpreted as a magic character, but instead as a path separator.\n *\n * If the {@link MinimatchOptions.magicalBraces} option is used,\n * then braces (`{` and `}`) will be escaped.\n */\nexport const escape = (\n s: string,\n {\n windowsPathsNoEscape = false,\n magicalBraces = false,\n }: Pick<MinimatchOptions, 'windowsPathsNoEscape' | 'magicalBraces'> = {},\n) => {\n // don't need to escape +@! because we escape the parens\n // that make those magic, and escaping ! as [!] isn't valid,\n // because [!]] is a valid glob class meaning not ']'.\n if (magicalBraces) {\n return windowsPathsNoEscape ?\n s.replace(/[?*()[\\]{}]/g, '[$&]')\n : s.replace(/[?*()[\\]\\\\{}]/g, '\\\\$&')\n }\n return windowsPathsNoEscape ?\n s.replace(/[?*()[\\]]/g, '[$&]')\n : s.replace(/[?*()[\\]\\\\]/g, '\\\\$&')\n}\n","import { expand } from 'brace-expansion'\nimport { assertValidPattern } from './assert-valid-pattern.js'\nimport { AST, ExtglobType } from './ast.js'\nimport { escape } from './escape.js'\nimport { unescape } from './unescape.js'\n\nexport type Platform =\n | 'aix'\n | 'android'\n | 'darwin'\n | 'freebsd'\n | 'haiku'\n | 'linux'\n | 'openbsd'\n | 'sunos'\n | 'win32'\n | 'cygwin'\n | 'netbsd'\n\nexport interface MinimatchOptions {\n /** do not expand `{x,y}` style braces */\n nobrace?: boolean\n /** do not treat patterns starting with `#` as a comment */\n nocomment?: boolean\n /** do not treat patterns starting with `!` as a negation */\n nonegate?: boolean\n /** print LOTS of debugging output */\n debug?: boolean\n /** treat `**` the same as `*` */\n noglobstar?: boolean\n /** do not expand extglobs like `+(a|b)` */\n noext?: boolean\n /** return the pattern if nothing matches */\n nonull?: boolean\n /** treat `\\\\` as a path separator, not an escape character */\n windowsPathsNoEscape?: boolean\n /**\n * inverse of {@link MinimatchOptions.windowsPathsNoEscape}\n * @deprecated\n */\n allowWindowsEscape?: boolean\n /**\n * Compare a partial path to a pattern. As long as the parts\n * of the path that are present are not contradicted by the\n * pattern, it will be treated as a match. This is useful in\n * applications where you're walking through a folder structure,\n * and don't yet have the full path, but want to ensure that you\n * do not walk down paths that can never be a match.\n */\n partial?: boolean\n /** allow matches that start with `.` even if the pattern does not */\n dot?: boolean\n /** ignore case */\n nocase?: boolean\n /** ignore case only in wildcard patterns */\n nocaseMagicOnly?: boolean\n /** consider braces to be \"magic\" for the purpose of `hasMagic` */\n magicalBraces?: boolean\n /**\n * If set, then patterns without slashes will be matched\n * against the basename of the path if it contains slashes.\n * For example, `a?b` would match the path `/xyz/123/acb`, but\n * not `/xyz/acb/123`.\n */\n matchBase?: boolean\n /** invert the results of negated matches */\n flipNegate?: boolean\n /** do not collapse multiple `/` into a single `/` */\n preserveMultipleSlashes?: boolean\n /**\n * A number indicating the level of optimization that should be done\n * to the pattern prior to parsing and using it for matches.\n */\n optimizationLevel?: number\n /** operating system platform */\n platform?: Platform\n /**\n * When a pattern starts with a UNC path or drive letter, and in\n * `nocase:true` mode, do not convert the root portions of the\n * pattern into a case-insensitive regular expression, and instead\n * leave them as strings.\n *\n * This is the default when the platform is `win32` and\n * `nocase:true` is set.\n */\n windowsNoMagicRoot?: boolean\n /**\n * max number of `{...}` patterns to expand. Default 100_000.\n */\n braceExpandMax?: number\n}\n\nexport const minimatch = (\n p: string,\n pattern: string,\n options: MinimatchOptions = {},\n) => {\n assertValidPattern(pattern)\n\n // shortcut: comments match nothing.\n if (!options.nocomment && pattern.charAt(0) === '#') {\n return false\n }\n\n return new Minimatch(pattern, options).match(p)\n}\n\n// Optimized checking for the most common glob patterns.\nconst starDotExtRE = /^\\*+([^+@!?\\*\\[\\(]*)$/\nconst starDotExtTest = (ext: string) => (f: string) =>\n !f.startsWith('.') && f.endsWith(ext)\nconst starDotExtTestDot = (ext: string) => (f: string) => f.endsWith(ext)\nconst starDotExtTestNocase = (ext: string) => {\n ext = ext.toLowerCase()\n return (f: string) => !f.startsWith('.') && f.toLowerCase().endsWith(ext)\n}\nconst starDotExtTestNocaseDot = (ext: string) => {\n ext = ext.toLowerCase()\n return (f: string) => f.toLowerCase().endsWith(ext)\n}\nconst starDotStarRE = /^\\*+\\.\\*+$/\nconst starDotStarTest = (f: string) =>\n !f.startsWith('.') && f.includes('.')\nconst starDotStarTestDot = (f: string) =>\n f !== '.' && f !== '..' && f.includes('.')\nconst dotStarRE = /^\\.\\*+$/\nconst dotStarTest = (f: string) =>\n f !== '.' && f !== '..' && f.startsWith('.')\nconst starRE = /^\\*+$/\nconst starTest = (f: string) => f.length !== 0 && !f.startsWith('.')\nconst starTestDot = (f: string) =>\n f.length !== 0 && f !== '.' && f !== '..'\nconst qmarksRE = /^\\?+([^+@!?\\*\\[\\(]*)?$/\nconst qmarksTestNocase = ([$0, ext = '']: RegExpMatchArray) => {\n const noext = qmarksTestNoExt([$0])\n if (!ext) return noext\n ext = ext.toLowerCase()\n return (f: string) => noext(f) && f.toLowerCase().endsWith(ext)\n}\nconst qmarksTestNocaseDot = ([$0, ext = '']: RegExpMatchArray) => {\n const noext = qmarksTestNoExtDot([$0])\n if (!ext) return noext\n ext = ext.toLowerCase()\n return (f: string) => noext(f) && f.toLowerCase().endsWith(ext)\n}\nconst qmarksTestDot = ([$0, ext = '']: RegExpMatchArray) => {\n const noext = qmarksTestNoExtDot([$0])\n return !ext ? noext : (f: string) => noext(f) && f.endsWith(ext)\n}\nconst qmarksTest = ([$0, ext = '']: RegExpMatchArray) => {\n const noext = qmarksTestNoExt([$0])\n return !ext ? noext : (f: string) => noext(f) && f.endsWith(ext)\n}\nconst qmarksTestNoExt = ([$0]: RegExpMatchArray) => {\n const len = $0.length\n return (f: string) => f.length === len && !f.startsWith('.')\n}\nconst qmarksTestNoExtDot = ([$0]: RegExpMatchArray) => {\n const len = $0.length\n return (f: string) => f.length === len && f !== '.' && f !== '..'\n}\n\n/* c8 ignore start */\nconst defaultPlatform: Platform = (\n typeof process === 'object' && process ?\n (typeof process.env === 'object' &&\n process.env &&\n process.env.__MINIMATCH_TESTING_PLATFORM__) ||\n process.platform\n : 'posix') as Platform\n\nexport type Sep = '\\\\' | '/'\n\nconst path: { [k: string]: { sep: Sep } } = {\n win32: { sep: '\\\\' },\n posix: { sep: '/' },\n}\n/* c8 ignore stop */\n\nexport const sep =\n defaultPlatform === 'win32' ? path.win32.sep : path.posix.sep\nminimatch.sep = sep\n\nexport const GLOBSTAR = Symbol('globstar **')\nminimatch.GLOBSTAR = GLOBSTAR\n\n// any single thing other than /\n// don't need to escape / when using new RegExp()\nconst qmark = '[^/]'\n\n// * => any number of characters\nconst star = qmark + '*?'\n\n// ** when dots are allowed. Anything goes, except .. and .\n// not (^ or / followed by one or two dots followed by $ or /),\n// followed by anything, any number of times.\nconst twoStarDot = '(?:(?!(?:\\\\/|^)(?:\\\\.{1,2})($|\\\\/)).)*?'\n\n// not a ^ or / followed by a dot,\n// followed by anything, any number of times.\nconst twoStarNoDot = '(?:(?!(?:\\\\/|^)\\\\.).)*?'\n\nexport const filter =\n (pattern: string, options: MinimatchOptions = {}) =>\n (p: string) =>\n minimatch(p, pattern, options)\nminimatch.filter = filter\n\nconst ext = (a: MinimatchOptions, b: MinimatchOptions = {}) =>\n Object.assign({}, a, b)\n\nexport const defaults = (def: MinimatchOptions): typeof minimatch => {\n if (!def || typeof def !== 'object' || !Object.keys(def).length) {\n return minimatch\n }\n\n const orig = minimatch\n\n const m = (p: string, pattern: string, options: MinimatchOptions = {}) =>\n orig(p, pattern, ext(def, options))\n\n return Object.assign(m, {\n Minimatch: class Minimatch extends orig.Minimatch {\n constructor(pattern: string, options: MinimatchOptions = {}) {\n super(pattern, ext(def, options))\n }\n static defaults(options: MinimatchOptions) {\n return orig.defaults(ext(def, options)).Minimatch\n }\n },\n\n AST: class AST extends orig.AST {\n /* c8 ignore start */\n constructor(\n type: ExtglobType | null,\n parent?: AST,\n options: MinimatchOptions = {},\n ) {\n super(type, parent, ext(def, options))\n }\n /* c8 ignore stop */\n\n static fromGlob(pattern: string, options: MinimatchOptions = {}) {\n return orig.AST.fromGlob(pattern, ext(def, options))\n }\n },\n\n unescape: (\n s: string,\n options: Pick<\n MinimatchOptions,\n 'windowsPathsNoEscape' | 'magicalBraces'\n > = {},\n ) => orig.unescape(s, ext(def, options)),\n\n escape: (\n s: string,\n options: Pick<\n MinimatchOptions,\n 'windowsPathsNoEscape' | 'magicalBraces'\n > = {},\n ) => orig.escape(s, ext(def, options)),\n\n filter: (pattern: string, options: MinimatchOptions = {}) =>\n orig.filter(pattern, ext(def, options)),\n\n defaults: (options: MinimatchOptions) =>\n orig.defaults(ext(def, options)),\n\n makeRe: (pattern: string, options: MinimatchOptions = {}) =>\n orig.makeRe(pattern, ext(def, options)),\n\n braceExpand: (pattern: string, options: MinimatchOptions = {}) =>\n orig.braceExpand(pattern, ext(def, options)),\n\n match: (\n list: string[],\n pattern: string,\n options: MinimatchOptions = {},\n ) => orig.match(list, pattern, ext(def, options)),\n\n sep: orig.sep,\n GLOBSTAR: GLOBSTAR as typeof GLOBSTAR,\n })\n}\nminimatch.defaults = defaults\n\n// Brace expansion:\n// a{b,c}d -> abd acd\n// a{b,}c -> abc ac\n// a{0..3}d -> a0d a1d a2d a3d\n// a{b,c{d,e}f}g -> abg acdfg acefg\n// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg\n//\n// Invalid sets are not expanded.\n// a{2..}b -> a{2..}b\n// a{b}c -> a{b}c\nexport const braceExpand = (\n pattern: string,\n options: MinimatchOptions = {},\n) => {\n assertValidPattern(pattern)\n\n // Thanks to Yeting Li <https://github.com/yetingli> for\n // improving this regexp to avoid a ReDOS vulnerability.\n if (options.nobrace || !/\\{(?:(?!\\{).)*\\}/.test(pattern)) {\n // shortcut. no need to expand.\n return [pattern]\n }\n\n return expand(pattern, { max: options.braceExpandMax })\n}\nminimatch.braceExpand = braceExpand\n\n// parse a component of the expanded set.\n// At this point, no pattern may contain \"/\" in it\n// so we're going to return a 2d array, where each entry is the full\n// pattern, split on '/', and then turned into a regular expression.\n// A regexp is made at the end which joins each array with an\n// escaped /, and another full one which joins each regexp with |.\n//\n// Following the lead of Bash 4.1, note that \"**\" only has special meaning\n// when it is the *only* thing in a path portion. Otherwise, any series\n// of * is equivalent to a single *. Globstar behavior is enabled by\n// default, and can be disabled by setting options.noglobstar.\n\nexport const makeRe = (pattern: string, options: MinimatchOptions = {}) =>\n new Minimatch(pattern, options).makeRe()\nminimatch.makeRe = makeRe\n\nexport const match = (\n list: string[],\n pattern: string,\n options: MinimatchOptions = {},\n) => {\n const mm = new Minimatch(pattern, options)\n list = list.filter(f => mm.match(f))\n if (mm.options.nonull && !list.length) {\n list.push(pattern)\n }\n return list\n}\nminimatch.match = match\n\n// replace stuff like \\* with *\nconst globMagic = /[?*]|[+@!]\\(.*?\\)|\\[|\\]/\nconst regExpEscape = (s: string) =>\n s.replace(/[-[\\]{}()*+?.,\\\\^$|#\\s]/g, '\\\\$&')\n\nexport type MMRegExp = RegExp & {\n _src?: string\n _glob?: string\n}\n\nexport type ParseReturnFiltered = string | MMRegExp | typeof GLOBSTAR\nexport type ParseReturn = ParseReturnFiltered | false\n\nexport class Minimatch {\n options: MinimatchOptions\n set: ParseReturnFiltered[][]\n pattern: string\n\n windowsPathsNoEscape: boolean\n nonegate: boolean\n negate: boolean\n comment: boolean\n empty: boolean\n preserveMultipleSlashes: boolean\n partial: boolean\n globSet: string[]\n globParts: string[][]\n nocase: boolean\n\n isWindows: boolean\n platform: Platform\n windowsNoMagicRoot: boolean\n\n regexp: false | null | MMRegExp\n constructor(pattern: string, options: MinimatchOptions = {}) {\n assertValidPattern(pattern)\n\n options = options || {}\n this.options = options\n this.pattern = pattern\n this.platform = options.platform || defaultPlatform\n this.isWindows = this.platform === 'win32'\n // avoid the annoying deprecation flag lol\n const awe = ('allowWindow' + 'sEscape') as keyof MinimatchOptions\n this.windowsPathsNoEscape =\n !!options.windowsPathsNoEscape || options[awe] === false\n if (this.windowsPathsNoEscape) {\n this.pattern = this.pattern.replace(/\\\\/g, '/')\n }\n this.preserveMultipleSlashes = !!options.preserveMultipleSlashes\n this.regexp = null\n this.negate = false\n this.nonegate = !!options.nonegate\n this.comment = false\n this.empty = false\n this.partial = !!options.partial\n this.nocase = !!this.options.nocase\n this.windowsNoMagicRoot =\n options.windowsNoMagicRoot !== undefined ?\n options.windowsNoMagicRoot\n : !!(this.isWindows && this.nocase)\n\n this.globSet = []\n this.globParts = []\n this.set = []\n\n // make the set of regexps etc.\n this.make()\n }\n\n hasMagic(): boolean {\n if (this.options.magicalBraces && this.set.length > 1) {\n return true\n }\n for (const pattern of this.set) {\n for (const part of pattern) {\n if (typeof part !== 'string') return true\n }\n }\n return false\n }\n\n debug(..._: any[]) {}\n\n make() {\n const pattern = this.pattern\n const options = this.options\n\n // empty patterns and comments match nothing.\n if (!options.nocomment && pattern.charAt(0) === '#') {\n this.comment = true\n return\n }\n\n if (!pattern) {\n this.empty = true\n return\n }\n\n // step 1: figure out negation, etc.\n this.parseNegate()\n\n // step 2: expand braces\n this.globSet = [...new Set(this.braceExpand())]\n\n if (options.debug) {\n this.debug = (...args: any[]) => console.error(...args)\n }\n\n this.debug(this.pattern, this.globSet)\n\n // step 3: now we have a set, so turn each one into a series of\n // path-portion matching patterns.\n // These will be regexps, except in the case of \"**\", which is\n // set to the GLOBSTAR object for globstar behavior,\n // and will not contain any / characters\n //\n // First, we preprocess to make the glob pattern sets a bit simpler\n // and deduped. There are some perf-killing patterns that can cause\n // problems with a glob walk, but we can simplify them down a bit.\n const rawGlobParts = this.globSet.map(s => this.slashSplit(s))\n this.globParts = this.preprocess(rawGlobParts)\n this.debug(this.pattern, this.globParts)\n\n // glob --> regexps\n let set = this.globParts.map((s, _, __) => {\n if (this.isWindows && this.windowsNoMagicRoot) {\n // check if it's a drive or unc path.\n const isUNC =\n s[0] === '' &&\n s[1] === '' &&\n (s[2] === '?' || !globMagic.test(s[2])) &&\n !globMagic.test(s[3])\n const isDrive = /^[a-z]:/i.test(s[0])\n if (isUNC) {\n return [\n ...s.slice(0, 4),\n ...s.slice(4).map(ss => this.parse(ss)),\n ]\n } else if (isDrive) {\n return [s[0], ...s.slice(1).map(ss => this.parse(ss))]\n }\n }\n return s.map(ss => this.parse(ss))\n })\n\n this.debug(this.pattern, set)\n\n // filter out everything that didn't compile properly.\n this.set = set.filter(\n s => s.indexOf(false) === -1,\n ) as ParseReturnFiltered[][]\n\n // do not treat the ? in UNC paths as magic\n if (this.isWindows) {\n for (let i = 0; i < this.set.length; i++) {\n const p = this.set[i]\n if (\n p[0] === '' &&\n p[1] === '' &&\n this.globParts[i][2] === '?' &&\n typeof p[3] === 'string' &&\n /^[a-z]:$/i.test(p[3])\n ) {\n p[2] = '?'\n }\n }\n }\n\n this.debug(this.pattern, this.set)\n }\n\n // various transforms to equivalent pattern sets that are\n // faster to process in a filesystem walk. The goal is to\n // eliminate what we can, and push all ** patterns as far\n // to the right as possible, even if it increases the number\n // of patterns that we have to process.\n preprocess(globParts: string[][]) {\n // if we're not in globstar mode, then turn ** into *\n if (this.options.noglobstar) {\n for (let i = 0; i < globParts.length; i++) {\n for (let j = 0; j < globParts[i].length; j++) {\n if (globParts[i][j] === '**') {\n globParts[i][j] = '*'\n }\n }\n }\n }\n\n const { optimizationLevel = 1 } = this.options\n\n if (optimizationLevel >= 2) {\n // aggressive optimization for the purpose of fs walking\n globParts = this.firstPhasePreProcess(globParts)\n globParts = this.secondPhasePreProcess(globParts)\n } else if (optimizationLevel >= 1) {\n // just basic optimizations to remove some .. parts\n globParts = this.levelOneOptimize(globParts)\n } else {\n // just collapse multiple ** portions into one\n globParts = this.adjascentGlobstarOptimize(globParts)\n }\n\n return globParts\n }\n\n // just get rid of adjascent ** portions\n adjascentGlobstarOptimize(globParts: string[][]) {\n return globParts.map(parts => {\n let gs: number = -1\n while (-1 !== (gs = parts.indexOf('**', gs + 1))) {\n let i = gs\n while (parts[i + 1] === '**') {\n i++\n }\n if (i !== gs) {\n parts.splice(gs, i - gs)\n }\n }\n return parts\n })\n }\n\n // get rid of adjascent ** and resolve .. portions\n levelOneOptimize(globParts: string[][]) {\n return globParts.map(parts => {\n parts = parts.reduce((set: string[], part) => {\n const prev = set[set.length - 1]\n if (part === '**' && prev === '**') {\n return set\n }\n if (part === '..') {\n if (prev && prev !== '..' && prev !== '.' && prev !== '**') {\n set.pop()\n return set\n }\n }\n set.push(part)\n return set\n }, [])\n return parts.length === 0 ? [''] : parts\n })\n }\n\n levelTwoFileOptimize(parts: string | string[]) {\n if (!Array.isArray(parts)) {\n parts = this.slashSplit(parts)\n }\n let didSomething: boolean = false\n do {\n didSomething = false\n // <pre>/<e>/<rest> -> <pre>/<rest>\n if (!this.preserveMultipleSlashes) {\n for (let i = 1; i < parts.length - 1; i++) {\n const p = parts[i]\n // don't squeeze out UNC patterns\n if (i === 1 && p === '' && parts[0] === '') continue\n if (p === '.' || p === '') {\n didSomething = true\n parts.splice(i, 1)\n i--\n }\n }\n if (\n parts[0] === '.' &&\n parts.length === 2 &&\n (parts[1] === '.' || parts[1] === '')\n ) {\n didSomething = true\n parts.pop()\n }\n }\n\n // <pre>/<p>/../<rest> -> <pre>/<rest>\n let dd: number = 0\n while (-1 !== (dd = parts.indexOf('..', dd + 1))) {\n const p = parts[dd - 1]\n if (p && p !== '.' && p !== '..' && p !== '**') {\n didSomething = true\n parts.splice(dd - 1, 2)\n dd -= 2\n }\n }\n } while (didSomething)\n return parts.length === 0 ? [''] : parts\n }\n\n // First phase: single-pattern processing\n // <pre> is 1 or more portions\n // <rest> is 1 or more portions\n // <p> is any portion other than ., .., '', or **\n // <e> is . or ''\n //\n // **/.. is *brutal* for filesystem walking performance, because\n // it effectively resets the recursive walk each time it occurs,\n // and ** cannot be reduced out by a .. pattern part like a regexp\n // or most strings (other than .., ., and '') can be.\n //\n // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}\n // <pre>/<e>/<rest> -> <pre>/<rest>\n // <pre>/<p>/../<rest> -> <pre>/<rest>\n // **/**/<rest> -> **/<rest>\n //\n // **/*/<rest> -> */**/<rest> <== not valid because ** doesn't follow\n // this WOULD be allowed if ** did follow symlinks, or * didn't\n firstPhasePreProcess(globParts: string[][]) {\n let didSomething = false\n do {\n didSomething = false\n // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}\n for (let parts of globParts) {\n let gs: number = -1\n while (-1 !== (gs = parts.indexOf('**', gs + 1))) {\n let gss: number = gs\n while (parts[gss + 1] === '**') {\n // <pre>/**/**/<rest> -> <pre>/**/<rest>\n gss++\n }\n // eg, if gs is 2 and gss is 4, that means we have 3 **\n // parts, and can remove 2 of them.\n if (gss > gs) {\n parts.splice(gs + 1, gss - gs)\n }\n\n let next = parts[gs + 1]\n const p = parts[gs + 2]\n const p2 = parts[gs + 3]\n if (next !== '..') continue\n if (\n !p ||\n p === '.' ||\n p === '..' ||\n !p2 ||\n p2 === '.' ||\n p2 === '..'\n ) {\n continue\n }\n didSomething = true\n // edit parts in place, and push the new one\n parts.splice(gs, 1)\n const other = parts.slice(0)\n other[gs] = '**'\n globParts.push(other)\n gs--\n }\n\n // <pre>/<e>/<rest> -> <pre>/<rest>\n if (!this.preserveMultipleSlashes) {\n for (let i = 1; i < parts.length - 1; i++) {\n const p = parts[i]\n // don't squeeze out UNC patterns\n if (i === 1 && p === '' && parts[0] === '') continue\n if (p === '.' || p === '') {\n didSomething = true\n parts.splice(i, 1)\n i--\n }\n }\n if (\n parts[0] === '.' &&\n parts.length === 2 &&\n (parts[1] === '.' || parts[1] === '')\n ) {\n didSomething = true\n parts.pop()\n }\n }\n\n // <pre>/<p>/../<rest> -> <pre>/<rest>\n let dd: number = 0\n while (-1 !== (dd = parts.indexOf('..', dd + 1))) {\n const p = parts[dd - 1]\n if (p && p !== '.' && p !== '..' && p !== '**') {\n didSomething = true\n const needDot = dd === 1 && parts[dd + 1] === '**'\n const splin = needDot ? ['.'] : []\n parts.splice(dd - 1, 2, ...splin)\n if (parts.length === 0) parts.push('')\n dd -= 2\n }\n }\n }\n } while (didSomething)\n\n return globParts\n }\n\n // second phase: multi-pattern dedupes\n // {<pre>/*/<rest>,<pre>/<p>/<rest>} -> <pre>/*/<rest>\n // {<pre>/<rest>,<pre>/<rest>} -> <pre>/<rest>\n // {<pre>/**/<rest>,<pre>/<rest>} -> <pre>/**/<rest>\n //\n // {<pre>/**/<rest>,<pre>/**/<p>/<rest>} -> <pre>/**/<rest>\n // ^-- not valid because ** doens't follow symlinks\n secondPhasePreProcess(globParts: string[][]): string[][] {\n for (let i = 0; i < globParts.length - 1; i++) {\n for (let j = i + 1; j < globParts.length; j++) {\n const matched = this.partsMatch(\n globParts[i],\n globParts[j],\n !this.preserveMultipleSlashes,\n )\n if (matched) {\n globParts[i] = []\n globParts[j] = matched\n break\n }\n }\n }\n return globParts.filter(gs => gs.length)\n }\n\n partsMatch(\n a: string[],\n b: string[],\n emptyGSMatch: boolean = false,\n ): false | string[] {\n let ai = 0\n let bi = 0\n let result: string[] = []\n let which: string = ''\n while (ai < a.length && bi < b.length) {\n if (a[ai] === b[bi]) {\n result.push(which === 'b' ? b[bi] : a[ai])\n ai++\n bi++\n } else if (emptyGSMatch && a[ai] === '**' && b[bi] === a[ai + 1]) {\n result.push(a[ai])\n ai++\n } else if (emptyGSMatch && b[bi] === '**' && a[ai] === b[bi + 1]) {\n result.push(b[bi])\n bi++\n } else if (\n a[ai] === '*' &&\n b[bi] &&\n (this.options.dot || !b[bi].startsWith('.')) &&\n b[bi] !== '**'\n ) {\n if (which === 'b') return false\n which = 'a'\n result.push(a[ai])\n ai++\n bi++\n } else if (\n b[bi] === '*' &&\n a[ai] &&\n (this.options.dot || !a[ai].startsWith('.')) &&\n a[ai] !== '**'\n ) {\n if (which === 'a') return false\n which = 'b'\n result.push(b[bi])\n ai++\n bi++\n } else {\n return false\n }\n }\n // if we fall out of the loop, it means they two are identical\n // as long as their lengths match\n return a.length === b.length && result\n }\n\n parseNegate() {\n if (this.nonegate) return\n\n const pattern = this.pattern\n let negate = false\n let negateOffset = 0\n\n for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {\n negate = !negate\n negateOffset++\n }\n\n if (negateOffset) this.pattern = pattern.slice(negateOffset)\n this.negate = negate\n }\n\n // set partial to true to test if, for example,\n // \"/a/b\" matches the start of \"/*/b/*/d\"\n // Partial means, if you run out of file before you run\n // out of pattern, then that's fine, as long as all\n // the parts match.\n matchOne(\n file: string[],\n pattern: ParseReturn[],\n partial: boolean = false,\n ) {\n const options = this.options\n\n // UNC paths like //?/X:/... can match X:/... and vice versa\n // Drive letters in absolute drive or unc paths are always compared\n // case-insensitively.\n if (this.isWindows) {\n const fileDrive =\n typeof file[0] === 'string' && /^[a-z]:$/i.test(file[0])\n const fileUNC =\n !fileDrive &&\n file[0] === '' &&\n file[1] === '' &&\n file[2] === '?' &&\n /^[a-z]:$/i.test(file[3])\n\n const patternDrive =\n typeof pattern[0] === 'string' && /^[a-z]:$/i.test(pattern[0])\n const patternUNC =\n !patternDrive &&\n pattern[0] === '' &&\n pattern[1] === '' &&\n pattern[2] === '?' &&\n typeof pattern[3] === 'string' &&\n /^[a-z]:$/i.test(pattern[3])\n\n const fdi =\n fileUNC ? 3\n : fileDrive ? 0\n : undefined\n const pdi =\n patternUNC ? 3\n : patternDrive ? 0\n : undefined\n if (typeof fdi === 'number' && typeof pdi === 'number') {\n const [fd, pd]: [string, string] = [\n file[fdi],\n pattern[pdi] as string,\n ]\n if (fd.toLowerCase() === pd.toLowerCase()) {\n pattern[pdi] = fd\n if (pdi > fdi) {\n pattern = pattern.slice(pdi)\n } else if (fdi > pdi) {\n file = file.slice(fdi)\n }\n }\n }\n }\n\n // resolve and reduce . and .. portions in the file as well.\n // don't need to do the second phase, because it's only one string[]\n const { optimizationLevel = 1 } = this.options\n if (optimizationLevel >= 2) {\n file = this.levelTwoFileOptimize(file)\n }\n\n this.debug('matchOne', this, { file, pattern })\n this.debug('matchOne', file.length, pattern.length)\n\n for (\n var fi = 0, pi = 0, fl = file.length, pl = pattern.length;\n fi < fl && pi < pl;\n fi++, pi++\n ) {\n this.debug('matchOne loop')\n var p = pattern[pi]\n var f = file[fi]\n\n this.debug(pattern, p, f)\n\n // should be impossible.\n // some invalid regexp stuff in the set.\n /* c8 ignore start */\n if (p === false) {\n return false\n }\n /* c8 ignore stop */\n\n if (p === GLOBSTAR) {\n this.debug('GLOBSTAR', [pattern, p, f])\n\n // \"**\"\n // a/**/b/**/c would match the following:\n // a/b/x/y/z/c\n // a/x/y/z/b/c\n // a/b/x/b/x/c\n // a/b/c\n // To do this, take the rest of the pattern after\n // the **, and see if it would match the file remainder.\n // If so, return success.\n // If not, the ** \"swallows\" a segment, and try again.\n // This is recursively awful.\n //\n // a/**/b/**/c matching a/b/x/y/z/c\n // - a matches a\n // - doublestar\n // - matchOne(b/x/y/z/c, b/**/c)\n // - b matches b\n // - doublestar\n // - matchOne(x/y/z/c, c) -> no\n // - matchOne(y/z/c, c) -> no\n // - matchOne(z/c, c) -> no\n // - matchOne(c, c) yes, hit\n var fr = fi\n var pr = pi + 1\n if (pr === pl) {\n this.debug('** at the end')\n // a ** at the end will just swallow the rest.\n // We have found a match.\n // however, it will not swallow /.x, unless\n // options.dot is set.\n // . and .. are *never* matched by **, for explosively\n // exponential reasons.\n for (; fi < fl; fi++) {\n if (\n file[fi] === '.' ||\n file[fi] === '..' ||\n (!options.dot && file[fi].charAt(0) === '.')\n )\n return false\n }\n return true\n }\n\n // ok, let's see if we can swallow whatever we can.\n while (fr < fl) {\n var swallowee = file[fr]\n\n this.debug('\\nglobstar while', file, fr, pattern, pr, swallowee)\n\n // XXX remove this slice. Just pass the start index.\n if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {\n this.debug('globstar found match!', fr, fl, swallowee)\n // found a match.\n return true\n } else {\n // can't swallow \".\" or \"..\" ever.\n // can only swallow \".foo\" when explicitly asked.\n if (\n swallowee === '.' ||\n swallowee === '..' ||\n (!options.dot && swallowee.charAt(0) === '.')\n ) {\n this.debug('dot detected!', file, fr, pattern, pr)\n break\n }\n\n // ** swallows a segment, and continue.\n this.debug('globstar swallow a segment, and continue')\n fr++\n }\n }\n\n // no match was found.\n // However, in partial mode, we can't say this is necessarily over.\n /* c8 ignore start */\n if (partial) {\n // ran out of file\n this.debug('\\n>>> no match, partial?', file, fr, pattern, pr)\n if (fr === fl) {\n return true\n }\n }\n /* c8 ignore stop */\n return false\n }\n\n // something other than **\n // non-magic patterns just have to match exactly\n // patterns with magic have been turned into regexps.\n let hit: boolean\n if (typeof p === 'string') {\n hit = f === p\n this.debug('string match', p, f, hit)\n } else {\n hit = p.test(f)\n this.debug('pattern match', p, f, hit)\n }\n\n if (!hit) return false\n }\n\n // Note: ending in / means that we'll get a final \"\"\n // at the end of the pattern. This can only match a\n // corresponding \"\" at the end of the file.\n // If the file ends in /, then it can only match a\n // a pattern that ends in /, unless the pattern just\n // doesn't have any more for it. But, a/b/ should *not*\n // match \"a/b/*\", even though \"\" matches against the\n // [^/]*? pattern, except in partial mode, where it might\n // simply not be reached yet.\n // However, a/b/ should still satisfy a/*\n\n // now either we fell off the end of the pattern, or we're done.\n if (fi === fl && pi === pl) {\n // ran out of pattern and filename at the same time.\n // an exact hit!\n return true\n } else if (fi === fl) {\n // ran out of file, but still had pattern left.\n // this is ok if we're doing the match as part of\n // a glob fs traversal.\n return partial\n } else if (pi === pl) {\n // ran out of pattern, still have file left.\n // this is only acceptable if we're on the very last\n // empty segment of a file with a trailing slash.\n // a/* should match a/b/\n return fi === fl - 1 && file[fi] === ''\n\n /* c8 ignore start */\n } else {\n // should be unreachable.\n throw new Error('wtf?')\n }\n /* c8 ignore stop */\n }\n\n braceExpand() {\n return braceExpand(this.pattern, this.options)\n }\n\n parse(pattern: string): ParseReturn {\n assertValidPattern(pattern)\n\n const options = this.options\n\n // shortcuts\n if (pattern === '**') return GLOBSTAR\n if (pattern === '') return ''\n\n // far and away, the most common glob pattern parts are\n // *, *.*, and *.<ext> Add a fast check method for those.\n let m: RegExpMatchArray | null\n let fastTest: null | ((f: string) => boolean) = null\n if ((m = pattern.match(starRE))) {\n fastTest = options.dot ? starTestDot : starTest\n } else if ((m = pattern.match(starDotExtRE))) {\n fastTest = (\n options.nocase ?\n options.dot ?\n starDotExtTestNocaseDot\n : starDotExtTestNocase\n : options.dot ? starDotExtTestDot\n : starDotExtTest)(m[1])\n } else if ((m = pattern.match(qmarksRE))) {\n fastTest = (\n options.nocase ?\n options.dot ?\n qmarksTestNocaseDot\n : qmarksTestNocase\n : options.dot ? qmarksTestDot\n : qmarksTest)(m)\n } else if ((m = pattern.match(starDotStarRE))) {\n fastTest = options.dot ? starDotStarTestDot : starDotStarTest\n } else if ((m = pattern.match(dotStarRE))) {\n fastTest = dotStarTest\n }\n\n const re = AST.fromGlob(pattern, this.options).toMMPattern()\n if (fastTest && typeof re === 'object') {\n // Avoids overriding in frozen environments\n Reflect.defineProperty(re, 'test', { value: fastTest })\n }\n return re\n }\n\n makeRe() {\n if (this.regexp || this.regexp === false) return this.regexp\n\n // at this point, this.set is a 2d array of partial\n // pattern strings, or \"**\".\n //\n // It's better to use .match(). This function shouldn't\n // be used, really, but it's pretty convenient sometimes,\n // when you just want to work with a regex.\n const set = this.set\n\n if (!set.length) {\n this.regexp = false\n return this.regexp\n }\n const options = this.options\n\n const twoStar =\n options.noglobstar ? star\n : options.dot ? twoStarDot\n : twoStarNoDot\n const flags = new Set(options.nocase ? ['i'] : [])\n\n // regexpify non-globstar patterns\n // if ** is only item, then we just do one twoStar\n // if ** is first, and there are more, prepend (\\/|twoStar\\/)? to next\n // if ** is last, append (\\/twoStar|) to previous\n // if ** is in the middle, append (\\/|\\/twoStar\\/) to previous\n // then filter out GLOBSTAR symbols\n let re = set\n .map(pattern => {\n const pp: (string | typeof GLOBSTAR)[] = pattern.map(p => {\n if (p instanceof RegExp) {\n for (const f of p.flags.split('')) flags.add(f)\n }\n return (\n typeof p === 'string' ? regExpEscape(p)\n : p === GLOBSTAR ? GLOBSTAR\n : p._src\n )\n }) as (string | typeof GLOBSTAR)[]\n pp.forEach((p, i) => {\n const next = pp[i + 1]\n const prev = pp[i - 1]\n if (p !== GLOBSTAR || prev === GLOBSTAR) {\n return\n }\n if (prev === undefined) {\n if (next !== undefined && next !== GLOBSTAR) {\n pp[i + 1] = '(?:\\\\/|' + twoStar + '\\\\/)?' + next\n } else {\n pp[i] = twoStar\n }\n } else if (next === undefined) {\n pp[i - 1] = prev + '(?:\\\\/|\\\\/' + twoStar + ')?'\n } else if (next !== GLOBSTAR) {\n pp[i - 1] = prev + '(?:\\\\/|\\\\/' + twoStar + '\\\\/)' + next\n pp[i + 1] = GLOBSTAR\n }\n })\n const filtered = pp.filter(p => p !== GLOBSTAR)\n\n // For partial matches, we need to make the pattern match\n // any prefix of the full path. We do this by generating\n // alternative patterns that match progressively longer prefixes.\n if (this.partial && filtered.length >= 1) {\n const prefixes: string[] = []\n for (let i = 1; i <= filtered.length; i++) {\n prefixes.push(filtered.slice(0, i).join('/'))\n }\n return '(?:' + prefixes.join('|') + ')'\n }\n\n return filtered.join('/')\n })\n .join('|')\n\n // need to wrap in parens if we had more than one thing with |,\n // otherwise only the first will be anchored to ^ and the last to $\n const [open, close] = set.length > 1 ? ['(?:', ')'] : ['', '']\n // must match entire pattern\n // ending in a * or ** will make it less strict.\n re = '^' + open + re + close + '$'\n\n // In partial mode, '/' should always match as it's a valid prefix for any pattern\n if (this.partial) {\n re = '^(?:\\\\/|' + open + re.slice(1, -1) + close + ')$'\n }\n\n // can match anything, as long as it's not this.\n if (this.negate) re = '^(?!' + re + ').+$'\n\n try {\n this.regexp = new RegExp(re, [...flags].join(''))\n /* c8 ignore start */\n } catch (ex) {\n // should be impossible\n this.regexp = false\n }\n /* c8 ignore stop */\n return this.regexp\n }\n\n slashSplit(p: string) {\n // if p starts with // on windows, we preserve that\n // so that UNC paths aren't broken. Otherwise, any number of\n // / characters are coalesced into one, unless\n // preserveMultipleSlashes is set to true.\n if (this.preserveMultipleSlashes) {\n return p.split('/')\n } else if (this.isWindows && /^\\/\\/[^\\/]+/.test(p)) {\n // add an extra '' for the one we lose\n return ['', ...p.split(/\\/+/)]\n } else {\n return p.split(/\\/+/)\n }\n }\n\n match(f: string, partial = this.partial) {\n this.debug('match', f, this.pattern)\n // short-circuit in the case of busted things.\n // comments, etc.\n if (this.comment) {\n return false\n }\n if (this.empty) {\n return f === ''\n }\n\n if (f === '/' && partial) {\n return true\n }\n\n const options = this.options\n\n // windows: need to use /, not \\\n if (this.isWindows) {\n f = f.split('\\\\').join('/')\n }\n\n // treat the test path as a set of pathparts.\n const ff = this.slashSplit(f)\n this.debug(this.pattern, 'split', ff)\n\n // just ONE of the pattern sets in this.set needs to match\n // in order for it to be valid. If negating, then just one\n // match means that we have failed.\n // Either way, return on the first hit.\n\n const set = this.set\n this.debug(this.pattern, 'set', set)\n\n // Find the basename of the path by looking for the last non-empty segment\n let filename: string = ff[ff.length - 1]\n if (!filename) {\n for (let i = ff.length - 2; !filename && i >= 0; i--) {\n filename = ff[i]\n }\n }\n\n for (let i = 0; i < set.length; i++) {\n const pattern = set[i]\n let file = ff\n if (options.matchBase && pattern.length === 1) {\n file = [filename]\n }\n const hit = this.matchOne(file, pattern, partial)\n if (hit) {\n if (options.flipNegate) {\n return true\n }\n return !this.negate\n }\n }\n\n // didn't get any hits. this is success if it's a negative\n // pattern, failure otherwise.\n if (options.flipNegate) {\n return false\n }\n return this.negate\n }\n\n static defaults(def: MinimatchOptions) {\n return minimatch.defaults(def).Minimatch\n }\n}\n/* c8 ignore start */\nexport { AST } from './ast.js'\nexport { escape } from './escape.js'\nexport { unescape } from './unescape.js'\n/* c8 ignore stop */\nminimatch.AST = AST\nminimatch.Minimatch = Minimatch\nminimatch.escape = escape\nminimatch.unescape = unescape\n","import { Minimatch, MinimatchOptions } from 'minimatch'\nimport { Minipass } from 'minipass'\nimport { fileURLToPath } from 'node:url'\nimport {\n FSOption,\n Path,\n PathScurry,\n PathScurryDarwin,\n PathScurryPosix,\n PathScurryWin32,\n} from 'path-scurry'\nimport { IgnoreLike } from './ignore.js'\nimport { Pattern } from './pattern.js'\nimport { GlobStream, GlobWalker } from './walker.js'\n\nexport type MatchSet = Minimatch['set']\nexport type GlobParts = Exclude<Minimatch['globParts'], undefined>\n\n// if no process global, just call it linux.\n// so we default to case-sensitive, / separators\nconst defaultPlatform: NodeJS.Platform =\n (\n typeof process === 'object' &&\n process &&\n typeof process.platform === 'string'\n ) ?\n process.platform\n : 'linux'\n\n/**\n * A `GlobOptions` object may be provided to any of the exported methods, and\n * must be provided to the `Glob` constructor.\n *\n * All options are optional, boolean, and false by default, unless otherwise\n * noted.\n *\n * All resolved options are added to the Glob object as properties.\n *\n * If you are running many `glob` operations, you can pass a Glob object as the\n * `options` argument to a subsequent operation to share the previously loaded\n * cache.\n */\nexport interface GlobOptions {\n /**\n * Set to `true` to always receive absolute paths for\n * matched files. Set to `false` to always return relative paths.\n *\n * When this option is not set, absolute paths are returned for patterns\n * that are absolute, and otherwise paths are returned that are relative\n * to the `cwd` setting.\n *\n * This does _not_ make an extra system call to get\n * the realpath, it only does string path resolution.\n *\n * Conflicts with {@link withFileTypes}\n */\n absolute?: boolean\n\n /**\n * Set to false to enable {@link windowsPathsNoEscape}\n *\n * @deprecated\n */\n allowWindowsEscape?: boolean\n\n /**\n * The current working directory in which to search. Defaults to\n * `process.cwd()`.\n *\n * May be eiher a string path or a `file://` URL object or string.\n */\n cwd?: string | URL\n\n /**\n * Include `.dot` files in normal matches and `globstar`\n * matches. Note that an explicit dot in a portion of the pattern\n * will always match dot files.\n */\n dot?: boolean\n\n /**\n * Prepend all relative path strings with `./` (or `.\\` on Windows).\n *\n * Without this option, returned relative paths are \"bare\", so instead of\n * returning `'./foo/bar'`, they are returned as `'foo/bar'`.\n *\n * Relative patterns starting with `'../'` are not prepended with `./`, even\n * if this option is set.\n */\n dotRelative?: boolean\n\n /**\n * Follow symlinked directories when expanding `**`\n * patterns. This can result in a lot of duplicate references in\n * the presence of cyclic links, and make performance quite bad.\n *\n * By default, a `**` in a pattern will follow 1 symbolic link if\n * it is not the first item in the pattern, or none if it is the\n * first item in the pattern, following the same behavior as Bash.\n */\n follow?: boolean\n\n /**\n * string or string[], or an object with `ignored` and `childrenIgnored`\n * methods.\n *\n * If a string or string[] is provided, then this is treated as a glob\n * pattern or array of glob patterns to exclude from matches. To ignore all\n * children within a directory, as well as the entry itself, append `'/**'`\n * to the ignore pattern.\n *\n * **Note** `ignore` patterns are _always_ in `dot:true` mode, regardless of\n * any other settings.\n *\n * If an object is provided that has `ignored(path)` and/or\n * `childrenIgnored(path)` methods, then these methods will be called to\n * determine whether any Path is a match or if its children should be\n * traversed, respectively.\n */\n ignore?: string | string[] | IgnoreLike\n\n /**\n * Treat brace expansion like `{a,b}` as a \"magic\" pattern. Has no\n * effect if {@link nobrace} is set.\n *\n * Only has effect on the {@link hasMagic} function.\n */\n magicalBraces?: boolean\n\n /**\n * Add a `/` character to directory matches. Note that this requires\n * additional stat calls in some cases.\n */\n mark?: boolean\n\n /**\n * Perform a basename-only match if the pattern does not contain any slash\n * characters. That is, `*.js` would be treated as equivalent to\n * `**\\/*.js`, matching all js files in all directories.\n */\n matchBase?: boolean\n\n /**\n * Limit the directory traversal to a given depth below the cwd.\n * Note that this does NOT prevent traversal to sibling folders,\n * root patterns, and so on. It only limits the maximum folder depth\n * that the walk will descend, relative to the cwd.\n */\n maxDepth?: number\n\n /**\n * Do not expand `{a,b}` and `{1..3}` brace sets.\n */\n nobrace?: boolean\n\n /**\n * Perform a case-insensitive match. This defaults to `true` on macOS and\n * Windows systems, and `false` on all others.\n *\n * **Note** `nocase` should only be explicitly set when it is\n * known that the filesystem's case sensitivity differs from the\n * platform default. If set `true` on case-sensitive file\n * systems, or `false` on case-insensitive file systems, then the\n * walk may return more or less results than expected.\n */\n nocase?: boolean\n\n /**\n * Do not match directories, only files. (Note: to match\n * _only_ directories, put a `/` at the end of the pattern.)\n */\n nodir?: boolean\n\n /**\n * Do not match \"extglob\" patterns such as `+(a|b)`.\n */\n noext?: boolean\n\n /**\n * Do not match `**` against multiple filenames. (Ie, treat it as a normal\n * `*` instead.)\n *\n * Conflicts with {@link matchBase}\n */\n noglobstar?: boolean\n\n /**\n * Defaults to value of `process.platform` if available, or `'linux'` if\n * not. Setting `platform:'win32'` on non-Windows systems may cause strange\n * behavior.\n */\n platform?: NodeJS.Platform\n\n /**\n * Set to true to call `fs.realpath` on all of the\n * results. In the case of an entry that cannot be resolved, the\n * entry is omitted. This incurs a slight performance penalty, of\n * course, because of the added system calls.\n */\n realpath?: boolean\n\n /**\n *\n * A string path resolved against the `cwd` option, which\n * is used as the starting point for absolute patterns that start\n * with `/`, (but not drive letters or UNC paths on Windows).\n *\n * Note that this _doesn't_ necessarily limit the walk to the\n * `root` directory, and doesn't affect the cwd starting point for\n * non-absolute patterns. A pattern containing `..` will still be\n * able to traverse out of the root directory, if it is not an\n * actual root directory on the filesystem, and any non-absolute\n * patterns will be matched in the `cwd`. For example, the\n * pattern `/../*` with `{root:'/some/path'}` will return all\n * files in `/some`, not all files in `/some/path`. The pattern\n * `*` with `{root:'/some/path'}` will return all the entries in\n * the cwd, not the entries in `/some/path`.\n *\n * To start absolute and non-absolute patterns in the same\n * path, you can use `{root:''}`. However, be aware that on\n * Windows systems, a pattern like `x:/*` or `//host/share/*` will\n * _always_ start in the `x:/` or `//host/share` directory,\n * regardless of the `root` setting.\n */\n root?: string\n\n /**\n * A [PathScurry](http://npm.im/path-scurry) object used\n * to traverse the file system. If the `nocase` option is set\n * explicitly, then any provided `scurry` object must match this\n * setting.\n */\n scurry?: PathScurry\n\n /**\n * Call `lstat()` on all entries, whether required or not to determine\n * if it's a valid match. When used with {@link withFileTypes}, this means\n * that matches will include data such as modified time, permissions, and\n * so on. Note that this will incur a performance cost due to the added\n * system calls.\n */\n stat?: boolean\n\n /**\n * An AbortSignal which will cancel the Glob walk when\n * triggered.\n */\n signal?: AbortSignal\n\n /**\n * Use `\\\\` as a path separator _only_, and\n * _never_ as an escape character. If set, all `\\\\` characters are\n * replaced with `/` in the pattern.\n *\n * Note that this makes it **impossible** to match against paths\n * containing literal glob pattern characters, but allows matching\n * with patterns constructed using `path.join()` and\n * `path.resolve()` on Windows platforms, mimicking the (buggy!)\n * behavior of Glob v7 and before on Windows. Please use with\n * caution, and be mindful of [the caveat below about Windows\n * paths](#windows). (For legacy reasons, this is also set if\n * `allowWindowsEscape` is set to the exact value `false`.)\n */\n windowsPathsNoEscape?: boolean\n\n /**\n * Return [PathScurry](http://npm.im/path-scurry)\n * `Path` objects instead of strings. These are similar to a\n * NodeJS `Dirent` object, but with additional methods and\n * properties.\n *\n * Conflicts with {@link absolute}\n */\n withFileTypes?: boolean\n\n /**\n * An fs implementation to override some or all of the defaults. See\n * http://npm.im/path-scurry for details about what can be overridden.\n */\n fs?: FSOption\n\n /**\n * Just passed along to Minimatch. Note that this makes all pattern\n * matching operations slower and *extremely* noisy.\n */\n debug?: boolean\n\n /**\n * Return `/` delimited paths, even on Windows.\n *\n * On posix systems, this has no effect. But, on Windows, it means that\n * paths will be `/` delimited, and absolute paths will be their full\n * resolved UNC forms, eg instead of `'C:\\\\foo\\\\bar'`, it would return\n * `'//?/C:/foo/bar'`\n */\n posix?: boolean\n\n /**\n * Do not match any children of any matches. For example, the pattern\n * `**\\/foo` would match `a/foo`, but not `a/foo/b/foo` in this mode.\n *\n * This is especially useful for cases like \"find all `node_modules`\n * folders, but not the ones in `node_modules`\".\n *\n * In order to support this, the `Ignore` implementation must support an\n * `add(pattern: string)` method. If using the default `Ignore` class, then\n * this is fine, but if this is set to `false`, and a custom `Ignore` is\n * provided that does not have an `add()` method, then it will throw an\n * error.\n *\n * **Caveat** It *only* ignores matches that would be a descendant of a\n * previous match, and only if that descendant is matched *after* the\n * ancestor is encountered. Since the file system walk happens in\n * indeterminate order, it's possible that a match will already be added\n * before its ancestor, if multiple or braced patterns are used.\n *\n * For example:\n *\n * ```ts\n * const results = await glob([\n * // likely to match first, since it's just a stat\n * 'a/b/c/d/e/f',\n *\n * // this pattern is more complicated! It must to various readdir()\n * // calls and test the results against a regular expression, and that\n * // is certainly going to take a little bit longer.\n * //\n * // So, later on, it encounters a match at 'a/b/c/d/e', but it's too\n * // late to ignore a/b/c/d/e/f, because it's already been emitted.\n * 'a/[bdf]/?/[a-z]/*',\n * ], { includeChildMatches: false })\n * ```\n *\n * It's best to only set this to `false` if you can be reasonably sure that\n * no components of the pattern will potentially match one another's file\n * system descendants, or if the occasional included child entry will not\n * cause problems.\n *\n * @default true\n */\n includeChildMatches?: boolean\n\n /**\n * max number of `{...}` patterns to expand. Default `1_000`.\n *\n * Note: this is much less than minimatch's default of `100_000`,\n * because Glob has higher memory requirements due to walking\n * the file system tree.\n */\n braceExpandMax?: number\n}\n\nexport type GlobOptionsWithFileTypesTrue = GlobOptions & {\n withFileTypes: true\n // string options not relevant if returning Path objects.\n absolute?: undefined\n mark?: undefined\n posix?: undefined\n}\n\nexport type GlobOptionsWithFileTypesFalse = GlobOptions & {\n withFileTypes?: false\n}\n\nexport type GlobOptionsWithFileTypesUnset = GlobOptions & {\n withFileTypes?: undefined\n}\n\nexport type Result<Opts> =\n Opts extends GlobOptionsWithFileTypesTrue ? Path\n : Opts extends GlobOptionsWithFileTypesFalse ? string\n : Opts extends GlobOptionsWithFileTypesUnset ? string\n : string | Path\nexport type Results<Opts> = Result<Opts>[]\n\nexport type FileTypes<Opts> =\n Opts extends GlobOptionsWithFileTypesTrue ? true\n : Opts extends GlobOptionsWithFileTypesFalse ? false\n : Opts extends GlobOptionsWithFileTypesUnset ? false\n : boolean\n\n/**\n * An object that can perform glob pattern traversals.\n */\nexport class Glob<Opts extends GlobOptions> implements GlobOptions {\n absolute?: boolean\n cwd: string\n root?: string\n dot: boolean\n dotRelative: boolean\n follow: boolean\n ignore?: string | string[] | IgnoreLike\n magicalBraces: boolean\n mark?: boolean\n matchBase: boolean\n maxDepth: number\n nobrace: boolean\n nocase: boolean\n nodir: boolean\n noext: boolean\n noglobstar: boolean\n pattern: string[]\n platform: NodeJS.Platform\n realpath: boolean\n scurry: PathScurry\n stat: boolean\n signal?: AbortSignal\n windowsPathsNoEscape: boolean\n withFileTypes: FileTypes<Opts>\n includeChildMatches: boolean\n\n /**\n * The options provided to the constructor.\n */\n opts: Opts\n\n /**\n * An array of parsed immutable {@link Pattern} objects.\n */\n patterns: Pattern[]\n\n /**\n * All options are stored as properties on the `Glob` object.\n *\n * See {@link GlobOptions} for full options descriptions.\n *\n * Note that a previous `Glob` object can be passed as the\n * `GlobOptions` to another `Glob` instantiation to re-use settings\n * and caches with a new pattern.\n *\n * Traversal functions can be called multiple times to run the walk\n * again.\n */\n constructor(pattern: string | string[], opts: Opts) {\n /* c8 ignore start */\n if (!opts) throw new TypeError('glob options required')\n /* c8 ignore stop */\n this.withFileTypes = !!opts.withFileTypes as FileTypes<Opts>\n this.signal = opts.signal\n this.follow = !!opts.follow\n this.dot = !!opts.dot\n this.dotRelative = !!opts.dotRelative\n this.nodir = !!opts.nodir\n this.mark = !!opts.mark\n if (!opts.cwd) {\n this.cwd = ''\n } else if (opts.cwd instanceof URL || opts.cwd.startsWith('file://')) {\n opts.cwd = fileURLToPath(opts.cwd)\n }\n this.cwd = opts.cwd || ''\n this.root = opts.root\n this.magicalBraces = !!opts.magicalBraces\n this.nobrace = !!opts.nobrace\n this.noext = !!opts.noext\n this.realpath = !!opts.realpath\n this.absolute = opts.absolute\n this.includeChildMatches = opts.includeChildMatches !== false\n\n this.noglobstar = !!opts.noglobstar\n this.matchBase = !!opts.matchBase\n this.maxDepth =\n typeof opts.maxDepth === 'number' ? opts.maxDepth : Infinity\n this.stat = !!opts.stat\n this.ignore = opts.ignore\n\n if (this.withFileTypes && this.absolute !== undefined) {\n throw new Error('cannot set absolute and withFileTypes:true')\n }\n\n if (typeof pattern === 'string') {\n pattern = [pattern]\n }\n\n this.windowsPathsNoEscape =\n !!opts.windowsPathsNoEscape ||\n (opts as { allowWindowsEscape?: boolean }).allowWindowsEscape ===\n false\n\n if (this.windowsPathsNoEscape) {\n pattern = pattern.map(p => p.replace(/\\\\/g, '/'))\n }\n\n if (this.matchBase) {\n if (opts.noglobstar) {\n throw new TypeError('base matching requires globstar')\n }\n pattern = pattern.map(p => (p.includes('/') ? p : `./**/${p}`))\n }\n\n this.pattern = pattern\n\n this.platform = opts.platform || defaultPlatform\n this.opts = { ...opts, platform: this.platform }\n if (opts.scurry) {\n this.scurry = opts.scurry\n if (\n opts.nocase !== undefined &&\n opts.nocase !== opts.scurry.nocase\n ) {\n throw new Error('nocase option contradicts provided scurry option')\n }\n } else {\n const Scurry =\n opts.platform === 'win32' ? PathScurryWin32\n : opts.platform === 'darwin' ? PathScurryDarwin\n : opts.platform ? PathScurryPosix\n : PathScurry\n this.scurry = new Scurry(this.cwd, {\n nocase: opts.nocase,\n fs: opts.fs,\n })\n }\n this.nocase = this.scurry.nocase\n\n // If you do nocase:true on a case-sensitive file system, then\n // we need to use regexps instead of strings for non-magic\n // path portions, because statting `aBc` won't return results\n // for the file `AbC` for example.\n const nocaseMagicOnly =\n this.platform === 'darwin' || this.platform === 'win32'\n\n const mmo: MinimatchOptions = {\n braceExpandMax: 10_000,\n ...opts,\n dot: this.dot,\n matchBase: this.matchBase,\n nobrace: this.nobrace,\n // default nocase based on platform\n nocase: this.nocase,\n nocaseMagicOnly,\n nocomment: true,\n noext: this.noext,\n nonegate: true,\n optimizationLevel: 2,\n platform: this.platform,\n windowsPathsNoEscape: this.windowsPathsNoEscape,\n debug: !!this.opts.debug,\n }\n\n const mms = this.pattern.map(p => new Minimatch(p, mmo))\n const [matchSet, globParts] = mms.reduce(\n (set: [MatchSet, GlobParts], m) => {\n set[0].push(...m.set)\n set[1].push(...m.globParts)\n return set\n },\n [[], []],\n )\n this.patterns = matchSet.map((set, i) => {\n const g = globParts[i]\n /* c8 ignore start */\n if (!g) throw new Error('invalid pattern object')\n /* c8 ignore stop */\n return new Pattern(set, g, 0, this.platform)\n })\n }\n\n /**\n * Returns a Promise that resolves to the results array.\n */\n async walk(): Promise<Results<Opts>>\n async walk(): Promise<(string | Path)[]> {\n // Walkers always return array of Path objects, so we just have to\n // coerce them into the right shape. It will have already called\n // realpath() if the option was set to do so, so we know that's cached.\n // start out knowing the cwd, at least\n return [\n ...(await new GlobWalker(this.patterns, this.scurry.cwd, {\n ...this.opts,\n maxDepth:\n this.maxDepth !== Infinity ?\n this.maxDepth + this.scurry.cwd.depth()\n : Infinity,\n platform: this.platform,\n nocase: this.nocase,\n includeChildMatches: this.includeChildMatches,\n }).walk()),\n ]\n }\n\n /**\n * synchronous {@link Glob.walk}\n */\n walkSync(): Results<Opts>\n walkSync(): (string | Path)[] {\n return [\n ...new GlobWalker(this.patterns, this.scurry.cwd, {\n ...this.opts,\n maxDepth:\n this.maxDepth !== Infinity ?\n this.maxDepth + this.scurry.cwd.depth()\n : Infinity,\n platform: this.platform,\n nocase: this.nocase,\n includeChildMatches: this.includeChildMatches,\n }).walkSync(),\n ]\n }\n\n /**\n * Stream results asynchronously.\n */\n stream(): Minipass<Result<Opts>, Result<Opts>>\n stream(): Minipass<string | Path, string | Path> {\n return new GlobStream(this.patterns, this.scurry.cwd, {\n ...this.opts,\n maxDepth:\n this.maxDepth !== Infinity ?\n this.maxDepth + this.scurry.cwd.depth()\n : Infinity,\n platform: this.platform,\n nocase: this.nocase,\n includeChildMatches: this.includeChildMatches,\n }).stream()\n }\n\n /**\n * Stream results synchronously.\n */\n streamSync(): Minipass<Result<Opts>, Result<Opts>>\n streamSync(): Minipass<string | Path, string | Path> {\n return new GlobStream(this.patterns, this.scurry.cwd, {\n ...this.opts,\n maxDepth:\n this.maxDepth !== Infinity ?\n this.maxDepth + this.scurry.cwd.depth()\n : Infinity,\n platform: this.platform,\n nocase: this.nocase,\n includeChildMatches: this.includeChildMatches,\n }).streamSync()\n }\n\n /**\n * Default sync iteration function. Returns a Generator that\n * iterates over the results.\n */\n iterateSync(): Generator<Result<Opts>, void, void> {\n return this.streamSync()[Symbol.iterator]()\n }\n [Symbol.iterator]() {\n return this.iterateSync()\n }\n\n /**\n * Default async iteration function. Returns an AsyncGenerator that\n * iterates over the results.\n */\n iterate(): AsyncGenerator<Result<Opts>, void, void> {\n return this.stream()[Symbol.asyncIterator]()\n }\n [Symbol.asyncIterator]() {\n return this.iterate()\n }\n}\n","/**\n * @module LRUCache\n */\n\n// module-private names and types\n// this provides the default Perf object source.\n// it can be passed in via configuration to override it\n// for a single LRU object.\nexport type Perf = { now: () => number }\nconst defaultPerf: Perf =\n (\n typeof performance === 'object' &&\n performance &&\n typeof performance.now === 'function'\n ) ?\n performance\n : Date\n\nconst warned = new Set<string>()\n\n// either a function or a class\ntype ForC = ((...a: any[]) => any) | { new (...a: any[]): any }\n\n/* c8 ignore start */\nconst PROCESS = (\n typeof process === 'object' && !!process ?\n process\n : {}) as { [k: string]: any }\n/* c8 ignore start */\n\nconst emitWarning = (\n msg: string,\n type: string,\n code: string,\n fn: ForC,\n) => {\n typeof PROCESS.emitWarning === 'function' ?\n PROCESS.emitWarning(msg, type, code, fn)\n : console.error(`[${code}] ${type}: ${msg}`)\n}\n\nlet AC = globalThis.AbortController\nlet AS = globalThis.AbortSignal\n\n/* c8 ignore start */\nif (typeof AC === 'undefined') {\n //@ts-ignore\n AS = class AbortSignal {\n onabort?: (...a: any[]) => any\n _onabort: ((...a: any[]) => any)[] = []\n reason?: any\n aborted: boolean = false\n addEventListener(_: string, fn: (...a: any[]) => any) {\n this._onabort.push(fn)\n }\n }\n //@ts-ignore\n AC = class AbortController {\n constructor() {\n warnACPolyfill()\n }\n signal = new AS()\n abort(reason: any) {\n if (this.signal.aborted) return\n //@ts-ignore\n this.signal.reason = reason\n //@ts-ignore\n this.signal.aborted = true\n //@ts-ignore\n for (const fn of this.signal._onabort) {\n fn(reason)\n }\n this.signal.onabort?.(reason)\n }\n }\n let printACPolyfillWarning =\n PROCESS.env?.LRU_CACHE_IGNORE_AC_WARNING !== '1'\n const warnACPolyfill = () => {\n if (!printACPolyfillWarning) return\n printACPolyfillWarning = false\n emitWarning(\n 'AbortController is not defined. If using lru-cache in ' +\n 'node 14, load an AbortController polyfill from the ' +\n '`node-abort-controller` package. A minimal polyfill is ' +\n 'provided for use by LRUCache.fetch(), but it should not be ' +\n 'relied upon in other contexts (eg, passing it to other APIs that ' +\n 'use AbortController/AbortSignal might have undesirable effects). ' +\n 'You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.',\n 'NO_ABORT_CONTROLLER',\n 'ENOTSUP',\n warnACPolyfill,\n )\n }\n}\n/* c8 ignore stop */\n\nconst shouldWarn = (code: string) => !warned.has(code)\n\nconst TYPE = Symbol('type')\nexport type PosInt = number & { [TYPE]: 'Positive Integer' }\nexport type Index = number & { [TYPE]: 'LRUCache Index' }\n\nconst isPosInt = (n: any): n is PosInt =>\n n && n === Math.floor(n) && n > 0 && isFinite(n)\n\nexport type UintArray = Uint8Array | Uint16Array | Uint32Array\nexport type NumberArray = UintArray | number[]\n\n/* c8 ignore start */\n// This is a little bit ridiculous, tbh.\n// The maximum array length is 2^32-1 or thereabouts on most JS impls.\n// And well before that point, you're caching the entire world, I mean,\n// that's ~32GB of just integers for the next/prev links, plus whatever\n// else to hold that many keys and values. Just filling the memory with\n// zeroes at init time is brutal when you get that big.\n// But why not be complete?\n// Maybe in the future, these limits will have expanded.\nconst getUintArray = (max: number) =>\n !isPosInt(max) ? null\n : max <= Math.pow(2, 8) ? Uint8Array\n : max <= Math.pow(2, 16) ? Uint16Array\n : max <= Math.pow(2, 32) ? Uint32Array\n : max <= Number.MAX_SAFE_INTEGER ? ZeroArray\n : null\n/* c8 ignore stop */\n\nclass ZeroArray extends Array<number> {\n constructor(size: number) {\n super(size)\n this.fill(0)\n }\n}\nexport type { ZeroArray }\nexport type { Stack }\n\nexport type StackLike = Stack | Index[]\nclass Stack {\n heap: NumberArray\n length: number\n // private constructor\n static #constructing: boolean = false\n static create(max: number): StackLike {\n const HeapCls = getUintArray(max)\n if (!HeapCls) return []\n Stack.#constructing = true\n const s = new Stack(max, HeapCls)\n Stack.#constructing = false\n return s\n }\n constructor(max: number, HeapCls: { new (n: number): NumberArray }) {\n /* c8 ignore start */\n if (!Stack.#constructing) {\n throw new TypeError('instantiate Stack using Stack.create(n)')\n }\n /* c8 ignore stop */\n this.heap = new HeapCls(max)\n this.length = 0\n }\n push(n: Index) {\n this.heap[this.length++] = n\n }\n pop(): Index {\n return this.heap[--this.length] as Index\n }\n}\n\n/**\n * Promise representing an in-progress {@link LRUCache#fetch} call\n */\nexport type BackgroundFetch<V> = Promise<V | undefined> & {\n __returned: BackgroundFetch<V> | undefined\n __abortController: AbortController\n __staleWhileFetching: V | undefined\n}\n\nexport type DisposeTask<K, V> = [\n value: V,\n key: K,\n reason: LRUCache.DisposeReason,\n]\n\nexport namespace LRUCache {\n /**\n * An integer greater than 0, reflecting the calculated size of items\n */\n export type Size = number\n\n /**\n * Integer greater than 0, representing some number of milliseconds, or the\n * time at which a TTL started counting from.\n */\n export type Milliseconds = number\n\n /**\n * An integer greater than 0, reflecting a number of items\n */\n export type Count = number\n\n /**\n * The reason why an item was removed from the cache, passed\n * to the {@link Disposer} methods.\n *\n * - `evict`: The item was evicted because it is the least recently used,\n * and the cache is full.\n * - `set`: A new value was set, overwriting the old value being disposed.\n * - `delete`: The item was explicitly deleted, either by calling\n * {@link LRUCache#delete}, {@link LRUCache#clear}, or\n * {@link LRUCache#set} with an undefined value.\n * - `expire`: The item was removed due to exceeding its TTL.\n * - `fetch`: A {@link OptionsBase#fetchMethod} operation returned\n * `undefined` or was aborted, causing the item to be deleted.\n */\n export type DisposeReason =\n | 'evict'\n | 'set'\n | 'delete'\n | 'expire'\n | 'fetch'\n /**\n * A method called upon item removal, passed as the\n * {@link OptionsBase.dispose} and/or\n * {@link OptionsBase.disposeAfter} options.\n */\n export type Disposer<K, V> = (\n value: V,\n key: K,\n reason: DisposeReason,\n ) => void\n\n /**\n * The reason why an item was added to the cache, passed\n * to the {@link Inserter} methods.\n *\n * - `add`: the item was not found in the cache, and was added\n * - `update`: the item was in the cache, with the same value provided\n * - `replace`: the item was in the cache, and replaced\n */\n export type InsertReason = 'add' | 'update' | 'replace'\n\n /**\n * A method called upon item insertion, passed as the\n * {@link OptionsBase.insert}\n */\n export type Inserter<K, V> = (\n value: V,\n key: K,\n reason: InsertReason,\n ) => void\n\n /**\n * A function that returns the effective calculated size\n * of an entry in the cache.\n */\n export type SizeCalculator<K, V> = (value: V, key: K) => Size\n\n /**\n * Options provided to the\n * {@link OptionsBase.fetchMethod} function.\n */\n export interface FetcherOptions<K, V, FC = unknown> {\n signal: AbortSignal\n options: FetcherFetchOptions<K, V, FC>\n /**\n * Object provided in the {@link FetchOptions.context} option to\n * {@link LRUCache#fetch}\n */\n context: FC\n }\n\n /**\n * Occasionally, it may be useful to track the internal behavior of the\n * cache, particularly for logging, debugging, or for behavior within the\n * `fetchMethod`. To do this, you can pass a `status` object to the\n * {@link LRUCache#fetch}, {@link LRUCache#get}, {@link LRUCache#set},\n * {@link LRUCache#memo}, and {@link LRUCache#has} methods.\n *\n * The `status` option should be a plain JavaScript object. The following\n * fields will be set on it appropriately, depending on the situation.\n */\n export interface Status<V> {\n /**\n * The status of a set() operation.\n *\n * - add: the item was not found in the cache, and was added\n * - update: the item was in the cache, with the same value provided\n * - replace: the item was in the cache, and replaced\n * - miss: the item was not added to the cache for some reason\n */\n set?: 'add' | 'update' | 'replace' | 'miss'\n\n /**\n * the ttl stored for the item, or undefined if ttls are not used.\n */\n ttl?: Milliseconds\n\n /**\n * the start time for the item, or undefined if ttls are not used.\n */\n start?: Milliseconds\n\n /**\n * The timestamp used for TTL calculation\n */\n now?: Milliseconds\n\n /**\n * the remaining ttl for the item, or undefined if ttls are not used.\n */\n remainingTTL?: Milliseconds\n\n /**\n * The calculated size for the item, if sizes are used.\n */\n entrySize?: Size\n\n /**\n * The total calculated size of the cache, if sizes are used.\n */\n totalCalculatedSize?: Size\n\n /**\n * A flag indicating that the item was not stored, due to exceeding the\n * {@link OptionsBase.maxEntrySize}\n */\n maxEntrySizeExceeded?: true\n\n /**\n * The old value, specified in the case of `set:'update'` or\n * `set:'replace'`\n */\n oldValue?: V\n\n /**\n * The results of a {@link LRUCache#has} operation\n *\n * - hit: the item was found in the cache\n * - stale: the item was found in the cache, but is stale\n * - miss: the item was not found in the cache\n */\n has?: 'hit' | 'stale' | 'miss'\n\n /**\n * The status of a {@link LRUCache#fetch} operation.\n * Note that this can change as the underlying fetch() moves through\n * various states.\n *\n * - inflight: there is another fetch() for this key which is in process\n * - get: there is no {@link OptionsBase.fetchMethod}, so\n * {@link LRUCache#get} was called.\n * - miss: the item is not in cache, and will be fetched.\n * - hit: the item is in the cache, and was resolved immediately.\n * - stale: the item is in the cache, but stale.\n * - refresh: the item is in the cache, and not stale, but\n * {@link FetchOptions.forceRefresh} was specified.\n */\n fetch?: 'get' | 'inflight' | 'miss' | 'hit' | 'stale' | 'refresh'\n\n /**\n * The {@link OptionsBase.fetchMethod} was called\n */\n fetchDispatched?: true\n\n /**\n * The cached value was updated after a successful call to\n * {@link OptionsBase.fetchMethod}\n */\n fetchUpdated?: true\n\n /**\n * The reason for a fetch() rejection. Either the error raised by the\n * {@link OptionsBase.fetchMethod}, or the reason for an\n * AbortSignal.\n */\n fetchError?: Error\n\n /**\n * The fetch received an abort signal\n */\n fetchAborted?: true\n\n /**\n * The abort signal received was ignored, and the fetch was allowed to\n * continue.\n */\n fetchAbortIgnored?: true\n\n /**\n * The fetchMethod promise resolved successfully\n */\n fetchResolved?: true\n\n /**\n * The fetchMethod promise was rejected\n */\n fetchRejected?: true\n\n /**\n * The status of a {@link LRUCache#get} operation.\n *\n * - fetching: The item is currently being fetched. If a previous value\n * is present and allowed, that will be returned.\n * - stale: The item is in the cache, and is stale.\n * - hit: the item is in the cache\n * - miss: the item is not in the cache\n */\n get?: 'stale' | 'hit' | 'miss'\n\n /**\n * A fetch or get operation returned a stale value.\n */\n returnedStale?: true\n }\n\n /**\n * options which override the options set in the LRUCache constructor\n * when calling {@link LRUCache#fetch}.\n *\n * This is the union of {@link GetOptions} and {@link SetOptions}, plus\n * {@link OptionsBase.noDeleteOnFetchRejection},\n * {@link OptionsBase.allowStaleOnFetchRejection},\n * {@link FetchOptions.forceRefresh}, and\n * {@link FetcherOptions.context}\n *\n * Any of these may be modified in the {@link OptionsBase.fetchMethod}\n * function, but the {@link GetOptions} fields will of course have no\n * effect, as the {@link LRUCache#get} call already happened by the time\n * the fetchMethod is called.\n */\n export interface FetcherFetchOptions<K, V, FC = unknown>\n extends Pick<\n OptionsBase<K, V, FC>,\n | 'allowStale'\n | 'updateAgeOnGet'\n | 'noDeleteOnStaleGet'\n | 'sizeCalculation'\n | 'ttl'\n | 'noDisposeOnSet'\n | 'noUpdateTTL'\n | 'noDeleteOnFetchRejection'\n | 'allowStaleOnFetchRejection'\n | 'ignoreFetchAbort'\n | 'allowStaleOnFetchAbort'\n > {\n status?: Status<V>\n size?: Size\n }\n\n /**\n * Options that may be passed to the {@link LRUCache#fetch} method.\n */\n export interface FetchOptions<K, V, FC>\n extends FetcherFetchOptions<K, V, FC> {\n /**\n * Set to true to force a re-load of the existing data, even if it\n * is not yet stale.\n */\n forceRefresh?: boolean\n /**\n * Context provided to the {@link OptionsBase.fetchMethod} as\n * the {@link FetcherOptions.context} param.\n *\n * If the FC type is specified as unknown (the default),\n * undefined or void, then this is optional. Otherwise, it will\n * be required.\n */\n context?: FC\n signal?: AbortSignal\n status?: Status<V>\n }\n /**\n * Options provided to {@link LRUCache#fetch} when the FC type is something\n * other than `unknown`, `undefined`, or `void`\n */\n export interface FetchOptionsWithContext<K, V, FC>\n extends FetchOptions<K, V, FC> {\n context: FC\n }\n /**\n * Options provided to {@link LRUCache#fetch} when the FC type is\n * `undefined` or `void`\n */\n export interface FetchOptionsNoContext<K, V>\n extends FetchOptions<K, V, undefined> {\n context?: undefined\n }\n\n export interface MemoOptions<K, V, FC = unknown>\n extends Pick<\n OptionsBase<K, V, FC>,\n | 'allowStale'\n | 'updateAgeOnGet'\n | 'noDeleteOnStaleGet'\n | 'sizeCalculation'\n | 'ttl'\n | 'noDisposeOnSet'\n | 'noUpdateTTL'\n | 'noDeleteOnFetchRejection'\n | 'allowStaleOnFetchRejection'\n | 'ignoreFetchAbort'\n | 'allowStaleOnFetchAbort'\n > {\n /**\n * Set to true to force a re-load of the existing data, even if it\n * is not yet stale.\n */\n forceRefresh?: boolean\n /**\n * Context provided to the {@link OptionsBase.memoMethod} as\n * the {@link MemoizerOptions.context} param.\n *\n * If the FC type is specified as unknown (the default),\n * undefined or void, then this is optional. Otherwise, it will\n * be required.\n */\n context?: FC\n status?: Status<V>\n }\n /**\n * Options provided to {@link LRUCache#memo} when the FC type is something\n * other than `unknown`, `undefined`, or `void`\n */\n export interface MemoOptionsWithContext<K, V, FC>\n extends MemoOptions<K, V, FC> {\n context: FC\n }\n /**\n * Options provided to {@link LRUCache#memo} when the FC type is\n * `undefined` or `void`\n */\n export interface MemoOptionsNoContext<K, V>\n extends MemoOptions<K, V, undefined> {\n context?: undefined\n }\n\n /**\n * Options provided to the\n * {@link OptionsBase.memoMethod} function.\n */\n export interface MemoizerOptions<K, V, FC = unknown> {\n options: MemoizerMemoOptions<K, V, FC>\n /**\n * Object provided in the {@link MemoOptions.context} option to\n * {@link LRUCache#memo}\n */\n context: FC\n }\n\n /**\n * options which override the options set in the LRUCache constructor\n * when calling {@link LRUCache#memo}.\n *\n * This is the union of {@link GetOptions} and {@link SetOptions}, plus\n * {@link MemoOptions.forceRefresh}, and\n * {@link MemoOptions.context}\n *\n * Any of these may be modified in the {@link OptionsBase.memoMethod}\n * function, but the {@link GetOptions} fields will of course have no\n * effect, as the {@link LRUCache#get} call already happened by the time\n * the memoMethod is called.\n */\n export interface MemoizerMemoOptions<K, V, FC = unknown>\n extends Pick<\n OptionsBase<K, V, FC>,\n | 'allowStale'\n | 'updateAgeOnGet'\n | 'noDeleteOnStaleGet'\n | 'sizeCalculation'\n | 'ttl'\n | 'noDisposeOnSet'\n | 'noUpdateTTL'\n > {\n status?: Status<V>\n size?: Size\n start?: Milliseconds\n }\n\n /**\n * Options that may be passed to the {@link LRUCache#has} method.\n */\n export interface HasOptions<K, V, FC>\n extends Pick<OptionsBase<K, V, FC>, 'updateAgeOnHas'> {\n status?: Status<V>\n }\n\n /**\n * Options that may be passed to the {@link LRUCache#get} method.\n */\n export interface GetOptions<K, V, FC>\n extends Pick<\n OptionsBase<K, V, FC>,\n 'allowStale' | 'updateAgeOnGet' | 'noDeleteOnStaleGet'\n > {\n status?: Status<V>\n }\n\n /**\n * Options that may be passed to the {@link LRUCache#peek} method.\n */\n export interface PeekOptions<K, V, FC>\n extends Pick<OptionsBase<K, V, FC>, 'allowStale'> {}\n\n /**\n * Options that may be passed to the {@link LRUCache#set} method.\n */\n export interface SetOptions<K, V, FC>\n extends Pick<\n OptionsBase<K, V, FC>,\n 'sizeCalculation' | 'ttl' | 'noDisposeOnSet' | 'noUpdateTTL'\n > {\n /**\n * If size tracking is enabled, then setting an explicit size\n * in the {@link LRUCache#set} call will prevent calling the\n * {@link OptionsBase.sizeCalculation} function.\n */\n size?: Size\n /**\n * If TTL tracking is enabled, then setting an explicit start\n * time in the {@link LRUCache#set} call will override the\n * default time from `performance.now()` or `Date.now()`.\n *\n * Note that it must be a valid value for whichever time-tracking\n * method is in use.\n */\n start?: Milliseconds\n status?: Status<V>\n }\n\n /**\n * The type signature for the {@link OptionsBase.fetchMethod} option.\n */\n export type Fetcher<K, V, FC = unknown> = (\n key: K,\n staleValue: V | undefined,\n options: FetcherOptions<K, V, FC>,\n ) => Promise<V | undefined | void> | V | undefined | void\n\n /**\n * the type signature for the {@link OptionsBase.memoMethod} option.\n */\n export type Memoizer<K, V, FC = unknown> = (\n key: K,\n staleValue: V | undefined,\n options: MemoizerOptions<K, V, FC>,\n ) => V\n\n /**\n * Options which may be passed to the {@link LRUCache} constructor.\n *\n * Most of these may be overridden in the various options that use\n * them.\n *\n * Despite all being technically optional, the constructor requires that\n * a cache is at minimum limited by one or more of {@link OptionsBase.max},\n * {@link OptionsBase.ttl}, or {@link OptionsBase.maxSize}.\n *\n * If {@link OptionsBase.ttl} is used alone, then it is strongly advised\n * (and in fact required by the type definitions here) that the cache\n * also set {@link OptionsBase.ttlAutopurge}, to prevent potentially\n * unbounded storage.\n *\n * All options are also available on the {@link LRUCache} instance, making\n * it safe to pass an LRUCache instance as the options argumemnt to\n * make another empty cache of the same type.\n *\n * Some options are marked as read-only, because changing them after\n * instantiation is not safe. Changing any of the other options will of\n * course only have an effect on subsequent method calls.\n */\n export interface OptionsBase<K, V, FC> {\n /**\n * The maximum number of items to store in the cache before evicting\n * old entries. This is read-only on the {@link LRUCache} instance,\n * and may not be overridden.\n *\n * If set, then storage space will be pre-allocated at construction\n * time, and the cache will perform significantly faster.\n *\n * Note that significantly fewer items may be stored, if\n * {@link OptionsBase.maxSize} and/or {@link OptionsBase.ttl} are also\n * set.\n *\n * **It is strongly recommended to set a `max` to prevent unbounded growth\n * of the cache.**\n */\n max?: Count\n\n /**\n * Max time in milliseconds for items to live in cache before they are\n * considered stale. Note that stale items are NOT preemptively removed by\n * default, and MAY live in the cache, contributing to its LRU max, long\n * after they have expired, unless {@link OptionsBase.ttlAutopurge} is\n * set.\n *\n * If set to `0` (the default value), then that means \"do not track\n * TTL\", not \"expire immediately\".\n *\n * Also, as this cache is optimized for LRU/MRU operations, some of\n * the staleness/TTL checks will reduce performance, as they will incur\n * overhead by deleting items.\n *\n * This is not primarily a TTL cache, and does not make strong TTL\n * guarantees. There is no pre-emptive pruning of expired items, but you\n * _may_ set a TTL on the cache, and it will treat expired items as missing\n * when they are fetched, and delete them.\n *\n * Optional, but must be a non-negative integer in ms if specified.\n *\n * This may be overridden by passing an options object to `cache.set()`.\n *\n * At least one of `max`, `maxSize`, or `TTL` is required. This must be a\n * positive integer if set.\n *\n * Even if ttl tracking is enabled, **it is strongly recommended to set a\n * `max` to prevent unbounded growth of the cache.**\n *\n * If ttl tracking is enabled, and `max` and `maxSize` are not set,\n * and `ttlAutopurge` is not set, then a warning will be emitted\n * cautioning about the potential for unbounded memory consumption.\n * (The TypeScript definitions will also discourage this.)\n */\n ttl?: Milliseconds\n\n /**\n * Minimum amount of time in ms in which to check for staleness.\n * Defaults to 1, which means that the current time is checked\n * at most once per millisecond.\n *\n * Set to 0 to check the current time every time staleness is tested.\n * (This reduces performance, and is theoretically unnecessary.)\n *\n * Setting this to a higher value will improve performance somewhat\n * while using ttl tracking, albeit at the expense of keeping stale\n * items around a bit longer than their TTLs would indicate.\n *\n * @default 1\n */\n ttlResolution?: Milliseconds\n\n /**\n * Preemptively remove stale items from the cache.\n *\n * Note that this may *significantly* degrade performance, especially if\n * the cache is storing a large number of items. It is almost always best\n * to just leave the stale items in the cache, and let them fall out as new\n * items are added.\n *\n * Note that this means that {@link OptionsBase.allowStale} is a bit\n * pointless, as stale items will be deleted almost as soon as they\n * expire.\n *\n * Use with caution!\n */\n ttlAutopurge?: boolean\n\n /**\n * When using time-expiring entries with `ttl`, setting this to `true` will\n * make each item's age reset to 0 whenever it is retrieved from cache with\n * {@link LRUCache#get}, causing it to not expire. (It can still fall out\n * of cache based on recency of use, of course.)\n *\n * Has no effect if {@link OptionsBase.ttl} is not set.\n *\n * This may be overridden by passing an options object to `cache.get()`.\n */\n updateAgeOnGet?: boolean\n\n /**\n * When using time-expiring entries with `ttl`, setting this to `true` will\n * make each item's age reset to 0 whenever its presence in the cache is\n * checked with {@link LRUCache#has}, causing it to not expire. (It can\n * still fall out of cache based on recency of use, of course.)\n *\n * Has no effect if {@link OptionsBase.ttl} is not set.\n */\n updateAgeOnHas?: boolean\n\n /**\n * Allow {@link LRUCache#get} and {@link LRUCache#fetch} calls to return\n * stale data, if available.\n *\n * By default, if you set `ttl`, stale items will only be deleted from the\n * cache when you `get(key)`. That is, it's not preemptively pruning items,\n * unless {@link OptionsBase.ttlAutopurge} is set.\n *\n * If you set `allowStale:true`, it'll return the stale value *as well as*\n * deleting it. If you don't set this, then it'll return `undefined` when\n * you try to get a stale entry.\n *\n * Note that when a stale entry is fetched, _even if it is returned due to\n * `allowStale` being set_, it is removed from the cache immediately. You\n * can suppress this behavior by setting\n * {@link OptionsBase.noDeleteOnStaleGet}, either in the constructor, or in\n * the options provided to {@link LRUCache#get}.\n *\n * This may be overridden by passing an options object to `cache.get()`.\n * The `cache.has()` method will always return `false` for stale items.\n *\n * Only relevant if a ttl is set.\n */\n allowStale?: boolean\n\n /**\n * Function that is called on items when they are dropped from the\n * cache, as `dispose(value, key, reason)`.\n *\n * This can be handy if you want to close file descriptors or do\n * other cleanup tasks when items are no longer stored in the cache.\n *\n * **NOTE**: It is called _before_ the item has been fully removed\n * from the cache, so if you want to put it right back in, you need\n * to wait until the next tick. If you try to add it back in during\n * the `dispose()` function call, it will break things in subtle and\n * weird ways.\n *\n * Unlike several other options, this may _not_ be overridden by\n * passing an option to `set()`, for performance reasons.\n *\n * The `reason` will be one of the following strings, corresponding\n * to the reason for the item's deletion:\n *\n * - `evict` Item was evicted to make space for a new addition\n * - `set` Item was overwritten by a new value\n * - `expire` Item expired its TTL\n * - `fetch` Item was deleted due to a failed or aborted fetch, or a\n * fetchMethod returning `undefined.\n * - `delete` Item was removed by explicit `cache.delete(key)`,\n * `cache.clear()`, or `cache.set(key, undefined)`.\n */\n dispose?: Disposer<K, V>\n\n /**\n * Function that is called when new items are inserted into the cache,\n * as `onInsert(value, key, reason)`.\n *\n * This can be useful if you need to perform actions when an item is\n * added, such as logging or tracking insertions.\n *\n * Unlike some other options, this may _not_ be overridden by passing\n * an option to `set()`, for performance and consistency reasons.\n */\n onInsert?: Inserter<K, V>\n\n /**\n * The same as {@link OptionsBase.dispose}, but called *after* the entry\n * is completely removed and the cache is once again in a clean state.\n *\n * It is safe to add an item right back into the cache at this point.\n * However, note that it is *very* easy to inadvertently create infinite\n * recursion this way.\n */\n disposeAfter?: Disposer<K, V>\n\n /**\n * Set to true to suppress calling the\n * {@link OptionsBase.dispose} function if the entry key is\n * still accessible within the cache.\n *\n * This may be overridden by passing an options object to\n * {@link LRUCache#set}.\n *\n * Only relevant if `dispose` or `disposeAfter` are set.\n */\n noDisposeOnSet?: boolean\n\n /**\n * Boolean flag to tell the cache to not update the TTL when setting a new\n * value for an existing key (ie, when updating a value rather than\n * inserting a new value). Note that the TTL value is _always_ set (if\n * provided) when adding a new entry into the cache.\n *\n * Has no effect if a {@link OptionsBase.ttl} is not set.\n *\n * May be passed as an option to {@link LRUCache#set}.\n */\n noUpdateTTL?: boolean\n\n /**\n * Set to a positive integer to track the sizes of items added to the\n * cache, and automatically evict items in order to stay below this size.\n * Note that this may result in fewer than `max` items being stored.\n *\n * Attempting to add an item to the cache whose calculated size is greater\n * that this amount will be a no-op. The item will not be cached, and no\n * other items will be evicted.\n *\n * Optional, must be a positive integer if provided.\n *\n * Sets `maxEntrySize` to the same value, unless a different value is\n * provided for `maxEntrySize`.\n *\n * At least one of `max`, `maxSize`, or `TTL` is required. This must be a\n * positive integer if set.\n *\n * Even if size tracking is enabled, **it is strongly recommended to set a\n * `max` to prevent unbounded growth of the cache.**\n *\n * Note also that size tracking can negatively impact performance,\n * though for most cases, only minimally.\n */\n maxSize?: Size\n\n /**\n * The maximum allowed size for any single item in the cache.\n *\n * If a larger item is passed to {@link LRUCache#set} or returned by a\n * {@link OptionsBase.fetchMethod} or {@link OptionsBase.memoMethod}, then\n * it will not be stored in the cache.\n *\n * Attempting to add an item whose calculated size is greater than\n * this amount will not cache the item or evict any old items, but\n * WILL delete an existing value if one is already present.\n *\n * Optional, must be a positive integer if provided. Defaults to\n * the value of `maxSize` if provided.\n */\n maxEntrySize?: Size\n\n /**\n * A function that returns a number indicating the item's size.\n *\n * Requires {@link OptionsBase.maxSize} to be set.\n *\n * If not provided, and {@link OptionsBase.maxSize} or\n * {@link OptionsBase.maxEntrySize} are set, then all\n * {@link LRUCache#set} calls **must** provide an explicit\n * {@link SetOptions.size} or sizeCalculation param.\n */\n sizeCalculation?: SizeCalculator<K, V>\n\n /**\n * Method that provides the implementation for {@link LRUCache#fetch}\n *\n * ```ts\n * fetchMethod(key, staleValue, { signal, options, context })\n * ```\n *\n * If `fetchMethod` is not provided, then `cache.fetch(key)` is equivalent\n * to `Promise.resolve(cache.get(key))`.\n *\n * If at any time, `signal.aborted` is set to `true`, or if the\n * `signal.onabort` method is called, or if it emits an `'abort'` event\n * which you can listen to with `addEventListener`, then that means that\n * the fetch should be abandoned. This may be passed along to async\n * functions aware of AbortController/AbortSignal behavior.\n *\n * The `fetchMethod` should **only** return `undefined` or a Promise\n * resolving to `undefined` if the AbortController signaled an `abort`\n * event. In all other cases, it should return or resolve to a value\n * suitable for adding to the cache.\n *\n * The `options` object is a union of the options that may be provided to\n * `set()` and `get()`. If they are modified, then that will result in\n * modifying the settings to `cache.set()` when the value is resolved, and\n * in the case of\n * {@link OptionsBase.noDeleteOnFetchRejection} and\n * {@link OptionsBase.allowStaleOnFetchRejection}, the handling of\n * `fetchMethod` failures.\n *\n * For example, a DNS cache may update the TTL based on the value returned\n * from a remote DNS server by changing `options.ttl` in the `fetchMethod`.\n */\n fetchMethod?: Fetcher<K, V, FC>\n\n /**\n * Method that provides the implementation for {@link LRUCache#memo}\n */\n memoMethod?: Memoizer<K, V, FC>\n\n /**\n * Set to true to suppress the deletion of stale data when a\n * {@link OptionsBase.fetchMethod} returns a rejected promise.\n */\n noDeleteOnFetchRejection?: boolean\n\n /**\n * Do not delete stale items when they are retrieved with\n * {@link LRUCache#get}.\n *\n * Note that the `get` return value will still be `undefined`\n * unless {@link OptionsBase.allowStale} is true.\n *\n * When using time-expiring entries with `ttl`, by default stale\n * items will be removed from the cache when the key is accessed\n * with `cache.get()`.\n *\n * Setting this option will cause stale items to remain in the cache, until\n * they are explicitly deleted with `cache.delete(key)`, or retrieved with\n * `noDeleteOnStaleGet` set to `false`.\n *\n * This may be overridden by passing an options object to `cache.get()`.\n *\n * Only relevant if a ttl is used.\n */\n noDeleteOnStaleGet?: boolean\n\n /**\n * Set to true to allow returning stale data when a\n * {@link OptionsBase.fetchMethod} throws an error or returns a rejected\n * promise.\n *\n * This differs from using {@link OptionsBase.allowStale} in that stale\n * data will ONLY be returned in the case that the {@link LRUCache#fetch}\n * fails, not any other times.\n *\n * If a `fetchMethod` fails, and there is no stale value available, the\n * `fetch()` will resolve to `undefined`. Ie, all `fetchMethod` errors are\n * suppressed.\n *\n * Implies `noDeleteOnFetchRejection`.\n *\n * This may be set in calls to `fetch()`, or defaulted on the constructor,\n * or overridden by modifying the options object in the `fetchMethod`.\n */\n allowStaleOnFetchRejection?: boolean\n\n /**\n * Set to true to return a stale value from the cache when the\n * `AbortSignal` passed to the {@link OptionsBase.fetchMethod} dispatches\n * an `'abort'` event, whether user-triggered, or due to internal cache\n * behavior.\n *\n * Unless {@link OptionsBase.ignoreFetchAbort} is also set, the underlying\n * {@link OptionsBase.fetchMethod} will still be considered canceled, and\n * any value it returns will be ignored and not cached.\n *\n * Caveat: since fetches are aborted when a new value is explicitly\n * set in the cache, this can lead to fetch returning a stale value,\n * since that was the fallback value _at the moment the `fetch()` was\n * initiated_, even though the new updated value is now present in\n * the cache.\n *\n * For example:\n *\n * ```ts\n * const cache = new LRUCache<string, any>({\n * ttl: 100,\n * fetchMethod: async (url, oldValue, { signal }) => {\n * const res = await fetch(url, { signal })\n * return await res.json()\n * }\n * })\n * cache.set('https://example.com/', { some: 'data' })\n * // 100ms go by...\n * const result = cache.fetch('https://example.com/')\n * cache.set('https://example.com/', { other: 'thing' })\n * console.log(await result) // { some: 'data' }\n * console.log(cache.get('https://example.com/')) // { other: 'thing' }\n * ```\n */\n allowStaleOnFetchAbort?: boolean\n\n /**\n * Set to true to ignore the `abort` event emitted by the `AbortSignal`\n * object passed to {@link OptionsBase.fetchMethod}, and still cache the\n * resulting resolution value, as long as it is not `undefined`.\n *\n * When used on its own, this means aborted {@link LRUCache#fetch} calls\n * are not immediately resolved or rejected when they are aborted, and\n * instead take the full time to await.\n *\n * When used with {@link OptionsBase.allowStaleOnFetchAbort}, aborted\n * {@link LRUCache#fetch} calls will resolve immediately to their stale\n * cached value or `undefined`, and will continue to process and eventually\n * update the cache when they resolve, as long as the resulting value is\n * not `undefined`, thus supporting a \"return stale on timeout while\n * refreshing\" mechanism by passing `AbortSignal.timeout(n)` as the signal.\n *\n * For example:\n *\n * ```ts\n * const c = new LRUCache({\n * ttl: 100,\n * ignoreFetchAbort: true,\n * allowStaleOnFetchAbort: true,\n * fetchMethod: async (key, oldValue, { signal }) => {\n * // note: do NOT pass the signal to fetch()!\n * // let's say this fetch can take a long time.\n * const res = await fetch(`https://slow-backend-server/${key}`)\n * return await res.json()\n * },\n * })\n *\n * // this will return the stale value after 100ms, while still\n * // updating in the background for next time.\n * const val = await c.fetch('key', { signal: AbortSignal.timeout(100) })\n * ```\n *\n * **Note**: regardless of this setting, an `abort` event _is still\n * emitted on the `AbortSignal` object_, so may result in invalid results\n * when passed to other underlying APIs that use AbortSignals.\n *\n * This may be overridden in the {@link OptionsBase.fetchMethod} or the\n * call to {@link LRUCache#fetch}.\n */\n ignoreFetchAbort?: boolean\n\n /**\n * In some cases, you may want to swap out the performance/Date object\n * used for TTL tracking. This should almost certainly NOT be done in\n * production environments!\n *\n * This value defaults to `global.performance` if it has a `now()` method,\n * or the `global.Date` object otherwise.\n */\n perf?: Perf\n }\n\n export interface OptionsMaxLimit<K, V, FC>\n extends OptionsBase<K, V, FC> {\n max: Count\n }\n export interface OptionsTTLLimit<K, V, FC>\n extends OptionsBase<K, V, FC> {\n ttl: Milliseconds\n ttlAutopurge: boolean\n }\n export interface OptionsSizeLimit<K, V, FC>\n extends OptionsBase<K, V, FC> {\n maxSize: Size\n }\n\n /**\n * The valid safe options for the {@link LRUCache} constructor\n */\n export type Options<K, V, FC> =\n | OptionsMaxLimit<K, V, FC>\n | OptionsSizeLimit<K, V, FC>\n | OptionsTTLLimit<K, V, FC>\n\n /**\n * Entry objects used by {@link LRUCache#load} and {@link LRUCache#dump},\n * and returned by {@link LRUCache#info}.\n */\n export interface Entry<V> {\n value: V\n ttl?: Milliseconds\n size?: Size\n start?: Milliseconds\n }\n}\n\n/**\n * Default export, the thing you're using this module to get.\n *\n * The `K` and `V` types define the key and value types, respectively. The\n * optional `FC` type defines the type of the `context` object passed to\n * `cache.fetch()` and `cache.memo()`.\n *\n * Keys and values **must not** be `null` or `undefined`.\n *\n * All properties from the options object (with the exception of `max`,\n * `maxSize`, `fetchMethod`, `memoMethod`, `dispose` and `disposeAfter`) are\n * added as normal public members. (The listed options are read-only getters.)\n *\n * Changing any of these will alter the defaults for subsequent method calls.\n */\nexport class LRUCache<K extends {}, V extends {}, FC = unknown> {\n // options that cannot be changed without disaster\n readonly #max: LRUCache.Count\n readonly #maxSize: LRUCache.Size\n readonly #dispose?: LRUCache.Disposer<K, V>\n readonly #onInsert?: LRUCache.Inserter<K, V>\n readonly #disposeAfter?: LRUCache.Disposer<K, V>\n readonly #fetchMethod?: LRUCache.Fetcher<K, V, FC>\n readonly #memoMethod?: LRUCache.Memoizer<K, V, FC>\n readonly #perf: Perf\n\n /**\n * {@link LRUCache.OptionsBase.perf}\n */\n get perf() {\n return this.#perf\n }\n\n /**\n * {@link LRUCache.OptionsBase.ttl}\n */\n ttl: LRUCache.Milliseconds\n\n /**\n * {@link LRUCache.OptionsBase.ttlResolution}\n */\n ttlResolution: LRUCache.Milliseconds\n /**\n * {@link LRUCache.OptionsBase.ttlAutopurge}\n */\n ttlAutopurge: boolean\n /**\n * {@link LRUCache.OptionsBase.updateAgeOnGet}\n */\n updateAgeOnGet: boolean\n /**\n * {@link LRUCache.OptionsBase.updateAgeOnHas}\n */\n updateAgeOnHas: boolean\n /**\n * {@link LRUCache.OptionsBase.allowStale}\n */\n allowStale: boolean\n\n /**\n * {@link LRUCache.OptionsBase.noDisposeOnSet}\n */\n noDisposeOnSet: boolean\n /**\n * {@link LRUCache.OptionsBase.noUpdateTTL}\n */\n noUpdateTTL: boolean\n /**\n * {@link LRUCache.OptionsBase.maxEntrySize}\n */\n maxEntrySize: LRUCache.Size\n /**\n * {@link LRUCache.OptionsBase.sizeCalculation}\n */\n sizeCalculation?: LRUCache.SizeCalculator<K, V>\n /**\n * {@link LRUCache.OptionsBase.noDeleteOnFetchRejection}\n */\n noDeleteOnFetchRejection: boolean\n /**\n * {@link LRUCache.OptionsBase.noDeleteOnStaleGet}\n */\n noDeleteOnStaleGet: boolean\n /**\n * {@link LRUCache.OptionsBase.allowStaleOnFetchAbort}\n */\n allowStaleOnFetchAbort: boolean\n /**\n * {@link LRUCache.OptionsBase.allowStaleOnFetchRejection}\n */\n allowStaleOnFetchRejection: boolean\n /**\n * {@link LRUCache.OptionsBase.ignoreFetchAbort}\n */\n ignoreFetchAbort: boolean\n\n // computed properties\n #size: LRUCache.Count\n #calculatedSize: LRUCache.Size\n #keyMap: Map<K, Index>\n #keyList: (K | undefined)[]\n #valList: (V | BackgroundFetch<V> | undefined)[]\n #next: NumberArray\n #prev: NumberArray\n #head: Index\n #tail: Index\n #free: StackLike\n #disposed?: DisposeTask<K, V>[]\n #sizes?: ZeroArray\n #starts?: ZeroArray\n #ttls?: ZeroArray\n #autopurgeTimers?: (undefined | ReturnType<typeof setTimeout>)[]\n\n #hasDispose: boolean\n #hasFetchMethod: boolean\n #hasDisposeAfter: boolean\n #hasOnInsert: boolean\n\n /**\n * Do not call this method unless you need to inspect the\n * inner workings of the cache. If anything returned by this\n * object is modified in any way, strange breakage may occur.\n *\n * These fields are private for a reason!\n *\n * @internal\n */\n static unsafeExposeInternals<\n K extends {},\n V extends {},\n FC extends unknown = unknown,\n >(c: LRUCache<K, V, FC>) {\n return {\n // properties\n starts: c.#starts,\n ttls: c.#ttls,\n autopurgeTimers: c.#autopurgeTimers,\n sizes: c.#sizes,\n keyMap: c.#keyMap as Map<K, number>,\n keyList: c.#keyList,\n valList: c.#valList,\n next: c.#next,\n prev: c.#prev,\n get head() {\n return c.#head\n },\n get tail() {\n return c.#tail\n },\n free: c.#free,\n // methods\n isBackgroundFetch: (p: any) => c.#isBackgroundFetch(p),\n backgroundFetch: (\n k: K,\n index: number | undefined,\n options: LRUCache.FetchOptions<K, V, FC>,\n context: any,\n ): BackgroundFetch<V> =>\n c.#backgroundFetch(\n k,\n index as Index | undefined,\n options,\n context,\n ),\n moveToTail: (index: number): void => c.#moveToTail(index as Index),\n indexes: (options?: { allowStale: boolean }) => c.#indexes(options),\n rindexes: (options?: { allowStale: boolean }) =>\n c.#rindexes(options),\n isStale: (index: number | undefined) => c.#isStale(index as Index),\n }\n }\n\n // Protected read-only members\n\n /**\n * {@link LRUCache.OptionsBase.max} (read-only)\n */\n get max(): LRUCache.Count {\n return this.#max\n }\n /**\n * {@link LRUCache.OptionsBase.maxSize} (read-only)\n */\n get maxSize(): LRUCache.Count {\n return this.#maxSize\n }\n /**\n * The total computed size of items in the cache (read-only)\n */\n get calculatedSize(): LRUCache.Size {\n return this.#calculatedSize\n }\n /**\n * The number of items stored in the cache (read-only)\n */\n get size(): LRUCache.Count {\n return this.#size\n }\n /**\n * {@link LRUCache.OptionsBase.fetchMethod} (read-only)\n */\n get fetchMethod(): LRUCache.Fetcher<K, V, FC> | undefined {\n return this.#fetchMethod\n }\n get memoMethod(): LRUCache.Memoizer<K, V, FC> | undefined {\n return this.#memoMethod\n }\n /**\n * {@link LRUCache.OptionsBase.dispose} (read-only)\n */\n get dispose() {\n return this.#dispose\n }\n /**\n * {@link LRUCache.OptionsBase.onInsert} (read-only)\n */\n get onInsert() {\n return this.#onInsert\n }\n /**\n * {@link LRUCache.OptionsBase.disposeAfter} (read-only)\n */\n get disposeAfter() {\n return this.#disposeAfter\n }\n\n constructor(options: LRUCache.Options<K, V, FC> | LRUCache<K, V, FC>) {\n const {\n max = 0,\n ttl,\n ttlResolution = 1,\n ttlAutopurge,\n updateAgeOnGet,\n updateAgeOnHas,\n allowStale,\n dispose,\n onInsert,\n disposeAfter,\n noDisposeOnSet,\n noUpdateTTL,\n maxSize = 0,\n maxEntrySize = 0,\n sizeCalculation,\n fetchMethod,\n memoMethod,\n noDeleteOnFetchRejection,\n noDeleteOnStaleGet,\n allowStaleOnFetchRejection,\n allowStaleOnFetchAbort,\n ignoreFetchAbort,\n perf,\n } = options\n\n if (perf !== undefined) {\n if (typeof perf?.now !== 'function') {\n throw new TypeError(\n 'perf option must have a now() method if specified',\n )\n }\n }\n\n this.#perf = perf ?? defaultPerf\n\n if (max !== 0 && !isPosInt(max)) {\n throw new TypeError('max option must be a nonnegative integer')\n }\n\n const UintArray = max ? getUintArray(max) : Array\n if (!UintArray) {\n throw new Error('invalid max value: ' + max)\n }\n\n this.#max = max\n this.#maxSize = maxSize\n this.maxEntrySize = maxEntrySize || this.#maxSize\n this.sizeCalculation = sizeCalculation\n if (this.sizeCalculation) {\n if (!this.#maxSize && !this.maxEntrySize) {\n throw new TypeError(\n 'cannot set sizeCalculation without setting maxSize or maxEntrySize',\n )\n }\n if (typeof this.sizeCalculation !== 'function') {\n throw new TypeError('sizeCalculation set to non-function')\n }\n }\n\n if (memoMethod !== undefined && typeof memoMethod !== 'function') {\n throw new TypeError('memoMethod must be a function if defined')\n }\n this.#memoMethod = memoMethod\n\n if (fetchMethod !== undefined && typeof fetchMethod !== 'function') {\n throw new TypeError('fetchMethod must be a function if specified')\n }\n this.#fetchMethod = fetchMethod\n this.#hasFetchMethod = !!fetchMethod\n\n this.#keyMap = new Map()\n this.#keyList = new Array(max).fill(undefined)\n this.#valList = new Array(max).fill(undefined)\n this.#next = new UintArray(max)\n this.#prev = new UintArray(max)\n this.#head = 0 as Index\n this.#tail = 0 as Index\n this.#free = Stack.create(max)\n this.#size = 0\n this.#calculatedSize = 0\n\n if (typeof dispose === 'function') {\n this.#dispose = dispose\n }\n if (typeof onInsert === 'function') {\n this.#onInsert = onInsert\n }\n if (typeof disposeAfter === 'function') {\n this.#disposeAfter = disposeAfter\n this.#disposed = []\n } else {\n this.#disposeAfter = undefined\n this.#disposed = undefined\n }\n this.#hasDispose = !!this.#dispose\n this.#hasOnInsert = !!this.#onInsert\n this.#hasDisposeAfter = !!this.#disposeAfter\n\n this.noDisposeOnSet = !!noDisposeOnSet\n this.noUpdateTTL = !!noUpdateTTL\n this.noDeleteOnFetchRejection = !!noDeleteOnFetchRejection\n this.allowStaleOnFetchRejection = !!allowStaleOnFetchRejection\n this.allowStaleOnFetchAbort = !!allowStaleOnFetchAbort\n this.ignoreFetchAbort = !!ignoreFetchAbort\n\n // NB: maxEntrySize is set to maxSize if it's set\n if (this.maxEntrySize !== 0) {\n if (this.#maxSize !== 0) {\n if (!isPosInt(this.#maxSize)) {\n throw new TypeError(\n 'maxSize must be a positive integer if specified',\n )\n }\n }\n if (!isPosInt(this.maxEntrySize)) {\n throw new TypeError(\n 'maxEntrySize must be a positive integer if specified',\n )\n }\n this.#initializeSizeTracking()\n }\n\n this.allowStale = !!allowStale\n this.noDeleteOnStaleGet = !!noDeleteOnStaleGet\n this.updateAgeOnGet = !!updateAgeOnGet\n this.updateAgeOnHas = !!updateAgeOnHas\n this.ttlResolution =\n isPosInt(ttlResolution) || ttlResolution === 0 ? ttlResolution : 1\n this.ttlAutopurge = !!ttlAutopurge\n this.ttl = ttl || 0\n if (this.ttl) {\n if (!isPosInt(this.ttl)) {\n throw new TypeError('ttl must be a positive integer if specified')\n }\n this.#initializeTTLTracking()\n }\n\n // do not allow completely unbounded caches\n if (this.#max === 0 && this.ttl === 0 && this.#maxSize === 0) {\n throw new TypeError(\n 'At least one of max, maxSize, or ttl is required',\n )\n }\n if (!this.ttlAutopurge && !this.#max && !this.#maxSize) {\n const code = 'LRU_CACHE_UNBOUNDED'\n if (shouldWarn(code)) {\n warned.add(code)\n const msg =\n 'TTL caching without ttlAutopurge, max, or maxSize can ' +\n 'result in unbounded memory consumption.'\n emitWarning(msg, 'UnboundedCacheWarning', code, LRUCache)\n }\n }\n }\n\n /**\n * Return the number of ms left in the item's TTL. If item is not in cache,\n * returns `0`. Returns `Infinity` if item is in cache without a defined TTL.\n */\n getRemainingTTL(key: K) {\n return this.#keyMap.has(key) ? Infinity : 0\n }\n\n #initializeTTLTracking() {\n const ttls = new ZeroArray(this.#max)\n const starts = new ZeroArray(this.#max)\n this.#ttls = ttls\n this.#starts = starts\n const purgeTimers =\n this.ttlAutopurge ?\n new Array<undefined | ReturnType<typeof setTimeout>>(this.#max)\n : undefined\n this.#autopurgeTimers = purgeTimers\n\n this.#setItemTTL = (index, ttl, start = this.#perf.now()) => {\n starts[index] = ttl !== 0 ? start : 0\n ttls[index] = ttl\n // clear out the purge timer if we're setting TTL to 0, and\n // previously had a ttl purge timer running, so it doesn't\n // fire unnecessarily.\n if (purgeTimers?.[index]) {\n clearTimeout(purgeTimers[index])\n purgeTimers[index] = undefined\n }\n if (ttl !== 0 && purgeTimers) {\n const t = setTimeout(() => {\n if (this.#isStale(index)) {\n this.#delete(this.#keyList[index] as K, 'expire')\n }\n }, ttl + 1)\n // unref() not supported on all platforms\n /* c8 ignore start */\n if (t.unref) {\n t.unref()\n }\n /* c8 ignore stop */\n purgeTimers[index] = t\n }\n }\n\n this.#updateItemAge = index => {\n starts[index] = ttls[index] !== 0 ? this.#perf.now() : 0\n }\n\n this.#statusTTL = (status, index) => {\n if (ttls[index]) {\n const ttl = ttls[index]\n const start = starts[index]\n /* c8 ignore next */\n if (!ttl || !start) return\n status.ttl = ttl\n status.start = start\n status.now = cachedNow || getNow()\n const age = status.now - start\n status.remainingTTL = ttl - age\n }\n }\n\n // debounce calls to perf.now() to 1s so we're not hitting\n // that costly call repeatedly.\n let cachedNow = 0\n const getNow = () => {\n const n = this.#perf.now()\n if (this.ttlResolution > 0) {\n cachedNow = n\n const t = setTimeout(() => (cachedNow = 0), this.ttlResolution)\n // not available on all platforms\n /* c8 ignore start */\n if (t.unref) {\n t.unref()\n }\n /* c8 ignore stop */\n }\n return n\n }\n\n this.getRemainingTTL = key => {\n const index = this.#keyMap.get(key)\n if (index === undefined) {\n return 0\n }\n const ttl = ttls[index]\n const start = starts[index]\n if (!ttl || !start) {\n return Infinity\n }\n const age = (cachedNow || getNow()) - start\n return ttl - age\n }\n\n this.#isStale = index => {\n const s = starts[index]\n const t = ttls[index]\n return !!t && !!s && (cachedNow || getNow()) - s > t\n }\n }\n\n // conditionally set private methods related to TTL\n #updateItemAge: (index: Index) => void = () => {}\n #statusTTL: (status: LRUCache.Status<V>, index: Index) => void = () => {}\n #setItemTTL: (\n index: Index,\n ttl: LRUCache.Milliseconds,\n start?: LRUCache.Milliseconds,\n // ignore because we never call this if we're not already in TTL mode\n /* c8 ignore start */\n ) => void = () => {}\n /* c8 ignore stop */\n\n #isStale: (index: Index) => boolean = () => false\n\n #initializeSizeTracking() {\n const sizes = new ZeroArray(this.#max)\n this.#calculatedSize = 0\n this.#sizes = sizes\n this.#removeItemSize = index => {\n this.#calculatedSize -= sizes[index] as number\n sizes[index] = 0\n }\n this.#requireSize = (k, v, size, sizeCalculation) => {\n // provisionally accept background fetches.\n // actual value size will be checked when they return.\n if (this.#isBackgroundFetch(v)) {\n return 0\n }\n if (!isPosInt(size)) {\n if (sizeCalculation) {\n if (typeof sizeCalculation !== 'function') {\n throw new TypeError('sizeCalculation must be a function')\n }\n size = sizeCalculation(v, k)\n if (!isPosInt(size)) {\n throw new TypeError(\n 'sizeCalculation return invalid (expect positive integer)',\n )\n }\n } else {\n throw new TypeError(\n 'invalid size value (must be positive integer). ' +\n 'When maxSize or maxEntrySize is used, sizeCalculation ' +\n 'or size must be set.',\n )\n }\n }\n return size\n }\n this.#addItemSize = (\n index: Index,\n size: LRUCache.Size,\n status?: LRUCache.Status<V>,\n ) => {\n sizes[index] = size\n if (this.#maxSize) {\n const maxSize = this.#maxSize - (sizes[index] as number)\n while (this.#calculatedSize > maxSize) {\n this.#evict(true)\n }\n }\n this.#calculatedSize += sizes[index] as number\n if (status) {\n status.entrySize = size\n status.totalCalculatedSize = this.#calculatedSize\n }\n }\n }\n\n #removeItemSize: (index: Index) => void = _i => {}\n #addItemSize: (\n index: Index,\n size: LRUCache.Size,\n status?: LRUCache.Status<V>,\n ) => void = (_i, _s, _st) => {}\n #requireSize: (\n k: K,\n v: V | BackgroundFetch<V>,\n size?: LRUCache.Size,\n sizeCalculation?: LRUCache.SizeCalculator<K, V>,\n ) => LRUCache.Size = (\n _k: K,\n _v: V | BackgroundFetch<V>,\n size?: LRUCache.Size,\n sizeCalculation?: LRUCache.SizeCalculator<K, V>,\n ) => {\n if (size || sizeCalculation) {\n throw new TypeError(\n 'cannot set size without setting maxSize or maxEntrySize on cache',\n )\n }\n return 0\n };\n\n *#indexes({ allowStale = this.allowStale } = {}) {\n if (this.#size) {\n for (let i = this.#tail; true; ) {\n if (!this.#isValidIndex(i)) {\n break\n }\n if (allowStale || !this.#isStale(i)) {\n yield i\n }\n if (i === this.#head) {\n break\n } else {\n i = this.#prev[i] as Index\n }\n }\n }\n }\n\n *#rindexes({ allowStale = this.allowStale } = {}) {\n if (this.#size) {\n for (let i = this.#head; true; ) {\n if (!this.#isValidIndex(i)) {\n break\n }\n if (allowStale || !this.#isStale(i)) {\n yield i\n }\n if (i === this.#tail) {\n break\n } else {\n i = this.#next[i] as Index\n }\n }\n }\n }\n\n #isValidIndex(index: Index) {\n return (\n index !== undefined &&\n this.#keyMap.get(this.#keyList[index] as K) === index\n )\n }\n\n /**\n * Return a generator yielding `[key, value]` pairs,\n * in order from most recently used to least recently used.\n */\n *entries() {\n for (const i of this.#indexes()) {\n if (\n this.#valList[i] !== undefined &&\n this.#keyList[i] !== undefined &&\n !this.#isBackgroundFetch(this.#valList[i])\n ) {\n yield [this.#keyList[i], this.#valList[i]] as [K, V]\n }\n }\n }\n\n /**\n * Inverse order version of {@link LRUCache.entries}\n *\n * Return a generator yielding `[key, value]` pairs,\n * in order from least recently used to most recently used.\n */\n *rentries() {\n for (const i of this.#rindexes()) {\n if (\n this.#valList[i] !== undefined &&\n this.#keyList[i] !== undefined &&\n !this.#isBackgroundFetch(this.#valList[i])\n ) {\n yield [this.#keyList[i], this.#valList[i]]\n }\n }\n }\n\n /**\n * Return a generator yielding the keys in the cache,\n * in order from most recently used to least recently used.\n */\n *keys() {\n for (const i of this.#indexes()) {\n const k = this.#keyList[i]\n if (k !== undefined && !this.#isBackgroundFetch(this.#valList[i])) {\n yield k\n }\n }\n }\n\n /**\n * Inverse order version of {@link LRUCache.keys}\n *\n * Return a generator yielding the keys in the cache,\n * in order from least recently used to most recently used.\n */\n *rkeys() {\n for (const i of this.#rindexes()) {\n const k = this.#keyList[i]\n if (k !== undefined && !this.#isBackgroundFetch(this.#valList[i])) {\n yield k\n }\n }\n }\n\n /**\n * Return a generator yielding the values in the cache,\n * in order from most recently used to least recently used.\n */\n *values() {\n for (const i of this.#indexes()) {\n const v = this.#valList[i]\n if (v !== undefined && !this.#isBackgroundFetch(this.#valList[i])) {\n yield this.#valList[i] as V\n }\n }\n }\n\n /**\n * Inverse order version of {@link LRUCache.values}\n *\n * Return a generator yielding the values in the cache,\n * in order from least recently used to most recently used.\n */\n *rvalues() {\n for (const i of this.#rindexes()) {\n const v = this.#valList[i]\n if (v !== undefined && !this.#isBackgroundFetch(this.#valList[i])) {\n yield this.#valList[i]\n }\n }\n }\n\n /**\n * Iterating over the cache itself yields the same results as\n * {@link LRUCache.entries}\n */\n [Symbol.iterator]() {\n return this.entries()\n }\n\n /**\n * A String value that is used in the creation of the default string\n * description of an object. Called by the built-in method\n * `Object.prototype.toString`.\n */\n [Symbol.toStringTag] = 'LRUCache'\n\n /**\n * Find a value for which the supplied fn method returns a truthy value,\n * similar to `Array.find()`. fn is called as `fn(value, key, cache)`.\n */\n find(\n fn: (v: V, k: K, self: LRUCache<K, V, FC>) => boolean,\n getOptions: LRUCache.GetOptions<K, V, FC> = {},\n ) {\n for (const i of this.#indexes()) {\n const v = this.#valList[i]\n const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v\n if (value === undefined) continue\n if (fn(value, this.#keyList[i] as K, this)) {\n return this.get(this.#keyList[i] as K, getOptions)\n }\n }\n }\n\n /**\n * Call the supplied function on each item in the cache, in order from most\n * recently used to least recently used.\n *\n * `fn` is called as `fn(value, key, cache)`.\n *\n * If `thisp` is provided, function will be called in the `this`-context of\n * the provided object, or the cache if no `thisp` object is provided.\n *\n * Does not update age or recenty of use, or iterate over stale values.\n */\n forEach(\n fn: (v: V, k: K, self: LRUCache<K, V, FC>) => any,\n thisp: any = this,\n ) {\n for (const i of this.#indexes()) {\n const v = this.#valList[i]\n const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v\n if (value === undefined) continue\n fn.call(thisp, value, this.#keyList[i] as K, this)\n }\n }\n\n /**\n * The same as {@link LRUCache.forEach} but items are iterated over in\n * reverse order. (ie, less recently used items are iterated over first.)\n */\n rforEach(\n fn: (v: V, k: K, self: LRUCache<K, V, FC>) => any,\n thisp: any = this,\n ) {\n for (const i of this.#rindexes()) {\n const v = this.#valList[i]\n const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v\n if (value === undefined) continue\n fn.call(thisp, value, this.#keyList[i] as K, this)\n }\n }\n\n /**\n * Delete any stale entries. Returns true if anything was removed,\n * false otherwise.\n */\n purgeStale() {\n let deleted = false\n for (const i of this.#rindexes({ allowStale: true })) {\n if (this.#isStale(i)) {\n this.#delete(this.#keyList[i] as K, 'expire')\n deleted = true\n }\n }\n return deleted\n }\n\n /**\n * Get the extended info about a given entry, to get its value, size, and\n * TTL info simultaneously. Returns `undefined` if the key is not present.\n *\n * Unlike {@link LRUCache#dump}, which is designed to be portable and survive\n * serialization, the `start` value is always the current timestamp, and the\n * `ttl` is a calculated remaining time to live (negative if expired).\n *\n * Always returns stale values, if their info is found in the cache, so be\n * sure to check for expirations (ie, a negative {@link LRUCache.Entry#ttl})\n * if relevant.\n */\n info(key: K): LRUCache.Entry<V> | undefined {\n const i = this.#keyMap.get(key)\n if (i === undefined) return undefined\n const v = this.#valList[i]\n /* c8 ignore start - this isn't tested for the info function,\n * but it's the same logic as found in other places. */\n const value: V | undefined =\n this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v\n if (value === undefined) return undefined\n /* c8 ignore end */\n const entry: LRUCache.Entry<V> = { value }\n if (this.#ttls && this.#starts) {\n const ttl = this.#ttls[i]\n const start = this.#starts[i]\n if (ttl && start) {\n const remain = ttl - (this.#perf.now() - start)\n entry.ttl = remain\n entry.start = Date.now()\n }\n }\n if (this.#sizes) {\n entry.size = this.#sizes[i]\n }\n return entry\n }\n\n /**\n * Return an array of [key, {@link LRUCache.Entry}] tuples which can be\n * passed to {@link LRUCache#load}.\n *\n * The `start` fields are calculated relative to a portable `Date.now()`\n * timestamp, even if `performance.now()` is available.\n *\n * Stale entries are always included in the `dump`, even if\n * {@link LRUCache.OptionsBase.allowStale} is false.\n *\n * Note: this returns an actual array, not a generator, so it can be more\n * easily passed around.\n */\n dump() {\n const arr: [K, LRUCache.Entry<V>][] = []\n for (const i of this.#indexes({ allowStale: true })) {\n const key = this.#keyList[i]\n const v = this.#valList[i]\n const value: V | undefined =\n this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v\n if (value === undefined || key === undefined) continue\n const entry: LRUCache.Entry<V> = { value }\n if (this.#ttls && this.#starts) {\n entry.ttl = this.#ttls[i]\n // always dump the start relative to a portable timestamp\n // it's ok for this to be a bit slow, it's a rare operation.\n const age = this.#perf.now() - (this.#starts[i] as number)\n entry.start = Math.floor(Date.now() - age)\n }\n if (this.#sizes) {\n entry.size = this.#sizes[i]\n }\n arr.unshift([key, entry])\n }\n return arr\n }\n\n /**\n * Reset the cache and load in the items in entries in the order listed.\n *\n * The shape of the resulting cache may be different if the same options are\n * not used in both caches.\n *\n * The `start` fields are assumed to be calculated relative to a portable\n * `Date.now()` timestamp, even if `performance.now()` is available.\n */\n load(arr: [K, LRUCache.Entry<V>][]) {\n this.clear()\n for (const [key, entry] of arr) {\n if (entry.start) {\n // entry.start is a portable timestamp, but we may be using\n // node's performance.now(), so calculate the offset, so that\n // we get the intended remaining TTL, no matter how long it's\n // been on ice.\n //\n // it's ok for this to be a bit slow, it's a rare operation.\n const age = Date.now() - entry.start\n entry.start = this.#perf.now() - age\n }\n this.set(key, entry.value, entry)\n }\n }\n\n /**\n * Add a value to the cache.\n *\n * Note: if `undefined` is specified as a value, this is an alias for\n * {@link LRUCache#delete}\n *\n * Fields on the {@link LRUCache.SetOptions} options param will override\n * their corresponding values in the constructor options for the scope\n * of this single `set()` operation.\n *\n * If `start` is provided, then that will set the effective start\n * time for the TTL calculation. Note that this must be a previous\n * value of `performance.now()` if supported, or a previous value of\n * `Date.now()` if not.\n *\n * Options object may also include `size`, which will prevent\n * calling the `sizeCalculation` function and just use the specified\n * number if it is a positive integer, and `noDisposeOnSet` which\n * will prevent calling a `dispose` function in the case of\n * overwrites.\n *\n * If the `size` (or return value of `sizeCalculation`) for a given\n * entry is greater than `maxEntrySize`, then the item will not be\n * added to the cache.\n *\n * Will update the recency of the entry.\n *\n * If the value is `undefined`, then this is an alias for\n * `cache.delete(key)`. `undefined` is never stored in the cache.\n */\n set(\n k: K,\n v: V | BackgroundFetch<V> | undefined,\n setOptions: LRUCache.SetOptions<K, V, FC> = {},\n ) {\n if (v === undefined) {\n this.delete(k)\n return this\n }\n const {\n ttl = this.ttl,\n start,\n noDisposeOnSet = this.noDisposeOnSet,\n sizeCalculation = this.sizeCalculation,\n status,\n } = setOptions\n let { noUpdateTTL = this.noUpdateTTL } = setOptions\n\n const size = this.#requireSize(\n k,\n v,\n setOptions.size || 0,\n sizeCalculation,\n )\n // if the item doesn't fit, don't do anything\n // NB: maxEntrySize set to maxSize by default\n if (this.maxEntrySize && size > this.maxEntrySize) {\n if (status) {\n status.set = 'miss'\n status.maxEntrySizeExceeded = true\n }\n // have to delete, in case something is there already.\n this.#delete(k, 'set')\n return this\n }\n let index = this.#size === 0 ? undefined : this.#keyMap.get(k)\n if (index === undefined) {\n // addition\n index = (\n this.#size === 0 ? this.#tail\n : this.#free.length !== 0 ? this.#free.pop()\n : this.#size === this.#max ? this.#evict(false)\n : this.#size) as Index\n this.#keyList[index] = k\n this.#valList[index] = v\n this.#keyMap.set(k, index)\n this.#next[this.#tail] = index\n this.#prev[index] = this.#tail\n this.#tail = index\n this.#size++\n this.#addItemSize(index, size, status)\n if (status) status.set = 'add'\n noUpdateTTL = false\n if (this.#hasOnInsert) {\n this.#onInsert?.(v as V, k, 'add')\n }\n } else {\n // update\n this.#moveToTail(index)\n const oldVal = this.#valList[index] as V | BackgroundFetch<V>\n if (v !== oldVal) {\n if (this.#hasFetchMethod && this.#isBackgroundFetch(oldVal)) {\n oldVal.__abortController.abort(new Error('replaced'))\n const { __staleWhileFetching: s } = oldVal\n if (s !== undefined && !noDisposeOnSet) {\n if (this.#hasDispose) {\n this.#dispose?.(s as V, k, 'set')\n }\n if (this.#hasDisposeAfter) {\n this.#disposed?.push([s as V, k, 'set'])\n }\n }\n } else if (!noDisposeOnSet) {\n if (this.#hasDispose) {\n this.#dispose?.(oldVal as V, k, 'set')\n }\n if (this.#hasDisposeAfter) {\n this.#disposed?.push([oldVal as V, k, 'set'])\n }\n }\n this.#removeItemSize(index)\n this.#addItemSize(index, size, status)\n this.#valList[index] = v\n if (status) {\n status.set = 'replace'\n const oldValue =\n oldVal && this.#isBackgroundFetch(oldVal) ?\n oldVal.__staleWhileFetching\n : oldVal\n if (oldValue !== undefined) status.oldValue = oldValue\n }\n } else if (status) {\n status.set = 'update'\n }\n\n if (this.#hasOnInsert) {\n this.onInsert?.(v as V, k, v === oldVal ? 'update' : 'replace')\n }\n }\n if (ttl !== 0 && !this.#ttls) {\n this.#initializeTTLTracking()\n }\n if (this.#ttls) {\n if (!noUpdateTTL) {\n this.#setItemTTL(index, ttl, start)\n }\n if (status) this.#statusTTL(status, index)\n }\n if (!noDisposeOnSet && this.#hasDisposeAfter && this.#disposed) {\n const dt = this.#disposed\n let task: DisposeTask<K, V> | undefined\n while ((task = dt?.shift())) {\n this.#disposeAfter?.(...task)\n }\n }\n return this\n }\n\n /**\n * Evict the least recently used item, returning its value or\n * `undefined` if cache is empty.\n */\n pop(): V | undefined {\n try {\n while (this.#size) {\n const val = this.#valList[this.#head]\n this.#evict(true)\n if (this.#isBackgroundFetch(val)) {\n if (val.__staleWhileFetching) {\n return val.__staleWhileFetching\n }\n } else if (val !== undefined) {\n return val\n }\n }\n } finally {\n if (this.#hasDisposeAfter && this.#disposed) {\n const dt = this.#disposed\n let task: DisposeTask<K, V> | undefined\n while ((task = dt?.shift())) {\n this.#disposeAfter?.(...task)\n }\n }\n }\n }\n\n #evict(free: boolean) {\n const head = this.#head\n const k = this.#keyList[head] as K\n const v = this.#valList[head] as V\n if (this.#hasFetchMethod && this.#isBackgroundFetch(v)) {\n v.__abortController.abort(new Error('evicted'))\n } else if (this.#hasDispose || this.#hasDisposeAfter) {\n if (this.#hasDispose) {\n this.#dispose?.(v, k, 'evict')\n }\n if (this.#hasDisposeAfter) {\n this.#disposed?.push([v, k, 'evict'])\n }\n }\n this.#removeItemSize(head)\n if (this.#autopurgeTimers?.[head]) {\n clearTimeout(this.#autopurgeTimers[head])\n this.#autopurgeTimers[head] = undefined\n }\n // if we aren't about to use the index, then null these out\n if (free) {\n this.#keyList[head] = undefined\n this.#valList[head] = undefined\n this.#free.push(head)\n }\n if (this.#size === 1) {\n this.#head = this.#tail = 0 as Index\n this.#free.length = 0\n } else {\n this.#head = this.#next[head] as Index\n }\n this.#keyMap.delete(k)\n this.#size--\n return head\n }\n\n /**\n * Check if a key is in the cache, without updating the recency of use.\n * Will return false if the item is stale, even though it is technically\n * in the cache.\n *\n * Check if a key is in the cache, without updating the recency of\n * use. Age is updated if {@link LRUCache.OptionsBase.updateAgeOnHas} is set\n * to `true` in either the options or the constructor.\n *\n * Will return `false` if the item is stale, even though it is technically in\n * the cache. The difference can be determined (if it matters) by using a\n * `status` argument, and inspecting the `has` field.\n *\n * Will not update item age unless\n * {@link LRUCache.OptionsBase.updateAgeOnHas} is set.\n */\n has(k: K, hasOptions: LRUCache.HasOptions<K, V, FC> = {}) {\n const { updateAgeOnHas = this.updateAgeOnHas, status } = hasOptions\n const index = this.#keyMap.get(k)\n if (index !== undefined) {\n const v = this.#valList[index]\n if (\n this.#isBackgroundFetch(v) &&\n v.__staleWhileFetching === undefined\n ) {\n return false\n }\n if (!this.#isStale(index)) {\n if (updateAgeOnHas) {\n this.#updateItemAge(index)\n }\n if (status) {\n status.has = 'hit'\n this.#statusTTL(status, index)\n }\n return true\n } else if (status) {\n status.has = 'stale'\n this.#statusTTL(status, index)\n }\n } else if (status) {\n status.has = 'miss'\n }\n return false\n }\n\n /**\n * Like {@link LRUCache#get} but doesn't update recency or delete stale\n * items.\n *\n * Returns `undefined` if the item is stale, unless\n * {@link LRUCache.OptionsBase.allowStale} is set.\n */\n peek(k: K, peekOptions: LRUCache.PeekOptions<K, V, FC> = {}) {\n const { allowStale = this.allowStale } = peekOptions\n const index = this.#keyMap.get(k)\n if (index === undefined || (!allowStale && this.#isStale(index))) {\n return\n }\n const v = this.#valList[index]\n // either stale and allowed, or forcing a refresh of non-stale value\n return this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v\n }\n\n #backgroundFetch(\n k: K,\n index: Index | undefined,\n options: LRUCache.FetchOptions<K, V, FC>,\n context: any,\n ): BackgroundFetch<V> {\n const v = index === undefined ? undefined : this.#valList[index]\n if (this.#isBackgroundFetch(v)) {\n return v\n }\n\n const ac = new AC()\n const { signal } = options\n // when/if our AC signals, then stop listening to theirs.\n signal?.addEventListener('abort', () => ac.abort(signal.reason), {\n signal: ac.signal,\n })\n\n const fetchOpts = {\n signal: ac.signal,\n options,\n context,\n }\n\n const cb = (v: V | undefined, updateCache = false): V | undefined => {\n const { aborted } = ac.signal\n const ignoreAbort = options.ignoreFetchAbort && v !== undefined\n const proceed = options.ignoreFetchAbort ||\n !!(options.allowStaleOnFetchAbort && v !== undefined)\n if (options.status) {\n if (aborted && !updateCache) {\n options.status.fetchAborted = true\n options.status.fetchError = ac.signal.reason\n if (ignoreAbort) options.status.fetchAbortIgnored = true\n } else {\n options.status.fetchResolved = true\n }\n }\n if (aborted && !ignoreAbort && !updateCache) {\n return fetchFail(ac.signal.reason, proceed)\n }\n // either we didn't abort, and are still here, or we did, and ignored\n const bf = p as BackgroundFetch<V>\n // if nothing else has been written there but we're set to update the\n // cache and ignore the abort, or if it's still pending on this specific\n // background request, then write it to the cache.\n const vl = this.#valList[index as Index]\n if (vl === p || (ignoreAbort && updateCache && vl === undefined)) {\n if (v === undefined) {\n if (bf.__staleWhileFetching !== undefined) {\n this.#valList[index as Index] = bf.__staleWhileFetching\n } else {\n this.#delete(k, 'fetch')\n }\n } else {\n if (options.status) options.status.fetchUpdated = true\n this.set(k, v, fetchOpts.options)\n }\n }\n return v\n }\n\n const eb = (er: any) => {\n if (options.status) {\n options.status.fetchRejected = true\n options.status.fetchError = er\n }\n // do not pass go, do not collect $200\n return fetchFail(er, false)\n }\n\n const fetchFail = (er: any, proceed: boolean): V | undefined => {\n const { aborted } = ac.signal\n const allowStaleAborted = aborted && options.allowStaleOnFetchAbort\n const allowStale =\n allowStaleAborted || options.allowStaleOnFetchRejection\n const noDelete = allowStale || options.noDeleteOnFetchRejection\n const bf = p as BackgroundFetch<V>\n if (this.#valList[index as Index] === p) {\n // if we allow stale on fetch rejections, then we need to ensure that\n // the stale value is not removed from the cache when the fetch fails.\n const del = !noDelete ||\n !proceed && bf.__staleWhileFetching === undefined\n if (del) {\n this.#delete(k, 'fetch')\n } else if (!allowStaleAborted) {\n // still replace the *promise* with the stale value,\n // since we are done with the promise at this point.\n // leave it untouched if we're still waiting for an\n // aborted background fetch that hasn't yet returned.\n this.#valList[index as Index] = bf.__staleWhileFetching\n }\n }\n if (allowStale) {\n if (options.status && bf.__staleWhileFetching !== undefined) {\n options.status.returnedStale = true\n }\n return bf.__staleWhileFetching\n } else if (bf.__returned === bf) {\n throw er\n }\n }\n\n const pcall = (\n res: (v: V | undefined) => void,\n rej: (e: any) => void,\n ) => {\n const fmp = this.#fetchMethod?.(k, v, fetchOpts)\n if (fmp && fmp instanceof Promise) {\n fmp.then(v => res(v === undefined ? undefined : v), rej)\n }\n // ignored, we go until we finish, regardless.\n // defer check until we are actually aborting,\n // so fetchMethod can override.\n ac.signal.addEventListener('abort', () => {\n if (!options.ignoreFetchAbort || options.allowStaleOnFetchAbort) {\n res(undefined)\n // when it eventually resolves, update the cache.\n if (options.allowStaleOnFetchAbort) {\n res = v => cb(v, true)\n }\n }\n })\n }\n\n if (options.status) options.status.fetchDispatched = true\n const p = new Promise(pcall).then(cb, eb)\n const bf: BackgroundFetch<V> = Object.assign(p, {\n __abortController: ac,\n __staleWhileFetching: v,\n __returned: undefined,\n })\n\n if (index === undefined) {\n // internal, don't expose status.\n this.set(k, bf, { ...fetchOpts.options, status: undefined })\n index = this.#keyMap.get(k)\n } else {\n this.#valList[index] = bf\n }\n return bf\n }\n\n #isBackgroundFetch(p: any): p is BackgroundFetch<V> {\n if (!this.#hasFetchMethod) return false\n const b = p as BackgroundFetch<V>\n return (\n !!b &&\n b instanceof Promise &&\n b.hasOwnProperty('__staleWhileFetching') &&\n b.__abortController instanceof AC\n )\n }\n\n /**\n * Make an asynchronous cached fetch using the\n * {@link LRUCache.OptionsBase.fetchMethod} function.\n *\n * If the value is in the cache and not stale, then the returned\n * Promise resolves to the value.\n *\n * If not in the cache, or beyond its TTL staleness, then\n * `fetchMethod(key, staleValue, { options, signal, context })` is\n * called, and the value returned will be added to the cache once\n * resolved.\n *\n * If called with `allowStale`, and an asynchronous fetch is\n * currently in progress to reload a stale value, then the former\n * stale value will be returned.\n *\n * If called with `forceRefresh`, then the cached item will be\n * re-fetched, even if it is not stale. However, if `allowStale` is also\n * set, then the old value will still be returned. This is useful\n * in cases where you want to force a reload of a cached value. If\n * a background fetch is already in progress, then `forceRefresh`\n * has no effect.\n *\n * If multiple fetches for the same key are issued, then they will all be\n * coalesced into a single call to fetchMethod.\n *\n * Note that this means that handling options such as\n * {@link LRUCache.OptionsBase.allowStaleOnFetchAbort},\n * {@link LRUCache.FetchOptions.signal},\n * and {@link LRUCache.OptionsBase.allowStaleOnFetchRejection} will be\n * determined by the FIRST fetch() call for a given key.\n *\n * This is a known (fixable) shortcoming which will be addresed on when\n * someone complains about it, as the fix would involve added complexity and\n * may not be worth the costs for this edge case.\n *\n * If {@link LRUCache.OptionsBase.fetchMethod} is not specified, then this is\n * effectively an alias for `Promise.resolve(cache.get(key))`.\n *\n * When the fetch method resolves to a value, if the fetch has not\n * been aborted due to deletion, eviction, or being overwritten,\n * then it is added to the cache using the options provided.\n *\n * If the key is evicted or deleted before the `fetchMethod`\n * resolves, then the AbortSignal passed to the `fetchMethod` will\n * receive an `abort` event, and the promise returned by `fetch()`\n * will reject with the reason for the abort.\n *\n * If a `signal` is passed to the `fetch()` call, then aborting the\n * signal will abort the fetch and cause the `fetch()` promise to\n * reject with the reason provided.\n *\n * **Setting `context`**\n *\n * If an `FC` type is set to a type other than `unknown`, `void`, or\n * `undefined` in the {@link LRUCache} constructor, then all\n * calls to `cache.fetch()` _must_ provide a `context` option. If\n * set to `undefined` or `void`, then calls to fetch _must not_\n * provide a `context` option.\n *\n * The `context` param allows you to provide arbitrary data that\n * might be relevant in the course of fetching the data. It is only\n * relevant for the course of a single `fetch()` operation, and\n * discarded afterwards.\n *\n * **Note: `fetch()` calls are inflight-unique**\n *\n * If you call `fetch()` multiple times with the same key value,\n * then every call after the first will resolve on the same\n * promise<sup>1</sup>,\n * _even if they have different settings that would otherwise change\n * the behavior of the fetch_, such as `noDeleteOnFetchRejection`\n * or `ignoreFetchAbort`.\n *\n * In most cases, this is not a problem (in fact, only fetching\n * something once is what you probably want, if you're caching in\n * the first place). If you are changing the fetch() options\n * dramatically between runs, there's a good chance that you might\n * be trying to fit divergent semantics into a single object, and\n * would be better off with multiple cache instances.\n *\n * **1**: Ie, they're not the \"same Promise\", but they resolve at\n * the same time, because they're both waiting on the same\n * underlying fetchMethod response.\n */\n\n fetch(\n k: K,\n fetchOptions: unknown extends FC ? LRUCache.FetchOptions<K, V, FC>\n : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V>\n : LRUCache.FetchOptionsWithContext<K, V, FC>,\n ): Promise<undefined | V>\n\n // this overload not allowed if context is required\n fetch(\n k: unknown extends FC ? K\n : FC extends undefined | void ? K\n : never,\n fetchOptions?: unknown extends FC ? LRUCache.FetchOptions<K, V, FC>\n : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V>\n : never,\n ): Promise<undefined | V>\n\n async fetch(\n k: K,\n fetchOptions: LRUCache.FetchOptions<K, V, FC> = {},\n ): Promise<undefined | V> {\n const {\n // get options\n allowStale = this.allowStale,\n updateAgeOnGet = this.updateAgeOnGet,\n noDeleteOnStaleGet = this.noDeleteOnStaleGet,\n // set options\n ttl = this.ttl,\n noDisposeOnSet = this.noDisposeOnSet,\n size = 0,\n sizeCalculation = this.sizeCalculation,\n noUpdateTTL = this.noUpdateTTL,\n // fetch exclusive options\n noDeleteOnFetchRejection = this.noDeleteOnFetchRejection,\n allowStaleOnFetchRejection = this.allowStaleOnFetchRejection,\n ignoreFetchAbort = this.ignoreFetchAbort,\n allowStaleOnFetchAbort = this.allowStaleOnFetchAbort,\n context,\n forceRefresh = false,\n status,\n signal,\n } = fetchOptions\n\n if (!this.#hasFetchMethod) {\n if (status) status.fetch = 'get'\n return this.get(k, {\n allowStale,\n updateAgeOnGet,\n noDeleteOnStaleGet,\n status,\n })\n }\n\n const options = {\n allowStale,\n updateAgeOnGet,\n noDeleteOnStaleGet,\n ttl,\n noDisposeOnSet,\n size,\n sizeCalculation,\n noUpdateTTL,\n noDeleteOnFetchRejection,\n allowStaleOnFetchRejection,\n allowStaleOnFetchAbort,\n ignoreFetchAbort,\n status,\n signal,\n }\n\n let index = this.#keyMap.get(k)\n if (index === undefined) {\n if (status) status.fetch = 'miss'\n const p = this.#backgroundFetch(k, index, options, context)\n return (p.__returned = p)\n } else {\n // in cache, maybe already fetching\n const v = this.#valList[index]\n if (this.#isBackgroundFetch(v)) {\n const stale = allowStale && v.__staleWhileFetching !== undefined\n if (status) {\n status.fetch = 'inflight'\n if (stale) status.returnedStale = true\n }\n return stale ? v.__staleWhileFetching : (v.__returned = v)\n }\n\n // if we force a refresh, that means do NOT serve the cached value,\n // unless we are already in the process of refreshing the cache.\n const isStale = this.#isStale(index)\n if (!forceRefresh && !isStale) {\n if (status) status.fetch = 'hit'\n this.#moveToTail(index)\n if (updateAgeOnGet) {\n this.#updateItemAge(index)\n }\n if (status) this.#statusTTL(status, index)\n return v\n }\n\n // ok, it is stale or a forced refresh, and not already fetching.\n // refresh the cache.\n const p = this.#backgroundFetch(k, index, options, context)\n const hasStale = p.__staleWhileFetching !== undefined\n const staleVal = hasStale && allowStale\n if (status) {\n status.fetch = isStale ? 'stale' : 'refresh'\n if (staleVal && isStale) status.returnedStale = true\n }\n return staleVal ? p.__staleWhileFetching : (p.__returned = p)\n }\n }\n\n /**\n * In some cases, `cache.fetch()` may resolve to `undefined`, either because\n * a {@link LRUCache.OptionsBase#fetchMethod} was not provided (turning\n * `cache.fetch(k)` into just an async wrapper around `cache.get(k)`) or\n * because `ignoreFetchAbort` was specified (either to the constructor or\n * in the {@link LRUCache.FetchOptions}). Also, the\n * {@link LRUCache.OptionsBase.fetchMethod} may return `undefined` or `void`, making\n * the test even more complicated.\n *\n * Because inferring the cases where `undefined` might be returned are so\n * cumbersome, but testing for `undefined` can also be annoying, this method\n * can be used, which will reject if `this.fetch()` resolves to undefined.\n */\n forceFetch(\n k: K,\n fetchOptions: unknown extends FC ? LRUCache.FetchOptions<K, V, FC>\n : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V>\n : LRUCache.FetchOptionsWithContext<K, V, FC>,\n ): Promise<V>\n // this overload not allowed if context is required\n forceFetch(\n k: unknown extends FC ? K\n : FC extends undefined | void ? K\n : never,\n fetchOptions?: unknown extends FC ? LRUCache.FetchOptions<K, V, FC>\n : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V>\n : never,\n ): Promise<V>\n async forceFetch(\n k: K,\n fetchOptions: LRUCache.FetchOptions<K, V, FC> = {},\n ): Promise<V> {\n const v = await this.fetch(\n k,\n fetchOptions as unknown extends FC ? LRUCache.FetchOptions<K, V, FC>\n : FC extends undefined | void ? LRUCache.FetchOptionsNoContext<K, V>\n : LRUCache.FetchOptionsWithContext<K, V, FC>,\n )\n if (v === undefined) throw new Error('fetch() returned undefined')\n return v\n }\n\n /**\n * If the key is found in the cache, then this is equivalent to\n * {@link LRUCache#get}. If not, in the cache, then calculate the value using\n * the {@link LRUCache.OptionsBase.memoMethod}, and add it to the cache.\n *\n * If an `FC` type is set to a type other than `unknown`, `void`, or\n * `undefined` in the LRUCache constructor, then all calls to `cache.memo()`\n * _must_ provide a `context` option. If set to `undefined` or `void`, then\n * calls to memo _must not_ provide a `context` option.\n *\n * The `context` param allows you to provide arbitrary data that might be\n * relevant in the course of fetching the data. It is only relevant for the\n * course of a single `memo()` operation, and discarded afterwards.\n */\n memo(\n k: K,\n memoOptions: unknown extends FC ? LRUCache.MemoOptions<K, V, FC>\n : FC extends undefined | void ? LRUCache.MemoOptionsNoContext<K, V>\n : LRUCache.MemoOptionsWithContext<K, V, FC>,\n ): V\n // this overload not allowed if context is required\n memo(\n k: unknown extends FC ? K\n : FC extends undefined | void ? K\n : never,\n memoOptions?: unknown extends FC ? LRUCache.MemoOptions<K, V, FC>\n : FC extends undefined | void ? LRUCache.MemoOptionsNoContext<K, V>\n : never,\n ): V\n memo(k: K, memoOptions: LRUCache.MemoOptions<K, V, FC> = {}) {\n const memoMethod = this.#memoMethod\n if (!memoMethod) {\n throw new Error('no memoMethod provided to constructor')\n }\n const { context, forceRefresh, ...options } = memoOptions\n const v = this.get(k, options)\n if (!forceRefresh && v !== undefined) return v\n const vv = memoMethod(k, v, {\n options,\n context,\n } as LRUCache.MemoizerOptions<K, V, FC>)\n this.set(k, vv, options)\n return vv\n }\n\n /**\n * Return a value from the cache. Will update the recency of the cache\n * entry found.\n *\n * If the key is not found, get() will return `undefined`.\n */\n get(k: K, getOptions: LRUCache.GetOptions<K, V, FC> = {}) {\n const {\n allowStale = this.allowStale,\n updateAgeOnGet = this.updateAgeOnGet,\n noDeleteOnStaleGet = this.noDeleteOnStaleGet,\n status,\n } = getOptions\n const index = this.#keyMap.get(k)\n if (index !== undefined) {\n const value = this.#valList[index]\n const fetching = this.#isBackgroundFetch(value)\n if (status) this.#statusTTL(status, index)\n if (this.#isStale(index)) {\n if (status) status.get = 'stale'\n // delete only if not an in-flight background fetch\n if (!fetching) {\n if (!noDeleteOnStaleGet) {\n this.#delete(k, 'expire')\n }\n if (status && allowStale) status.returnedStale = true\n return allowStale ? value : undefined\n } else {\n if (\n status &&\n allowStale &&\n value.__staleWhileFetching !== undefined\n ) {\n status.returnedStale = true\n }\n return allowStale ? value.__staleWhileFetching : undefined\n }\n } else {\n if (status) status.get = 'hit'\n // if we're currently fetching it, we don't actually have it yet\n // it's not stale, which means this isn't a staleWhileRefetching.\n // If it's not stale, and fetching, AND has a __staleWhileFetching\n // value, then that means the user fetched with {forceRefresh:true},\n // so it's safe to return that value.\n if (fetching) {\n return value.__staleWhileFetching\n }\n this.#moveToTail(index)\n if (updateAgeOnGet) {\n this.#updateItemAge(index)\n }\n return value\n }\n } else if (status) {\n status.get = 'miss'\n }\n }\n\n #connect(p: Index, n: Index) {\n this.#prev[n] = p\n this.#next[p] = n\n }\n\n #moveToTail(index: Index): void {\n // if tail already, nothing to do\n // if head, move head to next[index]\n // else\n // move next[prev[index]] to next[index] (head has no prev)\n // move prev[next[index]] to prev[index]\n // prev[index] = tail\n // next[tail] = index\n // tail = index\n if (index !== this.#tail) {\n if (index === this.#head) {\n this.#head = this.#next[index] as Index\n } else {\n this.#connect(\n this.#prev[index] as Index,\n this.#next[index] as Index,\n )\n }\n this.#connect(this.#tail, index)\n this.#tail = index\n }\n }\n\n /**\n * Deletes a key out of the cache.\n *\n * Returns true if the key was deleted, false otherwise.\n */\n delete(k: K) {\n return this.#delete(k, 'delete')\n }\n\n #delete(k: K, reason: LRUCache.DisposeReason) {\n let deleted = false\n if (this.#size !== 0) {\n const index = this.#keyMap.get(k)\n if (index !== undefined) {\n if (this.#autopurgeTimers?.[index]) {\n clearTimeout(this.#autopurgeTimers?.[index])\n this.#autopurgeTimers[index] = undefined\n }\n deleted = true\n if (this.#size === 1) {\n this.#clear(reason)\n } else {\n this.#removeItemSize(index)\n const v = this.#valList[index]\n if (this.#isBackgroundFetch(v)) {\n v.__abortController.abort(new Error('deleted'))\n } else if (this.#hasDispose || this.#hasDisposeAfter) {\n if (this.#hasDispose) {\n this.#dispose?.(v as V, k, reason)\n }\n if (this.#hasDisposeAfter) {\n this.#disposed?.push([v as V, k, reason])\n }\n }\n this.#keyMap.delete(k)\n this.#keyList[index] = undefined\n this.#valList[index] = undefined\n if (index === this.#tail) {\n this.#tail = this.#prev[index] as Index\n } else if (index === this.#head) {\n this.#head = this.#next[index] as Index\n } else {\n const pi = this.#prev[index] as number\n this.#next[pi] = this.#next[index] as number\n const ni = this.#next[index] as number\n this.#prev[ni] = this.#prev[index] as number\n }\n this.#size--\n this.#free.push(index)\n }\n }\n }\n if (this.#hasDisposeAfter && this.#disposed?.length) {\n const dt = this.#disposed\n let task: DisposeTask<K, V> | undefined\n while ((task = dt?.shift())) {\n this.#disposeAfter?.(...task)\n }\n }\n return deleted\n }\n\n /**\n * Clear the cache entirely, throwing away all values.\n */\n clear() {\n return this.#clear('delete')\n }\n #clear(reason: LRUCache.DisposeReason) {\n for (const index of this.#rindexes({ allowStale: true })) {\n const v = this.#valList[index]\n if (this.#isBackgroundFetch(v)) {\n v.__abortController.abort(new Error('deleted'))\n } else {\n const k = this.#keyList[index]\n if (this.#hasDispose) {\n this.#dispose?.(v as V, k as K, reason)\n }\n if (this.#hasDisposeAfter) {\n this.#disposed?.push([v as V, k as K, reason])\n }\n }\n }\n\n this.#keyMap.clear()\n this.#valList.fill(undefined)\n this.#keyList.fill(undefined)\n if (this.#ttls && this.#starts) {\n this.#ttls.fill(0)\n this.#starts.fill(0)\n for (const t of this.#autopurgeTimers ?? []) {\n if (t !== undefined) clearTimeout(t)\n }\n this.#autopurgeTimers?.fill(undefined)\n }\n if (this.#sizes) {\n this.#sizes.fill(0)\n }\n this.#head = 0 as Index\n this.#tail = 0 as Index\n this.#free.length = 0\n this.#calculatedSize = 0\n this.#size = 0\n if (this.#hasDisposeAfter && this.#disposed) {\n const dt = this.#disposed\n let task: DisposeTask<K, V> | undefined\n while ((task = dt?.shift())) {\n this.#disposeAfter?.(...task)\n }\n }\n }\n}\n","import { LRUCache } from 'lru-cache'\nimport { posix, win32 } from 'node:path'\n\nimport { fileURLToPath } from 'node:url'\n\nimport {\n lstatSync,\n readdir as readdirCB,\n readdirSync,\n readlinkSync,\n realpathSync as rps,\n} from 'fs'\nimport * as actualFS from 'node:fs'\n\nconst realpathSync = rps.native\n// TODO: test perf of fs/promises realpath vs realpathCB,\n// since the promises one uses realpath.native\n\nimport { lstat, readdir, readlink, realpath } from 'node:fs/promises'\n\nimport { Minipass } from 'minipass'\nimport type { Dirent, Stats } from 'node:fs'\n\n/**\n * An object that will be used to override the default `fs`\n * methods. Any methods that are not overridden will use Node's\n * built-in implementations.\n *\n * - lstatSync\n * - readdir (callback `withFileTypes` Dirent variant, used for\n * readdirCB and most walks)\n * - readdirSync\n * - readlinkSync\n * - realpathSync\n * - promises: Object containing the following async methods:\n * - lstat\n * - readdir (Dirent variant only)\n * - readlink\n * - realpath\n */\nexport interface FSOption {\n lstatSync?: (path: string) => Stats\n readdir?: (\n path: string,\n options: { withFileTypes: true },\n cb: (er: NodeJS.ErrnoException | null, entries?: Dirent[]) => any,\n ) => void\n readdirSync?: (\n path: string,\n options: { withFileTypes: true },\n ) => Dirent[]\n readlinkSync?: (path: string) => string\n realpathSync?: (path: string) => string\n promises?: {\n lstat?: (path: string) => Promise<Stats>\n readdir?: (\n path: string,\n options: { withFileTypes: true },\n ) => Promise<Dirent[]>\n readlink?: (path: string) => Promise<string>\n realpath?: (path: string) => Promise<string>\n [k: string]: any\n }\n [k: string]: any\n}\n\ninterface FSValue {\n lstatSync: (path: string) => Stats\n readdir: (\n path: string,\n options: { withFileTypes: true },\n cb: (er: NodeJS.ErrnoException | null, entries?: Dirent[]) => any,\n ) => void\n readdirSync: (path: string, options: { withFileTypes: true }) => Dirent[]\n readlinkSync: (path: string) => string\n realpathSync: (path: string) => string\n promises: {\n lstat: (path: string) => Promise<Stats>\n readdir: (\n path: string,\n options: { withFileTypes: true },\n ) => Promise<Dirent[]>\n readlink: (path: string) => Promise<string>\n realpath: (path: string) => Promise<string>\n [k: string]: any\n }\n [k: string]: any\n}\n\nconst defaultFS: FSValue = {\n lstatSync,\n readdir: readdirCB,\n readdirSync,\n readlinkSync,\n realpathSync,\n promises: {\n lstat,\n readdir,\n readlink,\n realpath,\n },\n}\n\n// if they just gave us require('fs') then use our default\nconst fsFromOption = (fsOption?: FSOption): FSValue =>\n !fsOption || fsOption === defaultFS || fsOption === actualFS ?\n defaultFS\n : {\n ...defaultFS,\n ...fsOption,\n promises: {\n ...defaultFS.promises,\n ...(fsOption.promises || {}),\n },\n }\n\n// turn something like //?/c:/ into c:\\\nconst uncDriveRegexp = /^\\\\\\\\\\?\\\\([a-z]:)\\\\?$/i\nconst uncToDrive = (rootPath: string): string =>\n rootPath.replace(/\\//g, '\\\\').replace(uncDriveRegexp, '$1\\\\')\n\n// windows paths are separated by either / or \\\nconst eitherSep = /[\\\\\\/]/\n\nconst UNKNOWN = 0 // may not even exist, for all we know\nconst IFIFO = 0b0001\nconst IFCHR = 0b0010\nconst IFDIR = 0b0100\nconst IFBLK = 0b0110\nconst IFREG = 0b1000\nconst IFLNK = 0b1010\nconst IFSOCK = 0b1100\nconst IFMT = 0b1111\n\nexport type Type =\n | 'Unknown'\n | 'FIFO'\n | 'CharacterDevice'\n | 'Directory'\n | 'BlockDevice'\n | 'File'\n | 'SymbolicLink'\n | 'Socket'\n\n// mask to unset low 4 bits\nconst IFMT_UNKNOWN = ~IFMT\n\n// set after successfully calling readdir() and getting entries.\nconst READDIR_CALLED = 0b0000_0001_0000\n// set after a successful lstat()\nconst LSTAT_CALLED = 0b0000_0010_0000\n// set if an entry (or one of its parents) is definitely not a dir\nconst ENOTDIR = 0b0000_0100_0000\n// set if an entry (or one of its parents) does not exist\n// (can also be set on lstat errors like EACCES or ENAMETOOLONG)\nconst ENOENT = 0b0000_1000_0000\n// cannot have child entries -- also verify &IFMT is either IFDIR or IFLNK\n// set if we fail to readlink\nconst ENOREADLINK = 0b0001_0000_0000\n// set if we know realpath() will fail\nconst ENOREALPATH = 0b0010_0000_0000\n\nconst ENOCHILD = ENOTDIR | ENOENT | ENOREALPATH\nconst TYPEMASK = 0b0011_1111_1111\n\nconst entToType = (s: Dirent | Stats) =>\n s.isFile() ? IFREG\n : s.isDirectory() ? IFDIR\n : s.isSymbolicLink() ? IFLNK\n : s.isCharacterDevice() ? IFCHR\n : s.isBlockDevice() ? IFBLK\n : s.isSocket() ? IFSOCK\n : s.isFIFO() ? IFIFO\n : UNKNOWN\n\n// normalize unicode path names\nconst normalizeCache = new LRUCache<string, string>({ max: 2 ** 12 })\nconst normalize = (s: string) => {\n const c = normalizeCache.get(s)\n if (c) return c\n const n = s.normalize('NFKD')\n normalizeCache.set(s, n)\n return n\n}\n\nconst normalizeNocaseCache = new LRUCache<string, string>({ max: 2 ** 12 })\nconst normalizeNocase = (s: string) => {\n const c = normalizeNocaseCache.get(s)\n if (c) return c\n const n = normalize(s.toLowerCase())\n normalizeNocaseCache.set(s, n)\n return n\n}\n\n/**\n * Options that may be provided to the Path constructor\n */\nexport interface PathOpts {\n fullpath?: string\n relative?: string\n relativePosix?: string\n parent?: PathBase\n /**\n * See {@link FSOption}\n */\n fs?: FSOption\n}\n\n/**\n * An LRUCache for storing resolved path strings or Path objects.\n * @internal\n */\nexport class ResolveCache extends LRUCache<string, string> {\n constructor() {\n super({ max: 256 })\n }\n}\n\n// In order to prevent blowing out the js heap by allocating hundreds of\n// thousands of Path entries when walking extremely large trees, the \"children\"\n// in this tree are represented by storing an array of Path entries in an\n// LRUCache, indexed by the parent. At any time, Path.children() may return an\n// empty array, indicating that it doesn't know about any of its children, and\n// thus has to rebuild that cache. This is fine, it just means that we don't\n// benefit as much from having the cached entries, but huge directory walks\n// don't blow out the stack, and smaller ones are still as fast as possible.\n//\n//It does impose some complexity when building up the readdir data, because we\n//need to pass a reference to the children array that we started with.\n\n/**\n * an LRUCache for storing child entries.\n * @internal\n */\nexport class ChildrenCache extends LRUCache<PathBase, Children> {\n constructor(maxSize: number = 16 * 1024) {\n super({\n maxSize,\n // parent + children\n sizeCalculation: a => a.length + 1,\n })\n }\n}\n\n/**\n * Array of Path objects, plus a marker indicating the first provisional entry\n *\n * @internal\n */\nexport type Children = PathBase[] & { provisional: number }\n\nconst setAsCwd = Symbol('PathScurry setAsCwd')\n\n/**\n * Path objects are sort of like a super-powered\n * {@link https://nodejs.org/docs/latest/api/fs.html#class-fsdirent fs.Dirent}\n *\n * Each one represents a single filesystem entry on disk, which may or may not\n * exist. It includes methods for reading various types of information via\n * lstat, readlink, and readdir, and caches all information to the greatest\n * degree possible.\n *\n * Note that fs operations that would normally throw will instead return an\n * \"empty\" value. This is in order to prevent excessive overhead from error\n * stack traces.\n */\nexport abstract class PathBase implements Dirent {\n /**\n * the basename of this path\n *\n * **Important**: *always* test the path name against any test string\n * usingthe {@link isNamed} method, and not by directly comparing this\n * string. Otherwise, unicode path strings that the system sees as identical\n * will not be properly treated as the same path, leading to incorrect\n * behavior and possible security issues.\n */\n name: string\n /**\n * the Path entry corresponding to the path root.\n *\n * @internal\n */\n root: PathBase\n /**\n * All roots found within the current PathScurry family\n *\n * @internal\n */\n roots: { [k: string]: PathBase }\n /**\n * a reference to the parent path, or undefined in the case of root entries\n *\n * @internal\n */\n parent?: PathBase\n /**\n * boolean indicating whether paths are compared case-insensitively\n * @internal\n */\n nocase: boolean\n\n /**\n * boolean indicating that this path is the current working directory\n * of the PathScurry collection that contains it.\n */\n isCWD: boolean = false\n\n /**\n * the string or regexp used to split paths. On posix, it is `'/'`, and on\n * windows it is a RegExp matching either `'/'` or `'\\\\'`\n */\n abstract splitSep: string | RegExp\n /**\n * The path separator string to use when joining paths\n */\n abstract sep: string\n\n // potential default fs override\n #fs: FSValue\n\n // Stats fields\n #dev?: number\n get dev() {\n return this.#dev\n }\n #mode?: number\n get mode() {\n return this.#mode\n }\n #nlink?: number\n get nlink() {\n return this.#nlink\n }\n #uid?: number\n get uid() {\n return this.#uid\n }\n #gid?: number\n get gid() {\n return this.#gid\n }\n #rdev?: number\n get rdev() {\n return this.#rdev\n }\n #blksize?: number\n get blksize() {\n return this.#blksize\n }\n #ino?: number\n get ino() {\n return this.#ino\n }\n #size?: number\n get size() {\n return this.#size\n }\n #blocks?: number\n get blocks() {\n return this.#blocks\n }\n #atimeMs?: number\n get atimeMs() {\n return this.#atimeMs\n }\n #mtimeMs?: number\n get mtimeMs() {\n return this.#mtimeMs\n }\n #ctimeMs?: number\n get ctimeMs() {\n return this.#ctimeMs\n }\n #birthtimeMs?: number\n get birthtimeMs() {\n return this.#birthtimeMs\n }\n #atime?: Date\n get atime() {\n return this.#atime\n }\n #mtime?: Date\n get mtime() {\n return this.#mtime\n }\n #ctime?: Date\n get ctime() {\n return this.#ctime\n }\n #birthtime?: Date\n get birthtime() {\n return this.#birthtime\n }\n\n #matchName: string\n #depth?: number\n #fullpath?: string\n #fullpathPosix?: string\n #relative?: string\n #relativePosix?: string\n #type: number\n #children: ChildrenCache\n #linkTarget?: PathBase\n #realpath?: PathBase\n\n /**\n * This property is for compatibility with the Dirent class as of\n * Node v20, where Dirent['parentPath'] refers to the path of the\n * directory that was passed to readdir. For root entries, it's the path\n * to the entry itself.\n */\n get parentPath(): string {\n return (this.parent || this).fullpath()\n }\n\n /* c8 ignore start */\n /**\n * Deprecated alias for Dirent['parentPath'] Somewhat counterintuitively,\n * this property refers to the *parent* path, not the path object itself.\n *\n * @deprecated\n */\n get path(): string {\n return this.parentPath\n }\n /* c8 ignore stop */\n\n /**\n * Do not create new Path objects directly. They should always be accessed\n * via the PathScurry class or other methods on the Path class.\n *\n * @internal\n */\n constructor(\n name: string,\n type: number = UNKNOWN,\n root: PathBase | undefined,\n roots: { [k: string]: PathBase },\n nocase: boolean,\n children: ChildrenCache,\n opts: PathOpts,\n ) {\n this.name = name\n this.#matchName = nocase ? normalizeNocase(name) : normalize(name)\n this.#type = type & TYPEMASK\n this.nocase = nocase\n this.roots = roots\n this.root = root || this\n this.#children = children\n this.#fullpath = opts.fullpath\n this.#relative = opts.relative\n this.#relativePosix = opts.relativePosix\n this.parent = opts.parent\n if (this.parent) {\n this.#fs = this.parent.#fs\n } else {\n this.#fs = fsFromOption(opts.fs)\n }\n }\n\n /**\n * Returns the depth of the Path object from its root.\n *\n * For example, a path at `/foo/bar` would have a depth of 2.\n */\n depth(): number {\n if (this.#depth !== undefined) return this.#depth\n if (!this.parent) return (this.#depth = 0)\n return (this.#depth = this.parent.depth() + 1)\n }\n\n /**\n * @internal\n */\n abstract getRootString(path: string): string\n /**\n * @internal\n */\n abstract getRoot(rootPath: string): PathBase\n /**\n * @internal\n */\n abstract newChild(name: string, type?: number, opts?: PathOpts): PathBase\n\n /**\n * @internal\n */\n childrenCache() {\n return this.#children\n }\n\n /**\n * Get the Path object referenced by the string path, resolved from this Path\n */\n resolve(path?: string): PathBase {\n if (!path) {\n return this\n }\n const rootPath = this.getRootString(path)\n const dir = path.substring(rootPath.length)\n const dirParts = dir.split(this.splitSep)\n const result: PathBase =\n rootPath ?\n this.getRoot(rootPath).#resolveParts(dirParts)\n : this.#resolveParts(dirParts)\n return result\n }\n\n #resolveParts(dirParts: string[]) {\n let p: PathBase = this\n for (const part of dirParts) {\n p = p.child(part)\n }\n return p\n }\n\n /**\n * Returns the cached children Path objects, if still available. If they\n * have fallen out of the cache, then returns an empty array, and resets the\n * READDIR_CALLED bit, so that future calls to readdir() will require an fs\n * lookup.\n *\n * @internal\n */\n children(): Children {\n const cached = this.#children.get(this)\n if (cached) {\n return cached\n }\n const children: Children = Object.assign([], { provisional: 0 })\n this.#children.set(this, children)\n this.#type &= ~READDIR_CALLED\n return children\n }\n\n /**\n * Resolves a path portion and returns or creates the child Path.\n *\n * Returns `this` if pathPart is `''` or `'.'`, or `parent` if pathPart is\n * `'..'`.\n *\n * This should not be called directly. If `pathPart` contains any path\n * separators, it will lead to unsafe undefined behavior.\n *\n * Use `Path.resolve()` instead.\n *\n * @internal\n */\n child(pathPart: string, opts?: PathOpts): PathBase {\n if (pathPart === '' || pathPart === '.') {\n return this\n }\n if (pathPart === '..') {\n return this.parent || this\n }\n\n // find the child\n const children = this.children()\n const name =\n this.nocase ? normalizeNocase(pathPart) : normalize(pathPart)\n for (const p of children) {\n if (p.#matchName === name) {\n return p\n }\n }\n\n // didn't find it, create provisional child, since it might not\n // actually exist. If we know the parent isn't a dir, then\n // in fact it CAN'T exist.\n const s = this.parent ? this.sep : ''\n const fullpath =\n this.#fullpath ? this.#fullpath + s + pathPart : undefined\n const pchild = this.newChild(pathPart, UNKNOWN, {\n ...opts,\n parent: this,\n fullpath,\n })\n\n if (!this.canReaddir()) {\n pchild.#type |= ENOENT\n }\n\n // don't have to update provisional, because if we have real children,\n // then provisional is set to children.length, otherwise a lower number\n children.push(pchild)\n return pchild\n }\n\n /**\n * The relative path from the cwd. If it does not share an ancestor with\n * the cwd, then this ends up being equivalent to the fullpath()\n */\n relative(): string {\n if (this.isCWD) return ''\n if (this.#relative !== undefined) {\n return this.#relative\n }\n const name = this.name\n const p = this.parent\n if (!p) {\n return (this.#relative = this.name)\n }\n const pv = p.relative()\n return pv + (!pv || !p.parent ? '' : this.sep) + name\n }\n\n /**\n * The relative path from the cwd, using / as the path separator.\n * If it does not share an ancestor with\n * the cwd, then this ends up being equivalent to the fullpathPosix()\n * On posix systems, this is identical to relative().\n */\n relativePosix(): string {\n if (this.sep === '/') return this.relative()\n if (this.isCWD) return ''\n if (this.#relativePosix !== undefined) return this.#relativePosix\n const name = this.name\n const p = this.parent\n if (!p) {\n return (this.#relativePosix = this.fullpathPosix())\n }\n const pv = p.relativePosix()\n return pv + (!pv || !p.parent ? '' : '/') + name\n }\n\n /**\n * The fully resolved path string for this Path entry\n */\n fullpath(): string {\n if (this.#fullpath !== undefined) {\n return this.#fullpath\n }\n const name = this.name\n const p = this.parent\n if (!p) {\n return (this.#fullpath = this.name)\n }\n const pv = p.fullpath()\n const fp = pv + (!p.parent ? '' : this.sep) + name\n return (this.#fullpath = fp)\n }\n\n /**\n * On platforms other than windows, this is identical to fullpath.\n *\n * On windows, this is overridden to return the forward-slash form of the\n * full UNC path.\n */\n fullpathPosix(): string {\n if (this.#fullpathPosix !== undefined) return this.#fullpathPosix\n if (this.sep === '/') return (this.#fullpathPosix = this.fullpath())\n if (!this.parent) {\n const p = this.fullpath().replace(/\\\\/g, '/')\n if (/^[a-z]:\\//i.test(p)) {\n return (this.#fullpathPosix = `//?/${p}`)\n } else {\n return (this.#fullpathPosix = p)\n }\n }\n const p = this.parent\n const pfpp = p.fullpathPosix()\n const fpp = pfpp + (!pfpp || !p.parent ? '' : '/') + this.name\n return (this.#fullpathPosix = fpp)\n }\n\n /**\n * Is the Path of an unknown type?\n *\n * Note that we might know *something* about it if there has been a previous\n * filesystem operation, for example that it does not exist, or is not a\n * link, or whether it has child entries.\n */\n isUnknown(): boolean {\n return (this.#type & IFMT) === UNKNOWN\n }\n\n isType(type: Type): boolean {\n return this[`is${type}`]()\n }\n\n getType(): Type {\n return (\n this.isUnknown() ? 'Unknown'\n : this.isDirectory() ? 'Directory'\n : this.isFile() ? 'File'\n : this.isSymbolicLink() ? 'SymbolicLink'\n : this.isFIFO() ? 'FIFO'\n : this.isCharacterDevice() ? 'CharacterDevice'\n : this.isBlockDevice() ? 'BlockDevice'\n : /* c8 ignore start */ this.isSocket() ? 'Socket'\n : 'Unknown'\n )\n /* c8 ignore stop */\n }\n\n /**\n * Is the Path a regular file?\n */\n isFile(): boolean {\n return (this.#type & IFMT) === IFREG\n }\n\n /**\n * Is the Path a directory?\n */\n isDirectory(): boolean {\n return (this.#type & IFMT) === IFDIR\n }\n\n /**\n * Is the path a character device?\n */\n isCharacterDevice(): boolean {\n return (this.#type & IFMT) === IFCHR\n }\n\n /**\n * Is the path a block device?\n */\n isBlockDevice(): boolean {\n return (this.#type & IFMT) === IFBLK\n }\n\n /**\n * Is the path a FIFO pipe?\n */\n isFIFO(): boolean {\n return (this.#type & IFMT) === IFIFO\n }\n\n /**\n * Is the path a socket?\n */\n isSocket(): boolean {\n return (this.#type & IFMT) === IFSOCK\n }\n\n /**\n * Is the path a symbolic link?\n */\n isSymbolicLink(): boolean {\n return (this.#type & IFLNK) === IFLNK\n }\n\n /**\n * Return the entry if it has been subject of a successful lstat, or\n * undefined otherwise.\n *\n * Does not read the filesystem, so an undefined result *could* simply\n * mean that we haven't called lstat on it.\n */\n lstatCached(): PathBase | undefined {\n return this.#type & LSTAT_CALLED ? this : undefined\n }\n\n /**\n * Return the cached link target if the entry has been the subject of a\n * successful readlink, or undefined otherwise.\n *\n * Does not read the filesystem, so an undefined result *could* just mean we\n * don't have any cached data. Only use it if you are very sure that a\n * readlink() has been called at some point.\n */\n readlinkCached(): PathBase | undefined {\n return this.#linkTarget\n }\n\n /**\n * Returns the cached realpath target if the entry has been the subject\n * of a successful realpath, or undefined otherwise.\n *\n * Does not read the filesystem, so an undefined result *could* just mean we\n * don't have any cached data. Only use it if you are very sure that a\n * realpath() has been called at some point.\n */\n realpathCached(): PathBase | undefined {\n return this.#realpath\n }\n\n /**\n * Returns the cached child Path entries array if the entry has been the\n * subject of a successful readdir(), or [] otherwise.\n *\n * Does not read the filesystem, so an empty array *could* just mean we\n * don't have any cached data. Only use it if you are very sure that a\n * readdir() has been called recently enough to still be valid.\n */\n readdirCached(): PathBase[] {\n const children = this.children()\n return children.slice(0, children.provisional)\n }\n\n /**\n * Return true if it's worth trying to readlink. Ie, we don't (yet) have\n * any indication that readlink will definitely fail.\n *\n * Returns false if the path is known to not be a symlink, if a previous\n * readlink failed, or if the entry does not exist.\n */\n canReadlink(): boolean {\n if (this.#linkTarget) return true\n if (!this.parent) return false\n // cases where it cannot possibly succeed\n const ifmt = this.#type & IFMT\n return !(\n (ifmt !== UNKNOWN && ifmt !== IFLNK) ||\n this.#type & ENOREADLINK ||\n this.#type & ENOENT\n )\n }\n\n /**\n * Return true if readdir has previously been successfully called on this\n * path, indicating that cachedReaddir() is likely valid.\n */\n calledReaddir(): boolean {\n return !!(this.#type & READDIR_CALLED)\n }\n\n /**\n * Returns true if the path is known to not exist. That is, a previous lstat\n * or readdir failed to verify its existence when that would have been\n * expected, or a parent entry was marked either enoent or enotdir.\n */\n isENOENT(): boolean {\n return !!(this.#type & ENOENT)\n }\n\n /**\n * Return true if the path is a match for the given path name. This handles\n * case sensitivity and unicode normalization.\n *\n * Note: even on case-sensitive systems, it is **not** safe to test the\n * equality of the `.name` property to determine whether a given pathname\n * matches, due to unicode normalization mismatches.\n *\n * Always use this method instead of testing the `path.name` property\n * directly.\n */\n isNamed(n: string): boolean {\n return !this.nocase ?\n this.#matchName === normalize(n)\n : this.#matchName === normalizeNocase(n)\n }\n\n /**\n * Return the Path object corresponding to the target of a symbolic link.\n *\n * If the Path is not a symbolic link, or if the readlink call fails for any\n * reason, `undefined` is returned.\n *\n * Result is cached, and thus may be outdated if the filesystem is mutated.\n */\n async readlink(): Promise<PathBase | undefined> {\n const target = this.#linkTarget\n if (target) {\n return target\n }\n if (!this.canReadlink()) {\n return undefined\n }\n /* c8 ignore start */\n // already covered by the canReadlink test, here for ts grumples\n if (!this.parent) {\n return undefined\n }\n /* c8 ignore stop */\n try {\n const read = await this.#fs.promises.readlink(this.fullpath())\n const linkTarget = (await this.parent.realpath())?.resolve(read)\n if (linkTarget) {\n return (this.#linkTarget = linkTarget)\n }\n } catch (er) {\n this.#readlinkFail((er as NodeJS.ErrnoException).code)\n return undefined\n }\n }\n\n /**\n * Synchronous {@link PathBase.readlink}\n */\n readlinkSync(): PathBase | undefined {\n const target = this.#linkTarget\n if (target) {\n return target\n }\n if (!this.canReadlink()) {\n return undefined\n }\n /* c8 ignore start */\n // already covered by the canReadlink test, here for ts grumples\n if (!this.parent) {\n return undefined\n }\n /* c8 ignore stop */\n try {\n const read = this.#fs.readlinkSync(this.fullpath())\n const linkTarget = this.parent.realpathSync()?.resolve(read)\n if (linkTarget) {\n return (this.#linkTarget = linkTarget)\n }\n } catch (er) {\n this.#readlinkFail((er as NodeJS.ErrnoException).code)\n return undefined\n }\n }\n\n #readdirSuccess(children: Children) {\n // succeeded, mark readdir called bit\n this.#type |= READDIR_CALLED\n // mark all remaining provisional children as ENOENT\n for (let p = children.provisional; p < children.length; p++) {\n const c = children[p]\n if (c) c.#markENOENT()\n }\n }\n\n #markENOENT() {\n // mark as UNKNOWN and ENOENT\n if (this.#type & ENOENT) return\n this.#type = (this.#type | ENOENT) & IFMT_UNKNOWN\n this.#markChildrenENOENT()\n }\n\n #markChildrenENOENT() {\n // all children are provisional and do not exist\n const children = this.children()\n children.provisional = 0\n for (const p of children) {\n p.#markENOENT()\n }\n }\n\n #markENOREALPATH() {\n this.#type |= ENOREALPATH\n this.#markENOTDIR()\n }\n\n // save the information when we know the entry is not a dir\n #markENOTDIR() {\n // entry is not a directory, so any children can't exist.\n // this *should* be impossible, since any children created\n // after it's been marked ENOTDIR should be marked ENOENT,\n // so it won't even get to this point.\n /* c8 ignore start */\n if (this.#type & ENOTDIR) return\n /* c8 ignore stop */\n let t = this.#type\n // this could happen if we stat a dir, then delete it,\n // then try to read it or one of its children.\n if ((t & IFMT) === IFDIR) t &= IFMT_UNKNOWN\n this.#type = t | ENOTDIR\n this.#markChildrenENOENT()\n }\n\n #readdirFail(code: string = '') {\n // markENOTDIR and markENOENT also set provisional=0\n if (code === 'ENOTDIR' || code === 'EPERM') {\n this.#markENOTDIR()\n } else if (code === 'ENOENT') {\n this.#markENOENT()\n } else {\n this.children().provisional = 0\n }\n }\n\n #lstatFail(code: string = '') {\n // Windows just raises ENOENT in this case, disable for win CI\n /* c8 ignore start */\n if (code === 'ENOTDIR') {\n // already know it has a parent by this point\n const p = this.parent as PathBase\n p.#markENOTDIR()\n } else if (code === 'ENOENT') {\n /* c8 ignore stop */\n this.#markENOENT()\n }\n }\n\n #readlinkFail(code: string = '') {\n let ter = this.#type\n ter |= ENOREADLINK\n if (code === 'ENOENT') ter |= ENOENT\n // windows gets a weird error when you try to readlink a file\n if (code === 'EINVAL' || code === 'UNKNOWN') {\n // exists, but not a symlink, we don't know WHAT it is, so remove\n // all IFMT bits.\n ter &= IFMT_UNKNOWN\n }\n this.#type = ter\n // windows just gets ENOENT in this case. We do cover the case,\n // just disabled because it's impossible on Windows CI\n /* c8 ignore start */\n if (code === 'ENOTDIR' && this.parent) {\n this.parent.#markENOTDIR()\n }\n /* c8 ignore stop */\n }\n\n #readdirAddChild(e: Dirent, c: Children) {\n return (\n this.#readdirMaybePromoteChild(e, c) ||\n this.#readdirAddNewChild(e, c)\n )\n }\n\n #readdirAddNewChild(e: Dirent, c: Children): PathBase {\n // alloc new entry at head, so it's never provisional\n const type = entToType(e)\n const child = this.newChild(e.name, type, { parent: this })\n const ifmt = child.#type & IFMT\n if (ifmt !== IFDIR && ifmt !== IFLNK && ifmt !== UNKNOWN) {\n child.#type |= ENOTDIR\n }\n c.unshift(child)\n c.provisional++\n return child\n }\n\n #readdirMaybePromoteChild(e: Dirent, c: Children): PathBase | undefined {\n for (let p = c.provisional; p < c.length; p++) {\n const pchild = c[p]\n const name =\n this.nocase ? normalizeNocase(e.name) : normalize(e.name)\n if (name !== pchild!.#matchName) {\n continue\n }\n\n return this.#readdirPromoteChild(e, pchild!, p, c)\n }\n }\n\n #readdirPromoteChild(\n e: Dirent,\n p: PathBase,\n index: number,\n c: Children,\n ): PathBase {\n const v = p.name\n // retain any other flags, but set ifmt from dirent\n p.#type = (p.#type & IFMT_UNKNOWN) | entToType(e)\n // case sensitivity fixing when we learn the true name.\n if (v !== e.name) p.name = e.name\n\n // just advance provisional index (potentially off the list),\n // otherwise we have to splice/pop it out and re-insert at head\n if (index !== c.provisional) {\n if (index === c.length - 1) c.pop()\n else c.splice(index, 1)\n c.unshift(p)\n }\n c.provisional++\n return p\n }\n\n /**\n * Call lstat() on this Path, and update all known information that can be\n * determined.\n *\n * Note that unlike `fs.lstat()`, the returned value does not contain some\n * information, such as `mode`, `dev`, `nlink`, and `ino`. If that\n * information is required, you will need to call `fs.lstat` yourself.\n *\n * If the Path refers to a nonexistent file, or if the lstat call fails for\n * any reason, `undefined` is returned. Otherwise the updated Path object is\n * returned.\n *\n * Results are cached, and thus may be out of date if the filesystem is\n * mutated.\n */\n async lstat(): Promise<PathBase | undefined> {\n if ((this.#type & ENOENT) === 0) {\n try {\n this.#applyStat(await this.#fs.promises.lstat(this.fullpath()))\n return this\n } catch (er) {\n this.#lstatFail((er as NodeJS.ErrnoException).code)\n }\n }\n }\n\n /**\n * synchronous {@link PathBase.lstat}\n */\n lstatSync(): PathBase | undefined {\n if ((this.#type & ENOENT) === 0) {\n try {\n this.#applyStat(this.#fs.lstatSync(this.fullpath()))\n return this\n } catch (er) {\n this.#lstatFail((er as NodeJS.ErrnoException).code)\n }\n }\n }\n\n #applyStat(st: Stats) {\n const {\n atime,\n atimeMs,\n birthtime,\n birthtimeMs,\n blksize,\n blocks,\n ctime,\n ctimeMs,\n dev,\n gid,\n ino,\n mode,\n mtime,\n mtimeMs,\n nlink,\n rdev,\n size,\n uid,\n } = st\n this.#atime = atime\n this.#atimeMs = atimeMs\n this.#birthtime = birthtime\n this.#birthtimeMs = birthtimeMs\n this.#blksize = blksize\n this.#blocks = blocks\n this.#ctime = ctime\n this.#ctimeMs = ctimeMs\n this.#dev = dev\n this.#gid = gid\n this.#ino = ino\n this.#mode = mode\n this.#mtime = mtime\n this.#mtimeMs = mtimeMs\n this.#nlink = nlink\n this.#rdev = rdev\n this.#size = size\n this.#uid = uid\n const ifmt = entToType(st)\n // retain any other flags, but set the ifmt\n this.#type = (this.#type & IFMT_UNKNOWN) | ifmt | LSTAT_CALLED\n if (ifmt !== UNKNOWN && ifmt !== IFDIR && ifmt !== IFLNK) {\n this.#type |= ENOTDIR\n }\n }\n\n #onReaddirCB: ((\n er: NodeJS.ErrnoException | null,\n entries: Path[],\n ) => any)[] = []\n #readdirCBInFlight: boolean = false\n #callOnReaddirCB(children: Path[]) {\n this.#readdirCBInFlight = false\n const cbs = this.#onReaddirCB.slice()\n this.#onReaddirCB.length = 0\n cbs.forEach(cb => cb(null, children))\n }\n\n /**\n * Standard node-style callback interface to get list of directory entries.\n *\n * If the Path cannot or does not contain any children, then an empty array\n * is returned.\n *\n * Results are cached, and thus may be out of date if the filesystem is\n * mutated.\n *\n * @param cb The callback called with (er, entries). Note that the `er`\n * param is somewhat extraneous, as all readdir() errors are handled and\n * simply result in an empty set of entries being returned.\n * @param allowZalgo Boolean indicating that immediately known results should\n * *not* be deferred with `queueMicrotask`. Defaults to `false`. Release\n * zalgo at your peril, the dark pony lord is devious and unforgiving.\n */\n readdirCB(\n cb: (er: NodeJS.ErrnoException | null, entries: PathBase[]) => any,\n allowZalgo: boolean = false,\n ): void {\n if (!this.canReaddir()) {\n if (allowZalgo) cb(null, [])\n else queueMicrotask(() => cb(null, []))\n return\n }\n\n const children = this.children()\n if (this.calledReaddir()) {\n const c = children.slice(0, children.provisional)\n if (allowZalgo) cb(null, c)\n else queueMicrotask(() => cb(null, c))\n return\n }\n\n // don't have to worry about zalgo at this point.\n this.#onReaddirCB.push(cb)\n if (this.#readdirCBInFlight) {\n return\n }\n this.#readdirCBInFlight = true\n\n // else read the directory, fill up children\n // de-provisionalize any provisional children.\n const fullpath = this.fullpath()\n this.#fs.readdir(fullpath, { withFileTypes: true }, (er, entries) => {\n if (er) {\n this.#readdirFail((er as NodeJS.ErrnoException).code)\n children.provisional = 0\n } else {\n // if we didn't get an error, we always get entries.\n //@ts-ignore\n for (const e of entries) {\n this.#readdirAddChild(e, children)\n }\n this.#readdirSuccess(children)\n }\n this.#callOnReaddirCB(children.slice(0, children.provisional))\n return\n })\n }\n\n #asyncReaddirInFlight?: Promise<void>\n\n /**\n * Return an array of known child entries.\n *\n * If the Path cannot or does not contain any children, then an empty array\n * is returned.\n *\n * Results are cached, and thus may be out of date if the filesystem is\n * mutated.\n */\n async readdir(): Promise<PathBase[]> {\n if (!this.canReaddir()) {\n return []\n }\n\n const children = this.children()\n if (this.calledReaddir()) {\n return children.slice(0, children.provisional)\n }\n\n // else read the directory, fill up children\n // de-provisionalize any provisional children.\n const fullpath = this.fullpath()\n if (this.#asyncReaddirInFlight) {\n await this.#asyncReaddirInFlight\n } else {\n /* c8 ignore start */\n let resolve: () => void = () => {}\n /* c8 ignore stop */\n this.#asyncReaddirInFlight = new Promise<void>(\n res => (resolve = res),\n )\n try {\n for (const e of await this.#fs.promises.readdir(fullpath, {\n withFileTypes: true,\n })) {\n this.#readdirAddChild(e, children)\n }\n this.#readdirSuccess(children)\n } catch (er) {\n this.#readdirFail((er as NodeJS.ErrnoException).code)\n children.provisional = 0\n }\n this.#asyncReaddirInFlight = undefined\n resolve()\n }\n return children.slice(0, children.provisional)\n }\n\n /**\n * synchronous {@link PathBase.readdir}\n */\n readdirSync(): PathBase[] {\n if (!this.canReaddir()) {\n return []\n }\n\n const children = this.children()\n if (this.calledReaddir()) {\n return children.slice(0, children.provisional)\n }\n\n // else read the directory, fill up children\n // de-provisionalize any provisional children.\n const fullpath = this.fullpath()\n try {\n for (const e of this.#fs.readdirSync(fullpath, {\n withFileTypes: true,\n })) {\n this.#readdirAddChild(e, children)\n }\n this.#readdirSuccess(children)\n } catch (er) {\n this.#readdirFail((er as NodeJS.ErrnoException).code)\n children.provisional = 0\n }\n return children.slice(0, children.provisional)\n }\n\n canReaddir() {\n if (this.#type & ENOCHILD) return false\n const ifmt = IFMT & this.#type\n // we always set ENOTDIR when setting IFMT, so should be impossible\n /* c8 ignore start */\n if (!(ifmt === UNKNOWN || ifmt === IFDIR || ifmt === IFLNK)) {\n return false\n }\n /* c8 ignore stop */\n return true\n }\n\n shouldWalk(\n dirs: Set<PathBase | undefined>,\n walkFilter?: (e: PathBase) => boolean,\n ): boolean {\n return (\n (this.#type & IFDIR) === IFDIR &&\n !(this.#type & ENOCHILD) &&\n !dirs.has(this) &&\n (!walkFilter || walkFilter(this))\n )\n }\n\n /**\n * Return the Path object corresponding to path as resolved\n * by realpath(3).\n *\n * If the realpath call fails for any reason, `undefined` is returned.\n *\n * Result is cached, and thus may be outdated if the filesystem is mutated.\n * On success, returns a Path object.\n */\n async realpath(): Promise<PathBase | undefined> {\n if (this.#realpath) return this.#realpath\n if ((ENOREALPATH | ENOREADLINK | ENOENT) & this.#type) return undefined\n try {\n const rp = await this.#fs.promises.realpath(this.fullpath())\n return (this.#realpath = this.resolve(rp))\n } catch (_) {\n this.#markENOREALPATH()\n }\n }\n\n /**\n * Synchronous {@link realpath}\n */\n realpathSync(): PathBase | undefined {\n if (this.#realpath) return this.#realpath\n if ((ENOREALPATH | ENOREADLINK | ENOENT) & this.#type) return undefined\n try {\n const rp = this.#fs.realpathSync(this.fullpath())\n return (this.#realpath = this.resolve(rp))\n } catch (_) {\n this.#markENOREALPATH()\n }\n }\n\n /**\n * Internal method to mark this Path object as the scurry cwd,\n * called by {@link PathScurry#chdir}\n *\n * @internal\n */\n [setAsCwd](oldCwd: PathBase): void {\n if (oldCwd === this) return\n oldCwd.isCWD = false\n this.isCWD = true\n\n const changed = new Set<PathBase>([])\n let rp = []\n let p: PathBase = this\n while (p && p.parent) {\n changed.add(p)\n p.#relative = rp.join(this.sep)\n p.#relativePosix = rp.join('/')\n p = p.parent\n rp.push('..')\n }\n // now un-memoize parents of old cwd\n p = oldCwd\n while (p && p.parent && !changed.has(p)) {\n p.#relative = undefined\n p.#relativePosix = undefined\n p = p.parent\n }\n }\n}\n\n/**\n * Path class used on win32 systems\n *\n * Uses `'\\\\'` as the path separator for returned paths, either `'\\\\'` or `'/'`\n * as the path separator for parsing paths.\n */\nexport class PathWin32 extends PathBase {\n /**\n * Separator for generating path strings.\n */\n sep: '\\\\' = '\\\\'\n /**\n * Separator for parsing path strings.\n */\n splitSep: RegExp = eitherSep\n\n /**\n * Do not create new Path objects directly. They should always be accessed\n * via the PathScurry class or other methods on the Path class.\n *\n * @internal\n */\n constructor(\n name: string,\n type: number = UNKNOWN,\n root: PathBase | undefined,\n roots: { [k: string]: PathBase },\n nocase: boolean,\n children: ChildrenCache,\n opts: PathOpts,\n ) {\n super(name, type, root, roots, nocase, children, opts)\n }\n\n /**\n * @internal\n */\n newChild(name: string, type: number = UNKNOWN, opts: PathOpts = {}) {\n return new PathWin32(\n name,\n type,\n this.root,\n this.roots,\n this.nocase,\n this.childrenCache(),\n opts,\n )\n }\n\n /**\n * @internal\n */\n getRootString(path: string): string {\n return win32.parse(path).root\n }\n\n /**\n * @internal\n */\n getRoot(rootPath: string): PathBase {\n rootPath = uncToDrive(rootPath.toUpperCase())\n if (rootPath === this.root.name) {\n return this.root\n }\n // ok, not that one, check if it matches another we know about\n for (const [compare, root] of Object.entries(this.roots)) {\n if (this.sameRoot(rootPath, compare)) {\n return (this.roots[rootPath] = root)\n }\n }\n // otherwise, have to create a new one.\n return (this.roots[rootPath] = new PathScurryWin32(\n rootPath,\n this,\n ).root)\n }\n\n /**\n * @internal\n */\n sameRoot(rootPath: string, compare: string = this.root.name): boolean {\n // windows can (rarely) have case-sensitive filesystem, but\n // UNC and drive letters are always case-insensitive, and canonically\n // represented uppercase.\n rootPath = rootPath\n .toUpperCase()\n .replace(/\\//g, '\\\\')\n .replace(uncDriveRegexp, '$1\\\\')\n return rootPath === compare\n }\n}\n\n/**\n * Path class used on all posix systems.\n *\n * Uses `'/'` as the path separator.\n */\nexport class PathPosix extends PathBase {\n /**\n * separator for parsing path strings\n */\n splitSep: '/' = '/'\n /**\n * separator for generating path strings\n */\n sep: '/' = '/'\n\n /**\n * Do not create new Path objects directly. They should always be accessed\n * via the PathScurry class or other methods on the Path class.\n *\n * @internal\n */\n constructor(\n name: string,\n type: number = UNKNOWN,\n root: PathBase | undefined,\n roots: { [k: string]: PathBase },\n nocase: boolean,\n children: ChildrenCache,\n opts: PathOpts,\n ) {\n super(name, type, root, roots, nocase, children, opts)\n }\n\n /**\n * @internal\n */\n getRootString(path: string): string {\n return path.startsWith('/') ? '/' : ''\n }\n\n /**\n * @internal\n */\n getRoot(_rootPath: string): PathBase {\n return this.root\n }\n\n /**\n * @internal\n */\n newChild(name: string, type: number = UNKNOWN, opts: PathOpts = {}) {\n return new PathPosix(\n name,\n type,\n this.root,\n this.roots,\n this.nocase,\n this.childrenCache(),\n opts,\n )\n }\n}\n\n/**\n * Options that may be provided to the PathScurry constructor\n */\nexport interface PathScurryOpts {\n /**\n * perform case-insensitive path matching. Default based on platform\n * subclass.\n */\n nocase?: boolean\n /**\n * Number of Path entries to keep in the cache of Path child references.\n *\n * Setting this higher than 65536 will dramatically increase the data\n * consumption and construction time overhead of each PathScurry.\n *\n * Setting this value to 256 or lower will significantly reduce the data\n * consumption and construction time overhead, but may also reduce resolve()\n * and readdir() performance on large filesystems.\n *\n * Default `16384`.\n */\n childrenCacheSize?: number\n /**\n * An object that overrides the built-in functions from the fs and\n * fs/promises modules.\n *\n * See {@link FSOption}\n */\n fs?: FSOption\n}\n\n/**\n * The base class for all PathScurry classes, providing the interface for path\n * resolution and filesystem operations.\n *\n * Typically, you should *not* instantiate this class directly, but rather one\n * of the platform-specific classes, or the exported {@link PathScurry} which\n * defaults to the current platform.\n */\nexport abstract class PathScurryBase {\n /**\n * The root Path entry for the current working directory of this Scurry\n */\n root: PathBase\n /**\n * The string path for the root of this Scurry's current working directory\n */\n rootPath: string\n /**\n * A collection of all roots encountered, referenced by rootPath\n */\n roots: { [k: string]: PathBase }\n /**\n * The Path entry corresponding to this PathScurry's current working directory.\n */\n cwd: PathBase\n #resolveCache: ResolveCache\n #resolvePosixCache: ResolveCache\n #children: ChildrenCache\n /**\n * Perform path comparisons case-insensitively.\n *\n * Defaults true on Darwin and Windows systems, false elsewhere.\n */\n nocase: boolean\n\n /**\n * The path separator used for parsing paths\n *\n * `'/'` on Posix systems, either `'/'` or `'\\\\'` on Windows\n */\n abstract sep: string | RegExp\n\n #fs: FSValue\n\n /**\n * This class should not be instantiated directly.\n *\n * Use PathScurryWin32, PathScurryDarwin, PathScurryPosix, or PathScurry\n *\n * @internal\n */\n constructor(\n cwd: URL | string = process.cwd(),\n pathImpl: typeof win32 | typeof posix,\n sep: string | RegExp,\n {\n nocase,\n childrenCacheSize = 16 * 1024,\n fs = defaultFS,\n }: PathScurryOpts = {},\n ) {\n this.#fs = fsFromOption(fs)\n if (cwd instanceof URL || cwd.startsWith('file://')) {\n cwd = fileURLToPath(cwd)\n }\n // resolve and split root, and then add to the store.\n // this is the only time we call path.resolve()\n const cwdPath = pathImpl.resolve(cwd)\n this.roots = Object.create(null)\n this.rootPath = this.parseRootPath(cwdPath)\n this.#resolveCache = new ResolveCache()\n this.#resolvePosixCache = new ResolveCache()\n this.#children = new ChildrenCache(childrenCacheSize)\n\n const split = cwdPath.substring(this.rootPath.length).split(sep)\n // resolve('/') leaves '', splits to [''], we don't want that.\n if (split.length === 1 && !split[0]) {\n split.pop()\n }\n /* c8 ignore start */\n if (nocase === undefined) {\n throw new TypeError(\n 'must provide nocase setting to PathScurryBase ctor',\n )\n }\n /* c8 ignore stop */\n this.nocase = nocase\n this.root = this.newRoot(this.#fs)\n this.roots[this.rootPath] = this.root\n let prev: PathBase = this.root\n let len = split.length - 1\n const joinSep = pathImpl.sep\n let abs = this.rootPath\n let sawFirst = false\n for (const part of split) {\n const l = len--\n prev = prev.child(part, {\n relative: new Array(l).fill('..').join(joinSep),\n relativePosix: new Array(l).fill('..').join('/'),\n fullpath: (abs += (sawFirst ? '' : joinSep) + part),\n })\n sawFirst = true\n }\n this.cwd = prev\n }\n\n /**\n * Get the depth of a provided path, string, or the cwd\n */\n depth(path: Path | string = this.cwd): number {\n if (typeof path === 'string') {\n path = this.cwd.resolve(path)\n }\n return path.depth()\n }\n\n /**\n * Parse the root portion of a path string\n *\n * @internal\n */\n abstract parseRootPath(dir: string): string\n /**\n * create a new Path to use as root during construction.\n *\n * @internal\n */\n abstract newRoot(fs: FSValue): PathBase\n /**\n * Determine whether a given path string is absolute\n */\n abstract isAbsolute(p: string): boolean\n\n /**\n * Return the cache of child entries. Exposed so subclasses can create\n * child Path objects in a platform-specific way.\n *\n * @internal\n */\n childrenCache() {\n return this.#children\n }\n\n /**\n * Resolve one or more path strings to a resolved string\n *\n * Same interface as require('path').resolve.\n *\n * Much faster than path.resolve() when called multiple times for the same\n * path, because the resolved Path objects are cached. Much slower\n * otherwise.\n */\n resolve(...paths: string[]): string {\n // first figure out the minimum number of paths we have to test\n // we always start at cwd, but any absolutes will bump the start\n let r = ''\n for (let i = paths.length - 1; i >= 0; i--) {\n const p = paths[i]\n if (!p || p === '.') continue\n r = r ? `${p}/${r}` : p\n if (this.isAbsolute(p)) {\n break\n }\n }\n const cached = this.#resolveCache.get(r)\n if (cached !== undefined) {\n return cached\n }\n const result = this.cwd.resolve(r).fullpath()\n this.#resolveCache.set(r, result)\n return result\n }\n\n /**\n * Resolve one or more path strings to a resolved string, returning\n * the posix path. Identical to .resolve() on posix systems, but on\n * windows will return a forward-slash separated UNC path.\n *\n * Same interface as require('path').resolve.\n *\n * Much faster than path.resolve() when called multiple times for the same\n * path, because the resolved Path objects are cached. Much slower\n * otherwise.\n */\n resolvePosix(...paths: string[]): string {\n // first figure out the minimum number of paths we have to test\n // we always start at cwd, but any absolutes will bump the start\n let r = ''\n for (let i = paths.length - 1; i >= 0; i--) {\n const p = paths[i]\n if (!p || p === '.') continue\n r = r ? `${p}/${r}` : p\n if (this.isAbsolute(p)) {\n break\n }\n }\n const cached = this.#resolvePosixCache.get(r)\n if (cached !== undefined) {\n return cached\n }\n const result = this.cwd.resolve(r).fullpathPosix()\n this.#resolvePosixCache.set(r, result)\n return result\n }\n\n /**\n * find the relative path from the cwd to the supplied path string or entry\n */\n relative(entry: PathBase | string = this.cwd): string {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n }\n return entry.relative()\n }\n\n /**\n * find the relative path from the cwd to the supplied path string or\n * entry, using / as the path delimiter, even on Windows.\n */\n relativePosix(entry: PathBase | string = this.cwd): string {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n }\n return entry.relativePosix()\n }\n\n /**\n * Return the basename for the provided string or Path object\n */\n basename(entry: PathBase | string = this.cwd): string {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n }\n return entry.name\n }\n\n /**\n * Return the dirname for the provided string or Path object\n */\n dirname(entry: PathBase | string = this.cwd): string {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n }\n return (entry.parent || entry).fullpath()\n }\n\n /**\n * Return an array of known child entries.\n *\n * First argument may be either a string, or a Path object.\n *\n * If the Path cannot or does not contain any children, then an empty array\n * is returned.\n *\n * Results are cached, and thus may be out of date if the filesystem is\n * mutated.\n *\n * Unlike `fs.readdir()`, the `withFileTypes` option defaults to `true`. Set\n * `{ withFileTypes: false }` to return strings.\n */\n\n readdir(): Promise<PathBase[]>\n readdir(opts: { withFileTypes: true }): Promise<PathBase[]>\n readdir(opts: { withFileTypes: false }): Promise<string[]>\n readdir(opts: { withFileTypes: boolean }): Promise<PathBase[] | string[]>\n readdir(entry: PathBase | string): Promise<PathBase[]>\n readdir(\n entry: PathBase | string,\n opts: { withFileTypes: true },\n ): Promise<PathBase[]>\n readdir(\n entry: PathBase | string,\n opts: { withFileTypes: false },\n ): Promise<string[]>\n readdir(\n entry: PathBase | string,\n opts: { withFileTypes: boolean },\n ): Promise<PathBase[] | string[]>\n async readdir(\n entry: PathBase | string | { withFileTypes: boolean } = this.cwd,\n opts: { withFileTypes: boolean } = {\n withFileTypes: true,\n },\n ): Promise<PathBase[] | string[]> {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n opts = entry\n entry = this.cwd\n }\n const { withFileTypes } = opts\n if (!entry.canReaddir()) {\n return []\n } else {\n const p = await entry.readdir()\n return withFileTypes ? p : p.map(e => e.name)\n }\n }\n\n /**\n * synchronous {@link PathScurryBase.readdir}\n */\n readdirSync(): PathBase[]\n readdirSync(opts: { withFileTypes: true }): PathBase[]\n readdirSync(opts: { withFileTypes: false }): string[]\n readdirSync(opts: { withFileTypes: boolean }): PathBase[] | string[]\n readdirSync(entry: PathBase | string): PathBase[]\n readdirSync(\n entry: PathBase | string,\n opts: { withFileTypes: true },\n ): PathBase[]\n readdirSync(\n entry: PathBase | string,\n opts: { withFileTypes: false },\n ): string[]\n readdirSync(\n entry: PathBase | string,\n opts: { withFileTypes: boolean },\n ): PathBase[] | string[]\n readdirSync(\n entry: PathBase | string | { withFileTypes: boolean } = this.cwd,\n opts: { withFileTypes: boolean } = {\n withFileTypes: true,\n },\n ): PathBase[] | string[] {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n opts = entry\n entry = this.cwd\n }\n const { withFileTypes = true } = opts\n if (!entry.canReaddir()) {\n return []\n } else if (withFileTypes) {\n return entry.readdirSync()\n } else {\n return entry.readdirSync().map(e => e.name)\n }\n }\n\n /**\n * Call lstat() on the string or Path object, and update all known\n * information that can be determined.\n *\n * Note that unlike `fs.lstat()`, the returned value does not contain some\n * information, such as `mode`, `dev`, `nlink`, and `ino`. If that\n * information is required, you will need to call `fs.lstat` yourself.\n *\n * If the Path refers to a nonexistent file, or if the lstat call fails for\n * any reason, `undefined` is returned. Otherwise the updated Path object is\n * returned.\n *\n * Results are cached, and thus may be out of date if the filesystem is\n * mutated.\n */\n async lstat(\n entry: string | PathBase = this.cwd,\n ): Promise<PathBase | undefined> {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n }\n return entry.lstat()\n }\n\n /**\n * synchronous {@link PathScurryBase.lstat}\n */\n lstatSync(entry: string | PathBase = this.cwd): PathBase | undefined {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n }\n return entry.lstatSync()\n }\n\n /**\n * Return the Path object or string path corresponding to the target of a\n * symbolic link.\n *\n * If the path is not a symbolic link, or if the readlink call fails for any\n * reason, `undefined` is returned.\n *\n * Result is cached, and thus may be outdated if the filesystem is mutated.\n *\n * `{withFileTypes}` option defaults to `false`.\n *\n * On success, returns a Path object if `withFileTypes` option is true,\n * otherwise a string.\n */\n readlink(): Promise<string | undefined>\n readlink(opt: { withFileTypes: false }): Promise<string | undefined>\n readlink(opt: { withFileTypes: true }): Promise<PathBase | undefined>\n readlink(opt: {\n withFileTypes: boolean\n }): Promise<PathBase | string | undefined>\n readlink(\n entry: string | PathBase,\n opt?: { withFileTypes: false },\n ): Promise<string | undefined>\n readlink(\n entry: string | PathBase,\n opt: { withFileTypes: true },\n ): Promise<PathBase | undefined>\n readlink(\n entry: string | PathBase,\n opt: { withFileTypes: boolean },\n ): Promise<string | PathBase | undefined>\n async readlink(\n entry: string | PathBase | { withFileTypes: boolean } = this.cwd,\n { withFileTypes }: { withFileTypes: boolean } = {\n withFileTypes: false,\n },\n ): Promise<string | PathBase | undefined> {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n withFileTypes = entry.withFileTypes\n entry = this.cwd\n }\n const e = await entry.readlink()\n return withFileTypes ? e : e?.fullpath()\n }\n\n /**\n * synchronous {@link PathScurryBase.readlink}\n */\n readlinkSync(): string | undefined\n readlinkSync(opt: { withFileTypes: false }): string | undefined\n readlinkSync(opt: { withFileTypes: true }): PathBase | undefined\n readlinkSync(opt: {\n withFileTypes: boolean\n }): PathBase | string | undefined\n readlinkSync(\n entry: string | PathBase,\n opt?: { withFileTypes: false },\n ): string | undefined\n readlinkSync(\n entry: string | PathBase,\n opt: { withFileTypes: true },\n ): PathBase | undefined\n readlinkSync(\n entry: string | PathBase,\n opt: { withFileTypes: boolean },\n ): string | PathBase | undefined\n readlinkSync(\n entry: string | PathBase | { withFileTypes: boolean } = this.cwd,\n { withFileTypes }: { withFileTypes: boolean } = {\n withFileTypes: false,\n },\n ): string | PathBase | undefined {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n withFileTypes = entry.withFileTypes\n entry = this.cwd\n }\n const e = entry.readlinkSync()\n return withFileTypes ? e : e?.fullpath()\n }\n\n /**\n * Return the Path object or string path corresponding to path as resolved\n * by realpath(3).\n *\n * If the realpath call fails for any reason, `undefined` is returned.\n *\n * Result is cached, and thus may be outdated if the filesystem is mutated.\n *\n * `{withFileTypes}` option defaults to `false`.\n *\n * On success, returns a Path object if `withFileTypes` option is true,\n * otherwise a string.\n */\n realpath(): Promise<string | undefined>\n realpath(opt: { withFileTypes: false }): Promise<string | undefined>\n realpath(opt: { withFileTypes: true }): Promise<PathBase | undefined>\n realpath(opt: {\n withFileTypes: boolean\n }): Promise<PathBase | string | undefined>\n realpath(\n entry: string | PathBase,\n opt?: { withFileTypes: false },\n ): Promise<string | undefined>\n realpath(\n entry: string | PathBase,\n opt: { withFileTypes: true },\n ): Promise<PathBase | undefined>\n realpath(\n entry: string | PathBase,\n opt: { withFileTypes: boolean },\n ): Promise<string | PathBase | undefined>\n async realpath(\n entry: string | PathBase | { withFileTypes: boolean } = this.cwd,\n { withFileTypes }: { withFileTypes: boolean } = {\n withFileTypes: false,\n },\n ): Promise<string | PathBase | undefined> {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n withFileTypes = entry.withFileTypes\n entry = this.cwd\n }\n const e = await entry.realpath()\n return withFileTypes ? e : e?.fullpath()\n }\n\n realpathSync(): string | undefined\n realpathSync(opt: { withFileTypes: false }): string | undefined\n realpathSync(opt: { withFileTypes: true }): PathBase | undefined\n realpathSync(opt: {\n withFileTypes: boolean\n }): PathBase | string | undefined\n realpathSync(\n entry: string | PathBase,\n opt?: { withFileTypes: false },\n ): string | undefined\n realpathSync(\n entry: string | PathBase,\n opt: { withFileTypes: true },\n ): PathBase | undefined\n realpathSync(\n entry: string | PathBase,\n opt: { withFileTypes: boolean },\n ): string | PathBase | undefined\n realpathSync(\n entry: string | PathBase | { withFileTypes: boolean } = this.cwd,\n { withFileTypes }: { withFileTypes: boolean } = {\n withFileTypes: false,\n },\n ): string | PathBase | undefined {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n withFileTypes = entry.withFileTypes\n entry = this.cwd\n }\n const e = entry.realpathSync()\n return withFileTypes ? e : e?.fullpath()\n }\n\n /**\n * Asynchronously walk the directory tree, returning an array of\n * all path strings or Path objects found.\n *\n * Note that this will be extremely memory-hungry on large filesystems.\n * In such cases, it may be better to use the stream or async iterator\n * walk implementation.\n */\n walk(): Promise<PathBase[]>\n walk(\n opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset,\n ): Promise<PathBase[]>\n walk(opts: WalkOptionsWithFileTypesFalse): Promise<string[]>\n walk(opts: WalkOptions): Promise<string[] | PathBase[]>\n walk(entry: string | PathBase): Promise<PathBase[]>\n walk(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset,\n ): Promise<PathBase[]>\n walk(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesFalse,\n ): Promise<string[]>\n walk(\n entry: string | PathBase,\n opts: WalkOptions,\n ): Promise<PathBase[] | string[]>\n async walk(\n entry: string | PathBase | WalkOptions = this.cwd,\n opts: WalkOptions = {},\n ): Promise<PathBase[] | string[]> {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n opts = entry\n entry = this.cwd\n }\n const {\n withFileTypes = true,\n follow = false,\n filter,\n walkFilter,\n } = opts\n const results: (string | PathBase)[] = []\n if (!filter || filter(entry)) {\n results.push(withFileTypes ? entry : entry.fullpath())\n }\n const dirs = new Set<PathBase>()\n const walk = (\n dir: PathBase,\n cb: (er?: NodeJS.ErrnoException) => void,\n ) => {\n dirs.add(dir)\n dir.readdirCB((er, entries) => {\n /* c8 ignore start */\n if (er) {\n return cb(er)\n }\n /* c8 ignore stop */\n let len = entries.length\n if (!len) return cb()\n const next = () => {\n if (--len === 0) {\n cb()\n }\n }\n for (const e of entries) {\n if (!filter || filter(e)) {\n results.push(withFileTypes ? e : e.fullpath())\n }\n if (follow && e.isSymbolicLink()) {\n e.realpath()\n .then(r => (r?.isUnknown() ? r.lstat() : r))\n .then(r =>\n r?.shouldWalk(dirs, walkFilter) ? walk(r, next) : next(),\n )\n } else {\n if (e.shouldWalk(dirs, walkFilter)) {\n walk(e, next)\n } else {\n next()\n }\n }\n }\n }, true) // zalgooooooo\n }\n\n const start = entry\n return new Promise<PathBase[] | string[]>((res, rej) => {\n walk(start, er => {\n /* c8 ignore start */\n if (er) return rej(er)\n /* c8 ignore stop */\n res(results as PathBase[] | string[])\n })\n })\n }\n\n /**\n * Synchronously walk the directory tree, returning an array of\n * all path strings or Path objects found.\n *\n * Note that this will be extremely memory-hungry on large filesystems.\n * In such cases, it may be better to use the stream or async iterator\n * walk implementation.\n */\n walkSync(): PathBase[]\n walkSync(\n opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset,\n ): PathBase[]\n walkSync(opts: WalkOptionsWithFileTypesFalse): string[]\n walkSync(opts: WalkOptions): string[] | PathBase[]\n walkSync(entry: string | PathBase): PathBase[]\n walkSync(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesUnset | WalkOptionsWithFileTypesTrue,\n ): PathBase[]\n walkSync(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesFalse,\n ): string[]\n walkSync(\n entry: string | PathBase,\n opts: WalkOptions,\n ): PathBase[] | string[]\n walkSync(\n entry: string | PathBase | WalkOptions = this.cwd,\n opts: WalkOptions = {},\n ): PathBase[] | string[] {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n opts = entry\n entry = this.cwd\n }\n const {\n withFileTypes = true,\n follow = false,\n filter,\n walkFilter,\n } = opts\n const results: (string | PathBase)[] = []\n if (!filter || filter(entry)) {\n results.push(withFileTypes ? entry : entry.fullpath())\n }\n const dirs = new Set<PathBase>([entry])\n for (const dir of dirs) {\n const entries = dir.readdirSync()\n for (const e of entries) {\n if (!filter || filter(e)) {\n results.push(withFileTypes ? e : e.fullpath())\n }\n let r: PathBase | undefined = e\n if (e.isSymbolicLink()) {\n if (!(follow && (r = e.realpathSync()))) continue\n if (r.isUnknown()) r.lstatSync()\n }\n if (r.shouldWalk(dirs, walkFilter)) {\n dirs.add(r)\n }\n }\n }\n return results as string[] | PathBase[]\n }\n\n /**\n * Support for `for await`\n *\n * Alias for {@link PathScurryBase.iterate}\n *\n * Note: As of Node 19, this is very slow, compared to other methods of\n * walking. Consider using {@link PathScurryBase.stream} if memory overhead\n * and backpressure are concerns, or {@link PathScurryBase.walk} if not.\n */\n [Symbol.asyncIterator]() {\n return this.iterate()\n }\n\n /**\n * Async generator form of {@link PathScurryBase.walk}\n *\n * Note: As of Node 19, this is very slow, compared to other methods of\n * walking, especially if most/all of the directory tree has been previously\n * walked. Consider using {@link PathScurryBase.stream} if memory overhead\n * and backpressure are concerns, or {@link PathScurryBase.walk} if not.\n */\n iterate(): AsyncGenerator<PathBase, void, void>\n iterate(\n opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset,\n ): AsyncGenerator<PathBase, void, void>\n iterate(\n opts: WalkOptionsWithFileTypesFalse,\n ): AsyncGenerator<string, void, void>\n iterate(opts: WalkOptions): AsyncGenerator<string | PathBase, void, void>\n iterate(entry: string | PathBase): AsyncGenerator<PathBase, void, void>\n iterate(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset,\n ): AsyncGenerator<PathBase, void, void>\n iterate(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesFalse,\n ): AsyncGenerator<string, void, void>\n iterate(\n entry: string | PathBase,\n opts: WalkOptions,\n ): AsyncGenerator<PathBase | string, void, void>\n iterate(\n entry: string | PathBase | WalkOptions = this.cwd,\n options: WalkOptions = {},\n ): AsyncGenerator<PathBase | string, void, void> {\n // iterating async over the stream is significantly more performant,\n // especially in the warm-cache scenario, because it buffers up directory\n // entries in the background instead of waiting for a yield for each one.\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n options = entry\n entry = this.cwd\n }\n return this.stream(entry, options)[Symbol.asyncIterator]()\n }\n\n /**\n * Iterating over a PathScurry performs a synchronous walk.\n *\n * Alias for {@link PathScurryBase.iterateSync}\n */\n [Symbol.iterator]() {\n return this.iterateSync()\n }\n\n iterateSync(): Generator<PathBase, void, void>\n iterateSync(\n opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset,\n ): Generator<PathBase, void, void>\n iterateSync(\n opts: WalkOptionsWithFileTypesFalse,\n ): Generator<string, void, void>\n iterateSync(opts: WalkOptions): Generator<string | PathBase, void, void>\n iterateSync(entry: string | PathBase): Generator<PathBase, void, void>\n iterateSync(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset,\n ): Generator<PathBase, void, void>\n iterateSync(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesFalse,\n ): Generator<string, void, void>\n iterateSync(\n entry: string | PathBase,\n opts: WalkOptions,\n ): Generator<PathBase | string, void, void>\n *iterateSync(\n entry: string | PathBase | WalkOptions = this.cwd,\n opts: WalkOptions = {},\n ): Generator<PathBase | string, void, void> {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n opts = entry\n entry = this.cwd\n }\n const {\n withFileTypes = true,\n follow = false,\n filter,\n walkFilter,\n } = opts\n if (!filter || filter(entry)) {\n yield withFileTypes ? entry : entry.fullpath()\n }\n const dirs = new Set<PathBase>([entry])\n for (const dir of dirs) {\n const entries = dir.readdirSync()\n for (const e of entries) {\n if (!filter || filter(e)) {\n yield withFileTypes ? e : e.fullpath()\n }\n let r: PathBase | undefined = e\n if (e.isSymbolicLink()) {\n if (!(follow && (r = e.realpathSync()))) continue\n if (r.isUnknown()) r.lstatSync()\n }\n if (r.shouldWalk(dirs, walkFilter)) {\n dirs.add(r)\n }\n }\n }\n }\n\n /**\n * Stream form of {@link PathScurryBase.walk}\n *\n * Returns a Minipass stream that emits {@link PathBase} objects by default,\n * or strings if `{ withFileTypes: false }` is set in the options.\n */\n stream(): Minipass<PathBase>\n stream(\n opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset,\n ): Minipass<PathBase>\n stream(opts: WalkOptionsWithFileTypesFalse): Minipass<string>\n stream(opts: WalkOptions): Minipass<string | PathBase>\n stream(entry: string | PathBase): Minipass<PathBase>\n stream(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesUnset | WalkOptionsWithFileTypesTrue,\n ): Minipass<PathBase>\n stream(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesFalse,\n ): Minipass<string>\n stream(\n entry: string | PathBase,\n opts: WalkOptions,\n ): Minipass<string> | Minipass<PathBase>\n stream(\n entry: string | PathBase | WalkOptions = this.cwd,\n opts: WalkOptions = {},\n ): Minipass<string> | Minipass<PathBase> {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n opts = entry\n entry = this.cwd\n }\n const {\n withFileTypes = true,\n follow = false,\n filter,\n walkFilter,\n } = opts\n const results = new Minipass<string | PathBase>({ objectMode: true })\n if (!filter || filter(entry)) {\n results.write(withFileTypes ? entry : entry.fullpath())\n }\n const dirs = new Set<PathBase>()\n const queue: PathBase[] = [entry]\n let processing = 0\n const process = () => {\n let paused = false\n while (!paused) {\n const dir = queue.shift()\n if (!dir) {\n if (processing === 0) results.end()\n return\n }\n\n processing++\n dirs.add(dir)\n\n const onReaddir = (\n er: null | NodeJS.ErrnoException,\n entries: PathBase[],\n didRealpaths: boolean = false,\n ) => {\n /* c8 ignore start */\n if (er) return results.emit('error', er)\n /* c8 ignore stop */\n if (follow && !didRealpaths) {\n const promises: Promise<PathBase | undefined>[] = []\n for (const e of entries) {\n if (e.isSymbolicLink()) {\n promises.push(\n e\n .realpath()\n .then((r: PathBase | undefined) =>\n r?.isUnknown() ? r.lstat() : r,\n ),\n )\n }\n }\n if (promises.length) {\n Promise.all(promises).then(() =>\n onReaddir(null, entries, true),\n )\n return\n }\n }\n\n for (const e of entries) {\n if (e && (!filter || filter(e))) {\n if (!results.write(withFileTypes ? e : e.fullpath())) {\n paused = true\n }\n }\n }\n\n processing--\n for (const e of entries) {\n const r = e.realpathCached() || e\n if (r.shouldWalk(dirs, walkFilter)) {\n queue.push(r)\n }\n }\n if (paused && !results.flowing) {\n results.once('drain', process)\n } else if (!sync) {\n process()\n }\n }\n\n // zalgo containment\n let sync = true\n dir.readdirCB(onReaddir, true)\n sync = false\n }\n }\n process()\n return results as Minipass<string> | Minipass<PathBase>\n }\n\n /**\n * Synchronous form of {@link PathScurryBase.stream}\n *\n * Returns a Minipass stream that emits {@link PathBase} objects by default,\n * or strings if `{ withFileTypes: false }` is set in the options.\n *\n * Will complete the walk in a single tick if the stream is consumed fully.\n * Otherwise, will pause as needed for stream backpressure.\n */\n streamSync(): Minipass<PathBase>\n streamSync(\n opts: WalkOptionsWithFileTypesTrue | WalkOptionsWithFileTypesUnset,\n ): Minipass<PathBase>\n streamSync(opts: WalkOptionsWithFileTypesFalse): Minipass<string>\n streamSync(opts: WalkOptions): Minipass<string | PathBase>\n streamSync(entry: string | PathBase): Minipass<PathBase>\n streamSync(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesUnset | WalkOptionsWithFileTypesTrue,\n ): Minipass<PathBase>\n streamSync(\n entry: string | PathBase,\n opts: WalkOptionsWithFileTypesFalse,\n ): Minipass<string>\n streamSync(\n entry: string | PathBase,\n opts: WalkOptions,\n ): Minipass<string> | Minipass<PathBase>\n streamSync(\n entry: string | PathBase | WalkOptions = this.cwd,\n opts: WalkOptions = {},\n ): Minipass<string> | Minipass<PathBase> {\n if (typeof entry === 'string') {\n entry = this.cwd.resolve(entry)\n } else if (!(entry instanceof PathBase)) {\n opts = entry\n entry = this.cwd\n }\n const {\n withFileTypes = true,\n follow = false,\n filter,\n walkFilter,\n } = opts\n const results = new Minipass<string | PathBase>({ objectMode: true })\n const dirs = new Set<PathBase>()\n if (!filter || filter(entry)) {\n results.write(withFileTypes ? entry : entry.fullpath())\n }\n const queue: PathBase[] = [entry]\n let processing = 0\n const process = () => {\n let paused = false\n while (!paused) {\n const dir = queue.shift()\n if (!dir) {\n if (processing === 0) results.end()\n return\n }\n processing++\n dirs.add(dir)\n\n const entries = dir.readdirSync()\n for (const e of entries) {\n if (!filter || filter(e)) {\n if (!results.write(withFileTypes ? e : e.fullpath())) {\n paused = true\n }\n }\n }\n processing--\n for (const e of entries) {\n let r: PathBase | undefined = e\n if (e.isSymbolicLink()) {\n if (!(follow && (r = e.realpathSync()))) continue\n if (r.isUnknown()) r.lstatSync()\n }\n if (r.shouldWalk(dirs, walkFilter)) {\n queue.push(r)\n }\n }\n }\n if (paused && !results.flowing) results.once('drain', process)\n }\n process()\n return results as Minipass<string> | Minipass<PathBase>\n }\n\n chdir(path: string | Path = this.cwd) {\n const oldCwd = this.cwd\n this.cwd = typeof path === 'string' ? this.cwd.resolve(path) : path\n this.cwd[setAsCwd](oldCwd)\n }\n}\n\n/**\n * Options provided to all walk methods.\n */\nexport interface WalkOptions {\n /**\n * Return results as {@link PathBase} objects rather than strings.\n * When set to false, results are fully resolved paths, as returned by\n * {@link PathBase.fullpath}.\n * @default true\n */\n withFileTypes?: boolean\n\n /**\n * Attempt to read directory entries from symbolic links. Otherwise, only\n * actual directories are traversed. Regardless of this setting, a given\n * target path will only ever be walked once, meaning that a symbolic link\n * to a previously traversed directory will never be followed.\n *\n * Setting this imposes a slight performance penalty, because `readlink`\n * must be called on all symbolic links encountered, in order to avoid\n * infinite cycles.\n * @default false\n */\n follow?: boolean\n\n /**\n * Only return entries where the provided function returns true.\n *\n * This will not prevent directories from being traversed, even if they do\n * not pass the filter, though it will prevent directories themselves from\n * being included in the result set. See {@link walkFilter}\n *\n * Asynchronous functions are not supported here.\n *\n * By default, if no filter is provided, all entries and traversed\n * directories are included.\n */\n filter?: (entry: PathBase) => boolean\n\n /**\n * Only traverse directories (and in the case of {@link follow} being set to\n * true, symbolic links to directories) if the provided function returns\n * true.\n *\n * This will not prevent directories from being included in the result set,\n * even if they do not pass the supplied filter function. See {@link filter}\n * to do that.\n *\n * Asynchronous functions are not supported here.\n */\n walkFilter?: (entry: PathBase) => boolean\n}\n\nexport type WalkOptionsWithFileTypesUnset = WalkOptions & {\n withFileTypes?: undefined\n}\nexport type WalkOptionsWithFileTypesTrue = WalkOptions & {\n withFileTypes: true\n}\nexport type WalkOptionsWithFileTypesFalse = WalkOptions & {\n withFileTypes: false\n}\n\n/**\n * Windows implementation of {@link PathScurryBase}\n *\n * Defaults to case insensitve, uses `'\\\\'` to generate path strings. Uses\n * {@link PathWin32} for Path objects.\n */\nexport class PathScurryWin32 extends PathScurryBase {\n /**\n * separator for generating path strings\n */\n sep: '\\\\' = '\\\\'\n\n constructor(\n cwd: URL | string = process.cwd(),\n opts: PathScurryOpts = {},\n ) {\n const { nocase = true } = opts\n super(cwd, win32, '\\\\', { ...opts, nocase })\n this.nocase = nocase\n for (let p: PathBase | undefined = this.cwd; p; p = p.parent) {\n p.nocase = this.nocase\n }\n }\n\n /**\n * @internal\n */\n parseRootPath(dir: string): string {\n // if the path starts with a single separator, it's not a UNC, and we'll\n // just get separator as the root, and driveFromUNC will return \\\n // In that case, mount \\ on the root from the cwd.\n return win32.parse(dir).root.toUpperCase()\n }\n\n /**\n * @internal\n */\n newRoot(fs: FSValue) {\n return new PathWin32(\n this.rootPath,\n IFDIR,\n undefined,\n this.roots,\n this.nocase,\n this.childrenCache(),\n { fs },\n )\n }\n\n /**\n * Return true if the provided path string is an absolute path\n */\n isAbsolute(p: string): boolean {\n return (\n p.startsWith('/') || p.startsWith('\\\\') || /^[a-z]:(\\/|\\\\)/i.test(p)\n )\n }\n}\n\n/**\n * {@link PathScurryBase} implementation for all posix systems other than Darwin.\n *\n * Defaults to case-sensitive matching, uses `'/'` to generate path strings.\n *\n * Uses {@link PathPosix} for Path objects.\n */\nexport class PathScurryPosix extends PathScurryBase {\n /**\n * separator for generating path strings\n */\n sep: '/' = '/'\n constructor(\n cwd: URL | string = process.cwd(),\n opts: PathScurryOpts = {},\n ) {\n const { nocase = false } = opts\n super(cwd, posix, '/', { ...opts, nocase })\n this.nocase = nocase\n }\n\n /**\n * @internal\n */\n parseRootPath(_dir: string): string {\n return '/'\n }\n\n /**\n * @internal\n */\n newRoot(fs: FSValue) {\n return new PathPosix(\n this.rootPath,\n IFDIR,\n undefined,\n this.roots,\n this.nocase,\n this.childrenCache(),\n { fs },\n )\n }\n\n /**\n * Return true if the provided path string is an absolute path\n */\n isAbsolute(p: string): boolean {\n return p.startsWith('/')\n }\n}\n\n/**\n * {@link PathScurryBase} implementation for Darwin (macOS) systems.\n *\n * Defaults to case-insensitive matching, uses `'/'` for generating path\n * strings.\n *\n * Uses {@link PathPosix} for Path objects.\n */\nexport class PathScurryDarwin extends PathScurryPosix {\n constructor(\n cwd: URL | string = process.cwd(),\n opts: PathScurryOpts = {},\n ) {\n const { nocase = true } = opts\n super(cwd, { ...opts, nocase })\n }\n}\n\n/**\n * Default {@link PathBase} implementation for the current platform.\n *\n * {@link PathWin32} on Windows systems, {@link PathPosix} on all others.\n */\nexport const Path = process.platform === 'win32' ? PathWin32 : PathPosix\nexport type Path = PathBase | InstanceType<typeof Path>\n\n/**\n * Default {@link PathScurryBase} implementation for the current platform.\n *\n * {@link PathScurryWin32} on Windows systems, {@link PathScurryDarwin} on\n * Darwin (macOS) systems, {@link PathScurryPosix} on all others.\n */\nexport const PathScurry:\n | typeof PathScurryWin32\n | typeof PathScurryDarwin\n | typeof PathScurryPosix =\n process.platform === 'win32' ? PathScurryWin32\n : process.platform === 'darwin' ? PathScurryDarwin\n : PathScurryPosix\nexport type PathScurry = PathScurryBase | InstanceType<typeof PathScurry>\n","const proc =\n typeof process === 'object' && process\n ? process\n : {\n stdout: null,\n stderr: null,\n }\nimport { EventEmitter } from 'node:events'\nimport Stream from 'node:stream'\nimport { StringDecoder } from 'node:string_decoder'\n\n/**\n * Same as StringDecoder, but exposing the `lastNeed` flag on the type\n */\ntype SD = StringDecoder & { lastNeed: boolean }\n\nexport type { SD, Pipe, PipeProxyErrors }\n\n/**\n * Return true if the argument is a Minipass stream, Node stream, or something\n * else that Minipass can interact with.\n */\nexport const isStream = (\n s: any\n): s is Minipass.Readable | Minipass.Writable =>\n !!s &&\n typeof s === 'object' &&\n (s instanceof Minipass ||\n s instanceof Stream ||\n isReadable(s) ||\n isWritable(s))\n\n/**\n * Return true if the argument is a valid {@link Minipass.Readable}\n */\nexport const isReadable = (s: any): s is Minipass.Readable =>\n !!s &&\n typeof s === 'object' &&\n s instanceof EventEmitter &&\n typeof (s as Minipass.Readable).pipe === 'function' &&\n // node core Writable streams have a pipe() method, but it throws\n (s as Minipass.Readable).pipe !== Stream.Writable.prototype.pipe\n\n/**\n * Return true if the argument is a valid {@link Minipass.Writable}\n */\nexport const isWritable = (s: any): s is Minipass.Readable =>\n !!s &&\n typeof s === 'object' &&\n s instanceof EventEmitter &&\n typeof (s as Minipass.Writable).write === 'function' &&\n typeof (s as Minipass.Writable).end === 'function'\n\nconst EOF = Symbol('EOF')\nconst MAYBE_EMIT_END = Symbol('maybeEmitEnd')\nconst EMITTED_END = Symbol('emittedEnd')\nconst EMITTING_END = Symbol('emittingEnd')\nconst EMITTED_ERROR = Symbol('emittedError')\nconst CLOSED = Symbol('closed')\nconst READ = Symbol('read')\nconst FLUSH = Symbol('flush')\nconst FLUSHCHUNK = Symbol('flushChunk')\nconst ENCODING = Symbol('encoding')\nconst DECODER = Symbol('decoder')\nconst FLOWING = Symbol('flowing')\nconst PAUSED = Symbol('paused')\nconst RESUME = Symbol('resume')\nconst BUFFER = Symbol('buffer')\nconst PIPES = Symbol('pipes')\nconst BUFFERLENGTH = Symbol('bufferLength')\nconst BUFFERPUSH = Symbol('bufferPush')\nconst BUFFERSHIFT = Symbol('bufferShift')\nconst OBJECTMODE = Symbol('objectMode')\n// internal event when stream is destroyed\nconst DESTROYED = Symbol('destroyed')\n// internal event when stream has an error\nconst ERROR = Symbol('error')\nconst EMITDATA = Symbol('emitData')\nconst EMITEND = Symbol('emitEnd')\nconst EMITEND2 = Symbol('emitEnd2')\nconst ASYNC = Symbol('async')\nconst ABORT = Symbol('abort')\nconst ABORTED = Symbol('aborted')\nconst SIGNAL = Symbol('signal')\nconst DATALISTENERS = Symbol('dataListeners')\nconst DISCARDED = Symbol('discarded')\n\nconst defer = (fn: (...a: any[]) => any) => Promise.resolve().then(fn)\nconst nodefer = (fn: (...a: any[]) => any) => fn()\n\n// events that mean 'the stream is over'\n// these are treated specially, and re-emitted\n// if they are listened for after emitting.\ntype EndishEvent = 'end' | 'finish' | 'prefinish'\nconst isEndish = (ev: any): ev is EndishEvent =>\n ev === 'end' || ev === 'finish' || ev === 'prefinish'\n\nconst isArrayBufferLike = (b: any): b is ArrayBufferLike =>\n b instanceof ArrayBuffer ||\n (!!b &&\n typeof b === 'object' &&\n b.constructor &&\n b.constructor.name === 'ArrayBuffer' &&\n b.byteLength >= 0)\n\nconst isArrayBufferView = (b: any): b is ArrayBufferView =>\n !Buffer.isBuffer(b) && ArrayBuffer.isView(b)\n\n/**\n * Options that may be passed to stream.pipe()\n */\nexport interface PipeOptions {\n /**\n * end the destination stream when the source stream ends\n */\n end?: boolean\n /**\n * proxy errors from the source stream to the destination stream\n */\n proxyErrors?: boolean\n}\n\n/**\n * Internal class representing a pipe to a destination stream.\n *\n * @internal\n */\nclass Pipe<T extends unknown> {\n src: Minipass<T>\n dest: Minipass<any, T>\n opts: PipeOptions\n ondrain: () => any\n constructor(\n src: Minipass<T>,\n dest: Minipass.Writable,\n opts: PipeOptions\n ) {\n this.src = src\n this.dest = dest as Minipass<any, T>\n this.opts = opts\n this.ondrain = () => src[RESUME]()\n this.dest.on('drain', this.ondrain)\n }\n unpipe() {\n this.dest.removeListener('drain', this.ondrain)\n }\n // only here for the prototype\n /* c8 ignore start */\n proxyErrors(_er: any) {}\n /* c8 ignore stop */\n end() {\n this.unpipe()\n if (this.opts.end) this.dest.end()\n }\n}\n\n/**\n * Internal class representing a pipe to a destination stream where\n * errors are proxied.\n *\n * @internal\n */\nclass PipeProxyErrors<T> extends Pipe<T> {\n unpipe() {\n this.src.removeListener('error', this.proxyErrors)\n super.unpipe()\n }\n constructor(\n src: Minipass<T>,\n dest: Minipass.Writable,\n opts: PipeOptions\n ) {\n super(src, dest, opts)\n this.proxyErrors = (er: Error) => this.dest.emit('error', er)\n src.on('error', this.proxyErrors)\n }\n}\n\nexport namespace Minipass {\n /**\n * Encoding used to create a stream that outputs strings rather than\n * Buffer objects.\n */\n export type Encoding = BufferEncoding | 'buffer' | null\n\n /**\n * Any stream that Minipass can pipe into\n */\n export type Writable =\n | Minipass<any, any, any>\n | NodeJS.WriteStream\n | (NodeJS.WriteStream & { fd: number })\n | (EventEmitter & {\n end(): any\n write(chunk: any, ...args: any[]): any\n })\n\n /**\n * Any stream that can be read from\n */\n export type Readable =\n | Minipass<any, any, any>\n | NodeJS.ReadStream\n | (NodeJS.ReadStream & { fd: number })\n | (EventEmitter & {\n pause(): any\n resume(): any\n pipe(...destArgs: any[]): any\n })\n\n /**\n * Utility type that can be iterated sync or async\n */\n export type DualIterable<T> = Iterable<T> & AsyncIterable<T>\n\n type EventArguments = Record<string | symbol, unknown[]>\n\n /**\n * The listing of events that a Minipass class can emit.\n * Extend this when extending the Minipass class, and pass as\n * the third template argument. The key is the name of the event,\n * and the value is the argument list.\n *\n * Any undeclared events will still be allowed, but the handler will get\n * arguments as `unknown[]`.\n */\n export interface Events<RType extends any = Buffer>\n extends EventArguments {\n readable: []\n data: [chunk: RType]\n error: [er: unknown]\n abort: [reason: unknown]\n drain: []\n resume: []\n end: []\n finish: []\n prefinish: []\n close: []\n [DESTROYED]: [er?: unknown]\n [ERROR]: [er: unknown]\n }\n\n /**\n * String or buffer-like data that can be joined and sliced\n */\n export type ContiguousData =\n | Buffer\n | ArrayBufferLike\n | ArrayBufferView\n | string\n export type BufferOrString = Buffer | string\n\n /**\n * Options passed to the Minipass constructor.\n */\n export type SharedOptions = {\n /**\n * Defer all data emission and other events until the end of the\n * current tick, similar to Node core streams\n */\n async?: boolean\n /**\n * A signal which will abort the stream\n */\n signal?: AbortSignal\n /**\n * Output string encoding. Set to `null` or `'buffer'` (or omit) to\n * emit Buffer objects rather than strings.\n *\n * Conflicts with `objectMode`\n */\n encoding?: BufferEncoding | null | 'buffer'\n /**\n * Output data exactly as it was written, supporting non-buffer/string\n * data (such as arbitrary objects, falsey values, etc.)\n *\n * Conflicts with `encoding`\n */\n objectMode?: boolean\n }\n\n /**\n * Options for a string encoded output\n */\n export type EncodingOptions = SharedOptions & {\n encoding: BufferEncoding\n objectMode?: false\n }\n\n /**\n * Options for contiguous data buffer output\n */\n export type BufferOptions = SharedOptions & {\n encoding?: null | 'buffer'\n objectMode?: false\n }\n\n /**\n * Options for objectMode arbitrary output\n */\n export type ObjectModeOptions = SharedOptions & {\n objectMode: true\n encoding?: null\n }\n\n /**\n * Utility type to determine allowed options based on read type\n */\n export type Options<T> =\n | ObjectModeOptions\n | (T extends string\n ? EncodingOptions\n : T extends Buffer\n ? BufferOptions\n : SharedOptions)\n}\n\nconst isObjectModeOptions = (\n o: Minipass.SharedOptions\n): o is Minipass.ObjectModeOptions => !!o.objectMode\n\nconst isEncodingOptions = (\n o: Minipass.SharedOptions\n): o is Minipass.EncodingOptions =>\n !o.objectMode && !!o.encoding && o.encoding !== 'buffer'\n\n/**\n * Main export, the Minipass class\n *\n * `RType` is the type of data emitted, defaults to Buffer\n *\n * `WType` is the type of data to be written, if RType is buffer or string,\n * then any {@link Minipass.ContiguousData} is allowed.\n *\n * `Events` is the set of event handler signatures that this object\n * will emit, see {@link Minipass.Events}\n */\nexport class Minipass<\n RType extends unknown = Buffer,\n WType extends unknown = RType extends Minipass.BufferOrString\n ? Minipass.ContiguousData\n : RType,\n Events extends Minipass.Events<RType> = Minipass.Events<RType>\n >\n extends EventEmitter\n implements Minipass.DualIterable<RType>\n{\n [FLOWING]: boolean = false;\n [PAUSED]: boolean = false;\n [PIPES]: Pipe<RType>[] = [];\n [BUFFER]: RType[] = [];\n [OBJECTMODE]: boolean;\n [ENCODING]: BufferEncoding | null;\n [ASYNC]: boolean;\n [DECODER]: SD | null;\n [EOF]: boolean = false;\n [EMITTED_END]: boolean = false;\n [EMITTING_END]: boolean = false;\n [CLOSED]: boolean = false;\n [EMITTED_ERROR]: unknown = null;\n [BUFFERLENGTH]: number = 0;\n [DESTROYED]: boolean = false;\n [SIGNAL]?: AbortSignal;\n [ABORTED]: boolean = false;\n [DATALISTENERS]: number = 0;\n [DISCARDED]: boolean = false\n\n /**\n * true if the stream can be written\n */\n writable: boolean = true\n /**\n * true if the stream can be read\n */\n readable: boolean = true\n\n /**\n * If `RType` is Buffer, then options do not need to be provided.\n * Otherwise, an options object must be provided to specify either\n * {@link Minipass.SharedOptions.objectMode} or\n * {@link Minipass.SharedOptions.encoding}, as appropriate.\n */\n constructor(\n ...args:\n | [Minipass.ObjectModeOptions]\n | (RType extends Buffer\n ? [] | [Minipass.Options<RType>]\n : [Minipass.Options<RType>])\n ) {\n const options: Minipass.Options<RType> = (args[0] ||\n {}) as Minipass.Options<RType>\n super()\n if (options.objectMode && typeof options.encoding === 'string') {\n throw new TypeError(\n 'Encoding and objectMode may not be used together'\n )\n }\n if (isObjectModeOptions(options)) {\n this[OBJECTMODE] = true\n this[ENCODING] = null\n } else if (isEncodingOptions(options)) {\n this[ENCODING] = options.encoding\n this[OBJECTMODE] = false\n } else {\n this[OBJECTMODE] = false\n this[ENCODING] = null\n }\n this[ASYNC] = !!options.async\n this[DECODER] = this[ENCODING]\n ? (new StringDecoder(this[ENCODING]) as SD)\n : null\n\n //@ts-ignore - private option for debugging and testing\n if (options && options.debugExposeBuffer === true) {\n Object.defineProperty(this, 'buffer', { get: () => this[BUFFER] })\n }\n //@ts-ignore - private option for debugging and testing\n if (options && options.debugExposePipes === true) {\n Object.defineProperty(this, 'pipes', { get: () => this[PIPES] })\n }\n\n const { signal } = options\n if (signal) {\n this[SIGNAL] = signal\n if (signal.aborted) {\n this[ABORT]()\n } else {\n signal.addEventListener('abort', () => this[ABORT]())\n }\n }\n }\n\n /**\n * The amount of data stored in the buffer waiting to be read.\n *\n * For Buffer strings, this will be the total byte length.\n * For string encoding streams, this will be the string character length,\n * according to JavaScript's `string.length` logic.\n * For objectMode streams, this is a count of the items waiting to be\n * emitted.\n */\n get bufferLength() {\n return this[BUFFERLENGTH]\n }\n\n /**\n * The `BufferEncoding` currently in use, or `null`\n */\n get encoding() {\n return this[ENCODING]\n }\n\n /**\n * @deprecated - This is a read only property\n */\n set encoding(_enc) {\n throw new Error('Encoding must be set at instantiation time')\n }\n\n /**\n * @deprecated - Encoding may only be set at instantiation time\n */\n setEncoding(_enc: Minipass.Encoding) {\n throw new Error('Encoding must be set at instantiation time')\n }\n\n /**\n * True if this is an objectMode stream\n */\n get objectMode() {\n return this[OBJECTMODE]\n }\n\n /**\n * @deprecated - This is a read-only property\n */\n set objectMode(_om) {\n throw new Error('objectMode must be set at instantiation time')\n }\n\n /**\n * true if this is an async stream\n */\n get ['async'](): boolean {\n return this[ASYNC]\n }\n /**\n * Set to true to make this stream async.\n *\n * Once set, it cannot be unset, as this would potentially cause incorrect\n * behavior. Ie, a sync stream can be made async, but an async stream\n * cannot be safely made sync.\n */\n set ['async'](a: boolean) {\n this[ASYNC] = this[ASYNC] || !!a\n }\n\n // drop everything and get out of the flow completely\n [ABORT]() {\n this[ABORTED] = true\n this.emit('abort', this[SIGNAL]?.reason)\n this.destroy(this[SIGNAL]?.reason)\n }\n\n /**\n * True if the stream has been aborted.\n */\n get aborted() {\n return this[ABORTED]\n }\n /**\n * No-op setter. Stream aborted status is set via the AbortSignal provided\n * in the constructor options.\n */\n set aborted(_) {}\n\n /**\n * Write data into the stream\n *\n * If the chunk written is a string, and encoding is not specified, then\n * `utf8` will be assumed. If the stream encoding matches the encoding of\n * a written string, and the state of the string decoder allows it, then\n * the string will be passed through to either the output or the internal\n * buffer without any processing. Otherwise, it will be turned into a\n * Buffer object for processing into the desired encoding.\n *\n * If provided, `cb` function is called immediately before return for\n * sync streams, or on next tick for async streams, because for this\n * base class, a chunk is considered \"processed\" once it is accepted\n * and either emitted or buffered. That is, the callback does not indicate\n * that the chunk has been eventually emitted, though of course child\n * classes can override this function to do whatever processing is required\n * and call `super.write(...)` only once processing is completed.\n */\n write(chunk: WType, cb?: () => void): boolean\n write(\n chunk: WType,\n encoding?: Minipass.Encoding,\n cb?: () => void\n ): boolean\n write(\n chunk: WType,\n encoding?: Minipass.Encoding | (() => void),\n cb?: () => void\n ): boolean {\n if (this[ABORTED]) return false\n if (this[EOF]) throw new Error('write after end')\n\n if (this[DESTROYED]) {\n this.emit(\n 'error',\n Object.assign(\n new Error('Cannot call write after a stream was destroyed'),\n { code: 'ERR_STREAM_DESTROYED' }\n )\n )\n return true\n }\n\n if (typeof encoding === 'function') {\n cb = encoding\n encoding = 'utf8'\n }\n\n if (!encoding) encoding = 'utf8'\n\n const fn = this[ASYNC] ? defer : nodefer\n\n // convert array buffers and typed array views into buffers\n // at some point in the future, we may want to do the opposite!\n // leave strings and buffers as-is\n // anything is only allowed if in object mode, so throw\n if (!this[OBJECTMODE] && !Buffer.isBuffer(chunk)) {\n if (isArrayBufferView(chunk)) {\n //@ts-ignore - sinful unsafe type changing\n chunk = Buffer.from(\n chunk.buffer,\n chunk.byteOffset,\n chunk.byteLength\n )\n } else if (isArrayBufferLike(chunk)) {\n //@ts-ignore - sinful unsafe type changing\n chunk = Buffer.from(chunk)\n } else if (typeof chunk !== 'string') {\n throw new Error(\n 'Non-contiguous data written to non-objectMode stream'\n )\n }\n }\n\n // handle object mode up front, since it's simpler\n // this yields better performance, fewer checks later.\n if (this[OBJECTMODE]) {\n // maybe impossible?\n /* c8 ignore start */\n if (this[FLOWING] && this[BUFFERLENGTH] !== 0) this[FLUSH](true)\n /* c8 ignore stop */\n\n if (this[FLOWING]) this.emit('data', chunk as unknown as RType)\n else this[BUFFERPUSH](chunk as unknown as RType)\n\n if (this[BUFFERLENGTH] !== 0) this.emit('readable')\n\n if (cb) fn(cb)\n\n return this[FLOWING]\n }\n\n // at this point the chunk is a buffer or string\n // don't buffer it up or send it to the decoder\n if (!(chunk as Minipass.BufferOrString).length) {\n if (this[BUFFERLENGTH] !== 0) this.emit('readable')\n if (cb) fn(cb)\n return this[FLOWING]\n }\n\n // fast-path writing strings of same encoding to a stream with\n // an empty buffer, skipping the buffer/decoder dance\n if (\n typeof chunk === 'string' &&\n // unless it is a string already ready for us to use\n !(encoding === this[ENCODING] && !this[DECODER]?.lastNeed)\n ) {\n //@ts-ignore - sinful unsafe type change\n chunk = Buffer.from(chunk, encoding)\n }\n\n if (Buffer.isBuffer(chunk) && this[ENCODING]) {\n //@ts-ignore - sinful unsafe type change\n chunk = this[DECODER].write(chunk)\n }\n\n // Note: flushing CAN potentially switch us into not-flowing mode\n if (this[FLOWING] && this[BUFFERLENGTH] !== 0) this[FLUSH](true)\n\n if (this[FLOWING]) this.emit('data', chunk as unknown as RType)\n else this[BUFFERPUSH](chunk as unknown as RType)\n\n if (this[BUFFERLENGTH] !== 0) this.emit('readable')\n\n if (cb) fn(cb)\n\n return this[FLOWING]\n }\n\n /**\n * Low-level explicit read method.\n *\n * In objectMode, the argument is ignored, and one item is returned if\n * available.\n *\n * `n` is the number of bytes (or in the case of encoding streams,\n * characters) to consume. If `n` is not provided, then the entire buffer\n * is returned, or `null` is returned if no data is available.\n *\n * If `n` is greater that the amount of data in the internal buffer,\n * then `null` is returned.\n */\n read(n?: number | null): RType | null {\n if (this[DESTROYED]) return null\n this[DISCARDED] = false\n\n if (\n this[BUFFERLENGTH] === 0 ||\n n === 0 ||\n (n && n > this[BUFFERLENGTH])\n ) {\n this[MAYBE_EMIT_END]()\n return null\n }\n\n if (this[OBJECTMODE]) n = null\n\n if (this[BUFFER].length > 1 && !this[OBJECTMODE]) {\n // not object mode, so if we have an encoding, then RType is string\n // otherwise, must be Buffer\n this[BUFFER] = [\n (this[ENCODING]\n ? this[BUFFER].join('')\n : Buffer.concat(\n this[BUFFER] as Buffer[],\n this[BUFFERLENGTH]\n )) as RType,\n ]\n }\n\n const ret = this[READ](n || null, this[BUFFER][0] as RType)\n this[MAYBE_EMIT_END]()\n return ret\n }\n\n [READ](n: number | null, chunk: RType) {\n if (this[OBJECTMODE]) this[BUFFERSHIFT]()\n else {\n const c = chunk as Minipass.BufferOrString\n if (n === c.length || n === null) this[BUFFERSHIFT]()\n else if (typeof c === 'string') {\n this[BUFFER][0] = c.slice(n) as RType\n chunk = c.slice(0, n) as RType\n this[BUFFERLENGTH] -= n\n } else {\n this[BUFFER][0] = c.subarray(n) as RType\n chunk = c.subarray(0, n) as RType\n this[BUFFERLENGTH] -= n\n }\n }\n\n this.emit('data', chunk)\n\n if (!this[BUFFER].length && !this[EOF]) this.emit('drain')\n\n return chunk\n }\n\n /**\n * End the stream, optionally providing a final write.\n *\n * See {@link Minipass#write} for argument descriptions\n */\n end(cb?: () => void): this\n end(chunk: WType, cb?: () => void): this\n end(chunk: WType, encoding?: Minipass.Encoding, cb?: () => void): this\n end(\n chunk?: WType | (() => void),\n encoding?: Minipass.Encoding | (() => void),\n cb?: () => void\n ): this {\n if (typeof chunk === 'function') {\n cb = chunk as () => void\n chunk = undefined\n }\n if (typeof encoding === 'function') {\n cb = encoding\n encoding = 'utf8'\n }\n if (chunk !== undefined) this.write(chunk, encoding)\n if (cb) this.once('end', cb)\n this[EOF] = true\n this.writable = false\n\n // if we haven't written anything, then go ahead and emit,\n // even if we're not reading.\n // we'll re-emit if a new 'end' listener is added anyway.\n // This makes MP more suitable to write-only use cases.\n if (this[FLOWING] || !this[PAUSED]) this[MAYBE_EMIT_END]()\n return this\n }\n\n // don't let the internal resume be overwritten\n [RESUME]() {\n if (this[DESTROYED]) return\n\n if (!this[DATALISTENERS] && !this[PIPES].length) {\n this[DISCARDED] = true\n }\n this[PAUSED] = false\n this[FLOWING] = true\n this.emit('resume')\n if (this[BUFFER].length) this[FLUSH]()\n else if (this[EOF]) this[MAYBE_EMIT_END]()\n else this.emit('drain')\n }\n\n /**\n * Resume the stream if it is currently in a paused state\n *\n * If called when there are no pipe destinations or `data` event listeners,\n * this will place the stream in a \"discarded\" state, where all data will\n * be thrown away. The discarded state is removed if a pipe destination or\n * data handler is added, if pause() is called, or if any synchronous or\n * asynchronous iteration is started.\n */\n resume() {\n return this[RESUME]()\n }\n\n /**\n * Pause the stream\n */\n pause() {\n this[FLOWING] = false\n this[PAUSED] = true\n this[DISCARDED] = false\n }\n\n /**\n * true if the stream has been forcibly destroyed\n */\n get destroyed() {\n return this[DESTROYED]\n }\n\n /**\n * true if the stream is currently in a flowing state, meaning that\n * any writes will be immediately emitted.\n */\n get flowing() {\n return this[FLOWING]\n }\n\n /**\n * true if the stream is currently in a paused state\n */\n get paused() {\n return this[PAUSED]\n }\n\n [BUFFERPUSH](chunk: RType) {\n if (this[OBJECTMODE]) this[BUFFERLENGTH] += 1\n else this[BUFFERLENGTH] += (chunk as Minipass.BufferOrString).length\n this[BUFFER].push(chunk)\n }\n\n [BUFFERSHIFT](): RType {\n if (this[OBJECTMODE]) this[BUFFERLENGTH] -= 1\n else\n this[BUFFERLENGTH] -= (\n this[BUFFER][0] as Minipass.BufferOrString\n ).length\n return this[BUFFER].shift() as RType\n }\n\n [FLUSH](noDrain: boolean = false) {\n do {} while (\n this[FLUSHCHUNK](this[BUFFERSHIFT]()) &&\n this[BUFFER].length\n )\n\n if (!noDrain && !this[BUFFER].length && !this[EOF]) this.emit('drain')\n }\n\n [FLUSHCHUNK](chunk: RType) {\n this.emit('data', chunk)\n return this[FLOWING]\n }\n\n /**\n * Pipe all data emitted by this stream into the destination provided.\n *\n * Triggers the flow of data.\n */\n pipe<W extends Minipass.Writable>(dest: W, opts?: PipeOptions): W {\n if (this[DESTROYED]) return dest\n this[DISCARDED] = false\n\n const ended = this[EMITTED_END]\n opts = opts || {}\n if (dest === proc.stdout || dest === proc.stderr) opts.end = false\n else opts.end = opts.end !== false\n opts.proxyErrors = !!opts.proxyErrors\n\n // piping an ended stream ends immediately\n if (ended) {\n if (opts.end) dest.end()\n } else {\n // \"as\" here just ignores the WType, which pipes don't care about,\n // since they're only consuming from us, and writing to the dest\n this[PIPES].push(\n !opts.proxyErrors\n ? new Pipe<RType>(this as Minipass<RType>, dest, opts)\n : new PipeProxyErrors<RType>(this as Minipass<RType>, dest, opts)\n )\n if (this[ASYNC]) defer(() => this[RESUME]())\n else this[RESUME]()\n }\n\n return dest\n }\n\n /**\n * Fully unhook a piped destination stream.\n *\n * If the destination stream was the only consumer of this stream (ie,\n * there are no other piped destinations or `'data'` event listeners)\n * then the flow of data will stop until there is another consumer or\n * {@link Minipass#resume} is explicitly called.\n */\n unpipe<W extends Minipass.Writable>(dest: W) {\n const p = this[PIPES].find(p => p.dest === dest)\n if (p) {\n if (this[PIPES].length === 1) {\n if (this[FLOWING] && this[DATALISTENERS] === 0) {\n this[FLOWING] = false\n }\n this[PIPES] = []\n } else this[PIPES].splice(this[PIPES].indexOf(p), 1)\n p.unpipe()\n }\n }\n\n /**\n * Alias for {@link Minipass#on}\n */\n addListener<Event extends keyof Events>(\n ev: Event,\n handler: (...args: Events[Event]) => any\n ): this {\n return this.on(ev, handler)\n }\n\n /**\n * Mostly identical to `EventEmitter.on`, with the following\n * behavior differences to prevent data loss and unnecessary hangs:\n *\n * - Adding a 'data' event handler will trigger the flow of data\n *\n * - Adding a 'readable' event handler when there is data waiting to be read\n * will cause 'readable' to be emitted immediately.\n *\n * - Adding an 'endish' event handler ('end', 'finish', etc.) which has\n * already passed will cause the event to be emitted immediately and all\n * handlers removed.\n *\n * - Adding an 'error' event handler after an error has been emitted will\n * cause the event to be re-emitted immediately with the error previously\n * raised.\n */\n on<Event extends keyof Events>(\n ev: Event,\n handler: (...args: Events[Event]) => any\n ): this {\n const ret = super.on(\n ev as string | symbol,\n handler as (...a: any[]) => any\n )\n if (ev === 'data') {\n this[DISCARDED] = false\n this[DATALISTENERS]++\n if (!this[PIPES].length && !this[FLOWING]) {\n this[RESUME]()\n }\n } else if (ev === 'readable' && this[BUFFERLENGTH] !== 0) {\n super.emit('readable')\n } else if (isEndish(ev) && this[EMITTED_END]) {\n super.emit(ev)\n this.removeAllListeners(ev)\n } else if (ev === 'error' && this[EMITTED_ERROR]) {\n const h = handler as (...a: Events['error']) => any\n if (this[ASYNC]) defer(() => h.call(this, this[EMITTED_ERROR]))\n else h.call(this, this[EMITTED_ERROR])\n }\n return ret\n }\n\n /**\n * Alias for {@link Minipass#off}\n */\n removeListener<Event extends keyof Events>(\n ev: Event,\n handler: (...args: Events[Event]) => any\n ) {\n return this.off(ev, handler)\n }\n\n /**\n * Mostly identical to `EventEmitter.off`\n *\n * If a 'data' event handler is removed, and it was the last consumer\n * (ie, there are no pipe destinations or other 'data' event listeners),\n * then the flow of data will stop until there is another consumer or\n * {@link Minipass#resume} is explicitly called.\n */\n off<Event extends keyof Events>(\n ev: Event,\n handler: (...args: Events[Event]) => any\n ) {\n const ret = super.off(\n ev as string | symbol,\n handler as (...a: any[]) => any\n )\n // if we previously had listeners, and now we don't, and we don't\n // have any pipes, then stop the flow, unless it's been explicitly\n // put in a discarded flowing state via stream.resume().\n if (ev === 'data') {\n this[DATALISTENERS] = this.listeners('data').length\n if (\n this[DATALISTENERS] === 0 &&\n !this[DISCARDED] &&\n !this[PIPES].length\n ) {\n this[FLOWING] = false\n }\n }\n return ret\n }\n\n /**\n * Mostly identical to `EventEmitter.removeAllListeners`\n *\n * If all 'data' event handlers are removed, and they were the last consumer\n * (ie, there are no pipe destinations), then the flow of data will stop\n * until there is another consumer or {@link Minipass#resume} is explicitly\n * called.\n */\n removeAllListeners<Event extends keyof Events>(ev?: Event) {\n const ret = super.removeAllListeners(ev as string | symbol | undefined)\n if (ev === 'data' || ev === undefined) {\n this[DATALISTENERS] = 0\n if (!this[DISCARDED] && !this[PIPES].length) {\n this[FLOWING] = false\n }\n }\n return ret\n }\n\n /**\n * true if the 'end' event has been emitted\n */\n get emittedEnd() {\n return this[EMITTED_END]\n }\n\n [MAYBE_EMIT_END]() {\n if (\n !this[EMITTING_END] &&\n !this[EMITTED_END] &&\n !this[DESTROYED] &&\n this[BUFFER].length === 0 &&\n this[EOF]\n ) {\n this[EMITTING_END] = true\n this.emit('end')\n this.emit('prefinish')\n this.emit('finish')\n if (this[CLOSED]) this.emit('close')\n this[EMITTING_END] = false\n }\n }\n\n /**\n * Mostly identical to `EventEmitter.emit`, with the following\n * behavior differences to prevent data loss and unnecessary hangs:\n *\n * If the stream has been destroyed, and the event is something other\n * than 'close' or 'error', then `false` is returned and no handlers\n * are called.\n *\n * If the event is 'end', and has already been emitted, then the event\n * is ignored. If the stream is in a paused or non-flowing state, then\n * the event will be deferred until data flow resumes. If the stream is\n * async, then handlers will be called on the next tick rather than\n * immediately.\n *\n * If the event is 'close', and 'end' has not yet been emitted, then\n * the event will be deferred until after 'end' is emitted.\n *\n * If the event is 'error', and an AbortSignal was provided for the stream,\n * and there are no listeners, then the event is ignored, matching the\n * behavior of node core streams in the presense of an AbortSignal.\n *\n * If the event is 'finish' or 'prefinish', then all listeners will be\n * removed after emitting the event, to prevent double-firing.\n */\n emit<Event extends keyof Events>(\n ev: Event,\n ...args: Events[Event]\n ): boolean {\n const data = args[0]\n // error and close are only events allowed after calling destroy()\n if (\n ev !== 'error' &&\n ev !== 'close' &&\n ev !== DESTROYED &&\n this[DESTROYED]\n ) {\n return false\n } else if (ev === 'data') {\n return !this[OBJECTMODE] && !data\n ? false\n : this[ASYNC]\n ? (defer(() => this[EMITDATA](data as RType)), true)\n : this[EMITDATA](data as RType)\n } else if (ev === 'end') {\n return this[EMITEND]()\n } else if (ev === 'close') {\n this[CLOSED] = true\n // don't emit close before 'end' and 'finish'\n if (!this[EMITTED_END] && !this[DESTROYED]) return false\n const ret = super.emit('close')\n this.removeAllListeners('close')\n return ret\n } else if (ev === 'error') {\n this[EMITTED_ERROR] = data\n super.emit(ERROR, data)\n const ret =\n !this[SIGNAL] || this.listeners('error').length\n ? super.emit('error', data)\n : false\n this[MAYBE_EMIT_END]()\n return ret\n } else if (ev === 'resume') {\n const ret = super.emit('resume')\n this[MAYBE_EMIT_END]()\n return ret\n } else if (ev === 'finish' || ev === 'prefinish') {\n const ret = super.emit(ev)\n this.removeAllListeners(ev)\n return ret\n }\n\n // Some other unknown event\n const ret = super.emit(ev as string, ...args)\n this[MAYBE_EMIT_END]()\n return ret\n }\n\n [EMITDATA](data: RType) {\n for (const p of this[PIPES]) {\n if (p.dest.write(data as RType) === false) this.pause()\n }\n const ret = this[DISCARDED] ? false : super.emit('data', data)\n this[MAYBE_EMIT_END]()\n return ret\n }\n\n [EMITEND]() {\n if (this[EMITTED_END]) return false\n\n this[EMITTED_END] = true\n this.readable = false\n return this[ASYNC]\n ? (defer(() => this[EMITEND2]()), true)\n : this[EMITEND2]()\n }\n\n [EMITEND2]() {\n if (this[DECODER]) {\n const data = this[DECODER].end()\n if (data) {\n for (const p of this[PIPES]) {\n p.dest.write(data as RType)\n }\n if (!this[DISCARDED]) super.emit('data', data)\n }\n }\n\n for (const p of this[PIPES]) {\n p.end()\n }\n const ret = super.emit('end')\n this.removeAllListeners('end')\n return ret\n }\n\n /**\n * Return a Promise that resolves to an array of all emitted data once\n * the stream ends.\n */\n async collect(): Promise<RType[] & { dataLength: number }> {\n const buf: RType[] & { dataLength: number } = Object.assign([], {\n dataLength: 0,\n })\n if (!this[OBJECTMODE]) buf.dataLength = 0\n // set the promise first, in case an error is raised\n // by triggering the flow here.\n const p = this.promise()\n this.on('data', c => {\n buf.push(c)\n if (!this[OBJECTMODE])\n buf.dataLength += (c as Minipass.BufferOrString).length\n })\n await p\n return buf\n }\n\n /**\n * Return a Promise that resolves to the concatenation of all emitted data\n * once the stream ends.\n *\n * Not allowed on objectMode streams.\n */\n async concat(): Promise<RType> {\n if (this[OBJECTMODE]) {\n throw new Error('cannot concat in objectMode')\n }\n const buf = await this.collect()\n return (\n this[ENCODING]\n ? buf.join('')\n : Buffer.concat(buf as Buffer[], buf.dataLength)\n ) as RType\n }\n\n /**\n * Return a void Promise that resolves once the stream ends.\n */\n async promise(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n this.on(DESTROYED, () => reject(new Error('stream destroyed')))\n this.on('error', er => reject(er))\n this.on('end', () => resolve())\n })\n }\n\n /**\n * Asynchronous `for await of` iteration.\n *\n * This will continue emitting all chunks until the stream terminates.\n */\n [Symbol.asyncIterator](): AsyncGenerator<RType, void, void> {\n // set this up front, in case the consumer doesn't call next()\n // right away.\n this[DISCARDED] = false\n let stopped = false\n const stop = async (): Promise<IteratorReturnResult<void>> => {\n this.pause()\n stopped = true\n return { value: undefined, done: true }\n }\n const next = (): Promise<IteratorResult<RType, void>> => {\n if (stopped) return stop()\n const res = this.read()\n if (res !== null) return Promise.resolve({ done: false, value: res })\n\n if (this[EOF]) return stop()\n\n let resolve!: (res: IteratorResult<RType>) => void\n let reject!: (er: unknown) => void\n const onerr = (er: unknown) => {\n this.off('data', ondata)\n this.off('end', onend)\n this.off(DESTROYED, ondestroy)\n stop()\n reject(er)\n }\n const ondata = (value: RType) => {\n this.off('error', onerr)\n this.off('end', onend)\n this.off(DESTROYED, ondestroy)\n this.pause()\n resolve({ value, done: !!this[EOF] })\n }\n const onend = () => {\n this.off('error', onerr)\n this.off('data', ondata)\n this.off(DESTROYED, ondestroy)\n stop()\n resolve({ done: true, value: undefined })\n }\n const ondestroy = () => onerr(new Error('stream destroyed'))\n return new Promise<IteratorResult<RType>>((res, rej) => {\n reject = rej\n resolve = res\n this.once(DESTROYED, ondestroy)\n this.once('error', onerr)\n this.once('end', onend)\n this.once('data', ondata)\n })\n }\n\n return {\n next,\n throw: stop,\n return: stop,\n [Symbol.asyncIterator]() {\n return this\n },\n [Symbol.asyncDispose]: async () => {},\n }\n }\n\n /**\n * Synchronous `for of` iteration.\n *\n * The iteration will terminate when the internal buffer runs out, even\n * if the stream has not yet terminated.\n */\n [Symbol.iterator](): Generator<RType, void, void> {\n // set this up front, in case the consumer doesn't call next()\n // right away.\n this[DISCARDED] = false\n let stopped = false\n const stop = (): IteratorReturnResult<void> => {\n this.pause()\n this.off(ERROR, stop)\n this.off(DESTROYED, stop)\n this.off('end', stop)\n stopped = true\n return { done: true, value: undefined }\n }\n\n const next = (): IteratorResult<RType, void> => {\n if (stopped) return stop()\n const value = this.read()\n return value === null ? stop() : { done: false, value }\n }\n\n this.once('end', stop)\n this.once(ERROR, stop)\n this.once(DESTROYED, stop)\n\n return {\n next,\n throw: stop,\n return: stop,\n [Symbol.iterator]() {\n return this\n },\n [Symbol.dispose]: () => {},\n }\n }\n\n /**\n * Destroy a stream, preventing it from being used for any further purpose.\n *\n * If the stream has a `close()` method, then it will be called on\n * destruction.\n *\n * After destruction, any attempt to write data, read data, or emit most\n * events will be ignored.\n *\n * If an error argument is provided, then it will be emitted in an\n * 'error' event.\n */\n destroy(er?: unknown) {\n if (this[DESTROYED]) {\n if (er) this.emit('error', er)\n else this.emit(DESTROYED)\n return this\n }\n\n this[DESTROYED] = true\n this[DISCARDED] = true\n\n // throw away all buffered data, it's never coming out\n this[BUFFER].length = 0\n this[BUFFERLENGTH] = 0\n\n const wc = this as Minipass<RType, WType, Events> & {\n close?: () => void\n }\n if (typeof wc.close === 'function' && !this[CLOSED]) wc.close()\n\n if (er) this.emit('error', er)\n // if no error to emit, still reject pending promises\n else this.emit(DESTROYED)\n\n return this\n }\n\n /**\n * Alias for {@link isStream}\n *\n * Former export location, maintained for backwards compatibility.\n *\n * @deprecated\n */\n static get isStream() {\n return isStream\n }\n}\n","// this is just a very light wrapper around 2 arrays with an offset index\n\nimport { GLOBSTAR } from 'minimatch'\nexport type MMPattern = string | RegExp | typeof GLOBSTAR\n\n// an array of length >= 1\nexport type PatternList = [p: MMPattern, ...rest: MMPattern[]]\nexport type UNCPatternList = [\n p0: '',\n p1: '',\n p2: string,\n p3: string,\n ...rest: MMPattern[],\n]\nexport type DrivePatternList = [p0: string, ...rest: MMPattern[]]\nexport type AbsolutePatternList = [p0: '', ...rest: MMPattern[]]\nexport type GlobList = [p: string, ...rest: string[]]\n\nconst isPatternList = (pl: MMPattern[]): pl is PatternList =>\n pl.length >= 1\nconst isGlobList = (gl: string[]): gl is GlobList => gl.length >= 1\n\nconst customInspect = Symbol.for('nodejs.util.inspect.custom')\n\n/**\n * An immutable-ish view on an array of glob parts and their parsed\n * results\n */\nexport class Pattern {\n readonly #patternList: PatternList\n readonly #globList: GlobList\n readonly #index: number\n readonly length: number\n readonly #platform: NodeJS.Platform\n #rest?: Pattern | null\n #globString?: string\n #isDrive?: boolean\n #isUNC?: boolean\n #isAbsolute?: boolean\n #followGlobstar: boolean = true\n\n constructor(\n patternList: MMPattern[],\n globList: string[],\n index: number,\n platform: NodeJS.Platform,\n ) {\n if (!isPatternList(patternList)) {\n throw new TypeError('empty pattern list')\n }\n if (!isGlobList(globList)) {\n throw new TypeError('empty glob list')\n }\n if (globList.length !== patternList.length) {\n throw new TypeError('mismatched pattern list and glob list lengths')\n }\n this.length = patternList.length\n if (index < 0 || index >= this.length) {\n throw new TypeError('index out of range')\n }\n this.#patternList = patternList\n this.#globList = globList\n this.#index = index\n this.#platform = platform\n\n // normalize root entries of absolute patterns on initial creation.\n if (this.#index === 0) {\n // c: => ['c:/']\n // C:/ => ['C:/']\n // C:/x => ['C:/', 'x']\n // //host/share => ['//host/share/']\n // //host/share/ => ['//host/share/']\n // //host/share/x => ['//host/share/', 'x']\n // /etc => ['/', 'etc']\n // / => ['/']\n if (this.isUNC()) {\n // '' / '' / 'host' / 'share'\n const [p0, p1, p2, p3, ...prest] = this.#patternList\n const [g0, g1, g2, g3, ...grest] = this.#globList\n if (prest[0] === '') {\n // ends in /\n prest.shift()\n grest.shift()\n }\n const p = [p0, p1, p2, p3, ''].join('/')\n const g = [g0, g1, g2, g3, ''].join('/')\n this.#patternList = [p, ...prest]\n this.#globList = [g, ...grest]\n this.length = this.#patternList.length\n } else if (this.isDrive() || this.isAbsolute()) {\n const [p1, ...prest] = this.#patternList\n const [g1, ...grest] = this.#globList\n if (prest[0] === '') {\n // ends in /\n prest.shift()\n grest.shift()\n }\n const p = (p1 as string) + '/'\n const g = g1 + '/'\n this.#patternList = [p, ...prest]\n this.#globList = [g, ...grest]\n this.length = this.#patternList.length\n }\n }\n }\n\n [customInspect]() {\n return 'Pattern <' + this.#globList.slice(this.#index).join('/') + '>'\n }\n\n /**\n * The first entry in the parsed list of patterns\n */\n pattern(): MMPattern {\n return this.#patternList[this.#index] as MMPattern\n }\n\n /**\n * true of if pattern() returns a string\n */\n isString(): boolean {\n return typeof this.#patternList[this.#index] === 'string'\n }\n /**\n * true of if pattern() returns GLOBSTAR\n */\n isGlobstar(): boolean {\n return this.#patternList[this.#index] === GLOBSTAR\n }\n /**\n * true if pattern() returns a regexp\n */\n isRegExp(): boolean {\n return this.#patternList[this.#index] instanceof RegExp\n }\n\n /**\n * The /-joined set of glob parts that make up this pattern\n */\n globString(): string {\n return (this.#globString =\n this.#globString ||\n (this.#index === 0 ?\n this.isAbsolute() ?\n this.#globList[0] + this.#globList.slice(1).join('/')\n : this.#globList.join('/')\n : this.#globList.slice(this.#index).join('/')))\n }\n\n /**\n * true if there are more pattern parts after this one\n */\n hasMore(): boolean {\n return this.length > this.#index + 1\n }\n\n /**\n * The rest of the pattern after this part, or null if this is the end\n */\n rest(): Pattern | null {\n if (this.#rest !== undefined) return this.#rest\n if (!this.hasMore()) return (this.#rest = null)\n this.#rest = new Pattern(\n this.#patternList,\n this.#globList,\n this.#index + 1,\n this.#platform,\n )\n this.#rest.#isAbsolute = this.#isAbsolute\n this.#rest.#isUNC = this.#isUNC\n this.#rest.#isDrive = this.#isDrive\n return this.#rest\n }\n\n /**\n * true if the pattern represents a //unc/path/ on windows\n */\n isUNC(): boolean {\n const pl = this.#patternList\n return this.#isUNC !== undefined ?\n this.#isUNC\n : (this.#isUNC =\n this.#platform === 'win32' &&\n this.#index === 0 &&\n pl[0] === '' &&\n pl[1] === '' &&\n typeof pl[2] === 'string' &&\n !!pl[2] &&\n typeof pl[3] === 'string' &&\n !!pl[3])\n }\n\n // pattern like C:/...\n // split = ['C:', ...]\n // XXX: would be nice to handle patterns like `c:*` to test the cwd\n // in c: for *, but I don't know of a way to even figure out what that\n // cwd is without actually chdir'ing into it?\n /**\n * True if the pattern starts with a drive letter on Windows\n */\n isDrive(): boolean {\n const pl = this.#patternList\n return this.#isDrive !== undefined ?\n this.#isDrive\n : (this.#isDrive =\n this.#platform === 'win32' &&\n this.#index === 0 &&\n this.length > 1 &&\n typeof pl[0] === 'string' &&\n /^[a-z]:$/i.test(pl[0]))\n }\n\n // pattern = '/' or '/...' or '/x/...'\n // split = ['', ''] or ['', ...] or ['', 'x', ...]\n // Drive and UNC both considered absolute on windows\n /**\n * True if the pattern is rooted on an absolute path\n */\n isAbsolute(): boolean {\n const pl = this.#patternList\n return this.#isAbsolute !== undefined ?\n this.#isAbsolute\n : (this.#isAbsolute =\n (pl[0] === '' && pl.length > 1) ||\n this.isDrive() ||\n this.isUNC())\n }\n\n /**\n * consume the root of the pattern, and return it\n */\n root(): string {\n const p = this.#patternList[0]\n return (\n typeof p === 'string' && this.isAbsolute() && this.#index === 0\n ) ?\n p\n : ''\n }\n\n /**\n * Check to see if the current globstar pattern is allowed to follow\n * a symbolic link.\n */\n checkFollowGlobstar(): boolean {\n return !(\n this.#index === 0 ||\n !this.isGlobstar() ||\n !this.#followGlobstar\n )\n }\n\n /**\n * Mark that the current globstar pattern is following a symbolic link\n */\n markFollowGlobstar(): boolean {\n if (this.#index === 0 || !this.isGlobstar() || !this.#followGlobstar)\n return false\n this.#followGlobstar = false\n return true\n }\n}\n","// give it a pattern, and it'll be able to tell you if\n// a given path should be ignored.\n// Ignoring a path ignores its children if the pattern ends in /**\n// Ignores are always parsed in dot:true mode\n\nimport { Minimatch, MinimatchOptions } from 'minimatch'\nimport { Path } from 'path-scurry'\nimport { Pattern } from './pattern.js'\nimport { GlobWalkerOpts } from './walker.js'\n\nexport interface IgnoreLike {\n ignored?: (p: Path) => boolean\n childrenIgnored?: (p: Path) => boolean\n add?: (ignore: string) => void\n}\n\nconst defaultPlatform: NodeJS.Platform =\n (\n typeof process === 'object' &&\n process &&\n typeof process.platform === 'string'\n ) ?\n process.platform\n : 'linux'\n\n/**\n * Class used to process ignored patterns\n */\nexport class Ignore implements IgnoreLike {\n relative: Minimatch[]\n relativeChildren: Minimatch[]\n absolute: Minimatch[]\n absoluteChildren: Minimatch[]\n platform: NodeJS.Platform\n mmopts: MinimatchOptions\n\n constructor(\n ignored: string[],\n {\n nobrace,\n nocase,\n noext,\n noglobstar,\n platform = defaultPlatform,\n }: GlobWalkerOpts,\n ) {\n this.relative = []\n this.absolute = []\n this.relativeChildren = []\n this.absoluteChildren = []\n this.platform = platform\n this.mmopts = {\n dot: true,\n nobrace,\n nocase,\n noext,\n noglobstar,\n optimizationLevel: 2,\n platform,\n nocomment: true,\n nonegate: true,\n }\n for (const ign of ignored) this.add(ign)\n }\n\n add(ign: string) {\n // this is a little weird, but it gives us a clean set of optimized\n // minimatch matchers, without getting tripped up if one of them\n // ends in /** inside a brace section, and it's only inefficient at\n // the start of the walk, not along it.\n // It'd be nice if the Pattern class just had a .test() method, but\n // handling globstars is a bit of a pita, and that code already lives\n // in minimatch anyway.\n // Another way would be if maybe Minimatch could take its set/globParts\n // as an option, and then we could at least just use Pattern to test\n // for absolute-ness.\n // Yet another way, Minimatch could take an array of glob strings, and\n // a cwd option, and do the right thing.\n const mm = new Minimatch(ign, this.mmopts)\n for (let i = 0; i < mm.set.length; i++) {\n const parsed = mm.set[i]\n const globParts = mm.globParts[i]\n /* c8 ignore start */\n if (!parsed || !globParts) {\n throw new Error('invalid pattern object')\n }\n // strip off leading ./ portions\n // https://github.com/isaacs/node-glob/issues/570\n while (parsed[0] === '.' && globParts[0] === '.') {\n parsed.shift()\n globParts.shift()\n }\n /* c8 ignore stop */\n const p = new Pattern(parsed, globParts, 0, this.platform)\n const m = new Minimatch(p.globString(), this.mmopts)\n const children = globParts[globParts.length - 1] === '**'\n const absolute = p.isAbsolute()\n if (absolute) this.absolute.push(m)\n else this.relative.push(m)\n if (children) {\n if (absolute) this.absoluteChildren.push(m)\n else this.relativeChildren.push(m)\n }\n }\n }\n\n ignored(p: Path): boolean {\n const fullpath = p.fullpath()\n const fullpaths = `${fullpath}/`\n const relative = p.relative() || '.'\n const relatives = `${relative}/`\n for (const m of this.relative) {\n if (m.match(relative) || m.match(relatives)) return true\n }\n for (const m of this.absolute) {\n if (m.match(fullpath) || m.match(fullpaths)) return true\n }\n return false\n }\n\n childrenIgnored(p: Path): boolean {\n const fullpath = p.fullpath() + '/'\n const relative = (p.relative() || '.') + '/'\n for (const m of this.relativeChildren) {\n if (m.match(relative)) return true\n }\n for (const m of this.absoluteChildren) {\n if (m.match(fullpath)) return true\n }\n return false\n }\n}\n","// synchronous utility for filtering entries and calculating subwalks\n\nimport { GLOBSTAR, MMRegExp } from 'minimatch'\nimport { Path } from 'path-scurry'\nimport { MMPattern, Pattern } from './pattern.js'\nimport { GlobWalkerOpts } from './walker.js'\n\n/**\n * A cache of which patterns have been processed for a given Path\n */\nexport class HasWalkedCache {\n store: Map<string, Set<string>>\n constructor(store: Map<string, Set<string>> = new Map()) {\n this.store = store\n }\n copy() {\n return new HasWalkedCache(new Map(this.store))\n }\n hasWalked(target: Path, pattern: Pattern) {\n return this.store.get(target.fullpath())?.has(pattern.globString())\n }\n storeWalked(target: Path, pattern: Pattern) {\n const fullpath = target.fullpath()\n const cached = this.store.get(fullpath)\n if (cached) cached.add(pattern.globString())\n else this.store.set(fullpath, new Set([pattern.globString()]))\n }\n}\n\n/**\n * A record of which paths have been matched in a given walk step,\n * and whether they only are considered a match if they are a directory,\n * and whether their absolute or relative path should be returned.\n */\nexport class MatchRecord {\n store: Map<Path, number> = new Map()\n add(target: Path, absolute: boolean, ifDir: boolean) {\n const n = (absolute ? 2 : 0) | (ifDir ? 1 : 0)\n const current = this.store.get(target)\n this.store.set(target, current === undefined ? n : n & current)\n }\n // match, absolute, ifdir\n entries(): [Path, boolean, boolean][] {\n return [...this.store.entries()].map(([path, n]) => [\n path,\n !!(n & 2),\n !!(n & 1),\n ])\n }\n}\n\n/**\n * A collection of patterns that must be processed in a subsequent step\n * for a given path.\n */\nexport class SubWalks {\n store: Map<Path, Pattern[]> = new Map()\n add(target: Path, pattern: Pattern) {\n if (!target.canReaddir()) {\n return\n }\n const subs = this.store.get(target)\n if (subs) {\n if (!subs.find(p => p.globString() === pattern.globString())) {\n subs.push(pattern)\n }\n } else this.store.set(target, [pattern])\n }\n get(target: Path): Pattern[] {\n const subs = this.store.get(target)\n /* c8 ignore start */\n if (!subs) {\n throw new Error('attempting to walk unknown path')\n }\n /* c8 ignore stop */\n return subs\n }\n entries(): [Path, Pattern[]][] {\n return this.keys().map(k => [k, this.store.get(k) as Pattern[]])\n }\n keys(): Path[] {\n return [...this.store.keys()].filter(t => t.canReaddir())\n }\n}\n\n/**\n * The class that processes patterns for a given path.\n *\n * Handles child entry filtering, and determining whether a path's\n * directory contents must be read.\n */\nexport class Processor {\n hasWalkedCache: HasWalkedCache\n matches = new MatchRecord()\n subwalks = new SubWalks()\n patterns?: Pattern[]\n follow: boolean\n dot: boolean\n opts: GlobWalkerOpts\n\n constructor(opts: GlobWalkerOpts, hasWalkedCache?: HasWalkedCache) {\n this.opts = opts\n this.follow = !!opts.follow\n this.dot = !!opts.dot\n this.hasWalkedCache =\n hasWalkedCache ? hasWalkedCache.copy() : new HasWalkedCache()\n }\n\n processPatterns(target: Path, patterns: Pattern[]) {\n this.patterns = patterns\n const processingSet: [Path, Pattern][] = patterns.map(p => [target, p])\n\n // map of paths to the magic-starting subwalks they need to walk\n // first item in patterns is the filter\n\n for (let [t, pattern] of processingSet) {\n this.hasWalkedCache.storeWalked(t, pattern)\n\n const root = pattern.root()\n const absolute = pattern.isAbsolute() && this.opts.absolute !== false\n\n // start absolute patterns at root\n if (root) {\n t = t.resolve(\n root === '/' && this.opts.root !== undefined ?\n this.opts.root\n : root,\n )\n const rest = pattern.rest()\n if (!rest) {\n this.matches.add(t, true, false)\n continue\n } else {\n pattern = rest\n }\n }\n\n if (t.isENOENT()) continue\n\n let p: MMPattern\n let rest: Pattern | null\n let changed = false\n while (\n typeof (p = pattern.pattern()) === 'string' &&\n (rest = pattern.rest())\n ) {\n const c = t.resolve(p)\n t = c\n pattern = rest\n changed = true\n }\n p = pattern.pattern()\n rest = pattern.rest()\n if (changed) {\n if (this.hasWalkedCache.hasWalked(t, pattern)) continue\n this.hasWalkedCache.storeWalked(t, pattern)\n }\n\n // now we have either a final string for a known entry,\n // more strings for an unknown entry,\n // or a pattern starting with magic, mounted on t.\n if (typeof p === 'string') {\n // must not be final entry, otherwise we would have\n // concatenated it earlier.\n const ifDir = p === '..' || p === '' || p === '.'\n this.matches.add(t.resolve(p), absolute, ifDir)\n continue\n } else if (p === GLOBSTAR) {\n // if no rest, match and subwalk pattern\n // if rest, process rest and subwalk pattern\n // if it's a symlink, but we didn't get here by way of a\n // globstar match (meaning it's the first time THIS globstar\n // has traversed a symlink), then we follow it. Otherwise, stop.\n if (\n !t.isSymbolicLink() ||\n this.follow ||\n pattern.checkFollowGlobstar()\n ) {\n this.subwalks.add(t, pattern)\n }\n const rp = rest?.pattern()\n const rrest = rest?.rest()\n if (!rest || ((rp === '' || rp === '.') && !rrest)) {\n // only HAS to be a dir if it ends in **/ or **/.\n // but ending in ** will match files as well.\n this.matches.add(t, absolute, rp === '' || rp === '.')\n } else {\n if (rp === '..') {\n // this would mean you're matching **/.. at the fs root,\n // and no thanks, I'm not gonna test that specific case.\n /* c8 ignore start */\n const tp = t.parent || t\n /* c8 ignore stop */\n if (!rrest) this.matches.add(tp, absolute, true)\n else if (!this.hasWalkedCache.hasWalked(tp, rrest)) {\n this.subwalks.add(tp, rrest)\n }\n }\n }\n } else if (p instanceof RegExp) {\n this.subwalks.add(t, pattern)\n }\n }\n\n return this\n }\n\n subwalkTargets(): Path[] {\n return this.subwalks.keys()\n }\n\n child() {\n return new Processor(this.opts, this.hasWalkedCache)\n }\n\n // return a new Processor containing the subwalks for each\n // child entry, and a set of matches, and\n // a hasWalkedCache that's a copy of this one\n // then we're going to call\n filterEntries(parent: Path, entries: Path[]): Processor {\n const patterns = this.subwalks.get(parent)\n // put matches and entry walks into the results processor\n const results = this.child()\n for (const e of entries) {\n for (const pattern of patterns) {\n const absolute = pattern.isAbsolute()\n const p = pattern.pattern()\n const rest = pattern.rest()\n if (p === GLOBSTAR) {\n results.testGlobstar(e, pattern, rest, absolute)\n } else if (p instanceof RegExp) {\n results.testRegExp(e, p, rest, absolute)\n } else {\n results.testString(e, p, rest, absolute)\n }\n }\n }\n return results\n }\n\n testGlobstar(\n e: Path,\n pattern: Pattern,\n rest: Pattern | null,\n absolute: boolean,\n ) {\n if (this.dot || !e.name.startsWith('.')) {\n if (!pattern.hasMore()) {\n this.matches.add(e, absolute, false)\n }\n if (e.canReaddir()) {\n // if we're in follow mode or it's not a symlink, just keep\n // testing the same pattern. If there's more after the globstar,\n // then this symlink consumes the globstar. If not, then we can\n // follow at most ONE symlink along the way, so we mark it, which\n // also checks to ensure that it wasn't already marked.\n if (this.follow || !e.isSymbolicLink()) {\n this.subwalks.add(e, pattern)\n } else if (e.isSymbolicLink()) {\n if (rest && pattern.checkFollowGlobstar()) {\n this.subwalks.add(e, rest)\n } else if (pattern.markFollowGlobstar()) {\n this.subwalks.add(e, pattern)\n }\n }\n }\n }\n // if the NEXT thing matches this entry, then also add\n // the rest.\n if (rest) {\n const rp = rest.pattern()\n if (\n typeof rp === 'string' &&\n // dots and empty were handled already\n rp !== '..' &&\n rp !== '' &&\n rp !== '.'\n ) {\n this.testString(e, rp, rest.rest(), absolute)\n } else if (rp === '..') {\n /* c8 ignore start */\n const ep = e.parent || e\n /* c8 ignore stop */\n this.subwalks.add(ep, rest)\n } else if (rp instanceof RegExp) {\n this.testRegExp(e, rp, rest.rest(), absolute)\n }\n }\n }\n\n testRegExp(\n e: Path,\n p: MMRegExp,\n rest: Pattern | null,\n absolute: boolean,\n ) {\n if (!p.test(e.name)) return\n if (!rest) {\n this.matches.add(e, absolute, false)\n } else {\n this.subwalks.add(e, rest)\n }\n }\n\n testString(e: Path, p: string, rest: Pattern | null, absolute: boolean) {\n // should never happen?\n if (!e.isNamed(p)) return\n if (!rest) {\n this.matches.add(e, absolute, false)\n } else {\n this.subwalks.add(e, rest)\n }\n }\n}\n","/**\n * Single-use utility classes to provide functionality to the {@link Glob}\n * methods.\n *\n * @module\n */\nimport { Minipass } from 'minipass'\nimport { Path } from 'path-scurry'\nimport { Ignore, IgnoreLike } from './ignore.js'\n\n// XXX can we somehow make it so that it NEVER processes a given path more than\n// once, enough that the match set tracking is no longer needed? that'd speed\n// things up a lot. Or maybe bring back nounique, and skip it in that case?\n\n// a single minimatch set entry with 1 or more parts\nimport { Pattern } from './pattern.js'\nimport { Processor } from './processor.js'\n\nexport interface GlobWalkerOpts {\n absolute?: boolean\n allowWindowsEscape?: boolean\n cwd?: string | URL\n dot?: boolean\n dotRelative?: boolean\n follow?: boolean\n ignore?: string | string[] | IgnoreLike\n mark?: boolean\n matchBase?: boolean\n // Note: maxDepth here means \"maximum actual Path.depth()\",\n // not \"maximum depth beyond cwd\"\n maxDepth?: number\n nobrace?: boolean\n nocase?: boolean\n nodir?: boolean\n noext?: boolean\n noglobstar?: boolean\n platform?: NodeJS.Platform\n posix?: boolean\n realpath?: boolean\n root?: string\n stat?: boolean\n signal?: AbortSignal\n windowsPathsNoEscape?: boolean\n withFileTypes?: boolean\n includeChildMatches?: boolean\n}\n\nexport type GWOFileTypesTrue = GlobWalkerOpts & {\n withFileTypes: true\n}\nexport type GWOFileTypesFalse = GlobWalkerOpts & {\n withFileTypes: false\n}\nexport type GWOFileTypesUnset = GlobWalkerOpts & {\n withFileTypes?: undefined\n}\n\nexport type Result<O extends GlobWalkerOpts> =\n O extends GWOFileTypesTrue ? Path\n : O extends GWOFileTypesFalse ? string\n : O extends GWOFileTypesUnset ? string\n : Path | string\n\nexport type Matches<O extends GlobWalkerOpts> =\n O extends GWOFileTypesTrue ? Set<Path>\n : O extends GWOFileTypesFalse ? Set<string>\n : O extends GWOFileTypesUnset ? Set<string>\n : Set<Path | string>\n\nexport type MatchStream<O extends GlobWalkerOpts> = Minipass<\n Result<O>,\n Result<O>\n>\n\nconst makeIgnore = (\n ignore: string | string[] | IgnoreLike,\n opts: GlobWalkerOpts,\n): IgnoreLike =>\n typeof ignore === 'string' ? new Ignore([ignore], opts)\n : Array.isArray(ignore) ? new Ignore(ignore, opts)\n : ignore\n\n/**\n * basic walking utilities that all the glob walker types use\n */\nexport abstract class GlobUtil<O extends GlobWalkerOpts = GlobWalkerOpts> {\n path: Path\n patterns: Pattern[]\n opts: O\n seen: Set<Path> = new Set<Path>()\n paused: boolean = false\n aborted: boolean = false\n #onResume: (() => any)[] = []\n #ignore?: IgnoreLike\n #sep: '\\\\' | '/'\n signal?: AbortSignal\n maxDepth: number\n includeChildMatches: boolean\n\n constructor(patterns: Pattern[], path: Path, opts: O)\n constructor(patterns: Pattern[], path: Path, opts: O) {\n this.patterns = patterns\n this.path = path\n this.opts = opts\n this.#sep = !opts.posix && opts.platform === 'win32' ? '\\\\' : '/'\n this.includeChildMatches = opts.includeChildMatches !== false\n if (opts.ignore || !this.includeChildMatches) {\n this.#ignore = makeIgnore(opts.ignore ?? [], opts)\n if (\n !this.includeChildMatches &&\n typeof this.#ignore.add !== 'function'\n ) {\n const m = 'cannot ignore child matches, ignore lacks add() method.'\n throw new Error(m)\n }\n }\n // ignore, always set with maxDepth, but it's optional on the\n // GlobOptions type\n /* c8 ignore start */\n this.maxDepth = opts.maxDepth || Infinity\n /* c8 ignore stop */\n if (opts.signal) {\n this.signal = opts.signal\n this.signal.addEventListener('abort', () => {\n this.#onResume.length = 0\n })\n }\n }\n\n #ignored(path: Path): boolean {\n return this.seen.has(path) || !!this.#ignore?.ignored?.(path)\n }\n #childrenIgnored(path: Path): boolean {\n return !!this.#ignore?.childrenIgnored?.(path)\n }\n\n // backpressure mechanism\n pause() {\n this.paused = true\n }\n resume() {\n /* c8 ignore start */\n if (this.signal?.aborted) return\n /* c8 ignore stop */\n this.paused = false\n let fn: (() => any) | undefined = undefined\n while (!this.paused && (fn = this.#onResume.shift())) {\n fn()\n }\n }\n onResume(fn: () => any) {\n if (this.signal?.aborted) return\n /* c8 ignore start */\n if (!this.paused) {\n fn()\n } else {\n /* c8 ignore stop */\n this.#onResume.push(fn)\n }\n }\n\n // do the requisite realpath/stat checking, and return the path\n // to add or undefined to filter it out.\n async matchCheck(e: Path, ifDir: boolean): Promise<Path | undefined> {\n if (ifDir && this.opts.nodir) return undefined\n let rpc: Path | undefined\n if (this.opts.realpath) {\n rpc = e.realpathCached() || (await e.realpath())\n if (!rpc) return undefined\n e = rpc\n }\n const needStat = e.isUnknown() || this.opts.stat\n const s = needStat ? await e.lstat() : e\n if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) {\n const target = await s.realpath()\n /* c8 ignore start */\n if (target && (target.isUnknown() || this.opts.stat)) {\n await target.lstat()\n }\n /* c8 ignore stop */\n }\n return this.matchCheckTest(s, ifDir)\n }\n\n matchCheckTest(e: Path | undefined, ifDir: boolean): Path | undefined {\n return (\n e &&\n (this.maxDepth === Infinity || e.depth() <= this.maxDepth) &&\n (!ifDir || e.canReaddir()) &&\n (!this.opts.nodir || !e.isDirectory()) &&\n (!this.opts.nodir ||\n !this.opts.follow ||\n !e.isSymbolicLink() ||\n !e.realpathCached()?.isDirectory()) &&\n !this.#ignored(e)\n ) ?\n e\n : undefined\n }\n\n matchCheckSync(e: Path, ifDir: boolean): Path | undefined {\n if (ifDir && this.opts.nodir) return undefined\n let rpc: Path | undefined\n if (this.opts.realpath) {\n rpc = e.realpathCached() || e.realpathSync()\n if (!rpc) return undefined\n e = rpc\n }\n const needStat = e.isUnknown() || this.opts.stat\n const s = needStat ? e.lstatSync() : e\n if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) {\n const target = s.realpathSync()\n if (target && (target?.isUnknown() || this.opts.stat)) {\n target.lstatSync()\n }\n }\n return this.matchCheckTest(s, ifDir)\n }\n\n abstract matchEmit(p: Result<O>): void\n abstract matchEmit(p: string | Path): void\n\n matchFinish(e: Path, absolute: boolean) {\n if (this.#ignored(e)) return\n // we know we have an ignore if this is false, but TS doesn't\n if (!this.includeChildMatches && this.#ignore?.add) {\n const ign = `${e.relativePosix()}/**`\n this.#ignore.add(ign)\n }\n const abs =\n this.opts.absolute === undefined ? absolute : this.opts.absolute\n this.seen.add(e)\n const mark = this.opts.mark && e.isDirectory() ? this.#sep : ''\n // ok, we have what we need!\n if (this.opts.withFileTypes) {\n this.matchEmit(e)\n } else if (abs) {\n const abs = this.opts.posix ? e.fullpathPosix() : e.fullpath()\n this.matchEmit(abs + mark)\n } else {\n const rel = this.opts.posix ? e.relativePosix() : e.relative()\n const pre =\n this.opts.dotRelative && !rel.startsWith('..' + this.#sep) ?\n '.' + this.#sep\n : ''\n this.matchEmit(!rel ? '.' + mark : pre + rel + mark)\n }\n }\n\n async match(e: Path, absolute: boolean, ifDir: boolean): Promise<void> {\n const p = await this.matchCheck(e, ifDir)\n if (p) this.matchFinish(p, absolute)\n }\n\n matchSync(e: Path, absolute: boolean, ifDir: boolean): void {\n const p = this.matchCheckSync(e, ifDir)\n if (p) this.matchFinish(p, absolute)\n }\n\n walkCB(target: Path, patterns: Pattern[], cb: () => any) {\n /* c8 ignore start */\n if (this.signal?.aborted) cb()\n /* c8 ignore stop */\n this.walkCB2(target, patterns, new Processor(this.opts), cb)\n }\n\n walkCB2(\n target: Path,\n patterns: Pattern[],\n processor: Processor,\n cb: () => any,\n ) {\n if (this.#childrenIgnored(target)) return cb()\n if (this.signal?.aborted) cb()\n if (this.paused) {\n this.onResume(() => this.walkCB2(target, patterns, processor, cb))\n return\n }\n processor.processPatterns(target, patterns)\n\n // done processing. all of the above is sync, can be abstracted out.\n // subwalks is a map of paths to the entry filters they need\n // matches is a map of paths to [absolute, ifDir] tuples.\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n tasks++\n this.match(m, absolute, ifDir).then(() => next())\n }\n\n for (const t of processor.subwalkTargets()) {\n if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {\n continue\n }\n tasks++\n const childrenCached = t.readdirCached()\n if (t.calledReaddir())\n this.walkCB3(t, childrenCached, processor, next)\n else {\n t.readdirCB(\n (_, entries) => this.walkCB3(t, entries, processor, next),\n true,\n )\n }\n }\n\n next()\n }\n\n walkCB3(\n target: Path,\n entries: Path[],\n processor: Processor,\n cb: () => any,\n ) {\n processor = processor.filterEntries(target, entries)\n\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n tasks++\n this.match(m, absolute, ifDir).then(() => next())\n }\n for (const [target, patterns] of processor.subwalks.entries()) {\n tasks++\n this.walkCB2(target, patterns, processor.child(), next)\n }\n\n next()\n }\n\n walkCBSync(target: Path, patterns: Pattern[], cb: () => any) {\n /* c8 ignore start */\n if (this.signal?.aborted) cb()\n /* c8 ignore stop */\n this.walkCB2Sync(target, patterns, new Processor(this.opts), cb)\n }\n\n walkCB2Sync(\n target: Path,\n patterns: Pattern[],\n processor: Processor,\n cb: () => any,\n ) {\n if (this.#childrenIgnored(target)) return cb()\n if (this.signal?.aborted) cb()\n if (this.paused) {\n this.onResume(() =>\n this.walkCB2Sync(target, patterns, processor, cb),\n )\n return\n }\n processor.processPatterns(target, patterns)\n\n // done processing. all of the above is sync, can be abstracted out.\n // subwalks is a map of paths to the entry filters they need\n // matches is a map of paths to [absolute, ifDir] tuples.\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n this.matchSync(m, absolute, ifDir)\n }\n\n for (const t of processor.subwalkTargets()) {\n if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {\n continue\n }\n tasks++\n const children = t.readdirSync()\n this.walkCB3Sync(t, children, processor, next)\n }\n\n next()\n }\n\n walkCB3Sync(\n target: Path,\n entries: Path[],\n processor: Processor,\n cb: () => any,\n ) {\n processor = processor.filterEntries(target, entries)\n\n let tasks = 1\n const next = () => {\n if (--tasks === 0) cb()\n }\n\n for (const [m, absolute, ifDir] of processor.matches.entries()) {\n if (this.#ignored(m)) continue\n this.matchSync(m, absolute, ifDir)\n }\n for (const [target, patterns] of processor.subwalks.entries()) {\n tasks++\n this.walkCB2Sync(target, patterns, processor.child(), next)\n }\n\n next()\n }\n}\n\nexport class GlobWalker<\n O extends GlobWalkerOpts = GlobWalkerOpts,\n> extends GlobUtil<O> {\n matches = new Set<Result<O>>()\n\n constructor(patterns: Pattern[], path: Path, opts: O) {\n super(patterns, path, opts)\n }\n\n matchEmit(e: Result<O>): void {\n this.matches.add(e)\n }\n\n async walk(): Promise<Set<Result<O>>> {\n if (this.signal?.aborted) throw this.signal.reason\n if (this.path.isUnknown()) {\n await this.path.lstat()\n }\n await new Promise((res, rej) => {\n this.walkCB(this.path, this.patterns, () => {\n if (this.signal?.aborted) {\n rej(this.signal.reason)\n } else {\n res(this.matches)\n }\n })\n })\n return this.matches\n }\n\n walkSync(): Set<Result<O>> {\n if (this.signal?.aborted) throw this.signal.reason\n if (this.path.isUnknown()) {\n this.path.lstatSync()\n }\n // nothing for the callback to do, because this never pauses\n this.walkCBSync(this.path, this.patterns, () => {\n if (this.signal?.aborted) throw this.signal.reason\n })\n return this.matches\n }\n}\n\nexport class GlobStream<\n O extends GlobWalkerOpts = GlobWalkerOpts,\n> extends GlobUtil<O> {\n results: Minipass<Result<O>, Result<O>>\n\n constructor(patterns: Pattern[], path: Path, opts: O) {\n super(patterns, path, opts)\n this.results = new Minipass<Result<O>, Result<O>>({\n signal: this.signal,\n objectMode: true,\n })\n this.results.on('drain', () => this.resume())\n this.results.on('resume', () => this.resume())\n }\n\n matchEmit(e: Result<O>): void {\n this.results.write(e)\n if (!this.results.flowing) this.pause()\n }\n\n stream(): MatchStream<O> {\n const target = this.path\n if (target.isUnknown()) {\n target.lstat().then(() => {\n this.walkCB(target, this.patterns, () => this.results.end())\n })\n } else {\n this.walkCB(target, this.patterns, () => this.results.end())\n }\n return this.results\n }\n\n streamSync(): MatchStream<O> {\n if (this.path.isUnknown()) {\n this.path.lstatSync()\n }\n this.walkCBSync(this.path, this.patterns, () => this.results.end())\n return this.results\n }\n}\n","import { Minimatch } from 'minimatch'\nimport { GlobOptions } from './glob.js'\n\n/**\n * Return true if the patterns provided contain any magic glob characters,\n * given the options provided.\n *\n * Brace expansion is not considered \"magic\" unless the `magicalBraces` option\n * is set, as brace expansion just turns one string into an array of strings.\n * So a pattern like `'x{a,b}y'` would return `false`, because `'xay'` and\n * `'xby'` both do not contain any magic glob characters, and it's treated the\n * same as if you had called it on `['xay', 'xby']`. When `magicalBraces:true`\n * is in the options, brace expansion _is_ treated as a pattern having magic.\n */\nexport const hasMagic = (\n pattern: string | string[],\n options: GlobOptions = {},\n): boolean => {\n if (!Array.isArray(pattern)) {\n pattern = [pattern]\n }\n for (const p of pattern) {\n if (new Minimatch(p, options).hasMagic()) return true\n }\n return false\n}\n","import { escape, unescape } from 'minimatch'\nimport { Minipass } from 'minipass'\nimport { Path } from 'path-scurry'\nimport type {\n GlobOptions,\n GlobOptionsWithFileTypesFalse,\n GlobOptionsWithFileTypesTrue,\n GlobOptionsWithFileTypesUnset,\n} from './glob.js'\nimport { Glob } from './glob.js'\nimport { hasMagic } from './has-magic.js'\n\nexport { escape, unescape } from 'minimatch'\nexport type {\n FSOption,\n Path,\n WalkOptions,\n WalkOptionsWithFileTypesTrue,\n WalkOptionsWithFileTypesUnset,\n} from 'path-scurry'\nexport { Glob } from './glob.js'\nexport type {\n GlobOptions,\n GlobOptionsWithFileTypesFalse,\n GlobOptionsWithFileTypesTrue,\n GlobOptionsWithFileTypesUnset,\n} from './glob.js'\nexport { hasMagic } from './has-magic.js'\nexport { Ignore } from './ignore.js'\nexport type { IgnoreLike } from './ignore.js'\nexport type { MatchStream } from './walker.js'\n\n/**\n * Syncronous form of {@link globStream}. Will read all the matches as fast as\n * you consume them, even all in a single tick if you consume them immediately,\n * but will still respond to backpressure if they're not consumed immediately.\n */\nexport function globStreamSync(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesTrue,\n): Minipass<Path, Path>\nexport function globStreamSync(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesFalse,\n): Minipass<string, string>\nexport function globStreamSync(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesUnset,\n): Minipass<string, string>\nexport function globStreamSync(\n pattern: string | string[],\n options: GlobOptions,\n): Minipass<Path, Path> | Minipass<string, string>\nexport function globStreamSync(\n pattern: string | string[],\n options: GlobOptions = {},\n) {\n return new Glob(pattern, options).streamSync()\n}\n\n/**\n * Return a stream that emits all the strings or `Path` objects and\n * then emits `end` when completed.\n */\nexport function globStream(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesFalse,\n): Minipass<string, string>\nexport function globStream(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesTrue,\n): Minipass<Path, Path>\nexport function globStream(\n pattern: string | string[],\n options?: GlobOptionsWithFileTypesUnset | undefined,\n): Minipass<string, string>\nexport function globStream(\n pattern: string | string[],\n options: GlobOptions,\n): Minipass<Path, Path> | Minipass<string, string>\nexport function globStream(\n pattern: string | string[],\n options: GlobOptions = {},\n) {\n return new Glob(pattern, options).stream()\n}\n\n/**\n * Synchronous form of {@link glob}\n */\nexport function globSync(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesFalse,\n): string[]\nexport function globSync(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesTrue,\n): Path[]\nexport function globSync(\n pattern: string | string[],\n options?: GlobOptionsWithFileTypesUnset | undefined,\n): string[]\nexport function globSync(\n pattern: string | string[],\n options: GlobOptions,\n): Path[] | string[]\nexport function globSync(\n pattern: string | string[],\n options: GlobOptions = {},\n) {\n return new Glob(pattern, options).walkSync()\n}\n\n/**\n * Perform an asynchronous glob search for the pattern(s) specified. Returns\n * [Path](https://isaacs.github.io/path-scurry/classes/PathBase) objects if the\n * {@link withFileTypes} option is set to `true`. See {@link GlobOptions} for\n * full option descriptions.\n */\nasync function glob_(\n pattern: string | string[],\n options?: GlobOptionsWithFileTypesUnset | undefined,\n): Promise<string[]>\nasync function glob_(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesTrue,\n): Promise<Path[]>\nasync function glob_(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesFalse,\n): Promise<string[]>\nasync function glob_(\n pattern: string | string[],\n options: GlobOptions,\n): Promise<Path[] | string[]>\nasync function glob_(\n pattern: string | string[],\n options: GlobOptions = {},\n) {\n return new Glob(pattern, options).walk()\n}\n\n/**\n * Return a sync iterator for walking glob pattern matches.\n */\nexport function globIterateSync(\n pattern: string | string[],\n options?: GlobOptionsWithFileTypesUnset | undefined,\n): Generator<string, void, void>\nexport function globIterateSync(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesTrue,\n): Generator<Path, void, void>\nexport function globIterateSync(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesFalse,\n): Generator<string, void, void>\nexport function globIterateSync(\n pattern: string | string[],\n options: GlobOptions,\n): Generator<Path, void, void> | Generator<string, void, void>\nexport function globIterateSync(\n pattern: string | string[],\n options: GlobOptions = {},\n) {\n return new Glob(pattern, options).iterateSync()\n}\n\n/**\n * Return an async iterator for walking glob pattern matches.\n */\nexport function globIterate(\n pattern: string | string[],\n options?: GlobOptionsWithFileTypesUnset | undefined,\n): AsyncGenerator<string, void, void>\nexport function globIterate(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesTrue,\n): AsyncGenerator<Path, void, void>\nexport function globIterate(\n pattern: string | string[],\n options: GlobOptionsWithFileTypesFalse,\n): AsyncGenerator<string, void, void>\nexport function globIterate(\n pattern: string | string[],\n options: GlobOptions,\n): AsyncGenerator<Path, void, void> | AsyncGenerator<string, void, void>\nexport function globIterate(\n pattern: string | string[],\n options: GlobOptions = {},\n) {\n return new Glob(pattern, options).iterate()\n}\n\n// aliases: glob.sync.stream() glob.stream.sync() glob.sync() etc\nexport const streamSync = globStreamSync\nexport const stream = Object.assign(globStream, { sync: globStreamSync })\nexport const iterateSync = globIterateSync\nexport const iterate = Object.assign(globIterate, {\n sync: globIterateSync,\n})\nexport const sync = Object.assign(globSync, {\n stream: globStreamSync,\n iterate: globIterateSync,\n})\n\nexport const glob = Object.assign(glob_, {\n glob: glob_,\n globSync,\n sync,\n globStream,\n stream,\n globStreamSync,\n streamSync,\n globIterate,\n iterate,\n globIterateSync,\n iterateSync,\n Glob,\n hasMagic,\n escape,\n unescape,\n})\nglob.glob = glob\n","import * as fs from \"fs-extra\";\nimport * as path from \"path\";\nimport * as os from \"os\";\n\n// ─── Constants ────────────────────────────────────────────────────────────────\n\nexport const GLOBAL_CONSTITUTION_FILE = \".ai-spec-global-constitution.md\";\n\n/**\n * Search order for global constitution:\n * 1. Workspace root (for monorepo-level shared rules)\n * 2. User home directory (for personal cross-project rules)\n */\nconst SEARCH_ROOTS = [\n // Workspace root is injected at runtime — see loadGlobalConstitution()\n os.homedir(),\n];\n\n// ─── Load ─────────────────────────────────────────────────────────────────────\n\n/**\n * Search for a global constitution file.\n * @param extraRoots Additional directories to check first (e.g. workspace root).\n * Returns the content string, or null if not found anywhere.\n */\nexport async function loadGlobalConstitution(\n extraRoots: string[] = []\n): Promise<{ content: string; source: string } | null> {\n const roots = [...extraRoots, ...SEARCH_ROOTS];\n\n for (const root of roots) {\n const filePath = path.join(root, GLOBAL_CONSTITUTION_FILE);\n if (await fs.pathExists(filePath)) {\n const content = await fs.readFile(filePath, \"utf-8\");\n return { content, source: filePath };\n }\n }\n\n return null;\n}\n\n// ─── Merge ────────────────────────────────────────────────────────────────────\n\n/**\n * Merge global and project constitutions.\n *\n * Injection order (from lowest to highest priority):\n * 1. Global constitution — team/personal baseline rules\n * 2. Project constitution — project-specific overrides (wins on conflict)\n *\n * The merged text is what gets injected into Spec/codegen prompts.\n */\nexport function mergeConstitutions(\n globalContent: string,\n projectContent: string | undefined\n): string {\n const parts: string[] = [\n \"<!-- BEGIN GLOBAL CONSTITUTION (team baseline — lower priority) -->\",\n globalContent.trim(),\n \"<!-- END GLOBAL CONSTITUTION -->\",\n ];\n\n if (projectContent && projectContent.trim()) {\n parts.push(\n \"\",\n \"<!-- BEGIN PROJECT CONSTITUTION (project-specific — HIGHER priority, overrides global) -->\",\n projectContent.trim(),\n \"<!-- END PROJECT CONSTITUTION -->\"\n );\n }\n\n return parts.join(\"\\n\");\n}\n\n// ─── Save ─────────────────────────────────────────────────────────────────────\n\n/**\n * Write a global constitution to disk.\n * @param targetDir Directory to write to. Defaults to user home directory.\n */\nexport async function saveGlobalConstitution(\n content: string,\n targetDir: string = os.homedir()\n): Promise<string> {\n const filePath = path.join(targetDir, GLOBAL_CONSTITUTION_FILE);\n await fs.writeFile(filePath, content, \"utf-8\");\n return filePath;\n}\n","import { editor, confirm, select } from \"@inquirer/prompts\";\nimport chalk from \"chalk\";\nimport { AIProvider } from \"./spec-generator\";\nimport { computeDiff, printDiff, printDiffSummary } from \"./spec-versioning\";\n\nexport class SpecRefiner {\n constructor(private provider: AIProvider) {}\n\n async refineLoop(initialSpec: string): Promise<string> {\n let currentSpec = initialSpec;\n let round = 1;\n\n while (true) {\n console.log(chalk.cyan(`\\n─── Spec Review (Round ${round}) ─────────────────`));\n console.log(chalk.gray(\" Opening spec in editor. Save and close to continue.\"));\n\n // Open spec in editor for user to review/edit\n currentSpec = await editor({\n message: \"Review and edit the spec:\",\n default: currentSpec,\n postfix: \".md\",\n waitForUserInput: false,\n });\n\n console.log(chalk.green(\" ✔ Spec saved.\"));\n\n // Ask what to do next\n const action = await select({\n message: \"What would you like to do?\",\n choices: [\n { name: \"✅ Finalize — proceed to code generation\", value: \"finalize\" },\n { name: \"🤖 AI Polish — let AI improve clarity & completeness\", value: \"ai\" },\n { name: \"✏️ Edit again — continue editing\", value: \"edit\" },\n ],\n });\n\n if (action === \"finalize\") {\n break;\n }\n\n if (action === \"ai\") {\n console.log(chalk.blue(` AI (${this.provider.providerName}/${this.provider.modelName}) is polishing the spec...`));\n try {\n const improved = await this.provider.generate(\n `Review the following feature spec and improve it for clarity, completeness, and technical feasibility.\nKeep the same structure and language (Chinese). Fix any gaps in API design, missing error cases, or vague requirements.\nOutput ONLY the improved markdown spec, nothing else.\n\n${currentSpec}`,\n \"You are a Senior Tech Lead doing a spec review. Output only the improved Markdown.\"\n );\n\n console.log(chalk.yellow(\"\\n AI has suggested improvements. Opening diff in editor...\"));\n const acceptImproved = await confirm({\n message: \"Accept AI improvements? (opens editor so you can review first)\",\n default: true,\n });\n\n if (acceptImproved) {\n // Show diff before opening editor\n const diff = computeDiff(currentSpec, improved);\n console.log(chalk.cyan(\"\\n ── AI Changes ──────────────────────────────\"));\n printDiffSummary(diff, \"AI edits\");\n printDiff(diff);\n console.log(chalk.cyan(\" ────────────────────────────────────────────\\n\"));\n\n // Let user review AI's version before accepting\n currentSpec = await editor({\n message: \"Review AI-improved spec (edit if needed, then save):\",\n default: improved,\n postfix: \".md\",\n waitForUserInput: false,\n });\n console.log(chalk.green(\" ✔ AI-improved spec accepted.\"));\n } else {\n console.log(chalk.gray(\" AI improvements discarded. Keeping your version.\"));\n }\n } catch (err) {\n console.error(chalk.red(\" AI improvement failed:\"), err);\n console.log(chalk.gray(\" Continuing with current spec.\"));\n }\n }\n\n round++;\n }\n\n return currentSpec;\n }\n}\n","import chalk from \"chalk\";\nimport * as fs from \"fs-extra\";\nimport * as path from \"path\";\n\n// ─── Slug ────────────────────────────────────────────────────────────────────\n\n/**\n * Convert a free-form idea string into a safe, concise filename slug.\n * e.g. \"用户登录 with OAuth2\" → \"user-login-with-oauth2\"\n */\nexport function slugify(idea: string): string {\n return idea\n .toLowerCase()\n .replace(/[\\u4e00-\\u9fa5]+/g, (m) => pinyinFallback(m)) // CJK → strip or placeholder\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .slice(0, 48) || \"feature\";\n}\n\n/** Best-effort: just strip CJK and use surrounding ascii context. */\nfunction pinyinFallback(cjk: string): string {\n // We don't have a pinyin lib — use empty string so the surrounding ascii words still form a slug\n void cjk;\n return \"-\";\n}\n\n// ─── Version Detection ───────────────────────────────────────────────────────\n\nexport interface SpecVersion {\n filePath: string;\n version: number;\n content: string;\n}\n\n/**\n * Scan `specsDir` for files matching `feature-<slug>-v<N>.md` and return the latest.\n */\nexport async function findLatestVersion(\n specsDir: string,\n slug: string\n): Promise<SpecVersion | null> {\n if (!(await fs.pathExists(specsDir))) return null;\n\n const files = await fs.readdir(specsDir);\n const pattern = new RegExp(`^feature-${escapeRegex(slug)}-v(\\\\d+)\\\\.md$`);\n let latest: SpecVersion | null = null;\n\n for (const file of files) {\n const m = file.match(pattern);\n if (!m) continue;\n const version = parseInt(m[1], 10);\n if (!latest || version > latest.version) {\n const filePath = path.join(specsDir, file);\n const content = await fs.readFile(filePath, \"utf-8\");\n latest = { filePath, version, content };\n }\n }\n\n return latest;\n}\n\n/**\n * Return the path and version number for the NEXT spec file.\n * If `feature-<slug>-v1.md` exists, returns `feature-<slug>-v2.md`, etc.\n */\nexport async function nextVersionPath(\n specsDir: string,\n slug: string\n): Promise<{ filePath: string; version: number }> {\n const latest = await findLatestVersion(specsDir, slug);\n const version = latest ? latest.version + 1 : 1;\n const filePath = path.join(specsDir, `feature-${slug}-v${version}.md`);\n return { filePath, version };\n}\n\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n// ─── Diff Engine ─────────────────────────────────────────────────────────────\n\nexport interface DiffLine {\n type: \"added\" | \"removed\" | \"unchanged\";\n content: string;\n lineNo: number;\n}\n\nexport interface DiffResult {\n added: number;\n removed: number;\n unchanged: number;\n lines: DiffLine[];\n}\n\n/**\n * Line-level diff between two text strings.\n * Uses a simple LCS-based greedy diff (no external deps required).\n */\nexport function computeDiff(oldText: string, newText: string): DiffResult {\n const oldLines = oldText.split(\"\\n\");\n const newLines = newText.split(\"\\n\");\n\n // Build LCS table\n const m = oldLines.length;\n const n = newLines.length;\n\n // For large files, limit to avoid quadratic cost\n const MAX = 800;\n if (m > MAX || n > MAX) {\n return computeSimpleDiff(oldLines, newLines);\n }\n\n const dp: number[][] = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));\n for (let i = m - 1; i >= 0; i--) {\n for (let j = n - 1; j >= 0; j--) {\n if (oldLines[i] === newLines[j]) {\n dp[i][j] = dp[i + 1][j + 1] + 1;\n } else {\n dp[i][j] = Math.max(dp[i + 1][j], dp[i][j + 1]);\n }\n }\n }\n\n const lines: DiffLine[] = [];\n let i = 0, j = 0, lineNo = 1;\n\n while (i < m || j < n) {\n if (i < m && j < n && oldLines[i] === newLines[j]) {\n lines.push({ type: \"unchanged\", content: oldLines[i], lineNo: lineNo++ });\n i++; j++;\n } else if (j < n && (i >= m || dp[i + 1][j] <= dp[i][j + 1])) {\n lines.push({ type: \"added\", content: newLines[j], lineNo: lineNo++ });\n j++;\n } else {\n lines.push({ type: \"removed\", content: oldLines[i], lineNo: lineNo });\n i++;\n }\n }\n\n const added = lines.filter((l) => l.type === \"added\").length;\n const removed = lines.filter((l) => l.type === \"removed\").length;\n const unchanged = lines.filter((l) => l.type === \"unchanged\").length;\n\n return { added, removed, unchanged, lines };\n}\n\n/** Fast O(n) diff for large files — just mark all old as removed, all new as added. */\nfunction computeSimpleDiff(oldLines: string[], newLines: string[]): DiffResult {\n const lines: DiffLine[] = [\n ...oldLines.map((c, i) => ({ type: \"removed\" as const, content: c, lineNo: i + 1 })),\n ...newLines.map((c, i) => ({ type: \"added\" as const, content: c, lineNo: i + 1 })),\n ];\n return { added: newLines.length, removed: oldLines.length, unchanged: 0, lines };\n}\n\n// ─── Diff Printer ─────────────────────────────────────────────────────────────\n\nconst CONTEXT_LINES = 3; // unchanged lines to show around each hunk\n\n/**\n * Print a compact, colored unified-style diff to the console.\n * Only shows changed hunks with `CONTEXT_LINES` lines of context.\n */\nexport function printDiff(diff: DiffResult): void {\n if (diff.added === 0 && diff.removed === 0) {\n console.log(chalk.gray(\" (no changes)\"));\n return;\n }\n\n const { lines } = diff;\n const changedIdxs = new Set(\n lines\n .map((l, i) => (l.type !== \"unchanged\" ? i : -1))\n .filter((i) => i !== -1)\n );\n\n // Build set of indices to display (changed ± context)\n const toShow = new Set<number>();\n for (const idx of changedIdxs) {\n for (let k = Math.max(0, idx - CONTEXT_LINES); k <= Math.min(lines.length - 1, idx + CONTEXT_LINES); k++) {\n toShow.add(k);\n }\n }\n\n const sorted = [...toShow].sort((a, b) => a - b);\n let prevIdx = -2;\n\n for (const idx of sorted) {\n if (idx > prevIdx + 1 && prevIdx !== -2) {\n console.log(chalk.cyan(\" @@\"));\n }\n const l = lines[idx];\n if (l.type === \"added\") {\n console.log(chalk.green(` + ${l.content}`));\n } else if (l.type === \"removed\") {\n console.log(chalk.red(` - ${l.content}`));\n } else {\n console.log(chalk.gray(` ${l.content}`));\n }\n prevIdx = idx;\n }\n}\n\n/**\n * Print a one-line diff summary banner.\n */\nexport function printDiffSummary(diff: DiffResult, label: string): void {\n const parts: string[] = [];\n if (diff.added > 0) parts.push(chalk.green(`+${diff.added}`));\n if (diff.removed > 0) parts.push(chalk.red(`-${diff.removed}`));\n if (parts.length === 0) parts.push(chalk.gray(\"no change\"));\n console.log(chalk.bold(` ${label}: `) + parts.join(\" \") + chalk.gray(` lines`));\n}\n","import chalk from \"chalk\";\nimport { execSync } from \"child_process\";\nimport * as path from \"path\";\nimport * as fs from \"fs-extra\";\nimport { AIProvider } from \"./spec-generator\";\nimport { ProjectContext, isFrontendDeps } from \"./context-loader\";\nimport { getCodeGenSystemPrompt } from \"../prompts/codegen.prompt\";\nimport { SpecTask, loadTasksForSpec, updateTaskStatus } from \"./task-generator\";\nimport { loadDslForSpec, buildDslContextSection } from \"./dsl-extractor\";\nimport { loadFrontendContext, buildFrontendContextSection } from \"./frontend-context-loader\";\n\n// ─── Shared Config Helper ───────────────────────────────────────────────────\n\nfunction buildSharedConfigSection(context?: ProjectContext): string {\n if (!context?.sharedConfigFiles || context.sharedConfigFiles.length === 0) return \"\";\n\n const lines: string[] = [\n \"\\n=== Existing Shared Config Files (study these to learn project conventions) ===\",\n \"These are real files from the project. Use them as ground truth for naming, structure, and registration patterns.\",\n \"Modify them in-place when adding new entries. Do NOT create parallel files for the same purpose.\\n\",\n ];\n\n for (const f of context.sharedConfigFiles) {\n lines.push(`--- File: ${f.path} [${f.category}] ---`);\n lines.push(f.preview);\n lines.push(\"\");\n }\n return lines.join(\"\\n\") + \"\\n\";\n}\n\nfunction buildInstalledPackagesSection(context?: ProjectContext): string {\n if (!context?.dependencies || context.dependencies.length === 0) return \"\";\n return `\\n=== Installed Packages (ONLY use packages from this list — NEVER import anything not listed here) ===\\n${context.dependencies.join(\", \")}\\n`;\n}\n\n/**\n * Build a context section from files already written in this generation run.\n * Injected before generating files that may import from those paths (e.g., route files\n * importing from API files generated in an earlier task).\n */\nfunction buildGeneratedFilesSection(cache: Map<string, string>): string {\n if (cache.size === 0) return \"\";\n const lines = [\n \"\\n=== Files Already Generated in This Run — USE EXACT EXPORTS (do not rename or invent alternatives) ===\",\n ];\n for (const [filePath, content] of cache) {\n lines.push(`\\n--- ${filePath} ---`);\n // Include enough to see all export names (first 800 chars covers most API files)\n lines.push(content.slice(0, 800));\n if (content.length > 800) lines.push(\"... (truncated)\");\n }\n return lines.join(\"\\n\") + \"\\n\";\n}\n\nexport type CodeGenMode = \"claude-code\" | \"api\" | \"plan\";\n\n// ─── RTK Helper ────────────────────────────────────────────────────────────────\n// RTK (Rust Token Killer) saves tokens by filtering verbose CLI output.\n// When available, prefix 'claude' with 'rtk' for token savings.\n\nfunction isRtkAvailable(): boolean {\n try {\n execSync(\"rtk --version\", { stdio: \"ignore\" });\n return true;\n } catch {\n return false;\n }\n}\n\ninterface FileAction {\n file: string;\n action: \"create\" | \"modify\";\n description: string;\n}\n\n// ─── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction stripCodeFences(output: string): string {\n // Remove ```lang ... ``` wrapping if present\n const fenced = output.match(/^```(?:\\w+)?\\n([\\s\\S]*?)```\\s*$/m);\n if (fenced) return fenced[1].trim();\n const lines = output.split(\"\\n\");\n if (lines[0].startsWith(\"```\")) lines.shift();\n if (lines[lines.length - 1].trim() === \"```\") lines.pop();\n return lines.join(\"\\n\").trim();\n}\n\nfunction parseJsonArray(text: string): FileAction[] {\n // Try a JSON code fence first\n const fenced = text.match(/```(?:json)?\\n(\\[[\\s\\S]*?\\])\\n```/);\n const raw = fenced ? fenced[1] : text.match(/\\[[\\s\\S]*?\\]/)?.[0] ?? \"\";\n try {\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed)) return parsed as FileAction[];\n } catch {\n // fall through\n }\n return [];\n}\n\n// ─── CodeGenerator ────────────────────────────────────────────────────────────\n\nexport interface CodeGenOptions {\n /** Run claude non-interactively via -p flag (saves tokens, good for automation) */\n auto?: boolean;\n /** Resume from last checkpoint — skip tasks already marked as done */\n resume?: boolean;\n /** Path to the DSL JSON file — if provided, structured context is injected into prompts */\n dslFilePath?: string;\n /** Repo language type — selects the appropriate codegen system prompt */\n repoType?: string;\n}\n\nexport class CodeGenerator {\n constructor(\n private provider: AIProvider,\n private mode: CodeGenMode = \"claude-code\"\n ) {}\n\n /** Returns the list of file paths written to disk (useful for api-mode review). */\n async generateCode(\n specFilePath: string,\n workingDir: string,\n context?: ProjectContext,\n options: CodeGenOptions = {}\n ): Promise<string[]> {\n let effectiveMode = this.mode;\n\n if (effectiveMode === \"claude-code\" && this.provider.providerName !== \"claude\") {\n console.log(\n chalk.yellow(\n `\\n ⚠ codegen 模式 \"claude-code\" 需要 Claude,但当前 provider 是 \"${this.provider.providerName}\"。`\n )\n );\n console.log(chalk.gray(` 自动切换到 \"api\" 模式(使用 ${this.provider.providerName}/${this.provider.modelName} 生成代码)。`));\n console.log(chalk.gray(` 提示:运行 \\`ai-spec config --codegen api\\` 可固化此设置。\\n`));\n effectiveMode = \"api\";\n }\n\n switch (effectiveMode) {\n case \"claude-code\":\n await this.runClaudeCode(specFilePath, workingDir, options);\n return [];\n case \"api\":\n return this.runApiMode(specFilePath, workingDir, context, options);\n case \"plan\":\n await this.runPlanMode(specFilePath);\n return [];\n }\n }\n\n // ── Mode: claude-code ──────────────────────────────────────────────────────\n\n private isClaudeCLIAvailable(): boolean {\n try {\n execSync(\"claude --version\", { stdio: \"ignore\" });\n return true;\n } catch {\n return false;\n }\n }\n\n private async runClaudeCode(\n specFilePath: string,\n workingDir: string,\n options: CodeGenOptions = {}\n ): Promise<void> {\n console.log(chalk.blue(\"\\n─── Code Generation: Claude Code CLI ───────────\"));\n\n if (!this.isClaudeCLIAvailable()) {\n console.log(chalk.yellow(\" ⚠️ Claude Code CLI not found. Falling back to plan mode.\"));\n console.log(chalk.gray(\" Install: npm install -g @anthropic-ai/claude-code\"));\n return this.runPlanMode(specFilePath);\n }\n\n const rtkAvailable = isRtkAvailable();\n const claudeCmd = rtkAvailable ? \"rtk claude\" : \"claude\";\n if (rtkAvailable) {\n console.log(chalk.green(\" ✓ RTK detected — using rtk claude for token savings\"));\n }\n\n const tasks = await loadTasksForSpec(specFilePath);\n\n // ── Auto + Tasks: incremental task-by-task execution ────────────────────\n if (options.auto && tasks && tasks.length > 0) {\n return this.runClaudeCodeIncremental(tasks, specFilePath, workingDir, claudeCmd, options);\n }\n\n // ── Interactive or no tasks: single session ──────────────────────────────\n const taskSection = tasks && tasks.length > 0\n ? `\\n\\n== Implementation Tasks (implement in order) ==\\n${tasks\n .map((t) => `${t.id} [${t.layer}] ${t.title}\\n Files: ${t.filesToTouch.join(\", \")}\\n Criteria: ${t.acceptanceCriteria.join(\"; \")}`)\n .join(\"\\n\")}`\n : \"\";\n\n const promptContent = `Please read the spec file at ${specFilePath} and implement all the requirements. Create or modify files as necessary.${taskSection}`;\n const promptFile = path.join(workingDir, \".claude-prompt.txt\");\n await fs.writeFile(promptFile, promptContent, \"utf-8\");\n\n if (options.auto) {\n console.log(chalk.cyan(` 🤖 Auto mode: running claude -p (non-interactive)...`));\n console.log(chalk.gray(` Spec: ${specFilePath}`));\n try {\n execSync(`${claudeCmd} -p \"${promptContent.replace(/\"/g, '\\\\\"')}\"`, {\n cwd: workingDir,\n stdio: \"inherit\",\n });\n console.log(chalk.green(\"\\n ✔ Claude Code completed.\"));\n } catch {\n console.log(chalk.yellow(\"\\n Claude Code exited. Check output above.\"));\n }\n } else {\n console.log(chalk.cyan(` 🚀 Launching ${claudeCmd} in: ${workingDir}`));\n console.log(chalk.gray(` Spec: ${specFilePath}`));\n if (tasks) console.log(chalk.gray(` Tasks: ${tasks.length} tasks loaded into .claude-prompt.txt`));\n console.log(chalk.gray(\" Prompt pre-loaded in .claude-prompt.txt\\n\"));\n try {\n execSync(claudeCmd, { cwd: workingDir, stdio: \"inherit\" });\n console.log(chalk.green(\"\\n ✔ Claude Code session completed.\"));\n } catch {\n console.log(chalk.yellow(\"\\n Claude Code session ended. Continuing workflow.\"));\n }\n }\n }\n\n /**\n * Incremental claude-code execution: one `claude -p` call per task.\n * Tasks marked as \"done\" are skipped (resume support).\n * Progress is shown as a percentage bar.\n */\n private async runClaudeCodeIncremental(\n tasks: SpecTask[],\n specFilePath: string,\n workingDir: string,\n claudeCmd: string,\n options: CodeGenOptions\n ): Promise<void> {\n const pending = tasks.filter((t) => t.status !== \"done\");\n const doneCount = tasks.length - pending.length;\n\n if (options.resume && doneCount > 0) {\n console.log(chalk.cyan(`\\n Resuming: ${doneCount}/${tasks.length} tasks already done — skipping.`));\n } else {\n console.log(chalk.cyan(`\\n Incremental mode: ${tasks.length} tasks`));\n }\n\n let completed = doneCount;\n\n for (const task of tasks) {\n if (task.status === \"done\") {\n printTaskProgress(completed, tasks.length, task, \"skip\");\n continue;\n }\n\n printTaskProgress(completed, tasks.length, task, \"run\");\n\n const taskPrompt =\n `Task: ${task.id} — ${task.title}\\n` +\n `Layer: ${task.layer}\\n` +\n `Description: ${task.description}\\n` +\n `Files to touch: ${task.filesToTouch.join(\", \") || \"as needed\"}\\n` +\n `Acceptance criteria:\\n${task.acceptanceCriteria.map((c) => ` - ${c}`).join(\"\\n\")}\\n\\n` +\n `Full spec is at: ${specFilePath}\\n` +\n `Implement ONLY this task. Do not implement other tasks.`;\n\n let taskStatus: \"done\" | \"failed\" = \"done\";\n try {\n execSync(`${claudeCmd} -p \"${taskPrompt.replace(/\"/g, '\\\\\"').replace(/\\n/g, \"\\\\n\")}\"`, {\n cwd: workingDir,\n stdio: \"inherit\",\n });\n completed++;\n } catch {\n taskStatus = \"failed\";\n console.log(chalk.yellow(`\\n ⚠ Task ${task.id} exited with error — marked as failed. Re-run with --resume to retry.`));\n }\n\n await updateTaskStatus(specFilePath, task.id, taskStatus);\n }\n\n const successCount = tasks.filter((t) => t.status === \"done\").length + (completed - doneCount);\n console.log(\n chalk.bold(\n `\\n ${successCount === tasks.length ? chalk.green(\"✔\") : chalk.yellow(\"!\")} ` +\n `Incremental build: ${completed}/${tasks.length} tasks completed.`\n )\n );\n }\n\n // ── Mode: api ─────────────────────────────────────────────────────────────\n\n private async runApiMode(\n specFilePath: string,\n workingDir: string,\n context?: ProjectContext,\n options: CodeGenOptions = {}\n ): Promise<string[]> {\n console.log(\n chalk.blue(\n `\\n─── Code Generation: API (${this.provider.providerName}/${this.provider.modelName}) ───`\n )\n );\n\n const systemPrompt = getCodeGenSystemPrompt(options.repoType);\n if (options.repoType && options.repoType !== \"node-express\" && options.repoType !== \"node-koa\" && options.repoType !== \"unknown\") {\n console.log(chalk.gray(` Language: ${options.repoType} (using language-specific codegen prompt)`));\n }\n\n const spec = await fs.readFile(specFilePath, \"utf-8\");\n const constitutionSection = context?.constitution\n ? `\\n=== Project Constitution (MUST follow) ===\\n${context.constitution.slice(0, 2000)}\\n`\n : \"\";\n const contextSummary = context\n ? `Tech Stack: ${context.techStack.join(\", \")}\\nExisting files: ${context.fileStructure.slice(0, 20).join(\", \")}`\n : \"\";\n const installedPackagesSection = buildInstalledPackagesSection(context);\n const sharedConfigSection = buildSharedConfigSection(context);\n\n // Load DSL for structured context injection.\n const dsl = await loadDslForSpec(specFilePath);\n const dslSection = dsl ? `\\n${buildDslContextSection(dsl)}\\n` : \"\";\n if (dsl) {\n const cmpCount = dsl.components?.length ?? 0;\n const cmpSuffix = cmpCount > 0 ? `, ${cmpCount} components` : \"\";\n console.log(chalk.green(` ✓ DSL loaded — ${dsl.endpoints.length} endpoints, ${dsl.models.length} models${cmpSuffix}`));\n }\n\n // Load frontend context for frontend projects (React/Vue/Next/RN)\n const isFrontend = isFrontendDeps(context?.dependencies ?? []);\n let frontendSection = \"\";\n if (isFrontend) {\n const fctx = await loadFrontendContext(workingDir);\n frontendSection = `\\n${buildFrontendContextSection(fctx)}\\n`;\n console.log(chalk.gray(` Frontend context: ${fctx.framework} / ${fctx.httpClient} | hooks:${fctx.hookFiles.length} stores:${fctx.storeFiles.length}`));\n }\n\n // Use tasks if available for finer-grained generation with resume support\n const tasks = await loadTasksForSpec(specFilePath);\n if (tasks && tasks.length > 0) {\n return this.runApiModeWithTasks(spec, tasks, specFilePath, workingDir, constitutionSection + dslSection + installedPackagesSection, frontendSection, sharedConfigSection, options, systemPrompt, context);\n }\n\n // Fallback: plan-then-generate\n console.log(chalk.gray(\" [1/2] Planning implementation files...\"));\n\n const planPrompt = `Based on the feature spec and project context below, list ALL files that need to be created or modified.\n\nIMPORTANT: Check the \"Existing Shared Config Files\" section below FIRST. For any file listed there,\nuse action \"modify\" (never \"create\") even if you are only adding new entries.\nIMPORTANT: Check the \"Frontend Project Context\" section below. Extend existing hooks/services/stores — do NOT create new parallel utilities.\n\n=== Feature Spec ===\n${spec}\n${constitutionSection}${dslSection}${frontendSection}${installedPackagesSection}${sharedConfigSection}\n=== Project Context ===\n${contextSummary}\n\nOutput ONLY a valid JSON array:\n[\n {\"file\": \"src/controllers/userController.ts\", \"action\": \"create\", \"description\": \"Handle user CRUD operations\"},\n {\"file\": \"src/routes/client/index.ts\", \"action\": \"modify\", \"description\": \"Register new routes\"}\n]`;\n\n let filePlan: FileAction[] = [];\n try {\n const planResponse = await this.provider.generate(planPrompt, systemPrompt);\n filePlan = parseJsonArray(planResponse);\n } catch (err) {\n console.error(chalk.red(\" Failed to generate file plan:\"), err);\n }\n\n if (filePlan.length === 0) {\n console.log(chalk.yellow(\" Could not determine file plan. Falling back to plan mode.\"));\n await this.runPlanMode(specFilePath);\n return [];\n }\n\n console.log(chalk.cyan(`\\n Plan: ${filePlan.length} file(s) to process`));\n filePlan.forEach((item) => {\n const icon = item.action === \"create\" ? chalk.green(\"+\") : chalk.yellow(\"~\");\n console.log(` ${icon} ${item.file}: ${chalk.gray(item.description)}`);\n });\n\n const { files } = await this.generateFiles(filePlan, spec, workingDir, constitutionSection + dslSection + frontendSection + installedPackagesSection, systemPrompt);\n return files;\n }\n\n private async runApiModeWithTasks(\n spec: string,\n tasks: SpecTask[],\n specFilePath: string,\n workingDir: string,\n constitutionSection: string,\n frontendSection: string = \"\",\n sharedConfigSection: string = \"\",\n options: CodeGenOptions = {},\n systemPrompt: string = getCodeGenSystemPrompt(),\n context?: ProjectContext\n ): Promise<string[]> {\n const pendingTasks = tasks.filter((t) => t.status !== \"done\");\n const doneCount = tasks.length - pendingTasks.length;\n\n if (options.resume && doneCount > 0) {\n console.log(chalk.cyan(`\\n Task-based generation (resume): ${tasks.length} tasks (${chalk.green(doneCount + \" already done\")}, skipping)`));\n } else if (doneCount > 0) {\n console.log(chalk.cyan(`\\n Task-based generation: ${tasks.length} tasks (${chalk.green(doneCount + \" already done\")}, resuming from checkpoint)`));\n } else {\n console.log(chalk.cyan(`\\n Task-based generation: ${tasks.length} tasks`));\n }\n\n // Build a set of shared config file paths for quick lookup.\n // Shared config files (e.g. routes/index.ts) are excluded from per-task parallel\n // filePlans and instead updated once per layer after all parallel tasks complete.\n const sharedConfigPaths = new Set(\n (context?.sharedConfigFiles ?? []).map((f) => f.path)\n );\n\n // Track which shared config files have already been processed across layers\n const processedSharedConfigs = new Set<string>();\n\n // Cross-task generated file cache: stores content of API/service/store files\n // written in earlier layers so subsequent layers can see exact function names.\n const generatedFileCache = new Map<string, string>();\n\n let totalSuccess = 0;\n let totalFiles = 0;\n let completedTasks = doneCount;\n const allGeneratedFiles: string[] = [];\n\n // ── Show already-done tasks ───────────────────────────────────────────────\n for (const task of tasks) {\n if (task.status === \"done\") {\n printTaskProgress(completedTasks++, tasks.length, task, \"skip\");\n }\n }\n\n // ── Group pending tasks by layer in dependency order ──────────────────────\n const LAYER_ORDER = [\"data\", \"infra\", \"service\", \"api\", \"test\"];\n const layerGroups: Array<{ layer: string; tasks: SpecTask[] }> = [];\n\n for (const layer of LAYER_ORDER) {\n const group = pendingTasks.filter((t) => t.layer === layer);\n if (group.length > 0) layerGroups.push({ layer, tasks: group });\n }\n // Unknown layers run last, in their original order\n const unknownTasks = pendingTasks.filter((t) => !LAYER_ORDER.includes(t.layer));\n if (unknownTasks.length > 0) layerGroups.push({ layer: \"other\", tasks: unknownTasks });\n\n // ── Process each layer ────────────────────────────────────────────────────\n for (const { layer, tasks: layerTasks } of layerGroups) {\n const isParallel = layerTasks.length > 1;\n const layerIcon = LAYER_ICONS[layer] ?? \" \";\n\n if (isParallel) {\n const pct = Math.round((completedTasks / tasks.length) * 100);\n const barWidth = 20;\n const filled = Math.round((pct / 100) * barWidth);\n const bar = chalk.green(\"█\".repeat(filled)) + chalk.gray(\"░\".repeat(barWidth - filled));\n console.log(\n chalk.bold(`\\n [${bar}] ${pct}% ⚡ Layer [${layer}] ${layerIcon} — ${layerTasks.length} tasks running in parallel`)\n );\n } else {\n printTaskProgress(completedTasks, tasks.length, layerTasks[0], \"run\");\n }\n\n // Snapshot the cache before this layer starts — all parallel tasks in the same\n // layer see the same (pre-layer) cache, preventing partial-write races.\n const generatedFilesSection = buildGeneratedFilesSection(generatedFileCache);\n\n // ── Execute all tasks in this layer concurrently ──────────────────────\n interface TaskResult {\n task: SpecTask;\n files: string[];\n createdFiles: string[]; // only \"create\" actions — used for shared config batching\n success: number;\n total: number;\n impliesRegistration: boolean;\n }\n\n const taskResultPromises: Promise<TaskResult>[] = layerTasks.map(async (task) => {\n if (task.filesToTouch.length === 0) {\n if (!isParallel) console.log(chalk.gray(\" No files specified, skipping.\"));\n return { task, files: [], createdFiles: [], success: 0, total: 0, impliesRegistration: false };\n }\n\n // Resolve file actions — exclude shared config files (they're batched post-layer)\n const filePlan: FileAction[] = await Promise.all(\n task.filesToTouch\n .filter((f) => !sharedConfigPaths.has(f))\n .map(async (f) => {\n const exists = await fs.pathExists(path.join(workingDir, f));\n return {\n file: f,\n action: (exists ? \"modify\" : \"create\") as \"create\" | \"modify\",\n description: task.description,\n };\n })\n );\n\n // Determine if this task creates registerable artifacts (for post-layer shared config update)\n const createsNewFiles = filePlan.some((f) => f.action === \"create\");\n const taskText = `${task.title} ${task.description}`.toLowerCase();\n const impliesRegistration =\n createsNewFiles &&\n (taskText.includes(\"route\") ||\n taskText.includes(\"router\") ||\n taskText.includes(\"page\") ||\n taskText.includes(\"view\") ||\n taskText.includes(\"store\") ||\n taskText.includes(\"service\") ||\n taskText.includes(\"component\") ||\n taskText.includes(\"menu\") ||\n taskText.includes(\"navigation\") ||\n taskText.includes(\"模块\") ||\n taskText.includes(\"页面\") ||\n taskText.includes(\"路由\") ||\n taskText.includes(\"注册\"));\n\n if (filePlan.length === 0) {\n return { task, files: [], createdFiles: [], success: 0, total: 0, impliesRegistration };\n }\n\n const taskContext = `Task: ${task.id} — ${task.title}\\n${task.description}\\nAcceptance: ${task.acceptanceCriteria.join(\"; \")}`;\n const { success, total, files } = await this.generateFiles(\n filePlan,\n `${spec}\\n\\n=== Current Task ===\\n${taskContext}`,\n workingDir,\n constitutionSection + frontendSection + sharedConfigSection + generatedFilesSection,\n systemPrompt,\n isParallel ? task.id : undefined // prefix output lines with task ID in parallel mode\n );\n\n const createdFiles = filePlan\n .filter((fp) => fp.action === \"create\")\n .map((fp) => fp.file);\n\n return { task, files, createdFiles, success, total, impliesRegistration };\n });\n\n const layerResults = await Promise.all(taskResultPromises);\n\n // ── Aggregate layer results ───────────────────────────────────────────\n if (isParallel) {\n console.log(\"\"); // blank line after parallel output block\n }\n\n for (const result of layerResults) {\n totalSuccess += result.success;\n totalFiles += result.total;\n allGeneratedFiles.push(...result.files);\n\n if (isParallel) {\n const icon = result.success === result.total ? chalk.green(\"✔\") : chalk.yellow(\"!\");\n const layerTaskIcon = LAYER_ICONS[result.task.layer] ?? \" \";\n console.log(` ${icon} ${result.task.id} ${layerTaskIcon} ${result.task.title} — ${result.success}/${result.total} files`);\n }\n\n const taskStatus = result.success === result.total ? \"done\" : \"failed\";\n await updateTaskStatus(specFilePath, result.task.id, taskStatus);\n if (taskStatus === \"failed\") {\n console.log(chalk.yellow(` ⚠ ${result.task.id} marked as failed — re-run with --resume to retry`));\n }\n }\n\n completedTasks += layerTasks.length;\n\n // ── Update generatedFileCache with all files written in this layer ────\n // Done after all parallel tasks complete — ensures the next layer sees\n // the full set of exports from this layer, not a partial view.\n for (const result of layerResults) {\n for (const writtenFile of result.files) {\n if (/src[\\\\/](api[s]?|services?|stores?|composables?)[\\\\/]/.test(writtenFile)) {\n try {\n const content = await fs.readFile(path.join(workingDir, writtenFile), \"utf-8\");\n generatedFileCache.set(writtenFile, content);\n } catch { /* ignore */ }\n }\n }\n }\n\n // ── Post-layer: batch shared config update ────────────────────────────\n // If any task in this layer created registerable files, update shared config\n // files once using the complete list of new modules from the whole layer.\n const anyImpliesRegistration = layerResults.some((r) => r.impliesRegistration);\n if (anyImpliesRegistration && sharedConfigPaths.size > 0 && context?.sharedConfigFiles) {\n const allCreatedInLayer = layerResults.flatMap((r) => r.createdFiles);\n\n for (const sharedFile of context.sharedConfigFiles) {\n if (processedSharedConfigs.has(sharedFile.path)) continue;\n\n const newModuleNames = allCreatedInLayer\n .filter((f) => f !== sharedFile.path)\n .map((f) => path.basename(f).replace(/\\.[jt]sx?$/, \"\"));\n\n if (newModuleNames.length === 0 && sharedFile.category !== \"route-index\" && sharedFile.category !== \"store-index\") continue;\n\n let purpose = `Register/update ${sharedFile.category} entries for the new feature`;\n if ((sharedFile.category === \"route-index\" || sharedFile.category === \"store-index\") && newModuleNames.length > 0) {\n purpose = `Add to this file: import ${newModuleNames.join(\", \")} from their respective paths and register them in the export/default array. Do NOT remove any existing imports.`;\n }\n\n console.log(chalk.gray(`\\n + updating shared config: ${sharedFile.path} [${sharedFile.category}]`));\n const updatedGeneratedFilesSection = buildGeneratedFilesSection(generatedFileCache);\n await this.generateFiles(\n [{ file: sharedFile.path, action: \"modify\", description: purpose }],\n `${spec}\\n\\n=== Context ===\\nUpdating shared registration after layer [${layer}] completed. New modules: ${newModuleNames.join(\", \")}.`,\n workingDir,\n constitutionSection + frontendSection + sharedConfigSection + updatedGeneratedFilesSection,\n systemPrompt\n );\n\n processedSharedConfigs.add(sharedFile.path);\n }\n }\n }\n\n console.log(\n chalk.bold(\n `\\n ${totalSuccess === totalFiles ? chalk.green(\"✔\") : chalk.yellow(\"!\")} Task-based generation: ${totalSuccess}/${totalFiles} files written across ${pendingTasks.length} tasks.`\n )\n );\n\n return allGeneratedFiles;\n }\n\n private async generateFiles(\n filePlan: FileAction[],\n spec: string,\n workingDir: string,\n constitutionSection: string,\n systemPrompt: string = getCodeGenSystemPrompt(),\n /**\n * When set, output lines are prefixed with \"[taskLabel]\" (parallel mode).\n * Uses console.log (not process.stdout.write) to avoid line interleaving.\n */\n taskLabel?: string\n ): Promise<{ success: number; total: number; files: string[] }> {\n const prefix = taskLabel ? ` [${chalk.cyan(taskLabel)}] ` : \" \";\n if (!taskLabel) {\n console.log(chalk.gray(`\\n Generating ${filePlan.length} file(s)...`));\n }\n let successCount = 0;\n const writtenFiles: string[] = [];\n\n for (const item of filePlan) {\n const fullPath = path.join(workingDir, item.file);\n let existingContent = \"\";\n\n if (await fs.pathExists(fullPath)) {\n existingContent = await fs.readFile(fullPath, \"utf-8\");\n }\n\n const codePrompt = `Implement this file.\n\nFile: ${item.file}\nPurpose: ${item.description}\n\n=== Feature Spec ===\n${spec}\n${constitutionSection}\n=== ${existingContent ? \"Existing content (modify and return the complete file)\" : \"Create this file from scratch\"} ===\n${existingContent || \"Output only the complete file content.\"}`;\n\n try {\n const raw = await this.provider.generate(codePrompt, systemPrompt);\n const fileContent = stripCodeFences(raw);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, fileContent, \"utf-8\");\n console.log(`${prefix}${existingContent ? chalk.yellow(\"~\") : chalk.green(\"+\")} ${chalk.bold(item.file)} ${chalk.green(\"✔\")}`);\n successCount++;\n writtenFiles.push(item.file);\n } catch (err) {\n console.log(`${prefix}${chalk.red(\"✘\")} ${chalk.bold(item.file)} — ${chalk.red((err as Error).message)}`);\n }\n }\n\n if (!taskLabel) {\n console.log(\n chalk.bold(\n ` ${successCount === filePlan.length ? chalk.green(\"✔\") : chalk.yellow(\"!\")} ${successCount}/${filePlan.length} files written.`\n )\n );\n }\n return { success: successCount, total: filePlan.length, files: writtenFiles };\n }\n\n // ── Mode: plan ─────────────────────────────────────────────────────────────\n\n private async runPlanMode(specFilePath: string): Promise<void> {\n console.log(chalk.blue(\"\\n─── Implementation Plan ─────────────────────────\"));\n\n const spec = await fs.readFile(specFilePath, \"utf-8\");\n const plan = await this.provider.generate(\n `Create a detailed, step-by-step implementation plan for the following feature spec.\nBe specific about:\n- Which files to create or modify\n- Key functions/classes to implement\n- Data flow and integration points\n- Suggested implementation order\n\n${spec}`,\n \"You are a senior developer creating an actionable implementation guide.\"\n );\n\n console.log(chalk.cyan(\"\\n\") + plan);\n }\n}\n\n// ─── Progress Bar Helper ───────────────────────────────────────────────────────\n\nconst LAYER_ICONS: Record<string, string> = {\n data: \"💾\",\n infra: \"⚙️ \",\n service: \"🔧\",\n api: \"🌐\",\n test: \"🧪\",\n};\n\nexport function printTaskProgress(\n completed: number,\n total: number,\n task: SpecTask,\n mode: \"run\" | \"skip\"\n): void {\n const pct = total > 0 ? Math.round((completed / total) * 100) : 0;\n const barWidth = 20;\n const filled = Math.round((pct / 100) * barWidth);\n const bar = chalk.green(\"█\".repeat(filled)) + chalk.gray(\"░\".repeat(barWidth - filled));\n const icon = LAYER_ICONS[task.layer] ?? \" \";\n\n if (mode === \"skip\") {\n console.log(\n chalk.gray(`\\n [${bar}] ${pct}% ✓ ${task.id} ${icon} ${task.title} — already done`)\n );\n } else {\n console.log(\n chalk.bold(`\\n [${bar}] ${pct}% → ${task.id} ${icon} ${task.title}`)\n );\n }\n}\n","import chalk from \"chalk\";\nimport * as fs from \"fs-extra\";\nimport * as path from \"path\";\nimport { AIProvider } from \"./spec-generator\";\nimport { ProjectContext } from \"./context-loader\";\nimport { tasksSystemPrompt } from \"../prompts/tasks.prompt\";\n\n// ─── Verified File Inventory ──────────────────────────────────────────────────\n// Builds a structured, cross-referenced file list so the AI can pick\n// real paths for filesToTouch without hallucinating.\n\nfunction buildVerifiedInventory(context: ProjectContext): string {\n const lines: string[] = [\"=== Verified File Inventory (filesToTouch MUST use paths from here) ===\\n\"];\n\n // 1. Shared config files first — highest priority, most likely to be hallucinated\n if (context.sharedConfigFiles && context.sharedConfigFiles.length > 0) {\n lines.push(\"-- Shared Config Files (APPEND-ONLY — never create a parallel file) --\");\n for (const f of context.sharedConfigFiles) {\n lines.push(` [${f.category}] ${f.path}`);\n }\n lines.push(\"\");\n }\n\n // 2. API / route / controller files (often need new siblings)\n if (context.apiStructure.length > 0) {\n lines.push(\"-- API / Route / Controller Files --\");\n for (const f of context.apiStructure.slice(0, 20)) {\n lines.push(` ${f}`);\n }\n lines.push(\"\");\n }\n\n // 3. Full file tree (for deriving sibling naming patterns)\n if (context.fileStructure.length > 0) {\n lines.push(\"-- Project File Tree (first 60 entries) --\");\n for (const f of context.fileStructure.slice(0, 60)) {\n lines.push(` ${f}`);\n }\n lines.push(\"\");\n }\n\n lines.push(\n \"REMINDER: If a needed file does not appear above and is NOT a new file, verify its path.\\n\" +\n \"For i18n/locale files, constants, enums, or route indexes — use EXACTLY the path shown above.\\n\"\n );\n\n return lines.join(\"\\n\");\n}\n\nexport function buildTaskPrompt(spec: string, context?: ProjectContext): string {\n if (!context) return spec;\n\n const parts: string[] = [spec];\n\n if (context.constitution) {\n parts.push(`\\n=== Project Constitution (rules to follow) ===\\n${context.constitution.slice(0, 1500)}`);\n }\n\n if (context.techStack.length > 0) {\n parts.push(`\\n=== Tech Stack ===\\n${context.techStack.join(\", \")}`);\n }\n\n parts.push(\"\\n\" + buildVerifiedInventory(context));\n\n return parts.join(\"\\n\");\n}\n\nexport type TaskLayer = \"data\" | \"infra\" | \"service\" | \"api\" | \"test\";\nexport type TaskPriority = \"high\" | \"medium\" | \"low\";\nexport type TaskStatus = \"pending\" | \"done\" | \"failed\";\n\nexport interface SpecTask {\n id: string;\n title: string;\n description: string;\n layer: TaskLayer;\n filesToTouch: string[];\n acceptanceCriteria: string[];\n dependencies: string[];\n priority: TaskPriority;\n /** Runtime checkpoint — set by code generator, persisted to tasks file */\n status?: TaskStatus;\n}\n\nconst LAYER_ORDER: Record<TaskLayer, number> = {\n data: 0,\n infra: 1,\n service: 2,\n api: 3,\n test: 4,\n};\n\nexport class TaskGenerator {\n constructor(private provider: AIProvider) {}\n\n async generateTasks(spec: string, context?: ProjectContext): Promise<SpecTask[]> {\n const prompt = buildTaskPrompt(spec, context);\n const raw = await this.provider.generate(prompt, tasksSystemPrompt);\n return parseTasks(raw);\n }\n\n async saveTasks(tasks: SpecTask[], specFilePath: string): Promise<string> {\n const dir = path.dirname(specFilePath);\n const base = path.basename(specFilePath, \".md\");\n const tasksFile = path.join(dir, `${base}-tasks.json`);\n await fs.writeJson(tasksFile, tasks, { spaces: 2 });\n return tasksFile;\n }\n\n sortByLayer(tasks: SpecTask[]): SpecTask[] {\n return [...tasks].sort((a, b) => {\n const layerDiff = (LAYER_ORDER[a.layer] ?? 99) - (LAYER_ORDER[b.layer] ?? 99);\n if (layerDiff !== 0) return layerDiff;\n return a.id.localeCompare(b.id);\n });\n }\n}\n\nfunction parseTasks(raw: string): SpecTask[] {\n // Try JSON code fence first\n const fenced = raw.match(/```(?:json)?\\n(\\[[\\s\\S]*?\\])\\n```/);\n const jsonStr = fenced ? fenced[1] : (raw.match(/\\[[\\s\\S]*\\]/)?.[0] ?? \"\");\n try {\n const parsed = JSON.parse(jsonStr);\n if (Array.isArray(parsed)) return parsed as SpecTask[];\n } catch {\n // fall through\n }\n return [];\n}\n\nexport function printTasks(tasks: SpecTask[]): void {\n const layerColors: Record<TaskLayer, chalk.Chalk> = {\n data: chalk.magenta,\n infra: chalk.gray,\n service: chalk.blue,\n api: chalk.cyan,\n test: chalk.green,\n };\n\n console.log(chalk.bold(`\\n Tasks (${tasks.length}):`));\n for (const task of tasks) {\n const color = layerColors[task.layer] ?? chalk.white;\n const badge = color(`[${task.layer}]`);\n const prio = task.priority === \"high\" ? chalk.red(\"●\") : task.priority === \"medium\" ? chalk.yellow(\"●\") : chalk.gray(\"●\");\n console.log(` ${prio} ${chalk.bold(task.id)} ${badge} ${task.title}`);\n }\n}\n\nexport async function loadTasksForSpec(specFilePath: string): Promise<SpecTask[] | null> {\n const base = path.basename(specFilePath, \".md\");\n const dir = path.dirname(specFilePath);\n const tasksFile = path.join(dir, `${base}-tasks.json`);\n if (await fs.pathExists(tasksFile)) {\n return fs.readJson(tasksFile);\n }\n return null;\n}\n\n/** Persist a single task's status to the tasks JSON file (checkpoint). */\nexport async function updateTaskStatus(\n specFilePath: string,\n taskId: string,\n status: TaskStatus\n): Promise<void> {\n const tasks = await loadTasksForSpec(specFilePath);\n if (!tasks) return;\n const task = tasks.find((t) => t.id === taskId);\n if (!task) return;\n task.status = status;\n const base = path.basename(specFilePath, \".md\");\n const dir = path.dirname(specFilePath);\n await fs.writeJson(path.join(dir, `${base}-tasks.json`), tasks, { spaces: 2 });\n}\n","export const tasksSystemPrompt = `You are a Senior Software Architect. Decompose the provided Feature Spec into an ordered list of discrete implementation tasks.\n\nOutput ONLY a valid JSON array. No markdown fences, no explanation.\n\nEach task object must have these exact fields:\n{\n \"id\": \"TASK-001\", // sequential, zero-padded\n \"title\": \"...\", // short action phrase, e.g. \"Add UserFavorite Prisma model\"\n \"description\": \"...\", // 1-2 sentences, specific and actionable\n \"layer\": \"data|service|api|test|infra\", // implementation layer\n \"filesToTouch\": [\"...\"], // VERIFIED paths only — see rules below\n \"acceptanceCriteria\": [\"...\"], // verifiable completion conditions\n \"dependencies\": [\"TASK-001\"], // task ids that must complete first (empty array if none)\n \"priority\": \"high|medium|low\"\n}\n\nLayer ordering guidance (implement in this order):\n1. \"data\" — DB schema changes, migrations, seed data\n2. \"infra\" — config, env vars, external service setup\n3. \"service\" — business logic, service classes\n4. \"api\" — controllers, routes, middleware, validators\n5. \"test\" — unit tests, integration tests\n\nCRITICAL — filesToTouch Rules (hallucination prevention):\n- ONLY use paths that appear in the \"Verified File Inventory\" section of the prompt.\n- For NEW files that don't exist yet, derive the path by following the naming pattern of sibling files already in the inventory (same directory, same extension, same casing).\n- For EXISTING singleton files (i18n, constants, enums, route index), you MUST use the exact path from the inventory. NEVER invent a sub-path or nested variant.\n- If you are unsure of the exact path for a new file, leave it as \"TBD:<description>\" rather than guessing.\n- Cross-check: after writing all tasks, verify every path in filesToTouch exists in the inventory or is a logical new sibling. If it doesn't pass this check, fix it.\n\nOther rules:\n- acceptanceCriteria must be verifiable (not vague like \"works correctly\")\n- dependencies must reflect real implementation order\n- Aim for 4-10 tasks total — not too granular, not too coarse\n- Each task should be completable in one focused coding session`;\n","import chalk from \"chalk\";\nimport * as fs from \"fs-extra\";\nimport * as path from \"path\";\nimport { select } from \"@inquirer/prompts\";\nimport { AIProvider } from \"./spec-generator\";\nimport { SpecDSL } from \"./dsl-types\";\nimport { validateDsl, printValidationErrors, printDslSummary } from \"./dsl-validator\";\nimport {\n dslSystemPrompt,\n dslFrontendSystemPrompt,\n buildDslExtractionPrompt,\n buildDslRetryPrompt,\n} from \"../prompts/dsl.prompt\";\n\n// ─── DSL Sanitizer ───────────────────────────────────────────────────────────\n\n/**\n * Strips obviously-invalid entries from AI-generated DSL before validation,\n * preventing phantom errors from causing unnecessary retries.\n * - Removes endpoint.errors entries where code or description is empty/missing.\n */\nfunction sanitizeDsl(raw: unknown): unknown {\n if (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) return raw;\n const dsl = raw as Record<string, unknown>;\n\n if (Array.isArray(dsl[\"endpoints\"])) {\n dsl[\"endpoints\"] = (dsl[\"endpoints\"] as unknown[]).map((ep) => {\n if (ep === null || typeof ep !== \"object\" || Array.isArray(ep)) return ep;\n const endpoint = ep as Record<string, unknown>;\n if (Array.isArray(endpoint[\"errors\"])) {\n endpoint[\"errors\"] = (endpoint[\"errors\"] as unknown[]).filter((err) => {\n if (err === null || typeof err !== \"object\" || Array.isArray(err)) return false;\n const e = err as Record<string, unknown>;\n return typeof e[\"code\"] === \"string\" && e[\"code\"].trim().length > 0 &&\n typeof e[\"description\"] === \"string\" && e[\"description\"].trim().length > 0;\n });\n if ((endpoint[\"errors\"] as unknown[]).length === 0) {\n delete endpoint[\"errors\"];\n }\n }\n return endpoint;\n });\n }\n\n return dsl;\n}\n\n// ─── Constants ────────────────────────────────────────────────────────────────\n\n/** Maximum AI attempts (1 initial + up to this many retries). */\nconst MAX_RETRIES = 2;\n\n/** Maximum spec length passed to AI to avoid token/context blow-up. */\nconst MAX_SPEC_CHARS = 12_000;\n\n// ─── DSL file naming ──────────────────────────────────────────────────────────\n\nexport function dslFilePath(specFilePath: string): string {\n const dir = path.dirname(specFilePath);\n const base = path.basename(specFilePath, \".md\");\n return path.join(dir, `${base}.dsl.json`);\n}\n\n// ─── Parser ───────────────────────────────────────────────────────────────────\n\n/**\n * Parse JSON from raw AI output.\n * Handles two cases:\n * 1. Bare JSON object starting with `{`\n * 2. JSON wrapped in a ```json ... ``` fence (model sometimes ignores instructions)\n *\n * Does NOT use eval or Function() — only JSON.parse().\n */\nfunction parseJsonFromOutput(raw: string): unknown {\n const trimmed = raw.trim();\n\n // Case 1: bare JSON\n if (trimmed.startsWith(\"{\")) {\n return JSON.parse(trimmed);\n }\n\n // Case 2: fenced JSON — extract content between first ``` and last ```\n const fenceStart = trimmed.indexOf(\"```\");\n if (fenceStart !== -1) {\n const afterFence = trimmed.slice(fenceStart + 3);\n // Skip optional language tag (e.g. \"json\\n\")\n const newlinePos = afterFence.indexOf(\"\\n\");\n const jsonStart = newlinePos !== -1 ? newlinePos + 1 : 0;\n const fenceEnd = afterFence.lastIndexOf(\"```\");\n if (fenceEnd > jsonStart) {\n const jsonStr = afterFence.slice(jsonStart, fenceEnd).trim();\n return JSON.parse(jsonStr);\n }\n }\n\n // Case 3: try to find the first `{` and last `}` pair\n const objStart = trimmed.indexOf(\"{\");\n const objEnd = trimmed.lastIndexOf(\"}\");\n if (objStart !== -1 && objEnd > objStart) {\n return JSON.parse(trimmed.slice(objStart, objEnd + 1));\n }\n\n throw new SyntaxError(\"No JSON object found in AI output\");\n}\n\n// ─── DslExtractor ────────────────────────────────────────────────────────────\n\nexport class DslExtractor {\n constructor(private provider: AIProvider) {}\n\n /**\n * Extract and validate a SpecDSL from the given spec content.\n *\n * Flow:\n * attempt 1 → validate → if fail, show errors\n * attempt 2 (retry with errors) → validate → if fail, show errors\n * after MAX_RETRIES failures → prompt user: skip / abort\n *\n * Returns:\n * - SpecDSL if extraction succeeded\n * - null if user chose to skip (continue without DSL)\n * - throws if user chose to abort\n */\n async extract(\n specContent: string,\n opts: { auto?: boolean; isFrontend?: boolean } = {}\n ): Promise<SpecDSL | null> {\n // Truncate very long specs to avoid token issues\n const specForAI =\n specContent.length > MAX_SPEC_CHARS\n ? specContent.slice(0, MAX_SPEC_CHARS) + \"\\n... (truncated for DSL extraction)\"\n : specContent;\n\n let lastRawOutput = \"\";\n let lastErrors: Array<{ path: string; message: string }> = [];\n\n for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {\n const isRetry = attempt > 1;\n\n if (isRetry) {\n console.log(chalk.yellow(`\\n Retry ${attempt - 1}/${MAX_RETRIES - 1}: fixing validation errors...`));\n }\n\n // Build prompt — first attempt uses extraction prompt, retries include error feedback\n const activeSystemPrompt = opts.isFrontend ? dslFrontendSystemPrompt : dslSystemPrompt;\n const userPrompt = isRetry\n ? buildDslRetryPrompt(specForAI, lastRawOutput, lastErrors)\n : buildDslExtractionPrompt(specForAI, opts.isFrontend);\n\n // Call AI\n let rawOutput: string;\n try {\n rawOutput = await this.provider.generate(userPrompt, activeSystemPrompt);\n } catch (err) {\n console.log(chalk.red(` ✘ AI call failed: ${(err as Error).message}`));\n // Don't retry on network/API errors — ask user immediately\n return this.handleFailure(opts, \"AI call failed\");\n }\n\n lastRawOutput = rawOutput;\n\n // Parse JSON\n let parsed: unknown;\n try {\n parsed = parseJsonFromOutput(rawOutput);\n } catch (parseErr) {\n console.log(chalk.red(` ✘ Failed to parse JSON from AI output: ${(parseErr as Error).message}`));\n lastErrors = [{ path: \"root\", message: \"Output is not valid JSON — see raw output above\" }];\n\n if (attempt < MAX_RETRIES) continue;\n return this.handleFailure(opts, \"AI produced invalid JSON after retries\");\n }\n\n // Validate schema\n const result = validateDsl(sanitizeDsl(parsed));\n\n if (result.valid) {\n printDslSummary(result.dsl);\n return result.dsl;\n }\n\n // Validation failed\n printValidationErrors(result.errors);\n lastErrors = result.errors;\n\n if (attempt < MAX_RETRIES) {\n console.log(chalk.gray(` Will retry with error feedback...`));\n continue;\n }\n\n // All retries exhausted\n return this.handleFailure(opts, `DSL validation failed after ${MAX_RETRIES} attempts`);\n }\n\n // Should be unreachable, but TypeScript needs a return\n return this.handleFailure(opts, \"Unexpected extraction loop exit\");\n }\n\n /**\n * When extraction fails: in --auto mode skip silently; interactively ask user.\n * Returns null to skip, or throws to abort the pipeline.\n */\n private async handleFailure(\n opts: { auto?: boolean },\n reason: string\n ): Promise<null> {\n console.log(chalk.yellow(`\\n ⚠ DSL extraction failed: ${reason}`));\n\n if (opts.auto) {\n console.log(chalk.gray(\" --auto mode: skipping DSL, continuing without it.\"));\n return null;\n }\n\n const action = await select({\n message: \"DSL extraction failed. What would you like to do?\",\n choices: [\n { name: \"⏭ Skip DSL — continue to code generation without it\", value: \"skip\" },\n { name: \"❌ Abort — stop the pipeline\", value: \"abort\" },\n ],\n });\n\n if (action === \"abort\") {\n console.log(chalk.red(\" Pipeline aborted by user.\"));\n process.exit(1);\n }\n\n console.log(chalk.gray(\" Continuing without DSL.\"));\n return null;\n }\n\n // ─── Save ────────────────────────────────────────────────────────────────────\n\n async saveDsl(dsl: SpecDSL, specFilePath: string): Promise<string> {\n const outPath = dslFilePath(specFilePath);\n await fs.writeJson(outPath, dsl, { spaces: 2 });\n return outPath;\n }\n}\n\n// ─── DSL summary for codegen prompts ──────────────────────────────────────────\n\n/**\n * Build a compact, token-efficient DSL summary to inject into codegen prompts.\n * Avoids dumping the full DSL JSON (which would be large) — only extracts\n * the most actionable parts: endpoint signatures and model field lists.\n */\nexport function buildDslContextSection(dsl: SpecDSL): string {\n const lines: string[] = [\n \"=== Feature DSL (structured summary — use for implementation guidance) ===\",\n ];\n\n // Models\n if (dsl.models.length > 0) {\n lines.push(\"\\n-- Data Models --\");\n for (const model of dsl.models) {\n lines.push(`${model.name}:`);\n for (const field of model.fields) {\n const flags: string[] = [];\n if (field.required) flags.push(\"required\");\n if (field.unique) flags.push(\"unique\");\n lines.push(` ${field.name}: ${field.type}${flags.length ? ` (${flags.join(\", \")})` : \"\"}`);\n }\n if (model.relations && model.relations.length > 0) {\n lines.push(` relations: ${model.relations.join(\"; \")}`);\n }\n }\n }\n\n // Endpoints\n if (dsl.endpoints.length > 0) {\n lines.push(\"\\n-- API Endpoints --\");\n for (const ep of dsl.endpoints) {\n lines.push(`${ep.id}: ${ep.method} ${ep.path} [auth: ${ep.auth}] → ${ep.successStatus}`);\n lines.push(` ${ep.description}`);\n if (ep.request?.body) {\n const fields = Object.entries(ep.request.body)\n .map(([k, v]) => `${k}: ${v}`)\n .join(\", \");\n lines.push(` body: { ${fields} }`);\n }\n if (ep.errors && ep.errors.length > 0) {\n lines.push(` errors: ${ep.errors.map((e) => `${e.status} ${e.code}`).join(\", \")}`);\n }\n }\n }\n\n // Behaviors\n if (dsl.behaviors.length > 0) {\n lines.push(\"\\n-- Business Behaviors --\");\n for (const b of dsl.behaviors) {\n lines.push(`${b.id}: ${b.description}`);\n if (b.trigger) lines.push(` trigger: ${b.trigger}`);\n if (b.constraints && b.constraints.length > 0) {\n lines.push(` rules: ${b.constraints.join(\"; \")}`);\n }\n }\n }\n\n // Components (frontend only)\n if (dsl.components && dsl.components.length > 0) {\n lines.push(\"\\n-- UI Components --\");\n for (const cmp of dsl.components) {\n lines.push(`${cmp.id}: ${cmp.name} — ${cmp.description}`);\n if (cmp.props.length > 0) {\n lines.push(` props: ${cmp.props.map((p) => `${p.name}${p.required ? \"\" : \"?\"}:${p.type}`).join(\", \")}`);\n }\n if (cmp.events.length > 0) {\n lines.push(` events: ${cmp.events.map((e) => `${e.name}(${e.payload ?? \"\"})`).join(\", \")}`);\n }\n if (Object.keys(cmp.state).length > 0) {\n lines.push(` state: ${Object.entries(cmp.state).map(([k, v]) => `${k}:${v}`).join(\", \")}`);\n }\n if (cmp.apiCalls.length > 0) {\n lines.push(` calls: ${cmp.apiCalls.join(\", \")}`);\n }\n }\n }\n\n lines.push(\"\\n=== End of DSL ===\");\n return lines.join(\"\\n\");\n}\n\n/**\n * Load DSL from disk if available alongside a spec file.\n * Returns null (never throws) if file is missing or corrupt.\n */\nexport async function loadDslForSpec(specFilePath: string): Promise<SpecDSL | null> {\n const dslPath = dslFilePath(specFilePath);\n if (!(await fs.pathExists(dslPath))) return null;\n try {\n const raw = await fs.readJson(dslPath);\n const result = validateDsl(raw);\n return result.valid ? result.dsl : null;\n } catch {\n return null;\n }\n}\n","/**\n * DSL Schema Validator — no external dependencies, no recursion.\n *\n * Safety design:\n * - All loops are bounded by finite array lengths.\n * - No recursive function calls.\n * - Collects ALL errors in one pass instead of throwing on first failure.\n * - Never mutates the input.\n */\n\nimport chalk from \"chalk\";\nimport {\n SpecDSL,\n DslValidationError,\n DslValidationResult,\n HttpMethod,\n} from \"./dsl-types\";\n\nconst VALID_METHODS: HttpMethod[] = [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\"];\nconst MAX_MODELS = 50;\nconst MAX_FIELDS_PER_MODEL = 100;\nconst MAX_ENDPOINTS = 100;\nconst MAX_BEHAVIORS = 50;\nconst MAX_ERRORS_PER_ENDPOINT = 20;\n\n// ─── Main entry point ─────────────────────────────────────────────────────────\n\nexport function validateDsl(raw: unknown): DslValidationResult {\n const errors: DslValidationError[] = [];\n\n // Guard: must be a plain object\n if (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) {\n return {\n valid: false,\n errors: [{ path: \"root\", message: \"DSL must be a JSON object, got: \" + typeLabel(raw) }],\n };\n }\n\n const obj = raw as Record<string, unknown>;\n\n // ── version ────────────────────────────────────────────────────────────────\n if (obj[\"version\"] !== \"1.0\") {\n errors.push({\n path: \"version\",\n message: `Must be \"1.0\", got: ${JSON.stringify(obj[\"version\"])}`,\n });\n }\n\n // ── feature ────────────────────────────────────────────────────────────────\n validateFeature(obj[\"feature\"], \"feature\", errors);\n\n // ── models ─────────────────────────────────────────────────────────────────\n if (!Array.isArray(obj[\"models\"])) {\n errors.push({ path: \"models\", message: `Must be an array, got: ${typeLabel(obj[\"models\"])}` });\n } else {\n const models = obj[\"models\"] as unknown[];\n if (models.length > MAX_MODELS) {\n errors.push({ path: \"models\", message: `Too many models (${models.length} > ${MAX_MODELS})` });\n }\n // Bounded loop — no recursion\n for (let i = 0; i < Math.min(models.length, MAX_MODELS); i++) {\n validateModel(models[i], `models[${i}]`, errors);\n }\n }\n\n // ── endpoints ──────────────────────────────────────────────────────────────\n if (!Array.isArray(obj[\"endpoints\"])) {\n errors.push({ path: \"endpoints\", message: `Must be an array, got: ${typeLabel(obj[\"endpoints\"])}` });\n } else {\n const eps = obj[\"endpoints\"] as unknown[];\n if (eps.length > MAX_ENDPOINTS) {\n errors.push({ path: \"endpoints\", message: `Too many endpoints (${eps.length} > ${MAX_ENDPOINTS})` });\n }\n for (let i = 0; i < Math.min(eps.length, MAX_ENDPOINTS); i++) {\n validateEndpoint(eps[i], `endpoints[${i}]`, errors);\n }\n }\n\n // ── behaviors (optional, but must be array if present) ────────────────────\n if (obj[\"behaviors\"] !== undefined) {\n if (!Array.isArray(obj[\"behaviors\"])) {\n errors.push({ path: \"behaviors\", message: `Must be an array if present, got: ${typeLabel(obj[\"behaviors\"])}` });\n } else {\n const behaviors = obj[\"behaviors\"] as unknown[];\n if (behaviors.length > MAX_BEHAVIORS) {\n errors.push({ path: \"behaviors\", message: `Too many behaviors (${behaviors.length} > ${MAX_BEHAVIORS})` });\n }\n for (let i = 0; i < Math.min(behaviors.length, MAX_BEHAVIORS); i++) {\n validateBehavior(behaviors[i], `behaviors[${i}]`, errors);\n }\n }\n }\n\n // ── components (optional, frontend only) ──────────────────────────────────\n if (obj[\"components\"] !== undefined) {\n if (!Array.isArray(obj[\"components\"])) {\n errors.push({ path: \"components\", message: `Must be an array if present, got: ${typeLabel(obj[\"components\"])}` });\n } else {\n const components = obj[\"components\"] as unknown[];\n for (let i = 0; i < Math.min(components.length, 50); i++) {\n validateComponent(components[i], `components[${i}]`, errors);\n }\n }\n }\n\n if (errors.length > 0) {\n return { valid: false, errors };\n }\n\n return { valid: true, dsl: raw as SpecDSL };\n}\n\n// ─── Section validators (all iterative, no recursion) ────────────────────────\n\nfunction validateFeature(\n raw: unknown,\n path: string,\n errors: DslValidationError[]\n): void {\n if (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) {\n errors.push({ path, message: `Must be an object, got: ${typeLabel(raw)}` });\n return;\n }\n const f = raw as Record<string, unknown>;\n requireNonEmptyString(f[\"id\"], `${path}.id`, errors);\n requireNonEmptyString(f[\"title\"], `${path}.title`, errors);\n requireNonEmptyString(f[\"description\"], `${path}.description`, errors);\n}\n\nfunction validateModel(\n raw: unknown,\n path: string,\n errors: DslValidationError[]\n): void {\n if (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) {\n errors.push({ path, message: `Must be an object, got: ${typeLabel(raw)}` });\n return;\n }\n const m = raw as Record<string, unknown>;\n requireNonEmptyString(m[\"name\"], `${path}.name`, errors);\n\n if (!Array.isArray(m[\"fields\"])) {\n errors.push({ path: `${path}.fields`, message: `Must be an array, got: ${typeLabel(m[\"fields\"])}` });\n } else {\n const fields = m[\"fields\"] as unknown[];\n if (fields.length > MAX_FIELDS_PER_MODEL) {\n errors.push({ path: `${path}.fields`, message: `Too many fields (${fields.length} > ${MAX_FIELDS_PER_MODEL})` });\n }\n for (let j = 0; j < Math.min(fields.length, MAX_FIELDS_PER_MODEL); j++) {\n validateModelField(fields[j], `${path}.fields[${j}]`, errors);\n }\n }\n\n // relations: optional array of strings\n if (m[\"relations\"] !== undefined) {\n if (!Array.isArray(m[\"relations\"])) {\n errors.push({ path: `${path}.relations`, message: \"Must be an array of strings if present\" });\n } else {\n const rels = m[\"relations\"] as unknown[];\n for (let j = 0; j < rels.length; j++) {\n if (typeof rels[j] !== \"string\") {\n errors.push({ path: `${path}.relations[${j}]`, message: \"Must be a string\" });\n }\n }\n }\n }\n}\n\nfunction validateModelField(\n raw: unknown,\n path: string,\n errors: DslValidationError[]\n): void {\n if (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) {\n errors.push({ path, message: `Must be an object, got: ${typeLabel(raw)}` });\n return;\n }\n const f = raw as Record<string, unknown>;\n requireNonEmptyString(f[\"name\"], `${path}.name`, errors);\n requireNonEmptyString(f[\"type\"], `${path}.type`, errors);\n if (typeof f[\"required\"] !== \"boolean\") {\n errors.push({ path: `${path}.required`, message: `Must be boolean, got: ${typeLabel(f[\"required\"])}` });\n }\n}\n\nfunction validateEndpoint(\n raw: unknown,\n path: string,\n errors: DslValidationError[]\n): void {\n if (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) {\n errors.push({ path, message: `Must be an object, got: ${typeLabel(raw)}` });\n return;\n }\n const e = raw as Record<string, unknown>;\n\n requireNonEmptyString(e[\"id\"], `${path}.id`, errors);\n requireNonEmptyString(e[\"description\"], `${path}.description`, errors);\n\n // method\n if (!VALID_METHODS.includes(e[\"method\"] as HttpMethod)) {\n errors.push({\n path: `${path}.method`,\n message: `Must be one of ${VALID_METHODS.join(\"|\")}, got: ${JSON.stringify(e[\"method\"])}`,\n });\n }\n\n // path must be a string starting with \"/\"\n if (typeof e[\"path\"] !== \"string\" || !e[\"path\"].startsWith(\"/\")) {\n errors.push({\n path: `${path}.path`,\n message: `Must be a string starting with \"/\", got: ${JSON.stringify(e[\"path\"])}`,\n });\n }\n\n // auth\n if (typeof e[\"auth\"] !== \"boolean\") {\n errors.push({ path: `${path}.auth`, message: `Must be boolean, got: ${typeLabel(e[\"auth\"])}` });\n }\n\n // successStatus\n if (typeof e[\"successStatus\"] !== \"number\" || e[\"successStatus\"] < 100 || e[\"successStatus\"] > 599) {\n errors.push({\n path: `${path}.successStatus`,\n message: `Must be an HTTP status code (100-599), got: ${JSON.stringify(e[\"successStatus\"])}`,\n });\n }\n\n requireNonEmptyString(e[\"successDescription\"], `${path}.successDescription`, errors);\n\n // request: optional\n if (e[\"request\"] !== undefined) {\n validateRequestSchema(e[\"request\"], `${path}.request`, errors);\n }\n\n // errors: optional array\n if (e[\"errors\"] !== undefined) {\n if (!Array.isArray(e[\"errors\"])) {\n errors.push({ path: `${path}.errors`, message: \"Must be an array if present\" });\n } else {\n const errs = e[\"errors\"] as unknown[];\n if (errs.length > MAX_ERRORS_PER_ENDPOINT) {\n errors.push({ path: `${path}.errors`, message: `Too many error entries (${errs.length} > ${MAX_ERRORS_PER_ENDPOINT})` });\n }\n for (let j = 0; j < Math.min(errs.length, MAX_ERRORS_PER_ENDPOINT); j++) {\n validateResponseError(errs[j], `${path}.errors[${j}]`, errors);\n }\n }\n }\n}\n\nfunction validateRequestSchema(\n raw: unknown,\n path: string,\n errors: DslValidationError[]\n): void {\n if (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) {\n errors.push({ path, message: `Must be an object, got: ${typeLabel(raw)}` });\n return;\n }\n const r = raw as Record<string, unknown>;\n // Each of body/query/params must be a flat Record<string,string> if present\n for (const key of [\"body\", \"query\", \"params\"] as const) {\n if (r[key] !== undefined) {\n validateFieldMap(r[key], `${path}.${key}`, errors);\n }\n }\n}\n\nfunction validateFieldMap(\n raw: unknown,\n path: string,\n errors: DslValidationError[]\n): void {\n if (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) {\n errors.push({ path, message: `Must be a flat object (FieldMap), got: ${typeLabel(raw)}` });\n return;\n }\n const map = raw as Record<string, unknown>;\n // All values must be strings\n for (const [k, v] of Object.entries(map)) {\n if (typeof v !== \"string\") {\n errors.push({ path: `${path}.${k}`, message: `Value must be a type-description string, got: ${typeLabel(v)}` });\n }\n }\n}\n\nfunction validateResponseError(\n raw: unknown,\n path: string,\n errors: DslValidationError[]\n): void {\n if (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) {\n errors.push({ path, message: `Must be an object, got: ${typeLabel(raw)}` });\n return;\n }\n const e = raw as Record<string, unknown>;\n if (typeof e[\"status\"] !== \"number\" || e[\"status\"] < 100 || e[\"status\"] > 599) {\n errors.push({ path: `${path}.status`, message: `Must be an HTTP status code (100-599), got: ${JSON.stringify(e[\"status\"])}` });\n }\n requireNonEmptyString(e[\"code\"], `${path}.code`, errors);\n requireNonEmptyString(e[\"description\"], `${path}.description`, errors);\n}\n\nfunction validateBehavior(\n raw: unknown,\n path: string,\n errors: DslValidationError[]\n): void {\n if (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) {\n errors.push({ path, message: `Must be an object, got: ${typeLabel(raw)}` });\n return;\n }\n const b = raw as Record<string, unknown>;\n requireNonEmptyString(b[\"id\"], `${path}.id`, errors);\n requireNonEmptyString(b[\"description\"], `${path}.description`, errors);\n // constraints: optional array of strings\n if (b[\"constraints\"] !== undefined) {\n if (!Array.isArray(b[\"constraints\"])) {\n errors.push({ path: `${path}.constraints`, message: \"Must be an array of strings if present\" });\n } else {\n const cs = b[\"constraints\"] as unknown[];\n for (let j = 0; j < cs.length; j++) {\n if (typeof cs[j] !== \"string\") {\n errors.push({ path: `${path}.constraints[${j}]`, message: \"Must be a string\" });\n }\n }\n }\n }\n}\n\nfunction validateComponent(\n raw: unknown,\n path: string,\n errors: DslValidationError[]\n): void {\n if (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) {\n errors.push({ path, message: `Must be an object, got: ${typeLabel(raw)}` });\n return;\n }\n const c = raw as Record<string, unknown>;\n requireNonEmptyString(c[\"id\"], `${path}.id`, errors);\n requireNonEmptyString(c[\"name\"], `${path}.name`, errors);\n requireNonEmptyString(c[\"description\"], `${path}.description`, errors);\n\n // props: array of {name, type, required}\n if (c[\"props\"] !== undefined) {\n if (!Array.isArray(c[\"props\"])) {\n errors.push({ path: `${path}.props`, message: \"Must be an array if present\" });\n } else {\n const props = c[\"props\"] as unknown[];\n for (let j = 0; j < props.length; j++) {\n const p = props[j] as Record<string, unknown>;\n if (typeof p !== \"object\" || p === null) {\n errors.push({ path: `${path}.props[${j}]`, message: \"Must be an object\" });\n continue;\n }\n requireNonEmptyString(p[\"name\"], `${path}.props[${j}].name`, errors);\n requireNonEmptyString(p[\"type\"], `${path}.props[${j}].type`, errors);\n if (typeof p[\"required\"] !== \"boolean\") {\n errors.push({ path: `${path}.props[${j}].required`, message: \"Must be boolean\" });\n }\n }\n }\n }\n\n // events: array of {name, payload?}\n if (c[\"events\"] !== undefined) {\n if (!Array.isArray(c[\"events\"])) {\n errors.push({ path: `${path}.events`, message: \"Must be an array if present\" });\n } else {\n const events = c[\"events\"] as unknown[];\n for (let j = 0; j < events.length; j++) {\n const e = events[j] as Record<string, unknown>;\n if (typeof e !== \"object\" || e === null) {\n errors.push({ path: `${path}.events[${j}]`, message: \"Must be an object\" });\n continue;\n }\n requireNonEmptyString(e[\"name\"], `${path}.events[${j}].name`, errors);\n }\n }\n }\n\n // state: Record<string, string>\n if (c[\"state\"] !== undefined) {\n if (typeof c[\"state\"] !== \"object\" || Array.isArray(c[\"state\"]) || c[\"state\"] === null) {\n errors.push({ path: `${path}.state`, message: \"Must be a flat object (Record<string, string>) if present\" });\n }\n }\n\n // apiCalls: string[]\n if (c[\"apiCalls\"] !== undefined) {\n if (!Array.isArray(c[\"apiCalls\"])) {\n errors.push({ path: `${path}.apiCalls`, message: \"Must be an array of strings if present\" });\n }\n }\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction requireNonEmptyString(\n v: unknown,\n path: string,\n errors: DslValidationError[]\n): void {\n if (typeof v !== \"string\" || v.trim().length === 0) {\n errors.push({\n path,\n message: `Must be a non-empty string, got: ${typeLabel(v)}`,\n });\n }\n}\n\nfunction typeLabel(v: unknown): string {\n if (v === null) return \"null\";\n if (Array.isArray(v)) return \"array\";\n return typeof v;\n}\n\n// ─── Pretty printer ───────────────────────────────────────────────────────────\n\nexport function printValidationErrors(errors: DslValidationError[]): void {\n console.log(chalk.red(`\\n DSL Validation failed — ${errors.length} error(s):\\n`));\n for (const err of errors) {\n console.log(chalk.red(` ✘ ${chalk.bold(err.path)}: ${err.message}`));\n }\n console.log();\n}\n\nexport function printDslSummary(dsl: SpecDSL): void {\n console.log(chalk.green(\" ✔ DSL valid\"));\n console.log(chalk.gray(` Models : ${dsl.models.length}`));\n console.log(chalk.gray(` Endpoints : ${dsl.endpoints.length}`));\n console.log(chalk.gray(` Behaviors : ${dsl.behaviors.length}`));\n if (dsl.components && dsl.components.length > 0) {\n console.log(chalk.gray(` Components: ${dsl.components.length}`));\n for (const cmp of dsl.components) {\n console.log(chalk.gray(` ${cmp.id} ${cmp.name} — props:${cmp.props.length} events:${cmp.events.length}`));\n }\n }\n if (dsl.endpoints.length > 0) {\n for (const ep of dsl.endpoints) {\n const auth = ep.auth ? chalk.yellow(\" [auth]\") : \"\";\n console.log(chalk.gray(` ${ep.method.padEnd(6)} ${ep.path}${auth} — ${ep.description}`));\n }\n }\n}\n\n// Re-export for convenience\nexport type { SpecDSL, DslValidationResult, DslValidationError } from \"./dsl-types\";\n","/**\n * System prompt for DSL extraction.\n *\n * Key anti-hallucination rules enforced in this prompt:\n * 1. Extract ONLY what is explicitly stated — no inference.\n * 2. Empty arrays are correct and preferred over invented entries.\n * 3. Exact JSON schema with field types and constraints provided.\n * 4. Concrete example included so model has a reference to match.\n * 5. Output ONLY JSON — no prose, no markdown fences.\n */\nexport const dslSystemPrompt = `You are a precise structured-data extractor. Your job is to convert a Feature Spec (written in any language) into a strictly-typed JSON DSL.\n\nCRITICAL RULES — read carefully before outputting:\n1. EXTRACT ONLY what is EXPLICITLY written in the spec. Do NOT infer, assume, or complete anything not stated.\n2. If the spec does not mention data models, output \"models\": [].\n3. If the spec does not mention endpoints, output \"endpoints\": [].\n4. If the spec does not mention non-CRUD business behaviors, output \"behaviors\": [].\n5. Output ONLY valid JSON. No markdown fences, no explanation, no prose before or after.\n6. Every required field must be present. If a value cannot be extracted, use an empty string \"\" — never omit the field.\n7. \"path\" values must start with \"/\". Method must be one of: GET POST PUT PATCH DELETE.\n8. successStatus must be an integer (e.g. 200, 201). auth must be true or false (boolean, not string).\n9. FieldMap values must be type-description strings (e.g. \"string\", \"number\", \"string (email format)\") — NOT nested objects.\n\nOUTPUT FORMAT (follow exactly):\n{\n \"version\": \"1.0\",\n \"feature\": {\n \"id\": \"<slug — lowercase, hyphens only, e.g. user-login>\",\n \"title\": \"<verbatim title from spec>\",\n \"description\": \"<one paragraph summary>\"\n },\n \"models\": [\n {\n \"name\": \"<PascalCase model name>\",\n \"description\": \"<optional one-line description>\",\n \"fields\": [\n {\n \"name\": \"<camelCase field name>\",\n \"type\": \"<String|Int|Float|Boolean|DateTime|Json|ModelName>\",\n \"required\": true,\n \"unique\": false,\n \"description\": \"<optional>\"\n }\n ],\n \"relations\": [\"<plain-text relation, e.g. belongs to User via userId>\"]\n }\n ],\n \"endpoints\": [\n {\n \"id\": \"EP-001\",\n \"method\": \"POST\",\n \"path\": \"/api/v1/...\",\n \"description\": \"<what this endpoint does>\",\n \"auth\": false,\n \"request\": {\n \"body\": { \"fieldName\": \"type description\" },\n \"query\": { \"fieldName\": \"type description\" },\n \"params\": { \"fieldName\": \"type description\" }\n },\n \"successStatus\": 200,\n \"successDescription\": \"<what the success response contains>\",\n \"errors\": [\n { \"status\": 401, \"code\": \"ERROR_CODE\", \"description\": \"<when this error occurs>\" }\n ]\n }\n ],\n \"behaviors\": [\n {\n \"id\": \"BHV-001\",\n \"description\": \"<what happens>\",\n \"trigger\": \"<what event triggers this>\",\n \"constraints\": [\"<rule 1>\", \"<rule 2>\"]\n }\n ]\n}\n\nEXAMPLE (for reference only — your output must reflect the actual spec, not this example):\nInput spec mentions: \"POST /api/v1/auth/login — accepts email+password, returns JWT. 401 if wrong credentials. Rate limited: 5 failures lock account for 30 min.\"\nCorrect output:\n{\n \"version\": \"1.0\",\n \"feature\": { \"id\": \"user-login\", \"title\": \"用户登录\", \"description\": \"用户通过邮箱和密码登录,获取 JWT token。\" },\n \"models\": [],\n \"endpoints\": [\n {\n \"id\": \"EP-001\",\n \"method\": \"POST\",\n \"path\": \"/api/v1/auth/login\",\n \"description\": \"用户登录,返回 JWT token\",\n \"auth\": false,\n \"request\": { \"body\": { \"email\": \"string (email format)\", \"password\": \"string (min 8 chars)\" } },\n \"successStatus\": 200,\n \"successDescription\": \"返回 JWT access token 和过期时间\",\n \"errors\": [\n { \"status\": 401, \"code\": \"INVALID_CREDENTIALS\", \"description\": \"邮箱或密码错误\" },\n { \"status\": 429, \"code\": \"ACCOUNT_LOCKED\", \"description\": \"连续失败超过 5 次,账号锁定 30 分钟\" }\n ]\n }\n ],\n \"behaviors\": [\n {\n \"id\": \"BHV-001\",\n \"description\": \"连续登录失败超过 5 次后锁定账号\",\n \"trigger\": \"登录接口返回 401\",\n \"constraints\": [\"失败计数存储在 Redis\", \"锁定时间 30 分钟\", \"解锁后计数重置\"]\n }\n ]\n}`;\n\n/**\n * System prompt for frontend DSL extraction.\n * Extends the backend prompt with ComponentSpec support.\n */\nexport const dslFrontendSystemPrompt = `You are a precise structured-data extractor. Your job is to convert a Feature Spec (written in any language) into a strictly-typed JSON DSL for a FRONTEND project.\n\nCRITICAL RULES:\n1. EXTRACT ONLY what is EXPLICITLY written in the spec. Do NOT infer or complete anything not stated.\n2. Output ONLY valid JSON. No markdown fences, no explanation.\n3. Every required field must be present. If a value cannot be extracted, use an empty string \"\" — never omit.\n4. \"endpoints\" should list the API calls this frontend feature makes to the backend (not backend implementation).\n5. \"components\" is the most important section for frontend. List every named UI component in the spec.\n6. \"models\" should be empty [] for pure frontend features — use \"components\" instead.\n7. ComponentProp.type and ComponentEvent.payload must be plain type strings, not nested objects.\n\nOUTPUT FORMAT (follow exactly):\n{\n \"version\": \"1.0\",\n \"feature\": {\n \"id\": \"<slug>\",\n \"title\": \"<verbatim title>\",\n \"description\": \"<one paragraph>\"\n },\n \"models\": [],\n \"endpoints\": [\n {\n \"id\": \"EP-001\",\n \"method\": \"POST\",\n \"path\": \"/api/v1/...\",\n \"description\": \"<what the frontend calls this for>\",\n \"auth\": true,\n \"request\": { \"body\": { \"fieldName\": \"type description\" } },\n \"successStatus\": 200,\n \"successDescription\": \"<what the response contains>\",\n \"errors\": [{ \"status\": 401, \"code\": \"UNAUTHORIZED\", \"description\": \"Not logged in\" }]\n }\n ],\n \"behaviors\": [],\n \"components\": [\n {\n \"id\": \"CMP-001\",\n \"name\": \"<PascalCase component name>\",\n \"description\": \"<what this component does>\",\n \"props\": [\n { \"name\": \"<propName>\", \"type\": \"<TypeScript type>\", \"required\": true, \"description\": \"<optional>\" }\n ],\n \"events\": [\n { \"name\": \"<onEventName>\", \"payload\": \"<payload type or empty string>\" }\n ],\n \"state\": {\n \"<stateName>\": \"<TypeScript type>\"\n },\n \"apiCalls\": [\"<endpoint id or path that this component calls>\"]\n }\n ]\n}`;\n\n/**\n * Build the user-turn prompt for DSL extraction.\n * Keeps it minimal — the spec content is all the model needs.\n */\nexport function buildDslExtractionPrompt(specContent: string, isFrontend = false): string {\n const hint = isFrontend\n ? \"This is a FRONTEND feature spec. Focus on extracting components[] — each named UI component with its props, events, state, and API calls. Output ONLY valid JSON.\\n\\n\"\n : \"Extract the DSL from the following Feature Spec. Output ONLY valid JSON.\\n\\n\";\n return hint + specContent;\n}\n\n/**\n * Build the retry prompt when the previous attempt produced invalid output.\n * Includes the specific validation errors so the model can fix them.\n */\nexport function buildDslRetryPrompt(\n specContent: string,\n previousOutput: string,\n validationErrors: Array<{ path: string; message: string }>\n): string {\n const errorLines = validationErrors\n .map((e) => ` - ${e.path}: ${e.message}`)\n .join(\"\\n\");\n\n return `Your previous DSL output had validation errors. Fix them and output corrected JSON only.\n\nValidation errors found:\n${errorLines}\n\nYour previous output (for reference):\n${previousOutput.slice(0, 2000)}${previousOutput.length > 2000 ? \"\\n... (truncated)\" : \"\"}\n\nOriginal spec:\n${specContent}\n\nOutput ONLY the corrected JSON. No explanation.`;\n}\n","import * as fs from \"fs-extra\";\nimport * as path from \"path\";\nimport { glob } from \"glob\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type FrontendFramework = \"react\" | \"next\" | \"vue\" | \"react-native\" | \"unknown\";\n\nexport interface FrontendContext {\n framework: FrontendFramework;\n /** e.g. ['zustand', 'redux', 'jotai'] */\n stateManagement: string[];\n /** e.g. 'axios', 'fetch', 'swr', 'react-query' */\n httpClient: string;\n /** e.g. 'tailwind', 'antd', 'shadcn' */\n uiLibrary: string;\n /** e.g. 'react-router', 'next-app-router' */\n routingPattern: string;\n /** Whether tests use React Testing Library */\n testFramework: \"rtl\" | \"cypress\" | \"jest\" | \"vitest\" | \"unknown\";\n /** api/ or services/ file paths */\n existingApiFiles: string[];\n /** First 60 lines of up to 2 existing API wrapper files */\n apiWrapperContent: string[];\n /** Custom hook files (use*.ts/tsx) — relative paths */\n hookFiles: string[];\n /** First 30 lines of up to 2 hook files */\n hookPatterns: string[];\n /** State slice / store files — relative paths */\n storeFiles: string[];\n /** First 60 lines of up to 2 existing store files — shows the real store pattern */\n storePatterns: string[];\n /**\n * The exact HTTP client import line found in an existing API file.\n * e.g. \"import request from '@/utils/http'\"\n * Extracted from real code — use this verbatim, never invent a different import path.\n */\n httpClientImport?: string;\n /**\n * Reusable components found in src/components/ — relative paths.\n * AI must check this list before creating any new component.\n */\n reusableComponents: string[];\n /**\n * First 60 lines of up to 2 existing page/view files.\n * Shows how UI library components and shared components are actually imported and used.\n */\n pageExamples: string[];\n /** Sample component structures (first 40 lines of up to 3 components) */\n componentPatterns: string[];\n /**\n * The exact layout component import line found in an existing route module.\n * e.g. \"const Layout = () => import('@/layout/index.vue')\"\n * Extracted from real code — must be copied verbatim when creating new route modules.\n */\n layoutImport?: string;\n /**\n * Full content of one existing route module file — use as a copy-paste template.\n * Relative path + content.\n */\n routeModuleExample?: { path: string; content: string };\n /**\n * A real paginated API function extracted from the existing codebase.\n * Shows the exact pagination parameter names (e.g. pageIndex/pageSize vs page/size)\n * and how they are passed (POST body vs GET query params).\n * COPY THIS PATTERN exactly for all new paginated list APIs.\n */\n paginationExample?: string;\n}\n\n// ─── Detection Maps ────────────────────────────────────────────────────────────\n\nconst STATE_MANAGEMENT_LIBS = [\n \"zustand\",\n \"redux\",\n \"@reduxjs/toolkit\",\n \"jotai\",\n \"recoil\",\n \"mobx\",\n \"mobx-react\",\n \"valtio\",\n \"pinia\",\n \"vuex\",\n];\n\nconst HTTP_CLIENT_LIBS: Array<[string, string]> = [\n [\"swr\", \"swr\"],\n [\"@tanstack/react-query\", \"react-query\"],\n [\"react-query\", \"react-query\"],\n [\"axios\", \"axios\"],\n [\"ky\", \"ky\"],\n];\n\nconst UI_LIBRARY_LIBS: Array<[string, string]> = [\n [\"antd\", \"antd\"],\n [\"@ant-design/pro-components\", \"antd-pro\"],\n [\"@mui/material\", \"mui\"],\n [\"@chakra-ui/react\", \"chakra-ui\"],\n [\"shadcn-ui\", \"shadcn\"],\n [\"@radix-ui/react-primitive\", \"radix-ui\"],\n [\"element-plus\", \"element-plus\"],\n [\"vant\", \"vant\"],\n [\"tailwindcss\", \"tailwind\"],\n [\"@tailwindcss/vite\", \"tailwind\"],\n [\"react-native-paper\", \"react-native-paper\"],\n];\n\nconst ROUTING_LIBS: Array<[string, string]> = [\n [\"react-router-dom\", \"react-router\"],\n [\"react-router\", \"react-router\"],\n [\"@tanstack/react-router\", \"tanstack-router\"],\n [\"react-navigation\", \"react-navigation\"],\n [\"expo-router\", \"expo-router\"],\n [\"vue-router\", \"vue-router\"],\n];\n\n// ─── Main function ─────────────────────────────────────────────────────────────\n\n/**\n * Load frontend-specific project context (framework, state mgmt, HTTP client, etc.)\n * Never throws — returns partial results on failure.\n */\nexport async function loadFrontendContext(\n projectRoot: string\n): Promise<FrontendContext> {\n const ctx: FrontendContext = {\n framework: \"unknown\",\n stateManagement: [],\n httpClient: \"fetch\",\n uiLibrary: \"unknown\",\n routingPattern: \"unknown\",\n testFramework: \"unknown\",\n existingApiFiles: [],\n apiWrapperContent: [],\n hookFiles: [],\n hookPatterns: [],\n storeFiles: [],\n storePatterns: [],\n reusableComponents: [],\n pageExamples: [],\n componentPatterns: [],\n };\n\n try {\n const pkgPath = path.join(projectRoot, \"package.json\");\n if (!(await fs.pathExists(pkgPath))) return ctx;\n\n const pkg = await fs.readJson(pkgPath);\n const allDeps: Record<string, string> = {\n ...(pkg.dependencies ?? {}),\n ...(pkg.devDependencies ?? {}),\n };\n const depKeys = Object.keys(allDeps);\n const has = (name: string) => depKeys.includes(name);\n\n // Framework\n if (has(\"react-native\") || has(\"expo\")) {\n ctx.framework = \"react-native\";\n } else if (has(\"next\")) {\n ctx.framework = \"next\";\n } else if (has(\"react\")) {\n ctx.framework = \"react\";\n } else if (has(\"vue\")) {\n ctx.framework = \"vue\";\n }\n\n // State management (may have multiple)\n ctx.stateManagement = STATE_MANAGEMENT_LIBS.filter((lib) => has(lib));\n\n // HTTP client (first match wins)\n for (const [lib, label] of HTTP_CLIENT_LIBS) {\n if (has(lib)) {\n ctx.httpClient = label;\n break;\n }\n }\n\n // UI library (first match wins)\n for (const [lib, label] of UI_LIBRARY_LIBS) {\n if (has(lib)) {\n ctx.uiLibrary = label;\n break;\n }\n }\n if (ctx.uiLibrary === \"unknown\") {\n ctx.uiLibrary = \"none\";\n }\n\n // Routing\n if (ctx.framework === \"next\") {\n // Detect app router vs pages router\n const hasAppDir = await fs.pathExists(path.join(projectRoot, \"app\"));\n ctx.routingPattern = hasAppDir ? \"next-app-router\" : \"next-pages-router\";\n } else {\n for (const [lib, label] of ROUTING_LIBS) {\n if (has(lib)) {\n ctx.routingPattern = label;\n break;\n }\n }\n }\n\n // Test framework detection\n if (depKeys.includes(\"@testing-library/react\") || depKeys.includes(\"@testing-library/vue\")) {\n ctx.testFramework = \"rtl\";\n } else if (depKeys.includes(\"cypress\")) {\n ctx.testFramework = \"cypress\";\n } else if (depKeys.includes(\"vitest\")) {\n ctx.testFramework = \"vitest\";\n } else if (depKeys.includes(\"jest\") || depKeys.includes(\"@jest/core\")) {\n ctx.testFramework = \"jest\";\n }\n\n // Existing API files\n const apiFilePatterns = [\n \"src/api/**/*.{ts,js}\",\n \"src/apis/**/*.{ts,js}\",\n \"src/services/**/*.{ts,js}\",\n \"src/lib/api/**/*.{ts,js}\",\n \"src/utils/api/**/*.{ts,js}\",\n \"api/**/*.{ts,js}\",\n \"services/**/*.{ts,js}\",\n ];\n for (const pattern of apiFilePatterns) {\n const files = await glob(pattern, {\n cwd: projectRoot,\n ignore: [\"**/*.test.*\", \"**/*.spec.*\", \"node_modules/**\"],\n });\n ctx.existingApiFiles.push(...files);\n }\n ctx.existingApiFiles = [...new Set(ctx.existingApiFiles)].slice(0, 20);\n\n // API wrapper content preview — first 60 lines of up to 2 files\n for (const relPath of ctx.existingApiFiles.slice(0, 2)) {\n try {\n const content = await fs.readFile(path.join(projectRoot, relPath), \"utf-8\");\n const preview = content.split(\"\\n\").slice(0, 60).join(\"\\n\");\n ctx.apiWrapperContent.push(`// ${relPath}\\n${preview}`);\n } catch {\n // skip\n }\n }\n\n // Hook files — use*.ts/tsx\n const hookPatterns = [\n \"src/hooks/use*.{ts,tsx}\",\n \"src/**/hooks/use*.{ts,tsx}\",\n \"hooks/use*.{ts,tsx}\",\n ];\n for (const pattern of hookPatterns) {\n const files = await glob(pattern, {\n cwd: projectRoot,\n ignore: [\"**/*.test.*\", \"**/*.spec.*\", \"node_modules/**\"],\n });\n ctx.hookFiles.push(...files);\n }\n ctx.hookFiles = [...new Set(ctx.hookFiles)].slice(0, 15);\n\n // Hook content preview — first 30 lines of up to 2 hook files\n for (const relPath of ctx.hookFiles.slice(0, 2)) {\n try {\n const content = await fs.readFile(path.join(projectRoot, relPath), \"utf-8\");\n const preview = content.split(\"\\n\").slice(0, 30).join(\"\\n\");\n ctx.hookPatterns.push(`// ${relPath}\\n${preview}`);\n } catch {\n // skip\n }\n }\n\n // Store / slice files (Redux slices, Zustand stores, Pinia stores)\n const storeFilePatterns = [\n \"src/store/**/*.{ts,js}\",\n \"src/stores/**/*.{ts,js}\",\n \"src/**/slice*.{ts,js}\",\n \"src/**/*slice.{ts,js}\",\n \"src/**/*store.{ts,js}\",\n \"src/**/*Store.{ts,js}\",\n \"store/**/*.{ts,js}\",\n \"stores/**/*.{ts,js}\",\n ];\n for (const pattern of storeFilePatterns) {\n const files = await glob(pattern, {\n cwd: projectRoot,\n ignore: [\"**/*.test.*\", \"**/*.spec.*\", \"node_modules/**\"],\n });\n ctx.storeFiles.push(...files);\n }\n ctx.storeFiles = [...new Set(ctx.storeFiles)].slice(0, 10);\n\n // Store content preview — first 60 lines of up to 2 store files\n // (shows the AI what stores actually do: state + actions that call API layer, NOT HTTP directly)\n for (const relPath of ctx.storeFiles.slice(0, 2)) {\n try {\n const content = await fs.readFile(path.join(projectRoot, relPath), \"utf-8\");\n const preview = content.split(\"\\n\").slice(0, 60).join(\"\\n\");\n ctx.storePatterns.push(`// ${relPath}\\n${preview}`);\n } catch {\n // skip\n }\n }\n\n // Extract the exact HTTP client import line from an existing API file\n // e.g. \"import request from '@/utils/http'\" or \"import axios from 'axios'\"\n // This is ground truth — prevents the AI from inventing a different import path.\n const httpImportRegex = /^import\\s+(?:\\w+|\\{[^}]+\\})\\s+from\\s+['\"](@\\/[^'\"]+|axios|ky)['\"]/m;\n for (const relPath of ctx.existingApiFiles.slice(0, 5)) {\n try {\n const content = await fs.readFile(path.join(projectRoot, relPath), \"utf-8\");\n const match = content.match(httpImportRegex);\n if (match) {\n ctx.httpClientImport = match[0].trim();\n break;\n }\n } catch {\n // skip\n }\n }\n\n // Pagination pattern extraction — find a real paginated list function from the existing codebase.\n // Scans API files for interfaces/params that contain pagination field names,\n // then extracts the matching function as ground truth for the AI to copy.\n const paginationFieldNames = [\"pageIndex\", \"pageSize\", \"pageNum\", \"current\", \"page\", \"size\", \"offset\", \"limit\"];\n const paginationInterfaceRegex = new RegExp(\n `(?:interface|type)\\\\s+(\\\\w*(?:Params|Query|Request|Filter|Page)\\\\w*)\\\\s*\\\\{[^}]*\\\\b(?:${paginationFieldNames.join(\"|\")})\\\\b[^}]*\\\\}`,\n \"s\"\n );\n const apiExportFnRegex = /export\\s+(?:async\\s+)?function\\s+\\w+\\s*\\([^)]*\\)[^{]*\\{[\\s\\S]*?\\n\\}/g;\n for (const relPath of ctx.existingApiFiles) {\n // Skip type-only and index files\n if (/types?\\.ts$|index\\.ts$/.test(relPath)) continue;\n try {\n const content = await fs.readFile(path.join(projectRoot, relPath), \"utf-8\");\n // Only process files that have pagination field names at all\n if (!paginationFieldNames.some((f) => content.includes(f))) continue;\n // Check this file has an interface with pagination fields\n const interfaceMatch = content.match(paginationInterfaceRegex);\n if (!interfaceMatch) continue;\n // Find the first exported function that uses this interface\n const interfaceName = interfaceMatch[1];\n const fnRegex = new RegExp(\n `export\\\\s+(?:async\\\\s+)?function\\\\s+\\\\w+\\\\s*\\\\(\\\\s*\\\\w+\\\\s*:\\\\s*${interfaceName}[^)]*\\\\)[\\\\s\\\\S]*?\\\\n\\\\}`,\n \"\"\n );\n const fnMatch = content.match(fnRegex);\n if (fnMatch) {\n ctx.paginationExample = `// From ${relPath}\\n${interfaceMatch[0]}\\n\\n${fnMatch[0]}`;\n break;\n }\n } catch {\n // skip\n }\n }\n\n // Reusable components — scan src/components/ (the shared component library)\n const sharedComponentDirs = [\"src/components\", \"components\"];\n for (const dir of sharedComponentDirs) {\n const absDir = path.join(projectRoot, dir);\n if (!(await fs.pathExists(absDir))) continue;\n const files = await glob(\"**/*.{vue,tsx,jsx}\", {\n cwd: absDir,\n ignore: [\"**/*.test.*\", \"**/*.spec.*\", \"node_modules/**\"],\n maxDepth: 4,\n });\n ctx.reusableComponents.push(...files.map((f) => path.join(dir, f)));\n }\n ctx.reusableComponents = [...new Set(ctx.reusableComponents)].slice(0, 40);\n\n // Page examples — read 2 existing view/page files to show component usage patterns\n const viewDirs = [\"src/views\", \"src/pages\", \"views\", \"pages\"];\n const viewFiles: string[] = [];\n for (const dir of viewDirs) {\n const absDir = path.join(projectRoot, dir);\n if (!(await fs.pathExists(absDir))) continue;\n const files = await glob(\"**/*.{vue,tsx,jsx}\", {\n cwd: absDir,\n ignore: [\"**/*.test.*\", \"**/*.spec.*\", \"node_modules/**\"],\n maxDepth: 3,\n });\n viewFiles.push(...files.map((f) => path.join(dir, f)));\n if (viewFiles.length >= 6) break;\n }\n for (const relPath of viewFiles.slice(0, 2)) {\n try {\n const content = await fs.readFile(path.join(projectRoot, relPath), \"utf-8\");\n // Read up to 80 lines — enough to see the template section with component usage\n const preview = content.split(\"\\n\").slice(0, 80).join(\"\\n\");\n ctx.pageExamples.push(`// ${relPath}\\n${preview}`);\n } catch {\n // skip\n }\n }\n\n // Component patterns — sample a few component files (generic structure reference)\n const componentFiles: string[] = [];\n for (const dir of sharedComponentDirs) {\n const absDir = path.join(projectRoot, dir);\n if (!(await fs.pathExists(absDir))) continue;\n const files = await glob(\"**/*.{tsx,vue,jsx}\", {\n cwd: absDir,\n ignore: [\"**/*.test.*\", \"**/*.spec.*\", \"node_modules/**\"],\n maxDepth: 2,\n });\n componentFiles.push(...files.map((f) => path.join(dir, f)));\n if (componentFiles.length >= 5) break;\n }\n\n // Read first 40 lines of up to 3 component files\n for (const relPath of componentFiles.slice(0, 3)) {\n try {\n const content = await fs.readFile(path.join(projectRoot, relPath), \"utf-8\");\n const preview = content.split(\"\\n\").slice(0, 40).join(\"\\n\");\n ctx.componentPatterns.push(`// ${relPath}\\n${preview}`);\n } catch {\n // skip unreadable files\n }\n }\n // Route module example + layout import extraction\n await extractRouteModuleContext(projectRoot, ctx);\n\n } catch {\n // Graceful degradation — return whatever we've collected so far\n }\n\n return ctx;\n}\n\n/**\n * Scan existing router module files to extract:\n * 1. The exact layout component import line (ground truth, not guessed)\n * 2. A full route module file as a copy-paste template\n */\nasync function extractRouteModuleContext(\n projectRoot: string,\n ctx: FrontendContext\n): Promise<void> {\n const modulePatterns = [\n \"src/router/modules/**/*.{ts,js}\",\n \"src/routes/modules/**/*.{ts,js}\",\n \"src/router/**/*.{ts,js}\",\n ];\n\n const moduleFiles: string[] = [];\n for (const pattern of modulePatterns) {\n const files = await glob(pattern, {\n cwd: projectRoot,\n ignore: [\"**/index.{ts,js}\", \"node_modules/**\", \"**/*.test.*\"],\n });\n moduleFiles.push(...files);\n }\n\n if (moduleFiles.length === 0) return;\n\n // Layout import regex — matches common patterns:\n // const Layout = () => import('@/layout/index.vue')\n // import Layout from '@/layouts/default/index.vue'\n // const Layout = defineAsyncComponent(() => import('@/layout/index.vue'))\n const layoutImportRegex =\n /^(?:const\\s+Layout\\s*=.*import\\(['\"][^'\"]+['\"]\\)|import\\s+Layout\\s+from\\s+['\"][^'\"]+['\"])/m;\n\n for (const relPath of moduleFiles) {\n try {\n const content = await fs.readFile(path.join(projectRoot, relPath), \"utf-8\");\n const match = content.match(layoutImportRegex);\n if (match) {\n ctx.layoutImport = match[0].trim();\n // Use this file as the route module template (cap at 100 lines)\n const preview = content.split(\"\\n\").slice(0, 100).join(\"\\n\");\n ctx.routeModuleExample = { path: relPath, content: preview };\n break; // first match is enough\n }\n } catch {\n // skip\n }\n }\n}\n\n/**\n * Build a concise context section from FrontendContext for prompt injection.\n */\nexport function buildFrontendContextSection(ctx: FrontendContext): string {\n const lines: string[] = [\n \"=== Frontend Project Context ===\",\n `Framework : ${ctx.framework}`,\n `State Management : ${ctx.stateManagement.join(\", \") || \"none detected\"}`,\n `HTTP Client : ${ctx.httpClient}`,\n `UI Library : ${ctx.uiLibrary}`,\n `Routing : ${ctx.routingPattern}`,\n `Test Framework : ${ctx.testFramework}`,\n ];\n\n // Layout import — most critical for correct route module generation\n if (ctx.layoutImport) {\n lines.push(\n `\\nLayout component import (COPY THIS EXACTLY in every new route module — do NOT invent a different path):`,\n ` ${ctx.layoutImport}`\n );\n }\n\n // Route module template — shows exact file structure to replicate\n if (ctx.routeModuleExample) {\n lines.push(\n `\\nExisting route module template (${ctx.routeModuleExample.path}) — use this as the structural template for new route modules:`,\n \"```\",\n ctx.routeModuleExample.content,\n \"```\"\n );\n }\n\n if (ctx.existingApiFiles.length > 0) {\n lines.push(`\\nExisting API/service files (${ctx.existingApiFiles.length}):`);\n ctx.existingApiFiles.slice(0, 10).forEach((f) => lines.push(` - ${f}`));\n }\n\n // HTTP client import — must be copied verbatim\n if (ctx.httpClientImport) {\n lines.push(\n `\\nHTTP client import (COPY THIS EXACTLY in every new API file — do NOT import from any other path):`,\n ` ${ctx.httpClientImport}`\n );\n }\n\n // Pagination example — the most critical ground truth for list APIs\n if (ctx.paginationExample) {\n lines.push(\n `\\nPagination pattern (COPY THIS EXACTLY for all paginated list APIs — use IDENTICAL parameter names, HTTP method, and call style):`,\n \"```typescript\",\n ctx.paginationExample,\n \"```\"\n );\n }\n\n if (ctx.apiWrapperContent.length > 0) {\n lines.push(`\\nAPI file patterns (new API functions must follow this exact structure):`);\n ctx.apiWrapperContent.forEach((p) => {\n lines.push(\"```\");\n lines.push(p);\n lines.push(\"```\");\n });\n }\n\n if (ctx.hookFiles.length > 0) {\n lines.push(`\\nExisting custom hooks (${ctx.hookFiles.length}):`);\n ctx.hookFiles.slice(0, 8).forEach((f) => lines.push(` - ${f}`));\n }\n\n if (ctx.hookPatterns.length > 0) {\n lines.push(`\\nHook patterns (follow same structure):`);\n ctx.hookPatterns.forEach((p) => {\n lines.push(\"```\");\n lines.push(p);\n lines.push(\"```\");\n });\n }\n\n if (ctx.storeFiles.length > 0) {\n lines.push(`\\nState store files (${ctx.storeFiles.length}):`);\n ctx.storeFiles.slice(0, 8).forEach((f) => lines.push(` - ${f}`));\n }\n\n if (ctx.storePatterns.length > 0) {\n lines.push(\n `\\nExisting store patterns (CRITICAL — stores in this project call API layer functions, they do NOT make HTTP requests directly):`,\n `Follow this exact structure for new stores:`\n );\n ctx.storePatterns.forEach((p) => {\n lines.push(\"```\");\n lines.push(p);\n lines.push(\"```\");\n });\n }\n\n if (ctx.reusableComponents.length > 0) {\n lines.push(\n `\\nExisting reusable components in src/components/ (${ctx.reusableComponents.length} files):`,\n `ALWAYS check this list before creating a new component. Import and reuse existing ones instead of reinventing.`\n );\n ctx.reusableComponents.forEach((f) => lines.push(` - ${f}`));\n }\n\n if (ctx.pageExamples.length > 0) {\n lines.push(\n `\\nExisting page examples (shows which UI library components and shared components are used — follow the same import and usage patterns):`\n );\n ctx.pageExamples.forEach((p) => {\n lines.push(\"```\");\n lines.push(p);\n lines.push(\"```\");\n });\n }\n\n if (ctx.componentPatterns.length > 0) {\n lines.push(`\\nShared component structure patterns:`);\n ctx.componentPatterns.forEach((p) => {\n lines.push(\"```\");\n lines.push(p.slice(0, 500));\n lines.push(\"```\");\n });\n }\n\n lines.push(\"=== End of Frontend Context ===\");\n return lines.join(\"\\n\");\n}\n","import chalk from \"chalk\";\nimport { execSync } from \"child_process\";\nimport * as path from \"path\";\nimport * as fs from \"fs-extra\";\nimport { AIProvider } from \"./spec-generator\";\nimport {\n reviewSystemPrompt,\n reviewArchitectureSystemPrompt,\n reviewImplementationSystemPrompt,\n} from \"../prompts/codegen.prompt\";\n\n// ─── Review History ────────────────────────────────────────────────────────────\n\ninterface ReviewHistoryEntry {\n date: string;\n specFile: string;\n score: number;\n topIssues: string[];\n}\n\nconst REVIEW_HISTORY_FILE = \".ai-spec-reviews.json\";\n\nasync function loadReviewHistory(projectRoot: string): Promise<ReviewHistoryEntry[]> {\n const historyPath = path.join(projectRoot, REVIEW_HISTORY_FILE);\n try {\n if (await fs.pathExists(historyPath)) {\n return await fs.readJson(historyPath);\n }\n } catch {\n // ignore\n }\n return [];\n}\n\nasync function appendReviewHistory(\n projectRoot: string,\n entry: ReviewHistoryEntry\n): Promise<void> {\n const historyPath = path.join(projectRoot, REVIEW_HISTORY_FILE);\n const existing = await loadReviewHistory(projectRoot);\n // Keep the last 20 entries\n const updated = [...existing, entry].slice(-20);\n try {\n await fs.writeJson(historyPath, updated, { spaces: 2 });\n } catch {\n // ignore — history is non-critical\n }\n}\n\n/** Extract numeric score from a review result string (looks for \"Score: X/10\") */\nfunction extractScore(reviewText: string): number {\n const match = reviewText.match(/Score:\\s*(\\d+(?:\\.\\d+)?)\\s*\\/\\s*10/i);\n return match ? parseFloat(match[1]) : 0;\n}\n\n/** Extract top issue lines from a review result (lines starting with - or · under ⚠️ section) */\nfunction extractTopIssues(reviewText: string): string[] {\n const issuesSection = reviewText.match(/##.*?问题.*?\\n([\\s\\S]*?)(?=##|$)/i)?.[1] ?? \"\";\n return issuesSection\n .split(\"\\n\")\n .filter((l) => /^[-·•*]/.test(l.trim()))\n .map((l) => l.replace(/^[-·•*]\\s*/, \"\").trim())\n .filter(Boolean)\n .slice(0, 3);\n}\n\n/** Format recent review history as a context string for Pass 2 */\nfunction buildHistoryContext(history: ReviewHistoryEntry[]): string {\n if (history.length === 0) return \"\";\n const recent = history.slice(-5);\n const lines = [\"\\n=== 历史审查问题 (Past Review Issues — check if any recur) ===\"];\n for (const entry of recent) {\n lines.push(`\\n[${entry.date}] ${path.basename(entry.specFile)} — Score: ${entry.score}/10`);\n entry.topIssues.forEach((issue) => lines.push(` · ${issue}`));\n }\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n// ─── CodeReviewer ─────────────────────────────────────────────────────────────\n\nexport class CodeReviewer {\n constructor(\n private provider: AIProvider,\n private projectRoot: string = process.cwd()\n ) {}\n\n private getGitDiff(): string {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const silent: any = { encoding: \"utf-8\", stdio: \"pipe\" };\n try {\n execSync(\"git rev-parse --is-inside-work-tree\", silent);\n } catch {\n return \"\";\n }\n try {\n let diff: string = execSync(\"git diff --cached\", silent) as string;\n if (!diff.trim()) diff = execSync(\"git diff HEAD\", silent) as string;\n if (!diff.trim()) diff = execSync(\"git diff\", silent) as string;\n return diff;\n } catch {\n return \"\";\n }\n }\n\n private getDiffStats(diff: string): { files: number; added: number; removed: number } {\n const lines = diff.split(\"\\n\");\n return {\n files: lines.filter((l) => l.startsWith(\"diff --git\")).length,\n added: lines.filter((l) => l.startsWith(\"+\") && !l.startsWith(\"+++\")).length,\n removed: lines.filter((l) => l.startsWith(\"-\") && !l.startsWith(\"---\")).length,\n };\n }\n\n /**\n * Two-pass review:\n * Pass 1 — architecture (spec compliance, layer separation, auth)\n * Pass 2 — implementation details (validation, error handling, edge cases)\n * + historical issue recurrence check\n *\n * Falls back to single-pass if the two-pass flag is not set.\n */\n private async runTwoPassReview(\n specContent: string,\n codeContext: string,\n specFile?: string\n ): Promise<string> {\n console.log(chalk.gray(\" Pass 1/2: Architecture review...\"));\n\n // ── Pass 1: Architecture ──────────────────────────────────────────────────\n const archPrompt = `Review the architecture of this change.\n\n=== Feature Spec ===\n${specContent || \"(No spec — review for general code quality)\"}\n\n=== Code ===\n${codeContext}`;\n\n const archReview = await this.provider.generate(archPrompt, reviewArchitectureSystemPrompt);\n console.log(chalk.gray(\" Pass 2/2: Implementation review...\"));\n\n // ── Pass 2: Implementation + History ─────────────────────────────────────\n const history = await loadReviewHistory(this.projectRoot);\n const historyContext = buildHistoryContext(history);\n\n const implPrompt = `Review the implementation details of this change.\n\n=== Feature Spec ===\n${specContent || \"(No spec — review for general code quality)\"}\n\n=== Code ===\n${codeContext}\n\n=== Architecture Review (Pass 1 — do NOT repeat these findings) ===\n${archReview}\n${historyContext}`;\n\n const implReview = await this.provider.generate(implPrompt, reviewImplementationSystemPrompt);\n\n // ── Combine ───────────────────────────────────────────────────────────────\n const combined = `${archReview}\\n\\n${\"─\".repeat(52)}\\n\\n${implReview}`;\n\n // ── Persist history ───────────────────────────────────────────────────────\n const score = extractScore(implReview) || extractScore(archReview);\n const topIssues = extractTopIssues(implReview);\n if (score > 0 && specFile) {\n await appendReviewHistory(this.projectRoot, {\n date: new Date().toISOString().slice(0, 10),\n specFile: path.relative(this.projectRoot, specFile),\n score,\n topIssues,\n });\n }\n\n return combined;\n }\n\n async reviewCode(specContent: string, specFile?: string): Promise<string> {\n console.log(chalk.cyan(\"\\n─── Automated Code Review ───────────────────────\"));\n\n const diff = this.getGitDiff();\n if (!diff.trim()) {\n console.log(\n chalk.yellow(\" No git diff found. Stage or commit changes first, then run review.\")\n );\n console.log(chalk.gray(\" Tip: run `git add .` then `ai-spec review` to review your work.\"));\n return \"No changes\";\n }\n\n const { files, added, removed } = this.getDiffStats(diff);\n console.log(\n chalk.gray(` Diff: ${files} file(s), ${chalk.green(\"+\" + added)} ${chalk.red(\"-\" + removed)}`)\n );\n console.log(\n chalk.blue(` Reviewing with ${this.provider.providerName}/${this.provider.modelName}...`)\n );\n\n const codeContext = diff.slice(0, 10000);\n const reviewResult = await this.runTwoPassReview(specContent, codeContext, specFile);\n\n console.log(chalk.cyan(\"\\n─── Review Result ───────────────────────────────\"));\n console.log(reviewResult);\n console.log(chalk.cyan(\"─────────────────────────────────────────────────\\n\"));\n\n return reviewResult;\n }\n\n /**\n * Review directly from generated file contents (for api mode where git diff is empty).\n */\n async reviewFiles(\n specContent: string,\n filePaths: string[],\n workingDir: string,\n specFile?: string\n ): Promise<string> {\n console.log(chalk.cyan(\"\\n─── Automated Code Review (file-based) ─────────\"));\n console.log(chalk.gray(` Reviewing ${filePaths.length} generated file(s)...`));\n console.log(\n chalk.blue(` Reviewing with ${this.provider.providerName}/${this.provider.modelName}...`)\n );\n\n let filesSection = \"\";\n for (const filePath of filePaths) {\n const fullPath = path.join(workingDir, filePath);\n try {\n const content = await fs.readFile(fullPath, \"utf-8\");\n filesSection += `\\n\\n=== ${filePath} ===\\n${content.slice(0, 3000)}`;\n if (content.length > 3000) filesSection += `\\n... (truncated, ${content.length} chars total)`;\n } catch {\n filesSection += `\\n\\n=== ${filePath} ===\\n(file not found)`;\n }\n }\n\n const reviewResult = await this.runTwoPassReview(specContent, filesSection, specFile);\n\n console.log(chalk.cyan(\"\\n─── Review Result ───────────────────────────────\"));\n console.log(reviewResult);\n console.log(chalk.cyan(\"─────────────────────────────────────────────────\\n\"));\n\n return reviewResult;\n }\n\n /** Print score trend from history (last N reviews) */\n async printScoreTrend(limit = 5): Promise<void> {\n const history = await loadReviewHistory(this.projectRoot);\n if (history.length === 0) {\n console.log(chalk.gray(\" No review history yet.\"));\n return;\n }\n const recent = history.slice(-limit);\n console.log(chalk.cyan(\"\\n─── Review Score Trend ──────────────────────────\"));\n for (const entry of recent) {\n const bar = \"█\".repeat(entry.score) + \"░\".repeat(10 - entry.score);\n const color = entry.score >= 8 ? chalk.green : entry.score >= 6 ? chalk.yellow : chalk.red;\n console.log(` ${entry.date} [${color(bar)}] ${color(entry.score + \"/10\")} ${path.basename(entry.specFile)}`);\n }\n console.log(chalk.cyan(\"─────────────────────────────────────────────────\"));\n }\n}\n","import { execSync } from \"child_process\";\nimport * as path from \"path\";\nimport * as fs from \"fs-extra\";\nimport chalk from \"chalk\";\n\nexport class GitWorktreeManager {\n constructor(private baseDir: string) {}\n\n private isGitRepo(): boolean {\n try {\n execSync(\"git rev-parse --is-inside-work-tree\", { cwd: this.baseDir, stdio: \"ignore\" });\n return true;\n } catch {\n return false;\n }\n }\n\n private sanitizeFeatureName(idea: string): string {\n return idea\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .substring(0, 30) || `feature-${Date.now()}`;\n }\n\n /**\n * Symlink dependency directories from the base repo into the worktree so that\n * tools like `vite`, `tsc`, etc. are available without re-installing.\n *\n * Handles: node_modules (npm/yarn/pnpm), vendor (PHP Composer)\n */\n private async linkDependencies(worktreePath: string): Promise<void> {\n const candidates = [\"node_modules\", \"vendor\"];\n\n for (const dir of candidates) {\n const src = path.join(this.baseDir, dir);\n const dest = path.join(worktreePath, dir);\n\n if (!(await fs.pathExists(src))) continue;\n if (await fs.pathExists(dest)) continue; // already there (or linked)\n\n try {\n await fs.ensureSymlink(src, dest, \"dir\");\n console.log(chalk.gray(` Symlinked ${dir}/ from base repo → worktree`));\n } catch (err) {\n // Non-fatal: symlink may fail on some systems (e.g. cross-device)\n console.log(chalk.yellow(` ⚠ Could not symlink ${dir}/: ${(err as Error).message}`));\n console.log(chalk.yellow(` Run \\`npm install\\` inside the worktree manually.`));\n }\n }\n }\n\n async createWorktree(idea: string): Promise<string | null> {\n if (!this.isGitRepo()) {\n console.log(chalk.yellow(\"⚠️ Not a git repository. Skipping worktree creation.\"));\n return null;\n }\n\n const featureName = this.sanitizeFeatureName(idea);\n const branchName = `feature/${featureName}`;\n const repoName = path.basename(this.baseDir);\n const worktreePath = path.resolve(this.baseDir, \"..\", `${repoName}-${featureName}`);\n\n console.log(chalk.cyan(`\\n--- Setting up Git Worktree ---`));\n\n if (await fs.pathExists(worktreePath)) {\n console.log(chalk.yellow(`⚠️ Worktree directory already exists at: ${worktreePath}`));\n await this.linkDependencies(worktreePath);\n return worktreePath;\n }\n\n try {\n let branchExists = false;\n try {\n execSync(`git show-ref --verify refs/heads/${branchName}`, {\n cwd: this.baseDir,\n stdio: \"ignore\",\n });\n branchExists = true;\n } catch {}\n\n console.log(chalk.gray(`Creating worktree at: ${worktreePath}`));\n\n if (branchExists) {\n execSync(`git worktree add \"${worktreePath}\" ${branchName}`, {\n cwd: this.baseDir,\n stdio: \"inherit\",\n });\n } else {\n execSync(`git worktree add -b ${branchName} \"${worktreePath}\"`, {\n cwd: this.baseDir,\n stdio: \"inherit\",\n });\n }\n\n console.log(\n chalk.green(`✔ Worktree successfully created and isolated on branch '${branchName}'`)\n );\n\n // Link node_modules / vendor so the project can run immediately\n await this.linkDependencies(worktreePath);\n\n return worktreePath;\n } catch (error) {\n console.error(chalk.red(\"Failed to create git worktree:\"), error);\n return null;\n }\n }\n}\n","import chalk from \"chalk\";\nimport * as fs from \"fs-extra\";\nimport * as path from \"path\";\nimport { AIProvider } from \"./spec-generator\";\nimport { ContextLoader, ProjectContext } from \"./context-loader\";\nimport { constitutionSystemPrompt } from \"../prompts/constitution.prompt\";\n\nexport const CONSTITUTION_FILE = \".ai-spec-constitution.md\";\n\nexport class ConstitutionGenerator {\n constructor(private provider: AIProvider) {}\n\n async generate(projectRoot: string): Promise<string> {\n const loader = new ContextLoader(projectRoot);\n const context = await loader.loadProjectContext();\n\n const prompt = buildConstitutionPrompt(context, projectRoot);\n return this.provider.generate(prompt, constitutionSystemPrompt);\n }\n\n async saveConstitution(projectRoot: string, content: string): Promise<string> {\n const filePath = path.join(projectRoot, CONSTITUTION_FILE);\n await fs.writeFile(filePath, content, \"utf-8\");\n return filePath;\n }\n}\n\nfunction buildConstitutionPrompt(context: ProjectContext, projectRoot: string): string {\n const parts: string[] = [\n \"Analyze this project and generate its Project Constitution.\\n\",\n `=== Tech Stack ===\\n${context.techStack.join(\", \") || \"unknown\"}\\n`,\n `=== Dependencies (top 30) ===\\n${context.dependencies.slice(0, 30).join(\", \")}\\n`,\n ];\n\n if (context.apiStructure.length > 0) {\n parts.push(`=== API/Route Files ===\\n${context.apiStructure.join(\"\\n\")}\\n`);\n }\n\n if (context.routeSummary) {\n parts.push(`=== Route Code Samples ===\\n${context.routeSummary}\\n`);\n }\n\n if (context.schema) {\n parts.push(`=== Prisma Schema ===\\n${context.schema.slice(0, 4000)}\\n`);\n }\n\n if (context.errorPatterns) {\n parts.push(`=== Error Handling Patterns ===\\n${context.errorPatterns}\\n`);\n }\n\n if (context.sharedConfigFiles && context.sharedConfigFiles.length > 0) {\n const grouped = context.sharedConfigFiles.reduce(\n (acc, f) => {\n (acc[f.category] ??= []).push(f);\n return acc;\n },\n {} as Record<string, typeof context.sharedConfigFiles>\n );\n\n const sections: string[] = [];\n for (const [category, files] of Object.entries(grouped)) {\n sections.push(`--- ${category} ---`);\n for (const f of files!) {\n sections.push(`File: ${f.path}\\n${f.preview.slice(0, 600)}\\n`);\n }\n }\n parts.push(`=== Existing Shared Config Files (Append-Only — NEVER Recreate) ===\\n${sections.join(\"\\n\")}\\n`);\n }\n\n return parts.join(\"\\n\");\n}\n\nexport async function loadConstitution(projectRoot: string): Promise<string | undefined> {\n const filePath = path.join(projectRoot, CONSTITUTION_FILE);\n if (await fs.pathExists(filePath)) {\n return fs.readFile(filePath, \"utf-8\");\n }\n return undefined;\n}\n\nexport function printConstitutionHint(exists: boolean): void {\n if (!exists) {\n console.log(\n chalk.yellow(\n \" ⚡ Tip: Run `ai-spec init` to generate a Project Constitution for better spec quality.\"\n )\n );\n }\n}\n","export const constitutionSystemPrompt = `You are a Senior Software Architect. Analyze the provided project codebase context and generate a concise \"Project Constitution\" — a living document that captures the architectural rules, conventions, and red lines that ALL future feature specs and code generation MUST follow.\n\nOutput a Markdown document with EXACTLY these sections. Be specific and derive rules directly from the observed codebase — no generic advice.\n\n---\n\n# Project Constitution\n\n## 1. 架构规则 (Architecture Rules)\n列出项目的核心架构模式和强制约束(从代码中提取,而非通用建议)。\n- 分层架构规则(如:routes → controllers → services → DB)\n- 禁止跨层直接调用的规则\n- 模块组织规范\n\n## 2. 命名规范 (Naming Conventions)\n- 文件命名规则(驼峰/下划线/kebab)\n- 变量、函数、类的命名模式\n- 路由路径的命名规范\n\n## 3. API 规范 (API Patterns)\n- 路由前缀规则(如 /api/v1/client/... vs /api/v1/admin/...)\n- 统一响应结构模板(code/message/data 格式)\n- 错误码规范(已有的错误码范围和含义)\n- 认证/鉴权模式(middleware 名称和使用位置)\n\n## 4. 数据层规范 (Data Layer Rules)\n- ORM/数据库访问规则(仅通过 service 层访问?直接用 Prisma/Mongoose?)\n- 已有的数据模型命名规范\n- 事务处理模式\n\n## 5. 错误处理规范 (Error Handling Patterns)\n- 统一错误处理 middleware 的使用规则\n- 错误抛出和捕获的模式\n- 已知错误码列表(从代码中提取)\n\n## 6. 禁区 (Red Lines — Never Violate)\n明确列出绝对不能做的事情(从现有代码/架构推断):\n- [ ] 禁止 ...\n- [ ] 禁止 ...\n\n## 7. 测试规范 (Testing Rules)\n- 测试文件存放位置\n- 必须覆盖的测试场景类型\n- 测试框架和工具\n\n## 8. 共享配置文件清单 (Shared Config Files — Append-Only)\n\nCRITICAL: The following files are **singleton config files** that already exist in the project.\nWhen any feature needs to add entries (translations, constants, routes, enums, etc.), they MUST be\nappended/merged into these existing files. **NEVER create a new parallel file.**\n\nFor each discovered file, list it as:\n- \\`<relative-path>\\` — <category> — **MODIFY ONLY, never recreate**\n\nIf the project context includes i18n/locale files: list ALL of them with their paths.\nIf the project context includes constants/enums files: list ALL of them.\nIf the project context includes route index files: list ALL of them.\nIf none are provided in the context, write: \"(No shared config files detected — will be populated on first run)\"\n\n---\n\nBe concise. Each rule must be specific enough to enforce, not a vague principle.\n**Section 8 is the most important section for preventing file duplication bugs.**`;\n","import chalk from \"chalk\";\nimport * as fs from \"fs-extra\";\nimport * as path from \"path\";\nimport { AIProvider } from \"./spec-generator\";\nimport { CONSTITUTION_FILE } from \"./constitution-generator\";\nimport {\n consolidateSystemPrompt,\n buildConsolidatePrompt,\n parseConstitutionStats,\n ConstitutionStats,\n} from \"../prompts/consolidate.prompt\";\nimport { computeDiff, printDiff, printDiffSummary } from \"./spec-versioning\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface ConsolidateOptions {\n /** Preview the result without writing to disk */\n dryRun?: boolean;\n /** Skip interactive confirmation */\n auto?: boolean;\n /** Minimum number of §9 lessons before consolidation is useful (default: 5) */\n minLessons?: number;\n}\n\nexport interface ConsolidateResult {\n /** Whether the file was actually written */\n written: boolean;\n /** Stats before consolidation */\n before: ConstitutionStats;\n /** Stats after consolidation */\n after: ConstitutionStats;\n /** Path to the backup file */\n backupPath: string | null;\n}\n\n// ─── Threshold Warning ────────────────────────────────────────────────────────\n\n/**\n * Check if §9 has grown past the warning threshold.\n * Call this after appending lessons to warn the user when consolidation is needed.\n */\nexport function checkConsolidationNeeded(\n projectRoot: string,\n lessonCount: number,\n warnAt = 8\n): void {\n if (lessonCount >= warnAt) {\n console.log(\n chalk.yellow(\n `\\n ⚠ §9 has ${lessonCount} accumulated lessons — consider running \\`ai-spec init --consolidate\\` to prune.`\n )\n );\n }\n}\n\n// ─── Consolidator ─────────────────────────────────────────────────────────────\n\nexport class ConstitutionConsolidator {\n constructor(private provider: AIProvider) {}\n\n async consolidate(\n projectRoot: string,\n opts: ConsolidateOptions = {}\n ): Promise<ConsolidateResult> {\n const minLessons = opts.minLessons ?? 5;\n const constitutionPath = path.join(projectRoot, CONSTITUTION_FILE);\n\n // ── Load constitution ───────────────────────────────────────────────────\n if (!(await fs.pathExists(constitutionPath))) {\n throw new Error(`No constitution file found at ${constitutionPath}. Run \\`ai-spec init\\` first.`);\n }\n\n const original = await fs.readFile(constitutionPath, \"utf-8\");\n const before = parseConstitutionStats(original);\n\n console.log(chalk.blue(\"\\n─── Constitution Consolidation ──────────────────\"));\n console.log(chalk.gray(` File : ${CONSTITUTION_FILE}`));\n console.log(chalk.gray(` Size : ${before.totalLines} lines`));\n console.log(chalk.gray(` §9 items: ${before.lessonCount} accumulated lessons`));\n\n if (before.lessonCount < minLessons) {\n console.log(\n chalk.green(\n `\\n ✔ §9 has only ${before.lessonCount} lesson(s) — no consolidation needed yet (threshold: ${minLessons}).`\n )\n );\n return { written: false, before, after: before, backupPath: null };\n }\n\n // ── Generate consolidated version ───────────────────────────────────────\n console.log(chalk.cyan(`\\n Consolidating ${before.lessonCount} lesson(s) with AI...`));\n\n const prompt = buildConsolidatePrompt(original, before.lessonCount);\n let consolidated: string;\n try {\n const raw = await this.provider.generate(prompt, consolidateSystemPrompt);\n // Strip markdown fences if present\n consolidated = raw\n .replace(/^```(?:markdown|md)?\\n?/im, \"\")\n .replace(/\\n?```\\s*$/im, \"\")\n .trim();\n } catch (err) {\n throw new Error(`AI consolidation failed: ${(err as Error).message}`);\n }\n\n const after = parseConstitutionStats(consolidated);\n\n // ── Show diff ───────────────────────────────────────────────────────────\n const diff = computeDiff(original, consolidated);\n console.log(chalk.blue(\"\\n Changes preview:\"));\n printDiff(diff, 4);\n printDiffSummary(diff);\n\n console.log(chalk.cyan(\"\\n After consolidation:\"));\n console.log(chalk.gray(` Size : ${after.totalLines} lines (was ${before.totalLines})`));\n console.log(chalk.gray(` §9 items: ${after.lessonCount} remaining (was ${before.lessonCount})`));\n\n const liftedCount = Math.max(0, before.lessonCount - after.lessonCount);\n if (liftedCount > 0) {\n console.log(chalk.green(` ✔ ~${liftedCount} lesson(s) lifted into §1–§8 or removed`));\n }\n\n if (opts.dryRun) {\n console.log(chalk.yellow(\"\\n [dry-run] No changes written.\"));\n return { written: false, before, after, backupPath: null };\n }\n\n // ── Backup ──────────────────────────────────────────────────────────────\n const timestamp = new Date().toISOString().slice(0, 19).replace(/[T:]/g, \"-\");\n const backupName = `.ai-spec-constitution.backup-${timestamp}.md`;\n const backupPath = path.join(projectRoot, backupName);\n await fs.writeFile(backupPath, original, \"utf-8\");\n console.log(chalk.gray(`\\n Backup : ${backupName}`));\n\n // ── Write ───────────────────────────────────────────────────────────────\n await fs.writeFile(constitutionPath, consolidated, \"utf-8\");\n console.log(chalk.green(` ✔ Constitution updated: ${CONSTITUTION_FILE}`));\n\n return { written: true, before, after, backupPath };\n }\n}\n","// ─── System Prompt ────────────────────────────────────────────────────────────\n\nexport const consolidateSystemPrompt = `You are a Principal Engineer maintaining a living \"Project Constitution\" document.\n\nThe constitution has sections §1–§8 (core rules) and §9 (accumulated lessons from code reviews).\nYour job is to perform a \"constitution rebase\": consolidate §9 lessons into the core sections, producing a leaner, more precise document.\n\nRules:\n1. READ §9 carefully. For each lesson, decide:\n a. LIFT — The lesson is a general, durable rule. Merge it into the appropriate §1–§8 section.\n b. KEEP — The lesson is specific, recent, and not yet generalizable. Keep it in §9.\n c. DROP — The lesson is a duplicate, already covered by an existing rule, or no longer relevant.\n\n2. When LIFTING a lesson:\n - Integrate it naturally into the target section's existing list of rules.\n - Rephrase it as a prescriptive rule (\"Always do X\", \"Never do Y\"), not a past-tense observation.\n - Do NOT add a \"(lifted from §9)\" annotation.\n\n3. When KEEPING lessons in §9:\n - Remove duplicates (keep the most specific/recent version).\n - Keep at most the 5 most recent, unique, not-yet-generalizable lessons.\n\n4. When DROPPING a lesson:\n - Only drop if it is clearly covered elsewhere or obviously outdated.\n\n5. Preserve all §1–§8 content that is NOT being modified. Do not remove or rewrite sections unless adding lifted lessons.\n\n6. Output the COMPLETE updated constitution in Markdown. All original section headings must be present.\n7. Do NOT add any meta-commentary, changelog, or \"consolidation note\" inside the document.`;\n\n// ─── User Prompt ──────────────────────────────────────────────────────────────\n\nexport function buildConsolidatePrompt(\n constitutionContent: string,\n lessonCount: number\n): string {\n return `The Project Constitution below has ${lessonCount} accumulated lesson(s) in §9.\nConsolidate: lift durable lessons into §1–§8, remove duplicates, keep only the most recent unique lessons in §9 (max 5).\n\n=== Current Constitution ===\n${constitutionContent}\n\nOutput the complete updated constitution.`;\n}\n\n// ─── Stats Helper ─────────────────────────────────────────────────────────────\n\nexport interface ConstitutionStats {\n totalLines: number;\n section9Lines: number;\n lessonCount: number;\n}\n\nexport function parseConstitutionStats(content: string): ConstitutionStats {\n const lines = content.split(\"\\n\");\n const totalLines = lines.length;\n\n const section9Start = lines.findIndex((l) => l.includes(\"## 9.\") || l.includes(\"## §9\"));\n if (section9Start === -1) {\n return { totalLines, section9Lines: 0, lessonCount: 0 };\n }\n\n // Count section 9 lines until next ## or EOF\n let section9Lines = 0;\n let lessonCount = 0;\n for (let i = section9Start + 1; i < lines.length; i++) {\n if (lines[i].match(/^## \\d/) && i > section9Start) break;\n section9Lines++;\n if (lines[i].trim().startsWith(\"-\")) lessonCount++;\n }\n\n return { totalLines, section9Lines, lessonCount };\n}\n","/**\n * combined-generator.ts\n *\n * Generates Spec + Tasks in a single AI call instead of two sequential calls.\n * Avoids the circular-dependency that would arise if spec-generator.ts imported\n * from task-generator.ts (which already imports AIProvider from spec-generator).\n */\n\nimport { AIProvider } from \"./spec-generator\";\nimport { ProjectContext } from \"./context-loader\";\nimport { SpecTask, buildTaskPrompt } from \"./task-generator\";\nimport { specPrompt } from \"../prompts/spec.prompt\";\n\nconst TASKS_SEPARATOR = \"---TASKS_JSON---\";\n\n// Appended to specPrompt so the AI outputs spec + tasks in one response.\nconst tasksInstruction = `\n\n---\nAfter outputting the complete spec above, append EXACTLY this line on its own (no extra text before or after it):\n${TASKS_SEPARATOR}\nThen output a valid JSON array of implementation tasks. Each element must have these exact fields:\n{\"id\":\"TASK-001\",\"title\":\"...\",\"description\":\"1-2 sentences, specific\",\"layer\":\"data|infra|service|api|test\",\"filesToTouch\":[\"src/...\"],\"acceptanceCriteria\":[\"verifiable condition\"],\"dependencies\":[],\"priority\":\"high|medium|low\"}\nLayer order: data → infra → service → api → test. 4-10 tasks total. filesToTouch must use real paths from the project context.`;\n\nexport async function generateSpecWithTasks(\n provider: AIProvider,\n idea: string,\n context?: ProjectContext\n): Promise<{ spec: string; tasks: SpecTask[] }> {\n // Use buildTaskPrompt to get the full verified-inventory context,\n // then prepend the idea so the spec generator also sees it.\n const contextBlock = buildTaskPrompt(\"\", context).trim();\n const fullPrompt = [idea, contextBlock].filter(Boolean).join(\"\\n\\n\");\n\n const combinedSystemPrompt = specPrompt + tasksInstruction;\n const raw = await provider.generate(fullPrompt, combinedSystemPrompt);\n return parseSpecAndTasks(raw);\n}\n\nfunction parseSpecAndTasks(raw: string): { spec: string; tasks: SpecTask[] } {\n const sepIdx = raw.indexOf(TASKS_SEPARATOR);\n\n if (sepIdx === -1) {\n // AI didn't output the separator — return full response as spec, no tasks\n return { spec: raw.trim(), tasks: [] };\n }\n\n const spec = raw.slice(0, sepIdx).trim();\n const tasksRaw = raw.slice(sepIdx + TASKS_SEPARATOR.length).trim();\n\n let tasks: SpecTask[] = [];\n try {\n const jsonMatch = tasksRaw.match(/\\[[\\s\\S]*\\]/);\n if (jsonMatch) {\n tasks = JSON.parse(jsonMatch[0]);\n }\n } catch {\n // Parse failed, return empty tasks — caller handles gracefully\n }\n\n return { spec, tasks };\n}\n","import chalk from \"chalk\";\nimport * as fs from \"fs-extra\";\nimport * as path from \"path\";\nimport { AIProvider } from \"./spec-generator\";\nimport { SpecDSL } from \"./dsl-types\";\nimport { testGenSystemPrompt, testGenFrontendSystemPrompt, tddTestGenSystemPrompt } from \"../prompts/testgen.prompt\";\nimport { loadFrontendContext, FrontendContext } from \"./frontend-context-loader\";\nimport { FRONTEND_FRAMEWORKS } from \"./context-loader\";\n\n// ─── Prompt builders ──────────────────────────────────────────────────────────\n\nfunction buildBackendTestGenPrompt(dsl: SpecDSL, testDir: string): string {\n const lines: string[] = [\n `Generate test skeleton files for the \"${dsl.feature.title}\" feature.`,\n `Test files should be placed under: ${testDir}\\n`,\n ];\n\n if (dsl.models.length > 0) {\n lines.push(\"=== Data Models ===\");\n for (const m of dsl.models) {\n lines.push(`${m.name}:`);\n for (const f of m.fields) {\n const flags = [f.required ? \"required\" : \"\", f.unique ? \"unique\" : \"\"].filter(Boolean).join(\", \");\n lines.push(` ${f.name}: ${f.type}${flags ? ` (${flags})` : \"\"}`);\n }\n }\n lines.push(\"\");\n }\n\n if (dsl.endpoints.length > 0) {\n lines.push(\"=== API Endpoints ===\");\n for (const ep of dsl.endpoints) {\n lines.push(`${ep.id}: ${ep.method} ${ep.path} [auth: ${ep.auth}] → ${ep.successStatus}`);\n lines.push(` ${ep.description}`);\n if (ep.request?.body) {\n const fields = Object.entries(ep.request.body).map(([k, v]) => `${k}: ${v}`).join(\", \");\n lines.push(` body: { ${fields} }`);\n }\n if (ep.errors && ep.errors.length > 0) {\n lines.push(` errors: ${ep.errors.map((e) => `${e.status} ${e.code}`).join(\", \")}`);\n }\n }\n lines.push(\"\");\n }\n\n if (dsl.behaviors.length > 0) {\n lines.push(\"=== Business Behaviors (include edge-case tests for these) ===\");\n for (const b of dsl.behaviors) {\n lines.push(`- ${b.description}`);\n if (b.constraints) lines.push(` rules: ${b.constraints.join(\"; \")}`);\n }\n lines.push(\"\");\n }\n\n lines.push(\n \"Generate one test file per logical module (e.g. one for API routes, one for service/model tests).\",\n 'Output a JSON array of {\"file\": \"path\", \"content\": \"full test file source\"}.'\n );\n\n return lines.join(\"\\n\");\n}\n\nfunction buildFrontendTestGenPrompt(dsl: SpecDSL, testDir: string, ctx: FrontendContext): string {\n const lines: string[] = [\n `Generate test skeleton files for the \"${dsl.feature.title}\" frontend feature.`,\n `Test framework : ${ctx.testFramework}`,\n `Test files should be placed under: ${testDir}\\n`,\n ];\n\n // Component specs (primary for frontend)\n if (dsl.components && dsl.components.length > 0) {\n lines.push(\"=== Component Specs ===\");\n for (const cmp of dsl.components) {\n lines.push(`${cmp.id}: ${cmp.name} — ${cmp.description}`);\n if (cmp.props.length > 0) {\n lines.push(` props: ${cmp.props.map((p) => `${p.name}${p.required ? \"\" : \"?\"}: ${p.type}`).join(\", \")}`);\n }\n if (cmp.events.length > 0) {\n lines.push(` events: ${cmp.events.map((e) => `${e.name}(${e.payload ?? \"\"})`).join(\", \")}`);\n }\n if (Object.keys(cmp.state).length > 0) {\n lines.push(` state: ${Object.entries(cmp.state).map(([k, v]) => `${k}: ${v}`).join(\", \")}`);\n }\n if (cmp.apiCalls.length > 0) {\n lines.push(` api calls: ${cmp.apiCalls.join(\", \")}`);\n }\n }\n lines.push(\"\");\n }\n\n // Endpoints (for API hook tests)\n if (dsl.endpoints.length > 0) {\n lines.push(\"=== API Endpoints (write hook/service tests for these) ===\");\n for (const ep of dsl.endpoints) {\n lines.push(`${ep.id}: ${ep.method} ${ep.path} [auth: ${ep.auth}] → ${ep.successStatus}`);\n if (ep.errors && ep.errors.length > 0) {\n lines.push(` errors: ${ep.errors.map((e) => `${e.status} ${e.code}`).join(\", \")}`);\n }\n }\n lines.push(\"\");\n }\n\n // Existing hooks (to import from)\n if (ctx.hookFiles.length > 0) {\n lines.push(\"=== Existing custom hooks (import from these, don't create duplicates) ===\");\n ctx.hookFiles.forEach((f) => lines.push(` - ${f}`));\n lines.push(\"\");\n }\n\n // Existing API wrappers\n if (ctx.apiWrapperContent.length > 0) {\n lines.push(\"=== Existing API wrappers (reference these call patterns) ===\");\n ctx.apiWrapperContent.forEach((c) => {\n lines.push(\"```\");\n lines.push(c.slice(0, 400));\n lines.push(\"```\");\n });\n lines.push(\"\");\n }\n\n lines.push(\n \"Generate test files: one per component (RTL) and one for API hooks/services.\",\n 'Output a JSON array of {\"file\": \"path\", \"content\": \"full source\"}.'\n );\n\n return lines.join(\"\\n\");\n}\n\n// ─── Parser ───────────────────────────────────────────────────────────────────\n\ninterface TestFileResult {\n file: string;\n content: string;\n}\n\nfunction parseTestFiles(raw: string): TestFileResult[] {\n const fenced = raw.match(/```(?:json)?\\n(\\[[\\s\\S]*?\\])\\n```/);\n const jsonStr = fenced ? fenced[1] : (raw.match(/\\[[\\s\\S]*\\]/)?.[0] ?? \"\");\n try {\n const parsed = JSON.parse(jsonStr);\n if (Array.isArray(parsed)) return parsed as TestFileResult[];\n } catch {\n // fall through\n }\n return [];\n}\n\n// ─── Frontend detection ───────────────────────────────────────────────────────\n\nasync function isFrontendProject(workingDir: string): Promise<boolean> {\n const pkgPath = path.join(workingDir, \"package.json\");\n if (!(await fs.pathExists(pkgPath))) return false;\n try {\n const pkg = await fs.readJson(pkgPath);\n const deps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };\n const keys = Object.keys(deps);\n return keys.some((k) => (FRONTEND_FRAMEWORKS as readonly string[]).includes(k));\n } catch {\n return false;\n }\n}\n\n// ─── TestGenerator ────────────────────────────────────────────────────────────\n\nexport class TestGenerator {\n constructor(private provider: AIProvider) {}\n\n /**\n * Generate test skeleton files from a validated DSL.\n * Automatically detects frontend vs backend and uses the appropriate template.\n * Returns the list of test file paths written.\n */\n async generate(dsl: SpecDSL, workingDir: string): Promise<string[]> {\n console.log(chalk.blue(\"\\n─── Test Generation ─────────────────────────────\"));\n\n const testDir = await this.detectTestDir(workingDir);\n const frontend = await isFrontendProject(workingDir);\n\n let prompt: string;\n let systemPrompt: string;\n\n if (frontend) {\n const ctx = await loadFrontendContext(workingDir);\n console.log(chalk.gray(` Mode: frontend (${ctx.framework} / ${ctx.testFramework})`));\n console.log(chalk.gray(` Test directory: ${testDir}`));\n prompt = buildFrontendTestGenPrompt(dsl, testDir, ctx);\n systemPrompt = testGenFrontendSystemPrompt;\n } else {\n console.log(chalk.gray(` Mode: backend`));\n console.log(chalk.gray(` Test directory: ${testDir}`));\n prompt = buildBackendTestGenPrompt(dsl, testDir);\n systemPrompt = testGenSystemPrompt;\n }\n\n let rawOutput: string;\n try {\n rawOutput = await this.provider.generate(prompt, systemPrompt);\n } catch (err) {\n console.log(chalk.yellow(` ⚠ Test generation AI call failed: ${(err as Error).message}`));\n return [];\n }\n\n const testFiles = parseTestFiles(rawOutput);\n if (testFiles.length === 0) {\n console.log(chalk.yellow(\" ⚠ Could not parse test files from AI output. Skipping.\"));\n return [];\n }\n\n const writtenFiles: string[] = [];\n for (const tf of testFiles) {\n const fullPath = path.join(workingDir, tf.file);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, tf.content, \"utf-8\");\n console.log(chalk.green(` + ${tf.file}`));\n writtenFiles.push(tf.file);\n }\n\n console.log(chalk.green(` ✔ ${writtenFiles.length} test file(s) generated.`));\n return writtenFiles;\n }\n\n /**\n * TDD mode: generate test files with real assertions BEFORE the implementation exists.\n * These tests will initially fail — the error feedback loop drives implementation to pass them.\n * Only supports backend projects (uses supertest + DSL endpoints/models).\n */\n async generateTdd(dsl: SpecDSL, workingDir: string): Promise<string[]> {\n console.log(chalk.blue(\"\\n─── TDD Test Generation (pre-implementation) ────\"));\n\n const testDir = await this.detectTestDir(workingDir);\n console.log(chalk.gray(` Mode: TDD (real assertions — tests will fail until implementation is complete)`));\n console.log(chalk.gray(` Test directory: ${testDir}`));\n\n const prompt = buildBackendTestGenPrompt(dsl, testDir);\n\n let rawOutput: string;\n try {\n rawOutput = await this.provider.generate(prompt, tddTestGenSystemPrompt);\n } catch (err) {\n console.log(chalk.yellow(` ⚠ TDD test generation failed: ${(err as Error).message}`));\n return [];\n }\n\n const testFiles = parseTestFiles(rawOutput);\n if (testFiles.length === 0) {\n console.log(chalk.yellow(\" ⚠ Could not parse TDD test files from AI output. Skipping.\"));\n return [];\n }\n\n const writtenFiles: string[] = [];\n for (const tf of testFiles) {\n const fullPath = path.join(workingDir, tf.file);\n await fs.ensureDir(path.dirname(fullPath));\n await fs.writeFile(fullPath, tf.content, \"utf-8\");\n console.log(chalk.green(` + ${tf.file}`));\n writtenFiles.push(tf.file);\n }\n\n console.log(\n chalk.green(` ✔ ${writtenFiles.length} TDD test file(s) written.`) +\n chalk.gray(\" (expected to fail — implementation will make them pass)\")\n );\n return writtenFiles;\n }\n\n private async detectTestDir(workingDir: string): Promise<string> {\n const candidates = [\"tests\", \"test\", \"__tests__\", \"src/__tests__\", \"spec\"];\n for (const c of candidates) {\n if (await fs.pathExists(path.join(workingDir, c))) return c;\n }\n return \"tests\";\n }\n}\n","export const testGenSystemPrompt = `You are a Senior QA Engineer generating test skeletons for a Node.js/TypeScript project.\n\nRules:\n1. Output ONLY a JSON array — no markdown fences, no explanations outside the JSON\n2. Generate test files using the project's existing test framework (Jest or Vitest)\n3. Each test file must import the module under test and follow existing test patterns\n4. Generate describe/it blocks with meaningful test names — do NOT implement assertions, use placeholder comments\n5. Cover: happy path, validation errors, auth checks, edge cases per the DSL\n6. For each endpoint, generate at least: one success test, one validation error test, one auth test (if auth=true)\n7. For each model, generate at least: one creation test, one unique constraint test (if unique fields exist)\n8. Keep test structure flat — max 2 levels of describe nesting\n9. Use relative imports matching the project structure\n10. Output format: JSON array of {\"file\": \"relative/path\", \"content\": \"full source\"}`;\n\n// ─── TDD Test Generation (real assertions, not skeletons) ─────────────────────\n\n/**\n * TDD mode: generate tests with REAL assertions based on the DSL.\n * These tests are written BEFORE implementation and are expected to fail initially.\n * The error feedback loop then drives the implementation to make them pass.\n */\nexport const tddTestGenSystemPrompt = `You are a Senior QA Engineer writing TDD tests for a Node.js/TypeScript project.\n\nThese tests are written BEFORE the implementation exists. They MUST:\n1. Have real, executable assertions — NO \"TODO\" comments, NO placeholder stubs\n2. Be runnable immediately (they should FAIL with \"module not found\" or assertion errors, not syntax errors)\n3. Use supertest for HTTP endpoint tests, or direct function imports for service/unit tests\n4. Cover: happy path, validation errors (400), auth errors (401/403), not-found (404)\n\nRules:\n1. Output ONLY a JSON array — no markdown fences, no explanations outside the JSON\n2. Generate test files using the project's existing test framework (Jest or Vitest)\n3. Use supertest for endpoint integration tests: import request from 'supertest'; import app from '../src/app'\n4. For each endpoint:\n - Success case: correct request → assert status + response shape (e.g. expect(res.body.data.id).toBeDefined())\n - Validation error: missing/invalid field → assert 400 + correct error code\n - Auth test (if auth=true): missing token → assert 401\n5. For each model with unique fields: test that duplicate creation returns 409 or the project's conflict code\n6. Assert specific fields and codes from the DSL — never use \"expect(res.status).not.toBe(500)\" as a substitute\n7. Use beforeAll/afterAll for test setup/teardown if needed\n8. Keep test structure flat — max 2 levels of describe nesting\n9. Use relative imports matching the project structure\n10. Output format: JSON array of {\"file\": \"relative/path\", \"content\": \"full source\"}\n\nExample of a CORRECT TDD test (with real assertions):\n\\`\\`\\`\nit('POST /api/v1/tasks → 201 with task data', async () => {\n const res = await request(app)\n .post('/api/v1/tasks')\n .set('Authorization', 'Bearer test-token')\n .send({ title: 'My task', status: 'todo', dueDate: '2026-12-31' });\n expect(res.status).toBe(201);\n expect(res.body.code).toBe(0);\n expect(res.body.data).toMatchObject({ title: 'My task', status: 'todo' });\n expect(res.body.data.id).toBeDefined();\n});\n\nit('POST /api/v1/tasks → 400 MISSING_FIELD when title absent', async () => {\n const res = await request(app)\n .post('/api/v1/tasks')\n .set('Authorization', 'Bearer test-token')\n .send({ status: 'todo' });\n expect(res.status).toBe(400);\n expect(res.body.code).toBe('MISSING_FIELD');\n});\n\\`\\`\\``;\n\nexport const testGenFrontendSystemPrompt = `You are a Senior Frontend QA Engineer generating test skeletons for a React/Vue/Next.js project.\n\nRules:\n1. Output ONLY a JSON array — no markdown fences, no explanations outside the JSON\n2. Use React Testing Library (@testing-library/react) for component tests unless the project uses Cypress, in which case generate Cypress spec files\n3. Generate describe/it (or describe/test) blocks with meaningful names — do NOT implement assertions, use TODO comments\n4. For each component spec (CMP-*):\n - One render test: \"renders without crashing\"\n - One prop test per required prop: \"renders correctly with <prop>\"\n - One interaction test per event: \"calls <handler> when <action>\"\n - One loading state test if the component has async API calls\n5. For API call tests, test the custom hook if present, not the component directly\n6. Optimistic update flows: add a test for the rollback case (simulate server error)\n7. For throttle/debounce: add a test that verifies the delay behavior with jest.useFakeTimers()\n8. Keep test structure flat — max 2 levels of describe nesting\n9. Use relative imports matching project structure — import from existing hook/service files\n10. Output format: JSON array of {\"file\": \"relative/path\", \"content\": \"full source\"}`;\n","import chalk from \"chalk\";\nimport { execSync } from \"child_process\";\nimport * as fs from \"fs-extra\";\nimport * as path from \"path\";\nimport { AIProvider } from \"./spec-generator\";\nimport { getCodeGenSystemPrompt } from \"../prompts/codegen.prompt\";\nimport { SpecDSL } from \"./dsl-types\";\nimport { buildDslContextSection } from \"./dsl-extractor\";\n\n// ─── Types ──────────────────────────────────────────────────────────────────────\n\ninterface ErrorEntry {\n source: \"test\" | \"lint\" | \"build\";\n message: string;\n file?: string;\n}\n\ninterface FixResult {\n fixed: boolean;\n file: string;\n explanation: string;\n}\n\n// ─── Error Detection ────────────────────────────────────────────────────────────\n\nfunction runCommand(cmd: string, cwd: string): { success: boolean; output: string } {\n try {\n const output = execSync(cmd, { cwd, encoding: \"utf-8\", timeout: 60_000 });\n return { success: true, output };\n } catch (err) {\n const e = err as { stdout?: string; stderr?: string; message?: string };\n return { success: false, output: e.stdout || e.stderr || e.message || \"\" };\n }\n}\n\n/**\n * Detect TypeScript type-check command for the given directory.\n * Returns null for non-TS projects or projects without tsconfig.\n */\nfunction detectBuildCommand(workingDir: string): string | null {\n // Only applies to Node.js / frontend TypeScript projects\n if (!fs.existsSync(path.join(workingDir, \"tsconfig.json\"))) return null;\n\n // vue-tsc for Vue projects (catches template type errors too)\n const pkgPath = path.join(workingDir, \"package.json\");\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };\n if (allDeps[\"vue-tsc\"]) return \"npx vue-tsc --noEmit\";\n // If there's a type-check or tsc script, prefer it\n if (pkg.scripts?.[\"type-check\"]) return \"npm run type-check\";\n if (pkg.scripts?.[\"typecheck\"]) return \"npm run typecheck\";\n } catch {\n // ignore\n }\n\n return \"npx tsc --noEmit\";\n}\n\nfunction detectTestCommand(workingDir: string): string | null {\n // ── Go ──────────────────────────────────────────────────────────────────────\n if (fs.existsSync(path.join(workingDir, \"go.mod\"))) return \"go test ./...\";\n\n // ── PHP (Lumen / Laravel) ───────────────────────────────────────────────────\n if (fs.existsSync(path.join(workingDir, \"composer.json\"))) {\n return fs.existsSync(path.join(workingDir, \"vendor\", \"bin\", \"phpunit\"))\n ? \"./vendor/bin/phpunit --colors=never\"\n : \"php artisan test --no-ansi\";\n }\n\n // ── Rust ────────────────────────────────────────────────────────────────────\n if (fs.existsSync(path.join(workingDir, \"Cargo.toml\"))) return \"cargo test\";\n\n // ── Java (Maven / Gradle) ───────────────────────────────────────────────────\n if (fs.existsSync(path.join(workingDir, \"pom.xml\"))) return \"mvn test -q\";\n if (\n fs.existsSync(path.join(workingDir, \"build.gradle\")) ||\n fs.existsSync(path.join(workingDir, \"build.gradle.kts\"))\n ) {\n return \"./gradlew test\";\n }\n\n // ── Python ──────────────────────────────────────────────────────────────────\n if (\n fs.existsSync(path.join(workingDir, \"requirements.txt\")) ||\n fs.existsSync(path.join(workingDir, \"pyproject.toml\")) ||\n fs.existsSync(path.join(workingDir, \"setup.py\"))\n ) {\n return \"pytest\";\n }\n\n // ── Node.js ──────────────────────────────────────────────────────────────────\n const pkgPath = path.join(workingDir, \"package.json\");\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n if (pkg.scripts?.test) return \"npm test\";\n if (pkg.scripts?.vitest) return \"npx vitest run\";\n } catch {\n // no package.json\n }\n for (const f of [\"vitest.config.ts\", \"vitest.config.js\", \"jest.config.ts\", \"jest.config.js\"]) {\n if (fs.existsSync(path.join(workingDir, f))) {\n return f.startsWith(\"vitest\") ? \"npx vitest run\" : \"npx jest --forceExit\";\n }\n }\n return null;\n}\n\nfunction detectLintCommand(workingDir: string): string | null {\n // ── Go ──────────────────────────────────────────────────────────────────────\n if (fs.existsSync(path.join(workingDir, \"go.mod\"))) {\n // golangci-lint is optional; fall back to go vet\n return \"go vet ./...\";\n }\n\n // ── PHP (Lumen / Laravel) ───────────────────────────────────────────────────\n if (fs.existsSync(path.join(workingDir, \"composer.json\"))) {\n return fs.existsSync(path.join(workingDir, \"vendor\", \"bin\", \"phpstan\"))\n ? \"./vendor/bin/phpstan analyse --no-progress --memory-limit=512M\"\n : null;\n }\n\n // ── Rust ────────────────────────────────────────────────────────────────────\n if (fs.existsSync(path.join(workingDir, \"Cargo.toml\"))) return \"cargo clippy -- -D warnings\";\n\n // ── Java — no universal lint, skip ──────────────────────────────────────────\n if (\n fs.existsSync(path.join(workingDir, \"pom.xml\")) ||\n fs.existsSync(path.join(workingDir, \"build.gradle\"))\n ) {\n return null;\n }\n\n // ── Python ──────────────────────────────────────────────────────────────────\n if (\n fs.existsSync(path.join(workingDir, \"requirements.txt\")) ||\n fs.existsSync(path.join(workingDir, \"pyproject.toml\")) ||\n fs.existsSync(path.join(workingDir, \"setup.py\"))\n ) {\n // Prefer ruff if available, fall back to flake8\n return \"ruff check . || flake8 .\";\n }\n\n // ── Node.js ──────────────────────────────────────────────────────────────────\n const pkgPath = path.join(workingDir, \"package.json\");\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n if (pkg.scripts?.lint) return \"npm run lint\";\n } catch {\n // ignore\n }\n if (\n fs.existsSync(path.join(workingDir, \".eslintrc\")) ||\n fs.existsSync(path.join(workingDir, \".eslintrc.js\")) ||\n fs.existsSync(path.join(workingDir, \".eslintrc.json\")) ||\n fs.existsSync(path.join(workingDir, \"eslint.config.js\"))\n ) {\n return \"npx eslint . --max-warnings=0\";\n }\n return null;\n}\n\nfunction parseErrors(output: string, source: ErrorEntry[\"source\"]): ErrorEntry[] {\n const errors: ErrorEntry[] = [];\n if (!output.trim()) return errors;\n\n // Take the last 80 lines — most relevant error output\n const lines = output.split(\"\\n\").slice(-80);\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n // Filter noise: skip npm timing, node warnings, stack traces to node_modules\n if (trimmed.startsWith(\"npm timing\")) continue;\n if (trimmed.includes(\"node_modules\")) continue;\n if (trimmed.startsWith(\"at \")) continue;\n if (trimmed.startsWith(\"Node.js \")) continue;\n\n // Try to extract file path (supports TS/JS, Go, Python, Java, Rust, PHP)\n const fileMatch = trimmed.match(/^([^:]+\\.(?:ts|js|tsx|jsx|go|py|java|rs|php)):\\d+/);\n errors.push({\n source,\n message: trimmed.slice(0, 300),\n file: fileMatch?.[1],\n });\n }\n\n return errors.slice(0, 20); // cap at 20 errors\n}\n\n// ─── Auto-Fix ───────────────────────────────────────────────────────────────────\n\nasync function attemptFix(\n provider: AIProvider,\n errors: ErrorEntry[],\n workingDir: string,\n dsl?: SpecDSL | null\n): Promise<FixResult[]> {\n const results: FixResult[] = [];\n\n // Group errors by file (fix one file at a time)\n const errorsByFile = new Map<string, ErrorEntry[]>();\n for (const err of errors) {\n const file = err.file || \"(unknown)\";\n if (!errorsByFile.has(file)) errorsByFile.set(file, []);\n errorsByFile.get(file)!.push(err);\n }\n\n for (const [file, fileErrors] of errorsByFile) {\n const fullPath = path.join(workingDir, file);\n let existingContent = \"\";\n try {\n existingContent = await fs.readFile(fullPath, \"utf-8\");\n } catch {\n results.push({ fixed: false, file, explanation: \"File not found — cannot auto-fix.\" });\n continue;\n }\n\n const dslSection = dsl ? `\\n${buildDslContextSection(dsl)}\\n` : \"\";\n const errorSummary = fileErrors.map((e) => `[${e.source}] ${e.message}`).join(\"\\n\");\n\n const prompt = `Fix the following errors in the file.\n\nFile: ${file}\n${dslSection}\n=== Errors ===\n${errorSummary}\n\n=== Current File Content ===\n${existingContent}\n\nOutput ONLY the complete fixed file content. No markdown fences, no explanations.`;\n\n try {\n const raw = await provider.generate(prompt, getCodeGenSystemPrompt());\n const fixed = raw.replace(/^```\\w*\\n?/gm, \"\").replace(/\\n?```$/gm, \"\").trim();\n await fs.writeFile(fullPath, fixed, \"utf-8\");\n results.push({ fixed: true, file, explanation: `Fixed ${fileErrors.length} error(s)` });\n console.log(chalk.green(` ✔ Auto-fixed: ${file}`));\n } catch (err) {\n results.push({ fixed: false, file, explanation: `AI fix failed: ${(err as Error).message}` });\n console.log(chalk.yellow(` ⚠ Could not auto-fix: ${file}`));\n }\n }\n\n return results;\n}\n\n// ─── Public API ─────────────────────────────────────────────────────────────────\n\nexport interface ErrorFeedbackOptions {\n /** Max fix-verify cycles (default: 2) */\n maxCycles?: number;\n /** Whether to skip test runs (--auto mode may want to skip for speed) */\n skipTests?: boolean;\n /** Whether to skip lint runs */\n skipLint?: boolean;\n /** Whether to skip TypeScript type-check (tsc --noEmit / vue-tsc --noEmit) */\n skipBuild?: boolean;\n}\n\n/**\n * Run error feedback loop: detect errors → auto-fix → re-verify.\n * Returns true if all checks pass after fixes, false if errors remain.\n */\nexport async function runErrorFeedback(\n provider: AIProvider,\n workingDir: string,\n dsl?: SpecDSL | null,\n opts: ErrorFeedbackOptions = {}\n): Promise<boolean> {\n const maxCycles = opts.maxCycles ?? 2;\n\n console.log(chalk.blue(\"\\n─── Error Feedback ──────────────────────────────\"));\n\n const testCmd = opts.skipTests ? null : detectTestCommand(workingDir);\n const lintCmd = opts.skipLint ? null : detectLintCommand(workingDir);\n const buildCmd = opts.skipBuild ? null : detectBuildCommand(workingDir);\n\n if (!testCmd && !lintCmd && !buildCmd) {\n console.log(chalk.gray(\" No test / lint / type-check commands detected. Skipping error feedback.\"));\n return true;\n }\n\n if (buildCmd) console.log(chalk.gray(` Type-check: ${buildCmd}`));\n\n for (let cycle = 1; cycle <= maxCycles; cycle++) {\n const allErrors: ErrorEntry[] = [];\n\n // ── TypeScript type-check (fast, runs before tests) ──────────────────────\n if (buildCmd) {\n console.log(chalk.gray(`\\n [cycle ${cycle}/${maxCycles}] Type-check: ${buildCmd}`));\n const buildResult = runCommand(buildCmd, workingDir);\n if (!buildResult.success) {\n // Detect tool crash (ReferenceError / TypeError inside node_modules) —\n // this means the type-check tool itself is broken (e.g. vue-tsc version\n // incompatibility), NOT a user code error. Skip silently instead of\n // feeding garbage into the auto-fix loop.\n const isToolCrash =\n /ReferenceError:|TypeError:|SyntaxError:/.test(buildResult.output) &&\n buildResult.output.includes(\"node_modules\");\n if (isToolCrash) {\n console.log(chalk.yellow(` ⚠ Type-check tool crashed (possible version incompatibility). Skipping.`));\n console.log(chalk.gray(` Tip: run \\`${buildCmd}\\` manually to investigate.`));\n } else {\n const buildErrors = parseErrors(buildResult.output, \"build\");\n allErrors.push(...buildErrors);\n console.log(chalk.yellow(` ✘ Type errors (${buildErrors.length} captured)`));\n }\n } else {\n console.log(chalk.green(\" ✔ Type-check passed.\"));\n }\n }\n\n // Run tests\n if (testCmd) {\n console.log(chalk.gray(`\\n [cycle ${cycle}/${maxCycles}] Running tests: ${testCmd}`));\n const testResult = runCommand(testCmd, workingDir);\n if (!testResult.success) {\n const testErrors = parseErrors(testResult.output, \"test\");\n allErrors.push(...testErrors);\n console.log(chalk.yellow(` ✘ Tests failed (${testErrors.length} error(s) captured)`));\n } else {\n console.log(chalk.green(\" ✔ Tests passed.\"));\n }\n }\n\n // Run lint\n if (lintCmd) {\n console.log(chalk.gray(` [cycle ${cycle}/${maxCycles}] Running lint: ${lintCmd}`));\n const lintResult = runCommand(lintCmd, workingDir);\n if (!lintResult.success) {\n const lintErrors = parseErrors(lintResult.output, \"lint\");\n allErrors.push(...lintErrors);\n console.log(chalk.yellow(` ✘ Lint failed (${lintErrors.length} error(s) captured)`));\n } else {\n console.log(chalk.green(\" ✔ Lint passed.\"));\n }\n }\n\n if (allErrors.length === 0) {\n console.log(chalk.green(`\\n ✔ All checks passed after ${cycle} cycle(s).`));\n return true;\n }\n\n if (cycle < maxCycles) {\n console.log(chalk.cyan(`\\n Attempting auto-fix (${allErrors.length} error(s))...`));\n await attemptFix(provider, allErrors, workingDir, dsl);\n }\n }\n\n console.log(chalk.yellow(\"\\n ⚠ Some errors remain after auto-fix cycles. Manual intervention needed.\"));\n return false;\n}\n","import chalk from \"chalk\";\nimport { AIProvider } from \"./spec-generator\";\nimport { specAssessSystemPrompt } from \"../prompts/spec-assess.prompt\";\n\n// ─── Types ─────────────────────────────────────────────────────────────────────\n\nexport interface SpecAssessment {\n coverageScore: number;\n clarityScore: number;\n constitutionScore: number;\n overallScore: number;\n issues: string[];\n suggestions: string[];\n dslExtractable: boolean;\n}\n\n// ─── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction scoreBar(score: number): string {\n const filled = Math.round(score);\n const bar = chalk.green(\"█\".repeat(filled)) + chalk.gray(\"░\".repeat(10 - filled));\n const color = score >= 8 ? chalk.green : score >= 6 ? chalk.yellow : chalk.red;\n return `[${bar}] ${color(score + \"/10\")}`;\n}\n\nfunction parseAssessment(raw: string): SpecAssessment | null {\n // Strip markdown fences if present\n const stripped = raw.replace(/```(?:json)?\\n?/g, \"\").replace(/```\\s*$/g, \"\").trim();\n try {\n const parsed = JSON.parse(stripped);\n if (\n typeof parsed.coverageScore === \"number\" &&\n typeof parsed.clarityScore === \"number\" &&\n typeof parsed.overallScore === \"number\"\n ) {\n return parsed as SpecAssessment;\n }\n } catch {\n // fall through\n }\n return null;\n}\n\n// ─── Main export ───────────────────────────────────────────────────────────────\n\n/**\n * Run a pre-Approval-Gate quality check on the spec.\n * Advisory only — does not block the flow regardless of scores.\n * Returns null if the AI call fails (graceful degradation).\n */\nexport async function assessSpec(\n provider: AIProvider,\n spec: string,\n constitution?: string\n): Promise<SpecAssessment | null> {\n const prompt = `Assess the following feature specification.\n${constitution ? `\\n=== Project Constitution (check consistency against this) ===\\n${constitution.slice(0, 1500)}\\n` : \"\"}\n=== Feature Spec ===\n${spec}`;\n\n try {\n const raw = await provider.generate(prompt, specAssessSystemPrompt);\n return parseAssessment(raw);\n } catch {\n return null;\n }\n}\n\n/**\n * Print the spec assessment panel to stdout.\n */\nexport function printSpecAssessment(assessment: SpecAssessment): void {\n console.log(chalk.blue(\"\\n─── Spec Quality Assessment ─────────────────────\"));\n console.log(` Coverage ${scoreBar(assessment.coverageScore)} error handling, edge cases, auth`);\n console.log(` Clarity ${scoreBar(assessment.clarityScore)} API contracts, response shapes`);\n console.log(` Constitution${scoreBar(assessment.constitutionScore)} naming, error codes, conventions`);\n console.log(chalk.bold(` Overall ${scoreBar(assessment.overallScore)}`));\n\n if (!assessment.dslExtractable) {\n console.log(\n chalk.yellow(\n \"\\n ⚠ DSL extraction may be unreliable — clarityScore < 6 or no structured API section.\"\n )\n );\n console.log(chalk.gray(\" Consider adding explicit request/response shapes before proceeding.\"));\n }\n\n if (assessment.issues.length > 0) {\n console.log(chalk.yellow(`\\n Issues found (${assessment.issues.length}):`));\n assessment.issues.forEach((issue) => console.log(chalk.yellow(` · ${issue}`)));\n }\n\n if (assessment.suggestions.length > 0) {\n console.log(chalk.cyan(\"\\n Suggestions:\"));\n assessment.suggestions.forEach((s) => console.log(chalk.cyan(` 💡 ${s}`)));\n }\n\n console.log(chalk.blue(\"─────────────────────────────────────────────────\"));\n}\n","/**\n * Spec quality pre-assessment prompt.\n * Called before the Approval Gate to give the engineer an advisory quality signal\n * before committing to code generation.\n */\nexport const specAssessSystemPrompt = `You are a Senior Software Architect reviewing a feature specification before it goes to code generation.\n\nEvaluate the spec on three dimensions and return a structured JSON object — nothing else:\n\n{\n \"coverageScore\": <0-10>,\n \"clarityScore\": <0-10>,\n \"constitutionScore\": <0-10>,\n \"overallScore\": <0-10>,\n \"issues\": [\"issue 1\", \"issue 2\"],\n \"suggestions\": [\"suggestion 1\"],\n \"dslExtractable\": true\n}\n\nScoring criteria:\n\n**coverageScore** (0-10): How well does the spec cover all dimensions needed for production code?\n- 9-10: Error handling for every endpoint, auth rules explicit, all edge cases covered, business invariants stated\n- 6-8: Most cases covered, 1-2 missing error codes or edge cases\n- 3-5: Major gaps: no error handling section, or vague \"handle errors appropriately\"\n- 0-2: Only happy path described\n\n**clarityScore** (0-10): Can a DSL be reliably extracted? Are API contracts unambiguous?\n- 9-10: Every endpoint has explicit request/response shape, error codes are named constants, no ambiguous \"return user info\"\n- 6-8: Mostly clear, but 1-2 endpoints have vague response shapes\n- 3-5: Endpoints listed but response shapes missing, or error handling says \"appropriate status code\"\n- 0-2: Free-form description, no structured API section\n\n**constitutionScore** (0-10): Consistency with the provided project constitution.\n- 9-10: Fully consistent — uses project's naming convention, error code system, auth middleware pattern\n- 6-8: Mostly consistent, minor deviations\n- 3-5: Notable conflicts (e.g., invents new error code format while project has one)\n- 0-2: Ignores project conventions entirely\n- If no constitution is provided, give 8 (neutral)\n\n**overallScore**: Weighted average — coverage * 0.4 + clarity * 0.4 + constitution * 0.2\n\n**issues**: Up to 5 specific, actionable issues. Be concrete — reference section numbers or field names.\nExamples:\n- \"§5 POST /users/login: 401 error response body format not specified\"\n- \"§6 UserFavorite model: missing unique constraint on (userId, itemId)\"\n- \"Spec invents error code FORBIDDEN_ACCESS but project uses AUTH_FORBIDDEN (see constitution §3)\"\n\n**suggestions**: Up to 3 concrete improvements. Be brief.\n\n**dslExtractable**: true if clarityScore >= 6 AND at least one endpoint is clearly defined with method + path + status codes. false otherwise.\n\nOutput ONLY the JSON object — no explanation, no markdown fences.`;\n","import chalk from \"chalk\";\nimport * as fs from \"fs-extra\";\nimport * as path from \"path\";\nimport { AIProvider } from \"./spec-generator\";\nimport { CONSTITUTION_FILE } from \"./constitution-generator\";\nimport { parseConstitutionStats } from \"../prompts/consolidate.prompt\";\n\n// ─── Types ──────────────────────────────────────────────────────────────────────\n\nexport interface ReviewIssue {\n /** Short description of the issue */\n description: string;\n /** Which file or area */\n location?: string;\n /** Category: bug / pattern / style / security / performance */\n category: string;\n}\n\n// ─── Extract Issues from Review ─────────────────────────────────────────────────\n\n/**\n * Parse review text to extract issues from the \"⚠️ 问题\" section.\n * Returns up to 10 issues (to keep constitution append manageable).\n */\nexport function extractIssuesFromReview(reviewText: string): ReviewIssue[] {\n const issues: ReviewIssue[] = [];\n\n // Find the issues section (between ⚠️ and 💡 or 📊)\n const issuesMatch = reviewText.match(\n /## ⚠[^\\n]*\\n([\\s\\S]*?)(?=## [💡📊]|\\n*$)/i\n );\n if (!issuesMatch) return issues;\n\n const section = issuesMatch[1];\n const lines = section.split(\"\\n\");\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) continue;\n\n // Match list items: \"- issue text\" or \"1. issue text\" or \"**Category**: text\"\n const itemMatch = trimmed.match(/^[-*\\d]+[.)]?\\s*(.+)/);\n if (itemMatch) {\n const desc = itemMatch[1].replace(/\\*\\*/g, \"\").trim();\n if (desc.length > 10) {\n issues.push({\n description: desc.slice(0, 200),\n category: categorizeIssue(desc),\n });\n }\n }\n }\n\n return issues.slice(0, 10);\n}\n\nfunction categorizeIssue(text: string): string {\n const lower = text.toLowerCase();\n if (lower.includes(\"security\") || lower.includes(\"auth\") || lower.includes(\"注入\") || lower.includes(\"xss\") || lower.includes(\"sql\")) return \"security\";\n if (lower.includes(\"performance\") || lower.includes(\"慢\") || lower.includes(\"性能\") || lower.includes(\"n+1\")) return \"performance\";\n if (lower.includes(\"error\") || lower.includes(\"异常\") || lower.includes(\"crash\") || lower.includes(\"bug\")) return \"bug\";\n if (lower.includes(\"pattern\") || lower.includes(\"模式\") || lower.includes(\"convention\") || lower.includes(\"命名\")) return \"pattern\";\n return \"general\";\n}\n\n// ─── Append to Constitution ────────────────────────────────────────────────────\n\nconst MEMORY_SECTION_HEADER = \"\\n\\n## 9. 积累教训 (Accumulated Lessons)\\n\";\nconst MEMORY_SECTION_MARKER = \"## 9. 积累教训\";\n\n/**\n * Append review issues to the project constitution as accumulated lessons.\n * Creates the section if it doesn't exist; appends if it does.\n * Deduplicates by checking if a similar lesson already exists.\n */\nexport async function appendLessonsToConstitution(\n projectRoot: string,\n issues: ReviewIssue[]\n): Promise<void> {\n if (issues.length === 0) return;\n\n const constitutionPath = path.join(projectRoot, CONSTITUTION_FILE);\n let content = \"\";\n try {\n content = await fs.readFile(constitutionPath, \"utf-8\");\n } catch {\n console.log(chalk.gray(\" No constitution file — skipping knowledge memory.\"));\n return;\n }\n\n // Check if section 9 already exists\n const hasMemorySection = content.includes(MEMORY_SECTION_MARKER);\n\n // Build new lesson entries with date stamp\n const date = new Date().toISOString().slice(0, 10);\n const newEntries: string[] = [];\n\n for (const issue of issues) {\n // Simple dedup: check if a similar line already exists (case-insensitive substring)\n const normalized = issue.description.toLowerCase().slice(0, 50);\n if (content.toLowerCase().includes(normalized)) continue;\n\n const badge = issue.category === \"security\" ? \"🔒\" :\n issue.category === \"performance\" ? \"⚡\" :\n issue.category === \"bug\" ? \"🐛\" :\n issue.category === \"pattern\" ? \"📐\" : \"📝\";\n newEntries.push(`- ${badge} **[${date}]** ${issue.description}`);\n }\n\n if (newEntries.length === 0) {\n console.log(chalk.gray(\" No new lessons to add (all deduplicated).\"));\n return;\n }\n\n let updatedContent: string;\n if (hasMemorySection) {\n // Append to existing section — find the end of section 9\n // Strategy: find \"## 9.\" then insert before the next \"## \" or EOF\n const sectionStart = content.indexOf(MEMORY_SECTION_MARKER);\n const afterHeader = sectionStart + MEMORY_SECTION_HEADER.length;\n // Find next section header after section 9\n const nextSectionMatch = content.slice(afterHeader).match(/\\n## \\d/);\n const insertPos = nextSectionMatch\n ? afterHeader + nextSectionMatch.index!\n : content.length;\n updatedContent =\n content.slice(0, insertPos) +\n newEntries.join(\"\\n\") + \"\\n\" +\n content.slice(insertPos);\n } else {\n // Append new section at the end\n updatedContent = content + MEMORY_SECTION_HEADER + newEntries.join(\"\\n\") + \"\\n\";\n }\n\n await fs.writeFile(constitutionPath, updatedContent, \"utf-8\");\n console.log(chalk.green(` ✔ ${newEntries.length} lesson(s) appended to constitution (§9).`));\n\n // Warn when §9 is getting long\n const stats = parseConstitutionStats(updatedContent);\n if (stats.lessonCount >= 8) {\n console.log(\n chalk.yellow(\n ` ⚠ §9 now has ${stats.lessonCount} accumulated lessons. Run \\`ai-spec init --consolidate\\` to prune and rebase.`\n )\n );\n }\n}\n\n/**\n * Full knowledge memory flow: extract issues from review → append to constitution.\n */\nexport async function accumulateReviewKnowledge(\n provider: AIProvider,\n projectRoot: string,\n reviewText: string\n): Promise<void> {\n console.log(chalk.blue(\"\\n─── Knowledge Memory ────────────────────────────\"));\n\n const issues = extractIssuesFromReview(reviewText);\n if (issues.length === 0) {\n console.log(chalk.gray(\" No actionable issues found in review. Skipping.\"));\n return;\n }\n\n console.log(chalk.gray(` Extracted ${issues.length} issue(s) from review:`));\n for (const issue of issues) {\n console.log(chalk.gray(` - [${issue.category}] ${issue.description.slice(0, 80)}`));\n }\n\n await appendLessonsToConstitution(projectRoot, issues);\n}\n","import * as fs from \"fs-extra\";\nimport * as path from \"path\";\nimport * as os from \"os\";\n\nconst KEY_STORE_FILE = path.join(os.homedir(), \".ai-spec-keys.json\");\n\ntype KeyStore = Record<string, string>;\n\nasync function readStore(): Promise<KeyStore> {\n try {\n if (await fs.pathExists(KEY_STORE_FILE)) {\n return await fs.readJson(KEY_STORE_FILE);\n }\n } catch {\n // ignore corrupt file\n }\n return {};\n}\n\nasync function writeStore(store: KeyStore): Promise<void> {\n await fs.writeJson(KEY_STORE_FILE, store, { spaces: 2 });\n // Restrict permissions to owner only (600)\n await fs.chmod(KEY_STORE_FILE, 0o600);\n}\n\nexport async function getSavedKey(provider: string): Promise<string | undefined> {\n const store = await readStore();\n return store[provider] || undefined;\n}\n\nexport async function saveKey(provider: string, key: string): Promise<void> {\n const store = await readStore();\n store[provider] = key;\n await writeStore(store);\n}\n\nexport async function clearAllKeys(): Promise<void> {\n if (await fs.pathExists(KEY_STORE_FILE)) {\n await fs.remove(KEY_STORE_FILE);\n }\n}\n\nexport async function clearKey(provider: string): Promise<void> {\n const store = await readStore();\n delete store[provider];\n await writeStore(store);\n}\n\nexport { KEY_STORE_FILE };\n","import chalk from \"chalk\";\nimport * as os from \"os\";\nimport * as path from \"path\";\nimport * as fs from \"fs-extra\";\n\n// ─── Layout constants ─────────────────────────────────────────────────────────\n\nconst VERSION = \"0.14.1\";\n/** Total visible width of the title / bottom bar */\nconst TOTAL_W = 76;\n/** Visible width of the left content column */\nconst L_WIDTH = 44;\n/** Visible width of the right content column (TOTAL_W - L_WIDTH - 4 for \" │ \" + leading space) */\nconst R_WIDTH = TOTAL_W - L_WIDTH - 4;\n\n// ─── ASCII robot ──────────────────────────────────────────────────────────────\n\nconst ROBOT_COLOR = chalk.hex(\"#E8885A\");\n\nconst ROBOT: string[] = [\n ROBOT_COLOR(\" ┌───────────┐\"),\n ROBOT_COLOR(\" │\") + chalk.bold.white(\" ◉ \") + ROBOT_COLOR(\" \") + chalk.bold.white(\"◉ \") + ROBOT_COLOR(\"│\"),\n ROBOT_COLOR(\" │\") + chalk.dim(\" ╰─╯ \") + ROBOT_COLOR(\"│\"),\n ROBOT_COLOR(\" └─────┬─────┘\"),\n ROBOT_COLOR(\" │\"),\n ROBOT_COLOR(\" ────┴────\"),\n];\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\n/** Visible (non-ANSI) length of a string */\nfunction visLen(s: string): number {\n // eslint-disable-next-line no-control-regex\n return s.replace(/\\x1b\\[[0-9;]*m/g, \"\").length;\n}\n\n/** Pad a string on the right to reach `width` visible chars */\nfunction padR(s: string, width: number): string {\n const vl = visLen(s);\n return vl >= width ? s : s + \" \".repeat(width - vl);\n}\n\n/** Render one full-width row: left column + separator + right column */\nfunction row(left: string, right: string): string {\n return padR(left, L_WIDTH) + \" \" + chalk.gray(\"│\") + \" \" + padR(right, R_WIDTH);\n}\n\n/** Center a string (with chalk codes) within `width` visible chars */\nfunction center(s: string, width: number): string {\n const vl = visLen(s);\n const pad = Math.max(0, Math.floor((width - vl) / 2));\n return \" \".repeat(pad) + s;\n}\n\n// ─── Recent specs ─────────────────────────────────────────────────────────────\n\nasync function getRecentSpecs(dir: string): Promise<string[]> {\n const specsDir = path.join(dir, \"specs\");\n if (!(await fs.pathExists(specsDir))) return [];\n try {\n const files = await fs.readdir(specsDir);\n const mdFiles = files.filter((f) => f.endsWith(\".md\"));\n const withStats = await Promise.all(\n mdFiles.map(async (f) => {\n const stat = await fs.stat(path.join(specsDir, f));\n return { name: f, mtime: stat.mtime.getTime() };\n })\n );\n withStats.sort((a, b) => b.mtime - a.mtime);\n return withStats.slice(0, 3).map(({ name, mtime }) => {\n const ms = Date.now() - mtime;\n const hours = Math.floor(ms / 3_600_000);\n const days = Math.floor(hours / 24);\n const age = days > 0 ? `${days}d ago` : hours > 0 ? `${hours}h ago` : \"just now\";\n // trim to fit right column\n const slug = name.replace(/\\.md$/, \"\").slice(0, R_WIDTH - age.length - 2);\n return chalk.white(slug) + chalk.dim(\" \" + age);\n });\n } catch {\n return [];\n }\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\nexport async function printWelcome(\n currentDir: string,\n config?: { provider?: string; model?: string }\n): Promise<void> {\n const username = os.userInfo().username;\n const homeDir = os.homedir();\n const shortDir = currentDir.startsWith(homeDir)\n ? \"~\" + currentDir.slice(homeDir.length)\n : currentDir;\n\n const recentSpecs = await getRecentSpecs(currentDir);\n\n const providerBit = config?.provider\n ? config.provider + (config.model ? \" · \" + config.model : \"\")\n : \"\";\n // Build bottom info and truncate to fit left column (leave 2-char indent)\n const bottomRaw = [providerBit, shortDir].filter(Boolean).join(\" · \");\n const maxInfoLen = L_WIDTH - 2;\n const bottomTruncated = bottomRaw.length > maxInfoLen\n ? bottomRaw.slice(0, maxInfoLen - 1) + \"…\"\n : bottomRaw;\n const bottomLine = \" \" + chalk.dim(bottomTruncated);\n\n // ── Title bar ───────────────────────────────────────────────────────────────\n const titleInner = `ai-spec v${VERSION} `;\n const titleDashes = \"─\".repeat(Math.max(0, TOTAL_W - titleInner.length - 4));\n console.log(\n \"\\n\" +\n chalk.hex(\"#FF6B35\")(\"─── \" + titleInner + titleDashes)\n );\n\n // ── Build left-column lines ──────────────────────────────────────────────────\n const welcomeText = \"Welcome back, \" + chalk.bold.white(username) + \"!\";\n const leftLines: string[] = [\n \"\",\n center(welcomeText, L_WIDTH),\n \"\",\n ...ROBOT,\n \"\",\n bottomLine,\n \"\",\n ];\n\n // ── Build right-column lines ─────────────────────────────────────────────────\n const rightLines: string[] = [\n chalk.hex(\"#FF8C00\").bold(\"Tips for getting started\"),\n chalk.gray(\"─\".repeat(R_WIDTH)),\n chalk.white('ai-spec create \"feature\"'),\n chalk.gray(\"ai-spec workspace run\"),\n chalk.gray(\"ai-spec update \\\"change\\\"\"),\n \"\",\n chalk.hex(\"#FF8C00\").bold(\"Recent activity\"),\n chalk.gray(\"─\".repeat(R_WIDTH)),\n ...(recentSpecs.length > 0 ? recentSpecs : [chalk.dim(\"No recent activity\")]),\n ];\n\n // ── Render rows ─────────────────────────────────────────────────────────────\n const maxLines = Math.max(leftLines.length, rightLines.length);\n for (let i = 0; i < maxLines; i++) {\n console.log(row(leftLines[i] ?? \"\", rightLines[i] ?? \"\"));\n }\n\n // ── Bottom bar ──────────────────────────────────────────────────────────────\n console.log(chalk.gray(\"─\".repeat(TOTAL_W)));\n console.log();\n}\n","export const globalConstitutionSystemPrompt = `You are a Senior Software Architect. Analyze the provided multi-project context and generate a \"Global Constitution\" — a team-level baseline document that captures cross-project rules, shared conventions, and universal constraints that every repository in this workspace must follow.\n\nThis document is the LOWER-PRIORITY layer. Project-specific constitutions will override it where they conflict.\nFocus only on patterns that truly apply across ALL repos — do not duplicate project-specific rules.\n\nOutput a Markdown document with EXACTLY these sections:\n\n---\n\n# Global Constitution\n\n## 1. 团队 API 规范 (Team-wide API Standards)\n- 通用响应结构(所有服务必须遵守的 code/message/data 格式)\n- 错误码命名规范(前缀规则、范围划分)\n- 认证 Token 格式(JWT payload 必须包含的字段)\n- CORS / 安全头规范\n\n## 2. 团队命名规范 (Team-wide Naming Conventions)\n- 跨服务的路由前缀约定(如 /api/v1/ 前缀)\n- 环境变量命名规则\n- 跨 repo 的类型/接口命名约定\n\n## 3. 团队架构禁区 (Team-wide Red Lines)\n列出跨所有项目绝对禁止的事项:\n- [ ] 禁止 ...\n- [ ] 禁止 ...\n\n## 4. 跨端契约规范 (Cross-Repo Contract Standards)\n- 前后端接口对接的字段命名约定(camelCase vs snake_case)\n- 分页响应结构规范\n- 日期/时间格式规范(ISO 8601?时间戳?)\n- 文件上传接口规范\n\n## 5. 日志与监控规范 (Logging & Observability Standards)\n- 日志格式规范\n- 必须记录的事件类型(登录、支付、关键业务操作)\n- 错误上报规范\n\n---\n\nBe concise. Every rule must be specific enough to enforce.\nRules here apply to ALL repos — if a rule only fits one project, it belongs in that project's constitution.`;\n\nexport function buildGlobalConstitutionPrompt(\n projectContextSummaries: Array<{ name: string; summary: string }>\n): string {\n const parts: string[] = [\n \"Analyze the following projects in this workspace and generate a Global Constitution that captures their shared conventions.\\n\",\n ];\n\n for (const { name, summary } of projectContextSummaries) {\n parts.push(`=== Project: ${name} ===\\n${summary}\\n`);\n }\n\n parts.push(\n \"Extract only cross-project patterns. Ignore project-specific details.\",\n \"Generate the Global Constitution now.\"\n );\n\n return parts.join(\"\\n\");\n}\n","import { WorkspaceConfig } from \"../core/workspace-loader\";\nimport { ProjectContext } from \"../core/context-loader\";\nimport { FrontendContext } from \"../core/frontend-context-loader\";\n\n/**\n * System prompt for multi-repo requirement decomposition.\n *\n * Key design goals:\n * 1. Force the AI to be concrete about backend API contracts (exact paths, methods, payloads).\n * 2. Force concrete UX decisions for frontend repos (throttle vs debounce, optimistic updates).\n * 3. Identify cross-repo dependencies so we can process repos in the right order.\n * 4. Output valid JSON matching DecompositionResult exactly.\n */\nexport const decomposeSystemPrompt = `You are a senior full-stack architect specializing in multi-repo feature decomposition.\n\nYour task: Given a high-level user requirement and a workspace containing multiple repos, decompose the requirement into specific, actionable per-repo specifications with concrete technical decisions.\n\nCRITICAL RULES:\n1. Output ONLY valid JSON — no markdown fences, no prose before or after.\n2. Be CONCRETE and SPECIFIC. Not vague descriptions but precise technical specs:\n - Backend: exact HTTP method, URL path, request body schema, response shape, error codes.\n - Frontend: exact UX pattern (throttle 300ms vs debounce 500ms), whether optimistic update is needed.\n3. Only include repos that ACTUALLY need changes for this requirement. Exclude repos that don't need to change.\n4. Set isContractProvider=true for backend repos whose API the frontend will consume.\n5. Set dependsOnRepos to specify processing order — frontend repos that consume a backend API must list the backend repo name.\n6. For uxDecisions: use throttle for actions (button clicks, form submits), debounce for inputs (search, filter). Be specific about ms values.\n7. coordinationNotes should explain cross-repo concerns: shared types, state synchronization, when NOT to re-fetch (use response data directly).\n\nUX DECISION GUIDE:\n- Throttle (throttleMs): Use for user actions like button clicks. Prevents rapid duplicate submissions. Typical: 300ms.\n- Debounce (debounceMs): Use for user inputs like search. Waits until user stops typing. Typical: 500ms.\n- Optimistic Update: Update UI before server responds, rollback on error. Use for low-risk toggle operations (like/unlike, follow/unfollow).\n- reloadOnSuccess: List endpoints to re-fetch after success. Leave empty [] if the response already contains updated data.\n- loadingState: Almost always true — show a spinner or disable button during request.\n\nOUTPUT FORMAT (follow exactly):\n{\n \"summary\": \"<1-2 sentences: what the requirement is and how it's split across repos>\",\n \"coordinationNotes\": \"<cross-repo concerns: shared types, state sync, API contract points>\",\n \"repos\": [\n {\n \"repoName\": \"<exact repo name from workspace config>\",\n \"role\": \"<backend|frontend|mobile|shared>\",\n \"specIdea\": \"<detailed per-repo requirement: for backend include exact API paths/methods/payloads; for frontend include UX pattern and which API to call>\",\n \"isContractProvider\": true,\n \"dependsOnRepos\": [],\n \"uxDecisions\": null\n },\n {\n \"repoName\": \"<frontend repo name>\",\n \"role\": \"frontend\",\n \"specIdea\": \"<detailed frontend spec including component name, state management approach, which API endpoint to call, and UX behavior>\",\n \"isContractProvider\": false,\n \"dependsOnRepos\": [\"<backend repo name>\"],\n \"uxDecisions\": {\n \"throttleMs\": 300,\n \"optimisticUpdate\": true,\n \"reloadOnSuccess\": [],\n \"errorRollback\": true,\n \"loadingState\": true,\n \"notes\": \"<explain WHY this UX pattern was chosen — technical reasoning>\"\n }\n }\n ]\n}\n\nEXAMPLE (for a \"like feature\" on a blog platform with repos: \"api\" (Express) and \"web\" (React)):\n{\n \"summary\": \"点赞功能需要后端新增 toggle like 接口,前端实现带乐观更新的点赞按钮\",\n \"coordinationNotes\": \"前端应在乐观更新后通过 likeCount 字段更新展示,不需要重新拉取详情接口。注意后端返回 liked 布尔值标识当前状态。\",\n \"repos\": [\n {\n \"repoName\": \"api\",\n \"role\": \"backend\",\n \"specIdea\": \"新增 POST /api/v1/posts/:postId/like 接口,toggle 语义(已点赞则取消),需要认证,返回 { liked: boolean, likeCount: number }。数据库新增 post_likes 表,字段 userId + postId,唯一约束防重复。\",\n \"isContractProvider\": true,\n \"dependsOnRepos\": [],\n \"uxDecisions\": null\n },\n {\n \"repoName\": \"web\",\n \"role\": \"frontend\",\n \"specIdea\": \"点赞按钮组件 LikeButton,调用 POST /api/v1/posts/:postId/like,乐观更新本地 liked 状态和 likeCount,300ms throttle 防止重复点击,错误时回滚状态并提示。\",\n \"isContractProvider\": false,\n \"dependsOnRepos\": [\"api\"],\n \"uxDecisions\": {\n \"throttleMs\": 300,\n \"optimisticUpdate\": true,\n \"reloadOnSuccess\": [],\n \"errorRollback\": true,\n \"loadingState\": true,\n \"notes\": \"点赞是高频离散操作,throttle 比 debounce 更合适(用户期望立即响应而非等待停止)。乐观更新后端接口返回 likeCount,直接更新本地状态,无需重新拉取帖子详情。\"\n }\n }\n ]\n}`;\n\n/**\n * Build the user-turn prompt for decomposition.\n * @param frontendContexts Optional map of repoName → FrontendContext for richer UX decisions.\n */\nexport function buildDecomposePrompt(\n requirement: string,\n workspace: WorkspaceConfig,\n contexts: Map<string, ProjectContext>,\n frontendContexts?: Map<string, FrontendContext>\n): string {\n const parts: string[] = [\n `Workspace: ${workspace.name}`,\n \"\",\n \"Repos in this workspace:\",\n ];\n\n for (const repo of workspace.repos) {\n const ctx = contexts.get(repo.name);\n const stack = ctx?.techStack?.join(\", \") || \"unknown\";\n const depsCount = ctx?.dependencies?.length ?? 0;\n\n parts.push(` - ${repo.name}: type=${repo.type}, role=${repo.role}, path=${repo.path}`);\n parts.push(` Tech stack: ${stack} | ${depsCount} dependencies`);\n\n if (ctx?.apiStructure && ctx.apiStructure.length > 0) {\n parts.push(` API files: ${ctx.apiStructure.slice(0, 5).join(\", \")}`);\n }\n if (repo.constitution) {\n const preview = repo.constitution.split(\"\\n\").slice(0, 5).join(\"\\n\");\n parts.push(` Constitution preview: ${preview}`);\n }\n\n // Inject frontend-specific context so AI can make grounded UX decisions\n const fctx = frontendContexts?.get(repo.name);\n if (fctx && (repo.role === \"frontend\" || repo.role === \"mobile\")) {\n parts.push(` Frontend context:`);\n parts.push(` Framework: ${fctx.framework} | Test: ${fctx.testFramework} | HTTP: ${fctx.httpClient}`);\n parts.push(` State mgmt: ${fctx.stateManagement.join(\", \") || \"none\"}`);\n\n if (fctx.hookFiles.length > 0) {\n parts.push(` Existing hooks (${fctx.hookFiles.length}) — reference these in specIdea:`);\n fctx.hookFiles.slice(0, 6).forEach((f) => parts.push(` - ${f}`));\n }\n if (fctx.existingApiFiles.length > 0) {\n parts.push(` Existing API wrappers — MUST extend, NOT recreate:`);\n fctx.existingApiFiles.slice(0, 5).forEach((f) => parts.push(` - ${f}`));\n }\n if (fctx.storeFiles.length > 0) {\n parts.push(` Store files (${fctx.storeFiles.length}) — add state here, don't create new stores:`);\n fctx.storeFiles.slice(0, 4).forEach((f) => parts.push(` - ${f}`));\n }\n // Show API wrapper content snippet so AI knows the call pattern\n if (fctx.apiWrapperContent.length > 0) {\n parts.push(` API call pattern (existing):`);\n const snippet = fctx.apiWrapperContent[0].split(\"\\n\").slice(0, 10).join(\"\\n\");\n parts.push(` ${snippet.replace(/\\n/g, \"\\n \")}`);\n }\n }\n }\n\n parts.push(\"\");\n parts.push(`User requirement: ${requirement}`);\n parts.push(\"\");\n parts.push(\n \"Decompose this requirement into per-repo specs with concrete technical decisions.\",\n \"For frontend repos: reference the existing hook/store/API files listed above — tell the AI to extend them, not create new ones.\",\n \"Output ONLY valid JSON.\"\n );\n\n return parts.join(\"\\n\");\n}\n","import { AIProvider } from \"./spec-generator\";\nimport { WorkspaceConfig, RepoRole } from \"./workspace-loader\";\nimport { ProjectContext } from \"./context-loader\";\nimport { FrontendContext } from \"./frontend-context-loader\";\nimport { decomposeSystemPrompt, buildDecomposePrompt } from \"../prompts/decompose.prompt\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface UxDecision {\n /** Throttle delay in ms, e.g. 300 for button clicks */\n throttleMs?: number;\n /** Debounce delay in ms, e.g. 500 for search inputs */\n debounceMs?: number;\n /** Update UI before server confirms */\n optimisticUpdate: boolean;\n /** Which API endpoints to re-fetch on success (empty = none needed) */\n reloadOnSuccess?: string[];\n /** Rollback optimistic update on error */\n errorRollback: boolean;\n /** Show loading indicator during request */\n loadingState: boolean;\n /** Free-form coordination notes */\n notes?: string;\n}\n\nexport interface RepoRequirement {\n repoName: string;\n role: RepoRole;\n /** The per-repo requirement description */\n specIdea: string;\n /** This repo's DSL becomes the contract for dependent repos */\n isContractProvider: boolean;\n /** Must be processed after these repos */\n dependsOnRepos: string[];\n /** Only for frontend/mobile repos */\n uxDecisions?: UxDecision | null;\n}\n\nexport interface DecompositionResult {\n originalRequirement: string;\n /** 1-2 sentence analysis of the requirement */\n summary: string;\n repos: RepoRequirement[];\n /** Cross-repo concerns: shared types, timing, state sync */\n coordinationNotes: string;\n}\n\n// ─── JSON Parser (same approach as dsl-extractor.ts) ─────────────────────────\n\nfunction parseJsonFromOutput(raw: string): unknown {\n const trimmed = raw.trim();\n\n if (trimmed.startsWith(\"{\")) {\n return JSON.parse(trimmed);\n }\n\n const fenceStart = trimmed.indexOf(\"```\");\n if (fenceStart !== -1) {\n const afterFence = trimmed.slice(fenceStart + 3);\n const newlinePos = afterFence.indexOf(\"\\n\");\n const jsonStart = newlinePos !== -1 ? newlinePos + 1 : 0;\n const fenceEnd = afterFence.lastIndexOf(\"```\");\n if (fenceEnd > jsonStart) {\n const jsonStr = afterFence.slice(jsonStart, fenceEnd).trim();\n return JSON.parse(jsonStr);\n }\n }\n\n const objStart = trimmed.indexOf(\"{\");\n const objEnd = trimmed.lastIndexOf(\"}\");\n if (objStart !== -1 && objEnd > objStart) {\n return JSON.parse(trimmed.slice(objStart, objEnd + 1));\n }\n\n throw new SyntaxError(\"No JSON object found in AI output\");\n}\n\n// ─── Validator ────────────────────────────────────────────────────────────────\n\nfunction validateDecomposition(raw: unknown): DecompositionResult {\n if (typeof raw !== \"object\" || raw === null) {\n throw new Error(\"Decomposition output is not an object\");\n }\n\n const obj = raw as Record<string, unknown>;\n\n if (typeof obj.summary !== \"string\" || !obj.summary) {\n throw new Error('Missing required field: \"summary\"');\n }\n if (typeof obj.coordinationNotes !== \"string\") {\n throw new Error('Missing required field: \"coordinationNotes\"');\n }\n if (!Array.isArray(obj.repos) || obj.repos.length === 0) {\n throw new Error('\"repos\" must be a non-empty array');\n }\n\n const repos: RepoRequirement[] = obj.repos.map((r: unknown, i: number) => {\n if (typeof r !== \"object\" || r === null) {\n throw new Error(`repos[${i}] is not an object`);\n }\n const repo = r as Record<string, unknown>;\n if (typeof repo.repoName !== \"string\" || !repo.repoName) {\n throw new Error(`repos[${i}].repoName is required`);\n }\n if (typeof repo.specIdea !== \"string\" || !repo.specIdea) {\n throw new Error(`repos[${i}].specIdea is required`);\n }\n return {\n repoName: repo.repoName as string,\n role: (repo.role as RepoRole) ?? \"backend\",\n specIdea: repo.specIdea as string,\n isContractProvider: Boolean(repo.isContractProvider),\n dependsOnRepos: Array.isArray(repo.dependsOnRepos)\n ? (repo.dependsOnRepos as string[])\n : [],\n uxDecisions:\n repo.uxDecisions && typeof repo.uxDecisions === \"object\"\n ? (repo.uxDecisions as UxDecision)\n : null,\n };\n });\n\n return {\n originalRequirement: \"\",\n summary: obj.summary as string,\n repos,\n coordinationNotes: obj.coordinationNotes as string,\n };\n}\n\n// ─── RequirementDecomposer ───────────────────────────────────────────────────\n\nexport class RequirementDecomposer {\n constructor(private provider: AIProvider) {}\n\n /**\n * Decompose a high-level requirement into per-repo specs with UX decisions.\n */\n async decompose(\n requirement: string,\n workspace: WorkspaceConfig,\n contexts: Map<string, ProjectContext>,\n frontendContexts?: Map<string, FrontendContext>\n ): Promise<DecompositionResult> {\n const userPrompt = buildDecomposePrompt(requirement, workspace, contexts, frontendContexts);\n\n let rawOutput: string;\n try {\n rawOutput = await this.provider.generate(userPrompt, decomposeSystemPrompt);\n } catch (err) {\n throw new Error(\n `AI call for requirement decomposition failed: ${(err as Error).message}`\n );\n }\n\n let parsed: unknown;\n try {\n parsed = parseJsonFromOutput(rawOutput);\n } catch (parseErr) {\n throw new Error(\n `Failed to parse decomposition JSON: ${(parseErr as Error).message}\\n\\nRaw output:\\n${rawOutput.slice(0, 500)}`\n );\n }\n\n const result = validateDecomposition(parsed);\n result.originalRequirement = requirement;\n return result;\n }\n\n /**\n * Sort repo requirements in dependency order (providers before dependents).\n */\n static sortByDependency(repos: RepoRequirement[]): RepoRequirement[] {\n const sorted: RepoRequirement[] = [];\n const remaining = [...repos];\n const processed = new Set<string>();\n\n let maxIterations = repos.length * 2;\n\n while (remaining.length > 0 && maxIterations-- > 0) {\n const idx = remaining.findIndex((r) =>\n r.dependsOnRepos.every((dep) => processed.has(dep))\n );\n\n if (idx === -1) {\n // Circular dependency or missing dep — add remaining as-is\n sorted.push(...remaining);\n break;\n }\n\n const [repo] = remaining.splice(idx, 1);\n sorted.push(repo);\n processed.add(repo.repoName);\n }\n\n return sorted;\n }\n}\n","import { SpecDSL, ApiEndpoint } from \"./dsl-types\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface FrontendApiContract {\n endpoints: Array<{\n method: string;\n path: string;\n auth: boolean;\n requestShape: string; // TypeScript interface as string\n responseShape: string; // TypeScript interface as string\n errorCodes: string[];\n }>;\n /** Full TypeScript interfaces block */\n typeDefinitions: string;\n /** Human-readable summary for prompt injection */\n summary: string;\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\n/**\n * Convert a DSL FieldMap (Record<string, string>) to a TypeScript interface body.\n * Each entry becomes: fieldName: fieldType; // original description\n */\nfunction fieldMapToTsInterface(\n fields: Record<string, string> | undefined,\n interfaceName: string\n): string {\n if (!fields || Object.keys(fields).length === 0) {\n return `interface ${interfaceName} { /* empty */ }`;\n }\n\n const lines = Object.entries(fields).map(([name, typeDesc]) => {\n // Try to extract a clean TS type from the description\n const tsType = inferTsType(typeDesc);\n return ` ${name}: ${tsType};`;\n });\n\n return `interface ${interfaceName} {\\n${lines.join(\"\\n\")}\\n}`;\n}\n\n/**\n * Heuristically map DSL type-description strings to TS primitive types.\n */\nfunction inferTsType(desc: string): string {\n const lower = desc.toLowerCase();\n if (lower.includes(\"boolean\") || lower.includes(\"bool\")) return \"boolean\";\n if (\n lower.includes(\"number\") ||\n lower.includes(\"int\") ||\n lower.includes(\"float\") ||\n lower.includes(\"count\") ||\n lower.includes(\"age\") ||\n lower.includes(\"price\") ||\n lower.includes(\"amount\")\n )\n return \"number\";\n if (lower.includes(\"string[]\") || lower.includes(\"array of string\")) return \"string[]\";\n if (lower.includes(\"number[]\") || lower.includes(\"array of number\")) return \"number[]\";\n if (lower.includes(\"datetime\") || lower.includes(\"date\")) return \"string /* ISO 8601 */\";\n if (lower.includes(\"json\") || lower.includes(\"object\")) return \"Record<string, unknown>\";\n return \"string\";\n}\n\n/**\n * Generate a PascalCase name from an endpoint ID + suffix.\n */\nfunction endpointTypeName(epId: string, suffix: \"Request\" | \"Response\"): string {\n const normalized = epId.replace(/[^a-zA-Z0-9]/g, \"\");\n return `${normalized}${suffix}`;\n}\n\n// ─── Core Functions ───────────────────────────────────────────────────────────\n\n/**\n * Convert a backend SpecDSL into a FrontendApiContract.\n * This is the main bridge between backend output and frontend spec generation.\n */\nexport function buildFrontendApiContract(dsl: SpecDSL): FrontendApiContract {\n const typeBlocks: string[] = [];\n\n const endpoints = dsl.endpoints.map((ep: ApiEndpoint) => {\n const reqName = endpointTypeName(ep.id, \"Request\");\n const resName = endpointTypeName(ep.id, \"Response\");\n\n // Build request shape from body (primary) or params + query\n const reqFields: Record<string, string> = {\n ...(ep.request?.body ?? {}),\n ...(ep.request?.params ?? {}),\n ...(ep.request?.query ?? {}),\n };\n const requestShape = fieldMapToTsInterface(reqFields, reqName);\n typeBlocks.push(requestShape);\n\n // Build response shape — derive from success description + model info\n // Since DSL doesn't have a structured response schema, we generate from model fields\n const responseShape = buildResponseInterface(dsl, ep, resName);\n typeBlocks.push(responseShape);\n\n const errorCodes = (ep.errors ?? []).map((e) => e.code);\n\n return {\n method: ep.method,\n path: ep.path,\n auth: ep.auth,\n requestShape,\n responseShape,\n errorCodes,\n };\n });\n\n const typeDefinitions = typeBlocks.join(\"\\n\\n\");\n\n const summary = buildContractSummary(dsl, endpoints);\n\n return { endpoints, typeDefinitions, summary };\n}\n\n/**\n * Build a response TypeScript interface by inferring from the DSL.\n * Uses model fields when the endpoint clearly returns a model, otherwise generates from description.\n */\nfunction buildResponseInterface(\n dsl: SpecDSL,\n ep: ApiEndpoint,\n name: string\n): string {\n // Try to match the endpoint to a data model by name heuristic\n const pathSegments = ep.path.split(\"/\").filter(Boolean);\n const modelName = dsl.models.find((m) =>\n pathSegments.some(\n (seg) =>\n seg.toLowerCase() === m.name.toLowerCase() ||\n seg.toLowerCase() === m.name.toLowerCase() + \"s\"\n )\n );\n\n if (modelName && (ep.method === \"GET\" || ep.method === \"POST\" || ep.method === \"PUT\" || ep.method === \"PATCH\")) {\n const fields = modelName.fields.map((f) => {\n const tsType = inferTsType(f.type);\n const optional = f.required ? \"\" : \"?\";\n return ` ${f.name}${optional}: ${tsType};`;\n });\n return `interface ${name} {\\n${fields.join(\"\\n\")}\\n}`;\n }\n\n // Generic success response\n if (ep.successStatus === 204) {\n return `interface ${name} { /* 204 No Content */ }`;\n }\n\n // Derive from success description keywords\n const desc = ep.successDescription.toLowerCase();\n const lines: string[] = [];\n\n if (desc.includes(\"list\") || desc.includes(\"array\") || desc.includes(\"多\")) {\n lines.push(` items: unknown[];`);\n lines.push(` total?: number;`);\n } else if (desc.includes(\"token\") || desc.includes(\"jwt\")) {\n lines.push(` token: string;`);\n lines.push(` expiresIn?: number;`);\n } else if (desc.includes(\"id\")) {\n lines.push(` id: number | string;`);\n } else {\n lines.push(` /* ${ep.successDescription} */`);\n lines.push(` success: boolean;`);\n }\n\n return `interface ${name} {\\n${lines.join(\"\\n\")}\\n}`;\n}\n\n/**\n * Build a human-readable summary of the API contract.\n */\nfunction buildContractSummary(\n dsl: SpecDSL,\n endpoints: FrontendApiContract[\"endpoints\"]\n): string {\n const lines: string[] = [\n `Backend feature: ${dsl.feature.title}`,\n `Description: ${dsl.feature.description}`,\n \"\",\n `Exposed endpoints (${endpoints.length}):`,\n ];\n\n for (const ep of endpoints) {\n const authLabel = ep.auth ? \"[auth required]\" : \"[public]\";\n const errorLabel =\n ep.errorCodes.length > 0 ? ` | errors: ${ep.errorCodes.join(\", \")}` : \"\";\n lines.push(` ${ep.method} ${ep.path} ${authLabel}${errorLabel}`);\n }\n\n if (dsl.models.length > 0) {\n lines.push(\"\");\n lines.push(`Data models: ${dsl.models.map((m) => m.name).join(\", \")}`);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Build the contract context section to inject into frontend spec generation prompts.\n */\nexport function buildContractContextSection(contract: FrontendApiContract): string {\n const lines: string[] = [\n \"=== Backend API Contract (use these exact endpoints — do NOT change paths, methods, or types) ===\",\n \"\",\n contract.summary,\n \"\",\n \"-- TypeScript Interface Definitions --\",\n contract.typeDefinitions,\n \"\",\n \"=== End of Backend API Contract ===\",\n ];\n return lines.join(\"\\n\");\n}\n","import { FrontendContext } from \"../core/frontend-context-loader\";\nimport { UxDecision } from \"../core/requirement-decomposer\";\n\n/**\n * System prompt for frontend spec generation.\n *\n * This prompt specializes the generic spec-writing for frontend repos.\n * It:\n * - Provides UX engineering patterns (throttle vs debounce)\n * - Emphasizes state management integration\n * - Includes API integration patterns\n * - Uses the \"you have a backend API contract, implement the frontend\" framing\n */\nexport const frontendSpecSystemPrompt = `You are an expert Frontend Architect. Your task is to convert a feature requirement (with an optional backend API contract) into a structured, actionable Markdown specification for a frontend application.\n\nThe spec MUST be written in Chinese (中文). Be comprehensive but focused — every section should contain practical, project-specific information derived from the provided context.\n\n=== UX ENGINEERING PATTERNS ===\n\nWhen the feature involves user interactions, apply these patterns:\n\n**Throttle vs Debounce (critical distinction):**\n- THROTTLE: Use for discrete user ACTIONS (button clicks, form submits, like/favorite). Limits how often the action fires. User gets immediate feedback on first click. Typical: 300ms.\n- DEBOUNCE: Use for continuous user INPUT (search boxes, filters, autocomplete). Waits until user stops typing. Avoids spamming API on every keystroke. Typical: 500ms.\n- RULE: Never use debounce on action buttons — users expect immediate visual feedback.\n\n**Optimistic Updates:**\n- Use when: the operation is likely to succeed (toggle states, low-risk mutations).\n- Don't use when: the operation is complex, irreversible, or has significant side effects.\n- Pattern: update local state immediately → send API request → on error: rollback state + show error.\n- Best for: like/unlike, follow/unfollow, read/unread toggles, simple item additions.\n\n**State Synchronization:**\n- Prefer using API response data directly (e.g., return likeCount from server) over re-fetching.\n- Only re-fetch full lists when item count/order changes (adding, deleting, reordering).\n- Use optimistic updates for field mutations (counters, booleans).\n\n**Loading States:**\n- Show loading indicator for ALL async operations.\n- Disable action buttons during request to prevent duplicate submissions.\n- Use skeleton screens for initial data loading.\n\n=== SPEC TEMPLATE ===\n\nUse the EXACT following template structure:\n\n---\n\n# Feature Spec: {功能名称}\n\n## 1. 功能概述 (Overview)\n用 2-3 句话说明这个前端功能是什么,对应哪个后端接口。\n\n## 2. 用户交互流程 (User Interaction Flow)\n- 用户操作步骤(点击、输入、导航)\n- 每个操作对应的 UI 状态变化\n- 错误场景的用户反馈\n\n## 3. 组件设计 (Component Design)\n\n### 3.1 组件结构\n- 新增/修改哪些组件\n- 组件的 Props 定义(TypeScript interface)\n- 组件间的数据流向\n\n### 3.2 状态管理\n- 需要管理哪些状态(本地 useState vs 全局状态管理库)\n- 状态的初始值、更新时机\n- 乐观更新的状态变化逻辑(如适用)\n\n## 4. API 集成 (API Integration)\n\n### 4.1 接口调用\n| Method | Endpoint | 触发时机 | 响应处理 |\n|--------|----------|---------|---------|\n| POST | /api/... | 点击按钮时 | 更新本地状态 |\n\n### 4.2 请求/响应处理\n- 请求参数构建\n- 响应数据的使用方式(直接更新本地状态 or 重新拉取列表)\n- 错误处理(网络错误、业务错误码)\n\n## 5. UX 工程决策 (UX Engineering Decisions)\n- **节流/防抖策略**: [具体方案及原因]\n- **乐观更新**: [是否使用、回滚机制]\n- **加载状态**: [哪些操作显示 loading,UI 变化]\n- **错误提示**: [toast/inline error/modal]\n\n## 6. 非功能性需求 (Non-functional Requirements)\n- **性能**: 避免不必要的重渲染,memo 使用时机\n- **可访问性**: ARIA 属性,键盘操作支持\n- **响应式**: 移动端适配要求\n\n## 7. 实施要点 (Implementation Notes)\n- 复用现有组件和 hooks\n- 与现有 API 层(axios instance / fetcher)的集成方式\n- TypeScript 类型定义位置\n- 测试要点(组件测试、hook 测试)\n\n---\n\n根据用户的需求和项目上下文生成上述完整 Spec。确保 API 集成遵循现有项目的 HTTP 客户端封装方式,组件设计符合现有 UI 库的规范,状态管理方案与现有架构一致。`;\n\n/**\n * Build a frontend spec generation prompt that includes:\n * - The repo requirement (per-repo specIdea)\n * - The backend API contract (if available)\n * - UX decisions (if available)\n * - Frontend project context\n */\nexport function buildFrontendSpecPrompt(opts: {\n specIdea: string;\n apiContractSection?: string;\n uxDecisions?: UxDecision | null;\n frontendContext?: FrontendContext | null;\n}): string {\n const parts: string[] = [opts.specIdea];\n\n // Inject backend API contract if available\n if (opts.apiContractSection) {\n parts.push(`\\n\\n${opts.apiContractSection}`);\n }\n\n // Inject concrete UX decisions if available\n if (opts.uxDecisions) {\n const ux = opts.uxDecisions;\n parts.push(\"\\n\\n=== UX Engineering Decisions (apply these exactly) ===\");\n\n if (ux.throttleMs !== undefined) {\n parts.push(`- Throttle button clicks: ${ux.throttleMs}ms (prevent duplicate submissions)`);\n }\n if (ux.debounceMs !== undefined) {\n parts.push(`- Debounce input: ${ux.debounceMs}ms (wait for user to stop typing)`);\n }\n\n parts.push(\n `- Optimistic update: ${ux.optimisticUpdate ? \"YES — update UI before server responds\" : \"NO — wait for server response\"}`\n );\n\n if (ux.optimisticUpdate && ux.errorRollback) {\n parts.push(\"- Error rollback: YES — revert to previous state if request fails\");\n }\n\n parts.push(\n `- Loading state: ${ux.loadingState ? \"YES — show loading indicator, disable button during request\" : \"NO\"}`\n );\n\n if (ux.reloadOnSuccess && ux.reloadOnSuccess.length > 0) {\n parts.push(`- Re-fetch on success: ${ux.reloadOnSuccess.join(\", \")}`);\n } else {\n parts.push(\"- Re-fetch on success: NO — use API response data to update local state directly\");\n }\n\n if (ux.notes) {\n parts.push(`- Notes: ${ux.notes}`);\n }\n }\n\n // Inject frontend context\n if (opts.frontendContext) {\n const ctx = opts.frontendContext;\n parts.push(\"\\n\\n=== Frontend Tech Stack ===\");\n parts.push(`Framework: ${ctx.framework}`);\n if (ctx.stateManagement.length > 0) {\n parts.push(`State Management: ${ctx.stateManagement.join(\", \")}`);\n }\n parts.push(`HTTP Client: ${ctx.httpClient}`);\n if (ctx.uiLibrary !== \"none\" && ctx.uiLibrary !== \"unknown\") {\n parts.push(`UI Library: ${ctx.uiLibrary}`);\n }\n parts.push(`Routing: ${ctx.routingPattern}`);\n\n if (ctx.existingApiFiles.length > 0) {\n parts.push(`\\nExisting API/service files:`);\n ctx.existingApiFiles\n .slice(0, 8)\n .forEach((f) => parts.push(` - ${f}`));\n }\n\n if (ctx.componentPatterns.length > 0) {\n parts.push(\"\\nExisting component patterns:\");\n ctx.componentPatterns.forEach((p) => {\n parts.push(\"```\");\n parts.push(p.slice(0, 400));\n parts.push(\"```\");\n });\n }\n }\n\n return parts.join(\"\\n\");\n}\n","import * as path from \"path\";\nimport * as fs from \"fs-extra\";\nimport { SpecDSL, ApiEndpoint, FieldMap } from \"./dsl-types\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface MockServerOptions {\n /** Port for the mock server (default: 3001) */\n port?: number;\n /** Generate MSW handlers file */\n msw?: boolean;\n /** Generate frontend proxy config */\n proxy?: boolean;\n /** Output directory for generated files (default: mock/) */\n outputDir?: string;\n}\n\nexport interface MockGenerationResult {\n files: Array<{ path: string; description: string }>;\n}\n\n// ─── Fixture Generator ────────────────────────────────────────────────────────\n\n/**\n * Convert a type-description string to a fixture value (JavaScript literal).\n */\nfunction typeToFixture(fieldName: string, typeDesc: string): unknown {\n const t = typeDesc.toLowerCase();\n\n if (t.includes(\"boolean\") || t === \"bool\") return true;\n if (t.includes(\"int\") || t.includes(\"number\") || t.includes(\"float\") || t.includes(\"decimal\")) {\n if (fieldName.toLowerCase().includes(\"id\")) return 1;\n if (fieldName.toLowerCase().includes(\"count\") || fieldName.toLowerCase().includes(\"total\")) return 42;\n if (fieldName.toLowerCase().includes(\"price\") || fieldName.toLowerCase().includes(\"amount\")) return 9.99;\n return 1;\n }\n if (t.includes(\"datetime\") || t.includes(\"date\") || t.includes(\"timestamp\")) {\n return \"2024-01-15T10:30:00.000Z\";\n }\n if (t.includes(\"[]\") || t.includes(\"array\") || t.includes(\"list\")) return [];\n if (t.includes(\"object\") || t.includes(\"json\") || t.includes(\"record\")) return {};\n\n // String heuristics by field name\n const name = fieldName.toLowerCase();\n if (name === \"id\" || name.endsWith(\"id\")) return \"abc123\";\n if (name.includes(\"email\")) return \"user@example.com\";\n if (name.includes(\"phone\")) return \"+1-555-0100\";\n if (name.includes(\"url\") || name.includes(\"image\") || name.includes(\"avatar\")) return \"https://example.com/sample.jpg\";\n if (name.includes(\"token\") || name.includes(\"secret\")) return \"mock-token-xyz\";\n if (name.includes(\"name\")) return \"Example Name\";\n if (name.includes(\"title\")) return \"Example Title\";\n if (name.includes(\"description\") || name.includes(\"content\") || name.includes(\"body\")) return \"Example description text\";\n if (name.includes(\"status\")) return \"active\";\n if (name.includes(\"type\") || name.includes(\"role\")) return \"default\";\n if (name.includes(\"code\")) return \"CODE001\";\n\n return `example_${fieldName}`;\n}\n\nfunction buildFixtureObject(fields: FieldMap): Record<string, unknown> {\n const obj: Record<string, unknown> = {};\n for (const [name, type] of Object.entries(fields)) {\n obj[name] = typeToFixture(name, type);\n }\n return obj;\n}\n\n/**\n * Build a fixture response object for an endpoint.\n * For endpoints without explicit response schemas, generate minimal fixtures from model context.\n */\nfunction buildEndpointFixture(endpoint: ApiEndpoint, dsl: SpecDSL): unknown {\n const method = endpoint.method;\n const status = endpoint.successStatus;\n\n // DELETE with 204 → no body\n if (status === 204) return null;\n\n // Try to derive fixture from model names mentioned in endpoint description\n const descLower = endpoint.description.toLowerCase();\n const matchedModel = dsl.models.find((m) =>\n descLower.includes(m.name.toLowerCase())\n );\n\n if (matchedModel) {\n const fields: FieldMap = {};\n for (const f of matchedModel.fields) {\n fields[f.name] = f.type;\n }\n const item = buildFixtureObject(fields);\n\n // List endpoints return arrays\n if (method === \"GET\" && (descLower.includes(\"list\") || descLower.includes(\"all\") || descLower.includes(\"paginate\"))) {\n return {\n data: [item, { ...item, id: \"def456\" }],\n total: 2,\n page: 1,\n pageSize: 10,\n };\n }\n return { data: item };\n }\n\n // Fallback based on method\n if (method === \"POST\") return { data: { id: \"abc123\", createdAt: \"2024-01-15T10:30:00.000Z\" } };\n if (method === \"GET\") return { data: { id: \"abc123\" } };\n return { success: true };\n}\n\n// ─── Express Mock Server Generator ───────────────────────────────────────────\n\nfunction generateMockServerJs(dsl: SpecDSL, port: number): string {\n const lines: string[] = [];\n\n lines.push(`// ─── Mock Server ─────────────────────────────────────────────`);\n lines.push(`// Auto-generated by ai-spec mock`);\n lines.push(`// Feature: ${dsl.feature.title}`);\n lines.push(`// DO NOT use in production. Standalone dev mock only.`);\n lines.push(``);\n lines.push(`const express = require('express');`);\n lines.push(`const app = express();`);\n lines.push(``);\n lines.push(`app.use(express.json());`);\n lines.push(``);\n lines.push(`// ─── CORS (dev only) ─────────────────────────────────────────`);\n lines.push(`app.use((req, res, next) => {`);\n lines.push(` res.setHeader('Access-Control-Allow-Origin', '*');`);\n lines.push(` res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,PATCH,DELETE,OPTIONS');`);\n lines.push(` res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');`);\n lines.push(` if (req.method === 'OPTIONS') return res.sendStatus(204);`);\n lines.push(` next();`);\n lines.push(`});`);\n lines.push(``);\n\n // Auth middleware\n const hasAuthEndpoints = dsl.endpoints.some((e) => e.auth);\n if (hasAuthEndpoints) {\n lines.push(`// ─── Auth check (returns 401 if Authorization header missing) ──`);\n lines.push(`function requireAuth(req, res, next) {`);\n lines.push(` const authHeader = req.headers['authorization'];`);\n lines.push(` if (!authHeader || !authHeader.startsWith('Bearer ')) {`);\n lines.push(` return res.status(401).json({ code: 'UNAUTHORIZED', message: 'Missing or invalid Authorization header' });`);\n lines.push(` }`);\n lines.push(` next();`);\n lines.push(`}`);\n lines.push(``);\n }\n\n lines.push(`// ─── Routes ──────────────────────────────────────────────────`);\n\n for (const endpoint of dsl.endpoints) {\n const fixture = buildEndpointFixture(endpoint, dsl);\n const fixtureJson = JSON.stringify(fixture, null, 2)\n .split(\"\\n\")\n .map((l, i) => (i === 0 ? l : ` ${l}`))\n .join(\"\\n\");\n\n const expressMethod = endpoint.method.toLowerCase();\n // Convert DSL path params :param to express :param (already compatible)\n const expressPath = endpoint.path;\n\n lines.push(`// ${endpoint.id}: ${endpoint.description}`);\n if (endpoint.auth) {\n lines.push(`app.${expressMethod}('${expressPath}', requireAuth, (req, res) => {`);\n } else {\n lines.push(`app.${expressMethod}('${expressPath}', (req, res) => {`);\n }\n\n if (fixture === null) {\n lines.push(` res.sendStatus(${endpoint.successStatus});`);\n } else {\n lines.push(` res.status(${endpoint.successStatus}).json(${fixtureJson});`);\n }\n\n // Error simulation query param: ?simulate_error=ERRORCODE\n if (endpoint.errors && endpoint.errors.length > 0) {\n const firstError = endpoint.errors[0];\n lines.push(` // Simulate error: GET /this/path?simulate_error=${firstError.code}`);\n }\n\n lines.push(`});`);\n lines.push(``);\n }\n\n lines.push(`// ─── Start ───────────────────────────────────────────────────`);\n lines.push(`const PORT = process.env.MOCK_PORT || ${port};`);\n lines.push(`app.listen(PORT, () => {`);\n lines.push(` console.log(\\`[ai-spec mock] Mock server running at http://localhost:\\${PORT}\\`);`);\n lines.push(` console.log('[ai-spec mock] Endpoints:');`);\n for (const endpoint of dsl.endpoints) {\n lines.push(` console.log(' ${endpoint.method.padEnd(7)} ${endpoint.path}');`);\n }\n lines.push(`});`);\n lines.push(``);\n\n return lines.join(\"\\n\");\n}\n\n// ─── Proxy Config Generators ──────────────────────────────────────────────────\n\nfunction detectFrontendFramework(projectDir: string): \"vite\" | \"next\" | \"webpack\" | \"cra\" | \"unknown\" {\n // Check vite.config\n for (const f of [\"vite.config.ts\", \"vite.config.js\", \"vite.config.mts\"]) {\n if (fs.existsSync(path.join(projectDir, f))) return \"vite\";\n }\n // Check next.config\n for (const f of [\"next.config.js\", \"next.config.ts\", \"next.config.mjs\"]) {\n if (fs.existsSync(path.join(projectDir, f))) return \"next\";\n }\n // Check for CRA (react-scripts in package.json)\n const pkgPath = path.join(projectDir, \"package.json\");\n if (fs.existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\"));\n const deps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };\n if (deps[\"react-scripts\"]) return \"cra\";\n } catch { /* ignore */ }\n }\n // Check webpack.config\n for (const f of [\"webpack.config.js\", \"webpack.config.ts\"]) {\n if (fs.existsSync(path.join(projectDir, f))) return \"webpack\";\n }\n return \"unknown\";\n}\n\nfunction generateViteProxyBlock(mockPort: number, endpoints: ApiEndpoint[]): string {\n // Collect unique path prefixes\n const prefixes = new Set<string>();\n for (const ep of endpoints) {\n const parts = ep.path.split(\"/\").filter(Boolean);\n if (parts.length > 0) prefixes.add(`/${parts[0]}`);\n }\n const target = `http://localhost:${mockPort}`;\n const proxyEntries = Array.from(prefixes)\n .map((p) => ` '${p}': { target: '${target}', changeOrigin: true }`)\n .join(\",\\n\");\n\n return `// Add this proxy block to your vite.config.ts / vite.config.js\n// Inside the defineConfig({ server: { proxy: { ... } } }) section:\n//\n// server: {\n// proxy: {\n${proxyEntries\n .split(\"\\n\")\n .map((l) => `// ${l}`)\n .join(\"\\n\")}\n// }\n// }\n\n// ─── Standalone proxy snippet for vite.config.ts ─────────────────────────────\n// import { defineConfig } from 'vite';\n// export default defineConfig({\n// server: {\n// proxy: {\n${proxyEntries\n .split(\"\\n\")\n .map((l) => `// ${l.trim()}`)\n .join(\"\\n\")}\n// }\n// }\n// });\n`;\n}\n\nfunction generateNextProxyBlock(mockPort: number, endpoints: ApiEndpoint[]): string {\n const prefixes = new Set<string>();\n for (const ep of endpoints) {\n const parts = ep.path.split(\"/\").filter(Boolean);\n if (parts.length > 0) prefixes.add(`/${parts[0]}`);\n }\n const rewrites = Array.from(prefixes).map(\n (p) => ` { source: '${p}/:path*', destination: 'http://localhost:${mockPort}${p}/:path*' }`\n );\n\n return `// Add this to your next.config.js rewrites():\n//\n// module.exports = {\n// async rewrites() {\n// return [\n${rewrites.map((r) => `// ${r}`).join(\",\\n\")}\n// ];\n// },\n// };\n`;\n}\n\nfunction generateWebpackProxyBlock(mockPort: number, endpoints: ApiEndpoint[]): string {\n const prefixes = new Set<string>();\n for (const ep of endpoints) {\n const parts = ep.path.split(\"/\").filter(Boolean);\n if (parts.length > 0) prefixes.add(`/${parts[0]}`);\n }\n const proxyEntries = Array.from(prefixes)\n .map(\n (p) =>\n ` '${p}': {\\n target: 'http://localhost:${mockPort}',\\n changeOrigin: true\\n }`\n )\n .join(\",\\n\");\n\n return `// Add this to your webpack.config.js devServer.proxy section:\n//\n// devServer: {\n// proxy: {\n${proxyEntries\n .split(\"\\n\")\n .map((l) => `// ${l}`)\n .join(\"\\n\")}\n// }\n// }\n`;\n}\n\nfunction generateCraProxyBlock(mockPort: number): string {\n return `// For Create React App: add a \"proxy\" field to package.json\n// This only proxies requests that don't match static files:\n//\n// {\n// \"proxy\": \"http://localhost:${mockPort}\"\n// }\n//\n// Or use src/setupProxy.js for per-path control:\n// const { createProxyMiddleware } = require('http-proxy-middleware');\n// module.exports = function(app) {\n// app.use('/api', createProxyMiddleware({ target: 'http://localhost:${mockPort}', changeOrigin: true }));\n// };\n`;\n}\n\nfunction generateProxyConfig(\n dsl: SpecDSL,\n mockPort: number,\n projectDir: string\n): { content: string; filename: string } {\n const framework = detectFrontendFramework(projectDir);\n\n switch (framework) {\n case \"vite\":\n return {\n filename: \"mock/proxy.vite.comment.txt\",\n content: generateViteProxyBlock(mockPort, dsl.endpoints),\n };\n case \"next\":\n return {\n filename: \"mock/proxy.next.comment.txt\",\n content: generateNextProxyBlock(mockPort, dsl.endpoints),\n };\n case \"cra\":\n return {\n filename: \"mock/proxy.cra.comment.txt\",\n content: generateCraProxyBlock(mockPort),\n };\n default:\n return {\n filename: \"mock/proxy.webpack.comment.txt\",\n content: generateWebpackProxyBlock(mockPort, dsl.endpoints),\n };\n }\n}\n\n// ─── MSW Handler Generator ────────────────────────────────────────────────────\n\nfunction generateMswHandlers(dsl: SpecDSL): string {\n const lines: string[] = [];\n\n lines.push(`// ─── MSW Handlers ────────────────────────────────────────────`);\n lines.push(`// Auto-generated by ai-spec mock --msw`);\n lines.push(`// Feature: ${dsl.feature.title}`);\n lines.push(`// Place this file at: src/mocks/handlers.ts`);\n lines.push(``);\n lines.push(`import { http, HttpResponse } from 'msw';`);\n lines.push(``);\n\n for (const endpoint of dsl.endpoints) {\n const fixture = buildEndpointFixture(endpoint, dsl);\n const fixtureJson = JSON.stringify(fixture, null, 4)\n .split(\"\\n\")\n .map((l, i) => (i === 0 ? l : ` ${l}`))\n .join(\"\\n\");\n const method = endpoint.method.toLowerCase();\n lines.push(`// ${endpoint.id}: ${endpoint.description}`);\n if (fixture === null) {\n lines.push(`http.${method}('${endpoint.path}', () => {`);\n lines.push(` return new HttpResponse(null, { status: ${endpoint.successStatus} });`);\n } else {\n lines.push(`http.${method}('${endpoint.path}', () => {`);\n lines.push(` return HttpResponse.json(${fixtureJson}, { status: ${endpoint.successStatus} });`);\n }\n lines.push(`}),`);\n lines.push(``);\n }\n\n // Wrap in export\n const handlerLines = lines.join(\"\\n\");\n\n return `// ─── MSW Handlers ────────────────────────────────────────────\n// Auto-generated by ai-spec mock --msw\n// Feature: ${dsl.feature.title}\n// Place this file at: src/mocks/handlers.ts\n\nimport { http, HttpResponse } from 'msw';\n\nexport const handlers = [\n${dsl.endpoints\n .map((endpoint) => {\n const fixture = buildEndpointFixture(endpoint, dsl);\n const method = endpoint.method.toLowerCase();\n const indent = \" \";\n const fixtureJson = JSON.stringify(fixture, null, 2)\n .split(\"\\n\")\n .map((l, i) => (i === 0 ? l : `${indent} ${l}`))\n .join(\"\\n\");\n\n const comment = `${indent}// ${endpoint.id}: ${endpoint.description}`;\n let handler: string;\n if (fixture === null) {\n handler = `${indent}http.${method}('${endpoint.path}', () => {\\n${indent} return new HttpResponse(null, { status: ${endpoint.successStatus} });\\n${indent}})`;\n } else {\n handler = `${indent}http.${method}('${endpoint.path}', () => {\\n${indent} return HttpResponse.json(${fixtureJson}, { status: ${endpoint.successStatus} });\\n${indent}})`;\n }\n return `${comment}\\n${handler}`;\n })\n .join(\",\\n\\n\")}\n];\n`;\n}\n\nfunction generateMswBrowser(): string {\n return `// src/mocks/browser.ts\n// MSW browser setup — import and call start() in your app entry point (dev only)\nimport { setupWorker } from 'msw/browser';\nimport { handlers } from './handlers';\n\nexport const worker = setupWorker(...handlers);\n`;\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Generate mock server, proxy config, and/or MSW handlers from a SpecDSL.\n * Writes files relative to projectDir.\n */\nexport async function generateMockAssets(\n dsl: SpecDSL,\n projectDir: string,\n opts: MockServerOptions = {}\n): Promise<MockGenerationResult> {\n const port = opts.port ?? 3001;\n const outputDir = path.join(projectDir, opts.outputDir ?? \"mock\");\n const result: MockGenerationResult = { files: [] };\n\n await fs.ensureDir(outputDir);\n\n // 1. Express mock server (always generated)\n const serverJs = generateMockServerJs(dsl, port);\n const serverPath = path.join(outputDir, \"server.js\");\n await fs.writeFile(serverPath, serverJs, \"utf-8\");\n result.files.push({\n path: path.relative(projectDir, serverPath),\n description: `Express mock server — run with: node mock/server.js`,\n });\n\n // README inside mock/\n const mockReadme = `# Mock Server\n\nAuto-generated by \\`ai-spec mock\\` for **${dsl.feature.title}**.\n\n## Quick start\n\n\\`\\`\\`bash\n# Install express (one-time)\nnpm install --save-dev express\n\n# Start the mock server\nnode mock/server.js\n# → Listening on http://localhost:${port}\n\\`\\`\\`\n\n## Endpoints\n\n| Method | Path | Auth | Status |\n|--------|------|------|--------|\n${dsl.endpoints\n .map(\n (e) =>\n `| ${e.method} | \\`${e.path}\\` | ${e.auth ? \"✓\" : \"—\"} | ${e.successStatus} |`\n )\n .join(\"\\n\")}\n\n## Error simulation\n\nAppend \\`?simulate_error=1\\` to any request to test error handling (not yet auto-wired — edit server.js manually).\n`;\n const readmePath = path.join(outputDir, \"README.md\");\n await fs.writeFile(readmePath, mockReadme, \"utf-8\");\n result.files.push({\n path: path.relative(projectDir, readmePath),\n description: \"Mock server usage guide\",\n });\n\n // 2. Proxy config (optional)\n if (opts.proxy) {\n const { content, filename } = generateProxyConfig(dsl, port, projectDir);\n const proxyPath = path.join(projectDir, filename);\n await fs.ensureDir(path.dirname(proxyPath));\n await fs.writeFile(proxyPath, content, \"utf-8\");\n result.files.push({\n path: filename,\n description: \"Proxy config snippet — copy instructions into your framework config\",\n });\n }\n\n // 3. MSW handlers (optional)\n if (opts.msw) {\n const mswDir = path.join(projectDir, \"src\", \"mocks\");\n await fs.ensureDir(mswDir);\n\n const handlersContent = generateMswHandlers(dsl);\n const handlersPath = path.join(mswDir, \"handlers.ts\");\n await fs.writeFile(handlersPath, handlersContent, \"utf-8\");\n result.files.push({\n path: path.relative(projectDir, handlersPath),\n description: \"MSW request handlers\",\n });\n\n const browserContent = generateMswBrowser();\n const browserPath = path.join(mswDir, \"browser.ts\");\n await fs.writeFile(browserPath, browserContent, \"utf-8\");\n result.files.push({\n path: path.relative(projectDir, browserPath),\n description: \"MSW browser worker setup\",\n });\n }\n\n return result;\n}\n\n/**\n * Find the latest DSL file in a project directory.\n * Looks for *.dsl.json files under .ai-spec/\n */\nexport async function findLatestDslFile(projectDir: string): Promise<string | null> {\n const specDir = path.join(projectDir, \".ai-spec\");\n if (!(await fs.pathExists(specDir))) return null;\n\n const allFiles: string[] = [];\n\n async function scan(dir: string): Promise<void> {\n const entries = await fs.readdir(dir);\n for (const entry of entries) {\n const abs = path.join(dir, entry);\n const stat = await fs.stat(abs);\n if (stat.isDirectory()) {\n await scan(abs);\n } else if (entry.endsWith(\".dsl.json\")) {\n allFiles.push(abs);\n }\n }\n }\n\n await scan(specDir);\n\n if (allFiles.length === 0) return null;\n\n // Return most recently modified\n const withMtimes = await Promise.all(\n allFiles.map(async (f) => ({ f, mtime: (await fs.stat(f)).mtime }))\n );\n withMtimes.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());\n return withMtimes[0].f;\n}\n","import chalk from \"chalk\";\nimport * as path from \"path\";\nimport * as fs from \"fs-extra\";\nimport { AIProvider } from \"./spec-generator\";\nimport { ProjectContext, FRONTEND_FRAMEWORKS } from \"./context-loader\";\nimport { SpecDSL } from \"./dsl-types\";\nimport { DslExtractor } from \"./dsl-extractor\";\nimport { nextVersionPath } from \"./spec-versioning\";\nimport { findLatestDslFile } from \"./mock-server-generator\";\nimport {\n specUpdateSystemPrompt,\n dslUpdateSystemPrompt,\n buildSpecUpdatePrompt,\n buildDslUpdatePrompt,\n buildAffectedFilesPrompt,\n} from \"../prompts/update.prompt\";\nimport { getCodeGenSystemPrompt } from \"../prompts/codegen.prompt\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface SpecUpdateResult {\n /** Path of the new spec version written to disk */\n newSpecPath: string;\n /** New version number */\n newVersion: number;\n /** Path of the updated DSL, or null if extraction failed */\n newDslPath: string | null;\n /** Files identified as needing updates */\n affectedFiles: AffectedFile[];\n /** Updated DSL, or null */\n updatedDsl: SpecDSL | null;\n}\n\nexport interface AffectedFile {\n file: string;\n action: \"create\" | \"modify\";\n description: string;\n}\n\nexport interface SpecUpdaterOptions {\n /** Skip generating the affected-files list */\n skipAffectedFiles?: boolean;\n /** Repo language type — for DSL extraction front detection */\n repoType?: string;\n}\n\n// ─── JSON parser (same pattern as requirement-decomposer.ts) ─────────────────\n\nfunction parseJsonFromOutput(raw: string): unknown {\n const trimmed = raw.trim();\n if (trimmed.startsWith(\"{\")) return JSON.parse(trimmed);\n const fenceStart = trimmed.indexOf(\"```\");\n if (fenceStart !== -1) {\n const afterFence = trimmed.slice(fenceStart + 3);\n const newlinePos = afterFence.indexOf(\"\\n\");\n const jsonStart = newlinePos !== -1 ? newlinePos + 1 : 0;\n const fenceEnd = afterFence.lastIndexOf(\"```\");\n if (fenceEnd > jsonStart) return JSON.parse(afterFence.slice(jsonStart, fenceEnd).trim());\n }\n const objStart = trimmed.indexOf(\"{\");\n const arrStart = trimmed.indexOf(\"[\");\n const start = objStart !== -1 && (arrStart === -1 || objStart < arrStart) ? objStart : arrStart;\n const isObj = start === objStart && objStart !== -1;\n const end = isObj ? trimmed.lastIndexOf(\"}\") : trimmed.lastIndexOf(\"]\");\n if (start !== -1 && end > start) return JSON.parse(trimmed.slice(start, end + 1));\n throw new SyntaxError(\"No JSON found in output\");\n}\n\nfunction parseAffectedFiles(raw: string): AffectedFile[] {\n try {\n const parsed = parseJsonFromOutput(raw);\n if (Array.isArray(parsed)) return parsed as AffectedFile[];\n } catch { /* ignore */ }\n return [];\n}\n\n// ─── Spec Updater ─────────────────────────────────────────────────────────────\n\nexport class SpecUpdater {\n private extractor: DslExtractor;\n\n constructor(private provider: AIProvider) {\n this.extractor = new DslExtractor(provider);\n }\n\n /**\n * Find the latest spec version for a given specs directory.\n * Returns all .md spec files sorted newest-first.\n */\n static async findLatestSpec(specsDir: string): Promise<{\n filePath: string;\n version: number;\n slug: string;\n content: string;\n } | null> {\n if (!(await fs.pathExists(specsDir))) return null;\n\n const files = await fs.readdir(specsDir);\n const pattern = /^feature-(.+)-v(\\d+)\\.md$/;\n\n let latest: { filePath: string; version: number; slug: string; content: string } | null = null;\n\n for (const file of files) {\n const m = file.match(pattern);\n if (!m) continue;\n const version = parseInt(m[2], 10);\n if (!latest || version > latest.version) {\n const filePath = path.join(specsDir, file);\n const content = await fs.readFile(filePath, \"utf-8\");\n latest = { filePath, version, slug: m[1], content };\n }\n }\n\n return latest;\n }\n\n /**\n * Update an existing spec with a change request.\n * Generates a new version of the spec, re-extracts the DSL, and identifies affected files.\n */\n async update(\n changeRequest: string,\n existingSpecPath: string,\n projectDir: string,\n context?: ProjectContext,\n opts: SpecUpdaterOptions = {}\n ): Promise<SpecUpdateResult> {\n // ── Load existing spec ──────────────────────────────────────────────────\n const existingSpec = await fs.readFile(existingSpecPath, \"utf-8\");\n\n // ── Load existing DSL (may be absent) ──────────────────────────────────\n let existingDsl: SpecDSL | null = null;\n const dslFile = await findLatestDslFile(projectDir);\n if (dslFile) {\n try {\n existingDsl = await fs.readJson(dslFile);\n } catch { /* ignore */ }\n }\n\n // ── Step 1: Generate updated spec ──────────────────────────────────────\n console.log(chalk.blue(\" [1/3] Generating updated spec...\"));\n const updatePrompt = buildSpecUpdatePrompt(changeRequest, existingSpec, existingDsl, context);\n\n let updatedSpecContent: string;\n try {\n updatedSpecContent = await this.provider.generate(updatePrompt, specUpdateSystemPrompt);\n // Strip markdown fences if present\n updatedSpecContent = updatedSpecContent.replace(/^```(?:markdown|md)?\\n?/im, \"\").replace(/\\n?```\\s*$/im, \"\").trim();\n } catch (err) {\n throw new Error(`Spec update generation failed: ${(err as Error).message}`);\n }\n\n // ── Step 2: Write new spec version ─────────────────────────────────────\n // Extract slug from existing spec path: feature-<slug>-v<N>.md\n const specBasename = path.basename(existingSpecPath);\n const slugMatch = specBasename.match(/^feature-(.+)-v\\d+\\.md$/);\n const slug = slugMatch ? slugMatch[1] : \"feature\";\n\n const specsDir = path.dirname(existingSpecPath);\n const { filePath: newSpecPath, version: newVersion } = await nextVersionPath(specsDir, slug);\n\n await fs.ensureDir(specsDir);\n await fs.writeFile(newSpecPath, updatedSpecContent, \"utf-8\");\n console.log(chalk.green(` ✔ New spec written: ${path.relative(projectDir, newSpecPath)}`));\n\n // ── Step 3: Update DSL ─────────────────────────────────────────────────\n console.log(chalk.blue(\" [2/3] Updating DSL...\"));\n let updatedDsl: SpecDSL | null = null;\n let newDslPath: string | null = null;\n\n if (existingDsl) {\n // Use targeted DSL update prompt\n const dslUpdatePrompt = buildDslUpdatePrompt(changeRequest, existingDsl, updatedSpecContent);\n try {\n const rawDsl = await this.provider.generate(dslUpdatePrompt, dslUpdateSystemPrompt);\n const parsed = parseJsonFromOutput(rawDsl) as SpecDSL;\n if (parsed && parsed.endpoints && parsed.models) {\n updatedDsl = parsed;\n }\n } catch {\n // Fall back to full extraction\n console.log(chalk.gray(\" Targeted DSL update failed — falling back to full extraction.\"));\n }\n }\n\n if (!updatedDsl) {\n // Full extraction from updated spec\n const isFrontend = opts.repoType\n ? (FRONTEND_FRAMEWORKS as readonly string[]).includes(opts.repoType)\n : false;\n updatedDsl = await this.extractor.extract(updatedSpecContent, { auto: true, isFrontend });\n }\n\n if (updatedDsl) {\n // Save DSL alongside spec\n const dslPath = newSpecPath.replace(/\\.md$/, \".dsl.json\");\n await fs.writeJson(dslPath, updatedDsl, { spaces: 2 });\n newDslPath = dslPath;\n console.log(chalk.green(` ✔ DSL updated: ${path.relative(projectDir, dslPath)}`));\n } else {\n console.log(chalk.yellow(\" ⚠ DSL update failed — continuing without DSL.\"));\n }\n\n // ── Step 4: Identify affected files ────────────────────────────────────\n let affectedFiles: AffectedFile[] = [];\n\n if (!opts.skipAffectedFiles && updatedDsl && existingDsl && context) {\n console.log(chalk.blue(\" [3/3] Identifying affected files...\"));\n const systemPrompt = getCodeGenSystemPrompt(opts.repoType);\n const affectedPrompt = buildAffectedFilesPrompt(\n changeRequest,\n existingDsl,\n updatedDsl,\n context.fileStructure\n );\n try {\n const affectedRaw = await this.provider.generate(affectedPrompt, systemPrompt);\n affectedFiles = parseAffectedFiles(affectedRaw);\n console.log(chalk.green(` ✔ ${affectedFiles.length} file(s) identified for update`));\n } catch {\n console.log(chalk.gray(\" Could not identify affected files — use manual selection.\"));\n }\n }\n\n return { newSpecPath, newVersion, newDslPath, affectedFiles, updatedDsl };\n }\n}\n","import { SpecDSL } from \"../core/dsl-types\";\nimport { ProjectContext } from \"../core/context-loader\";\n\n// ─── System Prompt ────────────────────────────────────────────────────────────\n\nexport const specUpdateSystemPrompt = `You are a Senior Software Architect updating an existing Feature Spec based on a change request.\n\nRules:\n1. Read the EXISTING spec carefully — understand what is already designed.\n2. Apply ONLY the changes described in the change request. Do not rewrite sections that are not affected.\n3. Preserve the original spec structure, headings, and wording for unchanged sections.\n4. For changed sections: update them in place. Clearly integrate new requirements.\n5. If a change is additive (new endpoint, new field), append it in the correct section.\n6. If a change is a modification, update the existing content — do not duplicate it.\n7. Output the COMPLETE updated spec in Markdown. All original sections must be present.\n8. Do NOT add a changelog or \"Changes in v2\" annotation inside the spec body — the versioning is handled externally.\n\nOutput: the full updated Markdown spec, nothing else.`;\n\nexport const dslUpdateSystemPrompt = `You are a precise DSL extractor updating an existing SpecDSL JSON based on a change request.\n\nYou will receive:\n- The ORIGINAL DSL (JSON)\n- The UPDATED spec (Markdown)\n- The CHANGE DESCRIPTION\n\nRules:\n1. Output a COMPLETE updated DSL JSON that represents the full updated spec.\n2. Preserve all unchanged endpoints, models, and behaviors exactly.\n3. For changed or new items: apply the change precisely.\n4. For removed items: omit them from the output.\n5. Follow the same DSL structure: version, feature, models, endpoints, behaviors, components.\n6. Output ONLY valid JSON — no markdown fences, no explanations.`;\n\n// ─── User Prompts ─────────────────────────────────────────────────────────────\n\nexport function buildSpecUpdatePrompt(\n changeRequest: string,\n existingSpec: string,\n existingDsl: SpecDSL | null,\n context?: ProjectContext\n): string {\n const constitutionSection = context?.constitution\n ? `\\n=== Project Constitution (all changes must comply) ===\\n${context.constitution.slice(0, 1500)}\\n`\n : \"\";\n\n const dslSummary = existingDsl\n ? `\\n=== Current DSL Summary (for reference) ===\nFeature: ${existingDsl.feature.title}\nModels: ${existingDsl.models.map((m) => m.name).join(\", \") || \"none\"}\nEndpoints: ${existingDsl.endpoints.map((e) => `${e.method} ${e.path}`).join(\", \") || \"none\"}\nBehaviors: ${existingDsl.behaviors.length}\n\\n`\n : \"\";\n\n return `You are updating an existing Feature Spec.\n\n=== Change Request ===\n${changeRequest}\n${constitutionSection}${dslSummary}\n=== Existing Spec (update this) ===\n${existingSpec}\n\nApply the change request to the spec above. Output the complete updated spec in Markdown.`;\n}\n\nexport function buildDslUpdatePrompt(\n changeRequest: string,\n originalDsl: SpecDSL,\n updatedSpec: string\n): string {\n return `Update the DSL JSON to reflect the following changes.\n\n=== Change Request ===\n${changeRequest}\n\n=== Original DSL (JSON) ===\n${JSON.stringify(originalDsl, null, 2)}\n\n=== Updated Spec (Markdown — the source of truth) ===\n${updatedSpec}\n\nOutput the complete updated DSL JSON only. No markdown fences.`;\n}\n\nexport function buildAffectedFilesPrompt(\n changeRequest: string,\n originalDsl: SpecDSL,\n updatedDsl: SpecDSL,\n projectFileStructure: string[]\n): string {\n // Compute a simple diff summary\n const addedEndpoints = updatedDsl.endpoints.filter(\n (e) => !originalDsl.endpoints.find((o) => o.id === e.id)\n );\n const modifiedEndpoints = updatedDsl.endpoints.filter((e) => {\n const orig = originalDsl.endpoints.find((o) => o.id === e.id);\n return orig && JSON.stringify(orig) !== JSON.stringify(e);\n });\n const addedModels = updatedDsl.models.filter(\n (m) => !originalDsl.models.find((o) => o.name === m.name)\n );\n const modifiedModels = updatedDsl.models.filter((m) => {\n const orig = originalDsl.models.find((o) => o.name === m.name);\n return orig && JSON.stringify(orig) !== JSON.stringify(m);\n });\n\n const diffLines: string[] = [];\n if (addedEndpoints.length) diffLines.push(`Added endpoints: ${addedEndpoints.map((e) => `${e.method} ${e.path}`).join(\", \")}`);\n if (modifiedEndpoints.length) diffLines.push(`Modified endpoints: ${modifiedEndpoints.map((e) => `${e.method} ${e.path}`).join(\", \")}`);\n if (addedModels.length) diffLines.push(`Added models: ${addedModels.map((m) => m.name).join(\", \")}`);\n if (modifiedModels.length) diffLines.push(`Modified models: ${modifiedModels.map((m) => m.name).join(\", \")}`);\n\n return `Given the DSL change below, list ONLY the files that need to be created or modified.\nDo not include files that are not affected by this change.\n\n=== Change Summary ===\n${changeRequest}\n\n=== DSL Delta ===\n${diffLines.join(\"\\n\") || \"Minor internal changes — determine affected files from the change request.\"}\n\n=== Existing Files ===\n${projectFileStructure.slice(0, 50).join(\"\\n\")}\n\nOutput ONLY a valid JSON array:\n[\n {\"file\": \"src/controllers/userController.ts\", \"action\": \"modify\", \"description\": \"Add new endpoint handler\"},\n {\"file\": \"src/routes/client/index.ts\", \"action\": \"modify\", \"description\": \"Register new route\"}\n]`;\n}\n","import * as path from \"path\";\nimport * as fs from \"fs-extra\";\nimport { SpecDSL, ApiEndpoint, DataModel, ModelField, FieldMap } from \"./dsl-types\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface OpenApiExportOptions {\n /** Output file path. Defaults to openapi.yaml in the project root. */\n outputPath?: string;\n /** API server URL (default: http://localhost:3000) */\n serverUrl?: string;\n /** Output format (default: yaml) */\n format?: \"yaml\" | \"json\";\n}\n\n// ─── Type Mapping ─────────────────────────────────────────────────────────────\n\ninterface OASchema {\n type?: string;\n format?: string;\n example?: unknown;\n $ref?: string;\n items?: OASchema;\n}\n\n/**\n * Convert a DSL type-description string to an OpenAPI schema object.\n */\nfunction dslTypeToOASchema(typeDesc: string, fieldName = \"\"): OASchema {\n const t = typeDesc.toLowerCase();\n\n if (t === \"string\" || t.includes(\"string\")) {\n const name = fieldName.toLowerCase();\n if (name.includes(\"email\")) return { type: \"string\", format: \"email\", example: \"user@example.com\" };\n if (name.includes(\"url\") || name.includes(\"image\")) return { type: \"string\", format: \"uri\", example: \"https://example.com\" };\n if (name.includes(\"datetime\") || name.includes(\"date\") || t.includes(\"datetime\") || t.includes(\"date\")) {\n return { type: \"string\", format: \"date-time\", example: \"2024-01-15T10:30:00.000Z\" };\n }\n if (name.includes(\"password\")) return { type: \"string\", format: \"password\" };\n return { type: \"string\", example: `example_${fieldName}` };\n }\n if (t.includes(\"int\") || t === \"number\") return { type: \"integer\", example: 1 };\n if (t.includes(\"float\") || t.includes(\"decimal\") || t.includes(\"double\")) return { type: \"number\", format: \"float\", example: 9.99 };\n if (t === \"boolean\" || t === \"bool\") return { type: \"boolean\", example: true };\n if (t.includes(\"datetime\") || t.includes(\"timestamp\")) return { type: \"string\", format: \"date-time\", example: \"2024-01-15T10:30:00.000Z\" };\n if (t.includes(\"[]\") || t.includes(\"array\") || t.includes(\"list\")) return { type: \"array\", items: { type: \"string\" } };\n if (t.includes(\"object\") || t.includes(\"json\") || t.includes(\"record\")) return { type: \"object\" };\n\n // If it looks like a model reference (PascalCase)\n if (/^[A-Z][a-zA-Z]+$/.test(typeDesc.trim())) {\n return { $ref: `#/components/schemas/${typeDesc.trim()}` };\n }\n\n return { type: \"string\", example: `example_${fieldName}` };\n}\n\nfunction fieldMapToOAProperties(\n fields: FieldMap,\n required?: string[]\n): { properties: Record<string, OASchema>; required?: string[] } {\n const properties: Record<string, OASchema> = {};\n for (const [name, type] of Object.entries(fields)) {\n properties[name] = dslTypeToOASchema(type, name);\n }\n const result: { properties: Record<string, OASchema>; required?: string[] } = { properties };\n if (required && required.length > 0) result.required = required;\n return result;\n}\n\nfunction modelToOASchema(model: DataModel): Record<string, unknown> {\n const properties: Record<string, OASchema> = {};\n const requiredFields: string[] = [];\n\n for (const field of model.fields) {\n properties[field.name] = dslTypeToOASchema(field.type, field.name);\n if (field.required) requiredFields.push(field.name);\n }\n\n const schema: Record<string, unknown> = {\n type: \"object\",\n properties,\n };\n if (requiredFields.length > 0) schema.required = requiredFields;\n if (model.description) schema.description = model.description;\n\n return schema;\n}\n\n// ─── Path Parameter Extraction ────────────────────────────────────────────────\n\nfunction extractPathParams(endpointPath: string): string[] {\n const matches = endpointPath.match(/\\{([^}]+)\\}|:([a-zA-Z_][a-zA-Z0-9_]*)/g) ?? [];\n return matches.map((m) => m.replace(/[{}:]/g, \"\"));\n}\n\n/**\n * Normalise DSL path (:id → {id}).\n */\nfunction normalisePath(endpointPath: string): string {\n return endpointPath.replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, \"{$1}\");\n}\n\n// ─── Endpoint to Path Item ────────────────────────────────────────────────────\n\nfunction endpointToPathItem(endpoint: ApiEndpoint): Record<string, unknown> {\n const method = endpoint.method.toLowerCase();\n const pathParams = extractPathParams(endpoint.path);\n\n const parameters: unknown[] = pathParams.map((p) => ({\n name: p,\n in: \"path\",\n required: true,\n schema: { type: \"string\" },\n description: `${p} identifier`,\n }));\n\n // Query params\n if (endpoint.request?.query) {\n for (const [name, typeDesc] of Object.entries(endpoint.request.query)) {\n parameters.push({\n name,\n in: \"query\",\n required: false,\n schema: dslTypeToOASchema(typeDesc, name),\n description: typeDesc,\n });\n }\n }\n\n const operation: Record<string, unknown> = {\n summary: endpoint.description,\n operationId: `${method}_${endpoint.path.replace(/[^a-zA-Z0-9]/g, \"_\").replace(/_+/g, \"_\").replace(/^_|_$/g, \"\")}`,\n tags: [endpoint.path.split(\"/\").filter(Boolean)[1] ?? \"default\"],\n };\n\n if (parameters.length > 0) operation.parameters = parameters;\n\n // Auth\n if (endpoint.auth) {\n operation.security = [{ bearerAuth: [] }];\n }\n\n // Request body\n if (endpoint.request?.body && Object.keys(endpoint.request.body).length > 0) {\n const bodyRequired = Object.entries(endpoint.request.body)\n .filter(([, t]) => !t.toLowerCase().includes(\"optional\"))\n .map(([k]) => k);\n operation.requestBody = {\n required: true,\n content: {\n \"application/json\": {\n schema: {\n type: \"object\",\n ...fieldMapToOAProperties(endpoint.request.body, bodyRequired),\n },\n },\n },\n };\n }\n\n // Responses\n const responses: Record<string, unknown> = {};\n\n if (endpoint.successStatus === 204) {\n responses[String(endpoint.successStatus)] = { description: endpoint.successDescription || \"No Content\" };\n } else {\n responses[String(endpoint.successStatus)] = {\n description: endpoint.successDescription || \"Success\",\n content: {\n \"application/json\": {\n schema: { type: \"object\" },\n },\n },\n };\n }\n\n if (endpoint.auth) {\n responses[\"401\"] = {\n description: \"Unauthorized — missing or invalid token\",\n content: {\n \"application/json\": {\n schema: { $ref: \"#/components/schemas/ErrorResponse\" },\n },\n },\n };\n }\n\n for (const err of endpoint.errors ?? []) {\n responses[String(err.status)] = {\n description: `${err.code} — ${err.description}`,\n content: {\n \"application/json\": {\n schema: { $ref: \"#/components/schemas/ErrorResponse\" },\n },\n },\n };\n }\n\n operation.responses = responses;\n return { [method]: operation };\n}\n\n// ─── YAML Serialiser (minimal, no external deps) ─────────────────────────────\n\nfunction toYaml(obj: unknown, indent = 0): string {\n const pad = \" \".repeat(indent);\n const childPad = \" \".repeat(indent + 1);\n\n if (obj === null || obj === undefined) return \"null\";\n if (typeof obj === \"boolean\") return String(obj);\n if (typeof obj === \"number\") return String(obj);\n if (typeof obj === \"string\") {\n // Needs quoting if it contains special chars or looks like a boolean/number\n if (\n obj.includes(\":\") ||\n obj.includes(\"#\") ||\n obj.includes(\"\\n\") ||\n obj.includes(\"'\") ||\n obj === \"true\" || obj === \"false\" ||\n /^\\d/.test(obj)\n ) {\n return `\"${obj.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"').replace(/\\n/g, \"\\\\n\")}\"`;\n }\n return obj;\n }\n\n if (Array.isArray(obj)) {\n if (obj.length === 0) return \"[]\";\n return obj.map((item) => `\\n${pad}- ${toYaml(item, indent + 1).trimStart()}`).join(\"\");\n }\n\n if (typeof obj === \"object\") {\n const entries = Object.entries(obj as Record<string, unknown>);\n if (entries.length === 0) return \"{}\";\n return entries\n .map(([k, v]) => {\n const valStr = toYaml(v, indent + 1);\n if (typeof v === \"object\" && v !== null && !Array.isArray(v) && Object.keys(v).length > 0) {\n return `\\n${pad}${k}:${valStr}`;\n }\n if (Array.isArray(v) && v.length > 0) {\n return `\\n${pad}${k}:${valStr}`;\n }\n return `\\n${pad}${k}: ${valStr}`;\n })\n .join(\"\");\n }\n\n return String(obj);\n}\n\nfunction buildYamlDoc(obj: Record<string, unknown>): string {\n return (\n \"openapi: 3.1.0\\n\" +\n Object.entries(obj)\n .filter(([k]) => k !== \"openapi\")\n .map(([k, v]) => {\n const valStr = toYaml(v, 1);\n if (typeof v === \"object\" && v !== null && Object.keys(v).length > 0) {\n return `${k}:${valStr}`;\n }\n return `${k}: ${valStr}`;\n })\n .join(\"\\n\") +\n \"\\n\"\n );\n}\n\n// ─── Main Export ──────────────────────────────────────────────────────────────\n\n/**\n * Convert a SpecDSL to an OpenAPI 3.1.0 document.\n * Returns the document as a plain JS object (can be serialised to YAML or JSON).\n */\nexport function dslToOpenApi(dsl: SpecDSL, serverUrl = \"http://localhost:3000\"): Record<string, unknown> {\n // ── Info ──────────────────────────────────────────────────────────────────\n const info = {\n title: dsl.feature.title,\n description: dsl.feature.description,\n version: \"1.0.0\",\n };\n\n // ── Paths ─────────────────────────────────────────────────────────────────\n const paths: Record<string, unknown> = {};\n for (const endpoint of dsl.endpoints) {\n const normalised = normalisePath(endpoint.path);\n if (!paths[normalised]) paths[normalised] = {};\n Object.assign(paths[normalised] as Record<string, unknown>, endpointToPathItem(endpoint));\n }\n\n // ── Schemas ───────────────────────────────────────────────────────────────\n const schemas: Record<string, unknown> = {\n ErrorResponse: {\n type: \"object\",\n properties: {\n code: { type: \"string\", example: \"ERROR_CODE\" },\n message: { type: \"string\", example: \"Human-readable error description\" },\n },\n required: [\"code\", \"message\"],\n },\n };\n\n for (const model of dsl.models) {\n schemas[model.name] = modelToOASchema(model);\n }\n\n // ── Security Schemes ──────────────────────────────────────────────────────\n const hasAuth = dsl.endpoints.some((e) => e.auth);\n const securitySchemes: Record<string, unknown> = {};\n if (hasAuth) {\n securitySchemes.bearerAuth = {\n type: \"http\",\n scheme: \"bearer\",\n bearerFormat: \"JWT\",\n };\n }\n\n // ── Assemble ──────────────────────────────────────────────────────────────\n const doc: Record<string, unknown> = {\n info,\n servers: [{ url: serverUrl, description: \"Development server\" }],\n paths,\n components: {\n schemas,\n ...(hasAuth ? { securitySchemes } : {}),\n },\n };\n\n return doc;\n}\n\n/**\n * Export a SpecDSL to an OpenAPI file (YAML or JSON) in the project directory.\n */\nexport async function exportOpenApi(\n dsl: SpecDSL,\n projectDir: string,\n opts: OpenApiExportOptions = {}\n): Promise<string> {\n const format = opts.format ?? \"yaml\";\n const serverUrl = opts.serverUrl ?? \"http://localhost:3000\";\n const defaultName = `openapi.${format}`;\n const outputPath = opts.outputPath\n ? path.isAbsolute(opts.outputPath)\n ? opts.outputPath\n : path.join(projectDir, opts.outputPath)\n : path.join(projectDir, defaultName);\n\n const doc = dslToOpenApi(dsl, serverUrl);\n\n let content: string;\n if (format === \"json\") {\n content = JSON.stringify(doc, null, 2);\n } else {\n content = buildYamlDoc(doc);\n }\n\n await fs.ensureDir(path.dirname(outputPath));\n await fs.writeFile(outputPath, content, \"utf-8\");\n return outputPath;\n}\n"],"mappings":"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","names":["n","fs","path","config","stat","path","fs","import_chalk","import_prompts","k","v","Anthropic","OpenAI","axios","fs","path","import_node_url","balanced","a","b","str","ma","maybeMatch","mb","range","reg","m","begs","beg","left","right","result","ai","bi","i","r","escSlash","escOpen","escClose","escComma","escPeriod","escSlashPattern","escOpenPattern","escClosePattern","escCommaPattern","escPeriodPattern","slashPattern","openPattern","closePattern","commaPattern","periodPattern","EXPANSION_MAX","numeric","escapeBraces","unescapeBraces","parseCommaParts","parts","pre","body","post","p","postParts","expand","options","max","expand_","embrace","isPadded","el","lte","y","gte","isTop","expansions","k","expansion","isNumericSequence","isAlphaSequence","isSequence","isOptions","n","N","x","width","incr","test","pad","c","need","z","j","assertValidPattern","pattern","posixClasses","braceEscape","s","regexpEscape","rangesToString","ranges","parseClass","glob","position","pos","negs","sawStart","uflag","escaping","negate","endPos","rangeStart","WHILE","cls","unip","u","neg","sranges","snegs","unescape","windowsPathsNoEscape","magicalBraces","types","isExtglobType","startNoTraversal","startNoDot","addPatternStart","justDots","reSpecials","regExpEscape","qmark","star","starNoEmpty","AST","_AST","#root","#hasMagic","#uflag","#parts","#parent","#parentIndex","#negs","#filledNegs","#options","#toString","#emptyExt","type","parent","#fillNegs","pp","part","ret","pl","#parseAST","ast","opt","inBrace","braceStart","braceNeg","acc","ext","re","hasMagic","flags","allowDot","dot","noEmpty","src","_","#parseGlob","start","aps","needNoTrav","needNoDot","end","repeated","#partsToRegExp","bodyDotAllowed","final","close","_hasMagic","inStar","needUflag","consumed","magic","escape","minimatch","Minimatch","starDotExtRE","starDotExtTest","f","starDotExtTestDot","starDotExtTestNocase","starDotExtTestNocaseDot","starDotStarRE","starDotStarTest","starDotStarTestDot","dotStarRE","dotStarTest","starRE","starTest","starTestDot","qmarksRE","qmarksTestNocase","$0","noext","qmarksTestNoExt","qmarksTestNocaseDot","qmarksTestNoExtDot","qmarksTestDot","qmarksTest","len","defaultPlatform","path","sep","GLOBSTAR","twoStarDot","twoStarNoDot","filter","defaults","def","orig","list","braceExpand","makeRe","match","mm","globMagic","awe","args","rawGlobParts","set","__","isUNC","isDrive","ss","globParts","optimizationLevel","gs","prev","didSomething","dd","gss","next","p2","other","splin","matched","emptyGSMatch","which","negateOffset","file","partial","fileDrive","fileUNC","patternDrive","patternUNC","fdi","pdi","fd","pd","fi","pi","fl","fr","pr","swallowee","hit","fastTest","twoStar","filtered","prefixes","open","ff","filename","defaultPerf","warned","PROCESS","emitWarning","msg","code","fn","AC","AS","warnACPolyfill","reason","printACPolyfillWarning","shouldWarn","isPosInt","getUintArray","ZeroArray","size","Stack","_Stack","#constructing","HeapCls","LRUCache","_LRUCache","#max","#maxSize","#dispose","#onInsert","#disposeAfter","#fetchMethod","#memoMethod","#perf","#size","#calculatedSize","#keyMap","#keyList","#valList","#next","#prev","#head","#tail","#free","#disposed","#sizes","#starts","#ttls","#autopurgeTimers","#hasDispose","#hasFetchMethod","#hasDisposeAfter","#hasOnInsert","#isBackgroundFetch","index","context","#backgroundFetch","#moveToTail","#indexes","#rindexes","#isStale","ttl","ttlResolution","ttlAutopurge","updateAgeOnGet","updateAgeOnHas","allowStale","dispose","onInsert","disposeAfter","noDisposeOnSet","noUpdateTTL","maxSize","maxEntrySize","sizeCalculation","fetchMethod","memoMethod","noDeleteOnFetchRejection","noDeleteOnStaleGet","allowStaleOnFetchRejection","allowStaleOnFetchAbort","ignoreFetchAbort","perf","UintArray","#initializeSizeTracking","#initializeTTLTracking","key","ttls","starts","purgeTimers","#setItemTTL","t","#delete","#updateItemAge","#statusTTL","status","cachedNow","getNow","age","sizes","#removeItemSize","#requireSize","v","#addItemSize","#evict","_i","_s","_st","_k","_v","#isValidIndex","getOptions","value","thisp","deleted","entry","remain","arr","setOptions","oldVal","oldValue","dt","task","val","free","head","hasOptions","peekOptions","ac","signal","fetchOpts","cb","updateCache","aborted","ignoreAbort","proceed","fetchFail","bf","vl","eb","er","allowStaleAborted","noDelete","pcall","res","rej","fmp","fetchOptions","forceRefresh","stale","isStale","staleVal","memoOptions","vv","fetching","#connect","#clear","ni","proc","isStream","Minipass","Stream","isReadable","isWritable","EventEmitter","EOF","MAYBE_EMIT_END","EMITTED_END","EMITTING_END","EMITTED_ERROR","CLOSED","READ","FLUSH","FLUSHCHUNK","ENCODING","DECODER","FLOWING","PAUSED","RESUME","BUFFER","PIPES","BUFFERLENGTH","BUFFERPUSH","BUFFERSHIFT","OBJECTMODE","DESTROYED","ERROR","EMITDATA","EMITEND","EMITEND2","ASYNC","ABORT","ABORTED","SIGNAL","DATALISTENERS","DISCARDED","defer","nodefer","isEndish","ev","isArrayBufferLike","isArrayBufferView","Pipe","dest","opts","_er","PipeProxyErrors","isObjectModeOptions","o","isEncodingOptions","StringDecoder","_enc","_om","chunk","encoding","noDrain","ended","handler","h","data","buf","resolve","reject","stopped","stop","onerr","ondata","onend","ondestroy","wc","realpathSync","rps","defaultFS","lstatSync","readdirCB","readdirSync","readlinkSync","lstat","readdir","readlink","realpath","fsFromOption","fsOption","actualFS","uncDriveRegexp","uncToDrive","rootPath","eitherSep","UNKNOWN","IFIFO","IFCHR","IFDIR","IFBLK","IFREG","IFLNK","IFSOCK","IFMT","IFMT_UNKNOWN","READDIR_CALLED","LSTAT_CALLED","ENOTDIR","ENOENT","ENOREADLINK","ENOREALPATH","ENOCHILD","TYPEMASK","entToType","normalizeCache","L","normalize","normalizeNocaseCache","normalizeNocase","ResolveCache","ChildrenCache","setAsCwd","PathBase","#fs","#dev","#mode","#nlink","#uid","#gid","#rdev","#blksize","#ino","#blocks","#atimeMs","#mtimeMs","#ctimeMs","#birthtimeMs","#atime","#mtime","#ctime","#birthtime","#matchName","#depth","#fullpath","#fullpathPosix","#relative","#relativePosix","#type","#children","#linkTarget","#realpath","name","root","roots","nocase","children","dirParts","#resolveParts","cached","pathPart","fullpath","pchild","pv","fp","pfpp","fpp","ifmt","target","read","linkTarget","#readlinkFail","#readdirSuccess","#markENOENT","#markChildrenENOENT","#markENOREALPATH","#markENOTDIR","#readdirFail","#lstatFail","ter","#readdirAddChild","e","#readdirMaybePromoteChild","#readdirAddNewChild","child","#readdirPromoteChild","#applyStat","st","atime","atimeMs","birthtime","birthtimeMs","blksize","blocks","ctime","ctimeMs","dev","gid","ino","mode","mtime","mtimeMs","nlink","rdev","uid","#onReaddirCB","#readdirCBInFlight","#callOnReaddirCB","cbs","allowZalgo","entries","#asyncReaddirInFlight","dirs","walkFilter","rp","oldCwd","changed","PathWin32","_PathWin32","win32","compare","PathScurryWin32","PathPosix","_PathPosix","_rootPath","PathScurryBase","#resolveCache","#resolvePosixCache","cwd","pathImpl","childrenCacheSize","fs","fileURLToPath","cwdPath","split","joinSep","abs","sawFirst","l","paths","withFileTypes","follow","results","walk","dir","queue","processing","process","paused","onReaddir","didRealpaths","promises","sync","PathScurryPosix","posix","_dir","PathScurryDarwin","Path","PathScurry","isPatternList","isGlobList","gl","customInspect","Pattern","_Pattern","#patternList","#globList","#index","#platform","#rest","#globString","#isDrive","#isUNC","#isAbsolute","#followGlobstar","patternList","globList","platform","p0","p1","p3","prest","g0","g1","g2","g3","grest","g","Ignore","ignored","nobrace","noglobstar","ign","parsed","absolute","fullpaths","relative","relatives","HasWalkedCache","_HasWalkedCache","store","MatchRecord","ifDir","current","SubWalks","subs","Processor","_Processor","hasWalkedCache","patterns","processingSet","rest","rrest","tp","ep","makeIgnore","ignore","GlobUtil","#onResume","#ignore","#sep","#ignored","#childrenIgnored","rpc","mark","rel","processor","tasks","childrenCached","GlobWalker","GlobStream","Glob","Scurry","nocaseMagicOnly","mmo","mms","matchSet","globStreamSync","globStream","globSync","glob_","globIterateSync","globIterate","streamSync","stream","iterateSync","iterate","fs","os","require","import_chalk","fs","path","n","i","j","chalk","k","chalk","import_chalk","path","fs","import_chalk","fs","path","chalk","import_chalk","fs","path","import_prompts","import_chalk","path","j","k","v","cs","chalk","chalk","k","v","fs","path","chalk","LAYER_ORDER","import_chalk","import_child_process","path","fs","chalk","import_child_process","path","fs","import_chalk","chalk","import_chalk","fs","path","import_chalk","fs","path","chalk","import_chalk","fs","path","k","v","chalk","import_chalk","import_child_process","fs","path","chalk","import_chalk","chalk","import_chalk","fs","path","chalk","fs","path","os","import_chalk","os","path","fs","chalk","stat","ms","config","parseJsonFromOutput","path","fs","stat","import_chalk","path","fs","parseJsonFromOutput","chalk","path","fs","k","v","v","chalk","config","confirm2","isFrontendProject","saved","k","meta","dsl","result"]}