aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.eslintrc.js22
-rw-r--r--app/Controllers/Http/DashboardController.js61
-rw-r--r--app/Controllers/Http/RecipeController.js159
-rw-r--r--app/Controllers/Http/ServiceController.js200
-rw-r--r--app/Controllers/Http/StaticController.js347
-rw-r--r--app/Controllers/Http/UserController.js213
-rw-r--r--app/Controllers/Http/WorkspaceController.js104
-rw-r--r--app/Exceptions/Handler.js16
-rw-r--r--app/Middleware/ConvertEmptyStringsToNull.js15
-rw-r--r--app/Models/Recipe.js5
-rw-r--r--app/Models/Service.js11
-rw-r--r--app/Models/Token.js5
-rw-r--r--app/Models/Traits/NoTimestamp.js9
-rw-r--r--app/Models/User.js28
-rw-r--r--app/Models/Workspace.js11
-rw-r--r--config/app.js23
-rw-r--r--config/auth.js17
-rw-r--r--config/bodyParser.js21
-rw-r--r--config/cors.js5
-rw-r--r--config/database.js21
-rw-r--r--config/drive.js17
-rw-r--r--config/hash.js11
-rw-r--r--config/session.js13
-rw-r--r--config/shield.js13
-rw-r--r--database/factory.js1
-rw-r--r--database/migrations/1503250034279_user.js23
-rw-r--r--database/migrations/1503250034280_token.js25
-rw-r--r--database/migrations/1566385379883_service_schema.js27
-rw-r--r--database/migrations/1566554231482_recipe_schema.js23
-rw-r--r--database/migrations/1566554359294_workspace_schema.js29
-rw-r--r--package-lock.json1295
-rw-r--r--package.json13
-rw-r--r--public/js/new.js9
-rw-r--r--server.js8
-rw-r--r--start/app.js15
-rw-r--r--start/kernel.js13
-rw-r--r--start/routes.js116
37 files changed, 2104 insertions, 840 deletions
diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 0000000..d02f489
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,22 @@
1module.exports = {
2 env: {
3 commonjs: true,
4 es6: true,
5 node: true,
6 },
7 extends: [
8 'airbnb-base',
9 ],
10 globals: {
11 Atomics: 'readonly',
12 SharedArrayBuffer: 'readonly',
13 use: 'readonly'
14 },
15 parserOptions: {
16 ecmaVersion: 2018,
17 },
18 rules: {
19 "class-methods-use-this": 'off',
20 "no-restricted-syntax": 'off',
21 },
22};
diff --git a/app/Controllers/Http/DashboardController.js b/app/Controllers/Http/DashboardController.js
index aa8127f..49f6cc0 100644
--- a/app/Controllers/Http/DashboardController.js
+++ b/app/Controllers/Http/DashboardController.js
@@ -1,7 +1,6 @@
1'use strict'
2 1
3const { 2const {
4 validateAll 3 validateAll,
5} = use('Validator'); 4} = use('Validator');
6 5
7const crypto = require('crypto'); 6const crypto = require('crypto');
@@ -11,7 +10,7 @@ class DashboardController {
11 request, 10 request,
12 response, 11 response,
13 auth, 12 auth,
14 session 13 session,
15 }) { 14 }) {
16 const validation = await validateAll(request.all(), { 15 const validation = await validateAll(request.all(), {
17 mail: 'required|email', 16 mail: 'required|email',
@@ -20,25 +19,25 @@ class DashboardController {
20 if (validation.fails()) { 19 if (validation.fails()) {
21 session.withErrors({ 20 session.withErrors({
22 type: 'danger', 21 type: 'danger',
23 message: 'Invalid mail or password' 22 message: 'Invalid mail or password',
24 }).flashExcept(['password']); 23 }).flashExcept(['password']);
25 return response.redirect('back'); 24 return response.redirect('back');
26 } 25 }
27 26
28 let { 27 const {
29 mail, 28 mail,
30 password 29 password,
31 } = request.all() 30 } = request.all();
32 31
33 const hashedPassword = crypto.createHash('sha256').update(password).digest('base64'); 32 const hashedPassword = crypto.createHash('sha256').update(password).digest('base64');
34 33
35 try { 34 try {
36 await auth.authenticator('session').attempt(mail, hashedPassword) 35 await auth.authenticator('session').attempt(mail, hashedPassword);
37 } catch (error) { 36 } catch (error) {
38 session.flash({ 37 session.flash({
39 type: 'danger', 38 type: 'danger',
40 message: 'Invalid mail or password' 39 message: 'Invalid mail or password',
41 }) 40 });
42 return response.redirect('back'); 41 return response.redirect('back');
43 } 42 }
44 return response.redirect('/user/account'); 43 return response.redirect('/user/account');
@@ -46,17 +45,18 @@ class DashboardController {
46 45
47 async account({ 46 async account({
48 auth, 47 auth,
49 view 48 view,
49 response,
50 }) { 50 }) {
51 try { 51 try {
52 await auth.check() 52 await auth.check();
53 } catch (error) { 53 } catch (error) {
54 return response.redirect('/user/login'); 54 return response.redirect('/user/login');
55 } 55 }
56 56
57 return view.render('dashboard.account', { 57 return view.render('dashboard.account', {
58 username: auth.user.username, 58 username: auth.user.username,
59 email: auth.user.email 59 email: auth.user.email,
60 }); 60 });
61 } 61 }
62 62
@@ -65,11 +65,11 @@ class DashboardController {
65 request, 65 request,
66 session, 66 session,
67 view, 67 view,
68 response 68 response,
69 }) { 69 }) {
70 let validation = await validateAll(request.all(), { 70 let validation = await validateAll(request.all(), {
71 username: 'required', 71 username: 'required',
72 email: 'required' 72 email: 'required',
73 }); 73 });
74 if (validation.fails()) { 74 if (validation.fails()) {
75 session.withErrors(validation.messages()).flashExcept(['password']); 75 session.withErrors(validation.messages()).flashExcept(['password']);
@@ -80,19 +80,19 @@ class DashboardController {
80 if (request.input('username') !== auth.user.username) { 80 if (request.input('username') !== auth.user.username) {
81 validation = await validateAll(request.all(), { 81 validation = await validateAll(request.all(), {
82 username: 'required|unique:users,username', 82 username: 'required|unique:users,username',
83 email: 'required' 83 email: 'required',
84 }); 84 });
85 if (validation.fails()) { 85 if (validation.fails()) {
86 session.withErrors(validation.messages()).flashExcept(['password']); 86 session.withErrors(validation.messages()).flashExcept(['password']);
87 return response.redirect('back'); 87 return response.redirect('back');
88 } 88 }
89 } 89 }
90 90
91 // Check new email 91 // Check new email
92 if (request.input('email') !== auth.user.email) { 92 if (request.input('email') !== auth.user.email) {
93 validation = await validateAll(request.all(), { 93 validation = await validateAll(request.all(), {
94 username: 'required', 94 username: 'required',
95 email: 'required|email|unique:users,email' 95 email: 'required|email|unique:users,email',
96 }); 96 });
97 if (validation.fails()) { 97 if (validation.fails()) {
98 session.withErrors(validation.messages()).flashExcept(['password']); 98 session.withErrors(validation.messages()).flashExcept(['password']);
@@ -101,24 +101,25 @@ class DashboardController {
101 } 101 }
102 102
103 // Update user account 103 // Update user account
104 auth.user.username = request.input('username'); 104 const { user } = auth;
105 auth.user.email = request.input('email'); 105 user.username = request.input('username');
106 if (!!request.input('password')) { 106 user.email = request.input('email');
107 if (request.input('password')) {
107 const hashedPassword = crypto.createHash('sha256').update(request.input('password')).digest('base64'); 108 const hashedPassword = crypto.createHash('sha256').update(request.input('password')).digest('base64');
108 auth.user.password = hashedPassword; 109 user.password = hashedPassword;
109 } 110 }
110 auth.user.save(); 111 user.save();
111 112
112 return view.render('dashboard.account', { 113 return view.render('dashboard.account', {
113 username: auth.user.username, 114 username: user.username,
114 email: auth.user.email, 115 email: user.email,
115 success: true 116 success: true,
116 }); 117 });
117 } 118 }
118 119
119 async data({ 120 async data({
120 auth, 121 auth,
121 view 122 view,
122 }) { 123 }) {
123 const general = auth.user; 124 const general = auth.user;
124 const services = (await auth.user.services().fetch()).toJSON(); 125 const services = (await auth.user.services().fetch()).toJSON();
@@ -136,7 +137,7 @@ class DashboardController {
136 137
137 logout({ 138 logout({
138 auth, 139 auth,
139 response 140 response,
140 }) { 141 }) {
141 auth.authenticator('session').logout(); 142 auth.authenticator('session').logout();
142 return response.redirect('/user/login'); 143 return response.redirect('/user/login');
@@ -144,7 +145,7 @@ class DashboardController {
144 145
145 delete({ 146 delete({
146 auth, 147 auth,
147 response 148 response,
148 }) { 149 }) {
149 auth.user.delete(); 150 auth.user.delete();
150 auth.authenticator('session').logout(); 151 auth.authenticator('session').logout();
@@ -152,4 +153,4 @@ class DashboardController {
152 } 153 }
153} 154}
154 155
155module.exports = DashboardController 156module.exports = DashboardController;
diff --git a/app/Controllers/Http/RecipeController.js b/app/Controllers/Http/RecipeController.js
index fd9ed83..217b05b 100644
--- a/app/Controllers/Http/RecipeController.js
+++ b/app/Controllers/Http/RecipeController.js
@@ -1,61 +1,58 @@
1'use strict'
2 1
3const Recipe = use('App/Models/Recipe'); 2const Recipe = use('App/Models/Recipe');
4const Helpers = use('Helpers') 3const Helpers = use('Helpers');
5const Drive = use('Drive') 4const Drive = use('Drive');
6const { 5const {
7 validateAll 6 validateAll,
8} = use('Validator'); 7} = use('Validator');
9const Env = use('Env') 8const Env = use('Env');
10 9
11const fetch = require('node-fetch'); 10const fetch = require('node-fetch');
12const targz = require('targz'); 11const targz = require('targz');
13const path = require('path'); 12const path = require('path');
14const fs = require('fs-extra'); 13const fs = require('fs-extra');
15 14
16const compress = (src, dest) => { 15const compress = (src, dest) => new Promise((resolve, reject) => {
17 return new Promise((resolve, reject) => { 16 targz.compress({
18 targz.compress({ 17 src,
19 src, 18 dest,
20 dest 19 }, (err) => {
21 }, function (err) { 20 if (err) {
22 if (err) { 21 reject(err);
23 reject(err); 22 } else {
24 } else { 23 resolve(dest);
25 resolve(dest); 24 }
26 } 25 });
27 }); 26});
28 })
29}
30 27
31class RecipeController { 28class RecipeController {
32 // List official and custom recipes 29 // List official and custom recipes
33 async list({ 30 async list({
34 response 31 response,
35 }) { 32 }) {
36 const officialRecipes = JSON.parse(await (await fetch('https://api.franzinfra.com/v1/recipes')).text()); 33 const officialRecipes = JSON.parse(await (await fetch('https://api.franzinfra.com/v1/recipes')).text());
37 const customRecipesArray = (await Recipe.all()).rows; 34 const customRecipesArray = (await Recipe.all()).rows;
38 const customRecipes = customRecipesArray.map(recipe => ({ 35 const customRecipes = customRecipesArray.map((recipe) => ({
39 "id": recipe.recipeId, 36 id: recipe.recipeId,
40 "name": recipe.name, 37 name: recipe.name,
41 ...JSON.parse(recipe.data) 38 ...JSON.parse(recipe.data),
42 })) 39 }));
43 40
44 const recipes = [ 41 const recipes = [
45 ...officialRecipes, 42 ...officialRecipes,
46 ...customRecipes, 43 ...customRecipes,
47 ] 44 ];
48 45
49 return response.send(recipes) 46 return response.send(recipes);
50 } 47 }
51 48
52 // Create a new recipe using the new.html page 49 // Create a new recipe using the new.html page
53 async create({ 50 async create({
54 request, 51 request,
55 response 52 response,
56 }) { 53 }) {
57 // Check if recipe creation is enabled 54 // Check if recipe creation is enabled
58 if (Env.get('IS_CREATION_ENABLED') == 'false') { 55 if (Env.get('IS_CREATION_ENABLED') == 'false') { // eslint-disable-line eqeqeq
59 return response.send('This server doesn\'t allow the creation of new recipes.'); 56 return response.send('This server doesn\'t allow the creation of new recipes.');
60 } 57 }
61 58
@@ -69,10 +66,10 @@ class RecipeController {
69 }); 66 });
70 if (validation.fails()) { 67 if (validation.fails()) {
71 return response.status(401).send({ 68 return response.status(401).send({
72 "message": "Invalid POST arguments", 69 message: 'Invalid POST arguments',
73 "messages": validation.messages(), 70 messages: validation.messages(),
74 "status": 401 71 status: 401,
75 }) 72 });
76 } 73 }
77 74
78 const data = request.all(); 75 const data = request.all();
@@ -90,16 +87,16 @@ class RecipeController {
90 await fs.emptyDir(Helpers.tmpPath('recipe')); 87 await fs.emptyDir(Helpers.tmpPath('recipe'));
91 88
92 // Move uploaded files to temporary path 89 // Move uploaded files to temporary path
93 const files = request.file('files') 90 const files = request.file('files');
94 await files.moveAll(Helpers.tmpPath('recipe')) 91 await files.moveAll(Helpers.tmpPath('recipe'));
95 92
96 // Compress files to .tar.gz file 93 // Compress files to .tar.gz file
97 const source = Helpers.tmpPath('recipe'); 94 const source = Helpers.tmpPath('recipe');
98 const destination = path.join(Helpers.appRoot(), '/recipes/' + data.id + '.tar.gz'); 95 const destination = path.join(Helpers.appRoot(), `/recipes/${data.id}.tar.gz`);
99 96
100 compress( 97 compress(
101 source, 98 source,
102 destination 99 destination,
103 ); 100 );
104 101
105 // Create recipe in db 102 // Create recipe in db
@@ -107,74 +104,73 @@ class RecipeController {
107 name: data.name, 104 name: data.name,
108 recipeId: data.id, 105 recipeId: data.id,
109 data: JSON.stringify({ 106 data: JSON.stringify({
110 "author": data.author, 107 author: data.author,
111 "featured": false, 108 featured: false,
112 "version": "1.0.0", 109 version: '1.0.0',
113 "icons": { 110 icons: {
114 "png": data.png, 111 png: data.png,
115 "svg": data.svg 112 svg: data.svg,
116 } 113 },
117 }) 114 }),
118 }) 115 });
119 116
120 return response.send('Created new recipe') 117 return response.send('Created new recipe');
121 } 118 }
122 119
123 // Search official and custom recipes 120 // Search official and custom recipes
124 async search({ 121 async search({
125 request, 122 request,
126 response 123 response,
127 }) { 124 }) {
128 // Validate user input 125 // Validate user input
129 const validation = await validateAll(request.all(), { 126 const validation = await validateAll(request.all(), {
130 needle: 'required' 127 needle: 'required',
131 }); 128 });
132 if (validation.fails()) { 129 if (validation.fails()) {
133 return response.status(401).send({ 130 return response.status(401).send({
134 "message": "Please provide a needle", 131 message: 'Please provide a needle',
135 "messages": validation.messages(), 132 messages: validation.messages(),
136 "status": 401 133 status: 401,
137 }) 134 });
138 } 135 }
139 136
140 const needle = request.input('needle') 137 const needle = request.input('needle');
141 138
142 // Get results 139 // Get results
143 let remoteResults = []; 140 let remoteResults = [];
144 if (Env.get('CONNECT_WITH_FRANZ') == 'true') { 141 if (Env.get('CONNECT_WITH_FRANZ') == 'true') { // eslint-disable-line eqeqeq
145 remoteResults = JSON.parse(await (await fetch('https://api.franzinfra.com/v1/recipes/search?needle=' + encodeURIComponent(needle))).text()); 142 remoteResults = JSON.parse(await (await fetch(`https://api.franzinfra.com/v1/recipes/search?needle=${encodeURIComponent(needle)}`)).text());
146 } 143 }
147 const localResultsArray = (await Recipe.query().where('name', 'LIKE', '%' + needle + '%').fetch()).toJSON(); 144 const localResultsArray = (await Recipe.query().where('name', 'LIKE', `%${needle}%`).fetch()).toJSON();
148 const localResults = localResultsArray.map(recipe => ({ 145 const localResults = localResultsArray.map((recipe) => ({
149 "id": recipe.recipeId, 146 id: recipe.recipeId,
150 "name": recipe.name, 147 name: recipe.name,
151 ...JSON.parse(recipe.data) 148 ...JSON.parse(recipe.data),
152 })) 149 }));
153 150
154 const results = [ 151 const results = [
155 ...localResults, 152 ...localResults,
156 ...remoteResults, 153 ...remoteResults,
157 ] 154 ];
158 155
159 return response.send(results); 156 return response.send(results);
160 } 157 }
161 158
162 // Download a recipe 159 // Download a recipe
163 async download({ 160 async download({
164 request,
165 response, 161 response,
166 params 162 params,
167 }) { 163 }) {
168 // Validate user input 164 // Validate user input
169 const validation = await validateAll(params, { 165 const validation = await validateAll(params, {
170 recipe: 'required|accepted' 166 recipe: 'required|accepted',
171 }); 167 });
172 if (validation.fails()) { 168 if (validation.fails()) {
173 return response.status(401).send({ 169 return response.status(401).send({
174 "message": "Please provide a recipe ID", 170 message: 'Please provide a recipe ID',
175 "messages": validation.messages(), 171 messages: validation.messages(),
176 "status": 401 172 status: 401,
177 }) 173 });
178 } 174 }
179 175
180 const service = params.recipe; 176 const service = params.recipe;
@@ -185,17 +181,16 @@ class RecipeController {
185 } 181 }
186 182
187 // Check if recipe exists in recipes folder 183 // Check if recipe exists in recipes folder
188 if (await Drive.exists(service + '.tar.gz')) { 184 if (await Drive.exists(`${service}.tar.gz`)) {
189 response.send(await Drive.get(service + '.tar.gz')) 185 response.send(await Drive.get(`${service}.tar.gz`));
190 } else if(Env.get('CONNECT_WITH_FRANZ') == 'true') { 186 } else if (Env.get('CONNECT_WITH_FRANZ') == 'true') { // eslint-disable-line eqeqeq
191 response.redirect('https://api.franzinfra.com/v1/recipes/download/' + service) 187 response.redirect(`https://api.franzinfra.com/v1/recipes/download/${service}`);
192 } else {
193 return response.status(400).send({
194 "message": "Recipe not found",
195 "code": "recipe-not-found"
196 })
197 } 188 }
189 return response.status(400).send({
190 message: 'Recipe not found',
191 code: 'recipe-not-found',
192 });
198 } 193 }
199} 194}
200 195
201module.exports = RecipeController 196module.exports = RecipeController;
diff --git a/app/Controllers/Http/ServiceController.js b/app/Controllers/Http/ServiceController.js
index e887e3a..309ae09 100644
--- a/app/Controllers/Http/ServiceController.js
+++ b/app/Controllers/Http/ServiceController.js
@@ -1,9 +1,6 @@
1'use strict'
2
3const User = use('App/Models/User');
4const Service = use('App/Models/Service'); 1const Service = use('App/Models/Service');
5const { 2const {
6 validateAll 3 validateAll,
7} = use('Validator'); 4} = use('Validator');
8 5
9const uuid = require('uuid/v4'); 6const uuid = require('uuid/v4');
@@ -13,12 +10,12 @@ class ServiceController {
13 async create({ 10 async create({
14 request, 11 request,
15 response, 12 response,
16 auth 13 auth,
17 }) { 14 }) {
18 try { 15 try {
19 await auth.getUser() 16 await auth.getUser();
20 } catch (error) { 17 } catch (error) {
21 return response.send('Missing or invalid api token') 18 return response.send('Missing or invalid api token');
22 } 19 }
23 20
24 // Validate user input 21 // Validate user input
@@ -28,10 +25,10 @@ class ServiceController {
28 }); 25 });
29 if (validation.fails()) { 26 if (validation.fails()) {
30 return response.status(401).send({ 27 return response.status(401).send({
31 "message": "Invalid POST arguments", 28 message: 'Invalid POST arguments',
32 "messages": validation.messages(), 29 messages: validation.messages(),
33 "status": 401 30 status: 401,
34 }) 31 });
35 } 32 }
36 33
37 const data = request.all(); 34 const data = request.all();
@@ -40,83 +37,82 @@ class ServiceController {
40 let serviceId; 37 let serviceId;
41 do { 38 do {
42 serviceId = uuid(); 39 serviceId = uuid();
43 } while ((await Service.query().where('serviceId', serviceId).fetch()).rows.length > 0) 40 } while ((await Service.query().where('serviceId', serviceId).fetch()).rows.length > 0); // eslint-disable-line no-await-in-loop
44 41
45 const service = await Service.create({ 42 await Service.create({
46 userId: auth.user.id, 43 userId: auth.user.id,
47 serviceId, 44 serviceId,
48 name: data.name, 45 name: data.name,
49 recipeId: data.recipeId, 46 recipeId: data.recipeId,
50 settings: JSON.stringify(data) 47 settings: JSON.stringify(data),
51 }); 48 });
52 49
53 return response.send({ 50 return response.send({
54 "data": { 51 data: {
55 userId: auth.user.id, 52 userId: auth.user.id,
56 id: serviceId, 53 id: serviceId,
57 "isEnabled": true, 54 isEnabled: true,
58 "isNotificationEnabled": true, 55 isNotificationEnabled: true,
59 "isBadgeEnabled": true, 56 isBadgeEnabled: true,
60 "isMuted": false, 57 isMuted: false,
61 "isDarkModeEnabled": "", 58 isDarkModeEnabled: '',
62 "spellcheckerLanguage": "", 59 spellcheckerLanguage: '',
63 "order": 1, 60 order: 1,
64 "customRecipe": false, 61 customRecipe: false,
65 "hasCustomIcon": false, 62 hasCustomIcon: false,
66 "workspaces": [], 63 workspaces: [],
67 "iconUrl": null, 64 iconUrl: null,
68 ...data, 65 ...data,
69 }, 66 },
70 "status": ["created"] 67 status: ['created'],
71 }) 68 });
72 } 69 }
73 70
74 // List all services a user has created 71 // List all services a user has created
75 async list({ 72 async list({
76 request,
77 response, 73 response,
78 auth 74 auth,
79 }) { 75 }) {
80 try { 76 try {
81 await auth.getUser() 77 await auth.getUser();
82 } catch (error) { 78 } catch (error) {
83 return response.send('Missing or invalid api token') 79 return response.send('Missing or invalid api token');
84 } 80 }
85 81
86 const services = (await auth.user.services().fetch()).rows; 82 const services = (await auth.user.services().fetch()).rows;
87 // Convert to array with all data Franz wants 83 // Convert to array with all data Franz wants
88 const servicesArray = services.map(service => ({ 84 const servicesArray = services.map((service) => ({
89 "customRecipe": false, 85 customRecipe: false,
90 "hasCustomIcon": false, 86 hasCustomIcon: false,
91 "isBadgeEnabled": true, 87 isBadgeEnabled: true,
92 "isDarkModeEnabled": "", 88 isDarkModeEnabled: '',
93 "isEnabled": true, 89 isEnabled: true,
94 "isMuted": false, 90 isMuted: false,
95 "isNotificationEnabled": true, 91 isNotificationEnabled: true,
96 "order": 1, 92 order: 1,
97 "spellcheckerLanguage": "", 93 spellcheckerLanguage: '',
98 "workspaces": [], 94 workspaces: [],
99 "iconUrl": null, 95 iconUrl: null,
100 ...JSON.parse(service.settings), 96 ...JSON.parse(service.settings),
101 "id": service.serviceId, 97 id: service.serviceId,
102 "name": service.name, 98 name: service.name,
103 "recipeId": service.recipeId, 99 recipeId: service.recipeId,
104 "userId": auth.user.id, 100 userId: auth.user.id,
105 })) 101 }));
106 102
107 return response.send(servicesArray) 103 return response.send(servicesArray);
108 } 104 }
109 105
110 async edit({ 106 async edit({
111 request, 107 request,
112 response, 108 response,
113 auth, 109 auth,
114 params 110 params,
115 }) { 111 }) {
116 try { 112 try {
117 await auth.getUser() 113 await auth.getUser();
118 } catch (error) { 114 } catch (error) {
119 return response.send('Missing or invalid api token') 115 return response.send('Missing or invalid api token');
120 } 116 }
121 117
122 // Validate user input 118 // Validate user input
@@ -125,15 +121,15 @@ class ServiceController {
125 }); 121 });
126 if (validation.fails()) { 122 if (validation.fails()) {
127 return response.status(401).send({ 123 return response.status(401).send({
128 "message": "Invalid POST arguments", 124 message: 'Invalid POST arguments',
129 "messages": validation.messages(), 125 messages: validation.messages(),
130 "status": 401 126 status: 401,
131 }) 127 });
132 } 128 }
133 129
134 const data = request.all(); 130 const data = request.all();
135 const { 131 const {
136 id 132 id,
137 } = params; 133 } = params;
138 134
139 // Get current settings from db 135 // Get current settings from db
@@ -141,7 +137,7 @@ class ServiceController {
141 .where('serviceId', id) 137 .where('serviceId', id)
142 .where('userId', auth.user.id).fetch()).rows[0]; 138 .where('userId', auth.user.id).fetch()).rows[0];
143 139
144 let settings = { 140 const settings = {
145 ...JSON.parse(serviceData.settings), 141 ...JSON.parse(serviceData.settings),
146 ...data, 142 ...data,
147 }; 143 };
@@ -150,9 +146,9 @@ class ServiceController {
150 await (Service.query() 146 await (Service.query()
151 .where('serviceId', id) 147 .where('serviceId', id)
152 .where('userId', auth.user.id)).update({ 148 .where('userId', auth.user.id)).update({
153 name: data.name, 149 name: data.name,
154 settings: JSON.stringify(settings) 150 settings: JSON.stringify(settings),
155 }); 151 });
156 152
157 // Get updated row 153 // Get updated row
158 const service = (await Service.query() 154 const service = (await Service.query()
@@ -160,88 +156,86 @@ class ServiceController {
160 .where('userId', auth.user.id).fetch()).rows[0]; 156 .where('userId', auth.user.id).fetch()).rows[0];
161 157
162 return response.send({ 158 return response.send({
163 "id": service.serviceId, 159 id: service.serviceId,
164 "name": data.name, 160 name: data.name,
165 ...settings, 161 ...settings,
166 "userId": auth.user.id 162 userId: auth.user.id,
167 }) 163 });
168 } 164 }
169 165
170 async reorder({ 166 async reorder({
171 request, 167 request,
172 response, 168 response,
173 auth 169 auth,
174 }) { 170 }) {
175 const data = request.all(); 171 const data = request.all();
176 172
177 for (const service in data) { 173 for (const service of Object.keys(data)) {
178 // Get current settings from db 174 // Get current settings from db
179 const serviceData = (await Service.query() 175 const serviceData = (await Service.query() // eslint-disable-line no-await-in-loop
180 .where('serviceId', service) 176 .where('serviceId', service)
181 .where('userId', auth.user.id).fetch()).rows[0]; 177 .where('userId', auth.user.id).fetch()).rows[0];
182 178
183 let settings = { 179 const settings = {
184 ...JSON.parse(serviceData.settings), 180 ...JSON.parse(serviceData.settings),
185 order: data[service] 181 order: data[service],
186 }; 182 };
187 183
188 // Update data in database 184 // Update data in database
189 await (Service.query() 185 await (Service.query() // eslint-disable-line no-await-in-loop
190 .where('serviceId', service) 186 .where('serviceId', service)
191 .where('userId', auth.user.id)) 187 .where('userId', auth.user.id))
192 .update({ 188 .update({
193 settings: JSON.stringify(settings) 189 settings: JSON.stringify(settings),
194 }); 190 });
195 } 191 }
196 192
197 // Get new services 193 // Get new services
198 const services = (await auth.user.services().fetch()).rows; 194 const services = (await auth.user.services().fetch()).rows;
199 // Convert to array with all data Franz wants 195 // Convert to array with all data Franz wants
200 const servicesArray = services.map(service => ({ 196 const servicesArray = services.map((service) => ({
201 "customRecipe": false, 197 customRecipe: false,
202 "hasCustomIcon": false, 198 hasCustomIcon: false,
203 "isBadgeEnabled": true, 199 isBadgeEnabled: true,
204 "isDarkModeEnabled": "", 200 isDarkModeEnabled: '',
205 "isEnabled": true, 201 isEnabled: true,
206 "isMuted": false, 202 isMuted: false,
207 "isNotificationEnabled": true, 203 isNotificationEnabled: true,
208 "order": 1, 204 order: 1,
209 "spellcheckerLanguage": "", 205 spellcheckerLanguage: '',
210 "workspaces": [], 206 workspaces: [],
211 "iconUrl": null, 207 iconUrl: null,
212 ...JSON.parse(service.settings), 208 ...JSON.parse(service.settings),
213 "id": service.serviceId, 209 id: service.serviceId,
214 "name": service.name, 210 name: service.name,
215 "recipeId": service.recipeId, 211 recipeId: service.recipeId,
216 "userId": auth.user.id, 212 userId: auth.user.id,
217 })) 213 }));
218 214
219 return response.send(servicesArray) 215 return response.send(servicesArray);
220 } 216 }
221 217
222 update({ 218 update({
223 request, 219 response,
224 response
225 }) { 220 }) {
226 return response.send([]) 221 return response.send([]);
227 } 222 }
228 223
229 async delete({ 224 async delete({
230 request,
231 params, 225 params,
232 auth, 226 auth,
233 response 227 response,
234 }) { 228 }) {
235 // Update data in database 229 // Update data in database
236 await (Service.query() 230 await (Service.query()
237 .where('serviceId', params.id) 231 .where('serviceId', params.id)
238 .where('userId', auth.user.id)).delete() 232 .where('userId', auth.user.id)).delete();
239 233
240 return response.send({ 234 return response.send({
241 "message": "Sucessfully deleted service", 235 message: 'Sucessfully deleted service',
242 "status": 200 236 status: 200,
243 }) 237 });
244 } 238 }
245} 239}
246 240
247module.exports = ServiceController 241module.exports = ServiceController;
diff --git a/app/Controllers/Http/StaticController.js b/app/Controllers/Http/StaticController.js
index 17b641f..b16e6cb 100644
--- a/app/Controllers/Http/StaticController.js
+++ b/app/Controllers/Http/StaticController.js
@@ -1,4 +1,4 @@
1'use strict' 1
2/** 2/**
3 * Controller for routes with static responses 3 * Controller for routes with static responses
4 */ 4 */
@@ -6,220 +6,219 @@
6class StaticController { 6class StaticController {
7 // Enable all features 7 // Enable all features
8 features({ 8 features({
9 response 9 response,
10 }) { 10 }) {
11 return response.send({ 11 return response.send({
12 "needToWaitToProceed": false, 12 needToWaitToProceed: false,
13 "isSpellcheckerPremiumFeature": true, 13 isSpellcheckerPremiumFeature: true,
14 "isServiceProxyEnabled": true, 14 isServiceProxyEnabled: true,
15 "isServiceProxyPremiumFeature": true, 15 isServiceProxyPremiumFeature: true,
16 "isWorkspacePremiumFeature": true, 16 isWorkspacePremiumFeature: true,
17 "isWorkspaceEnabled": true, 17 isWorkspaceEnabled: true,
18 "isAnnouncementsEnabled": true, 18 isAnnouncementsEnabled: true,
19 "isSettingsWSEnabled": false, 19 isSettingsWSEnabled: false,
20 "isServiceLimitEnabled": false, 20 isServiceLimitEnabled: false,
21 "serviceLimitCount": 0, 21 serviceLimitCount: 0,
22 "isCommunityRecipesPremiumFeature": false 22 isCommunityRecipesPremiumFeature: false,
23 }) 23 });
24 } 24 }
25 25
26 // Return an empty array 26 // Return an empty array
27 emptyArray({ 27 emptyArray({
28 response 28 response,
29 }) { 29 }) {
30 return response.send([]) 30 return response.send([]);
31 } 31 }
32 32
33 // Payment plans availible 33 // Payment plans availible
34 plans({ 34 plans({
35 response 35 response,
36 }) { 36 }) {
37 return response.send({ 37 return response.send({
38 "month": { 38 month: {
39 "id": "franz-supporter-license", 39 id: 'franz-supporter-license',
40 "price": 99 40 price: 99,
41 }, 41 },
42 "year": { 42 year: {
43 "id": "franz-supporter-license-year-2019", 43 id: 'franz-supporter-license-year-2019',
44 "price": 99 44 price: 99,
45 } 45 },
46 }) 46 });
47 } 47 }
48 48
49 // Return list of popular recipes (copy of the response Franz's API is returning) 49 // Return list of popular recipes (copy of the response Franz's API is returning)
50 popularRecipes({ 50 popularRecipes({
51 response 51 response,
52 }) { 52 }) {
53 return response.send([{ 53 return response.send([{
54 "author": "Stefan Malzner <stefan@adlk.io>", 54 author: 'Stefan Malzner <stefan@adlk.io>',
55 "featured": false, 55 featured: false,
56 "id": "slack", 56 id: 'slack',
57 "name": "Slack", 57 name: 'Slack',
58 "version": "1.0.4", 58 version: '1.0.4',
59 "icons": { 59 icons: {
60 "png": "https://cdn.franzinfra.com/recipes/dist/slack/src/icon.png", 60 png: 'https://cdn.franzinfra.com/recipes/dist/slack/src/icon.png',
61 "svg": "https://cdn.franzinfra.com/recipes/dist/slack/src/icon.svg" 61 svg: 'https://cdn.franzinfra.com/recipes/dist/slack/src/icon.svg',
62 } 62 },
63 }, { 63 }, {
64 "author": "Stefan Malzner <stefan@adlk.io>", 64 author: 'Stefan Malzner <stefan@adlk.io>',
65 "featured": false, 65 featured: false,
66 "id": "whatsapp", 66 id: 'whatsapp',
67 "name": "WhatsApp", 67 name: 'WhatsApp',
68 "version": "1.0.1", 68 version: '1.0.1',
69 "icons": { 69 icons: {
70 "png": "https://cdn.franzinfra.com/recipes/dist/whatsapp/src/icon.png", 70 png: 'https://cdn.franzinfra.com/recipes/dist/whatsapp/src/icon.png',
71 "svg": "https://cdn.franzinfra.com/recipes/dist/whatsapp/src/icon.svg" 71 svg: 'https://cdn.franzinfra.com/recipes/dist/whatsapp/src/icon.svg',
72 } 72 },
73 }, { 73 }, {
74 "author": "Stefan Malzner <stefan@adlk.io>", 74 author: 'Stefan Malzner <stefan@adlk.io>',
75 "featured": false, 75 featured: false,
76 "id": "messenger", 76 id: 'messenger',
77 "name": "Messenger", 77 name: 'Messenger',
78 "version": "1.0.6", 78 version: '1.0.6',
79 "icons": { 79 icons: {
80 "png": "https://cdn.franzinfra.com/recipes/dist/messenger/src/icon.png", 80 png: 'https://cdn.franzinfra.com/recipes/dist/messenger/src/icon.png',
81 "svg": "https://cdn.franzinfra.com/recipes/dist/messenger/src/icon.svg" 81 svg: 'https://cdn.franzinfra.com/recipes/dist/messenger/src/icon.svg',
82 } 82 },
83 }, { 83 }, {
84 "author": "Stefan Malzner <stefan@adlk.io>", 84 author: 'Stefan Malzner <stefan@adlk.io>',
85 "featured": false, 85 featured: false,
86 "id": "telegram", 86 id: 'telegram',
87 "name": "Telegram", 87 name: 'Telegram',
88 "version": "1.0.0", 88 version: '1.0.0',
89 "icons": { 89 icons: {
90 "png": "https://cdn.franzinfra.com/recipes/dist/telegram/src/icon.png", 90 png: 'https://cdn.franzinfra.com/recipes/dist/telegram/src/icon.png',
91 "svg": "https://cdn.franzinfra.com/recipes/dist/telegram/src/icon.svg" 91 svg: 'https://cdn.franzinfra.com/recipes/dist/telegram/src/icon.svg',
92 } 92 },
93 }, { 93 }, {
94 "author": "Stefan Malzner <stefan@adlk.io>", 94 author: 'Stefan Malzner <stefan@adlk.io>',
95 "featured": false, 95 featured: false,
96 "id": "gmail", 96 id: 'gmail',
97 "name": "Gmail", 97 name: 'Gmail',
98 "version": "1.0.0", 98 version: '1.0.0',
99 "icons": { 99 icons: {
100 "png": "https://cdn.franzinfra.com/recipes/dist/gmail/src/icon.png", 100 png: 'https://cdn.franzinfra.com/recipes/dist/gmail/src/icon.png',
101 "svg": "https://cdn.franzinfra.com/recipes/dist/gmail/src/icon.svg" 101 svg: 'https://cdn.franzinfra.com/recipes/dist/gmail/src/icon.svg',
102 } 102 },
103 }, { 103 }, {
104 "author": "Stefan Malzner <stefan@adlk.io>", 104 author: 'Stefan Malzner <stefan@adlk.io>',
105 "featured": false, 105 featured: false,
106 "id": "skype", 106 id: 'skype',
107 "name": "Skype", 107 name: 'Skype',
108 "version": "1.0.0", 108 version: '1.0.0',
109 "icons": { 109 icons: {
110 "png": "https://cdn.franzinfra.com/recipes/dist/skype/src/icon.png", 110 png: 'https://cdn.franzinfra.com/recipes/dist/skype/src/icon.png',
111 "svg": "https://cdn.franzinfra.com/recipes/dist/skype/src/icon.svg" 111 svg: 'https://cdn.franzinfra.com/recipes/dist/skype/src/icon.svg',
112 } 112 },
113 }, { 113 }, {
114 "author": "Stefan Malzner <stefan@adlk.io>", 114 author: 'Stefan Malzner <stefan@adlk.io>',
115 "featured": false, 115 featured: false,
116 "id": "hangouts", 116 id: 'hangouts',
117 "name": "Hangouts", 117 name: 'Hangouts',
118 "version": "1.0.0", 118 version: '1.0.0',
119 "icons": { 119 icons: {
120 "png": "https://cdn.franzinfra.com/recipes/dist/hangouts/src/icon.png", 120 png: 'https://cdn.franzinfra.com/recipes/dist/hangouts/src/icon.png',
121 "svg": "https://cdn.franzinfra.com/recipes/dist/hangouts/src/icon.svg" 121 svg: 'https://cdn.franzinfra.com/recipes/dist/hangouts/src/icon.svg',
122 } 122 },
123 }, { 123 }, {
124 "author": "Stefan Malzner <stefan@adlk.io>", 124 author: 'Stefan Malzner <stefan@adlk.io>',
125 "featured": false, 125 featured: false,
126 "id": "discord", 126 id: 'discord',
127 "name": "Discord", 127 name: 'Discord',
128 "version": "1.0.0", 128 version: '1.0.0',
129 "icons": { 129 icons: {
130 "png": "https://cdn.franzinfra.com/recipes/dist/discord/src/icon.png", 130 png: 'https://cdn.franzinfra.com/recipes/dist/discord/src/icon.png',
131 "svg": "https://cdn.franzinfra.com/recipes/dist/discord/src/icon.svg" 131 svg: 'https://cdn.franzinfra.com/recipes/dist/discord/src/icon.svg',
132 } 132 },
133 }, { 133 }, {
134 "author": "Stefan Malzner <stefan@adlk.io>", 134 author: 'Stefan Malzner <stefan@adlk.io>',
135 "featured": false, 135 featured: false,
136 "id": "tweetdeck", 136 id: 'tweetdeck',
137 "name": "Tweetdeck", 137 name: 'Tweetdeck',
138 "version": "1.0.1", 138 version: '1.0.1',
139 "icons": { 139 icons: {
140 "png": "https://cdn.franzinfra.com/recipes/dist/tweetdeck/src/icon.png", 140 png: 'https://cdn.franzinfra.com/recipes/dist/tweetdeck/src/icon.png',
141 "svg": "https://cdn.franzinfra.com/recipes/dist/tweetdeck/src/icon.svg" 141 svg: 'https://cdn.franzinfra.com/recipes/dist/tweetdeck/src/icon.svg',
142 } 142 },
143 }, { 143 }, {
144 "author": "Stefan Malzner <stefan@adlk.io>", 144 author: 'Stefan Malzner <stefan@adlk.io>',
145 "featured": false, 145 featured: false,
146 "id": "hipchat", 146 id: 'hipchat',
147 "name": "HipChat", 147 name: 'HipChat',
148 "version": "1.0.1", 148 version: '1.0.1',
149 "icons": { 149 icons: {
150 "png": "https://cdn.franzinfra.com/recipes/dist/hipchat/src/icon.png", 150 png: 'https://cdn.franzinfra.com/recipes/dist/hipchat/src/icon.png',
151 "svg": "https://cdn.franzinfra.com/recipes/dist/hipchat/src/icon.svg" 151 svg: 'https://cdn.franzinfra.com/recipes/dist/hipchat/src/icon.svg',
152 } 152 },
153 }, { 153 }, {
154 "author": "Stefan Malzner <stefan@adlk.io>", 154 author: 'Stefan Malzner <stefan@adlk.io>',
155 "featured": false, 155 featured: false,
156 "id": "gmailinbox", 156 id: 'gmailinbox',
157 "name": "Inbox by Gmail", 157 name: 'Inbox by Gmail',
158 "version": "1.0.0", 158 version: '1.0.0',
159 "icons": { 159 icons: {
160 "png": "https://cdn.franzinfra.com/recipes/dist/gmailinbox/src/icon.png", 160 png: 'https://cdn.franzinfra.com/recipes/dist/gmailinbox/src/icon.png',
161 "svg": "https://cdn.franzinfra.com/recipes/dist/gmailinbox/src/icon.svg" 161 svg: 'https://cdn.franzinfra.com/recipes/dist/gmailinbox/src/icon.svg',
162 } 162 },
163 }, { 163 }, {
164 "author": "Stefan Malzner <stefan@adlk.io>", 164 author: 'Stefan Malzner <stefan@adlk.io>',
165 "featured": false, 165 featured: false,
166 "id": "rocketchat", 166 id: 'rocketchat',
167 "name": "Rocket.Chat", 167 name: 'Rocket.Chat',
168 "version": "1.0.1", 168 version: '1.0.1',
169 "icons": { 169 icons: {
170 "png": "https://cdn.franzinfra.com/recipes/dist/rocketchat/src/icon.png", 170 png: 'https://cdn.franzinfra.com/recipes/dist/rocketchat/src/icon.png',
171 "svg": "https://cdn.franzinfra.com/recipes/dist/rocketchat/src/icon.svg" 171 svg: 'https://cdn.franzinfra.com/recipes/dist/rocketchat/src/icon.svg',
172 } 172 },
173 }, { 173 }, {
174 "author": "Brian Gilbert <brian@briangilbert.net>", 174 author: 'Brian Gilbert <brian@briangilbert.net>',
175 "featured": false, 175 featured: false,
176 "id": "gitter", 176 id: 'gitter',
177 "name": "Gitter", 177 name: 'Gitter',
178 "version": "1.0.0", 178 version: '1.0.0',
179 "icons": { 179 icons: {
180 "png": "https://cdn.franzinfra.com/recipes/dist/gitter/src/icon.png", 180 png: 'https://cdn.franzinfra.com/recipes/dist/gitter/src/icon.png',
181 "svg": "https://cdn.franzinfra.com/recipes/dist/gitter/src/icon.svg" 181 svg: 'https://cdn.franzinfra.com/recipes/dist/gitter/src/icon.svg',
182 } 182 },
183 }, { 183 }, {
184 "author": "Stefan Malzner <stefan@adlk.io>", 184 author: 'Stefan Malzner <stefan@adlk.io>',
185 "featured": false, 185 featured: false,
186 "id": "mattermost", 186 id: 'mattermost',
187 "name": "Mattermost", 187 name: 'Mattermost',
188 "version": "1.0.0", 188 version: '1.0.0',
189 "icons": { 189 icons: {
190 "png": "https://cdn.franzinfra.com/recipes/dist/mattermost/src/icon.png", 190 png: 'https://cdn.franzinfra.com/recipes/dist/mattermost/src/icon.png',
191 "svg": "https://cdn.franzinfra.com/recipes/dist/mattermost/src/icon.svg" 191 svg: 'https://cdn.franzinfra.com/recipes/dist/mattermost/src/icon.svg',
192 } 192 },
193 }, { 193 }, {
194 "author": "Franz <recipe@meetfranz.com>", 194 author: 'Franz <recipe@meetfranz.com>',
195 "featured": false, 195 featured: false,
196 "id": "toggl", 196 id: 'toggl',
197 "name": "toggl", 197 name: 'toggl',
198 "version": "1.0.0", 198 version: '1.0.0',
199 "icons": { 199 icons: {
200 "png": "https://cdn.franzinfra.com/recipes/dist/toggl/src/icon.png", 200 png: 'https://cdn.franzinfra.com/recipes/dist/toggl/src/icon.png',
201 "svg": "https://cdn.franzinfra.com/recipes/dist/toggl/src/icon.svg" 201 svg: 'https://cdn.franzinfra.com/recipes/dist/toggl/src/icon.svg',
202 } 202 },
203 }, { 203 }, {
204 "author": "Stuart Clark <stuart@realityloop.com>", 204 author: 'Stuart Clark <stuart@realityloop.com>',
205 "featured": false, 205 featured: false,
206 "id": "twist", 206 id: 'twist',
207 "name": "twist", 207 name: 'twist',
208 "version": "1.0.0", 208 version: '1.0.0',
209 "icons": { 209 icons: {
210 "png": "https://cdn.franzinfra.com/recipes/dist/twist/src/icon.png", 210 png: 'https://cdn.franzinfra.com/recipes/dist/twist/src/icon.png',
211 "svg": "https://cdn.franzinfra.com/recipes/dist/twist/src/icon.svg" 211 svg: 'https://cdn.franzinfra.com/recipes/dist/twist/src/icon.svg',
212 } 212 },
213 }]) 213 }]);
214 } 214 }
215 215
216 // Show announcements 216 // Show announcements
217 announcement({ 217 announcement({
218 response, 218 response,
219 params
220 }) { 219 }) {
221 return response.send('No announcement found.'); 220 return response.send('No announcement found.');
222 } 221 }
223} 222}
224 223
225module.exports = StaticController 224module.exports = StaticController;
diff --git a/app/Controllers/Http/UserController.js b/app/Controllers/Http/UserController.js
index ced27bb..1e67092 100644
--- a/app/Controllers/Http/UserController.js
+++ b/app/Controllers/Http/UserController.js
@@ -1,12 +1,10 @@
1'use strict'
2
3const User = use('App/Models/User'); 1const User = use('App/Models/User');
4const Service = use('App/Models/Service'); 2const Service = use('App/Models/Service');
5const Workspace = use('App/Models/Workspace'); 3const Workspace = use('App/Models/Workspace');
6const { 4const {
7 validateAll 5 validateAll,
8} = use('Validator'); 6} = use('Validator');
9const Env = use('Env') 7const Env = use('Env');
10 8
11const atob = require('atob'); 9const atob = require('atob');
12const btoa = require('btoa'); 10const btoa = require('btoa');
@@ -14,49 +12,44 @@ const fetch = require('node-fetch');
14const uuid = require('uuid/v4'); 12const uuid = require('uuid/v4');
15const crypto = require('crypto'); 13const crypto = require('crypto');
16 14
17const franzRequest = async (route, method, auth) => { 15const franzRequest = (route, method, auth) => new Promise((resolve, reject) => {
18 return new Promise(async (resolve, reject) => { 16 const base = 'https://api.franzinfra.com/v1/';
19 const base = 'https://api.franzinfra.com/v1/'; 17 const user = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Ferdi/5.3.0-beta.1 Chrome/69.0.3497.128 Electron/4.2.4 Safari/537.36';
20 const user = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Ferdi/5.3.0-beta.1 Chrome/69.0.3497.128 Electron/4.2.4 Safari/537.36'; 18
21 19 try {
22 try { 20 fetch(base + route, {
23 const rawResponse = await fetch(base + route, { 21 method,
24 method, 22 headers: {
25 headers: { 23 Authorization: `Bearer ${auth}`,
26 'Authorization': 'Bearer ' + auth, 24 'User-Agent': user,
27 'User-Agent': user 25 },
28 }, 26 })
29 }); 27 .then((data) => data.json())
30 const content = await rawResponse.json(); 28 .then((json) => resolve(json));
31 29 } catch (e) {
32 resolve(content); 30 reject();
33 } catch (e) { 31 }
34 reject(); 32});
35 }
36 })
37}
38 33
39class UserController { 34class UserController {
40
41 // Register a new user 35 // Register a new user
42 async signup({ 36 async signup({
43 request, 37 request,
44 response, 38 response,
45 auth, 39 auth,
46 session
47 }) { 40 }) {
48 // Validate user input 41 // Validate user input
49 const validation = await validateAll(request.all(), { 42 const validation = await validateAll(request.all(), {
50 firstname: 'required', 43 firstname: 'required',
51 email: 'required|email|unique:users,email', 44 email: 'required|email|unique:users,email',
52 password: 'required' 45 password: 'required',
53 }); 46 });
54 if (validation.fails()) { 47 if (validation.fails()) {
55 return response.status(401).send({ 48 return response.status(401).send({
56 "message": "Invalid POST arguments", 49 message: 'Invalid POST arguments',
57 "messages": validation.messages(), 50 messages: validation.messages(),
58 "status": 401 51 status: 401,
59 }) 52 });
60 } 53 }
61 54
62 const data = request.only(['firstname', 'email', 'password']); 55 const data = request.only(['firstname', 'email', 'password']);
@@ -67,21 +60,21 @@ class UserController {
67 user = await User.create({ 60 user = await User.create({
68 email: data.email, 61 email: data.email,
69 password: data.password, 62 password: data.password,
70 username: data.firstname 63 username: data.firstname,
71 }); 64 });
72 } catch (e) { 65 } catch (e) {
73 return response.status(401).send({ 66 return response.status(401).send({
74 "message": "E-Mail Address already in use", 67 message: 'E-Mail Address already in use',
75 "status": 401 68 status: 401,
76 }) 69 });
77 } 70 }
78 71
79 // Generate new auth token 72 // Generate new auth token
80 const token = await auth.generate(user) 73 const token = await auth.generate(user);
81 74
82 return response.send({ 75 return response.send({
83 "message": "Successfully created account", 76 message: 'Successfully created account',
84 "token": token.token 77 token: token.token,
85 }); 78 });
86 } 79 }
87 80
@@ -89,115 +82,112 @@ class UserController {
89 async login({ 82 async login({
90 request, 83 request,
91 response, 84 response,
92 auth 85 auth,
93 }) { 86 }) {
94 if (!request.header('Authorization')) { 87 if (!request.header('Authorization')) {
95 return response.status(401).send({ 88 return response.status(401).send({
96 "message": "Please provide authorization", 89 message: 'Please provide authorization',
97 "status": 401 90 status: 401,
98 }) 91 });
99 } 92 }
100 93
101 // Get auth data from auth token 94 // Get auth data from auth token
102 const authHeader = atob(request.header('Authorization').replace('Basic ', '')).split(':'); 95 const authHeader = atob(request.header('Authorization').replace('Basic ', '')).split(':');
103 96
104 // Check if user with email exists 97 // Check if user with email exists
105 let user = (await User.query().where('email', authHeader[0]).first()); 98 const user = (await User.query().where('email', authHeader[0]).first());
106 if (!user || !user.email) { 99 if (!user || !user.email) {
107 return response.status(401).send({ 100 return response.status(401).send({
108 "message": "User credentials not valid (Invalid mail)", 101 message: 'User credentials not valid (Invalid mail)',
109 "code": "invalid-credentials", 102 code: 'invalid-credentials',
110 "status": 401 103 status: 401,
111 }); 104 });
112 } 105 }
113 106
114 // Try to login 107 // Try to login
115 let token; 108 let token;
116 try { 109 try {
117 token = await auth.attempt(user.email, authHeader[1]) 110 token = await auth.attempt(user.email, authHeader[1]);
118 } catch (e) { 111 } catch (e) {
119 return response.status(401).send({ 112 return response.status(401).send({
120 "message": "User credentials not valid", 113 message: 'User credentials not valid',
121 "code": "invalid-credentials", 114 code: 'invalid-credentials',
122 "status": 401 115 status: 401,
123 }); 116 });
124 } 117 }
125 118
126 return response.send({ 119 return response.send({
127 "message": "Successfully logged in", 120 message: 'Successfully logged in',
128 "token": token.token 121 token: token.token,
129 }); 122 });
130 } 123 }
131 124
132 // Return information about the current user 125 // Return information about the current user
133 async me({ 126 async me({
134 request,
135 response, 127 response,
136 auth, 128 auth,
137 session
138 }) { 129 }) {
139 try { 130 try {
140 await auth.getUser() 131 await auth.getUser();
141 } catch (error) { 132 } catch (error) {
142 response.send('Missing or invalid api token') 133 response.send('Missing or invalid api token');
143 } 134 }
144 135
145 return response.send({ 136 return response.send({
146 accountType: "individual", 137 accountType: 'individual',
147 beta: false, 138 beta: false,
148 donor: {}, 139 donor: {},
149 email: auth.user.email, 140 email: auth.user.email,
150 emailValidated: true, 141 emailValidated: true,
151 features: {}, 142 features: {},
152 firstname: "Franz", 143 firstname: 'Franz',
153 id: "82c1cf9d-ab58-4da2-b55e-aaa41d2142d8", 144 id: '82c1cf9d-ab58-4da2-b55e-aaa41d2142d8',
154 isPremium: true, 145 isPremium: true,
155 isSubscriptionOwner: true, 146 isSubscriptionOwner: true,
156 lastname: "Franz", 147 lastname: 'Franz',
157 locale: "en-US" 148 locale: 'en-US',
158 }); 149 });
159 } 150 }
160 151
161 152
162
163 async import({ 153 async import({
164 request, 154 request,
165 response 155 response,
166 }) { 156 }) {
167 // Validate user input 157 // Validate user input
168 const validation = await validateAll(request.all(), { 158 const validation = await validateAll(request.all(), {
169 email: 'required|email|unique:users,email', 159 email: 'required|email|unique:users,email',
170 password: 'required' 160 password: 'required',
171 }); 161 });
172 if (validation.fails()) { 162 if (validation.fails()) {
173 let errorMessage = "There was an error while trying to import your account:\n"; 163 let errorMessage = 'There was an error while trying to import your account:\n';
174 for (const message of validation.messages()) { 164 for (const message of validation.messages()) {
175 if (message.validation == 'required') { 165 if (message.validation === 'required') {
176 errorMessage += '- Please make sure to supply your ' + message.field + '\n' 166 errorMessage += `- Please make sure to supply your ${message.field}\n`;
177 } else if (message.validation == 'unique') { 167 } else if (message.validation === 'unique') {
178 errorMessage += '- There is already a user with this email.\n' 168 errorMessage += '- There is already a user with this email.\n';
179 } else { 169 } else {
180 errorMessage += message.message + '\n'; 170 errorMessage += `${message.message}\n`;
181 } 171 }
182 } 172 }
183 return response.status(401).send(errorMessage) 173 return response.status(401).send(errorMessage);
184 } 174 }
185 175
186 const { 176 const {
187 email, 177 email,
188 password 178 password,
189 } = request.all() 179 } = request.all();
190 180
191 const hashedPassword = crypto.createHash('sha256').update(password).digest('base64'); 181 const hashedPassword = crypto.createHash('sha256').update(password).digest('base64');
192 182
193 if(Env.get('CONNECT_WITH_FRANZ') == 'false') { 183 if (Env.get('CONNECT_WITH_FRANZ') == 'false') { // eslint-disable-line eqeqeq
194 await User.create({ 184 await User.create({
195 email, 185 email,
196 password: hashedPassword, 186 password: hashedPassword,
197 username: 'Franz' 187 username: 'Franz',
198 }); 188 });
199 189
200 return response.send('Your account has been created but due to this server\'s configuration, we could not import your Franz account data.\n\nIf you are the server owner, please set CONNECT_WITH_FRANZ to true to enable account imports.') 190 return response.send('Your account has been created but due to this server\'s configuration, we could not import your Franz account data.\n\nIf you are the server owner, please set CONNECT_WITH_FRANZ to true to enable account imports.');
201 } 191 }
202 192
203 const base = 'https://api.franzinfra.com/v1/'; 193 const base = 'https://api.franzinfra.com/v1/';
@@ -206,42 +196,41 @@ class UserController {
206 // Try to get an authentication token 196 // Try to get an authentication token
207 let token; 197 let token;
208 try { 198 try {
209 const basicToken = btoa(email + ':' + hashedPassword) 199 const basicToken = btoa(`${email}:${hashedPassword}`);
210 200
211 const rawResponse = await fetch(base + 'auth/login', { 201 const rawResponse = await fetch(`${base}auth/login`, {
212 method: 'POST', 202 method: 'POST',
213 headers: { 203 headers: {
214 'Authorization': 'Basic ' + basicToken, 204 Authorization: `Basic ${basicToken}`,
215 'User-Agent': userAgent 205 'User-Agent': userAgent,
216 }, 206 },
217 }); 207 });
218 const content = await rawResponse.json(); 208 const content = await rawResponse.json();
219 209
220 if (!content.message || content.message !== 'Successfully logged in') { 210 if (!content.message || content.message !== 'Successfully logged in') {
221 const errorMessage = 'Could not login into Franz with your supplied credentials. Please check and try again'; 211 const errorMessage = 'Could not login into Franz with your supplied credentials. Please check and try again';
222 return response.status(401).send(errorMessage) 212 return response.status(401).send(errorMessage);
223 } 213 }
224 214
225 token = content.token; 215 token = content.token;
226 } catch (e) { 216 } catch (e) {
227 return response.status(401).send({ 217 return response.status(401).send({
228 "message": "Cannot login to Franz", 218 message: 'Cannot login to Franz',
229 "error": e 219 error: e,
230 }) 220 });
231 } 221 }
232 222
233 // Get user information 223 // Get user information
234 let userInf = false; 224 let userInf = false;
235 try { 225 try {
236 userInf = await franzRequest('me', 'GET', token) 226 userInf = await franzRequest('me', 'GET', token);
237 console.log('A', userInf)
238 } catch (e) { 227 } catch (e) {
239 const errorMessage = 'Could not get your user info from Franz. Please check your credentials or try again later.\nError: ' + e; 228 const errorMessage = `Could not get your user info from Franz. Please check your credentials or try again later.\nError: ${e}`;
240 return response.status(401).send(errorMessage) 229 return response.status(401).send(errorMessage);
241 } 230 }
242 if (!userInf) { 231 if (!userInf) {
243 const errorMessage = 'Could not get your user info from Franz. Please check your credentials or try again later.\nError: ' + e; 232 const errorMessage = 'Could not get your user info from Franz. Please check your credentials or try again later';
244 return response.status(401).send(errorMessage) 233 return response.status(401).send(errorMessage);
245 } 234 }
246 235
247 // Create user in DB 236 // Create user in DB
@@ -250,69 +239,69 @@ class UserController {
250 user = await User.create({ 239 user = await User.create({
251 email: userInf.email, 240 email: userInf.email,
252 password: hashedPassword, 241 password: hashedPassword,
253 username: userInf.firstname 242 username: userInf.firstname,
254 }); 243 });
255 } catch (e) { 244 } catch (e) {
256 const errorMessage = 'Could not create your user in our system.\nError: ' + e; 245 const errorMessage = `Could not create your user in our system.\nError: ${e}`;
257 return response.status(401).send(errorMessage) 246 return response.status(401).send(errorMessage);
258 } 247 }
259 248
260 let serviceIdTranslation = {}; 249 const serviceIdTranslation = {};
261 250
262 // Import services 251 // Import services
263 try { 252 try {
264 const services = await franzRequest('me/services', 'GET', token) 253 const services = await franzRequest('me/services', 'GET', token);
265 254
266 for (const service of services) { 255 for (const service of services) {
267 // Get new, unused uuid 256 // Get new, unused uuid
268 let serviceId; 257 let serviceId;
269 do { 258 do {
270 serviceId = uuid(); 259 serviceId = uuid();
271 } while ((await Service.query().where('serviceId', serviceId).fetch()).rows.length > 0) 260 } while ((await Service.query().where('serviceId', serviceId).fetch()).rows.length > 0); // eslint-disable-line no-await-in-loop
272 261
273 await Service.create({ 262 await Service.create({ // eslint-disable-line no-await-in-loop
274 userId: user.id, 263 userId: user.id,
275 serviceId, 264 serviceId,
276 name: service.name, 265 name: service.name,
277 recipeId: service.recipeId, 266 recipeId: service.recipeId,
278 settings: JSON.stringify(service) 267 settings: JSON.stringify(service),
279 }); 268 });
280 269
281 serviceIdTranslation[service.id] = serviceId; 270 serviceIdTranslation[service.id] = serviceId;
282 } 271 }
283 } catch (e) { 272 } catch (e) {
284 const errorMessage = 'Could not import your services into our system.\nError: ' + e; 273 const errorMessage = `Could not import your services into our system.\nError: ${e}`;
285 return response.status(401).send(errorMessage) 274 return response.status(401).send(errorMessage);
286 } 275 }
287 276
288 // Import workspaces 277 // Import workspaces
289 try { 278 try {
290 const workspaces = await franzRequest('workspace', 'GET', token) 279 const workspaces = await franzRequest('workspace', 'GET', token);
291 280
292 for (const workspace of workspaces) { 281 for (const workspace of workspaces) {
293 let workspaceId; 282 let workspaceId;
294 do { 283 do {
295 workspaceId = uuid(); 284 workspaceId = uuid();
296 } while ((await Workspace.query().where('workspaceId', workspaceId).fetch()).rows.length > 0) 285 } while ((await Workspace.query().where('workspaceId', workspaceId).fetch()).rows.length > 0); // eslint-disable-line no-await-in-loop
297 286
298 const services = workspace.services.map(service => serviceIdTranslation[service]) 287 const services = workspace.services.map((service) => serviceIdTranslation[service]);
299 288
300 await Workspace.create({ 289 await Workspace.create({ // eslint-disable-line no-await-in-loop
301 userId: auth.user.id, 290 userId: user.id,
302 workspaceId, 291 workspaceId,
303 name: workspace.name, 292 name: workspace.name,
304 order: workspace.order, 293 order: workspace.order,
305 services: JSON.stringify(services), 294 services: JSON.stringify(services),
306 data: JSON.stringify({}) 295 data: JSON.stringify({}),
307 }); 296 });
308 } 297 }
309 } catch (e) { 298 } catch (e) {
310 const errorMessage = 'Could not import your workspaces into our system.\nError: ' + e; 299 const errorMessage = `Could not import your workspaces into our system.\nError: ${e}`;
311 return response.status(401).send(errorMessage) 300 return response.status(401).send(errorMessage);
312 } 301 }
313 302
314 return response.send('Your account has been imported. You can now use your Franz account in Ferdi.') 303 return response.send('Your account has been imported. You can now use your Franz account in Ferdi.');
315 } 304 }
316} 305}
317 306
318module.exports = UserController 307module.exports = UserController;
diff --git a/app/Controllers/Http/WorkspaceController.js b/app/Controllers/Http/WorkspaceController.js
index b64d858..ecf79af 100644
--- a/app/Controllers/Http/WorkspaceController.js
+++ b/app/Controllers/Http/WorkspaceController.js
@@ -1,8 +1,7 @@
1'use strict'
2 1
3const Workspace = use('App/Models/Workspace'); 2const Workspace = use('App/Models/Workspace');
4const { 3const {
5 validateAll 4 validateAll,
6} = use('Validator'); 5} = use('Validator');
7 6
8const uuid = require('uuid/v4'); 7const uuid = require('uuid/v4');
@@ -12,12 +11,12 @@ class WorkspaceController {
12 async create({ 11 async create({
13 request, 12 request,
14 response, 13 response,
15 auth 14 auth,
16 }) { 15 }) {
17 try { 16 try {
18 await auth.getUser() 17 await auth.getUser();
19 } catch (error) { 18 } catch (error) {
20 return response.send('Missing or invalid api token') 19 return response.send('Missing or invalid api token');
21 } 20 }
22 21
23 // Validate user input 22 // Validate user input
@@ -26,10 +25,10 @@ class WorkspaceController {
26 }); 25 });
27 if (validation.fails()) { 26 if (validation.fails()) {
28 return response.status(401).send({ 27 return response.status(401).send({
29 "message": "Invalid POST arguments", 28 message: 'Invalid POST arguments',
30 "messages": validation.messages(), 29 messages: validation.messages(),
31 "status": 401 30 status: 401,
32 }) 31 });
33 } 32 }
34 33
35 const data = request.all(); 34 const data = request.all();
@@ -38,7 +37,7 @@ class WorkspaceController {
38 let workspaceId; 37 let workspaceId;
39 do { 38 do {
40 workspaceId = uuid(); 39 workspaceId = uuid();
41 } while ((await Workspace.query().where('workspaceId', workspaceId).fetch()).rows.length > 0) 40 } while ((await Workspace.query().where('workspaceId', workspaceId).fetch()).rows.length > 0); // eslint-disable-line no-await-in-loop
42 41
43 const order = (await auth.user.workspaces().fetch()).rows.length; 42 const order = (await auth.user.workspaces().fetch()).rows.length;
44 43
@@ -48,7 +47,7 @@ class WorkspaceController {
48 name: data.name, 47 name: data.name,
49 order, 48 order,
50 services: JSON.stringify([]), 49 services: JSON.stringify([]),
51 data: JSON.stringify(data) 50 data: JSON.stringify(data),
52 }); 51 });
53 52
54 return response.send({ 53 return response.send({
@@ -57,37 +56,37 @@ class WorkspaceController {
57 id: workspaceId, 56 id: workspaceId,
58 order, 57 order,
59 workspaces: [], 58 workspaces: [],
60 }) 59 });
61 } 60 }
62 61
63 async edit({ 62 async edit({
64 request, 63 request,
65 response, 64 response,
66 auth, 65 auth,
67 params 66 params,
68 }) { 67 }) {
69 try { 68 try {
70 await auth.getUser() 69 await auth.getUser();
71 } catch (error) { 70 } catch (error) {
72 return response.send('Missing or invalid api token') 71 return response.send('Missing or invalid api token');
73 } 72 }
74 73
75 // Validate user input 74 // Validate user input
76 const validation = await validateAll(request.all(), { 75 const validation = await validateAll(request.all(), {
77 name: 'required|alpha', 76 name: 'required|alpha',
78 services: 'required|array' 77 services: 'required|array',
79 }); 78 });
80 if (validation.fails()) { 79 if (validation.fails()) {
81 return response.status(401).send({ 80 return response.status(401).send({
82 "message": "Invalid POST arguments", 81 message: 'Invalid POST arguments',
83 "messages": validation.messages(), 82 messages: validation.messages(),
84 "status": 401 83 status: 401,
85 }) 84 });
86 } 85 }
87 86
88 const data = request.all(); 87 const data = request.all();
89 const { 88 const {
90 id 89 id,
91 } = params; 90 } = params;
92 91
93 // Update data in database 92 // Update data in database
@@ -95,7 +94,7 @@ class WorkspaceController {
95 .where('workspaceId', id) 94 .where('workspaceId', id)
96 .where('userId', auth.user.id)).update({ 95 .where('userId', auth.user.id)).update({
97 name: data.name, 96 name: data.name,
98 services: JSON.stringify(data.services) 97 services: JSON.stringify(data.services),
99 }); 98 });
100 99
101 // Get updated row 100 // Get updated row
@@ -104,24 +103,24 @@ class WorkspaceController {
104 .where('userId', auth.user.id).fetch()).rows[0]; 103 .where('userId', auth.user.id).fetch()).rows[0];
105 104
106 return response.send({ 105 return response.send({
107 "id": workspace.workspaceId, 106 id: workspace.workspaceId,
108 "name": data.name, 107 name: data.name,
109 "order": workspace.order, 108 order: workspace.order,
110 "services": data.services, 109 services: data.services,
111 "userId": auth.user.id 110 userId: auth.user.id,
112 }) 111 });
113 } 112 }
114 113
115 async delete({ 114 async delete({
116 request, 115 request,
117 response, 116 response,
118 auth, 117 auth,
119 params 118 params,
120 }) { 119 }) {
121 try { 120 try {
122 await auth.getUser() 121 await auth.getUser();
123 } catch (error) { 122 } catch (error) {
124 return response.send('Missing or invalid api token') 123 return response.send('Missing or invalid api token');
125 } 124 }
126 125
127 // Validate user input 126 // Validate user input
@@ -130,14 +129,14 @@ class WorkspaceController {
130 }); 129 });
131 if (validation.fails()) { 130 if (validation.fails()) {
132 return response.status(401).send({ 131 return response.status(401).send({
133 "message": "Invalid POST arguments", 132 message: 'Invalid POST arguments',
134 "messages": validation.messages(), 133 messages: validation.messages(),
135 "status": 401 134 status: 401,
136 }) 135 });
137 } 136 }
138 137
139 const { 138 const {
140 id 139 id,
141 } = params; 140 } = params;
142 141
143 // Update data in database 142 // Update data in database
@@ -146,38 +145,37 @@ class WorkspaceController {
146 .where('userId', auth.user.id)).delete(); 145 .where('userId', auth.user.id)).delete();
147 146
148 return response.send({ 147 return response.send({
149 "message": "Successfully deleted workspace", 148 message: 'Successfully deleted workspace',
150 }) 149 });
151 } 150 }
152 151
153 // List all workspaces a user has created 152 // List all workspaces a user has created
154 async list({ 153 async list({
155 request,
156 response, 154 response,
157 auth 155 auth,
158 }) { 156 }) {
159 try { 157 try {
160 await auth.getUser() 158 await auth.getUser();
161 } catch (error) { 159 } catch (error) {
162 return response.send('Missing or invalid api token') 160 return response.send('Missing or invalid api token');
163 } 161 }
164 162
165 const workspaces = (await auth.user.workspaces().fetch()).rows; 163 const workspaces = (await auth.user.workspaces().fetch()).rows;
166 // Convert to array with all data Franz wants 164 // Convert to array with all data Franz wants
167 let workspacesArray = []; 165 let workspacesArray = [];
168 if(workspaces) { 166 if (workspaces) {
169 workspacesArray = workspaces.map(workspace => ({ 167 workspacesArray = workspaces.map((workspace) => ({
170 "id": workspace.workspaceId, 168 id: workspace.workspaceId,
171 "name": workspace.name, 169 name: workspace.name,
172 "order": workspace.order, 170 order: workspace.order,
173 "services": JSON.parse(workspace.services), 171 services: JSON.parse(workspace.services),
174 "userId": auth.user.id 172 userId: auth.user.id,
175 })) 173 }));
176 } 174 }
177
178 175
179 return response.send(workspacesArray) 176
177 return response.send(workspacesArray);
180 } 178 }
181} 179}
182 180
183module.exports = WorkspaceController 181module.exports = WorkspaceController;
diff --git a/app/Exceptions/Handler.js b/app/Exceptions/Handler.js
index efa2e0b..cb9e10b 100644
--- a/app/Exceptions/Handler.js
+++ b/app/Exceptions/Handler.js
@@ -1,6 +1,5 @@
1'use strict'
2 1
3const BaseExceptionHandler = use('BaseExceptionHandler') 2const BaseExceptionHandler = use('BaseExceptionHandler');
4 3
5/** 4/**
6 * This class handles all exceptions thrown during 5 * This class handles all exceptions thrown during
@@ -20,14 +19,14 @@ class ExceptionHandler extends BaseExceptionHandler {
20 * 19 *
21 * @return {void} 20 * @return {void}
22 */ 21 */
23 async handle (error, { request, response }) { 22 async handle(error, { response }) {
24 if (error.name === 'ValidationException') { 23 if (error.name === 'ValidationException') {
25 return response.status(400).send('Invalid arguments') 24 return response.status(400).send('Invalid arguments');
26 } else if (error.name === 'InvalidSessionException') { 25 } if (error.name === 'InvalidSessionException') {
27 return response.status(401).redirect('/user/login'); 26 return response.status(401).redirect('/user/login');
28 } 27 }
29 28
30 response.status(error.status).send(error.message) 29 return response.status(error.status).send(error.message);
31 } 30 }
32 31
33 /** 32 /**
@@ -40,8 +39,9 @@ class ExceptionHandler extends BaseExceptionHandler {
40 * 39 *
41 * @return {void} 40 * @return {void}
42 */ 41 */
43 async report (error, { request }) { 42 async report() {
43 return true;
44 } 44 }
45} 45}
46 46
47module.exports = ExceptionHandler 47module.exports = ExceptionHandler;
diff --git a/app/Middleware/ConvertEmptyStringsToNull.js b/app/Middleware/ConvertEmptyStringsToNull.js
index a5750cc..556f223 100644
--- a/app/Middleware/ConvertEmptyStringsToNull.js
+++ b/app/Middleware/ConvertEmptyStringsToNull.js
@@ -1,17 +1,16 @@
1'use strict'
2 1
3class ConvertEmptyStringsToNull { 2class ConvertEmptyStringsToNull {
4 async handle ({ request }, next) { 3 async handle({ request }, next) {
5 if (Object.keys(request.body).length) { 4 if (Object.keys(request.body).length) {
6 request.body = Object.assign( 5 request.body = Object.assign(
7 ...Object.keys(request.body).map(key => ({ 6 ...Object.keys(request.body).map((key) => ({
8 [key]: request.body[key] !== '' ? request.body[key] : null 7 [key]: request.body[key] !== '' ? request.body[key] : null,
9 })) 8 })),
10 ) 9 );
11 } 10 }
12 11
13 await next() 12 await next();
14 } 13 }
15} 14}
16 15
17module.exports = ConvertEmptyStringsToNull 16module.exports = ConvertEmptyStringsToNull;
diff --git a/app/Models/Recipe.js b/app/Models/Recipe.js
index 9e3619c..da3618b 100644
--- a/app/Models/Recipe.js
+++ b/app/Models/Recipe.js
@@ -1,9 +1,8 @@
1'use strict'
2 1
3/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */ 2/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */
4const Model = use('Model') 3const Model = use('Model');
5 4
6class Recipe extends Model { 5class Recipe extends Model {
7} 6}
8 7
9module.exports = Recipe 8module.exports = Recipe;
diff --git a/app/Models/Service.js b/app/Models/Service.js
index 0ca72fd..0a13ec1 100644
--- a/app/Models/Service.js
+++ b/app/Models/Service.js
@@ -1,12 +1,11 @@
1'use strict'
2 1
3/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */ 2/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */
4const Model = use('Model') 3const Model = use('Model');
5 4
6class Service extends Model { 5class Service extends Model {
7 user() { 6 user() {
8 return this.belongsTo('App/Models/User', 'userId', 'id') 7 return this.belongsTo('App/Models/User', 'userId', 'id');
9 } 8 }
10} 9}
11 10
12module.exports = Service 11module.exports = Service;
diff --git a/app/Models/Token.js b/app/Models/Token.js
index e089e87..f6bec08 100644
--- a/app/Models/Token.js
+++ b/app/Models/Token.js
@@ -1,9 +1,8 @@
1'use strict'
2 1
3/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */ 2/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */
4const Model = use('Model') 3const Model = use('Model');
5 4
6class Token extends Model { 5class Token extends Model {
7} 6}
8 7
9module.exports = Token 8module.exports = Token;
diff --git a/app/Models/Traits/NoTimestamp.js b/app/Models/Traits/NoTimestamp.js
index edd07f0..c647428 100644
--- a/app/Models/Traits/NoTimestamp.js
+++ b/app/Models/Traits/NoTimestamp.js
@@ -1,16 +1,15 @@
1'use strict'
2 1
3class NoTimestamp { 2class NoTimestamp {
4 register (Model) { 3 register(Model) {
5 Object.defineProperties(Model, { 4 Object.defineProperties(Model, {
6 createdAtColumn: { 5 createdAtColumn: {
7 get: () => null, 6 get: () => null,
8 }, 7 },
9 updatedAtColumn: { 8 updatedAtColumn: {
10 get: () => null, 9 get: () => null,
11 } 10 },
12 }) 11 });
13 } 12 }
14} 13}
15 14
16module.exports = NoTimestamp 15module.exports = NoTimestamp;
diff --git a/app/Models/User.js b/app/Models/User.js
index c9a680a..3a40347 100644
--- a/app/Models/User.js
+++ b/app/Models/User.js
@@ -1,14 +1,13 @@
1'use strict'
2 1
3/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */ 2/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */
4const Model = use('Model') 3const Model = use('Model');
5 4
6/** @type {import('@adonisjs/framework/src/Hash')} */ 5/** @type {import('@adonisjs/framework/src/Hash')} */
7const Hash = use('Hash') 6const Hash = use('Hash');
8 7
9class User extends Model { 8class User extends Model {
10 static boot () { 9 static boot() {
11 super.boot() 10 super.boot();
12 11
13 /** 12 /**
14 * A hook to hash the user password before saving 13 * A hook to hash the user password before saving
@@ -16,9 +15,10 @@ class User extends Model {
16 */ 15 */
17 this.addHook('beforeSave', async (userInstance) => { 16 this.addHook('beforeSave', async (userInstance) => {
18 if (userInstance.dirty.password) { 17 if (userInstance.dirty.password) {
19 userInstance.password = await Hash.make(userInstance.password) 18 // eslint-disable-next-line no-param-reassign
19 userInstance.password = await Hash.make(userInstance.password);
20 } 20 }
21 }) 21 });
22 } 22 }
23 23
24 /** 24 /**
@@ -31,17 +31,17 @@ class User extends Model {
31 * 31 *
32 * @return {Object} 32 * @return {Object}
33 */ 33 */
34 tokens () { 34 tokens() {
35 return this.hasMany('App/Models/Token') 35 return this.hasMany('App/Models/Token');
36 } 36 }
37 37
38 services () { 38 services() {
39 return this.hasMany('App/Models/Service', 'id', 'userId') 39 return this.hasMany('App/Models/Service', 'id', 'userId');
40 } 40 }
41 41
42 workspaces () { 42 workspaces() {
43 return this.hasMany('App/Models/Workspace', 'id', 'userId') 43 return this.hasMany('App/Models/Workspace', 'id', 'userId');
44 } 44 }
45} 45}
46 46
47module.exports = User 47module.exports = User;
diff --git a/app/Models/Workspace.js b/app/Models/Workspace.js
index f78a3f9..b155e09 100644
--- a/app/Models/Workspace.js
+++ b/app/Models/Workspace.js
@@ -1,12 +1,11 @@
1'use strict'
2 1
3/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */ 2/** @type {typeof import('@adonisjs/lucid/src/Lucid/Model')} */
4const Model = use('Model') 3const Model = use('Model');
5 4
6class Workspace extends Model { 5class Workspace extends Model {
7 user() { 6 user() {
8 return this.belongsTo('App/Models/User', 'userId', 'id') 7 return this.belongsTo('App/Models/User', 'userId', 'id');
9 } 8 }
10} 9}
11 10
12module.exports = Workspace 11module.exports = Workspace;
diff --git a/config/app.js b/config/app.js
index 4b4f7a5..4d36c7b 100644
--- a/config/app.js
+++ b/config/app.js
@@ -1,7 +1,6 @@
1'use strict'
2 1
3/** @type {import('@adonisjs/framework/src/Env')} */ 2/** @type {import('@adonisjs/framework/src/Env')} */
4const Env = use('Env') 3const Env = use('Env');
5 4
6module.exports = { 5module.exports = {
7 6
@@ -94,7 +93,7 @@ module.exports = {
94 | response.send('Hello', { ignoreEtag: true }) 93 | response.send('Hello', { ignoreEtag: true })
95 | 94 |
96 */ 95 */
97 etag: false 96 etag: false,
98 }, 97 },
99 98
100 views: { 99 views: {
@@ -107,7 +106,7 @@ module.exports = {
107 | production to optimize view loading time. 106 | production to optimize view loading time.
108 | 107 |
109 */ 108 */
110 cache: Env.get('CACHE_VIEWS', true) 109 cache: Env.get('CACHE_VIEWS', true),
111 }, 110 },
112 111
113 static: { 112 static: {
@@ -146,7 +145,7 @@ module.exports = {
146 | that exists will be served. Example: ['html', 'htm']. 145 | that exists will be served. Example: ['html', 'htm'].
147 | 146 |
148 */ 147 */
149 extensions: false 148 extensions: false,
150 }, 149 },
151 150
152 locales: { 151 locales: {
@@ -173,7 +172,7 @@ module.exports = {
173 | based on HTTP headers/query string. 172 | based on HTTP headers/query string.
174 | 173 |
175 */ 174 */
176 locale: 'en' 175 locale: 'en',
177 }, 176 },
178 177
179 logger: { 178 logger: {
@@ -202,7 +201,7 @@ module.exports = {
202 console: { 201 console: {
203 driver: 'console', 202 driver: 'console',
204 name: 'adonis-app', 203 name: 'adonis-app',
205 level: 'info' 204 level: 'info',
206 }, 205 },
207 206
208 /* 207 /*
@@ -220,8 +219,8 @@ module.exports = {
220 driver: 'file', 219 driver: 'file',
221 name: 'adonis-app', 220 name: 'adonis-app',
222 filename: 'adonis.log', 221 filename: 'adonis.log',
223 level: 'info' 222 level: 'info',
224 } 223 },
225 }, 224 },
226 225
227 /* 226 /*
@@ -238,6 +237,6 @@ module.exports = {
238 httpOnly: true, 237 httpOnly: true,
239 sameSite: false, 238 sameSite: false,
240 path: '/', 239 path: '/',
241 maxAge: 7200 240 maxAge: 7200,
242 } 241 },
243} 242};
diff --git a/config/auth.js b/config/auth.js
index c70db3f..b831b06 100644
--- a/config/auth.js
+++ b/config/auth.js
@@ -1,7 +1,6 @@
1'use strict'
2 1
3/** @type {import('@adonisjs/framework/src/Env')} */ 2/** @type {import('@adonisjs/framework/src/Env')} */
4const Env = use('Env') 3const Env = use('Env');
5 4
6module.exports = { 5module.exports = {
7 /* 6 /*
@@ -32,7 +31,7 @@ module.exports = {
32 model: 'App/Models/User', 31 model: 'App/Models/User',
33 scheme: 'session', 32 scheme: 'session',
34 uid: 'email', 33 uid: 'email',
35 password: 'password' 34 password: 'password',
36 }, 35 },
37 36
38 /* 37 /*
@@ -53,7 +52,7 @@ module.exports = {
53 model: 'App/Models/User', 52 model: 'App/Models/User',
54 scheme: 'basic', 53 scheme: 'basic',
55 uid: 'email', 54 uid: 'email',
56 password: 'password' 55 password: 'password',
57 }, 56 },
58 57
59 /* 58 /*
@@ -72,8 +71,8 @@ module.exports = {
72 uid: 'email', 71 uid: 'email',
73 password: 'password', 72 password: 'password',
74 options: { 73 options: {
75 secret: Env.get('APP_KEY') 74 secret: Env.get('APP_KEY'),
76 } 75 },
77 }, 76 },
78 77
79 /* 78 /*
@@ -89,6 +88,6 @@ module.exports = {
89 model: 'App/Models/User', 88 model: 'App/Models/User',
90 scheme: 'api', 89 scheme: 'api',
91 uid: 'email', 90 uid: 'email',
92 password: 'password' 91 password: 'password',
93 } 92 },
94} 93};
diff --git a/config/bodyParser.js b/config/bodyParser.js
index f04d291..c336e67 100644
--- a/config/bodyParser.js
+++ b/config/bodyParser.js
@@ -1,4 +1,3 @@
1'use strict'
2 1
3module.exports = { 2module.exports = {
4 /* 3 /*
@@ -47,8 +46,8 @@ module.exports = {
47 'application/json', 46 'application/json',
48 'application/json-patch+json', 47 'application/json-patch+json',
49 'application/vnd.api+json', 48 'application/vnd.api+json',
50 'application/csp-report' 49 'application/csp-report',
51 ] 50 ],
52 }, 51 },
53 52
54 /* 53 /*
@@ -61,8 +60,8 @@ module.exports = {
61 */ 60 */
62 raw: { 61 raw: {
63 types: [ 62 types: [
64 'text/*' 63 'text/*',
65 ] 64 ],
66 }, 65 },
67 66
68 /* 67 /*
@@ -75,8 +74,8 @@ module.exports = {
75 */ 74 */
76 form: { 75 form: {
77 types: [ 76 types: [
78 'application/x-www-form-urlencoded' 77 'application/x-www-form-urlencoded',
79 ] 78 ],
80 }, 79 },
81 80
82 /* 81 /*
@@ -89,7 +88,7 @@ module.exports = {
89 */ 88 */
90 files: { 89 files: {
91 types: [ 90 types: [
92 'multipart/form-data' 91 'multipart/form-data',
93 ], 92 ],
94 93
95 /* 94 /*
@@ -133,7 +132,7 @@ module.exports = {
133 | is to true. Otherwise everything is processed manually. 132 | is to true. Otherwise everything is processed manually.
134 | 133 |
135 */ 134 */
136 processManually: [] 135 processManually: [],
137 136
138 /* 137 /*
139 |-------------------------------------------------------------------------- 138 |--------------------------------------------------------------------------
@@ -153,5 +152,5 @@ module.exports = {
153 | } 152 | }
154 | 153 |
155 */ 154 */
156 } 155 },
157} 156};
diff --git a/config/cors.js b/config/cors.js
index ffc1951..7ebbe3f 100644
--- a/config/cors.js
+++ b/config/cors.js
@@ -1,4 +1,3 @@
1'use strict'
2 1
3module.exports = { 2module.exports = {
4 /* 3 /*
@@ -83,5 +82,5 @@ module.exports = {
83 | Define Access-Control-Allow-Max-Age 82 | Define Access-Control-Allow-Max-Age
84 | 83 |
85 */ 84 */
86 maxAge: 90 85 maxAge: 90,
87} 86};
diff --git a/config/database.js b/config/database.js
index a7a2776..0e9cfba 100644
--- a/config/database.js
+++ b/config/database.js
@@ -1,10 +1,9 @@
1'use strict'
2 1
3/** @type {import('@adonisjs/framework/src/Env')} */ 2/** @type {import('@adonisjs/framework/src/Env')} */
4const Env = use('Env') 3const Env = use('Env');
5 4
6/** @type {import('@adonisjs/ignitor/src/Helpers')} */ 5/** @type {import('@adonisjs/ignitor/src/Helpers')} */
7const Helpers = use('Helpers') 6const Helpers = use('Helpers');
8 7
9module.exports = { 8module.exports = {
10 /* 9 /*
@@ -32,10 +31,10 @@ module.exports = {
32 sqlite: { 31 sqlite: {
33 client: 'sqlite3', 32 client: 'sqlite3',
34 connection: { 33 connection: {
35 filename: Helpers.databasePath(`${Env.get('DB_DATABASE', 'development')}.sqlite`) 34 filename: Helpers.databasePath(`${Env.get('DB_DATABASE', 'development')}.sqlite`),
36 }, 35 },
37 useNullAsDefault: true, 36 useNullAsDefault: true,
38 debug: Env.get('DB_DEBUG', false) 37 debug: Env.get('DB_DEBUG', false),
39 }, 38 },
40 39
41 /* 40 /*
@@ -55,9 +54,9 @@ module.exports = {
55 port: Env.get('DB_PORT', ''), 54 port: Env.get('DB_PORT', ''),
56 user: Env.get('DB_USER', 'root'), 55 user: Env.get('DB_USER', 'root'),
57 password: Env.get('DB_PASSWORD', ''), 56 password: Env.get('DB_PASSWORD', ''),
58 database: Env.get('DB_DATABASE', 'adonis') 57 database: Env.get('DB_DATABASE', 'adonis'),
59 }, 58 },
60 debug: Env.get('DB_DEBUG', false) 59 debug: Env.get('DB_DEBUG', false),
61 }, 60 },
62 61
63 /* 62 /*
@@ -77,8 +76,8 @@ module.exports = {
77 port: Env.get('DB_PORT', ''), 76 port: Env.get('DB_PORT', ''),
78 user: Env.get('DB_USER', 'root'), 77 user: Env.get('DB_USER', 'root'),
79 password: Env.get('DB_PASSWORD', ''), 78 password: Env.get('DB_PASSWORD', ''),
80 database: Env.get('DB_DATABASE', 'adonis') 79 database: Env.get('DB_DATABASE', 'adonis'),
81 }, 80 },
82 debug: Env.get('DB_DEBUG', false) 81 debug: Env.get('DB_DEBUG', false),
83 } 82 },
84} 83};
diff --git a/config/drive.js b/config/drive.js
index 901e699..617ce47 100644
--- a/config/drive.js
+++ b/config/drive.js
@@ -1,7 +1,4 @@
1'use strict' 1const Env = use('Env');
2
3const Helpers = use('Helpers')
4const Env = use('Env')
5 2
6module.exports = { 3module.exports = {
7 /* 4 /*
@@ -25,8 +22,8 @@ module.exports = {
25 | 22 |
26 */ 23 */
27 local: { 24 local: {
28 root: __dirname + '/../recipes', 25 root: `${__dirname}/../recipes`,
29 driver: 'local' 26 driver: 'local',
30 }, 27 },
31 28
32 /* 29 /*
@@ -42,7 +39,7 @@ module.exports = {
42 key: Env.get('S3_KEY'), 39 key: Env.get('S3_KEY'),
43 secret: Env.get('S3_SECRET'), 40 secret: Env.get('S3_SECRET'),
44 bucket: Env.get('S3_BUCKET'), 41 bucket: Env.get('S3_BUCKET'),
45 region: Env.get('S3_REGION') 42 region: Env.get('S3_REGION'),
46 } 43 },
47 } 44 },
48} 45};
diff --git a/config/hash.js b/config/hash.js
index 42f5805..297c977 100644
--- a/config/hash.js
+++ b/config/hash.js
@@ -1,7 +1,6 @@
1'use strict'
2 1
3/** @type {import('@adonisjs/framework/src/Env')} */ 2/** @type {import('@adonisjs/framework/src/Env')} */
4const Env = use('Env') 3const Env = use('Env');
5 4
6module.exports = { 5module.exports = {
7 /* 6 /*
@@ -25,7 +24,7 @@ module.exports = {
25 | 24 |
26 */ 25 */
27 bcrypt: { 26 bcrypt: {
28 rounds: 10 27 rounds: 10,
29 }, 28 },
30 29
31 /* 30 /*
@@ -44,6 +43,6 @@ module.exports = {
44 | 43 |
45 */ 44 */
46 argon: { 45 argon: {
47 type: 1 46 type: 1,
48 } 47 },
49} 48};
diff --git a/config/session.js b/config/session.js
index f49b9b7..bce28bd 100644
--- a/config/session.js
+++ b/config/session.js
@@ -1,6 +1,5 @@
1'use strict'
2 1
3const Env = use('Env') 2const Env = use('Env');
4 3
5module.exports = { 4module.exports = {
6 /* 5 /*
@@ -65,7 +64,7 @@ module.exports = {
65 cookie: { 64 cookie: {
66 httpOnly: true, 65 httpOnly: true,
67 path: '/', 66 path: '/',
68 sameSite: false 67 sameSite: false,
69 }, 68 },
70 69
71 /* 70 /*
@@ -78,7 +77,7 @@ module.exports = {
78 | 77 |
79 */ 78 */
80 file: { 79 file: {
81 location: 'sessions' 80 location: 'sessions',
82 }, 81 },
83 82
84 /* 83 /*
@@ -94,6 +93,6 @@ module.exports = {
94 port: 6379, 93 port: 6379,
95 password: null, 94 password: null,
96 db: 0, 95 db: 0,
97 keyPrefix: '' 96 keyPrefix: '',
98 } 97 },
99} 98};
diff --git a/config/shield.js b/config/shield.js
index 3d4526a..5c1c5cd 100644
--- a/config/shield.js
+++ b/config/shield.js
@@ -1,4 +1,3 @@
1'use strict'
2 1
3module.exports = { 2module.exports = {
4 /* 3 /*
@@ -64,7 +63,7 @@ module.exports = {
64 | if you want to know the behavior. https://github.com/helmetjs/helmet/pull/82 63 | if you want to know the behavior. https://github.com/helmetjs/helmet/pull/82
65 | 64 |
66 */ 65 */
67 disableAndroid: true 66 disableAndroid: true,
68 }, 67 },
69 68
70 /* 69 /*
@@ -80,7 +79,7 @@ module.exports = {
80 */ 79 */
81 xss: { 80 xss: {
82 enabled: true, 81 enabled: true,
83 enableOnOldIE: false 82 enableOnOldIE: false,
84 }, 83 },
85 84
86 /* 85 /*
@@ -139,7 +138,7 @@ module.exports = {
139 httpOnly: false, 138 httpOnly: false,
140 sameSite: true, 139 sameSite: true,
141 path: '/', 140 path: '/',
142 maxAge: 7200 141 maxAge: 7200,
143 } 142 },
144 } 143 },
145} 144};
diff --git a/database/factory.js b/database/factory.js
index 16b5084..550c5e6 100644
--- a/database/factory.js
+++ b/database/factory.js
@@ -1,4 +1,3 @@
1'use strict'
2 1
3/* 2/*
4|-------------------------------------------------------------------------- 3|--------------------------------------------------------------------------
diff --git a/database/migrations/1503250034279_user.js b/database/migrations/1503250034279_user.js
index 9148593..5010bec 100644
--- a/database/migrations/1503250034279_user.js
+++ b/database/migrations/1503250034279_user.js
@@ -1,22 +1,21 @@
1'use strict'
2 1
3/** @type {import('@adonisjs/lucid/src/Schema')} */ 2/** @type {import('@adonisjs/lucid/src/Schema')} */
4const Schema = use('Schema') 3const Schema = use('Schema');
5 4
6class UserSchema extends Schema { 5class UserSchema extends Schema {
7 up () { 6 up() {
8 this.create('users', (table) => { 7 this.create('users', (table) => {
9 table.increments() 8 table.increments();
10 table.string('username', 80).notNullable() 9 table.string('username', 80).notNullable();
11 table.string('email', 254).notNullable().unique() 10 table.string('email', 254).notNullable().unique();
12 table.string('password', 60).notNullable() 11 table.string('password', 60).notNullable();
13 table.timestamps() 12 table.timestamps();
14 }) 13 });
15 } 14 }
16 15
17 down () { 16 down() {
18 this.drop('users') 17 this.drop('users');
19 } 18 }
20} 19}
21 20
22module.exports = UserSchema 21module.exports = UserSchema;
diff --git a/database/migrations/1503250034280_token.js b/database/migrations/1503250034280_token.js
index c8bb9fc..ad97dba 100644
--- a/database/migrations/1503250034280_token.js
+++ b/database/migrations/1503250034280_token.js
@@ -1,23 +1,22 @@
1'use strict'
2 1
3/** @type {import('@adonisjs/lucid/src/Schema')} */ 2/** @type {import('@adonisjs/lucid/src/Schema')} */
4const Schema = use('Schema') 3const Schema = use('Schema');
5 4
6class TokensSchema extends Schema { 5class TokensSchema extends Schema {
7 up () { 6 up() {
8 this.create('tokens', (table) => { 7 this.create('tokens', (table) => {
9 table.increments() 8 table.increments();
10 table.integer('user_id').unsigned().references('id').inTable('users') 9 table.integer('user_id').unsigned().references('id').inTable('users');
11 table.string('token', 255).notNullable().unique().index() 10 table.string('token', 255).notNullable().unique().index();
12 table.string('type', 80).notNullable() 11 table.string('type', 80).notNullable();
13 table.boolean('is_revoked').defaultTo(false) 12 table.boolean('is_revoked').defaultTo(false);
14 table.timestamps() 13 table.timestamps();
15 }) 14 });
16 } 15 }
17 16
18 down () { 17 down() {
19 this.drop('tokens') 18 this.drop('tokens');
20 } 19 }
21} 20}
22 21
23module.exports = TokensSchema 22module.exports = TokensSchema;
diff --git a/database/migrations/1566385379883_service_schema.js b/database/migrations/1566385379883_service_schema.js
index a725699..093fb13 100644
--- a/database/migrations/1566385379883_service_schema.js
+++ b/database/migrations/1566385379883_service_schema.js
@@ -1,24 +1,23 @@
1'use strict'
2 1
3/** @type {import('@adonisjs/lucid/src/Schema')} */ 2/** @type {import('@adonisjs/lucid/src/Schema')} */
4const Schema = use('Schema') 3const Schema = use('Schema');
5 4
6class ServiceSchema extends Schema { 5class ServiceSchema extends Schema {
7 up () { 6 up() {
8 this.create('services', (table) => { 7 this.create('services', (table) => {
9 table.increments() 8 table.increments();
10 table.string('userId', 80).notNullable() 9 table.string('userId', 80).notNullable();
11 table.string('serviceId', 80).notNullable() 10 table.string('serviceId', 80).notNullable();
12 table.string('name', 80).notNullable() 11 table.string('name', 80).notNullable();
13 table.string('recipeId', 254).notNullable() 12 table.string('recipeId', 254).notNullable();
14 table.json('settings') 13 table.json('settings');
15 table.timestamps() 14 table.timestamps();
16 }) 15 });
17 } 16 }
18 17
19 down () { 18 down() {
20 this.drop('services') 19 this.drop('services');
21 } 20 }
22} 21}
23 22
24module.exports = ServiceSchema 23module.exports = ServiceSchema;
diff --git a/database/migrations/1566554231482_recipe_schema.js b/database/migrations/1566554231482_recipe_schema.js
index 7d8f5a8..14fcb82 100644
--- a/database/migrations/1566554231482_recipe_schema.js
+++ b/database/migrations/1566554231482_recipe_schema.js
@@ -1,22 +1,21 @@
1'use strict'
2 1
3/** @type {import('@adonisjs/lucid/src/Schema')} */ 2/** @type {import('@adonisjs/lucid/src/Schema')} */
4const Schema = use('Schema') 3const Schema = use('Schema');
5 4
6class RecipeSchema extends Schema { 5class RecipeSchema extends Schema {
7 up () { 6 up() {
8 this.create('recipes', (table) => { 7 this.create('recipes', (table) => {
9 table.increments() 8 table.increments();
10 table.string('name', 80).notNullable() 9 table.string('name', 80).notNullable();
11 table.string('recipeId', 254).notNullable().unique() 10 table.string('recipeId', 254).notNullable().unique();
12 table.json('data') 11 table.json('data');
13 table.timestamps() 12 table.timestamps();
14 }) 13 });
15 } 14 }
16 15
17 down () { 16 down() {
18 this.drop('recipes') 17 this.drop('recipes');
19 } 18 }
20} 19}
21 20
22module.exports = RecipeSchema 21module.exports = RecipeSchema;
diff --git a/database/migrations/1566554359294_workspace_schema.js b/database/migrations/1566554359294_workspace_schema.js
index 84e0bb9..0a3c138 100644
--- a/database/migrations/1566554359294_workspace_schema.js
+++ b/database/migrations/1566554359294_workspace_schema.js
@@ -1,25 +1,24 @@
1'use strict'
2 1
3/** @type {import('@adonisjs/lucid/src/Schema')} */ 2/** @type {import('@adonisjs/lucid/src/Schema')} */
4const Schema = use('Schema') 3const Schema = use('Schema');
5 4
6class WorkspaceSchema extends Schema { 5class WorkspaceSchema extends Schema {
7 up () { 6 up() {
8 this.create('workspaces', (table) => { 7 this.create('workspaces', (table) => {
9 table.increments() 8 table.increments();
10 table.string('workspaceId', 80).notNullable().unique() 9 table.string('workspaceId', 80).notNullable().unique();
11 table.string('userId', 80).notNullable() 10 table.string('userId', 80).notNullable();
12 table.string('name', 80).notNullable() 11 table.string('name', 80).notNullable();
13 table.integer('order') 12 table.integer('order');
14 table.json('services') 13 table.json('services');
15 table.json('data') 14 table.json('data');
16 table.timestamps() 15 table.timestamps();
17 }) 16 });
18 } 17 }
19 18
20 down () { 19 down() {
21 this.drop('workspaces') 20 this.drop('workspaces');
22 } 21 }
23} 22}
24 23
25module.exports = WorkspaceSchema 24module.exports = WorkspaceSchema;
diff --git a/package-lock.json b/package-lock.json
index 0a8707b..00d3f18 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -40,6 +40,16 @@
40 "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 40 "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
41 } 41 }
42 } 42 }
43 },
44 "fs-extra": {
45 "version": "7.0.1",
46 "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
47 "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
48 "requires": {
49 "graceful-fs": "^4.1.2",
50 "jsonfile": "^4.0.0",
51 "universalify": "^0.1.0"
52 }
43 } 53 }
44 } 54 }
45 }, 55 },
@@ -109,6 +119,16 @@
109 "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 119 "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
110 } 120 }
111 } 121 }
122 },
123 "fs-extra": {
124 "version": "7.0.1",
125 "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
126 "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
127 "requires": {
128 "graceful-fs": "^4.1.2",
129 "jsonfile": "^4.0.0",
130 "universalify": "^0.1.0"
131 }
112 } 132 }
113 } 133 }
114 }, 134 },
@@ -322,6 +342,16 @@
322 "ms": "^2.1.1" 342 "ms": "^2.1.1"
323 } 343 }
324 }, 344 },
345 "fs-extra": {
346 "version": "7.0.1",
347 "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
348 "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
349 "requires": {
350 "graceful-fs": "^4.1.2",
351 "jsonfile": "^4.0.0",
352 "universalify": "^0.1.0"
353 }
354 },
325 "ms": { 355 "ms": {
326 "version": "2.1.2", 356 "version": "2.1.2",
327 "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 357 "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -352,6 +382,43 @@
352 "lodash": "^4.17.11" 382 "lodash": "^4.17.11"
353 } 383 }
354 }, 384 },
385 "@babel/code-frame": {
386 "version": "7.5.5",
387 "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz",
388 "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==",
389 "dev": true,
390 "requires": {
391 "@babel/highlight": "^7.0.0"
392 }
393 },
394 "@babel/highlight": {
395 "version": "7.5.0",
396 "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz",
397 "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==",
398 "dev": true,
399 "requires": {
400 "chalk": "^2.0.0",
401 "esutils": "^2.0.2",
402 "js-tokens": "^4.0.0"
403 }
404 },
405 "@babel/runtime": {
406 "version": "7.5.5",
407 "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.5.tgz",
408 "integrity": "sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==",
409 "dev": true,
410 "requires": {
411 "regenerator-runtime": "^0.13.2"
412 },
413 "dependencies": {
414 "regenerator-runtime": {
415 "version": "0.13.3",
416 "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz",
417 "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==",
418 "dev": true
419 }
420 }
421 },
355 "@slynova/flydrive": { 422 "@slynova/flydrive": {
356 "version": "0.3.1", 423 "version": "0.3.1",
357 "resolved": "https://registry.npmjs.org/@slynova/flydrive/-/flydrive-0.3.1.tgz", 424 "resolved": "https://registry.npmjs.org/@slynova/flydrive/-/flydrive-0.3.1.tgz",
@@ -394,6 +461,12 @@
394 "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.0.0.tgz", 461 "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.0.0.tgz",
395 "integrity": "sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ==" 462 "integrity": "sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ=="
396 }, 463 },
464 "acorn-jsx": {
465 "version": "5.0.2",
466 "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.2.tgz",
467 "integrity": "sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw==",
468 "dev": true
469 },
397 "acorn-node": { 470 "acorn-node": {
398 "version": "1.8.2", 471 "version": "1.8.2",
399 "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", 472 "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz",
@@ -558,6 +631,12 @@
558 "ansi-wrap": "0.1.0" 631 "ansi-wrap": "0.1.0"
559 } 632 }
560 }, 633 },
634 "ansi-escapes": {
635 "version": "3.2.0",
636 "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
637 "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
638 "dev": true
639 },
561 "ansi-gray": { 640 "ansi-gray": {
562 "version": "0.1.1", 641 "version": "0.1.1",
563 "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", 642 "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz",
@@ -699,6 +778,25 @@
699 "readable-stream": "^2.0.6" 778 "readable-stream": "^2.0.6"
700 } 779 }
701 }, 780 },
781 "argparse": {
782 "version": "1.0.10",
783 "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
784 "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
785 "dev": true,
786 "requires": {
787 "sprintf-js": "~1.0.2"
788 }
789 },
790 "aria-query": {
791 "version": "3.0.0",
792 "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz",
793 "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=",
794 "dev": true,
795 "requires": {
796 "ast-types-flow": "0.0.7",
797 "commander": "^2.11.0"
798 }
799 },
702 "arr-diff": { 800 "arr-diff": {
703 "version": "4.0.0", 801 "version": "4.0.0",
704 "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", 802 "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
@@ -727,6 +825,16 @@
727 "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", 825 "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz",
728 "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=" 826 "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8="
729 }, 827 },
828 "array-includes": {
829 "version": "3.0.3",
830 "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz",
831 "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=",
832 "dev": true,
833 "requires": {
834 "define-properties": "^1.1.2",
835 "es-abstract": "^1.7.0"
836 }
837 },
730 "array-slice": { 838 "array-slice": {
731 "version": "1.1.0", 839 "version": "1.1.0",
732 "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", 840 "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz",
@@ -755,6 +863,18 @@
755 "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", 863 "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
756 "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" 864 "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c="
757 }, 865 },
866 "ast-types-flow": {
867 "version": "0.0.7",
868 "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
869 "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=",
870 "dev": true
871 },
872 "astral-regex": {
873 "version": "1.0.0",
874 "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
875 "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
876 "dev": true
877 },
758 "async": { 878 "async": {
759 "version": "2.6.3", 879 "version": "2.6.3",
760 "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", 880 "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz",
@@ -783,6 +903,15 @@
783 "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", 903 "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
784 "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" 904 "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
785 }, 905 },
906 "axobject-query": {
907 "version": "2.0.2",
908 "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz",
909 "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==",
910 "dev": true,
911 "requires": {
912 "ast-types-flow": "0.0.7"
913 }
914 },
786 "babel-runtime": { 915 "babel-runtime": {
787 "version": "6.26.0", 916 "version": "6.26.0",
788 "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", 917 "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
@@ -990,6 +1119,12 @@
990 "resolved": "https://registry.npmjs.org/chance/-/chance-1.0.18.tgz", 1119 "resolved": "https://registry.npmjs.org/chance/-/chance-1.0.18.tgz",
991 "integrity": "sha512-g9YLQVHVZS/3F+zIicfB58vjcxopvYQRp7xHzvyDFDhXH1aRZI/JhwSAO0X5qYiQluoGnaNAU6wByD2KTxJN1A==" 1120 "integrity": "sha512-g9YLQVHVZS/3F+zIicfB58vjcxopvYQRp7xHzvyDFDhXH1aRZI/JhwSAO0X5qYiQluoGnaNAU6wByD2KTxJN1A=="
992 }, 1121 },
1122 "chardet": {
1123 "version": "0.7.0",
1124 "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
1125 "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
1126 "dev": true
1127 },
993 "choices-separator": { 1128 "choices-separator": {
994 "version": "2.0.0", 1129 "version": "2.0.0",
995 "resolved": "https://registry.npmjs.org/choices-separator/-/choices-separator-2.0.0.tgz", 1130 "resolved": "https://registry.npmjs.org/choices-separator/-/choices-separator-2.0.0.tgz",
@@ -1077,6 +1212,15 @@
1077 } 1212 }
1078 } 1213 }
1079 }, 1214 },
1215 "cli-cursor": {
1216 "version": "2.1.0",
1217 "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
1218 "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
1219 "dev": true,
1220 "requires": {
1221 "restore-cursor": "^2.0.0"
1222 }
1223 },
1080 "cli-table": { 1224 "cli-table": {
1081 "version": "0.3.1", 1225 "version": "0.3.1",
1082 "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", 1226 "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz",
@@ -1085,6 +1229,12 @@
1085 "colors": "1.0.3" 1229 "colors": "1.0.3"
1086 } 1230 }
1087 }, 1231 },
1232 "cli-width": {
1233 "version": "2.2.0",
1234 "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
1235 "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
1236 "dev": true
1237 },
1088 "clone": { 1238 "clone": {
1089 "version": "2.1.2", 1239 "version": "2.1.2",
1090 "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", 1240 "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
@@ -1214,11 +1364,23 @@
1214 "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 1364 "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
1215 "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 1365 "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
1216 }, 1366 },
1367 "confusing-browser-globals": {
1368 "version": "1.0.8",
1369 "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.8.tgz",
1370 "integrity": "sha512-lI7asCibVJ6Qd3FGU7mu4sfG4try4LX3+GVS+Gv8UlrEf2AeW57piecapnog2UHZSbcX/P/1UDWVaTsblowlZg==",
1371 "dev": true
1372 },
1217 "console-control-strings": { 1373 "console-control-strings": {
1218 "version": "1.1.0", 1374 "version": "1.1.0",
1219 "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", 1375 "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
1220 "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" 1376 "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
1221 }, 1377 },
1378 "contains-path": {
1379 "version": "0.1.0",
1380 "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz",
1381 "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=",
1382 "dev": true
1383 },
1222 "content-disposition": { 1384 "content-disposition": {
1223 "version": "0.5.3", 1385 "version": "0.5.3",
1224 "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 1386 "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
@@ -1298,6 +1460,12 @@
1298 "uid-safe": "2.1.5" 1460 "uid-safe": "2.1.5"
1299 } 1461 }
1300 }, 1462 },
1463 "damerau-levenshtein": {
1464 "version": "1.0.5",
1465 "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.5.tgz",
1466 "integrity": "sha512-CBCRqFnpu715iPmw1KrdOrzRqbdFwQTwAWyyyYS42+iAgHCuXZ+/TdMgQkUENPomxEz9z1BEzuQU2Xw0kUuAgA==",
1467 "dev": true
1468 },
1301 "dashdash": { 1469 "dashdash": {
1302 "version": "1.14.1", 1470 "version": "1.14.1",
1303 "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 1471 "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@@ -1324,6 +1492,21 @@
1324 "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", 1492 "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
1325 "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" 1493 "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
1326 }, 1494 },
1495 "deep-is": {
1496 "version": "0.1.3",
1497 "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
1498 "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
1499 "dev": true
1500 },
1501 "define-properties": {
1502 "version": "1.1.3",
1503 "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
1504 "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
1505 "dev": true,
1506 "requires": {
1507 "object-keys": "^1.0.12"
1508 }
1509 },
1327 "define-property": { 1510 "define-property": {
1328 "version": "1.0.0", 1511 "version": "1.0.0",
1329 "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", 1512 "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
@@ -1372,6 +1555,15 @@
1372 "kuler": "1.0.x" 1555 "kuler": "1.0.x"
1373 } 1556 }
1374 }, 1557 },
1558 "doctrine": {
1559 "version": "3.0.0",
1560 "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
1561 "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
1562 "dev": true,
1563 "requires": {
1564 "esutils": "^2.0.2"
1565 }
1566 },
1375 "dotenv": { 1567 "dotenv": {
1376 "version": "6.2.0", 1568 "version": "6.2.0",
1377 "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz", 1569 "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz",
@@ -1430,6 +1622,12 @@
1430 "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 1622 "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
1431 "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 1623 "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
1432 }, 1624 },
1625 "emoji-regex": {
1626 "version": "7.0.3",
1627 "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
1628 "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
1629 "dev": true
1630 },
1433 "enabled": { 1631 "enabled": {
1434 "version": "1.0.2", 1632 "version": "1.0.2",
1435 "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", 1633 "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz",
@@ -1475,11 +1673,57 @@
1475 "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz", 1673 "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz",
1476 "integrity": "sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA==" 1674 "integrity": "sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA=="
1477 }, 1675 },
1676 "error-ex": {
1677 "version": "1.3.2",
1678 "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
1679 "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
1680 "dev": true,
1681 "requires": {
1682 "is-arrayish": "^0.2.1"
1683 },
1684 "dependencies": {
1685 "is-arrayish": {
1686 "version": "0.2.1",
1687 "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
1688 "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
1689 "dev": true
1690 }
1691 }
1692 },
1478 "error-symbol": { 1693 "error-symbol": {
1479 "version": "0.1.0", 1694 "version": "0.1.0",
1480 "resolved": "https://registry.npmjs.org/error-symbol/-/error-symbol-0.1.0.tgz", 1695 "resolved": "https://registry.npmjs.org/error-symbol/-/error-symbol-0.1.0.tgz",
1481 "integrity": "sha1-Ck2uN9YA0VopukU9jvkg8YRDM/Y=" 1696 "integrity": "sha1-Ck2uN9YA0VopukU9jvkg8YRDM/Y="
1482 }, 1697 },
1698 "es-abstract": {
1699 "version": "1.14.1",
1700 "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.14.1.tgz",
1701 "integrity": "sha512-cp/Tb1oA/rh2X7vqeSOvM+TSo3UkJLX70eNihgVEvnzwAgikjkTFr/QVgRCaxjm0knCNQzNoxxxcw2zO2LJdZA==",
1702 "dev": true,
1703 "requires": {
1704 "es-to-primitive": "^1.2.0",
1705 "function-bind": "^1.1.1",
1706 "has": "^1.0.3",
1707 "has-symbols": "^1.0.0",
1708 "is-callable": "^1.1.4",
1709 "is-regex": "^1.0.4",
1710 "object-inspect": "^1.6.0",
1711 "object-keys": "^1.1.1",
1712 "string.prototype.trimleft": "^2.0.0",
1713 "string.prototype.trimright": "^2.0.0"
1714 }
1715 },
1716 "es-to-primitive": {
1717 "version": "1.2.0",
1718 "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
1719 "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
1720 "dev": true,
1721 "requires": {
1722 "is-callable": "^1.1.4",
1723 "is-date-object": "^1.0.1",
1724 "is-symbol": "^1.0.2"
1725 }
1726 },
1483 "escape-html": { 1727 "escape-html": {
1484 "version": "1.0.3", 1728 "version": "1.0.3",
1485 "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 1729 "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
@@ -1490,11 +1734,299 @@
1490 "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 1734 "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
1491 "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 1735 "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
1492 }, 1736 },
1737 "eslint": {
1738 "version": "6.3.0",
1739 "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.3.0.tgz",
1740 "integrity": "sha512-ZvZTKaqDue+N8Y9g0kp6UPZtS4FSY3qARxBs7p4f0H0iof381XHduqVerFWtK8DPtKmemqbqCFENWSQgPR/Gow==",
1741 "dev": true,
1742 "requires": {
1743 "@babel/code-frame": "^7.0.0",
1744 "ajv": "^6.10.0",
1745 "chalk": "^2.1.0",
1746 "cross-spawn": "^6.0.5",
1747 "debug": "^4.0.1",
1748 "doctrine": "^3.0.0",
1749 "eslint-scope": "^5.0.0",
1750 "eslint-utils": "^1.4.2",
1751 "eslint-visitor-keys": "^1.1.0",
1752 "espree": "^6.1.1",
1753 "esquery": "^1.0.1",
1754 "esutils": "^2.0.2",
1755 "file-entry-cache": "^5.0.1",
1756 "functional-red-black-tree": "^1.0.1",
1757 "glob-parent": "^5.0.0",
1758 "globals": "^11.7.0",
1759 "ignore": "^4.0.6",
1760 "import-fresh": "^3.0.0",
1761 "imurmurhash": "^0.1.4",
1762 "inquirer": "^6.4.1",
1763 "is-glob": "^4.0.0",
1764 "js-yaml": "^3.13.1",
1765 "json-stable-stringify-without-jsonify": "^1.0.1",
1766 "levn": "^0.3.0",
1767 "lodash": "^4.17.14",
1768 "minimatch": "^3.0.4",
1769 "mkdirp": "^0.5.1",
1770 "natural-compare": "^1.4.0",
1771 "optionator": "^0.8.2",
1772 "progress": "^2.0.0",
1773 "regexpp": "^2.0.1",
1774 "semver": "^6.1.2",
1775 "strip-ansi": "^5.2.0",
1776 "strip-json-comments": "^3.0.1",
1777 "table": "^5.2.3",
1778 "text-table": "^0.2.0",
1779 "v8-compile-cache": "^2.0.3"
1780 },
1781 "dependencies": {
1782 "ansi-regex": {
1783 "version": "4.1.0",
1784 "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
1785 "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
1786 "dev": true
1787 },
1788 "debug": {
1789 "version": "4.1.1",
1790 "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
1791 "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
1792 "dev": true,
1793 "requires": {
1794 "ms": "^2.1.1"
1795 }
1796 },
1797 "is-glob": {
1798 "version": "4.0.1",
1799 "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
1800 "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
1801 "dev": true,
1802 "requires": {
1803 "is-extglob": "^2.1.1"
1804 }
1805 },
1806 "ms": {
1807 "version": "2.1.2",
1808 "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
1809 "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
1810 "dev": true
1811 },
1812 "semver": {
1813 "version": "6.3.0",
1814 "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
1815 "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
1816 "dev": true
1817 },
1818 "strip-ansi": {
1819 "version": "5.2.0",
1820 "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
1821 "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
1822 "dev": true,
1823 "requires": {
1824 "ansi-regex": "^4.1.0"
1825 }
1826 },
1827 "strip-json-comments": {
1828 "version": "3.0.1",
1829 "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz",
1830 "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==",
1831 "dev": true
1832 }
1833 }
1834 },
1835 "eslint-config-airbnb": {
1836 "version": "18.0.1",
1837 "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-18.0.1.tgz",
1838 "integrity": "sha512-hLb/ccvW4grVhvd6CT83bECacc+s4Z3/AEyWQdIT2KeTsG9dR7nx1gs7Iw4tDmGKozCNHFn4yZmRm3Tgy+XxyQ==",
1839 "dev": true,
1840 "requires": {
1841 "eslint-config-airbnb-base": "^14.0.0",
1842 "object.assign": "^4.1.0",
1843 "object.entries": "^1.1.0"
1844 }
1845 },
1846 "eslint-config-airbnb-base": {
1847 "version": "14.0.0",
1848 "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.0.0.tgz",
1849 "integrity": "sha512-2IDHobw97upExLmsebhtfoD3NAKhV4H0CJWP3Uprd/uk+cHuWYOczPVxQ8PxLFUAw7o3Th1RAU8u1DoUpr+cMA==",
1850 "dev": true,
1851 "requires": {
1852 "confusing-browser-globals": "^1.0.7",
1853 "object.assign": "^4.1.0",
1854 "object.entries": "^1.1.0"
1855 }
1856 },
1857 "eslint-import-resolver-node": {
1858 "version": "0.3.2",
1859 "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz",
1860 "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==",
1861 "dev": true,
1862 "requires": {
1863 "debug": "^2.6.9",
1864 "resolve": "^1.5.0"
1865 }
1866 },
1867 "eslint-module-utils": {
1868 "version": "2.4.1",
1869 "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz",
1870 "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==",
1871 "dev": true,
1872 "requires": {
1873 "debug": "^2.6.8",
1874 "pkg-dir": "^2.0.0"
1875 }
1876 },
1877 "eslint-plugin-import": {
1878 "version": "2.18.2",
1879 "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz",
1880 "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==",
1881 "dev": true,
1882 "requires": {
1883 "array-includes": "^3.0.3",
1884 "contains-path": "^0.1.0",
1885 "debug": "^2.6.9",
1886 "doctrine": "1.5.0",
1887 "eslint-import-resolver-node": "^0.3.2",
1888 "eslint-module-utils": "^2.4.0",
1889 "has": "^1.0.3",
1890 "minimatch": "^3.0.4",
1891 "object.values": "^1.1.0",
1892 "read-pkg-up": "^2.0.0",
1893 "resolve": "^1.11.0"
1894 },
1895 "dependencies": {
1896 "doctrine": {
1897 "version": "1.5.0",
1898 "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
1899 "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
1900 "dev": true,
1901 "requires": {
1902 "esutils": "^2.0.2",
1903 "isarray": "^1.0.0"
1904 }
1905 }
1906 }
1907 },
1908 "eslint-plugin-jsx-a11y": {
1909 "version": "6.2.3",
1910 "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.2.3.tgz",
1911 "integrity": "sha512-CawzfGt9w83tyuVekn0GDPU9ytYtxyxyFZ3aSWROmnRRFQFT2BiPJd7jvRdzNDi6oLWaS2asMeYSNMjWTV4eNg==",
1912 "dev": true,
1913 "requires": {
1914 "@babel/runtime": "^7.4.5",
1915 "aria-query": "^3.0.0",
1916 "array-includes": "^3.0.3",
1917 "ast-types-flow": "^0.0.7",
1918 "axobject-query": "^2.0.2",
1919 "damerau-levenshtein": "^1.0.4",
1920 "emoji-regex": "^7.0.2",
1921 "has": "^1.0.3",
1922 "jsx-ast-utils": "^2.2.1"
1923 }
1924 },
1925 "eslint-plugin-react": {
1926 "version": "7.14.3",
1927 "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.14.3.tgz",
1928 "integrity": "sha512-EzdyyBWC4Uz2hPYBiEJrKCUi2Fn+BJ9B/pJQcjw5X+x/H2Nm59S4MJIvL4O5NEE0+WbnQwEBxWY03oUk+Bc3FA==",
1929 "dev": true,
1930 "requires": {
1931 "array-includes": "^3.0.3",
1932 "doctrine": "^2.1.0",
1933 "has": "^1.0.3",
1934 "jsx-ast-utils": "^2.1.0",
1935 "object.entries": "^1.1.0",
1936 "object.fromentries": "^2.0.0",
1937 "object.values": "^1.1.0",
1938 "prop-types": "^15.7.2",
1939 "resolve": "^1.10.1"
1940 },
1941 "dependencies": {
1942 "doctrine": {
1943 "version": "2.1.0",
1944 "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
1945 "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
1946 "dev": true,
1947 "requires": {
1948 "esutils": "^2.0.2"
1949 }
1950 }
1951 }
1952 },
1953 "eslint-plugin-react-hooks": {
1954 "version": "1.7.0",
1955 "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-1.7.0.tgz",
1956 "integrity": "sha512-iXTCFcOmlWvw4+TOE8CLWj6yX1GwzT0Y6cUfHHZqWnSk144VmVIRcVGtUAzrLES7C798lmvnt02C7rxaOX1HNA==",
1957 "dev": true
1958 },
1959 "eslint-scope": {
1960 "version": "5.0.0",
1961 "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz",
1962 "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==",
1963 "dev": true,
1964 "requires": {
1965 "esrecurse": "^4.1.0",
1966 "estraverse": "^4.1.1"
1967 }
1968 },
1969 "eslint-utils": {
1970 "version": "1.4.2",
1971 "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz",
1972 "integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==",
1973 "dev": true,
1974 "requires": {
1975 "eslint-visitor-keys": "^1.0.0"
1976 }
1977 },
1978 "eslint-visitor-keys": {
1979 "version": "1.1.0",
1980 "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
1981 "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==",
1982 "dev": true
1983 },
1984 "espree": {
1985 "version": "6.1.1",
1986 "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.1.tgz",
1987 "integrity": "sha512-EYbr8XZUhWbYCqQRW0duU5LxzL5bETN6AjKBGy1302qqzPaCH10QbRg3Wvco79Z8x9WbiE8HYB4e75xl6qUYvQ==",
1988 "dev": true,
1989 "requires": {
1990 "acorn": "^7.0.0",
1991 "acorn-jsx": "^5.0.2",
1992 "eslint-visitor-keys": "^1.1.0"
1993 }
1994 },
1493 "esprima": { 1995 "esprima": {
1494 "version": "4.0.1", 1996 "version": "4.0.1",
1495 "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 1997 "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
1496 "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" 1998 "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
1497 }, 1999 },
2000 "esquery": {
2001 "version": "1.0.1",
2002 "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz",
2003 "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==",
2004 "dev": true,
2005 "requires": {
2006 "estraverse": "^4.0.0"
2007 }
2008 },
2009 "esrecurse": {
2010 "version": "4.2.1",
2011 "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
2012 "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
2013 "dev": true,
2014 "requires": {
2015 "estraverse": "^4.1.0"
2016 }
2017 },
2018 "estraverse": {
2019 "version": "4.3.0",
2020 "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
2021 "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
2022 "dev": true
2023 },
2024 "esutils": {
2025 "version": "2.0.3",
2026 "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
2027 "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
2028 "dev": true
2029 },
1498 "etag": { 2030 "etag": {
1499 "version": "1.8.1", 2031 "version": "1.8.1",
1500 "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 2032 "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
@@ -1601,6 +2133,17 @@
1601 "is-extendable": "^0.1.0" 2133 "is-extendable": "^0.1.0"
1602 } 2134 }
1603 }, 2135 },
2136 "external-editor": {
2137 "version": "3.1.0",
2138 "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
2139 "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
2140 "dev": true,
2141 "requires": {
2142 "chardet": "^0.7.0",
2143 "iconv-lite": "^0.4.24",
2144 "tmp": "^0.0.33"
2145 }
2146 },
1604 "extglob": { 2147 "extglob": {
1605 "version": "2.0.4", 2148 "version": "2.0.4",
1606 "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", 2149 "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
@@ -1654,6 +2197,24 @@
1654 "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", 2197 "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz",
1655 "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==" 2198 "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg=="
1656 }, 2199 },
2200 "figures": {
2201 "version": "2.0.0",
2202 "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
2203 "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
2204 "dev": true,
2205 "requires": {
2206 "escape-string-regexp": "^1.0.5"
2207 }
2208 },
2209 "file-entry-cache": {
2210 "version": "5.0.1",
2211 "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
2212 "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
2213 "dev": true,
2214 "requires": {
2215 "flat-cache": "^2.0.1"
2216 }
2217 },
1657 "fill-range": { 2218 "fill-range": {
1658 "version": "4.0.0", 2219 "version": "4.0.0",
1659 "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", 2220 "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
@@ -1665,6 +2226,15 @@
1665 "to-regex-range": "^2.1.0" 2226 "to-regex-range": "^2.1.0"
1666 } 2227 }
1667 }, 2228 },
2229 "find-up": {
2230 "version": "2.1.0",
2231 "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
2232 "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
2233 "dev": true,
2234 "requires": {
2235 "locate-path": "^2.0.0"
2236 }
2237 },
1668 "findup-sync": { 2238 "findup-sync": {
1669 "version": "2.0.0", 2239 "version": "2.0.0",
1670 "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", 2240 "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz",
@@ -1693,6 +2263,34 @@
1693 "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", 2263 "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz",
1694 "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==" 2264 "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q=="
1695 }, 2265 },
2266 "flat-cache": {
2267 "version": "2.0.1",
2268 "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
2269 "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
2270 "dev": true,
2271 "requires": {
2272 "flatted": "^2.0.0",
2273 "rimraf": "2.6.3",
2274 "write": "1.0.3"
2275 },
2276 "dependencies": {
2277 "rimraf": {
2278 "version": "2.6.3",
2279 "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
2280 "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
2281 "dev": true,
2282 "requires": {
2283 "glob": "^7.1.3"
2284 }
2285 }
2286 }
2287 },
2288 "flatted": {
2289 "version": "2.0.1",
2290 "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz",
2291 "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==",
2292 "dev": true
2293 },
1696 "for-in": { 2294 "for-in": {
1697 "version": "1.0.2", 2295 "version": "1.0.2",
1698 "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", 2296 "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@@ -1745,11 +2343,11 @@
1745 "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" 2343 "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
1746 }, 2344 },
1747 "fs-extra": { 2345 "fs-extra": {
1748 "version": "7.0.1", 2346 "version": "8.1.0",
1749 "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", 2347 "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
1750 "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", 2348 "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
1751 "requires": { 2349 "requires": {
1752 "graceful-fs": "^4.1.2", 2350 "graceful-fs": "^4.2.0",
1753 "jsonfile": "^4.0.0", 2351 "jsonfile": "^4.0.0",
1754 "universalify": "^0.1.0" 2352 "universalify": "^0.1.0"
1755 } 2353 }
@@ -1767,6 +2365,18 @@
1767 "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 2365 "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
1768 "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 2366 "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
1769 }, 2367 },
2368 "function-bind": {
2369 "version": "1.1.1",
2370 "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
2371 "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
2372 "dev": true
2373 },
2374 "functional-red-black-tree": {
2375 "version": "1.0.1",
2376 "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
2377 "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
2378 "dev": true
2379 },
1770 "gauge": { 2380 "gauge": {
1771 "version": "2.7.4", 2381 "version": "2.7.4",
1772 "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", 2382 "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
@@ -1836,6 +2446,26 @@
1836 "path-is-absolute": "^1.0.0" 2446 "path-is-absolute": "^1.0.0"
1837 } 2447 }
1838 }, 2448 },
2449 "glob-parent": {
2450 "version": "5.0.0",
2451 "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.0.0.tgz",
2452 "integrity": "sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==",
2453 "dev": true,
2454 "requires": {
2455 "is-glob": "^4.0.1"
2456 },
2457 "dependencies": {
2458 "is-glob": {
2459 "version": "4.0.1",
2460 "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
2461 "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
2462 "dev": true,
2463 "requires": {
2464 "is-extglob": "^2.1.1"
2465 }
2466 }
2467 }
2468 },
1839 "global-modules": { 2469 "global-modules": {
1840 "version": "1.0.0", 2470 "version": "1.0.0",
1841 "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", 2471 "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
@@ -1858,6 +2488,12 @@
1858 "which": "^1.2.14" 2488 "which": "^1.2.14"
1859 } 2489 }
1860 }, 2490 },
2491 "globals": {
2492 "version": "11.12.0",
2493 "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
2494 "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
2495 "dev": true
2496 },
1861 "graceful-fs": { 2497 "graceful-fs": {
1862 "version": "4.2.2", 2498 "version": "4.2.2",
1863 "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", 2499 "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz",
@@ -1877,11 +2513,26 @@
1877 "har-schema": "^2.0.0" 2513 "har-schema": "^2.0.0"
1878 } 2514 }
1879 }, 2515 },
2516 "has": {
2517 "version": "1.0.3",
2518 "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
2519 "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
2520 "dev": true,
2521 "requires": {
2522 "function-bind": "^1.1.1"
2523 }
2524 },
1880 "has-flag": { 2525 "has-flag": {
1881 "version": "3.0.0", 2526 "version": "3.0.0",
1882 "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 2527 "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
1883 "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 2528 "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
1884 }, 2529 },
2530 "has-symbols": {
2531 "version": "1.0.0",
2532 "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
2533 "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
2534 "dev": true
2535 },
1885 "has-unicode": { 2536 "has-unicode": {
1886 "version": "2.0.1", 2537 "version": "2.0.1",
1887 "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", 2538 "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
@@ -1929,6 +2580,12 @@
1929 "parse-passwd": "^1.0.0" 2580 "parse-passwd": "^1.0.0"
1930 } 2581 }
1931 }, 2582 },
2583 "hosted-git-info": {
2584 "version": "2.8.4",
2585 "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.4.tgz",
2586 "integrity": "sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ==",
2587 "dev": true
2588 },
1932 "http-errors": { 2589 "http-errors": {
1933 "version": "1.7.3", 2590 "version": "1.7.3",
1934 "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", 2591 "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz",
@@ -1959,6 +2616,12 @@
1959 "safer-buffer": ">= 2.1.2 < 3" 2616 "safer-buffer": ">= 2.1.2 < 3"
1960 } 2617 }
1961 }, 2618 },
2619 "ignore": {
2620 "version": "4.0.6",
2621 "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
2622 "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
2623 "dev": true
2624 },
1962 "ignore-walk": { 2625 "ignore-walk": {
1963 "version": "3.0.1", 2626 "version": "3.0.1",
1964 "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", 2627 "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz",
@@ -1967,6 +2630,30 @@
1967 "minimatch": "^3.0.4" 2630 "minimatch": "^3.0.4"
1968 } 2631 }
1969 }, 2632 },
2633 "import-fresh": {
2634 "version": "3.1.0",
2635 "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz",
2636 "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==",
2637 "dev": true,
2638 "requires": {
2639 "parent-module": "^1.0.0",
2640 "resolve-from": "^4.0.0"
2641 },
2642 "dependencies": {
2643 "resolve-from": {
2644 "version": "4.0.0",
2645 "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
2646 "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
2647 "dev": true
2648 }
2649 }
2650 },
2651 "imurmurhash": {
2652 "version": "0.1.4",
2653 "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
2654 "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
2655 "dev": true
2656 },
1970 "indent-string": { 2657 "indent-string": {
1971 "version": "3.2.0", 2658 "version": "3.2.0",
1972 "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", 2659 "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz",
@@ -2006,6 +2693,55 @@
2006 "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", 2693 "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
2007 "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" 2694 "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
2008 }, 2695 },
2696 "inquirer": {
2697 "version": "6.5.2",
2698 "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz",
2699 "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==",
2700 "dev": true,
2701 "requires": {
2702 "ansi-escapes": "^3.2.0",
2703 "chalk": "^2.4.2",
2704 "cli-cursor": "^2.1.0",
2705 "cli-width": "^2.0.0",
2706 "external-editor": "^3.0.3",
2707 "figures": "^2.0.0",
2708 "lodash": "^4.17.12",
2709 "mute-stream": "0.0.7",
2710 "run-async": "^2.2.0",
2711 "rxjs": "^6.4.0",
2712 "string-width": "^2.1.0",
2713 "strip-ansi": "^5.1.0",
2714 "through": "^2.3.6"
2715 },
2716 "dependencies": {
2717 "ansi-regex": {
2718 "version": "4.1.0",
2719 "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
2720 "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
2721 "dev": true
2722 },
2723 "chalk": {
2724 "version": "2.4.2",
2725 "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
2726 "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
2727 "dev": true,
2728 "requires": {
2729 "ansi-styles": "^3.2.1",
2730 "escape-string-regexp": "^1.0.5",
2731 "supports-color": "^5.3.0"
2732 }
2733 },
2734 "strip-ansi": {
2735 "version": "5.2.0",
2736 "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
2737 "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
2738 "dev": true,
2739 "requires": {
2740 "ansi-regex": "^4.1.0"
2741 }
2742 }
2743 }
2744 },
2009 "interpret": { 2745 "interpret": {
2010 "version": "1.2.0", 2746 "version": "1.2.0",
2011 "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", 2747 "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz",
@@ -2064,6 +2800,12 @@
2064 "kind-of": "^6.0.0" 2800 "kind-of": "^6.0.0"
2065 } 2801 }
2066 }, 2802 },
2803 "is-date-object": {
2804 "version": "1.0.1",
2805 "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
2806 "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
2807 "dev": true
2808 },
2067 "is-descriptor": { 2809 "is-descriptor": {
2068 "version": "1.0.2", 2810 "version": "1.0.2",
2069 "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", 2811 "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
@@ -2123,6 +2865,21 @@
2123 "isobject": "^3.0.1" 2865 "isobject": "^3.0.1"
2124 } 2866 }
2125 }, 2867 },
2868 "is-promise": {
2869 "version": "2.1.0",
2870 "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
2871 "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
2872 "dev": true
2873 },
2874 "is-regex": {
2875 "version": "1.0.4",
2876 "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
2877 "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
2878 "dev": true,
2879 "requires": {
2880 "has": "^1.0.1"
2881 }
2882 },
2126 "is-relative": { 2883 "is-relative": {
2127 "version": "1.0.0", 2884 "version": "1.0.0",
2128 "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", 2885 "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
@@ -2136,6 +2893,15 @@
2136 "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 2893 "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
2137 "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" 2894 "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
2138 }, 2895 },
2896 "is-symbol": {
2897 "version": "1.0.2",
2898 "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
2899 "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
2900 "dev": true,
2901 "requires": {
2902 "has-symbols": "^1.0.0"
2903 }
2904 },
2139 "is-typedarray": { 2905 "is-typedarray": {
2140 "version": "1.0.0", 2906 "version": "1.0.0",
2141 "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 2907 "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
@@ -2174,6 +2940,22 @@
2174 "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 2940 "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
2175 "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 2941 "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
2176 }, 2942 },
2943 "js-tokens": {
2944 "version": "4.0.0",
2945 "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
2946 "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
2947 "dev": true
2948 },
2949 "js-yaml": {
2950 "version": "3.13.1",
2951 "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
2952 "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
2953 "dev": true,
2954 "requires": {
2955 "argparse": "^1.0.7",
2956 "esprima": "^4.0.0"
2957 }
2958 },
2177 "jsbn": { 2959 "jsbn": {
2178 "version": "0.1.1", 2960 "version": "0.1.1",
2179 "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 2961 "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
@@ -2189,6 +2971,12 @@
2189 "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 2971 "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
2190 "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" 2972 "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
2191 }, 2973 },
2974 "json-stable-stringify-without-jsonify": {
2975 "version": "1.0.1",
2976 "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
2977 "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
2978 "dev": true
2979 },
2192 "json-stringify-safe": { 2980 "json-stringify-safe": {
2193 "version": "5.0.1", 2981 "version": "5.0.1",
2194 "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 2982 "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
@@ -2237,6 +3025,16 @@
2237 "verror": "1.10.0" 3025 "verror": "1.10.0"
2238 } 3026 }
2239 }, 3027 },
3028 "jsx-ast-utils": {
3029 "version": "2.2.1",
3030 "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.2.1.tgz",
3031 "integrity": "sha512-v3FxCcAf20DayI+uxnCuw795+oOIkVu6EnJ1+kSzhqqTZHNkTZ7B66ZgLp4oLJ/gbA64cI0B7WRoHZMSRdyVRQ==",
3032 "dev": true,
3033 "requires": {
3034 "array-includes": "^3.0.3",
3035 "object.assign": "^4.1.0"
3036 }
3037 },
2240 "jwa": { 3038 "jwa": {
2241 "version": "1.4.1", 3039 "version": "1.4.1",
2242 "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", 3040 "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
@@ -2330,6 +3128,16 @@
2330 "set-getter": "^0.1.0" 3128 "set-getter": "^0.1.0"
2331 } 3129 }
2332 }, 3130 },
3131 "levn": {
3132 "version": "0.3.0",
3133 "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
3134 "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
3135 "dev": true,
3136 "requires": {
3137 "prelude-ls": "~1.1.2",
3138 "type-check": "~0.3.2"
3139 }
3140 },
2333 "liftoff": { 3141 "liftoff": {
2334 "version": "2.5.0", 3142 "version": "2.5.0",
2335 "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", 3143 "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz",
@@ -2345,6 +3153,36 @@
2345 "resolve": "^1.1.7" 3153 "resolve": "^1.1.7"
2346 } 3154 }
2347 }, 3155 },
3156 "load-json-file": {
3157 "version": "2.0.0",
3158 "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
3159 "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
3160 "dev": true,
3161 "requires": {
3162 "graceful-fs": "^4.1.2",
3163 "parse-json": "^2.2.0",
3164 "pify": "^2.0.0",
3165 "strip-bom": "^3.0.0"
3166 },
3167 "dependencies": {
3168 "pify": {
3169 "version": "2.3.0",
3170 "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
3171 "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
3172 "dev": true
3173 }
3174 }
3175 },
3176 "locate-path": {
3177 "version": "2.0.0",
3178 "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
3179 "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
3180 "dev": true,
3181 "requires": {
3182 "p-locate": "^2.0.0",
3183 "path-exists": "^3.0.0"
3184 }
3185 },
2348 "lodash": { 3186 "lodash": {
2349 "version": "4.17.15", 3187 "version": "4.17.15",
2350 "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 3188 "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
@@ -2432,6 +3270,15 @@
2432 } 3270 }
2433 } 3271 }
2434 }, 3272 },
3273 "loose-envify": {
3274 "version": "1.4.0",
3275 "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
3276 "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
3277 "dev": true,
3278 "requires": {
3279 "js-tokens": "^3.0.0 || ^4.0.0"
3280 }
3281 },
2435 "lru-cache": { 3282 "lru-cache": {
2436 "version": "4.1.5", 3283 "version": "4.1.5",
2437 "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", 3284 "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
@@ -2555,6 +3402,12 @@
2555 "mime-db": "1.40.0" 3402 "mime-db": "1.40.0"
2556 } 3403 }
2557 }, 3404 },
3405 "mimic-fn": {
3406 "version": "1.2.0",
3407 "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
3408 "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
3409 "dev": true
3410 },
2558 "minimatch": { 3411 "minimatch": {
2559 "version": "3.0.4", 3412 "version": "3.0.4",
2560 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 3413 "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@@ -2724,6 +3577,12 @@
2724 } 3577 }
2725 } 3578 }
2726 }, 3579 },
3580 "natural-compare": {
3581 "version": "1.4.0",
3582 "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
3583 "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
3584 "dev": true
3585 },
2727 "needle": { 3586 "needle": {
2728 "version": "2.4.0", 3587 "version": "2.4.0",
2729 "resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz", 3588 "resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz",
@@ -2853,6 +3712,18 @@
2853 "osenv": "^0.1.4" 3712 "osenv": "^0.1.4"
2854 } 3713 }
2855 }, 3714 },
3715 "normalize-package-data": {
3716 "version": "2.5.0",
3717 "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
3718 "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
3719 "dev": true,
3720 "requires": {
3721 "hosted-git-info": "^2.1.4",
3722 "resolve": "^1.10.0",
3723 "semver": "2 || 3 || 4 || 5",
3724 "validate-npm-package-license": "^3.0.1"
3725 }
3726 },
2856 "npm-bundled": { 3727 "npm-bundled": {
2857 "version": "1.0.6", 3728 "version": "1.0.6",
2858 "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz", 3729 "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz",
@@ -2954,6 +3825,18 @@
2954 } 3825 }
2955 } 3826 }
2956 }, 3827 },
3828 "object-inspect": {
3829 "version": "1.6.0",
3830 "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz",
3831 "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==",
3832 "dev": true
3833 },
3834 "object-keys": {
3835 "version": "1.1.1",
3836 "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
3837 "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
3838 "dev": true
3839 },
2957 "object-visit": { 3840 "object-visit": {
2958 "version": "1.0.1", 3841 "version": "1.0.1",
2959 "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", 3842 "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
@@ -2962,6 +3845,18 @@
2962 "isobject": "^3.0.0" 3845 "isobject": "^3.0.0"
2963 } 3846 }
2964 }, 3847 },
3848 "object.assign": {
3849 "version": "4.1.0",
3850 "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
3851 "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
3852 "dev": true,
3853 "requires": {
3854 "define-properties": "^1.1.2",
3855 "function-bind": "^1.1.1",
3856 "has-symbols": "^1.0.0",
3857 "object-keys": "^1.0.11"
3858 }
3859 },
2965 "object.defaults": { 3860 "object.defaults": {
2966 "version": "1.1.0", 3861 "version": "1.1.0",
2967 "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", 3862 "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz",
@@ -2973,6 +3868,30 @@
2973 "isobject": "^3.0.0" 3868 "isobject": "^3.0.0"
2974 } 3869 }
2975 }, 3870 },
3871 "object.entries": {
3872 "version": "1.1.0",
3873 "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz",
3874 "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==",
3875 "dev": true,
3876 "requires": {
3877 "define-properties": "^1.1.3",
3878 "es-abstract": "^1.12.0",
3879 "function-bind": "^1.1.1",
3880 "has": "^1.0.3"
3881 }
3882 },
3883 "object.fromentries": {
3884 "version": "2.0.0",
3885 "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.0.tgz",
3886 "integrity": "sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA==",
3887 "dev": true,
3888 "requires": {
3889 "define-properties": "^1.1.2",
3890 "es-abstract": "^1.11.0",
3891 "function-bind": "^1.1.1",
3892 "has": "^1.0.1"
3893 }
3894 },
2976 "object.map": { 3895 "object.map": {
2977 "version": "1.0.1", 3896 "version": "1.0.1",
2978 "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", 3897 "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz",
@@ -2990,6 +3909,18 @@
2990 "isobject": "^3.0.1" 3909 "isobject": "^3.0.1"
2991 } 3910 }
2992 }, 3911 },
3912 "object.values": {
3913 "version": "1.1.0",
3914 "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz",
3915 "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==",
3916 "dev": true,
3917 "requires": {
3918 "define-properties": "^1.1.3",
3919 "es-abstract": "^1.12.0",
3920 "function-bind": "^1.1.1",
3921 "has": "^1.0.3"
3922 }
3923 },
2993 "on-finished": { 3924 "on-finished": {
2994 "version": "2.3.0", 3925 "version": "2.3.0",
2995 "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 3926 "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
@@ -3011,6 +3942,29 @@
3011 "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", 3942 "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz",
3012 "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=" 3943 "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4="
3013 }, 3944 },
3945 "onetime": {
3946 "version": "2.0.1",
3947 "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
3948 "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
3949 "dev": true,
3950 "requires": {
3951 "mimic-fn": "^1.0.0"
3952 }
3953 },
3954 "optionator": {
3955 "version": "0.8.2",
3956 "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz",
3957 "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=",
3958 "dev": true,
3959 "requires": {
3960 "deep-is": "~0.1.3",
3961 "fast-levenshtein": "~2.0.4",
3962 "levn": "~0.3.0",
3963 "prelude-ls": "~1.1.2",
3964 "type-check": "~0.3.2",
3965 "wordwrap": "~1.0.0"
3966 }
3967 },
3014 "os-homedir": { 3968 "os-homedir": {
3015 "version": "1.0.2", 3969 "version": "1.0.2",
3016 "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", 3970 "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
@@ -3030,11 +3984,52 @@
3030 "os-tmpdir": "^1.0.0" 3984 "os-tmpdir": "^1.0.0"
3031 } 3985 }
3032 }, 3986 },
3987 "p-limit": {
3988 "version": "1.3.0",
3989 "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
3990 "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
3991 "dev": true,
3992 "requires": {
3993 "p-try": "^1.0.0"
3994 }
3995 },
3996 "p-locate": {
3997 "version": "2.0.0",
3998 "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
3999 "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
4000 "dev": true,
4001 "requires": {
4002 "p-limit": "^1.1.0"
4003 }
4004 },
4005 "p-try": {
4006 "version": "1.0.0",
4007 "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
4008 "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
4009 "dev": true
4010 },
3033 "packet-reader": { 4011 "packet-reader": {
3034 "version": "1.0.0", 4012 "version": "1.0.0",
3035 "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", 4013 "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
3036 "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" 4014 "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ=="
3037 }, 4015 },
4016 "parent-module": {
4017 "version": "1.0.1",
4018 "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
4019 "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
4020 "dev": true,
4021 "requires": {
4022 "callsites": "^3.0.0"
4023 },
4024 "dependencies": {
4025 "callsites": {
4026 "version": "3.1.0",
4027 "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
4028 "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
4029 "dev": true
4030 }
4031 }
4032 },
3038 "parse-filepath": { 4033 "parse-filepath": {
3039 "version": "1.0.2", 4034 "version": "1.0.2",
3040 "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", 4035 "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz",
@@ -3045,6 +4040,15 @@
3045 "path-root": "^0.1.1" 4040 "path-root": "^0.1.1"
3046 } 4041 }
3047 }, 4042 },
4043 "parse-json": {
4044 "version": "2.2.0",
4045 "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
4046 "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
4047 "dev": true,
4048 "requires": {
4049 "error-ex": "^1.2.0"
4050 }
4051 },
3048 "parse-passwd": { 4052 "parse-passwd": {
3049 "version": "1.0.0", 4053 "version": "1.0.0",
3050 "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", 4054 "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
@@ -3060,6 +4064,12 @@
3060 "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", 4064 "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
3061 "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" 4065 "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ="
3062 }, 4066 },
4067 "path-exists": {
4068 "version": "3.0.0",
4069 "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
4070 "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
4071 "dev": true
4072 },
3063 "path-is-absolute": { 4073 "path-is-absolute": {
3064 "version": "1.0.1", 4074 "version": "1.0.1",
3065 "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 4075 "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
@@ -3093,6 +4103,23 @@
3093 "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.4.0.tgz", 4103 "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.4.0.tgz",
3094 "integrity": "sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w==" 4104 "integrity": "sha512-G6zHoVqC6GGTQkZwF4lkuEyMbVOjoBKAEybQUypI1WTkqinCOrq2x6U2+phkJ1XsEMTy4LjtwPI7HW+NVrRR2w=="
3095 }, 4105 },
4106 "path-type": {
4107 "version": "2.0.0",
4108 "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
4109 "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
4110 "dev": true,
4111 "requires": {
4112 "pify": "^2.0.0"
4113 },
4114 "dependencies": {
4115 "pify": {
4116 "version": "2.3.0",
4117 "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
4118 "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
4119 "dev": true
4120 }
4121 }
4122 },
3096 "pend": { 4123 "pend": {
3097 "version": "1.2.0", 4124 "version": "1.2.0",
3098 "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", 4125 "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
@@ -3164,6 +4191,15 @@
3164 "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", 4191 "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
3165 "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" 4192 "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="
3166 }, 4193 },
4194 "pkg-dir": {
4195 "version": "2.0.0",
4196 "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
4197 "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
4198 "dev": true,
4199 "requires": {
4200 "find-up": "^2.1.0"
4201 }
4202 },
3167 "platform": { 4203 "platform": {
3168 "version": "1.3.5", 4204 "version": "1.3.5",
3169 "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.5.tgz", 4205 "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.5.tgz",
@@ -3207,6 +4243,12 @@
3207 "xtend": "^4.0.0" 4243 "xtend": "^4.0.0"
3208 } 4244 }
3209 }, 4245 },
4246 "prelude-ls": {
4247 "version": "1.1.2",
4248 "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
4249 "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
4250 "dev": true
4251 },
3210 "pretty-hrtime": { 4252 "pretty-hrtime": {
3211 "version": "1.0.3", 4253 "version": "1.0.3",
3212 "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", 4254 "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz",
@@ -3217,6 +4259,12 @@
3217 "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 4259 "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
3218 "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 4260 "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
3219 }, 4261 },
4262 "progress": {
4263 "version": "2.0.3",
4264 "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
4265 "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
4266 "dev": true
4267 },
3220 "promise-reduce": { 4268 "promise-reduce": {
3221 "version": "2.1.0", 4269 "version": "2.1.0",
3222 "resolved": "https://registry.npmjs.org/promise-reduce/-/promise-reduce-2.1.0.tgz", 4270 "resolved": "https://registry.npmjs.org/promise-reduce/-/promise-reduce-2.1.0.tgz",
@@ -3566,6 +4614,17 @@
3566 } 4614 }
3567 } 4615 }
3568 }, 4616 },
4617 "prop-types": {
4618 "version": "15.7.2",
4619 "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
4620 "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
4621 "dev": true,
4622 "requires": {
4623 "loose-envify": "^1.4.0",
4624 "object-assign": "^4.1.1",
4625 "react-is": "^16.8.1"
4626 }
4627 },
3569 "proxy-addr": { 4628 "proxy-addr": {
3570 "version": "2.0.5", 4629 "version": "2.0.5",
3571 "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", 4630 "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz",
@@ -3646,6 +4705,33 @@
3646 "strip-json-comments": "~2.0.1" 4705 "strip-json-comments": "~2.0.1"
3647 } 4706 }
3648 }, 4707 },
4708 "react-is": {
4709 "version": "16.9.0",
4710 "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.9.0.tgz",
4711 "integrity": "sha512-tJBzzzIgnnRfEm046qRcURvwQnZVXmuCbscxUO5RWrGTXpon2d4c8mI0D8WE6ydVIm29JiLB6+RslkIvym9Rjw==",
4712 "dev": true
4713 },
4714 "read-pkg": {
4715 "version": "2.0.0",
4716 "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
4717 "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
4718 "dev": true,
4719 "requires": {
4720 "load-json-file": "^2.0.0",
4721 "normalize-package-data": "^2.3.2",
4722 "path-type": "^2.0.0"
4723 }
4724 },
4725 "read-pkg-up": {
4726 "version": "2.0.0",
4727 "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
4728 "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
4729 "dev": true,
4730 "requires": {
4731 "find-up": "^2.0.0",
4732 "read-pkg": "^2.0.0"
4733 }
4734 },
3649 "readable-stream": { 4735 "readable-stream": {
3650 "version": "2.3.6", 4736 "version": "2.3.6",
3651 "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 4737 "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
@@ -3735,6 +4821,12 @@
3735 } 4821 }
3736 } 4822 }
3737 }, 4823 },
4824 "regexpp": {
4825 "version": "2.0.1",
4826 "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
4827 "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
4828 "dev": true
4829 },
3738 "repeat-element": { 4830 "repeat-element": {
3739 "version": "1.1.3", 4831 "version": "1.1.3",
3740 "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", 4832 "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
@@ -3841,6 +4933,16 @@
3841 "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", 4933 "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
3842 "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" 4934 "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo="
3843 }, 4935 },
4936 "restore-cursor": {
4937 "version": "2.0.0",
4938 "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
4939 "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
4940 "dev": true,
4941 "requires": {
4942 "onetime": "^2.0.0",
4943 "signal-exit": "^3.0.2"
4944 }
4945 },
3844 "ret": { 4946 "ret": {
3845 "version": "0.1.15", 4947 "version": "0.1.15",
3846 "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", 4948 "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
@@ -3859,6 +4961,24 @@
3859 "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", 4961 "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz",
3860 "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=" 4962 "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w="
3861 }, 4963 },
4964 "run-async": {
4965 "version": "2.3.0",
4966 "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
4967 "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
4968 "dev": true,
4969 "requires": {
4970 "is-promise": "^2.1.0"
4971 }
4972 },
4973 "rxjs": {
4974 "version": "6.5.3",
4975 "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz",
4976 "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==",
4977 "dev": true,
4978 "requires": {
4979 "tslib": "^1.9.0"
4980 }
4981 },
3862 "safe-buffer": { 4982 "safe-buffer": {
3863 "version": "5.2.0", 4983 "version": "5.2.0",
3864 "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", 4984 "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
@@ -4063,6 +5183,17 @@
4063 "is-arrayish": "^0.3.1" 5183 "is-arrayish": "^0.3.1"
4064 } 5184 }
4065 }, 5185 },
5186 "slice-ansi": {
5187 "version": "2.1.0",
5188 "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
5189 "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
5190 "dev": true,
5191 "requires": {
5192 "ansi-styles": "^3.2.0",
5193 "astral-regex": "^1.0.0",
5194 "is-fullwidth-code-point": "^2.0.0"
5195 }
5196 },
4066 "snapdragon": { 5197 "snapdragon": {
4067 "version": "0.8.2", 5198 "version": "0.8.2",
4068 "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", 5199 "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
@@ -4196,6 +5327,38 @@
4196 "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", 5327 "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
4197 "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" 5328 "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM="
4198 }, 5329 },
5330 "spdx-correct": {
5331 "version": "3.1.0",
5332 "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
5333 "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
5334 "dev": true,
5335 "requires": {
5336 "spdx-expression-parse": "^3.0.0",
5337 "spdx-license-ids": "^3.0.0"
5338 }
5339 },
5340 "spdx-exceptions": {
5341 "version": "2.2.0",
5342 "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
5343 "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
5344 "dev": true
5345 },
5346 "spdx-expression-parse": {
5347 "version": "3.0.0",
5348 "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
5349 "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
5350 "dev": true,
5351 "requires": {
5352 "spdx-exceptions": "^2.1.0",
5353 "spdx-license-ids": "^3.0.0"
5354 }
5355 },
5356 "spdx-license-ids": {
5357 "version": "3.0.5",
5358 "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
5359 "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
5360 "dev": true
5361 },
4199 "split": { 5362 "split": {
4200 "version": "1.0.1", 5363 "version": "1.0.1",
4201 "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", 5364 "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
@@ -4231,6 +5394,12 @@
4231 } 5394 }
4232 } 5395 }
4233 }, 5396 },
5397 "sprintf-js": {
5398 "version": "1.0.3",
5399 "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
5400 "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
5401 "dev": true
5402 },
4234 "sqlite3": { 5403 "sqlite3": {
4235 "version": "4.1.0", 5404 "version": "4.1.0",
4236 "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.1.0.tgz", 5405 "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.1.0.tgz",
@@ -4361,6 +5530,26 @@
4361 } 5530 }
4362 } 5531 }
4363 }, 5532 },
5533 "string.prototype.trimleft": {
5534 "version": "2.0.0",
5535 "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.0.0.tgz",
5536 "integrity": "sha1-aLaqjhYsaoDnbjqKDC50cYbicf8=",
5537 "dev": true,
5538 "requires": {
5539 "define-properties": "^1.1.2",
5540 "function-bind": "^1.0.2"
5541 }
5542 },
5543 "string.prototype.trimright": {
5544 "version": "2.0.0",
5545 "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.0.0.tgz",
5546 "integrity": "sha1-q0pW2AKgH75yk+EehPJNyBZGYd0=",
5547 "dev": true,
5548 "requires": {
5549 "define-properties": "^1.1.2",
5550 "function-bind": "^1.0.2"
5551 }
5552 },
4364 "string_decoder": { 5553 "string_decoder": {
4365 "version": "1.1.1", 5554 "version": "1.1.1",
4366 "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 5555 "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -4384,6 +5573,12 @@
4384 "ansi-regex": "^2.0.0" 5573 "ansi-regex": "^2.0.0"
4385 } 5574 }
4386 }, 5575 },
5576 "strip-bom": {
5577 "version": "3.0.0",
5578 "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
5579 "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
5580 "dev": true
5581 },
4387 "strip-color": { 5582 "strip-color": {
4388 "version": "0.1.0", 5583 "version": "0.1.0",
4389 "resolved": "https://registry.npmjs.org/strip-color/-/strip-color-0.1.0.tgz", 5584 "resolved": "https://registry.npmjs.org/strip-color/-/strip-color-0.1.0.tgz",
@@ -4415,6 +5610,46 @@
4415 "acorn-node": "^1.2.0" 5610 "acorn-node": "^1.2.0"
4416 } 5611 }
4417 }, 5612 },
5613 "table": {
5614 "version": "5.4.6",
5615 "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
5616 "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
5617 "dev": true,
5618 "requires": {
5619 "ajv": "^6.10.2",
5620 "lodash": "^4.17.14",
5621 "slice-ansi": "^2.1.0",
5622 "string-width": "^3.0.0"
5623 },
5624 "dependencies": {
5625 "ansi-regex": {
5626 "version": "4.1.0",
5627 "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
5628 "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
5629 "dev": true
5630 },
5631 "string-width": {
5632 "version": "3.1.0",
5633 "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
5634 "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
5635 "dev": true,
5636 "requires": {
5637 "emoji-regex": "^7.0.1",
5638 "is-fullwidth-code-point": "^2.0.0",
5639 "strip-ansi": "^5.1.0"
5640 }
5641 },
5642 "strip-ansi": {
5643 "version": "5.2.0",
5644 "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
5645 "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
5646 "dev": true,
5647 "requires": {
5648 "ansi-regex": "^4.1.0"
5649 }
5650 }
5651 }
5652 },
4418 "tar": { 5653 "tar": {
4419 "version": "4.4.10", 5654 "version": "4.4.10",
4420 "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.10.tgz", 5655 "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.10.tgz",
@@ -4493,6 +5728,12 @@
4493 "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", 5728 "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
4494 "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" 5729 "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="
4495 }, 5730 },
5731 "text-table": {
5732 "version": "0.2.0",
5733 "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
5734 "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
5735 "dev": true
5736 },
4496 "through": { 5737 "through": {
4497 "version": "2.3.8", 5738 "version": "2.3.8",
4498 "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 5739 "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
@@ -4624,6 +5865,12 @@
4624 "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", 5865 "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
4625 "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" 5866 "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw=="
4626 }, 5867 },
5868 "tslib": {
5869 "version": "1.10.0",
5870 "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
5871 "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==",
5872 "dev": true
5873 },
4627 "tsscmp": { 5874 "tsscmp": {
4628 "version": "1.0.6", 5875 "version": "1.0.6",
4629 "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", 5876 "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz",
@@ -4642,6 +5889,15 @@
4642 "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 5889 "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
4643 "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" 5890 "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
4644 }, 5891 },
5892 "type-check": {
5893 "version": "0.3.2",
5894 "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
5895 "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
5896 "dev": true,
5897 "requires": {
5898 "prelude-ls": "~1.1.2"
5899 }
5900 },
4645 "type-is": { 5901 "type-is": {
4646 "version": "1.6.18", 5902 "version": "1.6.18",
4647 "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 5903 "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
@@ -4784,6 +6040,12 @@
4784 "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", 6040 "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
4785 "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" 6041 "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
4786 }, 6042 },
6043 "v8-compile-cache": {
6044 "version": "2.1.0",
6045 "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz",
6046 "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==",
6047 "dev": true
6048 },
4787 "v8flags": { 6049 "v8flags": {
4788 "version": "3.1.3", 6050 "version": "3.1.3",
4789 "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", 6051 "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz",
@@ -4792,6 +6054,16 @@
4792 "homedir-polyfill": "^1.0.1" 6054 "homedir-polyfill": "^1.0.1"
4793 } 6055 }
4794 }, 6056 },
6057 "validate-npm-package-license": {
6058 "version": "3.0.4",
6059 "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
6060 "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
6061 "dev": true,
6062 "requires": {
6063 "spdx-correct": "^3.0.0",
6064 "spdx-expression-parse": "^3.0.0"
6065 }
6066 },
4795 "vary": { 6067 "vary": {
4796 "version": "1.1.2", 6068 "version": "1.1.2",
4797 "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 6069 "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
@@ -4874,11 +6146,26 @@
4874 "triple-beam": "^1.2.0" 6146 "triple-beam": "^1.2.0"
4875 } 6147 }
4876 }, 6148 },
6149 "wordwrap": {
6150 "version": "1.0.0",
6151 "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
6152 "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
6153 "dev": true
6154 },
4877 "wrappy": { 6155 "wrappy": {
4878 "version": "1.0.2", 6156 "version": "1.0.2",
4879 "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 6157 "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
4880 "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 6158 "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
4881 }, 6159 },
6160 "write": {
6161 "version": "1.0.3",
6162 "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
6163 "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
6164 "dev": true,
6165 "requires": {
6166 "mkdirp": "^0.5.1"
6167 }
6168 },
4882 "xtend": { 6169 "xtend": {
4883 "version": "4.0.2", 6170 "version": "4.0.2",
4884 "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 6171 "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
diff --git a/package.json b/package.json
index 927c513..3211894 100644
--- a/package.json
+++ b/package.json
@@ -6,7 +6,8 @@
6 "main": "index.js", 6 "main": "index.js",
7 "scripts": { 7 "scripts": {
8 "start": "node server.js", 8 "start": "node server.js",
9 "test": "node ace test" 9 "test": "node ace test",
10 "lint": "eslint --fix ./"
10 }, 11 },
11 "keywords": [ 12 "keywords": [
12 "adonisjs", 13 "adonisjs",
@@ -37,7 +38,15 @@
37 "targz": "^1.0.1", 38 "targz": "^1.0.1",
38 "uuid": "^3.3.3" 39 "uuid": "^3.3.3"
39 }, 40 },
40 "devDependencies": {}, 41 "devDependencies": {
42 "eslint": "^6.3.0",
43 "eslint-config-airbnb": "^18.0.1",
44 "eslint-config-airbnb-base": "^14.0.0",
45 "eslint-plugin-import": "^2.18.2",
46 "eslint-plugin-jsx-a11y": "^6.2.3",
47 "eslint-plugin-react": "^7.14.3",
48 "eslint-plugin-react-hooks": "^1.7.0"
49 },
41 "autoload": { 50 "autoload": {
42 "App": "./app" 51 "App": "./app"
43 } 52 }
diff --git a/public/js/new.js b/public/js/new.js
index 4f54245..beaa36d 100644
--- a/public/js/new.js
+++ b/public/js/new.js
@@ -1,12 +1,13 @@
1/* eslint-env browser */
1const elDrop = document.getElementById('dropzone'); 2const elDrop = document.getElementById('dropzone');
2const submitBtn = document.getElementById('submitbutton'); 3const submitBtn = document.getElementById('submitbutton');
3const fileInput = document.getElementById('files'); 4const fileInput = document.getElementById('files');
4 5
5elDrop.addEventListener('dragover', function (event) { 6elDrop.addEventListener('dragover', (event) => {
6 event.preventDefault(); 7 event.preventDefault();
7}); 8});
8 9
9elDrop.addEventListener('drop', async function (event) { 10elDrop.addEventListener('drop', async (event) => {
10 event.preventDefault(); 11 event.preventDefault();
11 12
12 submitBtn.disabled = true; 13 submitBtn.disabled = true;
@@ -19,5 +20,5 @@ elDrop.addEventListener('drop', async function (event) {
19 submitBtn.disabled = false; 20 submitBtn.disabled = false;
20}); 21});
21elDrop.addEventListener('click', () => { 22elDrop.addEventListener('click', () => {
22 fileInput.click(); 23 fileInput.click();
23}) \ No newline at end of file 24});
diff --git a/server.js b/server.js
index e2371aa..e56b08e 100644
--- a/server.js
+++ b/server.js
@@ -1,4 +1,3 @@
1'use strict'
2 1
3/* 2/*
4|-------------------------------------------------------------------------- 3|--------------------------------------------------------------------------
@@ -17,9 +16,10 @@
17| Make sure to pass a relative path from the project root. 16| Make sure to pass a relative path from the project root.
18*/ 17*/
19 18
20const { Ignitor } = require('@adonisjs/ignitor') 19const { Ignitor } = require('@adonisjs/ignitor');
20const fold = require('@adonisjs/fold');
21 21
22new Ignitor(require('@adonisjs/fold')) 22new Ignitor(fold)
23 .appRoot(__dirname) 23 .appRoot(__dirname)
24 .fireHttpServer() 24 .fireHttpServer()
25 .catch(console.error) 25 .catch(console.error); // eslint-disable-line no-console
diff --git a/start/app.js b/start/app.js
index 9cf2735..d0986fe 100644
--- a/start/app.js
+++ b/start/app.js
@@ -1,4 +1,3 @@
1'use strict'
2 1
3/* 2/*
4|-------------------------------------------------------------------------- 3|--------------------------------------------------------------------------
@@ -21,7 +20,7 @@ const providers = [
21 '@adonisjs/framework/providers/ViewProvider', 20 '@adonisjs/framework/providers/ViewProvider',
22 '@adonisjs/session/providers/SessionProvider', 21 '@adonisjs/session/providers/SessionProvider',
23 '@adonisjs/shield/providers/ShieldProvider', 22 '@adonisjs/shield/providers/ShieldProvider',
24] 23];
25 24
26/* 25/*
27|-------------------------------------------------------------------------- 26|--------------------------------------------------------------------------
@@ -33,8 +32,8 @@ const providers = [
33| 32|
34*/ 33*/
35const aceProviders = [ 34const aceProviders = [
36 '@adonisjs/lucid/providers/MigrationsProvider' 35 '@adonisjs/lucid/providers/MigrationsProvider',
37] 36];
38 37
39/* 38/*
40|-------------------------------------------------------------------------- 39|--------------------------------------------------------------------------
@@ -48,7 +47,7 @@ const aceProviders = [
48| { Route: 'Adonis/Src/Route' } 47| { Route: 'Adonis/Src/Route' }
49| 48|
50*/ 49*/
51const aliases = {} 50const aliases = {};
52 51
53/* 52/*
54|-------------------------------------------------------------------------- 53|--------------------------------------------------------------------------
@@ -58,6 +57,8 @@ const aliases = {}
58| Here you store ace commands for your package 57| Here you store ace commands for your package
59| 58|
60*/ 59*/
61const commands = [] 60const commands = [];
62 61
63module.exports = { providers, aceProviders, aliases, commands } 62module.exports = {
63 providers, aceProviders, aliases, commands,
64};
diff --git a/start/kernel.js b/start/kernel.js
index 18fb5bf..b54fc29 100644
--- a/start/kernel.js
+++ b/start/kernel.js
@@ -1,7 +1,6 @@
1'use strict'
2 1
3/** @type {import('@adonisjs/framework/src/Server')} */ 2/** @type {import('@adonisjs/framework/src/Server')} */
4const Server = use('Server') 3const Server = use('Server');
5 4
6/* 5/*
7|-------------------------------------------------------------------------- 6|--------------------------------------------------------------------------
@@ -17,7 +16,7 @@ const globalMiddleware = [
17 'App/Middleware/ConvertEmptyStringsToNull', 16 'App/Middleware/ConvertEmptyStringsToNull',
18 'Adonis/Middleware/AuthInit', 17 'Adonis/Middleware/AuthInit',
19 'Adonis/Middleware/Session', 18 'Adonis/Middleware/Session',
20] 19];
21 20
22/* 21/*
23|-------------------------------------------------------------------------- 22|--------------------------------------------------------------------------
@@ -40,7 +39,7 @@ const namedMiddleware = {
40 auth: 'Adonis/Middleware/Auth', 39 auth: 'Adonis/Middleware/Auth',
41 guest: 'Adonis/Middleware/AllowGuestOnly', 40 guest: 'Adonis/Middleware/AllowGuestOnly',
42 shield: 'Adonis/Middleware/Shield', 41 shield: 'Adonis/Middleware/Shield',
43} 42};
44 43
45/* 44/*
46|-------------------------------------------------------------------------- 45|--------------------------------------------------------------------------
@@ -54,10 +53,10 @@ const namedMiddleware = {
54*/ 53*/
55const serverMiddleware = [ 54const serverMiddleware = [
56 'Adonis/Middleware/Static', 55 'Adonis/Middleware/Static',
57 'Adonis/Middleware/Cors' 56 'Adonis/Middleware/Cors',
58] 57];
59 58
60Server 59Server
61 .registerGlobal(globalMiddleware) 60 .registerGlobal(globalMiddleware)
62 .registerNamed(namedMiddleware) 61 .registerNamed(namedMiddleware)
63 .use(serverMiddleware) 62 .use(serverMiddleware);
diff --git a/start/routes.js b/start/routes.js
index 5cf9fda..8e0f640 100644
--- a/start/routes.js
+++ b/start/routes.js
@@ -1,4 +1,3 @@
1'use strict'
2 1
3/* 2/*
4|-------------------------------------------------------------------------- 3|--------------------------------------------------------------------------
@@ -8,99 +7,92 @@
8*/ 7*/
9 8
10/** @type {typeof import('@adonisjs/framework/src/Route/Manager')} */ 9/** @type {typeof import('@adonisjs/framework/src/Route/Manager')} */
11const Route = use('Route') 10const Route = use('Route');
12const Env = use('Env') 11const Env = use('Env');
13 12
14// Health: Returning if all systems function correctly 13// Health: Returning if all systems function correctly
15Route.get('health', ({ 14Route.get('health', ({
16 response 15 response,
17}) => { 16}) => response.send({
18 return response.send({ 17 api: 'success',
19 api: 'success', 18 db: 'success',
20 db: 'success' 19}));
21 })
22})
23 20
24// API is grouped under '/v1/' route 21// API is grouped under '/v1/' route
25Route.group(() => { 22Route.group(() => {
26 // User authentification 23 // User authentification
27 Route.post('auth/signup', 'UserController.signup').middleware('guest') 24 Route.post('auth/signup', 'UserController.signup').middleware('guest');
28 Route.post('auth/login', 'UserController.login').middleware('guest') 25 Route.post('auth/login', 'UserController.login').middleware('guest');
29 26
30 // User info 27 // User info
31 Route.get('me', 'UserController.me').middleware('auth') 28 Route.get('me', 'UserController.me').middleware('auth');
32 29
33 // Service info 30 // Service info
34 Route.post('service', 'ServiceController.create').middleware('auth') 31 Route.post('service', 'ServiceController.create').middleware('auth');
35 Route.put('service/:id', 'ServiceController.edit').middleware('auth') 32 Route.put('service/:id', 'ServiceController.edit').middleware('auth');
36 Route.delete('service/:id', 'ServiceController.delete').middleware('auth') 33 Route.delete('service/:id', 'ServiceController.delete').middleware('auth');
37 Route.get('me/services', 'ServiceController.list').middleware('auth') 34 Route.get('me/services', 'ServiceController.list').middleware('auth');
38 Route.put('service/reorder', 'ServiceController.reorder').middleware('auth') 35 Route.put('service/reorder', 'ServiceController.reorder').middleware('auth');
39 Route.get('recipe', 'ServiceController.list').middleware('auth') 36 Route.get('recipe', 'ServiceController.list').middleware('auth');
40 Route.post('recipes/update', 'ServiceController.update').middleware('auth') 37 Route.post('recipes/update', 'ServiceController.update').middleware('auth');
41 38
42 // Recipe store 39 // Recipe store
43 Route.get('recipes', 'RecipeController.list') 40 Route.get('recipes', 'RecipeController.list');
44 Route.get('recipes/download/:recipe', 'RecipeController.download') 41 Route.get('recipes/download/:recipe', 'RecipeController.download');
45 Route.get('recipes/search', 'RecipeController.search') 42 Route.get('recipes/search', 'RecipeController.search');
46 Route.get('recipes/popular', 'StaticController.popularRecipes') 43 Route.get('recipes/popular', 'StaticController.popularRecipes');
47 Route.get('recipes/update', 'StaticController.emptyArray') 44 Route.get('recipes/update', 'StaticController.emptyArray');
48 45
49 // Workspaces 46 // Workspaces
50 Route.put('workspace/:id', 'WorkspaceController.edit').middleware('auth') 47 Route.put('workspace/:id', 'WorkspaceController.edit').middleware('auth');
51 Route.delete('workspace/:id', 'WorkspaceController.delete').middleware('auth') 48 Route.delete('workspace/:id', 'WorkspaceController.delete').middleware('auth');
52 Route.post('workspace', 'WorkspaceController.create').middleware('auth') 49 Route.post('workspace', 'WorkspaceController.create').middleware('auth');
53 Route.get('workspace', 'WorkspaceController.list').middleware('auth') 50 Route.get('workspace', 'WorkspaceController.list').middleware('auth');
54 51
55 // Static responses 52 // Static responses
56 Route.get('features', 'StaticController.features') 53 Route.get('features', 'StaticController.features');
57 Route.get('services', 'StaticController.emptyArray') 54 Route.get('services', 'StaticController.emptyArray');
58 Route.get('news', 'StaticController.emptyArray') 55 Route.get('news', 'StaticController.emptyArray');
59 Route.get('payment/plans', 'StaticController.plans') 56 Route.get('payment/plans', 'StaticController.plans');
60 Route.get('announcements/:version', 'StaticController.announcement') 57 Route.get('announcements/:version', 'StaticController.announcement');
61}).prefix('v1') 58}).prefix('v1');
62 59
63// User dashboard 60// User dashboard
64Route.group(() => { 61Route.group(() => {
65 // Auth 62 // Auth
66 Route.get('login', ({view}) => { 63 Route.get('login', ({ view }) => view.render('dashboard.login')).middleware('guest');
67 return view.render('dashboard.login'); 64 Route.post('login', 'DashboardController.login').middleware('guest');
68 }).middleware('guest');
69 Route.post('login', 'DashboardController.login').middleware('guest')
70 65
71 // Dashboard 66 // Dashboard
72 Route.get('account', 'DashboardController.account').middleware('auth:session') 67 Route.get('account', 'DashboardController.account').middleware('auth:session');
73 Route.post('account', 'DashboardController.edit').middleware('auth:session') 68 Route.post('account', 'DashboardController.edit').middleware('auth:session');
74 Route.get('data', 'DashboardController.data').middleware('auth:session') 69 Route.get('data', 'DashboardController.data').middleware('auth:session');
75 Route.get('delete', ({view}) => { 70 Route.get('delete', ({ view }) => view.render('dashboard.delete')).middleware('auth:session');
76 return view.render('dashboard.delete'); 71 Route.post('delete', 'DashboardController.delete').middleware('auth:session');
77 }).middleware('auth:session'); 72 Route.get('logout', 'DashboardController.logout').middleware('auth:session');
78 Route.post('delete', 'DashboardController.delete').middleware('auth:session') 73
79 Route.get('logout', 'DashboardController.logout').middleware('auth:session') 74 Route.get('*', ({ response }) => response.redirect('/user/account'));
80 75}).prefix('user').middleware('shield');
81 Route.get('*', ({ response }) => response.redirect('/user/account'))
82}).prefix('user').middleware('shield')
83 76
84// Recipe creation 77// Recipe creation
85Route.post('new', 'RecipeController.create') 78Route.post('new', 'RecipeController.create');
86Route.get('new', ({ response, view }) => { 79Route.get('new', ({ response, view }) => {
87 if (Env.get('IS_CREATION_ENABLED') == 'false') { 80 if (Env.get('IS_CREATION_ENABLED') == 'false') { // eslint-disable-line eqeqeq
88 return response.send('This server doesn\'t allow the creation of new recipes.\n\nIf you are the server owner, please set IS_CREATION_ENABLED to true to enable recipe creation.'); 81 return response.send('This server doesn\'t allow the creation of new recipes.\n\nIf you are the server owner, please set IS_CREATION_ENABLED to true to enable recipe creation.');
89 } else {
90 return view.render('others.new')
91 } 82 }
92}) 83 return view.render('others.new');
84});
93 85
94// Franz account import 86// Franz account import
95Route.post('import', 'UserController.import') 87Route.post('import', 'UserController.import');
96Route.get('import', ({ view }) => view.render('others.import')) 88Route.get('import', ({ view }) => view.render('others.import'));
97 89
98// Legal documents 90// Legal documents
99Route.get('terms', ({ response }) => response.redirect('/terms.html')) 91Route.get('terms', ({ response }) => response.redirect('/terms.html'));
100Route.get('privacy', ({ response }) => response.redirect('/privacy.html')) 92Route.get('privacy', ({ response }) => response.redirect('/privacy.html'));
101 93
102// Index 94// Index
103Route.get('/', ({ view }) => view.render('others.index')) 95Route.get('/', ({ view }) => view.render('others.index'));
104 96
105// 404 handler 97// 404 handler
106Route.get('/*', ({ response }) => response.redirect('/')) \ No newline at end of file 98Route.get('/*', ({ response }) => response.redirect('/'));