@ff-labs/fff-bun 0.1.0-nightly.fcdf4a9 → 0.2.4-dev.233679d
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 +341 -60
- package/src/finder.ts +72 -53
- 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/README.md
CHANGED
|
@@ -16,20 +16,20 @@ High-performance fuzzy file finder for Bun, powered by Rust. Perfect for LLM age
|
|
|
16
16
|
bun add @ff-labs/bun
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
The correct native binary for your platform is installed automatically via platform-specific packages (e.g. `@ff-labs/fff-
|
|
19
|
+
The correct native binary for your platform is installed automatically via platform-specific packages (e.g. `@ff-labs/fff-bin-darwin-arm64`, `@ff-labs/fff-bin-linux-x64-gnu`). No GitHub downloads are needed.
|
|
20
20
|
|
|
21
21
|
### Supported Platforms
|
|
22
22
|
|
|
23
23
|
| Platform | Architecture | Package |
|
|
24
24
|
|----------|-------------|---------|
|
|
25
|
-
| macOS | ARM64 (Apple Silicon) | `@ff-labs/fff-
|
|
26
|
-
| macOS | x64 (Intel) | `@ff-labs/fff-
|
|
27
|
-
| Linux | x64 (glibc) | `@ff-labs/fff-
|
|
28
|
-
| Linux | ARM64 (glibc) | `@ff-labs/fff-
|
|
29
|
-
| Linux | x64 (musl) | `@ff-labs/fff-
|
|
30
|
-
| Linux | ARM64 (musl) | `@ff-labs/fff-
|
|
31
|
-
| Windows | x64 | `@ff-labs/fff-
|
|
32
|
-
| Windows | ARM64 | `@ff-labs/fff-
|
|
25
|
+
| macOS | ARM64 (Apple Silicon) | `@ff-labs/fff-bin-darwin-arm64` |
|
|
26
|
+
| macOS | x64 (Intel) | `@ff-labs/fff-bin-darwin-x64` |
|
|
27
|
+
| Linux | x64 (glibc) | `@ff-labs/fff-bin-linux-x64-gnu` |
|
|
28
|
+
| Linux | ARM64 (glibc) | `@ff-labs/fff-bin-linux-arm64-gnu` |
|
|
29
|
+
| Linux | x64 (musl) | `@ff-labs/fff-bin-linux-x64-musl` |
|
|
30
|
+
| Linux | ARM64 (musl) | `@ff-labs/fff-bin-linux-arm64-musl` |
|
|
31
|
+
| Windows | x64 | `@ff-labs/fff-bin-win32-x64` |
|
|
32
|
+
| Windows | ARM64 | `@ff-labs/fff-bin-win32-arm64` |
|
|
33
33
|
|
|
34
34
|
If the platform package isn't available, the postinstall script will attempt to download from GitHub releases as a fallback.
|
|
35
35
|
|
|
@@ -113,7 +113,7 @@ Track file access for frecency scoring.
|
|
|
113
113
|
FileFinder.trackAccess("/path/to/file.ts");
|
|
114
114
|
```
|
|
115
115
|
|
|
116
|
-
### `FileFinder.
|
|
116
|
+
### `FileFinder.grep(query, options?)`
|
|
117
117
|
|
|
118
118
|
Search file contents with SIMD-accelerated matching.
|
|
119
119
|
|
|
@@ -129,7 +129,7 @@ interface GrepOptions {
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
// Plain text search
|
|
132
|
-
const result = FileFinder.
|
|
132
|
+
const result = FileFinder.grep("TODO", { pageLimit: 20 });
|
|
133
133
|
if (result.ok) {
|
|
134
134
|
for (const match of result.value.items) {
|
|
135
135
|
console.log(`${match.relativePath}:${match.lineNumber}: ${match.lineContent}`);
|
|
@@ -137,22 +137,22 @@ if (result.ok) {
|
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
// Regex search
|
|
140
|
-
const regexResult = FileFinder.
|
|
140
|
+
const regexResult = FileFinder.grep("fn\\s+\\w+", { mode: "regex" });
|
|
141
141
|
|
|
142
142
|
// Fuzzy search
|
|
143
|
-
const fuzzyResult = FileFinder.
|
|
143
|
+
const fuzzyResult = FileFinder.grep("imprt recat", { mode: "fuzzy" });
|
|
144
144
|
|
|
145
145
|
// Pagination
|
|
146
|
-
const page1 = FileFinder.
|
|
146
|
+
const page1 = FileFinder.grep("error");
|
|
147
147
|
if (page1.ok && page1.value.nextCursor) {
|
|
148
|
-
const page2 = FileFinder.
|
|
148
|
+
const page2 = FileFinder.grep("error", {
|
|
149
149
|
cursor: page1.value.nextCursor,
|
|
150
150
|
});
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
// With file constraints
|
|
154
|
-
const tsOnly = FileFinder.
|
|
155
|
-
const srcOnly = FileFinder.
|
|
154
|
+
const tsOnly = FileFinder.grep("*.ts useState");
|
|
155
|
+
const srcOnly = FileFinder.grep("src/ handleClick");
|
|
156
156
|
```
|
|
157
157
|
|
|
158
158
|
### `FileFinder.trackQuery(query, selectedFile)`
|
|
@@ -178,7 +178,7 @@ if (health.ok) {
|
|
|
178
178
|
|
|
179
179
|
### Other Methods
|
|
180
180
|
|
|
181
|
-
- `FileFinder.
|
|
181
|
+
- `FileFinder.grep(query, options?)` - Search file contents
|
|
182
182
|
- `FileFinder.scanFiles()` - Trigger rescan
|
|
183
183
|
- `FileFinder.isScanning()` - Check scan status
|
|
184
184
|
- `FileFinder.getScanProgress()` - Get scan progress
|
package/examples/grep.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ff-labs/fff-bun",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.4-dev.233679d",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "High-performance fuzzy file finder for Bun - perfect for LLM agent tools",
|
|
6
6
|
"type": "module",
|
|
@@ -13,19 +13,14 @@
|
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"bin": {
|
|
16
|
-
"fff": "./scripts/cli.ts",
|
|
17
16
|
"fff-demo": "./examples/search.ts",
|
|
18
17
|
"fff-grep": "./examples/grep.ts"
|
|
19
18
|
},
|
|
20
19
|
"files": [
|
|
21
20
|
"src",
|
|
22
|
-
"bin",
|
|
23
|
-
"scripts",
|
|
24
21
|
"examples"
|
|
25
22
|
],
|
|
26
23
|
"scripts": {
|
|
27
|
-
"postinstall": "bun ./scripts/postinstall.ts",
|
|
28
|
-
"download": "bun ./scripts/cli.ts download",
|
|
29
24
|
"test": "bun test src/",
|
|
30
25
|
"typecheck": "tsc --noEmit",
|
|
31
26
|
"demo": "bun ./examples/search.ts"
|
|
@@ -67,14 +62,14 @@
|
|
|
67
62
|
},
|
|
68
63
|
"homepage": "https://github.com/dmtrKovalenko/fff.nvim#readme",
|
|
69
64
|
"optionalDependencies": {
|
|
70
|
-
"@ff-labs/fff-
|
|
71
|
-
"@ff-labs/fff-
|
|
72
|
-
"@ff-labs/fff-
|
|
73
|
-
"@ff-labs/fff-
|
|
74
|
-
"@ff-labs/fff-
|
|
75
|
-
"@ff-labs/fff-
|
|
76
|
-
"@ff-labs/fff-
|
|
77
|
-
"@ff-labs/fff-
|
|
65
|
+
"@ff-labs/fff-bin-darwin-arm64": "0.2.4-dev.233679d",
|
|
66
|
+
"@ff-labs/fff-bin-darwin-x64": "0.2.4-dev.233679d",
|
|
67
|
+
"@ff-labs/fff-bin-linux-x64-gnu": "0.2.4-dev.233679d",
|
|
68
|
+
"@ff-labs/fff-bin-linux-arm64-gnu": "0.2.4-dev.233679d",
|
|
69
|
+
"@ff-labs/fff-bin-linux-x64-musl": "0.2.4-dev.233679d",
|
|
70
|
+
"@ff-labs/fff-bin-linux-arm64-musl": "0.2.4-dev.233679d",
|
|
71
|
+
"@ff-labs/fff-bin-win32-x64": "0.2.4-dev.233679d",
|
|
72
|
+
"@ff-labs/fff-bin-win32-arm64": "0.2.4-dev.233679d"
|
|
78
73
|
},
|
|
79
74
|
"devDependencies": {
|
|
80
75
|
"@types/bun": "^1.3.8",
|
package/src/download.ts
CHANGED
|
@@ -1,25 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Binary resolution utilities for fff
|
|
3
3
|
*
|
|
4
|
-
* Resolves the native
|
|
5
|
-
* 1. Platform-specific npm package (e.g. @ff-labs/fff-
|
|
6
|
-
* 2. Local
|
|
7
|
-
* 3. Local dev build (target/release or target/debug)
|
|
8
|
-
* 4. GitHub releases (fallback, requires network)
|
|
4
|
+
* Resolves the native library from:
|
|
5
|
+
* 1. Platform-specific npm package (e.g. @ff-labs/fff-bin-darwin-arm64)
|
|
6
|
+
* 2. Local dev build (target/release or target/debug)
|
|
9
7
|
*/
|
|
10
8
|
|
|
11
|
-
import {
|
|
9
|
+
import { existsSync } from "node:fs";
|
|
12
10
|
import { createRequire } from "node:module";
|
|
13
11
|
import { dirname, join } from "node:path";
|
|
14
12
|
import { fileURLToPath } from "node:url";
|
|
15
|
-
import {
|
|
16
|
-
getLibExtension,
|
|
17
|
-
getLibFilename,
|
|
18
|
-
getNpmPackageName,
|
|
19
|
-
getTriple,
|
|
20
|
-
} from "./platform";
|
|
21
|
-
|
|
22
|
-
const GITHUB_REPO = "dmtrKovalenko/fff.nvim";
|
|
13
|
+
import { getLibFilename, getNpmPackageName } from "./platform";
|
|
23
14
|
|
|
24
15
|
/**
|
|
25
16
|
* Get the current file's directory
|
|
@@ -47,21 +38,6 @@ function getPackageDir(): string {
|
|
|
47
38
|
return dirname(currentDir);
|
|
48
39
|
}
|
|
49
40
|
|
|
50
|
-
/**
|
|
51
|
-
* Get the directory where binaries are stored (legacy/fallback)
|
|
52
|
-
*/
|
|
53
|
-
export function getBinDir(): string {
|
|
54
|
-
return join(getPackageDir(), "bin");
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Get the full path to the native library in bin/ (legacy/fallback)
|
|
59
|
-
*/
|
|
60
|
-
export function getBinaryPath(): string {
|
|
61
|
-
const binDir = getBinDir();
|
|
62
|
-
return join(binDir, getLibFilename());
|
|
63
|
-
}
|
|
64
|
-
|
|
65
41
|
/**
|
|
66
42
|
* Check if the binary exists in any known location
|
|
67
43
|
*/
|
|
@@ -72,8 +48,8 @@ export function binaryExists(): boolean {
|
|
|
72
48
|
/**
|
|
73
49
|
* Try to resolve the binary from the platform-specific npm package.
|
|
74
50
|
*
|
|
75
|
-
* When users install @ff-labs/bun, npm/bun automatically installs the matching
|
|
76
|
-
* optionalDependency (e.g. @ff-labs/fff-
|
|
51
|
+
* When users install @ff-labs/fff-bun, npm/bun automatically installs the matching
|
|
52
|
+
* optionalDependency (e.g. @ff-labs/fff-bin-darwin-arm64). We resolve the binary
|
|
77
53
|
* path by requiring that package's package.json and looking for the binary
|
|
78
54
|
* in the same directory.
|
|
79
55
|
*/
|
|
@@ -101,7 +77,7 @@ function resolveFromNpmPackage(): string | null {
|
|
|
101
77
|
/**
|
|
102
78
|
* Get the development binary path (for local development)
|
|
103
79
|
*/
|
|
104
|
-
|
|
80
|
+
function getDevBinaryPath(): string | null {
|
|
105
81
|
const packageDir = getPackageDir();
|
|
106
82
|
const workspaceRoot = join(packageDir, "..", "..");
|
|
107
83
|
|
|
@@ -125,11 +101,20 @@ function isDevWorkspace(): boolean {
|
|
|
125
101
|
return existsSync(join(workspaceRoot, "Cargo.toml"));
|
|
126
102
|
}
|
|
127
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Find the native library binary.
|
|
106
|
+
*
|
|
107
|
+
* Resolution order:
|
|
108
|
+
* - Dev workspace: local dev build first, then npm package
|
|
109
|
+
* - Production: npm package first, then dev build
|
|
110
|
+
*
|
|
111
|
+
* @returns Absolute path to the library, or null if not found
|
|
112
|
+
*/
|
|
128
113
|
export function findBinary(): string | null {
|
|
129
114
|
if (isDevWorkspace()) {
|
|
130
115
|
// 1. Local bin/ directory (populated by `make prepare-bun`)
|
|
131
|
-
const
|
|
132
|
-
if (existsSync(
|
|
116
|
+
const binPath = join(getPackageDir(), "bin", getLibFilename());
|
|
117
|
+
if (existsSync(binPath)) return binPath;
|
|
133
118
|
|
|
134
119
|
// 2. Local dev build (target/release or target/debug)
|
|
135
120
|
const devPath = getDevBinaryPath();
|
|
@@ -143,117 +128,9 @@ export function findBinary(): string | null {
|
|
|
143
128
|
}
|
|
144
129
|
|
|
145
130
|
// Production: npm package first
|
|
146
|
-
// 1. Try platform-specific npm package first
|
|
147
131
|
const npmPath = resolveFromNpmPackage();
|
|
148
132
|
if (npmPath) return npmPath;
|
|
149
133
|
|
|
150
|
-
//
|
|
151
|
-
const installedPath = getBinaryPath();
|
|
152
|
-
if (existsSync(installedPath)) return installedPath;
|
|
153
|
-
|
|
154
|
-
// 3. Try local dev build
|
|
134
|
+
// Fallback: local dev build (e.g. user built from source)
|
|
155
135
|
return getDevBinaryPath();
|
|
156
136
|
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Download the binary from GitHub releases as a fallback.
|
|
160
|
-
* This is only used when the platform npm package is not available.
|
|
161
|
-
*
|
|
162
|
-
* @param tag - The release tag to download (e.g. commit hash), or "latest"
|
|
163
|
-
*/
|
|
164
|
-
export async function downloadBinary(tag?: string): Promise<string> {
|
|
165
|
-
const resolvedTag = tag || "latest";
|
|
166
|
-
const triple = getTriple();
|
|
167
|
-
const ext = getLibExtension();
|
|
168
|
-
|
|
169
|
-
// Resolve "latest" tag via GitHub API
|
|
170
|
-
let releaseTag = resolvedTag;
|
|
171
|
-
if (releaseTag === "latest") {
|
|
172
|
-
console.log("fff: Fetching latest release tag from GitHub...");
|
|
173
|
-
releaseTag = await fetchLatestReleaseTag();
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const binaryName = `c-lib-${triple}.${ext}`;
|
|
177
|
-
const baseUrl = `https://github.com/${GITHUB_REPO}/releases/download/${releaseTag}`;
|
|
178
|
-
const binaryUrl = `${baseUrl}/${binaryName}`;
|
|
179
|
-
|
|
180
|
-
console.log(`fff: Downloading native library for ${triple}...`);
|
|
181
|
-
console.log(`fff: Release: ${releaseTag}`);
|
|
182
|
-
|
|
183
|
-
const binaryResponse = await fetch(binaryUrl);
|
|
184
|
-
if (!binaryResponse.ok) {
|
|
185
|
-
throw new Error(
|
|
186
|
-
`Failed to download binary: ${binaryResponse.status} ${binaryResponse.statusText}\nURL: ${binaryUrl}`,
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
const binaryBuffer = Buffer.from(await binaryResponse.arrayBuffer());
|
|
191
|
-
|
|
192
|
-
const binDir = getBinDir();
|
|
193
|
-
if (!existsSync(binDir)) {
|
|
194
|
-
mkdirSync(binDir, { recursive: true });
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const binaryPath = getBinaryPath();
|
|
198
|
-
writeFileSync(binaryPath, binaryBuffer);
|
|
199
|
-
|
|
200
|
-
// Make executable on Unix
|
|
201
|
-
if (process.platform !== "win32") {
|
|
202
|
-
chmodSync(binaryPath, 0o755);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
console.log(`fff: Binary downloaded to ${binaryPath}`);
|
|
206
|
-
return releaseTag;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Fetch the latest release tag from GitHub
|
|
211
|
-
*/
|
|
212
|
-
async function fetchLatestReleaseTag(): Promise<string> {
|
|
213
|
-
const url = `https://api.github.com/repos/${GITHUB_REPO}/releases/latest`;
|
|
214
|
-
|
|
215
|
-
const response = await fetch(url, {
|
|
216
|
-
headers: {
|
|
217
|
-
Accept: "application/vnd.github.v3+json",
|
|
218
|
-
"User-Agent": "fff-bun-client",
|
|
219
|
-
},
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
if (!response.ok) {
|
|
223
|
-
const allReleasesUrl = `https://api.github.com/repos/${GITHUB_REPO}/releases`;
|
|
224
|
-
const allResponse = await fetch(allReleasesUrl, {
|
|
225
|
-
headers: {
|
|
226
|
-
Accept: "application/vnd.github.v3+json",
|
|
227
|
-
"User-Agent": "fff-bun-client",
|
|
228
|
-
},
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
if (!allResponse.ok) {
|
|
232
|
-
throw new Error(`Failed to fetch releases: ${allResponse.status}`);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
const releases = (await allResponse.json()) as Array<{ tag_name: string }>;
|
|
236
|
-
if (releases.length === 0) {
|
|
237
|
-
throw new Error("No releases found");
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
return releases[0].tag_name;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
const release = (await response.json()) as { tag_name: string };
|
|
244
|
-
return release.tag_name;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Ensure the binary exists, downloading from GitHub if necessary.
|
|
249
|
-
*/
|
|
250
|
-
export async function ensureBinary(): Promise<string> {
|
|
251
|
-
const existingPath = findBinary();
|
|
252
|
-
if (existingPath) {
|
|
253
|
-
return existingPath;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// Fallback: download from GitHub
|
|
257
|
-
await downloadBinary();
|
|
258
|
-
return getBinaryPath();
|
|
259
|
-
}
|