@gohcltech/bitbucket-mcp
Version:
Bitbucket integration for Claude via Model Context Protocol
355 lines • 13 kB
JavaScript
/**
* @fileoverview Zod validation schemas for Bitbucket commit operations.
*
* This module provides comprehensive validation schemas for commit-related
* operations using Zod for runtime type checking and validation. These schemas
* ensure that data conforms to Bitbucket API v2.0 specifications and provide
* type-safe validation for MCP tool inputs and API responses.
*
* Key features:
* - Runtime validation of commit API responses
* - Commit diff and file change validation
* - Author attribution and repository context validation
* - Input parameter validation for commit analysis tools
* - Type-safe schema definitions matching TypeScript interfaces
* - Comprehensive error reporting for validation failures
*/
import { z } from 'zod';
import { RepositoryBaseSchema, ValidationPatterns } from '../common.js';
/**
* Zod schema for validating Bitbucket commit API responses.
*
* This schema validates the structure of commit objects returned by
* Bitbucket's REST API v2.0. It ensures proper validation of commit
* hashes, timestamps, author information, and related metadata.
*
* @example
* ```typescript
* const apiResponse = await fetch('/2.0/repositories/gohcl/bitbucket-mcp/commit/abc123');
* const rawData = await apiResponse.json();
* const commit = CommitSchema.parse(rawData);
* ```
*/
export const CommitSchema = z.object({
/**
* SHA-1 hash uniquely identifying the commit.
* Must be a 40-character hexadecimal string.
*/
hash: z.string().length(40, 'Commit hash must be 40 characters')
.regex(ValidationPatterns.commitHash, 'Invalid commit hash format'),
/**
* ISO 8601 timestamp when the commit was created.
* Must be a valid datetime string with timezone information.
*/
date: z.string().datetime('Invalid commit date format'),
/**
* Commit message describing the changes.
* Can contain multiple lines and formatting.
*/
message: z.string().min(1, 'Commit message cannot be empty')
.max(10000, 'Commit message too long'),
/**
* Author information for the commit.
* Contains both raw git data and optional Bitbucket user details.
*/
author: z.object({
/**
* Raw git author string from the commit.
* Typically in format "Name <email@domain.com>".
*/
raw: z.string().min(1, 'Author raw string is required'),
/**
* Optional Bitbucket user information for the author.
* Present if author email matches a registered user.
*/
user: z.object({
/** Display name of the author's Bitbucket account */
display_name: z.string().min(1, 'Author display name is required'),
/** Unique UUID identifier for the author */
uuid: z.string().min(1, 'Author UUID is required'),
/**
* Links related to the author's account.
*/
links: z.object({
/**
* Link to the author's avatar image.
*/
avatar: z.object({
/** URL to the author's profile picture */
href: z.string().url('Invalid author avatar link'),
}),
}),
}).optional(),
}),
/**
* Array of parent commits.
* Empty for initial commits, one parent for regular commits, multiple for merges.
*/
parents: z.array(z.object({
/**
* SHA-1 hash of the parent commit.
* Must be a valid 40-character commit hash.
*/
hash: z.string().length(40, 'Parent commit hash must be 40 characters')
.regex(ValidationPatterns.commitHash, 'Invalid parent commit hash format'),
/**
* Links related to the parent commit.
*/
links: z.object({
/**
* API endpoint for the parent commit.
*/
self: z.object({
/** Full URL to the parent commit's API endpoint */
href: z.string().url('Invalid parent commit link'),
}),
}),
})),
/**
* Repository information for this commit.
* Provides context about where the commit exists.
*/
repository: z.object({
/** Repository name within the workspace */
name: z.string().min(1, 'Repository name is required'),
/** Full repository name including workspace prefix */
full_name: z.string().min(1, 'Repository full name is required')
.regex(/^[a-zA-Z0-9_-]+\/[a-zA-Z0-9_.-]+$/, 'Invalid full repository name format'),
/** Unique UUID identifier for the repository */
uuid: z.string().min(1, 'Repository UUID is required'),
}),
/**
* Collection of related URLs and endpoints for the commit.
* Provides access to different views and formats of commit data.
*/
links: z.object({
/**
* API endpoint for this commit.
*/
self: z.object({
/** Full URL to this commit's API endpoint */
href: z.string().url('Invalid commit self link'),
}),
/**
* Web interface link to the commit page.
*/
html: z.object({
/** Full URL to the commit page in Bitbucket */
href: z.string().url('Invalid commit HTML link'),
}),
/**
* API endpoint for the commit's diff.
*/
diff: z.object({
/** Full URL to the commit's diff API endpoint */
href: z.string().url('Invalid commit diff link'),
}),
/**
* API endpoint for the commit's patch.
*/
patch: z.object({
/** Full URL to the commit's patch API endpoint */
href: z.string().url('Invalid commit patch link'),
}),
}),
/**
* Optional formatted summary of the commit message.
* Contains the message in various display formats.
*/
summary: z.object({
/** Raw commit message as entered */
raw: z.string(),
/** Commit message with markup processing */
markup: z.string(),
/** Commit message rendered as HTML */
html: z.string(),
/** Type of markup used in the message */
type: z.string(),
}).optional(),
});
/**
* Zod schema for validating commit diff API responses.
*
* This schema validates the structure of commit diff objects that show
* file changes in a commit. It includes validation for different types
* of file operations and optional diff content.
*
* @example
* ```typescript
* const apiResponse = await fetch('/2.0/repositories/gohcl/bitbucket-mcp/diff/abc123');
* const rawData = await apiResponse.json();
* const commitDiff = CommitDiffSchema.parse(rawData);
* ```
*/
export const CommitDiffSchema = z.object({
/**
* Array of file changes in the commit.
* Each entry represents a single file modification.
*/
values: z.array(z.object({
/**
* Type of change made to the file.
* Must be one of the predefined change types.
*/
type: z.enum(['add', 'modify', 'delete', 'rename'], {
errorMap: () => ({ message: 'Invalid file change type' })
}),
/**
* Information about the file before the change.
* Required for modify, delete, and rename operations.
*/
old: z.object({
/**
* File path before the change.
* Must be a valid relative path from repository root.
*/
path: z.string().min(1, 'File path is required')
.max(4096, 'File path too long'),
/**
* Type of filesystem object.
*/
type: z.enum(['commit_file', 'commit_directory'], {
errorMap: () => ({ message: 'Invalid file type' })
}),
/**
* Links related to the old file version.
*/
links: z.object({
/**
* API endpoint for the old file content.
*/
self: z.object({
/** Full URL to access the old file content */
href: z.string().url('Invalid old file link'),
}),
}),
}).optional(),
/**
* Information about the file after the change.
* Required for add, modify, and rename operations.
*/
new: z.object({
/**
* File path after the change.
* Must be a valid relative path from repository root.
*/
path: z.string().min(1, 'File path is required')
.max(4096, 'File path too long'),
/**
* Type of filesystem object.
*/
type: z.enum(['commit_file', 'commit_directory'], {
errorMap: () => ({ message: 'Invalid file type' })
}),
/**
* Links related to the new file version.
*/
links: z.object({
/**
* API endpoint for the new file content.
*/
self: z.object({
/** Full URL to access the new file content */
href: z.string().url('Invalid new file link'),
}),
}),
}).optional(),
/**
* Optional unified diff content.
* Contains the actual line-by-line changes for text files.
*/
diff: z.string().max(1000000, 'Diff content too large').optional(),
})),
/**
* Current page number in paginated results.
* Used for navigation through large commit diffs.
*/
page: z.number().int().min(1, 'Page number must be positive').optional(),
/**
* Number of items per page in paginated results.
* Controls how many file changes are returned per page.
*/
pagelen: z.number().int().min(1, 'Page length must be positive').optional(),
/**
* Total number of file changes across all pages.
* Useful for calculating pagination and progress.
*/
size: z.number().int().min(0, 'Size cannot be negative').optional(),
/**
* URL for the next page of results.
* Present when additional pages are available.
*/
next: z.string().url('Invalid next page URL').optional(),
});
/**
* Input validation schema for commit-related MCP tool parameters.
*
* This schema validates the basic parameters required by commit tools,
* extending the repository base schema with commit-specific validation.
* Used by tools that operate on specific commits.
*
* @example
* ```typescript
* const input = {
* workspace: 'gohcl',
* repo_slug: 'bitbucket-mcp',
* commit_hash: 'a1b2c3d4e5f6789012345678901234567890abcd'
* };
* const validatedInput = CommitInputSchema.parse(input);
* ```
*/
export const CommitInputSchema = RepositoryBaseSchema.extend({
/**
* SHA-1 hash of the target commit.
* Must be a valid 40-character hexadecimal commit hash.
*/
commit_hash: z.string().length(40, 'Commit hash must be 40 characters')
.regex(ValidationPatterns.commitHash, 'Invalid commit hash format'),
});
/**
* Input validation schema for the list_commits MCP tool.
*
* This schema validates parameters for listing commits with optional
* filtering by branch, inclusion, and exclusion criteria. Supports
* complex commit history queries and filtering.
*
* @example
* ```typescript
* const input = {
* workspace: 'gohcl',
* repo_slug: 'bitbucket-mcp',
* branch: 'develop',
* include: 'feature/auth',
* exclude: 'master'
* };
* const validatedInput = ListCommitsInputSchema.parse(input);
* ```
*/
export const ListCommitsInputSchema = RepositoryBaseSchema.extend({
/**
* Optional branch name to filter commits.
* When specified, only returns commits reachable from this branch.
* Must be a valid git branch name if provided.
*/
branch: z.string().min(1, 'Branch name cannot be empty')
.max(100, 'Branch name too long')
.regex(/^[a-zA-Z0-9][a-zA-Z0-9._/-]*[a-zA-Z0-9]$|^[a-zA-Z0-9]$/, 'Invalid branch name format')
.optional(),
/**
* Optional commit or branch to include in the result set.
* Only commits reachable from this reference will be included.
* Can be a commit hash or branch name.
*/
include: z.string().min(1, 'Include reference cannot be empty')
.max(100, 'Include reference too long')
.optional(),
/**
* Optional commit or branch to exclude from the result set.
* Commits reachable from this reference will be excluded.
* Can be a commit hash or branch name.
*/
exclude: z.string().min(1, 'Exclude reference cannot be empty')
.max(100, 'Exclude reference too long')
.optional(),
});
//# sourceMappingURL=schemas.js.map