@gohcltech/bitbucket-mcp
Version:
Bitbucket integration for Claude via Model Context Protocol
239 lines • 9.57 kB
JavaScript
/**
* @fileoverview Common types and schemas shared across all domain modules.
*
* This module contains:
* - Error classes for different failure scenarios
* - Pagination interfaces used by all API responses
* - Configuration schemas for server and OAuth settings
* - Utility functions for validation and sanitization
* - Common validation patterns used across domains
*
*/
import { z } from 'zod';
// =============================================================================
// ERROR CLASSES
// =============================================================================
/**
* Error thrown when input validation fails.
* Contains detailed information about validation failures for debugging.
*/
export class ValidationError extends Error {
details;
constructor(message, details) {
super(message);
this.details = details;
this.name = 'ValidationError';
}
}
/**
* Error thrown when authentication fails or tokens are invalid.
* Indicates that the user needs to re-authenticate or refresh tokens.
*/
export class AuthenticationError extends Error {
constructor(message) {
super(message);
this.name = 'AuthenticationError';
}
}
/**
* Error thrown when API rate limits are exceeded.
* Includes retry-after information when available from the API.
*/
export class RateLimitError extends Error {
retryAfter;
constructor(message, retryAfter) {
super(message);
this.retryAfter = retryAfter;
this.name = 'RateLimitError';
}
}
/**
* Error thrown when Bitbucket API requests fail.
* Contains HTTP status code and response data for debugging.
*/
export class BitbucketApiError extends Error {
statusCode;
response;
constructor(message, statusCode, response) {
super(message);
this.statusCode = statusCode;
this.response = response;
this.name = 'BitbucketApiError';
}
}
// =============================================================================
// CONFIGURATION SCHEMAS
// =============================================================================
/**
* Schema for logging configuration parameters.
* Defines options for multiple output destinations and logging behavior.
*/
export const LoggingConfigSchema = z.object({
/** Enable real-time web log viewer */
enableLogViewer: z.boolean().default(true),
/** Enable console logging output */
enableConsoleLogging: z.boolean().default(true),
/** Enable file logging output */
enableFileLogging: z.boolean().default(false),
/** Path for log file when file logging is enabled */
logFilePath: z.string().default('./logs/bitbucket-mcp.log'),
/** Maximum number of log entries to keep in memory for web viewer */
logViewerMaxEntries: z.number().int().min(10).default(1000),
/** Enable structured logging with additional metadata */
enableStructuredLogging: z.boolean().default(true),
});
/**
* Schema for server configuration parameters.
* Defines valid ranges and defaults for server operation settings.
*/
export const ServerConfigSchema = z.object({
/** Application version (loaded dynamically from package.json) */
version: z.string().default('unknown'),
/** Server port number (1-65535) */
port: z.number().int().min(1).max(65535).default(3000),
/** Logging level for server operations */
logLevel: z.enum(['error', 'warn', 'info', 'debug']).default('info'),
/** Logging configuration for multiple output destinations */
logging: LoggingConfigSchema.default({}),
/** Rate limiting configuration to respect API quotas using token bucket algorithm */
rateLimit: z.object({
/** Maximum concurrent requests to prevent overwhelming the API */
maxConcurrent: z.number().int().min(1).default(10),
/** Minimum time between requests in milliseconds to throttle request rate */
minTime: z.number().int().min(0).default(100),
/** Request reservoir size - initial number of tokens available for burst requests */
reservoir: z.number().int().min(1).default(100),
/** Amount to refill reservoir - tokens added during each refresh interval */
reservoirRefreshAmount: z.number().int().min(1).default(100),
/** Reservoir refresh interval in milliseconds - how often tokens are replenished */
reservoirRefreshInterval: z.number().int().min(1000).default(60000),
}).default({}),
/** Optional encrypted token storage configuration */
tokenStorage: z.object({
/** Encryption key (minimum 32 characters for security) */
encryptionKey: z.string().min(32, 'Encryption key must be at least 32 characters'),
/** File path for encrypted token storage */
filePath: z.string().default('./tokens.enc'),
}).optional(),
/** Pull request configuration options */
pullRequest: z.object({
/** Automatically close source branch when PR is merged (default: true) */
autoCloseBranchOnMerge: z.boolean().default(true),
}).default({}),
});
// =============================================================================
// TOKEN SCHEMAS
// =============================================================================
/**
* Schema for OAuth token data persistence.
* Defines the structure for storing authentication tokens securely.
*/
export const TokenDataSchema = z.object({
/** OAuth 2.0 access token */
accessToken: z.string(),
/** Optional refresh token for automatic renewal */
refreshToken: z.string().optional(),
/** Token expiration timestamp (milliseconds since epoch) */
expiresAt: z.number().optional(),
/** Token type (typically 'Bearer') */
tokenType: z.string().default('Bearer'),
});
// =============================================================================
// OAUTH CONFIGURATION SCHEMAS
// =============================================================================
// NOTE: OAuth configuration schemas have been removed as part of v2.0
// architecture simplification. Old schemas that were removed:
// - BitbucketOAuthConfigSchema
// - EnhancedBitbucketOAuthConfigSchema
//
// These have been replaced with token-based authentication in src/types.ts:
// - AuthMethod enum
// - ApiTokenAuth schema
// - RepositoryTokenAuth schema
// - AuthConfig discriminated union
//
// See src/types.ts for new authentication types.
// =============================================================================
// COMMON VALIDATION PATTERNS
// =============================================================================
/**
* Common regex patterns for validating Bitbucket identifiers.
*/
export const ValidationPatterns = {
/** Workspace slug validation (alphanumeric, hyphens, underscores) */
workspace: /^[a-zA-Z0-9_-]+$/,
/** Repository slug validation (alphanumeric, hyphens, underscores, dots) */
repository: /^[a-zA-Z0-9_.-]+$/,
/** Commit hash validation (40 character hexadecimal) */
commitHash: /^[a-f0-9]{40}$/,
/** Branch name validation (general git branch naming rules) */
branchName: /^[a-zA-Z0-9][a-zA-Z0-9._/-]*[a-zA-Z0-9]$|^[a-zA-Z0-9]$/,
};
/**
* Base schema for workspace-related operations.
*/
export const WorkspaceBaseSchema = z.object({
workspace: z.string()
.min(1, 'Workspace is required')
.regex(ValidationPatterns.workspace, 'Invalid workspace format'),
});
/**
* Base schema for repository-related operations.
*/
export const RepositoryBaseSchema = WorkspaceBaseSchema.extend({
repo_slug: z.string()
.min(1, 'Repository slug is required')
.regex(ValidationPatterns.repository, 'Invalid repository slug format'),
});
// =============================================================================
// UTILITY FUNCTIONS
// =============================================================================
/**
* Validates input against a Zod schema and throws detailed error on failure.
*
* @template T - The expected type after validation
* @param schema - Zod schema to validate against
* @param input - Input data to validate
* @returns Validated and typed data
* @throws {ValidationError} If validation fails with detailed error information
*/
export function validateInput(schema, input) {
try {
return schema.parse(input);
}
catch (error) {
if (error instanceof z.ZodError) {
const errorMessage = error.errors.map(err => `${err.path.join('.')}: ${err.message}`).join(', ');
throw new ValidationError(`Validation failed: ${errorMessage}`, error.errors);
}
throw error;
}
}
/**
* Sanitizes string input to prevent injection attacks and limit length.
*
* @param input - String to sanitize
* @returns Sanitized string safe for processing
*/
export function sanitizeString(input) {
return input
.replace(/[<>"'&]/g, '') // Remove HTML/script injection characters
.trim()
.substring(0, 1000); // Limit length
}
// =============================================================================
// TYPE GUARD FUNCTIONS
// =============================================================================
/**
* Type guard to check if input matches workspace input schema.
*/
export function isWorkspaceInput(input) {
return WorkspaceBaseSchema.safeParse(input).success;
}
/**
* Type guard to check if input matches repository input schema.
*/
export function isRepositoryInput(input) {
return RepositoryBaseSchema.safeParse(input).success;
}
//# sourceMappingURL=common.js.map