errors.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /**
  2. * CodeGraph Error Classes
  3. *
  4. * Custom error types for better error handling and debugging.
  5. *
  6. * @module errors
  7. *
  8. * @example
  9. * ```typescript
  10. * import { FileError, ParseError, setLogger, silentLogger } from 'codegraph';
  11. *
  12. * // Catch specific error types
  13. * try {
  14. * await cg.indexAll();
  15. * } catch (error) {
  16. * if (error instanceof FileError) {
  17. * console.log(`File error at ${error.filePath}: ${error.message}`);
  18. * } else if (error instanceof ParseError) {
  19. * console.log(`Parse error at ${error.filePath}:${error.line}`);
  20. * }
  21. * }
  22. *
  23. * // Disable logging for tests
  24. * setLogger(silentLogger);
  25. * ```
  26. */
  27. /**
  28. * Base error class for all CodeGraph errors.
  29. *
  30. * All CodeGraph-specific errors extend this class, allowing you to catch
  31. * all CodeGraph errors with a single catch block.
  32. *
  33. * @example
  34. * ```typescript
  35. * try {
  36. * await cg.indexAll();
  37. * } catch (error) {
  38. * if (error instanceof CodeGraphError) {
  39. * console.log(`CodeGraph error [${error.code}]: ${error.message}`);
  40. * }
  41. * }
  42. * ```
  43. */
  44. export class CodeGraphError extends Error {
  45. /** Error code for categorization (e.g., 'FILE_ERROR', 'PARSE_ERROR') */
  46. readonly code: string;
  47. /** Additional context about the error */
  48. readonly context?: Record<string, unknown>;
  49. constructor(message: string, code: string, context?: Record<string, unknown>) {
  50. super(message);
  51. this.name = 'CodeGraphError';
  52. this.code = code;
  53. this.context = context;
  54. // Maintain proper stack trace for V8
  55. if (Error.captureStackTrace) {
  56. Error.captureStackTrace(this, this.constructor);
  57. }
  58. }
  59. }
  60. /**
  61. * Error reading or accessing files
  62. */
  63. export class FileError extends CodeGraphError {
  64. readonly filePath: string;
  65. constructor(message: string, filePath: string, cause?: Error) {
  66. super(message, 'FILE_ERROR', { filePath, cause: cause?.message });
  67. this.name = 'FileError';
  68. this.filePath = filePath;
  69. if (cause) {
  70. this.cause = cause;
  71. }
  72. }
  73. }
  74. /**
  75. * Error parsing source code
  76. */
  77. export class ParseError extends CodeGraphError {
  78. readonly filePath: string;
  79. readonly line?: number;
  80. readonly column?: number;
  81. constructor(
  82. message: string,
  83. filePath: string,
  84. options?: { line?: number; column?: number; cause?: Error }
  85. ) {
  86. super(message, 'PARSE_ERROR', {
  87. filePath,
  88. line: options?.line,
  89. column: options?.column,
  90. cause: options?.cause?.message,
  91. });
  92. this.name = 'ParseError';
  93. this.filePath = filePath;
  94. this.line = options?.line;
  95. this.column = options?.column;
  96. if (options?.cause) {
  97. this.cause = options.cause;
  98. }
  99. }
  100. }
  101. /**
  102. * Error with database operations
  103. */
  104. export class DatabaseError extends CodeGraphError {
  105. readonly operation: string;
  106. constructor(message: string, operation: string, cause?: Error) {
  107. super(message, 'DATABASE_ERROR', { operation, cause: cause?.message });
  108. this.name = 'DatabaseError';
  109. this.operation = operation;
  110. if (cause) {
  111. this.cause = cause;
  112. }
  113. }
  114. }
  115. /**
  116. * Error with search operations
  117. */
  118. export class SearchError extends CodeGraphError {
  119. readonly query: string;
  120. constructor(message: string, query: string, cause?: Error) {
  121. super(message, 'SEARCH_ERROR', { query, cause: cause?.message });
  122. this.name = 'SearchError';
  123. this.query = query;
  124. if (cause) {
  125. this.cause = cause;
  126. }
  127. }
  128. }
  129. /**
  130. * Error with vector/embedding operations
  131. */
  132. export class VectorError extends CodeGraphError {
  133. constructor(message: string, operation: string, cause?: Error) {
  134. super(message, 'VECTOR_ERROR', { operation, cause: cause?.message });
  135. this.name = 'VectorError';
  136. if (cause) {
  137. this.cause = cause;
  138. }
  139. }
  140. }
  141. /**
  142. * Error with configuration
  143. */
  144. export class ConfigError extends CodeGraphError {
  145. constructor(message: string, details?: Record<string, unknown>) {
  146. super(message, 'CONFIG_ERROR', details);
  147. this.name = 'ConfigError';
  148. }
  149. }
  150. /**
  151. * Simple logger for CodeGraph operations
  152. *
  153. * By default, logs to console.warn for warnings and console.error for errors.
  154. * Can be configured to use custom logging.
  155. */
  156. export interface Logger {
  157. debug(message: string, context?: Record<string, unknown>): void;
  158. warn(message: string, context?: Record<string, unknown>): void;
  159. error(message: string, context?: Record<string, unknown>): void;
  160. }
  161. /**
  162. * Default console-based logger
  163. */
  164. export const defaultLogger: Logger = {
  165. debug(message: string, context?: Record<string, unknown>): void {
  166. if (process.env.CODEGRAPH_DEBUG) {
  167. console.debug(`[CodeGraph] ${message}`, context ?? '');
  168. }
  169. },
  170. warn(message: string, context?: Record<string, unknown>): void {
  171. console.warn(`[CodeGraph] ${message}`, context ?? '');
  172. },
  173. error(message: string, context?: Record<string, unknown>): void {
  174. console.error(`[CodeGraph] ${message}`, context ?? '');
  175. },
  176. };
  177. /**
  178. * Silent logger (no output) - useful for tests
  179. */
  180. export const silentLogger: Logger = {
  181. debug(): void {},
  182. warn(): void {},
  183. error(): void {},
  184. };
  185. /**
  186. * Current logger instance (can be replaced)
  187. */
  188. let currentLogger: Logger = defaultLogger;
  189. /**
  190. * Set the global logger
  191. */
  192. export function setLogger(logger: Logger): void {
  193. currentLogger = logger;
  194. }
  195. /**
  196. * Get the current logger
  197. */
  198. export function getLogger(): Logger {
  199. return currentLogger;
  200. }
  201. /**
  202. * Log a debug message
  203. */
  204. export function logDebug(message: string, context?: Record<string, unknown>): void {
  205. currentLogger.debug(message, context);
  206. }
  207. /**
  208. * Log a warning message
  209. */
  210. export function logWarn(message: string, context?: Record<string, unknown>): void {
  211. currentLogger.warn(message, context);
  212. }
  213. /**
  214. * Log an error message
  215. */
  216. export function logError(message: string, context?: Record<string, unknown>): void {
  217. currentLogger.error(message, context);
  218. }