ti2 1.0.10 → 1.0.13
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 +40 -66
- package/api.yml +480 -15
- package/controllers/__tests__/bookings.js +74 -2
- package/controllers/bookings.js +114 -1
- package/jsdoc.conf.json +25 -0
- package/package.json +5 -2
- package/test/plugin.js +386 -3
- package/tutorials/index.json +8 -0
- package/tutorials/plugin-development.md +220 -0
- package/tutorials/setup-your-instance.md +77 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
## Environment values
|
|
2
|
+
|
|
3
|
+
Plugin environment keys are passed down to the instance while is being created, this is the preferred way of accesing environmen keys from the plugins, such values are not design to hold client / user's API keys or specific data, they are to be stored on the database itself via the AppKey collection.
|
|
4
|
+
|
|
5
|
+
Plugin ENV variable name convention: ti2_pluginName_environmenVariableName, for example:
|
|
6
|
+
|
|
7
|
+
```env
|
|
8
|
+
ti2_tourconnect_apiUrl=http://backend:8080
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Methods
|
|
12
|
+
|
|
13
|
+
In oorder for an integration or system apps, we must use a set of standirzed methods to matain a compatibility; there are following methods are available, more can be supported but should be a part of the API TI2 spec to maximize it's compatibility.
|
|
14
|
+
|
|
15
|
+
**General Methods** (should always be included):
|
|
16
|
+
* [validateToken]{@link Plugin#validateToken}
|
|
17
|
+
|
|
18
|
+
**Content Methods** (related to marketing information update for profile, locations and/or products):
|
|
19
|
+
* [getProfile]{@link Plugin#getProfile}
|
|
20
|
+
* [updateProfile]{@link Plugin#updateProfile}
|
|
21
|
+
* [createLocation]{@link Plugin#createLocation}
|
|
22
|
+
* [updateLocation]{@link Plugin#updateLocation}
|
|
23
|
+
* [getProducts]{@link Plugin#getProducts}
|
|
24
|
+
* [createProduct]{@link Plugin#createProduct}
|
|
25
|
+
* [updateProduct]{@link Plugin#updateProduct}
|
|
26
|
+
|
|
27
|
+
**Booking Methods** (all related to bookings and operations):
|
|
28
|
+
* [searchBooking]{@link Plugin#searchBooking}
|
|
29
|
+
* [searchProducts]{@link Plugin#searchProducts}
|
|
30
|
+
* [searchAvailability]{@link Plugin#searchAvailability}
|
|
31
|
+
* [searchQuote]{@link Plugin#searchQuote}
|
|
32
|
+
* [createBooking]{@link Plugin#createBooking}
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
## Codebase setup
|
|
38
|
+
|
|
39
|
+
You can review some of the plugins previously developed and use them as a guide, plugin methods are encourage to include tests and return results on the same format, however the return values can include additional information, currently Ti2 is expected to run on node version 12.22.8; we suggest you use the same for your codebase.
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
After initializing your git environment for development; you can initialize your node project; we recommend naming your repo ti2-\<pluginname\> but it is not required.
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
$ node init .
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Entry file / constructor
|
|
49
|
+
|
|
50
|
+
The plugin is expected to have an index.js file that exports a Plugin Class like so:
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
// index.js
|
|
54
|
+
class Plugin {
|
|
55
|
+
constructor(params = {}) { // we get the env variables from here
|
|
56
|
+
Object.entries(params).forEach(([attr, value]) => {
|
|
57
|
+
this[attr] = value;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
module.exports = Plugin;
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The constructor of the plugins should extend the attributes with the received params, this allows the plugin to receive configurations or settings that are to be used by any user; that is settings that are shared across accounts.
|
|
65
|
+
|
|
66
|
+
By default Ti2 will pass down all environment variables that match the plugin name to it's constructor; for example, if the following environment variables are defined:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
ti2_ventrata_acceptLanguage=en
|
|
70
|
+
ti2_travelgate_clientCode=tourconnect
|
|
71
|
+
ti2_tourconnect_apiUrl=http://backend:8080
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The plugin named ti2-ventrata would receive acceptLanguage variable and it's value, ti2-travelgate the clientCode variable and ti-touconnect the apiUrl value.
|
|
75
|
+
|
|
76
|
+
## Method calling
|
|
77
|
+
|
|
78
|
+
On the previous example code we are declaring a validateToken method; we are normally expected to receive two parameters one is token and the second one payload.
|
|
79
|
+
|
|
80
|
+
```javascript
|
|
81
|
+
// index.js
|
|
82
|
+
class Plugin {
|
|
83
|
+
constructor(params = {}) { // we get the env variables from here
|
|
84
|
+
Object.entries(params).forEach(([attr, value]) => {
|
|
85
|
+
this[attr] = value;
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
async validateToken({
|
|
89
|
+
token: {
|
|
90
|
+
apiKey = this.apiKey,
|
|
91
|
+
apiUrl = this.apiUrl,
|
|
92
|
+
},
|
|
93
|
+
}) {
|
|
94
|
+
// TODO: actually test the apiKey against the integration.
|
|
95
|
+
return assert(apiKey);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
module.exports = Plugin;
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The token parameter includes all the settings for the current configured user; on these example we are defauring this settings to the ones configured to the pluging when it was instanced; so if the user settings do not include an apiUrl it will fall back to the environment variable on the running server.
|
|
102
|
+
|
|
103
|
+
## Testing Suite
|
|
104
|
+
|
|
105
|
+
The plugin should contain a test file, for the following example assumes we will be using jest as the testing platform.
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
$ npm i -D jest
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
```javascript
|
|
112
|
+
// index.test.js
|
|
113
|
+
const Plugin = require('./index');
|
|
114
|
+
|
|
115
|
+
const app = new Plugin({
|
|
116
|
+
jwtKey: process.env.ti2_ventrata_jwtKey,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
describe('Base Tests', () => {
|
|
120
|
+
const token = { // a valid token to run tests
|
|
121
|
+
apiKey: process.env.ti2_ventrata_apiKey,
|
|
122
|
+
endpoint: process.env.ti2_ventrata_endpoint,
|
|
123
|
+
};
|
|
124
|
+
it('should not validate an invalid api key', async () => {
|
|
125
|
+
const isValid = await app.validateToken({
|
|
126
|
+
token: { apiKey: 'some Randomg Text' }
|
|
127
|
+
});
|
|
128
|
+
expect(isValid).toBeFalsy();
|
|
129
|
+
});
|
|
130
|
+
it('should not validate an invalid api key', async () => {
|
|
131
|
+
const isValid = await app.validateToken({
|
|
132
|
+
token,
|
|
133
|
+
});
|
|
134
|
+
expect(isValid).toBeTruthy();
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
$ npx jest
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Adding the folder to a ti2 instance
|
|
145
|
+
|
|
146
|
+
After setting up a [Ti2 instance]{@tutorial setup-your-instance} you can add your development folder as a package on your instance's npm repo (not on the plugin's instance), like so:
|
|
147
|
+
|
|
148
|
+
```json
|
|
149
|
+
"dependencies": {
|
|
150
|
+
"ti2-myplugin": "file:../ti2-myplugin"
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Extending the base API
|
|
155
|
+
|
|
156
|
+
Ti2 uses the [Swagger API specification](https://swagger.io/specification/) standard to define it's own methods, you can review the base methods [here](https://ti2-staging.tourconnect.com/api-docs/); these methods can be extender using the same format; this allows any plugin to extend the base API endpoints that are linked to any plugin method (part of the base methods or new ones).
|
|
157
|
+
|
|
158
|
+
All the extender methods would be availble under the /\[plugin name] namespace, i.e.: /ti2-greatPlugin/ping.
|
|
159
|
+
|
|
160
|
+
For Ti2 to pickup the extender definition one must create a new file on the root of the plugin named api.yml, such file would contain only the methods to be extender and it must comply with the current swagger version used on ti2.
|
|
161
|
+
|
|
162
|
+
```yaml
|
|
163
|
+
# api.yml
|
|
164
|
+
openapi: '3.0.0'
|
|
165
|
+
info:
|
|
166
|
+
description: My amazing ti2-plugin
|
|
167
|
+
version: 0.0.1
|
|
168
|
+
title: Ti2's new plugin
|
|
169
|
+
components:
|
|
170
|
+
securitySchemes:
|
|
171
|
+
bearerAuth:
|
|
172
|
+
type: http
|
|
173
|
+
scheme: bearer
|
|
174
|
+
bearerFormat: JWT
|
|
175
|
+
schemas:
|
|
176
|
+
ServerInfo:
|
|
177
|
+
type: object
|
|
178
|
+
properties:
|
|
179
|
+
name:
|
|
180
|
+
type: string
|
|
181
|
+
description:
|
|
182
|
+
type: string
|
|
183
|
+
version:
|
|
184
|
+
type: string
|
|
185
|
+
uptime:
|
|
186
|
+
type: string
|
|
187
|
+
paths:
|
|
188
|
+
/ping:
|
|
189
|
+
get:
|
|
190
|
+
tags:
|
|
191
|
+
- public
|
|
192
|
+
summary: Should return basic system status
|
|
193
|
+
operationId: ping
|
|
194
|
+
responses:
|
|
195
|
+
'200':
|
|
196
|
+
description: success
|
|
197
|
+
content:
|
|
198
|
+
application/json:
|
|
199
|
+
schema:
|
|
200
|
+
$ref: '#/components/schemas/ServerInfo'
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Database Migrations (plugin's own database tables)
|
|
204
|
+
|
|
205
|
+
Ti2 uses [Sequelize v6.13](https://sequelize.org/v6) and is the database ORM we ecourage to use, you can add your own tables via migrations that should be placed under a migrations folder on the root of the plugin folder.
|
|
206
|
+
|
|
207
|
+
Migrations should be run after the fact, from the root of ti2 instance like so:
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
$ npm explore ti2<pluginName> -- npx sequelize db:migrate"
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
We strongly encourage all the plugin's table names are predicated with the plugin name (i.e. ti2-pluginName-cacheTable).
|
|
215
|
+
|
|
216
|
+
This should be executed ater the ti2 project migrations have been executed.
|
|
217
|
+
|
|
218
|
+
## Scheduled Task (to be released on v2)
|
|
219
|
+
|
|
220
|
+
TBD.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
## Initializing your new Repo
|
|
2
|
+
|
|
3
|
+
We suggest creating a folder with your instance name+i2 (i.e acme-ti2); then initialize an node's npm package and install ti2 along with any plugins to be used.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
$ mkdir acme-ti2
|
|
7
|
+
$ cd acmme-ti2
|
|
8
|
+
$ npm init .
|
|
9
|
+
$ npm i ti2 ti2-tourconnect
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Requirements
|
|
13
|
+
|
|
14
|
+
A MySQl instance is required and the following environment variables are required:
|
|
15
|
+
|
|
16
|
+
- DB_URL (mysql connection in url format)
|
|
17
|
+
- dbCryptoKey (integration details encription key, should be a 32 chars base64 encoded random string)
|
|
18
|
+
- adminKey (a key for admin related requests)
|
|
19
|
+
- jwtKey (a key to encrypt user sessions request)
|
|
20
|
+
- frontendKey (an additional optional key to validate the origin of the requests)
|
|
21
|
+
- PORT (an optional port to run the http server, in case a port is not specified as a parameter)
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
DB_URL=mysql://root:@mysqlserver/ti2development
|
|
25
|
+
dbCryptoKey=cG9VYmJyQ2tlSDVHeXQ4RUN4VlNieEJRejNYWDlZU0g=
|
|
26
|
+
jwtSecret=C8k0mrHVfWVTP7pIoZEHRrvFgTULhw3E4swDq1aoDH4P
|
|
27
|
+
frontendKey=IpOiLahrGQxsQimwoK7Z
|
|
28
|
+
adminKey=bCviyz7iKyuEBoOVlODn
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
After installing the ti2 package you need to run the datbase migrations for ti2:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
$ npm explore ti2<pluginName> -- npx sequelize db:migrate"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Entry File
|
|
38
|
+
|
|
39
|
+
then just create an entry file like this :
|
|
40
|
+
|
|
41
|
+
```javascript
|
|
42
|
+
// index.js
|
|
43
|
+
const ti2 = require('ti2')({
|
|
44
|
+
plugins: {
|
|
45
|
+
travelgate: require('ti2-travelgate'),
|
|
46
|
+
ventrata: require('ti2-ventrata'),
|
|
47
|
+
tourconnect: require('ti2-tourconnect'),
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
and stat the server using node:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
$ node index.js
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## API logging
|
|
59
|
+
|
|
60
|
+
Currently logging is supported via elastic search, an elasticLogClient value can ben passed down, example:
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
const { Client } = require('@elastic/elasticsearch');
|
|
64
|
+
const elasticLogsClient = (() => {
|
|
65
|
+
if (!elasticLogs) return null;
|
|
66
|
+
return new Client({ node: elasticLogs });
|
|
67
|
+
})();
|
|
68
|
+
|
|
69
|
+
const ti2 = require('ti2')({
|
|
70
|
+
elasticLogsClient,
|
|
71
|
+
plugins: {
|
|
72
|
+
ventrata: require('ti2-ventrata'),
|
|
73
|
+
travelgate: require('ti2-travelgate'),
|
|
74
|
+
tourconnect: require('ti2-tourconnect'),
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
```
|