1.7.3 • Published 4 years ago

@osjs/proc-provider v1.7.3

Weekly downloads
-
License
MIT
Repository
github
Last release
4 years ago

OS.js is an open-source web desktop platform with a window manager, application APIs, GUI toolkit, filesystem abstractions and much more.

Support Support Donate Donate Community

OS.js Proc Service Provider

Adds support for spawning and piping processes and pseudo terminals on the node server.

Communicates via the internal websocket.

Installation

npm install @osjs/proc-provider

In your initialization scripts:

// Client index.js file
import {ProcServiceProvider} from '@osjs/proc-provider';
osjs.register(ProcServiceProvider);

// Client index.scss file
@import "~@osjs/proc-provider/dist/main.css";

// Server index.js file
const {ProcServiceProvider} = require('@osjs/proc-provider/src/server.js');
osjs.register(ProcServiceProvider);

Configuration

By default the server provider is set up to only allow users with the admin group to access this feature.

You can change this by adding options:

const {ProcServiceProvider} = require('@osjs/proc-provider/src/server.js');
osjs.register(ProcServiceProvider, {
  args: {
    groups: ['other-group']
  }
});

API

You can reach this service with core.make('osjs/proc').

  • pty(cmd, ...args) => Promise<p, Error> - Creates a new pseudo terminal over websocket
  • spawn(cmd, ...args) => Promise<p, Error> - Spawns a new process over websocket
  • exec(cmd, ...args) => Promise<{code, stdout, stderr}, Error> - Execs a process over http
  • xterm(win[, options]) => Xterm - Creates a new xterm.js class instance and bind it to a window

The cmd can either be a string, or an object: {cmd: string, env: {A: 'value'}}.

The p returned in a promise resolution is an EventEmitter with some special methods for interacting with the process.

See examples below.

Pseudo terminal over websocket

Execute a process, but inside a PTY. This makes it possible to use interactive processes.

Note that it is not possible to differentiate between stdout and stderr in this case.

core.make('osjs/proc')
  .pty('ls')
  .then(p => {
    // Process events
    p.on('data', str => console.log(str))
    p.on('exit', code => console.info(code))

    // Internal events
    p.on('spawned', () => {}); // Spawn successful
    p.on('error', error => console.error(error)); // Spawn errors

    // Send data to the shell
    p.send('Hello World\n');

    // You can kill long running processes
    p.kill();
  })

Execute over websocket

Execute a process via standard node child_process.

Note that processes that requires an interactive shell won't work here. See PTY above.

core.make('osjs/proc')
  .spawn('ls')
  .then(p => {
    // Process events
    p.on('stdout', str => console.log(str))
    p.on('stderr', str => console.warn(str))
    p.on('exit', code => console.info(code))

    // Internal events
    p.on('spawned', () => {}); // Spawn successful
    p.on('error', error => console.error(error)); // Spawn errors

    // You can kill long running processes
    p.kill();
  })

Execute over http

Directly execute a program via child_process and return the result.

core.make('osjs/proc')
  .exec('ls')
  .then(({stdout, stderr, code}) => console.log(stdout, stderr, code))

Passing arguments

core.make('osjs/proc')
  .spawn('ls', '-l') // Works for all methods

Passing environmental variables

You can also pass environmental data to all methods.

core.make('osjs/proc')
  .spawn({cmd: 'ls', env: {foo: 'bar'}}) // Works for all methods

Spawning windows to monitor output

For a PTY this also supports input. Just spawn a process as above, but:

core.make('osjs/proc')
  .pty('ls')
  .then(p => {
    const win = p.createWindow({
      // Keep window open for as long as you want
      keepOpen: false
    })

    // Close window after 2.5s when command is complete
    p.on('exit', () => setTimeout(() => win.destroy(), 2500))
  })

Attaching a shell via GUI

You can attach an Xterm (PTY recommended) to any arbitrary DOM element.

This example shows you how to use it in Hyperapp:

Note that the xterm reference is a xterm.js class instance. The addon fit has been loaded and you can specify terminal options via the second argument: .xterm(win, {terminal: {}}).

import {h, app} from 'hyperapp';
import {Box} from '@osjs/gui';

// Create a custom hyperapp component
// The CSS is included by this provider
const XtermElement = props => h('div', {
  class: 'osjs-gui osjs-gui-xterm',
  oncreate: el => props.xterm.open(el),
  onclick: () => props.xterm.focus()
});

// When you render your window, create a new Xterm reference
// Then provide it as a reference to the component
win.render(($content, win) => {
  const pp = core.make('osjs/proc');
  const xterm = pp.xterm(win);
  const hyperapp = app({}, {
    runPty: () => {
      pp.pty('ls', '-l')
        .then(p => p.attachXterm(xterm))
        .catch(error => console.error(error));
    }
  }, (state, actions) => {
    return h(Box, {
      grow: 1,
      shrink: 1
    }, h(XtermElement, {xterm}));
  }, $content);

  // Execute immediately. You can call this action from a button or whatever
  // using components
  hyperapp.runPty();
});

Features

  • Launch processes via websocket (pipeable)
  • Launch pseudo terminals via websocket (pipeable)
  • Launch process via http
  • Support for manually killing a running process
  • Server clears out stale processes (ex when client disconnects)
  • Works on all platforms

TODO

  • Add option for spawning standalone socket
  • Move the HTTP API purely to websocket signals ?
  • Add a system socket and host service
  • Add shell method for direct PTY

Contribution

Documentation

See the Official Manuals for articles, tutorials and guides.

Links

1.7.3

4 years ago

1.7.2

4 years ago

1.7.1

5 years ago

1.7.0

5 years ago

1.6.2

5 years ago

1.6.1

5 years ago

1.6.0

5 years ago

1.5.0

5 years ago

1.0.5

5 years ago

1.0.4

5 years ago

1.0.3

5 years ago

1.0.2

5 years ago

1.0.1

5 years ago