pkgprn 0.1.0 → 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/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # pkgprn
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - c234bfb: improved cleanup
8
+ - 1ad1966: support multiple paths for flatten
9
+
10
+ ### Patch Changes
11
+
12
+ - 34d968a: better walkDir
13
+
3
14
  ## 0.1.0
4
15
 
5
16
  ### Minor Changes
package/README.md CHANGED
@@ -1,3 +1,219 @@
1
1
  # package-prune
2
2
 
3
- Prune package.json before publish
3
+ Prune `package.json` before publishing to npm. Removes `devDependencies`, strips unnecessary scripts, cleans up junk files, optimizes the `files` array, and optionally flattens dist directories — so your published package is lean and clean.
4
+
5
+ ## Installation
6
+
7
+ ```sh
8
+ npm install -D pkgprn
9
+ ```
10
+
11
+ Or with other package managers:
12
+
13
+ ```sh
14
+ pnpm add -D pkgprn
15
+ yarn add -D pkgprn
16
+ ```
17
+
18
+ You can also run it directly with `npx`:
19
+
20
+ ```sh
21
+ npx pkgprn
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ The recommended way to use `pkgprn` is as a `prepack` script in your `package.json`:
27
+
28
+ ```json
29
+ {
30
+ "scripts": {
31
+ "prepack": "pkgprn"
32
+ }
33
+ }
34
+ ```
35
+
36
+ This ensures your `package.json` is pruned automatically every time you run `npm pack` or `npm publish`.
37
+
38
+ You can also run it manually:
39
+
40
+ ```sh
41
+ npx pkgprn [options]
42
+ ```
43
+
44
+ The tool reads the `package.json` in the current working directory, applies all transformations in place, and writes the result back.
45
+
46
+ ## What It Does
47
+
48
+ By default, `pkgprn` performs the following steps:
49
+
50
+ 1. **Removes `devDependencies`** — Strips the entire `devDependencies` field from `package.json`.
51
+ 2. **Removes `packageManager`** — Strips the `packageManager` field.
52
+ 3. **Prunes scripts** — Removes scripts that are not relevant to package consumers (based on the selected [profile](#profiles)).
53
+ 4. **Removes junk files** — Deletes OS and editor artifacts (`.DS_Store`, `*.orig`, `.*.swp`, `._*`, etc.) from the package directory.
54
+ 5. **Optimizes the `files` array** — Collapses individual file entries into their parent directory when all files in that directory are already listed, and removes entries that npm always includes automatically (`package.json`, `README`, `LICENSE`).
55
+ 6. **Cleans up unlisted files** — Removes files and directories not covered by the `files` array, then drops the `files` field itself (since only the included files remain on disk).
56
+
57
+ Additional optional features can be enabled via flags:
58
+
59
+ - **Flatten** dist directories into the package root.
60
+ - **Remove sourcemaps** and their `//# sourceMappingURL=` references.
61
+
62
+ ## Options
63
+
64
+ | Flag | Type | Default | Description |
65
+ | --------------------- | ------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------ |
66
+ | `--profile` | `string` | `library` | Script-retention profile (`library` or `app`). |
67
+ | `--flatten` | `string \| boolean` | `false` | Flatten dist directories to the package root. Pass without a value to auto-detect, or provide comma-separated directory names. |
68
+ | `--remove-sourcemaps` | `boolean` | `false` | Delete `.map` files and strip `sourceMappingURL` comments from source files. |
69
+ | `--optimize-files` | `boolean` | `true` | Optimize the `files` array by collapsing entries. |
70
+ | `--cleanup-files` | `boolean` | `true` | Remove files not listed in the `files` array. |
71
+ | `--version` | | | Show version number. |
72
+ | `--help` | | | Show help message. |
73
+
74
+ ## Profiles
75
+
76
+ Profiles control which npm lifecycle scripts are kept in the published `package.json`. All other scripts are removed.
77
+
78
+ ### `library` (default)
79
+
80
+ Keeps only the scripts that npm runs during package installation:
81
+
82
+ - `preinstall`, `install`, `postinstall`
83
+ - `prepublish`
84
+ - `preprepare`, `prepare`, `postprepare`
85
+
86
+ ### `app`
87
+
88
+ Keeps everything from the `library` profile, plus runtime and test lifecycle scripts:
89
+
90
+ - `prestart`, `start`, `poststart`
91
+ - `prerestart`, `restart`, `postrestart`
92
+ - `prestop`, `stop`, `poststop`
93
+ - `pretest`, `test`, `posttest`
94
+
95
+ ## Flattening
96
+
97
+ Flattening moves files from a dist directory (e.g. `dist/`) into the package root and updates all references in `package.json` (`main`, `module`, `exports`, `bin`, `types`, `typesVersions`, etc.) accordingly.
98
+
99
+ ### Auto-detect
100
+
101
+ When `--flatten` is passed without a value, `pkgprn` inspects `main`, `bin`, `module`, `exports`, `types`, and other entry-point fields to find the longest common directory prefix, and flattens that:
102
+
103
+ ```sh
104
+ pkgprn --flatten
105
+ ```
106
+
107
+ ### Explicit directories
108
+
109
+ You can specify one or more directories to flatten (comma-separated):
110
+
111
+ ```sh
112
+ pkgprn --flatten dist
113
+ pkgprn --flatten dist,lib
114
+ ```
115
+
116
+ ### What flattening does
117
+
118
+ 1. Identifies all files in the target directory/directories.
119
+ 2. Checks for naming conflicts with existing root-level files.
120
+ 3. Moves all files to the root (preserving subdirectory structure relative to the dist directory).
121
+ 4. Removes the now-empty dist directory.
122
+ 5. Rewrites all path references in `package.json` to point to the new locations.
123
+ 6. Updates the `files` array.
124
+ 7. Cleans up any leftover export-map stub directories that only contain a `package.json`.
125
+
126
+ ## Examples
127
+
128
+ ### Basic library
129
+
130
+ ```json
131
+ {
132
+ "scripts": {
133
+ "build": "tsc",
134
+ "test": "vitest",
135
+ "prepack": "pkgprn"
136
+ }
137
+ }
138
+ ```
139
+
140
+ After packing, `build` and `test` are removed; `devDependencies` and `packageManager` are gone.
141
+
142
+ ### Library with flattened dist
143
+
144
+ ```json
145
+ {
146
+ "scripts": {
147
+ "build": "rollup -c",
148
+ "prepack": "pkgprn --flatten dist"
149
+ },
150
+ "main": "dist/index.js",
151
+ "types": "dist/index.d.ts",
152
+ "files": ["dist"]
153
+ }
154
+ ```
155
+
156
+ After packing, `dist/index.js` becomes `index.js`, `main` points to `index.js`, and the `dist` directory is gone.
157
+
158
+ ### Application with sourcemap removal
159
+
160
+ ```sh
161
+ pkgprn --profile app --remove-sourcemaps
162
+ ```
163
+
164
+ ### Disable file cleanup
165
+
166
+ If you only want script and dependency pruning without touching files on disk:
167
+
168
+ ```sh
169
+ pkgprn --no-cleanup-files --no-optimize-files
170
+ ```
171
+
172
+ ## Programmatic API
173
+
174
+ The core pruning logic is also available as a function:
175
+
176
+ ```js
177
+ import { prunePkg } from "pkgprn";
178
+
179
+ const pkg = JSON.parse(await readFile("package.json", "utf8"));
180
+
181
+ await prunePkg(
182
+ pkg,
183
+ {
184
+ profile: "library",
185
+ flatten: false,
186
+ removeSourcemaps: false,
187
+ optimizeFiles: true,
188
+ cleanupFiles: true,
189
+ },
190
+ logger,
191
+ );
192
+ ```
193
+
194
+ ### `prunePkg(pkg, options, logger)`
195
+
196
+ - **`pkg`** — A mutable `package.json` object. Modified in place.
197
+ - **`options`** — An options object matching the CLI flags.
198
+ - **`logger`** — A logger instance (from [`@niceties/logger`](https://www.npmjs.com/package/@niceties/logger)).
199
+
200
+ ## Ignored Files
201
+
202
+ `pkgprn` automatically removes files that npm itself always ignores:
203
+
204
+ - `.DS_Store`, `.git`, `.hg`, `.svn`, `CVS`
205
+ - `.lock-wscript`, `config.gypi`, `npm-debug.log`
206
+ - `*.orig`, `.*.swp`, `._*`, `.wafpickle-N`
207
+ - `node_modules`, `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`, `bun.lockb`, `.npmrc`
208
+
209
+ Files that npm always includes are preserved regardless of the `files` array:
210
+
211
+ - `package.json`
212
+ - `README` (any extension, case-insensitive)
213
+ - `LICENSE` / `LICENCE` (any extension, case-insensitive)
214
+ - The file referenced by `main`
215
+ - Files referenced by `bin`
216
+
217
+ ## License
218
+
219
+ [MIT](./LICENSE)
package/biome.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/2.3.2/schema.json",
3
+ "linter": {
4
+ "enabled": true,
5
+ "rules": {
6
+ "recommended": true
7
+ }
8
+ },
9
+ "assist": {
10
+ "actions": {
11
+ "source": {
12
+ "organizeImports": {
13
+ "level": "on",
14
+ "options": {
15
+ "groups": [
16
+ ":NODE:",
17
+ ":BLANK_LINE:",
18
+ { "type": false, "source": [":PACKAGE:", "!@slimlib/**", "!@niceties/**"] },
19
+ ":BLANK_LINE:",
20
+ { "type": false, "source": ["@slimlib/**", "@niceties/**"] },
21
+ ":BLANK_LINE:",
22
+ { "type": false, "source": ":PATH:" }
23
+ ]
24
+ }
25
+ }
26
+ }
27
+ }
28
+ },
29
+ "formatter": {
30
+ "enabled": true,
31
+ "formatWithErrors": false,
32
+ "indentStyle": "space",
33
+ "indentWidth": 4,
34
+ "lineEnding": "lf",
35
+ "lineWidth": 140
36
+ },
37
+ "javascript": {
38
+ "formatter": {
39
+ "quoteStyle": "single",
40
+ "jsxQuoteStyle": "single",
41
+ "quoteProperties": "asNeeded",
42
+ "trailingCommas": "es5",
43
+ "semicolons": "always",
44
+ "arrowParentheses": "asNeeded",
45
+ "bracketSpacing": true,
46
+ "bracketSameLine": false,
47
+ "attributePosition": "auto"
48
+ }
49
+ },
50
+ "json": {
51
+ "formatter": {
52
+ "enabled": true,
53
+ "indentWidth": 4,
54
+ "lineWidth": 140
55
+ }
56
+ },
57
+ "vcs": {
58
+ "enabled": true,
59
+ "clientKind": "git",
60
+ "useIgnoreFile": true
61
+ }
62
+ }
package/index.js CHANGED
@@ -1,9 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import { createLogger } from '@niceties/logger';
3
- import { cli } from 'cleye';
4
2
  import { readFile, writeFile } from 'node:fs/promises';
5
3
  import { dirname, resolve } from 'node:path';
6
4
  import { fileURLToPath } from 'node:url';
5
+
6
+ import { cli } from 'cleye';
7
+
8
+ import { createLogger } from '@niceties/logger';
9
+
7
10
  import { prunePkg } from './prune.js';
8
11
 
9
12
  // globals
@@ -21,8 +24,9 @@ try {
21
24
  const cliOptions = cli({
22
25
  name: 'pkgprn',
23
26
  version: version ?? '<unknown>',
24
- description:
25
- 'prune devDependencies and redundant scripts from package.json',
27
+ help: {
28
+ description: 'prune devDependencies and redundant scripts from package.json',
29
+ },
26
30
  flags: {
27
31
  profile: {
28
32
  type: String,
@@ -31,7 +35,7 @@ try {
31
35
  },
32
36
  flatten: {
33
37
  type: FlattenParam,
34
- description: 'flatten package files',
38
+ description: 'flatten package files (comma-separated for multiple directories)',
35
39
  default: false,
36
40
  },
37
41
  removeSourcemaps: {
@@ -44,6 +48,11 @@ try {
44
48
  description: 'optimize files array',
45
49
  default: true,
46
50
  },
51
+ cleanupFiles: {
52
+ type: Boolean,
53
+ description: 'cleanup files not included in files array',
54
+ default: true,
55
+ },
47
56
  },
48
57
  });
49
58
 
@@ -66,9 +75,7 @@ try {
66
75
  async function getMyVersion() {
67
76
  const pkg = await readPackage(resolve(__dirname));
68
77
 
69
- return pkg && 'version' in pkg && typeof pkg.version === 'string'
70
- ? pkg.version
71
- : '<unknown>';
78
+ return pkg && 'version' in pkg && typeof pkg.version === 'string' ? pkg.version : '<unknown>';
72
79
  }
73
80
 
74
81
  /**
@@ -96,9 +103,6 @@ async function writePackage(pkg) {
96
103
  * @param {string | false} value
97
104
  */
98
105
  function FlattenParam(value) {
99
- if (typeof value === 'boolean') {
100
- return value; // false
101
- }
102
106
  if (value === '') {
103
107
  return true; // means auto
104
108
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pkgprn",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "license": "MIT",
5
5
  "author": "Konstantin Shutkin",
6
6
  "bin": "./index.js",
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "main": "prune.js",
18
18
  "dependencies": {
19
- "cleye": "1.3.2",
19
+ "cleye": "2.2.1",
20
20
  "jsonata": "^2.1.0",
21
21
  "@niceties/logger": "^1.1.13"
22
22
  }
@@ -1,2 +1,4 @@
1
+ overrides:
2
+ yargs: ^18.0.0
1
3
  onlyBuiltDependencies:
2
- - '@biomejs/biome'
4
+ - "@biomejs/biome"