@tonder.io/ionic-lite-sdk 0.0.16 → 0.0.17-beta

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 CHANGED
@@ -1,496 +1,496 @@
1
- # Tonder SDK
2
-
3
- Tonder SDK Lite to integrate REST service
4
-
5
- ## Installation
6
-
7
- You can install using NPM
8
- ```bash
9
- npm i @tonder/ionic-lite-sdk
10
- ```
11
-
12
- or using an script tag
13
- ```html
14
- // TO DO
15
- ```
16
-
17
- Add dependencies to the root of the app (index.html)
18
- ```html
19
- <script src=https://openpay.s3.amazonaws.com/openpay.v1.min.js></script>
20
- <script src=https://openpay.s3.amazonaws.com/openpay-data.v1.min.js></script>
21
- ```
22
-
23
- ## Usage
24
- ## Import LiteCheckout class
25
- ```javascript
26
- import { LiteCheckout } from "@tonder/ionic-lite-sdk"
27
- ```
28
- ## Create instance
29
-
30
- ```javascript
31
- const liteCheckout = new LiteCheckout({
32
- signal,
33
- baseUrlTonder,
34
- apiKeyTonder
35
- })
36
- ```
37
-
38
- | Property | Type | Description |
39
- |:---------------:|:-------------:|:-----------------------------------------------------------------------:|
40
- | signal | AborSignal | Signal from AbortController instance if it need cancel request |
41
- | baseUrlTonder | string | Live server: http://stage.tonder.io |
42
- | | | Mock Server: https://stoplight.io/mocks/tonder/tonder-api-v1-2/3152148 |
43
- | apiKeyTonder | string | You can take this from you Tonder Dashboard |
44
- | | | |
45
-
46
- # Class methods
47
-
48
- # Business
49
-
50
- ## Get business
51
-
52
- ```javascript
53
- const merchantData = await liteCheckout.getBusiness();
54
- ```
55
-
56
- ## Return business data
57
-
58
- ```typescript
59
- {
60
- business: {
61
- pk: number,
62
- name: string,
63
- categories: [
64
- {
65
- pk: number,
66
- name: string
67
- }
68
- ],
69
- web: string,
70
- logo: string,
71
- full_logo_url: string,
72
- background_color: string,
73
- primary_color: string,
74
- checkout_mode: boolean,
75
- textCheckoutColor: string,
76
- textDetailsColor: string,
77
- checkout_logo: string
78
- },
79
- openpay_keys: {
80
- merchant_id: string,
81
- public_key: string
82
- },
83
- fintoc_keys: {
84
- public_key: string
85
- },
86
- vault_id: string,
87
- vault_url: string,
88
- reference: number,
89
- is_installments_available: boolean
90
- }
91
- ```
92
-
93
- # OpenPay
94
-
95
- ## Get OpenPay session id
96
-
97
- ```javascript
98
- const { openpay_keys } = merchantData;
99
-
100
- const deviceSessionIdTonder = await liteCheckout.getOpenpayDeviceSessionID(
101
- openpay_keys.merchant_id,
102
- openpay_keys.public_key,
103
- is_sandbox: true
104
- );
105
- ```
106
-
107
- ## Return OpenPay device session id
108
-
109
- string
110
-
111
- # Customer
112
-
113
- ## Get customer authorization token
114
-
115
- ```javascript
116
- const customerEmail = "john.c.calhoun@examplepetstore.com";
117
-
118
- const { auth_token } = await liteCheckout.customerRegister(customerEmail);
119
- ```
120
-
121
- ## Return customer data
122
-
123
- ```typescript
124
- {
125
- id: number,
126
- email: string,
127
- auth_token: string
128
- }
129
- ```
130
-
131
- # Order
132
-
133
- ## Create order
134
-
135
- ```typescript
136
- const cartItems = [
137
- {
138
- description: "Test product description",
139
- quantity: 1,
140
- price_unit: 25,
141
- discount: 0,
142
- taxes: 12,
143
- product_reference: 65421,
144
- name: "Test product",
145
- amount_total: 25
146
- }
147
- ]
148
-
149
- const { reference } = merchantData;
150
-
151
- const orderData = {
152
- business: apiKeyTonder,
153
- client: auth_token,
154
- billing_address_id: null,
155
- shipping_address_id: null,
156
- amount: total,
157
- status: "A",
158
- reference: reference,
159
- is_oneclick: true,
160
- items: cartItems,
161
- };
162
-
163
- const jsonResponseOrder = await liteCheckout.createOrder(
164
- orderData
165
- );
166
- ```
167
-
168
- ## Return order data
169
- ```typescript
170
- {
171
- id: number,
172
- created: string,
173
- amount: string,
174
- status: string,
175
- payment_method?: string,
176
- reference?: string,
177
- is_oneclick: boolean,
178
- items: [
179
- {
180
- description: string,
181
- product_reference: string,
182
- quantity: string,
183
- price_unit: string,
184
- discount: string,
185
- taxes: string,
186
- amount_total: string
187
- }
188
- ],
189
- billing_address?: string,
190
- shipping_address?: string,
191
- client: {
192
- email: string,
193
- name: string,
194
- first_name: string,
195
- last_name: string,
196
- client_profile: {
197
- gender: string,
198
- date_birth?: string,
199
- terms: boolean,
200
- phone: string
201
- }
202
- }
203
- }
204
- ```
205
-
206
- # Payment
207
-
208
- ## Create payment
209
- ```javascript
210
- const now = new Date();
211
- const dateString = now.toISOString();
212
-
213
- const paymentData = {
214
- business_pk: business.pk,
215
- amount: total,
216
- date: dateString,
217
- order: jsonResponseOrder.id,
218
- };
219
-
220
- const jsonResponsePayment = await liteCheckout.createPayment(
221
- paymentData
222
- );
223
- ```
224
-
225
- ## Return payment data
226
- ```javascript
227
- {
228
- pk: number,
229
- order?: string,
230
- amount: string,
231
- status: string,
232
- date: string,
233
- paid_date?: string,
234
- shipping_address: {
235
- street: string,
236
- number: string,
237
- suburb: string,
238
- city: {
239
- name: string
240
- },
241
- state: {
242
- name: string,
243
- country: {
244
- name: string
245
- }
246
- },
247
- zip_code: string
248
- },
249
- shipping_address_id?: string,
250
- billing_address: {
251
- street: string,
252
- number: string,
253
- suburb: string,
254
- city: {
255
- name: string
256
- },
257
- state: {
258
- name: string,
259
- country: {
260
- name: string
261
- }
262
- },
263
- zip_code: string
264
- },
265
- billing_address_id?: string,
266
- client?: string,
267
- customer_order_reference?: string
268
- }
269
- ```
270
-
271
- # Skyflow tokens
272
-
273
- ## Get skyflow payment form tokenized values
274
-
275
- The values of the variable skyflowTokens come from your html form
276
-
277
- ```javascript
278
-
279
- const skyflowFields = {
280
- card_number: this.paymentForm.value.cardNumber,
281
- cvv: this.paymentForm.value.cvv,
282
- expiration_month: this.paymentForm.value.month,
283
- expiration_year: this.paymentForm.value.expirationYear,
284
- cardholder_name: this.paymentForm.value.name
285
- }
286
-
287
- const { vault_id, vault_url } = merchantData;
288
-
289
-
290
- const skyflowTokens = await liteCheckout.getSkyflowTokens({
291
- vault_id: vault_id,
292
- vault_url: vault_url,
293
- data: skyflowFields
294
- })
295
-
296
- ```
297
-
298
- ## Return skyflow tokenized data
299
- ```typescript
300
- {
301
- vaultID: string,
302
- responses: [
303
- {
304
- records: [
305
- {
306
- skyflow_id: string
307
- }
308
- ]
309
- },
310
- {
311
- fields: {
312
- card_number: string,
313
- cardholder_name: string,
314
- cvv: string,
315
- expiration_month: string,
316
- expiration_year: string,
317
- skyflow_id: string
318
- }
319
- }
320
- ]
321
- }
322
- ```
323
-
324
- # Checkout router
325
-
326
- ## Get checkout router data
327
-
328
- ```javascript
329
-
330
- const customerPhone = "+11111111";
331
- const returnUrl = "http://localhost:8100/payment/success";
332
-
333
- const routerData = {
334
- card: skyflowTokens,
335
- name: skyflowTokens.cardholder_name,
336
- last_name: "",
337
- email_client: customerEmail,
338
- phone_number: customerPhone,
339
- return_url: returnUrl,
340
- id_product: "no_id",
341
- quantity_product: 1,
342
- id_ship: "0",
343
- instance_id_ship: "0",
344
- amount: total,
345
- title_ship: "shipping",
346
- description: "Transaction from the lite SDK",
347
- device_session_id: deviceSessionIdTonder,
348
- token_id: "",
349
- order_id: jsonResponseOrder.id,
350
- business_id: business.pk,
351
- payment_id: jsonResponsePayment.pk,
352
- source: 'ionic-lite-sdk',
353
- };
354
-
355
- const jsonResponseRouter = await liteCheckout.startCheckoutRouter(
356
- routerData
357
- );
358
-
359
- ```
360
-
361
- ## Return checkout router data
362
-
363
- ```typescript
364
- {
365
- status: 200,
366
- message: "Success",
367
- psp_response: {
368
- id: string,
369
- authorization: number,
370
- operation_type: string,
371
- transaction_type: string,
372
- status: string,
373
- conciliated: boolean,
374
- creation_date: string,
375
- operation_date: string,
376
- description: string,
377
- error_message?: string,
378
- order_id?: string,
379
- card: {
380
- type: string,
381
- brand: string,
382
- address?: string,
383
- card_number: string,
384
- holder_name: string,
385
- expiration_year: string,
386
- expiration_month: string,
387
- allows_charges: boolean,
388
- allows_payouts: boolean,
389
- bank_name: string,
390
- points_type: string,
391
- points_card: boolean,
392
- bank_code: number
393
- },
394
- customer_id: string,
395
- gateway_card_present: string,
396
- amount: number,
397
- fee: {
398
- amount: number,
399
- tax: number,
400
- currency: string
401
- },
402
- payment_method: {
403
- type: string,
404
- url: string
405
- },
406
- currency: string,
407
- method: string,
408
- object: string
409
- },
410
- transaction_status: string,
411
- transaction_id: number,
412
- payment_id: number,
413
- provider: string,
414
- next_action: {
415
- redirect_to_url: {
416
- url: string,
417
- return_url: string,
418
- verify_transaction_status_url: string
419
- }
420
- },
421
- actions: [
422
- {
423
- name: string,
424
- url: string,
425
- method: string
426
- }
427
- ]
428
- }
429
- ```
430
-
431
- ## Take actions on base to the checkout router response
432
-
433
- # Customer Cards(Register)
434
-
435
- ## Register customer card
436
-
437
- ```typescript
438
-
439
- aut_token: string;
440
-
441
- data: {
442
- skyflow_id: string;
443
- };
444
-
445
- const jsonResponseOrder = await liteCheckout.registerCustomerCard(
446
- aut_token,
447
- data
448
- );
449
- ```
450
-
451
- ## Return register customer card
452
- ```typescript
453
- {
454
- skyflow_id: string;
455
- user_id: number;
456
- }
457
- ```
458
-
459
- # Customer Cards(Get)
460
-
461
- ## Get customer cards
462
-
463
- ```typescript
464
-
465
- aut_token: string;
466
-
467
- query: string = "?ordering=<string>&search=<string>";
468
-
469
- const jsonResponseOrder = await liteCheckout.getCustomerCards(
470
- aut_token,
471
- query
472
- );
473
- ```
474
-
475
- ## Return get customer cards
476
- ```typescript
477
- {
478
- user_id: number,
479
- cards: [
480
- {
481
- fields: {
482
- card_number: string,
483
- cardholder_name: string,
484
- cvv: string,
485
- expiration_month: string,
486
- expiration_year: string,
487
- skyflow_id: string
488
- }
489
- }
490
- ]
491
- }
492
- ```
493
-
494
- ## License
495
-
496
- [MIT](https://choosealicense.com/licenses/mit/)
1
+ # Tonder SDK
2
+
3
+ Tonder SDK Lite to integrate REST service
4
+
5
+ ## Installation
6
+
7
+ You can install using NPM
8
+ ```bash
9
+ npm i @tonder/ionic-lite-sdk
10
+ ```
11
+
12
+ or using an script tag
13
+ ```html
14
+ // TO DO
15
+ ```
16
+
17
+ Add dependencies to the root of the app (index.html)
18
+ ```html
19
+ <script src=https://openpay.s3.amazonaws.com/openpay.v1.min.js></script>
20
+ <script src=https://openpay.s3.amazonaws.com/openpay-data.v1.min.js></script>
21
+ ```
22
+
23
+ ## Usage
24
+ ## Import LiteCheckout class
25
+ ```javascript
26
+ import { LiteCheckout } from "@tonder/ionic-lite-sdk"
27
+ ```
28
+ ## Create instance
29
+
30
+ ```javascript
31
+ const liteCheckout = new LiteCheckout({
32
+ signal,
33
+ baseUrlTonder,
34
+ apiKeyTonder
35
+ })
36
+ ```
37
+
38
+ | Property | Type | Description |
39
+ |:---------------:|:-------------:|:-----------------------------------------------------------------------:|
40
+ | signal | AborSignal | Signal from AbortController instance if it need cancel request |
41
+ | baseUrlTonder | string | Live server: http://stage.tonder.io |
42
+ | | | Mock Server: https://stoplight.io/mocks/tonder/tonder-api-v1-2/3152148 |
43
+ | apiKeyTonder | string | You can take this from you Tonder Dashboard |
44
+ | | | |
45
+
46
+ # Class methods
47
+
48
+ # Business
49
+
50
+ ## Get business
51
+
52
+ ```javascript
53
+ const merchantData = await liteCheckout.getBusiness();
54
+ ```
55
+
56
+ ## Return business data
57
+
58
+ ```typescript
59
+ {
60
+ business: {
61
+ pk: number,
62
+ name: string,
63
+ categories: [
64
+ {
65
+ pk: number,
66
+ name: string
67
+ }
68
+ ],
69
+ web: string,
70
+ logo: string,
71
+ full_logo_url: string,
72
+ background_color: string,
73
+ primary_color: string,
74
+ checkout_mode: boolean,
75
+ textCheckoutColor: string,
76
+ textDetailsColor: string,
77
+ checkout_logo: string
78
+ },
79
+ openpay_keys: {
80
+ merchant_id: string,
81
+ public_key: string
82
+ },
83
+ fintoc_keys: {
84
+ public_key: string
85
+ },
86
+ vault_id: string,
87
+ vault_url: string,
88
+ reference: number,
89
+ is_installments_available: boolean
90
+ }
91
+ ```
92
+
93
+ # OpenPay
94
+
95
+ ## Get OpenPay session id
96
+
97
+ ```javascript
98
+ const { openpay_keys } = merchantData;
99
+
100
+ const deviceSessionIdTonder = await liteCheckout.getOpenpayDeviceSessionID(
101
+ openpay_keys.merchant_id,
102
+ openpay_keys.public_key,
103
+ is_sandbox: true
104
+ );
105
+ ```
106
+
107
+ ## Return OpenPay device session id
108
+
109
+ string
110
+
111
+ # Customer
112
+
113
+ ## Get customer authorization token
114
+
115
+ ```javascript
116
+ const customerEmail = "john.c.calhoun@examplepetstore.com";
117
+
118
+ const { auth_token } = await liteCheckout.customerRegister(customerEmail);
119
+ ```
120
+
121
+ ## Return customer data
122
+
123
+ ```typescript
124
+ {
125
+ id: number,
126
+ email: string,
127
+ auth_token: string
128
+ }
129
+ ```
130
+
131
+ # Order
132
+
133
+ ## Create order
134
+
135
+ ```typescript
136
+ const cartItems = [
137
+ {
138
+ description: "Test product description",
139
+ quantity: 1,
140
+ price_unit: 25,
141
+ discount: 0,
142
+ taxes: 12,
143
+ product_reference: 65421,
144
+ name: "Test product",
145
+ amount_total: 25
146
+ }
147
+ ]
148
+
149
+ const { reference } = merchantData;
150
+
151
+ const orderData = {
152
+ business: apiKeyTonder,
153
+ client: auth_token,
154
+ billing_address_id: null,
155
+ shipping_address_id: null,
156
+ amount: total,
157
+ status: "A",
158
+ reference: reference,
159
+ is_oneclick: true,
160
+ items: cartItems,
161
+ };
162
+
163
+ const jsonResponseOrder = await liteCheckout.createOrder(
164
+ orderData
165
+ );
166
+ ```
167
+
168
+ ## Return order data
169
+ ```typescript
170
+ {
171
+ id: number,
172
+ created: string,
173
+ amount: string,
174
+ status: string,
175
+ payment_method?: string,
176
+ reference?: string,
177
+ is_oneclick: boolean,
178
+ items: [
179
+ {
180
+ description: string,
181
+ product_reference: string,
182
+ quantity: string,
183
+ price_unit: string,
184
+ discount: string,
185
+ taxes: string,
186
+ amount_total: string
187
+ }
188
+ ],
189
+ billing_address?: string,
190
+ shipping_address?: string,
191
+ client: {
192
+ email: string,
193
+ name: string,
194
+ first_name: string,
195
+ last_name: string,
196
+ client_profile: {
197
+ gender: string,
198
+ date_birth?: string,
199
+ terms: boolean,
200
+ phone: string
201
+ }
202
+ }
203
+ }
204
+ ```
205
+
206
+ # Payment
207
+
208
+ ## Create payment
209
+ ```javascript
210
+ const now = new Date();
211
+ const dateString = now.toISOString();
212
+
213
+ const paymentData = {
214
+ business_pk: business.pk,
215
+ amount: total,
216
+ date: dateString,
217
+ order: jsonResponseOrder.id,
218
+ };
219
+
220
+ const jsonResponsePayment = await liteCheckout.createPayment(
221
+ paymentData
222
+ );
223
+ ```
224
+
225
+ ## Return payment data
226
+ ```javascript
227
+ {
228
+ pk: number,
229
+ order?: string,
230
+ amount: string,
231
+ status: string,
232
+ date: string,
233
+ paid_date?: string,
234
+ shipping_address: {
235
+ street: string,
236
+ number: string,
237
+ suburb: string,
238
+ city: {
239
+ name: string
240
+ },
241
+ state: {
242
+ name: string,
243
+ country: {
244
+ name: string
245
+ }
246
+ },
247
+ zip_code: string
248
+ },
249
+ shipping_address_id?: string,
250
+ billing_address: {
251
+ street: string,
252
+ number: string,
253
+ suburb: string,
254
+ city: {
255
+ name: string
256
+ },
257
+ state: {
258
+ name: string,
259
+ country: {
260
+ name: string
261
+ }
262
+ },
263
+ zip_code: string
264
+ },
265
+ billing_address_id?: string,
266
+ client?: string,
267
+ customer_order_reference?: string
268
+ }
269
+ ```
270
+
271
+ # Skyflow tokens
272
+
273
+ ## Get skyflow payment form tokenized values
274
+
275
+ The values of the variable skyflowTokens come from your html form
276
+
277
+ ```javascript
278
+
279
+ const skyflowFields = {
280
+ card_number: this.paymentForm.value.cardNumber,
281
+ cvv: this.paymentForm.value.cvv,
282
+ expiration_month: this.paymentForm.value.month,
283
+ expiration_year: this.paymentForm.value.expirationYear,
284
+ cardholder_name: this.paymentForm.value.name
285
+ }
286
+
287
+ const { vault_id, vault_url } = merchantData;
288
+
289
+
290
+ const skyflowTokens = await liteCheckout.getSkyflowTokens({
291
+ vault_id: vault_id,
292
+ vault_url: vault_url,
293
+ data: skyflowFields
294
+ })
295
+
296
+ ```
297
+
298
+ ## Return skyflow tokenized data
299
+ ```typescript
300
+ {
301
+ vaultID: string,
302
+ responses: [
303
+ {
304
+ records: [
305
+ {
306
+ skyflow_id: string
307
+ }
308
+ ]
309
+ },
310
+ {
311
+ fields: {
312
+ card_number: string,
313
+ cardholder_name: string,
314
+ cvv: string,
315
+ expiration_month: string,
316
+ expiration_year: string,
317
+ skyflow_id: string
318
+ }
319
+ }
320
+ ]
321
+ }
322
+ ```
323
+
324
+ # Checkout router
325
+
326
+ ## Get checkout router data
327
+
328
+ ```javascript
329
+
330
+ const customerPhone = "+11111111";
331
+ const returnUrl = "http://localhost:8100/payment/success";
332
+
333
+ const routerData = {
334
+ card: skyflowTokens,
335
+ name: skyflowTokens.cardholder_name,
336
+ last_name: "",
337
+ email_client: customerEmail,
338
+ phone_number: customerPhone,
339
+ return_url: returnUrl,
340
+ id_product: "no_id",
341
+ quantity_product: 1,
342
+ id_ship: "0",
343
+ instance_id_ship: "0",
344
+ amount: total,
345
+ title_ship: "shipping",
346
+ description: "Transaction from the lite SDK",
347
+ device_session_id: deviceSessionIdTonder,
348
+ token_id: "",
349
+ order_id: jsonResponseOrder.id,
350
+ business_id: business.pk,
351
+ payment_id: jsonResponsePayment.pk,
352
+ source: 'ionic-lite-sdk',
353
+ };
354
+
355
+ const jsonResponseRouter = await liteCheckout.startCheckoutRouter(
356
+ routerData
357
+ );
358
+
359
+ ```
360
+
361
+ ## Return checkout router data
362
+
363
+ ```typescript
364
+ {
365
+ status: 200,
366
+ message: "Success",
367
+ psp_response: {
368
+ id: string,
369
+ authorization: number,
370
+ operation_type: string,
371
+ transaction_type: string,
372
+ status: string,
373
+ conciliated: boolean,
374
+ creation_date: string,
375
+ operation_date: string,
376
+ description: string,
377
+ error_message?: string,
378
+ order_id?: string,
379
+ card: {
380
+ type: string,
381
+ brand: string,
382
+ address?: string,
383
+ card_number: string,
384
+ holder_name: string,
385
+ expiration_year: string,
386
+ expiration_month: string,
387
+ allows_charges: boolean,
388
+ allows_payouts: boolean,
389
+ bank_name: string,
390
+ points_type: string,
391
+ points_card: boolean,
392
+ bank_code: number
393
+ },
394
+ customer_id: string,
395
+ gateway_card_present: string,
396
+ amount: number,
397
+ fee: {
398
+ amount: number,
399
+ tax: number,
400
+ currency: string
401
+ },
402
+ payment_method: {
403
+ type: string,
404
+ url: string
405
+ },
406
+ currency: string,
407
+ method: string,
408
+ object: string
409
+ },
410
+ transaction_status: string,
411
+ transaction_id: number,
412
+ payment_id: number,
413
+ provider: string,
414
+ next_action: {
415
+ redirect_to_url: {
416
+ url: string,
417
+ return_url: string,
418
+ verify_transaction_status_url: string
419
+ }
420
+ },
421
+ actions: [
422
+ {
423
+ name: string,
424
+ url: string,
425
+ method: string
426
+ }
427
+ ]
428
+ }
429
+ ```
430
+
431
+ ## Take actions on base to the checkout router response
432
+
433
+ # Customer Cards(Register)
434
+
435
+ ## Register customer card
436
+
437
+ ```typescript
438
+
439
+ aut_token: string;
440
+
441
+ data: {
442
+ skyflow_id: string;
443
+ };
444
+
445
+ const jsonResponseOrder = await liteCheckout.registerCustomerCard(
446
+ aut_token,
447
+ data
448
+ );
449
+ ```
450
+
451
+ ## Return register customer card
452
+ ```typescript
453
+ {
454
+ skyflow_id: string;
455
+ user_id: number;
456
+ }
457
+ ```
458
+
459
+ # Customer Cards(Get)
460
+
461
+ ## Get customer cards
462
+
463
+ ```typescript
464
+
465
+ aut_token: string;
466
+
467
+ query: string = "?ordering=<string>&search=<string>";
468
+
469
+ const jsonResponseOrder = await liteCheckout.getCustomerCards(
470
+ aut_token,
471
+ query
472
+ );
473
+ ```
474
+
475
+ ## Return get customer cards
476
+ ```typescript
477
+ {
478
+ user_id: number,
479
+ cards: [
480
+ {
481
+ fields: {
482
+ card_number: string,
483
+ cardholder_name: string,
484
+ cvv: string,
485
+ expiration_month: string,
486
+ expiration_year: string,
487
+ skyflow_id: string
488
+ }
489
+ }
490
+ ]
491
+ }
492
+ ```
493
+
494
+ ## License
495
+
496
+ [MIT](https://choosealicense.com/licenses/mit/)