Make error handling and console logging consistent

This commit is contained in:
Dermot Duffy
2022-06-20 03:03:27 +00:00
parent bd393d953a
commit 4901905ca1
11 changed files with 132 additions and 99 deletions
+17
View File
@@ -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);
}
}
+2 -2
View File
@@ -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.
+3 -3
View File
@@ -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
View File
@@ -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 {
+11 -6
View File
@@ -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);
}