xrootd 0.2.2 → 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 +333 -96
  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,146 +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
- > **Work in Progress**: This package is currently under active development with some features not supported yet. While core features are highly functional, the API may undergo refinements. Api interfaces are not tests thoroughly so it may be unstable.
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.
9
10
 
11
+ ## Installation
10
12
 
11
- ## Supported Capabilities
13
+ ```sh
14
+ npm install xrootd
15
+ ```
12
16
 
13
- * **`FileSystem`**: Cluster-level operations (`stat`, `dirList`, `rm`, `mkdir`, `locate`).
14
- * **`File`**: High-performance I/O (`open`, `read`, `write`, `vectorRead`, server-side `clone`).
15
- * **`CopyProcess`**: Asynchronous, highly-parallel data transfers with real-time progress callbacks.
16
- * **`Env`**: Type-safe configuration management and OS-level auth protocol routing.
17
- * **`Url`**: XRootD-specific URI scheme parsing and validation.
17
+ ## Quick Start
18
18
 
19
+ ```ts
20
+ import { XRootDClient, OpenFlags } from 'xrootd'
19
21
 
20
- ## Prerequisites
22
+ const client = new XRootDClient('root://server.example.com')
23
+ await client.connect()
21
24
 
22
- To ensure compatibility with the pre-compiled native bindings, your environment must meet the following requirements:
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
+ }
23
30
 
24
- * **Node.js**: Version 20.x or higher.
25
- * **System Dependencies (Linux)**: Requires `libstdc++` providing `GLIBCXX_3.4.26` or newer (typically GCC 9+, e.g., CentOS 9 / Ubuntu 20.04+).
26
- * **System Dependencies (Macos)**: Requires macos 14 or later for arm64 architecture, macos 15 or later for intel architecture.
27
- * **Authentication**: Ensure your host machine has valid tickets (e.g., `kinit` for Kerberos) if accessing a secured cluster.
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()
28
35
 
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()
29
40
 
30
- ## Installation
41
+ await client.close()
42
+ ```
31
43
 
32
- ```bash
33
- npm install xrootd
34
- # or
35
- yarn add xrootd
44
+ ## API
45
+
46
+ ### XRootDClient
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()
82
+ ```
83
+
84
+ ### File
85
+
86
+ File operations for reading, writing, and managing files on XRootD servers.
87
+
88
+ Obtained via `client.open()` — do not construct directly.
89
+
90
+ ```ts
91
+ // Open a file
92
+ const file = await client.open('/data/file.dat', { flags: OpenFlags.Read })
93
+
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
36
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()
37
155
  ```
38
156
 
39
- ---
157
+ When connecting to a server that requires authentication, the client will automatically:
40
158
 
41
- ## Usage Examples
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)
42
162
 
43
- ### 1. Configuration & Basic FileSystem
163
+ ### Error Handling
44
164
 
45
- ```typescript
46
- import { Env, FileSystem } from 'xrootd';
165
+ All errors are thrown as `XRootDError` instances:
47
166
 
48
- // Safely configure underlying XRootD environment
49
- Env.configure({
50
- RequestTimeout: 30, // Prevent 30-min infinite hangs (Node.js friendly)
51
- WorkerThreads: 4, // Boost underlying multiplexing
52
- SecProtocol: 'krb5,unix' // Force Kerberos or Unix socket auth
53
- });
167
+ ```ts
168
+ import { XRootDClient, OpenFlags, XRootDError } from 'xrootd'
54
169
 
55
- const fs = new FileSystem('root://eos01.ihep.ac.cn/');
170
+ const client = new XRootDClient('root://server.example.com')
171
+ await client.connect()
56
172
 
57
- async function checkCluster() {
58
- try {
59
- const stat = await fs.stat('/eos/lhaaso/data');
60
- console.log(`Directory size: ${stat.size} bytes`);
61
- console.log(`Modified at: ${stat.modTimeAsString}`);
62
- } catch (err: any) {
63
- if (err.code === 'ENOENT') {
64
- console.error('File not found in cluster.');
65
- } else {
66
- console.error(err.message);
67
- }
68
- }
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
69
221
  }
70
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
+ }
71
253
  ```
72
254
 
73
- ### 2. Zero-Copy File Reading
255
+ #### OpenOptions
74
256
 
75
- ```typescript
76
- 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
+ ```
77
264
 
78
- async function readHeader() {
79
- const file = new File();
80
-
81
- // Auto-translates and handles C++ lifecycle
82
- await file.open('root://eos01.ihep.ac.cn//eos/test.dat', OpenFlags.Read);
83
-
84
- // The returned buffer is a zero-copy mapping of C++ allocated memory
85
- const buffer = await file.read(0n, 1024);
86
- console.log(buffer.toString('utf-8'));
87
-
88
- 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,
89
278
  }
279
+ ```
280
+
281
+ ### Redirect Handling
90
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
+ })
91
294
  ```
92
295
 
93
- ### 3. High-Performance CopyProcess with Progress
296
+ ## Architecture
94
297
 
95
- ```typescript
96
- import { CopyProcess } from 'xrootd';
298
+ The library uses a three-layer architecture, simplified from the original C++ XrdCl's five-layer design:
97
299
 
98
- async function syncData() {
99
- const cp = new CopyProcess();
100
-
101
- cp.addJob({
102
- source: 'root://eos01.ihep.ac.cn//eos/data.raw',
103
- target: '/local/disk/data.raw',
104
- force: true,
105
- parallelChunks: 4
106
- });
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
+ ```
107
313
 
108
- await cp.prepare();
109
-
110
- const results = await cp.run((jobNum, processed, total) => {
111
- const percent = ((processed / total) * 100).toFixed(2);
112
- console.log(`Job ${jobNum} Progress: ${percent}%`);
113
- });
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 |
114
321
 
115
- console.log('Copy completed:', results);
116
- }
322
+ ## Development
117
323
 
324
+ ### Prerequisites
325
+
326
+ - Node.js >= 22
327
+ - pnpm
328
+
329
+ ### Setup
330
+
331
+ ```sh
332
+ pnpm install
118
333
  ```
119
334
 
120
- ## Why `xrootd`? (Core Architecture)
335
+ ### Mock Server
121
336
 
122
- 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:
123
338
 
124
- * **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.
125
- * **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.
126
- * **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.
127
- * **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
128
342
 
129
- ---
343
+ # Verify it's running
344
+ pnpm mock-server:verify
130
345
 
131
- ## Licensing
346
+ # View logs
347
+ pnpm mock-server:logs
132
348
 
133
- 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
+ ```
134
352
 
135
- 1. **[GNU GPLv3](LICENSE-GPLv3)**: The native binding codebase adheres to the GPLv3 license to remain fully compatible with the upstream C++ XRootD project.
136
- 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
+ ```
137
370
 
138
- *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
139
372
 
140
- ---
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
141
378
 
142
- ## Contributing
379
+ ## License
143
380
 
144
- 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).
145
382
 
146
- *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.