11import { existsSync } from "fs" ;
2- import { join , resolve } from "path" ;
2+ import { join } from "path" ;
33import { warn } from "@cloudflare/cli" ;
44import { brandColor , dim } from "@cloudflare/cli/colors" ;
5+ import TOML from "@iarna/toml" ;
56import { runCommand } from "helpers/command" ;
67import { getLatestTypesEntrypoint } from "helpers/compatDate" ;
78import { readFile , readJSON , usesTypescript , writeFile } from "helpers/files" ;
89import { detectPackageManager } from "helpers/packageManagers" ;
910import { installPackages } from "helpers/packages" ;
11+ import { parse as jsoncParse } from "jsonc-parser" ;
1012import * as jsonc from "jsonc-parser" ;
13+ import {
14+ readWranglerJson ,
15+ readWranglerToml ,
16+ wranglerJsonExists ,
17+ wranglerTomlExists ,
18+ } from "./wrangler/config" ;
1119import type { C3Context , PackageJson } from "types" ;
1220
1321/**
@@ -18,9 +26,12 @@ export async function generateWorkersTypes(ctx: C3Context) {
1826 if ( ! usesTypescript ( ctx ) ) {
1927 return ;
2028 }
21- const packageJsonPath = resolve ( "package.json" ) ;
29+ const packageJsonPath = join ( ctx . project . path , "package.json" ) ;
30+ if ( ! existsSync ( packageJsonPath ) ) {
31+ return ;
32+ }
2233 const packageManifest = readJSON ( packageJsonPath ) as PackageJson ;
23- if ( ! Object . keys ( packageManifest . scripts ?? { } ) . includes ( "cf-typegen" ) ) {
34+ if ( ! packageManifest . scripts ?. [ "cf-typegen" ] ) {
2435 return ;
2536 }
2637
@@ -35,19 +46,43 @@ export async function generateWorkersTypes(ctx: C3Context) {
3546 doneText : `${ brandColor ( "generated" ) } ${ dim ( `to \`${ ctx . template . typesPath } \` via \`${ typesCmd . join ( " " ) } \`` ) } ` ,
3647 } ) ;
3748
38- if ( ctx . template . compatibilityFlags ?. includes ( "nodejs_compat" ) ) {
49+ const usesNodeCompat = await maybeInstallNodeTypes ( ctx , npm ) ;
50+
51+ delete packageManifest [ "devDependencies" ] ?. [ "@cloudflare/workers-types" ] ;
52+
53+ writeFile ( packageJsonPath , JSON . stringify ( packageManifest , null , 2 ) ) ;
54+ await updateTsConfig ( ctx , usesNodeCompat ) ;
55+ }
56+
57+ const maybeInstallNodeTypes = async ( ctx : C3Context , npm : string ) => {
58+ let parsedConfig : Record < string , unknown > = { } ;
59+ if ( wranglerJsonExists ( ctx ) ) {
60+ const wranglerJsonStr = readWranglerJson ( ctx ) ;
61+ parsedConfig = jsoncParse ( wranglerJsonStr , undefined , {
62+ allowTrailingComma : true ,
63+ } ) ;
64+ } else if ( wranglerTomlExists ( ctx ) ) {
65+ const wranglerTomlStr = readWranglerToml ( ctx ) ;
66+ parsedConfig = TOML . parse ( wranglerTomlStr ) ;
67+ }
68+
69+ const compatibility_flags = Array . isArray ( parsedConfig [ "compatibility_flags" ] )
70+ ? parsedConfig [ "compatibility_flags" ]
71+ : [ ] ;
72+
73+ if (
74+ compatibility_flags . includes ( "nodejs_compat" ) ||
75+ compatibility_flags . includes ( "nodejs_compat_v2" )
76+ ) {
3977 await installPackages ( [ "@types/node" ] , {
4078 dev : true ,
4179 startText : "Installing @types/node" ,
4280 doneText : `${ brandColor ( "installed" ) } ${ dim ( `via ${ npm } ` ) } ` ,
4381 } ) ;
82+ return true ;
4483 }
45-
46- delete packageManifest [ "devDependencies" ] ?. [ "@cloudflare/workers-types" ] ;
47-
48- writeFile ( packageJsonPath , JSON . stringify ( packageManifest , null , 2 ) ) ;
49- await updateTsConfig ( ctx ) ;
50- }
84+ return false ;
85+ } ;
5186
5287/**
5388 * update `types` in tsconfig:
@@ -56,7 +91,7 @@ export async function generateWorkersTypes(ctx: C3Context) {
5691 * - add generated types file if types were generated
5792 * - add node if node compat
5893 */
59- export async function updateTsConfig ( ctx : C3Context ) {
94+ export async function updateTsConfig ( ctx : C3Context , usesNodeCompat : boolean ) {
6095 const tsconfigPath = join ( ctx . project . path , "tsconfig.json" ) ;
6196 if ( ! existsSync ( tsconfigPath ) ) {
6297 return ;
@@ -99,7 +134,7 @@ export async function updateTsConfig(ctx: C3Context) {
99134 ) ;
100135 }
101136 // add node types if nodejs_compat is enabled
102- if ( ctx . template . compatibilityFlags ?. includes ( "nodejs_compat" ) ) {
137+ if ( usesNodeCompat ) {
103138 newTypes . push ( "node" ) ;
104139 }
105140 }
@@ -143,5 +178,6 @@ export async function installWorkersTypes(ctx: C3Context) {
143178 startText : "Installing @cloudflare/workers-types" ,
144179 doneText : `${ brandColor ( "installed" ) } ${ dim ( `via ${ npm } ` ) } ` ,
145180 } ) ;
146- await updateTsConfig ( ctx ) ;
181+ const usesNodeCompat = await maybeInstallNodeTypes ( ctx , npm ) ;
182+ await updateTsConfig ( ctx , usesNodeCompat ) ;
147183}
0 commit comments