aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/api/package.js
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/api/package.js')
-rw-r--r--scripts/api/package.js207
1 files changed, 0 insertions, 207 deletions
diff --git a/scripts/api/package.js b/scripts/api/package.js
deleted file mode 100644
index c64132f..0000000
--- a/scripts/api/package.js
+++ /dev/null
@@ -1,207 +0,0 @@
1/**
2 * Package recipe into tar.gz file
3 */
4const targz = require('targz');
5const fs = require('fs-extra');
6const path = require('path');
7const sizeOf = require('image-size');
8const semver = require('semver');
9
10// Publicly availible link to this repository's uncompressed folder
11// Used for generating public icon URLs
12const repo = 'https://cdn.jsdelivr.net/gh/getferdi/recipes/uncompressed/';
13
14// Helper: Compress src folder into dest file
15const compress = (src, dest) => new Promise((resolve, reject) => {
16 targz.compress({
17 src,
18 dest,
19 tar: {
20 // Don't package .DS_Store files
21 ignore: function(name) {
22 return path.basename(name) === '.DS_Store'
23 }
24 },
25 }, (err) => {
26 if (err) {
27 reject(err);
28 } else {
29 resolve(dest);
30 }
31 });
32});
33// Let us work in an async environment
34module.exports = async () => {
35 // Create paths to important files
36 const recipeSrc = path.join(__dirname, '../recipe_src');
37 const packageJson = path.join(recipeSrc, 'package.json');
38 const svgIcon = path.join(recipeSrc, 'icon.svg');
39 const pngIcon = path.join(recipeSrc, 'icon.png');
40 const allJson = path.join(__dirname, '../../', 'all.json');
41 let all = await fs.readJson(allJson);
42
43 let errorMessages = []
44
45 // Check that package.json exists
46 if (!await fs.pathExists(packageJson)) {
47 errorMessages.push(`⚠️ It looks like your recipe is missing the "package.json" file.
48 ↪ Please add your recipe to ${recipeSrc} and make sure that folder contains a "package.json".
49 ℹ For more information on how to add your recipe visit: https://github.com/getferdi/recipes/blob/master/docs/integration.md`);
50 }
51
52 // Check that icons exist
53 const hasSvg = await fs.pathExists(svgIcon);
54 if (!hasSvg) {
55 errorMessages.push(`⚠️ It looks like your recipe is missing the "icon.svg" file.
56 ↪ Please make sure your recipe contains an icon.svg file.
57 ℹ For more information about recipe icons visit: https://github.com/getferdi/recipes/blob/master/docs/integration.md#icons`);
58 }
59
60 const hasPng = await fs.pathExists(pngIcon);
61 if (!hasPng) {
62 errorMessages.push(`⚠️ It looks like your recipe is missing the "icon.png" file.
63 ↪ Please make sure your recipe contains an icon.png file.
64 ↪ Please also make sure that your PNG icon is 1024x1024px in size.
65 ℹ For more information about recipe icons visit: https://github.com/getferdi/recipes/blob/master/docs/integration.md#icons`);
66 }
67
68 // Check that icons have the right dimensions
69 if (hasSvg) {
70 const svgSize = sizeOf(svgIcon);
71 const svgHasRightSize = svgSize.width === svgSize.height;
72 if (!svgHasRightSize) {
73 errorMessages.push(`⚠️ It looks like your "icon.svg" is not a square.
74 ↪ Please make sure that your "icon.svg" has the right dimensions to make a square- width and height should be the same.
75 ℹ You can use software like Photoshop, GIMP or Photopea (https://www.photopea.com/) to resize your icons.
76 ℹ For more information about recipe icons visit: https://github.com/getferdi/recipes/blob/master/docs/integration.md#icons`);
77 }
78 }
79
80 if (hasPng) {
81 const pngSize = sizeOf(pngIcon);
82 const pngHasRightSize = pngSize.width === 1024 && pngSize.height === 1024;
83 if (hasPng && !pngHasRightSize) {
84 errorMessages.push(`⚠️ it looks like your "icon.png" is not 1024x1024 in size.
85 ↪ Please make sure that your "icon.png" has the right dimeensions of 1024x1024px.
86 ℹ You can use software like Photoshop, GIMP or Photopea (https://www.photopea.com/) to resize your icons.
87 ℹ For more information about recipe icons visit: https://github.com/getferdi/recipes/blob/master/docs/integration.md#icons`);
88 }
89 }
90
91 // Read package.json
92 const config = await fs.readJson(packageJson)
93
94 // Make sure it contains all required fields
95 if (!config) {
96 errorMessages.push(`⚠️ It looks like your "package.json" file could not read or parsed.
97 ↪ Please make sure your "package.json" contains valid JSON.
98 ℹ You can use a JSON Validator like JSONLint: https://jsonlint.com/
99 ℹ For more information about the package.json file visit: https://github.com/getferdi/recipes/blob/master/docs/configuration.md`);
100 }
101
102 if (!config.id) {
103 errorMessages.push(`⚠️ It looks like your "package.json" does not contain an "id" field.
104 ↪ Please make sure the "id" field contains a unique ID made of lowercase letters (a-z), numbers (0-9), hyphens (-), periods (.), and underscores (_)
105 ℹ For more information about the package.json file visit: https://github.com/getferdi/recipes/blob/master/docs/configuration.md`);
106 } else if (!/^[a-z._\-]+$/.test(config.id)) {
107 errorMessages.push(`⚠️ It looks like your "package.json" defines an invalid recipe ID.
108 ↪ Please make sure the "id" field only contains lowercase letters (a-z), numbers (0-9), hyphens (-), periods (.), and underscores (_)
109 ℹ For more information about the package.json file visit: https://github.com/getferdi/recipes/blob/master/docs/configuration.md`);
110 }
111 if (!config.name) {
112 errorMessages.push(`⚠️ It looks like your "package.json" does not contain a "name" field.
113 ↪ Please make sure the "name" field contains the name of the service (e.g. "Google Keep")
114 ℹ For more information about the package.json file visit: https://github.com/getferdi/recipes/blob/master/docs/configuration.md`);
115 }
116 if (!config.version) {
117 errorMessages.push(`⚠️ It looks like your "package.json" does not contain a "version" field.
118 ↪ Please make sure the "version" field contains a semver-compatible version number for your recipe (e.g. "1.0.0")
119 ℹ For more information about the package.json file visit: https://github.com/getferdi/recipes/blob/master/docs/configuration.md`);
120 }
121 if (!config.config || typeof config.config !== "object") {
122 errorMessages.push(`⚠️ It looks like your "package.json" does not contain a "config" object.
123 ↪ Please make sure the "config" object contains a configuration for your service.
124 ℹ For more information about the package.json file visit: https://github.com/getferdi/recipes/blob/master/docs/configuration.md`);
125 } else if (!config.config.serviceURL) {
126 errorMessages.push(`⚠️ It looks like your "package.json" does not contain a "config" object without a "serviceURL" field.
127 ↪ Please make sure the "serviceURL" contains the URL of your service.
128 ℹ For more information about the package.json file visit: https://github.com/getferdi/recipes/blob/master/docs/configuration.md`);
129 }
130
131 // Index of the current recipe in all.json
132 const packageIndex = all.findIndex(e => e.id === config.id)
133
134 if (packageIndex !== -1) {
135 const currentVersion = config.version;
136 const repoVersion = all[packageIndex].version;
137
138 if (semver.gte(repoVersion, currentVersion)) {
139 errorMessages.push(`⚠️ It looks like your recipe is using the same version number as the current recipe.
140 ↪ Please make sure to increase the version number inside your "package.json" everytime you want to repackage (e.g. '1.0.0' to '1.0.1').
141 ↪ If you don't increase your version number, Ferdi cannot detect that you have made changes to the recipe.
142 ℹ For more information about versioning of recipes visit: https://github.com/getferdi/recipes/blob/master/docs/configuration.md#config-flags`);
143 }
144 }
145
146 if (!await fs.exists(path.join(recipeSrc, 'webview.js'))) {
147 errorMessages.push(`⚠️ It looks like your recipe doesn't contain a "webview.js" file.
148 ↪ Please make sure to create that file and add your features to it.
149 ℹ For more information about the webview.js file visit: https://github.com/getferdi/recipes/blob/master/docs/integration.md#webviewjs and https://github.com/getferdi/recipes/blob/master/docs/frontend_api.md`);
150 }
151 if (!await fs.exists(path.join(recipeSrc, 'index.js'))) {
152 errorMessages.push(`⚠️ It looks like your recipe doesn't contain a "index.js" file.
153 ↪ Please make sure to create that file and add your features to it. For most recipes it is enough to simply add the basic template found at https://github.com/getferdi/recipes/blob/master/docs/integration.md#indexjs
154 ℹ For more information about the webview.js file visit: https://github.com/getferdi/recipes/blob/master/docs/integration.md#indexjs and https://github.com/getferdi/recipes/blob/master/docs/backend_api.md`);
155 }
156
157 if (errorMessages.length > 0) {
158 console.log(`❌ Could not add your recipe, the following ${errorMessages.length} error(s) were found:
159${errorMessages.reduce((str, err) => `${str}\n${err}`)}
160ℹ For more information, visit: https://github.com/getferdi/recipes/tree/master/docs`);
161 return;
162 }
163
164 // Package to .tar.gz
165 console.log(`[Info] Packaging ${config.id}...`);
166 compress(recipeSrc, path.join(__dirname, '../../', 'archives', `${config.id}.tar.gz`));
167
168 // Copy recipe src folder to /uncompressed/:id folder
169 console.log('[Info] Copying to uncompressed recipes');
170 await fs.copy('recipe_src', path.join(__dirname, '../../', 'uncompressed', `${config.id}`));
171
172 // Add recipe to all.json
173 console.log('[Info] Adding to all.json');
174 const isFeatured = packageIndex !== -1 ? all[packageIndex].featured : false;
175 const packageInfo = {
176 "author": config.author || '',
177 "featured": isFeatured,
178 "id": config.id,
179 "name": config.name,
180 "version": config.version || '1.0.0',
181 "icons": {
182 "png": `${repo}${config.id}/icon.png`,
183 "svg": `${repo}${config.id}/icon.svg`,
184 },
185 };
186 // Check if package ID already exists
187 if (packageIndex !== -1) {
188 console.log('[Info] Recipe with ID already exists - overwriting');
189 all[packageIndex] = packageInfo;
190 } else {
191 console.log('[Info] No recipe with ID found - creating new.');
192 all.push(packageInfo);
193 }
194
195 // Sort package list alphabetically
196 all = all.sort((a, b) => {
197 var textA = a.id.toLowerCase();
198 var textB = b.id.toLowerCase();
199 return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
200 });
201 await fs.writeJson(allJson, all, {
202 spaces: 2,
203 EOL: '\n',
204 });
205
206 console.log(`✅ Successfully packaged and added new recipe "${config.id}"`);
207};