@zoho_apptics/apptics-js-sdk 2.0.0-beta → 2.0.0-beta.1

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 (220) hide show
  1. package/CHANGELOG.md +111 -5
  2. package/README.md +399 -300
  3. package/dist/apptics.esm.min.js +2 -2
  4. package/dist/apptics.esm.min.js.map +1 -1
  5. package/dist/apptics.min.js +2 -2
  6. package/dist/apptics.min.js.map +1 -1
  7. package/dist/chunks/lifecycle-VYr43KcB.min.js +3 -0
  8. package/dist/chunks/lifecycle-VYr43KcB.min.js.map +1 -0
  9. package/dist/cjs/auto-init.d.ts +3 -3
  10. package/dist/cjs/auto-init.js +1 -1
  11. package/dist/cjs/core/attempts.js +1 -1
  12. package/dist/cjs/core/batch.js +2 -1
  13. package/dist/cjs/core/callsite.d.ts +6 -0
  14. package/dist/cjs/core/callsite.js +25 -3
  15. package/dist/cjs/core/consent.d.ts +5 -1
  16. package/dist/cjs/core/consent.js +8 -6
  17. package/dist/cjs/core/constants.d.ts +35 -10
  18. package/dist/cjs/core/constants.js +31 -15
  19. package/dist/cjs/core/db.d.ts +12 -4
  20. package/dist/cjs/core/db.js +167 -34
  21. package/dist/cjs/core/debug.js +1 -1
  22. package/dist/cjs/core/env.js +1 -1
  23. package/dist/cjs/core/framework-id.d.ts +1 -1
  24. package/dist/cjs/core/framework-id.js +3 -3
  25. package/dist/cjs/core/guard.d.ts +9 -0
  26. package/dist/cjs/core/guard.js +27 -13
  27. package/dist/cjs/core/hooks.d.ts +2 -4
  28. package/dist/cjs/core/hooks.js +2 -3
  29. package/dist/cjs/core/locks.d.ts +9 -0
  30. package/dist/cjs/core/locks.js +22 -0
  31. package/dist/cjs/core/logger.d.ts +3 -4
  32. package/dist/cjs/core/logger.js +4 -40
  33. package/dist/cjs/core/state.d.ts +3 -2
  34. package/dist/cjs/core/state.js +2 -2
  35. package/dist/cjs/core/storage.d.ts +20 -5
  36. package/dist/cjs/core/storage.js +115 -17
  37. package/dist/cjs/core/stylesheet.d.ts +8 -0
  38. package/dist/cjs/core/stylesheet.js +29 -0
  39. package/dist/cjs/core/transport.d.ts +2 -0
  40. package/dist/cjs/core/transport.js +19 -4
  41. package/dist/cjs/core/utils.js +1 -1
  42. package/dist/cjs/core/validate.js +2 -2
  43. package/dist/cjs/device/appversion.d.ts +1 -6
  44. package/dist/cjs/device/appversion.js +13 -1
  45. package/dist/cjs/device/index.d.ts +11 -0
  46. package/dist/cjs/device/index.js +120 -20
  47. package/dist/cjs/engagement/api-rules.d.ts +32 -67
  48. package/dist/cjs/engagement/api-rules.js +144 -157
  49. package/dist/cjs/engagement/auto-api.js +2 -2
  50. package/dist/cjs/engagement/auto-screen.d.ts +2 -0
  51. package/dist/cjs/engagement/auto-screen.js +67 -3
  52. package/dist/cjs/engagement/defined-events.js +1 -1
  53. package/dist/cjs/engagement/send.js +6 -1
  54. package/dist/cjs/engagement/session.d.ts +12 -3
  55. package/dist/cjs/engagement/session.js +161 -25
  56. package/dist/cjs/engagement/track.js +45 -20
  57. package/dist/cjs/errors/send.js +1 -1
  58. package/dist/cjs/errors/track.d.ts +1 -1
  59. package/dist/cjs/errors/track.js +46 -6
  60. package/dist/cjs/feedback/controls.d.ts +6 -0
  61. package/dist/cjs/feedback/controls.js +31 -1
  62. package/dist/cjs/feedback/index.d.ts +8 -7
  63. package/dist/cjs/feedback/index.js +32 -13
  64. package/dist/cjs/feedback/logs.d.ts +10 -5
  65. package/dist/cjs/feedback/logs.js +52 -13
  66. package/dist/cjs/feedback/quartz.d.ts +18 -0
  67. package/dist/cjs/feedback/quartz.js +105 -0
  68. package/dist/cjs/feedback/send.d.ts +3 -0
  69. package/dist/cjs/feedback/send.js +28 -3
  70. package/dist/cjs/feedback/styles.d.ts +10 -0
  71. package/dist/cjs/feedback/styles.js +8 -0
  72. package/dist/cjs/feedback/template.d.ts +1 -1
  73. package/dist/cjs/feedback/template.js +12 -12
  74. package/dist/cjs/feedback/ui.d.ts +14 -6
  75. package/dist/cjs/feedback/ui.js +126 -48
  76. package/dist/cjs/heatmap/send.js +1 -1
  77. package/dist/cjs/heatmap/track.d.ts +1 -1
  78. package/dist/cjs/heatmap/track.js +87 -16
  79. package/dist/cjs/index.d.ts +17 -63
  80. package/dist/cjs/index.js +104 -92
  81. package/dist/cjs/lifecycle.d.ts +8 -1
  82. package/dist/cjs/lifecycle.js +258 -62
  83. package/dist/cjs/remoteconfig/country.d.ts +4 -0
  84. package/dist/cjs/remoteconfig/country.js +73 -0
  85. package/dist/cjs/remoteconfig/custom.d.ts +7 -7
  86. package/dist/cjs/remoteconfig/custom.js +31 -51
  87. package/dist/cjs/remoteconfig/evaluate.d.ts +3 -3
  88. package/dist/cjs/remoteconfig/evaluate.js +56 -43
  89. package/dist/cjs/remoteconfig/fetch.d.ts +3 -3
  90. package/dist/cjs/remoteconfig/fetch.js +9 -23
  91. package/dist/cjs/remoteconfig/index.d.ts +10 -8
  92. package/dist/cjs/remoteconfig/index.js +65 -39
  93. package/dist/cjs/remoteconfig/store.js +1 -1
  94. package/dist/cjs/remoteconfig/tz-countries.d.ts +8 -0
  95. package/dist/cjs/remoteconfig/tz-countries.js +13 -0
  96. package/dist/cjs/remotelog/gate.d.ts +2 -11
  97. package/dist/cjs/remotelog/gate.js +9 -35
  98. package/dist/cjs/remotelog/index.d.ts +4 -21
  99. package/dist/cjs/remotelog/logger.d.ts +11 -17
  100. package/dist/cjs/remotelog/logger.js +30 -58
  101. package/dist/cjs/remotelog/send.js +10 -10
  102. package/dist/cjs/remotelogger/index.d.ts +12 -0
  103. package/dist/cjs/remotelogger/index.js +18 -0
  104. package/dist/cjs/scheduler.js +2 -2
  105. package/dist/cjs/types.d.ts +155 -82
  106. package/dist/cjs/user/index.js +11 -6
  107. package/dist/esm/auto-init.d.ts +3 -3
  108. package/dist/esm/auto-init.js +1 -1
  109. package/dist/esm/core/attempts.js +1 -1
  110. package/dist/esm/core/batch.js +2 -1
  111. package/dist/esm/core/callsite.d.ts +6 -0
  112. package/dist/esm/core/callsite.js +25 -4
  113. package/dist/esm/core/consent.d.ts +5 -1
  114. package/dist/esm/core/consent.js +9 -7
  115. package/dist/esm/core/constants.d.ts +35 -10
  116. package/dist/esm/core/constants.js +30 -15
  117. package/dist/esm/core/db.d.ts +12 -4
  118. package/dist/esm/core/db.js +164 -35
  119. package/dist/esm/core/debug.js +1 -1
  120. package/dist/esm/core/env.js +1 -1
  121. package/dist/esm/core/framework-id.d.ts +1 -1
  122. package/dist/esm/core/framework-id.js +3 -3
  123. package/dist/esm/core/guard.d.ts +9 -0
  124. package/dist/esm/core/guard.js +27 -14
  125. package/dist/esm/core/hooks.d.ts +2 -4
  126. package/dist/esm/core/hooks.js +2 -3
  127. package/dist/esm/core/locks.d.ts +9 -0
  128. package/dist/esm/core/locks.js +20 -0
  129. package/dist/esm/core/logger.d.ts +3 -4
  130. package/dist/esm/core/logger.js +4 -40
  131. package/dist/esm/core/state.d.ts +3 -2
  132. package/dist/esm/core/state.js +2 -2
  133. package/dist/esm/core/storage.d.ts +20 -5
  134. package/dist/esm/core/storage.js +113 -18
  135. package/dist/esm/core/stylesheet.d.ts +8 -0
  136. package/dist/esm/core/stylesheet.js +27 -0
  137. package/dist/esm/core/transport.d.ts +2 -0
  138. package/dist/esm/core/transport.js +19 -5
  139. package/dist/esm/core/utils.js +1 -1
  140. package/dist/esm/core/validate.js +2 -2
  141. package/dist/esm/device/appversion.d.ts +1 -6
  142. package/dist/esm/device/appversion.js +13 -2
  143. package/dist/esm/device/index.d.ts +11 -0
  144. package/dist/esm/device/index.js +123 -24
  145. package/dist/esm/engagement/api-rules.d.ts +32 -67
  146. package/dist/esm/engagement/api-rules.js +143 -155
  147. package/dist/esm/engagement/auto-api.js +3 -3
  148. package/dist/esm/engagement/auto-screen.d.ts +2 -0
  149. package/dist/esm/engagement/auto-screen.js +67 -4
  150. package/dist/esm/engagement/defined-events.js +1 -1
  151. package/dist/esm/engagement/send.js +6 -1
  152. package/dist/esm/engagement/session.d.ts +12 -3
  153. package/dist/esm/engagement/session.js +162 -29
  154. package/dist/esm/engagement/track.js +52 -27
  155. package/dist/esm/errors/send.js +1 -1
  156. package/dist/esm/errors/track.d.ts +1 -1
  157. package/dist/esm/errors/track.js +46 -6
  158. package/dist/esm/feedback/controls.d.ts +6 -0
  159. package/dist/esm/feedback/controls.js +31 -2
  160. package/dist/esm/feedback/index.d.ts +8 -7
  161. package/dist/esm/feedback/index.js +34 -13
  162. package/dist/esm/feedback/logs.d.ts +10 -5
  163. package/dist/esm/feedback/logs.js +54 -15
  164. package/dist/esm/feedback/quartz.d.ts +18 -0
  165. package/dist/esm/feedback/quartz.js +99 -0
  166. package/dist/esm/feedback/send.d.ts +3 -0
  167. package/dist/esm/feedback/send.js +28 -5
  168. package/dist/esm/feedback/styles.d.ts +10 -0
  169. package/dist/esm/feedback/styles.js +4 -0
  170. package/dist/esm/feedback/template.d.ts +1 -1
  171. package/dist/esm/feedback/template.js +12 -12
  172. package/dist/esm/feedback/ui.d.ts +14 -6
  173. package/dist/esm/feedback/ui.js +126 -49
  174. package/dist/esm/heatmap/send.js +1 -1
  175. package/dist/esm/heatmap/track.d.ts +1 -1
  176. package/dist/esm/heatmap/track.js +87 -16
  177. package/dist/esm/index.d.ts +17 -63
  178. package/dist/esm/index.js +108 -80
  179. package/dist/esm/lifecycle.d.ts +8 -1
  180. package/dist/esm/lifecycle.js +266 -71
  181. package/dist/esm/remoteconfig/country.d.ts +4 -0
  182. package/dist/esm/remoteconfig/country.js +70 -0
  183. package/dist/esm/remoteconfig/custom.d.ts +7 -7
  184. package/dist/esm/remoteconfig/custom.js +32 -52
  185. package/dist/esm/remoteconfig/evaluate.d.ts +3 -3
  186. package/dist/esm/remoteconfig/evaluate.js +57 -44
  187. package/dist/esm/remoteconfig/fetch.d.ts +3 -3
  188. package/dist/esm/remoteconfig/fetch.js +9 -23
  189. package/dist/esm/remoteconfig/index.d.ts +10 -8
  190. package/dist/esm/remoteconfig/index.js +66 -40
  191. package/dist/esm/remoteconfig/store.js +1 -1
  192. package/dist/esm/remoteconfig/tz-countries.d.ts +8 -0
  193. package/dist/esm/remoteconfig/tz-countries.js +11 -0
  194. package/dist/esm/remotelog/gate.d.ts +2 -11
  195. package/dist/esm/remotelog/gate.js +10 -32
  196. package/dist/esm/remotelog/index.d.ts +4 -21
  197. package/dist/esm/remotelog/logger.d.ts +11 -17
  198. package/dist/esm/remotelog/logger.js +32 -60
  199. package/dist/esm/remotelog/send.js +12 -12
  200. package/dist/esm/remotelogger/index.d.ts +12 -0
  201. package/dist/esm/remotelogger/index.js +13 -0
  202. package/dist/esm/scheduler.js +2 -2
  203. package/dist/esm/types.d.ts +155 -82
  204. package/dist/esm/user/index.js +12 -6
  205. package/dist/feedback.esm.min.js +2 -2
  206. package/dist/feedback.esm.min.js.map +1 -1
  207. package/package.json +14 -16
  208. package/dist/chunks/batch-BU_mTpm1.min.js +0 -3
  209. package/dist/chunks/batch-BU_mTpm1.min.js.map +0 -1
  210. package/dist/chunks/logs-Bea5zUW_.min.js +0 -3
  211. package/dist/chunks/logs-Bea5zUW_.min.js.map +0 -1
  212. package/dist/cjs/heatmap/index.d.ts +0 -16
  213. package/dist/cjs/heatmap/index.js +0 -22
  214. package/dist/cjs/remotelog/index.js +0 -55
  215. package/dist/esm/heatmap/index.d.ts +0 -16
  216. package/dist/esm/heatmap/index.js +0 -17
  217. package/dist/esm/remotelog/index.js +0 -51
  218. package/dist/heatmap.esm.min.js +0 -3
  219. package/dist/heatmap.esm.min.js.map +0 -1
  220. package/dist/style.css +0 -1
@@ -1,4 +1,4 @@
1
- /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
2
2
  'use strict';
3
3
 
4
4
  var storage = require('../core/storage.js');
@@ -6,73 +6,53 @@ var logger = require('../core/logger.js');
6
6
  var store = require('./store.js');
7
7
 
8
8
  /**
9
- * Custom condition values, as Android's AppticsRemoteConfig.setCustomConditionValue: the app says
10
- * what this device is for a custom criteria the console defines (a condition key with a list of
11
- * values), and a condition on that key matches when the value set here is one of the listed ones.
9
+ * Custom condition values: a console condition on the custom criteria (`custom_sdk_value`) is
10
+ * answered by what the app says this device is for that condition, by the condition's name:
12
11
  *
13
- * AppticsRemoteConfig.setCustomConditionValue('plan_tier', 'gold');
12
+ * AppticsRemoteConfig.setCustomConditionValue('is_custom', 'custom_color');
13
+ * AppticsRemoteConfig.setCustomConditionValue('is_custom', 'gold,platinum'); // several
14
14
  *
15
- * The rules are evaluated on the device, so the values have to be here on the next visit too:
16
- * they are stored, and a value set on this page wins over a stored one. Setting one before
17
- * storage has loaded — before init(), say — is kept in memory and saved once it has.
18
- *
19
- * Assumed wire format, until the server confirms it: a custom criteria arrives with the custom
20
- * key as its `key` and operator 1 ("is one of"), the same shape as the built-in criteria. A
21
- * different shape fails closed — the condition does not match and the default is used.
15
+ * The condition matches when one of the comma separated values is one of the values it lists.
16
+ * Values are for this page: an app sets them as it starts, as it would any other app state.
22
17
  */
23
- const STORE_KEY = 'remoteconfig_custom'; // no i18n
24
- /** This page's values; null marks a key removed here, so a stored value no longer counts. */
25
18
  var mine = {};
26
- function stored() {
27
- var saved = storage.user_defaults.item(STORE_KEY);
28
- return saved && typeof saved === 'object' ? saved : {}; // no i18n
29
- }
30
- /** The value set for a custom criteria key, or undefined when none is. */
31
- function customConditionValue(key) {
32
- if (Object.prototype.hasOwnProperty.call(mine, key)) {
33
- var here = mine[key];
34
- return here === null ? undefined : here;
35
- }
36
- var saved = stored();
37
- return Object.prototype.hasOwnProperty.call(saved, key) ? saved[key] : undefined;
19
+ /** The values set for a condition, by its name; empty when none are. */
20
+ function customConditionValues(conditionname) {
21
+ var name = String(conditionname || '').trim(); // no i18n
22
+ return Object.prototype.hasOwnProperty.call(mine, name) ? mine[name] : [];
38
23
  }
39
24
  /**
40
- * Sets what this device is for a custom criteria, or removes it with an empty value. Re-applies
41
- * the stored rules as soon as storage is ready, so the next read sees the new result without a
42
- * fetch.
25
+ * Sets what this device is for a custom condition, by its name, as comma separated values; an
26
+ * empty value removes it. Re-applies the stored rules once storage is ready, so the next read sees
27
+ * the new result without a fetch.
43
28
  */
44
- function setCustomConditionValue(key, value) {
45
- var name = typeof key === 'string' ? key.trim() : ''; // no i18n
29
+ function setCustomConditionValue(conditionname, value) {
30
+ var name = typeof conditionname === 'string' ? conditionname.trim() : ''; // no i18n
46
31
  if (name === '') { // no i18n
47
- logger.Console.warn('AppticsRemoteConfig.setCustomConditionValue: a condition key is required'); // no i18n
32
+ logger.Console.warn('AppticsRemoteConfig.setCustomConditionValue: a condition name is required'); // no i18n
48
33
  return;
49
34
  }
50
- var text = value === null || value === undefined ? '' : String(value).trim(); // no i18n
51
- mine[name] = text === '' ? null : text; // no i18n
35
+ var values = (value === null || value === undefined ? '' : String(value)).split(',') // no i18n
36
+ .map(function (one) { return one.trim(); })
37
+ .filter(function (one, i, all) { return one !== '' && all.indexOf(one) === i; }); // no i18n
38
+ if (values.length === 0) {
39
+ delete mine[name];
40
+ }
41
+ else {
42
+ mine[name] = values;
43
+ }
52
44
  storage.storageReady().then(function (backend) {
53
- if (!backend) {
54
- return;
55
- }
56
- var saved = stored();
57
- Object.keys(mine).forEach(function (one) {
58
- var here = mine[one];
59
- if (here === null || here === undefined) {
60
- delete saved[one];
61
- }
62
- else {
63
- saved[one] = here;
64
- }
65
- });
66
- storage.user_defaults.add(STORE_KEY, saved);
67
45
  // only once storage has loaded: re-resolving before it would read an empty rule set and keep it
68
- store.reresolve();
46
+ if (backend) {
47
+ store.reresolve();
48
+ }
69
49
  });
70
50
  }
71
- /** reset(): forgets the values set on this page; the stored ones go with the rest of storage. */
51
+ /** reset(): forgets the values set on this page. */
72
52
  function clearCustomConditionValues() {
73
53
  mine = {};
74
54
  }
75
55
 
76
56
  exports.clearCustomConditionValues = clearCustomConditionValues;
77
- exports.customConditionValue = customConditionValue;
57
+ exports.customConditionValues = customConditionValues;
78
58
  exports.setCustomConditionValue = setCustomConditionValue;
@@ -10,10 +10,10 @@ export declare function conditionMatches(condition: Dict): boolean;
10
10
  /**
11
11
  * The value of one parameter on this device, as the string the server stores it as.
12
12
  *
13
- * `byId` is every condition the answer carried, keyed by its id — the mapping on the parameter
14
- * names a condition but does not repeat its criteria.
13
+ * `conditions` is `all_condition` as the server sent it: its order is the order they are tried
14
+ * in. The parameter's own `conditions` say which of them apply to it, and with what value.
15
15
  */
16
- export declare function resolve(parameter: Dict, byId: Record<string, Dict>): string;
16
+ export declare function resolve(parameter: Dict, conditions: Dict[]): string;
17
17
  /**
18
18
  * Every parameter resolved against this device, as a flat name -> value map.
19
19
  *
@@ -1,10 +1,11 @@
1
- /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
2
2
  'use strict';
3
3
 
4
4
  var logger = require('../core/logger.js');
5
5
  var state = require('../core/state.js');
6
6
  var utils = require('../core/utils.js');
7
7
  var custom = require('./custom.js');
8
+ var country = require('./country.js');
8
9
 
9
10
  /**
10
11
  * Working out what a parameter is worth on this device.
@@ -13,11 +14,17 @@ var custom = require('./custom.js');
13
14
  * condition with its criteria, and the mapping between them. Resolving it here rather than on
14
15
  * the server is what lets a value be read with no network at all on the next visit.
15
16
  *
16
- * A parameter resolves by walking its conditions in `conditionorder` and taking the value of the
17
- * first one that matches this device. Nothing matches, or nothing is mapped: the default.
17
+ * A parameter resolves by walking the conditions in the order of `all_condition`, the console's
18
+ * own order, and taking the value the parameter maps to the first one that both applies to it and
19
+ * matches this device. A condition matches when every one of its criteria does. Nothing matches,
20
+ * or nothing is mapped: the parameter's default value.
21
+ *
22
+ * Criteria are answered from what the browser knows about itself (app version, device type,
23
+ * country...), except a custom one (`custom_sdk_value`): that is answered by what the app set with
24
+ * setCustomConditionValue(conditionname, 'a,b'), and matches when one of those values is listed.
18
25
  *
19
26
  * Everything fails closed. An operator we do not recognise, a criteria key we cannot answer, a
20
- * condition the parameter names but the server did not send — each one means "does not match",
27
+ * condition the parameter names but the server did not send: each one means "does not match",
21
28
  * never "matches". A config system that guesses hands an app a value its author never chose, on
22
29
  * a device they cannot see, and that is far worse than falling back to the default.
23
30
  */
@@ -41,9 +48,12 @@ const FACTS = Object.freeze({
41
48
  osversion: function () { return String(state._ZAP._device_info.osversion || ''); }, // no i18n
42
49
  devicetype: function () { return String(state._ZAP._device_info.devicetype || ''); }, // no i18n
43
50
  language: function () { return String(navigator.language || ''); }, // no i18n
51
+ country: country.deviceCountry,
44
52
  customergroupid: function () { return String(state._ZAP._user_info.groupid || ''); }, // no i18n
45
53
  userid: function () { return String(state._ZAP._user_info.userid || ''); }, // no i18n
46
54
  });
55
+ /** The criteria key of a custom condition, answered by setCustomConditionValue. */
56
+ const CUSTOM_KEY = 'custom_sdk_value'; // no i18n
47
57
  /** Codes and keys already complained about, so one unknown rule is not a log per read. */
48
58
  var reported = {};
49
59
  function sayOnce(key, message) {
@@ -65,8 +75,8 @@ function valuesOf(criteria) {
65
75
  }
66
76
  return raw.map(function (one) { return String(one); });
67
77
  }
68
- /** Whether one criteria holds on this device. */
69
- function criteriaMatches(criteria) {
78
+ /** Whether one criteria holds on this device; `conditionname` answers a custom criteria. */
79
+ function criteriaMatches(criteria, conditionname) {
70
80
  var key = String(criteria.key || ''); // no i18n
71
81
  var operator = OPERATORS[String(criteria.status)];
72
82
  if (operator === undefined) {
@@ -74,21 +84,31 @@ function criteriaMatches(criteria) {
74
84
  + '", so conditions using it will not match'); // no i18n
75
85
  return false;
76
86
  }
87
+ var listed = valuesOf(criteria);
88
+ if (key === CUSTOM_KEY) {
89
+ var mine = custom.customConditionValues(conditionname);
90
+ if (mine.length === 0) {
91
+ sayOnce('custom:' + conditionname, 'AppticsRemoteConfig: no value for the custom condition "' + conditionname // no i18n
92
+ + '"; set one with setCustomConditionValue, or it will not match'); // no i18n
93
+ return false;
94
+ }
95
+ // 'in': one of the values the app set is one of the listed ones
96
+ return mine.some(function (one) { return listed.indexOf(one) !== -1; });
97
+ }
77
98
  var fact = FACTS[key];
78
- // not something a browser knows about itself: a custom criteria, answered by what the app set
79
- // with setCustomConditionValue
80
- var actual = fact !== undefined ? fact() : custom.customConditionValue(key);
81
- if (actual === undefined) {
82
- sayOnce('key:' + key, 'AppticsRemoteConfig: no value for criteria "' + key // no i18n
83
- + '"; set one with setCustomConditionValue, or conditions using it will not match'); // no i18n
99
+ if (fact === undefined) {
100
+ // not something a browser knows about itself
101
+ sayOnce('key:' + key, 'AppticsRemoteConfig: unknown criteria "' + key // no i18n
102
+ + '", so conditions using it will not match'); // no i18n
84
103
  return false;
85
104
  }
105
+ var actual = fact();
86
106
  if (actual === '') {
87
107
  return false;
88
108
  }
89
109
  // 'in': the device's value is one of the listed ones. Compared as strings because that is
90
110
  // what both sides are - '1.1' is a version, not the number 1.1
91
- return valuesOf(criteria).indexOf(actual) !== -1;
111
+ return listed.indexOf(actual) !== -1;
92
112
  }
93
113
  /**
94
114
  * Whether a condition holds: every one of its criteria must. The template requires at least one
@@ -101,43 +121,40 @@ function conditionMatches(condition) {
101
121
  return false;
102
122
  }
103
123
  for (var i = 0; i < criterias.length; i++) {
104
- if (!criteriaMatches(criterias[i])) {
124
+ if (!criteriaMatches(criterias[i], String(condition.conditionname || ''))) { // no i18n
105
125
  return false;
106
126
  }
107
127
  }
108
128
  return true;
109
129
  }
110
- /** The conditions a parameter names, in the order the console put them in. */
111
- function orderedConditions(parameter) {
112
- var mapped = parameter.conditions;
113
- if (!Array.isArray(mapped)) {
114
- return [];
115
- }
116
- return mapped.slice().sort(function (a, b) {
117
- return Number(a.conditionorder || 0) - Number(b.conditionorder || 0); // no i18n
118
- });
119
- }
120
130
  /**
121
131
  * The value of one parameter on this device, as the string the server stores it as.
122
132
  *
123
- * `byId` is every condition the answer carried, keyed by its id — the mapping on the parameter
124
- * names a condition but does not repeat its criteria.
133
+ * `conditions` is `all_condition` as the server sent it: its order is the order they are tried
134
+ * in. The parameter's own `conditions` say which of them apply to it, and with what value.
125
135
  */
126
- function resolve(parameter, byId) {
127
- var mapped = orderedConditions(parameter);
128
- for (var i = 0; i < mapped.length; i++) {
129
- var link = mapped[i];
130
- var condition = byId[String(link.conditionid)];
131
- if (condition === undefined) {
132
- // the parameter points at a condition the answer did not include
133
- sayOnce('missing:' + link.conditionid, 'AppticsRemoteConfig: parameter "' + parameter.paramname // no i18n
134
- + '" uses condition ' + link.conditionid + ', which the server did not send'); // no i18n
135
- continue;
136
- }
137
- if (conditionMatches(condition)) {
136
+ function resolve(parameter, conditions) {
137
+ var links = {};
138
+ (Array.isArray(parameter.conditions) ? parameter.conditions : []).forEach(function (link) {
139
+ links[String(link.conditionid)] = link;
140
+ });
141
+ var sent = {};
142
+ for (var i = 0; i < conditions.length; i++) {
143
+ var condition = conditions[i];
144
+ var id = String(condition.conditionid);
145
+ sent[id] = true;
146
+ var link = links[id];
147
+ if (link !== undefined && conditionMatches(condition)) {
138
148
  return String(link.value === undefined || link.value === null ? '' : link.value);
139
149
  }
140
150
  }
151
+ Object.keys(links).forEach(function (id) {
152
+ if (!sent[id]) {
153
+ // the parameter points at a condition the answer did not include
154
+ sayOnce('missing:' + id, 'AppticsRemoteConfig: parameter "' + parameter.paramname // no i18n
155
+ + '" uses condition ' + id + ', which the server did not send'); // no i18n
156
+ }
157
+ });
141
158
  return String(parameter.defaultvalue === undefined || parameter.defaultvalue === null ? '' : parameter.defaultvalue);
142
159
  }
143
160
  /**
@@ -151,16 +168,12 @@ function resolveAll(remoteconfig) {
151
168
  var out = {};
152
169
  var parameters = Array.isArray(remoteconfig.all_parameter) ? remoteconfig.all_parameter : [];
153
170
  var conditions = Array.isArray(remoteconfig.all_condition) ? remoteconfig.all_condition : [];
154
- var byId = {};
155
- conditions.forEach(function (condition) {
156
- byId[String(condition.conditionid)] = condition;
157
- });
158
171
  parameters.forEach(function (parameter) {
159
172
  var name = String(parameter.paramname || ''); // no i18n
160
173
  if (name === '') {
161
174
  return;
162
175
  }
163
- out[name] = resolve(parameter, byId);
176
+ out[name] = resolve(parameter, conditions);
164
177
  });
165
178
  return out;
166
179
  }
@@ -15,10 +15,10 @@ export declare function fetchRemoteConfig(): Promise<Record<string, unknown>>;
15
15
  export declare function resetRemoteConfig(): void;
16
16
  /**
17
17
  * Makes sure the values are this page's own: from a fetch that just succeeded, or one within
18
- * CACHE_MS. Resolves true when they are, false when the fetch failed, could not be made, or was
19
- * past the coldFetch limit — the caller then decides whether stored values will do. Never rejects.
18
+ * CACHE_MS. Resolves true when they are, false when the fetch failed or could not be made — the
19
+ * caller then decides whether stored values will do. Never rejects.
20
20
  *
21
21
  * Waits for start-up and for the device to be registered, which a first visit is still doing
22
22
  * when ready() resolves: getupdates is refused without the device ids.
23
23
  */
24
- export declare function obtain(coldFetch?: boolean): Promise<boolean>;
24
+ export declare function obtain(): Promise<boolean>;
@@ -1,4 +1,4 @@
1
- /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
2
2
  'use strict';
3
3
 
4
4
  var constants = require('../core/constants.js');
@@ -9,8 +9,8 @@ var utils = require('../core/utils.js');
9
9
  var transport = require('../core/transport.js');
10
10
  var index = require('../device/index.js');
11
11
  var lifecycle = require('../lifecycle.js');
12
- var store = require('./store.js');
13
12
  var custom = require('./custom.js');
13
+ var store = require('./store.js');
14
14
 
15
15
  /**
16
16
  * The getupdates call.
@@ -34,16 +34,11 @@ var inFlight = null;
34
34
  var generation = 0;
35
35
  /**
36
36
  * How long a fetch that succeeded on this page answers for later ones, as on Android: a value
37
- * read on every render must not be a request on every render. coldFetch skips it.
37
+ * read on every render must not be a request on every render.
38
38
  */
39
39
  const CACHE_MS = 5 * 60 * 1000;
40
- /** coldFetch goes to the network every time, so it is limited: three in any minute, as on Android. */
41
- const COLD_LIMIT = 3;
42
- const COLD_WINDOW_MS = 60 * 1000;
43
40
  /** When a fetch on this page last succeeded; 0 until one has. */
44
41
  var fetchedAt = 0;
45
- /** When the coldFetch calls of the last minute went out. */
46
- var coldCalls = [];
47
42
  /**
48
43
  * Whether remote config is still worth asking about.
49
44
  *
@@ -156,36 +151,27 @@ function resetRemoteConfig() {
156
151
  generation++;
157
152
  inFlight = null;
158
153
  fetchedAt = 0;
159
- coldCalls = [];
160
154
  state._ZAP._remoteConfigReported = true;
161
155
  custom.clearCustomConditionValues();
162
156
  store.clearRemoteConfig();
163
157
  }
164
158
  /**
165
159
  * Makes sure the values are this page's own: from a fetch that just succeeded, or one within
166
- * CACHE_MS. Resolves true when they are, false when the fetch failed, could not be made, or was
167
- * past the coldFetch limit — the caller then decides whether stored values will do. Never rejects.
160
+ * CACHE_MS. Resolves true when they are, false when the fetch failed or could not be made — the
161
+ * caller then decides whether stored values will do. Never rejects.
168
162
  *
169
163
  * Waits for start-up and for the device to be registered, which a first visit is still doing
170
164
  * when ready() resolves: getupdates is refused without the device ids.
171
165
  */
172
- function obtain(coldFetch) {
166
+ function obtain() {
173
167
  return lifecycle.ready().then(function (running) {
174
168
  if (!running) {
175
169
  return false;
176
170
  }
177
171
  var now = utils.nowMs();
178
- if (coldFetch !== true && fetchedAt > 0 && now - fetchedAt < CACHE_MS) {
172
+ if (fetchedAt > 0 && now - fetchedAt < CACHE_MS) {
179
173
  return true;
180
174
  }
181
- if (coldFetch === true) {
182
- coldCalls = coldCalls.filter(function (at) { return now - at < COLD_WINDOW_MS; });
183
- if (coldCalls.length >= COLD_LIMIT) {
184
- logger.Console.warn(LABEL + ': coldFetch is limited to ' + COLD_LIMIT + ' a minute; this one is not sent'); // no i18n
185
- return false;
186
- }
187
- coldCalls.push(now);
188
- }
189
175
  return index.deviceReady().then(function () {
190
176
  return fetchRemoteConfig();
191
177
  }).then(function () {
@@ -198,11 +184,11 @@ function obtain(coldFetch) {
198
184
  }
199
185
  /** Start-up's own fetch, so values are this session's without the app asking. */
200
186
  function fetchOnStart() {
201
- obtain(false);
187
+ obtain();
202
188
  }
203
189
  hooks.hooks.resetRemoteConfig = resetRemoteConfig;
204
190
  hooks.hooks.remoteConfigStarted = fetchOnStart;
205
- // a condition on the customer group answers differently once AppticsSetUser has named one
191
+ // a condition on the customer group answers differently once AppticsUser.setUser has named one
206
192
  hooks.hooks.remoteConfigUserChanged = store.reresolve;
207
193
  // imported after start-up has already finished (a lazy import, say): fetch now, as start-up would have
208
194
  if (state._ZAP._ready) {
@@ -1,13 +1,15 @@
1
- /** Android's AppticsRemoteConfig: fetchValue, fetchValues, setCustomConditionValue, setFallbackWithOfflineValue. */
1
+ /** AppticsRemoteConfig: fetchValue, fetchValues and setCustomConditionValue, each with the parameter names the console shows. */
2
2
  export declare const AppticsRemoteConfig: {
3
- fetchValue: (name: string, callback?: (value: string | null) => void, coldFetch?: boolean) => Promise<string | null>;
4
- fetchValues: (defaults: Record<string, string | null>, callback?: (values: Record<string, string | null>) => void, coldFetch?: boolean) => Promise<Record<string, string | null>>;
5
- /** Whether a failed fetch answers with the values fetched before (the default) or with null. */
6
- setFallbackWithOfflineValue: (enabled?: boolean) => void;
3
+ fetchValue: (name: string, callback?: (value: string | null) => void) => Promise<string | null>;
4
+ /** The parameters named, or every parameter when none are: name -> value, null when there is none. */
5
+ fetchValues: {
6
+ (names?: string[], callback?: (values: Record<string, string | null>) => void): Promise<Record<string, string | null>>;
7
+ (callback: (values: Record<string, string | null>) => void): Promise<Record<string, string | null>>;
8
+ };
7
9
  /**
8
- * What this device is for a custom criteria the console defines, as Android's
9
- * setCustomConditionValue; an empty value removes it. Kept across visits.
10
+ * What this device is for a custom condition, by the condition's name, as comma separated
11
+ * values: it matches when one of them is listed. An empty value removes it.
10
12
  */
11
- setCustomConditionValue: (key: string, value: string | number | boolean | null) => void;
13
+ setCustomConditionValue: (conditionname: string, value: string | number | boolean | null) => void;
12
14
  };
13
15
  export default AppticsRemoteConfig;
@@ -1,4 +1,4 @@
1
- /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
2
2
  'use strict';
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
@@ -13,30 +13,21 @@ var store = require('./store.js');
13
13
  * Remote config, shipped as its own entry point:
14
14
  * import { AppticsRemoteConfig } from '@zoho_apptics/apptics-js-sdk/remote-config';
15
15
  *
16
- * Four calls, as on Android: fetchValue(name) and fetchValues({ name: default }) read parameters,
17
- * setCustomConditionValue says what this device is for a custom criteria, and
18
- * setFallbackWithOfflineValue chooses what a failed fetch answers with. The rule set is stored and
19
- * resolved on the device, so a fetch within five minutes, or a failed one with the offline fallback
20
- * on, answers without waiting on the network. The SDK fetches on start-up, and re-applies the rules
21
- * on its own when AppticsSetUser or setCustomConditionValue changes what this device is.
16
+ * fetchValue(name) reads one parameter, fetchValues(['a', 'b']) several, and fetchValues() every
17
+ * parameter the console has. Each parameter's value is the console's: the value of the first
18
+ * condition, in the console's order, that this device matches, else the parameter's default value.
19
+ * setCustomConditionValue(conditionname, 'a,b') answers the custom conditions.
20
+ * The rule set is stored and resolved on the device, so a fetch within five minutes answers without
21
+ * waiting on the network, and a failed one answers with the values fetched before. The SDK fetches
22
+ * on start-up, and re-applies the rules on its own when AppticsUser.setUser changes the user.
22
23
  *
23
- * A parameter the console does not have is null from fetchValue and the caller's default from
24
- * fetchValues, never undefined: a config system whose failure mode is `undefined` moves the
25
- * problem into the app's rendering code.
24
+ * A name the console does not have is null, never undefined: a config system whose failure mode
25
+ * is `undefined` moves the problem into the app's rendering code.
26
26
  */
27
27
  function raw(name) {
28
28
  var values = store.all();
29
29
  return Object.prototype.hasOwnProperty.call(values, name) ? values[name] : undefined;
30
30
  }
31
- /**
32
- * Whether a fetch that failed still answers with what was fetched before. On by default, as
33
- * `fallbackWithOfflineValue` is on Android: a page offline for a moment keeps its config.
34
- */
35
- var fallbackWithOfflineValue = true;
36
- /** Off: a failed fetch answers with null, or the caller's defaults, rather than stored values. */
37
- function setFallbackWithOfflineValue(enabled) {
38
- fallbackWithOfflineValue = typeof enabled === 'boolean' ? enabled : true; // no i18n
39
- }
40
31
  /** Hands a result to the app's callback, which must not be able to break the Promise. */
41
32
  function answer(value, callback) {
42
33
  if (typeof callback === 'function') { // no i18n
@@ -51,39 +42,74 @@ function answer(value, callback) {
51
42
  }
52
43
  /**
53
44
  * One parameter, fetched for this page, as Android's fetchValue: resolves with its value, or null
54
- * when the console has no such parameter or the fetch failed with the offline fallback off.
45
+ * when the console has no such parameter. A failed fetch answers with the value fetched before.
55
46
  */
56
- function fetchValue(name, callback, coldFetch) {
57
- return fetch.obtain(coldFetch).then(function (fresh) {
58
- var value = fresh || fallbackWithOfflineValue ? raw(name) : undefined;
47
+ function fetchValue(name, callback) {
48
+ return fetch.obtain().then(function () {
49
+ var value = raw(name);
59
50
  return answer(value === undefined ? null : value, callback);
60
51
  });
61
52
  }
62
53
  /**
63
- * Several parameters at once, as Android's fetchValues: `defaults` maps each name to the value to
64
- * use when there is none, and the result has exactly those names.
54
+ * Several parameters at once: `names` lists the ones wanted, and the result has exactly those
55
+ * names, null for one the console does not have. With no names (or an empty list), every
56
+ * parameter the console has. A callback may come first when there are no names.
65
57
  */
66
- function fetchValues(defaults, callback, coldFetch) {
67
- return fetch.obtain(coldFetch).then(function (fresh) {
58
+ function fetchValues(names, callback) {
59
+ if (typeof names === 'function') { // no i18n
60
+ // fetchValues(callback)
61
+ callback = names;
62
+ names = undefined;
63
+ }
64
+ var wanted = wantedNames(names);
65
+ var done = typeof callback === 'function' ? callback : undefined; // no i18n
66
+ return fetch.obtain().then(function () {
67
+ var values = store.all();
68
68
  var out = {};
69
- Object.keys(defaults || {}).forEach(function (name) {
70
- var value = fresh || fallbackWithOfflineValue ? raw(name) : undefined;
71
- out[name] = value === undefined ? defaults[name] : value;
69
+ (wanted === null ? Object.keys(values) : wanted).forEach(function (name) {
70
+ var value = raw(name);
71
+ out[name] = value === undefined ? null : value;
72
72
  });
73
- return answer(out, callback);
73
+ return answer(out, done);
74
+ });
75
+ }
76
+ /** The names asked for, or null for every parameter. Anything but a list of names counts as none. */
77
+ function wantedNames(names) {
78
+ if (names === undefined || names === null) {
79
+ return null;
80
+ }
81
+ if (!Array.isArray(names)) {
82
+ logger.Console.warn('AppticsRemoteConfig.fetchValues: takes a list of parameter names, as fetchValues([\'a\', \'b\']); answering with every parameter'); // no i18n
83
+ return null;
84
+ }
85
+ var out = [];
86
+ names.forEach(function (name) {
87
+ var one = typeof name === 'string' ? name.trim() : ''; // no i18n
88
+ if (one !== '' && out.indexOf(one) === -1) { // no i18n
89
+ out.push(one);
90
+ }
74
91
  });
92
+ return out.length === 0 ? null : out;
75
93
  }
76
- /** Android's AppticsRemoteConfig: fetchValue, fetchValues, setCustomConditionValue, setFallbackWithOfflineValue. */
94
+ const fetchValueGuarded = guard.guard('AppticsRemoteConfig.fetchValue', fetchValue); // no i18n
95
+ const fetchValuesGuarded = guard.guard('AppticsRemoteConfig.fetchValues', fetchValues); // no i18n
96
+ const setCustomConditionValueGuarded = guard.guard('AppticsRemoteConfig.setCustomConditionValue', custom.setCustomConditionValue); // no i18n
97
+ /** AppticsRemoteConfig: fetchValue, fetchValues and setCustomConditionValue, each with the parameter names the console shows. */
77
98
  const AppticsRemoteConfig = {
78
- fetchValue: guard.guard('AppticsRemoteConfig.fetchValue', fetchValue), // no i18n
79
- fetchValues: guard.guard('AppticsRemoteConfig.fetchValues', fetchValues), // no i18n
80
- /** Whether a failed fetch answers with the values fetched before (the default) or with null. */
81
- setFallbackWithOfflineValue: guard.guard('AppticsRemoteConfig.setFallbackWithOfflineValue', setFallbackWithOfflineValue), // no i18n
99
+ fetchValue: function fetchValue(name, callback) {
100
+ return guard.forward(fetchValueGuarded, arguments);
101
+ },
102
+ /** The parameters named, or every parameter when none are: name -> value, null when there is none. */
103
+ fetchValues: function fetchValues(names, callback) {
104
+ return guard.forward(fetchValuesGuarded, arguments);
105
+ }, // no i18n
82
106
  /**
83
- * What this device is for a custom criteria the console defines, as Android's
84
- * setCustomConditionValue; an empty value removes it. Kept across visits.
107
+ * What this device is for a custom condition, by the condition's name, as comma separated
108
+ * values: it matches when one of them is listed. An empty value removes it.
85
109
  */
86
- setCustomConditionValue: guard.guard('AppticsRemoteConfig.setCustomConditionValue', custom.setCustomConditionValue), // no i18n
110
+ setCustomConditionValue: function setCustomConditionValue(conditionname, value) {
111
+ guard.forward(setCustomConditionValueGuarded, arguments);
112
+ },
87
113
  };
88
114
 
89
115
  exports.AppticsRemoteConfig = AppticsRemoteConfig;
@@ -1,4 +1,4 @@
1
- /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta | (c) Zoho Corporation Private Limited | see LICENSE */
1
+ /*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.1 | (c) Zoho Corporation Private Limited | see LICENSE */
2
2
  'use strict';
3
3
 
4
4
  var logger = require('../core/logger.js');
@@ -0,0 +1,8 @@
1
+ /**
2
+ * The country of every IANA time zone, by its ISO 3166 code: generated by
3
+ * scripts/tz-countries.mjs from tzdata 2026d-rearguard (zone.tab, and the old names its links keep).
4
+ * Do not edit by hand.
5
+ *
6
+ * Packed as "CC:Area/City,City|Area/City;CC:...": a country, then its zones grouped by area.
7
+ */
8
+ export declare const TZ_COUNTRIES = "AD:Europe/Andorra;AE:Asia/Dubai;AF:Asia/Kabul;AG:America/Antigua;AI:America/Anguilla;AL:Europe/Tirane;AM:Asia/Yerevan;AO:Africa/Luanda;AQ:Antarctica/Casey,Davis,DumontDUrville,Mawson,McMurdo,Palmer,Rothera,Syowa,Troll,Vostok;AR:America/Argentina/Buenos_Aires,Argentina/Catamarca,Argentina/ComodRivadavia,Argentina/Cordoba,Argentina/Jujuy,Argentina/La_Rioja,Argentina/Mendoza,Argentina/Rio_Gallegos,Argentina/Salta,Argentina/San_Juan,Argentina/San_Luis,Argentina/Tucuman,Argentina/Ushuaia,Buenos_Aires,Catamarca,Cordoba,Jujuy,Mendoza,Rosario;AS:Pacific/Pago_Pago,Samoa|US/Samoa;AT:Europe/Vienna;AU:Antarctica/Macquarie|Australia/ACT,Adelaide,Brisbane,Broken_Hill,Canberra,Currie,Darwin,Eucla,Hobart,LHI,Lindeman,Lord_Howe,Melbourne,NSW,North,Perth,Queensland,South,Sydney,Tasmania,Victoria,West,Yancowinna;AW:America/Aruba;AX:Europe/Mariehamn;AZ:Asia/Baku;BA:Europe/Sarajevo;BB:America/Barbados;BD:Asia/Dacca,Dhaka;BE:CET,MET|Europe/Brussels;BF:Africa/Ouagadougou;BG:Europe/Sofia;BH:Asia/Bahrain;BI:Africa/Bujumbura;BJ:Africa/Porto-Novo;BL:America/St_Barthelemy;BM:Atlantic/Bermuda;BN:Asia/Brunei;BO:America/La_Paz;BQ:America/Kralendijk;BR:America/Araguaina,Bahia,Belem,Boa_Vista,Campo_Grande,Cuiaba,Eirunepe,Fortaleza,Maceio,Manaus,Noronha,Porto_Acre,Porto_Velho,Recife,Rio_Branco,Santarem,Sao_Paulo|Brazil/Acre,DeNoronha,East,West;BS:America/Nassau;BT:Asia/Thimbu,Thimphu;BW:Africa/Gaborone;BY:Europe/Minsk;BZ:America/Belize;CA:America/Atikokan,Blanc-Sablon,Cambridge_Bay,Creston,Dawson,Dawson_Creek,Edmonton,Fort_Nelson,Glace_Bay,Goose_Bay,Halifax,Inuvik,Iqaluit,Moncton,Montreal,Nipigon,Pangnirtung,Rainy_River,Rankin_Inlet,Regina,Resolute,St_Johns,Swift_Current,Thunder_Bay,Toronto,Vancouver,Whitehorse,Winnipeg,Yellowknife|Canada/Atlantic,Central,Eastern,Mountain,Newfoundland,Pacific,Saskatchewan,Yukon;CC:Indian/Cocos;CD:Africa/Kinshasa,Lubumbashi;CF:Africa/Bangui;CG:Africa/Brazzaville;CH:Europe/Zurich;CI:Africa/Abidjan,Timbuktu|Iceland;CK:Pacific/Rarotonga;CL:America/Coyhaique,Punta_Arenas,Santiago|Chile/Continental,EasterIsland|Pacific/Easter;CM:Africa/Douala;CN:Asia/Chongqing,Chungking,Harbin,Kashgar,Shanghai,Urumqi|PRC;CO:America/Bogota;CR:America/Costa_Rica;CU:America/Havana|Cuba;CV:Atlantic/Cape_Verde;CW:America/Curacao;CX:Indian/Christmas;CY:Asia/Famagusta,Nicosia|Europe/Nicosia;CZ:Europe/Prague;DE:Atlantic/Jan_Mayen|Europe/Berlin,Busingen;DJ:Africa/Djibouti;DK:Europe/Copenhagen;DM:America/Dominica;DO:America/Santo_Domingo;DZ:Africa/Algiers;EC:America/Guayaquil|Pacific/Galapagos;EE:Europe/Tallinn;EG:Africa/Cairo|Egypt;EH:Africa/El_Aaiun;ER:Africa/Asmara;ES:Africa/Ceuta|Atlantic/Canary|Europe/Madrid;ET:Africa/Addis_Ababa;FI:Europe/Helsinki;FJ:Pacific/Fiji;FK:Atlantic/Stanley;FM:Pacific/Chuuk,Kosrae,Pohnpei;FO:Atlantic/Faeroe,Faroe;FR:Europe/Paris;GA:Africa/Libreville;GB:Europe/Belfast,London|GB,GB-Eire;GD:America/Grenada;GE:Asia/Tbilisi;GF:America/Cayenne;GG:Europe/Guernsey;GH:Africa/Accra;GI:Europe/Gibraltar;GL:America/Danmarkshavn,Godthab,Nuuk,Scoresbysund,Thule;GM:Africa/Banjul;GN:Africa/Conakry;GP:America/Guadeloupe;GQ:Africa/Malabo;GR:EET|Europe/Athens;GS:Atlantic/South_Georgia;GT:America/Guatemala;GU:Pacific/Guam;GW:Africa/Bissau;GY:America/Guyana;HK:Asia/Hong_Kong|Hongkong;HN:America/Tegucigalpa;HR:Europe/Zagreb;HT:America/Port-au-Prince;HU:Europe/Budapest;ID:Asia/Jakarta,Jayapura,Makassar,Pontianak,Ujung_Pandang;IE:Eire|Europe/Dublin;IL:Asia/Jerusalem,Tel_Aviv|Israel;IM:Europe/Isle_of_Man;IN:Asia/Calcutta,Kolkata;IO:Indian/Chagos;IQ:Asia/Baghdad;IR:Asia/Tehran|Iran;IS:Atlantic/Reykjavik;IT:Europe/Rome;JE:Europe/Jersey;JM:America/Jamaica|Jamaica;JO:Asia/Amman;JP:Asia/Tokyo|Japan;KE:Africa/Asmera,Nairobi;KG:Asia/Bishkek;KH:Asia/Phnom_Penh;KI:Pacific/Enderbury,Kanton,Kiritimati,Tarawa;KM:Indian/Comoro;KN:America/St_Kitts;KP:Asia/Pyongyang;KR:Asia/Seoul|ROK;KW:Asia/Kuwait;KY:America/Cayman;KZ:Asia/Almaty,Aqtau,Aqtobe,Atyrau,Oral,Qostanay,Qyzylorda;LA:Asia/Vientiane;LB:Asia/Beirut;LC:America/St_Lucia;LI:Europe/Vaduz;LK:Asia/Colombo;LR:Africa/Monrovia;LS:Africa/Maseru;LT:Europe/Vilnius;LU:Europe/Luxembourg;LV:Europe/Riga;LY:Africa/Tripoli|Libya;MA:Africa/Casablanca;MC:Europe/Monaco;MD:Europe/Chisinau,Tiraspol;ME:Europe/Podgorica;MF:America/Marigot;MG:Indian/Antananarivo;MH:Kwajalein|Pacific/Kwajalein,Majuro;MK:Europe/Skopje;ML:Africa/Bamako;MM:Asia/Rangoon,Yangon;MN:Asia/Choibalsan,Hovd,Ulaanbaatar,Ulan_Bator;MO:Asia/Macao,Macau;MP:Pacific/Saipan;MQ:America/Martinique;MR:Africa/Nouakchott;MS:America/Montserrat;MT:Europe/Malta;MU:Indian/Mauritius;MV:Indian/Maldives;MW:Africa/Blantyre;MX:America/Bahia_Banderas,Cancun,Chihuahua,Ciudad_Juarez,Ensenada,Hermosillo,Matamoros,Mazatlan,Merida,Mexico_City,Monterrey,Ojinaga,Santa_Isabel,Tijuana|Mexico/BajaNorte,BajaSur,General;MY:Asia/Kuala_Lumpur,Kuching;MZ:Africa/Maputo;NA:Africa/Windhoek;NC:Pacific/Noumea;NE:Africa/Niamey;NF:Pacific/Norfolk;NG:Africa/Lagos;NI:America/Managua;NL:Europe/Amsterdam;NO:Europe/Oslo;NP:Asia/Kathmandu,Katmandu;NR:Pacific/Nauru;NU:Pacific/Niue;NZ:Antarctica/South_Pole|NZ,NZ-CHAT|Pacific/Auckland,Chatham;OM:Asia/Muscat;PA:America/Coral_Harbour,Panama|EST;PE:America/Lima;PF:Pacific/Gambier,Marquesas,Tahiti;PG:Pacific/Bougainville,Port_Moresby,Truk,Yap;PH:Asia/Manila;PK:Asia/Karachi;PL:Europe/Warsaw|Poland;PM:America/Miquelon;PN:Pacific/Pitcairn;PR:America/Puerto_Rico,Virgin;PS:Asia/Gaza,Hebron;PT:Atlantic/Azores,Madeira|Europe/Lisbon|Portugal,WET;PW:Pacific/Palau;PY:America/Asuncion;QA:Asia/Qatar;RE:Indian/Reunion;RO:Europe/Bucharest;RS:Europe/Belgrade;RU:Asia/Anadyr,Barnaul,Chita,Irkutsk,Kamchatka,Khandyga,Krasnoyarsk,Magadan,Novokuznetsk,Novosibirsk,Omsk,Sakhalin,Srednekolymsk,Tomsk,Ust-Nera,Vladivostok,Yakutsk,Yekaterinburg|Europe/Astrakhan,Kaliningrad,Kirov,Moscow,Samara,Saratov,Ulyanovsk,Volgograd|W-SU;RW:Africa/Kigali;SA:Asia/Riyadh;SB:Pacific/Guadalcanal,Ponape;SC:Indian/Mahe;SD:Africa/Khartoum;SE:Europe/Stockholm;SG:Asia/Singapore|Singapore;SH:Atlantic/St_Helena;SI:Europe/Ljubljana;SJ:Arctic/Longyearbyen;SK:Europe/Bratislava;SL:Africa/Freetown;SM:Europe/San_Marino;SN:Africa/Dakar;SO:Africa/Mogadishu;SR:America/Paramaribo;SS:Africa/Juba;ST:Africa/Sao_Tome;SV:America/El_Salvador;SX:America/Lower_Princes;SY:Asia/Damascus;SZ:Africa/Mbabane;TC:America/Grand_Turk;TD:Africa/Ndjamena;TF:Indian/Kerguelen;TG:Africa/Lome;TH:Asia/Bangkok;TJ:Asia/Dushanbe;TK:Pacific/Fakaofo;TL:Asia/Dili;TM:Asia/Ashgabat,Ashkhabad;TN:Africa/Tunis;TO:Pacific/Tongatapu;TR:Asia/Istanbul|Europe/Istanbul|Turkey;TT:America/Port_of_Spain;TV:Pacific/Funafuti;TW:Asia/Taipei|ROC;TZ:Africa/Dar_es_Salaam;UA:Europe/Kiev,Kyiv,Simferopol,Uzhgorod,Zaporozhye;UG:Africa/Kampala;UM:Pacific/Midway,Wake;US:America/Adak,Anchorage,Atka,Boise,Chicago,Denver,Detroit,Fort_Wayne,Indiana/Indianapolis,Indiana/Knox,Indiana/Marengo,Indiana/Petersburg,Indiana/Tell_City,Indiana/Vevay,Indiana/Vincennes,Indiana/Winamac,Indianapolis,Juneau,Kentucky/Louisville,Kentucky/Monticello,Knox_IN,Los_Angeles,Louisville,Menominee,Metlakatla,New_York,Nome,North_Dakota/Beulah,North_Dakota/Center,North_Dakota/New_Salem,Phoenix,Shiprock,Sitka,Yakutat|HST,MST,Navajo|Pacific/Honolulu,Johnston|US/Alaska,Aleutian,Arizona,Central,East-Indiana,Eastern,Hawaii,Indiana-Starke,Michigan,Mountain,Pacific;UY:America/Montevideo;UZ:Asia/Samarkand,Tashkent;VA:Europe/Vatican;VC:America/St_Vincent;VE:America/Caracas;VG:America/Tortola;VI:America/St_Thomas;VN:Asia/Ho_Chi_Minh,Saigon;VU:Pacific/Efate;WF:Pacific/Wallis;WS:Pacific/Apia;YE:Asia/Aden;YT:Indian/Mayotte;ZA:Africa/Johannesburg;ZM:Africa/Lusaka;ZW:Africa/Harare";