question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Allow per-type scope-enum

See original GitHub issue

Expected Behavior

I’d like to limit the valid scopes on a per-type basis. For example, the docs type should accept all and each of my lerna packages as scopes, but the build type should perhaps accept only npm, webpack, babel.

Current Behavior

I can specify valid types and valid scopes, but not tuples of which ones are valid together.

Affected packages

  • cli
  • core
  • prompt
  • config-angular

Possible Solution

Allow one (or both) of scopes-enum and types-enum to accept an object instead of an array. Alternatively, introduce a new rule that accepts an object.

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:7
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

4reactions
njlawcommented, Jul 24, 2021

I ran into the need for per-type scopes myself and after digging around a bit ended up implementing it as a local plugin. If there’s interest, I can clean up the code and publish it on npmjs. In the meantime, here’s my ugly working commitlint.config.js in case its helpful to anyone:

module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'scope-enums': [
      2, 'always', {
        feat: [/^frontend\/[^\/]+$/, 'backend'],
        perf: [],
        ci: [null, 'codebuild', 'jenkins']
      }
    ]
  },
  plugins: [
    {
      rules: {
        /**
         * - If a type does not appear in the rule, do not enforce scope
         * - If a type appears in the rule with an empty array,
         *   do not allow scope
         * - If a type appears in the rule with an non-empty array,
         *   only allow the values in the array for scope.
         * - If the array includes null, the scope is optional.
         *
         * E.g., {
         *   'allowed-scopes': [2, "always", {
         *     feat: [/^frontend\/[^\/]+$/, 'backend'],
         *     perf: [],
         *     ci: [null, 'codebuild', 'jenkins']
         *   }]
         * }
         *
         * In the above rules configuration,
         *  - if the type is 'feat', the scope must be either
         *    match the regex /frontend\/[^\/]+/ or be 'backend'
         *  - if the type if 'chore', the scope is optional and can
         *    be anything
         *  - if the type is 'perf', a scope is not allowed
         *  - if the type is 'ci', the scope must be 'codebuild' or
         *    'jenkins' if present, but is not required
         */
        'scope-enums': (ctx, applicable, rule) => {
          if (applicable === 'never') {
            return [false, 'the "allowed-scopes" rule does not support "never"'];
          }

          const allowedScopes = rule[ctx.type];

          // If the type does not appear in the rule config, allow any scope or no scope
          if (allowedScopes === undefined) {
            return [true];
          }

          if (Array.isArray(allowedScopes)) {
            // If the type maps to an empty array in the rule config, scope it not allowed
            if (allowedScopes.length === 0) {
              if (ctx.scope != null) {
                return [false, `commit messages with type "${ctx.type}" must not specify a scope`];
              }

              return [true];
            }

            // Otherwise attempt to match against either null, a string literal, or a RegExp
            if (
              allowedScopes.findIndex((s) => {
                if (
                  typeof ctx.scope === 'string' &&
                  Object.prototype.toString.call() === '[object RegExp]'
                ) {
                  return ctx.scope.match(s);
                }

                // Equality comparison works for both strings and null
                return s === ctx.scope;
              }) !== -1
            ) {
              return [true];
            } else if (allowedScopes.includes(null)) {
              return [
                false,
                `commit message with type "${
                  ctx.type
                }" may specify a scope, but if specified, it must be one of the following: ${allowedScopes
                  .filter((s) => s !== null)
                  .map((s) => `"${s}"`)
                  .join(', ')}`,
              ];
            } else {
              return [
                false,
                `commit message with type "${
                  ctx.type
                }" must specify one of the following scopes: ${allowedScopes
                  .map((s) => `"${s}"`)
                  .join(', ')}`,
              ];
            }
          }

          return [false, `invalid rule entry: { ${ctx.type}: ${JSON.stringify(allowedScopes)} }`];
        },
      },
    },
  ],
};
2reactions
ridvanaltuncommented, Sep 30, 2021

Thank you @njlaw

I converted it to an actual plugin, here: commitlint-plugin-selective-scope

Read more comments on GitHub >

github_iconTop Results From Across the Web

Spring scope references as enums? [duplicate] - Stack Overflow
PROTOTYPE, Scope. SINGLETON static references? Or do I always have to use non-typesafe strings as scopes?
Read more >
Access control for enum cases - Pitches - Swift Forums
Today, Swift doesn't allow access control modifiers on enum cases, unlike properties, methods and other kinds of declarations.
Read more >
Singleton and Prototype Bean Scopes in Java Spring
By default scope is not prototype so you have to declare the scope of a been as prototype explicitly. Singleton scope should be...
Read more >
Scope - cppreference.com
block scope; file scope; function scope; function prototype scope ... the scopes are nested (no other form of scope overlap is allowed), and...
Read more >
Scope - cppreference.com
Contents · [edit] Block scope · [edit] Function prototype scope · [edit] Function scope · [edit] Namespace scope · [edit] Class scope ·...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found