repomix
Version:
A tool to pack repository contents to single file for AI consumption
116 lines (115 loc) • 4.2 kB
JavaScript
import { inspect } from 'node:util';
import { REPOMIX_DISCORD_URL, REPOMIX_ISSUES_URL } from './constants.js';
import { logger, repomixLogLevels } from './logger.js';
export class RepomixError extends Error {
constructor(message, options) {
super(message, options);
this.name = 'RepomixError';
}
}
export class RepomixConfigValidationError extends RepomixError {
constructor(message, options) {
super(message, options);
this.name = 'RepomixConfigValidationError';
}
}
export class OperationCancelledError extends RepomixError {
constructor(message = 'Operation cancelled') {
super(message);
this.name = 'OperationCancelledError';
}
}
export const handleError = (error) => {
logger.log('');
if (isRepomixError(error)) {
logger.error(`✖ ${error.message}`);
if (logger.getLogLevel() < repomixLogLevels.DEBUG) {
logger.log('');
logger.note('For detailed debug information, use the --verbose flag');
}
logger.debug('Stack trace:', error.stack);
if (error.cause) {
logger.debug('Caused by:', error.cause);
}
}
else if (isError(error)) {
logger.error(`✖ Unexpected error: ${error.message}`);
logger.note('Stack trace:', error.stack);
if (logger.getLogLevel() < repomixLogLevels.DEBUG) {
logger.log('');
logger.note('For detailed debug information, use the --verbose flag');
}
}
else {
logger.error('✖ An unknown error occurred');
try {
logger.note('Error details:', inspect(error, {
depth: 3,
colors: false,
maxArrayLength: 10,
maxStringLength: 200,
breakLength: Number.POSITIVE_INFINITY,
}));
}
catch {
logger.note('Error details: [Error object could not be serialized]');
}
if (logger.getLogLevel() < repomixLogLevels.DEBUG) {
logger.log('');
logger.note('For detailed debug information, use the --verbose flag');
}
}
logger.log('');
logger.info('Need help?');
logger.info(`• File an issue on GitHub: ${REPOMIX_ISSUES_URL}`);
logger.info(`• Join our Discord community: ${REPOMIX_DISCORD_URL}`);
};
const isError = (error) => {
if (error instanceof Error)
return true;
if (typeof error !== 'object' || error === null)
return false;
const obj = error;
return (typeof obj.message === 'string' &&
(!('stack' in obj) || typeof obj.stack === 'string') &&
(!('name' in obj) || typeof obj.name === 'string'));
};
const isRepomixError = (error) => {
if (error instanceof RepomixError)
return true;
if (typeof error !== 'object' || error === null)
return false;
const obj = error;
return (typeof obj.message === 'string' &&
'name' in obj &&
(obj.name === RepomixError.name ||
obj.name === RepomixConfigValidationError.name ||
obj.name === OperationCancelledError.name));
};
export const rethrowValidationErrorIfSchemaError = (error, message) => {
if (!error || typeof error !== 'object')
return;
const err = error;
if ((err.name !== 'ZodError' && err.name !== 'ValiError') || !Array.isArray(err.issues)) {
return;
}
const issues = err.issues;
const errorText = issues
.map((issue) => {
const segments = Array.isArray(issue.path)
? issue.path
.map((segment) => {
if (segment && typeof segment === 'object') {
if ('key' in segment)
return String(segment.key);
return '';
}
return String(segment);
})
.filter((segment) => segment !== '')
: [];
return segments.length === 0 ? issue.message : `[${segments.join('.')}] ${issue.message}`;
})
.join('\n ');
throw new RepomixConfigValidationError(`${message}\n\n ${errorText}\n\n Please check the config file and try again.`);
};