@ff-labs/fff-bun 0.10.4-nightly.e2cad2f → 0.10.5-dev.2a477d2
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 +2 -2
- package/dist/download.d.ts +22 -0
- package/dist/download.d.ts.map +1 -0
- package/dist/embedded.d.ts +15 -0
- package/dist/embedded.d.ts.map +1 -0
- package/dist/fff-api.d.ts +607 -0
- package/dist/fff-api.d.ts.map +1 -0
- package/dist/ffi.d.ts +138 -0
- package/dist/ffi.d.ts.map +1 -0
- package/dist/finder.d.ts +378 -0
- package/dist/finder.d.ts.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1440 -0
- package/dist/index.js.map +15 -0
- package/dist/platform.d.ts +27 -0
- package/dist/platform.d.ts.map +1 -0
- package/package.json +22 -17
package/dist/index.js
ADDED
|
@@ -0,0 +1,1440 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/download.ts
|
|
3
|
+
import { existsSync } from "fs";
|
|
4
|
+
import { createRequire } from "module";
|
|
5
|
+
import { dirname, join } from "path";
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
7
|
+
|
|
8
|
+
// src/platform.ts
|
|
9
|
+
import { execSync } from "child_process";
|
|
10
|
+
function getTriple() {
|
|
11
|
+
const platform = process.platform;
|
|
12
|
+
const arch = process.arch;
|
|
13
|
+
let osName;
|
|
14
|
+
if (platform === "darwin") {
|
|
15
|
+
osName = "apple-darwin";
|
|
16
|
+
} else if (platform === "android") {
|
|
17
|
+
osName = "linux-android";
|
|
18
|
+
} else if (platform === "linux") {
|
|
19
|
+
osName = detectLinuxLibc();
|
|
20
|
+
} else if (platform === "win32") {
|
|
21
|
+
osName = "pc-windows-msvc";
|
|
22
|
+
} else {
|
|
23
|
+
throw new Error(`Unsupported platform: ${platform}`);
|
|
24
|
+
}
|
|
25
|
+
const archName = normalizeArch(arch);
|
|
26
|
+
return `${archName}-${osName}`;
|
|
27
|
+
}
|
|
28
|
+
function detectLinuxLibc() {
|
|
29
|
+
let output = "";
|
|
30
|
+
try {
|
|
31
|
+
output = execSync("ldd --version 2>&1", {
|
|
32
|
+
encoding: "utf-8",
|
|
33
|
+
timeout: 5000
|
|
34
|
+
});
|
|
35
|
+
} catch (e) {
|
|
36
|
+
const err = e;
|
|
37
|
+
output = String(err?.stdout ?? "") + String(err?.stderr ?? "");
|
|
38
|
+
}
|
|
39
|
+
if (output.toLowerCase().includes("musl")) {
|
|
40
|
+
return "unknown-linux-musl";
|
|
41
|
+
}
|
|
42
|
+
return "unknown-linux-gnu";
|
|
43
|
+
}
|
|
44
|
+
function normalizeArch(arch) {
|
|
45
|
+
switch (arch) {
|
|
46
|
+
case "x64":
|
|
47
|
+
case "amd64":
|
|
48
|
+
return "x86_64";
|
|
49
|
+
case "arm64":
|
|
50
|
+
return "aarch64";
|
|
51
|
+
case "arm":
|
|
52
|
+
return "arm";
|
|
53
|
+
default:
|
|
54
|
+
throw new Error(`Unsupported architecture: ${arch}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function getLibExtension() {
|
|
58
|
+
switch (process.platform) {
|
|
59
|
+
case "darwin":
|
|
60
|
+
return "dylib";
|
|
61
|
+
case "win32":
|
|
62
|
+
return "dll";
|
|
63
|
+
default:
|
|
64
|
+
return "so";
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function getLibPrefix() {
|
|
68
|
+
return process.platform === "win32" ? "" : "lib";
|
|
69
|
+
}
|
|
70
|
+
function getLibFilename() {
|
|
71
|
+
const prefix = getLibPrefix();
|
|
72
|
+
const ext = getLibExtension();
|
|
73
|
+
return `${prefix}fff_c.${ext}`;
|
|
74
|
+
}
|
|
75
|
+
var TRIPLE_TO_NPM_PACKAGE = {
|
|
76
|
+
"aarch64-apple-darwin": "@ff-labs/fff-bin-darwin-arm64",
|
|
77
|
+
"x86_64-apple-darwin": "@ff-labs/fff-bin-darwin-x64",
|
|
78
|
+
"x86_64-unknown-linux-gnu": "@ff-labs/fff-bin-linux-x64-gnu",
|
|
79
|
+
"aarch64-unknown-linux-gnu": "@ff-labs/fff-bin-linux-arm64-gnu",
|
|
80
|
+
"x86_64-unknown-linux-musl": "@ff-labs/fff-bin-linux-x64-musl",
|
|
81
|
+
"aarch64-unknown-linux-musl": "@ff-labs/fff-bin-linux-arm64-musl",
|
|
82
|
+
"x86_64-pc-windows-msvc": "@ff-labs/fff-bin-win32-x64",
|
|
83
|
+
"aarch64-pc-windows-msvc": "@ff-labs/fff-bin-win32-arm64",
|
|
84
|
+
"aarch64-linux-android": "@ff-labs/fff-bin-android-arm64"
|
|
85
|
+
};
|
|
86
|
+
function getNpmPackageName() {
|
|
87
|
+
const triple = getTriple();
|
|
88
|
+
const packageName = TRIPLE_TO_NPM_PACKAGE[triple];
|
|
89
|
+
if (!packageName) {
|
|
90
|
+
throw new Error(`No npm package available for platform: ${triple}`);
|
|
91
|
+
}
|
|
92
|
+
return packageName;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// src/download.ts
|
|
96
|
+
function getCurrentDir() {
|
|
97
|
+
const url = import.meta.url;
|
|
98
|
+
if (url.includes("$bunfs")) {
|
|
99
|
+
return dirname(process.execPath);
|
|
100
|
+
}
|
|
101
|
+
if (url.startsWith("file://")) {
|
|
102
|
+
return dirname(fileURLToPath(url));
|
|
103
|
+
}
|
|
104
|
+
return dirname(url);
|
|
105
|
+
}
|
|
106
|
+
function getPackageDir() {
|
|
107
|
+
const currentDir = getCurrentDir();
|
|
108
|
+
return dirname(currentDir);
|
|
109
|
+
}
|
|
110
|
+
function binaryExists() {
|
|
111
|
+
return findBinary() !== null;
|
|
112
|
+
}
|
|
113
|
+
function resolveFromNpmPackage() {
|
|
114
|
+
const packageName = getNpmPackageName();
|
|
115
|
+
try {
|
|
116
|
+
const require2 = createRequire(join(getPackageDir(), "package.json"));
|
|
117
|
+
const packageJsonPath = require2.resolve(`${packageName}/package.json`);
|
|
118
|
+
const packageDir = dirname(packageJsonPath);
|
|
119
|
+
const binaryPath = join(packageDir, getLibFilename());
|
|
120
|
+
if (existsSync(binaryPath)) {
|
|
121
|
+
return binaryPath;
|
|
122
|
+
}
|
|
123
|
+
} catch {}
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
function getDevBinaryPath() {
|
|
127
|
+
const packageDir = getPackageDir();
|
|
128
|
+
const workspaceRoot = join(packageDir, "..", "..");
|
|
129
|
+
const possiblePaths = [
|
|
130
|
+
join(workspaceRoot, "target", "release", getLibFilename()),
|
|
131
|
+
join(workspaceRoot, "target", "debug", getLibFilename())
|
|
132
|
+
];
|
|
133
|
+
for (const path of possiblePaths) {
|
|
134
|
+
if (existsSync(path)) {
|
|
135
|
+
return path;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
function isDevWorkspace() {
|
|
141
|
+
const packageDir = getPackageDir();
|
|
142
|
+
const workspaceRoot = join(packageDir, "..", "..");
|
|
143
|
+
return existsSync(join(workspaceRoot, "Cargo.toml"));
|
|
144
|
+
}
|
|
145
|
+
function findBinary() {
|
|
146
|
+
if (isDevWorkspace()) {
|
|
147
|
+
const binPath = join(getPackageDir(), "bin", getLibFilename());
|
|
148
|
+
if (existsSync(binPath))
|
|
149
|
+
return binPath;
|
|
150
|
+
const devPath = getDevBinaryPath();
|
|
151
|
+
if (devPath)
|
|
152
|
+
return devPath;
|
|
153
|
+
const npmPath2 = resolveFromNpmPackage();
|
|
154
|
+
if (npmPath2)
|
|
155
|
+
return npmPath2;
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
const npmPath = resolveFromNpmPackage();
|
|
159
|
+
if (npmPath)
|
|
160
|
+
return npmPath;
|
|
161
|
+
return getDevBinaryPath();
|
|
162
|
+
}
|
|
163
|
+
// src/finder.ts
|
|
164
|
+
import { FFIType as FFIType2, JSCallback } from "bun:ffi";
|
|
165
|
+
|
|
166
|
+
// src/ffi.ts
|
|
167
|
+
import {
|
|
168
|
+
CString,
|
|
169
|
+
dlopen,
|
|
170
|
+
FFIType,
|
|
171
|
+
ptr,
|
|
172
|
+
read
|
|
173
|
+
} from "bun:ffi";
|
|
174
|
+
|
|
175
|
+
// src/embedded.ts
|
|
176
|
+
async function importFile(promise) {
|
|
177
|
+
try {
|
|
178
|
+
return (await promise).default;
|
|
179
|
+
} catch {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
async function resolveEmbeddedLibPath() {
|
|
184
|
+
if (process.platform === "darwin") {
|
|
185
|
+
return importFile(import(`@ff-labs/fff-bin-darwin-${process.arch}/libfff_c.dylib`, {
|
|
186
|
+
with: { type: "file" }
|
|
187
|
+
}));
|
|
188
|
+
}
|
|
189
|
+
if (process.platform === "win32") {
|
|
190
|
+
return importFile(import(`@ff-labs/fff-bin-win32-${process.arch}/fff_c.dll`, {
|
|
191
|
+
with: { type: "file" }
|
|
192
|
+
}));
|
|
193
|
+
}
|
|
194
|
+
if (process.platform === "linux") {
|
|
195
|
+
return importFile(import(`@ff-labs/fff-bin-linux-${process.arch}-${typeof FFF_LIBC === "string" ? FFF_LIBC : "gnu"}/libfff_c.so`, { with: { type: "file" } }));
|
|
196
|
+
}
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
var embeddedLibPath = await resolveEmbeddedLibPath();
|
|
200
|
+
|
|
201
|
+
// src/fff-api.ts
|
|
202
|
+
function err(error) {
|
|
203
|
+
return { ok: false, error };
|
|
204
|
+
}
|
|
205
|
+
function createGrepCursor(offset) {
|
|
206
|
+
return { __brand: "GrepCursor", _offset: offset };
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// src/ffi.ts
|
|
210
|
+
var GREP_MODE_PLAIN = 0;
|
|
211
|
+
var GREP_MODE_REGEX = 1;
|
|
212
|
+
var GREP_MODE_FUZZY = 2;
|
|
213
|
+
function grepModeToU8(mode) {
|
|
214
|
+
switch (mode) {
|
|
215
|
+
case "regex":
|
|
216
|
+
return GREP_MODE_REGEX;
|
|
217
|
+
case "fuzzy":
|
|
218
|
+
return GREP_MODE_FUZZY;
|
|
219
|
+
default:
|
|
220
|
+
return GREP_MODE_PLAIN;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
var ffiDefinition = {
|
|
224
|
+
fff_create_instance2: {
|
|
225
|
+
args: [
|
|
226
|
+
FFIType.cstring,
|
|
227
|
+
FFIType.cstring,
|
|
228
|
+
FFIType.cstring,
|
|
229
|
+
FFIType.bool,
|
|
230
|
+
FFIType.bool,
|
|
231
|
+
FFIType.bool,
|
|
232
|
+
FFIType.bool,
|
|
233
|
+
FFIType.bool,
|
|
234
|
+
FFIType.cstring,
|
|
235
|
+
FFIType.cstring,
|
|
236
|
+
FFIType.u64,
|
|
237
|
+
FFIType.u64,
|
|
238
|
+
FFIType.u64
|
|
239
|
+
],
|
|
240
|
+
returns: FFIType.ptr
|
|
241
|
+
},
|
|
242
|
+
fff_create_instance_with: {
|
|
243
|
+
args: [FFIType.ptr],
|
|
244
|
+
returns: FFIType.ptr
|
|
245
|
+
},
|
|
246
|
+
fff_destroy: {
|
|
247
|
+
args: [FFIType.ptr],
|
|
248
|
+
returns: FFIType.void
|
|
249
|
+
},
|
|
250
|
+
fff_search: {
|
|
251
|
+
args: [
|
|
252
|
+
FFIType.ptr,
|
|
253
|
+
FFIType.cstring,
|
|
254
|
+
FFIType.cstring,
|
|
255
|
+
FFIType.u32,
|
|
256
|
+
FFIType.u32,
|
|
257
|
+
FFIType.u32,
|
|
258
|
+
FFIType.i32,
|
|
259
|
+
FFIType.u32
|
|
260
|
+
],
|
|
261
|
+
returns: FFIType.ptr
|
|
262
|
+
},
|
|
263
|
+
fff_glob: {
|
|
264
|
+
args: [
|
|
265
|
+
FFIType.ptr,
|
|
266
|
+
FFIType.cstring,
|
|
267
|
+
FFIType.cstring,
|
|
268
|
+
FFIType.u32,
|
|
269
|
+
FFIType.u32,
|
|
270
|
+
FFIType.u32
|
|
271
|
+
],
|
|
272
|
+
returns: FFIType.ptr
|
|
273
|
+
},
|
|
274
|
+
fff_search_directories: {
|
|
275
|
+
args: [
|
|
276
|
+
FFIType.ptr,
|
|
277
|
+
FFIType.cstring,
|
|
278
|
+
FFIType.cstring,
|
|
279
|
+
FFIType.u32,
|
|
280
|
+
FFIType.u32,
|
|
281
|
+
FFIType.u32
|
|
282
|
+
],
|
|
283
|
+
returns: FFIType.ptr
|
|
284
|
+
},
|
|
285
|
+
fff_search_mixed: {
|
|
286
|
+
args: [
|
|
287
|
+
FFIType.ptr,
|
|
288
|
+
FFIType.cstring,
|
|
289
|
+
FFIType.cstring,
|
|
290
|
+
FFIType.u32,
|
|
291
|
+
FFIType.u32,
|
|
292
|
+
FFIType.u32,
|
|
293
|
+
FFIType.i32,
|
|
294
|
+
FFIType.u32
|
|
295
|
+
],
|
|
296
|
+
returns: FFIType.ptr
|
|
297
|
+
},
|
|
298
|
+
fff_live_grep: {
|
|
299
|
+
args: [
|
|
300
|
+
FFIType.ptr,
|
|
301
|
+
FFIType.cstring,
|
|
302
|
+
FFIType.u8,
|
|
303
|
+
FFIType.u64,
|
|
304
|
+
FFIType.u32,
|
|
305
|
+
FFIType.bool,
|
|
306
|
+
FFIType.u32,
|
|
307
|
+
FFIType.u32,
|
|
308
|
+
FFIType.u64,
|
|
309
|
+
FFIType.u32,
|
|
310
|
+
FFIType.u32,
|
|
311
|
+
FFIType.bool
|
|
312
|
+
],
|
|
313
|
+
returns: FFIType.ptr
|
|
314
|
+
},
|
|
315
|
+
fff_multi_grep: {
|
|
316
|
+
args: [
|
|
317
|
+
FFIType.ptr,
|
|
318
|
+
FFIType.cstring,
|
|
319
|
+
FFIType.cstring,
|
|
320
|
+
FFIType.u64,
|
|
321
|
+
FFIType.u32,
|
|
322
|
+
FFIType.bool,
|
|
323
|
+
FFIType.u32,
|
|
324
|
+
FFIType.u32,
|
|
325
|
+
FFIType.u64,
|
|
326
|
+
FFIType.u32,
|
|
327
|
+
FFIType.u32,
|
|
328
|
+
FFIType.bool
|
|
329
|
+
],
|
|
330
|
+
returns: FFIType.ptr
|
|
331
|
+
},
|
|
332
|
+
fff_scan_files: {
|
|
333
|
+
args: [FFIType.ptr],
|
|
334
|
+
returns: FFIType.ptr
|
|
335
|
+
},
|
|
336
|
+
fff_is_scanning: {
|
|
337
|
+
args: [FFIType.ptr],
|
|
338
|
+
returns: FFIType.bool
|
|
339
|
+
},
|
|
340
|
+
fff_get_base_path: {
|
|
341
|
+
args: [FFIType.ptr],
|
|
342
|
+
returns: FFIType.ptr
|
|
343
|
+
},
|
|
344
|
+
fff_get_scan_progress: {
|
|
345
|
+
args: [FFIType.ptr],
|
|
346
|
+
returns: FFIType.ptr
|
|
347
|
+
},
|
|
348
|
+
fff_wait_for_scan: {
|
|
349
|
+
args: [FFIType.ptr, FFIType.u64],
|
|
350
|
+
returns: FFIType.ptr
|
|
351
|
+
},
|
|
352
|
+
fff_restart_index: {
|
|
353
|
+
args: [FFIType.ptr, FFIType.cstring],
|
|
354
|
+
returns: FFIType.ptr
|
|
355
|
+
},
|
|
356
|
+
fff_set_watch_callback: {
|
|
357
|
+
args: [
|
|
358
|
+
FFIType.ptr,
|
|
359
|
+
FFIType.function,
|
|
360
|
+
FFIType.ptr
|
|
361
|
+
],
|
|
362
|
+
returns: FFIType.ptr
|
|
363
|
+
},
|
|
364
|
+
fff_watch: {
|
|
365
|
+
args: [
|
|
366
|
+
FFIType.ptr,
|
|
367
|
+
FFIType.cstring,
|
|
368
|
+
FFIType.ptr
|
|
369
|
+
],
|
|
370
|
+
returns: FFIType.ptr
|
|
371
|
+
},
|
|
372
|
+
fff_unwatch: {
|
|
373
|
+
args: [FFIType.ptr, FFIType.u64],
|
|
374
|
+
returns: FFIType.ptr
|
|
375
|
+
},
|
|
376
|
+
fff_free_watch_events: {
|
|
377
|
+
args: [FFIType.ptr],
|
|
378
|
+
returns: FFIType.void
|
|
379
|
+
},
|
|
380
|
+
fff_watch_events_count: {
|
|
381
|
+
args: [FFIType.ptr],
|
|
382
|
+
returns: FFIType.u32
|
|
383
|
+
},
|
|
384
|
+
fff_watch_events_get_path: {
|
|
385
|
+
args: [FFIType.ptr, FFIType.u32],
|
|
386
|
+
returns: FFIType.ptr
|
|
387
|
+
},
|
|
388
|
+
fff_watch_events_get_kind: {
|
|
389
|
+
args: [FFIType.ptr, FFIType.u32],
|
|
390
|
+
returns: FFIType.u8
|
|
391
|
+
},
|
|
392
|
+
fff_refresh_git_status: {
|
|
393
|
+
args: [FFIType.ptr],
|
|
394
|
+
returns: FFIType.ptr
|
|
395
|
+
},
|
|
396
|
+
fff_track_query: {
|
|
397
|
+
args: [FFIType.ptr, FFIType.cstring, FFIType.cstring],
|
|
398
|
+
returns: FFIType.ptr
|
|
399
|
+
},
|
|
400
|
+
fff_get_historical_query: {
|
|
401
|
+
args: [FFIType.ptr, FFIType.u64],
|
|
402
|
+
returns: FFIType.ptr
|
|
403
|
+
},
|
|
404
|
+
fff_health_check: {
|
|
405
|
+
args: [FFIType.ptr, FFIType.cstring],
|
|
406
|
+
returns: FFIType.ptr
|
|
407
|
+
},
|
|
408
|
+
fff_free_search_result: {
|
|
409
|
+
args: [FFIType.ptr],
|
|
410
|
+
returns: FFIType.void
|
|
411
|
+
},
|
|
412
|
+
fff_search_result_get_item: {
|
|
413
|
+
args: [FFIType.ptr, FFIType.u32],
|
|
414
|
+
returns: FFIType.ptr
|
|
415
|
+
},
|
|
416
|
+
fff_search_result_get_score: {
|
|
417
|
+
args: [FFIType.ptr, FFIType.u32],
|
|
418
|
+
returns: FFIType.ptr
|
|
419
|
+
},
|
|
420
|
+
fff_free_dir_search_result: {
|
|
421
|
+
args: [FFIType.ptr],
|
|
422
|
+
returns: FFIType.void
|
|
423
|
+
},
|
|
424
|
+
fff_dir_search_result_get_item: {
|
|
425
|
+
args: [FFIType.ptr, FFIType.u32],
|
|
426
|
+
returns: FFIType.ptr
|
|
427
|
+
},
|
|
428
|
+
fff_dir_search_result_get_score: {
|
|
429
|
+
args: [FFIType.ptr, FFIType.u32],
|
|
430
|
+
returns: FFIType.ptr
|
|
431
|
+
},
|
|
432
|
+
fff_free_mixed_search_result: {
|
|
433
|
+
args: [FFIType.ptr],
|
|
434
|
+
returns: FFIType.void
|
|
435
|
+
},
|
|
436
|
+
fff_mixed_search_result_get_item: {
|
|
437
|
+
args: [FFIType.ptr, FFIType.u32],
|
|
438
|
+
returns: FFIType.ptr
|
|
439
|
+
},
|
|
440
|
+
fff_mixed_search_result_get_score: {
|
|
441
|
+
args: [FFIType.ptr, FFIType.u32],
|
|
442
|
+
returns: FFIType.ptr
|
|
443
|
+
},
|
|
444
|
+
fff_free_grep_result: {
|
|
445
|
+
args: [FFIType.ptr],
|
|
446
|
+
returns: FFIType.void
|
|
447
|
+
},
|
|
448
|
+
fff_grep_result_get_match: {
|
|
449
|
+
args: [FFIType.ptr, FFIType.u32],
|
|
450
|
+
returns: FFIType.ptr
|
|
451
|
+
},
|
|
452
|
+
fff_free_result: {
|
|
453
|
+
args: [FFIType.ptr],
|
|
454
|
+
returns: FFIType.void
|
|
455
|
+
},
|
|
456
|
+
fff_free_string: {
|
|
457
|
+
args: [FFIType.ptr],
|
|
458
|
+
returns: FFIType.void
|
|
459
|
+
},
|
|
460
|
+
fff_free_scan_progress: {
|
|
461
|
+
args: [FFIType.ptr],
|
|
462
|
+
returns: FFIType.void
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
var lib = null;
|
|
466
|
+
function loadLibrary() {
|
|
467
|
+
if (lib)
|
|
468
|
+
return lib;
|
|
469
|
+
const isEmbedded = embeddedLibPath?.includes("$bunfs") ?? false;
|
|
470
|
+
const binaryPath = isEmbedded ? embeddedLibPath : findBinary() ?? embeddedLibPath;
|
|
471
|
+
if (!binaryPath) {
|
|
472
|
+
throw new Error(libNotFoundMessage());
|
|
473
|
+
}
|
|
474
|
+
lib = dlopen(binaryPath, ffiDefinition);
|
|
475
|
+
return lib;
|
|
476
|
+
}
|
|
477
|
+
function libNotFoundMessage() {
|
|
478
|
+
if (import.meta.url.includes("$bunfs")) {
|
|
479
|
+
if (process.platform === "linux") {
|
|
480
|
+
return [
|
|
481
|
+
"You are running bun --compile with fff native library which CAN NOT resolve a binary",
|
|
482
|
+
"On Linux the libc must be supplied at compile time so the native lib is bundled.",
|
|
483
|
+
"Rebuild with:",
|
|
484
|
+
` bun build --compile --define FFF_LIBC='"gnu"' ... # glibc`,
|
|
485
|
+
` bun build --compile --define FFF_LIBC='"musl"' ... # musl / Alpine`
|
|
486
|
+
].join(`
|
|
487
|
+
`);
|
|
488
|
+
}
|
|
489
|
+
return "fff native library was not embedded into this executable. Rebuild with `bun build --compile` and ensure the @ff-labs/fff-bin-* package for this platform is installed.";
|
|
490
|
+
}
|
|
491
|
+
return "fff native library not found. Build from source with `cargo build --release -p fff-c` or install the platform package.";
|
|
492
|
+
}
|
|
493
|
+
function encodeString(s) {
|
|
494
|
+
return new TextEncoder().encode(`${s}\x00`);
|
|
495
|
+
}
|
|
496
|
+
function readCString(pointer) {
|
|
497
|
+
if (pointer === null || pointer === 0)
|
|
498
|
+
return null;
|
|
499
|
+
return new CString(pointer).toString();
|
|
500
|
+
}
|
|
501
|
+
function snakeToCamel(obj) {
|
|
502
|
+
if (obj === null || obj === undefined)
|
|
503
|
+
return obj;
|
|
504
|
+
if (typeof obj !== "object")
|
|
505
|
+
return obj;
|
|
506
|
+
if (Array.isArray(obj))
|
|
507
|
+
return obj.map(snakeToCamel);
|
|
508
|
+
const result = {};
|
|
509
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
510
|
+
const camelKey = key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
511
|
+
result[camelKey] = snakeToCamel(value);
|
|
512
|
+
}
|
|
513
|
+
return result;
|
|
514
|
+
}
|
|
515
|
+
var RES_SUCCESS = 0;
|
|
516
|
+
var RES_ERROR = 8;
|
|
517
|
+
var RES_HANDLE = 16;
|
|
518
|
+
var RES_INT_VALUE = 24;
|
|
519
|
+
var FFF_CREATE_OPTIONS_VERSION = 1;
|
|
520
|
+
var FFF_CREATE_OPTIONS_SIZE = 88;
|
|
521
|
+
var FCO_VERSION = 0;
|
|
522
|
+
var FCO_BASE_PATH = 8;
|
|
523
|
+
var FCO_FRECENCY_DB_PATH = 16;
|
|
524
|
+
var FCO_HISTORY_DB_PATH = 24;
|
|
525
|
+
var FCO_ENABLE_MMAP_CACHE = 32;
|
|
526
|
+
var FCO_ENABLE_CONTENT_INDEXING = 33;
|
|
527
|
+
var FCO_WATCH = 34;
|
|
528
|
+
var FCO_AI_MODE = 35;
|
|
529
|
+
var FCO_LOG_FILE_PATH = 40;
|
|
530
|
+
var FCO_LOG_LEVEL = 48;
|
|
531
|
+
var FCO_CACHE_BUDGET_MAX_FILES = 56;
|
|
532
|
+
var FCO_CACHE_BUDGET_MAX_BYTES = 64;
|
|
533
|
+
var FCO_CACHE_BUDGET_MAX_FILE_SIZE = 72;
|
|
534
|
+
var FCO_ENABLE_FS_ROOT_SCANNING = 80;
|
|
535
|
+
var FCO_ENABLE_HOME_DIR_SCANNING = 81;
|
|
536
|
+
function readResultEnvelope(resultPtr) {
|
|
537
|
+
if (resultPtr === null) {
|
|
538
|
+
return err("FFI returned null pointer");
|
|
539
|
+
}
|
|
540
|
+
const success = read.u8(resultPtr, RES_SUCCESS) !== 0;
|
|
541
|
+
const library = loadLibrary();
|
|
542
|
+
if (!success) {
|
|
543
|
+
const errorPtr = read.ptr(resultPtr, RES_ERROR);
|
|
544
|
+
const errorMsg = readCString(errorPtr) || "Unknown error";
|
|
545
|
+
library.symbols.fff_free_result(resultPtr);
|
|
546
|
+
return err(errorMsg);
|
|
547
|
+
}
|
|
548
|
+
const handlePtr = read.ptr(resultPtr, RES_HANDLE);
|
|
549
|
+
const intValue = Number(read.i64(resultPtr, RES_INT_VALUE));
|
|
550
|
+
library.symbols.fff_free_result(resultPtr);
|
|
551
|
+
return { success: true, handlePtr, intValue };
|
|
552
|
+
}
|
|
553
|
+
function parseBoolResult(resultPtr) {
|
|
554
|
+
const envelope = readResultEnvelope(resultPtr);
|
|
555
|
+
if (!("success" in envelope))
|
|
556
|
+
return envelope;
|
|
557
|
+
return { ok: true, value: envelope.intValue !== 0 };
|
|
558
|
+
}
|
|
559
|
+
function parseIntResult(resultPtr) {
|
|
560
|
+
const envelope = readResultEnvelope(resultPtr);
|
|
561
|
+
if (!("success" in envelope))
|
|
562
|
+
return envelope;
|
|
563
|
+
return { ok: true, value: envelope.intValue };
|
|
564
|
+
}
|
|
565
|
+
function parseStringResult(resultPtr) {
|
|
566
|
+
const envelope = readResultEnvelope(resultPtr);
|
|
567
|
+
if (!("success" in envelope))
|
|
568
|
+
return envelope;
|
|
569
|
+
if (envelope.handlePtr === 0)
|
|
570
|
+
return { ok: true, value: null };
|
|
571
|
+
const library = loadLibrary();
|
|
572
|
+
const str = readCString(envelope.handlePtr);
|
|
573
|
+
library.symbols.fff_free_string(asPtr(envelope.handlePtr));
|
|
574
|
+
return { ok: true, value: str };
|
|
575
|
+
}
|
|
576
|
+
function parseJsonResult(resultPtr) {
|
|
577
|
+
const envelope = readResultEnvelope(resultPtr);
|
|
578
|
+
if (!("success" in envelope))
|
|
579
|
+
return envelope;
|
|
580
|
+
if (envelope.handlePtr === 0)
|
|
581
|
+
return { ok: true, value: undefined };
|
|
582
|
+
const library = loadLibrary();
|
|
583
|
+
const jsonStr = readCString(envelope.handlePtr);
|
|
584
|
+
library.symbols.fff_free_string(asPtr(envelope.handlePtr));
|
|
585
|
+
if (jsonStr === null || jsonStr === "")
|
|
586
|
+
return { ok: true, value: undefined };
|
|
587
|
+
try {
|
|
588
|
+
return { ok: true, value: snakeToCamel(JSON.parse(jsonStr)) };
|
|
589
|
+
} catch {
|
|
590
|
+
return { ok: true, value: jsonStr };
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
function parseVoidResult(resultPtr) {
|
|
594
|
+
const envelope = readResultEnvelope(resultPtr);
|
|
595
|
+
if (!("success" in envelope))
|
|
596
|
+
return envelope;
|
|
597
|
+
return { ok: true, value: undefined };
|
|
598
|
+
}
|
|
599
|
+
function ffiCreate(basePath, frecencyDbPath, historyDbPath, _useUnsafeNoLock, enableMmapCache, enableContentIndexing, watch, aiMode, logFilePath, logLevel, cacheBudgetMaxFiles, cacheBudgetMaxBytes, cacheBudgetMaxFileSize, enableFsRootScanning, enableHomeDirScanning) {
|
|
600
|
+
const library = loadLibrary();
|
|
601
|
+
const basePathCStr = encodeCStringBuf(basePath);
|
|
602
|
+
const frecencyCStr = encodeCStringBuf(frecencyDbPath);
|
|
603
|
+
const historyCStr = encodeCStringBuf(historyDbPath);
|
|
604
|
+
const logFileCStr = encodeCStringBuf(logFilePath);
|
|
605
|
+
const logLevelCStr = encodeCStringBuf(logLevel);
|
|
606
|
+
const opts = Buffer.alloc(FFF_CREATE_OPTIONS_SIZE);
|
|
607
|
+
opts.writeUInt32LE(FFF_CREATE_OPTIONS_VERSION, FCO_VERSION);
|
|
608
|
+
writePtrLE(opts, FCO_BASE_PATH, basePathCStr);
|
|
609
|
+
writePtrLE(opts, FCO_FRECENCY_DB_PATH, frecencyCStr);
|
|
610
|
+
writePtrLE(opts, FCO_HISTORY_DB_PATH, historyCStr);
|
|
611
|
+
opts.writeUInt8(enableMmapCache ? 1 : 0, FCO_ENABLE_MMAP_CACHE);
|
|
612
|
+
opts.writeUInt8(enableContentIndexing ? 1 : 0, FCO_ENABLE_CONTENT_INDEXING);
|
|
613
|
+
opts.writeUInt8(watch ? 1 : 0, FCO_WATCH);
|
|
614
|
+
opts.writeUInt8(aiMode ? 1 : 0, FCO_AI_MODE);
|
|
615
|
+
writePtrLE(opts, FCO_LOG_FILE_PATH, logFileCStr);
|
|
616
|
+
writePtrLE(opts, FCO_LOG_LEVEL, logLevelCStr);
|
|
617
|
+
opts.writeBigUInt64LE(cacheBudgetMaxFiles, FCO_CACHE_BUDGET_MAX_FILES);
|
|
618
|
+
opts.writeBigUInt64LE(cacheBudgetMaxBytes, FCO_CACHE_BUDGET_MAX_BYTES);
|
|
619
|
+
opts.writeBigUInt64LE(cacheBudgetMaxFileSize, FCO_CACHE_BUDGET_MAX_FILE_SIZE);
|
|
620
|
+
opts.writeUInt8(enableFsRootScanning ? 1 : 0, FCO_ENABLE_FS_ROOT_SCANNING);
|
|
621
|
+
opts.writeUInt8(enableHomeDirScanning ? 1 : 0, FCO_ENABLE_HOME_DIR_SCANNING);
|
|
622
|
+
const resultPtr = library.symbols.fff_create_instance_with(ptr(opts));
|
|
623
|
+
if (resultPtr === null) {
|
|
624
|
+
return err("FFI returned null pointer");
|
|
625
|
+
}
|
|
626
|
+
const success = read.u8(resultPtr, RES_SUCCESS) !== 0;
|
|
627
|
+
if (success) {
|
|
628
|
+
const handlePtr = read.ptr(resultPtr, RES_HANDLE);
|
|
629
|
+
const handle = handlePtr;
|
|
630
|
+
library.symbols.fff_free_result(resultPtr);
|
|
631
|
+
if (!handle || handle === 0) {
|
|
632
|
+
return err("fff_create_instance_with returned null handle");
|
|
633
|
+
}
|
|
634
|
+
return { ok: true, value: handle };
|
|
635
|
+
} else {
|
|
636
|
+
const errorPtr = read.ptr(resultPtr, RES_ERROR);
|
|
637
|
+
const errorMsg = readCString(errorPtr) || "Unknown error";
|
|
638
|
+
library.symbols.fff_free_result(resultPtr);
|
|
639
|
+
return err(errorMsg);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
function encodeCStringBuf(s) {
|
|
643
|
+
if (!s)
|
|
644
|
+
return null;
|
|
645
|
+
return Buffer.from(s + "\x00", "utf-8");
|
|
646
|
+
}
|
|
647
|
+
function writePtrLE(buf, offset, target) {
|
|
648
|
+
if (target == null) {
|
|
649
|
+
buf.writeBigUInt64LE(0n, offset);
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
buf.writeBigUInt64LE(BigInt(ptr(target)), offset);
|
|
653
|
+
}
|
|
654
|
+
function ffiDestroy(handle) {
|
|
655
|
+
const library = loadLibrary();
|
|
656
|
+
library.symbols.fff_destroy(handle);
|
|
657
|
+
}
|
|
658
|
+
var SR_ITEMS = 0;
|
|
659
|
+
var SR_SCORES = 8;
|
|
660
|
+
var SR_COUNT = 16;
|
|
661
|
+
var SR_MATCHED = 20;
|
|
662
|
+
var SR_TOTAL = 24;
|
|
663
|
+
var SR_LOC_TAG = 28;
|
|
664
|
+
var SR_LOC_LINE = 32;
|
|
665
|
+
var SR_LOC_COL = 36;
|
|
666
|
+
var SR_LOC_END_LINE = 40;
|
|
667
|
+
var SR_LOC_END_COL = 44;
|
|
668
|
+
var FI_RELPATH = 0;
|
|
669
|
+
var FI_FNAME = 8;
|
|
670
|
+
var FI_GIT = 16;
|
|
671
|
+
var FI_SIZE = 24;
|
|
672
|
+
var FI_MODIFIED = 32;
|
|
673
|
+
var FI_ACCESS = 40;
|
|
674
|
+
var FI_MODFR = 48;
|
|
675
|
+
var FI_TOTAL_FR = 56;
|
|
676
|
+
var FI_SIZE_OF = 72;
|
|
677
|
+
var SC_TOTAL = 0;
|
|
678
|
+
var SC_BASE = 4;
|
|
679
|
+
var SC_FNAME = 8;
|
|
680
|
+
var SC_SPECIAL = 12;
|
|
681
|
+
var SC_FREC = 16;
|
|
682
|
+
var SC_DIST = 20;
|
|
683
|
+
var SC_CURFILE = 24;
|
|
684
|
+
var SC_COMBO = 28;
|
|
685
|
+
var SC_EXACT = 32;
|
|
686
|
+
var SC_MTYPE = 40;
|
|
687
|
+
var SC_SIZE_OF = 48;
|
|
688
|
+
function asPtr(n) {
|
|
689
|
+
return n;
|
|
690
|
+
}
|
|
691
|
+
function readFileItemStruct(p) {
|
|
692
|
+
const pp = asPtr(p);
|
|
693
|
+
return {
|
|
694
|
+
relativePath: readCString(read.ptr(pp, FI_RELPATH)) ?? "",
|
|
695
|
+
fileName: readCString(read.ptr(pp, FI_FNAME)) ?? "",
|
|
696
|
+
gitStatus: readCString(read.ptr(pp, FI_GIT)) ?? "",
|
|
697
|
+
size: Number(read.u64(pp, FI_SIZE)),
|
|
698
|
+
modified: Number(read.u64(pp, FI_MODIFIED)),
|
|
699
|
+
accessFrecencyScore: Number(read.i64(pp, FI_ACCESS)),
|
|
700
|
+
modificationFrecencyScore: Number(read.i64(pp, FI_MODFR)),
|
|
701
|
+
totalFrecencyScore: Number(read.i64(pp, FI_TOTAL_FR))
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
function readScoreStruct(p) {
|
|
705
|
+
const pp = asPtr(p);
|
|
706
|
+
return {
|
|
707
|
+
total: read.i32(pp, SC_TOTAL),
|
|
708
|
+
baseScore: read.i32(pp, SC_BASE),
|
|
709
|
+
filenameBonus: read.i32(pp, SC_FNAME),
|
|
710
|
+
specialFilenameBonus: read.i32(pp, SC_SPECIAL),
|
|
711
|
+
frecencyBoost: read.i32(pp, SC_FREC),
|
|
712
|
+
distancePenalty: read.i32(pp, SC_DIST),
|
|
713
|
+
currentFilePenalty: read.i32(pp, SC_CURFILE),
|
|
714
|
+
comboMatchBoost: read.i32(pp, SC_COMBO),
|
|
715
|
+
exactMatch: read.u8(pp, SC_EXACT) !== 0,
|
|
716
|
+
matchType: readCString(read.ptr(pp, SC_MTYPE)) ?? ""
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
function parseSearchResult(resultPtr) {
|
|
720
|
+
if (resultPtr === null) {
|
|
721
|
+
return err("FFI returned null pointer");
|
|
722
|
+
}
|
|
723
|
+
const envelope = readResultEnvelope(resultPtr);
|
|
724
|
+
if (!("success" in envelope))
|
|
725
|
+
return envelope;
|
|
726
|
+
if (envelope.handlePtr === 0) {
|
|
727
|
+
return err("fff_search returned null search result");
|
|
728
|
+
}
|
|
729
|
+
const hp = asPtr(envelope.handlePtr);
|
|
730
|
+
const count = read.u32(hp, SR_COUNT);
|
|
731
|
+
const totalMatched = read.u32(hp, SR_MATCHED);
|
|
732
|
+
const totalFiles = read.u32(hp, SR_TOTAL);
|
|
733
|
+
const itemsBase = read.ptr(hp, SR_ITEMS);
|
|
734
|
+
const scoresBase = read.ptr(hp, SR_SCORES);
|
|
735
|
+
const locTag = read.u8(hp, SR_LOC_TAG);
|
|
736
|
+
let location;
|
|
737
|
+
if (locTag === 1) {
|
|
738
|
+
location = { type: "line", line: read.i32(hp, SR_LOC_LINE) };
|
|
739
|
+
} else if (locTag === 2) {
|
|
740
|
+
location = {
|
|
741
|
+
type: "position",
|
|
742
|
+
line: read.i32(hp, SR_LOC_LINE),
|
|
743
|
+
col: read.i32(hp, SR_LOC_COL)
|
|
744
|
+
};
|
|
745
|
+
} else if (locTag === 3) {
|
|
746
|
+
location = {
|
|
747
|
+
type: "range",
|
|
748
|
+
start: { line: read.i32(hp, SR_LOC_LINE), col: read.i32(hp, SR_LOC_COL) },
|
|
749
|
+
end: {
|
|
750
|
+
line: read.i32(hp, SR_LOC_END_LINE),
|
|
751
|
+
col: read.i32(hp, SR_LOC_END_COL)
|
|
752
|
+
}
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
const items = [];
|
|
756
|
+
const scores = [];
|
|
757
|
+
for (let i = 0;i < count; i++) {
|
|
758
|
+
items.push(readFileItemStruct(itemsBase + i * FI_SIZE_OF));
|
|
759
|
+
scores.push(readScoreStruct(scoresBase + i * SC_SIZE_OF));
|
|
760
|
+
}
|
|
761
|
+
loadLibrary().symbols.fff_free_search_result(hp);
|
|
762
|
+
const result = { items, scores, totalMatched, totalFiles };
|
|
763
|
+
if (location) {
|
|
764
|
+
result.location = location;
|
|
765
|
+
}
|
|
766
|
+
return { ok: true, value: result };
|
|
767
|
+
}
|
|
768
|
+
var DSR_COUNT = 16;
|
|
769
|
+
var DSR_MATCHED = 20;
|
|
770
|
+
var DSR_TOTAL_DIRS = 24;
|
|
771
|
+
var DI_RELPATH = 0;
|
|
772
|
+
var DI_DIRNAME = 8;
|
|
773
|
+
var DI_MAX_FRECENCY = 16;
|
|
774
|
+
function readDirItemStruct(p) {
|
|
775
|
+
const pp = asPtr(p);
|
|
776
|
+
return {
|
|
777
|
+
relativePath: readCString(read.ptr(pp, DI_RELPATH)) ?? "",
|
|
778
|
+
dirName: readCString(read.ptr(pp, DI_DIRNAME)) ?? "",
|
|
779
|
+
maxAccessFrecency: read.i32(pp, DI_MAX_FRECENCY)
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
function parseDirSearchResult(resultPtr) {
|
|
783
|
+
if (resultPtr === null) {
|
|
784
|
+
return err("FFI returned null pointer");
|
|
785
|
+
}
|
|
786
|
+
const envelope = readResultEnvelope(resultPtr);
|
|
787
|
+
if (!("success" in envelope))
|
|
788
|
+
return envelope;
|
|
789
|
+
if (envelope.handlePtr === 0) {
|
|
790
|
+
return err("fff_search_directories returned null search result");
|
|
791
|
+
}
|
|
792
|
+
const hp = asPtr(envelope.handlePtr);
|
|
793
|
+
const count = read.u32(hp, DSR_COUNT);
|
|
794
|
+
const totalMatched = read.u32(hp, DSR_MATCHED);
|
|
795
|
+
const totalDirs = read.u32(hp, DSR_TOTAL_DIRS);
|
|
796
|
+
const library = loadLibrary();
|
|
797
|
+
const items = [];
|
|
798
|
+
const scores = [];
|
|
799
|
+
for (let i = 0;i < count; i++) {
|
|
800
|
+
const itemPtr = library.symbols.fff_dir_search_result_get_item(hp, i);
|
|
801
|
+
if (itemPtr !== null && itemPtr !== 0) {
|
|
802
|
+
items.push(readDirItemStruct(itemPtr));
|
|
803
|
+
}
|
|
804
|
+
const scorePtr = library.symbols.fff_dir_search_result_get_score(hp, i);
|
|
805
|
+
if (scorePtr !== null && scorePtr !== 0) {
|
|
806
|
+
scores.push(readScoreStruct(scorePtr));
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
library.symbols.fff_free_dir_search_result(hp);
|
|
810
|
+
return { ok: true, value: { items, scores, totalMatched, totalDirs } };
|
|
811
|
+
}
|
|
812
|
+
var MSR_COUNT = 16;
|
|
813
|
+
var MSR_MATCHED = 20;
|
|
814
|
+
var MSR_TOTAL_FILES = 24;
|
|
815
|
+
var MSR_TOTAL_DIRS = 28;
|
|
816
|
+
var MSR_LOC_TAG = 32;
|
|
817
|
+
var MSR_LOC_LINE = 36;
|
|
818
|
+
var MSR_LOC_COL = 40;
|
|
819
|
+
var MSR_LOC_END_LINE = 44;
|
|
820
|
+
var MSR_LOC_END_COL = 48;
|
|
821
|
+
var MI_TYPE = 0;
|
|
822
|
+
var MI_RELPATH = 8;
|
|
823
|
+
var MI_DISPLAY = 16;
|
|
824
|
+
var MI_GIT = 24;
|
|
825
|
+
var MI_SIZE = 32;
|
|
826
|
+
var MI_MODIFIED = 40;
|
|
827
|
+
var MI_ACCESS = 48;
|
|
828
|
+
var MI_MODFR = 56;
|
|
829
|
+
var MI_TOTAL_FR = 64;
|
|
830
|
+
function readMixedItemStruct(p) {
|
|
831
|
+
const pp = asPtr(p);
|
|
832
|
+
const itemType = read.u8(pp, MI_TYPE);
|
|
833
|
+
if (itemType === 1) {
|
|
834
|
+
return {
|
|
835
|
+
type: "directory",
|
|
836
|
+
item: {
|
|
837
|
+
relativePath: readCString(read.ptr(pp, MI_RELPATH)) ?? "",
|
|
838
|
+
dirName: readCString(read.ptr(pp, MI_DISPLAY)) ?? "",
|
|
839
|
+
maxAccessFrecency: Number(read.i64(pp, MI_ACCESS))
|
|
840
|
+
}
|
|
841
|
+
};
|
|
842
|
+
}
|
|
843
|
+
return {
|
|
844
|
+
type: "file",
|
|
845
|
+
item: {
|
|
846
|
+
relativePath: readCString(read.ptr(pp, MI_RELPATH)) ?? "",
|
|
847
|
+
fileName: readCString(read.ptr(pp, MI_DISPLAY)) ?? "",
|
|
848
|
+
gitStatus: readCString(read.ptr(pp, MI_GIT)) ?? "",
|
|
849
|
+
size: Number(read.u64(pp, MI_SIZE)),
|
|
850
|
+
modified: Number(read.u64(pp, MI_MODIFIED)),
|
|
851
|
+
accessFrecencyScore: Number(read.i64(pp, MI_ACCESS)),
|
|
852
|
+
modificationFrecencyScore: Number(read.i64(pp, MI_MODFR)),
|
|
853
|
+
totalFrecencyScore: Number(read.i64(pp, MI_TOTAL_FR))
|
|
854
|
+
}
|
|
855
|
+
};
|
|
856
|
+
}
|
|
857
|
+
function parseMixedSearchResult(resultPtr) {
|
|
858
|
+
if (resultPtr === null) {
|
|
859
|
+
return err("FFI returned null pointer");
|
|
860
|
+
}
|
|
861
|
+
const envelope = readResultEnvelope(resultPtr);
|
|
862
|
+
if (!("success" in envelope))
|
|
863
|
+
return envelope;
|
|
864
|
+
if (envelope.handlePtr === 0) {
|
|
865
|
+
return err("fff_search_mixed returned null search result");
|
|
866
|
+
}
|
|
867
|
+
const hp = asPtr(envelope.handlePtr);
|
|
868
|
+
const count = read.u32(hp, MSR_COUNT);
|
|
869
|
+
const totalMatched = read.u32(hp, MSR_MATCHED);
|
|
870
|
+
const totalFiles = read.u32(hp, MSR_TOTAL_FILES);
|
|
871
|
+
const totalDirs = read.u32(hp, MSR_TOTAL_DIRS);
|
|
872
|
+
const locTag = read.u8(hp, MSR_LOC_TAG);
|
|
873
|
+
let location;
|
|
874
|
+
if (locTag === 1) {
|
|
875
|
+
location = { type: "line", line: read.i32(hp, MSR_LOC_LINE) };
|
|
876
|
+
} else if (locTag === 2) {
|
|
877
|
+
location = {
|
|
878
|
+
type: "position",
|
|
879
|
+
line: read.i32(hp, MSR_LOC_LINE),
|
|
880
|
+
col: read.i32(hp, MSR_LOC_COL)
|
|
881
|
+
};
|
|
882
|
+
} else if (locTag === 3) {
|
|
883
|
+
location = {
|
|
884
|
+
type: "range",
|
|
885
|
+
start: {
|
|
886
|
+
line: read.i32(hp, MSR_LOC_LINE),
|
|
887
|
+
col: read.i32(hp, MSR_LOC_COL)
|
|
888
|
+
},
|
|
889
|
+
end: {
|
|
890
|
+
line: read.i32(hp, MSR_LOC_END_LINE),
|
|
891
|
+
col: read.i32(hp, MSR_LOC_END_COL)
|
|
892
|
+
}
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
const library = loadLibrary();
|
|
896
|
+
const items = [];
|
|
897
|
+
const scores = [];
|
|
898
|
+
for (let i = 0;i < count; i++) {
|
|
899
|
+
const itemPtr = library.symbols.fff_mixed_search_result_get_item(hp, i);
|
|
900
|
+
if (itemPtr !== null && itemPtr !== 0) {
|
|
901
|
+
items.push(readMixedItemStruct(itemPtr));
|
|
902
|
+
}
|
|
903
|
+
const scorePtr = library.symbols.fff_mixed_search_result_get_score(hp, i);
|
|
904
|
+
if (scorePtr !== null && scorePtr !== 0) {
|
|
905
|
+
scores.push(readScoreStruct(scorePtr));
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
library.symbols.fff_free_mixed_search_result(hp);
|
|
909
|
+
const result = {
|
|
910
|
+
items,
|
|
911
|
+
scores,
|
|
912
|
+
totalMatched,
|
|
913
|
+
totalFiles,
|
|
914
|
+
totalDirs
|
|
915
|
+
};
|
|
916
|
+
if (location) {
|
|
917
|
+
result.location = location;
|
|
918
|
+
}
|
|
919
|
+
return { ok: true, value: result };
|
|
920
|
+
}
|
|
921
|
+
var GM_RELPATH = 0;
|
|
922
|
+
var GM_FNAME = 8;
|
|
923
|
+
var GM_GIT = 16;
|
|
924
|
+
var GM_LINE_CONTENT = 24;
|
|
925
|
+
var GM_MATCH_RANGES = 32;
|
|
926
|
+
var GM_CTX_BEFORE = 40;
|
|
927
|
+
var GM_CTX_AFTER = 48;
|
|
928
|
+
var GM_SIZE = 56;
|
|
929
|
+
var GM_MODIFIED = 64;
|
|
930
|
+
var GM_TOTAL_FR = 72;
|
|
931
|
+
var GM_ACCESS_FR = 80;
|
|
932
|
+
var GM_MOD_FR = 88;
|
|
933
|
+
var GM_LINE_NUM = 96;
|
|
934
|
+
var GM_BYTE_OFF = 104;
|
|
935
|
+
var GM_COL = 112;
|
|
936
|
+
var GM_MR_COUNT = 116;
|
|
937
|
+
var GM_CTX_B_COUNT = 120;
|
|
938
|
+
var GM_CTX_A_COUNT = 124;
|
|
939
|
+
var GM_FUZZY_SCORE = 128;
|
|
940
|
+
var GM_HAS_FUZZY = 130;
|
|
941
|
+
var GM_IS_BINARY = 131;
|
|
942
|
+
var GM_IS_DEFINITION = 132;
|
|
943
|
+
var GM_SIZE_OF = 136;
|
|
944
|
+
var GR_ITEMS = 0;
|
|
945
|
+
var GR_COUNT = 8;
|
|
946
|
+
var GR_MATCHED = 12;
|
|
947
|
+
var GR_FILES_SEARCHED = 16;
|
|
948
|
+
var GR_TOTAL_FILES = 20;
|
|
949
|
+
var GR_FILTERED = 24;
|
|
950
|
+
var GR_NEXT_OFFSET = 28;
|
|
951
|
+
var GR_REGEX_ERR = 32;
|
|
952
|
+
var MR_START = 0;
|
|
953
|
+
var MR_END = 4;
|
|
954
|
+
var MR_SIZE = 8;
|
|
955
|
+
function readCStringArray(base, count) {
|
|
956
|
+
if (count === 0 || base === 0)
|
|
957
|
+
return [];
|
|
958
|
+
const result = [];
|
|
959
|
+
const bp = asPtr(base);
|
|
960
|
+
for (let i = 0;i < count; i++) {
|
|
961
|
+
const strPtr = read.ptr(bp, i * 8);
|
|
962
|
+
result.push(readCString(strPtr) ?? "");
|
|
963
|
+
}
|
|
964
|
+
return result;
|
|
965
|
+
}
|
|
966
|
+
function readGrepMatchStruct(p) {
|
|
967
|
+
const pp = asPtr(p);
|
|
968
|
+
const matchRangesPtr = read.ptr(pp, GM_MATCH_RANGES);
|
|
969
|
+
const matchRangesCount = read.u32(pp, GM_MR_COUNT);
|
|
970
|
+
const matchRanges = [];
|
|
971
|
+
for (let i = 0;i < matchRangesCount; i++) {
|
|
972
|
+
const base = matchRangesPtr + i * MR_SIZE;
|
|
973
|
+
const bp = asPtr(base);
|
|
974
|
+
matchRanges.push([read.u32(bp, MR_START), read.u32(bp, MR_END)]);
|
|
975
|
+
}
|
|
976
|
+
const hasFuzzy = read.u8(pp, GM_HAS_FUZZY) !== 0;
|
|
977
|
+
const ctxBeforeCount = read.u32(pp, GM_CTX_B_COUNT);
|
|
978
|
+
const ctxAfterCount = read.u32(pp, GM_CTX_A_COUNT);
|
|
979
|
+
const match = {
|
|
980
|
+
relativePath: readCString(read.ptr(pp, GM_RELPATH)) ?? "",
|
|
981
|
+
fileName: readCString(read.ptr(pp, GM_FNAME)) ?? "",
|
|
982
|
+
gitStatus: readCString(read.ptr(pp, GM_GIT)) ?? "",
|
|
983
|
+
lineContent: readCString(read.ptr(pp, GM_LINE_CONTENT)) ?? "",
|
|
984
|
+
size: Number(read.u64(pp, GM_SIZE)),
|
|
985
|
+
modified: Number(read.u64(pp, GM_MODIFIED)),
|
|
986
|
+
totalFrecencyScore: Number(read.i64(pp, GM_TOTAL_FR)),
|
|
987
|
+
accessFrecencyScore: Number(read.i64(pp, GM_ACCESS_FR)),
|
|
988
|
+
modificationFrecencyScore: Number(read.i64(pp, GM_MOD_FR)),
|
|
989
|
+
isBinary: read.u8(pp, GM_IS_BINARY) !== 0,
|
|
990
|
+
lineNumber: Number(read.u64(pp, GM_LINE_NUM)),
|
|
991
|
+
col: read.u32(pp, GM_COL),
|
|
992
|
+
byteOffset: Number(read.u64(pp, GM_BYTE_OFF)),
|
|
993
|
+
matchRanges
|
|
994
|
+
};
|
|
995
|
+
if (hasFuzzy) {
|
|
996
|
+
match.fuzzyScore = read.u16(pp, GM_FUZZY_SCORE);
|
|
997
|
+
}
|
|
998
|
+
if (ctxBeforeCount > 0) {
|
|
999
|
+
match.contextBefore = readCStringArray(read.ptr(pp, GM_CTX_BEFORE), ctxBeforeCount);
|
|
1000
|
+
}
|
|
1001
|
+
if (ctxAfterCount > 0) {
|
|
1002
|
+
match.contextAfter = readCStringArray(read.ptr(pp, GM_CTX_AFTER), ctxAfterCount);
|
|
1003
|
+
}
|
|
1004
|
+
if (read.u8(pp, GM_IS_DEFINITION) !== 0) {
|
|
1005
|
+
match.isDefinition = true;
|
|
1006
|
+
}
|
|
1007
|
+
return match;
|
|
1008
|
+
}
|
|
1009
|
+
function parseGrepResult(resultPtr) {
|
|
1010
|
+
const envelope = readResultEnvelope(resultPtr);
|
|
1011
|
+
if (!("success" in envelope))
|
|
1012
|
+
return envelope;
|
|
1013
|
+
if (envelope.handlePtr === 0) {
|
|
1014
|
+
return err("grep returned null result");
|
|
1015
|
+
}
|
|
1016
|
+
const hp = asPtr(envelope.handlePtr);
|
|
1017
|
+
const count = read.u32(hp, GR_COUNT);
|
|
1018
|
+
const totalMatched = read.u32(hp, GR_MATCHED);
|
|
1019
|
+
const totalFilesSearched = read.u32(hp, GR_FILES_SEARCHED);
|
|
1020
|
+
const totalFiles = read.u32(hp, GR_TOTAL_FILES);
|
|
1021
|
+
const filteredFileCount = read.u32(hp, GR_FILTERED);
|
|
1022
|
+
const nextFileOffset = read.u32(hp, GR_NEXT_OFFSET);
|
|
1023
|
+
const regexErrPtr = read.ptr(hp, GR_REGEX_ERR);
|
|
1024
|
+
const regexFallbackError = readCString(regexErrPtr) ?? undefined;
|
|
1025
|
+
const itemsBase = read.ptr(hp, GR_ITEMS);
|
|
1026
|
+
const items = [];
|
|
1027
|
+
for (let i = 0;i < count; i++) {
|
|
1028
|
+
items.push(readGrepMatchStruct(itemsBase + i * GM_SIZE_OF));
|
|
1029
|
+
}
|
|
1030
|
+
loadLibrary().symbols.fff_free_grep_result(hp);
|
|
1031
|
+
const grepResult = {
|
|
1032
|
+
items,
|
|
1033
|
+
totalMatched,
|
|
1034
|
+
totalFilesSearched,
|
|
1035
|
+
totalFiles,
|
|
1036
|
+
filteredFileCount,
|
|
1037
|
+
nextCursor: nextFileOffset > 0 ? createGrepCursor(nextFileOffset) : null
|
|
1038
|
+
};
|
|
1039
|
+
if (regexFallbackError) {
|
|
1040
|
+
grepResult.regexFallbackError = regexFallbackError;
|
|
1041
|
+
}
|
|
1042
|
+
return { ok: true, value: grepResult };
|
|
1043
|
+
}
|
|
1044
|
+
function ffiSearch(handle, query, currentFile, maxThreads, pageIndex, pageSize, comboBoostMultiplier, minComboCount) {
|
|
1045
|
+
const library = loadLibrary();
|
|
1046
|
+
const resultPtr = library.symbols.fff_search(handle, ptr(encodeString(query)), ptr(encodeString(currentFile)), maxThreads, pageIndex, pageSize, comboBoostMultiplier, minComboCount);
|
|
1047
|
+
return parseSearchResult(resultPtr);
|
|
1048
|
+
}
|
|
1049
|
+
function ffiGlob(handle, pattern, currentFile, maxThreads, pageIndex, pageSize) {
|
|
1050
|
+
const library = loadLibrary();
|
|
1051
|
+
const resultPtr = library.symbols.fff_glob(handle, ptr(encodeString(pattern)), ptr(encodeString(currentFile)), maxThreads, pageIndex, pageSize);
|
|
1052
|
+
return parseSearchResult(resultPtr);
|
|
1053
|
+
}
|
|
1054
|
+
function ffiSearchDirectories(handle, query, currentFile, maxThreads, pageIndex, pageSize) {
|
|
1055
|
+
const library = loadLibrary();
|
|
1056
|
+
const resultPtr = library.symbols.fff_search_directories(handle, ptr(encodeString(query)), ptr(encodeString(currentFile ?? "")), maxThreads, pageIndex, pageSize);
|
|
1057
|
+
return parseDirSearchResult(resultPtr);
|
|
1058
|
+
}
|
|
1059
|
+
function ffiSearchMixed(handle, query, currentFile, maxThreads, pageIndex, pageSize, comboBoostMultiplier, minComboCount) {
|
|
1060
|
+
const library = loadLibrary();
|
|
1061
|
+
const resultPtr = library.symbols.fff_search_mixed(handle, ptr(encodeString(query)), ptr(encodeString(currentFile)), maxThreads, pageIndex, pageSize, comboBoostMultiplier, minComboCount);
|
|
1062
|
+
return parseMixedSearchResult(resultPtr);
|
|
1063
|
+
}
|
|
1064
|
+
function ffiLiveGrep(handle, query, mode, maxFileSize, maxMatchesPerFile, smartCase, fileOffset, pageLimit, timeBudgetMs, beforeContext, afterContext, classifyDefinitions) {
|
|
1065
|
+
const library = loadLibrary();
|
|
1066
|
+
const resultPtr = library.symbols.fff_live_grep(handle, ptr(encodeString(query)), grepModeToU8(mode), BigInt(maxFileSize), maxMatchesPerFile, smartCase, fileOffset, pageLimit, BigInt(timeBudgetMs), beforeContext, afterContext, classifyDefinitions);
|
|
1067
|
+
return parseGrepResult(resultPtr);
|
|
1068
|
+
}
|
|
1069
|
+
function ffiMultiGrep(handle, patternsJoined, constraints, maxFileSize, maxMatchesPerFile, smartCase, fileOffset, pageLimit, timeBudgetMs, beforeContext, afterContext, classifyDefinitions) {
|
|
1070
|
+
const library = loadLibrary();
|
|
1071
|
+
const resultPtr = library.symbols.fff_multi_grep(handle, ptr(encodeString(patternsJoined)), ptr(encodeString(constraints)), BigInt(maxFileSize), maxMatchesPerFile, smartCase, fileOffset, pageLimit, BigInt(timeBudgetMs), beforeContext, afterContext, classifyDefinitions);
|
|
1072
|
+
return parseGrepResult(resultPtr);
|
|
1073
|
+
}
|
|
1074
|
+
function ffiScanFiles(handle) {
|
|
1075
|
+
const library = loadLibrary();
|
|
1076
|
+
const resultPtr = library.symbols.fff_scan_files(handle);
|
|
1077
|
+
return parseVoidResult(resultPtr);
|
|
1078
|
+
}
|
|
1079
|
+
function ffiIsScanning(handle) {
|
|
1080
|
+
const library = loadLibrary();
|
|
1081
|
+
return library.symbols.fff_is_scanning(handle);
|
|
1082
|
+
}
|
|
1083
|
+
function ffiGetBasePath(handle) {
|
|
1084
|
+
const library = loadLibrary();
|
|
1085
|
+
const resultPtr = library.symbols.fff_get_base_path(handle);
|
|
1086
|
+
return parseStringResult(resultPtr);
|
|
1087
|
+
}
|
|
1088
|
+
var SP_COUNT = 0;
|
|
1089
|
+
var SP_SCANNING = 8;
|
|
1090
|
+
var SP_WATCHER_READY = 9;
|
|
1091
|
+
var SP_WARMUP_COMPLETE = 10;
|
|
1092
|
+
function ffiGetScanProgress(handle) {
|
|
1093
|
+
const library = loadLibrary();
|
|
1094
|
+
const resultPtr = library.symbols.fff_get_scan_progress(handle);
|
|
1095
|
+
const envelope = readResultEnvelope(resultPtr);
|
|
1096
|
+
if (!("success" in envelope))
|
|
1097
|
+
return envelope;
|
|
1098
|
+
if (envelope.handlePtr === 0) {
|
|
1099
|
+
return err("scan progress returned null");
|
|
1100
|
+
}
|
|
1101
|
+
const hp = asPtr(envelope.handlePtr);
|
|
1102
|
+
const result = {
|
|
1103
|
+
scannedFilesCount: Number(read.u64(hp, SP_COUNT)),
|
|
1104
|
+
isScanning: read.u8(hp, SP_SCANNING) !== 0,
|
|
1105
|
+
isWatcherReady: read.u8(hp, SP_WATCHER_READY) !== 0,
|
|
1106
|
+
isWarmupComplete: read.u8(hp, SP_WARMUP_COMPLETE) !== 0
|
|
1107
|
+
};
|
|
1108
|
+
library.symbols.fff_free_scan_progress(hp);
|
|
1109
|
+
return { ok: true, value: result };
|
|
1110
|
+
}
|
|
1111
|
+
function ffiWaitForScan(handle, timeoutMs) {
|
|
1112
|
+
const library = loadLibrary();
|
|
1113
|
+
const resultPtr = library.symbols.fff_wait_for_scan(handle, BigInt(timeoutMs));
|
|
1114
|
+
return parseBoolResult(resultPtr);
|
|
1115
|
+
}
|
|
1116
|
+
function ffiRestartIndex(handle, newPath) {
|
|
1117
|
+
const library = loadLibrary();
|
|
1118
|
+
const resultPtr = library.symbols.fff_restart_index(handle, ptr(encodeString(newPath)));
|
|
1119
|
+
return parseVoidResult(resultPtr);
|
|
1120
|
+
}
|
|
1121
|
+
var FFF_WATCH_OPTIONS_VERSION = 1;
|
|
1122
|
+
var FFF_WATCH_OPTIONS_SIZE = 24;
|
|
1123
|
+
var FWO_VERSION = 0;
|
|
1124
|
+
var FWO_IGNORE = 8;
|
|
1125
|
+
var FWO_IGNORE_COUNT = 16;
|
|
1126
|
+
var WATCH_EVENT_KINDS = [
|
|
1127
|
+
"created",
|
|
1128
|
+
"modified",
|
|
1129
|
+
"removed",
|
|
1130
|
+
"rescan"
|
|
1131
|
+
];
|
|
1132
|
+
function readWatchEventBatch(batchPtr) {
|
|
1133
|
+
if (batchPtr === null || batchPtr === 0) {
|
|
1134
|
+
return [];
|
|
1135
|
+
}
|
|
1136
|
+
const bp = batchPtr;
|
|
1137
|
+
const symbols = loadLibrary().symbols;
|
|
1138
|
+
const count = symbols.fff_watch_events_count(bp);
|
|
1139
|
+
const events = [];
|
|
1140
|
+
for (let i = 0;i < count; i++) {
|
|
1141
|
+
const path = symbols.fff_watch_events_get_path(bp, i);
|
|
1142
|
+
const kind = symbols.fff_watch_events_get_kind(bp, i);
|
|
1143
|
+
events.push({
|
|
1144
|
+
path: readCString(path) ?? "",
|
|
1145
|
+
kind: WATCH_EVENT_KINDS[kind] ?? "rescan"
|
|
1146
|
+
});
|
|
1147
|
+
}
|
|
1148
|
+
symbols.fff_free_watch_events(bp);
|
|
1149
|
+
return events;
|
|
1150
|
+
}
|
|
1151
|
+
function ffiSetWatchCallback(handle, callback) {
|
|
1152
|
+
const library = loadLibrary();
|
|
1153
|
+
if (callback.ptr === null) {
|
|
1154
|
+
return err("watch callback has been closed");
|
|
1155
|
+
}
|
|
1156
|
+
const resultPtr = library.symbols.fff_set_watch_callback(handle, callback.ptr, null);
|
|
1157
|
+
return parseVoidResult(resultPtr);
|
|
1158
|
+
}
|
|
1159
|
+
function ffiWatch(handle, pattern, ignore = []) {
|
|
1160
|
+
const library = loadLibrary();
|
|
1161
|
+
const opts = Buffer.alloc(FFF_WATCH_OPTIONS_SIZE);
|
|
1162
|
+
opts.writeUInt32LE(FFF_WATCH_OPTIONS_VERSION, FWO_VERSION);
|
|
1163
|
+
const ignoreBuffers = ignore.map((entry) => encodeString(entry));
|
|
1164
|
+
const ignorePtrs = Buffer.alloc(Math.max(ignoreBuffers.length, 1) * 8);
|
|
1165
|
+
for (let i = 0;i < ignoreBuffers.length; i++) {
|
|
1166
|
+
ignorePtrs.writeBigUInt64LE(BigInt(ptr(ignoreBuffers[i])), i * 8);
|
|
1167
|
+
}
|
|
1168
|
+
opts.writeBigUInt64LE(ignoreBuffers.length > 0 ? BigInt(ptr(ignorePtrs)) : 0n, FWO_IGNORE);
|
|
1169
|
+
opts.writeUInt32LE(ignoreBuffers.length, FWO_IGNORE_COUNT);
|
|
1170
|
+
const resultPtr = library.symbols.fff_watch(handle, ptr(encodeString(pattern)), ptr(opts));
|
|
1171
|
+
return parseIntResult(resultPtr);
|
|
1172
|
+
}
|
|
1173
|
+
function ffiUnwatch(handle, watchId) {
|
|
1174
|
+
const library = loadLibrary();
|
|
1175
|
+
const resultPtr = library.symbols.fff_unwatch(handle, BigInt(watchId));
|
|
1176
|
+
return parseBoolResult(resultPtr);
|
|
1177
|
+
}
|
|
1178
|
+
function ffiRefreshGitStatus(handle) {
|
|
1179
|
+
const library = loadLibrary();
|
|
1180
|
+
const resultPtr = library.symbols.fff_refresh_git_status(handle);
|
|
1181
|
+
return parseIntResult(resultPtr);
|
|
1182
|
+
}
|
|
1183
|
+
function ffiTrackQuery(handle, query, filePath) {
|
|
1184
|
+
const library = loadLibrary();
|
|
1185
|
+
const resultPtr = library.symbols.fff_track_query(handle, ptr(encodeString(query)), ptr(encodeString(filePath)));
|
|
1186
|
+
return parseBoolResult(resultPtr);
|
|
1187
|
+
}
|
|
1188
|
+
function ffiGetHistoricalQuery(handle, offset) {
|
|
1189
|
+
const library = loadLibrary();
|
|
1190
|
+
const resultPtr = library.symbols.fff_get_historical_query(handle, BigInt(offset));
|
|
1191
|
+
return parseStringResult(resultPtr);
|
|
1192
|
+
}
|
|
1193
|
+
function ffiHealthCheck(handle, testPath) {
|
|
1194
|
+
const library = loadLibrary();
|
|
1195
|
+
const resultPtr = library.symbols.fff_health_check(handle ?? 0, ptr(encodeString(testPath)));
|
|
1196
|
+
return parseJsonResult(resultPtr);
|
|
1197
|
+
}
|
|
1198
|
+
function ensureLoaded() {
|
|
1199
|
+
loadLibrary();
|
|
1200
|
+
}
|
|
1201
|
+
function isAvailable() {
|
|
1202
|
+
try {
|
|
1203
|
+
loadLibrary();
|
|
1204
|
+
return true;
|
|
1205
|
+
} catch {
|
|
1206
|
+
return false;
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
// src/finder.ts
|
|
1211
|
+
class FileFinder {
|
|
1212
|
+
handle;
|
|
1213
|
+
watchHandlers = new Map;
|
|
1214
|
+
watchJsCallback = null;
|
|
1215
|
+
constructor(handle) {
|
|
1216
|
+
this.handle = handle;
|
|
1217
|
+
}
|
|
1218
|
+
static create(options) {
|
|
1219
|
+
const result = ffiCreate(options.basePath, options.frecencyDbPath ?? "", options.historyDbPath ?? "", options.useUnsafeNoLock ?? false, !(options.disableMmapCache ?? false), !(options.disableContentIndexing ?? options.disableMmapCache ?? false), !(options.disableWatch ?? false), options.aiMode ?? false, options.logFilePath ?? "", options.logLevel ?? "", BigInt(options.cacheBudgetMaxFiles ?? 0), BigInt(options.cacheBudgetMaxBytes ?? 0), BigInt(options.cacheBudgetMaxFileSize ?? 0), options.enableFsRootScanning ?? false, options.enableHomeDirScanning ?? false);
|
|
1220
|
+
if (!result.ok) {
|
|
1221
|
+
return result;
|
|
1222
|
+
}
|
|
1223
|
+
return { ok: true, value: new FileFinder(result.value) };
|
|
1224
|
+
}
|
|
1225
|
+
destroy() {
|
|
1226
|
+
if (this.handle !== null) {
|
|
1227
|
+
this.watchHandlers.clear();
|
|
1228
|
+
ffiDestroy(this.handle);
|
|
1229
|
+
this.handle = null;
|
|
1230
|
+
this.watchJsCallback?.close();
|
|
1231
|
+
this.watchJsCallback = null;
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
get isDestroyed() {
|
|
1235
|
+
return this.handle === null;
|
|
1236
|
+
}
|
|
1237
|
+
ensureAlive() {
|
|
1238
|
+
if (this.handle === null) {
|
|
1239
|
+
return err("FileFinder instance has been destroyed.");
|
|
1240
|
+
}
|
|
1241
|
+
return { ok: true, value: this.handle };
|
|
1242
|
+
}
|
|
1243
|
+
fileSearch(query, options) {
|
|
1244
|
+
const guard = this.ensureAlive();
|
|
1245
|
+
if (!guard.ok)
|
|
1246
|
+
return guard;
|
|
1247
|
+
return ffiSearch(guard.value, query, options?.currentFile ?? "", options?.maxThreads ?? 0, options?.pageIndex ?? 0, options?.pageSize ?? 0, options?.comboBoostMultiplier ?? 0, options?.minComboCount ?? 0);
|
|
1248
|
+
}
|
|
1249
|
+
glob(pattern, options) {
|
|
1250
|
+
const guard = this.ensureAlive();
|
|
1251
|
+
if (!guard.ok)
|
|
1252
|
+
return guard;
|
|
1253
|
+
return ffiGlob(guard.value, pattern, options?.currentFile ?? "", options?.maxThreads ?? 0, options?.pageIndex ?? 0, options?.pageSize ?? 0);
|
|
1254
|
+
}
|
|
1255
|
+
directorySearch(query, options) {
|
|
1256
|
+
const guard = this.ensureAlive();
|
|
1257
|
+
if (!guard.ok)
|
|
1258
|
+
return guard;
|
|
1259
|
+
return ffiSearchDirectories(guard.value, query, options?.currentFile ?? null, options?.maxThreads ?? 0, options?.pageIndex ?? 0, options?.pageSize ?? 0);
|
|
1260
|
+
}
|
|
1261
|
+
mixedSearch(query, options) {
|
|
1262
|
+
const guard = this.ensureAlive();
|
|
1263
|
+
if (!guard.ok)
|
|
1264
|
+
return guard;
|
|
1265
|
+
return ffiSearchMixed(guard.value, query, options?.currentFile ?? "", options?.maxThreads ?? 0, options?.pageIndex ?? 0, options?.pageSize ?? 0, options?.comboBoostMultiplier ?? 0, options?.minComboCount ?? 0);
|
|
1266
|
+
}
|
|
1267
|
+
grep(query, options) {
|
|
1268
|
+
const guard = this.ensureAlive();
|
|
1269
|
+
if (!guard.ok)
|
|
1270
|
+
return guard;
|
|
1271
|
+
return ffiLiveGrep(guard.value, query, options?.mode ?? "plain", options?.maxFileSize ?? 0, options?.maxMatchesPerFile ?? 0, options?.smartCase ?? true, options?.cursor?._offset ?? 0, options?.pageSize ?? 0, options?.timeBudgetMs ?? 0, options?.beforeContext ?? 0, options?.afterContext ?? 0, options?.classifyDefinitions ?? false);
|
|
1272
|
+
}
|
|
1273
|
+
multiGrep(options) {
|
|
1274
|
+
const guard = this.ensureAlive();
|
|
1275
|
+
if (!guard.ok)
|
|
1276
|
+
return guard;
|
|
1277
|
+
if (!options.patterns || options.patterns.length === 0) {
|
|
1278
|
+
return err("patterns array must have at least 1 element");
|
|
1279
|
+
}
|
|
1280
|
+
return ffiMultiGrep(guard.value, options.patterns.join(`
|
|
1281
|
+
`), options.constraints ?? "", options.maxFileSize ?? 0, options.maxMatchesPerFile ?? 0, options.smartCase ?? true, options.cursor?._offset ?? 0, options.pageSize ?? 0, options.timeBudgetMs ?? 0, options.beforeContext ?? 0, options.afterContext ?? 0, options.classifyDefinitions ?? false);
|
|
1282
|
+
}
|
|
1283
|
+
scanFiles() {
|
|
1284
|
+
const guard = this.ensureAlive();
|
|
1285
|
+
if (!guard.ok)
|
|
1286
|
+
return guard;
|
|
1287
|
+
return ffiScanFiles(guard.value);
|
|
1288
|
+
}
|
|
1289
|
+
isScanning() {
|
|
1290
|
+
if (this.handle === null)
|
|
1291
|
+
return false;
|
|
1292
|
+
return ffiIsScanning(this.handle);
|
|
1293
|
+
}
|
|
1294
|
+
getBasePath() {
|
|
1295
|
+
const guard = this.ensureAlive();
|
|
1296
|
+
if (!guard.ok)
|
|
1297
|
+
return guard;
|
|
1298
|
+
return ffiGetBasePath(guard.value);
|
|
1299
|
+
}
|
|
1300
|
+
getScanProgress() {
|
|
1301
|
+
const guard = this.ensureAlive();
|
|
1302
|
+
if (!guard.ok)
|
|
1303
|
+
return guard;
|
|
1304
|
+
return ffiGetScanProgress(guard.value);
|
|
1305
|
+
}
|
|
1306
|
+
async waitForScan(timeoutMs = 5000) {
|
|
1307
|
+
const guard = this.ensureAlive();
|
|
1308
|
+
if (!guard.ok)
|
|
1309
|
+
return guard;
|
|
1310
|
+
const deadline = Date.now() + timeoutMs;
|
|
1311
|
+
while (this.isScanning()) {
|
|
1312
|
+
if (Date.now() >= deadline) {
|
|
1313
|
+
return { ok: true, value: false };
|
|
1314
|
+
}
|
|
1315
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1316
|
+
}
|
|
1317
|
+
return { ok: true, value: true };
|
|
1318
|
+
}
|
|
1319
|
+
waitForScanBlocking(timeoutMs = 5000) {
|
|
1320
|
+
const guard = this.ensureAlive();
|
|
1321
|
+
if (!guard.ok)
|
|
1322
|
+
return guard;
|
|
1323
|
+
return ffiWaitForScan(guard.value, timeoutMs);
|
|
1324
|
+
}
|
|
1325
|
+
async waitForIndexReady(timeoutMs = 5000) {
|
|
1326
|
+
const guard = this.ensureAlive();
|
|
1327
|
+
if (!guard.ok)
|
|
1328
|
+
return guard;
|
|
1329
|
+
const deadline = Date.now() + timeoutMs;
|
|
1330
|
+
while (true) {
|
|
1331
|
+
const progress = this.getScanProgress();
|
|
1332
|
+
if (!progress.ok)
|
|
1333
|
+
return progress;
|
|
1334
|
+
if (!progress.value.isScanning && progress.value.isWarmupComplete) {
|
|
1335
|
+
return { ok: true, value: true };
|
|
1336
|
+
}
|
|
1337
|
+
if (Date.now() >= deadline) {
|
|
1338
|
+
return { ok: true, value: false };
|
|
1339
|
+
}
|
|
1340
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
reindex(newPath) {
|
|
1344
|
+
const guard = this.ensureAlive();
|
|
1345
|
+
if (!guard.ok)
|
|
1346
|
+
return guard;
|
|
1347
|
+
return ffiRestartIndex(guard.value, newPath);
|
|
1348
|
+
}
|
|
1349
|
+
refreshGitStatus() {
|
|
1350
|
+
const guard = this.ensureAlive();
|
|
1351
|
+
if (!guard.ok)
|
|
1352
|
+
return guard;
|
|
1353
|
+
return ffiRefreshGitStatus(guard.value);
|
|
1354
|
+
}
|
|
1355
|
+
trackQuery(query, selectedFilePath) {
|
|
1356
|
+
const guard = this.ensureAlive();
|
|
1357
|
+
if (!guard.ok)
|
|
1358
|
+
return guard;
|
|
1359
|
+
return ffiTrackQuery(guard.value, query, selectedFilePath);
|
|
1360
|
+
}
|
|
1361
|
+
getHistoricalQuery(offset) {
|
|
1362
|
+
const guard = this.ensureAlive();
|
|
1363
|
+
if (!guard.ok)
|
|
1364
|
+
return guard;
|
|
1365
|
+
return ffiGetHistoricalQuery(guard.value, offset);
|
|
1366
|
+
}
|
|
1367
|
+
ensureWatchTrampoline(handle) {
|
|
1368
|
+
if (this.watchJsCallback !== null)
|
|
1369
|
+
return { ok: true, value: undefined };
|
|
1370
|
+
const jsCallback = new JSCallback((watchId, batchPtr, _userData) => {
|
|
1371
|
+
const events = readWatchEventBatch(batchPtr);
|
|
1372
|
+
const handler = this.watchHandlers.get(Number(watchId));
|
|
1373
|
+
if (handler !== undefined && events.length > 0) {
|
|
1374
|
+
handler(events);
|
|
1375
|
+
}
|
|
1376
|
+
}, {
|
|
1377
|
+
args: [FFIType2.ptr, FFIType2.ptr, FFIType2.ptr],
|
|
1378
|
+
returns: FFIType2.void,
|
|
1379
|
+
threadsafe: true
|
|
1380
|
+
});
|
|
1381
|
+
const registered = ffiSetWatchCallback(handle, jsCallback);
|
|
1382
|
+
if (!registered.ok) {
|
|
1383
|
+
jsCallback.close();
|
|
1384
|
+
return registered;
|
|
1385
|
+
}
|
|
1386
|
+
this.watchJsCallback = jsCallback;
|
|
1387
|
+
return { ok: true, value: undefined };
|
|
1388
|
+
}
|
|
1389
|
+
watch(patternOrCallback, callbackOrOptions, maybeOptions) {
|
|
1390
|
+
const noPattern = typeof patternOrCallback === "function";
|
|
1391
|
+
const pattern = noPattern ? "" : patternOrCallback;
|
|
1392
|
+
const callback = noPattern ? patternOrCallback : callbackOrOptions;
|
|
1393
|
+
const options = noPattern ? callbackOrOptions : maybeOptions;
|
|
1394
|
+
if (typeof callback !== "function") {
|
|
1395
|
+
return err("watch callback must be a function");
|
|
1396
|
+
}
|
|
1397
|
+
const guard = this.ensureAlive();
|
|
1398
|
+
if (!guard.ok)
|
|
1399
|
+
return guard;
|
|
1400
|
+
const trampoline = this.ensureWatchTrampoline(guard.value);
|
|
1401
|
+
if (!trampoline.ok)
|
|
1402
|
+
return trampoline;
|
|
1403
|
+
const result = ffiWatch(guard.value, pattern, options?.ignore ?? []);
|
|
1404
|
+
if (!result.ok)
|
|
1405
|
+
return result;
|
|
1406
|
+
const watchId = result.value;
|
|
1407
|
+
this.watchHandlers.set(watchId, callback);
|
|
1408
|
+
return { ok: true, value: () => this.unwatchById(watchId) };
|
|
1409
|
+
}
|
|
1410
|
+
unwatchById(watchId) {
|
|
1411
|
+
if (!this.watchHandlers.delete(watchId))
|
|
1412
|
+
return;
|
|
1413
|
+
if (this.handle !== null) {
|
|
1414
|
+
ffiUnwatch(this.handle, watchId);
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
healthCheck(testPath) {
|
|
1418
|
+
return ffiHealthCheck(this.handle, testPath || "");
|
|
1419
|
+
}
|
|
1420
|
+
static isAvailable() {
|
|
1421
|
+
return isAvailable();
|
|
1422
|
+
}
|
|
1423
|
+
static ensureLoaded() {
|
|
1424
|
+
ensureLoaded();
|
|
1425
|
+
}
|
|
1426
|
+
static healthCheckStatic(testPath) {
|
|
1427
|
+
return ffiHealthCheck(null, testPath || "");
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
export {
|
|
1431
|
+
getTriple,
|
|
1432
|
+
getNpmPackageName,
|
|
1433
|
+
getLibFilename,
|
|
1434
|
+
getLibExtension,
|
|
1435
|
+
findBinary,
|
|
1436
|
+
binaryExists,
|
|
1437
|
+
FileFinder
|
|
1438
|
+
};
|
|
1439
|
+
|
|
1440
|
+
//# debugId=5525184652AF367A64756E2164756E21
|