@khester/dataverse-codegen
v0.1.1
Published
Terminal CLI to scaffold Dataverse TypeScript (CRUD API, constants, models, sample data) into client projects. Independent, composable subcommands over the entity-gen engine.
Maintainers
Readme
@dataverse-kit/dataverse-codegen (dvgen)
Terminal CLI that scaffolds the TypeScript a Dynamics 365 client project needs — a CRUD API layer, field constants, typed models, and test data — straight from a live Dataverse org. Independent, composable subcommands you run inside a client project (Web Resource / PCF / Grid Customizer).
Built on the shared @dataverse-kit/entity-gen engine. The published binary is
bundled and self-contained (zero runtime dependencies), so it runs in a bare client project with
no workspace install.
Requires Node ≥ 18 (uses the global
fetch).
Install
Pick whichever fits your workflow:
# 1. One-off, no install
npx @dataverse-kit/dataverse-codegen <command> [options]
# 2. Global
npm i -g @dataverse-kit/dataverse-codegen
dvgen <command> [options]
# 3. Per-project devDependency (recommended — mirrors your dev:token setup)
npm i -D @dataverse-kit/dataverse-codegenWith option 3, add scripts to the client project's package.json:
{
"scripts": {
"gen:api": "dvgen api",
"gen:constants": "dvgen constants --entity stn_order",
"gen:models": "dvgen models --entity stn_order --with-retrieve",
"seed:pull": "dvgen seed:pull --entity stn_order",
"seed:push": "dvgen seed:push --entity stn_order --dry-run"
}
}Authentication
Every command that hits the org resolves the URL + token in this order (tolerant of the env-var prefixes client projects use):
--url/--tokenflags--env-file <path>or process env:DYNAMICS_*, thenVITE_DYNAMICS_*, thenREACT_APP_DYNAMICS_*(_URLand_TOKEN)- Azure CLI fallback —
az account get-access-tokenfor the resolved org URL
For a cross-tenant client org where you don't have az login to the client's tenant, pass a token
explicitly: --token "$(...)" or set DYNAMICS_TOKEN.
# Examples
dvgen constants --entity account --url https://org.crm.dynamics.com # token via az
dvgen models --entity account --env-file .env.local # url+token from .env.localThe pipeline
Mirrors the client build workflow (CRUD API → constants → models → test data → test):
dvgen api # → src/services/* (self-contained IApiService layer)
dvgen constants --entity stn_order # → src/constants/StnOrderConstants.ts
dvgen models --entity stn_order # → src/models/StnOrder.ts (first pass)
dvgen models --entity stn_order --with-retrieve # + retrieveWithRelated() link-entity scaffolds
dvgen seed:pull --entity stn_order --top 25 # → src/sampleData/stn_order.json (OData fixture)
dvgen test-retrieve --entity stn_order # read fixture (CI-safe) — or --live to query the org
dvgen seed:push --entity stn_order --dry-run # create records from the fixture (preview first!)Commands
| Command | What it writes | Live org? |
|---------|----------------|-----------|
| api | src/services/{IApiService,FetchApiService,XrmApiService,MockApiService,ServiceFactory}.ts | No |
| constants --entity <e> | src/constants/<Entity>Constants.ts (field constants + option-set enums) | Yes |
| models --entity <e> [--with-retrieve] | src/models/<Entity>.ts (interface + class + fromRaw + validate + CRUD/retrieve) | Yes |
| seed:pull --entity <e> | src/sampleData/<entity>.json (OData { value: [...] }) | Yes |
| seed:push --entity <e> | creates records in Dataverse from the fixture | Yes |
| test-retrieve --entity <e> [--live] | nothing (reports row counts/fields) | only with --live |
Common options
--out <dir>— output base dir (defaultsrc); each command appends its own subdir (services/,constants/,models/,sampleData/). Pass--out ./src, not--out ./src/services.--url/--token/--env-file— connection (see Authentication).- Write safety (constants / models / seed:pull):
--dry-run,--diff,--force. Existing files are skipped unless--force— hand-customized files are never clobbered.
Notable flags
constants --no-augment— skip the typed-cast metadata pass (MaxLength/Precision/… JSDoc detail).models --with-retrieve— emitretrieveWithRelated()with commented parent-lookup<link-entity>scaffolds (uncomment the joins you need);--api-service <import>overrides the IApiService import.seed:pull --top <n> --select <cols> --filter <odata>.seed:push --dry-run(preview, no writes),--top <n>,--file <path>. Annotations, the primary id, and_x_valuelookups are stripped on push (lookups need@odata.bind, reported as skipped).
Design notes
- Independent but composable — run
constantswithoutmodels;modelsreferences the constants file (extension-agnostic import) without regenerating it. - Self-contained output — generated
src/services/*and models carry no package imports, so a generated project compiles standalone (verified:tscwithisolatedModules, ES2017, no@types/node). - Shared engine — constants/model generation is the same
entity-genengine the form-builder export uses, so output stays consistent across tools.
Develop / build
nvm use 20
npm install # at the dynamics-toolkit root (workspaces)
npm run build # tsup → dist (bundles all deps; dist/cli.cjs is the bin)
npm run typecheck
npm run test