UNPKG

@neodx/vfs

Version:

Simple virtual file system - working dir context, lazy changes, different modes, integrations and moreover

171 lines (170 loc) 4.57 kB
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