diff options
author | Ricardo Cino <ricardo@cino.io> | 2022-06-22 22:10:39 +0200 |
---|---|---|
committer | Vijay Aravamudhan <vraravam@users.noreply.github.com> | 2022-06-23 06:55:42 +0530 |
commit | 5dcc1aff28290fe3b7e2ed5cbe99d3034c0b6f34 (patch) | |
tree | 81f643c38eecdfa49476e0b9dac3aed9107ecf99 /src/stores/RecipesStore.ts | |
parent | Upgrade 'electron' to '19.0.6' (diff) | |
download | ferdium-app-5dcc1aff28290fe3b7e2ed5cbe99d3034c0b6f34.tar.gz ferdium-app-5dcc1aff28290fe3b7e2ed5cbe99d3034c0b6f34.tar.zst ferdium-app-5dcc1aff28290fe3b7e2ed5cbe99d3034c0b6f34.zip |
chore: recipes/request stores js => ts
Diffstat (limited to 'src/stores/RecipesStore.ts')
-rw-r--r-- | src/stores/RecipesStore.ts | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/src/stores/RecipesStore.ts b/src/stores/RecipesStore.ts new file mode 100644 index 000000000..af2aa7fb0 --- /dev/null +++ b/src/stores/RecipesStore.ts | |||
@@ -0,0 +1,169 @@ | |||
1 | import { action, computed, observable } from 'mobx'; | ||
2 | import { readJSONSync } from 'fs-extra'; | ||
3 | import semver from 'semver'; | ||
4 | |||
5 | import { Stores } from 'src/stores.types'; | ||
6 | import { ApiInterface } from 'src/api'; | ||
7 | import { Actions } from 'src/actions/lib/actions'; | ||
8 | import Recipe from 'src/models/Recipe'; | ||
9 | import CachedRequest from './lib/CachedRequest'; | ||
10 | import Request from './lib/Request'; | ||
11 | import { matchRoute } from '../helpers/routing-helpers'; | ||
12 | import { asarRecipesPath } from '../helpers/asar-helpers'; | ||
13 | import TypedStore from './lib/TypedStore'; | ||
14 | |||
15 | const debug = require('../preload-safe-debug')('Ferdium:RecipeStore'); | ||
16 | |||
17 | export default class RecipesStore extends TypedStore { | ||
18 | @observable allRecipesRequest = new CachedRequest(this.api.recipes, 'all'); | ||
19 | |||
20 | @observable installRecipeRequest = new Request(this.api.recipes, 'install'); | ||
21 | |||
22 | @observable getRecipeUpdatesRequest = new Request(this.api.recipes, 'update'); | ||
23 | |||
24 | constructor(stores: Stores, api: ApiInterface, actions: Actions) { | ||
25 | super(stores, api, actions); | ||
26 | |||
27 | // Register action handlers | ||
28 | this.actions.recipe.install.listen(this._install.bind(this)); | ||
29 | this.actions.recipe.update.listen(this._update.bind(this)); | ||
30 | |||
31 | // Reactions | ||
32 | this.registerReactions([this._checkIfRecipeIsInstalled.bind(this)]); | ||
33 | } | ||
34 | |||
35 | async setup(): Promise<void> { | ||
36 | // Initially load all recipes | ||
37 | this.all; | ||
38 | } | ||
39 | |||
40 | @computed get all(): Recipe[] { | ||
41 | return this.allRecipesRequest.execute().result || []; | ||
42 | } | ||
43 | |||
44 | @computed get active() { | ||
45 | const match = matchRoute( | ||
46 | '/settings/services/add/:id', | ||
47 | this.stores.router.location.pathname, | ||
48 | ); | ||
49 | if (match) { | ||
50 | const activeRecipe = this.one(match.id); | ||
51 | if (activeRecipe) { | ||
52 | return activeRecipe; | ||
53 | } | ||
54 | |||
55 | debug(`Recipe ${match.id} not installed`); | ||
56 | } | ||
57 | |||
58 | return null; | ||
59 | } | ||
60 | |||
61 | @computed get recipeIdForServices(): string[] { | ||
62 | return this.stores.services.all.map(s => s.recipe.id); | ||
63 | } | ||
64 | |||
65 | one(id: string): Recipe | undefined { | ||
66 | return this.all.find(recipe => recipe.id === id); | ||
67 | } | ||
68 | |||
69 | isInstalled(id: string): boolean { | ||
70 | return !!this.one(id); | ||
71 | } | ||
72 | |||
73 | // Actions | ||
74 | async _install({ recipeId }): Promise<Recipe> { | ||
75 | const recipe = await this.installRecipeRequest.execute(recipeId)._promise; | ||
76 | await this.allRecipesRequest.invalidate({ immediately: true })._promise; | ||
77 | |||
78 | return recipe; | ||
79 | } | ||
80 | |||
81 | @action async _update() { | ||
82 | const recipeIds = this.recipeIdForServices; | ||
83 | const recipes = {}; | ||
84 | |||
85 | // Hackfix, reference this.all to fetch services | ||
86 | debug(`Check Recipe updates for ${this.all.map(recipe => recipe.id)}`); | ||
87 | |||
88 | for (const r of recipeIds) { | ||
89 | const recipe = this.one(r); | ||
90 | if (recipe) { | ||
91 | recipes[r] = recipe.version; | ||
92 | } | ||
93 | } | ||
94 | |||
95 | if (Object.keys(recipes).length === 0) return; | ||
96 | |||
97 | const remoteUpdates = await this.getRecipeUpdatesRequest.execute(recipes) | ||
98 | ._promise; | ||
99 | |||
100 | // Check for local updates | ||
101 | const allJsonFile = asarRecipesPath('all.json'); | ||
102 | const allJson = readJSONSync(allJsonFile); | ||
103 | const localUpdates: string[] = []; | ||
104 | |||
105 | for (const recipe of Object.keys(recipes)) { | ||
106 | const version = recipes[recipe]; | ||
107 | |||
108 | // Find recipe in local recipe repository | ||
109 | const localRecipe = allJson.find(r => r.id === recipe); | ||
110 | |||
111 | if (localRecipe && semver.lt(version, localRecipe.version)) { | ||
112 | localUpdates.push(recipe); | ||
113 | } | ||
114 | } | ||
115 | |||
116 | const updates = [...remoteUpdates, ...localUpdates]; | ||
117 | debug( | ||
118 | 'Got update information (local, remote):', | ||
119 | localUpdates, | ||
120 | remoteUpdates, | ||
121 | ); | ||
122 | |||
123 | const length = updates.length - 1; | ||
124 | const syncUpdate = async i => { | ||
125 | const update = updates[i]; | ||
126 | |||
127 | this.actions.recipe.install({ recipeId: update }); | ||
128 | await this.installRecipeRequest._promise; | ||
129 | |||
130 | this.installRecipeRequest.reset(); | ||
131 | |||
132 | if (i === length) { | ||
133 | this.stores.ui.showServicesUpdatedInfoBar = true; | ||
134 | } else if (i < length) { | ||
135 | syncUpdate(i + 1); | ||
136 | } | ||
137 | }; | ||
138 | |||
139 | if (length >= 0) { | ||
140 | syncUpdate(0); | ||
141 | } | ||
142 | } | ||
143 | |||
144 | async _checkIfRecipeIsInstalled(): Promise<void> { | ||
145 | const { router } = this.stores; | ||
146 | |||
147 | const match = | ||
148 | router.location && | ||
149 | matchRoute('/settings/services/add/:id', router.location.pathname); | ||
150 | if (match) { | ||
151 | const recipeId = match.id; | ||
152 | |||
153 | if (!this.stores.recipes.isInstalled(recipeId)) { | ||
154 | router.push('/settings/recipes'); | ||
155 | debug(`Recipe ${recipeId} is not installed, trying to install it`); | ||
156 | |||
157 | const recipe = await this.installRecipeRequest.execute(recipeId) | ||
158 | ._promise; | ||
159 | if (recipe) { | ||
160 | await this.allRecipesRequest.invalidate({ immediately: true }) | ||
161 | ._promise; | ||
162 | router.push(`/settings/services/add/${recipeId}`); | ||
163 | } else { | ||
164 | router.push('/settings/recipes'); | ||
165 | } | ||
166 | } | ||
167 | } | ||
168 | } | ||
169 | } | ||