diff --git a/README.md b/README.md index 04105bd..35e0404 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@

pkgroll
- +

_pkgroll_ is a JavaScript package bundler powered by Rollup that automatically builds your package from entry-points defined in `package.json`. No config necessary! @@ -38,7 +38,7 @@ npm install --save-dev pkgroll 2. Define package entry-files in `package.json`. [These configurations](https://nodejs.org/api/packages.html#package-entry-points) are for Node.js to determine how to import the package. - + Pkgroll leverages the same configuration to determine how to build the package. ```json5 @@ -237,6 +237,12 @@ Run the bundler in watch mode during development: pkgroll --watch ``` +### Clean dist +Clean dist directory before bundling: +```sh +pkgroll --clean-dist +``` + ## FAQ ### Why bundle with Rollup? diff --git a/src/cli.ts b/src/cli.ts index 51233f1..7075b18 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -10,6 +10,7 @@ import { getSourcePath } from './utils/get-source-path.js'; import { getRollupConfigs } from './utils/get-rollup-configs.js'; import { tsconfig } from './utils/tsconfig.js'; import { log } from './utils/log.js'; +import { cleanDist } from './utils/clean-dist.js'; const { stringify } = JSON; @@ -78,6 +79,11 @@ const argv = cli({ }, description: 'Sourcemap generation. Provide `inline` option for inline sourcemap (eg. --sourcemap, --sourcemap=inline)', }, + cleanDist: { + type: Boolean, + description: 'Clean dist before bundling', + default: false, + }, }, help: { @@ -149,6 +155,15 @@ if (tsconfigTarget) { packageJson, ); + if (argv.flags.cleanDist) { + /** + * Typically, something like this would be implemented as a plugin, so it only + * deletes what it needs to but pkgroll runs multiple builds (e.g. d.ts, mjs, etc) + * so as a plugin, it won't be aware of the files emitted by other builds + */ + await cleanDist(distPath); + } + if (argv.flags.watch) { log('Watch initialized'); diff --git a/src/utils/clean-dist.ts b/src/utils/clean-dist.ts new file mode 100644 index 0000000..b3f9ba0 --- /dev/null +++ b/src/utils/clean-dist.ts @@ -0,0 +1,14 @@ +import fs from 'fs'; +import { fsExists } from './fs-exists.js'; + +export const cleanDist = async (directoryPath: string) => { + const exists = await fsExists(directoryPath); + if (!exists) { + return; + } + + await fs.promises.rm(directoryPath, { + recursive: true, + force: true, + }); +}; diff --git a/tests/specs/builds/clean-dist.ts b/tests/specs/builds/clean-dist.ts new file mode 100644 index 0000000..d4418ce --- /dev/null +++ b/tests/specs/builds/clean-dist.ts @@ -0,0 +1,105 @@ +import path from 'path'; +import fs from 'fs/promises'; +import { testSuite, expect } from 'manten'; +import { createFixture } from 'fs-fixture'; +import { pkgroll, installTypeScript } from '../../utils.js'; + +export default testSuite(({ describe }, nodePath: string) => { + describe('clean dist', ({ test }) => { + test('no flag', async ({ onTestFinish }) => { + const fixture = await createFixture('./tests/fixture-package'); + onTestFinish(async () => await fixture.rm()); + + installTypeScript(fixture.path); + + await fixture.writeJson('package.json', { + main: './dist/nested/index.js', + module: './dist/nested/index.mjs', + types: './dist/nested/index.d.ts', + }); + + await pkgroll( + [], + { + cwd: fixture.path, + nodePath, + }, + ); + + await fs.mkdir(path.join(fixture.path, 'src', 'nested2')); + await fixture.writeFile('./src/nested2/index.ts', 'export function sayHello2(name: string) { return name; }'); + + await fixture.writeJson('package.json', { + main: './dist/nested2/index.js', + module: './dist/nested2/index.mjs', + types: './dist/nested2/index.d.ts', + }); + + const pkgrollProcess = await pkgroll( + [], + { + cwd: fixture.path, + nodePath, + }, + ); + + expect(pkgrollProcess.exitCode).toBe(0); + expect(pkgrollProcess.stderr).toBe(''); + + expect(await fixture.exists('dist/nested/index.js')).toBe(true); + expect(await fixture.exists('dist/nested/index.mjs')).toBe(true); + expect(await fixture.exists('dist/nested/index.d.ts')).toBe(true); + expect(await fixture.exists('dist/nested2/index.js')).toBe(true); + expect(await fixture.exists('dist/nested2/index.mjs')).toBe(true); + expect(await fixture.exists('dist/nested2/index.d.ts')).toBe(true); + }); + + test('with flag', async ({ onTestFinish }) => { + const fixture = await createFixture('./tests/fixture-package'); + onTestFinish(async () => await fixture.rm()); + + installTypeScript(fixture.path); + + await fixture.writeJson('package.json', { + main: './dist/nested/index.js', + module: './dist/nested/index.mjs', + types: './dist/nested/index.d.ts', + }); + + await pkgroll( + [], + { + cwd: fixture.path, + nodePath, + }, + ); + + await fs.mkdir(path.join(fixture.path, 'src', 'nested2')); + await fixture.writeFile('./src/nested2/index.ts', 'export function sayHello2(name: string) { return name; }'); + + await fixture.writeJson('package.json', { + main: './dist/nested2/index.js', + module: './dist/nested2/index.mjs', + types: './dist/nested2/index.d.ts', + }); + + const pkgrollProcess = await pkgroll( + ['--clean-dist'], + { + cwd: fixture.path, + nodePath, + }, + ); + + expect(pkgrollProcess.exitCode).toBe(0); + expect(pkgrollProcess.stderr).toBe(''); + + expect(await fixture.exists('dist/nested/index.js')).toBe(false); + expect(await fixture.exists('dist/nested/index.mjs')).toBe(false); + expect(await fixture.exists('dist/nested/index.d.ts')).toBe(false); + expect(await fixture.exists('dist/nested2/index.js')).toBe(true); + expect(await fixture.exists('dist/nested2/index.mjs')).toBe(true); + expect(await fixture.exists('dist/nested2/index.d.ts')).toBe(true); + }); + }); +}); diff --git a/tests/specs/builds/index.ts b/tests/specs/builds/index.ts index 86db517..7e8a7d9 100644 --- a/tests/specs/builds/index.ts +++ b/tests/specs/builds/index.ts @@ -16,5 +16,6 @@ export default testSuite(({ describe }, nodePath: string) => { runTestSuite(import('./src-dist.js'), nodePath); runTestSuite(import('./sourcemap.js'), nodePath); runTestSuite(import('./typescript.js'), nodePath); + runTestSuite(import('./clean-dist.js'), nodePath); }); });