prod-files 0.1.4 → 0.2.0
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 +70 -20
- package/index.mjs +75 -75
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -36,8 +36,7 @@ Examples:
|
|
|
36
36
|
arguments, so don't use equals signs:
|
|
37
37
|
$ pf -i "**/foo" -e "**/*tsconfig*.json" node_modules/.pnpm
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
omitted:
|
|
39
|
+
In short-hand args the space between the key and the value can be omitted:
|
|
41
40
|
$ pf -i"**/foo" node_modules/.pnpm
|
|
42
41
|
|
|
43
42
|
Usage:
|
|
@@ -51,16 +50,22 @@ Arguments:
|
|
|
51
50
|
- yarn: 'node_modules' or 'node_modules/.store'
|
|
52
51
|
|
|
53
52
|
Flags:
|
|
54
|
-
-i, --include
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
-i, --include Extra custom glob pattern. Uses node's path.matchesGlob(),
|
|
54
|
+
with one exception: patterns ending with slash '**/foo/' are
|
|
55
|
+
marked as directories. Can have multiple.
|
|
57
56
|
|
|
58
57
|
-e, --exclude Exclude existing glob patterns if the script is too
|
|
59
|
-
aggressive. Must be exact match.
|
|
58
|
+
aggressive. Must be exact match. Can have multiple.
|
|
59
|
+
|
|
60
|
+
-d, --dryRun Nothing is removed and the paths are printed out.
|
|
60
61
|
|
|
61
62
|
-h, --help Prints out the help.
|
|
62
63
|
|
|
63
|
-
-g, --
|
|
64
|
+
-g, --showGlobs
|
|
65
|
+
Prints out the default globs.
|
|
66
|
+
|
|
67
|
+
--noGlobs Disable default glob patterns, only use patterns from
|
|
68
|
+
--include.
|
|
64
69
|
|
|
65
70
|
-n, --noSize Skips the size calculation.
|
|
66
71
|
|
|
@@ -88,6 +93,43 @@ Different package manager `node_modules` paths:
|
|
|
88
93
|
| yarn | pnpm | `node_modules/.store` | same as pnpm |
|
|
89
94
|
| yarn | pnp | no-op | no node_modules |
|
|
90
95
|
|
|
96
|
+
### Provide your own globs
|
|
97
|
+
|
|
98
|
+
The default globs can de disabled with `--noGlobs` flag, and only globs in
|
|
99
|
+
`--include` are matched:
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
pnpm prod-files --noGlobs -i "**/custom/" -i "**/*.html" node_modules/.pnpm
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Dy run
|
|
106
|
+
|
|
107
|
+
The `--dry-run` flag does not delete anything and prints out the paths:
|
|
108
|
+
|
|
109
|
+
```sh
|
|
110
|
+
pnpm prod-files --dryRun node_modules/.pnpm
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Use as a search
|
|
114
|
+
|
|
115
|
+
You can use `prod-files` to search any dir if you set `--dryRun` and
|
|
116
|
+
`--noGlobs`, and provide the search term in `--include`:
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
pnpm prod-files --noGlobs --dryRun --include="**/bower.json" node_modules/.pnpm
|
|
120
|
+
|
|
121
|
+
Pruning (--dryRun, nothing deleted): node_modules/.pnpm
|
|
122
|
+
node_modules/.pnpm/less@4.3.0/node_modules/less/bower.json
|
|
123
|
+
node_modules/.pnpm/papaparse@5.5.3/node_modules/papaparse/bower.json
|
|
124
|
+
node_modules/.pnpm/reflux@0.4.1_react@19.2.3/node_modules/reflux/bower.json
|
|
125
|
+
node_modules/.pnpm/sprintf-js@1.0.3/node_modules/sprintf-js/bower.json
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Sentry's `node_modules` has 4 bower config files :)
|
|
129
|
+
|
|
130
|
+
> [!CAUTION]\
|
|
131
|
+
> You're wielding `rm -rf` here, always remember to set `--dryRun`!
|
|
132
|
+
|
|
91
133
|
### Dockerfile example
|
|
92
134
|
|
|
93
135
|
Simple yet somewhat realistic example usage in Dockerfile for an app named `foo`
|
|
@@ -101,25 +143,27 @@ RUN pnpm fetch
|
|
|
101
143
|
COPY . ./
|
|
102
144
|
RUN pnpm i --offline --frozen-lockfile
|
|
103
145
|
RUN pnpm build
|
|
104
|
-
RUN pnpm -F=foo --prod deploy /
|
|
105
|
-
# Run it as the last command of the build step.
|
|
106
|
-
# --prod
|
|
107
|
-
|
|
146
|
+
RUN pnpm -F=foo --prod deploy /foo
|
|
147
|
+
# Run it as the last command of the build step.
|
|
148
|
+
# NOTE: with --prod, the script needs to be a prod dep. Or use pnpx/npx/yarn dlx
|
|
149
|
+
WORKDIR /foo
|
|
150
|
+
RUN pnpm prod-files node_modules/.pnpm --noSize
|
|
108
151
|
|
|
109
152
|
# Enjoy your new slimmer image
|
|
110
153
|
FROM node:lts-alpine3.19 AS foo
|
|
111
|
-
COPY --from=base /
|
|
112
|
-
|
|
154
|
+
COPY --from=base foo/build /foo/build
|
|
155
|
+
COPY --from=base foo/node_modules /foo/node_modules
|
|
156
|
+
WORKDIR /foo
|
|
113
157
|
CMD node build/server.js
|
|
114
158
|
```
|
|
115
159
|
|
|
116
|
-
Or use wget
|
|
117
|
-
|
|
160
|
+
Or use `wget` if you don't have a package manager in your env (there are certain
|
|
161
|
+
risks involved when you execute files downloaded from the net, if I get
|
|
118
162
|
comprised that file can have anything):
|
|
119
163
|
|
|
120
164
|
```dockerfile
|
|
121
|
-
RUN wget -O pf.
|
|
122
|
-
RUN node pf.
|
|
165
|
+
RUN wget -O pf.mjs https://raw.githubusercontent.com/hilja/prod-files/refs/heads/main/index.mjs
|
|
166
|
+
RUN node pf.mjs /foo/node_modules/.pnpm
|
|
123
167
|
```
|
|
124
168
|
|
|
125
169
|
## Development
|
|
@@ -138,7 +182,7 @@ pnpm test
|
|
|
138
182
|
|
|
139
183
|
### End to end tests
|
|
140
184
|
|
|
141
|
-
|
|
185
|
+
The `test-project` directory has Sentry's `package.json`. You can run the script
|
|
142
186
|
against it to see how it does in real-world use and get some timing data.
|
|
143
187
|
|
|
144
188
|
```sh
|
|
@@ -148,13 +192,19 @@ pnpm test:e2e
|
|
|
148
192
|
pnpm test:e2e --noSize
|
|
149
193
|
```
|
|
150
194
|
|
|
151
|
-
|
|
195
|
+
If you're testing `--dryRun`, use `test:e2e:run`, it does not reinstall:
|
|
196
|
+
|
|
197
|
+
```sh
|
|
198
|
+
pnpm test:r2e:run
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The nuke command removes `test-project/node_modules` and prunes the store:
|
|
152
202
|
|
|
153
203
|
```sh
|
|
154
204
|
pnpm test:e2e:nuke
|
|
155
205
|
```
|
|
156
206
|
|
|
157
|
-
There's also a simple script to print the weight of `test-project/node_modules
|
|
207
|
+
There's also a simple script to print the weight of `test-project/node_modules`
|
|
158
208
|
using `du`. You can run it before and after to see more detailed results:
|
|
159
209
|
|
|
160
210
|
```sh
|
package/index.mjs
CHANGED
|
@@ -21,13 +21,16 @@ const defaultGlobs = [
|
|
|
21
21
|
'**/*.md',
|
|
22
22
|
'**/*.map',
|
|
23
23
|
'**/*.{,m,c}ts',
|
|
24
|
-
'**/*.
|
|
24
|
+
'**/*.{j,t}sx',
|
|
25
25
|
'**/doc{,s}/',
|
|
26
26
|
|
|
27
27
|
// Types
|
|
28
28
|
'**/*tsconfig*.json',
|
|
29
29
|
'**/*.tsbuildinfo',
|
|
30
30
|
'**/flow-typed/',
|
|
31
|
+
'**/.flowconfig',
|
|
32
|
+
'**/*.flow',
|
|
33
|
+
'**/__typings__/',
|
|
31
34
|
|
|
32
35
|
// Sensitive
|
|
33
36
|
'**/.env*',
|
|
@@ -39,6 +42,8 @@ const defaultGlobs = [
|
|
|
39
42
|
'**/yarn.lock',
|
|
40
43
|
'**/bun.lock',
|
|
41
44
|
'**/bunfig.toml',
|
|
45
|
+
'**/bower.json',
|
|
46
|
+
'**/node_modules/.bin/',
|
|
42
47
|
|
|
43
48
|
// IDE
|
|
44
49
|
'**/.idea/',
|
|
@@ -54,6 +59,7 @@ const defaultGlobs = [
|
|
|
54
59
|
'**/contributing',
|
|
55
60
|
'**/CONTRIBUTORS',
|
|
56
61
|
'**/contributors',
|
|
62
|
+
'**/node_modules/**/man/',
|
|
57
63
|
|
|
58
64
|
// CI/CD
|
|
59
65
|
'**/.github/',
|
|
@@ -69,6 +75,7 @@ const defaultGlobs = [
|
|
|
69
75
|
// Tests
|
|
70
76
|
'**/test{,s}/',
|
|
71
77
|
'**/spec{,s}/',
|
|
78
|
+
'**/**.{test,spec}.{js,mjs}',
|
|
72
79
|
'**/__{mocks,tests}__/',
|
|
73
80
|
'**/jest.*.{js,ts}',
|
|
74
81
|
'**/vitest.*.ts',
|
|
@@ -77,6 +84,8 @@ const defaultGlobs = [
|
|
|
77
84
|
'**/wallaby.{js,ts}',
|
|
78
85
|
'**/playwright.config.{js,ts}',
|
|
79
86
|
'**/.mocharc*',
|
|
87
|
+
'**/.zuul.yml',
|
|
88
|
+
'**/.coveralls.yml',
|
|
80
89
|
|
|
81
90
|
// Build/bundle config
|
|
82
91
|
'**/{rollup,rolldown,vite}.config.{js,ts,mjs}',
|
|
@@ -100,8 +109,9 @@ const defaultGlobs = [
|
|
|
100
109
|
'**/*.png',
|
|
101
110
|
|
|
102
111
|
// Linters and formatters
|
|
103
|
-
'**/eslint*.{json,jsonc,ts}',
|
|
104
|
-
'**/.eslintrc',
|
|
112
|
+
'**/eslint*.{json,jsonc,ts,js,mjs}',
|
|
113
|
+
'**/.eslintrc*',
|
|
114
|
+
'**/.eslintignore',
|
|
105
115
|
'**/prettier.config*',
|
|
106
116
|
'**/.prettier*',
|
|
107
117
|
'**/.ox{lint,fmt}rc.json{,c}',
|
|
@@ -149,6 +159,11 @@ const defaultGlobs = [
|
|
|
149
159
|
'**/*.coffee',
|
|
150
160
|
|
|
151
161
|
// Misc
|
|
162
|
+
'**/KEYS',
|
|
163
|
+
'**/.spmignore',
|
|
164
|
+
'**/.editorconfig',
|
|
165
|
+
'**/component.json',
|
|
166
|
+
'**/*.jison',
|
|
152
167
|
'**/.jscpd',
|
|
153
168
|
'**/*.jst',
|
|
154
169
|
'**/*.log',
|
|
@@ -189,8 +204,7 @@ function usage() {
|
|
|
189
204
|
arguments, so don't use equals signs:
|
|
190
205
|
$ pf -i "**/foo" -e "**/*tsconfig*.json" node_modules/.pnpm
|
|
191
206
|
|
|
192
|
-
|
|
193
|
-
omitted:
|
|
207
|
+
In short-hand args the space between the key and the value can be omitted:
|
|
194
208
|
$ pf -i"**/foo" node_modules/.pnpm
|
|
195
209
|
|
|
196
210
|
Usage:
|
|
@@ -204,16 +218,22 @@ function usage() {
|
|
|
204
218
|
- yarn: 'node_modules' or 'node_modules/.store'
|
|
205
219
|
|
|
206
220
|
Flags:
|
|
207
|
-
-i, --include
|
|
208
|
-
|
|
209
|
-
|
|
221
|
+
-i, --include Extra custom glob pattern. Uses node's path.matchesGlob(),
|
|
222
|
+
with one exception: patterns ending with slash '**/foo/' are
|
|
223
|
+
marked as directories. Can have multiple.
|
|
210
224
|
|
|
211
225
|
-e, --exclude Exclude existing glob patterns if the script is too
|
|
212
|
-
aggressive. Must be exact match.
|
|
226
|
+
aggressive. Must be exact match. Can have multiple.
|
|
227
|
+
|
|
228
|
+
-d, --dryRun Nothing is removed and the paths are printed out.
|
|
213
229
|
|
|
214
230
|
-h, --help Prints out the help.
|
|
215
231
|
|
|
216
|
-
-g, --
|
|
232
|
+
-g, --showGlobs
|
|
233
|
+
Prints out the default globs.
|
|
234
|
+
|
|
235
|
+
--noGlobs Disable default glob patterns, only use patterns from
|
|
236
|
+
--include.
|
|
217
237
|
|
|
218
238
|
-n, --noSize Skips the size calculation.
|
|
219
239
|
|
|
@@ -264,8 +284,7 @@ const style = (color, args) => args.map(a => styleText(color, String(a)))
|
|
|
264
284
|
* @type {Logger}
|
|
265
285
|
*/
|
|
266
286
|
export const log = {
|
|
267
|
-
error: (...a) =>
|
|
268
|
-
quiet ? undefined : console.error.apply(console, style('red', a)),
|
|
287
|
+
error: (...a) => console.error.apply(console, style('red', a)),
|
|
269
288
|
info: (...a) =>
|
|
270
289
|
quiet ? undefined : console.info.apply(console, style('blue', a)),
|
|
271
290
|
log: (...a) => (quiet ? undefined : console.log.apply(console, a)),
|
|
@@ -312,10 +331,10 @@ async function treeSize(path) {
|
|
|
312
331
|
* @param {number} originalSize
|
|
313
332
|
* @param {number} prunedSize
|
|
314
333
|
*/
|
|
315
|
-
function calcSize(originalSize, prunedSize) {
|
|
334
|
+
export function calcSize(originalSize, prunedSize) {
|
|
316
335
|
const diff = originalSize - prunedSize
|
|
317
336
|
const diffMb = `${(diff / 1024).toFixed(1)} MB`
|
|
318
|
-
const diffPercent = `${((diff /
|
|
337
|
+
const diffPercent = `${((diff / originalSize) * 100).toFixed(1)}%`
|
|
319
338
|
|
|
320
339
|
return `${diffPercent} (${diffMb})`
|
|
321
340
|
}
|
|
@@ -352,9 +371,11 @@ export function printDiff({
|
|
|
352
371
|
* @property {string} [path] - Path to node_modules
|
|
353
372
|
* @property {string[]} include - New glob pattern
|
|
354
373
|
* @property {string[]} exclude - Existing glob pattern
|
|
374
|
+
* @property {boolean} dryRun - Print out the files to be removed, no deletion
|
|
355
375
|
* @property {boolean} help - Prints help
|
|
376
|
+
* @property {boolean} showGlobs - Prints globs
|
|
377
|
+
* @property {boolean} noGlobs - Disable default glob patterns
|
|
356
378
|
* @property {boolean} noSize - Don't show size savings
|
|
357
|
-
* @property {boolean} globs - Prints globs
|
|
358
379
|
* @property {boolean} quiet - Suppress console.log output
|
|
359
380
|
*/
|
|
360
381
|
|
|
@@ -362,7 +383,6 @@ export function printDiff({
|
|
|
362
383
|
* Parse the command-line arguments into an object
|
|
363
384
|
* @returns {Args}
|
|
364
385
|
*/
|
|
365
|
-
|
|
366
386
|
function handleArgs() {
|
|
367
387
|
try {
|
|
368
388
|
const {
|
|
@@ -373,8 +393,10 @@ function handleArgs() {
|
|
|
373
393
|
options: {
|
|
374
394
|
include: { type: 'string', short: 'i', default: [], multiple: true },
|
|
375
395
|
exclude: { type: 'string', short: 'e', default: [], multiple: true },
|
|
396
|
+
dryRun: { type: 'boolean', short: 'd', default: false },
|
|
376
397
|
help: { type: 'boolean', short: 'h', default: false },
|
|
377
|
-
|
|
398
|
+
showGlobs: { type: 'boolean', short: 'g', default: false },
|
|
399
|
+
noGlobs: { type: 'boolean', default: false },
|
|
378
400
|
noSize: { type: 'boolean', short: 'n', default: false },
|
|
379
401
|
quiet: { type: 'boolean', short: 'q', default: false },
|
|
380
402
|
},
|
|
@@ -685,36 +707,6 @@ export function findJunkFiles(files, compiledGlobs = defaultCompiledGlobs) {
|
|
|
685
707
|
return junkFiles
|
|
686
708
|
}
|
|
687
709
|
|
|
688
|
-
/**
|
|
689
|
-
* Removes descendant paths when an ancestor path is already present
|
|
690
|
-
* @param {string[]} paths - Paths to compact
|
|
691
|
-
* @returns {string[]} A sorted list without redundant child paths
|
|
692
|
-
*/
|
|
693
|
-
export function compactPaths(paths) {
|
|
694
|
-
/** @type {Set<string>} */
|
|
695
|
-
const seen = new Set()
|
|
696
|
-
/** @type {string[]} */
|
|
697
|
-
const compact = []
|
|
698
|
-
|
|
699
|
-
// Sorting guarantees parents are encountered before their nested children
|
|
700
|
-
for (const path of paths.toSorted()) {
|
|
701
|
-
let i = path.lastIndexOf('/')
|
|
702
|
-
|
|
703
|
-
while (i > 0) {
|
|
704
|
-
if (seen.has(path.slice(0, i))) break
|
|
705
|
-
i = path.lastIndexOf('/', i - 1)
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
// Skip this path if one of its ancestors has already been kept
|
|
709
|
-
if (i > 0) continue
|
|
710
|
-
|
|
711
|
-
seen.add(path)
|
|
712
|
-
compact.push(path)
|
|
713
|
-
}
|
|
714
|
-
|
|
715
|
-
return compact
|
|
716
|
-
}
|
|
717
|
-
|
|
718
710
|
/**
|
|
719
711
|
* @typedef {object} WalkResult
|
|
720
712
|
* @property {string[]} removed - Compacted list of removed paths
|
|
@@ -725,12 +717,11 @@ export function compactPaths(paths) {
|
|
|
725
717
|
* Parallel walker that finds junk, removes it, and cleans empty dirs in one
|
|
726
718
|
* pass. Skips recursing into junk directories (implicit path compacting) and
|
|
727
719
|
* removes empty ancestors bottom-up as the recursion unwinds.
|
|
728
|
-
* @param {string} rootDir - The directory to walk
|
|
729
720
|
* @param {CompiledGlobs} compiledGlobs - Precompiled glob matchers
|
|
730
|
-
* @param {
|
|
721
|
+
* @param {ArgsWithPath} opts - The args object
|
|
731
722
|
* @returns {Promise<WalkResult>}
|
|
732
723
|
*/
|
|
733
|
-
async function walkAndPrune(
|
|
724
|
+
async function walkAndPrune(compiledGlobs, opts) {
|
|
734
725
|
/** @type {string[]} */
|
|
735
726
|
const removed = []
|
|
736
727
|
let removedBlocks = 0
|
|
@@ -790,8 +781,9 @@ async function walkAndPrune(rootDir, compiledGlobs, trackSize) {
|
|
|
790
781
|
const [junkSizes, walkResults] = await Promise.all([
|
|
791
782
|
Promise.all(
|
|
792
783
|
junkPaths.map(async p => {
|
|
793
|
-
const size =
|
|
794
|
-
|
|
784
|
+
const size = opts.noSize ? 0 : await treeSize(p)
|
|
785
|
+
// No rm if --dryRun
|
|
786
|
+
if (!opts.dryRun) await fs.rm(p, { recursive: true, force: true })
|
|
795
787
|
return size
|
|
796
788
|
})
|
|
797
789
|
),
|
|
@@ -803,50 +795,55 @@ async function walkAndPrune(rootDir, compiledGlobs, trackSize) {
|
|
|
803
795
|
// Subdirs that became empty after pruning their contents
|
|
804
796
|
const emptyDirs = keptDirPaths.filter((_, i) => !walkResults[i])
|
|
805
797
|
if (emptyDirs.length > 0) {
|
|
806
|
-
|
|
798
|
+
// No rm if --dryRun
|
|
799
|
+
if (!opts.dryRun) await Promise.all(emptyDirs.map(d => fs.rmdir(d)))
|
|
807
800
|
}
|
|
808
801
|
|
|
809
802
|
return keptFiles + keptDirPaths.length - emptyDirs.length > 0
|
|
810
803
|
}
|
|
811
804
|
|
|
812
|
-
await walkDir(
|
|
805
|
+
await walkDir(opts.path)
|
|
813
806
|
return { removed, removedBlocks }
|
|
814
807
|
}
|
|
815
808
|
|
|
816
809
|
/**
|
|
817
|
-
* @typedef {Args & { path: string }}
|
|
810
|
+
* @typedef {Args & { path: string }} ArgsWithPath
|
|
818
811
|
*/
|
|
819
812
|
|
|
820
813
|
/**
|
|
821
814
|
* Removes unneeded files from node_modules
|
|
822
|
-
* @param {
|
|
815
|
+
* @param {ArgsWithPath} opts
|
|
823
816
|
*/
|
|
824
817
|
export async function prune(opts) {
|
|
825
818
|
const startTime = Date.now()
|
|
826
|
-
|
|
819
|
+
const dryRunMsg = opts.dryRun ? ' (--dryRun, nothing deleted)' : ''
|
|
820
|
+
log.info(`Pruning${dryRunMsg}:`, opts.path)
|
|
827
821
|
|
|
828
822
|
// Fire early so du runs concurrently with the walk
|
|
829
823
|
const sizePromise = opts.noSize ? undefined : getSize(opts.path)
|
|
830
824
|
const excludedGlobs = new Set(opts.exclude)
|
|
831
|
-
const activeGlobs = [
|
|
832
|
-
|
|
833
|
-
|
|
825
|
+
const activeGlobs = [
|
|
826
|
+
...(opts.noGlobs ? [] : defaultGlobs),
|
|
827
|
+
...opts.include,
|
|
828
|
+
].filter(glob => !excludedGlobs.has(glob))
|
|
834
829
|
const compiledGlobs = compileGlobs(activeGlobs)
|
|
835
830
|
|
|
836
831
|
/** @type {WalkResult} */
|
|
837
832
|
let result
|
|
838
833
|
try {
|
|
839
|
-
result = await walkAndPrune(
|
|
834
|
+
result = await walkAndPrune(compiledGlobs, opts)
|
|
840
835
|
} catch (err) {
|
|
841
836
|
throw bail(undefined, err)
|
|
842
837
|
}
|
|
843
838
|
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
839
|
+
if (!opts.dryRun) {
|
|
840
|
+
printDiff({
|
|
841
|
+
itemCount: result.removed.length,
|
|
842
|
+
removedBytes: opts.noSize ? undefined : result.removedBlocks,
|
|
843
|
+
originalSize: sizePromise ? await sizePromise : undefined,
|
|
844
|
+
startTime,
|
|
845
|
+
})
|
|
846
|
+
}
|
|
850
847
|
|
|
851
848
|
return result.removed
|
|
852
849
|
}
|
|
@@ -865,21 +862,24 @@ if (runAsScript) {
|
|
|
865
862
|
process.exit(0)
|
|
866
863
|
}
|
|
867
864
|
|
|
868
|
-
if (args.
|
|
865
|
+
if (args.showGlobs) {
|
|
869
866
|
log.log(JSON.stringify(defaultGlobs, null, 2))
|
|
870
867
|
process.exit(0)
|
|
871
868
|
}
|
|
872
869
|
|
|
873
|
-
//
|
|
870
|
+
// From this point forward we should have a path
|
|
874
871
|
if (!args.path) {
|
|
875
|
-
throw bail(
|
|
876
|
-
undefined,
|
|
877
|
-
'Path not defined. Usage: prod-files <path-to-node-modules>'
|
|
878
|
-
)
|
|
872
|
+
throw bail(undefined, 'Path not defined. Usage: prod-files <path>')
|
|
879
873
|
}
|
|
880
874
|
|
|
881
|
-
const argsWithPath = /** @type {
|
|
875
|
+
const argsWithPath = /** @type {ArgsWithPath} */ (args)
|
|
882
876
|
|
|
883
877
|
await validateNodeModulesPath(argsWithPath.path)
|
|
884
|
-
await prune(argsWithPath)
|
|
878
|
+
const pruned = await prune(argsWithPath)
|
|
879
|
+
|
|
880
|
+
// Print out paths if --dryRun
|
|
881
|
+
if (args.dryRun) {
|
|
882
|
+
if (pruned.length === 0) log.log('No results')
|
|
883
|
+
for (const item of pruned) log.log(item)
|
|
884
|
+
}
|
|
885
885
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prod-files",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Keep only prod files by pruning non-prod files from node_modules before deploying",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"clean",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"test": "node --test",
|
|
43
43
|
"test:e2e": "cd test-project && bash prepare_test.sh && time node ../index.mjs node_modules/.pnpm",
|
|
44
44
|
"test:e2e:nuke": "trash ./test-project/node_modules ./test-project/pnpm-lock.yaml && pnpm store prune",
|
|
45
|
+
"test:e2e:run": "cd test-project && node ../index.mjs node_modules/.pnpm",
|
|
45
46
|
"test:e2e:weight": "du -sh ./test-project/node_modules/.pnpm | sort -h"
|
|
46
47
|
}
|
|
47
48
|
}
|