2022-06-16 14:12:25 +00:00
import type { AstroAdapter , AstroConfig , AstroIntegration , BuildConfig } from 'astro' ;
import esbuild from 'esbuild' ;
import * as fs from 'fs' ;
import { fileURLToPath } from 'url' ;
2022-08-08 17:10:48 +00:00
type Options = {
mode : 'directory' | 'advanced' ;
} ;
export function getAdapter ( isModeDirectory : boolean ) : AstroAdapter {
return isModeDirectory
? {
name : '@astrojs/cloudflare' ,
serverEntrypoint : '@astrojs/cloudflare/server.directory.js' ,
exports : [ 'onRequest' ] ,
}
: {
name : '@astrojs/cloudflare' ,
serverEntrypoint : '@astrojs/cloudflare/server.advanced.js' ,
exports : [ 'default' ] ,
} ;
2022-06-16 14:12:25 +00:00
}
2022-07-27 20:15:19 +00:00
const SHIM = ` globalThis.process = {
argv : [ ] ,
env : { } ,
} ; ` ;
2022-08-08 17:10:48 +00:00
export default function createIntegration ( args? : Options ) : AstroIntegration {
2022-06-16 14:12:25 +00:00
let _config : AstroConfig ;
let _buildConfig : BuildConfig ;
2022-08-08 17:10:48 +00:00
const isModeDirectory = args ? . mode === 'directory' ;
2022-06-16 14:12:25 +00:00
return {
name : '@astrojs/cloudflare' ,
hooks : {
'astro:config:done' : ( { setAdapter , config } ) = > {
2022-08-08 17:10:48 +00:00
setAdapter ( getAdapter ( isModeDirectory ) ) ;
2022-06-16 14:12:25 +00:00
_config = config ;
2022-07-25 04:18:02 +00:00
2022-07-25 04:20:38 +00:00
if ( config . output === 'static' ) {
2022-07-27 15:50:48 +00:00
throw new Error ( `
[ @astrojs / cloudflare ] \ ` output: "server" \` is required to use this adapter. Otherwise, this adapter is not necessary to deploy a static site to Cloudflare.
` );
2022-07-25 04:18:02 +00:00
}
2022-06-16 14:12:25 +00:00
} ,
'astro:build:start' : ( { buildConfig } ) = > {
_buildConfig = buildConfig ;
buildConfig . client = new URL ( './static/' , _config . outDir ) ;
2022-08-08 17:10:48 +00:00
buildConfig . serverEntry = '_worker.js' ;
2022-06-16 14:12:25 +00:00
buildConfig . server = new URL ( './' , _config . outDir ) ;
} ,
'astro:build:setup' : ( { vite , target } ) = > {
if ( target === 'server' ) {
vite . resolve = vite . resolve || { } ;
vite . resolve . alias = vite . resolve . alias || { } ;
const aliases = [ { find : 'react-dom/server' , replacement : 'react-dom/server.browser' } ] ;
if ( Array . isArray ( vite . resolve . alias ) ) {
vite . resolve . alias = [ . . . vite . resolve . alias , . . . aliases ] ;
} else {
for ( const alias of aliases ) {
( vite . resolve . alias as Record < string , string > ) [ alias . find ] = alias . replacement ;
}
}
2022-10-06 14:28:47 +00:00
vite . ssr = vite . ssr || { } ;
vite . ssr . target = vite . ssr . target || 'webworker' ;
2022-06-16 14:12:25 +00:00
}
} ,
'astro:build:done' : async ( ) = > {
const entryUrl = new URL ( _buildConfig . serverEntry , _buildConfig . server ) ;
const pkg = fileURLToPath ( entryUrl ) ;
await esbuild . build ( {
target : 'es2020' ,
2022-10-06 14:28:47 +00:00
platform : 'browser' ,
2022-06-16 14:12:25 +00:00
entryPoints : [ pkg ] ,
outfile : pkg ,
allowOverwrite : true ,
format : 'esm' ,
bundle : true ,
minify : true ,
2022-07-27 20:15:19 +00:00
banner : {
2022-07-27 20:17:38 +00:00
js : SHIM ,
} ,
2022-06-16 14:12:25 +00:00
} ) ;
// throw the server folder in the bin
const chunksUrl = new URL ( './chunks' , _buildConfig . server ) ;
await fs . promises . rm ( chunksUrl , { recursive : true , force : true } ) ;
2022-08-08 17:10:48 +00:00
if ( isModeDirectory ) {
const functionsUrl = new URL ( ` file:// ${ process . cwd ( ) } /functions/ ` ) ;
await fs . promises . mkdir ( functionsUrl , { recursive : true } ) ;
const directoryUrl = new URL ( '[[path]].js' , functionsUrl ) ;
await fs . promises . rename ( entryUrl , directoryUrl ) ;
}
2022-06-16 14:12:25 +00:00
} ,
} ,
} ;
}