npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

full-powershell

v3.0.2

Published

![alt text](img/waves.svg)

Downloads

3,001

Readme

alt text

Full Powershell

Capture, separate and serialise all 6 PowerShell message streams at their source.

How it works

PowerShell has 6 message streams in addition to Stdout and Stderr. Cramming these 6 streams all through stdout removes each stream's semantics and is a nightmare to parse. Unexpected and intermittent warning or error messages (very common when remoting!) will make your application very brittle. Full-PowerShell sorts these streams before returning them, so output from one stream will not affect the other, so unexpected server messages won't break your program.

This library accepts PowerShell commands as strings. It wraps those commands in an Invoke-Command block that pipes their output into individual streams. All 6 message streams are captured and sorted at their source, they are then serialised using PowerShell's standard ConvertTo-JSON function, sent back to the parent Node.js process, before finally being deserilaised as individual streams. They can be subscribed to as an RxJS Observable, or as a Promise.

The source code is fairly concise, take a look at index.ts and wrapper.ts to see exactly how it works.

API

The PowerShell class.

Spawns a PowerShell child process on instantiation and exposes methods to read/write to/from that process:

class PowerShell {
    constructor(private options?: PowerShellOptions);
    success$: Subject<any[]>();
    error$: Subject<any[]>();
    warning$: Subject<any[]>();
    verbose$: Subject<any[]>();
    debug$: Subject<any[]>();
    info$: Subject<any[]>();
    call(command: string, format: Format = 'json'): SubjectWithPromise<PowerShellStreams>;
    destroy(): SubjectWithPromise<boolean>;
}

Note: The SubjectWithPromise object returned by call() will only emit the value returned by the command passed to call(). Use the streams postfixed with $ to listen to output from all calls made to that PowerShell instance.

The PowerShellStreams object.

Emittied by the <Observable|Promise> returned from .call().subscribe() or .call().promise().

interface PowerShellStreams {
    success: any[];
    error: any[];
    warning: any[];
    verbose: any[];
    debug: any[];
    info: any[];
}

The subjects exposed by the PowerShell class, as well as the singleton observable/promise returned by PowerShell.call all return arrays of strings or parsed JSON. It's important to note that these arrays reflect the output for each PowerShell command passed to PowerShell.call. For example, if you were to call PowerShell.call('Get-Date; Get-Date;'), you should expect to receive an Array containing two items in the next emission's success stream. However, there are exceptions to this - debug and verbose are newline delimited due to limitations of PowerShell redirection. While they will generally equate to one string per Write-Debug or Write-Verbose, it is up to you to ensure output has not been broken into multiple lines.

Importing:

ES6

import { PowerShell } from 'full-powershell';

CommonJS

const { PowerShell } = require('full-powershell');

Instantiating:

const shell = new PowerShell();

Options:

interface PowerShellOptions {
    tmp_dir?: string
    exe_path?: string
    timeout?: number
}
  • tmp_dir - Default: current directory Change the path for ephemeral '.tmp' files. Must have a trailing slash. (Must be set to /tmp/ when executing on AWS Lambda).

  • exe_path - Default: powershell for windows, pwsh for nix. Explicitly set the path or command name for the PowerShell executable (example: 'pwsh' or 'C:\\Program Files\\PowerShell\\7\\pwsh.exe')

  • timeout - Default: 10 minutes. Set number of milliseconds before each call to this shell will timeout. Warning: A timeout will result in the PowerShell child process being terminated and a new process created, any pending calls will be errored and PowerShell context will be lost.

Example:

const options: PowerShellOptions = {
    tmp_dir: '/tmp/'
    exe_path: 'pwsh',
    timeout: 60000
}
const shell = new PowerShell(options);

Executing PowerShell Commands:

The call method accepts a PowerShell command as a string, and an optional Format parameter. Use the format parameter to change how command output is serialised before returing it from PowerShell.

type Format = 'string' | 'json' | null;

shell.call(command: string, format: Format = 'json')

The call method returns an SubjectWithPromise object that provides two methods for handling the response:

  • subscribe - an RxJS Subject
  • promise - a standard JavaScript promise

Subscribing to the RxJS Subject:

Subscribe directly to a call by calling subscribe() on the returned object (observable will complete after first emission):

shell.call('My-Command')
.subscribe(
    (res: PowerShellStreams) => {
        /* result handler */
    },
    (err: Error) => {
        /* error handler */
    }
);

Async/Await:

The object returned by the call method also exposes a function called promise() which returns a promise instead of a subscription.

const { success, error, warning } = await shell.call('My-Command').promise();

Subscribing to all events:

In addition to subscribing/awaiting to individual calls, you can subscribe to the message streams individually. These Subscriptions will emit the results of all calls made to the instance. This may be useful for logging.

const shell = new PowerShell();

shell.success$
.subscribe(
    (res: Array<any>) => {
        /* result handler */
    },
    (err: Error) => {
        /* error handler */
    }
);

shell.error$.subscribe( /* same as success$ */);
shell.warning$.subscribe( /* same as success$ */);
shell.verbose$.subscribe( /* same as success$ */);
shell.debug$.subscribe( /* same as success$ */);
shell.info$.subscribe( /* same as success$ */);

Closing the Child Process:

It's important to signal when you are finished with the instance, otherwise your program might not exit gracefully. You should also wait for this task to complete.

shell.destroy().subscribe((destroyed: boolean) => { /*...*/ });

or

const destroyed: boolean = await shell.destroy().promise();