ForgeTotal.js 5
en

Total.js 5

Back up a folder with BACKUP() and RESTORE(), and run commands with SHELL()

Total.js 5 · total5@0.0.19 backupshellfiles Executed against Total.js 5
  • BACKUP(filename, directory, [callback], [filter]) packs a directory (with its subdirectories) into one file and resolves with { filename, files, size }. An existing file with that name is replaced. Without a callback it returns a promise.
  • RESTORE(filename, directory, [callback], [filter]) unpacks a file made with BACKUP() into a directory, creating the folders it needs, and resolves with { files, size, path }.
  • SHELL(command, [callback], [cwd]) runs a shell command and resolves with its output (stdout). The folder is the one of the project, or the text you pass as the last argument. When the command fails the promise is rejected with an error whose code is the exit code. With a callback it is called as callback(err, stdout, stderr).

SHELL() runs exactly the text you give it: never build the command from what a user sent.

controllers/backups.js
const Fs = require('fs');
const Path = require('path');

exports.install = function() {
	ROUTE('GET /backup/', backup);
	ROUTE('GET /shell/', shell);
};

async function backup($) {

	// a folder with a file and a subfolder
	const source = PATH.tmp('source');
	Fs.rmSync(source, { recursive: true, force: true });
	Fs.mkdirSync(Path.join(source, 'sub'), { recursive: true });
	Fs.writeFileSync(Path.join(source, 'a.txt'), 'hello');
	Fs.writeFileSync(Path.join(source, 'sub', 'b.txt'), 'world');

	const file = PATH.tmp('folder.backup');
	const packed = await BACKUP(file, source);

	const target = PATH.tmp('restored');
	Fs.rmSync(target, { recursive: true, force: true });
	const unpacked = await RESTORE(file, target);

	$.json({
		packed: [packed.files, packed.filename === file, Fs.existsSync(file)],
		unpacked: [unpacked.files, unpacked.size, unpacked.path === target],
		content: [Fs.readFileSync(Path.join(target, 'a.txt'), 'utf8'), Fs.readFileSync(Path.join(target, 'sub', 'b.txt'), 'utf8')]
	});
}

async function shell($) {

	const output = await SHELL('echo hello');
	const where = await SHELL('pwd', PATH.tmp());

	let code = null;
	try {
		await SHELL('exit 3');
	} catch (e) {
		code = e.code;
	}

	SHELL('echo from callback', (err, stdout) => $.json({ output: output, where: where.trim() === PATH.tmp() || where.trim().endsWith('/tmp'), code: code, callback: stdout }));
}