Skip to content

thomasgauvin: support automatic updates of wrangler.jsonc when creating a new resource in a worker project #9816

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

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

thomasgauvin
Copy link
Contributor

@thomasgauvin thomasgauvin commented Jul 1, 2025

addresses #9730

  1. Only support wrangler.jsonc. Supports KV, R2, D1, Hyperdrive, Vectorize
  2. Make updating wrangler.jsonc optional, interactive, logs to console otherwise
  3. Provide a flag to permit updating wrangler.jsonc from initial command line (--update-config)
  4. Try to add binding and add _2, _3... to binding variable in event of conflict
  5. Don't support auto-adding preview KV namespaces
  6. Preserves comments and structure of wrangler.jsonc

@thomasgauvin thomasgauvin self-assigned this Jul 1, 2025
@thomasgauvin thomasgauvin requested review from a team as code owners July 1, 2025 22:13
Copy link

changeset-bot bot commented Jul 1, 2025

⚠️ No Changeset found

Latest commit: 86b763f

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

pkg-pr-new bot commented Jul 1, 2025

create-cloudflare

npm i https://pkg.pr.new/create-cloudflare@9816

@cloudflare/kv-asset-handler

npm i https://pkg.pr.new/@cloudflare/kv-asset-handler@9816

miniflare

npm i https://pkg.pr.new/miniflare@9816

@cloudflare/pages-shared

npm i https://pkg.pr.new/@cloudflare/pages-shared@9816

@cloudflare/unenv-preset

npm i https://pkg.pr.new/@cloudflare/unenv-preset@9816

@cloudflare/vite-plugin

npm i https://pkg.pr.new/@cloudflare/vite-plugin@9816

@cloudflare/vitest-pool-workers

npm i https://pkg.pr.new/@cloudflare/vitest-pool-workers@9816

@cloudflare/workers-editor-shared

npm i https://pkg.pr.new/@cloudflare/workers-editor-shared@9816

wrangler

npm i https://pkg.pr.new/wrangler@9816

commit: 86b763f

Comment on lines 142 to 143
// Generate a unique binding name that doesn't conflict
const bindingName = generateUniqueBindingName(config, resource);
Copy link
Member

Choose a reason for hiding this comment

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

Why do we want to generate the binding name in this way?

Couldn't we just add another interactive question asking the user for what binding name they'd like to use? 🤔

(then check the config file to make sure there isn't a conflict)

Basically what I was thinking was something along the lines of for example:

Would you like to update the wrangler.jsonc file with the new KV Namespace binding? … yes
What binding name would you like to use? MY_KV
Updated wrangler.jsonc with new KV Namespace binding: MY_KV (my-kv, ID: 6d2dd6ae297441688c8376c43e4360d6)

Potentially with an error/or other questions in case there are conflicts

I don't think that just creating the binding with generic names is very polished 🤔

Copy link
Contributor Author

@thomasgauvin thomasgauvin Jul 2, 2025

Choose a reason for hiding this comment

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

using generic names is what we often have in docs/dashboard, and it's faster, so i wanted to match that. how about I default to generic and allow writing a custom binding?

Copy link
Member

Choose a reason for hiding this comment

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

using generic names is what we often have in docs/dashboard

Yeah, but there (especially in the docs) aren't really dealing with the user specific configs so it does make sense to use a generic naming 🤔

how about I default to generic and allow writing a custom binding?

Sorry what do you mean by allowing writing a custom binding?

Copy link
Member

Choose a reason for hiding this comment

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

PS: to be clear I don't think that using a generic binding name is terrible, I just think that not doing so would provide a better DX for our users

@@ -80,6 +80,11 @@ export const kvNamespaceCreateCommand = createCommand({
type: "boolean",
describe: "Interact with a preview namespace",
},
"update-config": {
Copy link
Member

Choose a reason for hiding this comment

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

Again I don't think this feels very polished and I would suggest to have something different, for example a flag config-binding-name that once set to a string it adds a binding with such name to the wrangler config (+ naming conflict to either error or create a new unique name)

For example:

npx wrangler kv namespace create my-kvvvv3 --config-binding-name MY_KV

Creating namespace with title "my-kv"
Success!
Updated wrangler.jsonc with new KV Namespace binding: MY_KV (my-kv, ID: 3e22ff5cbc63489984343bca4b825fe4)

Copy link
Member

@dario-piotrowicz dario-piotrowicz left a comment

Choose a reason for hiding this comment

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

Thanks for the PR 🙂

Code wise I think some things need to be polished also more testing (fixtures) will be needed anyways for now I just left some comments regarding the DX, I don't think it's very polished to just create the bindings names for the user and that we should instead ask the user what names they do want to use instead

@thomasgauvin thomasgauvin marked this pull request as draft July 3, 2025 04:47
@thomasgauvin
Copy link
Contributor Author

Thanks @dario-piotrowicz for the feedback & insights, I've started to address the DX ideas (interactive + config-binding-name) so am converting this to a draft PR for now

…n, added interactive prompting for binding name
updateJsonConfig(config.configPath!, resource, config);
} else {
// Show snippet only
const envString = args.env ? ` under [env.${args.env}]` : "";
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks unused?

}
}

export function updateJsonConfig(
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you please add JSDoc to this function?

Comment on lines +99 to +102
if (binding.binding && typeof binding.binding === "string") {
if (binding.binding.toUpperCase() === normalizedName) {
return true;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Collapse the 2 conditions?

				if (binding.binding && typeof binding.binding === "string" && binding.binding.toUpperCase() === normalizedName) {
						return true;
					}

I don't think binding.binding is needed with the typeof?

				if (typeof binding.binding === "string" && binding.binding.toUpperCase() === normalizedName) {
						return true;
					}


const validation = validateBindingName(config, bindingName);
if (validation.valid) {
isValid = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you need isValid here or can you while(true) and return bindingName; here?

*/
export async function handleResourceBindingAndConfigUpdate(
args: { configBindingName?: string; env?: string },
config: RawConfig & { configPath?: string },
Copy link
Contributor

Choose a reason for hiding this comment

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

Looking at the calls outside of tests, I see

{ ...config, configPath: config.configPath },

Would it make sense for configPath to be a distinct parameter?


// We now have a valid binding name. We can use it to update the wrangler.jsonc config.
if (resource.binding) {
updateJsonConfig(config.configPath!, resource, config);
Copy link
Contributor

Choose a reason for hiding this comment

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

config.configPath! -> should the value be required instead of optional ?

config: RawConfig
) {
// Read the original file content to preserve formatting and comments
const originalContent = readFileSync(configPath);
Copy link
Contributor

@vicb vicb Jul 3, 2025

Choose a reason for hiding this comment

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

nit: use async version? (also for write)

config.configPath
)

// Handle binding name and config update using unified utility
Copy link
Contributor

Choose a reason for hiding this comment

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

I love to see code comments and I must say you have done a great job in this PR!
But (nit) this one does not look to add value over the fn name?

Suggested change
// Handle binding name and config update using unified utility

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Untriaged
Development

Successfully merging this pull request may close these issues.

3 participants