cloudron 5.14.9 → 5.15.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/bin/cloudron CHANGED
@@ -10,7 +10,7 @@ const actions = require('../src/actions.js'),
10
10
  Command = require('commander').Command,
11
11
  safe = require('safetydance'),
12
12
  semver = require('semver'),
13
- superagent = require('../src/superagent.js'),
13
+ superagent = require('@cloudron/superagent'),
14
14
  util = require('util');
15
15
 
16
16
  const version = require('../package.json').version;
@@ -56,6 +56,7 @@ backupCommand.command('decrypt <infile> <outfile>')
56
56
  backupCommand.command('decrypt-dir <indir> <outdir>')
57
57
  .description('Decrypt an encrypted directory')
58
58
  .option('--password <password>', 'password')
59
+ .option('--no-decrypt-filenames', 'Decrypt filenames [false]')
59
60
  .action(backupTools.decryptDir);
60
61
 
61
62
  backupCommand.command('decrypt-filename <path>')
@@ -111,7 +112,7 @@ envCommand.command('list')
111
112
  .action(actions.envList);
112
113
 
113
114
  envCommand.command('set <KEY=value...>')
114
- .description('Set environment variables')
115
+ .description('Set environment variables. e.g X=1 Y=2')
115
116
  .option('--app <id>', 'App id')
116
117
  .action(actions.envSet);
117
118
 
@@ -168,10 +169,12 @@ program.command('install')
168
169
  .option('-l, --location <domain>', 'Subdomain or full domain')
169
170
  .option('-s, --secondary-domains [DOMAIN=domain,...]', 'Set secondary domains')
170
171
  .option('-a, --alias-domains [domain,...]', 'Alias domains')
172
+ .option('-m, --memory-limit [domain,...]', 'Memory Limit (e.g 1.5G, 512M)')
171
173
  .option('--appstore-id <appid[@version]>', 'Use app from the store')
172
174
  .option('--no-sso', 'Disable Cloudron SSO [false]')
173
175
  .option('--debug [cmd...]', 'Enable debug mode', false)
174
176
  .option('--readonly', 'Mount filesystem readonly. Default is read/write in debug mode.')
177
+ .option('--env <KEY=value...>', 'Set environment variables. e.g X=1 Y=2')
175
178
  .action(actions.install);
176
179
 
177
180
  program.command('list')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloudron",
3
- "version": "5.14.9",
3
+ "version": "5.15.0",
4
4
  "license": "MIT",
5
5
  "description": "Cloudron Commandline Tool",
6
6
  "main": "main.js",
@@ -17,7 +17,8 @@
17
17
  },
18
18
  "author": "Cloudron Developers <support@cloudron.io>",
19
19
  "dependencies": {
20
- "cloudron-manifestformat": "^5.27.0",
20
+ "@cloudron/manifest-format": "^5.27.0",
21
+ "@cloudron/superagent": "^1.0.0",
21
22
  "commander": "^13.1.0",
22
23
  "debug": "^4.4.0",
23
24
  "easy-table": "^1.2.0",
package/src/actions.js CHANGED
@@ -7,14 +7,14 @@ const assert = require('assert'),
7
7
  { EventSource } = require('eventsource'),
8
8
  fs = require('fs'),
9
9
  https = require('https'),
10
- manifestFormat = require('cloudron-manifestformat'),
10
+ manifestFormat = require('@cloudron/manifest-format'),
11
11
  os = require('os'),
12
12
  path = require('path'),
13
13
  readline = require('./readline.js'),
14
14
  safe = require('safetydance'),
15
15
  spawn = require('child_process').spawn,
16
16
  semver = require('semver'),
17
- superagent = require('./superagent.js'),
17
+ superagent = require('@cloudron/superagent'),
18
18
  Table = require('easy-table'),
19
19
  tar = require('tar-fs'),
20
20
  timers = require('timers/promises'),
@@ -544,6 +544,33 @@ async function getManifest(appstoreId) {
544
544
  return { manifest: result.manifest, manifestFilePath };
545
545
  }
546
546
 
547
+ function parseMemoryLimit(limit) {
548
+ assert.strictEqual(typeof limit, 'string');
549
+
550
+ const units = {
551
+ B: 1,
552
+ K: 1024,
553
+ KB: 1024,
554
+ M: 1024 ** 2,
555
+ MB: 1024 ** 2,
556
+ G: 1024 ** 3,
557
+ GB: 1024 ** 3,
558
+ T: 1024 ** 4,
559
+ TB: 1024 ** 4
560
+ };
561
+
562
+ const match = limit.trim().toUpperCase().match(/^([\d.]+)\s*([KMGT]?B?)$/);
563
+ if (!match) throw new Error(`Invalid size format: "${limit}"`);
564
+
565
+ const value = parseFloat(match[1]);
566
+ const unit = match[2] || 'B';
567
+
568
+ const multiplier = units[unit];
569
+ if (!multiplier) throw new Error(`Unknown unit: "${unit}"`);
570
+
571
+ return value * multiplier;
572
+ }
573
+
547
574
  async function install(localOptions, cmd) {
548
575
  const options = cmd.optsWithGlobals();
549
576
 
@@ -616,6 +643,18 @@ async function install(localOptions, cmd) {
616
643
 
617
644
  for (const port in ports) console.log(`Port ${port}: ${ports[port]}`);
618
645
 
646
+ // environment variables
647
+ const env = {};
648
+ if (options.env) {
649
+ options.env.forEach(envVar => {
650
+ const m = envVar.match(/(.*?)=(.*)/);
651
+ if (!m) return exit(`Expecting KEY=VALUE pattern. Got ${envVar}`);
652
+ env[m[1]] = m[2];
653
+ });
654
+ }
655
+
656
+ const memoryLimit = options.memoryLimit ? parseMemoryLimit(options.memoryLimit) : 0;
657
+
619
658
  const data = {
620
659
  appStoreId: options.appstoreId || '', // note case change
621
660
  manifest: options.appstoreId ? null : manifest, // cloudron ignores manifest anyway if appStoreId is set
@@ -625,7 +664,9 @@ async function install(localOptions, cmd) {
625
664
  secondaryDomains,
626
665
  aliasDomains,
627
666
  ports,
628
- accessRestriction: null
667
+ accessRestriction: null,
668
+ memoryLimit,
669
+ env
629
670
  };
630
671
 
631
672
  // the sso only applies for apps which allow optional sso
@@ -7,11 +7,11 @@ const assert = require('assert'),
7
7
  execSync = require('child_process').execSync,
8
8
  fs = require('fs'),
9
9
  { exit, locateManifest } = require('./helper.js'),
10
- manifestFormat = require('cloudron-manifestformat'),
10
+ manifestFormat = require('@cloudron/manifest-format'),
11
11
  path = require('path'),
12
12
  readline = require('./readline.js'),
13
13
  safe = require('safetydance'),
14
- superagent = require('./superagent.js'),
14
+ superagent = require('@cloudron/superagent'),
15
15
  Table = require('easy-table');
16
16
 
17
17
  exports = module.exports = {
@@ -262,11 +262,13 @@ async function decryptDir(inDir, outDir, options) {
262
262
  }
263
263
 
264
264
  const encryption = aesKeysFromPassword(options.password);
265
+ const decryptFilenames = options.decryptFilenames;
265
266
 
266
267
  const inDirAbs = path.resolve(process.cwd(), inDir);
267
268
  const outDirAbs = path.resolve(process.cwd(), outDir);
268
269
 
269
270
  const tbd = [ '' ]; // only has paths relative to inDirAbs
271
+ let errorCount = 0;
270
272
  while (true) {
271
273
  const cur = tbd.pop();
272
274
  const entries = fs.readdirSync(path.join(inDirAbs, cur), { withFileTypes: true });
@@ -279,29 +281,41 @@ async function decryptDir(inDir, outDir, options) {
279
281
  continue;
280
282
  }
281
283
 
282
- const encryptedFilePath = path.join(cur, entry.name);
283
-
284
- const { error, decryptedFilePath } = decryptFilePath(encryptedFilePath, encryption);
285
- if (error) throw error;
284
+ const fullPath = path.join(cur, entry.name);
285
+
286
+ let destPath = fullPath;
287
+ if (decryptFilenames) {
288
+ const { error, decryptedFilePath } = decryptFilePath(fullPath, encryption);
289
+ if (error) {
290
+ console.warn(`Could not decrypt filename: ${error.message}`);
291
+ errorCount++;
292
+ continue;
293
+ }
294
+ destPath = decryptedFilePath;
295
+ }
286
296
 
287
- console.log(`Decrypting ${decryptedFilePath}`);
297
+ console.log(`Decrypting ${destPath}`);
288
298
 
289
299
  const infile = path.join(inDirAbs, cur, entry.name);
290
300
  const inStream = fs.createReadStream(infile);
291
- fs.mkdirSync(path.dirname(path.join(outDirAbs, decryptedFilePath)), { recursive: true });
292
- const outfile = path.join(outDirAbs, decryptedFilePath);
301
+ fs.mkdirSync(path.dirname(path.join(outDirAbs, destPath)), { recursive: true });
302
+ const outfile = path.join(outDirAbs, destPath);
293
303
  const outStream = fs.createWriteStream(outfile);
294
304
  const decryptStream = new DecryptStream(encryption);
295
305
 
296
306
  const [decryptError] = await safe(stream.pipeline(inStream, decryptStream, outStream));
297
307
  if (decryptError) {
298
308
  safe.fs.rmSync(outfile);
299
- throw new Error(`Could not decrypt ${infile}: ${decryptError.message}`);
309
+ console.warn(`Could not decrypt ${infile}: ${decryptError.message}`);
310
+ ++errorCount;
300
311
  }
301
312
  }
302
313
 
303
314
  if (tbd.length === 0) break;
304
315
  }
316
+
317
+
318
+ if (errorCount) exit(`Failed to decrypt ${errorCount} files`);
305
319
  }
306
320
 
307
321
  async function decryptFilename(filePath, options) {
@@ -16,14 +16,14 @@ const assert = require('assert'),
16
16
  exit = require('./helper.js').exit,
17
17
  fs = require('fs'),
18
18
  helper = require('./helper.js'),
19
- manifestFormat = require('cloudron-manifestformat'),
19
+ manifestFormat = require('@cloudron/manifest-format'),
20
20
  micromatch = require('micromatch'),
21
21
  os = require('os'),
22
22
  path = require('path'),
23
23
  readline = require('./readline.js'),
24
24
  safe = require('safetydance'),
25
25
  stream = require('stream/promises'),
26
- superagent = require('./superagent.js'),
26
+ superagent = require('@cloudron/superagent'),
27
27
  tar = require('tar-fs'),
28
28
  url = require('url');
29
29