/**
* Base error class for all Logseq-related errors.
*/
export class LogseqError extends Error {
constructor(
message: string,
public readonly context?: Record<string, unknown>
) {
super(message);
this.name = "LogseqError";
Error.captureStackTrace?.(this, this.constructor);
}
/**
* Returns a formatted error message with context.
*/
toDetailedString(): string {
if (!this.context || Object.keys(this.context).length === 0) {
return this.message;
}
const contextStr = Object.entries(this.context)
.map(([key, value]) => ` ${key}: ${JSON.stringify(value)}`)
.join("\n");
return `${this.message}\nContext:\n${contextStr}`;
}
}
/**
* Error thrown when the Logseq API returns an error response.
*/
export class LogseqApiError extends LogseqError {
constructor(
message: string,
public readonly method: string,
public readonly statusCode?: number,
context?: Record<string, unknown>
) {
super(message, { method, statusCode, ...context });
this.name = "LogseqApiError";
}
static fromHttpError(method: string, status: number, statusText: string): LogseqApiError {
return new LogseqApiError(`Logseq API error: ${status} ${statusText}`, method, status, {
statusText,
});
}
static fromMethodError(method: string, errorMessage: string): LogseqApiError {
return new LogseqApiError(`Logseq API method failed: ${errorMessage}`, method, undefined, {
errorMessage,
});
}
}
/**
* Error thrown when unable to connect to the Logseq API server.
*/
export class LogseqConnectionError extends LogseqError {
constructor(
message: string,
public readonly url: string,
public readonly cause?: Error
) {
super(message, { url, cause: cause?.message });
this.name = "LogseqConnectionError";
}
static fromNetworkError(url: string, cause: Error): LogseqConnectionError {
return new LogseqConnectionError(
`Failed to connect to Logseq at ${url}: ${cause.message}`,
url,
cause
);
}
}
/**
* Error thrown when a requested resource is not found.
*/
export class LogseqNotFoundError extends LogseqError {
constructor(
public readonly resourceType: "page" | "block" | "graph" | "task" | "template",
public readonly identifier: string
) {
super(`${resourceType} not found: ${identifier}`, { resourceType, identifier });
this.name = "LogseqNotFoundError";
}
}
/**
* Error thrown when an operation receives invalid arguments.
*/
export class LogseqValidationError extends LogseqError {
constructor(
message: string,
public readonly field?: string,
public readonly value?: unknown
) {
super(message, { field, value });
this.name = "LogseqValidationError";
}
}
/**
* Type guard to check if an error is a LogseqError.
*/
export function isLogseqError(error: unknown): error is LogseqError {
return error instanceof LogseqError;
}
/**
* Formats any error into a user-friendly message.
*/
export function formatError(error: unknown): string {
if (error instanceof LogseqError) {
return error.toDetailedString();
}
if (error instanceof Error) {
return error.message;
}
return String(error);
}