@@ -11,10 +11,11 @@ import filters from "../filters/filters";
1111import bounds from "binary-search-bounds" ;
1212import { has } from "lodash" ;
1313import { StatisticValue } from "../recorder-types" ;
14- import { HassEntity , YValue } from "../types" ;
14+ import { Config , HassEntity , YValue } from "../types" ;
1515
1616class ConfigParser {
1717 private partiallyParsedConfig ?: any ;
18+ private errors ?: Error [ ] ;
1819 private inputConfig ?: any ;
1920 private hass ?: HomeAssistant ;
2021 cache = new Cache ( ) ;
@@ -25,8 +26,11 @@ class ConfigParser {
2526 raw_config : any ;
2627 hass : HomeAssistant ;
2728 cssVars : HATheme ;
28- } ) {
29+ } ) : Promise < { errors : Error [ ] ; parsed : Config } > {
2930 if ( this . busy ) throw new Error ( "ParseConfig was updated while busy" ) ;
31+ this . partiallyParsedConfig = { } ;
32+ this . errors = [ ] ;
33+
3034 this . busy = true ;
3135 try {
3236 this . hass = input . hass ;
@@ -69,15 +73,19 @@ class ConfigParser {
6973 hass : input . hass ,
7074 getFromConfig : ( ) => "" ,
7175 } ;
72- this . partiallyParsedConfig = { } ;
7376 this . inputConfig = config ;
7477 for ( const [ key , value ] of Object . entries ( config ) ) {
75- await this . evalNode ( {
76- parent : this . partiallyParsedConfig ,
77- path : key ,
78- key : key ,
79- value,
80- } ) ;
78+ try {
79+ await this . evalNode ( {
80+ parent : this . partiallyParsedConfig ,
81+ path : key ,
82+ key : key ,
83+ value,
84+ } ) ;
85+ } catch ( e ) {
86+ console . warn ( `Plotly Graph Card: Error parsing [${ key } ]` , e ) ;
87+ this . errors ?. push ( e as Error ) ;
88+ }
8189 }
8290
8391 // 3rd pass: decorate
@@ -112,7 +120,7 @@ class ConfigParser {
112120 this . partiallyParsedConfig . layout
113121 ) ;
114122
115- return this . partiallyParsedConfig ;
123+ return { errors : this . errors , parsed : this . partiallyParsedConfig } ;
116124 } finally {
117125 this . busy = false ;
118126 }
@@ -128,7 +136,6 @@ class ConfigParser {
128136 key : string ;
129137 value : any ;
130138 } ) {
131- errorIfDeprecated ( path ) ;
132139 if ( path . match ( / ^ d e f a u l t s $ / ) ) return ;
133140 this . fnParam . path = path ;
134141 this . fnParam . getFromConfig = ( pathQuery : string ) =>
@@ -137,7 +144,7 @@ class ConfigParser {
137144 if (
138145 path . match ( / ^ e n t i t i e s \. \d + \. / ) && //isInsideEntity
139146 ! path . match (
140- / ^ e n t i t i e s \. \d + \. ( e n t i t y | a t t r i b u t e | o f f s e t | s t a t i s t i c | p e r i o d ) /
147+ / ^ e n t i t i e s \. \d + \. ( e n t i t y | a t t r i b u t e | t i m e _ o f f s e t | s t a t i s t i c | p e r i o d ) /
141148 ) && //isInsideFetchParamNode
142149 ! this . fnParam . xs && // alreadyFetchedData
143150 ( is$fn ( value ) || path . match ( / ^ e n t i t i e s \. \d + \. f i l t e r s \. \d + $ / ) ) // if function of filter
@@ -147,6 +154,8 @@ class ConfigParser {
147154 if ( typeof value === "string" && value . startsWith ( "$fn" ) ) {
148155 value = myEval ( value . slice ( 3 ) ) ;
149156 }
157+ const error = getDeprecationError ( path , value ) ;
158+ if ( error ) this . errors ?. push ( error ) ;
150159
151160 if ( typeof value === "function" ) {
152161 /**
@@ -160,12 +169,18 @@ class ConfigParser {
160169 const me = Array . isArray ( value ) ? [ ] : { } ;
161170 parent [ key ] = me ;
162171 for ( const [ childKey , childValue ] of Object . entries ( value ) ) {
163- await this . evalNode ( {
164- parent : me ,
165- path : `${ path } .${ childKey } ` ,
166- key : childKey ,
167- value : childValue ,
168- } ) ;
172+ const childPath = `${ path } .${ childKey } ` ;
173+ try {
174+ await this . evalNode ( {
175+ parent : me ,
176+ path : childPath ,
177+ key : childKey ,
178+ value : childValue ,
179+ } ) ;
180+ } catch ( e : any ) {
181+ console . warn ( `Plotly Graph Card: Error parsing [${ childPath } ]` , e ) ;
182+ this . errors ?. push ( new Error ( `at [${ childPath } ]: ${ e ?. message || e } ` ) ) ;
183+ }
169184 }
170185 } else {
171186 parent [ key ] = value ;
@@ -238,7 +253,7 @@ class ConfigParser {
238253 if ( ! visible_range ) {
239254 const hours_to_show = this . fnParam . getFromConfig ( "hours_to_show" ) ;
240255 const global_offset = parseTimeDuration (
241- this . fnParam . getFromConfig ( "offset " )
256+ this . fnParam . getFromConfig ( "time_offset " )
242257 ) ;
243258 const ms = hours_to_show * 60 * 60 * 1000 ;
244259 visible_range = [
@@ -262,7 +277,7 @@ class ConfigParser {
262277 ...( statisticsParams ? statisticsParams : attribute ? { attribute } : { } ) ,
263278 } ;
264279 const offset = parseTimeDuration (
265- this . fnParam . getFromConfig ( path + ".offset " )
280+ this . fnParam . getFromConfig ( path + ".time_offset " )
266281 ) ;
267282
268283 const range_to_fetch = [
@@ -402,17 +417,28 @@ type FnParam = {
402417 meta ?: HassEntity [ "attributes" ] ;
403418} ;
404419
405- function errorIfDeprecated ( path : string ) {
406- if ( path . match ( / ^ e n t i t y \. \d + \. l a m b d a $ / ) )
407- throw new Error ( "Lambdas were removed, use filters instead" ) ;
420+ function getDeprecationError ( path : string , value : any ) {
421+ const e = _getDeprecationError ( path , value ) ;
422+ if ( e ) return new Error ( `at [${ path } ]: ${ e } ` ) ;
423+ return null ;
424+ }
425+ function _getDeprecationError ( path : string , value : any ) {
426+ if ( path . match ( / ^ o f f s e t $ / ) ) return "renamed to time_offset in v3.0.0" ;
427+ if ( path . match ( / ^ e n t i t i e s \. \d + \. o f f s e t $ / ) ) {
428+ try {
429+ parseTimeDuration ( value ) ;
430+ return 'renamed to time_offset in v3.0.0 to avoid conflicts with <a href="https://plotly.com/javascript/reference/bar/#bar-offset">bar-offsets</a>' ;
431+ } catch ( e ) {
432+ // bar-offsets are numbers without time unit
433+ }
434+ }
435+ if ( path . match ( / ^ e n t i t i e s \. \d + \. l a m b d a $ / ) )
436+ return "removed in v3.0.0, use filters instead" ;
408437 if ( path . match ( / ^ s i g n i f i c a n t _ c h a n g e s _ o n l y $ / ) )
409- throw new Error (
410- "significant_changes_only was removed, it is now always set to false"
411- ) ;
438+ return "removed in v3.0.0, it is now always set to false" ;
412439 if ( path . match ( / ^ m i n i m a l _ r e s p o n s e $ / ) )
413- throw new Error (
414- "minimal_response was removed, if you need attributes use the 'attribute' parameter instead."
415- ) ;
440+ return "removed in v3.0.0, if you need attributes use the 'attribute' parameter instead." ;
441+ return null ;
416442}
417443export const getEntityIndex = ( path : string ) =>
418444 + path . match ( / e n t i t i e s \. ( \d + ) / ) ! [ 1 ] ;
0 commit comments