Skip to content

Instantly share code, notes, and snippets.

@a-c-m
Last active December 13, 2023 15:05
Show Gist options
  • Save a-c-m/46cb3a672cee31f2a029993785ba3721 to your computer and use it in GitHub Desktop.
Save a-c-m/46cb3a672cee31f2a029993785ba3721 to your computer and use it in GitHub Desktop.

Revisions

  1. a-c-m revised this gist Dec 13, 2023. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions caret-or-tilde.js
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,6 @@
    /*
    Custom ESLint rule to disallow the use of '^' or '~' in dependencies' versions in package.json files.
    (--fix works and will remove the '^' or '~' characters from the package.json file!)
    eslint-plugin-package-json-dependencies/index.js
    module.exports = {
  2. a-c-m created this gist Dec 13, 2023.
    73 changes: 73 additions & 0 deletions caret-or-tilde.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,73 @@
    /*
    Custom ESLint rule to disallow the use of '^' or '~' in dependencies' versions in package.json files.
    eslint-plugin-package-json-dependencies/index.js
    module.exports = {
    rules: {
    'caret-or-tilde': require('./caret-or-tilde'),
    },
    };
    .estlint.rc.js
    {
    files: ['package.json'],
    parserOptions: {
    project: null, // unset parserOptions.project for this file
    },
    plugins: ['package-json-dependencies'],
    rules: {
    '@typescript-eslint/no-unused-expressions': 'off',
    '@typescript-eslint/no-unused-vars': 'off',
    '@typescript-eslint/no-var-requires': 'off',
    quotes: ['warn', 'double'],
    'object-curly-spacing': ['warn', 'always'],
    indent: ['warn', 2],
    'package-json-dependencies/caret-or-tilde': 'warn',
    },
    },
    */

    module.exports = {
    meta: {
    type: 'suggestion',
    docs: {
    description: "Disallow the use of '^' or '~' in dependencies' versions",
    category: 'Best Practices',
    recommended: true,
    },
    fixable: 'code',
    },

    create(context) {
    function reportError(node, message, fix) {
    context.report({
    node,
    message,
    fix,
    });
    }

    return {
    Property(node) {
    const allowedKeys = ['dependencies', 'devDependencies'];
    const parent = node.parent.parent.key?.value;

    if (parent && allowedKeys.includes(parent)) {
    const package = node.key.value;
    const version = node.value.value;

    if (version.startsWith('^') || version.startsWith('~')) {
    reportError(
    node,
    `Use exact versions instead of '^' or '~' for ${package} in ${parent}.`,
    (fixer) => {
    const fixedVersion = version.replace(/[\^~]/g, '');
    return fixer.replaceTextRange(node.value.range, JSON.stringify(fixedVersion));
    },
    );
    }
    }
    },
    };
    },
    };