Generate typings for multi-select picklist, file and image columns via AttributeTypeName - #333
Conversation
… test output hygiene
… and boolean control types
There was a problem hiding this comment.
Pull request overview
This PR updates the Dataverse typings generator to key off AttributeTypeName.Value (instead of legacy AttributeType) so newer column types like multi-select picklists, file, and image columns are correctly included in generated getAttribute/getControl signatures. It also makes form-eligibility filtering use IsValidForForm, fixes an async enum-resolution race, and introduces a VS Code–independent builder with unit tests.
Changes:
- Reworked typings generation via a new
typingsBuilderhelper that mapsAttributeTypeName.Valueto@types/xrmattribute/control types (including multi-select) and filters output usingIsValidForForm. - Fixed enum generation ordering/race by awaiting enum-resolution work and aligned enum emission with the same filtered attribute set as signature generation.
- Added a Node-friendly unit-test harness (
tsconfig.tests.json,test:unit, mocha tests) and bumped template@types/xrmto^9.0.68to ensure scaffolded projects compile with the new signatures.
Reviewed changes
Copilot reviewed 9 out of 11 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| tsconfig.tests.json | Adds a dedicated TS config for compiling mocha unit tests to out-tests. |
| src/utils/Interfaces.ts | Extends attribute metadata typing with IsValidForForm used by the generator filter. |
| src/test/unit/typingsBuilder.test.ts | Adds unit coverage for filtering, mapping, enum resolution awaiting, and emitted output. |
| src/helpers/typingsHelper.ts | Switches VS Code command path to call the new builder and write emitted typings output. |
| src/helpers/typingsBuilder.ts | New core builder: filtering, type mapping keyed by AttributeTypeName.Value, enum generation, and emission. |
| resources/templates/Webpack/package.json | Bumps @types/xrm to a version that includes multi-select and BooleanControl typings. |
| resources/templates/TypeScript/package.json | Bumps @types/xrm to ^9.0.68. |
| resources/templates/JavaScript/package.json | Bumps @types/xrm to ^9.0.68. |
| package.json | Adds test:unit script to compile/run mocha unit tests. |
| .gitignore | Ignores the unit-test build output directory out-tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@Power-Maverick This ok? |
|
Follow-up on the file/image note in the PR description — I observed the runtime values on existing forms in a live Dataverse environment (no columns created). Both a generic File control and an Image control report
So the conservative |
Power-Maverick
left a comment
There was a problem hiding this comment.
The enums were ok (need more review) but the list of attributes was not correct. it missed primary id field and some of the attributes like importsequencenumber, owninguser,owningbusinessunitname, etc. so it is not correct. Liked how you have a separate builder file but can you please fix the issue with the attribute generation. Thanks.
Filtering on IsValidForForm and IsPrimaryId dropped columns the previous implementation emitted, including primary ids and system columns such as importsequencenumber, owninguser and owningbusinessunitname. Exclude only true VirtualType columns, matching the previous rule, and restore the fallback to Attributes.Attribute/Controls.StandardControl so an unrecognised column type still gets a signature instead of being dropped. Keying the exclusion on AttributeTypeName rather than the legacy AttributeType enum keeps multi-select, file and image columns included. IsValidForForm is no longer read, so its addition to IAttributeDefinition is reverted.
BigInt, CalendarRules, EntityName, ManagedProperty and Uniqueidentifier columns were mapped in the previous implementation but absent from the AttributeTypeName maps, so they fell through to the generic types. Restore the mappings they had before.
|
Thanks,
Regression tests cover the specific columns you named and their generated signatures, plus the unmapped-type fallback and a check that multi-select/file/image are still included despite their legacy I have also removed the claims from the PR description that primary ids, BigInt, EntityName, ManagedProperty and other non-form columns were intentionally dropped — that behaviour is gone, so the description no longer describes it. The enum changes are untouched by this fix if you want to continue reviewing those. |
| export function isGeneratedAttribute(a: ITypingSourceAttribute): boolean { | ||
| return a.AttributeTypeName.Value !== virtualTypeName && a.IsCustomizable.Value && !a.LogicalName.endsWith("_base"); | ||
| } |
| // Primary ids and system columns are not placeable on a form, so filtering | ||
| // on form eligibility silently dropped them from generated typings. | ||
| it("retains primary ids and system columns that cannot go on a form", async () => { | ||
| const source = [ | ||
| attr("accountid", "UniqueidentifierType"), |
Problem
Generating typings for an entity with multi-select picklist (Choices) columns produces their option-value enums but no
getAttribute/getControlsignatures — addresses #313 (closed by the stale bot; I'm the original reporter and this delivers the PR discussed there). Root cause: generation filters on the legacyAttributeTypeproperty, where multi-select, file and image columns all reportVirtual, so they were dropped before the type maps were ever consulted. Microsoft's guidance is to useAttributeTypeNamefor anything newer than the original 2011 type set.Changes
AttributeTypeName.Value: multi-selects map toAttributes.MultiSelectOptionSetAttribute/Controls.MultiSelectOptionSetControl, booleans now getControls.BooleanControl(previously genericStandardControl), and file/image columns are included with conservative fallback types (Attributes.Attribute/Controls.StandardControl) since@types/xrmhas no dedicated interfaces for them. The docs listfile/imageas validgetAttributeType()values but don't document theirgetControlType(); these fallbacks are deliberately conservative, and I'll follow up with observed runtime values from a live form._baseexclusions. The exclusion keys onAttributeTypeName.Value !== "VirtualType"rather than the legacyAttributeType !== "Virtual", and that is precisely what lets multi-select, file and image columns through — all three reportVirtualin the legacy enum. Primary ids and system columns such asimportsequencenumber,owninguserandowningbusinessunitnameare emitted exactly as before.Attributes.Attribute/Controls.StandardControl) rather than being dropped, so a column type this version doesn't know about gets a usable signature instead of vanishing from the output.AttributeOfcompanion columns..forEach(async ...)and never awaited before the file was emitted — they only landed in the output because the directory QuickPick stalls long enough. Resolution is now awaited (Promise.all) with a regression test.src/helpers/typingsBuilder.tswith mocha unit tests (npm run test:unit, 13 tests). The new script exists because the currentpretest/testchain can't run:pretestcalls a nonexistentcompile-testsscript,tsconfig.jsonexcludessrc/test/**, andrunTest.tsimports the legacyvscode-testpackage. That harness is left untouched here;test:unitis additive and reuses the existing mocha devDependency.@types/xrm^9.0.68— the minimum version containingMultiSelectOptionSetAttribute/MultiSelectOptionSetControl(9.0.68) andBooleanControl(9.0.63). Without this, freshly generated typings don't compile in scaffolded projects. Note on the lockfile diff: the TypeScript template'spackage-lock.jsonshows ~4,800 changed lines because npm ≥7 can't writelockfileVersion: 1— the regeneration upgrades it to v2 (readable by npm 6+). The real change is just the@types/xrmbump.Known limitation
getAttribute/getControlreturnnullat runtime for a column that isn't on the loaded form. Generated signatures stay non-null, matching@types/xrm@9.0.68's own base signatures and the tool's existing behavior.Testing
npm run compile,npm run lint(no new warnings), andnpm run test:unit(13 tests: type-map coverage, retention of primary ids and system columns, unmapped-type fallback, exclusion of non-customizable /_base/ true virtual columns, sort determinism, input non-mutation, resolver scoping, race regression, emitted-signature assertions) all pass.tsc --strictagainst exactly@types/xrm@9.0.68, and fails against9.0.41with the expected missing-member errors — confirming the template bump is required.AttributeType = "Virtual"while reportingMultiSelectPicklistType/FileType/ImageTypeviaAttributeTypeName;statecode/statuscodereportStateType/StatusType.