@ijuantm/simpl-addon 2.0.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/install.js +111 -83
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -56,5 +56,5 @@ The installer:
|
|
|
56
56
|
|
|
57
57
|
## Requirements
|
|
58
58
|
|
|
59
|
-
- **Node.js**: >=
|
|
59
|
+
- **Node.js**: >= 22.x.x
|
|
60
60
|
- **Simpl Framework**: A (preferably clean) installation of Simpl, if not clean, some manual merging may be required, or the installer may skip files or break things (you have been warned).
|
package/install.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const https = require('https');
|
|
6
|
+
const readline = require('readline');
|
|
6
7
|
const {promisify} = require('util');
|
|
7
8
|
const {exec} = require('child_process');
|
|
8
9
|
|
|
@@ -13,6 +14,7 @@ const COLORS = {
|
|
|
13
14
|
};
|
|
14
15
|
|
|
15
16
|
const CDN_BASE = 'https://cdn.simpl.iwanvanderwal.nl/framework';
|
|
17
|
+
const LOCAL_RELEASES_DIR = process.env.SIMPL_LOCAL_RELEASES || path.join(process.cwd(), 'local-releases');
|
|
16
18
|
|
|
17
19
|
const log = (message, color = 'reset') => console.log(`${COLORS[color]}${message}${COLORS.reset}`);
|
|
18
20
|
|
|
@@ -56,13 +58,22 @@ const downloadFile = (url, dest) => new Promise((resolve, reject) => {
|
|
|
56
58
|
});
|
|
57
59
|
});
|
|
58
60
|
|
|
61
|
+
const promptUser = (question, defaultValue = '') => new Promise(resolve => {
|
|
62
|
+
const rl = readline.createInterface({input: process.stdin, output: process.stdout});
|
|
63
|
+
const prompt = defaultValue ? `${question} ${COLORS.dim}(${defaultValue})${COLORS.reset}: ` : `${question}: `;
|
|
64
|
+
|
|
65
|
+
rl.question(prompt, answer => {
|
|
66
|
+
rl.close();
|
|
67
|
+
resolve(answer.trim() || defaultValue);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
59
71
|
const getSimplVersion = () => {
|
|
60
72
|
const simplFile = path.join(process.cwd(), '.simpl');
|
|
61
73
|
|
|
62
74
|
if (!fs.existsSync(simplFile)) throw new Error('Not a Simpl project. Missing .simpl file in current directory.');
|
|
63
75
|
|
|
64
|
-
const
|
|
65
|
-
const config = JSON.parse(content);
|
|
76
|
+
const config = JSON.parse(fs.readFileSync(simplFile, 'utf8'));
|
|
66
77
|
|
|
67
78
|
if (!config.version) throw new Error('Invalid .simpl file: missing version field');
|
|
68
79
|
|
|
@@ -76,20 +87,14 @@ const showHelp = () => {
|
|
|
76
87
|
log(` ╰${'─'.repeat(62)}╯`);
|
|
77
88
|
console.log();
|
|
78
89
|
log(` ${COLORS.bold}Usage:${COLORS.reset}`, 'blue');
|
|
79
|
-
log(` ${COLORS.dim}npx @ijuantm/simpl-addon
|
|
80
|
-
log(` ${COLORS.dim}npx @ijuantm/simpl-addon --list${COLORS.reset}`);
|
|
90
|
+
log(` ${COLORS.dim}npx @ijuantm/simpl-addon${COLORS.reset}`);
|
|
81
91
|
log(` ${COLORS.dim}npx @ijuantm/simpl-addon --help${COLORS.reset}`);
|
|
82
92
|
console.log();
|
|
83
|
-
log(` ${COLORS.bold}Arguments:${COLORS.reset}`, 'blue');
|
|
84
|
-
log(` ${COLORS.dim}addon-name${COLORS.reset} Name of the add-on to install`);
|
|
85
|
-
console.log();
|
|
86
93
|
log(` ${COLORS.bold}Commands:${COLORS.reset}`, 'blue');
|
|
87
|
-
log(` ${COLORS.dim}--list, -l${COLORS.reset} List all available add-ons`);
|
|
88
94
|
log(` ${COLORS.dim}--help, -h${COLORS.reset} Show this help message`);
|
|
89
95
|
console.log();
|
|
90
96
|
log(` ${COLORS.bold}Examples:${COLORS.reset}`, 'blue');
|
|
91
|
-
log(` ${COLORS.dim}npx @ijuantm/simpl-addon
|
|
92
|
-
log(` ${COLORS.dim}npx @ijuantm/simpl-addon --list${COLORS.reset}`);
|
|
97
|
+
log(` ${COLORS.dim}npx @ijuantm/simpl-addon${COLORS.reset}`);
|
|
93
98
|
console.log();
|
|
94
99
|
log(` ${COLORS.bold}Note:${COLORS.reset}`, 'blue');
|
|
95
100
|
log(` Run this command from the root of your Simpl project.`);
|
|
@@ -97,31 +102,26 @@ const showHelp = () => {
|
|
|
97
102
|
console.log();
|
|
98
103
|
};
|
|
99
104
|
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
105
|
+
const checkServerAvailability = () => new Promise(resolve => {
|
|
106
|
+
const req = https.get(`${CDN_BASE}/versions.json`, {timeout: 5000}, res => {
|
|
107
|
+
res.resume();
|
|
108
|
+
resolve(res.statusCode === 200);
|
|
109
|
+
});
|
|
110
|
+
req.on('error', () => resolve(false));
|
|
111
|
+
req.on('timeout', () => {
|
|
112
|
+
req.destroy();
|
|
113
|
+
resolve(false);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
111
116
|
|
|
112
|
-
|
|
117
|
+
const getAvailableAddons = async (version) => {
|
|
118
|
+
const localListPath = path.join(LOCAL_RELEASES_DIR, version, 'add-ons', 'list.json');
|
|
113
119
|
|
|
114
|
-
|
|
115
|
-
else addons.forEach(name => log(` ${COLORS.cyan}•${COLORS.reset} ${name}`));
|
|
116
|
-
} catch (error) {
|
|
117
|
-
console.log();
|
|
118
|
-
log(` ${COLORS.red}✗${COLORS.reset} Failed to fetch add-ons: ${error.message}`, 'red');
|
|
119
|
-
console.log();
|
|
120
|
+
if (fs.existsSync(localListPath)) return JSON.parse(fs.readFileSync(localListPath, 'utf8'))['add-ons'];
|
|
120
121
|
|
|
121
|
-
|
|
122
|
-
}
|
|
122
|
+
if (!await checkServerAvailability()) throw new Error('CDN server is currently unreachable');
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
return JSON.parse(await fetchUrl(`${CDN_BASE}/${version}/add-ons/list.json`))['add-ons'];
|
|
125
125
|
};
|
|
126
126
|
|
|
127
127
|
const extractMarkers = (content) => {
|
|
@@ -142,13 +142,10 @@ const extractMarkers = (content) => {
|
|
|
142
142
|
|
|
143
143
|
const collectContentBetweenMarkers = (lines, startIndex) => {
|
|
144
144
|
const content = [];
|
|
145
|
-
|
|
146
145
|
for (let i = startIndex + 1; i < lines.length; i++) {
|
|
147
146
|
if (lines[i].trim().includes('@addon-end')) break;
|
|
148
|
-
|
|
149
147
|
content.push(lines[i]);
|
|
150
148
|
}
|
|
151
|
-
|
|
152
149
|
return content;
|
|
153
150
|
};
|
|
154
151
|
|
|
@@ -166,7 +163,6 @@ const processEnvContent = (content, targetContent) => {
|
|
|
166
163
|
}
|
|
167
164
|
|
|
168
165
|
const match = line.match(/^([A-Z_][A-Z0-9_]*)=/);
|
|
169
|
-
|
|
170
166
|
if (match && !new RegExp(`^${match[1]}=`, 'm').test(targetContent)) envVarsToAdd.push(line);
|
|
171
167
|
});
|
|
172
168
|
|
|
@@ -182,19 +178,16 @@ const mergeFile = (targetPath, addonContent, markers, isEnv = false) => {
|
|
|
182
178
|
const targetContent = fs.readFileSync(targetPath, 'utf8');
|
|
183
179
|
const addonLines = addonContent.split('\n');
|
|
184
180
|
const operations = [];
|
|
185
|
-
|
|
186
181
|
let newContent = targetContent;
|
|
187
182
|
|
|
188
183
|
markers.forEach(marker => {
|
|
189
184
|
let content = collectContentBetweenMarkers(addonLines, marker.lineIndex);
|
|
190
|
-
|
|
191
185
|
if (content.length === 0) return;
|
|
192
186
|
|
|
193
187
|
let lineCount = content.length;
|
|
194
188
|
|
|
195
189
|
if (isEnv) {
|
|
196
190
|
const processed = processEnvContent(content, newContent);
|
|
197
|
-
|
|
198
191
|
content = processed.content;
|
|
199
192
|
lineCount = processed.count;
|
|
200
193
|
|
|
@@ -214,13 +207,10 @@ const mergeFile = (targetPath, addonContent, markers, isEnv = false) => {
|
|
|
214
207
|
|
|
215
208
|
if (marker.type === 'prepend') {
|
|
216
209
|
newContent = content.join('\n') + '\n' + newContent;
|
|
217
|
-
|
|
218
210
|
operations.push({success: true, type: 'prepend', lines: lineCount});
|
|
219
211
|
} else if (marker.type === 'append') {
|
|
220
212
|
if (!newContent.endsWith('\n')) newContent += '\n';
|
|
221
|
-
|
|
222
213
|
newContent += '\n' + content.join('\n') + '\n';
|
|
223
|
-
|
|
224
214
|
operations.push({success: true, type: 'append', lines: lineCount});
|
|
225
215
|
} else if ((marker.type === 'after' || marker.type === 'before') && marker.searchText) {
|
|
226
216
|
const targetLines = newContent.split('\n');
|
|
@@ -232,9 +222,7 @@ const mergeFile = (targetPath, addonContent, markers, isEnv = false) => {
|
|
|
232
222
|
}
|
|
233
223
|
|
|
234
224
|
targetLines.splice(insertIndex, 0, ...content);
|
|
235
|
-
|
|
236
225
|
newContent = targetLines.join('\n');
|
|
237
|
-
|
|
238
226
|
operations.push({success: true, type: marker.type, lines: lineCount, searchText: marker.searchText});
|
|
239
227
|
}
|
|
240
228
|
});
|
|
@@ -247,13 +235,11 @@ const mergeFile = (targetPath, addonContent, markers, isEnv = false) => {
|
|
|
247
235
|
const printMergeResults = (relativePath, isEnv, result) => {
|
|
248
236
|
const indent = ' ';
|
|
249
237
|
const varText = isEnv ? 'environment variable' : 'line';
|
|
250
|
-
|
|
251
238
|
let hasChanges = false;
|
|
252
239
|
|
|
253
240
|
result.operations.forEach(op => {
|
|
254
241
|
if (op.success) {
|
|
255
242
|
hasChanges = true;
|
|
256
|
-
|
|
257
243
|
if (op.type === 'prepend') log(`${indent}${COLORS.green}✓${COLORS.reset} Prepended ${COLORS.bold}${op.lines}${COLORS.reset} ${varText}${op.lines !== 1 ? 's' : ''} to file start`);
|
|
258
244
|
else if (op.type === 'append') log(`${indent}${COLORS.green}✓${COLORS.reset} Appended ${COLORS.bold}${op.lines}${COLORS.reset} ${varText}${op.lines !== 1 ? 's' : ''} to file end`);
|
|
259
245
|
else if (op.type === 'after') log(`${indent}${COLORS.green}✓${COLORS.reset} Inserted ${COLORS.bold}${op.lines}${COLORS.reset} ${varText}${op.lines !== 1 ? 's' : ''} ${COLORS.cyan}after${COLORS.reset} "${COLORS.dim}${op.searchText}${COLORS.reset}"`);
|
|
@@ -265,19 +251,21 @@ const printMergeResults = (relativePath, isEnv, result) => {
|
|
|
265
251
|
return hasChanges;
|
|
266
252
|
};
|
|
267
253
|
|
|
268
|
-
const extractZip = async zipPath => {
|
|
269
|
-
|
|
254
|
+
const extractZip = async (zipPath, destDir) => {
|
|
255
|
+
fs.mkdirSync(destDir, {recursive: true});
|
|
270
256
|
|
|
271
|
-
if (process.platform === 'win32') {
|
|
272
|
-
|
|
273
|
-
} else {
|
|
274
|
-
await execAsync(`unzip -q "${zipPath}" -d "${tempExtract}"`);
|
|
275
|
-
}
|
|
257
|
+
if (process.platform === 'win32') await execAsync(`powershell -command "Expand-Archive -Path '${zipPath}' -DestinationPath '${destDir}' -Force"`);
|
|
258
|
+
else await execAsync(`unzip -q "${zipPath}" -d "${destDir}"`);
|
|
276
259
|
|
|
277
|
-
const entries = fs.readdirSync(
|
|
278
|
-
const sourceDir = entries.length === 1 && entries[0].isDirectory() ? path.join(tempExtract, entries[0].name) : tempExtract;
|
|
260
|
+
const entries = fs.readdirSync(destDir, {withFileTypes: true});
|
|
279
261
|
|
|
280
|
-
|
|
262
|
+
if (entries.length === 1 && entries[0].isDirectory()) {
|
|
263
|
+
const nestedDir = path.join(destDir, entries[0].name);
|
|
264
|
+
fs.readdirSync(nestedDir).forEach(item => fs.renameSync(path.join(nestedDir, item), path.join(destDir, item)));
|
|
265
|
+
fs.rmdirSync(nestedDir);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return destDir;
|
|
281
269
|
};
|
|
282
270
|
|
|
283
271
|
const processAddonFiles = (addonDir, targetDir) => {
|
|
@@ -290,19 +278,18 @@ const processAddonFiles = (addonDir, targetDir) => {
|
|
|
290
278
|
const relativePath = path.join(basePath, entry.name).replace(/\\/g, '/');
|
|
291
279
|
const destPath = path.join(targetDir, relativePath);
|
|
292
280
|
|
|
293
|
-
if (entry.isDirectory())
|
|
294
|
-
|
|
281
|
+
if (entry.isDirectory()) {
|
|
282
|
+
processDirectory(srcPath, relativePath);
|
|
283
|
+
} else {
|
|
295
284
|
const content = fs.readFileSync(srcPath, 'utf8');
|
|
296
285
|
|
|
297
286
|
if (fs.existsSync(destPath)) {
|
|
298
287
|
const markers = extractMarkers(content);
|
|
299
|
-
|
|
300
288
|
if (markers.length > 0 || entry.name === '.env') toMerge.push({content, destPath, relativePath, markers});
|
|
301
289
|
else skipped.push(relativePath);
|
|
302
290
|
} else {
|
|
303
291
|
fs.mkdirSync(path.dirname(destPath), {recursive: true});
|
|
304
292
|
fs.copyFileSync(srcPath, destPath);
|
|
305
|
-
|
|
306
293
|
copied.push(relativePath);
|
|
307
294
|
}
|
|
308
295
|
}
|
|
@@ -314,21 +301,30 @@ const processAddonFiles = (addonDir, targetDir) => {
|
|
|
314
301
|
};
|
|
315
302
|
|
|
316
303
|
const downloadAddon = async (addonName, version, targetDir) => {
|
|
317
|
-
const
|
|
318
|
-
const
|
|
304
|
+
const localZipPath = path.join(LOCAL_RELEASES_DIR, version, 'add-ons', `${addonName}.zip`);
|
|
305
|
+
const tempExtract = path.join(process.cwd(), '__temp_extract_addon__');
|
|
319
306
|
|
|
320
307
|
try {
|
|
321
|
-
|
|
308
|
+
if (fs.existsSync(localZipPath)) {
|
|
309
|
+
console.log();
|
|
310
|
+
log(` 💻 Using local add-on files`, 'bold');
|
|
311
|
+
const sourceDir = await extractZip(localZipPath, tempExtract);
|
|
312
|
+
const result = processAddonFiles(sourceDir, targetDir);
|
|
313
|
+
fs.rmSync(tempExtract, {recursive: true, force: true});
|
|
314
|
+
return result;
|
|
315
|
+
}
|
|
322
316
|
|
|
323
|
-
|
|
324
|
-
const result = processAddonFiles(sourceDir, targetDir);
|
|
317
|
+
if (!await checkServerAvailability()) throw new Error('CDN server is currently unreachable');
|
|
325
318
|
|
|
319
|
+
const tempZip = path.join(process.cwd(), `temp-addon-${addonName}.zip`);
|
|
320
|
+
await downloadFile(`${CDN_BASE}/${version}/add-ons/${addonName}.zip`, tempZip);
|
|
321
|
+
const sourceDir = await extractZip(tempZip, tempExtract);
|
|
322
|
+
const result = processAddonFiles(sourceDir, targetDir);
|
|
326
323
|
fs.unlinkSync(tempZip);
|
|
327
324
|
fs.rmSync(tempExtract, {recursive: true, force: true});
|
|
328
|
-
|
|
329
325
|
return result;
|
|
330
326
|
} catch (error) {
|
|
331
|
-
if (fs.existsSync(
|
|
327
|
+
if (fs.existsSync(tempExtract)) fs.rmSync(tempExtract, {recursive: true, force: true});
|
|
332
328
|
throw error;
|
|
333
329
|
}
|
|
334
330
|
};
|
|
@@ -340,17 +336,14 @@ const mergeFiles = (toMerge) => {
|
|
|
340
336
|
|
|
341
337
|
toMerge.forEach(({content, destPath, relativePath, markers}) => {
|
|
342
338
|
const isEnv = path.basename(destPath) === '.env';
|
|
343
|
-
|
|
344
339
|
log(`\n ${COLORS.cyan}•${COLORS.reset} ${COLORS.dim}${relativePath}${COLORS.reset}`);
|
|
345
340
|
|
|
346
341
|
try {
|
|
347
342
|
const result = mergeFile(destPath, content, markers, isEnv);
|
|
348
|
-
|
|
349
343
|
if (printMergeResults(relativePath, isEnv, result)) merged.push(relativePath);
|
|
350
344
|
else unchanged.push(relativePath);
|
|
351
345
|
} catch (error) {
|
|
352
346
|
log(` ${COLORS.red}✗ Error:${COLORS.reset} ${error.message}`, 'red');
|
|
353
|
-
|
|
354
347
|
failed.push(relativePath);
|
|
355
348
|
}
|
|
356
349
|
});
|
|
@@ -362,9 +355,8 @@ const main = async () => {
|
|
|
362
355
|
const args = process.argv.slice(2);
|
|
363
356
|
const firstArg = args[0];
|
|
364
357
|
|
|
365
|
-
if (
|
|
358
|
+
if (firstArg === '--help' || firstArg === '-h') {
|
|
366
359
|
showHelp();
|
|
367
|
-
|
|
368
360
|
process.exit(0);
|
|
369
361
|
}
|
|
370
362
|
|
|
@@ -376,21 +368,60 @@ const main = async () => {
|
|
|
376
368
|
console.log();
|
|
377
369
|
log(` ${COLORS.red}✗${COLORS.reset} ${error.message}`, 'red');
|
|
378
370
|
console.log();
|
|
371
|
+
process.exit(1);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
console.log();
|
|
375
|
+
log(` ╭${'─'.repeat(62)}╮`);
|
|
376
|
+
log(` │ ${COLORS.bold}Simpl Add-on Installer${COLORS.reset} ${COLORS.dim}(${version})${COLORS.reset}${' '.repeat(37 - version.length)}│`);
|
|
377
|
+
log(` ╰${'─'.repeat(62)}╯`);
|
|
378
|
+
console.log();
|
|
379
|
+
log(' 📦 Fetching available add-ons...', 'bold');
|
|
379
380
|
|
|
381
|
+
let addons;
|
|
382
|
+
|
|
383
|
+
try {
|
|
384
|
+
addons = await getAvailableAddons(version);
|
|
385
|
+
} catch (error) {
|
|
386
|
+
console.log();
|
|
387
|
+
log(` ${COLORS.red}✗${COLORS.reset} Failed to fetch add-ons`, 'red');
|
|
388
|
+
if (error.message === 'CDN server is currently unreachable') log(` ${COLORS.dim}The CDN server is currently unavailable. Please try again later.${COLORS.reset}`);
|
|
389
|
+
console.log();
|
|
380
390
|
process.exit(1);
|
|
381
391
|
}
|
|
382
392
|
|
|
383
|
-
|
|
384
|
-
await listAddons(version);
|
|
393
|
+
console.log();
|
|
385
394
|
|
|
395
|
+
if (addons.length === 0) {
|
|
396
|
+
log(` ${COLORS.yellow}⚠${COLORS.reset} No add-ons available for this version`);
|
|
397
|
+
console.log();
|
|
386
398
|
process.exit(0);
|
|
387
399
|
}
|
|
388
400
|
|
|
389
|
-
|
|
401
|
+
log(` ${COLORS.bold}Available add-ons:${COLORS.reset}`, 'blue');
|
|
402
|
+
addons.forEach(name => log(` ${COLORS.cyan}•${COLORS.reset} ${name}`));
|
|
403
|
+
console.log();
|
|
404
|
+
|
|
405
|
+
let addonName;
|
|
406
|
+
|
|
407
|
+
while (true) {
|
|
408
|
+
addonName = await promptUser(' Add-on to install');
|
|
409
|
+
if (!addonName) {
|
|
410
|
+
log(` ${COLORS.red}✗${COLORS.reset} Add-on name cannot be empty`, 'red');
|
|
411
|
+
console.log();
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
if (!addons.includes(addonName)) {
|
|
415
|
+
log(` ${COLORS.red}✗${COLORS.reset} Add-on "${addonName}" not found`, 'red');
|
|
416
|
+
console.log();
|
|
417
|
+
continue;
|
|
418
|
+
}
|
|
419
|
+
break;
|
|
420
|
+
}
|
|
390
421
|
|
|
391
422
|
console.log();
|
|
392
423
|
log(` ╭${'─'.repeat(62)}╮`);
|
|
393
|
-
log(` │ ${COLORS.bold}Installing
|
|
424
|
+
log(` │ ${COLORS.bold}Installing: ${COLORS.cyan}${addonName}${COLORS.reset} ${COLORS.dim}(${version})${COLORS.reset}${' '.repeat(46 - addonName.length - version.length)}│`);
|
|
394
425
|
log(` ╰${'─'.repeat(62)}╯`);
|
|
395
426
|
console.log();
|
|
396
427
|
log(' 📦 Downloading add-on...', 'bold');
|
|
@@ -401,10 +432,10 @@ const main = async () => {
|
|
|
401
432
|
({copied, skipped, toMerge} = await downloadAddon(addonName, version, process.cwd()));
|
|
402
433
|
} catch (error) {
|
|
403
434
|
console.log();
|
|
404
|
-
log(` ${COLORS.red}✗${COLORS.reset}
|
|
405
|
-
log(` ${COLORS.dim}
|
|
435
|
+
log(` ${COLORS.red}✗${COLORS.reset} Installation failed`, 'red');
|
|
436
|
+
if (error.message === 'CDN server is currently unreachable') log(` ${COLORS.dim}The CDN server is currently unavailable. Please try again later.${COLORS.reset}`);
|
|
437
|
+
else log(` ${COLORS.dim}Please verify the add-on exists and try again${COLORS.reset}`);
|
|
406
438
|
console.log();
|
|
407
|
-
|
|
408
439
|
process.exit(1);
|
|
409
440
|
}
|
|
410
441
|
|
|
@@ -416,7 +447,6 @@ const main = async () => {
|
|
|
416
447
|
if (skipped.length > 0) {
|
|
417
448
|
console.log();
|
|
418
449
|
log(` ${COLORS.gray}○${COLORS.reset} ${COLORS.dim}Skipped ${skipped.length} file${skipped.length !== 1 ? 's' : ''} (no merge markers):${COLORS.reset}`);
|
|
419
|
-
|
|
420
450
|
skipped.forEach(file => log(` ${COLORS.dim}• ${file}${COLORS.reset}`));
|
|
421
451
|
}
|
|
422
452
|
|
|
@@ -436,7 +466,6 @@ const main = async () => {
|
|
|
436
466
|
console.log();
|
|
437
467
|
log(` ${COLORS.yellow}⚠${COLORS.reset} ${COLORS.yellow}${failed.length} file${failed.length !== 1 ? 's' : ''} failed to merge${COLORS.reset}`);
|
|
438
468
|
log(` ${COLORS.yellow}Please review manually:${COLORS.reset}`);
|
|
439
|
-
|
|
440
469
|
failed.forEach(file => log(` ${COLORS.cyan}• ${file}${COLORS.reset}`));
|
|
441
470
|
}
|
|
442
471
|
}
|
|
@@ -446,8 +475,7 @@ const main = async () => {
|
|
|
446
475
|
console.log();
|
|
447
476
|
};
|
|
448
477
|
|
|
449
|
-
main().catch(
|
|
450
|
-
log(`\n ${COLORS.red}✗${COLORS.reset} Fatal error
|
|
451
|
-
|
|
478
|
+
main().catch(() => {
|
|
479
|
+
log(`\n ${COLORS.red}✗${COLORS.reset} Fatal error occurred\n`, 'red');
|
|
452
480
|
process.exit(1);
|
|
453
481
|
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ijuantm/simpl-addon",
|
|
3
3
|
"description": "CLI tool to install Simpl framework add-ons.",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.2.0",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"link": "npm link",
|
|
7
7
|
"unlink": "npm unlink -g @ijuantm/simpl-addon"
|
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
"simpl-addon": "install.js"
|
|
12
12
|
},
|
|
13
13
|
"engines": {
|
|
14
|
-
"node": ">=
|
|
14
|
+
"node": ">=22"
|
|
15
15
|
},
|
|
16
16
|
"repository": {
|
|
17
17
|
"type": "git",
|
|
18
|
-
"url": "https://github.com/IJuanTM/simpl"
|
|
18
|
+
"url": "https://github.com/IJuanTM/simpl/"
|
|
19
19
|
},
|
|
20
20
|
"keywords": [
|
|
21
21
|
"simpl",
|
|
@@ -26,5 +26,5 @@
|
|
|
26
26
|
],
|
|
27
27
|
"author": "Iwan van der Wal",
|
|
28
28
|
"license": "GPL-3.0-only",
|
|
29
|
-
"homepage": "https://simpl.iwanvanderwal.nl"
|
|
29
|
+
"homepage": "https://simpl.iwanvanderwal.nl/"
|
|
30
30
|
}
|