Fix validation error for block inputs without validation annotations - #6215
Draft
VPS-thodax wants to merge 1 commit into
Draft
Fix validation error for block inputs without validation annotations#6215VPS-thodax wants to merge 1 commit into
VPS-thodax wants to merge 1 commit into
Conversation
…otations class-validator rejects classes without any validation metadata since v0.14, where forbidUnknownValues is enabled by default. Block inputs that don't validate a single field - for instance a block without fields - therefore always failed to validate, which made documents containing such a block unsaveable. Registering validation metadata on BlockInput fixes this for every validation path without applications having to adapt their ValidationPipe. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TZkkSZg8EAHmU3NL63GsY8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A document cannot be saved as soon as it contains a block whose input class has no class-validator annotation at all — for instance a block without fields. Saving fails with:
Both rich text variants are affected, as they validate their link and child blocks with a direct
validate()call:createRichTextBlock(DraftJS) andcreateTipTapRichTextBlock(link marks and child blocks).Cause
class-validator enables
forbidUnknownValuesby default since v0.14. A class without any validation metadata is treated as an unknown value and rejected — even though there is nothing to validate.BlockInputcarries no validation metadata itself, so a block input without own decorators has none at all.Fix
BlockInputprovides a property that carries validation metadata, so every block input has metadata regardless of its own fields. This works for every validation path without applications having to adapt theirValidationPipe.The property is never set: it doesn't show up in
toPlain(), in the block meta, or in the saved block data.Decisions
BlockInputvalidation metadata instead of passingforbidUnknownValues: falseto thevalidate()calls. Setting the option only fixes the call sites in the core, so any application validating a block input itself would run into the same error again. It also matches the existing precedent in Fix validation error caused byEmptyDamScopewhen uploading a file #3620, which gaveEmptyDamScopean annotated dummy field for the same reason.@Equals(undefined)rather than@Allow(). An annotated property is whitelisted, so with@Allow()a client could sendthisBlockInputNeedsValidationMetadata____on any block and the value would end up in the saved block data — todayforbidNonWhitelistedrejects unknown properties, and that stays intact.private/protected, declaration emit fails withTS4094for the anonymous input classes returned by the block factories (e.g.createBlocksBlock).Similar workarounds in the codebase
A dummy property named
…____is the established way to satisfy a framework that rejects a class without members. It exists today for two reasons:EmptyDamScope(@IsUndefinable()onthisScopeHasNoFields____, added in Fix validation error caused byEmptyDamScopewhen uploading a file #3620). Same cause as this fix.EmptyPageTreeNodeScopeand [`EmptyRedirectScope`](https://github.com/vivid-planet/dextinity/blob/a53e8e4d6f4b9dd216958a5b4c25033699f2d0eb/packages/api/cms-api/src/redirects/dto/empty-redirect-scope.ts#L11``) incms-api,EmailCampaignScopeandBrevoContactFilterAttributesinbrevo-api. These carry no validation annotation.Unlike all of them, the property added here is not part of a GraphQL type, so it is annotated as unsettable instead of nullable.
Verification
block-input-validation.test.tscovers a block input without any annotation:ValidationPipeAll of them fail without the change, except the
ValidationPipeone — NestJS'ValidationPipedefaultsforbidUnknownValuestofalseitself, so that path was never broken. It is covered nonetheless, as applications may configure the option themselves.block-meta.jsonwas regenerated incms-apiand in Demo and is unchanged.Manual verification in the Demo admin
Reproduced and verified in the running Demo admin, as the reported case comes from an application. The Demo has no annotation-free link block, so a temporary one was added to
LinkBlockfor the test — it is not part of this PR.Inserting a link of that type in a
Rich Textblock, then saving the page:savePagereturnsBAD_REQUESTThe same applies to a link in a
Rich Text (TipTap)block.Adding a
Contact Formblock — which is annotation-free too, but sits in the page content and is therefore validated by the application'sValidationPipe— saves in both cases, which confirms that path was never broken.Further information