Skip to content

Commit

Permalink
Merge pull request #64 from Travelport-Ukraine/master
Browse files Browse the repository at this point in the history
Merged Milestone v0.5.0
  • Loading branch information
dchertousov authored Oct 31, 2016
2 parents 5303dad + d12214c commit 735e280
Show file tree
Hide file tree
Showing 23 changed files with 405 additions and 78 deletions.
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const uAPI = rqeuire('uapi-json');
const AirService = uAPI.createAirService(settings);
const HotelService = uAPI.createHotelService(settings);
const UtilsService = uAPI.createUtilsService(settings);
const TerminalService = uAPI.createTerminalService(settings);
```

It also exports a set of error classes that help to check errors against them
Expand Down Expand Up @@ -62,17 +63,20 @@ It also has several useful helpers to handle errors.
<a name="settings"></a>

## uAPI
* .**createAirService**(settings) ⇒ [`AirService`](docs/Air.md)
* .**createHotelService**(settings) ⇒ [`HotelService`](docs/Hotels.md)
* .**createUtilsService**(settings) ⇒ [`UtilsService`](docs/Utils.md)
* `.createAirService(settings)`[`AirService`](docs/Air.md)
* `.createHotelService(settings)`[`HotelService`](docs/Hotels.md)
* `.createUtilsService(settings)`[`UtilsService`](docs/Utils.md)
* `.createTerminalService(settings)`[`TerminalService`](docs/Terminal.md)

### Settings object

| Param | Type | Default | Description |
| --- | --- | --- | --- |
| auth | `Object <username, password, targetBranch>` | - | See `auth` description [below](#auth). |
| debug | `Number` | 0 | Can be 0, 1, or 2. |
| production | `Boolean` | true | Production variable is connected with production and pre-production environment. Can be true for production and false for pre-production. For more information read docs. . |
| debug | `Number` | `0` | Can be `0`, `1`, or `2`. |
| production | `Boolean` | `true` | Production variable is connected with production and pre-production environment. Can be true for production and false for pre-production. For more information read docs. |
| emulatePcc | `String` | - | Optional. Used for `TerminalService` only. See [`TerminalService`](docs/Terminal.md) |
| timeout | `Number` | - | Optional. Used for `TerminalService` only. See [`TerminalService`](docs/Terminal.md) |

### Auth object
<a name="auth"></a>
Expand All @@ -90,7 +94,7 @@ See the following services pages to take a detailed view
* [`AirService`](docs/Air.md)
* [`HotelService`](docs/Hotels.md)
* [`UtilsService`](docs/Utils.md)

* [`TerminalService`](docs/Terminal.md)


# Contributing
Expand Down
31 changes: 31 additions & 0 deletions docs/Terminal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Terminal :computer:

Terminal service provides an interface to run terminal commands
for terminal-enabled uAPI credentials.

You can use Terminal service to run commands on behalf of your own PCC
or to use `emulatePcc` option to run commands on behalf of other PC using your own Service bureau.

## API

**TerminalService**
* [`.executeCommand()`](#execute_command)`Promise`
* [`.closeSession()`](#close_session)`Promise`

## Methods
### .executeCommand(command)
<a name="execute_command"></a>
Executes a command in terminal and returns its terminal response

**Returns**: `Promise` that returns terminal command response in `String` format

| Param | Type | Description |
| --- | --- | --- |
| command | `String` | String representation of the command you want to execute |

### .closeSession()
<a name="close_session"></a>
When you have finished command execution it's necessary to close terminal connection
to free up space in the terminal pool. Takes no parameters

**Returns**: `Promise` which fullfills with true if terminal was succesfully closed
2 changes: 1 addition & 1 deletion docs/Utils.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Utils :hotel:
# Utils :cd:

Some powerfull utils that can help you build best products.

Expand Down
14 changes: 3 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "uapi-json",
"version": "0.4.4",
"version": "0.5.0",
"description": "Travelport Universal API",
"main": "build/",
"files": [
Expand Down Expand Up @@ -32,19 +32,16 @@
],
"license": "MIT",
"dependencies": {
"async": "^1.5.2",
"consolidate": "^0.14.1",
"galileo-screen": "^1.0.2",
"handlebars": "^4.0.5",
"lodash": "^3.10.1",
"moment": "^2.10.6",
"node-errors-helpers": "^0.1.2",
"object-assign": "^4.0.1",
"promise": "^7.0.3",
"request": "^2.60.0",
"xml2js": "^0.4.9"
},
"devDependencies": {
"argg": "",
"babel-cli": "^6.14.0",
"babel-plugin-add-module-exports": "^0.2.1",
"babel-preset-es2015-node4": "^2.1.0",
Expand All @@ -54,11 +51,6 @@
"eslint-plugin-jsx-a11y": "^2.2.3",
"eslint-plugin-react": "^6.4.1",
"istanbul": "^0.4.1",
"lolex": "",
"mocha": "^1.21.5",
"moment": "^2.10.6",
"object-assign": "^4.0.1",
"proxyquire": "^1.6.0",
"sinon": "^1.15.4"
"mocha": "^1.21.5"
}
}
36 changes: 19 additions & 17 deletions src/Request/uapi-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,25 @@ function mergeLeaf(item) {

function defaultConfig(ver) {
// do not collapse arrays with single objects or objects with single keys if they have this name
const noCollapseList = ['air:BookingInfo', 'air:FareRule',
// there's one SSR per each airline (per each passenger), they are usually identical
'common_' + ver + ':SSR',
'air:AirReservation',
'air:PassengerType',
'air:TicketInfo',
'common_' + ver + ':ResponseMessage',
'air:BaggageAllowanceInfo',
'air:CarryOnAllowanceInfo',
'hotel:RateInfo',
'hotel:HotelSearchResult',
// 'hotel:Amenities',
'hotel:Amenity',
'hotel:HotelDetailItem',
'hotel:AggregatorHotelDetails',
'common_' + ver + ':MediaItem',
];
const noCollapseList = [
'air:BookingInfo',
'air:FareRule',
// there's one SSR per each airline (per each passenger), they are usually identical
'common_' + ver + ':SSR',
'air:AirReservation',
'air:PassengerType',
'air:TicketInfo',
'common_' + ver + ':ResponseMessage',
'air:BaggageAllowanceInfo',
'air:CarryOnAllowanceInfo',
'hotel:RateInfo',
'hotel:HotelSearchResult',
// 'hotel:Amenities',
'hotel:Amenity',
'hotel:HotelDetailItem',
'hotel:AggregatorHotelDetails',
'common_' + ver + ':MediaItem',
];

// Non-single field objects don't get collapsed
// from single item arrays into objects automatically, e.g.
Expand Down
16 changes: 7 additions & 9 deletions src/Request/uapi-request.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { handlebars as Mustache } from 'consolidate';
import _ from 'lodash';
import handlebars from 'handlebars';
import fs from 'fs';
import request from 'request';
import Promise from 'promise';
Expand Down Expand Up @@ -50,26 +49,23 @@ module.exports = function (service, auth, reqType, rootObject,
console.log('Input params ', params);
}

const validateInput = (resolve, reject) => {
if (_.isEmpty(params)) {
reject(new RequestValidationError.ParamsMissing());
return;
}
const validateInput = (resolve) => {
params = validateFunction(params);
resolve(reqType);
};

const prepareRequest = function (data) {
const prepareRequest = function (template) {
// adding target branch param from auth variable and render xml
params.TargetBranch = auth.targetBranch;
params.Username = auth.username;
params.pcc = auth.pcc;
const renderedObj = Mustache.render(data.toString(), params);
const renderedObj = template(params);
return renderedObj;
};

const sendRequest = function (xml) {
if (debugMode) {
console.log('Request URL: ', service);
console.log('Request XML: ', xml);
}
return new Promise((resolve, reject) => {
Expand Down Expand Up @@ -145,6 +141,8 @@ module.exports = function (service, auth, reqType, rootObject,

return new Promise(validateInput)
.then(readFile)
.then(buffer => buffer.toString())
.then(handlebars.compile)
.then(prepareRequest)
.then(sendRequest)
.then(parseResponse)
Expand Down
1 change: 1 addition & 0 deletions src/Services/Air/AirErrors.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ Object.assign(AirRuntimeError, createErrorsList({
TicketingFoidRequired: 'FOID required for the PC selected',
NoResultsFound: 'No results found',
NoValidFare: 'No valid fare for input criteria.',
TravelersListError: 'Not all BookingTravelers present in list or wrong lookup keys provided',
}, AirRuntimeError));
Object.assign(GdsRuntimeError, createErrorsList({
PlacingInQueueMessageMissing: 'Placing success message missing',
Expand Down
28 changes: 10 additions & 18 deletions src/Services/Air/AirParser.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import _ from 'lodash';
import async from 'async';
import xml2js from 'xml2js';
import moment from 'moment';
import utils from '../../utils';
Expand Down Expand Up @@ -124,24 +123,19 @@ const nullParsing = obj => obj;


function getPassengers(list, BookingTraveler) {
const passengers = [];

async.forEachOf(list, (key) => {
return list.reduce((passengers, key) => {
const traveler = BookingTraveler[key];

if (!traveler) {
throw new Error('Not all BookingTravelers present in list or wrong lookup keys provided');
throw new AirRuntimeError.TravelersListError();
}

const name = traveler['common_' + this.uapi_version + ':BookingTravelerName'];
const name = traveler[`common_${this.uapi_version}:BookingTravelerName`];

// SSR DOC parsing of passport data http://gitlab.travel-swift.com/galileo/galileocommand/blob/master/lib/command/booking.js#L84
// TODO safety checks
const firstTraveler = utils.firstInObj(traveler['common_' + this.uapi_version + ':SSR']);
let ssr = [];
if (firstTraveler) {
ssr = firstTraveler.FreeText.split('/');
}
// SSR DOC parsing of passport data http://gitlab.travel-swift.com/galileo/galileocommand/blob/master/lib/command/booking.js#L84
// TODO safety checks
const firstTraveler = utils.firstInObj(traveler[`common_${this.uapi_version}:SSR`]);
const ssr = firstTraveler ? firstTraveler.FreeText.split('/') : [];

// TODO try to parse Swift XI from common_v36_0:AccountingRemark first

Expand All @@ -156,11 +150,9 @@ function getPassengers(list, BookingTraveler) {
uapi_ref_key: key,
};


passengers.push(passenger); // TODO error handling
});

return passengers;
passengers.push(passenger);
return passengers;
}, []);
}

const extractFareRulesLong = (obj) => {
Expand Down
2 changes: 1 addition & 1 deletion src/Services/Air/AirService.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ module.exports = (settings) => {
passengers: options.passengers,
rule: options.rule,
ticketingPcc: auth.pcc.toUpperCase(),
ticketDate: moment().add(1, 'hours').format(),
ticketDate: moment().format(),
ActionStatusType: 'TAU',
}, data);
return AirService.createReservation(bookingParams).catch((err) => {
Expand Down
2 changes: 1 addition & 1 deletion src/Services/Air/templates/AIR_PRICE_REQ.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@
ProviderCode="1G"
Key="{{@index}}"
Group="0">
</air:AirSegment>
{{#if transfer}}
<air:Connection/>
{{/if}}
</air:AirSegment>
{{/segments}}
</air:AirItinerary>
{{#if business}}
Expand Down
2 changes: 1 addition & 1 deletion src/Services/Hotels/HotelsValidator.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const { HotelsValidationError } = errors;

function Validator(params) {
this.params = params;
this.reg = /^[0-9]{4}\-[0-9]{2}\-[0-9]{2}$/;
this.reg = /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/;
}

Validator.prototype.end = function () {
Expand Down
78 changes: 78 additions & 0 deletions src/Services/Terminal/Terminal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { lib as screenLib } from 'galileo-screen';
import {
TerminalRuntimeError,
} from './TerminalErrors';
import terminalService from './TerminalService';

const responseHasMoreData = response => (response.slice(-1).join('') === ')><');

module.exports = function (settings) {
const service = terminalService(settings);
const emulatePcc = settings.emulatePcc || false;
const timeout = settings.timeout || false;
const state = {
sessionToken: null,
};
const processResponse = (response, previousResponse = []) => {
const processedResponse = screenLib.mergeLastLinesAtIntersection(
previousResponse.slice(0, -1),
response
);
if (!responseHasMoreData(response)) {
return processedResponse.join('\n');
}
return service.executeCommand({
sessionToken: state.sessionToken,
command: 'MD',
}).then(
mdResponse => processResponse(mdResponse, processedResponse)
);
};
const getSessionToken = () => new Promise((resolve, reject) => {
// Return token if already obtained
if (state.sessionToken !== null) {
resolve(state.sessionToken);
return;
}
// Getting token
service.getSessionToken({
timeout,
}).then((sessionToken) => {
// Remember sesion token
Object.assign(state, {
sessionToken,
});
// Return if no emulation needed
if (!emulatePcc) {
resolve(sessionToken);
return;
}
// Emulate pcc
service.executeCommand({
sessionToken,
command: `SEM/${emulatePcc}/AG`,
}).then((response) => {
if (!response[0].match(/^PROCEED/)) {
reject(new TerminalRuntimeError.TerminalEmulationFailed(response));
return;
}
resolve(sessionToken);
});
}).catch(reject);
});
return {
executeCommand: command => getSessionToken().then(
sessionToken => service.executeCommand({
command,
sessionToken,
}).then(
response => processResponse(response)
)
),
closeSession: () => getSessionToken().then(
sessionToken => service.closeSession({
sessionToken,
})
),
};
};
Loading

0 comments on commit 735e280

Please sign in to comment.