vovk.config.{js,cjs,mjs}
The config file sets the CLI options, the template definitions and other settings. Often you don’t need it: the CLI has defaults and flags. For more advanced use, create one.
Valid Config File Names
The config is a CJS or ESM module with the .js, .cjs or .mjs extension. It lives in the project root or in the .config folder. The CLI checks these paths in this order and uses the first one that exists (it warns if there are more):
- .config/vovk.config.cjs
- vovk.config.cjs
- .config/vovk.config.mjs
- vovk.config.mjs
- .config/vovk.config.js
- vovk.config.js
vovk init writes vovk.config.mjs, in the .config folder if that folder exists.
Config Options
The config has the VovkConfig type from the vovk package. Its options:
exposeConfigKeys: boolean | string[]
Which config options go to .vovk-schema/_meta.json. true emits all of them, and an array of strings only the listed ones. rootEntry is always emitted: the generated clients build their URLs from it. Default: ["libs", "rootEntry"]
clientTemplateDefs: object
Adds custom template definitions. Use their names in fromTemplates of the composed client or the segmented client.
composedClient: object
Options of the composed client, such as outDir, fromTemplates and excludeSegments.
segmentedClient: object
Options of the segmented client, such as outDir, fromTemplates and excludeSegments.
bundle: object
Options of the bundle, such as excludeSegments and the build function that runs the bundler.
modulesDir = 'src/modules'
The folder of the module files; modules when the app isn’t in src/app. vovk new creates modules in it, and vovk dev watches it for changes.
schemaOutDir = '.vovk-schema'
The folder the schema is written to.
rootEntry = 'api'
The root path of the API. With the default api, routes are served under /api, and the segment route.ts files live in ./src/app/api (the src/ folder is optional). An empty string '' serves the API from the domain root, with the segments in ./src/app. The root segment then takes /, so it can’t sit next to a root page.tsx: Next.js refuses the two routes.
rootSegmentModulesDirName = ''
Used only by vovk new, for projects with several segments. A non-empty string puts the modules of the root segment in a folder with this name. For example, with "root", vovk new controller user creates src/modules/root/user/user-controller.ts instead of src/modules/user/user-controller.ts (in the root of modulesDir).
logLevel = 'info'
The log level of the CLI: "trace", "debug", "info", "warn" or "error". "debug" shows the internal steps, such as file watching.
devHttps = false
Progressive Web Apps need HTTPS in development and in production. For HTTPS in development, pass --experimental-https to next dev, and turn on the HTTPS mode of vovk dev with devHttps: true or the --https flag.
const config = {
// ...
devHttps: true,
};
export default config;To keep HTTPS off by default, add a separate NPM script with the flags:
"scripts": {
"dev-https": "vovk dev --https --next-dev -- --experimental-https",
"dev": "vovk dev --next-dev"
}moduleTemplates: object
Module template names mapped to their paths. vovk new uses them to create services, controllers and other module types.
/** @type {import('vovk').VovkConfig} */
const config = {
// ...
moduleTemplates: {
state: './module-templates/state.ts.ejs',
// add your own templates here
},
};Then create a module in modulesDir:
npm exec -- vovk new state thing # creates src/modules/thing/thing-state.tsnpm exec -- vovk new state segment/thing # creates src/modules/segment/thing/thing-state.tslibs: object
Config for the libraries the client uses, or any other config the client should see. For example, the options of vovk-ajv, the main client-side validation library, described on the customization page.
/** @type {import('vovk').VovkConfig} */
const config = {
// ...
libs: {
/** @type {import('vovk-ajv').VovkAjvConfig} */
ajv: {
options: {
strict: false,
},
target: 'draft-2020-12', // auto-detected by default
},
},
};
export default config;If exposeConfigKeys has "libs", it’s emitted to .vovk-schema/_meta.json, and you can read it in several ways:
import { schema, UserRPC } from '@/client';
console.log(schema.meta.config.libs.ajv.options.strict);
console.log(UserRPC.updateUser.fullSchema.meta?.config.libs?.ajv.target);outputConfig
Customizes the generated client: its imports, its origin and its OpenAPI mixins.
origin: string | null
The origin of the client URLs. Defaults to '', for relative URLs. For absolute URLs, set it to your domain, such as https://example.com. An outputConfig that overrides this one, such as composedClient.outputConfig, can set origin to null or '' to go back to relative URLs.
package: PackageJson & { py_name?: string; rs_name?: string }
The data of the generated package.json (TypeScript client), Cargo.toml (Rust client) and pyproject.toml (Python client). The generated README.md uses it too: for the name, version, description and so on, and for the package name in the code samples.
By default, the Python and Rust package names come from package.name, as [package_name] does: @acme/web-app becomes acme_web_app. py_name and rs_name override them. They name the package, its folder and the imports in the README samples.
readme: { banner?: string, installCommand?: string, description?: string }
Customizes the generated README.md: a banner at the top, an installCommand, and a description that overrides package.description.
samples: { apiRoot?: string, headers?: Record<string, string> }
Customizes the code samples in the generated README.md files and in the Scalar OpenAPI documentation: the samples pass the given apiRoot and headers.
openAPIObject: Partial<import('openapi3-ts/oas31').OpenAPIObject>
Adds to the generated OpenAPI schema. Fields such as info and servers are merged into it.
reExports: Record<string, string>
Re-exports names from other modules, next to the generated RPC modules (in the bundled package too). The keys list the names to re-export, as they go inside the curly braces; the values are module paths. A path that starts with . is relative to the project root, like the other config paths, and is rewritten relative to the folder of each generated client. Any other value, such as a package name, stays as it is.
const config = {
// ...
outputConfig: {
reExports: {
'type MyType': './src/types',
'MyClass, myFunction': './src/utils',
'MyComponent as RenamedComponent': './src/components',
'default as MyDefault': './src/default-export',
},
},
};With the client in src/client, this compiles to:
export { type MyType } from '../types';
export { MyClass, myFunction } from '../utils';
export { MyComponent as RenamedComponent } from '../components';
export { default as MyDefault } from '../default-export';import { type MyType, MyClass, myFunction, RenamedComponent, MyDefault } from '@/client';With the segmented client, the top-level outputConfig.reExports go to the root segment.
import { type MyType, MyClass, myFunction, RenamedComponent, MyDefault } from '@/client/root';imports: { fetcher?: string, validateOnClient?: string | null, createRPC?: string }
The module paths the client imports fetcher, validateOnClient and createRPC from. The defaults are vovk/fetcher, no client-side validation, and vovk/create-rpc. A segment can set only fetcher and validateOnClient. See Imports.
segments
Options for each segment. It takes the same properties as outputConfig (origin, package, readme, samples, openAPIObject, reExports, imports) and the ones below.
rootEntry: string
Overrides the root entry of the segment in the generated clients and the OpenAPI document, for example to change api to another path for multitenancy.
segmentNameOverride: string
Replaces the segment name in the paths that the generated clients call and in the OpenAPI document. An empty string leaves the segment name out, as the multitenancy setup does.
openAPIMixin: VovkOpenAPIMixin
Makes the segment an OpenAPI mixin, which adds a third-party API to the generated client. See OpenAPI mixins.