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 controllers. On the initial run, or when the change is detected, it makes an HTTP request to the Next.js dev server endpoint _schema_
of a corresponding segment, that is exposed when process.env.NODE_ENV
is set to development
. The endpoint returns schema for the corresponding segment, 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 this:
- root.json
- admin.json
- customer.json
- static.json
- _meta.json
As you can see, the emited files follow recursive structure of the segments, and a segment foo/bar/baz
will have a file .vovk-schema/foo/bar/baz.json
. The root segment as the only exception from the rule is represented by root.json
file.
The _meta.json
file contains additional metadata, such as explicitly emitted fields of the vovk.config file using config
key and some other information, having loose format, free to be extended.
When Vovk CLI reads these files, it builds a single object (called βfull schemaβ) 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.
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 for the current segment.
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,
"$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.
"openapi": {
"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"
}
}
}
}
}
}