knip 3.5.0 → 3.6.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/dist/ConfigurationChief.js +3 -2
- package/dist/ConfigurationValidator.d.ts +16 -16
- package/dist/ConfigurationValidator.js +5 -4
- package/dist/DependencyDeputy.d.ts +10 -8
- package/dist/DependencyDeputy.js +67 -25
- package/dist/IssueCollector.js +2 -5
- package/dist/ProjectPrincipal.js +5 -3
- package/dist/WorkspaceWorker.js +2 -2
- package/dist/constants.js +1 -0
- package/dist/index.js +24 -32
- package/dist/plugins/_template/index.js +2 -4
- package/dist/plugins/astro/index.js +1 -1
- package/dist/plugins/ava/index.js +4 -6
- package/dist/plugins/babel/index.js +2 -3
- package/dist/plugins/commitizen/index.js +2 -3
- package/dist/plugins/commitlint/index.js +2 -3
- package/dist/plugins/eslint/helpers.js +2 -2
- package/dist/plugins/eslint/index.js +2 -1
- package/dist/plugins/github-actions/index.js +2 -3
- package/dist/plugins/graphql-codegen/index.js +2 -4
- package/dist/plugins/husky/index.js +2 -3
- package/dist/plugins/jest/index.js +4 -4
- package/dist/plugins/lefthook/index.js +5 -5
- package/dist/plugins/lint-staged/index.js +4 -6
- package/dist/plugins/mocha/index.js +2 -3
- package/dist/plugins/node-test-runner/index.js +1 -5
- package/dist/plugins/npm-package-json-lint/index.js +2 -3
- package/dist/plugins/nx/index.js +2 -3
- package/dist/plugins/postcss/index.js +2 -3
- package/dist/plugins/prettier/index.js +2 -3
- package/dist/plugins/release-it/index.js +4 -6
- package/dist/plugins/remark/index.js +2 -3
- package/dist/plugins/semantic-release/index.js +2 -3
- package/dist/plugins/stylelint/index.js +2 -4
- package/dist/plugins/typedoc/index.js +3 -2
- package/dist/types/config.d.ts +2 -2
- package/dist/types/imports.d.ts +1 -1
- package/dist/types/issues.d.ts +1 -1
- package/dist/types/workspace.d.ts +2 -2
- package/dist/typescript/getImportsAndExports.js +5 -4
- package/dist/util/compilers.d.ts +4 -4
- package/dist/util/modules.d.ts +1 -1
- package/dist/util/modules.js +2 -2
- package/dist/util/path.d.ts +1 -0
- package/dist/util/path.js +1 -0
- package/dist/util/plugin.d.ts +1 -0
- package/dist/util/plugin.js +1 -0
- package/dist/util/regex.d.ts +4 -0
- package/dist/util/regex.js +4 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +7 -7
- package/schema.json +4 -4
|
@@ -17,6 +17,7 @@ import { _load } from './util/loader.js';
|
|
|
17
17
|
import { getKeysByValue } from './util/object.js';
|
|
18
18
|
import { join, relative, toPosix } from './util/path.js';
|
|
19
19
|
import { normalizePluginConfig, toCamelCase } from './util/plugin.js';
|
|
20
|
+
import { toRegexOrString } from './util/regex.js';
|
|
20
21
|
import { _require } from './util/require.js';
|
|
21
22
|
import { unwrapFunction } from './util/unwrap-function.js';
|
|
22
23
|
import { byPathDepth } from './util/workspace.js';
|
|
@@ -131,9 +132,9 @@ export class ConfigurationChief {
|
|
|
131
132
|
const include = rawConfig.include ?? defaultConfig.include;
|
|
132
133
|
const exclude = rawConfig.exclude ?? defaultConfig.exclude;
|
|
133
134
|
const ignore = arrayify(rawConfig.ignore ?? defaultConfig.ignore);
|
|
134
|
-
const ignoreBinaries = rawConfig.ignoreBinaries ?? [];
|
|
135
|
+
const ignoreBinaries = (rawConfig.ignoreBinaries ?? []).map(toRegexOrString);
|
|
136
|
+
const ignoreDependencies = (rawConfig.ignoreDependencies ?? []).map(toRegexOrString);
|
|
135
137
|
const ignoreExportsUsedInFile = rawConfig.ignoreExportsUsedInFile ?? false;
|
|
136
|
-
const ignoreDependencies = rawConfig.ignoreDependencies ?? [];
|
|
137
138
|
const ignoreWorkspaces = rawConfig.ignoreWorkspaces ?? defaultConfig.ignoreWorkspaces;
|
|
138
139
|
const isIncludeEntryExports = rawConfig.includeEntryExports ?? this.isIncludeEntryExports;
|
|
139
140
|
const { syncCompilers, asyncCompilers } = rawConfig;
|
|
@@ -19,9 +19,9 @@ export declare const ConfigurationValidator: z.ZodObject<{
|
|
|
19
19
|
project: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
|
|
20
20
|
paths: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>>;
|
|
21
21
|
ignore: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
|
|
22
|
-
ignoreBinaries: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
22
|
+
ignoreBinaries: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodType<RegExp, z.ZodTypeDef, RegExp>]>, "many">>;
|
|
23
|
+
ignoreDependencies: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodType<RegExp, z.ZodTypeDef, RegExp>]>, "many">>;
|
|
23
24
|
ignoreExportsUsedInFile: z.ZodOptional<z.ZodUnion<[z.ZodBoolean, z.ZodRecord<z.ZodUnion<[z.ZodLiteral<"class">, z.ZodLiteral<"enum">, z.ZodLiteral<"function">, z.ZodLiteral<"interface">, z.ZodLiteral<"member">, z.ZodLiteral<"type">]>, z.ZodBoolean>]>>;
|
|
24
|
-
ignoreDependencies: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
25
25
|
ignoreWorkspaces: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
26
26
|
includeEntryExports: z.ZodOptional<z.ZodBoolean>;
|
|
27
27
|
compilers: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodFunction<z.ZodTuple<[z.ZodString], z.ZodUnknown>, z.ZodString>, z.ZodFunction<z.ZodTuple<[z.ZodString], z.ZodUnknown>, z.ZodPromise<z.ZodString>>]>>>;
|
|
@@ -33,8 +33,8 @@ export declare const ConfigurationValidator: z.ZodObject<{
|
|
|
33
33
|
project: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
|
|
34
34
|
paths: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>>;
|
|
35
35
|
ignore: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
|
|
36
|
-
ignoreBinaries: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
37
|
-
ignoreDependencies: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
36
|
+
ignoreBinaries: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodType<RegExp, z.ZodTypeDef, RegExp>]>, "many">>;
|
|
37
|
+
ignoreDependencies: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodType<RegExp, z.ZodTypeDef, RegExp>]>, "many">>;
|
|
38
38
|
includeEntryExports: z.ZodOptional<z.ZodBoolean>;
|
|
39
39
|
astro: z.ZodOptional<z.ZodUnion<[z.ZodBoolean, z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>, z.ZodObject<{
|
|
40
40
|
config: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
|
|
@@ -613,8 +613,8 @@ export declare const ConfigurationValidator: z.ZodObject<{
|
|
|
613
613
|
project?: string | string[] | undefined;
|
|
614
614
|
paths?: Record<string, string[]> | undefined;
|
|
615
615
|
ignore?: string | string[] | undefined;
|
|
616
|
-
ignoreBinaries?: string[] | undefined;
|
|
617
|
-
ignoreDependencies?: string[] | undefined;
|
|
616
|
+
ignoreBinaries?: (string | RegExp)[] | undefined;
|
|
617
|
+
ignoreDependencies?: (string | RegExp)[] | undefined;
|
|
618
618
|
includeEntryExports?: boolean | undefined;
|
|
619
619
|
astro?: string | boolean | string[] | {
|
|
620
620
|
config?: string | string[] | undefined;
|
|
@@ -841,8 +841,8 @@ export declare const ConfigurationValidator: z.ZodObject<{
|
|
|
841
841
|
project?: string | string[] | undefined;
|
|
842
842
|
paths?: Record<string, string[]> | undefined;
|
|
843
843
|
ignore?: string | string[] | undefined;
|
|
844
|
-
ignoreBinaries?: string[] | undefined;
|
|
845
|
-
ignoreDependencies?: string[] | undefined;
|
|
844
|
+
ignoreBinaries?: (string | RegExp)[] | undefined;
|
|
845
|
+
ignoreDependencies?: (string | RegExp)[] | undefined;
|
|
846
846
|
includeEntryExports?: boolean | undefined;
|
|
847
847
|
astro?: string | boolean | string[] | {
|
|
848
848
|
config?: string | string[] | undefined;
|
|
@@ -1644,9 +1644,9 @@ export declare const ConfigurationValidator: z.ZodObject<{
|
|
|
1644
1644
|
project?: string | string[] | undefined;
|
|
1645
1645
|
paths?: Record<string, string[]> | undefined;
|
|
1646
1646
|
ignore?: string | string[] | undefined;
|
|
1647
|
-
ignoreBinaries?: string[] | undefined;
|
|
1647
|
+
ignoreBinaries?: (string | RegExp)[] | undefined;
|
|
1648
|
+
ignoreDependencies?: (string | RegExp)[] | undefined;
|
|
1648
1649
|
ignoreExportsUsedInFile?: boolean | Partial<Record<"function" | "type" | "enum" | "class" | "interface" | "member", boolean>> | undefined;
|
|
1649
|
-
ignoreDependencies?: string[] | undefined;
|
|
1650
1650
|
ignoreWorkspaces?: string[] | undefined;
|
|
1651
1651
|
includeEntryExports?: boolean | undefined;
|
|
1652
1652
|
compilers?: Record<string, ((args_0: string, ...args_1: unknown[]) => string) | ((args_0: string, ...args_1: unknown[]) => Promise<string>)> | undefined;
|
|
@@ -1658,8 +1658,8 @@ export declare const ConfigurationValidator: z.ZodObject<{
|
|
|
1658
1658
|
project?: string | string[] | undefined;
|
|
1659
1659
|
paths?: Record<string, string[]> | undefined;
|
|
1660
1660
|
ignore?: string | string[] | undefined;
|
|
1661
|
-
ignoreBinaries?: string[] | undefined;
|
|
1662
|
-
ignoreDependencies?: string[] | undefined;
|
|
1661
|
+
ignoreBinaries?: (string | RegExp)[] | undefined;
|
|
1662
|
+
ignoreDependencies?: (string | RegExp)[] | undefined;
|
|
1663
1663
|
includeEntryExports?: boolean | undefined;
|
|
1664
1664
|
astro?: string | boolean | string[] | {
|
|
1665
1665
|
config?: string | string[] | undefined;
|
|
@@ -2109,9 +2109,9 @@ export declare const ConfigurationValidator: z.ZodObject<{
|
|
|
2109
2109
|
project?: string | string[] | undefined;
|
|
2110
2110
|
paths?: Record<string, string[]> | undefined;
|
|
2111
2111
|
ignore?: string | string[] | undefined;
|
|
2112
|
-
ignoreBinaries?: string[] | undefined;
|
|
2112
|
+
ignoreBinaries?: (string | RegExp)[] | undefined;
|
|
2113
|
+
ignoreDependencies?: (string | RegExp)[] | undefined;
|
|
2113
2114
|
ignoreExportsUsedInFile?: boolean | Partial<Record<"function" | "type" | "enum" | "class" | "interface" | "member", boolean>> | undefined;
|
|
2114
|
-
ignoreDependencies?: string[] | undefined;
|
|
2115
2115
|
ignoreWorkspaces?: string[] | undefined;
|
|
2116
2116
|
includeEntryExports?: boolean | undefined;
|
|
2117
2117
|
compilers?: Record<string, ((args_0: string, ...args_1: unknown[]) => string) | ((args_0: string, ...args_1: unknown[]) => Promise<string>)> | undefined;
|
|
@@ -2123,8 +2123,8 @@ export declare const ConfigurationValidator: z.ZodObject<{
|
|
|
2123
2123
|
project?: string | string[] | undefined;
|
|
2124
2124
|
paths?: Record<string, string[]> | undefined;
|
|
2125
2125
|
ignore?: string | string[] | undefined;
|
|
2126
|
-
ignoreBinaries?: string[] | undefined;
|
|
2127
|
-
ignoreDependencies?: string[] | undefined;
|
|
2126
|
+
ignoreBinaries?: (string | RegExp)[] | undefined;
|
|
2127
|
+
ignoreDependencies?: (string | RegExp)[] | undefined;
|
|
2128
2128
|
includeEntryExports?: boolean | undefined;
|
|
2129
2129
|
astro?: string | boolean | string[] | {
|
|
2130
2130
|
config?: string | string[] | undefined;
|
|
@@ -5,6 +5,7 @@ const syncCompilerSchema = z.function().args(z.string()).returns(z.string());
|
|
|
5
5
|
const asyncCompilerSchema = z.function().args(z.string()).returns(z.promise(z.string()));
|
|
6
6
|
const compilerSchema = z.union([syncCompilerSchema, asyncCompilerSchema]);
|
|
7
7
|
const compilersSchema = z.record(z.string(), compilerSchema);
|
|
8
|
+
const stringOrRegexSchema = z.array(z.union([z.string(), z.instanceof(RegExp)]));
|
|
8
9
|
const issueTypeSchema = z.union([
|
|
9
10
|
z.literal('files'),
|
|
10
11
|
z.literal('dependencies'),
|
|
@@ -38,9 +39,9 @@ const rootConfigurationSchema = z.object({
|
|
|
38
39
|
project: globSchema.optional(),
|
|
39
40
|
paths: pathsSchema.optional(),
|
|
40
41
|
ignore: globSchema.optional(),
|
|
41
|
-
ignoreBinaries:
|
|
42
|
+
ignoreBinaries: stringOrRegexSchema.optional(),
|
|
43
|
+
ignoreDependencies: stringOrRegexSchema.optional(),
|
|
42
44
|
ignoreExportsUsedInFile: ignoreExportsUsedInFileSchema.optional(),
|
|
43
|
-
ignoreDependencies: z.array(z.string()).optional(),
|
|
44
45
|
ignoreWorkspaces: z.array(z.string()).optional(),
|
|
45
46
|
includeEntryExports: z.boolean().optional(),
|
|
46
47
|
compilers: compilersSchema.optional(),
|
|
@@ -111,8 +112,8 @@ const baseWorkspaceConfigurationSchema = z.object({
|
|
|
111
112
|
project: globSchema.optional(),
|
|
112
113
|
paths: pathsSchema.optional(),
|
|
113
114
|
ignore: globSchema.optional(),
|
|
114
|
-
ignoreBinaries:
|
|
115
|
-
ignoreDependencies:
|
|
115
|
+
ignoreBinaries: stringOrRegexSchema.optional(),
|
|
116
|
+
ignoreDependencies: stringOrRegexSchema.optional(),
|
|
116
117
|
includeEntryExports: z.boolean().optional(),
|
|
117
118
|
});
|
|
118
119
|
const workspaceConfigurationSchema = baseWorkspaceConfigurationSchema.merge(pluginsSchema.partial());
|
|
@@ -4,9 +4,11 @@ import type { ConfigurationHints, Issue } from './types/issues.js';
|
|
|
4
4
|
import type { WorkspaceManifests, HostDependencies, InstalledBinaries } from './types/workspace.js';
|
|
5
5
|
import type { PackageJson } from '@npmcli/package-json';
|
|
6
6
|
type Options = {
|
|
7
|
+
isProduction: boolean;
|
|
7
8
|
isStrict: boolean;
|
|
8
9
|
};
|
|
9
10
|
export declare class DependencyDeputy {
|
|
11
|
+
isProduction: boolean;
|
|
10
12
|
isStrict: boolean;
|
|
11
13
|
_manifests: WorkspaceManifests;
|
|
12
14
|
referencedDependencies: Map<string, Set<string>>;
|
|
@@ -14,18 +16,18 @@ export declare class DependencyDeputy {
|
|
|
14
16
|
hostDependencies: Map<string, HostDependencies>;
|
|
15
17
|
installedBinaries: Map<string, InstalledBinaries>;
|
|
16
18
|
hasTypesIncluded: Map<string, Set<string>>;
|
|
17
|
-
ignoreBinaries: string[];
|
|
18
|
-
ignoreDependencies: string[];
|
|
19
|
-
constructor({ isStrict }: Options);
|
|
19
|
+
ignoreBinaries: (string | RegExp)[];
|
|
20
|
+
ignoreDependencies: (string | RegExp)[];
|
|
21
|
+
constructor({ isProduction, isStrict }: Options);
|
|
20
22
|
addWorkspace({ name, dir, manifestPath, manifest, ignoreDependencies, ignoreBinaries, }: {
|
|
21
23
|
name: string;
|
|
22
24
|
dir: string;
|
|
23
25
|
manifestPath: string;
|
|
24
26
|
manifest: PackageJson;
|
|
25
|
-
ignoreDependencies: string[];
|
|
26
|
-
ignoreBinaries: string[];
|
|
27
|
+
ignoreDependencies: (string | RegExp)[];
|
|
28
|
+
ignoreBinaries: (string | RegExp)[];
|
|
27
29
|
}): void;
|
|
28
|
-
addIgnored(ignoreBinaries: string[], ignoreDependencies: string[]): void;
|
|
30
|
+
addIgnored(ignoreBinaries: (string | RegExp)[], ignoreDependencies: (string | RegExp)[]): void;
|
|
29
31
|
getWorkspaceManifest(workspaceName: string): {
|
|
30
32
|
workspaceDir: string;
|
|
31
33
|
manifestPath: string;
|
|
@@ -36,8 +38,8 @@ export declare class DependencyDeputy {
|
|
|
36
38
|
optionalDependencies: string[];
|
|
37
39
|
devDependencies: string[];
|
|
38
40
|
allDependencies: string[];
|
|
39
|
-
ignoreDependencies: string[];
|
|
40
|
-
ignoreBinaries: string[];
|
|
41
|
+
ignoreDependencies: (string | RegExp)[];
|
|
42
|
+
ignoreBinaries: (string | RegExp)[];
|
|
41
43
|
} | undefined;
|
|
42
44
|
getProductionDependencies(workspaceName: string): string[];
|
|
43
45
|
getDevDependencies(workspaceName: string): string[];
|
package/dist/DependencyDeputy.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { isBuiltin } from 'node:module';
|
|
2
2
|
import { IGNORE_DEFINITELY_TYPED, IGNORED_DEPENDENCIES, IGNORED_GLOBAL_BINARIES, ROOT_WORKSPACE_NAME, } from './constants.js';
|
|
3
3
|
import { isDefinitelyTyped, getDefinitelyTypedFor, getPackageFromDefinitelyTyped } from './util/modules.js';
|
|
4
|
+
import { hasMatch, hasMatchInArray, hasMatchInSet } from './util/regex.js';
|
|
4
5
|
export class DependencyDeputy {
|
|
6
|
+
isProduction;
|
|
5
7
|
isStrict;
|
|
6
8
|
_manifests = new Map();
|
|
7
9
|
referencedDependencies;
|
|
@@ -11,7 +13,8 @@ export class DependencyDeputy {
|
|
|
11
13
|
hasTypesIncluded;
|
|
12
14
|
ignoreBinaries = [];
|
|
13
15
|
ignoreDependencies = [];
|
|
14
|
-
constructor({ isStrict }) {
|
|
16
|
+
constructor({ isProduction, isStrict }) {
|
|
17
|
+
this.isProduction = isProduction;
|
|
15
18
|
this.isStrict = isStrict;
|
|
16
19
|
this.referencedDependencies = new Map();
|
|
17
20
|
this.referencedBinaries = new Map();
|
|
@@ -122,9 +125,9 @@ export class DependencyDeputy {
|
|
|
122
125
|
else {
|
|
123
126
|
this.addReferencedDependency(workspace.name, packageName);
|
|
124
127
|
}
|
|
125
|
-
if (this.getWorkspaceManifest(workspace.name)?.ignoreDependencies
|
|
128
|
+
if (hasMatch(this.getWorkspaceManifest(workspace.name)?.ignoreDependencies, packageName))
|
|
126
129
|
return true;
|
|
127
|
-
if (this.ignoreDependencies
|
|
130
|
+
if (hasMatch(this.ignoreDependencies, packageName))
|
|
128
131
|
return true;
|
|
129
132
|
return false;
|
|
130
133
|
}
|
|
@@ -143,9 +146,9 @@ export class DependencyDeputy {
|
|
|
143
146
|
}
|
|
144
147
|
}
|
|
145
148
|
}
|
|
146
|
-
if (this.getWorkspaceManifest(workspace.name)?.ignoreBinaries
|
|
149
|
+
if (hasMatch(this.getWorkspaceManifest(workspace.name)?.ignoreBinaries, binaryName))
|
|
147
150
|
return true;
|
|
148
|
-
if (this.ignoreBinaries
|
|
151
|
+
if (hasMatch(this.ignoreBinaries, binaryName))
|
|
149
152
|
return true;
|
|
150
153
|
return false;
|
|
151
154
|
}
|
|
@@ -166,12 +169,14 @@ export class DependencyDeputy {
|
|
|
166
169
|
const hasTypesIncluded = this.getHasTypesIncluded(workspaceName);
|
|
167
170
|
const ignoreBins = [...IGNORED_GLOBAL_BINARIES, ...this.ignoreBinaries, ...ignoreBinaries];
|
|
168
171
|
const ignoreDeps = [...IGNORED_DEPENDENCIES, ...this.ignoreDependencies, ...ignoreDependencies];
|
|
169
|
-
const isNotIgnoredDependency = (packageName) => !ignoreDeps
|
|
172
|
+
const isNotIgnoredDependency = (packageName) => !hasMatch(ignoreDeps, packageName);
|
|
170
173
|
const isNotIgnoredBinary = (packageName) => {
|
|
171
174
|
if (installedBinaries?.has(packageName)) {
|
|
172
175
|
const binaryNames = installedBinaries.get(packageName);
|
|
173
176
|
if (binaryNames) {
|
|
174
|
-
if (ignoreBins.some(
|
|
177
|
+
if (ignoreBins.some(binaryName => typeof binaryName === 'string'
|
|
178
|
+
? binaryNames.has(binaryName)
|
|
179
|
+
: [...binaryNames].some(n => binaryName.test(n))))
|
|
175
180
|
return false;
|
|
176
181
|
}
|
|
177
182
|
}
|
|
@@ -225,30 +230,56 @@ export class DependencyDeputy {
|
|
|
225
230
|
}
|
|
226
231
|
getConfigurationHints() {
|
|
227
232
|
const configurationHints = new Set();
|
|
228
|
-
const rootIgnoreBinaries =
|
|
229
|
-
const rootIgnoreDependencies =
|
|
233
|
+
const rootIgnoreBinaries = new Map(this.ignoreBinaries.map(key => [key, 0]));
|
|
234
|
+
const rootIgnoreDependencies = new Map(this.ignoreDependencies.map(key => [key, 0]));
|
|
230
235
|
for (const [workspaceName, { ignoreDependencies, ignoreBinaries }] of this._manifests.entries()) {
|
|
231
236
|
const referencedDependencies = this.referencedDependencies.get(workspaceName);
|
|
232
237
|
const referencedBinaries = this.referencedBinaries.get(workspaceName);
|
|
233
238
|
const installedBinaries = this.getInstalledBinaries(workspaceName);
|
|
234
|
-
referencedDependencies?.forEach(pkg =>
|
|
235
|
-
|
|
239
|
+
referencedDependencies?.forEach(pkg => {
|
|
240
|
+
for (const key of rootIgnoreDependencies.keys()) {
|
|
241
|
+
if ((typeof key === 'string' && key === pkg) || (key instanceof RegExp && key.test(pkg))) {
|
|
242
|
+
rootIgnoreDependencies.set(key, rootIgnoreDependencies.get(key) + 1);
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
referencedBinaries?.forEach(binaryName => {
|
|
248
|
+
for (const key of rootIgnoreBinaries.keys()) {
|
|
249
|
+
if ((typeof key === 'string' && key === binaryName) || (key instanceof RegExp && key.test(binaryName))) {
|
|
250
|
+
rootIgnoreBinaries.set(key, rootIgnoreBinaries.get(key) + 1);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
});
|
|
236
255
|
const dependencies = [
|
|
237
256
|
...this.getProductionDependencies(workspaceName),
|
|
238
257
|
...this.getDevDependencies(workspaceName),
|
|
239
258
|
];
|
|
240
259
|
const peerDependencies = this.getPeerDependencies(workspaceName);
|
|
241
|
-
const isReferencedDep = (name) => referencedDependencies?.has(name) && dependencies.includes(name);
|
|
242
|
-
const isReferencedBin = (name) => referencedBinaries?.has(name) && installedBinaries?.has(name);
|
|
243
260
|
ignoreDependencies
|
|
244
|
-
.filter(packageName =>
|
|
245
|
-
(
|
|
246
|
-
|
|
247
|
-
|
|
261
|
+
.filter(packageName => {
|
|
262
|
+
if (hasMatchInArray(IGNORED_DEPENDENCIES, packageName))
|
|
263
|
+
return true;
|
|
264
|
+
if (workspaceName !== ROOT_WORKSPACE_NAME && this.ignoreDependencies.includes(packageName))
|
|
265
|
+
return true;
|
|
266
|
+
const isReferenced = hasMatchInSet(referencedDependencies, packageName);
|
|
267
|
+
const isListed = hasMatchInArray(dependencies, packageName) && !hasMatchInArray(peerDependencies, packageName);
|
|
268
|
+
return isListed && isReferenced;
|
|
269
|
+
})
|
|
270
|
+
.forEach(identifier => {
|
|
271
|
+
configurationHints.add({ workspaceName, identifier, type: 'ignoreDependencies' });
|
|
272
|
+
});
|
|
248
273
|
ignoreBinaries
|
|
249
|
-
.filter(binaryName =>
|
|
250
|
-
(
|
|
251
|
-
|
|
274
|
+
.filter(binaryName => {
|
|
275
|
+
if (hasMatchInArray(IGNORED_GLOBAL_BINARIES, binaryName))
|
|
276
|
+
return true;
|
|
277
|
+
if (workspaceName !== ROOT_WORKSPACE_NAME && this.ignoreBinaries.includes(binaryName))
|
|
278
|
+
return true;
|
|
279
|
+
const isReferenced = hasMatchInSet(referencedBinaries, binaryName);
|
|
280
|
+
const isInstalled = hasMatchInArray(Array.from(installedBinaries?.keys() ?? []), binaryName);
|
|
281
|
+
return isReferenced && isInstalled;
|
|
282
|
+
})
|
|
252
283
|
.forEach(identifier => configurationHints.add({ workspaceName, identifier, type: 'ignoreBinaries' }));
|
|
253
284
|
}
|
|
254
285
|
const installedBinaries = this.getInstalledBinaries(ROOT_WORKSPACE_NAME);
|
|
@@ -257,12 +288,23 @@ export class DependencyDeputy {
|
|
|
257
288
|
...this.getDevDependencies(ROOT_WORKSPACE_NAME),
|
|
258
289
|
];
|
|
259
290
|
const peerDependencies = this.getPeerDependencies(ROOT_WORKSPACE_NAME);
|
|
260
|
-
|
|
261
|
-
.filter(
|
|
291
|
+
Array.from(rootIgnoreBinaries.keys())
|
|
292
|
+
.filter(binaryName => {
|
|
293
|
+
if (hasMatchInArray(IGNORED_GLOBAL_BINARIES, binaryName))
|
|
294
|
+
return true;
|
|
295
|
+
const isReferenced = rootIgnoreBinaries.get(binaryName) !== 0;
|
|
296
|
+
const isInstalled = hasMatchInArray(Array.from(installedBinaries?.keys() ?? []), binaryName);
|
|
297
|
+
return (isReferenced && isInstalled) || (!this.isProduction && !isReferenced && !isInstalled);
|
|
298
|
+
})
|
|
262
299
|
.forEach(identifier => configurationHints.add({ workspaceName: ROOT_WORKSPACE_NAME, identifier, type: 'ignoreBinaries' }));
|
|
263
|
-
|
|
264
|
-
.filter(
|
|
265
|
-
|
|
300
|
+
Array.from(rootIgnoreDependencies.keys())
|
|
301
|
+
.filter(packageName => {
|
|
302
|
+
if (hasMatchInArray(IGNORED_DEPENDENCIES, packageName))
|
|
303
|
+
return true;
|
|
304
|
+
const isReferenced = rootIgnoreDependencies.get(packageName) !== 0;
|
|
305
|
+
const isListed = hasMatchInArray(dependencies, packageName) && !hasMatchInArray(peerDependencies, packageName);
|
|
306
|
+
return (isReferenced && isListed) || (!this.isProduction && !isReferenced && !isListed);
|
|
307
|
+
})
|
|
266
308
|
.forEach(identifier => configurationHints.add({ workspaceName: ROOT_WORKSPACE_NAME, identifier, type: 'ignoreDependencies' }));
|
|
267
309
|
return { configurationHints };
|
|
268
310
|
}
|
package/dist/IssueCollector.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { initIssues, initCounters } from './issues/initializers.js';
|
|
2
2
|
import { relative } from './util/path.js';
|
|
3
|
-
|
|
4
|
-
const objJSON = JSON.stringify(obj);
|
|
5
|
-
return Array.from(set).some(item => JSON.stringify(item) === objJSON);
|
|
6
|
-
}
|
|
3
|
+
const hasHint = (hints, hint) => Array.from(hints).some(item => item.identifier === hint.identifier && item.type === hint.type && item.workspaceName === hint.workspaceName);
|
|
7
4
|
export class IssueCollector {
|
|
8
5
|
cwd;
|
|
9
6
|
rules;
|
|
@@ -44,7 +41,7 @@ export class IssueCollector {
|
|
|
44
41
|
}
|
|
45
42
|
}
|
|
46
43
|
addConfigurationHint(issue) {
|
|
47
|
-
if (!
|
|
44
|
+
if (!hasHint(this.configurationHints, issue)) {
|
|
48
45
|
this.configurationHints.add(issue);
|
|
49
46
|
}
|
|
50
47
|
}
|
package/dist/ProjectPrincipal.js
CHANGED
|
@@ -7,7 +7,8 @@ import { getImportsAndExports } from './typescript/getImportsAndExports.js';
|
|
|
7
7
|
import { createCustomModuleResolver } from './typescript/resolveModuleNames.js';
|
|
8
8
|
import { SourceFileManager } from './typescript/SourceFileManager.js';
|
|
9
9
|
import { compact } from './util/array.js';
|
|
10
|
-
import {
|
|
10
|
+
import { debugLog } from './util/debug.js';
|
|
11
|
+
import { isStartsLikePackageName, sanitizeSpecifier } from './util/modules.js';
|
|
11
12
|
import { dirname, extname, isInNodeModules, join } from './util/path.js';
|
|
12
13
|
import { timerify } from './util/Performance.js';
|
|
13
14
|
const baseCompilerOptions = {
|
|
@@ -145,7 +146,7 @@ export class ProjectPrincipal {
|
|
|
145
146
|
}
|
|
146
147
|
else {
|
|
147
148
|
const sanitizedSpecifier = sanitizeSpecifier(specifier);
|
|
148
|
-
if (
|
|
149
|
+
if (isStartsLikePackageName(sanitizedSpecifier)) {
|
|
149
150
|
external.add(sanitizedSpecifier);
|
|
150
151
|
}
|
|
151
152
|
else {
|
|
@@ -210,7 +211,8 @@ export class ProjectPrincipal {
|
|
|
210
211
|
try {
|
|
211
212
|
return this.backend.lsFindReferences(filePath, pos) ?? [];
|
|
212
213
|
}
|
|
213
|
-
catch {
|
|
214
|
+
catch (error) {
|
|
215
|
+
debugLog('*', String(error));
|
|
214
216
|
return [];
|
|
215
217
|
}
|
|
216
218
|
}
|
package/dist/WorkspaceWorker.js
CHANGED
|
@@ -4,7 +4,7 @@ import { debugLogArray, debugLogObject } from './util/debug.js';
|
|
|
4
4
|
import { _pureGlob, negate, hasProductionSuffix, hasNoProductionSuffix, prependDirToPattern } from './util/glob.js';
|
|
5
5
|
import { FAKE_PATH } from './util/loader.js';
|
|
6
6
|
import { get, getKeysByValue } from './util/object.js';
|
|
7
|
-
import { join, toPosix } from './util/path.js';
|
|
7
|
+
import { basename, join, toPosix } from './util/path.js';
|
|
8
8
|
import { fromEntryPattern, fromProductionEntryPattern, isEntryPattern, isProductionEntryPattern, } from './util/protocols.js';
|
|
9
9
|
const nullConfig = { config: null, entry: null, project: null };
|
|
10
10
|
export class WorkspaceWorker {
|
|
@@ -183,7 +183,7 @@ export class WorkspaceWorker {
|
|
|
183
183
|
continue;
|
|
184
184
|
const patterns = this.getConfigurationFilePatterns(pluginName);
|
|
185
185
|
const allConfigFilePaths = await _pureGlob({ patterns, cwd, ignore, gitignore: false });
|
|
186
|
-
const configFilePaths = allConfigFilePaths.filter(filePath =>
|
|
186
|
+
const configFilePaths = allConfigFilePaths.filter(filePath => basename(filePath) !== 'package.json' ||
|
|
187
187
|
get(this.manifest, 'PACKAGE_JSON_PATH' in plugin ? plugin.PACKAGE_JSON_PATH : pluginName));
|
|
188
188
|
debugLogArray([name, plugin.NAME], 'config file paths', configFilePaths);
|
|
189
189
|
if (configFilePaths.length === 0)
|
package/dist/constants.js
CHANGED
|
@@ -33,6 +33,7 @@ export const IGNORED_GLOBAL_BINARIES = [
|
|
|
33
33
|
'test',
|
|
34
34
|
'true',
|
|
35
35
|
'yarn',
|
|
36
|
+
'xargs',
|
|
36
37
|
];
|
|
37
38
|
export const IGNORED_DEPENDENCIES = ['knip', 'typescript'];
|
|
38
39
|
export const DUMMY_VIRTUAL_FILE_EXTENSIONS = new Set(['.html', '.jpeg', '.jpg', '.png', '.svg', '.webp']);
|
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ export const main = async (unresolvedConfiguration) => {
|
|
|
19
19
|
const { cwd, tsConfigFile, gitignore, isStrict, isProduction, isShowProgress, isIncludeEntryExports, isIsolateWorkspaces, } = unresolvedConfiguration;
|
|
20
20
|
debugLogObject('*', 'Unresolved configuration (from CLI arguments)', unresolvedConfiguration);
|
|
21
21
|
const chief = new ConfigurationChief({ cwd, isProduction, isStrict, isIncludeEntryExports });
|
|
22
|
-
const deputy = new DependencyDeputy({ isStrict });
|
|
22
|
+
const deputy = new DependencyDeputy({ isProduction, isStrict });
|
|
23
23
|
const factory = new PrincipalFactory();
|
|
24
24
|
const streamer = new ConsoleStreamer({ isEnabled: isShowProgress });
|
|
25
25
|
const isGitIgnored = gitignore ? isGitIgnoredSync({ cwd }) : () => false;
|
|
@@ -214,15 +214,14 @@ export const main = async (unresolvedConfiguration) => {
|
|
|
214
214
|
}
|
|
215
215
|
else {
|
|
216
216
|
const importedModule = importedSymbols.get(specifierFilePath);
|
|
217
|
-
for (const identifier of importItems.symbols)
|
|
217
|
+
for (const identifier of importItems.symbols)
|
|
218
218
|
importedModule.symbols.add(identifier);
|
|
219
|
-
|
|
219
|
+
if (importItems.hasStar)
|
|
220
|
+
importedModule.hasStar = true;
|
|
220
221
|
if (importItems.isReExport) {
|
|
221
|
-
importedModule.isReExport =
|
|
222
|
+
importedModule.isReExport = true;
|
|
222
223
|
importedModule.isReExportedBy.add(filePath);
|
|
223
224
|
}
|
|
224
|
-
if (importItems.isStar)
|
|
225
|
-
importedModule.isStar = importItems.isStar;
|
|
226
225
|
}
|
|
227
226
|
}
|
|
228
227
|
duplicate.forEach(symbols => {
|
|
@@ -299,16 +298,17 @@ export const main = async (unresolvedConfiguration) => {
|
|
|
299
298
|
const workspace = chief.findWorkspaceByFilePath(filePath);
|
|
300
299
|
const principal = workspace && factory.getPrincipalByPackageName(workspace.pkgName);
|
|
301
300
|
if (principal) {
|
|
302
|
-
|
|
301
|
+
const { isIncludeEntryExports } = workspace.config;
|
|
302
|
+
if (!isIncludeEntryExports && principal.entryPaths.has(filePath))
|
|
303
303
|
continue;
|
|
304
|
-
const
|
|
304
|
+
const importsForExport = importedSymbols.get(filePath);
|
|
305
305
|
for (const [symbol, exportedItem] of exportItems.entries()) {
|
|
306
306
|
if (exportedItem.jsDocTags.has('@public') || exportedItem.jsDocTags.has('@beta'))
|
|
307
307
|
continue;
|
|
308
308
|
if (isProduction && exportedItem.jsDocTags.has('@internal'))
|
|
309
309
|
continue;
|
|
310
|
-
if (
|
|
311
|
-
if (
|
|
310
|
+
if (importsForExport && isSymbolImported(symbol, importsForExport)) {
|
|
311
|
+
if (importsForExport.isReExport && isExportedInEntryFile(principal, importsForExport))
|
|
312
312
|
continue;
|
|
313
313
|
if (report.enumMembers && exportedItem.type === 'enum' && exportedItem.members) {
|
|
314
314
|
principal.findUnusedMembers(filePath, exportedItem.members).forEach(member => {
|
|
@@ -334,28 +334,20 @@ export const main = async (unresolvedConfiguration) => {
|
|
|
334
334
|
}
|
|
335
335
|
continue;
|
|
336
336
|
}
|
|
337
|
-
const
|
|
338
|
-
const
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
const type = isStar ? 'nsExports' : 'exports';
|
|
352
|
-
collector.addIssue({
|
|
353
|
-
type,
|
|
354
|
-
filePath,
|
|
355
|
-
symbol,
|
|
356
|
-
...principal.getPos(exportedItem.node, exportedItem.pos),
|
|
357
|
-
});
|
|
358
|
-
}
|
|
337
|
+
const hasNsImport = Boolean(importsForExport?.hasStar);
|
|
338
|
+
const isReExport = !isIncludeEntryExports && hasNsImport && isExportedInEntryFile(principal, importsForExport);
|
|
339
|
+
const isType = ['enum', 'type', 'interface'].includes(exportedItem.type);
|
|
340
|
+
if (hasNsImport && ((!report.nsTypes && isType) || (!report.nsExports && !isType)))
|
|
341
|
+
continue;
|
|
342
|
+
if (!isReExport && !isExportedItemReferenced(principal, exportedItem, filePath)) {
|
|
343
|
+
const type = isType ? (hasNsImport ? 'nsTypes' : 'types') : hasNsImport ? 'nsExports' : 'exports';
|
|
344
|
+
collector.addIssue({
|
|
345
|
+
type,
|
|
346
|
+
filePath,
|
|
347
|
+
symbol,
|
|
348
|
+
symbolType: exportedItem.type,
|
|
349
|
+
...principal.getPos(exportedItem.node, exportedItem.pos),
|
|
350
|
+
});
|
|
359
351
|
}
|
|
360
352
|
}
|
|
361
353
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { basename } from '../../util/path.js';
|
|
1
2
|
import { timerify } from '../../util/Performance.js';
|
|
2
3
|
import { hasDependency, load } from '../../util/plugin.js';
|
|
3
4
|
import { toEntryPattern, toProductionEntryPattern } from '../../util/protocols.js';
|
|
@@ -10,10 +11,7 @@ export const PRODUCTION_ENTRY_FILE_PATTERNS = [];
|
|
|
10
11
|
export const PROJECT_FILE_PATTERNS = [];
|
|
11
12
|
const findPluginDependencies = async (configFilePath, options) => {
|
|
12
13
|
const { manifest, config, isProduction } = options;
|
|
13
|
-
const localConfig = configFilePath
|
|
14
|
-
?
|
|
15
|
-
manifest.plugin
|
|
16
|
-
: await load(configFilePath);
|
|
14
|
+
const localConfig = basename(configFilePath) === 'package.json' ? manifest.plugin : await load(configFilePath);
|
|
17
15
|
if (!localConfig)
|
|
18
16
|
return [];
|
|
19
17
|
const entryPatterns = (config?.entry ?? localConfig.entryPathsOrPatterns ?? ENTRY_FILE_PATTERNS).map(toEntryPattern);
|
|
@@ -12,7 +12,7 @@ export const findDependencies = async (configFilePath, options) => {
|
|
|
12
12
|
: [...ENTRY_FILE_PATTERNS.map(toEntryPattern), ...PRODUCTION_ENTRY_FILE_PATTERNS.map(toProductionEntryPattern)];
|
|
13
13
|
if (!isProduction &&
|
|
14
14
|
manifest.scripts &&
|
|
15
|
-
Object.values(manifest.scripts).some(script => /astro
|
|
15
|
+
Object.values(manifest.scripts).some(script => /(?<=^|\s)astro(\s|\s.+\s)check(?=\s|$)/.test(script))) {
|
|
16
16
|
dependencies.push('@astrojs/check');
|
|
17
17
|
}
|
|
18
18
|
return dependencies;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { basename } from '../../util/path.js';
|
|
2
2
|
import { timerify } from '../../util/Performance.js';
|
|
3
|
-
import { hasDependency, load } from '../../util/plugin.js';
|
|
3
|
+
import { getDependenciesFromScripts, hasDependency, load } from '../../util/plugin.js';
|
|
4
4
|
import { toEntryPattern } from '../../util/protocols.js';
|
|
5
5
|
export const NAME = 'Ava';
|
|
6
6
|
export const ENABLERS = ['ava'];
|
|
@@ -20,9 +20,7 @@ export const ENTRY_FILE_PATTERNS = [
|
|
|
20
20
|
];
|
|
21
21
|
const findAvaDependencies = async (configFilePath, options) => {
|
|
22
22
|
const { cwd, manifest, isProduction, config } = options;
|
|
23
|
-
let localConfig = configFilePath
|
|
24
|
-
? manifest.ava
|
|
25
|
-
: await load(configFilePath);
|
|
23
|
+
let localConfig = basename(configFilePath) === 'package.json' ? manifest.ava : await load(configFilePath);
|
|
26
24
|
if (typeof localConfig === 'function')
|
|
27
25
|
localConfig = localConfig();
|
|
28
26
|
const entryPatterns = (config.entry ?? localConfig?.files ?? ENTRY_FILE_PATTERNS).map(toEntryPattern);
|
|
@@ -31,7 +29,7 @@ const findAvaDependencies = async (configFilePath, options) => {
|
|
|
31
29
|
const nodeArgs = localConfig.nodeArguments ?? [];
|
|
32
30
|
const requireArgs = (localConfig.require ?? []).map(require => `--require ${require}`);
|
|
33
31
|
const fakeCommand = `node ${nodeArgs.join(' ')} ${requireArgs.join(' ')}`;
|
|
34
|
-
const dependencies =
|
|
32
|
+
const dependencies = getDependenciesFromScripts([fakeCommand], {
|
|
35
33
|
cwd,
|
|
36
34
|
manifest,
|
|
37
35
|
knownGlobalsOnly: true,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { compact } from '../../util/array.js';
|
|
2
|
+
import { basename } from '../../util/path.js';
|
|
2
3
|
import { timerify } from '../../util/Performance.js';
|
|
3
4
|
import { hasDependency, load } from '../../util/plugin.js';
|
|
4
5
|
import { resolveName, api } from './helpers.js';
|
|
@@ -21,9 +22,7 @@ export const getDependenciesFromConfig = (config) => {
|
|
|
21
22
|
const findBabelDependencies = async (configFilePath, { manifest, isProduction }) => {
|
|
22
23
|
if (isProduction)
|
|
23
24
|
return [];
|
|
24
|
-
let localConfig = configFilePath
|
|
25
|
-
? manifest.babel
|
|
26
|
-
: await load(configFilePath);
|
|
25
|
+
let localConfig = basename(configFilePath) === 'package.json' ? manifest.babel : await load(configFilePath);
|
|
27
26
|
if (typeof localConfig === 'function')
|
|
28
27
|
localConfig = localConfig(api);
|
|
29
28
|
if (!localConfig)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { basename } from '../../util/path.js';
|
|
1
2
|
import { timerify } from '../../util/Performance.js';
|
|
2
3
|
import { hasDependency, load } from '../../util/plugin.js';
|
|
3
4
|
export const NAME = 'Commitizen';
|
|
@@ -8,9 +9,7 @@ export const CONFIG_FILE_PATTERNS = ['.czrc', '.cz.json', 'package.json'];
|
|
|
8
9
|
const findPluginDependencies = async (configFilePath, { manifest, isProduction }) => {
|
|
9
10
|
if (isProduction)
|
|
10
11
|
return [];
|
|
11
|
-
const localConfig = configFilePath
|
|
12
|
-
? manifest.config?.commitizen
|
|
13
|
-
: await load(configFilePath);
|
|
12
|
+
const localConfig = basename(configFilePath) === 'package.json' ? manifest.config?.commitizen : await load(configFilePath);
|
|
14
13
|
if (!localConfig)
|
|
15
14
|
return [];
|
|
16
15
|
return localConfig.path ? [localConfig.path] : [];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { basename } from '../../util/path.js';
|
|
1
2
|
import { timerify } from '../../util/Performance.js';
|
|
2
3
|
import { hasDependency, load } from '../../util/plugin.js';
|
|
3
4
|
export const NAME = 'commitlint';
|
|
@@ -12,9 +13,7 @@ export const CONFIG_FILE_PATTERNS = [
|
|
|
12
13
|
const findCommitLintDependencies = async (configFilePath, { manifest, isProduction }) => {
|
|
13
14
|
if (isProduction)
|
|
14
15
|
return [];
|
|
15
|
-
const localConfig = configFilePath
|
|
16
|
-
? manifest.commitlint
|
|
17
|
-
: await load(configFilePath);
|
|
16
|
+
const localConfig = basename(configFilePath) === 'package.json' ? manifest.commitlint : await load(configFilePath);
|
|
18
17
|
if (!localConfig)
|
|
19
18
|
return [];
|
|
20
19
|
return localConfig.extends ? [localConfig.extends].flat() : [];
|