Giter Club home page Giter Club logo

nodebox-runtime's Introduction

Nodebox

Nodebox is a runtime for executing Node.js modules in the browser.

Why we built Nodebox

With sandpack-bundler, we allowed any developer anywhere to instantly create a fast, local, shareable playground inside their browser, without having to wait forever to install dependencies and fight with devtools. This improves the learning, experimentation and sharing experience of client-side JavaScript code.

However, server-side JavaScript remained a challenge. At CodeSandbox we have solved this by using Firecracker VMs, allowing us to bring your entire development environment to the cloud regardless of the programming language or tooling you might be using. Unfortunately, as VMs live in the cloud, they require infrastructure and a network connection, resulting in a higher cost compared to our client-side sandboxes.

To solve this problem, we built Nodebox, a runtime that runs entirely in the browser, eliminating the need for a network connection and infrastructure.

Nodebox gives you the same user experience you have come to expect from Sandpack, which means a near-instant server-side JavaScript environment at the click of a button—built for experimentation, examples and documentation.

The differences between a VM and Nodebox

As mentioned in the previous section, we solved server-side sandboxes in CodeSandbox by using Firecracker VMs. In this section, we'll explain the advantages and disadvantages of each approach.

Advantages of VMs over Nodebox

  • You get dedicated resources, with no resource limits enforced by the browser
  • You have an entire Unix OS available
  • You can run any language, database, command
  • You can use network sockets
  • You can run large and complex projects
  • A perfect 1:1 environment as compared to your local setup (at least, if you're using a Unix-based system)
  • No emulation, so Node.js would run exactly the same way as locally

Advantages of Nodebox

  • No need for any infrastructure
  • No need for a network connection
  • Instant feedback to any change
  • Easy to get started
  • Easy and instant reset - simply refresh the page/iframe
  • Every page visitor gets their own Nodebox instance automatically

What makes it different

Nodebox is currently the only cross-browser Node.js runtime supporting all the latest browsers:

  • Chrome;
  • Firefox;
  • Safari *
  • Support for iOS Safari is in beta

Nodebox does not emulate Node.js but is, instead, a Node.js-compatible runtime. This means that it implements as much of the Node.js API as possible while keeping a minimal performance imprint, using browser API where applicable and, in some cases, leaving out certain parts of Node.js due to browser limitations or complexity.

Nodebox uses an internal dependency manager that is fine-tuned to deliver optimal initial load time by utilizing dependency caching via Sandpack CDN. That CDN is an open-source Rust package manager that runs in the cloud and can be self-hosted pretty easily as well.

While there are alternatives to Nodebox, they are closer to mimicking a container-based environment, running commands step-by-step, or even the entire Linux distributive in your browser. That makes them slower and harder to use compared to Nodebox, which is optimized to run sandboxes fast and with as little friction as possible.

Limitations

Unfortunately, any type of runtime that does not have access to operating system-level APIs will come with certain limitations. For Nodebox, those are the following:

  • N-API modules
  • net#Sockets pointing to external IPs
  • Synchronous exec/spawn
  • async_hooks (planned for implementation)
  • Automatic process exiting - users now need to manually call process.exit before the process is exited (planned for implementation)

As we implement every module manually one by one, it is possible that some will not behave correctly. If this happens, feel free to open an issue here on GitHub and we'll make sure to fix it.

Documentation


Getting started

Nodebox is meant for usage in your client-side applications, granting them the capability of running actual Node.js code directly in the browser. Here are a couple of examples of when Nodebox can be used:

  • Building interactive examples for server-side code in your documentation;
  • Showcasing a UI component library in the actual framework it's built for;
  • Generally any evaluation of Node.js code and previewing it in the browser.

In the context of this tutorial, we will be working on a documentation website that illustrates different examples of using a Next.js application. Bear in mind that our documentation itself can be written in any framework of our choosing.

Install

Nodebox can be installed from NPM just like any other dependency:

npm install @codesandbox/nodebox

Setup

Nodebox consists of two main parts:

  • A runtime environment evaluating the code;
  • A preview environment serving the result of the evaluation.

Corresponding to these two parts, let's create two iframes in our application:

<!--
  The "nodebox" iframe will mount the Nodebox runtime,
  allowing it to communicate with the rest of the application.
-->
<iframe id="nodebox-iframe"></iframe>

<!--
  The "preview" iframe will contain the result of running
  the Next.js example we will configure in a moment.
-->
<iframe id="preview-iframe"></iframe>

Although the runtime environment can be self-hosted, we will use the default one pointing to the deployed Nodebox instance on CodeSandbox servers. We do need, however, to specify an iframe reference in our application where Nodebox should render its preview.

import { Nodebox } from '@codesandbox/nodebox';

const runtime = new Nodebox({
  // Provide a reference to the <iframe> element in the DOM
  // where Nodebox should render the preview.
  iframe: document.getElementById('nodebox-iframe'),
});

// Establish a connection with the runtime environment.
await runtime.connect();

Learn more about the Nodebox API.

You want to establish a single Nodebox instance across your entire application. Bear that in mind during the setup phase and consult your framework's documentation and best practices regarding the most efficient way of achieving this.

Previews correspond to commands executed in Nodebox, meaning that at this stage there will be no previews mounted at the given iframe because we haven't run any commands yet. Let's change that.

Initialize file system

Much like your own project, the project you create in Nodebox needs files to work with. It can be a single JavaScript file or the entire project, like Astro or Next.js.

Let's describe a Next.js project that we need.

// Populate the in-memory file system of Nodebox
// with a Next.js project files.
await runtime.fs.init({
  'package.json': JSON.stringify({
    name: 'nextjs-preview',
    dependencies: {
      '@next/swc-wasm-nodejs': '12.1.6',
      next: '12.1.6',
      react: '18.2.0',
      'react-dom': '18.2.0',
    },
  }),
  // On the index page, let's illustrate how server-side props
  // propagate to your page component in Next.js.
  'pages/index.jsx': `
export default function Homepage({ name }) {
  return (
    <div>
      <h1>Hello, {name}</h1>
      <p>The name "{name}" has been received from server-side props.</p>
    </div>
  )
}

export function getServerSideProps() {
  return {
    props: {
      name: 'John'
    }
  }
}
    `,
});

You can reference standard Node.js modules, as well as external dependencies while writing your project files. Note that you don't have to install those dependencies as Nodebox will manage dependency installation, caching, and resolution automatically.

What we did above was outline a file system state of an actual Next.js project for Nodebox to run. The last step remaining is to run Next.js.

Run project

To run the project, we will run the npm dev command using the Shell API provided by Nodebox.

// First, create a new shell instance.
// You can use the same instance to spawn commands,
// observe stdio, restart and kill the process.
const shell = runtime.shell.create();

// Then, let's run the "dev" script that we've defined
// in "package.json" during the previous step.
const nextProcess = await shell.runCommand('npm', ['dev']);

// Find the preview by the process and mount it
// on the preview iframe on the page.
const previewInfo = await runtime.preview.getByShellId(nextProcess.id);
const previewIframe = document.getElementById('preview-iframe');
previewIframe.setAttribute('src', previewInfo.url);

Note that you can treat shell.runCommand similar to spawn in Node.js. Learn more about the Shell API in the documentation.

Once this command runs, it will return a shell reference we can use to retrieve the preview URL. By mounting that preview URL on our preview iframe from the setup, we can see the Next.js project running:

That's it! 🎉 Not a single server was spawned while running this Next.js application. Everything was managed by Nodebox directly in your browser.

👉 Check out the Sandbox for this tutorial.

nodebox-runtime's People

Contributors

compuives avatar demoorjasper avatar vanvuongngo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nodebox-runtime's Issues

Non-fatal errors being reported

I have Nodebox working nicely now.

However, I always see the following warnings and errors in the browser developer tools console, though they don't appear to impact Nodebox's behaviour:

Just wanted to let you know - these errors don't seem to have anything to do with my logic, and will appear for me on even the most stripped-down examples:

The FetchEvent for "https://9o137ia-3000.nodebox.codesandbox.io/cdn-cgi/rum?" resulted in a network error response: the promise was rejected.


Promise.then (async)
(anonymous) @ __csb_sw.4wa7ggdebk0h9uqz33slhe79sdhwmue.js:105
__csb_sw.4wa7ggdebk0h9uqz33slhe79sdhwmue.js:105 
Uncaught (in promise) 

Error: Failed to handle POST https://9o137ia-3000.nodebox.codesandbox.io/cdn-cgi/rum? request: no response received from the BroadcastChannel within timeout. There's likely an issue with the bridge/worker communication.
    at __csb_sw.4wa7ggdebk0h9uqz33slhe79sdhwmue.js:105:17527

Is this file not available as open source ?

Screenshot 2023-02-18 at 10 30 24 PM

Noticed that the preview iframe loads this URL. Is this the build of nodejs runtime for browser ?
Is this part of opensource ?

Asking this because it doesn't work without internet. Would like to use nodebox in a on-premise basis where is no access to external internet.

Error: Failed to get shell by ID...

I'm trying to run this example app: https://github.com/abstractalgo/webcontainer-github
It fetches an example React app repo from Github and tries to run it within Nodebox.

The example runs well with WebContainers, but Nodeboox simply throws:

Error: Failed to get shell by ID "clinlnn6t0000039oe41a5r3y"
    at index.mjs:949:13

I am clueless even what to try. I've tested this with the basic Node example for Nodebox and it works, but without any information on what goes wrong with this exact setup I am not sure what to try even.

`DataCloneError` when fetching endpoint in Next.js

Bug report

Packages affected

  • sandpack-client
  • sandpack-react

Description of the problem

When you fetch an API endpoint in Next.js you get a DataCloneError. Looks like a function isn't serialized for postMessage. If you then "open in CodeSandbox", the error doesn't occur.

chrome_1m4ti9Hfg6

What were you doing when the problem occurred?

Trying to fetch an endpoint.

What steps can we take to reproduce the problem?

Click the button in the sandbox to see the error.

If you "open in CodeSandbox" from the Sandpack demo, you'll see the code works fine there, just not in Sandpack.

Link to sandbox: link (optional)

Your Environment

Software Name/Version
Sandpack-react version 2.0.1
Browser Chrome
Operating System Windows 10

PS: Love the project, thanks for your work on it!

Example cannot run

image

Why can't I run it when I switch the version?
'@next/swc-wasm-nodejs': '13.1.6',
next: '13.1.6',

Limitations can be avoided using a Web extension and Native Messaging

Limitations
Unfortunately, any type of runtime that does not have access to operating system-level APIs will come with certain limitations. For Nodebox, those are the following:

  • N-API modules
  • net#Sockets pointing to external IPs
  • Synchronous exec/spawn
  • async_hooks (planned for implementation)
  • Automatic process exiting - users now need to manually call process.exit before the - process is exited (planned for implementation)

Note, it is possible to run local node executable controlled from the browser using a Web extension and Native Messaging to avoid those limitations, e.g., https://github.com/guest271314/native-messaging-nodejs.

Working Offline

Hi,

Is there any way to work completely offline once you have installed all the packages?

Can PWA cache all required files?

Thanks.

vite-react doesn't work in iOS safari

Bug report

Packages affected

  • sandpack-client
  • sandpack-react

Description of the problem

The default vite-react sandpack setup doesn't work in iOS safari

import { Sandpack } from "@codesandbox/sandpack-react";

export default function App() {
  return (
    <Sandpack
      theme="light"
      template="vite-react"
      options={{
        showConsoleButton: true,
        showInlineErrors: true,
        showNavigator: true,
        showLineNumbers: true,
        showTabs: true,
      }}
    />
  );
};

What steps can we take to reproduce the problem?

  • run vite-react in iOS safari
  • safari will die
RPReplay_Final1678300533.MP4

Your Environment

Software Name/Version
Sandpack-react version 2.1.2
Browser iOS safari
Operating System iOS 16.0

Problem loading @fastify/static

I'm adding @fastify/static to the package.json file:

{
  "name": "my-app",
  "dependencies": {
    "fastify": "latest",
    "@fastify/static": "latest",
    "fs-extra": "latest",
    "golgi-sbadmin": "latest"
  }
}

but this line appears to fail in the index.js file:

const fastifyStatic = require('@fastify/static');

On inspection of the /nodebox/node_modules directory, @fastify/static isn't included - perhaps the syntax of the "@fastify/static" package name in the package.json file is causing problems and it doesn't get loaded into the file system?

Sandpack could not resolve some modules

Bug report

Packages affected

  • sandpack-client
  • sandpack-react

Description of the problem

I run sandpack with @react-pdf/renderer library and get those errors:

main.js:1561 Uncaught (in promise) Error: Build failed with 6 errors:
node_modules/.store/@react-pdf/[email protected]/node_modules/@react-pdf/fns/lib/index.es.js:1:30: ERROR: Could not resolve "@babel/runtime/helpers/asyncToGenerator"
node_modules/.store/@react-pdf/[email protected]/node_modules/@react-pdf/fns/lib/index.es.js:2:32: ERROR: Could not resolve "@babel/runtime/regenerator"
node_modules/.store/@react-pdf/[email protected]/node_modules/@react-pdf/pdfkit/lib/pdfkit.browser.es.js:3:23: ERROR: Could not resolve "pako/lib/zlib/zstream"
node_modules/.store/@react-pdf/[email protected]/node_modules/@react-pdf/pdfkit/lib/pdfkit.browser.es.js:4:23: ERROR: Could not resolve "pako/lib/zlib/deflate.js"
node_modules/.store/@react-pdf/[email protected]/node_modules/@react-pdf/pdfkit/lib/pdfkit.browser.es.js:5:23: ERROR: Could not resolve "pako/lib/zlib/inflate.js"
...

Link to sandbox:

sandbox

Your Environment

Software Name/Version
Sandpack-react version 2.0.1

Exit not sent on successful runCommand; also no way to get return value of runCommand except through console.log

I have a simple case where I'd like to execute code in Nodebox, and see the return value from the file.

            const {Nodebox} = await import("@codesandbox/nodebox");
            const runtime = new Nodebox({
                // Provide a reference to the <iframe> element in the DOM
                // where Nodebox should render the runtime.
                iframe: runtimeFrame,
            });

            // Establish a connection with the runtime environment.
            await runtime.connect();

            // Populate the in-memory file system of Nodebox
            await runtime.fs.init({
                "package.json": JSON.stringify({
                    name: "code-evaluator",
                }),
                "index.js": "console.log('hello world'),
            });

            const shell = runtime.shell.create();

            // Listen for console and send that back to the server.
            shell.stdout.on("data", async (data) => {
                console.log(data);
            });

            // Exit is sent if there is an error parsing the file.
            await shell.on("exit", async (_exitCode, error: Error) => {
                if (error) console.log(error);
            });

            await shell.runCommand("node", ["index.js"]);

A couple of notes:

  • shell.on("exit") is never called in this case. Only if there's a parsing error of index.js.
  • There seems to be no way to get the results from index.js except through listening to stdout.on("data)".

Follow-on questions:

  • Is there a way to get a reliable "exit" called even on successful execution of the command/index.js example?
  • And is there an alternative to getting the return value (for example, if index.js returned a value, that's lost since there's no way to capture that result).

Next.js: not able to use `/api` routes

Discussed in codesandbox/sandpack#808

Originally posted by ismaelrumzan March 6, 2023
Hi,
I'm trying to set up an embed codesandbox for an API edge function code example.
It works in the sandbox here:
https://codesandbox.io/p/sandbox/hopeful-lake-4ncj08

When I try to use a similar example (JS version) in the code embed, I get failed to load in the preview. This is my code.
Any suggestions?

import {
  SandpackProvider,
  SandpackLayout,
  SandpackCodeEditor,
  SandpackFileExplorer,
  SandpackPreview,
} from "@codesandbox/sandpack-react";

const filename = '/pages/api/hello.js';

const files={};

files[filename] = {
code: `import { NextResponse } from 'next/server';
export const config = {
    runtime: 'edge',
};

export default (req) => {
    return NextResponse.json({
      name: 'Hello now an Edge Function!',
    });
  };
  `,
};

  files['/pages/index.js'] = {
    code: `import useSwr from 'swr';
    const fetcher = (url) => fetch(url).then((res) => res.json());
    export default function Index() {
    const { data, error, isLoading } = useSwr('/api/hello', fetcher)

  if (error) return <div>Failed to load</div>
  if (isLoading) return <div>Loading...</div>
  if (!data) return null

  return (
  <div>Got data</div>
  )
}
    `
  }

export default () => (
  <SandpackProvider template="nextjs" files={files} customSetup={{
          dependencies: {
            swr: 'latest',
          },
        }}>
    <SandpackLayout>
      <SandpackFileExplorer />
      <SandpackCodeEditor />
      <SandpackPreview />
    </SandpackLayout>
  </SandpackProvider>
);

Reproducible sandbox: https://codesandbox.io/s/laughing-yalow-cb3c03?file=/src/App.tsx

Your self-hosted hello world demo isn't working.

I'm using the https://codesandbox.io/p/sandbox/nodebox-next-js-example-ji27x8?file=%2Findex.js%3A8%2C11 from the link in your readme page.

It doesn't work. The iframe is empty. There's no Hello John.

When I try run on my local desktop environment, I get the same results.. an empty iframe.

If your demo page doesn't work, I'm not sure how I'm supposed to keep hacking away to get it working on my local environment. I don't think your nodebox solution works.??

Seems to be broken

I've come back to Nodebox after some months, only to find that my previously working examples no longer work. The odd thing is that your online version here works:

https://codesandbox.io/p/devbox/priceless-bash-nlrrz4

I've stripped back my standalone vanilla JS version to this - based on the example from your version above:

(async () => {
  const {Nodebox} = await import('https://unpkg.com/@codesandbox/[email protected]/build/index.mjs');
  const emulator = new Nodebox({
    iframe: document.getElementById('preview'),
  });
  await emulator.connect();
  await emulator.fs.init({
    'package.json': JSON.stringify({
      name: 'my-app',
      dependencies: {
        express: "4.18.2"
      }
    }),
    'index.js': `const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Hello world')
});

app.listen(port, () => {
  console.log(\`Example app listening on port \${port}\`)
});`
  });

const shell = emulator.shell.create();
const {id} = await shell.runCommand('node', ['index.js']);
const { url } = await emulator.preview.getByShellId(id);
console.log(url);

})();

When I try to connect using the URL shown in the console, it hangs and then I'm told it can't connect.

Could not connect to "nu13cex-3000.nodebox.codesandbox.io"
This server couldn't be reached. Make sure the node script is running and a server is started on port: "3000"

I see the following errors in the console:

https://nu13cex-3000.nodebox.codesandbox.io
__csb_sw.at3powcctjnrkzffq3qyf5kkzqljh91.js:105 Uncaught (in promise) DOMException: Failed to execute 'postMessage' on 'MessagePort': A ReadableStream could not be cloned because it was not transferred.
    at _0x2e1433 (https://nu13cex-3000.nodebox.codesandbox.io/__csb_sw.at3powcctjnrkzffq3qyf5kkzqljh91.js:105:13782)
_0x2e1433 @ __csb_sw.at3powcctjnrkzffq3qyf5kkzqljh91.js:105
await in _0x2e1433 (async)
_0x63346a @ __csb_sw.at3powcctjnrkzffq3qyf5kkzqljh91.js:105
_0x3ea396 @ __csb_sw.at3powcctjnrkzffq3qyf5kkzqljh91.js:105
(anonymous) @ __csb_sw.at3powcctjnrkzffq3qyf5kkzqljh91.js:105
The FetchEvent for "https://nu13cex-3000.nodebox.codesandbox.io/cdn-cgi/rum?" resulted in a network error response: the promise was rejected.
Promise.then (async)
(anonymous) @ __csb_sw.at3powcctjnrkzffq3qyf5kkzqljh91.js:105
__csb_sw.at3powcctjnrkzffq3qyf5kkzqljh91.js:105 Uncaught (in promise) Error: Failed to handle POST https://nu13cex-3000.nodebox.codesandbox.io/cdn-cgi/rum? request: no response received from the BroadcastChannel within timeout. There's likely an issue with the bridge/worker communication.
    at __csb_sw.at3powcctjnrkzffq3qyf5kkzqljh91.js:105:15526
(anonymous) @ __csb_sw.at3powcctjnrkzffq3qyf5kkzqljh91.js:105
setTimeout (async)
_0x63346a @ __csb_sw.at3powcctjnrkzffq3qyf5kkzqljh91.js:105
_0x3ea396 @ __csb_sw.at3powcctjnrkzffq3qyf5kkzqljh91.js:105
(anonymous) @ __csb_sw.at3powcctjnrkzffq3qyf5kkzqljh91.js:105
v84a3a4012de94ce1a686ba8c167c359c1696973893317:1     POST https://nu13cex-3000.nodebox.codesandbox.io/cdn-cgi/rum? net::ERR_FAILED

It would be good to get it working again - any ideas?

Many thanks

Nodebox doesn't send 'resize' event to Sandpack

When Sandpack is used without Nodebox, the Sandpack bundler sends a 'resize' event during initialization. (https://github.com/codesandbox/sandpack-bundler/blob/ab9e6cb50be618f404e0f0e4886d2c51963790da/src/index.ts#L100)

It looks like this message doesn't get sent when using Sandpack with Nodebox.

Currently, the React docs integration relies on this message and hides its content until that message is sent. (https://github.com/reactjs/react.dev/blob/4f9e9a56611c7a56b9506cf0a7ca84ab409824bc/src/components/MDX/Sandpack/Preview.tsx#L153) This seems to be based on similar code in sandpack-react but takes it further in that it depends on resize being sent to show any content. I would guess that this avoids reflows when Sandpack is used in a documentation context.

What would it take to get Nodebox to send this message at the same point that sandpack-bundler does?

Accessing fs from within files created by fs.init()

I've indirectly reported this problem in an earlier issue, but I think it deserves its own specific issue. The solution may be that I've missed something but here's the problem I'm hitting:

If I'm creating my main "index.js" file using fs.init(), one of the things I want to be able to do within that index.js file is to access the file system, so I want to be able to use the nodebox.fs APIs within it. However, I don't actually see a way of making the nodebox.fs object accessible from within the index.js when it executes - it complains that it doesn't exist if I try.

I then tried to pass nodebox.fs as an env object in the shell.runCommand, but it crashed when attempting to pass it in.

Am I missing something obvious or is this a bug/oversight?

Many thanks!

Suggestion: Add fs.readdir()

It would be useful to be able to read the contents of the virtual file system's directories, particularly when debugging/developing

Could this be added to a future release?

The `https.request` abstraction is not defining the `https` protocol like node

Context

I was trying out some socket connections that relied on https.request inside Nodebox when I first saw the following error:

Mixed Content: The page at 'https://nodebox-runtime.codesandbox.io/worker-360phrzywik3ot71qeou7g44viv8u49.js' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://my-url:27017/'. This request has been blocked; the content must be served over HTTPS

Bare in mind that all of this was previously tested in a "normal" node environment and worked without any issues. 👍

Problem

After debugging a little bit, it looks like the problem origins from nodebox abstraction of https.request not setting the protocol property value to https as the regular node one does.

node stringified version of https.request: ✔️

{"_events":{},"_eventsCount":0,"outputData":[],"outputSize":0,"writable":true,"destroyed":false,"_last":true,"chunkedEncoding":false,"shouldKeepAlive":false,"maxRequestsOnConnectionReached":false,"_defaultKeepAlive":true,"useChunkedEncodingByDefault":false,"sendDate":false,"_removedConnection":false,"_removedContLen":false,"_removedTE":false,"strictContentLength":false,"_contentLength":null,"_hasBody":true,"_trailer":"","finished":false,"_headerSent":false,"_closed":false,"socket":null,"_header":null,"_keepAliveTimeout":0,"agent":{"_events":{},"_eventsCount":2,"defaultPort":443,"protocol":"https:","options":{"noDelay":true,"path":null},"requests":{},"sockets":{"jsonplaceholder.typicode.com:443:::::::::::::::::::::":[{"_tlsOptions":{"pipe":false,"secureContext":{"context":{}},"isServer":false,"requestCert":true,"rejectUnauthorized":true},"_secureEstablished":false,"_securePending":false,"_newSessionPending":false,"_controlReleased":true,"secureConnecting":true,"_SNICallback":null,"servername":null,"alpnProtocol":null,"authorized":false,"authorizationError":null,"encrypted":true,"_events":{"close":[null,null,null],"end":[null,null]},"_eventsCount":9,"connecting":true,"_hadError":false,"_parent":null,"_host":"jsonplaceholder.typicode.com","_closeAfterHandlingError":false,"_readableState":{"objectMode":false,"highWaterMark":16384,"buffer":{"head":null,"tail":null,"length":0},"length":0,"pipes":[],"flowing":null,"ended":false,"endEmitted":false,"reading":false,"constructed":true,"sync":true,"needReadable":false,"emittedReadable":false,"readableListening":false,"resumeScheduled":false,"errorEmitted":false,"emitClose":false,"autoDestroy":true,"destroyed":false,"errored":null,"closed":false,"closeEmitted":false,"defaultEncoding":"utf8","awaitDrainWriters":null,"multiAwaitDrain":false,"readingMore":false,"dataEmitted":false,"decoder":null,"encoding":null},"_writableState":{"objectMode":false,"highWaterMark":16384,"finalCalled":false,"needDrain":false,"ending":false,"ended":false,"finished":false,"destroyed":false,"decodeStrings":false,"defaultEncoding":"utf8","length":0,"writing":false,"corked":0,"sync":true,"bufferProcessing":false,"writecb":null,"writelen":0,"afterWriteTickInfo":null,"buffered":[],"bufferedIndex":0,"allBuffers":true,"allNoop":true,"pendingcb":0,"constructed":true,"prefinished":false,"errorEmitted":false,"emitClose":false,"autoDestroy":true,"errored":null,"closed":false,"closeEmitted":false},"allowHalfOpen":false,"_sockname":null,"_pendingData":null,"_pendingEncoding":"","_server":null,"ssl":{"_parent":{"reading":false,"onconnection":null},"_secureContext":{"context":{}},"reading":false},"_requestCert":true,"_rejectUnauthorized":true}],"localhost:443:::::::::::::::::::::":[{"_tlsOptions":{"pipe":false,"secureContext":{"context":{}},"isServer":false,"requestCert":true,"rejectUnauthorized":true},"_secureEstablished":false,"_securePending":false,"_newSessionPending":false,"_controlReleased":true,"secureConnecting":true,"_SNICallback":null,"servername":null,"alpnProtocol":null,"authorized":false,"authorizationError":null,"encrypted":true,"_events":{"close":[null,null,null],"end":[null,null]},"_eventsCount":9,"connecting":true,"_hadError":false,"_parent":null,"_host":"localhost","_closeAfterHandlingError":false,"_readableState":{"objectMode":false,"highWaterMark":16384,"buffer":{"head":null,"tail":null,"length":0},"length":0,"pipes":[],"flowing":null,"ended":false,"endEmitted":false,"reading":false,"constructed":true,"sync":true,"needReadable":false,"emittedReadable":false,"readableListening":false,"resumeScheduled":false,"errorEmitted":false,"emitClose":false,"autoDestroy":true,"destroyed":false,"errored":null,"closed":false,"closeEmitted":false,"defaultEncoding":"utf8","awaitDrainWriters":null,"multiAwaitDrain":false,"readingMore":false,"dataEmitted":false,"decoder":null,"encoding":null},"_writableState":{"objectMode":false,"highWaterMark":16384,"finalCalled":false,"needDrain":false,"ending":false,"ended":false,"finished":false,"destroyed":false,"decodeStrings":false,"defaultEncoding":"utf8","length":0,"writing":false,"corked":0,"sync":true,"bufferProcessing":false,"writecb":null,"writelen":0,"afterWriteTickInfo":null,"buffered":[],"bufferedIndex":0,"allBuffers":true,"allNoop":true,"pendingcb":0,"constructed":true,"prefinished":false,"errorEmitted":false,"emitClose":false,"autoDestroy":true,"errored":null,"closed":false,"closeEmitted":false},"allowHalfOpen":false,"_sockname":null,"_pendingData":null,"_pendingEncoding":"","_server":null,"ssl":{"_parent":{"reading":false,"onconnection":null},"_secureContext":{"context":{}},"reading":false},"_requestCert":true,"_rejectUnauthorized":true}]},"freeSockets":{},"keepAliveMsecs":1000,"keepAlive":false,"maxSockets":null,"maxFreeSockets":256,"scheduling":"lifo","maxTotalSockets":null,"totalSocketCount":2,"maxCachedSessions":100,"_sessionCache":{"map":{},"list":[]}},"method":"GET","path":"/","_ended":false,"res":null,"aborted":false,"timeoutCb":null,"upgradeOrConnect":false,"parser":null,"maxHeadersCount":null,"reusedSocket":false,"host":"localhost","protocol":"https:"}

nodebox stringified version of https.request:

{"_writableState":{"objectMode":false,"highWaterMark":9007199254740991,"finalCalled":false,"needDrain":false,"ending":false,"ended":false,"finished":false,"destroyed":false,"decodeStrings":true,"defaultEncoding":"utf8","length":0,"writing":false,"corked":0,"sync":true,"bufferProcessing":false,"writecb":null,"writelen":0,"afterWriteTickInfo":null,"buffered":[],"bufferedIndex":0,"allBuffers":true,"allNoop":true,"pendingcb":0,"constructed":true,"prefinished":false,"errorEmitted":false,"emitClose":true,"autoDestroy":true,"errored":null,"closed":false,"closeEmitted":false},"_events":{},"_eventsCount":0,"_chunks":[],"_headers":{},"_headersSent":false,"writable":true,"uri":"http://undefined:80/","withCredentials":false,"method":"GET","response":{"_readableState":{"objectMode":false,"highWaterMark":9007199254740991,"buffer":{"head":null,"tail":null,"length":0},"length":0,"pipes":[],"flowing":null,"ended":false,"endEmitted":false,"reading":false,"constructed":true,"sync":true,"needReadable":false,"emittedReadable":false,"readableListening":false,"resumeScheduled":false,"errorEmitted":false,"emitClose":true,"autoDestroy":true,"destroyed":false,"errored":null,"closed":false,"closeEmitted":false,"defaultEncoding":"utf8","awaitDrainWriters":null,"multiAwaitDrain":false,"readingMore":false,"dataEmitted":false,"decoder":null,"encoding":null},"_events":{},"_eventsCount":1,"complete":false,"upgrade":false,"httpVersion":"1.1","httpVersionMajor":1,"httpVersionMinor":1,"method":"GET","url":"","statusCode":null,"statusMessage":null,"headers":{},"trailers":{},"rawTrailers":[],"trailersDistinct":{}}}

If you take a look at both JSON chunks, you will notice that the nodebox version doesn't define the protocol property and it ends up doing a http request if one passes a relative URL without the protocol set.

REPRODUCIBLE SANDBOX

You will see the exact same error in this sandbox, and although this one has a "dummy" URL and credentials, the problem is still the exact same with authentic ones. 👇

https://codesandbox.io/p/sandbox/brave-swirles-4inf6s
image

Svelte (Vite) template can't preview.

Bug report

Packages affected

  • sandpack-client
  • sandpack-react

Description of the problem

image

Your Environment

Software Name/Version
Browser Edge
Operating System Win11

worker_threads: support "eval" mode

I know that Nodebox is intended for small application/demonstration purposes, and given the practical limitations, I suspect the answer is no, but, given the capabilities of our own products that I'd like to be able to demo in Nodebox, I'm interested to know if, from within the running Nodebox Node.js environment, it is (or will be in future) possible to fire up a child process or Worker Thread.

One even whackier thought: could Nodebox start and access a WebWorker in the browser? Again I suspect not, but if so, it could be a potentially interesting way to emulate a Node.js Worker

BTW - are questions such as these best posted as Discussions or here as Issues?

Problem serving static files from Express

I'd like to be able to serve up files in the "virtual" emulator.fs file system using Express.

I've tried adding:

app.use(express.static('/nodebox'));

but I'm getting fetch errors within Nodebox if I try to retrieve, say:

https://{id}-3000.nodebox.codesandbox.io/package.json

and the request times out telling me the site can't be reached

Let me know if you need a worked example

Eventually I want to be able to fetch files via Express from my golgi-sbadmin package which will be in /nodebox/node_modules/golgi-sbadmin which I assume should, in theory, be possible. If so I'll be able to create a complete golgi-sbadmin client and server example running entirely in the browser, which will be perfect for users to kick its tyres and without me needing to set up a physical server

Suggestion: add fs.fileExists()

It would be useful to have an additional fs API so that you can check if a file path exists in the simulated file system.

Terminal support and going beyond simple testing.

I been doing a lot of research and I found wasm-webterm very interesting. There are also other wasm terminal but I don't know if they support custom commands. Sadly codesandbox doesn't support this package.

What I wanted to know is will nodebox ever support this terminal or are you just going to keep stuck with basic proto typing?

I tried stackblitz but it is very buggy and doesn't work well in the mobile browser and is not opensource but according to @this post(look at the end of the article)

While unfortunately we are not open-sourcing Nodebox for a variety of reasons, some

Nodebox is not also.

Is there anyway of running this package in codesandbox (or nodeonbox) without relying on microvm( Wich is unbearably slow with an extremely bad interface on mobile)?

Module resolution failing due to missing `name` field in package.json

Also filed here codesandbox/sandpack#1071


Problem

From what I can tell in the error, when adding custom dependencies to sandpack in a template that uses nodepack, the internal module resolution fails if a dependency's package.json doesn't have a name field.

The package referenced in the error does have one. It does not have a "parent package", however.
https://github.com/vanilla-extract-css/vanilla-extract/blob/fa7105066a5fbb70822af89939abcc48731aeb2e/packages/integration/package.json#L2
https://github.com/vanilla-extract-css/vanilla-extract/blob/951131127feee1e1a0a13b0b4e11e9ae2ba26536/packages/vite-plugin/package.json#L2

error when starting dev server:
Error: Couldn't find parent package.json with a name field from '/nodebox'
    at Object.getPackageInfo (nodebox:///nodebox/node_modules/.store/@vanilla-extract/[email protected]/node_modules/@vanilla-extract/integration/dist/vanilla-extract-integration.cjs.dev.js:338:11)
    at configResolved (nodebox:///nodebox/node_modules/.store/@vanilla-extract/[email protected]/node_modules/@vanilla-extract/vite-plugin/dist/vanilla-extract-vite-plugin.cjs.dev.js:85:33)
    at eval (nodebox:///nodebox/node_modules/.store/[email protected]/node_modules/vite/dist/node/chunks/dep-ca21228b.js:62127:28)
    at Array.map (<anonymous>)
    at resolveConfig (nodebox:///nodebox/node_modules/.store/[email protected]/node_modules/vite/dist/node/chunks/dep-ca21228b.js:62127:14)
    at async createServer (nodebox:///nodebox/node_modules/.store/[email protected]/node_modules/vite/dist/node/chunks/dep-ca21228b.js:61191:20)
    at async CAC.eval (nodebox:///nodebox/node_modules/.store/[email protected]/node_modules/vite/dist/node/cli.js:741:24)

Setup

import type { SandpackFiles, SandpackPredefinedTemplate, SandpackSetup } from "@codesandbox/sandpack-react";
import {
  SandpackConsole,
  SandpackFileExplorer,
  SandpackLayout,
  SandpackPreview,
  SandpackProvider,
  SandpackThemeProvider,
} from "@codesandbox/sandpack-react";
import React from "react";

import { Editor } from "./Editor";

const requiredSetup: SandpackSetup = {
  dependencies: {
    "@vanilla-extract/css": "^1.13.0",
    "@vanilla-extract/recipes": "^0.5.0",
    "@vanilla-extract/sprinkles": "^1.6.1",
    "@vanilla-extract/vite-plugin": "^3.9.0",
  },
};

const requiredFiles: SandpackFiles = {
  "styles.css.ts": `import { style } from '@vanilla-extract/css'`,
  "vite.config.ts": `import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin';

export default defineConfig({
  plugins: [react(), vanillaExtractPlugin()],
});
  `,
};

export const Playground: React.FC<{
  template?: SandpackPredefinedTemplate;
  files?: SandpackFiles;
}> = ({ template = "vite-react-ts", files }) => {
  return (
    <SandpackProvider
      template={template}
      customSetup={requiredSetup}
      files={{ ...requiredFiles, ...files }}
    >
      <SandpackThemeProvider>
        <SandpackLayout>
          <SandpackFileExplorer />
          <Editor />
          <SandpackPreview />
          <SandpackConsole />
        </SandpackLayout>
      </SandpackThemeProvider>
    </SandpackProvider>
  );
};

Project package.json

{
  "scripts": {
    "watch": "astro dev",
    "build": "astro build",
    "preview": "astro preview",
  },
  "dependencies": {
    "@astrojs/mdx": "^1.1.2",
    "@astrojs/react": "^3.0.3",
    "@astrojs/ts-plugin": "^1.2.0",
    "@codesandbox/nodebox": "^0.1.9",
    "@codesandbox/sandpack-react": "^2.11.3",
    "@codesandbox/sandpack-themes": "^2.0.21",
    "@vanilla-extract/css": "^1.13.0",
    "@vanilla-extract/esbuild-plugin": "^2.3.2",
    "@vanilla-extract/recipes": "^0.5.0",
    "@vanilla-extract/sprinkles": "^1.6.1",
    "@vanilla-extract/vite-plugin": "^3.9.0",
    "astro": "^3.3.3",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-native": "0.71.13",
  },
  "devDependencies": {
    "@types/react": "^18.2.31",
    "@types/react-dom": "^18.2.14",
  }
}

Process exits when --conditions option is used

When I try to pass the arguments -C foo (or equivalently--conditions=foo) to the node process, it exits with status code 1. Are conditional export resolution conditions supported by Nodebox? If not, what would be required to add support?

This is pursuant to getting React Server Components demos going in the React documentation. The Webpack plugin that processes Server Components has to be imported with the react-server condition set in order to work.

As an aside, I'm accessing Nodebox via Sandpack and when the process exits, I haven't been able to find how to get a stacktrace for the call to process.exit() or any other helpful information. Any tips here would be appreciated.

I'd like to post a succinct repro using nodebox-runtime directly, but am unable to run any of the scripts for this package. I get errors like this:

$ pnpm build               

> [email protected] build /Users/davemccabe/src/nodebox-runtime
> turbo run build --no-cache && pnpm build:consumer

 ERROR  run failed: could not unmarshal lockfile: : yaml: unmarshal errors:
  line 1: cannot unmarshal !!str `6.0` into float32
  line 12: cannot unmarshal !!map into string
  line 15: cannot unmarshal !!map into string
  line 18: cannot unmarshal !!map into string
  line 21: cannot unmarshal !!map into string
  line 24: cannot unmarshal !!map into string
  line 27: cannot unmarshal !!map into string
  line 30: cannot unmarshal !!map into string
  line 33: cannot unmarshal !!map into string
  line 36: cannot unmarshal !!map into string
  line 39: cannot unmarshal !!map into string
  line 42: cannot unmarshal !!map into string
  line 45: cannot unmarshal !!map into string
  line 48: cannot unmarshal !!map into string
  line 52: cannot unmarshal !!map into string
  line 55: cannot unmarshal !!map into string
  line 58: cannot unmarshal !!map into string
  line 61: cannot unmarshal !!map into string
  line 64: cannot unmarshal !!map into string
  line 67: cannot unmarshal !!map into string
  line 70: cannot unmarshal !!map into string
  line 73: cannot unmarshal !!map into string
  line 76: cannot unmarshal !!map into string
  line 79: cannot unmarshal !!map into string
  line 82: cannot unmarshal !!map into string
  line 85: cannot unmarshal !!map into string
  line 88: cannot unmarshal !!map into string
  line 91: cannot unmarshal !!map into string
  line 94: cannot unmarshal !!map into string
  line 97: cannot unmarshal !!map into string
  line 100: cannot unmarshal !!map into string
  line 103: cannot unmarshal !!map into string
  line 106: cannot unmarshal !!map into string
  line 109: cannot unmarshal !!map into string
  line 112: cannot unmarshal !!map into string
  line 115: cannot unmarshal !!map into string
  line 118: cannot unmarshal !!map into string
  line 121: cannot unmarshal !!map into string
  line 124: cannot unmarshal !!map into string
  line 127: cannot unmarshal !!map into string
  line 133: cannot unmarshal !!map into string
  line 136: cannot unmarshal !!map into string
 ELIFECYCLE  Command failed with exit code 1.

I am using pnpm version 8.10.2. If you could direct me to how to run the tests or something for nodebox-runtime then I will post a repro.

Feedback: Yarn

Really nice work! I threw together a quick demo of trying to run an unmodified build of Yarn within Nodebox; it almost works, which would be incredibly useful for writing tutorials for our website! Here are some of my findings:

blockers

  • The http2 module seems missing. It's used by got, one of our dependencies, so we can't disable it.

  • The Brotli functions (in particular zlib.brotliDecompressSync) don't seem supported.

  • Bug: new URL('npm:1.2.3').pathname === '//1.2.3'; the // is extraneous and breaks Yarn

  • Missing worker support (we have a build that can disable it; I need to try without).

  • Bug: The Worker constructor doesn't support the eval parameter.

workarounds

  • The trailing \n added to strings going through console.log(...) seems missing from the shell.stdout stream - I suspect it's because you also forward it to the caller's console.log function.

  • Speaking of which, it'd be good to have a way to disable this automatic forwarding - either as an option, or possibly when detecting that there are listeners bound to the data event?

  • Data written on stdout via process.stdout.write (rather than console.log) don't seem to trigger the shell.stdout callback. I workaround this by doing a process.stdout.write = console.log right before spawning the process.

  • I didn't manage to catch the output from shell.stderr - it seems the callback is never called. Yarn doesn't use stderr so it's not a problem for my use case.

  • It doesn't seem possible at the moment to set environment variables in the shell before spawning the process. It'd be nice if it was natively supported (for example by an env option on both emulator.shell.create() and shell.runCommand()).

  • It seems that even once the process within a shell exits, shell.kill() must be called if we want to run a new command (seems it's just a matter of shell.id not being reset on exit).

nits

  • It'd be nice to have an helper function doing the equivalent of new Promise((resolve) => shell.on(exit, resolve));

  • The iframe parameter from the Nodebox constructor should probably be moved to connect, since it's not needed until this point. This way the instance can be created before we have the ref to the iframe.

Windows can't preview the results

Bug report

Packages affected

  • sandpack-client
  • sandpack-react

Description of the problem

Windows can't preview the results. (template="vite-react")

image

image

image

[Question] How to use nodebox-runtime in browser without any online resource's support

Hello, I have following codesandbox projects for many years. Thank you for let these excellent codes open source.
When I test nodebox-runtime in local machine accoding to https://sandpack.codesandbox.io/docs/advanced-usage/nodebox. I found that we need to load some runtime support resouces from https://nodebox-runtime.codesandbox.io and https://rm127lp-3000.nodebox.codesandbox.io.
My question is that how to use nodebox-runtime without any online resource's support? Because users in my area can't load these resouces without VPN.
I think it will be better if we have a pure node js runtime in browser. We can run it without load any other online resources when in running period.
Thanks.

Is NodeBox really compiled by a local browser without the need for a network?

I want to ask a question, the documentation says that it runs completely in the browser, even if you don't need an Internet, but the links generated by the iframe after I run it are all official links

https:vu13f7e-3000.nodebox.codesandbox.io
https:nodebox-runtime.codesandbox.io

How could this link work without an Internet connection?

Problem writing a file

As an alternative to fetching an NPM package of files, I was trying to fetch a file from Github and save it locally:

async function importGithubFile(path) {

  // eg /index.html

  let url = 'https://raw.githubusercontent.com/robtweed/golgi-sbadmin/master/example';
  url = url + path;
  let res = await fetch(url);
  let text = await res.text();
  //console.log(text);
  await emulator.fs.writeFile('./server' + path, text);
  console.log(3333333);
}

console.log(8888888);
await importGithubFile('/index.html');
console.log(9999999);

Unfortunately this doesn't complete. If I un-comment the console.log(text) line, I can see that it has successfully fetched the contents of the file from Github, but the emulator.fs.writeFile() method appears to be failing.

I'm not seeing an error as such in the browser's console, but I don't see it showing the 33333 or 99999 in the console and it doesn't get any further in my logic.

Any ideas?

Use "hostname" instead of "host" in `worker.js`

// _0x1f31f9(0x1029) -> "host"
this[_0x1f31f9(0x1144)] = (_0x47c213[_0x1f31f9(0x10ac)] || _0x1f31f9(0xc5d)) + '//' + _0x47c213[_0x1f31f9(0x1029)] + (_0x47c213[_0x1f31f9(0xb50)] ? ':' + _0x47c213[_0x1f31f9(0xb50)] : '') + (_0x47c213[_0x1f31f9(0x2a8)] || '/'),

should probably be:

this[_0x1f31f9(0x1144)] = (_0x47c213[_0x1f31f9(0x10ac)] || _0x1f31f9(0xc5d)) + '//' + _0x47c213["hostname"] + (_0x47c213[_0x1f31f9(0xb50)] ? ':' + _0x47c213[_0x1f31f9(0xb50)] : '') + (_0x47c213[_0x1f31f9(0x2a8)] || '/')

Otherwise you can build invalid URLs like: http://hostname:8080:8080/pathname

"Error: Failed to get shell by ID ..." when running npm scripts

Hello!

I get an error when running the example on https://github.com/codesandbox/nodebox-runtime/blob/main/README.md

Uncaught (in promise) Error: Failed to get shell by ID "clfv3ugjh0000039ox0avsv01"

It runs if I change:
const nextProcess = await shell.runCommand('npm', ['dev']);
to
const nextProcess = await shell.runCommand('next', ['dev']);

I noticed the same issue in other projects also. npm scripts fails, while running, for example, node index.js works.

Example sandbox

(Open developer console and wait about 10 seconds for emulator.preview.getByShellId to time out)

Error: `The service was stopped`

I'm having a hard time debugging this issue. When I open in the project in codesandbox, everything works.

When I run with sandpack, I get the following errors:

worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105 The service was stopped
_0x20c137.<computed> @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
output @ dep-ca21228b.js:12543
error @ dep-ca21228b.js:12570
eval @ dep-ca21228b.js:42331
setTimeout (async)
refresh @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
_0x461887 @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
_0x4dfa29 @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
eval @ dep-ca21228b.js:42308
createDepsOptimizer @ dep-ca21228b.js:42306
await in createDepsOptimizer (async)
initDepsOptimizer @ dep-ca21228b.js:42206
eval @ dep-ca21228b.js:61433
await in eval (async)
initServer @ dep-ca21228b.js:61437
httpServer.listen @ dep-ca21228b.js:61445
eval @ dep-ca21228b.js:51520
httpServerStart @ dep-ca21228b.js:51502
startServer @ dep-ca21228b.js:61468
await in startServer (async)
listen @ dep-ca21228b.js:61247
eval @ cli.js:754
await in eval (async)
runMatchedCommand @ cli.js:660
parse @ cli.js:587
eval @ cli.js:901
_iterateThroughGenerator @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
await in _iterateThroughGenerator (async)
_finishLoading @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
load @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
await in load (async)
loadEsModule @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
dynamicImport @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
_0x1d899e @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
start @ vite.js:46
eval @ vite.js:62
_iterateThroughGenerator @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
await in _iterateThroughGenerator (async)
_finishLoading @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
load @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
loadEsModule @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
_0x16d150 @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
_0x12a9ec @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105 Uncaught Error: Process.exit called with exit code 2
    at globalThis.Go._0x481fa1 [as exit] (worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105:1030235)
    at runtime.wasmExit (nodebox:///nodebox/node_modules/.store/[email protected]/node_modules/esbuild-wasm/wasm_exec.js:226:12)
    at wasm://wasm/0287ae4a
    at wasm://wasm/0287ae4a
    at wasm://wasm/0287ae4a
    at wasm://wasm/0287ae4a
    at wasm://wasm/0287ae4a
    at wasm://wasm/0287ae4a
    at wasm://wasm/0287ae4a
    at wasm://wasm/0287ae4a

Followed by:

worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105 2:28:19 PM [vite] Internal server error: The service is no longer running
  Plugin: vite:esbuild
  File: /nodebox/index.jsx
      at eval (nodebox:///nodebox/node_modules/.store/[email protected]/node_modules/esbuild-wasm/lib/main.js:787:29)
      at sendRequest (nodebox:///nodebox/node_modules/.store/[email protected]/node_modules/esbuild-wasm/lib/main.js:662:14)
      at start (nodebox:///nodebox/node_modules/.store/[email protected]/node_modules/esbuild-wasm/lib/main.js:785:9)
      at Object.transform2 [as transform] (nodebox:///nodebox/node_modules/.store/[email protected]/node_modules/esbuild-wasm/lib/main.js:842:5)
      at eval (nodebox:///nodebox/node_modules/.store/[email protected]/node_modules/esbuild-wasm/lib/main.js:1929:55)
      at new Promise (<anonymous>)
      at Object.transform (nodebox:///nodebox/node_modules/.store/[email protected]/node_modules/esbuild-wasm/lib/main.js:1929:14)
      at transform (nodebox:///nodebox/node_modules/.store/[email protected]/node_modules/esbuild-wasm/lib/main.js:1752:62)
      at transformWithEsbuild (nodebox:///nodebox/node_modules/.store/[email protected]/node_modules/vite/dist/node/chunks/dep-ca21228b.js:13448:49)
      at TransformContext.transform (nodebox:///nodebox/node_modules/.store/[email protected]/node_modules/vite/dist/node/chunks/dep-ca21228b.js:13521:38)
      at Object.transform (nodebox:///nodebox/node_modules/.store/[email protected]/node_modules/vite/dist/node/chunks/dep-ca21228b.js:41723:44)
      at async loadAndTransform (nodebox:///nodebox/node_modules/.store/[email protected]/node_modules/vite/dist/node/chunks/dep-ca21228b.js:39517:29)
_0x20c137.<computed> @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
output @ dep-ca21228b.js:12543
error @ dep-ca21228b.js:12570
logError @ dep-ca21228b.js:41250
viteErrorMiddleware @ dep-ca21228b.js:41264
call @ dep-ca21228b.js:47362
next @ dep-ca21228b.js:47310
call @ dep-ca21228b.js:47375
next @ dep-ca21228b.js:47310
call @ dep-ca21228b.js:47375
next @ dep-ca21228b.js:47310
call @ dep-ca21228b.js:47375
next @ dep-ca21228b.js:47310
call @ dep-ca21228b.js:47375
next @ dep-ca21228b.js:47310
call @ dep-ca21228b.js:47375
next @ dep-ca21228b.js:47310
viteTransformMiddleware @ dep-ca21228b.js:60787
await in viteTransformMiddleware (async)
call @ dep-ca21228b.js:47366
next @ dep-ca21228b.js:47310
eval @ dep-ca21228b.js:39169
viteServePublicMiddleware @ dep-ca21228b.js:39219
call @ dep-ca21228b.js:47366
next @ dep-ca21228b.js:47310
next @ dep-ca21228b.js:47288
cors @ dep-ca21228b.js:47842
eval @ dep-ca21228b.js:47878
originCallback @ dep-ca21228b.js:47868
eval @ dep-ca21228b.js:47873
optionsCallback @ dep-ca21228b.js:47853
corsMiddleware @ dep-ca21228b.js:47858
call @ dep-ca21228b.js:47366
next @ dep-ca21228b.js:47310
handle @ dep-ca21228b.js:47313
app @ dep-ca21228b.js:47178
(anonymous) @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
_0x3a9228.<computed> @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
_0x19a5c3 @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
(anonymous) @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
(anonymous) @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
fire @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
handleMessage @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
(anonymous) @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
(anonymous) @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
xq138j5-5173.nodebox.codesandbox.io/:25          GET https://xq138j5-5173.nodebox.codesandbox.io/index.jsx net::ERR_ABORTED 500
worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105 2:28:19 PM [vite] error while updating dependencies:
Error: The service is no longer running
    at eval (nodebox:///nodebox/node_modules/.store/[email protected]/node_modules/esbuild-wasm/lib/main.js:1108:25)
    at sendRequest (nodebox:///nodebox/node_modules/.store/[email protected]/node_modules/esbuild-wasm/lib/main.js:662:14)
    at buildOrServeContinue (nodebox:///nodebox/node_modules/.store/[email protected]/node_modules/esbuild-wasm/lib/main.js:1106:5)
    at eval (nodebox:///nodebox/node_modules/.store/[email protected]/node_modules/esbuild-wasm/lib/main.js:954:11)
_0x20c137.<computed> @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
output @ dep-ca21228b.js:12543
error @ dep-ca21228b.js:12570
runOptimizer @ dep-ca21228b.js:42494
await in runOptimizer (async)
rerun @ dep-ca21228b.js:42522
eval @ dep-ca21228b.js:42589
setTimeout (async)
refresh @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
_0x461887 @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
_0x4dfa29 @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
debouncedProcessing @ dep-ca21228b.js:42585
onCrawlEnd @ dep-ca21228b.js:42644
await in onCrawlEnd (async)
afterLoad @ dep-ca21228b.js:42703
Promise.catch (async)
runOptimizerWhenIdle @ dep-ca21228b.js:42712
afterLoad @ dep-ca21228b.js:42700
setTimeout (async)
refresh @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
_0x461887 @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
_0x4dfa29 @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
eval @ dep-ca21228b.js:42710
Promise.then (async)
runOptimizerWhenIdle @ dep-ca21228b.js:42709
afterLoad @ dep-ca21228b.js:42700
setTimeout (async)
refresh @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
_0x461887 @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
_0x4dfa29 @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
eval @ dep-ca21228b.js:42710
Promise.then (async)
runOptimizerWhenIdle @ dep-ca21228b.js:42709
afterLoad @ dep-ca21228b.js:42700
setTimeout (async)
refresh @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
_0x461887 @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
_0x4dfa29 @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
eval @ dep-ca21228b.js:42710
Promise.then (async)
runOptimizerWhenIdle @ dep-ca21228b.js:42709
delayDepsOptimizerUntil @ dep-ca21228b.js:42688
doTransform @ dep-ca21228b.js:39437
await in doTransform (async)
transformRequest @ dep-ca21228b.js:39399
viteTransformMiddleware @ dep-ca21228b.js:60741
call @ dep-ca21228b.js:47366
next @ dep-ca21228b.js:47310
viteServePublicMiddleware @ dep-ca21228b.js:39217
call @ dep-ca21228b.js:47366
next @ dep-ca21228b.js:47310
next @ dep-ca21228b.js:47288
cors @ dep-ca21228b.js:47842
eval @ dep-ca21228b.js:47878
originCallback @ dep-ca21228b.js:47868
eval @ dep-ca21228b.js:47873
optionsCallback @ dep-ca21228b.js:47853
corsMiddleware @ dep-ca21228b.js:47858
call @ dep-ca21228b.js:47366
next @ dep-ca21228b.js:47310
handle @ dep-ca21228b.js:47313
app @ dep-ca21228b.js:47178
(anonymous) @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
_0x3a9228.<computed> @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
_0x19a5c3 @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
(anonymous) @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
(anonymous) @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
fire @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
handleMessage @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
(anonymous) @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
(anonymous) @ worker-kiri4aiwm06x1zrozbs6j1zxkkqx0ml.js:105
__csb_sw.4wa7ggdebk0h9uqz33slhe79sdhwmue.js:105 Uncaught (in promise) DOMException: Failed to execute 'postMessage' on 'MessagePort': A ReadableStream could not be cloned because it was not transferred.
    at _0x393a80 (https://xq138j5-5173.nodebox.codesandbox.io/__csb_sw.4wa7ggdebk0h9uqz33slhe79sdhwmue.js:105:15805)

Content-Type is changed to text/html and script tag is inserted

I am sending JSON using res.json in Express. In this case Content-Type of res headers should be application/json.
But in Nodebox Runtime it is changed to text/html.

dev-tools-hello-header

And <script> tag is inserted.
dev-tools-hello

step to reproduce

A sandbox for step to reproduce.
https://codesandbox.io/p/sandbox/reproduce-btoken-json-responce-fohukt

Server part code:
https://codesandbox.io/p/sandbox/reproduce-content-type-is-changed-to-text-html-fohukt?file=%2Fbox-src%2Fvite-project%2Fserver.js%3A1%2C1

Express + Vite server is started inside the Nodebox environment and fetch the JSON from the preview window.
This will result in a parse error.

nodebox

Start the above server without using Nodebox with npm run server.
This is displayed as expected.
nodejs

Running jest test on Nodebox

I am trying to run jest test but it is not even starting. I am trying the reason behind at least a log why it did not run.

here is my code:

import { Box } from "@chakra-ui/react";
import { useContext, useEffect, useRef } from "react";
import { FileSystemContext } from "@/contexts/FileSystem";

const TestRunner = () => {
  const { visibleFiles } = useContext(FileSystemContext);
  const iFrame = useRef<HTMLIFrameElement>(null);

  const startEmulator = async () => {
    if (iFrame.current) {
      const { Nodebox } = await import("@codesandbox/nodebox");
      const emulator = new Nodebox({
        iframe: iFrame.current,
      });
      await emulator.connect();
      await emulator.fs.init({
        "package.json": JSON.stringify({
          name: "my-app",
          scripts: {
            test: "jest",
          },
          dependencies: {
            // jest: "29.5.0",
            "@testing-library/jest-dom": "5.16.5",
          },
        }),
        "test.test.js": `
          import { readFileSync } from "fs";
          import '@testing-library/jest-dom/extend-expect';

          describe('index.html', () => {
            let content;
            beforeEach(() => {
              content = readFileSync("./index.html",'utf8');
              document.documentElement.innerHTML = content;
            });
          
            it('contains h1 tag', () => {
              expect(document.querySelector("h1")).not.toBeNull();
            });

            it('h1 tag has text Murad', () => {
              expect(document.querySelector("h1").innerHTML).toEqual("Murad");
            });
            
            it('has to have a style', () => {

              expect(document.querySelector('h1')).toHaveStyle({
                backgroundColor: 'red',
                fontSize: '16px',
              });
            });

          });`,
        "index.html": `<html>
        <head>
          <title>first</title>
          <style>
            h1 {
              background-color: red;
              font-size: 16px;
            }
          </style>
        </head>
        <body>
          <h1>Murad</h1>
        </body>
        </html>`,
      });
      const shell = emulator.shell.create();
      shell.on("progress", (status) => console.log(status));
      shell.stderr.on("data", (data) => {
        console.log("Error:", data);
      });
      shell.stdout.on("data", (data) => {
        console.log("Output:", data);
      });
      shell.on("exit", (status) => console.log(status));
      const serverCommand = await shell.runCommand("npm", ["run", "test"]);
      console.log(serverCommand);
    }
  };

  useEffect(() => {
    startEmulator();
  }, []);

  return (
    <Box>
      <iframe ref={iFrame}></iframe>
    </Box>
  );
};

export default TestRunner;

and log:
image
basicaly it downloads the packages and quits

Getting started

It's not clear from the documentation what's needed to bootstrap the nodebox environment in the browser. eg is nodebox dependent on first loading sandpack into the browser?

I think your worked "getting started" example needs to start from the absolute ground up - ie several basic steps earlier than you do - for very interested dimwits like me to get it and actually get something working :-)

Unable to import Fastify

I see a max string error occurring if I try to import Fastify:

  await emulator.fs.init({
    'package.json': JSON.stringify({
      name: 'my-app',
      dependencies: {
       fastify: "latest"
      }
    }),
    'index.js': `
import Fastify from 'fastify';
...etc

Importing Express works OK. I assume the Fastify module is simply too big for the way Nodebox handles things?

`InvalidStateError` when using WebSockets

Bug report

Packages affected

  • sandpack-client
  • sandpack-react

Note

First off—there may not be enough info here, sorry about that! Just posting this in case you can identify the error from the message. If needed, I'll try find more info. The code in the demo isn't really relevant, it's just used to highlight the issue occurring in Sandpack, but not in CodeSandbox.

Description of the problem

I'm getting the following error message when using Liveblocks in a Next.js project in Sandpack, a service that provides a collaborative toolkit for building apps through websockets.

chrome_1cDF4OxR0T

If you take a look at my Sandbox and then "open in CodeSandbox", you'll find that the problem disappears in CodeSandbox. Perhaps the issue is possibly being caused by a WebSockets polyfill?

Note that I've generated an API key for this demo, but it will be revoked on 2023/03/06, so the demo will stop working then.

What were you doing when the problem occurred?

Trying to use Liveblocks, and the Liveblocks package makes use of WebSockets. The code is copied from an old example and it definitely works in a normal environment.

This is where the error occurs in the uglified runtime

go5jVPqIq3

What steps can we take to reproduce the problem?

The demo is a real-time cursors demo, so open the sandbox then move your mouse over the window to make the error occur. Then try "open in CodeSandbox" and note that the error does not occur there. Note that if you open the preview in two windows, you will see multiplayer cursors.

Link to sandbox: link (optional)

Your Environment

Software Name/Version
Sandpack-react version 2.0.1
Browser Chrome
Operating System Windows 10

PS: Love the project, thanks for your work on it!

Clarification of preview URL

Nodebox will evaluate the index.js module, and since it spawns a server process at port 3000, it will automatically open a new preview at that port. The preview will appear in the iframe provided during the Nodebox setup and it will be directly available at https://{projectId}-3000.nodebox-runtime.codesandbox.io.

If all bundling and execution happens in the local browser, what role does this external preview URL play?

I could probably dig deeper in the code to figure it out, but makes sense that this is explained in the readme as it feels inconsistent.

Really nice project in any case, can't wait to give it a try!

Not finding a new module in NPM

I've created a new module/repository in NPM today (golgi-sbadmin). NPM reports that it has been successfully published.

However if I try to now specify it as a dependency in my Nodebox package.json file, it errors, telling me that golgi-sbadmin cannot be found.

Is this perhaps because you're using a mirror of NPM and it will take time for it to get there?

Could you share how to build node as webassembly target using emscripten or some other tools.

Hi, I am just curious about how to build node as webassembly target.

Could you share the patches and instructions on how to do it?

I want to execute some demonstration node code in browser without a server locally. codesandbox or webcontainer are good choices except they could not run self-hosted locally or offline.

I really want to learn how to make node run purely in browser.

Express app, multiple issues

Hi, I'm running into multiple issues with Nodebox trying to run a fairly standard Express app.

Here's my sandbox: https://codesandbox.io/p/sandbox/nodebox-issue-vty6zs

Here are my issues:

// 1.
// These appear to break the Nodebox:
const __filename = url.fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// 2.
// Despite setting this header, the browser console shows the error:
// > Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "application/octet-stream". Strict MIME type checking is enforced for module scripts per HTML spec.
response.setHeader("Content-Type", "text/javascript");

// 3.
// response.sendFile() would not work.
//response.sendFile(path.join(__dirname, "public", "js", "main.js"));
// I had to do this as a workaround:
response.send(await fs.readFile("public/js/main.js"));

I think 2 may be related to #39

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.