Compare commits

..

9 Commits

Author SHA1 Message Date
baa3e4e6e9 2.0.5 2018-08-04 16:43:02 +02:00
0d68361381 fix(PATH): add proper PATH handling for child processes 2018-08-04 16:43:02 +02:00
286d80328c 2.0.4 2018-07-30 16:34:45 +02:00
2a71f00ab0 2.0.3 2018-07-30 16:19:38 +02:00
80a44a43cb fix(ci): update build step to be faster 2018-07-30 16:19:38 +02:00
5ea780acda 2.0.2 2018-07-30 16:08:14 +02:00
7c9cf6e70d fix(structure): clean up 2018-07-30 16:08:14 +02:00
697f789b55 2.0.1 2018-07-30 16:06:43 +02:00
f452964779 fix(test): add test for environment 2018-07-30 16:06:43 +02:00
9 changed files with 119 additions and 143 deletions

View File

@ -117,8 +117,9 @@ pages:
image: hosttoday/ht-docker-node:npmci
stage: metadata
script:
- npmci command npm install -g npmpage
- npmci command npmpage
- npmci command npm install -g typedoc typescript
- npmci npm install
- npmci command typedoc --module "commonjs" --target "ES2016" --out public/ ts/
tags:
- docker
- notpriv

View File

@ -1,9 +1,6 @@
{
"npmci": {
"npmGlobalTools": [
"npmts",
"ts-node"
],
"npmGlobalTools": [],
"npmAccessLevel": "public"
}
}

36
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "@pushrocks/smartshell",
"version": "2.0.0",
"version": "2.0.5",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -14,6 +14,19 @@
"nan": "^2.9.2"
}
},
"@gitzone/tsbuild": {
"version": "2.0.21",
"resolved": "https://registry.npmjs.org/@gitzone/tsbuild/-/tsbuild-2.0.21.tgz",
"integrity": "sha512-MAKfqnhf+42twSzXziRoBCu+sW61+2Rvc5qXxpEb594Fpnsj28cZ1VIEckSmiAkoBSiCnoU+2/qea2ycwWMBTg==",
"dev": true,
"requires": {
"@pushrocks/smartfile": "^6.0.3",
"@pushrocks/smartlog": "^2.0.1",
"@pushrocks/smartpath": "^4.0.1",
"@pushrocks/smartpromise": "^2.0.5",
"typescript": "^2.9.2"
}
},
"@gitzone/tsrun": {
"version": "1.1.9",
"resolved": "https://registry.npmjs.org/@gitzone/tsrun/-/tsrun-1.1.9.tgz",
@ -51,6 +64,27 @@
"vinyl-file": "^3.0.0"
}
},
"@pushrocks/smartlog": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@pushrocks/smartlog/-/smartlog-2.0.1.tgz",
"integrity": "sha512-GtsDTGIUF3VuWPyF8FV5dF31ZCEIcaJ56ZlvJsWxjnyJq57X25mk5/K0QAaRE9IIeHg6fORcukFomb5C+AOQrg==",
"dev": true,
"requires": {
"@pushrocks/smartlog-interfaces": "^1.0.9"
}
},
"@pushrocks/smartlog-interfaces": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@pushrocks/smartlog-interfaces/-/smartlog-interfaces-1.0.9.tgz",
"integrity": "sha512-0qwpomrRN0kFjmhR9m1iHYXoISoNuXtRP0Wr+JtkYyURLwKHMaW8Xoznf8MzXJptRfqufJi3Fxh5HodpPrIZUA==",
"dev": true
},
"@pushrocks/smartpath": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@pushrocks/smartpath/-/smartpath-4.0.1.tgz",
"integrity": "sha512-MaI0+uLQPCr2V3WGnbdgb0pWa9xkWyrP4qYcbsHIjeismGLbn9s3jmP/HIXU8LkgzRgaVb+BJxmZJHOwl32DyA==",
"dev": true
},
"@pushrocks/smartpromise": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@pushrocks/smartpromise/-/smartpromise-2.0.5.tgz",

View File

@ -1,13 +1,13 @@
{
"name": "@pushrocks/smartshell",
"private": false,
"version": "2.0.0",
"version": "2.0.5",
"description": "shell actions designed as promises",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"scripts": {
"test": "(tsrun test/test.ts)",
"build": "(npmts)"
"build": "(tsbuild)"
},
"repository": {
"type": "git",
@ -24,6 +24,7 @@
},
"homepage": "https://gitlab.com/pushrocks/smartshell#README",
"devDependencies": {
"@gitzone/tsbuild": "^2.0.21",
"@gitzone/tsrun": "^1.1.9",
"@pushrocks/tapbundle": "^3.0.1",
"@types/node": "^10.5.2"

View File

@ -44,6 +44,10 @@ tap.test('smartshell should run async', async () => {
});
});
tap.test('should be able to find git', async () => {
testSmartshell.exec('git --version');
});
tap.start({
throwOnError: true
});

View File

@ -1,27 +1,53 @@
export type TExecutor = 'sh' | 'bash';
export type TExecutor = "sh" | "bash";
export interface IShellEnvContructorOptions {
executor: TExecutor;
sourceFilePaths: string[];
sourceFilePaths?: string[];
pathDirectories?: string[];
}
export class ShellEnv {
executor: TExecutor;
sourceFileArray: string[] = [];
pathDirArray: string[] = [];
/**
* constructor for the shellenv
*/
constructor(optionsArg: IShellEnvContructorOptions) {
this.executor = optionsArg.executor;
for (let sourceFilePath of optionsArg.sourceFilePaths) {
this.sourceFileArray.push(sourceFilePath);
// add sourcefiles
if (optionsArg.sourceFilePaths) {
this.sourceFileArray = this.sourceFileArray.concat(
optionsArg.sourceFilePaths
);
}
};
// add pathDirectories
if (optionsArg.pathDirectories) {
this.pathDirArray = this.pathDirArray.concat(optionsArg.pathDirectories);
}
}
/**
* imports path into the shell from env if available and returns it with
*/
private _setPath(commandStringArg): string {
let commandResult = commandStringArg;
let commandPath = process.env.PATH;
if (process.env.SMARTSHELL_PATH) {
commandPath = `${commandPath}:${process.env.SMARTSHELL_PATH}`;
}
commandResult = `PATH=${
commandPath
} && ${commandStringArg}`;
return commandResult;
}
/**
* add files that are going to be sourced when running a command
* @param sourceFilePathsArray
* @param sourceFilePathsArray
*/
addSourceFiles(sourceFilePathsArray: string[]) {
for (let sourceFilePath of sourceFilePathsArray) {
@ -37,14 +63,15 @@ export class ShellEnv {
}
createEnvExecString(commandArg): string {
if (this.executor === 'bash') {
let sourceString = '';
let commandResult = ''
if (this.executor === "bash") {
let sourceString = "";
for (let sourceFilePath of this.sourceFileArray) {
sourceString = sourceString + `source ${sourceFilePath} && `;
}
return `bash -c '${sourceString} ${commandArg}'`;
} else {
return commandArg;
commandResult = `bash -c '${sourceString} ${commandArg}'`;
}
commandResult = this._setPath(commandResult);
return commandResult;
}
}
}

View File

@ -9,7 +9,7 @@ export class ShellLog {
/**
* log data to console
* @param dataArg
* @param dataArg
*/
logToConsole(dataArg: string | Buffer): void {
// make sure we have the data as string
@ -34,11 +34,11 @@ export class ShellLog {
}
return dataArg;
})();
this.logStore = Buffer.concat([this.logStore,dataBuffer]);
this.logStore = Buffer.concat([this.logStore, dataBuffer]);
}
logAndAdd(dataArg: string | Buffer): void {
this.logToConsole(dataArg);
this.addToBuffer(dataArg);
}
}
}

View File

@ -1,11 +1,10 @@
// -- imports --
import * as plugins from './smartshell.plugins';
import * as smartshellWrap from './smartshell.wrap';
import { ShellEnv, IShellEnvContructorOptions, TExecutor, } from './smartshell.classes.shellenv';
import { ShellEnv, IShellEnvContructorOptions, TExecutor } from './smartshell.classes.shellenv';
import { ShellLog } from './smartshell.classes.shelllog';
import * as cp from "child_process";
import { Deferred } from "@pushrocks/smartpromise";
import * as cp from 'child_process';
import { Deferred } from '@pushrocks/smartpromise';
// -- interfaces --
/**
@ -30,26 +29,13 @@ export class Smartshell {
constructor(optionsArg: IShellEnvContructorOptions) {
this.shellEnv = new ShellEnv(optionsArg);
}
/**
* imports path into the shell from env if available and returns it with
*/
private _importEnvVarPath (stringArg): string {
if (process.env.SMARTSHELL_PATH) {
let commandResult = `PATH=${process.env.SMARTSHELL_PATH} && ${stringArg}`;
// console.log(commandResult)
return commandResult;
} else {
return stringArg;
}
};
/**
* executes a given command async
* @param commandStringArg
*/
private async _exec (
private async _exec(
commandStringArg: string,
silentArg: boolean = false,
strictArg = false,
@ -59,46 +45,45 @@ export class Smartshell {
const done = plugins.smartpromise.defer<IExecResult | IExecResultStreaming>();
const childProcessEnded = plugins.smartpromise.defer<IExecResult>();
// build commandToExecute
let commandToExecute = commandStringArg
let commandToExecute = commandStringArg;
commandToExecute = this.shellEnv.createEnvExecString(commandStringArg);
commandToExecute = this._importEnvVarPath(commandToExecute);
const spawnlogInstance = new ShellLog();
const execChildProcess = cp.spawn(commandToExecute, [], {
shell: true,
env: process.env
});
execChildProcess.stdout.on("data", data => {
execChildProcess.stdout.on('data', data => {
if (!silentArg) {
spawnlogInstance.logToConsole(data);
}
spawnlogInstance.addToBuffer(data);
});
execChildProcess.stderr.on("data", data => {
execChildProcess.stderr.on('data', data => {
if (!silentArg) {
spawnlogInstance.logToConsole(data);
}
spawnlogInstance.addToBuffer(data);
});
if(streamingArg) {
if (streamingArg) {
done.resolve({
childProcess: execChildProcess,
finalPromise: childProcessEnded.promise
});
}
execChildProcess.on("exit", (code, signal) => {
if(strictArg && code === 1) {
execChildProcess.on('exit', (code, signal) => {
if (strictArg && code === 1) {
done.reject();
}
const execResult = {
exitCode: code,
stdout: spawnlogInstance.logStore.toString()
}
};
if(!streamingArg) {
if (!streamingArg) {
done.resolve(execResult);
}
childProcessEnded.resolve(execResult);
@ -106,72 +91,58 @@ export class Smartshell {
const result = await done.promise;
return result;
};
}
async exec (
commandStringArg: string
): Promise<IExecResult> {
async exec(commandStringArg: string): Promise<IExecResult> {
return (await this._exec(commandStringArg, false)) as IExecResult;
};
}
/**
* executes a given command async and silent
* @param commandStringArg
*/
async execSilent (
commandStringArg: string
): Promise<IExecResult> {
async execSilent(commandStringArg: string): Promise<IExecResult> {
return (await this._exec(commandStringArg, true)) as IExecResult;
};
}
/**
* executes a command async and strict, meaning it rejects the promise if something happens
*/
async execStrict (
commandStringArg: string
): Promise<IExecResult> {
return (await this._exec(commandStringArg, true, true)) as IExecResult;
};
async execStrict(commandStringArg: string): Promise<IExecResult> {
return (await this._exec(commandStringArg, true, true)) as IExecResult;
}
/**
* executes a command and allows you to stream output
*/
async execStreaming (
async execStreaming(
commandStringArg: string,
silentArg: boolean = false
): Promise<IExecResultStreaming> {
return (await this._exec(commandStringArg, silentArg, false, true)) as IExecResultStreaming;
};
}
async execStreamingSilent (commandStringArg: string) {
async execStreamingSilent(commandStringArg: string) {
return (await this.execStreaming(commandStringArg, true)) as IExecResultStreaming;
};
}
/**
* executes a command and returns promise that will be fullfilled once an putput line matches RegexArg
* @param commandStringArg
* @param regexArg
*/
async execAndWaitForLine (
commandStringArg: string,
regexArg: RegExp,
silentArg: boolean = false
) {
async execAndWaitForLine(commandStringArg: string, regexArg: RegExp, silentArg: boolean = false) {
let done = plugins.smartpromise.defer();
let execStreamingResult = await this.execStreaming(commandStringArg, silentArg);
execStreamingResult.childProcess.stdout.on("data", (stdOutChunk: string) => {
execStreamingResult.childProcess.stdout.on('data', (stdOutChunk: string) => {
if (regexArg.test(stdOutChunk)) {
done.resolve();
}
});
return done.promise;
};
}
async execAndWaitForLineSilent (
commandStringArg: string,
regexArg: RegExp
) {
async execAndWaitForLineSilent(commandStringArg: string, regexArg: RegExp) {
this.execAndWaitForLine(commandStringArg, regexArg, true);
};
}
}

View File

@ -1,59 +0,0 @@
import * as plugins from "./smartshell.plugins";
import { ShellLog } from "./smartshell.classes.shelllog";
// interfaces
import * as cp from "child_process";
import { Deferred } from "@pushrocks/smartpromise";
/**
* interface for ExecResult
*/
export interface IExecResult {
exitCode: number;
stdout: string;
}
/**
* interface for streaming ExecResult
*/
export interface IExecResultStreaming {
childProcess: cp.ChildProcess;
finalPromise: Promise<IExecResult>;
}
/**
* get a path
*/
export let which = (cmd: string): Promise<string> => {
let done = plugins.smartpromise.defer<string>();
plugins.which(cmd, (err, path: string) => {
if (err) {
done.reject(err);
}
done.resolve(path);
});
return done.promise;
};
/* /////////////////////////////////////////////////////////
/**
* executes silently and returns IExecResult
* @param commandArg
async execSilent(commandArg: string) {
let execCommand = this..createExecString(commandArg);
return await smartshellWrap.execSilent(execCommand);
}
/**
* executes and returns IExecResult
* @param commandArg
async exec(commandArg: string) {
let execCommand = this.createExecString(commandArg);
return await smartshellWrap.exec(execCommand);
} */