@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/src/client.js
CHANGED
|
@@ -10,14 +10,14 @@ 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";
|
|
14
|
-
|
|
13
|
+
"use strict";
|
|
14
|
+
|
|
15
15
|
|
|
16
16
|
/**********************************************************************************
|
|
17
|
-
*
|
|
17
|
+
*
|
|
18
18
|
* ACC JavaScript SDK
|
|
19
19
|
* See README.md for usage
|
|
20
|
-
*
|
|
20
|
+
*
|
|
21
21
|
*********************************************************************************/
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -39,16 +39,16 @@ const { Util } = require('./util.js');
|
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* @namespace Campaign
|
|
42
|
-
*
|
|
42
|
+
*
|
|
43
43
|
* @typedef {Object} SessionInfo
|
|
44
44
|
* @memberOf Campaign
|
|
45
|
-
*
|
|
45
|
+
*
|
|
46
46
|
* @typedef {Object} RedirStatus
|
|
47
47
|
* @memberOf Campaign
|
|
48
|
-
*
|
|
48
|
+
*
|
|
49
49
|
* @typedef {Object} PingStatus
|
|
50
50
|
* @memberOf Campaign
|
|
51
|
-
*
|
|
51
|
+
*
|
|
52
52
|
* @typedef {Object} McPingStatus
|
|
53
53
|
* @memberOf Campaign
|
|
54
54
|
*
|
|
@@ -59,14 +59,14 @@ const { Util } = require('./util.js');
|
|
|
59
59
|
|
|
60
60
|
/**
|
|
61
61
|
* Java Script Proxy handler for an XTK object. An XTK object is one constructed with the following syntax:
|
|
62
|
-
*
|
|
62
|
+
*
|
|
63
63
|
* <code>
|
|
64
64
|
* NLWS.xtkQueryDef.create(...)
|
|
65
65
|
* </code>
|
|
66
|
-
*
|
|
66
|
+
*
|
|
67
67
|
* Any Xtk methods can be called directly on such an object using this proxy handler which will lookup
|
|
68
68
|
* the method definition and manage parameters marshalling and SOAP call
|
|
69
|
-
*
|
|
69
|
+
*
|
|
70
70
|
* @private
|
|
71
71
|
* @memberof Campaign
|
|
72
72
|
*/
|
|
@@ -84,20 +84,20 @@ const xtkObjectHandler = {
|
|
|
84
84
|
return new Proxy(caller, {
|
|
85
85
|
apply: function(target, thisArg, argumentsList) {
|
|
86
86
|
return target(thisArg, argumentsList);
|
|
87
|
-
}
|
|
87
|
+
}
|
|
88
88
|
});
|
|
89
89
|
|
|
90
90
|
}
|
|
91
91
|
};
|
|
92
92
|
|
|
93
93
|
/**
|
|
94
|
-
* Java Script Proxy handler for NLWS.
|
|
94
|
+
* Java Script Proxy handler for NLWS.
|
|
95
95
|
* The proxy resolves constructs such as
|
|
96
|
-
*
|
|
96
|
+
*
|
|
97
97
|
* <code>
|
|
98
98
|
* result = await client.NLWS.xtkSession.getServerTime();
|
|
99
99
|
* </code>
|
|
100
|
-
*
|
|
100
|
+
*
|
|
101
101
|
* To get a handler, call the `clientHandler` function and optionally pass a representation.
|
|
102
102
|
* If no representation is passed (undefined), the representation set at the client level
|
|
103
103
|
* will be used, which is the default behavior.
|
|
@@ -195,7 +195,7 @@ const clientHandler = (representation, headers, pushDownOptions) => {
|
|
|
195
195
|
return new Proxy(caller, {
|
|
196
196
|
apply: function(target, thisArg, argumentsList) {
|
|
197
197
|
return target(thisArg, argumentsList);
|
|
198
|
-
}
|
|
198
|
+
}
|
|
199
199
|
});
|
|
200
200
|
}
|
|
201
201
|
});
|
|
@@ -207,7 +207,7 @@ const clientHandler = (representation, headers, pushDownOptions) => {
|
|
|
207
207
|
// Campaign credentials
|
|
208
208
|
// ========================================================================================
|
|
209
209
|
|
|
210
|
-
/**
|
|
210
|
+
/**
|
|
211
211
|
* @class
|
|
212
212
|
* @constructor
|
|
213
213
|
* @private
|
|
@@ -223,7 +223,7 @@ class Credentials {
|
|
|
223
223
|
* @param {string} securityToken the security token. Will use an empty token if not specified
|
|
224
224
|
*/
|
|
225
225
|
constructor(type, sessionToken, securityToken) {
|
|
226
|
-
if (type != "UserPassword" && type != "ImsServiceToken" && type != "SessionToken" &&
|
|
226
|
+
if (type != "UserPassword" && type != "ImsServiceToken" && type != "SessionToken" &&
|
|
227
227
|
type != "AnonymousUser" && type != "SecurityToken" && type != "BearerToken")
|
|
228
228
|
throw CampaignException.INVALID_CREDENTIALS_TYPE(type);
|
|
229
229
|
this._type = type;
|
|
@@ -237,7 +237,7 @@ class Credentials {
|
|
|
237
237
|
|
|
238
238
|
/**
|
|
239
239
|
* For "UserPassword" type credentials, return the user name
|
|
240
|
-
*
|
|
240
|
+
*
|
|
241
241
|
* @private
|
|
242
242
|
* @returns {string} the user name
|
|
243
243
|
*/
|
|
@@ -251,7 +251,7 @@ class Credentials {
|
|
|
251
251
|
|
|
252
252
|
/**
|
|
253
253
|
* For "UserPassword" type credentials, return the user password
|
|
254
|
-
*
|
|
254
|
+
*
|
|
255
255
|
* @private
|
|
256
256
|
* @returns {string} the user password
|
|
257
257
|
*/
|
|
@@ -289,7 +289,7 @@ class Credentials {
|
|
|
289
289
|
* @property {number} timeout - Can be set to change the HTTP call timeout. Value is passed in ms.
|
|
290
290
|
* @memberOf Campaign
|
|
291
291
|
*/
|
|
292
|
-
|
|
292
|
+
|
|
293
293
|
|
|
294
294
|
/**
|
|
295
295
|
* @class
|
|
@@ -331,7 +331,7 @@ class ConnectionParameters {
|
|
|
331
331
|
|
|
332
332
|
this._options.entityCacheTTL = options.entityCacheTTL || 1000*300; // 5 mins
|
|
333
333
|
this._options.methodCacheTTL = options.methodCacheTTL || 1000*300; // 5 mins
|
|
334
|
-
this._options.optionCacheTTL = options.optionCacheTTL || 1000*300; // 5 mins
|
|
334
|
+
this._options.optionCacheTTL = options.optionCacheTTL || 1000*300; // 5 mins
|
|
335
335
|
this._options.traceAPICalls = options.traceAPICalls === null || options.traceAPICalls ? !!options.traceAPICalls : false;
|
|
336
336
|
this._options.transport = options.transport || request;
|
|
337
337
|
|
|
@@ -343,10 +343,10 @@ class ConnectionParameters {
|
|
|
343
343
|
storage = options.storage;
|
|
344
344
|
try {
|
|
345
345
|
if (!storage)
|
|
346
|
-
storage = localStorage;
|
|
346
|
+
storage = localStorage;
|
|
347
347
|
} catch (ex) {
|
|
348
348
|
/* ignore error if localStorage not found */
|
|
349
|
-
}
|
|
349
|
+
}
|
|
350
350
|
}
|
|
351
351
|
this._options._storage = storage;
|
|
352
352
|
this._options.refreshClient = options.refreshClient;
|
|
@@ -362,7 +362,7 @@ class ConnectionParameters {
|
|
|
362
362
|
|
|
363
363
|
/**
|
|
364
364
|
* Creates connection parameters for a Campaign instance, using a user name and password
|
|
365
|
-
*
|
|
365
|
+
*
|
|
366
366
|
* @param {string} endpoint The campaign endpoint (URL)
|
|
367
367
|
* @param {string} user The user name
|
|
368
368
|
* @param {string} password The user password
|
|
@@ -376,7 +376,7 @@ class ConnectionParameters {
|
|
|
376
376
|
|
|
377
377
|
/**
|
|
378
378
|
* Creates connection parameters for a Campaign instance from bearer token
|
|
379
|
-
*
|
|
379
|
+
*
|
|
380
380
|
* @param {string} endpoint The campaign endpoint (URL)
|
|
381
381
|
* @param {string} bearerToken IMS bearer token
|
|
382
382
|
* @param {*} options connection options
|
|
@@ -388,7 +388,7 @@ class ConnectionParameters {
|
|
|
388
388
|
}
|
|
389
389
|
/**
|
|
390
390
|
* Creates connection parameters for a Campaign instance, using an IMS service token and a user name (the user to impersonate)
|
|
391
|
-
*
|
|
391
|
+
*
|
|
392
392
|
* @param {string} endpoint The campaign endpoint (URL)
|
|
393
393
|
* @param {string} user The user name
|
|
394
394
|
* @param {string} serviceToken The IMS service token
|
|
@@ -402,7 +402,7 @@ class ConnectionParameters {
|
|
|
402
402
|
|
|
403
403
|
/**
|
|
404
404
|
* Creates connection parameters for a Campaign instance, using a session token
|
|
405
|
-
*
|
|
405
|
+
*
|
|
406
406
|
* @static
|
|
407
407
|
* @param {string} endpoint The campaign endpoint (URL)
|
|
408
408
|
* @param {string} sessionToken The session token
|
|
@@ -419,7 +419,7 @@ class ConnectionParameters {
|
|
|
419
419
|
* Typically, called when embedding the SDK in Campaign: the session token will be
|
|
420
420
|
* passed automatically as a cookie, so only the security token is actually needed
|
|
421
421
|
* to logon
|
|
422
|
-
*
|
|
422
|
+
*
|
|
423
423
|
* @static
|
|
424
424
|
* @param {string} endpoint The campaign endpoint (URL)
|
|
425
425
|
* @param {string} securityToken The session token
|
|
@@ -433,7 +433,7 @@ class ConnectionParameters {
|
|
|
433
433
|
|
|
434
434
|
/**
|
|
435
435
|
* Creates connection parameters for a Campaign instance for an anonymous user
|
|
436
|
-
*
|
|
436
|
+
*
|
|
437
437
|
* @param {string} endpoint The campaign endpoint (URL)
|
|
438
438
|
* @param {Campaign.ConnectionOptions} options connection options
|
|
439
439
|
* @returns {ConnectionParameters} a ConnectionParameters object which can be used to create a Client
|
|
@@ -448,7 +448,7 @@ class ConnectionParameters {
|
|
|
448
448
|
* Creates connection parameters for a Campaign instance, using an external account. This can be used to connect
|
|
449
449
|
* to a mid-sourcing instance, or to a message center instance. This function will lookup the external account,
|
|
450
450
|
* and use its credentials to get connection parameters to the corresponding Campaign instance
|
|
451
|
-
*
|
|
451
|
+
*
|
|
452
452
|
* @param {Client} client The Campaign Client from which to lookup the external account (normally, a connected client to the marketing instance)
|
|
453
453
|
* @param {string} extAccountName The name of the external account. Only mid-sourcing accounts (type 3) are supported
|
|
454
454
|
* @returns {ConnectionParameters} a ConnectionParameters object which can be used to create a Client
|
|
@@ -494,6 +494,102 @@ class ConnectionParameters {
|
|
|
494
494
|
|
|
495
495
|
}
|
|
496
496
|
|
|
497
|
+
// ========================================================================================
|
|
498
|
+
// File Uploader
|
|
499
|
+
// ========================================================================================
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* File Uploader API for JS SDK(Currently available only in browsers)
|
|
503
|
+
* @private
|
|
504
|
+
* @ignore
|
|
505
|
+
* @memberof Campaign
|
|
506
|
+
* @param client
|
|
507
|
+
* @returns {{upload: (function(*=): Promise<{name: string, md5: string, type: string, size: string, url: string}>)}}
|
|
508
|
+
*/
|
|
509
|
+
const fileUploader = (client) => {
|
|
510
|
+
|
|
511
|
+
return {
|
|
512
|
+
/**
|
|
513
|
+
* This is the exposed/public method for fileUploader instance which will do all the processing related to the upload process internally and returns the promise containing all the required data.
|
|
514
|
+
* @ignore
|
|
515
|
+
* @param file, where file is an instance of [File](https://developer.mozilla.org/en-US/docs/Web/API/File)
|
|
516
|
+
* @returns {Promise<{name: string, md5: string, type: string, size: string, url: string}>}
|
|
517
|
+
*/
|
|
518
|
+
upload: (file) => {
|
|
519
|
+
console.log(`fileuploader.upload is an experimental feature and is not currently fully functional. It is work in progress and will change in the future.`);
|
|
520
|
+
return new Promise((resolve, reject) => {
|
|
521
|
+
try {
|
|
522
|
+
if (!Util.isBrowser()) {
|
|
523
|
+
throw 'File uploading is only supported in browser based calls.';
|
|
524
|
+
}
|
|
525
|
+
const data = new FormData();
|
|
526
|
+
data.append('file_noMd5', file);
|
|
527
|
+
//TODO: Needs to be refactored after cookie issue get resolved.
|
|
528
|
+
client._makeHttpCall({
|
|
529
|
+
url: `${client._connectionParameters._endpoint}/nl/jsp/uploadFile.jsp`,
|
|
530
|
+
processData: false,
|
|
531
|
+
credentials: 'include',
|
|
532
|
+
method: 'POST',
|
|
533
|
+
body: data,
|
|
534
|
+
headers: {
|
|
535
|
+
'x-security-token': client._securityToken,
|
|
536
|
+
'Cookie': '__sessiontoken=' + client._sessionToken,
|
|
537
|
+
}
|
|
538
|
+
}).then((okay) => {
|
|
539
|
+
if (!okay.startsWith('Ok')) {
|
|
540
|
+
throw okay;
|
|
541
|
+
}
|
|
542
|
+
const iframe = document.createElement('iframe');
|
|
543
|
+
iframe.style.height = 0;
|
|
544
|
+
iframe.style.width = 0;
|
|
545
|
+
document.controller = { // Written to support https://git.corp.adobe.com/Campaign/ac/blob/v6-master/nl/datakit/nl/jsp/uploadFile.jsp
|
|
546
|
+
uploadFileCallBack: async (data) => {
|
|
547
|
+
if (!data || data.length !== 1) {
|
|
548
|
+
// Tried to replicate the logic for file upload functionality written here:
|
|
549
|
+
// https://git.corp.adobe.com/Campaign/ac/blob/v6-master/wpp/xtk/web/dce/uploader.js
|
|
550
|
+
return reject(CampaignException.FILE_UPLOAD_FAILED(file.name, 'Malformed data:' + data.toString()));
|
|
551
|
+
}
|
|
552
|
+
const counter = await client.NLWS.xtkCounter.increaseValue({name: 'xtkResource'});
|
|
553
|
+
const fileRes= {
|
|
554
|
+
internalName: 'RES' + counter,
|
|
555
|
+
md5: data[0].md5,
|
|
556
|
+
label: data[0].fileName,
|
|
557
|
+
fileName: data[0].fileName,
|
|
558
|
+
originalName: data[0].fileName,
|
|
559
|
+
useMd5AsFilename: '1',
|
|
560
|
+
storageType: 5,
|
|
561
|
+
xtkschema: 'xtk:fileRes'
|
|
562
|
+
|
|
563
|
+
};
|
|
564
|
+
await client.NLWS.xtkSession.write(fileRes);
|
|
565
|
+
await client.NLWS.xtkFileRes.create(fileRes).publishIfNeeded();
|
|
566
|
+
const url = await client.NLWS.xtkFileRes.create(fileRes).getURL();
|
|
567
|
+
resolve({
|
|
568
|
+
name: data[0].fileName,
|
|
569
|
+
md5: data[0].md5,
|
|
570
|
+
type: file.type,
|
|
571
|
+
size: file.size,
|
|
572
|
+
url: url
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
const html = `<body>${okay}</body>`;
|
|
577
|
+
document.body.appendChild(iframe);
|
|
578
|
+
iframe.contentWindow.document.open();
|
|
579
|
+
iframe.contentWindow.document.write(html);
|
|
580
|
+
iframe.contentWindow.document.close();
|
|
581
|
+
}).catch((ex) => {
|
|
582
|
+
reject(CampaignException.FILE_UPLOAD_FAILED(file.name, ex));
|
|
583
|
+
});
|
|
584
|
+
} catch (ex) {
|
|
585
|
+
reject(CampaignException.FILE_UPLOAD_FAILED(file.name, ex));
|
|
586
|
+
}
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
};
|
|
590
|
+
};
|
|
591
|
+
|
|
592
|
+
|
|
497
593
|
// ========================================================================================
|
|
498
594
|
// ACC Client
|
|
499
595
|
// ========================================================================================
|
|
@@ -509,7 +605,7 @@ class Client {
|
|
|
509
605
|
/**
|
|
510
606
|
* ACC API Client.
|
|
511
607
|
* Do not create directly, use SDK.init instead
|
|
512
|
-
*
|
|
608
|
+
*
|
|
513
609
|
* @param {Campaign.SDK} sdk is the global sdk object used to create the client
|
|
514
610
|
* @param {Campaign.ConnectionParameters} user user name, for instance admin
|
|
515
611
|
*/
|
|
@@ -522,9 +618,9 @@ class Client {
|
|
|
522
618
|
this._sessionToken = undefined;
|
|
523
619
|
this._securityToken = undefined;
|
|
524
620
|
this._installedPackages = {}; // package set (key and value = package id, ex: "nms:amp")
|
|
525
|
-
|
|
621
|
+
|
|
526
622
|
this._secretKeyCipher = undefined;
|
|
527
|
-
|
|
623
|
+
|
|
528
624
|
this._storage = connectionParameters._options._storage;
|
|
529
625
|
// TODO late cache initiallzation because need XtkDatabaseId / instance name
|
|
530
626
|
var instanceKey = connectionParameters._endpoint || "";
|
|
@@ -546,13 +642,18 @@ class Client {
|
|
|
546
642
|
this._refreshClient = connectionParameters._options.refreshClient;
|
|
547
643
|
|
|
548
644
|
// expose utilities
|
|
645
|
+
/**
|
|
646
|
+
* File Uploader API
|
|
647
|
+
* @type {{upload: (function(*=): Promise<{name: string, md5: string, type: string, size: string, url: string}>)}}
|
|
648
|
+
*/
|
|
649
|
+
this.fileUploader = fileUploader(this);
|
|
549
650
|
|
|
550
|
-
/**
|
|
651
|
+
/**
|
|
551
652
|
* Accessor to DOM helpers
|
|
552
653
|
* @type {XML.DomUtil}
|
|
553
654
|
*/
|
|
554
655
|
this.DomUtil = DomUtil;
|
|
555
|
-
/**
|
|
656
|
+
/**
|
|
556
657
|
* Accessor to a XtkCaster
|
|
557
658
|
* @type {XtkCaster}
|
|
558
659
|
*/
|
|
@@ -562,12 +663,27 @@ class Client {
|
|
|
562
663
|
* @type {Campaign.Application}
|
|
563
664
|
*/
|
|
564
665
|
this.application = null;
|
|
666
|
+
|
|
667
|
+
// Context for observability. See logon() function which will fill this context
|
|
668
|
+
this._lastStatsReport = Date.now();
|
|
669
|
+
this._observabilityContext = {
|
|
670
|
+
eventId: 0,
|
|
671
|
+
client: {
|
|
672
|
+
sdkVersion: this.sdk.getSDKVersion().version,
|
|
673
|
+
endpoint: this._connectionParameters._endpoint,
|
|
674
|
+
createdAt: Date.now(),
|
|
675
|
+
clientApp: this._connectionParameters._options.clientApp,
|
|
676
|
+
}
|
|
677
|
+
};
|
|
678
|
+
if (this._connectionParameters._credentials) {
|
|
679
|
+
this._observabilityContext.client.type = this._connectionParameters._credentials.type;
|
|
680
|
+
}
|
|
565
681
|
}
|
|
566
682
|
|
|
567
683
|
/**
|
|
568
684
|
* Override the transport. By default, we are using axios, but this can be customised.
|
|
569
685
|
* See transport.js and documentation in the README for more details
|
|
570
|
-
* @param {*} transport
|
|
686
|
+
* @param {*} transport
|
|
571
687
|
*/
|
|
572
688
|
setTransport(transport) {
|
|
573
689
|
this._transport = transport;
|
|
@@ -575,7 +691,7 @@ class Client {
|
|
|
575
691
|
|
|
576
692
|
/**
|
|
577
693
|
* Get the user agent string to use in all HTTP requests
|
|
578
|
-
*
|
|
694
|
+
*
|
|
579
695
|
* @returns {string} the user agent string
|
|
580
696
|
*/
|
|
581
697
|
_getUserAgentString() {
|
|
@@ -585,7 +701,7 @@ class Client {
|
|
|
585
701
|
|
|
586
702
|
/**
|
|
587
703
|
* Convert an XML object into a representation
|
|
588
|
-
*
|
|
704
|
+
*
|
|
589
705
|
* @private
|
|
590
706
|
* @param {DOMElement} xml the XML DOM element to convert
|
|
591
707
|
* @param {string} representation the expected representation ('xml', 'BadgerFish', or 'SimpleJson'). If not set, will use the current representation
|
|
@@ -602,7 +718,7 @@ class Client {
|
|
|
602
718
|
|
|
603
719
|
/**
|
|
604
720
|
* Convert to an XML object from a representation
|
|
605
|
-
*
|
|
721
|
+
*
|
|
606
722
|
* @private
|
|
607
723
|
* @param {string} rootName the name of the root XML element
|
|
608
724
|
* @param {XML.XtkObject} entity the object to convert
|
|
@@ -622,7 +738,7 @@ class Client {
|
|
|
622
738
|
|
|
623
739
|
/**
|
|
624
740
|
* Convert between 2 representations
|
|
625
|
-
*
|
|
741
|
+
*
|
|
626
742
|
* @private
|
|
627
743
|
* @param {XML.XtkObject} entity the object to convert
|
|
628
744
|
* @param {string} fromRepresentation the source representation ('xml', 'BadgerFish', or 'SimpleJson').
|
|
@@ -640,7 +756,7 @@ class Client {
|
|
|
640
756
|
|
|
641
757
|
/**
|
|
642
758
|
* Compare two representations
|
|
643
|
-
*
|
|
759
|
+
*
|
|
644
760
|
* @private
|
|
645
761
|
* @param {string} rep1 the first representation ('xml', 'BadgerFish', or 'SimpleJson')
|
|
646
762
|
* @param {string} rep2 the second representation ('xml', 'BadgerFish', or 'SimpleJson')
|
|
@@ -656,7 +772,7 @@ class Client {
|
|
|
656
772
|
|
|
657
773
|
/**
|
|
658
774
|
* Activate / deactivate tracing of API calls
|
|
659
|
-
*
|
|
775
|
+
*
|
|
660
776
|
* @param {boolean} trace indicates whether to activate tracing or not
|
|
661
777
|
*/
|
|
662
778
|
traceAPICalls(trace) {
|
|
@@ -692,9 +808,67 @@ class Client {
|
|
|
692
808
|
this._observers.map((observer) => callback(observer));
|
|
693
809
|
}
|
|
694
810
|
|
|
811
|
+
_trackEvent(eventName, parentEvent, payload) {
|
|
812
|
+
try {
|
|
813
|
+
if (payload && payload.name === 'CampaignException') {
|
|
814
|
+
payload = {
|
|
815
|
+
detail: payload.detail,
|
|
816
|
+
errorCode: payload.errorCode,
|
|
817
|
+
faultCode: payload.faultCode,
|
|
818
|
+
faultString: payload.faultString,
|
|
819
|
+
message: payload.message,
|
|
820
|
+
statusCode: payload.statusCode,
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
this._observabilityContext.eventId = this._observabilityContext.eventId + 1;
|
|
824
|
+
const now = Date.now();
|
|
825
|
+
const event = {
|
|
826
|
+
client: this._observabilityContext.client,
|
|
827
|
+
session: this._observabilityContext.session,
|
|
828
|
+
eventId: this._observabilityContext.eventId,
|
|
829
|
+
eventName: eventName,
|
|
830
|
+
payload: payload,
|
|
831
|
+
timestamp: now,
|
|
832
|
+
};
|
|
833
|
+
if (parentEvent) event.parentEventId = parentEvent.eventId;
|
|
834
|
+
this._notifyObservers((observer) => observer.event && observer.event(event, parentEvent));
|
|
835
|
+
|
|
836
|
+
// Regularly report internal stats every 5 mins
|
|
837
|
+
if ((now - this._lastStatsReport) >= 300000) {
|
|
838
|
+
this._lastStatsReport = now;
|
|
839
|
+
this._trackInternalStats();
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
return event;
|
|
843
|
+
} catch (error) {
|
|
844
|
+
console.info(`Failed to track observability event`, error);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
_trackInternalStats() {
|
|
849
|
+
this._trackCacheStats('entityCache', this._entityCache);
|
|
850
|
+
this._trackCacheStats('optionCache', this._optionCache);
|
|
851
|
+
this._trackCacheStats('methodCache', this._methodCache);
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
_trackCacheStats(name, cache) {
|
|
855
|
+
if (!cache || !cache._stats) return;
|
|
856
|
+
this._trackEvent('CACHE//stats', undefined, {
|
|
857
|
+
name: name,
|
|
858
|
+
reads: cache._stats.reads,
|
|
859
|
+
writes: cache._stats.writes,
|
|
860
|
+
removals: cache._stats.removals,
|
|
861
|
+
clears: cache._stats.clears,
|
|
862
|
+
memoryHits: cache._stats.memoryHits,
|
|
863
|
+
storageHits: cache._stats.storageHits,
|
|
864
|
+
loads: cache._stats.loads,
|
|
865
|
+
saves: cache._stats.saves,
|
|
866
|
+
});
|
|
867
|
+
}
|
|
868
|
+
|
|
695
869
|
/**
|
|
696
870
|
* Is the client logged?
|
|
697
|
-
*
|
|
871
|
+
*
|
|
698
872
|
* @returns {boolean} a boolean indicating if the client is logged or not
|
|
699
873
|
*/
|
|
700
874
|
isLogged() {
|
|
@@ -729,7 +903,7 @@ class Client {
|
|
|
729
903
|
|
|
730
904
|
/**
|
|
731
905
|
* Prepares a SOAP call, including authentication, headers...
|
|
732
|
-
*
|
|
906
|
+
*
|
|
733
907
|
* @private
|
|
734
908
|
* @param {string} urn is the API name space, usually the schema. For instance xtk:session
|
|
735
909
|
* @param {string} method is the method to call, for instance Logon
|
|
@@ -738,8 +912,8 @@ class Client {
|
|
|
738
912
|
* parameters should be set
|
|
739
913
|
*/
|
|
740
914
|
_prepareSoapCall(urn, method, internal, extraHttpHeaders, pushDownOptions) {
|
|
741
|
-
const soapCall = new SoapMethodCall(this._transport, urn, method,
|
|
742
|
-
this._sessionToken, this._securityToken,
|
|
915
|
+
const soapCall = new SoapMethodCall(this._transport, urn, method,
|
|
916
|
+
this._sessionToken, this._securityToken,
|
|
743
917
|
this._getUserAgentString(),
|
|
744
918
|
Object.assign({}, this._connectionParameters._options, pushDownOptions),
|
|
745
919
|
extraHttpHeaders);
|
|
@@ -757,16 +931,30 @@ class Client {
|
|
|
757
931
|
async _retrySoapCall(soapCall) {
|
|
758
932
|
soapCall.retry = false;
|
|
759
933
|
soapCall._retryCount = soapCall._retryCount + 1;
|
|
760
|
-
var newClient = await this._refreshClient(this);
|
|
934
|
+
var newClient = await this._refreshClient(this);
|
|
761
935
|
soapCall.finalize(newClient._soapEndPoint(), newClient);
|
|
936
|
+
const safeCallData = Util.trim(soapCall.request.data);
|
|
762
937
|
if (this._traceAPICalls) {
|
|
763
|
-
const safeCallData = Util.trim(soapCall.request.data);
|
|
764
938
|
console.log(`RETRY SOAP//request ${safeCallData}`);
|
|
765
939
|
}
|
|
766
|
-
|
|
767
|
-
|
|
940
|
+
const event = this._trackEvent('SOAP//request', undefined, {
|
|
941
|
+
urn: soapCall.urn,
|
|
942
|
+
methodName: soapCall.methodName,
|
|
943
|
+
internal: soapCall.internal,
|
|
944
|
+
retry: true,
|
|
945
|
+
retryCount: soapCall._retryCount,
|
|
946
|
+
safeCallData: safeCallData,
|
|
947
|
+
});
|
|
948
|
+
try {
|
|
949
|
+
await soapCall.execute();
|
|
768
950
|
const safeCallResponse = Util.trim(soapCall.response);
|
|
769
|
-
|
|
951
|
+
if (this._traceAPICalls) {
|
|
952
|
+
console.log(`SOAP//response ${safeCallResponse}`);
|
|
953
|
+
}
|
|
954
|
+
this._trackEvent('SOAP//response', event, { safeCallResponse: safeCallResponse });
|
|
955
|
+
} catch(error) {
|
|
956
|
+
this._trackEvent('SOAP//failure', event, error);
|
|
957
|
+
throw error;
|
|
770
958
|
}
|
|
771
959
|
return;
|
|
772
960
|
}
|
|
@@ -783,7 +971,7 @@ class Client {
|
|
|
783
971
|
/**
|
|
784
972
|
* After a SOAP method call has been prepared with '_prepareSoapCall', and parameters have been added,
|
|
785
973
|
* this function actually executes the SOAP call
|
|
786
|
-
*
|
|
974
|
+
*
|
|
787
975
|
* @private
|
|
788
976
|
* @param {SOAP.SoapMethodCall} soapCall the SOAP method to call
|
|
789
977
|
*/
|
|
@@ -792,24 +980,34 @@ class Client {
|
|
|
792
980
|
if (soapCall.requiresLogon() && !that.isLogged())
|
|
793
981
|
throw CampaignException.NOT_LOGGED_IN(soapCall, `Cannot execute SOAP call ${soapCall.urn}#${soapCall.methodName}: you are not logged in. Use the Logon function first`);
|
|
794
982
|
soapCall.finalize(this._soapEndPoint());
|
|
795
|
-
|
|
983
|
+
|
|
796
984
|
const safeCallData = Util.trim(soapCall.request.data);
|
|
797
985
|
if (that._traceAPICalls)
|
|
798
986
|
console.log(`SOAP//request ${safeCallData}`);
|
|
799
987
|
that._notifyObservers((observer) => observer.onSOAPCall && observer.onSOAPCall(soapCall, safeCallData) );
|
|
800
|
-
|
|
988
|
+
|
|
989
|
+
const event = this._trackEvent('SOAP//request', undefined, {
|
|
990
|
+
urn: soapCall.urn,
|
|
991
|
+
methodName: soapCall.methodName,
|
|
992
|
+
internal: soapCall.internal,
|
|
993
|
+
retry: false,
|
|
994
|
+
retryCount: soapCall._retryCount,
|
|
995
|
+
safeCallData: safeCallData,
|
|
996
|
+
});
|
|
801
997
|
return soapCall.execute()
|
|
802
998
|
.then(() => {
|
|
803
999
|
const safeCallResponse = Util.trim(soapCall.response);
|
|
804
1000
|
if (that._traceAPICalls)
|
|
805
1001
|
console.log(`SOAP//response ${safeCallResponse}`);
|
|
806
1002
|
that._notifyObservers((observer) => observer.onSOAPCallSuccess && observer.onSOAPCallSuccess(soapCall, safeCallResponse) );
|
|
1003
|
+
this._trackEvent('SOAP//response', event, { safeCallResponse: safeCallResponse });
|
|
807
1004
|
return Promise.resolve();
|
|
808
1005
|
})
|
|
809
1006
|
.catch((ex) => {
|
|
810
1007
|
if (that._traceAPICalls)
|
|
811
1008
|
console.log(`SOAP//failure ${ex.toString()}`);
|
|
812
1009
|
that._notifyObservers((observer) => observer.onSOAPCallFailure && observer.onSOAPCallFailure(soapCall, ex) );
|
|
1010
|
+
this._trackEvent('SOAP//failure', event, ex);
|
|
813
1011
|
// Call session expiration callback in case of 401
|
|
814
1012
|
if (ex.statusCode == 401 && that._refreshClient && soapCall.retry) {
|
|
815
1013
|
return this._retrySoapCall(soapCall);
|
|
@@ -819,6 +1017,32 @@ class Client {
|
|
|
819
1017
|
});
|
|
820
1018
|
}
|
|
821
1019
|
|
|
1020
|
+
_onLogon() {
|
|
1021
|
+
this.application = new Application(this);
|
|
1022
|
+
this.application._registerCacheChangeListener();
|
|
1023
|
+
this._observabilityContext.instance = {
|
|
1024
|
+
buildNumber: this.application.buildNumber,
|
|
1025
|
+
version: this.application.version,
|
|
1026
|
+
instanceName: this.application.instanceName,
|
|
1027
|
+
};
|
|
1028
|
+
if (this.application.operator) {
|
|
1029
|
+
this._observabilityContext.instance.operator = {
|
|
1030
|
+
login: this.application.operator.login,
|
|
1031
|
+
id: this.application.operator.id,
|
|
1032
|
+
timezone: this.application.operator.timezone,
|
|
1033
|
+
rights: this.application.operator.rights,
|
|
1034
|
+
packages: this.application.operator.packages,
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
1037
|
+
this._observabilityContext.session = {
|
|
1038
|
+
logonAt: Date.now(),
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
_onLogoff() {
|
|
1043
|
+
delete this._observabilityContext.instance;
|
|
1044
|
+
delete this._observabilityContext.session;
|
|
1045
|
+
}
|
|
822
1046
|
|
|
823
1047
|
/**
|
|
824
1048
|
* Login to an instance
|
|
@@ -843,6 +1067,8 @@ class Client {
|
|
|
843
1067
|
// See NEO-35259
|
|
844
1068
|
this._connectionParameters._options.extraHttpHeaders['X-Query-Source'] = `${version}${clientApp? "," + clientApp : ""}`;
|
|
845
1069
|
|
|
1070
|
+
this._trackEvent('SDK//logon', undefined, {});
|
|
1071
|
+
|
|
846
1072
|
// Clear session token cookie to ensure we're not inheriting an expired cookie. See NEO-26589
|
|
847
1073
|
if (credentials._type != "SecurityToken" && typeof document != "undefined") {
|
|
848
1074
|
document.cookie = '__sessiontoken=;path=/;';
|
|
@@ -852,8 +1078,7 @@ class Client {
|
|
|
852
1078
|
that._installedPackages = {};
|
|
853
1079
|
that._sessionToken = credentials._sessionToken;
|
|
854
1080
|
that._securityToken = "";
|
|
855
|
-
that.
|
|
856
|
-
that.application._registerCacheChangeListener();
|
|
1081
|
+
that._onLogon();
|
|
857
1082
|
return Promise.resolve();
|
|
858
1083
|
}
|
|
859
1084
|
else if (credentials._type == "SecurityToken") {
|
|
@@ -861,8 +1086,7 @@ class Client {
|
|
|
861
1086
|
that._installedPackages = {};
|
|
862
1087
|
that._sessionToken = "";
|
|
863
1088
|
that._securityToken = credentials._securityToken;
|
|
864
|
-
that.
|
|
865
|
-
that.application._registerCacheChangeListener();
|
|
1089
|
+
that._onLogon();
|
|
866
1090
|
return Promise.resolve();
|
|
867
1091
|
}
|
|
868
1092
|
else if (credentials._type == "UserPassword" || credentials._type == "BearerToken") {
|
|
@@ -886,10 +1110,10 @@ class Client {
|
|
|
886
1110
|
else {
|
|
887
1111
|
const bearerToken = credentials._bearerToken;
|
|
888
1112
|
soapCall.writeString("bearerToken", bearerToken);
|
|
889
|
-
}
|
|
1113
|
+
}
|
|
890
1114
|
return this._makeSoapCall(soapCall).then(function() {
|
|
891
1115
|
const sessionToken = soapCall.getNextString();
|
|
892
|
-
|
|
1116
|
+
|
|
893
1117
|
that._sessionInfo = soapCall.getNextDocument();
|
|
894
1118
|
that._installedPackages = {};
|
|
895
1119
|
const userInfo = DomUtil.findElement(that._sessionInfo, "userInfo");
|
|
@@ -901,7 +1125,7 @@ class Client {
|
|
|
901
1125
|
that._installedPackages[name] = name;
|
|
902
1126
|
pack = DomUtil.getNextSiblingElement(pack);
|
|
903
1127
|
}
|
|
904
|
-
|
|
1128
|
+
|
|
905
1129
|
const securityToken = soapCall.getNextString();
|
|
906
1130
|
soapCall.checkNoMoreArgs();
|
|
907
1131
|
// Sanity check: we should have both a session token and a security token.
|
|
@@ -913,8 +1137,7 @@ class Client {
|
|
|
913
1137
|
that._sessionToken = sessionToken;
|
|
914
1138
|
that._securityToken = securityToken;
|
|
915
1139
|
|
|
916
|
-
that.
|
|
917
|
-
that.application._registerCacheChangeListener();
|
|
1140
|
+
that._onLogon();
|
|
918
1141
|
});
|
|
919
1142
|
}
|
|
920
1143
|
else {
|
|
@@ -925,7 +1148,7 @@ class Client {
|
|
|
925
1148
|
|
|
926
1149
|
/**
|
|
927
1150
|
* Get details about the session (assumes client is logged)
|
|
928
|
-
*
|
|
1151
|
+
*
|
|
929
1152
|
* @param {string} representation the expected representation. If not set, will use the default client representation
|
|
930
1153
|
* @returns {Campaign.SessionInfo} details about the session
|
|
931
1154
|
*/
|
|
@@ -939,30 +1162,35 @@ class Client {
|
|
|
939
1162
|
*/
|
|
940
1163
|
logoff() {
|
|
941
1164
|
var that = this;
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
1165
|
+
try {
|
|
1166
|
+
if (!that.isLogged()) return;
|
|
1167
|
+
that.application._unregisterCacheChangeListener();
|
|
1168
|
+
that._unregisterAllCacheChangeListeners();
|
|
1169
|
+
this.stopRefreshCaches();
|
|
1170
|
+
const credentials = this._connectionParameters._credentials;
|
|
1171
|
+
if (credentials._type != "SessionToken" && credentials._type != "AnonymousUser") {
|
|
1172
|
+
var soapCall = that._prepareSoapCall("xtk:session", "Logoff", false, this._connectionParameters._options.extraHttpHeaders);
|
|
1173
|
+
return this._makeSoapCall(soapCall).then(function() {
|
|
1174
|
+
that._sessionToken = "";
|
|
1175
|
+
that._securityToken = "";
|
|
1176
|
+
that.application = null;
|
|
1177
|
+
soapCall.checkNoMoreArgs();
|
|
1178
|
+
});
|
|
1179
|
+
}
|
|
1180
|
+
else {
|
|
950
1181
|
that._sessionToken = "";
|
|
951
1182
|
that._securityToken = "";
|
|
952
1183
|
that.application = null;
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
that._sessionToken = "";
|
|
958
|
-
that._securityToken = "";
|
|
959
|
-
that.application = null;
|
|
1184
|
+
}
|
|
1185
|
+
} finally {
|
|
1186
|
+
this._trackEvent('SDK//logoff', undefined, {});
|
|
1187
|
+
this._onLogoff();
|
|
960
1188
|
}
|
|
961
1189
|
}
|
|
962
1190
|
|
|
963
1191
|
/**
|
|
964
1192
|
* Get the value of an option
|
|
965
|
-
*
|
|
1193
|
+
*
|
|
966
1194
|
* @param {string} name is the option name, for instance XtkDatabaseId
|
|
967
1195
|
* @param {boolean} useCache indicates whether to use the cache or not. Default is true
|
|
968
1196
|
* @return the option value, casted in the expected data type. If the option does not exist, it will return null.
|
|
@@ -982,7 +1210,7 @@ class Client {
|
|
|
982
1210
|
/**
|
|
983
1211
|
* Set an option value. Creates the option if it does not exists. Update the option
|
|
984
1212
|
* if it exists already
|
|
985
|
-
*
|
|
1213
|
+
*
|
|
986
1214
|
* @param {string} name the option name
|
|
987
1215
|
* @param {*} rawValue the value to set
|
|
988
1216
|
* @param {string} description the optional description of the option
|
|
@@ -999,7 +1227,7 @@ class Client {
|
|
|
999
1227
|
var attName = XtkCaster._variantStorageAttribute(type);
|
|
1000
1228
|
if (!attName) {
|
|
1001
1229
|
// could not infer the storage type of the attribute to use to store the value (when option did not exist before) => assume string
|
|
1002
|
-
type = 6;
|
|
1230
|
+
type = 6;
|
|
1003
1231
|
attName = "stringValue";
|
|
1004
1232
|
}
|
|
1005
1233
|
var doc = { xtkschema: "xtk:option", _operation: "insertOrUpdate", _key: "@name", name: name, dataType: type };
|
|
@@ -1088,7 +1316,7 @@ class Client {
|
|
|
1088
1316
|
|
|
1089
1317
|
/**
|
|
1090
1318
|
* Tests if a package is installed
|
|
1091
|
-
*
|
|
1319
|
+
*
|
|
1092
1320
|
* @param {string} packageId the package identifier, for instance: "nms:amp"
|
|
1093
1321
|
* @param {string} optionalName if set, the first parameter will be interpreted as the namespace (ex: "nms") and the second as the name, ex: "amp"
|
|
1094
1322
|
* @returns {boolean} a boolean indicating if the package is installed or not
|
|
@@ -1103,8 +1331,8 @@ class Client {
|
|
|
1103
1331
|
|
|
1104
1332
|
/**
|
|
1105
1333
|
* Obtains a cipher that can be used to encrypt/decrypt passwords, using the database secret key.
|
|
1106
|
-
* This is used for example for mid-sourcing account.
|
|
1107
|
-
*
|
|
1334
|
+
* This is used for example for mid-sourcing account.
|
|
1335
|
+
*
|
|
1108
1336
|
* @private
|
|
1109
1337
|
* @deprecated since version 1.0.0
|
|
1110
1338
|
*/
|
|
@@ -1119,10 +1347,10 @@ class Client {
|
|
|
1119
1347
|
|
|
1120
1348
|
/**
|
|
1121
1349
|
* Gets an entity, such as a schema, a source schema, a form, a navtree, etc. Each Campaign entity has a MD5 which is used to determine
|
|
1122
|
-
* if an entity has changed or not. The GetEntityIfMoreRecent SOAP call can use this MD5 to avoid returning entities that did not
|
|
1350
|
+
* if an entity has changed or not. The GetEntityIfMoreRecent SOAP call can use this MD5 to avoid returning entities that did not
|
|
1123
1351
|
* actually changed. Currently, the SDK, however is not able to use the MD5 and will perform a SOAP call every time the function is
|
|
1124
1352
|
* called and return the whole entity
|
|
1125
|
-
*
|
|
1353
|
+
*
|
|
1126
1354
|
* @param {string} entityType is the type of entity requested, such as "xtk:schema", "xtk:srcSchema", "xtk:navtree", "xtk:form", etc.
|
|
1127
1355
|
* @param {string} fullName is the fully qualified name of the entity (i.e. <namespace>:<name>)
|
|
1128
1356
|
* @param {string} representation the expected representation, or undefined to set the default
|
|
@@ -1145,7 +1373,7 @@ class Client {
|
|
|
1145
1373
|
|
|
1146
1374
|
/**
|
|
1147
1375
|
* Get a compiled schema (not a source schema) definition as a DOM or JSON object depending on hte current representation
|
|
1148
|
-
*
|
|
1376
|
+
*
|
|
1149
1377
|
* @param {string} schemaId the schema id, such as "xtk:session", or "nms:recipient"
|
|
1150
1378
|
* @param {string} representation an optional representation of the schema: "BadgerFish", "SimpleJson" or "xml". If not set, we'll use the client default representation
|
|
1151
1379
|
* @param {boolean} internal indicates an "internal" call, i.e. a call performed by the SDK itself rather than the user of the SDK. For instance, the SDK will dynamically load schemas to find method definitions
|
|
@@ -1167,7 +1395,7 @@ class Client {
|
|
|
1167
1395
|
|
|
1168
1396
|
/**
|
|
1169
1397
|
* Get the definition of a system enumeration (SysEnum). Will be returned as JSON or XML depending on the client 'representation' attribute
|
|
1170
|
-
*
|
|
1398
|
+
*
|
|
1171
1399
|
* @param {string} enumName
|
|
1172
1400
|
* @param {string} optionalStartSchemaOrSchemaName
|
|
1173
1401
|
* @returns {XML.XtkObject} the enumeration definition in the current representation
|
|
@@ -1193,13 +1421,13 @@ class Client {
|
|
|
1193
1421
|
if (index == -1)
|
|
1194
1422
|
throw CampaignException.BAD_PARAMETER("optionalStartSchemaOrSchemaName", optionalStartSchemaOrSchemaName, `getEnum expects a valid schema name. '${optionalStartSchemaOrSchemaName}' is not a valid name.`);
|
|
1195
1423
|
optionalStartSchemaOrSchemaName = await this.getSchema(optionalStartSchemaOrSchemaName, undefined, true);
|
|
1196
|
-
if (!optionalStartSchemaOrSchemaName)
|
|
1424
|
+
if (!optionalStartSchemaOrSchemaName)
|
|
1197
1425
|
throw CampaignException.BAD_PARAMETER("optionalStartSchemaOrSchemaName", optionalStartSchemaOrSchemaName, `Schema '${optionalStartSchemaOrSchemaName}' not found.`);
|
|
1198
1426
|
}
|
|
1199
|
-
else
|
|
1427
|
+
else
|
|
1200
1428
|
throw CampaignException.BAD_PARAMETER("optionalStartSchemaOrSchemaName", optionalStartSchemaOrSchemaName, `getEnum expects a valid schema name wich is a string. Given ${typeof optionalStartSchemaOrSchemaName} instead`);
|
|
1201
1429
|
|
|
1202
|
-
const schema = optionalStartSchemaOrSchemaName;
|
|
1430
|
+
const schema = optionalStartSchemaOrSchemaName;
|
|
1203
1431
|
for (const e of EntityAccessor.getChildElements(schema, "enumeration")) {
|
|
1204
1432
|
const n = EntityAccessor.getAttributeAsString(e, "name");
|
|
1205
1433
|
if (n == enumName)
|
|
@@ -1209,7 +1437,7 @@ class Client {
|
|
|
1209
1437
|
|
|
1210
1438
|
/**
|
|
1211
1439
|
* Call Campaign SOAP method
|
|
1212
|
-
*
|
|
1440
|
+
*
|
|
1213
1441
|
* @private
|
|
1214
1442
|
* @param {string} methodName is the method to call. In order to be more JavaScript friendly, the first char can be lower-cased
|
|
1215
1443
|
* @param {*} callContext the call context)
|
|
@@ -1220,7 +1448,7 @@ class Client {
|
|
|
1220
1448
|
const that = this;
|
|
1221
1449
|
const result = [];
|
|
1222
1450
|
const schemaId = callContext.schemaId;
|
|
1223
|
-
|
|
1451
|
+
|
|
1224
1452
|
var schema = await that.getSchema(schemaId, "xml", true);
|
|
1225
1453
|
if (!schema)
|
|
1226
1454
|
throw CampaignException.SOAP_UNKNOWN_METHOD(schemaId, methodName, `Schema '${schemaId}' not found`);
|
|
@@ -1315,7 +1543,7 @@ class Client {
|
|
|
1315
1543
|
param = DomUtil.getNextSiblingElement(param, "param");
|
|
1316
1544
|
}
|
|
1317
1545
|
}
|
|
1318
|
-
|
|
1546
|
+
|
|
1319
1547
|
return that._makeSoapCall(soapCall).then(function() {
|
|
1320
1548
|
if (!isStatic) {
|
|
1321
1549
|
// Non static methods, such as xtk:query#SelectAll return a element named "entity" which is the object itself on which
|
|
@@ -1414,30 +1642,40 @@ class Client {
|
|
|
1414
1642
|
request.headers = request.headers || [];
|
|
1415
1643
|
if (!request.headers['User-Agent'])
|
|
1416
1644
|
request.headers['User-Agent'] = this._getUserAgentString();
|
|
1645
|
+
let event;
|
|
1417
1646
|
try {
|
|
1418
1647
|
const safeCallData = Util.trim(request.data);
|
|
1419
1648
|
if (this._traceAPICalls)
|
|
1420
1649
|
console.log(`HTTP//request ${request.method} ${request.url}${safeCallData ? " " + safeCallData : ""}`);
|
|
1421
1650
|
this._notifyObservers((observer) => observer.onHTTPCall && observer.onHTTPCall(request, safeCallData) );
|
|
1651
|
+
event = this._trackEvent('HTTP//request', undefined, {
|
|
1652
|
+
url: request.url,
|
|
1653
|
+
method: request.method,
|
|
1654
|
+
headers: request.request,
|
|
1655
|
+
safeCallData: safeCallData,
|
|
1656
|
+
});
|
|
1422
1657
|
const body = await this._transport(request);
|
|
1423
1658
|
|
|
1424
1659
|
const safeCallResponse = Util.trim(body);
|
|
1425
1660
|
if (this._traceAPICalls)
|
|
1426
1661
|
console.log(`HTTP//response${safeCallResponse ? " " + safeCallResponse : ""}`);
|
|
1427
1662
|
this._notifyObservers((observer) => observer.onHTTPCallSuccess && observer.onHTTPCallSuccess(request, safeCallResponse) );
|
|
1663
|
+
this._trackEvent('HTTP//response', event, { safeCallResponse: safeCallResponse });
|
|
1428
1664
|
return body;
|
|
1429
1665
|
} catch(err) {
|
|
1430
1666
|
if (this._traceAPICalls)
|
|
1431
1667
|
console.log("HTTP//failure", err);
|
|
1432
1668
|
this._notifyObservers((observer) => observer.onHTTPCallFailure && observer.onHTTPCallFailure(request, err) );
|
|
1433
|
-
|
|
1669
|
+
const ex = makeCampaignException({ request:request, reqponse:err.response }, err);
|
|
1670
|
+
this._trackEvent('HTTP//failure', event, { }, ex);
|
|
1671
|
+
throw ex;
|
|
1434
1672
|
}
|
|
1435
1673
|
}
|
|
1436
1674
|
|
|
1437
1675
|
/**
|
|
1438
1676
|
* Tests if the Campaign redirection server is up (/r/test).
|
|
1439
1677
|
* Does not require a logged client
|
|
1440
|
-
*
|
|
1678
|
+
*
|
|
1441
1679
|
* @returns {Campaign.RedirStatus} an object describing the status of the redirection server
|
|
1442
1680
|
*/
|
|
1443
1681
|
async test() {
|
|
@@ -1455,12 +1693,12 @@ class Client {
|
|
|
1455
1693
|
|
|
1456
1694
|
/**
|
|
1457
1695
|
* Ping the Campaign server (/nl/jsp/ping.jsp)
|
|
1458
|
-
*
|
|
1696
|
+
*
|
|
1459
1697
|
* @returns {Campaign.PingStatus} an object describing the server status
|
|
1460
1698
|
*/
|
|
1461
1699
|
async ping() {
|
|
1462
1700
|
const request = {
|
|
1463
|
-
url: `${this._connectionParameters._endpoint}/nl/jsp/ping.jsp`,
|
|
1701
|
+
url: `${this._connectionParameters._endpoint}/nl/jsp/ping.jsp`,
|
|
1464
1702
|
headers: {
|
|
1465
1703
|
'X-Security-Token': this._securityToken,
|
|
1466
1704
|
'Cookie': '__sessiontoken=' + this._sessionToken
|
|
@@ -1486,12 +1724,12 @@ class Client {
|
|
|
1486
1724
|
/**
|
|
1487
1725
|
* Ping a Message Center Campaign server (/nl/jsp/mcPing.jsp).
|
|
1488
1726
|
* Assumes Message Center is installed
|
|
1489
|
-
*
|
|
1727
|
+
*
|
|
1490
1728
|
* @returns {Campaign.McPingStatus} an object describing Message Center server status
|
|
1491
1729
|
*/
|
|
1492
1730
|
async mcPing() {
|
|
1493
1731
|
const request = {
|
|
1494
|
-
url: `${this._connectionParameters._endpoint}/nl/jsp/mcPing.jsp`,
|
|
1732
|
+
url: `${this._connectionParameters._endpoint}/nl/jsp/mcPing.jsp`,
|
|
1495
1733
|
headers: {
|
|
1496
1734
|
'X-Security-Token': this._securityToken,
|
|
1497
1735
|
'Cookie': '__sessiontoken=' + this._sessionToken
|
|
@@ -1505,7 +1743,7 @@ class Client {
|
|
|
1505
1743
|
const root = doc.documentElement;
|
|
1506
1744
|
var status = lines[0].trim();
|
|
1507
1745
|
if (status != "") root.setAttribute("status", status);
|
|
1508
|
-
|
|
1746
|
+
|
|
1509
1747
|
var rtCount;
|
|
1510
1748
|
var threshold;
|
|
1511
1749
|
if (status == "Error") {
|
|
@@ -1548,4 +1786,4 @@ exports.Client = Client;
|
|
|
1548
1786
|
exports.Credentials = Credentials;
|
|
1549
1787
|
exports.ConnectionParameters = ConnectionParameters;
|
|
1550
1788
|
|
|
1551
|
-
})();
|
|
1789
|
+
})();
|