@@ -2,159 +2,160 @@ import * as fs from "node:fs";
22import { basename , dirname , extname , join , relative , resolve } from "node:path" ;
33import { findUpSync } from "find-up" ;
44import { getNodeCompat } from "miniflare" ;
5- import { experimental_readRawConfig , readConfig } from "../config" ;
5+ import { experimental_readRawConfig } from "../config" ;
6+ import { createCommand } from "../core/create-command" ;
67import { getEntry } from "../deployment-bundle/entry" ;
78import { getVarsForDev } from "../dev/dev-vars" ;
89import { CommandLineArgsError , UserError } from "../errors" ;
910import { logger } from "../logger" ;
1011import { parseJSONC } from "../parse" ;
11- import { printWranglerBanner } from "../wrangler-banner" ;
1212import { generateRuntimeTypes } from "./runtime" ;
1313import { logRuntimeTypesMessage } from "./runtime/log-runtime-types-message" ;
1414import type { Config , RawEnvironment } from "../config" ;
1515import type { Entry } from "../deployment-bundle/entry" ;
1616import type { CfScriptFormat } from "../deployment-bundle/worker" ;
17- import type {
18- CommonYargsArgv ,
19- StrictYargsOptionsToInterface ,
20- } from "../yargs-types" ;
21-
22- export function typesOptions ( yargs : CommonYargsArgv ) {
23- return yargs
24- . positional ( "path" , {
17+
18+ export const typesCommand = createCommand ( {
19+ metadata : {
20+ description :
21+ "📝 Generate types from bindings and module rules in configuration\n" ,
22+ status : "stable" ,
23+ owner : "Workers: Authoring and Testing" ,
24+ } ,
25+ positionalArgs : [ "path" ] ,
26+ args : {
27+ path : {
2528 describe : "The path to the declaration file to generate" ,
2629 type : "string" ,
2730 default : "worker-configuration.d.ts" ,
2831 demandOption : false ,
29- } )
30- . option ( "env-interface" , {
32+ } ,
33+ "env-interface" : {
3134 type : "string" ,
3235 default : "Env" ,
3336 describe : "The name of the generated environment interface" ,
3437 requiresArg : true ,
35- } )
36- . option ( "experimental-include-runtime" , {
38+ } ,
39+ "experimental-include-runtime" : {
3740 alias : "x-include-runtime" ,
3841 type : "string" ,
3942 describe : "The path of the generated runtime types file" ,
4043 demandOption : false ,
41- } )
42- . option ( "strict-vars" , {
44+ } ,
45+ "strict-vars" : {
4346 type : "boolean" ,
4447 default : true ,
4548 describe : "Generate literal and union types for variables" ,
46- } ) ;
47- }
49+ } ,
50+ } ,
51+ validateArgs ( args ) {
52+ const { envInterface, path : outputPath } = args ;
4853
49- export async function typesHandler (
50- args : StrictYargsOptionsToInterface < typeof typesOptions >
51- ) {
52- const { envInterface, path : outputPath } = args ;
54+ const validInterfaceRegex = / ^ [ a - z A - Z ] [ a - z A - Z 0 - 9 _ ] * $ / ;
5355
54- const validInterfaceRegex = / ^ [ a - z A - Z ] [ a - z A - Z 0 - 9 _ ] * $ / ;
56+ if ( ! validInterfaceRegex . test ( envInterface ) ) {
57+ throw new CommandLineArgsError (
58+ `The provided env-interface value ("${ envInterface } ") does not satisfy the validation regex: ${ validInterfaceRegex } `
59+ ) ;
60+ }
5561
56- if ( ! validInterfaceRegex . test ( envInterface ) ) {
57- throw new CommandLineArgsError (
58- `The provided env-interface value ("${ envInterface } ") does not satisfy the validation regex: ${ validInterfaceRegex } `
59- ) ;
60- }
62+ if ( ! outputPath . endsWith ( ".d.ts" ) ) {
63+ throw new CommandLineArgsError (
64+ `The provided path value ("${ outputPath } ") does not point to a declaration file (please use the 'd.ts' extension)`
65+ ) ;
66+ }
67+ } ,
68+ async handler ( args , { config } ) {
69+ const { envInterface, path : outputPath } = args ;
6170
62- if ( ! outputPath . endsWith ( ".d.ts" ) ) {
63- throw new CommandLineArgsError (
64- `The provided path value ("${ outputPath } ") does not point to a declaration file (please use the 'd.ts' extension)`
65- ) ;
66- }
71+ if (
72+ ! config . configPath ||
73+ ! fs . existsSync ( config . configPath ) ||
74+ fs . statSync ( config . configPath ) . isDirectory ( )
75+ ) {
76+ logger . warn (
77+ `No config file detected${
78+ args . config ? ` (at ${ args . config } )` : ""
79+ } , aborting`
80+ ) ;
81+ return ;
82+ }
6783
68- await printWranglerBanner ( ) ;
84+ // args.xRuntime will be a string if the user passes "--x-include-runtime" or "--x-include-runtime=..."
85+ if ( typeof args . experimentalIncludeRuntime === "string" ) {
86+ logger . log ( `Generating runtime types...` ) ;
87+
88+ const { outFile } = await generateRuntimeTypes ( {
89+ config,
90+ outFile : args . experimentalIncludeRuntime || undefined ,
91+ } ) ;
92+
93+ const tsconfigPath =
94+ config . tsconfig ?? join ( dirname ( config . configPath ) , "tsconfig.json" ) ;
95+ const tsconfigTypes = readTsconfigTypes ( tsconfigPath ) ;
96+ const { mode } = getNodeCompat (
97+ config . compatibility_date ,
98+ config . compatibility_flags ,
99+ {
100+ nodeCompat : config . node_compat ,
101+ }
102+ ) ;
69103
70- const config = readConfig ( args ) ;
71- if (
72- ! config . configPath ||
73- ! fs . existsSync ( config . configPath ) ||
74- fs . statSync ( config . configPath ) . isDirectory ( )
75- ) {
76- logger . warn (
77- `No config file detected${
78- args . config ? ` (at ${ args . config } )` : ""
79- } , aborting`
80- ) ;
81- return ;
82- }
104+ logRuntimeTypesMessage (
105+ outFile ,
106+ tsconfigTypes ,
107+ mode !== null ,
108+ config . configPath
109+ ) ;
110+ }
83111
84- // args.xRuntime will be a string if the user passes "--x-include-runtime" or "--x-include-runtime=..."
85- if ( typeof args . experimentalIncludeRuntime === "string" ) {
86- logger . log ( `Generating runtime types...` ) ;
112+ const secrets = getVarsForDev (
113+ // We do not want `getVarsForDev()` to merge in the standard vars into the dev vars
114+ // because we want to be able to work with secrets differently to vars.
115+ // So we pass in a fake vars object here.
116+ { ...config , vars : { } } ,
117+ args . env ,
118+ true
119+ ) as Record < string , string > ;
120+
121+ const configBindingsWithSecrets = {
122+ kv_namespaces : config . kv_namespaces ?? [ ] ,
123+ vars : collectAllVars ( args ) ,
124+ wasm_modules : config . wasm_modules ,
125+ text_blobs : {
126+ ...config . text_blobs ,
127+ } ,
128+ data_blobs : config . data_blobs ,
129+ durable_objects : config . durable_objects ,
130+ r2_buckets : config . r2_buckets ,
131+ d1_databases : config . d1_databases ,
132+ services : config . services ,
133+ analytics_engine_datasets : config . analytics_engine_datasets ,
134+ dispatch_namespaces : config . dispatch_namespaces ,
135+ logfwdr : config . logfwdr ,
136+ unsafe : config . unsafe ,
137+ rules : config . rules ,
138+ queues : config . queues ,
139+ send_email : config . send_email ,
140+ vectorize : config . vectorize ,
141+ hyperdrive : config . hyperdrive ,
142+ mtls_certificates : config . mtls_certificates ,
143+ browser : config . browser ,
144+ ai : config . ai ,
145+ version_metadata : config . version_metadata ,
146+ secrets,
147+ assets : config . assets ,
148+ workflows : config . workflows ,
149+ } ;
87150
88- const { outFile } = await generateRuntimeTypes ( {
151+ await generateTypes (
152+ configBindingsWithSecrets ,
89153 config ,
90- outFile : args . experimentalIncludeRuntime || undefined ,
91- } ) ;
92-
93- const tsconfigPath =
94- config . tsconfig ?? join ( dirname ( config . configPath ) , "tsconfig.json" ) ;
95- const tsconfigTypes = readTsconfigTypes ( tsconfigPath ) ;
96- const { mode } = getNodeCompat (
97- config . compatibility_date ,
98- config . compatibility_flags ,
99- {
100- nodeCompat : config . node_compat ,
101- }
102- ) ;
103-
104- logRuntimeTypesMessage (
105- outFile ,
106- tsconfigTypes ,
107- mode !== null ,
108- config . configPath
154+ envInterface ,
155+ outputPath
109156 ) ;
110- }
111-
112- const secrets = getVarsForDev (
113- // We do not want `getVarsForDev()` to merge in the standard vars into the dev vars
114- // because we want to be able to work with secrets differently to vars.
115- // So we pass in a fake vars object here.
116- { ...config , vars : { } } ,
117- args . env ,
118- true
119- ) as Record < string , string > ;
120-
121- const configBindingsWithSecrets = {
122- kv_namespaces : config . kv_namespaces ?? [ ] ,
123- vars : collectAllVars ( args ) ,
124- wasm_modules : config . wasm_modules ,
125- text_blobs : {
126- ...config . text_blobs ,
127- } ,
128- data_blobs : config . data_blobs ,
129- durable_objects : config . durable_objects ,
130- r2_buckets : config . r2_buckets ,
131- d1_databases : config . d1_databases ,
132- services : config . services ,
133- analytics_engine_datasets : config . analytics_engine_datasets ,
134- dispatch_namespaces : config . dispatch_namespaces ,
135- logfwdr : config . logfwdr ,
136- unsafe : config . unsafe ,
137- rules : config . rules ,
138- queues : config . queues ,
139- send_email : config . send_email ,
140- vectorize : config . vectorize ,
141- hyperdrive : config . hyperdrive ,
142- mtls_certificates : config . mtls_certificates ,
143- browser : config . browser ,
144- ai : config . ai ,
145- version_metadata : config . version_metadata ,
146- secrets,
147- assets : config . assets ,
148- workflows : config . workflows ,
149- } ;
150-
151- await generateTypes (
152- configBindingsWithSecrets ,
153- config ,
154- envInterface ,
155- outputPath
156- ) ;
157- }
157+ } ,
158+ } ) ;
158159
159160/**
160161 * Check if a string is a valid TypeScript identifier. This is a naive check and doesn't cover all cases
@@ -584,7 +585,7 @@ type VarTypes = Record<string, string[]>;
584585 * @returns an object which keys are the variable names and values are arrays containing all the computed types for such variables
585586 */
586587function collectAllVars (
587- args : StrictYargsOptionsToInterface < typeof typesOptions >
588+ args : ( typeof typesCommand ) [ "args" ]
588589) : Record < string , string [ ] > {
589590 const varsInfo : Record < string , Set < string > > = { } ;
590591
0 commit comments