update dockerfile env logic & deploy database cf worker
This commit is contained in:
parent
34a7fd7ab9
commit
c5762d430c
@ -1,18 +1,18 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: service_name
|
||||
name: <SANDBOX>
|
||||
labels:
|
||||
app: service_name
|
||||
app: <SANDBOX>
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: service_name
|
||||
app: <SANDBOX>
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: service_name
|
||||
app: <SANDBOX>
|
||||
spec:
|
||||
volumes:
|
||||
- name: workspace-volume
|
||||
@ -33,15 +33,20 @@ spec:
|
||||
limits:
|
||||
cpu: "1"
|
||||
memory: "1Gi"
|
||||
env:
|
||||
- name: CF_API_TOKEN
|
||||
value: <CF_API_TOKEN>
|
||||
- name: CF_USER_ID
|
||||
value: <CF_USER_ID>
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: service_name
|
||||
name: <SANDBOX>
|
||||
spec:
|
||||
selector:
|
||||
app: service_name
|
||||
app: <SANDBOX>
|
||||
ports:
|
||||
- protocol: TCP
|
||||
name: ws
|
||||
@ -55,27 +60,27 @@ spec:
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: service_name
|
||||
name: <SANDBOX>
|
||||
spec:
|
||||
ingressClassName: nginx
|
||||
rules:
|
||||
- host: service_name.ws.ishaand.com
|
||||
- host: <SANDBOX>.ws.ishaand.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: service_name
|
||||
name: <SANDBOX>
|
||||
port:
|
||||
number: 4000
|
||||
- host: service_name.s.ishaand.com
|
||||
- host: <SANDBOX>.s.ishaand.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: service_name
|
||||
name: <SANDBOX>
|
||||
port:
|
||||
number: 3000
|
||||
|
@ -1,5 +1,5 @@
|
||||
import express, { Express, Request, Response } from "express"
|
||||
// import dotenv from "dotenv"
|
||||
import dotenv from "dotenv"
|
||||
|
||||
import fs from "fs"
|
||||
import yaml from "yaml"
|
||||
@ -17,6 +17,7 @@ const app = express()
|
||||
const port = process.env.PORT || 4001
|
||||
app.use(express.json())
|
||||
app.use(cors())
|
||||
dotenv.config()
|
||||
|
||||
const kubeconfig = new KubeConfig()
|
||||
kubeconfig.loadFromDefault()
|
||||
@ -24,14 +25,31 @@ const coreV1Api = kubeconfig.makeApiClient(CoreV1Api)
|
||||
const appsV1Api = kubeconfig.makeApiClient(AppsV1Api)
|
||||
const networkingV1Api = kubeconfig.makeApiClient(NetworkingV1Api)
|
||||
|
||||
// Updated utility function to handle multi-document YAML files
|
||||
const readAndParseKubeYaml = (filePath: string, replId: string): Array<any> => {
|
||||
const readAndParseKubeYaml = (
|
||||
filePath: string,
|
||||
sandboxId: string
|
||||
): Array<any> => {
|
||||
const fileContent = fs.readFileSync(filePath, "utf8")
|
||||
const docs = yaml.parseAllDocuments(fileContent).map((doc) => {
|
||||
let docString = doc.toString()
|
||||
const regex = new RegExp(`service_name`, "g")
|
||||
docString = docString.replace(regex, replId)
|
||||
console.log(docString)
|
||||
|
||||
const regex = new RegExp(`<SANDBOX>`, "g")
|
||||
docString = docString.replace(regex, sandboxId)
|
||||
|
||||
// replace <CF_API_TOKEN> with process.env.CF_API_TOKEN
|
||||
if (!process.env.CF_API_TOKEN) {
|
||||
throw new Error("CF_API_TOKEN is not defined")
|
||||
}
|
||||
const regexEnv1 = new RegExp(`<CF_API_TOKEN>`, "g")
|
||||
docString = docString.replace(regexEnv1, process.env.CF_API_TOKEN)
|
||||
|
||||
// replace <CF_USER_ID> with process.env.CF_USER_ID
|
||||
if (!process.env.CF_USER_ID) {
|
||||
throw new Error("CF_USER_ID is not defined")
|
||||
}
|
||||
const regexEnv2 = new RegExp(`<CF_USER_ID>`, "g")
|
||||
docString = docString.replace(regexEnv2, process.env.CF_USER_ID)
|
||||
|
||||
return yaml.parse(docString)
|
||||
})
|
||||
return docs
|
||||
|
2
backend/server/.dockerignore
Normal file
2
backend/server/.dockerignore
Normal file
@ -0,0 +1,2 @@
|
||||
.env
|
||||
node_modules
|
79
backend/server/dist/getSandboxFiles.js
vendored
79
backend/server/dist/getSandboxFiles.js
vendored
@ -1,79 +0,0 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getSandboxFiles = void 0;
|
||||
const getSandboxFiles = (id) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const sandboxRes = yield fetch(`https://storage.ishaan1013.workers.dev/api?sandboxId=${id}`);
|
||||
const sandboxData = yield sandboxRes.json();
|
||||
const paths = sandboxData.objects.map((obj) => obj.key);
|
||||
const processedFiles = yield processFiles(paths, id);
|
||||
// console.log("processedFiles.fileData:", processedFiles.fileData)
|
||||
return processedFiles;
|
||||
});
|
||||
exports.getSandboxFiles = getSandboxFiles;
|
||||
const processFiles = (paths, id) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const root = { id: "/", type: "folder", name: "/", children: [] };
|
||||
const fileData = [];
|
||||
paths.forEach((path) => {
|
||||
const allParts = path.split("/");
|
||||
if (allParts[1] !== id) {
|
||||
console.log("invalid path!!!!");
|
||||
return;
|
||||
}
|
||||
const parts = allParts.slice(2);
|
||||
let current = root;
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
const part = parts[i];
|
||||
const isFile = i === parts.length - 1 && part.includes(".");
|
||||
const existing = current.children.find((child) => child.name === part);
|
||||
if (existing) {
|
||||
if (!isFile) {
|
||||
current = existing;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (isFile) {
|
||||
const file = { id: path, type: "file", name: part };
|
||||
current.children.push(file);
|
||||
fileData.push({ id: path, data: "" });
|
||||
}
|
||||
else {
|
||||
const folder = {
|
||||
id: path,
|
||||
type: "folder",
|
||||
name: part,
|
||||
children: [],
|
||||
};
|
||||
current.children.push(folder);
|
||||
current = folder;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
yield Promise.all(fileData.map((file) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const data = yield fetchFileContent(file.id);
|
||||
file.data = data;
|
||||
})));
|
||||
return {
|
||||
files: root.children,
|
||||
fileData,
|
||||
};
|
||||
});
|
||||
const fetchFileContent = (fileId) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
try {
|
||||
const fileRes = yield fetch(`https://storage.ishaan1013.workers.dev/api?fileId=${fileId}`);
|
||||
return yield fileRes.text();
|
||||
}
|
||||
catch (error) {
|
||||
console.error("ERROR fetching file:", error);
|
||||
return "";
|
||||
}
|
||||
});
|
251
backend/server/dist/index.js
vendored
251
backend/server/dist/index.js
vendored
@ -1,251 +0,0 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const fs_1 = __importDefault(require("fs"));
|
||||
const os_1 = __importDefault(require("os"));
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const express_1 = __importDefault(require("express"));
|
||||
const dotenv_1 = __importDefault(require("dotenv"));
|
||||
const http_1 = require("http");
|
||||
const socket_io_1 = require("socket.io");
|
||||
const zod_1 = require("zod");
|
||||
const utils_1 = require("./utils");
|
||||
const node_pty_1 = require("node-pty");
|
||||
const ratelimit_1 = require("./ratelimit");
|
||||
dotenv_1.default.config();
|
||||
const app = (0, express_1.default)();
|
||||
const port = process.env.PORT || 4000;
|
||||
// app.use(cors())
|
||||
const httpServer = (0, http_1.createServer)(app);
|
||||
const io = new socket_io_1.Server(httpServer, {
|
||||
cors: {
|
||||
origin: "*",
|
||||
},
|
||||
});
|
||||
const terminals = {};
|
||||
const dirName = path_1.default.join(__dirname, "..");
|
||||
const handshakeSchema = zod_1.z.object({
|
||||
userId: zod_1.z.string(),
|
||||
sandboxId: zod_1.z.string(),
|
||||
EIO: zod_1.z.string(),
|
||||
transport: zod_1.z.string(),
|
||||
});
|
||||
io.use((socket, next) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const q = socket.handshake.query;
|
||||
const parseQuery = handshakeSchema.safeParse(q);
|
||||
if (!parseQuery.success) {
|
||||
console.log("Invalid request.");
|
||||
next(new Error("Invalid request."));
|
||||
return;
|
||||
}
|
||||
const { sandboxId, userId } = parseQuery.data;
|
||||
const dbUser = yield fetch(`http://localhost:8787/api/user?id=${userId}`);
|
||||
const dbUserJSON = (yield dbUser.json());
|
||||
if (!dbUserJSON) {
|
||||
console.log("DB error.");
|
||||
next(new Error("DB error."));
|
||||
return;
|
||||
}
|
||||
const sandbox = dbUserJSON.sandbox.find((s) => s.id === sandboxId);
|
||||
const sharedSandboxes = dbUserJSON.usersToSandboxes.find((uts) => uts.sandboxId === sandboxId);
|
||||
if (!sandbox && !sharedSandboxes) {
|
||||
console.log("Invalid credentials.");
|
||||
next(new Error("Invalid credentials."));
|
||||
return;
|
||||
}
|
||||
socket.data = {
|
||||
userId,
|
||||
sandboxId: sandboxId,
|
||||
};
|
||||
next();
|
||||
}));
|
||||
io.on("connection", (socket) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const data = socket.data;
|
||||
const sandboxFiles = yield (0, utils_1.getSandboxFiles)(data.sandboxId);
|
||||
sandboxFiles.fileData.forEach((file) => {
|
||||
const filePath = path_1.default.join(dirName, file.id);
|
||||
fs_1.default.mkdirSync(path_1.default.dirname(filePath), { recursive: true });
|
||||
fs_1.default.writeFile(filePath, file.data, function (err) {
|
||||
if (err)
|
||||
throw err;
|
||||
});
|
||||
});
|
||||
socket.emit("loaded", sandboxFiles.files);
|
||||
socket.on("getFile", (fileId, callback) => {
|
||||
const file = sandboxFiles.fileData.find((f) => f.id === fileId);
|
||||
if (!file)
|
||||
return;
|
||||
callback(file.data);
|
||||
});
|
||||
// todo: send diffs + debounce for efficiency
|
||||
socket.on("saveFile", (fileId, body) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
try {
|
||||
yield ratelimit_1.saveFileRL.consume(data.userId, 1);
|
||||
if (Buffer.byteLength(body, "utf-8") > ratelimit_1.MAX_BODY_SIZE) {
|
||||
socket.emit("rateLimit", "Rate limited: file size too large. Please reduce the file size.");
|
||||
return;
|
||||
}
|
||||
const file = sandboxFiles.fileData.find((f) => f.id === fileId);
|
||||
if (!file)
|
||||
return;
|
||||
file.data = body;
|
||||
fs_1.default.writeFile(path_1.default.join(dirName, file.id), body, function (err) {
|
||||
if (err)
|
||||
throw err;
|
||||
});
|
||||
yield (0, utils_1.saveFile)(fileId, body);
|
||||
}
|
||||
catch (e) {
|
||||
socket.emit("rateLimit", "Rate limited: file saving. Please slow down.");
|
||||
}
|
||||
}));
|
||||
socket.on("createFile", (name) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
try {
|
||||
yield ratelimit_1.createFileRL.consume(data.userId, 1);
|
||||
const id = `projects/${data.sandboxId}/${name}`;
|
||||
fs_1.default.writeFile(path_1.default.join(dirName, id), "", function (err) {
|
||||
if (err)
|
||||
throw err;
|
||||
});
|
||||
sandboxFiles.files.push({
|
||||
id,
|
||||
name,
|
||||
type: "file",
|
||||
});
|
||||
sandboxFiles.fileData.push({
|
||||
id,
|
||||
data: "",
|
||||
});
|
||||
yield (0, utils_1.createFile)(id);
|
||||
}
|
||||
catch (e) {
|
||||
socket.emit("rateLimit", "Rate limited: file creation. Please slow down.");
|
||||
}
|
||||
}));
|
||||
socket.on("renameFile", (fileId, newName) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
try {
|
||||
yield ratelimit_1.renameFileRL.consume(data.userId, 1);
|
||||
const file = sandboxFiles.fileData.find((f) => f.id === fileId);
|
||||
if (!file)
|
||||
return;
|
||||
file.id = newName;
|
||||
const parts = fileId.split("/");
|
||||
const newFileId = parts.slice(0, parts.length - 1).join("/") + "/" + newName;
|
||||
fs_1.default.rename(path_1.default.join(dirName, fileId), path_1.default.join(dirName, newFileId), function (err) {
|
||||
if (err)
|
||||
throw err;
|
||||
});
|
||||
yield (0, utils_1.renameFile)(fileId, newFileId, file.data);
|
||||
}
|
||||
catch (e) {
|
||||
socket.emit("rateLimit", "Rate limited: file renaming. Please slow down.");
|
||||
return;
|
||||
}
|
||||
}));
|
||||
socket.on("deleteFile", (fileId, callback) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
try {
|
||||
yield ratelimit_1.deleteFileRL.consume(data.userId, 1);
|
||||
const file = sandboxFiles.fileData.find((f) => f.id === fileId);
|
||||
if (!file)
|
||||
return;
|
||||
fs_1.default.unlink(path_1.default.join(dirName, fileId), function (err) {
|
||||
if (err)
|
||||
throw err;
|
||||
});
|
||||
sandboxFiles.fileData = sandboxFiles.fileData.filter((f) => f.id !== fileId);
|
||||
yield (0, utils_1.deleteFile)(fileId);
|
||||
const newFiles = yield (0, utils_1.getSandboxFiles)(data.sandboxId);
|
||||
callback(newFiles.files);
|
||||
}
|
||||
catch (e) {
|
||||
socket.emit("rateLimit", "Rate limited: file deletion. Please slow down.");
|
||||
}
|
||||
}));
|
||||
socket.on("createTerminal", ({ id }) => {
|
||||
if (terminals[id]) {
|
||||
console.log("Terminal already exists.");
|
||||
return;
|
||||
}
|
||||
if (Object.keys(terminals).length >= 4) {
|
||||
console.log("Too many terminals.");
|
||||
return;
|
||||
}
|
||||
const pty = (0, node_pty_1.spawn)(os_1.default.platform() === "win32" ? "cmd.exe" : "bash", [], {
|
||||
name: "xterm",
|
||||
cols: 100,
|
||||
cwd: path_1.default.join(dirName, "projects", data.sandboxId),
|
||||
});
|
||||
const onData = pty.onData((data) => {
|
||||
socket.emit("terminalResponse", {
|
||||
// data: Buffer.from(data, "utf-8").toString("base64"),
|
||||
data,
|
||||
});
|
||||
});
|
||||
const onExit = pty.onExit((code) => console.log("exit :(", code));
|
||||
pty.write("clear\r");
|
||||
terminals[id] = {
|
||||
terminal: pty,
|
||||
onData,
|
||||
onExit,
|
||||
};
|
||||
});
|
||||
socket.on("terminalData", (id, data) => {
|
||||
if (!terminals[id]) {
|
||||
console.log("terminals", terminals);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
terminals[id].terminal.write(data);
|
||||
}
|
||||
catch (e) {
|
||||
console.log("Error writing to terminal", e);
|
||||
}
|
||||
});
|
||||
socket.on("generateCode", (fileName, code, line, instructions, callback) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const fetchPromise = fetch(`http://localhost:8787/api/sandbox/generate`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
userId: data.userId,
|
||||
}),
|
||||
});
|
||||
const generateCodePromise = (0, utils_1.generateCode)({
|
||||
fileName,
|
||||
code,
|
||||
line,
|
||||
instructions,
|
||||
});
|
||||
const [fetchResponse, generateCodeResponse] = yield Promise.all([
|
||||
fetchPromise,
|
||||
generateCodePromise,
|
||||
]);
|
||||
const json = yield generateCodeResponse.json();
|
||||
callback(json);
|
||||
}));
|
||||
socket.on("disconnect", () => {
|
||||
Object.entries(terminals).forEach((t) => {
|
||||
const { terminal, onData, onExit } = t[1];
|
||||
if (os_1.default.platform() !== "win32")
|
||||
terminal.kill();
|
||||
onData.dispose();
|
||||
onExit.dispose();
|
||||
delete terminals[t[0]];
|
||||
});
|
||||
});
|
||||
}));
|
||||
httpServer.listen(port, () => {
|
||||
console.log(`Server running on port ${port}`);
|
||||
});
|
34
backend/server/dist/terminal.js
vendored
34
backend/server/dist/terminal.js
vendored
@ -1,34 +0,0 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Pty = void 0;
|
||||
const node_pty_1 = require("node-pty");
|
||||
const os_1 = __importDefault(require("os"));
|
||||
class Pty {
|
||||
constructor(socket, id, cwd) {
|
||||
this.socket = socket;
|
||||
this.id = id;
|
||||
this.ptyProcess = (0, node_pty_1.spawn)(os_1.default.platform() === "win32" ? "cmd.exe" : "bash", [], {
|
||||
name: "xterm",
|
||||
cols: 100,
|
||||
cwd: cwd,
|
||||
});
|
||||
this.ptyProcess.onData((data) => {
|
||||
console.log("onData", data);
|
||||
this.send(data);
|
||||
});
|
||||
// this.write("hello world")
|
||||
}
|
||||
write(data) {
|
||||
console.log("writing data", data);
|
||||
this.ptyProcess.write(data);
|
||||
}
|
||||
send(data) {
|
||||
this.socket.emit("terminalResponse", {
|
||||
data: Buffer.from(data, "utf-8"),
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.Pty = Pty;
|
3
backend/server/dist/types.js
vendored
3
backend/server/dist/types.js
vendored
@ -1,3 +0,0 @@
|
||||
"use strict";
|
||||
// DB Types
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
155
backend/server/dist/utils.js
vendored
155
backend/server/dist/utils.js
vendored
@ -1,155 +0,0 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.generateCode = exports.deleteFile = exports.saveFile = exports.renameFile = exports.createFile = exports.getSandboxFiles = void 0;
|
||||
const getSandboxFiles = (id) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const sandboxRes = yield fetch(`https://storage.ishaan1013.workers.dev/api?sandboxId=${id}`);
|
||||
const sandboxData = yield sandboxRes.json();
|
||||
const paths = sandboxData.objects.map((obj) => obj.key);
|
||||
const processedFiles = yield processFiles(paths, id);
|
||||
// console.log("processedFiles.fileData:", processedFiles.fileData)
|
||||
return processedFiles;
|
||||
});
|
||||
exports.getSandboxFiles = getSandboxFiles;
|
||||
const processFiles = (paths, id) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const root = { id: "/", type: "folder", name: "/", children: [] };
|
||||
const fileData = [];
|
||||
paths.forEach((path) => {
|
||||
const allParts = path.split("/");
|
||||
if (allParts[1] !== id) {
|
||||
console.log("invalid path!!!!");
|
||||
return;
|
||||
}
|
||||
const parts = allParts.slice(2);
|
||||
let current = root;
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
const part = parts[i];
|
||||
const isFile = i === parts.length - 1 && part.includes(".");
|
||||
const existing = current.children.find((child) => child.name === part);
|
||||
if (existing) {
|
||||
if (!isFile) {
|
||||
current = existing;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (isFile) {
|
||||
const file = { id: path, type: "file", name: part };
|
||||
current.children.push(file);
|
||||
fileData.push({ id: path, data: "" });
|
||||
}
|
||||
else {
|
||||
const folder = {
|
||||
id: path, // todo: wrong id. for example, folder "src" ID is: projects/a7vgttfqbgy403ratp7du3ln/src/App.css
|
||||
type: "folder",
|
||||
name: part,
|
||||
children: [],
|
||||
};
|
||||
current.children.push(folder);
|
||||
current = folder;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
yield Promise.all(fileData.map((file) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const data = yield fetchFileContent(file.id);
|
||||
file.data = data;
|
||||
})));
|
||||
return {
|
||||
files: root.children,
|
||||
fileData,
|
||||
};
|
||||
});
|
||||
const fetchFileContent = (fileId) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
try {
|
||||
const fileRes = yield fetch(`https://storage.ishaan1013.workers.dev/api?fileId=${fileId}`);
|
||||
return yield fileRes.text();
|
||||
}
|
||||
catch (error) {
|
||||
console.error("ERROR fetching file:", error);
|
||||
return "";
|
||||
}
|
||||
});
|
||||
const createFile = (fileId) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const res = yield fetch(`https://storage.ishaan1013.workers.dev/api`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({ fileId }),
|
||||
});
|
||||
return res.ok;
|
||||
});
|
||||
exports.createFile = createFile;
|
||||
const renameFile = (fileId, newFileId, data) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const res = yield fetch(`https://storage.ishaan1013.workers.dev/api/rename`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({ fileId, newFileId, data }),
|
||||
});
|
||||
return res.ok;
|
||||
});
|
||||
exports.renameFile = renameFile;
|
||||
const saveFile = (fileId, data) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const res = yield fetch(`https://storage.ishaan1013.workers.dev/api/save`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({ fileId, data }),
|
||||
});
|
||||
return res.ok;
|
||||
});
|
||||
exports.saveFile = saveFile;
|
||||
const deleteFile = (fileId) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const res = yield fetch(`https://storage.ishaan1013.workers.dev/api`, {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({ fileId }),
|
||||
});
|
||||
return res.ok;
|
||||
});
|
||||
exports.deleteFile = deleteFile;
|
||||
const generateCode = (_a) => __awaiter(void 0, [_a], void 0, function* ({ fileName, code, line, instructions, }) {
|
||||
return yield fetch(`https://api.cloudflare.com/client/v4/accounts/${process.env.CF_USER_ID}/ai/run/@cf/meta/llama-3-8b-instruct`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${process.env.CF_API_TOKEN}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
messages: [
|
||||
{
|
||||
role: "system",
|
||||
content: "You are an expert coding assistant. You read code from a file, and you suggest new code to add to the file. You may be given instructions on what to generate, which you should follow. You should generate code that is correct, efficient, and follows best practices. You should also generate code that is clear and easy to read. When you generate code, you should only return the code, and nothing else. You should not include backticks in the code you generate.",
|
||||
},
|
||||
{
|
||||
role: "user",
|
||||
content: `The file is called ${fileName}.`,
|
||||
},
|
||||
{
|
||||
role: "user",
|
||||
content: `Here are my instructions on what to generate: ${instructions}.`,
|
||||
},
|
||||
{
|
||||
role: "user",
|
||||
content: `Suggest me code to insert at line ${line} in my file. Give only the code, and NOTHING else. DO NOT include backticks in your response. My code file content is as follows
|
||||
|
||||
${code}`,
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
});
|
||||
exports.generateCode = generateCode;
|
@ -1,3 +1,6 @@
|
||||
ARG cf_api_token
|
||||
ARG cf_user_id
|
||||
|
||||
FROM node:20
|
||||
|
||||
WORKDIR /code
|
||||
@ -12,4 +15,7 @@ RUN npm run build
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
ENV cf_api_token=$cf_api_token
|
||||
ENV cf_user_id=$cf_user_id
|
||||
|
||||
CMD [ "node", "dist/index.js" ]
|
@ -62,7 +62,7 @@ io.use(async (socket, next) => {
|
||||
}
|
||||
|
||||
const { sandboxId, userId } = parseQuery.data
|
||||
const dbUser = await fetch(`http://localhost:8787/api/user?id=${userId}`)
|
||||
const dbUser = await fetch(`https://database.ishaan1013.workers.dev/api/user?id=${userId}`)
|
||||
const dbUserJSON = (await dbUser.json()) as User
|
||||
|
||||
if (!dbUserJSON) {
|
||||
@ -271,7 +271,7 @@ io.on("connection", async (socket) => {
|
||||
instructions: string,
|
||||
callback
|
||||
) => {
|
||||
const fetchPromise = fetch(`http://localhost:8787/api/sandbox/generate`, {
|
||||
const fetchPromise = fetch(`https://database.ishaan1013.workers.dev/api/sandbox/generate`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
|
@ -10,13 +10,17 @@ const CodeEditor = dynamic(() => import("@/components/editor"), {
|
||||
})
|
||||
|
||||
const getUserData = async (id: string) => {
|
||||
const userRes = await fetch(`http://localhost:8787/api/user?id=${id}`)
|
||||
const userRes = await fetch(
|
||||
`https://database.ishaan1013.workers.dev/api/user?id=${id}`
|
||||
)
|
||||
const userData: User = await userRes.json()
|
||||
return userData
|
||||
}
|
||||
|
||||
const getSandboxData = async (id: string) => {
|
||||
const sandboxRes = await fetch(`http://localhost:8787/api/sandbox?id=${id}`)
|
||||
const sandboxRes = await fetch(
|
||||
`https://database.ishaan1013.workers.dev/api/sandbox?id=${id}`
|
||||
)
|
||||
const sandboxData: Sandbox = await sandboxRes.json()
|
||||
return sandboxData
|
||||
}
|
||||
@ -25,7 +29,7 @@ const getSharedUsers = async (usersToSandboxes: UsersToSandboxes[]) => {
|
||||
const shared = await Promise.all(
|
||||
usersToSandboxes.map(async (user) => {
|
||||
const userRes = await fetch(
|
||||
`http://localhost:8787/api/user?id=${user.userId}`
|
||||
`https://database.ishaan1013.workers.dev/api/user?id=${user.userId}`
|
||||
)
|
||||
const userData: User = await userRes.json()
|
||||
return { id: userData.id, name: userData.name }
|
||||
|
@ -11,11 +11,13 @@ export default async function DashboardPage() {
|
||||
redirect("/")
|
||||
}
|
||||
|
||||
const userRes = await fetch(`http://localhost:8787/api/user?id=${user.id}`)
|
||||
const userRes = await fetch(
|
||||
`https://database.ishaan1013.workers.dev/api/user?id=${user.id}`
|
||||
)
|
||||
const userData = (await userRes.json()) as User
|
||||
|
||||
const sharedRes = await fetch(
|
||||
`http://localhost:8787/api/sandbox/share?id=${user.id}`
|
||||
`https://database.ishaan1013.workers.dev/api/sandbox/share?id=${user.id}`
|
||||
)
|
||||
const shared = (await sharedRes.json()) as {
|
||||
id: string
|
||||
|
@ -13,11 +13,15 @@ export default async function AppAuthLayout({
|
||||
redirect("/")
|
||||
}
|
||||
|
||||
const dbUser = await fetch(`http://localhost:8787/api/user?id=${user.id}`)
|
||||
const dbUser = await fetch(
|
||||
`https://database.ishaan1013.workers.dev/api/user?id=${user.id}`
|
||||
)
|
||||
const dbUserJSON = (await dbUser.json()) as User
|
||||
|
||||
if (!dbUserJSON.id) {
|
||||
const res = await fetch("http://localhost:8787/api/user", {
|
||||
const res = await fetch(
|
||||
"https://database.ishaan1013.workers.dev/api/user",
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@ -27,7 +31,8 @@ export default async function AppAuthLayout({
|
||||
name: user.firstName + " " + user.lastName,
|
||||
email: user.emailAddresses[0].emailAddress,
|
||||
}),
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
console.log(res)
|
||||
} else {
|
||||
|
@ -17,7 +17,9 @@ export async function POST(request: NextRequest) {
|
||||
return new Response("Unauthorized", { status: 401 })
|
||||
}
|
||||
|
||||
const res = await fetch(`http://localhost:8787/api/user?id=${clerkUser.id}`)
|
||||
const res = await fetch(
|
||||
`https://database.ishaan1013.workers.dev/api/user?id=${clerkUser.id}`
|
||||
)
|
||||
const user = (await res.json()) as User
|
||||
|
||||
const colorNames = Object.keys(colors)
|
||||
|
@ -8,13 +8,16 @@ export async function createSandbox(body: {
|
||||
userId: string
|
||||
visibility: string
|
||||
}) {
|
||||
const res = await fetch("http://localhost:8787/api/sandbox", {
|
||||
const res = await fetch(
|
||||
"https://database.ishaan1013.workers.dev/api/sandbox",
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
return await res.text()
|
||||
}
|
||||
@ -24,7 +27,7 @@ export async function updateSandbox(body: {
|
||||
name?: string
|
||||
visibility?: "public" | "private"
|
||||
}) {
|
||||
await fetch("http://localhost:8787/api/sandbox", {
|
||||
await fetch("https://database.ishaan1013.workers.dev/api/sandbox", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@ -36,7 +39,7 @@ export async function updateSandbox(body: {
|
||||
}
|
||||
|
||||
export async function deleteSandbox(id: string) {
|
||||
await fetch(`http://localhost:8787/api/sandbox?id=${id}`, {
|
||||
await fetch(`https://database.ishaan1013.workers.dev/api/sandbox?id=${id}`, {
|
||||
method: "DELETE",
|
||||
})
|
||||
|
||||
@ -44,13 +47,16 @@ export async function deleteSandbox(id: string) {
|
||||
}
|
||||
|
||||
export async function shareSandbox(sandboxId: string, email: string) {
|
||||
const res = await fetch("http://localhost:8787/api/sandbox/share", {
|
||||
const res = await fetch(
|
||||
"https://database.ishaan1013.workers.dev/api/sandbox/share",
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({ sandboxId, email }),
|
||||
})
|
||||
}
|
||||
)
|
||||
const text = await res.text()
|
||||
|
||||
if (res.status !== 200) {
|
||||
@ -62,7 +68,7 @@ export async function shareSandbox(sandboxId: string, email: string) {
|
||||
}
|
||||
|
||||
export async function unshareSandbox(sandboxId: string, userId: string) {
|
||||
await fetch("http://localhost:8787/api/sandbox/share", {
|
||||
await fetch("https://database.ishaan1013.workers.dev/api/sandbox/share", {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
|
Loading…
x
Reference in New Issue
Block a user