diff --git a/README.md b/README.md index 6de5f05..530519f 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,20 @@ # @kineticcafe/rollup-plugin-delete -Delete files and folders using Rollup. This is a fork of the excellent -[rollup-plugin-delete][]. The changes are mostly: +A Rollup plugin to delete files and folders during the build process. This is +a fork of the excellent [`rollup-plugin-delete`][rpd]. The changes are: -- Convert to Typescript. The previous version produces TS2349 even though the +- Convert to Typescript. The previous version produces `TS2349` even though the created type declaration file and the generated type declaration file are more or less the same. +- Removing [`del`][del], which depends on outdated versions of + [`globby`][globby] and [`rimraf`][rimraf]. + ## About This plugin is useful when you want to clean `dist` or other folders and files -before bundling. It's using [del][] internally, check it for pattern examples. +before bundling. Targets use [`minimatch` pattern matching][minimatch], so +review the documentation for patterns. ## Installation @@ -27,7 +31,7 @@ npm install -D @kineticcafe/rollup-plugin-delete ## Usage -```js +```javascript // rollup.config.js import { del } from '@kineticcafe/rollup-plugin-delete' @@ -41,7 +45,8 @@ export default { } ``` -You can also remove files after the bundle has been written: +You can also remove files after the bundle has been written by changing the +`hook`: ```typescript // vite.config.ts @@ -62,65 +67,41 @@ export default defineConfig({ ### Configuration -There are some useful options: +| Name | Type | Default | Purpose | +| ------------- | ---------------------- | ------------- | -------------------------------------------------------------------------------------- | +| `targets` | `string` \| `string[]` | [] | A string or an array of patterns of files and folders to be deleted. | +| `verbose` | `boolean` | `false` | Output removed files and folders to console. Default is `false`. | +| `hook` | `string` | `buildStart` | The [Rollup hook](https://rollupjs.org/guide/en/#build-hooks) the plugin should use. | +| `runOnce` | `boolean` | `false` | Delete items once. Useful in watch mode. | +| `dryRun` | `boolean` | `false` | Does not remove the files, but reports what would be removed. Implies `verbose: true`. | +| `concurrency` | `number` | `Infinity` | Concurrency limit. Minimum `1`. | +| `cwd` | `string` | `process.cwd` | The current working directory in which to search. | -#### `targets` +All other options are inherited from `globby`, but [`expandDirectories`][ed], +[`onlyFiles`][of], and [`followSymbolicLinks`][fsl] default to `false`. -A string or an array of patterns of files and folders to be deleted. Default is -`[]`. +#### Examples -```js +```javascript del({ targets: 'dist/*' }) - -del({ - targets: ['dist/*', 'build/*'], -}) -``` - -#### `verbose` - -Output removed files and folders to console. Default is `false`. - -```js -del({ - targets: 'dist/*', - verbose: true, -}) -``` - -> Note: use \* (wildcard character) in pattern to show removed files - -#### `hook` - -The [Rollup hook](https://rollupjs.org/guide/en/#build-hooks) the plugin should -use. Default is `buildStart`. - -```js -del({ - targets: 'dist/*', - hook: 'buildEnd', -}) -``` - -#### `runOnce` - -Type: `boolean` | Default: `false` - -Delete items once. Useful in watch mode. - -```js -del({ - targets: 'dist/*', - runOnce: true, -}) +del({ targets: ['dist/*', 'build/*'] }) +del({ targets: 'dist/*', verbose: true }) +del({ targets: 'dist/*', hook: 'buildEnd' }) +del({ targets: 'dist/*', runOnce: true }) +del({ targets: 'dist/*', dryRun: true }) ``` -All other options are passed to [del -package](https://github.com/sindresorhus/del) which is used inside. +> Note: use `*` (wildcard character) in the pattern to show removed files. ## License MIT -[rollup-plugin-delete]: https://github.com/vladshcherbin/rollup-plugin-delete +[rpd]: https://github.com/vladshcherbin/rollup-plugin-delete [del]: https://github.com/sindresorhus/del +[rimraf]: https://github.com/isaacs/rimraf +[globby]: https://github.com/sindresorhus/globby +[minimatch]: https://github.com/isaacs/minimatch#features +[ed]: https://github.com/sindresorhus/globby?tab=readme-ov-file#expanddirectories +[of]: https://github.com/mrmlnc/fast-glob?tab=readme-ov-file#onlyfiles +[fsl]: https://github.com/mrmlnc/fast-glob?tab=readme-ov-file#followsymboliclinks diff --git a/package.json b/package.json index 165a315..d3a0a6b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kineticcafe/rollup-plugin-delete", - "version": "3.0.0-beta.1", + "version": "3.0.0", "type": "module", "contributors": [ "Vlad Shcherbin ", @@ -48,16 +48,24 @@ "test": "vitest" }, "dependencies": { - "del": "^7.1.0" + "globby": "^14.0.1", + "is-glob": "^4.0.3", + "is-path-cwd": "^3.0.0", + "is-path-inside": "^4.0.0", + "p-map": "^7.0.2", + "rimraf": "^5.0.7", + "slash": "^5.1.0" }, "devDependencies": { "@biomejs/biome": "^1.8.1", "@types/fs-extra": "^11.0.4", + "@types/graceful-fs": "^4.1.9", + "@types/is-glob": "^4.0.4", + "@types/node": "20", "@types/rollup-plugin-auto-external": "^2.0.5", "fs-extra": "^11.2.0", "publint": "^0.2.8", "replace-in-file": "^7.2.0", - "rimraf": "^5.0.7", "rollup": "^4.18.0", "rollup-plugin-auto-external": "^2.0.0", "typescript": "^5.4.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f588a68..1f17570 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,9 +8,27 @@ importers: .: dependencies: - del: - specifier: ^7.1.0 - version: 7.1.0 + globby: + specifier: ^14.0.1 + version: 14.0.1 + is-glob: + specifier: ^4.0.3 + version: 4.0.3 + is-path-cwd: + specifier: ^3.0.0 + version: 3.0.0 + is-path-inside: + specifier: ^4.0.0 + version: 4.0.0 + p-map: + specifier: ^7.0.2 + version: 7.0.2 + rimraf: + specifier: ^5.0.7 + version: 5.0.7 + slash: + specifier: ^5.1.0 + version: 5.1.0 devDependencies: '@biomejs/biome': specifier: ^1.8.1 @@ -18,6 +36,15 @@ importers: '@types/fs-extra': specifier: ^11.0.4 version: 11.0.4 + '@types/graceful-fs': + specifier: ^4.1.9 + version: 4.1.9 + '@types/is-glob': + specifier: ^4.0.4 + version: 4.0.4 + '@types/node': + specifier: '20' + version: 20.14.2 '@types/rollup-plugin-auto-external': specifier: ^2.0.5 version: 2.0.5 @@ -30,9 +57,6 @@ importers: replace-in-file: specifier: ^7.2.0 version: 7.2.0 - rimraf: - specifier: ^5.0.7 - version: 5.0.7 rollup: specifier: ^4.18.0 version: 4.18.0 @@ -349,12 +373,22 @@ packages: '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + '@sindresorhus/merge-streams@2.3.0': + resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} + engines: {node: '>=18'} + '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} '@types/fs-extra@11.0.4': resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} + '@types/graceful-fs@4.1.9': + resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + + '@types/is-glob@4.0.4': + resolution: {integrity: sha512-3mFBtIPQ0TQetKRDe94g8YrxJZxdMillMGegyv6zRBXvq4peRRhf2wLZ/Dl53emtTsC29dQQBwYvovS20yXpiQ==} + '@types/jsonfile@6.1.4': resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} @@ -388,10 +422,6 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - aggregate-error@4.0.1: - resolution: {integrity: sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==} - engines: {node: '>=12'} - ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -418,9 +448,6 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} @@ -446,10 +473,6 @@ packages: check-error@1.0.3: resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} - clean-stack@4.2.0: - resolution: {integrity: sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==} - engines: {node: '>=12'} - cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -461,9 +484,6 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - confbox@0.1.7: resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} @@ -484,18 +504,10 @@ packages: resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} engines: {node: '>=6'} - del@7.1.0: - resolution: {integrity: sha512-v2KyNk7efxhlyHpjEvfyxaAihKKK0nWCuf6ZtqZcFFpQRG0bJ12Qsr0RpvsICMjAAZ8DOVCxrlqpxISlMHC4Kg==} - engines: {node: '>=14.16'} - diff-sequences@29.6.3: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -517,10 +529,6 @@ packages: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} - escape-string-regexp@5.0.0: - resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} - engines: {node: '>=12'} - estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -578,18 +586,14 @@ packages: engines: {node: '>=16 || 14 >=14.18'} hasBin: true - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - glob@8.1.0: resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} engines: {node: '>=12'} deprecated: Glob versions prior to v9 are no longer supported - globby@13.2.2: - resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + globby@14.0.1: + resolution: {integrity: sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==} + engines: {node: '>=18'} graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -617,10 +621,6 @@ packages: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} - indent-string@5.0.0: - resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} - engines: {node: '>=12'} - inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. @@ -711,9 +711,6 @@ packages: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - minimatch@5.1.6: resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} engines: {node: '>=10'} @@ -772,18 +769,14 @@ packages: resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} engines: {node: '>=18'} - p-map@5.5.0: - resolution: {integrity: sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==} - engines: {node: '>=12'} + p-map@7.0.2: + resolution: {integrity: sha512-z4cYYMMdKHzw4O5UkWJImbZynVIo0lSGTXc7bzB1e/rrDqkgGUNysK/o4bTr+0+xKvvLoTyGqYC4Fgljy9qe1Q==} + engines: {node: '>=18'} parse-json@4.0.0: resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} engines: {node: '>=4'} - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -803,9 +796,9 @@ packages: resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==} engines: {node: '>=4'} - path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} + path-type@5.0.0: + resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==} + engines: {node: '>=12'} pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} @@ -867,11 +860,6 @@ packages: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - rimraf@5.0.7: resolution: {integrity: sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==} engines: {node: '>=14.18'} @@ -921,9 +909,9 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - slash@4.0.0: - resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} - engines: {node: '>=12'} + slash@5.1.0: + resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} + engines: {node: '>=14.16'} source-map-js@1.2.0: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} @@ -1012,6 +1000,10 @@ packages: undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} + universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} @@ -1300,6 +1292,8 @@ snapshots: '@sinclair/typebox@0.27.8': {} + '@sindresorhus/merge-streams@2.3.0': {} + '@types/estree@1.0.5': {} '@types/fs-extra@11.0.4': @@ -1307,6 +1301,12 @@ snapshots: '@types/jsonfile': 6.1.4 '@types/node': 20.14.2 + '@types/graceful-fs@4.1.9': + dependencies: + '@types/node': 20.14.2 + + '@types/is-glob@4.0.4': {} + '@types/jsonfile@6.1.4': dependencies: '@types/node': 20.14.2 @@ -1354,11 +1354,6 @@ snapshots: acorn@8.12.0: {} - aggregate-error@4.0.1: - dependencies: - clean-stack: 4.2.0 - indent-string: 5.0.0 - ansi-regex@5.0.1: {} ansi-regex@6.0.1: {} @@ -1375,11 +1370,6 @@ snapshots: balanced-match@1.0.2: {} - brace-expansion@1.1.11: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - brace-expansion@2.0.1: dependencies: balanced-match: 1.0.2 @@ -1413,10 +1403,6 @@ snapshots: dependencies: get-func-name: 2.0.2 - clean-stack@4.2.0: - dependencies: - escape-string-regexp: 5.0.0 - cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -1429,8 +1415,6 @@ snapshots: color-name@1.1.4: {} - concat-map@0.0.1: {} - confbox@0.1.7: {} cross-spawn@7.0.3: @@ -1447,23 +1431,8 @@ snapshots: dependencies: type-detect: 4.0.8 - del@7.1.0: - dependencies: - globby: 13.2.2 - graceful-fs: 4.2.11 - is-glob: 4.0.3 - is-path-cwd: 3.0.0 - is-path-inside: 4.0.0 - p-map: 5.5.0 - rimraf: 3.0.2 - slash: 4.0.0 - diff-sequences@29.6.3: {} - dir-glob@3.0.1: - dependencies: - path-type: 4.0.0 - eastasianwidth@0.2.0: {} emoji-regex@8.0.0: {} @@ -1502,8 +1471,6 @@ snapshots: escalade@3.1.2: {} - escape-string-regexp@5.0.0: {} - estree-walker@3.0.3: dependencies: '@types/estree': 1.0.5 @@ -1572,15 +1539,6 @@ snapshots: minipass: 7.1.2 path-scurry: 1.11.1 - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - glob@8.1.0: dependencies: fs.realpath: 1.0.0 @@ -1589,13 +1547,14 @@ snapshots: minimatch: 5.1.6 once: 1.4.0 - globby@13.2.2: + globby@14.0.1: dependencies: - dir-glob: 3.0.1 + '@sindresorhus/merge-streams': 2.3.0 fast-glob: 3.3.2 ignore: 5.3.1 - merge2: 1.4.1 - slash: 4.0.0 + path-type: 5.0.0 + slash: 5.1.0 + unicorn-magic: 0.1.0 graceful-fs@4.2.11: {} @@ -1615,8 +1574,6 @@ snapshots: ignore@5.3.1: {} - indent-string@5.0.0: {} - inflight@1.0.6: dependencies: once: 1.4.0 @@ -1697,10 +1654,6 @@ snapshots: mimic-fn@4.0.0: {} - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.11 - minimatch@5.1.6: dependencies: brace-expansion: 2.0.1 @@ -1760,17 +1713,13 @@ snapshots: dependencies: yocto-queue: 1.0.0 - p-map@5.5.0: - dependencies: - aggregate-error: 4.0.1 + p-map@7.0.2: {} parse-json@4.0.0: dependencies: error-ex: 1.3.2 json-parse-better-errors: 1.0.2 - path-is-absolute@1.0.1: {} - path-key@3.1.1: {} path-key@4.0.0: {} @@ -1786,7 +1735,7 @@ snapshots: dependencies: pify: 3.0.0 - path-type@4.0.0: {} + path-type@5.0.0: {} pathe@1.1.2: {} @@ -1848,10 +1797,6 @@ snapshots: reusify@1.0.4: {} - rimraf@3.0.2: - dependencies: - glob: 7.2.3 - rimraf@5.0.7: dependencies: glob: 10.4.1 @@ -1910,7 +1855,7 @@ snapshots: signal-exit@4.1.0: {} - slash@4.0.0: {} + slash@5.1.0: {} source-map-js@1.2.0: {} @@ -1984,6 +1929,8 @@ snapshots: undici-types@5.26.5: {} + unicorn-magic@0.1.0: {} + universalify@2.0.1: {} validate-npm-package-license@3.0.4: diff --git a/src/index.ts b/src/index.ts index b695333..5d07d2d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,36 @@ -import { deleteAsync } from 'del' +import path from 'node:path' -import type { Options as DelOptions } from 'del' -import type { Plugin } from 'rollup' +import { globby } from 'globby' +import isGlob from 'is-glob' +import isPathCwd from 'is-path-cwd' +import isPathInside from 'is-path-inside' +import pMap from 'p-map' +import { rimraf } from 'rimraf' +import slash from 'slash' + +import type { Options as GlobbyOptions } from 'globby' + +export interface Options extends GlobbyOptions { + /** + * See what would be deleted. + * + * @default false + * + * @example + * ``` + * import {deleteAsync} from 'del' + * const deletedPaths = await deleteAsync(['temp/*.js'], {dryRun: true}) + * console.log('Files and directories that would be deleted:\n', deletedPaths.join('\n')) + * ``` + */ + readonly dryRun?: boolean + + /** + * Concurrency limit. Minimum: `1`. + * @default Infinity + */ + readonly concurrency?: number -export interface Options extends DelOptions { /** * Rollup hook the plugin should use. * @default 'buildStart' @@ -29,13 +56,81 @@ export interface Options extends DelOptions { readonly verbose?: boolean } +import type { Plugin } from 'rollup' + +const safeCheck = (file: string, cwd: string) => { + if (isPathCwd(file)) { + throw new Error('Cannot delete the current working directory.') + } + + if (!isPathInside(file, cwd)) { + throw new Error( + 'Cannot delete files/directories outside the current working directory.', + ) + } +} + +const normalizePatterns = (inPatterns: string | ReadonlyArray) => { + const patterns = Array.isArray(inPatterns) ? inPatterns : [inPatterns] + + return patterns.map((pattern) => { + if (process.platform === 'win32' && isGlob(pattern) === false) { + return slash(pattern) + } + + return pattern + }) +} + +const deleteAsync = async ( + inPatterns: string | ReadonlyArray, + opts: Options = {}, +) => { + const { dryRun, concurrency, cwd: cwd_, ...options } = opts + + const cwd = typeof cwd_ === 'string' ? cwd_ : process.cwd() + const globbyOptions = { + expandDirectories: false, + onlyFiles: false, + followSymbolicLinks: false, + cwd, + ...options, + } + + const patterns = normalizePatterns(inPatterns) + const paths = await globby(patterns, globbyOptions) + const files = paths.sort((a, b) => b.localeCompare(a)) + + let deletedCount = 0 + + const mapper = async (name: string) => { + const file = path.resolve(cwd, name) + + safeCheck(file, cwd) + + if (!dryRun) { + await rimraf(file, { glob: false }) + } + + deletedCount += 1 + + return file + } + + const removedFiles = await pMap(files, mapper, { concurrency }) + + removedFiles.sort((a, b) => a.localeCompare(b)) + + return removedFiles +} + export function del(options: Options = {}): Plugin { const { hook = 'buildStart', runOnce = false, targets = [], verbose = false, - ...rest + ...deleteOptions } = options let deleted = false @@ -47,10 +142,10 @@ export function del(options: Options = {}): Plugin { return } - const paths = await deleteAsync(targets, rest) + const paths = await deleteAsync(targets, deleteOptions) - if (verbose || rest.dryRun) { - const message = rest.dryRun + if (verbose || deleteOptions.dryRun) { + const message = deleteOptions.dryRun ? `Expected files and folders to be deleted: ${paths.length}` : `Deleted files and folders: ${paths.length}`