dataverse-types-gen
v0.3.0
Published
Generate TypeScript types and optionset enums from a Microsoft Dataverse / Dynamics 365 environment's $metadata.
Maintainers
Readme
dataverse-types-gen
Generate TypeScript types and optionset enums from a Microsoft Dataverse / Dynamics 365 environment's $metadata endpoint.
For each requested entity the CLI writes:
- An
<entity>.tsfile with aninterfacefor the entity, an<Entity>Bindinterface for@odata.bindwrites, and imports for related entities. Each field carries a JSDoc comment built from its Dataverse attribute metadata (description, display name, attribute type and required level) so editors and AI agents get column-level context on hover. - A shared
optionsets.tsfile withenums for every picklist/state/status/multiselect option set discovered across the requested entities - A shared
entity-names.tsfile withEntityLogicalNamesandEntitySetNamesas constobjects for the requested entities - An
index.tsbarrel re-exporting all generated types
Installation
npm install --save-dev dataverse-types-gen
# or
pnpm add -D dataverse-types-genUsage
1. Create a config
dataverse-types.config.json:
{
"entities": ["account", "contact", "msdyn_workorder"],
"outputDir": "src/dataverse-gen"
}2. Set environment variables
The generator authenticates with Microsoft Entra ID using the client-credentials flow. Provide these via your shell, a .env file, or your runner's secret store:
| Variable | Description |
| ------------------------ | ------------------------------------------------------------------------ |
| SERVER_URL | Dataverse environment URL, e.g. https://contoso.crm.dynamics.com |
| TENANT_ID | Microsoft Entra tenant ID |
| DYNAMICS_CLIENT_ID | Azure AD application (client) ID |
| DYNAMICS_CLIENT_SECRET | Azure AD application client secret |
The app registration must be granted access to the Dataverse environment as an application user with read permission on entity metadata.
3. Run it
npx dataverse-types-gen
# or with an explicit config path
npx dataverse-types-gen --config ./config/dataverse.jsonA common pattern is to add it as a script in your package.json:
{
"scripts": {
"gen:types": "dataverse-types-gen"
}
}What gets generated
For entities: ["account"] you get:
src/dataverse-gen/
account.ts # export interface Account, export interface AccountBind
optionsets.ts # export enum AccountStatecode, ...
entity-names.ts # export const EntityLogicalNames, EntitySetNames
index.ts # re-exportsentity-names.ts gives you the correct strings to pass to a Web API client —
EntitySetNames is the plural collection name (accounts) used in request
URLs and @odata.bind, EntityLogicalNames is the singular name (account)
used for metadata paths:
import { EntitySetNames } from "./dataverse-gen";
await webApi.retrieveMultiple(EntitySetNames.Account);How it works
- Acquires a bearer token via MSAL using client credentials.
- Fetches the OData
$metadatadocument and parses the EDM schema. - For each requested entity, fetches
EntityDefinitions(...)/Attributes/Microsoft.Dynamics.CRM.<PicklistSubtype>to enumerate option sets. - For each requested entity, fetches
EntityDefinitions(...)/Attributes?$select=LogicalName,AttributeType,DisplayName,Description,RequiredLevelto collect per-column metadata for the JSDoc comments. The English (LCID 1033) label is used, falling back to the user-localized label; when an attribute has no description the display name is used as the comment summary. - Renders one
.tsfile per entity, a sharedoptionsets.ts, and anentity-names.ts(entity set names are read from theEntityContainerin$metadata).
Inherited properties are flattened from @BaseType chains. Navigation properties to entities in your requested set are typed; those outside the set fall back to unknown (use $expand carefully).
License
MIT
