@gjsify/fs 0.0.4 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +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/lib/esm/stats.js
CHANGED
|
@@ -1,6 +1,41 @@
|
|
|
1
1
|
import Gio from "@girs/gio-2.0";
|
|
2
2
|
import { Dirent } from "./dirent.js";
|
|
3
|
-
import { basename } from "path";
|
|
3
|
+
import { basename } from "node:path";
|
|
4
|
+
const STAT_ATTRIBUTES = "standard::*,time::*,unix::*";
|
|
5
|
+
function populateFromInfo(info) {
|
|
6
|
+
const atimeSec = info.get_attribute_uint64("time::access");
|
|
7
|
+
const atimeUsec = info.get_attribute_uint32("time::access-usec") || 0;
|
|
8
|
+
const mtimeSec = info.get_attribute_uint64("time::modified");
|
|
9
|
+
const mtimeUsec = info.get_attribute_uint32("time::modified-usec") || 0;
|
|
10
|
+
const ctimeSec = info.get_attribute_uint64("time::changed");
|
|
11
|
+
const ctimeUsec = info.get_attribute_uint32("time::changed-usec") || 0;
|
|
12
|
+
const createdSec = info.get_attribute_uint64("time::created");
|
|
13
|
+
const createdUsec = info.get_attribute_uint32("time::created-usec") || 0;
|
|
14
|
+
const atimeMs = atimeSec * 1e3 + atimeUsec / 1e3;
|
|
15
|
+
const mtimeMs = mtimeSec * 1e3 + mtimeUsec / 1e3;
|
|
16
|
+
const ctimeMs = ctimeSec ? ctimeSec * 1e3 + ctimeUsec / 1e3 : mtimeMs;
|
|
17
|
+
const birthtimeMs = createdSec ? createdSec * 1e3 + createdUsec / 1e3 : ctimeMs;
|
|
18
|
+
return {
|
|
19
|
+
dev: info.get_attribute_uint32("unix::device") || 0,
|
|
20
|
+
ino: Number(info.get_attribute_uint64("unix::inode") || 0),
|
|
21
|
+
mode: info.get_attribute_uint32("unix::mode") || 0,
|
|
22
|
+
nlink: info.get_attribute_uint32("unix::nlink") || 0,
|
|
23
|
+
uid: info.get_attribute_uint32("unix::uid") || 0,
|
|
24
|
+
gid: info.get_attribute_uint32("unix::gid") || 0,
|
|
25
|
+
rdev: info.get_attribute_uint32("unix::rdev") || 0,
|
|
26
|
+
size: Number(info.get_size() || 0),
|
|
27
|
+
blksize: info.get_attribute_uint32("unix::block-size") || 4096,
|
|
28
|
+
blocks: Number(info.get_attribute_uint64("unix::blocks") || 0),
|
|
29
|
+
atimeMs,
|
|
30
|
+
mtimeMs,
|
|
31
|
+
ctimeMs,
|
|
32
|
+
birthtimeMs,
|
|
33
|
+
atime: new Date(atimeMs),
|
|
34
|
+
mtime: new Date(mtimeMs),
|
|
35
|
+
ctime: new Date(ctimeMs),
|
|
36
|
+
birthtime: new Date(birthtimeMs)
|
|
37
|
+
};
|
|
38
|
+
}
|
|
4
39
|
class Stats extends Dirent {
|
|
5
40
|
dev;
|
|
6
41
|
ino;
|
|
@@ -15,31 +50,116 @@ class Stats extends Dirent {
|
|
|
15
50
|
atimeMs;
|
|
16
51
|
mtimeMs;
|
|
17
52
|
ctimeMs;
|
|
18
|
-
|
|
19
|
-
get birthtimeMs() {
|
|
20
|
-
const creationDateTime = this._info.get_creation_date_time();
|
|
21
|
-
return creationDateTime.get_microsecond() * 1e3;
|
|
22
|
-
}
|
|
53
|
+
birthtimeMs;
|
|
23
54
|
atime;
|
|
24
55
|
mtime;
|
|
25
56
|
ctime;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
57
|
+
birthtime;
|
|
58
|
+
_info;
|
|
59
|
+
constructor(infoOrPath, pathOrFilename, filename) {
|
|
60
|
+
let info;
|
|
61
|
+
let pathStr;
|
|
62
|
+
if (infoOrPath instanceof Gio.FileInfo) {
|
|
63
|
+
info = infoOrPath;
|
|
64
|
+
pathStr = pathOrFilename.toString();
|
|
65
|
+
if (!filename) filename = basename(pathStr);
|
|
66
|
+
} else {
|
|
67
|
+
pathStr = infoOrPath.toString();
|
|
68
|
+
if (typeof pathOrFilename === "string") filename = pathOrFilename;
|
|
69
|
+
if (!filename) filename = basename(pathStr);
|
|
70
|
+
const file = Gio.File.new_for_path(pathStr);
|
|
71
|
+
info = file.query_info(STAT_ATTRIBUTES, Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null);
|
|
72
|
+
}
|
|
73
|
+
super(pathStr, filename, info.get_file_type());
|
|
74
|
+
this._info = info;
|
|
75
|
+
const data = populateFromInfo(info);
|
|
76
|
+
this.dev = data.dev;
|
|
77
|
+
this.ino = data.ino;
|
|
78
|
+
this.mode = data.mode;
|
|
79
|
+
this.nlink = data.nlink;
|
|
80
|
+
this.uid = data.uid;
|
|
81
|
+
this.gid = data.gid;
|
|
82
|
+
this.rdev = data.rdev;
|
|
83
|
+
this.size = data.size;
|
|
84
|
+
this.blksize = data.blksize;
|
|
85
|
+
this.blocks = data.blocks;
|
|
86
|
+
this.atimeMs = data.atimeMs;
|
|
87
|
+
this.mtimeMs = data.mtimeMs;
|
|
88
|
+
this.ctimeMs = data.ctimeMs;
|
|
89
|
+
this.birthtimeMs = data.birthtimeMs;
|
|
90
|
+
this.atime = data.atime;
|
|
91
|
+
this.mtime = data.mtime;
|
|
92
|
+
this.ctime = data.ctime;
|
|
93
|
+
this.birthtime = data.birthtime;
|
|
30
94
|
}
|
|
95
|
+
}
|
|
96
|
+
class BigIntStats extends Dirent {
|
|
97
|
+
dev;
|
|
98
|
+
ino;
|
|
99
|
+
mode;
|
|
100
|
+
nlink;
|
|
101
|
+
uid;
|
|
102
|
+
gid;
|
|
103
|
+
rdev;
|
|
104
|
+
size;
|
|
105
|
+
blksize;
|
|
106
|
+
blocks;
|
|
107
|
+
atimeMs;
|
|
108
|
+
mtimeMs;
|
|
109
|
+
ctimeMs;
|
|
110
|
+
birthtimeMs;
|
|
111
|
+
atimeNs;
|
|
112
|
+
mtimeNs;
|
|
113
|
+
ctimeNs;
|
|
114
|
+
birthtimeNs;
|
|
115
|
+
atime;
|
|
116
|
+
mtime;
|
|
117
|
+
ctime;
|
|
118
|
+
birthtime;
|
|
31
119
|
_info;
|
|
32
|
-
constructor(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
120
|
+
constructor(infoOrPath, pathOrFilename, filename) {
|
|
121
|
+
let info;
|
|
122
|
+
let pathStr;
|
|
123
|
+
if (infoOrPath instanceof Gio.FileInfo) {
|
|
124
|
+
info = infoOrPath;
|
|
125
|
+
pathStr = pathOrFilename.toString();
|
|
126
|
+
if (!filename) filename = basename(pathStr);
|
|
127
|
+
} else {
|
|
128
|
+
pathStr = infoOrPath.toString();
|
|
129
|
+
if (typeof pathOrFilename === "string") filename = pathOrFilename;
|
|
130
|
+
if (!filename) filename = basename(pathStr);
|
|
131
|
+
const file = Gio.File.new_for_path(pathStr);
|
|
132
|
+
info = file.query_info(STAT_ATTRIBUTES, Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null);
|
|
39
133
|
}
|
|
40
|
-
|
|
134
|
+
super(pathStr, filename, info.get_file_type());
|
|
135
|
+
this._info = info;
|
|
136
|
+
const data = populateFromInfo(info);
|
|
137
|
+
this.dev = BigInt(data.dev);
|
|
138
|
+
this.ino = BigInt(data.ino);
|
|
139
|
+
this.mode = BigInt(data.mode);
|
|
140
|
+
this.nlink = BigInt(data.nlink);
|
|
141
|
+
this.uid = BigInt(data.uid);
|
|
142
|
+
this.gid = BigInt(data.gid);
|
|
143
|
+
this.rdev = BigInt(data.rdev);
|
|
144
|
+
this.size = BigInt(data.size);
|
|
145
|
+
this.blksize = BigInt(data.blksize);
|
|
146
|
+
this.blocks = BigInt(data.blocks);
|
|
147
|
+
this.atimeMs = BigInt(Math.trunc(data.atimeMs));
|
|
148
|
+
this.mtimeMs = BigInt(Math.trunc(data.mtimeMs));
|
|
149
|
+
this.ctimeMs = BigInt(Math.trunc(data.ctimeMs));
|
|
150
|
+
this.birthtimeMs = BigInt(Math.trunc(data.birthtimeMs));
|
|
151
|
+
this.atimeNs = this.atimeMs * 1000000n;
|
|
152
|
+
this.mtimeNs = this.mtimeMs * 1000000n;
|
|
153
|
+
this.ctimeNs = this.ctimeMs * 1000000n;
|
|
154
|
+
this.birthtimeNs = this.birthtimeMs * 1000000n;
|
|
155
|
+
this.atime = data.atime;
|
|
156
|
+
this.mtime = data.mtime;
|
|
157
|
+
this.ctime = data.ctime;
|
|
158
|
+
this.birthtime = data.birthtime;
|
|
41
159
|
}
|
|
42
160
|
}
|
|
43
161
|
export {
|
|
162
|
+
BigIntStats,
|
|
163
|
+
STAT_ATTRIBUTES,
|
|
44
164
|
Stats
|
|
45
165
|
};
|
package/lib/esm/sync.js
CHANGED
|
@@ -1,33 +1,112 @@
|
|
|
1
1
|
import GLib from "@girs/glib-2.0";
|
|
2
2
|
import Gio from "@girs/gio-2.0";
|
|
3
3
|
import { existsSync } from "@gjsify/utils";
|
|
4
|
-
import {
|
|
4
|
+
import { Buffer } from "node:buffer";
|
|
5
|
+
import { join } from "node:path";
|
|
5
6
|
import FSWatcher from "./fs-watcher.js";
|
|
6
7
|
import { getEncodingFromOptions, encodeUint8Array, decode } from "./encoding.js";
|
|
7
8
|
import { FileHandle } from "./file-handle.js";
|
|
8
9
|
import { Dirent } from "./dirent.js";
|
|
10
|
+
import { Stats, BigIntStats, STAT_ATTRIBUTES } from "./stats.js";
|
|
11
|
+
import { createNodeError, isNotFoundError } from "./errors.js";
|
|
9
12
|
import { tempDirPath } from "./utils.js";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
function statSync(path, options) {
|
|
14
|
+
try {
|
|
15
|
+
const file = Gio.File.new_for_path(path.toString());
|
|
16
|
+
const info = file.query_info(STAT_ATTRIBUTES, Gio.FileQueryInfoFlags.NONE, null);
|
|
17
|
+
return options?.bigint ? new BigIntStats(info, path) : new Stats(info, path);
|
|
18
|
+
} catch (err) {
|
|
19
|
+
if (options?.throwIfNoEntry === false && isNotFoundError(err)) return void 0;
|
|
20
|
+
throw createNodeError(err, "stat", path);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function lstatSync(path, options) {
|
|
24
|
+
try {
|
|
25
|
+
const file = Gio.File.new_for_path(path.toString());
|
|
26
|
+
const info = file.query_info(STAT_ATTRIBUTES, Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null);
|
|
27
|
+
return options?.bigint ? new BigIntStats(info, path) : new Stats(info, path);
|
|
28
|
+
} catch (err) {
|
|
29
|
+
if (options?.throwIfNoEntry === false && isNotFoundError(err)) return void 0;
|
|
30
|
+
throw createNodeError(err, "lstat", path);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function readdirSync(path, options) {
|
|
34
|
+
const pathStr = path.toString();
|
|
35
|
+
const file = Gio.File.new_for_path(pathStr);
|
|
36
|
+
const enumerator = file.enumerate_children(
|
|
37
|
+
"standard::name,standard::type",
|
|
38
|
+
Gio.FileQueryInfoFlags.NONE,
|
|
39
|
+
null
|
|
40
|
+
);
|
|
41
|
+
const result = [];
|
|
42
|
+
let info = enumerator.next_file(null);
|
|
43
|
+
while (info !== null) {
|
|
44
|
+
const childName = info.get_name();
|
|
45
|
+
const childPath = join(pathStr, childName);
|
|
46
|
+
if (options?.withFileTypes) {
|
|
47
|
+
result.push(new Dirent(childPath, childName));
|
|
48
|
+
} else {
|
|
49
|
+
result.push(childName);
|
|
50
|
+
}
|
|
51
|
+
if (options?.recursive && info.get_file_type() === Gio.FileType.DIRECTORY) {
|
|
52
|
+
const subEntries = readdirSync(childPath, options);
|
|
53
|
+
for (const entry of subEntries) {
|
|
54
|
+
if (typeof entry === "string") {
|
|
55
|
+
result.push(join(childName, entry));
|
|
56
|
+
} else {
|
|
57
|
+
result.push(entry);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
info = enumerator.next_file(null);
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
65
|
+
const MAX_SYMLINK_DEPTH = 40;
|
|
66
|
+
function realpathSync(path) {
|
|
67
|
+
let current = Gio.File.new_for_path(path.toString());
|
|
68
|
+
let depth = 0;
|
|
69
|
+
while (true) {
|
|
70
|
+
const info = current.query_info(
|
|
71
|
+
"standard::is-symlink,standard::symlink-target",
|
|
72
|
+
Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
|
|
73
|
+
null
|
|
74
|
+
);
|
|
75
|
+
if (!info.get_is_symlink()) {
|
|
76
|
+
return current.get_path();
|
|
77
|
+
}
|
|
78
|
+
const target = info.get_symlink_target();
|
|
79
|
+
const parent = current.get_parent();
|
|
80
|
+
current = parent ? parent.resolve_relative_path(target) : Gio.File.new_for_path(target);
|
|
81
|
+
if (++depth > MAX_SYMLINK_DEPTH) {
|
|
82
|
+
throw new Error(`ELOOP: too many levels of symbolic links, realpath '${path}'`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
realpathSync.native = realpathSync;
|
|
87
|
+
function symlinkSync(target, path, _type) {
|
|
88
|
+
const file = Gio.File.new_for_path(path.toString());
|
|
89
|
+
file.make_symbolic_link(target.toString(), null);
|
|
90
|
+
}
|
|
15
91
|
function readFileSync(path, options = { encoding: null, flag: "r" }) {
|
|
16
92
|
const file = Gio.File.new_for_path(path);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
93
|
+
try {
|
|
94
|
+
const [ok, data] = file.load_contents(null);
|
|
95
|
+
if (!ok) {
|
|
96
|
+
throw createNodeError(new Error("failed to read file"), "read", path);
|
|
97
|
+
}
|
|
98
|
+
return encodeUint8Array(getEncodingFromOptions(options, "buffer"), data);
|
|
99
|
+
} catch (err) {
|
|
100
|
+
if (err.code && typeof err.code === "string") throw err;
|
|
101
|
+
throw createNodeError(err, "read", path);
|
|
20
102
|
}
|
|
21
|
-
return encodeUint8Array(getEncodingFromOptions(options, "buffer"), data);
|
|
22
103
|
}
|
|
23
104
|
function mkdirSync(path, options) {
|
|
24
105
|
let recursive = false;
|
|
25
106
|
let mode = 511;
|
|
26
107
|
if (typeof options === "object") {
|
|
27
|
-
if (options?.recursive)
|
|
28
|
-
|
|
29
|
-
if (options?.mode)
|
|
30
|
-
mode = options.mode;
|
|
108
|
+
if (options?.recursive) recursive = options.recursive;
|
|
109
|
+
if (options?.mode) mode = options.mode;
|
|
31
110
|
} else {
|
|
32
111
|
mode = options || 511;
|
|
33
112
|
}
|
|
@@ -37,38 +116,191 @@ function mkdirSync(path, options) {
|
|
|
37
116
|
if (typeof mode === "string") {
|
|
38
117
|
throw new TypeError("mode as string is currently not supported!");
|
|
39
118
|
}
|
|
40
|
-
if (GLib.mkdir_with_parents(path, mode) !== 0) {
|
|
41
|
-
throw new Error(`failed to make ${path} directory`);
|
|
42
|
-
}
|
|
43
119
|
if (recursive) {
|
|
44
|
-
return path
|
|
120
|
+
return mkdirSyncRecursive(path, mode);
|
|
121
|
+
}
|
|
122
|
+
const file = Gio.File.new_for_path(path);
|
|
123
|
+
try {
|
|
124
|
+
file.make_directory(null);
|
|
125
|
+
} catch (err) {
|
|
126
|
+
throw createNodeError(err, "mkdir", path);
|
|
45
127
|
}
|
|
46
128
|
return void 0;
|
|
47
129
|
}
|
|
48
|
-
function
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (
|
|
56
|
-
|
|
57
|
-
} else if (childFile.isFile()) {
|
|
58
|
-
rmSync(join(path.toString(), childFile.name));
|
|
130
|
+
function mkdirSyncRecursive(pathStr, mode) {
|
|
131
|
+
const file = Gio.File.new_for_path(pathStr);
|
|
132
|
+
try {
|
|
133
|
+
file.make_directory(null);
|
|
134
|
+
return pathStr;
|
|
135
|
+
} catch (err) {
|
|
136
|
+
const gErr = err;
|
|
137
|
+
if (gErr.code === Gio.IOErrorEnum.EXISTS) {
|
|
138
|
+
return void 0;
|
|
59
139
|
}
|
|
140
|
+
if (gErr.code === Gio.IOErrorEnum.NOT_FOUND) {
|
|
141
|
+
const parentPath = join(pathStr, "..");
|
|
142
|
+
const resolvedParent = Gio.File.new_for_path(parentPath).get_path();
|
|
143
|
+
if (resolvedParent === pathStr) {
|
|
144
|
+
throw createNodeError(err, "mkdir", pathStr);
|
|
145
|
+
}
|
|
146
|
+
const firstCreated = mkdirSyncRecursive(resolvedParent, mode);
|
|
147
|
+
const retryFile = Gio.File.new_for_path(pathStr);
|
|
148
|
+
try {
|
|
149
|
+
retryFile.make_directory(null);
|
|
150
|
+
} catch (retryErr) {
|
|
151
|
+
throw createNodeError(retryErr, "mkdir", pathStr);
|
|
152
|
+
}
|
|
153
|
+
return firstCreated ?? pathStr;
|
|
154
|
+
}
|
|
155
|
+
throw createNodeError(err, "mkdir", pathStr);
|
|
60
156
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
157
|
+
}
|
|
158
|
+
function rmdirSync(path, _options) {
|
|
159
|
+
const file = Gio.File.new_for_path(path.toString());
|
|
160
|
+
try {
|
|
161
|
+
const info = file.query_info("standard::type", Gio.FileQueryInfoFlags.NONE, null);
|
|
162
|
+
if (info.get_file_type() !== Gio.FileType.DIRECTORY) {
|
|
163
|
+
const err = Object.assign(new Error(), { code: 4 });
|
|
164
|
+
throw createNodeError(err, "rmdir", path);
|
|
165
|
+
}
|
|
166
|
+
const enumerator = file.enumerate_children("standard::name", Gio.FileQueryInfoFlags.NONE, null);
|
|
167
|
+
if (enumerator.next_file(null) !== null) {
|
|
168
|
+
const err = Object.assign(new Error(), { code: 5 });
|
|
169
|
+
throw createNodeError(err, "rmdir", path);
|
|
170
|
+
}
|
|
171
|
+
file.delete(null);
|
|
172
|
+
} catch (err) {
|
|
173
|
+
if (err.code && typeof err.code === "string") throw err;
|
|
174
|
+
throw createNodeError(err, "rmdir", path);
|
|
64
175
|
}
|
|
65
176
|
}
|
|
66
177
|
function unlinkSync(path) {
|
|
67
|
-
|
|
178
|
+
const file = Gio.File.new_for_path(path.toString());
|
|
179
|
+
try {
|
|
180
|
+
file.delete(null);
|
|
181
|
+
} catch (err) {
|
|
182
|
+
throw createNodeError(err, "unlink", path);
|
|
183
|
+
}
|
|
68
184
|
}
|
|
69
185
|
function writeFileSync(path, data) {
|
|
70
186
|
GLib.file_set_contents(path, data);
|
|
71
187
|
}
|
|
188
|
+
function renameSync(oldPath, newPath) {
|
|
189
|
+
const src = Gio.File.new_for_path(oldPath.toString());
|
|
190
|
+
const dest = Gio.File.new_for_path(newPath.toString());
|
|
191
|
+
try {
|
|
192
|
+
src.move(dest, Gio.FileCopyFlags.OVERWRITE, null, null);
|
|
193
|
+
} catch (err) {
|
|
194
|
+
throw createNodeError(err, "rename", oldPath, newPath);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function copyFileSync(src, dest, mode) {
|
|
198
|
+
const srcFile = Gio.File.new_for_path(src.toString());
|
|
199
|
+
const destFile = Gio.File.new_for_path(dest.toString());
|
|
200
|
+
let flags = Gio.FileCopyFlags.NONE;
|
|
201
|
+
if (mode && (mode & 1) === 0) {
|
|
202
|
+
flags = Gio.FileCopyFlags.OVERWRITE;
|
|
203
|
+
} else if (!mode) {
|
|
204
|
+
flags = Gio.FileCopyFlags.OVERWRITE;
|
|
205
|
+
}
|
|
206
|
+
try {
|
|
207
|
+
srcFile.copy(destFile, flags, null, null);
|
|
208
|
+
} catch (err) {
|
|
209
|
+
throw createNodeError(err, "copyfile", src, dest);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
function accessSync(path, mode) {
|
|
213
|
+
const file = Gio.File.new_for_path(path.toString());
|
|
214
|
+
try {
|
|
215
|
+
const info = file.query_info("access::*", Gio.FileQueryInfoFlags.NONE, null);
|
|
216
|
+
if (mode !== void 0 && mode !== 0) {
|
|
217
|
+
const permErr = { code: 14, message: `permission denied, access '${path}'` };
|
|
218
|
+
if (mode & 4 && !info.get_attribute_boolean("access::can-read")) {
|
|
219
|
+
throw createNodeError(permErr, "access", path);
|
|
220
|
+
}
|
|
221
|
+
if (mode & 2 && !info.get_attribute_boolean("access::can-write")) {
|
|
222
|
+
throw createNodeError(permErr, "access", path);
|
|
223
|
+
}
|
|
224
|
+
if (mode & 1 && !info.get_attribute_boolean("access::can-execute")) {
|
|
225
|
+
throw createNodeError(permErr, "access", path);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
} catch (err) {
|
|
229
|
+
if (err.code && typeof err.code === "string") throw err;
|
|
230
|
+
throw createNodeError(err, "access", path);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
function appendFileSync(path, data, options) {
|
|
234
|
+
const file = Gio.File.new_for_path(path.toString());
|
|
235
|
+
let bytes;
|
|
236
|
+
if (typeof data === "string") {
|
|
237
|
+
bytes = new TextEncoder().encode(data);
|
|
238
|
+
} else {
|
|
239
|
+
bytes = data;
|
|
240
|
+
}
|
|
241
|
+
try {
|
|
242
|
+
const stream = file.append_to(Gio.FileCreateFlags.NONE, null);
|
|
243
|
+
if (bytes.length > 0) {
|
|
244
|
+
stream.write_bytes(new GLib.Bytes(bytes), null);
|
|
245
|
+
}
|
|
246
|
+
stream.close(null);
|
|
247
|
+
} catch (err) {
|
|
248
|
+
throw createNodeError(err, "appendfile", path);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
function readlinkSync(path, options) {
|
|
252
|
+
const file = Gio.File.new_for_path(path.toString());
|
|
253
|
+
try {
|
|
254
|
+
const info = file.query_info("standard::symlink-target", Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, null);
|
|
255
|
+
const target = info.get_symlink_target();
|
|
256
|
+
if (!target) {
|
|
257
|
+
throw Object.assign(new Error(`EINVAL: invalid argument, readlink '${path}'`), { code: "EINVAL", errno: -22, syscall: "readlink", path: path.toString() });
|
|
258
|
+
}
|
|
259
|
+
const encoding = typeof options === "string" ? options : options?.encoding;
|
|
260
|
+
if (encoding === "buffer") {
|
|
261
|
+
return Buffer.from(target);
|
|
262
|
+
}
|
|
263
|
+
return target;
|
|
264
|
+
} catch (err) {
|
|
265
|
+
if (typeof err.code === "string") throw err;
|
|
266
|
+
throw createNodeError(err, "readlink", path);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
function linkSync(existingPath, newPath) {
|
|
270
|
+
const result = GLib.spawn_command_line_sync(`ln ${existingPath.toString()} ${newPath.toString()}`);
|
|
271
|
+
if (!result[0]) {
|
|
272
|
+
throw Object.assign(new Error(`EPERM: operation not permitted, link '${existingPath}' -> '${newPath}'`), { code: "EPERM", errno: -1, syscall: "link", path: existingPath.toString(), dest: newPath.toString() });
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
function truncateSync(path, len) {
|
|
276
|
+
const file = Gio.File.new_for_path(path.toString());
|
|
277
|
+
try {
|
|
278
|
+
const stream = file.replace(null, false, Gio.FileCreateFlags.NONE, null);
|
|
279
|
+
if (len && len > 0) {
|
|
280
|
+
const [, data] = file.load_contents(null);
|
|
281
|
+
const truncated = data.slice(0, len);
|
|
282
|
+
if (truncated.length > 0) {
|
|
283
|
+
stream.write_bytes(new GLib.Bytes(truncated), null);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
stream.close(null);
|
|
287
|
+
} catch (err) {
|
|
288
|
+
throw createNodeError(err, "truncate", path);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
function chmodSync(path, mode) {
|
|
292
|
+
const modeNum = typeof mode === "string" ? parseInt(mode, 8) : mode;
|
|
293
|
+
const result = GLib.spawn_command_line_sync(`chmod ${modeNum.toString(8)} ${path.toString()}`);
|
|
294
|
+
if (!result[0]) {
|
|
295
|
+
throw Object.assign(new Error(`EPERM: operation not permitted, chmod '${path}'`), { code: "EPERM", errno: -1, syscall: "chmod", path: path.toString() });
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
function chownSync(path, uid, gid) {
|
|
299
|
+
const result = GLib.spawn_command_line_sync(`chown ${uid}:${gid} ${path.toString()}`);
|
|
300
|
+
if (!result[0]) {
|
|
301
|
+
throw Object.assign(new Error(`EPERM: operation not permitted, chown '${path}'`), { code: "EPERM", errno: -1, syscall: "chown", path: path.toString() });
|
|
302
|
+
}
|
|
303
|
+
}
|
|
72
304
|
function watch(filename, options, listener) {
|
|
73
305
|
return new FSWatcher(filename, options, listener);
|
|
74
306
|
}
|
|
@@ -85,41 +317,58 @@ function mkdtempSync(prefix, options) {
|
|
|
85
317
|
return decode(path, encoding);
|
|
86
318
|
}
|
|
87
319
|
function rmSync(path, options) {
|
|
88
|
-
const
|
|
320
|
+
const pathStr = path.toString();
|
|
321
|
+
const file = Gio.File.new_for_path(pathStr);
|
|
89
322
|
const recursive = options?.recursive || false;
|
|
90
|
-
const
|
|
323
|
+
const force = options?.force || false;
|
|
324
|
+
let dirent;
|
|
325
|
+
try {
|
|
326
|
+
dirent = new Dirent(pathStr);
|
|
327
|
+
} catch (err) {
|
|
328
|
+
if (force && isNotFoundError(err)) return;
|
|
329
|
+
throw createNodeError(err, "rm", path);
|
|
330
|
+
}
|
|
91
331
|
if (dirent.isDirectory()) {
|
|
92
332
|
const childFiles = readdirSync(path, { withFileTypes: true });
|
|
93
333
|
if (!recursive && childFiles.length) {
|
|
94
|
-
|
|
334
|
+
const err = Object.assign(new Error(), { code: 5 });
|
|
335
|
+
throw createNodeError(err, "rm", path);
|
|
95
336
|
}
|
|
96
337
|
for (const childFile of childFiles) {
|
|
97
|
-
if (childFile
|
|
98
|
-
|
|
99
|
-
} else if (childFile.isFile()) {
|
|
100
|
-
rmSync(join(path.toString(), childFile.name), options);
|
|
338
|
+
if (typeof childFile !== "string") {
|
|
339
|
+
rmSync(join(pathStr, childFile.name), options);
|
|
101
340
|
}
|
|
102
341
|
}
|
|
103
342
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
343
|
+
try {
|
|
344
|
+
file.delete(null);
|
|
345
|
+
} catch (err) {
|
|
346
|
+
if (force && isNotFoundError(err)) return;
|
|
347
|
+
throw createNodeError(err, "rm", path);
|
|
108
348
|
}
|
|
109
349
|
}
|
|
110
350
|
export {
|
|
351
|
+
accessSync,
|
|
352
|
+
appendFileSync,
|
|
353
|
+
chmodSync,
|
|
354
|
+
chownSync,
|
|
355
|
+
copyFileSync,
|
|
111
356
|
existsSync,
|
|
357
|
+
linkSync,
|
|
112
358
|
lstatSync,
|
|
113
359
|
mkdirSync,
|
|
114
360
|
mkdtempSync,
|
|
115
361
|
openSync,
|
|
116
362
|
readFileSync,
|
|
117
363
|
readdirSync,
|
|
364
|
+
readlinkSync,
|
|
118
365
|
realpathSync,
|
|
366
|
+
renameSync,
|
|
119
367
|
rmSync,
|
|
120
368
|
rmdirSync,
|
|
121
369
|
statSync,
|
|
122
370
|
symlinkSync,
|
|
371
|
+
truncateSync,
|
|
123
372
|
unlinkSync,
|
|
124
373
|
watch,
|
|
125
374
|
writeFileSync
|
package/lib/esm/write-stream.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Writable } from "stream";
|
|
2
|
-
import { fileURLToPath, URL } from "url";
|
|
1
|
+
import { Writable } from "node:stream";
|
|
2
|
+
import { fileURLToPath, URL } from "node:url";
|
|
3
3
|
import { open, write, close } from "./callback.js";
|
|
4
|
-
const kIsPerformingIO = Symbol("kIsPerformingIO");
|
|
5
|
-
const kIoDone = Symbol("kIoDone");
|
|
4
|
+
const kIsPerformingIO = /* @__PURE__ */ Symbol("kIsPerformingIO");
|
|
5
|
+
const kIoDone = /* @__PURE__ */ Symbol("kIoDone");
|
|
6
6
|
function toPathIfFileURL(fileURLOrPath) {
|
|
7
7
|
if (!(fileURLOrPath instanceof URL)) {
|
|
8
8
|
return fileURLOrPath;
|