@adobe/acc-js-sdk 1.1.15 → 1.1.16

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/src/xtkJob.js ADDED
@@ -0,0 +1,337 @@
1
+ /*
2
+ Copyright 2022 Adobe. All rights reserved.
3
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License. You may obtain a copy
5
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+ Unless required by applicable law or agreed to in writing, software distributed under
8
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
+ OF ANY KIND, either express or implied. See the License for the specific language
10
+ governing permissions and limitations under the License.
11
+ */
12
+ (function() {
13
+ "use strict";
14
+
15
+ const { CampaignException } = require("./campaign.js");
16
+ const { DomUtil } = require("./domUtil.js");
17
+ const { XtkCaster } = require("./xtkCaster.js");
18
+
19
+ /**
20
+ * @namespace Campaign
21
+ *
22
+ * @typedef {DOMElement} SoapMethodDefinition
23
+ * @memberof Campaign
24
+ */
25
+
26
+
27
+
28
+ /**
29
+ * The complete Triforce, or one or more components of the Triforce.
30
+ * @typedef {Object} XtkSoapCallSpec
31
+ * @property {string} method - the Soap method name (without any schema information)
32
+ * @property {string} xtkschema - the method schema id. It can be ommited if the object has a xtkschema property
33
+ * @property {any} object - the object ("this") to call the method with, possibly null for static methods. Should implement the xtk:job interface
34
+ * @property {Array} args - the list of arguments to the SOAP call
35
+ * @memberOf Campaign
36
+ */
37
+
38
+ /**
39
+ * @typedef {Object} XtkJobLog
40
+ * @property {number} id - the job log id, which can be used for subsequent calls to getStatus
41
+ * @property {number} iRc - the job return code (0 = ok)
42
+ * @property {Date} logDate - the timestamp of the log
43
+ * @property {number} logType - the level of the log message according
44
+ * @property {string} message - the log message
45
+ * @property {string} object - the log object
46
+ * @property {string} errorCode - the log error code if any
47
+ * @memberOf Campaign
48
+ */
49
+
50
+
51
+ /**
52
+ * @typedef {Object} XtkJobStatus
53
+ * @property {number} status - the job status code, as defined in the xtk:job:jobStatus enumeration
54
+ * @property {XtkJobLog[]} logs - the job log messages
55
+ * @property {{key: string, value: string}} properties - job properties
56
+ * @memberOf Campaign
57
+ */
58
+
59
+ /**********************************************************************************
60
+ *
61
+ * Job Interface
62
+ * Wraps the xtk:jobInterface interface into convenient JavaScript class
63
+ *
64
+ *********************************************************************************/
65
+ /**
66
+ * @private
67
+ * @class
68
+ * @constructor
69
+ * @memberof Campaign
70
+ */
71
+ class XtkJobInterface {
72
+
73
+ /**
74
+ * Create a job interface from a client and a SOAP call definition. This method is not meant to be called directly,
75
+ * use client.jobInterface instead
76
+ * @param {Campaign.Client} client the Client object to call Campaign API
77
+ * @param {Campaign.XtkSoapCallSpec} soapCallSpec the definition of the SOAP call
78
+ */
79
+ constructor(client, soapCallSpec) {
80
+ this._client = client;
81
+ this._soapCall = soapCallSpec;
82
+ this._maxLogCount = 100; // default fetch size
83
+ this._reset();
84
+ }
85
+
86
+ // Reset state before executing or submitting a job
87
+ _reset() {
88
+ this.jobId = undefined;
89
+ this.status = undefined;
90
+ this.result = undefined;
91
+ this.lastLogId = 0;
92
+ this.iRc = 0;
93
+ this.lastErrorCode = undefined;
94
+ this.firstErrorCode = undefined;
95
+ }
96
+
97
+ /**
98
+ * Execute job synchronously (xtk:jobInterface#Execute). Expects the job to have been built with an object implementing the xtk:job interface,
99
+ * for instance a delivery, and with the method to call (for instance "Prepare")
100
+ * Static methods are not supported
101
+ * @returns {string} a job id
102
+ */
103
+ async execute() {
104
+ this._reset();
105
+ const methodName = this._soapCall.method;
106
+ const entitySchemaId = this._soapCall.xtkschema ? this._soapCall.xtkschema : (this._soapCall.object ? this._soapCall.object.xtkschema : undefined);
107
+ if (!entitySchemaId)
108
+ throw CampaignException.SOAP_UNKNOWN_METHOD(entitySchemaId, methodName, `No schema was provided in soap call or object`);
109
+ const callContext = {
110
+ client: this._client,
111
+ object: this._soapCall.object,
112
+ schemaId: 'xtk:jobInterface',
113
+ entitySchemaId: entitySchemaId
114
+ };
115
+ var jobId = await callContext.client._callMethod("Execute", callContext, [ methodName ]);
116
+ this.jobId = jobId;
117
+ return jobId;
118
+ }
119
+
120
+ /**
121
+ * Execute job asynchronously (xtk:jobInterface#Execute). Expects the job to have been built with an object implementing the xtk:job interface,
122
+ * for instance a delivery, and with the method to call (for instance "Prepare")
123
+ * Static methods are not supported
124
+ * @returns {string} a job id
125
+ */
126
+ async submit() {
127
+ this._reset();
128
+ const methodName = this._soapCall.method;
129
+ const entitySchemaId = this._soapCall.xtkschema ? this._soapCall.xtkschema : (this._soapCall.object ? this._soapCall.object.xtkschema : undefined);
130
+ if (!entitySchemaId)
131
+ throw CampaignException.SOAP_UNKNOWN_METHOD(entitySchemaId, methodName, `No schema was provided in soap call or object`);
132
+ const callContext = {
133
+ client: this._client,
134
+ object: this._soapCall.object,
135
+ schemaId: 'xtk:jobInterface',
136
+ entitySchemaId: entitySchemaId
137
+ };
138
+ var jobId = await callContext.client._callMethod("Submit", callContext, [ this._soapCall.method ]);
139
+ this.jobId = jobId;
140
+ return jobId;
141
+ }
142
+
143
+ /**
144
+ * Execute a SOAP call asynchronously (xtk:jobInterface#Execute). Expects the job to have been built with an object implementing the xtk:job interface,
145
+ * for instance a delivery, and with the method to call (for instance "Prepare"). Can optionally pass parameters to the job.
146
+ * Static methods are not supported
147
+ * @returns {string} a job id
148
+ */
149
+ async submitSoapCall() {
150
+ this._reset();
151
+ const entitySchemaId = this._soapCall.xtkschema ? this._soapCall.xtkschema : (this._soapCall.object ? this._soapCall.object.xtkschema : undefined);
152
+ const callContext = {
153
+ client: this._client,
154
+ object: this._soapCall.object,
155
+ schemaId: 'xtk:jobInterface',
156
+ entitySchemaId: entitySchemaId,
157
+ };
158
+
159
+ const methodName = this._soapCall.method;
160
+ var schema = await this._client.getSchema(entitySchemaId, "xml", true);
161
+ if (!schema)
162
+ throw CampaignException.SOAP_UNKNOWN_METHOD(entitySchemaId, methodName, `Schema '${entitySchemaId}' not found`);
163
+ var method = this._client._methodCache.get(entitySchemaId, methodName);
164
+ if (!method)
165
+ throw CampaignException.SOAP_UNKNOWN_METHOD(entitySchemaId, methodName, `Method '${methodName}' of schema '${entitySchemaId}' not found`);
166
+ // SubmitSoapCall does not support
167
+ const isStatic = DomUtil.getAttributeAsBoolean(method, "static");
168
+ if (isStatic)
169
+ throw CampaignException.SOAP_UNKNOWN_METHOD(entitySchemaId, methodName, `Method '${methodName}' of schema '${entitySchemaId}' is static`);
170
+
171
+
172
+ var jobId = await callContext.client._callMethod("SubmitSoapCall", callContext, [ {
173
+ name: this._soapCall.method,
174
+ service: this._soapCall.xtkschema,
175
+ param: [
176
+ { name:"this", type:"DOMDocument", value: this._soapCall.object },
177
+ { name:"bStart", type:"boolean", value:"false" },
178
+ ]
179
+ } ]);
180
+ this.jobId = jobId;
181
+ return jobId;
182
+ }
183
+
184
+ /**
185
+ * Poll the status of a job previously submitted with Execute, Submit, or SubmitSoapCall. The status is made of 3 objects: the status code,
186
+ * logs, and job properties. Job Properties are arbitrary key value pairs set by the job, but also contains progress information.
187
+ * This call will fetch the most recent status and logs and aggregate it with previously fetched statuses
188
+ * @param {number|undefined} lastLogId the log id fetch logs from. If unspecified, this function will return the next batch of logs. If set to 0, will return logs from the beginning
189
+ * @param {number|undefined} maxLogCount the max number of logs to fetch. Defaults to 100
190
+ * @returns {Campaign.XtkJobStatus} an object containing the job status, all logs fetched so for, and job properties
191
+ */
192
+ async getStatus(lastLogId, maxLogCount) {
193
+ if (lastLogId === undefined) lastLogId = this.lastLogId;
194
+ if (maxLogCount === null || maxLogCount === undefined) maxLogCount = this._maxLogCount;
195
+ var status = await this._client.NLWS.xtkJob.getStatus(this.jobId, lastLogId, maxLogCount);
196
+ if (this._client._representation === "xml") {
197
+ status[1] = this._client._toRepresentation(status[1], "SimpleJson");
198
+ status[2] = this._client._toRepresentation(status[2], "SimpleJson");
199
+ }
200
+ status = this._makeJobStatus(status);
201
+ this._updateStatus(status);
202
+ return status;
203
+ }
204
+
205
+ // Aggregate new status with previously fetched status
206
+ _updateStatus(status) {
207
+ for (var i=0; i<status.logs.length; i++) {
208
+ if (status.logs[i].id > this.lastLogId)
209
+ this.lastLogId = status.logs[i].id;
210
+ }
211
+ if (this.status === undefined) {
212
+ this.status = status;
213
+ }
214
+ else {
215
+ const oldLogs = this.status.logs;
216
+ this.status = status;
217
+ this.status.logs = oldLogs.concat(this.status.logs);
218
+ }
219
+ }
220
+
221
+ /**
222
+ * Returns current progress of the job as a percentage (value between 0 and 1). This requires getStatus to have been called before
223
+ * @returns {number} the current job progress as a percentage value
224
+ */
225
+ getProgress() {
226
+ if (!this.status || !this.status.properties || !this.status.properties.progress) return 0;
227
+ if (!this.status.properties.progress.max) return 0;
228
+ return this.status.properties.progress.current / this.status.properties.progress.max;
229
+ }
230
+
231
+ /**
232
+ * Get the result of a job, i.e. the value returned by the underlying SOAP call if it had been called directlty.
233
+ * Assumes that the job is successful. If not, this call will throw an exception
234
+ * @returns {*} the job result
235
+ */
236
+ async getResult() {
237
+ var result = await this._client.NLWS.xtkJob.getResult(this.jobId);
238
+ result = this._makeJobResult(result);
239
+ this.result = result;
240
+ return result;
241
+ }
242
+
243
+ // Convert the job result into a typed object
244
+ _makeJobResult(rawResult) {
245
+ return rawResult;
246
+ }
247
+
248
+ // Convert job logs into a type object
249
+ _makeLogs(rawLogs) {
250
+ const logs = [];
251
+ rawLogs = rawLogs || {};
252
+ rawLogs = XtkCaster.asArray(rawLogs.log);
253
+ for (var i=0; i<rawLogs.length; i++) {
254
+ const rawLog = rawLogs[i];
255
+ var message = XtkCaster.asString(rawLog.message);
256
+ const match = message.match(/(\w{3}-\d{6})(.*)/);
257
+ var errorCode = undefined;
258
+ if (match && match.length >= 2) {
259
+ errorCode = match[1];
260
+ message = match[2] || "";
261
+ message = message.trim();
262
+ }
263
+ rawLog.id = XtkCaster.asLong(rawLog.id);
264
+ rawLog.iRc = XtkCaster.asLong(rawLog.iRc);
265
+ rawLog.logDate = XtkCaster.asDatetime(rawLog.logDate);
266
+ rawLog.logType = XtkCaster.asLong(rawLog.logType);
267
+ rawLog.message = message;
268
+ rawLog.object = XtkCaster.asString(rawLog.object);
269
+ rawLog.errorCode = errorCode;
270
+ logs.push(rawLog);
271
+
272
+ if (errorCode)
273
+ this.lastErrorCode = errorCode;
274
+ if (errorCode && !this.firstErrorCode)
275
+ this.firstErrorCode = errorCode;
276
+ if (rawLog.iRc != 0)
277
+ this.iRc = rawLog.iRc;
278
+ }
279
+ return logs;
280
+ }
281
+
282
+ // Convert job properties into a typed object
283
+ _makeProperties(rawProperties) {
284
+ rawProperties = rawProperties || {};
285
+ rawProperties.warning = XtkCaster.asBoolean(rawProperties.warning);
286
+ if (!rawProperties.progress) rawProperties.progress = {};
287
+ rawProperties.progress.current = XtkCaster.asLong(rawProperties.progress.current);
288
+ rawProperties.progress.max = XtkCaster.asLong(rawProperties.progress.max);
289
+ return rawProperties;
290
+ }
291
+
292
+ // Parse the result of GetStatus API. The result is an array of 3 object. The first is the status code,
293
+ // followed by the the logs, and finally the properties
294
+ _makeJobStatus(rawStatus) {
295
+ if (!rawStatus) rawStatus = [];
296
+ return {
297
+ status: XtkCaster.asLong(rawStatus[0]),
298
+ logs: this._makeLogs(rawStatus[1]),
299
+ properties: this._makeProperties(rawStatus[2])
300
+ };
301
+ }
302
+
303
+ /**
304
+ * Cancel a preciously submitted job
305
+ */
306
+ async cancel() {
307
+ await this._client.NLWS.xtkJob.cancel(this.jobId);
308
+ }
309
+
310
+ /**
311
+ * Pause a preciously submitted job
312
+ */
313
+ async pause() {
314
+ await this._client.NLWS.xtkJob.pause(this.jobId);
315
+ }
316
+
317
+ /**
318
+ * Waits until a job is actually cancelled
319
+ * @param {number} timeoutSeconds in seconds
320
+ */
321
+ async waitJobCancelled(timeoutSeconds) {
322
+ await this._client.NLWS.xtkJob.waitJobCancelled(this.jobId, timeoutSeconds);
323
+ }
324
+
325
+ /**
326
+ * Queries if warnings or errors have been generated for this job
327
+ * @return {boolean} Returns 'true' if there has been at least one warning or error message
328
+ */
329
+ async hasWarning() {
330
+ return XtkCaster.asBoolean(await this._client.NLWS.xtkJob.hasWarning(this.jobId));
331
+ }
332
+ }
333
+
334
+ // Public exports
335
+ exports.XtkJobInterface = XtkJobInterface;
336
+
337
+ })();
package/test/mock.js CHANGED
@@ -285,7 +285,114 @@ const GET_XTK_SESSION_SCHEMA_RESPONSE = Promise.resolve(`<?xml version='1.0'?>
285
285
  </pdomDoc>
286
286
  </GetEntityIfMoreRecentResponse>
287
287
  </SOAP-ENV:Body>
288
- </SOAP-ENV:Envelope>`)
288
+ </SOAP-ENV:Envelope>`);
289
+
290
+ const GET_XTK_JOB_SCHEMA_RESPONSE = Promise.resolve(`<?xml version='1.0'?>
291
+ <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:wpp:default' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
292
+ <SOAP-ENV:Body>
293
+ <GetEntityIfMoreRecentResponse xmlns='urn:wpp:default' SOAP-ENV:encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
294
+ <pdomDoc xsi:type='ns:Element' SOAP-ENV:encodingStyle='http://xml.apache.org/xml-soap/literalxml'>
295
+ <schema implements="xtk:jobInterface" name="job" namespace="xtk" xtkschema="xtk:schema">
296
+ <interface async="true" label="Job interface" name="jobInterface">
297
+ <method const="true" name="Execute">
298
+ <parameters>
299
+ <param inout="in" name="methodName" type="string"/>
300
+ <param inout="out" name="id" type="string"/>
301
+ </parameters>
302
+ </method>
303
+ <method const="true" name="Submit">
304
+ <parameters>
305
+ <param inout="in" name="methodName" type="string"/>
306
+ <param inout="out" name="id" type="string"/>
307
+ </parameters>
308
+ </method>
309
+ <method const="true" name="SubmitSoapCall">
310
+ <parameters>
311
+ <param inout="in" name="soapCall" type="DOMElement"/>
312
+ <param inout="out" name="id" type="string"/>
313
+ </parameters>
314
+ </method>
315
+ <method name="SubmitFromModel" static="true">
316
+ <parameters>
317
+ <param inout="in" name="schema" type="string"/>
318
+ <param inout="in" name="where" type="string"/>
319
+ <param inout="in" name="methodName" type="string"/>
320
+ <param inout="in" name="diff" type="DOMElement"/>
321
+ <param inout="in" name="async" type="boolean"/>
322
+ <param inout="out" name="jobId" type="long"/>
323
+ </parameters>
324
+ </method>
325
+ <method name="Cancel" static="true">
326
+ <parameters>
327
+ <param inout="in" name="id" type="string"/>
328
+ </parameters>
329
+ </method>
330
+ <method name="WaitJobCancelled" static="true">
331
+ <parameters>
332
+ <param inout="in" name="id" type="string"/>
333
+ <param desc="Maximum wait (in seconds)" inout="in" name="timeout" type="long"/>
334
+ </parameters>
335
+ </method>
336
+ <method name="Pause" static="true">
337
+ <parameters>
338
+ <param inout="in" name="id" type="string"/>
339
+ </parameters>
340
+ </method>
341
+ <method name="CheckIfJobInProcess" static="true">
342
+ <parameters>
343
+ <param inout="in" name="pid" type="long"/>
344
+ <param name="hostName" type="string"/>
345
+ <param inout="out" name="result" type="boolean"/>
346
+ </parameters>
347
+ </method>
348
+ <method name="GetJobsInProcess" static="true">
349
+ <parameters>
350
+ <param desc="Returned document" inout="out" name="jobInfo" type="DOMDocument"/>
351
+ </parameters>
352
+ </method>
353
+ <method name="GetStatus" static="true">
354
+ <parameters>
355
+ <param inout="in" name="id" type="string"/>
356
+ <param inout="in" name="lastLogId" type="long"/>
357
+ <param inout="in" name="maxLogCount" type="long"/>
358
+ <param enum="xtk:jobLog:logType" inout="out" name="status" type="short"/>
359
+ <param inout="out" name="returnLogs" type="DOMElement"/>
360
+ <param inout="out" name="properties" type="DOMElement"/>
361
+ </parameters>
362
+ </method>
363
+ <method name="GetResult" static="true">
364
+ <parameters>
365
+ <param inout="in" name="id" type="string"/>
366
+ <param inout="out" name="response" type="string"/>
367
+ </parameters>
368
+ </method>
369
+ <method name="HasWarning" static="true">
370
+ <parameters>
371
+ <param inout="in" name="id" type="string"/>
372
+ <param inout="out" name="hasWarning" type="boolean"/>
373
+ </parameters>
374
+ </method>
375
+ <method name="FilesExist" static="true">
376
+ <parameters>
377
+ <param inout="in" name="files" type="DOMDocument"/>
378
+ <param inout="out" name="exist" type="DOMDocument"/>
379
+ </parameters>
380
+ </method>
381
+ <method name="GetServerDiskSpace" static="true">
382
+ <parameters>
383
+ <param inout="out" name="serverDiskSpace" type="int64"/>
384
+ </parameters>
385
+ </method>
386
+ </interface>
387
+
388
+ <element autopk="true" name="job">
389
+ <attribute name="id" sqlname="iJobId" type="long"/>
390
+ </element>
391
+ </schema>
392
+ </pdomDoc>
393
+ </GetEntityIfMoreRecentResponse>
394
+ </SOAP-ENV:Body>
395
+ </SOAP-ENV:Envelope>`);
289
396
 
290
397
  const GET_DATABASEID_RESPONSE = Promise.resolve(`<?xml version='1.0'?>
291
398
  <SOAP-ENV:Envelope xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:ns='urn:xtk:session' xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
@@ -873,6 +980,7 @@ exports.Mock = {
873
980
  LOGON_RESPONSE_NO_SECURITYTOKEN: LOGON_RESPONSE_NO_SECURITYTOKEN,
874
981
  LOGOFF_RESPONSE: LOGOFF_RESPONSE,
875
982
  GET_XTK_SESSION_SCHEMA_RESPONSE: GET_XTK_SESSION_SCHEMA_RESPONSE,
983
+ GET_XTK_JOB_SCHEMA_RESPONSE: GET_XTK_JOB_SCHEMA_RESPONSE,
876
984
  GET_DATABASEID_RESPONSE: GET_DATABASEID_RESPONSE,
877
985
  GET_OPTION_NOTFOUND_RESPONSE: GET_OPTION_NOTFOUND_RESPONSE,
878
986
  GET_OPTION_MISSING_DATA_RESPONSE: GET_OPTION_MISSING_DATA_RESPONSE,
package/test/util.test.js CHANGED
@@ -37,6 +37,15 @@ describe('Util', function() {
37
37
  expect(Util.isArray([ 1 ])).toBe(true);
38
38
  });
39
39
 
40
+ describe("util.schemaIdFromNamespace", () => {
41
+ it("Should should extract schema id for simple namespaces", () => {
42
+ expect(Util.schemaIdFromNamespace("")).toBe("");
43
+ expect(Util.schemaIdFromNamespace("nmsRecipient")).toBe("nms:recipient");
44
+ expect(Util.schemaIdFromNamespace("000Recipient")).toBe("000:recipient");
45
+ expect(Util.schemaIdFromNamespace("Recipient")).toBe(":recipient");
46
+ });
47
+ });
48
+
40
49
  describe("Util.trim", () => {
41
50
  it("Should remove trailing spaces", () => {
42
51
  expect(Util.trim("Hello \n \r \t ")).toBe("Hello");