Client Templates
Introduction
Vovk.ts renders the client libraries from EJS templates. The template logic works like this:
- One template definition renders several files: a template is a folder with one or more files. A file with the
.ejsextension is rendered as an EJS template, and other files are copied as they are.index.ts.ejsis rendered asindex.ts; anindex.tswithout the.ejsextension is copied as it is. - A template can build on another one with the
extendsoption: it takes the options of the other template and overrides some of them. - A template can include other templates with the
requiresoption: it renders them into the output folder.
Template definitions live in the clientTemplateDefs option of the config, together with the built-in definitions. To see them all, set exposeConfigKeys to true, or add clientTemplateDefs to it if it’s an array. Then .vovk-schema/_meta.json lists them under config.
Example
Take the built-in template definition of the Rust client as an example of the options in the next section. Its main definition is under the rs key: the template name you use in the segmented client or composed client config.
The rs template has no files of its own, so it has no templatePath. It requires:
- rsSrc, which renders the Rust source files to
./src(relative tooutDir), - rsPkg, which renders the Cargo files to the root of
outDir, - and rsReadme, which renders the README to the root of
outDir.
The rs definition also sets composedClient.outDir to dist_rust, so it doesn’t write into the src/client folder of the composed TypeScript client.
rsSrc points templatePath to its template folder (lib.rs.ejs, http_request.rs and so on). It requires the schemaJson template, which renders schema.json: the full schema from the .vovk-schema/ folder.
The same setup in your own vovk.config.mjs file:
/** @type {import('vovk').VovkConfig} */
const config = {
clientTemplateDefs: {
schemaJson: {
templatePath: `vovk-cli/client-templates/schema-json/`,
},
rsSrc: {
templatePath: `vovk-rust/client-templates/rs-src/`,
requires: {
schemaJson: './',
},
},
rsPkg: {
templatePath: `vovk-rust/client-templates/rs-pkg/`,
},
rsReadme: {
templatePath: `vovk-rust/client-templates/rs-readme/`,
},
rs: {
composedClient: {
outDir: 'dist_rust',
},
requires: {
rsSrc: './src/',
rsPkg: './',
rsReadme: './',
},
},
}
};
export default config;(the paths end with / for clarity; it isn’t required)
With this setup, generate the full Cargo package:
npx vovk generate --from rs --out ./dist_rustOr only the source code:
npx vovk generate --from rsSrc --out ./my_rust_project/srcOr only the README.md file:
npx vovk generate --from rsReadme --out ./my_rust_projectTemplate Definitions
A definition has these options:
extends?: string
The name of the built-in template this definition extends. The definition takes the options of that template and can override them, such as segmentedClient.outDir.
templatePath?: string
The path of the template folder: relative to the project root, or a package path such as vovk-cli/client-templates/ts-base/. Without it, the template can still include other templates with requires.
requires?: Record<string, string>
The template definitions this template includes. The keys are template names; the values are the paths they render to, relative to the output folder.
composedClient?: object
Composed client options for this template, on top of the root composedClient options of the config, such as outDir or excludeSegments.
segmentedClient?: object
Segmented client options for this template, on top of the root segmentedClient options of the config, such as outDir or excludeSegments.
outputConfig?: object
Overrides the root outputConfig of the config for this template, such as origin or openAPIObject.
Built-in Templates
ts
The default template of the composed client and the segmented client. Renders TypeScript code.
tsBase
The default template of the bundle, since it has no openapi object. Renders TypeScript code.
templatePathisvovk-cli/client-templates/ts-base/.requiresschemaTs, mixins (the last one only when the project has OpenAPI mixins).
schemaTs
Renders schema.ts, which imports the segment schemas from the .vovk-schema/ folder and exports them as a TypeScript object.
templatePathisvovk-cli/client-templates/schema-ts/.
schemaJson
Renders schema.json: all segment schemas from the .vovk-schema/ folder for the composed client, or one segment schema for the segmented client.
templatePathisvovk-cli/client-templates/schema-json/.
openapiTs
Renders openapi.ts, which exports the OpenAPI schema from the openapi.json file next to it (rendered by the openapiJson template).
templatePathisvovk-cli/client-templates/openapi-ts/.requiresopenapiJson, for the OpenAPI schema it imports.
openapiJson
Renders openapi.json, the OpenAPI schema. Use it alone to add the OpenAPI schema to your project.
templatePathisvovk-cli/client-templates/openapi-json/.
To write only the openapi.json file, without a client:
npx vovk generate --from openapiJson --out ./publicreadme
Renders README.md, the documentation of the generated TypeScript client. It takes its data from package.json. The bundle, composedClient or segmentedClient options of the config can override that data, at the root or in a template definition. Each RPC method gets a code sample that you can copy into your code.
templatePathisvovk-cli/client-templates/readme/.
packageJson
Renders package.json, so the generated client can be published to NPM. It takes name, version, description, license, author, contributors, repository, homepage, bugs and keywords from the root package.json, and sets version to 0.0.0 when there is none. The bundle, composedClient or segmentedClient options of the config can override these and other package fields, at the root or in a template definition.
templatePathisvovk-cli/client-templates/package-json/.
mixins
Renders the types and the schema of OpenAPI mixins, when the project has them.
templatePathisvovk-cli/client-templates/mixins/.
rs
Renders the Rust client package: the source code and the Cargo files.
rsSrc
Renders the source files of the Rust client, such as lib.rs and http_request.rs.
templatePathisvovk-rust/client-templates/rs-src/.requiresschemaJson, for the full schema in the generated code.
rsPkg
Renders Cargo.toml for the Rust client.
templatePathisvovk-rust/client-templates/rs-pkg/.
rsReadme
Renders README.md for the Rust client, like the readme template.
templatePathisvovk-rust/client-templates/rs-readme/.
py
Renders the Python client package: the source code and the setup files.
requirespySrc (rendered to./src/[package_name]/), pyPkg and pyReadme.[package_name]is the package name without@, with/,-and other characters a Python name can’t hold turned into_:@acme/web-appbecomesacme_web_app. A name that starts with a digit gets apkg_prefix, and a Python or Rust keyword gets a_pkgsuffix:3d-viewerbecomespkg_3d_viewer,classbecomesclass_pkg. TheCargo.tomlof the Rust client uses the same name.- Sets
composedClient.outDirtodist_python.
pySrc
Renders the source files of the Python client: __init__.py, api_client.py and py.typed.
templatePathisvovk-python/client-templates/py-src/.requiresschemaJson, for the full schema in the generated code.
pyPkg
Renders pyproject.toml and setup.cfg for the Python client.
templatePathisvovk-python/client-templates/py-pkg/.
pyReadme
Renders README.md for the Python client, like the readme template.
templatePathisvovk-python/client-templates/py-readme/.
Roadmap
- 📝 Document how to create custom templates.