knip 5.70.1 → 5.71.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/DependencyDeputy.js +2 -2
- package/dist/ProjectPrincipal.js +1 -1
- package/dist/WorkspaceWorker.js +32 -35
- package/dist/binaries/bash-parser.js +14 -1
- package/dist/compilers/index.js +1 -1
- package/dist/constants.js +1 -0
- package/dist/graph/analyze.js +21 -16
- package/dist/graph/build.js +71 -87
- package/dist/graph-explorer/constants.d.ts +2 -0
- package/dist/graph-explorer/constants.js +2 -0
- package/dist/graph-explorer/explorer.d.ts +11 -0
- package/dist/graph-explorer/explorer.js +10 -0
- package/dist/graph-explorer/operations/build-trace-tree.d.ts +12 -0
- package/dist/graph-explorer/operations/build-trace-tree.js +51 -0
- package/dist/graph-explorer/operations/has-strictly-ns-references.d.ts +2 -0
- package/dist/graph-explorer/operations/has-strictly-ns-references.js +98 -0
- package/dist/graph-explorer/operations/is-referenced.d.ts +4 -0
- package/dist/graph-explorer/operations/is-referenced.js +89 -0
- package/dist/graph-explorer/utils.d.ts +4 -0
- package/dist/graph-explorer/utils.js +28 -0
- package/dist/graph-explorer/visitors.d.ts +12 -0
- package/dist/graph-explorer/visitors.js +30 -0
- package/dist/graph-explorer/walk-down.d.ts +4 -0
- package/dist/graph-explorer/walk-down.js +119 -0
- package/dist/index.js +2 -98
- package/dist/plugins/angular/index.js +3 -3
- package/dist/plugins/astro/index.js +0 -2
- package/dist/plugins/next/index.js +4 -3
- package/dist/plugins/next/resolveFromAST.d.ts +1 -0
- package/dist/plugins/next/resolveFromAST.js +42 -1
- package/dist/plugins/vite/helpers.js +1 -1
- package/dist/reporters/codeclimate.js +3 -7
- package/dist/reporters/util/util.d.ts +2 -1
- package/dist/reporters/util/util.js +1 -0
- package/dist/reporters/watch.js +1 -1
- package/dist/run.d.ts +25 -0
- package/dist/run.js +107 -0
- package/dist/types/issues.d.ts +4 -4
- package/dist/types/module-graph.d.ts +14 -12
- package/dist/typescript/ast-helpers.d.ts +4 -0
- package/dist/typescript/ast-helpers.js +48 -0
- package/dist/typescript/get-imports-and-exports.js +18 -3
- package/dist/typescript/visitors/dynamic-imports/importCall.js +5 -19
- package/dist/typescript/visitors/dynamic-imports/jsDocType.js +7 -5
- package/dist/typescript/visitors/imports/importDeclaration.js +5 -4
- package/dist/util/create-options.js +1 -1
- package/dist/util/file-entry-cache.js +1 -1
- package/dist/util/graph-sequencer.js +1 -1
- package/dist/util/input.d.ts +1 -0
- package/dist/util/module-graph.js +7 -7
- package/dist/util/plugin.d.ts +1 -1
- package/dist/util/plugin.js +4 -3
- package/dist/util/trace.d.ts +3 -13
- package/dist/util/trace.js +10 -41
- package/dist/util/watch.d.ts +19 -3
- package/dist/util/watch.js +28 -17
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/vendor/bash-parser/index.d.ts +6 -1
- package/dist/util/has-strictly-ns-references.d.ts +0 -4
- package/dist/util/has-strictly-ns-references.js +0 -103
- package/dist/util/is-identifier-referenced.d.ts +0 -9
- package/dist/util/is-identifier-referenced.js +0 -145
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { CONTINUE } from '../constants.js';
|
|
2
|
+
import { walkDown } from '../walk-down.js';
|
|
3
|
+
export const buildExportsTree = (graph, entryPaths, options) => {
|
|
4
|
+
const traces = [];
|
|
5
|
+
const processFile = (filePath, file) => {
|
|
6
|
+
for (const exportId of options.identifier ? [options.identifier] : file.exports.keys()) {
|
|
7
|
+
if (!options.identifier || file.exports.has(exportId)) {
|
|
8
|
+
const trace = buildExportTree(graph, entryPaths, filePath, exportId);
|
|
9
|
+
if (trace)
|
|
10
|
+
traces.push(trace);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
if (options.filePath) {
|
|
15
|
+
const file = graph.get(options.filePath);
|
|
16
|
+
if (file)
|
|
17
|
+
processFile(options.filePath, file);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
for (const [filePath, file] of graph)
|
|
21
|
+
processFile(filePath, file);
|
|
22
|
+
}
|
|
23
|
+
return traces;
|
|
24
|
+
};
|
|
25
|
+
const buildExportTree = (graph, entryPaths, filePath, identifier) => {
|
|
26
|
+
const rootNode = {
|
|
27
|
+
filePath,
|
|
28
|
+
identifier,
|
|
29
|
+
hasRef: false,
|
|
30
|
+
isEntry: entryPaths.has(filePath),
|
|
31
|
+
children: [],
|
|
32
|
+
};
|
|
33
|
+
const nodeMap = new Map();
|
|
34
|
+
nodeMap.set(`${filePath}:${identifier}`, rootNode);
|
|
35
|
+
walkDown(graph, filePath, identifier, (sourceFile, sourceId, importingFile, id, isEntry, isReExport) => {
|
|
36
|
+
const key = `${importingFile}:${id}`;
|
|
37
|
+
const childNode = nodeMap.get(key) ?? {
|
|
38
|
+
filePath: importingFile,
|
|
39
|
+
identifier: id,
|
|
40
|
+
hasRef: !isReExport && Boolean(graph.get(importingFile)?.traceRefs?.has(id)),
|
|
41
|
+
isEntry,
|
|
42
|
+
children: [],
|
|
43
|
+
};
|
|
44
|
+
nodeMap.set(key, childNode);
|
|
45
|
+
const parentKey = `${sourceFile}:${sourceId}`;
|
|
46
|
+
const parentNode = nodeMap.get(parentKey) ?? rootNode;
|
|
47
|
+
parentNode.children.push(childNode);
|
|
48
|
+
return CONTINUE;
|
|
49
|
+
}, entryPaths);
|
|
50
|
+
return rootNode;
|
|
51
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { forEachAliasReExport, forEachNamespaceReExport, forEachPassThroughReExport, getStarReExportSources, } from '../visitors.js';
|
|
2
|
+
export const hasStrictlyNsReferences = (graph, importsForExport, identifier) => {
|
|
3
|
+
if (!importsForExport)
|
|
4
|
+
return [false];
|
|
5
|
+
let foundNamespace;
|
|
6
|
+
const aliasByIdentifier = new Map();
|
|
7
|
+
const namespaceReExports = new Map();
|
|
8
|
+
const namespaceEdges = [];
|
|
9
|
+
const directById = new Map();
|
|
10
|
+
forEachPassThroughReExport(importsForExport, (id, sources) => {
|
|
11
|
+
directById.set(id, sources);
|
|
12
|
+
});
|
|
13
|
+
forEachAliasReExport(importsForExport, (id, alias, sources) => {
|
|
14
|
+
let arr = aliasByIdentifier.get(id);
|
|
15
|
+
if (!arr) {
|
|
16
|
+
arr = [];
|
|
17
|
+
aliasByIdentifier.set(id, arr);
|
|
18
|
+
}
|
|
19
|
+
arr.push({ alias, sources });
|
|
20
|
+
});
|
|
21
|
+
forEachNamespaceReExport(importsForExport, (namespace, sources) => {
|
|
22
|
+
namespaceEdges.push({ namespace, sources });
|
|
23
|
+
let arr = namespaceReExports.get(namespace);
|
|
24
|
+
if (!arr) {
|
|
25
|
+
arr = [];
|
|
26
|
+
namespaceReExports.set(namespace, arr);
|
|
27
|
+
}
|
|
28
|
+
arr.push(sources);
|
|
29
|
+
});
|
|
30
|
+
const starSources = getStarReExportSources(importsForExport);
|
|
31
|
+
const followReExports = (sources, nextId, propagateNamespace = true) => {
|
|
32
|
+
for (const filePath of sources) {
|
|
33
|
+
const file = graph.get(filePath);
|
|
34
|
+
if (!file?.imported)
|
|
35
|
+
continue;
|
|
36
|
+
const result = hasStrictlyNsReferences(graph, file.imported, nextId);
|
|
37
|
+
if (result[0] === false)
|
|
38
|
+
return result;
|
|
39
|
+
if (propagateNamespace && result[1])
|
|
40
|
+
foundNamespace = result[1];
|
|
41
|
+
}
|
|
42
|
+
return undefined;
|
|
43
|
+
};
|
|
44
|
+
for (const ns of importsForExport.importedNs.keys()) {
|
|
45
|
+
const hasNsRef = importsForExport.refs.has(ns);
|
|
46
|
+
if (!hasNsRef)
|
|
47
|
+
return [false, ns];
|
|
48
|
+
for (const ref of importsForExport.refs) {
|
|
49
|
+
if (ref.startsWith(`${ns}.`))
|
|
50
|
+
return [false, ns];
|
|
51
|
+
}
|
|
52
|
+
const nsReExports = namespaceReExports.get(ns);
|
|
53
|
+
if (nsReExports) {
|
|
54
|
+
for (const sources of nsReExports) {
|
|
55
|
+
const result = followReExports(sources, identifier, false);
|
|
56
|
+
if (result)
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const nsAliases = aliasByIdentifier.get(ns);
|
|
61
|
+
if (nsAliases) {
|
|
62
|
+
for (const { sources } of nsAliases) {
|
|
63
|
+
const result = followReExports(sources, identifier, false);
|
|
64
|
+
if (result)
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
foundNamespace = ns;
|
|
69
|
+
}
|
|
70
|
+
const directSources = directById.get(identifier);
|
|
71
|
+
if (directSources) {
|
|
72
|
+
const result = followReExports(directSources, identifier, true);
|
|
73
|
+
if (result)
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
if (starSources) {
|
|
77
|
+
const result = followReExports(starSources, identifier, true);
|
|
78
|
+
if (result)
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
const [id, ...rest] = identifier.split('.');
|
|
82
|
+
const aliasEntries = aliasByIdentifier.get(id);
|
|
83
|
+
if (aliasEntries) {
|
|
84
|
+
for (const { alias, sources } of aliasEntries) {
|
|
85
|
+
const result = followReExports(sources, [alias, ...rest].join('.'), true);
|
|
86
|
+
if (result)
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
for (const { namespace: ns, sources } of namespaceEdges) {
|
|
91
|
+
const result = followReExports(sources, `${ns}.${identifier}`, true);
|
|
92
|
+
if (result)
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
if (foundNamespace)
|
|
96
|
+
return [true, foundNamespace];
|
|
97
|
+
return [false];
|
|
98
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Identifier, ModuleGraph } from '../../types/module-graph.js';
|
|
2
|
+
export declare const isReferenced: (graph: ModuleGraph, entryPaths: Set<string>, filePath: string, id: Identifier, options: {
|
|
3
|
+
includeEntryExports: boolean;
|
|
4
|
+
}) => [boolean, string | undefined];
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { OPAQUE } from '../../constants.js';
|
|
2
|
+
import { getAliasReExportMap, getNamespaceReExportSources, getPassThroughReExportSources, getStarReExportSources, } from '../visitors.js';
|
|
3
|
+
export const isReferenced = (graph, entryPaths, filePath, id, options) => {
|
|
4
|
+
const seen = new Set();
|
|
5
|
+
const check = (currentPath, currentId) => {
|
|
6
|
+
const isEntryFile = entryPaths.has(currentPath);
|
|
7
|
+
let reExportingEntryFile = isEntryFile ? currentPath : undefined;
|
|
8
|
+
if (isEntryFile && !options.includeEntryExports)
|
|
9
|
+
return [false, reExportingEntryFile];
|
|
10
|
+
if (seen.has(currentPath))
|
|
11
|
+
return [false, reExportingEntryFile];
|
|
12
|
+
seen.add(currentPath);
|
|
13
|
+
const restIds = currentId.split('.');
|
|
14
|
+
const identifier = restIds.shift();
|
|
15
|
+
const file = graph.get(currentPath)?.imported;
|
|
16
|
+
if (!identifier || !file) {
|
|
17
|
+
return [false, reExportingEntryFile];
|
|
18
|
+
}
|
|
19
|
+
const directSources = getPassThroughReExportSources(file, identifier);
|
|
20
|
+
const starSources = getStarReExportSources(file);
|
|
21
|
+
const followSources = (sources, nextId) => {
|
|
22
|
+
for (const byFilePath of sources) {
|
|
23
|
+
if (seen.has(byFilePath))
|
|
24
|
+
continue;
|
|
25
|
+
const result = check(byFilePath, nextId);
|
|
26
|
+
if (result[1])
|
|
27
|
+
reExportingEntryFile = result[1];
|
|
28
|
+
if (result[0])
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
};
|
|
33
|
+
if (file.imported.get(OPAQUE) ||
|
|
34
|
+
((identifier === currentId || (identifier !== currentId && file.refs.has(currentId))) &&
|
|
35
|
+
(file.imported.has(identifier) || file.importedAs.has(identifier)))) {
|
|
36
|
+
return [true, reExportingEntryFile];
|
|
37
|
+
}
|
|
38
|
+
for (const [exportId, aliases] of file.importedAs) {
|
|
39
|
+
if (identifier === exportId) {
|
|
40
|
+
for (const alias of aliases.keys()) {
|
|
41
|
+
const aliasedRef = [alias, ...restIds].join('.');
|
|
42
|
+
if (file.refs.has(aliasedRef)) {
|
|
43
|
+
return [true, reExportingEntryFile];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
for (const namespace of file.importedNs.keys()) {
|
|
49
|
+
if (file.refs.has(`${namespace}.${currentId}`)) {
|
|
50
|
+
return [true, reExportingEntryFile];
|
|
51
|
+
}
|
|
52
|
+
const nsAliasMap = getAliasReExportMap(file, namespace);
|
|
53
|
+
if (nsAliasMap) {
|
|
54
|
+
for (const [alias, sources] of nsAliasMap) {
|
|
55
|
+
if (followSources(sources, `${alias}.${currentId}`))
|
|
56
|
+
return [true, reExportingEntryFile];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const nsReExportSources = getNamespaceReExportSources(file, namespace);
|
|
60
|
+
if (nsReExportSources) {
|
|
61
|
+
if (followSources(nsReExportSources, `${namespace}.${currentId}`))
|
|
62
|
+
return [true, reExportingEntryFile];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const aliasMap = getAliasReExportMap(file, identifier);
|
|
66
|
+
if (aliasMap) {
|
|
67
|
+
for (const [alias, sources] of aliasMap) {
|
|
68
|
+
const ref = [alias, ...restIds].join('.');
|
|
69
|
+
if (followSources(sources, ref))
|
|
70
|
+
return [true, reExportingEntryFile];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (directSources) {
|
|
74
|
+
if (followSources(directSources, currentId))
|
|
75
|
+
return [true, reExportingEntryFile];
|
|
76
|
+
}
|
|
77
|
+
else if (starSources) {
|
|
78
|
+
if (followSources(starSources, currentId))
|
|
79
|
+
return [true, reExportingEntryFile];
|
|
80
|
+
}
|
|
81
|
+
for (const [namespace, sources] of file.reExportedNs) {
|
|
82
|
+
if (followSources(sources, `${namespace}.${currentId}`)) {
|
|
83
|
+
return [true, reExportingEntryFile];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return [false, reExportingEntryFile];
|
|
87
|
+
};
|
|
88
|
+
return check(filePath, id);
|
|
89
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ImportMaps, ModuleGraph } from '../types/module-graph.js';
|
|
2
|
+
export declare const hasNamespaceMemberReference: (graph: ModuleGraph, importingFile: string, importedFile: string, namespace: string, member: string) => boolean | null;
|
|
3
|
+
export declare const hasStrictlyEnumReferences: (importsForExport: ImportMaps | undefined, identifier: string) => boolean;
|
|
4
|
+
export declare const getIssueType: (hasOnlyNsReference: boolean, isType: boolean) => "exports" | "nsExports" | "types" | "nsTypes";
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { OPAQUE } from '../constants.js';
|
|
2
|
+
export const hasNamespaceMemberReference = (graph, importingFile, importedFile, namespace, member) => {
|
|
3
|
+
const importerNode = graph.get(importingFile);
|
|
4
|
+
if (!importerNode)
|
|
5
|
+
return null;
|
|
6
|
+
const importMap = importerNode.imports.internal.get(importedFile);
|
|
7
|
+
if (!importMap)
|
|
8
|
+
return null;
|
|
9
|
+
if (importMap.imported.get(OPAQUE))
|
|
10
|
+
return true;
|
|
11
|
+
if (importMap.refs.size === 0)
|
|
12
|
+
return false;
|
|
13
|
+
const refKey = member ? `${namespace}.${member}` : namespace;
|
|
14
|
+
return refKey ? importMap.refs.has(refKey) : null;
|
|
15
|
+
};
|
|
16
|
+
export const hasStrictlyEnumReferences = (importsForExport, identifier) => {
|
|
17
|
+
if (!importsForExport || !importsForExport.refs.has(identifier))
|
|
18
|
+
return false;
|
|
19
|
+
for (const ref of importsForExport.refs)
|
|
20
|
+
if (ref.startsWith(`${identifier}.`))
|
|
21
|
+
return false;
|
|
22
|
+
return true;
|
|
23
|
+
};
|
|
24
|
+
export const getIssueType = (hasOnlyNsReference, isType) => {
|
|
25
|
+
if (hasOnlyNsReference)
|
|
26
|
+
return isType ? 'nsTypes' : 'nsExports';
|
|
27
|
+
return isType ? 'types' : 'exports';
|
|
28
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ImportMaps } from '../types/module-graph.js';
|
|
2
|
+
type PassThroughReExportCallback = (identifier: string, sources: Set<string>) => boolean | void;
|
|
3
|
+
type AliasReExportCallback = (identifier: string, alias: string, sources: Set<string>) => boolean | void;
|
|
4
|
+
type NamespaceReExportCallback = (namespace: string, sources: Set<string>) => boolean | void;
|
|
5
|
+
export declare const forEachPassThroughReExport: (importMaps: ImportMaps, callback: PassThroughReExportCallback) => boolean;
|
|
6
|
+
export declare const forEachAliasReExport: (importMaps: ImportMaps, callback: AliasReExportCallback) => boolean;
|
|
7
|
+
export declare const forEachNamespaceReExport: (importMaps: ImportMaps, callback: NamespaceReExportCallback) => boolean;
|
|
8
|
+
export declare const getStarReExportSources: (importMaps: ImportMaps) => Set<string> | undefined;
|
|
9
|
+
export declare const getPassThroughReExportSources: (importMaps: ImportMaps, identifier: string) => Set<string> | undefined;
|
|
10
|
+
export declare const getAliasReExportMap: (importMaps: ImportMaps, identifier: string) => Map<string, Set<string>> | undefined;
|
|
11
|
+
export declare const getNamespaceReExportSources: (importMaps: ImportMaps, namespace: string) => Set<string> | undefined;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { IMPORT_STAR } from '../constants.js';
|
|
2
|
+
export const forEachPassThroughReExport = (importMaps, callback) => {
|
|
3
|
+
for (const [identifier, sources] of importMaps.reExported) {
|
|
4
|
+
if (identifier === IMPORT_STAR)
|
|
5
|
+
continue;
|
|
6
|
+
if (callback(identifier, sources ?? new Set()) === false)
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
return true;
|
|
10
|
+
};
|
|
11
|
+
export const forEachAliasReExport = (importMaps, callback) => {
|
|
12
|
+
for (const [identifier, aliasMap] of importMaps.reExportedAs) {
|
|
13
|
+
for (const [alias, sources] of aliasMap) {
|
|
14
|
+
if (callback(identifier, alias, sources ?? new Set()) === false)
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return true;
|
|
19
|
+
};
|
|
20
|
+
export const forEachNamespaceReExport = (importMaps, callback) => {
|
|
21
|
+
for (const [namespace, sources] of importMaps.reExportedNs) {
|
|
22
|
+
if (callback(namespace, sources ?? new Set()) === false)
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
};
|
|
27
|
+
export const getStarReExportSources = (importMaps) => importMaps.reExported.get(IMPORT_STAR);
|
|
28
|
+
export const getPassThroughReExportSources = (importMaps, identifier) => importMaps.reExported.get(identifier);
|
|
29
|
+
export const getAliasReExportMap = (importMaps, identifier) => importMaps.reExportedAs.get(identifier);
|
|
30
|
+
export const getNamespaceReExportSources = (importMaps, namespace) => importMaps.reExportedNs.get(namespace);
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ModuleGraph } from '../types/module-graph.js';
|
|
2
|
+
type Visitor = (sourceFile: string, identifier: string, importingFile: string, identifierPath: string, isEntry: boolean, isReExport: boolean) => 'continue' | 'stop' | undefined;
|
|
3
|
+
export declare const walkDown: (graph: ModuleGraph, filePath: string, identifier: string, visitor: Visitor, entryPaths: Set<string>, visited?: Set<string>) => boolean;
|
|
4
|
+
export {};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { STOP } from './constants.js';
|
|
2
|
+
import { hasNamespaceMemberReference } from './utils.js';
|
|
3
|
+
import { getAliasReExportMap, getPassThroughReExportSources, getStarReExportSources } from './visitors.js';
|
|
4
|
+
export const walkDown = (graph, filePath, identifier, visitor, entryPaths, visited = new Set()) => {
|
|
5
|
+
const key = `${filePath}:${identifier}`;
|
|
6
|
+
if (visited.has(key))
|
|
7
|
+
return false;
|
|
8
|
+
visited.add(key);
|
|
9
|
+
const file = graph.get(filePath);
|
|
10
|
+
if (!file?.imported)
|
|
11
|
+
return false;
|
|
12
|
+
const restIds = identifier.split('.');
|
|
13
|
+
const id = restIds.shift();
|
|
14
|
+
if (!id)
|
|
15
|
+
return false;
|
|
16
|
+
const imported = file.imported;
|
|
17
|
+
const importedByFiles = imported.imported.get(id);
|
|
18
|
+
if (importedByFiles) {
|
|
19
|
+
for (const importingFile of importedByFiles) {
|
|
20
|
+
const isEntry = entryPaths.has(importingFile);
|
|
21
|
+
if (visitor(filePath, id, importingFile, id, isEntry, false) === STOP)
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const importedAsAliases = imported.importedAs.get(id);
|
|
26
|
+
if (importedAsAliases) {
|
|
27
|
+
for (const [alias, byFilePaths] of importedAsAliases) {
|
|
28
|
+
for (const importingFile of byFilePaths) {
|
|
29
|
+
const isEntry = entryPaths.has(importingFile);
|
|
30
|
+
if (visitor(filePath, id, importingFile, alias, isEntry, false) === STOP)
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
for (const [namespace, byFilePaths] of imported.importedNs) {
|
|
36
|
+
for (const importingFile of byFilePaths) {
|
|
37
|
+
if (hasNamespaceMemberReference(graph, importingFile, filePath, namespace, identifier) === false)
|
|
38
|
+
continue;
|
|
39
|
+
const isEntry = entryPaths.has(importingFile);
|
|
40
|
+
if (visitor(filePath, identifier, importingFile, `${namespace}.${identifier}`, isEntry, false) === STOP) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
let done = false;
|
|
46
|
+
if (!done) {
|
|
47
|
+
const passThroughSources = getPassThroughReExportSources(imported, id);
|
|
48
|
+
if (passThroughSources) {
|
|
49
|
+
for (const reExportingFile of passThroughSources) {
|
|
50
|
+
const isEntry = entryPaths.has(reExportingFile);
|
|
51
|
+
if (visitor(filePath, id, reExportingFile, id, isEntry, true) === STOP) {
|
|
52
|
+
done = true;
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
if (!isEntry && walkDown(graph, reExportingFile, identifier, visitor, entryPaths, visited)) {
|
|
56
|
+
done = true;
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (!done) {
|
|
63
|
+
const aliasReExportMap = getAliasReExportMap(imported, id);
|
|
64
|
+
if (aliasReExportMap) {
|
|
65
|
+
for (const [alias, sources] of aliasReExportMap) {
|
|
66
|
+
for (const reExportingFile of sources) {
|
|
67
|
+
const isEntry = entryPaths.has(reExportingFile);
|
|
68
|
+
if (visitor(filePath, id, reExportingFile, alias, isEntry, true) === STOP) {
|
|
69
|
+
done = true;
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
if (!isEntry) {
|
|
73
|
+
const ref = [alias, ...restIds].join('.');
|
|
74
|
+
if (walkDown(graph, reExportingFile, ref, visitor, entryPaths, visited)) {
|
|
75
|
+
done = true;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (done)
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (!done) {
|
|
86
|
+
for (const [namespace, sources] of imported.reExportedNs) {
|
|
87
|
+
for (const reExportingFile of sources) {
|
|
88
|
+
const isEntry = entryPaths.has(reExportingFile);
|
|
89
|
+
if (visitor(filePath, identifier, reExportingFile, `${namespace}.${identifier}`, isEntry, true) === STOP) {
|
|
90
|
+
done = true;
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
if (!isEntry && walkDown(graph, reExportingFile, `${namespace}.${identifier}`, visitor, entryPaths, visited)) {
|
|
94
|
+
done = true;
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (done)
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (!done) {
|
|
103
|
+
const starSources = getStarReExportSources(imported);
|
|
104
|
+
if (starSources) {
|
|
105
|
+
for (const reExportingFile of starSources) {
|
|
106
|
+
const isEntry = entryPaths.has(reExportingFile);
|
|
107
|
+
if (visitor(filePath, id, reExportingFile, id, isEntry, true) === STOP) {
|
|
108
|
+
done = true;
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
if (!isEntry && walkDown(graph, reExportingFile, identifier, visitor, entryPaths, visited)) {
|
|
112
|
+
done = true;
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return done;
|
|
119
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1,98 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { CatalogCounselor } from './CatalogCounselor.js';
|
|
4
|
-
import { ConfigurationChief } from './ConfigurationChief.js';
|
|
5
|
-
import { ConsoleStreamer } from './ConsoleStreamer.js';
|
|
6
|
-
import { DependencyDeputy } from './DependencyDeputy.js';
|
|
7
|
-
import { analyze } from './graph/analyze.js';
|
|
8
|
-
import { build } from './graph/build.js';
|
|
9
|
-
import { IssueCollector } from './IssueCollector.js';
|
|
10
|
-
import { IssueFixer } from './IssueFixer.js';
|
|
11
|
-
import { PrincipalFactory } from './PrincipalFactory.js';
|
|
12
|
-
import watchReporter from './reporters/watch.js';
|
|
13
|
-
import { debugLogArray, debugLogObject } from './util/debug.js';
|
|
14
|
-
import { getGitIgnoredHandler } from './util/glob-core.js';
|
|
15
|
-
import { getWatchHandler } from './util/watch.js';
|
|
16
|
-
export const main = async (options) => {
|
|
17
|
-
debugLogObject('*', 'Unresolved configuration', options);
|
|
18
|
-
debugLogObject('*', 'Included issue types', options.includedIssueTypes);
|
|
19
|
-
const chief = new ConfigurationChief(options);
|
|
20
|
-
const deputy = new DependencyDeputy(options);
|
|
21
|
-
const factory = new PrincipalFactory();
|
|
22
|
-
const streamer = new ConsoleStreamer(options);
|
|
23
|
-
const fixer = new IssueFixer(options);
|
|
24
|
-
const collector = new IssueCollector(options);
|
|
25
|
-
const counselor = new CatalogCounselor(options);
|
|
26
|
-
streamer.cast('Reading workspace configuration');
|
|
27
|
-
const workspaces = await chief.getWorkspaces();
|
|
28
|
-
const isGitIgnored = await getGitIgnoredHandler(options);
|
|
29
|
-
collector.setIgnoreIssues(chief.config.ignoreIssues);
|
|
30
|
-
debugLogObject('*', 'Included workspaces', () => workspaces.map(w => w.pkgName));
|
|
31
|
-
debugLogObject('*', 'Included workspace configs', () => workspaces.map(w => ({ pkgName: w.pkgName, name: w.name, config: w.config, ancestors: w.ancestors })));
|
|
32
|
-
const { graph, entryPaths, analyzedFiles, unreferencedFiles, analyzeSourceFile } = await build({
|
|
33
|
-
chief,
|
|
34
|
-
collector,
|
|
35
|
-
counselor,
|
|
36
|
-
deputy,
|
|
37
|
-
factory,
|
|
38
|
-
isGitIgnored,
|
|
39
|
-
streamer,
|
|
40
|
-
workspaces,
|
|
41
|
-
options,
|
|
42
|
-
});
|
|
43
|
-
const reAnalyze = await analyze({
|
|
44
|
-
analyzedFiles,
|
|
45
|
-
counselor,
|
|
46
|
-
chief,
|
|
47
|
-
collector,
|
|
48
|
-
deputy,
|
|
49
|
-
entryPaths,
|
|
50
|
-
factory,
|
|
51
|
-
fixer,
|
|
52
|
-
graph,
|
|
53
|
-
streamer,
|
|
54
|
-
unreferencedFiles,
|
|
55
|
-
options,
|
|
56
|
-
});
|
|
57
|
-
if (options.isWatch) {
|
|
58
|
-
const isIgnored = (filePath) => filePath.startsWith(options.cacheLocation) || filePath.includes('/.git/') || isGitIgnored(filePath);
|
|
59
|
-
const onUpdate = options.isWatch
|
|
60
|
-
? ({ issues, duration }) => watchReporter(options, { issues, streamer, size: analyzedFiles.size, duration })
|
|
61
|
-
: () => { };
|
|
62
|
-
const watchHandler = await getWatchHandler(options, {
|
|
63
|
-
analyzedFiles,
|
|
64
|
-
analyzeSourceFile,
|
|
65
|
-
chief,
|
|
66
|
-
collector,
|
|
67
|
-
analyze: reAnalyze,
|
|
68
|
-
factory,
|
|
69
|
-
graph,
|
|
70
|
-
isIgnored,
|
|
71
|
-
onUpdate,
|
|
72
|
-
unreferencedFiles,
|
|
73
|
-
});
|
|
74
|
-
watch('.', { recursive: true }, watchHandler);
|
|
75
|
-
}
|
|
76
|
-
const { issues, counters, tagHints, configurationHints } = collector.getIssues();
|
|
77
|
-
if (options.isFix) {
|
|
78
|
-
const touchedFiles = await fixer.fixIssues(issues);
|
|
79
|
-
if (options.isFormat) {
|
|
80
|
-
const report = await formatly(Array.from(touchedFiles));
|
|
81
|
-
if (report.ran && report.result && (report.result.runner === 'virtual' || report.result.code === 0)) {
|
|
82
|
-
debugLogArray('*', `Formatted files using ${report.formatter.name} (${report.formatter.runner})`, touchedFiles);
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
debugLogObject('*', 'Formatting files failed', report);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
if (!options.isWatch)
|
|
90
|
-
streamer.clear();
|
|
91
|
-
return {
|
|
92
|
-
issues,
|
|
93
|
-
counters,
|
|
94
|
-
tagHints,
|
|
95
|
-
configurationHints,
|
|
96
|
-
includedWorkspaceDirs: chief.includedWorkspaces.map(w => w.dir),
|
|
97
|
-
};
|
|
98
|
-
};
|
|
1
|
+
import { run } from './run.js';
|
|
2
|
+
export const main = async (options) => (await run(options)).results;
|
|
@@ -36,8 +36,8 @@ const resolveConfig = async (config, options) => {
|
|
|
36
36
|
}
|
|
37
37
|
return opts.isProduction ? toProductionEntry(normalizedPath) : toEntry(normalizedPath);
|
|
38
38
|
};
|
|
39
|
-
for (const [configName, entriesByOption] of entriesByOptionByConfig
|
|
40
|
-
for (const [option, entries] of entriesByOption
|
|
39
|
+
for (const [configName, entriesByOption] of entriesByOptionByConfig) {
|
|
40
|
+
for (const [option, entries] of entriesByOption) {
|
|
41
41
|
for (const entry of entries) {
|
|
42
42
|
inputs.add(toInput(entry, {
|
|
43
43
|
isProduction: isBuildTarget && configName === PRODUCTION_CONFIG_NAME,
|
|
@@ -46,7 +46,7 @@ const resolveConfig = async (config, options) => {
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
for (const [option, entries] of defaultEntriesByOption
|
|
49
|
+
for (const [option, entries] of defaultEntriesByOption) {
|
|
50
50
|
for (const entry of entries) {
|
|
51
51
|
inputs.add(toInput(entry, {
|
|
52
52
|
isProduction: isBuildTarget && !productionEntriesByOption.get(option)?.length,
|
|
@@ -6,7 +6,6 @@ const enablers = ['astro'];
|
|
|
6
6
|
const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
|
|
7
7
|
export const config = ['astro.config.{js,cjs,mjs,ts,mts}'];
|
|
8
8
|
const entry = ['src/content/config.ts', 'src/content.config.ts'];
|
|
9
|
-
const project = ['src/**/*'];
|
|
10
9
|
const production = [
|
|
11
10
|
'src/pages/**/*.{astro,mdx,js,ts}',
|
|
12
11
|
'!src/pages/**/_*',
|
|
@@ -42,6 +41,5 @@ const plugin = {
|
|
|
42
41
|
production,
|
|
43
42
|
resolveFromAST,
|
|
44
43
|
resolve,
|
|
45
|
-
project,
|
|
46
44
|
};
|
|
47
45
|
export default plugin;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { toProductionEntry } from '../../util/input.js';
|
|
1
|
+
import { toDependency, toProductionEntry } from '../../util/input.js';
|
|
2
2
|
import { hasDependency } from '../../util/plugin.js';
|
|
3
|
-
import { getPageExtensions } from './resolveFromAST.js';
|
|
3
|
+
import { getMdxPlugins, getPageExtensions } from './resolveFromAST.js';
|
|
4
4
|
const title = 'Next.js';
|
|
5
5
|
const enablers = ['next'];
|
|
6
6
|
const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
|
|
@@ -26,7 +26,8 @@ const resolveFromAST = sourceFile => {
|
|
|
26
26
|
const pageExtensions = getPageExtensions(sourceFile);
|
|
27
27
|
const extensions = pageExtensions.length > 0 ? pageExtensions : defaultPageExtensions;
|
|
28
28
|
const patterns = getEntryFilePatterns(extensions);
|
|
29
|
-
|
|
29
|
+
const mdxPlugins = getMdxPlugins(sourceFile);
|
|
30
|
+
return [...patterns.map(id => toProductionEntry(id)), ...Array.from(mdxPlugins).map(id => toDependency(id))];
|
|
30
31
|
};
|
|
31
32
|
const plugin = {
|
|
32
33
|
title,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
|
-
import { getPropertyValues } from '../../typescript/ast-helpers.js';
|
|
2
|
+
import { getDefaultImportName, getImportMap, getPropertyValues, stripQuotes } from '../../typescript/ast-helpers.js';
|
|
3
3
|
export const getPageExtensions = (sourceFile) => {
|
|
4
4
|
const pageExtensions = new Set();
|
|
5
5
|
function visit(node) {
|
|
@@ -13,3 +13,44 @@ export const getPageExtensions = (sourceFile) => {
|
|
|
13
13
|
visit(sourceFile);
|
|
14
14
|
return Array.from(pageExtensions);
|
|
15
15
|
};
|
|
16
|
+
const isNamedProp = (prop, name) => ts.isPropertyAssignment(prop) && prop.name.getText() === name;
|
|
17
|
+
export const getMdxPlugins = (sourceFile) => {
|
|
18
|
+
const plugins = new Set();
|
|
19
|
+
const importMap = getImportMap(sourceFile);
|
|
20
|
+
const mdxImportName = getDefaultImportName(importMap, '@next/mdx');
|
|
21
|
+
if (!mdxImportName)
|
|
22
|
+
return plugins;
|
|
23
|
+
function visit(node) {
|
|
24
|
+
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === mdxImportName) {
|
|
25
|
+
if (node.arguments.length > 0 && ts.isObjectLiteralExpression(node.arguments[0])) {
|
|
26
|
+
const options = node.arguments[0]?.properties.find(prop => isNamedProp(prop, 'options'));
|
|
27
|
+
if (options && ts.isPropertyAssignment(options)) {
|
|
28
|
+
if (ts.isObjectLiteralExpression(options.initializer)) {
|
|
29
|
+
for (const pluginType of ['remarkPlugins', 'rehypePlugins', 'recmaPlugins']) {
|
|
30
|
+
const props = options.initializer.properties.find(prop => isNamedProp(prop, pluginType));
|
|
31
|
+
if (props && ts.isPropertyAssignment(props)) {
|
|
32
|
+
if (ts.isArrayLiteralExpression(props.initializer)) {
|
|
33
|
+
for (const element of props.initializer.elements) {
|
|
34
|
+
if (ts.isStringLiteral(element)) {
|
|
35
|
+
plugins.add(stripQuotes(element.text));
|
|
36
|
+
}
|
|
37
|
+
else if (ts.isArrayLiteralExpression(element) && element.elements.length > 0) {
|
|
38
|
+
const firstElement = element.elements[0];
|
|
39
|
+
if (ts.isStringLiteral(firstElement)) {
|
|
40
|
+
plugins.add(stripQuotes(firstElement.text));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
return ts.forEachChild(node, visit) ?? false;
|
|
53
|
+
}
|
|
54
|
+
visit(sourceFile);
|
|
55
|
+
return plugins;
|
|
56
|
+
};
|