Make error handling and console logging consistent
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { FrigateCardError } from '../types';
|
||||
|
||||
/**
|
||||
* Dispatch a Frigate Card event.
|
||||
@@ -60,3 +61,19 @@ export function arrayMove(target: unknown[], from: number, to: number): void {
|
||||
export function contentsChanged(n: unknown, o: unknown): boolean {
|
||||
return !isEqual(n, o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an error as a warning to the console.
|
||||
* @param e The Error object.
|
||||
* @param func The Console func to call.
|
||||
*/
|
||||
export function errorToConsole(e: Error, func?: CallableFunction): void {
|
||||
if (!func) {
|
||||
func = console.warn;
|
||||
}
|
||||
if (e instanceof FrigateCardError && e.context) {
|
||||
func(e, e.context);
|
||||
} else {
|
||||
func(e);
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ const recordingSegmentsSchema = recordingSegmentSchema.array();
|
||||
export type RecordingSegments = z.infer<typeof recordingSegmentsSchema>;
|
||||
|
||||
/**
|
||||
* Get the recordings summary.
|
||||
* Get the recordings summary. May throw.
|
||||
* @param hass The Home Assistant object.
|
||||
* @param client_id The Frigate client_id.
|
||||
* @param camera_name The Frigate camera name.
|
||||
@@ -70,7 +70,7 @@ export const getRecordingsSummary = async (
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the recording segments..
|
||||
* Get the recording segments. May throw.
|
||||
* @param hass The Home Assistant object.
|
||||
* @param client_id The Frigate client_id.
|
||||
* @param camera_name The Frigate camera name.
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
EntityList,
|
||||
entityListSchema,
|
||||
ExtendedEntity,
|
||||
extendedEntitySchema
|
||||
extendedEntitySchema,
|
||||
} from '../../types.js';
|
||||
|
||||
export class ExtendedEntityCache {
|
||||
@@ -78,7 +78,7 @@ export const getExtendedEntity = async (
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the extended entity information for an array of entities.
|
||||
* Get the extended entity information for an array of entities. May throw.
|
||||
* @param hass The Home Assistant object.
|
||||
* @param entities An array of entity ids.
|
||||
* @param cache An optional ExtendedEntityCache.
|
||||
@@ -98,7 +98,7 @@ export const getExtendedEntities = async (
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a list of all entities from the entity registry.
|
||||
* Get a list of all entities from the entity registry. May throw.
|
||||
* @param hass The Home Assistant object.
|
||||
* @returns An entity list object.
|
||||
*/
|
||||
|
||||
+25
-25
@@ -9,7 +9,7 @@ import {
|
||||
FrigateCardError,
|
||||
SignedPath,
|
||||
signedPathSchema,
|
||||
StateParameters
|
||||
StateParameters,
|
||||
} from '../../types.js';
|
||||
import { stateIcon } from '../icons/state-icon.js';
|
||||
import { getParseErrorKeys } from '../zod.js';
|
||||
@@ -26,27 +26,30 @@ export async function homeAssistantWSRequest<T>(
|
||||
schema: ZodSchema<T>,
|
||||
request: MessageBase,
|
||||
): Promise<T> {
|
||||
const response = await hass.callWS<T>(request);
|
||||
let response;
|
||||
try {
|
||||
response = await hass.callWS<T>(request);
|
||||
} catch (e) {
|
||||
if (!(e instanceof Error)) {
|
||||
throw new FrigateCardError(localize('error.failed_response'), {
|
||||
request: request,
|
||||
response: e,
|
||||
});
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (!response) {
|
||||
const error_message = `${localize('error.empty_response')}: ${JSON.stringify(
|
||||
request,
|
||||
)}`;
|
||||
console.warn(error_message);
|
||||
throw new Error(error_message);
|
||||
throw new FrigateCardError(localize('error.empty_response'), {
|
||||
request: request,
|
||||
});
|
||||
}
|
||||
const parseResult = schema.safeParse(response);
|
||||
if (!parseResult.success) {
|
||||
const keys = getParseErrorKeys<T>(parseResult.error);
|
||||
const error_message = localize('error.invalid_response');
|
||||
console.warn(
|
||||
`${error_message}: ${JSON.stringify(request)}. ${localize(
|
||||
'error.invalid_keys',
|
||||
)}: ${keys}`,
|
||||
);
|
||||
throw new FrigateCardError(error_message, {
|
||||
throw new FrigateCardError(localize('error.invalid_response'), {
|
||||
request: request,
|
||||
invalid_keys: keys,
|
||||
response: response,
|
||||
invalid_keys: getParseErrorKeys<T>(parseResult.error),
|
||||
});
|
||||
}
|
||||
return parseResult.data;
|
||||
@@ -96,9 +99,7 @@ export async function homeAssistantHTTPRequest<T>(
|
||||
let signResponse: string | null | undefined;
|
||||
try {
|
||||
signResponse = await homeAssistantSignPath(hass, url);
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
if (!signResponse) {
|
||||
throw new FrigateCardError(localize('error.failed_sign'), {
|
||||
@@ -127,21 +128,20 @@ export async function homeAssistantHTTPRequest<T>(
|
||||
try {
|
||||
raw_json = await response.json();
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
throw new FrigateCardError(localize('error.undecodable_response'), {
|
||||
url: signedURL.toString(),
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
return schema.parse(raw_json);
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
const parseResult = schema.safeParse(raw_json);
|
||||
if (!parseResult.success) {
|
||||
throw new FrigateCardError(localize('error.invalid_response'), {
|
||||
url: signedURL.toString(),
|
||||
response: raw_json,
|
||||
raw_json: raw_json,
|
||||
invalid_keys: getParseErrorKeys<T>(parseResult.error),
|
||||
});
|
||||
}
|
||||
return parseResult.data;
|
||||
}
|
||||
|
||||
interface HassStateDifference {
|
||||
|
||||
@@ -2,10 +2,11 @@ import { HomeAssistant } from 'custom-card-helpers';
|
||||
import QuickLRU from 'quick-lru';
|
||||
import { homeAssistantWSRequest } from '.';
|
||||
import {
|
||||
FrigateBrowseMediaSource,
|
||||
ResolvedMedia,
|
||||
resolvedMediaSchema
|
||||
FrigateBrowseMediaSource,
|
||||
ResolvedMedia,
|
||||
resolvedMediaSchema,
|
||||
} from '../../types.js';
|
||||
import { errorToConsole } from '../basic';
|
||||
|
||||
// It's important the cache size be at least as large as the largest likely
|
||||
// media query or media items will from a given query will be evicted for other
|
||||
@@ -30,7 +31,6 @@ export class ResolvedMediaCache {
|
||||
return this._cache.has(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get resolved media information given an id.
|
||||
* @param id The id.
|
||||
@@ -55,7 +55,7 @@ export class ResolvedMediaCache {
|
||||
* @param hass The Home Assistant object.
|
||||
* @param mediaSource The media source object.
|
||||
* @param cache An optional ResolvedMediaCache object.
|
||||
* @returns
|
||||
* @returns The resolved media or `null`.
|
||||
*/
|
||||
export const resolveMedia = async (
|
||||
hass: HomeAssistant,
|
||||
@@ -73,7 +73,12 @@ export const resolveMedia = async (
|
||||
type: 'media_source/resolve_media',
|
||||
media_content_id: mediaSource.media_content_id,
|
||||
};
|
||||
const resolvedMedia = await homeAssistantWSRequest(hass, resolvedMediaSchema, request);
|
||||
let resolvedMedia: ResolvedMedia | null = null;
|
||||
try {
|
||||
resolvedMedia = await homeAssistantWSRequest(hass, resolvedMediaSchema, request);
|
||||
} catch (e) {
|
||||
errorToConsole(e as Error);
|
||||
}
|
||||
if (cache && resolvedMedia) {
|
||||
cache.set(mediaSource.media_content_id, resolvedMedia);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user