UNPKG

@neodx/vfs

Version:

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

296 lines (295 loc) 8.74 kB
import { g as e, i as t, a as r, e as a, r as n, b as s, w as l, c as i, d as o, t as p, f as c, p as d } from './_internal/operations-D4d9Xk5B.mjs'; export { h as createInMemoryFilesRecord } from './_internal/operations-D4d9Xk5B.mjs'; import { readdir as u } from 'node:fs/promises'; import { readFile as g, ensureFile as f, writeFile as _, rm as m, exists as h, isDirectory as y, isFile as w } from '@neodx/fs'; import { createLogger as v, createAutoLogger as A } from '@neodx/log/node'; import { uniqBy as D, mapValues as x, isNull as b, fromKeys as k, asyncReduce as F, quickPluralize as j, concurrently as S, isTypeOfBoolean as V } from '@neodx/std'; import { resolve as C, normalize as M, relative as B, dirname as P } from 'pathe'; import { colors as E } from '@neodx/colors'; import { eslint as R } from './plugins/eslint.mjs'; import { glob as W } from './plugins/glob.mjs'; import { json as $ } from './plugins/json.mjs'; import { packageJson as I } from './plugins/package-json.mjs'; import { prettier as H } from './plugins/prettier.mjs'; import { scan as N } from './plugins/scan.mjs'; export { c as createVfsPlugin } from './_internal/create-vfs-plugin-CTZbwgZU.mjs'; function T() { return { async read(e) { try { return await g(e); } catch { return null; } }, write: async (e, t) => (await f(e), await _(e, t)), delete: async e => await m(e, { force: !0, recursive: !0 }), exists: async e => await h(e), async readDir(e) { try { return await u(e, { withFileTypes: !0 }); } catch { return []; } }, isDir: async e => await y(e), isFile: async e => await w(e), __: { kind: 'node-fs' } }; } let q = ({ parent: e, logLevel: t, log: r = t ? O.fork({ level: t }) : O, ...a }) => { let n = new Map(), s = { log: r, ...a, catch(e, t) { let r = Error(`${e} (${t})`); return (r.path = s.path), (r.name = 'VfsError'), (r.cause = t), s.log.error(r), r; }, get(e) { let t = s.resolve(e); return s.getAllChanges().find(e => e.path === t) ?? null; }, getAllChanges: () => K(s.__.getAll()), getAllDirectChanges: () => K(s.__.getScoped()), getRelativeChanges(e) { let t = L(s.resolve(e)); return D( s.__.getAll() .flatMap(e => Array.from(e.__.getStore().values())) .filter(e => e.path.startsWith(t)), e => e.path ); }, writePathContent(e, t) { let r = s.resolve(e), a = s.get(r); s.__.register(r, { deleted: !1, content: t, updatedAfterDelete: a?.deleted }); }, deletePath(e) { s.__.register(s.resolve(e), { content: null, deleted: !0 }); }, unregister(e) { s.__.unregister(s.resolve(e)); }, resolve: (...e) => C(s.path, ...e), relative(e) { let t = M(e); return '/' === s.path && t.startsWith('/') ? t.slice(1) : B(s.path, C(s.path, t)); }, backend: x(a.backend, (e, t) => '__' === t ? e : async (t, ...r) => await e(s.resolve(t), ...r) ), __: { kind: z, parent: e, plugins: [], children: [], getStore: () => n, getAll: () => [...s.__.getAncestors(), s, ...s.__.getDescendants()], getScoped: () => [s, ...s.__.getDescendants()], getAncestors: () => G(s), getDescendants: () => J(s), register: (e, t) => { let r = { ...s.get(e), ...t, path: e, content: b(t.content) ? t.content : Buffer.from(t.content), relativePath: s.relative(e) }; s.__.getAll().forEach(t => t.__.getStore().set(e, r)); }, unregister: e => { s.__.getAll().forEach(t => t.__.getStore().delete(e)); } } }; return e && e.__.children.push(s), s; }, z = Symbol('VfsContext'), G = e => (e.__.parent ? [e.__.parent, ...G(e.__.parent)] : []), J = e => e.__.children.flatMap(e => [e, ...J(e)]), K = e => D( e.flatMap(e => Array.from(e.__.getStore().values())), e => e.path ), L = e => (e.endsWith('/') ? e : `${e}/`), O = v({ name: 'vfs', level: 'info' }), Q = e => e.__?.kind ?? 'unknown', U = () => { let e = new Map(); return { scope(t) { let r = e.get(t) ?? []; return e.set(t, r), e => r.push(e); }, get: t => e.get(t) ?? [], async run(e, ...t) { return F(this.get(e), async (e, r) => await r(...t), void 0); } }; }, X = (e, t, r) => { let a = { context: t, ...k(['beforeApply', 'beforeApplyFile', 'afterDelete'], r.scope) }; return { ...e, __: a, child(e) { let { log: r, backend: a } = t, n = q({ backend: a, parent: t, path: t.resolve(e), log: r }); return Y(Z(n), n, U(), ...t.__.plugins); }, pipe: (...a) => Y(e, t, r, ...a) }; }, Y = (e, t, r, ...a) => { let n = a.reduce( (e, a) => a(e, { context: t, ...k(['beforeApply', 'beforeApplyFile', 'afterDelete'], r.scope) }), e ); return t.__.plugins.push(...a), (t.__.vfs = n), X(n, t, r); }; function Z(c) { let d = U(), u = Q(c.backend), g = async e => { c.log.info('%s %s', ee[e.type], e.relativePath), await d.run('beforeApplyFile', e, _()), ('delete' === e.type || e.updatedAfterDelete) && (await c.backend.delete(e.path)), 'delete' !== e.type && (await c.backend.write(e.path, e.content)), 'delete' === e.type && (await d.run('afterDelete', e.path, _())), c.unregister(e.path); }, f = { [et]: c, get log() { return c.log; }, get path() { return c.path; }, get dirname() { return P(c.path); }, get virtual() { return 'in-memory' === u; }, get readonly() { return 'readonly' === u; }, async apply() { try { let t = await e(c); c.log.info('Applying %d %s...', t.length, j(t.length, 'change', 'changes')), await d.run('beforeApply', t, _()), await S(await e(c), g); } catch (e) { throw c.catch('Failed to apply changes', e); } }, resolve: c.resolve, relative: c.relative, isDir: e => t(c, e), isFile: e => r(c, e), exists: e => a(c, e), readDir: async (e, t) => { let [r, { withFileTypes: a } = {}] = 'string' == typeof e ? [e, t] : [void 0, e], s = await n(c, r); return a ? s : s.map(e => e.name); }, read: (e, t) => s(c, e, t), write: (e, t) => l(c, e, t), rename: (e, ...t) => i(c, e, ...t), delete: e => o(c, e), tryRead: (e, t) => p(c, e, t) }, _ = () => c.__.vfs ?? f; return X(f, c, d); } let ee = { delete: E.red('delete'), create: E.green('create'), update: E.yellow('update') }, et = Symbol('context'); function er(e, { eslint: t = !0, prettier: r = !0, ...a } = {}) { return ea(e, a).pipe($(), N(), W(), R(V(t) ? { auto: t } : t), H(V(r) ? { auto: r } : r), I()); } function ea( e, { log: t = 'error', virtual: r, readonly: a, backend: n = en(e, { virtual: r, readonly: a }) } = {} ) { return Z(q({ path: e, log: A(t, { name: 'vfs' }), backend: n })); } function en(e, { virtual: t, readonly: r }) { let a = t ? c(e, !0 === t ? {} : t) : T(); return r ? (function (e) { let t = c(), r = e => { let r = Array.from(t.__.getDeleted()); return r.includes(e) || r.some(t => d(e, t)); }; return { read: a => (r(a) ? null : t.read(a) ?? e.read(a)), exists: a => !r(a) && (t.exists(a) || e.exists(a)), isFile: a => !r(a) && (t.isFile(a) || e.isFile(a)), isDir: a => !r(a) && (t.isDir(a) || e.isDir(a)), write: t.write, delete: t.delete, readDir: async a => r(a) ? [] : D( (await e.readDir(a)).filter(e => !r(C(a, e.name))).concat(t.readDir(a)), e => e.name ), __: { kind: 'readonly' } }; })(a) : a; } export { Z as createBaseVfs, en as createDefaultVfsBackend, ea as createHeadlessVfs, c as createInMemoryBackend, T as createNodeFsBackend, er as createVfs, q as createVfsContext }; //# sourceMappingURL=index.mjs.map