import fs , { existsSync } from "fs" ; import { resolve , extname , dirname , basename } from "path" ; import commonjs from "@rollup/plugin-commonjs" ; import shebang from "rollup-plugin-preserve-shebang" ; import json from "@rollup/plugin-json" ; import babel from "@rollup/plugin-babel" ; import nodeResolve from "@rollup/plugin-node-resolve" ; import { InputOptions , OutputOptions , Plugin } from "rollup" ; import { terser } from "rollup-plugin-terser" ; import { PackageMetadata , BuncheeRollupConfig , CliArgs , BundleOptions } from "./types" ; import config from "./config" ; import { logger } from "./utils" ; const { Module } = require ( "module" ) ; let hasLoggedTsWarning = false ; function resolveTypescript ( ) { let ts ; const m = new Module ( "" , null ) ; m . paths = Module . _nodeModulePaths ( config . rootDir ) ; try { ts = m . require ( "typescript" ) ; } catch ( _ ) { if ( ! hasLoggedTsWarning ) { hasLoggedTsWarning = true ; logger . warn ( "Could not load TypeScript compiler. Try `yarn add --dev typescript`" ) ; } } return ts ; } function getDistPath ( distPath ) { return resolve ( config . rootDir , distPath ) ; } function createInputConfig ( entry , pkg , options ) { const externals = [ pkg . peerDependencies , pkg . dependencies ] . filter ( < T > ( n ? ) : n is T => Boolean ( n ) ) . map ( ( o ) : string [ ] => Object . keys ( o ) ) . reduce ( ( a , b ) => a . concat ( b ) , [ ] as string [ ] ) ; const { useTypescript , target , minify = false } = options ; const typings = pkg . types || pkg . typings ; const cwd = config . rootDir ; const plugins = [ nodeResolve ( { preferBuiltins : target === "node" , extensions : [ ".mjs" , ".js" , ".json" , ".node" , ".jsx" ] , } ) , commonjs ( { include : /node_modules\// , } ) , json ( ) , shebang ( ) , useTypescript && require ( "@rollup/plugin-typescript" ) ( { tsconfig : ( ( ) => { const tsconfig = resolve ( cwd , "tsconfig.json" ) ; return existsSync ( tsconfig ) ? tsconfig : undefined ; } ) ( ) , typescript : resolveTypescript ( ) , jsx : "react" , module : "ES6" , target : "ES5" , noEmitOnError : true , sourceMap : options . sourcemap , declaration : ! ! typings , ... ( ! ! typings && { declarationDir : dirname ( resolve ( cwd , typings ) ) , } ) , } ) , ! useTypescript && babel ( { babelHelpers : "bundled" , babelrc : false , configFile : false , exclude : "node_modules/**" , presets : [ [ "babel-preset-o" , { targets : { } } ] ] , } ) , minify && terser ( { compress : { "keep_infinity" : true , } , format : { "comments" : /^\s*([@#]__[A-Z]__\s*$|@[a-zA-Z]\s*$)/ , "wrap_func_args" : false , "preserve_annotations" : true , } } ) , ] . filter ( ( n ) : n is Plugin => Boolean ( n ) ) ; return { input : entry , external ( id ) { return externals . some ( name => id === name || id . startsWith ( name + "/" ) ) ; } , plugins , treeshake : { propertyReadSideEffects : false , } , onwarn ( warning , warn ) { if ( warning . code && [ 'MIXED_EXPORTS' , 'PREFER_NAMED_EXPORTS' ] . includes ( warning . code ) ) return ; warn ( warning ) ; } , } ; } function createOutputOptions ( options , pkg ) { const { format , useTypescript } = options ; let tsCompilerOptions = { } as any ; if ( useTypescript ) { const ts = resolveTypescript ( ) ; const tsconfigPath = resolve ( config . rootDir , "tsconfig.json" ) ; if ( fs . existsSync ( tsconfigPath ) ) { const tsconfigJSON = ts . readConfigFile ( tsconfigPath , ts . sys . readFile ) . config ; tsCompilerOptions = ts . parseJsonConfigFileContent ( tsconfigJSON , ts . sys , "./" ) . options ; } } const exportPaths = getExportPaths ( pkg ) ; const useEsModuleMark = Boolean ( tsCompilerOptions . esModuleInterop || ( exportPaths . main && exportPaths . module ) ) ; const file = resolve ( options . file as string ) ; return { name : pkg . name , dir : dirname ( file ) , entryFileNames : basename ( file ) , format , esModule : useEsModuleMark && format !== "umd" , freeze : false , strict : false , sourcemap : options . sourcemap , } ; } function findExport ( field ) { if ( ! field ) return null ; if ( typeof field === "string" ) return field ; const value = field [ "." ] || field [ "import" ] || field [ "module" ] || field [ "default" ] ; return findExport ( value ) ; } function getExportPaths ( pkg ) { const paths = { main : null , module : null , export : null , } ; if ( pkg . main ) { paths . main = pkg . main ; } if ( pkg . module ) { paths . module = pkg . module ; } if ( pkg . exports ) { if ( typeof pkg . exports === "string" ) { paths . export = pkg . exports ; } else { paths . main = paths . main || pkg . exports [ "require" ] || pkg . exports [ "node" ] || pkg . exports [ "default" ] ; paths . module = paths . module || pkg . exports [ "module" ] ; paths . export = findExport ( pkg . exports ) ; } } return paths ; } function getExportDist ( pkg ) { const paths = getExportPaths ( pkg ) ; const dist = [ ] ; if ( paths . main ) { dist . push ( { format : "cjs" , file : getDistPath ( paths . main ) } ) ; } if ( paths . module ) { dist . push ( { format : "esm" , file : getDistPath ( paths . module ) } ) ; } if ( paths . export ) { dist . push ( { format : "esm" , file : getDistPath ( paths . export ) } ) ; } if ( dist . length === 0 ) { dist . push ( { format : "cjs" , file : getDistPath ( "dist/index.js" ) } ) ; } return dist ; } function createRollupConfig ( entry , pkg , cliArgs ) { const { file , format } = cliArgs ; const ext = extname ( entry ) ; const useTypescript = ext === ".ts" || ext === ".tsx" ; const options = { ... cliArgs , useTypescript } ; const inputOptions = createInputConfig ( entry , pkg , options ) ; let outputConfigs = getExportDist ( pkg ) . map ( ( exportDist ) => { return createOutputOptions ( { ... cliArgs , file : exportDist . file , format : exportDist . format , useTypescript , } , pkg ) ; } ) ; if ( file ) { outputConfigs = [ createOutputOptions ( { ... cliArgs , file , format , useTypescript , } , pkg ) ] ; } return { input : inputOptions , output : outputConfigs , } ; } export default createRollupConfig ;