/* This file is part of »mimir«. Copyright 2025 kcf »mimir« is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. »mimir« is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with »mimir«. If not, see . */ namespace _mimir { /** */ function get_stamp( ) : string { const date : Date = (new Date(Date.now())); return lib_plankton.string.coin( // "{{year}}{{month}}{{day}}T{{hour}}{{minute}}{{second}}", "{{year}}-{{month}}-{{day}}", { "year": date.getFullYear().toFixed(0).padStart(4, "0"), "month": (date.getMonth() + 1).toFixed(0).padStart(2, "0"), "day": date.getDate().toFixed(0).padStart(2, "0"), "hour": date.getHours().toFixed(0).padStart(2, "0"), "minute": date.getMinutes().toFixed(0).padStart(2, "0"), "second": date.getSeconds().toFixed(0).padStart(2, "0"), } ); } /** */ export async function main( args_raw : Array ) : Promise { // args const arg_handler : lib_plankton.args.class_handler = new lib_plankton.args.class_handler({ "action": lib_plankton.args.class_argument.positional({ "index": 0, "type": lib_plankton.args.enum_type.string, "mode": lib_plankton.args.enum_mode.replace, "default": "run", "name": "action", "info": lib_plankton.string.coin( "{{description}}:\n{{options}}\n\t\t", { "description": "what to do", "options": ( [ { "name": "conf-schema", "description": "conf-schema" }, { "name": "conf-expose", "description": "conf-expose" }, { "name": "init", "description": "init" }, { "name": "run", "description": "run" }, ] .map( entry => lib_plankton.string.coin( "\t\t- {{name}}\n\t\t\t{{description}}\n", { "name": entry.name, "description": entry.description, } ) ) .join("") ), } ), }), "conf_path": lib_plankton.args.class_argument.volatile({ "indicators_long": ["conf_path"], "indicators_short": ["c"], "type": lib_plankton.args.enum_type.string, "mode": lib_plankton.args.enum_mode.replace, "default": "mmr.json", "info": "conf_path", "name": "conf-path", }), "help": lib_plankton.args.class_argument.volatile({ "indicators_long": ["help"], "indicators_short": ["h"], "type": lib_plankton.args.enum_type.boolean, "mode": lib_plankton.args.enum_mode.replace, "default": false, "info": "help", "name": "help", }), }); const args : Record = arg_handler.read(lib_plankton.args.enum_environment.cli, args_raw.join(" ")); if (args.help) { process.stdout.write( arg_handler.generate_help( { "programname": "Mimir", "description": "backup tool", "executable": "mimir", } ) + "\n" ); } else { switch (args["action"]) { default: { lib_plankton.log.error( "invalid_action", { "action": args["action"], } ); return Promise.reject("invalid action"); break; } case "conf-schema": { process.stdout.write( JSON.stringify( _mimir.conf.schema, undefined, "\t" ) ); return Promise.resolve(undefined); break; } case "conf-expose": { const conf : _mimir.conf.type_conf = await _mimir.conf.get(args["conf_path"]); process.stdout.write( JSON.stringify( conf, undefined, "\t" ) ); return Promise.resolve(undefined); break; } case "init": { /** * @todo implement */ return Promise.reject(new Error("not implemented")); break; } case "run": { const conf : _mimir.conf.type_conf = await _mimir.conf.get(args["conf_path"]); const stamp : string = get_stamp(); for await (const concern of conf.concerns) { let commands : Array = []; const commands_add : ((command : string) => void) = (command) => { commands.push(command); }; const commands_apply : (() => void) = () => { process.stdout.write(commands.join("\n") + "\n"); }; commands_add( lib_plankton.string.coin( "## {{name}}\n", { "name": concern.name, } ) ); commands_add( lib_plankton.string.coin( "echo '-- {{name}}'", { "name": concern.name, "kind": concern.kind, } ) ); if (! concern.active) { commands_add( "echo '-- (skipping)'" ); } else { const directory : string = lib_plankton.string.coin( "{{base}}/{{stamp}}/{{name}}", { "base": conf.settings.temp_directory, "stamp": stamp, "name": concern.name, } ); // preparation { commands_add( lib_plankton.string.coin( "mkdir --parents {{directory}}", { "directory": directory, } ) ); } // serialization { const serialization_logic : _mimir.serialization.type_logic = _mimir.serialization.get_logic(concern); commands = commands.concat( serialization_logic.execute( directory ) ); } // transfer { const target_logic : _mimir.transfer.type_logic = _mimir.transfer.get_logic(conf.target); commands = commands.concat( target_logic.execute( concern.name, stamp, directory ) ); } // cleaning { /** * @todo use shred? */ commands_add( lib_plankton.string.coin( "rm --recursive {{path}}/*", { "path": conf.settings.temp_directory, } ) ); } } commands_add( "" ); commands_add( "" ); commands_apply(); } return Promise.resolve(undefined); break; } } } } } ( _mimir.main(process.argv.slice(2)) .then( (result) => { process.exit(0); } ) .catch( (reason) => { process.stderr.write("fatal error: " + String(reason) + "\n"); process.exit(1); } ) );