shipfolio 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -457,34 +457,68 @@ var init_logger = __esm({
457
457
  // src/scanner/index.ts
458
458
  import ora from "ora";
459
459
  async function scanProjects(directories) {
460
- const allRepos = [];
460
+ const allPaths = [];
461
461
  const spinner = ora("Scanning for projects...").start();
462
462
  for (const dir of directories) {
463
463
  try {
464
464
  const repos = await findGitRepos(dir);
465
- allRepos.push(...repos);
465
+ allPaths.push(...repos);
466
+ const nonGitDirs = await findNonGitProjects(dir, new Set(repos));
467
+ allPaths.push(...nonGitDirs);
466
468
  } catch (err) {
467
469
  logger.warn(`Could not scan ${dir}: ${err}`);
468
470
  }
469
471
  }
470
- const uniqueRepos = [...new Set(allRepos)];
471
- spinner.text = `Found ${uniqueRepos.length} repositories. Extracting metadata...`;
472
+ const uniquePaths = [...new Set(allPaths)];
473
+ spinner.text = `Found ${uniquePaths.length} projects. Extracting metadata...`;
472
474
  const projects = [];
473
- for (const repoPath of uniqueRepos) {
475
+ for (const projectPath of uniquePaths) {
474
476
  try {
475
- const project = await extractProjectMeta(repoPath);
477
+ const project = await extractProjectMeta(projectPath);
476
478
  if (project) {
477
479
  projects.push(project);
478
480
  }
479
481
  } catch (err) {
480
482
  }
481
483
  }
484
+ const idCounts = /* @__PURE__ */ new Map();
485
+ for (const project of projects) {
486
+ const count = idCounts.get(project.id) || 0;
487
+ if (count > 0) {
488
+ project.id = `${project.id}-${count}`;
489
+ }
490
+ idCounts.set(project.id.replace(/-\d+$/, ""), count + 1);
491
+ }
482
492
  spinner.succeed(`Scanned ${projects.length} projects`);
483
493
  return projects;
484
494
  }
495
+ async function findNonGitProjects(rootPath, gitRepos) {
496
+ const { glob: glob2 } = await import("glob");
497
+ const indicators = [
498
+ "*/package.json",
499
+ "*/Cargo.toml",
500
+ "*/go.mod",
501
+ "*/pyproject.toml",
502
+ "*/requirements.txt",
503
+ "*/setup.py"
504
+ ];
505
+ const found = /* @__PURE__ */ new Set();
506
+ for (const pattern of indicators) {
507
+ const matches = await glob2(pattern, {
508
+ cwd: rootPath,
509
+ ignore: ["**/node_modules/**", "**/vendor/**"]
510
+ });
511
+ for (const match of matches) {
512
+ const dir = `${rootPath}/${match.split("/")[0]}`;
513
+ if (!gitRepos.has(dir) && !found.has(dir)) {
514
+ found.add(dir);
515
+ }
516
+ }
517
+ }
518
+ return [...found].sort();
519
+ }
485
520
  async function extractProjectMeta(projectPath) {
486
521
  const gitMeta = await getGitMeta(projectPath);
487
- if (!gitMeta.isRepo) return null;
488
522
  let techStack = [];
489
523
  let name = null;
490
524
  let description = null;
@@ -524,7 +558,8 @@ async function extractProjectMeta(projectPath) {
524
558
  if (!name) {
525
559
  name = deriveNameFromPath(projectPath);
526
560
  }
527
- const id = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
561
+ const folderName = deriveNameFromPath(projectPath);
562
+ const id = folderName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
528
563
  return {
529
564
  id,
530
565
  name,
@@ -620,49 +655,161 @@ function handleCancel(value) {
620
655
  process.exit(0);
621
656
  }
622
657
  }
658
+ async function runMergeStep(projects) {
659
+ const shouldMerge = await p.confirm({
660
+ message: "Merge any related projects into one entry? (e.g. web + mobile)",
661
+ initialValue: false
662
+ });
663
+ handleCancel(shouldMerge);
664
+ if (!shouldMerge) return projects;
665
+ let remaining = [...projects];
666
+ while (remaining.length >= 2) {
667
+ const mergeIds = await p.multiselect({
668
+ message: "Select projects to merge together (space = select, enter = confirm):",
669
+ options: remaining.map((proj) => ({
670
+ value: proj.id,
671
+ label: `${proj.name} (${proj.localPath})`,
672
+ hint: proj.techStack.slice(0, 3).join(", ")
673
+ })),
674
+ required: true
675
+ });
676
+ handleCancel(mergeIds);
677
+ if (mergeIds.length < 2) {
678
+ logger.warn("Need at least 2 projects to merge. Skipping.");
679
+ break;
680
+ }
681
+ const toMerge = mergeIds.map(
682
+ (id) => remaining.find((p6) => p6.id === id)
683
+ );
684
+ const defaultName = toMerge.map((p6) => p6.name).join(" + ");
685
+ const mergedName = await p.text({
686
+ message: "Name for the merged entry:",
687
+ placeholder: defaultName,
688
+ defaultValue: defaultName
689
+ });
690
+ handleCancel(mergedName);
691
+ const merged = mergeProjects(toMerge, mergedName);
692
+ remaining = remaining.filter((p6) => !mergeIds.includes(p6.id));
693
+ remaining.push(merged);
694
+ logger.info(
695
+ `Merged ${toMerge.map((p6) => p6.name).join(", ")} -> "${mergedName}"`
696
+ );
697
+ if (remaining.length < 2) break;
698
+ const more = await p.confirm({
699
+ message: "Merge more projects?",
700
+ initialValue: false
701
+ });
702
+ handleCancel(more);
703
+ if (!more) break;
704
+ }
705
+ return remaining;
706
+ }
707
+ function mergeProjects(projects, name) {
708
+ const allChildren = [];
709
+ for (const proj of projects) {
710
+ if (proj.children && proj.children.length > 0) {
711
+ allChildren.push(...proj.children);
712
+ } else {
713
+ const { children, ...rest } = proj;
714
+ allChildren.push(rest);
715
+ }
716
+ }
717
+ const techStack = [
718
+ ...new Set(allChildren.flatMap((p6) => p6.techStack))
719
+ ];
720
+ const languages = {};
721
+ for (const child of allChildren) {
722
+ for (const [lang, count] of Object.entries(child.languages)) {
723
+ languages[lang] = (languages[lang] || 0) + count;
724
+ }
725
+ }
726
+ const firstDates = allChildren.map((p6) => p6.firstCommitDate).filter(Boolean).sort();
727
+ const lastDates = allChildren.map((p6) => p6.lastCommitDate).filter(Boolean).sort();
728
+ const totalCommits = allChildren.reduce(
729
+ (sum, p6) => sum + p6.totalCommits,
730
+ 0
731
+ );
732
+ const remoteUrl = allChildren.find((p6) => p6.remoteUrl)?.remoteUrl || null;
733
+ const demoUrl = allChildren.find((p6) => p6.demoUrl)?.demoUrl || null;
734
+ const readmeParts = allChildren.filter((p6) => p6.readmeContent).map(
735
+ (p6) => `--- ${p6.name} ---
736
+ ${p6.readmeContent}`
737
+ );
738
+ const readmeContent = readmeParts.length > 0 ? readmeParts.join("\n\n") : null;
739
+ const descriptions = allChildren.map((p6) => p6.description).filter(Boolean);
740
+ const description = descriptions.join(" | ");
741
+ const localPath = allChildren[0].localPath;
742
+ const id = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
743
+ return {
744
+ id,
745
+ name,
746
+ localPath,
747
+ description,
748
+ techStack,
749
+ languages,
750
+ firstCommitDate: firstDates[0] || "",
751
+ lastCommitDate: lastDates[lastDates.length - 1] || "",
752
+ totalCommits,
753
+ remoteUrl,
754
+ demoUrl,
755
+ readmeContent,
756
+ lastScannedCommit: allChildren[0].lastScannedCommit || "",
757
+ children: allChildren
758
+ };
759
+ }
623
760
  async function runInterview(scannedProjects, availableEngines) {
624
761
  p.intro("shipfolio");
625
762
  logger.header("Project Selection");
626
- const projectOptions = scannedProjects.map((proj) => ({
627
- value: proj.id,
628
- label: `${proj.name}`,
629
- hint: `${proj.techStack.slice(0, 3).join(", ")} | ${proj.totalCommits} commits`
630
- }));
763
+ const projectOptions = scannedProjects.map((proj) => {
764
+ const techInfo = proj.techStack.slice(0, 3).join(", ");
765
+ const commitInfo = proj.totalCommits > 0 ? `${proj.totalCommits} commits` : "no git";
766
+ return {
767
+ value: proj.id,
768
+ label: `${proj.name} (${proj.localPath})`,
769
+ hint: techInfo ? `${techInfo} | ${commitInfo}` : commitInfo
770
+ };
771
+ });
631
772
  const selectedIds = await p.multiselect({
632
- message: "Select projects to include:",
773
+ message: "Select projects to include (space = select, enter = confirm):",
633
774
  options: projectOptions,
634
775
  required: true
635
776
  });
636
777
  handleCancel(selectedIds);
778
+ let selectedMetas = selectedIds.map(
779
+ (id) => scannedProjects.find((p6) => p6.id === id)
780
+ );
781
+ if (selectedMetas.length >= 2) {
782
+ selectedMetas = await runMergeStep(selectedMetas);
783
+ }
637
784
  const projectEntries = [];
638
- for (const id of selectedIds) {
639
- const meta = scannedProjects.find((p6) => p6.id === id);
785
+ for (const meta of selectedMetas) {
786
+ const displayName = meta.children ? `${meta.name} (${meta.children.length} sub-projects)` : meta.name;
640
787
  logger.plain(`
641
- Configuring: ${meta.name}`);
788
+ Configuring: ${displayName}`);
642
789
  const overrideDesc = await p.text({
643
- message: `Description for ${meta.name} (enter to use auto-generated):`,
790
+ message: `Description for ${displayName} (enter to use auto-generated):`,
644
791
  placeholder: meta.description?.slice(0, 80) || "Auto-generate from README",
645
792
  defaultValue: ""
646
793
  });
647
794
  handleCancel(overrideDesc);
648
795
  const demoUrl = await p.text({
649
- message: `Demo URL for ${meta.name}:`,
796
+ message: `Demo URL for ${displayName}:`,
650
797
  placeholder: meta.demoUrl || "none",
651
798
  defaultValue: meta.demoUrl || ""
652
799
  });
653
800
  handleCancel(demoUrl);
654
801
  const showSource = await p.confirm({
655
- message: `Show source code link for ${meta.name}?`,
802
+ message: `Show source code link for ${displayName}?`,
656
803
  initialValue: !!meta.remoteUrl
657
804
  });
658
805
  handleCancel(showSource);
659
806
  const role = await p.select({
660
- message: `Your role in ${meta.name}:`,
807
+ message: `Your role in ${displayName}:`,
661
808
  options: ROLE_OPTIONS
662
809
  });
663
810
  handleCancel(role);
664
811
  const metricsInput = await p.text({
665
- message: `Key metrics for ${meta.name} (e.g. "1k users, $5k MRR"):`,
812
+ message: `Key metrics for ${displayName} (e.g. "1k users, $5k MRR"):`,
666
813
  placeholder: "optional",
667
814
  defaultValue: ""
668
815
  });
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../src/scanner/git.ts","../src/utils/fs.ts","../src/scanner/detectors/node.ts","../src/scanner/detectors/python.ts","../src/scanner/detectors/rust.ts","../src/scanner/detectors/go.ts","../src/scanner/detectors/generic.ts","../src/scanner/extractors.ts","../src/utils/logger.ts","../src/scanner/index.ts","../src/interviewer/questions.ts","../src/interviewer/index.ts","../src/spec/builder.ts","../src/orchestrator/prompt-builder.ts","../src/utils/exec.ts","../src/orchestrator/detect.ts","../src/orchestrator/engines/claude.ts","../src/orchestrator/engines/codex.ts","../src/orchestrator/engines/v0.ts","../src/orchestrator/validator.ts","../src/orchestrator/index.ts","../src/deployer/auth.ts","../src/deployer/cloudflare.ts","../src/deployer/vercel.ts","../src/deployer/github.ts","../src/deployer/index.ts","../src/pdf/index.ts","../src/commands/init.ts","../src/index.ts","../src/commands/update.ts","../src/spec/diff.ts","../src/commands/spec.ts","../src/commands/deploy.ts","../src/commands/pdf.ts","../src/commands/preview.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import simpleGit from \"simple-git\";\nimport { basename } from \"node:path\";\n\nexport interface GitMeta {\n isRepo: boolean;\n firstCommitDate: string | null;\n lastCommitDate: string | null;\n totalCommits: number;\n remoteUrl: string | null;\n lastCommitHash: string | null;\n}\n\nexport async function getGitMeta(projectPath: string): Promise<GitMeta> {\n const git = simpleGit(projectPath);\n const empty: GitMeta = {\n isRepo: false,\n firstCommitDate: null,\n lastCommitDate: null,\n totalCommits: 0,\n remoteUrl: null,\n lastCommitHash: null,\n };\n\n try {\n const isRepo = await git.checkIsRepo();\n if (!isRepo) return empty;\n } catch {\n return empty;\n }\n\n try {\n const log = await git.log({ maxCount: 1 });\n\n // Get first commit date\n let firstCommitDate: string | null = null;\n try {\n const firstResult = await git.raw([\"log\", \"--reverse\", \"--format=%aI\", \"--max-count=1\"]);\n firstCommitDate = firstResult.trim() || null;\n } catch {\n // ignore\n }\n\n let remoteUrl: string | null = null;\n try {\n const remotes = await git.getRemotes(true);\n const origin = remotes.find((r) => r.name === \"origin\");\n if (origin?.refs?.fetch) {\n remoteUrl = normalizeGitUrl(origin.refs.fetch);\n }\n } catch {\n // no remotes\n }\n\n // Get total commit count\n let totalCommits = 0;\n try {\n const result = await git.raw([\"rev-list\", \"--count\", \"HEAD\"]);\n totalCommits = parseInt(result.trim(), 10) || 0;\n } catch {\n totalCommits = 0;\n }\n\n return {\n isRepo: true,\n firstCommitDate,\n lastCommitDate: log.latest?.date || null,\n totalCommits,\n remoteUrl,\n lastCommitHash: log.latest?.hash || null,\n };\n } catch {\n return { ...empty, isRepo: true };\n }\n}\n\nfunction normalizeGitUrl(url: string): string {\n // Convert SSH to HTTPS\n if (url.startsWith(\"git@\")) {\n url = url.replace(\":\", \"/\").replace(\"git@\", \"https://\");\n }\n // Remove .git suffix\n if (url.endsWith(\".git\")) {\n url = url.slice(0, -4);\n }\n return url;\n}\n\nexport async function findGitRepos(\n rootPath: string,\n maxDepth: number = 3\n): Promise<string[]> {\n const { glob } = await import(\"glob\");\n const gitDirs = await glob(\"**/.git\", {\n cwd: rootPath,\n maxDepth: maxDepth + 1,\n dot: true,\n ignore: [\n \"**/node_modules/**/.git\",\n \"**/vendor/**/.git\",\n \"**/__pycache__/**/.git\",\n ],\n });\n\n return gitDirs\n .map((gitDir) => {\n const parts = gitDir.split(\"/\");\n parts.pop(); // remove .git\n return parts.length > 0\n ? `${rootPath}/${parts.join(\"/\")}`\n : rootPath;\n })\n .sort();\n}\n","import { readFile, writeFile, access, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport async function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function readJson<T = unknown>(path: string): Promise<T> {\n const content = await readFile(path, \"utf-8\");\n return JSON.parse(content) as T;\n}\n\nexport async function writeJson(path: string, data: unknown): Promise<void> {\n await writeFile(path, JSON.stringify(data, null, 2), \"utf-8\");\n}\n\nexport async function readText(path: string): Promise<string> {\n return readFile(path, \"utf-8\");\n}\n\nexport async function writeText(path: string, content: string): Promise<void> {\n await writeFile(path, content, \"utf-8\");\n}\n\nexport async function ensureDir(path: string): Promise<void> {\n await mkdir(path, { recursive: true });\n}\n\nexport { join };\n","import { fileExists, readJson, join } from \"../../utils/fs.js\";\n\ninterface PackageJson {\n name?: string;\n description?: string;\n homepage?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nexport async function detectNode(projectPath: string) {\n const pkgPath = join(projectPath, \"package.json\");\n if (!(await fileExists(pkgPath))) return null;\n\n const pkg = await readJson<PackageJson>(pkgPath);\n const allDeps = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n const depNames = Object.keys(allDeps);\n\n const techStack: string[] = [];\n\n // Frameworks\n if (depNames.includes(\"next\")) techStack.push(\"Next.js\");\n else if (depNames.includes(\"nuxt\")) techStack.push(\"Nuxt\");\n else if (depNames.includes(\"astro\")) techStack.push(\"Astro\");\n else if (depNames.includes(\"svelte\") || depNames.includes(\"@sveltejs/kit\"))\n techStack.push(\"Svelte\");\n\n // UI libraries\n if (depNames.includes(\"react\")) techStack.push(\"React\");\n if (depNames.includes(\"vue\")) techStack.push(\"Vue\");\n\n // Styling\n if (depNames.includes(\"tailwindcss\")) techStack.push(\"Tailwind CSS\");\n\n // Backend\n if (depNames.includes(\"express\")) techStack.push(\"Express\");\n if (depNames.includes(\"fastify\")) techStack.push(\"Fastify\");\n if (depNames.includes(\"hono\")) techStack.push(\"Hono\");\n\n // Database\n if (depNames.includes(\"prisma\") || depNames.includes(\"@prisma/client\"))\n techStack.push(\"Prisma\");\n if (depNames.includes(\"drizzle-orm\")) techStack.push(\"Drizzle\");\n if (depNames.includes(\"mongoose\")) techStack.push(\"MongoDB\");\n\n // AI/ML\n if (depNames.includes(\"openai\")) techStack.push(\"OpenAI\");\n if (depNames.includes(\"@anthropic-ai/sdk\")) techStack.push(\"Claude API\");\n if (depNames.includes(\"langchain\")) techStack.push(\"LangChain\");\n\n // Language\n if (depNames.includes(\"typescript\")) techStack.push(\"TypeScript\");\n else techStack.push(\"JavaScript\");\n\n return {\n name: pkg.name || null,\n description: pkg.description || null,\n homepage: pkg.homepage || null,\n techStack,\n };\n}\n","import { fileExists, readText, join } from \"../../utils/fs.js\";\n\nexport async function detectPython(projectPath: string) {\n const techStack: string[] = [\"Python\"];\n\n const reqPath = join(projectPath, \"requirements.txt\");\n const pyprojectPath = join(projectPath, \"pyproject.toml\");\n const setupPath = join(projectPath, \"setup.py\");\n\n let deps = \"\";\n\n if (await fileExists(reqPath)) {\n deps = await readText(reqPath);\n } else if (await fileExists(pyprojectPath)) {\n deps = await readText(pyprojectPath);\n } else if (await fileExists(setupPath)) {\n deps = await readText(setupPath);\n } else {\n return null;\n }\n\n const depsLower = deps.toLowerCase();\n\n if (depsLower.includes(\"django\")) techStack.push(\"Django\");\n if (depsLower.includes(\"flask\")) techStack.push(\"Flask\");\n if (depsLower.includes(\"fastapi\")) techStack.push(\"FastAPI\");\n if (depsLower.includes(\"pytorch\") || depsLower.includes(\"torch\"))\n techStack.push(\"PyTorch\");\n if (depsLower.includes(\"tensorflow\")) techStack.push(\"TensorFlow\");\n if (depsLower.includes(\"transformers\")) techStack.push(\"Transformers\");\n if (depsLower.includes(\"langchain\")) techStack.push(\"LangChain\");\n if (depsLower.includes(\"openai\")) techStack.push(\"OpenAI\");\n if (depsLower.includes(\"pandas\")) techStack.push(\"Pandas\");\n if (depsLower.includes(\"numpy\")) techStack.push(\"NumPy\");\n if (depsLower.includes(\"scikit\")) techStack.push(\"Scikit-learn\");\n\n return { techStack };\n}\n","import { fileExists, readText, join } from \"../../utils/fs.js\";\n\nexport async function detectRust(projectPath: string) {\n const cargoPath = join(projectPath, \"Cargo.toml\");\n if (!(await fileExists(cargoPath))) return null;\n\n const content = await readText(cargoPath);\n const techStack: string[] = [\"Rust\"];\n\n if (content.includes(\"actix\")) techStack.push(\"Actix\");\n if (content.includes(\"axum\")) techStack.push(\"Axum\");\n if (content.includes(\"tokio\")) techStack.push(\"Tokio\");\n if (content.includes(\"wasm\")) techStack.push(\"WebAssembly\");\n if (content.includes(\"tauri\")) techStack.push(\"Tauri\");\n if (content.includes(\"diesel\")) techStack.push(\"Diesel\");\n if (content.includes(\"sqlx\")) techStack.push(\"SQLx\");\n\n // Extract name from [package] section\n const nameMatch = content.match(/\\[package\\][\\s\\S]*?name\\s*=\\s*\"([^\"]+)\"/);\n const descMatch = content.match(\n /\\[package\\][\\s\\S]*?description\\s*=\\s*\"([^\"]+)\"/\n );\n\n return {\n name: nameMatch?.[1] || null,\n description: descMatch?.[1] || null,\n techStack,\n };\n}\n","import { fileExists, readText, join } from \"../../utils/fs.js\";\n\nexport async function detectGo(projectPath: string) {\n const goModPath = join(projectPath, \"go.mod\");\n if (!(await fileExists(goModPath))) return null;\n\n const content = await readText(goModPath);\n const techStack: string[] = [\"Go\"];\n\n if (content.includes(\"gin-gonic\")) techStack.push(\"Gin\");\n if (content.includes(\"echo\")) techStack.push(\"Echo\");\n if (content.includes(\"fiber\")) techStack.push(\"Fiber\");\n if (content.includes(\"grpc\")) techStack.push(\"gRPC\");\n if (content.includes(\"gorm\")) techStack.push(\"GORM\");\n if (content.includes(\"cobra\")) techStack.push(\"Cobra\");\n if (content.includes(\"ent\")) techStack.push(\"Ent\");\n\n return { techStack };\n}\n","import { glob } from \"glob\";\nimport { basename, extname } from \"node:path\";\n\nconst EXTENSION_MAP: Record<string, string> = {\n \".ts\": \"TypeScript\",\n \".tsx\": \"TypeScript\",\n \".js\": \"JavaScript\",\n \".jsx\": \"JavaScript\",\n \".py\": \"Python\",\n \".rs\": \"Rust\",\n \".go\": \"Go\",\n \".java\": \"Java\",\n \".kt\": \"Kotlin\",\n \".swift\": \"Swift\",\n \".rb\": \"Ruby\",\n \".php\": \"PHP\",\n \".cs\": \"C#\",\n \".cpp\": \"C++\",\n \".c\": \"C\",\n \".dart\": \"Dart\",\n \".lua\": \"Lua\",\n \".zig\": \"Zig\",\n \".sol\": \"Solidity\",\n \".ex\": \"Elixir\",\n \".exs\": \"Elixir\",\n};\n\nconst IGNORE_DIRS = [\n \"node_modules\",\n \".git\",\n \"dist\",\n \"build\",\n \"out\",\n \".next\",\n \"target\",\n \"vendor\",\n \"__pycache__\",\n \".venv\",\n \"venv\",\n];\n\nexport async function detectLanguages(\n projectPath: string\n): Promise<Record<string, number>> {\n const ignorePattern = IGNORE_DIRS.map((d) => `**/${d}/**`);\n const files = await glob(\"**/*.*\", {\n cwd: projectPath,\n ignore: ignorePattern,\n nodir: true,\n maxDepth: 5,\n });\n\n const counts: Record<string, number> = {};\n for (const file of files) {\n const ext = extname(file).toLowerCase();\n const lang = EXTENSION_MAP[ext];\n if (lang) {\n counts[lang] = (counts[lang] || 0) + 1;\n }\n }\n\n return counts;\n}\n\nexport function deriveNameFromPath(projectPath: string): string {\n return basename(projectPath);\n}\n","import { fileExists, readText, join } from \"../utils/fs.js\";\n\nexport async function extractReadme(\n projectPath: string\n): Promise<string | null> {\n const candidates = [\n \"README.md\",\n \"readme.md\",\n \"Readme.md\",\n \"README.txt\",\n \"README\",\n ];\n for (const name of candidates) {\n const p = join(projectPath, name);\n if (await fileExists(p)) {\n const content = await readText(p);\n // Limit to first 3000 chars to keep spec manageable\n return content.slice(0, 3000);\n }\n }\n return null;\n}\n\nexport function extractFirstParagraph(readme: string | null): string | null {\n if (!readme) return null;\n // Skip title lines (# heading)\n const lines = readme.split(\"\\n\");\n let collecting = false;\n const paragraphLines: string[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.startsWith(\"#\")) {\n if (collecting && paragraphLines.length > 0) break;\n collecting = true;\n continue;\n }\n if (collecting && trimmed === \"\" && paragraphLines.length > 0) break;\n if (collecting && trimmed !== \"\") {\n paragraphLines.push(trimmed);\n }\n if (!collecting && trimmed !== \"\" && !trimmed.startsWith(\"[\")) {\n paragraphLines.push(trimmed);\n collecting = true;\n }\n }\n\n return paragraphLines.length > 0 ? paragraphLines.join(\" \") : null;\n}\n\nexport function extractDemoUrl(readme: string | null): string | null {\n if (!readme) return null;\n // Look for common demo URL patterns\n const patterns = [\n /(?:demo|live|website|site|url|link)[\\s:]*\\[?[^\\]]*\\]?\\(?(https?:\\/\\/[^\\s)]+)/i,\n /\\[(?:demo|live|website|try it)\\]\\((https?:\\/\\/[^\\s)]+)\\)/i,\n /(https?:\\/\\/[^\\s)]+\\.(?:vercel|netlify|pages\\.dev|herokuapp|railway)\\.app[^\\s)]*)/i,\n ];\n for (const pattern of patterns) {\n const match = readme.match(pattern);\n if (match?.[1]) return match[1];\n }\n return null;\n}\n","import chalk from \"chalk\";\n\nexport const logger = {\n info(msg: string) {\n console.log(chalk.cyan(`-- ${msg}`));\n },\n success(msg: string) {\n console.log(chalk.green(`-- ${msg}`));\n },\n warn(msg: string) {\n console.log(chalk.yellow(`-- ${msg}`));\n },\n error(msg: string) {\n console.error(chalk.red(`-- ${msg}`));\n },\n plain(msg: string) {\n console.log(msg);\n },\n blank() {\n console.log();\n },\n header(msg: string) {\n console.log();\n console.log(chalk.bold(msg));\n console.log();\n },\n table(rows: string[][]) {\n if (rows.length === 0) return;\n const colWidths = rows[0].map((_, colIdx) =>\n Math.max(...rows.map((row) => (row[colIdx] || \"\").length))\n );\n for (const row of rows) {\n const line = row\n .map((cell, i) => (cell || \"\").padEnd(colWidths[i] + 2))\n .join(\"\");\n console.log(` ${line}`);\n }\n },\n};\n","import { findGitRepos, getGitMeta } from \"./git.js\";\nimport { detectNode } from \"./detectors/node.js\";\nimport { detectPython } from \"./detectors/python.js\";\nimport { detectRust } from \"./detectors/rust.js\";\nimport { detectGo } from \"./detectors/go.js\";\nimport { detectLanguages, deriveNameFromPath } from \"./detectors/generic.js\";\nimport {\n extractReadme,\n extractFirstParagraph,\n extractDemoUrl,\n} from \"./extractors.js\";\nimport type { ProjectMeta } from \"../spec/schema.js\";\nimport { logger } from \"../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function scanProjects(\n directories: string[]\n): Promise<ProjectMeta[]> {\n const allRepos: string[] = [];\n\n const spinner = ora(\"Scanning for projects...\").start();\n\n for (const dir of directories) {\n try {\n const repos = await findGitRepos(dir);\n allRepos.push(...repos);\n } catch (err) {\n logger.warn(`Could not scan ${dir}: ${err}`);\n }\n }\n\n // Deduplicate\n const uniqueRepos = [...new Set(allRepos)];\n spinner.text = `Found ${uniqueRepos.length} repositories. Extracting metadata...`;\n\n const projects: ProjectMeta[] = [];\n\n for (const repoPath of uniqueRepos) {\n try {\n const project = await extractProjectMeta(repoPath);\n if (project) {\n projects.push(project);\n }\n } catch (err) {\n // Skip projects that fail extraction\n }\n }\n\n spinner.succeed(`Scanned ${projects.length} projects`);\n return projects;\n}\n\nasync function extractProjectMeta(\n projectPath: string\n): Promise<ProjectMeta | null> {\n const gitMeta = await getGitMeta(projectPath);\n if (!gitMeta.isRepo) return null;\n\n // Detect tech stack from various sources\n let techStack: string[] = [];\n let name: string | null = null;\n let description: string | null = null;\n let homepage: string | null = null;\n\n const nodeInfo = await detectNode(projectPath);\n if (nodeInfo) {\n techStack.push(...nodeInfo.techStack);\n name = nodeInfo.name || name;\n description = nodeInfo.description || description;\n homepage = nodeInfo.homepage || homepage;\n }\n\n const pythonInfo = await detectPython(projectPath);\n if (pythonInfo) {\n techStack.push(...pythonInfo.techStack);\n }\n\n const rustInfo = await detectRust(projectPath);\n if (rustInfo) {\n techStack.push(...rustInfo.techStack);\n name = rustInfo.name || name;\n description = rustInfo.description || description;\n }\n\n const goInfo = await detectGo(projectPath);\n if (goInfo) {\n techStack.push(...goInfo.techStack);\n }\n\n // Deduplicate tech stack\n techStack = [...new Set(techStack)];\n\n // Language breakdown\n const languages = await detectLanguages(projectPath);\n\n // If no tech stack detected, derive from languages\n if (techStack.length === 0) {\n const topLangs = Object.entries(languages)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 3)\n .map(([lang]) => lang);\n techStack = topLangs;\n }\n\n // README\n const readmeContent = await extractReadme(projectPath);\n if (!description) {\n description = extractFirstParagraph(readmeContent) || \"\";\n }\n\n // Demo URL\n const demoUrl = homepage || extractDemoUrl(readmeContent);\n\n // Name fallback\n if (!name) {\n name = deriveNameFromPath(projectPath);\n }\n\n // Generate stable ID from path\n const id = name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n\n return {\n id,\n name,\n localPath: projectPath,\n description: description || \"\",\n techStack,\n languages,\n firstCommitDate: gitMeta.firstCommitDate || \"\",\n lastCommitDate: gitMeta.lastCommitDate || \"\",\n totalCommits: gitMeta.totalCommits,\n remoteUrl: gitMeta.remoteUrl,\n demoUrl,\n readmeContent,\n lastScannedCommit: gitMeta.lastCommitHash || \"\",\n };\n}\n","import type {\n StyleConfig,\n SectionId,\n EngineType,\n DeployPlatform,\n} from \"../spec/schema.js\";\n\nexport const THEME_OPTIONS: { value: StyleConfig[\"theme\"]; label: string }[] = [\n { value: \"dark-minimal\", label: \"Dark Minimal\" },\n { value: \"light-clean\", label: \"Light Clean\" },\n { value: \"monochrome\", label: \"Monochrome\" },\n { value: \"custom\", label: \"Custom (AI decides)\" },\n];\n\nexport const FONT_OPTIONS: { value: StyleConfig[\"font\"]; label: string }[] = [\n { value: \"Inter\", label: \"Inter\" },\n { value: \"JetBrains Mono\", label: \"JetBrains Mono\" },\n { value: \"system\", label: \"System Default\" },\n];\n\nexport const ANIMATION_OPTIONS: {\n value: StyleConfig[\"animationLevel\"];\n label: string;\n}[] = [\n { value: \"subtle\", label: \"Subtle\" },\n { value: \"moderate\", label: \"Moderate\" },\n { value: \"none\", label: \"None\" },\n];\n\nexport const SECTION_OPTIONS: { value: SectionId; label: string }[] = [\n { value: \"skills\", label: \"Skills / Tech Stack\" },\n { value: \"about\", label: \"About Me\" },\n { value: \"timeline\", label: \"Timeline / Changelog\" },\n { value: \"blog\", label: \"Blog\" },\n { value: \"metrics\", label: \"Metrics Dashboard\" },\n { value: \"contact\", label: \"Contact\" },\n];\n\nexport const ENGINE_OPTIONS: { value: EngineType; label: string }[] = [\n { value: \"claude\", label: \"Claude Code\" },\n { value: \"codex\", label: \"Codex\" },\n { value: \"v0\", label: \"v0 (Vercel)\" },\n];\n\nexport const DEPLOY_OPTIONS: { value: DeployPlatform; label: string }[] = [\n { value: \"cloudflare\", label: \"Cloudflare Pages\" },\n { value: \"vercel\", label: \"Vercel\" },\n { value: \"local\", label: \"Local only (no deploy)\" },\n];\n\nexport const ROLE_OPTIONS: {\n value: \"solo\" | \"lead\" | \"contributor\";\n label: string;\n}[] = [\n { value: \"solo\", label: \"Solo\" },\n { value: \"lead\", label: \"Lead\" },\n { value: \"contributor\", label: \"Contributor\" },\n];\n\nexport const DEFAULT_ACCENT_COLORS: { value: string; label: string }[] = [\n { value: \"#7c3aed\", label: \"Purple\" },\n { value: \"#10b981\", label: \"Green\" },\n { value: \"#f97316\", label: \"Orange\" },\n { value: \"#3b82f6\", label: \"Blue\" },\n { value: \"#ef4444\", label: \"Red\" },\n { value: \"#ec4899\", label: \"Pink\" },\n];\n","import * as p from \"@clack/prompts\";\nimport type {\n ProjectMeta,\n ProjectEntry,\n OwnerInfo,\n StyleConfig,\n SectionId,\n EngineType,\n DeployPlatform,\n} from \"../spec/schema.js\";\nimport {\n THEME_OPTIONS,\n FONT_OPTIONS,\n ANIMATION_OPTIONS,\n SECTION_OPTIONS,\n ENGINE_OPTIONS,\n DEPLOY_OPTIONS,\n ROLE_OPTIONS,\n DEFAULT_ACCENT_COLORS,\n} from \"./questions.js\";\nimport { logger } from \"../utils/logger.js\";\n\nfunction handleCancel(value: unknown): void {\n if (p.isCancel(value)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n}\n\nexport interface InterviewResult {\n projects: ProjectEntry[];\n owner: OwnerInfo;\n style: StyleConfig;\n sections: SectionId[];\n engine: EngineType;\n deploy: {\n platform: DeployPlatform;\n projectName: string;\n };\n}\n\nexport async function runInterview(\n scannedProjects: ProjectMeta[],\n availableEngines: EngineType[]\n): Promise<InterviewResult> {\n p.intro(\"shipfolio\");\n\n // -- Project Selection --\n logger.header(\"Project Selection\");\n\n const projectOptions = scannedProjects.map((proj) => ({\n value: proj.id,\n label: `${proj.name}`,\n hint: `${proj.techStack.slice(0, 3).join(\", \")} | ${proj.totalCommits} commits`,\n }));\n\n const selectedIds = (await p.multiselect({\n message: \"Select projects to include:\",\n options: projectOptions,\n required: true,\n })) as string[];\n handleCancel(selectedIds);\n\n // -- Per-Project Details --\n const projectEntries: ProjectEntry[] = [];\n\n for (const id of selectedIds) {\n const meta = scannedProjects.find((p) => p.id === id)!;\n\n logger.plain(`\\n Configuring: ${meta.name}`);\n\n const overrideDesc = (await p.text({\n message: `Description for ${meta.name} (enter to use auto-generated):`,\n placeholder: meta.description?.slice(0, 80) || \"Auto-generate from README\",\n defaultValue: \"\",\n })) as string;\n handleCancel(overrideDesc);\n\n const demoUrl = (await p.text({\n message: `Demo URL for ${meta.name}:`,\n placeholder: meta.demoUrl || \"none\",\n defaultValue: meta.demoUrl || \"\",\n })) as string;\n handleCancel(demoUrl);\n\n const showSource = (await p.confirm({\n message: `Show source code link for ${meta.name}?`,\n initialValue: !!meta.remoteUrl,\n })) as boolean;\n handleCancel(showSource);\n\n const role = (await p.select({\n message: `Your role in ${meta.name}:`,\n options: ROLE_OPTIONS,\n })) as \"solo\" | \"lead\" | \"contributor\";\n handleCancel(role);\n\n const metricsInput = (await p.text({\n message: `Key metrics for ${meta.name} (e.g. \"1k users, $5k MRR\"):`,\n placeholder: \"optional\",\n defaultValue: \"\",\n })) as string;\n handleCancel(metricsInput);\n\n const metrics: ProjectEntry[\"metrics\"] = {};\n if (metricsInput) {\n metrics.custom = { summary: metricsInput };\n }\n\n projectEntries.push({\n ...meta,\n included: true,\n overrideDescription: overrideDesc || null,\n showSourceLink: showSource,\n demoUrl: demoUrl || meta.demoUrl,\n role,\n metrics,\n });\n }\n\n // -- Personal Info --\n logger.header(\"Personal Information\");\n\n const name = (await p.text({\n message: \"Your full name:\",\n validate: (v) => (v.length === 0 ? \"Name is required\" : undefined),\n })) as string;\n handleCancel(name);\n\n const tagline = (await p.text({\n message: \"Professional tagline (one line):\",\n placeholder: \"Full-stack developer. I ship things.\",\n })) as string;\n handleCancel(tagline);\n\n const bioChoice = (await p.select({\n message: \"Bio:\",\n options: [\n { value: \"auto\", label: \"Auto-generate from my projects\" },\n { value: \"manual\", label: \"Write manually\" },\n ],\n })) as string;\n handleCancel(bioChoice);\n\n let bio: string | \"auto\" = \"auto\";\n if (bioChoice === \"manual\") {\n bio = (await p.text({\n message: \"Your bio (2-3 sentences):\",\n })) as string;\n handleCancel(bio);\n }\n\n const photoUrl = (await p.text({\n message: \"Photo URL (optional):\",\n placeholder: \"https://...\",\n defaultValue: \"\",\n })) as string;\n handleCancel(photoUrl);\n\n const github = (await p.text({\n message: \"GitHub username or URL:\",\n defaultValue: \"\",\n })) as string;\n handleCancel(github);\n\n const twitter = (await p.text({\n message: \"Twitter/X handle:\",\n defaultValue: \"\",\n })) as string;\n handleCancel(twitter);\n\n const linkedin = (await p.text({\n message: \"LinkedIn URL:\",\n defaultValue: \"\",\n })) as string;\n handleCancel(linkedin);\n\n const blogUrl = (await p.text({\n message: \"Blog URL:\",\n defaultValue: \"\",\n })) as string;\n handleCancel(blogUrl);\n\n const email = (await p.text({\n message: \"Contact email:\",\n defaultValue: \"\",\n })) as string;\n handleCancel(email);\n\n const owner: OwnerInfo = {\n name,\n tagline,\n bio,\n photoUrl: photoUrl || null,\n social: {\n github: github || undefined,\n twitter: twitter || undefined,\n linkedin: linkedin || undefined,\n blog: blogUrl || undefined,\n email: email || undefined,\n },\n };\n\n // -- Design Preferences --\n logger.header(\"Design Preferences\");\n\n const theme = (await p.select({\n message: \"Theme:\",\n options: THEME_OPTIONS,\n })) as StyleConfig[\"theme\"];\n handleCancel(theme);\n\n const accentColor = (await p.select({\n message: \"Accent color:\",\n options: [\n ...DEFAULT_ACCENT_COLORS,\n { value: \"custom\", label: \"Custom hex\" },\n ],\n })) as string;\n handleCancel(accentColor);\n\n let finalAccent = accentColor;\n if (accentColor === \"custom\") {\n finalAccent = (await p.text({\n message: \"Custom accent color (hex):\",\n placeholder: \"#7c3aed\",\n validate: (v) =>\n /^#[0-9a-fA-F]{6}$/.test(v) ? undefined : \"Enter a valid hex color\",\n })) as string;\n handleCancel(finalAccent);\n }\n\n const font = (await p.select({\n message: \"Font:\",\n options: FONT_OPTIONS,\n })) as StyleConfig[\"font\"];\n handleCancel(font);\n\n const animationLevel = (await p.select({\n message: \"Animation level:\",\n options: ANIMATION_OPTIONS,\n })) as StyleConfig[\"animationLevel\"];\n handleCancel(animationLevel);\n\n const style: StyleConfig = {\n theme,\n accentColor: finalAccent,\n font,\n animationLevel,\n };\n\n // -- Sections --\n logger.header(\"Sections\");\n\n const additionalSections = (await p.multiselect({\n message: \"Additional sections (Hero + Projects always included):\",\n options: SECTION_OPTIONS,\n required: false,\n })) as SectionId[];\n handleCancel(additionalSections);\n\n const sections: SectionId[] = [\n \"hero\",\n \"projects\",\n ...additionalSections,\n ];\n\n // -- Engine Selection --\n logger.header(\"AI Engine\");\n\n let engine: EngineType;\n if (availableEngines.length === 1) {\n engine = availableEngines[0];\n logger.info(`Using ${engine}`);\n } else {\n const filteredEngineOptions = ENGINE_OPTIONS.filter((o) =>\n availableEngines.includes(o.value)\n );\n engine = (await p.select({\n message: \"AI engine to use:\",\n options: filteredEngineOptions,\n })) as EngineType;\n handleCancel(engine);\n }\n\n // -- Deploy Target --\n logger.header(\"Deployment\");\n\n const deployPlatform = (await p.select({\n message: \"Deploy to:\",\n options: DEPLOY_OPTIONS,\n })) as DeployPlatform;\n handleCancel(deployPlatform);\n\n let projectName = \"\";\n if (deployPlatform !== \"local\") {\n projectName = (await p.text({\n message: \"Project name (used in URL):\",\n placeholder: \"my-shipfolio\",\n validate: (v) =>\n /^[a-z0-9-]+$/.test(v)\n ? undefined\n : \"Lowercase letters, numbers, and hyphens only\",\n })) as string;\n handleCancel(projectName);\n }\n\n p.outro(\"Configuration complete. Generating your site...\");\n\n return {\n projects: projectEntries,\n owner,\n style,\n sections,\n engine,\n deploy: {\n platform: deployPlatform,\n projectName,\n },\n };\n}\n","import type { ShipfolioSpec } from \"./schema.js\";\nimport type { InterviewResult } from \"../interviewer/index.js\";\n\nexport function buildSpec(interview: InterviewResult): ShipfolioSpec {\n return {\n version: \"1.0.0\",\n generatedAt: new Date().toISOString(),\n engine: interview.engine,\n framework: \"next\",\n style: interview.style,\n owner: interview.owner,\n projects: interview.projects,\n sections: interview.sections,\n deploy: {\n platform: interview.deploy.platform,\n projectName: interview.deploy.projectName,\n },\n };\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { ShipfolioSpec, ShipfolioConfig, SiteDiff } from \"../spec/schema.js\";\n\nfunction getPromptsDir(): string {\n // In development: relative to src/orchestrator/\n // In built: relative to dist/\n const currentDir = dirname(fileURLToPath(import.meta.url));\n // Try multiple possible locations\n const candidates = [\n join(currentDir, \"../../prompts\"),\n join(currentDir, \"../prompts\"),\n join(currentDir, \"../../../prompts\"),\n ];\n return candidates[0]; // Default; will fail gracefully if not found\n}\n\nasync function loadTemplate(filename: string): Promise<string> {\n const promptsDir = getPromptsDir();\n // Try each candidate path\n const candidates = [\n join(promptsDir, filename),\n join(dirname(fileURLToPath(import.meta.url)), \"../../prompts\", filename),\n join(dirname(fileURLToPath(import.meta.url)), \"../../../prompts\", filename),\n ];\n\n for (const candidate of candidates) {\n try {\n return await readFile(candidate, \"utf-8\");\n } catch {\n continue;\n }\n }\n\n throw new Error(`Prompt template not found: ${filename}`);\n}\n\nexport async function buildFreshPrompt(spec: ShipfolioSpec): Promise<string> {\n let template = await loadTemplate(\"fresh-build.md\");\n\n const sectionsText = spec.sections\n .map((s) => `- ${s}`)\n .join(\"\\n\");\n\n template = template\n .replace(\"{{SPEC_JSON}}\", JSON.stringify(spec, null, 2))\n .replace(\"{{THEME}}\", spec.style.theme)\n .replace(\"{{ACCENT_COLOR}}\", spec.style.accentColor)\n .replace(\"{{ANIMATION_LEVEL}}\", spec.style.animationLevel)\n .replace(\"{{FONT}}\", spec.style.font)\n .replace(\"{{SECTIONS_LIST}}\", sectionsText);\n\n return template;\n}\n\nexport async function buildUpdatePrompt(\n existingConfig: ShipfolioConfig,\n diff: SiteDiff\n): Promise<string> {\n let template = await loadTemplate(\"update.md\");\n\n const newProjectsText =\n diff.newProjects.length > 0\n ? diff.newProjects\n .map(\n (p) =>\n `- ${p.name}: ${p.description}\\n Tech: ${p.techStack.join(\", \")}\\n README excerpt: ${(p.readmeContent || \"\").slice(0, 500)}`\n )\n .join(\"\\n\\n\")\n : \"None\";\n\n const updatedProjectsText =\n diff.updatedProjects.length > 0\n ? diff.updatedProjects\n .map(\n (u) =>\n `- ${u.project.name}: ${u.newCommits} new commits\\n README changed: ${u.readmeChanged}\\n Dependencies changed: ${u.depsChanged}`\n )\n .join(\"\\n\\n\")\n : \"None\";\n\n const removedProjectsText =\n diff.removedProjects.length > 0\n ? diff.removedProjects.map((p) => `- ${p.name}`).join(\"\\n\")\n : \"None\";\n\n template = template\n .replace(\n \"{{EXISTING_CONFIG_JSON}}\",\n JSON.stringify(existingConfig, null, 2)\n )\n .replace(\"{{NEW_PROJECTS}}\", newProjectsText)\n .replace(\"{{UPDATED_PROJECTS}}\", updatedProjectsText)\n .replace(\"{{REMOVED_PROJECTS}}\", removedProjectsText)\n .replace(\"{{PERSONAL_INFO_DIFF}}\", \"No changes\");\n\n return template;\n}\n","import { execa, type Options as ExecaOptions } from \"execa\";\n\nexport async function run(\n command: string,\n args: string[],\n options?: ExecaOptions\n) {\n return execa(command, args, {\n stdio: \"pipe\",\n ...options,\n });\n}\n\nexport async function commandExists(command: string): Promise<boolean> {\n try {\n await execa(\"which\", [command]);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function runWithOutput(\n command: string,\n args: string[],\n options?: ExecaOptions\n): Promise<string> {\n const result = await execa(command, args, {\n stdio: \"pipe\",\n ...options,\n });\n return result.stdout;\n}\n","import { commandExists } from \"../utils/exec.js\";\nimport type { EngineType } from \"../spec/schema.js\";\n\nexport interface DetectedEngine {\n type: EngineType;\n available: boolean;\n}\n\nexport async function detectEngines(): Promise<DetectedEngine[]> {\n const results: DetectedEngine[] = [];\n\n // Check for v0 API key\n if (process.env.V0_API_KEY) {\n results.push({ type: \"v0\", available: true });\n }\n\n // Check for Claude Code CLI\n if (await commandExists(\"claude\")) {\n results.push({ type: \"claude\", available: true });\n }\n\n // Check for Codex CLI\n if (await commandExists(\"codex\")) {\n results.push({ type: \"codex\", available: true });\n }\n\n return results;\n}\n\nexport function getAvailableEngineTypes(engines: DetectedEngine[]): EngineType[] {\n return engines.filter((e) => e.available).map((e) => e.type);\n}\n","import { execa } from \"execa\";\nimport { logger } from \"../../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function generateWithClaude(\n prompt: string,\n outputDir: string\n): Promise<void> {\n const spinner = ora(\"Generating site with Claude Code...\").start();\n\n try {\n // Use claude CLI with --print flag for non-interactive mode\n // and direct it to create files in the output directory\n const fullPrompt = `${prompt}\\n\\nCreate all files in the current working directory. Do not ask questions, just generate all files.`;\n\n await execa(\"claude\", [\"-p\", fullPrompt], {\n cwd: outputDir,\n stdio: \"pipe\",\n timeout: 300000, // 5 minute timeout\n });\n\n spinner.succeed(\"Site generated with Claude Code\");\n } catch (error) {\n spinner.fail(\"Claude Code generation failed\");\n throw error;\n }\n}\n","import { execa } from \"execa\";\nimport { logger } from \"../../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function generateWithCodex(\n prompt: string,\n outputDir: string\n): Promise<void> {\n const spinner = ora(\"Generating site with Codex...\").start();\n\n try {\n const fullPrompt = `${prompt}\\n\\nCreate all files in the current working directory. Do not ask questions, just generate all files.`;\n\n await execa(\"codex\", [\"--quiet\", \"--full-auto\", fullPrompt], {\n cwd: outputDir,\n stdio: \"pipe\",\n timeout: 300000,\n });\n\n spinner.succeed(\"Site generated with Codex\");\n } catch (error) {\n spinner.fail(\"Codex generation failed\");\n throw error;\n }\n}\n","import OpenAI from \"openai\";\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { join, dirname } from \"node:path\";\nimport { logger } from \"../../utils/logger.js\";\nimport ora from \"ora\";\n\ninterface ExtractedFile {\n filename: string;\n content: string;\n}\n\nexport async function generateWithV0(\n prompt: string,\n outputDir: string,\n apiKey: string\n): Promise<void> {\n const spinner = ora(\"Generating site with v0...\").start();\n\n const client = new OpenAI({\n apiKey,\n baseURL: \"https://api.v0.dev/v1\",\n });\n\n try {\n const response = await client.chat.completions.create({\n model: \"v0-1.0-md\",\n messages: [\n {\n role: \"system\",\n content:\n \"Generate a complete Next.js 15 portfolio website using TypeScript, Tailwind CSS, and shadcn/ui. \" +\n \"Return all files with their paths clearly marked. Use ```tsx filename.tsx or ```ts filename.ts \" +\n \"code blocks with the filename on the same line as the opening backticks. \" +\n \"No emoji in any output.\",\n },\n {\n role: \"user\",\n content: prompt,\n },\n ],\n });\n\n const content = response.choices[0]?.message?.content;\n if (!content) {\n throw new Error(\"v0 returned empty response\");\n }\n\n spinner.text = \"Parsing v0 output...\";\n\n const files = extractFiles(content);\n if (files.length === 0) {\n throw new Error(\"No files extracted from v0 response\");\n }\n\n spinner.text = `Writing ${files.length} files...`;\n\n for (const file of files) {\n const filePath = join(outputDir, file.filename);\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, file.content, \"utf-8\");\n }\n\n // Ensure package.json exists with required deps\n const hasPkgJson = files.some((f) => f.filename === \"package.json\");\n if (!hasPkgJson) {\n await writeFile(\n join(outputDir, \"package.json\"),\n JSON.stringify(\n {\n name: \"shipfolio-site\",\n version: \"1.0.0\",\n private: true,\n scripts: {\n dev: \"next dev\",\n build: \"next build\",\n start: \"next start\",\n },\n dependencies: {\n next: \"^15.0.0\",\n react: \"^19.0.0\",\n \"react-dom\": \"^19.0.0\",\n \"class-variance-authority\": \"^0.7.0\",\n clsx: \"^2.1.0\",\n \"tailwind-merge\": \"^2.6.0\",\n \"lucide-react\": \"^0.460.0\",\n },\n devDependencies: {\n typescript: \"^5.7.0\",\n \"@types/node\": \"^22.0.0\",\n \"@types/react\": \"^19.0.0\",\n \"@types/react-dom\": \"^19.0.0\",\n tailwindcss: \"^4.0.0\",\n \"@tailwindcss/postcss\": \"^4.0.0\",\n },\n },\n null,\n 2\n ),\n \"utf-8\"\n );\n }\n\n spinner.succeed(`Site generated with v0 (${files.length} files)`);\n } catch (error) {\n spinner.fail(\"v0 generation failed\");\n throw error;\n }\n}\n\nfunction extractFiles(content: string): ExtractedFile[] {\n const files: ExtractedFile[] = [];\n\n // Match code blocks with filename: ```tsx src/app/page.tsx or ```tsx filename=\"src/app/page.tsx\"\n const patterns = [\n // ```tsx src/app/page.tsx\n /```(?:tsx?|jsx?|css|json|mjs|cjs)\\s+([^\\n`]+)\\n([\\s\\S]*?)```/g,\n // ```tsx filename=\"src/app/page.tsx\"\n /```(?:tsx?|jsx?|css|json|mjs|cjs)\\s+filename=\"([^\"]+)\"\\n([\\s\\S]*?)```/g,\n // ```tsx {filename: \"src/app/page.tsx\"}\n /```(?:tsx?|jsx?|css|json|mjs|cjs).*?filename:\\s*\"([^\"]+)\".*?\\n([\\s\\S]*?)```/g,\n ];\n\n for (const pattern of patterns) {\n let match;\n while ((match = pattern.exec(content)) !== null) {\n const filename = match[1].trim();\n const fileContent = match[2].trim();\n\n // Skip if filename looks like a description rather than a path\n if (\n filename.includes(\" \") &&\n !filename.includes(\"/\") &&\n !filename.includes(\".\")\n ) {\n continue;\n }\n\n // Clean up filename\n const cleanFilename = filename\n .replace(/^[\"']|[\"']$/g, \"\")\n .replace(/^\\.\\//g, \"\");\n\n if (cleanFilename && fileContent) {\n files.push({ filename: cleanFilename, content: fileContent });\n }\n }\n }\n\n return files;\n}\n","import { fileExists, join } from \"../utils/fs.js\";\n\nexport interface ValidationResult {\n valid: boolean;\n errors: string[];\n}\n\nexport async function validateGeneratedSite(\n siteDir: string\n): Promise<ValidationResult> {\n const errors: string[] = [];\n\n const requiredFiles = [\n \"package.json\",\n \"next.config.ts\",\n \"src/app/layout.tsx\",\n \"src/app/page.tsx\",\n ];\n\n // Also check common alternatives\n const alternativeChecks: [string, string[]][] = [\n [\"next.config.ts\", [\"next.config.ts\", \"next.config.js\", \"next.config.mjs\"]],\n ];\n\n for (const file of requiredFiles) {\n const alternatives = alternativeChecks.find(([key]) => key === file);\n if (alternatives) {\n const anyExists = await Promise.any(\n alternatives[1].map(async (alt) => {\n if (await fileExists(join(siteDir, alt))) return true;\n throw new Error(\"not found\");\n })\n ).catch(() => false);\n if (!anyExists) {\n errors.push(`Missing: ${file} (or any alternative)`);\n }\n } else {\n if (!(await fileExists(join(siteDir, file)))) {\n errors.push(`Missing: ${file}`);\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\nexport async function validateBuildOutput(\n siteDir: string\n): Promise<ValidationResult> {\n const errors: string[] = [];\n\n const outDir = join(siteDir, \"out\");\n if (!(await fileExists(outDir))) {\n errors.push(\"Build output directory 'out/' not found\");\n return { valid: false, errors };\n }\n\n const indexHtml = join(outDir, \"index.html\");\n if (!(await fileExists(indexHtml))) {\n errors.push(\"Missing: out/index.html\");\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n","import { generateWithClaude } from \"./engines/claude.js\";\nimport { generateWithCodex } from \"./engines/codex.js\";\nimport { generateWithV0 } from \"./engines/v0.js\";\nimport {\n validateGeneratedSite,\n validateBuildOutput,\n} from \"./validator.js\";\nimport { ensureDir } from \"../utils/fs.js\";\nimport { run } from \"../utils/exec.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { EngineType } from \"../spec/schema.js\";\nimport ora from \"ora\";\n\nexport async function generateSite(\n engine: EngineType,\n prompt: string,\n outputDir: string\n): Promise<void> {\n await ensureDir(outputDir);\n\n switch (engine) {\n case \"claude\":\n await generateWithClaude(prompt, outputDir);\n break;\n case \"codex\":\n await generateWithCodex(prompt, outputDir);\n break;\n case \"v0\": {\n const apiKey = process.env.V0_API_KEY;\n if (!apiKey) {\n throw new Error(\n \"V0_API_KEY environment variable is required for v0 engine\"\n );\n }\n await generateWithV0(prompt, outputDir, apiKey);\n break;\n }\n }\n\n // Validate generated output\n const validation = await validateGeneratedSite(outputDir);\n if (!validation.valid) {\n logger.warn(\"Generated site has issues:\");\n for (const err of validation.errors) {\n logger.warn(` ${err}`);\n }\n // Could retry here, but for now just warn\n }\n}\n\nexport async function buildSite(siteDir: string): Promise<boolean> {\n const spinner = ora(\"Installing dependencies...\").start();\n\n try {\n await run(\"npm\", [\"install\"], { cwd: siteDir });\n spinner.text = \"Building site...\";\n await run(\"npm\", [\"run\", \"build\"], { cwd: siteDir });\n spinner.succeed(\"Site built successfully\");\n } catch (error: any) {\n spinner.fail(\"Build failed\");\n logger.error(error.stderr || error.message || String(error));\n return false;\n }\n\n // Validate build output\n const validation = await validateBuildOutput(siteDir);\n if (!validation.valid) {\n logger.error(\"Build output validation failed:\");\n for (const err of validation.errors) {\n logger.error(` ${err}`);\n }\n return false;\n }\n\n return true;\n}\n\nexport async function retryBuild(\n engine: EngineType,\n siteDir: string,\n buildError: string,\n originalPrompt: string\n): Promise<boolean> {\n logger.info(\"Retrying: feeding build error back to AI...\");\n\n const fixPrompt = `The site generation produced build errors. Fix the following errors without changing the overall design or structure:\\n\\n${buildError}\\n\\nOriginal prompt for context:\\n${originalPrompt.slice(0, 2000)}`;\n\n try {\n await generateSite(engine, fixPrompt, siteDir);\n return await buildSite(siteDir);\n } catch {\n return false;\n }\n}\n","import { run, commandExists, runWithOutput } from \"../utils/exec.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { DeployPlatform } from \"../spec/schema.js\";\n\nexport async function checkAuth(\n platform: DeployPlatform\n): Promise<boolean> {\n if (platform === \"local\") return true;\n\n try {\n if (platform === \"cloudflare\") {\n await runWithOutput(\"npx\", [\"wrangler\", \"whoami\"]);\n return true;\n }\n if (platform === \"vercel\") {\n await runWithOutput(\"npx\", [\"vercel\", \"whoami\"]);\n return true;\n }\n } catch {\n return false;\n }\n return false;\n}\n\nexport async function login(platform: DeployPlatform): Promise<void> {\n if (platform === \"cloudflare\") {\n logger.info(\"Opening Cloudflare login in browser...\");\n await run(\"npx\", [\"wrangler\", \"login\"], { stdio: \"inherit\" });\n } else if (platform === \"vercel\") {\n logger.info(\"Opening Vercel login in browser...\");\n await run(\"npx\", [\"vercel\", \"login\"], { stdio: \"inherit\" });\n }\n}\n\nexport async function ensureAuth(platform: DeployPlatform): Promise<void> {\n if (platform === \"local\") return;\n\n const isAuthed = await checkAuth(platform);\n if (!isAuthed) {\n await login(platform);\n // Verify login succeeded\n const nowAuthed = await checkAuth(platform);\n if (!nowAuthed) {\n throw new Error(`Authentication failed for ${platform}`);\n }\n }\n}\n","import { runWithOutput } from \"../utils/exec.js\";\nimport { logger } from \"../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function deployToCloudflare(\n distDir: string,\n projectName: string\n): Promise<string> {\n const spinner = ora(\"Deploying to Cloudflare Pages...\").start();\n\n try {\n const output = await runWithOutput(\"npx\", [\n \"wrangler\",\n \"pages\",\n \"deploy\",\n distDir,\n `--project-name=${projectName}`,\n ]);\n\n // Extract URL from output\n const urlMatch = output.match(\n /https:\\/\\/[^\\s]+\\.pages\\.dev/\n );\n const url = urlMatch?.[0] || `https://${projectName}.pages.dev`;\n\n spinner.succeed(`Deployed to Cloudflare Pages`);\n logger.info(`URL: ${url}`);\n\n return url;\n } catch (error: any) {\n spinner.fail(\"Cloudflare Pages deployment failed\");\n throw error;\n }\n}\n","import { runWithOutput } from \"../utils/exec.js\";\nimport { logger } from \"../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function deployToVercel(\n distDir: string\n): Promise<string> {\n const spinner = ora(\"Deploying to Vercel...\").start();\n\n try {\n const output = await runWithOutput(\"npx\", [\n \"vercel\",\n \"deploy\",\n distDir,\n \"--yes\",\n \"--prod\",\n ]);\n\n // Extract URL from output\n const urlMatch = output.match(\n /https:\\/\\/[^\\s]+\\.vercel\\.app/\n );\n const url = urlMatch?.[0] || output.trim().split(\"\\n\").pop() || \"\";\n\n spinner.succeed(\"Deployed to Vercel\");\n logger.info(`URL: ${url}`);\n\n return url;\n } catch (error: any) {\n spinner.fail(\"Vercel deployment failed\");\n throw error;\n }\n}\n","import { run, runWithOutput, commandExists } from \"../utils/exec.js\";\nimport { fileExists, join } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\nimport * as p from \"@clack/prompts\";\n\nexport async function setupGitHubAutoDeploy(\n siteDir: string,\n projectName: string\n): Promise<void> {\n const hasGh = await commandExists(\"gh\");\n if (!hasGh) {\n logger.info(\n \"GitHub CLI (gh) not found. Install it to enable auto-deploy setup.\"\n );\n return;\n }\n\n const shouldSetup = (await p.confirm({\n message: \"Set up GitHub auto-deploy? (push = redeploy)\",\n initialValue: false,\n })) as boolean;\n\n if (p.isCancel(shouldSetup) || !shouldSetup) return;\n\n const visibility = (await p.select({\n message: \"Repository visibility:\",\n options: [\n { value: \"private\", label: \"Private\" },\n { value: \"public\", label: \"Public\" },\n ],\n })) as string;\n\n if (p.isCancel(visibility)) return;\n\n try {\n // Init git if not already\n const gitDir = join(siteDir, \".git\");\n if (!(await fileExists(gitDir))) {\n await run(\"git\", [\"init\"], { cwd: siteDir });\n }\n\n // Create GitHub repo\n await run(\n \"gh\",\n [\n \"repo\",\n \"create\",\n projectName,\n `--${visibility}`,\n \"--source\",\n siteDir,\n \"--push\",\n ],\n { cwd: siteDir, stdio: \"inherit\" }\n );\n\n logger.success(`GitHub repository created: ${projectName}`);\n logger.info(\n \"Connect this repo in your Cloudflare Pages or Vercel dashboard for auto-deploy.\"\n );\n } catch (error: any) {\n logger.error(`GitHub setup failed: ${error.message}`);\n }\n}\n","import { ensureAuth } from \"./auth.js\";\nimport { deployToCloudflare } from \"./cloudflare.js\";\nimport { deployToVercel } from \"./vercel.js\";\nimport { setupGitHubAutoDeploy } from \"./github.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { DeployPlatform } from \"../spec/schema.js\";\nimport { join } from \"node:path\";\n\nexport async function deploy(\n siteDir: string,\n platform: DeployPlatform,\n projectName: string\n): Promise<string | null> {\n if (platform === \"local\") {\n logger.info(`Site built at ${join(siteDir, \"out/\")}`);\n logger.info(\"Run `npx serve ./out` in the site directory to preview.\");\n return null;\n }\n\n await ensureAuth(platform);\n\n const distDir = join(siteDir, \"out\");\n let url: string;\n\n if (platform === \"cloudflare\") {\n url = await deployToCloudflare(distDir, projectName);\n } else {\n url = await deployToVercel(distDir);\n }\n\n // Offer GitHub auto-deploy setup\n await setupGitHubAutoDeploy(siteDir, projectName);\n\n return url;\n}\n","import { createServer, type Server } from \"node:http\";\nimport { join } from \"node:path\";\nimport { logger } from \"../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function exportPdf(\n siteDir: string,\n outputPath?: string\n): Promise<string> {\n const distDir = join(siteDir, \"out\");\n const pdfPath = outputPath || join(distDir, \"shipfolio.pdf\");\n\n const spinner = ora(\"Exporting PDF...\").start();\n\n // Start a local server for the built site\n const server = await startStaticServer(distDir);\n const port = (server.address() as any)?.port || 3456;\n\n try {\n // Dynamic import to avoid requiring playwright at install time\n const { chromium } = await import(\"playwright\");\n\n const browser = await chromium.launch();\n const page = await browser.newPage();\n\n await page.goto(`http://localhost:${port}`, {\n waitUntil: \"networkidle\",\n });\n\n // Wait a moment for any CSS transitions to complete\n await page.waitForTimeout(1000);\n\n await page.pdf({\n path: pdfPath,\n format: \"A4\",\n printBackground: true,\n margin: {\n top: \"1cm\",\n right: \"1cm\",\n bottom: \"1cm\",\n left: \"1cm\",\n },\n });\n\n await browser.close();\n spinner.succeed(`PDF exported: ${pdfPath}`);\n return pdfPath;\n } catch (error: any) {\n spinner.fail(\"PDF export failed\");\n if (error.message?.includes(\"browserType.launch\")) {\n logger.error(\n \"Playwright browsers not installed. Run: npx playwright install chromium\"\n );\n } else {\n logger.error(error.message || String(error));\n }\n throw error;\n } finally {\n server.close();\n }\n}\n\nfunction startStaticServer(dir: string): Promise<Server> {\n return new Promise(async (resolve, reject) => {\n const handler = await import(\"serve-handler\");\n\n const server = createServer((req, res) => {\n return handler.default(req, res, {\n public: dir,\n cleanUrls: true,\n });\n });\n\n server.listen(0, () => {\n resolve(server);\n });\n\n server.on(\"error\", reject);\n });\n}\n\nexport async function startPreviewServer(\n siteDir: string,\n port: number = 3000\n): Promise<Server> {\n const distDir = join(siteDir, \"out\");\n const handler = await import(\"serve-handler\");\n\n const server = createServer((req, res) => {\n return handler.default(req, res, {\n public: distDir,\n cleanUrls: true,\n });\n });\n\n return new Promise((resolve, reject) => {\n server.listen(port, () => {\n logger.info(`Preview: http://localhost:${port}`);\n resolve(server);\n });\n server.on(\"error\", reject);\n });\n}\n","import { resolve } from \"node:path\";\nimport { scanProjects } from \"../scanner/index.js\";\nimport { runInterview } from \"../interviewer/index.js\";\nimport { buildSpec } from \"../spec/builder.js\";\nimport { buildFreshPrompt } from \"../orchestrator/prompt-builder.js\";\nimport { detectEngines, getAvailableEngineTypes } from \"../orchestrator/detect.js\";\nimport { generateSite, buildSite } from \"../orchestrator/index.js\";\nimport { deploy } from \"../deployer/index.js\";\nimport { exportPdf } from \"../pdf/index.js\";\nimport { startPreviewServer } from \"../pdf/index.js\";\nimport { writeJson, ensureDir } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\nimport { join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\n\ninterface InitOptions {\n scan?: string[];\n engine?: string;\n deploy?: string;\n style?: string;\n accent?: string;\n auto?: boolean;\n output?: string;\n noPdf?: boolean;\n noPreview?: boolean;\n verbose?: boolean;\n}\n\nexport async function initCommand(options: InitOptions): Promise<void> {\n logger.header(\"shipfolio v1.0.0\");\n\n // Step 1: Detect AI engines\n logger.info(\"Detecting AI engines...\");\n const engines = await detectEngines();\n const availableTypes = getAvailableEngineTypes(engines);\n\n if (availableTypes.length === 0) {\n logger.error(\"No AI engine found.\");\n logger.plain(\"\");\n logger.plain(\" shipfolio requires one of the following:\");\n logger.plain(\" - Claude Code: npm install -g @anthropic-ai/claude-code\");\n logger.plain(\" - Codex: npm install -g @openai/codex\");\n logger.plain(\" - v0: Set V0_API_KEY environment variable\");\n logger.plain(\"\");\n process.exit(1);\n }\n\n logger.info(\n `Available engines: ${availableTypes.join(\", \")}`\n );\n\n // Step 2: Scan projects\n const scanDirs = options.scan?.map((d) => resolve(d)) || [\n resolve(process.cwd()),\n ];\n const scannedProjects = await scanProjects(scanDirs);\n\n if (scannedProjects.length === 0) {\n logger.error(\"No projects found. Specify a different directory with --scan.\");\n process.exit(1);\n }\n\n // Display scanned projects\n logger.header(`Found ${scannedProjects.length} projects:`);\n const tableRows = scannedProjects.map((proj) => [\n proj.name,\n proj.techStack.slice(0, 3).join(\", \"),\n proj.firstCommitDate?.slice(0, 10) || \"?\",\n `${proj.totalCommits} commits`,\n ]);\n logger.table(tableRows);\n logger.blank();\n\n // Step 3: Interactive interview\n const interviewResult = await runInterview(scannedProjects, availableTypes);\n\n // Step 4: Build spec\n const spec = buildSpec(interviewResult);\n\n // Step 5: Generate prompt\n const prompt = await buildFreshPrompt(spec);\n\n // Step 6: Generate site\n const outputDir = resolve(options.output || \"./shipfolio-site\");\n await ensureDir(outputDir);\n\n await generateSite(spec.engine, prompt, outputDir);\n\n // Step 7: Build\n let buildSuccess = await buildSite(outputDir);\n if (!buildSuccess) {\n logger.info(\"Attempting retry...\");\n buildSuccess = await buildSite(outputDir);\n if (!buildSuccess) {\n logger.error(\"Build failed after retry. Check the output directory for details.\");\n process.exit(1);\n }\n }\n\n // Step 8: Preview\n if (!options.noPreview) {\n const server = await startPreviewServer(outputDir);\n logger.blank();\n\n const proceed = (await p.confirm({\n message: \"Deploy now?\",\n initialValue: true,\n })) as boolean;\n\n server.close();\n\n if (p.isCancel(proceed) || !proceed) {\n if (spec.deploy.platform === \"local\") {\n // Already local, just exit\n } else {\n logger.info(\"Skipping deploy. Run `npx shipfolio deploy` later.\");\n }\n }\n }\n\n // Step 9: PDF export\n if (!options.noPdf) {\n try {\n await exportPdf(outputDir);\n } catch {\n logger.warn(\"PDF export skipped due to error.\");\n }\n }\n\n // Step 10: Deploy\n if (spec.deploy.platform !== \"local\") {\n const url = await deploy(\n outputDir,\n spec.deploy.platform,\n spec.deploy.projectName\n );\n if (url) {\n spec.deploy.url = url;\n }\n }\n\n // Save config for future updates\n await writeJson(join(outputDir, \"shipfolio.config.json\"), {\n ...spec,\n sitePath: outputDir,\n });\n\n // Summary\n logger.header(\"Done.\");\n if (spec.deploy.url) {\n logger.info(`Site: ${spec.deploy.url}`);\n }\n logger.info(`Local: ${outputDir}`);\n logger.info(\n `Update: npx shipfolio update --site ${outputDir}`\n );\n}\n","import { Command } from \"commander\";\nimport { initCommand } from \"./commands/init.js\";\nimport { updateCommand } from \"./commands/update.js\";\nimport { specCommand } from \"./commands/spec.js\";\nimport { deployCommand } from \"./commands/deploy.js\";\nimport { pdfCommand } from \"./commands/pdf.js\";\nimport { previewCommand } from \"./commands/preview.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"shipfolio\")\n .description(\n \"Generate and deploy your personal portfolio site from local projects using AI\"\n )\n .version(\"1.0.0\");\n\n// Default command: init (fresh build)\nprogram\n .command(\"init\", { isDefault: true })\n .description(\"Generate a new portfolio site\")\n .option(\"-s, --scan <dirs...>\", \"Directories to scan for projects\")\n .option(\"-e, --engine <engine>\", \"AI engine: claude | codex | v0\")\n .option(\"-d, --deploy <platform>\", \"Deploy target: cloudflare | vercel | local\")\n .option(\"--style <theme>\", \"Theme: dark-minimal | light-clean | monochrome\")\n .option(\"--accent <hex>\", \"Accent color (hex)\")\n .option(\"--auto\", \"Skip prompts, use defaults\")\n .option(\"-o, --output <dir>\", \"Output directory\", \"./shipfolio-site\")\n .option(\"--no-pdf\", \"Skip PDF export\")\n .option(\"--no-preview\", \"Skip local preview\")\n .option(\"-v, --verbose\", \"Verbose output\")\n .action(initCommand);\n\n// Update existing site\nprogram\n .command(\"update\")\n .description(\"Update an existing portfolio site\")\n .requiredOption(\"--site <path>\", \"Path to existing site directory\")\n .option(\"-s, --scan <dirs...>\", \"Directories to scan for projects\")\n .option(\"--no-pdf\", \"Skip PDF export\")\n .option(\"--no-preview\", \"Skip preview\")\n .option(\"--no-deploy\", \"Skip deployment\")\n .action(updateCommand);\n\n// Generate spec only (for use inside AI tools)\nprogram\n .command(\"spec\")\n .description(\"Generate spec and prompt files only\")\n .option(\"-s, --scan <dirs...>\", \"Directories to scan for projects\")\n .option(\"-o, --output <dir>\", \"Output directory for spec files\", \".\")\n .action(specCommand);\n\n// Deploy existing site\nprogram\n .command(\"deploy\")\n .description(\"Deploy an existing built site\")\n .requiredOption(\"--site <path>\", \"Path to site directory\")\n .option(\"-p, --platform <platform>\", \"Deploy platform: cloudflare | vercel\")\n .action(deployCommand);\n\n// Export PDF\nprogram\n .command(\"pdf\")\n .description(\"Export site to PDF\")\n .requiredOption(\"--site <path>\", \"Path to site directory\")\n .option(\"-o, --output <path>\", \"PDF output path\")\n .action(pdfCommand);\n\n// Preview\nprogram\n .command(\"preview\")\n .description(\"Start local preview server\")\n .requiredOption(\"--site <path>\", \"Path to site directory\")\n .option(\"--port <port>\", \"Port number\", \"3000\")\n .action((opts) => previewCommand({ ...opts, port: parseInt(opts.port) }));\n\nprogram.parse();\n","import { resolve } from \"node:path\";\nimport { scanProjects } from \"../scanner/index.js\";\nimport { computeDiff } from \"../spec/diff.js\";\nimport { buildUpdatePrompt } from \"../orchestrator/prompt-builder.js\";\nimport { detectEngines, getAvailableEngineTypes } from \"../orchestrator/detect.js\";\nimport { generateSite, buildSite } from \"../orchestrator/index.js\";\nimport { deploy } from \"../deployer/index.js\";\nimport { exportPdf, startPreviewServer } from \"../pdf/index.js\";\nimport { readJson, writeJson, fileExists, join } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { ShipfolioConfig, ProjectEntry } from \"../spec/schema.js\";\nimport * as p from \"@clack/prompts\";\n\ninterface UpdateOptions {\n site: string;\n scan?: string[];\n noPdf?: boolean;\n noPreview?: boolean;\n noDeploy?: boolean;\n}\n\nexport async function updateCommand(options: UpdateOptions): Promise<void> {\n logger.header(\"shipfolio update\");\n\n const siteDir = resolve(options.site);\n const configPath = join(siteDir, \"shipfolio.config.json\");\n\n // Read existing config\n if (!(await fileExists(configPath))) {\n logger.error(\n \"shipfolio.config.json not found. This directory was not generated by shipfolio.\"\n );\n const fresh = (await p.confirm({\n message: \"Proceed with fresh build instead?\",\n initialValue: true,\n })) as boolean;\n\n if (p.isCancel(fresh) || !fresh) {\n process.exit(0);\n }\n\n // Redirect to init\n const { initCommand } = await import(\"./init.js\");\n await initCommand({ output: siteDir });\n return;\n }\n\n const config = await readJson<ShipfolioConfig>(configPath);\n logger.info(\n `Site: ${config.deploy.projectName || \"local\"} (generated ${config.generatedAt.slice(0, 10)})`\n );\n logger.info(`Theme: ${config.style.theme}`);\n logger.info(`Projects: ${config.projects.length}`);\n\n // Detect engines\n const engines = await detectEngines();\n const availableTypes = getAvailableEngineTypes(engines);\n if (availableTypes.length === 0) {\n logger.error(\"No AI engine found. See `npx shipfolio` for install instructions.\");\n process.exit(1);\n }\n\n // Scan for changes\n const scanDirs = options.scan?.map((d) => resolve(d)) ||\n [...new Set(config.projects.map((p) => {\n const parts = p.localPath.split(\"/\");\n parts.pop();\n return parts.join(\"/\");\n }))];\n\n const scannedProjects = await scanProjects(scanDirs);\n const diff = computeDiff(config, scannedProjects);\n\n // Display changes\n logger.header(\"Changes detected:\");\n\n if (diff.newProjects.length > 0) {\n logger.plain(\" New:\");\n for (const proj of diff.newProjects) {\n logger.plain(` + ${proj.name} ${proj.techStack.slice(0, 3).join(\", \")}`);\n }\n }\n\n if (diff.updatedProjects.length > 0) {\n logger.plain(\" Updated:\");\n for (const upd of diff.updatedProjects) {\n logger.plain(\n ` ~ ${upd.project.name} ${upd.newCommits} new commits`\n );\n }\n }\n\n if (diff.removedProjects.length > 0) {\n logger.plain(\" Removed:\");\n for (const proj of diff.removedProjects) {\n logger.plain(` - ${proj.name} (directory gone)`);\n }\n }\n\n if (\n diff.newProjects.length === 0 &&\n diff.updatedProjects.length === 0 &&\n diff.removedProjects.length === 0\n ) {\n logger.info(\"No changes detected.\");\n return;\n }\n\n // Confirm changes\n const proceed = (await p.confirm({\n message: \"Apply these changes?\",\n initialValue: true,\n })) as boolean;\n\n if (p.isCancel(proceed) || !proceed) {\n process.exit(0);\n }\n\n // Build update prompt\n const engine = availableTypes.includes(config.engine)\n ? config.engine\n : availableTypes[0];\n\n const prompt = await buildUpdatePrompt(config, diff);\n\n // Generate updates\n await generateSite(engine, prompt, siteDir);\n\n // Build\n const buildSuccess = await buildSite(siteDir);\n if (!buildSuccess) {\n logger.error(\"Build failed. Check the site directory.\");\n process.exit(1);\n }\n\n // Preview\n if (!options.noPreview) {\n const server = await startPreviewServer(siteDir);\n const ok = (await p.confirm({\n message: \"Looks good?\",\n initialValue: true,\n })) as boolean;\n server.close();\n if (p.isCancel(ok) || !ok) {\n logger.info(\"Update cancelled at preview.\");\n return;\n }\n }\n\n // PDF\n if (!options.noPdf) {\n try {\n await exportPdf(siteDir);\n } catch {\n logger.warn(\"PDF export skipped.\");\n }\n }\n\n // Deploy\n if (!options.noDeploy && config.deploy.platform !== \"local\") {\n await deploy(siteDir, config.deploy.platform, config.deploy.projectName);\n }\n\n // Update config\n const updatedConfig: ShipfolioConfig = {\n ...config,\n generatedAt: new Date().toISOString(),\n projects: [\n ...diff.unchangedProjects,\n ...diff.updatedProjects.map((u) => {\n const existing = config.projects.find(\n (p) => p.localPath === u.project.localPath\n );\n return {\n ...u.project,\n included: true,\n overrideDescription: existing?.overrideDescription || null,\n showSourceLink: existing?.showSourceLink ?? !!u.project.remoteUrl,\n role: existing?.role || \"solo\",\n metrics: existing?.metrics || {},\n } as ProjectEntry;\n }),\n ...diff.newProjects.map(\n (proj) =>\n ({\n ...proj,\n included: true,\n overrideDescription: null,\n showSourceLink: !!proj.remoteUrl,\n role: \"solo\" as const,\n metrics: {},\n }) as ProjectEntry\n ),\n ],\n };\n\n await writeJson(join(siteDir, \"shipfolio.config.json\"), updatedConfig);\n logger.success(\"Update complete.\");\n}\n","import type {\n ProjectMeta,\n ProjectEntry,\n ShipfolioConfig,\n SiteDiff,\n ProjectUpdate,\n} from \"./schema.js\";\n\nexport function computeDiff(\n oldConfig: ShipfolioConfig,\n newScan: ProjectMeta[]\n): SiteDiff {\n const oldProjectMap = new Map(\n oldConfig.projects.map((p) => [p.localPath, p])\n );\n const newProjectMap = new Map(newScan.map((p) => [p.localPath, p]));\n\n const newProjects: ProjectMeta[] = [];\n const updatedProjects: ProjectUpdate[] = [];\n const removedProjects: ProjectEntry[] = [];\n const unchangedProjects: ProjectEntry[] = [];\n\n // Check new and updated\n for (const [path, meta] of newProjectMap) {\n const oldProject = oldProjectMap.get(path);\n if (!oldProject) {\n newProjects.push(meta);\n } else if (meta.lastScannedCommit !== oldProject.lastScannedCommit) {\n const newCommits = meta.totalCommits - oldProject.totalCommits;\n updatedProjects.push({\n project: meta,\n newCommits: Math.max(newCommits, 0),\n readmeChanged: meta.readmeContent !== oldProject.readmeContent,\n depsChanged:\n JSON.stringify(meta.techStack) !==\n JSON.stringify(oldProject.techStack),\n });\n } else {\n unchangedProjects.push(oldProject);\n }\n }\n\n // Check removed\n for (const [path, project] of oldProjectMap) {\n if (!newProjectMap.has(path)) {\n removedProjects.push(project);\n }\n }\n\n return {\n newProjects,\n updatedProjects,\n removedProjects,\n unchangedProjects,\n };\n}\n","import { resolve } from \"node:path\";\nimport { scanProjects } from \"../scanner/index.js\";\nimport { runInterview } from \"../interviewer/index.js\";\nimport { buildSpec } from \"../spec/builder.js\";\nimport { buildFreshPrompt } from \"../orchestrator/prompt-builder.js\";\nimport { detectEngines, getAvailableEngineTypes } from \"../orchestrator/detect.js\";\nimport { writeJson, writeText } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\n\ninterface SpecOptions {\n scan?: string[];\n output?: string;\n}\n\nexport async function specCommand(options: SpecOptions): Promise<void> {\n logger.header(\"shipfolio spec\");\n\n // Detect engines (needed for interview but not for execution)\n const engines = await detectEngines();\n const availableTypes = getAvailableEngineTypes(engines);\n\n // Even if no engine is available, we can still generate spec\n // (user will use it inside their own AI session)\n const engineTypes =\n availableTypes.length > 0 ? availableTypes : ([\"claude\"] as const);\n\n // Scan\n const scanDirs = options.scan?.map((d) => resolve(d)) || [\n resolve(process.cwd()),\n ];\n const scannedProjects = await scanProjects(scanDirs);\n\n if (scannedProjects.length === 0) {\n logger.error(\"No projects found.\");\n process.exit(1);\n }\n\n logger.info(`Found ${scannedProjects.length} projects`);\n\n // Interview\n const interviewResult = await runInterview(\n scannedProjects,\n [...engineTypes]\n );\n\n // Build spec\n const spec = buildSpec(interviewResult);\n\n // Generate prompt\n const prompt = await buildFreshPrompt(spec);\n\n // Save outputs\n const outputDir = options.output || \".\";\n const specPath = resolve(outputDir, \"shipfolio-spec.json\");\n const promptPath = resolve(outputDir, \"shipfolio-prompt.md\");\n\n await writeJson(specPath, spec);\n await writeText(promptPath, prompt);\n\n logger.success(`Spec saved: ${specPath}`);\n logger.success(`Prompt saved: ${promptPath}`);\n logger.blank();\n logger.info(\n \"Use these files inside your Claude Code or Codex session to generate the site.\"\n );\n}\n","import { resolve } from \"node:path\";\nimport { deploy as deployFn } from \"../deployer/index.js\";\nimport { readJson, fileExists, join } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { ShipfolioConfig, DeployPlatform } from \"../spec/schema.js\";\nimport * as p from \"@clack/prompts\";\n\ninterface DeployOptions {\n site: string;\n platform?: string;\n}\n\nexport async function deployCommand(options: DeployOptions): Promise<void> {\n const siteDir = resolve(options.site);\n const configPath = join(siteDir, \"shipfolio.config.json\");\n\n let platform: DeployPlatform;\n let projectName: string;\n\n if (await fileExists(configPath)) {\n const config = await readJson<ShipfolioConfig>(configPath);\n platform =\n (options.platform as DeployPlatform) || config.deploy.platform;\n projectName = config.deploy.projectName;\n } else {\n platform = (options.platform as DeployPlatform) || \"cloudflare\";\n projectName = (await p.text({\n message: \"Project name:\",\n validate: (v) =>\n /^[a-z0-9-]+$/.test(v)\n ? undefined\n : \"Lowercase letters, numbers, and hyphens only\",\n })) as string;\n\n if (p.isCancel(projectName)) process.exit(0);\n }\n\n if (platform === \"local\") {\n logger.info(\"Deploy platform is set to local. Nothing to deploy.\");\n return;\n }\n\n const outDir = join(siteDir, \"out\");\n if (!(await fileExists(outDir))) {\n logger.error(\"Build output not found. Run `npm run build` in the site directory first.\");\n process.exit(1);\n }\n\n await deployFn(siteDir, platform, projectName);\n}\n","import { resolve } from \"node:path\";\nimport { exportPdf } from \"../pdf/index.js\";\nimport { fileExists, join } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\n\ninterface PdfOptions {\n site: string;\n output?: string;\n}\n\nexport async function pdfCommand(options: PdfOptions): Promise<void> {\n const siteDir = resolve(options.site);\n const outDir = join(siteDir, \"out\");\n\n if (!(await fileExists(outDir))) {\n logger.error(\n \"Build output not found. Run `npm run build` in the site directory first.\"\n );\n process.exit(1);\n }\n\n await exportPdf(siteDir, options.output);\n}\n","import { resolve } from \"node:path\";\nimport { startPreviewServer } from \"../pdf/index.js\";\nimport { fileExists, join } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\n\ninterface PreviewOptions {\n site: string;\n port?: number;\n}\n\nexport async function previewCommand(options: PreviewOptions): Promise<void> {\n const siteDir = resolve(options.site);\n const outDir = join(siteDir, \"out\");\n\n if (!(await fileExists(outDir))) {\n logger.error(\n \"Build output not found. Run `npm run build` in the site directory first.\"\n );\n process.exit(1);\n }\n\n const port = options.port || 3000;\n await startPreviewServer(siteDir, port);\n logger.info(\"Press Ctrl+C to stop.\");\n\n // Keep process alive\n await new Promise(() => {});\n}\n"],"mappings":"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","names":["glob","path","p","p","readFile","join","fileURLToPath","p","execa","ora","execa","ora","writeFile","mkdir","join","dirname","ora","ora","ora","ora","p","join","join","ora","resolve","join","p","resolve","p","path","p","resolve","initCommand","resolve","resolve","p","resolve","resolve"]}
1
+ {"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../src/scanner/git.ts","../src/utils/fs.ts","../src/scanner/detectors/node.ts","../src/scanner/detectors/python.ts","../src/scanner/detectors/rust.ts","../src/scanner/detectors/go.ts","../src/scanner/detectors/generic.ts","../src/scanner/extractors.ts","../src/utils/logger.ts","../src/scanner/index.ts","../src/interviewer/questions.ts","../src/interviewer/index.ts","../src/spec/builder.ts","../src/orchestrator/prompt-builder.ts","../src/utils/exec.ts","../src/orchestrator/detect.ts","../src/orchestrator/engines/claude.ts","../src/orchestrator/engines/codex.ts","../src/orchestrator/engines/v0.ts","../src/orchestrator/validator.ts","../src/orchestrator/index.ts","../src/deployer/auth.ts","../src/deployer/cloudflare.ts","../src/deployer/vercel.ts","../src/deployer/github.ts","../src/deployer/index.ts","../src/pdf/index.ts","../src/commands/init.ts","../src/index.ts","../src/commands/update.ts","../src/spec/diff.ts","../src/commands/spec.ts","../src/commands/deploy.ts","../src/commands/pdf.ts","../src/commands/preview.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import simpleGit from \"simple-git\";\nimport { basename } from \"node:path\";\n\nexport interface GitMeta {\n isRepo: boolean;\n firstCommitDate: string | null;\n lastCommitDate: string | null;\n totalCommits: number;\n remoteUrl: string | null;\n lastCommitHash: string | null;\n}\n\nexport async function getGitMeta(projectPath: string): Promise<GitMeta> {\n const git = simpleGit(projectPath);\n const empty: GitMeta = {\n isRepo: false,\n firstCommitDate: null,\n lastCommitDate: null,\n totalCommits: 0,\n remoteUrl: null,\n lastCommitHash: null,\n };\n\n try {\n const isRepo = await git.checkIsRepo();\n if (!isRepo) return empty;\n } catch {\n return empty;\n }\n\n try {\n const log = await git.log({ maxCount: 1 });\n\n // Get first commit date\n let firstCommitDate: string | null = null;\n try {\n const firstResult = await git.raw([\"log\", \"--reverse\", \"--format=%aI\", \"--max-count=1\"]);\n firstCommitDate = firstResult.trim() || null;\n } catch {\n // ignore\n }\n\n let remoteUrl: string | null = null;\n try {\n const remotes = await git.getRemotes(true);\n const origin = remotes.find((r) => r.name === \"origin\");\n if (origin?.refs?.fetch) {\n remoteUrl = normalizeGitUrl(origin.refs.fetch);\n }\n } catch {\n // no remotes\n }\n\n // Get total commit count\n let totalCommits = 0;\n try {\n const result = await git.raw([\"rev-list\", \"--count\", \"HEAD\"]);\n totalCommits = parseInt(result.trim(), 10) || 0;\n } catch {\n totalCommits = 0;\n }\n\n return {\n isRepo: true,\n firstCommitDate,\n lastCommitDate: log.latest?.date || null,\n totalCommits,\n remoteUrl,\n lastCommitHash: log.latest?.hash || null,\n };\n } catch {\n return { ...empty, isRepo: true };\n }\n}\n\nfunction normalizeGitUrl(url: string): string {\n // Convert SSH to HTTPS\n if (url.startsWith(\"git@\")) {\n url = url.replace(\":\", \"/\").replace(\"git@\", \"https://\");\n }\n // Remove .git suffix\n if (url.endsWith(\".git\")) {\n url = url.slice(0, -4);\n }\n return url;\n}\n\nexport async function findGitRepos(\n rootPath: string,\n maxDepth: number = 3\n): Promise<string[]> {\n const { glob } = await import(\"glob\");\n const gitDirs = await glob(\"**/.git\", {\n cwd: rootPath,\n maxDepth: maxDepth + 1,\n dot: true,\n ignore: [\n \"**/node_modules/**/.git\",\n \"**/vendor/**/.git\",\n \"**/__pycache__/**/.git\",\n ],\n });\n\n return gitDirs\n .map((gitDir) => {\n const parts = gitDir.split(\"/\");\n parts.pop(); // remove .git\n return parts.length > 0\n ? `${rootPath}/${parts.join(\"/\")}`\n : rootPath;\n })\n .sort();\n}\n","import { readFile, writeFile, access, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport async function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function readJson<T = unknown>(path: string): Promise<T> {\n const content = await readFile(path, \"utf-8\");\n return JSON.parse(content) as T;\n}\n\nexport async function writeJson(path: string, data: unknown): Promise<void> {\n await writeFile(path, JSON.stringify(data, null, 2), \"utf-8\");\n}\n\nexport async function readText(path: string): Promise<string> {\n return readFile(path, \"utf-8\");\n}\n\nexport async function writeText(path: string, content: string): Promise<void> {\n await writeFile(path, content, \"utf-8\");\n}\n\nexport async function ensureDir(path: string): Promise<void> {\n await mkdir(path, { recursive: true });\n}\n\nexport { join };\n","import { fileExists, readJson, join } from \"../../utils/fs.js\";\n\ninterface PackageJson {\n name?: string;\n description?: string;\n homepage?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nexport async function detectNode(projectPath: string) {\n const pkgPath = join(projectPath, \"package.json\");\n if (!(await fileExists(pkgPath))) return null;\n\n const pkg = await readJson<PackageJson>(pkgPath);\n const allDeps = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n const depNames = Object.keys(allDeps);\n\n const techStack: string[] = [];\n\n // Frameworks\n if (depNames.includes(\"next\")) techStack.push(\"Next.js\");\n else if (depNames.includes(\"nuxt\")) techStack.push(\"Nuxt\");\n else if (depNames.includes(\"astro\")) techStack.push(\"Astro\");\n else if (depNames.includes(\"svelte\") || depNames.includes(\"@sveltejs/kit\"))\n techStack.push(\"Svelte\");\n\n // UI libraries\n if (depNames.includes(\"react\")) techStack.push(\"React\");\n if (depNames.includes(\"vue\")) techStack.push(\"Vue\");\n\n // Styling\n if (depNames.includes(\"tailwindcss\")) techStack.push(\"Tailwind CSS\");\n\n // Backend\n if (depNames.includes(\"express\")) techStack.push(\"Express\");\n if (depNames.includes(\"fastify\")) techStack.push(\"Fastify\");\n if (depNames.includes(\"hono\")) techStack.push(\"Hono\");\n\n // Database\n if (depNames.includes(\"prisma\") || depNames.includes(\"@prisma/client\"))\n techStack.push(\"Prisma\");\n if (depNames.includes(\"drizzle-orm\")) techStack.push(\"Drizzle\");\n if (depNames.includes(\"mongoose\")) techStack.push(\"MongoDB\");\n\n // AI/ML\n if (depNames.includes(\"openai\")) techStack.push(\"OpenAI\");\n if (depNames.includes(\"@anthropic-ai/sdk\")) techStack.push(\"Claude API\");\n if (depNames.includes(\"langchain\")) techStack.push(\"LangChain\");\n\n // Language\n if (depNames.includes(\"typescript\")) techStack.push(\"TypeScript\");\n else techStack.push(\"JavaScript\");\n\n return {\n name: pkg.name || null,\n description: pkg.description || null,\n homepage: pkg.homepage || null,\n techStack,\n };\n}\n","import { fileExists, readText, join } from \"../../utils/fs.js\";\n\nexport async function detectPython(projectPath: string) {\n const techStack: string[] = [\"Python\"];\n\n const reqPath = join(projectPath, \"requirements.txt\");\n const pyprojectPath = join(projectPath, \"pyproject.toml\");\n const setupPath = join(projectPath, \"setup.py\");\n\n let deps = \"\";\n\n if (await fileExists(reqPath)) {\n deps = await readText(reqPath);\n } else if (await fileExists(pyprojectPath)) {\n deps = await readText(pyprojectPath);\n } else if (await fileExists(setupPath)) {\n deps = await readText(setupPath);\n } else {\n return null;\n }\n\n const depsLower = deps.toLowerCase();\n\n if (depsLower.includes(\"django\")) techStack.push(\"Django\");\n if (depsLower.includes(\"flask\")) techStack.push(\"Flask\");\n if (depsLower.includes(\"fastapi\")) techStack.push(\"FastAPI\");\n if (depsLower.includes(\"pytorch\") || depsLower.includes(\"torch\"))\n techStack.push(\"PyTorch\");\n if (depsLower.includes(\"tensorflow\")) techStack.push(\"TensorFlow\");\n if (depsLower.includes(\"transformers\")) techStack.push(\"Transformers\");\n if (depsLower.includes(\"langchain\")) techStack.push(\"LangChain\");\n if (depsLower.includes(\"openai\")) techStack.push(\"OpenAI\");\n if (depsLower.includes(\"pandas\")) techStack.push(\"Pandas\");\n if (depsLower.includes(\"numpy\")) techStack.push(\"NumPy\");\n if (depsLower.includes(\"scikit\")) techStack.push(\"Scikit-learn\");\n\n return { techStack };\n}\n","import { fileExists, readText, join } from \"../../utils/fs.js\";\n\nexport async function detectRust(projectPath: string) {\n const cargoPath = join(projectPath, \"Cargo.toml\");\n if (!(await fileExists(cargoPath))) return null;\n\n const content = await readText(cargoPath);\n const techStack: string[] = [\"Rust\"];\n\n if (content.includes(\"actix\")) techStack.push(\"Actix\");\n if (content.includes(\"axum\")) techStack.push(\"Axum\");\n if (content.includes(\"tokio\")) techStack.push(\"Tokio\");\n if (content.includes(\"wasm\")) techStack.push(\"WebAssembly\");\n if (content.includes(\"tauri\")) techStack.push(\"Tauri\");\n if (content.includes(\"diesel\")) techStack.push(\"Diesel\");\n if (content.includes(\"sqlx\")) techStack.push(\"SQLx\");\n\n // Extract name from [package] section\n const nameMatch = content.match(/\\[package\\][\\s\\S]*?name\\s*=\\s*\"([^\"]+)\"/);\n const descMatch = content.match(\n /\\[package\\][\\s\\S]*?description\\s*=\\s*\"([^\"]+)\"/\n );\n\n return {\n name: nameMatch?.[1] || null,\n description: descMatch?.[1] || null,\n techStack,\n };\n}\n","import { fileExists, readText, join } from \"../../utils/fs.js\";\n\nexport async function detectGo(projectPath: string) {\n const goModPath = join(projectPath, \"go.mod\");\n if (!(await fileExists(goModPath))) return null;\n\n const content = await readText(goModPath);\n const techStack: string[] = [\"Go\"];\n\n if (content.includes(\"gin-gonic\")) techStack.push(\"Gin\");\n if (content.includes(\"echo\")) techStack.push(\"Echo\");\n if (content.includes(\"fiber\")) techStack.push(\"Fiber\");\n if (content.includes(\"grpc\")) techStack.push(\"gRPC\");\n if (content.includes(\"gorm\")) techStack.push(\"GORM\");\n if (content.includes(\"cobra\")) techStack.push(\"Cobra\");\n if (content.includes(\"ent\")) techStack.push(\"Ent\");\n\n return { techStack };\n}\n","import { glob } from \"glob\";\nimport { basename, extname } from \"node:path\";\n\nconst EXTENSION_MAP: Record<string, string> = {\n \".ts\": \"TypeScript\",\n \".tsx\": \"TypeScript\",\n \".js\": \"JavaScript\",\n \".jsx\": \"JavaScript\",\n \".py\": \"Python\",\n \".rs\": \"Rust\",\n \".go\": \"Go\",\n \".java\": \"Java\",\n \".kt\": \"Kotlin\",\n \".swift\": \"Swift\",\n \".rb\": \"Ruby\",\n \".php\": \"PHP\",\n \".cs\": \"C#\",\n \".cpp\": \"C++\",\n \".c\": \"C\",\n \".dart\": \"Dart\",\n \".lua\": \"Lua\",\n \".zig\": \"Zig\",\n \".sol\": \"Solidity\",\n \".ex\": \"Elixir\",\n \".exs\": \"Elixir\",\n};\n\nconst IGNORE_DIRS = [\n \"node_modules\",\n \".git\",\n \"dist\",\n \"build\",\n \"out\",\n \".next\",\n \"target\",\n \"vendor\",\n \"__pycache__\",\n \".venv\",\n \"venv\",\n];\n\nexport async function detectLanguages(\n projectPath: string\n): Promise<Record<string, number>> {\n const ignorePattern = IGNORE_DIRS.map((d) => `**/${d}/**`);\n const files = await glob(\"**/*.*\", {\n cwd: projectPath,\n ignore: ignorePattern,\n nodir: true,\n maxDepth: 5,\n });\n\n const counts: Record<string, number> = {};\n for (const file of files) {\n const ext = extname(file).toLowerCase();\n const lang = EXTENSION_MAP[ext];\n if (lang) {\n counts[lang] = (counts[lang] || 0) + 1;\n }\n }\n\n return counts;\n}\n\nexport function deriveNameFromPath(projectPath: string): string {\n return basename(projectPath);\n}\n","import { fileExists, readText, join } from \"../utils/fs.js\";\n\nexport async function extractReadme(\n projectPath: string\n): Promise<string | null> {\n const candidates = [\n \"README.md\",\n \"readme.md\",\n \"Readme.md\",\n \"README.txt\",\n \"README\",\n ];\n for (const name of candidates) {\n const p = join(projectPath, name);\n if (await fileExists(p)) {\n const content = await readText(p);\n // Limit to first 3000 chars to keep spec manageable\n return content.slice(0, 3000);\n }\n }\n return null;\n}\n\nexport function extractFirstParagraph(readme: string | null): string | null {\n if (!readme) return null;\n // Skip title lines (# heading)\n const lines = readme.split(\"\\n\");\n let collecting = false;\n const paragraphLines: string[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.startsWith(\"#\")) {\n if (collecting && paragraphLines.length > 0) break;\n collecting = true;\n continue;\n }\n if (collecting && trimmed === \"\" && paragraphLines.length > 0) break;\n if (collecting && trimmed !== \"\") {\n paragraphLines.push(trimmed);\n }\n if (!collecting && trimmed !== \"\" && !trimmed.startsWith(\"[\")) {\n paragraphLines.push(trimmed);\n collecting = true;\n }\n }\n\n return paragraphLines.length > 0 ? paragraphLines.join(\" \") : null;\n}\n\nexport function extractDemoUrl(readme: string | null): string | null {\n if (!readme) return null;\n // Look for common demo URL patterns\n const patterns = [\n /(?:demo|live|website|site|url|link)[\\s:]*\\[?[^\\]]*\\]?\\(?(https?:\\/\\/[^\\s)]+)/i,\n /\\[(?:demo|live|website|try it)\\]\\((https?:\\/\\/[^\\s)]+)\\)/i,\n /(https?:\\/\\/[^\\s)]+\\.(?:vercel|netlify|pages\\.dev|herokuapp|railway)\\.app[^\\s)]*)/i,\n ];\n for (const pattern of patterns) {\n const match = readme.match(pattern);\n if (match?.[1]) return match[1];\n }\n return null;\n}\n","import chalk from \"chalk\";\n\nexport const logger = {\n info(msg: string) {\n console.log(chalk.cyan(`-- ${msg}`));\n },\n success(msg: string) {\n console.log(chalk.green(`-- ${msg}`));\n },\n warn(msg: string) {\n console.log(chalk.yellow(`-- ${msg}`));\n },\n error(msg: string) {\n console.error(chalk.red(`-- ${msg}`));\n },\n plain(msg: string) {\n console.log(msg);\n },\n blank() {\n console.log();\n },\n header(msg: string) {\n console.log();\n console.log(chalk.bold(msg));\n console.log();\n },\n table(rows: string[][]) {\n if (rows.length === 0) return;\n const colWidths = rows[0].map((_, colIdx) =>\n Math.max(...rows.map((row) => (row[colIdx] || \"\").length))\n );\n for (const row of rows) {\n const line = row\n .map((cell, i) => (cell || \"\").padEnd(colWidths[i] + 2))\n .join(\"\");\n console.log(` ${line}`);\n }\n },\n};\n","import { findGitRepos, getGitMeta } from \"./git.js\";\nimport { detectNode } from \"./detectors/node.js\";\nimport { detectPython } from \"./detectors/python.js\";\nimport { detectRust } from \"./detectors/rust.js\";\nimport { detectGo } from \"./detectors/go.js\";\nimport { detectLanguages, deriveNameFromPath } from \"./detectors/generic.js\";\nimport {\n extractReadme,\n extractFirstParagraph,\n extractDemoUrl,\n} from \"./extractors.js\";\nimport type { ProjectMeta } from \"../spec/schema.js\";\nimport { logger } from \"../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function scanProjects(\n directories: string[]\n): Promise<ProjectMeta[]> {\n const allPaths: string[] = [];\n\n const spinner = ora(\"Scanning for projects...\").start();\n\n for (const dir of directories) {\n try {\n // Find git repos\n const repos = await findGitRepos(dir);\n allPaths.push(...repos);\n\n // Also find non-git project directories (with package.json, Cargo.toml, etc.)\n const nonGitDirs = await findNonGitProjects(dir, new Set(repos));\n allPaths.push(...nonGitDirs);\n } catch (err) {\n logger.warn(`Could not scan ${dir}: ${err}`);\n }\n }\n\n // Deduplicate\n const uniquePaths = [...new Set(allPaths)];\n spinner.text = `Found ${uniquePaths.length} projects. Extracting metadata...`;\n\n const projects: ProjectMeta[] = [];\n\n for (const projectPath of uniquePaths) {\n try {\n const project = await extractProjectMeta(projectPath);\n if (project) {\n projects.push(project);\n }\n } catch (err) {\n // Skip projects that fail extraction\n }\n }\n\n // Deduplicate IDs (same folder name in different parent dirs)\n const idCounts = new Map<string, number>();\n for (const project of projects) {\n const count = idCounts.get(project.id) || 0;\n if (count > 0) {\n project.id = `${project.id}-${count}`;\n }\n idCounts.set(project.id.replace(/-\\d+$/, \"\"), count + 1);\n }\n\n spinner.succeed(`Scanned ${projects.length} projects`);\n return projects;\n}\n\nasync function findNonGitProjects(\n rootPath: string,\n gitRepos: Set<string>\n): Promise<string[]> {\n const { glob } = await import(\"glob\");\n const indicators = [\n \"*/package.json\",\n \"*/Cargo.toml\",\n \"*/go.mod\",\n \"*/pyproject.toml\",\n \"*/requirements.txt\",\n \"*/setup.py\",\n ];\n const found = new Set<string>();\n for (const pattern of indicators) {\n const matches = await glob(pattern, {\n cwd: rootPath,\n ignore: [\"**/node_modules/**\", \"**/vendor/**\"],\n });\n for (const match of matches) {\n const dir = `${rootPath}/${match.split(\"/\")[0]}`;\n if (!gitRepos.has(dir) && !found.has(dir)) {\n found.add(dir);\n }\n }\n }\n return [...found].sort();\n}\n\nasync function extractProjectMeta(\n projectPath: string\n): Promise<ProjectMeta | null> {\n const gitMeta = await getGitMeta(projectPath);\n\n // Detect tech stack from various sources\n let techStack: string[] = [];\n let name: string | null = null;\n let description: string | null = null;\n let homepage: string | null = null;\n\n const nodeInfo = await detectNode(projectPath);\n if (nodeInfo) {\n techStack.push(...nodeInfo.techStack);\n name = nodeInfo.name || name;\n description = nodeInfo.description || description;\n homepage = nodeInfo.homepage || homepage;\n }\n\n const pythonInfo = await detectPython(projectPath);\n if (pythonInfo) {\n techStack.push(...pythonInfo.techStack);\n }\n\n const rustInfo = await detectRust(projectPath);\n if (rustInfo) {\n techStack.push(...rustInfo.techStack);\n name = rustInfo.name || name;\n description = rustInfo.description || description;\n }\n\n const goInfo = await detectGo(projectPath);\n if (goInfo) {\n techStack.push(...goInfo.techStack);\n }\n\n // Deduplicate tech stack\n techStack = [...new Set(techStack)];\n\n // Language breakdown\n const languages = await detectLanguages(projectPath);\n\n // If no tech stack detected, derive from languages\n if (techStack.length === 0) {\n const topLangs = Object.entries(languages)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 3)\n .map(([lang]) => lang);\n techStack = topLangs;\n }\n\n // README\n const readmeContent = await extractReadme(projectPath);\n if (!description) {\n description = extractFirstParagraph(readmeContent) || \"\";\n }\n\n // Demo URL\n const demoUrl = homepage || extractDemoUrl(readmeContent);\n\n // Name fallback\n if (!name) {\n name = deriveNameFromPath(projectPath);\n }\n\n // Generate stable ID from path (use folder name to keep it readable, but\n // append a hash suffix when the same folder name appears in multiple paths)\n const folderName = deriveNameFromPath(projectPath);\n const id = folderName\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n\n return {\n id,\n name,\n localPath: projectPath,\n description: description || \"\",\n techStack,\n languages,\n firstCommitDate: gitMeta.firstCommitDate || \"\",\n lastCommitDate: gitMeta.lastCommitDate || \"\",\n totalCommits: gitMeta.totalCommits,\n remoteUrl: gitMeta.remoteUrl,\n demoUrl,\n readmeContent,\n lastScannedCommit: gitMeta.lastCommitHash || \"\",\n };\n}\n","import type {\n StyleConfig,\n SectionId,\n EngineType,\n DeployPlatform,\n} from \"../spec/schema.js\";\n\nexport const THEME_OPTIONS: { value: StyleConfig[\"theme\"]; label: string }[] = [\n { value: \"dark-minimal\", label: \"Dark Minimal\" },\n { value: \"light-clean\", label: \"Light Clean\" },\n { value: \"monochrome\", label: \"Monochrome\" },\n { value: \"custom\", label: \"Custom (AI decides)\" },\n];\n\nexport const FONT_OPTIONS: { value: StyleConfig[\"font\"]; label: string }[] = [\n { value: \"Inter\", label: \"Inter\" },\n { value: \"JetBrains Mono\", label: \"JetBrains Mono\" },\n { value: \"system\", label: \"System Default\" },\n];\n\nexport const ANIMATION_OPTIONS: {\n value: StyleConfig[\"animationLevel\"];\n label: string;\n}[] = [\n { value: \"subtle\", label: \"Subtle\" },\n { value: \"moderate\", label: \"Moderate\" },\n { value: \"none\", label: \"None\" },\n];\n\nexport const SECTION_OPTIONS: { value: SectionId; label: string }[] = [\n { value: \"skills\", label: \"Skills / Tech Stack\" },\n { value: \"about\", label: \"About Me\" },\n { value: \"timeline\", label: \"Timeline / Changelog\" },\n { value: \"blog\", label: \"Blog\" },\n { value: \"metrics\", label: \"Metrics Dashboard\" },\n { value: \"contact\", label: \"Contact\" },\n];\n\nexport const ENGINE_OPTIONS: { value: EngineType; label: string }[] = [\n { value: \"claude\", label: \"Claude Code\" },\n { value: \"codex\", label: \"Codex\" },\n { value: \"v0\", label: \"v0 (Vercel)\" },\n];\n\nexport const DEPLOY_OPTIONS: { value: DeployPlatform; label: string }[] = [\n { value: \"cloudflare\", label: \"Cloudflare Pages\" },\n { value: \"vercel\", label: \"Vercel\" },\n { value: \"local\", label: \"Local only (no deploy)\" },\n];\n\nexport const ROLE_OPTIONS: {\n value: \"solo\" | \"lead\" | \"contributor\";\n label: string;\n}[] = [\n { value: \"solo\", label: \"Solo\" },\n { value: \"lead\", label: \"Lead\" },\n { value: \"contributor\", label: \"Contributor\" },\n];\n\nexport const DEFAULT_ACCENT_COLORS: { value: string; label: string }[] = [\n { value: \"#7c3aed\", label: \"Purple\" },\n { value: \"#10b981\", label: \"Green\" },\n { value: \"#f97316\", label: \"Orange\" },\n { value: \"#3b82f6\", label: \"Blue\" },\n { value: \"#ef4444\", label: \"Red\" },\n { value: \"#ec4899\", label: \"Pink\" },\n];\n","import * as p from \"@clack/prompts\";\nimport type {\n ProjectMeta,\n ProjectEntry,\n OwnerInfo,\n StyleConfig,\n SectionId,\n EngineType,\n DeployPlatform,\n} from \"../spec/schema.js\";\nimport {\n THEME_OPTIONS,\n FONT_OPTIONS,\n ANIMATION_OPTIONS,\n SECTION_OPTIONS,\n ENGINE_OPTIONS,\n DEPLOY_OPTIONS,\n ROLE_OPTIONS,\n DEFAULT_ACCENT_COLORS,\n} from \"./questions.js\";\nimport { logger } from \"../utils/logger.js\";\n\n/** ProjectMeta with optional children for merged groups */\ninterface MergeableMeta extends ProjectMeta {\n children?: ProjectMeta[];\n}\n\nfunction handleCancel(value: unknown): void {\n if (p.isCancel(value)) {\n p.cancel(\"Cancelled.\");\n process.exit(0);\n }\n}\n\nexport interface InterviewResult {\n projects: ProjectEntry[];\n owner: OwnerInfo;\n style: StyleConfig;\n sections: SectionId[];\n engine: EngineType;\n deploy: {\n platform: DeployPlatform;\n projectName: string;\n };\n}\n\nasync function runMergeStep(\n projects: MergeableMeta[]\n): Promise<MergeableMeta[]> {\n const shouldMerge = (await p.confirm({\n message: \"Merge any related projects into one entry? (e.g. web + mobile)\",\n initialValue: false,\n })) as boolean;\n handleCancel(shouldMerge);\n\n if (!shouldMerge) return projects;\n\n // Work on a mutable copy\n let remaining = [...projects];\n\n while (remaining.length >= 2) {\n const mergeIds = (await p.multiselect({\n message:\n \"Select projects to merge together (space = select, enter = confirm):\",\n options: remaining.map((proj) => ({\n value: proj.id,\n label: `${proj.name} (${proj.localPath})`,\n hint: proj.techStack.slice(0, 3).join(\", \"),\n })),\n required: true,\n })) as string[];\n handleCancel(mergeIds);\n\n if (mergeIds.length < 2) {\n logger.warn(\"Need at least 2 projects to merge. Skipping.\");\n break;\n }\n\n // Collect the projects being merged\n const toMerge = mergeIds.map(\n (id) => remaining.find((p) => p.id === id)!\n );\n\n // Ask for the merged entry name\n const defaultName = toMerge.map((p) => p.name).join(\" + \");\n const mergedName = (await p.text({\n message: \"Name for the merged entry:\",\n placeholder: defaultName,\n defaultValue: defaultName,\n })) as string;\n handleCancel(mergedName);\n\n // Build the merged meta\n const merged = mergeProjects(toMerge, mergedName);\n\n // Remove merged items, add the new merged entry\n remaining = remaining.filter((p) => !mergeIds.includes(p.id));\n remaining.push(merged);\n\n logger.info(\n `Merged ${toMerge.map((p) => p.name).join(\", \")} -> \"${mergedName}\"`\n );\n\n if (remaining.length < 2) break;\n\n const more = (await p.confirm({\n message: \"Merge more projects?\",\n initialValue: false,\n })) as boolean;\n handleCancel(more);\n\n if (!more) break;\n }\n\n return remaining;\n}\n\nfunction mergeProjects(\n projects: MergeableMeta[],\n name: string\n): MergeableMeta {\n // Flatten: if any project is itself a merged group, collect its children\n const allChildren: ProjectMeta[] = [];\n for (const proj of projects) {\n if (proj.children && proj.children.length > 0) {\n allChildren.push(...proj.children);\n } else {\n // Store the original as a child (strip children field)\n const { children, ...rest } = proj as MergeableMeta;\n allChildren.push(rest);\n }\n }\n\n // Combine tech stacks (deduplicated)\n const techStack = [\n ...new Set(allChildren.flatMap((p) => p.techStack)),\n ];\n\n // Combine languages\n const languages: Record<string, number> = {};\n for (const child of allChildren) {\n for (const [lang, count] of Object.entries(child.languages)) {\n languages[lang] = (languages[lang] || 0) + count;\n }\n }\n\n // Use earliest first commit, latest last commit\n const firstDates = allChildren\n .map((p) => p.firstCommitDate)\n .filter(Boolean)\n .sort();\n const lastDates = allChildren\n .map((p) => p.lastCommitDate)\n .filter(Boolean)\n .sort();\n\n // Sum commits\n const totalCommits = allChildren.reduce(\n (sum, p) => sum + p.totalCommits,\n 0\n );\n\n // Collect all remote URLs (pick first non-null)\n const remoteUrl =\n allChildren.find((p) => p.remoteUrl)?.remoteUrl || null;\n\n // Collect all demo URLs (pick first non-null)\n const demoUrl =\n allChildren.find((p) => p.demoUrl)?.demoUrl || null;\n\n // Concatenate README contents\n const readmeParts = allChildren\n .filter((p) => p.readmeContent)\n .map(\n (p) =>\n `--- ${p.name} ---\\n${p.readmeContent}`\n );\n const readmeContent =\n readmeParts.length > 0 ? readmeParts.join(\"\\n\\n\") : null;\n\n // Combine descriptions\n const descriptions = allChildren\n .map((p) => p.description)\n .filter(Boolean);\n const description = descriptions.join(\" | \");\n\n // Use first child's path as the \"primary\" local path\n const localPath = allChildren[0].localPath;\n\n const id = name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n\n return {\n id,\n name,\n localPath,\n description,\n techStack,\n languages,\n firstCommitDate: firstDates[0] || \"\",\n lastCommitDate: lastDates[lastDates.length - 1] || \"\",\n totalCommits,\n remoteUrl,\n demoUrl,\n readmeContent,\n lastScannedCommit: allChildren[0].lastScannedCommit || \"\",\n children: allChildren,\n };\n}\n\nexport async function runInterview(\n scannedProjects: ProjectMeta[],\n availableEngines: EngineType[]\n): Promise<InterviewResult> {\n p.intro(\"shipfolio\");\n\n // -- Project Selection --\n logger.header(\"Project Selection\");\n\n const projectOptions = scannedProjects.map((proj) => {\n const techInfo = proj.techStack.slice(0, 3).join(\", \");\n const commitInfo = proj.totalCommits > 0 ? `${proj.totalCommits} commits` : \"no git\";\n return {\n value: proj.id,\n label: `${proj.name} (${proj.localPath})`,\n hint: techInfo ? `${techInfo} | ${commitInfo}` : commitInfo,\n };\n });\n\n const selectedIds = (await p.multiselect({\n message: \"Select projects to include (space = select, enter = confirm):\",\n options: projectOptions,\n required: true,\n })) as string[];\n handleCancel(selectedIds);\n\n // Build the working list of selected project metas\n let selectedMetas: MergeableMeta[] = selectedIds.map(\n (id) => scannedProjects.find((p) => p.id === id)!\n );\n\n // -- Merge Step --\n if (selectedMetas.length >= 2) {\n selectedMetas = await runMergeStep(selectedMetas);\n }\n\n // -- Per-Project Details --\n const projectEntries: ProjectEntry[] = [];\n\n for (const meta of selectedMetas) {\n const displayName = meta.children\n ? `${meta.name} (${meta.children.length} sub-projects)`\n : meta.name;\n\n logger.plain(`\\n Configuring: ${displayName}`);\n\n const overrideDesc = (await p.text({\n message: `Description for ${displayName} (enter to use auto-generated):`,\n placeholder: meta.description?.slice(0, 80) || \"Auto-generate from README\",\n defaultValue: \"\",\n })) as string;\n handleCancel(overrideDesc);\n\n const demoUrl = (await p.text({\n message: `Demo URL for ${displayName}:`,\n placeholder: meta.demoUrl || \"none\",\n defaultValue: meta.demoUrl || \"\",\n })) as string;\n handleCancel(demoUrl);\n\n const showSource = (await p.confirm({\n message: `Show source code link for ${displayName}?`,\n initialValue: !!meta.remoteUrl,\n })) as boolean;\n handleCancel(showSource);\n\n const role = (await p.select({\n message: `Your role in ${displayName}:`,\n options: ROLE_OPTIONS,\n })) as \"solo\" | \"lead\" | \"contributor\";\n handleCancel(role);\n\n const metricsInput = (await p.text({\n message: `Key metrics for ${displayName} (e.g. \"1k users, $5k MRR\"):`,\n placeholder: \"optional\",\n defaultValue: \"\",\n })) as string;\n handleCancel(metricsInput);\n\n const metrics: ProjectEntry[\"metrics\"] = {};\n if (metricsInput) {\n metrics.custom = { summary: metricsInput };\n }\n\n projectEntries.push({\n ...meta,\n included: true,\n overrideDescription: overrideDesc || null,\n showSourceLink: showSource,\n demoUrl: demoUrl || meta.demoUrl,\n role,\n metrics,\n });\n }\n\n // -- Personal Info --\n logger.header(\"Personal Information\");\n\n const name = (await p.text({\n message: \"Your full name:\",\n validate: (v) => (v.length === 0 ? \"Name is required\" : undefined),\n })) as string;\n handleCancel(name);\n\n const tagline = (await p.text({\n message: \"Professional tagline (one line):\",\n placeholder: \"Full-stack developer. I ship things.\",\n })) as string;\n handleCancel(tagline);\n\n const bioChoice = (await p.select({\n message: \"Bio:\",\n options: [\n { value: \"auto\", label: \"Auto-generate from my projects\" },\n { value: \"manual\", label: \"Write manually\" },\n ],\n })) as string;\n handleCancel(bioChoice);\n\n let bio: string | \"auto\" = \"auto\";\n if (bioChoice === \"manual\") {\n bio = (await p.text({\n message: \"Your bio (2-3 sentences):\",\n })) as string;\n handleCancel(bio);\n }\n\n const photoUrl = (await p.text({\n message: \"Photo URL (optional):\",\n placeholder: \"https://...\",\n defaultValue: \"\",\n })) as string;\n handleCancel(photoUrl);\n\n const github = (await p.text({\n message: \"GitHub username or URL:\",\n defaultValue: \"\",\n })) as string;\n handleCancel(github);\n\n const twitter = (await p.text({\n message: \"Twitter/X handle:\",\n defaultValue: \"\",\n })) as string;\n handleCancel(twitter);\n\n const linkedin = (await p.text({\n message: \"LinkedIn URL:\",\n defaultValue: \"\",\n })) as string;\n handleCancel(linkedin);\n\n const blogUrl = (await p.text({\n message: \"Blog URL:\",\n defaultValue: \"\",\n })) as string;\n handleCancel(blogUrl);\n\n const email = (await p.text({\n message: \"Contact email:\",\n defaultValue: \"\",\n })) as string;\n handleCancel(email);\n\n const owner: OwnerInfo = {\n name,\n tagline,\n bio,\n photoUrl: photoUrl || null,\n social: {\n github: github || undefined,\n twitter: twitter || undefined,\n linkedin: linkedin || undefined,\n blog: blogUrl || undefined,\n email: email || undefined,\n },\n };\n\n // -- Design Preferences --\n logger.header(\"Design Preferences\");\n\n const theme = (await p.select({\n message: \"Theme:\",\n options: THEME_OPTIONS,\n })) as StyleConfig[\"theme\"];\n handleCancel(theme);\n\n const accentColor = (await p.select({\n message: \"Accent color:\",\n options: [\n ...DEFAULT_ACCENT_COLORS,\n { value: \"custom\", label: \"Custom hex\" },\n ],\n })) as string;\n handleCancel(accentColor);\n\n let finalAccent = accentColor;\n if (accentColor === \"custom\") {\n finalAccent = (await p.text({\n message: \"Custom accent color (hex):\",\n placeholder: \"#7c3aed\",\n validate: (v) =>\n /^#[0-9a-fA-F]{6}$/.test(v) ? undefined : \"Enter a valid hex color\",\n })) as string;\n handleCancel(finalAccent);\n }\n\n const font = (await p.select({\n message: \"Font:\",\n options: FONT_OPTIONS,\n })) as StyleConfig[\"font\"];\n handleCancel(font);\n\n const animationLevel = (await p.select({\n message: \"Animation level:\",\n options: ANIMATION_OPTIONS,\n })) as StyleConfig[\"animationLevel\"];\n handleCancel(animationLevel);\n\n const style: StyleConfig = {\n theme,\n accentColor: finalAccent,\n font,\n animationLevel,\n };\n\n // -- Sections --\n logger.header(\"Sections\");\n\n const additionalSections = (await p.multiselect({\n message: \"Additional sections (Hero + Projects always included):\",\n options: SECTION_OPTIONS,\n required: false,\n })) as SectionId[];\n handleCancel(additionalSections);\n\n const sections: SectionId[] = [\n \"hero\",\n \"projects\",\n ...additionalSections,\n ];\n\n // -- Engine Selection --\n logger.header(\"AI Engine\");\n\n let engine: EngineType;\n if (availableEngines.length === 1) {\n engine = availableEngines[0];\n logger.info(`Using ${engine}`);\n } else {\n const filteredEngineOptions = ENGINE_OPTIONS.filter((o) =>\n availableEngines.includes(o.value)\n );\n engine = (await p.select({\n message: \"AI engine to use:\",\n options: filteredEngineOptions,\n })) as EngineType;\n handleCancel(engine);\n }\n\n // -- Deploy Target --\n logger.header(\"Deployment\");\n\n const deployPlatform = (await p.select({\n message: \"Deploy to:\",\n options: DEPLOY_OPTIONS,\n })) as DeployPlatform;\n handleCancel(deployPlatform);\n\n let projectName = \"\";\n if (deployPlatform !== \"local\") {\n projectName = (await p.text({\n message: \"Project name (used in URL):\",\n placeholder: \"my-shipfolio\",\n validate: (v) =>\n /^[a-z0-9-]+$/.test(v)\n ? undefined\n : \"Lowercase letters, numbers, and hyphens only\",\n })) as string;\n handleCancel(projectName);\n }\n\n p.outro(\"Configuration complete. Generating your site...\");\n\n return {\n projects: projectEntries,\n owner,\n style,\n sections,\n engine,\n deploy: {\n platform: deployPlatform,\n projectName,\n },\n };\n}\n","import type { ShipfolioSpec } from \"./schema.js\";\nimport type { InterviewResult } from \"../interviewer/index.js\";\n\nexport function buildSpec(interview: InterviewResult): ShipfolioSpec {\n return {\n version: \"1.0.0\",\n generatedAt: new Date().toISOString(),\n engine: interview.engine,\n framework: \"next\",\n style: interview.style,\n owner: interview.owner,\n projects: interview.projects,\n sections: interview.sections,\n deploy: {\n platform: interview.deploy.platform,\n projectName: interview.deploy.projectName,\n },\n };\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { ShipfolioSpec, ShipfolioConfig, SiteDiff } from \"../spec/schema.js\";\n\nfunction getPromptsDir(): string {\n // In development: relative to src/orchestrator/\n // In built: relative to dist/\n const currentDir = dirname(fileURLToPath(import.meta.url));\n // Try multiple possible locations\n const candidates = [\n join(currentDir, \"../../prompts\"),\n join(currentDir, \"../prompts\"),\n join(currentDir, \"../../../prompts\"),\n ];\n return candidates[0]; // Default; will fail gracefully if not found\n}\n\nasync function loadTemplate(filename: string): Promise<string> {\n const promptsDir = getPromptsDir();\n // Try each candidate path\n const candidates = [\n join(promptsDir, filename),\n join(dirname(fileURLToPath(import.meta.url)), \"../../prompts\", filename),\n join(dirname(fileURLToPath(import.meta.url)), \"../../../prompts\", filename),\n ];\n\n for (const candidate of candidates) {\n try {\n return await readFile(candidate, \"utf-8\");\n } catch {\n continue;\n }\n }\n\n throw new Error(`Prompt template not found: ${filename}`);\n}\n\nexport async function buildFreshPrompt(spec: ShipfolioSpec): Promise<string> {\n let template = await loadTemplate(\"fresh-build.md\");\n\n const sectionsText = spec.sections\n .map((s) => `- ${s}`)\n .join(\"\\n\");\n\n template = template\n .replace(\"{{SPEC_JSON}}\", JSON.stringify(spec, null, 2))\n .replace(\"{{THEME}}\", spec.style.theme)\n .replace(\"{{ACCENT_COLOR}}\", spec.style.accentColor)\n .replace(\"{{ANIMATION_LEVEL}}\", spec.style.animationLevel)\n .replace(\"{{FONT}}\", spec.style.font)\n .replace(\"{{SECTIONS_LIST}}\", sectionsText);\n\n return template;\n}\n\nexport async function buildUpdatePrompt(\n existingConfig: ShipfolioConfig,\n diff: SiteDiff\n): Promise<string> {\n let template = await loadTemplate(\"update.md\");\n\n const newProjectsText =\n diff.newProjects.length > 0\n ? diff.newProjects\n .map(\n (p) =>\n `- ${p.name}: ${p.description}\\n Tech: ${p.techStack.join(\", \")}\\n README excerpt: ${(p.readmeContent || \"\").slice(0, 500)}`\n )\n .join(\"\\n\\n\")\n : \"None\";\n\n const updatedProjectsText =\n diff.updatedProjects.length > 0\n ? diff.updatedProjects\n .map(\n (u) =>\n `- ${u.project.name}: ${u.newCommits} new commits\\n README changed: ${u.readmeChanged}\\n Dependencies changed: ${u.depsChanged}`\n )\n .join(\"\\n\\n\")\n : \"None\";\n\n const removedProjectsText =\n diff.removedProjects.length > 0\n ? diff.removedProjects.map((p) => `- ${p.name}`).join(\"\\n\")\n : \"None\";\n\n template = template\n .replace(\n \"{{EXISTING_CONFIG_JSON}}\",\n JSON.stringify(existingConfig, null, 2)\n )\n .replace(\"{{NEW_PROJECTS}}\", newProjectsText)\n .replace(\"{{UPDATED_PROJECTS}}\", updatedProjectsText)\n .replace(\"{{REMOVED_PROJECTS}}\", removedProjectsText)\n .replace(\"{{PERSONAL_INFO_DIFF}}\", \"No changes\");\n\n return template;\n}\n","import { execa, type Options as ExecaOptions } from \"execa\";\n\nexport async function run(\n command: string,\n args: string[],\n options?: ExecaOptions\n) {\n return execa(command, args, {\n stdio: \"pipe\",\n ...options,\n });\n}\n\nexport async function commandExists(command: string): Promise<boolean> {\n try {\n await execa(\"which\", [command]);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function runWithOutput(\n command: string,\n args: string[],\n options?: ExecaOptions\n): Promise<string> {\n const result = await execa(command, args, {\n stdio: \"pipe\",\n ...options,\n });\n return result.stdout;\n}\n","import { commandExists } from \"../utils/exec.js\";\nimport type { EngineType } from \"../spec/schema.js\";\n\nexport interface DetectedEngine {\n type: EngineType;\n available: boolean;\n}\n\nexport async function detectEngines(): Promise<DetectedEngine[]> {\n const results: DetectedEngine[] = [];\n\n // Check for v0 API key\n if (process.env.V0_API_KEY) {\n results.push({ type: \"v0\", available: true });\n }\n\n // Check for Claude Code CLI\n if (await commandExists(\"claude\")) {\n results.push({ type: \"claude\", available: true });\n }\n\n // Check for Codex CLI\n if (await commandExists(\"codex\")) {\n results.push({ type: \"codex\", available: true });\n }\n\n return results;\n}\n\nexport function getAvailableEngineTypes(engines: DetectedEngine[]): EngineType[] {\n return engines.filter((e) => e.available).map((e) => e.type);\n}\n","import { execa } from \"execa\";\nimport { logger } from \"../../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function generateWithClaude(\n prompt: string,\n outputDir: string\n): Promise<void> {\n const spinner = ora(\"Generating site with Claude Code...\").start();\n\n try {\n // Use claude CLI with --print flag for non-interactive mode\n // and direct it to create files in the output directory\n const fullPrompt = `${prompt}\\n\\nCreate all files in the current working directory. Do not ask questions, just generate all files.`;\n\n await execa(\"claude\", [\"-p\", fullPrompt], {\n cwd: outputDir,\n stdio: \"pipe\",\n timeout: 300000, // 5 minute timeout\n });\n\n spinner.succeed(\"Site generated with Claude Code\");\n } catch (error) {\n spinner.fail(\"Claude Code generation failed\");\n throw error;\n }\n}\n","import { execa } from \"execa\";\nimport { logger } from \"../../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function generateWithCodex(\n prompt: string,\n outputDir: string\n): Promise<void> {\n const spinner = ora(\"Generating site with Codex...\").start();\n\n try {\n const fullPrompt = `${prompt}\\n\\nCreate all files in the current working directory. Do not ask questions, just generate all files.`;\n\n await execa(\"codex\", [\"--quiet\", \"--full-auto\", fullPrompt], {\n cwd: outputDir,\n stdio: \"pipe\",\n timeout: 300000,\n });\n\n spinner.succeed(\"Site generated with Codex\");\n } catch (error) {\n spinner.fail(\"Codex generation failed\");\n throw error;\n }\n}\n","import OpenAI from \"openai\";\nimport { writeFile, mkdir } from \"node:fs/promises\";\nimport { join, dirname } from \"node:path\";\nimport { logger } from \"../../utils/logger.js\";\nimport ora from \"ora\";\n\ninterface ExtractedFile {\n filename: string;\n content: string;\n}\n\nexport async function generateWithV0(\n prompt: string,\n outputDir: string,\n apiKey: string\n): Promise<void> {\n const spinner = ora(\"Generating site with v0...\").start();\n\n const client = new OpenAI({\n apiKey,\n baseURL: \"https://api.v0.dev/v1\",\n });\n\n try {\n const response = await client.chat.completions.create({\n model: \"v0-1.0-md\",\n messages: [\n {\n role: \"system\",\n content:\n \"Generate a complete Next.js 15 portfolio website using TypeScript, Tailwind CSS, and shadcn/ui. \" +\n \"Return all files with their paths clearly marked. Use ```tsx filename.tsx or ```ts filename.ts \" +\n \"code blocks with the filename on the same line as the opening backticks. \" +\n \"No emoji in any output.\",\n },\n {\n role: \"user\",\n content: prompt,\n },\n ],\n });\n\n const content = response.choices[0]?.message?.content;\n if (!content) {\n throw new Error(\"v0 returned empty response\");\n }\n\n spinner.text = \"Parsing v0 output...\";\n\n const files = extractFiles(content);\n if (files.length === 0) {\n throw new Error(\"No files extracted from v0 response\");\n }\n\n spinner.text = `Writing ${files.length} files...`;\n\n for (const file of files) {\n const filePath = join(outputDir, file.filename);\n await mkdir(dirname(filePath), { recursive: true });\n await writeFile(filePath, file.content, \"utf-8\");\n }\n\n // Ensure package.json exists with required deps\n const hasPkgJson = files.some((f) => f.filename === \"package.json\");\n if (!hasPkgJson) {\n await writeFile(\n join(outputDir, \"package.json\"),\n JSON.stringify(\n {\n name: \"shipfolio-site\",\n version: \"1.0.0\",\n private: true,\n scripts: {\n dev: \"next dev\",\n build: \"next build\",\n start: \"next start\",\n },\n dependencies: {\n next: \"^15.0.0\",\n react: \"^19.0.0\",\n \"react-dom\": \"^19.0.0\",\n \"class-variance-authority\": \"^0.7.0\",\n clsx: \"^2.1.0\",\n \"tailwind-merge\": \"^2.6.0\",\n \"lucide-react\": \"^0.460.0\",\n },\n devDependencies: {\n typescript: \"^5.7.0\",\n \"@types/node\": \"^22.0.0\",\n \"@types/react\": \"^19.0.0\",\n \"@types/react-dom\": \"^19.0.0\",\n tailwindcss: \"^4.0.0\",\n \"@tailwindcss/postcss\": \"^4.0.0\",\n },\n },\n null,\n 2\n ),\n \"utf-8\"\n );\n }\n\n spinner.succeed(`Site generated with v0 (${files.length} files)`);\n } catch (error) {\n spinner.fail(\"v0 generation failed\");\n throw error;\n }\n}\n\nfunction extractFiles(content: string): ExtractedFile[] {\n const files: ExtractedFile[] = [];\n\n // Match code blocks with filename: ```tsx src/app/page.tsx or ```tsx filename=\"src/app/page.tsx\"\n const patterns = [\n // ```tsx src/app/page.tsx\n /```(?:tsx?|jsx?|css|json|mjs|cjs)\\s+([^\\n`]+)\\n([\\s\\S]*?)```/g,\n // ```tsx filename=\"src/app/page.tsx\"\n /```(?:tsx?|jsx?|css|json|mjs|cjs)\\s+filename=\"([^\"]+)\"\\n([\\s\\S]*?)```/g,\n // ```tsx {filename: \"src/app/page.tsx\"}\n /```(?:tsx?|jsx?|css|json|mjs|cjs).*?filename:\\s*\"([^\"]+)\".*?\\n([\\s\\S]*?)```/g,\n ];\n\n for (const pattern of patterns) {\n let match;\n while ((match = pattern.exec(content)) !== null) {\n const filename = match[1].trim();\n const fileContent = match[2].trim();\n\n // Skip if filename looks like a description rather than a path\n if (\n filename.includes(\" \") &&\n !filename.includes(\"/\") &&\n !filename.includes(\".\")\n ) {\n continue;\n }\n\n // Clean up filename\n const cleanFilename = filename\n .replace(/^[\"']|[\"']$/g, \"\")\n .replace(/^\\.\\//g, \"\");\n\n if (cleanFilename && fileContent) {\n files.push({ filename: cleanFilename, content: fileContent });\n }\n }\n }\n\n return files;\n}\n","import { fileExists, join } from \"../utils/fs.js\";\n\nexport interface ValidationResult {\n valid: boolean;\n errors: string[];\n}\n\nexport async function validateGeneratedSite(\n siteDir: string\n): Promise<ValidationResult> {\n const errors: string[] = [];\n\n const requiredFiles = [\n \"package.json\",\n \"next.config.ts\",\n \"src/app/layout.tsx\",\n \"src/app/page.tsx\",\n ];\n\n // Also check common alternatives\n const alternativeChecks: [string, string[]][] = [\n [\"next.config.ts\", [\"next.config.ts\", \"next.config.js\", \"next.config.mjs\"]],\n ];\n\n for (const file of requiredFiles) {\n const alternatives = alternativeChecks.find(([key]) => key === file);\n if (alternatives) {\n const anyExists = await Promise.any(\n alternatives[1].map(async (alt) => {\n if (await fileExists(join(siteDir, alt))) return true;\n throw new Error(\"not found\");\n })\n ).catch(() => false);\n if (!anyExists) {\n errors.push(`Missing: ${file} (or any alternative)`);\n }\n } else {\n if (!(await fileExists(join(siteDir, file)))) {\n errors.push(`Missing: ${file}`);\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n\nexport async function validateBuildOutput(\n siteDir: string\n): Promise<ValidationResult> {\n const errors: string[] = [];\n\n const outDir = join(siteDir, \"out\");\n if (!(await fileExists(outDir))) {\n errors.push(\"Build output directory 'out/' not found\");\n return { valid: false, errors };\n }\n\n const indexHtml = join(outDir, \"index.html\");\n if (!(await fileExists(indexHtml))) {\n errors.push(\"Missing: out/index.html\");\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n","import { generateWithClaude } from \"./engines/claude.js\";\nimport { generateWithCodex } from \"./engines/codex.js\";\nimport { generateWithV0 } from \"./engines/v0.js\";\nimport {\n validateGeneratedSite,\n validateBuildOutput,\n} from \"./validator.js\";\nimport { ensureDir } from \"../utils/fs.js\";\nimport { run } from \"../utils/exec.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { EngineType } from \"../spec/schema.js\";\nimport ora from \"ora\";\n\nexport async function generateSite(\n engine: EngineType,\n prompt: string,\n outputDir: string\n): Promise<void> {\n await ensureDir(outputDir);\n\n switch (engine) {\n case \"claude\":\n await generateWithClaude(prompt, outputDir);\n break;\n case \"codex\":\n await generateWithCodex(prompt, outputDir);\n break;\n case \"v0\": {\n const apiKey = process.env.V0_API_KEY;\n if (!apiKey) {\n throw new Error(\n \"V0_API_KEY environment variable is required for v0 engine\"\n );\n }\n await generateWithV0(prompt, outputDir, apiKey);\n break;\n }\n }\n\n // Validate generated output\n const validation = await validateGeneratedSite(outputDir);\n if (!validation.valid) {\n logger.warn(\"Generated site has issues:\");\n for (const err of validation.errors) {\n logger.warn(` ${err}`);\n }\n // Could retry here, but for now just warn\n }\n}\n\nexport async function buildSite(siteDir: string): Promise<boolean> {\n const spinner = ora(\"Installing dependencies...\").start();\n\n try {\n await run(\"npm\", [\"install\"], { cwd: siteDir });\n spinner.text = \"Building site...\";\n await run(\"npm\", [\"run\", \"build\"], { cwd: siteDir });\n spinner.succeed(\"Site built successfully\");\n } catch (error: any) {\n spinner.fail(\"Build failed\");\n logger.error(error.stderr || error.message || String(error));\n return false;\n }\n\n // Validate build output\n const validation = await validateBuildOutput(siteDir);\n if (!validation.valid) {\n logger.error(\"Build output validation failed:\");\n for (const err of validation.errors) {\n logger.error(` ${err}`);\n }\n return false;\n }\n\n return true;\n}\n\nexport async function retryBuild(\n engine: EngineType,\n siteDir: string,\n buildError: string,\n originalPrompt: string\n): Promise<boolean> {\n logger.info(\"Retrying: feeding build error back to AI...\");\n\n const fixPrompt = `The site generation produced build errors. Fix the following errors without changing the overall design or structure:\\n\\n${buildError}\\n\\nOriginal prompt for context:\\n${originalPrompt.slice(0, 2000)}`;\n\n try {\n await generateSite(engine, fixPrompt, siteDir);\n return await buildSite(siteDir);\n } catch {\n return false;\n }\n}\n","import { run, commandExists, runWithOutput } from \"../utils/exec.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { DeployPlatform } from \"../spec/schema.js\";\n\nexport async function checkAuth(\n platform: DeployPlatform\n): Promise<boolean> {\n if (platform === \"local\") return true;\n\n try {\n if (platform === \"cloudflare\") {\n await runWithOutput(\"npx\", [\"wrangler\", \"whoami\"]);\n return true;\n }\n if (platform === \"vercel\") {\n await runWithOutput(\"npx\", [\"vercel\", \"whoami\"]);\n return true;\n }\n } catch {\n return false;\n }\n return false;\n}\n\nexport async function login(platform: DeployPlatform): Promise<void> {\n if (platform === \"cloudflare\") {\n logger.info(\"Opening Cloudflare login in browser...\");\n await run(\"npx\", [\"wrangler\", \"login\"], { stdio: \"inherit\" });\n } else if (platform === \"vercel\") {\n logger.info(\"Opening Vercel login in browser...\");\n await run(\"npx\", [\"vercel\", \"login\"], { stdio: \"inherit\" });\n }\n}\n\nexport async function ensureAuth(platform: DeployPlatform): Promise<void> {\n if (platform === \"local\") return;\n\n const isAuthed = await checkAuth(platform);\n if (!isAuthed) {\n await login(platform);\n // Verify login succeeded\n const nowAuthed = await checkAuth(platform);\n if (!nowAuthed) {\n throw new Error(`Authentication failed for ${platform}`);\n }\n }\n}\n","import { runWithOutput } from \"../utils/exec.js\";\nimport { logger } from \"../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function deployToCloudflare(\n distDir: string,\n projectName: string\n): Promise<string> {\n const spinner = ora(\"Deploying to Cloudflare Pages...\").start();\n\n try {\n const output = await runWithOutput(\"npx\", [\n \"wrangler\",\n \"pages\",\n \"deploy\",\n distDir,\n `--project-name=${projectName}`,\n ]);\n\n // Extract URL from output\n const urlMatch = output.match(\n /https:\\/\\/[^\\s]+\\.pages\\.dev/\n );\n const url = urlMatch?.[0] || `https://${projectName}.pages.dev`;\n\n spinner.succeed(`Deployed to Cloudflare Pages`);\n logger.info(`URL: ${url}`);\n\n return url;\n } catch (error: any) {\n spinner.fail(\"Cloudflare Pages deployment failed\");\n throw error;\n }\n}\n","import { runWithOutput } from \"../utils/exec.js\";\nimport { logger } from \"../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function deployToVercel(\n distDir: string\n): Promise<string> {\n const spinner = ora(\"Deploying to Vercel...\").start();\n\n try {\n const output = await runWithOutput(\"npx\", [\n \"vercel\",\n \"deploy\",\n distDir,\n \"--yes\",\n \"--prod\",\n ]);\n\n // Extract URL from output\n const urlMatch = output.match(\n /https:\\/\\/[^\\s]+\\.vercel\\.app/\n );\n const url = urlMatch?.[0] || output.trim().split(\"\\n\").pop() || \"\";\n\n spinner.succeed(\"Deployed to Vercel\");\n logger.info(`URL: ${url}`);\n\n return url;\n } catch (error: any) {\n spinner.fail(\"Vercel deployment failed\");\n throw error;\n }\n}\n","import { run, runWithOutput, commandExists } from \"../utils/exec.js\";\nimport { fileExists, join } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\nimport * as p from \"@clack/prompts\";\n\nexport async function setupGitHubAutoDeploy(\n siteDir: string,\n projectName: string\n): Promise<void> {\n const hasGh = await commandExists(\"gh\");\n if (!hasGh) {\n logger.info(\n \"GitHub CLI (gh) not found. Install it to enable auto-deploy setup.\"\n );\n return;\n }\n\n const shouldSetup = (await p.confirm({\n message: \"Set up GitHub auto-deploy? (push = redeploy)\",\n initialValue: false,\n })) as boolean;\n\n if (p.isCancel(shouldSetup) || !shouldSetup) return;\n\n const visibility = (await p.select({\n message: \"Repository visibility:\",\n options: [\n { value: \"private\", label: \"Private\" },\n { value: \"public\", label: \"Public\" },\n ],\n })) as string;\n\n if (p.isCancel(visibility)) return;\n\n try {\n // Init git if not already\n const gitDir = join(siteDir, \".git\");\n if (!(await fileExists(gitDir))) {\n await run(\"git\", [\"init\"], { cwd: siteDir });\n }\n\n // Create GitHub repo\n await run(\n \"gh\",\n [\n \"repo\",\n \"create\",\n projectName,\n `--${visibility}`,\n \"--source\",\n siteDir,\n \"--push\",\n ],\n { cwd: siteDir, stdio: \"inherit\" }\n );\n\n logger.success(`GitHub repository created: ${projectName}`);\n logger.info(\n \"Connect this repo in your Cloudflare Pages or Vercel dashboard for auto-deploy.\"\n );\n } catch (error: any) {\n logger.error(`GitHub setup failed: ${error.message}`);\n }\n}\n","import { ensureAuth } from \"./auth.js\";\nimport { deployToCloudflare } from \"./cloudflare.js\";\nimport { deployToVercel } from \"./vercel.js\";\nimport { setupGitHubAutoDeploy } from \"./github.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { DeployPlatform } from \"../spec/schema.js\";\nimport { join } from \"node:path\";\n\nexport async function deploy(\n siteDir: string,\n platform: DeployPlatform,\n projectName: string\n): Promise<string | null> {\n if (platform === \"local\") {\n logger.info(`Site built at ${join(siteDir, \"out/\")}`);\n logger.info(\"Run `npx serve ./out` in the site directory to preview.\");\n return null;\n }\n\n await ensureAuth(platform);\n\n const distDir = join(siteDir, \"out\");\n let url: string;\n\n if (platform === \"cloudflare\") {\n url = await deployToCloudflare(distDir, projectName);\n } else {\n url = await deployToVercel(distDir);\n }\n\n // Offer GitHub auto-deploy setup\n await setupGitHubAutoDeploy(siteDir, projectName);\n\n return url;\n}\n","import { createServer, type Server } from \"node:http\";\nimport { join } from \"node:path\";\nimport { logger } from \"../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function exportPdf(\n siteDir: string,\n outputPath?: string\n): Promise<string> {\n const distDir = join(siteDir, \"out\");\n const pdfPath = outputPath || join(distDir, \"shipfolio.pdf\");\n\n const spinner = ora(\"Exporting PDF...\").start();\n\n // Start a local server for the built site\n const server = await startStaticServer(distDir);\n const port = (server.address() as any)?.port || 3456;\n\n try {\n // Dynamic import to avoid requiring playwright at install time\n const { chromium } = await import(\"playwright\");\n\n const browser = await chromium.launch();\n const page = await browser.newPage();\n\n await page.goto(`http://localhost:${port}`, {\n waitUntil: \"networkidle\",\n });\n\n // Wait a moment for any CSS transitions to complete\n await page.waitForTimeout(1000);\n\n await page.pdf({\n path: pdfPath,\n format: \"A4\",\n printBackground: true,\n margin: {\n top: \"1cm\",\n right: \"1cm\",\n bottom: \"1cm\",\n left: \"1cm\",\n },\n });\n\n await browser.close();\n spinner.succeed(`PDF exported: ${pdfPath}`);\n return pdfPath;\n } catch (error: any) {\n spinner.fail(\"PDF export failed\");\n if (error.message?.includes(\"browserType.launch\")) {\n logger.error(\n \"Playwright browsers not installed. Run: npx playwright install chromium\"\n );\n } else {\n logger.error(error.message || String(error));\n }\n throw error;\n } finally {\n server.close();\n }\n}\n\nfunction startStaticServer(dir: string): Promise<Server> {\n return new Promise(async (resolve, reject) => {\n const handler = await import(\"serve-handler\");\n\n const server = createServer((req, res) => {\n return handler.default(req, res, {\n public: dir,\n cleanUrls: true,\n });\n });\n\n server.listen(0, () => {\n resolve(server);\n });\n\n server.on(\"error\", reject);\n });\n}\n\nexport async function startPreviewServer(\n siteDir: string,\n port: number = 3000\n): Promise<Server> {\n const distDir = join(siteDir, \"out\");\n const handler = await import(\"serve-handler\");\n\n const server = createServer((req, res) => {\n return handler.default(req, res, {\n public: distDir,\n cleanUrls: true,\n });\n });\n\n return new Promise((resolve, reject) => {\n server.listen(port, () => {\n logger.info(`Preview: http://localhost:${port}`);\n resolve(server);\n });\n server.on(\"error\", reject);\n });\n}\n","import { resolve } from \"node:path\";\nimport { scanProjects } from \"../scanner/index.js\";\nimport { runInterview } from \"../interviewer/index.js\";\nimport { buildSpec } from \"../spec/builder.js\";\nimport { buildFreshPrompt } from \"../orchestrator/prompt-builder.js\";\nimport { detectEngines, getAvailableEngineTypes } from \"../orchestrator/detect.js\";\nimport { generateSite, buildSite } from \"../orchestrator/index.js\";\nimport { deploy } from \"../deployer/index.js\";\nimport { exportPdf } from \"../pdf/index.js\";\nimport { startPreviewServer } from \"../pdf/index.js\";\nimport { writeJson, ensureDir } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\nimport { join } from \"node:path\";\nimport * as p from \"@clack/prompts\";\n\ninterface InitOptions {\n scan?: string[];\n engine?: string;\n deploy?: string;\n style?: string;\n accent?: string;\n auto?: boolean;\n output?: string;\n noPdf?: boolean;\n noPreview?: boolean;\n verbose?: boolean;\n}\n\nexport async function initCommand(options: InitOptions): Promise<void> {\n logger.header(\"shipfolio v1.0.0\");\n\n // Step 1: Detect AI engines\n logger.info(\"Detecting AI engines...\");\n const engines = await detectEngines();\n const availableTypes = getAvailableEngineTypes(engines);\n\n if (availableTypes.length === 0) {\n logger.error(\"No AI engine found.\");\n logger.plain(\"\");\n logger.plain(\" shipfolio requires one of the following:\");\n logger.plain(\" - Claude Code: npm install -g @anthropic-ai/claude-code\");\n logger.plain(\" - Codex: npm install -g @openai/codex\");\n logger.plain(\" - v0: Set V0_API_KEY environment variable\");\n logger.plain(\"\");\n process.exit(1);\n }\n\n logger.info(\n `Available engines: ${availableTypes.join(\", \")}`\n );\n\n // Step 2: Scan projects\n const scanDirs = options.scan?.map((d) => resolve(d)) || [\n resolve(process.cwd()),\n ];\n const scannedProjects = await scanProjects(scanDirs);\n\n if (scannedProjects.length === 0) {\n logger.error(\"No projects found. Specify a different directory with --scan.\");\n process.exit(1);\n }\n\n // Display scanned projects\n logger.header(`Found ${scannedProjects.length} projects:`);\n const tableRows = scannedProjects.map((proj) => [\n proj.name,\n proj.techStack.slice(0, 3).join(\", \"),\n proj.firstCommitDate?.slice(0, 10) || \"?\",\n `${proj.totalCommits} commits`,\n ]);\n logger.table(tableRows);\n logger.blank();\n\n // Step 3: Interactive interview\n const interviewResult = await runInterview(scannedProjects, availableTypes);\n\n // Step 4: Build spec\n const spec = buildSpec(interviewResult);\n\n // Step 5: Generate prompt\n const prompt = await buildFreshPrompt(spec);\n\n // Step 6: Generate site\n const outputDir = resolve(options.output || \"./shipfolio-site\");\n await ensureDir(outputDir);\n\n await generateSite(spec.engine, prompt, outputDir);\n\n // Step 7: Build\n let buildSuccess = await buildSite(outputDir);\n if (!buildSuccess) {\n logger.info(\"Attempting retry...\");\n buildSuccess = await buildSite(outputDir);\n if (!buildSuccess) {\n logger.error(\"Build failed after retry. Check the output directory for details.\");\n process.exit(1);\n }\n }\n\n // Step 8: Preview\n if (!options.noPreview) {\n const server = await startPreviewServer(outputDir);\n logger.blank();\n\n const proceed = (await p.confirm({\n message: \"Deploy now?\",\n initialValue: true,\n })) as boolean;\n\n server.close();\n\n if (p.isCancel(proceed) || !proceed) {\n if (spec.deploy.platform === \"local\") {\n // Already local, just exit\n } else {\n logger.info(\"Skipping deploy. Run `npx shipfolio deploy` later.\");\n }\n }\n }\n\n // Step 9: PDF export\n if (!options.noPdf) {\n try {\n await exportPdf(outputDir);\n } catch {\n logger.warn(\"PDF export skipped due to error.\");\n }\n }\n\n // Step 10: Deploy\n if (spec.deploy.platform !== \"local\") {\n const url = await deploy(\n outputDir,\n spec.deploy.platform,\n spec.deploy.projectName\n );\n if (url) {\n spec.deploy.url = url;\n }\n }\n\n // Save config for future updates\n await writeJson(join(outputDir, \"shipfolio.config.json\"), {\n ...spec,\n sitePath: outputDir,\n });\n\n // Summary\n logger.header(\"Done.\");\n if (spec.deploy.url) {\n logger.info(`Site: ${spec.deploy.url}`);\n }\n logger.info(`Local: ${outputDir}`);\n logger.info(\n `Update: npx shipfolio update --site ${outputDir}`\n );\n}\n","import { Command } from \"commander\";\nimport { initCommand } from \"./commands/init.js\";\nimport { updateCommand } from \"./commands/update.js\";\nimport { specCommand } from \"./commands/spec.js\";\nimport { deployCommand } from \"./commands/deploy.js\";\nimport { pdfCommand } from \"./commands/pdf.js\";\nimport { previewCommand } from \"./commands/preview.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"shipfolio\")\n .description(\n \"Generate and deploy your personal portfolio site from local projects using AI\"\n )\n .version(\"1.0.0\");\n\n// Default command: init (fresh build)\nprogram\n .command(\"init\", { isDefault: true })\n .description(\"Generate a new portfolio site\")\n .option(\"-s, --scan <dirs...>\", \"Directories to scan for projects\")\n .option(\"-e, --engine <engine>\", \"AI engine: claude | codex | v0\")\n .option(\"-d, --deploy <platform>\", \"Deploy target: cloudflare | vercel | local\")\n .option(\"--style <theme>\", \"Theme: dark-minimal | light-clean | monochrome\")\n .option(\"--accent <hex>\", \"Accent color (hex)\")\n .option(\"--auto\", \"Skip prompts, use defaults\")\n .option(\"-o, --output <dir>\", \"Output directory\", \"./shipfolio-site\")\n .option(\"--no-pdf\", \"Skip PDF export\")\n .option(\"--no-preview\", \"Skip local preview\")\n .option(\"-v, --verbose\", \"Verbose output\")\n .action(initCommand);\n\n// Update existing site\nprogram\n .command(\"update\")\n .description(\"Update an existing portfolio site\")\n .requiredOption(\"--site <path>\", \"Path to existing site directory\")\n .option(\"-s, --scan <dirs...>\", \"Directories to scan for projects\")\n .option(\"--no-pdf\", \"Skip PDF export\")\n .option(\"--no-preview\", \"Skip preview\")\n .option(\"--no-deploy\", \"Skip deployment\")\n .action(updateCommand);\n\n// Generate spec only (for use inside AI tools)\nprogram\n .command(\"spec\")\n .description(\"Generate spec and prompt files only\")\n .option(\"-s, --scan <dirs...>\", \"Directories to scan for projects\")\n .option(\"-o, --output <dir>\", \"Output directory for spec files\", \".\")\n .action(specCommand);\n\n// Deploy existing site\nprogram\n .command(\"deploy\")\n .description(\"Deploy an existing built site\")\n .requiredOption(\"--site <path>\", \"Path to site directory\")\n .option(\"-p, --platform <platform>\", \"Deploy platform: cloudflare | vercel\")\n .action(deployCommand);\n\n// Export PDF\nprogram\n .command(\"pdf\")\n .description(\"Export site to PDF\")\n .requiredOption(\"--site <path>\", \"Path to site directory\")\n .option(\"-o, --output <path>\", \"PDF output path\")\n .action(pdfCommand);\n\n// Preview\nprogram\n .command(\"preview\")\n .description(\"Start local preview server\")\n .requiredOption(\"--site <path>\", \"Path to site directory\")\n .option(\"--port <port>\", \"Port number\", \"3000\")\n .action((opts) => previewCommand({ ...opts, port: parseInt(opts.port) }));\n\nprogram.parse();\n","import { resolve } from \"node:path\";\nimport { scanProjects } from \"../scanner/index.js\";\nimport { computeDiff } from \"../spec/diff.js\";\nimport { buildUpdatePrompt } from \"../orchestrator/prompt-builder.js\";\nimport { detectEngines, getAvailableEngineTypes } from \"../orchestrator/detect.js\";\nimport { generateSite, buildSite } from \"../orchestrator/index.js\";\nimport { deploy } from \"../deployer/index.js\";\nimport { exportPdf, startPreviewServer } from \"../pdf/index.js\";\nimport { readJson, writeJson, fileExists, join } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { ShipfolioConfig, ProjectEntry } from \"../spec/schema.js\";\nimport * as p from \"@clack/prompts\";\n\ninterface UpdateOptions {\n site: string;\n scan?: string[];\n noPdf?: boolean;\n noPreview?: boolean;\n noDeploy?: boolean;\n}\n\nexport async function updateCommand(options: UpdateOptions): Promise<void> {\n logger.header(\"shipfolio update\");\n\n const siteDir = resolve(options.site);\n const configPath = join(siteDir, \"shipfolio.config.json\");\n\n // Read existing config\n if (!(await fileExists(configPath))) {\n logger.error(\n \"shipfolio.config.json not found. This directory was not generated by shipfolio.\"\n );\n const fresh = (await p.confirm({\n message: \"Proceed with fresh build instead?\",\n initialValue: true,\n })) as boolean;\n\n if (p.isCancel(fresh) || !fresh) {\n process.exit(0);\n }\n\n // Redirect to init\n const { initCommand } = await import(\"./init.js\");\n await initCommand({ output: siteDir });\n return;\n }\n\n const config = await readJson<ShipfolioConfig>(configPath);\n logger.info(\n `Site: ${config.deploy.projectName || \"local\"} (generated ${config.generatedAt.slice(0, 10)})`\n );\n logger.info(`Theme: ${config.style.theme}`);\n logger.info(`Projects: ${config.projects.length}`);\n\n // Detect engines\n const engines = await detectEngines();\n const availableTypes = getAvailableEngineTypes(engines);\n if (availableTypes.length === 0) {\n logger.error(\"No AI engine found. See `npx shipfolio` for install instructions.\");\n process.exit(1);\n }\n\n // Scan for changes\n const scanDirs = options.scan?.map((d) => resolve(d)) ||\n [...new Set(config.projects.map((p) => {\n const parts = p.localPath.split(\"/\");\n parts.pop();\n return parts.join(\"/\");\n }))];\n\n const scannedProjects = await scanProjects(scanDirs);\n const diff = computeDiff(config, scannedProjects);\n\n // Display changes\n logger.header(\"Changes detected:\");\n\n if (diff.newProjects.length > 0) {\n logger.plain(\" New:\");\n for (const proj of diff.newProjects) {\n logger.plain(` + ${proj.name} ${proj.techStack.slice(0, 3).join(\", \")}`);\n }\n }\n\n if (diff.updatedProjects.length > 0) {\n logger.plain(\" Updated:\");\n for (const upd of diff.updatedProjects) {\n logger.plain(\n ` ~ ${upd.project.name} ${upd.newCommits} new commits`\n );\n }\n }\n\n if (diff.removedProjects.length > 0) {\n logger.plain(\" Removed:\");\n for (const proj of diff.removedProjects) {\n logger.plain(` - ${proj.name} (directory gone)`);\n }\n }\n\n if (\n diff.newProjects.length === 0 &&\n diff.updatedProjects.length === 0 &&\n diff.removedProjects.length === 0\n ) {\n logger.info(\"No changes detected.\");\n return;\n }\n\n // Confirm changes\n const proceed = (await p.confirm({\n message: \"Apply these changes?\",\n initialValue: true,\n })) as boolean;\n\n if (p.isCancel(proceed) || !proceed) {\n process.exit(0);\n }\n\n // Build update prompt\n const engine = availableTypes.includes(config.engine)\n ? config.engine\n : availableTypes[0];\n\n const prompt = await buildUpdatePrompt(config, diff);\n\n // Generate updates\n await generateSite(engine, prompt, siteDir);\n\n // Build\n const buildSuccess = await buildSite(siteDir);\n if (!buildSuccess) {\n logger.error(\"Build failed. Check the site directory.\");\n process.exit(1);\n }\n\n // Preview\n if (!options.noPreview) {\n const server = await startPreviewServer(siteDir);\n const ok = (await p.confirm({\n message: \"Looks good?\",\n initialValue: true,\n })) as boolean;\n server.close();\n if (p.isCancel(ok) || !ok) {\n logger.info(\"Update cancelled at preview.\");\n return;\n }\n }\n\n // PDF\n if (!options.noPdf) {\n try {\n await exportPdf(siteDir);\n } catch {\n logger.warn(\"PDF export skipped.\");\n }\n }\n\n // Deploy\n if (!options.noDeploy && config.deploy.platform !== \"local\") {\n await deploy(siteDir, config.deploy.platform, config.deploy.projectName);\n }\n\n // Update config\n const updatedConfig: ShipfolioConfig = {\n ...config,\n generatedAt: new Date().toISOString(),\n projects: [\n ...diff.unchangedProjects,\n ...diff.updatedProjects.map((u) => {\n const existing = config.projects.find(\n (p) => p.localPath === u.project.localPath\n );\n return {\n ...u.project,\n included: true,\n overrideDescription: existing?.overrideDescription || null,\n showSourceLink: existing?.showSourceLink ?? !!u.project.remoteUrl,\n role: existing?.role || \"solo\",\n metrics: existing?.metrics || {},\n } as ProjectEntry;\n }),\n ...diff.newProjects.map(\n (proj) =>\n ({\n ...proj,\n included: true,\n overrideDescription: null,\n showSourceLink: !!proj.remoteUrl,\n role: \"solo\" as const,\n metrics: {},\n }) as ProjectEntry\n ),\n ],\n };\n\n await writeJson(join(siteDir, \"shipfolio.config.json\"), updatedConfig);\n logger.success(\"Update complete.\");\n}\n","import type {\n ProjectMeta,\n ProjectEntry,\n ShipfolioConfig,\n SiteDiff,\n ProjectUpdate,\n} from \"./schema.js\";\n\nexport function computeDiff(\n oldConfig: ShipfolioConfig,\n newScan: ProjectMeta[]\n): SiteDiff {\n const oldProjectMap = new Map(\n oldConfig.projects.map((p) => [p.localPath, p])\n );\n const newProjectMap = new Map(newScan.map((p) => [p.localPath, p]));\n\n const newProjects: ProjectMeta[] = [];\n const updatedProjects: ProjectUpdate[] = [];\n const removedProjects: ProjectEntry[] = [];\n const unchangedProjects: ProjectEntry[] = [];\n\n // Check new and updated\n for (const [path, meta] of newProjectMap) {\n const oldProject = oldProjectMap.get(path);\n if (!oldProject) {\n newProjects.push(meta);\n } else if (meta.lastScannedCommit !== oldProject.lastScannedCommit) {\n const newCommits = meta.totalCommits - oldProject.totalCommits;\n updatedProjects.push({\n project: meta,\n newCommits: Math.max(newCommits, 0),\n readmeChanged: meta.readmeContent !== oldProject.readmeContent,\n depsChanged:\n JSON.stringify(meta.techStack) !==\n JSON.stringify(oldProject.techStack),\n });\n } else {\n unchangedProjects.push(oldProject);\n }\n }\n\n // Check removed\n for (const [path, project] of oldProjectMap) {\n if (!newProjectMap.has(path)) {\n removedProjects.push(project);\n }\n }\n\n return {\n newProjects,\n updatedProjects,\n removedProjects,\n unchangedProjects,\n };\n}\n","import { resolve } from \"node:path\";\nimport { scanProjects } from \"../scanner/index.js\";\nimport { runInterview } from \"../interviewer/index.js\";\nimport { buildSpec } from \"../spec/builder.js\";\nimport { buildFreshPrompt } from \"../orchestrator/prompt-builder.js\";\nimport { detectEngines, getAvailableEngineTypes } from \"../orchestrator/detect.js\";\nimport { writeJson, writeText } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\n\ninterface SpecOptions {\n scan?: string[];\n output?: string;\n}\n\nexport async function specCommand(options: SpecOptions): Promise<void> {\n logger.header(\"shipfolio spec\");\n\n // Detect engines (needed for interview but not for execution)\n const engines = await detectEngines();\n const availableTypes = getAvailableEngineTypes(engines);\n\n // Even if no engine is available, we can still generate spec\n // (user will use it inside their own AI session)\n const engineTypes =\n availableTypes.length > 0 ? availableTypes : ([\"claude\"] as const);\n\n // Scan\n const scanDirs = options.scan?.map((d) => resolve(d)) || [\n resolve(process.cwd()),\n ];\n const scannedProjects = await scanProjects(scanDirs);\n\n if (scannedProjects.length === 0) {\n logger.error(\"No projects found.\");\n process.exit(1);\n }\n\n logger.info(`Found ${scannedProjects.length} projects`);\n\n // Interview\n const interviewResult = await runInterview(\n scannedProjects,\n [...engineTypes]\n );\n\n // Build spec\n const spec = buildSpec(interviewResult);\n\n // Generate prompt\n const prompt = await buildFreshPrompt(spec);\n\n // Save outputs\n const outputDir = options.output || \".\";\n const specPath = resolve(outputDir, \"shipfolio-spec.json\");\n const promptPath = resolve(outputDir, \"shipfolio-prompt.md\");\n\n await writeJson(specPath, spec);\n await writeText(promptPath, prompt);\n\n logger.success(`Spec saved: ${specPath}`);\n logger.success(`Prompt saved: ${promptPath}`);\n logger.blank();\n logger.info(\n \"Use these files inside your Claude Code or Codex session to generate the site.\"\n );\n}\n","import { resolve } from \"node:path\";\nimport { deploy as deployFn } from \"../deployer/index.js\";\nimport { readJson, fileExists, join } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\nimport type { ShipfolioConfig, DeployPlatform } from \"../spec/schema.js\";\nimport * as p from \"@clack/prompts\";\n\ninterface DeployOptions {\n site: string;\n platform?: string;\n}\n\nexport async function deployCommand(options: DeployOptions): Promise<void> {\n const siteDir = resolve(options.site);\n const configPath = join(siteDir, \"shipfolio.config.json\");\n\n let platform: DeployPlatform;\n let projectName: string;\n\n if (await fileExists(configPath)) {\n const config = await readJson<ShipfolioConfig>(configPath);\n platform =\n (options.platform as DeployPlatform) || config.deploy.platform;\n projectName = config.deploy.projectName;\n } else {\n platform = (options.platform as DeployPlatform) || \"cloudflare\";\n projectName = (await p.text({\n message: \"Project name:\",\n validate: (v) =>\n /^[a-z0-9-]+$/.test(v)\n ? undefined\n : \"Lowercase letters, numbers, and hyphens only\",\n })) as string;\n\n if (p.isCancel(projectName)) process.exit(0);\n }\n\n if (platform === \"local\") {\n logger.info(\"Deploy platform is set to local. Nothing to deploy.\");\n return;\n }\n\n const outDir = join(siteDir, \"out\");\n if (!(await fileExists(outDir))) {\n logger.error(\"Build output not found. Run `npm run build` in the site directory first.\");\n process.exit(1);\n }\n\n await deployFn(siteDir, platform, projectName);\n}\n","import { resolve } from \"node:path\";\nimport { exportPdf } from \"../pdf/index.js\";\nimport { fileExists, join } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\n\ninterface PdfOptions {\n site: string;\n output?: string;\n}\n\nexport async function pdfCommand(options: PdfOptions): Promise<void> {\n const siteDir = resolve(options.site);\n const outDir = join(siteDir, \"out\");\n\n if (!(await fileExists(outDir))) {\n logger.error(\n \"Build output not found. Run `npm run build` in the site directory first.\"\n );\n process.exit(1);\n }\n\n await exportPdf(siteDir, options.output);\n}\n","import { resolve } from \"node:path\";\nimport { startPreviewServer } from \"../pdf/index.js\";\nimport { fileExists, join } from \"../utils/fs.js\";\nimport { logger } from \"../utils/logger.js\";\n\ninterface PreviewOptions {\n site: string;\n port?: number;\n}\n\nexport async function previewCommand(options: PreviewOptions): Promise<void> {\n const siteDir = resolve(options.site);\n const outDir = join(siteDir, \"out\");\n\n if (!(await fileExists(outDir))) {\n logger.error(\n \"Build output not found. Run `npm run build` in the site directory first.\"\n );\n process.exit(1);\n }\n\n const port = options.port || 3000;\n await startPreviewServer(siteDir, port);\n logger.info(\"Press Ctrl+C to stop.\");\n\n // Keep process alive\n await new Promise(() => {});\n}\n"],"mappings":";;;;;;;;;;;;AACA,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAF9B;AAAA;AAAA;AAAA;AAAA;;;ACAA,OAAO,eAAe;AAYtB,eAAsB,WAAW,aAAuC;AACtE,QAAM,MAAM,UAAU,WAAW;AACjC,QAAM,QAAiB;AAAA,IACrB,QAAQ;AAAA,IACR,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,WAAW;AAAA,IACX,gBAAgB;AAAA,EAClB;AAEA,MAAI;AACF,UAAM,SAAS,MAAM,IAAI,YAAY;AACrC,QAAI,CAAC,OAAQ,QAAO;AAAA,EACtB,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,MAAM,MAAM,IAAI,IAAI,EAAE,UAAU,EAAE,CAAC;AAGzC,QAAI,kBAAiC;AACrC,QAAI;AACF,YAAM,cAAc,MAAM,IAAI,IAAI,CAAC,OAAO,aAAa,gBAAgB,eAAe,CAAC;AACvF,wBAAkB,YAAY,KAAK,KAAK;AAAA,IAC1C,QAAQ;AAAA,IAER;AAEA,QAAI,YAA2B;AAC/B,QAAI;AACF,YAAM,UAAU,MAAM,IAAI,WAAW,IAAI;AACzC,YAAM,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ;AACtD,UAAI,QAAQ,MAAM,OAAO;AACvB,oBAAY,gBAAgB,OAAO,KAAK,KAAK;AAAA,MAC/C;AAAA,IACF,QAAQ;AAAA,IAER;AAGA,QAAI,eAAe;AACnB,QAAI;AACF,YAAM,SAAS,MAAM,IAAI,IAAI,CAAC,YAAY,WAAW,MAAM,CAAC;AAC5D,qBAAe,SAAS,OAAO,KAAK,GAAG,EAAE,KAAK;AAAA,IAChD,QAAQ;AACN,qBAAe;AAAA,IACjB;AAEA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR;AAAA,MACA,gBAAgB,IAAI,QAAQ,QAAQ;AAAA,MACpC;AAAA,MACA;AAAA,MACA,gBAAgB,IAAI,QAAQ,QAAQ;AAAA,IACtC;AAAA,EACF,QAAQ;AACN,WAAO,EAAE,GAAG,OAAO,QAAQ,KAAK;AAAA,EAClC;AACF;AAEA,SAAS,gBAAgB,KAAqB;AAE5C,MAAI,IAAI,WAAW,MAAM,GAAG;AAC1B,UAAM,IAAI,QAAQ,KAAK,GAAG,EAAE,QAAQ,QAAQ,UAAU;AAAA,EACxD;AAEA,MAAI,IAAI,SAAS,MAAM,GAAG;AACxB,UAAM,IAAI,MAAM,GAAG,EAAE;AAAA,EACvB;AACA,SAAO;AACT;AAEA,eAAsB,aACpB,UACA,WAAmB,GACA;AACnB,QAAM,EAAE,MAAAA,MAAK,IAAI,MAAM,OAAO,MAAM;AACpC,QAAM,UAAU,MAAMA,MAAK,WAAW;AAAA,IACpC,KAAK;AAAA,IACL,UAAU,WAAW;AAAA,IACrB,KAAK;AAAA,IACL,QAAQ;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO,QACJ,IAAI,CAAC,WAAW;AACf,UAAM,QAAQ,OAAO,MAAM,GAAG;AAC9B,UAAM,IAAI;AACV,WAAO,MAAM,SAAS,IAClB,GAAG,QAAQ,IAAI,MAAM,KAAK,GAAG,CAAC,KAC9B;AAAA,EACN,CAAC,EACA,KAAK;AACV;AAhHA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,SAAS,UAAU,WAAW,QAAQ,aAAa;AACnD,SAAS,YAAY;AAErB,eAAsB,WAAWC,OAAgC;AAC/D,MAAI;AACF,UAAM,OAAOA,KAAI;AACjB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,SAAsBA,OAA0B;AACpE,QAAM,UAAU,MAAM,SAASA,OAAM,OAAO;AAC5C,SAAO,KAAK,MAAM,OAAO;AAC3B;AAEA,eAAsB,UAAUA,OAAc,MAA8B;AAC1E,QAAM,UAAUA,OAAM,KAAK,UAAU,MAAM,MAAM,CAAC,GAAG,OAAO;AAC9D;AAEA,eAAsB,SAASA,OAA+B;AAC5D,SAAO,SAASA,OAAM,OAAO;AAC/B;AAEA,eAAsB,UAAUA,OAAc,SAAgC;AAC5E,QAAM,UAAUA,OAAM,SAAS,OAAO;AACxC;AAEA,eAAsB,UAAUA,OAA6B;AAC3D,QAAM,MAAMA,OAAM,EAAE,WAAW,KAAK,CAAC;AACvC;AA/BA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACUA,eAAsB,WAAW,aAAqB;AACpD,QAAM,UAAU,KAAK,aAAa,cAAc;AAChD,MAAI,CAAE,MAAM,WAAW,OAAO,EAAI,QAAO;AAEzC,QAAM,MAAM,MAAM,SAAsB,OAAO;AAC/C,QAAM,UAAU;AAAA,IACd,GAAG,IAAI;AAAA,IACP,GAAG,IAAI;AAAA,EACT;AACA,QAAM,WAAW,OAAO,KAAK,OAAO;AAEpC,QAAM,YAAsB,CAAC;AAG7B,MAAI,SAAS,SAAS,MAAM,EAAG,WAAU,KAAK,SAAS;AAAA,WAC9C,SAAS,SAAS,MAAM,EAAG,WAAU,KAAK,MAAM;AAAA,WAChD,SAAS,SAAS,OAAO,EAAG,WAAU,KAAK,OAAO;AAAA,WAClD,SAAS,SAAS,QAAQ,KAAK,SAAS,SAAS,eAAe;AACvE,cAAU,KAAK,QAAQ;AAGzB,MAAI,SAAS,SAAS,OAAO,EAAG,WAAU,KAAK,OAAO;AACtD,MAAI,SAAS,SAAS,KAAK,EAAG,WAAU,KAAK,KAAK;AAGlD,MAAI,SAAS,SAAS,aAAa,EAAG,WAAU,KAAK,cAAc;AAGnE,MAAI,SAAS,SAAS,SAAS,EAAG,WAAU,KAAK,SAAS;AAC1D,MAAI,SAAS,SAAS,SAAS,EAAG,WAAU,KAAK,SAAS;AAC1D,MAAI,SAAS,SAAS,MAAM,EAAG,WAAU,KAAK,MAAM;AAGpD,MAAI,SAAS,SAAS,QAAQ,KAAK,SAAS,SAAS,gBAAgB;AACnE,cAAU,KAAK,QAAQ;AACzB,MAAI,SAAS,SAAS,aAAa,EAAG,WAAU,KAAK,SAAS;AAC9D,MAAI,SAAS,SAAS,UAAU,EAAG,WAAU,KAAK,SAAS;AAG3D,MAAI,SAAS,SAAS,QAAQ,EAAG,WAAU,KAAK,QAAQ;AACxD,MAAI,SAAS,SAAS,mBAAmB,EAAG,WAAU,KAAK,YAAY;AACvE,MAAI,SAAS,SAAS,WAAW,EAAG,WAAU,KAAK,WAAW;AAG9D,MAAI,SAAS,SAAS,YAAY,EAAG,WAAU,KAAK,YAAY;AAAA,MAC3D,WAAU,KAAK,YAAY;AAEhC,SAAO;AAAA,IACL,MAAM,IAAI,QAAQ;AAAA,IAClB,aAAa,IAAI,eAAe;AAAA,IAChC,UAAU,IAAI,YAAY;AAAA,IAC1B;AAAA,EACF;AACF;AA/DA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,eAAsB,aAAa,aAAqB;AACtD,QAAM,YAAsB,CAAC,QAAQ;AAErC,QAAM,UAAU,KAAK,aAAa,kBAAkB;AACpD,QAAM,gBAAgB,KAAK,aAAa,gBAAgB;AACxD,QAAM,YAAY,KAAK,aAAa,UAAU;AAE9C,MAAI,OAAO;AAEX,MAAI,MAAM,WAAW,OAAO,GAAG;AAC7B,WAAO,MAAM,SAAS,OAAO;AAAA,EAC/B,WAAW,MAAM,WAAW,aAAa,GAAG;AAC1C,WAAO,MAAM,SAAS,aAAa;AAAA,EACrC,WAAW,MAAM,WAAW,SAAS,GAAG;AACtC,WAAO,MAAM,SAAS,SAAS;AAAA,EACjC,OAAO;AACL,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,KAAK,YAAY;AAEnC,MAAI,UAAU,SAAS,QAAQ,EAAG,WAAU,KAAK,QAAQ;AACzD,MAAI,UAAU,SAAS,OAAO,EAAG,WAAU,KAAK,OAAO;AACvD,MAAI,UAAU,SAAS,SAAS,EAAG,WAAU,KAAK,SAAS;AAC3D,MAAI,UAAU,SAAS,SAAS,KAAK,UAAU,SAAS,OAAO;AAC7D,cAAU,KAAK,SAAS;AAC1B,MAAI,UAAU,SAAS,YAAY,EAAG,WAAU,KAAK,YAAY;AACjE,MAAI,UAAU,SAAS,cAAc,EAAG,WAAU,KAAK,cAAc;AACrE,MAAI,UAAU,SAAS,WAAW,EAAG,WAAU,KAAK,WAAW;AAC/D,MAAI,UAAU,SAAS,QAAQ,EAAG,WAAU,KAAK,QAAQ;AACzD,MAAI,UAAU,SAAS,QAAQ,EAAG,WAAU,KAAK,QAAQ;AACzD,MAAI,UAAU,SAAS,OAAO,EAAG,WAAU,KAAK,OAAO;AACvD,MAAI,UAAU,SAAS,QAAQ,EAAG,WAAU,KAAK,cAAc;AAE/D,SAAO,EAAE,UAAU;AACrB;AArCA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,eAAsB,WAAW,aAAqB;AACpD,QAAM,YAAY,KAAK,aAAa,YAAY;AAChD,MAAI,CAAE,MAAM,WAAW,SAAS,EAAI,QAAO;AAE3C,QAAM,UAAU,MAAM,SAAS,SAAS;AACxC,QAAM,YAAsB,CAAC,MAAM;AAEnC,MAAI,QAAQ,SAAS,OAAO,EAAG,WAAU,KAAK,OAAO;AACrD,MAAI,QAAQ,SAAS,MAAM,EAAG,WAAU,KAAK,MAAM;AACnD,MAAI,QAAQ,SAAS,OAAO,EAAG,WAAU,KAAK,OAAO;AACrD,MAAI,QAAQ,SAAS,MAAM,EAAG,WAAU,KAAK,aAAa;AAC1D,MAAI,QAAQ,SAAS,OAAO,EAAG,WAAU,KAAK,OAAO;AACrD,MAAI,QAAQ,SAAS,QAAQ,EAAG,WAAU,KAAK,QAAQ;AACvD,MAAI,QAAQ,SAAS,MAAM,EAAG,WAAU,KAAK,MAAM;AAGnD,QAAM,YAAY,QAAQ,MAAM,yCAAyC;AACzE,QAAM,YAAY,QAAQ;AAAA,IACxB;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM,YAAY,CAAC,KAAK;AAAA,IACxB,aAAa,YAAY,CAAC,KAAK;AAAA,IAC/B;AAAA,EACF;AACF;AA5BA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,eAAsB,SAAS,aAAqB;AAClD,QAAM,YAAY,KAAK,aAAa,QAAQ;AAC5C,MAAI,CAAE,MAAM,WAAW,SAAS,EAAI,QAAO;AAE3C,QAAM,UAAU,MAAM,SAAS,SAAS;AACxC,QAAM,YAAsB,CAAC,IAAI;AAEjC,MAAI,QAAQ,SAAS,WAAW,EAAG,WAAU,KAAK,KAAK;AACvD,MAAI,QAAQ,SAAS,MAAM,EAAG,WAAU,KAAK,MAAM;AACnD,MAAI,QAAQ,SAAS,OAAO,EAAG,WAAU,KAAK,OAAO;AACrD,MAAI,QAAQ,SAAS,MAAM,EAAG,WAAU,KAAK,MAAM;AACnD,MAAI,QAAQ,SAAS,MAAM,EAAG,WAAU,KAAK,MAAM;AACnD,MAAI,QAAQ,SAAS,OAAO,EAAG,WAAU,KAAK,OAAO;AACrD,MAAI,QAAQ,SAAS,KAAK,EAAG,WAAU,KAAK,KAAK;AAEjD,SAAO,EAAE,UAAU;AACrB;AAlBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,SAAS,YAAY;AACrB,SAAS,UAAU,eAAe;AAwClC,eAAsB,gBACpB,aACiC;AACjC,QAAM,gBAAgB,YAAY,IAAI,CAAC,MAAM,MAAM,CAAC,KAAK;AACzD,QAAM,QAAQ,MAAM,KAAK,UAAU;AAAA,IACjC,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,UAAU;AAAA,EACZ,CAAC;AAED,QAAM,SAAiC,CAAC;AACxC,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,QAAQ,IAAI,EAAE,YAAY;AACtC,UAAM,OAAO,cAAc,GAAG;AAC9B,QAAI,MAAM;AACR,aAAO,IAAI,KAAK,OAAO,IAAI,KAAK,KAAK;AAAA,IACvC;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,mBAAmB,aAA6B;AAC9D,SAAO,SAAS,WAAW;AAC7B;AAlEA,IAGM,eAwBA;AA3BN;AAAA;AAAA;AAAA;AAGA,IAAM,gBAAwC;AAAA,MAC5C,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS;AAAA,MACT,OAAO;AAAA,MACP,UAAU;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,QAAQ;AAAA,IACV;AAEA,IAAM,cAAc;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA;AAAA;;;ACrCA,eAAsB,cACpB,aACwB;AACxB,QAAM,aAAa;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,aAAW,QAAQ,YAAY;AAC7B,UAAMC,KAAI,KAAK,aAAa,IAAI;AAChC,QAAI,MAAM,WAAWA,EAAC,GAAG;AACvB,YAAM,UAAU,MAAM,SAASA,EAAC;AAEhC,aAAO,QAAQ,MAAM,GAAG,GAAI;AAAA,IAC9B;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,sBAAsB,QAAsC;AAC1E,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,MAAI,aAAa;AACjB,QAAM,iBAA2B,CAAC;AAElC,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,QAAQ,WAAW,GAAG,GAAG;AAC3B,UAAI,cAAc,eAAe,SAAS,EAAG;AAC7C,mBAAa;AACb;AAAA,IACF;AACA,QAAI,cAAc,YAAY,MAAM,eAAe,SAAS,EAAG;AAC/D,QAAI,cAAc,YAAY,IAAI;AAChC,qBAAe,KAAK,OAAO;AAAA,IAC7B;AACA,QAAI,CAAC,cAAc,YAAY,MAAM,CAAC,QAAQ,WAAW,GAAG,GAAG;AAC7D,qBAAe,KAAK,OAAO;AAC3B,mBAAa;AAAA,IACf;AAAA,EACF;AAEA,SAAO,eAAe,SAAS,IAAI,eAAe,KAAK,GAAG,IAAI;AAChE;AAEO,SAAS,eAAe,QAAsC;AACnE,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,WAAW;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,aAAW,WAAW,UAAU;AAC9B,UAAM,QAAQ,OAAO,MAAM,OAAO;AAClC,QAAI,QAAQ,CAAC,EAAG,QAAO,MAAM,CAAC;AAAA,EAChC;AACA,SAAO;AACT;AA/DA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,OAAO,WAAW;AAAlB,IAEa;AAFb;AAAA;AAAA;AAAA;AAEO,IAAM,SAAS;AAAA,MACpB,KAAK,KAAa;AAChB,gBAAQ,IAAI,MAAM,KAAK,MAAM,GAAG,EAAE,CAAC;AAAA,MACrC;AAAA,MACA,QAAQ,KAAa;AACnB,gBAAQ,IAAI,MAAM,MAAM,MAAM,GAAG,EAAE,CAAC;AAAA,MACtC;AAAA,MACA,KAAK,KAAa;AAChB,gBAAQ,IAAI,MAAM,OAAO,MAAM,GAAG,EAAE,CAAC;AAAA,MACvC;AAAA,MACA,MAAM,KAAa;AACjB,gBAAQ,MAAM,MAAM,IAAI,MAAM,GAAG,EAAE,CAAC;AAAA,MACtC;AAAA,MACA,MAAM,KAAa;AACjB,gBAAQ,IAAI,GAAG;AAAA,MACjB;AAAA,MACA,QAAQ;AACN,gBAAQ,IAAI;AAAA,MACd;AAAA,MACA,OAAO,KAAa;AAClB,gBAAQ,IAAI;AACZ,gBAAQ,IAAI,MAAM,KAAK,GAAG,CAAC;AAC3B,gBAAQ,IAAI;AAAA,MACd;AAAA,MACA,MAAM,MAAkB;AACtB,YAAI,KAAK,WAAW,EAAG;AACvB,cAAM,YAAY,KAAK,CAAC,EAAE;AAAA,UAAI,CAAC,GAAG,WAChC,KAAK,IAAI,GAAG,KAAK,IAAI,CAAC,SAAS,IAAI,MAAM,KAAK,IAAI,MAAM,CAAC;AAAA,QAC3D;AACA,mBAAW,OAAO,MAAM;AACtB,gBAAM,OAAO,IACV,IAAI,CAAC,MAAM,OAAO,QAAQ,IAAI,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,EACtD,KAAK,EAAE;AACV,kBAAQ,IAAI,KAAK,IAAI,EAAE;AAAA,QACzB;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACzBA,OAAO,SAAS;AAEhB,eAAsB,aACpB,aACwB;AACxB,QAAM,WAAqB,CAAC;AAE5B,QAAM,UAAU,IAAI,0BAA0B,EAAE,MAAM;AAEtD,aAAW,OAAO,aAAa;AAC7B,QAAI;AAEF,YAAM,QAAQ,MAAM,aAAa,GAAG;AACpC,eAAS,KAAK,GAAG,KAAK;AAGtB,YAAM,aAAa,MAAM,mBAAmB,KAAK,IAAI,IAAI,KAAK,CAAC;AAC/D,eAAS,KAAK,GAAG,UAAU;AAAA,IAC7B,SAAS,KAAK;AACZ,aAAO,KAAK,kBAAkB,GAAG,KAAK,GAAG,EAAE;AAAA,IAC7C;AAAA,EACF;AAGA,QAAM,cAAc,CAAC,GAAG,IAAI,IAAI,QAAQ,CAAC;AACzC,UAAQ,OAAO,SAAS,YAAY,MAAM;AAE1C,QAAM,WAA0B,CAAC;AAEjC,aAAW,eAAe,aAAa;AACrC,QAAI;AACF,YAAM,UAAU,MAAM,mBAAmB,WAAW;AACpD,UAAI,SAAS;AACX,iBAAS,KAAK,OAAO;AAAA,MACvB;AAAA,IACF,SAAS,KAAK;AAAA,IAEd;AAAA,EACF;AAGA,QAAM,WAAW,oBAAI,IAAoB;AACzC,aAAW,WAAW,UAAU;AAC9B,UAAM,QAAQ,SAAS,IAAI,QAAQ,EAAE,KAAK;AAC1C,QAAI,QAAQ,GAAG;AACb,cAAQ,KAAK,GAAG,QAAQ,EAAE,IAAI,KAAK;AAAA,IACrC;AACA,aAAS,IAAI,QAAQ,GAAG,QAAQ,SAAS,EAAE,GAAG,QAAQ,CAAC;AAAA,EACzD;AAEA,UAAQ,QAAQ,WAAW,SAAS,MAAM,WAAW;AACrD,SAAO;AACT;AAEA,eAAe,mBACb,UACA,UACmB;AACnB,QAAM,EAAE,MAAAC,MAAK,IAAI,MAAM,OAAO,MAAM;AACpC,QAAM,aAAa;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,QAAQ,oBAAI,IAAY;AAC9B,aAAW,WAAW,YAAY;AAChC,UAAM,UAAU,MAAMA,MAAK,SAAS;AAAA,MAClC,KAAK;AAAA,MACL,QAAQ,CAAC,sBAAsB,cAAc;AAAA,IAC/C,CAAC;AACD,eAAW,SAAS,SAAS;AAC3B,YAAM,MAAM,GAAG,QAAQ,IAAI,MAAM,MAAM,GAAG,EAAE,CAAC,CAAC;AAC9C,UAAI,CAAC,SAAS,IAAI,GAAG,KAAK,CAAC,MAAM,IAAI,GAAG,GAAG;AACzC,cAAM,IAAI,GAAG;AAAA,MACf;AAAA,IACF;AAAA,EACF;AACA,SAAO,CAAC,GAAG,KAAK,EAAE,KAAK;AACzB;AAEA,eAAe,mBACb,aAC6B;AAC7B,QAAM,UAAU,MAAM,WAAW,WAAW;AAG5C,MAAI,YAAsB,CAAC;AAC3B,MAAI,OAAsB;AAC1B,MAAI,cAA6B;AACjC,MAAI,WAA0B;AAE9B,QAAM,WAAW,MAAM,WAAW,WAAW;AAC7C,MAAI,UAAU;AACZ,cAAU,KAAK,GAAG,SAAS,SAAS;AACpC,WAAO,SAAS,QAAQ;AACxB,kBAAc,SAAS,eAAe;AACtC,eAAW,SAAS,YAAY;AAAA,EAClC;AAEA,QAAM,aAAa,MAAM,aAAa,WAAW;AACjD,MAAI,YAAY;AACd,cAAU,KAAK,GAAG,WAAW,SAAS;AAAA,EACxC;AAEA,QAAM,WAAW,MAAM,WAAW,WAAW;AAC7C,MAAI,UAAU;AACZ,cAAU,KAAK,GAAG,SAAS,SAAS;AACpC,WAAO,SAAS,QAAQ;AACxB,kBAAc,SAAS,eAAe;AAAA,EACxC;AAEA,QAAM,SAAS,MAAM,SAAS,WAAW;AACzC,MAAI,QAAQ;AACV,cAAU,KAAK,GAAG,OAAO,SAAS;AAAA,EACpC;AAGA,cAAY,CAAC,GAAG,IAAI,IAAI,SAAS,CAAC;AAGlC,QAAM,YAAY,MAAM,gBAAgB,WAAW;AAGnD,MAAI,UAAU,WAAW,GAAG;AAC1B,UAAM,WAAW,OAAO,QAAQ,SAAS,EACtC,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAC1B,MAAM,GAAG,CAAC,EACV,IAAI,CAAC,CAAC,IAAI,MAAM,IAAI;AACvB,gBAAY;AAAA,EACd;AAGA,QAAM,gBAAgB,MAAM,cAAc,WAAW;AACrD,MAAI,CAAC,aAAa;AAChB,kBAAc,sBAAsB,aAAa,KAAK;AAAA,EACxD;AAGA,QAAM,UAAU,YAAY,eAAe,aAAa;AAGxD,MAAI,CAAC,MAAM;AACT,WAAO,mBAAmB,WAAW;AAAA,EACvC;AAIA,QAAM,aAAa,mBAAmB,WAAW;AACjD,QAAM,KAAK,WACR,YAAY,EACZ,QAAQ,eAAe,GAAG,EAC1B,QAAQ,UAAU,EAAE;AAEvB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,aAAa,eAAe;AAAA,IAC5B;AAAA,IACA;AAAA,IACA,iBAAiB,QAAQ,mBAAmB;AAAA,IAC5C,gBAAgB,QAAQ,kBAAkB;AAAA,IAC1C,cAAc,QAAQ;AAAA,IACtB,WAAW,QAAQ;AAAA,IACnB;AAAA,IACA;AAAA,IACA,mBAAmB,QAAQ,kBAAkB;AAAA,EAC/C;AACF;AAxLA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AAAA;AAAA;;;ACZA,IAOa,eAOA,cAMA,mBASA,iBASA,gBAMA,gBAMA,cASA;AA3Db;AAAA;AAAA;AAAA;AAOO,IAAM,gBAAkE;AAAA,MAC7E,EAAE,OAAO,gBAAgB,OAAO,eAAe;AAAA,MAC/C,EAAE,OAAO,eAAe,OAAO,cAAc;AAAA,MAC7C,EAAE,OAAO,cAAc,OAAO,aAAa;AAAA,MAC3C,EAAE,OAAO,UAAU,OAAO,sBAAsB;AAAA,IAClD;AAEO,IAAM,eAAgE;AAAA,MAC3E,EAAE,OAAO,SAAS,OAAO,QAAQ;AAAA,MACjC,EAAE,OAAO,kBAAkB,OAAO,iBAAiB;AAAA,MACnD,EAAE,OAAO,UAAU,OAAO,iBAAiB;AAAA,IAC7C;AAEO,IAAM,oBAGP;AAAA,MACJ,EAAE,OAAO,UAAU,OAAO,SAAS;AAAA,MACnC,EAAE,OAAO,YAAY,OAAO,WAAW;AAAA,MACvC,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,IACjC;AAEO,IAAM,kBAAyD;AAAA,MACpE,EAAE,OAAO,UAAU,OAAO,sBAAsB;AAAA,MAChD,EAAE,OAAO,SAAS,OAAO,WAAW;AAAA,MACpC,EAAE,OAAO,YAAY,OAAO,uBAAuB;AAAA,MACnD,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,MAC/B,EAAE,OAAO,WAAW,OAAO,oBAAoB;AAAA,MAC/C,EAAE,OAAO,WAAW,OAAO,UAAU;AAAA,IACvC;AAEO,IAAM,iBAAyD;AAAA,MACpE,EAAE,OAAO,UAAU,OAAO,cAAc;AAAA,MACxC,EAAE,OAAO,SAAS,OAAO,QAAQ;AAAA,MACjC,EAAE,OAAO,MAAM,OAAO,cAAc;AAAA,IACtC;AAEO,IAAM,iBAA6D;AAAA,MACxE,EAAE,OAAO,cAAc,OAAO,mBAAmB;AAAA,MACjD,EAAE,OAAO,UAAU,OAAO,SAAS;AAAA,MACnC,EAAE,OAAO,SAAS,OAAO,yBAAyB;AAAA,IACpD;AAEO,IAAM,eAGP;AAAA,MACJ,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,MAC/B,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,MAC/B,EAAE,OAAO,eAAe,OAAO,cAAc;AAAA,IAC/C;AAEO,IAAM,wBAA4D;AAAA,MACvE,EAAE,OAAO,WAAW,OAAO,SAAS;AAAA,MACpC,EAAE,OAAO,WAAW,OAAO,QAAQ;AAAA,MACnC,EAAE,OAAO,WAAW,OAAO,SAAS;AAAA,MACpC,EAAE,OAAO,WAAW,OAAO,OAAO;AAAA,MAClC,EAAE,OAAO,WAAW,OAAO,MAAM;AAAA,MACjC,EAAE,OAAO,WAAW,OAAO,OAAO;AAAA,IACpC;AAAA;AAAA;;;AClEA,YAAY,OAAO;AA2BnB,SAAS,aAAa,OAAsB;AAC1C,MAAM,WAAS,KAAK,GAAG;AACrB,IAAE,SAAO,YAAY;AACrB,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAcA,eAAe,aACb,UAC0B;AAC1B,QAAM,cAAe,MAAQ,UAAQ;AAAA,IACnC,SAAS;AAAA,IACT,cAAc;AAAA,EAChB,CAAC;AACD,eAAa,WAAW;AAExB,MAAI,CAAC,YAAa,QAAO;AAGzB,MAAI,YAAY,CAAC,GAAG,QAAQ;AAE5B,SAAO,UAAU,UAAU,GAAG;AAC5B,UAAM,WAAY,MAAQ,cAAY;AAAA,MACpC,SACE;AAAA,MACF,SAAS,UAAU,IAAI,CAAC,UAAU;AAAA,QAChC,OAAO,KAAK;AAAA,QACZ,OAAO,GAAG,KAAK,IAAI,MAAM,KAAK,SAAS;AAAA,QACvC,MAAM,KAAK,UAAU,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI;AAAA,MAC5C,EAAE;AAAA,MACF,UAAU;AAAA,IACZ,CAAC;AACD,iBAAa,QAAQ;AAErB,QAAI,SAAS,SAAS,GAAG;AACvB,aAAO,KAAK,8CAA8C;AAC1D;AAAA,IACF;AAGA,UAAM,UAAU,SAAS;AAAA,MACvB,CAAC,OAAO,UAAU,KAAK,CAACC,OAAMA,GAAE,OAAO,EAAE;AAAA,IAC3C;AAGA,UAAM,cAAc,QAAQ,IAAI,CAACA,OAAMA,GAAE,IAAI,EAAE,KAAK,KAAK;AACzD,UAAM,aAAc,MAAQ,OAAK;AAAA,MAC/B,SAAS;AAAA,MACT,aAAa;AAAA,MACb,cAAc;AAAA,IAChB,CAAC;AACD,iBAAa,UAAU;AAGvB,UAAM,SAAS,cAAc,SAAS,UAAU;AAGhD,gBAAY,UAAU,OAAO,CAACA,OAAM,CAAC,SAAS,SAASA,GAAE,EAAE,CAAC;AAC5D,cAAU,KAAK,MAAM;AAErB,WAAO;AAAA,MACL,UAAU,QAAQ,IAAI,CAACA,OAAMA,GAAE,IAAI,EAAE,KAAK,IAAI,CAAC,QAAQ,UAAU;AAAA,IACnE;AAEA,QAAI,UAAU,SAAS,EAAG;AAE1B,UAAM,OAAQ,MAAQ,UAAQ;AAAA,MAC5B,SAAS;AAAA,MACT,cAAc;AAAA,IAChB,CAAC;AACD,iBAAa,IAAI;AAEjB,QAAI,CAAC,KAAM;AAAA,EACb;AAEA,SAAO;AACT;AAEA,SAAS,cACP,UACA,MACe;AAEf,QAAM,cAA6B,CAAC;AACpC,aAAW,QAAQ,UAAU;AAC3B,QAAI,KAAK,YAAY,KAAK,SAAS,SAAS,GAAG;AAC7C,kBAAY,KAAK,GAAG,KAAK,QAAQ;AAAA,IACnC,OAAO;AAEL,YAAM,EAAE,UAAU,GAAG,KAAK,IAAI;AAC9B,kBAAY,KAAK,IAAI;AAAA,IACvB;AAAA,EACF;AAGA,QAAM,YAAY;AAAA,IAChB,GAAG,IAAI,IAAI,YAAY,QAAQ,CAACA,OAAMA,GAAE,SAAS,CAAC;AAAA,EACpD;AAGA,QAAM,YAAoC,CAAC;AAC3C,aAAW,SAAS,aAAa;AAC/B,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,MAAM,SAAS,GAAG;AAC3D,gBAAU,IAAI,KAAK,UAAU,IAAI,KAAK,KAAK;AAAA,IAC7C;AAAA,EACF;AAGA,QAAM,aAAa,YAChB,IAAI,CAACA,OAAMA,GAAE,eAAe,EAC5B,OAAO,OAAO,EACd,KAAK;AACR,QAAM,YAAY,YACf,IAAI,CAACA,OAAMA,GAAE,cAAc,EAC3B,OAAO,OAAO,EACd,KAAK;AAGR,QAAM,eAAe,YAAY;AAAA,IAC/B,CAAC,KAAKA,OAAM,MAAMA,GAAE;AAAA,IACpB;AAAA,EACF;AAGA,QAAM,YACJ,YAAY,KAAK,CAACA,OAAMA,GAAE,SAAS,GAAG,aAAa;AAGrD,QAAM,UACJ,YAAY,KAAK,CAACA,OAAMA,GAAE,OAAO,GAAG,WAAW;AAGjD,QAAM,cAAc,YACjB,OAAO,CAACA,OAAMA,GAAE,aAAa,EAC7B;AAAA,IACC,CAACA,OACC,OAAOA,GAAE,IAAI;AAAA,EAASA,GAAE,aAAa;AAAA,EACzC;AACF,QAAM,gBACJ,YAAY,SAAS,IAAI,YAAY,KAAK,MAAM,IAAI;AAGtD,QAAM,eAAe,YAClB,IAAI,CAACA,OAAMA,GAAE,WAAW,EACxB,OAAO,OAAO;AACjB,QAAM,cAAc,aAAa,KAAK,KAAK;AAG3C,QAAM,YAAY,YAAY,CAAC,EAAE;AAEjC,QAAM,KAAK,KACR,YAAY,EACZ,QAAQ,eAAe,GAAG,EAC1B,QAAQ,UAAU,EAAE;AAEvB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,iBAAiB,WAAW,CAAC,KAAK;AAAA,IAClC,gBAAgB,UAAU,UAAU,SAAS,CAAC,KAAK;AAAA,IACnD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB,YAAY,CAAC,EAAE,qBAAqB;AAAA,IACvD,UAAU;AAAA,EACZ;AACF;AAEA,eAAsB,aACpB,iBACA,kBAC0B;AAC1B,EAAE,QAAM,WAAW;AAGnB,SAAO,OAAO,mBAAmB;AAEjC,QAAM,iBAAiB,gBAAgB,IAAI,CAAC,SAAS;AACnD,UAAM,WAAW,KAAK,UAAU,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI;AACrD,UAAM,aAAa,KAAK,eAAe,IAAI,GAAG,KAAK,YAAY,aAAa;AAC5E,WAAO;AAAA,MACL,OAAO,KAAK;AAAA,MACZ,OAAO,GAAG,KAAK,IAAI,MAAM,KAAK,SAAS;AAAA,MACvC,MAAM,WAAW,GAAG,QAAQ,MAAM,UAAU,KAAK;AAAA,IACnD;AAAA,EACF,CAAC;AAED,QAAM,cAAe,MAAQ,cAAY;AAAA,IACvC,SAAS;AAAA,IACT,SAAS;AAAA,IACT,UAAU;AAAA,EACZ,CAAC;AACD,eAAa,WAAW;AAGxB,MAAI,gBAAiC,YAAY;AAAA,IAC/C,CAAC,OAAO,gBAAgB,KAAK,CAACA,OAAMA,GAAE,OAAO,EAAE;AAAA,EACjD;AAGA,MAAI,cAAc,UAAU,GAAG;AAC7B,oBAAgB,MAAM,aAAa,aAAa;AAAA,EAClD;AAGA,QAAM,iBAAiC,CAAC;AAExC,aAAW,QAAQ,eAAe;AAChC,UAAM,cAAc,KAAK,WACrB,GAAG,KAAK,IAAI,KAAK,KAAK,SAAS,MAAM,mBACrC,KAAK;AAET,WAAO,MAAM;AAAA,iBAAoB,WAAW,EAAE;AAE9C,UAAM,eAAgB,MAAQ,OAAK;AAAA,MACjC,SAAS,mBAAmB,WAAW;AAAA,MACvC,aAAa,KAAK,aAAa,MAAM,GAAG,EAAE,KAAK;AAAA,MAC/C,cAAc;AAAA,IAChB,CAAC;AACD,iBAAa,YAAY;AAEzB,UAAM,UAAW,MAAQ,OAAK;AAAA,MAC5B,SAAS,gBAAgB,WAAW;AAAA,MACpC,aAAa,KAAK,WAAW;AAAA,MAC7B,cAAc,KAAK,WAAW;AAAA,IAChC,CAAC;AACD,iBAAa,OAAO;AAEpB,UAAM,aAAc,MAAQ,UAAQ;AAAA,MAClC,SAAS,6BAA6B,WAAW;AAAA,MACjD,cAAc,CAAC,CAAC,KAAK;AAAA,IACvB,CAAC;AACD,iBAAa,UAAU;AAEvB,UAAM,OAAQ,MAAQ,SAAO;AAAA,MAC3B,SAAS,gBAAgB,WAAW;AAAA,MACpC,SAAS;AAAA,IACX,CAAC;AACD,iBAAa,IAAI;AAEjB,UAAM,eAAgB,MAAQ,OAAK;AAAA,MACjC,SAAS,mBAAmB,WAAW;AAAA,MACvC,aAAa;AAAA,MACb,cAAc;AAAA,IAChB,CAAC;AACD,iBAAa,YAAY;AAEzB,UAAM,UAAmC,CAAC;AAC1C,QAAI,cAAc;AAChB,cAAQ,SAAS,EAAE,SAAS,aAAa;AAAA,IAC3C;AAEA,mBAAe,KAAK;AAAA,MAClB,GAAG;AAAA,MACH,UAAU;AAAA,MACV,qBAAqB,gBAAgB;AAAA,MACrC,gBAAgB;AAAA,MAChB,SAAS,WAAW,KAAK;AAAA,MACzB;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAGA,SAAO,OAAO,sBAAsB;AAEpC,QAAM,OAAQ,MAAQ,OAAK;AAAA,IACzB,SAAS;AAAA,IACT,UAAU,CAAC,MAAO,EAAE,WAAW,IAAI,qBAAqB;AAAA,EAC1D,CAAC;AACD,eAAa,IAAI;AAEjB,QAAM,UAAW,MAAQ,OAAK;AAAA,IAC5B,SAAS;AAAA,IACT,aAAa;AAAA,EACf,CAAC;AACD,eAAa,OAAO;AAEpB,QAAM,YAAa,MAAQ,SAAO;AAAA,IAChC,SAAS;AAAA,IACT,SAAS;AAAA,MACP,EAAE,OAAO,QAAQ,OAAO,iCAAiC;AAAA,MACzD,EAAE,OAAO,UAAU,OAAO,iBAAiB;AAAA,IAC7C;AAAA,EACF,CAAC;AACD,eAAa,SAAS;AAEtB,MAAI,MAAuB;AAC3B,MAAI,cAAc,UAAU;AAC1B,UAAO,MAAQ,OAAK;AAAA,MAClB,SAAS;AAAA,IACX,CAAC;AACD,iBAAa,GAAG;AAAA,EAClB;AAEA,QAAM,WAAY,MAAQ,OAAK;AAAA,IAC7B,SAAS;AAAA,IACT,aAAa;AAAA,IACb,cAAc;AAAA,EAChB,CAAC;AACD,eAAa,QAAQ;AAErB,QAAM,SAAU,MAAQ,OAAK;AAAA,IAC3B,SAAS;AAAA,IACT,cAAc;AAAA,EAChB,CAAC;AACD,eAAa,MAAM;AAEnB,QAAM,UAAW,MAAQ,OAAK;AAAA,IAC5B,SAAS;AAAA,IACT,cAAc;AAAA,EAChB,CAAC;AACD,eAAa,OAAO;AAEpB,QAAM,WAAY,MAAQ,OAAK;AAAA,IAC7B,SAAS;AAAA,IACT,cAAc;AAAA,EAChB,CAAC;AACD,eAAa,QAAQ;AAErB,QAAM,UAAW,MAAQ,OAAK;AAAA,IAC5B,SAAS;AAAA,IACT,cAAc;AAAA,EAChB,CAAC;AACD,eAAa,OAAO;AAEpB,QAAM,QAAS,MAAQ,OAAK;AAAA,IAC1B,SAAS;AAAA,IACT,cAAc;AAAA,EAChB,CAAC;AACD,eAAa,KAAK;AAElB,QAAM,QAAmB;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,YAAY;AAAA,IACtB,QAAQ;AAAA,MACN,QAAQ,UAAU;AAAA,MAClB,SAAS,WAAW;AAAA,MACpB,UAAU,YAAY;AAAA,MACtB,MAAM,WAAW;AAAA,MACjB,OAAO,SAAS;AAAA,IAClB;AAAA,EACF;AAGA,SAAO,OAAO,oBAAoB;AAElC,QAAM,QAAS,MAAQ,SAAO;AAAA,IAC5B,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC;AACD,eAAa,KAAK;AAElB,QAAM,cAAe,MAAQ,SAAO;AAAA,IAClC,SAAS;AAAA,IACT,SAAS;AAAA,MACP,GAAG;AAAA,MACH,EAAE,OAAO,UAAU,OAAO,aAAa;AAAA,IACzC;AAAA,EACF,CAAC;AACD,eAAa,WAAW;AAExB,MAAI,cAAc;AAClB,MAAI,gBAAgB,UAAU;AAC5B,kBAAe,MAAQ,OAAK;AAAA,MAC1B,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU,CAAC,MACT,oBAAoB,KAAK,CAAC,IAAI,SAAY;AAAA,IAC9C,CAAC;AACD,iBAAa,WAAW;AAAA,EAC1B;AAEA,QAAM,OAAQ,MAAQ,SAAO;AAAA,IAC3B,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC;AACD,eAAa,IAAI;AAEjB,QAAM,iBAAkB,MAAQ,SAAO;AAAA,IACrC,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC;AACD,eAAa,cAAc;AAE3B,QAAM,QAAqB;AAAA,IACzB;AAAA,IACA,aAAa;AAAA,IACb;AAAA,IACA;AAAA,EACF;AAGA,SAAO,OAAO,UAAU;AAExB,QAAM,qBAAsB,MAAQ,cAAY;AAAA,IAC9C,SAAS;AAAA,IACT,SAAS;AAAA,IACT,UAAU;AAAA,EACZ,CAAC;AACD,eAAa,kBAAkB;AAE/B,QAAM,WAAwB;AAAA,IAC5B;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL;AAGA,SAAO,OAAO,WAAW;AAEzB,MAAI;AACJ,MAAI,iBAAiB,WAAW,GAAG;AACjC,aAAS,iBAAiB,CAAC;AAC3B,WAAO,KAAK,SAAS,MAAM,EAAE;AAAA,EAC/B,OAAO;AACL,UAAM,wBAAwB,eAAe;AAAA,MAAO,CAAC,MACnD,iBAAiB,SAAS,EAAE,KAAK;AAAA,IACnC;AACA,aAAU,MAAQ,SAAO;AAAA,MACvB,SAAS;AAAA,MACT,SAAS;AAAA,IACX,CAAC;AACD,iBAAa,MAAM;AAAA,EACrB;AAGA,SAAO,OAAO,YAAY;AAE1B,QAAM,iBAAkB,MAAQ,SAAO;AAAA,IACrC,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC;AACD,eAAa,cAAc;AAE3B,MAAI,cAAc;AAClB,MAAI,mBAAmB,SAAS;AAC9B,kBAAe,MAAQ,OAAK;AAAA,MAC1B,SAAS;AAAA,MACT,aAAa;AAAA,MACb,UAAU,CAAC,MACT,eAAe,KAAK,CAAC,IACjB,SACA;AAAA,IACR,CAAC;AACD,iBAAa,WAAW;AAAA,EAC1B;AAEA,EAAE,QAAM,iDAAiD;AAEzD,SAAO;AAAA,IACL,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,MACN,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF;AACF;AA3fA;AAAA;AAAA;AAAA;AAUA;AAUA;AAAA;AAAA;;;ACjBO,SAAS,UAAU,WAA2C;AACnE,SAAO;AAAA,IACL,SAAS;AAAA,IACT,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC,QAAQ,UAAU;AAAA,IAClB,WAAW;AAAA,IACX,OAAO,UAAU;AAAA,IACjB,OAAO,UAAU;AAAA,IACjB,UAAU,UAAU;AAAA,IACpB,UAAU,UAAU;AAAA,IACpB,QAAQ;AAAA,MACN,UAAU,UAAU,OAAO;AAAA,MAC3B,aAAa,UAAU,OAAO;AAAA,IAChC;AAAA,EACF;AACF;AAlBA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,SAAS,YAAAC,iBAAgB;AACzB,SAAS,QAAAC,OAAM,eAAe;AAC9B,SAAS,iBAAAC,sBAAqB;AAG9B,SAAS,gBAAwB;AAG/B,QAAM,aAAa,QAAQA,eAAc,YAAY,GAAG,CAAC;AAEzD,QAAM,aAAa;AAAA,IACjBD,MAAK,YAAY,eAAe;AAAA,IAChCA,MAAK,YAAY,YAAY;AAAA,IAC7BA,MAAK,YAAY,kBAAkB;AAAA,EACrC;AACA,SAAO,WAAW,CAAC;AACrB;AAEA,eAAe,aAAa,UAAmC;AAC7D,QAAM,aAAa,cAAc;AAEjC,QAAM,aAAa;AAAA,IACjBA,MAAK,YAAY,QAAQ;AAAA,IACzBA,MAAK,QAAQC,eAAc,YAAY,GAAG,CAAC,GAAG,iBAAiB,QAAQ;AAAA,IACvED,MAAK,QAAQC,eAAc,YAAY,GAAG,CAAC,GAAG,oBAAoB,QAAQ;AAAA,EAC5E;AAEA,aAAW,aAAa,YAAY;AAClC,QAAI;AACF,aAAO,MAAMF,UAAS,WAAW,OAAO;AAAA,IAC1C,QAAQ;AACN;AAAA,IACF;AAAA,EACF;AAEA,QAAM,IAAI,MAAM,8BAA8B,QAAQ,EAAE;AAC1D;AAEA,eAAsB,iBAAiB,MAAsC;AAC3E,MAAI,WAAW,MAAM,aAAa,gBAAgB;AAElD,QAAM,eAAe,KAAK,SACvB,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,EACnB,KAAK,IAAI;AAEZ,aAAW,SACR,QAAQ,iBAAiB,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC,EACtD,QAAQ,aAAa,KAAK,MAAM,KAAK,EACrC,QAAQ,oBAAoB,KAAK,MAAM,WAAW,EAClD,QAAQ,uBAAuB,KAAK,MAAM,cAAc,EACxD,QAAQ,YAAY,KAAK,MAAM,IAAI,EACnC,QAAQ,qBAAqB,YAAY;AAE5C,SAAO;AACT;AAEA,eAAsB,kBACpB,gBACA,MACiB;AACjB,MAAI,WAAW,MAAM,aAAa,WAAW;AAE7C,QAAM,kBACJ,KAAK,YAAY,SAAS,IACtB,KAAK,YACF;AAAA,IACC,CAACG,OACC,KAAKA,GAAE,IAAI,KAAKA,GAAE,WAAW;AAAA,UAAaA,GAAE,UAAU,KAAK,IAAI,CAAC;AAAA,qBAAwBA,GAAE,iBAAiB,IAAI,MAAM,GAAG,GAAG,CAAC;AAAA,EAChI,EACC,KAAK,MAAM,IACd;AAEN,QAAM,sBACJ,KAAK,gBAAgB,SAAS,IAC1B,KAAK,gBACF;AAAA,IACC,CAAC,MACC,KAAK,EAAE,QAAQ,IAAI,KAAK,EAAE,UAAU;AAAA,oBAAmC,EAAE,aAAa;AAAA,0BAA6B,EAAE,WAAW;AAAA,EACpI,EACC,KAAK,MAAM,IACd;AAEN,QAAM,sBACJ,KAAK,gBAAgB,SAAS,IAC1B,KAAK,gBAAgB,IAAI,CAACA,OAAM,KAAKA,GAAE,IAAI,EAAE,EAAE,KAAK,IAAI,IACxD;AAEN,aAAW,SACR;AAAA,IACC;AAAA,IACA,KAAK,UAAU,gBAAgB,MAAM,CAAC;AAAA,EACxC,EACC,QAAQ,oBAAoB,eAAe,EAC3C,QAAQ,wBAAwB,mBAAmB,EACnD,QAAQ,wBAAwB,mBAAmB,EACnD,QAAQ,0BAA0B,YAAY;AAEjD,SAAO;AACT;AAlGA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,SAAS,aAA2C;AAEpD,eAAsB,IACpB,SACA,MACA,SACA;AACA,SAAO,MAAM,SAAS,MAAM;AAAA,IAC1B,OAAO;AAAA,IACP,GAAG;AAAA,EACL,CAAC;AACH;AAEA,eAAsB,cAAc,SAAmC;AACrE,MAAI;AACF,UAAM,MAAM,SAAS,CAAC,OAAO,CAAC;AAC9B,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,cACpB,SACA,MACA,SACiB;AACjB,QAAM,SAAS,MAAM,MAAM,SAAS,MAAM;AAAA,IACxC,OAAO;AAAA,IACP,GAAG;AAAA,EACL,CAAC;AACD,SAAO,OAAO;AAChB;AAhCA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACQA,eAAsB,gBAA2C;AAC/D,QAAM,UAA4B,CAAC;AAGnC,MAAI,QAAQ,IAAI,YAAY;AAC1B,YAAQ,KAAK,EAAE,MAAM,MAAM,WAAW,KAAK,CAAC;AAAA,EAC9C;AAGA,MAAI,MAAM,cAAc,QAAQ,GAAG;AACjC,YAAQ,KAAK,EAAE,MAAM,UAAU,WAAW,KAAK,CAAC;AAAA,EAClD;AAGA,MAAI,MAAM,cAAc,OAAO,GAAG;AAChC,YAAQ,KAAK,EAAE,MAAM,SAAS,WAAW,KAAK,CAAC;AAAA,EACjD;AAEA,SAAO;AACT;AAEO,SAAS,wBAAwB,SAAyC;AAC/E,SAAO,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AAC7D;AA/BA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,SAAS,SAAAC,cAAa;AAEtB,OAAOC,UAAS;AAEhB,eAAsB,mBACpB,QACA,WACe;AACf,QAAM,UAAUA,KAAI,qCAAqC,EAAE,MAAM;AAEjE,MAAI;AAGF,UAAM,aAAa,GAAG,MAAM;AAAA;AAAA;AAE5B,UAAMD,OAAM,UAAU,CAAC,MAAM,UAAU,GAAG;AAAA,MACxC,KAAK;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA;AAAA,IACX,CAAC;AAED,YAAQ,QAAQ,iCAAiC;AAAA,EACnD,SAAS,OAAO;AACd,YAAQ,KAAK,+BAA+B;AAC5C,UAAM;AAAA,EACR;AACF;AA1BA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,SAAS,SAAAE,cAAa;AAEtB,OAAOC,UAAS;AAEhB,eAAsB,kBACpB,QACA,WACe;AACf,QAAM,UAAUA,KAAI,+BAA+B,EAAE,MAAM;AAE3D,MAAI;AACF,UAAM,aAAa,GAAG,MAAM;AAAA;AAAA;AAE5B,UAAMD,OAAM,SAAS,CAAC,WAAW,eAAe,UAAU,GAAG;AAAA,MAC3D,KAAK;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,IACX,CAAC;AAED,YAAQ,QAAQ,2BAA2B;AAAA,EAC7C,SAAS,OAAO;AACd,YAAQ,KAAK,yBAAyB;AACtC,UAAM;AAAA,EACR;AACF;AAxBA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,OAAO,YAAY;AACnB,SAAS,aAAAE,YAAW,SAAAC,cAAa;AACjC,SAAS,QAAAC,OAAM,WAAAC,gBAAe;AAE9B,OAAOC,UAAS;AAOhB,eAAsB,eACpB,QACA,WACA,QACe;AACf,QAAM,UAAUA,KAAI,4BAA4B,EAAE,MAAM;AAExD,QAAM,SAAS,IAAI,OAAO;AAAA,IACxB;AAAA,IACA,SAAS;AAAA,EACX,CAAC;AAED,MAAI;AACF,UAAM,WAAW,MAAM,OAAO,KAAK,YAAY,OAAO;AAAA,MACpD,OAAO;AAAA,MACP,UAAU;AAAA,QACR;AAAA,UACE,MAAM;AAAA,UACN,SACE;AAAA,QAIJ;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF,CAAC;AAED,UAAM,UAAU,SAAS,QAAQ,CAAC,GAAG,SAAS;AAC9C,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AAEA,YAAQ,OAAO;AAEf,UAAM,QAAQ,aAAa,OAAO;AAClC,QAAI,MAAM,WAAW,GAAG;AACtB,YAAM,IAAI,MAAM,qCAAqC;AAAA,IACvD;AAEA,YAAQ,OAAO,WAAW,MAAM,MAAM;AAEtC,eAAW,QAAQ,OAAO;AACxB,YAAM,WAAWF,MAAK,WAAW,KAAK,QAAQ;AAC9C,YAAMD,OAAME,SAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAClD,YAAMH,WAAU,UAAU,KAAK,SAAS,OAAO;AAAA,IACjD;AAGA,UAAM,aAAa,MAAM,KAAK,CAAC,MAAM,EAAE,aAAa,cAAc;AAClE,QAAI,CAAC,YAAY;AACf,YAAMA;AAAA,QACJE,MAAK,WAAW,cAAc;AAAA,QAC9B,KAAK;AAAA,UACH;AAAA,YACE,MAAM;AAAA,YACN,SAAS;AAAA,YACT,SAAS;AAAA,YACT,SAAS;AAAA,cACP,KAAK;AAAA,cACL,OAAO;AAAA,cACP,OAAO;AAAA,YACT;AAAA,YACA,cAAc;AAAA,cACZ,MAAM;AAAA,cACN,OAAO;AAAA,cACP,aAAa;AAAA,cACb,4BAA4B;AAAA,cAC5B,MAAM;AAAA,cACN,kBAAkB;AAAA,cAClB,gBAAgB;AAAA,YAClB;AAAA,YACA,iBAAiB;AAAA,cACf,YAAY;AAAA,cACZ,eAAe;AAAA,cACf,gBAAgB;AAAA,cAChB,oBAAoB;AAAA,cACpB,aAAa;AAAA,cACb,wBAAwB;AAAA,YAC1B;AAAA,UACF;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,YAAQ,QAAQ,2BAA2B,MAAM,MAAM,SAAS;AAAA,EAClE,SAAS,OAAO;AACd,YAAQ,KAAK,sBAAsB;AACnC,UAAM;AAAA,EACR;AACF;AAEA,SAAS,aAAa,SAAkC;AACtD,QAAM,QAAyB,CAAC;AAGhC,QAAM,WAAW;AAAA;AAAA,IAEf;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA,EACF;AAEA,aAAW,WAAW,UAAU;AAC9B,QAAI;AACJ,YAAQ,QAAQ,QAAQ,KAAK,OAAO,OAAO,MAAM;AAC/C,YAAM,WAAW,MAAM,CAAC,EAAE,KAAK;AAC/B,YAAM,cAAc,MAAM,CAAC,EAAE,KAAK;AAGlC,UACE,SAAS,SAAS,GAAG,KACrB,CAAC,SAAS,SAAS,GAAG,KACtB,CAAC,SAAS,SAAS,GAAG,GACtB;AACA;AAAA,MACF;AAGA,YAAM,gBAAgB,SACnB,QAAQ,gBAAgB,EAAE,EAC1B,QAAQ,UAAU,EAAE;AAEvB,UAAI,iBAAiB,aAAa;AAChC,cAAM,KAAK,EAAE,UAAU,eAAe,SAAS,YAAY,CAAC;AAAA,MAC9D;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AArJA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACOA,eAAsB,sBACpB,SAC2B;AAC3B,QAAM,SAAmB,CAAC;AAE1B,QAAM,gBAAgB;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAGA,QAAM,oBAA0C;AAAA,IAC9C,CAAC,kBAAkB,CAAC,kBAAkB,kBAAkB,iBAAiB,CAAC;AAAA,EAC5E;AAEA,aAAW,QAAQ,eAAe;AAChC,UAAM,eAAe,kBAAkB,KAAK,CAAC,CAAC,GAAG,MAAM,QAAQ,IAAI;AACnE,QAAI,cAAc;AAChB,YAAM,YAAY,MAAM,QAAQ;AAAA,QAC9B,aAAa,CAAC,EAAE,IAAI,OAAO,QAAQ;AACjC,cAAI,MAAM,WAAW,KAAK,SAAS,GAAG,CAAC,EAAG,QAAO;AACjD,gBAAM,IAAI,MAAM,WAAW;AAAA,QAC7B,CAAC;AAAA,MACH,EAAE,MAAM,MAAM,KAAK;AACnB,UAAI,CAAC,WAAW;AACd,eAAO,KAAK,YAAY,IAAI,uBAAuB;AAAA,MACrD;AAAA,IACF,OAAO;AACL,UAAI,CAAE,MAAM,WAAW,KAAK,SAAS,IAAI,CAAC,GAAI;AAC5C,eAAO,KAAK,YAAY,IAAI,EAAE;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,OAAO,WAAW;AAAA,IACzB;AAAA,EACF;AACF;AAEA,eAAsB,oBACpB,SAC2B;AAC3B,QAAM,SAAmB,CAAC;AAE1B,QAAM,SAAS,KAAK,SAAS,KAAK;AAClC,MAAI,CAAE,MAAM,WAAW,MAAM,GAAI;AAC/B,WAAO,KAAK,yCAAyC;AACrD,WAAO,EAAE,OAAO,OAAO,OAAO;AAAA,EAChC;AAEA,QAAM,YAAY,KAAK,QAAQ,YAAY;AAC3C,MAAI,CAAE,MAAM,WAAW,SAAS,GAAI;AAClC,WAAO,KAAK,yBAAyB;AAAA,EACvC;AAEA,SAAO;AAAA,IACL,OAAO,OAAO,WAAW;AAAA,IACzB;AAAA,EACF;AACF;AArEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACWA,OAAOG,UAAS;AAEhB,eAAsB,aACpB,QACA,QACA,WACe;AACf,QAAM,UAAU,SAAS;AAEzB,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,YAAM,mBAAmB,QAAQ,SAAS;AAC1C;AAAA,IACF,KAAK;AACH,YAAM,kBAAkB,QAAQ,SAAS;AACzC;AAAA,IACF,KAAK,MAAM;AACT,YAAM,SAAS,QAAQ,IAAI;AAC3B,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AACA,YAAM,eAAe,QAAQ,WAAW,MAAM;AAC9C;AAAA,IACF;AAAA,EACF;AAGA,QAAM,aAAa,MAAM,sBAAsB,SAAS;AACxD,MAAI,CAAC,WAAW,OAAO;AACrB,WAAO,KAAK,4BAA4B;AACxC,eAAW,OAAO,WAAW,QAAQ;AACnC,aAAO,KAAK,KAAK,GAAG,EAAE;AAAA,IACxB;AAAA,EAEF;AACF;AAEA,eAAsB,UAAU,SAAmC;AACjE,QAAM,UAAUA,KAAI,4BAA4B,EAAE,MAAM;AAExD,MAAI;AACF,UAAM,IAAI,OAAO,CAAC,SAAS,GAAG,EAAE,KAAK,QAAQ,CAAC;AAC9C,YAAQ,OAAO;AACf,UAAM,IAAI,OAAO,CAAC,OAAO,OAAO,GAAG,EAAE,KAAK,QAAQ,CAAC;AACnD,YAAQ,QAAQ,yBAAyB;AAAA,EAC3C,SAAS,OAAY;AACnB,YAAQ,KAAK,cAAc;AAC3B,WAAO,MAAM,MAAM,UAAU,MAAM,WAAW,OAAO,KAAK,CAAC;AAC3D,WAAO;AAAA,EACT;AAGA,QAAM,aAAa,MAAM,oBAAoB,OAAO;AACpD,MAAI,CAAC,WAAW,OAAO;AACrB,WAAO,MAAM,iCAAiC;AAC9C,eAAW,OAAO,WAAW,QAAQ;AACnC,aAAO,MAAM,KAAK,GAAG,EAAE;AAAA,IACzB;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AA3EA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AAIA;AACA;AACA;AAAA;AAAA;;;ACLA,eAAsB,UACpB,UACkB;AAClB,MAAI,aAAa,QAAS,QAAO;AAEjC,MAAI;AACF,QAAI,aAAa,cAAc;AAC7B,YAAM,cAAc,OAAO,CAAC,YAAY,QAAQ,CAAC;AACjD,aAAO;AAAA,IACT;AACA,QAAI,aAAa,UAAU;AACzB,YAAM,cAAc,OAAO,CAAC,UAAU,QAAQ,CAAC;AAC/C,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,eAAsB,MAAM,UAAyC;AACnE,MAAI,aAAa,cAAc;AAC7B,WAAO,KAAK,wCAAwC;AACpD,UAAM,IAAI,OAAO,CAAC,YAAY,OAAO,GAAG,EAAE,OAAO,UAAU,CAAC;AAAA,EAC9D,WAAW,aAAa,UAAU;AAChC,WAAO,KAAK,oCAAoC;AAChD,UAAM,IAAI,OAAO,CAAC,UAAU,OAAO,GAAG,EAAE,OAAO,UAAU,CAAC;AAAA,EAC5D;AACF;AAEA,eAAsB,WAAW,UAAyC;AACxE,MAAI,aAAa,QAAS;AAE1B,QAAM,WAAW,MAAM,UAAU,QAAQ;AACzC,MAAI,CAAC,UAAU;AACb,UAAM,MAAM,QAAQ;AAEpB,UAAM,YAAY,MAAM,UAAU,QAAQ;AAC1C,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,6BAA6B,QAAQ,EAAE;AAAA,IACzD;AAAA,EACF;AACF;AA9CA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;;;ACCA,OAAOC,UAAS;AAEhB,eAAsB,mBACpB,SACA,aACiB;AACjB,QAAM,UAAUA,KAAI,kCAAkC,EAAE,MAAM;AAE9D,MAAI;AACF,UAAM,SAAS,MAAM,cAAc,OAAO;AAAA,MACxC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,kBAAkB,WAAW;AAAA,IAC/B,CAAC;AAGD,UAAM,WAAW,OAAO;AAAA,MACtB;AAAA,IACF;AACA,UAAM,MAAM,WAAW,CAAC,KAAK,WAAW,WAAW;AAEnD,YAAQ,QAAQ,8BAA8B;AAC9C,WAAO,KAAK,QAAQ,GAAG,EAAE;AAEzB,WAAO;AAAA,EACT,SAAS,OAAY;AACnB,YAAQ,KAAK,oCAAoC;AACjD,UAAM;AAAA,EACR;AACF;AAjCA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;;;ACCA,OAAOC,UAAS;AAEhB,eAAsB,eACpB,SACiB;AACjB,QAAM,UAAUA,KAAI,wBAAwB,EAAE,MAAM;AAEpD,MAAI;AACF,UAAM,SAAS,MAAM,cAAc,OAAO;AAAA,MACxC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAGD,UAAM,WAAW,OAAO;AAAA,MACtB;AAAA,IACF;AACA,UAAM,MAAM,WAAW,CAAC,KAAK,OAAO,KAAK,EAAE,MAAM,IAAI,EAAE,IAAI,KAAK;AAEhE,YAAQ,QAAQ,oBAAoB;AACpC,WAAO,KAAK,QAAQ,GAAG,EAAE;AAEzB,WAAO;AAAA,EACT,SAAS,OAAY;AACnB,YAAQ,KAAK,0BAA0B;AACvC,UAAM;AAAA,EACR;AACF;AAhCA;AAAA;AAAA;AAAA;AAAA;AACA;AAAA;AAAA;;;ACEA,YAAYC,QAAO;AAEnB,eAAsB,sBACpB,SACA,aACe;AACf,QAAM,QAAQ,MAAM,cAAc,IAAI;AACtC,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,MACL;AAAA,IACF;AACA;AAAA,EACF;AAEA,QAAM,cAAe,MAAQ,WAAQ;AAAA,IACnC,SAAS;AAAA,IACT,cAAc;AAAA,EAChB,CAAC;AAED,MAAM,YAAS,WAAW,KAAK,CAAC,YAAa;AAE7C,QAAM,aAAc,MAAQ,UAAO;AAAA,IACjC,SAAS;AAAA,IACT,SAAS;AAAA,MACP,EAAE,OAAO,WAAW,OAAO,UAAU;AAAA,MACrC,EAAE,OAAO,UAAU,OAAO,SAAS;AAAA,IACrC;AAAA,EACF,CAAC;AAED,MAAM,YAAS,UAAU,EAAG;AAE5B,MAAI;AAEF,UAAM,SAAS,KAAK,SAAS,MAAM;AACnC,QAAI,CAAE,MAAM,WAAW,MAAM,GAAI;AAC/B,YAAM,IAAI,OAAO,CAAC,MAAM,GAAG,EAAE,KAAK,QAAQ,CAAC;AAAA,IAC7C;AAGA,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK,UAAU;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,EAAE,KAAK,SAAS,OAAO,UAAU;AAAA,IACnC;AAEA,WAAO,QAAQ,8BAA8B,WAAW,EAAE;AAC1D,WAAO;AAAA,MACL;AAAA,IACF;AAAA,EACF,SAAS,OAAY;AACnB,WAAO,MAAM,wBAAwB,MAAM,OAAO,EAAE;AAAA,EACtD;AACF;AA/DA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AAAA;AAAA;;;ACIA,SAAS,QAAAC,aAAY;AAErB,eAAsB,OACpB,SACA,UACA,aACwB;AACxB,MAAI,aAAa,SAAS;AACxB,WAAO,KAAK,iBAAiBA,MAAK,SAAS,MAAM,CAAC,EAAE;AACpD,WAAO,KAAK,yDAAyD;AACrE,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,QAAQ;AAEzB,QAAM,UAAUA,MAAK,SAAS,KAAK;AACnC,MAAI;AAEJ,MAAI,aAAa,cAAc;AAC7B,UAAM,MAAM,mBAAmB,SAAS,WAAW;AAAA,EACrD,OAAO;AACL,UAAM,MAAM,eAAe,OAAO;AAAA,EACpC;AAGA,QAAM,sBAAsB,SAAS,WAAW;AAEhD,SAAO;AACT;AAlCA;AAAA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AAAA;AAAA;;;ACJA,SAAS,oBAAiC;AAC1C,SAAS,QAAAC,aAAY;AAErB,OAAOC,UAAS;AAEhB,eAAsB,UACpB,SACA,YACiB;AACjB,QAAM,UAAUD,MAAK,SAAS,KAAK;AACnC,QAAM,UAAU,cAAcA,MAAK,SAAS,eAAe;AAE3D,QAAM,UAAUC,KAAI,kBAAkB,EAAE,MAAM;AAG9C,QAAM,SAAS,MAAM,kBAAkB,OAAO;AAC9C,QAAM,OAAQ,OAAO,QAAQ,GAAW,QAAQ;AAEhD,MAAI;AAEF,UAAM,EAAE,SAAS,IAAI,MAAM,OAAO,YAAY;AAE9C,UAAM,UAAU,MAAM,SAAS,OAAO;AACtC,UAAM,OAAO,MAAM,QAAQ,QAAQ;AAEnC,UAAM,KAAK,KAAK,oBAAoB,IAAI,IAAI;AAAA,MAC1C,WAAW;AAAA,IACb,CAAC;AAGD,UAAM,KAAK,eAAe,GAAI;AAE9B,UAAM,KAAK,IAAI;AAAA,MACb,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,iBAAiB;AAAA,MACjB,QAAQ;AAAA,QACN,KAAK;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,MAAM;AAAA,MACR;AAAA,IACF,CAAC;AAED,UAAM,QAAQ,MAAM;AACpB,YAAQ,QAAQ,iBAAiB,OAAO,EAAE;AAC1C,WAAO;AAAA,EACT,SAAS,OAAY;AACnB,YAAQ,KAAK,mBAAmB;AAChC,QAAI,MAAM,SAAS,SAAS,oBAAoB,GAAG;AACjD,aAAO;AAAA,QACL;AAAA,MACF;AAAA,IACF,OAAO;AACL,aAAO,MAAM,MAAM,WAAW,OAAO,KAAK,CAAC;AAAA,IAC7C;AACA,UAAM;AAAA,EACR,UAAE;AACA,WAAO,MAAM;AAAA,EACf;AACF;AAEA,SAAS,kBAAkB,KAA8B;AACvD,SAAO,IAAI,QAAQ,OAAOC,UAAS,WAAW;AAC5C,UAAM,UAAU,MAAM,OAAO,eAAe;AAE5C,UAAM,SAAS,aAAa,CAAC,KAAK,QAAQ;AACxC,aAAO,QAAQ,QAAQ,KAAK,KAAK;AAAA,QAC/B,QAAQ;AAAA,QACR,WAAW;AAAA,MACb,CAAC;AAAA,IACH,CAAC;AAED,WAAO,OAAO,GAAG,MAAM;AACrB,MAAAA,SAAQ,MAAM;AAAA,IAChB,CAAC;AAED,WAAO,GAAG,SAAS,MAAM;AAAA,EAC3B,CAAC;AACH;AAEA,eAAsB,mBACpB,SACA,OAAe,KACE;AACjB,QAAM,UAAUF,MAAK,SAAS,KAAK;AACnC,QAAM,UAAU,MAAM,OAAO,eAAe;AAE5C,QAAM,SAAS,aAAa,CAAC,KAAK,QAAQ;AACxC,WAAO,QAAQ,QAAQ,KAAK,KAAK;AAAA,MAC/B,QAAQ;AAAA,MACR,WAAW;AAAA,IACb,CAAC;AAAA,EACH,CAAC;AAED,SAAO,IAAI,QAAQ,CAACE,UAAS,WAAW;AACtC,WAAO,OAAO,MAAM,MAAM;AACxB,aAAO,KAAK,6BAA6B,IAAI,EAAE;AAC/C,MAAAA,SAAQ,MAAM;AAAA,IAChB,CAAC;AACD,WAAO,GAAG,SAAS,MAAM;AAAA,EAC3B,CAAC;AACH;AAtGA;AAAA;AAAA;AAAA;AAEA;AAAA;AAAA;;;ACFA;AAAA;AAAA;AAAA;AAAA,SAAS,eAAe;AAYxB,SAAS,QAAAC,aAAY;AACrB,YAAYC,QAAO;AAenB,eAAsB,YAAY,SAAqC;AACrE,SAAO,OAAO,kBAAkB;AAGhC,SAAO,KAAK,yBAAyB;AACrC,QAAM,UAAU,MAAM,cAAc;AACpC,QAAM,iBAAiB,wBAAwB,OAAO;AAEtD,MAAI,eAAe,WAAW,GAAG;AAC/B,WAAO,MAAM,qBAAqB;AAClC,WAAO,MAAM,EAAE;AACf,WAAO,MAAM,4CAA4C;AACzD,WAAO,MAAM,6DAA6D;AAC1E,WAAO,MAAM,iDAAiD;AAC9D,WAAO,MAAM,wDAAwD;AACrE,WAAO,MAAM,EAAE;AACf,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,SAAO;AAAA,IACL,sBAAsB,eAAe,KAAK,IAAI,CAAC;AAAA,EACjD;AAGA,QAAM,WAAW,QAAQ,MAAM,IAAI,CAAC,MAAM,QAAQ,CAAC,CAAC,KAAK;AAAA,IACvD,QAAQ,QAAQ,IAAI,CAAC;AAAA,EACvB;AACA,QAAM,kBAAkB,MAAM,aAAa,QAAQ;AAEnD,MAAI,gBAAgB,WAAW,GAAG;AAChC,WAAO,MAAM,+DAA+D;AAC5E,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,SAAO,OAAO,SAAS,gBAAgB,MAAM,YAAY;AACzD,QAAM,YAAY,gBAAgB,IAAI,CAAC,SAAS;AAAA,IAC9C,KAAK;AAAA,IACL,KAAK,UAAU,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI;AAAA,IACpC,KAAK,iBAAiB,MAAM,GAAG,EAAE,KAAK;AAAA,IACtC,GAAG,KAAK,YAAY;AAAA,EACtB,CAAC;AACD,SAAO,MAAM,SAAS;AACtB,SAAO,MAAM;AAGb,QAAM,kBAAkB,MAAM,aAAa,iBAAiB,cAAc;AAG1E,QAAM,OAAO,UAAU,eAAe;AAGtC,QAAM,SAAS,MAAM,iBAAiB,IAAI;AAG1C,QAAM,YAAY,QAAQ,QAAQ,UAAU,kBAAkB;AAC9D,QAAM,UAAU,SAAS;AAEzB,QAAM,aAAa,KAAK,QAAQ,QAAQ,SAAS;AAGjD,MAAI,eAAe,MAAM,UAAU,SAAS;AAC5C,MAAI,CAAC,cAAc;AACjB,WAAO,KAAK,qBAAqB;AACjC,mBAAe,MAAM,UAAU,SAAS;AACxC,QAAI,CAAC,cAAc;AACjB,aAAO,MAAM,mEAAmE;AAChF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAGA,MAAI,CAAC,QAAQ,WAAW;AACtB,UAAM,SAAS,MAAM,mBAAmB,SAAS;AACjD,WAAO,MAAM;AAEb,UAAM,UAAW,MAAQ,WAAQ;AAAA,MAC/B,SAAS;AAAA,MACT,cAAc;AAAA,IAChB,CAAC;AAED,WAAO,MAAM;AAEb,QAAM,YAAS,OAAO,KAAK,CAAC,SAAS;AACnC,UAAI,KAAK,OAAO,aAAa,SAAS;AAAA,MAEtC,OAAO;AACL,eAAO,KAAK,oDAAoD;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AAGA,MAAI,CAAC,QAAQ,OAAO;AAClB,QAAI;AACF,YAAM,UAAU,SAAS;AAAA,IAC3B,QAAQ;AACN,aAAO,KAAK,kCAAkC;AAAA,IAChD;AAAA,EACF;AAGA,MAAI,KAAK,OAAO,aAAa,SAAS;AACpC,UAAM,MAAM,MAAM;AAAA,MAChB;AAAA,MACA,KAAK,OAAO;AAAA,MACZ,KAAK,OAAO;AAAA,IACd;AACA,QAAI,KAAK;AACP,WAAK,OAAO,MAAM;AAAA,IACpB;AAAA,EACF;AAGA,QAAM,UAAUD,MAAK,WAAW,uBAAuB,GAAG;AAAA,IACxD,GAAG;AAAA,IACH,UAAU;AAAA,EACZ,CAAC;AAGD,SAAO,OAAO,OAAO;AACrB,MAAI,KAAK,OAAO,KAAK;AACnB,WAAO,KAAK,SAAS,KAAK,OAAO,GAAG,EAAE;AAAA,EACxC;AACA,SAAO,KAAK,UAAU,SAAS,EAAE;AACjC,SAAO;AAAA,IACL,uCAAuC,SAAS;AAAA,EAClD;AACF;AA5JA;AAAA;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;;;ACXA;AACA;AADA,SAAS,eAAe;;;ACAxB;AACA;AADA,SAAS,WAAAE,gBAAe;;;ACAxB;AAQO,SAAS,YACd,WACA,SACU;AACV,QAAM,gBAAgB,IAAI;AAAA,IACxB,UAAU,SAAS,IAAI,CAACC,OAAM,CAACA,GAAE,WAAWA,EAAC,CAAC;AAAA,EAChD;AACA,QAAM,gBAAgB,IAAI,IAAI,QAAQ,IAAI,CAACA,OAAM,CAACA,GAAE,WAAWA,EAAC,CAAC,CAAC;AAElE,QAAM,cAA6B,CAAC;AACpC,QAAM,kBAAmC,CAAC;AAC1C,QAAM,kBAAkC,CAAC;AACzC,QAAM,oBAAoC,CAAC;AAG3C,aAAW,CAACC,OAAM,IAAI,KAAK,eAAe;AACxC,UAAM,aAAa,cAAc,IAAIA,KAAI;AACzC,QAAI,CAAC,YAAY;AACf,kBAAY,KAAK,IAAI;AAAA,IACvB,WAAW,KAAK,sBAAsB,WAAW,mBAAmB;AAClE,YAAM,aAAa,KAAK,eAAe,WAAW;AAClD,sBAAgB,KAAK;AAAA,QACnB,SAAS;AAAA,QACT,YAAY,KAAK,IAAI,YAAY,CAAC;AAAA,QAClC,eAAe,KAAK,kBAAkB,WAAW;AAAA,QACjD,aACE,KAAK,UAAU,KAAK,SAAS,MAC7B,KAAK,UAAU,WAAW,SAAS;AAAA,MACvC,CAAC;AAAA,IACH,OAAO;AACL,wBAAkB,KAAK,UAAU;AAAA,IACnC;AAAA,EACF;AAGA,aAAW,CAACA,OAAM,OAAO,KAAK,eAAe;AAC3C,QAAI,CAAC,cAAc,IAAIA,KAAI,GAAG;AAC5B,sBAAgB,KAAK,OAAO;AAAA,IAC9B;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ADpDA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA,YAAYC,QAAO;AAUnB,eAAsB,cAAc,SAAuC;AACzE,SAAO,OAAO,kBAAkB;AAEhC,QAAM,UAAUC,SAAQ,QAAQ,IAAI;AACpC,QAAM,aAAa,KAAK,SAAS,uBAAuB;AAGxD,MAAI,CAAE,MAAM,WAAW,UAAU,GAAI;AACnC,WAAO;AAAA,MACL;AAAA,IACF;AACA,UAAM,QAAS,MAAQ,WAAQ;AAAA,MAC7B,SAAS;AAAA,MACT,cAAc;AAAA,IAChB,CAAC;AAED,QAAM,YAAS,KAAK,KAAK,CAAC,OAAO;AAC/B,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,UAAM,EAAE,aAAAC,aAAY,IAAI,MAAM;AAC9B,UAAMA,aAAY,EAAE,QAAQ,QAAQ,CAAC;AACrC;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,SAA0B,UAAU;AACzD,SAAO;AAAA,IACL,SAAS,OAAO,OAAO,eAAe,OAAO,eAAe,OAAO,YAAY,MAAM,GAAG,EAAE,CAAC;AAAA,EAC7F;AACA,SAAO,KAAK,UAAU,OAAO,MAAM,KAAK,EAAE;AAC1C,SAAO,KAAK,aAAa,OAAO,SAAS,MAAM,EAAE;AAGjD,QAAM,UAAU,MAAM,cAAc;AACpC,QAAM,iBAAiB,wBAAwB,OAAO;AACtD,MAAI,eAAe,WAAW,GAAG;AAC/B,WAAO,MAAM,mEAAmE;AAChF,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,WAAW,QAAQ,MAAM,IAAI,CAAC,MAAMD,SAAQ,CAAC,CAAC,KAClD,CAAC,GAAG,IAAI,IAAI,OAAO,SAAS,IAAI,CAACD,OAAM;AACrC,UAAM,QAAQA,GAAE,UAAU,MAAM,GAAG;AACnC,UAAM,IAAI;AACV,WAAO,MAAM,KAAK,GAAG;AAAA,EACvB,CAAC,CAAC,CAAC;AAEL,QAAM,kBAAkB,MAAM,aAAa,QAAQ;AACnD,QAAM,OAAO,YAAY,QAAQ,eAAe;AAGhD,SAAO,OAAO,mBAAmB;AAEjC,MAAI,KAAK,YAAY,SAAS,GAAG;AAC/B,WAAO,MAAM,QAAQ;AACrB,eAAW,QAAQ,KAAK,aAAa;AACnC,aAAO,MAAM,SAAS,KAAK,IAAI,OAAO,KAAK,UAAU,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,IAC/E;AAAA,EACF;AAEA,MAAI,KAAK,gBAAgB,SAAS,GAAG;AACnC,WAAO,MAAM,YAAY;AACzB,eAAW,OAAO,KAAK,iBAAiB;AACtC,aAAO;AAAA,QACL,SAAS,IAAI,QAAQ,IAAI,OAAO,IAAI,UAAU;AAAA,MAChD;AAAA,IACF;AAAA,EACF;AAEA,MAAI,KAAK,gBAAgB,SAAS,GAAG;AACnC,WAAO,MAAM,YAAY;AACzB,eAAW,QAAQ,KAAK,iBAAiB;AACvC,aAAO,MAAM,SAAS,KAAK,IAAI,sBAAsB;AAAA,IACvD;AAAA,EACF;AAEA,MACE,KAAK,YAAY,WAAW,KAC5B,KAAK,gBAAgB,WAAW,KAChC,KAAK,gBAAgB,WAAW,GAChC;AACA,WAAO,KAAK,sBAAsB;AAClC;AAAA,EACF;AAGA,QAAM,UAAW,MAAQ,WAAQ;AAAA,IAC/B,SAAS;AAAA,IACT,cAAc;AAAA,EAChB,CAAC;AAED,MAAM,YAAS,OAAO,KAAK,CAAC,SAAS;AACnC,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,SAAS,eAAe,SAAS,OAAO,MAAM,IAChD,OAAO,SACP,eAAe,CAAC;AAEpB,QAAM,SAAS,MAAM,kBAAkB,QAAQ,IAAI;AAGnD,QAAM,aAAa,QAAQ,QAAQ,OAAO;AAG1C,QAAM,eAAe,MAAM,UAAU,OAAO;AAC5C,MAAI,CAAC,cAAc;AACjB,WAAO,MAAM,yCAAyC;AACtD,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,MAAI,CAAC,QAAQ,WAAW;AACtB,UAAM,SAAS,MAAM,mBAAmB,OAAO;AAC/C,UAAM,KAAM,MAAQ,WAAQ;AAAA,MAC1B,SAAS;AAAA,MACT,cAAc;AAAA,IAChB,CAAC;AACD,WAAO,MAAM;AACb,QAAM,YAAS,EAAE,KAAK,CAAC,IAAI;AACzB,aAAO,KAAK,8BAA8B;AAC1C;AAAA,IACF;AAAA,EACF;AAGA,MAAI,CAAC,QAAQ,OAAO;AAClB,QAAI;AACF,YAAM,UAAU,OAAO;AAAA,IACzB,QAAQ;AACN,aAAO,KAAK,qBAAqB;AAAA,IACnC;AAAA,EACF;AAGA,MAAI,CAAC,QAAQ,YAAY,OAAO,OAAO,aAAa,SAAS;AAC3D,UAAM,OAAO,SAAS,OAAO,OAAO,UAAU,OAAO,OAAO,WAAW;AAAA,EACzE;AAGA,QAAM,gBAAiC;AAAA,IACrC,GAAG;AAAA,IACH,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC,UAAU;AAAA,MACR,GAAG,KAAK;AAAA,MACR,GAAG,KAAK,gBAAgB,IAAI,CAAC,MAAM;AACjC,cAAM,WAAW,OAAO,SAAS;AAAA,UAC/B,CAACA,OAAMA,GAAE,cAAc,EAAE,QAAQ;AAAA,QACnC;AACA,eAAO;AAAA,UACL,GAAG,EAAE;AAAA,UACL,UAAU;AAAA,UACV,qBAAqB,UAAU,uBAAuB;AAAA,UACtD,gBAAgB,UAAU,kBAAkB,CAAC,CAAC,EAAE,QAAQ;AAAA,UACxD,MAAM,UAAU,QAAQ;AAAA,UACxB,SAAS,UAAU,WAAW,CAAC;AAAA,QACjC;AAAA,MACF,CAAC;AAAA,MACD,GAAG,KAAK,YAAY;AAAA,QAClB,CAAC,UACE;AAAA,UACC,GAAG;AAAA,UACH,UAAU;AAAA,UACV,qBAAqB;AAAA,UACrB,gBAAgB,CAAC,CAAC,KAAK;AAAA,UACvB,MAAM;AAAA,UACN,SAAS,CAAC;AAAA,QACZ;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,KAAK,SAAS,uBAAuB,GAAG,aAAa;AACrE,SAAO,QAAQ,kBAAkB;AACnC;;;AEtMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA,SAAS,WAAAG,gBAAe;AAcxB,eAAsB,YAAY,SAAqC;AACrE,SAAO,OAAO,gBAAgB;AAG9B,QAAM,UAAU,MAAM,cAAc;AACpC,QAAM,iBAAiB,wBAAwB,OAAO;AAItD,QAAM,cACJ,eAAe,SAAS,IAAI,iBAAkB,CAAC,QAAQ;AAGzD,QAAM,WAAW,QAAQ,MAAM,IAAI,CAAC,MAAMA,SAAQ,CAAC,CAAC,KAAK;AAAA,IACvDA,SAAQ,QAAQ,IAAI,CAAC;AAAA,EACvB;AACA,QAAM,kBAAkB,MAAM,aAAa,QAAQ;AAEnD,MAAI,gBAAgB,WAAW,GAAG;AAChC,WAAO,MAAM,oBAAoB;AACjC,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,SAAO,KAAK,SAAS,gBAAgB,MAAM,WAAW;AAGtD,QAAM,kBAAkB,MAAM;AAAA,IAC5B;AAAA,IACA,CAAC,GAAG,WAAW;AAAA,EACjB;AAGA,QAAM,OAAO,UAAU,eAAe;AAGtC,QAAM,SAAS,MAAM,iBAAiB,IAAI;AAG1C,QAAM,YAAY,QAAQ,UAAU;AACpC,QAAM,WAAWA,SAAQ,WAAW,qBAAqB;AACzD,QAAM,aAAaA,SAAQ,WAAW,qBAAqB;AAE3D,QAAM,UAAU,UAAU,IAAI;AAC9B,QAAM,UAAU,YAAY,MAAM;AAElC,SAAO,QAAQ,eAAe,QAAQ,EAAE;AACxC,SAAO,QAAQ,iBAAiB,UAAU,EAAE;AAC5C,SAAO,MAAM;AACb,SAAO;AAAA,IACL;AAAA,EACF;AACF;;;ACjEA;AACA;AACA;AACA;AAHA,SAAS,WAAAC,gBAAe;AAKxB,YAAYC,QAAO;AAOnB,eAAsB,cAAc,SAAuC;AACzE,QAAM,UAAUD,SAAQ,QAAQ,IAAI;AACpC,QAAM,aAAa,KAAK,SAAS,uBAAuB;AAExD,MAAI;AACJ,MAAI;AAEJ,MAAI,MAAM,WAAW,UAAU,GAAG;AAChC,UAAM,SAAS,MAAM,SAA0B,UAAU;AACzD,eACG,QAAQ,YAA+B,OAAO,OAAO;AACxD,kBAAc,OAAO,OAAO;AAAA,EAC9B,OAAO;AACL,eAAY,QAAQ,YAA+B;AACnD,kBAAe,MAAQ,QAAK;AAAA,MAC1B,SAAS;AAAA,MACT,UAAU,CAAC,MACT,eAAe,KAAK,CAAC,IACjB,SACA;AAAA,IACR,CAAC;AAED,QAAM,YAAS,WAAW,EAAG,SAAQ,KAAK,CAAC;AAAA,EAC7C;AAEA,MAAI,aAAa,SAAS;AACxB,WAAO,KAAK,qDAAqD;AACjE;AAAA,EACF;AAEA,QAAM,SAAS,KAAK,SAAS,KAAK;AAClC,MAAI,CAAE,MAAM,WAAW,MAAM,GAAI;AAC/B,WAAO,MAAM,0EAA0E;AACvF,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,OAAS,SAAS,UAAU,WAAW;AAC/C;;;ACjDA;AACA;AACA;AACA;AAHA,SAAS,WAAAE,gBAAe;AAUxB,eAAsB,WAAW,SAAoC;AACnE,QAAM,UAAUA,SAAQ,QAAQ,IAAI;AACpC,QAAM,SAAS,KAAK,SAAS,KAAK;AAElC,MAAI,CAAE,MAAM,WAAW,MAAM,GAAI;AAC/B,WAAO;AAAA,MACL;AAAA,IACF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,UAAU,SAAS,QAAQ,MAAM;AACzC;;;ACtBA;AACA;AACA;AACA;AAHA,SAAS,WAAAC,gBAAe;AAUxB,eAAsB,eAAe,SAAwC;AAC3E,QAAM,UAAUA,SAAQ,QAAQ,IAAI;AACpC,QAAM,SAAS,KAAK,SAAS,KAAK;AAElC,MAAI,CAAE,MAAM,WAAW,MAAM,GAAI;AAC/B,WAAO;AAAA,MACL;AAAA,IACF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,QAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAM,mBAAmB,SAAS,IAAI;AACtC,SAAO,KAAK,uBAAuB;AAGnC,QAAM,IAAI,QAAQ,MAAM;AAAA,EAAC,CAAC;AAC5B;;;ANnBA,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,WAAW,EAChB;AAAA,EACC;AACF,EACC,QAAQ,OAAO;AAGlB,QACG,QAAQ,QAAQ,EAAE,WAAW,KAAK,CAAC,EACnC,YAAY,+BAA+B,EAC3C,OAAO,wBAAwB,kCAAkC,EACjE,OAAO,yBAAyB,gCAAgC,EAChE,OAAO,2BAA2B,4CAA4C,EAC9E,OAAO,mBAAmB,gDAAgD,EAC1E,OAAO,kBAAkB,oBAAoB,EAC7C,OAAO,UAAU,4BAA4B,EAC7C,OAAO,sBAAsB,oBAAoB,kBAAkB,EACnE,OAAO,YAAY,iBAAiB,EACpC,OAAO,gBAAgB,oBAAoB,EAC3C,OAAO,iBAAiB,gBAAgB,EACxC,OAAO,WAAW;AAGrB,QACG,QAAQ,QAAQ,EAChB,YAAY,mCAAmC,EAC/C,eAAe,iBAAiB,iCAAiC,EACjE,OAAO,wBAAwB,kCAAkC,EACjE,OAAO,YAAY,iBAAiB,EACpC,OAAO,gBAAgB,cAAc,EACrC,OAAO,eAAe,iBAAiB,EACvC,OAAO,aAAa;AAGvB,QACG,QAAQ,MAAM,EACd,YAAY,qCAAqC,EACjD,OAAO,wBAAwB,kCAAkC,EACjE,OAAO,sBAAsB,mCAAmC,GAAG,EACnE,OAAO,WAAW;AAGrB,QACG,QAAQ,QAAQ,EAChB,YAAY,+BAA+B,EAC3C,eAAe,iBAAiB,wBAAwB,EACxD,OAAO,6BAA6B,sCAAsC,EAC1E,OAAO,aAAa;AAGvB,QACG,QAAQ,KAAK,EACb,YAAY,oBAAoB,EAChC,eAAe,iBAAiB,wBAAwB,EACxD,OAAO,uBAAuB,iBAAiB,EAC/C,OAAO,UAAU;AAGpB,QACG,QAAQ,SAAS,EACjB,YAAY,4BAA4B,EACxC,eAAe,iBAAiB,wBAAwB,EACxD,OAAO,iBAAiB,eAAe,MAAM,EAC7C,OAAO,CAAC,SAAS,eAAe,EAAE,GAAG,MAAM,MAAM,SAAS,KAAK,IAAI,EAAE,CAAC,CAAC;AAE1E,QAAQ,MAAM;","names":["glob","path","p","glob","p","readFile","join","fileURLToPath","p","execa","ora","execa","ora","writeFile","mkdir","join","dirname","ora","ora","ora","ora","p","join","join","ora","resolve","join","p","resolve","p","path","p","resolve","initCommand","resolve","resolve","p","resolve","resolve"]}
@@ -367,34 +367,68 @@ var logger = {
367
367
  // src/scanner/index.ts
368
368
  import ora from "ora";
369
369
  async function scanProjects(directories) {
370
- const allRepos = [];
370
+ const allPaths = [];
371
371
  const spinner = ora("Scanning for projects...").start();
372
372
  for (const dir of directories) {
373
373
  try {
374
374
  const repos = await findGitRepos(dir);
375
- allRepos.push(...repos);
375
+ allPaths.push(...repos);
376
+ const nonGitDirs = await findNonGitProjects(dir, new Set(repos));
377
+ allPaths.push(...nonGitDirs);
376
378
  } catch (err) {
377
379
  logger.warn(`Could not scan ${dir}: ${err}`);
378
380
  }
379
381
  }
380
- const uniqueRepos = [...new Set(allRepos)];
381
- spinner.text = `Found ${uniqueRepos.length} repositories. Extracting metadata...`;
382
+ const uniquePaths = [...new Set(allPaths)];
383
+ spinner.text = `Found ${uniquePaths.length} projects. Extracting metadata...`;
382
384
  const projects = [];
383
- for (const repoPath of uniqueRepos) {
385
+ for (const projectPath of uniquePaths) {
384
386
  try {
385
- const project = await extractProjectMeta(repoPath);
387
+ const project = await extractProjectMeta(projectPath);
386
388
  if (project) {
387
389
  projects.push(project);
388
390
  }
389
391
  } catch (err) {
390
392
  }
391
393
  }
394
+ const idCounts = /* @__PURE__ */ new Map();
395
+ for (const project of projects) {
396
+ const count = idCounts.get(project.id) || 0;
397
+ if (count > 0) {
398
+ project.id = `${project.id}-${count}`;
399
+ }
400
+ idCounts.set(project.id.replace(/-\d+$/, ""), count + 1);
401
+ }
392
402
  spinner.succeed(`Scanned ${projects.length} projects`);
393
403
  return projects;
394
404
  }
405
+ async function findNonGitProjects(rootPath, gitRepos) {
406
+ const { glob: glob2 } = await import("glob");
407
+ const indicators = [
408
+ "*/package.json",
409
+ "*/Cargo.toml",
410
+ "*/go.mod",
411
+ "*/pyproject.toml",
412
+ "*/requirements.txt",
413
+ "*/setup.py"
414
+ ];
415
+ const found = /* @__PURE__ */ new Set();
416
+ for (const pattern of indicators) {
417
+ const matches = await glob2(pattern, {
418
+ cwd: rootPath,
419
+ ignore: ["**/node_modules/**", "**/vendor/**"]
420
+ });
421
+ for (const match of matches) {
422
+ const dir = `${rootPath}/${match.split("/")[0]}`;
423
+ if (!gitRepos.has(dir) && !found.has(dir)) {
424
+ found.add(dir);
425
+ }
426
+ }
427
+ }
428
+ return [...found].sort();
429
+ }
395
430
  async function extractProjectMeta(projectPath) {
396
431
  const gitMeta = await getGitMeta(projectPath);
397
- if (!gitMeta.isRepo) return null;
398
432
  let techStack = [];
399
433
  let name = null;
400
434
  let description = null;
@@ -434,7 +468,8 @@ async function extractProjectMeta(projectPath) {
434
468
  if (!name) {
435
469
  name = deriveNameFromPath(projectPath);
436
470
  }
437
- const id = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
471
+ const folderName = deriveNameFromPath(projectPath);
472
+ const id = folderName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
438
473
  return {
439
474
  id,
440
475
  name,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/scanner/git.ts","../../../src/utils/fs.ts","../../../src/scanner/detectors/node.ts","../../../src/scanner/detectors/python.ts","../../../src/scanner/detectors/rust.ts","../../../src/scanner/detectors/go.ts","../../../src/scanner/detectors/generic.ts","../../../src/scanner/extractors.ts","../../../src/utils/logger.ts","../../../src/scanner/index.ts"],"sourcesContent":["import simpleGit from \"simple-git\";\nimport { basename } from \"node:path\";\n\nexport interface GitMeta {\n isRepo: boolean;\n firstCommitDate: string | null;\n lastCommitDate: string | null;\n totalCommits: number;\n remoteUrl: string | null;\n lastCommitHash: string | null;\n}\n\nexport async function getGitMeta(projectPath: string): Promise<GitMeta> {\n const git = simpleGit(projectPath);\n const empty: GitMeta = {\n isRepo: false,\n firstCommitDate: null,\n lastCommitDate: null,\n totalCommits: 0,\n remoteUrl: null,\n lastCommitHash: null,\n };\n\n try {\n const isRepo = await git.checkIsRepo();\n if (!isRepo) return empty;\n } catch {\n return empty;\n }\n\n try {\n const log = await git.log({ maxCount: 1 });\n\n // Get first commit date\n let firstCommitDate: string | null = null;\n try {\n const firstResult = await git.raw([\"log\", \"--reverse\", \"--format=%aI\", \"--max-count=1\"]);\n firstCommitDate = firstResult.trim() || null;\n } catch {\n // ignore\n }\n\n let remoteUrl: string | null = null;\n try {\n const remotes = await git.getRemotes(true);\n const origin = remotes.find((r) => r.name === \"origin\");\n if (origin?.refs?.fetch) {\n remoteUrl = normalizeGitUrl(origin.refs.fetch);\n }\n } catch {\n // no remotes\n }\n\n // Get total commit count\n let totalCommits = 0;\n try {\n const result = await git.raw([\"rev-list\", \"--count\", \"HEAD\"]);\n totalCommits = parseInt(result.trim(), 10) || 0;\n } catch {\n totalCommits = 0;\n }\n\n return {\n isRepo: true,\n firstCommitDate,\n lastCommitDate: log.latest?.date || null,\n totalCommits,\n remoteUrl,\n lastCommitHash: log.latest?.hash || null,\n };\n } catch {\n return { ...empty, isRepo: true };\n }\n}\n\nfunction normalizeGitUrl(url: string): string {\n // Convert SSH to HTTPS\n if (url.startsWith(\"git@\")) {\n url = url.replace(\":\", \"/\").replace(\"git@\", \"https://\");\n }\n // Remove .git suffix\n if (url.endsWith(\".git\")) {\n url = url.slice(0, -4);\n }\n return url;\n}\n\nexport async function findGitRepos(\n rootPath: string,\n maxDepth: number = 3\n): Promise<string[]> {\n const { glob } = await import(\"glob\");\n const gitDirs = await glob(\"**/.git\", {\n cwd: rootPath,\n maxDepth: maxDepth + 1,\n dot: true,\n ignore: [\n \"**/node_modules/**/.git\",\n \"**/vendor/**/.git\",\n \"**/__pycache__/**/.git\",\n ],\n });\n\n return gitDirs\n .map((gitDir) => {\n const parts = gitDir.split(\"/\");\n parts.pop(); // remove .git\n return parts.length > 0\n ? `${rootPath}/${parts.join(\"/\")}`\n : rootPath;\n })\n .sort();\n}\n","import { readFile, writeFile, access, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport async function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function readJson<T = unknown>(path: string): Promise<T> {\n const content = await readFile(path, \"utf-8\");\n return JSON.parse(content) as T;\n}\n\nexport async function writeJson(path: string, data: unknown): Promise<void> {\n await writeFile(path, JSON.stringify(data, null, 2), \"utf-8\");\n}\n\nexport async function readText(path: string): Promise<string> {\n return readFile(path, \"utf-8\");\n}\n\nexport async function writeText(path: string, content: string): Promise<void> {\n await writeFile(path, content, \"utf-8\");\n}\n\nexport async function ensureDir(path: string): Promise<void> {\n await mkdir(path, { recursive: true });\n}\n\nexport { join };\n","import { fileExists, readJson, join } from \"../../utils/fs.js\";\n\ninterface PackageJson {\n name?: string;\n description?: string;\n homepage?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nexport async function detectNode(projectPath: string) {\n const pkgPath = join(projectPath, \"package.json\");\n if (!(await fileExists(pkgPath))) return null;\n\n const pkg = await readJson<PackageJson>(pkgPath);\n const allDeps = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n const depNames = Object.keys(allDeps);\n\n const techStack: string[] = [];\n\n // Frameworks\n if (depNames.includes(\"next\")) techStack.push(\"Next.js\");\n else if (depNames.includes(\"nuxt\")) techStack.push(\"Nuxt\");\n else if (depNames.includes(\"astro\")) techStack.push(\"Astro\");\n else if (depNames.includes(\"svelte\") || depNames.includes(\"@sveltejs/kit\"))\n techStack.push(\"Svelte\");\n\n // UI libraries\n if (depNames.includes(\"react\")) techStack.push(\"React\");\n if (depNames.includes(\"vue\")) techStack.push(\"Vue\");\n\n // Styling\n if (depNames.includes(\"tailwindcss\")) techStack.push(\"Tailwind CSS\");\n\n // Backend\n if (depNames.includes(\"express\")) techStack.push(\"Express\");\n if (depNames.includes(\"fastify\")) techStack.push(\"Fastify\");\n if (depNames.includes(\"hono\")) techStack.push(\"Hono\");\n\n // Database\n if (depNames.includes(\"prisma\") || depNames.includes(\"@prisma/client\"))\n techStack.push(\"Prisma\");\n if (depNames.includes(\"drizzle-orm\")) techStack.push(\"Drizzle\");\n if (depNames.includes(\"mongoose\")) techStack.push(\"MongoDB\");\n\n // AI/ML\n if (depNames.includes(\"openai\")) techStack.push(\"OpenAI\");\n if (depNames.includes(\"@anthropic-ai/sdk\")) techStack.push(\"Claude API\");\n if (depNames.includes(\"langchain\")) techStack.push(\"LangChain\");\n\n // Language\n if (depNames.includes(\"typescript\")) techStack.push(\"TypeScript\");\n else techStack.push(\"JavaScript\");\n\n return {\n name: pkg.name || null,\n description: pkg.description || null,\n homepage: pkg.homepage || null,\n techStack,\n };\n}\n","import { fileExists, readText, join } from \"../../utils/fs.js\";\n\nexport async function detectPython(projectPath: string) {\n const techStack: string[] = [\"Python\"];\n\n const reqPath = join(projectPath, \"requirements.txt\");\n const pyprojectPath = join(projectPath, \"pyproject.toml\");\n const setupPath = join(projectPath, \"setup.py\");\n\n let deps = \"\";\n\n if (await fileExists(reqPath)) {\n deps = await readText(reqPath);\n } else if (await fileExists(pyprojectPath)) {\n deps = await readText(pyprojectPath);\n } else if (await fileExists(setupPath)) {\n deps = await readText(setupPath);\n } else {\n return null;\n }\n\n const depsLower = deps.toLowerCase();\n\n if (depsLower.includes(\"django\")) techStack.push(\"Django\");\n if (depsLower.includes(\"flask\")) techStack.push(\"Flask\");\n if (depsLower.includes(\"fastapi\")) techStack.push(\"FastAPI\");\n if (depsLower.includes(\"pytorch\") || depsLower.includes(\"torch\"))\n techStack.push(\"PyTorch\");\n if (depsLower.includes(\"tensorflow\")) techStack.push(\"TensorFlow\");\n if (depsLower.includes(\"transformers\")) techStack.push(\"Transformers\");\n if (depsLower.includes(\"langchain\")) techStack.push(\"LangChain\");\n if (depsLower.includes(\"openai\")) techStack.push(\"OpenAI\");\n if (depsLower.includes(\"pandas\")) techStack.push(\"Pandas\");\n if (depsLower.includes(\"numpy\")) techStack.push(\"NumPy\");\n if (depsLower.includes(\"scikit\")) techStack.push(\"Scikit-learn\");\n\n return { techStack };\n}\n","import { fileExists, readText, join } from \"../../utils/fs.js\";\n\nexport async function detectRust(projectPath: string) {\n const cargoPath = join(projectPath, \"Cargo.toml\");\n if (!(await fileExists(cargoPath))) return null;\n\n const content = await readText(cargoPath);\n const techStack: string[] = [\"Rust\"];\n\n if (content.includes(\"actix\")) techStack.push(\"Actix\");\n if (content.includes(\"axum\")) techStack.push(\"Axum\");\n if (content.includes(\"tokio\")) techStack.push(\"Tokio\");\n if (content.includes(\"wasm\")) techStack.push(\"WebAssembly\");\n if (content.includes(\"tauri\")) techStack.push(\"Tauri\");\n if (content.includes(\"diesel\")) techStack.push(\"Diesel\");\n if (content.includes(\"sqlx\")) techStack.push(\"SQLx\");\n\n // Extract name from [package] section\n const nameMatch = content.match(/\\[package\\][\\s\\S]*?name\\s*=\\s*\"([^\"]+)\"/);\n const descMatch = content.match(\n /\\[package\\][\\s\\S]*?description\\s*=\\s*\"([^\"]+)\"/\n );\n\n return {\n name: nameMatch?.[1] || null,\n description: descMatch?.[1] || null,\n techStack,\n };\n}\n","import { fileExists, readText, join } from \"../../utils/fs.js\";\n\nexport async function detectGo(projectPath: string) {\n const goModPath = join(projectPath, \"go.mod\");\n if (!(await fileExists(goModPath))) return null;\n\n const content = await readText(goModPath);\n const techStack: string[] = [\"Go\"];\n\n if (content.includes(\"gin-gonic\")) techStack.push(\"Gin\");\n if (content.includes(\"echo\")) techStack.push(\"Echo\");\n if (content.includes(\"fiber\")) techStack.push(\"Fiber\");\n if (content.includes(\"grpc\")) techStack.push(\"gRPC\");\n if (content.includes(\"gorm\")) techStack.push(\"GORM\");\n if (content.includes(\"cobra\")) techStack.push(\"Cobra\");\n if (content.includes(\"ent\")) techStack.push(\"Ent\");\n\n return { techStack };\n}\n","import { glob } from \"glob\";\nimport { basename, extname } from \"node:path\";\n\nconst EXTENSION_MAP: Record<string, string> = {\n \".ts\": \"TypeScript\",\n \".tsx\": \"TypeScript\",\n \".js\": \"JavaScript\",\n \".jsx\": \"JavaScript\",\n \".py\": \"Python\",\n \".rs\": \"Rust\",\n \".go\": \"Go\",\n \".java\": \"Java\",\n \".kt\": \"Kotlin\",\n \".swift\": \"Swift\",\n \".rb\": \"Ruby\",\n \".php\": \"PHP\",\n \".cs\": \"C#\",\n \".cpp\": \"C++\",\n \".c\": \"C\",\n \".dart\": \"Dart\",\n \".lua\": \"Lua\",\n \".zig\": \"Zig\",\n \".sol\": \"Solidity\",\n \".ex\": \"Elixir\",\n \".exs\": \"Elixir\",\n};\n\nconst IGNORE_DIRS = [\n \"node_modules\",\n \".git\",\n \"dist\",\n \"build\",\n \"out\",\n \".next\",\n \"target\",\n \"vendor\",\n \"__pycache__\",\n \".venv\",\n \"venv\",\n];\n\nexport async function detectLanguages(\n projectPath: string\n): Promise<Record<string, number>> {\n const ignorePattern = IGNORE_DIRS.map((d) => `**/${d}/**`);\n const files = await glob(\"**/*.*\", {\n cwd: projectPath,\n ignore: ignorePattern,\n nodir: true,\n maxDepth: 5,\n });\n\n const counts: Record<string, number> = {};\n for (const file of files) {\n const ext = extname(file).toLowerCase();\n const lang = EXTENSION_MAP[ext];\n if (lang) {\n counts[lang] = (counts[lang] || 0) + 1;\n }\n }\n\n return counts;\n}\n\nexport function deriveNameFromPath(projectPath: string): string {\n return basename(projectPath);\n}\n","import { fileExists, readText, join } from \"../utils/fs.js\";\n\nexport async function extractReadme(\n projectPath: string\n): Promise<string | null> {\n const candidates = [\n \"README.md\",\n \"readme.md\",\n \"Readme.md\",\n \"README.txt\",\n \"README\",\n ];\n for (const name of candidates) {\n const p = join(projectPath, name);\n if (await fileExists(p)) {\n const content = await readText(p);\n // Limit to first 3000 chars to keep spec manageable\n return content.slice(0, 3000);\n }\n }\n return null;\n}\n\nexport function extractFirstParagraph(readme: string | null): string | null {\n if (!readme) return null;\n // Skip title lines (# heading)\n const lines = readme.split(\"\\n\");\n let collecting = false;\n const paragraphLines: string[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.startsWith(\"#\")) {\n if (collecting && paragraphLines.length > 0) break;\n collecting = true;\n continue;\n }\n if (collecting && trimmed === \"\" && paragraphLines.length > 0) break;\n if (collecting && trimmed !== \"\") {\n paragraphLines.push(trimmed);\n }\n if (!collecting && trimmed !== \"\" && !trimmed.startsWith(\"[\")) {\n paragraphLines.push(trimmed);\n collecting = true;\n }\n }\n\n return paragraphLines.length > 0 ? paragraphLines.join(\" \") : null;\n}\n\nexport function extractDemoUrl(readme: string | null): string | null {\n if (!readme) return null;\n // Look for common demo URL patterns\n const patterns = [\n /(?:demo|live|website|site|url|link)[\\s:]*\\[?[^\\]]*\\]?\\(?(https?:\\/\\/[^\\s)]+)/i,\n /\\[(?:demo|live|website|try it)\\]\\((https?:\\/\\/[^\\s)]+)\\)/i,\n /(https?:\\/\\/[^\\s)]+\\.(?:vercel|netlify|pages\\.dev|herokuapp|railway)\\.app[^\\s)]*)/i,\n ];\n for (const pattern of patterns) {\n const match = readme.match(pattern);\n if (match?.[1]) return match[1];\n }\n return null;\n}\n","import chalk from \"chalk\";\n\nexport const logger = {\n info(msg: string) {\n console.log(chalk.cyan(`-- ${msg}`));\n },\n success(msg: string) {\n console.log(chalk.green(`-- ${msg}`));\n },\n warn(msg: string) {\n console.log(chalk.yellow(`-- ${msg}`));\n },\n error(msg: string) {\n console.error(chalk.red(`-- ${msg}`));\n },\n plain(msg: string) {\n console.log(msg);\n },\n blank() {\n console.log();\n },\n header(msg: string) {\n console.log();\n console.log(chalk.bold(msg));\n console.log();\n },\n table(rows: string[][]) {\n if (rows.length === 0) return;\n const colWidths = rows[0].map((_, colIdx) =>\n Math.max(...rows.map((row) => (row[colIdx] || \"\").length))\n );\n for (const row of rows) {\n const line = row\n .map((cell, i) => (cell || \"\").padEnd(colWidths[i] + 2))\n .join(\"\");\n console.log(` ${line}`);\n }\n },\n};\n","import { findGitRepos, getGitMeta } from \"./git.js\";\nimport { detectNode } from \"./detectors/node.js\";\nimport { detectPython } from \"./detectors/python.js\";\nimport { detectRust } from \"./detectors/rust.js\";\nimport { detectGo } from \"./detectors/go.js\";\nimport { detectLanguages, deriveNameFromPath } from \"./detectors/generic.js\";\nimport {\n extractReadme,\n extractFirstParagraph,\n extractDemoUrl,\n} from \"./extractors.js\";\nimport type { ProjectMeta } from \"../spec/schema.js\";\nimport { logger } from \"../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function scanProjects(\n directories: string[]\n): Promise<ProjectMeta[]> {\n const allRepos: string[] = [];\n\n const spinner = ora(\"Scanning for projects...\").start();\n\n for (const dir of directories) {\n try {\n const repos = await findGitRepos(dir);\n allRepos.push(...repos);\n } catch (err) {\n logger.warn(`Could not scan ${dir}: ${err}`);\n }\n }\n\n // Deduplicate\n const uniqueRepos = [...new Set(allRepos)];\n spinner.text = `Found ${uniqueRepos.length} repositories. Extracting metadata...`;\n\n const projects: ProjectMeta[] = [];\n\n for (const repoPath of uniqueRepos) {\n try {\n const project = await extractProjectMeta(repoPath);\n if (project) {\n projects.push(project);\n }\n } catch (err) {\n // Skip projects that fail extraction\n }\n }\n\n spinner.succeed(`Scanned ${projects.length} projects`);\n return projects;\n}\n\nasync function extractProjectMeta(\n projectPath: string\n): Promise<ProjectMeta | null> {\n const gitMeta = await getGitMeta(projectPath);\n if (!gitMeta.isRepo) return null;\n\n // Detect tech stack from various sources\n let techStack: string[] = [];\n let name: string | null = null;\n let description: string | null = null;\n let homepage: string | null = null;\n\n const nodeInfo = await detectNode(projectPath);\n if (nodeInfo) {\n techStack.push(...nodeInfo.techStack);\n name = nodeInfo.name || name;\n description = nodeInfo.description || description;\n homepage = nodeInfo.homepage || homepage;\n }\n\n const pythonInfo = await detectPython(projectPath);\n if (pythonInfo) {\n techStack.push(...pythonInfo.techStack);\n }\n\n const rustInfo = await detectRust(projectPath);\n if (rustInfo) {\n techStack.push(...rustInfo.techStack);\n name = rustInfo.name || name;\n description = rustInfo.description || description;\n }\n\n const goInfo = await detectGo(projectPath);\n if (goInfo) {\n techStack.push(...goInfo.techStack);\n }\n\n // Deduplicate tech stack\n techStack = [...new Set(techStack)];\n\n // Language breakdown\n const languages = await detectLanguages(projectPath);\n\n // If no tech stack detected, derive from languages\n if (techStack.length === 0) {\n const topLangs = Object.entries(languages)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 3)\n .map(([lang]) => lang);\n techStack = topLangs;\n }\n\n // README\n const readmeContent = await extractReadme(projectPath);\n if (!description) {\n description = extractFirstParagraph(readmeContent) || \"\";\n }\n\n // Demo URL\n const demoUrl = homepage || extractDemoUrl(readmeContent);\n\n // Name fallback\n if (!name) {\n name = deriveNameFromPath(projectPath);\n }\n\n // Generate stable ID from path\n const id = name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n\n return {\n id,\n name,\n localPath: projectPath,\n description: description || \"\",\n techStack,\n languages,\n firstCommitDate: gitMeta.firstCommitDate || \"\",\n lastCommitDate: gitMeta.lastCommitDate || \"\",\n totalCommits: gitMeta.totalCommits,\n remoteUrl: gitMeta.remoteUrl,\n demoUrl,\n readmeContent,\n lastScannedCommit: gitMeta.lastCommitHash || \"\",\n };\n}\n"],"mappings":"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","names":["glob"]}
1
+ {"version":3,"sources":["../../../src/scanner/git.ts","../../../src/utils/fs.ts","../../../src/scanner/detectors/node.ts","../../../src/scanner/detectors/python.ts","../../../src/scanner/detectors/rust.ts","../../../src/scanner/detectors/go.ts","../../../src/scanner/detectors/generic.ts","../../../src/scanner/extractors.ts","../../../src/utils/logger.ts","../../../src/scanner/index.ts"],"sourcesContent":["import simpleGit from \"simple-git\";\nimport { basename } from \"node:path\";\n\nexport interface GitMeta {\n isRepo: boolean;\n firstCommitDate: string | null;\n lastCommitDate: string | null;\n totalCommits: number;\n remoteUrl: string | null;\n lastCommitHash: string | null;\n}\n\nexport async function getGitMeta(projectPath: string): Promise<GitMeta> {\n const git = simpleGit(projectPath);\n const empty: GitMeta = {\n isRepo: false,\n firstCommitDate: null,\n lastCommitDate: null,\n totalCommits: 0,\n remoteUrl: null,\n lastCommitHash: null,\n };\n\n try {\n const isRepo = await git.checkIsRepo();\n if (!isRepo) return empty;\n } catch {\n return empty;\n }\n\n try {\n const log = await git.log({ maxCount: 1 });\n\n // Get first commit date\n let firstCommitDate: string | null = null;\n try {\n const firstResult = await git.raw([\"log\", \"--reverse\", \"--format=%aI\", \"--max-count=1\"]);\n firstCommitDate = firstResult.trim() || null;\n } catch {\n // ignore\n }\n\n let remoteUrl: string | null = null;\n try {\n const remotes = await git.getRemotes(true);\n const origin = remotes.find((r) => r.name === \"origin\");\n if (origin?.refs?.fetch) {\n remoteUrl = normalizeGitUrl(origin.refs.fetch);\n }\n } catch {\n // no remotes\n }\n\n // Get total commit count\n let totalCommits = 0;\n try {\n const result = await git.raw([\"rev-list\", \"--count\", \"HEAD\"]);\n totalCommits = parseInt(result.trim(), 10) || 0;\n } catch {\n totalCommits = 0;\n }\n\n return {\n isRepo: true,\n firstCommitDate,\n lastCommitDate: log.latest?.date || null,\n totalCommits,\n remoteUrl,\n lastCommitHash: log.latest?.hash || null,\n };\n } catch {\n return { ...empty, isRepo: true };\n }\n}\n\nfunction normalizeGitUrl(url: string): string {\n // Convert SSH to HTTPS\n if (url.startsWith(\"git@\")) {\n url = url.replace(\":\", \"/\").replace(\"git@\", \"https://\");\n }\n // Remove .git suffix\n if (url.endsWith(\".git\")) {\n url = url.slice(0, -4);\n }\n return url;\n}\n\nexport async function findGitRepos(\n rootPath: string,\n maxDepth: number = 3\n): Promise<string[]> {\n const { glob } = await import(\"glob\");\n const gitDirs = await glob(\"**/.git\", {\n cwd: rootPath,\n maxDepth: maxDepth + 1,\n dot: true,\n ignore: [\n \"**/node_modules/**/.git\",\n \"**/vendor/**/.git\",\n \"**/__pycache__/**/.git\",\n ],\n });\n\n return gitDirs\n .map((gitDir) => {\n const parts = gitDir.split(\"/\");\n parts.pop(); // remove .git\n return parts.length > 0\n ? `${rootPath}/${parts.join(\"/\")}`\n : rootPath;\n })\n .sort();\n}\n","import { readFile, writeFile, access, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\n\nexport async function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function readJson<T = unknown>(path: string): Promise<T> {\n const content = await readFile(path, \"utf-8\");\n return JSON.parse(content) as T;\n}\n\nexport async function writeJson(path: string, data: unknown): Promise<void> {\n await writeFile(path, JSON.stringify(data, null, 2), \"utf-8\");\n}\n\nexport async function readText(path: string): Promise<string> {\n return readFile(path, \"utf-8\");\n}\n\nexport async function writeText(path: string, content: string): Promise<void> {\n await writeFile(path, content, \"utf-8\");\n}\n\nexport async function ensureDir(path: string): Promise<void> {\n await mkdir(path, { recursive: true });\n}\n\nexport { join };\n","import { fileExists, readJson, join } from \"../../utils/fs.js\";\n\ninterface PackageJson {\n name?: string;\n description?: string;\n homepage?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nexport async function detectNode(projectPath: string) {\n const pkgPath = join(projectPath, \"package.json\");\n if (!(await fileExists(pkgPath))) return null;\n\n const pkg = await readJson<PackageJson>(pkgPath);\n const allDeps = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n const depNames = Object.keys(allDeps);\n\n const techStack: string[] = [];\n\n // Frameworks\n if (depNames.includes(\"next\")) techStack.push(\"Next.js\");\n else if (depNames.includes(\"nuxt\")) techStack.push(\"Nuxt\");\n else if (depNames.includes(\"astro\")) techStack.push(\"Astro\");\n else if (depNames.includes(\"svelte\") || depNames.includes(\"@sveltejs/kit\"))\n techStack.push(\"Svelte\");\n\n // UI libraries\n if (depNames.includes(\"react\")) techStack.push(\"React\");\n if (depNames.includes(\"vue\")) techStack.push(\"Vue\");\n\n // Styling\n if (depNames.includes(\"tailwindcss\")) techStack.push(\"Tailwind CSS\");\n\n // Backend\n if (depNames.includes(\"express\")) techStack.push(\"Express\");\n if (depNames.includes(\"fastify\")) techStack.push(\"Fastify\");\n if (depNames.includes(\"hono\")) techStack.push(\"Hono\");\n\n // Database\n if (depNames.includes(\"prisma\") || depNames.includes(\"@prisma/client\"))\n techStack.push(\"Prisma\");\n if (depNames.includes(\"drizzle-orm\")) techStack.push(\"Drizzle\");\n if (depNames.includes(\"mongoose\")) techStack.push(\"MongoDB\");\n\n // AI/ML\n if (depNames.includes(\"openai\")) techStack.push(\"OpenAI\");\n if (depNames.includes(\"@anthropic-ai/sdk\")) techStack.push(\"Claude API\");\n if (depNames.includes(\"langchain\")) techStack.push(\"LangChain\");\n\n // Language\n if (depNames.includes(\"typescript\")) techStack.push(\"TypeScript\");\n else techStack.push(\"JavaScript\");\n\n return {\n name: pkg.name || null,\n description: pkg.description || null,\n homepage: pkg.homepage || null,\n techStack,\n };\n}\n","import { fileExists, readText, join } from \"../../utils/fs.js\";\n\nexport async function detectPython(projectPath: string) {\n const techStack: string[] = [\"Python\"];\n\n const reqPath = join(projectPath, \"requirements.txt\");\n const pyprojectPath = join(projectPath, \"pyproject.toml\");\n const setupPath = join(projectPath, \"setup.py\");\n\n let deps = \"\";\n\n if (await fileExists(reqPath)) {\n deps = await readText(reqPath);\n } else if (await fileExists(pyprojectPath)) {\n deps = await readText(pyprojectPath);\n } else if (await fileExists(setupPath)) {\n deps = await readText(setupPath);\n } else {\n return null;\n }\n\n const depsLower = deps.toLowerCase();\n\n if (depsLower.includes(\"django\")) techStack.push(\"Django\");\n if (depsLower.includes(\"flask\")) techStack.push(\"Flask\");\n if (depsLower.includes(\"fastapi\")) techStack.push(\"FastAPI\");\n if (depsLower.includes(\"pytorch\") || depsLower.includes(\"torch\"))\n techStack.push(\"PyTorch\");\n if (depsLower.includes(\"tensorflow\")) techStack.push(\"TensorFlow\");\n if (depsLower.includes(\"transformers\")) techStack.push(\"Transformers\");\n if (depsLower.includes(\"langchain\")) techStack.push(\"LangChain\");\n if (depsLower.includes(\"openai\")) techStack.push(\"OpenAI\");\n if (depsLower.includes(\"pandas\")) techStack.push(\"Pandas\");\n if (depsLower.includes(\"numpy\")) techStack.push(\"NumPy\");\n if (depsLower.includes(\"scikit\")) techStack.push(\"Scikit-learn\");\n\n return { techStack };\n}\n","import { fileExists, readText, join } from \"../../utils/fs.js\";\n\nexport async function detectRust(projectPath: string) {\n const cargoPath = join(projectPath, \"Cargo.toml\");\n if (!(await fileExists(cargoPath))) return null;\n\n const content = await readText(cargoPath);\n const techStack: string[] = [\"Rust\"];\n\n if (content.includes(\"actix\")) techStack.push(\"Actix\");\n if (content.includes(\"axum\")) techStack.push(\"Axum\");\n if (content.includes(\"tokio\")) techStack.push(\"Tokio\");\n if (content.includes(\"wasm\")) techStack.push(\"WebAssembly\");\n if (content.includes(\"tauri\")) techStack.push(\"Tauri\");\n if (content.includes(\"diesel\")) techStack.push(\"Diesel\");\n if (content.includes(\"sqlx\")) techStack.push(\"SQLx\");\n\n // Extract name from [package] section\n const nameMatch = content.match(/\\[package\\][\\s\\S]*?name\\s*=\\s*\"([^\"]+)\"/);\n const descMatch = content.match(\n /\\[package\\][\\s\\S]*?description\\s*=\\s*\"([^\"]+)\"/\n );\n\n return {\n name: nameMatch?.[1] || null,\n description: descMatch?.[1] || null,\n techStack,\n };\n}\n","import { fileExists, readText, join } from \"../../utils/fs.js\";\n\nexport async function detectGo(projectPath: string) {\n const goModPath = join(projectPath, \"go.mod\");\n if (!(await fileExists(goModPath))) return null;\n\n const content = await readText(goModPath);\n const techStack: string[] = [\"Go\"];\n\n if (content.includes(\"gin-gonic\")) techStack.push(\"Gin\");\n if (content.includes(\"echo\")) techStack.push(\"Echo\");\n if (content.includes(\"fiber\")) techStack.push(\"Fiber\");\n if (content.includes(\"grpc\")) techStack.push(\"gRPC\");\n if (content.includes(\"gorm\")) techStack.push(\"GORM\");\n if (content.includes(\"cobra\")) techStack.push(\"Cobra\");\n if (content.includes(\"ent\")) techStack.push(\"Ent\");\n\n return { techStack };\n}\n","import { glob } from \"glob\";\nimport { basename, extname } from \"node:path\";\n\nconst EXTENSION_MAP: Record<string, string> = {\n \".ts\": \"TypeScript\",\n \".tsx\": \"TypeScript\",\n \".js\": \"JavaScript\",\n \".jsx\": \"JavaScript\",\n \".py\": \"Python\",\n \".rs\": \"Rust\",\n \".go\": \"Go\",\n \".java\": \"Java\",\n \".kt\": \"Kotlin\",\n \".swift\": \"Swift\",\n \".rb\": \"Ruby\",\n \".php\": \"PHP\",\n \".cs\": \"C#\",\n \".cpp\": \"C++\",\n \".c\": \"C\",\n \".dart\": \"Dart\",\n \".lua\": \"Lua\",\n \".zig\": \"Zig\",\n \".sol\": \"Solidity\",\n \".ex\": \"Elixir\",\n \".exs\": \"Elixir\",\n};\n\nconst IGNORE_DIRS = [\n \"node_modules\",\n \".git\",\n \"dist\",\n \"build\",\n \"out\",\n \".next\",\n \"target\",\n \"vendor\",\n \"__pycache__\",\n \".venv\",\n \"venv\",\n];\n\nexport async function detectLanguages(\n projectPath: string\n): Promise<Record<string, number>> {\n const ignorePattern = IGNORE_DIRS.map((d) => `**/${d}/**`);\n const files = await glob(\"**/*.*\", {\n cwd: projectPath,\n ignore: ignorePattern,\n nodir: true,\n maxDepth: 5,\n });\n\n const counts: Record<string, number> = {};\n for (const file of files) {\n const ext = extname(file).toLowerCase();\n const lang = EXTENSION_MAP[ext];\n if (lang) {\n counts[lang] = (counts[lang] || 0) + 1;\n }\n }\n\n return counts;\n}\n\nexport function deriveNameFromPath(projectPath: string): string {\n return basename(projectPath);\n}\n","import { fileExists, readText, join } from \"../utils/fs.js\";\n\nexport async function extractReadme(\n projectPath: string\n): Promise<string | null> {\n const candidates = [\n \"README.md\",\n \"readme.md\",\n \"Readme.md\",\n \"README.txt\",\n \"README\",\n ];\n for (const name of candidates) {\n const p = join(projectPath, name);\n if (await fileExists(p)) {\n const content = await readText(p);\n // Limit to first 3000 chars to keep spec manageable\n return content.slice(0, 3000);\n }\n }\n return null;\n}\n\nexport function extractFirstParagraph(readme: string | null): string | null {\n if (!readme) return null;\n // Skip title lines (# heading)\n const lines = readme.split(\"\\n\");\n let collecting = false;\n const paragraphLines: string[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.startsWith(\"#\")) {\n if (collecting && paragraphLines.length > 0) break;\n collecting = true;\n continue;\n }\n if (collecting && trimmed === \"\" && paragraphLines.length > 0) break;\n if (collecting && trimmed !== \"\") {\n paragraphLines.push(trimmed);\n }\n if (!collecting && trimmed !== \"\" && !trimmed.startsWith(\"[\")) {\n paragraphLines.push(trimmed);\n collecting = true;\n }\n }\n\n return paragraphLines.length > 0 ? paragraphLines.join(\" \") : null;\n}\n\nexport function extractDemoUrl(readme: string | null): string | null {\n if (!readme) return null;\n // Look for common demo URL patterns\n const patterns = [\n /(?:demo|live|website|site|url|link)[\\s:]*\\[?[^\\]]*\\]?\\(?(https?:\\/\\/[^\\s)]+)/i,\n /\\[(?:demo|live|website|try it)\\]\\((https?:\\/\\/[^\\s)]+)\\)/i,\n /(https?:\\/\\/[^\\s)]+\\.(?:vercel|netlify|pages\\.dev|herokuapp|railway)\\.app[^\\s)]*)/i,\n ];\n for (const pattern of patterns) {\n const match = readme.match(pattern);\n if (match?.[1]) return match[1];\n }\n return null;\n}\n","import chalk from \"chalk\";\n\nexport const logger = {\n info(msg: string) {\n console.log(chalk.cyan(`-- ${msg}`));\n },\n success(msg: string) {\n console.log(chalk.green(`-- ${msg}`));\n },\n warn(msg: string) {\n console.log(chalk.yellow(`-- ${msg}`));\n },\n error(msg: string) {\n console.error(chalk.red(`-- ${msg}`));\n },\n plain(msg: string) {\n console.log(msg);\n },\n blank() {\n console.log();\n },\n header(msg: string) {\n console.log();\n console.log(chalk.bold(msg));\n console.log();\n },\n table(rows: string[][]) {\n if (rows.length === 0) return;\n const colWidths = rows[0].map((_, colIdx) =>\n Math.max(...rows.map((row) => (row[colIdx] || \"\").length))\n );\n for (const row of rows) {\n const line = row\n .map((cell, i) => (cell || \"\").padEnd(colWidths[i] + 2))\n .join(\"\");\n console.log(` ${line}`);\n }\n },\n};\n","import { findGitRepos, getGitMeta } from \"./git.js\";\nimport { detectNode } from \"./detectors/node.js\";\nimport { detectPython } from \"./detectors/python.js\";\nimport { detectRust } from \"./detectors/rust.js\";\nimport { detectGo } from \"./detectors/go.js\";\nimport { detectLanguages, deriveNameFromPath } from \"./detectors/generic.js\";\nimport {\n extractReadme,\n extractFirstParagraph,\n extractDemoUrl,\n} from \"./extractors.js\";\nimport type { ProjectMeta } from \"../spec/schema.js\";\nimport { logger } from \"../utils/logger.js\";\nimport ora from \"ora\";\n\nexport async function scanProjects(\n directories: string[]\n): Promise<ProjectMeta[]> {\n const allPaths: string[] = [];\n\n const spinner = ora(\"Scanning for projects...\").start();\n\n for (const dir of directories) {\n try {\n // Find git repos\n const repos = await findGitRepos(dir);\n allPaths.push(...repos);\n\n // Also find non-git project directories (with package.json, Cargo.toml, etc.)\n const nonGitDirs = await findNonGitProjects(dir, new Set(repos));\n allPaths.push(...nonGitDirs);\n } catch (err) {\n logger.warn(`Could not scan ${dir}: ${err}`);\n }\n }\n\n // Deduplicate\n const uniquePaths = [...new Set(allPaths)];\n spinner.text = `Found ${uniquePaths.length} projects. Extracting metadata...`;\n\n const projects: ProjectMeta[] = [];\n\n for (const projectPath of uniquePaths) {\n try {\n const project = await extractProjectMeta(projectPath);\n if (project) {\n projects.push(project);\n }\n } catch (err) {\n // Skip projects that fail extraction\n }\n }\n\n // Deduplicate IDs (same folder name in different parent dirs)\n const idCounts = new Map<string, number>();\n for (const project of projects) {\n const count = idCounts.get(project.id) || 0;\n if (count > 0) {\n project.id = `${project.id}-${count}`;\n }\n idCounts.set(project.id.replace(/-\\d+$/, \"\"), count + 1);\n }\n\n spinner.succeed(`Scanned ${projects.length} projects`);\n return projects;\n}\n\nasync function findNonGitProjects(\n rootPath: string,\n gitRepos: Set<string>\n): Promise<string[]> {\n const { glob } = await import(\"glob\");\n const indicators = [\n \"*/package.json\",\n \"*/Cargo.toml\",\n \"*/go.mod\",\n \"*/pyproject.toml\",\n \"*/requirements.txt\",\n \"*/setup.py\",\n ];\n const found = new Set<string>();\n for (const pattern of indicators) {\n const matches = await glob(pattern, {\n cwd: rootPath,\n ignore: [\"**/node_modules/**\", \"**/vendor/**\"],\n });\n for (const match of matches) {\n const dir = `${rootPath}/${match.split(\"/\")[0]}`;\n if (!gitRepos.has(dir) && !found.has(dir)) {\n found.add(dir);\n }\n }\n }\n return [...found].sort();\n}\n\nasync function extractProjectMeta(\n projectPath: string\n): Promise<ProjectMeta | null> {\n const gitMeta = await getGitMeta(projectPath);\n\n // Detect tech stack from various sources\n let techStack: string[] = [];\n let name: string | null = null;\n let description: string | null = null;\n let homepage: string | null = null;\n\n const nodeInfo = await detectNode(projectPath);\n if (nodeInfo) {\n techStack.push(...nodeInfo.techStack);\n name = nodeInfo.name || name;\n description = nodeInfo.description || description;\n homepage = nodeInfo.homepage || homepage;\n }\n\n const pythonInfo = await detectPython(projectPath);\n if (pythonInfo) {\n techStack.push(...pythonInfo.techStack);\n }\n\n const rustInfo = await detectRust(projectPath);\n if (rustInfo) {\n techStack.push(...rustInfo.techStack);\n name = rustInfo.name || name;\n description = rustInfo.description || description;\n }\n\n const goInfo = await detectGo(projectPath);\n if (goInfo) {\n techStack.push(...goInfo.techStack);\n }\n\n // Deduplicate tech stack\n techStack = [...new Set(techStack)];\n\n // Language breakdown\n const languages = await detectLanguages(projectPath);\n\n // If no tech stack detected, derive from languages\n if (techStack.length === 0) {\n const topLangs = Object.entries(languages)\n .sort((a, b) => b[1] - a[1])\n .slice(0, 3)\n .map(([lang]) => lang);\n techStack = topLangs;\n }\n\n // README\n const readmeContent = await extractReadme(projectPath);\n if (!description) {\n description = extractFirstParagraph(readmeContent) || \"\";\n }\n\n // Demo URL\n const demoUrl = homepage || extractDemoUrl(readmeContent);\n\n // Name fallback\n if (!name) {\n name = deriveNameFromPath(projectPath);\n }\n\n // Generate stable ID from path (use folder name to keep it readable, but\n // append a hash suffix when the same folder name appears in multiple paths)\n const folderName = deriveNameFromPath(projectPath);\n const id = folderName\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n\n return {\n id,\n name,\n localPath: projectPath,\n description: description || \"\",\n techStack,\n languages,\n firstCommitDate: gitMeta.firstCommitDate || \"\",\n lastCommitDate: gitMeta.lastCommitDate || \"\",\n totalCommits: gitMeta.totalCommits,\n remoteUrl: gitMeta.remoteUrl,\n demoUrl,\n readmeContent,\n lastScannedCommit: gitMeta.lastCommitHash || \"\",\n };\n}\n"],"mappings":"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","names":["glob","glob"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shipfolio",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Generate and deploy your personal portfolio site from local projects using AI",
5
5
  "type": "module",
6
6
  "bin": {