@nghyane/arcane-natives 0.1.0
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 +61 -0
- package/native/arcane_natives.darwin-arm64.node +0 -0
- package/native/pi_natives.darwin-arm64.node +0 -0
- package/package.json +163 -0
- package/src/bindings.ts +23 -0
- package/src/clipboard/index.ts +92 -0
- package/src/clipboard/types.ts +27 -0
- package/src/embedded-addon.ts +15 -0
- package/src/glob/index.ts +43 -0
- package/src/glob/types.ts +69 -0
- package/src/grep/index.ts +72 -0
- package/src/grep/types.ts +185 -0
- package/src/highlight/index.ts +9 -0
- package/src/highlight/types.ts +56 -0
- package/src/html/index.ts +19 -0
- package/src/html/types.ts +24 -0
- package/src/image/index.ts +13 -0
- package/src/image/types.ts +65 -0
- package/src/index.ts +125 -0
- package/src/keys/index.ts +9 -0
- package/src/keys/types.ts +75 -0
- package/src/native.ts +278 -0
- package/src/ps/index.ts +10 -0
- package/src/ps/types.ts +24 -0
- package/src/pty/index.ts +10 -0
- package/src/pty/types.ts +57 -0
- package/src/shell/index.ts +26 -0
- package/src/shell/types.ts +100 -0
- package/src/text/index.ts +44 -0
- package/src/text/types.ts +84 -0
- package/src/work/index.ts +11 -0
- package/src/work/types.ts +31 -0
package/README.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# @nghyane/arcane-natives
|
|
2
|
+
|
|
3
|
+
Native Rust functionality via N-API.
|
|
4
|
+
|
|
5
|
+
## What's Inside
|
|
6
|
+
|
|
7
|
+
- **Grep**: Regex-based search powered by ripgrep's engine with native file walking and matching
|
|
8
|
+
- **Find**: Glob-based file/directory discovery with gitignore support (pure TypeScript via `globPaths`)
|
|
9
|
+
- **Image**: Image processing via photon-rs (resize, format conversion) exposed through N-API
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { grep, find, PhotonImage, SamplingFilter, ImageFormat } from "@nghyane/arcane-natives";
|
|
15
|
+
|
|
16
|
+
// Grep for a pattern
|
|
17
|
+
const results = await grep({
|
|
18
|
+
pattern: "TODO",
|
|
19
|
+
path: "/path/to/project",
|
|
20
|
+
glob: "*.ts",
|
|
21
|
+
context: 2,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Find files
|
|
25
|
+
const files = await find({
|
|
26
|
+
pattern: "*.rs",
|
|
27
|
+
path: "/path/to/project",
|
|
28
|
+
fileType: "file",
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Image processing
|
|
32
|
+
const image = await PhotonImage.parse(bytes);
|
|
33
|
+
const resized = await image.resize(800, 600, SamplingFilter.Lanczos3);
|
|
34
|
+
const pngBytes = await resized.encode(ImageFormat.PNG, 100);
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Building
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Build native addon from workspace root (requires Rust)
|
|
41
|
+
bun run build:native
|
|
42
|
+
|
|
43
|
+
# Type check
|
|
44
|
+
bun run check
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Architecture
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
crates/arcane-natives/ # Rust source (workspace member)
|
|
51
|
+
src/lib.rs # N-API exports
|
|
52
|
+
src/image.rs # Image processing (photon-rs)
|
|
53
|
+
Cargo.toml # Rust dependencies
|
|
54
|
+
native/ # Native addon binaries
|
|
55
|
+
arcane_natives.<platform>-<arch>-modern.node # x64 modern ISA (AVX2)
|
|
56
|
+
arcane_natives.<platform>-<arch>-baseline.node # x64 baseline ISA
|
|
57
|
+
arcane_natives.<platform>-<arch>.node # non-x64 build artifact
|
|
58
|
+
src/ # TypeScript wrappers
|
|
59
|
+
native.ts # Native addon loader
|
|
60
|
+
index.ts # Public API
|
|
61
|
+
```
|
|
Binary file
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "module",
|
|
3
|
+
"name": "@nghyane/arcane-natives",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"description": "Native Rust bindings for grep, clipboard, image processing, syntax highlighting, PTY, and shell operations via N-API",
|
|
6
|
+
"homepage": "https://github.com/nghyane/arcane",
|
|
7
|
+
"author": "Can Bölük",
|
|
8
|
+
"license": "GPL-3.0-or-later",
|
|
9
|
+
"publishConfig": {
|
|
10
|
+
"access": "public"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/nghyane/arcane.git",
|
|
15
|
+
"directory": "packages/natives"
|
|
16
|
+
},
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/nghyane/arcane/issues"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"napi",
|
|
22
|
+
"rust",
|
|
23
|
+
"native",
|
|
24
|
+
"grep",
|
|
25
|
+
"text-processing",
|
|
26
|
+
"clipboard",
|
|
27
|
+
"image",
|
|
28
|
+
"pty",
|
|
29
|
+
"shell",
|
|
30
|
+
"syntax-highlighting"
|
|
31
|
+
],
|
|
32
|
+
"main": "./src/index.ts",
|
|
33
|
+
"types": "./src/index.ts",
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build:native": "bun scripts/build-native.ts",
|
|
36
|
+
"dev:native": "bun scripts/build-native.ts --dev",
|
|
37
|
+
"embed:native": "bun scripts/embed-native.ts",
|
|
38
|
+
"check": "biome check . && tsgo -p tsconfig.json",
|
|
39
|
+
"fix": "biome check --write --unsafe .",
|
|
40
|
+
"test": "bun run build:native && bun test",
|
|
41
|
+
"bench": "bun bench/grep.ts"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@nghyane/arcane-utils": "workspace:*"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/bun": "^1.3.9"
|
|
48
|
+
},
|
|
49
|
+
"engines": {
|
|
50
|
+
"bun": ">=1.3.7"
|
|
51
|
+
},
|
|
52
|
+
"files": [
|
|
53
|
+
"src",
|
|
54
|
+
"native",
|
|
55
|
+
"README.md"
|
|
56
|
+
],
|
|
57
|
+
"exports": {
|
|
58
|
+
".": {
|
|
59
|
+
"types": "./src/index.ts",
|
|
60
|
+
"import": "./src/index.ts"
|
|
61
|
+
},
|
|
62
|
+
"./*": {
|
|
63
|
+
"types": "./src/*.ts",
|
|
64
|
+
"import": "./src/*.ts"
|
|
65
|
+
},
|
|
66
|
+
"./clipboard": {
|
|
67
|
+
"types": "./src/clipboard/index.ts",
|
|
68
|
+
"import": "./src/clipboard/index.ts"
|
|
69
|
+
},
|
|
70
|
+
"./clipboard/*": {
|
|
71
|
+
"types": "./src/clipboard/*.ts",
|
|
72
|
+
"import": "./src/clipboard/*.ts"
|
|
73
|
+
},
|
|
74
|
+
"./glob": {
|
|
75
|
+
"types": "./src/glob/index.ts",
|
|
76
|
+
"import": "./src/glob/index.ts"
|
|
77
|
+
},
|
|
78
|
+
"./glob/*": {
|
|
79
|
+
"types": "./src/glob/*.ts",
|
|
80
|
+
"import": "./src/glob/*.ts"
|
|
81
|
+
},
|
|
82
|
+
"./grep": {
|
|
83
|
+
"types": "./src/grep/index.ts",
|
|
84
|
+
"import": "./src/grep/index.ts"
|
|
85
|
+
},
|
|
86
|
+
"./grep/*": {
|
|
87
|
+
"types": "./src/grep/*.ts",
|
|
88
|
+
"import": "./src/grep/*.ts"
|
|
89
|
+
},
|
|
90
|
+
"./highlight": {
|
|
91
|
+
"types": "./src/highlight/index.ts",
|
|
92
|
+
"import": "./src/highlight/index.ts"
|
|
93
|
+
},
|
|
94
|
+
"./highlight/*": {
|
|
95
|
+
"types": "./src/highlight/*.ts",
|
|
96
|
+
"import": "./src/highlight/*.ts"
|
|
97
|
+
},
|
|
98
|
+
"./html": {
|
|
99
|
+
"types": "./src/html/index.ts",
|
|
100
|
+
"import": "./src/html/index.ts"
|
|
101
|
+
},
|
|
102
|
+
"./html/*": {
|
|
103
|
+
"types": "./src/html/*.ts",
|
|
104
|
+
"import": "./src/html/*.ts"
|
|
105
|
+
},
|
|
106
|
+
"./image": {
|
|
107
|
+
"types": "./src/image/index.ts",
|
|
108
|
+
"import": "./src/image/index.ts"
|
|
109
|
+
},
|
|
110
|
+
"./image/*": {
|
|
111
|
+
"types": "./src/image/*.ts",
|
|
112
|
+
"import": "./src/image/*.ts"
|
|
113
|
+
},
|
|
114
|
+
"./keys": {
|
|
115
|
+
"types": "./src/keys/index.ts",
|
|
116
|
+
"import": "./src/keys/index.ts"
|
|
117
|
+
},
|
|
118
|
+
"./keys/*": {
|
|
119
|
+
"types": "./src/keys/*.ts",
|
|
120
|
+
"import": "./src/keys/*.ts"
|
|
121
|
+
},
|
|
122
|
+
"./ps": {
|
|
123
|
+
"types": "./src/ps/index.ts",
|
|
124
|
+
"import": "./src/ps/index.ts"
|
|
125
|
+
},
|
|
126
|
+
"./ps/*": {
|
|
127
|
+
"types": "./src/ps/*.ts",
|
|
128
|
+
"import": "./src/ps/*.ts"
|
|
129
|
+
},
|
|
130
|
+
"./pty": {
|
|
131
|
+
"types": "./src/pty/index.ts",
|
|
132
|
+
"import": "./src/pty/index.ts"
|
|
133
|
+
},
|
|
134
|
+
"./pty/*": {
|
|
135
|
+
"types": "./src/pty/*.ts",
|
|
136
|
+
"import": "./src/pty/*.ts"
|
|
137
|
+
},
|
|
138
|
+
"./shell": {
|
|
139
|
+
"types": "./src/shell/index.ts",
|
|
140
|
+
"import": "./src/shell/index.ts"
|
|
141
|
+
},
|
|
142
|
+
"./shell/*": {
|
|
143
|
+
"types": "./src/shell/*.ts",
|
|
144
|
+
"import": "./src/shell/*.ts"
|
|
145
|
+
},
|
|
146
|
+
"./text": {
|
|
147
|
+
"types": "./src/text/index.ts",
|
|
148
|
+
"import": "./src/text/index.ts"
|
|
149
|
+
},
|
|
150
|
+
"./text/*": {
|
|
151
|
+
"types": "./src/text/*.ts",
|
|
152
|
+
"import": "./src/text/*.ts"
|
|
153
|
+
},
|
|
154
|
+
"./work": {
|
|
155
|
+
"types": "./src/work/index.ts",
|
|
156
|
+
"import": "./src/work/index.ts"
|
|
157
|
+
},
|
|
158
|
+
"./work/*": {
|
|
159
|
+
"types": "./src/work/*.ts",
|
|
160
|
+
"import": "./src/work/*.ts"
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
package/src/bindings.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base types for native bindings.
|
|
3
|
+
* Modules extend this interface via declaration merging.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** Callback type for threadsafe functions from N-API. */
|
|
7
|
+
export type TsFunc<T> = (error: Error | null, value: T) => void;
|
|
8
|
+
|
|
9
|
+
/** Options for cancellable operations. */
|
|
10
|
+
export interface Cancellable {
|
|
11
|
+
/** Timeout in milliseconds for the operation. */
|
|
12
|
+
timeoutMs?: number;
|
|
13
|
+
/** Abort signal for cancelling the operation. */
|
|
14
|
+
signal?: AbortSignal;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Native bindings interface.
|
|
19
|
+
* Extended by each module via declaration merging.
|
|
20
|
+
*/
|
|
21
|
+
export interface NativeBindings {
|
|
22
|
+
cancelWork(id: number): void;
|
|
23
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clipboard helpers backed by native arboard bindings.
|
|
3
|
+
*
|
|
4
|
+
* Adds OSC 52 fallback for SSH/mosh, Termux support, and headless guards
|
|
5
|
+
* on top of the native arboard layer.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { execSync } from "node:child_process";
|
|
9
|
+
|
|
10
|
+
import { native } from "../native";
|
|
11
|
+
|
|
12
|
+
import type { ClipboardImage } from "./types";
|
|
13
|
+
|
|
14
|
+
export type { ClipboardImage } from "./types";
|
|
15
|
+
|
|
16
|
+
/** Whether a display server is available on Linux. */
|
|
17
|
+
const hasDisplay = process.platform !== "linux" || Boolean(process.env.DISPLAY || process.env.WAYLAND_DISPLAY);
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Copy text to the system clipboard.
|
|
21
|
+
*
|
|
22
|
+
* Emits OSC 52 first when running in a real terminal (works over SSH/mosh),
|
|
23
|
+
* then attempts native clipboard copy as best-effort for local sessions.
|
|
24
|
+
* On Termux, tries `termux-clipboard-set` before native.
|
|
25
|
+
*
|
|
26
|
+
* @param text - UTF-8 text to place on the clipboard.
|
|
27
|
+
*/
|
|
28
|
+
export async function copyToClipboard(text: string): Promise<void> {
|
|
29
|
+
if (process.stdout.isTTY) {
|
|
30
|
+
const encoded = Buffer.from(text).toString("base64");
|
|
31
|
+
const osc52 = `\x1b]52;c;${encoded}\x07`;
|
|
32
|
+
const onError = (err: unknown) => {
|
|
33
|
+
process.stdout.off("error", onError);
|
|
34
|
+
// Prevent unhandled 'error' from crashing the process when stdout is a closed pipe.
|
|
35
|
+
if ((err as NodeJS.ErrnoException | null | undefined)?.code === "EPIPE") {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
try {
|
|
40
|
+
process.stdout.on("error", onError);
|
|
41
|
+
process.stdout.write(osc52, err => {
|
|
42
|
+
process.stdout.off("error", onError);
|
|
43
|
+
// If stdout is closed (e.g. piped to a process that exits early),
|
|
44
|
+
// ignore EPIPE and proceed with native clipboard best-effort.
|
|
45
|
+
if ((err as NodeJS.ErrnoException | null | undefined)?.code === "EPIPE") {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
} catch (err) {
|
|
50
|
+
process.stdout.off("error", onError);
|
|
51
|
+
if ((err as NodeJS.ErrnoException | null | undefined)?.code !== "EPIPE") {
|
|
52
|
+
// Ignore all write failures (OSC 52 is best-effort).
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Also try native tools (best effort for local sessions)
|
|
58
|
+
try {
|
|
59
|
+
if (process.env.TERMUX_VERSION) {
|
|
60
|
+
try {
|
|
61
|
+
execSync("termux-clipboard-set", { input: text, timeout: 5000 });
|
|
62
|
+
return;
|
|
63
|
+
} catch {
|
|
64
|
+
// Fall through to native
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
await native.copyToClipboard(text);
|
|
69
|
+
} catch {
|
|
70
|
+
// Ignore — clipboard copy is best-effort
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Read an image from the system clipboard.
|
|
76
|
+
*
|
|
77
|
+
* Returns null on Termux (no image clipboard support) or when no display
|
|
78
|
+
* server is available (headless/SSH without forwarding).
|
|
79
|
+
*
|
|
80
|
+
* @returns PNG payload or null when no image is available.
|
|
81
|
+
*/
|
|
82
|
+
export async function readImageFromClipboard(): Promise<ClipboardImage | null> {
|
|
83
|
+
if (process.env.TERMUX_VERSION) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!hasDisplay) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return native.readImageFromClipboard();
|
|
92
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for clipboard operations.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/** PNG-encoded clipboard image payload. */
|
|
6
|
+
export interface ClipboardImage {
|
|
7
|
+
/** PNG image bytes. */
|
|
8
|
+
data: Uint8Array;
|
|
9
|
+
/** MIME type for the PNG payload. */
|
|
10
|
+
mimeType: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
declare module "../bindings" {
|
|
14
|
+
/** Native clipboard operations exposed by the bindings layer. */
|
|
15
|
+
interface NativeBindings {
|
|
16
|
+
/**
|
|
17
|
+
* Copy text to the system clipboard.
|
|
18
|
+
* @param text - UTF-8 text to place on the clipboard.
|
|
19
|
+
*/
|
|
20
|
+
copyToClipboard(text: string): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Read an image from the clipboard.
|
|
23
|
+
* @returns PNG payload or null when no image is available.
|
|
24
|
+
*/
|
|
25
|
+
readImageFromClipboard(): Promise<ClipboardImage | null>;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type EmbeddedAddonVariant = "modern" | "baseline" | "default";
|
|
2
|
+
|
|
3
|
+
export interface EmbeddedAddonFile {
|
|
4
|
+
variant: EmbeddedAddonVariant;
|
|
5
|
+
filename: string;
|
|
6
|
+
filePath: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface EmbeddedAddon {
|
|
10
|
+
platformTag: string;
|
|
11
|
+
version: string;
|
|
12
|
+
files: EmbeddedAddonFile[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const embeddedAddon: EmbeddedAddon | null = null;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File discovery API powered by globset + ignore crate.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import * as path from "node:path";
|
|
6
|
+
import { native } from "../native";
|
|
7
|
+
import type { GlobMatch, GlobOptions, GlobResult } from "./types";
|
|
8
|
+
|
|
9
|
+
export type { GlobMatch, GlobOptions, GlobResult } from "./types";
|
|
10
|
+
export { FileType } from "./types";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Find files matching a glob pattern.
|
|
14
|
+
* Respects .gitignore by default.
|
|
15
|
+
*/
|
|
16
|
+
export async function glob(options: GlobOptions, onMatch?: (match: GlobMatch) => void): Promise<GlobResult> {
|
|
17
|
+
const searchPath = path.resolve(options.path);
|
|
18
|
+
const pattern = options.pattern || "*";
|
|
19
|
+
// napi-rs ThreadsafeFunction passes (error, value) - skip callback on error
|
|
20
|
+
const cb = onMatch ? (err: Error | null, m: GlobMatch) => !err && onMatch(m) : undefined;
|
|
21
|
+
|
|
22
|
+
return native.glob(
|
|
23
|
+
{
|
|
24
|
+
...options,
|
|
25
|
+
path: searchPath,
|
|
26
|
+
pattern,
|
|
27
|
+
hidden: options.hidden ?? false,
|
|
28
|
+
gitignore: options.gitignore ?? true,
|
|
29
|
+
recursive: options.recursive ?? true,
|
|
30
|
+
},
|
|
31
|
+
cb,
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Invalidate the filesystem scan cache.
|
|
37
|
+
*
|
|
38
|
+
* When called with a path, removes entries for roots containing that path.
|
|
39
|
+
* When called without a path, clears the entire cache.
|
|
40
|
+
*/
|
|
41
|
+
export function invalidateFsScanCache(path?: string): void {
|
|
42
|
+
native.invalidateFsScanCache(path);
|
|
43
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for native find API.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { Cancellable, TsFunc } from "../bindings";
|
|
6
|
+
|
|
7
|
+
export const enum FileType {
|
|
8
|
+
/** A regular file. */
|
|
9
|
+
File = 1,
|
|
10
|
+
/** A directory. */
|
|
11
|
+
Dir = 2,
|
|
12
|
+
/** A symlink. */
|
|
13
|
+
Symlink = 3,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Options for discovering files and directories. */
|
|
17
|
+
export interface GlobOptions extends Cancellable {
|
|
18
|
+
/** Glob pattern to match (e.g., `*.ts`). */
|
|
19
|
+
pattern: string;
|
|
20
|
+
/** Directory to search. */
|
|
21
|
+
path: string;
|
|
22
|
+
/** Filter by file type: "file", "dir", or "symlink". Symlinks match file/dir filters when their target type matches. */
|
|
23
|
+
fileType?: FileType;
|
|
24
|
+
/** Match simple patterns recursively by default (example: *.ts -> recursive match). Set false to keep patterns relative to the search root only. */
|
|
25
|
+
recursive?: boolean;
|
|
26
|
+
/** Include hidden files (default: false). */
|
|
27
|
+
hidden?: boolean;
|
|
28
|
+
/** Maximum number of results to return. */
|
|
29
|
+
maxResults?: number;
|
|
30
|
+
/** Respect .gitignore files (default: true). */
|
|
31
|
+
gitignore?: boolean;
|
|
32
|
+
/** Enable shared filesystem scan cache (default: false). */
|
|
33
|
+
cache?: boolean;
|
|
34
|
+
/** Sort results by mtime (most recent first) before applying limit. */
|
|
35
|
+
sortByMtime?: boolean;
|
|
36
|
+
/** Include node_modules entries even when pattern does not mention node_modules. */
|
|
37
|
+
includeNodeModules?: boolean;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** A single filesystem match. */
|
|
41
|
+
export interface GlobMatch {
|
|
42
|
+
/** Relative path from the search root. */
|
|
43
|
+
path: string;
|
|
44
|
+
/** Resolved filesystem type for the match (for fileType=file/dir filters, symlink targets are reported as file/dir). */
|
|
45
|
+
fileType: FileType;
|
|
46
|
+
/** Modification time in milliseconds since epoch, if available. */
|
|
47
|
+
mtime?: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Result of a find operation. */
|
|
51
|
+
export interface GlobResult {
|
|
52
|
+
/** Matched filesystem entries. */
|
|
53
|
+
matches: GlobMatch[];
|
|
54
|
+
/** Number of matches returned after limits are applied. */
|
|
55
|
+
totalMatches: number;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
declare module "../bindings" {
|
|
59
|
+
interface NativeBindings {
|
|
60
|
+
/**
|
|
61
|
+
* Find filesystem entries matching a glob pattern.
|
|
62
|
+
* @param options Search options that control globbing and filters.
|
|
63
|
+
* @param onMatch Optional callback for streaming matches as they are found.
|
|
64
|
+
*/
|
|
65
|
+
glob(options: GlobOptions, onMatch?: TsFunc<GlobMatch>): Promise<GlobResult>;
|
|
66
|
+
/** Invalidate the filesystem scan cache for the given path (or all caches if omitted). */
|
|
67
|
+
invalidateFsScanCache(path?: string): void;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native ripgrep wrapper using N-API.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { native } from "../native";
|
|
6
|
+
import type {
|
|
7
|
+
ContextLine,
|
|
8
|
+
FuzzyFindMatch,
|
|
9
|
+
FuzzyFindOptions,
|
|
10
|
+
FuzzyFindResult,
|
|
11
|
+
GrepMatch,
|
|
12
|
+
GrepOptions,
|
|
13
|
+
GrepResult,
|
|
14
|
+
GrepSummary,
|
|
15
|
+
SearchOptions,
|
|
16
|
+
SearchResult,
|
|
17
|
+
} from "./types";
|
|
18
|
+
|
|
19
|
+
export type {
|
|
20
|
+
ContextLine,
|
|
21
|
+
FuzzyFindMatch,
|
|
22
|
+
FuzzyFindOptions,
|
|
23
|
+
FuzzyFindResult,
|
|
24
|
+
GrepMatch,
|
|
25
|
+
GrepOptions,
|
|
26
|
+
GrepResult,
|
|
27
|
+
GrepSummary,
|
|
28
|
+
SearchOptions,
|
|
29
|
+
SearchResult,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Search files for a regex pattern with optional streaming callback.
|
|
34
|
+
*/
|
|
35
|
+
export async function grep(options: GrepOptions, onMatch?: (match: GrepMatch) => void): Promise<GrepResult> {
|
|
36
|
+
// napi-rs ThreadsafeFunction passes (error, value) - skip callback on error
|
|
37
|
+
const cb = onMatch ? (err: Error | null, m: GrepMatch) => !err && onMatch(m) : undefined;
|
|
38
|
+
return native.grep(options, cb);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Search a single file's content for a pattern.
|
|
43
|
+
* Lower-level API for when you already have file content.
|
|
44
|
+
*
|
|
45
|
+
* Accepts `Uint8Array`/`Buffer` for zero-copy when content is already UTF-8 encoded.
|
|
46
|
+
*/
|
|
47
|
+
export function searchContent(content: string | Uint8Array, options: SearchOptions): SearchResult {
|
|
48
|
+
return native.search(content, options);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Quick check if content contains a pattern match.
|
|
53
|
+
*
|
|
54
|
+
* Accepts `Uint8Array`/`Buffer` for zero-copy when content/pattern are already UTF-8 encoded.
|
|
55
|
+
*/
|
|
56
|
+
export function hasMatch(
|
|
57
|
+
content: string | Uint8Array,
|
|
58
|
+
pattern: string | Uint8Array,
|
|
59
|
+
options?: { ignoreCase?: boolean; multiline?: boolean },
|
|
60
|
+
): boolean {
|
|
61
|
+
return native.hasMatch(content, pattern, options?.ignoreCase ?? false, options?.multiline ?? false);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Fuzzy file path search for autocomplete.
|
|
66
|
+
*
|
|
67
|
+
* Searches for files and directories whose paths contain the query substring
|
|
68
|
+
* (case-insensitive). Respects .gitignore by default.
|
|
69
|
+
*/
|
|
70
|
+
export async function fuzzyFind(options: FuzzyFindOptions): Promise<FuzzyFindResult> {
|
|
71
|
+
return native.fuzzyFind(options);
|
|
72
|
+
}
|