Skip to content

comvi typegen

View .md

Fetch the project’s key schema and write a .d.ts that types every t() call: key names, required parameters and parameter types.

Terminal
comvi typegen [options]
Option Default Meaning
-c, --config <path> nearest .comvirc.json Config file to read
-w, --watch off Generate once, then subscribe to schema updates over SSE and regenerate on every change
--check off Write nothing; compare the file on disk with the current schema and exit 1 when outdated

--check wins over --watch when both are passed. The output path comes from outputPath in the config, default src/types/i18n.d.ts; strictParams: false makes every parameter optional, and augment names the module to augment. Every field is on Comvi CLI.

Generate once
npx comvi typegen
Regenerate while developing
npx comvi typegen --watch
.github/workflows/ci.yml
- run: npx comvi typegen --check
env:
COMVI_API_KEY: ${{ secrets.COMVI_API_KEY }}
- run: npx tsc --noEmit
Monorepo package with a shared config
npx comvi typegen --config ../../.comvirc.json

--watch regenerates when a translator adds, renames or removes a key; it does not watch local files. Ctrl-C closes the connection. Regenerating an unchanged schema produces no diff, so the command is safe in a pre-commit hook or a build step. Without --config, the file is searched upward from the working directory and the search stops at the first package.json, so a config at the repository root is not found from packages/web.

src/i18n.ts
import { createI18n } from '@comvi/core';
import './types/i18n';
export const i18n = createI18n({ locale: 'en', fallbackLocale: 'en' });
src/usage.ts
import { i18n } from './i18n';
i18n.t('hello');
i18n.t('greeting', { name: 'Alice' });
i18n.t('cart.items', { count: 5 });
i18n.t('dashboard.title', { ns: 'admin' });

Import the file once, for its side effect, in the module that builds the i18n instance. The declaration augments the Comvi package your package.json declares, so the same import types t() in every binding. Keys from the default namespace lose their prefix; every other namespace keeps namespace:key. The file’s structure and the augment rule are on Type-check translation keys.

Terminal
comvi typegen --check

The check fetches the schema, emits what the file should contain and compares it with the file on disk. A Generated at: header line in an older file is ignored.

Exit Meaning
0 The file is up to date
1 Outdated: run comvi typegen and commit the result. Also a missing .comvirc.json
2 The check could not run: the API was unreachable, timed out, rejected the key or returned something unusable
4 Invalid config, or a schema the emitter refuses: an unsupported parameter type, or two keys that collide once the default namespace is stripped

Treat 1 as a staleness failure for developers and 2 as an infrastructure failure, or every API blip looks like stale types. A missing config also exits 1, so a job that never checked out .comvirc.json looks the same as outdated types; check that the file exists first when the two must differ. Plain comvi typegen reports the same emitter refusal as a failed generation and exits 1.

comvi typegen and @comvi/vite-plugin share one internal emitter, so the CLI in CI and the Vite plugin in development never disagree about the file. The emitter is bundled into both tools and not published. To generate from another schema source, use TypeEmitter from @comvi/cli, new TypeEmitter().generate(schema, { strictParams, defaultNsName, augment }), or shell out to comvi typegen.