Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add onboarding #175

Merged
merged 14 commits into from
Jan 8, 2025
Merged
5 changes: 5 additions & 0 deletions apps/api/app/utils/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { customAlphabet } from "nanoid";
export const nanoid = customAlphabet(
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
7,
);
91 changes: 91 additions & 0 deletions apps/api/app/v1/[[...route]]/project.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { zValidator } from "@hono/zod-validator";
import { prisma } from "@plura/db";
import { Hono } from "hono";
import { projectSchema } from "@repo/types";
import { auth } from "@plura/auth";
import { cache } from "@plura/cache";
import { nanoid } from "nanoid";

const CACHE_EXPIRY = 300;
const app = new Hono()
.get("/workspace/:workspaceId", async (c) => {
const session = await auth.api.getSession({
headers: c.req.raw.headers,
});
if (!session) {
return c.json({ message: "Unauthorized", status: 401 }, 401);
}
const workspaceId = c.req.param("workspaceId");
if (!workspaceId) {
return c.json({ message: "Missing workspace id", status: 400 }, 400);
}
try {
const projects = await prisma.project.findMany({
where: {
workspaceId: workspaceId,
},
orderBy: {
createdAt: "asc",
},
});
return c.json(projects[0], 200);
} catch (error) {
return c.json({ message: "Error fetching projects", status: 400 }, 400);
}
})
.post("/", zValidator("json", projectSchema), async (c) => {
const session = await auth.api.getSession({
headers: c.req.raw.headers,
});
if (!session?.user.id) {
return c.json({ message: "unauthorized", status: 401 }, 401);
}
const body = c.req.valid("json");
try {
const project = await prisma.project.create({
data: {
name: body.name,
ownerId: session.user.id,
slug: nanoid(),
workspaceId: body.workspaceId,
},
});
return c.json({ project }, 200);
} catch (error) {
console.log(error);
}
})
.delete("/:id", async (c) => {
const projectId = c.req.param("id");
if (!projectId) {
return c.json({ message: "Missing project id", status: 400 }, 400);
}

const session = await auth.api.getSession({
headers: c.req.raw.headers,
});
if (!session?.user.id) {
return c.json({ message: "unauthorized", status: 401 }, 401);
}

const existingProject = await prisma.project.findUnique({
where: {
id: projectId,
ownerId: session.user.id,
},
});
if (!existingProject) {
return c.json({ message: "Project not found", status: 404 }, 404);
}

const project = await prisma.project.delete({
where: {
id: projectId,
ownerId: session.user.id,
},
});

return c.json({ deletedProject: project }, 200);
});

export default app;
2 changes: 2 additions & 0 deletions apps/api/app/v1/[[...route]]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import auth from "./auth";
import status from "./status";
import health from "./health";
import user from "./user";
import project from "./project";
import contributors from "./contributors";
import { cors } from "hono/cors";
import workspace from "./workspace";
Expand Down Expand Up @@ -73,6 +74,7 @@ app.route("/auth", auth);
app.route("/user", user);
app.route("/contributors", contributors);
app.route("/workspace", workspace);
app.route("project", project);

const GET = handle(app);
const POST = handle(app);
Expand Down
61 changes: 61 additions & 0 deletions apps/api/app/v1/[[...route]]/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,67 @@ const app = new Hono()
}

return c.json(response, 200);
})
.get("/:id", async (c) => {
const userId = c.req.param("id");
if (!userId) {
return c.json({
message: "User ID is required",
status: 400,
});
}

const cacheKey = `user:${userId}`;
let user: User | null = null;

try {
const cachedData: User | null = await cache.get(cacheKey);
if (cachedData) {
user = cachedData;
console.log("Returned user data from cache (by ID)");
}
} catch (error) {
console.error("Cache parsing error (by ID):", error);
}

if (!user) {
user = await prisma.user.findUnique({
where: {
id: userId,
},
});

if (user) {
console.log("Fetched user data from database (by ID):");
try {
await cache.set(cacheKey, user, { ex: CACHE_EXPIRY });
} catch (cacheError) {
console.error(
"Error storing user data in cache (by ID):",
cacheError,
);
}
}
}

return c.json({ user }, 200);
})
.post("/onboarding-complete", async (c) => {
const session = await auth.api.getSession({
headers: c.req.raw.headers,
});
if (!session?.user.id) {
return c.json({ message: "unauthorized", status: 401 }, 401);
}
const user = await prisma.user.update({
where: {
id: session.user.id,
},
data: {
isOnboarding: true,
},
});
return c.json({ user }, 200);
});

export default app;
22 changes: 13 additions & 9 deletions apps/api/app/v1/[[...route]]/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ import { checkLogin } from "@/app/actions/checkLogin";
import { checkAdmin } from "@/app/actions/checkAdmin";

const CACHE_EXPIRY = 300; // Cache expiry time in seconds
const ENCRYPTION_KEY = new Uint8Array(
JSON.parse(process.env.ENCRYPTION_KEY || "[]"),
);
type Workspace = {
id: string;
name: string;
Expand Down Expand Up @@ -90,6 +87,9 @@ const app = new Hono()
where: {
userId: userId,
},
orderBy: {
createdAt: "asc",
},
});

if (workspaces.length === 0) {
Expand All @@ -104,26 +104,31 @@ const app = new Hono()
}
}

return c.json({ workspaces }, 200);
return c.json(
{ workspace: workspaces, firstWorkspace: workspaces[0] },
200,
);
})
.post("/", zValidator("form", workspaceSchema), async (c) => {
.post("/", zValidator("json", workspaceSchema), async (c) => {
const session = await auth.api.getSession({
headers: c.req.raw.headers,
});
console.log("session", session);
const userId = session?.user.id;
const body = c.req.valid("form");
const body = c.req.valid("json");

if (!body) {
console.log("body");
return c.json({ message: "Missing body", status: 400 }, 400);
}
if (!userId) {
console.log("userId");
return c.json({ message: "Missing user id", status: 400 }, 400);
}
const name = await encrypt(body.name, ENCRYPTION_KEY);

const workspace = await prisma.workspace.create({
data: {
name: name.toString(),
name: body.name,
userId: userId,
},
});
Expand All @@ -135,7 +140,6 @@ const app = new Hono()
);
}

// Invalidate cache for user workspaces
const userWorkspacesCacheKey = `workspaces:user:${userId}`;
try {
await cache.del(userWorkspacesCacheKey);
Expand Down
3 changes: 3 additions & 0 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@
"@upstash/ratelimit": "^2.0.5",
"@upstash/redis": "^1.34.3",
"hono": "^4.6.9",

"nanoid": "^5.0.9",
"next": "15.1.3",

"prisma": "^5.22.0",
"react": "19.0.0-rc-02c0e824-20241028",
"react-dom": "19.0.0-rc-02c0e824-20241028",
Expand Down
18 changes: 8 additions & 10 deletions apps/api/triggers/src/db.status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,14 @@ export const dbStatusTask = schedules.task({
const createPromises = Array.from(
{ length: massOperationsCount },
(_, i) =>
db
.from("triggers")
.insert([
{
id: `mass-${i}`,
name: `Mass Test ${i}`,
email: `mass${i}@test.com`,
email_verified: true,
},
]),
db.from("triggers").insert([
{
id: `mass-${i}`,
name: `Mass Test ${i}`,
email: `mass${i}@test.com`,
email_verified: true,
},
]),
);
await Promise.all(createPromises);
});
Expand Down
Loading