knip 2.3.0 → 2.3.2
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 +59 -62
- package/dist/ConfigurationChief.d.ts +1 -0
- package/dist/ConfigurationChief.js +2 -0
- package/dist/DependencyDeputy.js +19 -14
- package/dist/WorkspaceWorker.js +1 -1
- package/dist/binaries/bash-parser.js +3 -2
- package/dist/binaries/index.js +4 -3
- package/dist/binaries/resolvers/fallback.js +2 -2
- package/dist/binaries/resolvers/node.js +1 -1
- package/dist/binaries/resolvers/npx.js +5 -2
- package/dist/binaries/resolvers/pnpm.js +5 -4
- package/dist/binaries/resolvers/rollup.js +2 -2
- package/dist/binaries/resolvers/yarn.js +6 -5
- package/dist/binaries/util.d.ts +6 -0
- package/dist/binaries/util.js +23 -0
- package/dist/index.js +2 -9
- package/dist/plugins/eslint/helpers.js +12 -11
- package/dist/util/modules.d.ts +0 -1
- package/dist/util/modules.js +0 -4
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/dist/binaries/resolvers/util.d.ts +0 -2
- package/dist/binaries/resolvers/util.js +0 -15
package/README.md
CHANGED
|
@@ -32,16 +32,11 @@ Knip shines in both small and large projects. It's a fresh take on keeping your
|
|
|
32
32
|
[![An orange cow with scissors, Van Gogh style][7]][6] <sup>_“An orange cow with scissors, Van Gogh style” - generated
|
|
33
33
|
with OpenAI_</sup>
|
|
34
34
|
|
|
35
|
-
## Migrating to v2.0.0
|
|
36
|
-
|
|
37
|
-
Migrating from v1 to v2 requires no changes in configuration. Mostly it's just a whole lot faster! The [release notes
|
|
38
|
-
for v2][8] provide more details.
|
|
39
|
-
|
|
40
35
|
## Installation
|
|
41
36
|
|
|
42
37
|
npm install -D knip
|
|
43
38
|
|
|
44
|
-
Knip supports LTS versions of Node.js, and currently requires at least Node.js v16.17 or v18.6.
|
|
39
|
+
Knip supports LTS versions of Node.js, and currently requires at least Node.js v16.17 or v18.6.
|
|
45
40
|
|
|
46
41
|
## Configuration
|
|
47
42
|
|
|
@@ -54,7 +49,7 @@ Knip has good defaults and you can run it without any configuration. Here's the
|
|
|
54
49
|
}
|
|
55
50
|
```
|
|
56
51
|
|
|
57
|
-
|
|
52
|
+
Well, almost, this is the full list of default extensions: `js`, `mjs`, `cjs`, `jsx`, `ts`, `mts`, `cts` and `tsx`.
|
|
58
53
|
|
|
59
54
|
### Entry Files
|
|
60
55
|
|
|
@@ -65,8 +60,8 @@ Knip looks for entry files at the default locations above, but also in other pla
|
|
|
65
60
|
- The `scripts` in package.json may also provide entry files that Knip can use.
|
|
66
61
|
- Knip does this for each [workspace][1] it finds.
|
|
67
62
|
|
|
68
|
-
In other words, Knip looks in many places and you may not need much configuration.
|
|
69
|
-
defaults you don't even need a `knip.json` file.
|
|
63
|
+
In other words, Knip looks in many places and you may not need much configuration. In a perfectly boring world where
|
|
64
|
+
everything is according to defaults you don't even need a `knip.json` file.
|
|
70
65
|
|
|
71
66
|
Larger projects tend to have more things customized, and therefore probably get more out of Knip with a configuration
|
|
72
67
|
file. Let's say you are using `.ts` files excusively and have all source files only in the `src` directory:
|
|
@@ -178,19 +173,23 @@ The report contains the following types of issues:
|
|
|
178
173
|
|
|
179
174
|
- **Unused files**: did not find references to this file
|
|
180
175
|
- **Unused dependencies**: did not find references to this dependency
|
|
181
|
-
- **
|
|
176
|
+
- **Unused devDependencies**: did not find references to this dependency
|
|
177
|
+
- **Unlisted dependencies**: used dependencies, but not listed in package.json _(1)_
|
|
182
178
|
- **Unresolved imports**: import specifiers that could not be resolved
|
|
183
179
|
- **Unused exports**: did not find references to this exported variable
|
|
184
|
-
- **Unused exports in namespaces**: did not find direct references to this exported variable _(
|
|
180
|
+
- **Unused exports in namespaces**: did not find direct references to this exported variable _(2)_
|
|
185
181
|
- **Unused exported types**: did not find references to this exported type
|
|
186
|
-
- **Unused exported types in namespaces**: did not find direct references to this exported variable _(
|
|
182
|
+
- **Unused exported types in namespaces**: did not find direct references to this exported variable _(2)_
|
|
187
183
|
- **Unused exported enum members**: did not find references to this member of the exported enum
|
|
188
184
|
- **Unused exported class members**: did not find references to this member of the exported class
|
|
189
185
|
- **Duplicate exports**: the same thing is exported more than once
|
|
190
186
|
|
|
191
187
|
When an issue type has zero issues, it is not shown.
|
|
192
188
|
|
|
193
|
-
_(1)_
|
|
189
|
+
_(1)_ If an unlisted dependency is prefixed with `bin:` it means a binary is missing. This often equals the package
|
|
190
|
+
name, but not always (e.g. `tsc` of `typescript` or `webpack` from `webpack-cli`).
|
|
191
|
+
|
|
192
|
+
_(2)_ The variable or type is not referenced directly, and has become a member of a namespace. Knip can't find a
|
|
194
193
|
reference to it, so you can _probably_ remove it.
|
|
195
194
|
|
|
196
195
|
### Output filters
|
|
@@ -209,8 +208,8 @@ Use `--exclude` to ignore reports you're not interested in:
|
|
|
209
208
|
|
|
210
209
|
Use `--dependencies` or `--exports` as shortcuts to combine groups of related types.
|
|
211
210
|
|
|
212
|
-
Still not happy with the results? Getting too much output/false positives? The [FAQ][
|
|
213
|
-
an issue and I'm happy to look into it. Also see the next section on how to [ignore][
|
|
211
|
+
Still not happy with the results? Getting too much output/false positives? The [FAQ][8] may be useful. Feel free to open
|
|
212
|
+
an issue and I'm happy to look into it. Also see the next section on how to [ignore][9] certain false positives:
|
|
214
213
|
|
|
215
214
|
## Ignore
|
|
216
215
|
|
|
@@ -391,7 +390,7 @@ to override any defaults. Let's take Cypress for example. By default it uses `cy
|
|
|
391
390
|
### Multi-project repositories
|
|
392
391
|
|
|
393
392
|
Some repositories have a single `package.json`, but consist of multiple projects with potentially lots of configuration
|
|
394
|
-
files (such as the [Nx "intregrated repo" style][
|
|
393
|
+
files (such as the [Nx "intregrated repo" style][10]). Let's assume some of these projects are apps and have their own
|
|
395
394
|
Cypress configuration and test files. In that case, we could configure the Cypress plugin like this:
|
|
396
395
|
|
|
397
396
|
```json
|
|
@@ -408,7 +407,7 @@ In case a plugin causes issues, it can be disabled by using `false` as its value
|
|
|
408
407
|
|
|
409
408
|
### Create a new plugin
|
|
410
409
|
|
|
411
|
-
Getting false positives because a plugin is missing? Want to help out? Please read more at [writing a plugin][
|
|
410
|
+
Getting false positives because a plugin is missing? Want to help out? Please read more at [writing a plugin][11]. This
|
|
412
411
|
guide also contains more details if you want to learn more about plugins and why they are useful.
|
|
413
412
|
|
|
414
413
|
## Compilers
|
|
@@ -431,7 +430,7 @@ export default {
|
|
|
431
430
|
};
|
|
432
431
|
```
|
|
433
432
|
|
|
434
|
-
Read [Compilers][
|
|
433
|
+
Read [Compilers][12] for more details and examples.
|
|
435
434
|
|
|
436
435
|
## Production Mode
|
|
437
436
|
|
|
@@ -508,7 +507,7 @@ When the provided built-in reporters are not sufficient, a custom reporter can b
|
|
|
508
507
|
Pass `--reporter ./my-reporter` from the command-line. The data can then be used to write issues to `stdout`, a JSON or
|
|
509
508
|
CSV file, or sent to a service.
|
|
510
509
|
|
|
511
|
-
Find more details and ideas in [custom reporters][
|
|
510
|
+
Find more details and ideas in [custom reporters][13].
|
|
512
511
|
|
|
513
512
|
## Public exports
|
|
514
513
|
|
|
@@ -557,34 +556,33 @@ When unused dependencies are related to dependencies having a Knip [plugin][1],
|
|
|
557
556
|
for that dependency are at custom locations. The default values are at the plugin's documentation, and can be overridden
|
|
558
557
|
to match the custom location(s).
|
|
559
558
|
|
|
560
|
-
When the dependencies don't have a Knip plugin yet, please file an issue or [create a new plugin][
|
|
559
|
+
When the dependencies don't have a Knip plugin yet, please file an issue or [create a new plugin][14].
|
|
561
560
|
|
|
562
561
|
#### Too many unused exports
|
|
563
562
|
|
|
564
|
-
|
|
563
|
+
Unused exports of `entry` files are not reported. When exports of other files are marked as unused, because they are
|
|
564
|
+
meant to be used by consumers of the library, there are a few options:
|
|
565
565
|
|
|
566
|
-
1.
|
|
567
|
-
|
|
568
|
-
|
|
566
|
+
1. Add the containing file to the `entry` array in the configuration.
|
|
567
|
+
2. Re-export from an existing entry file.
|
|
568
|
+
3. Mark the exported value or type [using the JSDoc `@public` tag][15].
|
|
569
569
|
|
|
570
570
|
### How to start using Knip in CI while having too many issues to sort out?
|
|
571
571
|
|
|
572
572
|
Eventually this type of QA only really works when it's tied to an automated workflow. But with too many issues to
|
|
573
573
|
resolve this might not be feasible right away, especially in existing larger codebase. Here are a few options that may
|
|
574
|
-
help:
|
|
574
|
+
help in the meantime:
|
|
575
575
|
|
|
576
576
|
- Use `--no-exit-code` for exit code 0 in CI.
|
|
577
577
|
- Use `--include` (or `--exclude`) to report only the issue types that have little or no errors.
|
|
578
|
-
- Use separate Knip commands to analyze e.g.
|
|
579
|
-
- Use [ignore patterns][
|
|
580
|
-
|
|
581
|
-
All of this is hiding problems, so please make sure to plan for fixing them and/or open issues here for false positives.
|
|
578
|
+
- Use separate Knip commands to analyze e.g. only `--dependencies` or `--exports`.
|
|
579
|
+
- Use [ignore patterns][9] to filter out the most problematic areas.
|
|
582
580
|
|
|
583
581
|
## Comparison
|
|
584
582
|
|
|
585
583
|
This table is an ongoing comparison. Based on their docs (please report any mistakes):
|
|
586
584
|
|
|
587
|
-
| Feature | **knip** | [depcheck][
|
|
585
|
+
| Feature | **knip** | [depcheck][16] | [unimported][17] | [ts-unused-exports][18] | [ts-prune][19] |
|
|
588
586
|
| :---------------------- | :------: | :------------: | :--------------: | :---------------------: | :------------: |
|
|
589
587
|
| Unused files | ✅ | - | ✅ | - | - |
|
|
590
588
|
| Unused dependencies | ✅ | ✅ | ✅ | - | - |
|
|
@@ -620,7 +618,7 @@ The following commands are similar:
|
|
|
620
618
|
unimported
|
|
621
619
|
knip --production --dependencies --include files
|
|
622
620
|
|
|
623
|
-
Also see [production mode][
|
|
621
|
+
Also see [production mode][20].
|
|
624
622
|
|
|
625
623
|
### ts-unused-exports
|
|
626
624
|
|
|
@@ -642,13 +640,13 @@ The following commands are similar:
|
|
|
642
640
|
|
|
643
641
|
Many thanks to some of the early adopters of Knip:
|
|
644
642
|
|
|
645
|
-
- [Block Protocol][
|
|
646
|
-
- [DeepmergeTS][
|
|
647
|
-
- [eslint-plugin-functional][
|
|
648
|
-
- [freeCodeCamp.org][
|
|
649
|
-
- [is-immutable-type][
|
|
650
|
-
- [release-it][
|
|
651
|
-
- [Template TypeScript Node Package][
|
|
643
|
+
- [Block Protocol][21]
|
|
644
|
+
- [DeepmergeTS][22]
|
|
645
|
+
- [eslint-plugin-functional][23]
|
|
646
|
+
- [freeCodeCamp.org][24]
|
|
647
|
+
- [is-immutable-type][25]
|
|
648
|
+
- [release-it][26]
|
|
649
|
+
- [Template TypeScript Node Package][27]
|
|
652
650
|
|
|
653
651
|
## Knip?!
|
|
654
652
|
|
|
@@ -659,7 +657,7 @@ for the job. I'm motivated to make knip perfectly suited for the job of cutting
|
|
|
659
657
|
|
|
660
658
|
Special thanks to the wonderful people who have contributed to this project:
|
|
661
659
|
|
|
662
|
-
[![Contributors][
|
|
660
|
+
[![Contributors][29]][28]
|
|
663
661
|
|
|
664
662
|
[1]: #workspaces-monorepos
|
|
665
663
|
[2]: #plugins
|
|
@@ -668,29 +666,28 @@ Special thanks to the wonderful people who have contributed to this project:
|
|
|
668
666
|
[5]: #custom-reporters
|
|
669
667
|
[6]: https://labs.openai.com/s/xZQACaLepaKya0PRUPtIN5dC
|
|
670
668
|
[7]: ./assets/cow-with-orange-scissors-van-gogh-style.webp
|
|
671
|
-
[8]:
|
|
672
|
-
[9]: #
|
|
673
|
-
[10]:
|
|
674
|
-
[11]:
|
|
675
|
-
[12]: ./docs/
|
|
676
|
-
[13]: ./docs/
|
|
677
|
-
[14]:
|
|
678
|
-
[15]: #
|
|
679
|
-
[16]:
|
|
680
|
-
[17]: https://github.com/
|
|
681
|
-
[18]: https://github.com/
|
|
682
|
-
[19]: https://github.com/
|
|
683
|
-
[20]:
|
|
684
|
-
[21]:
|
|
685
|
-
[22]: https://github.com/
|
|
686
|
-
[23]: https://github.com/
|
|
687
|
-
[24]: https://github.com/
|
|
688
|
-
[25]: https://github.com/
|
|
689
|
-
[26]: https://github.com/
|
|
690
|
-
[27]: https://github.com/
|
|
691
|
-
[28]: https://github.com/
|
|
692
|
-
[29]: https://
|
|
693
|
-
[30]: https://contrib.rocks/image?repo=webpro/knip
|
|
669
|
+
[8]: #faq
|
|
670
|
+
[9]: #ignore
|
|
671
|
+
[10]: https://nx.dev/concepts/integrated-vs-package-based
|
|
672
|
+
[11]: ./docs/writing-a-plugin.md
|
|
673
|
+
[12]: ./docs/compilers.md
|
|
674
|
+
[13]: ./docs/custom-reporters.md
|
|
675
|
+
[14]: #create-a-new-plugin
|
|
676
|
+
[15]: #public-exports
|
|
677
|
+
[16]: https://github.com/depcheck/depcheck
|
|
678
|
+
[17]: https://github.com/smeijer/unimported
|
|
679
|
+
[18]: https://github.com/pzavolinsky/ts-unused-exports
|
|
680
|
+
[19]: https://github.com/nadeesha/ts-prune
|
|
681
|
+
[20]: #production-mode
|
|
682
|
+
[21]: https://github.com/blockprotocol/blockprotocol
|
|
683
|
+
[22]: https://github.com/RebeccaStevens/deepmerge-ts
|
|
684
|
+
[23]: https://github.com/eslint-functional/eslint-plugin-functional
|
|
685
|
+
[24]: https://github.com/freeCodeCamp/freeCodeCamp
|
|
686
|
+
[25]: https://github.com/RebeccaStevens/is-immutable-type
|
|
687
|
+
[26]: https://github.com/release-it/release-it
|
|
688
|
+
[27]: https://github.com/JoshuaKGoldberg/template-typescript-node-package
|
|
689
|
+
[28]: https://github.com/webpro/knip/graphs/contributors
|
|
690
|
+
[29]: https://contrib.rocks/image?repo=webpro/knip
|
|
694
691
|
[plugin-ava]: ./src/plugins/ava
|
|
695
692
|
[plugin-babel]: ./src/plugins/babel
|
|
696
693
|
[plugin-capacitor]: ./src/plugins/capacitor
|
|
@@ -24,6 +24,7 @@ export declare class ConfigurationChief {
|
|
|
24
24
|
additionalWorkspaces: Set<string>;
|
|
25
25
|
workspaceDirs: string[];
|
|
26
26
|
workspaces: Workspace[];
|
|
27
|
+
localWorkspaces: Set<string>;
|
|
27
28
|
resolvedConfigFilePath?: string;
|
|
28
29
|
constructor({ cwd, isProduction }: ConfigurationManagerOptions);
|
|
29
30
|
init(): Promise<void>;
|
|
@@ -50,6 +50,7 @@ export class ConfigurationChief {
|
|
|
50
50
|
additionalWorkspaces = new Set();
|
|
51
51
|
workspaceDirs = [];
|
|
52
52
|
workspaces = [];
|
|
53
|
+
localWorkspaces = new Set();
|
|
53
54
|
resolvedConfigFilePath;
|
|
54
55
|
constructor({ cwd, isProduction }) {
|
|
55
56
|
this.cwd = cwd;
|
|
@@ -152,6 +153,7 @@ export class ConfigurationChief {
|
|
|
152
153
|
this.ignoreWorkspaces = this.getIgnoredWorkspaces();
|
|
153
154
|
this.manifestWorkspaces = await this.getManifestWorkspaces();
|
|
154
155
|
this.additionalWorkspaces = await this.getAdditionalWorkspaces();
|
|
156
|
+
this.localWorkspaces = new Set(compact(this.getEnabledWorkspaces().map(w => w.pkgName)));
|
|
155
157
|
this.workspaces = this.getEnabledWorkspaces();
|
|
156
158
|
this.workspaceDirs = this.getAllWorkspaces()
|
|
157
159
|
.sort(byPathDepth)
|
package/dist/DependencyDeputy.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isBuiltin } from 'node:module';
|
|
2
|
+
import { fromBinary, isBinary } from './binaries/util.js';
|
|
2
3
|
import { IGNORE_DEFINITELY_TYPED, IGNORED_DEPENDENCIES, IGNORED_GLOBAL_BINARIES } from './constants.js';
|
|
3
4
|
import { isDefinitelyTyped, getDefinitelyTypedFor, getPackageFromDefinitelyTyped } from './util/modules.js';
|
|
4
5
|
export class DependencyDeputy {
|
|
@@ -72,6 +73,24 @@ export class DependencyDeputy {
|
|
|
72
73
|
return true;
|
|
73
74
|
const workspaceNames = this.isStrict ? [workspace.name] : [workspace.name, ...[...workspace.ancestors].reverse()];
|
|
74
75
|
const closestWorkspaceName = workspaceNames.find(name => this.isInDependencies(name, packageName));
|
|
76
|
+
if (isBinary(packageName)) {
|
|
77
|
+
const binaryName = fromBinary(packageName);
|
|
78
|
+
if (IGNORED_GLOBAL_BINARIES.includes(binaryName))
|
|
79
|
+
return true;
|
|
80
|
+
if (this.getWorkspaceManifest(workspace.name)?.ignoreBinaries.includes(binaryName))
|
|
81
|
+
return true;
|
|
82
|
+
for (const name of workspaceNames) {
|
|
83
|
+
const binaries = this.getInstalledBinaries(name);
|
|
84
|
+
if (binaries?.has(binaryName)) {
|
|
85
|
+
const dependencies = binaries.get(binaryName);
|
|
86
|
+
if (dependencies?.size) {
|
|
87
|
+
dependencies.forEach(dependency => this.addReferencedDependency(name, dependency));
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
75
94
|
if (this.getWorkspaceManifest(workspace.name)?.ignoreDependencies.includes(packageName))
|
|
76
95
|
return true;
|
|
77
96
|
const typesPackageName = !isDefinitelyTyped(packageName) && getDefinitelyTypedFor(packageName);
|
|
@@ -81,20 +100,6 @@ export class DependencyDeputy {
|
|
|
81
100
|
closestWorkspaceNameForTypes && this.addReferencedDependency(closestWorkspaceNameForTypes, typesPackageName);
|
|
82
101
|
return true;
|
|
83
102
|
}
|
|
84
|
-
if (IGNORED_GLOBAL_BINARIES.includes(packageName))
|
|
85
|
-
return true;
|
|
86
|
-
if (this.getWorkspaceManifest(workspace.name)?.ignoreBinaries.includes(packageName))
|
|
87
|
-
return true;
|
|
88
|
-
for (const name of workspaceNames) {
|
|
89
|
-
const binaries = this.getInstalledBinaries(name);
|
|
90
|
-
if (binaries?.has(packageName)) {
|
|
91
|
-
const dependencies = binaries.get(packageName);
|
|
92
|
-
if (dependencies?.size) {
|
|
93
|
-
dependencies.forEach(dependency => this.addReferencedDependency(name, dependency));
|
|
94
|
-
return true;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
103
|
return false;
|
|
99
104
|
}
|
|
100
105
|
isInDependencies(workspaceName, packageName) {
|
package/dist/WorkspaceWorker.js
CHANGED
|
@@ -207,7 +207,7 @@ export class WorkspaceWorker {
|
|
|
207
207
|
if (!pluginConfig)
|
|
208
208
|
continue;
|
|
209
209
|
const patterns = this.getConfigurationFilePatterns(pluginName);
|
|
210
|
-
const configFilePaths = await _pureGlob({ patterns, cwd, ignore });
|
|
210
|
+
const configFilePaths = await _pureGlob({ patterns, cwd, ignore, gitignore: false });
|
|
211
211
|
debugLogArray(`Found ${plugin.NAME} config file paths`, configFilePaths);
|
|
212
212
|
if (configFilePaths.length === 0)
|
|
213
213
|
continue;
|
|
@@ -3,6 +3,7 @@ import parseArgs from 'minimist';
|
|
|
3
3
|
import { debugLogObject } from '../util/debug.js';
|
|
4
4
|
import * as FallbackResolver from './resolvers/fallback.js';
|
|
5
5
|
import * as KnownResolvers from './resolvers/index.js';
|
|
6
|
+
import { stripBinaryPath, toBinary } from './util.js';
|
|
6
7
|
const spawningBinaries = ['cross-env', 'dotenv'];
|
|
7
8
|
export const getBinariesFromScript = (script, { cwd, manifest, knownGlobalsOnly = false }) => {
|
|
8
9
|
if (!script)
|
|
@@ -11,7 +12,7 @@ export const getBinariesFromScript = (script, { cwd, manifest, knownGlobalsOnly
|
|
|
11
12
|
const getBinariesFromNodes = (nodes) => nodes.flatMap(node => {
|
|
12
13
|
switch (node.type) {
|
|
13
14
|
case 'Command': {
|
|
14
|
-
const binary = node.name?.text;
|
|
15
|
+
const binary = node.name?.text ? stripBinaryPath(node.name.text) : node.name?.text;
|
|
15
16
|
const commandExpansions = node.prefix?.flatMap(prefix => prefix.expansion?.filter(expansion => expansion.type === 'CommandExpansion') ?? []) ?? [];
|
|
16
17
|
if (commandExpansions.length > 0) {
|
|
17
18
|
return commandExpansions.flatMap(expansion => getBinariesFromNodes(expansion.commandAST.commands)) ?? [];
|
|
@@ -35,7 +36,7 @@ export const getBinariesFromScript = (script, { cwd, manifest, knownGlobalsOnly
|
|
|
35
36
|
const [spawnedBinary] = parsedArgs._;
|
|
36
37
|
if (spawnedBinary) {
|
|
37
38
|
const restArgs = args.slice(args.indexOf(spawnedBinary));
|
|
38
|
-
return [binary, ...fromArgs(restArgs)];
|
|
39
|
+
return [toBinary(binary), ...fromArgs(restArgs)];
|
|
39
40
|
}
|
|
40
41
|
else {
|
|
41
42
|
return [];
|
package/dist/binaries/index.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { compact } from '../util/array.js';
|
|
2
|
-
import { getPackageNameFromModuleSpecifier
|
|
2
|
+
import { getPackageNameFromModuleSpecifier } from '../util/modules.js';
|
|
3
3
|
import { isInternal } from '../util/path.js';
|
|
4
4
|
import { timerify } from '../util/Performance.js';
|
|
5
5
|
import { getBinariesFromScript } from './bash-parser.js';
|
|
6
|
+
import { isBinary } from './util.js';
|
|
6
7
|
const defaultCwd = process.cwd();
|
|
7
8
|
const getDependenciesFromScripts = (npmScripts, options = {}) => {
|
|
8
9
|
const { cwd = defaultCwd, manifest = {}, knownGlobalsOnly = false } = options;
|
|
9
10
|
const scripts = typeof npmScripts === 'string' ? [npmScripts] : [...npmScripts];
|
|
10
11
|
const results = scripts.flatMap(script => getBinariesFromScript(script, { cwd, manifest, knownGlobalsOnly }));
|
|
11
12
|
return compact(results.map(identifier => {
|
|
12
|
-
if (isInternal(identifier))
|
|
13
|
+
if (isBinary(identifier) || isInternal(identifier))
|
|
13
14
|
return identifier;
|
|
14
|
-
const packageName = getPackageNameFromModuleSpecifier(
|
|
15
|
+
const packageName = getPackageNameFromModuleSpecifier(identifier);
|
|
15
16
|
if (!packageName.startsWith('.'))
|
|
16
17
|
return packageName;
|
|
17
18
|
}));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import parseArgs from 'minimist';
|
|
2
2
|
import { compact } from '../../util/array.js';
|
|
3
|
-
import { tryResolveFilePaths } from '
|
|
3
|
+
import { toBinary, tryResolveFilePaths } from '../util.js';
|
|
4
4
|
const withPositional = parsed => [parsed._[0], parsed.require].flat();
|
|
5
5
|
const withoutPositional = parsed => [parsed.require].flat();
|
|
6
6
|
const argFilters = {
|
|
@@ -16,5 +16,5 @@ export const resolve = (binary, args, { cwd }) => {
|
|
|
16
16
|
const parsed = parseArgs(args, { string: ['r'], alias: { require: ['r', 'loader'] }, boolean: ['quiet', 'verbose'] });
|
|
17
17
|
const argFilter = argFilters[binary] ?? argFilters.default;
|
|
18
18
|
const filteredArgs = compact(argFilter(parsed));
|
|
19
|
-
return [binary, ...tryResolveFilePaths(cwd, filteredArgs)];
|
|
19
|
+
return [toBinary(binary), ...tryResolveFilePaths(cwd, filteredArgs)];
|
|
20
20
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import parseArgs from 'minimist';
|
|
2
|
-
import { tryResolveFilePath, tryResolveFilePaths } from '
|
|
2
|
+
import { tryResolveFilePath, tryResolveFilePaths } from '../util.js';
|
|
3
3
|
export const resolve = (binary, args, { cwd }) => {
|
|
4
4
|
const parsed = parseArgs(args, { string: ['r'], alias: { require: ['r', 'loader', 'experimental-loader'] } });
|
|
5
5
|
return [...tryResolveFilePath(cwd, parsed._[0]), ...tryResolveFilePaths(cwd, [parsed.require].flat())];
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import parseArgs from 'minimist';
|
|
2
|
+
import { fromBinary } from '../util.js';
|
|
2
3
|
export const resolve = (binary, args, { fromArgs }) => {
|
|
3
4
|
const parsed = parseArgs(args, { '--': true, stopEarly: true, boolean: ['yes', 'no'], alias: { yes: 'y', no: 'n' } });
|
|
4
|
-
const
|
|
5
|
+
const leftParsed = fromArgs(parsed._);
|
|
6
|
+
const left = parsed.yes ? leftParsed.slice(1) : leftParsed;
|
|
7
|
+
const packageName = left[0] ? [fromBinary(left[0])] : [];
|
|
5
8
|
const right = parsed['--'] ? fromArgs(parsed['--']) : [];
|
|
6
|
-
return [...
|
|
9
|
+
return [...packageName, ...left.slice(1), ...right];
|
|
7
10
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import parseArgs from 'minimist';
|
|
2
|
+
import { toBinary } from '../util.js';
|
|
2
3
|
const commands = [
|
|
3
4
|
'add',
|
|
4
5
|
'dlx',
|
|
@@ -33,13 +34,13 @@ const commands = [
|
|
|
33
34
|
't',
|
|
34
35
|
'tst',
|
|
35
36
|
];
|
|
36
|
-
export const resolve = (
|
|
37
|
+
export const resolve = (_binary, args, { manifest }) => {
|
|
37
38
|
const scripts = manifest.scripts ? Object.keys(manifest.scripts) : [];
|
|
38
39
|
const parsed = parseArgs(args, {});
|
|
39
|
-
const [command,
|
|
40
|
+
const [command, binary] = parsed._;
|
|
40
41
|
if (scripts.includes(command) || commands.includes(command))
|
|
41
42
|
return [];
|
|
42
43
|
if (command === 'exec')
|
|
43
|
-
return [
|
|
44
|
-
return command ? [command] : [];
|
|
44
|
+
return [toBinary(binary)];
|
|
45
|
+
return command ? [toBinary(command)] : [];
|
|
45
46
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import parseArgs from 'minimist';
|
|
2
|
-
import { tryResolveFilePaths } from '
|
|
2
|
+
import { toBinary, tryResolveFilePaths } from '../util.js';
|
|
3
3
|
export const resolve = (binary, args, { cwd, fromArgs }) => {
|
|
4
4
|
const safeArgs = args.filter(arg => arg !== '--watch');
|
|
5
5
|
const parsed = parseArgs(safeArgs, { alias: { plugin: 'p' } });
|
|
6
6
|
const watchers = parsed.watch ? fromArgs(Object.values(parsed.watch)) : [];
|
|
7
7
|
const plugins = parsed.plugin ? tryResolveFilePaths(cwd, [parsed.plugin].flat()) : [];
|
|
8
8
|
const configPlugins = parsed.configPlugin ? tryResolveFilePaths(cwd, [parsed.configPlugin].flat()) : [];
|
|
9
|
-
return [binary, ...watchers, ...plugins, ...configPlugins];
|
|
9
|
+
return [toBinary(binary), ...watchers, ...plugins, ...configPlugins];
|
|
10
10
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import parseArgs from 'minimist';
|
|
2
|
+
import { toBinary } from '../util.js';
|
|
2
3
|
const commands = [
|
|
3
4
|
'add',
|
|
4
5
|
'bin',
|
|
@@ -30,17 +31,17 @@ const commands = [
|
|
|
30
31
|
'workspace',
|
|
31
32
|
'workspaces',
|
|
32
33
|
];
|
|
33
|
-
export const resolve = (
|
|
34
|
+
export const resolve = (_binary, args, { manifest, fromArgs }) => {
|
|
34
35
|
const scripts = manifest.scripts ? Object.keys(manifest.scripts) : [];
|
|
35
36
|
const parsed = parseArgs(args, {});
|
|
36
|
-
const [command,
|
|
37
|
+
const [command, binary] = parsed._;
|
|
37
38
|
if (scripts.includes(command) || commands.includes(command))
|
|
38
39
|
return [];
|
|
39
|
-
if (command === 'run' && scripts.includes(
|
|
40
|
+
if (command === 'run' && scripts.includes(binary))
|
|
40
41
|
return [];
|
|
41
42
|
if (command === 'run' || command === 'exec')
|
|
42
|
-
return [
|
|
43
|
+
return [toBinary(binary)];
|
|
43
44
|
if (command === 'node')
|
|
44
45
|
return fromArgs(parsed._);
|
|
45
|
-
return command ? [command] : [];
|
|
46
|
+
return command ? [toBinary(command)] : [];
|
|
46
47
|
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const tryResolveFilePath: (cwd: string, specifier: string, fallback?: string) => string[];
|
|
2
|
+
export declare const tryResolveFilePaths: (cwd: string, specifiers: string[]) => string[];
|
|
3
|
+
export declare const toBinary: (specifier: string) => string;
|
|
4
|
+
export declare const fromBinary: (specifier: string) => string;
|
|
5
|
+
export declare const isBinary: (specifier: string) => boolean;
|
|
6
|
+
export declare const stripBinaryPath: (command: string) => string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { isInNodeModules, join } from '../util/path.js';
|
|
2
|
+
import { _tryResolve } from '../util/require.js';
|
|
3
|
+
export const tryResolveFilePath = (cwd, specifier, fallback) => {
|
|
4
|
+
if (specifier) {
|
|
5
|
+
const filePath = join(cwd, specifier);
|
|
6
|
+
if (!isInNodeModules(filePath)) {
|
|
7
|
+
const resolvedFilePath = _tryResolve(filePath, cwd);
|
|
8
|
+
if (resolvedFilePath)
|
|
9
|
+
return [resolvedFilePath];
|
|
10
|
+
}
|
|
11
|
+
return fallback ? [stripNodeModulesFromPath(fallback)] : [];
|
|
12
|
+
}
|
|
13
|
+
return [];
|
|
14
|
+
};
|
|
15
|
+
export const tryResolveFilePaths = (cwd, specifiers) => specifiers.flatMap(specifier => tryResolveFilePath(cwd, specifier, specifier));
|
|
16
|
+
export const toBinary = (specifier) => specifier.replace(/^(bin:)?/, 'bin:');
|
|
17
|
+
export const fromBinary = (specifier) => specifier.replace(/^(bin:)?/, '');
|
|
18
|
+
export const isBinary = (specifier) => specifier.startsWith('bin:');
|
|
19
|
+
const stripNodeModulesFromPath = (command) => command.replace(/^(\.\/)?node_modules\//, '');
|
|
20
|
+
export const stripBinaryPath = (command) => stripNodeModulesFromPath(command)
|
|
21
|
+
.replace(/^(\.bin\/)/, '')
|
|
22
|
+
.replace(/\$\(npm bin\)\/(\w+)/, '$1')
|
|
23
|
+
.replace(/(\S+)@.*/, '$1');
|
package/dist/index.js
CHANGED
|
@@ -183,15 +183,8 @@ export const main = async (unresolvedConfiguration) => {
|
|
|
183
183
|
exportedSymbols.set(filePath, exported);
|
|
184
184
|
for (const [specifierFilePath, importItems] of internal.entries()) {
|
|
185
185
|
const packageName = getPackageNameFromModuleSpecifier(importItems.specifier);
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
if (importedWorkspace === workspace) {
|
|
189
|
-
principal.addEntryPath(specifierFilePath);
|
|
190
|
-
}
|
|
191
|
-
else {
|
|
192
|
-
external.add(importItems.specifier);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
186
|
+
if (chief.localWorkspaces.has(packageName))
|
|
187
|
+
external.add(packageName);
|
|
195
188
|
if (!importedSymbols.has(specifierFilePath)) {
|
|
196
189
|
importedSymbols.set(specifierFilePath, importItems);
|
|
197
190
|
}
|
|
@@ -48,7 +48,7 @@ export const getDependenciesDeep = async (configFilePath, dependencies = new Set
|
|
|
48
48
|
return dependencies;
|
|
49
49
|
};
|
|
50
50
|
const resolvePackageName = (namespace, pluginName) => {
|
|
51
|
-
return pluginName.includes(namespace)
|
|
51
|
+
return pluginName.includes(namespace + '-')
|
|
52
52
|
? pluginName
|
|
53
53
|
: pluginName.startsWith('@')
|
|
54
54
|
? pluginName.includes('/')
|
|
@@ -60,16 +60,17 @@ export const resolvePluginPackageName = (pluginName) => resolvePackageName('esli
|
|
|
60
60
|
const resolveExtendsSpecifier = (specifier) => {
|
|
61
61
|
if (isInternal(specifier))
|
|
62
62
|
return;
|
|
63
|
-
if (
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
63
|
+
if (/\/eslint-(config|plugin)/.test(specifier))
|
|
64
|
+
return specifier;
|
|
65
|
+
const strippedSpecifier = specifier
|
|
66
|
+
.replace(/(^plugin:|:.+$)/, '')
|
|
67
|
+
.replace(/\/(eslint-)?(recommended.*|strict|all)$/, '');
|
|
68
|
+
if (/eslint-(config|plugin)-/.test(strippedSpecifier))
|
|
69
|
+
return strippedSpecifier;
|
|
70
|
+
const pluginName = getPackageNameFromModuleSpecifier(strippedSpecifier);
|
|
71
|
+
if (pluginName === 'eslint')
|
|
72
|
+
return;
|
|
73
|
+
return resolvePackageName(specifier.startsWith('plugin:') ? 'eslint-plugin' : 'eslint-config', pluginName);
|
|
73
74
|
};
|
|
74
75
|
const getImportPluginDependencies = (settings) => {
|
|
75
76
|
const knownKeys = ['typescript'];
|
package/dist/util/modules.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { PackageJson } from '@npmcli/package-json';
|
|
2
2
|
export declare const getPackageNameFromModuleSpecifier: (moduleSpecifier: string) => string;
|
|
3
3
|
export declare const getPackageNameFromFilePath: (value: string) => string;
|
|
4
|
-
export declare const stripBinary: (command: string) => string;
|
|
5
4
|
export declare const isDefinitelyTyped: (packageName: string) => boolean;
|
|
6
5
|
export declare const getDefinitelyTypedFor: (packageName: string) => string;
|
|
7
6
|
export declare const getPackageFromDefinitelyTyped: (typedDependency: string) => string;
|
package/dist/util/modules.js
CHANGED
|
@@ -11,10 +11,6 @@ export const getPackageNameFromFilePath = (value) => {
|
|
|
11
11
|
return match[match.length - 1];
|
|
12
12
|
return value;
|
|
13
13
|
};
|
|
14
|
-
export const stripBinary = (command) => command
|
|
15
|
-
.replace(/(\.\/)?node_modules\/(\.bin\/)?(\w+)/, '$3')
|
|
16
|
-
.replace(/\$\(npm bin\)\/(\w+)/, '$1')
|
|
17
|
-
.replace(/(\S+)@.*/, '$1');
|
|
18
14
|
export const isDefinitelyTyped = (packageName) => packageName.startsWith('@types/');
|
|
19
15
|
export const getDefinitelyTypedFor = (packageName) => {
|
|
20
16
|
if (isDefinitelyTyped(packageName))
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "2.3.
|
|
1
|
+
export declare const version = "2.3.2";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '2.3.
|
|
1
|
+
export const version = '2.3.2';
|
package/package.json
CHANGED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { isInNodeModules, join } from '../../util/path.js';
|
|
2
|
-
import { _tryResolve } from '../../util/require.js';
|
|
3
|
-
export const tryResolveFilePath = (cwd, specifier, fallback) => {
|
|
4
|
-
if (specifier) {
|
|
5
|
-
const filePath = join(cwd, specifier);
|
|
6
|
-
if (!isInNodeModules(filePath)) {
|
|
7
|
-
const resolvedFilePath = _tryResolve(filePath, cwd);
|
|
8
|
-
if (resolvedFilePath)
|
|
9
|
-
return [resolvedFilePath];
|
|
10
|
-
}
|
|
11
|
-
return fallback ? [fallback] : [];
|
|
12
|
-
}
|
|
13
|
-
return [];
|
|
14
|
-
};
|
|
15
|
-
export const tryResolveFilePaths = (cwd, specifiers) => specifiers.flatMap(specifier => tryResolveFilePath(cwd, specifier, specifier));
|