@gjsify/fs 0.0.4 → 0.1.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.
- package/README.md +31 -2
- package/lib/esm/callback.js +251 -15
- package/lib/esm/dirent.js +47 -6
- package/lib/esm/encoding.js +2 -3
- package/lib/esm/errors.js +13 -0
- package/lib/esm/file-handle.js +108 -66
- package/lib/esm/fs-watcher.js +44 -7
- package/lib/esm/index.js +140 -5
- package/lib/esm/promises.js +290 -69
- package/lib/esm/read-stream.js +82 -57
- package/lib/esm/stats.js +138 -18
- package/lib/esm/sync.js +293 -44
- package/lib/esm/write-stream.js +4 -4
- package/lib/types/callback.d.ts +233 -0
- package/lib/types/dirent.d.ts +77 -0
- package/lib/types/encoding.d.ts +6 -0
- package/lib/types/errors.d.ts +7 -0
- package/lib/types/file-handle.d.ts +367 -0
- package/lib/types/fs-watcher.d.ts +17 -0
- package/lib/types/index.d.ts +149 -0
- package/lib/types/promises.d.ts +158 -0
- package/lib/types/read-stream.d.ts +21 -0
- package/lib/types/stats.d.ts +67 -0
- package/lib/types/sync.d.ts +109 -0
- package/lib/types/types/encoding-option.d.ts +2 -0
- package/lib/types/types/file-read-options.d.ts +15 -0
- package/lib/types/types/file-read-result.d.ts +4 -0
- package/lib/types/types/flag-and-open-mode.d.ts +5 -0
- package/lib/types/types/index.d.ts +6 -0
- package/lib/types/types/open-flags.d.ts +1 -0
- package/lib/types/types/read-options.d.ts +5 -0
- package/lib/types/utils.d.ts +2 -0
- package/lib/types/write-stream.d.ts +45 -0
- package/package.json +22 -35
- package/src/callback.spec.ts +284 -30
- package/src/callback.ts +352 -39
- package/src/dirent.ts +56 -8
- package/src/encoding.ts +7 -2
- package/src/errors.spec.ts +389 -0
- package/src/errors.ts +19 -0
- package/src/extended.spec.ts +706 -0
- package/src/file-handle.spec.ts +104 -23
- package/src/file-handle.ts +147 -79
- package/src/fs-watcher.ts +55 -8
- package/src/index.ts +146 -2
- package/src/new-apis.spec.ts +505 -0
- package/src/promises.spec.ts +651 -11
- package/src/promises.ts +353 -81
- package/src/read-stream.ts +98 -74
- package/src/stat.spec.ts +22 -14
- package/src/stats.ts +176 -75
- package/src/streams.spec.ts +455 -0
- package/src/symlink.spec.ts +176 -26
- package/src/sync.spec.ts +204 -32
- package/src/sync.ts +363 -58
- package/src/test.mts +7 -2
- package/src/types/encoding-option.ts +1 -1
- package/src/types/flag-and-open-mode.ts +1 -1
- package/src/types/read-options.ts +2 -2
- package/src/utils.ts +2 -0
- package/src/write-stream.ts +9 -7
- package/tsconfig.json +23 -10
- package/tsconfig.tsbuildinfo +1 -0
- package/lib/cjs/callback.js +0 -112
- package/lib/cjs/dirent.js +0 -98
- package/lib/cjs/encoding.js +0 -34
- package/lib/cjs/file-handle.js +0 -444
- package/lib/cjs/fs-watcher.js +0 -50
- package/lib/cjs/index.js +0 -95
- package/lib/cjs/promises.js +0 -160
- package/lib/cjs/read-stream.js +0 -78
- package/lib/cjs/stats.js +0 -45
- package/lib/cjs/sync.js +0 -126
- package/lib/cjs/types/encoding-option.js +0 -0
- package/lib/cjs/types/file-read-options.js +0 -0
- package/lib/cjs/types/file-read-result.js +0 -0
- package/lib/cjs/types/flag-and-open-mode.js +0 -0
- package/lib/cjs/types/index.js +0 -6
- package/lib/cjs/types/open-flags.js +0 -0
- package/lib/cjs/types/read-options.js +0 -0
- package/lib/cjs/utils.js +0 -18
- package/lib/cjs/write-stream.js +0 -116
- package/test/watch.js +0 -1
- package/test.gjs.js +0 -35359
- package/test.gjs.js.map +0 -7
- package/test.gjs.mjs +0 -40534
- package/test.gjs.mjs.meta.json +0 -1
- package/test.node.js +0 -1479
- package/test.node.js.map +0 -7
- package/test.node.mjs +0 -710
- package/tsconfig.types.json +0 -8
package/src/read-stream.ts
CHANGED
|
@@ -1,92 +1,116 @@
|
|
|
1
|
-
//
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// Adapted from Deno (refs/deno/ext/node/polyfills/_fs/_fs_streams.ts)
|
|
3
|
+
// Copyright (c) 2018-2026 the Deno authors. MIT license.
|
|
4
|
+
// Modifications: Rewritten to use Gio.File / Gio.FileInputStream for GJS
|
|
5
|
+
import Gio from '@girs/gio-2.0';
|
|
2
6
|
import GLib from '@girs/glib-2.0';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { URL } from "url";
|
|
7
|
+
import { Buffer } from "node:buffer";
|
|
8
|
+
import { Readable } from "node:stream";
|
|
9
|
+
import { URL, fileURLToPath } from "node:url";
|
|
7
10
|
|
|
8
|
-
import type { CreateReadStreamOptions } from 'fs/promises';
|
|
9
|
-
import type { PathLike, ReadStream as IReadStream } from 'fs';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Converts a file URL to a path string.
|
|
13
|
-
*
|
|
14
|
-
* ```ts
|
|
15
|
-
* import { fromFileUrl } from "./posix.ts";
|
|
16
|
-
* fromFileUrl("file:///home/foo"); // "/home/foo"
|
|
17
|
-
* ```
|
|
18
|
-
* @param url of a file URL
|
|
19
|
-
* @credits https://github.com/denoland/deno_std/blob/44d05e7a8d445888d989d49eb3e59eee3055f2c5/node/path/posix.ts#L486
|
|
20
|
-
*/
|
|
21
|
-
export function fromFileUrl(url: string | URL): string {
|
|
22
|
-
url = url instanceof URL ? url : new URL(url);
|
|
23
|
-
if (url.protocol != "file:") {
|
|
24
|
-
throw new TypeError("Must be a file URL.");
|
|
25
|
-
}
|
|
26
|
-
return decodeURIComponent(
|
|
27
|
-
url.pathname.replace(/%(?![0-9A-Fa-f]{2})/g, "%25"),
|
|
28
|
-
);
|
|
29
|
-
}
|
|
11
|
+
import type { CreateReadStreamOptions } from 'node:fs/promises';
|
|
12
|
+
import type { PathLike, ReadStream as IReadStream } from 'node:fs';
|
|
30
13
|
|
|
31
14
|
export class ReadStream extends Readable implements IReadStream {
|
|
15
|
+
bytesRead = 0;
|
|
16
|
+
path: string | Buffer;
|
|
17
|
+
pending = true;
|
|
18
|
+
fd: number | null = null;
|
|
19
|
+
|
|
20
|
+
private _gioFile: Gio.File;
|
|
21
|
+
private _inputStream: Gio.FileInputStream | null = null;
|
|
22
|
+
private _start: number;
|
|
23
|
+
private _end: number;
|
|
24
|
+
private _pos: number;
|
|
25
|
+
|
|
32
26
|
close(callback?: (err?: NodeJS.ErrnoException | null) => void): void {
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
if (this._inputStream) {
|
|
28
|
+
try { this._inputStream.close(null); } catch {}
|
|
29
|
+
this._inputStream = null;
|
|
30
|
+
}
|
|
31
|
+
this.destroy();
|
|
32
|
+
if (callback) callback(null);
|
|
35
33
|
}
|
|
36
|
-
/**
|
|
37
|
-
* The number of bytes that have been read so far.
|
|
38
|
-
* @since v6.4.0
|
|
39
|
-
*/
|
|
40
|
-
bytesRead: number;
|
|
41
|
-
/**
|
|
42
|
-
* The path to the file the stream is reading from as specified in the first
|
|
43
|
-
* argument to `fs.createReadStream()`. If `path` is passed as a string, then`readStream.path` will be a string. If `path` is passed as a `Buffer`, then`readStream.path` will be a
|
|
44
|
-
* `Buffer`. If `fd` is specified, then`readStream.path` will be `undefined`.
|
|
45
|
-
* @since v0.1.93
|
|
46
|
-
*/
|
|
47
|
-
path: string | Buffer;
|
|
48
|
-
/**
|
|
49
|
-
* This property is `true` if the underlying file has not been opened yet,
|
|
50
|
-
* i.e. before the `'ready'` event is emitted.
|
|
51
|
-
* @since v11.2.0, v10.16.0
|
|
52
|
-
*/
|
|
53
|
-
pending: boolean;
|
|
54
34
|
|
|
55
35
|
constructor(path: PathLike, opts?: CreateReadStreamOptions) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
opts.start || opts.end
|
|
59
|
-
);
|
|
60
|
-
if (hasBadOptions) {
|
|
61
|
-
notImplemented(
|
|
62
|
-
`fs.ReadStream.prototype.constructor with unsupported options (${
|
|
63
|
-
JSON.stringify(opts)
|
|
64
|
-
})`,
|
|
65
|
-
);
|
|
36
|
+
if (path instanceof URL) {
|
|
37
|
+
path = fileURLToPath(path);
|
|
66
38
|
}
|
|
67
|
-
|
|
68
|
-
const buffer = "";
|
|
39
|
+
|
|
69
40
|
super({
|
|
70
|
-
|
|
71
|
-
|
|
41
|
+
highWaterMark: opts?.highWaterMark ?? 64 * 1024,
|
|
42
|
+
encoding: opts?.encoding as BufferEncoding | undefined,
|
|
72
43
|
objectMode: false,
|
|
73
|
-
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
this.path = path.toString();
|
|
47
|
+
this._gioFile = Gio.File.new_for_path(this.path.toString());
|
|
48
|
+
this._start = (opts?.start as number) ?? 0;
|
|
49
|
+
this._end = (opts?.end as number) ?? Infinity;
|
|
50
|
+
this._pos = this._start;
|
|
51
|
+
|
|
52
|
+
// Validate file existence eagerly (like Node.js) to emit error event
|
|
53
|
+
Promise.resolve().then(() => {
|
|
54
|
+
if (!this._inputStream && !this.destroyed) {
|
|
74
55
|
try {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
this.
|
|
56
|
+
this._inputStream = this._gioFile.read(null);
|
|
57
|
+
this.pending = false;
|
|
58
|
+
this.emit('open', 0);
|
|
59
|
+
this.emit('ready');
|
|
60
|
+
if (this._start > 0 && this._inputStream.can_seek()) {
|
|
61
|
+
this._inputStream.seek(this._start, GLib.SeekType.SET, null);
|
|
62
|
+
}
|
|
78
63
|
} catch (err) {
|
|
79
64
|
this.destroy(err as Error);
|
|
80
65
|
}
|
|
81
|
-
}
|
|
82
|
-
destroy: (err, cb) => {
|
|
83
|
-
try {
|
|
84
|
-
file.close();
|
|
85
|
-
} catch {}
|
|
86
|
-
cb(err);
|
|
87
|
-
},
|
|
66
|
+
}
|
|
88
67
|
});
|
|
89
|
-
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
override _read(size: number): void {
|
|
71
|
+
// Stream is opened eagerly in constructor; if not yet ready, wait
|
|
72
|
+
if (!this._inputStream) {
|
|
73
|
+
if (this.destroyed) return;
|
|
74
|
+
// Retry on next tick (constructor's async open hasn't completed yet)
|
|
75
|
+
Promise.resolve().then(() => this._read(size));
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Calculate how many bytes to read
|
|
80
|
+
let toRead = size;
|
|
81
|
+
if (this._end !== Infinity) {
|
|
82
|
+
const remaining = this._end - this._pos + 1;
|
|
83
|
+
if (remaining <= 0) {
|
|
84
|
+
this.push(null);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
toRead = Math.min(size, remaining);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
const gbytes = this._inputStream!.read_bytes(toRead, null);
|
|
92
|
+
const data = gbytes.get_data();
|
|
93
|
+
|
|
94
|
+
if (!data || data.length === 0) {
|
|
95
|
+
// EOF
|
|
96
|
+
this.push(null);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
this.bytesRead += data.length;
|
|
101
|
+
this._pos += data.length;
|
|
102
|
+
this.push(Buffer.from(data));
|
|
103
|
+
} catch (err) {
|
|
104
|
+
this.destroy(err as Error);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
override _destroy(error: Error | null, callback: (error?: Error | null) => void): void {
|
|
109
|
+
if (this._inputStream) {
|
|
110
|
+
try { this._inputStream.close(null); } catch {}
|
|
111
|
+
this._inputStream = null;
|
|
112
|
+
}
|
|
113
|
+
callback(error);
|
|
90
114
|
}
|
|
91
115
|
}
|
|
92
116
|
|
|
@@ -95,4 +119,4 @@ export function createReadStream(
|
|
|
95
119
|
options?: CreateReadStreamOptions,
|
|
96
120
|
): ReadStream {
|
|
97
121
|
return new ReadStream(path, options);
|
|
98
|
-
}
|
|
122
|
+
}
|
package/src/stat.spec.ts
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import { describe, it, expect } from '@gjsify/unit';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
// const __dirname = dirname(__filename)
|
|
7
|
-
|
|
8
|
-
import { statSync } from 'fs';
|
|
9
|
-
import { stat } from 'fs/promises';
|
|
2
|
+
import { statSync, mkdtempSync, writeFileSync, rmSync, rmdirSync } from 'node:fs';
|
|
3
|
+
import { stat } from 'node:fs/promises';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { tmpdir } from 'node:os';
|
|
10
6
|
|
|
11
7
|
export default async () => {
|
|
12
8
|
await describe('fs.statSync', async () => {
|
|
13
9
|
|
|
14
10
|
await it('Should return the file stat', async () => {
|
|
11
|
+
const dir = mkdtempSync(join(tmpdir(), 'fs-stat-'));
|
|
12
|
+
const filePath = join(dir, 'test.txt');
|
|
13
|
+
writeFileSync(filePath, 'stat test data');
|
|
15
14
|
|
|
16
|
-
const s = statSync(
|
|
15
|
+
const s = statSync(filePath);
|
|
17
16
|
|
|
18
17
|
expect(s.atime instanceof Date).toBeTruthy();
|
|
19
18
|
expect(s.atimeMs).toBeGreaterThan(0);
|
|
@@ -24,7 +23,7 @@ export default async () => {
|
|
|
24
23
|
expect(s.ctime instanceof Date).toBeTruthy();
|
|
25
24
|
expect(s.ctimeMs).toBeGreaterThan(0);
|
|
26
25
|
expect(s.dev).toBeGreaterThan(0);
|
|
27
|
-
expect(s.gid).toBeGreaterThan(
|
|
26
|
+
expect(s.gid).toBeGreaterThan(-1);
|
|
28
27
|
expect(s.ino).toBeGreaterThan(0);
|
|
29
28
|
expect(s.mode).toBeGreaterThan(0);
|
|
30
29
|
expect(s.mtime instanceof Date).toBeTruthy();
|
|
@@ -32,7 +31,7 @@ export default async () => {
|
|
|
32
31
|
expect(s.nlink).toBeGreaterThan(0);
|
|
33
32
|
expect(s.rdev).toBeGreaterThan(-1);
|
|
34
33
|
expect(s.size).toBeGreaterThan(0);
|
|
35
|
-
expect(s.uid).toBeGreaterThan(
|
|
34
|
+
expect(s.uid).toBeGreaterThan(-1);
|
|
36
35
|
expect(s.isBlockDevice()).toBeFalsy();
|
|
37
36
|
expect(s.isCharacterDevice()).toBeFalsy();
|
|
38
37
|
expect(s.isDirectory()).toBeFalsy();
|
|
@@ -40,14 +39,20 @@ export default async () => {
|
|
|
40
39
|
expect(s.isFile()).toBeTruthy();
|
|
41
40
|
expect(s.isSocket()).toBeFalsy();
|
|
42
41
|
expect(s.isSymbolicLink()).toBeFalsy();
|
|
42
|
+
|
|
43
|
+
rmSync(filePath);
|
|
44
|
+
rmdirSync(dir);
|
|
43
45
|
});
|
|
44
46
|
});
|
|
45
47
|
|
|
46
48
|
await describe('fs.stat (promise)', async () => {
|
|
47
49
|
|
|
48
50
|
await it('Should return the file stat', async () => {
|
|
51
|
+
const dir = mkdtempSync(join(tmpdir(), 'fs-pstat-'));
|
|
52
|
+
const filePath = join(dir, 'test.txt');
|
|
53
|
+
writeFileSync(filePath, 'stat test data');
|
|
49
54
|
|
|
50
|
-
const s = await stat(
|
|
55
|
+
const s = await stat(filePath);
|
|
51
56
|
|
|
52
57
|
expect(s.atime instanceof Date).toBeTruthy();
|
|
53
58
|
expect(s.atimeMs).toBeGreaterThan(0);
|
|
@@ -58,7 +63,7 @@ export default async () => {
|
|
|
58
63
|
expect(s.ctime instanceof Date).toBeTruthy();
|
|
59
64
|
expect(s.ctimeMs).toBeGreaterThan(0);
|
|
60
65
|
expect(s.dev).toBeGreaterThan(0);
|
|
61
|
-
expect(s.gid).toBeGreaterThan(
|
|
66
|
+
expect(s.gid).toBeGreaterThan(-1);
|
|
62
67
|
expect(s.ino).toBeGreaterThan(0);
|
|
63
68
|
expect(s.mode).toBeGreaterThan(0);
|
|
64
69
|
expect(s.mtime instanceof Date).toBeTruthy();
|
|
@@ -66,7 +71,7 @@ export default async () => {
|
|
|
66
71
|
expect(s.nlink).toBeGreaterThan(0);
|
|
67
72
|
expect(s.rdev).toBeGreaterThan(-1);
|
|
68
73
|
expect(s.size).toBeGreaterThan(0);
|
|
69
|
-
expect(s.uid).toBeGreaterThan(
|
|
74
|
+
expect(s.uid).toBeGreaterThan(-1);
|
|
70
75
|
expect(s.isBlockDevice()).toBeFalsy();
|
|
71
76
|
expect(s.isCharacterDevice()).toBeFalsy();
|
|
72
77
|
expect(s.isDirectory()).toBeFalsy();
|
|
@@ -74,6 +79,9 @@ export default async () => {
|
|
|
74
79
|
expect(s.isFile()).toBeTruthy();
|
|
75
80
|
expect(s.isSocket()).toBeFalsy();
|
|
76
81
|
expect(s.isSymbolicLink()).toBeFalsy();
|
|
82
|
+
|
|
83
|
+
rmSync(filePath);
|
|
84
|
+
rmdirSync(dir);
|
|
77
85
|
});
|
|
78
86
|
});
|
|
79
87
|
}
|
package/src/stats.ts
CHANGED
|
@@ -1,67 +1,54 @@
|
|
|
1
|
+
// Reference: Node.js lib/internal/fs/utils.js (Stats class)
|
|
2
|
+
// Reimplemented for GJS using Gio.FileInfo attributes
|
|
3
|
+
|
|
1
4
|
import Gio from '@girs/gio-2.0';
|
|
2
5
|
import { Dirent } from './dirent.js';
|
|
3
|
-
import { basename } from 'path';
|
|
6
|
+
import { basename } from 'node:path';
|
|
7
|
+
|
|
8
|
+
import type { Stats as NodeStats, BigIntStats as NodeBigIntStats, PathLike } from 'node:fs';
|
|
9
|
+
|
|
10
|
+
// Query all attributes needed for a full Node.js Stats object
|
|
11
|
+
export const STAT_ATTRIBUTES = 'standard::*,time::*,unix::*';
|
|
4
12
|
|
|
5
|
-
|
|
13
|
+
function populateFromInfo(info: Gio.FileInfo) {
|
|
14
|
+
const atimeSec = info.get_attribute_uint64('time::access');
|
|
15
|
+
const atimeUsec = info.get_attribute_uint32('time::access-usec') || 0;
|
|
16
|
+
const mtimeSec = info.get_attribute_uint64('time::modified');
|
|
17
|
+
const mtimeUsec = info.get_attribute_uint32('time::modified-usec') || 0;
|
|
18
|
+
const ctimeSec = info.get_attribute_uint64('time::changed');
|
|
19
|
+
const ctimeUsec = info.get_attribute_uint32('time::changed-usec') || 0;
|
|
20
|
+
const createdSec = info.get_attribute_uint64('time::created');
|
|
21
|
+
const createdUsec = info.get_attribute_uint32('time::created-usec') || 0;
|
|
22
|
+
|
|
23
|
+
const atimeMs = atimeSec * 1000 + atimeUsec / 1000;
|
|
24
|
+
const mtimeMs = mtimeSec * 1000 + mtimeUsec / 1000;
|
|
25
|
+
const ctimeMs = ctimeSec ? ctimeSec * 1000 + ctimeUsec / 1000 : mtimeMs;
|
|
26
|
+
const birthtimeMs = createdSec ? createdSec * 1000 + createdUsec / 1000 : ctimeMs;
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
dev: info.get_attribute_uint32('unix::device') || 0,
|
|
30
|
+
ino: Number(info.get_attribute_uint64('unix::inode') || 0),
|
|
31
|
+
mode: info.get_attribute_uint32('unix::mode') || 0,
|
|
32
|
+
nlink: info.get_attribute_uint32('unix::nlink') || 0,
|
|
33
|
+
uid: info.get_attribute_uint32('unix::uid') || 0,
|
|
34
|
+
gid: info.get_attribute_uint32('unix::gid') || 0,
|
|
35
|
+
rdev: info.get_attribute_uint32('unix::rdev') || 0,
|
|
36
|
+
size: Number(info.get_size() || 0),
|
|
37
|
+
blksize: info.get_attribute_uint32('unix::block-size') || 4096,
|
|
38
|
+
blocks: Number(info.get_attribute_uint64('unix::blocks') || 0),
|
|
39
|
+
atimeMs,
|
|
40
|
+
mtimeMs,
|
|
41
|
+
ctimeMs,
|
|
42
|
+
birthtimeMs,
|
|
43
|
+
atime: new Date(atimeMs),
|
|
44
|
+
mtime: new Date(mtimeMs),
|
|
45
|
+
ctime: new Date(ctimeMs),
|
|
46
|
+
birthtime: new Date(birthtimeMs),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
6
49
|
|
|
7
50
|
/**
|
|
8
51
|
* A `fs.Stats` object provides information about a file.
|
|
9
|
-
*
|
|
10
|
-
* Objects returned from {@link stat}, {@link lstat} and {@link fstat} and
|
|
11
|
-
* their synchronous counterparts are of this type.
|
|
12
|
-
* If `bigint` in the `options` passed to those methods is true, the numeric values
|
|
13
|
-
* will be `bigint` instead of `number`, and the object will contain additional
|
|
14
|
-
* nanosecond-precision properties suffixed with `Ns`.
|
|
15
|
-
*
|
|
16
|
-
* ```console
|
|
17
|
-
* Stats {
|
|
18
|
-
* dev: 2114,
|
|
19
|
-
* ino: 48064969,
|
|
20
|
-
* mode: 33188,
|
|
21
|
-
* nlink: 1,
|
|
22
|
-
* uid: 85,
|
|
23
|
-
* gid: 100,
|
|
24
|
-
* rdev: 0,
|
|
25
|
-
* size: 527,
|
|
26
|
-
* blksize: 4096,
|
|
27
|
-
* blocks: 8,
|
|
28
|
-
* atimeMs: 1318289051000.1,
|
|
29
|
-
* mtimeMs: 1318289051000.1,
|
|
30
|
-
* ctimeMs: 1318289051000.1,
|
|
31
|
-
* birthtimeMs: 1318289051000.1,
|
|
32
|
-
* atime: Mon, 10 Oct 2011 23:24:11 GMT,
|
|
33
|
-
* mtime: Mon, 10 Oct 2011 23:24:11 GMT,
|
|
34
|
-
* ctime: Mon, 10 Oct 2011 23:24:11 GMT,
|
|
35
|
-
* birthtime: Mon, 10 Oct 2011 23:24:11 GMT }
|
|
36
|
-
* ```
|
|
37
|
-
*
|
|
38
|
-
* `bigint` version:
|
|
39
|
-
*
|
|
40
|
-
* ```console
|
|
41
|
-
* BigIntStats {
|
|
42
|
-
* dev: 2114n,
|
|
43
|
-
* ino: 48064969n,
|
|
44
|
-
* mode: 33188n,
|
|
45
|
-
* nlink: 1n,
|
|
46
|
-
* uid: 85n,
|
|
47
|
-
* gid: 100n,
|
|
48
|
-
* rdev: 0n,
|
|
49
|
-
* size: 527n,
|
|
50
|
-
* blksize: 4096n,
|
|
51
|
-
* blocks: 8n,
|
|
52
|
-
* atimeMs: 1318289051000n,
|
|
53
|
-
* mtimeMs: 1318289051000n,
|
|
54
|
-
* ctimeMs: 1318289051000n,
|
|
55
|
-
* birthtimeMs: 1318289051000n,
|
|
56
|
-
* atimeNs: 1318289051000000000n,
|
|
57
|
-
* mtimeNs: 1318289051000000000n,
|
|
58
|
-
* ctimeNs: 1318289051000000000n,
|
|
59
|
-
* birthtimeNs: 1318289051000000000n,
|
|
60
|
-
* atime: Mon, 10 Oct 2011 23:24:11 GMT,
|
|
61
|
-
* mtime: Mon, 10 Oct 2011 23:24:11 GMT,
|
|
62
|
-
* ctime: Mon, 10 Oct 2011 23:24:11 GMT,
|
|
63
|
-
* birthtime: Mon, 10 Oct 2011 23:24:11 GMT }
|
|
64
|
-
* ```
|
|
65
52
|
* @since v0.1.21
|
|
66
53
|
*/
|
|
67
54
|
export class Stats extends Dirent implements NodeStats {
|
|
@@ -78,29 +65,143 @@ export class Stats extends Dirent implements NodeStats {
|
|
|
78
65
|
atimeMs: number;
|
|
79
66
|
mtimeMs: number;
|
|
80
67
|
ctimeMs: number;
|
|
81
|
-
|
|
82
|
-
get birthtimeMs(): number {
|
|
83
|
-
const creationDateTime = this._info.get_creation_date_time();
|
|
84
|
-
return creationDateTime.get_microsecond() * 1000;
|
|
85
|
-
}
|
|
68
|
+
birthtimeMs: number;
|
|
86
69
|
atime: Date;
|
|
87
70
|
mtime: Date;
|
|
88
71
|
ctime: Date;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
72
|
+
birthtime: Date;
|
|
73
|
+
|
|
74
|
+
protected _info: Gio.FileInfo;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Create Stats from a pre-queried FileInfo, or from a path.
|
|
78
|
+
* @param infoOrPath - A Gio.FileInfo or a file path
|
|
79
|
+
* @param pathOrFilename - The file path (when first arg is FileInfo) or filename
|
|
80
|
+
* @param filename - Optional filename (when first arg is FileInfo)
|
|
81
|
+
*/
|
|
82
|
+
constructor(info: Gio.FileInfo, path: PathLike, filename?: string);
|
|
83
|
+
constructor(path: PathLike, filename?: string);
|
|
84
|
+
constructor(
|
|
85
|
+
infoOrPath: Gio.FileInfo | PathLike,
|
|
86
|
+
pathOrFilename?: PathLike | string,
|
|
87
|
+
filename?: string
|
|
88
|
+
) {
|
|
89
|
+
let info: Gio.FileInfo;
|
|
90
|
+
let pathStr: string;
|
|
91
|
+
|
|
92
|
+
if (infoOrPath instanceof Gio.FileInfo) {
|
|
93
|
+
info = infoOrPath;
|
|
94
|
+
pathStr = (pathOrFilename as PathLike).toString();
|
|
95
|
+
if (!filename) filename = basename(pathStr);
|
|
96
|
+
} else {
|
|
97
|
+
pathStr = infoOrPath.toString();
|
|
98
|
+
if (typeof pathOrFilename === 'string') filename = pathOrFilename;
|
|
99
|
+
if (!filename) filename = basename(pathStr);
|
|
100
|
+
const file = Gio.File.new_for_path(pathStr);
|
|
101
|
+
info = file.query_info(STAT_ATTRIBUTES, Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
super(pathStr, filename, info.get_file_type());
|
|
105
|
+
this._info = info;
|
|
106
|
+
|
|
107
|
+
const data = populateFromInfo(info);
|
|
108
|
+
this.dev = data.dev;
|
|
109
|
+
this.ino = data.ino;
|
|
110
|
+
this.mode = data.mode;
|
|
111
|
+
this.nlink = data.nlink;
|
|
112
|
+
this.uid = data.uid;
|
|
113
|
+
this.gid = data.gid;
|
|
114
|
+
this.rdev = data.rdev;
|
|
115
|
+
this.size = data.size;
|
|
116
|
+
this.blksize = data.blksize;
|
|
117
|
+
this.blocks = data.blocks;
|
|
118
|
+
this.atimeMs = data.atimeMs;
|
|
119
|
+
this.mtimeMs = data.mtimeMs;
|
|
120
|
+
this.ctimeMs = data.ctimeMs;
|
|
121
|
+
this.birthtimeMs = data.birthtimeMs;
|
|
122
|
+
this.atime = data.atime;
|
|
123
|
+
this.mtime = data.mtime;
|
|
124
|
+
this.ctime = data.ctime;
|
|
125
|
+
this.birthtime = data.birthtime;
|
|
93
126
|
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* BigIntStats — same as Stats but with bigint fields and nanosecond precision.
|
|
131
|
+
*/
|
|
132
|
+
export class BigIntStats extends Dirent implements NodeBigIntStats {
|
|
133
|
+
dev: bigint;
|
|
134
|
+
ino: bigint;
|
|
135
|
+
mode: bigint;
|
|
136
|
+
nlink: bigint;
|
|
137
|
+
uid: bigint;
|
|
138
|
+
gid: bigint;
|
|
139
|
+
rdev: bigint;
|
|
140
|
+
size: bigint;
|
|
141
|
+
blksize: bigint;
|
|
142
|
+
blocks: bigint;
|
|
143
|
+
atimeMs: bigint;
|
|
144
|
+
mtimeMs: bigint;
|
|
145
|
+
ctimeMs: bigint;
|
|
146
|
+
birthtimeMs: bigint;
|
|
147
|
+
atimeNs: bigint;
|
|
148
|
+
mtimeNs: bigint;
|
|
149
|
+
ctimeNs: bigint;
|
|
150
|
+
birthtimeNs: bigint;
|
|
151
|
+
atime: Date;
|
|
152
|
+
mtime: Date;
|
|
153
|
+
ctime: Date;
|
|
154
|
+
birthtime: Date;
|
|
94
155
|
|
|
95
156
|
protected _info: Gio.FileInfo;
|
|
96
157
|
|
|
97
|
-
constructor(path: PathLike, filename?: string)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
158
|
+
constructor(info: Gio.FileInfo, path: PathLike, filename?: string);
|
|
159
|
+
constructor(path: PathLike, filename?: string);
|
|
160
|
+
constructor(
|
|
161
|
+
infoOrPath: Gio.FileInfo | PathLike,
|
|
162
|
+
pathOrFilename?: PathLike | string,
|
|
163
|
+
filename?: string
|
|
164
|
+
) {
|
|
165
|
+
let info: Gio.FileInfo;
|
|
166
|
+
let pathStr: string;
|
|
167
|
+
|
|
168
|
+
if (infoOrPath instanceof Gio.FileInfo) {
|
|
169
|
+
info = infoOrPath;
|
|
170
|
+
pathStr = (pathOrFilename as PathLike).toString();
|
|
171
|
+
if (!filename) filename = basename(pathStr);
|
|
172
|
+
} else {
|
|
173
|
+
pathStr = infoOrPath.toString();
|
|
174
|
+
if (typeof pathOrFilename === 'string') filename = pathOrFilename;
|
|
175
|
+
if (!filename) filename = basename(pathStr);
|
|
176
|
+
const file = Gio.File.new_for_path(pathStr);
|
|
177
|
+
info = file.query_info(STAT_ATTRIBUTES, Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null);
|
|
103
178
|
}
|
|
104
|
-
|
|
179
|
+
|
|
180
|
+
super(pathStr, filename, info.get_file_type());
|
|
181
|
+
this._info = info;
|
|
182
|
+
|
|
183
|
+
const data = populateFromInfo(info);
|
|
184
|
+
this.dev = BigInt(data.dev);
|
|
185
|
+
this.ino = BigInt(data.ino);
|
|
186
|
+
this.mode = BigInt(data.mode);
|
|
187
|
+
this.nlink = BigInt(data.nlink);
|
|
188
|
+
this.uid = BigInt(data.uid);
|
|
189
|
+
this.gid = BigInt(data.gid);
|
|
190
|
+
this.rdev = BigInt(data.rdev);
|
|
191
|
+
this.size = BigInt(data.size);
|
|
192
|
+
this.blksize = BigInt(data.blksize);
|
|
193
|
+
this.blocks = BigInt(data.blocks);
|
|
194
|
+
this.atimeMs = BigInt(Math.trunc(data.atimeMs));
|
|
195
|
+
this.mtimeMs = BigInt(Math.trunc(data.mtimeMs));
|
|
196
|
+
this.ctimeMs = BigInt(Math.trunc(data.ctimeMs));
|
|
197
|
+
this.birthtimeMs = BigInt(Math.trunc(data.birthtimeMs));
|
|
198
|
+
this.atimeNs = this.atimeMs * 1000000n;
|
|
199
|
+
this.mtimeNs = this.mtimeMs * 1000000n;
|
|
200
|
+
this.ctimeNs = this.ctimeMs * 1000000n;
|
|
201
|
+
this.birthtimeNs = this.birthtimeMs * 1000000n;
|
|
202
|
+
this.atime = data.atime;
|
|
203
|
+
this.mtime = data.mtime;
|
|
204
|
+
this.ctime = data.ctime;
|
|
205
|
+
this.birthtime = data.birthtime;
|
|
105
206
|
}
|
|
106
|
-
}
|
|
207
|
+
}
|