websh v1.0.3
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 issues
Pipe 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