@form8ion/javascript 15.5.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 (259) hide show
  1. package/lib/index.js +2 -2
  2. package/lib/index.js.map +1 -1
  3. package/package.json +4 -3
  4. package/src/code-style/index.js +3 -0
  5. package/src/code-style/lifter.js +6 -0
  6. package/src/code-style/lifter.test.js +25 -0
  7. package/src/code-style/remark/index.js +3 -0
  8. package/src/code-style/remark/lifter.js +10 -0
  9. package/src/code-style/remark/lifter.test.js +28 -0
  10. package/src/code-style/remark/scaffolder.js +38 -0
  11. package/src/code-style/remark/scaffolder.test.js +102 -0
  12. package/src/code-style/remark/tester.js +11 -0
  13. package/src/code-style/remark/tester.test.js +46 -0
  14. package/src/code-style/scaffolder.js +26 -0
  15. package/src/code-style/scaffolder.test.js +87 -0
  16. package/src/code-style/tester.js +5 -0
  17. package/src/code-style/tester.test.js +23 -0
  18. package/src/corepack/index.js +1 -0
  19. package/src/corepack/lifter.js +5 -0
  20. package/src/corepack/lifter.test.js +22 -0
  21. package/src/coverage/index.js +3 -0
  22. package/src/coverage/lifter.js +31 -0
  23. package/src/coverage/lifter.test.js +58 -0
  24. package/src/coverage/nyc/index.js +2 -0
  25. package/src/coverage/nyc/remover.js +16 -0
  26. package/src/coverage/nyc/remover.test.js +24 -0
  27. package/src/coverage/nyc/tester.js +5 -0
  28. package/src/coverage/nyc/tester.test.js +29 -0
  29. package/src/coverage/scaffolder.js +7 -0
  30. package/src/coverage/scaffolder.test.js +32 -0
  31. package/src/coverage/tester.js +10 -0
  32. package/src/coverage/tester.test.js +50 -0
  33. package/src/dependencies/index.js +3 -0
  34. package/src/dependencies/installer.js +25 -0
  35. package/src/dependencies/installer.test.js +77 -0
  36. package/src/dependencies/package-managers.js +32 -0
  37. package/src/dependencies/package-managers.test.js +46 -0
  38. package/src/dependencies/processor.js +30 -0
  39. package/src/dependencies/processor.test.js +75 -0
  40. package/src/dependencies/remover.js +10 -0
  41. package/src/dependencies/remover.test.js +28 -0
  42. package/src/dialects/babel/config/ignore-adder.js +10 -0
  43. package/src/dialects/babel/config/ignore-adder.test.js +33 -0
  44. package/src/dialects/babel/config/index.js +3 -0
  45. package/src/dialects/babel/config/loader.js +5 -0
  46. package/src/dialects/babel/config/loader.test.js +21 -0
  47. package/src/dialects/babel/config/writer.js +6 -0
  48. package/src/dialects/babel/config/writer.test.js +20 -0
  49. package/src/dialects/babel/index.js +3 -0
  50. package/src/dialects/babel/lifter.js +7 -0
  51. package/src/dialects/babel/lifter.test.js +17 -0
  52. package/src/dialects/babel/predicate.js +5 -0
  53. package/src/dialects/babel/predicate.test.js +25 -0
  54. package/src/dialects/babel/scaffolder.js +14 -0
  55. package/src/dialects/babel/scaffolder.test.js +28 -0
  56. package/src/dialects/index.js +2 -0
  57. package/src/dialects/prompt-choices.js +10 -0
  58. package/src/dialects/prompt-choices.test.js +28 -0
  59. package/src/dialects/scaffolder.js +15 -0
  60. package/src/dialects/scaffolder.test.js +49 -0
  61. package/src/dialects/typescript/index.js +1 -0
  62. package/src/dialects/typescript/scaffolder.js +31 -0
  63. package/src/dialects/typescript/scaffolder.test.js +95 -0
  64. package/src/documentation/generation-command.js +11 -0
  65. package/src/documentation/generation-command.test.js +25 -0
  66. package/src/documentation/index.js +1 -0
  67. package/src/documentation/scaffolder.js +20 -0
  68. package/src/documentation/scaffolder.test.js +49 -0
  69. package/src/engines/index.js +2 -0
  70. package/src/engines/lifter.js +7 -0
  71. package/src/engines/lifter.test.js +18 -0
  72. package/src/engines/tester.js +7 -0
  73. package/src/engines/tester.test.js +37 -0
  74. package/src/index.js +9 -0
  75. package/src/lifter.js +55 -0
  76. package/src/lifter.test.js +96 -0
  77. package/src/linting/index.js +1 -0
  78. package/src/linting/scaffolder.js +5 -0
  79. package/src/linting/scaffolder.test.js +31 -0
  80. package/src/lockfile-lint/allowed-hosts-builder.js +6 -0
  81. package/src/lockfile-lint/allowed-hosts-builder.test.js +35 -0
  82. package/src/lockfile-lint/config.js +12 -0
  83. package/src/lockfile-lint/config.test.js +37 -0
  84. package/src/lockfile-lint/index.js +3 -0
  85. package/src/lockfile-lint/scaffolder.js +38 -0
  86. package/src/lockfile-lint/scaffolder.test.js +85 -0
  87. package/src/lockfile-lint/tester.js +5 -0
  88. package/src/lockfile-lint/tester.test.js +25 -0
  89. package/src/node-version/index.js +2 -0
  90. package/src/node-version/scaffolder.js +19 -0
  91. package/src/node-version/scaffolder.test.js +33 -0
  92. package/src/node-version/tasks.js +25 -0
  93. package/src/node-version/tasks.test.js +43 -0
  94. package/src/node-version/tester.js +5 -0
  95. package/src/node-version/tester.test.js +29 -0
  96. package/src/npm-config/index.js +5 -0
  97. package/src/npm-config/lifter.js +14 -0
  98. package/src/npm-config/lifter.test.js +23 -0
  99. package/src/npm-config/reader.js +11 -0
  100. package/src/npm-config/reader.test.js +33 -0
  101. package/src/npm-config/scaffolder.js +16 -0
  102. package/src/npm-config/scaffolder.test.js +54 -0
  103. package/src/npm-config/tester.js +5 -0
  104. package/src/npm-config/tester.test.js +29 -0
  105. package/src/npm-config/writer.js +6 -0
  106. package/src/npm-config/writer.test.js +24 -0
  107. package/src/options/schemas.js +14 -0
  108. package/src/options/schemas.test.js +147 -0
  109. package/src/options/validator.js +45 -0
  110. package/src/options/validator.test.js +79 -0
  111. package/src/package/details.js +18 -0
  112. package/src/package/details.test.js +51 -0
  113. package/src/package/index.js +2 -0
  114. package/src/package/lifter.js +47 -0
  115. package/src/package/lifter.test.js +100 -0
  116. package/src/package/package-name.js +13 -0
  117. package/src/package/package-name.test.js +52 -0
  118. package/src/package/property-sorter.js +38 -0
  119. package/src/package/property-sorter.test.js +56 -0
  120. package/src/package/scaffolder.js +32 -0
  121. package/src/package/scaffolder.test.js +46 -0
  122. package/src/package/scripts/index.js +1 -0
  123. package/src/package/scripts/lifter.js +14 -0
  124. package/src/package/scripts/lifter.test.js +31 -0
  125. package/src/package/scripts/script-comparator.js +46 -0
  126. package/src/package/scripts/script-comparator.test.js +119 -0
  127. package/src/package/scripts/scripts-sorter.js +7 -0
  128. package/src/package/scripts/scripts-sorter.test.js +20 -0
  129. package/src/package/scripts/test-script-updater.js +15 -0
  130. package/src/package/scripts/test-script-updater.test.js +32 -0
  131. package/src/package/vcs-host-details.js +12 -0
  132. package/src/package/vcs-host-details.test.js +16 -0
  133. package/src/package-managers/current-manager-resolver.js +21 -0
  134. package/src/package-managers/current-manager-resolver.test.js +51 -0
  135. package/src/package-managers/index.js +5 -0
  136. package/src/package-managers/lifter.js +7 -0
  137. package/src/package-managers/lifter.test.js +18 -0
  138. package/src/package-managers/lockfile-path-resolver.js +10 -0
  139. package/src/package-managers/lockfile-path-resolver.test.js +15 -0
  140. package/src/package-managers/npm/index.js +2 -0
  141. package/src/package-managers/npm/scaffolder.js +19 -0
  142. package/src/package-managers/npm/scaffolder.test.js +33 -0
  143. package/src/package-managers/npm/tester.js +11 -0
  144. package/src/package-managers/npm/tester.test.js +33 -0
  145. package/src/package-managers/scaffolder.js +11 -0
  146. package/src/package-managers/scaffolder.test.js +27 -0
  147. package/src/package-managers/tester.js +11 -0
  148. package/src/package-managers/tester.test.js +33 -0
  149. package/src/package-managers/yarn/index.js +2 -0
  150. package/src/package-managers/yarn/scaffolder.js +19 -0
  151. package/src/package-managers/yarn/scaffolder.test.js +33 -0
  152. package/src/package-managers/yarn/tester.js +11 -0
  153. package/src/package-managers/yarn/tester.test.js +33 -0
  154. package/src/plugins-schemas.js +4 -0
  155. package/src/plugins-schemas.test.js +28 -0
  156. package/src/project-type/application/index.js +2 -0
  157. package/src/project-type/application/predicate.js +3 -0
  158. package/src/project-type/application/predicate.test.js +14 -0
  159. package/src/project-type/application/scaffolder.js +24 -0
  160. package/src/project-type/application/scaffolder.test.js +35 -0
  161. package/src/project-type/cli/index.js +3 -0
  162. package/src/project-type/cli/lifter.js +5 -0
  163. package/src/project-type/cli/lifter.test.js +20 -0
  164. package/src/project-type/cli/scaffolder.js +52 -0
  165. package/src/project-type/cli/scaffolder.test.js +103 -0
  166. package/src/project-type/cli/tester.js +3 -0
  167. package/src/project-type/cli/tester.test.js +14 -0
  168. package/src/project-type/index.js +3 -0
  169. package/src/project-type/lifter.js +23 -0
  170. package/src/project-type/lifter.test.js +69 -0
  171. package/src/project-type/monorepo/index.js +1 -0
  172. package/src/project-type/monorepo/scaffolder.js +16 -0
  173. package/src/project-type/monorepo/scaffolder.test.js +27 -0
  174. package/src/project-type/package/build-details.js +56 -0
  175. package/src/project-type/package/build-details.test.js +111 -0
  176. package/src/project-type/package/documentation.js +34 -0
  177. package/src/project-type/package/documentation.test.js +106 -0
  178. package/src/project-type/package/index.js +3 -0
  179. package/src/project-type/package/lifter.js +5 -0
  180. package/src/project-type/package/lifter.test.js +20 -0
  181. package/src/project-type/package/scaffolder.js +84 -0
  182. package/src/project-type/package/scaffolder.test.js +267 -0
  183. package/src/project-type/package/tester.js +5 -0
  184. package/src/project-type/package/tester.test.js +28 -0
  185. package/src/project-type/publishable/access-level.js +3 -0
  186. package/src/project-type/publishable/access-level.test.js +13 -0
  187. package/src/project-type/publishable/badges.js +20 -0
  188. package/src/project-type/publishable/badges.test.js +29 -0
  189. package/src/project-type/publishable/bundler/index.js +1 -0
  190. package/src/project-type/publishable/bundler/prompt.js +16 -0
  191. package/src/project-type/publishable/bundler/prompt.test.js +35 -0
  192. package/src/project-type/publishable/bundler/scaffolder.js +8 -0
  193. package/src/project-type/publishable/bundler/scaffolder.test.js +33 -0
  194. package/src/project-type/publishable/index.js +2 -0
  195. package/src/project-type/publishable/lifter.js +24 -0
  196. package/src/project-type/publishable/lifter.test.js +49 -0
  197. package/src/project-type/publishable/provenance/index.js +1 -0
  198. package/src/project-type/publishable/provenance/lifter.js +15 -0
  199. package/src/project-type/publishable/provenance/lifter.test.js +56 -0
  200. package/src/project-type/publishable/provenance/slsa.js +17 -0
  201. package/src/project-type/publishable/provenance/slsa.test.js +21 -0
  202. package/src/project-type/publishable/registry-resolver.js +15 -0
  203. package/src/project-type/publishable/registry-resolver.test.js +60 -0
  204. package/src/project-type/publishable/scaffolder.js +7 -0
  205. package/src/project-type/publishable/scaffolder.test.js +23 -0
  206. package/src/project-type/scaffolder.js +56 -0
  207. package/src/project-type/scaffolder.test.js +115 -0
  208. package/src/project-type/tester.js +9 -0
  209. package/src/project-type/tester.test.js +51 -0
  210. package/src/project-type-plugin/index.js +1 -0
  211. package/src/project-type-plugin/prompt.js +16 -0
  212. package/src/project-type-plugin/prompt.test.js +39 -0
  213. package/src/project-type-plugin/scaffolder.js +28 -0
  214. package/src/project-type-plugin/scaffolder.test.js +70 -0
  215. package/src/prompts/conditionals.js +39 -0
  216. package/src/prompts/conditionals.test.js +95 -0
  217. package/src/prompts/question-names.js +17 -0
  218. package/src/prompts/questions.js +158 -0
  219. package/src/prompts/questions.test.js +247 -0
  220. package/src/prompts/validators.js +9 -0
  221. package/src/prompts/validators.test.js +19 -0
  222. package/src/registries/index.js +2 -0
  223. package/src/registries/lifter.js +43 -0
  224. package/src/registries/lifter.test.js +63 -0
  225. package/src/registries/npm-config/list-builder.js +9 -0
  226. package/src/registries/npm-config/list-builder.test.js +43 -0
  227. package/src/registries/tester.js +3 -0
  228. package/src/registries/tester.test.js +9 -0
  229. package/src/runkit/badge/index.js +1 -0
  230. package/src/runkit/badge/scaffolder.js +13 -0
  231. package/src/runkit/badge/scaffolder.test.js +22 -0
  232. package/src/runkit/index.js +4 -0
  233. package/src/runkit/lifter.js +5 -0
  234. package/src/runkit/lifter.test.js +17 -0
  235. package/src/runkit/remover.js +3 -0
  236. package/src/runkit/remover.test.js +9 -0
  237. package/src/runkit/scaffolder.js +11 -0
  238. package/src/runkit/scaffolder.test.js +35 -0
  239. package/src/runkit/tester.js +3 -0
  240. package/src/runkit/tester.test.js +16 -0
  241. package/src/scaffolder.js +155 -0
  242. package/src/scaffolder.test.js +239 -0
  243. package/src/tester.js +17 -0
  244. package/src/tester.test.js +37 -0
  245. package/src/testing/index.js +1 -0
  246. package/src/testing/scaffolder.js +31 -0
  247. package/src/testing/scaffolder.test.js +63 -0
  248. package/src/testing/unit/index.js +1 -0
  249. package/src/testing/unit/prompt.js +15 -0
  250. package/src/testing/unit/prompt.test.js +33 -0
  251. package/src/testing/unit/scaffolder.js +30 -0
  252. package/src/testing/unit/scaffolder.test.js +54 -0
  253. package/src/vcs/ignore-lists-builder.js +6 -0
  254. package/src/vcs/ignore-lists-builder.test.js +25 -0
  255. package/src/vcs/schema.js +7 -0
  256. package/src/vcs/schema.test.js +40 -0
  257. package/src/verification/index.js +1 -0
  258. package/src/verification/scaffolder.js +35 -0
  259. package/src/verification/scaffolder.test.js +56 -0
@@ -0,0 +1,27 @@
1
+ import {packageManagers} from '@form8ion/javascript-core';
2
+
3
+ import {describe, it, vi, expect} from 'vitest';
4
+ import any from '@travi/any';
5
+
6
+ import {scaffold as scaffoldNpm} from './npm/index.js';
7
+ import {scaffold as scaffoldYarn} from './yarn/index.js';
8
+ import scaffoldPackageManager from './scaffolder.js';
9
+
10
+ vi.mock('./npm/index.js');
11
+ vi.mock('./yarn/index.js');
12
+
13
+ describe('package manager scaffolder', () => {
14
+ const projectRoot = any.string();
15
+
16
+ it('should scaffold npm when npm is the chosen packageManager', async () => {
17
+ await scaffoldPackageManager({projectRoot, packageManager: packageManagers.NPM});
18
+
19
+ expect(scaffoldNpm).toHaveBeenCalledWith({projectRoot});
20
+ });
21
+
22
+ it('should scaffold yarn when yarn is the chosen packageManager', async () => {
23
+ await scaffoldPackageManager({projectRoot, packageManager: packageManagers.YARN});
24
+
25
+ expect(scaffoldYarn).toHaveBeenCalledWith({projectRoot});
26
+ });
27
+ });
@@ -0,0 +1,11 @@
1
+ import {test as npmIsUsed} from './npm/index.js';
2
+ import {test as yarnIsUsed} from './yarn/index.js';
3
+
4
+ export default async function packageManagerInUse({projectRoot}) {
5
+ const [npmFound, yarnFound] = await Promise.all([
6
+ npmIsUsed({projectRoot}),
7
+ yarnIsUsed({projectRoot})
8
+ ]);
9
+
10
+ return npmFound || yarnFound;
11
+ }
@@ -0,0 +1,33 @@
1
+ import {describe, expect, it, vi} from 'vitest';
2
+ import any from '@travi/any';
3
+ import {when} from 'vitest-when';
4
+
5
+ import {test as npmIsUsed} from './npm/index.js';
6
+ import {test as yarnIsUsed} from './yarn/index.js';
7
+ import test from './tester.js';
8
+
9
+ vi.mock('./npm/index.js');
10
+ vi.mock('./yarn/index.js');
11
+
12
+ describe('package managers predicate', () => {
13
+ const projectRoot = any.string();
14
+
15
+ it('should return `true` if npm is used', async () => {
16
+ when(npmIsUsed).calledWith({projectRoot}).thenResolve(true);
17
+
18
+ expect(await test({projectRoot})).toBe(true);
19
+ });
20
+
21
+ it('should return `true` if yarn is used', async () => {
22
+ when(yarnIsUsed).calledWith({projectRoot}).thenResolve(true);
23
+
24
+ expect(await test({projectRoot})).toBe(true);
25
+ });
26
+
27
+ it('should return `false` if neither npm nor yarn is used', async () => {
28
+ when(npmIsUsed).calledWith({projectRoot}).thenResolve(false);
29
+ when(yarnIsUsed).calledWith({projectRoot}).thenResolve(false);
30
+
31
+ expect(await test({projectRoot})).toBe(false);
32
+ });
33
+ });
@@ -0,0 +1,2 @@
1
+ export {default as scaffold} from './scaffolder.js';
2
+ export {default as test} from './tester.js';
@@ -0,0 +1,19 @@
1
+ import {promises as fs} from 'node:fs';
2
+ import {execa} from 'execa';
3
+ import {writePackageJson} from '@form8ion/javascript-core';
4
+
5
+ export default async function scaffoldYarn({projectRoot}) {
6
+ const [packageContents, {stdout}] = await Promise.all([
7
+ fs.readFile(`${projectRoot}/package.json`, 'utf-8'),
8
+ execa('yarn', ['--version'])
9
+ ]);
10
+ const existingPackageJsonContents = JSON.parse(packageContents);
11
+
12
+ await writePackageJson({
13
+ projectRoot,
14
+ config: {
15
+ ...existingPackageJsonContents,
16
+ packageManager: `yarn@${stdout}`
17
+ }
18
+ });
19
+ }
@@ -0,0 +1,33 @@
1
+ import {promises as fs} from 'node:fs';
2
+ import {execa} from 'execa';
3
+ import {writePackageJson} from '@form8ion/javascript-core';
4
+
5
+ import any from '@travi/any';
6
+ import {vi, it, describe, expect} from 'vitest';
7
+ import {when} from 'vitest-when';
8
+
9
+ import scaffoldYarn from './scaffolder.js';
10
+
11
+ vi.mock('node:fs');
12
+ vi.mock('execa');
13
+ vi.mock('@form8ion/javascript-core');
14
+
15
+ describe('yarn scaffolder', () => {
16
+ const projectRoot = any.string();
17
+
18
+ it('should scaffold the yarn package manager', async () => {
19
+ const existingPackageContents = any.simpleObject();
20
+ const cliVersion = any.word();
21
+ when(fs.readFile)
22
+ .calledWith(`${projectRoot}/package.json`, 'utf-8')
23
+ .thenResolve(JSON.stringify(existingPackageContents));
24
+ when(execa).calledWith('yarn', ['--version']).thenResolve({stdout: cliVersion});
25
+
26
+ await scaffoldYarn({projectRoot});
27
+
28
+ expect(writePackageJson).toHaveBeenCalledWith({
29
+ projectRoot,
30
+ config: {...existingPackageContents, packageManager: `yarn@${cliVersion}`}
31
+ });
32
+ });
33
+ });
@@ -0,0 +1,11 @@
1
+ import {fileExists} from '@form8ion/core';
2
+ import {packageManagers} from '@form8ion/javascript-core';
3
+
4
+ import determineLockfilePath from '../lockfile-path-resolver.js';
5
+
6
+ export default function packageManagerIsYarn({projectRoot, pinnedPackageManager = ''}) {
7
+ const [packageManager] = pinnedPackageManager.split('@');
8
+
9
+ return packageManagers.YARN === packageManager
10
+ || fileExists(`${projectRoot}/${determineLockfilePath(packageManagers.YARN)}`);
11
+ }
@@ -0,0 +1,33 @@
1
+ import {fileExists} from '@form8ion/core';
2
+
3
+ import {expect, describe, it, vi, afterEach} from 'vitest';
4
+ import any from '@travi/any';
5
+ import {when} from 'vitest-when';
6
+
7
+ import yarnIsUsed from './tester.js';
8
+
9
+ vi.mock('@form8ion/core');
10
+
11
+ describe('yarn predicate', () => {
12
+ const projectRoot = any.string();
13
+
14
+ afterEach(() => {
15
+ vi.clearAllMocks();
16
+ });
17
+
18
+ it('should return `true` is a `yarn.lock` exists', async () => {
19
+ when(fileExists).calledWith(`${projectRoot}/yarn.lock`).thenResolve(true);
20
+
21
+ expect(await yarnIsUsed({projectRoot})).toBe(true);
22
+ });
23
+
24
+ it('should return `false` is a `yarn.lock` does not exist', async () => {
25
+ when(fileExists).calledWith(`${projectRoot}/yarn.lock`).thenResolve(false);
26
+
27
+ expect(await yarnIsUsed({projectRoot})).toBe(false);
28
+ });
29
+
30
+ it('should return true if the package manager is pinned to yarn', async () => {
31
+ expect(await yarnIsUsed({projectRoot, pinnedPackageManager: 'yarn@1.2.3'})).toBe(true);
32
+ });
33
+ });
@@ -0,0 +1,4 @@
1
+ import joi from 'joi';
2
+ import {optionsSchemas} from '@form8ion/core';
3
+
4
+ export const pluginsSchema = joi.object().pattern(/^/, optionsSchemas.form8ionPlugin).default({});
@@ -0,0 +1,28 @@
1
+ import {validateOptions} from '@form8ion/core';
2
+
3
+ import {describe, expect, it} from 'vitest';
4
+ import any from '@travi/any';
5
+
6
+ import {pluginsSchema} from './plugins-schemas.js';
7
+
8
+ describe('plugins schemas', () => {
9
+ const key = any.word();
10
+
11
+ it('should require that a provided framework define a `scaffolder`', () => {
12
+ expect(() => validateOptions(pluginsSchema, {[key]: {scaffold: any.word()}}))
13
+ .toThrowError(`"${key}.scaffold" must be of type function`);
14
+ });
15
+
16
+ it('should require that the `scaffold` defined by a provided framework take an options object', () => {
17
+ expect(() => validateOptions(pluginsSchema, {[key]: {scaffold: () => undefined}}))
18
+ .toThrowError(`"${key}.scaffold" must have an arity greater or equal to 1`);
19
+ });
20
+
21
+ it('should consider a provided framework definition valid if the scaffolder accepts an options object', () => {
22
+ validateOptions(pluginsSchema, {[key]: {scaffold: options => options}});
23
+ });
24
+
25
+ it('should provide an empty object by default', () => {
26
+ expect(validateOptions(pluginsSchema, undefined)).toEqual({});
27
+ });
28
+ });
@@ -0,0 +1,2 @@
1
+ export {default as scaffold} from './scaffolder.js';
2
+ export {default as test} from './predicate.js';
@@ -0,0 +1,3 @@
1
+ export default function projectIsApplication({packageDetails}) {
2
+ return !!packageDetails.private;
3
+ }
@@ -0,0 +1,14 @@
1
+ import {describe, it, expect} from 'vitest';
2
+ import any from '@travi/any';
3
+
4
+ import projectIsAnApplication from './predicate.js';
5
+
6
+ describe('application project-type predicate', () => {
7
+ it('should return `true` for a project marked as `private` according to npm', async () => {
8
+ expect(await projectIsAnApplication({packageDetails: {private: true}})).toBe(true);
9
+ });
10
+
11
+ it('should return `false` for a project not marked as `private` according to npm', async () => {
12
+ expect(await projectIsAnApplication({packageDetails: any.simpleObject()})).toBe(false);
13
+ });
14
+ });
@@ -0,0 +1,24 @@
1
+ import {mergeIntoExistingPackageJson} from '@form8ion/javascript-core';
2
+ import {info} from '@travi/cli-messages';
3
+
4
+ const defaultBuildDirectory = 'public';
5
+
6
+ export default async function scaffoldApplication({projectRoot}) {
7
+ info('Scaffolding Application Details');
8
+
9
+ await mergeIntoExistingPackageJson({projectRoot, config: {private: true}});
10
+
11
+ const buildDirectory = defaultBuildDirectory;
12
+
13
+ return {
14
+ scripts: {
15
+ clean: `rimraf ./${buildDirectory}`,
16
+ start: `node ./${buildDirectory}/index.js`,
17
+ prebuild: 'run-s clean'
18
+ },
19
+ dependencies: {javascript: {development: ['rimraf']}},
20
+ vcsIgnore: {files: ['.env'], directories: [`/${buildDirectory}/`]},
21
+ buildDirectory,
22
+ nextSteps: []
23
+ };
24
+ }
@@ -0,0 +1,35 @@
1
+ import {mergeIntoExistingPackageJson} from '@form8ion/javascript-core';
2
+
3
+ import {afterEach, describe, expect, it, vi} from 'vitest';
4
+ import any from '@travi/any';
5
+
6
+ import scaffoldApplication from './scaffolder.js';
7
+
8
+ vi.mock('@form8ion/javascript-core');
9
+
10
+ describe('application project-type scaffolder', () => {
11
+ afterEach(() => {
12
+ vi.clearAllMocks();
13
+ });
14
+
15
+ it('should scaffold the details specific to an application project-type', async () => {
16
+ const projectRoot = any.string();
17
+ const buildDirectory = 'public';
18
+
19
+ expect(await scaffoldApplication({projectRoot})).toEqual({
20
+ scripts: {
21
+ clean: `rimraf ./${buildDirectory}`,
22
+ start: `node ./${buildDirectory}/index.js`,
23
+ prebuild: 'run-s clean'
24
+ },
25
+ dependencies: {javascript: {development: ['rimraf']}},
26
+ vcsIgnore: {
27
+ files: ['.env'],
28
+ directories: [`/${buildDirectory}/`]
29
+ },
30
+ buildDirectory,
31
+ nextSteps: []
32
+ });
33
+ expect(mergeIntoExistingPackageJson).toHaveBeenCalledWith({projectRoot, config: {private: true}});
34
+ });
35
+ });
@@ -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,5 @@
1
+ import {lift as liftPublishable} from '../publishable/index.js';
2
+
3
+ export default function liftCli({projectRoot, packageDetails, configs}) {
4
+ return liftPublishable({projectRoot, packageDetails, configs});
5
+ }
@@ -0,0 +1,20 @@
1
+ import {describe, expect, it, vi} from 'vitest';
2
+ import any from '@travi/any';
3
+ import {when} from 'vitest-when';
4
+
5
+ import {lift as liftPublishable} from '../publishable/index.js';
6
+ import lift from './lifter.js';
7
+
8
+ vi.mock('../publishable/lifter');
9
+
10
+ describe('cli project-type lifter', () => {
11
+ it('should leverage the publishable lifter', async () => {
12
+ const projectRoot = any.string();
13
+ const packageDetails = any.simpleObject();
14
+ const configs = any.simpleObject();
15
+ const publishableResults = any.simpleObject();
16
+ when(liftPublishable).calledWith({projectRoot, packageDetails, configs}).thenResolve(publishableResults);
17
+
18
+ expect(await lift({projectRoot, packageDetails, configs})).toEqual(publishableResults);
19
+ });
20
+ });
@@ -0,0 +1,52 @@
1
+ import deepmerge from 'deepmerge';
2
+ import {mergeIntoExistingPackageJson, projectTypes} from '@form8ion/javascript-core';
3
+
4
+ import determinePackageAccessLevelFromProjectVisibility from '../publishable/access-level.js';
5
+ import {scaffold as scaffoldPublishable} from '../publishable/index.js';
6
+ import {scaffold as scaffoldBundler} from '../publishable/bundler/index.js';
7
+
8
+ const defaultBuildDirectory = 'bin';
9
+
10
+ export default async function scaffoldCli({
11
+ packageName,
12
+ visibility,
13
+ projectRoot,
14
+ dialect,
15
+ publishRegistry,
16
+ decisions,
17
+ packageBundlers
18
+ }) {
19
+ const packageAccessLevel = determinePackageAccessLevelFromProjectVisibility({projectVisibility: visibility});
20
+ const [bundlerResults, publishableResults] = await Promise.all([
21
+ scaffoldBundler({bundlers: packageBundlers, projectRoot, dialect, decisions, projectType: projectTypes.CLI}),
22
+ scaffoldPublishable({packageName, packageAccessLevel}),
23
+ mergeIntoExistingPackageJson({
24
+ projectRoot,
25
+ config: {
26
+ bin: {},
27
+ files: [`${defaultBuildDirectory}/`, 'src/'],
28
+ publishConfig: {
29
+ access: packageAccessLevel,
30
+ ...publishRegistry && {registry: publishRegistry}
31
+ }
32
+ }
33
+ })
34
+ ]);
35
+
36
+ return deepmerge.all([
37
+ publishableResults,
38
+ bundlerResults,
39
+ {
40
+ scripts: {
41
+ clean: `rimraf ./${defaultBuildDirectory}`,
42
+ prebuild: 'run-s clean',
43
+ build: 'npm-run-all --print-label --parallel build:*',
44
+ prepack: 'run-s build'
45
+ },
46
+ dependencies: {javascript: {production: ['update-notifier'], development: ['rimraf']}},
47
+ vcsIgnore: {files: [], directories: [`/${defaultBuildDirectory}/`]},
48
+ buildDirectory: defaultBuildDirectory,
49
+ nextSteps: [{summary: 'Define supported node.js versions as `engines.node` in the `package.json` file'}]
50
+ }
51
+ ]);
52
+ }
@@ -0,0 +1,103 @@
1
+ import {mergeIntoExistingPackageJson, projectTypes} from '@form8ion/javascript-core';
2
+
3
+ import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
4
+ import any from '@travi/any';
5
+ import {when} from 'vitest-when';
6
+
7
+ import determinePackageAccessLevelFromProjectVisibility from '../publishable/access-level.js';
8
+ import {scaffold as scaffoldBundler} from '../publishable/bundler/index.js';
9
+ import {scaffold as scaffoldPublishable} from '../publishable/index.js';
10
+ import scaffoldCli from './scaffolder.js';
11
+
12
+ vi.mock('@form8ion/javascript-core');
13
+ vi.mock('../publishable/access-level');
14
+ vi.mock('../publishable/bundler');
15
+ vi.mock('../publishable');
16
+
17
+ describe('cli project-type scaffolder', () => {
18
+ const projectRoot = any.string();
19
+ const packageName = any.word();
20
+ const publishableResults = any.simpleObject();
21
+ const configs = any.simpleObject();
22
+ const visibility = any.word();
23
+ const packageAccessLevel = any.word();
24
+ const bundlerResults = any.simpleObject();
25
+ const dialect = any.word();
26
+ const decisions = any.simpleObject();
27
+ const packageBundlers = any.simpleObject();
28
+
29
+ beforeEach(() => {
30
+ when(determinePackageAccessLevelFromProjectVisibility)
31
+ .calledWith({projectVisibility: visibility})
32
+ .thenReturn(packageAccessLevel);
33
+ when(scaffoldPublishable).calledWith({packageName, packageAccessLevel}).thenReturn(publishableResults);
34
+ when(scaffoldBundler)
35
+ .calledWith({bundlers: packageBundlers, decisions, projectRoot, dialect, projectType: projectTypes.CLI})
36
+ .thenResolve(bundlerResults);
37
+ });
38
+
39
+ afterEach(() => {
40
+ vi.clearAllMocks();
41
+ });
42
+
43
+ it('should scaffold the cli project-type details', async () => {
44
+ const results = await scaffoldCli({
45
+ projectRoot,
46
+ configs,
47
+ packageName,
48
+ visibility,
49
+ dialect,
50
+ decisions,
51
+ packageBundlers
52
+ });
53
+
54
+ expect(results).toEqual({
55
+ ...publishableResults,
56
+ ...bundlerResults,
57
+ scripts: {
58
+ clean: 'rimraf ./bin',
59
+ prebuild: 'run-s clean',
60
+ build: 'npm-run-all --print-label --parallel build:*',
61
+ prepack: 'run-s build'
62
+ },
63
+ dependencies: {javascript: {production: ['update-notifier'], development: ['rimraf']}},
64
+ vcsIgnore: {
65
+ files: [],
66
+ directories: ['/bin/']
67
+ },
68
+ buildDirectory: 'bin',
69
+ nextSteps: [{summary: 'Define supported node.js versions as `engines.node` in the `package.json` file'}]
70
+ });
71
+ expect(mergeIntoExistingPackageJson).toHaveBeenCalledWith({
72
+ projectRoot,
73
+ config: {bin: {}, files: ['bin/', 'src/'], publishConfig: {access: packageAccessLevel}}
74
+ });
75
+ });
76
+
77
+ it('should define the registry to publish to when provided', async () => {
78
+ const publishRegistry = any.url();
79
+
80
+ await scaffoldCli({
81
+ projectRoot,
82
+ configs,
83
+ packageName,
84
+ visibility,
85
+ publishRegistry,
86
+ dialect,
87
+ decisions,
88
+ packageBundlers
89
+ });
90
+
91
+ expect(mergeIntoExistingPackageJson).toHaveBeenCalledWith({
92
+ projectRoot,
93
+ config: {
94
+ bin: {},
95
+ files: ['bin/', 'src/'],
96
+ publishConfig: {
97
+ access: packageAccessLevel,
98
+ registry: publishRegistry
99
+ }
100
+ }
101
+ });
102
+ });
103
+ });
@@ -0,0 +1,3 @@
1
+ export default async function projectIsCli({packageDetails: {bin}}) {
2
+ return !!bin;
3
+ }
@@ -0,0 +1,14 @@
1
+ import {describe, expect, it} from 'vitest';
2
+ import any from '@travi/any';
3
+
4
+ import test from './tester.js';
5
+
6
+ describe('cli project-type tester', () => {
7
+ it('should return `true` when the project defines `bin`', async () => {
8
+ expect(await test({packageDetails: {...any.simpleObject(), bin: any.simpleObject()}})).toBe(true);
9
+ });
10
+
11
+ it('should return `false` when the project does not define `bin`', async () => {
12
+ expect(await test({packageDetails: any.simpleObject()})).toBe(false);
13
+ });
14
+ });
@@ -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,23 @@
1
+ import {mergeIntoExistingPackageJson} from '@form8ion/javascript-core';
2
+
3
+ import {test as isPackage, lift as liftPackage} from './package/index.js';
4
+ import {test as isCli, lift as liftCli} from './cli/index.js';
5
+
6
+ function vcsRepositoryHostedOnGithub(vcs) {
7
+ return vcs && 'github' === vcs.host;
8
+ }
9
+
10
+ export default async function liftProjectType({projectRoot, packageDetails, vcs, configs}) {
11
+ if (await isPackage({projectRoot, packageDetails})) return liftPackage({projectRoot, packageDetails, configs});
12
+ if (await isCli({projectRoot, packageDetails})) return liftCli({projectRoot, packageDetails, configs});
13
+
14
+ let homepage;
15
+
16
+ if (vcsRepositoryHostedOnGithub(vcs)) {
17
+ homepage = `https://github.com/${vcs.owner}/${vcs.name}#readme`;
18
+
19
+ await mergeIntoExistingPackageJson({projectRoot, config: {homepage}});
20
+ }
21
+
22
+ return {homepage};
23
+ }
@@ -0,0 +1,69 @@
1
+ import {afterEach, describe, expect, it, vi} from 'vitest';
2
+ import {when} from 'vitest-when';
3
+ import any from '@travi/any';
4
+
5
+ import {lift as liftPackage, test as packagePredicate} from './package/index.js';
6
+ import {lift as liftCli, test as cliPredicate} from './cli/index.js';
7
+ import lift from './lifter.js';
8
+
9
+ vi.mock('@form8ion/javascript-core');
10
+ vi.mock('./package/index.js');
11
+ vi.mock('./cli/index.js');
12
+
13
+ describe('lift project-type', () => {
14
+ const projectRoot = any.string();
15
+ const packageDetails = any.simpleObject();
16
+
17
+ afterEach(() => {
18
+ vi.clearAllMocks();
19
+ });
20
+
21
+ it('should lift a package project-type', async () => {
22
+ const configs = any.simpleObject();
23
+ const liftPackageResults = any.simpleObject();
24
+ when(packagePredicate).calledWith({projectRoot, packageDetails}).thenResolve(true);
25
+ when(liftPackage).calledWith({projectRoot, packageDetails, configs}).thenResolve(liftPackageResults);
26
+
27
+ expect(await lift({projectRoot, packageDetails, configs})).toEqual(liftPackageResults);
28
+ });
29
+
30
+ it('should lift a cli project-type', async () => {
31
+ const configs = any.simpleObject();
32
+ const liftCliResults = any.simpleObject();
33
+ when(cliPredicate).calledWith({projectRoot, packageDetails}).thenResolve(true);
34
+ when(packagePredicate).calledWith({projectRoot, packageDetails}).thenResolve(false);
35
+ when(liftCli).calledWith({projectRoot, packageDetails, configs}).thenResolve(liftCliResults);
36
+
37
+ expect(await lift({projectRoot, packageDetails, configs})).toEqual(liftCliResults);
38
+ });
39
+
40
+ it('should define the repository as the homepage if the available project-type lifters do not apply', async () => {
41
+ const vcsOwner = any.word();
42
+ const vcsName = any.word();
43
+ when(packagePredicate).calledWith({projectRoot, packageDetails}).thenResolve(false);
44
+ when(cliPredicate).calledWith({projectRoot, packageDetails}).thenResolve(false);
45
+
46
+ expect(await lift({projectRoot, vcs: {host: 'github', owner: vcsOwner, name: vcsName}}))
47
+ .toEqual({homepage: `https://github.com/${vcsOwner}/${vcsName}#readme`});
48
+ });
49
+
50
+ it(
51
+ 'should return empty results if the available project-type lifters do not apply and not hosted on github',
52
+ async () => {
53
+ when(packagePredicate).calledWith({projectRoot, packageDetails}).thenResolve(false);
54
+ when(cliPredicate).calledWith({projectRoot, packageDetails}).thenResolve(false);
55
+
56
+ expect(await lift({projectRoot, vcs: {host: any.word()}})).toEqual({});
57
+ }
58
+ );
59
+
60
+ it(
61
+ 'should return empty results if the available project-type lifters do not apply and not version controlled',
62
+ async () => {
63
+ when(packagePredicate).calledWith({projectRoot, packageDetails}).thenResolve(false);
64
+ when(cliPredicate).calledWith({projectRoot, packageDetails}).thenResolve(false);
65
+
66
+ expect(await lift({projectRoot})).toEqual({});
67
+ }
68
+ );
69
+ });
@@ -0,0 +1 @@
1
+ export {default as scaffold} from './scaffolder.js';
@@ -0,0 +1,16 @@
1
+ import {mergeIntoExistingPackageJson} from '@form8ion/javascript-core';
2
+ import {info} from '@travi/cli-messages';
3
+
4
+ export default async function scaffoldMonorepo({projectRoot}) {
5
+ info('Scaffolding Monorepo Details');
6
+
7
+ await mergeIntoExistingPackageJson({projectRoot, config: {private: true}});
8
+
9
+ return {
10
+ nextSteps: [{
11
+ summary: 'Add packages to your new monorepo',
12
+ description: 'Leverage [@form8ion/add-package-to-monorepo](https://npm.im/@form8ion/add-package-to-monorepo)'
13
+ + ' to scaffold new packages into your new monorepo'
14
+ }]
15
+ };
16
+ }
@@ -0,0 +1,27 @@
1
+ import {mergeIntoExistingPackageJson} from '@form8ion/javascript-core';
2
+
3
+ import {describe, vi, it, expect, afterEach} from 'vitest';
4
+ import any from '@travi/any';
5
+
6
+ import scaffoldMonorepo from './scaffolder.js';
7
+
8
+ vi.mock('@form8ion/javascript-core');
9
+
10
+ describe('monorepo project-type scaffolder', () => {
11
+ const projectRoot = any.string();
12
+
13
+ afterEach(() => {
14
+ vi.clearAllMocks();
15
+ });
16
+
17
+ it('should scaffold the monorepo specific project details', async () => {
18
+ expect(await scaffoldMonorepo({projectRoot})).toEqual({
19
+ nextSteps: [{
20
+ summary: 'Add packages to your new monorepo',
21
+ description: 'Leverage [@form8ion/add-package-to-monorepo](https://npm.im/@form8ion/add-package-to-monorepo)'
22
+ + ' to scaffold new packages into your new monorepo'
23
+ }]
24
+ });
25
+ expect(mergeIntoExistingPackageJson).toHaveBeenCalledWith({projectRoot, config: {private: true}});
26
+ });
27
+ });