prod-files 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -18
- package/index.mjs +210 -60
- package/package.json +4 -6
package/README.md
CHANGED
|
@@ -63,6 +63,8 @@ Flags:
|
|
|
63
63
|
-g, --globs Prints out the default globs.
|
|
64
64
|
|
|
65
65
|
-n, --noSize Skips the size calc at the end, saves about 200-1000ms.
|
|
66
|
+
|
|
67
|
+
-q, --quiet Quiet output, suppresses stdout.
|
|
66
68
|
```
|
|
67
69
|
|
|
68
70
|
With a package manager:
|
|
@@ -122,42 +124,41 @@ RUN node pf.js my-app/foo/node_modules/.pnpm
|
|
|
122
124
|
|
|
123
125
|
## Development
|
|
124
126
|
|
|
125
|
-
Unit tests are written with node's test utils.
|
|
126
|
-
|
|
127
127
|
```sh
|
|
128
|
-
pnpm
|
|
128
|
+
pnpm i
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
-
|
|
132
|
-
random deps. You can run the script against it to see how it fairs in real usage
|
|
133
|
-
and get some timing data.
|
|
131
|
+
### Unit tests
|
|
134
132
|
|
|
135
|
-
|
|
133
|
+
Unit tests are written with node's test utils.
|
|
136
134
|
|
|
137
135
|
```sh
|
|
138
|
-
pnpm test
|
|
136
|
+
pnpm test
|
|
139
137
|
```
|
|
140
138
|
|
|
141
|
-
|
|
139
|
+
### End to end tests
|
|
140
|
+
|
|
141
|
+
In `test-project` directory has Sentry's `package.json`. You can run the script
|
|
142
|
+
against it to see how it fairs in real-world use and get some timing data.
|
|
142
143
|
|
|
143
144
|
```sh
|
|
144
|
-
|
|
145
|
+
# Re-installs the packages and runs the script on it
|
|
146
|
+
pnpm test:e2e
|
|
147
|
+
# Disable size reportings since it's pretty slow
|
|
148
|
+
pnpm test:e2e --noSize
|
|
145
149
|
```
|
|
146
150
|
|
|
147
|
-
|
|
148
|
-
before running another test.
|
|
149
|
-
|
|
150
|
-
Or chain it for ease of use (with timing):
|
|
151
|
+
The nuke command removes `node_modules` and prunes the store:
|
|
151
152
|
|
|
152
153
|
```sh
|
|
153
|
-
pnpm test:
|
|
154
|
+
pnpm test:e2e:nuke
|
|
154
155
|
```
|
|
155
156
|
|
|
156
|
-
There's also a simple script to print the
|
|
157
|
-
using `du
|
|
157
|
+
There's also a simple script to print the weight of `test-project/node_modules/`
|
|
158
|
+
using `du`. You can run it before and after to see more detailed results:
|
|
158
159
|
|
|
159
160
|
```sh
|
|
160
|
-
pnpm test:
|
|
161
|
+
pnpm test:e2e:weight
|
|
161
162
|
```
|
|
162
163
|
|
|
163
164
|
## Prior art
|
package/index.mjs
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
// oxlint-disable prefer-spread
|
|
2
|
+
import cp from 'node:child_process'
|
|
2
3
|
import fs from 'node:fs/promises'
|
|
3
|
-
import { matchesGlob, join, isAbsolute, resolve } from 'node:path'
|
|
4
|
-
import { parseArgs, styleText } from 'node:util'
|
|
4
|
+
import { matchesGlob, join, isAbsolute, resolve, dirname } from 'node:path'
|
|
5
|
+
import { parseArgs, promisify, styleText } from 'node:util'
|
|
6
|
+
|
|
7
|
+
const exec = promisify(cp.exec)
|
|
5
8
|
|
|
6
9
|
/**
|
|
7
10
|
* A list of glob patterns for files/dirs to be deleted. The globs are matched
|
|
8
11
|
* with node's `matchesGlob()`. With one special rule: globs which end in `/`
|
|
9
12
|
* are marked as directories.
|
|
10
13
|
*
|
|
11
|
-
*
|
|
14
|
+
* Roughly ordered by popularity (educated guess).
|
|
12
15
|
*
|
|
13
16
|
* Partially based on
|
|
14
17
|
* @see {@link https://github.com/duniul/clean-modules/blob/main/.cleanmodules-default}
|
|
@@ -21,16 +24,21 @@ const defaultGlobs = [
|
|
|
21
24
|
'**/*.tsx',
|
|
22
25
|
'**/doc{,s}/',
|
|
23
26
|
|
|
24
|
-
//
|
|
27
|
+
// Types
|
|
25
28
|
'**/*tsconfig*.json',
|
|
26
29
|
'**/*.tsbuildinfo',
|
|
30
|
+
'**/flow-typed/',
|
|
31
|
+
|
|
32
|
+
// Sensitive
|
|
33
|
+
'**/.env*',
|
|
27
34
|
|
|
28
35
|
// Package mangers
|
|
29
36
|
'**/.npm*',
|
|
30
|
-
'**/pnpm
|
|
37
|
+
'**/pnpm-{lock,workspace}.yaml',
|
|
31
38
|
'**/.yarn*',
|
|
32
39
|
'**/yarn.lock',
|
|
33
40
|
'**/bun.lock',
|
|
41
|
+
'**/bunfig.toml',
|
|
34
42
|
|
|
35
43
|
// IDE
|
|
36
44
|
'**/.idea/',
|
|
@@ -50,6 +58,13 @@ const defaultGlobs = [
|
|
|
50
58
|
// CI/CD
|
|
51
59
|
'**/.github/',
|
|
52
60
|
'**/.circleci/',
|
|
61
|
+
'**/.vercel',
|
|
62
|
+
'**/now.json',
|
|
63
|
+
'**/.travis.yml',
|
|
64
|
+
|
|
65
|
+
// Docker
|
|
66
|
+
'**/Dockerfile*',
|
|
67
|
+
'**/.dockerignore',
|
|
53
68
|
|
|
54
69
|
// Tests
|
|
55
70
|
'**/test{,s}/',
|
|
@@ -60,31 +75,42 @@ const defaultGlobs = [
|
|
|
60
75
|
'**/karma.conf.{js,ts}',
|
|
61
76
|
'**/wallaby.conf.{js,ts}',
|
|
62
77
|
'**/wallaby.{js,ts}',
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
78
|
+
'**/playwright.config.{js,ts}',
|
|
79
|
+
'**/.mocharc*',
|
|
80
|
+
|
|
81
|
+
// Build/bundle config
|
|
82
|
+
'**/{rollup,rolldown,vite}.config.{js,ts,mjs}',
|
|
83
|
+
'**/webpack.config.{js,mjs,cjs,ts}',
|
|
84
|
+
'**/babel.config.{js,mjs,cjs,json}',
|
|
85
|
+
'**/parcel.config.{js,ts,json}',
|
|
86
|
+
'**/rspack.config.{js,mjs,cjs,ts}',
|
|
87
|
+
'**/.babelrc*',
|
|
88
|
+
'**/turbo.json',
|
|
89
|
+
'**/.browserslist*',
|
|
90
|
+
'**/metro.config.{js,json}',
|
|
66
91
|
'**/{G,g}runtfile.{js,ts}',
|
|
67
92
|
'**/{G,g}ulpfile.{js,ts}',
|
|
68
93
|
'**/{M,m}akefile',
|
|
94
|
+
'**/gemfile',
|
|
69
95
|
|
|
70
96
|
// Images
|
|
71
97
|
'**/*.jp{,e}g',
|
|
72
|
-
'**/*.png',
|
|
73
|
-
'**/*.gif',
|
|
74
98
|
'**/*.svg',
|
|
99
|
+
'**/*.gif',
|
|
100
|
+
'**/*.png',
|
|
75
101
|
|
|
76
102
|
// Linters and formatters
|
|
77
|
-
'**/.jshintrc',
|
|
78
|
-
'**/.lint',
|
|
79
|
-
'**/.prettier*',
|
|
80
|
-
'**/prettier.config*',
|
|
81
|
-
'**/biome.json{,c}',
|
|
82
|
-
'**/tslint.json',
|
|
83
|
-
'**/.eslintrc',
|
|
84
103
|
'**/eslint*.{json,jsonc,ts}',
|
|
104
|
+
'**/.eslintrc',
|
|
105
|
+
'**/prettier.config*',
|
|
106
|
+
'**/.prettier*',
|
|
85
107
|
'**/.ox{lint,fmt}rc.json{,c}',
|
|
86
108
|
'**/ox{lint,fmt}*.{json,jsonc,ts}',
|
|
109
|
+
'**/biome.json{,c}',
|
|
87
110
|
'**/.dprint.json{,c}',
|
|
111
|
+
'**/.jshintrc',
|
|
112
|
+
'**/.lint',
|
|
113
|
+
'**/tslint.json',
|
|
88
114
|
|
|
89
115
|
// Git
|
|
90
116
|
'**/.git/',
|
|
@@ -93,7 +119,7 @@ const defaultGlobs = [
|
|
|
93
119
|
|
|
94
120
|
// Code coverage
|
|
95
121
|
'**/.nyc_output/',
|
|
96
|
-
'**/.nycrc',
|
|
122
|
+
'**/.nycrc*',
|
|
97
123
|
'**/.codecov.y{,a}ml',
|
|
98
124
|
'**/coverage/',
|
|
99
125
|
|
|
@@ -123,6 +149,7 @@ const defaultGlobs = [
|
|
|
123
149
|
'**/*.coffee',
|
|
124
150
|
|
|
125
151
|
// Misc
|
|
152
|
+
'**/.jscpd',
|
|
126
153
|
'**/*.jst',
|
|
127
154
|
'**/*.log',
|
|
128
155
|
'**/*.mkd',
|
|
@@ -189,9 +216,11 @@ function usage() {
|
|
|
189
216
|
-g, --globs Prints out the default globs.
|
|
190
217
|
|
|
191
218
|
-n, --noSize Skips the size calc at the end, saves about 200-1000ms.
|
|
219
|
+
|
|
220
|
+
-q, --quiet Quiet output, suppresses stdout.
|
|
192
221
|
`
|
|
193
222
|
|
|
194
|
-
|
|
223
|
+
log.log(usageText)
|
|
195
224
|
}
|
|
196
225
|
|
|
197
226
|
/**
|
|
@@ -213,29 +242,48 @@ function bail(message, error, withUsage = false) {
|
|
|
213
242
|
|
|
214
243
|
/**
|
|
215
244
|
* @typedef {Object} Logger
|
|
216
|
-
* @property {
|
|
217
|
-
* @property {
|
|
218
|
-
* @property {
|
|
245
|
+
* @property {typeof console.error} error - Logs error messages in red
|
|
246
|
+
* @property {typeof console.info} info - Logs information messages in blue
|
|
247
|
+
* @property {typeof console.info} log - Logs with no color
|
|
248
|
+
* @property {typeof console.log} success - Logs success messages in green
|
|
249
|
+
* @property {typeof console.table} table - Logs as table
|
|
219
250
|
*/
|
|
220
251
|
|
|
252
|
+
// Quiet mode
|
|
253
|
+
let quiet = /** @type {boolean} */ (false)
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* @param {import('node:util').InspectColor} color
|
|
257
|
+
* @param {any[]} args
|
|
258
|
+
* @returns
|
|
259
|
+
*/
|
|
260
|
+
const style = (color, args) => args.map(a => styleText(color, String(a)))
|
|
261
|
+
|
|
221
262
|
/**
|
|
222
263
|
* A utility for styled console logs
|
|
223
264
|
* @type {Logger}
|
|
224
265
|
*/
|
|
225
|
-
const log = {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
266
|
+
export const log = {
|
|
267
|
+
error: (...a) =>
|
|
268
|
+
quiet ? undefined : console.error.apply(console, style('red', a)),
|
|
269
|
+
info: (...a) =>
|
|
270
|
+
quiet ? undefined : console.info.apply(console, style('blue', a)),
|
|
271
|
+
log: (...a) => (quiet ? undefined : console.log.apply(console, a)),
|
|
272
|
+
success: (...a) =>
|
|
273
|
+
quiet ? undefined : console.log.apply(console, style('green', a)),
|
|
274
|
+
table: (...a) => (quiet ? undefined : console.table.apply(console, a)),
|
|
229
275
|
}
|
|
230
276
|
|
|
231
277
|
/**
|
|
232
278
|
* Get size of node_modules
|
|
233
279
|
* @param {string} dirPath - Path to node_modules
|
|
234
|
-
* @returns {number}
|
|
280
|
+
* @returns {Promise<number>}
|
|
235
281
|
*/
|
|
236
|
-
function getSize(dirPath) {
|
|
237
|
-
const stdout =
|
|
238
|
-
|
|
282
|
+
async function getSize(dirPath) {
|
|
283
|
+
const { stdout, stderr } = await exec(`LC_ALL=C du -s ${dirPath}`)
|
|
284
|
+
if (stderr.length > 0) bail(stderr)
|
|
285
|
+
const size = stdout.split('\t')[0]
|
|
286
|
+
return size ? Number.parseInt(size, 10) : 0
|
|
239
287
|
}
|
|
240
288
|
|
|
241
289
|
/**
|
|
@@ -253,16 +301,25 @@ function calcSize(originalSize, prunedSize) {
|
|
|
253
301
|
/**
|
|
254
302
|
* Prints a nice diff table
|
|
255
303
|
* @param {object} opts
|
|
256
|
-
* @param {number | undefined} opts.prunedSize
|
|
304
|
+
* @param {Promise<number> | undefined} opts.prunedSize
|
|
257
305
|
* @param {number} opts.startTime
|
|
258
306
|
* @param {number} opts.itemCount
|
|
259
|
-
* @param {number | undefined} opts.originalSize
|
|
307
|
+
* @param {Promise<number> | undefined} opts.originalSize
|
|
260
308
|
*/
|
|
261
|
-
export function printDiff({
|
|
262
|
-
|
|
309
|
+
export async function printDiff({
|
|
310
|
+
prunedSize,
|
|
311
|
+
startTime,
|
|
312
|
+
itemCount,
|
|
313
|
+
originalSize,
|
|
314
|
+
}) {
|
|
315
|
+
const [original, pruned] =
|
|
316
|
+
originalSize && prunedSize
|
|
317
|
+
? await Promise.all([originalSize, prunedSize])
|
|
318
|
+
: [undefined, undefined]
|
|
319
|
+
|
|
320
|
+
log.table([
|
|
263
321
|
{
|
|
264
|
-
Pruned:
|
|
265
|
-
originalSize && prunedSize ? calcSize(originalSize, prunedSize) : 'n/a',
|
|
322
|
+
...(original && pruned && { Pruned: calcSize(original, pruned) }),
|
|
266
323
|
Time: `${((Date.now() - startTime) / 1000).toFixed(1)}s`,
|
|
267
324
|
Items: itemCount,
|
|
268
325
|
},
|
|
@@ -272,18 +329,20 @@ export function printDiff({ prunedSize, startTime, itemCount, originalSize }) {
|
|
|
272
329
|
/**
|
|
273
330
|
* @typedef Args
|
|
274
331
|
* @type {object}
|
|
275
|
-
* @property {string} path - Path to node_modules
|
|
332
|
+
* @property {string} [path] - Path to node_modules
|
|
276
333
|
* @property {string[]} include - New glob pattern
|
|
277
334
|
* @property {string[]} exclude - Existing glob pattern
|
|
278
335
|
* @property {boolean} help - Prints help
|
|
279
336
|
* @property {boolean} noSize - Don't show size savings
|
|
280
337
|
* @property {boolean} globs - Prints globs
|
|
338
|
+
* @property {boolean} quiet - Suppress console.log output
|
|
281
339
|
*/
|
|
282
340
|
|
|
283
341
|
/**
|
|
284
342
|
* Parse the command-line arguments into an object
|
|
285
343
|
* @returns {Args}
|
|
286
344
|
*/
|
|
345
|
+
|
|
287
346
|
function handleArgs() {
|
|
288
347
|
try {
|
|
289
348
|
const {
|
|
@@ -297,9 +356,9 @@ function handleArgs() {
|
|
|
297
356
|
help: { type: 'boolean', short: 'h', default: false },
|
|
298
357
|
globs: { type: 'boolean', short: 'g', default: false },
|
|
299
358
|
noSize: { type: 'boolean', short: 'n', default: false },
|
|
359
|
+
quiet: { type: 'boolean', short: 'q', default: false },
|
|
300
360
|
},
|
|
301
361
|
})
|
|
302
|
-
if (!path) throw bail('Path not defined', undefined, true)
|
|
303
362
|
|
|
304
363
|
return { ...values, path }
|
|
305
364
|
} catch (err) {
|
|
@@ -327,14 +386,6 @@ export async function validateNodeModulesPath(nodeModulesPath) {
|
|
|
327
386
|
}
|
|
328
387
|
}
|
|
329
388
|
|
|
330
|
-
/**
|
|
331
|
-
* Removes a directory or a file
|
|
332
|
-
* @param {string} file - the file or dir to remove
|
|
333
|
-
*/
|
|
334
|
-
async function rimraf(file) {
|
|
335
|
-
await fs.rm(file, { recursive: true, force: true })
|
|
336
|
-
}
|
|
337
|
-
|
|
338
389
|
/**
|
|
339
390
|
* `file.matchesGlob()` does not match dotfiles, this util replaces leading dots
|
|
340
391
|
* with an underscore
|
|
@@ -644,44 +695,131 @@ export function compactPaths(paths) {
|
|
|
644
695
|
return compact
|
|
645
696
|
}
|
|
646
697
|
|
|
698
|
+
/**
|
|
699
|
+
* Checks the rmdir error: ENOTEMPTY means the dir was not empty and the removal
|
|
700
|
+
* failed, which is what we want
|
|
701
|
+
* @param {unknown} err
|
|
702
|
+
* @returns {boolean}
|
|
703
|
+
*/
|
|
704
|
+
function hasContent(err) {
|
|
705
|
+
return (
|
|
706
|
+
!!err &&
|
|
707
|
+
typeof err === 'object' &&
|
|
708
|
+
'code' in err &&
|
|
709
|
+
(err.code === 'ENOTEMPTY' || err.code === 'ENOENT')
|
|
710
|
+
)
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/**
|
|
714
|
+
* Removes a dir if it's empty
|
|
715
|
+
* @param {string[]} dirs
|
|
716
|
+
* @returns {Promise<void>[]}
|
|
717
|
+
*/
|
|
718
|
+
function rmEmptyDir(dirs) {
|
|
719
|
+
return dirs.map(dir =>
|
|
720
|
+
fs.rmdir(dir).catch(err => {
|
|
721
|
+
if (hasContent(err)) return
|
|
722
|
+
throw err
|
|
723
|
+
})
|
|
724
|
+
)
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
/**
|
|
728
|
+
* Removes a file and collects parent directories for later cleanup
|
|
729
|
+
* @param {string} file - the file to remove
|
|
730
|
+
* @param {Set<string>} visited - tracks directories we've already visited
|
|
731
|
+
* @param {Map<number, Set<string>>} dirDepths - cleanup dirs grouped by depth
|
|
732
|
+
* @param {string} rootDir - stop collecting once we reach this directory
|
|
733
|
+
*/
|
|
734
|
+
async function rimraf(
|
|
735
|
+
file,
|
|
736
|
+
visited = new Set(),
|
|
737
|
+
dirDepths = new Map(),
|
|
738
|
+
rootDir = dirname(file)
|
|
739
|
+
) {
|
|
740
|
+
// Remove the file/dir recursively
|
|
741
|
+
await fs.rm(file, { recursive: true, force: true })
|
|
742
|
+
|
|
743
|
+
// Walk up the tree collecting all the ancestors, we'll use them later on to
|
|
744
|
+
// delete directories which are left empty
|
|
745
|
+
let dir = dirname(file)
|
|
746
|
+
while (dir !== rootDir) {
|
|
747
|
+
if (visited.has(dir)) break
|
|
748
|
+
visited.add(dir)
|
|
749
|
+
|
|
750
|
+
const depth = dir.split('/').length
|
|
751
|
+
|
|
752
|
+
// Group the dirs by depth
|
|
753
|
+
const dirs = dirDepths.get(depth)
|
|
754
|
+
if (dirs) dirs.add(dir)
|
|
755
|
+
else dirDepths.set(depth, new Set([dir]))
|
|
756
|
+
|
|
757
|
+
dir = dirname(dir)
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* @typedef {Args & { path: string }} ArgsWithRequiredPath
|
|
763
|
+
*/
|
|
764
|
+
|
|
647
765
|
/**
|
|
648
766
|
* Removes unneeded files from node_modules
|
|
649
|
-
* @param {
|
|
767
|
+
* @param {ArgsWithRequiredPath} opts
|
|
650
768
|
*/
|
|
651
769
|
export async function prune(opts) {
|
|
652
770
|
const startTime = Date.now()
|
|
653
771
|
log.info('Pruning:', opts.path)
|
|
654
772
|
|
|
655
|
-
|
|
773
|
+
// Don't wait
|
|
774
|
+
const originalSize = getSize(opts.path)
|
|
656
775
|
const excludedGlobs = new Set(opts.exclude)
|
|
657
776
|
const activeGlobs = [...defaultGlobs, ...opts.include].filter(
|
|
658
777
|
glob => !excludedGlobs.has(glob)
|
|
659
778
|
)
|
|
660
779
|
const compiledGlobs = compileGlobs(activeGlobs)
|
|
661
780
|
|
|
662
|
-
//
|
|
781
|
+
// TODO: this could be slightly faster with an optimized walker
|
|
663
782
|
const allFiles = await fs.readdir(opts.path, {
|
|
664
783
|
recursive: true,
|
|
665
784
|
withFileTypes: true,
|
|
666
785
|
})
|
|
667
786
|
|
|
668
|
-
const
|
|
669
|
-
const results = compactPaths(junkFiles)
|
|
787
|
+
const junk = compactPaths(findJunkFiles(allFiles, compiledGlobs))
|
|
670
788
|
|
|
671
789
|
try {
|
|
672
|
-
|
|
790
|
+
/** @type {Set<string>} */
|
|
791
|
+
const visited = new Set()
|
|
792
|
+
/** @type {Map<number, Set<string>>} */
|
|
793
|
+
const dirDepths = new Map()
|
|
794
|
+
// Rm & populate visited & dirDepths so dirs can be removed in parallel
|
|
795
|
+
await Promise.all(junk.map(x => rimraf(x, visited, dirDepths, opts.path)))
|
|
796
|
+
const depths = [...dirDepths.keys()].sort((a, b) => b - a)
|
|
797
|
+
|
|
798
|
+
/**
|
|
799
|
+
* Remove one depth level at a time, but parallelize within each level
|
|
800
|
+
* @param {number} i
|
|
801
|
+
* @returns {Promise<void>}
|
|
802
|
+
*/
|
|
803
|
+
async function removeDepth(i) {
|
|
804
|
+
if (i >= depths.length) return
|
|
805
|
+
const dirs = dirDepths.get(depths[i] || 0) ?? []
|
|
806
|
+
await Promise.all(rmEmptyDir([...dirs]))
|
|
807
|
+
await removeDepth(i + 1)
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
await removeDepth(0)
|
|
673
811
|
} catch (err) {
|
|
674
812
|
throw bail(undefined, err)
|
|
675
813
|
}
|
|
676
814
|
|
|
677
|
-
printDiff({
|
|
678
|
-
itemCount:
|
|
815
|
+
void printDiff({
|
|
816
|
+
itemCount: junk.length,
|
|
679
817
|
prunedSize: opts.noSize ? undefined : getSize(opts.path),
|
|
680
|
-
originalSize,
|
|
818
|
+
originalSize: opts.noSize ? undefined : originalSize,
|
|
681
819
|
startTime,
|
|
682
820
|
})
|
|
683
821
|
|
|
684
|
-
return
|
|
822
|
+
return junk
|
|
685
823
|
}
|
|
686
824
|
|
|
687
825
|
const entry = process.argv[1]
|
|
@@ -691,16 +829,28 @@ const runAsScript =
|
|
|
691
829
|
if (runAsScript) {
|
|
692
830
|
const args = handleArgs()
|
|
693
831
|
|
|
832
|
+
quiet = args.quiet
|
|
833
|
+
|
|
694
834
|
if (args.help) {
|
|
695
835
|
usage()
|
|
696
836
|
process.exit(0)
|
|
697
837
|
}
|
|
698
838
|
|
|
699
839
|
if (args.globs) {
|
|
700
|
-
|
|
840
|
+
log.log(JSON.stringify(defaultGlobs, null, 2))
|
|
701
841
|
process.exit(0)
|
|
702
842
|
}
|
|
703
843
|
|
|
704
|
-
|
|
705
|
-
|
|
844
|
+
// Should have a path by now
|
|
845
|
+
if (!args.path) {
|
|
846
|
+
throw bail(
|
|
847
|
+
undefined,
|
|
848
|
+
'Path not defined. Usage: prod-files <path-to-node-modules>'
|
|
849
|
+
)
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
const argsWithPath = /** @type {ArgsWithRequiredPath} */ (args)
|
|
853
|
+
|
|
854
|
+
await validateNodeModulesPath(argsWithPath.path)
|
|
855
|
+
await prune(argsWithPath)
|
|
706
856
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prod-files",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Keep only prod files by pruning non-prod files from node_modules before deploying",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"clean",
|
|
@@ -40,10 +40,8 @@
|
|
|
40
40
|
"pf": "node ./index.mjs",
|
|
41
41
|
"pub": "(npm whoami || npm login) && pnpm publish --access=public --tag=latest",
|
|
42
42
|
"test": "node --test",
|
|
43
|
-
"test:
|
|
44
|
-
"test:
|
|
45
|
-
"test:
|
|
46
|
-
"test:size": "du -sh ./test-project/node_modules/.pnpm | sort -h",
|
|
47
|
-
"test:watch": "node --test --watch"
|
|
43
|
+
"test:e2e": "cd test-project && bash prepare_test.sh && time node ../index.mjs node_modules/.pnpm",
|
|
44
|
+
"test:e2e:nuke": "trash ./test-project/node_modules ./test-project/pnpm-lock.yaml && pnpm store prune",
|
|
45
|
+
"test:e2e:weight": "du -sh ./test-project/node_modules/.pnpm | sort -h"
|
|
48
46
|
}
|
|
49
47
|
}
|