@@ -20,7 +20,14 @@ interface BuildOptions {
2020 bin ?: Record < string , { input : string ; sourcemap ?: boolean } > ;
2121}
2222
23- export const distDir = "dist" ;
23+ export const DIST_DIR = "dist" ;
24+
25+ interface PackageInfo {
26+ packagePath : string ;
27+ cwd : string ;
28+ pkg : any ;
29+ fullName : string ;
30+ }
2431
2532export const buildCommand = createCommand <
2633 { } ,
@@ -42,31 +49,48 @@ export const buildCommand = createCommand<
4249 } ) ;
4350 } ,
4451 async handler ( args ) {
52+ config . dists = config . dists || [
53+ {
54+ distDir : DIST_DIR ,
55+ distPath : ''
56+ }
57+ ] ;
4558 if ( args . single ) {
46- await buildSingle ( ) ;
59+ await buildSingle ( { distDir : DIST_DIR } ) ;
4760 return ;
4861 }
4962
5063 const limit = pLimit ( 4 ) ;
5164 const packages = await globby ( "packages/**/package.json" , {
5265 cwd : process . cwd ( ) ,
5366 absolute : true ,
54- ignore : [ "**/node_modules/**" , `**/${ distDir } /**` ] ,
67+ ignore : [ "**/node_modules/**" , ... config . dists . map ( ( { distDir } ) => `**/${ distDir } /**` ) ] ,
5568 } ) ;
5669
57- await Promise . all (
58- packages . map ( ( packagePath ) =>
59- limit ( ( ) => build ( packagePath , config , reporter ) )
60- )
70+ const packageInfoList : PackageInfo [ ] = await Promise . all (
71+ packages . map ( packagePath => limit ( async ( ) => {
72+ const cwd = packagePath . replace ( "/package.json" , "" ) ;
73+ const pkg = await fs . readJSON ( resolve ( cwd , 'package.json' ) ) ;
74+ const fullName : string = pkg . name ;
75+ return { packagePath, cwd, pkg, fullName } ;
76+ } ) )
6177 ) ;
78+
79+ for ( const { distDir, distPath } of config . dists ) {
80+ await Promise . all (
81+ packageInfoList . map ( ( { packagePath, cwd, pkg, fullName } ) =>
82+ limit ( ( ) => build ( { packagePath, cwd, pkg, fullName, config, reporter, distDir, distPath, packageInfoList } ) )
83+ )
84+ ) ;
85+ }
6286 } ,
6387 } ;
6488} ) ;
6589
66- async function buildSingle ( ) {
90+ async function buildSingle ( { distDir , distPath = '' } : { distDir : string ; distPath ?: string ; } ) {
6791 const cwd = process . cwd ( ) ;
6892 const packagePath = join ( process . cwd ( ) , "package.json" ) ;
69- const pkg = await readPackageJson ( cwd ) ;
93+ const pkg = await fs . readJSON ( packagePath ) ;
7094
7195 validatePackageJson ( pkg ) ;
7296
@@ -87,7 +111,7 @@ async function buildSingle() {
87111 } ) ,
88112 typescript ( ) ,
89113 generatePackageJson ( {
90- baseContents : rewritePackageJson ( pkg ) ,
114+ baseContents : rewritePackageJson ( pkg , distPath ) ,
91115 additionalDependencies : Object . keys ( pkg . dependencies || { } ) ,
92116 } ) ,
93117 ] ,
@@ -108,24 +132,16 @@ async function buildSingle() {
108132 const generates = [
109133 {
110134 ...commonOutputOptions ,
111- file : join ( distDir , "index.cjs. js" ) ,
135+ file : join ( distDir , "index.js" ) ,
112136 format : "cjs" as const ,
113137 } ,
114138 {
115139 ...commonOutputOptions ,
116- file : join ( distDir , "index.esm.js " ) ,
140+ file : join ( distDir , "index.mjs " ) ,
117141 format : "esm" as const ,
118142 } ,
119143 ] ;
120144
121- if ( pkg . exports ) {
122- generates . push ( {
123- ...commonOutputOptions ,
124- file : join ( distDir , "index.mjs" ) ,
125- format : "esm" as const ,
126- } ) ;
127- }
128-
129145 await Promise . all (
130146 generates . map ( async ( outputOptions ) => {
131147 await bundle . write ( outputOptions ) ;
@@ -135,26 +151,22 @@ async function buildSingle() {
135151 // move README.md and LICENSE
136152 await copyToDist (
137153 cwd ,
138- [ "README.md" , "LICENSE" ] . concat ( buildOptions ?. copy || [ ] )
154+ [ "README.md" , "LICENSE" ] . concat ( buildOptions ?. copy || [ ] ) ,
155+ DIST_DIR + distPath
139156 ) ;
140157}
141158
142159async function build (
143- packagePath : string ,
144- config : BobConfig ,
145- reporter : Consola
160+ { packagePath, cwd, pkg, fullName, config, reporter, distDir, distPath = '' , packageInfoList } : { packagePath : string ; cwd : string ; pkg : any ; fullName : string ; config : BobConfig ; reporter : Consola ; distDir : string ; distPath ?: string ; packageInfoList : PackageInfo [ ] } ,
146161) {
147162 const scope = config . scope ;
148- const cwd = packagePath . replace ( "/package.json" , "" ) ;
149- const pkg = await readPackageJson ( cwd ) ;
150- const fullName : string = pkg . name ;
151163
152164 if ( ( config . ignore || [ ] ) . includes ( fullName ) ) {
153165 reporter . warn ( `Ignored ${ fullName } ` ) ;
154166 return ;
155167 }
156168
157- const name = fullName . replace ( `${ scope } /` , "" ) ;
169+ const name = fullName . replace ( `${ scope } /` , distPath ) ;
158170
159171 validatePackageJson ( pkg ) ;
160172
@@ -184,7 +196,7 @@ async function build(
184196 packageJSONPath : packagePath ,
185197 } ) ,
186198 generatePackageJson ( {
187- baseContents : rewritePackageJson ( pkg ) ,
199+ baseContents : rewritePackageJson ( pkg , distPath ) ,
188200 additionalDependencies : Object . keys ( pkg . dependencies || { } ) ,
189201 } ) ,
190202 ] ,
@@ -205,24 +217,16 @@ async function build(
205217 const generates = [
206218 {
207219 ...commonOutputOptions ,
208- file : join ( bobProjectDir , "index.cjs. js" ) ,
220+ file : join ( bobProjectDir , "index.js" ) ,
209221 format : "cjs" as const ,
210222 } ,
211223 {
212224 ...commonOutputOptions ,
213- file : join ( bobProjectDir , "index.esm.js " ) ,
225+ file : join ( bobProjectDir , "index.mjs " ) ,
214226 format : "esm" as const ,
215227 } ,
216228 ] ;
217229
218- if ( pkg . exports ) {
219- generates . push ( {
220- ...commonOutputOptions ,
221- file : join ( distDir , "index.mjs" ) ,
222- format : "esm" as const ,
223- } ) ;
224- }
225-
226230 const declarations = await globby ( "**/*.d.ts" , {
227231 cwd : distProjectSrcDir ,
228232 ignore : [ "**/node_modules/**" ] ,
@@ -269,37 +273,45 @@ async function build(
269273 banner : `#!/usr/bin/env node` ,
270274 preferConst : true ,
271275 sourcemap : options . sourcemap ,
272- file : join ( bobProjectDir , pkg . bin [ alias ] . replace ( `${ distDir } /` , "" ) ) ,
276+ file : join ( bobProjectDir , pkg . bin [ alias ] . replace ( `${ DIST_DIR } /` , "" ) ) ,
273277 format : "cjs" ,
274278 } ) ;
275279 } )
276280 ) ;
277281 }
278282
279283 // remove <project>/dist
280- await fs . remove ( join ( cwd , distDir ) ) ;
284+ await fs . remove ( join ( cwd , DIST_DIR + distPath ) ) ;
285+
286+ // fix distPath import in extra dists
287+ function replaceAll ( str : string , from : string , to : string ) {
288+ return str . split ( from ) . join ( to ) ;
289+ }
290+ if ( distPath ) {
291+ await Promise . all (
292+ generates . map ( ( { file } ) => limit ( async ( ) => {
293+ let content = await fs . readFile ( file , 'utf8' ) ;
294+ for ( const { fullName } of packageInfoList ) {
295+ content = replaceAll ( content , `'${ fullName } '` , `'${ fullName } ${ distPath } '` ) ;
296+ }
297+ await fs . writeFile ( file , content , { encoding : 'utf8' , flag : 'w' } ) ;
298+ } ) )
299+ )
300+ }
301+
281302 // move bob/<project-name> to <project>/dist
282- await fs . move ( bobProjectDir , join ( cwd , distDir ) ) ;
303+ await fs . move ( bobProjectDir , join ( cwd , DIST_DIR + distPath ) ) ;
283304 // move README.md and LICENSE
284305 await copyToDist (
285306 cwd ,
286- [ "README.md" , "LICENSE" ] . concat ( pkg . buildOptions ?. copy || [ ] )
307+ [ "README.md" , "LICENSE" ] . concat ( pkg . buildOptions ?. copy || [ ] ) ,
308+ DIST_DIR + distPath
287309 ) ;
288310
289311 reporter . success ( `Built ${ pkg . name } ` ) ;
290312}
291313
292- //
293-
294- export async function readPackageJson ( baseDir : string ) {
295- return JSON . parse (
296- await fs . readFile ( resolve ( baseDir , "package.json" ) , {
297- encoding : "utf-8" ,
298- } )
299- ) ;
300- }
301-
302- function rewritePackageJson ( pkg : Record < string , any > ) {
314+ function rewritePackageJson ( pkg : Record < string , any > , distPath : string ) {
303315 const newPkg : Record < string , any > = { } ;
304316 const fields = [
305317 "name" ,
@@ -323,18 +335,30 @@ function rewritePackageJson(pkg: Record<string, any>) {
323335 }
324336 } ) ;
325337
326- newPkg . main = "index.cjs.js" ;
327- newPkg . module = "index.esm.js" ;
338+ newPkg . name += distPath ;
339+ newPkg . main = "index.js" ;
340+ newPkg . module = "index.mjs" ;
328341 newPkg . typings = "index.d.ts" ;
329342 newPkg . typescript = {
330343 definition : newPkg . typings ,
331344 } ;
332345
346+ newPkg . exports = {
347+ "." : {
348+ require : "./index.js" ,
349+ import : "./index.mjs" ,
350+ } ,
351+ "./*" : {
352+ require : "./*.js" ,
353+ import : "./*.mjs" ,
354+ } ,
355+ } ;
356+
333357 if ( pkg . bin ) {
334358 newPkg . bin = { } ;
335359
336360 for ( const alias in pkg . bin ) {
337- newPkg . bin [ alias ] = pkg . bin [ alias ] . replace ( `${ distDir } /` , "" ) ;
361+ newPkg . bin [ alias ] = pkg . bin [ alias ] . replace ( `${ DIST_DIR } /` , "" ) ;
338362 }
339363 }
340364
@@ -352,18 +376,19 @@ export function validatePackageJson(pkg: any) {
352376 }
353377 }
354378
355- expect ( "main" , `${ distDir } /index.cjs .js` ) ;
356- expect ( "module" , `${ distDir } /index.esm.js ` ) ;
357- expect ( "typings" , `${ distDir } /index.d.ts` ) ;
358- expect ( "typescript.definition" , `${ distDir } /index.d.ts` ) ;
379+ expect ( "main" , `${ DIST_DIR } /index.js` ) ;
380+ expect ( "module" , `${ DIST_DIR } /index.mjs ` ) ;
381+ expect ( "typings" , `${ DIST_DIR } /index.d.ts` ) ;
382+ expect ( "typescript.definition" , `${ DIST_DIR } /index.d.ts` ) ;
359383
360- if ( pkg . exports ) {
361- expect ( "exports.require" , `./${ pkg . main } ` ) ;
362- expect ( "exports.default" , `./${ distDir } /index.mjs` ) ;
363- }
384+ expect ( "exports['.'].require" , `./${ DIST_DIR } /index.js` ) ;
385+ expect ( "exports['.'].import" , `./${ DIST_DIR } /index.mjs` ) ;
386+
387+ expect ( "exports['./*'].require" , `./${ DIST_DIR } /*.js` ) ;
388+ expect ( "exports['./*'].import" , `./${ DIST_DIR } /*.mjs` ) ;
364389}
365390
366- async function copyToDist ( cwd : string , files : string [ ] ) {
391+ async function copyToDist ( cwd : string , files : string [ ] , distDir : string ) {
367392 const allFiles = await globby ( files , { cwd } ) ;
368393
369394 return Promise . all (
0 commit comments