API Reference
Core
createVovkApp
An internal function that creates the Vovk.ts app with the decorators and init function.
export const { get, post, put, patch, del, head, options, prefix, initSegment } = createVovkApp();
initSegment
Createsd Next.js App Route handlers used by the main Optional Catch-all Segmentβ. The function accepts the following options:
segmentName?: string
- the name of the segment thatβs going to be used in the route. Default is empty string (root segment).controllers: Record<string, Function>
- the list of Controllers.exposeValidation?: boolean
- set tofalse
if you want to hide validation logic from the client-side code.emitSchema?: boolean
- set totrue
if you want to emit the schema for the segment. The schema is going to be emitted to the .vovk-schema folder.onError?: (err: Error, req: VovkRequest) => void | Promise<void>
- called on Controller exceptions, can be used to log errors by a third-party service. The second argument can be utilised to retrieve request URL, authorisation info, and other useful information about the failed request.
Decorators
@get
, @post
, @put
, @patch
, @del
, @head
, @options
HTTP method decorators define an HTTP method for a handler. They accept two optional arguments:
path? = ''
- the path for the route.opts?: { cors?: boolean, headers?: Record<string, string>, staticParams?: Record<string, string>[] }
- options for the route. Ifcors
is set totrue
, it will add CORS headers to the response and makeOPTIONS
HTTP method be properly handled.headers
is an object with headers to be added to the response.staticParams
(@get
decorator only) is an array of objects with static parameters that can be used in the route path, e.g.[{ id: '123' }]
.
import { get } from 'vovk';
export default class HelloController {
@get('world', { cors: true, headers: { 'x-hello': 'world' }, staticParams: [{ id: '123' }] })
static getHelloWorld(req, { id }: { id: string }) {
return { hello: 'world', id };
}
}
Each decorator has an .auto()
method that can be used to generate the path automatically based on the controller and method names. It accepts the same options as the decorator itself.
import { get } from 'vovk';
export default class HelloController {
@get.auto({ cors: true, headers: { 'x-hello': 'world' }, staticParams: [{ id: '123' }] })
static getHelloWorld(req, { id }: { id: string }) {
return { hello: 'world', id };
}
}
@prefix
@prefix(p: string)
decorator used to prepend a sub-path to the endpoint. Itβs usage is optional.
import { prefix, get } from 'vovk';
@prefix('hello')
export default class HelloController {
@get('world')
static getHelloWorld() {
return { hello: 'world' };
}
}
@openapi
@openapi(openAPIOperationObject)
decorator can be used to add OpenAPI documentation to the controller method. It accepts an object with summary
, description
and other OpenAPI Operation Object properties.
import { openapi } from 'vovk';
export default class HelloController {
@openapi({
summary: 'Get Hello World',
description: 'Returns a hello world message',
})
@get('world')
static getHelloWorld() {
return { hello: 'world' };
}
}
Utils
createDecorator
createDecorator
is a higher-order function that produces a decorator factory (a function that returns a decorator) for controller class methods. It accepts a middleware function with the following parameters:
import { createDecorator, get } from 'vovk';
const myDecorator = createDecorator(
(req, next, a: string, b: number) => {
// do something with the request
},
(a: string, b: number) => {
// modify schema here
}
);
export default class MyController {
@get.auto()
@myDecorator('foo', 1) // Passes 'foo' as 'a', and 1 as 'b'
static doSomething() {
// ...
}
}
See decorators docs for more info.
createRPC
Function that creates RPC modules out of schema and types inferred from controllers. Itβs imported by the generated TypeScript, ESM and CJS files and can be customized at config.
fetcher
Function that creates a data fetching layer for the RPC client. It handles HTTP requests, client-side validation, and response parsing. Itβs imported by the generated TypeScript, ESM and CJS files and can be customized at config. A new fetcher can be created using createFetcher function.
createFetcher
Function that creates a custom fetcher for the RPC client. It accepts a generic type parameter that defines the options for the resulting RPC methods. The function returns a fetcher
function that is going to be used in the createRPC
function.
import { createFetcher } from 'vovk';
export const fetcher = createFetcher<{
successMessage?: string; // "Successfully created a new user"
useAuth?: boolean; // if true, Authorization header will be set
someOtherCustomFlag?: boolean; // any custom flag that you want to pass to the RPC method
}>({
prepareRequestInit: async (init, { useAuth, someOtherCustomFlag }) => {
// ...
return {
...init,
headers: {
...init.headers,
...(useAuth ? { Authorization: 'Bearer token' } : {}),
},
};
},
transformResponse: async (data, { someOtherCustomFlag }) => {
// ...
return {
...data,
};
},
onSuccess: async (data, { successMessage }) => {
if (successMessage) {
alert(successMessage);
}
},
onError: async (error) => {
alert(error.message);
},
});
generateStaticAPI
Function that generates API that is generated at build time instead of on-demand at request time. It accepts a record of controllers and an optional slug that is used to generate the static API path. The function returns an array of static parameters that can be used in the generateStaticParams
function.
// ...
export type Controllers = typeof controllers;
export function generateStaticParams() {
return generateStaticAPI(controllers);
}
export const { GET } = initSegment({ controllers });
See static segment documentation for more info.
withValidationLibrary
A lower-order function that allows to create validation function for controller methods.
createStandardValidation
Creates a custom validation library that uses Standard Schema. The only option of this function is toJSONSchema
function that defines how to convert the models to JSON Schema format.
import type { type } from 'arktype';
import { createStandardValidation } from 'vovk';
export const withArk = createStandardValidation({
toJSONSchema: (model: type) => model.toJsonSchema(),
});
import { prefix, post, openapi } from 'vovk';
import { type } from 'arktype';
import { withArk } from '@/lib/withArk';
@prefix('users')
export default class UserController {
@openapi({
summary: 'Update user',
description: 'Update user by ID with',
})
@post('{id}')
static updateUser = withArk({
body: type({
name: type('string').describe('User full name'),
age: type('0 < number < 120').describe('User age'),
email: type('string.email').describe('User email'),
}),
// ...
async handle(req, { id }) {
// ...
},
});
}
multitenant
createLLMTools
createCodeExamples
createValidateOnClient
progressive
openAPIToVovkSchema
vovkSchemaToOpenAPI
Types and Enums
KnownAny
VovkClient
VovkClientFetcher
VovkDefaultFetcherOptions
VovkStreamAsyncIterable
VovkValidateOnClient
VovkSegmentSchema
VovkErrorResponse
VovkRequest
VovkOutput
VovkIteration
VovkBody
VovkQuery
VovkParams
VovkYieldType
VovkReturnType
VovkMetaSchema
VovkControllerSchema
VovkHandlerSchema
VovkSchema
VovkConfig
VovkStrictConfig
VovkValidationType
VovkLLMTool
VovkTypedMethod
VovkSimpleJSONSchema
VovkSchemaIdEnum
API
TODO: setClientValidatorsForHandler, VovkControllerSchema, createRPC, VovkHandlerSchema, VovkClient, KnownAny, VovkStreamAsyncIterator
Full list of available imports for quick reference:
import {
// core
initSegment,
createDecorator,
// controller method decorators
get,
post,
put,
patch,
del,
head,
options,
// controller class decorator
prefix,
// core types
type VovkClientFetcher,
type VovkDefaultFetcherOptions,
type VovkSchema,
type VovkErrorResponse,
// types used by controllers
type VovkRequest,
type VovkControllerBody,
type VovkControllerQuery,
type VovkControllerParams,
type VovkControllerReturnType,
type VovkControllerYieldType,
// types used by client-side code
type VovkBody,
type VovkQuery,
type VovkParams,
type VovkReturnType,
type VovkYieldType,
type VovkClientOptions,
// classes
JSONLinesResponse,
HttpException,
// enums
HttpStatus,
HttpMethod,
// misc
generateStaticAPI,
} from 'vovk';
// CLI types
import type { VovkConfig, VovkEnv } from 'vovk-cli';
Core
initSegment
Creates the standard Next.js App Route handlers used by the main Optional Catch-all Segmentβ. The function accepts the following options:
segmentName?: string
- the name of the segment thatβs going to be used in the route. Default is empty string (root segment).controllers: Record<string, Function>
- the list of ControllersexposeValidation?: boolean
- set tofalse
if you want to hide validation logic from the client-side code.onError?: (err: Error, req: VovkRequest) => void | Promise<void>
- called on Controller exceptions, can be used to log errors by a third-party service. The second argument can be utilised to retrieve reques URL, authorisation info, and other useful information about the failed request.
import { initSegment } from 'vovk';
import HelloController from '../../modules/hello/HelloController';
import UserController from '../../modules/user/UserController';
const controllers = { HelloRPC: HelloController, UserRPC: UserController };
export type Controllers = typeof controllers;
export const { GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS } = initSegment({
controllers,
exposeValidation: false,
onError(e, req) {
console.log('Error', e);
},
});
createDecorator
Defines a custom decorator to extend default behavoir of API endpoints. Accepts 2 arguments: middleware function and init function. The first one defines what the decorator is going to do, the second one is called once per initialisation and intended to pass extra data to the schema (for now itβs client validation, if exposed).
The middleware accepts at least 2 arguments: VovkRequest
, next
function that needs to be called and its awaited result needs to be returned after you perform required actions and ...rest
- the arguments that are going to be used by the created decorator fabric.
import { createDecorator, get, HttpException, HttpStatus } from 'vovk';
const myDecorator = createDecorator(
(req, next, a: string, b: number) => {
console.log(a, b); // Outputs: "foo", 1
if (isSomething) {
// override route method behavior and return { hello: 'world' } from the endpoint
return { hello: 'world' };
}
if (isSomethingElse) {
// throw HTTP error if needed
throw new HttpException(HttpStatus.BAD_REQUEST, 'Something went wrong');
}
return next();
},
(a: string, b: number) => {
console.info('Decorator is initialised with', a, b);
}
);
class MyController {
static rpcModuleName = 'MyController';
@get.auto()
@myDecorator('foo', 1) // Passes 'foo' as 'a', and 1 as 'b'
static getSomething() {
// ...
}
}
Controller Decorators
@prefix
decorator
@prefix(p: string)
decorator used to prepend a sub-path to the endpoint. Itβs usage is optional.
@get
, @post
, @put
, @patch
, @del
, @head
, @options
@HTTP_METHOD(p: string, opts?: { cors?: boolean, headers?: Record<string, string> })
decorator define an HTTP method and an endpoint thatβs handled by the Controller method.
@get.auto
, @post.auto
, @put.auto
β¦
@HTTP_METHOD.auto(opts?: { cors?: boolean, headers?: Record<string, string> })
define HTTP method and generate endpoint string automatically from controller and method name.
import { prefix, get, post, put, patch, del, head, options } from 'vovk';
@prefix('hello')
export default class HelloController {
@get('world', { cors: true })
static getHelloWorld() {
return { hello: 'world' };
}
@post.auto({ headers: { 'x-hello': 'world' } })
static postData(/* req: VovkRequest */) {
return { success: true };
}
}
Enums
import { HttpMethod, HttpStatus, HttpException } from 'vovk';
HttpMethod
enum
Can be used with your code to create a custom fetcher.
export enum HttpMethod {
GET = 'GET',
POST = 'POST',
PUT = 'PUT',
PATCH = 'PATCH',
DELETE = 'DELETE',
HEAD = 'HEAD',
OPTIONS = 'OPTIONS',
}
HttpStatus
enum
Used to throw and catch errors thrown by the server. Notice NULL
member. It can be used to simulate HTTP errors on client validation errors (this approach is used at vovk-zodβ).
export enum HttpStatus {
NULL = 0,
CONTINUE = 100,
SWITCHING_PROTOCOLS = 101,
PROCESSING = 102,
EARLYHINTS = 103,
OK = 200,
CREATED = 201,
ACCEPTED = 202,
NON_AUTHORITATIVE_INFORMATION = 203,
NO_CONTENT = 204,
RESET_CONTENT = 205,
PARTIAL_CONTENT = 206,
AMBIGUOUS = 300,
MOVED_PERMANENTLY = 301,
FOUND = 302,
SEE_OTHER = 303,
NOT_MODIFIED = 304,
TEMPORARY_REDIRECT = 307,
PERMANENT_REDIRECT = 308,
BAD_REQUEST = 400,
UNAUTHORIZED = 401,
PAYMENT_REQUIRED = 402,
FORBIDDEN = 403,
NOT_FOUND = 404,
METHOD_NOT_ALLOWED = 405,
NOT_ACCEPTABLE = 406,
PROXY_AUTHENTICATION_REQUIRED = 407,
REQUEST_TIMEOUT = 408,
CONFLICT = 409,
GONE = 410,
LENGTH_REQUIRED = 411,
PRECONDITION_FAILED = 412,
PAYLOAD_TOO_LARGE = 413,
URI_TOO_LONG = 414,
UNSUPPORTED_MEDIA_TYPE = 415,
REQUESTED_RANGE_NOT_SATISFIABLE = 416,
EXPECTATION_FAILED = 417,
I_AM_A_TEAPOT = 418,
MISDIRECTED = 421,
UNPROCESSABLE_ENTITY = 422,
FAILED_DEPENDENCY = 424,
PRECONDITION_REQUIRED = 428,
TOO_MANY_REQUESTS = 429,
INTERNAL_SERVER_ERROR = 500,
NOT_IMPLEMENTED = 501,
BAD_GATEWAY = 502,
SERVICE_UNAVAILABLE = 503,
GATEWAY_TIMEOUT = 504,
HTTP_VERSION_NOT_SUPPORTED = 505,
}
Classes
HttpException
class
Used to throw HTTP errors on server-side and re-throw, simulate and handle HTTP errors on client-side. The instance provides 2 properties: statusCode
and message
.
Server-side:
// ...
export default class HelloController {
@get()
static getHello() {
if(/* ... */) {
throw new HttpException(HttpStatus.BAD_REQUEST, 'Something went wrong');
}
}
}
Client-side:
import { HelloRPC } from 'vovk-client';
export async function getHello() {
try {
return await HelloRPC.getHello();
} catch (e) {
console.log(e instanceof HttpException);
const err = e as HttpException;
console.log(err.statusCode, err.message);
}
}
JSONLinesResponse
JSONLinesResponse<T>(init?: ResponseInit)
class can be used as an alternative to generators to implement JSON response streaming. Instances of this class provide the following methods:
send(data: T)
- sends portion of dataclose()
- close the connectionthrow(error: any)
- throws an error on client-side and closes the connection
import { prefix, get, JSONLinesResponse, type VovkRequest } from 'vovk';
type Token = { message: string };
@prefix('stream')
export default class StreamController {
@get('tokens')
static async streamTokens() {
const resp = new JSONLinesResponse<Token>();
void (async () => {
const tokens: Token[] = [{ message: 'Hello,' }, { message: ' World' }, { message: '!' }];
for (const token of tokens) {
await new Promise((resolve) => setTimeout(resolve, 300));
if (somethingWentWrong) {
resp.throw(new Error('Somethiing went wrong'));
}
resp.send(token);
}
resp.close();
});
return resp;
}
}
The class also provides static property defaultHeaders
that contains the standard headers for the keep-alive connections. Since JSONLinesResponse
accepts standard ResponseInit
as options argument you can override default headers and optionally spread JSONLinesResponse.defaultHeaders
.
const resp = new JSONLinesResponse<Token>({
headers: {
...JSONLinesResponse.defaultHeaders,
'x-hello': 'world',
},
});
Core types
VovkClientFetcher
and VovkDefaultFetcherOptions
types
Used to redefine the default fetcher. See customization docs.
VovkEnv
type
Defines Vovk.ts env variable types.
For more info check customization docs.
VovkSchema
type
Defines format for one schema file at .vovk-schema/ folder.
VovkErrorResponse
type
Original shape of an object returned from the server when an error is thrown.
Controller Types
VovkRequest
type
Originally, the type is used to define types for req.json
and req.nextUrl.searchParams.get
and allow to infer types in other environments.
import { get, type VovkRequest } from 'vovk';
export class HelloController {
@get('{someParam}')
static doSomething(req: VovkRequest<{ body: true }, { q: string }>, { someParam }: { someParam: string }) {
const body = await req.body(); // { body: true }
const q = req.nextUrl.searchParams.get('q'); // string
const nope = req.nextUrl.searchParams.get('nope'); // never
// ...
return { success: true };
}
}
Starting V3 the type is alsoused to define req.vovk
object with body()
, query()
, meta()
and form()
methods.
await req.vovk.body()
- returns request body. In most of cases works the same way asreq.json()
but if used with vovk-dto itβs going to return an instance of the DTO class.req.vovk.query()
- returns serialized object with query string parameters. If used with vovk-dto itβs going to return an instance of the DTO class.req.vovk.meta<T>([metadata])
- allows to get and set meta information for the request (for example, to store current user authorization info, etc).- If called without arguments it returns the current meta object.
- If called with an object it sets the meta object by extending the current one and returns the new meta object.
- If called with
null
it resets the meta object.
await req.vovk.form<T>()
- returns a serialized object with form data.
Check request documentation for more info.
import { get, type VovkRequest } from 'vovk';
export class HelloController {
@get('{someParam}')
static doSomething(req: VovkRequest, { someParam }: { someParam: string }) {
const body = await req.vovk.body(); // { body: true }
const q = req.vovk.query(); // { q: string }
const meta = req.vovk.meta(); // { user: 'admin' }
const form = req.vovk.form(); // { foo: 'bar' }
// ...
return { success: true };
}
}
VovkControllerBody
type
Extracts request body type from a controller method.
VovkControllerQuery
type
Extracts query (search params) type from a controller method.
VovkControllerParams
type
Extracts params type from a controller method.
VovkControllerReturnType
type
Extracts return type from a controller method and unwraps the promise.
VovkControllerYieldType
type
Extracts yield type from a controller method implemented as a generator.
import {
get,
type VovkControllerBody,
type VovkControllerQuery,
type VovkControllerParams,
type VovkControllerReturnType,
type VovkControllerYieldType,
} from 'vovk';
export class HelloController {
@get('{someParam}')
static doSomething(/* ... */) {
// ...
}
static *generator(/* ... */);
}
type DoSomethingBody = VovkControllerBody<typeof HelloController.doSomething>;
type DoSomethingQuery = VovkControllerQuery<typeof HelloController.doSomething>;
type DoSomethingParams = VovkControllerParams<typeof HelloController.doSomething>;
type DoSomethingReturnType = VovkControllerReturnType<typeof HelloController.doSomething>;
type GeneratorYieldtype = VovkControllerYieldType<typeof HelloController.generator>;
Types for the client
VovkBody
type
Extracts request body type from a clientized controller method.
VovkQuery
type
Extracts query (search params) type from a clientized controller method.
VovkParams
type
Extracts params type from a clientized controller method.
VovkReturnType
type
Extracts return type from a clientized controller method and unwraps the promise.
VovkYieldType
type
Extracts yield type from a clientized generator controller method.
import { HelloRPC } from 'vovk-client';
type DoSomethingBody = VovkBody<typeof HelloRPC.doSomething>;
type DoSomethingQuery = VovkQuery<typeof HelloRPC.doSomething>;
type DoSomethingParams = VovkParams<typeof HelloRPC.doSomething>;
type DoSomethingReturnType = VovkReturnType<typeof HelloRPC.doSomething>;
type GeneratorYieldType = VovkYieldType<typeof HelloRPC.generator>;
VovkClientOptions
type
Type that used internally and exposed to customize the client. See customization for more info.
Misc
generateStaticAPI
generateStaticAPI(controllers: Record<string, Function>, slug?: string)
is used to generate static endpoints with generateStaticParamsβ at build time instead of on-demand at request time. It can be used in a Static Export modeβ with the output: 'export'
Next.js config setting:
See segment documenation for more info.
// ...
export type Controllers = typeof controllers;
export function generateStaticParams() {
return generateStaticAPI(controllers);
}
export const { GET } = initSegment({ controllers });
CLI types
The types below are imported from vovk-cli package.
VovkConfig
type
Defines config types.
/** @type {import('vovk-cli').VovkConfig} */
const vovkConfig = {
// ...
};
export default vovkConfig;
VovkEnv
type
Defines env variable types that override config options.