@gjsify/fs 0.3.13 → 0.3.14

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.
@@ -1,113 +1,109 @@
1
- import Gio from "@girs/gio-2.0";
1
+ import { normalizePath } from "./utils.js";
2
2
  import GLib from "@girs/glib-2.0";
3
+ import Gio from "@girs/gio-2.0";
3
4
  import { Buffer } from "node:buffer";
4
5
  import { Readable } from "node:stream";
5
- import { normalizePath } from "./utils.js";
6
- class ReadStream extends Readable {
7
- bytesRead = 0;
8
- path;
9
- pending = true;
10
- fd = null;
11
- _gioFile;
12
- _inputStream = null;
13
- _cancellable = new Gio.Cancellable();
14
- _start;
15
- _end;
16
- _pos;
17
- close(callback) {
18
- this._cancellable.cancel();
19
- if (this._inputStream) {
20
- this._inputStream.close_async(GLib.PRIORITY_DEFAULT, null, () => {
21
- });
22
- this._inputStream = null;
23
- }
24
- this.destroy();
25
- if (callback) callback(null);
26
- }
27
- constructor(path, opts) {
28
- const pathStr = normalizePath(path);
29
- super({
30
- highWaterMark: opts?.highWaterMark ?? 64 * 1024,
31
- encoding: opts?.encoding,
32
- objectMode: false
33
- });
34
- this.path = pathStr;
35
- this._gioFile = Gio.File.new_for_path(pathStr);
36
- this._start = opts?.start ?? 0;
37
- this._end = opts?.end ?? Infinity;
38
- this._pos = this._start;
39
- }
40
- // Use _construct() for async file opening so the stream machinery defers
41
- // _read() until the file is open. This avoids the fragile _pendingReadSize
42
- // pattern and correctly handles backpressure via the constructed flag.
43
- _construct(callback) {
44
- this._gioFile.read_async(GLib.PRIORITY_DEFAULT, this._cancellable, (_source, asyncResult) => {
45
- if (this.destroyed) {
46
- callback();
47
- return;
48
- }
49
- try {
50
- this._inputStream = this._gioFile.read_finish(asyncResult);
51
- this.pending = false;
52
- this.emit("open", 0);
53
- this.emit("ready");
54
- if (this._start > 0 && this._inputStream.can_seek()) {
55
- this._inputStream.seek(this._start, GLib.SeekType.SET, null);
56
- }
57
- callback();
58
- } catch (err) {
59
- if (!this._cancellable.is_cancelled()) {
60
- callback(err);
61
- }
62
- }
63
- });
64
- }
65
- _read(size) {
66
- this._doRead(size);
67
- }
68
- _doRead(size) {
69
- let toRead = size;
70
- if (this._end !== Infinity) {
71
- const remaining = this._end - this._pos + 1;
72
- if (remaining <= 0) {
73
- this.push(null);
74
- return;
75
- }
76
- toRead = Math.min(size, remaining);
77
- }
78
- const stream = this._inputStream;
79
- stream.read_bytes_async(toRead, GLib.PRIORITY_DEFAULT, this._cancellable, (_source, asyncResult) => {
80
- try {
81
- const gbytes = stream.read_bytes_finish(asyncResult);
82
- const data = gbytes.get_data();
83
- if (!data || data.length === 0) {
84
- this.push(null);
85
- return;
86
- }
87
- this.bytesRead += data.length;
88
- this._pos += data.length;
89
- this.push(Buffer.from(data));
90
- } catch (err) {
91
- if (!this._cancellable.is_cancelled()) {
92
- this.destroy(err);
93
- }
94
- }
95
- });
96
- }
97
- _destroy(error, callback) {
98
- this._cancellable.cancel();
99
- if (this._inputStream) {
100
- this._inputStream.close_async(GLib.PRIORITY_DEFAULT, null, () => {
101
- });
102
- this._inputStream = null;
103
- }
104
- callback(error);
105
- }
106
- }
6
+
7
+ //#region src/read-stream.ts
8
+ var ReadStream = class extends Readable {
9
+ bytesRead = 0;
10
+ path;
11
+ pending = true;
12
+ fd = null;
13
+ _gioFile;
14
+ _inputStream = null;
15
+ _cancellable = new Gio.Cancellable();
16
+ _start;
17
+ _end;
18
+ _pos;
19
+ close(callback) {
20
+ this._cancellable.cancel();
21
+ if (this._inputStream) {
22
+ this._inputStream.close_async(GLib.PRIORITY_DEFAULT, null, () => {});
23
+ this._inputStream = null;
24
+ }
25
+ this.destroy();
26
+ if (callback) callback(null);
27
+ }
28
+ constructor(path, opts) {
29
+ const pathStr = normalizePath(path);
30
+ super({
31
+ highWaterMark: opts?.highWaterMark ?? 64 * 1024,
32
+ encoding: opts?.encoding,
33
+ objectMode: false
34
+ });
35
+ this.path = pathStr;
36
+ this._gioFile = Gio.File.new_for_path(pathStr);
37
+ this._start = opts?.start ?? 0;
38
+ this._end = opts?.end ?? Infinity;
39
+ this._pos = this._start;
40
+ }
41
+ _construct(callback) {
42
+ this._gioFile.read_async(GLib.PRIORITY_DEFAULT, this._cancellable, (_source, asyncResult) => {
43
+ if (this.destroyed) {
44
+ callback();
45
+ return;
46
+ }
47
+ try {
48
+ this._inputStream = this._gioFile.read_finish(asyncResult);
49
+ this.pending = false;
50
+ this.emit("open", 0);
51
+ this.emit("ready");
52
+ if (this._start > 0 && this._inputStream.can_seek()) {
53
+ this._inputStream.seek(this._start, GLib.SeekType.SET, null);
54
+ }
55
+ callback();
56
+ } catch (err) {
57
+ if (!this._cancellable.is_cancelled()) {
58
+ callback(err);
59
+ }
60
+ }
61
+ });
62
+ }
63
+ _read(size) {
64
+ this._doRead(size);
65
+ }
66
+ _doRead(size) {
67
+ let toRead = size;
68
+ if (this._end !== Infinity) {
69
+ const remaining = this._end - this._pos + 1;
70
+ if (remaining <= 0) {
71
+ this.push(null);
72
+ return;
73
+ }
74
+ toRead = Math.min(size, remaining);
75
+ }
76
+ const stream = this._inputStream;
77
+ stream.read_bytes_async(toRead, GLib.PRIORITY_DEFAULT, this._cancellable, (_source, asyncResult) => {
78
+ try {
79
+ const gbytes = stream.read_bytes_finish(asyncResult);
80
+ const data = gbytes.get_data();
81
+ if (!data || data.length === 0) {
82
+ this.push(null);
83
+ return;
84
+ }
85
+ this.bytesRead += data.length;
86
+ this._pos += data.length;
87
+ this.push(Buffer.from(data));
88
+ } catch (err) {
89
+ if (!this._cancellable.is_cancelled()) {
90
+ this.destroy(err);
91
+ }
92
+ }
93
+ });
94
+ }
95
+ _destroy(error, callback) {
96
+ this._cancellable.cancel();
97
+ if (this._inputStream) {
98
+ this._inputStream.close_async(GLib.PRIORITY_DEFAULT, null, () => {});
99
+ this._inputStream = null;
100
+ }
101
+ callback(error);
102
+ }
103
+ };
107
104
  function createReadStream(path, options) {
108
- return new ReadStream(path, options);
105
+ return new ReadStream(path, options);
109
106
  }
110
- export {
111
- ReadStream,
112
- createReadStream
113
- };
107
+
108
+ //#endregion
109
+ export { ReadStream, createReadStream };
@@ -1,121 +1,120 @@
1
- import { EventEmitter } from "node:events";
2
1
  import { statSync } from "./sync.js";
2
+ import { EventEmitter } from "node:events";
3
+
4
+ //#region src/stat-watcher.ts
3
5
  function zeroedStat() {
4
- return {
5
- dev: 0,
6
- ino: 0,
7
- mode: 0,
8
- nlink: 0,
9
- uid: 0,
10
- gid: 0,
11
- rdev: 0,
12
- size: 0,
13
- blksize: 0,
14
- blocks: 0,
15
- atimeMs: 0,
16
- mtimeMs: 0,
17
- ctimeMs: 0,
18
- birthtimeMs: 0,
19
- atime: /* @__PURE__ */ new Date(0),
20
- mtime: /* @__PURE__ */ new Date(0),
21
- ctime: /* @__PURE__ */ new Date(0),
22
- birthtime: /* @__PURE__ */ new Date(0),
23
- isFile: () => false,
24
- isDirectory: () => false,
25
- isBlockDevice: () => false,
26
- isCharacterDevice: () => false,
27
- isSymbolicLink: () => false,
28
- isFIFO: () => false,
29
- isSocket: () => false
30
- };
31
- }
32
- class StatWatcher extends EventEmitter {
33
- _path;
34
- _interval;
35
- _timerId = null;
36
- _prev;
37
- _changeCount = 0;
38
- constructor(path, interval) {
39
- super();
40
- this._path = path;
41
- this._interval = interval;
42
- this._prev = zeroedStat();
43
- }
44
- start() {
45
- try {
46
- this._prev = statSync(this._path);
47
- } catch {
48
- }
49
- this._timerId = setInterval(() => {
50
- let curr;
51
- try {
52
- curr = statSync(this._path);
53
- } catch {
54
- curr = zeroedStat();
55
- }
56
- const prev = this._prev;
57
- if (curr.mtimeMs !== prev.mtimeMs || curr.size !== prev.size || curr.ino !== prev.ino) {
58
- this._prev = curr;
59
- this.emit("change", curr, prev);
60
- }
61
- }, this._interval);
62
- }
63
- stop() {
64
- if (this._timerId !== null) {
65
- clearInterval(this._timerId);
66
- this._timerId = null;
67
- }
68
- this.emit("stop");
69
- }
70
- addChangeListener(listener) {
71
- this._changeCount++;
72
- this.on("change", listener);
73
- }
74
- removeChangeListener(listener) {
75
- this._changeCount--;
76
- this.removeListener("change", listener);
77
- }
78
- removeAllChangeListeners() {
79
- this._changeCount = 0;
80
- this.removeAllListeners("change");
81
- }
82
- get changeListenerCount() {
83
- return this._changeCount;
84
- }
6
+ return {
7
+ dev: 0,
8
+ ino: 0,
9
+ mode: 0,
10
+ nlink: 0,
11
+ uid: 0,
12
+ gid: 0,
13
+ rdev: 0,
14
+ size: 0,
15
+ blksize: 0,
16
+ blocks: 0,
17
+ atimeMs: 0,
18
+ mtimeMs: 0,
19
+ ctimeMs: 0,
20
+ birthtimeMs: 0,
21
+ atime: new Date(0),
22
+ mtime: new Date(0),
23
+ ctime: new Date(0),
24
+ birthtime: new Date(0),
25
+ isFile: () => false,
26
+ isDirectory: () => false,
27
+ isBlockDevice: () => false,
28
+ isCharacterDevice: () => false,
29
+ isSymbolicLink: () => false,
30
+ isFIFO: () => false,
31
+ isSocket: () => false
32
+ };
85
33
  }
86
- const statWatchers = /* @__PURE__ */ new Map();
34
+ var StatWatcher = class extends EventEmitter {
35
+ _path;
36
+ _interval;
37
+ _timerId = null;
38
+ _prev;
39
+ _changeCount = 0;
40
+ constructor(path, interval) {
41
+ super();
42
+ this._path = path;
43
+ this._interval = interval;
44
+ this._prev = zeroedStat();
45
+ }
46
+ start() {
47
+ try {
48
+ this._prev = statSync(this._path);
49
+ } catch {}
50
+ this._timerId = setInterval(() => {
51
+ let curr;
52
+ try {
53
+ curr = statSync(this._path);
54
+ } catch {
55
+ curr = zeroedStat();
56
+ }
57
+ const prev = this._prev;
58
+ if (curr.mtimeMs !== prev.mtimeMs || curr.size !== prev.size || curr.ino !== prev.ino) {
59
+ this._prev = curr;
60
+ this.emit("change", curr, prev);
61
+ }
62
+ }, this._interval);
63
+ }
64
+ stop() {
65
+ if (this._timerId !== null) {
66
+ clearInterval(this._timerId);
67
+ this._timerId = null;
68
+ }
69
+ this.emit("stop");
70
+ }
71
+ addChangeListener(listener) {
72
+ this._changeCount++;
73
+ this.on("change", listener);
74
+ }
75
+ removeChangeListener(listener) {
76
+ this._changeCount--;
77
+ this.removeListener("change", listener);
78
+ }
79
+ removeAllChangeListeners() {
80
+ this._changeCount = 0;
81
+ this.removeAllListeners("change");
82
+ }
83
+ get changeListenerCount() {
84
+ return this._changeCount;
85
+ }
86
+ };
87
+ const statWatchers = new Map();
87
88
  function watchFile(filename, options, listener) {
88
- if (typeof options === "function") {
89
- listener = options;
90
- options = {};
91
- }
92
- const interval = options.interval ?? 5007;
93
- const resolved = filename.toString();
94
- let watcher = statWatchers.get(resolved);
95
- if (!watcher) {
96
- watcher = new StatWatcher(resolved, interval);
97
- watcher.start();
98
- statWatchers.set(resolved, watcher);
99
- }
100
- if (listener) watcher.addChangeListener(listener);
101
- return watcher;
89
+ if (typeof options === "function") {
90
+ listener = options;
91
+ options = {};
92
+ }
93
+ const interval = options.interval ?? 5007;
94
+ const resolved = filename.toString();
95
+ let watcher = statWatchers.get(resolved);
96
+ if (!watcher) {
97
+ watcher = new StatWatcher(resolved, interval);
98
+ watcher.start();
99
+ statWatchers.set(resolved, watcher);
100
+ }
101
+ if (listener) watcher.addChangeListener(listener);
102
+ return watcher;
102
103
  }
103
104
  function unwatchFile(filename, listener) {
104
- const resolved = filename.toString();
105
- const watcher = statWatchers.get(resolved);
106
- if (!watcher) return;
107
- if (listener) {
108
- watcher.removeChangeListener(listener);
109
- } else {
110
- watcher.removeAllChangeListeners();
111
- }
112
- if (watcher.changeListenerCount === 0) {
113
- watcher.stop();
114
- statWatchers.delete(resolved);
115
- }
105
+ const resolved = filename.toString();
106
+ const watcher = statWatchers.get(resolved);
107
+ if (!watcher) return;
108
+ if (listener) {
109
+ watcher.removeChangeListener(listener);
110
+ } else {
111
+ watcher.removeAllChangeListeners();
112
+ }
113
+ if (watcher.changeListenerCount === 0) {
114
+ watcher.stop();
115
+ statWatchers.delete(resolved);
116
+ }
116
117
  }
117
- export {
118
- StatWatcher,
119
- unwatchFile,
120
- watchFile
121
- };
118
+
119
+ //#endregion
120
+ export { StatWatcher, unwatchFile, watchFile };
package/lib/esm/statfs.js CHANGED
@@ -1,57 +1,70 @@
1
- import Gio from "@girs/gio-2.0";
2
- import GLib from "@girs/glib-2.0";
3
1
  import { normalizePath } from "./utils.js";
4
- const FS_INFO_ATTRS = [
5
- "filesystem::size",
6
- "filesystem::free"
7
- ].join(",");
2
+ import GLib from "@girs/glib-2.0";
3
+ import Gio from "@girs/gio-2.0";
4
+
5
+ //#region src/statfs.ts
6
+ const FS_INFO_ATTRS = ["filesystem::size", "filesystem::free"].join(",");
8
7
  const BSIZE = 4096;
9
8
  function buildStatFs(info) {
10
- const totalBytes = Number(info.get_attribute_uint64("filesystem::size") ?? 0);
11
- const freeBytes = Number(info.get_attribute_uint64("filesystem::free") ?? 0);
12
- const blocks = Math.floor(totalBytes / BSIZE);
13
- const bfree = Math.floor(freeBytes / BSIZE);
14
- return { type: 0, bsize: BSIZE, blocks, bfree, bavail: bfree, files: 0, ffree: 0 };
9
+ const totalBytes = Number(info.get_attribute_uint64("filesystem::size") ?? 0);
10
+ const freeBytes = Number(info.get_attribute_uint64("filesystem::free") ?? 0);
11
+ const blocks = Math.floor(totalBytes / BSIZE);
12
+ const bfree = Math.floor(freeBytes / BSIZE);
13
+ return {
14
+ type: 0,
15
+ bsize: BSIZE,
16
+ blocks,
17
+ bfree,
18
+ bavail: bfree,
19
+ files: 0,
20
+ ffree: 0
21
+ };
15
22
  }
16
23
  function buildBigIntStatFs(info) {
17
- const totalBytes = BigInt(info.get_attribute_uint64("filesystem::size") ?? 0);
18
- const freeBytes = BigInt(info.get_attribute_uint64("filesystem::free") ?? 0);
19
- const bsize = BigInt(BSIZE);
20
- const blocks = totalBytes / bsize;
21
- const bfree = freeBytes / bsize;
22
- return { type: 0n, bsize, blocks, bfree, bavail: bfree, files: 0n, ffree: 0n };
24
+ const totalBytes = BigInt(info.get_attribute_uint64("filesystem::size") ?? 0);
25
+ const freeBytes = BigInt(info.get_attribute_uint64("filesystem::free") ?? 0);
26
+ const bsize = BigInt(BSIZE);
27
+ const blocks = totalBytes / bsize;
28
+ const bfree = freeBytes / bsize;
29
+ return {
30
+ type: 0n,
31
+ bsize,
32
+ blocks,
33
+ bfree,
34
+ bavail: bfree,
35
+ files: 0n,
36
+ ffree: 0n
37
+ };
23
38
  }
24
39
  function statfsSync(path, options) {
25
- const file = Gio.File.new_for_path(normalizePath(path));
26
- const info = file.query_filesystem_info(FS_INFO_ATTRS, null);
27
- return options?.bigint === true ? buildBigIntStatFs(info) : buildStatFs(info);
40
+ const file = Gio.File.new_for_path(normalizePath(path));
41
+ const info = file.query_filesystem_info(FS_INFO_ATTRS, null);
42
+ return options?.bigint === true ? buildBigIntStatFs(info) : buildStatFs(info);
28
43
  }
29
44
  function queryFsInfoAsync(path, useBigInt) {
30
- return new Promise((resolve, reject) => {
31
- const file = Gio.File.new_for_path(normalizePath(path));
32
- file.query_filesystem_info_async(FS_INFO_ATTRS, GLib.PRIORITY_DEFAULT, null, (_s, res) => {
33
- try {
34
- const info = file.query_filesystem_info_finish(res);
35
- resolve(useBigInt ? buildBigIntStatFs(info) : buildStatFs(info));
36
- } catch (err) {
37
- reject(err);
38
- }
39
- });
40
- });
45
+ return new Promise((resolve, reject) => {
46
+ const file = Gio.File.new_for_path(normalizePath(path));
47
+ file.query_filesystem_info_async(FS_INFO_ATTRS, GLib.PRIORITY_DEFAULT, null, (_s, res) => {
48
+ try {
49
+ const info = file.query_filesystem_info_finish(res);
50
+ resolve(useBigInt ? buildBigIntStatFs(info) : buildStatFs(info));
51
+ } catch (err) {
52
+ reject(err);
53
+ }
54
+ });
55
+ });
41
56
  }
42
57
  function statfs(path, optionsOrCb, callback) {
43
- if (typeof optionsOrCb === "function") {
44
- callback = optionsOrCb;
45
- optionsOrCb = {};
46
- }
47
- const useBigInt = optionsOrCb?.bigint === true;
48
- queryFsInfoAsync(path, useBigInt).then((result) => callback(null, result), (err) => callback(err, null));
58
+ if (typeof optionsOrCb === "function") {
59
+ callback = optionsOrCb;
60
+ optionsOrCb = {};
61
+ }
62
+ const useBigInt = optionsOrCb?.bigint === true;
63
+ queryFsInfoAsync(path, useBigInt).then((result) => callback(null, result), (err) => callback(err, null));
49
64
  }
50
65
  async function statfsAsync(path, options) {
51
- return queryFsInfoAsync(path, options?.bigint === true);
66
+ return queryFsInfoAsync(path, options?.bigint === true);
52
67
  }
53
- export {
54
- statfs,
55
- statfsAsync,
56
- statfsSync
57
- };
68
+
69
+ //#endregion
70
+ export { statfs, statfsAsync, statfsSync };