Fix: transform() return type to MaybePromise and handle async array case (fixes #495)#611
Open
shivamtiwari3 wants to merge 3 commits intomarkdoc:mainfrom
Open
Conversation
…ase (fixes markdoc#495) Root cause: Node.transform() returns MaybePromise<RenderableTreeNodes> but the exported transform() overloads declared sync-only return types. The array path also used flatMap directly without checking for Promise results, so async schemas would silently return unresolved Promises instead of awaitable values. Fix: Update overload signatures to MaybePromise<RenderableTreeNode> / MaybePromise<RenderableTreeNode[]> and mirror the Promise.all pattern from transformer.children() in the array case so async transforms are correctly aggregated and exposed to callers.
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.
Summary
Fixes #495.
Markdoc.transform()declared sync-only return types (RenderableTreeNode/RenderableTreeNode[]) even thoughNode.transform()already returnsMaybePromise<RenderableTreeNodes>. This made it impossible for callers to correctly type-check orawaitasync transforms.Root Cause
In
index.ts, the two exported overload signatures fortransform()were:But
Node.transform()(insrc/ast/node.ts:81) returnsMaybePromise<RenderableTreeNodes>, meaning schemas that define anasync transform()would produce aPromiseat runtime — yet the declared return type claimed it was always synchronous. TypeScript would flag anyawait Markdoc.transform(...)call as "result is not a Promise".Additionally, the array path in the implementation called
content.flatMap((child) => child.transform(config))without checking forPromiseresults, so async children would be silently embedded in the returned array as unresolvedPromiseobjects rather than being correctly awaited.Solution
Update overload signatures to
MaybePromise<RenderableTreeNode>/MaybePromise<RenderableTreeNode[]>, matching the return type contract already established byNode.transform().Fix the array-case implementation to mirror the
Promise.allpattern already used intransformer.children()(src/transformer.ts:62-68): collect child results, check if any are Promises, and if so returnPromise.all(results).then(...).Testing
Added
src/transformer.test.tswith 5 tests covering:Nodereturns non-PromiseTagNode[]returns non-PromiseRenderableTreeNode[]Nodewith async schema returns aPromise<Tag>Node[]where one child uses async schema returnsPromise<RenderableTreeNode[]>All 264 existing specs pass.
tsc --noEmitclean (pre-existing React errors in renderers unaffected).Run with:
Checklist