inup 1.5.4 → 1.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -10
- package/dist/cli.js +20 -22
- package/dist/config/constants.js +4 -2
- package/dist/config/package-meta.js +10 -0
- package/dist/config/project-config.js +6 -1
- package/dist/core/package-detector.js +8 -4
- package/dist/core/upgrade-runner.js +7 -10
- package/dist/core/upgrader.js +6 -8
- package/dist/features/changelog/clients/github-client.js +5 -6
- package/dist/features/changelog/services/changelog-service.js +2 -4
- package/dist/features/changelog/services/package-metadata-service.js +6 -11
- package/dist/features/changelog/services/release-notes-service.js +4 -2
- package/dist/features/debug/services/performance-tracker.js +6 -8
- package/dist/index.js +1 -2
- package/dist/interactive-ui.js +30 -587
- package/dist/services/background-audit.js +3 -5
- package/dist/services/cache-manager.js +5 -7
- package/dist/services/http/inflight.js +22 -0
- package/dist/services/http/retry.js +30 -0
- package/dist/services/jsdelivr/client.js +191 -0
- package/dist/services/jsdelivr/manifest.js +136 -0
- package/dist/services/jsdelivr-registry.js +6 -392
- package/dist/services/npm-registry.js +12 -81
- package/dist/services/persistent-cache.js +8 -13
- package/dist/types/domain.js +3 -0
- package/dist/types/streaming.js +3 -0
- package/dist/types/ui.js +3 -0
- package/dist/types.js +17 -0
- package/dist/ui/controllers/package-info-modal-controller.js +22 -31
- package/dist/ui/controllers/vulnerability-audit-controller.js +17 -8
- package/dist/ui/index.js +3 -0
- package/dist/ui/input-handler.js +62 -77
- package/dist/ui/keymap.js +208 -0
- package/dist/ui/modal/package-info-sections/release-notes.js +161 -0
- package/dist/ui/modal/package-info-sections/sections.js +150 -0
- package/dist/ui/modal/package-info-sections/text.js +75 -0
- package/dist/ui/modal/package-info-sections.js +15 -368
- package/dist/ui/modal/package-info.js +1 -1
- package/dist/ui/renderer/help-modal.js +75 -0
- package/dist/ui/renderer/index.js +2 -5
- package/dist/ui/renderer/package-list/interface.js +184 -0
- package/dist/ui/renderer/package-list/rows.js +172 -0
- package/dist/ui/renderer/package-list.js +15 -462
- package/dist/ui/session/action-dispatcher.js +233 -0
- package/dist/ui/session/index.js +13 -0
- package/dist/ui/session/interactive-session.js +280 -0
- package/dist/ui/session/selection-state-builder.js +144 -0
- package/dist/ui/state/filter-manager.js +17 -6
- package/dist/ui/state/modal-manager.js +35 -0
- package/dist/ui/state/navigation-manager.js +33 -4
- package/dist/ui/state/state-manager.js +68 -3
- package/dist/ui/state/theme-manager.js +1 -0
- package/dist/ui/themes-colors.js +8 -0
- package/dist/ui/themes.js +11 -19
- package/dist/ui/utils/cursor.js +3 -4
- package/dist/ui/utils/index.js +6 -1
- package/dist/ui/utils/text.js +3 -2
- package/dist/ui/utils/version.js +60 -86
- package/dist/utils/config.js +13 -1
- package/dist/utils/filesystem/io.js +87 -0
- package/dist/utils/filesystem/paths.js +19 -0
- package/dist/utils/filesystem/scan.js +205 -0
- package/dist/utils/filesystem.js +17 -335
- package/dist/utils/version.js +31 -1
- package/package.json +10 -9
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readPackageJson = readPackageJson;
|
|
4
|
+
exports.readPackageJsonAsync = readPackageJsonAsync;
|
|
5
|
+
exports.collectAllDependencies = collectAllDependencies;
|
|
6
|
+
exports.collectAllDependenciesAsync = collectAllDependenciesAsync;
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const fs_2 = require("fs");
|
|
9
|
+
function readPackageJson(path) {
|
|
10
|
+
try {
|
|
11
|
+
const content = (0, fs_1.readFileSync)(path, 'utf-8');
|
|
12
|
+
return JSON.parse(content);
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
throw new Error(`Failed to read package.json: ${error}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
async function readPackageJsonAsync(path) {
|
|
19
|
+
try {
|
|
20
|
+
const content = await fs_2.promises.readFile(path, 'utf-8');
|
|
21
|
+
return JSON.parse(content);
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
throw new Error(`Failed to read package.json: ${error}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function collectAllDependencies(packageJsonFiles, _options = {}) {
|
|
28
|
+
const allDeps = [];
|
|
29
|
+
for (const packageJsonPath of packageJsonFiles) {
|
|
30
|
+
try {
|
|
31
|
+
const packageJson = readPackageJson(packageJsonPath);
|
|
32
|
+
const depTypes = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
|
|
33
|
+
for (const depType of depTypes) {
|
|
34
|
+
const deps = packageJson[depType];
|
|
35
|
+
if (deps && typeof deps === 'object') {
|
|
36
|
+
for (const [name, version] of Object.entries(deps)) {
|
|
37
|
+
allDeps.push({
|
|
38
|
+
name,
|
|
39
|
+
version: version,
|
|
40
|
+
type: depType,
|
|
41
|
+
packageJsonPath,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// Skip malformed package.json files
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return allDeps;
|
|
52
|
+
}
|
|
53
|
+
async function collectAllDependenciesAsync(packageJsonFiles, _options = {}) {
|
|
54
|
+
const packageJsonPromises = packageJsonFiles.map(async (packageJsonPath) => {
|
|
55
|
+
try {
|
|
56
|
+
const packageJson = await readPackageJsonAsync(packageJsonPath);
|
|
57
|
+
return { packageJson, packageJsonPath };
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// Skip malformed package.json files
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
const results = await Promise.all(packageJsonPromises);
|
|
65
|
+
const allDeps = [];
|
|
66
|
+
for (const result of results) {
|
|
67
|
+
if (!result)
|
|
68
|
+
continue;
|
|
69
|
+
const { packageJson, packageJsonPath } = result;
|
|
70
|
+
const depTypes = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
|
|
71
|
+
for (const depType of depTypes) {
|
|
72
|
+
const deps = packageJson[depType];
|
|
73
|
+
if (deps && typeof deps === 'object') {
|
|
74
|
+
for (const [name, version] of Object.entries(deps)) {
|
|
75
|
+
allDeps.push({
|
|
76
|
+
name,
|
|
77
|
+
version: version,
|
|
78
|
+
type: depType,
|
|
79
|
+
packageJsonPath,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return allDeps;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=io.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findPackageJson = findPackageJson;
|
|
4
|
+
exports.findWorkspaceRoot = findWorkspaceRoot;
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
const path_1 = require("path");
|
|
7
|
+
const package_manager_detector_1 = require("../../services/package-manager-detector");
|
|
8
|
+
function findPackageJson(cwd = process.cwd()) {
|
|
9
|
+
const packageJsonPath = (0, path_1.join)(cwd, 'package.json');
|
|
10
|
+
return (0, fs_1.existsSync)(packageJsonPath) ? packageJsonPath : null;
|
|
11
|
+
}
|
|
12
|
+
function findWorkspaceRoot(cwd = process.cwd(), packageManager) {
|
|
13
|
+
if (!packageManager) {
|
|
14
|
+
const detected = package_manager_detector_1.PackageManagerDetector.detect(cwd);
|
|
15
|
+
packageManager = detected.name;
|
|
16
|
+
}
|
|
17
|
+
return package_manager_detector_1.PackageManagerDetector.findWorkspaceRoot(cwd, packageManager);
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findAllPackageJsonFiles = findAllPackageJsonFiles;
|
|
4
|
+
exports.findAllPackageJsonFilesAsync = findAllPackageJsonFilesAsync;
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
const fs_2 = require("fs");
|
|
7
|
+
const path_1 = require("path");
|
|
8
|
+
const SKIP_DIRS = new Set([
|
|
9
|
+
'node_modules',
|
|
10
|
+
'dist',
|
|
11
|
+
'build',
|
|
12
|
+
'coverage',
|
|
13
|
+
'out',
|
|
14
|
+
'lib',
|
|
15
|
+
'es',
|
|
16
|
+
'esm',
|
|
17
|
+
'cjs',
|
|
18
|
+
]);
|
|
19
|
+
function shouldSkipDirectory(name) {
|
|
20
|
+
return name.startsWith('.') || SKIP_DIRS.has(name);
|
|
21
|
+
}
|
|
22
|
+
function findAllPackageJsonFiles(rootDir = process.cwd(), excludePatterns = [], maxDepth = 10, onProgress) {
|
|
23
|
+
const packageJsonFiles = [];
|
|
24
|
+
const visitedPaths = new Set();
|
|
25
|
+
let directoriesScanned = 0;
|
|
26
|
+
let lastProgressAt = 0;
|
|
27
|
+
const progressIntervalMs = 250;
|
|
28
|
+
const excludeRegexes = excludePatterns.map((pattern) => new RegExp(pattern, 'i'));
|
|
29
|
+
function shouldExcludePath(relativePath) {
|
|
30
|
+
return excludeRegexes.some((regex) => regex.test(relativePath));
|
|
31
|
+
}
|
|
32
|
+
function reportProgress(currentDir, force = false) {
|
|
33
|
+
if (!onProgress)
|
|
34
|
+
return;
|
|
35
|
+
const now = Date.now();
|
|
36
|
+
if (!force && now - lastProgressAt < progressIntervalMs) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
lastProgressAt = now;
|
|
40
|
+
const relativePath = (0, path_1.relative)(rootDir, currentDir) || '.';
|
|
41
|
+
onProgress(relativePath, packageJsonFiles.length);
|
|
42
|
+
}
|
|
43
|
+
function traverseDirectory(dir, depth = 0) {
|
|
44
|
+
if (depth > maxDepth) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
// Prevent symlink cycles by tracking visited real paths
|
|
49
|
+
const realPath = (0, fs_1.realpathSync)(dir);
|
|
50
|
+
if (visitedPaths.has(realPath)) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
visitedPaths.add(realPath);
|
|
54
|
+
directoriesScanned++;
|
|
55
|
+
// Report progress every 10 directories or on first scan
|
|
56
|
+
if (onProgress && (directoriesScanned % 10 === 0 || directoriesScanned === 1)) {
|
|
57
|
+
reportProgress(dir, true);
|
|
58
|
+
}
|
|
59
|
+
const files = (0, fs_1.readdirSync)(dir);
|
|
60
|
+
for (const file of files) {
|
|
61
|
+
reportProgress(dir);
|
|
62
|
+
const fullPath = (0, path_1.join)(dir, file);
|
|
63
|
+
const relativePath = (0, path_1.relative)(rootDir, fullPath);
|
|
64
|
+
if (shouldExcludePath(relativePath)) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
let stat;
|
|
68
|
+
try {
|
|
69
|
+
stat = (0, fs_1.statSync)(fullPath);
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// Skip files/dirs we can't stat (broken symlinks, permission issues)
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (stat.isDirectory() && !shouldSkipDirectory(file)) {
|
|
76
|
+
traverseDirectory(fullPath, depth + 1);
|
|
77
|
+
}
|
|
78
|
+
else if (file === 'package.json' && stat.isFile()) {
|
|
79
|
+
packageJsonFiles.push(fullPath);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// Skip directories that can't be read (permission issues, etc.)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
traverseDirectory(rootDir);
|
|
88
|
+
return packageJsonFiles;
|
|
89
|
+
}
|
|
90
|
+
async function findAllPackageJsonFilesAsync(rootDir = process.cwd(), excludePatterns = [], maxDepth = 10, onProgress, options = {}) {
|
|
91
|
+
const packageJsonFiles = [];
|
|
92
|
+
const visitedPaths = new Set();
|
|
93
|
+
let directoriesScanned = 0;
|
|
94
|
+
let lastProgressAt = 0;
|
|
95
|
+
const progressIntervalMs = 250;
|
|
96
|
+
const concurrency = Math.max(1, Math.min(options.concurrency ?? 16, 64));
|
|
97
|
+
const excludeRegexes = excludePatterns.map((pattern) => new RegExp(pattern, 'i'));
|
|
98
|
+
function shouldExcludePath(relativePath) {
|
|
99
|
+
return excludeRegexes.some((regex) => regex.test(relativePath));
|
|
100
|
+
}
|
|
101
|
+
function reportProgress(currentDir, force = false) {
|
|
102
|
+
if (!onProgress)
|
|
103
|
+
return;
|
|
104
|
+
const now = Date.now();
|
|
105
|
+
if (!force && now - lastProgressAt < progressIntervalMs) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
lastProgressAt = now;
|
|
109
|
+
const relativePath = (0, path_1.relative)(rootDir, currentDir) || '.';
|
|
110
|
+
onProgress(relativePath, packageJsonFiles.length);
|
|
111
|
+
}
|
|
112
|
+
const pending = [];
|
|
113
|
+
let activeTasks = 0;
|
|
114
|
+
let failedError = null;
|
|
115
|
+
let resolveDone = null;
|
|
116
|
+
let rejectDone = null;
|
|
117
|
+
const done = new Promise((resolve, reject) => {
|
|
118
|
+
resolveDone = resolve;
|
|
119
|
+
rejectDone = reject;
|
|
120
|
+
});
|
|
121
|
+
function finishIfIdle() {
|
|
122
|
+
if (pending.length === 0 && activeTasks === 0) {
|
|
123
|
+
resolveDone?.();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function schedule(dir, depth) {
|
|
127
|
+
pending.push({ dir, depth });
|
|
128
|
+
pump();
|
|
129
|
+
}
|
|
130
|
+
async function processDirectory(dir, depth) {
|
|
131
|
+
if (depth > maxDepth) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
let realPath;
|
|
135
|
+
try {
|
|
136
|
+
realPath = await fs_2.promises.realpath(dir);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (visitedPaths.has(realPath)) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
visitedPaths.add(realPath);
|
|
145
|
+
directoriesScanned++;
|
|
146
|
+
if (directoriesScanned % 10 === 0 || directoriesScanned === 1) {
|
|
147
|
+
reportProgress(dir, true);
|
|
148
|
+
}
|
|
149
|
+
let files;
|
|
150
|
+
try {
|
|
151
|
+
files = await fs_2.promises.readdir(dir);
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
for (const file of files) {
|
|
157
|
+
reportProgress(dir);
|
|
158
|
+
const fullPath = (0, path_1.join)(dir, file);
|
|
159
|
+
const relativePath = (0, path_1.relative)(rootDir, fullPath);
|
|
160
|
+
if (shouldExcludePath(relativePath)) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
let stat;
|
|
164
|
+
try {
|
|
165
|
+
stat = await fs_2.promises.stat(fullPath);
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
if (stat.isDirectory() && !shouldSkipDirectory(file)) {
|
|
171
|
+
schedule(fullPath, depth + 1);
|
|
172
|
+
}
|
|
173
|
+
else if (file === 'package.json' && stat.isFile()) {
|
|
174
|
+
packageJsonFiles.push(fullPath);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function pump() {
|
|
179
|
+
while (activeTasks < concurrency && pending.length > 0 && !failedError) {
|
|
180
|
+
const next = pending.shift();
|
|
181
|
+
if (!next)
|
|
182
|
+
break;
|
|
183
|
+
activeTasks++;
|
|
184
|
+
void processDirectory(next.dir, next.depth)
|
|
185
|
+
.catch((error) => {
|
|
186
|
+
if (!failedError) {
|
|
187
|
+
failedError = error;
|
|
188
|
+
rejectDone?.(error);
|
|
189
|
+
}
|
|
190
|
+
})
|
|
191
|
+
.finally(() => {
|
|
192
|
+
activeTasks--;
|
|
193
|
+
if (failedError) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
pump();
|
|
197
|
+
finishIfIdle();
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
schedule(rootDir, 0);
|
|
202
|
+
await done;
|
|
203
|
+
return packageJsonFiles;
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=scan.js.map
|
package/dist/utils/filesystem.js
CHANGED
|
@@ -1,338 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
2
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports
|
|
4
|
-
exports
|
|
5
|
-
exports
|
|
6
|
-
exports.readPackageJsonAsync = readPackageJsonAsync;
|
|
7
|
-
exports.collectAllDependencies = collectAllDependencies;
|
|
8
|
-
exports.collectAllDependenciesAsync = collectAllDependenciesAsync;
|
|
9
|
-
exports.findAllPackageJsonFiles = findAllPackageJsonFiles;
|
|
10
|
-
exports.findAllPackageJsonFilesAsync = findAllPackageJsonFilesAsync;
|
|
11
|
-
const fs_1 = require("fs");
|
|
12
|
-
const fs_2 = require("fs");
|
|
13
|
-
const path_1 = require("path");
|
|
14
|
-
const package_manager_detector_1 = require("../services/package-manager-detector");
|
|
15
|
-
/**
|
|
16
|
-
* Find package.json in the current working directory
|
|
17
|
-
*/
|
|
18
|
-
function findPackageJson(cwd = process.cwd()) {
|
|
19
|
-
const packageJsonPath = (0, path_1.join)(cwd, 'package.json');
|
|
20
|
-
return (0, fs_1.existsSync)(packageJsonPath) ? packageJsonPath : null;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Find the workspace root by detecting package manager and checking for workspace configuration
|
|
24
|
-
* @param cwd - Current working directory
|
|
25
|
-
* @param packageManager - Optional package manager to use (will auto-detect if not provided)
|
|
26
|
-
*/
|
|
27
|
-
function findWorkspaceRoot(cwd = process.cwd(), packageManager) {
|
|
28
|
-
// Auto-detect if not provided
|
|
29
|
-
if (!packageManager) {
|
|
30
|
-
const detected = package_manager_detector_1.PackageManagerDetector.detect(cwd);
|
|
31
|
-
packageManager = detected.name;
|
|
32
|
-
}
|
|
33
|
-
return package_manager_detector_1.PackageManagerDetector.findWorkspaceRoot(cwd, packageManager);
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Read and parse a package.json file
|
|
37
|
-
*/
|
|
38
|
-
function readPackageJson(path) {
|
|
39
|
-
try {
|
|
40
|
-
const content = (0, fs_1.readFileSync)(path, 'utf-8');
|
|
41
|
-
return JSON.parse(content);
|
|
42
|
-
}
|
|
43
|
-
catch (error) {
|
|
44
|
-
throw new Error(`Failed to read package.json: ${error}`);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Read and parse a package.json file asynchronously
|
|
49
|
-
*/
|
|
50
|
-
async function readPackageJsonAsync(path) {
|
|
51
|
-
try {
|
|
52
|
-
const content = await fs_2.promises.readFile(path, 'utf-8');
|
|
53
|
-
return JSON.parse(content);
|
|
54
|
-
}
|
|
55
|
-
catch (error) {
|
|
56
|
-
throw new Error(`Failed to read package.json: ${error}`);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
const SKIP_DIRS = new Set([
|
|
60
|
-
'node_modules',
|
|
61
|
-
'dist',
|
|
62
|
-
'build',
|
|
63
|
-
'coverage',
|
|
64
|
-
'out',
|
|
65
|
-
'lib',
|
|
66
|
-
'es',
|
|
67
|
-
'esm',
|
|
68
|
-
'cjs',
|
|
69
|
-
]);
|
|
70
|
-
function shouldSkipDirectory(name) {
|
|
71
|
-
return name.startsWith('.') || SKIP_DIRS.has(name);
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Collects all dependencies from multiple package.json files.
|
|
75
|
-
* Always includes regular dependencies and devDependencies.
|
|
76
|
-
* Optionally includes peer and optional dependencies based on flags.
|
|
77
|
-
*/
|
|
78
|
-
function collectAllDependencies(packageJsonFiles, options = {}) {
|
|
79
|
-
const allDeps = [];
|
|
80
|
-
for (const packageJsonPath of packageJsonFiles) {
|
|
81
|
-
try {
|
|
82
|
-
const packageJson = readPackageJson(packageJsonPath);
|
|
83
|
-
const depTypes = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
|
|
84
|
-
for (const depType of depTypes) {
|
|
85
|
-
const deps = packageJson[depType];
|
|
86
|
-
if (deps && typeof deps === 'object') {
|
|
87
|
-
for (const [name, version] of Object.entries(deps)) {
|
|
88
|
-
allDeps.push({
|
|
89
|
-
name,
|
|
90
|
-
version: version,
|
|
91
|
-
type: depType,
|
|
92
|
-
packageJsonPath,
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
catch (error) {
|
|
99
|
-
// Skip malformed package.json files
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return allDeps;
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Collects all dependencies from multiple package.json files asynchronously.
|
|
106
|
-
* Reads all package.json files in parallel for better performance.
|
|
107
|
-
* Always includes regular dependencies and devDependencies.
|
|
108
|
-
* Optionally includes peer and optional dependencies based on flags.
|
|
109
|
-
*/
|
|
110
|
-
async function collectAllDependenciesAsync(packageJsonFiles, options = {}) {
|
|
111
|
-
// Read all package.json files in parallel
|
|
112
|
-
const packageJsonPromises = packageJsonFiles.map(async (packageJsonPath) => {
|
|
113
|
-
try {
|
|
114
|
-
const packageJson = await readPackageJsonAsync(packageJsonPath);
|
|
115
|
-
return { packageJson, packageJsonPath };
|
|
116
|
-
}
|
|
117
|
-
catch (error) {
|
|
118
|
-
// Skip malformed package.json files
|
|
119
|
-
return null;
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
const results = await Promise.all(packageJsonPromises);
|
|
123
|
-
// Collect dependencies from all successfully read package.json files
|
|
124
|
-
const allDeps = [];
|
|
125
|
-
for (const result of results) {
|
|
126
|
-
if (!result)
|
|
127
|
-
continue;
|
|
128
|
-
const { packageJson, packageJsonPath } = result;
|
|
129
|
-
const depTypes = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
|
|
130
|
-
for (const depType of depTypes) {
|
|
131
|
-
const deps = packageJson[depType];
|
|
132
|
-
if (deps && typeof deps === 'object') {
|
|
133
|
-
for (const [name, version] of Object.entries(deps)) {
|
|
134
|
-
allDeps.push({
|
|
135
|
-
name,
|
|
136
|
-
version: version,
|
|
137
|
-
type: depType,
|
|
138
|
-
packageJsonPath,
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
return allDeps;
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Find all package.json files recursively
|
|
148
|
-
*/
|
|
149
|
-
function findAllPackageJsonFiles(rootDir = process.cwd(), excludePatterns = [], maxDepth = 10, onProgress) {
|
|
150
|
-
const packageJsonFiles = [];
|
|
151
|
-
const visitedPaths = new Set();
|
|
152
|
-
let directoriesScanned = 0;
|
|
153
|
-
let lastProgressAt = 0;
|
|
154
|
-
const progressIntervalMs = 250;
|
|
155
|
-
// Compile regex patterns for exclude filtering
|
|
156
|
-
const excludeRegexes = excludePatterns.map((pattern) => new RegExp(pattern, 'i'));
|
|
157
|
-
function shouldExcludePath(relativePath) {
|
|
158
|
-
return excludeRegexes.some((regex) => regex.test(relativePath));
|
|
159
|
-
}
|
|
160
|
-
function reportProgress(currentDir, force = false) {
|
|
161
|
-
if (!onProgress)
|
|
162
|
-
return;
|
|
163
|
-
const now = Date.now();
|
|
164
|
-
if (!force && now - lastProgressAt < progressIntervalMs) {
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
lastProgressAt = now;
|
|
168
|
-
const relativePath = (0, path_1.relative)(rootDir, currentDir) || '.';
|
|
169
|
-
onProgress(relativePath, packageJsonFiles.length);
|
|
170
|
-
}
|
|
171
|
-
function traverseDirectory(dir, depth = 0) {
|
|
172
|
-
// Prevent infinite recursion with depth limit
|
|
173
|
-
if (depth > maxDepth) {
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
try {
|
|
177
|
-
// Prevent symlink cycles by tracking visited real paths
|
|
178
|
-
const realPath = (0, fs_1.realpathSync)(dir);
|
|
179
|
-
if (visitedPaths.has(realPath)) {
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
visitedPaths.add(realPath);
|
|
183
|
-
directoriesScanned++;
|
|
184
|
-
// Report progress every 10 directories or on first scan
|
|
185
|
-
if (onProgress && (directoriesScanned % 10 === 0 || directoriesScanned === 1)) {
|
|
186
|
-
reportProgress(dir, true);
|
|
187
|
-
}
|
|
188
|
-
const files = (0, fs_1.readdirSync)(dir);
|
|
189
|
-
for (const file of files) {
|
|
190
|
-
reportProgress(dir);
|
|
191
|
-
const fullPath = (0, path_1.join)(dir, file);
|
|
192
|
-
const relativePath = (0, path_1.relative)(rootDir, fullPath);
|
|
193
|
-
// Skip if path matches exclude patterns
|
|
194
|
-
if (shouldExcludePath(relativePath)) {
|
|
195
|
-
continue;
|
|
196
|
-
}
|
|
197
|
-
let stat;
|
|
198
|
-
try {
|
|
199
|
-
stat = (0, fs_1.statSync)(fullPath);
|
|
200
|
-
}
|
|
201
|
-
catch {
|
|
202
|
-
// Skip files/dirs we can't stat (broken symlinks, permission issues)
|
|
203
|
-
continue;
|
|
204
|
-
}
|
|
205
|
-
if (stat.isDirectory() && !shouldSkipDirectory(file)) {
|
|
206
|
-
traverseDirectory(fullPath, depth + 1);
|
|
207
|
-
}
|
|
208
|
-
else if (file === 'package.json' && stat.isFile()) {
|
|
209
|
-
packageJsonFiles.push(fullPath);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
catch (error) {
|
|
214
|
-
// Skip directories that can't be read (permission issues, etc.)
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
traverseDirectory(rootDir);
|
|
218
|
-
return packageJsonFiles;
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* Find all package.json files recursively with bounded parallel directory traversal.
|
|
222
|
-
*/
|
|
223
|
-
async function findAllPackageJsonFilesAsync(rootDir = process.cwd(), excludePatterns = [], maxDepth = 10, onProgress, options = {}) {
|
|
224
|
-
const packageJsonFiles = [];
|
|
225
|
-
const visitedPaths = new Set();
|
|
226
|
-
let directoriesScanned = 0;
|
|
227
|
-
let lastProgressAt = 0;
|
|
228
|
-
const progressIntervalMs = 250;
|
|
229
|
-
const concurrency = Math.max(1, Math.min(options.concurrency ?? 16, 64));
|
|
230
|
-
const excludeRegexes = excludePatterns.map((pattern) => new RegExp(pattern, 'i'));
|
|
231
|
-
function shouldExcludePath(relativePath) {
|
|
232
|
-
return excludeRegexes.some((regex) => regex.test(relativePath));
|
|
233
|
-
}
|
|
234
|
-
function reportProgress(currentDir, force = false) {
|
|
235
|
-
if (!onProgress)
|
|
236
|
-
return;
|
|
237
|
-
const now = Date.now();
|
|
238
|
-
if (!force && now - lastProgressAt < progressIntervalMs) {
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
lastProgressAt = now;
|
|
242
|
-
const relativePath = (0, path_1.relative)(rootDir, currentDir) || '.';
|
|
243
|
-
onProgress(relativePath, packageJsonFiles.length);
|
|
244
|
-
}
|
|
245
|
-
const pending = [];
|
|
246
|
-
let activeTasks = 0;
|
|
247
|
-
let failedError = null;
|
|
248
|
-
let resolveDone = null;
|
|
249
|
-
let rejectDone = null;
|
|
250
|
-
const done = new Promise((resolve, reject) => {
|
|
251
|
-
resolveDone = resolve;
|
|
252
|
-
rejectDone = reject;
|
|
253
|
-
});
|
|
254
|
-
function finishIfIdle() {
|
|
255
|
-
if (pending.length === 0 && activeTasks === 0) {
|
|
256
|
-
resolveDone?.();
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
function schedule(dir, depth) {
|
|
260
|
-
pending.push({ dir, depth });
|
|
261
|
-
pump();
|
|
262
|
-
}
|
|
263
|
-
async function processDirectory(dir, depth) {
|
|
264
|
-
if (depth > maxDepth) {
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
let realPath;
|
|
268
|
-
try {
|
|
269
|
-
realPath = await fs_2.promises.realpath(dir);
|
|
270
|
-
}
|
|
271
|
-
catch {
|
|
272
|
-
return;
|
|
273
|
-
}
|
|
274
|
-
if (visitedPaths.has(realPath)) {
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
277
|
-
visitedPaths.add(realPath);
|
|
278
|
-
directoriesScanned++;
|
|
279
|
-
if (directoriesScanned % 10 === 0 || directoriesScanned === 1) {
|
|
280
|
-
reportProgress(dir, true);
|
|
281
|
-
}
|
|
282
|
-
let files;
|
|
283
|
-
try {
|
|
284
|
-
files = await fs_2.promises.readdir(dir);
|
|
285
|
-
}
|
|
286
|
-
catch {
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
for (const file of files) {
|
|
290
|
-
reportProgress(dir);
|
|
291
|
-
const fullPath = (0, path_1.join)(dir, file);
|
|
292
|
-
const relativePath = (0, path_1.relative)(rootDir, fullPath);
|
|
293
|
-
if (shouldExcludePath(relativePath)) {
|
|
294
|
-
continue;
|
|
295
|
-
}
|
|
296
|
-
let stat;
|
|
297
|
-
try {
|
|
298
|
-
stat = await fs_2.promises.stat(fullPath);
|
|
299
|
-
}
|
|
300
|
-
catch {
|
|
301
|
-
continue;
|
|
302
|
-
}
|
|
303
|
-
if (stat.isDirectory() && !shouldSkipDirectory(file)) {
|
|
304
|
-
schedule(fullPath, depth + 1);
|
|
305
|
-
}
|
|
306
|
-
else if (file === 'package.json' && stat.isFile()) {
|
|
307
|
-
packageJsonFiles.push(fullPath);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
function pump() {
|
|
312
|
-
while (activeTasks < concurrency && pending.length > 0 && !failedError) {
|
|
313
|
-
const next = pending.shift();
|
|
314
|
-
if (!next)
|
|
315
|
-
break;
|
|
316
|
-
activeTasks++;
|
|
317
|
-
void processDirectory(next.dir, next.depth)
|
|
318
|
-
.catch((error) => {
|
|
319
|
-
if (!failedError) {
|
|
320
|
-
failedError = error;
|
|
321
|
-
rejectDone?.(error);
|
|
322
|
-
}
|
|
323
|
-
})
|
|
324
|
-
.finally(() => {
|
|
325
|
-
activeTasks--;
|
|
326
|
-
if (failedError) {
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
pump();
|
|
330
|
-
finishIfIdle();
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
schedule(rootDir, 0);
|
|
335
|
-
await done;
|
|
336
|
-
return packageJsonFiles;
|
|
337
|
-
}
|
|
17
|
+
__exportStar(require("./filesystem/paths"), exports);
|
|
18
|
+
__exportStar(require("./filesystem/io"), exports);
|
|
19
|
+
__exportStar(require("./filesystem/scan"), exports);
|
|
338
20
|
//# sourceMappingURL=filesystem.js.map
|