Audit fixes: qualify() helper, docs onboarding, CI hardening, testing coverage#294
Merged
Conversation
Builds the fromPromise qualifier every activity previously hand-wrote: an Error rejection keeps its message and is preserved as cause, with nonRetryable/details/message (non-Error fallback) options. Always wraps so the declared type is guaranteed for retry policies. Dogfooded in the order-processing example, which drops its private helper. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- testing: move @temporalio/client and @temporalio/worker to peer dependencies (their types leak through the public it fixture), drop the phantom config entry from files, add keywords - all packages: declare sideEffects: false for tree-shaking - worker: replace the last explicit any with ChildWorkflowHandle<Workflow>; fix JSDoc examples to ESM-correct imports (.js extensions, workflowsPathFromURL instead of require.resolve) - example: rethrow cancellation in the notification catch so a cancel request cannot be swallowed - rules: correct stale peer-dep table and overrides section Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The testing package had zero tests despite being the harness for all integration suites; extension.ts and global-setup.ts are now covered with mocked Temporal connections/testcontainers. contract's format.ts gets a spec for every path-rendering branch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- all first- and third-party actions pinned to full SHAs (Dependabot's github-actions ecosystem keeps them updated) - the test job now runs a matrix of .node-version (24.x) and 22.19.0, the engines floor declared by the published packages - timeout-minutes on every job; release no longer builds twice (the publish script already runs pnpm build) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- getting-started now compiles as written: qualify() in activities, createWorker + workflowsPathFromURL instead of require.resolve - .js extensions on all relative imports in guide snippets; all require.resolve sites replaced with ESM-safe resolution - installation prerequisites corrected (Node 22.19+, TypeScript 6.0) and the testing package's Vitest 4/ESM/Docker requirements stated - new Testing guide documenting the globalSetup + it.extend wiring - README: full peer-dependency install block, qualify() in the quick example, Stability & Versioning section; migration guides moved to a collapsed sidebar group; stale v0.5.0 claim removed - CONTRIBUTING floors aligned with engines; stray docs/package-lock.json removed Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR applies a broad “audit fixes” pass across temporal-contract, focusing on reducing activity boilerplate via a new qualify() helper, aligning docs/snippets with the repo’s ESM + .js import requirements, strengthening CI, and adding missing test coverage.
Changes:
- Added
qualify(type, options?)to@temporal-contract/worker/activityand updated examples/docs to use it. - Hardened workflows/docs for ESM correctness (
.jsextensions,workflowsPathFromURL(...)vsrequire.resolve), and improved onboarding docs. - Expanded coverage (new unit specs for worker qualify + contract formatters; introduced a Vitest setup + tests for
@temporal-contract/testing) and tightened CI (timeouts, matrix, pinned actions).
Reviewed changes
Copilot reviewed 37 out of 39 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Updates public-facing examples/install instructions to use qualify and peer-dep install guidance. |
| pnpm-lock.yaml | Lockfile updates reflecting dependency/peer-dep reshuffles (notably testing package). |
| packages/worker/src/workflow.ts | Fixes JSDoc snippet imports to be ESM-correct (.js). |
| packages/worker/src/worker.ts | Updates JSDoc to use workflowsPathFromURL and ESM imports. |
| packages/worker/src/child-workflow.ts | Removes internal any in child workflow handle typing. |
| packages/worker/src/activity.ts | Introduces qualify() helper and updates docs/examples within the module. |
| packages/worker/src/activity.spec.ts | Adds test coverage for qualify() behavior. |
| packages/worker/package.json | Declares sideEffects: false for better tree-shaking. |
| packages/testing/vitest.config.ts | Adds Vitest config with coverage + injected testcontainers address. |
| packages/testing/src/global-setup.spec.ts | Adds unit coverage for Vitest globalSetup via mocked testcontainers. |
| packages/testing/src/extension.spec.ts | Adds unit coverage for it fixture extension (mocked Temporal connections). |
| packages/testing/package.json | Adds keywords, sideEffects: false, Vitest scripts, and moves Temporal SDK deps to peers. |
| packages/contract/src/format.spec.ts | Adds tests for formatIssue / summarizeIssues rendering. |
| packages/contract/package.json | Declares sideEffects: false. |
| packages/client/package.json | Declares sideEffects: false. |
| examples/order-processing-worker/src/application/workflows.ts | Ensures workflow cancellation propagates (isCancellation). |
| examples/order-processing-worker/src/application/activities.ts | Dogfoods qualify() to remove repeated ApplicationFailure.create boilerplate. |
| docs/package-lock.json | Removes stray lockfile from docs. |
| docs/guide/worker-usage.md | Updates snippets for ESM .js imports and workflowsPathFromURL. |
| docs/guide/worker-implementation.md | Updates snippets for ESM .js imports. |
| docs/guide/troubleshooting.md | Updates snippets to workflowsPathFromURL and qualify. |
| docs/guide/testing.md | Adds a new testing guide for @temporal-contract/testing. |
| docs/guide/result-pattern.md | Updates imports in snippets to ESM .js. |
| docs/guide/nexus-integration.md | Updates snippets to ESM .js and workflowsPathFromURL. |
| docs/guide/installation.md | Updates prerequisites and adds warnings about testing package requirements. |
| docs/guide/getting-started.md | Updates onboarding snippets to use qualify and ESM-safe workflow path resolution. |
| docs/guide/entry-points.md | Updates workflow path examples to workflowsPathFromURL and .js exports. |
| docs/guide/client-usage.md | Updates snippet imports to ESM .js. |
| docs/guide/activity-handlers.md | Adds qualify guidance and converts examples to use it + ESM .js imports. |
| docs/.vitepress/config.ts | Adds Testing guide nav entry; moves migration guides into a collapsed group. |
| CONTRIBUTING.md | Aligns prerequisites with supported Node/pnpm versions. |
| .github/workflows/release.yml | Adds timeout, pins actions to SHAs, removes redundant build step. |
| .github/workflows/deploy-docs.yml | Adds timeouts and pins actions to SHAs. |
| .github/workflows/ci.yml | Adds timeouts, pins actions, expands test matrix (Node floor), renames artifacts. |
| .github/actions/setup/action.yml | Adds node-version override input; pins setup/cache actions to SHAs. |
| .changeset/qualify-helper.md | Changeset documenting new qualify() helper release. |
| .changeset/audit-fixes.md | Changeset summarizing audit fixes and the testing package breaking change. |
| .agents/rules/handlers.md | Updates handler guidance to mention qualify(). |
| .agents/rules/dependencies.md | Updates peer-dependency policy table and security override guidance. |
Files not reviewed (2)
- docs/package-lock.json: Generated file
- pnpm-lock.yaml: Generated file
Nobody outside this repo consumes @temporal-contract/testing, so the dependency-to-peer reclassification doesn't warrant a major that would drag the whole fixed release group to 7.0.0. The group now lands at 6.1.0 (minor, from the qualify helper). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- extension.spec: assert the client connection is closed via afterAll instead of a follow-up test that assumed execution order - troubleshooting docs: add the workflowsPathFromURL import to the two worker snippets so they are copy/paste-runnable Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
unthrown 4 is incompatible with 3: TaggedError now reserves name and message as payload fields (message is set via Error, not passed as structured data). Migrated all 14 TaggedError-based error classes in client and worker to set this.message after super() with a message-free payload; their public shape (_tag, name, message, typed fields) is unchanged and covered by the existing error specs. Bump the catalog (unthrown + @unthrown/vitest to 4.0.0) and the peer range (^3 -> ^4) in contract, client, and worker. Released as a minor, not a major: no external consumer is pinned to unthrown@3. Stability note in the README updated accordingly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Peer Dependency Warnings section listed the Temporal SDK and zod but omitted unthrown; add it and state that worker/client require it because its Result/AsyncResult types are part of their public API. README now tells consumers to install unthrown explicitly (their own code imports its types) and to pin to v4. Note the v3/v4 incompatibility in both. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The testing package moves @temporalio/client and @temporalio/worker from
dependencies to peerDependencies, which can require consumer action — that's a
minor, not a patch. Bump the audit-fixes changeset accordingly.
Also document qualify()'s flip side: since the wrapper's type/nonRetryable take
precedence, an inner ApplicationFailure's own nonRetryable: true is masked —
pass { nonRetryable: true } (or a custom qualifier) to keep it non-retryable.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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 from a full project audit (code health, security, DX):
New API —
qualify()(worker, minor)qualify(type, options?)builds thefromPromisequalifier, replacing the ~8-lineApplicationFailure.createboilerplate repeated in every activity.Errorrejections keep their message and are preserved ascause;nonRetryable/details/ fallbackmessagesupported. Always wraps so the declaredtypeis guaranteed for retry policies. Dogfooded in the order-processing example.Packages
@temporal-contract/testing:@temporalio/clientand@temporalio/workermoved to peer dependencies — their types leak through the publicitfixture (breaking, see changeset; edit.changeset/audit-fixes.mddown tominorif you consider it non-breaking in practice). Phantomconfigentry dropped fromfiles, keywords added.sideEffects: false; worker's last explicitanyreplaced withChildWorkflowHandle<Workflow>; JSDoc examples fixed to ESM-correct imports.isCancellation) instead of swallowing it in the notification catch.Tests
extension.tsandglobal-setup.tsnow covered (mocked testcontainers/Temporal). New spec forcontract/src/format.ts.CI
timeout-minuteseverywhere; release no longer builds twice.Docs
qualify,createWorker+workflowsPathFromURLinstead ofrequire.resolve);.jsextensions on all ~45 relative snippet imports; 12require.resolvesites replaced.docs/package-lock.jsonremoved.Test plan
pnpm lint/pnpm format/pnpm knipcleanpnpm typecheck— 12/12 taskspnpm test— 9/9 tasks (incl. 6 new testing-package tests, 12 new format tests, 6 new qualify tests)pnpm test:integration— 8/8 tasks against a real Temporal server (Docker)pnpm build+ typedoc regen + VitePress docs build (validates dead links, incl. the new /guide/testing)🤖 Generated with Claude Code