sql schema update + start share logic

This commit is contained in:
Ishaan Dey 2024-05-01 01:29:16 -04:00
parent c171cb580e
commit 66a76eb0f9
13 changed files with 294 additions and 82 deletions

View File

@ -1,18 +0,0 @@
CREATE TABLE `sandbox` (
`id` text PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`type` text NOT NULL,
`bucket` text,
`init` integer DEFAULT false,
`user_id` text NOT NULL,
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE no action
);
--> statement-breakpoint
CREATE TABLE `user` (
`id` text PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`email` text NOT NULL
);
--> statement-breakpoint
CREATE UNIQUE INDEX `sandbox_id_unique` ON `sandbox` (`id`);--> statement-breakpoint
CREATE UNIQUE INDEX `user_id_unique` ON `user` (`id`);

View File

@ -1,2 +0,0 @@
ALTER TABLE `sandbox` DROP COLUMN `bucket`;--> statement-breakpoint
ALTER TABLE `sandbox` DROP COLUMN `init`;

View File

@ -1 +0,0 @@
ALTER TABLE sandbox ADD `visibility` text;

View File

@ -1,7 +1,7 @@
{ {
"version": "5", "version": "5",
"dialect": "sqlite", "dialect": "sqlite",
"id": "9c09f493-3a05-496c-997e-b527c8f17cf9", "id": "6570ba20-a672-400c-8147-7ba533784918",
"prevId": "00000000-0000-0000-0000-000000000000", "prevId": "00000000-0000-0000-0000-000000000000",
"tables": { "tables": {
"sandbox": { "sandbox": {
@ -28,21 +28,13 @@
"notNull": true, "notNull": true,
"autoincrement": false "autoincrement": false
}, },
"bucket": { "visibility": {
"name": "bucket", "name": "visibility",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": false, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"init": {
"name": "init",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": false
},
"user_id": { "user_id": {
"name": "user_id", "name": "user_id",
"type": "text", "type": "text",
@ -115,6 +107,56 @@
"foreignKeys": {}, "foreignKeys": {},
"compositePrimaryKeys": {}, "compositePrimaryKeys": {},
"uniqueConstraints": {} "uniqueConstraints": {}
},
"users_to_sandboxes": {
"name": "users_to_sandboxes",
"columns": {
"userId": {
"name": "userId",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"sandboxId": {
"name": "sandboxId",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {
"users_to_sandboxes_userId_user_id_fk": {
"name": "users_to_sandboxes_userId_user_id_fk",
"tableFrom": "users_to_sandboxes",
"tableTo": "user",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"users_to_sandboxes_sandboxId_sandbox_id_fk": {
"name": "users_to_sandboxes_sandboxId_sandbox_id_fk",
"tableFrom": "users_to_sandboxes",
"tableTo": "sandbox",
"columnsFrom": [
"sandboxId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
} }
}, },
"enums": {}, "enums": {},

View File

@ -1,8 +1,8 @@
{ {
"version": "5", "version": "5",
"dialect": "sqlite", "dialect": "sqlite",
"id": "739c5df4-de1b-408b-bc8c-5783688c5297", "id": "9f64104a-4954-40c0-8155-17755ea0a243",
"prevId": "9c09f493-3a05-496c-997e-b527c8f17cf9", "prevId": "6570ba20-a672-400c-8147-7ba533784918",
"tables": { "tables": {
"sandbox": { "sandbox": {
"name": "sandbox", "name": "sandbox",
@ -28,6 +28,13 @@
"notNull": true, "notNull": true,
"autoincrement": false "autoincrement": false
}, },
"visibility": {
"name": "visibility",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"user_id": { "user_id": {
"name": "user_id", "name": "user_id",
"type": "text", "type": "text",
@ -86,6 +93,13 @@
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true,
"autoincrement": false "autoincrement": false
},
"image": {
"name": "image",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
} }
}, },
"indexes": { "indexes": {
@ -100,6 +114,56 @@
"foreignKeys": {}, "foreignKeys": {},
"compositePrimaryKeys": {}, "compositePrimaryKeys": {},
"uniqueConstraints": {} "uniqueConstraints": {}
},
"users_to_sandboxes": {
"name": "users_to_sandboxes",
"columns": {
"userId": {
"name": "userId",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"sandboxId": {
"name": "sandboxId",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {
"users_to_sandboxes_userId_user_id_fk": {
"name": "users_to_sandboxes_userId_user_id_fk",
"tableFrom": "users_to_sandboxes",
"tableTo": "user",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"users_to_sandboxes_sandboxId_sandbox_id_fk": {
"name": "users_to_sandboxes_sandboxId_sandbox_id_fk",
"tableFrom": "users_to_sandboxes",
"tableTo": "sandbox",
"columnsFrom": [
"sandboxId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
} }
}, },
"enums": {}, "enums": {},

View File

@ -1,8 +1,8 @@
{ {
"version": "5", "version": "5",
"dialect": "sqlite", "dialect": "sqlite",
"id": "a2239d60-e4b8-4375-979f-bbca5539a825", "id": "5baf10d6-7697-42ba-a11a-ee4c7bd7e91e",
"prevId": "739c5df4-de1b-408b-bc8c-5783688c5297", "prevId": "9f64104a-4954-40c0-8155-17755ea0a243",
"tables": { "tables": {
"sandbox": { "sandbox": {
"name": "sandbox", "name": "sandbox",
@ -32,7 +32,7 @@
"name": "visibility", "name": "visibility",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": false,
"autoincrement": false "autoincrement": false
}, },
"user_id": { "user_id": {
@ -107,6 +107,56 @@
"foreignKeys": {}, "foreignKeys": {},
"compositePrimaryKeys": {}, "compositePrimaryKeys": {},
"uniqueConstraints": {} "uniqueConstraints": {}
},
"users_to_sandboxes": {
"name": "users_to_sandboxes",
"columns": {
"userId": {
"name": "userId",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"sandboxId": {
"name": "sandboxId",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {
"users_to_sandboxes_userId_user_id_fk": {
"name": "users_to_sandboxes_userId_user_id_fk",
"tableFrom": "users_to_sandboxes",
"tableTo": "user",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"users_to_sandboxes_sandboxId_sandbox_id_fk": {
"name": "users_to_sandboxes_sandboxId_sandbox_id_fk",
"tableFrom": "users_to_sandboxes",
"tableTo": "sandbox",
"columnsFrom": [
"sandboxId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
} }
}, },
"enums": {}, "enums": {},

View File

@ -1,8 +1,8 @@
{ {
"version": "5", "version": "5",
"dialect": "sqlite", "dialect": "sqlite",
"id": "913932e8-65cf-40b9-a978-8818396234f6", "id": "37e38b82-1494-4818-8c26-b9024cce3fa9",
"prevId": "a2239d60-e4b8-4375-979f-bbca5539a825", "prevId": "5baf10d6-7697-42ba-a11a-ee4c7bd7e91e",
"tables": { "tables": {
"sandbox": { "sandbox": {
"name": "sandbox", "name": "sandbox",
@ -93,6 +93,13 @@
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true,
"autoincrement": false "autoincrement": false
},
"image": {
"name": "image",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
} }
}, },
"indexes": { "indexes": {
@ -107,6 +114,56 @@
"foreignKeys": {}, "foreignKeys": {},
"compositePrimaryKeys": {}, "compositePrimaryKeys": {},
"uniqueConstraints": {} "uniqueConstraints": {}
},
"users_to_sandboxes": {
"name": "users_to_sandboxes",
"columns": {
"userId": {
"name": "userId",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"sandboxId": {
"name": "sandboxId",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {
"users_to_sandboxes_userId_user_id_fk": {
"name": "users_to_sandboxes_userId_user_id_fk",
"tableFrom": "users_to_sandboxes",
"tableTo": "user",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"users_to_sandboxes_sandboxId_sandbox_id_fk": {
"name": "users_to_sandboxes_sandboxId_sandbox_id_fk",
"tableFrom": "users_to_sandboxes",
"tableTo": "sandbox",
"columnsFrom": [
"sandboxId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
} }
}, },
"enums": {}, "enums": {},

View File

@ -5,50 +5,29 @@
{ {
"idx": 0, "idx": 0,
"version": "5", "version": "5",
"when": 1713849093097, "when": 1714540200800,
"tag": "0000_blushing_surge", "tag": "0000_big_rogue",
"breakpoints": true "breakpoints": true
}, },
{ {
"idx": 1, "idx": 1,
"version": "5", "version": "5",
"when": 1713937589365, "when": 1714541190588,
"tag": "0001_magenta_tenebrous", "tag": "0001_empty_black_knight",
"breakpoints": true "breakpoints": true
}, },
{ {
"idx": 2, "idx": 2,
"version": "5", "version": "5",
"when": 1714247208074, "when": 1714541209173,
"tag": "0002_rare_beyonder", "tag": "0002_sour_ego",
"breakpoints": true "breakpoints": true
}, },
{ {
"idx": 3, "idx": 3,
"version": "5", "version": "5",
"when": 1714247272878, "when": 1714541233589,
"tag": "0003_silky_talos", "tag": "0003_pale_overlord",
"breakpoints": true
},
{
"idx": 4,
"version": "5",
"when": 1714535843677,
"tag": "0004_curved_shadow_king",
"breakpoints": true
},
{
"idx": 5,
"version": "5",
"when": 1714536021138,
"tag": "0005_light_komodo",
"breakpoints": true
},
{
"idx": 6,
"version": "5",
"when": 1714536446137,
"tag": "0006_clear_blue_shield",
"breakpoints": true "breakpoints": true
} }
] ]

View File

@ -3,7 +3,7 @@ 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 } from "./schema"; import { user, sandbox, usersToSandboxes } from "./schema";
import * as schema from "./schema"; import * as schema from "./schema";
import { eq } from "drizzle-orm"; import { eq } from "drizzle-orm";
@ -88,6 +88,24 @@ export default {
console.log(method); console.log(method);
return methodNotAllowed; return methodNotAllowed;
} }
} else if (path === "/api/sandbox/share" && method === "POST") {
const shareSchema = z.object({
sandboxId: z.string(),
email: z.string(),
});
const body = await request.json();
const { sandboxId, email } = shareSchema.parse(body);
const user = await db.query.user.findFirst({
where: (user, { eq }) => eq(user.email, email),
});
if (!user) return invalidRequest;
await db.insert(usersToSandboxes).values({ userId: user.id, sandboxId }).get();
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;
@ -98,6 +116,7 @@ export default {
where: (user, { eq }) => eq(user.id, id), where: (user, { eq }) => eq(user.id, id),
with: { with: {
sandbox: true, sandbox: true,
usersToSandboxes: true,
}, },
}); });
return json(res ?? {}); return json(res ?? {});

View File

@ -9,17 +9,14 @@ export const user = sqliteTable("user", {
.unique(), .unique(),
name: text("name").notNull(), name: text("name").notNull(),
email: text("email").notNull(), email: text("email").notNull(),
image: text("image"),
}); });
export type User = typeof user.$inferSelect; export type User = typeof user.$inferSelect;
export const userRelations = relations(user, ({ many }) => ({ export const userRelations = relations(user, ({ many }) => ({
sandbox: many(sandbox, { sandbox: many(sandbox),
relationName: "author", usersToSandboxes: many(usersToSandboxes),
}),
sharedSandbox: many(sandbox, {
relationName: "sharedTo",
}),
})); }));
export const sandbox = sqliteTable("sandbox", { export const sandbox = sqliteTable("sandbox", {
@ -41,18 +38,15 @@ export const sandboxRelations = relations(sandbox, ({ one, many }) => ({
author: one(user, { author: one(user, {
fields: [sandbox.userId], fields: [sandbox.userId],
references: [user.id], references: [user.id],
relationName: "sandbox",
}),
sharedTo: many(user, {
relationName: "sharedSandbox",
}), }),
usersToSandboxes: many(usersToSandboxes),
})); }));
export const usersToSandboxes = sqliteTable("users_to_sandboxes", { export const usersToSandboxes = sqliteTable("users_to_sandboxes", {
userId: integer("userId") userId: text("userId")
.notNull() .notNull()
.references(() => user.id), .references(() => user.id),
sandboxId: integer("sandboxId") sandboxId: text("sandboxId")
.notNull() .notNull()
.references(() => sandbox.id), .references(() => sandbox.id),
}); });

View File

@ -31,6 +31,7 @@ export default async function AppAuthLayout({
console.log(res) console.log(res)
} else { } else {
// user already exists in db // user already exists in db
console.log("user exists already.", dbUserJSON)
} }
return <>{children}</> return <>{children}</>

View File

@ -30,10 +30,12 @@ import {
SelectValue, SelectValue,
} from "@/components/ui/select" } from "@/components/ui/select"
import { Loader2, UserPlus, X } from "lucide-react" import { Loader2, UserPlus, X } from "lucide-react"
import { useState } from "react" import { useState, useTransition } from "react"
import { Sandbox } from "@/lib/types" import { Sandbox } from "@/lib/types"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
import Avatar from "@/components/ui/avatar" import Avatar from "@/components/ui/avatar"
import { shareSandbox } from "@/lib/actions"
import { toast } from "sonner"
const formSchema = z.object({ const formSchema = z.object({
email: z.string().email(), email: z.string().email(),
@ -64,6 +66,14 @@ export default function ShareSandboxModal({
// const id = await createSandbox(sandboxData) // const id = await createSandbox(sandboxData)
console.log(values) console.log(values)
setLoading(true)
const res = await shareSandbox(data.id, values.email)
if (!res) {
toast.error("Failed to share.")
}
setLoading(false)
} }
return ( return (

View File

@ -42,3 +42,20 @@ export async function deleteSandbox(id: string) {
revalidatePath("/dashboard") revalidatePath("/dashboard")
} }
export async function shareSandbox(sandboxId: string, email: string) {
try {
const res = await fetch("http://localhost:8787/api/sandbox/share", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ sandboxId, email }),
})
revalidatePath(`/code/${sandboxId}`)
return true
} catch (err) {
return false
}
}