Shared TypeScript type definitions for the commitlint ecosystem.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
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.
type RuleField =
| "header"
| "type"
| "scope"
| "subject"
| "body"
| "footer";Core commit message components that can be prompted:
type PromptName =
| RuleField
| "isBreaking"
| "breakingBody"
| "breaking"
| "isIssueAffected"
| "issuesBody"
| "issues";Extended set of prompt fields including breaking change and issue handling:
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:
interface PromptSettings {
scopeEnumSeparator: string;
enableMultipleScopes: boolean;
}Global settings for prompt behavior:
interface PromptMessages {
skip: string;
max: string;
min: string;
emptyWarning: string;
upperLimitWarning: string;
lowerLimitWarning: string;
[_key: string]: string;
}Localized messages used throughout the prompt interface:
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:
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"
}
}
}
};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"
}
}
}
};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"
}
}
}
};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"
}
}
}
};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");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;
}