@emeryld/manager 1.5.2 → 1.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/directory-picker.js +273 -73
- package/dist/ts-trace/picker.js +10 -49
- package/package.json +1 -1
package/dist/directory-picker.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import { readdir, readFile } from 'node:fs/promises';
|
|
3
3
|
import { IGNORED_DIRECTORIES } from './format-checker/scan/constants.js';
|
|
4
|
-
import { normalizeScripts } from './helper-cli/scripts.js';
|
|
5
|
-
import { promptForScript } from './helper-cli/prompts.js';
|
|
6
4
|
import { rootDir } from './helper-cli/env.js';
|
|
5
|
+
import { promptForScript } from './helper-cli/prompts.js';
|
|
6
|
+
import { normalizeScripts } from './helper-cli/scripts.js';
|
|
7
7
|
import { loadPackages } from './packages.js';
|
|
8
8
|
const ROOT_ENTRY = {
|
|
9
9
|
label: 'Workspace root',
|
|
@@ -11,21 +11,53 @@ const ROOT_ENTRY = {
|
|
|
11
11
|
description: 'Root directory',
|
|
12
12
|
color: 'brightBlue',
|
|
13
13
|
};
|
|
14
|
+
const ACTION_SCRIPT_PREFIX = '__explorer_action__';
|
|
14
15
|
export async function promptDirectorySelection(options = {}) {
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
const packageMap = await buildPackageMap();
|
|
17
|
+
const selection = await promptWorkspaceExplorer({
|
|
18
|
+
title: options.title ?? 'Select a directory',
|
|
19
|
+
mode: 'directory',
|
|
20
|
+
rootPath: rootDir,
|
|
21
|
+
includeRootSelection: options.includeWorkspaceRoot ?? true,
|
|
22
|
+
includeFile: () => true,
|
|
23
|
+
describeDirectory: (entry) => describeDirectory(entry, packageMap),
|
|
24
|
+
describeFile: (entry) => ({
|
|
25
|
+
label: entry.name,
|
|
26
|
+
description: entry.relativePath,
|
|
27
|
+
}),
|
|
28
|
+
});
|
|
24
29
|
if (!selection)
|
|
25
30
|
return undefined;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
return {
|
|
32
|
+
label: selection.label,
|
|
33
|
+
relativePath: selection.relativePath,
|
|
34
|
+
absolutePath: selection.absolutePath,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export async function promptWorkspaceFileSelection(options = {}) {
|
|
38
|
+
const rootPath = resolveRootPath(options.rootPath);
|
|
39
|
+
const selection = await promptWorkspaceExplorer({
|
|
40
|
+
title: options.title ?? 'Select a file',
|
|
41
|
+
mode: 'file',
|
|
42
|
+
rootPath,
|
|
43
|
+
includeRootSelection: false,
|
|
44
|
+
includeFile: options.includeFile ?? (() => true),
|
|
45
|
+
describeDirectory: (entry) => ({
|
|
46
|
+
label: `${entry.name}/`,
|
|
47
|
+
description: entry.relativePath,
|
|
48
|
+
}),
|
|
49
|
+
describeFile: (entry) => ({
|
|
50
|
+
label: entry.name,
|
|
51
|
+
description: entry.relativePath,
|
|
52
|
+
}),
|
|
53
|
+
});
|
|
54
|
+
if (!selection || selection.kind !== 'file')
|
|
55
|
+
return undefined;
|
|
56
|
+
return {
|
|
57
|
+
label: selection.label,
|
|
58
|
+
relativePath: selection.relativePath,
|
|
59
|
+
absolutePath: selection.absolutePath,
|
|
60
|
+
};
|
|
29
61
|
}
|
|
30
62
|
export function describeDirectorySelection(selection) {
|
|
31
63
|
const normalized = selection.relativePath
|
|
@@ -36,83 +68,243 @@ export function describeDirectorySelection(selection) {
|
|
|
36
68
|
}
|
|
37
69
|
return `${selection.label} (${normalized})`;
|
|
38
70
|
}
|
|
39
|
-
async function
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
71
|
+
async function promptWorkspaceExplorer(options) {
|
|
72
|
+
const ignorePatterns = await collectIgnorePatterns(options.rootPath);
|
|
73
|
+
let currentPath = options.rootPath;
|
|
74
|
+
// eslint-disable-next-line no-constant-condition
|
|
75
|
+
while (true) {
|
|
76
|
+
const entries = await readExplorerEntries(currentPath, options, ignorePatterns);
|
|
77
|
+
const { menuEntries, actionMap } = buildExplorerMenuEntries(options, currentPath, entries);
|
|
78
|
+
const selectedEntry = await promptForScript(menuEntries, `${options.title} (${formatCurrentLocation(options.rootPath, currentPath)})`);
|
|
79
|
+
if (!selectedEntry?.script) {
|
|
80
|
+
const parentPath = getParentPath(currentPath, options.rootPath);
|
|
81
|
+
if (parentPath) {
|
|
82
|
+
currentPath = parentPath;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
const action = actionMap.get(selectedEntry.script);
|
|
88
|
+
if (!action) {
|
|
54
89
|
continue;
|
|
55
90
|
}
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
91
|
+
if (action.type === 'select-current-directory') {
|
|
92
|
+
return buildCurrentDirectorySelection(options, currentPath);
|
|
93
|
+
}
|
|
94
|
+
if (action.type === 'open-directory') {
|
|
95
|
+
currentPath = action.entry.absolutePath;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (action.type === 'select-file') {
|
|
99
|
+
if (options.mode === 'file') {
|
|
100
|
+
return toExplorerSelection(action.entry);
|
|
101
|
+
}
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
// noop placeholder
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function buildExplorerMenuEntries(options, currentPath, entries) {
|
|
108
|
+
const actionMap = new Map();
|
|
109
|
+
const scripts = [];
|
|
110
|
+
let actionIndex = 0;
|
|
111
|
+
const addAction = (action, entry) => {
|
|
112
|
+
const scriptId = `${ACTION_SCRIPT_PREFIX}${actionIndex++}`;
|
|
113
|
+
actionMap.set(scriptId, action);
|
|
114
|
+
scripts.push({
|
|
115
|
+
...entry,
|
|
116
|
+
script: scriptId,
|
|
117
|
+
});
|
|
118
|
+
};
|
|
119
|
+
if (options.mode === 'directory' && canSelectCurrentDirectory(options, currentPath)) {
|
|
120
|
+
const currentSelection = buildCurrentDirectorySelection(options, currentPath);
|
|
121
|
+
addAction({ type: 'select-current-directory' }, {
|
|
122
|
+
name: currentSelection.relativePath === '.'
|
|
123
|
+
? ROOT_ENTRY.label
|
|
124
|
+
: 'Select this directory',
|
|
125
|
+
emoji: '✅',
|
|
126
|
+
description: currentSelection.relativePath === '.'
|
|
127
|
+
? ROOT_ENTRY.description
|
|
128
|
+
: currentSelection.relativePath,
|
|
129
|
+
color: currentSelection.relativePath === '.' ? ROOT_ENTRY.color : undefined,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
for (const entry of entries) {
|
|
133
|
+
if (entry.kind === 'directory') {
|
|
134
|
+
addAction({ type: 'open-directory', entry }, {
|
|
135
|
+
name: entry.label,
|
|
136
|
+
emoji: '📁',
|
|
137
|
+
description: entry.description,
|
|
138
|
+
color: entry.color,
|
|
62
139
|
});
|
|
63
140
|
continue;
|
|
64
141
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
description: entry.
|
|
142
|
+
addAction({ type: 'select-file', entry }, {
|
|
143
|
+
name: entry.label,
|
|
144
|
+
emoji: '📄',
|
|
145
|
+
description: entry.description,
|
|
146
|
+
color: entry.color,
|
|
69
147
|
});
|
|
70
148
|
}
|
|
71
|
-
if (
|
|
72
|
-
|
|
149
|
+
if (scripts.length === 0) {
|
|
150
|
+
addAction({ type: 'noop' }, {
|
|
151
|
+
name: 'No entries at this level',
|
|
152
|
+
emoji: '🫥',
|
|
153
|
+
description: 'Go deeper into another folder or press 0 to go back.',
|
|
154
|
+
});
|
|
73
155
|
}
|
|
74
|
-
return
|
|
156
|
+
return {
|
|
157
|
+
menuEntries: normalizeScripts(scripts),
|
|
158
|
+
actionMap,
|
|
159
|
+
};
|
|
75
160
|
}
|
|
76
|
-
async function
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
161
|
+
async function readExplorerEntries(currentPath, options, ignorePatterns) {
|
|
162
|
+
let filesystemEntries;
|
|
163
|
+
try {
|
|
164
|
+
filesystemEntries = await readdir(currentPath, { withFileTypes: true });
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
return [];
|
|
168
|
+
}
|
|
169
|
+
const entries = [];
|
|
170
|
+
for (const filesystemEntry of filesystemEntries) {
|
|
171
|
+
if (filesystemEntry.isSymbolicLink())
|
|
172
|
+
continue;
|
|
173
|
+
const absolutePath = path.join(currentPath, filesystemEntry.name);
|
|
174
|
+
const relativePath = normalizeRelativePath(path.relative(options.rootPath, absolutePath));
|
|
175
|
+
if (shouldIgnore(relativePath, ignorePatterns))
|
|
176
|
+
continue;
|
|
177
|
+
const candidate = {
|
|
178
|
+
name: filesystemEntry.name,
|
|
179
|
+
absolutePath,
|
|
180
|
+
relativePath,
|
|
181
|
+
};
|
|
182
|
+
if (filesystemEntry.isDirectory()) {
|
|
183
|
+
const presentation = options.describeDirectory(candidate);
|
|
184
|
+
entries.push({
|
|
185
|
+
...candidate,
|
|
186
|
+
kind: 'directory',
|
|
187
|
+
label: presentation.label,
|
|
188
|
+
description: presentation.description ?? candidate.relativePath,
|
|
189
|
+
color: presentation.color,
|
|
190
|
+
});
|
|
191
|
+
continue;
|
|
97
192
|
}
|
|
193
|
+
if (!filesystemEntry.isFile())
|
|
194
|
+
continue;
|
|
195
|
+
if (!options.includeFile(candidate))
|
|
196
|
+
continue;
|
|
197
|
+
const presentation = options.describeFile(candidate);
|
|
198
|
+
entries.push({
|
|
199
|
+
...candidate,
|
|
200
|
+
kind: 'file',
|
|
201
|
+
label: presentation.label,
|
|
202
|
+
description: presentation.description ?? candidate.relativePath,
|
|
203
|
+
color: presentation.color,
|
|
204
|
+
});
|
|
98
205
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
206
|
+
entries.sort((left, right) => {
|
|
207
|
+
if (left.kind !== right.kind)
|
|
208
|
+
return left.kind === 'directory' ? -1 : 1;
|
|
209
|
+
return left.label.localeCompare(right.label, undefined, {
|
|
210
|
+
sensitivity: 'base',
|
|
211
|
+
numeric: true,
|
|
212
|
+
});
|
|
106
213
|
});
|
|
107
|
-
return
|
|
214
|
+
return entries;
|
|
215
|
+
}
|
|
216
|
+
function toExplorerSelection(entry) {
|
|
217
|
+
return {
|
|
218
|
+
kind: entry.kind,
|
|
219
|
+
label: entry.label,
|
|
220
|
+
relativePath: entry.relativePath,
|
|
221
|
+
absolutePath: entry.absolutePath,
|
|
222
|
+
};
|
|
108
223
|
}
|
|
109
|
-
|
|
224
|
+
function formatCurrentLocation(rootPath, currentPath) {
|
|
225
|
+
const relativePath = normalizeRelativePath(path.relative(rootPath, currentPath));
|
|
226
|
+
return relativePath === '.'
|
|
227
|
+
? `${ROOT_ENTRY.label} (${ROOT_ENTRY.relativePath})`
|
|
228
|
+
: relativePath;
|
|
229
|
+
}
|
|
230
|
+
function canSelectCurrentDirectory(options, currentPath) {
|
|
231
|
+
if (options.mode !== 'directory')
|
|
232
|
+
return false;
|
|
233
|
+
if (options.includeRootSelection)
|
|
234
|
+
return true;
|
|
235
|
+
const relativePath = normalizeRelativePath(path.relative(options.rootPath, currentPath));
|
|
236
|
+
return relativePath !== '.';
|
|
237
|
+
}
|
|
238
|
+
function buildCurrentDirectorySelection(options, currentPath) {
|
|
239
|
+
const relativePath = normalizeRelativePath(path.relative(options.rootPath, currentPath));
|
|
240
|
+
const candidate = {
|
|
241
|
+
name: path.basename(currentPath),
|
|
242
|
+
absolutePath: currentPath,
|
|
243
|
+
relativePath,
|
|
244
|
+
};
|
|
245
|
+
const presentation = relativePath === '.'
|
|
246
|
+
? {
|
|
247
|
+
label: ROOT_ENTRY.label,
|
|
248
|
+
description: ROOT_ENTRY.description,
|
|
249
|
+
color: ROOT_ENTRY.color,
|
|
250
|
+
}
|
|
251
|
+
: options.describeDirectory(candidate);
|
|
252
|
+
return {
|
|
253
|
+
kind: 'directory',
|
|
254
|
+
label: presentation.label,
|
|
255
|
+
relativePath,
|
|
256
|
+
absolutePath: currentPath,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
function getParentPath(currentPath, rootPath) {
|
|
260
|
+
const relativePath = normalizeRelativePath(path.relative(rootPath, currentPath));
|
|
261
|
+
if (relativePath === '.')
|
|
262
|
+
return undefined;
|
|
263
|
+
const parent = path.dirname(currentPath);
|
|
264
|
+
if (!isWithinRoot(parent, rootPath))
|
|
265
|
+
return undefined;
|
|
266
|
+
return parent;
|
|
267
|
+
}
|
|
268
|
+
function isWithinRoot(targetPath, rootPath) {
|
|
269
|
+
const relative = path.relative(rootPath, targetPath);
|
|
270
|
+
return (relative === '' ||
|
|
271
|
+
relative === '.' ||
|
|
272
|
+
(!relative.startsWith('..') && !path.isAbsolute(relative)));
|
|
273
|
+
}
|
|
274
|
+
function describeDirectory(entry, packageMap) {
|
|
275
|
+
if (entry.relativePath === '.') {
|
|
276
|
+
return {
|
|
277
|
+
label: ROOT_ENTRY.label,
|
|
278
|
+
description: ROOT_ENTRY.description,
|
|
279
|
+
color: ROOT_ENTRY.color,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
const pkg = packageMap.get(entry.relativePath);
|
|
283
|
+
if (pkg) {
|
|
284
|
+
return {
|
|
285
|
+
label: pkg.name ?? pkg.dirName,
|
|
286
|
+
description: pkg.relativeDir,
|
|
287
|
+
color: pkg.color,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
return {
|
|
291
|
+
label: entry.name,
|
|
292
|
+
description: entry.relativePath,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
function resolveRootPath(rootPath) {
|
|
296
|
+
const basePath = rootPath ?? rootDir;
|
|
297
|
+
if (path.isAbsolute(basePath))
|
|
298
|
+
return path.resolve(basePath);
|
|
299
|
+
return path.resolve(rootDir, basePath);
|
|
300
|
+
}
|
|
301
|
+
async function collectIgnorePatterns(rootPath) {
|
|
110
302
|
const patterns = new Set();
|
|
111
303
|
for (const entry of IGNORED_DIRECTORIES) {
|
|
112
304
|
patterns.add(normalizeRelativePath(entry));
|
|
113
305
|
}
|
|
114
306
|
try {
|
|
115
|
-
const contents = await readFile(path.join(
|
|
307
|
+
const contents = await readFile(path.join(rootPath, '.gitignore'), 'utf-8');
|
|
116
308
|
for (const rawLine of contents.split(/\r?\n/)) {
|
|
117
309
|
const trimmed = rawLine.trim();
|
|
118
310
|
if (!trimmed || trimmed.startsWith('#') || trimmed.startsWith('!'))
|
|
@@ -125,6 +317,14 @@ async function collectIgnorePatterns() {
|
|
|
125
317
|
}
|
|
126
318
|
return Array.from(patterns).filter(Boolean);
|
|
127
319
|
}
|
|
320
|
+
async function buildPackageMap() {
|
|
321
|
+
const packages = await loadPackageMetadata();
|
|
322
|
+
const packageMap = new Map();
|
|
323
|
+
for (const pkg of packages) {
|
|
324
|
+
packageMap.set(normalizeRelativePath(pkg.relativeDir), pkg);
|
|
325
|
+
}
|
|
326
|
+
return packageMap;
|
|
327
|
+
}
|
|
128
328
|
function normalizeRelativePath(value) {
|
|
129
329
|
const normalized = value.replace(/\\/g, '/').replace(/^\/+/, '');
|
|
130
330
|
const trimmed = normalized.replace(/\/+$/, '');
|
package/dist/ts-trace/picker.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { tmpdir } from 'node:os';
|
|
2
2
|
import { readdir, stat } from 'node:fs/promises';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
-
import { describeDirectorySelection, promptDirectorySelection, } from '../directory-picker.js';
|
|
4
|
+
import { describeDirectorySelection, promptDirectorySelection, promptWorkspaceFileSelection, } from '../directory-picker.js';
|
|
5
5
|
import { IGNORED_DIRECTORIES, SOURCE_EXTENSIONS, } from '../format-checker/scan/constants.js';
|
|
6
6
|
import { rootDir } from '../helper-cli/env.js';
|
|
7
7
|
import { promptForScript } from '../helper-cli/prompts.js';
|
|
@@ -13,8 +13,6 @@ const TRACE_FILE_NAME = 'trace.json';
|
|
|
13
13
|
const TYPES_FILE_NAME = 'types.json';
|
|
14
14
|
const TRACE_SCAN_MAX_DEPTH = 4;
|
|
15
15
|
const TRACE_SCAN_MAX_RESULTS = 300;
|
|
16
|
-
const PROFILE_SCAN_MAX_DEPTH = 8;
|
|
17
|
-
const PROFILE_SCAN_MAX_RESULTS = 600;
|
|
18
16
|
export async function promptTraceProfileTargetSelection() {
|
|
19
17
|
// eslint-disable-next-line no-constant-condition
|
|
20
18
|
while (true) {
|
|
@@ -25,7 +23,7 @@ export async function promptTraceProfileTargetSelection() {
|
|
|
25
23
|
{
|
|
26
24
|
name: 'Pick folder from workspace',
|
|
27
25
|
emoji: '📁',
|
|
28
|
-
description: 'Profile all TypeScript work under
|
|
26
|
+
description: 'Profile all TypeScript work under any workspace folder',
|
|
29
27
|
handler: async () => {
|
|
30
28
|
selected = await pickProfileDirectoryFromWorkspace();
|
|
31
29
|
},
|
|
@@ -33,7 +31,7 @@ export async function promptTraceProfileTargetSelection() {
|
|
|
33
31
|
{
|
|
34
32
|
name: 'Pick file from workspace',
|
|
35
33
|
emoji: '📄',
|
|
36
|
-
description: 'Profile a single
|
|
34
|
+
description: 'Profile a single file from anywhere in the workspace',
|
|
37
35
|
handler: async () => {
|
|
38
36
|
selected = await pickProfileFileFromWorkspace();
|
|
39
37
|
},
|
|
@@ -116,22 +114,15 @@ async function pickProfileDirectoryFromWorkspace() {
|
|
|
116
114
|
};
|
|
117
115
|
}
|
|
118
116
|
async function pickProfileFileFromWorkspace() {
|
|
119
|
-
const
|
|
120
|
-
title: '
|
|
117
|
+
const chosen = await promptWorkspaceFileSelection({
|
|
118
|
+
title: 'Pick file to profile',
|
|
119
|
+
includeFile: (entry) => SOURCE_EXTENSIONS.has(path.extname(entry.name).toLowerCase()),
|
|
121
120
|
});
|
|
122
|
-
if (!baseSelection)
|
|
123
|
-
return undefined;
|
|
124
|
-
const files = await collectProfileFiles(baseSelection.absolutePath, PROFILE_SCAN_MAX_DEPTH, PROFILE_SCAN_MAX_RESULTS);
|
|
125
|
-
if (!files.length) {
|
|
126
|
-
console.log(colors.yellow(`No TypeScript/JavaScript source files found under ${baseSelection.relativePath || '.'}.`));
|
|
127
|
-
return undefined;
|
|
128
|
-
}
|
|
129
|
-
const chosen = await promptPathCandidate(files, 'Pick file to profile', baseSelection.absolutePath, '📄');
|
|
130
121
|
if (!chosen)
|
|
131
122
|
return undefined;
|
|
132
123
|
return {
|
|
133
124
|
absolutePath: chosen.absolutePath,
|
|
134
|
-
label:
|
|
125
|
+
label: chosen.relativePath,
|
|
135
126
|
kind: 'file',
|
|
136
127
|
};
|
|
137
128
|
}
|
|
@@ -207,17 +198,10 @@ async function pickTraceFolderFromTmp() {
|
|
|
207
198
|
};
|
|
208
199
|
}
|
|
209
200
|
async function pickTraceFileFromWorkspace() {
|
|
210
|
-
const
|
|
211
|
-
title: '
|
|
201
|
+
const chosen = await promptWorkspaceFileSelection({
|
|
202
|
+
title: 'Pick trace.json file',
|
|
203
|
+
includeFile: (entry) => entry.name.toLowerCase() === TRACE_FILE_NAME,
|
|
212
204
|
});
|
|
213
|
-
if (!baseSelection)
|
|
214
|
-
return undefined;
|
|
215
|
-
const files = await collectNamedFiles(baseSelection.absolutePath, TRACE_FILE_NAME, TRACE_SCAN_MAX_DEPTH, TRACE_SCAN_MAX_RESULTS);
|
|
216
|
-
if (!files.length) {
|
|
217
|
-
console.log(colors.yellow('No trace.json files found in that selection.'));
|
|
218
|
-
return undefined;
|
|
219
|
-
}
|
|
220
|
-
const chosen = await promptPathCandidate(files, 'Pick trace.json file', baseSelection.absolutePath, '📦');
|
|
221
205
|
if (!chosen)
|
|
222
206
|
return undefined;
|
|
223
207
|
return resolveTraceDirectoryFromInput(chosen.absolutePath);
|
|
@@ -289,17 +273,6 @@ async function promptPathCandidate(candidates, title, basePath, emoji) {
|
|
|
289
273
|
relativePath: path.relative(basePath, absolutePath).replace(/\\/g, '/') || '.',
|
|
290
274
|
};
|
|
291
275
|
}
|
|
292
|
-
async function collectNamedFiles(rootPath, filename, maxDepth, maxResults) {
|
|
293
|
-
const output = [];
|
|
294
|
-
await walk(rootPath, rootPath, 0, async (absolutePath, relativePath) => {
|
|
295
|
-
if (path.basename(absolutePath).toLowerCase() !== filename)
|
|
296
|
-
return;
|
|
297
|
-
if (output.length >= maxResults)
|
|
298
|
-
return;
|
|
299
|
-
output.push({ absolutePath, relativePath });
|
|
300
|
-
}, maxDepth);
|
|
301
|
-
return output;
|
|
302
|
-
}
|
|
303
276
|
async function collectTraceDirectories(rootPath, maxDepth, maxResults) {
|
|
304
277
|
const output = [];
|
|
305
278
|
await walk(rootPath, rootPath, 0, async (absolutePath, relativePath) => {
|
|
@@ -314,18 +287,6 @@ async function collectTraceDirectories(rootPath, maxDepth, maxResults) {
|
|
|
314
287
|
}, maxDepth);
|
|
315
288
|
return output;
|
|
316
289
|
}
|
|
317
|
-
async function collectProfileFiles(rootPath, maxDepth, maxResults) {
|
|
318
|
-
const output = [];
|
|
319
|
-
await walk(rootPath, rootPath, 0, async (absolutePath, relativePath) => {
|
|
320
|
-
if (output.length >= maxResults)
|
|
321
|
-
return;
|
|
322
|
-
const extension = path.extname(absolutePath).toLowerCase();
|
|
323
|
-
if (!SOURCE_EXTENSIONS.has(extension))
|
|
324
|
-
return;
|
|
325
|
-
output.push({ absolutePath, relativePath });
|
|
326
|
-
}, maxDepth);
|
|
327
|
-
return output;
|
|
328
|
-
}
|
|
329
290
|
async function walk(currentPath, basePath, depth, onEntry, maxDepth) {
|
|
330
291
|
if (depth > maxDepth)
|
|
331
292
|
return;
|