@brandon_m_behring/book-scaffold-astro 3.5.2 → 3.5.3

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@brandon_m_behring/book-scaffold-astro",
3
3
  "description": "Astro 6 + MDX toolkit for long-form technical books. Profile-aware (academic / tools / minimal); ships Tufte typography, KaTeX, BibTeX citations, Pagefind, Cloudflare Workers deploy. See PACKAGE_DESIGN.md for the API contract.",
4
- "version": "3.5.2",
4
+ "version": "3.5.3",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": "Brandon Behring",
@@ -27,8 +27,40 @@
27
27
  */
28
28
  import { readFile, access } from 'node:fs/promises';
29
29
  import { glob } from 'node:fs/promises';
30
+ import { existsSync, readFileSync } from 'node:fs';
30
31
  import { resolve, dirname, join } from 'node:path';
31
32
 
33
+ /**
34
+ * Best-effort .env reader. Mirrors `readEnvFile` in src/types.ts; kept inline
35
+ * here because scripts/ is shipped as plain JS without compiling src/.
36
+ *
37
+ * Closes #20 — validate.mjs previously skipped the .env fallback that
38
+ * `resolveProfileWithSource` honors, so consumers who set BOOK_PROFILE in
39
+ * .env (per the SKILL.md and scaffold's create-book defaults) saw the CLI
40
+ * silently default to minimal, masking academic-profile errors.
41
+ */
42
+ function readEnvFile(path = '.env') {
43
+ try {
44
+ if (!existsSync(path)) return {};
45
+ const out = {};
46
+ for (const line of readFileSync(path, 'utf8').split(/\r?\n/)) {
47
+ const m = line.match(/^\s*([A-Z_][A-Z0-9_]*)\s*=\s*(.*?)\s*$/);
48
+ if (!m) continue;
49
+ let val = m[2] ?? '';
50
+ if (
51
+ (val.startsWith('"') && val.endsWith('"')) ||
52
+ (val.startsWith("'") && val.endsWith("'"))
53
+ ) {
54
+ val = val.slice(1, -1);
55
+ }
56
+ out[m[1]] = val;
57
+ }
58
+ return out;
59
+ } catch {
60
+ return {};
61
+ }
62
+ }
63
+
32
64
  // --help / -h: non-mutating (closes #14).
33
65
  const USAGE = `Usage: book-scaffold validate [--preset <name>]
34
66
 
@@ -67,8 +99,20 @@ const CHAPTERS_DIR = resolve(ROOT, 'src/content/chapters');
67
99
  const PUBLIC_DIR = resolve(ROOT, 'public');
68
100
  const DATA_DIR = resolve(ROOT, 'src/data');
69
101
 
70
- // Preset resolution: --preset flag > BOOK_PRESET env > BOOK_PROFILE env > 'minimal'.
71
- const PRESET = presetFromFlag ?? process.env.BOOK_PRESET ?? process.env.BOOK_PROFILE ?? 'minimal';
102
+ // Preset resolution (matches resolvePreset in src/types.ts):
103
+ // --preset flag > BOOK_PRESET env > BOOK_PROFILE env >
104
+ // .env BOOK_PRESET > .env BOOK_PROFILE > 'minimal'.
105
+ // .env fallback closes #20 — without it, consumers who set BOOK_PROFILE in
106
+ // .env (the documented convenience in SKILL.md + create-book defaults) saw
107
+ // the CLI silently default to minimal, hiding academic-profile errors.
108
+ const dotenv = readEnvFile(resolve(ROOT, '.env'));
109
+ const PRESET =
110
+ presetFromFlag ??
111
+ process.env.BOOK_PRESET ??
112
+ process.env.BOOK_PROFILE ??
113
+ dotenv.BOOK_PRESET ??
114
+ dotenv.BOOK_PROFILE ??
115
+ 'minimal';
72
116
  // Alias kept for downstream message text only; the resolution above is canonical.
73
117
  const PROFILE = PRESET;
74
118
  const REPO_ROOT = process.env.BOOK_REPO_ROOT ?? null;