@kexi/vibe-native 0.12.5
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 +156 -0
- package/index.d.ts +34 -0
- package/index.js +320 -0
- package/package.json +65 -0
- package/vibe-native.darwin-arm64.node +0 -0
- package/vibe-native.darwin-x64.node +0 -0
- package/vibe-native.linux-arm64-gnu.node +0 -0
- package/vibe-native.linux-x64-gnu.node +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# @kexi/vibe-native
|
|
2
|
+
|
|
3
|
+
Native Copy-on-Write (CoW) file cloning for Node.js using Rust (napi-rs).
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **macOS**: Uses `clonefile()` syscall on APFS filesystems
|
|
8
|
+
- **Linux**: Uses `FICLONE` ioctl on Btrfs/XFS filesystems
|
|
9
|
+
- **Zero-copy**: Creates instant file clones without copying data
|
|
10
|
+
- **Async/Sync**: Both async and sync APIs available
|
|
11
|
+
- **Type-safe**: Full TypeScript support with auto-generated types
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @kexi/vibe-native
|
|
17
|
+
# or
|
|
18
|
+
pnpm add @kexi/vibe-native
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Platform Support
|
|
22
|
+
|
|
23
|
+
| Platform | Architecture | Filesystem |
|
|
24
|
+
|----------|--------------|------------|
|
|
25
|
+
| macOS | x64, arm64 | APFS |
|
|
26
|
+
| Linux | x64, arm64 | Btrfs, XFS (with reflink) |
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
import {
|
|
32
|
+
cloneAsync,
|
|
33
|
+
cloneSync,
|
|
34
|
+
isAvailable,
|
|
35
|
+
supportsDirectory,
|
|
36
|
+
getPlatform,
|
|
37
|
+
} from "@kexi/vibe-native";
|
|
38
|
+
|
|
39
|
+
// Check if native cloning is available
|
|
40
|
+
if (isAvailable()) {
|
|
41
|
+
console.log(`Platform: ${getPlatform()}`);
|
|
42
|
+
console.log(`Directory cloning: ${supportsDirectory()}`);
|
|
43
|
+
|
|
44
|
+
// Async cloning (recommended)
|
|
45
|
+
await cloneAsync("/path/to/source", "/path/to/dest");
|
|
46
|
+
|
|
47
|
+
// Sync cloning
|
|
48
|
+
cloneSync("/path/to/source", "/path/to/dest");
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## API
|
|
53
|
+
|
|
54
|
+
### `cloneAsync(src: string, dest: string): Promise<void>`
|
|
55
|
+
|
|
56
|
+
Clone a file or directory asynchronously using native Copy-on-Write.
|
|
57
|
+
|
|
58
|
+
### `cloneSync(src: string, dest: string): void`
|
|
59
|
+
|
|
60
|
+
Clone a file or directory synchronously using native Copy-on-Write.
|
|
61
|
+
|
|
62
|
+
### `clone(src: string, dest: string): void`
|
|
63
|
+
|
|
64
|
+
Alias for `cloneSync` (for backward compatibility).
|
|
65
|
+
|
|
66
|
+
### `isAvailable(): boolean`
|
|
67
|
+
|
|
68
|
+
Check if native clone operations are available on the current platform.
|
|
69
|
+
|
|
70
|
+
### `supportsDirectory(): boolean`
|
|
71
|
+
|
|
72
|
+
Check if directory cloning is supported:
|
|
73
|
+
- macOS (`clonefile`): `true`
|
|
74
|
+
- Linux (`FICLONE`): `false` (files only)
|
|
75
|
+
|
|
76
|
+
### `getPlatform(): "darwin" | "linux" | "unknown"`
|
|
77
|
+
|
|
78
|
+
Get the current platform identifier.
|
|
79
|
+
|
|
80
|
+
## Security
|
|
81
|
+
|
|
82
|
+
### File Type Validation
|
|
83
|
+
|
|
84
|
+
Only regular files and directories are allowed. The following are rejected:
|
|
85
|
+
- Symlinks (to prevent path traversal)
|
|
86
|
+
- Device files (block/character devices)
|
|
87
|
+
- Sockets
|
|
88
|
+
- FIFOs (named pipes)
|
|
89
|
+
|
|
90
|
+
### Path Handling
|
|
91
|
+
|
|
92
|
+
This library does not perform path normalization or validation. Callers should:
|
|
93
|
+
- Validate paths before calling clone functions
|
|
94
|
+
- Use `path.resolve()` to normalize relative paths
|
|
95
|
+
- Check for symlinks if path traversal is a concern
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { resolve, dirname } from "path";
|
|
99
|
+
import { realpath } from "fs/promises";
|
|
100
|
+
|
|
101
|
+
// Example: Safe path handling
|
|
102
|
+
async function safeClone(src: string, dest: string, allowedDir: string) {
|
|
103
|
+
const resolvedSrc = await realpath(resolve(src));
|
|
104
|
+
const resolvedDest = resolve(dest);
|
|
105
|
+
|
|
106
|
+
// Verify paths are within allowed directory
|
|
107
|
+
if (!resolvedSrc.startsWith(allowedDir)) {
|
|
108
|
+
throw new Error("Source path outside allowed directory");
|
|
109
|
+
}
|
|
110
|
+
if (!resolvedDest.startsWith(allowedDir)) {
|
|
111
|
+
throw new Error("Destination path outside allowed directory");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
await cloneAsync(resolvedSrc, resolvedDest);
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Error Handling
|
|
119
|
+
|
|
120
|
+
Errors include system errno information for debugging:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
try {
|
|
124
|
+
await cloneAsync("/nonexistent", "/dest");
|
|
125
|
+
} catch (error) {
|
|
126
|
+
// Error: open source failed: No such file or directory (errno 2)
|
|
127
|
+
console.error(error.message);
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Filesystem Requirements
|
|
132
|
+
|
|
133
|
+
### macOS
|
|
134
|
+
- **APFS** is required for `clonefile()` to work
|
|
135
|
+
- HFS+ and other filesystems will return `ENOTSUP`
|
|
136
|
+
|
|
137
|
+
### Linux
|
|
138
|
+
- **Btrfs** or **XFS** (with reflink support) is required
|
|
139
|
+
- ext4 and other filesystems will return `EOPNOTSUPP`
|
|
140
|
+
|
|
141
|
+
## Building from Source
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# Install dependencies
|
|
145
|
+
pnpm install
|
|
146
|
+
|
|
147
|
+
# Build (requires Rust toolchain)
|
|
148
|
+
pnpm run build
|
|
149
|
+
|
|
150
|
+
# Run tests
|
|
151
|
+
cargo test
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## License
|
|
155
|
+
|
|
156
|
+
Apache-2.0
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
/* auto-generated by NAPI-RS */
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Clone a file or directory synchronously using native Copy-on-Write
|
|
8
|
+
*
|
|
9
|
+
* - macOS: Uses clonefile() which supports both files and directories
|
|
10
|
+
* - Linux: Uses FICLONE ioctl which only supports files
|
|
11
|
+
*/
|
|
12
|
+
export declare function cloneSync(src: string, dest: string): void
|
|
13
|
+
/**
|
|
14
|
+
* Clone a file or directory asynchronously using native Copy-on-Write
|
|
15
|
+
*
|
|
16
|
+
* - macOS: Uses clonefile() which supports both files and directories
|
|
17
|
+
* - Linux: Uses FICLONE ioctl which only supports files
|
|
18
|
+
*/
|
|
19
|
+
export declare function cloneAsync(src: string, dest: string): Promise<void>
|
|
20
|
+
/** Clone a file or directory synchronously (alias for cloneSync for backward compatibility) */
|
|
21
|
+
export declare function clone(src: string, dest: string): void
|
|
22
|
+
/** Check if native clone operations are available */
|
|
23
|
+
export declare function isAvailable(): boolean
|
|
24
|
+
/**
|
|
25
|
+
* Check if directory cloning is supported
|
|
26
|
+
* - macOS clonefile: true (supports directories)
|
|
27
|
+
* - Linux FICLONE: false (files only)
|
|
28
|
+
*/
|
|
29
|
+
export declare function supportsDirectory(): boolean
|
|
30
|
+
/**
|
|
31
|
+
* Get the current platform
|
|
32
|
+
* Returns "darwin" or "linux"
|
|
33
|
+
*/
|
|
34
|
+
export declare function getPlatform(): string
|
package/index.js
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
/* prettier-ignore */
|
|
4
|
+
|
|
5
|
+
/* auto-generated by NAPI-RS */
|
|
6
|
+
|
|
7
|
+
const { existsSync, readFileSync } = require('fs')
|
|
8
|
+
const { join } = require('path')
|
|
9
|
+
|
|
10
|
+
const { platform, arch } = process
|
|
11
|
+
|
|
12
|
+
let nativeBinding = null
|
|
13
|
+
let localFileExisted = false
|
|
14
|
+
let loadError = null
|
|
15
|
+
|
|
16
|
+
function isMusl() {
|
|
17
|
+
// For Node 10
|
|
18
|
+
if (!process.report || typeof process.report.getReport !== 'function') {
|
|
19
|
+
try {
|
|
20
|
+
const lddPath = require('child_process').execSync('which ldd').toString().trim()
|
|
21
|
+
return readFileSync(lddPath, 'utf8').includes('musl')
|
|
22
|
+
} catch (e) {
|
|
23
|
+
return true
|
|
24
|
+
}
|
|
25
|
+
} else {
|
|
26
|
+
const { glibcVersionRuntime } = process.report.getReport().header
|
|
27
|
+
return !glibcVersionRuntime
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
switch (platform) {
|
|
32
|
+
case 'android':
|
|
33
|
+
switch (arch) {
|
|
34
|
+
case 'arm64':
|
|
35
|
+
localFileExisted = existsSync(join(__dirname, 'vibe-native.android-arm64.node'))
|
|
36
|
+
try {
|
|
37
|
+
if (localFileExisted) {
|
|
38
|
+
nativeBinding = require('./vibe-native.android-arm64.node')
|
|
39
|
+
} else {
|
|
40
|
+
nativeBinding = require('@kexi/vibe-native-android-arm64')
|
|
41
|
+
}
|
|
42
|
+
} catch (e) {
|
|
43
|
+
loadError = e
|
|
44
|
+
}
|
|
45
|
+
break
|
|
46
|
+
case 'arm':
|
|
47
|
+
localFileExisted = existsSync(join(__dirname, 'vibe-native.android-arm-eabi.node'))
|
|
48
|
+
try {
|
|
49
|
+
if (localFileExisted) {
|
|
50
|
+
nativeBinding = require('./vibe-native.android-arm-eabi.node')
|
|
51
|
+
} else {
|
|
52
|
+
nativeBinding = require('@kexi/vibe-native-android-arm-eabi')
|
|
53
|
+
}
|
|
54
|
+
} catch (e) {
|
|
55
|
+
loadError = e
|
|
56
|
+
}
|
|
57
|
+
break
|
|
58
|
+
default:
|
|
59
|
+
throw new Error(`Unsupported architecture on Android ${arch}`)
|
|
60
|
+
}
|
|
61
|
+
break
|
|
62
|
+
case 'win32':
|
|
63
|
+
switch (arch) {
|
|
64
|
+
case 'x64':
|
|
65
|
+
localFileExisted = existsSync(
|
|
66
|
+
join(__dirname, 'vibe-native.win32-x64-msvc.node')
|
|
67
|
+
)
|
|
68
|
+
try {
|
|
69
|
+
if (localFileExisted) {
|
|
70
|
+
nativeBinding = require('./vibe-native.win32-x64-msvc.node')
|
|
71
|
+
} else {
|
|
72
|
+
nativeBinding = require('@kexi/vibe-native-win32-x64-msvc')
|
|
73
|
+
}
|
|
74
|
+
} catch (e) {
|
|
75
|
+
loadError = e
|
|
76
|
+
}
|
|
77
|
+
break
|
|
78
|
+
case 'ia32':
|
|
79
|
+
localFileExisted = existsSync(
|
|
80
|
+
join(__dirname, 'vibe-native.win32-ia32-msvc.node')
|
|
81
|
+
)
|
|
82
|
+
try {
|
|
83
|
+
if (localFileExisted) {
|
|
84
|
+
nativeBinding = require('./vibe-native.win32-ia32-msvc.node')
|
|
85
|
+
} else {
|
|
86
|
+
nativeBinding = require('@kexi/vibe-native-win32-ia32-msvc')
|
|
87
|
+
}
|
|
88
|
+
} catch (e) {
|
|
89
|
+
loadError = e
|
|
90
|
+
}
|
|
91
|
+
break
|
|
92
|
+
case 'arm64':
|
|
93
|
+
localFileExisted = existsSync(
|
|
94
|
+
join(__dirname, 'vibe-native.win32-arm64-msvc.node')
|
|
95
|
+
)
|
|
96
|
+
try {
|
|
97
|
+
if (localFileExisted) {
|
|
98
|
+
nativeBinding = require('./vibe-native.win32-arm64-msvc.node')
|
|
99
|
+
} else {
|
|
100
|
+
nativeBinding = require('@kexi/vibe-native-win32-arm64-msvc')
|
|
101
|
+
}
|
|
102
|
+
} catch (e) {
|
|
103
|
+
loadError = e
|
|
104
|
+
}
|
|
105
|
+
break
|
|
106
|
+
default:
|
|
107
|
+
throw new Error(`Unsupported architecture on Windows: ${arch}`)
|
|
108
|
+
}
|
|
109
|
+
break
|
|
110
|
+
case 'darwin':
|
|
111
|
+
localFileExisted = existsSync(join(__dirname, 'vibe-native.darwin-universal.node'))
|
|
112
|
+
try {
|
|
113
|
+
if (localFileExisted) {
|
|
114
|
+
nativeBinding = require('./vibe-native.darwin-universal.node')
|
|
115
|
+
} else {
|
|
116
|
+
nativeBinding = require('@kexi/vibe-native-darwin-universal')
|
|
117
|
+
}
|
|
118
|
+
break
|
|
119
|
+
} catch {}
|
|
120
|
+
switch (arch) {
|
|
121
|
+
case 'x64':
|
|
122
|
+
localFileExisted = existsSync(join(__dirname, 'vibe-native.darwin-x64.node'))
|
|
123
|
+
try {
|
|
124
|
+
if (localFileExisted) {
|
|
125
|
+
nativeBinding = require('./vibe-native.darwin-x64.node')
|
|
126
|
+
} else {
|
|
127
|
+
nativeBinding = require('@kexi/vibe-native-darwin-x64')
|
|
128
|
+
}
|
|
129
|
+
} catch (e) {
|
|
130
|
+
loadError = e
|
|
131
|
+
}
|
|
132
|
+
break
|
|
133
|
+
case 'arm64':
|
|
134
|
+
localFileExisted = existsSync(
|
|
135
|
+
join(__dirname, 'vibe-native.darwin-arm64.node')
|
|
136
|
+
)
|
|
137
|
+
try {
|
|
138
|
+
if (localFileExisted) {
|
|
139
|
+
nativeBinding = require('./vibe-native.darwin-arm64.node')
|
|
140
|
+
} else {
|
|
141
|
+
nativeBinding = require('@kexi/vibe-native-darwin-arm64')
|
|
142
|
+
}
|
|
143
|
+
} catch (e) {
|
|
144
|
+
loadError = e
|
|
145
|
+
}
|
|
146
|
+
break
|
|
147
|
+
default:
|
|
148
|
+
throw new Error(`Unsupported architecture on macOS: ${arch}`)
|
|
149
|
+
}
|
|
150
|
+
break
|
|
151
|
+
case 'freebsd':
|
|
152
|
+
if (arch !== 'x64') {
|
|
153
|
+
throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
|
|
154
|
+
}
|
|
155
|
+
localFileExisted = existsSync(join(__dirname, 'vibe-native.freebsd-x64.node'))
|
|
156
|
+
try {
|
|
157
|
+
if (localFileExisted) {
|
|
158
|
+
nativeBinding = require('./vibe-native.freebsd-x64.node')
|
|
159
|
+
} else {
|
|
160
|
+
nativeBinding = require('@kexi/vibe-native-freebsd-x64')
|
|
161
|
+
}
|
|
162
|
+
} catch (e) {
|
|
163
|
+
loadError = e
|
|
164
|
+
}
|
|
165
|
+
break
|
|
166
|
+
case 'linux':
|
|
167
|
+
switch (arch) {
|
|
168
|
+
case 'x64':
|
|
169
|
+
if (isMusl()) {
|
|
170
|
+
localFileExisted = existsSync(
|
|
171
|
+
join(__dirname, 'vibe-native.linux-x64-musl.node')
|
|
172
|
+
)
|
|
173
|
+
try {
|
|
174
|
+
if (localFileExisted) {
|
|
175
|
+
nativeBinding = require('./vibe-native.linux-x64-musl.node')
|
|
176
|
+
} else {
|
|
177
|
+
nativeBinding = require('@kexi/vibe-native-linux-x64-musl')
|
|
178
|
+
}
|
|
179
|
+
} catch (e) {
|
|
180
|
+
loadError = e
|
|
181
|
+
}
|
|
182
|
+
} else {
|
|
183
|
+
localFileExisted = existsSync(
|
|
184
|
+
join(__dirname, 'vibe-native.linux-x64-gnu.node')
|
|
185
|
+
)
|
|
186
|
+
try {
|
|
187
|
+
if (localFileExisted) {
|
|
188
|
+
nativeBinding = require('./vibe-native.linux-x64-gnu.node')
|
|
189
|
+
} else {
|
|
190
|
+
nativeBinding = require('@kexi/vibe-native-linux-x64-gnu')
|
|
191
|
+
}
|
|
192
|
+
} catch (e) {
|
|
193
|
+
loadError = e
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
break
|
|
197
|
+
case 'arm64':
|
|
198
|
+
if (isMusl()) {
|
|
199
|
+
localFileExisted = existsSync(
|
|
200
|
+
join(__dirname, 'vibe-native.linux-arm64-musl.node')
|
|
201
|
+
)
|
|
202
|
+
try {
|
|
203
|
+
if (localFileExisted) {
|
|
204
|
+
nativeBinding = require('./vibe-native.linux-arm64-musl.node')
|
|
205
|
+
} else {
|
|
206
|
+
nativeBinding = require('@kexi/vibe-native-linux-arm64-musl')
|
|
207
|
+
}
|
|
208
|
+
} catch (e) {
|
|
209
|
+
loadError = e
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
localFileExisted = existsSync(
|
|
213
|
+
join(__dirname, 'vibe-native.linux-arm64-gnu.node')
|
|
214
|
+
)
|
|
215
|
+
try {
|
|
216
|
+
if (localFileExisted) {
|
|
217
|
+
nativeBinding = require('./vibe-native.linux-arm64-gnu.node')
|
|
218
|
+
} else {
|
|
219
|
+
nativeBinding = require('@kexi/vibe-native-linux-arm64-gnu')
|
|
220
|
+
}
|
|
221
|
+
} catch (e) {
|
|
222
|
+
loadError = e
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
break
|
|
226
|
+
case 'arm':
|
|
227
|
+
if (isMusl()) {
|
|
228
|
+
localFileExisted = existsSync(
|
|
229
|
+
join(__dirname, 'vibe-native.linux-arm-musleabihf.node')
|
|
230
|
+
)
|
|
231
|
+
try {
|
|
232
|
+
if (localFileExisted) {
|
|
233
|
+
nativeBinding = require('./vibe-native.linux-arm-musleabihf.node')
|
|
234
|
+
} else {
|
|
235
|
+
nativeBinding = require('@kexi/vibe-native-linux-arm-musleabihf')
|
|
236
|
+
}
|
|
237
|
+
} catch (e) {
|
|
238
|
+
loadError = e
|
|
239
|
+
}
|
|
240
|
+
} else {
|
|
241
|
+
localFileExisted = existsSync(
|
|
242
|
+
join(__dirname, 'vibe-native.linux-arm-gnueabihf.node')
|
|
243
|
+
)
|
|
244
|
+
try {
|
|
245
|
+
if (localFileExisted) {
|
|
246
|
+
nativeBinding = require('./vibe-native.linux-arm-gnueabihf.node')
|
|
247
|
+
} else {
|
|
248
|
+
nativeBinding = require('@kexi/vibe-native-linux-arm-gnueabihf')
|
|
249
|
+
}
|
|
250
|
+
} catch (e) {
|
|
251
|
+
loadError = e
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
break
|
|
255
|
+
case 'riscv64':
|
|
256
|
+
if (isMusl()) {
|
|
257
|
+
localFileExisted = existsSync(
|
|
258
|
+
join(__dirname, 'vibe-native.linux-riscv64-musl.node')
|
|
259
|
+
)
|
|
260
|
+
try {
|
|
261
|
+
if (localFileExisted) {
|
|
262
|
+
nativeBinding = require('./vibe-native.linux-riscv64-musl.node')
|
|
263
|
+
} else {
|
|
264
|
+
nativeBinding = require('@kexi/vibe-native-linux-riscv64-musl')
|
|
265
|
+
}
|
|
266
|
+
} catch (e) {
|
|
267
|
+
loadError = e
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
localFileExisted = existsSync(
|
|
271
|
+
join(__dirname, 'vibe-native.linux-riscv64-gnu.node')
|
|
272
|
+
)
|
|
273
|
+
try {
|
|
274
|
+
if (localFileExisted) {
|
|
275
|
+
nativeBinding = require('./vibe-native.linux-riscv64-gnu.node')
|
|
276
|
+
} else {
|
|
277
|
+
nativeBinding = require('@kexi/vibe-native-linux-riscv64-gnu')
|
|
278
|
+
}
|
|
279
|
+
} catch (e) {
|
|
280
|
+
loadError = e
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
break
|
|
284
|
+
case 's390x':
|
|
285
|
+
localFileExisted = existsSync(
|
|
286
|
+
join(__dirname, 'vibe-native.linux-s390x-gnu.node')
|
|
287
|
+
)
|
|
288
|
+
try {
|
|
289
|
+
if (localFileExisted) {
|
|
290
|
+
nativeBinding = require('./vibe-native.linux-s390x-gnu.node')
|
|
291
|
+
} else {
|
|
292
|
+
nativeBinding = require('@kexi/vibe-native-linux-s390x-gnu')
|
|
293
|
+
}
|
|
294
|
+
} catch (e) {
|
|
295
|
+
loadError = e
|
|
296
|
+
}
|
|
297
|
+
break
|
|
298
|
+
default:
|
|
299
|
+
throw new Error(`Unsupported architecture on Linux: ${arch}`)
|
|
300
|
+
}
|
|
301
|
+
break
|
|
302
|
+
default:
|
|
303
|
+
throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (!nativeBinding) {
|
|
307
|
+
if (loadError) {
|
|
308
|
+
throw loadError
|
|
309
|
+
}
|
|
310
|
+
throw new Error(`Failed to load native binding`)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const { cloneSync, cloneAsync, clone, isAvailable, supportsDirectory, getPlatform } = nativeBinding
|
|
314
|
+
|
|
315
|
+
module.exports.cloneSync = cloneSync
|
|
316
|
+
module.exports.cloneAsync = cloneAsync
|
|
317
|
+
module.exports.clone = clone
|
|
318
|
+
module.exports.isAvailable = isAvailable
|
|
319
|
+
module.exports.supportsDirectory = supportsDirectory
|
|
320
|
+
module.exports.getPlatform = getPlatform
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kexi/vibe-native",
|
|
3
|
+
"version": "0.12.5",
|
|
4
|
+
"description": "Native clone operations for vibe CLI (clonefile on macOS, FICLONE on Linux)",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"types": "index.d.ts",
|
|
7
|
+
"napi": {
|
|
8
|
+
"name": "vibe-native",
|
|
9
|
+
"triples": {
|
|
10
|
+
"defaults": false,
|
|
11
|
+
"additional": [
|
|
12
|
+
"x86_64-apple-darwin",
|
|
13
|
+
"aarch64-apple-darwin",
|
|
14
|
+
"x86_64-unknown-linux-gnu",
|
|
15
|
+
"aarch64-unknown-linux-gnu"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"index.js",
|
|
21
|
+
"index.d.ts",
|
|
22
|
+
"README.md",
|
|
23
|
+
"*.node"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"artifacts": "napi artifacts",
|
|
27
|
+
"build": "napi build --platform --release",
|
|
28
|
+
"build:debug": "napi build --platform",
|
|
29
|
+
"prepublishOnly": "napi prepublish -t npm",
|
|
30
|
+
"version": "napi version"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@napi-rs/cli": "^2.18.0"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=18.0.0"
|
|
37
|
+
},
|
|
38
|
+
"os": [
|
|
39
|
+
"darwin",
|
|
40
|
+
"linux"
|
|
41
|
+
],
|
|
42
|
+
"cpu": [
|
|
43
|
+
"x64",
|
|
44
|
+
"arm64"
|
|
45
|
+
],
|
|
46
|
+
"repository": {
|
|
47
|
+
"type": "git",
|
|
48
|
+
"url": "git+https://github.com/kexi/vibe.git",
|
|
49
|
+
"directory": "packages/@kexi/vibe-native"
|
|
50
|
+
},
|
|
51
|
+
"keywords": [
|
|
52
|
+
"clonefile",
|
|
53
|
+
"ficlone",
|
|
54
|
+
"cow",
|
|
55
|
+
"copy-on-write",
|
|
56
|
+
"native",
|
|
57
|
+
"napi-rs"
|
|
58
|
+
],
|
|
59
|
+
"author": "kexi",
|
|
60
|
+
"license": "Apache-2.0",
|
|
61
|
+
"publishConfig": {
|
|
62
|
+
"access": "public",
|
|
63
|
+
"registry": "https://registry.npmjs.org/"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|