knip 0.11.2 → 0.12.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/runner.js CHANGED
@@ -1,29 +1,22 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.findIssues = void 0;
7
- const node_path_1 = __importDefault(require("node:path"));
8
- const ts_morph_1 = require("ts-morph");
9
- const ts_morph_helpers_1 = require("ts-morph-helpers");
10
- const project_1 = require("./util/project");
11
- const type_1 = require("./util/type");
12
- const dependencies_1 = require("./util/dependencies");
13
- const debug_1 = require("./util/debug");
14
- const progress_1 = require("./progress");
15
- async function findIssues(configuration) {
16
- const { workingDir, report, isDev, jsDocOptions, debug } = configuration;
1
+ import path from 'node:path';
2
+ import { ts } from 'ts-morph';
3
+ import { partitionSourceFiles, _findDuplicateExportedNames, _hasReferencingDefaultImport, _findReferencingNamespaceNodes, _getExportedDeclarations, _findReferences, } from './util/project.js';
4
+ import { getType } from './util/type.js';
5
+ import { getDependencyAnalyzer } from './util/dependencies.js';
6
+ import { debugLogSourceFiles } from './util/debug.js';
7
+ import { getCountersUpdater, getMessageUpdater } from './progress.js';
8
+ export async function findIssues(configuration) {
9
+ const { workingDir, report, jsDocOptions, debug } = configuration;
17
10
  const { entryFiles, productionFiles, projectFiles, isIncludeEntryFiles } = configuration;
18
11
  const { manifestPath } = configuration;
19
- const updateMessage = (0, progress_1.getMessageUpdater)(configuration);
20
- const { getUnresolvedDependencies, getUnusedDependencies, getUnusedDevDependencies } = (0, dependencies_1.getDependencyAnalyzer)(configuration);
21
- const [usedProductionFiles, unreferencedProductionFiles] = (0, project_1.partitionSourceFiles)(projectFiles, productionFiles);
22
- const [usedEntryFiles, usedNonEntryFiles] = (0, project_1.partitionSourceFiles)(usedProductionFiles, entryFiles);
23
- (0, debug_1.debugLogSourceFiles)(debug, 1, 'Used production files', usedProductionFiles);
24
- (0, debug_1.debugLogSourceFiles)(debug, 1, 'Unreferenced production files', unreferencedProductionFiles);
25
- (0, debug_1.debugLogSourceFiles)(debug, 1, 'Used entry files', usedEntryFiles);
26
- (0, debug_1.debugLogSourceFiles)(debug, 1, 'Used non-entry files', usedNonEntryFiles);
12
+ const updateMessage = getMessageUpdater(configuration);
13
+ const { _findUnresolvedDependencies, getUnusedDependencies, getUnusedDevDependencies } = getDependencyAnalyzer(configuration);
14
+ const [usedProductionFiles, unreferencedProductionFiles] = partitionSourceFiles(projectFiles, productionFiles);
15
+ const [usedEntryFiles, usedNonEntryFiles] = partitionSourceFiles(usedProductionFiles, entryFiles);
16
+ debugLogSourceFiles(debug, 1, 'Used production files', usedProductionFiles);
17
+ debugLogSourceFiles(debug, 1, 'Unreferenced production files', unreferencedProductionFiles);
18
+ debugLogSourceFiles(debug, 1, 'Used entry files', usedEntryFiles);
19
+ debugLogSourceFiles(debug, 1, 'Used non-entry files', usedNonEntryFiles);
27
20
  const issues = {
28
21
  files: new Set(unreferencedProductionFiles.map(file => file.getFilePath())),
29
22
  dependencies: {},
@@ -48,10 +41,10 @@ async function findIssues(configuration) {
48
41
  processed: issues.files.size,
49
42
  total: projectFiles.length,
50
43
  };
51
- const updateCounters = (0, progress_1.getCountersUpdater)(configuration, counters);
44
+ const updateCounters = getCountersUpdater(configuration, counters);
52
45
  const addSymbolIssue = (issueType, issue) => {
53
46
  const { filePath, symbol } = issue;
54
- const key = node_path_1.default.relative(workingDir, filePath).replace(/\\/g, '/');
47
+ const key = path.relative(workingDir, filePath).replace(/\\/g, '/');
55
48
  issues[issueType][key] = issues[issueType][key] ?? {};
56
49
  issues[issueType][key][symbol] = issue;
57
50
  counters[issueType]++;
@@ -69,12 +62,11 @@ async function findIssues(configuration) {
69
62
  counters.processed++;
70
63
  const filePath = sourceFile.getFilePath();
71
64
  if (report.dependencies || report.unlisted) {
72
- const unresolvedDependencies = getUnresolvedDependencies(sourceFile);
65
+ const unresolvedDependencies = _findUnresolvedDependencies(sourceFile);
73
66
  unresolvedDependencies.forEach(issue => addSymbolIssue('unlisted', issue));
74
67
  }
75
- const exportDeclarations = sourceFile.getExportedDeclarations();
76
68
  if (report.duplicates) {
77
- const duplicateExports = (0, ts_morph_helpers_1.findDuplicateExportedNames)(sourceFile);
69
+ const duplicateExports = _findDuplicateExportedNames(sourceFile);
78
70
  duplicateExports.forEach(symbols => {
79
71
  const symbol = symbols.join('|');
80
72
  addSymbolIssue('duplicates', { filePath, symbol, symbols });
@@ -83,6 +75,7 @@ async function findIssues(configuration) {
83
75
  if (!isIncludeEntryFiles && usedEntryFiles.includes(sourceFile))
84
76
  return;
85
77
  if (report.exports || report.types || report.nsExports || report.nsTypes) {
78
+ const exportDeclarations = _getExportedDeclarations(sourceFile);
86
79
  if (!isIncludeEntryFiles) {
87
80
  const uniqueExportedSymbols = new Set([...exportDeclarations.values()].flat());
88
81
  if (uniqueExportedSymbols.size === 1)
@@ -90,41 +83,41 @@ async function findIssues(configuration) {
90
83
  }
91
84
  exportDeclarations.forEach(declarations => {
92
85
  declarations.forEach(declaration => {
93
- const type = (0, type_1.getType)(declaration);
86
+ const type = getType(declaration);
94
87
  if (!report.nsExports && !report.nsTypes) {
95
88
  if (!report.types && type)
96
89
  return;
97
90
  if (!report.exports && !type)
98
91
  return;
99
92
  }
100
- if (jsDocOptions.isReadPublicTag && ts_morph_1.ts.getJSDocPublicTag(declaration.compilerNode))
93
+ if (jsDocOptions.isReadPublicTag && ts.getJSDocPublicTag(declaration.compilerNode))
101
94
  return;
102
95
  let identifier;
103
96
  let fakeIdentifier;
104
- if (declaration.isKind(ts_morph_1.ts.SyntaxKind.Identifier)) {
97
+ if (declaration.isKind(ts.SyntaxKind.Identifier)) {
105
98
  identifier = declaration;
106
99
  }
107
- else if (declaration.isKind(ts_morph_1.ts.SyntaxKind.ArrowFunction) ||
108
- declaration.isKind(ts_morph_1.ts.SyntaxKind.ObjectLiteralExpression) ||
109
- declaration.isKind(ts_morph_1.ts.SyntaxKind.ArrayLiteralExpression) ||
110
- declaration.isKind(ts_morph_1.ts.SyntaxKind.StringLiteral) ||
111
- declaration.isKind(ts_morph_1.ts.SyntaxKind.NumericLiteral)) {
112
- if (!(0, ts_morph_helpers_1.hasReferencingDefaultImport)(sourceFile)) {
100
+ else if (declaration.isKind(ts.SyntaxKind.ArrowFunction) ||
101
+ declaration.isKind(ts.SyntaxKind.ObjectLiteralExpression) ||
102
+ declaration.isKind(ts.SyntaxKind.ArrayLiteralExpression) ||
103
+ declaration.isKind(ts.SyntaxKind.StringLiteral) ||
104
+ declaration.isKind(ts.SyntaxKind.NumericLiteral)) {
105
+ if (!_hasReferencingDefaultImport(sourceFile)) {
113
106
  fakeIdentifier = 'default';
114
107
  }
115
108
  }
116
- else if (declaration.isKind(ts_morph_1.ts.SyntaxKind.FunctionDeclaration) ||
117
- declaration.isKind(ts_morph_1.ts.SyntaxKind.ClassDeclaration) ||
118
- declaration.isKind(ts_morph_1.ts.SyntaxKind.TypeAliasDeclaration) ||
119
- declaration.isKind(ts_morph_1.ts.SyntaxKind.InterfaceDeclaration) ||
120
- declaration.isKind(ts_morph_1.ts.SyntaxKind.EnumDeclaration)) {
121
- identifier = declaration.getFirstChildByKindOrThrow(ts_morph_1.ts.SyntaxKind.Identifier);
109
+ else if (declaration.isKind(ts.SyntaxKind.FunctionDeclaration) ||
110
+ declaration.isKind(ts.SyntaxKind.ClassDeclaration) ||
111
+ declaration.isKind(ts.SyntaxKind.TypeAliasDeclaration) ||
112
+ declaration.isKind(ts.SyntaxKind.InterfaceDeclaration) ||
113
+ declaration.isKind(ts.SyntaxKind.EnumDeclaration)) {
114
+ identifier = declaration.getFirstChildByKindOrThrow(ts.SyntaxKind.Identifier);
122
115
  }
123
- else if (declaration.isKind(ts_morph_1.ts.SyntaxKind.PropertyAccessExpression)) {
124
- identifier = declaration.getLastChildByKindOrThrow(ts_morph_1.ts.SyntaxKind.Identifier);
116
+ else if (declaration.isKind(ts.SyntaxKind.PropertyAccessExpression)) {
117
+ identifier = declaration.getLastChildByKindOrThrow(ts.SyntaxKind.Identifier);
125
118
  }
126
119
  else {
127
- identifier = declaration.getFirstDescendantByKind(ts_morph_1.ts.SyntaxKind.Identifier);
120
+ identifier = declaration.getFirstDescendantByKind(ts.SyntaxKind.Identifier);
128
121
  }
129
122
  if (identifier || fakeIdentifier) {
130
123
  const identifierText = fakeIdentifier ?? identifier?.getText() ?? '*';
@@ -136,7 +129,7 @@ async function findIssues(configuration) {
136
129
  return;
137
130
  if (report.nsTypes && issues.nsTypes[filePath]?.[identifierText])
138
131
  return;
139
- const refs = identifier?.findReferences() ?? [];
132
+ const refs = _findReferences(identifier);
140
133
  if (refs.length === 0) {
141
134
  addSymbolIssue('exports', { filePath, symbol: identifierText });
142
135
  }
@@ -145,7 +138,7 @@ async function findIssues(configuration) {
145
138
  const isReferencedOnlyBySelf = refFiles.size === 1 && [...refFiles][0] === filePath;
146
139
  if (!isReferencedOnlyBySelf)
147
140
  return;
148
- if ((0, ts_morph_helpers_1.findReferencingNamespaceNodes)(sourceFile).length > 0) {
141
+ if (_findReferencingNamespaceNodes(sourceFile).length > 0) {
149
142
  if (type) {
150
143
  addSymbolIssue('nsTypes', { filePath, symbol: identifierText, symbolType: type });
151
144
  }
@@ -169,12 +162,11 @@ async function findIssues(configuration) {
169
162
  if (report.dependencies) {
170
163
  const unusedDependencies = getUnusedDependencies();
171
164
  unusedDependencies.forEach(symbol => addSymbolIssue('dependencies', { filePath: manifestPath, symbol }));
172
- if (isDev) {
173
- const unusedDevDependencies = getUnusedDevDependencies();
174
- unusedDevDependencies.forEach(symbol => addSymbolIssue('devDependencies', { filePath: manifestPath, symbol }));
175
- }
165
+ }
166
+ if (report.devDependencies) {
167
+ const unusedDevDependencies = getUnusedDevDependencies();
168
+ unusedDevDependencies.forEach(symbol => addSymbolIssue('devDependencies', { filePath: manifestPath, symbol }));
176
169
  }
177
170
  updateCounters();
178
171
  return { issues, counters };
179
172
  }
180
- exports.findIssues = findIssues;
package/dist/types.js CHANGED
@@ -1,2 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ export {};
@@ -1,4 +1,4 @@
1
- import type { ImportedConfiguration, LocalConfiguration, Report } from '../types';
1
+ import type { ImportedConfiguration, LocalConfiguration, Report } from '../types.js';
2
2
  export declare const resolveConfig: (importedConfiguration: ImportedConfiguration, options?: {
3
3
  workingDir?: string;
4
4
  isDev?: boolean;
@@ -1,18 +1,12 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.resolveIncludedIssueTypes = exports.resolveConfig = void 0;
7
- const micromatch_1 = __importDefault(require("micromatch"));
8
- const resolveConfig = (importedConfiguration, options) => {
1
+ import micromatch from 'micromatch';
2
+ export const resolveConfig = (importedConfiguration, options) => {
9
3
  if (!importedConfiguration)
10
4
  return;
11
5
  let resolvedConfig = importedConfiguration;
12
6
  const { workingDir, isDev } = options ?? {};
13
7
  const configKeys = Object.keys(importedConfiguration);
14
8
  if (workingDir && !('projectFiles' in importedConfiguration)) {
15
- const importedConfigKey = configKeys.find(pattern => micromatch_1.default.isMatch(workingDir.replace(/\/$/, ''), pattern));
9
+ const importedConfigKey = configKeys.find(pattern => micromatch.isMatch(workingDir.replace(/\/$/, ''), pattern));
16
10
  if (importedConfigKey) {
17
11
  resolvedConfig = importedConfiguration[importedConfigKey];
18
12
  }
@@ -27,17 +21,26 @@ const resolveConfig = (importedConfiguration, options) => {
27
21
  resolvedConfig.dev = Boolean(typeof resolvedConfig.dev === 'boolean' ? resolvedConfig.dev : isDev);
28
22
  return resolvedConfig;
29
23
  };
30
- exports.resolveConfig = resolveConfig;
31
- const resolveIncludedIssueTypes = (includeArg, excludeArg, resolvedConfig) => {
32
- const deps = resolvedConfig?.dev ? ['dependencies', 'devDependencies'] : ['dependencies'];
33
- const groups = ['files', ...deps, 'unlisted', 'exports', 'types', 'nsExports', 'nsTypes', 'duplicates'];
24
+ const ISSUE_TYPES = [
25
+ 'files',
26
+ 'dependencies',
27
+ 'devDependencies',
28
+ 'unlisted',
29
+ 'exports',
30
+ 'types',
31
+ 'nsExports',
32
+ 'nsTypes',
33
+ 'duplicates',
34
+ ];
35
+ export const resolveIncludedIssueTypes = (includeArg, excludeArg, resolvedConfig) => {
34
36
  const normalizedIncludesArg = includeArg.map(value => value.split(',')).flat();
35
37
  const normalizedExcludesArg = excludeArg.map(value => value.split(',')).flat();
36
38
  const excludes = (resolvedConfig?.exclude ?? []).filter(exclude => !normalizedIncludesArg.includes(exclude));
37
39
  const includes = (resolvedConfig?.include ?? []).filter(include => !normalizedExcludesArg.includes(include));
38
40
  const include = [normalizedIncludesArg, includes].flat();
39
41
  const exclude = [normalizedExcludesArg, excludes].flat();
40
- const included = (include.length > 0 ? include : groups).filter(group => !exclude.includes(group));
41
- return groups.reduce((types, group) => ((types[group] = included.includes(group)), types), {});
42
+ include.includes('dependencies') && include.push('devDependencies');
43
+ !resolvedConfig?.dev && exclude.push('devDependencies');
44
+ const included = (include.length > 0 ? include : ISSUE_TYPES).filter(group => !exclude.includes(group));
45
+ return ISSUE_TYPES.reduce((types, group) => ((types[group] = included.includes(group)), types), {});
42
46
  };
43
- exports.resolveIncludedIssueTypes = resolveIncludedIssueTypes;
@@ -1,19 +1,12 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.debugLogSourceFiles = exports.debugLogFiles = exports.debugLogObject = void 0;
7
- const node_util_1 = __importDefault(require("node:util"));
8
- const logArray = (collection) => console.log(node_util_1.default.inspect(collection, { maxArrayLength: null }));
9
- const debugLogObject = (debug, minimumLevel, name, obj) => {
1
+ import util from 'node:util';
2
+ const logArray = (collection) => console.log(util.inspect(collection, { maxArrayLength: null }));
3
+ export const debugLogObject = (debug, minimumLevel, name, obj) => {
10
4
  if (minimumLevel > debug.level)
11
5
  return;
12
6
  console.log(`[knip] ${name}:`);
13
- console.log(node_util_1.default.inspect(obj, { depth: null, colors: true }));
7
+ console.log(util.inspect(obj, { depth: null, colors: true }));
14
8
  };
15
- exports.debugLogObject = debugLogObject;
16
- const debugLogFiles = (debug, minimumLevel, name, filePaths) => {
9
+ export const debugLogFiles = (debug, minimumLevel, name, filePaths) => {
17
10
  if (minimumLevel > debug.level)
18
11
  return;
19
12
  console.debug(`[knip] ${name} (${filePaths.length}):`);
@@ -21,8 +14,7 @@ const debugLogFiles = (debug, minimumLevel, name, filePaths) => {
21
14
  logArray(filePaths);
22
15
  }
23
16
  };
24
- exports.debugLogFiles = debugLogFiles;
25
- const debugLogSourceFiles = (debug, minimumLevel, name, sourceFiles) => {
17
+ export const debugLogSourceFiles = (debug, minimumLevel, name, sourceFiles) => {
26
18
  if (minimumLevel > debug.level)
27
19
  return;
28
20
  console.debug(`[knip] ${name} (${sourceFiles.length})`);
@@ -31,7 +23,6 @@ const debugLogSourceFiles = (debug, minimumLevel, name, sourceFiles) => {
31
23
  logArray(files);
32
24
  }
33
25
  };
34
- exports.debugLogSourceFiles = debugLogSourceFiles;
35
26
  const debugLogDiff = (debug, minimumLevel, name, arrA, arrB) => {
36
27
  if (minimumLevel > debug.level)
37
28
  return;
@@ -1,7 +1,7 @@
1
1
  import type { SourceFile } from 'ts-morph';
2
- import type { Configuration, Issue } from '../types';
2
+ import type { Configuration, Issue } from '../types.js';
3
3
  export declare const getDependencyAnalyzer: (configuration: Configuration) => {
4
- getUnresolvedDependencies: (sourceFile: SourceFile) => Set<Issue>;
4
+ _findUnresolvedDependencies: (sourceFile: SourceFile) => Set<Issue>;
5
5
  getUnusedDependencies: () => string[];
6
6
  getUnusedDevDependencies: () => string[];
7
7
  };
@@ -1,21 +1,16 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getDependencyAnalyzer = void 0;
7
- const ts_morph_1 = require("ts-morph");
8
- const is_builtin_module_1 = __importDefault(require("is-builtin-module"));
9
- const micromatch_1 = __importDefault(require("micromatch"));
10
- const ts_morph_helpers_1 = require("ts-morph-helpers");
1
+ import { isBuiltin } from 'node:module';
2
+ import { ts } from 'ts-morph';
3
+ import micromatch from 'micromatch';
4
+ import { findCallExpressionsByName } from 'ts-morph-helpers';
5
+ import { timerify } from './performance.js';
11
6
  const compact = (collection) => Array.from(new Set(collection)).filter((value) => Boolean(value));
12
- const findRequireModuleSpecifiers = (sourceFile) => (0, ts_morph_helpers_1.findCallExpressionsByName)(sourceFile, 'require').map(expression => expression.getFirstDescendantByKind(ts_morph_1.ts.SyntaxKind.StringLiteral));
7
+ const findRequireModuleSpecifiers = (sourceFile) => findCallExpressionsByName(sourceFile, 'require').map(expression => expression.getFirstDescendantByKind(ts.SyntaxKind.StringLiteral));
13
8
  const isExternalDependency = (moduleSpecifier, tsConfigPathGlobs) => {
14
9
  if (moduleSpecifier.startsWith('.'))
15
10
  return false;
16
- if ((0, is_builtin_module_1.default)(moduleSpecifier))
11
+ if (isBuiltin(moduleSpecifier))
17
12
  return false;
18
- if (tsConfigPathGlobs.length > 0 && micromatch_1.default.isMatch(moduleSpecifier, tsConfigPathGlobs))
13
+ if (tsConfigPathGlobs.length > 0 && micromatch.isMatch(moduleSpecifier, tsConfigPathGlobs))
19
14
  return false;
20
15
  return true;
21
16
  };
@@ -23,11 +18,11 @@ const resolvePackageName = (moduleSpecifier) => {
23
18
  const parts = moduleSpecifier.split('/').slice(0, 2);
24
19
  return moduleSpecifier.startsWith('@') ? parts.join('/') : parts[0];
25
20
  };
26
- const getDependencyAnalyzer = (configuration) => {
21
+ export const getDependencyAnalyzer = (configuration) => {
27
22
  const { dependencies, devDependencies, peerDependencies, optionalDependencies, tsConfigPathGlobs } = configuration;
28
23
  const productionDependencies = [...dependencies, ...peerDependencies, ...optionalDependencies];
29
24
  const referencedDependencies = new Set();
30
- const getUnresolvedDependencies = (sourceFile) => {
25
+ const findUnresolvedDependencies = (sourceFile) => {
31
26
  const unresolvedDependencies = new Set();
32
27
  const importLiterals = sourceFile.getImportStringLiterals();
33
28
  const requireCallExpressions = findRequireModuleSpecifiers(sourceFile);
@@ -47,6 +42,9 @@ const getDependencyAnalyzer = (configuration) => {
47
42
  };
48
43
  const getUnusedDependencies = () => productionDependencies.filter(dependency => !referencedDependencies.has(dependency));
49
44
  const getUnusedDevDependencies = () => devDependencies.filter(dependency => !referencedDependencies.has(dependency));
50
- return { getUnresolvedDependencies, getUnusedDependencies, getUnusedDevDependencies };
45
+ return {
46
+ _findUnresolvedDependencies: timerify(findUnresolvedDependencies),
47
+ getUnusedDependencies,
48
+ getUnusedDevDependencies,
49
+ };
51
50
  };
52
- exports.getDependencyAnalyzer = getDependencyAnalyzer;
@@ -1,6 +1,2 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ConfigurationError = void 0;
4
- class ConfigurationError extends Error {
1
+ export class ConfigurationError extends Error {
5
2
  }
6
- exports.ConfigurationError = ConfigurationError;
package/dist/util/fs.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export declare const isFile: (filePath: string) => Promise<boolean>;
2
2
  export declare const findFile: (cwd: string, workingDir: string, fileName: string) => Promise<string | undefined>;
3
+ export declare const loadJSON: (filePath: string) => any;
package/dist/util/fs.js CHANGED
@@ -1,31 +1,26 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.findFile = exports.isFile = void 0;
7
- const promises_1 = __importDefault(require("node:fs/promises"));
8
- const node_path_1 = __importDefault(require("node:path"));
9
- const isFile = async (filePath) => {
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { createRequire } from 'node:module';
4
+ const require = createRequire(process.cwd());
5
+ export const isFile = async (filePath) => {
10
6
  try {
11
- const stats = await promises_1.default.stat(filePath);
7
+ const stats = await fs.stat(filePath);
12
8
  return stats.isFile();
13
9
  }
14
10
  catch {
15
11
  return false;
16
12
  }
17
13
  };
18
- exports.isFile = isFile;
19
- const findFile = async (cwd, workingDir, fileName) => {
20
- const filePath = node_path_1.default.join(workingDir, fileName);
21
- if (await (0, exports.isFile)(filePath)) {
14
+ export const findFile = async (cwd, workingDir, fileName) => {
15
+ const filePath = path.join(workingDir, fileName);
16
+ if (await isFile(filePath)) {
22
17
  return filePath;
23
18
  }
24
19
  else {
25
20
  if (cwd === workingDir)
26
21
  return;
27
- const parentDir = node_path_1.default.resolve(workingDir, '..');
28
- return (0, exports.findFile)(cwd, parentDir, fileName);
22
+ const parentDir = path.resolve(workingDir, '..');
23
+ return findFile(cwd, parentDir, fileName);
29
24
  }
30
25
  };
31
- exports.findFile = findFile;
26
+ export const loadJSON = (filePath) => require(filePath);
@@ -1,4 +1,4 @@
1
- export declare const glob: ({ cwd, workingDir, patterns, ignore, gitignore, }: {
1
+ export declare const _glob: ({ cwd, workingDir, patterns, ignore, gitignore, }: {
2
2
  cwd: string;
3
3
  workingDir: string;
4
4
  patterns: string[];
package/dist/util/glob.js CHANGED
@@ -1,32 +1,20 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.glob = void 0;
7
- const node_path_1 = __importDefault(require("node:path"));
8
- let _globby;
9
- const globProxy = async function (patterns, options) {
10
- if (!_globby) {
11
- const { globby } = await eval('import("globby")');
12
- _globby = globby;
13
- }
14
- return _globby(patterns, options);
15
- };
16
- const ensurePosixPath = (value) => value.split(node_path_1.default.sep).join(node_path_1.default.posix.sep);
1
+ import path from 'node:path';
2
+ import { globby } from 'globby';
3
+ import { timerify } from './performance.js';
4
+ const ensurePosixPath = (value) => value.split(path.sep).join(path.posix.sep);
17
5
  const prependDirToPattern = (workingDir, pattern) => {
18
6
  if (pattern.startsWith('!'))
19
- return '!' + node_path_1.default.posix.join(workingDir, pattern.slice(1));
20
- return node_path_1.default.posix.join(workingDir, pattern);
7
+ return '!' + path.posix.join(workingDir, pattern.slice(1));
8
+ return path.posix.join(workingDir, pattern);
21
9
  };
22
10
  const glob = async ({ cwd, workingDir, patterns, ignore, gitignore, }) => {
23
11
  const cwdPosix = ensurePosixPath(cwd);
24
12
  const workingDirPosix = ensurePosixPath(workingDir);
25
- return globProxy(patterns.map(pattern => prependDirToPattern(node_path_1.default.posix.relative(cwdPosix, workingDirPosix), pattern)), {
13
+ return globby(patterns.map(pattern => prependDirToPattern(path.posix.relative(cwdPosix, workingDirPosix), pattern)), {
26
14
  cwd,
27
15
  ignore: [...ignore, '**/node_modules/**'],
28
16
  gitignore,
29
17
  absolute: true,
30
18
  });
31
19
  };
32
- exports.glob = glob;
20
+ export const _glob = timerify(glob);
@@ -0,0 +1,24 @@
1
+ declare const _default: {
2
+ values: {
3
+ help: boolean | undefined;
4
+ config: string | undefined;
5
+ tsConfig: string | undefined;
6
+ dir: string | undefined;
7
+ include: string[] | undefined;
8
+ exclude: string[] | undefined;
9
+ ignore: string[] | undefined;
10
+ 'no-gitignore': boolean | undefined;
11
+ dev: boolean | undefined;
12
+ 'include-entry-files': boolean | undefined;
13
+ 'no-progress': boolean | undefined;
14
+ 'max-issues': string | undefined;
15
+ reporter: string | undefined;
16
+ 'reporter-options': string | undefined;
17
+ jsdoc: string[] | undefined;
18
+ debug: boolean | undefined;
19
+ 'debug-level': string | undefined;
20
+ performance: boolean | undefined;
21
+ };
22
+ positionals: [];
23
+ };
24
+ export default _default;
@@ -0,0 +1,23 @@
1
+ import { parseArgs } from 'node:util';
2
+ export default parseArgs({
3
+ options: {
4
+ help: { type: 'boolean' },
5
+ config: { type: 'string', short: 'c' },
6
+ tsConfig: { type: 'string', short: 't' },
7
+ dir: { type: 'string' },
8
+ include: { type: 'string', multiple: true },
9
+ exclude: { type: 'string', multiple: true },
10
+ ignore: { type: 'string', multiple: true },
11
+ 'no-gitignore': { type: 'boolean' },
12
+ dev: { type: 'boolean' },
13
+ 'include-entry-files': { type: 'boolean' },
14
+ 'no-progress': { type: 'boolean' },
15
+ 'max-issues': { type: 'string' },
16
+ reporter: { type: 'string' },
17
+ 'reporter-options': { type: 'string' },
18
+ jsdoc: { type: 'string', multiple: true },
19
+ debug: { type: 'boolean' },
20
+ 'debug-level': { type: 'string' },
21
+ performance: { type: 'boolean' },
22
+ },
23
+ });
package/dist/util/path.js CHANGED
@@ -1,10 +1,3 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.relative = void 0;
7
- const node_path_1 = __importDefault(require("node:path"));
1
+ import path from 'node:path';
8
2
  const cwd = process.cwd();
9
- const relative = (to) => node_path_1.default.relative(cwd, to);
10
- exports.relative = relative;
3
+ export const relative = (to) => path.relative(cwd, to);
@@ -0,0 +1,22 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ import { PerformanceObserver, PerformanceEntry } from 'node:perf_hooks';
3
+ import EasyTable from 'easy-table';
4
+ import type { TimerifyOptions } from 'node:perf_hooks';
5
+ declare type Timerify = <T extends (...params: any[]) => any>(fn: T, options?: TimerifyOptions) => T;
6
+ export declare const timerify: Timerify;
7
+ declare class Performance {
8
+ enabled: boolean;
9
+ entries: PerformanceEntry[];
10
+ instanceId?: number;
11
+ observer?: PerformanceObserver;
12
+ constructor(enabled: boolean);
13
+ start(name: string): void;
14
+ end(name: string): void;
15
+ getEntriesByName(): Record<string, number[]>;
16
+ getTable(sort?: string[]): EasyTable;
17
+ flush(): Promise<void>;
18
+ print(): Promise<void>;
19
+ reset(): void;
20
+ }
21
+ export declare const measure: Performance;
22
+ export {};
@@ -0,0 +1,81 @@
1
+ import { performance, PerformanceObserver } from 'node:perf_hooks';
2
+ import Summary from 'summary';
3
+ import EasyTable from 'easy-table';
4
+ import parsedArgs from './parseArgs.js';
5
+ const { values } = parsedArgs;
6
+ const { performance: isEnabled = false } = values;
7
+ export const timerify = fn => (isEnabled ? performance.timerify(fn) : fn);
8
+ class Performance {
9
+ enabled;
10
+ entries = [];
11
+ instanceId;
12
+ observer;
13
+ constructor(enabled) {
14
+ if (enabled) {
15
+ this.instanceId = Math.floor(performance.now() * 100);
16
+ this.observer = new PerformanceObserver(items => {
17
+ items.getEntries().forEach(entry => {
18
+ this.entries.push(entry);
19
+ });
20
+ });
21
+ this.observer.observe({ entryTypes: ['measure', 'function'] });
22
+ }
23
+ this.enabled = enabled;
24
+ }
25
+ start(name) {
26
+ if (!this.enabled)
27
+ return;
28
+ const id = `${this.instanceId}:${name}`;
29
+ performance.mark(`${id}:start`);
30
+ }
31
+ end(name) {
32
+ if (!this.enabled)
33
+ return;
34
+ const id = `${this.instanceId}:${name}`;
35
+ performance.mark(`${id}:end`);
36
+ performance.measure(id, `${id}:start`, `${id}:end`);
37
+ performance.clearMarks(`${id}:start`);
38
+ performance.clearMarks(`${id}:end`);
39
+ }
40
+ getEntriesByName() {
41
+ return this.entries.reduce((entries, entry) => {
42
+ const name = entry.name.replace(`${this.instanceId}:`, '');
43
+ entries[name] = entries[name] ?? [];
44
+ entries[name].push(entry.duration);
45
+ return entries;
46
+ }, {});
47
+ }
48
+ getTable(sort = ['sum|des']) {
49
+ const entriesByName = this.getEntriesByName();
50
+ const table = new EasyTable();
51
+ Object.entries(entriesByName).map(([name, values]) => {
52
+ const stats = new Summary(values);
53
+ table.cell('Name', name);
54
+ table.cell('size', stats.size(), EasyTable.number(0));
55
+ table.cell('min', stats.min(), EasyTable.number(2));
56
+ table.cell('max', stats.max(), EasyTable.number(2));
57
+ table.cell('median', stats.median(), EasyTable.number(2));
58
+ table.cell('sum', stats.sum(), EasyTable.number(2));
59
+ table.newRow();
60
+ });
61
+ table.total('sum', { printer: EasyTable.number(2) });
62
+ table.sort(sort);
63
+ return table;
64
+ }
65
+ async flush() {
66
+ this.start('_flush');
67
+ await new Promise(resolve => setTimeout(resolve, 1));
68
+ this.end('_flush');
69
+ }
70
+ async print() {
71
+ if (!this.enabled)
72
+ return;
73
+ await this.flush();
74
+ console.log('\n' + this.getTable().toString().trim());
75
+ }
76
+ reset() {
77
+ this.entries = [];
78
+ this.observer?.disconnect();
79
+ }
80
+ }
81
+ export const measure = new Performance(isEnabled);