@gjsify/fs 0.3.21 → 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.
- package/lib/esm/_virtual/_rolldown/runtime.js +1 -1
- package/lib/esm/callback.js +1 -1
- package/lib/esm/cp.js +1 -1
- package/lib/esm/dir.js +1 -1
- package/lib/esm/dirent.js +1 -1
- package/lib/esm/encoding.js +1 -1
- package/lib/esm/errors.js +1 -1
- package/lib/esm/fd-ops.js +1 -1
- package/lib/esm/file-handle.js +1 -1
- package/lib/esm/fs-watcher.js +1 -1
- package/lib/esm/glob.js +1 -1
- package/lib/esm/read-stream.js +1 -1
- package/lib/esm/stat-watcher.js +1 -1
- package/lib/esm/statfs.js +1 -1
- package/lib/esm/stats.js +1 -1
- package/lib/esm/sync.js +1 -1
- package/lib/esm/utils.js +1 -1
- package/lib/esm/utimes.js +1 -1
- package/lib/esm/write-stream.js +1 -1
- package/package.json +51 -48
- package/src/callback.spec.ts +0 -296
- package/src/callback.ts +0 -684
- package/src/cp.spec.ts +0 -181
- package/src/cp.ts +0 -328
- package/src/dir.spec.ts +0 -204
- package/src/dir.ts +0 -199
- package/src/dirent.ts +0 -165
- package/src/encoding.ts +0 -45
- package/src/errors.spec.ts +0 -389
- package/src/errors.ts +0 -19
- package/src/extended.spec.ts +0 -706
- package/src/fd-ops.spec.ts +0 -234
- package/src/fd-ops.ts +0 -251
- package/src/file-handle.spec.ts +0 -115
- package/src/file-handle.ts +0 -856
- package/src/fs-watcher.ts +0 -198
- package/src/glob.spec.ts +0 -201
- package/src/glob.ts +0 -205
- package/src/index.ts +0 -313
- package/src/new-apis.spec.ts +0 -505
- package/src/promises.spec.ts +0 -812
- package/src/promises.ts +0 -686
- package/src/read-stream.ts +0 -128
- package/src/stat-watcher.ts +0 -116
- package/src/stat.spec.ts +0 -87
- package/src/statfs.spec.ts +0 -67
- package/src/statfs.ts +0 -92
- package/src/stats.ts +0 -207
- package/src/streams.spec.ts +0 -513
- package/src/symlink.spec.ts +0 -188
- package/src/sync.spec.ts +0 -377
- package/src/sync.ts +0 -562
- package/src/test.mts +0 -27
- package/src/types/encoding-option.ts +0 -3
- package/src/types/file-read-options.ts +0 -15
- package/src/types/file-read-result.ts +0 -4
- package/src/types/flag-and-open-mode.ts +0 -6
- package/src/types/index.ts +0 -6
- package/src/types/open-flags.ts +0 -14
- package/src/types/read-options.ts +0 -9
- package/src/utils.ts +0 -31
- package/src/utimes.spec.ts +0 -113
- package/src/utimes.ts +0 -97
- package/src/watch.spec.ts +0 -171
- package/src/watchfile.spec.ts +0 -185
- package/src/write-stream.ts +0 -142
- package/test/file.txt +0 -1
- package/tsconfig.json +0 -29
- package/tsconfig.tsbuildinfo +0 -1
package/src/dir.spec.ts
DELETED
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
// Ported from refs/bun/test/js/node/fs/dir.test.ts
|
|
2
|
-
// Original: MIT, Oven & contributors.
|
|
3
|
-
// Rewritten for @gjsify/unit — behavior preserved, assertion dialect adapted.
|
|
4
|
-
|
|
5
|
-
import { describe, it, expect } from '@gjsify/unit';
|
|
6
|
-
import {
|
|
7
|
-
Dir,
|
|
8
|
-
opendirSync,
|
|
9
|
-
opendir,
|
|
10
|
-
promises,
|
|
11
|
-
mkdirSync,
|
|
12
|
-
writeFileSync,
|
|
13
|
-
mkdtempSync,
|
|
14
|
-
rmSync,
|
|
15
|
-
} from 'node:fs';
|
|
16
|
-
import { join } from 'node:path';
|
|
17
|
-
import { tmpdir } from 'node:os';
|
|
18
|
-
|
|
19
|
-
function makeTmp(): string {
|
|
20
|
-
return mkdtempSync(join(tmpdir(), 'gjsify-dir-'));
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export default async () => {
|
|
24
|
-
await describe('fs.opendirSync', async () => {
|
|
25
|
-
await it('returns a Dir instance', async () => {
|
|
26
|
-
const tmp = makeTmp();
|
|
27
|
-
const dir = opendirSync(tmp);
|
|
28
|
-
expect(dir).toBeDefined();
|
|
29
|
-
expect(dir instanceof Dir).toBe(true);
|
|
30
|
-
dir.closeSync();
|
|
31
|
-
rmSync(tmp, { recursive: true, force: true });
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
await it('dir.path reflects the opened path', async () => {
|
|
35
|
-
const tmp = makeTmp();
|
|
36
|
-
const dir = opendirSync(tmp);
|
|
37
|
-
expect(dir.path).toBe(tmp);
|
|
38
|
-
dir.closeSync();
|
|
39
|
-
rmSync(tmp, { recursive: true, force: true });
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
await it('readSync returns null on empty directory', async () => {
|
|
43
|
-
const tmp = makeTmp();
|
|
44
|
-
const dir = opendirSync(tmp);
|
|
45
|
-
const entry = dir.readSync();
|
|
46
|
-
expect(entry).toBeNull();
|
|
47
|
-
dir.closeSync();
|
|
48
|
-
rmSync(tmp, { recursive: true, force: true });
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
await it('readSync returns Dirent entries for directory contents', async () => {
|
|
52
|
-
const tmp = makeTmp();
|
|
53
|
-
writeFileSync(join(tmp, 'a.txt'), 'a');
|
|
54
|
-
writeFileSync(join(tmp, 'b.txt'), 'b');
|
|
55
|
-
|
|
56
|
-
const dir = opendirSync(tmp);
|
|
57
|
-
const names: string[] = [];
|
|
58
|
-
let entry = dir.readSync();
|
|
59
|
-
while (entry !== null) {
|
|
60
|
-
names.push(entry.name);
|
|
61
|
-
entry = dir.readSync();
|
|
62
|
-
}
|
|
63
|
-
dir.closeSync();
|
|
64
|
-
|
|
65
|
-
expect(names.sort()).toStrictEqual(['a.txt', 'b.txt']);
|
|
66
|
-
rmSync(tmp, { recursive: true, force: true });
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
await it('Dirent has correct type flags', async () => {
|
|
70
|
-
const tmp = makeTmp();
|
|
71
|
-
writeFileSync(join(tmp, 'file.txt'), 'x');
|
|
72
|
-
mkdirSync(join(tmp, 'subdir'));
|
|
73
|
-
|
|
74
|
-
const dir = opendirSync(tmp);
|
|
75
|
-
const entries: { name: string; isFile: boolean; isDirectory: boolean }[] = [];
|
|
76
|
-
let entry = dir.readSync();
|
|
77
|
-
while (entry !== null) {
|
|
78
|
-
entries.push({ name: entry.name, isFile: entry.isFile(), isDirectory: entry.isDirectory() });
|
|
79
|
-
entry = dir.readSync();
|
|
80
|
-
}
|
|
81
|
-
dir.closeSync();
|
|
82
|
-
|
|
83
|
-
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
84
|
-
expect(entries).toStrictEqual([
|
|
85
|
-
{ name: 'file.txt', isFile: true, isDirectory: false },
|
|
86
|
-
{ name: 'subdir', isFile: false, isDirectory: true },
|
|
87
|
-
]);
|
|
88
|
-
rmSync(tmp, { recursive: true, force: true });
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
await it('closeSync throws after close', async () => {
|
|
92
|
-
const tmp = makeTmp();
|
|
93
|
-
const dir = opendirSync(tmp);
|
|
94
|
-
dir.closeSync();
|
|
95
|
-
|
|
96
|
-
let threw = false;
|
|
97
|
-
try {
|
|
98
|
-
dir.closeSync();
|
|
99
|
-
} catch (e: any) {
|
|
100
|
-
threw = true;
|
|
101
|
-
expect(e.code).toBe('ERR_DIR_CLOSED');
|
|
102
|
-
}
|
|
103
|
-
expect(threw).toBe(true);
|
|
104
|
-
rmSync(tmp, { recursive: true, force: true });
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
await it('readSync throws after close', async () => {
|
|
108
|
-
const tmp = makeTmp();
|
|
109
|
-
const dir = opendirSync(tmp);
|
|
110
|
-
dir.closeSync();
|
|
111
|
-
|
|
112
|
-
let threw = false;
|
|
113
|
-
try {
|
|
114
|
-
dir.readSync();
|
|
115
|
-
} catch (e: any) {
|
|
116
|
-
threw = true;
|
|
117
|
-
expect(e.code).toBe('ERR_DIR_CLOSED');
|
|
118
|
-
}
|
|
119
|
-
expect(threw).toBe(true);
|
|
120
|
-
rmSync(tmp, { recursive: true, force: true });
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
await it('read() returns Dirent or null asynchronously', async () => {
|
|
124
|
-
const tmp = makeTmp();
|
|
125
|
-
writeFileSync(join(tmp, 'hello.txt'), 'hi');
|
|
126
|
-
|
|
127
|
-
const dir = opendirSync(tmp);
|
|
128
|
-
const entry = await dir.read();
|
|
129
|
-
expect(entry).toBeDefined();
|
|
130
|
-
expect(entry!.name).toBe('hello.txt');
|
|
131
|
-
|
|
132
|
-
const next = await dir.read();
|
|
133
|
-
expect(next).toBeNull();
|
|
134
|
-
await dir.close();
|
|
135
|
-
rmSync(tmp, { recursive: true, force: true });
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
await it('[Symbol.asyncIterator] iterates all entries', async () => {
|
|
139
|
-
const tmp = makeTmp();
|
|
140
|
-
writeFileSync(join(tmp, 'x.ts'), '');
|
|
141
|
-
writeFileSync(join(tmp, 'y.ts'), '');
|
|
142
|
-
|
|
143
|
-
const dir = opendirSync(tmp);
|
|
144
|
-
const names: string[] = [];
|
|
145
|
-
for await (const entry of dir) {
|
|
146
|
-
names.push(entry.name);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
expect(names.sort()).toStrictEqual(['x.ts', 'y.ts']);
|
|
150
|
-
rmSync(tmp, { recursive: true, force: true });
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
await describe('fs.opendir (callback)', async () => {
|
|
155
|
-
await it('opens directory and returns Dir instance via callback', async () => {
|
|
156
|
-
const tmp = makeTmp();
|
|
157
|
-
await new Promise<void>((resolve, reject) => {
|
|
158
|
-
opendir(tmp, (err, dir) => {
|
|
159
|
-
if (err) return reject(err);
|
|
160
|
-
expect(dir instanceof Dir).toBe(true);
|
|
161
|
-
expect(dir.path).toBe(tmp);
|
|
162
|
-
dir.closeSync();
|
|
163
|
-
rmSync(tmp, { recursive: true, force: true });
|
|
164
|
-
resolve();
|
|
165
|
-
});
|
|
166
|
-
});
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
await it('throws if callback is not a function', async () => {
|
|
170
|
-
let threw = false;
|
|
171
|
-
try {
|
|
172
|
-
(opendir as any)('/tmp');
|
|
173
|
-
} catch (e: any) {
|
|
174
|
-
threw = true;
|
|
175
|
-
}
|
|
176
|
-
expect(threw).toBe(true);
|
|
177
|
-
});
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
await describe('fs.promises.opendir', async () => {
|
|
181
|
-
await it('opens directory and returns Dir instance', async () => {
|
|
182
|
-
const tmp = makeTmp();
|
|
183
|
-
const dir = await promises.opendir(tmp);
|
|
184
|
-
expect(dir instanceof Dir).toBe(true);
|
|
185
|
-
await dir.close();
|
|
186
|
-
rmSync(tmp, { recursive: true, force: true });
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
await it('async iterates directory entries', async () => {
|
|
190
|
-
const tmp = makeTmp();
|
|
191
|
-
writeFileSync(join(tmp, 'alpha.txt'), '');
|
|
192
|
-
writeFileSync(join(tmp, 'beta.txt'), '');
|
|
193
|
-
|
|
194
|
-
const dir = await promises.opendir(tmp);
|
|
195
|
-
const names: string[] = [];
|
|
196
|
-
for await (const entry of dir) {
|
|
197
|
-
names.push(entry.name);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
expect(names.sort()).toStrictEqual(['alpha.txt', 'beta.txt']);
|
|
201
|
-
rmSync(tmp, { recursive: true, force: true });
|
|
202
|
-
});
|
|
203
|
-
});
|
|
204
|
-
};
|
package/src/dir.ts
DELETED
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
// Reference: Node.js lib/internal/fs/dir.js
|
|
2
|
-
// Reimplemented for GJS using Gio.FileEnumerator
|
|
3
|
-
|
|
4
|
-
import Gio from '@girs/gio-2.0';
|
|
5
|
-
import GLib from '@girs/glib-2.0';
|
|
6
|
-
import { normalizePath } from './utils.js';
|
|
7
|
-
import { Dirent } from './dirent.js';
|
|
8
|
-
import { createNodeError } from './errors.js';
|
|
9
|
-
import type { PathLike } from 'node:fs';
|
|
10
|
-
|
|
11
|
-
const DIR_ATTRS = 'standard::name,standard::type,standard::is-symlink,standard::size,standard::symlink-target,unix::uid,unix::gid,unix::mode,time::modified,time::access,time::created';
|
|
12
|
-
|
|
13
|
-
export class Dir {
|
|
14
|
-
readonly path: string;
|
|
15
|
-
private _enumerator: Gio.FileEnumerator | null;
|
|
16
|
-
private _closed = false;
|
|
17
|
-
|
|
18
|
-
constructor(path: string, enumerator: Gio.FileEnumerator) {
|
|
19
|
-
this.path = path;
|
|
20
|
-
this._enumerator = enumerator;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
private _assertOpen(): void {
|
|
24
|
-
if (this._closed) {
|
|
25
|
-
const err = new Error('Directory handle was closed') as NodeJS.ErrnoException;
|
|
26
|
-
err.code = 'ERR_DIR_CLOSED';
|
|
27
|
-
throw err;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
readSync(): Dirent | null {
|
|
32
|
-
this._assertOpen();
|
|
33
|
-
try {
|
|
34
|
-
const info = this._enumerator!.next_file(null);
|
|
35
|
-
if (info === null) return null;
|
|
36
|
-
const name = info.get_name();
|
|
37
|
-
const fileType = info.get_file_type();
|
|
38
|
-
const childPath = this.path.endsWith('/') ? this.path + name : this.path + '/' + name;
|
|
39
|
-
return new Dirent(childPath, name, fileType);
|
|
40
|
-
} catch (err: unknown) {
|
|
41
|
-
throw createNodeError(err, 'readdir', this.path);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
read(): Promise<Dirent | null>;
|
|
46
|
-
read(callback: (err: NodeJS.ErrnoException | null, dirent: Dirent | null) => void): void;
|
|
47
|
-
read(callback?: (err: NodeJS.ErrnoException | null, dirent: Dirent | null) => void): Promise<Dirent | null> | void {
|
|
48
|
-
if (callback !== undefined) {
|
|
49
|
-
if (typeof callback !== 'function') {
|
|
50
|
-
throw new TypeError('The "callback" argument must be of type function');
|
|
51
|
-
}
|
|
52
|
-
try {
|
|
53
|
-
this._assertOpen();
|
|
54
|
-
const dirent = this.readSync();
|
|
55
|
-
Promise.resolve().then(() => callback(null, dirent));
|
|
56
|
-
} catch (err: unknown) {
|
|
57
|
-
Promise.resolve().then(() => callback(err as NodeJS.ErrnoException, null));
|
|
58
|
-
}
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return new Promise((resolve, reject) => {
|
|
63
|
-
try {
|
|
64
|
-
this._assertOpen();
|
|
65
|
-
resolve(this.readSync());
|
|
66
|
-
} catch (err: unknown) {
|
|
67
|
-
reject(err);
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
closeSync(): void {
|
|
73
|
-
this._assertOpen();
|
|
74
|
-
this._closed = true;
|
|
75
|
-
try {
|
|
76
|
-
this._enumerator!.close(null);
|
|
77
|
-
} catch {
|
|
78
|
-
// ignore close errors
|
|
79
|
-
}
|
|
80
|
-
this._enumerator = null;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
close(): Promise<void>;
|
|
84
|
-
close(callback: (err: NodeJS.ErrnoException | null) => void): void;
|
|
85
|
-
close(callback?: (err: NodeJS.ErrnoException | null) => void): Promise<void> | void {
|
|
86
|
-
if (callback !== undefined) {
|
|
87
|
-
if (typeof callback !== 'function') {
|
|
88
|
-
throw new TypeError('The "callback" argument must be of type function');
|
|
89
|
-
}
|
|
90
|
-
try {
|
|
91
|
-
this.closeSync();
|
|
92
|
-
Promise.resolve().then(() => callback(null));
|
|
93
|
-
} catch (err: unknown) {
|
|
94
|
-
Promise.resolve().then(() => callback(err as NodeJS.ErrnoException));
|
|
95
|
-
}
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return new Promise((resolve, reject) => {
|
|
100
|
-
try {
|
|
101
|
-
this.closeSync();
|
|
102
|
-
resolve();
|
|
103
|
-
} catch (err: unknown) {
|
|
104
|
-
reject(err);
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
async *[Symbol.asyncIterator](): AsyncIterableIterator<Dirent> {
|
|
110
|
-
try {
|
|
111
|
-
while (true) {
|
|
112
|
-
const dirent = await this.read();
|
|
113
|
-
if (dirent === null) break;
|
|
114
|
-
yield dirent;
|
|
115
|
-
}
|
|
116
|
-
} finally {
|
|
117
|
-
if (!this._closed) {
|
|
118
|
-
await this.close();
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function _openDir(pathStr: string): Dir {
|
|
125
|
-
const file = Gio.File.new_for_path(pathStr);
|
|
126
|
-
let enumerator: Gio.FileEnumerator;
|
|
127
|
-
try {
|
|
128
|
-
enumerator = file.enumerate_children(DIR_ATTRS, Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null);
|
|
129
|
-
} catch (err: unknown) {
|
|
130
|
-
throw createNodeError(err, 'opendir', pathStr);
|
|
131
|
-
}
|
|
132
|
-
return new Dir(pathStr, enumerator);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
export function opendirSync(path: PathLike): Dir {
|
|
136
|
-
return _openDir(normalizePath(path));
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
export function opendir(
|
|
140
|
-
path: PathLike,
|
|
141
|
-
callback: (err: NodeJS.ErrnoException | null, dir: Dir) => void,
|
|
142
|
-
): void;
|
|
143
|
-
export function opendir(
|
|
144
|
-
path: PathLike,
|
|
145
|
-
options: { encoding?: BufferEncoding | null; bufferSize?: number; recursive?: boolean },
|
|
146
|
-
callback: (err: NodeJS.ErrnoException | null, dir: Dir) => void,
|
|
147
|
-
): void;
|
|
148
|
-
export function opendir(
|
|
149
|
-
path: PathLike,
|
|
150
|
-
optionsOrCallback:
|
|
151
|
-
| { encoding?: BufferEncoding | null; bufferSize?: number; recursive?: boolean }
|
|
152
|
-
| ((err: NodeJS.ErrnoException | null, dir: Dir) => void),
|
|
153
|
-
callback?: (err: NodeJS.ErrnoException | null, dir: Dir) => void,
|
|
154
|
-
): void {
|
|
155
|
-
let cb: (err: NodeJS.ErrnoException | null, dir: Dir) => void;
|
|
156
|
-
if (typeof optionsOrCallback === 'function') {
|
|
157
|
-
cb = optionsOrCallback;
|
|
158
|
-
} else {
|
|
159
|
-
cb = callback!;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (typeof cb !== 'function') {
|
|
163
|
-
throw new TypeError('The "callback" argument must be of type function');
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
Promise.resolve().then(() => {
|
|
167
|
-
try {
|
|
168
|
-
const dir = opendirSync(path);
|
|
169
|
-
cb(null, dir);
|
|
170
|
-
} catch (err: unknown) {
|
|
171
|
-
cb(err as NodeJS.ErrnoException, null as unknown as Dir);
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// promises.opendir
|
|
177
|
-
export async function opendirAsync(
|
|
178
|
-
path: PathLike,
|
|
179
|
-
_options?: { encoding?: BufferEncoding | null; bufferSize?: number; recursive?: boolean },
|
|
180
|
-
): Promise<Dir> {
|
|
181
|
-
return new Promise<Dir>((resolve, reject) => {
|
|
182
|
-
const pathStr = normalizePath(path);
|
|
183
|
-
const file = Gio.File.new_for_path(pathStr);
|
|
184
|
-
file.enumerate_children_async(
|
|
185
|
-
DIR_ATTRS,
|
|
186
|
-
Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
|
|
187
|
-
GLib.PRIORITY_DEFAULT,
|
|
188
|
-
null,
|
|
189
|
-
(_source: unknown, result: Gio.AsyncResult) => {
|
|
190
|
-
try {
|
|
191
|
-
const enumerator = file.enumerate_children_finish(result);
|
|
192
|
-
resolve(new Dir(pathStr, enumerator));
|
|
193
|
-
} catch (err: unknown) {
|
|
194
|
-
reject(createNodeError(err, 'opendir', pathStr));
|
|
195
|
-
}
|
|
196
|
-
},
|
|
197
|
-
);
|
|
198
|
-
});
|
|
199
|
-
}
|
package/src/dirent.ts
DELETED
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
// Reference: Node.js lib/internal/fs/utils.js (Dirent class)
|
|
2
|
-
// Reimplemented for GJS using Gio.FileInfo
|
|
3
|
-
|
|
4
|
-
import Gio from '@girs/gio-2.0';
|
|
5
|
-
import { basename, dirname } from 'node:path';
|
|
6
|
-
|
|
7
|
-
import type { Dirent as OriginalDirent } from 'node:fs'; // Types from @types/node
|
|
8
|
-
|
|
9
|
-
// POSIX file type constants from stat mode bits (S_IFMT mask = 0o170000)
|
|
10
|
-
const S_IFMT = 0o170000;
|
|
11
|
-
const S_IFSOCK = 0o140000;
|
|
12
|
-
const S_IFLNK = 0o120000;
|
|
13
|
-
const S_IFREG = 0o100000;
|
|
14
|
-
const S_IFBLK = 0o060000;
|
|
15
|
-
const S_IFDIR = 0o040000;
|
|
16
|
-
const S_IFCHR = 0o020000;
|
|
17
|
-
const S_IFIFO = 0o010000;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* A representation of a directory entry, which can be a file or a subdirectory
|
|
21
|
-
* within the directory, as returned by reading from an `fs.Dir`. The
|
|
22
|
-
* directory entry is a combination of the file name and file type pairs.
|
|
23
|
-
*
|
|
24
|
-
* Additionally, when {@link readdir} or {@link readdirSync} is called with
|
|
25
|
-
* the `withFileTypes` option set to `true`, the resulting array is filled with `fs.Dirent` objects, rather than strings or `Buffer` s.
|
|
26
|
-
* @since v10.10.0
|
|
27
|
-
*/
|
|
28
|
-
export class Dirent implements OriginalDirent {
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* The file name that this `fs.Dirent` object refers to. The type of this
|
|
32
|
-
* value is determined by the `options.encoding` passed to {@link readdir} or {@link readdirSync}.
|
|
33
|
-
* @since v10.10.0
|
|
34
|
-
*/
|
|
35
|
-
name: string;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* The path to the parent directory of the file this `fs.Dirent` object refers to.
|
|
39
|
-
* @since v20.12.0, v18.20.0
|
|
40
|
-
*/
|
|
41
|
-
parentPath: string;
|
|
42
|
-
|
|
43
|
-
private _isFile = false;
|
|
44
|
-
private _isDirectory = false;
|
|
45
|
-
private _isBlockDevice = false;
|
|
46
|
-
private _isCharacterDevice = false;
|
|
47
|
-
private _isSymbolicLink = false;
|
|
48
|
-
private _isFIFO = false;
|
|
49
|
-
private _isSocket = false;
|
|
50
|
-
|
|
51
|
-
/** This is not part of node.fs and is used internal by gjsify */
|
|
52
|
-
protected _file: Gio.File;
|
|
53
|
-
|
|
54
|
-
/** This is not part of node.fs and is used internal by gjsify */
|
|
55
|
-
constructor(path: string, filename?: string, fileType?: Gio.FileType) {
|
|
56
|
-
if (!filename) filename = basename(path);
|
|
57
|
-
this.name = filename;
|
|
58
|
-
this.parentPath = dirname(path);
|
|
59
|
-
this._file = Gio.File.new_for_path(path);
|
|
60
|
-
const type = fileType ?? this._file.query_file_type(Gio.FileQueryInfoFlags.NONE, null);
|
|
61
|
-
|
|
62
|
-
switch (type) {
|
|
63
|
-
case Gio.FileType.DIRECTORY:
|
|
64
|
-
this._isDirectory = true;
|
|
65
|
-
break;
|
|
66
|
-
case Gio.FileType.MOUNTABLE:
|
|
67
|
-
break;
|
|
68
|
-
case Gio.FileType.REGULAR:
|
|
69
|
-
this._isFile = true;
|
|
70
|
-
break;
|
|
71
|
-
case Gio.FileType.SYMBOLIC_LINK:
|
|
72
|
-
case Gio.FileType.SHORTCUT:
|
|
73
|
-
this._isSymbolicLink = true; // ?
|
|
74
|
-
break;
|
|
75
|
-
case Gio.FileType.SPECIAL:
|
|
76
|
-
// File is a "special" file, such as a socket, fifo, block device, or character device.
|
|
77
|
-
// Use unix::mode from Gio.FileInfo to distinguish the exact type via POSIX S_IFMT bits.
|
|
78
|
-
this._classifySpecialFile(path);
|
|
79
|
-
break;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Classify a SPECIAL file type using the unix::mode attribute from Gio.FileInfo.
|
|
86
|
-
* Falls back to marking nothing if the mode attribute is unavailable.
|
|
87
|
-
*/
|
|
88
|
-
private _classifySpecialFile(path: string): void {
|
|
89
|
-
try {
|
|
90
|
-
const file = Gio.File.new_for_path(path);
|
|
91
|
-
const info = file.query_info('unix::mode', Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null);
|
|
92
|
-
const mode = info.get_attribute_uint32('unix::mode');
|
|
93
|
-
if (mode === 0) return;
|
|
94
|
-
const fmt = mode & S_IFMT;
|
|
95
|
-
switch (fmt) {
|
|
96
|
-
case S_IFBLK:
|
|
97
|
-
this._isBlockDevice = true;
|
|
98
|
-
break;
|
|
99
|
-
case S_IFCHR:
|
|
100
|
-
this._isCharacterDevice = true;
|
|
101
|
-
break;
|
|
102
|
-
case S_IFSOCK:
|
|
103
|
-
this._isSocket = true;
|
|
104
|
-
break;
|
|
105
|
-
case S_IFIFO:
|
|
106
|
-
this._isFIFO = true;
|
|
107
|
-
break;
|
|
108
|
-
}
|
|
109
|
-
} catch {
|
|
110
|
-
// If we can't query the mode (e.g. permission denied), leave all flags as false
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Returns `true` if the `fs.Dirent` object describes a regular file.
|
|
116
|
-
* @since v10.10.0
|
|
117
|
-
*/
|
|
118
|
-
isFile(): boolean {
|
|
119
|
-
return this._isFile;
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Returns `true` if the `fs.Dirent` object describes a file system
|
|
123
|
-
* directory.
|
|
124
|
-
* @since v10.10.0
|
|
125
|
-
*/
|
|
126
|
-
isDirectory(): boolean {
|
|
127
|
-
return this._isDirectory;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Returns `true` if the `fs.Dirent` object describes a block device.
|
|
131
|
-
* @since v10.10.0
|
|
132
|
-
*/
|
|
133
|
-
isBlockDevice(): boolean {
|
|
134
|
-
return this._isBlockDevice;
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Returns `true` if the `fs.Dirent` object describes a character device.
|
|
138
|
-
* @since v10.10.0
|
|
139
|
-
*/
|
|
140
|
-
isCharacterDevice(): boolean {
|
|
141
|
-
return this._isCharacterDevice;
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Returns `true` if the `fs.Dirent` object describes a symbolic link.
|
|
145
|
-
* @since v10.10.0
|
|
146
|
-
*/
|
|
147
|
-
isSymbolicLink(): boolean {
|
|
148
|
-
return this._isSymbolicLink;
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Returns `true` if the `fs.Dirent` object describes a first-in-first-out
|
|
152
|
-
* (FIFO) pipe.
|
|
153
|
-
* @since v10.10.0
|
|
154
|
-
*/
|
|
155
|
-
isFIFO(): boolean {
|
|
156
|
-
return this._isFIFO;
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Returns `true` if the `fs.Dirent` object describes a socket.
|
|
160
|
-
* @since v10.10.0
|
|
161
|
-
*/
|
|
162
|
-
isSocket(): boolean {
|
|
163
|
-
return this._isSocket;
|
|
164
|
-
}
|
|
165
|
-
}
|
package/src/encoding.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
// Adapted from Deno (refs/deno/ext/node/polyfills/_fs/_fs_mkdtemp.ts)
|
|
3
|
-
// Copyright (c) 2018-2026 the Deno authors. MIT license.
|
|
4
|
-
// Modifications: Extracted encoding helpers, adapted for GJS
|
|
5
|
-
|
|
6
|
-
import { Buffer } from 'node:buffer';
|
|
7
|
-
|
|
8
|
-
import type { ReadOptions } from './types/index.js';
|
|
9
|
-
import type { ObjectEncodingOptions, BufferEncodingOption } from 'node:fs'; // Types from @types/node
|
|
10
|
-
|
|
11
|
-
export function getEncodingFromOptions(options: ReadOptions | ObjectEncodingOptions | BufferEncodingOption= { encoding: null, flag: 'r' }, defaultEncoding: null | BufferEncoding | "buffer" = 'utf8'): BufferEncoding | 'buffer' {
|
|
12
|
-
if (options === null) {
|
|
13
|
-
return defaultEncoding;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (typeof options === 'string') {
|
|
17
|
-
return options as BufferEncoding | 'buffer';
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
if (typeof options === 'object' && typeof options.encoding === 'string') {
|
|
21
|
-
return options.encoding;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return defaultEncoding;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function encodeUint8Array(encoding: BufferEncoding | 'buffer', data: Uint8Array) {
|
|
28
|
-
if (encoding === 'buffer') {
|
|
29
|
-
return Buffer.from(data);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const decoder = new TextDecoder(encoding);
|
|
33
|
-
return decoder.decode(data);
|
|
34
|
-
// return byteArray.toString(data);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Credits https://github.com/denoland/deno_std/blob/63be40277264e71af60f9b118a2cb569e02beeab/node/_fs/_fs_mkdtemp.ts#L82
|
|
38
|
-
export function decode(str: string, encoding?: string): string {
|
|
39
|
-
if (!encoding) return str;
|
|
40
|
-
else {
|
|
41
|
-
const decoder = new TextDecoder(encoding);
|
|
42
|
-
const encoder = new TextEncoder();
|
|
43
|
-
return decoder.decode(encoder.encode(str));
|
|
44
|
-
}
|
|
45
|
-
}
|