-
Notifications
You must be signed in to change notification settings - Fork 1k
feat: allow wrangler types to run without config file
#11247
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
base: main
Are you sure you want to change the base?
Conversation
Add --compatibility-date and --compatibility-flags arguments to the wrangler types command, making the config file optional. When no config file is detected, the command will: - Use the latest workerd compatibility date by default - Set includeEnv to false (only generate runtime types) - Accept compatibility settings via command-line arguments Co-Authored-By: [email protected] <[email protected]>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
🦋 Changeset detectedLatest commit: 36e79e8 The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
create-cloudflare
@cloudflare/kv-asset-handler
miniflare
@cloudflare/pages-shared
@cloudflare/unenv-preset
@cloudflare/vite-plugin
@cloudflare/vitest-pool-workers
@cloudflare/workers-editor-shared
@cloudflare/workers-utils
wrangler
commit: |
Co-Authored-By: [email protected] <[email protected]>
Co-Authored-By: [email protected] <[email protected]>
| // Get the maximum compatibility date supported by the installed workerd | ||
| const miniflareEntry = require.resolve("miniflare"); | ||
| const miniflareRequire = module.createRequire(miniflareEntry); | ||
| const miniflareWorkerd = miniflareRequire("workerd") as { | ||
| compatibilityDate: string; | ||
| }; | ||
| args.compatibilityDate = miniflareWorkerd.compatibilityDate; | ||
| logger.log( | ||
| `No config file detected. Using the installed Workers runtime's latest supported date: ${args.compatibilityDate}\n` | ||
| ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a utility function for this called getDevCompatibilityDate(). Use that instead
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done! Replaced the manual workerd resolution with getDevCompatibilityDate() in both locations (lines 149-154 and 224-228).
| let config: Config | undefined; | ||
| const secondaryConfigs: Config[] = []; | ||
| if (Array.isArray(args.config)) { | ||
| config = readConfig({ ...args, config: args.config[0] }); | ||
| for (const configPath of args.config.slice(1)) { | ||
| secondaryConfigs.push(readConfig({ config: configPath })); | ||
| let hasConfigFile = false; | ||
|
|
||
| try { | ||
| if (Array.isArray(args.config)) { | ||
| config = readConfig({ ...args, config: args.config[0] }); | ||
| for (const configPath of args.config.slice(1)) { | ||
| secondaryConfigs.push(readConfig({ config: configPath })); | ||
| } | ||
| } else { | ||
| config = readConfig(args); | ||
| } | ||
| } else { | ||
| config = readConfig(args); | ||
|
|
||
| if ( | ||
| config.configPath && | ||
| fs.existsSync(config.configPath) && | ||
| !fs.statSync(config.configPath).isDirectory() | ||
| ) { | ||
| hasConfigFile = true; | ||
| } | ||
| } catch (error) { | ||
| if (args.config) { | ||
| throw error; | ||
| } | ||
| config = undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is all a bit overkill. readConfig() won't throw if no config file exists
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done! Simplified the config reading logic by removing the try-catch block and fs checks. Now using const hasConfigFile = Boolean(config.configPath) to detect if a config file exists (lines 137-146).
| let compatibilityDate = | ||
| args.compatibilityDate ?? config?.compatibility_date; | ||
| const compatibilityFlags = | ||
| args.compatibilityFlags?.map(String) ?? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't need a .map(String)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done! Removed .map(String) and used a type assertion instead: compatibilityFlags as string[] (lines 229-230 and 235).
| if (!compatibilityDate) { | ||
| const miniflareEntry = require.resolve("miniflare"); | ||
| const miniflareRequire = module.createRequire(miniflareEntry); | ||
| const miniflareWorkerd = miniflareRequire("workerd") as { | ||
| compatibilityDate: string; | ||
| }; | ||
| compatibilityDate = miniflareWorkerd.compatibilityDate; | ||
| if (hasConfigFile) { | ||
| logger.warn( | ||
| `No compatibility_date was specified. Using the installed Workers runtime's latest supported date: ${compatibilityDate}` | ||
| ); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this point there should always be a compat date. Remove this check
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done! Removed the entire if (!compatibilityDate) check since getDevCompatibilityDate() now guarantees a compatibility date is always returned (lines 224-228).
- Use getDevCompatibilityDate() utility instead of manual workerd resolution - Simplify config reading by removing unnecessary try-catch and fs checks - Remove .map(String) from compatibilityFlags (use type assertion instead) - Remove redundant if (!compatibilityDate) check - Remove unused node:module import Co-Authored-By: [email protected] <[email protected]>
- Add type assertion to handle yargs array type (string | number)[] - Ensure compatibilityFlags is typed as string[] for getNodeCompat() - Provide default empty array when compatibilityFlags is undefined Co-Authored-By: [email protected] <[email protected]>
This PR allows the
wrangler typescommand to run without requiring a Wrangler config file, addressing a common pain point for developers who want to generate runtime types without a full project setup.Changes
Added two new command-line arguments:
--compatibility-date: Specifies the compatibility date for runtime types (defaults to the latest date supported by the installed workerd)--compatibility-flags: Specifies compatibility flags for runtime typesWhen no config file is detected:
--compatibility-dateis not provided--include-envis automatically set to false (only runtime types are generated, not project-specific environment types)Key Implementation Details
Config file detection: The handler now wraps config reading in a try-catch block. If no config is explicitly specified via
-c, missing config files are treated as "no config" rather than an error.Fallback chain: For compatibility settings, the code follows this priority:
--compatibility-date,--compatibility-flags)Type safety: Added proper handling for
configbeingundefinedthroughout the handler using optional chaining.Backward compatibility: When a user explicitly specifies a config file with
-cthat doesn't exist, the command still errors as before.Testing
Added 4 new test cases covering:
--compatibility-dateis provided--compatibility-flagsargument without configincludeEnvis set to false when no config existsAll 49 existing tests continue to pass.
Areas for Review
Type coercion on line 247-248 and 293-295: Using
.map(String)to convert yargs'(string | number)[]tostring[]. This is duplicated in two places - consider if this should be extracted to a helper.Behavior change for configs without compatibility_date: Previously this would error in
generateRuntimeTypes. Now it falls back to the default workerd date with a warning (lines 251-261). This is a breaking change that should be documented.Config detection logic (lines 137-159): Verify the logic correctly distinguishes between "no config file found" vs "user explicitly specified a config file that doesn't exist".
Optional chaining throughout: Ensure all code paths properly handle
configbeingundefined, especially ingenerateEnvTypesand when accessingconfig.configPath.Link to Devin run: https://app.devin.ai/sessions/d05913dfe4fc454cbcd10f3734baeb68
Requested by: [email protected]
wrangler types --help