Welcome to the second part of the reactive X exercises, lets checkout the branch exercise/rxjs. You can then edit the index.ts file to do the exercises.

git checkout exercise/rxjs-dapi
yarn install
yarn start

In these exercises we will merge what we have learned so far, the typescript sdk and rxjs. This way instead of using promises with async/await to handle the calls to the api we will use observables. The departure point will be the same as for the typescript sdk exercises:

(async () => {
  // Initialize the digital API targeting DigitalForAirlines gateway.
  const gatewayAddress = 'https://test.airlines.api.amadeus.com/v1/security/oauth2';
  const gatewayPlugin = createAmadeusGatewayTokenRequest({
    gatewayUrl: gatewayAddress,
    gatewayClientId: 'CQZddrc7RFTBmG6Hbl7pQTyiPtHUuOAq',
    gatewayClientPrivate: 'NaeP7dKAgV2emuvi'
  });
  const clientFactsPlugin = new ClientFactsRequestPlugin({
    initialGlobalFacts: {
      corporateCodes: '000001'
    }
  });
  const client = new ApiFetchClient({
    basePath: 'https://test.airlines.api.amadeus.com/v2',
    requestPlugins: [gatewayPlugin, clientFactsPlugin, new SessionIdRequest()]
  });
  const api = {
    airBoundApi: new AirBoundApi(client),
    cartApi: new CartApi(client),
    orderApi: new OrderApi(client)
  };

  // Some data to accelerate building your calls
  const millisecondsInADay = 24 * 3600 * 1000;
  const tomorrow = new utils.DateTime(new Date().setHours(0, 0, 0, 0) + millisecondsInADay);
  const commercialFareFamilies = ['ECONOMY', 'BUSINESS'];
})();

The following 4 exercises follow a similar structure as we had seen in the typescript sdk, we are working with the cart centric approach, so we will search for some flights, create a cart

Solution

const returnDate = new utils.DateTime(new Date().setHours(0, 0, 0, 0) + 6 * millisecondsInADay);
const offersPromise = api.airBoundApi.airBoundsShopping({
  airBoundsInputs: {
    itineraries: [{
      departureDateTime: tomorrow,
      originLocationCode: 'LHR',
      destinationLocationCode: 'CDG',
      isRequestedBound: true
    }, {
      departureDateTime: returnDate,
      originLocationCode: 'CDG',
      destinationLocationCode: 'LHR'
    }],
    commercialFareFamilies: commercialFareFamilies
  }
});

const offers$ = from(offersPromise);
offers$.subscribe((offers) => console.log(offers.data.airBoundGroups.length));

Solution

const inboundOffers$ = outboundOffers$.pipe(
  map((offers) => offers.data.airBoundGroups[1].airBounds[0].airBoundId),
  switchMap((selectedBoundId) => from(
    api.airBoundApi.airBoundsShopping({
      airBoundsInputs: {
        itineraries: [{
          departureDateTime: tomorrow,
          originLocationCode: 'LHR',
          destinationLocationCode: 'CDG'
        }, {
          departureDateTime: returnDate,
          originLocationCode: 'CDG',
          destinationLocationCode: 'LHR',
          isRequestedBound: true
        }],
        commercialFareFamilies: commercialFareFamilies,
        selectedBoundId
      }
    })
  )),
  map((offerReply) => offerReply.data)
);

Solution

const sharedOffer$ = inboundOffers$.pipe(map((offers) => offers.airBoundGroups[1].airBounds[0]), share());
sharedOffer$.subscribe((offer) => console.log(offer.airBoundId));
sharedOffer$.subscribe((offer) => console.log(offer.fareFamilyCode));

Solution

const cart$ = from(api.cartApi.createCart({}));
combineLatest([
  cart$,
  outboundOffers$.pipe(map((offers) => offers.data.airBoundGroups[0].airBounds[0].airBoundId)),
  sharedOffer$.pipe(map((offer) => offer.airBoundId))
]).pipe(
  switchMap(([cartReply, outboundOfferId, inboundOfferId]) =>
    from(
      api.cartApi.addAirOfferToCart({
        cartId: cartReply.data.id,
        postAirOfferBody: {
          airBoundIds: [outboundOfferId, inboundOfferId]
        }
      })
    ).pipe(
      map(() => cartReply.data.id)
    )
  ),
  switchMap((cartId) => from(api.cartApi.retrieveCart({cartId})))
).subscribe((cart: CartReply) => console.log(`The cart contains ${cart.data.airOffers.length} offer`));