diff --git a/cli/lrcli.js b/cli/lrcli.js index 4066e50..879a76b 100644 --- a/cli/lrcli.js +++ b/cli/lrcli.js @@ -6,11 +6,13 @@ var parsed_args = parse( default: { h: false, }, + stopEarly: true, boolean: [ "h" ], string: [], alias: { h: [ "help", "usage", "u" ] }, + collect: [], negatable: [], // a function which is invoked with a command line parameter not defined // in the options configuration object. If the function returns false, @@ -63,17 +65,73 @@ Actions and Action Options: console.log(usage) } +let parsePluginActionArgs = (args, argdef) => { + + var plugin_args_config = { + boolean: [], + string: [], + alias: {}, + collect: [], + negatable: [], + unknown: null, + default: {}, + alias: {} + } + + for (const [argname, argconfig] of Object.entries(argdef)) { + if ( ("collect" in argconfig) && (argconfig.collect === true) ) { + plugin_args_config.collect.push(argname) + } + if ( ("string" in argconfig) && (argconfig.string === true) ) { + plugin_args_config.string.push(argname) + } + if ( ("boolean" in argconfig) && (argconfig.boolean === true) ) { + plugin_args_config.boolean.push(argname) + } + if ( ("negatable" in argconfig) && (argconfig.negatable === true) ) { + plugin_args_config.negatable.push(argname) + } + if ("default" in argconfig) { + plugin_args_config.default[argname] = argconfig.default + } + } + + var parsed = parse(args, plugin_args_config) + console.log(parsed) + + var result = [] + for (const argname of Object.keys(argdef)) { + if (argname in parsed) { + result.push(parsed[argname]) + } + } + + return result +} + // assuming: // - the first unknown argument is the name of the plugin // - plugins live in ../plugins//cli.js, relative to lrcli.js location // - only one plugin loaded per invocation, at least for now +// +// we *always* pass arguments to plugins as arrays of strings, +// even if we only got one value let plugin if (parsed_args._.length > 0) { plugin = await import(`../plugins/${parsed_args._[0]}/cli.js`); if (parsed_args._.length > 1) { + let action = parsed_args._[1] if (action in plugin.actions) { - plugin.actions[action].run() + + var parsed_plugin_args = parsePluginActionArgs( + // removing the plugin name and the method name + parsed_args._.slice(2), + plugin.actions[action].arguments + ) + + plugin.actions[action].run(...parsed_plugin_args) + } else { printpluginUsage(plugin) } @@ -84,7 +142,4 @@ if (parsed_args._.length > 0) { printUsage() } - - -console.log(parsed_args) console.log(new URL('', import.meta.url).toString().split('/').at(-1)) diff --git a/plugins/basic-integrity/cli.js b/plugins/basic-integrity/cli.js index de0356a..559e1d7 100644 --- a/plugins/basic-integrity/cli.js +++ b/plugins/basic-integrity/cli.js @@ -9,6 +9,29 @@ * https://deno.land/ */ +let getFileIntegrity = async (path, algos) => { + + const file = await Deno.open( + path, + { read: true } + ); + const fileInfo = await file.stat(); + console.log(fileInfo) + if (fileInfo.isFile) { + const decoder = new TextDecoder(); + for await (const chunk of file.readable) { + console.log(decoder.decode(chunk)); + } + } + // putting this in a try-catch block as the file + // is apparently being auto-closed? + // https://issueantenna.com/repo/denoland/deno/issues/15442 + try { + await file.close(); + } catch (BadResource) {} +} + + /** * get integrity data for specified urls, using specified algorithms * @@ -27,11 +50,11 @@ let getIntegrity = (paths, algos=["SHA-256"]) => { if (!Array.isArray(algos) || (algos.length == 0)) { throw new Error("Expected non-empty array of strings in the 'algos' argument.") } - - console.log('weeee') - console.log(paths) - console.log(algos) - + + var result = paths.map(p => { + return getFileIntegrity(p, algos) + }) + console.log(result) } @@ -44,8 +67,17 @@ const pluginActions = { run: getIntegrity, description: "calculate subresource integrity hashes for provided files", arguments: { - paths: "array of strings, paths to individual pieces of content", - algos: "array of SubtleCrypto.digest-compatible algorithm names nto use to calculate digests (default: \"SHA-256\")" + path: { + description: "array of strings, paths to individual pieces of content", + collect: true, + string: true + }, + algorithm: { + description: "array of SubtleCrypto.digest-compatible algorithm names to use to calculate digests (default: \"SHA-256\")", + collect: true, + string: true, + default: "SHA-256" + } } } }