@neodx/vfs
Version:
Simple virtual file system - working dir context, lazy changes, different modes, integrations and moreover
171 lines (170 loc) • 4.57 kB
JavaScript
import { colors as e } from '@neodx/colors';
import {
entries as t,
uniq as a,
isTypeOfString as r,
concurrently as i,
isTruthy as n,
compact as s,
uniqBy as l
} from '@neodx/std';
import { join as o, dirname as f, sep as d, relative as c } from 'pathe';
function u(e = '/', r = {}) {
let i = new Map(t(y(r, e)).map(([e, t]) => [e, Buffer.from(t)])),
n = new Set(),
s = e => i.has(e),
l = e => !s(e) && Array.from(i.keys()).some(m(e)),
d = e => {
i.delete(e), n.add(e);
};
return {
read: e => i.get(e) ?? null,
isFile: s,
isDir: l,
exists: e => s(e) || l(e),
readDir: e =>
a(
Array.from(i.keys())
.filter(m(e))
.map(t => t.split(p(e))[1].split('/')[0])
).map(t => g(t, s(o(e, t)))),
write(e, t) {
for (i.set(e, Buffer.from(t)); '/' !== e; ) n.delete(e), (e = f(e));
},
delete(e) {
for (let t of (d(e), i.keys())) h(t, e) && d(t);
},
__: { kind: 'in-memory', getStore: () => new Map(i), getDeleted: () => new Set(n) }
};
}
let g = (e, t, a = !1) => ({
isFile: () => t,
isDirectory: () => !t,
isSymbolicLink: () => a,
name: e
}),
p = e => (e.endsWith('/') ? e : `${e}/`),
h = (e, t) => e.startsWith(p(t)),
m = e => t => h(t, e);
function y(e, a = '') {
let i = {};
for (let [n, s] of t(e)) {
let e = o(a, n);
r(s) ? (i[e] = s) : Object.assign(i, y(s, e));
}
return i;
}
async function w(e, t = '.') {
let a = e.get(t);
return (
e.log.debug('Check exists %s', S(e, t)),
!A(e, t) &&
(!!a ||
e.getRelativeChanges(t).filter(e => !e.deleted).length > 0 ||
(await e.backend.exists(t)))
);
}
async function b(e, t = '.') {
let a = e.get(t);
return a ? !a.deleted : await e.backend.isFile(t);
}
async function k(e, t = '.') {
return e.getRelativeChanges(t).some(e => !e.deleted) || (await e.backend.isDir(t));
}
async function v(e, t = '.') {
e.log.debug('Read dir %s', S(e, t));
let a = await e.backend.readDir(t),
r = e.getRelativeChanges(t),
i = t => !A(e, t),
n = e.resolve(t),
s = t => c(n, e.resolve(t)).split(d)[0];
return l(
[
...a.filter(a => i(e.resolve(t, a.name))),
...r
.filter(e => i(e.path))
.map(e => g(s(e.path), !0))
.filter(e => !!e.name.replaceAll('.', ''))
],
e => e.name
);
}
async function V(e, t, a) {
if ((e.log.debug('Read %s', S(e, t)), !(await b(e, t)))) return null;
let r = e.get(t)?.content ?? (await e.backend.read(t));
return a ? r.toString(a) : r;
}
async function x(e, t, a) {
let r = await V(e, t, a);
if (null === r) throw Error(`"${t}" is not file`);
return r;
}
async function D(e, t, a) {
e.log.debug('Write %s', S(e, t));
let r = await P(e, t);
(function e(t, a) {
let r = f(a);
r !== a && (t.unregister(r), e(t, r));
})(e, e.resolve(t)),
r && Buffer.from(a).equals(r) ? e.unregister(t) : e.writePathContent(t, a);
}
async function R(e, t) {
for (let a of (e.log.debug('Delete %s', S(e, t)), e.deletePath(t, !0), e.getRelativeChanges(t)))
e.unregister(a.path);
let a = f(e.resolve(t));
0 === (await v(e, a)).length && (await R(e, a));
}
async function F(e, t, ...a) {
if ((e.log.debug('Rename %s to %s', S(e, t), a.map(t => S(e, t)).join(', ')), !(await w(e, t)))) {
e.log.debug('Path %s not exists, rename skipped', S(e, t));
return;
}
let r = await x(e, t);
await R(e, t), await i(a, t => D(e, t, r), 5);
}
async function C(e, t) {
let a = await i(e.getAllDirectChanges(), async ({ path: t, deleted: a, content: r, ...i }) => {
let n = await e.backend.exists(t);
return a && !n
? null
: a
? { ...i, path: t, type: 'delete' }
: { ...i, path: t, type: n ? 'update' : 'create', content: r };
});
return t ? a.filter(e => n(e) && t.includes(e.type)) : s(a);
}
async function P(e, t) {
let a = e.resolve(t);
return (await e.backend.isFile(a)) ? await e.backend.read(a) : null;
}
let S = (t, a) => {
let r =
t.path.length > W ? `${t.path.slice(0, W / 4)}...${t.path.slice(-(3 * W) / 4)}` : t.path;
return `${e.gray(r + d)}${t.relative(a)}`;
},
$ = (e, t) => e.get(t)?.deleted,
A = (e, t) =>
$(e, t) ||
e
.relative(t)
.split('/')
.filter(e => !e.startsWith('.'))
.some(t => $(e, t)),
W = 28;
export {
b as a,
x as b,
F as c,
R as d,
w as e,
u as f,
C as g,
y as h,
k as i,
S as j,
h as p,
v as r,
V as t,
D as w
};
//# sourceMappingURL=operations-D4d9Xk5B.mjs.map