Schema
The npm run dev
command runs vovk dev together with next dev
via concurrently . The first one watches for changes in modules
folder, looking for updates of controller methods and their validation. On the initial run, or when a change has been detected, it makes an HTTP request to the Next.js dev server’s endpoint _schema_
of a corresponding segment, that is exposed only when process.env.NODE_ENV
is set to development
. The endpoint returns schema for the corresponding segment only, allowing to isolate emitted .json files from each other. This approach works even in Edge Runtime , since route.ts
files don’t have to import Node.js modules such as fs
.
Each segment emits back-end schema into an individual JSON file that in its turn is used to generate client-side RPC modules. If you have different areas of your application (e.g. root, admin, customer), each area will have its own JSON schema file.
For a segment structure like this:
- route.ts (root segment
/api/
)
- route.ts (root segment
- route.ts (admin segment
/api/admin
)
- route.ts (admin segment
- route.ts (customer segment
/api/customer
) - route.ts (static segment
/api/customer/static
for OpenAPI)
- route.ts (static segment
- route.ts (customer segment
The resulting schema files will be located in .vovk-schema/
directory like the following:
- root.json
- admin.json
- customer.json
- static.json
- _meta.json
As you can see, the emited files follow recursive structure of the segments, so a segment foo/bar/baz
will emit a schema file located at .vovk-schema/foo/bar/baz.json
. The root segment as the only exception from this rule is represented by root.json
file for nicer organization.
The _meta.json
file contains additional metadata, such as explicitly emitted fields of the vovk.config file behind config
key but also some other information.
When Vovk CLI reads these files, it builds a single object of keys segments
and meta
, where segments
have flat structure of segment names as keys and their schema as values, and meta
contains the _meta.json
file content. This object is then used to generate client-side RPC modules, OpenAPI documentation, but also available on both client-side and server-side as schema
export.
{
"segments": {
"": { ... }, // root segment schema from root.json
"admin": { ... }, // admin segment schema from admin.json
"customer": { ... }, // customer segment schema from customer.json
"customer/static": { ... } // static segment schema from customer/static.json
},
"meta": { ... } // content of _meta.json file
}
import { schema } from 'vovk-client';
// or
import { schema } from 'vovk-client/schema'; // exports only the schema object, not the client-side RPC modules
import type { VovkSchema, VovkSegmentSchema } from 'vovk';
console.log(schema satisfies VovkSchema); // schema for the admin segment
console.log(schema.segments.admin satisfies VovkSegmentSchema); // schema for the admin segment
The schema
is also available in the segmented client, containing schema with a single segment.
{
"segments": {
"": { ... } // root segment schema from root.json
},
"meta": { ... } // content of _meta.json file
}
import { schema } from '@client/root';
// or
import { schema } from '@client/root/schema';
Example of a segment schema file:
{
// Segment schema version
"$schema": "https://vovk.dev/api/spec/v3/segment.json",
// vovkInit function option that defines is the schema going to be emitted for this segment
"emitSchema": true,
// Segment name, for the root segment it's an empty string
"segmentName": "foo",
// List of controllers as key-value pairs for fast access
// Key is a name of the variable that's going to be exported from "vovk-client"
// Value is controller information
"controllers": {
"HelloRPC": {
// RPC name that's going to be used in the client
"rpcModuleName": "HelloRPC",
// Original name of the controller class, used to determine segment name when the controller is changed on "vovk dev"
"originalControllerName": "HelloController",
// An argument of @prefix class decorator
"prefix": "hello",
// List of handlers as key-value pairs for fast access
// Key is a static method name
// Value is a handler information
"handlers": {
"getHello": {
// Endpoint that's concatenated with the prefix
"path": "greeting",
// HTTP method
"httpMethod": "POST",
// Validation for "body", "query", "params", "output" and "iteration"
// Can contain any custom data, at this case it's JSON schema emitted by "vovk-zod"
"validation": {
"body": {
"type": "object",
"properties": {
"foo": {
"type": "string"
}
},
"required": ["foo"],
"additionalProperties": false,
"x-isForm": true, // A vovk-specific field that indicates that the body is a FormData
"$schema": "https://json-schema.org/draft/2020-12/schema"
},
"query": {
"type": "object",
"properties": {
"bar": {
"type": "string"
}
},
"required": ["bar"],
"additionalProperties": false,
"$schema": "https://json-schema.org/draft/2020-12/schema"
},
"params": {
"type": "object",
"properties": {
"baz": {
"type": "string"
}
},
"required": ["baz"],
"additionalProperties": false,
"$schema": "https://json-schema.org/draft/2020-12/schema"
},
"output": {
// or "iteration" for JSONLines response
"type": "object",
"properties": {
"hello": {
"type": "string"
}
},
"required": ["hello"],
"additionalProperties": false,
"$schema": "https://json-schema.org/draft/2020-12/schema"
}
},
// OpenAPI object that can be used to generate OpenAPI documentation, LLM tools, MCP etc.
"operationObject": {
"summary": "Hello world",
"description": "Hello world",
"x-tool-description": "Hello world" // custom description for an LLM tool
},
// Custom data that can be defined by a custom decorator
"misc": {
"hello": "World"
}
}
}
}
}
}