diff options
Diffstat (limited to 'src/api/server')
-rw-r--r-- | src/api/server/LocalApi.js | 20 | ||||
-rw-r--r-- | src/api/server/ServerApi.js | 358 |
2 files changed, 199 insertions, 179 deletions
diff --git a/src/api/server/LocalApi.js b/src/api/server/LocalApi.js index 4b1f03f22..644f15b93 100644 --- a/src/api/server/LocalApi.js +++ b/src/api/server/LocalApi.js | |||
@@ -2,14 +2,14 @@ import { ipcRenderer } from 'electron'; | |||
2 | import { session } from '@electron/remote'; | 2 | import { session } from '@electron/remote'; |
3 | import du from 'du'; | 3 | import du from 'du'; |
4 | 4 | ||
5 | import { getServicePartitionsDirectory } from '../../helpers/service-helpers.js'; | 5 | import { getServicePartitionsDirectory } from '../../helpers/service-helpers'; |
6 | 6 | ||
7 | const debug = require('debug')('Ferdi:LocalApi'); | 7 | const debug = require('debug')('Ferdi:LocalApi'); |
8 | 8 | ||
9 | export default class LocalApi { | 9 | export default class LocalApi { |
10 | // Settings | 10 | // Settings |
11 | getAppSettings(type) { | 11 | getAppSettings(type) { |
12 | return new Promise((resolve) => { | 12 | return new Promise(resolve => { |
13 | ipcRenderer.once('appSettings', (event, resp) => { | 13 | ipcRenderer.once('appSettings', (event, resp) => { |
14 | debug('LocalApi::getAppSettings resolves', resp.type, resp.data); | 14 | debug('LocalApi::getAppSettings resolves', resp.type, resp.data); |
15 | resolve(resp); | 15 | resolve(resp); |
@@ -41,11 +41,21 @@ export default class LocalApi { | |||
41 | } | 41 | } |
42 | 42 | ||
43 | async clearCache(serviceId = null) { | 43 | async clearCache(serviceId = null) { |
44 | const s = serviceId ? session.fromPartition(`persist:service-${serviceId}`) : session.defaultSession; | 44 | const s = serviceId |
45 | ? session.fromPartition(`persist:service-${serviceId}`) | ||
46 | : session.defaultSession; | ||
45 | 47 | ||
46 | debug('LocalApi::clearCache resolves', (serviceId || 'clearAppCache')); | 48 | debug('LocalApi::clearCache resolves', serviceId || 'clearAppCache'); |
47 | await s.clearStorageData({ | 49 | await s.clearStorageData({ |
48 | storages: ['appcache', 'cookies', 'filesystem', 'indexdb', 'localstorage', 'shadercache', 'websql', 'serviceworkers', 'cachestorage'], | 50 | storages: [ |
51 | 'appcache', | ||
52 | 'filesystem', | ||
53 | 'indexdb', | ||
54 | 'shadercache', | ||
55 | 'websql', | ||
56 | 'serviceworkers', | ||
57 | 'cachestorage', | ||
58 | ], | ||
49 | quotas: ['temporary', 'persistent', 'syncable'], | 59 | quotas: ['temporary', 'persistent', 'syncable'], |
50 | }); | 60 | }); |
51 | return s.clearCache(); | 61 | return s.clearCache(); |
diff --git a/src/api/server/ServerApi.js b/src/api/server/ServerApi.js index c63aa7dda..bc0b0dff9 100644 --- a/src/api/server/ServerApi.js +++ b/src/api/server/ServerApi.js | |||
@@ -1,12 +1,11 @@ | |||
1 | import path from 'path'; | 1 | import { join } from 'path'; |
2 | import tar from 'tar'; | 2 | import tar from 'tar'; |
3 | import fs from 'fs-extra'; | 3 | import { readdirSync, statSync, writeFileSync, copySync, ensureDirSync, pathExistsSync, readJsonSync, removeSync } from 'fs-extra'; |
4 | import { app, require as remoteRequire } from '@electron/remote'; | 4 | import { app, require as remoteRequire } from '@electron/remote'; |
5 | 5 | ||
6 | import ServiceModel from '../../models/Service'; | 6 | import ServiceModel from '../../models/Service'; |
7 | import RecipePreviewModel from '../../models/RecipePreview'; | 7 | import RecipePreviewModel from '../../models/RecipePreview'; |
8 | import RecipeModel from '../../models/Recipe'; | 8 | import RecipeModel from '../../models/Recipe'; |
9 | import PlanModel from '../../models/Plan'; | ||
10 | import NewsModel from '../../models/News'; | 9 | import NewsModel from '../../models/News'; |
11 | import UserModel from '../../models/User'; | 10 | import UserModel from '../../models/User'; |
12 | import OrderModel from '../../models/Order'; | 11 | import OrderModel from '../../models/Order'; |
@@ -14,7 +13,7 @@ import OrderModel from '../../models/Order'; | |||
14 | import { sleep } from '../../helpers/async-helpers'; | 13 | import { sleep } from '../../helpers/async-helpers'; |
15 | 14 | ||
16 | import { SERVER_NOT_LOADED } from '../../config'; | 15 | import { SERVER_NOT_LOADED } from '../../config'; |
17 | import { osArch, osPlatform, RECIPES_PATH } from '../../environment'; | 16 | import { osArch, osPlatform, asarRecipesPath, userDataRecipesPath, userDataPath } from '../../environment'; |
18 | import apiBase from '../apiBase'; | 17 | import apiBase from '../apiBase'; |
19 | import { prepareAuthRequest, sendAuthRequest } from '../utils/auth'; | 18 | import { prepareAuthRequest, sendAuthRequest } from '../utils/auth'; |
20 | 19 | ||
@@ -24,16 +23,11 @@ import { | |||
24 | loadRecipeConfig, | 23 | loadRecipeConfig, |
25 | } from '../../helpers/recipe-helpers'; | 24 | } from '../../helpers/recipe-helpers'; |
26 | 25 | ||
27 | import { | 26 | import { removeServicePartitionDirectory } from '../../helpers/service-helpers'; |
28 | removeServicePartitionDirectory, | ||
29 | } from '../../helpers/service-helpers.js'; | ||
30 | 27 | ||
31 | const debug = require('debug')('Ferdi:ServerApi'); | 28 | const debug = require('debug')('Ferdi:ServerApi'); |
32 | 29 | ||
33 | module.paths.unshift( | 30 | module.paths.unshift(getDevRecipeDirectory(), getRecipeDirectory()); |
34 | getDevRecipeDirectory(), | ||
35 | getRecipeDirectory(), | ||
36 | ); | ||
37 | 31 | ||
38 | const { default: fetch } = remoteRequire('electron-fetch'); | 32 | const { default: fetch } = remoteRequire('electron-fetch'); |
39 | 33 | ||
@@ -44,12 +38,16 @@ export default class ServerApi { | |||
44 | 38 | ||
45 | // User | 39 | // User |
46 | async login(email, passwordHash) { | 40 | async login(email, passwordHash) { |
47 | const request = await sendAuthRequest(`${apiBase()}/auth/login`, { | 41 | const request = await sendAuthRequest( |
48 | method: 'POST', | 42 | `${apiBase()}/auth/login`, |
49 | headers: { | 43 | { |
50 | Authorization: `Basic ${window.btoa(`${email}:${passwordHash}`)}`, | 44 | method: 'POST', |
45 | headers: { | ||
46 | Authorization: `Basic ${window.btoa(`${email}:${passwordHash}`)}`, | ||
47 | }, | ||
51 | }, | 48 | }, |
52 | }, false); | 49 | false, |
50 | ); | ||
53 | if (!request.ok) { | 51 | if (!request.ok) { |
54 | throw request; | 52 | throw request; |
55 | } | 53 | } |
@@ -60,10 +58,14 @@ export default class ServerApi { | |||
60 | } | 58 | } |
61 | 59 | ||
62 | async signup(data) { | 60 | async signup(data) { |
63 | const request = await sendAuthRequest(`${apiBase()}/auth/signup`, { | 61 | const request = await sendAuthRequest( |
64 | method: 'POST', | 62 | `${apiBase()}/auth/signup`, |
65 | body: JSON.stringify(data), | 63 | { |
66 | }, false); | 64 | method: 'POST', |
65 | body: JSON.stringify(data), | ||
66 | }, | ||
67 | false, | ||
68 | ); | ||
67 | if (!request.ok) { | 69 | if (!request.ok) { |
68 | throw request; | 70 | throw request; |
69 | } | 71 | } |
@@ -73,20 +75,6 @@ export default class ServerApi { | |||
73 | return u.token; | 75 | return u.token; |
74 | } | 76 | } |
75 | 77 | ||
76 | async activateTrial(data) { | ||
77 | const request = await sendAuthRequest(`${apiBase()}/payment/trial`, { | ||
78 | method: 'POST', | ||
79 | body: JSON.stringify(data), | ||
80 | }); | ||
81 | if (!request.ok) { | ||
82 | throw request; | ||
83 | } | ||
84 | const trial = await request.json(); | ||
85 | |||
86 | debug('ServerApi::activateTrial resolves', trial); | ||
87 | return true; | ||
88 | } | ||
89 | |||
90 | async inviteUser(data) { | 78 | async inviteUser(data) { |
91 | const request = await sendAuthRequest(`${apiBase()}/invite`, { | 79 | const request = await sendAuthRequest(`${apiBase()}/invite`, { |
92 | method: 'POST', | 80 | method: 'POST', |
@@ -101,12 +89,16 @@ export default class ServerApi { | |||
101 | } | 89 | } |
102 | 90 | ||
103 | async retrievePassword(email) { | 91 | async retrievePassword(email) { |
104 | const request = await sendAuthRequest(`${apiBase()}/auth/password`, { | 92 | const request = await sendAuthRequest( |
105 | method: 'POST', | 93 | `${apiBase()}/auth/password`, |
106 | body: JSON.stringify({ | 94 | { |
107 | email, | 95 | method: 'POST', |
108 | }), | 96 | body: JSON.stringify({ |
109 | }, false); | 97 | email, |
98 | }), | ||
99 | }, | ||
100 | false, | ||
101 | ); | ||
110 | if (!request.ok) { | 102 | if (!request.ok) { |
111 | throw request; | 103 | throw request; |
112 | } | 104 | } |
@@ -143,7 +135,9 @@ export default class ServerApi { | |||
143 | } | 135 | } |
144 | const updatedData = await request.json(); | 136 | const updatedData = await request.json(); |
145 | 137 | ||
146 | const user = Object.assign(updatedData, { data: new UserModel(updatedData.data) }); | 138 | const user = Object.assign(updatedData, { |
139 | data: new UserModel(updatedData.data), | ||
140 | }); | ||
147 | debug('ServerApi::updateUserInfo resolves', user); | 141 | debug('ServerApi::updateUserInfo resolves', user); |
148 | return user; | 142 | return user; |
149 | } | 143 | } |
@@ -173,10 +167,10 @@ export default class ServerApi { | |||
173 | } | 167 | } |
174 | const data = await request.json(); | 168 | const data = await request.json(); |
175 | 169 | ||
176 | let services = await this._mapServiceModels(data); | 170 | const services = await this._mapServiceModels(data); |
177 | services = services.filter(service => service !== null); | 171 | const filteredServices = services.filter(service => !!service); |
178 | debug('ServerApi::getServices resolves', services); | 172 | debug('ServerApi::getServices resolves', filteredServices); |
179 | return services; | 173 | return filteredServices; |
180 | } | 174 | } |
181 | 175 | ||
182 | async createService(recipeId, data) { | 176 | async createService(recipeId, data) { |
@@ -190,12 +184,17 @@ export default class ServerApi { | |||
190 | const serviceData = await request.json(); | 184 | const serviceData = await request.json(); |
191 | 185 | ||
192 | if (data.iconFile) { | 186 | if (data.iconFile) { |
193 | const iconData = await this.uploadServiceIcon(serviceData.data.id, data.iconFile); | 187 | const iconData = await this.uploadServiceIcon( |
188 | serviceData.data.id, | ||
189 | data.iconFile, | ||
190 | ); | ||
194 | 191 | ||
195 | serviceData.data = iconData; | 192 | serviceData.data = iconData; |
196 | } | 193 | } |
197 | 194 | ||
198 | const service = Object.assign(serviceData, { data: await this._prepareServiceModel(serviceData.data) }); | 195 | const service = Object.assign(serviceData, { |
196 | data: await this._prepareServiceModel(serviceData.data), | ||
197 | }); | ||
199 | 198 | ||
200 | debug('ServerApi::createService resolves', service); | 199 | debug('ServerApi::createService resolves', service); |
201 | return service; | 200 | return service; |
@@ -219,7 +218,9 @@ export default class ServerApi { | |||
219 | 218 | ||
220 | const serviceData = await request.json(); | 219 | const serviceData = await request.json(); |
221 | 220 | ||
222 | const service = Object.assign(serviceData, { data: await this._prepareServiceModel(serviceData.data) }); | 221 | const service = Object.assign(serviceData, { |
222 | data: await this._prepareServiceModel(serviceData.data), | ||
223 | }); | ||
223 | 224 | ||
224 | debug('ServerApi::updateService resolves', service); | 225 | debug('ServerApi::updateService resolves', service); |
225 | return service; | 226 | return service; |
@@ -236,7 +237,10 @@ export default class ServerApi { | |||
236 | 237 | ||
237 | delete requestData.headers['Content-Type']; | 238 | delete requestData.headers['Content-Type']; |
238 | 239 | ||
239 | const request = await window.fetch(`${apiBase()}/service/${serviceId}`, requestData); | 240 | const request = await window.fetch( |
241 | `${apiBase()}/service/${serviceId}`, | ||
242 | requestData, | ||
243 | ); | ||
240 | 244 | ||
241 | if (!request.ok) { | 245 | if (!request.ok) { |
242 | throw request; | 246 | throw request; |
@@ -307,18 +311,21 @@ export default class ServerApi { | |||
307 | // Recipes | 311 | // Recipes |
308 | async getInstalledRecipes() { | 312 | async getInstalledRecipes() { |
309 | const recipesDirectory = getRecipeDirectory(); | 313 | const recipesDirectory = getRecipeDirectory(); |
310 | const paths = fs.readdirSync(recipesDirectory) | 314 | const paths = readdirSync(recipesDirectory) |
311 | .filter(file => ( | 315 | .filter( |
312 | fs.statSync(path.join(recipesDirectory, file)).isDirectory() | 316 | file => |
313 | && file !== 'temp' | 317 | statSync(join(recipesDirectory, file)).isDirectory() && |
314 | && file !== 'dev' | 318 | file !== 'temp' && |
315 | )); | 319 | file !== 'dev', |
316 | 320 | ); | |
317 | this.recipes = paths.map((id) => { | 321 | |
318 | // eslint-disable-next-line | 322 | this.recipes = paths |
319 | const Recipe = require(id)(RecipeModel); | 323 | .map(id => { |
320 | return new Recipe(loadRecipeConfig(id)); | 324 | // eslint-disable-next-line |
321 | }).filter(recipe => recipe.id); | 325 | const Recipe = require(id)(RecipeModel); |
326 | return new Recipe(loadRecipeConfig(id)); | ||
327 | }) | ||
328 | .filter(recipe => recipe.id); | ||
322 | 329 | ||
323 | this.recipes = this.recipes.concat(this._getDevRecipes()); | 330 | this.recipes = this.recipes.concat(this._getDevRecipes()); |
324 | 331 | ||
@@ -350,12 +357,11 @@ export default class ServerApi { | |||
350 | } | 357 | } |
351 | 358 | ||
352 | async getFeaturedRecipePreviews() { | 359 | async getFeaturedRecipePreviews() { |
360 | // TODO: If we are hitting the internal-server, we need to return an empty list, else we can hit the remote server and get the data | ||
353 | const request = await sendAuthRequest(`${apiBase()}/recipes/popular`); | 361 | const request = await sendAuthRequest(`${apiBase()}/recipes/popular`); |
354 | if (!request.ok) throw request; | 362 | if (!request.ok) throw request; |
355 | 363 | ||
356 | const data = await request.json(); | 364 | const data = await request.json(); |
357 | // data = this._addLocalRecipesToPreviews(data); | ||
358 | |||
359 | const recipePreviews = this._mapRecipePreviewModel(data); | 365 | const recipePreviews = this._mapRecipePreviewModel(data); |
360 | debug('ServerApi::getFeaturedRecipes resolves', recipePreviews); | 366 | debug('ServerApi::getFeaturedRecipes resolves', recipePreviews); |
361 | return recipePreviews; | 367 | return recipePreviews; |
@@ -374,21 +380,21 @@ export default class ServerApi { | |||
374 | 380 | ||
375 | async getRecipePackage(recipeId) { | 381 | async getRecipePackage(recipeId) { |
376 | try { | 382 | try { |
377 | const recipesDirectory = path.join(app.getPath('userData'), 'recipes'); | 383 | const recipesDirectory = userDataRecipesPath(); |
378 | const recipeTempDirectory = path.join(recipesDirectory, 'temp', recipeId); | 384 | const recipeTempDirectory = join(recipesDirectory, 'temp', recipeId); |
379 | const tempArchivePath = path.join(recipeTempDirectory, 'recipe.tar.gz'); | 385 | const tempArchivePath = join(recipeTempDirectory, 'recipe.tar.gz'); |
380 | 386 | ||
381 | const internalRecipeFile = path.join(RECIPES_PATH, `${recipeId}.tar.gz`); | 387 | const internalRecipeFile = asarRecipesPath(`${recipeId}.tar.gz`); |
382 | 388 | ||
383 | fs.ensureDirSync(recipeTempDirectory); | 389 | ensureDirSync(recipeTempDirectory); |
384 | 390 | ||
385 | let archivePath; | 391 | let archivePath; |
386 | 392 | ||
387 | if (await fs.exists(internalRecipeFile)) { | 393 | if (pathExistsSync(internalRecipeFile)) { |
388 | console.log('[ServerApi::getRecipePackage] Using internal recipe file'); | 394 | debug('[ServerApi::getRecipePackage] Using internal recipe file'); |
389 | archivePath = internalRecipeFile; | 395 | archivePath = internalRecipeFile; |
390 | } else { | 396 | } else { |
391 | console.log('[ServerApi::getRecipePackage] Downloading recipe from server'); | 397 | debug('[ServerApi::getRecipePackage] Downloading recipe from server'); |
392 | archivePath = tempArchivePath; | 398 | archivePath = tempArchivePath; |
393 | 399 | ||
394 | const packageUrl = `${apiBase()}/recipes/download/${recipeId}`; | 400 | const packageUrl = `${apiBase()}/recipes/download/${recipeId}`; |
@@ -396,9 +402,9 @@ export default class ServerApi { | |||
396 | const res = await fetch(packageUrl); | 402 | const res = await fetch(packageUrl); |
397 | debug('Recipe downloaded', recipeId); | 403 | debug('Recipe downloaded', recipeId); |
398 | const buffer = await res.buffer(); | 404 | const buffer = await res.buffer(); |
399 | fs.writeFileSync(archivePath, buffer); | 405 | writeFileSync(archivePath, buffer); |
400 | } | 406 | } |
401 | console.log(archivePath); | 407 | debug(archivePath); |
402 | 408 | ||
403 | await sleep(10); | 409 | await sleep(10); |
404 | 410 | ||
@@ -408,16 +414,16 @@ export default class ServerApi { | |||
408 | preservePaths: true, | 414 | preservePaths: true, |
409 | unlink: true, | 415 | unlink: true, |
410 | preserveOwner: false, | 416 | preserveOwner: false, |
411 | onwarn: x => console.log('warn', recipeId, x), | 417 | onwarn: x => debug('warn', recipeId, x), |
412 | }); | 418 | }); |
413 | 419 | ||
414 | await sleep(10); | 420 | await sleep(10); |
415 | 421 | ||
416 | const { id } = fs.readJsonSync(path.join(recipeTempDirectory, 'package.json')); | 422 | const { id } = readJsonSync(join(recipeTempDirectory, 'package.json')); |
417 | const recipeDirectory = path.join(recipesDirectory, id); | 423 | const recipeDirectory = join(recipesDirectory, id); |
418 | fs.copySync(recipeTempDirectory, recipeDirectory); | 424 | copySync(recipeTempDirectory, recipeDirectory); |
419 | fs.remove(recipeTempDirectory); | 425 | removeSync(recipeTempDirectory); |
420 | fs.remove(path.join(recipesDirectory, recipeId, 'recipe.tar.gz')); | 426 | removeSync(join(recipesDirectory, recipeId, 'recipe.tar.gz')); |
421 | 427 | ||
422 | return id; | 428 | return id; |
423 | } catch (err) { | 429 | } catch (err) { |
@@ -427,35 +433,11 @@ export default class ServerApi { | |||
427 | } | 433 | } |
428 | } | 434 | } |
429 | 435 | ||
430 | // Payment | ||
431 | async getPlans() { | ||
432 | const request = await sendAuthRequest(`${apiBase()}/payment/plans`); | ||
433 | if (!request.ok) throw request; | ||
434 | const data = await request.json(); | ||
435 | const plan = new PlanModel(data); | ||
436 | debug('ServerApi::getPlans resolves', plan); | ||
437 | return plan; | ||
438 | } | ||
439 | |||
440 | async getHostedPage(planId) { | ||
441 | const request = await sendAuthRequest(`${apiBase()}/payment/init`, { | ||
442 | method: 'POST', | ||
443 | body: JSON.stringify({ | ||
444 | planId, | ||
445 | }), | ||
446 | }); | ||
447 | if (!request.ok) { | ||
448 | throw request; | ||
449 | } | ||
450 | const data = await request.json(); | ||
451 | |||
452 | debug('ServerApi::getHostedPage resolves', data); | ||
453 | return data; | ||
454 | } | ||
455 | |||
456 | // News | 436 | // News |
457 | async getLatestNews() { | 437 | async getLatestNews() { |
458 | const url = `${apiBase(true)}/news?platform=${osPlatform}&arch=${osArch}&version=${app.getVersion()}`; | 438 | const url = `${apiBase( |
439 | true, | ||
440 | )}/news?platform=${osPlatform}&arch=${osArch}&version=${app.getVersion()}`; | ||
459 | const request = await sendAuthRequest(url); | 441 | const request = await sendAuthRequest(url); |
460 | if (!request.ok) throw request; | 442 | if (!request.ok) throw request; |
461 | const data = await request.json(); | 443 | const data = await request.json(); |
@@ -465,7 +447,7 @@ export default class ServerApi { | |||
465 | } | 447 | } |
466 | 448 | ||
467 | async hideNews(id) { | 449 | async hideNews(id) { |
468 | const request = await sendAuthRequest(`${apiBase(true)}/news/${id}/read`); | 450 | const request = await sendAuthRequest(`${apiBase()}/news/${id}/read`); |
469 | if (!request.ok) throw request; | 451 | if (!request.ok) throw request; |
470 | debug('ServerApi::hideNews resolves', id); | 452 | debug('ServerApi::hideNews resolves', id); |
471 | } | 453 | } |
@@ -476,9 +458,13 @@ export default class ServerApi { | |||
476 | throw new Error('Server not loaded'); | 458 | throw new Error('Server not loaded'); |
477 | } | 459 | } |
478 | 460 | ||
479 | const request = await sendAuthRequest(`${apiBase(false)}/health`, { | 461 | const request = await sendAuthRequest( |
480 | method: 'GET', | 462 | `${apiBase(false)}/health`, |
481 | }, false); | 463 | { |
464 | method: 'GET', | ||
465 | }, | ||
466 | false, | ||
467 | ); | ||
482 | if (!request.ok) { | 468 | if (!request.ok) { |
483 | throw request; | 469 | throw request; |
484 | } | 470 | } |
@@ -486,23 +472,27 @@ export default class ServerApi { | |||
486 | } | 472 | } |
487 | 473 | ||
488 | async getLegacyServices() { | 474 | async getLegacyServices() { |
489 | const file = path.join(app.getPath('userData'), 'settings', 'services.json'); | 475 | const file = userDataPath('settings', 'services.json'); |
490 | 476 | ||
491 | try { | 477 | try { |
492 | const config = fs.readJsonSync(file); | 478 | const config = readJsonSync(file); |
493 | 479 | ||
494 | if (Object.prototype.hasOwnProperty.call(config, 'services')) { | 480 | if (Object.prototype.hasOwnProperty.call(config, 'services')) { |
495 | const services = await Promise.all(config.services.map(async (s) => { | 481 | const services = await Promise.all( |
496 | const service = s; | 482 | config.services.map(async s => { |
497 | const request = await sendAuthRequest(`${apiBase()}/recipes/${s.service}`); | 483 | const service = s; |
498 | 484 | const request = await sendAuthRequest( | |
499 | if (request.status === 200) { | 485 | `${apiBase()}/recipes/${s.service}`, |
500 | const data = await request.json(); | 486 | ); |
501 | service.recipe = new RecipePreviewModel(data); | 487 | |
502 | } | 488 | if (request.status === 200) { |
503 | 489 | const data = await request.json(); | |
504 | return service; | 490 | service.recipe = new RecipePreviewModel(data); |
505 | })); | 491 | } |
492 | |||
493 | return service; | ||
494 | }), | ||
495 | ); | ||
506 | 496 | ||
507 | debug('ServerApi::getLegacyServices resolves', services); | 497 | debug('ServerApi::getLegacyServices resolves', services); |
508 | return services; | 498 | return services; |
@@ -519,7 +509,9 @@ export default class ServerApi { | |||
519 | const recipes = services.map(s => s.recipeId); | 509 | const recipes = services.map(s => s.recipeId); |
520 | await this._bulkRecipeCheck(recipes); | 510 | await this._bulkRecipeCheck(recipes); |
521 | /* eslint-disable no-return-await */ | 511 | /* eslint-disable no-return-await */ |
522 | return Promise.all(services.map(async service => await this._prepareServiceModel(service))); | 512 | return Promise.all( |
513 | services.map(async service => await this._prepareServiceModel(service)), | ||
514 | ); | ||
523 | /* eslint-enable no-return-await */ | 515 | /* eslint-enable no-return-await */ |
524 | } | 516 | } |
525 | 517 | ||
@@ -542,14 +534,18 @@ export default class ServerApi { | |||
542 | 534 | ||
543 | async _bulkRecipeCheck(unfilteredRecipes) { | 535 | async _bulkRecipeCheck(unfilteredRecipes) { |
544 | // Filter recipe duplicates as we don't need to download 3 Slack recipes | 536 | // Filter recipe duplicates as we don't need to download 3 Slack recipes |
545 | const recipes = unfilteredRecipes.filter((elem, pos, arr) => arr.indexOf(elem) === pos); | 537 | const recipes = unfilteredRecipes.filter( |
538 | (elem, pos, arr) => arr.indexOf(elem) === pos, | ||
539 | ); | ||
546 | 540 | ||
547 | return Promise.all(recipes | 541 | return Promise.all( |
548 | .map(async (recipeId) => { | 542 | recipes.map(async recipeId => { |
549 | let recipe = this.recipes.find(r => r.id === recipeId); | 543 | let recipe = this.recipes.find(r => r.id === recipeId); |
550 | 544 | ||
551 | if (!recipe) { | 545 | if (!recipe) { |
552 | console.warn(`Recipe '${recipeId}' not installed, trying to fetch from server`); | 546 | console.warn( |
547 | `Recipe '${recipeId}' not installed, trying to fetch from server`, | ||
548 | ); | ||
553 | 549 | ||
554 | await this.getRecipePackage(recipeId); | 550 | await this.getRecipePackage(recipeId); |
555 | 551 | ||
@@ -565,69 +561,83 @@ export default class ServerApi { | |||
565 | } | 561 | } |
566 | 562 | ||
567 | return recipe; | 563 | return recipe; |
568 | })).catch(err => console.error('Can\'t load recipe', err)); | 564 | }), |
565 | ).catch(err => console.error("Can't load recipe", err)); | ||
569 | } | 566 | } |
570 | 567 | ||
571 | _mapRecipePreviewModel(recipes) { | 568 | _mapRecipePreviewModel(recipes) { |
572 | return recipes.map((recipe) => { | 569 | return recipes |
573 | try { | 570 | .map(recipe => { |
574 | return new RecipePreviewModel(recipe); | 571 | try { |
575 | } catch (e) { | 572 | return new RecipePreviewModel(recipe); |
576 | console.error(e); | 573 | } catch (e) { |
577 | return null; | 574 | console.error(e); |
578 | } | 575 | return null; |
579 | }).filter(recipe => recipe !== null); | 576 | } |
577 | }) | ||
578 | .filter(recipe => recipe !== null); | ||
580 | } | 579 | } |
581 | 580 | ||
582 | _mapNewsModels(news) { | 581 | _mapNewsModels(news) { |
583 | return news.map((newsItem) => { | 582 | return news |
584 | try { | 583 | .map(newsItem => { |
585 | return new NewsModel(newsItem); | 584 | try { |
586 | } catch (e) { | 585 | return new NewsModel(newsItem); |
587 | console.error(e); | 586 | } catch (e) { |
588 | return null; | 587 | console.error(e); |
589 | } | 588 | return null; |
590 | }).filter(newsItem => newsItem !== null); | 589 | } |
590 | }) | ||
591 | .filter(newsItem => newsItem !== null); | ||
591 | } | 592 | } |
592 | 593 | ||
593 | _mapOrderModels(orders) { | 594 | _mapOrderModels(orders) { |
594 | return orders.map((orderItem) => { | 595 | return orders |
595 | try { | 596 | .map(orderItem => { |
596 | return new OrderModel(orderItem); | 597 | try { |
597 | } catch (e) { | 598 | return new OrderModel(orderItem); |
598 | console.error(e); | 599 | } catch (e) { |
599 | return null; | 600 | console.error(e); |
600 | } | 601 | return null; |
601 | }).filter(orderItem => orderItem !== null); | 602 | } |
603 | }) | ||
604 | .filter(orderItem => orderItem !== null); | ||
602 | } | 605 | } |
603 | 606 | ||
604 | _getDevRecipes() { | 607 | _getDevRecipes() { |
605 | const recipesDirectory = getDevRecipeDirectory(); | 608 | const recipesDirectory = getDevRecipeDirectory(); |
606 | try { | 609 | try { |
607 | const paths = fs.readdirSync(recipesDirectory) | 610 | const paths = readdirSync(recipesDirectory) |
608 | .filter(file => fs.statSync(path.join(recipesDirectory, file)).isDirectory() && file !== 'temp'); | 611 | .filter( |
609 | 612 | file => | |
610 | const recipes = paths.map((id) => { | 613 | statSync(join(recipesDirectory, file)).isDirectory() && |
611 | let Recipe; | 614 | file !== 'temp', |
612 | try { | 615 | ); |
613 | // eslint-disable-next-line | 616 | |
614 | Recipe = require(id)(RecipeModel); | 617 | const recipes = paths |
615 | return new Recipe(loadRecipeConfig(id)); | 618 | .map(id => { |
616 | } catch (err) { | 619 | let Recipe; |
617 | console.error(err); | 620 | try { |
618 | } | 621 | // eslint-disable-next-line |
622 | Recipe = require(id)(RecipeModel); | ||
623 | return new Recipe(loadRecipeConfig(id)); | ||
624 | } catch (err) { | ||
625 | console.error(err); | ||
626 | } | ||
619 | 627 | ||
620 | return false; | 628 | return false; |
621 | }).filter(recipe => recipe.id).map((data) => { | 629 | }) |
622 | const recipe = data; | 630 | .filter(recipe => recipe.id) |
631 | .map(data => { | ||
632 | const recipe = data; | ||
623 | 633 | ||
624 | recipe.icons = { | 634 | recipe.icons = { |
625 | svg: `${recipe.path}/icon.svg`, | 635 | svg: `${recipe.path}/icon.svg`, |
626 | }; | 636 | }; |
627 | recipe.local = true; | 637 | recipe.local = true; |
628 | 638 | ||
629 | return data; | 639 | return data; |
630 | }); | 640 | }); |
631 | 641 | ||
632 | return recipes; | 642 | return recipes; |
633 | } catch (err) { | 643 | } catch (err) { |