CRUD ops for all but image table

This commit is contained in:
2026-06-28 20:06:01 -05:00
parent 18ee1940b0
commit 58996792da
3 changed files with 106 additions and 17 deletions
+13 -14
View File
@@ -7,8 +7,7 @@ import {
varchar, varchar,
integer, integer,
bigint, bigint,
uniqueIndex, unique,
index,
boolean, boolean,
smallint, smallint,
check check
@@ -35,15 +34,19 @@ export const articles = pgTable("articles", {
id: uuid().notNull().primaryKey().defaultRandom(), id: uuid().notNull().primaryKey().defaultRandom(),
name: varchar({ length: 255 }).notNull(), name: varchar({ length: 255 }).notNull(),
article_status: articleStatusEnum().default("draft"), article_status: articleStatusEnum().notNull().default("draft"),
author_id: uuid().notNull(), author_id: uuid().notNull().references(() => users.id, { onDelete: "cascade" }),
slug: varchar({ length: 511 }).unique().notNull(), slug: varchar({ length: 511 }).unique().notNull(),
summary: varchar({ length: 255 }).notNull(), summary: varchar({ length: 255 }).notNull(),
date_created: timestamp({ mode: "date", withTimezone: true }).defaultNow().notNull(), date_created: timestamp({ mode: "date", withTimezone: true }).defaultNow().notNull(),
last_edit: timestamp({ mode: "date", withTimezone: true }).defaultNow().notNull(), last_edit: timestamp({ mode: "date", withTimezone: true }).defaultNow().notNull(),
date_published: timestamp({ mode: "date", withTimezone: true }), date_published: timestamp({ mode: "date", withTimezone: true }),
}); },
(table) => [{
slugIdx: unique("no_repeat_slugs_per_author")
.on(table.author_id, table.slug)
}]);
export const articleBlocks = pgTable("article_blocks", { export const articleBlocks = pgTable("article_blocks", {
id: uuid().notNull().primaryKey().defaultRandom(), id: uuid().notNull().primaryKey().defaultRandom(),
@@ -55,22 +58,18 @@ export const articleBlocks = pgTable("article_blocks", {
}, },
(table) => [{ (table) => [{
postPositionIdx: uniqueIndex("article_blocks_article_position_idx") postPositionIdx: unique("no_repeat_block_position_per_article")
.on(table.article_id, table.position), .on(table.article_id, table.position)
postIdx: index("article_blocks_article_id_idx")
.on(table.article_id),
}]); }]);
export const images = pgTable("images", { export const images = pgTable("images", {
id: uuid().notNull().primaryKey().defaultRandom(), id: uuid().notNull().primaryKey().defaultRandom(), // Linked in 'content' of articleBlock with type 'image'
bucket: varchar({ length: 63 }).notNull(), bucket: varchar({ length: 63 }).notNull(),
key: varchar({ length: 255 }).notNull(), key: varchar({ length: 255 }).notNull(),
mime_type: varchar({ length: 63 }).notNull(), mime_type: varchar({ length: 63 }).notNull(),
height: integer().notNull(), height: integer().notNull(),
width: integer().notNull(), width: integer().notNull(),
bytes: bigint({ mode: "number" }).notNull(), bytes: bigint({ mode: "number" }).notNull(),
}); });
export const users = pgTable("users", { export const users = pgTable("users", {
@@ -84,13 +83,13 @@ export const users = pgTable("users", {
token: varchar({ length: 511 }), token: varchar({ length: 511 }),
permissions: smallint().notNull().default(44), permissions: smallint().notNull().default(44),
}, },
(users) => [ (_) => [
check("permissions lower bound", sql`users.permissions >= 0`), check("permissions lower bound", sql`users.permissions >= 0`),
check("permissions upper bound", sql`users.permissions <= 77`), check("permissions upper bound", sql`users.permissions <= 77`),
] ]
); );
export const relations = defineRelations({ articles, articleBlocks }, (r) => ({ export const relations = defineRelations({ articles, articleBlocks, users }, (r) => ({
articles: { articles: {
blocks: r.many.articleBlocks() blocks: r.many.articleBlocks()
}, },
+52 -2
View File
@@ -1,9 +1,59 @@
import { drizzle } from 'drizzle-orm/node-postgres'; import { drizzle } from 'drizzle-orm/node-postgres';
import { eq } from 'drizzle-orm'; import { eq } from 'drizzle-orm';
import { articles } from '../db/schema.ts'; import { articleBlocks } from '../db/schema.ts';
import express, { Request, Response } from "express"; import express, { Request, Response } from "express";
const db = drizzle(process.env.DATABASE_URL!); const db = drizzle(process.env.DATABASE_URL!);
export const blocksRouter = express.Router(); export const blocksRouter = express.Router();
// TODO: implement blocksRouter.get("/getAllBlocks", async (_: Request, res: Response) => {
const resp = await db.select().from(articleBlocks);
res.json(resp);
});
blocksRouter.get("/getBlocks/:articleId", async (req: Request, res: Response) => {
const { articleId } = req.params;
const parsedId = Array.isArray(articleId) ? articleId[0] : articleId;
const resp = await db.select()
.from(articleBlocks)
.where(eq(articleBlocks.article_id, parsedId));
res.json(resp);
});
blocksRouter.post("/createBlock", async (req: Request, res: Response) => {
const resp = await db
.insert(articleBlocks)
.values({
...req.body
});
res.json(resp);
});
blocksRouter.put("/updateBlock/:blockId", async (req: Request, res: Response) => {
const { blockId } = req.params;
const parsedId = Array.isArray(blockId) ? blockId[0] : blockId;
const resp = await db
.update(articleBlocks)
.set({
...req.body
})
.where(eq(articleBlocks.id, parsedId));
res.json(resp);
});
blocksRouter.delete("/deleteBlock/:blockId", async (req: Request, res: Response) => {
const { blockId } = req.params;
const parsedId = Array.isArray(blockId) ? blockId[0] : blockId;
const resp = await db
.delete(articleBlocks)
.where(eq(articleBlocks.id, parsedId));
res.json(resp);
});
+41 -1
View File
@@ -7,7 +7,12 @@ import { auth } from '../middleware/auth.ts';
const db = drizzle(process.env.DATABASE_URL!); const db = drizzle(process.env.DATABASE_URL!);
export const usersRouter = express.Router(); export const usersRouter = express.Router();
usersRouter.get("/getUser/:userId", auth, async (req: Request, res: Response) => { usersRouter.get("/getUsers", async (_: Request, res: Response) => {
const resp = await db.select().from(users);
res.json(resp)
});
usersRouter.get("/getUser/:userId", async (req: Request, res: Response) => {
const { userId } = req.params; const { userId } = req.params;
const parsedId = Array.isArray(userId) ? userId[0] : userId; const parsedId = Array.isArray(userId) ? userId[0] : userId;
@@ -17,3 +22,38 @@ usersRouter.get("/getUser/:userId", auth, async (req: Request, res: Response) =>
res.json(resp); res.json(resp);
}); });
usersRouter.post("/createUser", async (req: Request, res: Response) => {
const resp = await db
.insert(users)
.values({
...req.body
});
res.json(resp);
});
usersRouter.delete("/deleteUser/:userId", async (req: Request, res: Response) => {
const { userId } = req.params;
const parsedId = Array.isArray(userId) ? userId[0] : userId;
const resp = await db
.delete(users)
.where(eq(users.id, parsedId));
res.json(resp);
});
usersRouter.put("/updateUser/:userId", async (req: Request, res: Response) => {
const { userId } = req.params;
const parsedId = Array.isArray(userId) ? userId[0] : userId;
const resp = await db
.update(users)
.set({
...req.body
})
.where(eq(users.id, parsedId));
res.json(resp);
});