Skip to content

Added basic PZ commands#86

Open
burstw0w wants to merge 18 commits into
BunnyWay:mainfrom
burstw0w:pullzone-commands
Open

Added basic PZ commands#86
burstw0w wants to merge 18 commits into
BunnyWay:mainfrom
burstw0w:pullzone-commands

Conversation

@burstw0w
Copy link
Copy Markdown

@burstw0w burstw0w commented Jun 2, 2026

Right now, you can do:

pz select - selects a pullzone, keeping it in context so all the other commands can be ran without specifying ID/name
pz deselect - removes context (this might not be needed, as you dont have that for your db commands)
pz create - creates a pullzone, accepts two params and those are [name] [origin url]
pz delete - deletes pullzone (if you don't use name, it will ask you if you want to delete the current zone that is in the context)
pz purge - purges pullzone (again, if you dont specify the name, uses context)
pz show - shows info about pullzone
pz list - lists your available pullzones
pz clone - clones your pullzone

Tested everything with bun run

@bogdan-at-bunny
Copy link
Copy Markdown

@codex review

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jun 2, 2026

⚠️ No Changeset found

Latest commit: f69b0f5

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

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 54b9cbc720

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/cli/src/commands/pz/clone.ts Outdated
Comment thread packages/cli/src/commands/pz/delete.ts Outdated
Comment thread packages/cli/src/commands/pz/index.ts Outdated
Comment thread packages/cli/src/commands/pz/clone.ts Outdated
Comment thread packages/cli/src/commands/pz/resolve-pullzone.ts Outdated
Comment thread packages/cli/src/commands/pz/resolve-pullzone.ts Outdated
@burstw0w
Copy link
Copy Markdown
Author

burstw0w commented Jun 2, 2026

@bogdan-at-bunny Resolved all the issues codex found. Can you run it again?

Copy link
Copy Markdown
Member

@jamie-at-bunny jamie-at-bunny left a comment

Choose a reason for hiding this comment

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

Hey @burstw0w, appreciate the PR and enthusiasm here ❤️

It's a solid first pass. I appreciate the thought of keeping existing patterns in other commands here in this one.

That said, we should cut the scope back to "billy basic". I would drop clone, use id instead of name sugar+magic, and use the type system we already have to ensure end to end type safety as much as possible. This will result in less code added, and more predictable results. We're planning to add a project schema soon where a Project schema owns multiple PZs, at which point name based lookups get ambiguous and the manifest likely needs to carry project context too. Let's anchor on the stable IDs now, and provide the link/unlink methods for single PZ contexts.

I left a few raw comments as I went through the code. Apologies for the delay in reviewing, my focus is purely on scripts and apps at the moment (and storage next), amongst other things.

Comment thread packages/cli/src/commands/pz/create.ts Outdated
type PullZoneManifest,
} from "./constants.ts";

interface PullZone {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'd prefer we didn't new interfaces and used what we could from the OpenAPI Spec, components["schemas"]["PullZoneModel"] should have what's needed here.

Name?: string | null;
}

interface CreateArgs {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

components["schemas"]["EdgeRuleV2Model"] should be used inline instead of declaring here, at worst, we can Pick from here, although I'd rather not limit scope and use the input type as is, which allows us to spread on more options.

Comment thread packages/cli/src/commands/pz/clone.ts Outdated
Comment thread packages/cli/src/commands/pz/clone.ts Outdated
Comment thread packages/cli/src/commands/pz/create.ts Outdated
Comment thread packages/cli/src/commands/pz/create.ts Outdated
const createSpin = spinner("Creating pull zone...");
createSpin.start();

await client.POST("/pullzone", {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What happens here if there is an error from the API?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Rewrote process of creating PZ completely, it now has a check for that as well.

Comment thread packages/cli/src/commands/pz/purge.ts Outdated
const spin = spinner("Purging cache...");
spin.start();

await client.POST("/pullzone/{id}/purgeCache", {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What happens with any error/response from the API here? Network or response error.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Nothing, you are correct.

Added a check that will print an error if there is any.

Comment thread packages/cli/src/commands/pz/clone.ts Outdated
Comment thread packages/cli/src/commands/pz/clone.ts Outdated
Comment thread packages/cli/src/commands/pz/clone.ts Outdated
@burstw0w
Copy link
Copy Markdown
Author

burstw0w commented Jun 3, 2026

Scaled everything down a bit, and implemented most of fixes requested by @jamie-at-bunny

@jamie-at-bunny
Copy link
Copy Markdown
Member

@greptile-apps review

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Jun 4, 2026

Greptile Summary

This PR introduces the pz (pull zone) command namespace with seven sub-commands: list, create, delete, link, unlink, purge, and show. The commands follow the existing db namespace conventions — manifest-based context, spinner feedback, JSON output mode, and UserError for user-facing errors.

  • list, create, purge, delete, unlinkdelete and purge correctly use { data, error } destructuring; list silently swallows GET errors (prior thread); create uses as any body cast and an inline response type instead of generated schema types (prior thread).
  • show and link (id path) — both wrap the openapi client call in a try/catch, but openapi-fetch returns HTTP errors in { error } rather than throwing; auth failures and 5xx responses are therefore misreported as "pull zone not found" instead of the real error.
  • link (interactive path)GET /pullzone error is silently swallowed (prior thread); cancellation correctly returns without a non-zero exit code.

Confidence Score: 4/5

Safe to merge with the try/catch error-handling fix applied to show.ts and link.ts; all other issues are already tracked in prior review threads.

In show.ts and the id path of link.ts, the openapi client's HTTP errors land in the { error } field and are never inspected — the try/catch only catches true network exceptions. A 401 or 5xx response leaves zone undefined and the user receives a misleading 'not found' message instead of the real failure reason.

packages/cli/src/commands/pz/show.ts and packages/cli/src/commands/pz/link.ts (id path) need the try/catch replaced with { data, error } destructuring, matching the pattern already used in delete.ts.

Important Files Changed

Filename Overview
packages/cli/src/commands/pz/show.ts Adds pz show command; try/catch around openapi client call won't intercept HTTP errors (401, 5xx), causing auth/server failures to surface as a misleading 'not found' message.
packages/cli/src/commands/pz/link.ts Adds pz link command; same try/catch error-handling bug as show.ts in the id-path branch; interactive path's GET /pullzone error is already flagged in prior threads.
packages/cli/src/commands/pz/delete.ts Adds pz delete command; correctly uses { data, error } destructuring for both GET and DELETE calls; confirmation and manifest cleanup logic look correct.
packages/cli/src/commands/pz/create.ts Adds pz create; error handling and spinner usage are correct; as any body cast and inline response type (flagged in prior threads) bypass generated schema types.
packages/cli/src/commands/pz/list.ts Adds pz list; does not destructure error from GET /pullzone (flagged in prior thread); otherwise structurally sound.
packages/cli/src/commands/pz/purge.ts Adds pz purge; correctly destructures { error } from POST and surfaces it as a UserError; no issues found.
packages/cli/src/commands/pz/unlink.ts Adds pz unlink; simple manifest removal with JSON output support; no issues found.
packages/cli/src/commands/pz/index.ts Registers the pz namespace with all seven sub-commands; pz clone described in PR description but not implemented (flagged in prior thread).
packages/cli/src/commands/pz/constants.ts Defines PULL_ZONE_MANIFEST constant and PullZoneManifest interface; clean and minimal.
packages/cli/src/cli.ts Registers pzNamespace into the top-level CLI command list; one-line import and one-line registration, no issues.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    CLI["bunny pz"] --> LIST["pz list\nGET /pullzone"]
    CLI --> CREATE["pz create name origin\nPOST /pullzone"]
    CLI --> DELETE["pz delete [id]\nGET + DELETE /pullzone/{id}"]
    CLI --> LINK["pz link [id]"]
    CLI --> UNLINK["pz unlink"]
    CLI --> PURGE["pz purge [id]\nPOST /pullzone/{id}/purgeCache"]
    CLI --> SHOW["pz show [id]\nGET /pullzone/{id}"]
    LINK -->|id supplied| LINK_ID["GET /pullzone/{id}\ntry/catch only"]
    LINK -->|interactive| LINK_INT["GET /pullzone\nselect prompt"]
    SHOW --> SHOW_GET["GET /pullzone/{id}\ntry/catch only"]
    DELETE --> DEL_GET["GET /pullzone/{id}\n{ data, error } check"]
    DEL_GET --> CONFIRM["confirm prompt"]
    CONFIRM -->|ok| DEL_DELETE["DELETE /pullzone/{id}"]
    DEL_DELETE --> MANIFEST_RM["removeManifest if linked"]
    CREATE --> CREATE_POST["POST /pullzone\n{ data, error } check"]
    CREATE_POST --> MANIFEST_OPT["offer saveManifest"]
    LINK_INT --> MANIFEST_SAVE["saveManifest pullzone.json"]
    LINK_ID --> MANIFEST_SAVE
    UNLINK --> MANIFEST_DEL["removeManifest pullzone.json"]
Loading

Fix All in Claude Code

Reviews (8): Last reviewed commit: "Added error catch" | Re-trigger Greptile

Comment thread packages/cli/src/commands/pz/index.ts
Comment thread packages/cli/src/commands/pz/constants.ts Outdated
Comment on lines +48 to +57
const { data, error } = await client.POST("/pullzone", {
body: { Name: name, OriginUrl: url } as any,
});

createSpin.stop();

if (error) {
throw new UserError(`Failed to create pull zone: ${error}`);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 as any cast and inline type instead of generated schema types

The POST body is cast with as any and the response is typed with an inline { Id?: number; Name?: string | null } rather than using Pick<components["schemas"]["PullZone"], ...> from @bunny.net/openapi-client/generated/core.d.ts. CLAUDE.md explicitly requires: "Prefer generated schema types over inline primitives. Only fall back to string, any, or number when no generated type exists." Both casts bypass compile-time safety, so a field rename in the spec would silently break this command.

Context Used: CLAUDE.md (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Claude Code

Comment thread packages/cli/src/commands/pz/link.ts Outdated
Comment thread packages/cli/src/commands/pz/show.ts Outdated
Comment on lines +1 to +25
import { defineNamespace } from "../../core/define-namespace.ts";
import { pzCreateCommand } from "./create.ts";
import { pzDeleteCommand } from "./delete.ts";
import { pzLinkCommand } from "./link.ts";
import { pzListCommand } from "./list.ts";
import { pzPurgeCommand } from "./purge.ts";
import { pzShowCommand } from "./show.ts";
import { pzUnlinkCommand } from "./unlink.ts";

// TODO: implement rules and hostnames subcommands
// const rulesNamespace = defineNamespace("rules", "Manage pull zone edge rules.", [...]);
// const hostnamesNamespace = defineNamespace("hostnames", "Manage pull zone hostnames.", [...]);

export const pzNamespace = defineNamespace(
"pz",
"Manage pull zones.",
[
pzListCommand,
pzCreateCommand,
pzDeleteCommand,
pzLinkCommand,
pzPurgeCommand,
pzShowCommand,
pzUnlinkCommand,
],
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 README.md and AGENTS.md not updated

CLAUDE.md explicitly requires: "When adding, changing, or removing commands or flags, update the corresponding sections in README.md — user-facing command docs and examples. AGENTS.md — architecture docs, command reference tree, and file listing." The new pz namespace and its seven sub-commands are absent from both documents.

Context Used: CLAUDE.md (source)

Fix in Claude Code

Comment thread packages/cli/src/commands/pz/link.ts
Comment on lines +28 to +32
const { data } = await client.GET("/pullzone");

spin.stop();

const zones = ((data ?? []) as PullZone[]).sort((a: PullZone, b: PullZone) =>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 API error silently swallowed — misleading empty-list output

client.GET("/pullzone") returns { data, error } but only data is destructured. When the request fails (invalid API key, network error, server 5xx), data is undefined, so zones becomes [] and the command prints "No pull zones found." instead of surfacing the real error. The same pattern appears in the interactive path of link.ts at the equivalent GET /pullzone call — both should destructure and check error.

Fix in Claude Code

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Shouldn't middleware throw every non ok response before destructuring? I mostly transferred my golang code to ts, but i've been trying to do stuff like you do it in db. I might have missed something

@burstw0w burstw0w requested a review from jamie-at-bunny June 5, 2026 13:51
Comment thread packages/cli/src/commands/pz/delete.ts Outdated
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.

3 participants