@archildata/client 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 ADDED
@@ -0,0 +1,126 @@
1
+ # @archil/node
2
+
3
+ High-performance Node.js bindings for the Archil distributed filesystem client.
4
+
5
+ ## Overview
6
+
7
+ This package provides low-level N-API bindings to the Archil client library, exposing the `ArchilService` trait methods directly to JavaScript/TypeScript. It's designed for use cases where you need direct protocol access without FUSE overhead.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install @archil/node
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```typescript
18
+ import { ArchilClient } from '@archil/node';
19
+
20
+ // Connect to Archil (authenticated via mount server)
21
+ const client = await ArchilClient.connectAuthenticated({
22
+ mountServer: 'https://mount.archil.io',
23
+ mountName: 'my-account/my-disk',
24
+ });
25
+
26
+ // Get root directory attributes
27
+ const rootAttrs = await client.getAttributes(1n);
28
+ console.log('Root size:', rootAttrs.size);
29
+
30
+ // List directory contents
31
+ const entries = await client.readDirectory(1n);
32
+ for (const entry of entries) {
33
+ console.log(`${entry.name} (inode: ${entry.inodeId})`);
34
+ }
35
+
36
+ // Read a file
37
+ const lookup = await client.lookupInode(1n, 'myfile.txt');
38
+ const data = await client.readInode(lookup.inodeId, 0n, 1024);
39
+ console.log('File content:', data.toString());
40
+
41
+ // Close when done
42
+ await client.close();
43
+ ```
44
+
45
+ ## API
46
+
47
+ ### `ArchilClient`
48
+
49
+ The main client class for interacting with Archil filesystems.
50
+
51
+ #### Connection Methods
52
+
53
+ - `connectDirect(config)` - Connect directly to a server (for testing)
54
+ - `connectAuthenticated(config)` - Connect via mount server with authentication
55
+
56
+ #### Metadata Operations
57
+
58
+ - `getAttributes(inodeId, user?)` - Get inode attributes
59
+ - `lookupInode(parentInodeId, name, user?)` - Lookup entry by name
60
+ - `readDirectory(inodeId, offset?, cookie?, user?)` - List directory entries
61
+ - `getExtendedAttribute(inodeId, name, user?)` - Get xattr value
62
+ - `listExtendedAttributes(inodeId, user?)` - List xattr names
63
+
64
+ #### Data Operations
65
+
66
+ - `readInode(inodeId, offset, length, user?)` - Read file data
67
+
68
+ #### Delegation Operations
69
+
70
+ - `checkout(inodeId, force?, user?)` - Acquire write delegation
71
+ - `checkin(inodeId, user?)` - Release delegation
72
+ - `checkinAll()` - Release all delegations
73
+
74
+ #### Mutation Operations
75
+
76
+ - `conditionalCreate(parentInodeId, name, childInodeId, attributes, user?)` - Create file/directory
77
+ - `setImmutable(inodeId)` - Mark subtree as immutable
78
+ - `setMutable(inodeId)` - Mark subtree as mutable
79
+ - `listImmutableSubtrees()` - List immutable roots
80
+
81
+ ### Types
82
+
83
+ All inode IDs and file offsets use JavaScript `bigint` for 64-bit support:
84
+
85
+ ```typescript
86
+ interface UnixUser {
87
+ uid: number;
88
+ gid: number;
89
+ }
90
+
91
+ interface InodeAttributes {
92
+ inodeId: bigint;
93
+ inodeType: 'File' | 'Directory' | 'Symlink' | ...;
94
+ size: bigint;
95
+ uid: number;
96
+ gid: number;
97
+ mode: number;
98
+ nlink: number;
99
+ ctimeMs: number;
100
+ atimeMs: number;
101
+ mtimeMs: number;
102
+ btimeMs: number;
103
+ rdev?: bigint;
104
+ symlinkTarget?: string;
105
+ }
106
+
107
+ interface DirectoryEntry {
108
+ name: string;
109
+ inodeId: bigint;
110
+ inodeType: string;
111
+ }
112
+ ```
113
+
114
+ ## Building
115
+
116
+ This package uses napi-rs for native bindings. To build from source:
117
+
118
+ ```bash
119
+ cd rust-libs/archil-node
120
+ npm install
121
+ npm run build
122
+ ```
123
+
124
+ ## License
125
+
126
+ Proprietary - Archil Inc.
Binary file
package/index.d.ts ADDED
@@ -0,0 +1,332 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /* auto-generated by NAPI-RS */
5
+
6
+ /**
7
+ * Initialize the Rust logger to output to stderr.
8
+ *
9
+ * @param level - Log level: "trace", "debug", "info", "warn", or "error"
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { initLogging } from '@archildata/client';
14
+ * initLogging('debug'); // Call once at startup
15
+ * ```
16
+ */
17
+ export declare function initLogging(level?: string | undefined | null): void
18
+ /** Unix user context for permission checks */
19
+ export interface UnixUser {
20
+ uid: number
21
+ gid: number
22
+ }
23
+ /** Inode type enum exposed to JavaScript */
24
+ export const enum JsInodeType {
25
+ File = 'File',
26
+ Directory = 'Directory',
27
+ Symlink = 'Symlink',
28
+ BlockDevice = 'BlockDevice',
29
+ CharacterDevice = 'CharacterDevice',
30
+ Fifo = 'Fifo',
31
+ Socket = 'Socket'
32
+ }
33
+ /**
34
+ * Inode attributes exposed to JavaScript
35
+ *
36
+ * Note: inode_id, size, and rdev use i64 which will be converted to/from
37
+ * JavaScript BigInt automatically by napi-rs when values exceed Number.MAX_SAFE_INTEGER.
38
+ */
39
+ export interface InodeAttributes {
40
+ /** Inode ID (use BigInt in JS for values > 2^53) */
41
+ inodeId: number
42
+ /** Type of the inode (File, Directory, Symlink, etc.) */
43
+ inodeType: string
44
+ /** File size in bytes */
45
+ size: number
46
+ /** Owner user ID */
47
+ uid: number
48
+ /** Owner group ID */
49
+ gid: number
50
+ /** Unix permission mode */
51
+ mode: number
52
+ /** Number of hard links */
53
+ nlink: number
54
+ /** Change time (milliseconds since epoch) */
55
+ ctimeMs: number
56
+ /** Access time (milliseconds since epoch) */
57
+ atimeMs: number
58
+ /** Modification time (milliseconds since epoch) */
59
+ mtimeMs: number
60
+ /** Birth/creation time (milliseconds since epoch) */
61
+ btimeMs: number
62
+ /** Device ID for block/char devices */
63
+ rdev?: number
64
+ /** Symlink target if this is a symlink */
65
+ symlinkTarget?: string
66
+ }
67
+ /** Directory entry returned from readdir */
68
+ export interface DirectoryEntry {
69
+ /** Name of the entry */
70
+ name: string
71
+ /** Inode ID of the entry */
72
+ inodeId: number
73
+ /** Type of the entry (File, Directory, etc.) */
74
+ inodeType: string
75
+ }
76
+ /** Lookup response containing inode info */
77
+ export interface LookupResponse {
78
+ /** Inode ID of the found entry (-1 if not found) */
79
+ inodeId: number
80
+ /** Attributes of the found inode */
81
+ attributes: InodeAttributes
82
+ }
83
+ /** Connection configuration for direct server connections */
84
+ export interface DirectConnectionConfig {
85
+ /** Server address (e.g., "localhost:8080") */
86
+ serverAddress: string
87
+ /** File system ID (optional, will be determined by server if not provided) */
88
+ fileSystemId?: number
89
+ /** Log level for Rust logging (e.g., "debug", "info", "warn", "error", "trace") */
90
+ logLevel?: string
91
+ }
92
+ /** Connection configuration for authenticated connections via mount server */
93
+ export interface AuthenticatedConnectionConfig {
94
+ /** Mount server address */
95
+ mountServer: string
96
+ /** Disk name (e.g., "dsk-xxx" or "account/diskname") */
97
+ mountName: string
98
+ /** Optional auth token (uses IAM if not provided) */
99
+ authToken?: string
100
+ /** Optional STS region for IAM authentication */
101
+ stsRegion?: string
102
+ }
103
+ /**
104
+ * Simplified connection configuration using just region and disk name.
105
+ *
106
+ * This mirrors the CLI's `archil mount` command interface.
107
+ *
108
+ * Example usage:
109
+ * ```javascript
110
+ * const client = await ArchilClient.connect({
111
+ * region: 'aws-us-east-1',
112
+ * diskName: 'myaccount/mydisk'
113
+ * });
114
+ * ```
115
+ *
116
+ * To enable debug logging:
117
+ * ```javascript
118
+ * const client = await ArchilClient.connect({
119
+ * region: 'aws-us-east-1',
120
+ * diskName: 'myaccount/mydisk',
121
+ * logLevel: 'debug' // Enables Rust debug logs to stderr
122
+ * });
123
+ * ```
124
+ */
125
+ export interface SimpleConnectionConfig {
126
+ /** Region identifier (e.g., "aws-us-east-1", "gcp-us-central1") */
127
+ region: string
128
+ /** Disk name - either "account/diskname" format or "dsk-xxx" disk ID */
129
+ diskName: string
130
+ /** Optional auth token (uses IAM if not provided) */
131
+ authToken?: string
132
+ /** Optional STS region for IAM authentication (defaults to region from the region parameter) */
133
+ stsRegion?: string
134
+ /** Log level for Rust logging (e.g., "debug", "info", "warn", "error", "trace") */
135
+ logLevel?: string
136
+ }
137
+ /** Inode ID range returned from reserve_inodes */
138
+ export interface InodeRange {
139
+ /** Start of the reserved range (inclusive) */
140
+ start: number
141
+ /** End of the reserved range (exclusive) */
142
+ end: number
143
+ }
144
+ /** Delegation information for an inode */
145
+ export interface DelegationInfo {
146
+ /** Inode ID that the delegation is for */
147
+ inodeId: number
148
+ /** State of the delegation: "Active", "Pending", or "Removing" */
149
+ state: string
150
+ }
151
+ /**
152
+ * Options for setattr operation
153
+ *
154
+ * All fields are optional - only provided fields will be updated.
155
+ * For atime/mtime: use timestamp in milliseconds, or -1 to set to current time.
156
+ */
157
+ export interface SetAttrOptions {
158
+ /** New permission mode (e.g., 0o644) */
159
+ mode?: number
160
+ /** New owner user ID */
161
+ uid?: number
162
+ /** New owner group ID */
163
+ gid?: number
164
+ /** New file size (for truncate) */
165
+ size?: number
166
+ /** New access time in milliseconds since epoch (-1 for current time) */
167
+ atimeMs?: number
168
+ /** New modification time in milliseconds since epoch (-1 for current time) */
169
+ mtimeMs?: number
170
+ /** New change time in milliseconds since epoch */
171
+ ctimeMs?: number
172
+ }
173
+ /**
174
+ * ArchilClient provides low-level access to Archil filesystem operations.
175
+ *
176
+ * This client uses the headless client mode from archil-client-core to provide
177
+ * direct protocol access without FUSE mount infrastructure.
178
+ */
179
+ export declare class ArchilClient {
180
+ /**
181
+ * Connect to an Archil server using a simplified configuration.
182
+ *
183
+ * This is the recommended way to connect and mirrors the CLI interface.
184
+ *
185
+ * @example
186
+ * ```typescript
187
+ * const client = await ArchilClient.connect({
188
+ * region: 'aws-us-east-1',
189
+ * diskName: 'myaccount/mydisk'
190
+ * });
191
+ * ```
192
+ */
193
+ static connect(config: SimpleConnectionConfig): Promise<ArchilClient>
194
+ /**
195
+ * Connect to an Archil server using direct connection.
196
+ *
197
+ * This is primarily for testing or internal use.
198
+ */
199
+ static connectDirect(config: DirectConnectionConfig): Promise<ArchilClient>
200
+ /**
201
+ * Close the client connection and release resources.
202
+ *
203
+ * This will sync all pending writes and release all delegations held by
204
+ * this client before closing. Returns the number of delegations that were released.
205
+ */
206
+ close(): Promise<number>
207
+ /** Get attributes for an inode (uses cache). */
208
+ getAttributes(inodeId: number, user?: UnixUser | undefined | null): Promise<InodeAttributes>
209
+ /** Lookup an entry by name in a directory (uses cache). */
210
+ lookupInode(parentInodeId: number, name: string, user?: UnixUser | undefined | null): Promise<LookupResponse>
211
+ /**
212
+ * Read directory entries.
213
+ *
214
+ * Uses the cache layer via snapshot_and_synchronize_directory to ensure
215
+ * the dirent cache is properly populated. This ensures that subsequent
216
+ * lookup_inode calls can find the entries returned here.
217
+ */
218
+ readDirectory(inodeId: number, offset?: number | undefined | null, cookie?: number | undefined | null, user?: UnixUser | undefined | null): Promise<Array<DirectoryEntry>>
219
+ /** Get an extended attribute value. */
220
+ getExtendedAttribute(inodeId: number, name: string, user?: UnixUser | undefined | null): Promise<Buffer | null>
221
+ /** List all extended attribute names. */
222
+ listExtendedAttributes(inodeId: number, user?: UnixUser | undefined | null): Promise<Array<string>>
223
+ /**
224
+ * Read data from a file (uses cache).
225
+ *
226
+ * Returns zero-copy Buffer when possible for optimal performance.
227
+ */
228
+ readInode(inodeId: number, offset: number, length: number, user?: UnixUser | undefined | null): Promise<Buffer>
229
+ /**
230
+ * Checkout (acquire delegation for) an inode for writing.
231
+ *
232
+ * This tracks the delegation locally so that subsequent write operations
233
+ * can proceed without additional server round-trips for permission checks.
234
+ */
235
+ checkout(inodeId: number, force?: boolean | undefined | null, user?: UnixUser | undefined | null): Promise<void>
236
+ /**
237
+ * Checkin (release delegation for) an inode.
238
+ *
239
+ * This syncs any pending writes and releases the local delegation tracking.
240
+ */
241
+ checkin(inodeId: number, user?: UnixUser | undefined | null): Promise<void>
242
+ /** Release all delegations held by this client. */
243
+ checkinAll(): Promise<number>
244
+ /**
245
+ * Sync all pending writes to the server.
246
+ *
247
+ * This flushes all buffered writes through the transaction scheduler,
248
+ * ensuring data durability before the method returns.
249
+ */
250
+ sync(): Promise<void>
251
+ /**
252
+ * Write data to a file.
253
+ *
254
+ * This performs a proper write operation using the transaction scheduler
255
+ * to batch and commit changes. Requires a delegation on the file
256
+ * (call checkout first).
257
+ *
258
+ * @example
259
+ * ```typescript
260
+ * // First checkout to get write delegation
261
+ * await client.checkout(inodeId, false, user);
262
+ * // Then write data
263
+ * await client.writeData(inodeId, 0n, Buffer.from('Hello World'), user);
264
+ * // Optionally checkin when done
265
+ * await client.checkin(inodeId, user);
266
+ * ```
267
+ */
268
+ writeData(inodeId: number, offset: number, data: Buffer, user?: UnixUser | undefined | null): Promise<void>
269
+ /**
270
+ * Set attributes on an inode.
271
+ *
272
+ * Updates file metadata like mode, timestamps, size, etc.
273
+ * Requires a delegation on the inode (call checkout first).
274
+ *
275
+ * For atime_ms and mtime_ms, use -1 to set to current time.
276
+ *
277
+ * @example
278
+ * ```typescript
279
+ * // First checkout to get write delegation
280
+ * await client.checkout(inodeId, false, user);
281
+ * // Update timestamps (touch)
282
+ * await client.setattr(inodeId, { atimeMs: -1, mtimeMs: -1 }, user);
283
+ * // Or change mode
284
+ * await client.setattr(inodeId, { mode: 0o755 }, user);
285
+ * // Checkin when done
286
+ * await client.checkin(inodeId, user);
287
+ * ```
288
+ */
289
+ setattr(inodeId: number, options: SetAttrOptions, user: UnixUser): Promise<InodeAttributes>
290
+ /**
291
+ * Unlink (delete) a file or empty directory.
292
+ *
293
+ * Removes the directory entry from the parent directory. Requires
294
+ * write permission on the parent directory.
295
+ */
296
+ unlink(parentInodeId: number, name: string, user?: UnixUser | undefined | null): Promise<void>
297
+ /**
298
+ * Rename (move) a file or directory.
299
+ *
300
+ * Atomically moves an entry from one location to another. If the destination
301
+ * exists, it will be replaced. Requires write permission on both parent directories.
302
+ *
303
+ * @example
304
+ * ```typescript
305
+ * // Move a file
306
+ * await client.rename(srcParentInodeId, 'oldname.txt', destParentInodeId, 'newname.txt', user);
307
+ * ```
308
+ */
309
+ rename(parentInodeId: number, name: string, newParentInodeId: number, newName: string, user?: UnixUser | undefined | null): Promise<void>
310
+ /**
311
+ * Create a new file or directory.
312
+ *
313
+ * Automatically chooses between unconditional create (if we have a delegation
314
+ * on the parent) and conditional create (if we need the server to issue a delegation).
315
+ *
316
+ * Returns the inode ID of the created file.
317
+ */
318
+ create(parentInodeId: number, name: string, attributes: InodeAttributes, user?: UnixUser | undefined | null): Promise<number>
319
+ /** Mark an inode subtree as immutable. */
320
+ setImmutable(inodeId: number): Promise<void>
321
+ /** Mark an inode subtree as mutable (reverse of set_immutable). */
322
+ setMutable(inodeId: number): Promise<void>
323
+ /** List all immutable subtree root inodes. */
324
+ listImmutableSubtrees(): Promise<Array<number>>
325
+ /**
326
+ * List all delegations currently held by this client.
327
+ *
328
+ * Returns a list of delegation info objects containing the inode ID and state.
329
+ * State is one of: "Active", "Pending", "Removing"
330
+ */
331
+ listDelegations(): Array<DelegationInfo>
332
+ }
package/index.js ADDED
@@ -0,0 +1,317 @@
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, 'archildata-client.android-arm64.node'))
36
+ try {
37
+ if (localFileExisted) {
38
+ nativeBinding = require('./archildata-client.android-arm64.node')
39
+ } else {
40
+ nativeBinding = require('@archildata/client-android-arm64')
41
+ }
42
+ } catch (e) {
43
+ loadError = e
44
+ }
45
+ break
46
+ case 'arm':
47
+ localFileExisted = existsSync(join(__dirname, 'archildata-client.android-arm-eabi.node'))
48
+ try {
49
+ if (localFileExisted) {
50
+ nativeBinding = require('./archildata-client.android-arm-eabi.node')
51
+ } else {
52
+ nativeBinding = require('@archildata/client-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, 'archildata-client.win32-x64-msvc.node')
67
+ )
68
+ try {
69
+ if (localFileExisted) {
70
+ nativeBinding = require('./archildata-client.win32-x64-msvc.node')
71
+ } else {
72
+ nativeBinding = require('@archildata/client-win32-x64-msvc')
73
+ }
74
+ } catch (e) {
75
+ loadError = e
76
+ }
77
+ break
78
+ case 'ia32':
79
+ localFileExisted = existsSync(
80
+ join(__dirname, 'archildata-client.win32-ia32-msvc.node')
81
+ )
82
+ try {
83
+ if (localFileExisted) {
84
+ nativeBinding = require('./archildata-client.win32-ia32-msvc.node')
85
+ } else {
86
+ nativeBinding = require('@archildata/client-win32-ia32-msvc')
87
+ }
88
+ } catch (e) {
89
+ loadError = e
90
+ }
91
+ break
92
+ case 'arm64':
93
+ localFileExisted = existsSync(
94
+ join(__dirname, 'archildata-client.win32-arm64-msvc.node')
95
+ )
96
+ try {
97
+ if (localFileExisted) {
98
+ nativeBinding = require('./archildata-client.win32-arm64-msvc.node')
99
+ } else {
100
+ nativeBinding = require('@archildata/client-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, 'archildata-client.darwin-universal.node'))
112
+ try {
113
+ if (localFileExisted) {
114
+ nativeBinding = require('./archildata-client.darwin-universal.node')
115
+ } else {
116
+ nativeBinding = require('@archildata/client-darwin-universal')
117
+ }
118
+ break
119
+ } catch {}
120
+ switch (arch) {
121
+ case 'x64':
122
+ localFileExisted = existsSync(join(__dirname, 'archildata-client.darwin-x64.node'))
123
+ try {
124
+ if (localFileExisted) {
125
+ nativeBinding = require('./archildata-client.darwin-x64.node')
126
+ } else {
127
+ nativeBinding = require('@archildata/client-darwin-x64')
128
+ }
129
+ } catch (e) {
130
+ loadError = e
131
+ }
132
+ break
133
+ case 'arm64':
134
+ localFileExisted = existsSync(
135
+ join(__dirname, 'archildata-client.darwin-arm64.node')
136
+ )
137
+ try {
138
+ if (localFileExisted) {
139
+ nativeBinding = require('./archildata-client.darwin-arm64.node')
140
+ } else {
141
+ nativeBinding = require('@archildata/client-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, 'archildata-client.freebsd-x64.node'))
156
+ try {
157
+ if (localFileExisted) {
158
+ nativeBinding = require('./archildata-client.freebsd-x64.node')
159
+ } else {
160
+ nativeBinding = require('@archildata/client-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, 'archildata-client.linux-x64-musl.node')
172
+ )
173
+ try {
174
+ if (localFileExisted) {
175
+ nativeBinding = require('./archildata-client.linux-x64-musl.node')
176
+ } else {
177
+ nativeBinding = require('@archildata/client-linux-x64-musl')
178
+ }
179
+ } catch (e) {
180
+ loadError = e
181
+ }
182
+ } else {
183
+ localFileExisted = existsSync(
184
+ join(__dirname, 'archildata-client.linux-x64-gnu.node')
185
+ )
186
+ try {
187
+ if (localFileExisted) {
188
+ nativeBinding = require('./archildata-client.linux-x64-gnu.node')
189
+ } else {
190
+ nativeBinding = require('@archildata/client-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, 'archildata-client.linux-arm64-musl.node')
201
+ )
202
+ try {
203
+ if (localFileExisted) {
204
+ nativeBinding = require('./archildata-client.linux-arm64-musl.node')
205
+ } else {
206
+ nativeBinding = require('@archildata/client-linux-arm64-musl')
207
+ }
208
+ } catch (e) {
209
+ loadError = e
210
+ }
211
+ } else {
212
+ localFileExisted = existsSync(
213
+ join(__dirname, 'archildata-client.linux-arm64-gnu.node')
214
+ )
215
+ try {
216
+ if (localFileExisted) {
217
+ nativeBinding = require('./archildata-client.linux-arm64-gnu.node')
218
+ } else {
219
+ nativeBinding = require('@archildata/client-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, 'archildata-client.linux-arm-musleabihf.node')
230
+ )
231
+ try {
232
+ if (localFileExisted) {
233
+ nativeBinding = require('./archildata-client.linux-arm-musleabihf.node')
234
+ } else {
235
+ nativeBinding = require('@archildata/client-linux-arm-musleabihf')
236
+ }
237
+ } catch (e) {
238
+ loadError = e
239
+ }
240
+ } else {
241
+ localFileExisted = existsSync(
242
+ join(__dirname, 'archildata-client.linux-arm-gnueabihf.node')
243
+ )
244
+ try {
245
+ if (localFileExisted) {
246
+ nativeBinding = require('./archildata-client.linux-arm-gnueabihf.node')
247
+ } else {
248
+ nativeBinding = require('@archildata/client-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, 'archildata-client.linux-riscv64-musl.node')
259
+ )
260
+ try {
261
+ if (localFileExisted) {
262
+ nativeBinding = require('./archildata-client.linux-riscv64-musl.node')
263
+ } else {
264
+ nativeBinding = require('@archildata/client-linux-riscv64-musl')
265
+ }
266
+ } catch (e) {
267
+ loadError = e
268
+ }
269
+ } else {
270
+ localFileExisted = existsSync(
271
+ join(__dirname, 'archildata-client.linux-riscv64-gnu.node')
272
+ )
273
+ try {
274
+ if (localFileExisted) {
275
+ nativeBinding = require('./archildata-client.linux-riscv64-gnu.node')
276
+ } else {
277
+ nativeBinding = require('@archildata/client-linux-riscv64-gnu')
278
+ }
279
+ } catch (e) {
280
+ loadError = e
281
+ }
282
+ }
283
+ break
284
+ case 's390x':
285
+ localFileExisted = existsSync(
286
+ join(__dirname, 'archildata-client.linux-s390x-gnu.node')
287
+ )
288
+ try {
289
+ if (localFileExisted) {
290
+ nativeBinding = require('./archildata-client.linux-s390x-gnu.node')
291
+ } else {
292
+ nativeBinding = require('@archildata/client-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 { initLogging, ArchilClient, JsInodeType } = nativeBinding
314
+
315
+ module.exports.initLogging = initLogging
316
+ module.exports.ArchilClient = ArchilClient
317
+ module.exports.JsInodeType = JsInodeType
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@archildata/client",
3
+ "version": "0.1.0",
4
+ "description": "High-performance Node.js client for Archil distributed filesystem",
5
+ "main": "index.js",
6
+ "types": "index.d.ts",
7
+ "napi": {
8
+ "name": "archildata-client",
9
+ "triples": {
10
+ "defaults": true,
11
+ "additional": [
12
+ "aarch64-apple-darwin",
13
+ "aarch64-unknown-linux-gnu",
14
+ "x86_64-apple-darwin",
15
+ "x86_64-unknown-linux-gnu"
16
+ ]
17
+ }
18
+ },
19
+ "license": "UNLICENSED",
20
+ "devDependencies": {
21
+ "@napi-rs/cli": "^2.18.0"
22
+ },
23
+ "engines": {
24
+ "node": ">= 18"
25
+ },
26
+ "scripts": {
27
+ "artifacts": "napi artifacts",
28
+ "build": "napi build --platform --release",
29
+ "build:debug": "napi build --platform",
30
+ "prepublishOnly": "napi prepublish -t npm",
31
+ "test": "node --test test/*.js",
32
+ "universal": "napi universal",
33
+ "version": "napi version"
34
+ },
35
+ "files": [
36
+ "index.js",
37
+ "index.d.ts",
38
+ "*.node"
39
+ ],
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "https://github.com/archil-io/archil"
43
+ },
44
+ "keywords": [
45
+ "archil",
46
+ "filesystem",
47
+ "distributed",
48
+ "napi",
49
+ "native"
50
+ ],
51
+ "optionalDependencies": {
52
+ "@archildata/client-win32-x64-msvc": "0.1.0",
53
+ "@archildata/client-darwin-x64": "0.1.0",
54
+ "@archildata/client-linux-x64-gnu": "0.1.0",
55
+ "@archildata/client-darwin-arm64": "0.1.0",
56
+ "@archildata/client-linux-arm64-gnu": "0.1.0"
57
+ }
58
+ }