import { existsSync , statSync } from 'fs' ; import { extname , resolve , dirname , join } from 'path' ; import { Plugin as RollupPlugin } from 'rollup' ; import { transform , Loader , CommonOptions } from 'esbuild' ; import { MarkOptional } from 'ts-essentials' ; import { createFilter , FilterPattern } from '@rollup/pluginutils' ; import createDebug from 'debug' ; import { getOptions } from './options' ; import { minify , getRenderChunk } from './minify' ; import { warn } from './warn' ; import { optimizeDeps , OptimizeDepsOptions , OptimizeDepsResult , } from './optimizer/optmize-deps' ; export { minify } ; const debugOptimizeDeps = createDebug ( 'rpe:optimize-deps' ) ; const defaultLoaders = { '.js' : 'js' , '.jsx' : 'jsx' , '.ts' : 'ts' , '.tsx' : 'tsx' , } ; export type Options = { include ? : FilterPattern ; exclude ? : FilterPattern ; sourceMap ? : boolean ; minify ? : boolean ; minifyWhitespace ? : boolean ; minifyIdentifiers ? : boolean ; minifySyntax ? : boolean ; keepNames ? : boolean ; legalComments ? : CommonOptions [ 'legalComments' ] ; target ? : string | string [ ] ; /**
     * Requires esbuild >= 0.12.1
     */ jsx ? : 'transform' | 'preserve' ; jsxFactory ? : string ; jsxFragment ? : string ; define ? : { [ k ] : string ; } ; optimizeDeps ? : MarkOptional < OptimizeDepsOptions , 'cwd' | 'sourceMap' > ; /**
     * Use this tsconfig file instead
     * Disable it by setting to `false`
     */ tsconfig ? : string | false ; /**
     * Map extension to esbuild loader
     * Note that each entry (the extension) needs to start with a dot
     */ loaders ? : { [ ext ] : Loader | false ; } ; pure ? : string [ ] ; } ; export default ( options = { } ) : RollupPlugin => { let target ; const loaders = { ... defaultLoaders , } ; if ( options . loaders ) { for ( const key of Object . keys ( options . loaders ) ) { const value = options . loaders [ key ] ; if ( typeof value === 'string' ) { loaders [ key ] = value ; } else if ( value === false ) { delete loaders [ key ] ; } } } const extensions = Object . keys ( loaders ) ; const INCLUDE_REGEXP = new RegExp ( `\\.(${ extensions . map ( ( ext ) => ext . slice ( 1 ) ) . join ( '|' ) })$` ) ; const EXCLUDE_REGEXP = /node_modules/ ; const filter = createFilter ( options . include || INCLUDE_REGEXP , options . exclude || EXCLUDE_REGEXP ) ; const resolveFile = ( resolved , index = false ) => { for ( const ext of extensions ) { const file = index ? join ( resolved , `index${ ext }` ) : `${ resolved }${ ext }` ; if ( existsSync ( file ) ) return file ; } return null ; } ; let optimizeDepsResult ; let cwd = process . cwd ( ) ; let sourceMap = false ; return { name : 'esbuild' , options ( { context } ) { if ( context ) { cwd = context ; options ; } return null ; } , outputOptions ( { sourcemap } ) { sourceMap = options . sourceMap ?? ! ! sourcemap ; return null ; } , async buildStart ( ) { if ( ! options . optimizeDeps || optimizeDepsResult ) return ; optimizeDepsResult = await optimizeDeps ( { cwd , sourceMap , ... options . optimizeDeps , } ) ; debugOptimizeDeps ( 'optimized %O' , optimizeDepsResult . optimized ) ; } , async resolveId ( id , importer ) { if ( optimizeDepsResult ?. optimized . has ( id ) ) { const m = optimizeDepsResult . optimized . get ( id ) ! ; debugOptimizeDeps ( 'resolved %s to %s' , id , m . file ) ; return m . file ; } if ( importer && id [ 0 ] === '.' ) { const resolved = resolve ( importer ? dirname ( importer ) : process . cwd ( ) , id ) ; let file = resolveFile ( resolved ) ; if ( file ) return file ; if ( ! file && existsSync ( resolved ) && statSync ( resolved ) . isDirectory ( ) ) { file = resolveFile ( resolved , true ) ; if ( file ) return file ; } } } , async transform ( code , id ) { if ( ! filter ( id ) || optimizeDepsResult ?. optimized . has ( id ) ) { return null ; } const ext = extname ( id ) ; const loader = loaders [ ext ] ; if ( ! loader ) { return null ; } const defaultOptions = options . tsconfig === false ? { } : await getOptions ( dirname ( id ) , options . tsconfig ) ; target = options . target || defaultOptions . target || 'es2017' ; const result = await transform ( code , { loader , target , jsx : options . jsx , jsxFactory : options . jsxFactory || defaultOptions . jsxFactory , jsxFragment : options . jsxFragment || defaultOptions . jsxFragment , define : options . define , sourcemap : sourceMap , sourcefile : id , pure : options . pure , legalComments : options . legalComments , } ) ; await warn ( this , result . warnings ) ; return ( result . code && { code : result . code , map : result . map || null , } ) ; } , renderChunk : getRenderChunk ( { ... options , sourceMap , } ) , } ; } ;