@gjsify/fs 0.4.0 → 0.4.3

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 (50) hide show
  1. package/package.json +51 -48
  2. package/src/callback.spec.ts +0 -296
  3. package/src/callback.ts +0 -684
  4. package/src/cp.spec.ts +0 -181
  5. package/src/cp.ts +0 -328
  6. package/src/dir.spec.ts +0 -204
  7. package/src/dir.ts +0 -199
  8. package/src/dirent.ts +0 -165
  9. package/src/encoding.ts +0 -45
  10. package/src/errors.spec.ts +0 -389
  11. package/src/errors.ts +0 -19
  12. package/src/extended.spec.ts +0 -706
  13. package/src/fd-ops.spec.ts +0 -234
  14. package/src/fd-ops.ts +0 -251
  15. package/src/file-handle.spec.ts +0 -115
  16. package/src/file-handle.ts +0 -856
  17. package/src/fs-watcher.ts +0 -198
  18. package/src/glob.spec.ts +0 -201
  19. package/src/glob.ts +0 -205
  20. package/src/index.ts +0 -313
  21. package/src/new-apis.spec.ts +0 -505
  22. package/src/promises.spec.ts +0 -812
  23. package/src/promises.ts +0 -686
  24. package/src/read-stream.ts +0 -128
  25. package/src/stat-watcher.ts +0 -116
  26. package/src/stat.spec.ts +0 -87
  27. package/src/statfs.spec.ts +0 -67
  28. package/src/statfs.ts +0 -92
  29. package/src/stats.ts +0 -207
  30. package/src/streams.spec.ts +0 -513
  31. package/src/symlink.spec.ts +0 -188
  32. package/src/sync.spec.ts +0 -377
  33. package/src/sync.ts +0 -568
  34. package/src/test.mts +0 -27
  35. package/src/types/encoding-option.ts +0 -3
  36. package/src/types/file-read-options.ts +0 -15
  37. package/src/types/file-read-result.ts +0 -4
  38. package/src/types/flag-and-open-mode.ts +0 -6
  39. package/src/types/index.ts +0 -6
  40. package/src/types/open-flags.ts +0 -14
  41. package/src/types/read-options.ts +0 -9
  42. package/src/utils.ts +0 -31
  43. package/src/utimes.spec.ts +0 -113
  44. package/src/utimes.ts +0 -97
  45. package/src/watch.spec.ts +0 -171
  46. package/src/watchfile.spec.ts +0 -185
  47. package/src/write-stream.ts +0 -142
  48. package/test/file.txt +0 -1
  49. package/tsconfig.json +0 -29
  50. package/tsconfig.tsbuildinfo +0 -1
@@ -1,128 +0,0 @@
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';
6
- import GLib from '@girs/glib-2.0';
7
- import { Buffer } from "node:buffer";
8
- import { Readable } from "node:stream";
9
- import { normalizePath } from './utils.js';
10
-
11
- import type { CreateReadStreamOptions } from 'node:fs/promises';
12
- import type { PathLike, ReadStream as IReadStream } from 'node:fs';
13
-
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 _cancellable = new Gio.Cancellable();
23
- private _start: number;
24
- private _end: number;
25
- private _pos: number;
26
-
27
- close(callback?: (err?: NodeJS.ErrnoException | null) => void): void {
28
- this._cancellable.cancel();
29
- if (this._inputStream) {
30
- this._inputStream.close_async(GLib.PRIORITY_DEFAULT, null, () => {});
31
- this._inputStream = null;
32
- }
33
- this.destroy();
34
- if (callback) callback(null);
35
- }
36
-
37
- constructor(path: PathLike, opts?: CreateReadStreamOptions) {
38
- const pathStr = normalizePath(path);
39
-
40
- super({
41
- highWaterMark: opts?.highWaterMark ?? 64 * 1024,
42
- encoding: opts?.encoding as BufferEncoding | undefined,
43
- objectMode: false,
44
- });
45
-
46
- this.path = pathStr;
47
- this._gioFile = Gio.File.new_for_path(pathStr);
48
- this._start = (opts?.start as number) ?? 0;
49
- this._end = (opts?.end as number) ?? Infinity;
50
- this._pos = this._start;
51
- }
52
-
53
- // Use _construct() for async file opening so the stream machinery defers
54
- // _read() until the file is open. This avoids the fragile _pendingReadSize
55
- // pattern and correctly handles backpressure via the constructed flag.
56
- override _construct(callback: (err?: Error | null) => void): void {
57
- this._gioFile.read_async(GLib.PRIORITY_DEFAULT, this._cancellable, (_source, asyncResult) => {
58
- if (this.destroyed) { callback(); return; }
59
- try {
60
- this._inputStream = this._gioFile.read_finish(asyncResult);
61
- this.pending = false;
62
- this.emit('open', 0);
63
- this.emit('ready');
64
- if (this._start > 0 && this._inputStream!.can_seek()) {
65
- this._inputStream!.seek(this._start, GLib.SeekType.SET, null);
66
- }
67
- callback();
68
- } catch (err) {
69
- if (!this._cancellable.is_cancelled()) {
70
- callback(err as Error);
71
- }
72
- }
73
- });
74
- }
75
-
76
- override _read(size: number): void {
77
- this._doRead(size);
78
- }
79
-
80
- private _doRead(size: number): void {
81
- let toRead = size;
82
- if (this._end !== Infinity) {
83
- const remaining = this._end - this._pos + 1;
84
- if (remaining <= 0) {
85
- this.push(null);
86
- return;
87
- }
88
- toRead = Math.min(size, remaining);
89
- }
90
-
91
- const stream = this._inputStream!;
92
- stream.read_bytes_async(toRead, GLib.PRIORITY_DEFAULT, this._cancellable, (_source, asyncResult) => {
93
- try {
94
- const gbytes = stream.read_bytes_finish(asyncResult);
95
- const data = gbytes.get_data();
96
-
97
- if (!data || data.length === 0) {
98
- this.push(null);
99
- return;
100
- }
101
-
102
- this.bytesRead += data.length;
103
- this._pos += data.length;
104
- this.push(Buffer.from(data));
105
- } catch (err) {
106
- if (!this._cancellable.is_cancelled()) {
107
- this.destroy(err as Error);
108
- }
109
- }
110
- });
111
- }
112
-
113
- override _destroy(error: Error | null, callback: (error?: Error | null) => void): void {
114
- this._cancellable.cancel();
115
- if (this._inputStream) {
116
- this._inputStream.close_async(GLib.PRIORITY_DEFAULT, null, () => {});
117
- this._inputStream = null;
118
- }
119
- callback(error);
120
- }
121
- }
122
-
123
- export function createReadStream(
124
- path: string | URL,
125
- options?: CreateReadStreamOptions,
126
- ): ReadStream {
127
- return new ReadStream(path, options);
128
- }
@@ -1,116 +0,0 @@
1
- // Reference: Node.js lib/internal/fs/watchers.js (StatWatcher)
2
- // Reimplemented for GJS using setInterval polling
3
-
4
- import { EventEmitter } from 'node:events';
5
- import { statSync } from './sync.js';
6
-
7
- import type { PathLike, Stats } from 'node:fs';
8
-
9
- function zeroedStat(): Stats {
10
- return {
11
- dev: 0, ino: 0, mode: 0, nlink: 0, uid: 0, gid: 0, rdev: 0,
12
- size: 0, blksize: 0, blocks: 0,
13
- atimeMs: 0, mtimeMs: 0, ctimeMs: 0, birthtimeMs: 0,
14
- atime: new Date(0), mtime: new Date(0), ctime: new Date(0), birthtime: new Date(0),
15
- isFile: () => false, isDirectory: () => false, isBlockDevice: () => false,
16
- isCharacterDevice: () => false, isSymbolicLink: () => false, isFIFO: () => false,
17
- isSocket: () => false,
18
- } as unknown as Stats;
19
- }
20
-
21
- export class StatWatcher extends EventEmitter {
22
- private _path: string;
23
- private _interval: number;
24
- private _timerId: ReturnType<typeof setInterval> | null = null;
25
- private _prev: Stats;
26
- private _changeCount = 0;
27
-
28
- constructor(path: string, interval: number) {
29
- super();
30
- this._path = path;
31
- this._interval = interval;
32
- this._prev = zeroedStat();
33
- }
34
-
35
- start(): void {
36
- try { this._prev = statSync(this._path) as unknown as Stats; } catch {}
37
- this._timerId = setInterval(() => {
38
- let curr: Stats;
39
- try { curr = statSync(this._path) as unknown as Stats; } catch { curr = zeroedStat(); }
40
- const prev = this._prev;
41
- if (curr.mtimeMs !== prev.mtimeMs || curr.size !== prev.size || curr.ino !== prev.ino) {
42
- this._prev = curr;
43
- this.emit('change', curr, prev);
44
- }
45
- }, this._interval);
46
- }
47
-
48
- stop(): void {
49
- if (this._timerId !== null) {
50
- clearInterval(this._timerId);
51
- this._timerId = null;
52
- }
53
- this.emit('stop');
54
- }
55
-
56
- addChangeListener(listener: (curr: Stats, prev: Stats) => void): void {
57
- this._changeCount++;
58
- this.on('change', listener);
59
- }
60
-
61
- removeChangeListener(listener: (curr: Stats, prev: Stats) => void): void {
62
- this._changeCount--;
63
- this.removeListener('change', listener);
64
- }
65
-
66
- removeAllChangeListeners(): void {
67
- this._changeCount = 0;
68
- this.removeAllListeners('change');
69
- }
70
-
71
- get changeListenerCount(): number {
72
- return this._changeCount;
73
- }
74
- }
75
-
76
- const statWatchers = new Map<string, StatWatcher>();
77
-
78
- export function watchFile(
79
- filename: PathLike,
80
- options: { persistent?: boolean; interval?: number } | ((curr: Stats, prev: Stats) => void),
81
- listener?: (curr: Stats, prev: Stats) => void,
82
- ): StatWatcher {
83
- if (typeof options === 'function') {
84
- listener = options;
85
- options = {};
86
- }
87
- const interval = (options as { interval?: number }).interval ?? 5007;
88
- const resolved = filename.toString();
89
-
90
- let watcher = statWatchers.get(resolved);
91
- if (!watcher) {
92
- watcher = new StatWatcher(resolved, interval);
93
- watcher.start();
94
- statWatchers.set(resolved, watcher);
95
- }
96
- if (listener) watcher.addChangeListener(listener);
97
- return watcher;
98
- }
99
-
100
- export function unwatchFile(
101
- filename: PathLike,
102
- listener?: (curr: Stats, prev: Stats) => void,
103
- ): void {
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
- }
116
- }
package/src/stat.spec.ts DELETED
@@ -1,87 +0,0 @@
1
- import { describe, it, expect } from '@gjsify/unit';
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';
6
-
7
- export default async () => {
8
- await describe('fs.statSync', async () => {
9
-
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');
14
-
15
- const s = statSync(filePath);
16
-
17
- expect(s.atime instanceof Date).toBeTruthy();
18
- expect(s.atimeMs).toBeGreaterThan(0);
19
- expect(s.birthtime instanceof Date).toBeTruthy();
20
- expect(s.birthtimeMs).toBeGreaterThan(0);
21
- expect(s.blksize).toBeGreaterThan(0);
22
- expect(s.blocks).toBeGreaterThan(0);
23
- expect(s.ctime instanceof Date).toBeTruthy();
24
- expect(s.ctimeMs).toBeGreaterThan(0);
25
- expect(s.dev).toBeGreaterThan(0);
26
- expect(s.gid).toBeGreaterThan(-1);
27
- expect(s.ino).toBeGreaterThan(0);
28
- expect(s.mode).toBeGreaterThan(0);
29
- expect(s.mtime instanceof Date).toBeTruthy();
30
- expect(s.mtimeMs).toBeGreaterThan(0);
31
- expect(s.nlink).toBeGreaterThan(0);
32
- expect(s.rdev).toBeGreaterThan(-1);
33
- expect(s.size).toBeGreaterThan(0);
34
- expect(s.uid).toBeGreaterThan(-1);
35
- expect(s.isBlockDevice()).toBeFalsy();
36
- expect(s.isCharacterDevice()).toBeFalsy();
37
- expect(s.isDirectory()).toBeFalsy();
38
- expect(s.isFIFO()).toBeFalsy();
39
- expect(s.isFile()).toBeTruthy();
40
- expect(s.isSocket()).toBeFalsy();
41
- expect(s.isSymbolicLink()).toBeFalsy();
42
-
43
- rmSync(filePath);
44
- rmdirSync(dir);
45
- });
46
- });
47
-
48
- await describe('fs.stat (promise)', async () => {
49
-
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');
54
-
55
- const s = await stat(filePath);
56
-
57
- expect(s.atime instanceof Date).toBeTruthy();
58
- expect(s.atimeMs).toBeGreaterThan(0);
59
- expect(s.birthtime instanceof Date).toBeTruthy();
60
- expect(s.birthtimeMs).toBeGreaterThan(0);
61
- expect(s.blksize).toBeGreaterThan(0);
62
- expect(s.blocks).toBeGreaterThan(0);
63
- expect(s.ctime instanceof Date).toBeTruthy();
64
- expect(s.ctimeMs).toBeGreaterThan(0);
65
- expect(s.dev).toBeGreaterThan(0);
66
- expect(s.gid).toBeGreaterThan(-1);
67
- expect(s.ino).toBeGreaterThan(0);
68
- expect(s.mode).toBeGreaterThan(0);
69
- expect(s.mtime instanceof Date).toBeTruthy();
70
- expect(s.mtimeMs).toBeGreaterThan(0);
71
- expect(s.nlink).toBeGreaterThan(0);
72
- expect(s.rdev).toBeGreaterThan(-1);
73
- expect(s.size).toBeGreaterThan(0);
74
- expect(s.uid).toBeGreaterThan(-1);
75
- expect(s.isBlockDevice()).toBeFalsy();
76
- expect(s.isCharacterDevice()).toBeFalsy();
77
- expect(s.isDirectory()).toBeFalsy();
78
- expect(s.isFIFO()).toBeFalsy();
79
- expect(s.isFile()).toBeTruthy();
80
- expect(s.isSocket()).toBeFalsy();
81
- expect(s.isSymbolicLink()).toBeFalsy();
82
-
83
- rmSync(filePath);
84
- rmdirSync(dir);
85
- });
86
- });
87
- }
@@ -1,67 +0,0 @@
1
- // Ported from refs/node-test/parallel/test-fs-statfs.js (behavior)
2
- // Original: MIT, Node.js contributors.
3
- // Rewritten for @gjsify/unit — behavior preserved, assertion dialect adapted.
4
-
5
- import { describe, it, expect } from '@gjsify/unit';
6
- import { statfsSync, statfs, promises } from 'node:fs';
7
- import { tmpdir } from 'node:os';
8
-
9
- const TMP = tmpdir();
10
-
11
- export default async () => {
12
- await describe('fs.statfs / fs.promises.statfs', async () => {
13
- await it('statfsSync returns object with expected shape', async () => {
14
- const result = statfsSync(TMP);
15
- expect(typeof result.type).toBe('number');
16
- expect(typeof result.bsize).toBe('number');
17
- expect(typeof result.blocks).toBe('number');
18
- expect(typeof result.bfree).toBe('number');
19
- expect(typeof result.bavail).toBe('number');
20
- expect(typeof result.files).toBe('number');
21
- expect(typeof result.ffree).toBe('number');
22
- });
23
-
24
- await it('statfsSync returns plausible values', async () => {
25
- const result = statfsSync(TMP);
26
- expect(result.bsize).toBe(4096);
27
- expect(result.blocks).toBeGreaterThan(0);
28
- expect(result.bfree).toBeGreaterThanOrEqual(0);
29
- expect(result.bavail).toBeGreaterThanOrEqual(0);
30
- });
31
-
32
- await it('statfs callback form returns same shape', async () => {
33
- const result = await new Promise<any>((resolve, reject) => {
34
- statfs(TMP, (err, stats) => {
35
- if (err) reject(err);
36
- else resolve(stats);
37
- });
38
- });
39
- expect(typeof result.type).toBe('number');
40
- expect(typeof result.bsize).toBe('number');
41
- expect(result.bsize).toBe(4096);
42
- expect(result.blocks).toBeGreaterThan(0);
43
- });
44
-
45
- await it('promises.statfs returns same shape', async () => {
46
- const result = await promises.statfs(TMP);
47
- expect(typeof result.type).toBe('number');
48
- expect(typeof result.bsize).toBe('number');
49
- expect(result.bsize).toBe(4096);
50
- expect(result.blocks).toBeGreaterThan(0);
51
- });
52
-
53
- await it('statfsSync with bigint:true returns bigint fields', async () => {
54
- const result = statfsSync(TMP, { bigint: true });
55
- expect(typeof result.type).toBe('bigint');
56
- expect(typeof result.bsize).toBe('bigint');
57
- expect(typeof result.blocks).toBe('bigint');
58
- expect(typeof result.bfree).toBe('bigint');
59
- expect(result.bsize).toBe(4096n);
60
- expect(result.blocks > 0n).toBe(true);
61
- });
62
-
63
- await it('statfsSync throws on non-existent path', async () => {
64
- expect(() => statfsSync('/nonexistent-gjsify-test-path-xyz')).toThrow();
65
- });
66
- });
67
- };
package/src/statfs.ts DELETED
@@ -1,92 +0,0 @@
1
- // Reference: Node.js lib/fs.js (fs.statfs / fs.promises.statfs)
2
- // Reimplemented for GJS using Gio.File.query_filesystem_info
3
-
4
- import Gio from '@girs/gio-2.0';
5
- import GLib from '@girs/glib-2.0';
6
- import { normalizePath } from './utils.js';
7
-
8
- import type { PathLike } from 'node:fs';
9
-
10
- const FS_INFO_ATTRS = [
11
- 'filesystem::size',
12
- 'filesystem::free',
13
- ].join(',');
14
-
15
- // Block size used to derive block counts from byte counts.
16
- // Gio does not expose the real fs block size; 4096 is a safe default.
17
- const BSIZE = 4096;
18
-
19
- export interface StatFsResult {
20
- type: number;
21
- bsize: number;
22
- blocks: number;
23
- bfree: number;
24
- bavail: number;
25
- files: number;
26
- ffree: number;
27
- }
28
-
29
- export interface BigIntStatFsResult {
30
- type: bigint;
31
- bsize: bigint;
32
- blocks: bigint;
33
- bfree: bigint;
34
- bavail: bigint;
35
- files: bigint;
36
- ffree: bigint;
37
- }
38
-
39
- function buildStatFs(info: Gio.FileInfo): StatFsResult {
40
- const totalBytes = Number(info.get_attribute_uint64('filesystem::size') ?? 0);
41
- const freeBytes = Number(info.get_attribute_uint64('filesystem::free') ?? 0);
42
- const blocks = Math.floor(totalBytes / BSIZE);
43
- const bfree = Math.floor(freeBytes / BSIZE);
44
- return { type: 0, bsize: BSIZE, blocks, bfree, bavail: bfree, files: 0, ffree: 0 };
45
- }
46
-
47
- function buildBigIntStatFs(info: Gio.FileInfo): BigIntStatFsResult {
48
- const totalBytes = BigInt(info.get_attribute_uint64('filesystem::size') ?? 0);
49
- const freeBytes = BigInt(info.get_attribute_uint64('filesystem::free') ?? 0);
50
- const bsize = BigInt(BSIZE);
51
- const blocks = totalBytes / bsize;
52
- const bfree = freeBytes / bsize;
53
- return { type: 0n, bsize, blocks, bfree, bavail: bfree, files: 0n, ffree: 0n };
54
- }
55
-
56
- export function statfsSync(path: PathLike, options?: { bigint?: false }): StatFsResult;
57
- export function statfsSync(path: PathLike, options: { bigint: true }): BigIntStatFsResult;
58
- export function statfsSync(path: PathLike, options?: { bigint?: boolean }): StatFsResult | BigIntStatFsResult {
59
- const file = Gio.File.new_for_path(normalizePath(path));
60
- const info = file.query_filesystem_info(FS_INFO_ATTRS, null);
61
- return options?.bigint === true ? buildBigIntStatFs(info) : buildStatFs(info);
62
- }
63
-
64
- function queryFsInfoAsync(path: PathLike, useBigInt: boolean): Promise<StatFsResult | BigIntStatFsResult> {
65
- return new Promise((resolve, reject) => {
66
- const file = Gio.File.new_for_path(normalizePath(path));
67
- file.query_filesystem_info_async(FS_INFO_ATTRS, GLib.PRIORITY_DEFAULT, null, (_s: unknown, res: Gio.AsyncResult) => {
68
- try {
69
- const info = file.query_filesystem_info_finish(res);
70
- resolve(useBigInt ? buildBigIntStatFs(info) : buildStatFs(info));
71
- } catch (err) {
72
- reject(err);
73
- }
74
- });
75
- });
76
- }
77
-
78
- export function statfs(path: PathLike, callback: (err: NodeJS.ErrnoException | null, stats: StatFsResult) => void): void;
79
- export function statfs(path: PathLike, options: { bigint?: false }, callback: (err: NodeJS.ErrnoException | null, stats: StatFsResult) => void): void;
80
- export function statfs(path: PathLike, options: { bigint: true }, callback: (err: NodeJS.ErrnoException | null, stats: BigIntStatFsResult) => void): void;
81
- export function statfs(path: PathLike, optionsOrCb: any, callback?: any): void {
82
- if (typeof optionsOrCb === 'function') {
83
- callback = optionsOrCb;
84
- optionsOrCb = {};
85
- }
86
- const useBigInt = optionsOrCb?.bigint === true;
87
- queryFsInfoAsync(path, useBigInt).then(result => callback(null, result), err => callback(err, null));
88
- }
89
-
90
- export async function statfsAsync(path: PathLike, options?: { bigint?: boolean }): Promise<StatFsResult | BigIntStatFsResult> {
91
- return queryFsInfoAsync(path, options?.bigint === true);
92
- }
package/src/stats.ts DELETED
@@ -1,207 +0,0 @@
1
- // Reference: Node.js lib/internal/fs/utils.js (Stats class)
2
- // Reimplemented for GJS using Gio.FileInfo attributes
3
-
4
- import Gio from '@girs/gio-2.0';
5
- import { Dirent } from './dirent.js';
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::*';
12
-
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
- }
49
-
50
- /**
51
- * A `fs.Stats` object provides information about a file.
52
- * @since v0.1.21
53
- */
54
- export class Stats extends Dirent implements NodeStats {
55
- dev: number;
56
- ino: number;
57
- mode: number;
58
- nlink: number;
59
- uid: number;
60
- gid: number;
61
- rdev: number;
62
- size: number;
63
- blksize: number;
64
- blocks: number;
65
- atimeMs: number;
66
- mtimeMs: number;
67
- ctimeMs: number;
68
- birthtimeMs: number;
69
- atime: Date;
70
- mtime: Date;
71
- ctime: Date;
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;
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;
155
-
156
- protected _info: Gio.FileInfo;
157
-
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);
178
- }
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;
206
- }
207
- }