11import { defineAddon , defineAddonOptions } from '../../core/index.ts' ;
2- import { exports , functions , imports , object } from '../../core/tooling/js/index.ts' ;
3- import { parseJson , parseScript } from '../../core/tooling/parsers.ts' ;
2+ import { exports , functions , imports , object , type AstTypes } from '../../core/tooling/js/index.ts' ;
3+ import { parseJson , parseScript , parseToml } from '../../core/tooling/parsers.ts' ;
4+ import { fileExists , readFile } from '../../cli/add/utils.ts' ;
5+ import { resolveCommand } from 'package-manager-detector' ;
6+ import * as js from '../../core/tooling/js/index.ts' ;
47
58const adapters = [
69 { id : 'auto' , package : '@sveltejs/adapter-auto' , version : '^7.0.0' } ,
@@ -18,6 +21,16 @@ const options = defineAddonOptions()
1821 default : 'auto' ,
1922 options : adapters . map ( ( p ) => ( { value : p . id , label : p . id , hint : p . package } ) )
2023 } )
24+ . add ( 'cfTarget' , {
25+ condition : ( options ) => options . adapter === 'cloudflare' ,
26+ type : 'select' ,
27+ question : 'Are you deploying to Workers (assets) or Pages?' ,
28+ default : 'workers' ,
29+ options : [
30+ { value : 'workers' , label : 'Workers' , hint : 'Recommended way to deploy to Cloudflare' } ,
31+ { value : 'pages' , label : 'Pages' }
32+ ]
33+ } )
2134 . build ( ) ;
2235
2336export default defineAddon ( {
@@ -29,7 +42,7 @@ export default defineAddon({
2942 setup : ( { kit, unsupported } ) => {
3043 if ( ! kit ) unsupported ( 'Requires SvelteKit' ) ;
3144 } ,
32- run : ( { sv, options, files } ) => {
45+ run : ( { sv, options, files, cwd , packageManager , typescript } ) => {
3346 const adapter = adapters . find ( ( a ) => a . id === options . adapter ) ! ;
3447
3548 // removes previously installed adapters
@@ -99,5 +112,135 @@ export default defineAddon({
99112
100113 return generateCode ( ) ;
101114 } ) ;
115+
116+ if ( adapter . package === '@sveltejs/adapter-cloudflare' ) {
117+ sv . devDependency ( 'wrangler' , 'latest' ) ;
118+
119+ // default to jsonc
120+ const configFormat = fileExists ( cwd , 'wrangler.toml' ) ? 'toml' : 'jsonc' ;
121+
122+ // Setup Cloudlfare workers/pages config
123+ sv . file ( `wrangler.${ configFormat } ` , ( content ) => {
124+ const { data, generateCode } =
125+ configFormat === 'jsonc' ? parseJson ( content ) : parseToml ( content ) ;
126+
127+ if ( configFormat === 'jsonc' ) {
128+ data . $schema ??= './node_modules/wrangler/config-schema.json' ;
129+ }
130+
131+ if ( ! data . name ) {
132+ const pkg = parseJson ( readFile ( cwd , files . package ) ) ;
133+ data . name = pkg . data . name ;
134+ }
135+
136+ data . compatibility_date ??= new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] ;
137+ data . compatibility_flags ??= [ ] ;
138+
139+ if (
140+ ! data . compatibility_flags . includes ( 'nodejs_compat' ) &&
141+ ! data . compatibility_flags . includes ( 'nodejs_als' )
142+ ) {
143+ data . compatibility_flags . push ( 'nodejs_als' ) ;
144+ }
145+
146+ switch ( options . cfTarget ) {
147+ case 'workers' :
148+ data . main = '.svelte-kit/cloudflare/_worker.js' ;
149+ data . assets ??= { } ;
150+ data . assets . binding = 'ASSETS' ;
151+ data . assets . directory = '.svelte-kit/cloudflare' ;
152+ data . workers_dev = true ;
153+ data . preview_urls = true ;
154+ break ;
155+
156+ case 'pages' :
157+ data . pages_build_output_dir = '.svelte-kit/cloudflare' ;
158+ break ;
159+ }
160+
161+ return generateCode ( ) ;
162+ } ) ;
163+
164+ const jsconfig = fileExists ( cwd , 'jsconfig.json' ) ;
165+ const typeChecked = typescript || jsconfig ;
166+
167+ if ( typeChecked ) {
168+ // Ignore generated Cloudflare Types
169+ sv . file ( files . gitignore , ( content ) => {
170+ return content . includes ( '.wrangler' ) && content . includes ( 'worker-configuration.d.ts' )
171+ ? content
172+ : `${ content . trimEnd ( ) } \n\n# Cloudflare Types\n/worker-configuration.d.ts` ;
173+ } ) ;
174+
175+ // Setup wrangler types command
176+ sv . file ( files . package , ( content ) => {
177+ const { data, generateCode } = parseJson ( content ) ;
178+
179+ data . scripts ??= { } ;
180+ data . scripts . types = 'wrangler types' ;
181+ const { command, args } = resolveCommand ( packageManager , 'run' , [ 'types' ] ) ! ;
182+ data . scripts . prepare = data . scripts . prepare
183+ ? `${ command } ${ args . join ( ' ' ) } && ${ data . scripts . prepare } `
184+ : `${ command } ${ args . join ( ' ' ) } ` ;
185+
186+ return generateCode ( ) ;
187+ } ) ;
188+
189+ // Add Cloudflare generated types to tsconfig
190+ sv . file ( `${ jsconfig ? 'jsconfig' : 'tsconfig' } .json` , ( content ) => {
191+ const { data, generateCode } = parseJson ( content ) ;
192+
193+ data . compilerOptions ??= { } ;
194+ data . compilerOptions . types ??= [ ] ;
195+ data . compilerOptions . types . push ( 'worker-configuration.d.ts' ) ;
196+
197+ return generateCode ( ) ;
198+ } ) ;
199+
200+ sv . file ( 'src/app.d.ts' , ( content ) => {
201+ const { ast, generateCode } = parseScript ( content ) ;
202+
203+ const platform = js . kit . addGlobalAppInterface ( ast , { name : 'Platform' } ) ;
204+ if ( ! platform ) {
205+ throw new Error ( 'Failed detecting `platform` interface in `src/app.d.ts`' ) ;
206+ }
207+
208+ platform . body . body . push (
209+ createCloudflarePlatformType ( 'env' , 'Env' ) ,
210+ createCloudflarePlatformType ( 'ctx' , 'ExecutionContext' ) ,
211+ createCloudflarePlatformType ( 'caches' , 'CacheStorage' ) ,
212+ createCloudflarePlatformType ( 'cf' , 'IncomingRequestCfProperties' , true )
213+ ) ;
214+
215+ return generateCode ( ) ;
216+ } ) ;
217+ }
218+ }
102219 }
103220} ) ;
221+
222+ function createCloudflarePlatformType (
223+ name : string ,
224+ value : string ,
225+ optional = false
226+ ) : AstTypes . TSInterfaceBody [ 'body' ] [ number ] {
227+ return {
228+ type : 'TSPropertySignature' ,
229+ key : {
230+ type : 'Identifier' ,
231+ name
232+ } ,
233+ computed : false ,
234+ optional,
235+ typeAnnotation : {
236+ type : 'TSTypeAnnotation' ,
237+ typeAnnotation : {
238+ type : 'TSTypeReference' ,
239+ typeName : {
240+ type : 'Identifier' ,
241+ name : value
242+ }
243+ }
244+ }
245+ } ;
246+ }
0 commit comments