<commit_before>import { App } from "../../lib";

import * as path from 'path';
import * as cp from 'child_process';

import { buffer } from './buffer';
import * as fs from 'fs';
import * as execa from 'execa';

export class Npx {
	constructor(private app: App) {}

	call(args, bufferized?: boolean) {
		const cwd = this.app.path;

		const npmPath = path.join(
			__dirname,
			'node_modules',
			'npm',
			'bin',
			`npx-cli.js`
		);
		const proc = cp.fork(npmPath, args, {
			cwd: cwd,
			silent: true
		});
		if (bufferized) {
			return buffer(proc);
		} else {
			return proc;
		}
	}

	exec(command: string, params?: string[]): Promise<any> {
		return new Promise((resolve, reject) => {
			let data = '';
			let stream = null;
			if (fs.existsSync(path.resolve(`node_modules/.bin/npx`))) {
				stream = execa(path.resolve(`node_modules/.bin/npx`), [command, ...params], {
					cwd: this.app.path
				});
			} else {
				stream = execa(path.join(path.resolve(), `resources/node_modules/.bin/npx`), [command, ...params], {
					cwd: this.app.path
				});
			}
			stream.stdout.on('data', d => {
				data += d;
			});
			stream.stderr.on('data', (d) => {
				data += d;
			});

			stream.on('close', (code) => {
				if (code == 0) {
					return resolve(data);
				} else {
					return reject({
						code,
						data
					});<commit_msg>(Api/NpxLib) Fix npx path: use which to discover global path<commit_after>import * as execa from 'execa';
import * as which from 'which';

import { App } from "../../lib";

export class Npx {

	constructor(private app: App) {}

	exec(command: string, params?: string[]): Promise<any> {
		return new Promise((resolve, reject) => {
			return this._getNpxPath().then(npxPath => {
				let data = '';
				const stream = execa(npxPath, [command, ...params], {
					cwd: this.app.path
				});
				stream.stdout.on('data', d => {
					data += d;
				});
				stream.stderr.on('data', (d) => {
					data += d;
				});

				stream.on('close', (code) => {
					if (code == 0) {
						return resolve(data);
					} else {
						return reject({
							code,
							data
						});
					}
				});
			});
		});
	}

	private _getNpxPath() {
		return new Promise((resolve, reject) => {
			which('npx', (err, npxPath) => {
				if (err && ! npxPath) {
					if (this.app) {
						this.app.logger.error(`npx -> path error: ${err}`)
					}
					reject(err);
				} else {
					if (this.app) {
						this.app.logger.log(`npx -> path: ${npxPath}`)
					}
					resolve(npxPath)
{'fraction_non_alphanumeric': 0.18832997987927566, 'fraction_numerical': 0.0008048289738430583, 'mean_word_length': 2.4866760168302946, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 18, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '465542', 'n_tokens_mistral': 1117, 'n_tokens_neox': 876, 'n_words': 208}