@zoho_apptics/apptics-js-sdk 2.0.0-beta → 2.0.0-beta.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.
- package/CHANGELOG.md +191 -21
- package/README.md +519 -333
- package/dist/apptics.esm.min.js +2 -2
- package/dist/apptics.esm.min.js.map +1 -1
- package/dist/apptics.min.js +2 -2
- package/dist/apptics.min.js.map +1 -1
- package/dist/chunks/lifecycle-C6m1W7jo.min.js +3 -0
- package/dist/chunks/lifecycle-C6m1W7jo.min.js.map +1 -0
- package/dist/chunks/send-CgUO82ne.min.js +3 -0
- package/dist/chunks/send-CgUO82ne.min.js.map +1 -0
- package/dist/cjs/core/attempts.js +1 -1
- package/dist/cjs/core/batch.js +2 -2
- package/dist/cjs/core/consent.d.ts +18 -4
- package/dist/cjs/core/consent.js +31 -15
- package/dist/cjs/core/constants.d.ts +57 -27
- package/dist/cjs/core/constants.js +52 -33
- package/dist/cjs/core/db.d.ts +12 -4
- package/dist/cjs/core/db.js +167 -34
- package/dist/cjs/core/debug.js +1 -1
- package/dist/cjs/core/env.d.ts +0 -3
- package/dist/cjs/core/env.js +1 -9
- package/dist/cjs/core/framework-id.d.ts +1 -1
- package/dist/cjs/core/framework-id.js +3 -3
- package/dist/cjs/core/guard.d.ts +9 -0
- package/dist/cjs/core/guard.js +27 -13
- package/dist/cjs/core/hooks.d.ts +7 -4
- package/dist/cjs/core/hooks.js +3 -3
- package/dist/cjs/core/locks.d.ts +9 -0
- package/dist/cjs/core/locks.js +22 -0
- package/dist/cjs/core/logger.d.ts +3 -4
- package/dist/cjs/core/logger.js +4 -40
- package/dist/cjs/core/state.d.ts +9 -6
- package/dist/cjs/core/state.js +3 -5
- package/dist/cjs/core/storage.d.ts +20 -5
- package/dist/cjs/core/storage.js +115 -20
- package/dist/cjs/core/stylesheet.d.ts +8 -0
- package/dist/cjs/core/stylesheet.js +29 -0
- package/dist/cjs/core/transport.d.ts +2 -0
- package/dist/cjs/core/transport.js +30 -18
- package/dist/cjs/core/utils.js +1 -1
- package/dist/cjs/core/validate.js +2 -2
- package/dist/cjs/device/appversion.d.ts +10 -6
- package/dist/cjs/device/appversion.js +38 -3
- package/dist/cjs/device/index.d.ts +28 -2
- package/dist/cjs/device/index.js +312 -44
- package/dist/cjs/engagement/api-rules.d.ts +32 -67
- package/dist/cjs/engagement/api-rules.js +144 -157
- package/dist/cjs/engagement/auto-api.js +2 -2
- package/dist/cjs/engagement/auto-screen.d.ts +2 -0
- package/dist/cjs/engagement/auto-screen.js +67 -3
- package/dist/cjs/engagement/defined-events.js +1 -1
- package/dist/cjs/engagement/send.js +12 -3
- package/dist/cjs/engagement/session.d.ts +29 -3
- package/dist/cjs/engagement/session.js +253 -26
- package/dist/cjs/engagement/track.d.ts +4 -4
- package/dist/cjs/engagement/track.js +58 -30
- package/dist/cjs/errors/send.js +2 -2
- package/dist/cjs/errors/track.d.ts +2 -1
- package/dist/cjs/errors/track.js +49 -7
- package/dist/cjs/feedback/controls.d.ts +12 -0
- package/dist/cjs/feedback/controls.js +104 -25
- package/dist/cjs/feedback/index.d.ts +8 -7
- package/dist/cjs/feedback/index.js +32 -13
- package/dist/cjs/feedback/logs.d.ts +13 -11
- package/dist/cjs/feedback/logs.js +57 -28
- package/dist/cjs/feedback/quartz.d.ts +18 -0
- package/dist/cjs/feedback/quartz.js +105 -0
- package/dist/cjs/feedback/send.d.ts +5 -2
- package/dist/cjs/feedback/send.js +30 -28
- package/dist/cjs/feedback/styles.d.ts +10 -0
- package/dist/cjs/feedback/styles.js +8 -0
- package/dist/cjs/feedback/template.d.ts +1 -1
- package/dist/cjs/feedback/template.js +20 -12
- package/dist/cjs/feedback/ui.d.ts +21 -6
- package/dist/cjs/feedback/ui.js +283 -70
- package/dist/cjs/heatmap/send.d.ts +2 -0
- package/dist/cjs/heatmap/send.js +3 -5
- package/dist/cjs/heatmap/track.d.ts +1 -1
- package/dist/cjs/heatmap/track.js +87 -16
- package/dist/cjs/index.d.ts +16 -63
- package/dist/cjs/index.js +144 -95
- package/dist/cjs/lifecycle.d.ts +21 -3
- package/dist/cjs/lifecycle.js +353 -89
- package/dist/cjs/remoteconfig/country.d.ts +4 -0
- package/dist/cjs/remoteconfig/country.js +73 -0
- package/dist/cjs/remoteconfig/custom.d.ts +7 -7
- package/dist/cjs/remoteconfig/custom.js +31 -51
- package/dist/cjs/remoteconfig/evaluate.d.ts +3 -3
- package/dist/cjs/remoteconfig/evaluate.js +56 -43
- package/dist/cjs/remoteconfig/fetch.d.ts +16 -9
- package/dist/cjs/remoteconfig/fetch.js +120 -39
- package/dist/cjs/remoteconfig/index.d.ts +19 -8
- package/dist/cjs/remoteconfig/index.js +81 -39
- package/dist/cjs/remoteconfig/store.d.ts +15 -7
- package/dist/cjs/remoteconfig/store.js +68 -35
- package/dist/cjs/remoteconfig/tz-countries.d.ts +8 -0
- package/dist/cjs/remoteconfig/tz-countries.js +13 -0
- package/dist/{esm/core → cjs/remotelog}/callsite.d.ts +11 -4
- package/dist/cjs/{core → remotelog}/callsite.js +30 -7
- package/dist/cjs/remotelog/gate.d.ts +2 -11
- package/dist/cjs/remotelog/gate.js +9 -35
- package/dist/cjs/remotelog/index.d.ts +4 -21
- package/dist/cjs/remotelog/logger.d.ts +11 -17
- package/dist/cjs/remotelog/logger.js +31 -59
- package/dist/cjs/remotelog/send.js +11 -11
- package/dist/cjs/remotelogger/index.d.ts +12 -0
- package/dist/cjs/remotelogger/index.js +18 -0
- package/dist/cjs/scheduler.d.ts +3 -1
- package/dist/cjs/scheduler.js +25 -22
- package/dist/cjs/types.d.ts +208 -90
- package/dist/cjs/user/index.js +16 -7
- package/dist/esm/core/attempts.js +1 -1
- package/dist/esm/core/batch.js +2 -2
- package/dist/esm/core/consent.d.ts +18 -4
- package/dist/esm/core/consent.js +32 -17
- package/dist/esm/core/constants.d.ts +57 -27
- package/dist/esm/core/constants.js +51 -33
- package/dist/esm/core/db.d.ts +12 -4
- package/dist/esm/core/db.js +164 -35
- package/dist/esm/core/debug.js +1 -1
- package/dist/esm/core/env.d.ts +0 -3
- package/dist/esm/core/env.js +2 -9
- package/dist/esm/core/framework-id.d.ts +1 -1
- package/dist/esm/core/framework-id.js +3 -3
- package/dist/esm/core/guard.d.ts +9 -0
- package/dist/esm/core/guard.js +27 -14
- package/dist/esm/core/hooks.d.ts +7 -4
- package/dist/esm/core/hooks.js +3 -3
- package/dist/esm/core/locks.d.ts +9 -0
- package/dist/esm/core/locks.js +20 -0
- package/dist/esm/core/logger.d.ts +3 -4
- package/dist/esm/core/logger.js +4 -40
- package/dist/esm/core/state.d.ts +9 -6
- package/dist/esm/core/state.js +3 -5
- package/dist/esm/core/storage.d.ts +20 -5
- package/dist/esm/core/storage.js +113 -21
- package/dist/esm/core/stylesheet.d.ts +8 -0
- package/dist/esm/core/stylesheet.js +27 -0
- package/dist/esm/core/transport.d.ts +2 -0
- package/dist/esm/core/transport.js +30 -19
- package/dist/esm/core/utils.js +1 -1
- package/dist/esm/core/validate.js +2 -2
- package/dist/esm/device/appversion.d.ts +10 -6
- package/dist/esm/device/appversion.js +37 -4
- package/dist/esm/device/index.d.ts +28 -2
- package/dist/esm/device/index.js +313 -49
- package/dist/esm/engagement/api-rules.d.ts +32 -67
- package/dist/esm/engagement/api-rules.js +143 -155
- package/dist/esm/engagement/auto-api.js +3 -3
- package/dist/esm/engagement/auto-screen.d.ts +2 -0
- package/dist/esm/engagement/auto-screen.js +67 -4
- package/dist/esm/engagement/defined-events.js +1 -1
- package/dist/esm/engagement/send.js +12 -3
- package/dist/esm/engagement/session.d.ts +29 -3
- package/dist/esm/engagement/session.js +251 -30
- package/dist/esm/engagement/track.d.ts +4 -4
- package/dist/esm/engagement/track.js +65 -37
- package/dist/esm/errors/send.js +2 -2
- package/dist/esm/errors/track.d.ts +2 -1
- package/dist/esm/errors/track.js +49 -7
- package/dist/esm/feedback/controls.d.ts +12 -0
- package/dist/esm/feedback/controls.js +103 -26
- package/dist/esm/feedback/index.d.ts +8 -7
- package/dist/esm/feedback/index.js +34 -13
- package/dist/esm/feedback/logs.d.ts +13 -11
- package/dist/esm/feedback/logs.js +59 -30
- package/dist/esm/feedback/quartz.d.ts +18 -0
- package/dist/esm/feedback/quartz.js +99 -0
- package/dist/esm/feedback/send.d.ts +5 -2
- package/dist/esm/feedback/send.js +31 -31
- package/dist/esm/feedback/styles.d.ts +10 -0
- package/dist/esm/feedback/styles.js +4 -0
- package/dist/esm/feedback/template.d.ts +1 -1
- package/dist/esm/feedback/template.js +20 -12
- package/dist/esm/feedback/ui.d.ts +21 -6
- package/dist/esm/feedback/ui.js +283 -71
- package/dist/esm/heatmap/send.d.ts +2 -0
- package/dist/esm/heatmap/send.js +3 -5
- package/dist/esm/heatmap/track.d.ts +1 -1
- package/dist/esm/heatmap/track.js +87 -16
- package/dist/esm/index.d.ts +16 -63
- package/dist/esm/index.js +148 -83
- package/dist/esm/lifecycle.d.ts +21 -3
- package/dist/esm/lifecycle.js +359 -98
- package/dist/esm/remoteconfig/country.d.ts +4 -0
- package/dist/esm/remoteconfig/country.js +70 -0
- package/dist/esm/remoteconfig/custom.d.ts +7 -7
- package/dist/esm/remoteconfig/custom.js +32 -52
- package/dist/esm/remoteconfig/evaluate.d.ts +3 -3
- package/dist/esm/remoteconfig/evaluate.js +57 -44
- package/dist/esm/remoteconfig/fetch.d.ts +16 -9
- package/dist/esm/remoteconfig/fetch.js +120 -39
- package/dist/esm/remoteconfig/index.d.ts +19 -8
- package/dist/esm/remoteconfig/index.js +82 -40
- package/dist/esm/remoteconfig/store.d.ts +15 -7
- package/dist/esm/remoteconfig/store.js +68 -36
- package/dist/esm/remoteconfig/tz-countries.d.ts +8 -0
- package/dist/esm/remoteconfig/tz-countries.js +11 -0
- package/dist/{cjs/core → esm/remotelog}/callsite.d.ts +11 -4
- package/dist/esm/{core → remotelog}/callsite.js +30 -8
- package/dist/esm/remotelog/gate.d.ts +2 -11
- package/dist/esm/remotelog/gate.js +10 -32
- package/dist/esm/remotelog/index.d.ts +4 -21
- package/dist/esm/remotelog/logger.d.ts +11 -17
- package/dist/esm/remotelog/logger.js +33 -61
- package/dist/esm/remotelog/send.js +13 -13
- package/dist/esm/remotelogger/index.d.ts +12 -0
- package/dist/esm/remotelogger/index.js +13 -0
- package/dist/esm/scheduler.d.ts +3 -1
- package/dist/esm/scheduler.js +26 -24
- package/dist/esm/types.d.ts +208 -90
- package/dist/esm/user/index.js +18 -8
- package/dist/feedback.esm.min.js +2 -2
- package/dist/feedback.esm.min.js.map +1 -1
- package/dist/remoteconfig.esm.min.js +3 -0
- package/dist/remoteconfig.esm.min.js.map +1 -0
- package/dist/remotelogger.esm.min.js +3 -0
- package/dist/remotelogger.esm.min.js.map +1 -0
- package/package.json +16 -17
- package/dist/chunks/batch-BU_mTpm1.min.js +0 -3
- package/dist/chunks/batch-BU_mTpm1.min.js.map +0 -1
- package/dist/chunks/logs-Bea5zUW_.min.js +0 -3
- package/dist/chunks/logs-Bea5zUW_.min.js.map +0 -1
- package/dist/cjs/auto-init.d.ts +0 -8
- package/dist/cjs/auto-init.js +0 -32
- package/dist/cjs/heatmap/index.d.ts +0 -16
- package/dist/cjs/heatmap/index.js +0 -22
- package/dist/cjs/remotelog/index.js +0 -55
- package/dist/esm/auto-init.d.ts +0 -8
- package/dist/esm/auto-init.js +0 -29
- package/dist/esm/heatmap/index.d.ts +0 -16
- package/dist/esm/heatmap/index.js +0 -17
- package/dist/esm/remotelog/index.js +0 -51
- package/dist/heatmap.esm.min.js +0 -3
- package/dist/heatmap.esm.min.js.map +0 -1
- package/dist/style.css +0 -1
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** The ISO code of a time zone's country, '' for one with none (UTC) or unknown. */
|
|
2
|
+
export declare function timeZoneCountryCode(timeZone: string): string;
|
|
3
|
+
/** The country: the user's, else the time zone's. '' when neither says. */
|
|
4
|
+
export declare function deviceCountry(): string;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/*! @zoho_apptics/apptics-js-sdk v2.0.0-beta.2 | (c) Zoho Corporation Private Limited | see LICENSE */
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var state = require('../core/state.js');
|
|
5
|
+
var env = require('../core/env.js');
|
|
6
|
+
var tzCountries = require('./tz-countries.js');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The country of this device, for remote config's `country` criteria, by its English name as the
|
|
10
|
+
* console lists it ("India").
|
|
11
|
+
*
|
|
12
|
+
* The one AppticsUser.setUser registered comes first. Otherwise it is the country of the
|
|
13
|
+
* browser's time zone, which is the device clock's: Asia/Kolkata (or Chrome's Asia/Calcutta) is
|
|
14
|
+
* India, whatever language the browser is in. A browser has no other source short of asking for
|
|
15
|
+
* the user's location, which is a permission prompt. A zone shared by several countries is the
|
|
16
|
+
* one tzdata names for it.
|
|
17
|
+
*/
|
|
18
|
+
/** Zone -> ISO code, unpacked on first use. */
|
|
19
|
+
var byZone = null;
|
|
20
|
+
function zones() {
|
|
21
|
+
if (byZone !== null) {
|
|
22
|
+
return byZone;
|
|
23
|
+
}
|
|
24
|
+
var out = {};
|
|
25
|
+
tzCountries.TZ_COUNTRIES.split(';').forEach(function (entry) {
|
|
26
|
+
var colon = entry.indexOf(':'); // no i18n
|
|
27
|
+
var code = entry.slice(0, colon);
|
|
28
|
+
entry.slice(colon + 1).split('|').forEach(function (group) {
|
|
29
|
+
// "Area/City,City", or bare names with no area ("Cuba,Egypt")
|
|
30
|
+
var slash = group.indexOf('/'); // no i18n
|
|
31
|
+
var area = slash === -1 ? '' : group.slice(0, slash + 1); // no i18n
|
|
32
|
+
group.slice(area.length).split(',').forEach(function (city) {
|
|
33
|
+
out[area + city] = code;
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
byZone = out;
|
|
38
|
+
return out;
|
|
39
|
+
}
|
|
40
|
+
/** The ISO code of a time zone's country, '' for one with none (UTC) or unknown. */
|
|
41
|
+
function timeZoneCountryCode(timeZone) {
|
|
42
|
+
var all = zones();
|
|
43
|
+
return Object.prototype.hasOwnProperty.call(all, timeZone) ? all[timeZone] : ''; // no i18n
|
|
44
|
+
}
|
|
45
|
+
/** IN -> India, in English; the code itself where the browser has no region names. */
|
|
46
|
+
function regionName(code) {
|
|
47
|
+
try {
|
|
48
|
+
var names = new Intl.DisplayNames(['en'], { type: 'region' }); // no i18n
|
|
49
|
+
return names.of(code) || code;
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
return code;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** The country: the user's, else the time zone's. '' when neither says. */
|
|
56
|
+
function deviceCountry() {
|
|
57
|
+
var named = String(state._ZAP._user_info.country || '').trim(); // no i18n
|
|
58
|
+
if (named !== '') {
|
|
59
|
+
return named;
|
|
60
|
+
}
|
|
61
|
+
var timeZone = ''; // no i18n
|
|
62
|
+
try {
|
|
63
|
+
timeZone = String(env.getTimeZone() || ''); // no i18n
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
timeZone = ''; // no i18n
|
|
67
|
+
}
|
|
68
|
+
var code = timeZoneCountryCode(timeZone);
|
|
69
|
+
return code === '' ? '' : regionName(code); // no i18n
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
exports.deviceCountry = deviceCountry;
|
|
73
|
+
exports.timeZoneCountryCode = timeZoneCountryCode;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
/** The
|
|
2
|
-
export declare function
|
|
1
|
+
/** The values set for a condition, by its name; empty when none are. */
|
|
2
|
+
export declare function customConditionValues(conditionname: string): string[];
|
|
3
3
|
/**
|
|
4
|
-
* Sets what this device is for a custom
|
|
5
|
-
* the stored rules
|
|
6
|
-
* fetch.
|
|
4
|
+
* Sets what this device is for a custom condition, by its name, as comma separated values; an
|
|
5
|
+
* empty value removes it. Re-applies the stored rules once storage is ready, so the next read sees
|
|
6
|
+
* the new result without a fetch.
|
|
7
7
|
*/
|
|
8
|
-
export declare function setCustomConditionValue(
|
|
9
|
-
/** reset(): forgets the values set on this page
|
|
8
|
+
export declare function setCustomConditionValue(conditionname: string, value: string | number | boolean | null | undefined): void;
|
|
9
|
+
/** reset(): forgets the values set on this page. */
|
|
10
10
|
export declare function clearCustomConditionValues(): void;
|
|
@@ -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.2 | (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
|
|
10
|
-
* what this device is for
|
|
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('
|
|
12
|
+
* AppticsRemoteConfig.setCustomConditionValue('is_custom', 'custom_color');
|
|
13
|
+
* AppticsRemoteConfig.setCustomConditionValue('is_custom', 'gold,platinum'); // several
|
|
14
14
|
*
|
|
15
|
-
* The
|
|
16
|
-
*
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
|
41
|
-
* the stored rules
|
|
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(
|
|
45
|
-
var name = typeof
|
|
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
|
|
32
|
+
logger.Console.warn('AppticsRemoteConfig.setCustomConditionValue: a condition name is required'); // no i18n
|
|
48
33
|
return;
|
|
49
34
|
}
|
|
50
|
-
var
|
|
51
|
-
|
|
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
|
-
|
|
46
|
+
if (backend) {
|
|
47
|
+
store.reresolve();
|
|
48
|
+
}
|
|
69
49
|
});
|
|
70
50
|
}
|
|
71
|
-
/** reset(): forgets the values set on this page
|
|
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.
|
|
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
|
-
* `
|
|
14
|
-
*
|
|
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,
|
|
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.2 | (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
|
|
17
|
-
*
|
|
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
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
|
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
|
-
* `
|
|
124
|
-
*
|
|
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,
|
|
127
|
-
var
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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,
|
|
176
|
+
out[name] = resolve(parameter, conditions);
|
|
164
177
|
});
|
|
165
178
|
return out;
|
|
166
179
|
}
|
|
@@ -1,22 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Asks for the rule set
|
|
2
|
+
* Asks for the rule set: the whole of it with flagtime 0 on the first fetch of a page load, then
|
|
3
|
+
* only what changed since the last answered request, which is merged into what is stored.
|
|
3
4
|
*
|
|
4
|
-
* Resolves with the
|
|
5
|
-
*
|
|
6
|
-
* normal case and not a failure.
|
|
5
|
+
* Resolves with the answer, whether or not it carried a rule set — a later answer with no
|
|
6
|
+
* `remoteconfig` block means nothing has changed, which is the normal case and not a failure.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* With `whole`, a cold fetch: flagtime 0 whatever this page has fetched already, and the answer
|
|
9
|
+
* replaces the stored set as the first fetch of a page load does.
|
|
10
|
+
*
|
|
11
|
+
* A second caller joins the first rather than making another request. A cold fetch joins one
|
|
12
|
+
* only when it asked with flagtime 0 too, and otherwise asks once it has answered.
|
|
9
13
|
*/
|
|
10
|
-
export declare function fetchRemoteConfig(): Promise<Record<string, unknown>>;
|
|
14
|
+
export declare function fetchRemoteConfig(whole?: boolean): Promise<Record<string, unknown>>;
|
|
11
15
|
/**
|
|
12
16
|
* reset(): forgets the rule set, its values and what the server last reported, and disowns a
|
|
13
17
|
* request still in flight, whose answer would otherwise put the old rule set back.
|
|
14
18
|
*/
|
|
15
19
|
export declare function resetRemoteConfig(): void;
|
|
16
20
|
/**
|
|
17
|
-
* Makes sure the values are this page's own: from a fetch that
|
|
18
|
-
*
|
|
19
|
-
*
|
|
21
|
+
* Makes sure the values are this page's own: from a fetch on this page that succeeded, kept up to
|
|
22
|
+
* date by the polling after it. With `coldFetch`, a fetch with flagtime 0 now, whatever this page
|
|
23
|
+
* already has, whose answer replaces what is stored: at most COLD_LIMIT a minute, and one past
|
|
24
|
+
* that answers from what this page has. Resolves true when they are, false when the
|
|
25
|
+
* fetch failed or could not be made — the caller then decides whether stored values will do.
|
|
26
|
+
* Never rejects.
|
|
20
27
|
*
|
|
21
28
|
* Waits for start-up and for the device to be registered, which a first visit is still doing
|
|
22
29
|
* when ready() resolves: getupdates is refused without the device ids.
|