ha-nunjucks 1.6.1 → 1.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +4 -0
  2. package/dist/filters.d.ts +2 -2
  3. package/dist/filters.js +134 -134
  4. package/dist/globals.d.ts +2 -2
  5. package/dist/globals.js +142 -142
  6. package/dist/helpers.d.ts +18 -0
  7. package/dist/helpers.js +71 -0
  8. package/dist/index.d.ts +16 -16
  9. package/dist/index.js +77 -78
  10. package/dist/models/interfaces/hass.d.ts +42 -42
  11. package/dist/models/interfaces/hass.js +1 -1
  12. package/dist/models/interfaces/registries.d.ts +63 -63
  13. package/dist/models/interfaces/registries.js +1 -1
  14. package/dist/tests.d.ts +2 -2
  15. package/dist/tests.js +24 -24
  16. package/dist/utils/areas.d.ts +6 -6
  17. package/dist/utils/areas.js +105 -105
  18. package/dist/utils/contains.d.ts +1 -1
  19. package/dist/utils/contains.js +3 -3
  20. package/dist/utils/devices.d.ts +7 -7
  21. package/dist/utils/devices.js +72 -72
  22. package/dist/utils/distance.d.ts +4 -4
  23. package/dist/utils/distance.js +246 -246
  24. package/dist/utils/entities.d.ts +2 -2
  25. package/dist/utils/entities.js +8 -8
  26. package/dist/utils/floors.d.ts +6 -6
  27. package/dist/utils/floors.js +105 -105
  28. package/dist/utils/groups.d.ts +3 -3
  29. package/dist/utils/groups.js +44 -44
  30. package/dist/utils/iif.d.ts +2 -2
  31. package/dist/utils/iif.js +22 -22
  32. package/dist/utils/integrations.d.ts +2 -2
  33. package/dist/utils/integrations.js +17 -17
  34. package/dist/utils/json.d.ts +3 -3
  35. package/dist/utils/json.js +29 -29
  36. package/dist/utils/labels.d.ts +9 -9
  37. package/dist/utils/labels.js +118 -118
  38. package/dist/utils/miscellaneous.d.ts +2 -2
  39. package/dist/utils/miscellaneous.js +6 -6
  40. package/dist/utils/numeric.d.ts +30 -30
  41. package/dist/utils/numeric.js +283 -283
  42. package/dist/utils/regexp.d.ts +6 -6
  43. package/dist/utils/regexp.js +18 -18
  44. package/dist/utils/state_translated.d.ts +9 -9
  45. package/dist/utils/state_translated.js +65 -65
  46. package/dist/utils/states.d.ts +7 -7
  47. package/dist/utils/states.js +74 -74
  48. package/dist/utils/string_filters.d.ts +4 -4
  49. package/dist/utils/string_filters.js +27 -27
  50. package/dist/utils/time.d.ts +15 -15
  51. package/dist/utils/time.js +268 -268
  52. package/dist/utils/type_checking.d.ts +5 -5
  53. package/dist/utils/type_checking.js +18 -18
  54. package/dist/utils/type_conversions.d.ts +2 -2
  55. package/dist/utils/type_conversions.js +6 -6
  56. package/dist/utils/zip.d.ts +1 -1
  57. package/dist/utils/zip.js +24 -24
  58. package/package.json +55 -54
package/README.md CHANGED
@@ -90,6 +90,10 @@ When the return type is expected to be a number, end users should cast these val
90
90
 
91
91
  `renderTemplate` will return an empty string for strings that may have been cast from nullish non-numerical values, such as `undefined`, `null`, and `None` (case sensitive).
92
92
 
93
+ ### Global Environment
94
+
95
+ ha-nunjucks creates one global object on the browser window, which contains an nunjucks environment used by all custom element instances that use ha-nunjucks. This prevents redundant re-initializing of ha-nunjucks across many custom elements and a significant initial page load speedup. If multiple different custom elements use ha-nunjucks, they will all use the same shared nunjucks environment which is initialized the first time one of them is loaded. ha-nunjucks will also check the version that is loaded, and overwrite it if one custom element has a new version than the currently loaded version.
96
+
93
97
  ## Available Extensions
94
98
 
95
99
  The vast majority of the [Home Assistant template extensions](https://www.home-assistant.io/docs/configuration/templating/#home-assistant-template-extensions) have been implemented into this package. If there are functions that you use that are not currently supported or don't behave exactly like their jinja2 versions, please make a feature request or try adding it to the project yourself and create a pull request.
package/dist/filters.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { Environment } from 'nunjucks';
2
- export declare function addFilters(env: Environment): Environment;
1
+ import { Environment } from 'nunjucks';
2
+ export declare function addFilters(env: Environment): Environment;
package/dist/filters.js CHANGED
@@ -1,134 +1,134 @@
1
- import { area_devices, area_entities, area_id, area_name } from './utils/areas';
2
- import { contains } from './utils/contains';
3
- import { device_attr, device_entities, device_id, device_name, } from './utils/devices';
4
- import { closest } from './utils/distance';
5
- import { floor_areas, floor_entities, floor_id, floor_name, } from './utils/floors';
6
- import { expand } from './utils/groups';
7
- import { iif } from './utils/iif';
8
- import { from_json, is_defined, to_json } from './utils/json';
9
- import { label_areas, label_description, label_devices, label_entities, label_id, label_name, labels, } from './utils/labels';
10
- import { str } from './utils/miscellaneous';
11
- import { acos, add, asin, atan, atan2, average, bitwise_and, bitwise_not, bitwise_or, bitwise_xor, bool, cos, is_number, log, max, median, min, multiply, ord, sin, sqrt, statistical_mode, tan, } from './utils/numeric';
12
- import { regex_findall, regex_findall_index, regex_replace, } from './utils/regexp';
13
- import { attr_name_translated, attr_value_translated, date_translated, datetime_translated, number_translated, state_translated, time_translated, } from './utils/state_translated';
14
- import { has_value, state_attr, states } from './utils/states';
15
- import { base64_decode, base64_encode, ordinal, slugify, } from './utils/string_filters';
16
- import { as_datetime, as_local, as_timedelta, as_timestamp, relative_time, time_since, time_until, timestamp_custom, timestamp_local, timestamp_utc, today_at, } from './utils/time';
17
- export function addFilters(env) {
18
- for (const func in FILTERS) {
19
- env.addFilter(func, function (...args) {
20
- return FILTERS[func](...args);
21
- });
22
- }
23
- for (const func in HASS_FILTERS) {
24
- env.addFilter(func, function (...args) {
25
- return HASS_FILTERS[func](window.haNunjucks.hass, ...args);
26
- });
27
- }
28
- return env;
29
- }
30
- const HASS_FILTERS = {
31
- // States
32
- states,
33
- state_attr,
34
- has_value,
35
- // State Translated
36
- state_translated,
37
- attr_name_translated,
38
- attr_value_translated,
39
- // Groups
40
- expand,
41
- // Devices
42
- device_entities,
43
- device_attr,
44
- device_id,
45
- device_name,
46
- // Floors
47
- floor_id,
48
- floor_name,
49
- floor_areas,
50
- floor_entities,
51
- // Areas
52
- area_id,
53
- area_name,
54
- area_entities,
55
- area_devices,
56
- // Labels
57
- labels,
58
- label_areas,
59
- label_devices,
60
- label_entities,
61
- // IIF
62
- iif,
63
- // Distance
64
- closest,
65
- };
66
- const FILTERS = {
67
- // Labels
68
- label_id,
69
- label_name,
70
- label_description,
71
- // Time
72
- today_at,
73
- as_timedelta,
74
- as_datetime,
75
- as_timestamp,
76
- as_local,
77
- relative_time,
78
- time_since,
79
- time_until,
80
- timestamp_local,
81
- timestamp_utc,
82
- timestamp_custom,
83
- date_translated,
84
- time_translated,
85
- datetime_translated,
86
- // To/From JSON
87
- to_json,
88
- from_json,
89
- // Is Defined
90
- is_defined,
91
- // Distance
92
- closest,
93
- // Contains
94
- contains,
95
- // Numeric
96
- // float filter is built into nunjucks
97
- is_number,
98
- // int filter is built into nunjucks
99
- bool,
100
- log,
101
- sin,
102
- cos,
103
- tan,
104
- asin,
105
- acos,
106
- atan,
107
- atan2,
108
- sqrt,
109
- max,
110
- min,
111
- average,
112
- median,
113
- statistical_mode,
114
- bitwise_and,
115
- bitwise_or,
116
- bitwise_xor,
117
- bitwise_not,
118
- ord,
119
- multiply,
120
- add,
121
- number_translated,
122
- // Type conversions
123
- str,
124
- // String filters
125
- // urlencode filter is built into nunjucks
126
- slugify,
127
- ordinal,
128
- base64_encode,
129
- base64_decode,
130
- // Regular Expressions
131
- regex_replace,
132
- regex_findall,
133
- regex_findall_index,
134
- };
1
+ import { area_devices, area_entities, area_id, area_name } from './utils/areas';
2
+ import { contains } from './utils/contains';
3
+ import { device_attr, device_entities, device_id, device_name, } from './utils/devices';
4
+ import { closest } from './utils/distance';
5
+ import { floor_areas, floor_entities, floor_id, floor_name, } from './utils/floors';
6
+ import { expand } from './utils/groups';
7
+ import { iif } from './utils/iif';
8
+ import { from_json, is_defined, to_json } from './utils/json';
9
+ import { label_areas, label_description, label_devices, label_entities, label_id, label_name, labels, } from './utils/labels';
10
+ import { str } from './utils/miscellaneous';
11
+ import { acos, add, asin, atan, atan2, average, bitwise_and, bitwise_not, bitwise_or, bitwise_xor, bool, cos, is_number, log, max, median, min, multiply, ord, sin, sqrt, statistical_mode, tan, } from './utils/numeric';
12
+ import { regex_findall, regex_findall_index, regex_replace, } from './utils/regexp';
13
+ import { attr_name_translated, attr_value_translated, date_translated, datetime_translated, number_translated, state_translated, time_translated, } from './utils/state_translated';
14
+ import { has_value, state_attr, states } from './utils/states';
15
+ import { base64_decode, base64_encode, ordinal, slugify, } from './utils/string_filters';
16
+ import { as_datetime, as_local, as_timedelta, as_timestamp, relative_time, time_since, time_until, timestamp_custom, timestamp_local, timestamp_utc, today_at, } from './utils/time';
17
+ export function addFilters(env) {
18
+ for (const func in FILTERS) {
19
+ env.addFilter(func, function (...args) {
20
+ return FILTERS[func](...args);
21
+ });
22
+ }
23
+ for (const func in HASS_FILTERS) {
24
+ env.addFilter(func, function (...args) {
25
+ return HASS_FILTERS[func](window.haNunjucks.hass, ...args);
26
+ });
27
+ }
28
+ return env;
29
+ }
30
+ const HASS_FILTERS = {
31
+ // States
32
+ states,
33
+ state_attr,
34
+ has_value,
35
+ // State Translated
36
+ state_translated,
37
+ attr_name_translated,
38
+ attr_value_translated,
39
+ // Groups
40
+ expand,
41
+ // Devices
42
+ device_entities,
43
+ device_attr,
44
+ device_id,
45
+ device_name,
46
+ // Floors
47
+ floor_id,
48
+ floor_name,
49
+ floor_areas,
50
+ floor_entities,
51
+ // Areas
52
+ area_id,
53
+ area_name,
54
+ area_entities,
55
+ area_devices,
56
+ // Labels
57
+ labels,
58
+ label_areas,
59
+ label_devices,
60
+ label_entities,
61
+ // IIF
62
+ iif,
63
+ // Distance
64
+ closest,
65
+ };
66
+ const FILTERS = {
67
+ // Labels
68
+ label_id,
69
+ label_name,
70
+ label_description,
71
+ // Time
72
+ today_at,
73
+ as_timedelta,
74
+ as_datetime,
75
+ as_timestamp,
76
+ as_local,
77
+ relative_time,
78
+ time_since,
79
+ time_until,
80
+ timestamp_local,
81
+ timestamp_utc,
82
+ timestamp_custom,
83
+ date_translated,
84
+ time_translated,
85
+ datetime_translated,
86
+ // To/From JSON
87
+ to_json,
88
+ from_json,
89
+ // Is Defined
90
+ is_defined,
91
+ // Distance
92
+ closest,
93
+ // Contains
94
+ contains,
95
+ // Numeric
96
+ // float filter is built into nunjucks
97
+ is_number,
98
+ // int filter is built into nunjucks
99
+ bool,
100
+ log,
101
+ sin,
102
+ cos,
103
+ tan,
104
+ asin,
105
+ acos,
106
+ atan,
107
+ atan2,
108
+ sqrt,
109
+ max,
110
+ min,
111
+ average,
112
+ median,
113
+ statistical_mode,
114
+ bitwise_and,
115
+ bitwise_or,
116
+ bitwise_xor,
117
+ bitwise_not,
118
+ ord,
119
+ multiply,
120
+ add,
121
+ number_translated,
122
+ // Type conversions
123
+ str,
124
+ // String filters
125
+ // urlencode filter is built into nunjucks
126
+ slugify,
127
+ ordinal,
128
+ base64_encode,
129
+ base64_decode,
130
+ // Regular Expressions
131
+ regex_replace,
132
+ regex_findall,
133
+ regex_findall_index,
134
+ };
package/dist/globals.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { Environment } from 'nunjucks';
2
- export declare function addGlobals(env: Environment): Environment;
1
+ import { Environment } from 'nunjucks';
2
+ export declare function addGlobals(env: Environment): Environment;
package/dist/globals.js CHANGED
@@ -1,142 +1,142 @@
1
- import { area_devices, area_entities, area_id, area_name, areas, } from './utils/areas';
2
- import { device_attr, device_entities, device_id, device_name, is_device_attr, } from './utils/devices';
3
- import { closest, distance } from './utils/distance';
4
- import { is_hidden_entity } from './utils/entities';
5
- import { floor_areas, floor_entities, floor_id, floor_name, floors, } from './utils/floors';
6
- import { expand } from './utils/groups';
7
- import { iif } from './utils/iif';
8
- import { integration_entities } from './utils/integrations';
9
- import { label_areas, label_description, label_devices, label_entities, label_id, label_name, labels, } from './utils/labels';
10
- import { match_media, str } from './utils/miscellaneous';
11
- import { acos, asin, atan, atan2, average, bool, cos, e, float, inf, int, is_number, log, max, median, min, pi, sin, sqrt, statistical_mode, tan, tau, } from './utils/numeric';
12
- import { attr_name_translated, attr_value_translated, date_translated, datetime_translated, number_translated, state_translated, time_translated, } from './utils/state_translated';
13
- import { has_value, is_state, is_state_attr, state_attr, states, } from './utils/states';
14
- import { slugify } from './utils/string_filters';
15
- import { as_datetime, as_local, as_timedelta, as_timestamp, now, relative_time, strptime, time_since, time_until, today_at, utcnow, } from './utils/time';
16
- import { list, set } from './utils/type_conversions';
17
- import { zip } from './utils/zip';
18
- import dt, { date, datetime, time, timedelta } from 'ts-py-datetime';
19
- export function addGlobals(env) {
20
- for (const func in GLOBALS) {
21
- env.addGlobal(func, function (...args) {
22
- return GLOBALS[func](...args);
23
- });
24
- }
25
- for (const func in HASS_GLOBALS) {
26
- env.addGlobal(func, function (...args) {
27
- return HASS_GLOBALS[func](window.haNunjucks.hass, ...args);
28
- });
29
- }
30
- for (const c in CONST_GLOBALS) {
31
- env.addGlobal(c, CONST_GLOBALS[c]);
32
- }
33
- env.addGlobal('dt', dt);
34
- env.addGlobal('date', date);
35
- env.addGlobal('time', time);
36
- env.addGlobal('datetime', datetime);
37
- env.addGlobal('timedelta', timedelta);
38
- return env;
39
- }
40
- const HASS_GLOBALS = {
41
- // States
42
- states,
43
- is_state,
44
- state_attr,
45
- is_state_attr,
46
- has_value,
47
- // State Translated
48
- state_translated,
49
- attr_name_translated,
50
- attr_value_translated,
51
- // Groups
52
- expand,
53
- // Entities
54
- is_hidden_entity,
55
- // Devices
56
- device_entities,
57
- device_attr,
58
- is_device_attr,
59
- device_id,
60
- device_name,
61
- // Floors
62
- floors,
63
- floor_id,
64
- floor_name,
65
- floor_areas,
66
- floor_entities,
67
- // Areas
68
- areas,
69
- area_id,
70
- area_name,
71
- area_entities,
72
- area_devices,
73
- // Integrations
74
- integration_entities,
75
- // Labels
76
- labels,
77
- label_areas,
78
- label_devices,
79
- label_entities,
80
- // Immediate If
81
- iif,
82
- // Distance
83
- distance,
84
- closest,
85
- };
86
- const GLOBALS = {
87
- // Labels
88
- label_id,
89
- label_name,
90
- label_description,
91
- // Time
92
- now,
93
- utcnow,
94
- today_at,
95
- as_datetime,
96
- as_timestamp,
97
- as_local,
98
- strptime,
99
- relative_time,
100
- time_since,
101
- time_until,
102
- as_timedelta,
103
- date_translated,
104
- time_translated,
105
- datetime_translated,
106
- // Numeric,
107
- float,
108
- is_number,
109
- int,
110
- bool,
111
- log,
112
- sin,
113
- cos,
114
- tan,
115
- asin,
116
- acos,
117
- atan,
118
- atan2,
119
- sqrt,
120
- max,
121
- min,
122
- average,
123
- median,
124
- statistical_mode,
125
- number_translated,
126
- // Type Conversions
127
- set,
128
- list,
129
- str,
130
- // Iterating Multiple Objects
131
- zip,
132
- // String fitlers
133
- slugify,
134
- // Miscellaneous
135
- match_media,
136
- };
137
- const CONST_GLOBALS = {
138
- e,
139
- pi,
140
- tau,
141
- inf,
142
- };
1
+ import { area_devices, area_entities, area_id, area_name, areas, } from './utils/areas';
2
+ import { device_attr, device_entities, device_id, device_name, is_device_attr, } from './utils/devices';
3
+ import { closest, distance } from './utils/distance';
4
+ import { is_hidden_entity } from './utils/entities';
5
+ import { floor_areas, floor_entities, floor_id, floor_name, floors, } from './utils/floors';
6
+ import { expand } from './utils/groups';
7
+ import { iif } from './utils/iif';
8
+ import { integration_entities } from './utils/integrations';
9
+ import { label_areas, label_description, label_devices, label_entities, label_id, label_name, labels, } from './utils/labels';
10
+ import { match_media, str } from './utils/miscellaneous';
11
+ import { acos, asin, atan, atan2, average, bool, cos, e, float, inf, int, is_number, log, max, median, min, pi, sin, sqrt, statistical_mode, tan, tau, } from './utils/numeric';
12
+ import { attr_name_translated, attr_value_translated, date_translated, datetime_translated, number_translated, state_translated, time_translated, } from './utils/state_translated';
13
+ import { has_value, is_state, is_state_attr, state_attr, states, } from './utils/states';
14
+ import { slugify } from './utils/string_filters';
15
+ import { as_datetime, as_local, as_timedelta, as_timestamp, now, relative_time, strptime, time_since, time_until, today_at, utcnow, } from './utils/time';
16
+ import { list, set } from './utils/type_conversions';
17
+ import { zip } from './utils/zip';
18
+ import dt, { date, datetime, time, timedelta } from 'ts-py-datetime';
19
+ export function addGlobals(env) {
20
+ for (const func in GLOBALS) {
21
+ env.addGlobal(func, function (...args) {
22
+ return GLOBALS[func](...args);
23
+ });
24
+ }
25
+ for (const func in HASS_GLOBALS) {
26
+ env.addGlobal(func, function (...args) {
27
+ return HASS_GLOBALS[func](window.haNunjucks.hass, ...args);
28
+ });
29
+ }
30
+ for (const c in CONST_GLOBALS) {
31
+ env.addGlobal(c, CONST_GLOBALS[c]);
32
+ }
33
+ env.addGlobal('dt', dt);
34
+ env.addGlobal('date', date);
35
+ env.addGlobal('time', time);
36
+ env.addGlobal('datetime', datetime);
37
+ env.addGlobal('timedelta', timedelta);
38
+ return env;
39
+ }
40
+ const HASS_GLOBALS = {
41
+ // States
42
+ states,
43
+ is_state,
44
+ state_attr,
45
+ is_state_attr,
46
+ has_value,
47
+ // State Translated
48
+ state_translated,
49
+ attr_name_translated,
50
+ attr_value_translated,
51
+ // Groups
52
+ expand,
53
+ // Entities
54
+ is_hidden_entity,
55
+ // Devices
56
+ device_entities,
57
+ device_attr,
58
+ is_device_attr,
59
+ device_id,
60
+ device_name,
61
+ // Floors
62
+ floors,
63
+ floor_id,
64
+ floor_name,
65
+ floor_areas,
66
+ floor_entities,
67
+ // Areas
68
+ areas,
69
+ area_id,
70
+ area_name,
71
+ area_entities,
72
+ area_devices,
73
+ // Integrations
74
+ integration_entities,
75
+ // Labels
76
+ labels,
77
+ label_areas,
78
+ label_devices,
79
+ label_entities,
80
+ // Immediate If
81
+ iif,
82
+ // Distance
83
+ distance,
84
+ closest,
85
+ };
86
+ const GLOBALS = {
87
+ // Labels
88
+ label_id,
89
+ label_name,
90
+ label_description,
91
+ // Time
92
+ now,
93
+ utcnow,
94
+ today_at,
95
+ as_datetime,
96
+ as_timestamp,
97
+ as_local,
98
+ strptime,
99
+ relative_time,
100
+ time_since,
101
+ time_until,
102
+ as_timedelta,
103
+ date_translated,
104
+ time_translated,
105
+ datetime_translated,
106
+ // Numeric,
107
+ float,
108
+ is_number,
109
+ int,
110
+ bool,
111
+ log,
112
+ sin,
113
+ cos,
114
+ tan,
115
+ asin,
116
+ acos,
117
+ atan,
118
+ atan2,
119
+ sqrt,
120
+ max,
121
+ min,
122
+ average,
123
+ median,
124
+ statistical_mode,
125
+ number_translated,
126
+ // Type Conversions
127
+ set,
128
+ list,
129
+ str,
130
+ // Iterating Multiple Objects
131
+ zip,
132
+ // String fitlers
133
+ slugify,
134
+ // Miscellaneous
135
+ match_media,
136
+ };
137
+ const CONST_GLOBALS = {
138
+ e,
139
+ pi,
140
+ tau,
141
+ inf,
142
+ };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Call a handler function when a ready function returns true.
3
+ * If the ready function returns false, this method recursively recalls itself on a timeout.
4
+ * The function continues to recall itself with an exponentially increasing timeout until
5
+ * the ready function returns true or the timeout is exceeded.
6
+ * @param {() => void | Promise<void>} handler The function to call when ready
7
+ * @param {() => boolean | Promise<boolean>} handleReady The function to check and return true when ready
8
+ * @param {number} timeout The max time to wait in milliseconds, defaults to 20000
9
+ * @param {number} delay The initial delay in milliseconds, defaults to 10
10
+ */
11
+ export declare function handleWhenReady(handler: () => void | Promise<void>, handleReady: () => boolean | Promise<boolean>, timeout?: number, delay?: number, errorMessage?: string): Promise<void>;
12
+ /**
13
+ * Compare two semantic versions
14
+ * @param {string} v1
15
+ * @param {string} v2
16
+ * @returns {1 | 0 | -1}
17
+ */
18
+ export declare function compareVersions(v1: string, v2: string): 1 | 0 | -1;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Call a handler function when a ready function returns true.
3
+ * If the ready function returns false, this method recursively recalls itself on a timeout.
4
+ * The function continues to recall itself with an exponentially increasing timeout until
5
+ * the ready function returns true or the timeout is exceeded.
6
+ * @param {() => void | Promise<void>} handler The function to call when ready
7
+ * @param {() => boolean | Promise<boolean>} handleReady The function to check and return true when ready
8
+ * @param {number} timeout The max time to wait in milliseconds, defaults to 20000
9
+ * @param {number} delay The initial delay in milliseconds, defaults to 10
10
+ */
11
+ export async function handleWhenReady(handler, handleReady, timeout = 20000, delay = 10, errorMessage = `handleWhenReady ${timeout}ms timeout exceeded`) {
12
+ if (delay > timeout) {
13
+ console.error(errorMessage);
14
+ return;
15
+ }
16
+ if (!(await handleReady())) {
17
+ setTimeout(async () => await handleWhenReady(handler, handleReady, timeout, delay * 2), delay);
18
+ return;
19
+ }
20
+ await handler();
21
+ }
22
+ const prereleaseOrder = {
23
+ dev: 0,
24
+ alpha: 1,
25
+ beta: 2,
26
+ rc: 3,
27
+ release: 4,
28
+ };
29
+ /**
30
+ * Get Semantic Version object from version string
31
+ * @param {string} version
32
+ * @returns {SemanticVersion}
33
+ */
34
+ function getSemanticVersion(version) {
35
+ const [mmp, prerelease] = version.split('-');
36
+ const [major, minor, patch] = mmp.split('.').map(Number);
37
+ const [pOrder, pVersion] = prerelease?.split('.') || ['release', '0'];
38
+ return {
39
+ major: major || 0,
40
+ minor: minor || 0,
41
+ patch: patch || 0,
42
+ prerelease: prereleaseOrder[pOrder] ?? 4,
43
+ prereleaseVersion: isNaN(Number(pVersion)) ? 0 : Number(pVersion),
44
+ };
45
+ }
46
+ /**
47
+ * Compare two semantic versions
48
+ * @param {string} v1
49
+ * @param {string} v2
50
+ * @returns {1 | 0 | -1}
51
+ */
52
+ export function compareVersions(v1, v2) {
53
+ if (v1 == v2) {
54
+ return 0;
55
+ }
56
+ const sv1 = getSemanticVersion(v1);
57
+ const sv2 = getSemanticVersion(v2);
58
+ const fields = [
59
+ 'major',
60
+ 'minor',
61
+ 'patch',
62
+ 'prerelease',
63
+ 'prereleaseVersion',
64
+ ];
65
+ for (const field of fields) {
66
+ if (sv1[field] != sv2[field]) {
67
+ return sv1[field] > sv2[field] ? 1 : -1;
68
+ }
69
+ }
70
+ return 0;
71
+ }