@form8ion/javascript 15.6.0 → 15.6.1

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 (257) hide show
  1. package/package.json +4 -3
  2. package/src/code-style/index.js +3 -0
  3. package/src/code-style/lifter.js +6 -0
  4. package/src/code-style/lifter.test.js +25 -0
  5. package/src/code-style/remark/index.js +3 -0
  6. package/src/code-style/remark/lifter.js +10 -0
  7. package/src/code-style/remark/lifter.test.js +28 -0
  8. package/src/code-style/remark/scaffolder.js +38 -0
  9. package/src/code-style/remark/scaffolder.test.js +102 -0
  10. package/src/code-style/remark/tester.js +11 -0
  11. package/src/code-style/remark/tester.test.js +46 -0
  12. package/src/code-style/scaffolder.js +26 -0
  13. package/src/code-style/scaffolder.test.js +87 -0
  14. package/src/code-style/tester.js +5 -0
  15. package/src/code-style/tester.test.js +23 -0
  16. package/src/corepack/index.js +1 -0
  17. package/src/corepack/lifter.js +5 -0
  18. package/src/corepack/lifter.test.js +22 -0
  19. package/src/coverage/index.js +3 -0
  20. package/src/coverage/lifter.js +31 -0
  21. package/src/coverage/lifter.test.js +58 -0
  22. package/src/coverage/nyc/index.js +2 -0
  23. package/src/coverage/nyc/remover.js +16 -0
  24. package/src/coverage/nyc/remover.test.js +24 -0
  25. package/src/coverage/nyc/tester.js +5 -0
  26. package/src/coverage/nyc/tester.test.js +29 -0
  27. package/src/coverage/scaffolder.js +7 -0
  28. package/src/coverage/scaffolder.test.js +32 -0
  29. package/src/coverage/tester.js +10 -0
  30. package/src/coverage/tester.test.js +50 -0
  31. package/src/dependencies/index.js +3 -0
  32. package/src/dependencies/installer.js +25 -0
  33. package/src/dependencies/installer.test.js +77 -0
  34. package/src/dependencies/package-managers.js +32 -0
  35. package/src/dependencies/package-managers.test.js +46 -0
  36. package/src/dependencies/processor.js +30 -0
  37. package/src/dependencies/processor.test.js +75 -0
  38. package/src/dependencies/remover.js +10 -0
  39. package/src/dependencies/remover.test.js +28 -0
  40. package/src/dialects/babel/config/ignore-adder.js +10 -0
  41. package/src/dialects/babel/config/ignore-adder.test.js +33 -0
  42. package/src/dialects/babel/config/index.js +3 -0
  43. package/src/dialects/babel/config/loader.js +5 -0
  44. package/src/dialects/babel/config/loader.test.js +21 -0
  45. package/src/dialects/babel/config/writer.js +6 -0
  46. package/src/dialects/babel/config/writer.test.js +20 -0
  47. package/src/dialects/babel/index.js +3 -0
  48. package/src/dialects/babel/lifter.js +7 -0
  49. package/src/dialects/babel/lifter.test.js +17 -0
  50. package/src/dialects/babel/predicate.js +5 -0
  51. package/src/dialects/babel/predicate.test.js +25 -0
  52. package/src/dialects/babel/scaffolder.js +14 -0
  53. package/src/dialects/babel/scaffolder.test.js +28 -0
  54. package/src/dialects/index.js +2 -0
  55. package/src/dialects/prompt-choices.js +10 -0
  56. package/src/dialects/prompt-choices.test.js +28 -0
  57. package/src/dialects/scaffolder.js +15 -0
  58. package/src/dialects/scaffolder.test.js +49 -0
  59. package/src/dialects/typescript/index.js +1 -0
  60. package/src/dialects/typescript/scaffolder.js +31 -0
  61. package/src/dialects/typescript/scaffolder.test.js +95 -0
  62. package/src/documentation/generation-command.js +11 -0
  63. package/src/documentation/generation-command.test.js +25 -0
  64. package/src/documentation/index.js +1 -0
  65. package/src/documentation/scaffolder.js +20 -0
  66. package/src/documentation/scaffolder.test.js +49 -0
  67. package/src/engines/index.js +2 -0
  68. package/src/engines/lifter.js +7 -0
  69. package/src/engines/lifter.test.js +18 -0
  70. package/src/engines/tester.js +7 -0
  71. package/src/engines/tester.test.js +37 -0
  72. package/src/index.js +9 -0
  73. package/src/lifter.js +55 -0
  74. package/src/lifter.test.js +96 -0
  75. package/src/linting/index.js +1 -0
  76. package/src/linting/scaffolder.js +5 -0
  77. package/src/linting/scaffolder.test.js +31 -0
  78. package/src/lockfile-lint/allowed-hosts-builder.js +6 -0
  79. package/src/lockfile-lint/allowed-hosts-builder.test.js +35 -0
  80. package/src/lockfile-lint/config.js +12 -0
  81. package/src/lockfile-lint/config.test.js +37 -0
  82. package/src/lockfile-lint/index.js +3 -0
  83. package/src/lockfile-lint/scaffolder.js +38 -0
  84. package/src/lockfile-lint/scaffolder.test.js +85 -0
  85. package/src/lockfile-lint/tester.js +5 -0
  86. package/src/lockfile-lint/tester.test.js +25 -0
  87. package/src/node-version/index.js +2 -0
  88. package/src/node-version/scaffolder.js +19 -0
  89. package/src/node-version/scaffolder.test.js +33 -0
  90. package/src/node-version/tasks.js +25 -0
  91. package/src/node-version/tasks.test.js +43 -0
  92. package/src/node-version/tester.js +5 -0
  93. package/src/node-version/tester.test.js +29 -0
  94. package/src/npm-config/index.js +5 -0
  95. package/src/npm-config/lifter.js +14 -0
  96. package/src/npm-config/lifter.test.js +23 -0
  97. package/src/npm-config/reader.js +11 -0
  98. package/src/npm-config/reader.test.js +33 -0
  99. package/src/npm-config/scaffolder.js +16 -0
  100. package/src/npm-config/scaffolder.test.js +54 -0
  101. package/src/npm-config/tester.js +5 -0
  102. package/src/npm-config/tester.test.js +29 -0
  103. package/src/npm-config/writer.js +6 -0
  104. package/src/npm-config/writer.test.js +24 -0
  105. package/src/options/schemas.js +14 -0
  106. package/src/options/schemas.test.js +147 -0
  107. package/src/options/validator.js +45 -0
  108. package/src/options/validator.test.js +79 -0
  109. package/src/package/details.js +18 -0
  110. package/src/package/details.test.js +51 -0
  111. package/src/package/index.js +2 -0
  112. package/src/package/lifter.js +47 -0
  113. package/src/package/lifter.test.js +100 -0
  114. package/src/package/package-name.js +13 -0
  115. package/src/package/package-name.test.js +52 -0
  116. package/src/package/property-sorter.js +38 -0
  117. package/src/package/property-sorter.test.js +56 -0
  118. package/src/package/scaffolder.js +32 -0
  119. package/src/package/scaffolder.test.js +46 -0
  120. package/src/package/scripts/index.js +1 -0
  121. package/src/package/scripts/lifter.js +14 -0
  122. package/src/package/scripts/lifter.test.js +31 -0
  123. package/src/package/scripts/script-comparator.js +46 -0
  124. package/src/package/scripts/script-comparator.test.js +119 -0
  125. package/src/package/scripts/scripts-sorter.js +7 -0
  126. package/src/package/scripts/scripts-sorter.test.js +20 -0
  127. package/src/package/scripts/test-script-updater.js +15 -0
  128. package/src/package/scripts/test-script-updater.test.js +32 -0
  129. package/src/package/vcs-host-details.js +12 -0
  130. package/src/package/vcs-host-details.test.js +16 -0
  131. package/src/package-managers/current-manager-resolver.js +21 -0
  132. package/src/package-managers/current-manager-resolver.test.js +51 -0
  133. package/src/package-managers/index.js +5 -0
  134. package/src/package-managers/lifter.js +7 -0
  135. package/src/package-managers/lifter.test.js +18 -0
  136. package/src/package-managers/lockfile-path-resolver.js +10 -0
  137. package/src/package-managers/lockfile-path-resolver.test.js +15 -0
  138. package/src/package-managers/npm/index.js +2 -0
  139. package/src/package-managers/npm/scaffolder.js +19 -0
  140. package/src/package-managers/npm/scaffolder.test.js +33 -0
  141. package/src/package-managers/npm/tester.js +11 -0
  142. package/src/package-managers/npm/tester.test.js +33 -0
  143. package/src/package-managers/scaffolder.js +11 -0
  144. package/src/package-managers/scaffolder.test.js +27 -0
  145. package/src/package-managers/tester.js +11 -0
  146. package/src/package-managers/tester.test.js +33 -0
  147. package/src/package-managers/yarn/index.js +2 -0
  148. package/src/package-managers/yarn/scaffolder.js +19 -0
  149. package/src/package-managers/yarn/scaffolder.test.js +33 -0
  150. package/src/package-managers/yarn/tester.js +11 -0
  151. package/src/package-managers/yarn/tester.test.js +33 -0
  152. package/src/plugins-schemas.js +4 -0
  153. package/src/plugins-schemas.test.js +28 -0
  154. package/src/project-type/application/index.js +2 -0
  155. package/src/project-type/application/predicate.js +3 -0
  156. package/src/project-type/application/predicate.test.js +14 -0
  157. package/src/project-type/application/scaffolder.js +24 -0
  158. package/src/project-type/application/scaffolder.test.js +35 -0
  159. package/src/project-type/cli/index.js +3 -0
  160. package/src/project-type/cli/lifter.js +5 -0
  161. package/src/project-type/cli/lifter.test.js +20 -0
  162. package/src/project-type/cli/scaffolder.js +52 -0
  163. package/src/project-type/cli/scaffolder.test.js +103 -0
  164. package/src/project-type/cli/tester.js +3 -0
  165. package/src/project-type/cli/tester.test.js +14 -0
  166. package/src/project-type/index.js +3 -0
  167. package/src/project-type/lifter.js +23 -0
  168. package/src/project-type/lifter.test.js +69 -0
  169. package/src/project-type/monorepo/index.js +1 -0
  170. package/src/project-type/monorepo/scaffolder.js +16 -0
  171. package/src/project-type/monorepo/scaffolder.test.js +27 -0
  172. package/src/project-type/package/build-details.js +56 -0
  173. package/src/project-type/package/build-details.test.js +111 -0
  174. package/src/project-type/package/documentation.js +34 -0
  175. package/src/project-type/package/documentation.test.js +106 -0
  176. package/src/project-type/package/index.js +3 -0
  177. package/src/project-type/package/lifter.js +5 -0
  178. package/src/project-type/package/lifter.test.js +20 -0
  179. package/src/project-type/package/scaffolder.js +84 -0
  180. package/src/project-type/package/scaffolder.test.js +267 -0
  181. package/src/project-type/package/tester.js +5 -0
  182. package/src/project-type/package/tester.test.js +28 -0
  183. package/src/project-type/publishable/access-level.js +3 -0
  184. package/src/project-type/publishable/access-level.test.js +13 -0
  185. package/src/project-type/publishable/badges.js +20 -0
  186. package/src/project-type/publishable/badges.test.js +29 -0
  187. package/src/project-type/publishable/bundler/index.js +1 -0
  188. package/src/project-type/publishable/bundler/prompt.js +16 -0
  189. package/src/project-type/publishable/bundler/prompt.test.js +35 -0
  190. package/src/project-type/publishable/bundler/scaffolder.js +8 -0
  191. package/src/project-type/publishable/bundler/scaffolder.test.js +33 -0
  192. package/src/project-type/publishable/index.js +2 -0
  193. package/src/project-type/publishable/lifter.js +24 -0
  194. package/src/project-type/publishable/lifter.test.js +49 -0
  195. package/src/project-type/publishable/provenance/index.js +1 -0
  196. package/src/project-type/publishable/provenance/lifter.js +15 -0
  197. package/src/project-type/publishable/provenance/lifter.test.js +56 -0
  198. package/src/project-type/publishable/provenance/slsa.js +17 -0
  199. package/src/project-type/publishable/provenance/slsa.test.js +21 -0
  200. package/src/project-type/publishable/registry-resolver.js +15 -0
  201. package/src/project-type/publishable/registry-resolver.test.js +60 -0
  202. package/src/project-type/publishable/scaffolder.js +7 -0
  203. package/src/project-type/publishable/scaffolder.test.js +23 -0
  204. package/src/project-type/scaffolder.js +56 -0
  205. package/src/project-type/scaffolder.test.js +115 -0
  206. package/src/project-type/tester.js +9 -0
  207. package/src/project-type/tester.test.js +51 -0
  208. package/src/project-type-plugin/index.js +1 -0
  209. package/src/project-type-plugin/prompt.js +16 -0
  210. package/src/project-type-plugin/prompt.test.js +39 -0
  211. package/src/project-type-plugin/scaffolder.js +28 -0
  212. package/src/project-type-plugin/scaffolder.test.js +70 -0
  213. package/src/prompts/conditionals.js +39 -0
  214. package/src/prompts/conditionals.test.js +95 -0
  215. package/src/prompts/question-names.js +17 -0
  216. package/src/prompts/questions.js +158 -0
  217. package/src/prompts/questions.test.js +247 -0
  218. package/src/prompts/validators.js +9 -0
  219. package/src/prompts/validators.test.js +19 -0
  220. package/src/registries/index.js +2 -0
  221. package/src/registries/lifter.js +43 -0
  222. package/src/registries/lifter.test.js +63 -0
  223. package/src/registries/npm-config/list-builder.js +9 -0
  224. package/src/registries/npm-config/list-builder.test.js +43 -0
  225. package/src/registries/tester.js +3 -0
  226. package/src/registries/tester.test.js +9 -0
  227. package/src/runkit/badge/index.js +1 -0
  228. package/src/runkit/badge/scaffolder.js +13 -0
  229. package/src/runkit/badge/scaffolder.test.js +22 -0
  230. package/src/runkit/index.js +4 -0
  231. package/src/runkit/lifter.js +5 -0
  232. package/src/runkit/lifter.test.js +17 -0
  233. package/src/runkit/remover.js +3 -0
  234. package/src/runkit/remover.test.js +9 -0
  235. package/src/runkit/scaffolder.js +11 -0
  236. package/src/runkit/scaffolder.test.js +35 -0
  237. package/src/runkit/tester.js +3 -0
  238. package/src/runkit/tester.test.js +16 -0
  239. package/src/scaffolder.js +155 -0
  240. package/src/scaffolder.test.js +239 -0
  241. package/src/tester.js +17 -0
  242. package/src/tester.test.js +37 -0
  243. package/src/testing/index.js +1 -0
  244. package/src/testing/scaffolder.js +31 -0
  245. package/src/testing/scaffolder.test.js +63 -0
  246. package/src/testing/unit/index.js +1 -0
  247. package/src/testing/unit/prompt.js +15 -0
  248. package/src/testing/unit/prompt.test.js +33 -0
  249. package/src/testing/unit/scaffolder.js +30 -0
  250. package/src/testing/unit/scaffolder.test.js +54 -0
  251. package/src/vcs/ignore-lists-builder.js +6 -0
  252. package/src/vcs/ignore-lists-builder.test.js +25 -0
  253. package/src/vcs/schema.js +7 -0
  254. package/src/vcs/schema.test.js +40 -0
  255. package/src/verification/index.js +1 -0
  256. package/src/verification/scaffolder.js +35 -0
  257. package/src/verification/scaffolder.test.js +56 -0
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@form8ion/javascript",
3
3
  "description": "JavaScript language plugin for the @form8ion toolset",
4
4
  "license": "MIT",
5
- "version": "15.6.0",
5
+ "version": "15.6.1",
6
6
  "type": "module",
7
7
  "engines": {
8
8
  "node": "^20.19.0 || >=22.14.0"
@@ -30,7 +30,7 @@
30
30
  "lint:publish": "publint --strict",
31
31
  "lint:sensitive": "ban",
32
32
  "test:unit": "run-s 'test:unit:base -- --coverage'",
33
- "test:unit:base": "DEBUG=any vitest run",
33
+ "test:unit:base": "NODE_ENV=test DEBUG=any vitest run src/",
34
34
  "test:integration": "run-s 'test:integration:base -- --profile noWip'",
35
35
  "pretest:integration:base": "run-s build",
36
36
  "test:integration:base": "NODE_OPTIONS=--enable-source-maps DEBUG=any cucumber-js test/integration",
@@ -52,7 +52,8 @@
52
52
  "files": [
53
53
  "example.js",
54
54
  "lib/",
55
- "templates/"
55
+ "templates/",
56
+ "src/"
56
57
  ],
57
58
  "publishConfig": {
58
59
  "access": "public",
@@ -0,0 +1,3 @@
1
+ export {default as scaffold} from './scaffolder.js';
2
+ export {default as lift} from './lifter.js';
3
+ export {default as test} from './tester.js';
@@ -0,0 +1,6 @@
1
+ import {applyEnhancers} from '@form8ion/core';
2
+ import * as eslintPlugin from '@form8ion/eslint';
3
+
4
+ export default function liftCodeStyle(options) {
5
+ return applyEnhancers({options, enhancers: [eslintPlugin]});
6
+ }
@@ -0,0 +1,25 @@
1
+ import {applyEnhancers} from '@form8ion/core';
2
+ import * as eslintPlugin from '@form8ion/eslint';
3
+
4
+ import {describe, vi, it, expect, afterEach} from 'vitest';
5
+ import any from '@travi/any';
6
+ import {when} from 'vitest-when';
7
+
8
+ import liftCodeStyle from './lifter.js';
9
+
10
+ vi.mock('@form8ion/core');
11
+ vi.mock('@form8ion/eslint');
12
+
13
+ describe('code-style lifter', () => {
14
+ afterEach(() => {
15
+ vi.clearAllMocks();
16
+ });
17
+
18
+ it('should lift the code-style tools', async () => {
19
+ const options = any.simpleObject();
20
+ const results = any.simpleObject();
21
+ when(applyEnhancers).calledWith({options, enhancers: [eslintPlugin]}).thenResolve(results);
22
+
23
+ expect(await liftCodeStyle(options)).toEqual(results);
24
+ });
25
+ });
@@ -0,0 +1,3 @@
1
+ export {default as scaffold} from './scaffolder.js';
2
+ export {default as test} from './tester.js';
3
+ export {default as lift} from './lifter.js';
@@ -0,0 +1,10 @@
1
+ import {fileTypes} from '@form8ion/core';
2
+ import {load, write} from '@form8ion/config-file';
3
+
4
+ export default async function liftRemark({projectRoot}) {
5
+ const CONFIG_NAME = 'remark';
6
+
7
+ await write({format: fileTypes.JSON, path: projectRoot, name: CONFIG_NAME, config: await load({name: CONFIG_NAME})});
8
+
9
+ return {};
10
+ }
@@ -0,0 +1,28 @@
1
+ import {fileTypes} from '@form8ion/core';
2
+ import {load, write} from '@form8ion/config-file';
3
+
4
+ import any from '@travi/any';
5
+ import {describe, it, expect, afterEach, vi} from 'vitest';
6
+ import {when} from 'vitest-when';
7
+
8
+ import lift from './lifter.js';
9
+
10
+ vi.mock('@form8ion/config-file');
11
+
12
+ describe('remark lifter', () => {
13
+ const projectRoot = any.string();
14
+
15
+ afterEach(() => {
16
+ vi.clearAllMocks();
17
+ });
18
+
19
+ it('should copy existing config to json format', async () => {
20
+ const existingConfig = any.simpleObject();
21
+ when(load).calledWith({name: 'remark'}).thenResolve(existingConfig);
22
+
23
+ expect(await lift({projectRoot})).toEqual({});
24
+
25
+ expect(write)
26
+ .toHaveBeenCalledWith({format: fileTypes.JSON, path: projectRoot, name: 'remark', config: existingConfig});
27
+ });
28
+ });
@@ -0,0 +1,38 @@
1
+ import deepmerge from 'deepmerge';
2
+ import {fileTypes} from '@form8ion/core';
3
+ import {projectTypes} from '@form8ion/javascript-core';
4
+ import {write} from '@form8ion/config-file';
5
+
6
+ export default async function scaffoldRemark({config, projectRoot, projectType, vcs}) {
7
+ await write({
8
+ format: fileTypes.JSON,
9
+ path: projectRoot,
10
+ name: 'remark',
11
+ config: {
12
+ settings: {
13
+ listItemIndent: 'one',
14
+ emphasis: '_',
15
+ strong: '_',
16
+ bullet: '*',
17
+ incrementListMarker: false
18
+ },
19
+ plugins: [
20
+ config,
21
+ ['remark-toc', {tight: true}],
22
+ ...projectTypes.PACKAGE === projectType ? [['remark-usage', {heading: 'example'}]] : [],
23
+ ...!vcs ? [['validate-links', {repository: false}]] : []
24
+ ]
25
+ }
26
+ });
27
+
28
+ return deepmerge(
29
+ {
30
+ dependencies: {javascript: {development: [config, 'remark-cli', 'remark-toc']}},
31
+ scripts: {
32
+ 'lint:md': 'remark . --frail',
33
+ 'generate:md': 'remark . --output'
34
+ }
35
+ },
36
+ {...projectTypes.PACKAGE === projectType && {dependencies: {javascript: {development: ['remark-usage']}}}}
37
+ );
38
+ }
@@ -0,0 +1,102 @@
1
+ import {fileTypes} from '@form8ion/core';
2
+ import {projectTypes} from '@form8ion/javascript-core';
3
+ import {write as writeConfigFile} from '@form8ion/config-file';
4
+
5
+ import {describe, vi, it, expect, afterEach} from 'vitest';
6
+ import any from '@travi/any';
7
+
8
+ import scaffoldRemark from './scaffolder.js';
9
+
10
+ vi.mock('@form8ion/config-file');
11
+
12
+ describe('remark scaffolder', () => {
13
+ const config = any.string();
14
+ const projectRoot = any.string();
15
+
16
+ afterEach(() => {
17
+ vi.clearAllMocks();
18
+ });
19
+
20
+ it('should write the config and define dependencies', async () => {
21
+ expect(await scaffoldRemark({config, projectRoot, vcs: any.simpleObject()}))
22
+ .toEqual({
23
+ dependencies: {javascript: {development: [config, 'remark-cli', 'remark-toc']}},
24
+ scripts: {
25
+ 'lint:md': 'remark . --frail',
26
+ 'generate:md': 'remark . --output'
27
+ }
28
+ });
29
+ expect(writeConfigFile).toHaveBeenCalledWith({
30
+ format: fileTypes.JSON,
31
+ path: projectRoot,
32
+ name: 'remark',
33
+ config: {
34
+ settings: {
35
+ listItemIndent: 'one',
36
+ emphasis: '_',
37
+ strong: '_',
38
+ bullet: '*',
39
+ incrementListMarker: false
40
+ },
41
+ plugins: [
42
+ config,
43
+ ['remark-toc', {tight: true}]
44
+ ]
45
+ }
46
+ });
47
+ });
48
+
49
+ it('should configure the remark-usage plugin for package projects', async () => {
50
+ expect(await scaffoldRemark({config, projectRoot, projectType: projectTypes.PACKAGE, vcs: any.simpleObject()}))
51
+ .toEqual({
52
+ dependencies: {javascript: {development: [config, 'remark-cli', 'remark-toc', 'remark-usage']}},
53
+ scripts: {
54
+ 'lint:md': 'remark . --frail',
55
+ 'generate:md': 'remark . --output'
56
+ }
57
+ });
58
+ expect(writeConfigFile).toHaveBeenCalledWith({
59
+ format: fileTypes.JSON,
60
+ path: projectRoot,
61
+ name: 'remark',
62
+ config: {
63
+ settings: {
64
+ listItemIndent: 'one',
65
+ emphasis: '_',
66
+ strong: '_',
67
+ bullet: '*',
68
+ incrementListMarker: false
69
+ },
70
+ plugins: [
71
+ config,
72
+ ['remark-toc', {tight: true}],
73
+ ['remark-usage', {heading: 'example'}]
74
+ ]
75
+ }
76
+ });
77
+ });
78
+
79
+ it('should configure validate-links when the project will not be versioned', async () => {
80
+ await scaffoldRemark({config, projectRoot, vcs: undefined});
81
+
82
+ expect(writeConfigFile).toHaveBeenCalledWith({
83
+ format: fileTypes.JSON,
84
+ path: projectRoot,
85
+ name: 'remark',
86
+ config: {
87
+ settings: {
88
+ listItemIndent: 'one',
89
+ emphasis: '_',
90
+ strong: '_',
91
+ bullet: '*',
92
+ incrementListMarker: false
93
+ },
94
+ plugins: [
95
+ config,
96
+ ['remark-toc', {tight: true}],
97
+ ['validate-links', {repository: false}]
98
+ ]
99
+ }
100
+ });
101
+ });
102
+ });
@@ -0,0 +1,11 @@
1
+ import {fileExists} from '@form8ion/core';
2
+
3
+ export default async function remarkConfigured({projectRoot}) {
4
+ const [jsonConfigExists, jsConfigExists, cjsConfigExists] = await Promise.all([
5
+ fileExists(`${projectRoot}/.remarkrc.json`),
6
+ fileExists(`${projectRoot}/.remarkrc.js`),
7
+ fileExists(`${projectRoot}/.remarkrc.cjs`)
8
+ ]);
9
+
10
+ return jsonConfigExists || jsConfigExists || cjsConfigExists;
11
+ }
@@ -0,0 +1,46 @@
1
+ import {fileExists} from '@form8ion/core';
2
+
3
+ import {describe, vi, it, expect, afterEach, beforeEach} from 'vitest';
4
+ import any from '@travi/any';
5
+ import {when} from 'vitest-when';
6
+
7
+ import testForRemark from './tester.js';
8
+
9
+ vi.mock('@form8ion/core');
10
+
11
+ describe('remark predicate', () => {
12
+ const projectRoot = any.string();
13
+
14
+ beforeEach(() => {
15
+ fileExists.mockResolvedValue(false);
16
+ });
17
+
18
+ afterEach(() => {
19
+ vi.clearAllMocks();
20
+ });
21
+
22
+ it('should return false when remark config is not present in the project', async () => {
23
+ expect(await testForRemark({projectRoot})).toBe(false);
24
+ });
25
+
26
+ it('should return true when json remark config is present in the project', async () => {
27
+ when(fileExists).calledWith(`${projectRoot}/.remarkrc.json`).thenResolve(true);
28
+
29
+ expect(await testForRemark({projectRoot})).toBe(true);
30
+ });
31
+
32
+ it('should return true when js remark config is present in the project', async () => {
33
+ when(fileExists).calledWith(`${projectRoot}/.remarkrc.json`).thenResolve(false);
34
+ when(fileExists).calledWith(`${projectRoot}/.remarkrc.js`).thenResolve(true);
35
+
36
+ expect(await testForRemark({projectRoot})).toBe(true);
37
+ });
38
+
39
+ it('should return true when cjs remark config is present in the project', async () => {
40
+ when(fileExists).calledWith(`${projectRoot}/.remarkrc.json`).thenResolve(false);
41
+ when(fileExists).calledWith(`${projectRoot}/.remarkrc.js`).thenResolve(false);
42
+ when(fileExists).calledWith(`${projectRoot}/.remarkrc.cjs`).thenResolve(true);
43
+
44
+ expect(await testForRemark({projectRoot})).toBe(true);
45
+ });
46
+ });
@@ -0,0 +1,26 @@
1
+ import deepmerge from 'deepmerge';
2
+ import {scaffold as scaffoldPrettier} from '@form8ion/prettier';
3
+ import {scaffold as scaffoldEslint} from '@form8ion/eslint';
4
+
5
+ import {scaffold as scaffoldRemark} from './remark/index.js';
6
+
7
+ export default async function scaffoldCodeStyle({
8
+ projectRoot,
9
+ projectType,
10
+ configs,
11
+ vcs,
12
+ configureLinting
13
+ }) {
14
+ return deepmerge.all(await Promise.all([
15
+ configs.eslint
16
+ && configureLinting
17
+ && scaffoldEslint({projectRoot, config: configs.eslint}),
18
+ scaffoldRemark({
19
+ projectRoot,
20
+ projectType,
21
+ vcs,
22
+ config: configs.remark || '@form8ion/remark-lint-preset'
23
+ }),
24
+ scaffoldPrettier({projectRoot, config: configs.prettier})
25
+ ].filter(Boolean)));
26
+ }
@@ -0,0 +1,87 @@
1
+ import {scaffold as scaffoldPrettier} from '@form8ion/prettier';
2
+ import {scaffold as scaffoldEslint} from '@form8ion/eslint';
3
+ import deepmerge from 'deepmerge';
4
+
5
+ import {describe, vi, it, expect, afterEach, beforeEach} from 'vitest';
6
+ import any from '@travi/any';
7
+ import {when} from 'vitest-when';
8
+
9
+ import {scaffold as scaffoldRemark} from './remark/index.js';
10
+ import {scaffold} from './index.js';
11
+
12
+ vi.mock('@form8ion/prettier');
13
+ vi.mock('@form8ion/eslint');
14
+ vi.mock('deepmerge');
15
+ vi.mock('./remark');
16
+
17
+ describe('code-style scaffolder', () => {
18
+ const pathWithinParent = any.string();
19
+ const projectRoot = any.string();
20
+ const projectType = any.word();
21
+ const configForEslint = any.simpleObject();
22
+ const configForPrettier = any.simpleObject();
23
+ const vcs = any.simpleObject();
24
+ const configForRemark = any.simpleObject();
25
+ const configureLinting = true;
26
+ const remarkResults = any.simpleObject();
27
+ const eslintResults = any.simpleObject();
28
+ const prettierResults = any.simpleObject();
29
+ const mergedResults = any.simpleObject();
30
+
31
+ beforeEach(() => {
32
+ when(scaffoldEslint).calledWith({projectRoot, config: configForEslint}).thenResolve(eslintResults);
33
+ when(scaffoldRemark)
34
+ .calledWith({projectRoot, projectType, config: configForRemark, vcs})
35
+ .thenResolve(remarkResults);
36
+ when(scaffoldPrettier).calledWith({projectRoot, config: configForPrettier}).thenResolve(prettierResults);
37
+ });
38
+
39
+ afterEach(() => {
40
+ vi.clearAllMocks();
41
+ });
42
+
43
+ it('should configure linters when config definitions are provided', async () => {
44
+ when(deepmerge.all).calledWith([eslintResults, remarkResults, prettierResults]).thenReturn(mergedResults);
45
+
46
+ const result = await scaffold({
47
+ projectRoot,
48
+ projectType,
49
+ configs: {eslint: configForEslint, remark: configForRemark, prettier: configForPrettier},
50
+ vcs,
51
+ configureLinting,
52
+ pathWithinParent
53
+ });
54
+
55
+ expect(result).toEqual(mergedResults);
56
+ });
57
+
58
+ it('should not scaffold eslint when a config is not provided', async () => {
59
+ when(deepmerge.all).calledWith([remarkResults, prettierResults]).thenReturn(mergedResults);
60
+
61
+ const result = await scaffold({
62
+ projectRoot,
63
+ projectType,
64
+ configs: {remark: configForRemark, prettier: configForPrettier},
65
+ vcs,
66
+ configureLinting,
67
+ pathWithinParent
68
+ });
69
+
70
+ expect(result).toEqual(mergedResults);
71
+ });
72
+
73
+ it('should not scaffold eslint when `transpileLint` is false', async () => {
74
+ when(deepmerge.all).calledWith([remarkResults, prettierResults]).thenReturn(mergedResults);
75
+
76
+ const result = await scaffold({
77
+ projectRoot,
78
+ projectType,
79
+ configs: {eslint: configForEslint, remark: configForRemark, prettier: configForPrettier},
80
+ vcs,
81
+ configureLinting: false,
82
+ pathWithinParent
83
+ });
84
+
85
+ expect(result).toEqual(mergedResults);
86
+ });
87
+ });
@@ -0,0 +1,5 @@
1
+ import {test as testForEslint} from '@form8ion/eslint';
2
+
3
+ export default function codeStyleConfigured(options) {
4
+ return testForEslint(options);
5
+ }
@@ -0,0 +1,23 @@
1
+ import {test as testForEslint} from '@form8ion/eslint';
2
+
3
+ import {describe, vi, it, expect, afterEach} from 'vitest';
4
+ import any from '@travi/any';
5
+ import {when} from 'vitest-when';
6
+
7
+ import testForCodeStyleTools from './tester.js';
8
+
9
+ vi.mock('@form8ion/eslint');
10
+
11
+ describe('code-style tester', () => {
12
+ afterEach(() => {
13
+ vi.clearAllMocks();
14
+ });
15
+
16
+ it('should determine if eslint is used by the project', async () => {
17
+ const options = any.simpleObject();
18
+ const eslintResult = any.boolean();
19
+ when(testForEslint).calledWith(options).thenResolve(eslintResult);
20
+
21
+ expect(await testForCodeStyleTools(options)).toEqual(eslintResult);
22
+ });
23
+ });
@@ -0,0 +1 @@
1
+ export {default as lift} from './lifter.js';
@@ -0,0 +1,5 @@
1
+ import {execa} from 'execa';
2
+
3
+ export default async function liftCorepack() {
4
+ await execa('corepack', ['use', 'npm@latest']);
5
+ }
@@ -0,0 +1,22 @@
1
+ import {execa} from 'execa';
2
+
3
+ import {describe, it, vi, expect, afterEach} from 'vitest';
4
+
5
+ import liftCorepack from './lifter.js';
6
+
7
+ vi.mock('execa');
8
+
9
+ describe('corepack lifter', () => {
10
+ afterEach(() => {
11
+ vi.clearAllMocks();
12
+ });
13
+
14
+ it(
15
+ 'should set the `packageManager` package.json property to the latest version of the current package manager',
16
+ async () => {
17
+ await liftCorepack();
18
+
19
+ expect(execa).toHaveBeenCalledWith('corepack', ['use', 'npm@latest']);
20
+ }
21
+ );
22
+ });
@@ -0,0 +1,3 @@
1
+ export {default as scaffold} from './scaffolder.js';
2
+ export {lift} from './lifter.js';
3
+ export {default as test} from './tester.js';
@@ -0,0 +1,31 @@
1
+ import deepmerge from 'deepmerge';
2
+ import {lift as liftCodecov} from '@form8ion/codecov';
3
+ import {scaffold as scaffoldC8} from '@form8ion/c8';
4
+
5
+ import {test as nycIsConfigured, remove as removeNyc} from './nyc/index.js';
6
+
7
+ export async function lift({projectRoot, packageManager, vcs}) {
8
+ const codecovResults = await liftCodecov({projectRoot, packageManager, vcs});
9
+
10
+ if (await nycIsConfigured({projectRoot})) {
11
+ const [c8Results, nycResults] = await Promise.all([
12
+ scaffoldC8({projectRoot}),
13
+ removeNyc({projectRoot})
14
+ ]);
15
+
16
+ return deepmerge.all([
17
+ c8Results,
18
+ nycResults,
19
+ codecovResults,
20
+ {
21
+ scripts: {'test:unit': 'cross-env NODE_ENV=test c8 run-s test:unit:base'},
22
+ nextSteps: [{
23
+ summary: 'Remove use of `@istanbuljs/nyc-config-babel` from your babel config, if present,'
24
+ + ' after the migration away from `nyc`'
25
+ }]
26
+ }
27
+ ]);
28
+ }
29
+
30
+ return codecovResults;
31
+ }
@@ -0,0 +1,58 @@
1
+ import deepmerge from 'deepmerge';
2
+ import {lift as liftCodecov} from '@form8ion/codecov';
3
+ import {scaffold as scaffoldC8} from '@form8ion/c8';
4
+
5
+ import {describe, expect, it, vi} from 'vitest';
6
+ import any from '@travi/any';
7
+ import {when} from 'vitest-when';
8
+
9
+ import testForNyc from './nyc/tester.js';
10
+ import removeNyc from './nyc/remover.js';
11
+ import {lift} from './lifter.js';
12
+
13
+ vi.mock('deepmerge');
14
+ vi.mock('@form8ion/codecov');
15
+ vi.mock('@form8ion/c8');
16
+ vi.mock('./nyc/tester');
17
+ vi.mock('./nyc/remover');
18
+
19
+ describe('coverage lifter', () => {
20
+ const projectRoot = any.string();
21
+ const vcs = any.simpleObject();
22
+ const c8Results = any.simpleObject();
23
+ const codecovResults = any.simpleObject();
24
+ const packageManager = any.word();
25
+
26
+ it('should replace `nyc` with `c8` if nyc config exists', async () => {
27
+ const nycResults = any.simpleObject();
28
+ const mergedResults = any.simpleObject();
29
+ when(scaffoldC8).calledWith({projectRoot}).thenResolve(c8Results);
30
+ when(testForNyc).calledWith({projectRoot}).thenResolve(true);
31
+ when(removeNyc).calledWith({projectRoot}).thenResolve(nycResults);
32
+ when(liftCodecov).calledWith({projectRoot, packageManager, vcs}).thenResolve(codecovResults);
33
+ when(deepmerge.all).calledWith([
34
+ c8Results,
35
+ nycResults,
36
+ codecovResults,
37
+ {
38
+ scripts: {'test:unit': 'cross-env NODE_ENV=test c8 run-s test:unit:base'},
39
+ nextSteps: [{
40
+ summary: 'Remove use of `@istanbuljs/nyc-config-babel` from your babel config, if present,'
41
+ + ' after the migration away from `nyc`'
42
+ }]
43
+ }
44
+ ]).thenReturn(mergedResults);
45
+
46
+ expect(await lift({projectRoot, packageManager, vcs})).toEqual(mergedResults);
47
+ });
48
+
49
+ it('should not replace `nyc` with `c8` if nyc config does not exist', async () => {
50
+ when(scaffoldC8).calledWith({projectRoot}).thenResolve(c8Results);
51
+ when(testForNyc).calledWith({projectRoot}).thenResolve(false);
52
+ when(liftCodecov).calledWith({projectRoot, packageManager}).thenResolve(codecovResults);
53
+
54
+ expect(await lift({projectRoot, packageManager})).toEqual(codecovResults);
55
+
56
+ expect(scaffoldC8).not.toHaveBeenCalled();
57
+ });
58
+ });
@@ -0,0 +1,2 @@
1
+ export {default as test} from './tester.js';
2
+ export {default as remove} from './remover.js';
@@ -0,0 +1,16 @@
1
+ import {promises as fs} from 'node:fs';
2
+
3
+ export default async function removeNyc({projectRoot}) {
4
+ await Promise.all([
5
+ fs.unlink(`${projectRoot}/.nycrc`),
6
+ fs.rm(`${projectRoot}/.nyc_output`, {recursive: true, force: true})
7
+ ]);
8
+
9
+ return {
10
+ dependencies: {
11
+ javascript: {
12
+ remove: ['nyc', '@istanbuljs/nyc-config-babel', 'babel-plugin-istanbul']
13
+ }
14
+ }
15
+ };
16
+ }
@@ -0,0 +1,24 @@
1
+ import {promises as fs} from 'node:fs';
2
+
3
+ import {describe, it, expect, vi, afterEach} from 'vitest';
4
+ import any from '@travi/any';
5
+
6
+ import removeNyc from './remover.js';
7
+
8
+ vi.mock('node:fs');
9
+
10
+ describe('nyc remover', () => {
11
+ afterEach(() => {
12
+ vi.clearAllMocks();
13
+ });
14
+
15
+ it('should remove configuration and dependencies', async () => {
16
+ const projectRoot = any.string();
17
+
18
+ const {dependencies} = await removeNyc({projectRoot});
19
+
20
+ expect(fs.unlink).toHaveBeenCalledWith(`${projectRoot}/.nycrc`);
21
+ expect(fs.rm).toHaveBeenCalledWith(`${projectRoot}/.nyc_output`, {recursive: true, force: true});
22
+ expect(dependencies.javascript.remove).toEqual(['nyc', '@istanbuljs/nyc-config-babel', 'babel-plugin-istanbul']);
23
+ });
24
+ });
@@ -0,0 +1,5 @@
1
+ import {fileExists} from '@form8ion/core';
2
+
3
+ export default function nyvInUse({projectRoot}) {
4
+ return fileExists(`${projectRoot}/.nycrc`);
5
+ }
@@ -0,0 +1,29 @@
1
+ import {fileExists} from '@form8ion/core';
2
+
3
+ import {describe, it, expect, vi, afterEach} from 'vitest';
4
+ import any from '@travi/any';
5
+ import {when} from 'vitest-when';
6
+
7
+ import nycIsConfigured from './tester.js';
8
+
9
+ vi.mock('@form8ion/core');
10
+
11
+ describe('nyc predicate', () => {
12
+ const projectRoot = any.string();
13
+
14
+ afterEach(() => {
15
+ vi.clearAllMocks();
16
+ });
17
+
18
+ it('should return `true` if the config file exists', async () => {
19
+ when(fileExists).calledWith(`${projectRoot}/.nycrc`).thenResolve(true);
20
+
21
+ expect(await nycIsConfigured({projectRoot})).toBe(true);
22
+ });
23
+
24
+ it('should return `false` if the config file does not exist', async () => {
25
+ when(fileExists).calledWith(`${projectRoot}/.nycrc`).thenResolve(false);
26
+
27
+ expect(await nycIsConfigured({projectRoot})).toBe(false);
28
+ });
29
+ });