@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,545 +0,0 @@
1
- import esmock from 'esmock'
2
- import path from 'node:path'
3
- import sinon from 'sinon'
4
- import test from 'ava'
5
-
6
- /**
7
- * Installer Module Integration Tests
8
- *
9
- * Tests the installer façade module behavior with mocked dependencies.
10
- */
11
-
12
- test.beforeEach((t) => {
13
- t.context.sandbox = sinon.createSandbox()
14
- })
15
-
16
- test.afterEach.always((t) => {
17
- t.context.sandbox.restore()
18
- })
19
-
20
- // ─────────────────────────────────────────────────────────────────────────────
21
- // getVersionFromPath() tests
22
- // ─────────────────────────────────────────────────────────────────────────────
23
-
24
- test('getVersionFromPath() throws InvalidPathError when path does not exist', async (t) => {
25
- const { sandbox } = t.context
26
-
27
- const mockFs = {
28
- existsSync: sandbox.stub().returns(false),
29
- readJsonSync: sandbox.stub()
30
- }
31
-
32
- const { getVersionFromPath } = await esmock('./index.js', {
33
- '#lib/npm/index.js': { default: {} },
34
- '#lib/project/index.js': {
35
- getVersionsFromStarter: sandbox.stub(),
36
- setVersion: sandbox.stub(),
37
- writeVersionFile: sandbox.stub()
38
- },
39
- '#lib/git/index.js': { default: {} },
40
- 'fs-extra': mockFs,
41
- '#helpers/is-empty.js': { isEmpty: sandbox.stub() },
42
- '#src/packageConfig.js': { default: { version: '1.0.0' } }
43
- })
44
-
45
- const error = t.throws(() => getVersionFromPath('/nonexistent/path'))
46
-
47
- t.is(error.code, 'INVALID_PATH', 'should throw InvalidPathError')
48
- t.true(error.message.includes('/nonexistent/path'))
49
- })
50
-
51
- test('getVersionFromPath() throws VersionNotFoundError when package.json is missing', async (t) => {
52
- const { sandbox } = t.context
53
-
54
- const resolvedQuirePath = path.resolve('/local/quire')
55
- const packageJsonPath = path.join(resolvedQuirePath, 'package.json')
56
-
57
- const existsSyncStub = sandbox.stub()
58
- existsSyncStub.withArgs(resolvedQuirePath).returns(true)
59
- existsSyncStub.withArgs(packageJsonPath).returns(false)
60
-
61
- const mockFs = {
62
- existsSync: existsSyncStub,
63
- readJsonSync: sandbox.stub()
64
- }
65
-
66
- const { getVersionFromPath } = await esmock('./index.js', {
67
- '#lib/npm/index.js': { default: {} },
68
- '#lib/project/index.js': {
69
- getVersionsFromStarter: sandbox.stub(),
70
- setVersion: sandbox.stub(),
71
- writeVersionFile: sandbox.stub()
72
- },
73
- '#lib/git/index.js': { default: {} },
74
- 'fs-extra': mockFs,
75
- '#helpers/is-empty.js': { isEmpty: sandbox.stub() },
76
- '#src/packageConfig.js': { default: { version: '1.0.0' } }
77
- })
78
-
79
- const error = t.throws(() => getVersionFromPath('/local/quire'))
80
-
81
- t.is(error.code, 'VERSION_NOT_FOUND', 'should throw VersionNotFoundError')
82
- t.true(error.message.includes('package.json not found'))
83
- })
84
-
85
- test('getVersionFromPath() throws VersionNotFoundError when package.json has no version', async (t) => {
86
- const { sandbox } = t.context
87
-
88
- const mockFs = {
89
- existsSync: sandbox.stub().returns(true),
90
- readJsonSync: sandbox.stub().returns({ name: '@thegetty/quire-11ty' }) // no version
91
- }
92
-
93
- const { getVersionFromPath } = await esmock('./index.js', {
94
- '#lib/npm/index.js': { default: {} },
95
- '#lib/project/index.js': {
96
- getVersionsFromStarter: sandbox.stub(),
97
- setVersion: sandbox.stub(),
98
- writeVersionFile: sandbox.stub()
99
- },
100
- '#lib/git/index.js': { default: {} },
101
- 'fs-extra': mockFs,
102
- '#helpers/is-empty.js': { isEmpty: sandbox.stub() },
103
- '#src/packageConfig.js': { default: { version: '1.0.0' } }
104
- })
105
-
106
- const error = t.throws(() => getVersionFromPath('/local/quire'))
107
-
108
- t.is(error.code, 'VERSION_NOT_FOUND', 'should throw VersionNotFoundError')
109
- t.true(error.message.includes('no version field'))
110
- })
111
-
112
- test('getVersionFromPath() returns version and resolved path when valid', async (t) => {
113
- const { sandbox } = t.context
114
-
115
- const mockFs = {
116
- existsSync: sandbox.stub().returns(true),
117
- readJsonSync: sandbox.stub().returns({ version: '1.0.0-local' })
118
- }
119
-
120
- const { getVersionFromPath } = await esmock('./index.js', {
121
- '#lib/npm/index.js': { default: {} },
122
- '#lib/project/index.js': {
123
- getVersionsFromStarter: sandbox.stub(),
124
- setVersion: sandbox.stub(),
125
- writeVersionFile: sandbox.stub()
126
- },
127
- '#lib/git/index.js': { default: {} },
128
- 'fs-extra': mockFs,
129
- '#helpers/is-empty.js': { isEmpty: sandbox.stub() },
130
- '#src/packageConfig.js': { default: { version: '1.0.0' } }
131
- })
132
-
133
- const result = getVersionFromPath('/local/quire')
134
-
135
- t.is(result.version, '1.0.0-local')
136
- t.truthy(result.resolvedPath)
137
- })
138
-
139
- // ─────────────────────────────────────────────────────────────────────────────
140
- // latest() tests
141
- // ─────────────────────────────────────────────────────────────────────────────
142
-
143
- test('latest() returns latest version when called with "latest"', async (t) => {
144
- const { sandbox } = t.context
145
-
146
- const mockNpm = {
147
- view: sandbox.stub().resolves('1.0.5'),
148
- getCompatibleVersion: sandbox.stub()
149
- }
150
-
151
- const { latest } = await esmock('./index.js', {
152
- '#lib/npm/index.js': { default: mockNpm },
153
- '#lib/project/index.js': {
154
- getVersionsFromStarter: sandbox.stub(),
155
- setVersion: sandbox.stub(),
156
- writeVersionFile: sandbox.stub()
157
- },
158
- '#lib/git/index.js': { default: {} },
159
- 'fs-extra': {},
160
- '#helpers/is-empty.js': { isEmpty: sandbox.stub() },
161
- '#src/packageConfig.js': { default: { version: '1.0.0' } }
162
- })
163
-
164
- const result = await latest('latest')
165
-
166
- t.is(result, '1.0.5')
167
- t.true(mockNpm.view.calledWith('@thegetty/quire-11ty', 'version'))
168
- })
169
-
170
- test('latest() returns latest version when called without argument', async (t) => {
171
- const { sandbox } = t.context
172
-
173
- const mockNpm = {
174
- view: sandbox.stub().resolves('1.0.5'),
175
- getCompatibleVersion: sandbox.stub()
176
- }
177
-
178
- const { latest } = await esmock('./index.js', {
179
- '#lib/npm/index.js': { default: mockNpm },
180
- '#lib/project/index.js': {
181
- getVersionsFromStarter: sandbox.stub(),
182
- setVersion: sandbox.stub(),
183
- writeVersionFile: sandbox.stub()
184
- },
185
- '#lib/git/index.js': { default: {} },
186
- 'fs-extra': {},
187
- '#helpers/is-empty.js': { isEmpty: sandbox.stub() },
188
- '#src/packageConfig.js': { default: { version: '1.0.0' } }
189
- })
190
-
191
- const result = await latest()
192
-
193
- t.is(result, '1.0.5')
194
- t.true(mockNpm.view.calledWith('@thegetty/quire-11ty', 'version'))
195
- })
196
-
197
- test('latest() resolves semver range to compatible version', async (t) => {
198
- const { sandbox } = t.context
199
-
200
- const mockNpm = {
201
- view: sandbox.stub(),
202
- getCompatibleVersion: sandbox.stub().resolves('1.2.3')
203
- }
204
-
205
- const { latest } = await esmock('./index.js', {
206
- '#lib/npm/index.js': { default: mockNpm },
207
- '#lib/project/index.js': {
208
- getVersionsFromStarter: sandbox.stub(),
209
- setVersion: sandbox.stub(),
210
- writeVersionFile: sandbox.stub()
211
- },
212
- '#lib/git/index.js': { default: {} },
213
- 'fs-extra': {},
214
- '#helpers/is-empty.js': { isEmpty: sandbox.stub() },
215
- '#src/packageConfig.js': { default: { version: '1.0.0' } }
216
- })
217
-
218
- const result = await latest('^1.0.0')
219
-
220
- t.is(result, '1.2.3')
221
- t.true(mockNpm.getCompatibleVersion.calledWith('@thegetty/quire-11ty', '^1.0.0'))
222
- t.false(mockNpm.view.called)
223
- })
224
-
225
- test('latest() throws error when no compatible version found', async (t) => {
226
- const { sandbox } = t.context
227
-
228
- const mockNpm = {
229
- view: sandbox.stub(),
230
- getCompatibleVersion: sandbox.stub().resolves(null)
231
- }
232
-
233
- const { latest } = await esmock('./index.js', {
234
- '#lib/npm/index.js': { default: mockNpm },
235
- '#lib/project/index.js': {
236
- getVersionsFromStarter: sandbox.stub(),
237
- setVersion: sandbox.stub(),
238
- writeVersionFile: sandbox.stub()
239
- },
240
- '#lib/git/index.js': { default: {} },
241
- 'fs-extra': {},
242
- '#helpers/is-empty.js': { isEmpty: sandbox.stub() },
243
- '#src/packageConfig.js': { default: { version: '1.0.0' } }
244
- })
245
-
246
- const error = await t.throwsAsync(() => latest('^99.0.0'))
247
-
248
- t.is(error.code, 'VERSION_NOT_FOUND')
249
- t.true(error.message.includes('^99.0.0'))
250
- })
251
-
252
- // ─────────────────────────────────────────────────────────────────────────────
253
- // versions() tests
254
- // ─────────────────────────────────────────────────────────────────────────────
255
-
256
- test('versions() returns all published versions', async (t) => {
257
- const { sandbox } = t.context
258
-
259
- const mockNpm = {
260
- show: sandbox.stub().resolves(['1.0.0', '1.0.1', '1.1.0'])
261
- }
262
-
263
- const { versions } = await esmock('./index.js', {
264
- '#lib/npm/index.js': { default: mockNpm },
265
- '#lib/project/index.js': {
266
- getVersionsFromStarter: sandbox.stub(),
267
- setVersion: sandbox.stub(),
268
- writeVersionFile: sandbox.stub()
269
- },
270
- '#lib/git/index.js': { default: {} },
271
- 'fs-extra': {},
272
- '#helpers/is-empty.js': { isEmpty: sandbox.stub() },
273
- '#src/packageConfig.js': { default: { version: '1.0.0' } }
274
- })
275
-
276
- const result = await versions()
277
-
278
- t.deepEqual(result, ['1.0.0', '1.0.1', '1.1.0'])
279
- t.true(mockNpm.show.calledWith('@thegetty/quire-11ty', 'versions'))
280
- })
281
-
282
- // ─────────────────────────────────────────────────────────────────────────────
283
- // initStarter() tests
284
- // ─────────────────────────────────────────────────────────────────────────────
285
-
286
- test('initStarter() throws when target directory is not empty', async (t) => {
287
- const { sandbox } = t.context
288
-
289
- const mockFs = {
290
- ensureDirSync: sandbox.stub(),
291
- remove: sandbox.stub()
292
- }
293
-
294
- // Create a mock Git class
295
- class MockGit {
296
- constructor() {}
297
- clone() { return Promise.resolve() }
298
- init() { return Promise.resolve() }
299
- add() { return Promise.resolve() }
300
- commit() { return Promise.resolve() }
301
- }
302
-
303
- const { initStarter } = await esmock('./index.js', {
304
- '#lib/npm/index.js': { default: {} },
305
- '#lib/project/index.js': {
306
- getVersionsFromStarter: sandbox.stub(),
307
- setVersion: sandbox.stub(),
308
- writeVersionFile: sandbox.stub()
309
- },
310
- '#lib/git/index.js': { Git: MockGit },
311
- 'fs-extra': mockFs,
312
- '#helpers/is-empty.js': { isEmpty: sandbox.stub().returns(false) },
313
- '#src/packageConfig.js': { default: { version: '1.0.0' } }
314
- })
315
-
316
- await t.throwsAsync(
317
- () => initStarter('https://github.com/test/starter', '/project'),
318
- { message: /non-empty directory/ }
319
- )
320
- })
321
-
322
- test('initStarter() clones starter and sets up project', async (t) => {
323
- const { sandbox } = t.context
324
-
325
- const mockFs = {
326
- ensureDirSync: sandbox.stub(),
327
- remove: sandbox.stub().resolves(),
328
- readFileSync: sandbox.stub().returns(JSON.stringify({
329
- version: '1.0.0',
330
- peerDependencies: { '@thegetty/quire-11ty': '^1.0.0' }
331
- })),
332
- writeFileSync: sandbox.stub()
333
- }
334
-
335
- // Create a mock Git class with spies
336
- const gitSpies = {
337
- clone: sandbox.stub().resolves(),
338
- init: sandbox.stub().resolves(),
339
- add: sandbox.stub().resolves(),
340
- commit: sandbox.stub().resolves()
341
- }
342
-
343
- class MockGit {
344
- constructor() {}
345
- clone(...args) { return gitSpies.clone(...args) }
346
- init(...args) { return gitSpies.init(...args) }
347
- add(...args) { return gitSpies.add(...args) }
348
- commit(...args) { return gitSpies.commit(...args) }
349
- }
350
-
351
- const mockNpm = {
352
- init: sandbox.stub().resolves(),
353
- getCompatibleVersion: sandbox.stub().resolves('1.2.0')
354
- }
355
-
356
- const { initStarter } = await esmock('./index.js', {
357
- '#lib/npm/index.js': { default: mockNpm },
358
- '#lib/project/index.js': {
359
- getVersionsFromStarter: sandbox.stub().resolves({
360
- quire11tyVersion: '^1.0.0',
361
- starterVersion: '1.0.0'
362
- }),
363
- setVersion: sandbox.stub(),
364
- writeVersionFile: sandbox.stub()
365
- },
366
- '#lib/git/index.js': { Git: MockGit },
367
- 'fs-extra': mockFs,
368
- '#helpers/is-empty.js': { isEmpty: sandbox.stub().returns(true) },
369
- '#src/packageConfig.js': { default: { version: '1.0.0' } }
370
- })
371
-
372
- const result = await initStarter('https://github.com/test/starter', '/project')
373
-
374
- t.is(result, '1.2.0', 'should return resolved quire version')
375
- t.true(gitSpies.clone.called, 'should clone starter repository')
376
- t.true(gitSpies.init.called, 'should initialize git repository')
377
- t.true(mockNpm.init.called, 'should run npm init')
378
- })
379
-
380
- // ─────────────────────────────────────────────────────────────────────────────
381
- // installer object export tests
382
- // ─────────────────────────────────────────────────────────────────────────────
383
-
384
- test('installer object exports all required functions', async (t) => {
385
- const { sandbox } = t.context
386
-
387
- // Create a mock Git class
388
- class MockGit {
389
- constructor() {}
390
- clone() { return Promise.resolve() }
391
- init() { return Promise.resolve() }
392
- add() { return Promise.resolve() }
393
- commit() { return Promise.resolve() }
394
- rm() { return Promise.resolve() }
395
- }
396
-
397
- const { installer } = await esmock('./index.js', {
398
- '#lib/npm/index.js': { default: {} },
399
- '#lib/project/index.js': {
400
- getVersionsFromStarter: sandbox.stub(),
401
- setVersion: sandbox.stub(),
402
- writeVersionFile: sandbox.stub()
403
- },
404
- '#lib/git/index.js': { Git: MockGit },
405
- 'fs-extra': {},
406
- '#helpers/is-empty.js': { isEmpty: sandbox.stub() },
407
- '#src/packageConfig.js': { default: { version: '1.0.0' } }
408
- })
409
-
410
- t.is(typeof installer.initStarter, 'function', 'should export initStarter')
411
- t.is(typeof installer.installInProject, 'function', 'should export installInProject')
412
- t.is(typeof installer.latest, 'function', 'should export latest')
413
- t.is(typeof installer.versions, 'function', 'should export versions')
414
- })
415
-
416
- // ─────────────────────────────────────────────────────────────────────────────
417
- // installInProject() quirePath validation tests
418
- // ─────────────────────────────────────────────────────────────────────────────
419
-
420
- test('installInProject() throws InvalidPathError when quirePath does not exist', async (t) => {
421
- const { sandbox } = t.context
422
-
423
- // Create a mock Git class
424
- class MockGit {
425
- constructor() {}
426
- rm() { return Promise.resolve() }
427
- add() { return Promise.resolve() }
428
- commit() { return Promise.resolve() }
429
- }
430
-
431
- const mockFs = {
432
- mkdirSync: sandbox.stub(),
433
- existsSync: sandbox.stub().returns(false)
434
- }
435
-
436
- const { installInProject } = await esmock('./index.js', {
437
- '#lib/npm/index.js': { default: {} },
438
- '#lib/project/index.js': {
439
- getVersionsFromStarter: sandbox.stub(),
440
- setVersion: sandbox.stub(),
441
- writeVersionFile: sandbox.stub()
442
- },
443
- '#lib/git/index.js': { Git: MockGit },
444
- 'fs-extra': mockFs,
445
- '#helpers/is-empty.js': { isEmpty: sandbox.stub() },
446
- '#src/packageConfig.js': { default: { version: '1.0.0' } }
447
- })
448
-
449
- const error = await t.throwsAsync(
450
- () => installInProject('/project', '1.0.0', { quirePath: '/nonexistent/path' })
451
- )
452
-
453
- t.is(error.code, 'INVALID_PATH', 'should throw InvalidPathError')
454
- t.true(error.message.includes('--quire-path does not exist'))
455
- t.true(error.message.includes('/nonexistent/path'))
456
- })
457
-
458
- test('installInProject() throws InvalidPathError with resolved path for relative quirePath', async (t) => {
459
- const { sandbox } = t.context
460
-
461
- // Create a mock Git class
462
- class MockGit {
463
- constructor() {}
464
- rm() { return Promise.resolve() }
465
- add() { return Promise.resolve() }
466
- commit() { return Promise.resolve() }
467
- }
468
-
469
- const mockFs = {
470
- mkdirSync: sandbox.stub(),
471
- existsSync: sandbox.stub().returns(false)
472
- }
473
-
474
- const { installInProject } = await esmock('./index.js', {
475
- '#lib/npm/index.js': { default: {} },
476
- '#lib/project/index.js': {
477
- getVersionsFromStarter: sandbox.stub(),
478
- setVersion: sandbox.stub(),
479
- writeVersionFile: sandbox.stub()
480
- },
481
- '#lib/git/index.js': { Git: MockGit },
482
- 'fs-extra': mockFs,
483
- '#helpers/is-empty.js': { isEmpty: sandbox.stub() },
484
- '#src/packageConfig.js': { default: { version: '1.0.0' } }
485
- })
486
-
487
- const error = await t.throwsAsync(
488
- () => installInProject('/project', '1.0.0', { quirePath: '../relative/path' })
489
- )
490
-
491
- t.is(error.code, 'INVALID_PATH', 'should throw InvalidPathError')
492
- t.true(error.message.includes('--quire-path does not exist'))
493
- t.true(error.message.includes('../relative/path'))
494
- t.true(error.message.includes('resolved to:'), 'should show resolved path for relative paths')
495
- })
496
-
497
- test('installInProject() copies from quirePath when it exists', async (t) => {
498
- const { sandbox } = t.context
499
-
500
- // Create a mock Git class
501
- class MockGit {
502
- constructor() {}
503
- rm() { return Promise.resolve() }
504
- add() { return Promise.resolve() }
505
- commit() { return Promise.resolve() }
506
- }
507
-
508
- const cpSyncStub = sandbox.stub()
509
- const rmSyncStub = sandbox.stub()
510
-
511
- const mockFs = {
512
- mkdirSync: sandbox.stub(),
513
- existsSync: sandbox.stub().returns(true),
514
- readJsonSync: sandbox.stub().returns({ version: '1.0.0-local' }),
515
- cpSync: cpSyncStub,
516
- rmSync: rmSyncStub
517
- }
518
-
519
- const mockNpm = {
520
- install: sandbox.stub().resolves()
521
- }
522
-
523
- const { installInProject } = await esmock('./index.js', {
524
- '#lib/npm/index.js': { default: mockNpm },
525
- '#lib/project/index.js': {
526
- getVersionsFromStarter: sandbox.stub(),
527
- setVersion: sandbox.stub(),
528
- writeVersionFile: sandbox.stub()
529
- },
530
- '#lib/git/index.js': { Git: MockGit },
531
- 'fs-extra': mockFs,
532
- '#helpers/is-empty.js': { isEmpty: sandbox.stub() },
533
- '#src/packageConfig.js': { default: { version: '1.0.0' } }
534
- })
535
-
536
- await installInProject('/project', '1.0.0', { quirePath: '/local/quire-11ty' })
537
-
538
- // Should copy from local path, not download
539
- t.true(cpSyncStub.called, 'should copy from local path')
540
- const [srcPath] = cpSyncStub.firstCall.args
541
- t.is(srcPath, path.resolve('/local/quire-11ty'), 'should use resolved quirePath as source')
542
- })
543
-
544
- // Nota bene: Version reading from local package.json is now done in initStarter
545
- // via getVersionFromPath, not in installInProject. See getVersionFromPath tests above.