@ff-labs/fff-bun 0.9.4 → 0.9.5-nightly.636cf61
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/examples/glob-bench.ts +5 -11
- package/package.json +9 -9
- package/src/ffi.ts +12 -42
- package/src/finder.ts +1 -1
package/examples/glob-bench.ts
CHANGED
|
@@ -24,9 +24,8 @@ import { Glob as BunGlob } from "bun";
|
|
|
24
24
|
import { FileFinder } from "../src/index";
|
|
25
25
|
|
|
26
26
|
// npm glob — optional. Skip silently if not installed.
|
|
27
|
-
let npmGlob:
|
|
28
|
-
|
|
29
|
-
| null = null;
|
|
27
|
+
let npmGlob: ((pattern: string, opts: { cwd: string }) => Promise<string[]>) | null =
|
|
28
|
+
null;
|
|
30
29
|
try {
|
|
31
30
|
const mod: {
|
|
32
31
|
glob: (pattern: string, opts: { cwd: string }) => Promise<string[]>;
|
|
@@ -61,16 +60,13 @@ function summarize(label: string, samples: Sample[]): void {
|
|
|
61
60
|
const median = sorted[Math.floor(sorted.length / 2)]!;
|
|
62
61
|
const worst = sorted[sorted.length - 1]!;
|
|
63
62
|
const counts = new Set(samples.map((s) => s.count));
|
|
64
|
-
const countStr =
|
|
65
|
-
counts.size === 1 ? `${best.count}` : `[${[...counts].join(", ")}]`;
|
|
63
|
+
const countStr = counts.size === 1 ? `${best.count}` : `[${[...counts].join(", ")}]`;
|
|
66
64
|
console.log(
|
|
67
65
|
`${label.padEnd(16)} best=${best.ms.toFixed(2)}ms median=${median.ms.toFixed(2)}ms worst=${worst.ms.toFixed(2)}ms count=${countStr}`,
|
|
68
66
|
);
|
|
69
67
|
}
|
|
70
68
|
|
|
71
|
-
async function bench<T>(
|
|
72
|
-
fn: () => Promise<T> | T,
|
|
73
|
-
): Promise<{ ms: number; result: T }> {
|
|
69
|
+
async function bench<T>(fn: () => Promise<T> | T): Promise<{ ms: number; result: T }> {
|
|
74
70
|
const start = performance.now();
|
|
75
71
|
const result = await fn();
|
|
76
72
|
return { ms: performance.now() - start, result };
|
|
@@ -152,8 +148,6 @@ const counts = {
|
|
|
152
148
|
console.log(
|
|
153
149
|
`\nNote: fff respects gitignore + skips binaries; Bun.Glob and npm glob walk the raw filesystem. Count differences are expected.`,
|
|
154
150
|
);
|
|
155
|
-
console.log(
|
|
156
|
-
`raw counts: fff=${counts.fff} bun=${counts.bun} npm=${counts.npm}`,
|
|
157
|
-
);
|
|
151
|
+
console.log(`raw counts: fff=${counts.fff} bun=${counts.bun} npm=${counts.npm}`);
|
|
158
152
|
|
|
159
153
|
finder.destroy();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ff-labs/fff-bun",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.5-nightly.636cf61",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "High-performance fuzzy file finder for Bun - perfect for LLM agent tools",
|
|
6
6
|
"type": "module",
|
|
@@ -58,14 +58,14 @@
|
|
|
58
58
|
},
|
|
59
59
|
"homepage": "https://github.com/dmtrKovalenko/fff#readme",
|
|
60
60
|
"optionalDependencies": {
|
|
61
|
-
"@ff-labs/fff-bin-darwin-arm64": "0.9.
|
|
62
|
-
"@ff-labs/fff-bin-darwin-x64": "0.9.
|
|
63
|
-
"@ff-labs/fff-bin-linux-x64-gnu": "0.9.
|
|
64
|
-
"@ff-labs/fff-bin-linux-arm64-gnu": "0.9.
|
|
65
|
-
"@ff-labs/fff-bin-linux-x64-musl": "0.9.
|
|
66
|
-
"@ff-labs/fff-bin-linux-arm64-musl": "0.9.
|
|
67
|
-
"@ff-labs/fff-bin-win32-x64": "0.9.
|
|
68
|
-
"@ff-labs/fff-bin-win32-arm64": "0.9.
|
|
61
|
+
"@ff-labs/fff-bin-darwin-arm64": "0.9.5-nightly.636cf61",
|
|
62
|
+
"@ff-labs/fff-bin-darwin-x64": "0.9.5-nightly.636cf61",
|
|
63
|
+
"@ff-labs/fff-bin-linux-x64-gnu": "0.9.5-nightly.636cf61",
|
|
64
|
+
"@ff-labs/fff-bin-linux-arm64-gnu": "0.9.5-nightly.636cf61",
|
|
65
|
+
"@ff-labs/fff-bin-linux-x64-musl": "0.9.5-nightly.636cf61",
|
|
66
|
+
"@ff-labs/fff-bin-linux-arm64-musl": "0.9.5-nightly.636cf61",
|
|
67
|
+
"@ff-labs/fff-bin-win32-x64": "0.9.5-nightly.636cf61",
|
|
68
|
+
"@ff-labs/fff-bin-win32-arm64": "0.9.5-nightly.636cf61"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
71
|
"@types/bun": "^1.3.8",
|
package/src/ffi.ts
CHANGED
|
@@ -292,9 +292,7 @@ function loadLibrary(): FFFLibrary {
|
|
|
292
292
|
if (lib) return lib;
|
|
293
293
|
|
|
294
294
|
const isEmbedded = embeddedLibPath?.includes("$bunfs") ?? false;
|
|
295
|
-
const binaryPath = isEmbedded
|
|
296
|
-
? embeddedLibPath
|
|
297
|
-
: (findBinary() ?? embeddedLibPath);
|
|
295
|
+
const binaryPath = isEmbedded ? embeddedLibPath : (findBinary() ?? embeddedLibPath);
|
|
298
296
|
if (!binaryPath) {
|
|
299
297
|
throw new Error(libNotFoundMessage());
|
|
300
298
|
}
|
|
@@ -349,9 +347,7 @@ function snakeToCamel(obj: unknown): unknown {
|
|
|
349
347
|
|
|
350
348
|
const result: Record<string, unknown> = {};
|
|
351
349
|
for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {
|
|
352
|
-
const camelKey = key.replace(/_([a-z])/g, (_, letter) =>
|
|
353
|
-
letter.toUpperCase(),
|
|
354
|
-
);
|
|
350
|
+
const camelKey = key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
355
351
|
result[camelKey] = snakeToCamel(value);
|
|
356
352
|
}
|
|
357
353
|
return result;
|
|
@@ -446,8 +442,7 @@ function parseJsonResult<T>(resultPtr: Pointer | null): Result<T> {
|
|
|
446
442
|
const jsonStr = readCString(envelope.handlePtr);
|
|
447
443
|
library.symbols.fff_free_string(asPtr(envelope.handlePtr));
|
|
448
444
|
|
|
449
|
-
if (jsonStr === null || jsonStr === "")
|
|
450
|
-
return { ok: true, value: undefined as T };
|
|
445
|
+
if (jsonStr === null || jsonStr === "") return { ok: true, value: undefined as T };
|
|
451
446
|
|
|
452
447
|
try {
|
|
453
448
|
return { ok: true, value: snakeToCamel(JSON.parse(jsonStr)) as T };
|
|
@@ -748,9 +743,7 @@ function readDirItemStruct(p: number): DirItem {
|
|
|
748
743
|
/**
|
|
749
744
|
* Parse an FffDirSearchResult from a raw FffResult pointer, then free native memory.
|
|
750
745
|
*/
|
|
751
|
-
function parseDirSearchResult(
|
|
752
|
-
resultPtr: Pointer | null,
|
|
753
|
-
): Result<DirSearchResult> {
|
|
746
|
+
function parseDirSearchResult(resultPtr: Pointer | null): Result<DirSearchResult> {
|
|
754
747
|
if (resultPtr === null) {
|
|
755
748
|
return err("FFI returned null pointer");
|
|
756
749
|
}
|
|
@@ -853,9 +846,7 @@ function readMixedItemStruct(p: number): MixedItem {
|
|
|
853
846
|
/**
|
|
854
847
|
* Parse an FffMixedSearchResult from a raw FffResult pointer, then free native memory.
|
|
855
848
|
*/
|
|
856
|
-
function parseMixedSearchResult(
|
|
857
|
-
resultPtr: Pointer | null,
|
|
858
|
-
): Result<MixedSearchResult> {
|
|
849
|
+
function parseMixedSearchResult(resultPtr: Pointer | null): Result<MixedSearchResult> {
|
|
859
850
|
if (resultPtr === null) {
|
|
860
851
|
return err("FFI returned null pointer");
|
|
861
852
|
}
|
|
@@ -1036,16 +1027,10 @@ function readGrepMatchStruct(p: number): GrepMatch {
|
|
|
1036
1027
|
match.fuzzyScore = read.u16(pp, GM_FUZZY_SCORE);
|
|
1037
1028
|
}
|
|
1038
1029
|
if (ctxBeforeCount > 0) {
|
|
1039
|
-
match.contextBefore = readCStringArray(
|
|
1040
|
-
read.ptr(pp, GM_CTX_BEFORE),
|
|
1041
|
-
ctxBeforeCount,
|
|
1042
|
-
);
|
|
1030
|
+
match.contextBefore = readCStringArray(read.ptr(pp, GM_CTX_BEFORE), ctxBeforeCount);
|
|
1043
1031
|
}
|
|
1044
1032
|
if (ctxAfterCount > 0) {
|
|
1045
|
-
match.contextAfter = readCStringArray(
|
|
1046
|
-
read.ptr(pp, GM_CTX_AFTER),
|
|
1047
|
-
ctxAfterCount,
|
|
1048
|
-
);
|
|
1033
|
+
match.contextAfter = readCStringArray(read.ptr(pp, GM_CTX_AFTER), ctxAfterCount);
|
|
1049
1034
|
}
|
|
1050
1035
|
if (read.u8(pp, GM_IS_DEFINITION) !== 0) {
|
|
1051
1036
|
match.isDefinition = true;
|
|
@@ -1327,30 +1312,18 @@ export function ffiGetScanProgress(handle: NativeHandle): Result<ScanProgress> {
|
|
|
1327
1312
|
/**
|
|
1328
1313
|
* Wait for scan to complete.
|
|
1329
1314
|
*/
|
|
1330
|
-
export function ffiWaitForScan(
|
|
1331
|
-
handle: NativeHandle,
|
|
1332
|
-
timeoutMs: number,
|
|
1333
|
-
): Result<boolean> {
|
|
1315
|
+
export function ffiWaitForScan(handle: NativeHandle, timeoutMs: number): Result<boolean> {
|
|
1334
1316
|
const library = loadLibrary();
|
|
1335
|
-
const resultPtr = library.symbols.fff_wait_for_scan(
|
|
1336
|
-
handle,
|
|
1337
|
-
BigInt(timeoutMs),
|
|
1338
|
-
);
|
|
1317
|
+
const resultPtr = library.symbols.fff_wait_for_scan(handle, BigInt(timeoutMs));
|
|
1339
1318
|
return parseBoolResult(resultPtr);
|
|
1340
1319
|
}
|
|
1341
1320
|
|
|
1342
1321
|
/**
|
|
1343
1322
|
* Restart index in new path.
|
|
1344
1323
|
*/
|
|
1345
|
-
export function ffiRestartIndex(
|
|
1346
|
-
handle: NativeHandle,
|
|
1347
|
-
newPath: string,
|
|
1348
|
-
): Result<void> {
|
|
1324
|
+
export function ffiRestartIndex(handle: NativeHandle, newPath: string): Result<void> {
|
|
1349
1325
|
const library = loadLibrary();
|
|
1350
|
-
const resultPtr = library.symbols.fff_restart_index(
|
|
1351
|
-
handle,
|
|
1352
|
-
ptr(encodeString(newPath)),
|
|
1353
|
-
);
|
|
1326
|
+
const resultPtr = library.symbols.fff_restart_index(handle, ptr(encodeString(newPath)));
|
|
1354
1327
|
return parseVoidResult(resultPtr);
|
|
1355
1328
|
}
|
|
1356
1329
|
|
|
@@ -1388,10 +1361,7 @@ export function ffiGetHistoricalQuery(
|
|
|
1388
1361
|
offset: number,
|
|
1389
1362
|
): Result<string | null> {
|
|
1390
1363
|
const library = loadLibrary();
|
|
1391
|
-
const resultPtr = library.symbols.fff_get_historical_query(
|
|
1392
|
-
handle,
|
|
1393
|
-
BigInt(offset),
|
|
1394
|
-
);
|
|
1364
|
+
const resultPtr = library.symbols.fff_get_historical_query(handle, BigInt(offset));
|
|
1395
1365
|
return parseStringResult(resultPtr);
|
|
1396
1366
|
}
|
|
1397
1367
|
|
package/src/finder.ts
CHANGED
|
@@ -507,7 +507,7 @@ export class FileFinder implements FileFinderApi {
|
|
|
507
507
|
if (!guard.ok) return guard;
|
|
508
508
|
|
|
509
509
|
const deadline = Date.now() + timeoutMs;
|
|
510
|
-
while(true) {
|
|
510
|
+
while (true) {
|
|
511
511
|
const progress = this.getScanProgress();
|
|
512
512
|
if (!progress.ok) return progress;
|
|
513
513
|
if (!progress.value.isScanning && progress.value.isWarmupComplete) {
|