aberlaas 2.0.0 → 2.2.0

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 (81) hide show
  1. package/README.md +126 -4
  2. package/bin/{aberlaas → aberlaas.js} +1 -1
  3. package/commands/ci/autoRelease.js +9 -8
  4. package/commands/ci/index.js +10 -10
  5. package/commands/compress/dummy.js +11 -0
  6. package/commands/compress/index.js +10 -19
  7. package/commands/compress/png.js +22 -13
  8. package/commands/{init.js → init/index.js} +51 -31
  9. package/commands/lint/circleci.js +10 -11
  10. package/commands/lint/css.js +33 -25
  11. package/commands/lint/helpers/prettier.js +57 -0
  12. package/commands/lint/index.js +18 -48
  13. package/commands/lint/js.js +40 -52
  14. package/commands/lint/json.js +14 -12
  15. package/commands/lint/yml.js +16 -13
  16. package/commands/{precommit.js → precommit/index.js} +7 -7
  17. package/commands/readme/index.js +16 -16
  18. package/commands/{release.js → release/index.js} +5 -6
  19. package/commands/setup/autoRelease/envVars.js +9 -8
  20. package/commands/setup/autoRelease/index.js +12 -11
  21. package/commands/setup/autoRelease/privateKey.js +6 -5
  22. package/commands/setup/autoRelease/publicKey.js +8 -7
  23. package/commands/setup/circleci.js +9 -8
  24. package/commands/setup/github.js +6 -5
  25. package/commands/setup/helpers/circleci.js +6 -5
  26. package/commands/setup/helpers/github.js +6 -5
  27. package/commands/setup/helpers/npm.js +1 -1
  28. package/commands/setup/helpers/ssh.js +11 -10
  29. package/commands/setup/index.js +6 -6
  30. package/commands/setup/renovate.js +7 -6
  31. package/commands/test/index.js +83 -0
  32. package/configs/{eslint.js → eslint.cjs} +77 -29
  33. package/configs/{lintstaged.js → lintstaged.cjs} +7 -1
  34. package/configs/node.cjs +5 -0
  35. package/configs/vite/test/setupFiles/captureOutput.js +4 -0
  36. package/configs/vite/test/setupFiles/dedent.js +4 -0
  37. package/configs/vite/test/setupFiles/fit-xit-fdescribe-xdescribe.js +13 -0
  38. package/configs/vite/test/setupFiles/jest-extended.js +10 -0
  39. package/configs/vite/test/setupFiles/testName.js +9 -0
  40. package/configs/vite.js +25 -0
  41. package/helper.js +49 -38
  42. package/main.js +28 -22
  43. package/package.json +30 -23
  44. package/scripts/postinstall +15 -0
  45. package/templates/_circleci/config.yml +1 -1
  46. package/templates/_eslintignore.conf +1 -1
  47. package/templates/_eslintrc.cjs +3 -0
  48. package/templates/_lintstagedrc.cjs +4 -0
  49. package/templates/_prettierrc.cjs +4 -0
  50. package/templates/_stylelintrc.cjs +4 -0
  51. package/templates/_yarnrc.yml +9 -0
  52. package/templates/lib/__tests__/main.js +2 -2
  53. package/templates/lib/main.js +1 -1
  54. package/templates/scripts/{husky-precommit → compress} +1 -1
  55. package/templates/scripts/hooks/pre-commit +11 -0
  56. package/templates/vite.config.js +4 -0
  57. package/commands/test.js +0 -92
  58. package/configs/husky.js +0 -5
  59. package/configs/jest/index.js +0 -49
  60. package/configs/jest/jest-extended.js +0 -3
  61. package/configs/jest/setupFileAfterEnv.js +0 -13
  62. package/configs/jest/sharedState.js +0 -14
  63. package/configs/jest/testEnvironment.js +0 -46
  64. package/configs/jest.js +0 -1
  65. package/configs/node.js +0 -3
  66. package/lib/configs/deprecated.js +0 -17
  67. package/lib/configs/eslint.js +0 -2
  68. package/lib/configs/husky.js +0 -2
  69. package/lib/configs/jest.js +0 -2
  70. package/lib/configs/lintstaged.js +0 -2
  71. package/lib/configs/prettier.js +0 -2
  72. package/lib/configs/stylelint.js +0 -2
  73. package/templates/_eslintrc.js +0 -3
  74. package/templates/_huskyrc.js +0 -4
  75. package/templates/_lintstagedrc.js +0 -4
  76. package/templates/_prettierrc.js +0 -4
  77. package/templates/_stylelintrc.js +0 -4
  78. package/templates/babel.config.js +0 -3
  79. package/templates/jest.config.js +0 -4
  80. /package/configs/{prettier.js → prettier.cjs} +0 -0
  81. /package/configs/{stylelint.js → stylelint.cjs} +0 -0
@@ -1,8 +1,9 @@
1
- const run = require('firost/run');
2
- const { Octokit } = require('@octokit/rest');
3
- const parseGithubUrl = require('parse-github-repo-url');
4
- const _ = require('golgoth/lodash');
5
- module.exports = {
1
+ import run from 'firost/run.js';
2
+ import { Octokit } from '@octokit/rest';
3
+ import parseGithubUrl from 'parse-github-repo-url';
4
+ import _ from 'golgoth/lodash.js';
5
+
6
+ export default {
6
7
  /**
7
8
  * Returns the GitHub token saved in ENV
8
9
  * @returns {string} The GitHub token
@@ -1,4 +1,4 @@
1
- module.exports = {
1
+ export default {
2
2
  /**
3
3
  * Returns the npm token saved in ENV
4
4
  * @returns {string} The npm token
@@ -1,13 +1,14 @@
1
- const helper = require('../../../helper.js');
2
- const githubHelper = require('./github.js');
3
- const _ = require('golgoth/lodash');
4
- const which = require('firost/which');
5
- const exists = require('firost/exists');
6
- const read = require('firost/read');
7
- const run = require('firost/run');
8
- const mkdirp = require('firost/mkdirp');
9
- const path = require('path');
10
- module.exports = {
1
+ import helper from '../../../helper.js';
2
+ import githubHelper from './github.js';
3
+ import _ from 'golgoth/lodash.js';
4
+ import which from 'firost/which.js';
5
+ import exists from 'firost/exists.js';
6
+ import read from 'firost/read.js';
7
+ import run from 'firost/run.js';
8
+ import mkdirp from 'firost/mkdirp.js';
9
+ import path from 'path';
10
+
11
+ export default {
11
12
  /**
12
13
  * Check if ssh-keygen is available
13
14
  * @returns {boolean} True if available, false otherwise
@@ -1,10 +1,10 @@
1
- const github = require('./github.js');
2
- const circleci = require('./circleci.js');
3
- const renovate = require('./renovate.js');
4
- const autoRelease = require('./autoRelease');
5
- const _ = require('golgoth/lodash');
1
+ import github from './github.js';
2
+ import circleci from './circleci.js';
3
+ import renovate from './renovate.js';
4
+ import autoRelease from './autoRelease/index.js';
5
+ import _ from 'golgoth/lodash.js';
6
6
 
7
- module.exports = {
7
+ export default {
8
8
  /**
9
9
  * Enable external services.
10
10
  * Will enable CircleCI, GitHub and Renovate by default.
@@ -1,7 +1,8 @@
1
- const githubHelper = require('./helpers/github.js');
2
- const consoleSuccess = require('firost/consoleSuccess');
3
- const consoleError = require('firost/consoleError');
4
- module.exports = {
1
+ import githubHelper from './helpers/github.js';
2
+ import consoleSuccess from 'firost/consoleSuccess.js';
3
+ import consoleError from 'firost/consoleError.js';
4
+
5
+ export default {
5
6
  renovateId: 2471197,
6
7
  /**
7
8
  * Returns the GitHub repository Id
@@ -28,7 +29,7 @@ module.exports = {
28
29
  // Fail early if no token available
29
30
  if (!githubHelper.hasToken()) {
30
31
  this.__consoleError(
31
- `[renovate]: No GITHUB_TOKEN found, please visit ${manualUrl} to enable manually.`
32
+ `[renovate]: No GITHUB_TOKEN found, please visit ${manualUrl} to enable manually.`,
32
33
  );
33
34
  return false;
34
35
  }
@@ -41,7 +42,7 @@ module.exports = {
41
42
  });
42
43
  } catch (err) {
43
44
  this.__consoleError(
44
- `Renovate is not installed with this GitHub account, please visit ${manualUrl} to install it first.`
45
+ `Renovate is not installed with this GitHub account, please visit ${manualUrl} to install it first.`,
45
46
  );
46
47
  return false;
47
48
  }
@@ -0,0 +1,83 @@
1
+ import helper from '../../helper.js';
2
+ import run from 'firost/run.js';
3
+ import _ from 'golgoth/lodash.js';
4
+
5
+ export default {
6
+ /**
7
+ * Test all files using Vitest
8
+ * Usage:
9
+ * $ aberlaas test # Test all files
10
+ * $ aberlaas test ./path/to/__tests__/file.js # Test specific files
11
+ * $ aberlaas test ./path/to/file.js # Test specific files
12
+ * $ aberlaas test --related # Test all related files
13
+ * $ aberlaas test --failFast # Stop early as soon as one test fails
14
+ * $ aberlaas test --flags # Flags passed to vitest
15
+ * @param {object} cliArgs CLI Argument object, as created by minimist
16
+ * @returns {boolean} true on success
17
+ **/
18
+ async run(cliArgs) {
19
+ const options = await this.vitestCliOptions(cliArgs);
20
+
21
+ await run(`yarn run vitest ${options.join(' ')}`, { stdin: true });
22
+ return true;
23
+ },
24
+
25
+ /**
26
+ * Transform all aberlaas test cli options into suitable vitest CLI options
27
+ * @param {object} cliArgs CLI Argument object, as created by minimist
28
+ * @returns {Array} Array of cli arguments and values
29
+ **/
30
+ async vitestCliOptions(cliArgs = {}) {
31
+ // Options that have special meaning in aberlaas and shouldn't be passed
32
+ // as-is to vitest
33
+ const aberlaasOptions = ['_', 'watch', 'config', 'failFast', 'related'];
34
+
35
+ // Input files
36
+ const inputFiles = _.isEmpty(cliArgs._) ? [helper.hostPath()] : cliArgs._;
37
+ const vitestOptions = [...inputFiles];
38
+
39
+ // Run "vitest related" when --related is passed
40
+ if (cliArgs.related) {
41
+ vitestOptions.unshift('related');
42
+ }
43
+
44
+ // Stop early as soon as one test fails
45
+ if (cliArgs.failFast) {
46
+ vitestOptions.push('--bail=1');
47
+ }
48
+
49
+ // Disable watch by default
50
+ vitestOptions.push(cliArgs.watch ? '--watch=true' : '--watch=false');
51
+
52
+ // Allow a success, even if no files are passed
53
+ vitestOptions.push('--passWithNoTests');
54
+
55
+ // Hide skipped tests, allowing less noisy debug with fit/fdescribe
56
+ vitestOptions.push('--hideSkippedTests');
57
+
58
+ // Config file
59
+ const configFile = await helper.configFile(
60
+ cliArgs.config,
61
+ 'vite.config.js',
62
+ 'lib/configs/vite.js',
63
+ );
64
+ vitestOptions.push(`--config=${configFile}`);
65
+
66
+ // Pass any unknown options to vitest
67
+ _.each(cliArgs, (argValue, argKey) => {
68
+ // Skip keys that we already handled
69
+ if (_.includes(aberlaasOptions, argKey)) {
70
+ return;
71
+ }
72
+
73
+ if (argValue === true) {
74
+ vitestOptions.push(`--${argKey}`);
75
+ return;
76
+ }
77
+
78
+ vitestOptions.push(`--${argKey}=${argValue}`);
79
+ });
80
+
81
+ return vitestOptions;
82
+ },
83
+ };
@@ -1,27 +1,38 @@
1
- const nodeConfig = require('./node');
1
+ const nodeConfig = require('./node.cjs');
2
2
  module.exports = {
3
3
  env: {
4
4
  browser: true,
5
- es6: true,
5
+ es2023: true,
6
6
  node: true,
7
- jest: true,
8
7
  },
9
8
  parserOptions: {
10
- ecmaVersion: 2018,
9
+ sourceType: 'module',
10
+ ecmaVersion: 'latest',
11
11
  },
12
12
  extends: [
13
13
  'eslint:recommended',
14
- 'plugin:node/recommended',
15
- 'plugin:jest/recommended',
14
+ 'plugin:n/recommended',
15
+ 'plugin:import/recommended',
16
16
  'plugin:prettier/recommended',
17
17
  ],
18
- globals: {
19
- // Additional Jest globals added by Aberlaas
20
- testName: false,
21
- captureOutput: false,
22
- dedent: false,
18
+ settings: {
19
+ // eslint-plugin-import doesn't currently support the "exports" syntax in
20
+ // package.json. This allow mapping between custom entrypoints and
21
+ // files on disk.
22
+ // For example, it doesn't understand "import * from 'vitest/config';" as
23
+ // "vitest/config/" isn't really an existing filepath, but a mapping defined
24
+ // in vitest package.json
25
+ //
26
+ // Until this is fixed (see
27
+ // https://github.com/import-js/eslint-plugin-import/issues/2430)
28
+ // we manually define the most common extensions
29
+ 'import/resolver': {
30
+ node: {
31
+ extensions: ['.js', '.cjs', '.mjs', '.d.ts'],
32
+ },
33
+ },
23
34
  },
24
- plugins: ['jest', 'jsdoc', 'prettier'],
35
+ plugins: ['jsdoc', 'prettier'],
25
36
  rules: {
26
37
  'dot-notation': ['error'],
27
38
  'max-len': [
@@ -63,33 +74,20 @@ module.exports = {
63
74
  'quote-props': ['error', 'as-needed'],
64
75
  quotes: ['error', 'single', { avoidEscape: true }],
65
76
  // Node
66
- 'node/no-unsupported-features/es-syntax': [
67
- 'error',
68
- {
69
- version: `>=${nodeConfig.nodeVersion}`,
70
- },
71
- ],
72
- 'node/no-unsupported-features/node-builtins': [
77
+ 'n/no-unsupported-features/es-syntax': [
73
78
  'error',
74
79
  {
75
80
  version: `>=${nodeConfig.nodeVersion}`,
76
81
  },
77
82
  ],
78
- // Jest
79
- 'jest/expect-expect': ['error'],
80
- 'jest/no-test-prefixes': 0,
81
- 'jest/prefer-called-with': 0,
82
- 'jest/prefer-spy-on': ['error'],
83
- 'jest/prefer-todo': 0,
84
- 'jest/prefer-to-contain': ['error'],
85
- 'jest/prefer-to-have-length': ['error'],
86
- 'jest/valid-title': ['error'],
83
+ // Import
84
+ 'import/no-cycle': ['error'],
87
85
  // JSDoc
88
86
  'jsdoc/check-param-names': ['warn'],
89
87
  'jsdoc/check-types': ['warn'],
90
88
  'jsdoc/no-undefined-types': ['warn'],
91
89
  'jsdoc/check-alignment': ['warn'],
92
- 'jsdoc/check-examples': ['warn'],
90
+ 'jsdoc/check-examples': ['off'],
93
91
  'jsdoc/check-syntax': ['warn'],
94
92
  'jsdoc/check-tag-names': ['warn'],
95
93
  'jsdoc/require-jsdoc': ['warn'],
@@ -106,6 +104,56 @@ module.exports = {
106
104
  'prettier/prettier': 'error',
107
105
  },
108
106
  overrides: [
107
+ // Vitest
108
+ {
109
+ files: ['**/__tests__/**/*.js'],
110
+ env: {
111
+ 'vitest-globals/env': true,
112
+ },
113
+ globals: {
114
+ // Test name
115
+ testName: false,
116
+ // Shorter method names
117
+ fit: false,
118
+ fdescribe: false,
119
+ xit: false,
120
+ xdescribe: false,
121
+
122
+ captureOutput: false,
123
+ dedent: false,
124
+ },
125
+ extends: [
126
+ 'plugin:vitest/recommended',
127
+ 'plugin:vitest-globals/recommended',
128
+ ],
129
+ rules: {
130
+ 'no-restricted-globals': [
131
+ 'error',
132
+ {
133
+ name: 'fit',
134
+ message: 'No focused test',
135
+ },
136
+ {
137
+ name: 'fdescribe',
138
+ message: 'No focused tests',
139
+ },
140
+ {
141
+ name: 'xit',
142
+ message: 'No skipped test',
143
+ },
144
+ {
145
+ name: 'xdescribe',
146
+ message: 'No skipped tests',
147
+ },
148
+ ],
149
+ 'vitest/consistent-test-it': ['warn', { fn: 'it' }],
150
+ // Disabling vitest/no-identical-title
151
+ // It can make eslint crash when used with fit/xit/fdescribe/xdescribe
152
+ // See: https://github.com/veritem/eslint-plugin-vitest/issues/310
153
+ 'vitest/no-identical-title': ['off'],
154
+ 'vitest/prefer-to-contain': ['error'],
155
+ },
156
+ },
109
157
  // no-process-exit
110
158
  // We need to send clear exit codes in yarn run scripts
111
159
  {
@@ -18,8 +18,14 @@ if (pkg.scripts && pkg.scripts.lint) {
18
18
  result['*.json'] = ['yarn run lint:fix --json'];
19
19
  result['*.js'] = ['yarn run lint:fix --js'];
20
20
  }
21
+
22
+ // Compressing images
23
+ if (pkg.scripts && pkg.scripts.compress) {
24
+ result['*.png'] = ['yarn run compress --png'];
25
+ }
26
+
21
27
  // Testing changed js files
22
28
  if (pkg.scripts && pkg.scripts.test) {
23
- result['./lib/**/*.js'] = ['yarn run test --failFast --findRelatedTests'];
29
+ result['./lib/**/*.js'] = ['yarn run test --failFast --related'];
24
30
  }
25
31
  module.exports = result;
@@ -0,0 +1,5 @@
1
+ // Note: This file must still be in .cjs as it is require()d by eslintrc.cjs,
2
+ // which we also have to keep in cjs format
3
+ module.exports = {
4
+ nodeVersion: '18.18.0', // Also see templates/_circleci/config.yml
5
+ };
@@ -0,0 +1,4 @@
1
+ // We make captureOutput publicly available inside of tests
2
+ import captureOutput from 'firost/captureOutput.js';
3
+
4
+ globalThis.captureOutput = captureOutput;
@@ -0,0 +1,4 @@
1
+ // We make dedent publicly available inside of tests
2
+ import dedent from 'dedent';
3
+
4
+ globalThis.dedent = dedent;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Add faster to type aliases:
3
+ * - fit, ftest, fdescribe: To focus specific tests
4
+ * - xit, xtest, xdescribe: To skip specific tests
5
+ **/
6
+
7
+ globalThis.fit = globalThis.it.only;
8
+ globalThis.ftest = globalThis.test.only;
9
+ globalThis.fdescribe = globalThis.describe.only;
10
+
11
+ globalThis.xit = globalThis.it.skip;
12
+ globalThis.xtest = globalThis.test.skip;
13
+ globalThis.xdescribe = globalThis.describe.skip;
@@ -0,0 +1,10 @@
1
+ // We use extended matchers from jest-extended in vitest
2
+ // It includes matcher like .toStartWith, .toBeEmpty, etc
3
+ // See: https://github.com/jest-community/jest-extended
4
+ //
5
+ // The expect.extend() from Vitest is compatible with the one from Jest, so
6
+ // setup is straightforward
7
+ import { expect } from 'vitest';
8
+ import * as matchers from 'jest-extended';
9
+
10
+ expect.extend(matchers);
@@ -0,0 +1,9 @@
1
+ /* global beforeEach, expect */
2
+ /**
3
+ * Make the variable `testName` contain the name of the current test in each
4
+ * test
5
+ **/
6
+ beforeEach(() => {
7
+ const fullName = expect.getState().currentTestName;
8
+ globalThis.testName = fullName.split(' > ').pop();
9
+ });
@@ -0,0 +1,25 @@
1
+ import { configDefaults, defineConfig } from 'vitest/config';
2
+ const configDir = new URL('./vite/', import.meta.url).pathname;
3
+
4
+ export default defineConfig({
5
+ test: {
6
+ // Make describe, it, beforeEach and other globally available
7
+ globals: true,
8
+ // Tests should be in a __tests__ folder next to their code
9
+ include: ['**/__tests__/**/*.js?(x)'],
10
+ // We ignore temporary folders from the tests
11
+ exclude: [...configDefaults.exclude, '**/tmp/**'],
12
+ watchExclude: [...configDefaults.watchExclude, '**/tmp/**'],
13
+ // Restore mocks after each tests
14
+ restoreMocks: true,
15
+
16
+ // Run before each test file
17
+ setupFiles: [
18
+ `${configDir}/test/setupFiles/dedent.js`,
19
+ `${configDir}/test/setupFiles/captureOutput.js`,
20
+ `${configDir}/test/setupFiles/fit-xit-fdescribe-xdescribe.js`,
21
+ `${configDir}/test/setupFiles/jest-extended.js`,
22
+ `${configDir}/test/setupFiles/testName.js`,
23
+ ],
24
+ },
25
+ });
package/helper.js CHANGED
@@ -1,10 +1,12 @@
1
- const path = require('path');
2
- const _ = require('golgoth/_');
3
- const run = require('firost/run');
4
- const glob = require('firost/glob');
5
- const stripAnsi = require('strip-ansi');
6
- const findUp = require('find-up');
7
- module.exports = {
1
+ import path from 'path';
2
+ import _ from 'golgoth/lodash.js';
3
+ import run from 'firost/run.js';
4
+ import glob from 'firost/glob.js';
5
+ import exists from 'firost/exists.js';
6
+ import findUp from 'find-up';
7
+ import * as url from 'url';
8
+
9
+ export default {
8
10
  /**
9
11
  * Return absolute path to the host dir
10
12
  * @returns {string} Absolute path to host dir
@@ -25,7 +27,7 @@ module.exports = {
25
27
  * @returns {string} Absolute path to aberlaas dir
26
28
  **/
27
29
  aberlaasRoot() {
28
- return path.resolve(__dirname);
30
+ return url.fileURLToPath(new URL('.', import.meta.url));
29
31
  },
30
32
  /**
31
33
  * Return an absolute path to a file in the aberlaas directory
@@ -115,35 +117,39 @@ module.exports = {
115
117
 
116
118
  /**
117
119
  * Returns path to a specific binary.
118
- * Will use the local yarn version of the host if available, or the one
119
- * defined in aberlaas otherwise
120
+ *
121
+ * Knowing the path to a specific binary is not trivial:
122
+ * - Aberlaas dependencies should be in node_modules/aberlaas/.bin
123
+ * - Host dependencies should be in node_modules/.bin
124
+ *
125
+ * There are some special cases:
126
+ * - If both aberlaas and host use the same dependency version, it will be
127
+ * hoisted to the host
128
+ * - If they use different versions, priority should be given to the one in
129
+ * aberlaas
130
+ * - Mono-repo setup and yarn link will move dependencies out of
131
+ * node_modules/.bin
132
+ *
133
+ * For those reasons, we defer to running yarn bin to get the exact path to
134
+ * the binary, and check in order of importance in aberlaas first, and then in
135
+ * the host
136
+ *
120
137
  * @param {string} bin Binary name
121
138
  * @returns {string} Path to the binary
122
139
  **/
123
140
  async which(bin) {
124
- // Try to find the executable in the host
125
- const { stdout: hostPath } = await this.__run(`yarn bin ${bin}`, {
126
- stdout: false,
127
- stderr: false,
128
- });
129
- if (hostPath) {
130
- return stripAnsi(hostPath);
131
- }
141
+ const binaryPathSuffix = `./node_modules/.bin/${bin}`;
142
+ const pathsToTest = [
143
+ this.aberlaasPath(binaryPathSuffix),
144
+ this.hostPath(binaryPathSuffix),
145
+ ];
132
146
 
133
- // Try in Aberlaas
134
- const { stdout: aberlaasPath } = await this.__run(
135
- `cd ${this.aberlaasRoot()} && yarn bin ${bin}`,
136
- {
137
- shell: true,
138
- stdout: false,
139
- stderr: false,
147
+ for (const binaryPath of pathsToTest) {
148
+ if (await exists(binaryPath)) {
149
+ return binaryPath;
140
150
  }
141
- );
142
- if (aberlaasPath) {
143
- return stripAnsi(aberlaasPath);
144
151
  }
145
-
146
- return null;
152
+ return false;
147
153
  },
148
154
  /**
149
155
  * Run a specific script through yarn run
@@ -151,14 +157,19 @@ module.exports = {
151
157
  * @returns {object} Result of the run, including .sterr and .stdout
152
158
  **/
153
159
  async yarnRun(scriptName) {
154
- const currentDir = process.cwd();
155
- process.chdir(this.hostRoot());
160
+ return await run(`yarn run ${scriptName}`, { cwd: this.hostRoot() });
161
+ },
162
+ /**
163
+ * Dynamically import a file
164
+ * This is a wrapper around the default import, but bypasses the cache
165
+ * It makes sure importing a file several times always loads the last version
166
+ * TODO: This should probably be moved in firost once firost is moved to ESM
167
+ * @param {string} filepath Path to the file to load
168
+ * @returns {object} Content of the loaded file
169
+ **/
170
+ async import(filepath) {
171
+ const content = await import(`${filepath}?cacheBusting=${Date.now()}`);
156
172
 
157
- try {
158
- return await run(`yarn run ${scriptName}`);
159
- } finally {
160
- process.chdir(currentDir);
161
- }
173
+ return content.default || content;
162
174
  },
163
- __run: run,
164
175
  };
package/main.js CHANGED
@@ -1,27 +1,34 @@
1
- const minimist = require('minimist');
2
- const consoleError = require('firost/consoleError');
3
- const exit = require('firost/exit');
4
- const _ = require('golgoth/lodash');
1
+ import minimist from 'minimist';
2
+ import consoleError from 'firost/consoleError.js';
3
+ import exit from 'firost/exit.js';
4
+ import _ from 'golgoth/lodash.js';
5
+ import commandCi from './commands/ci/index.js';
6
+ import commandCompress from './commands/compress/index.js';
7
+ import commandInit from './commands/init/index.js';
8
+ import commandPrecommit from './commands/precommit/index.js';
9
+ import commandRelease from './commands/release/index.js';
10
+ import commandTest from './commands/test/index.js';
11
+ import commandLint from './commands/lint/index.js';
12
+ import commandReadme from './commands/readme/index.js';
13
+ import commandSetup from './commands/setup/index.js';
5
14
 
6
- module.exports = {
15
+ export default {
7
16
  /**
8
17
  * List of allowed commands to run
9
18
  * @returns {Array} List of allowed commands to run
10
19
  **/
11
- safelist() {
12
- return [
13
- 'build',
14
- 'ci',
15
- 'compress',
16
- 'init',
17
- 'lint',
18
- 'migrate',
19
- 'precommit',
20
- 'readme',
21
- 'release',
22
- 'setup',
23
- 'test',
24
- ];
20
+ allCommands() {
21
+ return {
22
+ ci: commandCi,
23
+ compress: commandCompress,
24
+ init: commandInit,
25
+ lint: commandLint,
26
+ precommit: commandPrecommit,
27
+ readme: commandReadme,
28
+ release: commandRelease,
29
+ setup: commandSetup,
30
+ test: commandTest,
31
+ };
25
32
  },
26
33
  /**
27
34
  * Run the command specified on the command-line, along with specific
@@ -34,7 +41,8 @@ module.exports = {
34
41
  });
35
42
 
36
43
  const commandName = args._[0];
37
- if (!_.includes(this.safelist(), commandName)) {
44
+ const command = this.allCommands()[commandName];
45
+ if (!command) {
38
46
  this.__consoleError(`Unknown command ${commandName}`);
39
47
  this.__exit(1);
40
48
  return;
@@ -44,7 +52,6 @@ module.exports = {
44
52
  args._ = _.drop(args._, 1);
45
53
 
46
54
  try {
47
- const command = this.__require(`./commands/${commandName}`);
48
55
  await command.run(args);
49
56
  } catch (err) {
50
57
  this.__consoleError(err.message);
@@ -53,5 +60,4 @@ module.exports = {
53
60
  },
54
61
  __consoleError: consoleError,
55
62
  __exit: exit,
56
- __require: require,
57
63
  };