@thegetty/quire-cli 1.0.0-rc.44 → 1.0.0-rc.46

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 (243) hide show
  1. package/CHANGELOG.md +0 -36
  2. package/README.md +0 -9
  3. package/bin/cli.js +1 -46
  4. package/package.json +9 -25
  5. package/src/Command.js +6 -26
  6. package/src/commands/README.md +122 -213
  7. package/src/commands/build.js +37 -45
  8. package/src/commands/clean.js +19 -33
  9. package/src/commands/conf.js +43 -0
  10. package/src/commands/create.js +14 -42
  11. package/src/commands/epub.js +31 -67
  12. package/src/commands/index.js +2 -9
  13. package/src/commands/info.js +86 -88
  14. package/src/commands/pdf.js +82 -63
  15. package/src/commands/preview.js +31 -32
  16. package/src/commands/validate.js +20 -64
  17. package/src/commands/version.js +43 -0
  18. package/src/errors/validation/validation-error.js +11 -20
  19. package/src/helpers/clean.js +1 -1
  20. package/src/helpers/is-quire.js +31 -0
  21. package/src/helpers/test-cwd.js +6 -5
  22. package/src/helpers/which.js +4 -10
  23. package/src/lib/11ty/README.md +19 -135
  24. package/src/lib/11ty/api.js +93 -235
  25. package/src/lib/11ty/cli.js +37 -112
  26. package/src/lib/11ty/index.js +5 -64
  27. package/src/lib/11ty/paths.js +103 -0
  28. package/src/lib/README.md +0 -330
  29. package/src/lib/conf/README.md +69 -86
  30. package/src/lib/conf/config.js +3 -5
  31. package/src/lib/conf/defaults.js +0 -65
  32. package/src/lib/conf/schema.js +9 -103
  33. package/src/lib/epub/README.md +2 -133
  34. package/src/lib/epub/epub.js +11 -36
  35. package/src/lib/epub/index.js +21 -111
  36. package/src/lib/epub/pandoc.js +4 -33
  37. package/src/lib/git/README.md +2 -151
  38. package/src/lib/git/index.js +13 -217
  39. package/src/lib/i18n/README.md +3 -0
  40. package/src/lib/i18n/config.js +53 -0
  41. package/src/lib/i18n/index.js +43 -0
  42. package/src/lib/i18n/localeService.js +58 -0
  43. package/src/lib/pdf/README.md +0 -131
  44. package/src/lib/pdf/index.js +21 -124
  45. package/src/lib/pdf/paged.js +52 -100
  46. package/src/lib/pdf/prince.js +37 -115
  47. package/src/lib/pdf/split.js +33 -61
  48. package/src/lib/quire/README.md +19 -0
  49. package/src/lib/quire/index.js +353 -0
  50. package/src/lib/reporter/README.md +2 -211
  51. package/src/lib/reporter/index.js +0 -607
  52. package/src/main.js +48 -221
  53. package/src/packageConfig.js +0 -17
  54. package/src/validators/utils.js +1 -2
  55. package/schemas/config.schema.json +0 -194
  56. package/schemas/figures.schema.json +0 -56
  57. package/schemas/layout.schema.json +0 -5
  58. package/schemas/objects.schema.json +0 -62
  59. package/schemas/publication.schema.json +0 -140
  60. package/schemas/references.schema.json +0 -29
  61. package/src/Command.spec.js +0 -99
  62. package/src/commands/build.spec.js +0 -113
  63. package/src/commands/build.test.js +0 -397
  64. package/src/commands/clean.spec.js +0 -118
  65. package/src/commands/clean.test.js +0 -382
  66. package/src/commands/config.js +0 -238
  67. package/src/commands/config.spec.js +0 -107
  68. package/src/commands/config.test.js +0 -845
  69. package/src/commands/create.spec.js +0 -112
  70. package/src/commands/create.test.js +0 -415
  71. package/src/commands/doctor.js +0 -251
  72. package/src/commands/doctor.spec.js +0 -115
  73. package/src/commands/doctor.test.js +0 -1409
  74. package/src/commands/epub.spec.js +0 -114
  75. package/src/commands/epub.test.js +0 -503
  76. package/src/commands/help.js +0 -60
  77. package/src/commands/help.test.js +0 -132
  78. package/src/commands/info.spec.js +0 -72
  79. package/src/commands/info.test.js +0 -512
  80. package/src/commands/pdf.spec.js +0 -114
  81. package/src/commands/pdf.test.js +0 -464
  82. package/src/commands/preview.spec.js +0 -97
  83. package/src/commands/preview.test.js +0 -250
  84. package/src/commands/use.js +0 -56
  85. package/src/commands/use.spec.js +0 -61
  86. package/src/commands/use.test.js +0 -280
  87. package/src/commands/validate.spec.js +0 -90
  88. package/src/commands/validate.test.js +0 -378
  89. package/src/commands/workflows.js +0 -70
  90. package/src/errors/build/build-failed-error.js +0 -19
  91. package/src/errors/build/config-field-missing-error.js +0 -20
  92. package/src/errors/build/config-file-not-found-error.js +0 -20
  93. package/src/errors/build/index.js +0 -11
  94. package/src/errors/help/help-topic-not-found-error.js +0 -30
  95. package/src/errors/help/index.js +0 -8
  96. package/src/errors/index.js +0 -58
  97. package/src/errors/input/index.js +0 -8
  98. package/src/errors/input/invalid-input-error.js +0 -21
  99. package/src/errors/install/dependency-install-error.js +0 -19
  100. package/src/errors/install/directory-not-empty-error.js +0 -25
  101. package/src/errors/install/index.js +0 -12
  102. package/src/errors/install/invalid-path-error.js +0 -31
  103. package/src/errors/install/invalid-starter-error.js +0 -27
  104. package/src/errors/install/version-not-found-error.js +0 -35
  105. package/src/errors/output/epub-generation-error.js +0 -19
  106. package/src/errors/output/index.js +0 -14
  107. package/src/errors/output/invalid-epub-library-error.js +0 -20
  108. package/src/errors/output/invalid-pdf-library-error.js +0 -20
  109. package/src/errors/output/missing-build-output-error.js +0 -21
  110. package/src/errors/output/pdf-generation-error.js +0 -24
  111. package/src/errors/output/tool-not-found-error.js +0 -37
  112. package/src/errors/project/index.js +0 -10
  113. package/src/errors/project/not-in-project-error.js +0 -20
  114. package/src/errors/project/project-create-error.js +0 -21
  115. package/src/errors/quire-error.js +0 -27
  116. package/src/errors/validation/index.js +0 -3
  117. package/src/errors/validation/unknown-config-key-error.js +0 -27
  118. package/src/errors/validation/unknown-config-operation-error.js +0 -24
  119. package/src/helpers/docs-url.js +0 -32
  120. package/src/helpers/pager.js +0 -59
  121. package/src/helpers/pager.test.js +0 -85
  122. package/src/helpers/suggest-similar.js +0 -124
  123. package/src/helpers/suggest-similar.test.js +0 -108
  124. package/src/helpers/test-cwd.test.js +0 -192
  125. package/src/lib/11ty/index.test.js +0 -655
  126. package/src/lib/commander/index.js +0 -103
  127. package/src/lib/commander/index.test.js +0 -86
  128. package/src/lib/commander/options.js +0 -237
  129. package/src/lib/commander/options.test.js +0 -205
  130. package/src/lib/conf/build-status.js +0 -103
  131. package/src/lib/conf/build-status.test.js +0 -247
  132. package/src/lib/conf/config.test.js +0 -281
  133. package/src/lib/conf/format.js +0 -60
  134. package/src/lib/conf/format.test.js +0 -106
  135. package/src/lib/conf/helpers.js +0 -91
  136. package/src/lib/conf/helpers.test.js +0 -136
  137. package/src/lib/conf/index.js +0 -22
  138. package/src/lib/constants.js +0 -28
  139. package/src/lib/doctor/README.md +0 -667
  140. package/src/lib/doctor/checks/environment/cli-version.js +0 -62
  141. package/src/lib/doctor/checks/environment/cli-version.test.js +0 -132
  142. package/src/lib/doctor/checks/environment/git-available.js +0 -77
  143. package/src/lib/doctor/checks/environment/git-available.test.js +0 -52
  144. package/src/lib/doctor/checks/environment/index.js +0 -13
  145. package/src/lib/doctor/checks/environment/node-version.js +0 -66
  146. package/src/lib/doctor/checks/environment/node-version.test.js +0 -17
  147. package/src/lib/doctor/checks/environment/npm-available.js +0 -66
  148. package/src/lib/doctor/checks/environment/npm-available.test.js +0 -52
  149. package/src/lib/doctor/checks/environment/os-info.js +0 -48
  150. package/src/lib/doctor/checks/environment/os-info.test.js +0 -81
  151. package/src/lib/doctor/checks/environment/runtime-info.js +0 -51
  152. package/src/lib/doctor/checks/environment/runtime-info.test.js +0 -132
  153. package/src/lib/doctor/checks/outputs/epub-output.js +0 -119
  154. package/src/lib/doctor/checks/outputs/epub-output.test.js +0 -277
  155. package/src/lib/doctor/checks/outputs/index.js +0 -10
  156. package/src/lib/doctor/checks/outputs/pdf-output.js +0 -144
  157. package/src/lib/doctor/checks/outputs/pdf-output.test.js +0 -377
  158. package/src/lib/doctor/checks/outputs/stale-build.js +0 -122
  159. package/src/lib/doctor/checks/outputs/stale-build.test.js +0 -282
  160. package/src/lib/doctor/checks/project/data-files.js +0 -56
  161. package/src/lib/doctor/checks/project/data-files.test.js +0 -125
  162. package/src/lib/doctor/checks/project/dependencies.js +0 -53
  163. package/src/lib/doctor/checks/project/dependencies.test.js +0 -71
  164. package/src/lib/doctor/checks/project/index.js +0 -11
  165. package/src/lib/doctor/checks/project/quire-11ty.js +0 -98
  166. package/src/lib/doctor/checks/project/quire-11ty.test.js +0 -170
  167. package/src/lib/doctor/checks/project/quire-project.js +0 -38
  168. package/src/lib/doctor/checks/project/quire-project.test.js +0 -47
  169. package/src/lib/doctor/checks/tools/index.js +0 -10
  170. package/src/lib/doctor/checks/tools/pandoc-available.js +0 -82
  171. package/src/lib/doctor/checks/tools/pandoc-available.test.js +0 -73
  172. package/src/lib/doctor/checks/tools/prince-available.js +0 -81
  173. package/src/lib/doctor/checks/tools/prince-available.test.js +0 -73
  174. package/src/lib/doctor/constants.js +0 -39
  175. package/src/lib/doctor/formatDuration.js +0 -108
  176. package/src/lib/doctor/formatDuration.test.js +0 -76
  177. package/src/lib/doctor/formatters/human.js +0 -257
  178. package/src/lib/doctor/formatters/human.test.js +0 -463
  179. package/src/lib/doctor/formatters/index.js +0 -8
  180. package/src/lib/doctor/formatters/json.js +0 -78
  181. package/src/lib/doctor/formatters/json.test.js +0 -174
  182. package/src/lib/doctor/formatters/shared.js +0 -129
  183. package/src/lib/doctor/formatters/shared.test.js +0 -194
  184. package/src/lib/doctor/index.js +0 -271
  185. package/src/lib/doctor/index.test.js +0 -797
  186. package/src/lib/epub/engines.js +0 -46
  187. package/src/lib/epub/index.test.js +0 -518
  188. package/src/lib/epub/pandoc.test.js +0 -122
  189. package/src/lib/epub/schema.js +0 -21
  190. package/src/lib/error/README.md +0 -170
  191. package/src/lib/error/handler.js +0 -107
  192. package/src/lib/git/index.spec.js +0 -80
  193. package/src/lib/git/index.test.js +0 -453
  194. package/src/lib/help/frontmatter.js +0 -77
  195. package/src/lib/help/frontmatter.test.js +0 -139
  196. package/src/lib/help/index.js +0 -146
  197. package/src/lib/help/index.test.js +0 -188
  198. package/src/lib/help/topics/configuration.md +0 -77
  199. package/src/lib/help/topics/debugging.md +0 -69
  200. package/src/lib/help/topics/epub.md +0 -74
  201. package/src/lib/help/topics/pdf.md +0 -74
  202. package/src/lib/help/topics/publishing.md +0 -80
  203. package/src/lib/help/topics/workflows.md +0 -50
  204. package/src/lib/installer/index.js +0 -309
  205. package/src/lib/installer/index.spec.js +0 -83
  206. package/src/lib/installer/index.test.js +0 -545
  207. package/src/lib/logger/README.md +0 -424
  208. package/src/lib/logger/debug.js +0 -132
  209. package/src/lib/logger/debug.spec.js +0 -130
  210. package/src/lib/logger/debug.test.js +0 -128
  211. package/src/lib/logger/index.js +0 -228
  212. package/src/lib/logger/index.spec.js +0 -131
  213. package/src/lib/logger/index.test.js +0 -578
  214. package/src/lib/npm/README.md +0 -127
  215. package/src/lib/npm/index.js +0 -198
  216. package/src/lib/npm/index.spec.js +0 -60
  217. package/src/lib/npm/index.test.js +0 -355
  218. package/src/lib/pdf/engines.js +0 -46
  219. package/src/lib/pdf/index.test.js +0 -708
  220. package/src/lib/pdf/paged.test.js +0 -366
  221. package/src/lib/pdf/prince.test.js +0 -202
  222. package/src/lib/pdf/schema.js +0 -21
  223. package/src/lib/pdf/split.test.js +0 -445
  224. package/src/lib/platform.js +0 -95
  225. package/src/lib/process/manager.js +0 -110
  226. package/src/lib/process/manager.test.js +0 -55
  227. package/src/lib/project/build.js +0 -162
  228. package/src/lib/project/build.test.js +0 -275
  229. package/src/lib/project/config.js +0 -48
  230. package/src/lib/project/config.test.js +0 -134
  231. package/src/lib/project/detect.js +0 -47
  232. package/src/lib/project/detect.test.js +0 -157
  233. package/src/lib/project/index.js +0 -56
  234. package/src/lib/project/output-paths.js +0 -87
  235. package/src/lib/project/output-paths.test.js +0 -66
  236. package/src/lib/project/paths.js +0 -272
  237. package/src/lib/project/version.js +0 -110
  238. package/src/lib/project/version.test.js +0 -350
  239. package/src/lib/reporter/index.test.js +0 -862
  240. package/src/main.spec.js +0 -61
  241. package/src/main.test.js +0 -347
  242. package/src/validators/validate-data-files.js +0 -154
  243. package/src/validators/validate-data-files.test.js +0 -217
@@ -1,667 +0,0 @@
1
- # Doctor Module
2
-
3
- Diagnostic checks for Quire environment and project health.
4
-
5
- ## Command Usage
6
-
7
- ```bash
8
- quire doctor # Run all diagnostic checks
9
- quire doctor --check environment # Check environment section only
10
- quire doctor --check node,npm # Check specific items
11
- quire doctor --verbose # Show additional details
12
- quire doctor --errors # Show only failed checks
13
- quire doctor --warnings # Show only warnings
14
- quire doctor --json # Output as JSON to stdout
15
- quire doctor --json report.json # Save JSON to file
16
- ```
17
-
18
- ### CI/Scripting
19
-
20
- The `--quiet` flag suppresses all console output, useful for CI pipelines and scripts.
21
-
22
- **Exit code only** (gate a CI step on environment health):
23
- ```bash
24
- quire doctor --check environment --quiet || exit 1
25
- ```
26
-
27
- **Save JSON report silently** (for CI artifacts):
28
- ```bash
29
- quire doctor --quiet --json reports/doctor.json
30
- ```
31
-
32
- **Exit codes:**
33
- - `0` - All checks passed (warnings don't affect exit code)
34
- - `1` - One or more checks failed
35
-
36
- ### Output Formats
37
-
38
- | Format | Flag | Use Case |
39
- |--------|------|----------|
40
- | Human | (default) | Interactive terminal use |
41
- | JSON | `--json` | Programmatic consumption, CI artifacts |
42
- | Quiet | `--quiet` | Exit code only, no output |
43
-
44
- ## Architecture
45
-
46
- ```
47
- doctor/
48
- ├── index.js # Barrel export, runners, checkSections
49
- ├── index.test.js # Integration tests for runners
50
- ├── constants.js # Re-exports from #lib/constants.js + stale thresholds
51
- ├── formatDuration.js # Human-readable time formatting
52
- ├── formatDuration.test.js # Duration formatting tests
53
- ├── README.md # This file
54
- └── checks/ # Domain-organized check modules
55
- ├── environment/ # System prerequisites
56
- │ ├── index.js # Barrel export
57
- │ ├── os-info.js # Operating system info
58
- │ ├── os-info.test.js
59
- │ ├── cli-version.js # CLI version check
60
- │ ├── cli-version.test.js
61
- │ ├── node-version.js # Node.js version check (OS-specific remediation)
62
- │ ├── node-version.test.js
63
- │ ├── npm-available.js # npm availability check (OS-specific remediation)
64
- │ ├── npm-available.test.js
65
- │ ├── git-available.js # Git availability check (OS-specific remediation)
66
- │ ├── git-available.test.js
67
- │ ├── prince-available.js # PrinceXML availability check (optional engine)
68
- │ ├── prince-available.test.js
69
- │ ├── pandoc-available.js # Pandoc availability check (optional engine)
70
- │ └── pandoc-available.test.js
71
- ├── project/ # Project configuration
72
- │ ├── index.js # Barrel export
73
- │ ├── quire-project.js # Project detection check
74
- │ ├── quire-project.test.js
75
- │ ├── dependencies.js # node_modules check
76
- │ ├── dependencies.test.js
77
- │ ├── quire-11ty.js # Version check
78
- │ ├── quire-11ty.test.js
79
- │ ├── data-files.js # YAML validation check
80
- │ └── data-files.test.js
81
- └── outputs/ # Build artifacts
82
- ├── index.js # Barrel export
83
- ├── stale-build.js # Stale build detection
84
- ├── stale-build.test.js
85
- ├── pdf-output.js # PDF output check
86
- ├── pdf-output.test.js
87
- ├── epub-output.js # EPUB output check
88
- └── epub-output.test.js
89
- ```
90
-
91
- ## Dependency Graph
92
-
93
- ```
94
- ┌─────────────────────────────────────────────────────────────────────────────┐
95
- │ doctor/index.js │
96
- │ Imports checks from domain submodules, defines checkSections, runners │
97
- └────────────────────────────────────┬────────────────────────────────────────┘
98
-
99
- ┌───────────────────────────┼───────────────────────────┐
100
- │ │ │
101
- ▼ ▼ ▼
102
- ┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
103
- │ checks/environment/ │ │ checks/project/ │ │ checks/outputs/ │
104
- │ │ │ │ │ │
105
- │ • checkOsInfo │ │ • checkQuireProject │ │ • checkStaleBuild │
106
- │ • checkCliVersion │ │ • checkDependencies │ │ • checkPdfOutput │
107
- │ • checkNodeVersion │ │ • checkOutdated... │ │ • checkEpubOutput │
108
- │ • checkNpmAvailable │ │ • checkDataFiles │ │ │
109
- │ • checkGitAvailable │ │ │ │ │
110
- │ • checkPrince... │ │ │ │ │
111
- │ • checkPandoc... │ │ │ │ │
112
- └──────────┬──────────┘ └──────────┬──────────┘ └──────────┬──────────┘
113
- │ │ │
114
- ▼ ▼ ▼
115
- ┌──────────────┐ ┌───────────────────┐ ┌──────────────────┐
116
- ┌──────────────┐ ┌───────────────────┐ ┌──────────────────┐
117
- │ constants.js │ │ validators/ │ │ #lib/project/ │
118
- │ │ │ validate-data- │ │ SOURCE_DIRS │
119
- │ DOCS_BASE_URL│ │ files.js │ │ │
120
- │ NODE_VERSION │ └───────────────────┘ └──────────────────┘
121
- │ QUIRE_11TY_ │
122
- │ PACKAGE │
123
- │ STALE_ │
124
- │ THRESHOLDS │
125
- └──────────────┘
126
- ```
127
-
128
- ## Dependencies
129
-
130
- | Module | Purpose |
131
- |--------|---------|
132
- | `#lib/platform.js` | OS detection utilities (getPlatform, Platform enum) |
133
- | `#lib/project/` | Project constants (`DATA_DIR`, `PROJECT_MARKERS`, `SOURCE_DIRECTORIES`) |
134
- | `#lib/git/` | Git availability check |
135
- | `#lib/npm/` | npm availability and registry queries |
136
- | `#lib/conf/config.js` | Configuration (updateChannel for version check, staleThreshold for output checks) |
137
- | `#src/packageConfig.js` | CLI package.json for version info |
138
- | `#src/validators/validate-data-files.js` | YAML validation logic |
139
- | `update-notifier` | Cached CLI update check info |
140
- | `semver` | Semantic version comparison |
141
- | `#lib/doctor/constants.js` | Re-exports from `#lib/constants.js` (DOCS_BASE_URL, REQUIRED_NODE_VERSION, QUIRE_11TY_PACKAGE) + STALE_THRESHOLDS, resolveStaleThreshold |
142
- | `#lib/doctor/formatDuration.js` | Human-readable time formatting |
143
-
144
- ## Check Result Type
145
-
146
- All check functions return a `CheckResult` object:
147
-
148
- ```javascript
149
- /**
150
- * @typedef {Object} CheckResult
151
- * @property {boolean} ok - Whether the check passed
152
- * @property {'error'|'warn'} [level] - Severity level (default: 'error')
153
- * @property {string|null} message - Optional message with details
154
- * @property {string|null} [remediation] - Steps to fix the issue
155
- * @property {string|null} [docsUrl] - Link to relevant documentation
156
- */
157
- ```
158
-
159
- ### Examples
160
-
161
- **Passing check:**
162
- ```javascript
163
- {
164
- ok: true,
165
- message: 'v22.0.0 (>= 22 required)'
166
- }
167
- ```
168
-
169
- **Failing check (error):**
170
- ```javascript
171
- {
172
- ok: false,
173
- message: 'npm not found in PATH',
174
- remediation: 'npm is included with Node.js...',
175
- docsUrl: 'https://quire.getty.edu/docs-v1/install-uninstall/'
176
- }
177
- ```
178
-
179
- **Failing check (warning):**
180
- ```javascript
181
- {
182
- ok: false,
183
- level: 'warn',
184
- message: 'Build output is 2 weeks older than source files',
185
- remediation: 'Run "quire build" to regenerate...',
186
- docsUrl: 'https://quire.getty.edu/docs-v1/quire-commands/'
187
- }
188
- ```
189
-
190
- ## Available Checks
191
-
192
- ### Environment Section
193
-
194
- | Check | Function | Module | Description |
195
- |-------|----------|--------|-------------|
196
- | Operating system | `checkOsInfo()` | `checks/environment/os-info.js` | Reports OS name, version, and architecture |
197
- | Quire CLI version | `checkCliVersion()` | `checks/environment/cli-version.js` | Reports CLI version and available updates |
198
- | Node.js version | `checkNodeVersion()` | `checks/environment/node-version.js` | Verifies Node.js >= 22 (OS-specific remediation) |
199
- | npm available | `checkNpmAvailable()` | `checks/environment/npm-available.js` | Verifies npm in PATH (OS-specific remediation) |
200
- | Git available | `checkGitAvailable()` | `checks/environment/git-available.js` | Verifies git in PATH (OS-specific remediation) |
201
- | PrinceXML | `checkPrinceAvailable()` | `checks/environment/prince-available.js` | Optional PDF engine (warn if missing) |
202
- | Pandoc | `checkPandocAvailable()` | `checks/environment/pandoc-available.js` | Optional EPUB engine (warn if missing) |
203
-
204
- ### Project Section
205
-
206
- | Check | Function | Module | Description |
207
- |-------|----------|--------|-------------|
208
- | Quire project | `checkQuireProject()` | `checks/project/quire-project.js` | Detects project marker files |
209
- | Dependencies | `checkDependencies()` | `checks/project/dependencies.js` | Verifies node_modules exists |
210
- | quire-11ty version | `checkOutdatedQuire11ty()` | `checks/project/quire-11ty.js` | Checks for newer quire-11ty versions |
211
- | Data files | `checkDataFiles()` | `checks/project/data-files.js` | Validates YAML files in content/_data/ |
212
-
213
- ### Outputs Section
214
-
215
- | Check | Function | Module | Description |
216
- |-------|----------|--------|-------------|
217
- | Build status | `checkStaleBuild()` | `checks/outputs/stale-build.js` | Compares source vs build timestamps |
218
- | PDF output | `checkPdfOutput()` | `checks/outputs/pdf-output.js` | Checks PDF freshness vs _site |
219
- | EPUB output | `checkEpubOutput()` | `checks/outputs/epub-output.js` | Checks EPUB freshness vs _site |
220
-
221
- ## Check Behaviors
222
-
223
- ### checkOsInfo
224
-
225
- | Scenario | Result |
226
- |----------|--------|
227
- | macOS | `ok: true` - "macOS 14 (arm64)" |
228
- | Windows | `ok: true` - "Windows (10.0.22621) (x64) - Git for Windows recommended" |
229
- | Linux | `ok: true` - "Linux (5.15.0) (x64)" |
230
-
231
- ### checkCliVersion
232
-
233
- | Scenario | Result |
234
- |----------|--------|
235
- | Up to date | `ok: true` - "v1.0.0-rc.33 (up to date)" |
236
- | Update available | `ok: false, level: warn` - "v1.0.0-rc.30 installed, v1.0.0-rc.33 available" |
237
- | No cached update info | `ok: true` - "v1.0.0-rc.33" (no "up to date" suffix) |
238
-
239
- ### checkNodeVersion
240
-
241
- | Scenario | Result |
242
- |----------|--------|
243
- | Node.js >= 22 | `ok: true` - "v22.0.0 (>= 22 required)" |
244
- | Node.js < 22 | `ok: false` - with OS-specific installation instructions |
245
-
246
- Remediation varies by platform:
247
- - **macOS**: nvm, Homebrew, or nodejs.org
248
- - **Windows**: nvm-windows, winget, or nodejs.org
249
- - **Linux**: nvm, apt, or nodejs.org
250
-
251
- ### checkNpmAvailable
252
-
253
- | Scenario | Result |
254
- |----------|--------|
255
- | npm in PATH | `ok: true` - no message |
256
- | npm not found | `ok: false` - "npm not found in PATH" with OS-specific troubleshooting |
257
-
258
- Remediation varies by platform:
259
- - **macOS**: nvm use, brew reinstall
260
- - **Windows**: Check PATH includes %APPDATA%\npm
261
- - **Linux**: nvm use, check PATH
262
-
263
- ### checkGitAvailable
264
-
265
- | Scenario | Result |
266
- |----------|--------|
267
- | git in PATH | `ok: true` - no message |
268
- | git not found | `ok: false` - "Git not found in PATH" with OS-specific installation |
269
-
270
- Remediation and docs URL vary by platform:
271
- - **macOS**: xcode-select --install or Homebrew
272
- - **Windows**: git-scm.com/download/win or winget
273
- - **Linux**: apt, dnf, or pacman
274
-
275
- ### checkPrinceAvailable (Optional Engine)
276
-
277
- | Scenario | Result |
278
- |----------|--------|
279
- | prince in PATH | `ok: true` - "installed" with path details |
280
- | prince not found | `ok: false, level: warn` - "not found (optional)" with OS-specific installation |
281
-
282
- Remediation varies by platform:
283
- - **macOS**: `brew install --cask prince` or princexml.com
284
- - **Windows**: `winget install` or princexml.com
285
- - **Linux**: Download from princexml.com
286
-
287
- ### checkPandocAvailable (Optional Engine)
288
-
289
- | Scenario | Result |
290
- |----------|--------|
291
- | pandoc in PATH | `ok: true` - "installed" with path details |
292
- | pandoc not found | `ok: false, level: warn` - "not found (optional)" with OS-specific installation |
293
-
294
- Remediation varies by platform:
295
- - **macOS**: `brew install pandoc` or pandoc.org
296
- - **Windows**: `winget install` or pandoc.org
297
- - **Linux**: `apt install pandoc`, `dnf install pandoc`, or pandoc.org
298
-
299
- ### checkQuireProject
300
-
301
- | Scenario | Result |
302
- |----------|--------|
303
- | Marker file found | `ok: true` - "Detected via .quire" |
304
- | No marker files | `ok: false` - "No Quire project marker found" |
305
-
306
- ### checkDependencies
307
-
308
- | Scenario | Result |
309
- |----------|--------|
310
- | No package.json | `ok: true` - "No package.json (not in project directory)" |
311
- | Has node_modules | `ok: true` - no message |
312
- | Missing node_modules | `ok: false` - "node_modules not found" |
313
-
314
- ### checkOutdatedQuire11ty
315
-
316
- | Scenario | Result |
317
- |----------|--------|
318
- | Not in project | `ok: true` - "quire-11ty not installed (not in project)" |
319
- | Up to date | `ok: true` - "v1.0.0-rc.33 (up to date)" |
320
- | Outdated | `ok: false, level: warn` - "v1.0.0-rc.30 installed, v1.0.0-rc.33 available" |
321
- | Can't read version | `ok: false, level: warn` - "Could not read installed quire-11ty version" |
322
- | Network error | `ok: true` - "v1.0.0-rc.30 (could not check for updates)" |
323
-
324
- ### checkDataFiles
325
-
326
- | Scenario | Result |
327
- |----------|--------|
328
- | Not in project | `ok: true` - "No content/_data directory (not in project)" |
329
- | All files valid | `ok: true` - "3 files validated" |
330
- | Missing required file | `ok: false, level: warn` - "1 issue in data files" |
331
- | YAML syntax error | `ok: false, level: warn` - with error details |
332
- | Duplicate IDs | `ok: false, level: warn` - with duplicate ID list |
333
-
334
- ### checkStaleBuild
335
-
336
- Staleness is determined by comparing source file timestamps against the `_site` build directory. A warning is only triggered when the time difference exceeds the configured `staleThreshold` setting (default: `HOURLY` = 60 minutes).
337
-
338
- | Scenario | Result |
339
- |----------|--------|
340
- | No _site directory | `ok: true` - "No build output yet (run quire build)" |
341
- | Build up to date | `ok: true` - "Build output is up to date" |
342
- | Build stale within threshold | `ok: true` - "Build output is up to date" |
343
- | Build stale beyond threshold | `ok: false, level: warn` - "Build output is 2 weeks older than source files" |
344
-
345
- ### checkPdfOutput
346
-
347
- Uses the same `staleThreshold` setting to compare PDF timestamps against `_site`. Loads project config to resolve config-aware PDF output paths.
348
-
349
- | Scenario | Result |
350
- |----------|--------|
351
- | No PDF files exist | `ok: true` - "No PDF output (run quire pdf to generate)" |
352
- | PDF exists, no _site | `ok: true` - "pagedjs.pdf exists (no _site to compare)" |
353
- | PDF up to date | `ok: true` - "pagedjs.pdf up to date" |
354
- | PDF stale within threshold | `ok: true` - "pagedjs.pdf up to date" |
355
- | PDF stale beyond threshold | `ok: false, level: warn` - "pagedjs.pdf is 2 hours older than _site" |
356
-
357
- ### checkEpubOutput
358
-
359
- Uses the same `staleThreshold` setting to compare EPUB timestamps against `_site`.
360
-
361
- | Scenario | Result |
362
- |----------|--------|
363
- | No EPUB files exist | `ok: true` - "No EPUB output (run quire epub to generate)" |
364
- | EPUB exists, no _site | `ok: true` - "epubjs.epub exists (no _site to compare)" |
365
- | EPUB up to date | `ok: true` - "epubjs.epub up to date" |
366
- | EPUB stale within threshold | `ok: true` - "epubjs.epub up to date" |
367
- | EPUB stale beyond threshold | `ok: false, level: warn` - "epubjs.epub is 2 hours older than _site" |
368
-
369
- ### Stale Threshold Configuration
370
-
371
- All output checks share the `staleThreshold` setting from `#lib/conf/config.js`. The threshold determines how much time difference is tolerated before flagging an output as stale.
372
-
373
- | Setting | Duration | Use Case |
374
- |---------|----------|----------|
375
- | `ZERO` | 0 minutes | Any time difference triggers a warning |
376
- | `SHORT` | 5 minutes | Quick iteration workflows |
377
- | `HOURLY` | 60 minutes | Default — within-session tolerance |
378
- | `DAILY` | 12 hours | Multi-session or batch workflows |
379
- | `NEVER` | Disabled | Never warn about stale outputs |
380
-
381
- ```sh
382
- ❯ quire config set staleThreshold DAILY
383
- ```
384
-
385
- The threshold is resolved by `resolveStaleThreshold()` in `constants.js`, which maps the setting name to milliseconds and falls back to `HOURLY` for unrecognized values.
386
-
387
- ## Exports
388
-
389
- ```javascript
390
- // Individual check functions (re-exported from domain modules)
391
- export { checkOsInfo }
392
- export { checkCliVersion }
393
- export { checkNodeVersion }
394
- export { checkNpmAvailable }
395
- export { checkGitAvailable }
396
- export { checkPrinceAvailable }
397
- export { checkPandocAvailable }
398
- export { checkQuireProject }
399
- export { checkDependencies }
400
- export { checkOutdatedQuire11ty }
401
- export { checkDataFiles }
402
- export { checkStaleBuild }
403
- export { checkPdfOutput }
404
- export { checkEpubOutput }
405
-
406
- // Constants
407
- export { DOCS_BASE_URL, REQUIRED_NODE_VERSION, QUIRE_11TY_PACKAGE }
408
- export { STALE_THRESHOLDS, resolveStaleThreshold }
409
-
410
- // Check collections
411
- export { checks } // Flat array of all checks (14 checks)
412
- export { checkSections } // Checks organized by section (3 sections)
413
-
414
- // Runners
415
- export { runAllChecks } // Run all, return flat results
416
- export { runAllChecksWithSections } // Run all, return by section
417
- ```
418
-
419
- ## Adding a New Check
420
-
421
- ### 1. Determine the domain
422
-
423
- - **environment/**: System prerequisites (OS info, CLI version, Node.js, npm, Git)
424
- - **project/**: Project configuration and dependencies
425
- - **outputs/**: Build artifacts and generated files
426
-
427
- ### 2. Create the check file
428
-
429
- ```javascript
430
- // checks/project/my-check.js
431
- import { DOCS_BASE_URL } from '#lib/doctor/constants.js'
432
- import createDebug from '#debug'
433
-
434
- const debug = createDebug('lib:doctor:my-check')
435
-
436
- /**
437
- * Check description here
438
- * @returns {import('../../index.js').CheckResult}
439
- */
440
- export function checkMyThing() {
441
- debug('Running my check')
442
-
443
- // Perform check logic
444
- const ok = /* condition */
445
-
446
- if (ok) {
447
- return {
448
- ok: true,
449
- message: 'Success message or null',
450
- }
451
- }
452
-
453
- return {
454
- ok: false,
455
- level: 'warn', // Optional: 'warn' for non-blocking issues
456
- message: 'What went wrong',
457
- remediation: `How to fix:\n • Step 1\n • Step 2`,
458
- docsUrl: `${DOCS_BASE_URL}/relevant-page/`,
459
- }
460
- }
461
-
462
- export default checkMyThing
463
- ```
464
-
465
- ### 3. Create the test file
466
-
467
- ```javascript
468
- // checks/project/my-check.test.js
469
- import test from 'ava'
470
- import sinon from 'sinon'
471
- import esmock from 'esmock'
472
-
473
- test.beforeEach((t) => {
474
- t.context.sandbox = sinon.createSandbox()
475
- })
476
-
477
- test.afterEach.always((t) => {
478
- t.context.sandbox.restore()
479
- })
480
-
481
- test('checkMyThing returns ok when condition met', async (t) => {
482
- const { checkMyThing } = await esmock('./my-check.js', {
483
- // Mock dependencies
484
- })
485
-
486
- const result = checkMyThing()
487
-
488
- t.true(result.ok)
489
- })
490
-
491
- test('checkMyThing returns not ok when condition fails', async (t) => {
492
- const { checkMyThing } = await esmock('./my-check.js', {
493
- // Mock dependencies for failure case
494
- })
495
-
496
- const result = checkMyThing()
497
-
498
- t.false(result.ok)
499
- t.truthy(result.remediation)
500
- t.truthy(result.docsUrl)
501
- })
502
- ```
503
-
504
- ### 4. Export from domain barrel
505
-
506
- ```javascript
507
- // checks/project/index.js
508
- export { checkQuireProject } from './quire-project.js'
509
- export { checkDependencies } from './dependencies.js'
510
- export { checkOutdatedQuire11ty } from './quire-11ty.js'
511
- export { checkDataFiles } from './data-files.js'
512
- export { checkMyThing } from './my-check.js' // Add new export
513
- ```
514
-
515
- ### 5. Add to main index.js
516
-
517
- ```javascript
518
- // In imports
519
- import {
520
- checkQuireProject,
521
- checkDependencies,
522
- checkOutdatedQuire11ty,
523
- checkDataFiles,
524
- checkMyThing, // Add new import
525
- } from './checks/project/index.js'
526
-
527
- // In re-exports
528
- export {
529
- // ... existing exports
530
- checkMyThing,
531
- }
532
-
533
- // In checkSections
534
- export const checkSections = [
535
- // ...
536
- {
537
- name: 'Project',
538
- checks: [
539
- // ... existing checks
540
- { name: 'My thing', check: checkMyThing },
541
- ],
542
- },
543
- ]
544
-
545
- // In checks (flat list)
546
- export const checks = [
547
- // ... existing checks
548
- { name: 'My thing', check: checkMyThing },
549
- ]
550
-
551
- // In default export
552
- export default {
553
- // ... existing exports
554
- checkMyThing,
555
- }
556
- ```
557
-
558
- ### 6. Update test count in index.test.js
559
-
560
- Update the assertions for check counts if needed.
561
-
562
- ## Design Principles
563
-
564
- ### Domain Organization
565
-
566
- Checks are organized by domain rather than technical concern:
567
- - **environment**: "Do I have what I need to run Quire?"
568
- - **project**: "Is my project properly configured?"
569
- - **outputs**: "Are my build outputs valid?"
570
-
571
- ### Check Independence
572
-
573
- Each check should be independent and not depend on the results of other checks. The runner executes all checks regardless of previous failures.
574
-
575
- ### Co-located Tests
576
-
577
- Each check file has its corresponding test file in the same directory:
578
- ```
579
- my-check.js
580
- my-check.test.js
581
- ```
582
-
583
- ### Graceful Degradation
584
-
585
- Checks should handle missing directories/files gracefully:
586
-
587
- ```javascript
588
- // Skip check if not in a project
589
- if (!fs.existsSync(DATA_DIR)) {
590
- return {
591
- ok: true,
592
- message: 'No content/_data directory (not in project)',
593
- }
594
- }
595
- ```
596
-
597
- ### Actionable Remediation
598
-
599
- Every failing check should include:
600
- 1. **Clear message** - What's wrong
601
- 2. **Remediation steps** - How to fix it
602
- 3. **Documentation link** - Where to learn more
603
-
604
- ## Testing
605
-
606
- Tests use AVA with esmock for ESM module mocking.
607
-
608
- ### Running Tests
609
-
610
- ```bash
611
- # All doctor tests
612
- npx ava 'src/lib/doctor/**/*.test.js'
613
-
614
- # Main integration tests
615
- npx ava src/lib/doctor/index.test.js
616
-
617
- # Domain-specific tests
618
- npx ava src/lib/doctor/checks/environment/*.test.js
619
- npx ava src/lib/doctor/checks/project/*.test.js
620
- npx ava src/lib/doctor/checks/outputs/*.test.js
621
-
622
- # Duration formatting tests
623
- npx ava src/lib/doctor/formatDuration.test.js
624
-
625
- # Related validator tests
626
- npx ava src/validators/validate-data-files.test.js
627
- ```
628
-
629
- ### Test Patterns
630
-
631
- **Mocking dependencies in domain checks:**
632
- ```javascript
633
- const { checkDataFiles } = await esmock('./data-files.js', {
634
- '#src/validators/validate-data-files.js': {
635
- validateDataFiles: sandbox.stub().returns({
636
- valid: true,
637
- errors: [],
638
- fileCount: 1,
639
- files: [],
640
- }),
641
- },
642
- })
643
- ```
644
-
645
- **Mocking filesystem:**
646
- ```javascript
647
- const { checkStaleBuild } = await esmock('./stale-build.js', {
648
- 'node:fs': {
649
- existsSync: sandbox.stub().returns(true),
650
- statSync: sandbox.stub().returns({ mtimeMs: Date.now() }),
651
- readdirSync: sandbox.stub().returns([]),
652
- },
653
- })
654
- ```
655
-
656
- ## Files Summary
657
-
658
- | File | Description |
659
- |------|-------------|
660
- | `index.js` | Barrel export, runners, checkSections |
661
- | `index.test.js` | Integration tests for runners and sections |
662
- | `constants.js` | Re-exports from `#lib/constants.js` + STALE_THRESHOLDS, resolveStaleThreshold |
663
- | `formatDuration.js` | Time duration formatting utility |
664
- | `formatDuration.test.js` | Duration formatting tests |
665
- | `checks/environment/` | Environment prerequisite checks (7 checks: os-info, cli-version, node-version, npm-available, git-available, prince-available, pandoc-available) |
666
- | `checks/project/` | Project configuration checks (4 checks) |
667
- | `checks/outputs/` | Build artifact checks (3 checks: stale-build, pdf-output, epub-output) |