pkgprn 0.6.0 → 0.8.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,9 +23,9 @@ declare module 'pkgprn' {
23
23
  };
24
24
  export type PruneOptions = {
25
25
  profile: string;
26
- flatten: string | boolean;
26
+ flatten: true | string[] | false;
27
27
  removeSourcemaps: boolean;
28
- stripComments: string | boolean;
28
+ stripComments: true | string[] | false;
29
29
  optimizeFiles: boolean;
30
30
  cleanupFiles: boolean;
31
31
  };
package/index.js CHANGED
@@ -1,70 +1,86 @@
1
1
  #!/usr/bin/env node
2
2
  import { readFile, writeFile } from 'node:fs/promises';
3
- import { dirname, resolve } from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
-
6
- import { cli } from 'cleye';
3
+ import { resolve } from 'node:path';
7
4
 
8
5
  import { createLogger } from '@niceties/logger';
6
+ import { parseArgsPlus } from '@niceties/node-parseargs-plus';
7
+ import { camelCase } from '@niceties/node-parseargs-plus/camel-case';
8
+ import { customValue } from '@niceties/node-parseargs-plus/custom-value';
9
+ import { help } from '@niceties/node-parseargs-plus/help';
10
+ import { optionalValue } from '@niceties/node-parseargs-plus/optional-value';
11
+ import { readPackageJson } from '@niceties/node-parseargs-plus/package-info';
9
12
 
10
13
  import { prunePkg } from './prune.js';
11
14
 
12
- const __dirname = dirname(fileURLToPath(import.meta.url));
15
+ function parseMultiString(values) {
16
+ const items = values
17
+ .flatMap(v => v.split(','))
18
+ .map(s => s.trim())
19
+ .filter(Boolean);
20
+ return items.length ? items : true;
21
+ }
13
22
 
14
23
  const logger = createLogger();
15
24
  logger.update('preparing..');
16
25
 
17
26
  try {
18
- const version = await getMyVersion();
27
+ const myPkgData = await readPackageJson(import.meta.url);
19
28
 
20
29
  logger.update('');
21
- process.stdout.moveCursor?.(0, -1);
22
30
 
23
- const cliOptions = cli({
24
- name: 'pkgprn',
25
- version: version ?? '<unknown>',
26
- help: {
27
- 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,
31
+ const { values } = parseArgsPlus(
32
+ {
33
+ ...myPkgData,
34
+ allowNegative: true,
35
+ options: {
36
+ profile: {
37
+ type: 'string',
38
+ description: 'profile to use',
39
+ default: 'library',
40
+ },
41
+ flatten: {
42
+ type: (parseMultiString),
43
+ multiple: true,
44
+ optionalValue: true,
45
+ description: 'flatten package files (omit value to auto-detect, or specify directories)',
46
+ },
47
+ removeSourcemaps: {
48
+ type: 'boolean',
49
+ description: 'remove sourcemaps',
50
+ default: false,
51
+ },
52
+ stripComments: {
53
+ type: (parseMultiString),
54
+ multiple: true,
55
+ optionalValue: true,
56
+ description: 'strip comments (omit value for defaults, or specify types: jsdoc, license, regular, annotation)',
57
+ },
58
+ optimizeFiles: {
59
+ type: 'boolean',
60
+ description: 'optimize files array',
61
+ default: true,
62
+ },
63
+ cleanupFiles: {
64
+ type: 'boolean',
65
+ description: 'cleanup files not included in files array',
66
+ default: true,
67
+ },
59
68
  },
60
69
  },
61
- });
70
+ [camelCase, customValue, optionalValue, help]
71
+ );
72
+
73
+ const flags = {
74
+ ...values,
75
+ flatten: values.flatten ?? false,
76
+ stripComments: values.stripComments ?? false,
77
+ };
62
78
 
63
79
  const pkg = await readPackage('.');
64
80
  if (!pkg) {
65
81
  throw new Error('Could not read package.json');
66
82
  }
67
- await prunePkg(pkg, cliOptions.flags, logger);
83
+ await prunePkg(pkg, flags, logger);
68
84
 
69
85
  await writePackage(pkg);
70
86
  } catch (error) {
@@ -73,12 +89,6 @@ try {
73
89
  process.exit(255);
74
90
  }
75
91
 
76
- async function getMyVersion() {
77
- const pkg = await readPackage(resolve(__dirname));
78
-
79
- return pkg && 'version' in pkg && typeof pkg.version === 'string' ? pkg.version : '<unknown>';
80
- }
81
-
82
92
  async function readPackage(dir) {
83
93
  const packageFileName = resolve(dir, 'package.json');
84
94
  try {
@@ -92,17 +102,3 @@ async function readPackage(dir) {
92
102
  async function writePackage(pkg) {
93
103
  await writeFile('./package.json', `${JSON.stringify(pkg, null, 2)}\n`);
94
104
  }
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.6.0",
3
+ "version": "0.8.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.5.0"
38
38
  }
39
39
  }
package/prune.js CHANGED
@@ -88,7 +88,7 @@ export async function prunePkg(pkg, options, logger) {
88
88
  }
89
89
 
90
90
  if (options.stripComments) {
91
- const typesToStrip = parseCommentTypes( (options.stripComments));
91
+ const typesToStrip = parseCommentTypes(options.stripComments);
92
92
  logger.update('stripping comments...');
93
93
  const allFiles = await walkDir('.', ['node_modules']);
94
94
  const jsFiles = allFiles.filter(isStrippableFile);
@@ -256,11 +256,7 @@ async function flatten(pkg, flatten, logger, skipSourcemapAdjust) {
256
256
  }
257
257
  distDirs = [distDir];
258
258
  } else {
259
-
260
- distDirs = flatten
261
- .split(',')
262
- .map(d => normalizePath(d.trim()))
263
- .filter(Boolean);
259
+ distDirs = flatten.map(d => normalizePath(d.trim())).filter(Boolean);
264
260
  }
265
261
 
266
262
  logger.update(`flattening ${distDirs.join(', ')}...`);
@@ -352,7 +348,7 @@ async function flatten(pkg, flatten, logger, skipSourcemapAdjust) {
352
348
 
353
349
  await Promise.all(renamePromises);
354
350
 
355
- if (typeof flatten === 'string' && !skipSourcemapAdjust) {
351
+ if (Array.isArray(flatten) && !skipSourcemapAdjust) {
356
352
 
357
353
  const oldToNew = new Map();
358
354
  for (const [newPath, oldPath] of movedFiles) {
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
 
@@ -288,30 +292,23 @@ function scanTemplateTail(s, i, len, templateStack, comments) {
288
292
  }
289
293
 
290
294
  export function parseCommentTypes(value) {
291
- if (value === true || value === 'all') {
292
- return new Set( (['jsdoc', 'license', 'regular']));
295
+ if (value === true) {
296
+ return new Set( (['jsdoc', 'regular']));
293
297
  }
294
298
 
295
- const valid = (['jsdoc', 'license', 'regular']);
296
- const parts = String(value)
297
- .split(',')
298
- .map(s => s.trim())
299
- .filter(Boolean);
299
+ const valid = (['jsdoc', 'license', 'regular', 'annotation']);
300
300
 
301
301
  const result = new Set();
302
302
 
303
- for (const part of parts) {
304
- if (part === 'all') {
305
- return new Set(valid);
306
- }
303
+ for (const part of value) {
307
304
  if (!valid.includes( (part))) {
308
- throw new Error(`unknown comment type "${part}" (expected: ${valid.join(', ')}, all)`);
305
+ throw new Error(`unknown comment type "${part}" (expected: ${valid.join(', ')})`);
309
306
  }
310
307
  result.add( (part));
311
308
  }
312
309
 
313
310
  if (result.size === 0) {
314
- return new Set(valid);
311
+ return new Set( (['jsdoc', 'regular']));
315
312
  }
316
313
 
317
314
  return result;