Building a Basic App
Learn how to create a new module, schema, and API route with Bedest.
1. Define Your Schema
Create a new Drizzle schema file under src/features/post/schemas/SPost.ts. We will use the Bedest Core helpers to ensure our schema supports multi-tenancy and soft deletes.
import { pgTable, varchar, text, uuid } from "drizzle-orm/pg-core";
import { baseColumns, UtilDbSchema } from "bedest-core";
export const SPost = pgTable(
"post",
{
...baseColumns,
tenantId: uuid("tenant_id").notNull(),
title: varchar("title", { length: 255 }).notNull(),
content: text("content"),
},
(t) => [
UtilDbSchema.activeIndex("idx_post_active", t.id),
UtilDbSchema.tenantIsolationPolicy(t.tenantId),
]
).enableRLS();
2. Create the Service
Extend the ServiceBaseTenant to automatically inherit robust, RLS-protected CRUD operations without writing any boilerplate SQL.
// src/features/post/services/ServicePost.ts
import { ServiceBaseTenant } from "bedest-core";
import { SPost } from "../schemas/SPost";
class ServicePost extends ServiceBaseTenant<typeof SPost> {
constructor() {
super(SPost);
}
// You can add custom business logic here
// The base class already handles: create, update, remove, getAll, getById
}
export default new ServicePost();
3. Expose the Router
Now, map your service to Elysia routes. Use Bedest's validation objects and decorators to secure your API.
// src/features/post/routers/RouterPost.ts
import Elysia, { t } from "elysia";
import ServicePost from "../services/ServicePost";
import { defPaginatedSchema, VId, VQuery } from "bedest-core";
const RouterPost = new Elysia({ prefix: "/posts" })
// Secure these routes using RoleGuard
.guard({ RoleGuard: ["ADMIN", "USER"] })
.get(
"/",
async ({ app, query }) => await ServicePost.getAll(app, query),
defPaginatedSchema("Post", t.Object({}))
)
.post(
"/",
async ({ app, body }) => await ServicePost.create(app, body),
{
body: t.Object({
title: t.String(),
content: t.Optional(t.String()),
}),
audit: { action: "POST_CREATED" }, // Automatic audit logging!
}
);
export default RouterPost;
4. Register the Router
Finally, open src/app/Router.ts and add your new RouterPost to the main application tree.
Success! You've just created a secure, multi-tenant ready, strictly typed, and auditable REST API endpoint in under 3 minutes.
