Derive Elysia request validators from Drizzle tables via drizzle-typebox

This commit is contained in:
2026-08-28 17:02:10 +00:00
parent 23643904da
commit 4d13570f0b
4 changed files with 36 additions and 22 deletions
+22
View File
@@ -0,0 +1,22 @@
import { createInsertSchema, createSelectSchema } from "drizzle-typebox";
import { t } from "elysia";
import { printers, printJobs } from "./schema";
// Generated straight from the Drizzle table definitions in `./schema` — this
// is the *only* place these shapes are defined. The Postgres column and the
// Elysia request/response validator can no longer drift apart: change a
// column in `./schema/printers.ts` and both the DB migration and the API
// validator below pick it up automatically.
//
// The second argument overrides fields Drizzle can't infer correctly for an
// insert — `id` is DB-generated (defaultRandom()) so it must be optional on
// the way in, even though it's required on the way out.
export const PrinterInsertSchema = createInsertSchema(printers, {
id: t.Optional(t.String({ format: "uuid" })),
});
export const PrinterSelectSchema = createSelectSchema(printers);
export const PrintJobInsertSchema = createInsertSchema(printJobs, {
id: t.Optional(t.String({ format: "uuid" })),
});
export const PrintJobSelectSchema = createSelectSchema(printJobs);
+8 -21
View File
@@ -2,6 +2,7 @@ import { Elysia, t } from "elysia";
import { eq } from "drizzle-orm";
import { db } from "../db";
import { printers } from "../db/schema";
import { PrinterInsertSchema } from "../db/validators";
export const printerRoutes = new Elysia({ prefix: "/printers" })
.get("/", async ({ query }) => {
@@ -21,28 +22,14 @@ export const printerRoutes = new Elysia({ prefix: "/printers" })
.post(
"/",
async ({ body, set }) => {
const [printer] = await db
.insert(printers)
.values({
farmId: body.farmId,
name: body.name,
vendor: body.vendor,
lanAddress: body.lanAddress,
serialNumber: body.serialNumber,
accessCode: body.accessCode,
})
.returning();
// `body` is already validated + shaped against the Drizzle table by
// PrinterInsertSchema, so it can go straight into `.values()` with no
// hand-mapping of individual fields.
const [printer] = await db.insert(printers).values(body).returning();
set.status = 201;
return printer;
},
{
body: t.Object({
farmId: t.String({ format: "uuid" }),
name: t.String({ minLength: 1 }),
vendor: t.Union([t.Literal("bambu"), t.Literal("prusa"), t.Literal("klipper")]),
lanAddress: t.Optional(t.String()),
serialNumber: t.Optional(t.String()),
accessCode: t.Optional(t.String()),
}),
},
// Derived from `printers` via drizzle-typebox — see src/db/validators.ts.
// Add or rename a column in the schema and this validator updates itself.
{ body: PrinterInsertSchema },
);