pkgprn 0.5.5 → 0.7.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 CHANGED
@@ -62,16 +62,16 @@ Additional optional features can be enabled via flags:
62
62
 
63
63
  ## Options
64
64
 
65
- | Flag | Type | Default | Description |
66
- | --------------------- | ------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------- |
67
- | `--profile` | `string` | `library` | Script-retention profile (`library` or `app`). |
68
- | `--flatten` | `string \| boolean` | `false` | Flatten dist directories to the package root. Pass without a value to auto-detect, or provide comma-separated directory names. |
69
- | `--remove-sourcemaps` | `boolean` | `false` | Delete `.map` files and strip `sourceMappingURL` comments from source files. |
70
- | `--strip-comments` | `string \| boolean` | `false` | Strip comments from JS files. Pass without a value to strip all, or provide comma-separated types: `jsdoc`, `license`, `regular`. |
71
- | `--optimize-files` | `boolean` | `true` | Optimize the `files` array by collapsing entries. |
72
- | `--cleanup-files` | `boolean` | `true` | Remove files not listed in the `files` array. |
73
- | `--version` | | | Show version number. |
74
- | `--help` | | | Show help message. |
65
+ | Flag | Type | Default | Description |
66
+ | --------------------- | ------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
67
+ | `--profile` | `string` | `library` | Script-retention profile (`library` or `app`). |
68
+ | `--flatten` | `string \| boolean` | `false` | Flatten dist directories to the package root. Pass without a value (or `auto`) to auto-detect, or provide comma-separated directory names or repeat the flag. |
69
+ | `--remove-sourcemaps` | `boolean` | `false` | Delete `.map` files and strip `sourceMappingURL` comments from source files. |
70
+ | `--strip-comments` | `string \| boolean` | `false` | Strip comments from JS files. Pass without a value to strip JSDoc and regular comments, or provide comma-separated types: `jsdoc`, `license`, `regular`, `annotation`. |
71
+ | `--optimize-files` | `boolean` | `true` | Optimize the `files` array by collapsing entries. |
72
+ | `--cleanup-files` | `boolean` | `true` | Remove files not listed in the `files` array. |
73
+ | `--version` | | | Show version number. |
74
+ | `--help` | | | Show help message. |
75
75
 
76
76
  ## Profiles
77
77
 
@@ -100,19 +100,21 @@ Flattening moves files from a dist directory (e.g. `dist/`) into the package roo
100
100
 
101
101
  ### Auto-detect
102
102
 
103
- 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:
103
+ When `--flatten` is passed without a value (or with `auto`), `pkgprn` inspects `main`, `bin`, `module`, `exports`, `types`, and other entry-point fields to find the longest common directory prefix, and flattens that:
104
104
 
105
105
  ```sh
106
106
  pkgprn --flatten
107
+ pkgprn --flatten auto
107
108
  ```
108
109
 
109
110
  ### Explicit directories
110
111
 
111
- You can specify one or more directories to flatten (comma-separated):
112
+ You can specify one or more directories to flatten (comma-separated or by repeating the flag):
112
113
 
113
114
  ```sh
114
115
  pkgprn --flatten dist
115
116
  pkgprn --flatten dist,lib
117
+ pkgprn --flatten dist --flatten lib
116
118
  ```
117
119
 
118
120
  ### What flattening does
@@ -133,20 +135,23 @@ The `--strip-comments` flag removes comments from `.js`, `.mjs`, and `.cjs` file
133
135
  ### Usage
134
136
 
135
137
  ```sh
136
- pkgprn --strip-comments # strip all comments
137
- pkgprn --strip-comments jsdoc # strip only JSDoc comments
138
- pkgprn --strip-comments license,regular # strip license and regular comments
138
+ pkgprn --strip-comments # strip JSDoc and regular comments (default)
139
+ pkgprn --strip-comments jsdoc # strip only JSDoc comments
140
+ pkgprn --strip-comments jsdoc,license,regular,annotation # strip all comment types
141
+ pkgprn --strip-comments license # strip only license comments
142
+ pkgprn --strip-comments annotation # strip only annotation comments
139
143
  ```
140
144
 
141
145
  ### Comment types
142
146
 
143
- | Type | Description |
144
- | --------- | -------------------------------------------------- |
145
- | `jsdoc` | `/** … */` documentation comments |
146
- | `license` | Comments containing "license", "copyright", or "©" |
147
- | `regular` | All other `//` and `/* */` comments |
147
+ | Type | Description | Stripped by default |
148
+ | ------------ | ------------------------------------------------------------------------------------- | ------------------- |
149
+ | `jsdoc` | `/** … */` documentation comments | ✓ |
150
+ | `regular` | All other `//` and `/* */` comments | ✓ |
151
+ | `license` | `/*! */` or comments containing `@license` / `@preserve` | |
152
+ | `annotation` | Bundler annotations like `/*#__PURE__*/`, `/*@__PURE__*/`, `/*#__NO_SIDE_EFFECTS__*/` | |
148
153
 
149
- Passing `--strip-comments` without a value (or with `all`) strips every type.
154
+ Passing `--strip-comments` without a value (or with `all`) strips `jsdoc` and `regular` comments. License and annotation comments are preserved by default — specify them explicitly to strip them.
150
155
 
151
156
  ### Sourcemap adjustment
152
157
 
@@ -224,9 +229,9 @@ await prunePkg(
224
229
  pkg,
225
230
  {
226
231
  profile: "library",
227
- flatten: false,
232
+ flatten: false, // or true for auto-detect, or ["dist"] / ["dist", "lib"]
228
233
  removeSourcemaps: false,
229
- stripComments: false, // or "all", "jsdoc", "license,regular", etc.
234
+ stripComments: false, // or "all" (jsdoc+regular), "jsdoc", "license", "annotation", etc.
230
235
  optimizeFiles: true,
231
236
  cleanupFiles: true,
232
237
  },
@@ -237,7 +242,7 @@ await prunePkg(
237
242
  ### `prunePkg(pkg, options, logger)`
238
243
 
239
244
  - **`pkg`** - A mutable `package.json` object. Modified in place.
240
- - **`options`** - An options object matching the CLI flags.
245
+ - **`options`** - An options object matching the CLI flags. Note that `flatten` accepts `boolean | string[]` (`true` for auto-detect, or an array of directory names).
241
246
  - **`logger`** - A logger instance (from [`@niceties/logger`](https://www.npmjs.com/package/@niceties/logger)).
242
247
 
243
248
  ## Ignored Files
package/index.d.ts CHANGED
@@ -23,7 +23,7 @@ declare module 'pkgprn' {
23
23
  };
24
24
  export type PruneOptions = {
25
25
  profile: string;
26
- flatten: string | boolean;
26
+ flatten: string[] | boolean;
27
27
  removeSourcemaps: boolean;
28
28
  stripComments: string | boolean;
29
29
  optimizeFiles: boolean;
package/index.js CHANGED
@@ -3,9 +3,11 @@ import { readFile, writeFile } from 'node:fs/promises';
3
3
  import { dirname, resolve } from 'node:path';
4
4
  import { fileURLToPath } from 'node:url';
5
5
 
6
- import { cli } from 'cleye';
7
-
8
6
  import { createLogger } from '@niceties/logger';
7
+ import { parseArgsPlus } from '@niceties/node-parseargs-plus';
8
+ import { camelCase } from '@niceties/node-parseargs-plus/camel-case';
9
+ import { help } from '@niceties/node-parseargs-plus/help';
10
+ import { optionalValue } from '@niceties/node-parseargs-plus/optional-value';
9
11
 
10
12
  import { prunePkg } from './prune.js';
11
13
 
@@ -20,51 +22,67 @@ try {
20
22
  logger.update('');
21
23
  process.stdout.moveCursor?.(0, -1);
22
24
 
23
- const cliOptions = cli({
24
- name: 'pkgprn',
25
- version: version ?? '<unknown>',
26
- help: {
25
+ const { values } = parseArgsPlus(
26
+ {
27
+ name: 'pkgprn',
28
+ version: version ?? '<unknown>',
27
29
  description: 'prune devDependencies and redundant scripts from package.json',
28
- },
29
- flags: {
30
- profile: {
31
- type: String,
32
- description: 'profile to use',
33
- default: 'library',
34
- },
35
- flatten: {
36
- type: FlattenParam,
37
- description: 'flatten package files (comma-separated for multiple directories)',
38
- default: false,
39
- },
40
- removeSourcemaps: {
41
- type: Boolean,
42
- description: 'remove sourcemaps',
43
- default: false,
44
- },
45
- stripComments: {
46
- type: StripCommentsParam,
47
- description: 'strip comments: all (default), jsdoc, license, regular (comma-separated)',
48
- default: false,
49
- },
50
- optimizeFiles: {
51
- type: Boolean,
52
- description: 'optimize files array',
53
- default: true,
54
- },
55
- cleanupFiles: {
56
- type: Boolean,
57
- description: 'cleanup files not included in files array',
58
- default: true,
30
+ allowPositionals: true,
31
+ allowNegative: true,
32
+ options: {
33
+ profile: {
34
+ type: 'string',
35
+ description: 'profile to use',
36
+ default: 'library',
37
+ },
38
+ flatten: {
39
+ type: 'string',
40
+ multiple: true,
41
+ optionalValue: true,
42
+ description: 'flatten package files (use "auto" for auto-detect, or specify directories)',
43
+ },
44
+ removeSourcemaps: {
45
+ type: 'boolean',
46
+ description: 'remove sourcemaps',
47
+ default: false,
48
+ },
49
+ stripComments: {
50
+ type: 'string',
51
+ multiple: true,
52
+ optionalValue: true,
53
+ description: 'strip comments: all (default: jsdoc,regular), jsdoc, license, regular, annotation',
54
+ },
55
+ optimizeFiles: {
56
+ type: 'boolean',
57
+ description: 'optimize files array',
58
+ default: true,
59
+ },
60
+ cleanupFiles: {
61
+ type: 'boolean',
62
+ description: 'cleanup files not included in files array',
63
+ default: true,
64
+ },
59
65
  },
60
66
  },
61
- });
67
+ [camelCase, optionalValue, help]
68
+ );
69
+
70
+ const flattenDirs = values.flatten
71
+ ?.flatMap(v => v.split(','))
72
+ .map(s => s.trim())
73
+ .filter(Boolean);
74
+
75
+ const flags = {
76
+ ...values,
77
+ flatten: flattenDirs?.includes('auto') || values.flatten?.includes('') ? true : flattenDirs?.length ? flattenDirs : false,
78
+ stripComments: values.stripComments?.length ? values.stripComments.filter(Boolean).join(',') || 'all' : false,
79
+ };
62
80
 
63
81
  const pkg = await readPackage('.');
64
82
  if (!pkg) {
65
83
  throw new Error('Could not read package.json');
66
84
  }
67
- await prunePkg(pkg, cliOptions.flags, logger);
85
+ await prunePkg(pkg, flags, logger);
68
86
 
69
87
  await writePackage(pkg);
70
88
  } catch (error) {
@@ -92,17 +110,3 @@ async function readPackage(dir) {
92
110
  async function writePackage(pkg) {
93
111
  await writeFile('./package.json', `${JSON.stringify(pkg, null, 2)}\n`);
94
112
  }
95
-
96
- function StripCommentsParam(value) {
97
- if (value === '') {
98
- return 'all';
99
- }
100
- return value;
101
- }
102
-
103
- function FlattenParam(value) {
104
- if (value === '') {
105
- return true;
106
- }
107
- return value;
108
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pkgprn",
3
- "version": "0.5.5",
3
+ "version": "0.7.0",
4
4
  "license": "MIT",
5
5
  "author": "Konstantin Shutkin",
6
6
  "bin": "./index.js",
@@ -33,7 +33,7 @@
33
33
  "main": "prune.js",
34
34
  "dependencies": {
35
35
  "@jridgewell/sourcemap-codec": "^1.5.5",
36
- "@niceties/logger": "^1.1.13",
37
- "cleye": "2.2.1"
36
+ "@niceties/logger": "^2.1.0",
37
+ "@niceties/node-parseargs-plus": "^0.2.1"
38
38
  }
39
39
  }
package/prune.js CHANGED
@@ -1,4 +1,4 @@
1
- import { access, mkdir, readdir, readFile, rename, rm, stat, writeFile } from 'node:fs/promises';
1
+ import { access, glob as fsGlob, mkdir, readdir, readFile, rename, rm, stat, writeFile } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
 
4
4
  import { extractReferences } from './extract-references.js';
@@ -46,6 +46,10 @@ export async function prunePkg(pkg, options, logger) {
46
46
  }
47
47
  }
48
48
 
49
+ if (pkg.files && Array.isArray(pkg.files)) {
50
+ pkg.files = await expandFileGlobs(pkg.files);
51
+ }
52
+
49
53
  if (options.cleanupFiles) {
50
54
  await removeJunkFiles('.');
51
55
  } else if (options.flatten) {
@@ -252,11 +256,7 @@ async function flatten(pkg, flatten, logger, skipSourcemapAdjust) {
252
256
  }
253
257
  distDirs = [distDir];
254
258
  } else {
255
-
256
- distDirs = flatten
257
- .split(',')
258
- .map(d => normalizePath(d.trim()))
259
- .filter(Boolean);
259
+ distDirs = flatten.map(d => normalizePath(d.trim())).filter(Boolean);
260
260
  }
261
261
 
262
262
  logger.update(`flattening ${distDirs.join(', ')}...`);
@@ -348,7 +348,7 @@ async function flatten(pkg, flatten, logger, skipSourcemapAdjust) {
348
348
 
349
349
  await Promise.all(renamePromises);
350
350
 
351
- if (typeof flatten === 'string' && !skipSourcemapAdjust) {
351
+ if (Array.isArray(flatten) && !skipSourcemapAdjust) {
352
352
 
353
353
  const oldToNew = new Map();
354
354
  for (const [newPath, oldPath] of movedFiles) {
@@ -594,6 +594,25 @@ function isAlwaysIncludedByBasename(file) {
594
594
  return alwaysIncludedBasenames.includes(basenameWithoutExtension);
595
595
  }
596
596
 
597
+ function isGlobPattern(str) {
598
+ return /[*?[\]{}]/.test(str);
599
+ }
600
+
601
+ async function expandFileGlobs(files) {
602
+
603
+ const result = [];
604
+ for (const entry of files) {
605
+ if (isGlobPattern(entry)) {
606
+ for await (const match of fsGlob(entry)) {
607
+ result.push(normalizePath(match));
608
+ }
609
+ } else {
610
+ result.push(entry);
611
+ }
612
+ }
613
+ return [...new Set(result)];
614
+ }
615
+
597
616
  async function cleanupDir(pkg, logger) {
598
617
  logger.update('cleaning up files...');
599
618
 
package/strip-comments.js CHANGED
@@ -41,6 +41,10 @@ function classifyBlockComment(source, start, end) {
41
41
  return 'jsdoc';
42
42
  }
43
43
 
44
+ if (/^[#@]__[A-Z_]+__$/.test(body.trim())) {
45
+ return 'annotation';
46
+ }
47
+
44
48
  return 'regular';
45
49
  }
46
50
 
@@ -289,10 +293,10 @@ function scanTemplateTail(s, i, len, templateStack, comments) {
289
293
 
290
294
  export function parseCommentTypes(value) {
291
295
  if (value === true || value === 'all') {
292
- return new Set( (['jsdoc', 'license', 'regular']));
296
+ return new Set( (['jsdoc', 'regular']));
293
297
  }
294
298
 
295
- const valid = (['jsdoc', 'license', 'regular']);
299
+ const valid = (['jsdoc', 'license', 'regular', 'annotation']);
296
300
  const parts = String(value)
297
301
  .split(',')
298
302
  .map(s => s.trim())
@@ -302,7 +306,7 @@ export function parseCommentTypes(value) {
302
306
 
303
307
  for (const part of parts) {
304
308
  if (part === 'all') {
305
- return new Set(valid);
309
+ return new Set( (['jsdoc', 'regular']));
306
310
  }
307
311
  if (!valid.includes( (part))) {
308
312
  throw new Error(`unknown comment type "${part}" (expected: ${valid.join(', ')}, all)`);
@@ -311,7 +315,7 @@ export function parseCommentTypes(value) {
311
315
  }
312
316
 
313
317
  if (result.size === 0) {
314
- return new Set(valid);
318
+ return new Set( (['jsdoc', 'regular']));
315
319
  }
316
320
 
317
321
  return result;