code made pretty

This commit is contained in:
Kevin Puig
2025-09-27 21:42:43 -04:00
parent 11f25ca915
commit c305298927
17 changed files with 1394 additions and 1292 deletions

View File

@@ -1,39 +1,40 @@
import{ import {
createCategory, createCategory,
getCategory, getCategory,
getCategoriesByInstance, getCategoriesByInstance,
updateCategory, updateCategory,
deleteCategory, deleteCategory,
deleteAllCategoriesFromInstance, deleteAllCategoriesFromInstance,
} from "../services/channelService"; } from "../services/channelService";
import{ import {
CreateCategoryInput, CreateCategoryInput,
UpdateCategoryInput, UpdateCategoryInput,
DeleteCategoryInput, DeleteCategoryInput,
DeleteCategoriesByInstanceIdInput DeleteCategoriesByInstanceIdInput,
} from "../validators/categoryValidator"; } from "../validators/categoryValidator";
export async function createNewCategory(data: CreateCategoryInput) { export async function createNewCategory(data: CreateCategoryInput) {
return await createCategory(data); return await createCategory(data);
} }
export async function fetchCategoryData(id: string) { export async function fetchCategoryData(id: string) {
return await getCategory(id); return await getCategory(id);
} }
export async function fetchCategoriesByInstance(instanceId: string) { export async function fetchCategoriesByInstance(instanceId: string) {
return await getCategoriesByInstance(instanceId); return await getCategoriesByInstance(instanceId);
} }
export async function updateExistingCategory(data: UpdateCategoryInput) { export async function updateExistingCategory(data: UpdateCategoryInput) {
return await updateCategory(data); return await updateCategory(data);
} }
export async function deleteExistingCategory(data: DeleteCategoryInput) { export async function deleteExistingCategory(data: DeleteCategoryInput) {
return await deleteCategory(data); return await deleteCategory(data);
} }
export async function deleteAllCategoriesByInstance(data: DeleteCategoriesByInstanceIdInput) { export async function deleteAllCategoriesByInstance(
return await deleteAllCategoriesFromInstance(data); data: DeleteCategoriesByInstanceIdInput,
) {
return await deleteAllCategoriesFromInstance(data);
} }

View File

@@ -1,38 +1,40 @@
import{ import {
createChannel, createChannel,
getChannel, getChannel,
getChannelsByCategory, getChannelsByCategory,
updateChannel, updateChannel,
deleteChannel, deleteChannel,
deleteAllChannelsFromCategory deleteAllChannelsFromCategory,
} from "../services/channelService"; } from "../services/channelService";
import { import {
CreateChannelInput, CreateChannelInput,
UpdateChannelInput, UpdateChannelInput,
DeleteChannelInput, DeleteChannelInput,
DeleteChannelsByCategoryIdInput DeleteChannelsByCategoryIdInput,
} from "../validators/channelValidator"; } from "../validators/channelValidator";
export async function createNewChannel(data: CreateChannelInput) { export async function createNewChannel(data: CreateChannelInput) {
return await createChannel(data); return await createChannel(data);
} }
export async function fetchChannelData(id: string) { export async function fetchChannelData(id: string) {
return await getChannel(id); return await getChannel(id);
} }
export async function fetchChannelsByCategory(categoryId: string) { export async function fetchChannelsByCategory(categoryId: string) {
return await getChannelsByCategory(categoryId); return await getChannelsByCategory(categoryId);
} }
export async function updateExistingChannel(data: UpdateChannelInput) { export async function updateExistingChannel(data: UpdateChannelInput) {
return await updateChannel(data); return await updateChannel(data);
} }
export async function deleteExistingChannel(data: DeleteChannelInput) { export async function deleteExistingChannel(data: DeleteChannelInput) {
return await deleteChannel(data); return await deleteChannel(data);
} }
export async function deleteAllChannelsByCategory(data: DeleteChannelsByCategoryIdInput) { export async function deleteAllChannelsByCategory(
return await deleteAllChannelsFromCategory(data); data: DeleteChannelsByCategoryIdInput,
) {
return await deleteAllChannelsFromCategory(data);
} }

View File

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

View File

@@ -1,25 +1,29 @@
import { getMessageInformation, getMessagesBefore, sendMessageToChannel } from "../services/messageService"; import {
getMessageInformation,
getMessagesBefore,
sendMessageToChannel,
} from "../services/messageService";
export async function fetchMessageData(id:string) { export async function fetchMessageData(id: string) {
return await getMessageInformation(id); return await getMessageInformation(id);
} }
export async function fetchMessagesBefore(date:string, channelId:string) { export async function fetchMessagesBefore(date: string, channelId: string) {
return getMessagesBefore(date, channelId); return getMessagesBefore(date, channelId);
} }
export async function sendMessage( export async function sendMessage(
channelId: string, channelId: string,
userId: string, userId: string,
content: string, content: string,
token: string, token: string,
repliedMessageId: string | null repliedMessageId: string | null,
) { ) {
return await sendMessageToChannel( return await sendMessageToChannel(
channelId, channelId,
userId, userId,
content, content,
token, token,
repliedMessageId repliedMessageId,
); );
} }

View File

@@ -1,297 +1,315 @@
import { import {
createNewCategory, createNewCategory,
fetchCategoryData, fetchCategoryData,
fetchCategoriesByInstance, fetchCategoriesByInstance,
updateExistingCategory, updateExistingCategory,
deleteExistingCategory, deleteExistingCategory,
deleteAllCategoriesByInstance, deleteAllCategoriesByInstance,
} from "../controller/categoryController"; } from "../controller/categoryController";
import { import {
createCategorySchema, createCategorySchema,
getCategorySchema, getCategorySchema,
getCategoriesByInstanceIdSchema, getCategoriesByInstanceIdSchema,
updateCategorySchema, updateCategorySchema,
deleteCategorySchema, deleteCategorySchema,
deleteCategoriesByInstanceIdSchema, deleteCategoriesByInstanceIdSchema,
CreateCategoryInput, CreateCategoryInput,
GetCategoryInput, GetCategoryInput,
GetCategoriesByInstanceIdInput, GetCategoriesByInstanceIdInput,
UpdateCategoryInput, UpdateCategoryInput,
DeleteCategoryInput, DeleteCategoryInput,
DeleteCategoriesByInstanceIdInput, DeleteCategoriesByInstanceIdInput,
} from "../validators/categoryValidator"; } from "../validators/categoryValidator";
import { zValidator } from "@hono/zod-validator"; import { zValidator } from "@hono/zod-validator";
import { Hono } from "hono"; import { Hono } from "hono";
import { describeRoute, resolver } from "hono-openapi"; import { describeRoute, resolver } from "hono-openapi";
const categoryRoutes = new Hono() const categoryRoutes = new Hono();
// Create a new category // Create a new category
categoryRoutes.post( categoryRoutes.post(
"/", "/",
describeRoute({ describeRoute({
description: "Create a new category", description: "Create a new category",
responses: { responses: {
200: { 200: {
description: "Success creating category", description: "Success creating category",
content: { content: {
"application/json": { schema: resolver(createCategorySchema) }, "application/json": { schema: resolver(createCategorySchema) },
},
},
400: {
description: "Bad Request - Invalid input data",
content: {
"application/json": { schema: resolver(createCategorySchema)},
},
},
401: {
description: "Unauthorized - Admin access required",
content: {
"application/json": { schema: resolver(createCategorySchema)},
},
},
404: {
description: "User Id not found",
content: {
"application/json": { schema: resolver(createCategorySchema)},
},
},
}, },
}), },
zValidator("json", createCategorySchema), 400: {
async (c) => { description: "Bad Request - Invalid input data",
const data = c.req.valid("json") as CreateCategoryInput; content: {
const categoryData = await createNewCategory(data); "application/json": { schema: resolver(createCategorySchema) },
if (categoryData) { },
return c.json(categoryData); },
} else { 401: {
return c.json({ error: "Failed to create category" }, 400); description: "Unauthorized - Admin access required",
} content: {
"application/json": { schema: resolver(createCategorySchema) },
},
},
404: {
description: "User Id not found",
content: {
"application/json": { schema: resolver(createCategorySchema) },
},
},
},
}),
zValidator("json", createCategorySchema),
async (c) => {
const data = c.req.valid("json") as CreateCategoryInput;
const categoryData = await createNewCategory(data);
if (categoryData) {
return c.json(categoryData);
} else {
return c.json({ error: "Failed to create category" }, 400);
} }
) },
);
// Get a category by ID // Get a category by ID
categoryRoutes.get( categoryRoutes.get(
"/:id", "/:id",
describeRoute({ describeRoute({
description: "Get category by id", description: "Get category by id",
responses: { responses: {
200: { 200: {
description: "Success getting category", description: "Success getting category",
content: { content: {
"application/json": { schema: resolver(getCategorySchema) }, "application/json": { schema: resolver(getCategorySchema) },
},
},
404: {
description: "Category id not found",
content: {
"application/json": { schema: resolver(getCategorySchema) },
},
},
}, },
}), },
async (c) => { 404: {
const id = c.req.param("id"); description: "Category id not found",
const categoryData = await fetchCategoryData(id); content: {
if (categoryData) { "application/json": { schema: resolver(getCategorySchema) },
return c.json(categoryData); },
} else { },
return c.json({ error: "Category not found" }, 404); },
} }),
async (c) => {
const id = c.req.param("id");
const categoryData = await fetchCategoryData(id);
if (categoryData) {
return c.json(categoryData);
} else {
return c.json({ error: "Category not found" }, 404);
} }
},
); );
// Get all categories by instance ID // Get all categories by instance ID
categoryRoutes.get( categoryRoutes.get(
"/instance/:instanceId", "/instance/:instanceId",
describeRoute({ describeRoute({
description: "Get all categories by instance id", description: "Get all categories by instance id",
responses: { responses: {
200: { 200: {
description: "Success getting all categories in instance", description: "Success getting all categories in instance",
content: { content: {
"application/json": { schema: resolver(getCategoriesByInstanceIdSchema) }, "application/json": {
}, schema: resolver(getCategoriesByInstanceIdSchema),
}, },
400: {
description: "Bad Request - Missing instance ID",
content: {
"application/json": { schema: resolver(getCategoriesByInstanceIdSchema) },
},
},
}, },
}), },
async (c) => { 400: {
const instanceId = c.req.param("instanceId"); description: "Bad Request - Missing instance ID",
if (!instanceId) { content: {
return c.json({ error: "No instance id provided" }, 400); "application/json": {
} schema: resolver(getCategoriesByInstanceIdSchema),
},
const categoryData = await fetchCategoriesByInstance(instanceId); },
if (categoryData) { },
return c.json(categoryData); },
} else { }),
return c.json({ error: "Error getting all categories from instance" }, 500); async (c) => {
} const instanceId = c.req.param("instanceId");
if (!instanceId) {
return c.json({ error: "No instance id provided" }, 400);
} }
const categoryData = await fetchCategoriesByInstance(instanceId);
if (categoryData) {
return c.json(categoryData);
} else {
return c.json(
{ error: "Error getting all categories from instance" },
500,
);
}
},
); );
// Update a category // Update a category
categoryRoutes.put( categoryRoutes.put(
"/:id", "/:id",
describeRoute({ describeRoute({
description: "Update an existing category", description: "Update an existing category",
responses: { responses: {
200: { 200: {
description: "Success updating category", description: "Success updating category",
content: { content: {
"application/json": { schema: resolver(updateCategorySchema) }, "application/json": { schema: resolver(updateCategorySchema) },
},
},
400: {
description: "Bad Request - Invalid input data",
content: {
"application/json": { schema: resolver(updateCategorySchema)},
},
},
401: {
description: "Unauthorized - Admin access required",
content: {
"application/json": { schema: resolver(updateCategorySchema)},
},
},
404: {
description: "Category id or User Id not found",
content: {
"application/json": { schema: resolver(updateCategorySchema)},
},
},
}, },
}), },
zValidator("json", updateCategorySchema), 400: {
async (c) => { description: "Bad Request - Invalid input data",
const id = c.req.param("id"); content: {
const data = c.req.valid("json") as UpdateCategoryInput; "application/json": { schema: resolver(updateCategorySchema) },
},
},
401: {
description: "Unauthorized - Admin access required",
content: {
"application/json": { schema: resolver(updateCategorySchema) },
},
},
404: {
description: "Category id or User Id not found",
content: {
"application/json": { schema: resolver(updateCategorySchema) },
},
},
},
}),
zValidator("json", updateCategorySchema),
async (c) => {
const id = c.req.param("id");
const data = c.req.valid("json") as UpdateCategoryInput;
// Ensure the ID in the path matches the one in the body // Ensure the ID in the path matches the one in the body
if (data.id && data.id !== id) { if (data.id && data.id !== id) {
return c.json({ error: "ID in path does not match ID in body" }, 400); return c.json({ error: "ID in path does not match ID in body" }, 400);
}
// Set ID from path if not in body
if (!data.id) {
data.id = id;
}
const categoryData = await updateExistingCategory(data);
if (categoryData) {
return c.json(categoryData);
} else {
return c.json({ error: "Failed to update category" }, 400);
}
} }
// Set ID from path if not in body
if (!data.id) {
data.id = id;
}
const categoryData = await updateExistingCategory(data);
if (categoryData) {
return c.json(categoryData);
} else {
return c.json({ error: "Failed to update category" }, 400);
}
},
); );
// Delete a specific category // Delete a specific category
categoryRoutes.delete( categoryRoutes.delete(
"/:id", "/:id",
describeRoute({ describeRoute({
description: "Delete an existing category", description: "Delete an existing category",
responses: { responses: {
200: { 200: {
description: "Success deleting category", description: "Success deleting category",
content: { content: {
"application/json": { schema: resolver(deleteCategorySchema) }, "application/json": { schema: resolver(deleteCategorySchema) },
},
},
400: {
description: "Bad Request - Invalid input data",
content: {
"application/json": { schema: resolver(deleteCategorySchema)},
},
},
401: {
description: "Unauthorized - Admin access required",
content: {
"application/json": { schema: resolver(deleteCategorySchema)},
},
},
404: {
description: "Category id or User Id not found",
content: {
"application/json": { schema: resolver(deleteCategorySchema)},
},
},
}, },
}), },
zValidator("json", deleteCategorySchema), 400: {
async (c) => { description: "Bad Request - Invalid input data",
const id = c.req.param("id"); content: {
const data = c.req.valid("json") as DeleteCategoryInput; "application/json": { schema: resolver(deleteCategorySchema) },
},
},
401: {
description: "Unauthorized - Admin access required",
content: {
"application/json": { schema: resolver(deleteCategorySchema) },
},
},
404: {
description: "Category id or User Id not found",
content: {
"application/json": { schema: resolver(deleteCategorySchema) },
},
},
},
}),
zValidator("json", deleteCategorySchema),
async (c) => {
const id = c.req.param("id");
const data = c.req.valid("json") as DeleteCategoryInput;
// Ensure the ID in the path matches the one in the body // Ensure the ID in the path matches the one in the body
if (data.id !== id) { if (data.id !== id) {
return c.json({ error: "ID in path does not match ID in body" }, 400); return c.json({ error: "ID in path does not match ID in body" }, 400);
}
const categoryData = await deleteExistingCategory(data);
if (categoryData) {
return c.json(categoryData);
} else {
return c.json({ error: "Failed to delete category" }, 400);
}
} }
)
const categoryData = await deleteExistingCategory(data);
if (categoryData) {
return c.json(categoryData);
} else {
return c.json({ error: "Failed to delete category" }, 400);
}
},
);
// Delete all categories by instance ID // Delete all categories by instance ID
categoryRoutes.delete( categoryRoutes.delete(
"/instance/:instanceId", "/instance/:instanceId",
describeRoute({ describeRoute({
description: "Delete all categories by instance id", description: "Delete all categories by instance id",
responses: { responses: {
200: { 200: {
description: "Success deleting all categories in instance", description: "Success deleting all categories in instance",
content: { content: {
"application/json": { schema: resolver(deleteCategoriesByInstanceIdSchema) }, "application/json": {
}, schema: resolver(deleteCategoriesByInstanceIdSchema),
}, },
400: {
description: "Bad Request - Invalid input data",
content: {
"application/json": { schema: resolver(deleteCategoriesByInstanceIdSchema)},
},
},
401: {
description: "Unauthorized - Admin access required",
content: {
"application/json": { schema: resolver(deleteCategoriesByInstanceIdSchema)},
},
},
404: {
description: "Instance id or User Id not found",
content: {
"application/json": { schema: resolver(deleteCategoriesByInstanceIdSchema)},
},
},
}, },
}), },
zValidator("json", deleteCategoriesByInstanceIdSchema), 400: {
async (c) => { description: "Bad Request - Invalid input data",
const instanceId = c.req.param("instanceId"); content: {
const data = c.req.valid("json") as DeleteCategoriesByInstanceIdInput; "application/json": {
schema: resolver(deleteCategoriesByInstanceIdSchema),
},
},
},
401: {
description: "Unauthorized - Admin access required",
content: {
"application/json": {
schema: resolver(deleteCategoriesByInstanceIdSchema),
},
},
},
404: {
description: "Instance id or User Id not found",
content: {
"application/json": {
schema: resolver(deleteCategoriesByInstanceIdSchema),
},
},
},
},
}),
zValidator("json", deleteCategoriesByInstanceIdSchema),
async (c) => {
const instanceId = c.req.param("instanceId");
const data = c.req.valid("json") as DeleteCategoriesByInstanceIdInput;
// Ensure the instanceId in the path matches the one in the body // Ensure the instanceId in the path matches the one in the body
if (data.instanceId !== instanceId) { if (data.instanceId !== instanceId) {
return c.json({ error: "Instance ID in path does not match Instance ID in body" }, 400); return c.json(
} { error: "Instance ID in path does not match Instance ID in body" },
400,
const categoryData = await deleteAllCategoriesByInstance(data); );
if (categoryData) {
return c.json(categoryData);
} else {
return c.json({ error: "Failed to delete categories" }, 400);
}
} }
)
const categoryData = await deleteAllCategoriesByInstance(data);
if (categoryData) {
return c.json(categoryData);
} else {
return c.json({ error: "Failed to delete categories" }, 400);
}
},
);
export { categoryRoutes }; export { categoryRoutes };

View File

@@ -1,299 +1,313 @@
import { import {
createNewChannel, createNewChannel,
fetchChannelData, fetchChannelData,
fetchChannelsByCategory, fetchChannelsByCategory,
updateExistingChannel, updateExistingChannel,
deleteExistingChannel, deleteExistingChannel,
deleteAllChannelsByCategory, deleteAllChannelsByCategory,
} from "../controller/channelController"; } from "../controller/channelController";
import { import {
createChannelSchema, createChannelSchema,
getChannelSchema, getChannelSchema,
getChannelsByCategoryIdSchema, getChannelsByCategoryIdSchema,
updateChannelSchema, updateChannelSchema,
deleteChannelSchema, deleteChannelSchema,
deleteChannelsByCategoryIdSchema, deleteChannelsByCategoryIdSchema,
CreateChannelInput,
CreateChannelInput, GetChannelInput,
GetChannelInput, GetChannelsByCategoryIdInput,
GetChannelsByCategoryIdInput, UpdateChannelInput,
UpdateChannelInput, DeleteChannelInput,
DeleteChannelInput, DeleteChannelsByCategoryIdInput,
DeleteChannelsByCategoryIdInput,
} from "../validators/channelValidator"; } from "../validators/channelValidator";
import { zValidator } from "@hono/zod-validator"; import { zValidator } from "@hono/zod-validator";
import { Hono } from "hono"; import { Hono } from "hono";
import { describeRoute, resolver } from "hono-openapi"; import { describeRoute, resolver } from "hono-openapi";
const channelRoutes = new Hono() const channelRoutes = new Hono();
// Create a new channel // Create a new channel
channelRoutes.post( channelRoutes.post(
"/", "/",
describeRoute({ describeRoute({
description: "Create a new channel", description: "Create a new channel",
responses: { responses: {
200: { 200: {
description: "Success creating channel", description: "Success creating channel",
content: { content: {
"application/json": { schema: resolver(createChannelSchema) }, "application/json": { schema: resolver(createChannelSchema) },
},
},
400: {
description: "Bad Request - Invalid input data",
content: {
"application/json": { schema: resolver(createChannelSchema)},
},
},
401: {
description: "Unauthorized - Admin access required",
content: {
"application/json": { schema: resolver(createChannelSchema)},
},
},
404: {
description: "User Id not found",
content: {
"application/json": { schema: resolver(createChannelSchema)},
},
},
}, },
}), },
zValidator("json", createChannelSchema), 400: {
async (c) => { description: "Bad Request - Invalid input data",
const data = c.req.valid("json") as CreateChannelInput; content: {
const channelData = await createNewChannel(data); "application/json": { schema: resolver(createChannelSchema) },
if (channelData) { },
return c.json(channelData); },
} else { 401: {
return c.json({ error: "Failed to create channel" }, 400); description: "Unauthorized - Admin access required",
} content: {
"application/json": { schema: resolver(createChannelSchema) },
},
},
404: {
description: "User Id not found",
content: {
"application/json": { schema: resolver(createChannelSchema) },
},
},
},
}),
zValidator("json", createChannelSchema),
async (c) => {
const data = c.req.valid("json") as CreateChannelInput;
const channelData = await createNewChannel(data);
if (channelData) {
return c.json(channelData);
} else {
return c.json({ error: "Failed to create channel" }, 400);
} }
) },
);
// Get a channel by ID // Get a channel by ID
channelRoutes.get( channelRoutes.get(
"/:id", "/:id",
describeRoute({ describeRoute({
description: "Get channel by id", description: "Get channel by id",
responses: { responses: {
200: { 200: {
description: "Success getting channel", description: "Success getting channel",
content: { content: {
"application/json": { schema: resolver(getChannelSchema) }, "application/json": { schema: resolver(getChannelSchema) },
},
},
404: {
description: "Channel id not found",
content: {
"application/json": { schema: resolver(getChannelSchema) },
},
},
}, },
}), },
async (c) => { 404: {
const id = c.req.param("id"); description: "Channel id not found",
const channelData = await fetchChannelData(id); content: {
if (channelData) { "application/json": { schema: resolver(getChannelSchema) },
return c.json(channelData); },
} else { },
return c.json({ error: "Channel not found" }, 404); },
} }),
async (c) => {
const id = c.req.param("id");
const channelData = await fetchChannelData(id);
if (channelData) {
return c.json(channelData);
} else {
return c.json({ error: "Channel not found" }, 404);
} }
},
); );
// Get all channels by category ID // Get all channels by category ID
channelRoutes.get( channelRoutes.get(
"/category/:categoryId", "/category/:categoryId",
describeRoute({ describeRoute({
description: "Get all channels by category id", description: "Get all channels by category id",
responses: { responses: {
200: { 200: {
description: "Success getting all channels in category", description: "Success getting all channels in category",
content: { content: {
"application/json": { schema: resolver(getChannelsByCategoryIdSchema) }, "application/json": {
}, schema: resolver(getChannelsByCategoryIdSchema),
}, },
400: {
description: "Bad Request - Missing category ID",
content: {
"application/json": { schema: resolver(getChannelsByCategoryIdSchema) },
},
},
}, },
}), },
async (c) => { 400: {
const categoryId = c.req.param("categoryId"); description: "Bad Request - Missing category ID",
if (!categoryId) { content: {
return c.json({ error: "No category id provided" }, 400); "application/json": {
} schema: resolver(getChannelsByCategoryIdSchema),
},
const channels = await fetchChannelsByCategory(categoryId); },
if (channels) { },
return c.json(channels); },
} else { }),
return c.json({ error: "Error getting channels from category" }, 500); async (c) => {
} const categoryId = c.req.param("categoryId");
if (!categoryId) {
return c.json({ error: "No category id provided" }, 400);
} }
const channels = await fetchChannelsByCategory(categoryId);
if (channels) {
return c.json(channels);
} else {
return c.json({ error: "Error getting channels from category" }, 500);
}
},
); );
// Update a channel // Update a channel
channelRoutes.put( channelRoutes.put(
"/:id", "/:id",
describeRoute({ describeRoute({
description: "Update an existing channel", description: "Update an existing channel",
responses: { responses: {
200: { 200: {
description: "Success updating channel", description: "Success updating channel",
content: { content: {
"application/json": { schema: resolver(updateChannelSchema) }, "application/json": { schema: resolver(updateChannelSchema) },
},
},
400: {
description: "Bad Request - Invalid input data",
content: {
"application/json": { schema: resolver(updateChannelSchema)},
},
},
401: {
description: "Unauthorized - Admin access required",
content: {
"application/json": { schema: resolver(updateChannelSchema)},
},
},
404: {
description: "Channel id or User Id not found",
content: {
"application/json": { schema: resolver(updateChannelSchema)},
},
},
}, },
}), },
zValidator("json", updateChannelSchema), 400: {
async (c) => { description: "Bad Request - Invalid input data",
const id = c.req.param("id"); content: {
const data = c.req.valid("json") as UpdateChannelInput; "application/json": { schema: resolver(updateChannelSchema) },
},
},
401: {
description: "Unauthorized - Admin access required",
content: {
"application/json": { schema: resolver(updateChannelSchema) },
},
},
404: {
description: "Channel id or User Id not found",
content: {
"application/json": { schema: resolver(updateChannelSchema) },
},
},
},
}),
zValidator("json", updateChannelSchema),
async (c) => {
const id = c.req.param("id");
const data = c.req.valid("json") as UpdateChannelInput;
// Ensure the ID in the path matches the one in the body // Ensure the ID in the path matches the one in the body
if (data.id && data.id !== id) { if (data.id && data.id !== id) {
return c.json({ error: "ID in path does not match ID in body" }, 400); return c.json({ error: "ID in path does not match ID in body" }, 400);
}
// Set ID from path if not in body
if (!data.id) {
data.id = id;
}
const result = await updateExistingChannel(data);
if (result) {
return c.json(result);
} else {
return c.json({ error: "Failed to update channel" }, 400);
}
} }
// Set ID from path if not in body
if (!data.id) {
data.id = id;
}
const result = await updateExistingChannel(data);
if (result) {
return c.json(result);
} else {
return c.json({ error: "Failed to update channel" }, 400);
}
},
); );
// Delete a specific channel // Delete a specific channel
channelRoutes.delete( channelRoutes.delete(
"/:id", "/:id",
describeRoute({ describeRoute({
description: "Delete an existing channel", description: "Delete an existing channel",
responses: { responses: {
200: { 200: {
description: "Success deleting channel", description: "Success deleting channel",
content: { content: {
"application/json": { schema: resolver(deleteChannelSchema) }, "application/json": { schema: resolver(deleteChannelSchema) },
},
},
400: {
description: "Bad Request - Invalid input data",
content: {
"application/json": { schema: resolver(deleteChannelSchema)},
},
},
401: {
description: "Unauthorized - Admin access required",
content: {
"application/json": { schema: resolver(deleteChannelSchema)},
},
},
404: {
description: "Channel id or User Id not found",
content: {
"application/json": { schema: resolver(deleteChannelSchema)},
},
},
}, },
}), },
zValidator("json", deleteChannelSchema), 400: {
async (c) => { description: "Bad Request - Invalid input data",
const id = c.req.param("id"); content: {
const data = c.req.valid("json") as DeleteChannelInput; "application/json": { schema: resolver(deleteChannelSchema) },
},
},
401: {
description: "Unauthorized - Admin access required",
content: {
"application/json": { schema: resolver(deleteChannelSchema) },
},
},
404: {
description: "Channel id or User Id not found",
content: {
"application/json": { schema: resolver(deleteChannelSchema) },
},
},
},
}),
zValidator("json", deleteChannelSchema),
async (c) => {
const id = c.req.param("id");
const data = c.req.valid("json") as DeleteChannelInput;
// Ensure the ID in the path matches the one in the body // Ensure the ID in the path matches the one in the body
if (data.id !== id) { if (data.id !== id) {
return c.json({ error: "ID in path does not match ID in body" }, 400); return c.json({ error: "ID in path does not match ID in body" }, 400);
}
const result = await deleteExistingChannel(data);
if (result) {
return c.json({ success: true });
} else {
return c.json({ error: "Failed to delete channel" }, 400);
}
} }
const result = await deleteExistingChannel(data);
if (result) {
return c.json({ success: true });
} else {
return c.json({ error: "Failed to delete channel" }, 400);
}
},
); );
// Delete all channels by category ID // Delete all channels by category ID
channelRoutes.delete( channelRoutes.delete(
"/category/:categoryId", "/category/:categoryId",
describeRoute({ describeRoute({
description: "Delete all channels by category id", description: "Delete all channels by category id",
responses: { responses: {
200: { 200: {
description: "Success deleting all channels in category", description: "Success deleting all channels in category",
content: { content: {
"application/json": { schema: resolver(deleteChannelsByCategoryIdSchema) }, "application/json": {
}, schema: resolver(deleteChannelsByCategoryIdSchema),
}, },
400: {
description: "Bad Request - Invalid input data",
content: {
"application/json": { schema: resolver(deleteChannelsByCategoryIdSchema)},
},
},
401: {
description: "Unauthorized - Admin access required",
content: {
"application/json": { schema: resolver(deleteChannelsByCategoryIdSchema)},
},
},
404: {
description: "Category id or User Id not found",
content: {
"application/json": { schema: resolver(deleteChannelsByCategoryIdSchema)},
},
},
}, },
}), },
zValidator("json", deleteChannelsByCategoryIdSchema), 400: {
async (c) => { description: "Bad Request - Invalid input data",
const categoryId = c.req.param("categoryId"); content: {
const data = c.req.valid("json") as DeleteChannelsByCategoryIdInput; "application/json": {
schema: resolver(deleteChannelsByCategoryIdSchema),
},
},
},
401: {
description: "Unauthorized - Admin access required",
content: {
"application/json": {
schema: resolver(deleteChannelsByCategoryIdSchema),
},
},
},
404: {
description: "Category id or User Id not found",
content: {
"application/json": {
schema: resolver(deleteChannelsByCategoryIdSchema),
},
},
},
},
}),
zValidator("json", deleteChannelsByCategoryIdSchema),
async (c) => {
const categoryId = c.req.param("categoryId");
const data = c.req.valid("json") as DeleteChannelsByCategoryIdInput;
// Ensure the categoryId in the path matches the one in the body // Ensure the categoryId in the path matches the one in the body
if (data.categoryId !== categoryId) { if (data.categoryId !== categoryId) {
return c.json({ error: "Category ID in path does not match Category ID in body" }, 400); return c.json(
} { error: "Category ID in path does not match Category ID in body" },
400,
const result = await deleteAllChannelsByCategory(data); );
if (result) {
return c.json({ success: true });
} else {
return c.json({ error: "Failed to delete channels" }, 400);
}
} }
)
const result = await deleteAllChannelsByCategory(data);
if (result) {
return c.json({ success: true });
} else {
return c.json({ error: "Failed to delete channels" }, 400);
}
},
);
export { channelRoutes }; export { channelRoutes };

View File

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

View File

@@ -1,121 +1,146 @@
import { Hono } from "hono"; import { Hono } from "hono";
import { describeResponse, describeRoute, resolver } from "hono-openapi"; import { describeResponse, describeRoute, resolver } from "hono-openapi";
import { getMessageByIdSchema, getMessagesBeforeDate, sendMessageSchema } from "../validators/messageValidator"; import {
getMessageByIdSchema,
getMessagesBeforeDate,
sendMessageSchema,
} from "../validators/messageValidator";
import { zValidator } from "@hono/zod-validator"; import { zValidator } from "@hono/zod-validator";
import { fetchMessageData, fetchMessagesBefore, sendMessage } from "../controller/messageController"; import {
fetchMessageData,
fetchMessagesBefore,
sendMessage,
} from "../controller/messageController";
const messageRoutes = new Hono(); const messageRoutes = new Hono();
messageRoutes.get( messageRoutes.get(
"/:id", "/:id",
describeRoute({ describeRoute({
description: "Get message by id", description: "Get message by id",
responses: { responses: {
200: { 200: {
description: "Success getting message", description: "Success getting message",
content: { content: {
"application/json": { schema: resolver(getMessageByIdSchema) } "application/json": { schema: resolver(getMessageByIdSchema) },
} },
}, },
404: { 404: {
description: "Message id not found", description: "Message id not found",
content: { content: {
"application/json": { schema: resolver(getMessageByIdSchema) } "application/json": { schema: resolver(getMessageByIdSchema) },
} },
} },
} },
}), }),
zValidator("param", getMessageByIdSchema), zValidator("param", getMessageByIdSchema),
async (c) => { async (c) => {
const id = c.req.param("id"); const id = c.req.param("id");
const messageData = await fetchMessageData(id); const messageData = await fetchMessageData(id);
if (messageData) { if (messageData) {
return c.json(messageData, 200); return c.json(messageData, 200);
} else { } else {
return c.json({ error: "Message not found" }, 404); return c.json({ error: "Message not found" }, 404);
}
} }
) },
);
messageRoutes.get( messageRoutes.get(
"", "",
describeRoute({ describeRoute({
description: "Get up to 50 messages prior to given datetime", description: "Get up to 50 messages prior to given datetime",
responses: { responses: {
200: { 200: {
description: "Success getting up to 50 messages", description: "Success getting up to 50 messages",
content: { content: {
"application/json": { schema: resolver(getMessagesBeforeDate) } "application/json": { schema: resolver(getMessagesBeforeDate) },
} },
} },
} },
}), }),
zValidator("query", getMessagesBeforeDate), zValidator("query", getMessagesBeforeDate),
async (c) => { async (c) => {
const date = c.req.query("date"); const date = c.req.query("date");
if (!date) { if (!date) {
return c.json({ error: "date not provided" }, 400); return c.json({ error: "date not provided" }, 400);
}
const channelId = c.req.query("channelId");
if (!channelId) {
return c.json({ error: "channelId not provided" }, 400);
}
const messagesArr = await fetchMessagesBefore(date, channelId);
if (messagesArr) {
return c.json(messagesArr, 200);
} else {
return c.json({ error: "Failed to fetch messages" }, 500);
}
} }
)
const channelId = c.req.query("channelId");
if (!channelId) {
return c.json({ error: "channelId not provided" }, 400);
}
const messagesArr = await fetchMessagesBefore(date, channelId);
if (messagesArr) {
return c.json(messagesArr, 200);
} else {
return c.json({ error: "Failed to fetch messages" }, 500);
}
},
);
messageRoutes.post( messageRoutes.post(
"", "",
describeRoute({ describeRoute({
description: "Send a message to a channel", description: "Send a message to a channel",
responses: { responses: {
201: { 201: {
description: "Message sent successfully", description: "Message sent successfully",
content: { content: {
"application/json": { schema: resolver(sendMessageSchema) } "application/json": { schema: resolver(sendMessageSchema) },
} },
},
401: {
description: "Unauthorized - invalid token or user credentials",
content: {
"application/json": {
schema: {
type: "object",
properties: { error: { type: "string" } },
}, },
401: { },
description: "Unauthorized - invalid token or user credentials", },
content: { },
"application/json": { schema: { type: "object", properties: { error: { type: "string" } } } } 500: {
} description: "Server error",
content: {
"application/json": {
schema: {
type: "object",
properties: { error: { type: "string" } },
}, },
500: { },
description: "Server error", },
content: { },
"application/json": { schema: { type: "object", properties: { error: { type: "string" } } } } },
} }),
} zValidator("json", sendMessageSchema),
} async (c) => {
}), const { channelId, userId, content, token, repliedMessageId } =
zValidator("json", sendMessageSchema), await c.req.json();
async (c) => {
const { channelId, userId, content, token, repliedMessageId } = await c.req.json();
const result = await sendMessage( const result = await sendMessage(
channelId, channelId,
userId, userId,
content, content,
token, token,
repliedMessageId || null repliedMessageId || null,
); );
if (result) { if (result) {
return c.json(result, 201); return c.json(result, 201);
} else { } else {
return c.json({ error: "Failed to send message. Check your credentials and try again." }, 401); return c.json(
} {
error:
"Failed to send message. Check your credentials and try again.",
},
401,
);
} }
) },
);
export default messageRoutes; export default messageRoutes;

View File

@@ -1,450 +1,457 @@
import{ import { Channel, Category } from "@prisma/client";
Channel,
Category
} from '@prisma/client';
import { PrismaClient } from "@prisma/client"; import { PrismaClient } from "@prisma/client";
import { getUserInformation, getUserCredentials } from './userService'; import { getUserInformation, getUserCredentials } from "./userService";
import { import {
CreateChannelInput, CreateChannelInput,
UpdateChannelInput, UpdateChannelInput,
DeleteChannelInput, DeleteChannelInput,
DeleteChannelsByCategoryIdInput DeleteChannelsByCategoryIdInput,
} from '../validators/channelValidator'; } from "../validators/channelValidator";
import{ import {
UpdateCategoryInput, UpdateCategoryInput,
DeleteCategoryInput, DeleteCategoryInput,
DeleteCategoriesByInstanceIdInput, DeleteCategoriesByInstanceIdInput,
CreateCategoryInput CreateCategoryInput,
} from '../validators/categoryValidator'; } from "../validators/categoryValidator";
const prisma = new PrismaClient(); const prisma = new PrismaClient();
export async function createCategory(
data: CreateCategoryInput,
): Promise<Category | null> {
try {
//Confirm if user exists and is admin
const requestingUser = await getUserInformation(data.requestingUserId);
const requestingUserCredentials = await getUserCredentials(
data.requestingUserId,
);
export async function createCategory(data: CreateCategoryInput): Promise<Category | null>{ if (
try{ !requestingUser ||
!requestingUserCredentials ||
//Confirm if user exists and is admin !requestingUser.admin ||
const requestingUser = await getUserInformation(data.requestingUserId); requestingUserCredentials.token == null ||
const requestingUserCredentials = await getUserCredentials( data.requestingUserToken != requestingUserCredentials.token
data.requestingUserId, ) {
) return null;
if (
!requestingUser ||
!requestingUserCredentials ||
!requestingUser.admin ||
requestingUserCredentials.token == null ||
data.requestingUserToken != requestingUserCredentials.token
) {
return null;
}
const newCategory = await prisma.category.create({
data: {
name: data.name,
position: data.position
}
});
if(!newCategory){
throw new Error("could not create category");
}
let curInstance;
if(data.instanceId){
curInstance = await prisma.instance.findUnique({
where: {
id: data.instanceId
},
include: {
Category: true
}
});
if(!curInstance){
throw new Error("could not find instance to add category to");
}
await prisma.category.update({
where: {
id: newCategory.id
},
data: {
instanceId: curInstance.id
}
});
return newCategory;
}
return newCategory;
}catch(err){
console.log("services::channelService::createCategory - ", err);
return null;
} }
const newCategory = await prisma.category.create({
data: {
name: data.name,
position: data.position,
},
});
if (!newCategory) {
throw new Error("could not create category");
}
let curInstance;
if (data.instanceId) {
curInstance = await prisma.instance.findUnique({
where: {
id: data.instanceId,
},
include: {
Category: true,
},
});
if (!curInstance) {
throw new Error("could not find instance to add category to");
}
await prisma.category.update({
where: {
id: newCategory.id,
},
data: {
instanceId: curInstance.id,
},
});
return newCategory;
}
return newCategory;
} catch (err) {
console.log("services::channelService::createCategory - ", err);
return null;
}
} }
export async function getCategory( export async function getCategory(
categoryId: string, categoryId: string,
): Promise<Category | null>{ ): Promise<Category | null> {
try{ try {
const category = await prisma.category.findUnique({ const category = await prisma.category.findUnique({
where: { where: {
id: categoryId id: categoryId,
} },
}); });
if(!category){ if (!category) {
throw new Error("could not find category"); throw new Error("could not find category");
}
return category;
}catch(err){
console.log("services::channelService::getCategory - ", err);
return null;
} }
return category;
} catch (err) {
console.log("services::channelService::getCategory - ", err);
return null;
}
} }
export async function getCategoriesByInstance( export async function getCategoriesByInstance(
instanceId: string instanceId: string,
): Promise<Category[] | null>{ ): Promise<Category[] | null> {
try{ try {
const categories = await prisma.category.findMany({ const categories = await prisma.category.findMany({
where: { where: {
instanceId: instanceId instanceId: instanceId,
}, },
include: { include: {
Channel: true Channel: true,
}, },
orderBy: { orderBy: {
position: 'asc' position: "asc",
} },
}); });
if(!categories){ if (!categories) {
throw new Error("could not find categories for instance"); throw new Error("could not find categories for instance");
}
return categories;
}catch(err){
console.log("services::channelService::getCategoriesByInstance - ", err);
return null;
} }
return categories;
} catch (err) {
console.log("services::channelService::getCategoriesByInstance - ", err);
return null;
}
} }
export async function updateCategory(data: UpdateCategoryInput): Promise<Category | null>{ export async function updateCategory(
try{ data: UpdateCategoryInput,
): Promise<Category | null> {
try {
//Confirm if user exists and is admin
const requestingUser = await getUserInformation(data.requestingUserId);
const requestingUserCredentials = await getUserCredentials(
data.requestingUserId,
);
//Confirm if user exists and is admin if (
const requestingUser = await getUserInformation(data.requestingUserId); !requestingUser ||
const requestingUserCredentials = await getUserCredentials( !requestingUserCredentials ||
data.requestingUserId, !requestingUser.admin ||
) requestingUserCredentials.token == null ||
data.requestingUserToken != requestingUserCredentials.token
if ( ) {
!requestingUser || return null;
!requestingUserCredentials ||
!requestingUser.admin ||
requestingUserCredentials.token == null ||
data.requestingUserToken != requestingUserCredentials.token
) {
return null;
}
const updatedCategory = await prisma.category.update({
where: {
id: data.id
},
data: {
name: data.name,
position: data.position,
Channel: data.channels ? { set: data.channels } : undefined
}
});
if(!updatedCategory){
throw new Error("could not update category");
}
return updatedCategory;
}catch(err){
console.log("services::channelService::updateCategory - ", err);
return null;
} }
const updatedCategory = await prisma.category.update({
where: {
id: data.id,
},
data: {
name: data.name,
position: data.position,
Channel: data.channels ? { set: data.channels } : undefined,
},
});
if (!updatedCategory) {
throw new Error("could not update category");
}
return updatedCategory;
} catch (err) {
console.log("services::channelService::updateCategory - ", err);
return null;
}
} }
export async function deleteCategory(data: DeleteCategoryInput): Promise<boolean | null>{ export async function deleteCategory(
try{ data: DeleteCategoryInput,
): Promise<boolean | null> {
try {
//Confirm if user exists and is admin
const requestingUser = await getUserInformation(data.requestingUserId);
const requestingUserCredentials = await getUserCredentials(
data.requestingUserId,
);
//Confirm if user exists and is admin if (
const requestingUser = await getUserInformation(data.requestingUserId); !requestingUser ||
const requestingUserCredentials = await getUserCredentials( !requestingUserCredentials ||
data.requestingUserId, !requestingUser.admin ||
) requestingUserCredentials.token == null ||
data.requestingUserToken != requestingUserCredentials.token
if ( ) {
!requestingUser || return null;
!requestingUserCredentials ||
!requestingUser.admin ||
requestingUserCredentials.token == null ||
data.requestingUserToken != requestingUserCredentials.token
) {
return null;
}
const deleteAllChannels = await prisma.channel.deleteMany({
where: {
categoryId: data.id
}
});
if(deleteAllChannels.count === 0){
throw new Error("could not delete channels from category");
}
const deletedCategory = await prisma.category.delete({
where: {
id: data.id
}
});
if(!deletedCategory){
throw new Error("could not delete category");
}
return true;
}catch(err){
console.log("services::channelService::deleteCategory - ", err);
return false;
} }
const deleteAllChannels = await prisma.channel.deleteMany({
where: {
categoryId: data.id,
},
});
if (deleteAllChannels.count === 0) {
throw new Error("could not delete channels from category");
}
const deletedCategory = await prisma.category.delete({
where: {
id: data.id,
},
});
if (!deletedCategory) {
throw new Error("could not delete category");
}
return true;
} catch (err) {
console.log("services::channelService::deleteCategory - ", err);
return false;
}
} }
export async function deleteAllCategoriesFromInstance(data: DeleteCategoriesByInstanceIdInput): Promise<boolean | null>{ export async function deleteAllCategoriesFromInstance(
try{ data: DeleteCategoriesByInstanceIdInput,
): Promise<boolean | null> {
try {
//Confirm if user exists and is admin
const requestingUser = await getUserInformation(data.requestingUserId);
const requestingUserCredentials = await getUserCredentials(
data.requestingUserId,
);
//Confirm if user exists and is admin if (
const requestingUser = await getUserInformation(data.requestingUserId); !requestingUser ||
const requestingUserCredentials = await getUserCredentials( !requestingUserCredentials ||
data.requestingUserId, !requestingUser.admin ||
) requestingUserCredentials.token == null ||
data.requestingUserToken != requestingUserCredentials.token
if ( ) {
!requestingUser || return null;
!requestingUserCredentials ||
!requestingUser.admin ||
requestingUserCredentials.token == null ||
data.requestingUserToken != requestingUserCredentials.token
) {
return null;
}
const deletedCategories = await prisma.category.deleteMany({
where: {
instanceId: data.instanceId
}
});
if(deletedCategories.count === 0){
throw new Error("could not delete categories from instance");
}
return true;
}catch(err){
console.log("services::channelService::deleteAllCategoriesFromInstance - ", err);
return false;
} }
const deletedCategories = await prisma.category.deleteMany({
where: {
instanceId: data.instanceId,
},
});
if (deletedCategories.count === 0) {
throw new Error("could not delete categories from instance");
}
return true;
} catch (err) {
console.log(
"services::channelService::deleteAllCategoriesFromInstance - ",
err,
);
return false;
}
} }
export async function createChannel(data: CreateChannelInput): Promise<Channel | null>{ export async function createChannel(
try{ data: CreateChannelInput,
): Promise<Channel | null> {
try {
//Confirm if user exists and is admin
const requestingUser = await getUserInformation(data.requestingUserId);
const requestingUserCredentials = await getUserCredentials(
data.requestingUserId,
);
//Confirm if user exists and is admin if (
const requestingUser = await getUserInformation(data.requestingUserId); !requestingUser ||
const requestingUserCredentials = await getUserCredentials( !requestingUserCredentials ||
data.requestingUserId, !requestingUser.admin ||
) requestingUserCredentials.token == null ||
data.requestingUserToken != requestingUserCredentials.token
if ( ) {
!requestingUser || return null;
!requestingUserCredentials ||
!requestingUser.admin ||
requestingUserCredentials.token == null ||
data.requestingUserToken != requestingUserCredentials.token
) {
return null;
}
const newChannel = await prisma.channel.create({
data: {
type: data.type,
name: data.name,
description: data.description,
categoryId: data.categoryId ? data.categoryId : null
}
});
if(!newChannel){
throw new Error("could not create channel");
}
return newChannel;
}catch(err){
console.log("services::channelService::createChannel - ", err);
return null;
} }
const newChannel = await prisma.channel.create({
data: {
type: data.type,
name: data.name,
description: data.description,
categoryId: data.categoryId ? data.categoryId : null,
},
});
if (!newChannel) {
throw new Error("could not create channel");
}
return newChannel;
} catch (err) {
console.log("services::channelService::createChannel - ", err);
return null;
}
} }
export async function getChannel( export async function getChannel(channelId: string): Promise<Channel | null> {
channelId: string try {
): Promise<Channel | null>{ const channel = await prisma.channel.findUnique({
try{ where: {
const channel = await prisma.channel.findUnique({ id: channelId,
where: { },
id: channelId });
}
});
if(!channel){ if (!channel) {
throw new Error("could not find channel"); throw new Error("could not find channel");
}
return channel;
}catch(err){
console.log("services::channelService::getChannel - ", err);
return null;
} }
return channel;
} catch (err) {
console.log("services::channelService::getChannel - ", err);
return null;
}
} }
export async function getChannelsByCategory( export async function getChannelsByCategory(
categoryId: string categoryId: string,
): Promise<Channel[] | null>{ ): Promise<Channel[] | null> {
try{ try {
const channels = await prisma.channel.findMany({ const channels = await prisma.channel.findMany({
where: { where: {
categoryId: categoryId categoryId: categoryId,
} },
}); });
if(!channels){ if (!channels) {
throw new Error("could not find channels for category"); throw new Error("could not find channels for category");
}
return channels;
}
catch(err){
console.log("services::channelService::getChannelsByCategory - ", err);
return null;
} }
return channels;
} catch (err) {
console.log("services::channelService::getChannelsByCategory - ", err);
return null;
}
} }
export async function updateChannel(data: UpdateChannelInput): Promise<Channel | null>{ export async function updateChannel(
try{ data: UpdateChannelInput,
): Promise<Channel | null> {
try {
//Confirm if user exists and is admin
const requestingUser = await getUserInformation(data.requestingUserId);
const requestingUserCredentials = await getUserCredentials(
data.requestingUserId,
);
//Confirm if user exists and is admin if (
const requestingUser = await getUserInformation(data.requestingUserId); !requestingUser ||
const requestingUserCredentials = await getUserCredentials( !requestingUserCredentials ||
data.requestingUserId, !requestingUser.admin ||
) requestingUserCredentials.token == null ||
data.requestingUserToken != requestingUserCredentials.token
if ( ) {
!requestingUser || return null;
!requestingUserCredentials ||
!requestingUser.admin ||
requestingUserCredentials.token == null ||
data.requestingUserToken != requestingUserCredentials.token
) {
return null;
}
const updatedChannel = await prisma.channel.update({
where: {
id: data.id
},
data: {
name: data.name,
description: data.description,
categoryId: data.categoryId ? data.categoryId : undefined
}
});
if(!updatedChannel){
throw new Error("could not update channel");
}
return updatedChannel;
}catch(err){
console.log("services::channelService::updateChannel - ", err);
return null;
} }
const updatedChannel = await prisma.channel.update({
where: {
id: data.id,
},
data: {
name: data.name,
description: data.description,
categoryId: data.categoryId ? data.categoryId : undefined,
},
});
if (!updatedChannel) {
throw new Error("could not update channel");
}
return updatedChannel;
} catch (err) {
console.log("services::channelService::updateChannel - ", err);
return null;
}
} }
export async function deleteChannel(data: DeleteChannelInput): Promise<boolean | null>{ export async function deleteChannel(
try{ data: DeleteChannelInput,
): Promise<boolean | null> {
try {
//Confirm if user exists and is admin
const requestingUser = await getUserInformation(data.requestingUserId);
const requestingUserCredentials = await getUserCredentials(
data.requestingUserId,
);
//Confirm if user exists and is admin if (
const requestingUser = await getUserInformation(data.requestingUserId); !requestingUser ||
const requestingUserCredentials = await getUserCredentials( !requestingUserCredentials ||
data.requestingUserId, !requestingUser.admin ||
) requestingUserCredentials.token == null ||
data.requestingUserToken != requestingUserCredentials.token
if ( ) {
!requestingUser || return null;
!requestingUserCredentials ||
!requestingUser.admin ||
requestingUserCredentials.token == null ||
data.requestingUserToken != requestingUserCredentials.token
) {
return null;
}
const deletedChannel = await prisma.channel.delete({
where: {
id: data.id
}
});
if(!deletedChannel){
throw new Error("could not delete channel");
}
return true;
}catch(err){
console.log("services::channelService::deleteChannel - ", err);
return false;
} }
const deletedChannel = await prisma.channel.delete({
where: {
id: data.id,
},
});
if (!deletedChannel) {
throw new Error("could not delete channel");
}
return true;
} catch (err) {
console.log("services::channelService::deleteChannel - ", err);
return false;
}
} }
export async function deleteAllChannelsFromCategory(data: DeleteChannelsByCategoryIdInput): Promise<boolean | null> export async function deleteAllChannelsFromCategory(
{ data: DeleteChannelsByCategoryIdInput,
try{ ): Promise<boolean | null> {
//Confirm if user exists and is admin try {
const requestingUser = await getUserInformation(data.requestingUserId); //Confirm if user exists and is admin
const requestingUserCredentials = await getUserCredentials( const requestingUser = await getUserInformation(data.requestingUserId);
data.requestingUserId, const requestingUserCredentials = await getUserCredentials(
) data.requestingUserId,
);
if ( if (
!requestingUser || !requestingUser ||
!requestingUserCredentials || !requestingUserCredentials ||
!requestingUser.admin || !requestingUser.admin ||
requestingUserCredentials.token == null || requestingUserCredentials.token == null ||
data.requestingUserToken != requestingUserCredentials.token data.requestingUserToken != requestingUserCredentials.token
) { ) {
return null; return null;
}
const deletedChannels = await prisma.channel.deleteMany({
where: {
categoryId: data.categoryId
}
});
if(deletedChannels.count === 0){
throw new Error("could not delete channels from category");
}
return true;
}catch(err){
console.log("services::channelService::deleteAllChannelsFromCategory - ", err);
return false;
} }
const deletedChannels = await prisma.channel.deleteMany({
where: {
categoryId: data.categoryId,
},
});
if (deletedChannels.count === 0) {
throw new Error("could not delete channels from category");
}
return true;
} catch (err) {
console.log(
"services::channelService::deleteAllChannelsFromCategory - ",
err,
);
return false;
}
} }

View File

@@ -5,53 +5,55 @@ import { getUserCredentials, getUserInformation } from "./userService";
const prisma = new PrismaClient(); const prisma = new PrismaClient();
export async function createInstance(data: CreateInstanceRequest) { export async function createInstance(data: CreateInstanceRequest) {
try { try {
const creds = await getUserCredentials(data.requestingUserId); const creds = await getUserCredentials(data.requestingUserId);
const user = await getUserInformation(data.requestingUserId); const user = await getUserInformation(data.requestingUserId);
if (!creds if (
|| creds.token != data.requestingUserToken !creds ||
|| !user creds.token != data.requestingUserToken ||
|| !user.admin) { !user ||
return null; !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"
};
} }
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() { export async function getAllInstances() {
try { try {
const instances = await prisma.instance.findMany({ const instances = await prisma.instance.findMany({
orderBy: { orderBy: {
createdAt: 'desc' createdAt: "desc",
} },
}); });
return { return {
success: true, success: true,
data: instances data: instances,
}; };
} catch (error) { } catch (error) {
console.error("Error fetching instances:", error); console.error("Error fetching instances:", error);
return { return {
success: false, success: false,
error: "Failed to fetch instances" error: "Failed to fetch instances",
}; };
} }
} }

View File

@@ -1,16 +1,14 @@
import { import { PrismaClient } from "@prisma/client";
PrismaClient,
} from "@prisma/client";
import { getUserCredentials } from "./userService"; import { getUserCredentials } from "./userService";
const prisma = new PrismaClient(); const prisma = new PrismaClient();
export async function getMessageInformation(id:string): Promise<{ export async function getMessageInformation(id: string): Promise<{
id: string, id: string;
channelId: string, channelId: string;
userId: string, userId: string;
text: string, text: string;
deleted: boolean, deleted: boolean;
replies: null | { replies: null | {
messageId: string; messageId: string;
repliesToId: string; repliesToId: string;
@@ -66,26 +64,28 @@ export async function getMessageInformation(id:string): Promise<{
const errMessage = err as Error; const errMessage = err as Error;
if (errMessage.message === "missing messageId") { if (errMessage.message === "missing messageId") {
console.log("services::actions::getMessageInformation - missing messageId"); console.log(
"services::actions::getMessageInformation - missing messageId",
);
return null; return null;
} }
if (errMessage.message === "could not find message") { if (errMessage.message === "could not find message") {
console.log( console.log(
"services::actions::getMessageInformation - unable to find message" "services::actions::getMessageInformation - unable to find message",
); );
return null; return null;
} }
console.log( console.log(
"services::actions::getMessageInformation - unknown error", "services::actions::getMessageInformation - unknown error",
errMessage errMessage,
); );
return null; return null;
} }
} }
export async function getMessagesBefore(date:string, channelId:string) { export async function getMessagesBefore(date: string, channelId: string) {
try { try {
if (!date || !channelId) { if (!date || !channelId) {
throw new Error("missing date or channelId"); throw new Error("missing date or channelId");
@@ -141,13 +141,15 @@ export async function getMessagesBefore(date:string, channelId:string) {
const errMessage = err as Error; const errMessage = err as Error;
if (errMessage.message === "missing date or channelId") { if (errMessage.message === "missing date or channelId") {
console.log("services::actions::getMessagesBefore - missing date or channelId"); console.log(
"services::actions::getMessagesBefore - missing date or channelId",
);
return null; return null;
} }
console.log( console.log(
"services::actions::getMessagesBefore - unknown error", "services::actions::getMessagesBefore - unknown error",
errMessage errMessage,
); );
return null; return null;
} }

View File

@@ -1,4 +1,3 @@
import { import {
Message, Message,
MessagePing, MessagePing,

View File

@@ -1,55 +1,61 @@
import { z } from 'zod'; import { z } from "zod";
//category validators //category validators
export const createCategorySchema = z.object({ export const createCategorySchema = z.object({
name: z.string().min(1).max(50), name: z.string().min(1).max(50),
position: z.number().min(0), position: z.number().min(0),
instanceId : z.uuidv7().optional(), instanceId: z.uuidv7().optional(),
admin: z.boolean(), admin: z.boolean(),
requestingUserId: z.uuidv7(), requestingUserId: z.uuidv7(),
requestingUserToken: z.uuidv4() requestingUserToken: z.uuidv4(),
}) });
export const getCategorySchema = z.object({ export const getCategorySchema = z.object({
id: z.uuidv7() id: z.uuidv7(),
}) });
export const getCategoriesByInstanceIdSchema = z.object({ export const getCategoriesByInstanceIdSchema = z.object({
instanceId: z.uuidv7() instanceId: z.uuidv7(),
});
})
export const updateCategorySchema = z.object({ export const updateCategorySchema = z.object({
id: z.uuidv7(), id: z.uuidv7(),
name: z.string().min(1).max(50).optional(), name: z.string().min(1).max(50).optional(),
position: z.number().min(0).optional(), position: z.number().min(0).optional(),
channels: z.array(z.object({ channels: z
id: z.string() .array(
})).optional(), z.object({
admin: z.boolean(), id: z.string(),
requestingUserId: z.uuidv7(), }),
requestingUserToken: z.uuidv4() )
}) .optional(),
admin: z.boolean(),
requestingUserId: z.uuidv7(),
requestingUserToken: z.uuidv4(),
});
export const deleteCategorySchema = z.object({ export const deleteCategorySchema = z.object({
id: z.uuidv7(), id: z.uuidv7(),
admin: z.boolean(), admin: z.boolean(),
requestingUserId: z.uuidv7(), requestingUserId: z.uuidv7(),
requestingUserToken: z.uuidv4() requestingUserToken: z.uuidv4(),
}) });
export const deleteCategoriesByInstanceIdSchema = z.object({ export const deleteCategoriesByInstanceIdSchema = z.object({
instanceId: z.uuidv7(), instanceId: z.uuidv7(),
admin: z.boolean(), admin: z.boolean(),
requestingUserId: z.uuidv7(), requestingUserId: z.uuidv7(),
requestingUserToken: z.uuidv4() requestingUserToken: z.uuidv4(),
}) });
export type CreateCategoryInput = z.infer<typeof createCategorySchema>;
export type CreateCategoryInput = z.infer<typeof createCategorySchema> export type GetCategoryInput = z.infer<typeof getCategorySchema>;
export type GetCategoryInput = z.infer<typeof getCategorySchema> export type GetCategoriesByInstanceIdInput = z.infer<
export type GetCategoriesByInstanceIdInput = z.infer<typeof getCategoriesByInstanceIdSchema> typeof getCategoriesByInstanceIdSchema
export type UpdateCategoryInput = z.infer<typeof updateCategorySchema> >;
export type DeleteCategoryInput = z.infer<typeof deleteCategorySchema> export type UpdateCategoryInput = z.infer<typeof updateCategorySchema>;
export type DeleteCategoriesByInstanceIdInput = z.infer<typeof deleteCategoriesByInstanceIdSchema> export type DeleteCategoryInput = z.infer<typeof deleteCategorySchema>;
export type DeleteCategoriesByInstanceIdInput = z.infer<
typeof deleteCategoriesByInstanceIdSchema
>;

View File

@@ -3,50 +3,54 @@ import { z } from "zod";
//channel validators //channel validators
export const createChannelSchema = z.object({ export const createChannelSchema = z.object({
type: z.enum(['text', 'voice']), type: z.enum(["text", "voice"]),
name: z.string().min(1).max(50), name: z.string().min(1).max(50),
description: z.string().max(255), description: z.string().max(255),
categoryId: z.uuidv7().optional(), categoryId: z.uuidv7().optional(),
admin: z.boolean(), admin: z.boolean(),
requestingUserId: z.uuidv7(), requestingUserId: z.uuidv7(),
requestingUserToken: z.uuidv4() requestingUserToken: z.uuidv4(),
}) });
export const getChannelSchema = z.object({ export const getChannelSchema = z.object({
id: z.uuidv7() id: z.uuidv7(),
}) });
export const getChannelsByCategoryIdSchema = z.object({ export const getChannelsByCategoryIdSchema = z.object({
categoryId: z.uuidv7() categoryId: z.uuidv7(),
}) });
export const updateChannelSchema = z.object({ export const updateChannelSchema = z.object({
id: z.uuidv7(), id: z.uuidv7(),
name: z.string().min(1).max(50).optional(), name: z.string().min(1).max(50).optional(),
description: z.string().max(255).optional(), description: z.string().max(255).optional(),
categoryId: z.uuidv7().optional(), categoryId: z.uuidv7().optional(),
admin: z.boolean(), admin: z.boolean(),
requestingUserId: z.uuidv7(), requestingUserId: z.uuidv7(),
requestingUserToken: z.uuidv4() requestingUserToken: z.uuidv4(),
}) });
export const deleteChannelSchema = z.object({ export const deleteChannelSchema = z.object({
id: z.uuidv7(), id: z.uuidv7(),
admin: z.boolean(), admin: z.boolean(),
requestingUserId: z.uuidv7(), requestingUserId: z.uuidv7(),
requestingUserToken: z.uuidv4() requestingUserToken: z.uuidv4(),
}) });
export const deleteChannelsByCategoryIdSchema = z.object({ export const deleteChannelsByCategoryIdSchema = z.object({
categoryId: z.uuidv7(), categoryId: z.uuidv7(),
admin: z.boolean(), admin: z.boolean(),
requestingUserId: z.uuidv7(), requestingUserId: z.uuidv7(),
requestingUserToken: z.uuidv4() requestingUserToken: z.uuidv4(),
}) });
export type CreateChannelInput = z.infer<typeof createChannelSchema> export type CreateChannelInput = z.infer<typeof createChannelSchema>;
export type GetChannelInput = z.infer<typeof getChannelSchema> export type GetChannelInput = z.infer<typeof getChannelSchema>;
export type GetChannelsByCategoryIdInput = z.infer<typeof getChannelsByCategoryIdSchema> export type GetChannelsByCategoryIdInput = z.infer<
export type UpdateChannelInput = z.infer<typeof updateChannelSchema> typeof getChannelsByCategoryIdSchema
export type DeleteChannelInput = z.infer<typeof deleteChannelSchema> >;
export type DeleteChannelsByCategoryIdInput = z.infer<typeof deleteChannelsByCategoryIdSchema> export type UpdateChannelInput = z.infer<typeof updateChannelSchema>;
export type DeleteChannelInput = z.infer<typeof deleteChannelSchema>;
export type DeleteChannelsByCategoryIdInput = z.infer<
typeof deleteChannelsByCategoryIdSchema
>;

View File

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

View File

@@ -1,20 +1,20 @@
import { z } from "zod"; import { z } from "zod";
export const getMessageByIdSchema = z.object({ export const getMessageByIdSchema = z.object({
id: z.uuidv7() id: z.uuidv7(),
}) });
export const getMessagesBeforeDate = z.object({ export const getMessagesBeforeDate = z.object({
date: z.string().refine((val) => !isNaN(Date.parse(val)), { date: z.string().refine((val) => !isNaN(Date.parse(val)), {
message: "Invalid date string format" message: "Invalid date string format",
}), }),
channelId: z.uuidv7() channelId: z.uuidv7(),
}) });
export const sendMessageSchema = z.object({ export const sendMessageSchema = z.object({
channelId: z.uuidv7(), channelId: z.uuidv7(),
userId: z.uuidv7(), userId: z.uuidv7(),
content: z.string(), content: z.string(),
token: z.string(), token: z.string(),
repliedMessageId: z.uuidv7().nullable().optional() repliedMessageId: z.uuidv7().nullable().optional(),
}) });

View File

@@ -7,7 +7,7 @@ export const queryUserByIdSchema = z.object({
export const queryAllUsersByInstanceId = z.object({ export const queryAllUsersByInstanceId = z.object({
instanceId: z.uuidv7(), instanceId: z.uuidv7(),
}); });
import { is } from 'zod/v4/locales'; import { is } from "zod/v4/locales";
export const createUserSchema = z.object({ export const createUserSchema = z.object({
username: z.string().min(3).max(30), username: z.string().min(3).max(30),
nickname: z.string().min(1).max(30).optional(), nickname: z.string().min(1).max(30).optional(),