diff options
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/package.json | 5 | ||||
-rw-r--r-- | scripts/update.js | 124 | ||||
-rw-r--r-- | scripts/yarn.lock | 10 |
3 files changed, 138 insertions, 1 deletions
diff --git a/scripts/package.json b/scripts/package.json index d416231..2bfc982 100644 --- a/scripts/package.json +++ b/scripts/package.json | |||
@@ -9,10 +9,13 @@ | |||
9 | "dependencies": { | 9 | "dependencies": { |
10 | "dir-compare": "^1.7.3", | 10 | "dir-compare": "^1.7.3", |
11 | "fs-extra": "^8.1.0", | 11 | "fs-extra": "^8.1.0", |
12 | "node-fetch": "^2.6.0", | ||
13 | "semver": "^6.3.0", | ||
12 | "targz": "^1.0.1" | 14 | "targz": "^1.0.1" |
13 | }, | 15 | }, |
14 | "scripts": { | 16 | "scripts": { |
15 | "package": "node package.js", | 17 | "package": "node package.js", |
16 | "verify": "node verify.js" | 18 | "verify": "node verify.js", |
19 | "update": "node update.js" | ||
17 | } | 20 | } |
18 | } | 21 | } |
diff --git a/scripts/update.js b/scripts/update.js new file mode 100644 index 0000000..802cd64 --- /dev/null +++ b/scripts/update.js | |||
@@ -0,0 +1,124 @@ | |||
1 | /** | ||
2 | * Update recipes from a Ferdi-compatible server | ||
3 | */ | ||
4 | const fetch = require('node-fetch'); | ||
5 | const targz = require('targz'); | ||
6 | const fs = require('fs-extra'); | ||
7 | const path = require('path'); | ||
8 | const semver = require('semver'); | ||
9 | |||
10 | console.log("Ferdi Recipe Repository Updater v1.0.0"); | ||
11 | |||
12 | // Server to update from | ||
13 | const server = "http://api.franzinfra.com/v1/"; | ||
14 | |||
15 | // Create paths to important files | ||
16 | const allJson = path.join('../', 'all.json'); | ||
17 | |||
18 | // Helper: Download file to filesystem | ||
19 | const downloadFile = (async (url, path) => { | ||
20 | const res = await fetch(url); | ||
21 | const fileStream = fs.createWriteStream(path); | ||
22 | await new Promise((resolve, reject) => { | ||
23 | res.body.pipe(fileStream); | ||
24 | res.body.on("error", (err) => { | ||
25 | reject(err); | ||
26 | }); | ||
27 | fileStream.on("finish", function () { | ||
28 | resolve(); | ||
29 | }); | ||
30 | }); | ||
31 | }); | ||
32 | |||
33 | // Helper: Decompress .tar.gz file | ||
34 | const decompress = (src, dest) => { | ||
35 | return new Promise(resolve => { | ||
36 | targz.decompress({ | ||
37 | src, | ||
38 | dest | ||
39 | }, function (err) { | ||
40 | if (err) { | ||
41 | console.log('Error while decompressing recipe:', err); | ||
42 | } | ||
43 | resolve(); | ||
44 | }); | ||
45 | }) | ||
46 | } | ||
47 | |||
48 | // Let us work in an async environment | ||
49 | (async () => { | ||
50 | // Get current recipes from server | ||
51 | const serverRecipes = await (await fetch(server + 'recipes')).json(); | ||
52 | |||
53 | // Get current local recipes | ||
54 | const localRecipes = await fs.readJson(allJson); | ||
55 | |||
56 | for (const recipe of serverRecipes) { | ||
57 | // Find local recipe info | ||
58 | const localRecipe = localRecipes.find(e => e.id === recipe.id); | ||
59 | |||
60 | if (!localRecipe || semver.gt(recipe.version, localRecipe.version)) { | ||
61 | // Update is availible | ||
62 | console.log(`Updating ${recipe.id} from ${localRecipe ? localRecipe.version : '-1'} to ${recipe.version}`); | ||
63 | |||
64 | const compressed = path.join('../', `${recipe.id}.tar.gz`); | ||
65 | const uncompressed = path.join('../uncompressed', recipe.id); | ||
66 | |||
67 | // Download recipe to filesystem | ||
68 | try { | ||
69 | await downloadFile( | ||
70 | server + '/recipes/download/' + recipe.id, | ||
71 | compressed | ||
72 | ); | ||
73 | } catch(e) { | ||
74 | console.log(`Could not download ${recipe.id}`); | ||
75 | return; | ||
76 | } | ||
77 | |||
78 | // Extract recipe | ||
79 | await decompress(compressed, uncompressed) | ||
80 | |||
81 | // Make sure we have all icons | ||
82 | const iconPng = path.join(uncompressed, '/icon.png'); | ||
83 | const iconSvg = path.join(uncompressed, '/icon.svg'); | ||
84 | if (!await fs.exists(iconPng)) { | ||
85 | downloadFile(recipe.icons.png, iconPng); | ||
86 | } | ||
87 | if (!await fs.exists(iconSvg)) { | ||
88 | downloadFile(recipe.icons.svg, iconSvg); | ||
89 | } | ||
90 | |||
91 | // Update entry in all.json | ||
92 | // Check if package ID already exists | ||
93 | const recipeIndex = localRecipes.findIndex(e => e.id === recipe.id); | ||
94 | |||
95 | const recipeInfo = recipe; | ||
96 | recipeInfo.icons.png = recipeInfo.icons.png.replace( | ||
97 | 'https://cdn.franzinfra.com/recipes/dist/', | ||
98 | 'https://cdn.jsdelivr.net/gh/getferdi/recipes/uncompressed/' | ||
99 | ).replace( | ||
100 | 'src/icon.png', | ||
101 | 'icon.png' | ||
102 | ); | ||
103 | recipeInfo.icons.svg = recipeInfo.icons.svg.replace( | ||
104 | 'https://cdn.franzinfra.com/recipes/dist/', | ||
105 | 'https://cdn.jsdelivr.net/gh/getferdi/recipes/uncompressed/' | ||
106 | ).replace( | ||
107 | 'src/icon.svg', | ||
108 | 'icon.svg' | ||
109 | ); | ||
110 | |||
111 | if (recipeIndex !== -1) { | ||
112 | localRecipes[recipeIndex] = recipeInfo; | ||
113 | } else { | ||
114 | localRecipes.push(recipeInfo); | ||
115 | } | ||
116 | } | ||
117 | } | ||
118 | |||
119 | // Write updated package info to all.json | ||
120 | await fs.writeJson(allJson, localRecipes, { | ||
121 | spaces: 2, | ||
122 | EOL: '\n', | ||
123 | }); | ||
124 | })(); \ No newline at end of file | ||
diff --git a/scripts/yarn.lock b/scripts/yarn.lock index a7b917b..a06349c 100644 --- a/scripts/yarn.lock +++ b/scripts/yarn.lock | |||
@@ -162,6 +162,11 @@ mkdirp@^0.5.1: | |||
162 | dependencies: | 162 | dependencies: |
163 | minimist "0.0.8" | 163 | minimist "0.0.8" |
164 | 164 | ||
165 | node-fetch@^2.6.0: | ||
166 | version "2.6.0" | ||
167 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" | ||
168 | integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== | ||
169 | |||
165 | once@^1.3.1, once@^1.4.0: | 170 | once@^1.3.1, once@^1.4.0: |
166 | version "1.4.0" | 171 | version "1.4.0" |
167 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" | 172 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" |
@@ -205,6 +210,11 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: | |||
205 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" | 210 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" |
206 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== | 211 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== |
207 | 212 | ||
213 | semver@^6.3.0: | ||
214 | version "6.3.0" | ||
215 | resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" | ||
216 | integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== | ||
217 | |||
208 | string_decoder@~1.1.1: | 218 | string_decoder@~1.1.1: |
209 | version "1.1.1" | 219 | version "1.1.1" |
210 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" | 220 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" |