Closed cbetta closed 6 years ago
Some notes:
Due to the limitations of the standard libraries in Node, 2 libraries were used as runtime dependencies:
bluebird
- Bluebird is a fully featured promise library with focus on innovative features and performance. This is used to support promises, await/async, and implementing this ourselves would have been not worth the effort. bluebird
has no further dependencies though, keeping the weight of this library to a limit.
qs
- A querystring parsing and stringifying library with some added security. Used to serialize an object into a query string. In most languages this would be in the standard library, but not in Node. `qs has no further dependencies though, keeping the weight of this library to a limit.
This library has backwards compatibility support for Node 4, but it is not automatically tested for Node 4 as the testing library used (Jest) does not support Node 4 fully. As the LTS for Node 4 ends this April I don't want to change the testing library just to support Node 4.
Not set up yet, as we need to make the repo public first
For now we have included the docs in the repo, so that we can host them temporarily using Github: https://workbetta.github.io/amadeus-node/
Amadeus SDK Specification Document
Table of Content | Templates
Overview
The goal of this document is to set a shared standard for implementation and development of all Amadeus SDKs. For the sake of this document, there is no differentiation between SDKs and API client SDKs.
This document is a work in progress, and should be changed and updated as changes are made to the APIs or developer needs are discovered.
Requirement Prioritization
The following document follows the MoSCoW method of prioritising rules. Please follow the following guidelines when evaluating rules.
MUST
- Rules labeled as must are requirements that should not be deviated from at any costSHOULD
- Rules labeled as should are requirements that could be deviated from if needed, though this will have to be documented and cleared with all stakeholders before it can be disregarded.COULD
- Rules labeled as could are requirements that are desirable but not necessary and therefore would be nice to have where time and resources permit.We do not use the fourth
won't
level in this specification.Limitations
Currently this specification is limited due to various reasons. This means that currently:
Table of Contents
Maintenance Requirements
1. Source Control
master
branchmaster
branch should be kept in a condition that allows for direct use through checkout2. Releases & Versioning
CHANGELOG
file must to be updated with theMajor
,Minor
andPatch
changesREADME
fileLICENSE
fileCHANGELOG
fileamadeus
,Amadeus
, oramadeus/amadeus
.amadeus-sdk
,AmadeusSDK
, oramadeusdev/amadeus
.amadeus-php
) or a reference to this being an SDK client library (e.g. notamadeus-sdk
) practices, and be one ofamadeus
,Amadeus
, oramadeus/amadeus
.1.0.0
3. CI Server
Additional Content Requirements
4. Documentation
README
fileREADME
file should include a version badgeREADME
file should include a test status badgeREADME
file must link to theLICENSE
fileREADME
file should be written in MarkdownREADME
file must have instructions on how to install the SDK using a package managerREADME
file could have instructions on how to install the SDK from version controlREADME
file must have instructions on how to initialise the SDK with the API credentialsamadeus
. For example,amadeus = new Amadeus::Client()
README
file should document all the different ways the SDK can be initializedREADME
file must include a basic sample on how to make a first API callREADME
file must link to the developer portalREADME
file should link to documentation on the developer portalREADME
file must document any installation requirements and prerequisitesREADME
file should to official support channelsREADME
file must document where a developer can find their API credentialsamadeus
,travel
,flights
,hotels
,sdk
,library
CHANGELOG
fileCODE_OF_CONDUCT
fileCONTRIBUTING
fileISSUE_TEMPLATE
filePULL_REQUEST_TEMPLATE
fileSUPPORT
file5. Testing
6. Linting
Dependencies & Infrastructure Requirements
7. Dependencies
8. HTTP Client
9. Logging
10. Reporting
library_name/library_version language_name/language_version
amadeus-ruby/1.0.0 ruby/2.4.2
library_name/library_version language_name/language_version app_name/app_version
amadeus-ruby/1.0.0 ruby/2.4.2 test_ios_app/1.0.0
Initialization & Interaction Requirements
11. Initialization
amadeus
,com.amadeus.developer
, orAmadeus
package nameAmadeus::Client
in Ruby, orAmadeus\Client
in PHPAMADEUS_CLIENT_ID
andAMADEUS_CLIENT_SECRET
AMADEUS_DEBUG
test
andproduction
)12. Namespacing
GET /v1/flights
:amadeus.flights.get
GET /v2/hotels/offers
:amadeus.hotels.offers.get
GET /v1/hotels/123
:amadeus.hotels(123)
GET /v1/hotels/123
:amadeus.hotels.get(123)
GET /v1/hotels/123
:amadeus.hotels.get(id: 123)
GET /v1/hotels/123/hotel-offers
:amadeus.hotels(123).offers
GET /v1/hotels/123/hotel-offers
:amadeus.hotels.get(123).offers
GET /v1/hotels/123/hotel-offers
:amadeus.hotels.get(id: 123).offers
GET /v1/flights/123/legs
:amadeus.flights(123).legs()
(should make 1 API call only)GET /v1/flights/123/legs/345
:amadeus.flights(123).legs(345)
(should make 1 API call only)reference-data
) to a more idiomatic format (e.g.reference_data
orReferenceData
)13. Method Syntax
amadeus.flights().get()
:GET /v1/flights
amadeus.flights().get({ foo: 123 }
:GET /v1/flights?foo=123
amadeus.flights(123).get()
:GET /v1/flights/123
amadeus.flights().post({ from: "LHR", to: "LAX" })
amadeus.flights().get(params, callback_function)
amadeus.flights().get(params).then(...).catch(...)
14. Error Handling
ResponseError
for any request that did not result a HTTP 200 or 201 response codeNetworkError
when a transport error occurs (e.g. if the API could not be reached, or unexpected data was returned from the API)AuthenticationError
when incorrect credentials were providedNotFoundError
when the API call returned a 404ClientError
when a generic client error occurs (e.g. incorrect data was sent to the API, basically any 4XXX error)ServerError
if the API returned a 5XX error]ParserError
if the response was JSON but could not be parsedcode
attribute containing the name of the error, e.g.NetworkError
.description
attribute containing the parsed JSON from the API, if the API errored and contained JSON.API Mapping Requirements
15. API Calls
reference-data
namespaceGET /v2/reference_data/urls/checkin-links
endpointamadeus.reference_data.urls.checkin_links.get({ airline: 'BA' })
GET /v2/reference_data/locations
endpointamadeus.reference_data.locations.get({ keyword: 'LON' })
GET /v2/reference_data/locations/airports
endpointamadeus.reference_data.locations.airports.get({ latitude: '0.0', longitude: '0.0' })
shopping
namespaceGET /v1/shopping/flight-destinations
endpointamadeus.shopping.flight_destinations.get({ origin: 'LAX' })
GET /v1/shopping/flight-offers
endpointamadeus.shopping.flight_offers.get({ origin: 'LAX', destination: 'LHR', departureDate: '2020-12-01' })
GET /v1/shopping/flight-dates
endpointamadeus.shopping.flight_dates.get({ origin: 'LAX', destination: 'LHR' })
travel/analytics
namespaceGET /v1/travel/analytics/fare-searches
endpointamadeus.travel.analytics.fare_searches.get({ origin: 'LAX', sourceCountry: 'US', period: 2015 })
GET /v1/travel/analytics/air-traffics
endpointamadeus.travel.analytics.air_traffics.get({ origin: 'LAX', period: '2015-07' })
shopping/hotels
namespaceGET /v1/shopping/hotel-offers
endpointamadeus.shopping.hotel_offers.get({ cityCode: 'LAX' }
GET /v1/shopping/hotels/:hotel_id/hotel-offers
endpointamadeus.shopping.hotels.get(123).hotel_offers.get({ checkInDate: '2018-12-01', checkOutDate: '2018-12-03' })
GET /v1/shopping/hotels/:hotel_id/offers/:offer_id
endpointamadeus.shopping.hotels.get(123).hotel_offers.get(345)
16. Responses
result
attribute with the parsed JSON content if the content could be parseddata
attribute with the content from the data key from theresult
hash, if it is presentstatusCode
attribute with HTTP status code of the responserequest
attribute with the details of the original request madeparsed
attribute which should betrue
when the JSON was successfully parsed17. Requests
18. Pagination
.next
,.first
,.last
,.previous
methods on the API client to find the relevant page for a responselet next_response = amadeus.next(response);
Key Developer Experience Interactions
19. Successful Path Interactions
locations = amadeus.reference_data.locations.get(keyword: 'lon', subType: Amadeus::Location::Airport)
let locations = amadeus.referenceData.locations.get({ keyword: 'lon', subType: Amadeus.location.airport });
amadeus.foo.bar(origin: locations.data.first['iataCode'])
amadeus.foo.bar({ origin: locations.data.first.iataCode });
20. Unsuccessful Path Interactions
Ruby example:
Node example:
```js amadeus.client.get('/foo/bar').then(...).catch(...); ``` ```js Amadeus AuthenticationError { error: 'invalid_client', error_description: 'Client credentials are invalid', code: 38187, title: 'Invalid parameters' } ```- [x] __20.2__ When an unknown path is provided, the error returned __should__ be clear even when debug mode is off
Ruby example:
```ruby amadeus.get('/foo/bar') ``` ```js W, [2018-02-19T16:06:13.523516 #67786] WARN -- Amadeus NotFoundError: [ { "code": 38196, "title": "Resource not found", "detail": "The targeted resource doesn't exist", "status": 404 } ] ```Node example:
```js amadeus.client.get('/foo/bar').then(...).catch(...); ``` ```js Amadeus NotFoundError [ { code: 38196, title: 'Resource not found', detail: 'The targeted resource doesn\'t exist', status: 404 } ] ```- [x] __20.3__ When incorrect params are provided, the error returned __should__ be clear even when debug mode is off
Ruby example:
```ruby amadeus.reference_data.locations.get( subType: Amadeus::Location::ANY ) ``` ```js W, [2018-02-19T16:05:55.923870 #67772] WARN -- Amadeus ClientError: [ { "status": 400, "code": 32171, "title": "MANDATORY DATA MISSING", "detail": "Missing mandatory query parameter", "source": { "parameter": "keyword" } } ] ```Node example:
```js amadeus.referenceData.locations.get({ keyword: 'lon' }).then(...).catch(...); ``` ```js Amadeus ClientError [ { status: 400, code: 32171, title: 'MANDATORY DATA MISSING', detail: 'Missing mandatory query parameter', source: { parameter: 'subType' } } ] ```- [x] __20.4__ When a server error occurs, the error returned __should__ be clear even when debug mode is off
Ruby example:
```js amadeus.get('/something/that/errors/'); ``` ```js W, [2018-02-19T16:07:42.651272 #67846] WARN -- Amadeus ServerError: [ { "code": 38189, "title": "Internal error", "detail": "An internal error occured, please contact your administrator", "status": 500 } ] ```Node example:
```js amadeus.get('/something/that/errors/').then(...).catch(...); ``` ```js Amadeus ServerError [ { code: 38189, title: 'Internal error', detail: 'An internal error occured, please contact your administrator', status: 500 } ] ```- [x] __20.5__ When a network error occurs, the error returned __should__ be clear even when debug mode is off
Ruby example:
```js amadeus.get('/something/that/errors/'); ``` ```js W, [2018-02-19T16:13:14.374444 #68060] WARN -- Amadeus NetworkError: nil ```Node example:
```js amadeus.get('/something/that/errors/').then(...).catch(...); ``` ```js Amadeus NetworkError null ```- [x] __20.6__ When a rate limit occurs, the error returned __should__ be clear even when debug mode is off
Ruby example:
```js amadeus.get('/something/that/rate/limits/'); ``` ```js W, [2018-02-19T16:07:42.651272 #67846] WARN -- Amadeus ServerError: [ { code: 38194, title: 'Too many requests', detail: 'The network rate limit is exceeded, please try again later', status: 429 } ] ```Node example:
```js amadeus.get('/something/that/errors/').then(...).catch(...); ``` ```js Amadeus ClientError [ { code: 38194, title: 'Too many requests', detail: 'The network rate limit is exceeded, please try again later', status: 429 } ] ```## Specific Language Requirements ### 22. Node / Javascript - [x] __22.1__ The SDK __should__ promises - [x] __22.2__ The SDK __could__ support ES7's `async/await` - [x] __22.3__ The SDK __should__ be written in ES6+ - [x] __22.4__ The SDK __should__ work in an ES5 environment - [x] __22.5__ The SDK __should__ support ES6 modules