@componentor/fs 3.0.40 → 3.0.42
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/dist/index.d.mts +30 -16
- package/dist/index.js +391 -78
- package/dist/index.js.map +1 -1
- package/dist/workers/async-relay.worker.js +4 -1
- package/dist/workers/async-relay.worker.js.map +1 -1
- package/dist/workers/repair.worker.js +34 -0
- package/dist/workers/repair.worker.js.map +1 -1
- package/dist/workers/server.worker.js +73 -1
- package/dist/workers/server.worker.js.map +1 -1
- package/dist/workers/sync-relay.worker.js +127 -3
- package/dist/workers/sync-relay.worker.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -354,7 +354,10 @@ var OP = {
|
|
|
354
354
|
FTRUNCATE: 27,
|
|
355
355
|
FSYNC: 28,
|
|
356
356
|
OPENDIR: 29,
|
|
357
|
-
MKDTEMP: 30
|
|
357
|
+
MKDTEMP: 30,
|
|
358
|
+
FCHMOD: 31,
|
|
359
|
+
FCHOWN: 32,
|
|
360
|
+
FUTIMES: 33
|
|
358
361
|
};
|
|
359
362
|
var SAB_OFFSETS = {
|
|
360
363
|
// Int32 - bytes in this chunk
|
|
@@ -1004,9 +1007,31 @@ function createFileHandle(fd, asyncRequest) {
|
|
|
1004
1007
|
const { status } = await asyncRequest(OP.FWRITE, "", 0, null, void 0, { fd, data: encoded, position: st.size });
|
|
1005
1008
|
if (status !== 0) throw statusToError(status, "write", String(fd));
|
|
1006
1009
|
},
|
|
1007
|
-
async chmod(
|
|
1010
|
+
async chmod(mode) {
|
|
1011
|
+
const payload = new Uint8Array(8);
|
|
1012
|
+
const dv = new DataView(payload.buffer);
|
|
1013
|
+
dv.setUint32(0, fd, true);
|
|
1014
|
+
dv.setUint32(4, mode, true);
|
|
1015
|
+
const { status } = await asyncRequest(OP.FCHMOD, "", 0, payload);
|
|
1016
|
+
if (status !== 0) throw statusToError(status, "fchmod", String(fd));
|
|
1008
1017
|
},
|
|
1009
|
-
async chown(
|
|
1018
|
+
async chown(uid, gid) {
|
|
1019
|
+
const payload = new Uint8Array(12);
|
|
1020
|
+
const dv = new DataView(payload.buffer);
|
|
1021
|
+
dv.setUint32(0, fd, true);
|
|
1022
|
+
dv.setUint32(4, uid, true);
|
|
1023
|
+
dv.setUint32(8, gid, true);
|
|
1024
|
+
const { status } = await asyncRequest(OP.FCHOWN, "", 0, payload);
|
|
1025
|
+
if (status !== 0) throw statusToError(status, "fchown", String(fd));
|
|
1026
|
+
},
|
|
1027
|
+
async utimes(atime, mtime) {
|
|
1028
|
+
const payload = new Uint8Array(24);
|
|
1029
|
+
const dv = new DataView(payload.buffer);
|
|
1030
|
+
dv.setUint32(0, fd, true);
|
|
1031
|
+
dv.setFloat64(8, typeof atime === "number" ? atime : atime.getTime(), true);
|
|
1032
|
+
dv.setFloat64(16, typeof mtime === "number" ? mtime : mtime.getTime(), true);
|
|
1033
|
+
const { status } = await asyncRequest(OP.FUTIMES, "", 0, payload);
|
|
1034
|
+
if (status !== 0) throw statusToError(status, "futimes", String(fd));
|
|
1010
1035
|
},
|
|
1011
1036
|
async sync() {
|
|
1012
1037
|
await asyncRequest(OP.FSYNC, "");
|
|
@@ -1209,6 +1234,23 @@ async function chmod(asyncRequest, filePath, mode) {
|
|
|
1209
1234
|
const { status } = await asyncRequest(OP.CHMOD, filePath, 0, modeBuf);
|
|
1210
1235
|
if (status !== 0) throw statusToError(status, "chmod", filePath);
|
|
1211
1236
|
}
|
|
1237
|
+
function fchmodSync(syncRequest, fd, mode) {
|
|
1238
|
+
const payload = new Uint8Array(8);
|
|
1239
|
+
const dv = new DataView(payload.buffer);
|
|
1240
|
+
dv.setUint32(0, fd, true);
|
|
1241
|
+
dv.setUint32(4, mode, true);
|
|
1242
|
+
const buf = encodeRequest(OP.FCHMOD, "", 0, payload);
|
|
1243
|
+
const { status } = syncRequest(buf);
|
|
1244
|
+
if (status !== 0) throw statusToError(status, "fchmod", String(fd));
|
|
1245
|
+
}
|
|
1246
|
+
async function fchmod(asyncRequest, fd, mode) {
|
|
1247
|
+
const payload = new Uint8Array(8);
|
|
1248
|
+
const dv = new DataView(payload.buffer);
|
|
1249
|
+
dv.setUint32(0, fd, true);
|
|
1250
|
+
dv.setUint32(4, mode, true);
|
|
1251
|
+
const { status } = await asyncRequest(OP.FCHMOD, "", 0, payload);
|
|
1252
|
+
if (status !== 0) throw statusToError(status, "fchmod", String(fd));
|
|
1253
|
+
}
|
|
1212
1254
|
|
|
1213
1255
|
// src/methods/writeFile.ts
|
|
1214
1256
|
var encoder3 = new TextEncoder();
|
|
@@ -1656,6 +1698,25 @@ async function chown(asyncRequest, filePath, uid, gid) {
|
|
|
1656
1698
|
const { status } = await asyncRequest(OP.CHOWN, filePath, 0, buf);
|
|
1657
1699
|
if (status !== 0) throw statusToError(status, "chown", filePath);
|
|
1658
1700
|
}
|
|
1701
|
+
function fchownSync(syncRequest, fd, uid, gid) {
|
|
1702
|
+
const payload = new Uint8Array(12);
|
|
1703
|
+
const dv = new DataView(payload.buffer);
|
|
1704
|
+
dv.setUint32(0, fd, true);
|
|
1705
|
+
dv.setUint32(4, uid, true);
|
|
1706
|
+
dv.setUint32(8, gid, true);
|
|
1707
|
+
const buf = encodeRequest(OP.FCHOWN, "", 0, payload);
|
|
1708
|
+
const { status } = syncRequest(buf);
|
|
1709
|
+
if (status !== 0) throw statusToError(status, "fchown", String(fd));
|
|
1710
|
+
}
|
|
1711
|
+
async function fchown(asyncRequest, fd, uid, gid) {
|
|
1712
|
+
const payload = new Uint8Array(12);
|
|
1713
|
+
const dv = new DataView(payload.buffer);
|
|
1714
|
+
dv.setUint32(0, fd, true);
|
|
1715
|
+
dv.setUint32(4, uid, true);
|
|
1716
|
+
dv.setUint32(8, gid, true);
|
|
1717
|
+
const { status } = await asyncRequest(OP.FCHOWN, "", 0, payload);
|
|
1718
|
+
if (status !== 0) throw statusToError(status, "fchown", String(fd));
|
|
1719
|
+
}
|
|
1659
1720
|
|
|
1660
1721
|
// src/methods/utimes.ts
|
|
1661
1722
|
function utimesSync(syncRequest, filePath, atime, mtime) {
|
|
@@ -1675,6 +1736,25 @@ async function utimes(asyncRequest, filePath, atime, mtime) {
|
|
|
1675
1736
|
const { status } = await asyncRequest(OP.UTIMES, filePath, 0, buf);
|
|
1676
1737
|
if (status !== 0) throw statusToError(status, "utimes", filePath);
|
|
1677
1738
|
}
|
|
1739
|
+
function futimesSync(syncRequest, fd, atime, mtime) {
|
|
1740
|
+
const payload = new Uint8Array(24);
|
|
1741
|
+
const dv = new DataView(payload.buffer);
|
|
1742
|
+
dv.setUint32(0, fd, true);
|
|
1743
|
+
dv.setFloat64(8, typeof atime === "number" ? atime : atime.getTime(), true);
|
|
1744
|
+
dv.setFloat64(16, typeof mtime === "number" ? mtime : mtime.getTime(), true);
|
|
1745
|
+
const buf = encodeRequest(OP.FUTIMES, "", 0, payload);
|
|
1746
|
+
const { status } = syncRequest(buf);
|
|
1747
|
+
if (status !== 0) throw statusToError(status, "futimes", String(fd));
|
|
1748
|
+
}
|
|
1749
|
+
async function futimes(asyncRequest, fd, atime, mtime) {
|
|
1750
|
+
const payload = new Uint8Array(24);
|
|
1751
|
+
const dv = new DataView(payload.buffer);
|
|
1752
|
+
dv.setUint32(0, fd, true);
|
|
1753
|
+
dv.setFloat64(8, typeof atime === "number" ? atime : atime.getTime(), true);
|
|
1754
|
+
dv.setFloat64(16, typeof mtime === "number" ? mtime : mtime.getTime(), true);
|
|
1755
|
+
const { status } = await asyncRequest(OP.FUTIMES, "", 0, payload);
|
|
1756
|
+
if (status !== 0) throw statusToError(status, "futimes", String(fd));
|
|
1757
|
+
}
|
|
1678
1758
|
|
|
1679
1759
|
// src/methods/symlink.ts
|
|
1680
1760
|
var encoder7 = new TextEncoder();
|
|
@@ -1908,12 +1988,8 @@ function onBroadcast(event) {
|
|
|
1908
1988
|
const { eventType, path: mutatedPath } = event.data;
|
|
1909
1989
|
for (const entry of watchers) {
|
|
1910
1990
|
const filename = matchWatcher(entry, mutatedPath);
|
|
1911
|
-
if (filename
|
|
1912
|
-
|
|
1913
|
-
entry.listener(eventType, filename);
|
|
1914
|
-
} catch {
|
|
1915
|
-
}
|
|
1916
|
-
}
|
|
1991
|
+
if (filename === null) continue;
|
|
1992
|
+
queueWatchEvent(entry, eventType, filename);
|
|
1917
1993
|
}
|
|
1918
1994
|
const fileSet = fileWatchers.get(mutatedPath);
|
|
1919
1995
|
if (fileSet) {
|
|
@@ -1922,6 +1998,29 @@ function onBroadcast(event) {
|
|
|
1922
1998
|
}
|
|
1923
1999
|
}
|
|
1924
2000
|
}
|
|
2001
|
+
function queueWatchEvent(entry, eventType, filename) {
|
|
2002
|
+
const key = eventType + ":" + filename;
|
|
2003
|
+
if (!entry.pendingEvents) {
|
|
2004
|
+
entry.pendingEvents = /* @__PURE__ */ new Set();
|
|
2005
|
+
queueMicrotask(() => {
|
|
2006
|
+
const pending = entry.pendingEvents;
|
|
2007
|
+
entry.pendingEvents = null;
|
|
2008
|
+
for (const k of pending) {
|
|
2009
|
+
const colon = k.indexOf(":");
|
|
2010
|
+
const et = k.slice(0, colon);
|
|
2011
|
+
const name = k.slice(colon + 1);
|
|
2012
|
+
try {
|
|
2013
|
+
entry.listener(et, entry.asBuffer ? encodeFilename(name) : name);
|
|
2014
|
+
} catch {
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
});
|
|
2018
|
+
}
|
|
2019
|
+
entry.pendingEvents.add(key);
|
|
2020
|
+
}
|
|
2021
|
+
function encodeFilename(name) {
|
|
2022
|
+
return new TextEncoder().encode(name);
|
|
2023
|
+
}
|
|
1925
2024
|
function matchWatcher(entry, mutatedPath) {
|
|
1926
2025
|
const { absPath, recursive } = entry;
|
|
1927
2026
|
if (mutatedPath === absPath) {
|
|
@@ -1936,17 +2035,20 @@ function matchWatcher(entry, mutatedPath) {
|
|
|
1936
2035
|
return relativePath.indexOf("/") === -1 ? relativePath : null;
|
|
1937
2036
|
}
|
|
1938
2037
|
function watch(ns, filePath, options, listener) {
|
|
1939
|
-
const opts = typeof options === "string" ? { } : options ?? {};
|
|
2038
|
+
const opts = typeof options === "string" ? { encoding: options } : options ?? {};
|
|
1940
2039
|
const cb = listener ?? (() => {
|
|
1941
2040
|
});
|
|
1942
2041
|
const absPath = resolve(filePath);
|
|
1943
2042
|
const signal = opts.signal;
|
|
2043
|
+
const asBuffer = opts.encoding === "buffer";
|
|
1944
2044
|
const entry = {
|
|
1945
2045
|
ns,
|
|
1946
2046
|
absPath,
|
|
1947
2047
|
recursive: opts.recursive ?? false,
|
|
1948
2048
|
listener: cb,
|
|
1949
|
-
signal
|
|
2049
|
+
signal,
|
|
2050
|
+
asBuffer,
|
|
2051
|
+
pendingEvents: null
|
|
1950
2052
|
};
|
|
1951
2053
|
ensureBc(ns);
|
|
1952
2054
|
watchers.add(entry);
|
|
@@ -2090,6 +2192,7 @@ async function* watchAsync(ns, _asyncRequest, filePath, options) {
|
|
|
2090
2192
|
const signal = options?.signal;
|
|
2091
2193
|
const queue = [];
|
|
2092
2194
|
let resolve2 = null;
|
|
2195
|
+
const asBuffer = options?.encoding === "buffer";
|
|
2093
2196
|
const entry = {
|
|
2094
2197
|
ns,
|
|
2095
2198
|
absPath,
|
|
@@ -2101,7 +2204,9 @@ async function* watchAsync(ns, _asyncRequest, filePath, options) {
|
|
|
2101
2204
|
resolve2 = null;
|
|
2102
2205
|
}
|
|
2103
2206
|
},
|
|
2104
|
-
signal
|
|
2207
|
+
signal,
|
|
2208
|
+
asBuffer,
|
|
2209
|
+
pendingEvents: null
|
|
2105
2210
|
};
|
|
2106
2211
|
ensureBc(ns);
|
|
2107
2212
|
watchers.add(entry);
|
|
@@ -2123,15 +2228,112 @@ async function* watchAsync(ns, _asyncRequest, filePath, options) {
|
|
|
2123
2228
|
}
|
|
2124
2229
|
|
|
2125
2230
|
// src/methods/glob.ts
|
|
2231
|
+
function expandBraces(pattern) {
|
|
2232
|
+
const out = [];
|
|
2233
|
+
function recurse(prefix, rest) {
|
|
2234
|
+
const open2 = findBrace(rest);
|
|
2235
|
+
if (open2 === -1) {
|
|
2236
|
+
out.push(prefix + rest);
|
|
2237
|
+
return;
|
|
2238
|
+
}
|
|
2239
|
+
const close = matchCloseBrace(rest, open2);
|
|
2240
|
+
if (close === -1) {
|
|
2241
|
+
out.push(prefix + rest);
|
|
2242
|
+
return;
|
|
2243
|
+
}
|
|
2244
|
+
const head = rest.slice(0, open2);
|
|
2245
|
+
const body = rest.slice(open2 + 1, close);
|
|
2246
|
+
const tail = rest.slice(close + 1);
|
|
2247
|
+
for (const alt of splitAlternations(body)) {
|
|
2248
|
+
recurse(prefix + head + alt, tail);
|
|
2249
|
+
}
|
|
2250
|
+
}
|
|
2251
|
+
recurse("", pattern);
|
|
2252
|
+
return out;
|
|
2253
|
+
}
|
|
2254
|
+
function findBrace(s) {
|
|
2255
|
+
for (let i = 0; i < s.length; i++) {
|
|
2256
|
+
const c = s[i];
|
|
2257
|
+
if (c === "\\") {
|
|
2258
|
+
i++;
|
|
2259
|
+
continue;
|
|
2260
|
+
}
|
|
2261
|
+
if (c === "[") {
|
|
2262
|
+
const end = s.indexOf("]", i + 1);
|
|
2263
|
+
if (end !== -1) {
|
|
2264
|
+
i = end;
|
|
2265
|
+
continue;
|
|
2266
|
+
}
|
|
2267
|
+
}
|
|
2268
|
+
if (c === "{") return i;
|
|
2269
|
+
}
|
|
2270
|
+
return -1;
|
|
2271
|
+
}
|
|
2272
|
+
function matchCloseBrace(s, open2) {
|
|
2273
|
+
let depth = 1;
|
|
2274
|
+
for (let i = open2 + 1; i < s.length; i++) {
|
|
2275
|
+
const c = s[i];
|
|
2276
|
+
if (c === "\\") {
|
|
2277
|
+
i++;
|
|
2278
|
+
continue;
|
|
2279
|
+
}
|
|
2280
|
+
if (c === "[") {
|
|
2281
|
+
const end = s.indexOf("]", i + 1);
|
|
2282
|
+
if (end !== -1) {
|
|
2283
|
+
i = end;
|
|
2284
|
+
continue;
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
if (c === "{") depth++;
|
|
2288
|
+
else if (c === "}") {
|
|
2289
|
+
depth--;
|
|
2290
|
+
if (depth === 0) return i;
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2293
|
+
return -1;
|
|
2294
|
+
}
|
|
2295
|
+
function splitAlternations(body) {
|
|
2296
|
+
const parts = [];
|
|
2297
|
+
let depth = 0;
|
|
2298
|
+
let start = 0;
|
|
2299
|
+
for (let i = 0; i < body.length; i++) {
|
|
2300
|
+
const c = body[i];
|
|
2301
|
+
if (c === "\\") {
|
|
2302
|
+
i++;
|
|
2303
|
+
continue;
|
|
2304
|
+
}
|
|
2305
|
+
if (c === "{") depth++;
|
|
2306
|
+
else if (c === "}") depth--;
|
|
2307
|
+
else if (c === "," && depth === 0) {
|
|
2308
|
+
parts.push(body.slice(start, i));
|
|
2309
|
+
start = i + 1;
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
parts.push(body.slice(start));
|
|
2313
|
+
return parts;
|
|
2314
|
+
}
|
|
2126
2315
|
function segmentToRegex(pattern) {
|
|
2127
2316
|
let re = "^";
|
|
2128
2317
|
for (let i = 0; i < pattern.length; i++) {
|
|
2129
2318
|
const ch = pattern[i];
|
|
2130
|
-
if (ch === "
|
|
2319
|
+
if (ch === "\\" && i + 1 < pattern.length) {
|
|
2320
|
+
const next = pattern[++i];
|
|
2321
|
+
re += /[.+^${}()|[\]\\*?]/.test(next) ? "\\" + next : next;
|
|
2322
|
+
} else if (ch === "*") {
|
|
2131
2323
|
re += "[^/]*";
|
|
2132
2324
|
} else if (ch === "?") {
|
|
2133
2325
|
re += "[^/]";
|
|
2134
|
-
} else if ("
|
|
2326
|
+
} else if (ch === "[") {
|
|
2327
|
+
const end = pattern.indexOf("]", i + 1);
|
|
2328
|
+
if (end === -1) {
|
|
2329
|
+
re += "\\[";
|
|
2330
|
+
} else {
|
|
2331
|
+
let body = pattern.slice(i + 1, end);
|
|
2332
|
+
if (body.startsWith("!")) body = "^" + body.slice(1);
|
|
2333
|
+
re += "[" + body + "]";
|
|
2334
|
+
i = end;
|
|
2335
|
+
}
|
|
2336
|
+
} else if (".+^${}()|\\".includes(ch)) {
|
|
2135
2337
|
re += "\\" + ch;
|
|
2136
2338
|
} else {
|
|
2137
2339
|
re += ch;
|
|
@@ -2140,25 +2342,69 @@ function segmentToRegex(pattern) {
|
|
|
2140
2342
|
re += "$";
|
|
2141
2343
|
return new RegExp(re);
|
|
2142
2344
|
}
|
|
2143
|
-
function matchSegment(name, pattern) {
|
|
2144
|
-
return segmentToRegex(pattern).test(name);
|
|
2145
|
-
}
|
|
2146
2345
|
function joinPath(base, name) {
|
|
2147
2346
|
if (base === "/") return "/" + name;
|
|
2148
2347
|
return base + "/" + name;
|
|
2149
2348
|
}
|
|
2349
|
+
function normalizeCwd(cwd) {
|
|
2350
|
+
if (!cwd) return "/";
|
|
2351
|
+
if (typeof cwd === "string") return cwd || "/";
|
|
2352
|
+
return cwd.pathname || "/";
|
|
2353
|
+
}
|
|
2354
|
+
function makeDirent(parentPath, name, isDir, isSymlink) {
|
|
2355
|
+
return {
|
|
2356
|
+
name,
|
|
2357
|
+
parentPath,
|
|
2358
|
+
isFile: () => !isDir && !isSymlink,
|
|
2359
|
+
isDirectory: () => isDir,
|
|
2360
|
+
isBlockDevice: () => false,
|
|
2361
|
+
isCharacterDevice: () => false,
|
|
2362
|
+
isSymbolicLink: () => isSymlink,
|
|
2363
|
+
isFIFO: () => false,
|
|
2364
|
+
isSocket: () => false
|
|
2365
|
+
};
|
|
2366
|
+
}
|
|
2150
2367
|
function globSync(syncRequest, pattern, options) {
|
|
2151
|
-
const
|
|
2368
|
+
const patterns = Array.isArray(pattern) ? pattern : [pattern];
|
|
2369
|
+
const cwd = normalizeCwd(options?.cwd);
|
|
2152
2370
|
const exclude = options?.exclude;
|
|
2153
|
-
const
|
|
2154
|
-
const
|
|
2155
|
-
|
|
2371
|
+
const withFileTypes = options?.withFileTypes === true;
|
|
2372
|
+
const resultsSet = /* @__PURE__ */ new Set();
|
|
2373
|
+
const resultsDirents = [];
|
|
2374
|
+
const pushResult = (fullPath) => {
|
|
2375
|
+
if (withFileTypes) {
|
|
2376
|
+
if (!resultsSet.has(fullPath)) {
|
|
2377
|
+
resultsSet.add(fullPath);
|
|
2378
|
+
let isDir = false, isSymlink = false;
|
|
2379
|
+
try {
|
|
2380
|
+
const s = statSync(syncRequest, fullPath);
|
|
2381
|
+
isDir = s.isDirectory();
|
|
2382
|
+
} catch {
|
|
2383
|
+
}
|
|
2384
|
+
const slash = fullPath.lastIndexOf("/");
|
|
2385
|
+
const parent = slash <= 0 ? "/" : fullPath.slice(0, slash);
|
|
2386
|
+
const name = fullPath.slice(slash + 1);
|
|
2387
|
+
const dirent = makeDirent(parent, name, isDir, isSymlink);
|
|
2388
|
+
if (exclude && exclude(dirent)) {
|
|
2389
|
+
resultsSet.delete(fullPath);
|
|
2390
|
+
return;
|
|
2391
|
+
}
|
|
2392
|
+
resultsDirents.push(dirent);
|
|
2393
|
+
}
|
|
2394
|
+
} else {
|
|
2395
|
+
if (exclude && exclude(fullPath)) return;
|
|
2396
|
+
resultsSet.add(fullPath);
|
|
2397
|
+
}
|
|
2398
|
+
};
|
|
2399
|
+
function walk(dir, segments, segIdx) {
|
|
2156
2400
|
if (segIdx >= segments.length) return;
|
|
2157
2401
|
const seg = segments[segIdx];
|
|
2158
2402
|
const isLast = segIdx === segments.length - 1;
|
|
2159
2403
|
if (seg === "**") {
|
|
2160
2404
|
if (segIdx + 1 < segments.length) {
|
|
2161
|
-
walk(dir, segIdx + 1);
|
|
2405
|
+
walk(dir, segments, segIdx + 1);
|
|
2406
|
+
} else {
|
|
2407
|
+
pushResult(dir);
|
|
2162
2408
|
}
|
|
2163
2409
|
let entries2;
|
|
2164
2410
|
try {
|
|
@@ -2168,20 +2414,16 @@ function globSync(syncRequest, pattern, options) {
|
|
|
2168
2414
|
}
|
|
2169
2415
|
for (const entry of entries2) {
|
|
2170
2416
|
const full = joinPath(dir, entry);
|
|
2171
|
-
if (exclude && exclude(full)) continue;
|
|
2172
2417
|
let isDir;
|
|
2173
2418
|
try {
|
|
2174
|
-
|
|
2175
|
-
isDir = s.isDirectory();
|
|
2419
|
+
isDir = statSync(syncRequest, full).isDirectory();
|
|
2176
2420
|
} catch {
|
|
2177
2421
|
continue;
|
|
2178
2422
|
}
|
|
2179
2423
|
if (isDir) {
|
|
2180
|
-
walk(full, segIdx);
|
|
2181
|
-
}
|
|
2182
|
-
if (isLast) {
|
|
2183
|
-
results.push(full);
|
|
2424
|
+
walk(full, segments, segIdx);
|
|
2184
2425
|
}
|
|
2426
|
+
if (isLast) pushResult(full);
|
|
2185
2427
|
}
|
|
2186
2428
|
return;
|
|
2187
2429
|
}
|
|
@@ -2191,41 +2433,71 @@ function globSync(syncRequest, pattern, options) {
|
|
|
2191
2433
|
} catch {
|
|
2192
2434
|
return;
|
|
2193
2435
|
}
|
|
2436
|
+
const re = segmentToRegex(seg);
|
|
2194
2437
|
for (const entry of entries) {
|
|
2195
|
-
if (!
|
|
2438
|
+
if (!re.test(entry)) continue;
|
|
2196
2439
|
const full = joinPath(dir, entry);
|
|
2197
|
-
if (exclude && exclude(full)) continue;
|
|
2198
2440
|
if (isLast) {
|
|
2199
|
-
|
|
2441
|
+
pushResult(full);
|
|
2200
2442
|
} else {
|
|
2201
2443
|
let isDir;
|
|
2202
2444
|
try {
|
|
2203
|
-
|
|
2204
|
-
isDir = s.isDirectory();
|
|
2445
|
+
isDir = statSync(syncRequest, full).isDirectory();
|
|
2205
2446
|
} catch {
|
|
2206
2447
|
continue;
|
|
2207
2448
|
}
|
|
2208
|
-
if (isDir)
|
|
2209
|
-
walk(full, segIdx + 1);
|
|
2210
|
-
}
|
|
2449
|
+
if (isDir) walk(full, segments, segIdx + 1);
|
|
2211
2450
|
}
|
|
2212
2451
|
}
|
|
2213
2452
|
}
|
|
2214
|
-
|
|
2215
|
-
|
|
2453
|
+
for (const pat of patterns) {
|
|
2454
|
+
for (const expanded of expandBraces(pat)) {
|
|
2455
|
+
const segments = expanded.split("/").filter((s) => s !== "");
|
|
2456
|
+
walk(cwd, segments, 0);
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
return withFileTypes ? resultsDirents : Array.from(resultsSet);
|
|
2216
2460
|
}
|
|
2217
2461
|
async function glob(asyncRequest, pattern, options) {
|
|
2218
|
-
const
|
|
2462
|
+
const patterns = Array.isArray(pattern) ? pattern : [pattern];
|
|
2463
|
+
const cwd = normalizeCwd(options?.cwd);
|
|
2219
2464
|
const exclude = options?.exclude;
|
|
2220
|
-
const
|
|
2221
|
-
const
|
|
2222
|
-
|
|
2465
|
+
const withFileTypes = options?.withFileTypes === true;
|
|
2466
|
+
const resultsSet = /* @__PURE__ */ new Set();
|
|
2467
|
+
const resultsDirents = [];
|
|
2468
|
+
const pushResult = async (fullPath) => {
|
|
2469
|
+
if (withFileTypes) {
|
|
2470
|
+
if (resultsSet.has(fullPath)) return;
|
|
2471
|
+
resultsSet.add(fullPath);
|
|
2472
|
+
let isDir = false, isSymlink = false;
|
|
2473
|
+
try {
|
|
2474
|
+
const s = await stat(asyncRequest, fullPath);
|
|
2475
|
+
isDir = s.isDirectory();
|
|
2476
|
+
} catch {
|
|
2477
|
+
}
|
|
2478
|
+
const slash = fullPath.lastIndexOf("/");
|
|
2479
|
+
const parent = slash <= 0 ? "/" : fullPath.slice(0, slash);
|
|
2480
|
+
const name = fullPath.slice(slash + 1);
|
|
2481
|
+
const dirent = makeDirent(parent, name, isDir, isSymlink);
|
|
2482
|
+
if (exclude && exclude(dirent)) {
|
|
2483
|
+
resultsSet.delete(fullPath);
|
|
2484
|
+
return;
|
|
2485
|
+
}
|
|
2486
|
+
resultsDirents.push(dirent);
|
|
2487
|
+
} else {
|
|
2488
|
+
if (exclude && exclude(fullPath)) return;
|
|
2489
|
+
resultsSet.add(fullPath);
|
|
2490
|
+
}
|
|
2491
|
+
};
|
|
2492
|
+
async function walk(dir, segments, segIdx) {
|
|
2223
2493
|
if (segIdx >= segments.length) return;
|
|
2224
2494
|
const seg = segments[segIdx];
|
|
2225
2495
|
const isLast = segIdx === segments.length - 1;
|
|
2226
2496
|
if (seg === "**") {
|
|
2227
2497
|
if (segIdx + 1 < segments.length) {
|
|
2228
|
-
await walk(dir, segIdx + 1);
|
|
2498
|
+
await walk(dir, segments, segIdx + 1);
|
|
2499
|
+
} else {
|
|
2500
|
+
await pushResult(dir);
|
|
2229
2501
|
}
|
|
2230
2502
|
let entries2;
|
|
2231
2503
|
try {
|
|
@@ -2235,20 +2507,14 @@ async function glob(asyncRequest, pattern, options) {
|
|
|
2235
2507
|
}
|
|
2236
2508
|
for (const entry of entries2) {
|
|
2237
2509
|
const full = joinPath(dir, entry);
|
|
2238
|
-
if (exclude && exclude(full)) continue;
|
|
2239
2510
|
let isDir;
|
|
2240
2511
|
try {
|
|
2241
|
-
|
|
2242
|
-
isDir = s.isDirectory();
|
|
2512
|
+
isDir = (await stat(asyncRequest, full)).isDirectory();
|
|
2243
2513
|
} catch {
|
|
2244
2514
|
continue;
|
|
2245
2515
|
}
|
|
2246
|
-
if (isDir)
|
|
2247
|
-
|
|
2248
|
-
}
|
|
2249
|
-
if (isLast) {
|
|
2250
|
-
results.push(full);
|
|
2251
|
-
}
|
|
2516
|
+
if (isDir) await walk(full, segments, segIdx);
|
|
2517
|
+
if (isLast) await pushResult(full);
|
|
2252
2518
|
}
|
|
2253
2519
|
return;
|
|
2254
2520
|
}
|
|
@@ -2258,28 +2524,30 @@ async function glob(asyncRequest, pattern, options) {
|
|
|
2258
2524
|
} catch {
|
|
2259
2525
|
return;
|
|
2260
2526
|
}
|
|
2527
|
+
const re = segmentToRegex(seg);
|
|
2261
2528
|
for (const entry of entries) {
|
|
2262
|
-
if (!
|
|
2529
|
+
if (!re.test(entry)) continue;
|
|
2263
2530
|
const full = joinPath(dir, entry);
|
|
2264
|
-
if (exclude && exclude(full)) continue;
|
|
2265
2531
|
if (isLast) {
|
|
2266
|
-
|
|
2532
|
+
await pushResult(full);
|
|
2267
2533
|
} else {
|
|
2268
2534
|
let isDir;
|
|
2269
2535
|
try {
|
|
2270
|
-
|
|
2271
|
-
isDir = s.isDirectory();
|
|
2536
|
+
isDir = (await stat(asyncRequest, full)).isDirectory();
|
|
2272
2537
|
} catch {
|
|
2273
2538
|
continue;
|
|
2274
2539
|
}
|
|
2275
|
-
if (isDir)
|
|
2276
|
-
await walk(full, segIdx + 1);
|
|
2277
|
-
}
|
|
2540
|
+
if (isDir) await walk(full, segments, segIdx + 1);
|
|
2278
2541
|
}
|
|
2279
2542
|
}
|
|
2280
2543
|
}
|
|
2281
|
-
|
|
2282
|
-
|
|
2544
|
+
for (const pat of patterns) {
|
|
2545
|
+
for (const expanded of expandBraces(pat)) {
|
|
2546
|
+
const segments = expanded.split("/").filter((s) => s !== "");
|
|
2547
|
+
await walk(cwd, segments, 0);
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
return withFileTypes ? resultsDirents : Array.from(resultsSet);
|
|
2283
2551
|
}
|
|
2284
2552
|
|
|
2285
2553
|
// src/filesystem.ts
|
|
@@ -3007,8 +3275,11 @@ var VFSFileSystem = class {
|
|
|
3007
3275
|
lchmodSync(filePath, mode) {
|
|
3008
3276
|
chmodSync(this._sync, filePath, mode);
|
|
3009
3277
|
}
|
|
3010
|
-
/** chmod on an open file descriptor.
|
|
3011
|
-
|
|
3278
|
+
/** chmod on an open file descriptor. Resolves the fd to its inode on the
|
|
3279
|
+
* server side and mutates the inode's mode bits directly, matching what
|
|
3280
|
+
* native Node's libuv does. */
|
|
3281
|
+
fchmodSync(fd, mode) {
|
|
3282
|
+
fchmodSync(this._sync, fd, mode);
|
|
3012
3283
|
}
|
|
3013
3284
|
chownSync(filePath, uid, gid) {
|
|
3014
3285
|
chownSync(this._sync, toPathString(filePath), uid, gid);
|
|
@@ -3017,14 +3288,16 @@ var VFSFileSystem = class {
|
|
|
3017
3288
|
lchownSync(filePath, uid, gid) {
|
|
3018
3289
|
chownSync(this._sync, filePath, uid, gid);
|
|
3019
3290
|
}
|
|
3020
|
-
/** chown on an open file descriptor.
|
|
3021
|
-
fchownSync(
|
|
3291
|
+
/** chown on an open file descriptor. Mutates the underlying inode's uid/gid. */
|
|
3292
|
+
fchownSync(fd, uid, gid) {
|
|
3293
|
+
fchownSync(this._sync, fd, uid, gid);
|
|
3022
3294
|
}
|
|
3023
3295
|
utimesSync(filePath, atime, mtime) {
|
|
3024
3296
|
utimesSync(this._sync, toPathString(filePath), atime, mtime);
|
|
3025
3297
|
}
|
|
3026
|
-
/** utimes on an open file descriptor.
|
|
3027
|
-
futimesSync(
|
|
3298
|
+
/** utimes on an open file descriptor. Mutates the underlying inode's atime/mtime. */
|
|
3299
|
+
futimesSync(fd, atime, mtime) {
|
|
3300
|
+
futimesSync(this._sync, fd, atime, mtime);
|
|
3028
3301
|
}
|
|
3029
3302
|
/** Like utimesSync but operates on the symlink itself. In this VFS, delegates to utimesSync. */
|
|
3030
3303
|
lutimesSync(filePath, atime, mtime) {
|
|
@@ -3649,15 +3922,15 @@ var VFSFileSystem = class {
|
|
|
3649
3922
|
}
|
|
3650
3923
|
futimes(fd, atime, mtime, callback) {
|
|
3651
3924
|
this._validateCb(callback);
|
|
3652
|
-
|
|
3925
|
+
return this._cbVoid(this.promises.futimes(fd, atime, mtime), callback);
|
|
3653
3926
|
}
|
|
3654
3927
|
fchmod(fd, mode, callback) {
|
|
3655
3928
|
this._validateCb(callback);
|
|
3656
|
-
|
|
3929
|
+
return this._cbVoid(this.promises.fchmod(fd, mode), callback);
|
|
3657
3930
|
}
|
|
3658
3931
|
fchown(fd, uid, gid, callback) {
|
|
3659
3932
|
this._validateCb(callback);
|
|
3660
|
-
|
|
3933
|
+
return this._cbVoid(this.promises.fchown(fd, uid, gid), callback);
|
|
3661
3934
|
}
|
|
3662
3935
|
lchmod(filePath, mode, callback) {
|
|
3663
3936
|
this._validateCb(callback);
|
|
@@ -3796,8 +4069,10 @@ var VFSPromises = class {
|
|
|
3796
4069
|
lchmod(filePath, mode) {
|
|
3797
4070
|
return chmod(this._async, filePath, mode);
|
|
3798
4071
|
}
|
|
3799
|
-
/** chmod on an open file descriptor.
|
|
3800
|
-
|
|
4072
|
+
/** chmod on an open file descriptor. Engine resolves fd → inode and
|
|
4073
|
+
* mutates the mode bits directly. */
|
|
4074
|
+
fchmod(fd, mode) {
|
|
4075
|
+
return fchmod(this._async, fd, mode);
|
|
3801
4076
|
}
|
|
3802
4077
|
chown(filePath, uid, gid) {
|
|
3803
4078
|
return chown(this._async, toPathString(filePath), uid, gid);
|
|
@@ -3806,14 +4081,18 @@ var VFSPromises = class {
|
|
|
3806
4081
|
lchown(filePath, uid, gid) {
|
|
3807
4082
|
return chown(this._async, filePath, uid, gid);
|
|
3808
4083
|
}
|
|
3809
|
-
/** chown on an open file descriptor.
|
|
3810
|
-
|
|
4084
|
+
/** chown on an open file descriptor. Engine resolves fd → inode and
|
|
4085
|
+
* mutates uid/gid directly. */
|
|
4086
|
+
fchown(fd, uid, gid) {
|
|
4087
|
+
return fchown(this._async, fd, uid, gid);
|
|
3811
4088
|
}
|
|
3812
4089
|
utimes(filePath, atime, mtime) {
|
|
3813
4090
|
return utimes(this._async, toPathString(filePath), atime, mtime);
|
|
3814
4091
|
}
|
|
3815
|
-
/** utimes on an open file descriptor.
|
|
3816
|
-
|
|
4092
|
+
/** utimes on an open file descriptor. Engine resolves fd → inode and
|
|
4093
|
+
* mutates atime/mtime directly. */
|
|
4094
|
+
futimes(fd, atime, mtime) {
|
|
4095
|
+
return futimes(this._async, fd, atime, mtime);
|
|
3817
4096
|
}
|
|
3818
4097
|
/** Like utimes but operates on the symlink itself. In this VFS, delegates to utimes. */
|
|
3819
4098
|
lutimes(filePath, atime, mtime) {
|
|
@@ -5133,6 +5412,40 @@ var VFSEngine = class {
|
|
|
5133
5412
|
this.handle.flush();
|
|
5134
5413
|
return { status: 0 };
|
|
5135
5414
|
}
|
|
5415
|
+
// ---- FCHMOD ----
|
|
5416
|
+
// fd-based chmod: look up the inode directly from the fd table and mutate
|
|
5417
|
+
// its mode bits. Native Node does the same thing at the libuv layer.
|
|
5418
|
+
fchmod(fd, mode) {
|
|
5419
|
+
const entry = this.fdTable.get(fd);
|
|
5420
|
+
if (!entry) return { status: CODE_TO_STATUS.EBADF };
|
|
5421
|
+
const inode = this.readInode(entry.inodeIdx);
|
|
5422
|
+
inode.mode = inode.mode & S_IFMT | mode & 4095;
|
|
5423
|
+
inode.ctime = Date.now();
|
|
5424
|
+
this.writeInode(entry.inodeIdx, inode);
|
|
5425
|
+
return { status: 0 };
|
|
5426
|
+
}
|
|
5427
|
+
// ---- FCHOWN ----
|
|
5428
|
+
fchown(fd, uid, gid) {
|
|
5429
|
+
const entry = this.fdTable.get(fd);
|
|
5430
|
+
if (!entry) return { status: CODE_TO_STATUS.EBADF };
|
|
5431
|
+
const inode = this.readInode(entry.inodeIdx);
|
|
5432
|
+
inode.uid = uid;
|
|
5433
|
+
inode.gid = gid;
|
|
5434
|
+
inode.ctime = Date.now();
|
|
5435
|
+
this.writeInode(entry.inodeIdx, inode);
|
|
5436
|
+
return { status: 0 };
|
|
5437
|
+
}
|
|
5438
|
+
// ---- FUTIMES ----
|
|
5439
|
+
futimes(fd, atime, mtime) {
|
|
5440
|
+
const entry = this.fdTable.get(fd);
|
|
5441
|
+
if (!entry) return { status: CODE_TO_STATUS.EBADF };
|
|
5442
|
+
const inode = this.readInode(entry.inodeIdx);
|
|
5443
|
+
inode.atime = atime;
|
|
5444
|
+
inode.mtime = mtime;
|
|
5445
|
+
inode.ctime = Date.now();
|
|
5446
|
+
this.writeInode(entry.inodeIdx, inode);
|
|
5447
|
+
return { status: 0 };
|
|
5448
|
+
}
|
|
5136
5449
|
// ---- OPENDIR ----
|
|
5137
5450
|
opendir(path, tabId) {
|
|
5138
5451
|
path = this.normalizePath(path);
|