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.
- package/dist/index.js +50 -7
- 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
|
-
|
|
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
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
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.
|
|
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);
|