Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions apps/docs/content/docs/dev/api/modules.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ Think of modules as containers for related API endpoints. They help organize you
```ts title="plugins/blog/src/api/modules/categories/categories.module.ts"
import { buildModule } from "@vitnode/core/api/lib/module";

import { CONFIG_PLUGIN } from "@/config";

export const categoriesModule = buildModule({
pluginId: CONFIG_PLUGIN.id,
name: "categories",
routes: [] // We'll populate this soon!
});
Expand All @@ -26,12 +24,10 @@ Want to create a module hierarchy? VitNode's got your back! Nested modules are p
```ts title="plugins/blog/src/api/modules/categories/categories.module.ts"
import { buildModule } from "@vitnode/core/api/lib/module";

import { CONFIG_PLUGIN } from "@/config";

import { postsModule } from "./posts/posts.module"; // [!code ++]

export const categoriesModule = buildModule({
pluginId: CONFIG_PLUGIN.id,
name: "categories",
routes: [],
modules: [postsModule] // [!code ++]
Expand All @@ -45,14 +41,12 @@ This creates a structure: `/api/{plugin_id}/categories/posts/*`
```ts title="plugins/blog/src/config.api.ts"
import { buildApiPlugin } from "@vitnode/core/api/lib/plugin";

import { CONFIG_PLUGIN } from "@/config";

import { categoriesModule } from "./api/modules/categories/categories.module"; // [!code ++]

export const blogApiPlugin = () => {
return buildApiPlugin({
pluginId: CONFIG_PLUGIN.pluginId,
modules: [categoriesModule] // [!code ++]
modules: [categoriesModule] // [!code ++]
});
};
```
```
12 changes: 1 addition & 11 deletions apps/docs/content/docs/dev/api/routes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,8 @@ Now for the fun part - creating actual endpoints! Each route is a small but migh
import { z } from "@hono/zod-openapi";
import { buildRoute } from "@vitnode/core/api/lib/route";

import { CONFIG_PLUGIN } from "@/config";

export const getCategoriesRoute = buildRoute({
pluginId: CONFIG_PLUGIN.pluginId,
route: {
method: "get",
path: "/",
Expand Down Expand Up @@ -54,11 +52,9 @@ export const getCategoriesRoute = buildRoute({
```ts title="plugins/blog/src/api/modules/categories/categories.module.ts"
import { buildModule } from "@vitnode/core/api/lib/module";

import { CONFIG_PLUGIN } from "@/config";
import { getCategoriesRoute } from "./routes/get.route"; // [!code ++]

export const categoriesModule = buildModule({
pluginId: CONFIG_PLUGIN.id,
name: "categories",
routes: [getCategoriesRoute] // [!code ++]
});
Expand All @@ -75,10 +71,8 @@ import { z } from "@hono/zod-openapi";
import { buildRoute } from "@vitnode/core/api/lib/route";
import { HTTPException } from "hono/http-exception";

import { CONFIG_PLUGIN } from "@/config";

export const getCategoryByIdRoute = buildRoute({
pluginId: CONFIG_PLUGIN.pluginId,
route: {
method: "get",
// [!code highlight]
Expand Down Expand Up @@ -136,10 +130,8 @@ Query parameters are your best friends for filtering, searching, and pagination.
import { z } from "@hono/zod-openapi";
import { buildRoute } from "@vitnode/core/api/lib/route";

import { CONFIG_PLUGIN } from "@/config";

export const searchCategoriesRoute = buildRoute({
pluginId: CONFIG_PLUGIN.pluginId,
route: {
method: "get",
path: "/search",
Expand Down Expand Up @@ -203,7 +195,6 @@ When you need to send complex data (creating, updating), request bodies are your
import { z } from "@hono/zod-openapi";
import { buildRoute } from "@vitnode/core/api/lib/route";

import { CONFIG_PLUGIN } from "@/config";

const createCategorySchema = z.object({
name: z.string().min(1).max(100).openapi({
Expand All @@ -225,7 +216,6 @@ const createCategorySchema = z.object({
});

export const createCategoryRoute = buildRoute({
pluginId: CONFIG_PLUGIN.pluginId,
route: {
method: "post",
path: "/",
Expand Down Expand Up @@ -274,4 +264,4 @@ export const createCategoryRoute = buildRoute({
return c.json(newCategory, 201);
}
});
```
```
1 change: 0 additions & 1 deletion apps/docs/content/docs/dev/captcha/custom-adapter.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ If you want to use captcha in your custom form or somewhere else, follow these s
import { buildRoute } from "@vitnode/core/api/lib/route";

export const exampleRoute = buildRoute({
pluginId: CONFIG_PLUGIN.pluginId,
route: {
method: "post",
description: "Create a new user",
Expand Down
1 change: 0 additions & 1 deletion apps/docs/content/docs/dev/captcha/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ Add `withCaptcha` to your route config to enable captcha validation for this rou
import { buildRoute } from "@vitnode/core/api/lib/route";

export const exampleRoute = buildRoute({
pluginId: CONFIG_PLUGIN.pluginId,
route: {
method: "post",
description: "Create a new user",
Expand Down
4 changes: 1 addition & 3 deletions apps/docs/content/docs/dev/cron/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,11 @@ export const cleanCron = buildCron({

```ts title="modules/clean/clean.module.ts"
import { buildModule } from "@vitnode/core/api/lib/module";
import { CONFIG_PLUGIN } from "@/config";

// [!code ++]
import { cleanCron } from "./cron/clean.cron";

export const cronModule = buildModule({
pluginId: CONFIG_PLUGIN.pluginId,
name: "clean",
routes: [],
// [!code ++]
Expand All @@ -69,4 +67,4 @@ When your CRON job will run first time, you should see your job in AdminCP under

</Step>

</Steps>
</Steps>
1 change: 0 additions & 1 deletion apps/docs/content/docs/dev/database/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ Access the database in your plugin handlers using `c.get('database')` from the H

```ts title="plugins/{plugin_name}/src/routes/posts.ts"
export const postsRoute = buildRoute({
pluginId: CONFIG_PLUGIN.pluginId,
route: {},
handler: async (c) => {
// [!code ++:7]
Expand Down
4 changes: 1 addition & 3 deletions apps/docs/content/docs/dev/database/pagination.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,9 @@ import {
zodPaginationPageInfo,
zodPaginationQuery
} from "@/api/lib/with-pagination";
import { CONFIG_PLUGIN } from "@/config";
import { core_cron } from "@/database/cron";

export const getCronsRoute = buildRoute({
pluginId: CONFIG_PLUGIN.pluginId,
route: {
method: "get",
description: "Get Admin Cron Logs",
Expand Down Expand Up @@ -275,4 +273,4 @@ export default function UsersPage() {
</React.Suspense>
);
}
```
```
30 changes: 12 additions & 18 deletions packages/vitnode/src/api/lib/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,45 @@ import { OpenAPIHono } from "@hono/zod-openapi";
import type { BuildCronReturn } from "./cron";
import type { Route } from "./route";

export interface BuildModuleType<T extends Route, Plugin extends string> {
plugin: Plugin;
routes: T;
}
import { getCurrentPluginId } from "./plugin-context";

export interface BaseBuildModuleReturn<
P extends string = string,
M extends string = string,
Routes extends Route<P>[] = Route<P>[],
Routes extends Route[] = Route[],
> {
cronJobs: BuildCronReturn[];
hono: OpenAPIHono;
modules?: BaseBuildModuleReturn<P>[];
modules?: BaseBuildModuleReturn[];
name: M;
pluginId: P;
pluginId: string;
routes: Routes;
}

export interface BuildModuleReturn<
P extends string,
M extends string,
Routes extends Route<P>[] = Route<P>[],
Modules extends BaseBuildModuleReturn<P>[] = BaseBuildModuleReturn<P>[],
> extends BaseBuildModuleReturn<P, M, Routes> {
Routes extends Route[] = Route[],
Modules extends BaseBuildModuleReturn[] = BaseBuildModuleReturn[],
> extends BaseBuildModuleReturn<M, Routes> {
modules?: Modules;
}

export function buildModule<
const P extends string,
const M extends string,
const Routes extends Route<P>[],
Modules extends BaseBuildModuleReturn<P>[],
const Routes extends Route[],
Modules extends BaseBuildModuleReturn[],
>({
routes,
pluginId,
name,
modules,
cronJobs = [],
}: {
cronJobs?: BuildCronReturn[];
modules?: Modules;
name: M;
pluginId: P;
routes: Routes;
}): BuildModuleReturn<P, M, Routes, Modules> {
}): BuildModuleReturn<M, Routes, Modules> {
const pluginId = getCurrentPluginId();

const hono = new OpenAPIHono();

if (routes) {
Expand Down
15 changes: 15 additions & 0 deletions packages/vitnode/src/api/lib/plugin-context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
let currentPluginId: string | undefined;

export const setCurrentPluginId = (pluginId: string) => {
currentPluginId = pluginId;
};

export const getCurrentPluginId = () => {
if (!currentPluginId) {
throw new Error(
"Plugin ID is not defined. Ensure that your plugin config sets it before building modules or routes.",
);
}

return currentPluginId;
};
2 changes: 1 addition & 1 deletion packages/vitnode/src/api/lib/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export function buildApiPlugin<P extends string>({
pluginId,
modules = [],
}: {
modules?: BuildModuleReturn<P, string>[];
modules?: BuildModuleReturn<string>[];
pluginId: P;
}): BuildPluginApiReturn {
// Run for checking if the plugin is valid
Expand Down
16 changes: 6 additions & 10 deletions packages/vitnode/src/api/lib/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import {
type EnvVitNode,
pluginMiddleware,
} from "../middlewares/global.middleware";
import { getCurrentPluginId } from "./plugin-context";

export const buildRoute = <
Plugin extends string,
P extends string,
R extends Omit<RouteConfig, "path"> & {
path: P;
Expand All @@ -18,12 +18,11 @@ export const buildRoute = <
>({
route,
handler,
pluginId,
}: {
handler: RouteHandler<R & { path: P }, EnvVitNode>;
pluginId: Plugin;
route: R;
}): Route<Plugin, R & { path: P }> => {
}): Route<R & { path: P }> => {
const pluginId = getCurrentPluginId();
const pluginTag = pluginId
.split(/[-_]/)
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
Expand All @@ -45,16 +44,13 @@ export const buildRoute = <
],
...route,
}) as R & { path: P },
handler: handler as Route<Plugin, R & { path: P }>["handler"],
handler: handler as Route<R & { path: P }>["handler"],
pluginId,
};
};

export interface Route<
Plugin extends string = string,
R extends RouteConfig = RouteConfig,
> {
export interface Route<R extends RouteConfig = RouteConfig> {
handler: (...args: unknown[]) => Promise<Response> | Response;
pluginId: Plugin;
pluginId: string;
route: R;
}
2 changes: 0 additions & 2 deletions packages/vitnode/src/api/modules/admin/admin.module.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { buildModule } from "@/api/lib/module";
import { CONFIG_PLUGIN } from "@/config";

import { advancedAdminModule } from "./advanced/advanced.admin.module";
import { debugAdminModule } from "./debug/debug.admin.module";
import { sessionAdminRoute } from "./routes/session.route";
import { usersAdminModule } from "./users/users.admin.module";

export const adminModule = buildModule({
pluginId: CONFIG_PLUGIN.pluginId,
name: "admin",
routes: [sessionAdminRoute],
modules: [usersAdminModule, debugAdminModule, advancedAdminModule],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { buildModule } from "@/api/lib/module";
import { CONFIG_PLUGIN } from "@/config";

import { cronAdminModule } from "./cron/cron.admin.module";

export const advancedAdminModule = buildModule({
pluginId: CONFIG_PLUGIN.pluginId,
name: "advanced",
routes: [],
modules: [cronAdminModule],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { buildModule } from "@/api/lib/module";
import { CONFIG_PLUGIN } from "@/config";

import { getCronsRoute } from "./routes/get.route";
import { runCronRoute } from "./routes/run.route";

export const cronAdminModule = buildModule({
pluginId: CONFIG_PLUGIN.pluginId,
name: "cron",
routes: [getCronsRoute, runCronRoute],
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@ import {
zodPaginationPageInfo,
zodPaginationQuery,
} from "@/api/lib/with-pagination";
import { CONFIG_PLUGIN } from "@/config";
import { core_cron } from "@/database/cron";

export const getCronsRoute = buildRoute({
pluginId: CONFIG_PLUGIN.pluginId,
route: {
method: "get",
description: "Get Admin Cron Logs",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ import { z } from "zod";
import type { CronJobConfig } from "@/api/lib/cron";

import { buildRoute } from "@/api/lib/route";
import { CONFIG_PLUGIN } from "@/config";
import { core_cron } from "@/database/cron";
import { getNextCronRunDate } from "@/lib/api/get-next-cron-run-date";

export const runCronRoute = buildRoute({
pluginId: CONFIG_PLUGIN.pluginId,
route: {
method: "post",
description: "Run a specific cron job",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { CONFIG_PLUGIN } from "../../../../config";
import { buildModule } from "../../../lib/module";
import { logsDebugAdminRoute } from "./routes/logs.route";

export const debugAdminModule = buildModule({
pluginId: CONFIG_PLUGIN.pluginId,
name: "debug",
routes: [logsDebugAdminRoute],
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { eq } from "drizzle-orm";
import { z } from "zod";

import { CONFIG_PLUGIN } from "@/config";
import { core_logs } from "@/database/logs";

import { core_users } from "../../../../../database/users";
Expand All @@ -13,7 +12,6 @@ import {
} from "../../../../lib/with-pagination";

export const logsDebugAdminRoute = buildRoute({
pluginId: CONFIG_PLUGIN.pluginId,
route: {
method: "get",
description: "Get Admin Debug Logs",
Expand Down
Loading
Loading