@adobe/acc-js-sdk 1.1.18 → 1.1.20

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/docs/caches.html CHANGED
@@ -43,10 +43,35 @@ client.clearAllCaches();
43
43
  <p>It's possible to disable persistent caches using the <b>noStorage</b> connection option.</p>
44
44
 
45
45
  <p>It is also possible to setup one's own persistent cache, by passing a <b>storage</b> object as a connection option.
46
- This object should implement 3 methods: <b>getItem</b>, <b>setItem</b>, and <b>removeItem</b> (synchronous)</p>
46
+ See the "Custom Storage" section below for more details.</p>
47
47
 
48
48
  <p>Additionally, since version 1.1.18, the <b>storage</b> object should also support the for...in operator to iterate through its keys</p>
49
49
 
50
+
51
+ <h1>Cache root key</h1>
52
+
53
+ <p>
54
+ By default, the SDK will prefix all cache entity by a root key, which is made of the SDK version and the instance URL.
55
+ It is possible to change this using the `cacheRootKey` connection parameter.
56
+ </p>
57
+ <ul>
58
+ <li>* `default` or undefined: default prefix</li>
59
+ <li>* `none`: no prefix</li>
60
+ </ul>
61
+
62
+ <h1>Custom storage</h1>
63
+
64
+ A custom storage is a JavaScript object with the following functions:
65
+ * `getItem` is given a cache key and should return the corresponding value
66
+ * `setItem` is given a cache key and value and should cache the corresponding key/value pair
67
+
68
+ Optionally, the storage object can contain the following
69
+ * `removeItem` is given a cache key and should remove the corresponding key/value pair from the cache
70
+ * The storage object should also be iterable using the for..in construct
71
+
72
+ The get/set/remove item function can be either synchronous or asynchronous, i.e. can optionally return a promise.
73
+
74
+
50
75
  <h1>Auto-refresh caches</h1>
51
76
 
52
77
  <p>The SDK includes a mechnism to maintain the schemas and options caches up-to-date by polling the Campaign server on a
@@ -2,13 +2,39 @@
2
2
  layout: page
3
3
  title: Change Log
4
4
  ---
5
+
6
+ <section class="changelog"><h1>Version 1.1.20</h1>
7
+ <h2>2023/01/11</h2>
8
+
9
+ <li>
10
+ Upgrade json5 dependency from 2.2.1 to 2.2.3 to fix a vulnerability
11
+ </li>
12
+
13
+ <li>
14
+ Add support for asynchronous caches. The signature of cache objects (Cache, MethodCache,
15
+ OptionCache, XtkEntityCache, SafeStorage) have changed to asynchronous functions.
16
+ However, the delegate object used to configure custom caches now support either synchronous
17
+ or async results. See the <a href="https://opensource.adobe.com/acc-js-sdk/caches.html">Cache documentation for more details</a>
18
+ </li>
19
+ <li>
20
+ Ability to configure the prefix to use for the cached objects. Default to a string containing
21
+ the SDK version and instance domain.
22
+ </li>
23
+ </section>
24
+
25
+
26
+ <section class="changelog"><h1>Version 1.1.19</h1>
27
+ <h2>2022/12/21</h2>
28
+
29
+ <li>Add the X-Session-Token custom header to all SOAP and API calls</li>
30
+ </section>
31
+
5
32
  <section class="changelog"><h1>Version 1.1.18</h1>
6
33
  <h2>2022/12/20</h2>
7
34
 
8
35
  <li>Automatically remove from local storage key items which correspond to previous versions of the SDK.</li>
9
36
  </section>
10
37
 
11
-
12
38
  <section class="changelog"><h1>Version 1.1.17</h1>
13
39
  <h2>2022/12/06</h2>
14
40
 
package/package-lock.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/acc-js-sdk",
3
- "version": "1.1.18",
3
+ "version": "1.1.20",
4
4
  "lockfileVersion": 1,
5
5
  "requires": true,
6
6
  "dependencies": {
@@ -2876,9 +2876,9 @@
2876
2876
  "dev": true
2877
2877
  },
2878
2878
  "json5": {
2879
- "version": "2.2.1",
2880
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
2881
- "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
2879
+ "version": "2.2.3",
2880
+ "resolved": "https://artifactory.corp.adobe.com/artifactory/api/npm/npm-adobe-release/json5/-/json5-2.2.3.tgz",
2881
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
2882
2882
  "dev": true
2883
2883
  },
2884
2884
  "klaw": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/acc-js-sdk",
3
- "version": "1.1.18",
3
+ "version": "1.1.20",
4
4
  "description": "ACC Javascript SDK",
5
5
  "main": "src/index.js",
6
6
  "homepage": "https://github.com/adobe/acc-js-sdk#readme",
package/src/cache.js CHANGED
@@ -12,6 +12,8 @@ governing permissions and limitations under the License.
12
12
  (function() {
13
13
  "use strict";
14
14
 
15
+ const { Util } = require("./util");
16
+
15
17
 
16
18
  /**********************************************************************************
17
19
  *
@@ -78,11 +80,11 @@ class SafeStorage {
78
80
  * @returns {Utils.CachedObject} the cached object, or undefined if not found.
79
81
  * The storage serDeser fucntion will be used to deserialize the cached value
80
82
  */
81
- getItem(key) {
83
+ async getItem(key) {
82
84
  if (!this._delegate || this._rootKey === undefined || this._rootKey === null)
83
85
  return;
84
86
  const itemKey = `${this._rootKey}${key}`;
85
- const raw = this._delegate.getItem(itemKey);
87
+ const raw = await Util.asPromise(this._delegate.getItem(itemKey));
86
88
  if (!raw)
87
89
  return undefined;
88
90
  try {
@@ -98,28 +100,28 @@ class SafeStorage {
98
100
  * @param {Utils.CachedObject} json the object to cache
99
101
  * The storage serDeser fucntion will be used to serialize the cached value
100
102
  */
101
- setItem(key, json) {
103
+ async setItem(key, json) {
102
104
  if (!this._delegate || this._rootKey === undefined || this._rootKey === null)
103
105
  return;
104
106
  try {
105
107
  //if (json && typeof json === "object") {
106
108
  const raw = this._serDeser(json, true);
107
- this._delegate.setItem(`${this._rootKey}${key}`, raw);
109
+ await Util.asPromise(this._delegate.setItem(`${this._rootKey}${key}`, raw));
108
110
  return;
109
111
  } catch(ex) { /* Ignore errors in safe class */
112
+ await this.removeItem(key);
110
113
  }
111
- this.removeItem(key);
112
114
  }
113
115
 
114
116
  /**
115
117
  * Removes an item from the storage
116
118
  * @param {string} key the item key (relative to the root key)
117
119
  */
118
- removeItem(key) {
120
+ async removeItem(key) {
119
121
  if (!this._delegate || this._rootKey === undefined || this._rootKey === null)
120
122
  return;
121
123
  try {
122
- this._delegate.removeItem(`${this._rootKey}${key}`);
124
+ await this._delegate.removeItem(`${this._rootKey}${key}`);
123
125
  } catch(ex) { /* Ignore errors in safe class */
124
126
  }
125
127
  }
@@ -178,7 +180,12 @@ class Cache {
178
180
  this._makeKeyFn = makeKeyFn || ((x) => x);
179
181
  this._cache = {};
180
182
  // timestamp at which the cache was last cleared
181
- this._lastCleared = this._loadLastCleared();
183
+ // The variable is set with special "null" value to indicate that the
184
+ // timestamp at which the cache was clear is not known, and therefore
185
+ // needs to be fetched. It will be fetched dynamically when needed,
186
+ // resulting in either an undefined value (cache was never cleared)
187
+ // or a actual timestamp.
188
+ this._lastCleared = null;
182
189
  this._stats = {
183
190
  reads: 0,
184
191
  writes: 0,
@@ -192,53 +199,57 @@ class Cache {
192
199
  }
193
200
 
194
201
  // Load timestamp at which the cache was last cleared
195
- _loadLastCleared() {
196
- const json = this._storage.getItem("lastCleared");
202
+ async _loadLastCleared() {
203
+ const json = await this._storage.getItem("lastCleared");
197
204
  return json ? json.timestamp : undefined;
198
205
  }
199
206
 
200
- _saveLastCleared() {
207
+ async _saveLastCleared() {
201
208
  const now = Date.now();
202
209
  this._lastCleared = now;
203
- this._storage.setItem("lastCleared", { timestamp: now});
210
+ await this._storage.setItem("lastCleared", { timestamp: now});
204
211
  }
205
212
 
206
213
  // Load from local storage
207
- _load(key) {
214
+ async _load(key) {
208
215
  this._stats.loads = this._stats.loads + 1;
209
- const json = this._storage.getItem(key);
216
+ // A null value here indicates that we have not yet loaded the
217
+ // timestamp at which the cache was cleared last
218
+ if (this._lastCleared === null)
219
+ this._lastCleared = await this._loadLastCleared();
220
+ const json = await this._storage.getItem(key);
210
221
  if (!json || !json.cachedAt || json.cachedAt <= this._lastCleared) {
211
- this._storage.removeItem(key);
222
+ await this._storage.removeItem(key);
212
223
  return;
213
224
  }
214
225
  return json;
215
226
  }
216
227
 
217
228
  // Save to local storage
218
- _save(key, cached) {
229
+ async _save(key, cached) {
219
230
  this._stats.saves = this._stats.saves + 1;
220
- this._storage.setItem(key, cached);
231
+ await this._storage.setItem(key, cached);
221
232
  }
222
233
 
223
234
  // Remove from local storage
224
- _remove(key) {
225
- this._storage.removeItem(key);
235
+ async _remove(key) {
236
+ await this._storage.removeItem(key);
226
237
  }
227
238
 
228
- _getIfActive(key) {
239
+ async _getIfActive(key) {
229
240
  // In memory cache?
230
241
  var cached = this._cache[key];
231
242
  var memoryHit = !!cached;
232
243
  // Local storage ?
233
244
  if (!cached) {
234
- cached = this._load(key);
245
+ cached = await this._load(key);
235
246
  this._cache[key] = cached;
236
247
  }
237
248
  if (!cached)
238
249
  return undefined;
239
250
  if (cached.expiresAt <= Date.now()) {
240
251
  delete this._cache[key];
241
- this._remove(key);
252
+ await this._remove(key);
242
253
  return undefined;
243
254
  }
244
255
  this._stats.memoryHits = this._stats.memoryHits + 1;
@@ -251,10 +262,10 @@ class Cache {
251
262
  * @param {*} key the key or keys of the value to retreive
252
263
  * @returns {*} the cached value, or undefined if not found
253
264
  */
254
- get() {
265
+ async get() {
255
266
  this._stats.reads = this._stats.reads + 1;
256
267
  const key = this._makeKeyFn.apply(this, arguments);
257
- const cached = this._getIfActive(key);
268
+ const cached = await this._getIfActive(key);
258
269
  return cached;
259
270
  }
260
271
 
@@ -264,7 +275,7 @@ class Cache {
264
275
  * @param {*} value the value to cache
265
276
  * @returns {CachedObject} a cached object containing the cached value
266
277
  */
267
- put() {
278
+ async put() {
268
279
  this._stats.writes = this._stats.writes + 1;
269
280
  const value = arguments[arguments.length -1];
270
281
  const key = this._makeKeyFn.apply(this, arguments);
@@ -272,7 +283,7 @@ class Cache {
272
283
  const expiresAt = now + this._ttl;
273
284
  const cached = new CachedObject(value, now, expiresAt);
274
285
  this._cache[key] = cached;
275
- this._save(key, cached);
286
+ await this._save(key, cached);
276
287
  return cached;
277
288
  }
278
289
 
@@ -280,20 +291,20 @@ class Cache {
280
291
  * Removes everything from the cache. It does not directly removes data from persistent storage if there is, but it marks the cache
281
292
  * as cleared so that subsequent get operation will not actually return any data cached in persistent storage
282
293
  */
283
- clear() {
294
+ async clear() {
284
295
  this._stats.clears = this._stats.clears + 1;
285
296
  this._cache = {};
286
- this._saveLastCleared();
297
+ await this._saveLastCleared();
287
298
  }
288
299
 
289
300
  /**
290
301
  * Remove a key from the cache
291
302
  * @param {string} key the key to remove
292
303
  */
293
- remove(key) {
304
+ async remove(key) {
294
305
  this._stats.removals = this._stats.removals + 1;
295
306
  delete this._cache[key];
296
- this._remove(key);
307
+ await this._remove(key);
297
308
  }
298
309
  }
299
310
 
@@ -47,7 +47,7 @@ governing permissions and limitations under the License.
47
47
  * @param {string} name is the propertie name
48
48
  * @param {string} rawValue string value
49
49
  */
50
- put(name, rawValue) {
50
+ async put(name, rawValue) {
51
51
  return super.put(name, { value: rawValue });
52
52
  }
53
53
 
@@ -57,8 +57,8 @@ governing permissions and limitations under the License.
57
57
  * @param {string} name the propertie name
58
58
  * @returns {*} the value
59
59
  */
60
- get(name) {
61
- const option = super.get(name);
60
+ async get(name) {
61
+ const option = await super.get(name);
62
62
  return option ? option.value : undefined;
63
63
  }
64
64
  }
@@ -149,13 +149,13 @@ governing permissions and limitations under the License.
149
149
  const soapCall = this._client._prepareSoapCall("xtk:session", "GetModifiedEntities", true, true, this._connectionParameters._options.extraHttpHeaders);
150
150
 
151
151
  if (this._lastTime === undefined) {
152
- const storedTime = this._refresherStateCache.get("time");
152
+ const storedTime = await this._refresherStateCache.get("time");
153
153
  if (storedTime != undefined) {
154
154
  this._lastTime = storedTime;
155
155
  }
156
156
  }
157
157
  if (this._buildNumber === undefined) {
158
- const storedBuildNumber = this._refresherStateCache.get("buildNumber");
158
+ const storedBuildNumber = await this._refresherStateCache.get("buildNumber");
159
159
  if (storedBuildNumber != undefined) {
160
160
  this._buildNumber = storedBuildNumber;
161
161
  }
@@ -192,37 +192,37 @@ governing permissions and limitations under the License.
192
192
  // Do a soap call GetModifiedEntities instead of xtksession.GetModifiedEnties because we don't want to go through methodCache
193
193
  // which might not contain the method GetModifiedEntities just after a build updgrade from a old version of acc
194
194
  // This is an internal SOAP call that cannot be intercepted by observers onBeforeCall / onAfterCall
195
- return this._client._makeSoapCall(soapCall)
196
- .then(() => {
197
- let doc = soapCall.getNextDocument();
198
- soapCall.checkNoMoreArgs();
199
- doc = that._client._toRepresentation(doc, 'xml');
200
- that._lastTime = DomUtil.getAttributeAsString(doc, "time"); // save time to be able to send it as an attribute in the next soap call
201
- that._buildNumber = DomUtil.getAttributeAsString(doc, "buildNumber");
202
- that._refresh(doc, event);
203
- that._refresherStateCache.put("time", that._lastTime);
204
- that._refresherStateCache.put("buildNumber", that._buildNumber);
205
- })
206
- .catch((ex) => {
207
- // if the method GetModifiedEntities is not found in this acc version we disable the autoresfresh of the cache
208
- if (soapCall.methodName == "GetModifiedEntities" && ex.errorCode == "SOP-330006") {
209
- this._client._trackEvent('CACHE_REFRESHER//abort', undefined, {
210
- cacheSchemaId: this._cacheSchemaId,
211
- error: ex,
212
- });
213
- this.stopAutoRefresh();
214
- } else {
215
- throw ex;
216
- }
217
- });
195
+ try {
196
+ await this._client._makeSoapCall(soapCall);
197
+ let doc = soapCall.getNextDocument();
198
+ soapCall.checkNoMoreArgs();
199
+ doc = that._client._toRepresentation(doc, 'xml');
200
+ that._lastTime = DomUtil.getAttributeAsString(doc, "time"); // save time to be able to send it as an attribute in the next soap call
201
+ that._buildNumber = DomUtil.getAttributeAsString(doc, "buildNumber");
202
+ await that._refresh(doc, event);
203
+ await that._refresherStateCache.put("time", that._lastTime);
204
+ await that._refresherStateCache.put("buildNumber", that._buildNumber);
205
+ }
206
+ catch(ex) {
207
+ // if the method GetModifiedEntities is not found in this acc version we disable the autoresfresh of the cache
208
+ if (soapCall.methodName == "GetModifiedEntities" && ex.errorCode == "SOP-330006") {
209
+ this._client._trackEvent('CACHE_REFRESHER//abort', undefined, {
210
+ cacheSchemaId: this._cacheSchemaId,
211
+ error: ex,
212
+ });
213
+ this.stopAutoRefresh();
214
+ } else {
215
+ throw ex;
216
+ }
217
+ };
218
218
  }
219
219
 
220
220
  // Refresh Cache : remove entities modified recently listed in xmlDoc
221
- _refresh(xmlDoc, event) {
221
+ async _refresh(xmlDoc, event) {
222
222
  const clearCache = XtkCaster.asBoolean(DomUtil.getAttributeAsString(xmlDoc, "emptyCache"));
223
223
  const evicted = [];
224
224
  if (clearCache == true) {
225
- this._cache.clear();
225
+ await this._cache.clear();
226
226
  } else {
227
227
  var child = DomUtil.getFirstChildElement(xmlDoc, "entityCache");
228
228
  while (child) {
@@ -230,7 +230,7 @@ governing permissions and limitations under the License.
230
230
  const schemaId = DomUtil.getAttributeAsString(child, "schema");
231
231
  if (schemaId === this._cacheSchemaId) {
232
232
  evicted.push(schemaId);
233
- this._cache.remove(pkSchemaId);
233
+ await this._cache.remove(pkSchemaId);
234
234
  // Notify listeners to refresh in SchemaCache
235
235
  if (schemaId === "xtk:schema") {
236
236
  const schemaIds = pkSchemaId.split("|");
package/src/client.js CHANGED
@@ -196,8 +196,7 @@ const clientHandler = (representation, headers, pushDownOptions) => {
196
196
  var promise = callContext.client._callMethod(methodName, callContext, argumentsList);
197
197
  return promise.then(function(optionAndValue) {
198
198
  const optionName = argumentsList[0];
199
- client._optionCache.put(optionName, optionAndValue);
200
- return optionAndValue;
199
+ return client._optionCache.put(optionName, optionAndValue).then(() => optionAndValue);
201
200
  });
202
201
  }
203
202
  // static method
@@ -308,6 +307,7 @@ class Credentials {
308
307
  * @property {boolean} noSDKHeaders - set to disable "ACC-SDK" HTTP headers
309
308
  * @property {boolean} noMethodInURL - Can be set to true to remove the method name from the URL
310
309
  * @property {number} timeout - Can be set to change the HTTP call timeout. Value is passed in ms.
310
+ * @property {string} cacheRootKey - "default" or "none" - determine the prefix to use for the keys in the caches of schemas, options, etc.
311
311
  * @memberOf Campaign
312
312
  */
313
313
 
@@ -379,6 +379,7 @@ class ConnectionParameters {
379
379
  this._options.clientApp = options.clientApp;
380
380
  this._options.noSDKHeaders = !!options.noSDKHeaders;
381
381
  this._options.noMethodInURL = !!options.noMethodInURL;
382
+ this._options.cacheRootKey = options.cacheRootKey === undefined ? "default": options.cacheRootKey;
382
383
  }
383
384
 
384
385
  /**
@@ -645,7 +646,14 @@ class Client {
645
646
  var instanceKey = connectionParameters._endpoint || "";
646
647
  if (instanceKey.startsWith("http://")) instanceKey = instanceKey.substr(7);
647
648
  if (instanceKey.startsWith("https://")) instanceKey = instanceKey.substr(8);
648
- const rootKey = `acc.js.sdk.${sdk.getSDKVersion().version}.${instanceKey}.cache`;
649
+
650
+ // Determine the cache root key. There are 3 possible values:
651
+ // * no value or "default" is the default behavior, i.e. all cache keys are prefixed with "acc.js.sdk.${sdk.getSDKVersion().version}.${instanceKey}.cache."
652
+ // * "none" (or actually anything else for now), where cache keys are not prefixed by anything
653
+ const rootKeyType = connectionParameters._options.cacheRootKey;
654
+ let rootKey = "";
655
+ if (!rootKeyType || rootKeyType === "default")
656
+ rootKey = `acc.js.sdk.${sdk.getSDKVersion().version}.${instanceKey}.cache.`;
649
657
 
650
658
  // Clear storage cache if the sdk versions or the instances are different
651
659
  if (this._storage && typeof this._storage.removeItem === 'function') {
@@ -656,11 +664,11 @@ class Client {
656
664
  }
657
665
  }
658
666
 
659
- this._entityCache = new XtkEntityCache(this._storage, `${rootKey}.XtkEntityCache`, connectionParameters._options.entityCacheTTL);
660
- this._entityCacheRefresher = new CacheRefresher(this._entityCache, this, "xtk:schema", `${rootKey}.XtkEntityCache`);
661
- this._methodCache = new MethodCache(this._storage, `${rootKey}.MethodCache`, connectionParameters._options.methodCacheTTL);
662
- this._optionCache = new OptionCache(this._storage, `${rootKey}.OptionCache`, connectionParameters._options.optionCacheTTL);
663
- this._optionCacheRefresher = new CacheRefresher(this._optionCache, this, "xtk:option", `${rootKey}.OptionCache`);
667
+ this._entityCache = new XtkEntityCache(this._storage, `${rootKey}XtkEntityCache`, connectionParameters._options.entityCacheTTL);
668
+ this._entityCacheRefresher = new CacheRefresher(this._entityCache, this, "xtk:schema", `${rootKey}XtkEntityCache`);
669
+ this._methodCache = new MethodCache(this._storage, `${rootKey}MethodCache`, connectionParameters._options.methodCacheTTL);
670
+ this._optionCache = new OptionCache(this._storage, `${rootKey}OptionCache`, connectionParameters._options.optionCacheTTL);
671
+ this._optionCacheRefresher = new CacheRefresher(this._optionCache, this, "xtk:option", `${rootKey}OptionCache`);
664
672
  this.NLWS = new Proxy(this, clientHandler());
665
673
 
666
674
  this._transport = connectionParameters._options.transport;
@@ -1447,11 +1455,11 @@ class Client {
1447
1455
  async getOption(name, useCache = true) {
1448
1456
  var value;
1449
1457
  if (useCache) {
1450
- value = this._optionCache.get(name);
1458
+ value = await this._optionCache.get(name);
1451
1459
  }
1452
1460
  if (value === undefined) {
1453
1461
  const option = await this.NLWS.xtkSession.getOption(name);
1454
- value = this._optionCache.put(name, option);
1462
+ value = await this._optionCache.put(name, option);
1455
1463
  }
1456
1464
  return value;
1457
1465
  }
@@ -1467,7 +1475,7 @@ class Client {
1467
1475
  async setOption(name, rawValue, description) {
1468
1476
  // First, read the current option value to make sure we have the right type
1469
1477
  await this.getOption(name, true);
1470
- const option = this._optionCache.getOption(name);
1478
+ const option = await this._optionCache.getOption(name);
1471
1479
  // Note: option is never null or undefined there: Campaign will return a value of type 0 and value ""
1472
1480
  var type = option.type;
1473
1481
  var value = XtkCaster.as(rawValue, type);
@@ -1483,40 +1491,41 @@ class Client {
1483
1491
  if (description != null && description != undefined)
1484
1492
  doc.description = description;
1485
1493
  doc[attName] = value;
1486
- return this.NLWS.xtkSession.write(doc).then(() => {
1487
- // Once set, cache the value
1488
- this._optionCache.put(name, [value, type]);
1489
- });
1494
+ await this.NLWS.xtkSession.write(doc);
1495
+ // Once set, cache the value
1496
+ await this._optionCache.put(name, [value, type]);
1490
1497
  }
1491
1498
 
1492
1499
  /**
1493
1500
  * Clears the options cache
1494
1501
  */
1495
- clearOptionCache() {
1496
- this._optionCache.clear();
1502
+ async clearOptionCache() {
1503
+ await this._optionCache.clear();
1497
1504
  }
1498
1505
 
1499
1506
  /**
1500
1507
  * Clears the method cache
1501
1508
  */
1502
- clearMethodCache() {
1503
- this._methodCache.clear();
1509
+ async clearMethodCache() {
1510
+ await this._methodCache.clear();
1504
1511
  }
1505
1512
 
1506
1513
  /**
1507
1514
  * Clears the entity cache
1508
1515
  */
1509
- clearEntityCache() {
1510
- this._entityCache.clear();
1516
+ async clearEntityCache() {
1517
+ await this._entityCache.clear();
1511
1518
  }
1512
1519
 
1513
1520
  /**
1514
1521
  * Clears all caches (options, methods, entities)
1515
1522
  */
1516
- clearAllCaches() {
1517
- this.clearEntityCache();
1518
- this.clearMethodCache();
1519
- this.clearOptionCache();
1523
+ async clearAllCaches() {
1524
+ return Promise.all([
1525
+ this.clearEntityCache(),
1526
+ this.clearMethodCache(),
1527
+ this.clearOptionCache(),
1528
+ ]);
1520
1529
  }
1521
1530
 
1522
1531
  /**
@@ -1629,7 +1638,7 @@ class Client {
1629
1638
  * @returns {XML.XtkObject} the schema definition, as either a DOM document or a JSON object
1630
1639
  */
1631
1640
  async getSchema(schemaId, representation, internal) {
1632
- var entity = this._entityCache.get("xtk:schema", schemaId);
1641
+ var entity = await this._entityCache.get("xtk:schema", schemaId);
1633
1642
  if (!entity) {
1634
1643
  entity = await this.getEntityIfMoreRecent("xtk:schema", schemaId, "xml", internal);
1635
1644
  if (entity) {
@@ -1638,8 +1647,8 @@ class Client {
1638
1647
  // Ensure xtk:persist is present by loading the xtk:session schema
1639
1648
  await this.getSchema("xtk:session", "xml", true);
1640
1649
  }
1641
- this._entityCache.put("xtk:schema", schemaId, entity);
1642
- this._methodCache.put(entity);
1650
+ await this._entityCache.put("xtk:schema", schemaId, entity);
1651
+ await this._methodCache.put(entity);
1643
1652
  }
1644
1653
  }
1645
1654
  entity = this._toRepresentation(entity, representation);
@@ -1714,24 +1723,24 @@ class Client {
1714
1723
  throw CampaignException.SOAP_UNKNOWN_METHOD(schemaId, methodName, `Schema '${schemaId}' not found`);
1715
1724
 
1716
1725
  // Lookup the method to call
1717
- var method = that._methodCache.get(methodSchemaId, methodName);
1726
+ var method = await that._methodCache.get(methodSchemaId, methodName);
1718
1727
  if (!method) {
1719
1728
  // first char of the method name may be lower case (ex: nms:seedMember.getAsModel) but the methodName
1720
1729
  // variable has been capitalized. Make an attempt to lookup method name without capitalisation
1721
1730
  const methodNameLC = methodName.substring(0, 1).toLowerCase() + methodName.substring(1);
1722
- method = that._methodCache.get(schemaId, methodNameLC);
1731
+ method = await that._methodCache.get(schemaId, methodNameLC);
1723
1732
  if (method) methodName = methodNameLC;
1724
1733
  }
1725
1734
  if (!method) {
1726
- this._methodCache.put(schema);
1727
- method = that._methodCache.get(methodSchemaId, methodName);
1735
+ await this._methodCache.put(schema);
1736
+ method = await that._methodCache.get(methodSchemaId, methodName);
1728
1737
  }
1729
1738
  if (!method)
1730
1739
  throw CampaignException.SOAP_UNKNOWN_METHOD(schemaId, methodName, `Method '${methodName}' of schema '${schemaId}' not found`);
1731
1740
 
1732
1741
  // Compute the SOAP URN. Again, specically handle xtk:jobInterface as it's not a real schema. The actual entity schema
1733
1742
  // would be available as the entitySchemaId property of the callContext
1734
- var urn = schemaId !== 'xtk:jobInterface' ? that._methodCache.getSoapUrn(schemaId, methodName)
1743
+ var urn = schemaId !== 'xtk:jobInterface' ? await that._methodCache.getSoapUrn(schemaId, methodName)
1735
1744
  : `xtk:jobInterface|${entitySchemaId}`;
1736
1745
 
1737
1746
  const isStatic = DomUtil.getAttributeAsBoolean(method, "static");
@@ -1881,6 +1890,7 @@ class Client {
1881
1890
  url: `${this._connectionParameters._endpoint}/nl/jsp/ping.jsp`,
1882
1891
  headers: {
1883
1892
  'X-Security-Token': this._securityToken,
1893
+ 'X-Session-Token': this._sessionToken,
1884
1894
  'Cookie': '__sessiontoken=' + this._sessionToken
1885
1895
  }
1886
1896
  };
@@ -1951,6 +1961,7 @@ class Client {
1951
1961
  url: `${this._connectionParameters._endpoint}/nl/jsp/mcPing.jsp`,
1952
1962
  headers: {
1953
1963
  'X-Security-Token': this._securityToken,
1964
+ 'X-Session-Token': this._sessionToken,
1954
1965
  'Cookie': '__sessiontoken=' + this._sessionToken
1955
1966
  }
1956
1967
  };