knip 2.0.0-alpha.1 → 2.0.0-alpha.3
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 +46 -49
- package/dist/cli.js +2 -3
- package/dist/configuration-chief.js +7 -8
- package/dist/constants.js +5 -1
- package/dist/index.js +2 -2
- package/dist/issue-collector.js +2 -2
- package/dist/manifest/helpers.js +3 -3
- package/dist/plugins/eslint/helpers.js +2 -3
- package/dist/plugins/jest/index.d.ts +1 -1
- package/dist/plugins/jest/index.js +6 -7
- package/dist/plugins/mocha/index.d.ts +1 -1
- package/dist/plugins/mocha/index.js +1 -1
- package/dist/plugins/playwright/index.js +1 -1
- package/dist/plugins/storybook/index.js +2 -3
- package/dist/plugins/typedoc/index.js +1 -1
- package/dist/plugins/typedoc/types.d.ts +1 -1
- package/dist/plugins/vitest/index.d.ts +1 -1
- package/dist/plugins/vitest/index.js +1 -1
- package/dist/plugins/webpack/index.js +2 -3
- package/dist/principal-factory.js +3 -4
- package/dist/project-principal.js +4 -5
- package/dist/reporters/codeowners.js +4 -5
- package/dist/reporters/json.js +3 -4
- package/dist/reporters/symbols.js +2 -2
- package/dist/reporters/util.js +3 -3
- package/dist/typescript/SourceFileManager.js +3 -3
- package/dist/typescript/createHosts.js +2 -2
- package/dist/typescript/resolveModuleNames.js +2 -3
- package/dist/util/binaries/resolvers/node.js +2 -3
- package/dist/util/fs.js +4 -4
- package/dist/util/glob.js +4 -5
- package/dist/util/loader.js +2 -2
- package/dist/util/modules.js +2 -2
- package/dist/util/path.d.ts +7 -2
- package/dist/util/path.js +8 -4
- package/dist/util/require.d.ts +1 -1
- package/dist/util/require.js +4 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/workspace-worker.js +2 -2
- package/package.json +12 -11
package/README.md
CHANGED
|
@@ -196,8 +196,8 @@ Use `--exclude` to ignore reports you're not interested in:
|
|
|
196
196
|
|
|
197
197
|
Use `--dependencies` or `--exports` as shortcuts to combine groups of related types.
|
|
198
198
|
|
|
199
|
-
Still not happy with the results? Getting too much output/false positives? The [FAQ][
|
|
200
|
-
an issue and I'm happy to look into it. Also see the next section on how to [ignore][11] certain false positives:
|
|
199
|
+
Still not happy with the results? Getting too much output/false positives? The [FAQ][10] may be useful. Feel free to
|
|
200
|
+
open an issue and I'm happy to look into it. Also see the next section on how to [ignore][11] certain false positives:
|
|
201
201
|
|
|
202
202
|
## Ignore
|
|
203
203
|
|
|
@@ -345,6 +345,14 @@ rest to find which of those dependencies are unused or missing.
|
|
|
345
345
|
Other configuration files use `require` or `import` statements to use dependencies, so they can be analyzed like the
|
|
346
346
|
rest of the source files. These configuration files are also considered `entry` files.
|
|
347
347
|
|
|
348
|
+
For plugins related to test files, it's good to know that the following glob patterns are always included by default:
|
|
349
|
+
|
|
350
|
+
- `**/*.{test,spec}.{js,jsx,ts,tsx,mjs,cjs}`
|
|
351
|
+
- `**/__tests__/**/*.{js,jsx,ts,tsx,mjs,cjs}`
|
|
352
|
+
- `**/test/**/*.{js,jsx,ts,tsx,mjs,cjs}`
|
|
353
|
+
|
|
354
|
+
Files matching these patterns are excluded in [production mode][45].
|
|
355
|
+
|
|
348
356
|
### Disable a plugin
|
|
349
357
|
|
|
350
358
|
In case a plugin causes issues, it can be disabled by using `false` as its value (e.g. `"webpack": false`).
|
|
@@ -440,10 +448,10 @@ Each workspace can also have its own `paths` configured. Note that Knip `paths`
|
|
|
440
448
|
|
|
441
449
|
Knip provides the following built-in reporters:
|
|
442
450
|
|
|
443
|
-
-
|
|
444
|
-
-
|
|
445
|
-
-
|
|
446
|
-
-
|
|
451
|
+
- codeowners
|
|
452
|
+
- compact
|
|
453
|
+
- json
|
|
454
|
+
- symbol
|
|
447
455
|
|
|
448
456
|
The `compact` reporter shows the sorted files first, and then a list of symbols:
|
|
449
457
|
|
|
@@ -470,13 +478,12 @@ type ReporterOptions = {
|
|
|
470
478
|
|
|
471
479
|
The data can then be used to write issues to `stdout`, a JSON or CSV file, or sent to a service.
|
|
472
480
|
|
|
473
|
-
Find more details and ideas in [custom reporters][
|
|
481
|
+
Find more details and ideas in [custom reporters][46].
|
|
474
482
|
|
|
475
|
-
##
|
|
483
|
+
## Public exports
|
|
476
484
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
in libraries can be marked with the JSDoc `@public` tag:
|
|
485
|
+
Sometimes a file that's not an entry file has one or more exports that are public, and should not be reported as unused.
|
|
486
|
+
Such variables and types can be marked with the JSDoc `@public` tag:
|
|
480
487
|
|
|
481
488
|
```js
|
|
482
489
|
/**
|
|
@@ -528,7 +535,7 @@ When unused dependencies are related to dependencies having a Knip [plugin][1],
|
|
|
528
535
|
for that dependency are at custom locations. The default values are at the plugin's documentation, and can be overridden
|
|
529
536
|
to match the custom location(s).
|
|
530
537
|
|
|
531
|
-
When the dependencies don't have a Knip plugin yet, please file an issue or [create a new plugin][
|
|
538
|
+
When the dependencies don't have a Knip plugin yet, please file an issue or [create a new plugin][47].
|
|
532
539
|
|
|
533
540
|
#### Too many unused exports
|
|
534
541
|
|
|
@@ -536,7 +543,7 @@ When the project is a library and the exports are meant to be used by consumers
|
|
|
536
543
|
|
|
537
544
|
1. By default, unused exports of `entry` files are not reported. You could re-export from an existing entry file, or
|
|
538
545
|
add the containing file to the `entry` array in the configuration.
|
|
539
|
-
2. The exported values or types can be marked [using the JSDoc `@public` tag][
|
|
546
|
+
2. The exported values or types can be marked [using the JSDoc `@public` tag][48]
|
|
540
547
|
|
|
541
548
|
### How to start using Knip in CI while having too many issues to sort out?
|
|
542
549
|
|
|
@@ -556,22 +563,23 @@ All of this is hiding problems, so please make sure to plan for fixing them and/
|
|
|
556
563
|
|
|
557
564
|
This table is an ongoing comparison. Based on their docs (please report any mistakes):
|
|
558
565
|
|
|
559
|
-
| Feature
|
|
560
|
-
|
|
|
561
|
-
| Unused files
|
|
562
|
-
| Unused dependencies
|
|
563
|
-
| Unlisted dependencies
|
|
564
|
-
| [Plugins][
|
|
565
|
-
|
|
|
566
|
-
| Unused
|
|
567
|
-
| Unused
|
|
568
|
-
|
|
|
569
|
-
|
|
|
570
|
-
|
|
|
571
|
-
|
|
|
572
|
-
|
|
|
573
|
-
|
|
|
574
|
-
|
|
|
566
|
+
| Feature | **knip** | [depcheck][49] | [unimported][50] | [ts-unused-exports][51] | [ts-prune][52] |
|
|
567
|
+
| :-------------------------------- | :------: | :------------: | :--------------: | :---------------------: | :------------: |
|
|
568
|
+
| Unused files | ✅ | - | ✅ | - | - |
|
|
569
|
+
| Unused dependencies | ✅ | ✅ | ✅ | - | - |
|
|
570
|
+
| Unlisted dependencies | ✅ | ✅ | ✅ | - | - |
|
|
571
|
+
| [Plugins][2] | ✅ | ✅ | ❌ | - | - |
|
|
572
|
+
| [Compilers][3] | ✅ | - | - | - | - |
|
|
573
|
+
| Unused exports | ✅ | - | - | ✅ | ✅ |
|
|
574
|
+
| Unused class members | ✅ | - | - | - | - |
|
|
575
|
+
| Unused enum members | ✅ | - | - | - | - |
|
|
576
|
+
| Duplicate exports | ✅ | - | - | ❌ | ❌ |
|
|
577
|
+
| Search namespaces | ✅ | - | - | ✅ | ❌ |
|
|
578
|
+
| Custom reporters | ✅ | - | - | - | - |
|
|
579
|
+
| JavaScript support | ✅ | ✅ | ✅ | - | - |
|
|
580
|
+
| Configure entry files | ✅ | ❌ | ✅ | ❌ | ❌ |
|
|
581
|
+
| [Support workspaces/monorepos][1] | ✅ | ❌ | ❌ | - | - |
|
|
582
|
+
| ESLint plugin available | - | - | - | ✅ | - |
|
|
575
583
|
|
|
576
584
|
✅ = Supported, ❌ = Not supported, - = Out of scope
|
|
577
585
|
|
|
@@ -591,7 +599,7 @@ The following commands are similar:
|
|
|
591
599
|
unimported
|
|
592
600
|
knip --production --dependencies --include files
|
|
593
601
|
|
|
594
|
-
Also see [production mode][
|
|
602
|
+
Also see [production mode][45].
|
|
595
603
|
|
|
596
604
|
### ts-unused-exports
|
|
597
605
|
|
|
@@ -609,13 +617,6 @@ The following commands are similar:
|
|
|
609
617
|
knip --include exports,types
|
|
610
618
|
knip --exports # Adds unused exports/types in namespaces and unused enum/class members
|
|
611
619
|
|
|
612
|
-
## TypeScript language services
|
|
613
|
-
|
|
614
|
-
TypeScript language services could play a major role in most of the "unused" areas, as they have an overview of the
|
|
615
|
-
project as a whole. This powers things in VS Code like "Find references" or the "Module "./some" declares 'Thing'
|
|
616
|
-
locally, but it is not exported" message. I think features like "duplicate exports" or "custom dependency resolvers" are
|
|
617
|
-
userland territory, much like code linters.
|
|
618
|
-
|
|
619
620
|
## Knip?!
|
|
620
621
|
|
|
621
622
|
Knip is Dutch for a "cut". A Dutch expression is "to be ge**knip**t for something", which means to be perfectly suited
|
|
@@ -665,15 +666,11 @@ for the job. I'm motivated to make knip perfectly suited for the job of cutting
|
|
|
665
666
|
[42]: ./src/plugins/vitest
|
|
666
667
|
[43]: ./src/plugins/webpack
|
|
667
668
|
[44]: #config
|
|
668
|
-
[45]: #
|
|
669
|
-
[46]:
|
|
670
|
-
[47]: #
|
|
671
|
-
[48]: #
|
|
672
|
-
[49]:
|
|
673
|
-
[50]:
|
|
674
|
-
[51]:
|
|
675
|
-
[52]: https://github.com/
|
|
676
|
-
[53]: https://github.com/smeijer/unimported
|
|
677
|
-
[54]: https://github.com/pzavolinsky/ts-unused-exports
|
|
678
|
-
[55]: https://github.com/nadeesha/ts-prune
|
|
679
|
-
[56]: #production-mode
|
|
669
|
+
[45]: #production-mode
|
|
670
|
+
[46]: ./docs/custom-reporters.md
|
|
671
|
+
[47]: #create-a-new-plugin
|
|
672
|
+
[48]: #public-exports
|
|
673
|
+
[49]: https://github.com/depcheck/depcheck
|
|
674
|
+
[50]: https://github.com/smeijer/unimported
|
|
675
|
+
[51]: https://github.com/pzavolinsky/ts-unused-exports
|
|
676
|
+
[52]: https://github.com/nadeesha/ts-prune
|
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import './util/register.js';
|
|
3
|
-
import path from 'node:path';
|
|
4
3
|
import prettyMilliseconds from 'pretty-ms';
|
|
5
4
|
import reporters from './reporters/index.js';
|
|
6
5
|
import parsedArgs, { helpText } from './util/cli-arguments.js';
|
|
7
6
|
import { ConfigurationError } from './util/errors.js';
|
|
8
7
|
import { _load } from './util/loader.js';
|
|
8
|
+
import { cwd, resolve } from './util/path.js';
|
|
9
9
|
import { Performance } from './util/performance.js';
|
|
10
10
|
import { version } from './version.js';
|
|
11
11
|
import { main } from './index.js';
|
|
@@ -18,9 +18,8 @@ if (isVersion) {
|
|
|
18
18
|
console.log(version);
|
|
19
19
|
process.exit(0);
|
|
20
20
|
}
|
|
21
|
-
const cwd = process.cwd();
|
|
22
21
|
const isShowProgress = !isDebug && isNoProgress === false && process.stdout.isTTY && typeof process.stdout.cursorTo === 'function';
|
|
23
|
-
const printReport = reporter in reporters ? reporters[reporter] : await _load(
|
|
22
|
+
const printReport = reporter in reporters ? reporters[reporter] : await _load(resolve(reporter));
|
|
24
23
|
const run = async () => {
|
|
25
24
|
try {
|
|
26
25
|
const perfObserver = new Performance(isObservePerf);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import mapWorkspaces from '@npmcli/map-workspaces';
|
|
3
2
|
import micromatch from 'micromatch';
|
|
4
3
|
import { ConfigurationValidator } from './configuration-validator.js';
|
|
@@ -11,16 +10,16 @@ import { ConfigurationError } from './util/errors.js';
|
|
|
11
10
|
import { findFile, loadJSON } from './util/fs.js';
|
|
12
11
|
import { _dirGlob } from './util/glob.js';
|
|
13
12
|
import { _load } from './util/loader.js';
|
|
14
|
-
import {
|
|
13
|
+
import { join, relative } from './util/path.js';
|
|
15
14
|
import { toCamelCase } from './util/plugin.js';
|
|
16
15
|
import { resolveIncludedIssueTypes } from './util/resolve-included-issue-types.js';
|
|
17
16
|
import { byPathDepth } from './util/workspace.js';
|
|
18
17
|
const { config: rawConfigArg, workspace: rawWorkspaceArg, include = [], exclude = [], dependencies = false, exports = false, } = parsedArgs.values;
|
|
19
18
|
const getDefaultWorkspaceConfig = (extensions) => {
|
|
20
|
-
const
|
|
19
|
+
const exts = [...DEFAULT_EXTENSIONS, ...(extensions ?? [])].map(ext => ext.slice(1)).join(',');
|
|
21
20
|
return {
|
|
22
|
-
entry: [`index.{${
|
|
23
|
-
project: [`**/*.{${
|
|
21
|
+
entry: [`index.{${exts}}!`, `src/index.{${exts}}!`],
|
|
22
|
+
project: [`**/*.{${exts}}!`],
|
|
24
23
|
paths: {},
|
|
25
24
|
ignore: [],
|
|
26
25
|
ignoreBinaries: [],
|
|
@@ -155,7 +154,7 @@ export class ConfigurationChief {
|
|
|
155
154
|
this.workspaceDirs = this.getWorkspaces()
|
|
156
155
|
.sort(byPathDepth)
|
|
157
156
|
.reverse()
|
|
158
|
-
.map(dir =>
|
|
157
|
+
.map(dir => join(this.cwd, dir));
|
|
159
158
|
}
|
|
160
159
|
async getManifestWorkspaces() {
|
|
161
160
|
const workspaces = await mapWorkspaces({
|
|
@@ -165,7 +164,7 @@ export class ConfigurationChief {
|
|
|
165
164
|
});
|
|
166
165
|
const manifestWorkspaces = new Map();
|
|
167
166
|
for (const [pkgName, dir] of workspaces.entries()) {
|
|
168
|
-
manifestWorkspaces.set(
|
|
167
|
+
manifestWorkspaces.set(relative(this.cwd, dir), pkgName);
|
|
169
168
|
}
|
|
170
169
|
return manifestWorkspaces;
|
|
171
170
|
}
|
|
@@ -195,7 +194,7 @@ export class ConfigurationChief {
|
|
|
195
194
|
return workspaces.sort(byPathDepth).map(name => ({
|
|
196
195
|
name,
|
|
197
196
|
pkgName: this.manifestWorkspaces.get(name),
|
|
198
|
-
dir:
|
|
197
|
+
dir: join(this.cwd, name),
|
|
199
198
|
config: this.getConfigForWorkspace(name),
|
|
200
199
|
ancestors: allWorkspaces.reduce(getAncestors(name), []),
|
|
201
200
|
}));
|
package/dist/constants.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
export const ROOT_WORKSPACE_NAME = '.';
|
|
2
2
|
export const KNIP_CONFIG_LOCATIONS = ['knip.json', 'knip.jsonc', '.knip.json', '.knip.jsonc', 'knip.ts', 'knip.js'];
|
|
3
3
|
export const DEFAULT_EXTENSIONS = ['.js', '.mjs', '.cjs', '.jsx', '.ts', '.tsx'];
|
|
4
|
-
export const TEST_FILE_PATTERNS = [
|
|
4
|
+
export const TEST_FILE_PATTERNS = [
|
|
5
|
+
'**/*.{test,spec}.{js,jsx,ts,tsx,mjs,cjs}',
|
|
6
|
+
'**/__tests__/**/*.{js,jsx,ts,tsx,mjs,cjs}',
|
|
7
|
+
'**/test/**/*.{js,jsx,ts,tsx,mjs,cjs}',
|
|
8
|
+
];
|
|
5
9
|
export const IGNORED_GLOBAL_BINARIES = [
|
|
6
10
|
'bun',
|
|
7
11
|
'deno',
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import { ConfigurationChief } from './configuration-chief.js';
|
|
3
2
|
import { ROOT_WORKSPACE_NAME, DEFAULT_EXTENSIONS } from './constants.js';
|
|
4
3
|
import { DependencyDeputy } from './dependency-deputy.js';
|
|
@@ -9,6 +8,7 @@ import { compact } from './util/array.js';
|
|
|
9
8
|
import { debugLogObject, debugLogArray } from './util/debug.js';
|
|
10
9
|
import { findFile, loadJSON, findFileWithExtensions } from './util/fs.js';
|
|
11
10
|
import { _glob } from './util/glob.js';
|
|
11
|
+
import { join } from './util/path.js';
|
|
12
12
|
import { loadTSConfig } from './util/tsconfig-loader.js';
|
|
13
13
|
import { WorkspaceWorker } from './workspace-worker.js';
|
|
14
14
|
export const main = async (unresolvedConfiguration) => {
|
|
@@ -38,7 +38,7 @@ export const main = async (unresolvedConfiguration) => {
|
|
|
38
38
|
continue;
|
|
39
39
|
const { ignoreDependencies } = chief.getConfigForWorkspace(name);
|
|
40
40
|
deputy.addWorkspace({ name, dir, manifestPath, manifest, ignoreDependencies });
|
|
41
|
-
const tsConfigFilePath =
|
|
41
|
+
const tsConfigFilePath = join(dir, tsConfigFile ?? 'tsconfig.json');
|
|
42
42
|
const tsConfig = await loadTSConfig(tsConfigFilePath);
|
|
43
43
|
const principal = factory.getPrincipal({
|
|
44
44
|
cwd: dir,
|
package/dist/issue-collector.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { initReport, initIssues, initCounters } from './issues/initializers.js';
|
|
2
2
|
import { LineRewriter } from './util/log.js';
|
|
3
|
-
import {
|
|
3
|
+
import { relative } from './util/path.js';
|
|
4
4
|
export class IssueCollector {
|
|
5
5
|
report;
|
|
6
6
|
issues;
|
|
@@ -31,7 +31,7 @@ export class IssueCollector {
|
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
33
|
addIssue(issue) {
|
|
34
|
-
const key =
|
|
34
|
+
const key = relative(this.cwd, issue.filePath);
|
|
35
35
|
this.issues[issue.type][key] = this.issues[issue.type][key] ?? {};
|
|
36
36
|
if (!this.issues[issue.type][key][issue.symbol]) {
|
|
37
37
|
this.issues[issue.type][key][issue.symbol] = issue;
|
package/dist/manifest/helpers.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { join } from '../util/path.js';
|
|
2
2
|
import { _require } from '../util/require.js';
|
|
3
3
|
export const getPackageManifest = async (workingDir, packageName, isRoot, cwd) => {
|
|
4
4
|
try {
|
|
5
|
-
return _require(
|
|
5
|
+
return _require(join(workingDir, 'node_modules', packageName, 'package.json'));
|
|
6
6
|
}
|
|
7
7
|
catch (error) {
|
|
8
8
|
if (!isRoot) {
|
|
9
9
|
try {
|
|
10
|
-
return _require(
|
|
10
|
+
return _require(join(cwd, 'node_modules', packageName, 'package.json'));
|
|
11
11
|
}
|
|
12
12
|
catch (error) {
|
|
13
13
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import { compact } from '../../util/array.js';
|
|
3
2
|
import { _load } from '../../util/loader.js';
|
|
4
3
|
import { getPackageName } from '../../util/modules.js';
|
|
5
|
-
import { isAbsolute, isInNodeModules } from '../../util/path.js';
|
|
4
|
+
import { isAbsolute, isInNodeModules, join, dirname } from '../../util/path.js';
|
|
6
5
|
import { _resolve } from '../../util/require.js';
|
|
7
6
|
import { fallback } from './fallback.js';
|
|
8
7
|
const getDependencies = (config) => {
|
|
@@ -36,7 +35,7 @@ export const getDependenciesDeep = async (configFilePath, dependencies = new Set
|
|
|
36
35
|
if (config.extends) {
|
|
37
36
|
for (const extend of [config.extends].flat()) {
|
|
38
37
|
if (extend.startsWith('.') || (isAbsolute(extend) && !isInNodeModules(extend))) {
|
|
39
|
-
const filePath = isAbsolute(extend) ? extend :
|
|
38
|
+
const filePath = isAbsolute(extend) ? extend : join(dirname(configFilePath), extend);
|
|
40
39
|
const extendConfigFilePath = _resolve(filePath);
|
|
41
40
|
addAll(await getDependenciesDeep(extendConfigFilePath, dependencies, options));
|
|
42
41
|
}
|
|
@@ -3,5 +3,5 @@ export declare const NAME = "Jest";
|
|
|
3
3
|
export declare const ENABLERS: string[];
|
|
4
4
|
export declare const isEnabled: IsPluginEnabledCallback;
|
|
5
5
|
export declare const CONFIG_FILE_PATTERNS: string[];
|
|
6
|
-
export declare const ENTRY_FILE_PATTERNS:
|
|
6
|
+
export declare const ENTRY_FILE_PATTERNS: never[];
|
|
7
7
|
export declare const findDependencies: GenericPluginCallback;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import { _load } from '../../util/loader.js';
|
|
3
2
|
import { getPackageName } from '../../util/modules.js';
|
|
4
|
-
import { isAbsolute } from '../../util/path.js';
|
|
3
|
+
import { isAbsolute, join, dirname } from '../../util/path.js';
|
|
5
4
|
import { timerify } from '../../util/performance.js';
|
|
6
5
|
import { hasDependency } from '../../util/plugin.js';
|
|
7
6
|
import { _resolve } from '../../util/require.js';
|
|
@@ -9,14 +8,14 @@ export const NAME = 'Jest';
|
|
|
9
8
|
export const ENABLERS = ['jest'];
|
|
10
9
|
export const isEnabled = ({ dependencies }) => hasDependency(dependencies, ENABLERS);
|
|
11
10
|
export const CONFIG_FILE_PATTERNS = ['jest.config.{js,ts,mjs,cjs,json}'];
|
|
12
|
-
export const ENTRY_FILE_PATTERNS = [
|
|
13
|
-
const
|
|
11
|
+
export const ENTRY_FILE_PATTERNS = [];
|
|
12
|
+
const maybeJoin = (base, id) => (isAbsolute(id) ? id : join(dirname(base), id));
|
|
14
13
|
const resolveExtensibleConfig = async (configFilePath) => {
|
|
15
14
|
const config = await _load(configFilePath);
|
|
16
15
|
if (config?.preset) {
|
|
17
16
|
const { preset } = config;
|
|
18
17
|
if (preset.startsWith('.') || isAbsolute(preset)) {
|
|
19
|
-
const presetConfigPath =
|
|
18
|
+
const presetConfigPath = maybeJoin(configFilePath, preset);
|
|
20
19
|
const presetConfig = await resolveExtensibleConfig(presetConfigPath);
|
|
21
20
|
delete config.preset;
|
|
22
21
|
Object.assign(config, presetConfig);
|
|
@@ -31,9 +30,9 @@ const findJestDependencies = async (configFilePath, { cwd }) => {
|
|
|
31
30
|
const dependencies = [];
|
|
32
31
|
const entryFiles = [];
|
|
33
32
|
const handleEntries = (name) => {
|
|
34
|
-
name = name.includes('<rootDir>') ?
|
|
33
|
+
name = name.includes('<rootDir>') ? join(cwd, name.replace(/^.*<rootDir>/, '')) : name;
|
|
35
34
|
if (name.startsWith('.') || isAbsolute(name)) {
|
|
36
|
-
entryFiles.push(_resolve(
|
|
35
|
+
entryFiles.push(_resolve(maybeJoin(configFilePath, name)));
|
|
37
36
|
}
|
|
38
37
|
else {
|
|
39
38
|
dependencies.push(name);
|
|
@@ -3,5 +3,5 @@ export declare const NAME = "Mocha";
|
|
|
3
3
|
export declare const ENABLERS: string[];
|
|
4
4
|
export declare const isEnabled: IsPluginEnabledCallback;
|
|
5
5
|
export declare const CONFIG_FILE_PATTERNS: string[];
|
|
6
|
-
export declare const ENTRY_FILE_PATTERNS:
|
|
6
|
+
export declare const ENTRY_FILE_PATTERNS: never[];
|
|
7
7
|
export declare const findDependencies: GenericPluginCallback;
|
|
@@ -6,7 +6,7 @@ export const NAME = 'Mocha';
|
|
|
6
6
|
export const ENABLERS = ['mocha'];
|
|
7
7
|
export const isEnabled = ({ dependencies }) => hasDependency(dependencies, ENABLERS);
|
|
8
8
|
export const CONFIG_FILE_PATTERNS = ['.mocharc.{js,cjs,json,jsonc,yml,yaml}', 'package.json'];
|
|
9
|
-
export const ENTRY_FILE_PATTERNS = [
|
|
9
|
+
export const ENTRY_FILE_PATTERNS = [];
|
|
10
10
|
const findMochaDependencies = async (configFilePath, { manifest }) => {
|
|
11
11
|
const config = configFilePath.endsWith('package.json') ? manifest.mocha : await _load(configFilePath);
|
|
12
12
|
if (config) {
|
|
@@ -2,4 +2,4 @@ import { hasDependency } from '../../util/plugin.js';
|
|
|
2
2
|
export const NAME = 'Playwright';
|
|
3
3
|
export const ENABLERS = ['@playwright/test'];
|
|
4
4
|
export const isEnabled = ({ dependencies }) => hasDependency(dependencies, ENABLERS);
|
|
5
|
-
export const ENTRY_FILE_PATTERNS = ['playwright.config.{js,ts}'
|
|
5
|
+
export const ENTRY_FILE_PATTERNS = ['playwright.config.{js,ts}'];
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import { _load } from '../../util/loader.js';
|
|
3
2
|
import { getPackageName } from '../../util/modules.js';
|
|
4
|
-
import { isAbsolute } from '../../util/path.js';
|
|
3
|
+
import { dirname, isAbsolute, join } from '../../util/path.js';
|
|
5
4
|
import { timerify } from '../../util/performance.js';
|
|
6
5
|
import { hasDependency } from '../../util/plugin.js';
|
|
7
6
|
import { _resolve } from '../../util/require.js';
|
|
@@ -20,7 +19,7 @@ const findStorybookDependencies = async (configFilePath) => {
|
|
|
20
19
|
config.addons?.forEach(addon => {
|
|
21
20
|
const name = typeof addon === 'string' ? addon : addon.name;
|
|
22
21
|
if (name.startsWith('.')) {
|
|
23
|
-
entryFiles.push(_resolve(
|
|
22
|
+
entryFiles.push(_resolve(join(dirname(configFilePath), name)));
|
|
24
23
|
}
|
|
25
24
|
else if (isAbsolute(name)) {
|
|
26
25
|
entryFiles.push(configFilePath);
|
|
@@ -12,6 +12,6 @@ export const CONFIG_FILE_PATTERNS = [
|
|
|
12
12
|
];
|
|
13
13
|
const findPluginDependencies = async (configFilePath) => {
|
|
14
14
|
const config = await _load(configFilePath);
|
|
15
|
-
return config?.
|
|
15
|
+
return config?.plugin ?? [];
|
|
16
16
|
};
|
|
17
17
|
export const findDependencies = timerify(findPluginDependencies);
|
|
@@ -3,5 +3,5 @@ export declare const NAME = "Vitest";
|
|
|
3
3
|
export declare const ENABLERS: string[];
|
|
4
4
|
export declare const isEnabled: IsPluginEnabledCallback;
|
|
5
5
|
export declare const CONFIG_FILE_PATTERNS: string[];
|
|
6
|
-
export declare const ENTRY_FILE_PATTERNS:
|
|
6
|
+
export declare const ENTRY_FILE_PATTERNS: never[];
|
|
7
7
|
export declare const findDependencies: GenericPluginCallback;
|
|
@@ -7,7 +7,7 @@ export const NAME = 'Vitest';
|
|
|
7
7
|
export const ENABLERS = ['vitest'];
|
|
8
8
|
export const isEnabled = ({ dependencies }) => hasDependency(dependencies, ENABLERS);
|
|
9
9
|
export const CONFIG_FILE_PATTERNS = ['vitest.config.ts', 'vite.config.ts'];
|
|
10
|
-
export const ENTRY_FILE_PATTERNS = [
|
|
10
|
+
export const ENTRY_FILE_PATTERNS = [];
|
|
11
11
|
const findVitestDependencies = async (configFilePath) => {
|
|
12
12
|
const config = await _load(configFilePath);
|
|
13
13
|
if (!config || !config.test)
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import { compact } from '../../util/array.js';
|
|
3
2
|
import { _load } from '../../util/loader.js';
|
|
4
3
|
import { getPackageName } from '../../util/modules.js';
|
|
5
|
-
import { isAbsolute } from '../../util/path.js';
|
|
4
|
+
import { isAbsolute, join } from '../../util/path.js';
|
|
6
5
|
import { timerify } from '../../util/performance.js';
|
|
7
6
|
import { hasDependency } from '../../util/plugin.js';
|
|
8
7
|
import { getDependenciesFromConfig } from '../babel/index.js';
|
|
@@ -62,7 +61,7 @@ const findWebpackDependencies = async (configFilePath, { cwd, manifest, isProduc
|
|
|
62
61
|
? cfg.entry
|
|
63
62
|
: Object.values(cfg.entry).map(entry => (typeof entry === 'string' ? entry : entry.filename));
|
|
64
63
|
entries.forEach(entry => {
|
|
65
|
-
entryFiles.add(isAbsolute(entry) ? entry :
|
|
64
|
+
entryFiles.add(isAbsolute(entry) ? entry : join(cwd, entry));
|
|
66
65
|
});
|
|
67
66
|
}
|
|
68
67
|
return dependencies;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import { ProjectPrincipal } from './project-principal.js';
|
|
3
|
-
import { isAbsolute } from './util/path.js';
|
|
2
|
+
import { join, isAbsolute } from './util/path.js';
|
|
4
3
|
const mergePaths = (cwd, compilerOptions = {}, paths = {}) => {
|
|
5
4
|
const mergedPaths = { ...compilerOptions.paths, ...paths };
|
|
6
5
|
const baseUrl = compilerOptions.baseUrl ?? '.';
|
|
7
6
|
compilerOptions.paths = Object.keys(mergedPaths).reduce((paths, key) => {
|
|
8
|
-
paths[key] = mergedPaths[key].map(entry => (isAbsolute(entry) ? entry :
|
|
7
|
+
paths[key] = mergedPaths[key].map(entry => (isAbsolute(entry) ? entry : join(cwd, baseUrl, entry)));
|
|
9
8
|
return paths;
|
|
10
9
|
}, {});
|
|
11
10
|
return compilerOptions;
|
|
@@ -40,7 +39,7 @@ export class PrincipalFactory {
|
|
|
40
39
|
const principal = new ProjectPrincipal({ cwd, compilerOptions, report, compilers });
|
|
41
40
|
const paths = new Set(Object.keys(compilerOptions?.paths ?? {}));
|
|
42
41
|
const isDefaultBaseUrl = hasDefaultBaseUrl(compilerOptions);
|
|
43
|
-
compilerOptions.baseUrl =
|
|
42
|
+
compilerOptions.baseUrl = join(cwd, compilerOptions.baseUrl ?? '.');
|
|
44
43
|
this.principals.add({ principal, cwds: new Set([cwd]), paths, isDefaultBaseUrl });
|
|
45
44
|
return principal;
|
|
46
45
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import ts from 'typescript';
|
|
3
2
|
import { DEFAULT_EXTENSIONS } from './constants.js';
|
|
4
3
|
import { IGNORED_FILE_EXTENSIONS } from './constants.js';
|
|
5
4
|
import { getImportsAndExports } from './typescript/ast-walker.js';
|
|
6
5
|
import { createHosts } from './typescript/createHosts.js';
|
|
7
|
-
import { isInNodeModules } from './util/path.js';
|
|
6
|
+
import { extname, isInNodeModules } from './util/path.js';
|
|
8
7
|
import { timerify } from './util/performance.js';
|
|
9
8
|
const baseCompilerOptions = {
|
|
10
9
|
allowJs: true,
|
|
@@ -64,7 +63,7 @@ export class ProjectPrincipal {
|
|
|
64
63
|
typeChecker();
|
|
65
64
|
}
|
|
66
65
|
hasAcceptedExtension(filePath) {
|
|
67
|
-
return this.extensions.has(
|
|
66
|
+
return this.extensions.has(extname(filePath));
|
|
68
67
|
}
|
|
69
68
|
addEntryPath(filePath) {
|
|
70
69
|
if (!isInNodeModules(filePath) && this.hasAcceptedExtension(filePath)) {
|
|
@@ -86,7 +85,7 @@ export class ProjectPrincipal {
|
|
|
86
85
|
async runAsyncCompilers() {
|
|
87
86
|
const add = timerify(this.backend.fileManager.compileAndAddSourceFile.bind(this.backend.fileManager));
|
|
88
87
|
const extensions = Array.from(this.asyncCompilers.keys());
|
|
89
|
-
const files = Array.from(this.projectPaths).filter(filePath => extensions.includes(
|
|
88
|
+
const files = Array.from(this.projectPaths).filter(filePath => extensions.includes(extname(filePath)));
|
|
90
89
|
for (const filePath of files) {
|
|
91
90
|
await add(filePath);
|
|
92
91
|
}
|
|
@@ -129,7 +128,7 @@ export class ProjectPrincipal {
|
|
|
129
128
|
externalImports.add(specifier);
|
|
130
129
|
}
|
|
131
130
|
else {
|
|
132
|
-
const ext =
|
|
131
|
+
const ext = extname(specifier);
|
|
133
132
|
if (!ext || (ext !== '.json' && !IGNORED_FILE_EXTENSIONS.includes(ext))) {
|
|
134
133
|
finalUnresolvedImports.add(specifier);
|
|
135
134
|
}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import { OwnershipEngine } from '@snyk/github-codeowners/dist/lib/ownership/index.js';
|
|
3
2
|
import chalk from 'chalk';
|
|
4
|
-
import { isAbsolute,
|
|
3
|
+
import { isAbsolute, relative, resolve } from '../util/path.js';
|
|
5
4
|
import { getTitle, logTitle, logIssueLine } from './util.js';
|
|
6
5
|
const logIssueSet = (issues) => {
|
|
7
6
|
issues
|
|
8
7
|
.sort((a, b) => (a.owner < b.owner ? -1 : 1))
|
|
9
|
-
.forEach(issue => console.log(chalk.cyan(issue.owner), isAbsolute(issue.symbol) ?
|
|
8
|
+
.forEach(issue => console.log(chalk.cyan(issue.owner), isAbsolute(issue.symbol) ? relative(issue.symbol) : issue.symbol));
|
|
10
9
|
};
|
|
11
10
|
const logIssueRecord = (issues) => {
|
|
12
11
|
const sortedByFilePath = issues.sort((a, b) => (a.owner < b.owner ? -1 : 1));
|
|
@@ -20,13 +19,13 @@ export default ({ report, issues, options }) => {
|
|
|
20
19
|
catch (error) {
|
|
21
20
|
console.error(error);
|
|
22
21
|
}
|
|
23
|
-
const codeownersFilePath =
|
|
22
|
+
const codeownersFilePath = resolve(opts.path ?? '.github/CODEOWNERS');
|
|
24
23
|
const codeownersEngine = OwnershipEngine.FromCodeownersFile(codeownersFilePath);
|
|
25
24
|
const reportMultipleGroups = Object.values(report).filter(Boolean).length > 1;
|
|
26
25
|
const [dependenciesOwner = '[no-owner]'] = codeownersEngine.calcFileOwnership('package.json');
|
|
27
26
|
const fallbackOwner = dependenciesOwner;
|
|
28
27
|
let totalIssues = 0;
|
|
29
|
-
const calcFileOwnership = (filePath) => codeownersEngine.calcFileOwnership(
|
|
28
|
+
const calcFileOwnership = (filePath) => codeownersEngine.calcFileOwnership(relative(filePath))[0] ?? fallbackOwner;
|
|
30
29
|
const addOwner = (issue) => ({ ...issue, owner: calcFileOwnership(issue.filePath) });
|
|
31
30
|
for (const [reportType, isReportType] of Object.entries(report)) {
|
|
32
31
|
if (isReportType) {
|
package/dist/reporters/json.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import { OwnershipEngine } from '@snyk/github-codeowners/dist/lib/ownership/index.js';
|
|
3
2
|
import { isFile } from '../util/fs.js';
|
|
4
|
-
import {
|
|
3
|
+
import { relative, resolve } from '../util/path.js';
|
|
5
4
|
const mergeTypes = (type) => type === 'exports' || type === 'nsExports' ? 'exports' : type === 'types' || type === 'nsTypes' ? 'types' : type;
|
|
6
5
|
export default async ({ report, issues, options }) => {
|
|
7
6
|
let opts = {};
|
|
@@ -12,11 +11,11 @@ export default async ({ report, issues, options }) => {
|
|
|
12
11
|
console.error(error);
|
|
13
12
|
}
|
|
14
13
|
const json = {};
|
|
15
|
-
const codeownersFilePath =
|
|
14
|
+
const codeownersFilePath = resolve(opts.codeowners ?? '.github/CODEOWNERS');
|
|
16
15
|
const codeownersEngine = isFile(codeownersFilePath) && OwnershipEngine.FromCodeownersFile(codeownersFilePath);
|
|
17
16
|
const flatten = (issues) => Object.values(issues).map(Object.values).flat();
|
|
18
17
|
const initRow = (filePath) => {
|
|
19
|
-
const file =
|
|
18
|
+
const file = relative(filePath);
|
|
20
19
|
const row = {
|
|
21
20
|
file,
|
|
22
21
|
...(codeownersEngine && { owners: codeownersEngine.calcFileOwnership(file) }),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import EasyTable from 'easy-table';
|
|
2
|
-
import {
|
|
2
|
+
import { relative } from '../util/path.js';
|
|
3
3
|
import { getTitle, logTitle, logIssueSet } from './util.js';
|
|
4
4
|
const TRUNCATE_WIDTH = 40;
|
|
5
5
|
const truncate = (text) => (text.length > TRUNCATE_WIDTH ? text.slice(0, TRUNCATE_WIDTH - 3) + '...' : text);
|
|
@@ -9,7 +9,7 @@ const logIssueRecord = (issues) => {
|
|
|
9
9
|
table.cell('symbol', issue.symbols ? truncate(issue.symbols.join(', ')) : issue.symbol);
|
|
10
10
|
issue.parentSymbol && table.cell('parentSymbol', issue.parentSymbol);
|
|
11
11
|
issue.symbolType && table.cell('symbolType', issue.symbolType);
|
|
12
|
-
table.cell('filePath',
|
|
12
|
+
table.cell('filePath', relative(issue.filePath));
|
|
13
13
|
table.newRow();
|
|
14
14
|
});
|
|
15
15
|
console.log(table.sort(['filePath', 'parentSymbol', 'symbol']).print().trim());
|
package/dist/reporters/util.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { ISSUE_TYPE_TITLE } from '../constants.js';
|
|
3
|
-
import { isAbsolute,
|
|
3
|
+
import { isAbsolute, relative } from '../util/path.js';
|
|
4
4
|
export const getTitle = (reportType) => {
|
|
5
5
|
return ISSUE_TYPE_TITLE[reportType];
|
|
6
6
|
};
|
|
@@ -8,8 +8,8 @@ export const logTitle = (title, count) => console.log(`${chalk.bold.yellow.under
|
|
|
8
8
|
export const logIssueLine = ({ owner, filePath, symbols, parentSymbol }) => {
|
|
9
9
|
const symbol = symbols ? `: ${symbols.join(', ')}` : '';
|
|
10
10
|
const parent = parentSymbol ? ` (${parentSymbol})` : '';
|
|
11
|
-
console.log(`${owner ? `${chalk.cyan(owner)} ` : ''}${
|
|
11
|
+
console.log(`${owner ? `${chalk.cyan(owner)} ` : ''}${relative(filePath)}${symbol}${parent}`);
|
|
12
12
|
};
|
|
13
13
|
export const logIssueSet = (issues) => {
|
|
14
|
-
issues.sort().forEach(value => console.log(isAbsolute(value) ?
|
|
14
|
+
issues.sort().forEach(value => console.log(isAbsolute(value) ? relative(value) : value));
|
|
15
15
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import ts from 'typescript';
|
|
3
2
|
import { debugLog } from '../util/debug.js';
|
|
3
|
+
import { extname } from '../util/path.js';
|
|
4
4
|
export class SourceFileManager {
|
|
5
5
|
sourceFileCache = new Map();
|
|
6
6
|
snapshotCache = new Map();
|
|
@@ -21,7 +21,7 @@ export class SourceFileManager {
|
|
|
21
21
|
const contents = ts.sys.readFile(filePath);
|
|
22
22
|
if (typeof contents !== 'string')
|
|
23
23
|
throw new Error(`Unable to read ${filePath}`);
|
|
24
|
-
const ext =
|
|
24
|
+
const ext = extname(filePath);
|
|
25
25
|
const compiler = this.syncCompilers?.get(ext);
|
|
26
26
|
const compiled = compiler ? compiler(contents) : contents;
|
|
27
27
|
if (compiler)
|
|
@@ -42,7 +42,7 @@ export class SourceFileManager {
|
|
|
42
42
|
const contents = ts.sys.readFile(filePath);
|
|
43
43
|
if (typeof contents !== 'string')
|
|
44
44
|
throw new Error(`Unable to read ${filePath}`);
|
|
45
|
-
const ext =
|
|
45
|
+
const ext = extname(filePath);
|
|
46
46
|
const compiler = this.asyncCompilers?.get(ext);
|
|
47
47
|
if (compiler) {
|
|
48
48
|
const compiled = await compiler(contents);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { EOL } from 'node:os';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import ts from 'typescript';
|
|
4
|
-
import {
|
|
4
|
+
import { _require } from '../util/require.js';
|
|
5
5
|
import { createCustomModuleResolver } from './resolveModuleNames.js';
|
|
6
6
|
import { SourceFileManager } from './SourceFileManager.js';
|
|
7
7
|
import { createCustomSys } from './sys.js';
|
|
8
8
|
const cwd = process.cwd();
|
|
9
|
-
const libLocation = path.dirname(
|
|
9
|
+
const libLocation = path.dirname(_require.resolve('typescript', { paths: [cwd] }));
|
|
10
10
|
const fileManager = new SourceFileManager();
|
|
11
11
|
export const createHosts = ({ cwd, compilerOptions, entryPaths, compilers }) => {
|
|
12
12
|
fileManager.installCompilers(compilers);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import ts from 'typescript';
|
|
3
|
-
import { isAbsolute } from '../util/path.js';
|
|
2
|
+
import { isAbsolute, join } from '../util/path.js';
|
|
4
3
|
import { ensureRealFilePath, isVirtualFilePath } from './utils.js';
|
|
5
4
|
export function createCustomModuleResolver(customSys, compilerOptions, virtualFileExtensions) {
|
|
6
5
|
function resolveModuleNames(moduleNames, containingFile) {
|
|
@@ -9,7 +8,7 @@ export function createCustomModuleResolver(customSys, compilerOptions, virtualFi
|
|
|
9
8
|
function resolveModuleName(name, containingFile) {
|
|
10
9
|
const tsResolvedModule = ts.resolveModuleName(name, containingFile, compilerOptions, ts.sys).resolvedModule;
|
|
11
10
|
if (tsResolvedModule && !isAbsolute(tsResolvedModule?.resolvedFileName)) {
|
|
12
|
-
tsResolvedModule.resolvedFileName =
|
|
11
|
+
tsResolvedModule.resolvedFileName = join(customSys.getCurrentDirectory(), tsResolvedModule.resolvedFileName);
|
|
13
12
|
}
|
|
14
13
|
if (virtualFileExtensions.length === 0)
|
|
15
14
|
return tsResolvedModule;
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import parseArgs from 'minimist';
|
|
3
|
-
import { isInNodeModules } from '../../path.js';
|
|
2
|
+
import { isInNodeModules, join } from '../../path.js';
|
|
4
3
|
import { tryResolve } from '../../require.js';
|
|
5
4
|
const tryResolveFilePath = (cwd, specifier, fallback) => {
|
|
6
5
|
if (specifier) {
|
|
7
|
-
const filePath =
|
|
6
|
+
const filePath = join(cwd, specifier);
|
|
8
7
|
if (!isInNodeModules(filePath)) {
|
|
9
8
|
const resolvedFilePath = tryResolve(filePath);
|
|
10
9
|
if (resolvedFilePath)
|
package/dist/util/fs.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { statSync } from 'node:fs';
|
|
2
2
|
import { readFile } from 'node:fs/promises';
|
|
3
|
-
import path from 'node:path';
|
|
4
3
|
import stripJsonComments from 'strip-json-comments';
|
|
5
4
|
import { LoaderError } from './errors.js';
|
|
5
|
+
import { join } from './path.js';
|
|
6
6
|
export const isFile = (filePath) => {
|
|
7
7
|
const stat = statSync(filePath, { throwIfNoEntry: false });
|
|
8
8
|
return stat !== undefined && stat.isFile();
|
|
9
9
|
};
|
|
10
10
|
export const findFile = (workingDir, fileName) => {
|
|
11
|
-
const filePath =
|
|
11
|
+
const filePath = join(workingDir, fileName);
|
|
12
12
|
return isFile(filePath) ? filePath : undefined;
|
|
13
13
|
};
|
|
14
14
|
export const loadJSON = async (filePath) => {
|
|
@@ -21,11 +21,11 @@ export const loadJSON = async (filePath) => {
|
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
23
|
export const findFileWithExtensions = (cwd, specifier, extensions) => {
|
|
24
|
-
const filePath =
|
|
24
|
+
const filePath = join(cwd, specifier);
|
|
25
25
|
if (isFile(filePath))
|
|
26
26
|
return filePath;
|
|
27
27
|
for (const ext of extensions) {
|
|
28
|
-
const filePath =
|
|
28
|
+
const filePath = join(cwd, specifier + ext);
|
|
29
29
|
if (isFile(filePath))
|
|
30
30
|
return filePath;
|
|
31
31
|
}
|
package/dist/util/glob.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import fg from 'fast-glob';
|
|
3
2
|
import { globby } from 'globby';
|
|
4
3
|
import memoize from 'nano-memoize';
|
|
5
4
|
import { ROOT_WORKSPACE_NAME } from '../constants.js';
|
|
6
5
|
import { compact } from './array.js';
|
|
7
6
|
import { debugLogObject } from './debug.js';
|
|
8
|
-
import {
|
|
7
|
+
import { join, relative } from './path.js';
|
|
9
8
|
import { timerify } from './performance.js';
|
|
10
9
|
export const prependDirToPattern = (workingDir, pattern) => {
|
|
11
10
|
if (pattern.startsWith('!'))
|
|
12
|
-
return '!' +
|
|
13
|
-
return
|
|
11
|
+
return '!' + join(workingDir, pattern.slice(1));
|
|
12
|
+
return join(workingDir, pattern);
|
|
14
13
|
};
|
|
15
14
|
export const negate = (pattern) => pattern.replace(/^!?/, '!');
|
|
16
15
|
export const hasProductionSuffix = (pattern) => pattern.endsWith('!');
|
|
@@ -18,7 +17,7 @@ export const hasNoProductionSuffix = (pattern) => !pattern.endsWith('!');
|
|
|
18
17
|
const removeProductionSuffix = (pattern) => pattern.replace(/!$/, '');
|
|
19
18
|
const negatedLast = (pattern) => (pattern.startsWith('!') ? 1 : -1);
|
|
20
19
|
const glob = async ({ cwd, workingDir = cwd, patterns, ignore = [], gitignore = true }) => {
|
|
21
|
-
const relativePath =
|
|
20
|
+
const relativePath = relative(cwd, workingDir);
|
|
22
21
|
const prepend = (pattern) => prependDirToPattern(relativePath, pattern);
|
|
23
22
|
const globPatterns = compact([patterns].flat().map(prepend).map(removeProductionSuffix)).sort(negatedLast);
|
|
24
23
|
const ignorePatterns = compact([...ignore, '**/node_modules/**']);
|
package/dist/util/loader.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
|
-
import path from 'node:path';
|
|
3
2
|
import { pathToFileURL } from 'node:url';
|
|
4
3
|
import yaml from 'js-yaml';
|
|
5
4
|
import { LoaderError } from './errors.js';
|
|
6
5
|
import { loadJSON } from './fs.js';
|
|
6
|
+
import { extname } from './path.js';
|
|
7
7
|
import { timerify } from './performance.js';
|
|
8
8
|
import { jiti } from './register.js';
|
|
9
9
|
const load = async (filePath) => {
|
|
10
10
|
try {
|
|
11
|
-
const ext =
|
|
11
|
+
const ext = extname(filePath);
|
|
12
12
|
if (ext === '.json' || ext === '.jsonc' || /rc$/.test(filePath)) {
|
|
13
13
|
return loadJSON(filePath);
|
|
14
14
|
}
|
package/dist/util/modules.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { isAbsolute,
|
|
1
|
+
import { isAbsolute, toPosix } from './path.js';
|
|
2
2
|
export const getPackageNameFromModuleSpecifier = (moduleSpecifier) => {
|
|
3
3
|
const parts = moduleSpecifier.split('/').slice(0, 2);
|
|
4
4
|
return moduleSpecifier.startsWith('@') ? parts.join('/') : parts[0];
|
|
5
5
|
};
|
|
6
6
|
export const getPackageName = (value) => {
|
|
7
|
-
const match =
|
|
7
|
+
const match = toPosix(value).match(/(?<=node_modules\/)(@[^/]+\/[^/]+|[^/]+)/g);
|
|
8
8
|
if (match)
|
|
9
9
|
return match[match.length - 1];
|
|
10
10
|
if (value.startsWith('@')) {
|
package/dist/util/path.d.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
export declare const
|
|
1
|
+
export declare const toPosix: (value: string) => string;
|
|
2
|
+
export declare const cwd: string;
|
|
3
|
+
export declare const resolve: (...paths: string[]) => string;
|
|
4
|
+
export declare const relative: (from: string, to?: string) => string;
|
|
3
5
|
export declare const isAbsolute: (value: string) => boolean;
|
|
4
6
|
export declare const isInNodeModules: (filePath: string) => boolean;
|
|
7
|
+
export declare const join: (...paths: string[]) => string;
|
|
8
|
+
export declare const extname: (path: string) => string;
|
|
9
|
+
export declare const dirname: (path: string) => string;
|
package/dist/util/path.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
const
|
|
3
|
-
export const
|
|
4
|
-
export const
|
|
5
|
-
export const
|
|
2
|
+
export const toPosix = (value) => value.split(path.sep).join(path.posix.sep);
|
|
3
|
+
export const cwd = toPosix(process.cwd());
|
|
4
|
+
export const resolve = (...paths) => paths.length === 1 ? path.posix.join(cwd, paths[0]) : path.posix.resolve(...paths);
|
|
5
|
+
export const relative = (from, to) => path.posix.relative(to ? toPosix(from) : cwd, toPosix(to ?? from));
|
|
6
|
+
export const isAbsolute = (value) => value.startsWith('/') || /^[A-Z]:(\/|\\)/.test(value);
|
|
6
7
|
export const isInNodeModules = (filePath) => filePath.includes('node_modules');
|
|
8
|
+
export const join = path.posix.join;
|
|
9
|
+
export const extname = path.posix.extname;
|
|
10
|
+
export const dirname = path.posix.dirname;
|
package/dist/util/require.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
export declare const tryResolve: (specifier: string) => string | undefined;
|
|
3
3
|
export declare const _require: NodeRequire;
|
|
4
|
-
export declare const _resolve:
|
|
4
|
+
export declare const _resolve: (specifier: string) => string;
|
package/dist/util/require.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';
|
|
2
|
+
import { toPosix } from './path.js';
|
|
2
3
|
import { timerify } from './performance.js';
|
|
3
4
|
const require = createRequire(process.cwd());
|
|
5
|
+
const resolve = (specifier) => toPosix(require.resolve(specifier));
|
|
4
6
|
export const tryResolve = (specifier) => {
|
|
5
7
|
try {
|
|
6
|
-
return
|
|
8
|
+
return resolve(specifier);
|
|
7
9
|
}
|
|
8
10
|
catch (error) {
|
|
9
11
|
}
|
|
10
12
|
};
|
|
11
13
|
export const _require = timerify(require);
|
|
12
|
-
export const _resolve = timerify(
|
|
14
|
+
export const _resolve = timerify(resolve);
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "2.0.0-alpha.
|
|
1
|
+
export declare const version = "2.0.0-alpha.3";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '2.0.0-alpha.
|
|
1
|
+
export const version = '2.0.0-alpha.3';
|
package/dist/workspace-worker.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import path from 'node:path';
|
|
2
1
|
import { ROOT_WORKSPACE_NAME, TEST_FILE_PATTERNS } from './constants.js';
|
|
3
2
|
import * as npm from './manifest/index.js';
|
|
4
3
|
import * as plugins from './plugins/index.js';
|
|
5
4
|
import { debugLogArray, debugLogObject } from './util/debug.js';
|
|
6
5
|
import { _pureGlob, negate, hasProductionSuffix, hasNoProductionSuffix, prependDirToPattern } from './util/glob.js';
|
|
6
|
+
import { join } from './util/path.js';
|
|
7
7
|
const negatedTestFilePatterns = TEST_FILE_PATTERNS.map(negate);
|
|
8
8
|
export class WorkspaceWorker {
|
|
9
9
|
name;
|
|
@@ -61,7 +61,7 @@ export class WorkspaceWorker {
|
|
|
61
61
|
dir: this.dir,
|
|
62
62
|
cwd: this.rootWorkspaceDir,
|
|
63
63
|
});
|
|
64
|
-
const filePath =
|
|
64
|
+
const filePath = join(this.dir, 'package.json');
|
|
65
65
|
dependencies.forEach(dependency => this.referencedDependencies.add([filePath, dependency]));
|
|
66
66
|
entryFiles.forEach(entryFile => this.entryFiles.add(entryFile));
|
|
67
67
|
this.peerDependencies = peerDependencies;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "knip",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.3",
|
|
4
4
|
"description": "Find unused files, dependencies and exports in your TypeScript and JavaScript projects",
|
|
5
5
|
"homepage": "https://github.com/webpro/knip",
|
|
6
6
|
"repository": "github:webpro/knip",
|
|
@@ -19,17 +19,18 @@
|
|
|
19
19
|
"scripts": {
|
|
20
20
|
"knip": "node ./dist/cli.js",
|
|
21
21
|
"knip:production": "node ./dist/cli.js --production --strict",
|
|
22
|
-
"lint": "eslint src",
|
|
23
|
-
"lint:fix": "eslint src --fix",
|
|
24
|
-
"format": "prettier scripts src
|
|
25
|
-
"test": "globstar -- node --loader tsx --test \"
|
|
22
|
+
"lint": "eslint src tests --ignore",
|
|
23
|
+
"lint:fix": "eslint src tests --fix",
|
|
24
|
+
"format": "prettier scripts src tests --with-node-modules --write --config .prettierrc",
|
|
25
|
+
"test": "globstar -- node --loader tsx --test \"tests/**/*.test.ts\"",
|
|
26
26
|
"watch": "tsc --watch",
|
|
27
|
-
"
|
|
27
|
+
"_prebuild": "rm -rf dist",
|
|
28
28
|
"build": "tsc",
|
|
29
29
|
"docs": "npm run docs:cli && npm run docs:plugins && npm run docs:format",
|
|
30
30
|
"docs:cli": "tsx ./scripts/update-cli-usage-in-readme.ts",
|
|
31
31
|
"docs:plugins": "tsx ./scripts/generate-plugin-docs.ts",
|
|
32
32
|
"docs:format": "remark README.md docs/*.md src/plugins/*/README.md -o",
|
|
33
|
+
"qa": "npm run lint && npm run build && npm run knip && npm run knip:production && npm test",
|
|
33
34
|
"release": "release-it",
|
|
34
35
|
"create-plugin": "tsx ./scripts/create-new-plugin.ts"
|
|
35
36
|
},
|
|
@@ -57,24 +58,24 @@
|
|
|
57
58
|
"zod": "^3.20.6"
|
|
58
59
|
},
|
|
59
60
|
"devDependencies": {
|
|
60
|
-
"@jest/types": "29.
|
|
61
|
+
"@jest/types": "29.5.0",
|
|
61
62
|
"@npmcli/package-json": "3.0.0",
|
|
62
63
|
"@release-it/bumper": "4.0.2",
|
|
63
64
|
"@types/eslint": "8.21.1",
|
|
64
65
|
"@types/js-yaml": "4.0.5",
|
|
65
66
|
"@types/micromatch": "4.0.2",
|
|
66
67
|
"@types/minimist": "1.2.2",
|
|
67
|
-
"@types/node": "18.14.
|
|
68
|
+
"@types/node": "18.14.6",
|
|
68
69
|
"@types/npmcli__map-workspaces": "3.0.0",
|
|
69
70
|
"@types/webpack": "5.28.0",
|
|
70
|
-
"@typescript-eslint/eslint-plugin": "5.54.
|
|
71
|
-
"@typescript-eslint/parser": "5.54.
|
|
71
|
+
"@typescript-eslint/eslint-plugin": "5.54.1",
|
|
72
|
+
"@typescript-eslint/parser": "5.54.1",
|
|
72
73
|
"eslint": "8.35.0",
|
|
73
74
|
"eslint-import-resolver-typescript": "3.5.3",
|
|
74
75
|
"eslint-plugin-import": "2.27.5",
|
|
75
76
|
"globstar": "1.0.0",
|
|
76
77
|
"prettier": "2.8.4",
|
|
77
|
-
"release-it": "^15.
|
|
78
|
+
"release-it": "^15.7.0",
|
|
78
79
|
"remark-cli": "11.0.0",
|
|
79
80
|
"remark-preset-webpro": "0.0.1",
|
|
80
81
|
"tsx": "3.12.3",
|