@ff-labs/fff-bun 0.1.0-nightly.00750c2
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 +283 -0
- package/examples/grep.ts +285 -0
- package/examples/search.ts +224 -0
- package/package.json +86 -0
- package/scripts/cli.ts +114 -0
- package/scripts/postinstall.ts +51 -0
- package/src/download.ts +252 -0
- package/src/ffi.ts +450 -0
- package/src/finder.ts +413 -0
- package/src/git-lifecycle.test.ts +291 -0
- package/src/index.test.ts +357 -0
- package/src/index.ts +83 -0
- package/src/platform.ts +121 -0
- package/src/types.ts +404 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Interactive file finder demo
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* bunx fff-demo [directory]
|
|
7
|
+
* bun examples/search.ts [directory]
|
|
8
|
+
*
|
|
9
|
+
* Indexes the specified directory (or cwd) and provides an interactive
|
|
10
|
+
* search prompt with detailed metadata about results.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { FileFinder } from "../src/index";
|
|
14
|
+
import * as readline from "readline";
|
|
15
|
+
|
|
16
|
+
const RESET = "\x1b[0m";
|
|
17
|
+
const BOLD = "\x1b[1m";
|
|
18
|
+
const DIM = "\x1b[2m";
|
|
19
|
+
const GREEN = "\x1b[32m";
|
|
20
|
+
const YELLOW = "\x1b[33m";
|
|
21
|
+
const BLUE = "\x1b[34m";
|
|
22
|
+
const MAGENTA = "\x1b[35m";
|
|
23
|
+
const CYAN = "\x1b[36m";
|
|
24
|
+
const RED = "\x1b[31m";
|
|
25
|
+
|
|
26
|
+
function formatGitStatus(status: string): string {
|
|
27
|
+
switch (status) {
|
|
28
|
+
case "modified":
|
|
29
|
+
return `${YELLOW}M${RESET}`;
|
|
30
|
+
case "untracked":
|
|
31
|
+
return `${GREEN}?${RESET}`;
|
|
32
|
+
case "added":
|
|
33
|
+
return `${GREEN}A${RESET}`;
|
|
34
|
+
case "deleted":
|
|
35
|
+
return `${RED}D${RESET}`;
|
|
36
|
+
case "renamed":
|
|
37
|
+
return `${BLUE}R${RESET}`;
|
|
38
|
+
case "clean":
|
|
39
|
+
case "current":
|
|
40
|
+
return `${DIM} ${RESET}`;
|
|
41
|
+
default:
|
|
42
|
+
return `${DIM}${status.charAt(0)}${RESET}`;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function formatScore(score: number): string {
|
|
47
|
+
if (score >= 100) return `${GREEN}${score}${RESET}`;
|
|
48
|
+
if (score >= 50) return `${YELLOW}${score}${RESET}`;
|
|
49
|
+
if (score > 0) return `${DIM}${score}${RESET}`;
|
|
50
|
+
return `${DIM}0${RESET}`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function formatSize(bytes: number): string {
|
|
54
|
+
if (bytes < 1024) return `${bytes}B`;
|
|
55
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}K`;
|
|
56
|
+
return `${(bytes / 1024 / 1024).toFixed(1)}M`;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function formatTime(unixSeconds: number): string {
|
|
60
|
+
if (unixSeconds === 0) return "unknown";
|
|
61
|
+
const date = new Date(unixSeconds * 1000);
|
|
62
|
+
const now = new Date();
|
|
63
|
+
const diffMs = now.getTime() - date.getTime();
|
|
64
|
+
const diffMins = Math.floor(diffMs / 60000);
|
|
65
|
+
const diffHours = Math.floor(diffMs / 3600000);
|
|
66
|
+
const diffDays = Math.floor(diffMs / 86400000);
|
|
67
|
+
|
|
68
|
+
if (diffMins < 1) return "just now";
|
|
69
|
+
if (diffMins < 60) return `${diffMins}m ago`;
|
|
70
|
+
if (diffHours < 24) return `${diffHours}h ago`;
|
|
71
|
+
if (diffDays < 7) return `${diffDays}d ago`;
|
|
72
|
+
return date.toLocaleDateString();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function main() {
|
|
76
|
+
const targetDir = process.argv[2] || process.cwd();
|
|
77
|
+
|
|
78
|
+
console.log(`${BOLD}${CYAN}fff - Fast File Finder Demo${RESET}\n`);
|
|
79
|
+
|
|
80
|
+
// Check library availability
|
|
81
|
+
if (!FileFinder.isAvailable()) {
|
|
82
|
+
console.error(`${RED}Error: Native library not found.${RESET}`);
|
|
83
|
+
console.error("Build with: cargo build --release -p fff-c");
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Create instance
|
|
88
|
+
console.log(`${DIM}Initializing index for: ${targetDir}${RESET}`);
|
|
89
|
+
const createResult = FileFinder.create({
|
|
90
|
+
basePath: targetDir,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
if (!createResult.ok) {
|
|
94
|
+
console.error(`${RED}Init failed: ${createResult.error}${RESET}`);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const finder = createResult.value;
|
|
99
|
+
|
|
100
|
+
// Wait for scan with progress
|
|
101
|
+
process.stdout.write(`${DIM}Scanning files...${RESET}`);
|
|
102
|
+
const startTime = Date.now();
|
|
103
|
+
let lastCount = 0;
|
|
104
|
+
|
|
105
|
+
while (finder.isScanning()) {
|
|
106
|
+
const progress = finder.getScanProgress();
|
|
107
|
+
if (progress.ok && progress.value.scannedFilesCount !== lastCount) {
|
|
108
|
+
lastCount = progress.value.scannedFilesCount;
|
|
109
|
+
process.stdout.write(`\r${DIM}Scanning files... ${lastCount}${RESET} `);
|
|
110
|
+
}
|
|
111
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const scanTime = Date.now() - startTime;
|
|
115
|
+
const finalProgress = finder.getScanProgress();
|
|
116
|
+
const totalFiles = finalProgress.ok ? finalProgress.value.scannedFilesCount : 0;
|
|
117
|
+
|
|
118
|
+
console.log(`\r${GREEN}✓${RESET} Indexed ${BOLD}${totalFiles}${RESET} files in ${scanTime}ms\n`);
|
|
119
|
+
|
|
120
|
+
// Show index info
|
|
121
|
+
const health = finder.healthCheck();
|
|
122
|
+
if (health.ok) {
|
|
123
|
+
console.log(`${DIM}Version:${RESET} ${health.value.version}`);
|
|
124
|
+
console.log(`${DIM}Base path:${RESET} ${health.value.filePicker.basePath}`);
|
|
125
|
+
if (health.value.git.repositoryFound) {
|
|
126
|
+
console.log(`${DIM}Git root:${RESET} ${health.value.git.workdir}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Interactive search loop
|
|
131
|
+
const rl = readline.createInterface({
|
|
132
|
+
input: process.stdin,
|
|
133
|
+
output: process.stdout,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
console.log(`${BOLD}Enter a search query${RESET} (or 'q' to quit, empty for all files):\n`);
|
|
137
|
+
|
|
138
|
+
const prompt = () => {
|
|
139
|
+
rl.question(`${CYAN}search>${RESET} `, (query) => {
|
|
140
|
+
if (query.toLowerCase() === "q" || query.toLowerCase() === "quit") {
|
|
141
|
+
console.log(`\n${DIM}Goodbye!${RESET}`);
|
|
142
|
+
finder.destroy();
|
|
143
|
+
rl.close();
|
|
144
|
+
process.exit(0);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const searchStart = Date.now();
|
|
148
|
+
const result = finder.search(query, { pageSize: 15 });
|
|
149
|
+
const searchTime = Date.now() - searchStart;
|
|
150
|
+
|
|
151
|
+
if (!result.ok) {
|
|
152
|
+
console.log(`${RED}Search error: ${result.error}${RESET}\n`);
|
|
153
|
+
prompt();
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const { items, scores, totalMatched, totalFiles } = result.value;
|
|
158
|
+
|
|
159
|
+
console.log();
|
|
160
|
+
console.log(
|
|
161
|
+
`${DIM}Found ${BOLD}${totalMatched}${RESET}${DIM} matches in ${totalFiles} files (${searchTime}ms)${RESET}`
|
|
162
|
+
);
|
|
163
|
+
console.log();
|
|
164
|
+
|
|
165
|
+
if (items.length === 0) {
|
|
166
|
+
console.log(`${DIM}No matches found.${RESET}\n`);
|
|
167
|
+
prompt();
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Header
|
|
172
|
+
console.log(
|
|
173
|
+
`${DIM} Git │ Score │ Size │ Modified │ Path${RESET}`
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
// Results
|
|
177
|
+
for (let i = 0; i < items.length; i++) {
|
|
178
|
+
const item = items[i];
|
|
179
|
+
const score = scores[i];
|
|
180
|
+
|
|
181
|
+
const gitStatus = formatGitStatus(item.gitStatus);
|
|
182
|
+
const totalScore = formatScore(score.total);
|
|
183
|
+
const size = formatSize(item.size).padStart(6);
|
|
184
|
+
const modified = formatTime(item.modified).padEnd(10);
|
|
185
|
+
const path = item.relativePath;
|
|
186
|
+
|
|
187
|
+
console.log(
|
|
188
|
+
` ${gitStatus} │ ${totalScore.padStart(5)} │ ${size} │ ${modified} │ ${path}`
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
// Show score breakdown for top results
|
|
192
|
+
if (i < 3 && score.total > 0) {
|
|
193
|
+
const breakdown: string[] = [];
|
|
194
|
+
if (score.baseScore > 0) breakdown.push(`base:${score.baseScore}`);
|
|
195
|
+
if (score.filenameBonus > 0) breakdown.push(`filename:+${score.filenameBonus}`);
|
|
196
|
+
if (score.frecencyBoost > 0) breakdown.push(`frecency:+${score.frecencyBoost}`);
|
|
197
|
+
if (score.comboMatchBoost > 0) breakdown.push(`combo:+${score.comboMatchBoost}`);
|
|
198
|
+
if (score.distancePenalty < 0) breakdown.push(`distance:${score.distancePenalty}`);
|
|
199
|
+
if (score.exactMatch) breakdown.push(`${GREEN}exact${RESET}`);
|
|
200
|
+
|
|
201
|
+
if (breakdown.length > 0) {
|
|
202
|
+
console.log(`${DIM} │ │ │ │ └─ ${breakdown.join(", ")}${RESET}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (totalMatched > items.length) {
|
|
208
|
+
console.log(
|
|
209
|
+
`${DIM} │ │ │ │ ... and ${totalMatched - items.length} more${RESET}`
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
console.log();
|
|
214
|
+
prompt();
|
|
215
|
+
});
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
prompt();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
main().catch((err) => {
|
|
222
|
+
console.error(`${RED}Fatal error: ${err.message}${RESET}`);
|
|
223
|
+
process.exit(1);
|
|
224
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ff-labs/fff-bun",
|
|
3
|
+
"version": "0.1.0-nightly.00750c2",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "High-performance fuzzy file finder for Bun - perfect for LLM agent tools",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "src/index.ts",
|
|
8
|
+
"types": "src/index.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./src/index.ts",
|
|
12
|
+
"types": "./src/index.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"bin": {
|
|
16
|
+
"fff": "./scripts/cli.ts",
|
|
17
|
+
"fff-demo": "./examples/search.ts",
|
|
18
|
+
"fff-grep": "./examples/grep.ts"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"src",
|
|
22
|
+
"bin",
|
|
23
|
+
"scripts",
|
|
24
|
+
"examples"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"postinstall": "bun ./scripts/postinstall.ts",
|
|
28
|
+
"download": "bun ./scripts/cli.ts download",
|
|
29
|
+
"test": "bun test src/",
|
|
30
|
+
"typecheck": "tsc --noEmit",
|
|
31
|
+
"demo": "bun ./examples/search.ts"
|
|
32
|
+
},
|
|
33
|
+
"engines": {
|
|
34
|
+
"bun": ">=1.0.0"
|
|
35
|
+
},
|
|
36
|
+
"os": [
|
|
37
|
+
"darwin",
|
|
38
|
+
"linux",
|
|
39
|
+
"win32"
|
|
40
|
+
],
|
|
41
|
+
"cpu": [
|
|
42
|
+
"x64",
|
|
43
|
+
"arm64"
|
|
44
|
+
],
|
|
45
|
+
"repository": {
|
|
46
|
+
"type": "git",
|
|
47
|
+
"url": "git+https://github.com/dmtrKovalenko/fff.nvim.git",
|
|
48
|
+
"directory": "packages/fff"
|
|
49
|
+
},
|
|
50
|
+
"keywords": [
|
|
51
|
+
"file-finder",
|
|
52
|
+
"fuzzy-search",
|
|
53
|
+
"bun",
|
|
54
|
+
"ffi",
|
|
55
|
+
"llm-tools",
|
|
56
|
+
"agent-tools",
|
|
57
|
+
"fast",
|
|
58
|
+
"rust"
|
|
59
|
+
],
|
|
60
|
+
"author": "Dmitry Kovalenko",
|
|
61
|
+
"license": "MIT",
|
|
62
|
+
"publishConfig": {
|
|
63
|
+
"access": "public"
|
|
64
|
+
},
|
|
65
|
+
"bugs": {
|
|
66
|
+
"url": "https://github.com/dmtrKovalenko/fff.nvim/issues"
|
|
67
|
+
},
|
|
68
|
+
"homepage": "https://github.com/dmtrKovalenko/fff.nvim#readme",
|
|
69
|
+
"optionalDependencies": {
|
|
70
|
+
"@ff-labs/fff-bun-darwin-arm64": "0.1.0-nightly.00750c2",
|
|
71
|
+
"@ff-labs/fff-bun-darwin-x64": "0.1.0-nightly.00750c2",
|
|
72
|
+
"@ff-labs/fff-bun-linux-x64-gnu": "0.1.0-nightly.00750c2",
|
|
73
|
+
"@ff-labs/fff-bun-linux-arm64-gnu": "0.1.0-nightly.00750c2",
|
|
74
|
+
"@ff-labs/fff-bun-linux-x64-musl": "0.1.0-nightly.00750c2",
|
|
75
|
+
"@ff-labs/fff-bun-linux-arm64-musl": "0.1.0-nightly.00750c2",
|
|
76
|
+
"@ff-labs/fff-bun-win32-x64": "0.1.0-nightly.00750c2",
|
|
77
|
+
"@ff-labs/fff-bun-win32-arm64": "0.1.0-nightly.00750c2"
|
|
78
|
+
},
|
|
79
|
+
"devDependencies": {
|
|
80
|
+
"@types/bun": "^1.3.8",
|
|
81
|
+
"typescript": "^5.0.0"
|
|
82
|
+
},
|
|
83
|
+
"peerDependencies": {
|
|
84
|
+
"bun": ">=1.0.0"
|
|
85
|
+
}
|
|
86
|
+
}
|
package/scripts/cli.ts
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
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 {
|
|
11
|
+
downloadBinary,
|
|
12
|
+
getBinaryPath,
|
|
13
|
+
findBinary,
|
|
14
|
+
} from "../src/download";
|
|
15
|
+
import { getTriple, getLibExtension, getLibFilename, getNpmPackageName } from "../src/platform";
|
|
16
|
+
import { dirname, join } from "node:path";
|
|
17
|
+
import { fileURLToPath } from "node:url";
|
|
18
|
+
|
|
19
|
+
const args = process.argv.slice(2);
|
|
20
|
+
const command = args[0];
|
|
21
|
+
|
|
22
|
+
interface PackageJson {
|
|
23
|
+
version: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function getPackageInfo(): Promise<PackageJson> {
|
|
27
|
+
const currentDir = dirname(fileURLToPath(import.meta.url));
|
|
28
|
+
const packageJsonPath = join(currentDir, "..", "package.json");
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
return await Bun.file(packageJsonPath).json();
|
|
32
|
+
} catch {
|
|
33
|
+
return { version: "unknown" };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function main() {
|
|
38
|
+
switch (command) {
|
|
39
|
+
case "download": {
|
|
40
|
+
const tag = args[1];
|
|
41
|
+
console.log("fff: Downloading native library from GitHub...");
|
|
42
|
+
try {
|
|
43
|
+
const resolvedTag = await downloadBinary(tag);
|
|
44
|
+
console.log(`fff: Download complete! (${resolvedTag})`);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
console.error("fff: Download failed:", error);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
case "info": {
|
|
53
|
+
const pkg = await getPackageInfo();
|
|
54
|
+
let npmPackage: string;
|
|
55
|
+
try {
|
|
56
|
+
npmPackage = getNpmPackageName();
|
|
57
|
+
} catch {
|
|
58
|
+
npmPackage = "unsupported";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
console.log("fff - Fast File Finder");
|
|
62
|
+
console.log(`Package version: ${pkg.version}`);
|
|
63
|
+
console.log("");
|
|
64
|
+
console.log("Platform Information:");
|
|
65
|
+
console.log(` Triple: ${getTriple()}`);
|
|
66
|
+
console.log(` Extension: ${getLibExtension()}`);
|
|
67
|
+
console.log(` Library name: ${getLibFilename()}`);
|
|
68
|
+
console.log(` npm package: ${npmPackage}`);
|
|
69
|
+
console.log("");
|
|
70
|
+
console.log("Binary Status:");
|
|
71
|
+
const existing = findBinary();
|
|
72
|
+
if (existing) {
|
|
73
|
+
console.log(` Found: ${existing}`);
|
|
74
|
+
} else {
|
|
75
|
+
console.log(` Not found`);
|
|
76
|
+
console.log(` Expected path: ${getBinaryPath()}`);
|
|
77
|
+
console.log(` Try: bun add ${npmPackage}`);
|
|
78
|
+
}
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
case "version":
|
|
83
|
+
case "--version":
|
|
84
|
+
case "-v": {
|
|
85
|
+
const pkg = await getPackageInfo();
|
|
86
|
+
console.log(pkg.version);
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
case "help":
|
|
91
|
+
case "--help":
|
|
92
|
+
case "-h":
|
|
93
|
+
default: {
|
|
94
|
+
const pkg = await getPackageInfo();
|
|
95
|
+
console.log(`fff - Fast File Finder CLI v${pkg.version}`);
|
|
96
|
+
console.log("");
|
|
97
|
+
console.log("Usage:");
|
|
98
|
+
console.log(" bunx fff download [tag] Download native binary from GitHub (fallback)");
|
|
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("Note: Binaries are normally provided via platform-specific npm packages.");
|
|
108
|
+
console.log("The download command is a fallback for when those aren't available.");
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
main();
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Postinstall script - ensures the native binary is available
|
|
4
|
+
*
|
|
5
|
+
* Resolution order:
|
|
6
|
+
* 1. Platform-specific npm package (installed via optionalDependencies)
|
|
7
|
+
* 2. Local dev build (target/release or target/debug)
|
|
8
|
+
* 3. Fallback: download from GitHub releases
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { findBinary, downloadBinary } from "../src/download";
|
|
12
|
+
import { getNpmPackageName } from "../src/platform";
|
|
13
|
+
|
|
14
|
+
async function main() {
|
|
15
|
+
// Check if binary is already available (npm package or dev build)
|
|
16
|
+
const existing = findBinary();
|
|
17
|
+
if (existing) {
|
|
18
|
+
console.log(`fff: Native library found at ${existing}`);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Binary not found via npm package - try downloading from GitHub as fallback
|
|
23
|
+
let packageName: string;
|
|
24
|
+
try {
|
|
25
|
+
packageName = getNpmPackageName();
|
|
26
|
+
} catch {
|
|
27
|
+
packageName = "unknown";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
console.log(
|
|
31
|
+
`fff: Platform package ${packageName} not found, falling back to GitHub download...`
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
const tag = await downloadBinary();
|
|
36
|
+
console.log(`fff: Native library installed successfully! (${tag})`);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
console.error("fff: Failed to download native library:", error);
|
|
39
|
+
console.error("");
|
|
40
|
+
console.error("fff: You can build from source instead:");
|
|
41
|
+
console.error(" cargo build --release -p fff-c");
|
|
42
|
+
console.error("");
|
|
43
|
+
console.error(
|
|
44
|
+
"fff: Or run `bunx fff download` after fixing network issues."
|
|
45
|
+
);
|
|
46
|
+
// Don't exit with error - allow install to complete
|
|
47
|
+
// The error will surface when the user tries to use the library
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
main();
|