refactor: scaffold the per-command tap registry (8)#34190
Open
davidr-cy wants to merge 4 commits into
Open
Conversation
Restructure the monolithic commands.ts into a commands/ module: the defineCommand authoring helper and TapCommandError move to definition.ts, the health command to health.ts, and the registry itself to index.ts. The TapManager gains the domain-failure (TapCommandError) catch and exec-args coercion gets its own spec. This is the foundation the per-command modules (specs, run, tests, commands) register into.
1 task
The app re-exported the shared tap contract from the compiled CJS build (`@packages/runner-discovery/dist/tap-contract`). Because the workspace package resolves through a symlink to a realpath outside node_modules, Vite's commonjs transform skips it during the app build and Rollup treats the CJS file as ESM, failing with "TAP_PROTOCOL_VERSION is not exported". Re-export from the zero-dependency TypeScript source (`lib/tap-contract`) instead, matching how the app consumes every other sibling package. The CLI keeps reading the same contract from the package's CJS build.
cypress
|
||||||||||||||||||||||||||||||||||||||||
| Project |
cypress
|
| Branch Review |
davidr/feat/tap-cli/tap-command-registry
|
| Run status |
|
| Run duration | 19m 27s |
| Commit |
|
| Committer | David Rowe |
| View all properties for this run ↗︎ | |
| Test results | |
|---|---|
|
|
0
|
|
|
9
|
|
|
1133
|
|
|
0
|
|
|
27516
|
| View all changes introduced in this branch ↗︎ | |
UI Coverage
64%
|
|
|---|---|
|
|
27
|
|
|
48
|
Accessibility
99.01%
|
|
|---|---|
|
|
0 critical
3 serious
1 moderate
0 minor
|
|
|
18
|
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.
Additional details
This PR scaffolds the command registry on the app side of the
cypress tapfeature — the single source of truth that both halves of the binding contract derive from. It sits between the runner binding (TapManager, below) and the per-command implementations (specs/run/tests, in the stacked PRs above):getSchema()serializes the registry to advertise commands to the CLI, andexecdispatches by name into it. Adding a subcommand becomes one sibling module plus one registry entry.packages/app/src/runner/tap/commands/). Newcommands/directory holds the registry.index.tsexportstapCommands— asatisfies Record<string, TapCommandDefinition>map thatgetSchema()serializes andexecdispatches against.definition.tsprovides thedefineCommandauthoring helper: it capturesparams/optionsas literal types (viaconsttype params) and derives the handler signature from them, so a handler is type-checked against its own schema with no annotations (a required{ name: 'spec', type: 'string' }param yieldsparams.spec: string). The first real command,health, lands ascommands/health.ts, replacing the inlinecommands.tsthat previously held it.definition.ts+tap-manager.ts). NewTapCommandErroris the sanctioned way for a handler to report a domain failure — a command that ran but could not do what was asked (no run mounted, no test with that id, no spec at that path).execnow wraps the handler call: aTapCommandErroris turned into an{ ok: false, code, message }envelope (same downstream path as dispatch failures — rendered on stderr, exit non-zero), while any other throw still escapes as a binding bug. Command-defined codes (e.g.NO_RUN,TEST_NOT_FOUND) are deliberately NOT enumerated in the frozen contract, so the envelope'scodewidens from a closed union to an openstring.contract.ts). Documents the cross-process binding surface (getSchema/exec), the JSON round-trip requirement, and the version-bump rule.TapExecFailureCodeis renamed to the more preciseTapExecDispatchFailureCode(the reserved dispatch-level codes), and per-command result shapes (HealthResult) move out of the frozen contract to live with their command incommands/<name>.ts. Adds aTapCommandOptionSchemadoc and the--name/-aoption shape.tap-manager.ts). Command lookup usesObject.prototype.hasOwnProperty.callso a wire-supplied name likeconstructorcannot resolve to a prototype member.@packages/runner-discovery). The cross-process contract was previously hand-mirrored between the app'scontract.tsandcli/lib/tap/contract.ts. This PR moves the shared surface —TAP_PROTOCOL_VERSION, the binding global-name + method-name constants, and theTapCommandParamSchema/OptionSchema/TapSchema/TapExecResulttypes — into a new pure, import-freepackages/runner-discovery/lib/tap-contract.ts, alongside the existing runner-discovery contract that already eliminates server↔CLI hand-mirroring.cli/lib/tap/contract.tsis deleted and the CLI imports from the package root; the app'scontract.tsbecomes a thin re-export shim that keeps only the app-onlyTapBindingContractandTapExecDispatchFailureCode. To keep nodepathout of the app's Vite browser bundle, the app imports the path-free module via a deep-dist entry (@packages/runner-discovery/dist/tap-contract) rather than the package root.Steps to test
App-side binding logic covered by component specs (
cypress:run:ct). New/updated specs:packages/app/src/runner/tap/exec-args.cy.ts— new spec for raw-string → typed coercion of params and options against the schema (required vs. optional, boolean defaulting, type rejection).packages/app/src/runner/tap/tap-manager.cy.ts— updated for the registry-drivengetSchema()serialization andexecdispatch, includingTapCommandError→ok: falseenvelope mapping and the own-property command lookup.The contract move is type-level and verified by the builds:
yarn workspace @packages/runner-discovery build && test,yarn workspace @packages/app check-ts, and the CLI rollup build (cd cli && yarn build) all pass.Manual end-to-end is exercised by the top wiring layer (#34148): start a Cypress instance, open a browser, and run
cypress tap healthto drive a registry command through the binding.How has the user experience changed?
No change. This is an internal refactor of the experimental tap binding's app-side structure; it adds no new user-facing command or flow.
cypress tap healthbehaves exactly as before — only the code that backs it was reorganized into the registry.PR Tasks
cypress-documentation?type definitions?Note
Low Risk
Internal experimental tap scaffolding with no user-facing behavior change; contract consolidation is mostly type-level and covered by existing CLI/app tests.
Overview
Refactors the experimental
cypress tapapp binding around acommands/registry (tapCommands,defineCommand,healthas the first module) thatgetSchemaandexecboth use, replacing the monolithiccommands.ts.TapCommandErroris the sanctioned domain failure path:TapManager.execmaps it to{ ok: false, code, message }while other handler throws still propagate. Command lookup uses own-property checks so names likeconstructorcannot hit the prototype.The CLI–app wire contract (protocol version, binding constants, schema types,
TapExecResult) moves into@packages/runner-discovery/lib/tap-contract.ts; the CLI imports from the package root and the duplicatedcli/lib/tap/contractis removed. The appcontract.tsre-exports the shared surface and keeps app-onlyTapBindingContract/ dispatch failure codes.Tests: new
exec-args.cy.ts;tap-manager.cy.tsupdated for registry dispatch,TapCommandError, and hardened lookup.Reviewed by Cursor Bugbot for commit 05fe25b. Bugbot is set up for automated code reviews on this repo. Configure here.