diff --git a/gems/wrapperV3.js b/gems/wrapperV3.js new file mode 100755 index 0000000..efafdf4 --- /dev/null +++ b/gems/wrapperV3.js @@ -0,0 +1,97 @@ +// wrapperV3.js + +/* +This is the third working version of the wrapper. Better error handling and accepting multiple JavaScript command for the secrets.js package. +*/ + +// Require the secrets package and assign it to a variable +const secrets = require('../secrets.js/secrets.js'); + +// If the script is executed directly, call the appropriate function based on arguments +if (require.main === module) { + const inputJson = process.argv[2]; + + if (!inputJson) { + console.error("No input provided."); + process.exit(1); + } + + try { + const inputData = JSON.parse(inputJson); + const output = { results: [] }; + + // Check if inputData has a "tasks" key + if ("tasks" in inputData && Array.isArray(inputData.tasks)) { + // Loop through tasks + for (const task of inputData.tasks) { + const taskResult = {}; + + // Check if task has a "setup" key + if ("setup" in task && Array.isArray(task.setup)) { + // Loop through setup tasks + for (const setupTask of task.setup) { + const setupFunction = setupTask.function; + const setupArguments = setupTask.args; + + // Dynamically call the setup function + const setupFn = secrets[setupFunction]; + + if (setupFn && typeof setupFn === 'function') { + try { + // Call the setup function + setupFn(...setupArguments); + taskResult.setupResult = { success: true }; + } catch (error) { + // Capture and report the error to stderr + console.error(error.message); + taskResult.setupResult = { success: false, error: error.message }; + } + } else { + // Report unknown function + const errorMessage = `Unknown function: ${setupFunction}`; + console.error(errorMessage); + taskResult.setupResult = { success: false, error: errorMessage }; + } + } + } + + // Check if task has a "start" key + if ("start" in task) { + const functionName = task.start.function; + const arguments = task.start.args; + + // Dynamically call the main function + const selectedFunction = secrets[functionName]; + + if (selectedFunction && typeof selectedFunction === 'function') { + try { + // Call the main function + const result = selectedFunction(...arguments); + taskResult.startResult = { success: true, result }; + } catch (error) { + // Capture and report the error to stderr + console.error(error.message); + taskResult.startResult = { success: false, error: error.message }; + } + } else { + // Report unknown function + const errorMessage = `Unknown function: ${functionName}`; + console.error(errorMessage); + taskResult.startResult = { success: false, error: errorMessage }; + } + } + + // Add task result to the output + output.results.push(taskResult); + } + + // Print the output as a JSON object + console.log(JSON.stringify(output)); + } + } catch (error) { + console.error("Error parsing or executing:", error.message); + // In case of an error, print a JSON object with an "error" key + console.log(JSON.stringify({ error: error.message })); + } +} + diff --git a/gems/wrapperV3_test.py b/gems/wrapperV3_test.py new file mode 100755 index 0000000..015b33d --- /dev/null +++ b/gems/wrapperV3_test.py @@ -0,0 +1,91 @@ +#! /usr/bin/env python3 +# -*- coding: utf-8 -*- +# vim: set et sw=4 fenc=utf-8: +# +# wrapperV3_test.py + +""" +This script demonstrates the third working version of calling Node.js to execute JavaScript using a wrapper to load the secrets.js package. +This version handles multiple commands, sent as setup and start. And have improved error handling. +""" + +import json +import subprocess + +# Path to the Node.js wrapper script +JS_FILE_PATH = "wrapperV3.js" + +def run_js_functions(input_data): + """ + Run a JavaScript function using the Node.js wrapper. + + Args: + input_data (dict): Dictionary containing the function name and arguments. + + Returns: + The result of the JavaScript function or None if there is an error. + """ + + # Enclose input_json in single quotes + js_command = ["node", JS_FILE_PATH, input_data] + + try: + # Run the command and capture the output and stderr + result = subprocess.run(js_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True) + + # Debugging statement to print stdout and stderr + # print("stdout:", result.stdout) + # print("stderr:", result.stderr) + + try: + # Attempt to load the entire stdout as JSON + js_result = json.loads(result.stdout) + + # Check if the result has 'error' or 'results' key + if js_result is not None and "results" in js_result: + start_result = js_result.get("results", [])[0].get("startResult", {}).get("result") + if start_result is not None: + print("Result of 'start' function:", start_result) + else: + print("No result found for 'start' function.") + elif js_result is not None and "error" in js_result: + print("JavaScript error:", js_result.get("error")) + else: + print("JavaScript output is missing 'error' or 'results' key.") + + # Print stderr if it exists + if result.stderr: + print("JavaScript stderr:", result.stderr) + + except json.JSONDecodeError as e: + print("Error decoding JSON:", e) + print("Raw stdout content:", result.stdout) + + except subprocess.CalledProcessError as e: + # Print the error from the JavaScript script + js_error = result.stderr.strip() + print("JavaScript error:", js_error) + return None + + +# Example usage +# Setup commands +setup = [ + {'function': 'setRNG', 'args': ['testRandom']}, +] + +# Dynamic Values +foo = ['1234abc', 6, 3] + +# Main function +main = {'function': 'share', 'args': foo} + +# Combine setup and main +tasks = {'tasks': [{'setup': setup, 'start': main}]} + +# Convert the Python dictionary to JSON +json_data = json.dumps(tasks, indent=None) +#print(json_data) + +run_js_functions(json_data) +