dynamic worker routes based on env
This commit is contained in:
parent
6285a68102
commit
6376493ae7
@ -1,16 +1,18 @@
|
|||||||
// import type { DrizzleD1Database } from "drizzle-orm/d1";
|
// import type { DrizzleD1Database } from "drizzle-orm/d1";
|
||||||
import { drizzle } from "drizzle-orm/d1";
|
import { drizzle } from "drizzle-orm/d1"
|
||||||
import { json } from "itty-router-extras";
|
import { json } from "itty-router-extras"
|
||||||
import { ZodError, z } from "zod";
|
import { ZodError, z } from "zod"
|
||||||
|
|
||||||
import { user, sandbox, usersToSandboxes } from "./schema";
|
import { user, sandbox, usersToSandboxes } from "./schema"
|
||||||
import * as schema from "./schema";
|
import * as schema from "./schema"
|
||||||
import { and, eq, sql } from "drizzle-orm";
|
import { and, eq, sql } from "drizzle-orm"
|
||||||
|
|
||||||
export interface Env {
|
export interface Env {
|
||||||
DB: D1Database;
|
DB: D1Database
|
||||||
STORAGE: any;
|
STORAGE: any
|
||||||
KV: KVNamespace;
|
KV: KVNamespace
|
||||||
|
KEY: string
|
||||||
|
STORAGE_WORKER_URL: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/drizzle-team/drizzle-orm/tree/main/examples/cloudflare-d1
|
// https://github.com/drizzle-team/drizzle-orm/tree/main/examples/cloudflare-d1
|
||||||
@ -19,130 +21,163 @@ export interface Env {
|
|||||||
// npx wrangler d1 execute d1-sandbox --local --file=./drizzle/<FILE>
|
// npx wrangler d1 execute d1-sandbox --local --file=./drizzle/<FILE>
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
|
async fetch(
|
||||||
const success = new Response("Success", { status: 200 });
|
request: Request,
|
||||||
const invalidRequest = new Response("Invalid Request", { status: 400 });
|
env: Env,
|
||||||
const notFound = new Response("Not Found", { status: 404 });
|
ctx: ExecutionContext
|
||||||
const methodNotAllowed = new Response("Method Not Allowed", { status: 405 });
|
): Promise<Response> {
|
||||||
|
const success = new Response("Success", { status: 200 })
|
||||||
|
const invalidRequest = new Response("Invalid Request", { status: 400 })
|
||||||
|
const notFound = new Response("Not Found", { status: 404 })
|
||||||
|
const methodNotAllowed = new Response("Method Not Allowed", { status: 405 })
|
||||||
|
|
||||||
const url = new URL(request.url);
|
const url = new URL(request.url)
|
||||||
const path = url.pathname;
|
const path = url.pathname
|
||||||
const method = request.method;
|
const method = request.method
|
||||||
|
|
||||||
const db = drizzle(env.DB, { schema });
|
if (request.headers.get("Authorization") !== env.KEY) {
|
||||||
|
return new Response("Unauthorized", { status: 401 })
|
||||||
|
}
|
||||||
|
|
||||||
|
const db = drizzle(env.DB, { schema })
|
||||||
|
|
||||||
if (path === "/api/session") {
|
if (path === "/api/session") {
|
||||||
if (method === "PUT") {
|
if (method === "PUT") {
|
||||||
const body = await request.json();
|
const body = await request.json()
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
userId: z.string(),
|
userId: z.string(),
|
||||||
sandboxId: z.string(),
|
sandboxId: z.string(),
|
||||||
});
|
})
|
||||||
|
|
||||||
const { userId, sandboxId } = schema.parse(body);
|
const { userId, sandboxId } = schema.parse(body)
|
||||||
|
|
||||||
await env.KV.put(userId, sandboxId);
|
await env.KV.put(userId, sandboxId)
|
||||||
|
|
||||||
return success;
|
return success
|
||||||
} else if (method === "GET") {
|
} else if (method === "GET") {
|
||||||
const params = url.searchParams;
|
const params = url.searchParams
|
||||||
if (params.has("id")) {
|
if (params.has("id")) {
|
||||||
const id = params.get("id") as string;
|
const id = params.get("id") as string
|
||||||
const sandboxId = await env.KV.get(id);
|
const sandboxId = await env.KV.get(id)
|
||||||
return json({ sandboxId });
|
return json({ sandboxId })
|
||||||
} else return invalidRequest;
|
} else return invalidRequest
|
||||||
} else if (method === "DELETE") {
|
} else if (method === "DELETE") {
|
||||||
const params = url.searchParams;
|
const params = url.searchParams
|
||||||
if (params.has("id")) {
|
if (params.has("id")) {
|
||||||
const id = params.get("id") as string;
|
const id = params.get("id") as string
|
||||||
await env.KV.delete(id);
|
await env.KV.delete(id)
|
||||||
return success;
|
return success
|
||||||
} else return invalidRequest;
|
} else return invalidRequest
|
||||||
} else return methodNotAllowed;
|
} else return methodNotAllowed
|
||||||
} else if (path === "/api/sandbox") {
|
} else if (path === "/api/sandbox") {
|
||||||
if (method === "GET") {
|
if (method === "GET") {
|
||||||
const params = url.searchParams;
|
const params = url.searchParams
|
||||||
if (params.has("id")) {
|
if (params.has("id")) {
|
||||||
const id = params.get("id") as string;
|
const id = params.get("id") as string
|
||||||
const res = await db.query.sandbox.findFirst({
|
const res = await db.query.sandbox.findFirst({
|
||||||
where: (sandbox, { eq }) => eq(sandbox.id, id),
|
where: (sandbox, { eq }) => eq(sandbox.id, id),
|
||||||
with: {
|
with: {
|
||||||
usersToSandboxes: true,
|
usersToSandboxes: true,
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
return json(res ?? {});
|
return json(res ?? {})
|
||||||
} else {
|
} else {
|
||||||
const res = await db.select().from(sandbox).all();
|
const res = await db.select().from(sandbox).all()
|
||||||
return json(res ?? {});
|
return json(res ?? {})
|
||||||
}
|
}
|
||||||
} else if (method === "DELETE") {
|
} else if (method === "DELETE") {
|
||||||
const params = url.searchParams;
|
const params = url.searchParams
|
||||||
if (params.has("id")) {
|
if (params.has("id")) {
|
||||||
const id = params.get("id") as string;
|
const id = params.get("id") as string
|
||||||
await db.delete(usersToSandboxes).where(eq(usersToSandboxes.sandboxId, id));
|
await db
|
||||||
await db.delete(sandbox).where(eq(sandbox.id, id));
|
.delete(usersToSandboxes)
|
||||||
|
.where(eq(usersToSandboxes.sandboxId, id))
|
||||||
|
await db.delete(sandbox).where(eq(sandbox.id, id))
|
||||||
|
|
||||||
const deleteStorageRequest = new Request("https://storage.ishaan1013.workers.dev/api/project", {
|
const deleteStorageRequest = new Request(
|
||||||
method: "DELETE",
|
`${env.STORAGE_WORKER_URL}/api/project`,
|
||||||
body: JSON.stringify({ sandboxId: id }),
|
{
|
||||||
headers: { "Content-Type": "application/json" },
|
method: "DELETE",
|
||||||
});
|
body: JSON.stringify({ sandboxId: id }),
|
||||||
const deleteStorageRes = await env.STORAGE.fetch(deleteStorageRequest);
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Authorization: `${env.KEY}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
await env.STORAGE.fetch(deleteStorageRequest)
|
||||||
|
|
||||||
return success;
|
return success
|
||||||
} else {
|
} else {
|
||||||
return invalidRequest;
|
return invalidRequest
|
||||||
}
|
}
|
||||||
} else if (method === "POST") {
|
} else if (method === "POST") {
|
||||||
const postSchema = z.object({
|
const postSchema = z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
name: z.string().optional(),
|
name: z.string().optional(),
|
||||||
visibility: z.enum(["public", "private"]).optional(),
|
visibility: z.enum(["public", "private"]).optional(),
|
||||||
});
|
})
|
||||||
|
|
||||||
const body = await request.json();
|
const body = await request.json()
|
||||||
const { id, name, visibility } = postSchema.parse(body);
|
const { id, name, visibility } = postSchema.parse(body)
|
||||||
const sb = await db.update(sandbox).set({ name, visibility }).where(eq(sandbox.id, id)).returning().get();
|
const sb = await db
|
||||||
|
.update(sandbox)
|
||||||
|
.set({ name, visibility })
|
||||||
|
.where(eq(sandbox.id, id))
|
||||||
|
.returning()
|
||||||
|
.get()
|
||||||
|
|
||||||
return success;
|
return success
|
||||||
} else if (method === "PUT") {
|
} else if (method === "PUT") {
|
||||||
const initSchema = z.object({
|
const initSchema = z.object({
|
||||||
type: z.enum(["react", "node"]),
|
type: z.enum(["react", "node"]),
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
userId: z.string(),
|
userId: z.string(),
|
||||||
visibility: z.enum(["public", "private"]),
|
visibility: z.enum(["public", "private"]),
|
||||||
});
|
})
|
||||||
|
|
||||||
const body = await request.json();
|
const body = await request.json()
|
||||||
const { type, name, userId, visibility } = initSchema.parse(body);
|
const { type, name, userId, visibility } = initSchema.parse(body)
|
||||||
|
|
||||||
const allSandboxes = await db.select().from(sandbox).all();
|
const allSandboxes = await db.select().from(sandbox).all()
|
||||||
if (allSandboxes.length >= 8) {
|
if (allSandboxes.length >= 8) {
|
||||||
return new Response("You reached the maximum # of sandboxes.", { status: 400 });
|
return new Response("You reached the maximum # of sandboxes.", {
|
||||||
|
status: 400,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const sb = await db.insert(sandbox).values({ type, name, userId, visibility, createdAt: new Date() }).returning().get();
|
const sb = await db
|
||||||
|
.insert(sandbox)
|
||||||
|
.values({ type, name, userId, visibility, createdAt: new Date() })
|
||||||
|
.returning()
|
||||||
|
.get()
|
||||||
|
|
||||||
const initStorageRequest = new Request("https://storage.ishaan1013.workers.dev/api/init", {
|
const initStorageRequest = new Request(
|
||||||
method: "POST",
|
`${env.STORAGE_WORKER_URL}/api/init`,
|
||||||
body: JSON.stringify({ sandboxId: sb.id, type }),
|
{
|
||||||
headers: { "Content-Type": "application/json" },
|
method: "POST",
|
||||||
});
|
body: JSON.stringify({ sandboxId: sb.id, type }),
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Authorization: `${env.KEY}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
await env.STORAGE.fetch(initStorageRequest);
|
await env.STORAGE.fetch(initStorageRequest)
|
||||||
|
|
||||||
return new Response(sb.id, { status: 200 });
|
return new Response(sb.id, { status: 200 })
|
||||||
} else {
|
} else {
|
||||||
return methodNotAllowed;
|
return methodNotAllowed
|
||||||
}
|
}
|
||||||
} else if (path === "/api/sandbox/share") {
|
} else if (path === "/api/sandbox/share") {
|
||||||
if (method === "GET") {
|
if (method === "GET") {
|
||||||
const params = url.searchParams;
|
const params = url.searchParams
|
||||||
if (params.has("id")) {
|
if (params.has("id")) {
|
||||||
const id = params.get("id") as string;
|
const id = params.get("id") as string
|
||||||
const res = await db.query.usersToSandboxes.findMany({
|
const res = await db.query.usersToSandboxes.findMany({
|
||||||
where: (uts, { eq }) => eq(uts.userId, id),
|
where: (uts, { eq }) => eq(uts.userId, id),
|
||||||
});
|
})
|
||||||
|
|
||||||
const owners = await Promise.all(
|
const owners = await Promise.all(
|
||||||
res.map(async (r) => {
|
res.map(async (r) => {
|
||||||
@ -151,22 +186,28 @@ export default {
|
|||||||
with: {
|
with: {
|
||||||
author: true,
|
author: true,
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
if (!sb) return;
|
if (!sb) return
|
||||||
return { id: sb.id, name: sb.name, type: sb.type, author: sb.author.name, sharedOn: r.sharedOn };
|
return {
|
||||||
|
id: sb.id,
|
||||||
|
name: sb.name,
|
||||||
|
type: sb.type,
|
||||||
|
author: sb.author.name,
|
||||||
|
sharedOn: r.sharedOn,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
);
|
)
|
||||||
|
|
||||||
return json(owners ?? {});
|
return json(owners ?? {})
|
||||||
} else return invalidRequest;
|
} else return invalidRequest
|
||||||
} else if (method === "POST") {
|
} else if (method === "POST") {
|
||||||
const shareSchema = z.object({
|
const shareSchema = z.object({
|
||||||
sandboxId: z.string(),
|
sandboxId: z.string(),
|
||||||
email: z.string(),
|
email: z.string(),
|
||||||
});
|
})
|
||||||
|
|
||||||
const body = await request.json();
|
const body = await request.json()
|
||||||
const { sandboxId, email } = shareSchema.parse(body);
|
const { sandboxId, email } = shareSchema.parse(body)
|
||||||
|
|
||||||
const user = await db.query.user.findFirst({
|
const user = await db.query.user.findFirst({
|
||||||
where: (user, { eq }) => eq(user.email, email),
|
where: (user, { eq }) => eq(user.email, email),
|
||||||
@ -174,66 +215,78 @@ export default {
|
|||||||
sandbox: true,
|
sandbox: true,
|
||||||
usersToSandboxes: true,
|
usersToSandboxes: true,
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return new Response("No user associated with email.", { status: 400 });
|
return new Response("No user associated with email.", { status: 400 })
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.sandbox.find((sb) => sb.id === sandboxId)) {
|
if (user.sandbox.find((sb) => sb.id === sandboxId)) {
|
||||||
return new Response("Cannot share with yourself!", { status: 400 });
|
return new Response("Cannot share with yourself!", { status: 400 })
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.usersToSandboxes.find((uts) => uts.sandboxId === sandboxId)) {
|
if (user.usersToSandboxes.find((uts) => uts.sandboxId === sandboxId)) {
|
||||||
return new Response("User already has access.", { status: 400 });
|
return new Response("User already has access.", { status: 400 })
|
||||||
}
|
}
|
||||||
|
|
||||||
await db.insert(usersToSandboxes).values({ userId: user.id, sandboxId, sharedOn: new Date() }).get();
|
await db
|
||||||
|
.insert(usersToSandboxes)
|
||||||
|
.values({ userId: user.id, sandboxId, sharedOn: new Date() })
|
||||||
|
.get()
|
||||||
|
|
||||||
return success;
|
return success
|
||||||
} else if (method === "DELETE") {
|
} else if (method === "DELETE") {
|
||||||
const deleteShareSchema = z.object({
|
const deleteShareSchema = z.object({
|
||||||
sandboxId: z.string(),
|
sandboxId: z.string(),
|
||||||
userId: z.string(),
|
userId: z.string(),
|
||||||
});
|
})
|
||||||
|
|
||||||
const body = await request.json();
|
const body = await request.json()
|
||||||
const { sandboxId, userId } = deleteShareSchema.parse(body);
|
const { sandboxId, userId } = deleteShareSchema.parse(body)
|
||||||
|
|
||||||
await db.delete(usersToSandboxes).where(and(eq(usersToSandboxes.userId, userId), eq(usersToSandboxes.sandboxId, sandboxId)));
|
await db
|
||||||
|
.delete(usersToSandboxes)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(usersToSandboxes.userId, userId),
|
||||||
|
eq(usersToSandboxes.sandboxId, sandboxId)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
return success;
|
return success
|
||||||
} else return methodNotAllowed;
|
} else return methodNotAllowed
|
||||||
} else if (path === "/api/sandbox/generate" && method === "POST") {
|
} else if (path === "/api/sandbox/generate" && method === "POST") {
|
||||||
const generateSchema = z.object({
|
const generateSchema = z.object({
|
||||||
userId: z.string(),
|
userId: z.string(),
|
||||||
});
|
})
|
||||||
const body = await request.json();
|
const body = await request.json()
|
||||||
const { userId } = generateSchema.parse(body);
|
const { userId } = generateSchema.parse(body)
|
||||||
|
|
||||||
const dbUser = await db.query.user.findFirst({
|
const dbUser = await db.query.user.findFirst({
|
||||||
where: (user, { eq }) => eq(user.id, userId),
|
where: (user, { eq }) => eq(user.id, userId),
|
||||||
});
|
})
|
||||||
if (!dbUser) {
|
if (!dbUser) {
|
||||||
return new Response("User not found.", { status: 400 });
|
return new Response("User not found.", { status: 400 })
|
||||||
}
|
}
|
||||||
if (dbUser.generations !== null && dbUser.generations >= 10) {
|
if (dbUser.generations !== null && dbUser.generations >= 10) {
|
||||||
return new Response("You reached the maximum # of generations.", { status: 400 });
|
return new Response("You reached the maximum # of generations.", {
|
||||||
|
status: 400,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
await db
|
await db
|
||||||
.update(user)
|
.update(user)
|
||||||
.set({ generations: sql`${user.generations} + 1` })
|
.set({ generations: sql`${user.generations} + 1` })
|
||||||
.where(eq(user.id, userId))
|
.where(eq(user.id, userId))
|
||||||
.get();
|
.get()
|
||||||
|
|
||||||
return success;
|
return success
|
||||||
} else if (path === "/api/user") {
|
} else if (path === "/api/user") {
|
||||||
if (method === "GET") {
|
if (method === "GET") {
|
||||||
const params = url.searchParams;
|
const params = url.searchParams
|
||||||
|
|
||||||
if (params.has("id")) {
|
if (params.has("id")) {
|
||||||
const id = params.get("id") as string;
|
const id = params.get("id") as string
|
||||||
const res = await db.query.user.findFirst({
|
const res = await db.query.user.findFirst({
|
||||||
where: (user, { eq }) => eq(user.id, id),
|
where: (user, { eq }) => eq(user.id, id),
|
||||||
with: {
|
with: {
|
||||||
@ -242,34 +295,38 @@ export default {
|
|||||||
},
|
},
|
||||||
usersToSandboxes: true,
|
usersToSandboxes: true,
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
return json(res ?? {});
|
return json(res ?? {})
|
||||||
} else {
|
} else {
|
||||||
const res = await db.select().from(user).all();
|
const res = await db.select().from(user).all()
|
||||||
return json(res ?? {});
|
return json(res ?? {})
|
||||||
}
|
}
|
||||||
} else if (method === "POST") {
|
} else if (method === "POST") {
|
||||||
const userSchema = z.object({
|
const userSchema = z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
email: z.string().email(),
|
email: z.string().email(),
|
||||||
});
|
})
|
||||||
|
|
||||||
const body = await request.json();
|
const body = await request.json()
|
||||||
const { id, name, email } = userSchema.parse(body);
|
const { id, name, email } = userSchema.parse(body)
|
||||||
|
|
||||||
const res = await db.insert(user).values({ id, name, email }).returning().get();
|
const res = await db
|
||||||
return json({ res });
|
.insert(user)
|
||||||
|
.values({ id, name, email })
|
||||||
|
.returning()
|
||||||
|
.get()
|
||||||
|
return json({ res })
|
||||||
} else if (method === "DELETE") {
|
} else if (method === "DELETE") {
|
||||||
const params = url.searchParams;
|
const params = url.searchParams
|
||||||
if (params.has("id")) {
|
if (params.has("id")) {
|
||||||
const id = params.get("id") as string;
|
const id = params.get("id") as string
|
||||||
await db.delete(user).where(eq(user.id, id));
|
await db.delete(user).where(eq(user.id, id))
|
||||||
return success;
|
return success
|
||||||
} else return invalidRequest;
|
} else return invalidRequest
|
||||||
} else {
|
} else {
|
||||||
return methodNotAllowed;
|
return methodNotAllowed
|
||||||
}
|
}
|
||||||
} else return notFound;
|
} else return notFound
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
@ -10,3 +10,7 @@ services = [{ binding = "STORAGE", service = "storage" }]
|
|||||||
binding = "DB"
|
binding = "DB"
|
||||||
database_name = ""
|
database_name = ""
|
||||||
database_id = ""
|
database_id = ""
|
||||||
|
|
||||||
|
[vars]
|
||||||
|
KEY = ""
|
||||||
|
STORAGE_WORKER_URL = ""
|
@ -1 +1,2 @@
|
|||||||
PORT=4000
|
PORT=4000
|
||||||
|
WORKERS_KEY=
|
@ -70,7 +70,12 @@ io.use(async (socket, next) => {
|
|||||||
|
|
||||||
const { sandboxId, userId } = parseQuery.data;
|
const { sandboxId, userId } = parseQuery.data;
|
||||||
const dbUser = await fetch(
|
const dbUser = await fetch(
|
||||||
`https://database.ishaan1013.workers.dev/api/user?id=${userId}`
|
`${process.env.DATABASE_WORKER_URL}/api/user?id=${userId}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `${process.env.WORKERS_KEY}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
);
|
);
|
||||||
const dbUserJSON = (await dbUser.json()) as User;
|
const dbUserJSON = (await dbUser.json()) as User;
|
||||||
|
|
||||||
@ -400,11 +405,12 @@ io.on("connection", async (socket) => {
|
|||||||
) => {
|
) => {
|
||||||
// Log code generation credit in DB
|
// Log code generation credit in DB
|
||||||
const fetchPromise = fetch(
|
const fetchPromise = fetch(
|
||||||
`https://database.ishaan1013.workers.dev/api/sandbox/generate`,
|
`${process.env.DATABASE_WORKER_URL}/api/sandbox/generate`,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
Authorization: `${process.env.WORKERS_KEY}`,
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
userId: data.userId,
|
userId: data.userId,
|
||||||
@ -414,7 +420,7 @@ io.on("connection", async (socket) => {
|
|||||||
|
|
||||||
// Generate code from cloudflare workers AI
|
// Generate code from cloudflare workers AI
|
||||||
const generateCodePromise = fetch(
|
const generateCodePromise = fetch(
|
||||||
`https://ai.ishaan1013.workers.dev/api?fileName=${fileName}&code=${code}&line=${line}&instructions=${instructions}`,
|
`${process.env.AI_WORKER_URL}/api?fileName=${fileName}&code=${code}&line=${line}&instructions=${instructions}`,
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
@ -12,7 +12,12 @@ dotenv.config();
|
|||||||
|
|
||||||
export const getSandboxFiles = async (id: string) => {
|
export const getSandboxFiles = async (id: string) => {
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`https://storage.ishaan1013.workers.dev/api?sandboxId=${id}`
|
`${process.env.STORAGE_WORKER_URL}/api?sandboxId=${id}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `${process.env.WORKERS_KEY}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
);
|
);
|
||||||
const data: R2Files = await res.json();
|
const data: R2Files = await res.json();
|
||||||
|
|
||||||
@ -23,7 +28,12 @@ export const getSandboxFiles = async (id: string) => {
|
|||||||
|
|
||||||
export const getFolder = async (folderId: string) => {
|
export const getFolder = async (folderId: string) => {
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`https://storage.ishaan1013.workers.dev/api?folderId=${folderId}`
|
`${process.env.STORAGE_WORKER_URL}/api?folderId=${folderId}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `${process.env.WORKERS_KEY}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
);
|
);
|
||||||
const data: R2Files = await res.json();
|
const data: R2Files = await res.json();
|
||||||
|
|
||||||
@ -88,7 +98,12 @@ const processFiles = async (paths: string[], id: string) => {
|
|||||||
const fetchFileContent = async (fileId: string): Promise<string> => {
|
const fetchFileContent = async (fileId: string): Promise<string> => {
|
||||||
try {
|
try {
|
||||||
const fileRes = await fetch(
|
const fileRes = await fetch(
|
||||||
`https://storage.ishaan1013.workers.dev/api?fileId=${fileId}`
|
`${process.env.STORAGE_WORKER_URL}/api?fileId=${fileId}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `${process.env.WORKERS_KEY}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
);
|
);
|
||||||
return await fileRes.text();
|
return await fileRes.text();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -98,10 +113,11 @@ const fetchFileContent = async (fileId: string): Promise<string> => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const createFile = async (fileId: string) => {
|
export const createFile = async (fileId: string) => {
|
||||||
const res = await fetch(`https://storage.ishaan1013.workers.dev/api`, {
|
const res = await fetch(`${process.env.STORAGE_WORKER_URL}/api`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
Authorization: `${process.env.WORKERS_KEY}`,
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ fileId }),
|
body: JSON.stringify({ fileId }),
|
||||||
});
|
});
|
||||||
@ -113,10 +129,11 @@ export const renameFile = async (
|
|||||||
newFileId: string,
|
newFileId: string,
|
||||||
data: string
|
data: string
|
||||||
) => {
|
) => {
|
||||||
const res = await fetch(`https://storage.ishaan1013.workers.dev/api/rename`, {
|
const res = await fetch(`${process.env.STORAGE_WORKER_URL}/api/rename`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
Authorization: `${process.env.WORKERS_KEY}`,
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ fileId, newFileId, data }),
|
body: JSON.stringify({ fileId, newFileId, data }),
|
||||||
});
|
});
|
||||||
@ -124,10 +141,11 @@ export const renameFile = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const saveFile = async (fileId: string, data: string) => {
|
export const saveFile = async (fileId: string, data: string) => {
|
||||||
const res = await fetch(`https://storage.ishaan1013.workers.dev/api/save`, {
|
const res = await fetch(`${process.env.STORAGE_WORKER_URL}/api/save`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
Authorization: `${process.env.WORKERS_KEY}`,
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ fileId, data }),
|
body: JSON.stringify({ fileId, data }),
|
||||||
});
|
});
|
||||||
@ -135,10 +153,11 @@ export const saveFile = async (fileId: string, data: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const deleteFile = async (fileId: string) => {
|
export const deleteFile = async (fileId: string) => {
|
||||||
const res = await fetch(`https://storage.ishaan1013.workers.dev/api`, {
|
const res = await fetch(`${process.env.STORAGE_WORKER_URL}/api`, {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
Authorization: `${process.env.WORKERS_KEY}`,
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ fileId }),
|
body: JSON.stringify({ fileId }),
|
||||||
});
|
});
|
||||||
@ -147,7 +166,12 @@ export const deleteFile = async (fileId: string) => {
|
|||||||
|
|
||||||
export const getProjectSize = async (id: string) => {
|
export const getProjectSize = async (id: string) => {
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`https://storage.ishaan1013.workers.dev/api/size?sandboxId=${id}`
|
`${process.env.STORAGE_WORKER_URL}/api/size?sandboxId=${id}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `${process.env.WORKERS_KEY}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
);
|
);
|
||||||
return (await res.json()).size;
|
return (await res.json()).size;
|
||||||
};
|
};
|
||||||
|
@ -1,150 +1,159 @@
|
|||||||
import { z } from 'zod';
|
import { z } from "zod"
|
||||||
import startercode from './startercode';
|
import startercode from "./startercode"
|
||||||
|
|
||||||
export interface Env {
|
export interface Env {
|
||||||
R2: R2Bucket;
|
R2: R2Bucket
|
||||||
|
KEY: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
|
async fetch(
|
||||||
const success = new Response('Success', { status: 200 });
|
request: Request,
|
||||||
const invalidRequest = new Response('Invalid Request', { status: 400 });
|
env: Env,
|
||||||
const notFound = new Response('Not Found', { status: 404 });
|
ctx: ExecutionContext
|
||||||
const methodNotAllowed = new Response('Method Not Allowed', { status: 405 });
|
): Promise<Response> {
|
||||||
|
const success = new Response("Success", { status: 200 })
|
||||||
|
const invalidRequest = new Response("Invalid Request", { status: 400 })
|
||||||
|
const notFound = new Response("Not Found", { status: 404 })
|
||||||
|
const methodNotAllowed = new Response("Method Not Allowed", { status: 405 })
|
||||||
|
|
||||||
const url = new URL(request.url);
|
if (request.headers.get("Authorization") !== env.KEY) {
|
||||||
const path = url.pathname;
|
return new Response("Unauthorized", { status: 401 })
|
||||||
const method = request.method;
|
}
|
||||||
|
|
||||||
if (path === '/api/project' && method === 'DELETE') {
|
const url = new URL(request.url)
|
||||||
|
const path = url.pathname
|
||||||
|
const method = request.method
|
||||||
|
|
||||||
|
if (path === "/api/project" && method === "DELETE") {
|
||||||
const deleteSchema = z.object({
|
const deleteSchema = z.object({
|
||||||
sandboxId: z.string(),
|
sandboxId: z.string(),
|
||||||
});
|
})
|
||||||
|
|
||||||
const body = await request.json();
|
const body = await request.json()
|
||||||
const { sandboxId } = deleteSchema.parse(body);
|
const { sandboxId } = deleteSchema.parse(body)
|
||||||
|
|
||||||
const res = await env.R2.list({ prefix: 'projects/' + sandboxId });
|
const res = await env.R2.list({ prefix: "projects/" + sandboxId })
|
||||||
// delete all files
|
// delete all files
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
res.objects.map(async (file) => {
|
res.objects.map(async (file) => {
|
||||||
await env.R2.delete(file.key);
|
await env.R2.delete(file.key)
|
||||||
})
|
})
|
||||||
);
|
)
|
||||||
|
|
||||||
return success;
|
return success
|
||||||
} else if (path === '/api/size' && method === 'GET') {
|
} else if (path === "/api/size" && method === "GET") {
|
||||||
const params = url.searchParams;
|
const params = url.searchParams
|
||||||
const sandboxId = params.get('sandboxId');
|
const sandboxId = params.get("sandboxId")
|
||||||
|
|
||||||
if (sandboxId) {
|
if (sandboxId) {
|
||||||
const res = await env.R2.list({ prefix: `projects/${sandboxId}` });
|
const res = await env.R2.list({ prefix: `projects/${sandboxId}` })
|
||||||
|
|
||||||
// sum up the size of all files
|
// sum up the size of all files
|
||||||
let size = 0;
|
let size = 0
|
||||||
for (const file of res.objects) {
|
for (const file of res.objects) {
|
||||||
size += file.size;
|
size += file.size
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Response(JSON.stringify({ size }), { status: 200 });
|
return new Response(JSON.stringify({ size }), { status: 200 })
|
||||||
} else return invalidRequest;
|
} else return invalidRequest
|
||||||
} else if (path === '/api') {
|
} else if (path === "/api") {
|
||||||
if (method === 'GET') {
|
if (method === "GET") {
|
||||||
const params = url.searchParams;
|
const params = url.searchParams
|
||||||
const sandboxId = params.get('sandboxId');
|
const sandboxId = params.get("sandboxId")
|
||||||
const folderId = params.get('folderId');
|
const folderId = params.get("folderId")
|
||||||
const fileId = params.get('fileId');
|
const fileId = params.get("fileId")
|
||||||
|
|
||||||
if (sandboxId) {
|
if (sandboxId) {
|
||||||
const res = await env.R2.list({ prefix: `projects/${sandboxId}` });
|
const res = await env.R2.list({ prefix: `projects/${sandboxId}` })
|
||||||
return new Response(JSON.stringify(res), { status: 200 });
|
return new Response(JSON.stringify(res), { status: 200 })
|
||||||
} else if (folderId) {
|
} else if (folderId) {
|
||||||
const res = await env.R2.list({ prefix: folderId });
|
const res = await env.R2.list({ prefix: folderId })
|
||||||
return new Response(JSON.stringify(res), { status: 200 });
|
return new Response(JSON.stringify(res), { status: 200 })
|
||||||
} else if (fileId) {
|
} else if (fileId) {
|
||||||
const obj = await env.R2.get(fileId);
|
const obj = await env.R2.get(fileId)
|
||||||
if (obj === null) {
|
if (obj === null) {
|
||||||
return new Response(`${fileId} not found`, { status: 404 });
|
return new Response(`${fileId} not found`, { status: 404 })
|
||||||
}
|
}
|
||||||
const headers = new Headers();
|
const headers = new Headers()
|
||||||
headers.set('etag', obj.httpEtag);
|
headers.set("etag", obj.httpEtag)
|
||||||
obj.writeHttpMetadata(headers);
|
obj.writeHttpMetadata(headers)
|
||||||
|
|
||||||
const text = await obj.text();
|
const text = await obj.text()
|
||||||
|
|
||||||
return new Response(text, {
|
return new Response(text, {
|
||||||
headers,
|
headers,
|
||||||
});
|
})
|
||||||
} else return invalidRequest;
|
} else return invalidRequest
|
||||||
} else if (method === 'POST') {
|
} else if (method === "POST") {
|
||||||
const createSchema = z.object({
|
const createSchema = z.object({
|
||||||
fileId: z.string(),
|
fileId: z.string(),
|
||||||
});
|
})
|
||||||
|
|
||||||
const body = await request.json();
|
const body = await request.json()
|
||||||
const { fileId } = createSchema.parse(body);
|
const { fileId } = createSchema.parse(body)
|
||||||
|
|
||||||
await env.R2.put(fileId, '');
|
await env.R2.put(fileId, "")
|
||||||
|
|
||||||
return success;
|
return success
|
||||||
} else if (method === 'DELETE') {
|
} else if (method === "DELETE") {
|
||||||
const deleteSchema = z.object({
|
const deleteSchema = z.object({
|
||||||
fileId: z.string(),
|
fileId: z.string(),
|
||||||
});
|
})
|
||||||
|
|
||||||
const body = await request.json();
|
const body = await request.json()
|
||||||
const { fileId } = deleteSchema.parse(body);
|
const { fileId } = deleteSchema.parse(body)
|
||||||
|
|
||||||
await env.R2.delete(fileId);
|
await env.R2.delete(fileId)
|
||||||
|
|
||||||
return success;
|
return success
|
||||||
} else return methodNotAllowed;
|
} else return methodNotAllowed
|
||||||
} else if (path === '/api/rename' && method === 'POST') {
|
} else if (path === "/api/rename" && method === "POST") {
|
||||||
const renameSchema = z.object({
|
const renameSchema = z.object({
|
||||||
fileId: z.string(),
|
fileId: z.string(),
|
||||||
newFileId: z.string(),
|
newFileId: z.string(),
|
||||||
data: z.string(),
|
data: z.string(),
|
||||||
});
|
})
|
||||||
|
|
||||||
const body = await request.json();
|
const body = await request.json()
|
||||||
const { fileId, newFileId, data } = renameSchema.parse(body);
|
const { fileId, newFileId, data } = renameSchema.parse(body)
|
||||||
|
|
||||||
await env.R2.delete(fileId);
|
await env.R2.delete(fileId)
|
||||||
await env.R2.put(newFileId, data);
|
await env.R2.put(newFileId, data)
|
||||||
|
|
||||||
return success;
|
return success
|
||||||
} else if (path === '/api/save' && method === 'POST') {
|
} else if (path === "/api/save" && method === "POST") {
|
||||||
const renameSchema = z.object({
|
const renameSchema = z.object({
|
||||||
fileId: z.string(),
|
fileId: z.string(),
|
||||||
data: z.string(),
|
data: z.string(),
|
||||||
});
|
})
|
||||||
|
|
||||||
const body = await request.json();
|
const body = await request.json()
|
||||||
const { fileId, data } = renameSchema.parse(body);
|
const { fileId, data } = renameSchema.parse(body)
|
||||||
|
|
||||||
await env.R2.put(fileId, data);
|
await env.R2.put(fileId, data)
|
||||||
|
|
||||||
return success;
|
return success
|
||||||
} else if (path === '/api/init' && method === 'POST') {
|
} else if (path === "/api/init" && method === "POST") {
|
||||||
const initSchema = z.object({
|
const initSchema = z.object({
|
||||||
sandboxId: z.string(),
|
sandboxId: z.string(),
|
||||||
type: z.enum(['react', 'node']),
|
type: z.enum(["react", "node"]),
|
||||||
});
|
})
|
||||||
|
|
||||||
const body = await request.json();
|
const body = await request.json()
|
||||||
const { sandboxId, type } = initSchema.parse(body);
|
const { sandboxId, type } = initSchema.parse(body)
|
||||||
|
|
||||||
console.log(startercode[type]);
|
console.log(startercode[type])
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
startercode[type].map(async (file) => {
|
startercode[type].map(async (file) => {
|
||||||
await env.R2.put(`projects/${sandboxId}/${file.name}`, file.body);
|
await env.R2.put(`projects/${sandboxId}/${file.name}`, file.body)
|
||||||
})
|
})
|
||||||
);
|
)
|
||||||
|
|
||||||
return success;
|
return success
|
||||||
} else {
|
} else {
|
||||||
return notFound;
|
return notFound
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
@ -11,3 +11,6 @@ workers_dev = true
|
|||||||
binding = 'R2'
|
binding = 'R2'
|
||||||
bucket_name = ''
|
bucket_name = ''
|
||||||
preview_bucket_name = ''
|
preview_bucket_name = ''
|
||||||
|
|
||||||
|
[vars]
|
||||||
|
KEY = ''
|
@ -4,6 +4,10 @@ NEXT_PUBLIC_LIVEBLOCKS_PUBLIC_KEY=
|
|||||||
LIVEBLOCKS_SECRET_KEY=
|
LIVEBLOCKS_SECRET_KEY=
|
||||||
|
|
||||||
NEXT_PUBLIC_SERVER_PORT=4000
|
NEXT_PUBLIC_SERVER_PORT=4000
|
||||||
|
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
||||||
|
|
||||||
|
NEXT_PUBLIC_DATABASE_WORKER_URL=
|
||||||
|
NEXT_PUBLIC_STORAGE_WORKER_URL=
|
||||||
|
|
||||||
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
|
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
|
||||||
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
|
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
|
||||||
|
@ -11,7 +11,12 @@ export const revalidate = 0
|
|||||||
|
|
||||||
const getUserData = async (id: string) => {
|
const getUserData = async (id: string) => {
|
||||||
const userRes = await fetch(
|
const userRes = await fetch(
|
||||||
`https://database.ishaan1013.workers.dev/api/user?id=${id}`
|
`${process.env.NEXT_PUBLIC_DATABASE_WORKER_URL}/api/user?id=${id}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `${process.env.NEXT_PUBLIC_WORKERS_KEY}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
const userData: User = await userRes.json()
|
const userData: User = await userRes.json()
|
||||||
return userData
|
return userData
|
||||||
@ -19,7 +24,12 @@ const getUserData = async (id: string) => {
|
|||||||
|
|
||||||
const getSandboxData = async (id: string) => {
|
const getSandboxData = async (id: string) => {
|
||||||
const sandboxRes = await fetch(
|
const sandboxRes = await fetch(
|
||||||
`https://database.ishaan1013.workers.dev/api/sandbox?id=${id}`
|
`${process.env.NEXT_PUBLIC_DATABASE_WORKER_URL}/api/sandbox?id=${id}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `${process.env.NEXT_PUBLIC_WORKERS_KEY}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
const sandboxData: Sandbox = await sandboxRes.json()
|
const sandboxData: Sandbox = await sandboxRes.json()
|
||||||
return sandboxData
|
return sandboxData
|
||||||
@ -33,7 +43,12 @@ const getSharedUsers = async (usersToSandboxes: UsersToSandboxes[]) => {
|
|||||||
const shared = await Promise.all(
|
const shared = await Promise.all(
|
||||||
usersToSandboxes.map(async (user) => {
|
usersToSandboxes.map(async (user) => {
|
||||||
const userRes = await fetch(
|
const userRes = await fetch(
|
||||||
`https://database.ishaan1013.workers.dev/api/user?id=${user.userId}`
|
`${process.env.NEXT_PUBLIC_DATABASE_WORKER_URL}/api/user?id=${user.userId}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `${process.env.NEXT_PUBLIC_WORKERS_KEY}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
const userData: User = await userRes.json()
|
const userData: User = await userRes.json()
|
||||||
return { id: userData.id, name: userData.name }
|
return { id: userData.id, name: userData.name }
|
||||||
|
@ -12,12 +12,22 @@ export default async function DashboardPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const userRes = await fetch(
|
const userRes = await fetch(
|
||||||
`https://database.ishaan1013.workers.dev/api/user?id=${user.id}`
|
`${process.env.NEXT_PUBLIC_DATABASE_WORKER_URL}/api/user?id=${user.id}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `${process.env.NEXT_PUBLIC_WORKERS_KEY}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
const userData = (await userRes.json()) as User
|
const userData = (await userRes.json()) as User
|
||||||
|
|
||||||
const sharedRes = await fetch(
|
const sharedRes = await fetch(
|
||||||
`https://database.ishaan1013.workers.dev/api/sandbox/share?id=${user.id}`
|
`${process.env.NEXT_PUBLIC_DATABASE_WORKER_URL}/api/sandbox/share?id=${user.id}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `${process.env.NEXT_PUBLIC_WORKERS_KEY}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
const shared = (await sharedRes.json()) as {
|
const shared = (await sharedRes.json()) as {
|
||||||
id: string
|
id: string
|
||||||
|
@ -1,30 +1,36 @@
|
|||||||
import { User } from "@/lib/types";
|
import { User } from "@/lib/types"
|
||||||
import { currentUser } from "@clerk/nextjs";
|
import { currentUser } from "@clerk/nextjs"
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation"
|
||||||
|
|
||||||
export default async function AppAuthLayout({
|
export default async function AppAuthLayout({
|
||||||
children,
|
children,
|
||||||
}: {
|
}: {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode
|
||||||
}) {
|
}) {
|
||||||
const user = await currentUser();
|
const user = await currentUser()
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
redirect("/");
|
redirect("/")
|
||||||
}
|
}
|
||||||
|
|
||||||
const dbUser = await fetch(
|
const dbUser = await fetch(
|
||||||
`https://database.ishaan1013.workers.dev/api/user?id=${user.id}`
|
`${process.env.NEXT_PUBLIC_DATABASE_WORKER_URL}/api/user?id=${user.id}`,
|
||||||
);
|
{
|
||||||
const dbUserJSON = (await dbUser.json()) as User;
|
headers: {
|
||||||
|
Authorization: `${process.env.NEXT_PUBLIC_WORKERS_KEY}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
const dbUserJSON = (await dbUser.json()) as User
|
||||||
|
|
||||||
if (!dbUserJSON.id) {
|
if (!dbUserJSON.id) {
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
"https://database.ishaan1013.workers.dev/api/user",
|
`${process.env.NEXT_PUBLIC_DATABASE_WORKER_URL}/api/user`,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
Authorization: `${process.env.NEXT_PUBLIC_WORKERS_KEY}`,
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
id: user.id,
|
id: user.id,
|
||||||
@ -32,8 +38,8 @@ export default async function AppAuthLayout({
|
|||||||
email: user.emailAddresses[0].emailAddress,
|
email: user.emailAddresses[0].emailAddress,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return <>{children}</>;
|
return <>{children}</>
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,12 @@ export async function POST(request: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
`https://database.ishaan1013.workers.dev/api/user?id=${clerkUser.id}`
|
`${process.env.NEXT_PUBLIC_DATABASE_WORKER_URL}/api/user?id=${clerkUser.id}`,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
Authorization: `${process.env.NEXT_PUBLIC_WORKERS_KEY}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
const user = (await res.json()) as User
|
const user = (await res.json()) as User
|
||||||
|
|
||||||
|
@ -60,9 +60,7 @@ export default function GenerateInput({
|
|||||||
regenerate?: boolean
|
regenerate?: boolean
|
||||||
}) => {
|
}) => {
|
||||||
if (user.generations >= 10) {
|
if (user.generations >= 10) {
|
||||||
toast.error(
|
toast.error("You reached the maximum # of generations.")
|
||||||
"You reached the maximum # of generations. Contact @ishaandey_ on X/Twitter to reset :)"
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,8 +51,7 @@ export default function Loading({
|
|||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
{didFail ? (
|
{didFail ? (
|
||||||
<DialogDescription className="pt-2">
|
<DialogDescription className="pt-2">
|
||||||
Try again in a minute, or contact @ishaandey_ on Twitter/X if it
|
Try again soon.
|
||||||
still doesn't work.
|
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
) : description ? (
|
) : description ? (
|
||||||
<DialogDescription className="pt-2">
|
<DialogDescription className="pt-2">
|
||||||
|
@ -75,13 +75,17 @@ export default function ShareSandboxModal({
|
|||||||
{data.visibility === "private" ? (
|
{data.visibility === "private" ? (
|
||||||
<DialogDescription className="text-sm text-muted-foreground">
|
<DialogDescription className="text-sm text-muted-foreground">
|
||||||
This sandbox is private. Making it public will allow shared
|
This sandbox is private. Making it public will allow shared
|
||||||
users to view and collaborate. You can still share & manage access below.
|
users to view and collaborate. You can still share & manage
|
||||||
|
access below.
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
) : null}
|
) : null}
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div className="flex space-x-4 w-full">
|
<div className="flex space-x-4 w-full">
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form onSubmit={form.handleSubmit(onSubmit)} className="flex w-full">
|
<form
|
||||||
|
onSubmit={form.handleSubmit(onSubmit)}
|
||||||
|
className="flex w-full"
|
||||||
|
>
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="email"
|
name="email"
|
||||||
@ -101,7 +105,8 @@ export default function ShareSandboxModal({
|
|||||||
<Button disabled={loading} type="submit" className="">
|
<Button disabled={loading} type="submit" className="">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<>
|
<>
|
||||||
<Loader2 className="animate-spin mr-2 h-4 w-4" /> Loading...
|
<Loader2 className="animate-spin mr-2 h-4 w-4" />{" "}
|
||||||
|
Loading...
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
@ -111,11 +116,19 @@ export default function ShareSandboxModal({
|
|||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
<Button onClick={() => {
|
<Button
|
||||||
navigator.clipboard.writeText(`https://s.ishaand.com/code/${data.id}`)
|
onClick={() => {
|
||||||
toast.success("Link copied to clipboard.")
|
navigator.clipboard.writeText(
|
||||||
}} size="icon" disabled={loading} variant="outline" className="shrink-0">
|
`${process.env.NEXT_PUBLIC_APP_URL}/code/${data.id}`
|
||||||
<Link className="h-4 w-4" />
|
)
|
||||||
|
toast.success("Link copied to clipboard.")
|
||||||
|
}}
|
||||||
|
size="icon"
|
||||||
|
disabled={loading}
|
||||||
|
variant="outline"
|
||||||
|
className="shrink-0"
|
||||||
|
>
|
||||||
|
<Link className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -9,11 +9,12 @@ export async function createSandbox(body: {
|
|||||||
visibility: string
|
visibility: string
|
||||||
}) {
|
}) {
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
"https://database.ishaan1013.workers.dev/api/sandbox",
|
`${process.env.NEXT_PUBLIC_DATABASE_WORKER_URL}/api/sandbox`,
|
||||||
{
|
{
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
Authorization: `${process.env.NEXT_PUBLIC_WORKERS_KEY}`,
|
||||||
},
|
},
|
||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body),
|
||||||
}
|
}
|
||||||
@ -27,10 +28,11 @@ export async function updateSandbox(body: {
|
|||||||
name?: string
|
name?: string
|
||||||
visibility?: "public" | "private"
|
visibility?: "public" | "private"
|
||||||
}) {
|
}) {
|
||||||
await fetch("https://database.ishaan1013.workers.dev/api/sandbox", {
|
await fetch(`${process.env.NEXT_PUBLIC_DATABASE_WORKER_URL}/api/sandbox`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
Authorization: `${process.env.NEXT_PUBLIC_WORKERS_KEY}`,
|
||||||
},
|
},
|
||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body),
|
||||||
})
|
})
|
||||||
@ -39,20 +41,27 @@ export async function updateSandbox(body: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteSandbox(id: string) {
|
export async function deleteSandbox(id: string) {
|
||||||
await fetch(`https://database.ishaan1013.workers.dev/api/sandbox?id=${id}`, {
|
await fetch(
|
||||||
method: "DELETE",
|
`${process.env.NEXT_PUBLIC_DATABASE_WORKER_URL}/api/sandbox?id=${id}`,
|
||||||
})
|
{
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
Authorization: `${process.env.NEXT_PUBLIC_WORKERS_KEY}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
revalidatePath("/dashboard")
|
revalidatePath("/dashboard")
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function shareSandbox(sandboxId: string, email: string) {
|
export async function shareSandbox(sandboxId: string, email: string) {
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
"https://database.ishaan1013.workers.dev/api/sandbox/share",
|
`${process.env.NEXT_PUBLIC_DATABASE_WORKER_URL}/api/sandbox/share`,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
Authorization: `${process.env.NEXT_PUBLIC_WORKERS_KEY}`,
|
||||||
},
|
},
|
||||||
body: JSON.stringify({ sandboxId, email }),
|
body: JSON.stringify({ sandboxId, email }),
|
||||||
}
|
}
|
||||||
@ -68,13 +77,17 @@ export async function shareSandbox(sandboxId: string, email: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function unshareSandbox(sandboxId: string, userId: string) {
|
export async function unshareSandbox(sandboxId: string, userId: string) {
|
||||||
await fetch("https://database.ishaan1013.workers.dev/api/sandbox/share", {
|
await fetch(
|
||||||
method: "DELETE",
|
`${process.env.NEXT_PUBLIC_DATABASE_WORKER_URL}/api/sandbox/share`,
|
||||||
headers: {
|
{
|
||||||
"Content-Type": "application/json",
|
method: "DELETE",
|
||||||
},
|
headers: {
|
||||||
body: JSON.stringify({ sandboxId, userId }),
|
"Content-Type": "application/json",
|
||||||
})
|
Authorization: `${process.env.NEXT_PUBLIC_WORKERS_KEY}`,
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ sandboxId, userId }),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
revalidatePath(`/code/${sandboxId}`)
|
revalidatePath(`/code/${sandboxId}`)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user