Experimenting using RunKit as a custom repl for nodejs. Warning, it starts off messy, but in the end we have a reusable nodejs custom REPL.

Table of Contents

Exploration

Embed

Lets start with just the simple demo embed, adding the embed script and a container below.

scriptinline
htmlinline
A container to hold the embed.

Run the #init cell below 👇 to populate it With some demo source.

Endpoint

jsxjsbelowreactendpoint
return (async fn => {

  const React = lit.utils.React
  const Embed = (await import('https://cdn.skypack.dev/runkit-embed-react')).default

  const createdAt = new Date()

  const helloSource = `exports.endpoint = function(request, response) {
    response.end("Hello world! From .lit and Nodejs thanks to RunKit. Created at " + createdAt);
}`

  const onLoad = (...args) => console.log(JSON.stringify([...args]))

  return <Embed
            mode='endpoint'
            readOnly={true}
            evaluateOnLoad={true}
            // hidesActionButton={true}
            source={ helloSource } 
            // ref='embed'
            onLoad={ onLoad } 
          />

})()
uribelow
https://2mkz0r1anfrl.runkit.sh/

Viewer plug-in

runkitinline
console.log("Hello world! From .lit and Nodejs thanks to RunKit.")
runkitbelowmode=endpoint
exports.endpoint = function(req, res) {
    res.end("Hello world! From .lit and Nodejs thanks to RunKit.");
}
runkitbelowmode=endpoint
exports.endpoint = function(req,res) {
  res.writeHead(200, {
    'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Methods': '*',
  });
  res.end('{"ping": "pong!"}')
}
js
return fetch("https://jzc0q8a4nyog.runkit.sh").then(res => res.text())
txtUpdated 58.6w ago
{"ping": "pong!"}

REPL Implementation

Split out the endpoint source to its own .lit cell for legibility instead of an inline string.

On load the following repl !plugin creates a RunKit endpoint if it doesn't exist using the above source.

Usage:

jsnodetest.jsid=exampleusage
module.exports = async (meta) => {
  return `Hello world! From .lit (${meta.id} ${meta.filename}) and Nodejs ${process.env.NODE_VERSION} (${process.platform} ${process.arch}) thanks to RunKit. At ${new Date()}`
}
txtUpdated 56.6w ago
{ result:
   'Hello world! From .lit (example test.js) and Nodejs 10.24.1 (linux x64) thanks to RunKit. At Sat May 29 2021 00:28:41 GMT+0000 (Coordinated Universal Time)' }

Next steps and improvements

  • Don't start the endpoint on every page load, and instead lazily setup just before first execution.
  • Don't use require module from string hack, and instead use a proper vm and context.
  • Create a testing/CORS Proxy