diff --git a/index.html b/index.html index e4b78ea..c573643 100644 --- a/index.html +++ b/index.html @@ -1,10 +1,20 @@ - + - + - Vite + React + TS + CodeSandbox SDK Playground + + + +
diff --git a/package-lock.json b/package-lock.json index db55907..fc7aa0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "shell-sdk-test", "version": "0.0.0", "dependencies": { - "@codesandbox/sdk": "^1.0.0-rc.2", + "@codesandbox/sdk": "^1.0.0", "@tailwindcss/vite": "^4.1.6", "@xterm/xterm": "^5.5.0", "express": "^5.1.0", @@ -46,9 +46,10 @@ } }, "node_modules/@codesandbox/sdk": { - "version": "1.0.0-rc.2", - "resolved": "https://registry.npmjs.org/@codesandbox/sdk/-/sdk-1.0.0-rc.2.tgz", - "integrity": "sha512-rc1k2WZjW+ic/07BumSDRo5GRJbJIR/LcAhPVGCAL345KPj6Pns6rkVFXYkFCF6ZzW4h/MynyzFiUXmk+W2z3w==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@codesandbox/sdk/-/sdk-1.0.0.tgz", + "integrity": "sha512-XRguQaddRbAk0HlaPPtSW7WxgeFGkC5t0+PsvX6Vm57tn88uLfrh2Jga1aXZnjlo4G5HTlGtL4NxdD4qAGIl4g==", + "license": "MIT", "dependencies": { "ora": "^8.2.0", "readline": "^1.3.0" diff --git a/package.json b/package.json index 6566196..23cc04f 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "preview": "vite preview" }, "dependencies": { - "@codesandbox/sdk": "^1.0.0-rc.2", + "@codesandbox/sdk": "^1.0.0", "@tailwindcss/vite": "^4.1.6", "@xterm/xterm": "^5.5.0", "express": "^5.1.0", diff --git a/public/codesandbox-icon.svg b/public/codesandbox-icon.svg new file mode 100644 index 0000000..80f7477 --- /dev/null +++ b/public/codesandbox-icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/og-sdk-playground.jpg b/public/og-sdk-playground.jpg new file mode 100644 index 0000000..f799875 Binary files /dev/null and b/public/og-sdk-playground.jpg differ diff --git a/server.ts b/server.ts index 229fbc2..b39a8f2 100644 --- a/server.ts +++ b/server.ts @@ -2,7 +2,7 @@ import { CodeSandbox } from "@codesandbox/sdk"; import express from "express"; const app = express(); -const sdk = new CodeSandbox(process.env.CSB_API_TOKEN); +const sdk = new CodeSandbox(process.env.CSB_API_KEY); app.post("/api/sandboxes", async (req, res) => { const sandbox = await sdk.sandboxes.create({ @@ -14,18 +14,7 @@ app.post("/api/sandboxes", async (req, res) => { }); app.get("/api/sandboxes/:id", async (req, res) => { const sandbox = await sdk.sandboxes.resume(req.params.id); - const session = await sandbox.createBrowserSession({ - id: "just-me", - permission: "write", - git: { - accessToken: process.env.GITHUB_TOKEN, - email: "christianalfoni@gmail.com", - name: "Christian Alfoni", - }, - env: { - FOO: "bar", - }, - }); + const session = await sandbox.createBrowserSession(); res.json(session); }); @@ -34,6 +23,6 @@ app.listen(4001, (error) => { if (error) { console.error(error); } else { - console.log("Server is running on port 3000"); + console.log("Server is running on port 4001"); } }); diff --git a/src/App.tsx b/src/App.tsx index c819baa..0333ead 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,6 +6,7 @@ import "../node_modules/@xterm/xterm/css/xterm.css"; import { InterpretersComponent } from "./Interpreters"; import { TasksComponent } from "./Tasks"; import { PreviewComponent } from "./Preview"; +import { TerminalComponent } from "./Terminal"; type State = | { @@ -43,8 +44,11 @@ function App() { progress: "Connecting to sandbox...", }); try { + const sessionData = await fetch(`/api/sandboxes/${storedId}`).then( + (res) => res.json() + ); const session = await connectToSandbox({ - id: storedId, + session: sessionData, getSession: (id) => fetch(`/api/sandboxes/${id}`).then((res) => res.json()), initStatusCb(status) { @@ -76,36 +80,30 @@ function App() { }); try { const res = await fetch("/api/sandboxes", { method: "POST" }); - const initialSession = await res.json(); - let hasConnectedInitialSession = false; + const sessionData = await res.json(); // Store sandboxId in localStorage - localStorage.setItem("sandboxId", initialSession.id); + localStorage.setItem("sandboxId", sessionData.id); setState({ current: "CONNECTING_TO_SANDBOX", - sandboxId: initialSession.id, + sandboxId: sessionData.id, progress: "Connecting to sandbox...", }); const session = await connectToSandbox({ - id: initialSession.id, + session: sessionData, getSession: (id) => { - if (!hasConnectedInitialSession) { - hasConnectedInitialSession = true; - return initialSession; - } - return fetch(`/api/sandboxes/${id}`).then((res) => res.json()); }, initStatusCb(status) { setState({ current: "CONNECTING_TO_SANDBOX", - sandboxId: initialSession.id, + sandboxId: sessionData.id, progress: status.message, }); }, }); setState({ current: "CONNECTED", - sandboxId: initialSession.id, + sandboxId: sessionData.id, session, selectedExample: null, }); @@ -178,18 +176,58 @@ function App() { {state.current === "IDLE" ? ( <> +
+

+ 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 + + +
+
+              
+                {`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} + - -
- +
+ {/* Left: Buttons */} +
+ +
+ {/* Right: Terminal output */} +
+
); }