import { Package } from "../package" ; import { Project } from "../project" ; import path from "path" ; import { rollup , OutputAsset , OutputChunk , OutputOptions } from "rollup" ; import { Aliases , getAliases } from "./aliases" ; import * as logger from "../logger" ; import * as fs from "fs-extra" ; import { FatalError , UnexpectedBuildError , ScopelessError , BatchError , } from "../errors" ; import { getRollupConfigs } from "./config" ; import { createWorker , destroyWorker } from "../worker-client" ; import { validateProject } from "../validate" ; import { cleanProjectBeforeBuild } from "./utils" ; let SOURCEMAPPING_URL = "sourceMa" ; SOURCEMAPPING_URL += "ppingURL" ; function writeOutputFile ( outputFile , outputOptions ) { const fileName = path . resolve ( outputOptions . dir || path . dirname ( outputOptions . file ! ) , outputFile . fileName ) ; let writeSourceMapPromise ; let source ; if ( outputFile . type === "asset" ) { source = outputFile . source ; } else { source = outputFile . code ; if ( outputOptions . sourcemap && outputFile . map ) { let url ; if ( outputOptions . sourcemap === "inline" ) { url = outputFile . map . toUrl ( ) ; } else { url = `${ path . basename ( outputFile . fileName ) }.map` ; writeSourceMapPromise = fs . outputFile ( `${ fileName }.map` , outputFile . map . toString ( ) ) ; } if ( outputOptions . sourcemap !== "hidden" ) { source += `//# ${ SOURCEMAPPING_URL }=${ url }\n` ; } } } return Promise . all ( [ fs . outputFile ( fileName , source ) , writeSourceMapPromise ] ) ; } async function buildPackage ( pkg , aliases ) { let configs = getRollupConfigs ( pkg , aliases ) ; let outputs = await Promise . all ( configs . map ( async ( { config , outputs } ) => { let bundle = await rollup ( config ) ; return Promise . all ( outputs . map ( async ( outputConfig ) => { return { output : ( await bundle . generate ( outputConfig ) ) . output , outputConfig , } ; } ) ) ; } ) ) ; await Promise . all ( outputs . map ( ( x ) => { return Promise . all ( x . map ( ( bundle ) => { return Promise . all ( bundle . output . map ( ( output ) => { return writeOutputFile ( output , bundle . outputConfig ) ; } ) ) ; } ) ) ; } ) ) ; } async function retryableBuild ( pkg , aliases ) { try { await buildPackage ( pkg , aliases ) ; } catch ( err ) { if ( err instanceof Promise ) { await err ; await retryableBuild ( pkg , aliases ) ; return ; } if ( err instanceof FatalError || err instanceof BatchError || err instanceof ScopelessError ) { throw err ; } if ( err . pluginCode === "BABEL_PARSE_ERROR" ) { throw new ScopelessError ( err . message ) ; } throw new UnexpectedBuildError ( err , pkg . name ) ; } } export default async function build ( directory ) { try { createWorker ( ) ; let project = await Project . create ( directory ) ; validateProject ( project ) ; logger . info ( "building bundles!" ) ; await cleanProjectBeforeBuild ( project ) ; let aliases = getAliases ( project ) ; let errors = [ ] ; await Promise . all ( project . packages . map ( async ( pkg ) => { try { await retryableBuild ( pkg , aliases ) ; } catch ( err ) { if ( err instanceof BatchError ) { errors . push ( ... err . errors ) ; } else { errors . push ( err ) ; } } } ) ) ; if ( errors . length ) { throw new BatchError ( errors . sort ( ( a , b ) => ( a . scope + a . message ) . localeCompare ( b . scope + b . message ) ) ) ; } logger . success ( "built bundles!" ) ; } finally { destroyWorker ( ) ; } }