xrootd 0.1.11 → 0.2.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 +131 -10
- package/dist/index.cjs +170 -22
- package/dist/index.d.cts +433 -24
- package/dist/index.d.mts +433 -24
- package/dist/index.mjs +170 -23
- package/package.json +3 -4
- package/prebuilds/darwin-arm64/xrootd.node +0 -0
- package/prebuilds/darwin-x64/xrootd.node +0 -0
- package/prebuilds/linux-arm64/xrootd.node +0 -0
- package/prebuilds/linux-x64/xrootd.node +0 -0
package/dist/index.mjs
CHANGED
|
@@ -119,13 +119,20 @@ var File = class {
|
|
|
119
119
|
async read(offset, size) {
|
|
120
120
|
return this._internal.Read(BigInt(offset), size);
|
|
121
121
|
}
|
|
122
|
+
async write(offset, arg1, arg2, arg3) {
|
|
123
|
+
if (Buffer.isBuffer(arg1)) return this._internal.Write(BigInt(offset), arg1);
|
|
124
|
+
else if (typeof arg1 === "number" && typeof arg2 === "number") return this._internal.WriteFd(BigInt(offset), arg1, arg2, arg3 !== void 0 ? BigInt(arg3) : void 0);
|
|
125
|
+
else throw new TypeError("Invalid arguments for write");
|
|
126
|
+
}
|
|
122
127
|
/**
|
|
123
|
-
* 写入文件块
|
|
124
|
-
* @param offset
|
|
125
|
-
* @param
|
|
128
|
+
* 从本地 fd 写入文件块 (直接映射)
|
|
129
|
+
* @param offset 写入的起始字节偏移量。
|
|
130
|
+
* @param size 写入大小。
|
|
131
|
+
* @param fd 本地文件描述符 (fd)。
|
|
132
|
+
* @param fdoff 可选,从本地 fd 中读取的起始偏移。
|
|
126
133
|
*/
|
|
127
|
-
async
|
|
128
|
-
return this._internal.
|
|
134
|
+
async writeFd(offset, size, fd, fdoff) {
|
|
135
|
+
return this._internal.WriteFd(BigInt(offset), size, fd, fdoff !== void 0 ? BigInt(fdoff) : void 0);
|
|
129
136
|
}
|
|
130
137
|
/**
|
|
131
138
|
* 同步文件缓冲区到磁盘
|
|
@@ -147,7 +154,9 @@ var File = class {
|
|
|
147
154
|
return this._internal.IsOpen();
|
|
148
155
|
}
|
|
149
156
|
async getProperty(name) {
|
|
150
|
-
|
|
157
|
+
const ret = this._internal.GetProperty(name);
|
|
158
|
+
if (ret.success) return ret.value;
|
|
159
|
+
throw new Error("TODO");
|
|
151
160
|
}
|
|
152
161
|
async setProperty(name, value) {
|
|
153
162
|
return this._internal.SetProperty(name, value);
|
|
@@ -179,25 +188,37 @@ var File = class {
|
|
|
179
188
|
/**
|
|
180
189
|
* 设置文件的扩展属性
|
|
181
190
|
*/
|
|
182
|
-
async
|
|
183
|
-
return this._internal.SetXAttr(
|
|
191
|
+
async setXAttrs(attrs) {
|
|
192
|
+
return this._internal.SetXAttr(attrs);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* 设置文件的扩展属性
|
|
196
|
+
*/
|
|
197
|
+
async setXAttr(key, value) {
|
|
198
|
+
return (await this._internal.SetXAttr({ [key]: value }))[0].ok;
|
|
184
199
|
}
|
|
185
200
|
/**
|
|
186
201
|
* 获取文件的扩展属性
|
|
187
202
|
*/
|
|
188
|
-
async
|
|
189
|
-
return this._internal.GetXAttr(
|
|
203
|
+
async getXAttrs(keys) {
|
|
204
|
+
return this._internal.GetXAttr(keys);
|
|
205
|
+
}
|
|
206
|
+
async getXAttr(key) {
|
|
207
|
+
return (await this._internal.GetXAttr([key]))[key];
|
|
190
208
|
}
|
|
191
209
|
/**
|
|
192
210
|
* 删除文件的扩展属性
|
|
193
211
|
*/
|
|
194
|
-
async
|
|
195
|
-
return this._internal.DelXAttr(
|
|
212
|
+
async delXAttrs(keys) {
|
|
213
|
+
return this._internal.DelXAttr(keys);
|
|
214
|
+
}
|
|
215
|
+
async delXAttr(key) {
|
|
216
|
+
return (await this._internal.DelXAttr([key]))[0].ok;
|
|
196
217
|
}
|
|
197
218
|
/**
|
|
198
|
-
*
|
|
219
|
+
* 列出文件所有的扩展属性和内容
|
|
199
220
|
*/
|
|
200
|
-
async
|
|
221
|
+
async listXAttrs() {
|
|
201
222
|
return this._internal.ListXAttr();
|
|
202
223
|
}
|
|
203
224
|
/**
|
|
@@ -503,25 +524,34 @@ var FileSystem = class {
|
|
|
503
524
|
* @param targetPath 目标路径
|
|
504
525
|
* @param attrs 扩展属性键值对记录
|
|
505
526
|
*/
|
|
506
|
-
async
|
|
527
|
+
async setXAttrs(targetPath, attrs) {
|
|
507
528
|
return this._internal.SetXAttr(this._normalize(targetPath), attrs);
|
|
508
529
|
}
|
|
530
|
+
async setXAttr(targetPath, key, value) {
|
|
531
|
+
return (await this.setXAttrs(targetPath, { [key]: value }))[0].ok;
|
|
532
|
+
}
|
|
509
533
|
/**
|
|
510
534
|
* 获取扩展属性
|
|
511
535
|
* @param targetPath 目标路径
|
|
512
536
|
* @param keys 需要获取的属性名数组
|
|
513
537
|
*/
|
|
514
|
-
async
|
|
538
|
+
async getXAttrs(targetPath, keys) {
|
|
515
539
|
return this._internal.GetXAttr(this._normalize(targetPath), keys);
|
|
516
540
|
}
|
|
541
|
+
async getXAttr(targetPath, key) {
|
|
542
|
+
return (await this.getXAttrs(targetPath, [key]))[key];
|
|
543
|
+
}
|
|
517
544
|
/**
|
|
518
545
|
* 删除指定的扩展属性
|
|
519
546
|
* @param targetPath 目标路径
|
|
520
547
|
* @param keys 需要删除的属性名数组
|
|
521
548
|
*/
|
|
522
|
-
async
|
|
549
|
+
async delXAttrs(targetPath, keys) {
|
|
523
550
|
return this._internal.DelXAttr(this._normalize(targetPath), keys);
|
|
524
551
|
}
|
|
552
|
+
async delXAttr(targetPath, key) {
|
|
553
|
+
return (await this.delXAttrs(targetPath, [key]))[0].ok;
|
|
554
|
+
}
|
|
525
555
|
/**
|
|
526
556
|
* 列出目标文件或目录的所有扩展属性
|
|
527
557
|
*/
|
|
@@ -530,6 +560,47 @@ var FileSystem = class {
|
|
|
530
560
|
}
|
|
531
561
|
};
|
|
532
562
|
//#endregion
|
|
563
|
+
//#region lib/copy.ts
|
|
564
|
+
var CopyProcess = class {
|
|
565
|
+
nativeCp;
|
|
566
|
+
constructor() {
|
|
567
|
+
this.nativeCp = new nativeAddon.CopyProcess();
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Add a job to the copy process synchronously
|
|
571
|
+
*/
|
|
572
|
+
addJob(config) {
|
|
573
|
+
this.nativeCp.AddJob(config);
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Asynchronously prepare the jobs (resolve DNS, check endpoints, etc.)
|
|
577
|
+
*/
|
|
578
|
+
async prepare() {
|
|
579
|
+
return this.nativeCp.Prepare();
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Run the copy process.
|
|
583
|
+
* @param onProgress Optional progress callback
|
|
584
|
+
* @returns Array of results corresponding to the jobs added
|
|
585
|
+
*/
|
|
586
|
+
async run(onProgress) {
|
|
587
|
+
if (onProgress) this.nativeCp.SetEventListener("progress", onProgress);
|
|
588
|
+
return this.nativeCp.Run();
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Abort the running copy process.
|
|
592
|
+
*/
|
|
593
|
+
abort() {
|
|
594
|
+
this.nativeCp.CancelJob();
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Abort the running copy process. (alias for abort)
|
|
598
|
+
*/
|
|
599
|
+
cancelJob() {
|
|
600
|
+
this.nativeCp.CancelJob();
|
|
601
|
+
}
|
|
602
|
+
};
|
|
603
|
+
//#endregion
|
|
533
604
|
//#region lib/url.ts
|
|
534
605
|
/**
|
|
535
606
|
* 纯 TypeScript 实现的 XRootD URL 解析器
|
|
@@ -631,11 +702,87 @@ var XRootDUrl = class XRootDUrl {
|
|
|
631
702
|
};
|
|
632
703
|
//#endregion
|
|
633
704
|
//#region lib/env.ts
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
705
|
+
function checkIntRange(key, value) {
|
|
706
|
+
const num = Number(value);
|
|
707
|
+
if (num < -2147483648 || num > 2147483647) console.warn(`[xrootd] Warning: value ${value} for key "${key}" is out of 32-bit signed integer range [-2147483648, 2147483647]. It will be truncated.`);
|
|
708
|
+
}
|
|
709
|
+
var XRootDEnvironment = class {
|
|
710
|
+
constructor() {}
|
|
711
|
+
/**
|
|
712
|
+
* 设置整数配置项,返回是否设置成功。
|
|
713
|
+
*/
|
|
714
|
+
putInt(key, intVal) {
|
|
715
|
+
checkIntRange(key, intVal);
|
|
716
|
+
const success = nativeAddon.Env.PutInt(key, Number(intVal));
|
|
717
|
+
if (!success) console.warn(`[xrootd] Warning: Failed to set integer configuration "${key}"=${intVal}. It might have been overridden by a system environment variable.`);
|
|
718
|
+
return success;
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* 设置字符串配置项,返回是否设置成功。
|
|
722
|
+
*/
|
|
723
|
+
putString(key, strVal) {
|
|
724
|
+
if (key === "SecProtocol") {
|
|
725
|
+
process.env.XrdSecPROTOCOL = strVal;
|
|
726
|
+
process.env.XRD_SECPROTOCOL = strVal;
|
|
727
|
+
return true;
|
|
728
|
+
}
|
|
729
|
+
const success = nativeAddon.Env.PutString(key, strVal);
|
|
730
|
+
if (!success) console.warn(`[xrootd] Warning: Failed to set string configuration "${key}"="${strVal}". It might have been overridden by a system environment variable.`);
|
|
731
|
+
return success;
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* 设置布尔配置项,返回是否设置成功。
|
|
735
|
+
*/
|
|
736
|
+
putBoolean(key, boolVal) {
|
|
737
|
+
if (typeof boolVal === "boolean") boolVal = boolVal ? "true" : "false";
|
|
738
|
+
return this.putString(key, boolVal);
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* 获取整数配置项。
|
|
742
|
+
*/
|
|
743
|
+
getInt(key) {
|
|
744
|
+
return nativeAddon.Env.GetInt(key) ?? void 0;
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* 获取字符串配置项。
|
|
748
|
+
*/
|
|
749
|
+
getString(key) {
|
|
750
|
+
if (key === "SecProtocol") return process.env.XrdSecPROTOCOL ?? process.env.XRD_SECPROTOCOL ?? void 0;
|
|
751
|
+
return nativeAddon.Env.GetString(key) ?? void 0;
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* 批量安全地设置 XRootD 底层参数
|
|
755
|
+
*/
|
|
756
|
+
configure(config) {
|
|
757
|
+
for (const [key, value] of Object.entries(config)) {
|
|
758
|
+
if (value === void 0 || value === null) continue;
|
|
759
|
+
let success = true;
|
|
760
|
+
if (key === "SecProtocol") {
|
|
761
|
+
process.env.XrdSecPROTOCOL = String(value);
|
|
762
|
+
process.env.XRD_SECPROTOCOL = String(value);
|
|
763
|
+
continue;
|
|
764
|
+
}
|
|
765
|
+
if (typeof value === "number" || typeof value === "bigint") {
|
|
766
|
+
checkIntRange(key, value);
|
|
767
|
+
success = nativeAddon.Env.PutInt(key, Number(value));
|
|
768
|
+
} else if (typeof value === "string") success = nativeAddon.Env.PutString(key, value);
|
|
769
|
+
else if (typeof value === "boolean") success = nativeAddon.Env.PutString(key, value ? "true" : "false");
|
|
770
|
+
else {
|
|
771
|
+
console.warn(`[xrootd] Unhandled type ${typeof value} for key ${key}.`);
|
|
772
|
+
success = nativeAddon.Env.PutString(key, value.toString());
|
|
773
|
+
}
|
|
774
|
+
if (!success) console.warn(`[xrootd] Warning: Failed to set configuration "${key}"=${value}. It might have been overridden by a system environment variable.`);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
get(key) {
|
|
778
|
+
if (key === "SecProtocol") return process.env.XrdSecPROTOCOL ?? process.env.XRD_SECPROTOCOL ?? void 0;
|
|
779
|
+
return nativeAddon.Env.GetInt(key) ?? nativeAddon.Env.GetString(key) ?? void 0;
|
|
780
|
+
}
|
|
639
781
|
};
|
|
782
|
+
const Env = new XRootDEnvironment();
|
|
783
|
+
Env.configure({
|
|
784
|
+
RequestTimeout: 30,
|
|
785
|
+
WorkerThreads: 4
|
|
786
|
+
});
|
|
640
787
|
//#endregion
|
|
641
|
-
export { AccessMode, Env, File, FileSystem, MkDirFlags, OpenFlags, XRootDUrl as URL };
|
|
788
|
+
export { AccessMode, CopyProcess, Env, File, FileSystem, MkDirFlags, OpenFlags, XRootDUrl as URL };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xrootd",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Prebuilt Node.js Native Addon for XRootD, allowing JS access to EOS file systems",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -70,7 +70,6 @@
|
|
|
70
70
|
],
|
|
71
71
|
"gypfile": false,
|
|
72
72
|
"scripts": {
|
|
73
|
-
"install": "echo 'Skip implicit node-gyp rebuild. Handled by explicit build.'",
|
|
74
73
|
"build:tsc": "tsc --noEmit",
|
|
75
74
|
"build:ts": "tsdown",
|
|
76
75
|
"build:addon": "node-gyp rebuild",
|
|
@@ -78,7 +77,7 @@
|
|
|
78
77
|
"build": "pnpm run build:addon && pnpm run build:binaries && pnpm run build:tsc && pnpm run build:ts",
|
|
79
78
|
"build:clean": "rm -r ./build && pnpm run build",
|
|
80
79
|
"pack": "mkdir -p packages && pnpm pack --pack-destination ./packages",
|
|
81
|
-
"test:prep": "unrun ./
|
|
82
|
-
"test": "node --test
|
|
80
|
+
"test:prep": "unrun ./tests/prepare.ts",
|
|
81
|
+
"test": "node --test tests/*.mjs"
|
|
83
82
|
}
|
|
84
83
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|