@adobe/acc-js-sdk 1.1.6 → 1.1.8
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/.eslintrc.js +1 -0
- package/CHANGELOG.md +11 -0
- package/README.md +36 -2
- package/package-lock.json +5 -4
- package/package.json +1 -1
- package/src/application.js +56 -13
- package/src/cache.js +19 -0
- package/src/cacheRefresher.js +53 -13
- package/src/campaign.js +29 -28
- package/src/client.js +342 -104
- package/src/transport.js +11 -10
- package/test/application.test.js +71 -0
- package/test/caches.test.js +6 -0
- package/test/client.test.js +272 -31
- package/test/mock.js +160 -46
- package/test/observability.test.js +267 -0
package/.eslintrc.js
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,17 @@ This is a node.js SDK for Campaign API. It exposes the Campaign API exactly like
|
|
|
5
5
|
|
|
6
6
|
# Changelog
|
|
7
7
|
|
|
8
|
+
## Version 1.1.8
|
|
9
|
+
_2022_10_03_
|
|
10
|
+
|
|
11
|
+
* Added translation ids (`labelLocalizationId`,`descriptionLocalizationId`, `labelSingularLocalizationId`) for `XtkSchema`, `XtkSchemaNode`, `XtkEnumerationValue` and `XtkEnumeration`
|
|
12
|
+
|
|
13
|
+
## Version 1.1.7
|
|
14
|
+
_2022_08_30_
|
|
15
|
+
|
|
16
|
+
* New listener interface to be notified of internal events from the SDK. Can be used to integrate with observability frameworks. See the "Observers" section of the README file.
|
|
17
|
+
* Experimental file upload feature. Will require server-side changes to work, and is currently limited to be used with browsers only.
|
|
18
|
+
|
|
8
19
|
## Version 1.1.6
|
|
9
20
|
_2022_08_19_
|
|
10
21
|
|
package/README.md
CHANGED
|
@@ -1111,6 +1111,34 @@ The `soapCall` parameter is a `SoapMethodCall` object which describes the SOAP c
|
|
|
1111
1111
|
* `response` is a string containing the XML result of the SOAP call if the call was successful. It may be undefined if the call was not executed yet or if the call failed
|
|
1112
1112
|
|
|
1113
1113
|
|
|
1114
|
+
In version 1.1.7, the observer interface is extended to listen for internal events of the SDK. The `event` function of the observer, if it exist will be call for each SDK event with 2 parameters: the event itself, and for some events, a parent event. For instance a SOAP response event will have the SOAP request for a parent event.
|
|
1115
|
+
```js
|
|
1116
|
+
client.registerObserver({
|
|
1117
|
+
event: (event, parentEvent) => { ... },
|
|
1118
|
+
});
|
|
1119
|
+
```
|
|
1120
|
+
|
|
1121
|
+
The following events are available
|
|
1122
|
+
|
|
1123
|
+
| event name | comment / description |
|
|
1124
|
+
|----|----|
|
|
1125
|
+
| SDK//logon | A client logs on |
|
|
1126
|
+
| SDK//logoff | A client logs off |
|
|
1127
|
+
| CACHE//stats | Regularly sends stats about internal caches |
|
|
1128
|
+
| SOAP//request | The SDK executes a SOAP request |
|
|
1129
|
+
| SOAP//response | The SDK processes the successful response of a SOAP request |
|
|
1130
|
+
| SOAP//failure | A SOAP request failed |
|
|
1131
|
+
| HTTP//request | The SDK executes an HTTP request |
|
|
1132
|
+
| HTTP//response | The SDK processes the successful response of an HTTP request |
|
|
1133
|
+
| HTTP//failure | An HTTP request failed |
|
|
1134
|
+
| CACHE_REFRESHER//start | A cache auto-refresher starts |
|
|
1135
|
+
| CACHE_REFRESHER//stop | A cache auto-refresher stops |
|
|
1136
|
+
| CACHE_REFRESHER//tick | A cache auto-refresh occurs |
|
|
1137
|
+
| CACHE_REFRESHER//loggedOff | The cache auto-refresh was triggered whereas the client was logged off |
|
|
1138
|
+
| CACHE_REFRESHER//error | The cache auto-refresh failed. Auto-refresh will continue. |
|
|
1139
|
+
| CACHE_REFRESHER//abort | The cache auto-refresh failed because the server does not support it. Auto-refresh will stop. |
|
|
1140
|
+
| CACHE_REFRESHER//response | The server responded to an auto-refresh request |
|
|
1141
|
+
|
|
1114
1142
|
# Configuration
|
|
1115
1143
|
|
|
1116
1144
|
## Tracking all SOAP calls
|
|
@@ -1528,8 +1556,6 @@ var event = await query.executeQuery();
|
|
|
1528
1556
|
console.log(`>> Event: ${JSON.stringify(event)}`);
|
|
1529
1557
|
```
|
|
1530
1558
|
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
1559
|
# Application
|
|
1534
1560
|
|
|
1535
1561
|
The `application` object can be obtained from a client, and will mimmic the Campaing `application` object (https://docs.adobe.com/content/help/en/campaign-classic/technicalresources/api/c-Application.html)
|
|
@@ -1727,7 +1753,9 @@ const root = await node.linkTarget();
|
|
|
1727
1753
|
| **namespace** | The namespace of the schema. For instance "nms"
|
|
1728
1754
|
| **name** | The name of the schema (internal name)
|
|
1729
1755
|
| **label** | The label (i.e. human readable, localised) name of the node.
|
|
1756
|
+
| **labelLocalizationId** | The translation id of the label of the node.
|
|
1730
1757
|
| **labelSingular** | The singular label (i.e. human readable, localised) name of the schema. The label of a schema is typically a plural.
|
|
1758
|
+
| **labelSingularTranslationId** | The translation id of the label of the node of the singular label.
|
|
1731
1759
|
| **isLibrary** | For schemas, indicates if the schema is a library
|
|
1732
1760
|
| **mappingType** |Schema mapping type. Usually "sql"
|
|
1733
1761
|
| **md5** | The MD5 code of the schema in the form of a hexadecimal string
|
|
@@ -1745,6 +1773,7 @@ A schema is also a `XtkSchemaNode` and the corresponding properties/methods are
|
|
|
1745
1773
|
| **children** | A array/map of children of the node. See note on the ArrayMap structure below
|
|
1746
1774
|
| **dataPolicy** | Returns a string of characters which provides the data policy of the current node.
|
|
1747
1775
|
| **description** | A long, human readable, description of the node
|
|
1776
|
+
| **descriptionLocalizationId** | The translation id of the description of the node.
|
|
1748
1777
|
| **editType** |Returns a string of characters which specifies the editing type of the current node.
|
|
1749
1778
|
| **enum** | The name of the enumeration for the node, or an empty string if the node does node have an enumeration. See `enumeration()` method to get the corresponding `XtkSchemaNode`
|
|
1750
1779
|
| **enumerationImage** | Returns the name of the image of the current node in the form of a string of characters.
|
|
@@ -1784,6 +1813,7 @@ A schema is also a `XtkSchemaNode` and the corresponding properties/methods are
|
|
|
1784
1813
|
| **unbound** | Returns a boolean which indicates whether the current node has an unlimited number of children of the same type.
|
|
1785
1814
|
| **joins** | Element of type "link" has an array of XtkJoin. See `joinNodes` method.
|
|
1786
1815
|
| **label** | The label (i.e. human readable, localised) name of the node.
|
|
1816
|
+
| **labelLocalizationId** | The translation id of the label of the node.
|
|
1787
1817
|
| **name** | The name of the node (internal name)
|
|
1788
1818
|
| **nodePath** | The xpath of the node
|
|
1789
1819
|
| **parent** | The parent node (a `XtkSchemaNode` object). Will be null for schema nodes
|
|
@@ -1836,7 +1866,9 @@ A schema is also a `XtkSchemaNode` and the corresponding properties/methods are
|
|
|
1836
1866
|
|---|---|
|
|
1837
1867
|
| **name** | The name of the enumeration, fully qualified, i.e. prefixed with the schema id
|
|
1838
1868
|
| **label** | The label (i.e. human readable, localised) name of the key
|
|
1869
|
+
| **labelLocalizationId** | The translation id of the label of the key.
|
|
1839
1870
|
| **description** | A long, human readable, description of the key
|
|
1871
|
+
| **descriptionLocalizationId** | The translation id of the description of the key.
|
|
1840
1872
|
| **baseType** | The base type of the enumeration, usually "string" or "byte"
|
|
1841
1873
|
| **default** | The default value of the enumeration, casted to the enumeration type
|
|
1842
1874
|
| **hasImage** | If the enumeration has an image
|
|
@@ -1848,7 +1880,9 @@ A schema is also a `XtkSchemaNode` and the corresponding properties/methods are
|
|
|
1848
1880
|
|---|---|
|
|
1849
1881
|
| **name** | The name of the key (internal name)
|
|
1850
1882
|
| **label** | The label (i.e. human readable, localised) name of the key
|
|
1883
|
+
| **labelLocalizationId** | The translation id of the label of the key.
|
|
1851
1884
|
| **description** | A long, human readable, description of the key
|
|
1885
|
+
| **descriptionLocalizationId** | The translation id of the description of the key.
|
|
1852
1886
|
| **image** |
|
|
1853
1887
|
| **enabledIf** |
|
|
1854
1888
|
| **applicableIf** |
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/acc-js-sdk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.8",
|
|
4
4
|
"lockfileVersion": 2,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@adobe/acc-js-sdk",
|
|
9
|
-
"version": "1.1.
|
|
9
|
+
"version": "1.1.8",
|
|
10
10
|
"license": "ISC",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"axios": "^0.25.0",
|
|
@@ -4809,9 +4809,10 @@
|
|
|
4809
4809
|
},
|
|
4810
4810
|
"node_modules/uuid": {
|
|
4811
4811
|
"version": "8.3.2",
|
|
4812
|
-
"resolved": "https://
|
|
4812
|
+
"resolved": "https://artifactory.corp.adobe.com/artifactory/api/npm/npm-adobe-release/uuid/-/uuid-8.3.2.tgz",
|
|
4813
4813
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
|
4814
4814
|
"dev": true,
|
|
4815
|
+
"license": "MIT",
|
|
4815
4816
|
"bin": {
|
|
4816
4817
|
"uuid": "dist/bin/uuid"
|
|
4817
4818
|
}
|
|
@@ -8751,7 +8752,7 @@
|
|
|
8751
8752
|
},
|
|
8752
8753
|
"uuid": {
|
|
8753
8754
|
"version": "8.3.2",
|
|
8754
|
-
"resolved": "https://
|
|
8755
|
+
"resolved": "https://artifactory.corp.adobe.com/artifactory/api/npm/npm-adobe-release/uuid/-/uuid-8.3.2.tgz",
|
|
8755
8756
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
|
8756
8757
|
"dev": true
|
|
8757
8758
|
},
|
package/package.json
CHANGED
package/src/application.js
CHANGED
|
@@ -422,6 +422,8 @@ class XtkSchemaNode {
|
|
|
422
422
|
*/
|
|
423
423
|
this.nodePath = this._getNodePath(true)._path;
|
|
424
424
|
|
|
425
|
+
this._buildLocalizationIds();
|
|
426
|
+
|
|
425
427
|
/**
|
|
426
428
|
* Element of type "link" has an array of XtkJoin
|
|
427
429
|
* @type {XtkJoin[]}
|
|
@@ -634,6 +636,35 @@ class XtkSchemaNode {
|
|
|
634
636
|
propagateImplicitValues(this);
|
|
635
637
|
}
|
|
636
638
|
|
|
639
|
+
/* create two ids that are identifying in an unique way the node label and
|
|
640
|
+
* the node description
|
|
641
|
+
* examples:
|
|
642
|
+
* nms__recipient__e____recipient__emailFormat__@desc
|
|
643
|
+
* nms__recipient__e____recipient__mobilePhone__@label
|
|
644
|
+
* */
|
|
645
|
+
_buildLocalizationIds() {
|
|
646
|
+
if (!this.parent) {
|
|
647
|
+
this._localizationId = this.schema.id.replace(":", "__");
|
|
648
|
+
} else {
|
|
649
|
+
this._localizationId = this.parent._localizationId;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
if (this.parent) {
|
|
653
|
+
// Separate each element of the path with a double _
|
|
654
|
+
if (this.isAttribute) {
|
|
655
|
+
this._localizationId = this._localizationId + "__" + this.name.replace('@', '');
|
|
656
|
+
} else {
|
|
657
|
+
// node is not an attribute so it is an element add "e____"
|
|
658
|
+
this._localizationId = this._localizationId + "__e____" + this.name;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
this.labelLocalizationId = this._localizationId + "__@label";
|
|
662
|
+
this.descriptionLocalizationId = this._localizationId + "__@desc";
|
|
663
|
+
if (!this.parent) {
|
|
664
|
+
this.labelSingularLocalizationId = this._localizationId + "__@labelSingular";
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
|
|
637
668
|
/**
|
|
638
669
|
* Indicates whether the current node has an unlimited number of children of the same type.
|
|
639
670
|
*
|
|
@@ -901,9 +932,10 @@ class XtkSchemaNode {
|
|
|
901
932
|
* @constructor
|
|
902
933
|
* @param {XML.XtkObject} The enumeration value definition
|
|
903
934
|
* @param {Campaign.XtkEnumerationType} baseType the enumeration type (often "string" or "byte")
|
|
935
|
+
* @param {string} parentTranslationId the translation id of the parent node
|
|
904
936
|
* @memberof Campaign
|
|
905
937
|
*/
|
|
906
|
-
function XtkEnumerationValue(xml, baseType) {
|
|
938
|
+
function XtkEnumerationValue(xml, baseType, parentTranslationId) {
|
|
907
939
|
/**
|
|
908
940
|
* The value (unique) name
|
|
909
941
|
* @type {string}
|
|
@@ -914,6 +946,14 @@ function XtkEnumerationValue(xml, baseType) {
|
|
|
914
946
|
* @type {string}
|
|
915
947
|
*/
|
|
916
948
|
this.label = EntityAccessor.getAttributeAsString(xml, "label");
|
|
949
|
+
/**
|
|
950
|
+
* Unique identifier for the translation of the label
|
|
951
|
+
* */
|
|
952
|
+
this.labelLocalizationId = parentTranslationId + '__' + this.name + '__@label';
|
|
953
|
+
/**
|
|
954
|
+
* Unique identifier for the tran,slation of the description of the label
|
|
955
|
+
* */
|
|
956
|
+
this.descriptionLocalizationId = parentTranslationId + '__' + this.name + '__@desc';
|
|
917
957
|
/**
|
|
918
958
|
* A human friendly long description of the value
|
|
919
959
|
* @type {string}
|
|
@@ -997,25 +1037,29 @@ class XtkEnumeration {
|
|
|
997
1037
|
*/
|
|
998
1038
|
this.values = new ArrayMap();
|
|
999
1039
|
|
|
1000
|
-
|
|
1040
|
+
var defaultValue = EntityAccessor.getAttributeAsString(xml, "default");
|
|
1041
|
+
this._localizationId = `${schemaId}__${this.name}`.replace(':','__');
|
|
1001
1042
|
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1043
|
+
for (var child of EntityAccessor.getChildElements(xml, "value")) {
|
|
1044
|
+
const e = new XtkEnumerationValue(child, this.baseType, this._localizationId);
|
|
1045
|
+
this.values._push(e.name, e);
|
|
1046
|
+
if (e.image != "") this.hasImage = true;
|
|
1047
|
+
const stringValue = EntityAccessor.getAttributeAsString(child, "value");
|
|
1048
|
+
if (defaultValue == stringValue)
|
|
1049
|
+
this.default = e;
|
|
1050
|
+
}
|
|
1010
1051
|
|
|
1011
|
-
|
|
1052
|
+
this.labelLocalizationId = this._localizationId + "__@label";
|
|
1053
|
+
this.descriptionLocalizationId = this._localizationId + "__@desc";
|
|
1054
|
+
propagateImplicitValues(this, true);
|
|
1012
1055
|
|
|
1013
1056
|
/**
|
|
1014
1057
|
* The system enumeration name, without the schema id prefix
|
|
1015
1058
|
* @type {string}
|
|
1016
1059
|
*/
|
|
1017
1060
|
this.shortName = this.name;
|
|
1018
|
-
|
|
1061
|
+
this.name = `${schemaId}:${this.shortName}`;
|
|
1062
|
+
|
|
1019
1063
|
}
|
|
1020
1064
|
}
|
|
1021
1065
|
|
|
@@ -1063,7 +1107,6 @@ class XtkSchema extends XtkSchemaNode {
|
|
|
1063
1107
|
* @type {string}
|
|
1064
1108
|
*/
|
|
1065
1109
|
this.labelSingular = EntityAccessor.getAttributeAsString(xml, "labelSingular");
|
|
1066
|
-
|
|
1067
1110
|
/**
|
|
1068
1111
|
* The schema mappgin type, following the xtk:srcSchema:mappingType enumeration
|
|
1069
1112
|
* @type {Campaign.XtkSchemaMappingType}
|
package/src/cache.js
CHANGED
|
@@ -179,6 +179,16 @@ class Cache {
|
|
|
179
179
|
this._cache = {};
|
|
180
180
|
// timestamp at which the cache was last cleared
|
|
181
181
|
this._lastCleared = this._loadLastCleared();
|
|
182
|
+
this._stats = {
|
|
183
|
+
reads: 0,
|
|
184
|
+
writes: 0,
|
|
185
|
+
removals: 0,
|
|
186
|
+
clears: 0,
|
|
187
|
+
memoryHits: 0,
|
|
188
|
+
storageHits: 0,
|
|
189
|
+
loads: 0,
|
|
190
|
+
saves: 0,
|
|
191
|
+
};
|
|
182
192
|
}
|
|
183
193
|
|
|
184
194
|
// Load timestamp at which the cache was last cleared
|
|
@@ -195,6 +205,7 @@ class Cache {
|
|
|
195
205
|
|
|
196
206
|
// Load from local storage
|
|
197
207
|
_load(key) {
|
|
208
|
+
this._stats.loads = this._stats.loads + 1;
|
|
198
209
|
const json = this._storage.getItem(key);
|
|
199
210
|
if (!json || !json.cachedAt || json.cachedAt <= this._lastCleared) {
|
|
200
211
|
this._storage.removeItem(key);
|
|
@@ -205,6 +216,7 @@ class Cache {
|
|
|
205
216
|
|
|
206
217
|
// Save to local storage
|
|
207
218
|
_save(key, cached) {
|
|
219
|
+
this._stats.saves = this._stats.saves + 1;
|
|
208
220
|
this._storage.setItem(key, cached);
|
|
209
221
|
}
|
|
210
222
|
|
|
@@ -216,6 +228,7 @@ class Cache {
|
|
|
216
228
|
_getIfActive(key) {
|
|
217
229
|
// In memory cache?
|
|
218
230
|
var cached = this._cache[key];
|
|
231
|
+
var memoryHit = !!cached;
|
|
219
232
|
// Local storage ?
|
|
220
233
|
if (!cached) {
|
|
221
234
|
cached = this._load(key);
|
|
@@ -228,6 +241,8 @@ class Cache {
|
|
|
228
241
|
this._remove(key);
|
|
229
242
|
return undefined;
|
|
230
243
|
}
|
|
244
|
+
this._stats.memoryHits = this._stats.memoryHits + 1;
|
|
245
|
+
if (!memoryHit) this._stats.storageHits = this._stats.storageHits + 1;
|
|
231
246
|
return cached.value;
|
|
232
247
|
}
|
|
233
248
|
|
|
@@ -237,6 +252,7 @@ class Cache {
|
|
|
237
252
|
* @returns {*} the cached value, or undefined if not found
|
|
238
253
|
*/
|
|
239
254
|
get() {
|
|
255
|
+
this._stats.reads = this._stats.reads + 1;
|
|
240
256
|
const key = this._makeKeyFn.apply(this, arguments);
|
|
241
257
|
const cached = this._getIfActive(key);
|
|
242
258
|
return cached;
|
|
@@ -249,6 +265,7 @@ class Cache {
|
|
|
249
265
|
* @returns {CachedObject} a cached object containing the cached value
|
|
250
266
|
*/
|
|
251
267
|
put() {
|
|
268
|
+
this._stats.writes = this._stats.writes + 1;
|
|
252
269
|
const value = arguments[arguments.length -1];
|
|
253
270
|
const key = this._makeKeyFn.apply(this, arguments);
|
|
254
271
|
const now = Date.now();
|
|
@@ -264,6 +281,7 @@ class Cache {
|
|
|
264
281
|
* as cleared so that subsequent get operation will not actually return any data cached in persistent storage
|
|
265
282
|
*/
|
|
266
283
|
clear() {
|
|
284
|
+
this._stats.clears = this._stats.clears + 1;
|
|
267
285
|
this._cache = {};
|
|
268
286
|
this._saveLastCleared();
|
|
269
287
|
}
|
|
@@ -273,6 +291,7 @@ class Cache {
|
|
|
273
291
|
* @param {string} key the key to remove
|
|
274
292
|
*/
|
|
275
293
|
remove(key) {
|
|
294
|
+
this._stats.removals = this._stats.removals + 1;
|
|
276
295
|
delete this._cache[key];
|
|
277
296
|
this._remove(key);
|
|
278
297
|
}
|
package/src/cacheRefresher.js
CHANGED
|
@@ -63,18 +63,21 @@ governing permissions and limitations under the License.
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
/**
|
|
67
|
+
* A class to refresh regulary a Cache every n seconds, by sending a query to get the last modified entities.
|
|
68
|
+
* The refresh mechanism can be activated by calling client.startRefreshCaches().
|
|
69
|
+
* This mechanism depends on the xtk:session:GetModifiedEntities API which is introduced in ACC 8.4 and above.
|
|
70
|
+
*
|
|
71
|
+
* @class
|
|
72
|
+
* @constructor
|
|
73
|
+
* @memberof Campaign
|
|
74
|
+
* @param {Cache} cache is the cache to refresh
|
|
75
|
+
* @param {Client} client is the ACC API Client.
|
|
76
|
+
* @param {string} cacheSchemaId is the id of the schema present in the cache to be refreshed every 10 seconds
|
|
77
|
+
* @param {string} rootKey is used as the root key of cache items in the refresher state cache
|
|
78
|
+
*/
|
|
66
79
|
class CacheRefresher {
|
|
67
80
|
|
|
68
|
-
/**
|
|
69
|
-
* A class to refresh regulary a Cache every n seconds, by sending a query to get the last modified entities.
|
|
70
|
-
* The refresh mechanism can be activated by calling client.startRefreshCaches().
|
|
71
|
-
* This mechanism depends on the xtk:session:GetModifiedEntities API which is introduced in ACC 8.4 and above.
|
|
72
|
-
*
|
|
73
|
-
* @param {Cache} cache is the cache to refresh
|
|
74
|
-
* @param {Client} client is the ACC API Client.
|
|
75
|
-
* @param {string} cacheSchemaId is the id of the schema present in the cache to be refreshed every 10 seconds
|
|
76
|
-
* @param {string} rootKey is used as the root key of cache items in the refresher state cache
|
|
77
|
-
*/
|
|
78
81
|
constructor(cache, client, cacheSchemaId, rootKey) {
|
|
79
82
|
const connectionParameters = client._connectionParameters;
|
|
80
83
|
this._cache = cache;
|
|
@@ -96,6 +99,10 @@ governing permissions and limitations under the License.
|
|
|
96
99
|
* @param {integer} refreshFrequency frequency of the refresh in ms (default value is 10,000 ms)
|
|
97
100
|
*/
|
|
98
101
|
startAutoRefresh(refreshFrequency) {
|
|
102
|
+
this._client._trackEvent('CACHE_REFRESHER//start', undefined, {
|
|
103
|
+
cacheSchemaId: this._cacheSchemaId,
|
|
104
|
+
refreshFrequency: refreshFrequency
|
|
105
|
+
});
|
|
99
106
|
if (this._intervalId != null) {
|
|
100
107
|
clearInterval(this._intervalId);
|
|
101
108
|
}
|
|
@@ -109,6 +116,9 @@ governing permissions and limitations under the License.
|
|
|
109
116
|
if (this._running) {
|
|
110
117
|
// This call is already running and maybe taking a long time to complete. Do not make things
|
|
111
118
|
// harder and just skip this run
|
|
119
|
+
this._client._trackEvent('CACHE_REFRESHER//skip', undefined, {
|
|
120
|
+
cacheSchemaId: this._cacheSchemaId,
|
|
121
|
+
});
|
|
112
122
|
return;
|
|
113
123
|
}
|
|
114
124
|
this._running = true;
|
|
@@ -117,9 +127,16 @@ governing permissions and limitations under the License.
|
|
|
117
127
|
} catch(ex) {
|
|
118
128
|
if (ex.errorCode === "SDK-000010") {
|
|
119
129
|
// client is not logged, this is not an error.
|
|
130
|
+
this._client._trackEvent('CACHE_REFRESHER//loggedOff', undefined, {
|
|
131
|
+
cacheSchemaId: this._cacheSchemaId,
|
|
132
|
+
});
|
|
120
133
|
return;
|
|
121
134
|
}
|
|
122
|
-
|
|
135
|
+
this._client._trackEvent('CACHE_REFRESHER//error', undefined, {
|
|
136
|
+
cacheSchemaId: this._cacheSchemaId,
|
|
137
|
+
error: ex,
|
|
138
|
+
});
|
|
139
|
+
console.warn(`Failed to refresh cache for ${this._cacheSchemaId}`, ex);
|
|
123
140
|
}
|
|
124
141
|
finally {
|
|
125
142
|
this._running = false;
|
|
@@ -166,6 +183,12 @@ governing permissions and limitations under the License.
|
|
|
166
183
|
if (!this._client.isLogged())
|
|
167
184
|
throw CampaignException.NOT_LOGGED_IN(soapCall, `Cannot call GetModifiedEntities: session not connected`);
|
|
168
185
|
|
|
186
|
+
const event = this._client._trackEvent('CACHE_REFRESHER//tick', undefined, {
|
|
187
|
+
cacheSchemaId: this._cacheSchemaId,
|
|
188
|
+
lastTime: this._lastTime,
|
|
189
|
+
buildNumber: this._buildNumber
|
|
190
|
+
});
|
|
191
|
+
|
|
169
192
|
// Do a soap call GetModifiedEntities instead of xtksession.GetModifiedEnties because we don't want to go through methodCache
|
|
170
193
|
// which might not contain the method GetModifiedEntities just after a build updgrade from a old version of acc
|
|
171
194
|
return this._client._makeSoapCall(soapCall)
|
|
@@ -175,13 +198,17 @@ governing permissions and limitations under the License.
|
|
|
175
198
|
doc = that._client._toRepresentation(doc, 'xml');
|
|
176
199
|
that._lastTime = DomUtil.getAttributeAsString(doc, "time"); // save time to be able to send it as an attribute in the next soap call
|
|
177
200
|
that._buildNumber = DomUtil.getAttributeAsString(doc, "buildNumber");
|
|
178
|
-
that._refresh(doc);
|
|
201
|
+
that._refresh(doc, event);
|
|
179
202
|
that._refresherStateCache.put("time", that._lastTime);
|
|
180
203
|
that._refresherStateCache.put("buildNumber", that._buildNumber);
|
|
181
204
|
})
|
|
182
205
|
.catch((ex) => {
|
|
183
206
|
// if the method GetModifiedEntities is not found in this acc version we disable the autoresfresh of the cache
|
|
184
207
|
if (soapCall.methodName == "GetModifiedEntities" && ex.errorCode == "SOP-330006") {
|
|
208
|
+
this._client._trackEvent('CACHE_REFRESHER//abort', undefined, {
|
|
209
|
+
cacheSchemaId: this._cacheSchemaId,
|
|
210
|
+
error: ex,
|
|
211
|
+
});
|
|
185
212
|
this.stopAutoRefresh();
|
|
186
213
|
} else {
|
|
187
214
|
throw ex;
|
|
@@ -190,8 +217,9 @@ governing permissions and limitations under the License.
|
|
|
190
217
|
}
|
|
191
218
|
|
|
192
219
|
// Refresh Cache : remove entities modified recently listed in xmlDoc
|
|
193
|
-
_refresh(xmlDoc) {
|
|
220
|
+
_refresh(xmlDoc, event) {
|
|
194
221
|
const clearCache = XtkCaster.asBoolean(DomUtil.getAttributeAsString(xmlDoc, "emptyCache"));
|
|
222
|
+
const evicted = [];
|
|
195
223
|
if (clearCache == true) {
|
|
196
224
|
this._cache.clear();
|
|
197
225
|
} else {
|
|
@@ -200,6 +228,7 @@ governing permissions and limitations under the License.
|
|
|
200
228
|
const pkSchemaId = DomUtil.getAttributeAsString(child, "pk");
|
|
201
229
|
const schemaId = DomUtil.getAttributeAsString(child, "schema");
|
|
202
230
|
if (schemaId === this._cacheSchemaId) {
|
|
231
|
+
evicted.push(schemaId);
|
|
203
232
|
this._cache.remove(pkSchemaId);
|
|
204
233
|
// Notify listeners to refresh in SchemaCache
|
|
205
234
|
if (schemaId === "xtk:schema") {
|
|
@@ -210,12 +239,23 @@ governing permissions and limitations under the License.
|
|
|
210
239
|
child = DomUtil.getNextSiblingElement(child);
|
|
211
240
|
}
|
|
212
241
|
}
|
|
242
|
+
|
|
243
|
+
this._client._trackEvent('CACHE_REFRESHER//response', event, {
|
|
244
|
+
cacheSchemaId: this._cacheSchemaId,
|
|
245
|
+
clearCache: clearCache,
|
|
246
|
+
evicted: evicted
|
|
247
|
+
});
|
|
213
248
|
}
|
|
214
249
|
|
|
215
250
|
/**
|
|
216
251
|
* Stop auto refreshing the cache
|
|
217
252
|
*/
|
|
218
253
|
stopAutoRefresh() {
|
|
254
|
+
if (this._intervalId) {
|
|
255
|
+
this._client._trackEvent('CACHE_REFRESHER//stop', undefined, {
|
|
256
|
+
cacheSchemaId: this._cacheSchemaId,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
219
259
|
clearInterval(this._intervalId);
|
|
220
260
|
this._intervalId = null;
|
|
221
261
|
}
|
package/src/campaign.js
CHANGED
|
@@ -10,10 +10,10 @@ OF ANY KIND, either express or implied. See the License for the specific languag
|
|
|
10
10
|
governing permissions and limitations under the License.
|
|
11
11
|
*/
|
|
12
12
|
(function() {
|
|
13
|
-
"use strict";
|
|
13
|
+
"use strict";
|
|
14
14
|
|
|
15
15
|
const { Util } = require("./util.js");
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
/**
|
|
18
18
|
* @namespace Campaign
|
|
19
19
|
*/
|
|
@@ -38,7 +38,8 @@ const { Util } = require("./util.js");
|
|
|
38
38
|
static NOT_LOGGED_IN(call, details) { return new CampaignException( call, 400, 16384, `SDK-000010 Cannot call API because client is not logged in`, details); }
|
|
39
39
|
static DECRYPT_ERROR(details) { return new CampaignException(undefined, 400, 16384, `SDK-000011 "Cannot decrypt password: password marker is missing`, details); }
|
|
40
40
|
static SESSION_EXPIRED() { return new CampaignException(undefined, 401, 16384, `SDK-000012 "Session has expired or is invalid. Please reconnect.`); }
|
|
41
|
-
|
|
41
|
+
static FILE_UPLOAD_FAILED(name, details) { return new CampaignException(undefined, 500, 16384, `SDK-000013 "Failed to upload file ${name}`, details); }
|
|
42
|
+
|
|
42
43
|
|
|
43
44
|
/**
|
|
44
45
|
* Returns a short description of the exception
|
|
@@ -49,18 +50,18 @@ const { Util } = require("./util.js");
|
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
/**
|
|
52
|
-
* Represents a Campaign exception, i.e. any kind of error that can happen when calling Campaign APIs,
|
|
53
|
+
* Represents a Campaign exception, i.e. any kind of error that can happen when calling Campaign APIs,
|
|
53
54
|
* ranging from HTTP errors, XML serialization errors, SOAP errors, authentication errors, etc.
|
|
54
|
-
*
|
|
55
|
+
*
|
|
55
56
|
* Members of this object are trimmed, and all session tokens, security tokens, passwords, etc. are replaced by "***"
|
|
56
|
-
*
|
|
57
|
+
*
|
|
57
58
|
* @param {SoapMethodCall|request} call the call that triggered the error. It can be a SoapMethodCall object, a HTTP request object, or even be undefined if the exception is generated outside of the context of a call
|
|
58
59
|
* @param {number} statusCode the HTTP status code (200, 500, etc.)
|
|
59
60
|
* @param {string} faultCode the fault code, i.e. an error code
|
|
60
61
|
* @param {string} faultString a short description of the error
|
|
61
62
|
* @param {string} detail a more detailed description of the error
|
|
62
63
|
* @param {Error|string} cause an optional error object representing the cause of the exception
|
|
63
|
-
*/
|
|
64
|
+
*/
|
|
64
65
|
constructor(call, statusCode, faultCode, faultString, detail, cause) {
|
|
65
66
|
|
|
66
67
|
// Provides a shorter and more friendly description of the call and method name
|
|
@@ -80,7 +81,7 @@ const { Util } = require("./util.js");
|
|
|
80
81
|
};
|
|
81
82
|
methodName = `${call.urn}#${call.methodName}`; // Example: "xtk:session#Logon"
|
|
82
83
|
}
|
|
83
|
-
else {
|
|
84
|
+
else {
|
|
84
85
|
// HTTP call
|
|
85
86
|
// Extract the path of the request URL if there's one
|
|
86
87
|
// If it's a relative URL, use the URL itself
|
|
@@ -140,48 +141,48 @@ const { Util } = require("./util.js");
|
|
|
140
141
|
faultString = faultString.trim();
|
|
141
142
|
}
|
|
142
143
|
|
|
143
|
-
/**
|
|
144
|
+
/**
|
|
144
145
|
* The type of exception, always "CampaignException"
|
|
145
146
|
* @type {string}
|
|
146
147
|
*/
|
|
147
148
|
this.name = "CampaignException";
|
|
148
|
-
/**
|
|
149
|
+
/**
|
|
149
150
|
* A human friendly message describing the error
|
|
150
151
|
* @type {string}
|
|
151
152
|
*/
|
|
152
153
|
this.message = message;
|
|
153
|
-
/**
|
|
154
|
-
* The HTTP status code corresponding to the error
|
|
154
|
+
/**
|
|
155
|
+
* The HTTP status code corresponding to the error
|
|
155
156
|
* @type {number}
|
|
156
157
|
*/
|
|
157
158
|
this.statusCode = statusCode;
|
|
158
|
-
/**
|
|
159
|
-
* An object describing the call (SOAP or HTTP) which caused the exception. Can be null
|
|
159
|
+
/**
|
|
160
|
+
* An object describing the call (SOAP or HTTP) which caused the exception. Can be null
|
|
160
161
|
* @type {string}
|
|
161
162
|
*/
|
|
162
163
|
this.methodCall = methodCall;
|
|
163
|
-
/**
|
|
164
|
-
* A Campaign-specific error code, such as XSV-350013. May not be set if the exception did not come from a SOAP call
|
|
164
|
+
/**
|
|
165
|
+
* A Campaign-specific error code, such as XSV-350013. May not be set if the exception did not come from a SOAP call
|
|
165
166
|
* @type {string}
|
|
166
167
|
*/
|
|
167
168
|
this.errorCode = errorCode;
|
|
168
|
-
/**
|
|
169
|
-
* An error code
|
|
169
|
+
/**
|
|
170
|
+
* An error code
|
|
170
171
|
* @type {string}
|
|
171
172
|
*/
|
|
172
173
|
this.faultCode = faultCode;
|
|
173
|
-
/**
|
|
174
|
-
* A short description of the error
|
|
174
|
+
/**
|
|
175
|
+
* A short description of the error
|
|
175
176
|
* @type {string}
|
|
176
177
|
*/
|
|
177
178
|
this.faultString = faultString;
|
|
178
|
-
/**
|
|
179
|
-
* A detailed description of the error
|
|
179
|
+
/**
|
|
180
|
+
* A detailed description of the error
|
|
180
181
|
* @type {string}
|
|
181
182
|
*/
|
|
182
183
|
this.detail = detail;
|
|
183
|
-
/**
|
|
184
|
-
* The cause of the error, such as the root cause exception
|
|
184
|
+
/**
|
|
185
|
+
* The cause of the error, such as the root cause exception
|
|
185
186
|
*/
|
|
186
187
|
this.cause = cause;
|
|
187
188
|
|
|
@@ -199,7 +200,7 @@ const { Util } = require("./util.js");
|
|
|
199
200
|
|
|
200
201
|
/**
|
|
201
202
|
* Creates a CampaignException for a SOAP call and from a root exception
|
|
202
|
-
*
|
|
203
|
+
*
|
|
203
204
|
* @private
|
|
204
205
|
* @param {SoapMethodCall} call the SOAP call
|
|
205
206
|
* @param {*} err the exception causing the SOAP call.
|
|
@@ -210,7 +211,7 @@ function makeCampaignException(call, err) {
|
|
|
210
211
|
// It's already a CampaignException
|
|
211
212
|
if (err instanceof CampaignException)
|
|
212
213
|
return err;
|
|
213
|
-
|
|
214
|
+
|
|
214
215
|
// Wraps DOM exceptions which can occur when dealing with malformed XML
|
|
215
216
|
const ctor = Object.getPrototypeOf(err).constructor;
|
|
216
217
|
if (ctor && ctor.name == "DOMException") {
|
|
@@ -244,9 +245,9 @@ exports.CampaignException = CampaignException;
|
|
|
244
245
|
exports.makeCampaignException = makeCampaignException;
|
|
245
246
|
|
|
246
247
|
/**********************************************************************************
|
|
247
|
-
*
|
|
248
|
+
*
|
|
248
249
|
* Business constants and helpers
|
|
249
|
-
*
|
|
250
|
+
*
|
|
250
251
|
*********************************************************************************/
|
|
251
252
|
|
|
252
253
|
// Ignore constant definitions from coverage
|