Change card configuration validation to zod.

This commit is contained in:
Dermot Duffy
2021-08-09 22:39:34 -07:00
parent 359177451a
commit 0eee85ccac
3 changed files with 30 additions and 45 deletions
+15 -28
View File
@@ -30,7 +30,7 @@ import './editor';
import style from './frigate-card.scss' import style from './frigate-card.scss'
import { frigateGetEventsResponseSchema } from './types'; import { frigateCardConfigSchema, frigateGetEventsResponseSchema } from './types';
import type { FrigateCardConfig, FrigateEvent, FrigateGetEventsResponse, GetEventsParameters, ControlVideosParameters } from './types'; import type { FrigateCardConfig, FrigateEvent, FrigateGetEventsResponse, GetEventsParameters, ControlVideosParameters } from './types';
import { actionHandler } from './action-handler-directive'; import { actionHandler } from './action-handler-directive';
import { CARD_VERSION } from './const'; import { CARD_VERSION } from './const';
@@ -100,42 +100,29 @@ export class FrigateCard extends LitElement {
if (!inputConfig) { if (!inputConfig) {
throw new Error(localize('common.invalid_configuration:')); throw new Error(localize('common.invalid_configuration:'));
} }
// inputConfig is not "extensible" (i.e. preventExtensions() has been
// called on it), need to make a copy to allow modifications.
const cardConfig = Object.assign({
name: 'Frigate'
}, inputConfig);
if (cardConfig.test_gui) { const parseResult = frigateCardConfigSchema.safeParse(inputConfig);
if (!parseResult.success) {
const errors = parseResult.error.format()
const keys = Object.keys(errors).filter(v => !v.startsWith("_"));
throw new Error(localize('common.invalid_configuration') + ": " + keys.join(", "));
}
const config = parseResult.data;
if (config.test_gui) {
getLovelace().setEditMode(true); getLovelace().setEditMode(true);
} }
if (!cardConfig.frigate_url) { if (!config.frigate_camera_name) {
throw new Error(localize('common.invalid_configuration_missing') + ": frigate_url");
}
if (!cardConfig.frigate_camera_name) {
// No camera name specified, so just assume it's the same as the entity name. // No camera name specified, so just assume it's the same as the entity name.
if (cardConfig.camera_entity.includes(".")) { if (config.camera_entity.includes(".")) {
cardConfig.frigate_camera_name = cardConfig.camera_entity.split('.', 2)[1] config.frigate_camera_name = config.camera_entity.split('.', 2)[1]
} else { } else {
throw new Error(localize('common.invalid_configuration_missing') + ": camera_entity"); throw new Error(localize('common.invalid_configuration') + ": camera_entity");
} }
} }
if (cardConfig.view_timeout) { this.config = config;
if (isNaN(Number(cardConfig.view_timeout))) {
throw new Error(localize('common.invalid_configuration') + ": view_timeout");
}
}
if (cardConfig.view_default) {
if (!["live", "clips", "clip", "snapshots", "snapshot"].includes(cardConfig.view_default)) {
throw new Error(localize('common.invalid_configuration') + ": view_default");
}
}
this.config = cardConfig;
this._setViewModeToDefault(); this._setViewModeToDefault();
} }
-1
View File
@@ -2,7 +2,6 @@
"common": { "common": {
"version": "Version", "version": "Version",
"invalid_configuration": "Invalid configuration", "invalid_configuration": "Invalid configuration",
"invalid_configuration_missing": "Missing parameter in configuration",
"show_warning": "Show Warning", "show_warning": "Show Warning",
"show_error": "Show Error" "show_error": "Show Error"
} }
+15 -16
View File
@@ -1,5 +1,6 @@
import { ActionConfig, LovelaceCard, LovelaceCardConfig, LovelaceCardEditor } from 'custom-card-helpers'; import { ActionConfig, LovelaceCard, LovelaceCardConfig, LovelaceCardEditor } from 'custom-card-helpers';
import { z } from "zod"; import { z } from "zod";
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
'frigate-card-editor': LovelaceCardEditor; 'frigate-card-editor': LovelaceCardEditor;
@@ -10,24 +11,22 @@ declare global {
/** /**
* Internal types. * Internal types.
*/ */
export interface FrigateCardConfig extends LovelaceCardConfig {
type: string;
name?: string;
camera_entity: string; export const frigateCardConfigSchema = z.object({
motion_entity: string | null; camera_entity: z.string(),
frigate_url: string; motion_entity: z.string().optional(),
frigate_camera_name?: string | null; frigate_url: z.string().url(),
default_view: string | null; frigate_camera_name: z.string().optional(),
timeout_ms?: number | null; view_default: z.enum(["live", "clips", "clip", "snapshots", "snapshot"]).optional().default("live"),
view_timeout: z.number().optional(),
label: z.string().optional(),
show_warning: z.boolean().optional(),
show_error: z.boolean().optional(),
test_gui: z.boolean().optional(),
})
export type FrigateCardConfig = z.infer<typeof frigateCardConfigSchema>;
show_warning?: boolean;
show_error?: boolean;
test_gui?: boolean;
tap_action?: ActionConfig;
hold_action?: ActionConfig;
double_tap_action?: ActionConfig;
}
export interface GetEventsParameters { export interface GetEventsParameters {
has_clip?: boolean; has_clip?: boolean;