@@ -5,6 +5,11 @@ const path = require('path')
55const { safeReadPackageJsonFromDir } = require ( '@pnpm/read-package-json' )
66const { runLifecycleHook } = require ( '@pnpm/lifecycle' )
77
8+ const { rollup} = require ( 'rollup' ) ;
9+ const { dts} = require ( 'rollup-plugin-dts' ) ;
10+ const commonjs = require ( '@rollup/plugin-commonjs' ) ;
11+ const { nodeResolve } = require ( '@rollup/plugin-node-resolve' ) ;
12+
813async function mkdirp ( p ) {
914 if ( p && ! fs . existsSync ( p ) ) {
1015 await mkdirp ( path . dirname ( p ) )
@@ -128,6 +133,89 @@ function isWindows() {
128133 return os . platform ( ) === 'win32'
129134}
130135
136+
137+ async function optimizePackage ( destDir ) {
138+ // We first copy the package to a temporary directory so that we don't have `node_modules`
139+ // in our name. Otherwise, `dts` will refuse to do anthing, since `respectExternals` defaults to false.
140+ // Setting that to true will inline _all_ externals (including dependencies), which
141+ // can break typechecking. Better to bundle the dependencies on their own.
142+ const tempDir = await fs . promises . mkdtemp ( path . join ( os . tmpdir ( ) , 'aspect_rules_js_' ) ) ;
143+ await fs . promises . cp ( destDir , tempDir , { recursive : true , force : true } ) ;
144+
145+ const packageJsonText = await fs . promises . readFile ( path . join ( tempDir , 'package.json' ) ) ;
146+ const packageJson = JSON . parse ( packageJsonText ) ;
147+
148+ const typesMain = path . join ( tempDir , packageJson . types ) ;
149+ const cjsMain = path . join ( tempDir , packageJson . main ) ;
150+ const esmMain = path . join ( tempDir , packageJson . module ) ;
151+
152+ async function bundleDts ( input ) {
153+ const result = await rollup ( {
154+ input,
155+ plugins : [ dts ( ) ] ,
156+ } ) ;
157+ await result . write ( {
158+ file : input ,
159+ format : 'esm' ,
160+ } ) ;
161+ }
162+
163+ async function bundle ( input , format , plugins ) {
164+ const result = await rollup ( {
165+ input,
166+ output : {
167+ file : input ,
168+ format,
169+ } ,
170+ plugins,
171+ external : [ / p a c k a g e \. j s o n $ / ] ,
172+ } ) ;
173+ await result . write ( {
174+ file : input ,
175+ format,
176+ } ) ;
177+ }
178+
179+ const bundlePromises = [ ] ;
180+ typesMain && bundlePromises . push ( bundleDts ( typesMain ) ) ;
181+ cjsMain && bundlePromises . push ( bundle ( cjsMain , 'cjs' , [ commonjs ( ) ] ) ) ;
182+ esmMain && bundlePromises . push ( bundle ( esmMain , 'esm' , [ nodeResolve ( ) ] ) ) ;
183+
184+ // Would be faster to use esbuild, but we cannot bundle esbuild itself :/
185+ /*cjsMain && bundlePromises.push(esbuild.build({
186+ entryPoints: [cjsMain],
187+ bundle: true,
188+ outfile: cjsMain,
189+ platform: 'node',
190+ format: 'cjs',
191+ }));
192+ esmMain && bundlePromises.push(esbuild.build({
193+ entryPoints: [esmMain],
194+ bundle: true,
195+ outfile: esmMain,
196+ platform: 'node',
197+ format: 'esm',
198+ }));*/
199+
200+ await Promise . all ( bundlePromises ) ;
201+
202+ await fs . promises . rm ( destDir , { recursive : true , force : true } ) ;
203+
204+ async function rename ( tmpPath , realPath ) {
205+ const realDir = path . dirname ( realPath ) ;
206+ await fs . promises . mkdir ( realDir , { recursive : true } ) ;
207+ await fs . promises . cp ( tmpPath , realPath ) ;
208+ }
209+
210+ const emitPromises = [ ] ;
211+ typesMain && emitPromises . push ( rename ( typesMain , path . join ( destDir , packageJson . types ) ) ) ;
212+ cjsMain && emitPromises . push ( rename ( cjsMain , path . join ( destDir , packageJson . main ) ) ) ;
213+ esmMain && emitPromises . push ( rename ( esmMain , path . join ( destDir , packageJson . module ) ) ) ;
214+ await Promise . all ( emitPromises ) ;
215+
216+ await fs . promises . writeFile ( path . join ( destDir , 'package.json' ) , packageJsonText ) ;
217+ }
218+
131219async function main ( args ) {
132220 if ( args . length < 3 ) {
133221 console . error (
@@ -260,6 +348,10 @@ async function main(args) {
260348 // Run user specified custom postinstall hook
261349 await runLifecycleHook ( 'custom_postinstall' , rulesJsJson , opts )
262350 }
351+
352+ if ( rulesJsJson . optimize_package ) {
353+ await optimizePackage ( outputDir ) ;
354+ }
263355}
264356
265357// Copy contents of a package dir to a destination dir (without copying the package dir itself)
0 commit comments