eslint-config-uphold
v6.12.0
Published
Uphold-flavored ESLint config
Readme
eslint-config-uphold
Uphold-flavored ESLint config.
The rules defined here extend the eslint-recommended preset, as well as the overrides that allow the Prettier pretty-printer to reformat the code without conflicts.
Status
Installation
npm install eslint eslint-config-uphold prettier --save-dev[!WARNING] Node.js minimum versions are
v23.0.0,v22.12.0andv20.19.0, as@stylistic/eslint-plugin-jsdepends on therequire('esm')module fromv4.0.0.
Usage
Create an eslint.config.mjs file with the following content:
import upholdConfig from 'eslint-config-uphold';
export default upholdConfig;If you'd like to extend the config, or change rules, you can do so like this:
import { defineConfig } from 'eslint/config';
import upholdConfig from 'eslint-config-uphold';
import yourPlugin from 'your-eslint-plugin';
export default defineConfig([
upholdConfig,
{
name: 'project-name/config',
plugins: {
'your-plugin': yourPlugin
},
rules: {
'your-plugin/rule-name': 'error'
}
}
]);See Using a Shareable Config for more information.
Add a lint command to the scripts section of your package.json, like so:
{
"scripts": {
"lint": "eslint"
}
}and run the linter with:
npm run lintTo automatically fix all lint issues, use the --fix option:
npm run lint --fixTypeScript
A TypeScript-specific config using typescript-eslint is available under eslint-config-uphold/configs/.
It can be used like this, on a eslint.config.mjs file:
import { defineConfig, globalIgnores } from 'eslint/config';
import { typescript as upholdTypescriptConfig } from 'eslint-config-uphold/configs';
import tseslint from 'typescript-eslint';
export default defineConfig([
{
extends: [upholdTypescriptConfig],
name: 'project-name/uphold-typescript',
rules: {
'jsdoc/no-types': 'warn'
}
},
globalIgnores(['coverage', 'dist'])
]);It's also possible to use the config without typescript-eslint. Minimal setup would look like the following:
import { typescript as upholdTypescriptConfig } from 'eslint-config-uphold/configs';
export default upholdTypescriptConfig;The TypeScript config assumes ESM by default.
If your project uses CJS, you can create a custom config using the createTypeScriptConfig factory.
This can also be used to specify a ecmaVersion other than the default 2022.
import { createTypeScriptConfig } from 'eslint-config-uphold/configs';
export default await createTypeScriptConfig('commonjs', { ecmaVersion: 2024 }); // 'module' for ESM, 'commonjs' for CJS.JavaScript
Likewise, a JavaScript-specific config is exported under eslint-config-uphold/configs/. The usage is similar to TypeScript's config:
import { defineConfig, globalIgnores } from 'eslint/config';
import { javascript as upholdJavascriptConfig } from 'eslint-config-uphold/configs';
export default defineConfig([upholdJavascriptConfig, globalIgnores(['coverage'])]);If not wanting to extend the config, it could even be used like the following:
import { javascript as upholdJavascriptConfig } from 'eslint-config-uphold/configs';
export default upholdJavascriptConfig;The JavaScript config assumes CJS by default.
If your project uses ESM, you can create a custom config using the createJavaScriptConfig factory.
This can also be used to specify a ecmaVersion other than the default 2022.
import { createJavaScriptConfig } from 'eslint-config-uphold/configs';
export default createJavaScriptConfig('module', { ecmaVersion: 2024 }); // 'module' for ESM, 'commonjs' for CJS.Custom rules
This config includes custom Uphold-specific rules, under uphold-plugin.
| Rule | Enabled in default config? | Fix? |
| --------------------------------------------------------------------------- | -------------------------- | ----- |
| database-migration-filename-format | False | False |
| explicit-sinon-use-fake-timers | True | False |
| no-trailing-period-in-log-messages | True | True |
| require-comment-punctuation | True | True |
database-migration-filename-format
Validates that migration file names are in the format YYYYMMDDHHMMSS-<name>, where name must match the regex [a-z0-9-]+, the date/time is UTC and is not in the future.
To enable the database-migration-filename-format rule, you can do so as following:
export default defineConfig([
...
{
files: ['**/database/migrations/*.js'] // glob to include/exclude the migration files to lint
name: 'project/migrations',
rules: {
'uphold-plugin/database-migration-filename-format': 'error'
}
},
...
]);explicit-sinon-use-fake-timers
Enforces explicit configuration when using Sinon's useFakeTimers() by requiring the toFake option to be specified. This ensures that only the intended timer functions are faked, reducing the risk of unintended side effects in tests.
Valid:
sinon.useFakeTimers({ toFake: ['setTimeout', 'clearTimeout'] });Invalid:
sinon.useFakeTimers(); // ❌ Missing 'toFake' option.no-trailing-period-in-log-messages
Disallows trailing periods in log messages, except for ... (ellipsis). This helps maintain consistency across log messages.
Valid:
console.log('Operation complete');
console.info('Processing...');
logger.error('An error occurred');Invalid:
console.log('Operation complete.'); // ❌ Remove the trailing period.
console.info('Processing..'); // ❌ Use three dots (...) or none.
logger.error('An error occurred.'); // ❌ Remove the trailing period.Options:
additionalMethods- You can configure additional methods to check:'uphold-plugin/no-trailing-period-in-log-messages': ['error', { additionalMethods: ['fatal', 'verbose', 'success'] }]
require-comment-punctuation
Requires // comment blocks to end with punctuation on the last line. Valid endings are ., :, ;, ?, !, or paired triple backticks (```). This helps maintain consistency in code comments.
Valid:
// This is a comment with a period.
// Is this a question?
// This is important!
// ``` let foo = 1 + 2 ```Invalid:
❌ Missing punctuation.
// This is a comment without punctuation // Comment with unmatched backticks ```
Options:
exclusionPrefixes- An array of strings. Comments starting with these prefixes (after//) are excluded from the rule:'uphold-plugin/require-comment-punctuation': ['error', { exclusionPrefixes: ['TODO:', 'FIXME:', 'NOTE:'] }]With this config, comments like
// TODO: implement thiswill not require punctuation.additionalAllowedEndings- An array of strings to extend the default allowed endings (.,:,;,?,!,```):'uphold-plugin/require-comment-punctuation': ['error', { additionalAllowedEndings: [')'] }]With this config, comments ending with
)will also be considered valid.
Test configs
This package includes individual exported configs for multiple test frameworks:
- Jest, depending on
eslint-plugin-jest. - Mocha, depending on
eslint-plugin-mocha. - Vitest, depending on
@vitest/eslint-pluginandtypescript.
To use them, import the config directly in your eslint.config.mjs file:
import { defineConfig } from 'eslint/config';
import { mocha as upholdMochaConfig } from 'eslint-config-uphold/configs';
import upholdConfig from 'eslint-config-uphold';
export default defineConfig([
upholdConfig,
{
extends: [upholdMochaConfig],
files: ['test/**/*.js'],
name: 'project-name/tests',
rules: {
'mocha/no-identical-title': 'off'
}
}
]);Those can be imported from eslint-config-uphold/configs:
import { jest, mocha, vitest } from 'eslint-config-uphold/configs';[!NOTE] Test configs use top-level
awaitfor dynamic module detection and are ESM-only. If your project uses CommonJS, youreslint.config.mjsstill supportsimport()and top-levelawait.
Upgrading ESLint
See the ESLint repo for ESLint's guidelines on semantic versioning.
A tilde range is set for the ESLint dependency to pick up any patch changes by default.
For any minor/major upgrades to ESLint it is recommended to update both eslint and eslint-config-uphold and keep them in parallel.
This is down to the fact that no guarantee is made that minor upgrades do not cause conflicts or issues with existing or new rules.
The downside here is a package update is required for any security or other bug fixes.
The benefit however is the included rules are always guaranteed to be stable.
Release process
The release of a version is automated via the release GitHub workflow. Run it by clicking the "Run workflow" button.
License
MIT
