@@ -14,10 +14,24 @@ import type { CommentObject } from "comment-json";
1414import type { C3Context } from "types" ;
1515
1616/**
17- * Update the `wrangler.(toml|json|jsonc)` file for this project by setting the name
18- * to the selected project name and adding the latest compatibility date.
17+ * Update the `wrangler.(toml|json|jsonc)` file for this project by:
18+ *
19+ * - setting the `name` to the passed project name
20+ * - adding the latest compatibility date when no valid one is present
21+ * - enabling observability
22+ * - adding comments with links to documentation for common configuration options
23+ * - substituting placeholders with actual values
24+ * - `__WORKER_NAME__` with the project name
25+ *
26+ * If both `wrangler.toml` and `wrangler.json`/`wrangler.jsonc` are present, only
27+ * the `wrangler.json`/`wrangler.jsonc` file will be updated.
1928 */
2029export const updateWranglerConfig = async ( ctx : C3Context ) => {
30+ // Placeholders to replace in the wrangler config files
31+ const substitutions : Record < string , string > = {
32+ __WORKER_NAME__ : ctx . project . name ,
33+ } ;
34+
2135 if ( wranglerJsonExists ( ctx ) ) {
2236 let wranglerJson = readWranglerJson ( ctx ) ;
2337
@@ -70,7 +84,11 @@ export const updateWranglerConfig = async (ctx: C3Context) => {
7084 } ,
7185 ] ) ;
7286
73- writeWranglerJson ( ctx , wranglerJson ) ;
87+ writeWranglerJson ( ctx , wranglerJson , ( _key , value ) =>
88+ typeof value === "string" && value in substitutions
89+ ? substitutions [ value ]
90+ : value ,
91+ ) ;
7492 addVscodeConfig ( ctx ) ;
7593 } else if ( wranglerTomlExists ( ctx ) ) {
7694 const wranglerTomlStr = readWranglerToml ( ctx ) ;
@@ -79,14 +97,17 @@ export const updateWranglerConfig = async (ctx: C3Context) => {
7997 parsed [ "compatibility_date" ] = await getCompatibilityDate ( parsed ) ;
8098 parsed [ "observability" ] ??= { enabled : true } ;
8199
82- const comment = `#:schema node_modules/wrangler/config-schema.json\n# For more details on how to configure Wrangler, refer to:\n# https://developers.cloudflare.com/workers/wrangler/configuration/\n` ;
100+ let strToml = TOML . stringify ( parsed ) ;
83101
84- const stringified = comment + TOML . stringify ( parsed ) ;
102+ for ( const [ key , value ] of Object . entries ( substitutions ) ) {
103+ strToml = strToml . replaceAll ( key , value ) ;
104+ }
85105
86106 writeWranglerToml (
87107 ctx ,
88- stringified +
89- `
108+ `#:schema node_modules/wrangler/config-schema.json
109+ # For more details on how to configure Wrangler, refer to:\n# https://developers.cloudflare.com/workers/wrangler/configuration/
110+ ${ strToml }
90111# Smart Placement
91112# Docs: https://developers.cloudflare.com/workers/configuration/smart-placement/#smart-placement
92113# [placement]
@@ -166,13 +187,32 @@ export const writeWranglerToml = (ctx: C3Context, contents: string) => {
166187 return writeFile ( wranglerTomlPath , contents ) ;
167188} ;
168189
169- export const writeWranglerJson = ( ctx : C3Context , config : CommentObject ) => {
190+ /**
191+ * Writes the passed JSON object as the configuration file for this project.
192+ *
193+ * If there is an existing `wrangler.json` file, it will be overwritten.
194+ * If not, `wrangler.jsonc` will be created/overwritten.
195+ *
196+ * @param ctx The C3 context.
197+ * @param config The JSON object (with comment properties) to write.
198+ * @param replacer A function that transforms the results or
199+ * an array of strings and numbers that acts as an approved list for selecting
200+ * the object properties that will be stringified.
201+ */
202+ export const writeWranglerJson = (
203+ ctx : C3Context ,
204+ config : CommentObject ,
205+ replacer ?:
206+ | ( ( key : string , value : unknown ) => unknown )
207+ | Array < number | string >
208+ | null ,
209+ ) => {
170210 const wranglerJsonPath = getWranglerJsonPath ( ctx ) ;
171211 if ( existsSync ( wranglerJsonPath ) ) {
172- return writeJSONWithComments ( wranglerJsonPath , config ) ;
212+ return writeJSONWithComments ( wranglerJsonPath , config , replacer ) ;
173213 }
174214 const wranglerJsoncPath = getWranglerJsoncPath ( ctx ) ;
175- return writeJSONWithComments ( wranglerJsoncPath , config ) ;
215+ return writeJSONWithComments ( wranglerJsoncPath , config , replacer ) ;
176216} ;
177217
178218export const addVscodeConfig = ( ctx : C3Context ) => {
@@ -193,16 +233,26 @@ export const addVscodeConfig = (ctx: C3Context) => {
193233 } ) ;
194234} ;
195235
236+ /**
237+ * Gets the compatibility date to use from the wrangler config.
238+ *
239+ * If the compatibility date is missing or invalid, it sets it to the latest workerd date.
240+ *
241+ * @param config Wrangler config
242+ * @returns The compatibility date to use in the form "YYYY-MM-DD"
243+ */
196244async function getCompatibilityDate < T extends Record < string , unknown > > (
197245 config : T ,
198- ) {
246+ ) : Promise < string > {
199247 const validCompatDateRe = / ^ \d { 4 } - \d { 2 } - \d { 2 } $ / m;
248+ const dateFromConfig = config [ "compatibility_date" ] ;
200249 if (
201- typeof config [ "compatibility_date" ] === "string" &&
202- config [ "compatibility_date" ] . match ( validCompatDateRe )
250+ typeof dateFromConfig === "string" &&
251+ dateFromConfig . match ( validCompatDateRe )
203252 ) {
204253 // If the compat date is already a valid one, leave it since it may be there for a specific compat reason
205- return config [ "compatibility_date" ] ;
254+ return dateFromConfig ;
206255 }
256+ // If the compat date is missing or invalid, set it to the latest workerd date
207257 return await getWorkerdCompatibilityDate ( ) ;
208258}
0 commit comments