1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
/**
* Update recipes from a Ferdi-compatible server
*/
const fetch = require('node-fetch');
const targz = require('targz');
const fs = require('fs-extra');
const path = require('path');
const semver = require('semver');
console.log("Ferdi Recipe Repository Updater v1.0.0");
// Server to update from
const server = "http://api.franzinfra.com/v1";
// Create paths to important files
const allJson = path.join('../', 'all.json');
// Helper: Download file to filesystem
const downloadFile = (async (url, path) => {
const res = await fetch(url);
const fileStream = fs.createWriteStream(path);
await new Promise((resolve, reject) => {
res.body.pipe(fileStream);
res.body.on("error", (err) => {
reject(err);
});
fileStream.on("finish", function () {
resolve();
});
});
});
// Helper: Decompress .tar.gz file
const decompress = (src, dest) => {
return new Promise(resolve => {
targz.decompress({
src,
dest
}, function (err) {
if (err) {
console.log('Error while decompressing recipe:', err);
}
resolve();
});
})
}
// Let us work in an async environment
(async () => {
// Get current recipes from server
const serverRecipes = await (await fetch(server + '/recipes')).json();
// Get current local recipes
const localRecipes = await fs.readJson(allJson);
for (const recipe of serverRecipes) {
// Find local recipe info
const localRecipe = localRecipes.find(e => e.id === recipe.id);
if (!localRecipe || semver.gt(recipe.version, localRecipe.version)) {
// Update is availible
console.log(`Updating ${recipe.id} from ${localRecipe ? localRecipe.version : '-1'} to ${recipe.version}`);
const compressed = path.join('../archives', `${recipe.id}.tar.gz`);
const uncompressed = path.join('../uncompressed', recipe.id);
// Download recipe to filesystem
try {
console.log("Downloading " + server + '/recipes/download/' + recipe.id);
await downloadFile(
server + '/recipes/download/' + recipe.id,
compressed
);
} catch(e) {
console.log(`Could not download ${recipe.id}`);
return;
}
// Extract recipe
await decompress(compressed, uncompressed)
// Make sure we have all icons
const iconPng = path.join(uncompressed, '/icon.png');
const iconSvg = path.join(uncompressed, '/icon.svg');
if (!await fs.exists(iconPng)) {
downloadFile(recipe.icons.png, iconPng);
}
if (!await fs.exists(iconSvg)) {
downloadFile(recipe.icons.svg, iconSvg);
}
// Update entry in all.json
// Check if package ID already exists
const recipeIndex = localRecipes.findIndex(e => e.id === recipe.id);
const recipeInfo = recipe;
recipeInfo.icons.png = recipeInfo.icons.png.replace(
'https://cdn.franzinfra.com/recipes/dist/',
'https://cdn.jsdelivr.net/gh/getferdi/recipes/uncompressed/'
).replace(
'src/icon.png',
'icon.png'
);
recipeInfo.icons.svg = recipeInfo.icons.svg.replace(
'https://cdn.franzinfra.com/recipes/dist/',
'https://cdn.jsdelivr.net/gh/getferdi/recipes/uncompressed/'
).replace(
'src/icon.svg',
'icon.svg'
);
if (recipeIndex !== -1) {
localRecipes[recipeIndex] = recipeInfo;
} else {
localRecipes.push(recipeInfo);
}
}
}
// Write updated package info to all.json
await fs.writeJson(allJson, localRecipes, {
spaces: 2,
EOL: '\n',
});
})();
|