@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,275 +1,133 @@
1
- /**
2
- * Quire11ty façade for Eleventy integration
3
- *
4
- * Provides a unified interface for Eleventy operations with path resolution.
5
- * Follows the singleton pattern like lib/npm and lib/git for consistency
6
- * and easy mocking in tests.
7
- *
8
- * @example Production usage
9
- * import eleventy from '#lib/11ty/index.js'
10
- * await eleventy.build({ debug: true })
11
- * const outputDir = eleventy.paths.getOutputDir()
12
- *
13
- * @example Path-only usage
14
- * import { paths } from '#lib/11ty/index.js'
15
- * const projectRoot = paths.getProjectRoot()
16
- *
17
- * @example Test mocking
18
- * const mockEleventy = {
19
- * build: sandbox.stub().resolves(),
20
- * serve: sandbox.stub().resolves(),
21
- * paths: {
22
- * getProjectRoot: () => '/project',
23
- * getOutputDir: () => '_site'
24
- * }
25
- * }
26
- * const MyCommand = await esmock('./mycommand.js', {
27
- * '#lib/11ty/index.js': { default: mockEleventy }
28
- * })
29
- *
30
- * @see https://www.11ty.dev/docs/programmatic/
31
- * @module lib/11ty
32
- */
33
1
  import { dynamicImport } from '#helpers/os-utils.js'
2
+ import { pathToFileURL } from 'node:url'
34
3
  import path from 'node:path'
35
- import paths from '#lib/project/index.js'
36
- import reporter from '#lib/reporter/index.js'
37
- import createDebug from '#debug'
38
-
39
- const debug = createDebug('lib:11ty:api')
4
+ import paths, { eleventyRoot, projectRoot } from './paths.js'
40
5
 
41
6
  /**
42
- * Configure environment variables required for Eleventy.
7
+ * A factory function to configure an instance of Eleventy
8
+ * @see https://www.11ty.dev/docs/config/#configuration-options
43
9
  *
44
- * These must be set before the Eleventy instance is created and the
45
- * `.eleventy.js` configuration file is parsed.
46
- *
47
- * Sets QUIRE_LOG_LEVEL to control output from multiple systems:
48
- * - quire-11ty chalk logger (_lib/chalk) — reads env var as level ceiling
49
- * - Vite bundler (_plugins/vite) — maps env var to Vite's logLevel option
50
- * - Directory output plugin (.eleventy.js) — conditionally registered
51
- *
52
- * CLI flag mapping:
53
- * (default) → 'warn' — spinner + warn/error only
54
- * --verbose → 'info' — adds chalk info output, directory listing, Vite info
55
- * --debug → 'debug' — adds chalk debug output, Eleventy DEBUG traces
56
- * --quiet → 'silent' — suppresses all chalk/Vite/directory output
57
- *
58
- * @see https://github.com/11ty/eleventy/issues/2655
59
- * @see packages/cli/docs/cli-output-modes.md
60
- *
61
- * @param {Object} options
62
- * @param {'production'|'development'} options.mode - Build mode
63
- * @param {boolean} options.debug - Enable Eleventy debug output
64
- * @param {boolean} options.verbose - Enable verbose output
65
- * @param {boolean} options.quiet - Suppress output
10
+ * @param {Object} options Eleventy configuration options
11
+ * @return {Eleventy} A configured instance of Eleventy
66
12
  */
67
- const configureEleventyEnv = ({ mode = 'production', debug = false, verbose = false, quiet = false } = {}) => {
68
- // Path configuration for decoupling quire-11ty from project input directory
69
- process.env.ELEVENTY_DATA = paths.getDataDir()
70
- process.env.ELEVENTY_INCLUDES = paths.getIncludesDir()
71
- process.env.ELEVENTY_LAYOUTS = paths.getLayoutsDir()
72
-
73
- // Build mode
74
- process.env.ELEVENTY_ENV = mode
13
+ const factory = async (options = {}) => {
14
+ const { config, input, output } = paths
75
15
 
76
- // Log level for quire-11ty's chalk logger
77
- if (quiet) {
78
- process.env.QUIRE_LOG_LEVEL = 'silent'
79
- } else if (debug) {
80
- process.env.QUIRE_LOG_LEVEL = 'debug'
81
- } else if (verbose) {
82
- process.env.QUIRE_LOG_LEVEL = 'info'
83
- } else {
84
- process.env.QUIRE_LOG_LEVEL = 'warn'
16
+ if (options.debug) {
17
+ console.debug('[CLI:11ty] projectRoot %s\n%o', projectRoot, paths)
85
18
  }
86
19
 
87
- // QUIRE_LOG_PREFIX and QUIRE_LOG_SHOW_LEVEL are set by the preAction hook
88
- // in main.js from config values. No action needed here — they are already
89
- // in process.env and will be read by the chalk logger at instantiation time.
90
-
91
- // Debug output
92
- if (debug) {
93
- process.env.DEBUG = 'Eleventy*'
94
- }
95
- }
96
-
97
- /**
98
- * Create an instance of Eleventy configured for Quire projects
99
- *
100
- * @param {Object} options - Eleventy configuration options
101
- * @param {boolean} [options.debug=false] - Enable debug output
102
- * @param {boolean} [options.quiet=false] - Suppress output
103
- * @param {string} [options.config] - Custom config path override
104
- * @param {'build'|'serve'|'watch'} [options.runMode='build'] - Eleventy run mode
105
- * @returns {Promise<Eleventy>} Configured Eleventy instance
106
- */
107
- const createEleventyInstance = async (options = {}) => {
108
- const config = paths.getConfigPath()
109
- const eleventyRoot = paths.getEleventyRoot()
110
- const input = paths.getInputDir()
111
- const output = paths.getOutputDir()
112
- const projectRoot = paths.getProjectRoot()
113
-
114
- debug('projectRoot: %s', projectRoot)
115
- debug('paths: %O', paths.toObject())
116
-
117
- // Dynamically import the correct version of Eleventy
20
+ /**
21
+ * Dynamically import the correct version of Eleventy
22
+ */
118
23
  const modulePath = path.join(eleventyRoot, 'node_modules', '@11ty', 'eleventy', 'src', 'Eleventy.js')
119
24
  const { default: Eleventy } = await dynamicImport(modulePath)
120
25
 
121
- // Create Eleventy instance
122
- // @see https://github.com/11ty/eleventy/blob/src/Eleventy.js
123
- const eleventy = new Eleventy(input, output, {
124
- config: (eleventyConfig) => {
125
- // Event callback when a build completes
126
- // @see https://www.11ty.dev/docs/events/#eleventy.after
127
- eleventyConfig.on('eleventy.after', async () => {
128
- debug('build complete')
129
- })
130
-
131
- return eleventyConfig
132
- },
133
- configPath: options.config || config,
134
- quietMode: options.quiet || !options.verbose,
135
- runMode: options.runMode || 'build',
136
- })
137
-
138
- return eleventy
139
- }
140
-
141
- /**
142
- * Quire11ty façade class
143
- *
144
- * Provides abstracted Eleventy operations with unified logging,
145
- * error handling, and path resolution. Stores active Eleventy
146
- * instance for cleanup registration with ProcessManager.
147
- */
148
- class Quire11ty {
149
26
  /**
150
- * Create Quire11ty instance
151
- * @param {Object} pathsInstance - Paths instance for path resolution
27
+ * Set Eleventy passthrough copy options
28
+ * @see https://www.11ty.dev/docs/copy/#advanced-options
29
+ * @see https://github.com/timkendrick/recursive-copy
152
30
  */
153
- constructor(pathsInstance) {
154
- this.paths = pathsInstance
155
- /**
156
- * Active Eleventy instance (for API mode)
157
- * @type {Eleventy|null}
158
- */
159
- this.activeInstance = null
31
+ const copyOptions = {
32
+ debug: options.debug || false
160
33
  }
161
34
 
162
35
  /**
163
- * Check if an Eleventy process is currently active
164
- * @returns {boolean}
36
+ * Set environment variables for paths relative to eleventy `input` dir,
37
+ * to allow `quire-11ty` to be decouple from the project input directory.
38
+ * Nota bene: environment variables read into the eleventy configuration
39
+ * file _must_ be set before the eleventy configuration file is parsed.
40
+ * @see https://github.com/11ty/eleventy/issues/2655
165
41
  */
166
- isActive() {
167
- return this.activeInstance !== null
168
- }
42
+ process.env.ELEVENTY_DATA = paths.data
43
+ process.env.ELEVENTY_INCLUDES = paths.includes
44
+ process.env.ELEVENTY_LAYOUTS = paths.layouts
169
45
 
170
46
  /**
171
- * Gracefully close any active Eleventy process
47
+ * Get an instance of the runtime of eleventy.
48
+ * @see https://github.com/11ty/eleventy/blob/src/Eleventy.js
172
49
  *
173
- * Calls eleventy.close() to stop the dev server and file watchers.
174
- * This method is registered with ProcessManager for signal handling.
50
+ * @param {String} input Path from which to read content templates
51
+ * @param {String} output Path where rendered files will be written
52
+ * @param {Object} options Options are merged with the Eleventy UserConfig
53
+ * @param {Object} config An eleventy configurtion object
175
54
  *
176
- * @returns {Promise<void>}
55
+ * @returns {module:11ty/eleventy/Eleventy~Eleventy}
177
56
  */
178
- async close() {
179
- if (this.activeInstance) {
180
- debug('shutting down Eleventy')
181
- try {
182
- await this.activeInstance.close()
183
- } catch (error) {
184
- // Ignore errors during shutdown (may already be closing)
185
- debug('close error (may be expected): %s', error.message)
57
+ const eleventy = new Eleventy(input, output, {
58
+ config: (eleventyConfig) => {
59
+ /**
60
+ * Override addPassthroughCopy to use _absolute_ system paths.
61
+ * @see https://www.11ty.dev/docs/copy/#passthrough-file-copy
62
+ * Nota bene: Eleventy addPassthroughCopy assumes paths are _relative_
63
+ * to the `config` file however the quire-cli separates 11ty from the
64
+ * project directory (`input`) and needs to use absolute system paths.
65
+ */
66
+ const addPassthroughCopy = eleventyConfig.addPassthroughCopy.bind(eleventyConfig)
67
+ eleventyConfig.addPassthroughCopy = (entry) => {
68
+ if (typeof entry === 'string') {
69
+ const filePath = path.resolve(entry) //path.join(projectRoot, file)
70
+ // console.debug('[11ty:API] passthrough copy %s', filePath)
71
+ return addPassthroughCopy(filePath, copyOptions)
72
+ } else {
73
+ // console.debug('[11ty:API] passthrough copy %o', entry)
74
+ entry = Object.fromEntries(
75
+ Object.entries(entry).map(([ src, dest ]) => {
76
+ return [ path.join(eleventyRoot, src), path.resolve(dest) ]
77
+ })
78
+ )
79
+ // console.debug('[11ty:API] passthrough copy %o', entry)
80
+ return addPassthroughCopy(entry, copyOptions)
81
+ }
186
82
  }
187
- this.activeInstance = null
188
- }
189
- }
190
-
191
- /**
192
- * Run Eleventy production build
193
- *
194
- * @param {Object} options - Build options
195
- * @param {boolean} [options.debug=false] - Enable debug output
196
- * @param {boolean} [options.dryRun=false] - Perform dry run without writing files
197
- * @param {boolean} [options.quiet=false] - Suppress output
198
- * @returns {Promise<void>}
199
- */
200
- async build(options = {}) {
201
- const projectRoot = this.paths.getProjectRoot()
202
- process.chdir(projectRoot)
203
-
204
- configureEleventyEnv({ mode: 'production', ...options })
205
-
206
- const eleventy = await createEleventyInstance(options)
207
83
 
208
- eleventy.setDryRun(options.dryRun)
84
+ /**
85
+ * Event callback when a build completes
86
+ * @see https://www.11ty.dev/docs/events/#eleventy.after
87
+ */
88
+ eleventyConfig.on('eleventy.after', async () => {
89
+ console.debug('[11ty:API] build complete')
90
+ })
209
91
 
210
- reporter.start('Building site...', { showElapsed: true })
92
+ return eleventyConfig
93
+ },
94
+ configPath: options.config || config,
95
+ quietMode: options.quiet || false,
96
+ })
211
97
 
212
- try {
213
- await eleventy.write()
214
- reporter.succeed('Build complete')
215
- } catch (error) {
216
- reporter.fail('Build failed')
217
- throw error
218
- }
219
- }
98
+ return eleventy
99
+ }
220
100
 
221
- /**
222
- * Run Eleventy development server
223
- *
224
- * @param {Object} options - Serve options
225
- * @param {boolean} [options.debug=false] - Enable debug output
226
- * @param {number} [options.port] - Server port
227
- * @param {boolean} [options.quiet=false] - Suppress output
228
- * @returns {Promise<void>}
229
- */
230
- async serve(options = {}) {
231
- const projectRoot = this.paths.getProjectRoot()
232
- process.chdir(projectRoot)
101
+ /**
102
+ * A wrapper module for using the Eleventy programmatic API
103
+ * @see https://www.11ty.dev/docs/programmatic/
104
+ * @todo read paths from the Quire project configuration
105
+ */
106
+ export default {
107
+ build: async (options = {}) => {
108
+ process.cwd(projectRoot)
233
109
 
234
- configureEleventyEnv({ mode: 'development', ...options })
110
+ console.info('[CLI:11ty] running eleventy build')
235
111
 
236
- const eleventy =
237
- await createEleventyInstance({ ...options, runMode: 'serve' })
112
+ process.env.ELEVENTY_ENV = 'production'
113
+ if (options.debug) process.env.DEBUG = 'Eleventy*'
238
114
 
239
- // Store reference for lifecycle management (graceful shutdown)
240
- this.activeInstance = eleventy
115
+ const eleventy = await factory(options)
241
116
 
242
- // Initialize Eleventy (required before watch/serve)
243
- await eleventy.init()
117
+ eleventy.setDryRun(options.dryrun)
244
118
 
245
- reporter.start('Building site...', { showElapsed: true })
119
+ await eleventy.write()
120
+ },
121
+ serve: async (options = {}) => {
122
+ process.cwd(projectRoot)
246
123
 
247
- // Build the site and start file watchers.
248
- // watch() performs the initial build via write(), then sets up chokidar
249
- // file watchers for incremental rebuilds on file changes.
250
- // This matches the Eleventy CLI sequence: init() → watch() → serve()
251
- // @see https://github.com/11ty/eleventy/blob/main/cmd.cjs
252
- await eleventy.watch()
124
+ console.info('[CLI:11ty] running development server')
253
125
 
254
- reporter.succeed('Build complete')
255
- reporter.start('Starting development server...')
126
+ process.env.ELEVENTY_ENV = 'development'
127
+ if (options.debug) process.env.DEBUG = 'Eleventy*'
256
128
 
257
- // Register a ready callback to resolve the spinner when the server is listening
258
- // @see https://www.11ty.dev/docs/dev-server/#options
259
- eleventy.eleventyServe.config.serverOptions = {
260
- ...eleventy.eleventyServe.config.serverOptions,
261
- ready: (server) => {
262
- const url = server.getServerUrl('localhost')
263
- reporter.succeed(`Server running at ${url}`)
264
- if (options.open) {
265
- import('open').then(({ default: open }) => open(url))
266
- }
267
- },
268
- }
129
+ const eleventy = await factory(options)
269
130
 
270
- // Start the HTTP dev server (serves the built _site/ directory)
271
131
  await eleventy.serve(options.port)
272
132
  }
273
133
  }
274
-
275
- export { Quire11ty, createEleventyInstance, configureEleventyEnv }
@@ -1,35 +1,7 @@
1
1
  import { execa } from 'execa'
2
2
  import fs from 'node:fs'
3
3
  import path from 'node:path'
4
- import paths from '#lib/project/index.js'
5
- import processManager from '#lib/process/manager.js'
6
- import reporter from '#lib/reporter/index.js'
7
- import { BuildFailedError } from '#src/errors/index.js'
8
- import createDebug from '#debug'
9
-
10
- const debug = createDebug('lib:11ty')
11
-
12
- /**
13
- * Spawn a cancellable subprocess with output piped to stdout
14
- *
15
- * @param {string[]} command - Command arguments for node
16
- * @param {Object} options - Spawn options
17
- * @param {string} options.cwd - Working directory
18
- * @param {Object} options.env - Environment variables
19
- * @returns {import('execa').ExecaChildProcess}
20
- */
21
- const spawn = (command, { cwd, env }) => {
22
- const subprocess = execa('node', command, {
23
- all: true,
24
- cwd,
25
- env,
26
- execPath: process.execPath,
27
- cancelSignal: processManager.signal,
28
- gracefulCancel: true,
29
- })
30
- subprocess.all.pipe(process.stdout)
31
- return subprocess
32
- }
4
+ import paths, { eleventyRoot, projectRoot } from './paths.js'
33
5
 
34
6
  /**
35
7
  * A factory function to configure an Eleventy CLI command
@@ -38,21 +10,20 @@ const spawn = (command, { cwd, env }) => {
38
10
  * @return {Array} Eleventy CLI options
39
11
  */
40
12
  const factory = (options = {}) => {
41
- const config = paths.getConfigPath()
42
- const eleventyRoot = paths.getEleventyRoot()
43
- const input = paths.getInputDir()
44
- const output = paths.getOutputDir()
45
- const projectRoot = paths.getProjectRoot()
13
+ const { config, input, output } = paths
46
14
 
47
- debug('projectRoot: %s', projectRoot)
48
- debug('paths: %O', paths.toObject())
15
+ if (options.debug) {
16
+ console.debug('[CLI:11ty] projectRoot %s\n%o', projectRoot, paths)
17
+ }
49
18
 
50
19
  /**
51
20
  * Use the version of Eleventy installed to `lib/quire/versions`
52
- * Nota bene: in eleventy v3 the CLI extension (".cjs") is load-bearing but v2 is simply ".js"
21
+ *
22
+ * NB: in eleventy v3 the CLI extension (".cjs") is load-bearing but v2 is simply ".js"
23
+ *
53
24
  */
54
25
  const eleventyModuleDir = path.join(eleventyRoot, 'node_modules', '@11ty', 'eleventy')
55
- const packagePath = path.join(eleventyModuleDir,'package.json')
26
+ const packagePath = path.join(eleventyModuleDir,'package.json')
56
27
 
57
28
  const pack = JSON.parse(fs.readFileSync(packagePath))
58
29
 
@@ -88,35 +59,14 @@ const factory = (options = {}) => {
88
59
  * @see https://github.com/11ty/eleventy/issues/2655
89
60
  */
90
61
  const env = {
91
- ELEVENTY_DATA: paths.getDataDir(),
92
- ELEVENTY_INCLUDES: paths.getIncludesDir(),
93
- ELEVENTY_LAYOUTS: paths.getLayoutsDir(),
94
- }
95
-
96
- // QUIRE_LOG_LEVEL controls output from the quire-11ty chalk logger,
97
- // the Vite plugin logLevel, and the directory output plugin registration.
98
- // @see packages/cli/docs/cli-output-modes.md
99
- if (options.quiet) {
100
- env.QUIRE_LOG_LEVEL = 'silent'
101
- } else if (options.debug) {
102
- env.QUIRE_LOG_LEVEL = 'debug'
103
- } else if (options.verbose) {
104
- env.QUIRE_LOG_LEVEL = 'info'
105
- } else {
106
- env.QUIRE_LOG_LEVEL = 'warn'
107
- }
108
-
109
- // Forward CLI log prefix and show-level settings (set by configureLogEnv)
110
- if (process.env.QUIRE_LOG_PREFIX !== undefined) {
111
- env.QUIRE_LOG_PREFIX = process.env.QUIRE_LOG_PREFIX
112
- }
113
- if (process.env.QUIRE_LOG_SHOW_LEVEL !== undefined) {
114
- env.QUIRE_LOG_SHOW_LEVEL = process.env.QUIRE_LOG_SHOW_LEVEL
62
+ ELEVENTY_DATA: paths.data,
63
+ ELEVENTY_INCLUDES: paths.includes,
64
+ ELEVENTY_LAYOUTS: paths.layouts,
115
65
  }
116
66
 
117
67
  if (options.debug) env.DEBUG = 'Eleventy*'
118
68
 
119
- return { command, env, projectRoot }
69
+ return { command, env }
120
70
  }
121
71
 
122
72
  /**
@@ -124,70 +74,45 @@ const factory = (options = {}) => {
124
74
  * @see https://www.11ty.dev/docs/usage/#command-line-usage
125
75
  */
126
76
  export default {
127
- /**
128
- * Run Eleventy build via CLI
129
- * @param {Object} options - Build options
130
- */
131
77
  build: async (options = {}) => {
132
- const { command, env, projectRoot } = factory(options)
78
+ console.info('[CLI:11ty] running eleventy build')
79
+
80
+ const { command, env } = factory(options)
133
81
 
134
82
  if (options.dryRun) command.push('--dryrun')
135
83
 
136
84
  env.ELEVENTY_ENV = 'production'
137
85
 
138
- reporter.start('Building site...', { showElapsed: true })
139
-
140
- try {
141
- const build = spawn(command, { cwd: projectRoot, env })
142
- await build
143
-
144
- if (build.exitCode !== 0) {
145
- throw new BuildFailedError(`Eleventy exited with code ${build.exitCode}`)
146
- }
147
- reporter.succeed('Build complete')
148
- } catch (error) {
149
- if (error.isCanceled) {
150
- debug('build cancelled')
151
- return
152
- }
153
- reporter.fail('Build failed')
154
- throw error
86
+ const build = execa('node', command, {
87
+ all: true,
88
+ cwd: projectRoot,
89
+ env,
90
+ execPath: process.execPath
91
+ })
92
+ build.all.pipe(process.stdout)
93
+ await build
94
+
95
+ if (build.exitCode !== 0) {
96
+ process.exit(build.exitCode)
155
97
  }
156
98
  },
157
99
 
158
- /**
159
- * Run Eleventy development server via CLI
160
- * @param {Object} options - Serve options
161
- */
162
100
  serve: async (options = {}) => {
163
- const { command, env, projectRoot } = factory(options)
101
+ console.info(`[CLI:11ty] running eleventy serve`)
102
+
103
+ const { command, env } = factory(options)
164
104
 
165
105
  command.push('--serve')
166
106
 
167
- const port = options.port || 8080
168
107
  if (options.port) command.push(`--port=${options.port}`)
169
108
 
170
109
  env.ELEVENTY_ENV = 'development'
171
110
 
172
- reporter.start('Starting development server...')
173
-
174
- // Resolve the spinner before the subprocess takes over stdout
175
- const url = `http://localhost:${port}`
176
- reporter.succeed(`Server running at ${url}`)
177
-
178
- if (options.open) {
179
- const { default: open } = await import('open')
180
- open(url)
181
- }
182
-
183
- try {
184
- await spawn(command, { cwd: projectRoot, env })
185
- } catch (error) {
186
- if (error.isCanceled) {
187
- debug('server stopped')
188
- return
189
- }
190
- throw error
191
- }
192
- },
111
+ await execa('node', command, {
112
+ all: true,
113
+ cwd: projectRoot,
114
+ env,
115
+ execPath: process.execPath
116
+ }).all.pipe(process.stdout)
117
+ }
193
118
  }
@@ -1,70 +1,11 @@
1
- /**
2
- * Quire Eleventy integration module
3
- *
4
- * Provides a unified façade for Eleventy operations following the singleton
5
- * pattern established by lib/npm and lib/git. Integrates with the central
6
- * ProcessManager for graceful shutdown on process signals.
7
- *
8
- * @example Recommended usage
9
- * import eleventy from '#lib/11ty/index.js'
10
- * await eleventy.build({ debug: true })
11
- * const outputDir = eleventy.paths.getOutputDir()
12
- *
13
- * @example Path-only usage (for consumers that only need paths)
14
- * import { paths } from '#lib/11ty/index.js'
15
- * const projectRoot = paths.getProjectRoot()
16
- *
17
- * @example Legacy usage (deprecated)
18
- * import { api, cli, paths } from '#lib/11ty/index.js'
19
- *
20
- * @module lib/11ty
21
- */
22
- import { Quire11ty } from './api.js'
23
- import cliModule from './cli.js'
24
- import paths, { Paths } from '#lib/project/index.js'
25
- import processManager from '#lib/process/manager.js'
1
+ import cli from './cli.js'
2
+ import api from './api.js'
3
+ import paths, { eleventyRoot, projectRoot } from './paths.js'
26
4
 
27
- /**
28
- * Quire11ty singleton instance
29
- * @type {Quire11ty}
30
- */
31
- const eleventy = new Quire11ty(paths)
32
-
33
- /**
34
- * CLI wrapper - delegates to cli.js which imports processManager directly
35
- */
36
- const cli = {
37
- build: async (options) => cliModule.build(options),
38
- serve: async (options) => cliModule.serve(options),
39
- }
40
-
41
- /**
42
- * Legacy API export for backwards compatibility
43
- *
44
- * Wraps the singleton methods to register cleanup handlers with
45
- * ProcessManager for graceful shutdown support.
46
- *
47
- * @deprecated Use default export instead: `import eleventy from '#lib/11ty/index.js'`
48
- */
49
- const api = {
50
- build: async (options) => eleventy.build(options),
51
- serve: async (options) => {
52
- processManager.onShutdown('eleventy', () => eleventy.close())
53
- try {
54
- return await eleventy.serve(options)
55
- } finally {
56
- processManager.onShutdownComplete('eleventy')
57
- }
58
- },
59
- }
60
-
61
- // Default export: unified façade
62
- export default eleventy
63
-
64
- // Named exports for backwards compatibility and path-only consumers
65
5
  export {
66
6
  api,
67
7
  cli,
8
+ eleventyRoot,
68
9
  paths,
69
- Paths,
10
+ projectRoot,
70
11
  }