UNPKG

@neodx/vfs

Version:

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

283 lines (282 loc) 8.93 kB
var e = require('./_internal/operations-DJhEnMA2.cjs'), t = require('node:fs/promises'), r = require('@neodx/fs'), a = require('@neodx/log/node'), n = require('@neodx/std'), s = require('pathe'), i = require('@neodx/colors'), l = require('./plugins/eslint.cjs'), o = require('./plugins/glob.cjs'), c = require('./plugins/json.cjs'), u = require('./plugins/package-json.cjs'), p = require('./plugins/prettier.cjs'), d = require('./plugins/scan.cjs'), g = require('./_internal/create-vfs-plugin-Bg0LL_-h.cjs'); function f() { return { async read(e) { try { return await r.readFile(e); } catch { return null; } }, write: async (e, t) => (await r.ensureFile(e), await r.writeFile(e, t)), delete: async e => await r.rm(e, { force: !0, recursive: !0 }), exists: async e => await r.exists(e), async readDir(e) { try { return await t.readdir(e, { withFileTypes: !0 }); } catch { return []; } }, isDir: async e => await r.isDirectory(e), isFile: async e => await r.isFile(e), __: { kind: 'node-fs' } }; } const _ = ({ parent: e, logLevel: t, log: r = t ? x.fork({ level: t }) : x, ...a }) => { let i = new Map(), l = { log: r, ...a, catch(e, t) { let r = Error(`${e} (${t})`); return (r.path = l.path), (r.name = 'VfsError'), (r.cause = t), l.log.error(r), r; }, get(e) { let t = l.resolve(e); return l.getAllChanges().find(e => e.path === t) ?? null; }, getAllChanges: () => w(l.__.getAll()), getAllDirectChanges: () => w(l.__.getScoped()), getRelativeChanges(e) { let t = m(l.resolve(e)); return n.uniqBy( l.__.getAll() .flatMap(e => Array.from(e.__.getStore().values())) .filter(e => e.path.startsWith(t)), e => e.path ); }, writePathContent(e, t) { let r = l.resolve(e), a = l.get(r); l.__.register(r, { deleted: !1, content: t, updatedAfterDelete: a?.deleted }); }, deletePath(e) { l.__.register(l.resolve(e), { content: null, deleted: !0 }); }, unregister(e) { l.__.unregister(l.resolve(e)); }, resolve: (...e) => s.resolve(l.path, ...e), relative(e) { let t = s.normalize(e); return '/' === l.path && t.startsWith('/') ? t.slice(1) : s.relative(l.path, s.resolve(l.path, t)); }, backend: n.mapValues(a.backend, (e, t) => '__' === t ? e : async (t, ...r) => await e(l.resolve(t), ...r) ), __: { kind: y, parent: e, plugins: [], children: [], getStore: () => i, getAll: () => [...l.__.getAncestors(), l, ...l.__.getDescendants()], getScoped: () => [l, ...l.__.getDescendants()], getAncestors: () => h(l), getDescendants: () => v(l), register: (e, t) => { let r = { ...l.get(e), ...t, path: e, content: n.isNull(t.content) ? t.content : Buffer.from(t.content), relativePath: l.relative(e) }; l.__.getAll().forEach(t => t.__.getStore().set(e, r)); }, unregister: e => { l.__.getAll().forEach(t => t.__.getStore().delete(e)); } } }; return e && e.__.children.push(l), l; }, y = Symbol('VfsContext'), h = e => (e.__.parent ? [e.__.parent, ...h(e.__.parent)] : []), v = e => e.__.children.flatMap(e => [e, ...v(e)]), w = e => n.uniqBy( e.flatMap(e => Array.from(e.__.getStore().values())), e => e.path ), m = e => (e.endsWith('/') ? e : `${e}/`), x = a.createLogger({ name: 'vfs', level: 'info' }), A = e => e.__?.kind ?? 'unknown', D = () => { 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 n.asyncReduce(this.get(e), async (e, r) => await r(...t), void 0); } }; }, F = (e, t, r) => { let a = { context: t, ...n.fromKeys(['beforeApply', 'beforeApplyFile', 'afterDelete'], r.scope) }; return { ...e, __: a, child(e) { let { log: r, backend: a } = t, n = _({ backend: a, parent: t, path: t.resolve(e), log: r }); return V(k(n), n, D(), ...t.__.plugins); }, pipe: (...a) => V(e, t, r, ...a) }; }, V = (e, t, r, ...a) => { let s = a.reduce( (e, a) => a(e, { context: t, ...n.fromKeys(['beforeApply', 'beforeApplyFile', 'afterDelete'], r.scope) }), e ); return t.__.plugins.push(...a), (t.__.vfs = s), F(s, t, r); }; function k(t) { let r = D(), a = A(t.backend), i = async e => { t.log.info('%s %s', q[e.type], e.relativePath), await r.run('beforeApplyFile', e, o()), ('delete' === e.type || e.updatedAfterDelete) && (await t.backend.delete(e.path)), 'delete' !== e.type && (await t.backend.write(e.path, e.content)), 'delete' === e.type && (await r.run('afterDelete', e.path, o())), t.unregister(e.path); }, l = { [b]: t, get log() { return t.log; }, get path() { return t.path; }, get dirname() { return s.dirname(t.path); }, get virtual() { return 'in-memory' === a; }, get readonly() { return 'readonly' === a; }, async apply() { try { let a = await e.getVfsActions(t); t.log.info( 'Applying %d %s...', a.length, n.quickPluralize(a.length, 'change', 'changes') ), await r.run('beforeApply', a, o()), await n.concurrently(await e.getVfsActions(t), i); } catch (e) { throw t.catch('Failed to apply changes', e); } }, resolve: t.resolve, relative: t.relative, isDir: r => e.isVfsDir(t, r), isFile: r => e.isVfsFile(t, r), exists: r => e.existsVfsPath(t, r), readDir: async (r, a) => { let [n, { withFileTypes: s } = {}] = 'string' == typeof r ? [r, a] : [void 0, r], i = await e.readVfsDir(t, n); return s ? i : i.map(e => e.name); }, read: (r, a) => e.readVfsFile(t, r, a), write: (r, a) => e.writeVfsFile(t, r, a), rename: (r, ...a) => e.renameVfs(t, r, ...a), delete: r => e.deleteVfsPath(t, r), tryRead: (r, a) => e.tryReadVfsFile(t, r, a) }, o = () => t.__.vfs ?? l; return F(l, t, r); } const q = { delete: i.colors.red('delete'), create: i.colors.green('create'), update: i.colors.yellow('update') }, b = Symbol('context'); function B( e, { log: t = 'error', virtual: r, readonly: n, backend: s = j(e, { virtual: r, readonly: n }) } = {} ) { return k(_({ path: e, log: a.createAutoLogger(t, { name: 'vfs' }), backend: s })); } function j(t, { virtual: r, readonly: a }) { let i = r ? e.createInMemoryBackend(t, !0 === r ? {} : r) : f(); return a ? (function (t) { let r = e.createInMemoryBackend(), a = t => { let a = Array.from(r.__.getDeleted()); return a.includes(t) || a.some(r => e.pathStartsWith(t, r)); }; return { read: e => (a(e) ? null : r.read(e) ?? t.read(e)), exists: e => !a(e) && (r.exists(e) || t.exists(e)), isFile: e => !a(e) && (r.isFile(e) || t.isFile(e)), isDir: e => !a(e) && (r.isDir(e) || t.isDir(e)), write: r.write, delete: r.delete, async readDir(e) { if (a(e)) return []; let i = await t.readDir(e); return n.uniqBy( i.filter(t => !a(s.resolve(e, t.name))).concat(r.readDir(e)), e => e.name ); }, __: { kind: 'readonly' } }; })(i) : i; } (exports.createInMemoryBackend = e.createInMemoryBackend), (exports.createInMemoryFilesRecord = e.createInMemoryFilesRecord), (exports.createVfsPlugin = g.createVfsPlugin), (exports.createBaseVfs = k), (exports.createDefaultVfsBackend = j), (exports.createHeadlessVfs = B), (exports.createNodeFsBackend = f), (exports.createVfs = function (e, { eslint: t = !0, prettier: r = !0, ...a } = {}) { return B(e, a).pipe( c.json(), d.scan(), o.glob(), l.eslint(n.isTypeOfBoolean(t) ? { auto: t } : t), p.prettier(n.isTypeOfBoolean(r) ? { auto: r } : r), u.packageJson() ); }), (exports.createVfsContext = _); //# sourceMappingURL=index.cjs.map