@form8ion/eslint-config-extender 10.0.2 → 11.0.0-beta.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.
package/example.js CHANGED
@@ -4,8 +4,9 @@ import {resolve} from 'node:path';
4
4
  import stubbedFs from 'mock-fs';
5
5
  import * as td from 'testdouble';
6
6
  import any from '@travi/any';
7
+ import {promptConstants} from '@form8ion/project';
7
8
 
8
- // remark-usage-ignore-next 12
9
+ // remark-usage-ignore-next 13
9
10
  const stubbedNodeModules = stubbedFs.load(resolve('node_modules'));
10
11
  const error = new Error('Command failed with exit code 1: npm ls husky --json');
11
12
  error.exitCode = 1;
@@ -18,9 +19,9 @@ td.when(execa('. ~/.nvm/nvm.sh && nvm install', {shell: true})).thenReturn({stdo
18
19
  td.when(execa('npm', ['ls', 'husky', '--json'])).thenReject(error);
19
20
  td.when(execa('npm run generate:md && npm test', {shell: true})).thenReturn({stdout: {pipe: () => undefined}});
20
21
  td.when(execa('npm', ['whoami'])).thenResolve({stdout: any.word()});
22
+ td.when(execa('npm', ['--version'])).thenResolve({stdout: any.word()});
21
23
 
22
24
  const {packageManagers} = await import('@form8ion/javascript-core');
23
- const githubPlugin = await import('@form8ion/github');
24
25
  const {questionNames: projectQuestionNames} = await import('@form8ion/project');
25
26
  const javascriptPlugin = await import('@form8ion/javascript');
26
27
  const {scaffold, extendEslintConfig} = await import('./lib/index.mjs');
@@ -46,15 +47,6 @@ stubbedFs({node_modules: stubbedNodeModules});
46
47
  await extendEslintConfig(
47
48
  {
48
49
  decisions: {
49
- [projectQuestionNames.PROJECT_NAME]: 'eslint-config-foo',
50
- [projectQuestionNames.DESCRIPTION]: 'a description of the project',
51
- [projectQuestionNames.VISIBILITY]: 'Public',
52
- [projectQuestionNames.LICENSE]: 'MIT',
53
- [projectQuestionNames.COPYRIGHT_HOLDER]: 'John Smith',
54
- [projectQuestionNames.COPYRIGHT_YEAR]: '2022',
55
- [projectQuestionNames.GIT_REPO]: true,
56
- [projectQuestionNames.REPO_HOST]: 'GitHub',
57
- [projectQuestionNames.REPO_OWNER]: 'org-name',
58
50
  [javascriptPlugin.questionNames.AUTHOR_NAME]: 'John Smith',
59
51
  [javascriptPlugin.questionNames.AUTHOR_EMAIL]: 'john@smith.org',
60
52
  [javascriptPlugin.questionNames.AUTHOR_URL]: 'https://smith.org',
@@ -64,7 +56,15 @@ stubbedFs({node_modules: stubbedNodeModules});
64
56
  [javascriptPlugin.questionNames.CI_SERVICE]: 'Other',
65
57
  [javascriptPlugin.questionNames.PROVIDE_EXAMPLE]: false
66
58
  },
67
- plugins: {vcsHosts: {GitHub: githubPlugin}}
59
+ plugins: {
60
+ vcsHosts: {
61
+ foo: {
62
+ scaffold: ({projectName}) => ({
63
+ vcs: {name: projectName, host: any.url(), owner: any.word(), ssh_url: any.url()}
64
+ })
65
+ }
66
+ }
67
+ }
68
68
  },
69
69
  decisions => ({
70
70
  ...javascriptPlugin,
@@ -74,6 +74,27 @@ stubbedFs({node_modules: stubbedNodeModules});
74
74
  configs: {},
75
75
  plugins: {unitTestFrameworks: {}}
76
76
  })
77
- })
77
+ }),
78
+ {
79
+ prompt: ({id}) => {
80
+ switch (id) {
81
+ case promptConstants.ids.BASE_DETAILS:
82
+ return {
83
+ [projectQuestionNames.PROJECT_NAME]: 'eslint-config-foo',
84
+ [projectQuestionNames.DESCRIPTION]: 'a description of the project',
85
+ [projectQuestionNames.VISIBILITY]: 'Public',
86
+ [projectQuestionNames.LICENSE]: 'MIT',
87
+ [projectQuestionNames.COPYRIGHT_HOLDER]: 'John Smith',
88
+ [projectQuestionNames.COPYRIGHT_YEAR]: '2022'
89
+ };
90
+ case promptConstants.ids.GIT_REPOSITORY:
91
+ return {[projectQuestionNames.GIT_REPO]: true};
92
+ case promptConstants.ids.REPOSITORY_HOST:
93
+ return {[projectQuestionNames.REPO_HOST]: 'foo'};
94
+ default:
95
+ throw new Error(`Unknown prompt: ${id}`);
96
+ }
97
+ }
98
+ }
78
99
  );
79
100
  })();
package/lib/index.mjs CHANGED
@@ -4,7 +4,7 @@ import { write } from '@form8ion/config-file';
4
4
  import deepmerge from 'deepmerge';
5
5
  import { questionNames as questionNames$1 } from '@form8ion/javascript';
6
6
  import { dialects } from '@form8ion/javascript-core';
7
- import { scaffold as scaffold$1, questionNames } from '@form8ion/project';
7
+ import { promptConstants, questionNames, scaffold as scaffold$1 } from '@form8ion/project';
8
8
 
9
9
  async function scaffold ({projectRoot, scope, projectName}) {
10
10
  const configShortName = projectName.substring('eslint-config-'.length);
@@ -34,8 +34,7 @@ async function scaffold ({projectRoot, scope, projectName}) {
34
34
 
35
35
  return {
36
36
  scripts: {'lint:js': 'eslint .'},
37
- dependencies: [`@form8ion/${projectName}`],
38
- devDependencies: [`@${scope}/eslint-config`],
37
+ dependencies: {javascript: {production: [`@form8ion/${projectName}`], development: [`@${scope}/eslint-config`]}},
39
38
  nextSteps: [
40
39
  {summary: 'Save the extended `@form8ion` eslint-config as an exact version'},
41
40
  {summary: 'Document saving this config using the dev flag'},
@@ -45,19 +44,30 @@ async function scaffold ({projectRoot, scope, projectName}) {
45
44
  }
46
45
 
47
46
  const PLUGIN_NAME = 'ESLint Config';
47
+ const JAVASCRIPT_LANGUAGE_CHOICE = 'JavaScript';
48
48
 
49
- function highLevel (options, javascriptPluginFactory) {
50
- const javaScriptLanguageChoice = 'JavaScript';
49
+ function injectLanguageChoiceIntoPrompt(prompt) {
50
+ return promptOptions => {
51
+ const {id} = promptOptions;
52
+
53
+ if (promptConstants.ids.PROJECT_LANGUAGE === id) {
54
+ return {[questionNames.PROJECT_LANGUAGE]: JAVASCRIPT_LANGUAGE_CHOICE};
55
+ }
56
+ return prompt(promptOptions);
57
+ };
58
+ }
59
+
60
+ function extendEslintConfig(options, javascriptPluginFactory, dependencies) {
61
+ const {decisions, ...otherOptions} = options;
51
62
 
52
63
  return scaffold$1(
53
64
  deepmerge(
54
- options,
65
+ otherOptions,
55
66
  {
56
- decisions: {[questionNames.PROJECT_LANGUAGE]: javaScriptLanguageChoice},
57
67
  plugins: {
58
68
  languages: {
59
- [javaScriptLanguageChoice]: javascriptPluginFactory({
60
- ...options.decisions,
69
+ [JAVASCRIPT_LANGUAGE_CHOICE]: javascriptPluginFactory({
70
+ ...decisions,
61
71
  [questionNames$1.PROJECT_TYPE]: 'Package',
62
72
  [questionNames$1.PROJECT_TYPE_CHOICE]: PLUGIN_NAME,
63
73
  [questionNames$1.UNIT_TESTS]: false,
@@ -69,9 +79,13 @@ function highLevel (options, javascriptPluginFactory) {
69
79
  }
70
80
  }
71
81
  }
72
- )
82
+ ),
83
+ {
84
+ ...dependencies,
85
+ prompt: injectLanguageChoiceIntoPrompt(dependencies.prompt)
86
+ }
73
87
  );
74
88
  }
75
89
 
76
- export { PLUGIN_NAME, highLevel as extendEslintConfig, scaffold };
90
+ export { PLUGIN_NAME, extendEslintConfig, scaffold };
77
91
  //# sourceMappingURL=index.mjs.map
package/lib/index.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/scaffold.js","../src/constants.js","../src/high-level.js"],"sourcesContent":["import {promises as fs} from 'node:fs';\nimport {fileTypes} from '@form8ion/core';\nimport {write} from '@form8ion/config-file';\n\nexport default async function ({projectRoot, scope, projectName}) {\n const configShortName = projectName.substring('eslint-config-'.length);\n\n await Promise.all([\n write({\n format: fileTypes.YAML,\n path: projectRoot,\n name: 'eslint',\n config: {root: true, extends: [`@${scope}`, '.']}\n }),\n fs.writeFile(\n `${projectRoot}/index.js`,\n `module.exports = {extends: '@form8ion/${configShortName}'};\\n`\n ),\n fs.writeFile(\n `${projectRoot}/example.js`,\n `module.exports = {\n extends: [\n '@${scope}',\n '@${scope}/${configShortName}'\n ]\n};\n`\n )\n ]);\n\n return {\n scripts: {'lint:js': 'eslint .'},\n dependencies: [`@form8ion/${projectName}`],\n devDependencies: [`@${scope}/eslint-config`],\n nextSteps: [\n {summary: 'Save the extended `@form8ion` eslint-config as an exact version'},\n {summary: 'Document saving this config using the dev flag'},\n {summary: 'Link to the extended `@form8ion` config in the README'}\n ]\n };\n}\n","export const PLUGIN_NAME = 'ESLint Config';\n","import deepmerge from 'deepmerge';\nimport {questionNames as jsQuestionNames} from '@form8ion/javascript';\nimport {dialects} from '@form8ion/javascript-core';\nimport {questionNames as projectQuestionNames, scaffold} from '@form8ion/project';\n\nimport {PLUGIN_NAME} from './constants.js';\n\nexport default function (options, javascriptPluginFactory) {\n const javaScriptLanguageChoice = 'JavaScript';\n\n return scaffold(\n deepmerge(\n options,\n {\n decisions: {[projectQuestionNames.PROJECT_LANGUAGE]: javaScriptLanguageChoice},\n plugins: {\n languages: {\n [javaScriptLanguageChoice]: javascriptPluginFactory({\n ...options.decisions,\n [jsQuestionNames.PROJECT_TYPE]: 'Package',\n [jsQuestionNames.PROJECT_TYPE_CHOICE]: PLUGIN_NAME,\n [jsQuestionNames.UNIT_TESTS]: false,\n [jsQuestionNames.INTEGRATION_TESTS]: false,\n [jsQuestionNames.CONFIGURE_LINTING]: false,\n [jsQuestionNames.DIALECT]: dialects.COMMON_JS,\n [jsQuestionNames.SHOULD_BE_SCOPED]: true\n })\n }\n }\n }\n )\n );\n}\n"],"names":["fs","scaffold","projectQuestionNames","jsQuestionNames"],"mappings":";;;;;;;;AAIe,uBAAc,EAAE,CAAC,WAAW,EAAE,KAAK,EAAE,WAAW,CAAC,EAAE;AAClE,EAAE,MAAM,eAAe,GAAG,WAAW,CAAC,SAAS,CAAC,gBAAgB,CAAC,MAAM,CAAC;;AAExE,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC;AACpB,IAAI,KAAK,CAAC;AACV,MAAM,MAAM,EAAE,SAAS,CAAC,IAAI;AAC5B,MAAM,IAAI,EAAE,WAAW;AACvB,MAAM,IAAI,EAAE,QAAQ;AACpB,MAAM,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;AACtD,KAAK,CAAC;AACN,IAAIA,QAAE,CAAC,SAAS;AAChB,MAAM,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC;AAC/B,MAAM,CAAC,sCAAsC,EAAE,eAAe,CAAC,KAAK;AACpE,KAAK;AACL,IAAIA,QAAE,CAAC,SAAS;AAChB,MAAM,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC;AACjC,MAAM,CAAC;AACP;AACA,MAAM,EAAE,KAAK,CAAC;AACd,MAAM,EAAE,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC;AACjC;AACA;AACA;AACA;AACA,GAAG,CAAC;;AAEJ,EAAE,OAAO;AACT,IAAI,OAAO,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC;AACpC,IAAI,YAAY,EAAE,CAAC,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;AAC9C,IAAI,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;AAChD,IAAI,SAAS,EAAE;AACf,MAAM,CAAC,OAAO,EAAE,iEAAiE,CAAC;AAClF,MAAM,CAAC,OAAO,EAAE,gDAAgD,CAAC;AACjE,MAAM,CAAC,OAAO,EAAE,uDAAuD;AACvE;AACA,GAAG;AACH;;ACxCY,MAAC,WAAW,GAAG;;ACOZ,kBAAQ,EAAE,OAAO,EAAE,uBAAuB,EAAE;AAC3D,EAAE,MAAM,wBAAwB,GAAG,YAAY;;AAE/C,EAAE,OAAOC,UAAQ;AACjB,IAAI,SAAS;AACb,MAAM,OAAO;AACb,MAAM;AACN,QAAQ,SAAS,EAAE,CAAC,CAACC,aAAoB,CAAC,gBAAgB,GAAG,wBAAwB,CAAC;AACtF,QAAQ,OAAO,EAAE;AACjB,UAAU,SAAS,EAAE;AACrB,YAAY,CAAC,wBAAwB,GAAG,uBAAuB,CAAC;AAChE,cAAc,GAAG,OAAO,CAAC,SAAS;AAClC,cAAc,CAACC,eAAe,CAAC,YAAY,GAAG,SAAS;AACvD,cAAc,CAACA,eAAe,CAAC,mBAAmB,GAAG,WAAW;AAChE,cAAc,CAACA,eAAe,CAAC,UAAU,GAAG,KAAK;AACjD,cAAc,CAACA,eAAe,CAAC,iBAAiB,GAAG,KAAK;AACxD,cAAc,CAACA,eAAe,CAAC,iBAAiB,GAAG,KAAK;AACxD,cAAc,CAACA,eAAe,CAAC,OAAO,GAAG,QAAQ,CAAC,SAAS;AAC3D,cAAc,CAACA,eAAe,CAAC,gBAAgB,GAAG;AAClD,aAAa;AACb;AACA;AACA;AACA;AACA,GAAG;AACH;;;;"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/scaffold.js","../src/constants.js","../src/language-handler-prompt.js","../src/high-level.js"],"sourcesContent":["import {promises as fs} from 'node:fs';\nimport {fileTypes} from '@form8ion/core';\nimport {write} from '@form8ion/config-file';\n\nexport default async function ({projectRoot, scope, projectName}) {\n const configShortName = projectName.substring('eslint-config-'.length);\n\n await Promise.all([\n write({\n format: fileTypes.YAML,\n path: projectRoot,\n name: 'eslint',\n config: {root: true, extends: [`@${scope}`, '.']}\n }),\n fs.writeFile(\n `${projectRoot}/index.js`,\n `module.exports = {extends: '@form8ion/${configShortName}'};\\n`\n ),\n fs.writeFile(\n `${projectRoot}/example.js`,\n `module.exports = {\n extends: [\n '@${scope}',\n '@${scope}/${configShortName}'\n ]\n};\n`\n )\n ]);\n\n return {\n scripts: {'lint:js': 'eslint .'},\n dependencies: {javascript: {production: [`@form8ion/${projectName}`], development: [`@${scope}/eslint-config`]}},\n nextSteps: [\n {summary: 'Save the extended `@form8ion` eslint-config as an exact version'},\n {summary: 'Document saving this config using the dev flag'},\n {summary: 'Link to the extended `@form8ion` config in the README'}\n ]\n };\n}\n","export const PLUGIN_NAME = 'ESLint Config';\nexport const JAVASCRIPT_LANGUAGE_CHOICE = 'JavaScript';\n","import {promptConstants, questionNames as projectQuestionNames} from '@form8ion/project';\nimport {JAVASCRIPT_LANGUAGE_CHOICE} from './constants.js';\n\nexport default function injectLanguageChoiceIntoPrompt(prompt) {\n return promptOptions => {\n const {id} = promptOptions;\n\n if (promptConstants.ids.PROJECT_LANGUAGE === id) {\n return {[projectQuestionNames.PROJECT_LANGUAGE]: JAVASCRIPT_LANGUAGE_CHOICE};\n }\n return prompt(promptOptions);\n };\n}\n","import deepmerge from 'deepmerge';\nimport {questionNames as jsQuestionNames} from '@form8ion/javascript';\nimport {dialects} from '@form8ion/javascript-core';\nimport {scaffold} from '@form8ion/project';\n\nimport {JAVASCRIPT_LANGUAGE_CHOICE, PLUGIN_NAME} from './constants.js';\nimport injectLanguageChoiceIntoPrompt from './language-handler-prompt.js';\n\nexport default function extendEslintConfig(options, javascriptPluginFactory, dependencies) {\n const {decisions, ...otherOptions} = options;\n\n return scaffold(\n deepmerge(\n otherOptions,\n {\n plugins: {\n languages: {\n [JAVASCRIPT_LANGUAGE_CHOICE]: javascriptPluginFactory({\n ...decisions,\n [jsQuestionNames.PROJECT_TYPE]: 'Package',\n [jsQuestionNames.PROJECT_TYPE_CHOICE]: PLUGIN_NAME,\n [jsQuestionNames.UNIT_TESTS]: false,\n [jsQuestionNames.INTEGRATION_TESTS]: false,\n [jsQuestionNames.CONFIGURE_LINTING]: false,\n [jsQuestionNames.DIALECT]: dialects.COMMON_JS,\n [jsQuestionNames.SHOULD_BE_SCOPED]: true\n })\n }\n }\n }\n ),\n {\n ...dependencies,\n prompt: injectLanguageChoiceIntoPrompt(dependencies.prompt)\n }\n );\n}\n"],"names":["fs","projectQuestionNames","scaffold","jsQuestionNames"],"mappings":"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"}
package/package.json CHANGED
@@ -2,10 +2,10 @@
2
2
  "name": "@form8ion/eslint-config-extender",
3
3
  "description": "shareable ESLint config scaffolder for extending another config",
4
4
  "license": "MIT",
5
- "version": "10.0.2",
5
+ "version": "11.0.0-beta.1",
6
6
  "type": "module",
7
7
  "engines": {
8
- "node": "^18.19.0 || ^20.6.1 || >=22"
8
+ "node": "^20.19.0 || >=22.14.0"
9
9
  },
10
10
  "author": "Matt Travi <npm@travi.org> (https://matt.travi.org)",
11
11
  "repository": "form8ion/eslint-config-extender",
@@ -16,7 +16,8 @@
16
16
  "main": "lib/index.mjs",
17
17
  "sideEffects": false,
18
18
  "scripts": {
19
- "test": "npm-run-all --print-label build --parallel lint:* --parallel test:*",
19
+ "pretest": "run-s build",
20
+ "test": "npm-run-all --print-label --parallel lint:* --parallel test:*",
20
21
  "lint:lockfile": "lockfile-lint",
21
22
  "lint:js": "eslint . --cache",
22
23
  "lint:md": "remark . --frail",
@@ -47,52 +48,54 @@
47
48
  },
48
49
  "files": [
49
50
  "example.js",
50
- "lib/"
51
+ "lib/",
52
+ "src/"
51
53
  ],
52
54
  "publishConfig": {
53
55
  "access": "public",
54
56
  "provenance": true
55
57
  },
56
- "packageManager": "npm@10.9.0+sha512.65a9c38a8172948f617a53619762cd77e12b9950fe1f9239debcb8d62c652f2081824b986fee7c0af6c0a7df615becebe4bf56e17ec27214a87aa29d9e038b4b",
58
+ "packageManager": "npm@11.6.2+sha512.ee22b335fcbc95662cdf3ab8a053daf045d9cf9c6df6040d28965abb707512b2c16fa6c5eec049d34c74f78f390cebd14f697919eadb97756564d4f9eccc4954",
57
59
  "dependencies": {
58
60
  "@form8ion/config-file": "^1.1.2",
59
61
  "@form8ion/core": "^4.7.1",
60
- "@form8ion/javascript": "^13.0.2",
62
+ "@form8ion/javascript": "^14.0.0-beta.1",
61
63
  "@form8ion/javascript-core": "^12.0.0",
62
- "@form8ion/project": "^20.0.0",
64
+ "@form8ion/project": "^22.0.0-beta.8",
63
65
  "deepmerge": "^4.2.2"
64
66
  },
65
67
  "devDependencies": {
66
- "@cucumber/cucumber": "11.0.1",
67
- "@form8ion/commitlint-config": "2.0.0",
68
- "@form8ion/eslint-config": "7.0.12",
68
+ "@cucumber/cucumber": "11.3.0",
69
+ "@form8ion/commitlint-config": "2.0.8",
70
+ "@form8ion/eslint-config": "7.0.13",
69
71
  "@form8ion/eslint-config-cucumber": "1.4.1",
70
- "@form8ion/github": "2.0.0",
71
- "@form8ion/remark-lint-preset": "6.0.5",
72
- "@travi/any": "3.1.2",
73
- "ban-sensitive-files": "1.10.6",
74
- "c8": "10.1.2",
75
- "chai": "5.1.2",
76
- "cross-env": "7.0.3",
72
+ "@form8ion/eslint-config-vitest": "1.0.0",
73
+ "@form8ion/remark-lint-preset": "6.0.7",
74
+ "@travi/any": "3.1.3",
75
+ "ban-sensitive-files": "1.10.11",
76
+ "c8": "10.1.3",
77
+ "chai": "6.2.0",
78
+ "cross-env": "10.1.0",
77
79
  "cz-conventional-changelog": "3.3.0",
78
- "debug": "4.3.7",
80
+ "debug": "4.4.3",
79
81
  "gherkin-lint": "4.2.4",
80
- "husky": "9.1.6",
81
- "jest-when": "3.6.0",
82
+ "husky": "9.1.7",
82
83
  "js-yaml": "4.1.0",
83
- "lockfile-lint": "4.14.0",
84
+ "lockfile-lint": "4.14.1",
84
85
  "ls-engines": "0.9.3",
85
- "mock-fs": "5.4.1",
86
- "nock": "13.5.6",
87
- "npm-run-all2": "7.0.1",
88
- "publint": "0.2.12",
86
+ "mock-fs": "5.5.0",
87
+ "nock": "14.0.10",
88
+ "npm-run-all2": "8.0.4",
89
+ "publint": "0.3.15",
89
90
  "remark-cli": "12.0.1",
90
91
  "remark-toc": "9.0.0",
91
92
  "remark-usage": "11.0.1",
92
93
  "rimraf": "6.0.1",
93
- "rollup": "4.25.0",
94
+ "rollup": "4.52.5",
94
95
  "rollup-plugin-auto-external": "2.0.0",
96
+ "simple-git": "3.28.0",
95
97
  "testdouble": "3.20.2",
96
- "vitest": "2.1.4"
98
+ "vitest": "4.0.4",
99
+ "vitest-when": "0.9.0"
97
100
  }
98
101
  }
@@ -0,0 +1,2 @@
1
+ export const PLUGIN_NAME = 'ESLint Config';
2
+ export const JAVASCRIPT_LANGUAGE_CHOICE = 'JavaScript';
@@ -0,0 +1,37 @@
1
+ import deepmerge from 'deepmerge';
2
+ import {questionNames as jsQuestionNames} from '@form8ion/javascript';
3
+ import {dialects} from '@form8ion/javascript-core';
4
+ import {scaffold} from '@form8ion/project';
5
+
6
+ import {JAVASCRIPT_LANGUAGE_CHOICE, PLUGIN_NAME} from './constants.js';
7
+ import injectLanguageChoiceIntoPrompt from './language-handler-prompt.js';
8
+
9
+ export default function extendEslintConfig(options, javascriptPluginFactory, dependencies) {
10
+ const {decisions, ...otherOptions} = options;
11
+
12
+ return scaffold(
13
+ deepmerge(
14
+ otherOptions,
15
+ {
16
+ plugins: {
17
+ languages: {
18
+ [JAVASCRIPT_LANGUAGE_CHOICE]: javascriptPluginFactory({
19
+ ...decisions,
20
+ [jsQuestionNames.PROJECT_TYPE]: 'Package',
21
+ [jsQuestionNames.PROJECT_TYPE_CHOICE]: PLUGIN_NAME,
22
+ [jsQuestionNames.UNIT_TESTS]: false,
23
+ [jsQuestionNames.INTEGRATION_TESTS]: false,
24
+ [jsQuestionNames.CONFIGURE_LINTING]: false,
25
+ [jsQuestionNames.DIALECT]: dialects.COMMON_JS,
26
+ [jsQuestionNames.SHOULD_BE_SCOPED]: true
27
+ })
28
+ }
29
+ }
30
+ }
31
+ ),
32
+ {
33
+ ...dependencies,
34
+ prompt: injectLanguageChoiceIntoPrompt(dependencies.prompt)
35
+ }
36
+ );
37
+ }
@@ -0,0 +1,48 @@
1
+ import * as projectScaffolder from '@form8ion/project';
2
+ import * as javascriptScaffolder from '@form8ion/javascript';
3
+ import {dialects} from '@form8ion/javascript-core';
4
+
5
+ import {describe, expect, it, vi} from 'vitest';
6
+ import any from '@travi/any';
7
+ import {when} from 'vitest-when';
8
+
9
+ import {JAVASCRIPT_LANGUAGE_CHOICE, PLUGIN_NAME} from './constants.js';
10
+ import injectLanguageChoiceIntoPrompt from './language-handler-prompt.js';
11
+ import extendEslintConfig from './high-level.js';
12
+
13
+ vi.mock('@form8ion/project');
14
+ vi.mock('./language-handler-prompt.js');
15
+
16
+ describe('high-level scaffolder', () => {
17
+ it('should execute the project-scaffolder', async () => {
18
+ const prompt = () => undefined;
19
+ const enhancedPrompt = () => undefined;
20
+ const dependencies = {...any.simpleObject(), prompt};
21
+ const providedDecisions = any.simpleObject();
22
+ const optionsWithoutDecisions = any.simpleObject();
23
+ const options = {...optionsWithoutDecisions, decisions: providedDecisions};
24
+ const jsPlugin = {scaffold: any.simpleObject()};
25
+ const javascriptPluginFactory = vi.fn();
26
+ when(javascriptPluginFactory).calledWith({
27
+ ...providedDecisions,
28
+ [javascriptScaffolder.questionNames.PROJECT_TYPE]: 'Package',
29
+ [javascriptScaffolder.questionNames.PROJECT_TYPE_CHOICE]: PLUGIN_NAME,
30
+ [javascriptScaffolder.questionNames.UNIT_TESTS]: false,
31
+ [javascriptScaffolder.questionNames.INTEGRATION_TESTS]: false,
32
+ [javascriptScaffolder.questionNames.CONFIGURE_LINTING]: false,
33
+ [javascriptScaffolder.questionNames.DIALECT]: dialects.COMMON_JS,
34
+ [javascriptScaffolder.questionNames.SHOULD_BE_SCOPED]: true
35
+ }).thenReturn(jsPlugin);
36
+ when(injectLanguageChoiceIntoPrompt).calledWith(prompt).thenReturn(enhancedPrompt);
37
+
38
+ await extendEslintConfig(options, javascriptPluginFactory, dependencies);
39
+
40
+ expect(projectScaffolder.scaffold).toHaveBeenCalledWith(
41
+ {
42
+ ...optionsWithoutDecisions,
43
+ plugins: {languages: {[JAVASCRIPT_LANGUAGE_CHOICE]: jsPlugin}}
44
+ },
45
+ {...dependencies, prompt: enhancedPrompt}
46
+ );
47
+ });
48
+ });
package/src/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export {default as scaffold} from './scaffold.js';
2
+ export {default as extendEslintConfig} from './high-level.js';
3
+ export {PLUGIN_NAME} from './constants.js';
@@ -0,0 +1,13 @@
1
+ import {promptConstants, questionNames as projectQuestionNames} from '@form8ion/project';
2
+ import {JAVASCRIPT_LANGUAGE_CHOICE} from './constants.js';
3
+
4
+ export default function injectLanguageChoiceIntoPrompt(prompt) {
5
+ return promptOptions => {
6
+ const {id} = promptOptions;
7
+
8
+ if (promptConstants.ids.PROJECT_LANGUAGE === id) {
9
+ return {[projectQuestionNames.PROJECT_LANGUAGE]: JAVASCRIPT_LANGUAGE_CHOICE};
10
+ }
11
+ return prompt(promptOptions);
12
+ };
13
+ }
@@ -0,0 +1,26 @@
1
+ import {promptConstants, questionNames as projectQuestionNames} from '@form8ion/project';
2
+
3
+ import {describe, it, vi, expect} from 'vitest';
4
+ import {when} from 'vitest-when';
5
+ import any from '@travi/any';
6
+
7
+ import injectLanguageChoiceIntoPrompt from './language-handler-prompt.js';
8
+ import {JAVASCRIPT_LANGUAGE_CHOICE} from './constants.js';
9
+
10
+ describe('language choice handler prompt', () => {
11
+ it('should call the provided prompt handler for other prompts', async () => {
12
+ const promptOptions = {...any.simpleObject(), id: any.word()};
13
+ const prompt = vi.fn();
14
+ const answers = any.simpleObject();
15
+ when(prompt).calledWith(promptOptions).thenResolve(answers);
16
+
17
+ expect(await injectLanguageChoiceIntoPrompt(prompt)(promptOptions)).toEqual(answers);
18
+ });
19
+
20
+ it('should define the language choice as JavaScript for the language handler prompt', async () => {
21
+ expect(await injectLanguageChoiceIntoPrompt(() => undefined)({
22
+ ...any.simpleObject(),
23
+ id: promptConstants.ids.PROJECT_LANGUAGE
24
+ })).toEqual({[projectQuestionNames.PROJECT_LANGUAGE]: JAVASCRIPT_LANGUAGE_CHOICE});
25
+ });
26
+ });
@@ -0,0 +1,40 @@
1
+ import {promises as fs} from 'node:fs';
2
+ import {fileTypes} from '@form8ion/core';
3
+ import {write} from '@form8ion/config-file';
4
+
5
+ export default async function ({projectRoot, scope, projectName}) {
6
+ const configShortName = projectName.substring('eslint-config-'.length);
7
+
8
+ await Promise.all([
9
+ write({
10
+ format: fileTypes.YAML,
11
+ path: projectRoot,
12
+ name: 'eslint',
13
+ config: {root: true, extends: [`@${scope}`, '.']}
14
+ }),
15
+ fs.writeFile(
16
+ `${projectRoot}/index.js`,
17
+ `module.exports = {extends: '@form8ion/${configShortName}'};\n`
18
+ ),
19
+ fs.writeFile(
20
+ `${projectRoot}/example.js`,
21
+ `module.exports = {
22
+ extends: [
23
+ '@${scope}',
24
+ '@${scope}/${configShortName}'
25
+ ]
26
+ };
27
+ `
28
+ )
29
+ ]);
30
+
31
+ return {
32
+ scripts: {'lint:js': 'eslint .'},
33
+ dependencies: {javascript: {production: [`@form8ion/${projectName}`], development: [`@${scope}/eslint-config`]}},
34
+ nextSteps: [
35
+ {summary: 'Save the extended `@form8ion` eslint-config as an exact version'},
36
+ {summary: 'Document saving this config using the dev flag'},
37
+ {summary: 'Link to the extended `@form8ion` config in the README'}
38
+ ]
39
+ };
40
+ }
@@ -0,0 +1,58 @@
1
+ import {promises as fs} from 'node:fs';
2
+ import {fileTypes} from '@form8ion/core';
3
+ import {write} from '@form8ion/config-file';
4
+
5
+ import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
6
+ import any from '@travi/any';
7
+
8
+ import scaffold from './scaffold.js';
9
+
10
+ describe('scaffold', () => {
11
+ const projectRoot = any.string();
12
+
13
+ beforeEach(() => {
14
+ vi.mock('node:fs');
15
+ vi.mock('@form8ion/config-file');
16
+ });
17
+
18
+ afterEach(() => {
19
+ vi.clearAllMocks();
20
+ });
21
+
22
+ it('should extend the chosen form8ion config', async () => {
23
+ const scope = any.word();
24
+ const configShortName = any.word();
25
+ const projectName = `eslint-config-${configShortName}`;
26
+
27
+ const {scripts, dependencies, nextSteps} = await scaffold({projectRoot, projectName, scope});
28
+
29
+ expect(write).toHaveBeenCalledWith({
30
+ path: projectRoot,
31
+ format: fileTypes.YAML,
32
+ name: 'eslint',
33
+ config: {root: true, extends: [`@${scope}`, '.']}
34
+ });
35
+ expect(fs.writeFile).toHaveBeenCalledWith(
36
+ `${projectRoot}/index.js`,
37
+ `module.exports = {extends: '@form8ion/${configShortName}'};\n`
38
+ );
39
+ expect(fs.writeFile).toHaveBeenCalledWith(
40
+ `${projectRoot}/example.js`,
41
+ `module.exports = {
42
+ extends: [
43
+ '@${scope}',
44
+ '@${scope}/${configShortName}'
45
+ ]
46
+ };
47
+ `
48
+ );
49
+ expect(scripts).toEqual({'lint:js': 'eslint .'});
50
+ expect(dependencies.javascript.production).toEqual([`@form8ion/${projectName}`]);
51
+ expect(dependencies.javascript.development).toEqual([`@${scope}/eslint-config`]);
52
+ expect(nextSteps).toEqual([
53
+ {summary: 'Save the extended `@form8ion` eslint-config as an exact version'},
54
+ {summary: 'Document saving this config using the dev flag'},
55
+ {summary: 'Link to the extended `@form8ion` config in the README'}
56
+ ]);
57
+ });
58
+ });