c34dab2cca
Build and Push Docker Container / build-and-push (push) Successful in 4m28s
- Create missing note files before running property:set. - Default date-only datetime values to midnight. - Keep property names out of path authorization checks. - Split policy, vault, daily note, and command target helpers. - Split n8n node args, description, output, and API response helpers. - Split API tests by auth, command, daily note, and property behavior. - Bump API and n8n node versions.
61 lines
2.0 KiB
TypeScript
61 lines
2.0 KiB
TypeScript
import type { IExecuteFunctions } from 'n8n-workflow';
|
|
import { NodeApiError } from 'n8n-workflow';
|
|
|
|
export function toCleanApiError(
|
|
context: IExecuteFunctions,
|
|
error: unknown,
|
|
itemIndex: number,
|
|
): Error {
|
|
const err = isRecord(error) ? error : {};
|
|
const statusCode = Number(
|
|
err.statusCode ?? err.status ?? (isRecord(err.response) ? err.response.statusCode : undefined) ?? 0,
|
|
);
|
|
const body = extractErrorBody(err);
|
|
const detail = extractErrorMessage(body) || (typeof err.message === 'string' ? err.message : '');
|
|
|
|
const statusText = statusCode ? `HTTP ${statusCode}` : 'Request failed';
|
|
const message = detail
|
|
? `Obsidian API error (${statusText}): ${detail}`
|
|
: `Obsidian API error (${statusText})`;
|
|
|
|
return new NodeApiError(
|
|
context.getNode(),
|
|
{ message, ...(statusCode ? { statusCode } : {}), ...(detail ? { detail } : {}) },
|
|
{ message, description: detail || undefined, httpCode: statusCode ? String(statusCode) : undefined, itemIndex },
|
|
);
|
|
}
|
|
|
|
function extractErrorBody(err: Record<string, unknown>): unknown {
|
|
if ('body' in err && err.body !== undefined) return err.body;
|
|
const response = err.response;
|
|
if (isRecord(response)) {
|
|
if ('body' in response && response.body !== undefined) return response.body;
|
|
if ('data' in response && response.data !== undefined) return response.data;
|
|
}
|
|
if ('error' in err && err.error !== undefined) return err.error;
|
|
return undefined;
|
|
}
|
|
|
|
function extractErrorMessage(body: unknown): string {
|
|
let data: unknown = body;
|
|
if (typeof data === 'string') {
|
|
const trimmed = data.trim();
|
|
if (!trimmed) return '';
|
|
try {
|
|
data = JSON.parse(trimmed);
|
|
} catch {
|
|
return trimmed;
|
|
}
|
|
}
|
|
if (isRecord(data)) {
|
|
const candidate = data.detail ?? data.message ?? data.error;
|
|
if (typeof candidate === 'string' && candidate) return candidate;
|
|
if (isRecord(candidate) && typeof candidate.message === 'string') return candidate.message;
|
|
}
|
|
return '';
|
|
}
|
|
|
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
return typeof value === 'object' && value !== null;
|
|
}
|