All files / lib environment.ts

97.14% Statements 34/35
77.77% Branches 7/9
100% Functions 5/5
97.05% Lines 33/34

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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 981x   1x       1x   1x   1x   1x               1x 3x   3x 3x   3x   3x       3x           1x 3x 90x 90x 90x   90x 90x       90x             1x 3x 3x   3x 3x   3x                 1x     3x   3x 3x 3x   3x                                
import {DateTime} from 'luxon';
 
import {execPromise} from '../util/helpers';
 
import {Manifest} from '../types/manifest';
import {NpmListResponse, PackageDependency} from '../types/environment';
import {osInfo} from '../util/os-checker';
 
import {STRINGS} from '../config/strings';
 
const packageJson = require('../../package.json');
 
const {CAPTURING_RUNTIME_ENVIRONMENT_DATA} = STRINGS;
 
/**
 * 1. Gets the high-resolution real time when the application starts.
 * 2. Converts the high-resolution time to milliseconds.
 * 3. Gets the current DateTime.
 * 4. Subtracts the milliseconds from the current DateTime.
 */
const getProcessStartingTimestamp = () => {
  const startTime = process.hrtime();
 
  const [seconds, nanoseconds] = process.hrtime(startTime);
  const milliseconds = seconds * 1000 + nanoseconds / 1e6;
 
  const currentDateTime = DateTime.local();
 
  const applicationStartDateTime = currentDateTime.minus({
    milliseconds: milliseconds,
  });
 
  return applicationStartDateTime.toUTC().toString();
};
 
/**
 * Goes through the dependencies, converts them into oneliner.
 */
const flattenDependencies = (dependencies: [string, PackageDependency][]) =>
  dependencies.map(dependency => {
    const [packageName, versionInfo] = dependency;
    const {version, extraneous, resolved} = versionInfo;
    const ifExtraneous = extraneous ? ` extraneous -> ${resolved}` : '';
    const ifFromGithub =
      resolved && resolved.startsWith('git') ? ` (${resolved})` : '';
    const formattedString = `${packageName}@${version}${
      ifExtraneous || ifFromGithub
    }`;
 
    return formattedString;
  });
 
/**
 * 1. Runs `npm list --json`.
 * 2. Parses json data and converts to list.
 */
const listDependencies = async () => {
  const {stdout} = await execPromise('npm list --json');
  const npmListResponse: NpmListResponse = JSON.parse(stdout);
 
  if (npmListResponse.dependencies) {
    const dependencies = Object.entries(npmListResponse.dependencies);
 
    return flattenDependencies(dependencies);
  }
 
  return [];
};
 
/**
 * Injects execution information (command, environment) to existing manifest.
 */
export const injectEnvironment = async (
  manifest: Manifest
): Promise<Manifest> => {
  console.debug(CAPTURING_RUNTIME_ENVIRONMENT_DATA);
 
  const dependencies = await listDependencies();
  const info = await osInfo();
  const dateTime = `${getProcessStartingTimestamp()} (UTC)`;
 
  return {
    ...manifest,
    execution: {
      status: 'success',
      command: process.argv.join(' '),
      environment: {
        'if-version': packageJson.version,
        os: info.os,
        'os-version': info['os-version'],
        'node-version': process.versions.node,
        'date-time': dateTime,
        dependencies,
      },
    },
  };
};