@vibgrate/cli 1.0.56 → 1.0.57
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/DOCS.md +1 -1
- package/README.md +2 -2
- package/dist/baseline-NZZNS4UI.js +10 -0
- package/dist/{chunk-RNVZIZNL.js → chunk-43ACU2WV.js} +72 -5
- package/dist/{chunk-PQEUNAVK.js → chunk-H473HICY.js} +283 -80
- package/dist/{chunk-CQMW6PVB.js → chunk-KLJ5NIGX.js} +2 -2
- package/dist/cli.js +4 -4
- package/dist/{fs-Q63DRR7L.js → fs-TWKR3VSL.js} +3 -1
- package/dist/index.js +2 -2
- package/package.json +1 -1
- package/dist/baseline-5ZOILNXB.js +0 -10
package/DOCS.md
CHANGED
package/README.md
CHANGED
|
@@ -350,8 +350,8 @@ The CLI writes per-project score files to `.vibgrate/` inside each detected proj
|
|
|
350
350
|
|
|
351
351
|
## Full docs
|
|
352
352
|
|
|
353
|
-
For full command reference, configuration, scanner details, and advanced examples, see [
|
|
353
|
+
For full command reference, configuration, scanner details, and advanced examples, see [CLI reference](https://vibgrate.com/cli).
|
|
354
354
|
|
|
355
355
|
---
|
|
356
356
|
|
|
357
|
-
Copyright © 2026 Vibgrate. All rights reserved. See [
|
|
357
|
+
Copyright © 2026 Vibgrate. All rights reserved. See [Vibgrate CLI License](https://vibgrate.com/license) for terms.
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// src/utils/fs.ts
|
|
2
|
+
import { execFile } from "child_process";
|
|
2
3
|
import * as fs from "fs/promises";
|
|
3
4
|
import * as os from "os";
|
|
4
5
|
import * as path2 from "path";
|
|
6
|
+
import { promisify } from "util";
|
|
5
7
|
|
|
6
8
|
// src/utils/semaphore.ts
|
|
7
9
|
var Semaphore = class {
|
|
@@ -113,6 +115,7 @@ function escapeRegex(s) {
|
|
|
113
115
|
}
|
|
114
116
|
|
|
115
117
|
// src/utils/fs.ts
|
|
118
|
+
var execFileAsync = promisify(execFile);
|
|
116
119
|
var SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
117
120
|
"node_modules",
|
|
118
121
|
".git",
|
|
@@ -205,6 +208,7 @@ var SKIP_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
205
208
|
// Source maps & lockfiles (large, not useful for drift analysis)
|
|
206
209
|
".map"
|
|
207
210
|
]);
|
|
211
|
+
var EXTRA_SKIP_DIRS = /* @__PURE__ */ new Set([".nuxt", ".output", ".svelte-kit"]);
|
|
208
212
|
var TEXT_CACHE_MAX_BYTES = 1048576;
|
|
209
213
|
var FileCache = class _FileCache {
|
|
210
214
|
/** Directory walk results keyed by rootDir */
|
|
@@ -225,6 +229,10 @@ var FileCache = class _FileCache {
|
|
|
225
229
|
_maxFileSize = 0;
|
|
226
230
|
/** Root dir for relative-path computation (set by the first walkDir call) */
|
|
227
231
|
_rootDir = null;
|
|
232
|
+
/** Cached tree summary captured during the shared walk */
|
|
233
|
+
walkSummary = /* @__PURE__ */ new Map();
|
|
234
|
+
/** Fast lookup for exact filename (e.g. package.json) */
|
|
235
|
+
fileNameIndex = /* @__PURE__ */ new Map();
|
|
228
236
|
/** Set exclude patterns from config (call once before the walk) */
|
|
229
237
|
setExcludePatterns(patterns) {
|
|
230
238
|
this.excludePredicate = compileGlobs(patterns);
|
|
@@ -266,8 +274,12 @@ var FileCache = class _FileCache {
|
|
|
266
274
|
this.walkCache.set(rootDir, promise);
|
|
267
275
|
return promise;
|
|
268
276
|
}
|
|
277
|
+
/** Return tree summary from the cached walk, if available. */
|
|
278
|
+
getWalkSummary(rootDir) {
|
|
279
|
+
return this.walkSummary.get(rootDir);
|
|
280
|
+
}
|
|
269
281
|
/** Additional dirs skipped only by the cached walk (framework outputs) */
|
|
270
|
-
static EXTRA_SKIP =
|
|
282
|
+
static EXTRA_SKIP = EXTRA_SKIP_DIRS;
|
|
271
283
|
async _doWalk(rootDir, onProgress) {
|
|
272
284
|
const results = [];
|
|
273
285
|
const cores = typeof os.availableParallelism === "function" ? os.availableParallelism() : os.cpus().length || 4;
|
|
@@ -328,6 +340,20 @@ var FileCache = class _FileCache {
|
|
|
328
340
|
await Promise.all(subWalks);
|
|
329
341
|
}
|
|
330
342
|
await walk(rootDir);
|
|
343
|
+
let totalDirs = 0;
|
|
344
|
+
const rootNameIndex = /* @__PURE__ */ new Map();
|
|
345
|
+
for (const entry of results) {
|
|
346
|
+
if (entry.isDirectory) totalDirs++;
|
|
347
|
+
if (!entry.isFile) continue;
|
|
348
|
+
const bucket = rootNameIndex.get(entry.name);
|
|
349
|
+
if (bucket) {
|
|
350
|
+
bucket.push(entry.absPath);
|
|
351
|
+
} else {
|
|
352
|
+
rootNameIndex.set(entry.name, [entry.absPath]);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
this.walkSummary.set(rootDir, { totalFiles: foundCount, totalDirs });
|
|
356
|
+
this.fileNameIndex.set(rootDir, rootNameIndex);
|
|
331
357
|
if (onProgress && foundCount !== lastReported) {
|
|
332
358
|
onProgress(foundCount, "");
|
|
333
359
|
}
|
|
@@ -342,13 +368,16 @@ var FileCache = class _FileCache {
|
|
|
342
368
|
return entries.filter((e) => e.isFile && predicate(e.name)).map((e) => e.absPath);
|
|
343
369
|
}
|
|
344
370
|
async findPackageJsonFiles(rootDir) {
|
|
345
|
-
|
|
371
|
+
await this.walkDir(rootDir);
|
|
372
|
+
return this.fileNameIndex.get(rootDir)?.get("package.json") ?? [];
|
|
346
373
|
}
|
|
347
374
|
async findCsprojFiles(rootDir) {
|
|
348
|
-
|
|
375
|
+
const entries = await this.walkDir(rootDir);
|
|
376
|
+
return entries.filter((e) => e.isFile && e.name.endsWith(".csproj")).map((e) => e.absPath);
|
|
349
377
|
}
|
|
350
378
|
async findSolutionFiles(rootDir) {
|
|
351
|
-
|
|
379
|
+
const entries = await this.walkDir(rootDir);
|
|
380
|
+
return entries.filter((e) => e.isFile && e.name.endsWith(".sln")).map((e) => e.absPath);
|
|
352
381
|
}
|
|
353
382
|
// ── File content reading ──
|
|
354
383
|
/**
|
|
@@ -416,6 +445,8 @@ var FileCache = class _FileCache {
|
|
|
416
445
|
/** Release all cached data. Call after the scan completes. */
|
|
417
446
|
clear() {
|
|
418
447
|
this.walkCache.clear();
|
|
448
|
+
this.walkSummary.clear();
|
|
449
|
+
this.fileNameIndex.clear();
|
|
419
450
|
this.textCache.clear();
|
|
420
451
|
this.jsonCache.clear();
|
|
421
452
|
this.existsCache.clear();
|
|
@@ -430,12 +461,14 @@ var FileCache = class _FileCache {
|
|
|
430
461
|
}
|
|
431
462
|
};
|
|
432
463
|
async function quickTreeCount(rootDir, excludePatterns) {
|
|
464
|
+
const native = await quickTreeCountWithRipgrep(rootDir, excludePatterns);
|
|
465
|
+
if (native) return native;
|
|
433
466
|
let totalFiles = 0;
|
|
434
467
|
let totalDirs = 0;
|
|
435
468
|
const cores = typeof os.availableParallelism === "function" ? os.availableParallelism() : os.cpus().length || 4;
|
|
436
469
|
const maxConcurrent = Math.max(8, Math.min(128, cores * 8));
|
|
437
470
|
const sem = new Semaphore(maxConcurrent);
|
|
438
|
-
const extraSkip =
|
|
471
|
+
const extraSkip = EXTRA_SKIP_DIRS;
|
|
439
472
|
const isExcluded = excludePatterns ? compileGlobs(excludePatterns) : null;
|
|
440
473
|
async function count(dir) {
|
|
441
474
|
let entries;
|
|
@@ -462,6 +495,39 @@ async function quickTreeCount(rootDir, excludePatterns) {
|
|
|
462
495
|
await count(rootDir);
|
|
463
496
|
return { totalFiles, totalDirs };
|
|
464
497
|
}
|
|
498
|
+
function normalizeGlobForRipgrep(pattern) {
|
|
499
|
+
return pattern.replace(/\\/g, "/");
|
|
500
|
+
}
|
|
501
|
+
async function quickTreeCountWithRipgrep(rootDir, excludePatterns) {
|
|
502
|
+
const args = ["--files", "--hidden", "--no-ignore", "--null"];
|
|
503
|
+
for (const dir of SKIP_DIRS) {
|
|
504
|
+
args.push("-g", `!**/${dir}/**`);
|
|
505
|
+
}
|
|
506
|
+
for (const dir of EXTRA_SKIP_DIRS) {
|
|
507
|
+
args.push("-g", `!**/${dir}/**`);
|
|
508
|
+
}
|
|
509
|
+
for (const ext of SKIP_EXTENSIONS) {
|
|
510
|
+
args.push("-g", `!**/*${ext}`);
|
|
511
|
+
}
|
|
512
|
+
for (const pattern of excludePatterns ?? []) {
|
|
513
|
+
const trimmed = pattern.trim();
|
|
514
|
+
if (!trimmed) continue;
|
|
515
|
+
args.push("-g", `!${normalizeGlobForRipgrep(trimmed)}`);
|
|
516
|
+
}
|
|
517
|
+
try {
|
|
518
|
+
const { stdout } = await execFileAsync("rg", args, { cwd: rootDir, maxBuffer: 64 * 1024 * 1024, encoding: "utf8" });
|
|
519
|
+
if (!stdout) return { totalFiles: 0, totalDirs: 0 };
|
|
520
|
+
const files = stdout.split("\0").filter(Boolean);
|
|
521
|
+
const dirs = /* @__PURE__ */ new Set();
|
|
522
|
+
for (const file of files) {
|
|
523
|
+
const dir = path2.dirname(file);
|
|
524
|
+
if (dir && dir !== ".") dirs.add(dir);
|
|
525
|
+
}
|
|
526
|
+
return { totalFiles: files.length, totalDirs: dirs.size };
|
|
527
|
+
} catch {
|
|
528
|
+
return null;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
465
531
|
async function countFilesInDir(dir, recursive = true) {
|
|
466
532
|
let count = 0;
|
|
467
533
|
const extraSkip = /* @__PURE__ */ new Set(["obj", "bin", "Debug", "Release", "TestResults"]);
|
|
@@ -555,6 +621,7 @@ export {
|
|
|
555
621
|
Semaphore,
|
|
556
622
|
FileCache,
|
|
557
623
|
quickTreeCount,
|
|
624
|
+
normalizeGlobForRipgrep,
|
|
558
625
|
countFilesInDir,
|
|
559
626
|
findFiles,
|
|
560
627
|
findPackageJsonFiles,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
readTextFile,
|
|
14
14
|
writeJsonFile,
|
|
15
15
|
writeTextFile
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-43ACU2WV.js";
|
|
17
17
|
|
|
18
18
|
// src/scoring/drift-score.ts
|
|
19
19
|
import * as crypto from "crypto";
|
|
@@ -484,14 +484,14 @@ function formatExtended(ext) {
|
|
|
484
484
|
}
|
|
485
485
|
}
|
|
486
486
|
if (ext.tsModernity && ext.tsModernity.typescriptVersion) {
|
|
487
|
-
const
|
|
487
|
+
const ts3 = ext.tsModernity;
|
|
488
488
|
lines.push(chalk.bold.underline(" TypeScript"));
|
|
489
489
|
const parts = [];
|
|
490
|
-
parts.push(`v${
|
|
491
|
-
if (
|
|
492
|
-
else if (
|
|
493
|
-
if (
|
|
494
|
-
if (
|
|
490
|
+
parts.push(`v${ts3.typescriptVersion}`);
|
|
491
|
+
if (ts3.strict === true) parts.push(chalk.green("strict \u2714"));
|
|
492
|
+
else if (ts3.strict === false) parts.push(chalk.yellow("strict \u2716"));
|
|
493
|
+
if (ts3.moduleType) parts.push(ts3.moduleType.toUpperCase());
|
|
494
|
+
if (ts3.target) parts.push(`target: ${ts3.target}`);
|
|
495
495
|
lines.push(` ${parts.join(chalk.dim(" \xB7 "))}`);
|
|
496
496
|
lines.push("");
|
|
497
497
|
}
|
|
@@ -1213,6 +1213,7 @@ import { Command as Command3 } from "commander";
|
|
|
1213
1213
|
import chalk6 from "chalk";
|
|
1214
1214
|
|
|
1215
1215
|
// src/scanners/node-scanner.ts
|
|
1216
|
+
import * as os2 from "os";
|
|
1216
1217
|
import * as path4 from "path";
|
|
1217
1218
|
import * as semver2 from "semver";
|
|
1218
1219
|
|
|
@@ -1314,11 +1315,52 @@ function maxStable(versions) {
|
|
|
1314
1315
|
if (stable.length === 0) return null;
|
|
1315
1316
|
return stable.sort(semver.rcompare)[0] ?? null;
|
|
1316
1317
|
}
|
|
1318
|
+
function parseNpmMetaPayload(data) {
|
|
1319
|
+
let latest = null;
|
|
1320
|
+
let versions = [];
|
|
1321
|
+
if (data && typeof data === "object") {
|
|
1322
|
+
const record = data;
|
|
1323
|
+
const dtLatest = record["dist-tags.latest"];
|
|
1324
|
+
if (typeof dtLatest === "string") latest = dtLatest;
|
|
1325
|
+
const distTags = record["dist-tags"];
|
|
1326
|
+
if (!latest && distTags && typeof distTags === "object" && typeof distTags.latest === "string") {
|
|
1327
|
+
latest = distTags.latest;
|
|
1328
|
+
}
|
|
1329
|
+
const v = record.versions;
|
|
1330
|
+
if (Array.isArray(v)) versions = v.map(String);
|
|
1331
|
+
else if (typeof v === "string") versions = [v];
|
|
1332
|
+
}
|
|
1333
|
+
const stable = stableOnly(versions);
|
|
1334
|
+
const latestStableOverall = maxStable(stable);
|
|
1335
|
+
if (!latest && latestStableOverall) latest = latestStableOverall;
|
|
1336
|
+
return { latest, stableVersions: stable, latestStableOverall };
|
|
1337
|
+
}
|
|
1338
|
+
var BATCH_SIZE = 24;
|
|
1339
|
+
var WINDOWS_MAX_COMMAND_CHARS = 7e3;
|
|
1340
|
+
var POSIX_MAX_COMMAND_CHARS = 3e4;
|
|
1341
|
+
function buildNpmViewChunks(pkgs, platform = process.platform) {
|
|
1342
|
+
const maxCommandChars = platform === "win32" ? WINDOWS_MAX_COMMAND_CHARS : POSIX_MAX_COMMAND_CHARS;
|
|
1343
|
+
const chunks = [];
|
|
1344
|
+
let current = [];
|
|
1345
|
+
let currentChars = 0;
|
|
1346
|
+
for (const pkg2 of pkgs) {
|
|
1347
|
+
const pkgChars = pkg2.length + 1;
|
|
1348
|
+
if (current.length >= BATCH_SIZE || current.length > 0 && currentChars + pkgChars > maxCommandChars) {
|
|
1349
|
+
chunks.push(current);
|
|
1350
|
+
current = [];
|
|
1351
|
+
currentChars = 0;
|
|
1352
|
+
}
|
|
1353
|
+
current.push(pkg2);
|
|
1354
|
+
currentChars += pkgChars;
|
|
1355
|
+
}
|
|
1356
|
+
if (current.length > 0) chunks.push(current);
|
|
1357
|
+
return chunks;
|
|
1358
|
+
}
|
|
1317
1359
|
async function npmViewJson(args, cwd) {
|
|
1318
1360
|
return new Promise((resolve10, reject) => {
|
|
1319
|
-
const
|
|
1361
|
+
const npmCommand = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
1362
|
+
const child = spawn2(npmCommand, ["view", ...args, "--json"], {
|
|
1320
1363
|
cwd,
|
|
1321
|
-
shell: true,
|
|
1322
1364
|
stdio: ["ignore", "pipe", "pipe"]
|
|
1323
1365
|
});
|
|
1324
1366
|
let out = "";
|
|
@@ -1352,56 +1394,127 @@ var NpmCache = class {
|
|
|
1352
1394
|
this.offline = offline;
|
|
1353
1395
|
}
|
|
1354
1396
|
meta = /* @__PURE__ */ new Map();
|
|
1397
|
+
async prefetch(pkgs) {
|
|
1398
|
+
const unique = [...new Set(pkgs.filter(Boolean))];
|
|
1399
|
+
const pending = unique.filter((pkg2) => !this.meta.has(pkg2));
|
|
1400
|
+
if (pending.length === 0) return;
|
|
1401
|
+
const batchPromise = this.sem.run(() => this.fetchBatch(pending));
|
|
1402
|
+
for (const pkg2 of pending) {
|
|
1403
|
+
const promise = batchPromise.then((batch) => batch.get(pkg2) ?? { latest: null, stableVersions: [], latestStableOverall: null });
|
|
1404
|
+
this.meta.set(pkg2, promise);
|
|
1405
|
+
}
|
|
1406
|
+
await batchPromise;
|
|
1407
|
+
}
|
|
1355
1408
|
get(pkg2) {
|
|
1356
1409
|
const existing = this.meta.get(pkg2);
|
|
1357
1410
|
if (existing) return existing;
|
|
1358
|
-
const p = this.sem.run(
|
|
1411
|
+
const p = this.sem.run(() => this.fetchOne(pkg2));
|
|
1412
|
+
this.meta.set(pkg2, p);
|
|
1413
|
+
return p;
|
|
1414
|
+
}
|
|
1415
|
+
async fetchBatch(pkgs) {
|
|
1416
|
+
const out = /* @__PURE__ */ new Map();
|
|
1417
|
+
const remote = [];
|
|
1418
|
+
for (const pkg2 of pkgs) {
|
|
1359
1419
|
const manifestEntry = getManifestEntry(this.manifest, "npm", pkg2);
|
|
1360
1420
|
if (manifestEntry) {
|
|
1361
|
-
const
|
|
1362
|
-
const
|
|
1363
|
-
|
|
1364
|
-
latest: manifestEntry.latest ??
|
|
1365
|
-
stableVersions:
|
|
1366
|
-
latestStableOverall
|
|
1367
|
-
};
|
|
1421
|
+
const stable = stableOnly(manifestEntry.versions ?? []);
|
|
1422
|
+
const latestStableOverall = maxStable(stable);
|
|
1423
|
+
out.set(pkg2, {
|
|
1424
|
+
latest: manifestEntry.latest ?? latestStableOverall,
|
|
1425
|
+
stableVersions: stable,
|
|
1426
|
+
latestStableOverall
|
|
1427
|
+
});
|
|
1428
|
+
} else if (this.offline) {
|
|
1429
|
+
out.set(pkg2, { latest: null, stableVersions: [], latestStableOverall: null });
|
|
1430
|
+
} else {
|
|
1431
|
+
remote.push(pkg2);
|
|
1368
1432
|
}
|
|
1369
|
-
|
|
1370
|
-
|
|
1433
|
+
}
|
|
1434
|
+
if (remote.length === 0) return out;
|
|
1435
|
+
for (const chunk of buildNpmViewChunks(remote)) {
|
|
1436
|
+
const chunkResults = await this.fetchRemoteChunk(chunk);
|
|
1437
|
+
for (const [pkg2, meta] of chunkResults) {
|
|
1438
|
+
out.set(pkg2, meta);
|
|
1371
1439
|
}
|
|
1440
|
+
}
|
|
1441
|
+
return out;
|
|
1442
|
+
}
|
|
1443
|
+
async fetchRemoteChunk(pkgs) {
|
|
1444
|
+
const out = /* @__PURE__ */ new Map();
|
|
1445
|
+
if (pkgs.length === 1) {
|
|
1446
|
+
out.set(pkgs[0], await this.fetchOneRemote(pkgs[0]));
|
|
1447
|
+
return out;
|
|
1448
|
+
}
|
|
1449
|
+
try {
|
|
1450
|
+
const data = await npmViewJson([...pkgs, "dist-tags.latest", "versions"], this.cwd);
|
|
1451
|
+
if (Array.isArray(data)) {
|
|
1452
|
+
for (let i = 0; i < data.length && i < pkgs.length; i++) {
|
|
1453
|
+
out.set(pkgs[i], parseNpmMetaPayload(data[i]));
|
|
1454
|
+
}
|
|
1455
|
+
} else if (data && typeof data === "object") {
|
|
1456
|
+
const record = data;
|
|
1457
|
+
let keyedByPkg = 0;
|
|
1458
|
+
for (const pkg2 of pkgs) {
|
|
1459
|
+
if (pkg2 in record) {
|
|
1460
|
+
out.set(pkg2, parseNpmMetaPayload(record[pkg2]));
|
|
1461
|
+
keyedByPkg++;
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
if (keyedByPkg === 0 && pkgs.length === 1) {
|
|
1465
|
+
out.set(pkgs[0], parseNpmMetaPayload(record));
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
} catch {
|
|
1469
|
+
}
|
|
1470
|
+
for (const pkg2 of pkgs) {
|
|
1471
|
+
if (!out.has(pkg2)) {
|
|
1472
|
+
out.set(pkg2, await this.fetchOneRemote(pkg2));
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
return out;
|
|
1476
|
+
}
|
|
1477
|
+
async fetchOne(pkg2) {
|
|
1478
|
+
const manifestEntry = getManifestEntry(this.manifest, "npm", pkg2);
|
|
1479
|
+
if (manifestEntry) {
|
|
1480
|
+
const stable = stableOnly(manifestEntry.versions ?? []);
|
|
1481
|
+
const latestStableOverall = maxStable(stable);
|
|
1482
|
+
return {
|
|
1483
|
+
latest: manifestEntry.latest ?? latestStableOverall,
|
|
1484
|
+
stableVersions: stable,
|
|
1485
|
+
latestStableOverall
|
|
1486
|
+
};
|
|
1487
|
+
}
|
|
1488
|
+
if (this.offline) {
|
|
1489
|
+
return { latest: null, stableVersions: [], latestStableOverall: null };
|
|
1490
|
+
}
|
|
1491
|
+
return this.fetchOneRemote(pkg2);
|
|
1492
|
+
}
|
|
1493
|
+
async fetchOneRemote(pkg2) {
|
|
1494
|
+
try {
|
|
1495
|
+
const data = await npmViewJson([pkg2, "dist-tags.latest", "versions"], this.cwd);
|
|
1496
|
+
return parseNpmMetaPayload(data);
|
|
1497
|
+
} catch {
|
|
1372
1498
|
let latest = null;
|
|
1373
1499
|
let versions = [];
|
|
1374
1500
|
try {
|
|
1375
|
-
const
|
|
1376
|
-
if (
|
|
1377
|
-
|
|
1378
|
-
if (typeof dt === "string") latest = dt;
|
|
1379
|
-
const v = data.versions;
|
|
1380
|
-
if (Array.isArray(v)) versions = v.map(String);
|
|
1381
|
-
else if (typeof v === "string") versions = [v];
|
|
1501
|
+
const dist = await npmViewJson([pkg2, "dist-tags"], this.cwd);
|
|
1502
|
+
if (dist && typeof dist === "object" && typeof dist.latest === "string") {
|
|
1503
|
+
latest = dist.latest;
|
|
1382
1504
|
}
|
|
1383
1505
|
} catch {
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
}
|
|
1391
|
-
try {
|
|
1392
|
-
const v = await npmViewJson([pkg2, "versions"], this.cwd);
|
|
1393
|
-
if (Array.isArray(v)) versions = v.map(String);
|
|
1394
|
-
else if (typeof v === "string") versions = [v];
|
|
1395
|
-
} catch {
|
|
1396
|
-
}
|
|
1506
|
+
}
|
|
1507
|
+
try {
|
|
1508
|
+
const v = await npmViewJson([pkg2, "versions"], this.cwd);
|
|
1509
|
+
if (Array.isArray(v)) versions = v.map(String);
|
|
1510
|
+
else if (typeof v === "string") versions = [v];
|
|
1511
|
+
} catch {
|
|
1397
1512
|
}
|
|
1398
1513
|
const stable = stableOnly(versions);
|
|
1399
1514
|
const latestStableOverall = maxStable(stable);
|
|
1400
1515
|
if (!latest && latestStableOverall) latest = latestStableOverall;
|
|
1401
1516
|
return { latest, stableVersions: stable, latestStableOverall };
|
|
1402
|
-
}
|
|
1403
|
-
this.meta.set(pkg2, p);
|
|
1404
|
-
return p;
|
|
1517
|
+
}
|
|
1405
1518
|
}
|
|
1406
1519
|
};
|
|
1407
1520
|
async function checkRegistryAccess(cwd) {
|
|
@@ -1514,24 +1627,32 @@ async function scanNodeProjects(rootDir, npmCache, cache) {
|
|
|
1514
1627
|
const results = [];
|
|
1515
1628
|
const packageNameToPath = /* @__PURE__ */ new Map();
|
|
1516
1629
|
const STUCK_TIMEOUT_MS = 6e4;
|
|
1517
|
-
|
|
1630
|
+
const cores = typeof os2.availableParallelism === "function" ? os2.availableParallelism() : os2.cpus().length || 4;
|
|
1631
|
+
const projectConcurrency = Math.max(2, Math.min(16, cores * 2));
|
|
1632
|
+
const projectSem = new Semaphore(projectConcurrency);
|
|
1633
|
+
const scannedProjects = await Promise.all(packageJsonFiles.map(async (pjPath) => projectSem.run(async () => {
|
|
1518
1634
|
try {
|
|
1519
1635
|
const scanPromise = scanOnePackageJson(pjPath, rootDir, npmCache, cache);
|
|
1520
1636
|
const result = await withTimeout(scanPromise, STUCK_TIMEOUT_MS);
|
|
1521
1637
|
if (result.ok) {
|
|
1522
|
-
|
|
1523
|
-
packageNameToPath.set(result.value.name, result.value.path);
|
|
1524
|
-
} else {
|
|
1525
|
-
const relPath = path4.relative(rootDir, path4.dirname(pjPath));
|
|
1526
|
-
if (cache) {
|
|
1527
|
-
cache.addStuckPath(relPath || ".");
|
|
1528
|
-
}
|
|
1529
|
-
console.error(`Timeout scanning ${pjPath} (>${STUCK_TIMEOUT_MS / 1e3}s) \u2014 skipped`);
|
|
1638
|
+
return result.value;
|
|
1530
1639
|
}
|
|
1640
|
+
const relPath = path4.relative(rootDir, path4.dirname(pjPath));
|
|
1641
|
+
if (cache) {
|
|
1642
|
+
cache.addStuckPath(relPath || ".");
|
|
1643
|
+
}
|
|
1644
|
+
console.error(`Timeout scanning ${pjPath} (>${STUCK_TIMEOUT_MS / 1e3}s) \u2014 skipped`);
|
|
1645
|
+
return null;
|
|
1531
1646
|
} catch (e) {
|
|
1532
1647
|
const msg = e instanceof Error ? e.message : String(e);
|
|
1533
1648
|
console.error(`Error scanning ${pjPath}: ${msg}`);
|
|
1649
|
+
return null;
|
|
1534
1650
|
}
|
|
1651
|
+
})));
|
|
1652
|
+
for (const project of scannedProjects) {
|
|
1653
|
+
if (!project) continue;
|
|
1654
|
+
results.push(project);
|
|
1655
|
+
packageNameToPath.set(project.name, project.path);
|
|
1535
1656
|
}
|
|
1536
1657
|
for (const project of results) {
|
|
1537
1658
|
const workspaceRefs = [];
|
|
@@ -1584,6 +1705,7 @@ async function scanOnePackageJson(packageJsonPath, rootDir, npmCache, cache) {
|
|
|
1584
1705
|
depEntries.push({ pkg: pkg2, section: s.name, spec });
|
|
1585
1706
|
}
|
|
1586
1707
|
}
|
|
1708
|
+
await npmCache.prefetch(depEntries.map((entry) => entry.pkg));
|
|
1587
1709
|
const metaPromises = depEntries.map(async (entry) => {
|
|
1588
1710
|
const meta = await npmCache.get(entry.pkg);
|
|
1589
1711
|
return { ...entry, meta };
|
|
@@ -2338,7 +2460,7 @@ async function scanPythonProjects(rootDir, pypiCache, cache) {
|
|
|
2338
2460
|
return results;
|
|
2339
2461
|
}
|
|
2340
2462
|
async function findPythonManifests(rootDir) {
|
|
2341
|
-
const { findFiles: findFiles2 } = await import("./fs-
|
|
2463
|
+
const { findFiles: findFiles2 } = await import("./fs-TWKR3VSL.js");
|
|
2342
2464
|
return findFiles2(rootDir, (name) => PYTHON_MANIFEST_FILES.has(name) || /^requirements.*\.txt$/.test(name));
|
|
2343
2465
|
}
|
|
2344
2466
|
async function scanOnePythonProject(dir, manifestFiles, rootDir, pypiCache, cache) {
|
|
@@ -2737,7 +2859,7 @@ async function scanJavaProjects(rootDir, mavenCache, cache) {
|
|
|
2737
2859
|
return results;
|
|
2738
2860
|
}
|
|
2739
2861
|
async function findJavaManifests(rootDir) {
|
|
2740
|
-
const { findFiles: findFiles2 } = await import("./fs-
|
|
2862
|
+
const { findFiles: findFiles2 } = await import("./fs-TWKR3VSL.js");
|
|
2741
2863
|
return findFiles2(rootDir, (name) => JAVA_MANIFEST_FILES.has(name));
|
|
2742
2864
|
}
|
|
2743
2865
|
async function scanOneJavaProject(dir, manifestFiles, rootDir, mavenCache, cache) {
|
|
@@ -3225,11 +3347,74 @@ var MavenCache = class {
|
|
|
3225
3347
|
// src/config.ts
|
|
3226
3348
|
import * as path9 from "path";
|
|
3227
3349
|
import * as fs from "fs/promises";
|
|
3350
|
+
import ts from "typescript";
|
|
3228
3351
|
var CONFIG_FILES = [
|
|
3229
3352
|
"vibgrate.config.ts",
|
|
3230
3353
|
"vibgrate.config.js",
|
|
3231
3354
|
"vibgrate.config.json"
|
|
3232
3355
|
];
|
|
3356
|
+
var TRUSTED_CONFIG_ENV = "VIBGRATE_TRUST_CONFIG";
|
|
3357
|
+
function isRecord(value) {
|
|
3358
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3359
|
+
}
|
|
3360
|
+
function toStaticValue(expr, constBindings) {
|
|
3361
|
+
if (ts.isParenthesizedExpression(expr)) return toStaticValue(expr.expression, constBindings);
|
|
3362
|
+
if (ts.isStringLiteralLike(expr)) return expr.text;
|
|
3363
|
+
if (ts.isNumericLiteral(expr)) return Number(expr.text);
|
|
3364
|
+
if (expr.kind === ts.SyntaxKind.TrueKeyword) return true;
|
|
3365
|
+
if (expr.kind === ts.SyntaxKind.FalseKeyword) return false;
|
|
3366
|
+
if (expr.kind === ts.SyntaxKind.NullKeyword) return null;
|
|
3367
|
+
if (ts.isArrayLiteralExpression(expr)) {
|
|
3368
|
+
return expr.elements.map((el) => {
|
|
3369
|
+
if (ts.isSpreadElement(el)) throw new Error("Spread not supported in static config arrays");
|
|
3370
|
+
return toStaticValue(el, constBindings);
|
|
3371
|
+
});
|
|
3372
|
+
}
|
|
3373
|
+
if (ts.isObjectLiteralExpression(expr)) {
|
|
3374
|
+
const out = {};
|
|
3375
|
+
for (const prop of expr.properties) {
|
|
3376
|
+
if (!ts.isPropertyAssignment(prop) || prop.initializer === void 0) {
|
|
3377
|
+
throw new Error("Only plain object properties are supported in static config");
|
|
3378
|
+
}
|
|
3379
|
+
if (ts.isComputedPropertyName(prop.name)) {
|
|
3380
|
+
throw new Error("Computed property names are not supported in static config");
|
|
3381
|
+
}
|
|
3382
|
+
const key = ts.isIdentifier(prop.name) ? prop.name.text : ts.isStringLiteral(prop.name) ? prop.name.text : ts.isNumericLiteral(prop.name) ? prop.name.text : null;
|
|
3383
|
+
if (key === null) {
|
|
3384
|
+
throw new Error("Unsupported object key in static config");
|
|
3385
|
+
}
|
|
3386
|
+
out[key] = toStaticValue(prop.initializer, constBindings);
|
|
3387
|
+
}
|
|
3388
|
+
return out;
|
|
3389
|
+
}
|
|
3390
|
+
if (ts.isIdentifier(expr)) {
|
|
3391
|
+
const bound = constBindings.get(expr.text);
|
|
3392
|
+
if (!bound) throw new Error(`Unknown identifier in static config: ${expr.text}`);
|
|
3393
|
+
return toStaticValue(bound, constBindings);
|
|
3394
|
+
}
|
|
3395
|
+
throw new Error("Non-static expression in config");
|
|
3396
|
+
}
|
|
3397
|
+
function tryParseStaticConfig(text, configPath) {
|
|
3398
|
+
const scriptKind = configPath.endsWith(".ts") ? ts.ScriptKind.TS : ts.ScriptKind.JS;
|
|
3399
|
+
const source = ts.createSourceFile(configPath, text, ts.ScriptTarget.ESNext, true, scriptKind);
|
|
3400
|
+
const constBindings = /* @__PURE__ */ new Map();
|
|
3401
|
+
for (const stmt of source.statements) {
|
|
3402
|
+
if (!ts.isVariableStatement(stmt)) continue;
|
|
3403
|
+
if (!(stmt.declarationList.flags & ts.NodeFlags.Const)) continue;
|
|
3404
|
+
for (const decl of stmt.declarationList.declarations) {
|
|
3405
|
+
if (ts.isIdentifier(decl.name) && decl.initializer) {
|
|
3406
|
+
constBindings.set(decl.name.text, decl.initializer);
|
|
3407
|
+
}
|
|
3408
|
+
}
|
|
3409
|
+
}
|
|
3410
|
+
for (const stmt of source.statements) {
|
|
3411
|
+
if (!ts.isExportAssignment(stmt)) continue;
|
|
3412
|
+
const parsed = toStaticValue(stmt.expression, constBindings);
|
|
3413
|
+
if (!isRecord(parsed)) return null;
|
|
3414
|
+
return { ...DEFAULT_CONFIG, ...parsed };
|
|
3415
|
+
}
|
|
3416
|
+
return null;
|
|
3417
|
+
}
|
|
3233
3418
|
var DEFAULT_MAX_FILE_SIZE = 5242880;
|
|
3234
3419
|
var DEFAULT_CONFIG = {
|
|
3235
3420
|
exclude: [],
|
|
@@ -3252,15 +3437,28 @@ async function loadConfig(rootDir) {
|
|
|
3252
3437
|
const configPath = path9.join(rootDir, file);
|
|
3253
3438
|
if (await pathExists(configPath)) {
|
|
3254
3439
|
if (file.endsWith(".json")) {
|
|
3255
|
-
const
|
|
3256
|
-
config = { ...DEFAULT_CONFIG, ...JSON.parse(
|
|
3440
|
+
const txt2 = await readTextFile(configPath);
|
|
3441
|
+
config = { ...DEFAULT_CONFIG, ...JSON.parse(txt2) };
|
|
3257
3442
|
break;
|
|
3258
3443
|
}
|
|
3444
|
+
const txt = await readTextFile(configPath);
|
|
3445
|
+
let staticConfig = null;
|
|
3259
3446
|
try {
|
|
3260
|
-
|
|
3261
|
-
config = { ...DEFAULT_CONFIG, ...mod.default ?? mod };
|
|
3262
|
-
break;
|
|
3447
|
+
staticConfig = tryParseStaticConfig(txt, configPath);
|
|
3263
3448
|
} catch {
|
|
3449
|
+
staticConfig = null;
|
|
3450
|
+
}
|
|
3451
|
+
if (staticConfig) {
|
|
3452
|
+
config = staticConfig;
|
|
3453
|
+
break;
|
|
3454
|
+
}
|
|
3455
|
+
if (process.env[TRUSTED_CONFIG_ENV] === "1") {
|
|
3456
|
+
try {
|
|
3457
|
+
const mod = await import(configPath);
|
|
3458
|
+
config = { ...DEFAULT_CONFIG, ...mod.default ?? mod };
|
|
3459
|
+
break;
|
|
3460
|
+
} catch {
|
|
3461
|
+
}
|
|
3264
3462
|
}
|
|
3265
3463
|
}
|
|
3266
3464
|
}
|
|
@@ -6587,7 +6785,7 @@ async function scanArchitecture(rootDir, projects, tooling, services, cache) {
|
|
|
6587
6785
|
|
|
6588
6786
|
// src/scanners/code-quality.ts
|
|
6589
6787
|
import * as path21 from "path";
|
|
6590
|
-
import * as
|
|
6788
|
+
import * as ts2 from "typescript";
|
|
6591
6789
|
var SOURCE_EXTENSIONS2 = /* @__PURE__ */ new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
6592
6790
|
var DEFAULT_RESULT = {
|
|
6593
6791
|
filesAnalyzed: 0,
|
|
@@ -6618,7 +6816,7 @@ async function scanCodeQuality(rootDir, cache) {
|
|
|
6618
6816
|
}
|
|
6619
6817
|
if (!raw.trim()) continue;
|
|
6620
6818
|
const rel = normalizeModuleId(path21.relative(rootDir, filePath));
|
|
6621
|
-
const source =
|
|
6819
|
+
const source = ts2.createSourceFile(filePath, raw, ts2.ScriptTarget.Latest, true);
|
|
6622
6820
|
const imports = collectLocalImports(source, path21.dirname(filePath), rootDir);
|
|
6623
6821
|
depGraph.set(rel, imports);
|
|
6624
6822
|
const fileMetrics = computeFileMetrics(source, raw);
|
|
@@ -6661,11 +6859,11 @@ async function findSourceFiles(rootDir, cache) {
|
|
|
6661
6859
|
function collectLocalImports(source, fileDir, rootDir) {
|
|
6662
6860
|
const deps = /* @__PURE__ */ new Set();
|
|
6663
6861
|
const visit = (node) => {
|
|
6664
|
-
if (
|
|
6862
|
+
if (ts2.isImportDeclaration(node) && ts2.isStringLiteral(node.moduleSpecifier)) {
|
|
6665
6863
|
const target = resolveLocalImport(node.moduleSpecifier.text, fileDir, rootDir);
|
|
6666
6864
|
if (target) deps.add(target);
|
|
6667
6865
|
}
|
|
6668
|
-
if (
|
|
6866
|
+
if (ts2.isCallExpression(node) && node.expression.kind === ts2.SyntaxKind.ImportKeyword && node.arguments[0] && ts2.isStringLiteral(node.arguments[0])) {
|
|
6669
6867
|
const target = resolveLocalImport(node.arguments[0].text, fileDir, rootDir);
|
|
6670
6868
|
if (target) deps.add(target);
|
|
6671
6869
|
}
|
|
@@ -6701,7 +6899,7 @@ function computeFileMetrics(source, raw) {
|
|
|
6701
6899
|
totalFunctionLength += lineLength;
|
|
6702
6900
|
maxNestingDepth = Math.max(maxNestingDepth, nestingDepth);
|
|
6703
6901
|
}
|
|
6704
|
-
if (
|
|
6902
|
+
if (ts2.isFunctionDeclaration(node) && node.name) {
|
|
6705
6903
|
functionDecls.push(node);
|
|
6706
6904
|
}
|
|
6707
6905
|
visitEach(node, visit);
|
|
@@ -6728,20 +6926,20 @@ function computeCyclomatic(fn) {
|
|
|
6728
6926
|
let complexity = 1;
|
|
6729
6927
|
const visit = (node) => {
|
|
6730
6928
|
switch (node.kind) {
|
|
6731
|
-
case
|
|
6732
|
-
case
|
|
6733
|
-
case
|
|
6734
|
-
case
|
|
6735
|
-
case
|
|
6736
|
-
case
|
|
6737
|
-
case
|
|
6738
|
-
case
|
|
6739
|
-
case
|
|
6929
|
+
case ts2.SyntaxKind.IfStatement:
|
|
6930
|
+
case ts2.SyntaxKind.ForStatement:
|
|
6931
|
+
case ts2.SyntaxKind.ForOfStatement:
|
|
6932
|
+
case ts2.SyntaxKind.ForInStatement:
|
|
6933
|
+
case ts2.SyntaxKind.WhileStatement:
|
|
6934
|
+
case ts2.SyntaxKind.DoStatement:
|
|
6935
|
+
case ts2.SyntaxKind.CaseClause:
|
|
6936
|
+
case ts2.SyntaxKind.CatchClause:
|
|
6937
|
+
case ts2.SyntaxKind.ConditionalExpression:
|
|
6740
6938
|
complexity++;
|
|
6741
6939
|
break;
|
|
6742
|
-
case
|
|
6940
|
+
case ts2.SyntaxKind.BinaryExpression: {
|
|
6743
6941
|
const be = node;
|
|
6744
|
-
if (be.operatorToken.kind ===
|
|
6942
|
+
if (be.operatorToken.kind === ts2.SyntaxKind.AmpersandAmpersandToken || be.operatorToken.kind === ts2.SyntaxKind.BarBarToken || be.operatorToken.kind === ts2.SyntaxKind.QuestionQuestionToken) {
|
|
6745
6943
|
complexity++;
|
|
6746
6944
|
}
|
|
6747
6945
|
break;
|
|
@@ -6793,15 +6991,15 @@ function computeNodeLineLength(source, node) {
|
|
|
6793
6991
|
return end - start + 1;
|
|
6794
6992
|
}
|
|
6795
6993
|
function isFunctionLike(node) {
|
|
6796
|
-
return
|
|
6994
|
+
return ts2.isFunctionDeclaration(node) || ts2.isMethodDeclaration(node) || ts2.isFunctionExpression(node) || ts2.isArrowFunction(node) || ts2.isConstructorDeclaration(node);
|
|
6797
6995
|
}
|
|
6798
6996
|
function isNestingNode(node) {
|
|
6799
|
-
return node.kind ===
|
|
6997
|
+
return node.kind === ts2.SyntaxKind.IfStatement || node.kind === ts2.SyntaxKind.ForStatement || node.kind === ts2.SyntaxKind.ForOfStatement || node.kind === ts2.SyntaxKind.ForInStatement || node.kind === ts2.SyntaxKind.WhileStatement || node.kind === ts2.SyntaxKind.DoStatement || node.kind === ts2.SyntaxKind.SwitchStatement || node.kind === ts2.SyntaxKind.TryStatement || node.kind === ts2.SyntaxKind.CatchClause;
|
|
6800
6998
|
}
|
|
6801
6999
|
function isExported(node) {
|
|
6802
|
-
if (!
|
|
6803
|
-
const modifiers =
|
|
6804
|
-
return !!modifiers?.some((m) => m.kind ===
|
|
7000
|
+
if (!ts2.canHaveModifiers(node)) return false;
|
|
7001
|
+
const modifiers = ts2.getModifiers(node);
|
|
7002
|
+
return !!modifiers?.some((m) => m.kind === ts2.SyntaxKind.ExportKeyword);
|
|
6805
7003
|
}
|
|
6806
7004
|
function countWholeWord(input, word) {
|
|
6807
7005
|
const re = new RegExp(`\\b${escapeRegExp(word)}\\b`, "g");
|
|
@@ -7513,8 +7711,9 @@ async function runScan(rootDir, opts) {
|
|
|
7513
7711
|
console.error(msg);
|
|
7514
7712
|
process.exit(1);
|
|
7515
7713
|
}
|
|
7714
|
+
const treeCountPromise = quickTreeCount(rootDir, excludePatterns);
|
|
7516
7715
|
progress.startStep("discovery");
|
|
7517
|
-
const treeCount = await
|
|
7716
|
+
const treeCount = await treeCountPromise;
|
|
7518
7717
|
progress.updateStats({ treeSummary: treeCount });
|
|
7519
7718
|
progress.completeStep(
|
|
7520
7719
|
"discovery",
|
|
@@ -7532,6 +7731,10 @@ async function runScan(rootDir, opts) {
|
|
|
7532
7731
|
await fileCache.walkDir(rootDir, (found, currentPath) => {
|
|
7533
7732
|
progress.updateStepProgress("walk", found, treeCount.totalFiles, currentPath);
|
|
7534
7733
|
});
|
|
7734
|
+
const indexedTreeCount = fileCache.getWalkSummary(rootDir);
|
|
7735
|
+
if (indexedTreeCount && (indexedTreeCount.totalFiles !== treeCount.totalFiles || indexedTreeCount.totalDirs !== treeCount.totalDirs)) {
|
|
7736
|
+
progress.updateStats({ treeSummary: indexedTreeCount });
|
|
7737
|
+
}
|
|
7535
7738
|
progress.completeStep("walk", `${treeCount.totalFiles.toLocaleString()} files indexed`);
|
|
7536
7739
|
progress.startStep("node");
|
|
7537
7740
|
const nodeProjects = await scanNodeProjects(rootDir, npmCache, fileCache);
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
baselineCommand
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-KLJ5NIGX.js";
|
|
5
5
|
import {
|
|
6
6
|
VERSION,
|
|
7
7
|
dsnCommand,
|
|
@@ -10,13 +10,13 @@ import {
|
|
|
10
10
|
pushCommand,
|
|
11
11
|
scanCommand,
|
|
12
12
|
writeDefaultConfig
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-H473HICY.js";
|
|
14
14
|
import {
|
|
15
15
|
ensureDir,
|
|
16
16
|
pathExists,
|
|
17
17
|
readJsonFile,
|
|
18
18
|
writeTextFile
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-43ACU2WV.js";
|
|
20
20
|
|
|
21
21
|
// src/cli.ts
|
|
22
22
|
import { Command as Command6 } from "commander";
|
|
@@ -39,7 +39,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
|
|
|
39
39
|
console.log(chalk.green("\u2714") + ` Created ${chalk.bold("vibgrate.config.ts")}`);
|
|
40
40
|
}
|
|
41
41
|
if (opts.baseline) {
|
|
42
|
-
const { runBaseline } = await import("./baseline-
|
|
42
|
+
const { runBaseline } = await import("./baseline-NZZNS4UI.js");
|
|
43
43
|
await runBaseline(rootDir);
|
|
44
44
|
}
|
|
45
45
|
console.log("");
|
|
@@ -6,13 +6,14 @@ import {
|
|
|
6
6
|
findFiles,
|
|
7
7
|
findPackageJsonFiles,
|
|
8
8
|
findSolutionFiles,
|
|
9
|
+
normalizeGlobForRipgrep,
|
|
9
10
|
pathExists,
|
|
10
11
|
quickTreeCount,
|
|
11
12
|
readJsonFile,
|
|
12
13
|
readTextFile,
|
|
13
14
|
writeJsonFile,
|
|
14
15
|
writeTextFile
|
|
15
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-43ACU2WV.js";
|
|
16
17
|
export {
|
|
17
18
|
FileCache,
|
|
18
19
|
countFilesInDir,
|
|
@@ -21,6 +22,7 @@ export {
|
|
|
21
22
|
findFiles,
|
|
22
23
|
findPackageJsonFiles,
|
|
23
24
|
findSolutionFiles,
|
|
25
|
+
normalizeGlobForRipgrep,
|
|
24
26
|
pathExists,
|
|
25
27
|
quickTreeCount,
|
|
26
28
|
readJsonFile,
|
package/dist/index.js
CHANGED
package/package.json
CHANGED