All files / builtins/shell index.ts

100% Statements 26/26
100% Branches 0/0
100% Functions 4/4
100% Lines 25/25

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 664x   4x 4x 4x     4x   4x   4x 3x             3x 3x 2x 2x 2x   1x           3x 3x       3x               3x 2x 2x   2x       1x   1x   1x       3x          
import {spawnSync, SpawnSyncReturns} from 'child_process';
 
import {loadAll, dump} from 'js-yaml';
import {z} from 'zod';
import {ERRORS} from '@grnsft/if-core/utils';
import {ExecutePlugin, PluginParams, ConfigParams} from '@grnsft/if-core/types';
 
import {validate} from '../../util/validations';
 
const {ProcessExecutionError} = ERRORS;
 
export const Shell = (globalConfig: ConfigParams): ExecutePlugin => {
  const metadata = {
    kind: 'execute',
  };
 
  /**
   * Calculate the total emissions for a list of inputs.
   */
  const execute = (inputs: PluginParams[]): any[] => {
    const inputWithConfig = Object.assign({}, inputs[0], validateConfig());
    const command = inputWithConfig.command;
    const inputAsString: string = dump(inputs, {indent: 2});
    const results = runModelInShell(inputAsString, command);
 
    return results?.outputs?.flat();
  };
 
  /**
   * Checks for required fields in input.
   */
  const validateConfig = () => {
    const schema = z.object({
      command: z.string(),
    });
 
    return validate<z.infer<typeof schema>>(schema, globalConfig);
  };
 
  /**
   * Runs the model in a shell. Spawns a child process to run an external IMP,
   * an executable with a CLI exposing two methods: `--execute` and `--manifest`.
   * The shell command then calls the `--command` method passing var manifest as the path to the desired manifest file.
   */
  const runModelInShell = (input: string, command: string) => {
    try {
      const [executable, ...args] = command.split(' ');
 
      const result: SpawnSyncReturns<string> = spawnSync(executable, args, {
        input,
        encoding: 'utf8',
      });
      const outputs = loadAll(result.stdout);
 
      return {outputs};
    } catch (error: any) {
      throw new ProcessExecutionError(error.message);
    }
  };
 
  return {
    metadata,
    execute,
  };
};