xrootd 0.2.3 → 1.0.0-beta.1

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.
Files changed (62) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/LICENSE +189 -0
  3. package/README.md +334 -101
  4. package/dist/index.d.mts +620 -821
  5. package/dist/index.mjs +1554 -723
  6. package/package.json +65 -83
  7. package/LICENSE-GPLv3 +0 -674
  8. package/LICENSE-MIT +0 -7
  9. package/dist/index.cjs +0 -817
  10. package/dist/index.d.cts +0 -864
  11. package/libs/darwin-arm64/libXrdCl.6.dylib +0 -0
  12. package/libs/darwin-arm64/libXrdCrypto.6.dylib +0 -0
  13. package/libs/darwin-arm64/libXrdCryptossl-6.so +0 -0
  14. package/libs/darwin-arm64/libXrdSec-6.so +0 -0
  15. package/libs/darwin-arm64/libXrdSecProt-6.so +0 -0
  16. package/libs/darwin-arm64/libXrdSeckrb5-6.so +0 -0
  17. package/libs/darwin-arm64/libXrdSecpwd-6.so +0 -0
  18. package/libs/darwin-arm64/libXrdSecsss-6.so +0 -0
  19. package/libs/darwin-arm64/libXrdSecunix-6.so +0 -0
  20. package/libs/darwin-arm64/libXrdSecztn-6.so +0 -0
  21. package/libs/darwin-arm64/libXrdUtils.6.dylib +0 -0
  22. package/libs/darwin-arm64/libXrdXml.6.dylib +0 -0
  23. package/libs/darwin-x64/libXrdCl.6.dylib +0 -0
  24. package/libs/darwin-x64/libXrdCrypto.6.dylib +0 -0
  25. package/libs/darwin-x64/libXrdCryptossl-6.so +0 -0
  26. package/libs/darwin-x64/libXrdSec-6.so +0 -0
  27. package/libs/darwin-x64/libXrdSecProt-6.so +0 -0
  28. package/libs/darwin-x64/libXrdSeckrb5-6.so +0 -0
  29. package/libs/darwin-x64/libXrdSecpwd-6.so +0 -0
  30. package/libs/darwin-x64/libXrdSecsss-6.so +0 -0
  31. package/libs/darwin-x64/libXrdSecunix-6.so +0 -0
  32. package/libs/darwin-x64/libXrdSecztn-6.so +0 -0
  33. package/libs/darwin-x64/libXrdUtils.6.dylib +0 -0
  34. package/libs/darwin-x64/libXrdXml.6.dylib +0 -0
  35. package/libs/linux-arm64/libXrdCl.so.6 +0 -0
  36. package/libs/linux-arm64/libXrdCrypto.so.6 +0 -0
  37. package/libs/linux-arm64/libXrdCryptossl-6.so +0 -0
  38. package/libs/linux-arm64/libXrdSec-6.so +0 -0
  39. package/libs/linux-arm64/libXrdSecProt-6.so +0 -0
  40. package/libs/linux-arm64/libXrdSeckrb5-6.so +0 -0
  41. package/libs/linux-arm64/libXrdSecpwd-6.so +0 -0
  42. package/libs/linux-arm64/libXrdSecsss-6.so +0 -0
  43. package/libs/linux-arm64/libXrdSecunix-6.so +0 -0
  44. package/libs/linux-arm64/libXrdSecztn-6.so +0 -0
  45. package/libs/linux-arm64/libXrdUtils.so.6 +0 -0
  46. package/libs/linux-arm64/libXrdXml.so.6 +0 -0
  47. package/libs/linux-x64/libXrdCl.so.6 +0 -0
  48. package/libs/linux-x64/libXrdCrypto.so.6 +0 -0
  49. package/libs/linux-x64/libXrdCryptossl-6.so +0 -0
  50. package/libs/linux-x64/libXrdSec-6.so +0 -0
  51. package/libs/linux-x64/libXrdSecProt-6.so +0 -0
  52. package/libs/linux-x64/libXrdSeckrb5-6.so +0 -0
  53. package/libs/linux-x64/libXrdSecpwd-6.so +0 -0
  54. package/libs/linux-x64/libXrdSecsss-6.so +0 -0
  55. package/libs/linux-x64/libXrdSecunix-6.so +0 -0
  56. package/libs/linux-x64/libXrdSecztn-6.so +0 -0
  57. package/libs/linux-x64/libXrdUtils.so.6 +0 -0
  58. package/libs/linux-x64/libXrdXml.so.6 +0 -0
  59. package/prebuilds/darwin-arm64/xrootd.node +0 -0
  60. package/prebuilds/darwin-x64/xrootd.node +0 -0
  61. package/prebuilds/linux-arm64/xrootd.node +0 -0
  62. package/prebuilds/linux-x64/xrootd.node +0 -0
package/README.md CHANGED
@@ -1,150 +1,383 @@
1
- # XRootD TypeScript Support
1
+ # xrootd
2
2
 
3
- A high-performance, enterprise-grade Node.js binding for the [XRootD](https://github.com/xrootd/xrootd) client library. Designed to bring seamless, extreme-throughput data access to the TypeScript ecosystem.
3
+ A TypeScript client library for the [XRootD](https://xrootd.org) protocol.
4
4
 
5
- Github Repo: [**Wu-Yijun/xrootd**](https://github.com/Wu-Yijun/xrootd); NPM package: [**XRootD**](https://www.npmjs.com/package/xrootd)
5
+ XRootD (eXtended ROOT Daemon) is a high-performance, fault-tolerant protocol for accessing and managing large-scale distributed storage systems. It is widely used in High Energy Physics (HEP) for data access at facilities like CERN's LHC experiments.
6
6
 
7
- > [!NOTE]
8
- > 🚀 Exciting News: A pure Node.js implementation is coming!
9
- > We are rewriting xrootd in pure native Node.js to eliminate C++ compilation (node-gyp) issues. You can try the beta version now:
10
- > ```bash
11
- > npm install xrootd@next
12
- > ```
13
- > Feedback is highly appreciated!
7
+ > **🚀 v2.0.0 is Here: A Modern, Native Rewrite!**
8
+ > ⚠️ **Breaking Changes**: Because of the fundamental architecture shift, **v2 is not API-compatible with v1**.
9
+ > Please read our [Migration Guide (MIGRATING.md)](MIGRATING.md) to upgrade.
14
10
 
15
- ## Supported Capabilities
11
+ ## Installation
16
12
 
17
- * **`FileSystem`**: Cluster-level operations (`stat`, `dirList`, `rm`, `mkdir`, `locate`).
18
- * **`File`**: High-performance I/O (`open`, `read`, `write`, `vectorRead`, server-side `clone`).
19
- * **`CopyProcess`**: Asynchronous, highly-parallel data transfers with real-time progress callbacks.
20
- * **`Env`**: Type-safe configuration management and OS-level auth protocol routing.
21
- * **`Url`**: XRootD-specific URI scheme parsing and validation.
13
+ ```sh
14
+ npm install xrootd
15
+ ```
22
16
 
17
+ ## Quick Start
23
18
 
24
- ## Prerequisites
19
+ ```ts
20
+ import { XRootDClient, OpenFlags } from 'xrootd'
25
21
 
26
- To ensure compatibility with the pre-compiled native bindings, your environment must meet the following requirements:
22
+ const client = new XRootDClient('root://server.example.com')
23
+ await client.connect()
27
24
 
28
- * **Node.js**: Version 20.x or higher.
29
- * **System Dependencies (Linux)**: Requires `libstdc++` providing `GLIBCXX_3.4.26` or newer (typically GCC 9+, e.g., CentOS 9 / Ubuntu 20.04+).
30
- * **System Dependencies (Macos)**: Requires macos 14 or later for arm64 architecture, macos 15 or later for intel architecture.
31
- * **Authentication**: Ensure your host machine has valid tickets (e.g., `kinit` for Kerberos) if accessing a secured cluster.
25
+ // List directory contents
26
+ const list = await client.readdir('/data')
27
+ for (const entry of list.entries) {
28
+ console.log(entry.name, entry.size)
29
+ }
32
30
 
31
+ // Read a file
32
+ const file = await client.open('/data/file.dat')
33
+ const data = await file.read(0, 1024)
34
+ await file.close()
33
35
 
34
- ## Installation
36
+ // Write a file
37
+ const file2 = await client.open('/data/output.dat', { flags: OpenFlags.Write | OpenFlags.New })
38
+ await file2.write(0, new Uint8Array([72, 101, 108, 108, 111]))
39
+ await file2.close()
35
40
 
36
- ```bash
37
- npm install xrootd
38
- # or
39
- yarn add xrootd
41
+ await client.close()
42
+ ```
43
+
44
+ ## API
45
+
46
+ ### XRootDClient
40
47
 
48
+ High-level client that manages connection, authentication, and automatic redirect handling.
49
+
50
+ ```ts
51
+ import { XRootDClient, OpenFlags } from 'xrootd'
52
+
53
+ const client = new XRootDClient('root://server.example.com', {
54
+ credentials: { username: 'user', password: 'pass' },
55
+ timeout: 30000,
56
+ maxRedirects: 16,
57
+ })
58
+
59
+ await client.connect()
60
+
61
+ // Connection state
62
+ console.log(client.isConnected) // boolean
63
+ console.log(client.location) // "root://server.example.com:1094/"
64
+
65
+ // File operations
66
+ const file = await client.open('/data/file.dat', { flags: OpenFlags.Read })
67
+ const data = await file.read(0, 1024)
68
+ await file.close()
69
+
70
+ // Filesystem operations
71
+ await client.mkdir('/new/dir')
72
+ const list = await client.readdir('/data')
73
+ await client.mv('/old/path', '/new/path')
74
+ await client.rm('/old/file')
75
+ await client.rmdir('/old/dir')
76
+
77
+ // Metadata — two approaches
78
+ const info1 = await client.stat('/data/file.dat') // opens + stats + closes
79
+ const info2 = await client.statFilesystem('/data/file.dat') // filesystem protocol, no file open
80
+
81
+ await client.close()
41
82
  ```
42
83
 
43
- ---
84
+ ### File
44
85
 
45
- ## Usage Examples
86
+ File operations for reading, writing, and managing files on XRootD servers.
46
87
 
47
- ### 1. Configuration & Basic FileSystem
88
+ Obtained via `client.open()` do not construct directly.
48
89
 
49
- ```typescript
50
- import { Env, FileSystem } from 'xrootd';
90
+ ```ts
91
+ // Open a file
92
+ const file = await client.open('/data/file.dat', { flags: OpenFlags.Read })
51
93
 
52
- // Safely configure underlying XRootD environment
53
- Env.configure({
54
- RequestTimeout: 30, // Prevent 30-min infinite hangs (Node.js friendly)
55
- WorkerThreads: 4, // Boost underlying multiplexing
56
- SecProtocol: 'krb5,unix' // Force Kerberos or Unix socket auth
57
- });
94
+ // Core operations
95
+ const data: Uint8Array = await file.read(offset, size)
96
+ const written: number = await file.write(offset, data)
97
+ const info: StatInfo = await file.stat()
98
+ await file.sync()
99
+ await file.truncate(size)
100
+ await file.close()
101
+ ```
102
+
103
+ ### FileSystem
104
+
105
+ Stateless filesystem metadata operations:
106
+
107
+ ```ts
108
+ import { FileSystem } from 'xrootd'
109
+
110
+ // Obtained internally by XRootDClient; shown here for reference
111
+ const fs = new FileSystem(mux)
112
+
113
+ // Metadata
114
+ const info = await fs.stat('/data/file.dat')
115
+ console.log(info.size, info.mtime, info.isDirectory)
116
+
117
+ // Directory operations
118
+ await fs.mkdir('/new/dir')
119
+ const list = await fs.readdir('/data')
120
+ await fs.mv('/old/path', '/new/path')
121
+ await fs.rm('/old/file')
122
+ await fs.rmdir('/old/dir')
123
+ ```
124
+
125
+ ### Authentication
126
+
127
+ XRootD supports multiple authentication mechanisms. The library automatically negotiates the best available protocol during handshake.
128
+
129
+ #### Supported Protocols
130
+
131
+ | Protocol | Description |
132
+ |----------|-------------|
133
+ | `host` | Host-based trust authentication (IP whitelist) |
134
+ | `sss` | Simple Shared Secret (Blowfish-ECB encrypted password) |
135
+
136
+ #### Configuration
137
+
138
+ ```ts
139
+ import { XRootDClient } from 'xrootd'
140
+
141
+ // host authentication (server trusts client by IP)
142
+ const client = new XRootDClient('root://server.example.com', {
143
+ credentials: { username: 'user' },
144
+ })
145
+
146
+ // SSS authentication (shared secret)
147
+ const client = new XRootDClient('root://server.example.com', {
148
+ credentials: {
149
+ username: 'user',
150
+ password: 'shared-secret',
151
+ },
152
+ })
153
+
154
+ await client.connect()
155
+ ```
58
156
 
59
- const fs = new FileSystem('root://eos01.ihep.ac.cn/');
157
+ When connecting to a server that requires authentication, the client will automatically:
60
158
 
61
- async function checkCluster() {
62
- try {
63
- const stat = await fs.stat('/eos/lhaaso/data');
64
- console.log(`Directory size: ${stat.size} bytes`);
65
- console.log(`Modified at: ${stat.modTimeAsString}`);
66
- } catch (err: any) {
67
- if (err.code === 'ENOENT') {
68
- console.error('File not found in cluster.');
69
- } else {
70
- console.error(err.message);
71
- }
72
- }
159
+ 1. Receive the server's supported authentication protocols (`secReqs`)
160
+ 2. Select the first matching protocol from the list
161
+ 3. Execute the authentication handshake (including multi-round `kXR_authmore` challenges)
162
+
163
+ ### Error Handling
164
+
165
+ All errors are thrown as `XRootDError` instances:
166
+
167
+ ```ts
168
+ import { XRootDClient, OpenFlags, XRootDError } from 'xrootd'
169
+
170
+ const client = new XRootDClient('root://server.example.com')
171
+ await client.connect()
172
+
173
+ try {
174
+ const file = await client.open('/nonexistent', { flags: OpenFlags.Read })
175
+ await file.read(0, 1024)
176
+ await file.close()
177
+ } catch (err) {
178
+ if (err instanceof XRootDError) {
179
+ console.log(err.code) // 3011 (NotFound)
180
+ console.log(err.message) // "File not found"
181
+ console.log(err.errno) // POSIX errno (if applicable)
182
+ }
183
+ }
184
+ ```
185
+
186
+ #### Common Error Codes
187
+
188
+ | Code | Constant | Description |
189
+ |------|----------|-------------|
190
+ | 3010 | `NotAuthorized` | Permission denied |
191
+ | 3011 | `NotFound` | File or directory not found |
192
+ | 3016 | `IsDirectory` | Expected file, got directory |
193
+ | 3018 | `ItExists` | File already exists (e.g. mkdir on existing path) |
194
+ | 3030 | `AuthFailed` | Authentication failed |
195
+
196
+ #### Client-side Error Codes
197
+
198
+ | Code | Constant | Description |
199
+ |------|----------|-------------|
200
+ | 309 | `Timeout` | Request timed out |
201
+ | 312 | `Disconnected` | Connection closed unexpectedly |
202
+ | 315 | `TooManyRedirs` | Exceeded maximum redirect count |
203
+
204
+ ### Types
205
+
206
+ ```ts
207
+ interface StatInfo {
208
+ id: string // opaque device id (string to avoid precision loss)
209
+ size: bigint // file size in bytes (bigint for >4GB files)
210
+ flags: number // XRootD server flags
211
+ mtime: number // modification time (epoch seconds)
212
+ ctime: number // change time (epoch seconds)
213
+ atime: number // access time (epoch seconds)
214
+ mode: number // POSIX mode (e.g. 0o100644)
215
+ owner: string // file owner
216
+ group: string // file group
217
+ get isDirectory(): boolean
218
+ get isLink(): boolean
219
+ get isOffline(): boolean
220
+ get isCached(): boolean
73
221
  }
74
222
 
223
+ interface DirectoryEntry {
224
+ name: string
225
+ size: number
226
+ flags: number
227
+ mtime: number
228
+ }
229
+
230
+ interface DirectoryList {
231
+ name: string
232
+ entries: DirectoryEntry[]
233
+ }
234
+
235
+ const enum OpenFlags {
236
+ Compress = 0x0001,
237
+ Delete = 0x0002,
238
+ Force = 0x0004,
239
+ New = 0x0008,
240
+ Read = 0x0010,
241
+ Write = 0x0020,
242
+ Async = 0x0040,
243
+ Refresh = 0x0080,
244
+ Mkpath = 0x0100,
245
+ Append = 0x0200,
246
+ Retstat = 0x0400,
247
+ Replica = 0x0800,
248
+ Posc = 0x1000,
249
+ Nowait = 0x2000,
250
+ Seqio = 0x4000,
251
+ Wrto = 0x8000,
252
+ }
75
253
  ```
76
254
 
77
- ### 2. Zero-Copy File Reading
255
+ #### OpenOptions
78
256
 
79
- ```typescript
80
- import { File, OpenFlags } from 'xrootd';
257
+ ```ts
258
+ interface OpenOptions {
259
+ flags?: OpenFlags // file open flags (default: OpenFlags.Read)
260
+ mode?: number // POSIX mode (default: 0)
261
+ signal?: AbortSignal // cancellation signal
262
+ }
263
+ ```
81
264
 
82
- async function readHeader() {
83
- const file = new File();
84
-
85
- // Auto-translates and handles C++ lifecycle
86
- await file.open('root://eos01.ihep.ac.cn//eos/test.dat', OpenFlags.Read);
87
-
88
- // The returned buffer is a zero-copy mapping of C++ allocated memory
89
- const buffer = await file.read(0n, 1024);
90
- console.log(buffer.toString('utf-8'));
91
-
92
- await file.close();
265
+ #### StatFlags
266
+
267
+ ```ts
268
+ const StatFlags = {
269
+ XBitSet: 1,
270
+ IsDir: 2,
271
+ Other: 4,
272
+ Offline: 8,
273
+ Readable: 16,
274
+ Writable: 32,
275
+ POSCPending: 64,
276
+ BackUpExists: 128,
277
+ CacheResp: 512,
93
278
  }
279
+ ```
280
+
281
+ ### Redirect Handling
94
282
 
283
+ The client automatically handles server redirects. When a server responds with `kXR_redirect`, the client:
284
+
285
+ 1. Closes the current connection
286
+ 2. Connects to the new target server
287
+ 3. Re-executes the handshake and authentication
288
+ 4. Retries the original request
289
+
290
+ ```ts
291
+ const client = new XRootDClient('root://server.example.com', {
292
+ maxRedirects: 16, // default
293
+ })
95
294
  ```
96
295
 
97
- ### 3. High-Performance CopyProcess with Progress
296
+ ## Architecture
98
297
 
99
- ```typescript
100
- import { CopyProcess } from 'xrootd';
298
+ The library uses a three-layer architecture, simplified from the original C++ XrdCl's five-layer design:
101
299
 
102
- async function syncData() {
103
- const cp = new CopyProcess();
104
-
105
- cp.addJob({
106
- source: 'root://eos01.ihep.ac.cn//eos/data.raw',
107
- target: '/local/disk/data.raw',
108
- force: true,
109
- parallelChunks: 4
110
- });
300
+ ```
301
+ ┌──────────────────────────────────────────────────┐
302
+ │ Layer 3: Multiplexer │
303
+ │ streamId → Promise mapping, timeout management │
304
+ │ + automatic redirect interception │
305
+ ├──────────────────────────────────────────────────┤
306
+ │ Layer 2: Framer │
307
+ │ TCP packet reassembly, Header+Body framing │
308
+ ├──────────────────────────────────────────────────┤
309
+ │ Layer 1: Transport │
310
+ │ net.Socket wrapper, binary data I/O │
311
+ └──────────────────────────────────────────────────┘
312
+ ```
111
313
 
112
- await cp.prepare();
113
-
114
- const results = await cp.run((jobNum, processed, total) => {
115
- const percent = ((processed / total) * 100).toFixed(2);
116
- console.log(`Job ${jobNum} Progress: ${percent}%`);
117
- });
314
+ | C++ Original | TypeScript |
315
+ |--------------|-----------|
316
+ | 138 files, ~15,000 lines | ~25 files, ~3,000 lines |
317
+ | Callbacks + state machines | async/await |
318
+ | Error code checking | throw XRootDError |
319
+ | 5-layer abstraction | 3-layer streamlined architecture |
320
+ | Multiple auth plugins | Pluggable SecurityProtocol interface |
118
321
 
119
- console.log('Copy completed:', results);
120
- }
322
+ ## Development
121
323
 
324
+ ### Prerequisites
325
+
326
+ - Node.js >= 22
327
+ - pnpm
328
+
329
+ ### Setup
330
+
331
+ ```sh
332
+ pnpm install
122
333
  ```
123
334
 
124
- ## Why `xrootd`? (Core Architecture)
335
+ ### Mock Server
125
336
 
126
- Unlike traditional Node.js C++ addons, `xrootd` is architected for **High Energy Physics (HEP)** and **Big Data** workloads:
337
+ A Docker-based XRootD mock server is available for integration testing:
127
338
 
128
- * **True Native Async**: Bypasses the notoriously limited Node.js `libuv` thread pool (default 4 threads). It hooks directly into XRootD's underlying C++ event loop via N-API `ThreadSafeFunction`, allowing thousands of concurrent requests without blocking the V8 engine.
129
- * **Absolute Zero-Copy I/O**: Implements direct memory handoffs. Data read from the EOS cluster is mounted directly as V8 `Buffer` objects without a single byte of internal memory copying, completely eliminating GC (Garbage Collection) pauses during heavy I/O.
130
- * **Idiomatic Node.js Experience**: "Thin C++, Thick TS". Complex XRootD protocol errors (e.g., `3011`) are smartly translated into standard Node.js exceptions (e.g., `ENOENT`, `EACCES`), complete with system call contexts and retryable flags.
131
- * **Zero-Config Authentication**: Bundles essential security plugins (Kerberos, SSS, Unix, Token) natively. Path injection is handled automatically under the hood—no more `[FATAL] Auth failed` or missing `.so` nightmares.
339
+ ```sh
340
+ # Start mock server
341
+ pnpm mock-server:up
132
342
 
133
- ---
343
+ # Verify it's running
344
+ pnpm mock-server:verify
134
345
 
135
- ## Licensing
346
+ # View logs
347
+ pnpm mock-server:logs
136
348
 
137
- This project is released under a **Dual License** strategy to balance open-source compatibility and developer freedom:
349
+ # Stop
350
+ pnpm mock-server:down
351
+ ```
138
352
 
139
- 1. **[GNU GPLv3](LICENSE-GPLv3)**: The native binding codebase adheres to the GPLv3 license to remain fully compatible with the upstream C++ XRootD project.
140
- 2. **[MIT](LICENSE-MIT)**: The core TypeScript APIs, interface definitions, and glue layers are provided under the MIT license, allowing you to integrate the TS components into your own software architectures without viral restrictive requirements.
353
+ ### Build
354
+
355
+ ```sh
356
+ pnpm build
357
+ ```
358
+
359
+ ### Type Check
360
+
361
+ ```sh
362
+ pnpm typecheck
363
+ ```
364
+
365
+ ### Test
366
+
367
+ ```sh
368
+ pnpm test
369
+ ```
141
370
 
142
- *Disclaimer: This project is a third-party community initiative built for modern web ecosystems and is not affiliated with, officially endorsed by, or sponsored by the core XRootD project.*
371
+ ## Documentation
143
372
 
144
- ---
373
+ - [Migration Design](docs/migration.md) — Full protocol analysis and architecture design
374
+ - [TypeScript API Design](docs/typescript-design.md) — Detailed API specifications
375
+ - [Work Plan](docs/work-plan.md) — Implementation roadmap
376
+ - [Phase 2 Plan](docs/phase2.md) — Complete API, fault tolerance, and authentication
377
+ - [Rust Future Optimizations](docs/rust-future-optimizations.md) — Performance optimizations deferred to Rust version
145
378
 
146
- ## Contributing
379
+ ## License
147
380
 
148
- We welcome contributions from the high-energy physics, astrophysics, and Node.js communities! Whether it's reporting bugs, improving documentation, or adding support for advanced XRootD features.
381
+ This project is licensed under the [GNU Lesser General Public License v3.0 or later](LICENSE).
149
382
 
150
- *Contribution guidelines coming soon.*
383
+ This is an independent TypeScript implementation of the XRootD protocol. The original XRootD project is developed by the Board of Trustees of the Leland Stanford, Jr. University and is licensed under LGPL-3.0-or-later.