nrdocs 0.2.2 → 0.2.4

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/bin.mjs +173 -130
  2. package/package.json +1 -1
package/dist/bin.mjs CHANGED
@@ -268,57 +268,24 @@ var require_punycode = __commonJS({
268
268
  }
269
269
  });
270
270
 
271
- // ../shared/dist/constants.js
272
- var NRDOCS_VERSION = "0.1.0";
273
- var ALLOWED_ASSET_EXTENSIONS = /* @__PURE__ */ new Set([
274
- ".html",
275
- ".css",
276
- ".json",
277
- ".svg",
278
- ".png",
279
- ".jpg",
280
- ".jpeg",
281
- ".gif",
282
- ".webp",
283
- ".ico",
284
- ".txt",
285
- ".pdf"
286
- ]);
287
- var REJECTED_EXTENSIONS = /* @__PURE__ */ new Set([".js", ".mjs", ".cjs"]);
288
-
289
- // ../shared/dist/naming.js
290
- var INSTANCE_NAME_REGEX = /^[a-z0-9]([a-z0-9-]{0,18}[a-z0-9])?$/;
291
- var MAX_INSTANCE_LENGTH = 20;
292
- function validateInstanceName(name) {
293
- if (!name) {
294
- return { valid: false, error: "Instance name cannot be empty" };
295
- }
296
- if (name.length > MAX_INSTANCE_LENGTH) {
297
- return { valid: false, error: `Instance name must be ${MAX_INSTANCE_LENGTH} characters or fewer` };
298
- }
299
- if (!INSTANCE_NAME_REGEX.test(name)) {
300
- return {
301
- valid: false,
302
- error: "Instance name must be lowercase alphanumeric with hyphens, cannot start or end with a hyphen"
303
- };
271
+ // src/version.ts
272
+ import { readFileSync } from "node:fs";
273
+ import * as path from "node:path";
274
+ import { fileURLToPath } from "node:url";
275
+ var cached;
276
+ function getCliVersion() {
277
+ if (cached) return cached;
278
+ try {
279
+ const pkgPath = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "package.json");
280
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
281
+ if (typeof pkg.version === "string" && pkg.version.length > 0) {
282
+ cached = pkg.version;
283
+ return cached;
284
+ }
285
+ } catch {
304
286
  }
305
- return { valid: true };
306
- }
307
- function getWorkerName(instance) {
308
- return `nrdocs-${instance}`;
309
- }
310
- function getD1Name(instance) {
311
- return `nrdocs-${instance}-db`;
312
- }
313
- function getR2BucketName(instance) {
314
- return `nrdocs-${instance}-artifacts`;
315
- }
316
- function getResourceNames(instance) {
317
- return {
318
- worker: getWorkerName(instance),
319
- d1: getD1Name(instance),
320
- r2: getR2BucketName(instance)
321
- };
287
+ cached = "0.0.0";
288
+ return cached;
322
289
  }
323
290
 
324
291
  // src/commands/auth/login.ts
@@ -326,17 +293,17 @@ import * as readline from "node:readline";
326
293
 
327
294
  // src/config/paths.ts
328
295
  import * as os from "node:os";
329
- import * as path from "node:path";
296
+ import * as path2 from "node:path";
330
297
  var APP_NAME = "nrdocs";
331
298
  var CONFIG_FILE = "config.json";
332
299
  function getConfigDir(overrideDir) {
333
300
  if (overrideDir) return overrideDir;
334
301
  const xdg = process.env["XDG_CONFIG_HOME"];
335
- const base = xdg || path.join(os.homedir(), ".config");
336
- return path.join(base, APP_NAME);
302
+ const base = xdg || path2.join(os.homedir(), ".config");
303
+ return path2.join(base, APP_NAME);
337
304
  }
338
305
  function getConfigPath(overrideDir) {
339
- return path.join(getConfigDir(overrideDir), CONFIG_FILE);
306
+ return path2.join(getConfigDir(overrideDir), CONFIG_FILE);
340
307
  }
341
308
 
342
309
  // src/config/schema.ts
@@ -366,7 +333,7 @@ function validateConfig(data) {
366
333
 
367
334
  // src/config/store.ts
368
335
  import * as fs from "node:fs";
369
- import * as path2 from "node:path";
336
+ import * as path3 from "node:path";
370
337
  var DIR_MODE = 448;
371
338
  var FILE_MODE = 384;
372
339
  function ensureConfigDir(configDir) {
@@ -403,7 +370,7 @@ function loadConfig(overrideDir) {
403
370
  }
404
371
  function saveConfig(config2, overrideDir) {
405
372
  const configDir = getConfigDir(overrideDir);
406
- const configPath = path2.join(configDir, "config.json");
373
+ const configPath = path3.join(configDir, "config.json");
407
374
  ensureConfigDir(configDir);
408
375
  const json = JSON.stringify(config2, null, 2) + "\n";
409
376
  fs.writeFileSync(configPath, json, { mode: FILE_MODE });
@@ -600,38 +567,53 @@ function authLogout(opts = {}) {
600
567
 
601
568
  // src/commands/init.ts
602
569
  import * as fs4 from "node:fs";
603
- import * as path5 from "node:path";
570
+ import * as path6 from "node:path";
604
571
  import * as readline2 from "node:readline";
605
572
 
606
573
  // src/config/docs-config.ts
607
574
  import * as fs3 from "node:fs";
608
- import * as path4 from "node:path";
575
+ import * as path5 from "node:path";
609
576
  import YAML from "yaml";
610
577
 
611
578
  // src/renderer/navigation.ts
612
579
  import * as fs2 from "node:fs";
613
- import * as path3 from "node:path";
580
+ import * as path4 from "node:path";
614
581
  function extractTitle(markdownContent, filePath) {
615
582
  const match2 = markdownContent.match(/^#\s+(.+)$/m);
616
583
  if (match2) {
617
584
  return match2[1].trim();
618
585
  }
619
- const basename3 = path3.basename(filePath, ".md");
586
+ const basename3 = path4.basename(filePath, ".md");
620
587
  if (basename3 === "index") {
621
588
  return "Home";
622
589
  }
623
590
  return basename3.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
624
591
  }
592
+ function isSkippablePlaceholderIndex(contentDir, relativePath) {
593
+ const normalized = relativePath.replace(/\\/g, "/");
594
+ if (path4.dirname(normalized) !== ".") return false;
595
+ const full = path4.join(contentDir, normalized);
596
+ let text2;
597
+ try {
598
+ text2 = fs2.readFileSync(full, "utf-8").trim();
599
+ } catch {
600
+ return false;
601
+ }
602
+ if (text2.length === 0) return true;
603
+ if (text2.includes("Welcome to your documentation site powered by nrdocs")) return true;
604
+ if (text2.includes("Edit this file to add your documentation content")) return true;
605
+ return false;
606
+ }
625
607
  function findMarkdownFiles(dir, relativeTo) {
626
608
  const results = [];
627
609
  if (!fs2.existsSync(dir)) return results;
628
610
  const entries = fs2.readdirSync(dir, { withFileTypes: true });
629
611
  for (const entry of entries) {
630
- const fullPath = path3.join(dir, entry.name);
612
+ const fullPath = path4.join(dir, entry.name);
631
613
  if (entry.isDirectory()) {
632
614
  results.push(...findMarkdownFiles(fullPath, relativeTo));
633
615
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
634
- results.push(path3.relative(relativeTo, fullPath).replace(/\\/g, "/"));
616
+ results.push(path4.relative(relativeTo, fullPath).replace(/\\/g, "/"));
635
617
  }
636
618
  }
637
619
  return results;
@@ -654,7 +636,7 @@ function mdPathToHref(filePath) {
654
636
  return `${withoutExt}/`;
655
637
  }
656
638
  function navEntryFromFile(contentDir, file) {
657
- const fullPath = path3.join(contentDir, file);
639
+ const fullPath = path4.join(contentDir, file);
658
640
  const content = fs2.readFileSync(fullPath, "utf-8");
659
641
  return {
660
642
  title: extractTitle(content, file),
@@ -670,7 +652,7 @@ function groupNavEntriesByFolders(files, contentDir, indexPath = "index.md") {
670
652
  const rootLinks = [];
671
653
  const byFolder = /* @__PURE__ */ new Map();
672
654
  for (const file of sorted) {
673
- const dir = path3.dirname(file).replace(/\\/g, "/");
655
+ const dir = path4.dirname(file).replace(/\\/g, "/");
674
656
  if (dir === ".") {
675
657
  rootLinks.push(navEntryFromFile(contentDir, file));
676
658
  continue;
@@ -694,7 +676,9 @@ function groupNavEntriesByFolders(files, contentDir, indexPath = "index.md") {
694
676
  }
695
677
  function discoverNavEntries(contentDir, options) {
696
678
  const indexPath = (options?.indexPath ?? "index.md").replace(/\\/g, "/");
697
- const files = findMarkdownFiles(contentDir, contentDir);
679
+ const files = findMarkdownFiles(contentDir, contentDir).filter(
680
+ (f) => !isSkippablePlaceholderIndex(contentDir, f)
681
+ );
698
682
  return groupNavEntriesByFolders(files, contentDir, indexPath);
699
683
  }
700
684
  function navConfigToNavItems(entries, contentDir) {
@@ -719,7 +703,7 @@ function navConfigToNavItems(entries, contentDir) {
719
703
  throw new Error("Nav has no pages (entries need path or nested children with paths)");
720
704
  }
721
705
  for (const item of items) {
722
- const full = path3.join(contentDir, item.path);
706
+ const full = path4.join(contentDir, item.path);
723
707
  if (!fs2.existsSync(full)) {
724
708
  throw new Error(`Nav path not found: ${item.path}`);
725
709
  }
@@ -764,7 +748,7 @@ function flattenNavPaths(entries) {
764
748
 
765
749
  // src/config/docs-config.ts
766
750
  function loadDocsConfig(docsDir) {
767
- const configPath = path4.resolve(docsDir, "nrdocs.yml");
751
+ const configPath = path5.resolve(docsDir, "nrdocs.yml");
768
752
  if (!fs3.existsSync(configPath)) {
769
753
  throw new Error(`Config file not found: ${configPath}`);
770
754
  }
@@ -774,7 +758,7 @@ function loadDocsConfig(docsDir) {
774
758
  throw new Error(`Invalid config: ${configPath}`);
775
759
  }
776
760
  const sourceDir = config2.content?.source_dir ?? ".";
777
- const contentDir = path4.resolve(docsDir, sourceDir);
761
+ const contentDir = path5.resolve(docsDir, sourceDir);
778
762
  return { config: config2, configPath, contentDir };
779
763
  }
780
764
  function hasExplicitNav(config2) {
@@ -830,7 +814,7 @@ function validateNavPaths(entries, contentDir) {
830
814
  errors.push(`Duplicate nav path: ${p}`);
831
815
  }
832
816
  seen.add(p);
833
- const full = path4.join(contentDir, p);
817
+ const full = path5.join(contentDir, p);
834
818
  if (!fs3.existsSync(full)) {
835
819
  errors.push(`Nav path not found: ${p}`);
836
820
  }
@@ -1011,11 +995,11 @@ async function handleInit(args2) {
1011
995
  process.exit(2);
1012
996
  }
1013
997
  const docsDir = opts.docsDir || "docs";
1014
- const docsPath = path5.resolve(docsDir);
1015
- const configFile = path5.join(docsPath, "nrdocs.yml");
998
+ const docsPath = path6.resolve(docsDir);
999
+ const configFile = path6.join(docsPath, "nrdocs.yml");
1016
1000
  const existing = readExistingConfig(configFile);
1017
1001
  const configExists = fs4.existsSync(configFile);
1018
- const dirName = path5.basename(process.cwd());
1002
+ const dirName = path6.basename(process.cwd());
1019
1003
  let title = opts.title || existing.title;
1020
1004
  if (!title) {
1021
1005
  title = await prompt2("Site title", `${dirName} Docs`);
@@ -1048,8 +1032,8 @@ async function handleInit(args2) {
1048
1032
  process.exit(2);
1049
1033
  }
1050
1034
  apiUrl = normalizeUrl(apiUrl);
1051
- const workflowDir = path5.resolve(".github", "workflows");
1052
- const workflowFile = path5.join(workflowDir, "nrdocs.yml");
1035
+ const workflowDir = path6.resolve(".github", "workflows");
1036
+ const workflowFile = path6.join(workflowDir, "nrdocs.yml");
1053
1037
  if (!opts.force && fs4.existsSync(workflowFile)) {
1054
1038
  console.error("Error: Workflow already exists:");
1055
1039
  console.error(` ${workflowFile}`);
@@ -1071,12 +1055,12 @@ async function handleInit(args2) {
1071
1055
  console.log("");
1072
1056
  console.log("Created/updated:");
1073
1057
  if (createdConfig) {
1074
- console.log(` ${path5.relative(process.cwd(), configFile)}`);
1058
+ console.log(` ${path6.relative(process.cwd(), configFile)}`);
1075
1059
  }
1076
- console.log(` ${path5.relative(process.cwd(), workflowFile)}`);
1060
+ console.log(` ${path6.relative(process.cwd(), workflowFile)}`);
1077
1061
  if (!createdConfig) {
1078
1062
  console.log("");
1079
- console.log(`Using existing: ${path5.relative(process.cwd(), configFile)}`);
1063
+ console.log(`Using existing: ${path6.relative(process.cwd(), configFile)}`);
1080
1064
  }
1081
1065
  if (navPageCount > 0) {
1082
1066
  console.log(` content.nav: ${navPageCount} page(s) from markdown under ${docsDir}/`);
@@ -1086,7 +1070,7 @@ async function handleInit(args2) {
1086
1070
  if (navPageCount === 0) {
1087
1071
  console.log(` 1. Add markdown files under ${docsDir}/, then run: nrdocs nav generate`);
1088
1072
  } else {
1089
- console.log(` 1. Edit content.nav in ${path5.relative(process.cwd(), configFile)} to reorder pages`);
1073
+ console.log(` 1. Edit content.nav in ${path6.relative(process.cwd(), configFile)} to reorder pages`);
1090
1074
  }
1091
1075
  console.log(" 2. Commit and push to trigger the workflow");
1092
1076
  console.log(" 3. Ask your operator to approve the repo");
@@ -1097,7 +1081,7 @@ import * as fs8 from "node:fs";
1097
1081
 
1098
1082
  // src/renderer/index.ts
1099
1083
  import * as fs7 from "node:fs";
1100
- import * as path8 from "node:path";
1084
+ import * as path9 from "node:path";
1101
1085
 
1102
1086
  // ../../node_modules/.pnpm/markdown-it@14.1.1/node_modules/markdown-it/lib/common/utils.mjs
1103
1087
  var utils_exports = {};
@@ -6588,9 +6572,63 @@ function escapeHtml2(str) {
6588
6572
 
6589
6573
  // src/renderer/assets.ts
6590
6574
  import * as fs5 from "node:fs";
6591
- import * as path6 from "node:path";
6575
+ import * as path7 from "node:path";
6576
+
6577
+ // ../shared/dist/constants.js
6578
+ var ALLOWED_ASSET_EXTENSIONS = /* @__PURE__ */ new Set([
6579
+ ".html",
6580
+ ".css",
6581
+ ".json",
6582
+ ".svg",
6583
+ ".png",
6584
+ ".jpg",
6585
+ ".jpeg",
6586
+ ".gif",
6587
+ ".webp",
6588
+ ".ico",
6589
+ ".txt",
6590
+ ".pdf"
6591
+ ]);
6592
+ var REJECTED_EXTENSIONS = /* @__PURE__ */ new Set([".js", ".mjs", ".cjs"]);
6593
+
6594
+ // ../shared/dist/naming.js
6595
+ var INSTANCE_NAME_REGEX = /^[a-z0-9]([a-z0-9-]{0,18}[a-z0-9])?$/;
6596
+ var MAX_INSTANCE_LENGTH = 20;
6597
+ function validateInstanceName(name) {
6598
+ if (!name) {
6599
+ return { valid: false, error: "Instance name cannot be empty" };
6600
+ }
6601
+ if (name.length > MAX_INSTANCE_LENGTH) {
6602
+ return { valid: false, error: `Instance name must be ${MAX_INSTANCE_LENGTH} characters or fewer` };
6603
+ }
6604
+ if (!INSTANCE_NAME_REGEX.test(name)) {
6605
+ return {
6606
+ valid: false,
6607
+ error: "Instance name must be lowercase alphanumeric with hyphens, cannot start or end with a hyphen"
6608
+ };
6609
+ }
6610
+ return { valid: true };
6611
+ }
6612
+ function getWorkerName(instance) {
6613
+ return `nrdocs-${instance}`;
6614
+ }
6615
+ function getD1Name(instance) {
6616
+ return `nrdocs-${instance}-db`;
6617
+ }
6618
+ function getR2BucketName(instance) {
6619
+ return `nrdocs-${instance}-artifacts`;
6620
+ }
6621
+ function getResourceNames(instance) {
6622
+ return {
6623
+ worker: getWorkerName(instance),
6624
+ d1: getD1Name(instance),
6625
+ r2: getR2BucketName(instance)
6626
+ };
6627
+ }
6628
+
6629
+ // src/renderer/assets.ts
6592
6630
  function collectAssets(docsDir) {
6593
- const resolvedDocsDir = path6.resolve(docsDir);
6631
+ const resolvedDocsDir = path7.resolve(docsDir);
6594
6632
  const files = [];
6595
6633
  collectFromDir(resolvedDocsDir, resolvedDocsDir, files);
6596
6634
  return files;
@@ -6603,8 +6641,8 @@ function collectFromDir(dir, rootDir, results) {
6603
6641
  return;
6604
6642
  }
6605
6643
  for (const entry of entries) {
6606
- const fullPath = path6.join(dir, entry.name);
6607
- const resolved = path6.resolve(fullPath);
6644
+ const fullPath = path7.join(dir, entry.name);
6645
+ const resolved = path7.resolve(fullPath);
6608
6646
  if (!resolved.startsWith(rootDir)) {
6609
6647
  continue;
6610
6648
  }
@@ -6612,11 +6650,11 @@ function collectFromDir(dir, rootDir, results) {
6612
6650
  if (entry.name.startsWith(".")) continue;
6613
6651
  collectFromDir(fullPath, rootDir, results);
6614
6652
  } else if (entry.isFile()) {
6615
- const ext = path6.extname(entry.name).toLowerCase();
6653
+ const ext = path7.extname(entry.name).toLowerCase();
6616
6654
  if (ext === ".md") continue;
6617
6655
  if (REJECTED_EXTENSIONS.has(ext)) continue;
6618
6656
  if (!ALLOWED_ASSET_EXTENSIONS.has(ext)) continue;
6619
- const relativePath = path6.relative(rootDir, fullPath);
6657
+ const relativePath = path7.relative(rootDir, fullPath);
6620
6658
  if (relativePath.includes("..")) continue;
6621
6659
  results.push({
6622
6660
  path: relativePath.replace(/\\/g, "/"),
@@ -6628,15 +6666,15 @@ function collectFromDir(dir, rootDir, results) {
6628
6666
 
6629
6667
  // src/renderer/mermaid-runtime.ts
6630
6668
  import * as fs6 from "node:fs";
6631
- import * as path7 from "node:path";
6632
- import { fileURLToPath } from "node:url";
6633
- var __dirname = path7.dirname(fileURLToPath(import.meta.url));
6669
+ import * as path8 from "node:path";
6670
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
6671
+ var __dirname = path8.dirname(fileURLToPath2(import.meta.url));
6634
6672
  var MERMAID_RUNTIME_REL = "runtime/mermaid.min.js";
6635
6673
  var MERMAID_ARTIFACT_PATH = "_nrdocs/mermaid.min.js";
6636
6674
  function mermaidRuntimeCandidates() {
6637
6675
  return [
6638
- path7.join(__dirname, MERMAID_RUNTIME_REL),
6639
- path7.join(__dirname, "../../dist/runtime/mermaid.min.js")
6676
+ path8.join(__dirname, MERMAID_RUNTIME_REL),
6677
+ path8.join(__dirname, "../../dist/runtime/mermaid.min.js")
6640
6678
  ];
6641
6679
  }
6642
6680
  function loadMermaidRuntime() {
@@ -6671,18 +6709,18 @@ function resolveNav(resolvedDocsDir, nav, indexPath) {
6671
6709
  }
6672
6710
  async function renderSite(options) {
6673
6711
  const { docsDir, siteTitle, baseUrl, owner, repo, nav, indexPath = "index.md" } = options;
6674
- const resolvedDocsDir = path8.resolve(docsDir);
6712
+ const resolvedDocsDir = path9.resolve(docsDir);
6675
6713
  const { items: navItems, sidebarConfig } = resolveNav(resolvedDocsDir, nav, indexPath);
6676
6714
  const siteBase = `/${owner}/${repo}/`;
6677
6715
  const renderedFiles = [];
6678
6716
  let siteHasMermaid = false;
6679
6717
  for (const navItem of navItems) {
6680
- const filePath = path8.join(resolvedDocsDir, navItem.path);
6718
+ const filePath = path9.join(resolvedDocsDir, navItem.path);
6681
6719
  const markdownContent = fs7.readFileSync(filePath, "utf-8");
6682
6720
  const pageHasMermaid = contentHasMermaid(markdownContent);
6683
6721
  if (pageHasMermaid) siteHasMermaid = true;
6684
6722
  let html = renderMarkdown(markdownContent);
6685
- const fileDir = path8.dirname(navItem.path);
6723
+ const fileDir = path9.dirname(navItem.path);
6686
6724
  const baseLinkPath = fileDir === "." ? "" : fileDir;
6687
6725
  html = rewriteLinks(html, baseLinkPath, owner, repo);
6688
6726
  const pageTitle = extractTitle(markdownContent, navItem.path);
@@ -6806,8 +6844,8 @@ function normalizeApiBaseUrl(url) {
6806
6844
  }
6807
6845
  function buildApiUrl(baseUrl, apiPath) {
6808
6846
  const { url } = normalizeApiBaseUrl(baseUrl);
6809
- const path12 = apiPath.startsWith("/") ? apiPath : `/${apiPath}`;
6810
- return `${url}${path12}`;
6847
+ const path13 = apiPath.startsWith("/") ? apiPath : `/${apiPath}`;
6848
+ return `${url}${path13}`;
6811
6849
  }
6812
6850
  function extractFetchError(err) {
6813
6851
  if (!(err instanceof Error)) {
@@ -6950,12 +6988,12 @@ async function probeApiStatus(baseUrl, timeoutMs = 15e3) {
6950
6988
  };
6951
6989
  }
6952
6990
  const json = await res.json();
6953
- const version = json.data?.version;
6991
+ const version2 = json.data?.version;
6954
6992
  return {
6955
6993
  ok: true,
6956
6994
  status: res.status,
6957
- message: version ? `OK (nrdocs ${version})` : "OK",
6958
- version
6995
+ message: version2 ? `OK (nrdocs ${version2})` : "OK",
6996
+ version: version2
6959
6997
  };
6960
6998
  } catch (e) {
6961
6999
  clearTimeout(timer);
@@ -7055,8 +7093,8 @@ var ApiClient = class {
7055
7093
  }
7056
7094
  };
7057
7095
  }
7058
- async request(method, path12, body, timeoutMs = DEFAULT_TIMEOUT_MS) {
7059
- const url = buildApiUrl(this.baseUrl, path12);
7096
+ async request(method, path13, body, timeoutMs = DEFAULT_TIMEOUT_MS) {
7097
+ const url = buildApiUrl(this.baseUrl, path13);
7060
7098
  const controller = new AbortController();
7061
7099
  const timer = setTimeout(() => controller.abort(), timeoutMs);
7062
7100
  const init = {
@@ -7125,8 +7163,8 @@ var ApiClient = class {
7125
7163
  });
7126
7164
  }
7127
7165
  async setSelfPasswordAllow(owner, repo, allow) {
7128
- const path12 = allow ? `/api/repos/${owner}/${repo}/allow-self-password` : `/api/repos/${owner}/${repo}/disallow-self-password`;
7129
- return this.request("POST", path12);
7166
+ const path13 = allow ? `/api/repos/${owner}/${repo}/allow-self-password` : `/api/repos/${owner}/${repo}/disallow-self-password`;
7167
+ return this.request("POST", path13);
7130
7168
  }
7131
7169
  async listRules() {
7132
7170
  return this.request("GET", "/api/auto-approval-rules");
@@ -7396,7 +7434,7 @@ async function handlePublish(args2) {
7396
7434
 
7397
7435
  // src/commands/doctor.ts
7398
7436
  import * as fs9 from "node:fs";
7399
- import * as path9 from "node:path";
7437
+ import * as path10 from "node:path";
7400
7438
  function parseDoctorArgs(args2) {
7401
7439
  const opts = {};
7402
7440
  for (const arg of args2) {
@@ -7410,7 +7448,7 @@ function countMarkdownFiles(docsDir) {
7410
7448
  let count = 0;
7411
7449
  const walk = (dir) => {
7412
7450
  for (const entry of fs9.readdirSync(dir, { withFileTypes: true })) {
7413
- const full = path9.join(dir, entry.name);
7451
+ const full = path10.join(dir, entry.name);
7414
7452
  if (entry.isDirectory()) walk(full);
7415
7453
  else if (entry.name.endsWith(".md")) count++;
7416
7454
  }
@@ -7422,14 +7460,14 @@ async function handleDoctor(args2) {
7422
7460
  const opts = parseDoctorArgs(args2);
7423
7461
  const inCI = opts.ci || process.env["GITHUB_ACTIONS"] === "true";
7424
7462
  const checks = [];
7425
- const isGitRepo = fs9.existsSync(path9.resolve(".git"));
7463
+ const isGitRepo = fs9.existsSync(path10.resolve(".git"));
7426
7464
  checks.push({
7427
7465
  section: "Repo setup",
7428
7466
  name: "Git repository",
7429
7467
  status: isGitRepo ? "ok" : "fail",
7430
7468
  message: isGitRepo ? "Found .git directory" : "Not a git repository"
7431
7469
  });
7432
- const configPath = path9.resolve("docs", "nrdocs.yml");
7470
+ const configPath = path10.resolve("docs", "nrdocs.yml");
7433
7471
  const hasConfig = fs9.existsSync(configPath);
7434
7472
  checks.push({
7435
7473
  section: "Repo setup",
@@ -7437,7 +7475,7 @@ async function handleDoctor(args2) {
7437
7475
  status: hasConfig ? "ok" : "fail",
7438
7476
  message: hasConfig ? "Found docs/nrdocs.yml" : "Missing docs/nrdocs.yml \u2014 run: nrdocs init"
7439
7477
  });
7440
- const docsDir = path9.resolve("docs");
7478
+ const docsDir = path10.resolve("docs");
7441
7479
  const mdCount = countMarkdownFiles(docsDir);
7442
7480
  checks.push({
7443
7481
  section: "Repo setup",
@@ -7445,7 +7483,7 @@ async function handleDoctor(args2) {
7445
7483
  status: mdCount > 0 ? "ok" : "warn",
7446
7484
  message: mdCount > 0 ? `${mdCount} markdown file(s) in docs/` : "No .md files in docs/ \u2014 publish will produce an empty site"
7447
7485
  });
7448
- const workflowPath = path9.resolve(".github", "workflows", "nrdocs.yml");
7486
+ const workflowPath = path10.resolve(".github", "workflows", "nrdocs.yml");
7449
7487
  const hasWorkflow = fs9.existsSync(workflowPath);
7450
7488
  checks.push({
7451
7489
  section: "Repo setup",
@@ -7626,7 +7664,7 @@ async function handleDoctor(args2) {
7626
7664
 
7627
7665
  // src/commands/nav.ts
7628
7666
  import * as fs10 from "node:fs";
7629
- import * as path10 from "node:path";
7667
+ import * as path11 from "node:path";
7630
7668
  function parseNavGenerateArgs(args2) {
7631
7669
  const opts = {};
7632
7670
  for (let i = 0; i < args2.length; i++) {
@@ -7645,8 +7683,8 @@ function parseNavGenerateArgs(args2) {
7645
7683
  }
7646
7684
  async function handleNavGenerate(args2) {
7647
7685
  const opts = parseNavGenerateArgs(args2);
7648
- const docsDir = path10.resolve(opts.docsDir ?? "docs");
7649
- const configPath = path10.join(docsDir, "nrdocs.yml");
7686
+ const docsDir = path11.resolve(opts.docsDir ?? "docs");
7687
+ const configPath = path11.join(docsDir, "nrdocs.yml");
7650
7688
  if (!fs10.existsSync(configPath)) {
7651
7689
  console.error(`Error: Config file not found: ${configPath}`);
7652
7690
  console.error("Run: nrdocs init");
@@ -7670,8 +7708,9 @@ async function handleNavGenerate(args2) {
7670
7708
  console.error(`Error: No markdown files found in ${loaded.contentDir}`);
7671
7709
  process.exit(10);
7672
7710
  }
7711
+ const pageCount = flattenNavPaths(entries).length;
7673
7712
  if (opts.json) {
7674
- console.log(JSON.stringify({ nav: entries, files: entries.length }, null, 2));
7713
+ console.log(JSON.stringify({ nav: entries, pages: pageCount }, null, 2));
7675
7714
  if (opts.dryRun) return;
7676
7715
  } else if (opts.dryRun) {
7677
7716
  console.log("# Dry run \u2014 content.nav that would be written:\n");
@@ -7680,8 +7719,11 @@ async function handleNavGenerate(args2) {
7680
7719
  }
7681
7720
  generateNavInConfig(docsDir, { generatedBy: "nrdocs nav generate", indexPath });
7682
7721
  if (!opts.json) {
7683
- console.log(`Generated navigation for ${entries.length} page(s) in ${path10.relative(process.cwd(), configPath)}`);
7684
- console.log("Edit the file to reorder or rename entries, then run publish.");
7722
+ console.log(
7723
+ `Updated content.nav (${pageCount} page(s)) in ${path11.relative(process.cwd(), configPath)}`
7724
+ );
7725
+ console.log("Only nrdocs.yml was changed \u2014 no markdown files are created or modified.");
7726
+ console.log("Edit content.nav to reorder, then publish via GitHub Actions.");
7685
7727
  }
7686
7728
  }
7687
7729
 
@@ -7689,7 +7731,7 @@ async function handleNavGenerate(args2) {
7689
7731
  import * as readline3 from "node:readline";
7690
7732
  import * as crypto from "node:crypto";
7691
7733
  import * as fs11 from "node:fs";
7692
- import * as path11 from "node:path";
7734
+ import * as path12 from "node:path";
7693
7735
  import { execSync } from "node:child_process";
7694
7736
  function parseDeployArgs(args2) {
7695
7737
  const opts = {};
@@ -7759,35 +7801,35 @@ function normalizeUrl2(url) {
7759
7801
  function packagedWorkerDir() {
7760
7802
  const cliEntry = process.argv[1];
7761
7803
  if (!cliEntry) return null;
7762
- const distDir = path11.dirname(path11.resolve(cliEntry));
7763
- const dir = path11.join(distDir, "deploy-worker");
7764
- if (fs11.existsSync(path11.join(dir, "index.js"))) return dir;
7804
+ const distDir = path12.dirname(path12.resolve(cliEntry));
7805
+ const dir = path12.join(distDir, "deploy-worker");
7806
+ if (fs11.existsSync(path12.join(dir, "index.js"))) return dir;
7765
7807
  return null;
7766
7808
  }
7767
7809
  function findWorkerDir() {
7768
7810
  const packaged = packagedWorkerDir();
7769
7811
  if (packaged) return packaged;
7770
7812
  const monorepoCandidates = [
7771
- path11.resolve("packages/worker"),
7772
- path11.resolve("../worker")
7813
+ path12.resolve("packages/worker"),
7814
+ path12.resolve("../worker")
7773
7815
  ];
7774
7816
  if (process.argv[1]) {
7775
- const cliDir = path11.dirname(path11.resolve(process.argv[1]));
7776
- monorepoCandidates.push(path11.resolve(cliDir, "../../../worker"));
7777
- monorepoCandidates.push(path11.resolve(cliDir, "../../../../packages/worker"));
7817
+ const cliDir = path12.dirname(path12.resolve(process.argv[1]));
7818
+ monorepoCandidates.push(path12.resolve(cliDir, "../../../worker"));
7819
+ monorepoCandidates.push(path12.resolve(cliDir, "../../../../packages/worker"));
7778
7820
  }
7779
7821
  for (const candidate of monorepoCandidates) {
7780
- if (fs11.existsSync(path11.join(candidate, "src", "index.ts"))) {
7822
+ if (fs11.existsSync(path12.join(candidate, "src", "index.ts"))) {
7781
7823
  return candidate;
7782
7824
  }
7783
7825
  }
7784
7826
  return null;
7785
7827
  }
7786
7828
  function isDocsContentRepo(cwd) {
7787
- return fs11.existsSync(path11.join(cwd, "docs", "nrdocs.yml")) && !fs11.existsSync(path11.join(cwd, "packages", "worker", "src", "index.ts"));
7829
+ return fs11.existsSync(path12.join(cwd, "docs", "nrdocs.yml")) && !fs11.existsSync(path12.join(cwd, "packages", "worker", "src", "index.ts"));
7788
7830
  }
7789
7831
  function workerUsesBundledEntry(workerDir) {
7790
- return fs11.existsSync(path11.join(workerDir, "index.js"));
7832
+ return fs11.existsSync(path12.join(workerDir, "index.js"));
7791
7833
  }
7792
7834
  async function handleDeploy(args2) {
7793
7835
  const opts = parseDeployArgs(args2);
@@ -7941,11 +7983,11 @@ bucket_name = "${names.r2}"
7941
7983
  [vars]
7942
7984
  BASE_URL = "${baseUrl}"
7943
7985
  `;
7944
- const wranglerPath = path11.join(workerDir, "wrangler.toml");
7986
+ const wranglerPath = path12.join(workerDir, "wrangler.toml");
7945
7987
  fs11.writeFileSync(wranglerPath, wranglerToml);
7946
7988
  console.log("\u2705 wrangler.toml generated");
7947
7989
  console.log("Applying D1 migrations...");
7948
- const migrationsDir = path11.join(workerDir, "migrations");
7990
+ const migrationsDir = path12.join(workerDir, "migrations");
7949
7991
  if (fs11.existsSync(migrationsDir)) {
7950
7992
  const migResult = runSilent(`npx wrangler d1 migrations apply ${names.d1} --remote --config "${wranglerPath}"`);
7951
7993
  if (migResult.ok) {
@@ -8914,12 +8956,13 @@ function parseAuthLogoutFlags(args2) {
8914
8956
 
8915
8957
  // src/bin.ts
8916
8958
  var args = process.argv.slice(2);
8959
+ var version = getCliVersion();
8917
8960
  if (args.includes("--version") || args.includes("-v")) {
8918
- console.log(`nrdocs ${NRDOCS_VERSION}`);
8961
+ console.log(`nrdocs ${version}`);
8919
8962
  process.exit(0);
8920
8963
  }
8921
8964
  if (args.includes("--help") || args.includes("-h") || args.length === 0) {
8922
- console.log(`nrdocs ${NRDOCS_VERSION}
8965
+ console.log(`nrdocs ${version}
8923
8966
 
8924
8967
  Usage:
8925
8968
  nrdocs <command> [options]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nrdocs",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "CLI for nrdocs - serverless docs publishing for private GitHub repos",
5
5
  "type": "module",
6
6
  "bin": {