README
Web.sh
This project aims to form kind of a shell for the web. It connects web-apps via window-messaging and let's you compose them like a shell-script. ** Tests
+BEGIN_SRC sh
npm install npm test
+END_SRC
** API
All public symbols are exported from the Websh.js module in the
root of the repository. All other modules should be considered
private and subject to change.
*** websh(driver?: Driver = inlineIframeDriver()): Websh
This function is the default export of the module and the
constructor for shell instances. Each shell instance closes over
a driver that abstracts the mechanism to talk to an iframe
instance. The default driver ~inlineIframeDriver~ creates a
full-screen iframe automatically and uses it as output. If you
need more control over the creation and the style of the iframe
use the ~iframeDriver~. The function returns a `Websh` instance
which is a function that expects the script as a string argument.
#+BEGIN_SRC js
import websh from './Websh.js'
const sh = websh()
sh('examples/input | examples/sed?regex=Foo&replace=bar | examples/cat')
.then(output => {
console.log(output) // This is the received output
})
#+END_SRC
*** iframeDriver(iframeElement: DOMElement): Driver
This is a more flexible driver than the default
~inlineIframeDriver~ which let's you control the iframe yourself.
#+BEGIN_SRC js
import websh, { iframeDriver } from './Websh.js'
const driver = iframeDriver(document.getElementById('my-iframe'))
const sh = websh(driver)
// ...
#+END_SRC
** Shell language
The shell-language is designed to be lightweight and easy to pick-up and learn. It's heavily inspired by unix shell scripts. *** Example
#+BEGIN_SRC sh
# Pipelines
https://mypage.com/prompt-input | https://secondpage.com/
# Parameters
https://mypage.com/prompt-input?text=Hello%20world
#+END_SRC
** Program interface
A script executes multiple so-called programs. These programs are web-apps that utilize the window messaging API to communicate with the system. *** Execution-flow
- The program is being loaded in an ~iframe~
- Then the content from the standard-input is being transmitted to
the content-window of the iframe using the following command:
#+BEGIN_SRC js
iframe.contentWindow.postMessage(["stdin", [] /* Array of input lines */])
#+END_SRC
This ~Array of input lines~ is an array filled with data from
the output that the previous program generated. If this is the
first program being executed the ~Array of input lines~ is an
empty array.
- The program should then use the input (or ignore if not need)
and generate output using the ~print~ [[*System%20calls][system-call]]:
#+BEGIN_SRC js
window.parent.postMessage(["print", "Sample output" /* The output data */])
#+END_SRC
The ~print~ system-call can be used multiple times to generate
multiple "output lines".
- Once the program finishes it should use the ~exit~ system-call
to handover the execution back to the system so that the next
program can be called.
*** System calls
The system communication is handled by sys-call-like messages with
the following syntax:
#+BEGIN_SRC javascript
["print", { my: 'message' }]
#+END_SRC
- ~print(<chunks>, ...)~
This command sends output chunks to the system.
- ~exit(<exitCode>)~
This command exits the currently running process and hands-over
an exit code. A non-zero exit-code means failure and stops the
execution of the script immediately.
** Security implications
Commands that operate on sensible user-data should use the second parameter of
window.parent.postMessage()to avoid sending data to malicious targets. ** Known issuesPipe characters in the query params to a command aren't handled correctly ** Missing features
The shell web-app should itself act like a program. E.g. sent the input to the first program and send back the output to the calling system. ** Thoughts / ideas
Environment variables: Global variables that are passed to each program