Skip to content

Use v.function() for function handle validators - #311

Draft
reeceyang wants to merge 2 commits into
mainfrom
reece/v-function-handles
Draft

reeceyang wants to merge 2 commits into
mainfrom
reece/v-function-handles

Conversation

@reeceyang

@reeceyang reeceyang commented Oct 27, 2026 •

Copy link
Copy Markdown

Summary

Replaces v.string() with v.function() (convex/convex#59475) for function handles, so they're validated as handles and typed as FunctionHandle_future. With convex/convex#59998 deployed, the signatures carry through to the generated ComponentApi. Same change as convex/workpool#250.

  • src/component/schema.ts:
    • workflowHandle is v.function({ fnType: "mutation", args: { workflowId: v.string(), generationNumber } }). The component calls it with the document Id<"workflows">, not the branded WorkflowId, so workflowId is v.string().
    • onComplete.fnHandle is v.function({ fnType: "mutation", args: { workflowId: vWorkflowId, result, context } }), the same args as nestedWorkflowOnComplete and OnCompleteArgs.
    • Step handles are a bare v.function(), since their function type is only known at runtime.
  • src/client/workflowMutation.ts: the direct-call onComplete arg is v.function({ fnType: "mutation" }), and the workflow's own reference is typed "mutation" so its handle matches workflowHandle.
  • src/component/workflow.ts: drops the as FunctionHandle<...> casts where handles go to ctx.runMutation.
  • Tests cast fake handle strings to FunctionHandle_future<any>.
  • package.json: requires convex ^1.49.0, the first release with v.function(), as both the dev dependency and the peer dependency.

The workflowHandle casts at the three workpool.enqueueMutation calls stay. In @convex-dev/workpool 0.4.14, enqueue* infers through FunctionReference, which rejects FunctionHandle_future. Making workpool's client accept FunctionReference_future would remove them. The step-handle casts in journal.ts stay because the type is only known at runtime.

Compatibility

  • The direct-call onComplete validator runs in apps that define workflows, so those apps need a backend that supports v.function(). This matters for self-hosted deployments.
  • Generated types show workflowId: string for onComplete, because validator JSON can't carry the WorkflowId brand.

Testing

Ran codegen against a dev deployment, then tsc --noEmit, build, lint, the example/convex typecheck, and npm test (129 passed), and reran codegen, typechecks and tests on convex 1.49.0. Checked that the generated types reject a query handle for workflowHandle and onComplete, and a mutation with the wrong args for onComplete.

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@pkg-pr-new

pkg-pr-new Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@convex-dev/workflow@311

commit: 66cc46b

@ianmacartney

ianmacartney commented Oct 27, 2026 via email

Copy link
Copy Markdown
Member

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants