@@ -20,7 +20,14 @@ interface BuildOptions {
2020 bin ?: Record < string , { input : string ; sourcemap ?: boolean } > ;
2121}
2222
23- export const distDir = "dist" ;
23+ 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 ] ,
@@ -135,26 +159,22 @@ async function buildSingle() {
135159 // move README.md and LICENSE
136160 await copyToDist (
137161 cwd ,
138- [ "README.md" , "LICENSE" ] . concat ( buildOptions ?. copy || [ ] )
162+ [ "README.md" , "LICENSE" ] . concat ( buildOptions ?. copy || [ ] ) ,
163+ DIST_DIR + distPath
139164 ) ;
140165}
141166
142167async function build (
143- packagePath : string ,
144- config : BobConfig ,
145- reporter : Consola
168+ { 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 [ ] } ,
146169) {
147170 const scope = config . scope ;
148- const cwd = packagePath . replace ( "/package.json" , "" ) ;
149- const pkg = await readPackageJson ( cwd ) ;
150- const fullName : string = pkg . name ;
151171
152172 if ( ( config . ignore || [ ] ) . includes ( fullName ) ) {
153173 reporter . warn ( `Ignored ${ fullName } ` ) ;
154174 return ;
155175 }
156176
157- const name = fullName . replace ( `${ scope } /` , "" ) ;
177+ const name = fullName . replace ( `${ scope } /` , distPath ) ;
158178
159179 validatePackageJson ( pkg ) ;
160180
@@ -184,7 +204,7 @@ async function build(
184204 packageJSONPath : packagePath ,
185205 } ) ,
186206 generatePackageJson ( {
187- baseContents : rewritePackageJson ( pkg ) ,
207+ baseContents : rewritePackageJson ( pkg , distPath ) ,
188208 additionalDependencies : Object . keys ( pkg . dependencies || { } ) ,
189209 } ) ,
190210 ] ,
@@ -218,7 +238,7 @@ async function build(
218238 if ( pkg . exports ) {
219239 generates . push ( {
220240 ...commonOutputOptions ,
221- file : join ( distDir , "index.mjs" ) ,
241+ file : join ( bobProjectDir , "index.mjs" ) ,
222242 format : "esm" as const ,
223243 } ) ;
224244 }
@@ -269,37 +289,45 @@ async function build(
269289 banner : `#!/usr/bin/env node` ,
270290 preferConst : true ,
271291 sourcemap : options . sourcemap ,
272- file : join ( bobProjectDir , pkg . bin [ alias ] . replace ( `${ distDir } /` , "" ) ) ,
292+ file : join ( bobProjectDir , pkg . bin [ alias ] . replace ( `${ DIST_DIR } /` , "" ) ) ,
273293 format : "cjs" ,
274294 } ) ;
275295 } )
276296 ) ;
277297 }
278298
279299 // remove <project>/dist
280- await fs . remove ( join ( cwd , distDir ) ) ;
300+ await fs . remove ( join ( cwd , DIST_DIR + distPath ) ) ;
301+
302+ // fix distPath import in extra dists
303+ function replaceAll ( str : string , from : string , to : string ) {
304+ return str . split ( from ) . join ( to ) ;
305+ }
306+ if ( distPath ) {
307+ await Promise . all (
308+ generates . map ( ( { file } ) => limit ( async ( ) => {
309+ let content = await fs . readFile ( file , 'utf8' ) ;
310+ for ( const { fullName } of packageInfoList ) {
311+ content = replaceAll ( content , `'${ fullName } '` , `'${ fullName } ${ distPath } '` ) ;
312+ }
313+ await fs . writeFile ( file , content , { encoding : 'utf8' , flag : 'w' } ) ;
314+ } ) )
315+ )
316+ }
317+
281318 // move bob/<project-name> to <project>/dist
282- await fs . move ( bobProjectDir , join ( cwd , distDir ) ) ;
319+ await fs . move ( bobProjectDir , join ( cwd , DIST_DIR + distPath ) ) ;
283320 // move README.md and LICENSE
284321 await copyToDist (
285322 cwd ,
286- [ "README.md" , "LICENSE" ] . concat ( pkg . buildOptions ?. copy || [ ] )
323+ [ "README.md" , "LICENSE" ] . concat ( pkg . buildOptions ?. copy || [ ] ) ,
324+ DIST_DIR + distPath
287325 ) ;
288326
289327 reporter . success ( `Built ${ pkg . name } ` ) ;
290328}
291329
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 > ) {
330+ function rewritePackageJson ( pkg : Record < string , any > , distPath : string ) {
303331 const newPkg : Record < string , any > = { } ;
304332 const fields = [
305333 "name" ,
@@ -323,6 +351,7 @@ function rewritePackageJson(pkg: Record<string, any>) {
323351 }
324352 } ) ;
325353
354+ newPkg . name += distPath ;
326355 newPkg . main = "index.cjs.js" ;
327356 newPkg . module = "index.esm.js" ;
328357 newPkg . typings = "index.d.ts" ;
@@ -334,7 +363,7 @@ function rewritePackageJson(pkg: Record<string, any>) {
334363 newPkg . bin = { } ;
335364
336365 for ( const alias in pkg . bin ) {
337- newPkg . bin [ alias ] = pkg . bin [ alias ] . replace ( `${ distDir } /` , "" ) ;
366+ newPkg . bin [ alias ] = pkg . bin [ alias ] . replace ( `${ DIST_DIR } /` , "" ) ;
338367 }
339368 }
340369
@@ -352,18 +381,18 @@ export function validatePackageJson(pkg: any) {
352381 }
353382 }
354383
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` ) ;
384+ expect ( "main" , `${ DIST_DIR } /index.cjs.js` ) ;
385+ expect ( "module" , `${ DIST_DIR } /index.esm.js` ) ;
386+ expect ( "typings" , `${ DIST_DIR } /index.d.ts` ) ;
387+ expect ( "typescript.definition" , `${ DIST_DIR } /index.d.ts` ) ;
359388
360389 if ( pkg . exports ) {
361- expect ( "exports.require" , `./ ${ pkg . main } ` ) ;
362- expect ( "exports.default" , `./ ${ distDir } /index.mjs` ) ;
390+ expect ( "exports.require" , pkg . main ) ;
391+ expect ( "exports.default" , `${ DIST_DIR } /index.mjs` ) ;
363392 }
364393}
365394
366- async function copyToDist ( cwd : string , files : string [ ] ) {
395+ async function copyToDist ( cwd : string , files : string [ ] , distDir : string ) {
367396 const allFiles = await globby ( files , { cwd } ) ;
368397
369398 return Promise . all (
0 commit comments