@ff-labs/fff-bun 0.1.0-nightly.fcdf4a9 → 0.2.4-dev.8d9ef38
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 +18 -18
- package/examples/grep.ts +1 -1
- package/package.json +9 -14
- package/src/download.ts +20 -143
- package/src/ffi.ts +638 -124
- package/src/finder.ts +55 -57
- package/src/git-lifecycle.test.ts +7 -7
- package/src/index.test.ts +13 -21
- package/src/index.ts +2 -6
- package/src/platform.ts +9 -9
- package/src/types.ts +0 -131
- package/bin/libfff_c.dylib +0 -0
- package/scripts/cli.ts +0 -116
- package/scripts/postinstall.ts +0 -49
package/src/finder.ts
CHANGED
|
@@ -40,33 +40,7 @@ import type {
|
|
|
40
40
|
SearchResult,
|
|
41
41
|
} from "./types";
|
|
42
42
|
|
|
43
|
-
import {
|
|
44
|
-
createGrepCursor,
|
|
45
|
-
err,
|
|
46
|
-
toInternalGrepOptions,
|
|
47
|
-
toInternalInitOptions,
|
|
48
|
-
toInternalMultiGrepOptions,
|
|
49
|
-
toInternalSearchOptions,
|
|
50
|
-
} from "./types";
|
|
51
|
-
|
|
52
|
-
/** Transform raw FFI grep result into typed GrepResult with opaque cursor. */
|
|
53
|
-
function transformGrepResult(result: Result<unknown>): Result<GrepResult> {
|
|
54
|
-
if (!result.ok) {
|
|
55
|
-
return result;
|
|
56
|
-
}
|
|
57
|
-
const raw = result.value as Record<string, unknown>;
|
|
58
|
-
const nextFileOffset = raw.nextFileOffset as number;
|
|
59
|
-
const grepResult: GrepResult = {
|
|
60
|
-
items: raw.items as GrepResult["items"],
|
|
61
|
-
totalMatched: raw.totalMatched as number,
|
|
62
|
-
totalFilesSearched: raw.totalFilesSearched as number,
|
|
63
|
-
totalFiles: raw.totalFiles as number,
|
|
64
|
-
filteredFileCount: raw.filteredFileCount as number,
|
|
65
|
-
nextCursor: nextFileOffset > 0 ? createGrepCursor(nextFileOffset) : null,
|
|
66
|
-
regexFallbackError: raw.regexFallbackError as string | undefined,
|
|
67
|
-
};
|
|
68
|
-
return { ok: true, value: grepResult };
|
|
69
|
-
}
|
|
43
|
+
import { err } from "./types";
|
|
70
44
|
|
|
71
45
|
/**
|
|
72
46
|
* FileFinder - Fast file finder with fuzzy search
|
|
@@ -127,8 +101,14 @@ export class FileFinder {
|
|
|
127
101
|
* ```
|
|
128
102
|
*/
|
|
129
103
|
static create(options: InitOptions): Result<FileFinder> {
|
|
130
|
-
const
|
|
131
|
-
|
|
104
|
+
const result = ffiCreate(
|
|
105
|
+
options.basePath,
|
|
106
|
+
options.frecencyDbPath ?? "",
|
|
107
|
+
options.historyDbPath ?? "",
|
|
108
|
+
options.useUnsafeNoLock ?? false,
|
|
109
|
+
options.warmupMmapCache ?? false,
|
|
110
|
+
options.aiMode ?? false,
|
|
111
|
+
);
|
|
132
112
|
|
|
133
113
|
if (!result.ok) {
|
|
134
114
|
return result;
|
|
@@ -192,18 +172,20 @@ export class FileFinder {
|
|
|
192
172
|
* }
|
|
193
173
|
* ```
|
|
194
174
|
*/
|
|
195
|
-
|
|
175
|
+
fileSearch(query: string, options?: SearchOptions): Result<SearchResult> {
|
|
196
176
|
const guard = this.ensureAlive();
|
|
197
177
|
if (!guard.ok) return guard;
|
|
198
178
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
179
|
+
return ffiSearch(
|
|
180
|
+
guard.value,
|
|
181
|
+
query,
|
|
182
|
+
options?.currentFile ?? "",
|
|
183
|
+
options?.maxThreads ?? 0,
|
|
184
|
+
options?.pageIndex ?? 0,
|
|
185
|
+
options?.pageSize ?? 0,
|
|
186
|
+
options?.comboBoostMultiplier ?? 0,
|
|
187
|
+
options?.minComboCount ?? 0,
|
|
188
|
+
);
|
|
207
189
|
}
|
|
208
190
|
|
|
209
191
|
/**
|
|
@@ -228,28 +210,38 @@ export class FileFinder {
|
|
|
228
210
|
* @example
|
|
229
211
|
* ```typescript
|
|
230
212
|
* // First page
|
|
231
|
-
* const result = finder.
|
|
213
|
+
* const result = finder.grep("TODO", { mode: "plain" });
|
|
232
214
|
* if (result.ok) {
|
|
233
215
|
* for (const match of result.value.items) {
|
|
234
216
|
* console.log(`${match.relativePath}:${match.lineNumber}: ${match.lineContent}`);
|
|
235
217
|
* }
|
|
236
218
|
* // Fetch next page
|
|
237
219
|
* if (result.value.nextCursor) {
|
|
238
|
-
* const page2 = finder.
|
|
220
|
+
* const page2 = finder.grep("TODO", {
|
|
239
221
|
* cursor: result.value.nextCursor,
|
|
240
222
|
* });
|
|
241
223
|
* }
|
|
242
224
|
* }
|
|
243
225
|
* ```
|
|
244
226
|
*/
|
|
245
|
-
|
|
227
|
+
grep(query: string, options?: GrepOptions): Result<GrepResult> {
|
|
246
228
|
const guard = this.ensureAlive();
|
|
247
229
|
if (!guard.ok) return guard;
|
|
248
230
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
231
|
+
return ffiLiveGrep(
|
|
232
|
+
guard.value,
|
|
233
|
+
query,
|
|
234
|
+
options?.mode ?? "plain",
|
|
235
|
+
options?.maxFileSize ?? 0,
|
|
236
|
+
options?.maxMatchesPerFile ?? 0,
|
|
237
|
+
options?.smartCase ?? true,
|
|
238
|
+
options?.cursor?._offset ?? 0,
|
|
239
|
+
0, // page_limit (0 = default 50)
|
|
240
|
+
options?.timeBudgetMs ?? 0,
|
|
241
|
+
options?.beforeContext ?? 0,
|
|
242
|
+
options?.afterContext ?? 0,
|
|
243
|
+
false,
|
|
244
|
+
);
|
|
253
245
|
}
|
|
254
246
|
|
|
255
247
|
/**
|
|
@@ -285,10 +277,20 @@ export class FileFinder {
|
|
|
285
277
|
return err("patterns array must have at least 1 element");
|
|
286
278
|
}
|
|
287
279
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
280
|
+
return ffiMultiGrep(
|
|
281
|
+
guard.value,
|
|
282
|
+
options.patterns.join("\n"),
|
|
283
|
+
options.constraints ?? "",
|
|
284
|
+
options.maxFileSize ?? 0,
|
|
285
|
+
options.maxMatchesPerFile ?? 0,
|
|
286
|
+
options.smartCase ?? true,
|
|
287
|
+
options.cursor?._offset ?? 0,
|
|
288
|
+
0, // page_limit (0 = default 50)
|
|
289
|
+
options.timeBudgetMs ?? 0,
|
|
290
|
+
options.beforeContext ?? 0,
|
|
291
|
+
options.afterContext ?? 0,
|
|
292
|
+
false,
|
|
293
|
+
);
|
|
292
294
|
}
|
|
293
295
|
|
|
294
296
|
/**
|
|
@@ -412,14 +414,9 @@ export class FileFinder {
|
|
|
412
414
|
return isAvailable();
|
|
413
415
|
}
|
|
414
416
|
|
|
415
|
-
/**
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
* This will download the binary if needed and load it.
|
|
419
|
-
* Useful for preloading before first use.
|
|
420
|
-
*/
|
|
421
|
-
static async ensureLoaded(): Promise<void> {
|
|
422
|
-
return ensureLoaded();
|
|
417
|
+
/** Ensure the native library is loaded. */
|
|
418
|
+
static ensureLoaded(): void {
|
|
419
|
+
ensureLoaded();
|
|
423
420
|
}
|
|
424
421
|
|
|
425
422
|
/**
|
|
@@ -433,3 +430,4 @@ export class FileFinder {
|
|
|
433
430
|
return ffiHealthCheck(null, testPath || "") as Result<HealthCheck>;
|
|
434
431
|
}
|
|
435
432
|
}
|
|
433
|
+
|
|
@@ -51,7 +51,7 @@ function sleep(ms: number) {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
function findFile(finder: FileFinder, name: string): FileItem | undefined {
|
|
54
|
-
const result = finder.
|
|
54
|
+
const result = finder.fileSearch(name, { pageSize: 200 });
|
|
55
55
|
if (!result.ok) throw new Error(`search failed: ${result.error}`);
|
|
56
56
|
return result.value.items.find((item) => item.fileName === name);
|
|
57
57
|
}
|
|
@@ -99,15 +99,15 @@ async function waitForFileGone(finder: FileFinder, name: string): Promise<boolea
|
|
|
99
99
|
async function waitForFileCount(finder: FileFinder, count: number): Promise<number> {
|
|
100
100
|
const start = Date.now();
|
|
101
101
|
while (Date.now() - start < WATCHER_TIMEOUT_MS) {
|
|
102
|
-
const result = finder.
|
|
102
|
+
const result = finder.fileSearch("", { pageSize: 200 });
|
|
103
103
|
if (result.ok && result.value.totalFiles === count) return count;
|
|
104
104
|
await sleep(POLL_INTERVAL_MS);
|
|
105
105
|
}
|
|
106
|
-
const result = finder.
|
|
106
|
+
const result = finder.fileSearch("", { pageSize: 200 });
|
|
107
107
|
return result.ok ? result.value.totalFiles : -1;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
/** Poll
|
|
110
|
+
/** Poll grep until predicate on totalMatched is satisfied, or the timeout is exceeded. */
|
|
111
111
|
async function waitForGrep(
|
|
112
112
|
finder: FileFinder,
|
|
113
113
|
pattern: string,
|
|
@@ -116,11 +116,11 @@ async function waitForGrep(
|
|
|
116
116
|
) {
|
|
117
117
|
const start = Date.now();
|
|
118
118
|
while (Date.now() - start < WATCHER_TIMEOUT_MS) {
|
|
119
|
-
const result = finder.
|
|
119
|
+
const result = finder.grep(pattern, options);
|
|
120
120
|
if (result.ok && predicate(result.value.totalMatched)) return result;
|
|
121
121
|
await sleep(POLL_INTERVAL_MS);
|
|
122
122
|
}
|
|
123
|
-
return finder.
|
|
123
|
+
return finder.grep(pattern, options);
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
describe.skipIf(process.platform === "win32")("Git lifecycle integration", () => {
|
|
@@ -161,7 +161,7 @@ describe.skipIf(process.platform === "win32")("Git lifecycle integration", () =>
|
|
|
161
161
|
});
|
|
162
162
|
|
|
163
163
|
test("initial scan indexes all committed files", () => {
|
|
164
|
-
const result = finder.
|
|
164
|
+
const result = finder.fileSearch("", { pageSize: 200 });
|
|
165
165
|
expect(result.ok).toBe(true);
|
|
166
166
|
if (!result.ok) return;
|
|
167
167
|
|
package/src/index.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
|
2
|
-
import { findBinary
|
|
2
|
+
import { findBinary } from "./download";
|
|
3
3
|
import { FileFinder } from "./index";
|
|
4
4
|
import { getLibExtension, getLibFilename, getTriple } from "./platform";
|
|
5
5
|
|
|
@@ -46,14 +46,6 @@ describe("Platform Detection", () => {
|
|
|
46
46
|
});
|
|
47
47
|
|
|
48
48
|
describe("Binary Detection", () => {
|
|
49
|
-
test("getDevBinaryPath finds local build", () => {
|
|
50
|
-
const devPath = getDevBinaryPath();
|
|
51
|
-
expect(devPath).not.toBeNull();
|
|
52
|
-
// Normalize path for cross-platform comparison (Windows uses backslashes)
|
|
53
|
-
const normalizedPath = normalizePath(devPath);
|
|
54
|
-
expect(normalizedPath).toContain("target/release");
|
|
55
|
-
});
|
|
56
|
-
|
|
57
49
|
test("findBinary returns a path", () => {
|
|
58
50
|
const path = findBinary();
|
|
59
51
|
expect(path).not.toBeNull();
|
|
@@ -120,7 +112,7 @@ describe("FileFinder - Full Lifecycle", () => {
|
|
|
120
112
|
if (progress.ok) {
|
|
121
113
|
}
|
|
122
114
|
|
|
123
|
-
const result = finder.
|
|
115
|
+
const result = finder.fileSearch("");
|
|
124
116
|
expect(result.ok).toBe(true);
|
|
125
117
|
|
|
126
118
|
if (result.ok) {
|
|
@@ -140,7 +132,7 @@ describe("FileFinder - Full Lifecycle", () => {
|
|
|
140
132
|
});
|
|
141
133
|
|
|
142
134
|
test("search returns a valid result structure", () => {
|
|
143
|
-
const result = finder.
|
|
135
|
+
const result = finder.fileSearch("Cargo.toml");
|
|
144
136
|
expect(result.ok).toBe(true);
|
|
145
137
|
|
|
146
138
|
if (result.ok) {
|
|
@@ -152,7 +144,7 @@ describe("FileFinder - Full Lifecycle", () => {
|
|
|
152
144
|
});
|
|
153
145
|
|
|
154
146
|
test("search returns empty for non-matching query", () => {
|
|
155
|
-
const result = finder.
|
|
147
|
+
const result = finder.fileSearch("xyznonexistentfilenamexyz123456");
|
|
156
148
|
expect(result.ok).toBe(true);
|
|
157
149
|
|
|
158
150
|
if (result.ok) {
|
|
@@ -162,7 +154,7 @@ describe("FileFinder - Full Lifecycle", () => {
|
|
|
162
154
|
});
|
|
163
155
|
|
|
164
156
|
test("search respects pageSize option", () => {
|
|
165
|
-
const result = finder.
|
|
157
|
+
const result = finder.fileSearch("ts", { pageSize: 3 });
|
|
166
158
|
expect(result.ok).toBe(true);
|
|
167
159
|
|
|
168
160
|
if (result.ok) {
|
|
@@ -170,8 +162,8 @@ describe("FileFinder - Full Lifecycle", () => {
|
|
|
170
162
|
}
|
|
171
163
|
});
|
|
172
164
|
|
|
173
|
-
test("
|
|
174
|
-
const result = finder.
|
|
165
|
+
test("grep plain text returns matching lines", () => {
|
|
166
|
+
const result = finder.grep("fff-core", {
|
|
175
167
|
mode: "plain",
|
|
176
168
|
});
|
|
177
169
|
expect(result.ok).toBe(true);
|
|
@@ -205,9 +197,9 @@ describe("FileFinder - Full Lifecycle", () => {
|
|
|
205
197
|
}
|
|
206
198
|
});
|
|
207
199
|
|
|
208
|
-
test("
|
|
200
|
+
test("grep fuzzy mode returns results with scores", () => {
|
|
209
201
|
// Intentional typo: "depdnency" instead of "dependency" to exercise fuzzy matching
|
|
210
|
-
const result = finder.
|
|
202
|
+
const result = finder.grep("depdnency", {
|
|
211
203
|
mode: "fuzzy",
|
|
212
204
|
});
|
|
213
205
|
expect(result.ok).toBe(true);
|
|
@@ -273,8 +265,8 @@ describe("FileFinder - Full Lifecycle", () => {
|
|
|
273
265
|
const finder2 = result2.value;
|
|
274
266
|
|
|
275
267
|
// Both should work independently
|
|
276
|
-
const search1 = finder.
|
|
277
|
-
const search2 = finder2.
|
|
268
|
+
const search1 = finder.fileSearch("Cargo");
|
|
269
|
+
const search2 = finder2.fileSearch("Cargo");
|
|
278
270
|
|
|
279
271
|
expect(search1.ok).toBe(true);
|
|
280
272
|
expect(search2.ok).toBe(true);
|
|
@@ -282,7 +274,7 @@ describe("FileFinder - Full Lifecycle", () => {
|
|
|
282
274
|
// Destroying one should not affect the other
|
|
283
275
|
finder2.destroy();
|
|
284
276
|
|
|
285
|
-
const search3 = finder.
|
|
277
|
+
const search3 = finder.fileSearch("Cargo");
|
|
286
278
|
expect(search3.ok).toBe(true);
|
|
287
279
|
}
|
|
288
280
|
});
|
|
@@ -297,7 +289,7 @@ describe("FileFinder - Error Handling", () => {
|
|
|
297
289
|
const f = createResult.value;
|
|
298
290
|
f.destroy();
|
|
299
291
|
|
|
300
|
-
const result = f.
|
|
292
|
+
const result = f.fileSearch("test");
|
|
301
293
|
expect(result.ok).toBe(false);
|
|
302
294
|
if (!result.ok) {
|
|
303
295
|
expect(result.error).toContain("destroyed");
|
package/src/index.ts
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
* finder.waitForScan(5000);
|
|
24
24
|
*
|
|
25
25
|
* // Search for files
|
|
26
|
-
* const search = finder.
|
|
26
|
+
* const search = finder.fileSearch("main.ts");
|
|
27
27
|
* if (search.ok) {
|
|
28
28
|
* for (const item of search.value.items) {
|
|
29
29
|
* console.log(item.relativePath);
|
|
@@ -37,15 +37,11 @@
|
|
|
37
37
|
* @packageDocumentation
|
|
38
38
|
*/
|
|
39
39
|
|
|
40
|
-
export { FileFinder } from "./finder";
|
|
41
|
-
|
|
42
40
|
export {
|
|
43
41
|
binaryExists,
|
|
44
|
-
downloadBinary,
|
|
45
|
-
ensureBinary,
|
|
46
42
|
findBinary,
|
|
47
|
-
getBinaryPath,
|
|
48
43
|
} from "./download";
|
|
44
|
+
export { FileFinder } from "./finder";
|
|
49
45
|
|
|
50
46
|
export {
|
|
51
47
|
getLibExtension,
|
package/src/platform.ts
CHANGED
|
@@ -95,20 +95,20 @@ export function getLibFilename(): string {
|
|
|
95
95
|
* Map from Rust target triple to npm platform package name
|
|
96
96
|
*/
|
|
97
97
|
const TRIPLE_TO_NPM_PACKAGE: Record<string, string> = {
|
|
98
|
-
"aarch64-apple-darwin": "@ff-labs/fff-
|
|
99
|
-
"x86_64-apple-darwin": "@ff-labs/fff-
|
|
100
|
-
"x86_64-unknown-linux-gnu": "@ff-labs/fff-
|
|
101
|
-
"aarch64-unknown-linux-gnu": "@ff-labs/fff-
|
|
102
|
-
"x86_64-unknown-linux-musl": "@ff-labs/fff-
|
|
103
|
-
"aarch64-unknown-linux-musl": "@ff-labs/fff-
|
|
104
|
-
"x86_64-pc-windows-msvc": "@ff-labs/fff-
|
|
105
|
-
"aarch64-pc-windows-msvc": "@ff-labs/fff-
|
|
98
|
+
"aarch64-apple-darwin": "@ff-labs/fff-bin-darwin-arm64",
|
|
99
|
+
"x86_64-apple-darwin": "@ff-labs/fff-bin-darwin-x64",
|
|
100
|
+
"x86_64-unknown-linux-gnu": "@ff-labs/fff-bin-linux-x64-gnu",
|
|
101
|
+
"aarch64-unknown-linux-gnu": "@ff-labs/fff-bin-linux-arm64-gnu",
|
|
102
|
+
"x86_64-unknown-linux-musl": "@ff-labs/fff-bin-linux-x64-musl",
|
|
103
|
+
"aarch64-unknown-linux-musl": "@ff-labs/fff-bin-linux-arm64-musl",
|
|
104
|
+
"x86_64-pc-windows-msvc": "@ff-labs/fff-bin-win32-x64",
|
|
105
|
+
"aarch64-pc-windows-msvc": "@ff-labs/fff-bin-win32-arm64",
|
|
106
106
|
};
|
|
107
107
|
|
|
108
108
|
/**
|
|
109
109
|
* Get the npm package name for the current platform's native binary.
|
|
110
110
|
*
|
|
111
|
-
* @returns Package name like "@ff-labs/fff-
|
|
111
|
+
* @returns Package name like "@ff-labs/fff-bin-darwin-arm64"
|
|
112
112
|
* @throws If the current platform is not supported
|
|
113
113
|
*/
|
|
114
114
|
export function getNpmPackageName(): string {
|
package/src/types.ts
CHANGED
|
@@ -208,62 +208,6 @@ export interface HealthCheck {
|
|
|
208
208
|
};
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
-
/**
|
|
212
|
-
* Internal: Options format sent to Rust FFI
|
|
213
|
-
* @internal
|
|
214
|
-
*/
|
|
215
|
-
export interface InitOptionsInternal {
|
|
216
|
-
base_path: string;
|
|
217
|
-
frecency_db_path?: string;
|
|
218
|
-
history_db_path?: string;
|
|
219
|
-
use_unsafe_no_lock: boolean;
|
|
220
|
-
warmup_mmap_cache: boolean;
|
|
221
|
-
ai_mode: boolean;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
/**
|
|
225
|
-
* Internal: Search options format sent to Rust FFI
|
|
226
|
-
* @internal
|
|
227
|
-
*/
|
|
228
|
-
export interface SearchOptionsInternal {
|
|
229
|
-
max_threads?: number;
|
|
230
|
-
current_file?: string;
|
|
231
|
-
combo_boost_multiplier?: number;
|
|
232
|
-
min_combo_count?: number;
|
|
233
|
-
page_index?: number;
|
|
234
|
-
page_size?: number;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* Convert public InitOptions to internal format
|
|
239
|
-
* @internal
|
|
240
|
-
*/
|
|
241
|
-
export function toInternalInitOptions(opts: InitOptions): InitOptionsInternal {
|
|
242
|
-
return {
|
|
243
|
-
base_path: opts.basePath,
|
|
244
|
-
frecency_db_path: opts.frecencyDbPath,
|
|
245
|
-
history_db_path: opts.historyDbPath,
|
|
246
|
-
use_unsafe_no_lock: opts.useUnsafeNoLock ?? false,
|
|
247
|
-
warmup_mmap_cache: opts.warmupMmapCache ?? false,
|
|
248
|
-
ai_mode: opts.aiMode ?? false,
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* Convert public SearchOptions to internal format
|
|
254
|
-
* @internal
|
|
255
|
-
*/
|
|
256
|
-
export function toInternalSearchOptions(opts?: SearchOptions): SearchOptionsInternal {
|
|
257
|
-
return {
|
|
258
|
-
max_threads: opts?.maxThreads,
|
|
259
|
-
current_file: opts?.currentFile,
|
|
260
|
-
combo_boost_multiplier: opts?.comboBoostMultiplier,
|
|
261
|
-
min_combo_count: opts?.minComboCount,
|
|
262
|
-
page_index: opts?.pageIndex,
|
|
263
|
-
page_size: opts?.pageSize,
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
|
|
267
211
|
/**
|
|
268
212
|
* Grep search mode
|
|
269
213
|
*/
|
|
@@ -417,78 +361,3 @@ export interface MultiGrepOptions {
|
|
|
417
361
|
afterContext?: number;
|
|
418
362
|
}
|
|
419
363
|
|
|
420
|
-
/**
|
|
421
|
-
* Internal: Multi-grep options format sent to Rust FFI
|
|
422
|
-
* @internal
|
|
423
|
-
*/
|
|
424
|
-
export interface MultiGrepOptionsInternal {
|
|
425
|
-
patterns: string[];
|
|
426
|
-
constraints?: string;
|
|
427
|
-
max_file_size?: number;
|
|
428
|
-
max_matches_per_file?: number;
|
|
429
|
-
smart_case?: boolean;
|
|
430
|
-
file_offset?: number;
|
|
431
|
-
page_limit?: number;
|
|
432
|
-
time_budget_ms?: number;
|
|
433
|
-
before_context?: number;
|
|
434
|
-
after_context?: number;
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
/**
|
|
438
|
-
* Convert public MultiGrepOptions to internal format
|
|
439
|
-
* @internal
|
|
440
|
-
*/
|
|
441
|
-
export function toInternalMultiGrepOptions(
|
|
442
|
-
opts: MultiGrepOptions,
|
|
443
|
-
pageLimit?: number,
|
|
444
|
-
): MultiGrepOptionsInternal {
|
|
445
|
-
return {
|
|
446
|
-
patterns: opts.patterns,
|
|
447
|
-
constraints: opts.constraints,
|
|
448
|
-
max_file_size: opts.maxFileSize,
|
|
449
|
-
max_matches_per_file: opts.maxMatchesPerFile,
|
|
450
|
-
smart_case: opts.smartCase,
|
|
451
|
-
file_offset: opts.cursor?._offset ?? 0,
|
|
452
|
-
page_limit: pageLimit,
|
|
453
|
-
time_budget_ms: opts.timeBudgetMs,
|
|
454
|
-
before_context: opts.beforeContext,
|
|
455
|
-
after_context: opts.afterContext,
|
|
456
|
-
};
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
/**
|
|
460
|
-
* Internal: Grep options format sent to Rust FFI
|
|
461
|
-
* @internal
|
|
462
|
-
*/
|
|
463
|
-
export interface GrepOptionsInternal {
|
|
464
|
-
max_file_size?: number;
|
|
465
|
-
max_matches_per_file?: number;
|
|
466
|
-
smart_case?: boolean;
|
|
467
|
-
file_offset?: number;
|
|
468
|
-
page_limit?: number;
|
|
469
|
-
mode?: string;
|
|
470
|
-
time_budget_ms?: number;
|
|
471
|
-
before_context?: number;
|
|
472
|
-
after_context?: number;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
/**
|
|
476
|
-
* Convert public GrepOptions to internal format
|
|
477
|
-
* @internal
|
|
478
|
-
*/
|
|
479
|
-
export function toInternalGrepOptions(
|
|
480
|
-
opts?: GrepOptions,
|
|
481
|
-
pageLimit?: number,
|
|
482
|
-
): GrepOptionsInternal {
|
|
483
|
-
return {
|
|
484
|
-
max_file_size: opts?.maxFileSize,
|
|
485
|
-
max_matches_per_file: opts?.maxMatchesPerFile,
|
|
486
|
-
smart_case: opts?.smartCase,
|
|
487
|
-
file_offset: opts?.cursor?._offset ?? 0,
|
|
488
|
-
page_limit: pageLimit,
|
|
489
|
-
mode: opts?.mode,
|
|
490
|
-
time_budget_ms: opts?.timeBudgetMs,
|
|
491
|
-
before_context: opts?.beforeContext,
|
|
492
|
-
after_context: opts?.afterContext,
|
|
493
|
-
};
|
|
494
|
-
}
|
package/bin/libfff_c.dylib
DELETED
|
Binary file
|
package/scripts/cli.ts
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
/**
|
|
3
|
-
* CLI tool for fff package management
|
|
4
|
-
*
|
|
5
|
-
* Usage:
|
|
6
|
-
* bunx fff download [tag] - Download native binary from GitHub
|
|
7
|
-
* bunx fff info - Show platform and binary info
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { downloadBinary, getBinaryPath, findBinary } from "../src/download";
|
|
11
|
-
import {
|
|
12
|
-
getTriple,
|
|
13
|
-
getLibExtension,
|
|
14
|
-
getLibFilename,
|
|
15
|
-
getNpmPackageName,
|
|
16
|
-
} from "../src/platform";
|
|
17
|
-
import { dirname, join } from "node:path";
|
|
18
|
-
import { fileURLToPath } from "node:url";
|
|
19
|
-
|
|
20
|
-
const args = process.argv.slice(2);
|
|
21
|
-
const command = args[0];
|
|
22
|
-
|
|
23
|
-
interface PackageJson {
|
|
24
|
-
version: string;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async function getPackageInfo(): Promise<PackageJson> {
|
|
28
|
-
const currentDir = dirname(fileURLToPath(import.meta.url));
|
|
29
|
-
const packageJsonPath = join(currentDir, "..", "package.json");
|
|
30
|
-
|
|
31
|
-
try {
|
|
32
|
-
return await Bun.file(packageJsonPath).json();
|
|
33
|
-
} catch {
|
|
34
|
-
return { version: "unknown" };
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async function main() {
|
|
39
|
-
switch (command) {
|
|
40
|
-
case "download": {
|
|
41
|
-
const tag = args[1];
|
|
42
|
-
console.log("fff: Downloading native library from GitHub...");
|
|
43
|
-
try {
|
|
44
|
-
const resolvedTag = await downloadBinary(tag);
|
|
45
|
-
console.log(`fff: Download complete! (${resolvedTag})`);
|
|
46
|
-
} catch (error) {
|
|
47
|
-
console.error("fff: Download failed:", error);
|
|
48
|
-
process.exit(1);
|
|
49
|
-
}
|
|
50
|
-
break;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
case "info": {
|
|
54
|
-
const pkg = await getPackageInfo();
|
|
55
|
-
let npmPackage: string;
|
|
56
|
-
try {
|
|
57
|
-
npmPackage = getNpmPackageName();
|
|
58
|
-
} catch {
|
|
59
|
-
npmPackage = "unsupported";
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
console.log("fff - Fast File Finder");
|
|
63
|
-
console.log(`Package version: ${pkg.version}`);
|
|
64
|
-
console.log("");
|
|
65
|
-
console.log("Platform Information:");
|
|
66
|
-
console.log(` Triple: ${getTriple()}`);
|
|
67
|
-
console.log(` Extension: ${getLibExtension()}`);
|
|
68
|
-
console.log(` Library name: ${getLibFilename()}`);
|
|
69
|
-
console.log(` npm package: ${npmPackage}`);
|
|
70
|
-
console.log("");
|
|
71
|
-
console.log("Binary Status:");
|
|
72
|
-
const existing = findBinary();
|
|
73
|
-
if (existing) {
|
|
74
|
-
console.log(` Found: ${existing}`);
|
|
75
|
-
} else {
|
|
76
|
-
console.log(` Not found`);
|
|
77
|
-
console.log(` Expected path: ${getBinaryPath()}`);
|
|
78
|
-
console.log(` Try: bun add ${npmPackage}`);
|
|
79
|
-
}
|
|
80
|
-
break;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
case "version":
|
|
84
|
-
case "--version":
|
|
85
|
-
case "-v": {
|
|
86
|
-
const pkg = await getPackageInfo();
|
|
87
|
-
console.log(pkg.version);
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
default: {
|
|
92
|
-
const pkg = await getPackageInfo();
|
|
93
|
-
console.log(`fff - Fast File Finder CLI v${pkg.version}`);
|
|
94
|
-
console.log("");
|
|
95
|
-
console.log("Usage:");
|
|
96
|
-
console.log(
|
|
97
|
-
" bunx fff download [tag] Download native binary from GitHub (fallback)",
|
|
98
|
-
);
|
|
99
|
-
console.log(" bunx fff info Show platform and binary info");
|
|
100
|
-
console.log(" bunx fff version Show version");
|
|
101
|
-
console.log(" bunx fff help Show this help message");
|
|
102
|
-
console.log("");
|
|
103
|
-
console.log("Examples:");
|
|
104
|
-
console.log(" bunx fff download Download latest binary from GitHub");
|
|
105
|
-
console.log(" bunx fff download abc1234 Download specific release tag");
|
|
106
|
-
console.log("");
|
|
107
|
-
console.log(
|
|
108
|
-
"Note: Binaries are normally provided via platform-specific npm packages.",
|
|
109
|
-
);
|
|
110
|
-
console.log("The download command is a fallback for when those aren't available.");
|
|
111
|
-
break;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
main();
|