Compare commits

..

15 Commits

Author SHA1 Message Date
7dd67f72d8 fix: remove editorRef from useEffect 2024-07-15 16:12:08 -04:00
5bf264b807 fix: remove extra state variables from useEffect 2024-07-15 15:32:40 -04:00
6f6926a621 fix: store rooms in map 2024-07-15 14:56:37 -04:00
c262fb2a31 fix: add error handling to the backend 2024-06-19 21:57:40 -04:00
ed709210e3 fix: remove hardcoded reference to localhost 2024-06-19 21:57:40 -04:00
97c8598717 fix: count only the current user's sandboxes towards the limit 2024-06-19 21:57:40 -04:00
9ec59bc781 fix: use the container URL for the preview panel 2024-06-19 21:57:40 -04:00
687416e6e9 fix: set project file permissions so that they belong to the terminal user 2024-06-19 21:57:40 -04:00
006c5cea66 fix: sync files to container instead of local file system 2024-06-19 21:57:40 -04:00
869ae6c148 fix: ensure container remains open until all owner connections are closed 2024-06-19 21:57:40 -04:00
7353e88567 fix: wait until terminals are killed to close the container 2024-06-19 21:57:40 -04:00
a0fb905a04 fix: move socket connection to useRef 2024-06-19 21:56:18 -04:00
0df074924f added debounced function in the editor 2024-06-14 12:10:01 -04:00
e5b320d1c5 feat: replace node-pty with E2B sandboxes 2024-06-14 12:02:20 -04:00
b561f1e962 chore: rename utils.ts to fileoperations.ts 2024-06-14 11:57:32 -04:00
5 changed files with 14 additions and 7 deletions

View File

@ -29,9 +29,7 @@ npm run dev
### Backend ### Backend
The backend consists of a primary Express and Socket.io server, and 3 Cloudflare Workers microservices for the D1 database, R2 storage, and Workers AI. The D1 database also contains a [service binding](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/) to the R2 storage worker. Each open sandbox instantiates a secure Linux sandboxes on E2B, which is used for the terminal and live preview. The backend consists of a primary Express and Socket.io server, and 3 Cloudflare Workers microservices for the D1 database, R2 storage, and Workers AI. The D1 database also contains a [service binding](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/) to the R2 storage worker.
You will need to make an account on [E2B](https://e2b.dev/) to get an API key.
#### Socket.io server #### Socket.io server
@ -183,4 +181,3 @@ It should be in the form `category(scope or module): message` in your commit mes
- [Express](https://expressjs.com/) - [Express](https://expressjs.com/)
- [Socket.io](https://socket.io/) - [Socket.io](https://socket.io/)
- [Drizzle ORM](https://orm.drizzle.team/) - [Drizzle ORM](https://orm.drizzle.team/)
- [E2B](https://e2b.dev/)

View File

@ -5,4 +5,3 @@ PORT=4000
WORKERS_KEY= WORKERS_KEY=
DATABASE_WORKER_URL= DATABASE_WORKER_URL=
STORAGE_WORKER_URL= STORAGE_WORKER_URL=
E2B_API_KEY=

View File

@ -192,8 +192,6 @@ io.on("connection", async (socket) => {
// todo: send diffs + debounce for efficiency // todo: send diffs + debounce for efficiency
socket.on("saveFile", async (fileId: string, body: string) => { socket.on("saveFile", async (fileId: string, body: string) => {
if (!fileId) return; // handles saving when no file is open
try { try {
if (Buffer.byteLength(body, "utf-8") > MAX_BODY_SIZE) { if (Buffer.byteLength(body, "utf-8") > MAX_BODY_SIZE) {
socket.emit( socket.emit(

View File

@ -63,6 +63,14 @@ const CodeEditor = dynamic(() => import("@/components/editor"), {
loading: () => <Loading />, loading: () => <Loading />,
}) })
function getReactDefinitionFile() {
const reactDefinitionFile = fs.readFileSync(
"node_modules/@types/react/index.d.ts",
"utf8"
)
return reactDefinitionFile
}
export default async function CodePage({ params }: { params: { id: string } }) { export default async function CodePage({ params }: { params: { id: string } }) {
const user = await currentUser() const user = await currentUser()
const sandboxId = params.id const sandboxId = params.id
@ -86,6 +94,8 @@ export default async function CodePage({ params }: { params: { id: string } }) {
return notFound() return notFound()
} }
const reactDefinitionFile = getReactDefinitionFile()
return ( return (
<div className="overflow-hidden overscroll-none w-screen flex flex-col h-screen bg-background"> <div className="overflow-hidden overscroll-none w-screen flex flex-col h-screen bg-background">
<Room id={sandboxId}> <Room id={sandboxId}>
@ -94,6 +104,7 @@ export default async function CodePage({ params }: { params: { id: string } }) {
<CodeEditor <CodeEditor
userData={userData} userData={userData}
sandboxData={sandboxData} sandboxData={sandboxData}
reactDefinitionFile={reactDefinitionFile}
/> />
</div> </div>
</Room> </Room>

View File

@ -35,9 +35,11 @@ import { ImperativePanelHandle } from "react-resizable-panels"
export default function CodeEditor({ export default function CodeEditor({
userData, userData,
sandboxData, sandboxData,
reactDefinitionFile,
}: { }: {
userData: User userData: User
sandboxData: Sandbox sandboxData: Sandbox
reactDefinitionFile: string
}) { }) {
const socketRef = useRef<Socket | null>(null); const socketRef = useRef<Socket | null>(null);