ti2 1.0.7 → 1.0.11

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.
@@ -1,24 +1,24 @@
1
- /* globals describe it expect beforeAll, afterAll */
1
+ /* globals describe it expect */
2
2
 
3
3
  const chance = require('chance').Chance();
4
- const request = require('supertest');
5
4
  const jwt = require('jwt-promise');
6
-
7
- const app = require('../../index');
8
- const sqldb = require('../../models/db');
9
- const { slugify } = require('../../test/utils');
5
+ const testUtils = require('../../test/utils');
6
+ const slugify = require('../../test/slugify');
10
7
 
11
8
  const { env: { adminKey, jwtSecret } } = process;
12
9
 
13
10
  describe('app', () => {
14
11
  const appName = slugify(
15
12
  chance.company(),
16
- ).toLowerCase();
13
+ );
17
14
  const newApp = {
18
15
  name: appName,
19
16
  packageName: `ti2-${appName}`,
20
17
  adminEmail: chance.email(),
21
18
  };
19
+ const { doApiPost, doApiGet, doApiPut } = testUtils({
20
+ plugins: [appName],
21
+ });
22
22
  let appKey;
23
23
  const userId = chance.guid();
24
24
  const apiKey = chance.guid();
@@ -31,47 +31,43 @@ describe('app', () => {
31
31
  payload: { lorem: chance.paragraph() },
32
32
  };
33
33
  let encodedKey;
34
- beforeAll(async () => {
35
- const resp = await request(app)
36
- .post('/app')
37
- .set('Authorization', `Bearer ${adminKey}`)
38
- .send(newApp);
39
- expect(resp.statusCode).toBe(200);
40
- expect(resp.body.value).toBeTruthy();
41
- appKey = resp.body.value;
42
- });
43
- afterAll(async () => {
44
- await sqldb.connectionManager.close();
34
+ it('should create a new app', async () => {
35
+ ({ value: appKey } = await doApiPost({
36
+ url: '/app',
37
+ token: adminKey,
38
+ payload: newApp,
39
+ }));
40
+ expect(appKey).toBeTruthy();
45
41
  });
46
42
  it('should encode an airbitrary object', async () => {
47
- const resp = await request(app)
48
- .put(`/app/encode/${appName}`)
49
- .set('Authorization', `Bearer ${appKey}`)
50
- .send({ payload: encodePayload });
51
- expect(resp.statusCode).toBe(200);
52
- expect(resp.body.value).toBeTruthy();
53
- encodedKey = resp.body.value;
43
+ ({ value: encodedKey } = await doApiPut({
44
+ url: `/app/encode/${appName}`,
45
+ token: appKey,
46
+ payload: encodePayload,
47
+ }));
48
+ expect(encodedKey).toBeTruthy();
54
49
  });
55
50
  it('the encoded key should be decodable', async () => {
56
51
  const decoded = await jwt.verify(encodedKey, `${appName}.${jwtSecret}`);
57
- expect(decoded.payload).toEqual(expect.objectContaining(encodePayload));
52
+ expect(decoded).toEqual(expect.objectContaining(encodePayload));
58
53
  });
59
54
  it('should be able to create a user token for the app', async () => {
60
- const resp = await request(app)
61
- .post(`/${appName}/${userId}`)
62
- .set('Authorization', `Bearer ${appKey}`)
63
- .send({
55
+ const { value } = await doApiPost({
56
+ url: `/${appName}/${userId}`,
57
+ token: appKey,
58
+ payload: {
64
59
  tokenHint: apiKey.split('-')[0],
65
60
  token,
66
- });
67
- expect(resp.statusCode).toBe(200);
61
+ },
62
+ });
63
+ expect(parseInt(value, 10)).toBeGreaterThan(0);
68
64
  });
69
65
  it('should be able to get a list of all tokens related to the app', async () => {
70
- const resp = await request(app)
71
- .get(`/app/tokens/${appName}`)
72
- .set('Authorization', `Bearer ${appKey}`);
73
- expect(resp.statusCode).toBe(200);
74
- expect(resp.body.userAppKeys).toEqual(
66
+ const { userAppKeys } = await doApiGet({
67
+ url: `/app/tokens/${appName}`,
68
+ token: appKey,
69
+ });
70
+ expect(userAppKeys).toEqual(
75
71
  expect.arrayContaining([
76
72
  expect.objectContaining({
77
73
  hint: apiKey.split('-')[0],
@@ -1,43 +1,59 @@
1
1
  /* globals describe it expect */
2
2
 
3
- const { doApiGet, doApiPost } = require('../../test/utils');
3
+ const chance = require('chance').Chance();
4
+ const testUtils = require('../../test/utils');
4
5
 
5
6
  const { env: { adminKey } } = process;
6
7
 
7
- const newApp = {
8
- name: 'travelgate',
9
- packageName: 'ti2-travelgate',
10
- adminEmail: 'engineering+travelgate@tourconnect.com',
11
- };
12
- const appKey = newApp.name;
13
- const userId = '551394be5ac58e5c76000019';
14
- const newIntegration = {
15
- tokenHint: 'testingToken',
16
- token: {
8
+ describe('user: booking search', () => {
9
+ const newApp = {
10
+ name: 'travelgate',
11
+ packageName: 'ti2-travelgate',
12
+ adminEmail: 'engineering+travelgate@tourconnect.com',
13
+ };
14
+ const appKey = newApp.name;
15
+ const userId = '551394be5ac58e5c76000019';
16
+ const token = {
17
17
  endpoint: 'https://api.travelgatex.com',
18
- apiKey: '8ca687f8-7968-4331-7b1a-dfcb276e5e44',
18
+ apiKey: chance.guid(),
19
19
  client: 'tourconnect',
20
- },
21
- };
20
+ };
21
+ const newIntegration = {
22
+ tokenHint: 'testingToken',
23
+ token,
24
+ };
25
+ const {
26
+ doApiDelete,
27
+ doApiGet,
28
+ doApiPost,
29
+ plugins,
30
+ } = testUtils({
31
+ plugins: [newApp.name],
32
+ });
22
33
 
23
- describe('user: booking search', () => {
24
34
  let userToken;
35
+ it('drop any existing travelgateapp integration', async () => {
36
+ try {
37
+ await doApiDelete({
38
+ url: `/travelgate/${userId}`,
39
+ token: adminKey,
40
+ payload: { tokenHint: 'testingToken' },
41
+ });
42
+ } catch {}
43
+ try {
44
+ await doApiDelete({
45
+ url: '/app/travelgate',
46
+ token: adminKey,
47
+ });
48
+ } catch {}
49
+ });
25
50
  it('create the travelgate app', async () => {
26
- // create the travelgate app
27
- // get the list of existing
28
- const { integrations } = await doApiGet({
29
- url: '/apps',
51
+ const { value: apiKey } = await doApiPost({
52
+ url: '/app',
30
53
  token: adminKey,
54
+ payload: newApp,
31
55
  });
32
- if (!integrations.map(e => e.name).includes(newApp.name)) {
33
- // creating the app
34
- const { value: appKey } = await doApiPost({
35
- url: '/app',
36
- token: adminKey,
37
- payload: newApp,
38
- });
39
- expect(appKey).toBeTruthy();
40
- }
56
+ expect(apiKey).toBeTruthy();
41
57
  // create the user token
42
58
  ({ value: userToken } = await doApiPost({
43
59
  url: '/user',
@@ -61,15 +77,93 @@ describe('user: booking search', () => {
61
77
  expect(value).toBeTruthy();
62
78
  }
63
79
  });
64
- it('should be able to search a travel gate for a booking', async () => {
65
- const retVal = await doApiPost({
80
+ it('should be able to search a for a booking', async () => {
81
+ const payload = {
82
+ bookingId: '', supplierId: '', name: '',
83
+ };
84
+ const { bookings } = await doApiPost({
66
85
  url: `/bookings/${appKey}/${userId}/search`,
67
86
  token: userToken,
68
- payload: {
69
- bookingId: '', supplierId: '', name: '',
70
- },
87
+ payload,
88
+ });
89
+ expect(plugins[0].searchHotelBooking).toHaveBeenCalled();
90
+ expect(Array.isArray(bookings)).toBeTruthy();
91
+ expect(plugins[0].searchHotelBooking.mock.calls[0][0].payload).toEqual(payload);
92
+ expect(plugins[0].searchHotelBooking.mock.calls[0][0].token).toEqual(token);
93
+
94
+ // expect(Array.isArray(retVal.bookings)).toBeTruthy();
95
+ // expect(retVal.bookings.length > 0).toBeTruthy();
96
+ });
97
+
98
+ it('should be able to search a for a booking product', async () => {
99
+ const payload = {};
100
+ const { products } = await doApiPost({
101
+ url: `/products/${appKey}/${userId}/search`,
102
+ token: userToken,
103
+ payload,
104
+ });
105
+ expect(plugins[0].searchProducts).toHaveBeenCalled();
106
+ expect(Array.isArray(products)).toBeTruthy();
107
+ expect(plugins[0].searchProducts.mock.calls[0][0].payload).toEqual(payload);
108
+ expect(plugins[0].searchProducts.mock.calls[0][0].token).toEqual(token);
109
+
110
+ // expect(Array.isArray(retVal.bookings)).toBeTruthy();
111
+ // expect(retVal.bookings.length > 0).toBeTruthy();
112
+ });
113
+ it('should be able to search for availabiility', async () => {
114
+ const payload = {
115
+ travelDateStart: '12/30/2025',
116
+ travelDateEnd: '01/15/2026',
117
+ dateFormat: 'MM/DD/YYYY',
118
+ occupancies: [{ paxes: [{ age: 30 }, { age: 40 }] }],
119
+ currency: 'EUR',
120
+ market: 'ES',
121
+ language: 'es',
122
+ nationality: 'ES',
123
+ };
124
+ const { availability } = await doApiPost({
125
+ url: `/bookings/${appKey}/${userId}/availability`,
126
+ token: userToken,
127
+ payload,
128
+ });
129
+ expect(plugins[0].searchAvailability).toHaveBeenCalled();
130
+ expect(Array.isArray(availability)).toBeTruthy();
131
+ expect(plugins[0].searchAvailability.mock.calls[0][0].payload).toEqual(payload);
132
+ expect(plugins[0].searchAvailability.mock.calls[0][0].token).toEqual(token);
133
+ });
134
+ it('should be able to obtain a quote', async () => {
135
+ const payload = {
136
+ id: chance.guid(), // availability result id
137
+ travelDateStart: '12/30/2025',
138
+ travelDateEnd: '01/15/2026',
139
+ dateFormat: 'MM/DD/YYYY',
140
+ occupancies: [{ paxes: [{ age: 30 }, { age: 40 }] }],
141
+ currency: 'EUR',
142
+ market: 'ES',
143
+ language: 'es',
144
+ nationality: 'ES',
145
+ };
146
+ const { quote } = await doApiPost({
147
+ url: `/bookings/${appKey}/${userId}/quote`,
148
+ token: userToken,
149
+ payload,
150
+ });
151
+ expect(plugins[0].searchQuote).toHaveBeenCalled();
152
+ expect(Array.isArray(quote)).toBeTruthy();
153
+ expect(plugins[0].searchQuote.mock.calls[0][0].payload).toEqual(payload);
154
+ expect(plugins[0].searchQuote.mock.calls[0][0].token).toEqual(token);
155
+ });
156
+ it('should be able create a booking', async () => {
157
+ const payload = {
158
+ id: chance.guid(),
159
+ };
160
+ await doApiPost({
161
+ url: `/bookings/${appKey}/${userId}/booking`,
162
+ token: userToken,
163
+ payload,
71
164
  });
72
- expect(Array.isArray(retVal.bookings)).toBeTruthy();
73
- expect(retVal.bookings.length > 0).toBeTruthy();
165
+ expect(plugins[0].createBooking).toHaveBeenCalled();
166
+ expect(plugins[0].createBooking.mock.calls[0][0].payload).toEqual(payload);
167
+ expect(plugins[0].createBooking.mock.calls[0][0].token).toEqual(token);
74
168
  });
75
169
  });
@@ -1,18 +1,13 @@
1
1
  /* global describe, it, expect */
2
2
 
3
- // const should = require('should');
4
- const request = require('supertest');
5
- const server = require('../../index');
3
+ const { doApiGet } = require('../../test/utils')();
6
4
 
7
5
  describe('ping', () => {
8
6
  it('should get a server pong', async () => {
9
- const response = await request(server)
10
- .get('/ping')
11
- .set('Accept', 'application/json');
12
- expect(response.headers['content-type']).toMatch(/json/);
13
- expect(response.statusCode).toBe(200);
14
- expect(response.body.error).toBeUndefined();
15
- expect(Object.keys(response.body))
7
+ const response = await doApiGet({
8
+ url: '/ping',
9
+ });
10
+ expect(Object.keys(response))
16
11
  .toEqual(expect.arrayContaining([
17
12
  'name',
18
13
  'description',
@@ -1,10 +1,8 @@
1
- /* globals describe it expect beforeAll, afterAll, jest, afterEach */
1
+ /* globals describe it expect beforeAll, jest, afterEach */
2
2
 
3
3
  const chance = require('chance').Chance();
4
- const request = require('supertest');
5
- const { getRequireMocks, slugify } = require('../../test/utils');
6
- const app = require('../../index');
7
- const sqldb = require('../../models/db');
4
+ const testUtils = require('../../test/utils');
5
+ const slugify = require('../../test/slugify');
8
6
 
9
7
  const { env: { adminKey } } = process;
10
8
 
@@ -17,6 +15,9 @@ describe('user', () => {
17
15
  packageName: `ti2-${appName}`,
18
16
  adminEmail: chance.email(),
19
17
  };
18
+ const { doApiPost, doApiGet, doApiDelete } = testUtils({
19
+ plugins: [appName],
20
+ });
20
21
  let appKey;
21
22
  const userId = chance.guid();
22
23
  let apiKey = chance.guid();
@@ -27,43 +28,39 @@ describe('user', () => {
27
28
  };
28
29
  beforeAll(async () => {
29
30
  // create an App
30
- const resp = await request(app)
31
- .post('/app')
32
- .set('Authorization', `Bearer ${adminKey}`)
33
- .send(newApp);
34
- expect(resp.statusCode).toBe(200);
35
- expect(resp.body.value).toBeTruthy();
36
- appKey = resp.body.value;
37
- // create an App+User Mapping
38
- await request(app)
39
- .post(`/${appName}/${userId}`)
40
- .set('Authorization', `Bearer ${appKey}`)
41
- .send({
31
+ ({ value: appKey } = await doApiPost({
32
+ url: '/app',
33
+ token: adminKey,
34
+ payload: newApp,
35
+ }));
36
+ const url = `/${appName}/${userId}`;
37
+ await doApiPost({
38
+ url,
39
+ token: appKey,
40
+ payload: {
42
41
  tokenHint: apiKey.split('-')[0],
43
42
  token,
44
- });
43
+ },
44
+ });
45
45
  });
46
46
  let userKey;
47
- afterAll(async () => {
48
- await sqldb.connectionManager.close();
49
- });
50
47
  afterEach(() => jest.clearAllMocks());
51
48
  it('a user should be able to get a user token via an admin key', async () => {
52
- const resp = await request(app)
53
- .post('/user')
54
- .set('Authorization', `Bearer ${adminKey}`)
55
- .send({
56
- value: userId,
57
- });
58
- expect(resp.body.value).toBeTruthy();
59
- userKey = resp.body.value;
49
+ ({ value: userKey } = await doApiPost({
50
+ url: '/user',
51
+ token: adminKey,
52
+ payload: {
53
+ userId,
54
+ },
55
+ }));
56
+ expect(userKey).toBeTruthy();
60
57
  });
61
58
  it('a user should be able to get a list of it\'s mapped apps', async () => {
62
- const resp = await request(app)
63
- .get(`/user/${userId}/apps`)
64
- .set('Authorization', `Bearer ${userKey}`);
65
- expect(resp.statusCode).toBe(200);
66
- expect(resp.body.userAppKeys).toEqual(
59
+ const { userAppKeys } = await doApiGet({
60
+ token: userKey,
61
+ url: `/user/${userId}/apps`,
62
+ });
63
+ expect(userAppKeys).toEqual(
67
64
  expect.arrayContaining([
68
65
  expect.objectContaining({
69
66
  hint: apiKey.split('-')[0],
@@ -74,17 +71,16 @@ describe('user', () => {
74
71
  );
75
72
  });
76
73
  it('should be able to delete a user/app key', async () => {
77
- const resp = await request(app)
78
- .delete(`/${appName}/${userId}`)
79
- .set('Authorization', `Bearer ${userKey}`)
80
- .send({ tokenHint: apiKey.split('-')[0] });
81
- expect(resp.statusCode).toBe(200);
82
- // make sure the app token is NOT there
83
- const respList = await request(app)
84
- .get(`/user/${userId}/apps`)
85
- .set('Authorization', `Bearer ${userKey}`);
86
- expect(respList.statusCode).toBe(200);
87
- expect(respList.body.userAppKeys).toEqual(
74
+ await doApiDelete({
75
+ url: `/${appName}/${userId}`,
76
+ token: userKey,
77
+ payload: { tokenHint: apiKey.split('-')[0] },
78
+ });
79
+ const { userAppKeys } = await doApiGet({
80
+ url: `/user/${userId}/apps`,
81
+ token: userKey,
82
+ });
83
+ expect(userAppKeys).toEqual(
88
84
  expect.not.arrayContaining([
89
85
  expect.objectContaining({
90
86
  hint: apiKey.split('-')[0],
@@ -98,20 +94,20 @@ describe('user', () => {
98
94
  // set up new token
99
95
  apiKey = chance.guid();
100
96
  token.apiKey = apiKey;
101
- const resp = await request(app)
102
- .post(`/${appName}/${userId}`)
103
- .set('Authorization', `Bearer ${userKey}`)
104
- .send({
97
+ await doApiPost({
98
+ url: `/${appName}/${userId}`,
99
+ token: userKey,
100
+ payload: {
105
101
  tokenHint: apiKey.split('-')[0],
106
102
  token,
107
- });
108
- expect(resp.statusCode).toBe(200);
103
+ },
104
+ });
109
105
  // make sure the app token is there
110
- const respList = await request(app)
111
- .get(`/user/${userId}/apps`)
112
- .set('Authorization', `Bearer ${userKey}`);
113
- expect(respList.statusCode).toBe(200);
114
- expect(respList.body.userAppKeys).toEqual(
106
+ const { userAppKeys } = await doApiGet({
107
+ url: `/user/${userId}/apps`,
108
+ token: userKey,
109
+ });
110
+ expect(userAppKeys).toEqual(
115
111
  expect.arrayContaining([
116
112
  expect.objectContaining({
117
113
  hint: apiKey.split('-')[0],
@@ -122,12 +118,11 @@ describe('user', () => {
122
118
  );
123
119
  });
124
120
  it('should be able to get all the methods for an app', async () => {
125
- getRequireMocks({ jest, app: newApp });
126
- const methods = await request(app)
127
- .get(`/app/${appName}/methods`)
128
- .set('Authorization', `Bearer ${userKey}`);
129
- expect(methods.statusCode).toBe(200);
130
- expect(methods.body.methods).toEqual(
121
+ const { methods } = await doApiGet({
122
+ url: `/app/${appName}/methods`,
123
+ token: userKey,
124
+ });
125
+ expect(methods).toEqual(
131
126
  expect.arrayContaining([
132
127
  'validateToken', 'getProduct',
133
128
  ]),
@@ -12,21 +12,43 @@ const createApp = async (req, res, next) => {
12
12
  adminEmail,
13
13
  } = req.body;
14
14
  try {
15
- const newApp = await sqldb.Integration.create({
16
- name,
17
- packageName,
18
- adminEmail,
15
+ const existing = await sqldb.Integration.findByPk(name, { paranoid: false });
16
+ const apiKey = await (async () => {
17
+ if (existing) {
18
+ await existing.restore();
19
+ return existing.apiKey;
20
+ }
21
+ const newApp = await sqldb.Integration.create({
22
+ name,
23
+ packageName,
24
+ adminEmail,
25
+ });
26
+ return newApp.apiKey;
27
+ })();
28
+ return res.json({ value: apiKey });
29
+ } catch (err) {
30
+ return next(err);
31
+ }
32
+ };
33
+
34
+ const deleteApp = async (req, res, next) => {
35
+ const { pathParams: { appKey: name } } = req;
36
+ try {
37
+ const newApp = await sqldb.Integration.destroy({
38
+ where: { name },
19
39
  });
20
40
  const { apiKey } = newApp;
21
41
  return res.json({ value: apiKey });
22
42
  } catch (err) {
43
+ console.log({ err });
23
44
  return next(err);
24
45
  }
25
46
  };
26
47
 
27
48
  const listApps = async (req, res, next) => {
28
49
  try {
29
- const integrations = await sqldb.Integration.findAll().map(int => omit(['apiKey'], int.dataValues));
50
+ const integrations = (await sqldb.Integration.findAll())
51
+ .map(int => omit(['apiKey'], int.dataValues));
30
52
  return res.json({ integrations });
31
53
  } catch (err) {
32
54
  return next(err);
@@ -71,6 +93,7 @@ const resetIntegrationToken = async (req, res, next) => {
71
93
 
72
94
  module.exports = {
73
95
  createApp,
96
+ deleteApp,
74
97
  createUserToken,
75
98
  listApps,
76
99
  resetIntegrationToken,
@@ -25,7 +25,6 @@ const bookingsSearch = plugins => async (req, res, next) => {
25
25
  });
26
26
  return res.json(results);
27
27
  } catch (err) {
28
- console.log({ err });
29
28
  return next(err);
30
29
  }
31
30
  };
@@ -57,7 +56,121 @@ const bookingsCancel = plugins => async (req, res, next) => {
57
56
  }
58
57
  };
59
58
 
59
+ const bookingsProductSearch = plugins => async (req, res, next) => {
60
+ const {
61
+ params: { appKey, userId, hint },
62
+ body: payload,
63
+ } = req;
64
+ try {
65
+ const app = plugins.find(({ name }) => name === appKey);
66
+ // const app = load(appKey);
67
+ const userAppKeys = (await UserAppKey.findOne({
68
+ where: {
69
+ userId,
70
+ integrationId: appKey,
71
+ ...(hint ? { hint } : {}),
72
+ },
73
+ }));
74
+ assert(userAppKeys, 'could not find the app key');
75
+ const token = userAppKeys.appKey;
76
+ const results = await app.searchProducts({
77
+ token,
78
+ payload,
79
+ });
80
+ return res.json(results);
81
+ } catch (err) {
82
+ return next(err);
83
+ }
84
+ };
85
+
86
+ const bookingsAvailabilitySearch = plugins => async (req, res, next) => {
87
+ const {
88
+ params: { appKey, userId, hint },
89
+ body: payload,
90
+ } = req;
91
+ try {
92
+ const app = plugins.find(({ name }) => name === appKey);
93
+ // const app = load(appKey);
94
+ const userAppKeys = (await UserAppKey.findOne({
95
+ where: {
96
+ userId,
97
+ integrationId: appKey,
98
+ ...(hint ? { hint } : {}),
99
+ },
100
+ }));
101
+ assert(userAppKeys, 'could not find the app key');
102
+ const token = userAppKeys.appKey;
103
+ const results = await app.searchAvailability({
104
+ token,
105
+ payload,
106
+ });
107
+ return res.json(results);
108
+ } catch (err) {
109
+ return next(err);
110
+ }
111
+ };
112
+
113
+ const searchQuote = plugins => async (req, res, next) => {
114
+ const {
115
+ params: { appKey, userId, hint },
116
+ body: payload,
117
+ } = req;
118
+ try {
119
+ const app = plugins.find(({ name }) => name === appKey);
120
+ // const app = load(appKey);
121
+ const userAppKeys = (await UserAppKey.findOne({
122
+ where: {
123
+ userId,
124
+ integrationId: appKey,
125
+ ...(hint ? { hint } : {}),
126
+ },
127
+ }));
128
+ assert(userAppKeys, 'could not find the app key');
129
+ const token = userAppKeys.appKey;
130
+ assert(payload.id, 'the availability id is required');
131
+ const results = await app.searchQuote({
132
+ token,
133
+ payload,
134
+ });
135
+ return res.json(results);
136
+ } catch (err) {
137
+ return next(err);
138
+ }
139
+ };
140
+
141
+ const createBooking = plugins => async (req, res, next) => {
142
+ const {
143
+ params: { appKey, userId, hint },
144
+ body: payload,
145
+ } = req;
146
+ try {
147
+ const app = plugins.find(({ name }) => name === appKey);
148
+ // const app = load(appKey);
149
+ const userAppKeys = (await UserAppKey.findOne({
150
+ where: {
151
+ userId,
152
+ integrationId: appKey,
153
+ ...(hint ? { hint } : {}),
154
+ },
155
+ }));
156
+ assert(userAppKeys, 'could not find the app key');
157
+ const token = userAppKeys.appKey;
158
+ assert(payload.id, 'the quote id is required');
159
+ const results = await app.createBooking({
160
+ token,
161
+ payload,
162
+ });
163
+ return res.json(results);
164
+ } catch (err) {
165
+ return next(err);
166
+ }
167
+ };
168
+
60
169
  module.exports = plugins => ({
61
170
  bookingsSearch: bookingsSearch(plugins),
62
171
  bookingsCancel: bookingsCancel(plugins),
172
+ bookingsProductSearch: bookingsProductSearch(plugins),
173
+ bookingsAvailabilitySearch: bookingsAvailabilitySearch(plugins),
174
+ searchQuote: searchQuote(plugins),
175
+ createBooking: createBooking(plugins),
63
176
  });