DevPluginsREST API
Generate a module
Create a VitNode API module with vitnode generate module, preview the change with a dry run, and nest a child module inside a parent.
vitnode g module creates an API module and registers it for you: a top-level module in buildApiPlugin({ modules }), a child module in its parent's modules. Use it whenever a plugin needs a new URL segment, such as /notes, for a group of routes.
Before you begin
- A fresh plugin made with Create plugin, such as
site-notes. - A terminal in
plugins/site-notes. From the workspace root, runpnpm --filter site-notes exec vitnode ...instead ofpnpm vitnode ....
The generator guides, from this page to Generate an API resource, build the same notes module as the hand-written lessons from API modules to Permissions. Follow one track per plugin: where the lessons' notes module already exists, these commands stop with "already exists".
Preview the change
Add --dry-run to print the exact changes without writing them:
pnpm vitnode g module notes --dry-run--- /dev/null
+++ b/src/api/modules/notes/notes.module.ts
@@ -0,0 +1,6 @@
+import { buildModule } from "@/api/builders";
+
+export const notesModule = buildModule({
+ name: "notes",
+ routes: [],
+});
--- a/src/config.api.ts
+++ b/src/config.api.ts
@@ -5,11 +5,12 @@
import { manifest } from "@/manifest.gen";
import { helloModule } from "./api/modules/hello/hello.module";
+import { notesModule } from "./api/modules/notes/notes.module";
export const siteNotesApiPlugin = () =>
buildApiPlugin({
manifest,
- modules: [helloModule],
+ modules: [helloModule, notesModule],
});
Dry run: 1 file to create, 1 to update. Nothing was written.The new import follows the style the file already uses, here a relative path. The rest of config.api.ts, including the VitNodeApiPlugin type, stays as it was.
Generate the module
Run the same command without --dry-run:
pnpm vitnode g module notesā VitNode
Generate a module
Plugin site-notes .
ā created src/api/modules/notes/notes.module.ts module "notes"
ā updated src/config.api.ts register notesModule in buildApiPlugin
Module notes is mounted at /site-notes/notes under the app's API base path (/api in the starter apps).
It has no routes yet, so there is nothing to call. Add one with:
vitnode g route notes/listAn empty module has no endpoint: /api/site-notes/notes answers 404 until you add a route.
Nest a child module
A module path with a slash creates a child module inside its parent. Pass --parents to create a missing parent too:
pnpm vitnode g module reports/weekly --parentsThis creates src/api/modules/reports/reports.module.ts, registered in config.api.ts, and src/api/modules/reports/weekly/weekly.module.ts, registered only in its parent:
import { buildModule } from "@/api/builders";
import { reportsWeeklyModule } from "./weekly/weekly.module";
export const reportsModule = buildModule({
name: "reports",
routes: [],
modules: [reportsWeeklyModule],
});Routes of the child module are served under /api/site-notes/reports/weekly, and the fetcher calls them with module: "reports/weekly". Without --parents, an interactive terminal asks whether to create a missing parent. Without a terminal, as in CI, the command stops with a hint.
Check the result
Run the generator for the same module again. It refuses, because the module is now registered:
pnpm vitnode g module notesā Module "notes" already exists.
Declared as notesModule in src/api/modules/notes/notes.module.ts.The generator never overwrites a file or a registration. Admin modules work the same way under admin/. Protect an admin endpoint creates them together with a guarded route.