helpshelf 0.4.0 → 0.4.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.
Files changed (2) hide show
  1. package/dist/index.js +50 -7
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import { Command } from "commander";
8
8
 
9
9
  // src/commands/scan.ts
10
10
  import { resolve, join as join8, relative as relative4 } from "path";
11
- import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync8, mkdirSync, readdirSync as readdirSync4 } from "fs";
11
+ import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync8, mkdirSync, readdirSync as readdirSync4, statSync as statSync3 } from "fs";
12
12
  import { createInterface } from "readline";
13
13
  import { basename as basename2 } from "path";
14
14
  import chalk from "chalk";
@@ -915,6 +915,36 @@ function generateDepFaqs(deps) {
915
915
  }
916
916
 
917
917
  // src/commands/scan.ts
918
+ function isICloudEvicted(filePath) {
919
+ try {
920
+ const stat = statSync3(filePath);
921
+ return stat.isFile() && stat.size > 0 && stat.blocks === 0;
922
+ } catch {
923
+ return false;
924
+ }
925
+ }
926
+ function checkICloudStatus(dir, log) {
927
+ const criticalFiles = ["package.json", "README.md", ".env", ".env.example", "tsconfig.json", "pyproject.toml"];
928
+ const evictedFiles = [];
929
+ for (const file of criticalFiles) {
930
+ const filePath = join8(dir, file);
931
+ if (existsSync8(filePath) && isICloudEvicted(filePath)) {
932
+ evictedFiles.push(file);
933
+ }
934
+ }
935
+ if (evictedFiles.length > 0) {
936
+ log(chalk.yellow.bold("\u26A0 iCloud Drive detected \u2014 key files are not downloaded locally:"));
937
+ for (const file of evictedFiles) {
938
+ log(chalk.yellow(` \u2022 ${file}`));
939
+ }
940
+ log();
941
+ log(chalk.dim(' To fix, open Finder \u2192 right-click the project folder \u2192 "Download Now"'));
942
+ log(chalk.dim(" Or move the project out of Desktop/Documents to a non-iCloud folder."));
943
+ log();
944
+ return true;
945
+ }
946
+ return false;
947
+ }
918
948
  async function scanCommand(options) {
919
949
  const startTime = Date.now();
920
950
  const projectDir = resolve(options.dir);
@@ -928,6 +958,10 @@ async function scanCommand(options) {
928
958
  console.error(chalk.red(`Directory not found: ${projectDir}`));
929
959
  process.exit(1);
930
960
  }
961
+ const hasEvictedFiles = checkICloudStatus(projectDir, log);
962
+ if (hasEvictedFiles) {
963
+ log(chalk.yellow(" Scanning anyway, but results will be incomplete.\n"));
964
+ }
931
965
  const spinner = ora("Reading project metadata...").start();
932
966
  const project = scanProjectMeta(projectDir);
933
967
  spinner.succeed(`Project: ${chalk.cyan(project.name)}${project.version ? ` v${project.version}` : ""}`);
@@ -1579,7 +1613,12 @@ function readDocsDirectory(dir) {
1579
1613
  const files = readdirSync5(dir).filter((f) => f.endsWith(".md"));
1580
1614
  const articles = [];
1581
1615
  for (const file of files) {
1582
- const content = readFileSync3(join9(dir, file), "utf-8");
1616
+ let content;
1617
+ try {
1618
+ content = readFileSync3(join9(dir, file), "utf-8");
1619
+ } catch {
1620
+ continue;
1621
+ }
1583
1622
  const slug = basename3(file, ".md");
1584
1623
  const { frontmatter, body } = parseFrontmatter2(content);
1585
1624
  const title = frontmatter.title || slug.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
@@ -1675,10 +1714,14 @@ async function initCommand() {
1675
1714
  }
1676
1715
  const gitignorePath = join10(dir, ".gitignore");
1677
1716
  if (existsSync10(gitignorePath)) {
1678
- const gitignore = readFileSync4(gitignorePath, "utf-8");
1679
- if (!gitignore.includes(".helpshelf/snapshot.json")) {
1680
- writeFileSync3(gitignorePath, gitignore.trimEnd() + "\n\n# HelpShelf\n.helpshelf/snapshot.json\n");
1681
- console.log(chalk3.green(" \u2713"), "Added .helpshelf/snapshot.json to .gitignore");
1717
+ try {
1718
+ const gitignore = readFileSync4(gitignorePath, "utf-8");
1719
+ if (!gitignore.includes(".helpshelf/snapshot.json")) {
1720
+ writeFileSync3(gitignorePath, gitignore.trimEnd() + "\n\n# HelpShelf\n.helpshelf/snapshot.json\n");
1721
+ console.log(chalk3.green(" \u2713"), "Added .helpshelf/snapshot.json to .gitignore");
1722
+ }
1723
+ } catch {
1724
+ console.log(chalk3.yellow(" \u26A0"), "Could not read .gitignore (file may be on iCloud)");
1682
1725
  }
1683
1726
  }
1684
1727
  console.log();
@@ -1768,7 +1811,7 @@ async function screenshotCommand(options) {
1768
1811
 
1769
1812
  // src/index.ts
1770
1813
  var program = new Command();
1771
- program.name("helpshelf").description("AI-agent toolkit for auto-generating support docs").version("0.4.0");
1814
+ program.name("helpshelf").description("AI-agent toolkit for auto-generating support docs").version("0.4.2");
1772
1815
  program.command("scan").description("Scan your codebase \u2192 snapshot.json + docs-template.json").option("-d, --dir <path>", "Project directory to scan", ".").option("-o, --output <path>", "Output file path", ".helpshelf/snapshot.json").option("--no-readme", "Skip README parsing").option("--no-deps", "Skip dependency analysis").option("--no-api", "Skip API route detection").option("--no-env", "Skip environment variable detection").option("--verbose", "Show detailed scan output").option("--quiet", "Suppress output (for programmatic use)").option("-u, --url <url>", "Also capture screenshots from a running app (e.g., http://localhost:3000)").option("-e, --email <email>", "Login email for screenshot auth").option("-p, --password <password>", "Login password for screenshot auth").option("-m, --max-pages <n>", "Max pages to screenshot", "20").action(scanCommand);
1773
1816
  program.command("screenshot").description("Capture screenshots of your running app's pages").requiredOption("-u, --url <url>", "URL of your running app (e.g., http://localhost:3000)").option("-e, --email <email>", "Login email for authenticated pages").option("-p, --password <password>", "Login password").option("-s, --snapshot <path>", "Path to scan snapshot (for route intelligence)", ".helpshelf/snapshot.json").option("-o, --output <path>", "Output directory for screenshots", ".helpshelf/screenshots").option("-m, --max-pages <n>", "Maximum pages to capture", "20").action(screenshotCommand);
1774
1817
  program.command("push").description("Push docs to HelpShelf (creates account if needed)").option("--email <email>", "HelpShelf account email").option("--domain <domain>", "Your app domain (for help center URL)").option("--docs-dir <path>", "Directory containing markdown docs", ".helpshelf/docs").option("--site <hash>", "Existing HelpShelf site hash").option("--api-key <key>", "Existing HelpShelf API key").option("--api-url <url>", "HelpShelf API URL", "https://app.helpshelf.com").option("--dry-run", "Preview what would be pushed without sending").action(pushCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "helpshelf",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "Scan your codebase and auto-generate support docs for HelpShelf",
5
5
  "type": "module",
6
6
  "bin": {