Basic instance stuff

This commit is contained in:
Kevin Puig
2025-09-27 21:01:52 -04:00
parent d1273ca4ec
commit d7aeb2fec8
6 changed files with 162 additions and 4 deletions

View File

@@ -0,0 +1,10 @@
import { createInstance, getAllInstances } from "../services/instanceService";
import { CreateInstanceRequest } from "../validators/instanceValidator";
export async function createInstanceReq(data:CreateInstanceRequest) {
return await createInstance(data);
}
export async function getAllInstancesReq() {
return await getAllInstances();
}

View File

@@ -3,11 +3,13 @@ import { Hono } from "hono";
import userRoutes from "./userRoutes"; import userRoutes from "./userRoutes";
import messageRoutes from "./messageRoutes"; import messageRoutes from "./messageRoutes";
import channelRoutes from "./channelRoutes"; import channelRoutes from "./channelRoutes";
import instanceRoutes from "./instanceRoutes";
const routes = new Hono(); const routes = new Hono();
routes.route("/user", userRoutes); routes.route("/user", userRoutes);
routes.route("/message", messageRoutes); routes.route("/message", messageRoutes);
routes.route("/channel", channelRoutes); routes.route("/channel", channelRoutes);
routes.route("/instance", instanceRoutes);
export default routes; export default routes;

View File

@@ -0,0 +1,63 @@
import { Hono } from "hono";
import { describeRoute, resolver } from "hono-openapi";
import { createInstanceRequestSchema, getAllInstancesResponseSchema } from "../validators/instanceValidator";
import { zValidator } from "@hono/zod-validator";
import { createInstanceReq, getAllInstancesReq } from "../controller/instanceController";
const instanceRoutes = new Hono();
instanceRoutes.post(
"",
describeRoute({
description: "Create instance",
responses: {
200: {
description: "Instance created",
content: {
"application/json": { schema: resolver(createInstanceRequestSchema) }
},
},
400: {
description: "Invalid request",
},
}
}),
zValidator('json', createInstanceRequestSchema),
async (c) => {
const data = await c.req.json();
if (!data) {
return c.json({ error: "could not parse data" }, 400);
}
const instance = await createInstanceReq(data);
return c.json(instance, 201);
}
);
instanceRoutes.get(
"",
describeRoute({
description: "Get all instances",
responses: {
200: {
description: "List of all instances",
content: {
"application/json": { schema: resolver(getAllInstancesResponseSchema) }
},
},
500: {
description: "Server error",
},
}
}),
async (c) => {
const instances = await getAllInstancesReq();
if (instances.success) {
return c.json(instances, 200);
} else {
return c.json({ success: false, error: instances.error || "Failed to fetch instances" }, 500);
}
}
);
export default instanceRoutes;

View File

@@ -0,0 +1,57 @@
import { PrismaClient } from "@prisma/client";
import { CreateInstanceRequest } from "../validators/instanceValidator";
import { getUserCredentials, getUserInformation } from "./userService";
const prisma = new PrismaClient();
export async function createInstance(data: CreateInstanceRequest) {
try {
const creds = await getUserCredentials(data.requestingUserId);
const user = await getUserInformation(data.requestingUserId);
if (!creds
|| creds.token != data.requestingUserToken
|| !user
|| !user.admin) {
return null;
}
const newInstance = await prisma.instance.create({
data: {
name: data.name,
icon: data.icon
}
});
return {
success: true,
data: newInstance
};
} catch (error) {
console.error("Error creating instance:", error);
return {
success: false,
error: "Failed to create instance"
};
}
}
export async function getAllInstances() {
try {
const instances = await prisma.instance.findMany({
orderBy: {
createdAt: 'desc'
}
});
return {
success: true,
data: instances
};
} catch (error) {
console.error("Error fetching instances:", error);
return {
success: false,
error: "Failed to fetch instances"
};
}
}

View File

@@ -256,10 +256,7 @@ export async function getAllUsersFrom(instanceId: string): Promise<
).includes(u.status as any) ).includes(u.status as any)
? (u.status as "online" | "offline" | "dnd" | "idle" | "invis") ? (u.status as "online" | "offline" | "dnd" | "idle" | "invis")
: "offline", : "offline",
role: adminRoles.map((r) => ({ role: adminRoles,
userId: r.userId,
instanceId: r.instanceId,
})),
}; };
}), }),
); );

View File

@@ -0,0 +1,29 @@
import { z } from 'zod';
export const createInstanceRequestSchema = z.object({
name: z.string().min(1, 'Instance name cannot be empty'),
icon: z.url().optional(),
requestingUserId: z.uuidv7(),
requestingUserToken: z.string()
});
export const getAllInstancesResponseSchema = z.object({
success: z.boolean(),
data: z.array(
z.object({
id: z.string(),
name: z.string(),
icon: z.string().nullable(),
createdAt: z.string().refine((val) => !isNaN(Date.parse(val)), {
message: "Invalid date string format"
}),
updatedAt: z.string().refine((val) => !isNaN(Date.parse(val)), {
message: "Invalid date string format"
})
})
).optional(),
error: z.string().optional()
});
export type CreateInstanceRequest = z.infer<typeof createInstanceRequestSchema>;
export type GetAllInstancesResponse = z.infer<typeof getAllInstancesResponseSchema>;