CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-commitlint--types

Shared TypeScript type definitions for the commitlint ecosystem.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

prompts.mddocs/

Interactive Prompts

The interactive prompts system provides types for creating guided commit message creation interfaces. This enables building interactive CLI tools that help users write valid commit messages through step-by-step prompts.

Field Types

Rule Fields

type RuleField =
  | "header"
  | "type"
  | "scope"
  | "subject"
  | "body"
  | "footer";

Core commit message components that can be prompted:

  • header: Complete first line (type + scope + subject)
  • type: Commit type (feat, fix, docs, etc.)
  • scope: Optional scope in parentheses
  • subject: Brief description of changes
  • body: Optional detailed description
  • footer: Optional footer with breaking changes, issues, etc.

Extended Prompt Names

type PromptName =
  | RuleField
  | "isBreaking"
  | "breakingBody"
  | "breaking"
  | "isIssueAffected"
  | "issuesBody"
  | "issues";

Extended set of prompt fields including breaking change and issue handling:

  • isBreaking: Boolean prompt for breaking changes
  • breakingBody: Description of breaking changes
  • breaking: Combined breaking change information
  • isIssueAffected: Boolean prompt for issue references
  • issuesBody: Description of affected issues
  • issues: Combined issue reference information

Prompt Configuration

Prompt Config Structure

interface PromptConfig {
  settings: {
    scopeEnumSeparator: string;
    enableMultipleScopes: boolean;
  };
  messages: PromptMessages;
  questions: Partial<
    Record<
      PromptName,
      {
        description?: string;
        messages?: { [K: string]: string };
        enum?: {
          [enumName: string]: {
            description?: string;
            title?: string;
            emoji?: string;
          };
        };
      }
    >
  >;
}

Complete prompt configuration structure:

  • settings: Global prompt behavior settings
  • messages: Localized text messages for prompts
  • questions: Configuration for each prompt field

Prompt Settings

interface PromptSettings {
  scopeEnumSeparator: string;
  enableMultipleScopes: boolean;
}

Global settings for prompt behavior:

  • scopeEnumSeparator: Character used to separate multiple scopes
  • enableMultipleScopes: Whether to allow selecting multiple scopes

Prompt Messages

interface PromptMessages {
  skip: string;
  max: string;
  min: string;
  emptyWarning: string;
  upperLimitWarning: string;
  lowerLimitWarning: string;
  [_key: string]: string;
}

Localized messages used throughout the prompt interface:

  • skip: Text for skipping optional fields
  • max: Message for maximum length warnings
  • min: Message for minimum length warnings
  • emptyWarning: Warning when required field is empty
  • upperLimitWarning: Warning when input exceeds maximum
  • lowerLimitWarning: Warning when input is below minimum
  • [_key: string]: Extensible for custom messages

User Prompt Configuration

type UserPromptConfig = DeepPartial<PromptConfig>;

type DeepPartial<T> = {
  [P in keyof T]?: {
    [K in keyof T[P]]?: T[P][K];
  };
};

User-provided partial configuration that overrides defaults:

  • UserPromptConfig: Deep partial of PromptConfig for user customization
  • DeepPartial: Utility type making all nested properties optional

Usage Examples

Basic Prompt Configuration

import { PromptConfig, PromptMessages } from "@commitlint/types";

const messages: PromptMessages = {
  skip: "Skip this field",
  max: "Maximum {0} characters",
  min: "Minimum {0} characters", 
  emptyWarning: "This field cannot be empty",
  upperLimitWarning: "Input too long",
  lowerLimitWarning: "Input too short"
};

const basicPromptConfig: PromptConfig = {
  settings: {
    scopeEnumSeparator: ",",
    enableMultipleScopes: true
  },
  messages,
  questions: {
    type: {
      description: "Select the type of change you're committing:",
      enum: {
        feat: {
          description: "A new feature",
          title: "Features",
          emoji: "✨"
        },
        fix: {
          description: "A bug fix", 
          title: "Bug Fixes",
          emoji: "🐛"
        },
        docs: {
          description: "Documentation only changes",
          title: "Documentation",
          emoji: "📚"
        }
      }
    },
    scope: {
      description: "What is the scope of this change (e.g. component, filename):",
      messages: {
        empty: "Scope can be empty"
      }
    },
    subject: {
      description: "Write a short, imperative tense description of the change:",
      messages: {
        empty: "Subject is required",
        maxLength: "Subject must be no more than 50 characters"
      }
    }
  }
};

User Customization

import { UserPromptConfig } from "@commitlint/types";

// Partial configuration that extends defaults
const userConfig: UserPromptConfig = {
  settings: {
    enableMultipleScopes: false // Override default
  },
  messages: {
    skip: "Press Enter to skip", // Custom message
    emptyWarning: "⚠️  This field is required"
  },
  questions: {
    type: {
      description: "Choose commit type:",
      enum: {
        feat: { title: "Feature", emoji: "🚀" },
        fix: { title: "Bug Fix", emoji: "🔧" },
        chore: { title: "Chore", emoji: "🧹" }
      }
    },
    breaking: {
      description: "Describe the breaking changes:",
      messages: {
        skip: "No breaking changes"
      }
    }
  }
};

Advanced Prompt Configuration

import { PromptConfig, PromptName } from "@commitlint/types";

const advancedConfig: PromptConfig = {
  settings: {
    scopeEnumSeparator: "|",
    enableMultipleScopes: true
  },
  messages: {
    skip: "Leave empty to skip",
    max: "Maximum {0} chars allowed",
    min: "At least {0} chars required",
    emptyWarning: "❌ Required field",
    upperLimitWarning: "📏 Too long!",
    lowerLimitWarning: "📏 Too short!"
  },
  questions: {
    type: {
      description: "🏷️  Select commit type:",
      enum: {
        feat: { description: "New feature", title: "✨ Feature", emoji: "✨" },
        fix: { description: "Bug fix", title: "🐛 Fix", emoji: "🐛" },
        docs: { description: "Documentation", title: "📝 Docs", emoji: "📝" },
        style: { description: "Code style", title: "💄 Style", emoji: "💄" },
        refactor: { description: "Code refactor", title: "♻️ Refactor", emoji: "♻️" },
        test: { description: "Tests", title: "🧪 Test", emoji: "🧪" },
        chore: { description: "Maintenance", title: "🔧 Chore", emoji: "🔧" }
      }
    },
    scope: {
      description: "📦 Scope (component/module affected):",
      messages: {
        empty: "Scope helps identify what changed",
        invalidFormat: "Use lowercase, no spaces"
      }
    },
    subject: {
      description: "📋 Brief description (imperative mood):",
      messages: {
        empty: "Subject describes what the commit does",
        maxLength: "Keep it under 50 characters",
        invalidFormat: "Start with lowercase verb"
      }
    },
    body: {
      description: "📖 Detailed description (optional):",
      messages: {
        skip: "Leave empty if subject is sufficient"
      }
    },
    isBreaking: {
      description: "💥 Are there breaking changes?",
      messages: {
        confirmation: "This will increment major version"
      }
    },
    breakingBody: {
      description: "💥 Describe the breaking changes:",
      messages: {
        empty: "Explain what breaks and how to migrate"
      }
    },
    isIssueAffected: {
      description: "🐛 Does this close any issues?",
      messages: {
        help: "Reference issues with fixes #123"
      }
    },
    issuesBody: {
      description: "🐛 List the issues (e.g., fixes #123, closes #456):",
      messages: {
        empty: "Use format: fixes #123, closes #456",
        invalidFormat: "Use keywords: fixes, closes, resolves"
      }
    }
  }
};

Internationalization

import { PromptMessages, UserPromptConfig } from "@commitlint/types";

// Spanish messages
const spanishMessages: PromptMessages = {
  skip: "Presiona Enter para omitir",
  max: "Máximo {0} caracteres",
  min: "Mínimo {0} caracteres",
  emptyWarning: "Este campo no puede estar vacío",
  upperLimitWarning: "Entrada demasiado larga",
  lowerLimitWarning: "Entrada demasiado corta"
};

const spanishConfig: UserPromptConfig = {
  messages: spanishMessages,
  questions: {
    type: {
      description: "Selecciona el tipo de cambio:",
      enum: {
        feat: { description: "Nueva funcionalidad", title: "Funcionalidad" },
        fix: { description: "Corrección de error", title: "Corrección" },
        docs: { description: "Solo documentación", title: "Documentación" }
      }
    },
    subject: {
      description: "Escribe una descripción breve en modo imperativo:",
      messages: {
        empty: "El asunto es requerido",
        maxLength: "El asunto no debe exceder 50 caracteres"
      }
    }
  }
};

Dynamic Prompt Configuration

import { PromptConfig, UserPromptConfig } from "@commitlint/types";

// Function to generate configuration based on project type
function createPromptConfig(projectType: "library" | "application" | "monorepo"): UserPromptConfig {
  const baseConfig: UserPromptConfig = {
    settings: {
      scopeEnumSeparator: ",",
      enableMultipleScopes: projectType === "monorepo"
    },
    questions: {
      type: {
        description: "Select commit type:",
        enum: {
          feat: { title: "Feature", emoji: "✨" },
          fix: { title: "Bug Fix", emoji: "🐛" },
          docs: { title: "Documentation", emoji: "📝" }
        }
      }
    }
  };
  
  // Add project-specific customizations
  switch (projectType) {
    case "library":
      baseConfig.questions!.type!.enum!.perf = {
        title: "Performance",
        emoji: "⚡",
        description: "Performance improvement"
      };
      break;
      
    case "application":
      baseConfig.questions!.type!.enum!.deploy = {
        title: "Deployment",
        emoji: "🚀",
        description: "Deployment related changes"
      };
      break;
      
    case "monorepo":
      baseConfig.questions!.scope = {
        description: "Which package/workspace is affected:",
        messages: {
          empty: "Scope is required for monorepo"
        }
      };
      break;
  }
  
  return baseConfig;
}

// Usage
const libraryPrompts = createPromptConfig("library");
const appPrompts = createPromptConfig("application");
const monorepoPrompts = createPromptConfig("monorepo");

Prompt Validation Integration

import { PromptConfig, RulesConfig } from "@commitlint/types";

// Generate prompt config from commitlint rules
function generatePromptsFromRules(rules: Partial<RulesConfig>): UserPromptConfig {
  const config: UserPromptConfig = {
    questions: {}
  };
  
  // Extract type enum from rules
  const typeEnumRule = rules["type-enum"];
  if (typeEnumRule && typeEnumRule[2]) {
    const types = typeEnumRule[2] as string[];
    config.questions!.type = {
      description: "Select commit type:",
      enum: types.reduce((acc, type) => {
        acc[type] = { title: type.charAt(0).toUpperCase() + type.slice(1) };
        return acc;
      }, {} as Record<string, { title: string }>)
    };
  }
  
  // Extract subject max length
  const subjectMaxRule = rules["subject-max-length"];
  if (subjectMaxRule && subjectMaxRule[2]) {
    const maxLength = subjectMaxRule[2] as number;
    config.questions!.subject = {
      description: `Brief description (max ${maxLength} chars):`,
      messages: {
        maxLength: `Subject must be no more than ${maxLength} characters`
      }
    };
  }
  
  return config;
}

docs

case-validation.md

configuration.md

formatting.md

index.md

linting.md

parsing.md

plugins.md

prompts.md

rules-config.md

tile.json