UNPKG

@gohcltech/bitbucket-mcp

Version:

Bitbucket integration for Claude via Model Context Protocol

355 lines 13 kB
/** * @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