diff --git a/index.html b/index.html
index e4b78ea..c573643 100644
--- a/index.html
+++ b/index.html
@@ -1,10 +1,20 @@
-
+
+
+ Experience the functionality of the SDK with this interactive
+ playground.
+
+
+ To start, create a sample playground
+
+
-
- Click the button above to create a Sandbox and connect. This will
- fork a snapshot of a template already running a vite dev server
- and wake it up on a new VM for you.
-
+
+
+
+ Example Code
+
+
+ navigator.clipboard
+ .writeText(`const handleCreateSandbox = async () => {
+ // Create a new sandbox
+ const res = await fetch("/api/sandboxes", { method: "POST" });
+ const initialSession = await res.json();
+
+ // Store sandboxId for reconnection
+ localStorage.setItem("sandboxId", initialSession.id);
+
+ // Connect to the sandbox
+ const session = await connectToSandbox({
+ id: initialSession.id,
+ getSession: (id) => fetch(\`/api/sandboxes/\${id}\`).then((res) => res.json())
+ });
+}`)
+ }
+ className="text-slate-400 hover:text-slate-200 text-sm font-aeonik-medium"
+ >
+ Copy
+
+
+
+
+ {`import { CodeSandbox } from "@codesandbox/sdk";
+
+const sdk = new CodeSandbox(process.env.CSB_API_KEY!);
+const sandbox = await sdk.sandboxes.create();
+ `}
+
+
>
) : state.current === "CONNECTED" ? (
@@ -199,6 +237,10 @@ function App() {
+
+
+
+
{
- const devCommand = session.commands
- .getAll()
- .find((command) => command.command === "pnpm run dev");
+ const devCommand = session.commands.getAll()[0];
+
if (devCommand) {
setDevCommand({
command: devCommand,
@@ -77,7 +76,7 @@ export function CommandComponent({ session }: { session: WebSocketSession }) {
async function runDevCommand() {
xterm.clear();
- const command = await session.commands.create("pnpm run dev");
+ const command = await session.commands.runBackground("pnpm run dev");
setDevCommand({
command,
disposable: command.onOutput((output: string) => {
diff --git a/src/Preview.tsx b/src/Preview.tsx
index f9c3329..021d600 100644
--- a/src/Preview.tsx
+++ b/src/Preview.tsx
@@ -17,14 +17,14 @@ export function PreviewComponent({ session }: { session: WebSocketSession }) {
useEffect(() => {
if (previewContainerRef.current) {
- const port = session.ports.getOpenedPort(5173);
+ const port = session.ports.get(5173);
if (!port) {
return;
}
const preview = createPreview<{ type: "ping" }, { type: "pong" }>(
- "https://" + port.host
+ session.hosts.getUrl(port.port)
);
previewRef.current = preview;
diff --git a/src/Tasks.tsx b/src/Tasks.tsx
index f2c6c4e..2195823 100644
--- a/src/Tasks.tsx
+++ b/src/Tasks.tsx
@@ -1,33 +1,23 @@
import { useEffect, useRef, useState } from "react";
import { Task, WebSocketSession } from "@codesandbox/sdk/browser";
-import { Terminal as XTerminal } from "@xterm/xterm";
+
import "../node_modules/@xterm/xterm/css/xterm.css";
+import { useXTerm } from "./useXTerm";
export function TasksComponent({ session }: { session: WebSocketSession }) {
const taskRef = useRef(null);
const [status, setStatus] = useState("IDLE");
const terminalContainerRef = useRef(null);
- const xtermRef = useRef(null);
-
- if (!xtermRef.current) {
- xtermRef.current = new XTerminal();
- }
+ const xterm = useXTerm(terminalContainerRef);
useEffect(() => {
- if (!xtermRef.current || !terminalContainerRef.current) {
- return;
- }
-
const devTask = session.tasks.getTask("dev");
if (!devTask) {
return;
}
- const xterm = xtermRef.current;
- const terminalContainer = terminalContainerRef.current;
-
- xterm.open(terminalContainer);
+ xterm.open(terminalContainerRef.current!);
taskRef.current = devTask;
@@ -48,12 +38,15 @@ export function TasksComponent({ session }: { session: WebSocketSession }) {
return () => {
statusChangeDisposer.dispose();
};
- }, []);
+ }, [session.tasks, xterm]);
return (
{/* Left: Buttons & status */}
-
Status: {status}
+
+ Status:{" "}
+ {status}
+
{
await taskRef.current?.restart();
diff --git a/src/Terminal.tsx b/src/Terminal.tsx
index 21d2ed3..54ce869 100644
--- a/src/Terminal.tsx
+++ b/src/Terminal.tsx
@@ -1,73 +1,60 @@
import { useEffect, useRef } from "react";
-import "./App.css";
-import { WebSocketSession, Terminal } from "@codesandbox/sdk/browser";
-import { Terminal as XTerminal } from "@xterm/xterm";
-import "../node_modules/@xterm/xterm/css/xterm.css";
+import { Terminal, WebSocketSession } from "@codesandbox/sdk/browser";
+
+import { useXTerm } from "./useXTerm";
export function TerminalComponent({ session }: { session: WebSocketSession }) {
const terminalContainerRef = useRef(null);
- // const terminalRef = useTerminal(session, terminalContainerRef);
- const xtermRef = useRef(null);
- const terminalRef = useRef(null);
-
- if (!xtermRef.current) {
- xtermRef.current = new XTerminal();
- }
+ const xterm = useXTerm(terminalContainerRef);
+ const terminalRef = useRef(null);
useEffect(() => {
- if (!xtermRef.current || !terminalContainerRef.current) {
- return;
- }
-
- const xterm = xtermRef.current;
const terminalContainer = terminalContainerRef.current;
-
+ if (!terminalContainer) return;
const disposers = new Set<() => void>();
-
xterm.open(terminalContainer);
-
const terminals = session.terminals.getAll();
const existingTerminal =
terminals[0] && session.terminals.get(terminals[0].id);
const terminalPromise = existingTerminal
? Promise.resolve(existingTerminal)
: session.terminals.create();
-
terminalPromise.then(async (terminal) => {
terminalRef.current = terminal;
terminal.onOutput((output) => {
xterm.write(output);
});
-
xterm.onData((data) => {
terminal.write(data);
});
-
xterm.write(await terminal.open());
-
disposers.add(() => terminal.kill());
});
-
return () => {
disposers.forEach((dispose) => dispose());
};
- }, [session]);
+ }, [session, xterm]);
return (
- <>
- SDK TEST
- terminalRef.current?.run(`echo "Hello World"`)}>
- Run echo
-
- {
- terminalRef.current?.kill().then(console.log).catch(console.error);
- }}
- >
- Kill
-
-
- >
+
+ {/* Left: Buttons */}
+
+ {
+ terminalRef.current?.kill();
+ xterm.dispose();
+ }}
+ className="bg-red-500 hover:bg-red-600 text-white rounded-md px-4 py-2 font-medium text-base shadow transition-colors focus:outline-none focus:ring-2 focus:ring-red-300 focus:ring-offset-2"
+ >
+ Kill
+
+
+ {/* Right: Terminal output */}
+
+
);
}