Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

defineCommand util #6526

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open

defineCommand util #6526

wants to merge 29 commits into from

Conversation

RamIdeas
Copy link
Contributor

@RamIdeas RamIdeas commented Aug 19, 2024

What this PR solves / how to test

Fixes DEVX-1377 DEVX-1367

This PR introduces a thin abstraction around yargs to improve wrangler's CLI command registration with 3 utilities:

  1. defineCommand: define an absolute command (wrangler [..namespace] subcommand) – satisfying the typescript compiler will ensure all necessary info is provided (description, status, owner, args, handler, etc...)
  2. defineNamespace: define an absolute command namespace (wrangler <..namespace>) – satisfying the typescript compiler will ensure all necessary info is provided (description, status, owner, etc...)
  3. defineAlias: define an alias from any absolute command to any other absolute command. Optionally, override metadata (eg description, status, deprecated, hidden, etc...).

Implementation details:
These 3 core utils are in src/core/define-commands. They simply push the definition into a flat array of all definitions.

In src/core/register-commands, a tree is built from the flat list and is validated, and exposes utils to register commands with yargs: register.registerAllCommands, register.registerNamespace (the latter of which is needed to register commands in the same order as the existing implementation).

Before registering the commands, the definitions are wrapped with src/core/wrap-commands to provide centralised behaviour and transforms the definition into something more friendly to pass to yargs.

Addressed:

  • current contrib experience starts with copy/paste
  • leading to inconsistencies
  • required knowledge of yargs (not obvious)

Wins:

  • ensure subtleties of command generation are handled consistently, centrally
    • subhelp by default
    • deprecated messaging handled
    • status (experimental, alpha, beta, etc) messaging handled
    • easier definition of args sharing arg definitions (as plain objects)
  • less random yargs builder functions importing them across multiple files
    • removed alias complexity
  • less complex yargs generic types
  • less naming fatigue export/import chains
    • move code where it makes sense, not where yargs makes you
  • declarative interface with types such that any missing info is caught by type checking
    • PR reviews can focus on implementation and not usage of yargs
  • definitions separated from the registration
    • module graph simplified
    • enabling test improvements in future

Author has addressed the following

  • Tests
    • TODO (before merge)
    • Included
    • Not necessary because:
  • E2E Tests CI Job required? (Use "e2e" label or ask maintainer to run separately)
    • I don't know
    • Required / Maybe required
    • Not required because:
  • Changeset (Changeset guidelines)
    • TODO (before merge)
    • Included
    • Not necessary because: no user facing changes
  • Public documentation
    • TODO (before merge)
    • Cloudflare docs PR(s):
    • Not necessary because: internal change

Copy link

changeset-bot bot commented Aug 19, 2024

⚠️ No Changeset found

Latest commit: ca3f113

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@penalosa penalosa linked an issue Aug 21, 2024 that may be closed by this pull request
Copy link
Contributor

github-actions bot commented Aug 21, 2024

A wrangler prerelease is available for testing. You can install this latest build in your project with:

npm install --save-dev https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/11123028091/npm-package-wrangler-6526

You can reference the automatically updated head of this PR with:

npm install --save-dev https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/prs/6526/npm-package-wrangler-6526

Or you can use npx with this latest build directly:

npx https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/11123028091/npm-package-wrangler-6526 dev path/to/script.js
Additional artifacts:
npx https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/11123028091/npm-package-create-cloudflare-6526 --no-auto-update
npm install https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/11123028091/npm-package-cloudflare-kv-asset-handler-6526
npm install https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/11123028091/npm-package-miniflare-6526
npm install https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/11123028091/npm-package-cloudflare-pages-shared-6526
npm install https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/11123028091/npm-package-cloudflare-vitest-pool-workers-6526
npm install https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/11123028091/npm-package-cloudflare-workers-editor-shared-6526
npm install https://prerelease-registry.devprod.cloudflare.dev/workers-sdk/runs/11123028091/npm-package-cloudflare-workers-shared-6526

Note that these links will no longer work once the GitHub Actions artifact expires.


[email protected] includes the following runtime dependencies:

Package Constraint Resolved
miniflare workspace:* 3.20240925.0
workerd 1.20240925.0 1.20240925.0
workerd --version 1.20240925.0 2024-09-25

Please ensure constraints are pinned, and miniflare/workerd minor versions match.

packages/wrangler/CONTRIBUTING.md Outdated Show resolved Hide resolved
packages/wrangler/src/core/teams.d.ts Outdated Show resolved Hide resolved
@RamIdeas RamIdeas force-pushed the register-command branch 4 times, most recently from 8209c19 to c17ca68 Compare September 6, 2024 14:43
@RamIdeas RamIdeas added the e2e Run e2e tests on a PR label Sep 6, 2024
@RamIdeas RamIdeas marked this pull request as ready for review September 6, 2024 16:27
@RamIdeas RamIdeas requested a review from a team as a code owner September 6, 2024 16:27
packages/wrangler/CONTRIBUTING.md Show resolved Hide resolved
packages/wrangler/CONTRIBUTING.md Outdated Show resolved Hide resolved
packages/wrangler/CONTRIBUTING.md Outdated Show resolved Hide resolved
packages/wrangler/CONTRIBUTING.md Outdated Show resolved Hide resolved
packages/wrangler/CONTRIBUTING.md Outdated Show resolved Hide resolved
packages/wrangler/CONTRIBUTING.md Outdated Show resolved Hide resolved
packages/wrangler/CONTRIBUTING.md Show resolved Hide resolved
packages/wrangler/CONTRIBUTING.md Outdated Show resolved Hide resolved
packages/wrangler/CONTRIBUTING.md Show resolved Hide resolved
packages/wrangler/CONTRIBUTING.md Outdated Show resolved Hide resolved
packages/wrangler/src/core/define-command.ts Show resolved Hide resolved
packages/wrangler/src/core/define-command.ts Outdated Show resolved Hide resolved
packages/wrangler/src/core/define-command.ts Show resolved Hide resolved
packages/wrangler/src/core/define-command.ts Show resolved Hide resolved
packages/wrangler/src/core/define-command.ts Outdated Show resolved Hide resolved
packages/wrangler/src/core/register-commands.ts Outdated Show resolved Hide resolved
packages/wrangler/src/core/register-commands.ts Outdated Show resolved Hide resolved
packages/wrangler/src/core/register-commands.ts Outdated Show resolved Hide resolved
packages/wrangler/src/core/wrap-command.ts Outdated Show resolved Hide resolved

statusMessage =
def.metadata.statusMessage ??
`🚧 \`${def.command}\` is a ${def.metadata.status} command. Please report any issues to https://github.com/cloudflare/workers-sdk/issues/new/choose`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, but a won't always be appropriate here (e.g. is a alpha command)

wrangler.command("kv", `🗂️ Manage Workers KV Namespaces`, (kvYargs) => {
return registerKvSubcommands(kvYargs, subHelp);
});
register.registerNamespace("kv");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this be better named commands?:

commands.registerNamespace("kv");

is more descriptive.

packages/wrangler/src/core/register-commands.ts Outdated Show resolved Hide resolved
packages/wrangler/src/core/register-commands.ts Outdated Show resolved Hide resolved
packages/wrangler/src/core/register-commands.ts Outdated Show resolved Hide resolved
Comment on lines 131 to 140
export const COMMAND_DEFINITIONS: Array<
CommandDefinition | NamespaceDefinition | AliasDefinition
> = [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering this too. What if they're used in multiple places, like in separate isolated packages?

To avoid any potential issues with shared state, and to make it more portable, we could create an index file here and export functions with closed state:

export const { defineCommand, defineNamespace, defineAlias } = createCommandDefineFns(); // terrible name...

This could then be created in each package where we want to isolate this behaviour, or could be used in the main wrangler package just as we're doing here in kv.

Copy link
Contributor

@andyjessop andyjessop left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great work. I love the way that commands are searchable by their string value, and the args validation is extracted from the handler.

});
```

2. Command specific (named positional) args vs Shared args vs Global args
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
2. Command specific (named positional) args vs Shared args vs Global args
2. Command-specific (named positional) args vs shared args vs global args

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
e2e Run e2e tests on a PR
Projects
Status: Approved
Development

Successfully merging this pull request may close these issues.

Establish source of truth for beta commands
4 participants