uapi-json 1.17.5 → 1.18.0

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/README.md CHANGED
@@ -89,6 +89,24 @@ It also has several useful helpers to handle errors.
89
89
 
90
90
  `logFunction` - set custom logging function that should match next shape `(...args) => {}`. Will receive all requests and responses from uapi/terminal.
91
91
 
92
+ `httpsAgent` - set custom HTTPS agent for all requests created by the service. If the agent has `options.timeout`, that value is used as the request timeout.
93
+
94
+ ```javascript
95
+ const https = require('https');
96
+
97
+ const TerminalService = uAPI.createTerminalService({
98
+ auth,
99
+ options: {
100
+ httpsAgent: new https.Agent({
101
+ keepAlive: true,
102
+ maxSockets: 1,
103
+ maxFreeSockets: 1,
104
+ timeout: 90000,
105
+ }),
106
+ },
107
+ });
108
+ ```
109
+
92
110
  ### Auth object
93
111
  <a name="auth"></a>
94
112
 
package/package.json CHANGED
@@ -1,8 +1,11 @@
1
1
  {
2
2
  "name": "uapi-json",
3
- "version": "1.17.5",
3
+ "version": "1.18.0",
4
4
  "description": "Travelport Universal API",
5
5
  "main": "src/",
6
+ "engines": {
7
+ "node": ">=20"
8
+ },
6
9
  "files": [
7
10
  "src/",
8
11
  "README.md",
@@ -27,37 +30,37 @@
27
30
  "node",
28
31
  "travelport"
29
32
  ],
30
- "author": "Mark Orel <mail.ormark@gmail.com>",
31
33
  "contributors": [
32
- "Dmitry Chertousov <d.chertousov@gmail.com>",
33
34
  "Artem Pylypchuk <articicejuice@gmail.com>",
34
- "Yevhenii Huselietov <d46k16@gmail.com>",
35
+ "Dmytro Chertousov <d.chertousov@gmail.com>",
36
+ "Mark Orel <mail.ormark@gmail.com>",
35
37
  "Mark Omarov <dev.mark.omarov@gmail.com>",
36
- "Oleksii Duvanov <colden.aid@gmail.com>"
38
+ "Oleksii Duvanov <colden.aid@gmail.com>",
39
+ "Yevhenii Huselietov <d46k16@gmail.com>"
37
40
  ],
38
41
  "license": "MIT",
39
42
  "dependencies": {
40
- "axios": "^1.9.0",
43
+ "axios": "~1.15.0",
41
44
  "galileo-screen": "1.0.5",
42
- "handlebars": "^4.7.8",
43
- "handlebars-helper-equal": "^1.0.0",
44
- "joi": "^17.13.3",
45
- "moment": "^2.30.1",
46
- "node-errors-helpers": "^1.0.0",
47
- "pretty-data": "^0.40.0",
48
- "promise-retry": "^2.0.1",
49
- "xml2js": "^0.6.2"
45
+ "handlebars": "~4.7.9",
46
+ "handlebars-helper-equal": "~1.0.0",
47
+ "joi": "~18.1.2",
48
+ "moment": "~2.30.1",
49
+ "node-errors-helpers": "~1.0.0",
50
+ "pretty-data": "~0.40.0",
51
+ "promise-retry": "~2.0.1",
52
+ "xml2js": "~0.6.2"
50
53
  },
51
54
  "devDependencies": {
52
55
  "chai": "^4.5.0",
53
56
  "eslint": "^8.39.0",
54
57
  "eslint-config-airbnb-base": "^15.0.0",
55
- "eslint-plugin-import": "^2.29.0",
56
- "mocha": "^11.5.0",
58
+ "eslint-plugin-import": "^2.32.0",
59
+ "mocha": "^11.7.5",
57
60
  "nyc": "^17.1.0",
58
- "proxyquire": "^2.1.3",
59
- "readline2": "^1.0.1",
60
- "sinon": "^20.0.0",
61
+ "proxyquire": "~2.1.3",
62
+ "readline2": "~1.0.1",
63
+ "sinon": "^21.0.0",
61
64
  "sinon-chai": "^3.7.0"
62
65
  }
63
66
  }
@@ -36,8 +36,9 @@ function mergeLeaf(item) {
36
36
  return { ...item, ...leaf };
37
37
  }
38
38
 
39
- function Parser(root, uapiVersion, env, debug, config, provider) {
39
+ function Parser(root, uapiVersion, env, debug, config, provider, log) {
40
40
  this.debug = debug;
41
+ this.log = log || console.info;
41
42
  if (!config) {
42
43
  this.config = defaultConfig(uapiVersion);
43
44
  } else {
@@ -212,7 +213,7 @@ Parser.prototype.parse = function (xml) {
212
213
 
213
214
  const end = new Date() - start;
214
215
  if (this.debug > 1) {
215
- console.info('uAPI_Parse execution time: %dms', end);
216
+ this.log('uAPI_Parse execution time: %dms', end);
216
217
  }
217
218
 
218
219
  return data[self.rootObject];
@@ -1,5 +1,6 @@
1
1
  const handlebars = require('handlebars');
2
2
  const axios = require('axios');
3
+ const https = require('https');
3
4
  const { pd } = require('pretty-data');
4
5
  const {
5
6
  RequestValidationError,
@@ -13,6 +14,14 @@ const configInit = require('../config');
13
14
 
14
15
  handlebars.registerHelper('equal', require('handlebars-helper-equal'));
15
16
 
17
+ const REQUEST_AGENT_OPTIONS = {
18
+ keepAlive: true,
19
+ keepAliveMsecs: 5000,
20
+ maxSockets: 20,
21
+ maxFreeSockets: 20,
22
+ };
23
+ const httpsAgent = new https.Agent(REQUEST_AGENT_OPTIONS);
24
+
16
25
  /**
17
26
  * basic function for requests/responses
18
27
  * @param {string} service service url for current response (gateway)
@@ -43,6 +52,15 @@ module.exports = function uapiRequest(
43
52
 
44
53
  const config = configInit(auth.region);
45
54
  const log = options.logFunction || console.log;
55
+ const customHttpsAgent = options.httpsAgent;
56
+ const requestHttpsAgent = customHttpsAgent || httpsAgent;
57
+ const requestTimeout = (
58
+ customHttpsAgent
59
+ && customHttpsAgent.options
60
+ && typeof customHttpsAgent.options.timeout === 'number'
61
+ )
62
+ ? customHttpsAgent.options.timeout
63
+ : config.timeout || 5000;
46
64
 
47
65
  // Performing checks
48
66
  if (!service || service.length <= 0) {
@@ -64,7 +82,7 @@ module.exports = function uapiRequest(
64
82
  }
65
83
 
66
84
  // create a v52 uAPI parser with default params and request data in env
67
- const uParser = new Parser(rootObject, 'v52_0', params, debugMode, null, auth.provider);
85
+ const uParser = new Parser(rootObject, 'v52_0', params, debugMode, null, auth.provider, log);
68
86
 
69
87
  const validateInput = () => (
70
88
  Promise.resolve(params)
@@ -85,7 +103,8 @@ module.exports = function uapiRequest(
85
103
  const response = await axios.request({
86
104
  url: service,
87
105
  method: 'POST',
88
- timeout: config.timeout || 5000,
106
+ timeout: requestTimeout,
107
+ httpsAgent: requestHttpsAgent,
89
108
  auth: {
90
109
  username: auth.username,
91
110
  password: auth.password,
@@ -156,7 +175,6 @@ module.exports = function uapiRequest(
156
175
  };
157
176
 
158
177
  const validateSOAP = function (parsedXML) {
159
- console.log(parsedXML);
160
178
  if (parsedXML['SOAP:Fault']) {
161
179
  if (debugMode > 2) {
162
180
  log('Parsed error response', pd.json(parsedXML));
@@ -169,7 +187,8 @@ module.exports = function uapiRequest(
169
187
  params,
170
188
  debugMode,
171
189
  errParserConfig,
172
- auth.provider
190
+ auth.provider,
191
+ log
173
192
  );
174
193
  const errData = errParser.mergeLeafRecursive(parsedXML['SOAP:Fault'][0]); // parse error data
175
194
  return errorHandler.call(errParser, errData);
@@ -197,7 +197,7 @@ function formatPassengerCategories(pricingInfo) {
197
197
 
198
198
  [code] = list;
199
199
  if (!list[0] || list.length !== 1) { // TODO throw error
200
- console.log('Warning: different categories '
200
+ console.warn('Warning: different categories '
201
201
  + list.join() + ' in single fare calculation ' + key + ' in fare ' + key);
202
202
  }
203
203
  passengerCounts[code] = count;
@@ -218,7 +218,7 @@ function airPrice(obj) {
218
218
 
219
219
  let pricingSolution = 0;
220
220
  if (priceKeys.length > 1) {
221
- console.log('More than one solution found in booking. Resolving the cheapest one.');
221
+ console.warn('More than one solution found in booking. Resolving the cheapest one.');
222
222
  const solutions = priceKeys.map((key) => pricingSolutions[key]);
223
223
 
224
224
  [pricingSolution] = solutions.sort(
@@ -347,7 +347,7 @@ function airPriceRspPricingSolutionXML(obj) {
347
347
  let pricingSolution = 0;
348
348
  if (pricingSolutions.length > 1) {
349
349
  // TODO: Check result for multiple passenger type results.
350
- console.log('More than one solution found in booking. Resolving the cheapest one.');
350
+ console.warn('More than one solution found in booking. Resolving the cheapest one.');
351
351
  [pricingSolution] = pricingSolutions.sort(
352
352
  (a, b) => parseFloat(a.$.TotalPrice.slice(3)) - parseFloat(b.$.TotalPrice.slice(3))
353
353
  );
@@ -207,6 +207,8 @@ module.exports = function (settings) {
207
207
 
208
208
  // Get terminal ID
209
209
  const getTerminalId = (sessionToken) => getHashSubstr(sessionToken);
210
+ const isClosed = () => state.terminalState === TERMINAL_STATE_CLOSED;
211
+ const isInitialized = () => state.terminalState !== TERMINAL_STATE_NONE;
210
212
 
211
213
  const terminal = {
212
214
  getToken: async () => {
@@ -251,6 +253,20 @@ module.exports = function (settings) {
251
253
  throw err;
252
254
  }
253
255
  },
256
+ isClosed,
257
+ isInitialized,
258
+ closeSessionSafe: async () => {
259
+ if (isClosed()) {
260
+ console.warn('UAPI-JSON WARNING: Terminal session is already closed');
261
+ return;
262
+ }
263
+ if (!isInitialized()) {
264
+ console.warn('UAPI-JSON WARNING: Terminal session is not initialized');
265
+ return;
266
+ }
267
+
268
+ await terminal.closeSession().catch(console.error);
269
+ },
254
270
  closeSession: () => getSessionToken()
255
271
  .then(
256
272
  (sessionToken) => service.closeSession({
@@ -50,6 +50,7 @@ Object.assign(TerminalRuntimeError, createErrorsList({
50
50
  InvalidAccount: ['Invalid account', errorCodes.Validation],
51
51
  TerminalUnexpectedError: ['Unexpected error message is returned by Travelport system. Please check PNR and try again later.', errorCodes.Validation],
52
52
  TerminalUnexpectedFinancialError: ['Unexpected error message is returned by Travelport system. Please check PNR and new Fare calculation. If the problem persists, contact your local helpdesk.', errorCodes.Validation],
53
+ InvalidResponseFromHCA: 'Invalid response from HCA',
53
54
  }, TerminalRuntimeError));
54
55
 
55
56
  module.exports = {
@@ -24,12 +24,12 @@ function errorHandler(rsp) {
24
24
  screen: faultString,
25
25
  pcc: utils.getErrorPcc(rsp.faultstring),
26
26
  });
27
+ case '2614':
28
+ throw new TerminalRuntimeError.InvalidResponseFromHCA({ screen: faultString });
27
29
  case '6207': // Error retrieving AccessProfile Unable to retrieve enough Dynamic GTIDs for this transaction
28
30
  case '6119': // Host system error
29
31
  case '14058': // Could not locate Session Token Information Session May Have Timed Out
30
- throw new RequestRuntimeError.UAPIServiceError({
31
- screen: faultString,
32
- });
32
+ throw new RequestRuntimeError.UAPIServiceError({ screen: faultString });
33
33
  default:
34
34
  throw new RequestRuntimeError.UnhandledError(null, new TerminalRuntimeError(rsp));
35
35
  }