@neodx/vfs
Version:
Simple virtual file system - working dir context, lazy changes, different modes, integrations and moreover
1 lines • 18.2 kB
Source Map (JSON)
{"version":3,"file":"operations-D4d9Xk5B.mjs","sources":["../../../src/backend/create-in-memory-backend.ts","../../../src/core/operations.ts"],"sourcesContent":["import { entries, isTypeOfString, uniq } from '@neodx/std';\nimport { dirname, join } from 'pathe';\nimport type { VfsContentLike } from '../core/types';\nimport type { VfsBackend } from './shared';\n\nexport interface VirtualInitializer {\n [path: string]: string | VirtualInitializer;\n}\n\n/**\n * In-memory VFS backend.\n * Useful for testing, emulating file system, etc.\n */\nexport function createInMemoryBackend(root = '/', initializer: VirtualInitializer = {}) {\n // generate new implementation based on old one\n const store = new Map<string, Buffer>(\n entries(createInMemoryFilesRecord(initializer, root)).map(([path, content]) => [\n path,\n Buffer.from(content)\n ])\n );\n const deleted = new Set<string>();\n\n const isFile = (path: string) => store.has(path);\n const isDir = (path: string) =>\n !isFile(path) && Array.from(store.keys()).some(pathStartsBy(path));\n const deletePath = (path: string) => {\n store.delete(path);\n deleted.add(path);\n };\n\n return {\n read(path: string) {\n return store.get(path) ?? null;\n },\n\n isFile,\n isDir,\n exists(path: string) {\n return isFile(path) || isDir(path);\n },\n\n readDir(path: string) {\n return uniq(\n Array.from(store.keys())\n .filter(pathStartsBy(path))\n .map(name => name.split(withTrailingSlash(path))[1]!.split('/')[0]!)\n ).map(name => createInMemoryDirent(name, isFile(join(path, name))));\n },\n\n write(path: string, content: VfsContentLike) {\n store.set(path, Buffer.from(content));\n while (path !== '/') {\n deleted.delete(path);\n path = dirname(path);\n }\n },\n\n delete(path: string) {\n deletePath(path);\n for (const name of store.keys()) {\n if (pathStartsWith(name, path)) {\n deletePath(name);\n }\n }\n },\n\n __: {\n kind: 'in-memory',\n getStore: () => new Map(store),\n getDeleted: () => new Set(deleted)\n }\n } satisfies VfsBackend;\n}\n\nexport const createInMemoryDirent = (name: string, file: boolean, symlink = false) => ({\n isFile: () => file,\n isDirectory: () => !file,\n isSymbolicLink: () => symlink,\n name\n});\n\nexport const withTrailingSlash = (path: string) => (path.endsWith('/') ? path : `${path}/`);\nexport const pathStartsWith = (fullPath: string, basePath: string) =>\n fullPath.startsWith(withTrailingSlash(basePath));\nexport const pathStartsBy = (basePath: string) => (fullPath: string) =>\n pathStartsWith(fullPath, basePath);\n\n/**\n * @param initializer Virtual files tree\n * @param base Root path\n * @example\n * ```ts\n * createInMemoryFilesRecord({\n * \"package.json\": \"{...}\",\n * \"src\": {\n * \"foo\": {\n * \"bar.ts\": \"export const a = 1\"\n * \"baz.ts\": \"export const b = 2\"\n * },\n * \"index.ts\": \"export const c = 3\"\n * }\n * });\n * // {\n * // \"package.json\": \"{...}\",\n * // \"src/foo/bar.ts\": \"export const a = 1\",\n * // \"src/foo/baz.ts\": \"export const b = 2\",\n * // \"src/index.ts\": \"export const c = 3\"\n * // }\n * ```\n */\nexport function createInMemoryFilesRecord(initializer: VirtualInitializer, base = '') {\n const result = {} as Record<string, string>;\n\n for (const [name, value] of entries(initializer)) {\n const path = join(base, name);\n\n if (isTypeOfString(value)) result[path] = value;\n else Object.assign(result, createInMemoryFilesRecord(value, path));\n }\n return result;\n}\n","import { colors } from '@neodx/colors';\nimport { compact, concurrently, isTruthy, uniqBy } from '@neodx/std';\nimport { dirname, relative, sep } from 'pathe';\nimport { createInMemoryDirent } from '../backend/create-in-memory-backend.ts';\nimport type { VfsContext } from './context';\nimport type { VfsContentLike, VfsFileAction } from './types';\n\nexport async function existsVfsPath(ctx: VfsContext, path = '.') {\n const meta = ctx.get(path);\n\n ctx.log.debug('Check exists %s', displayPath(ctx, path));\n if (isKnownDeletedPath(ctx, path)) return false;\n // If we know any non-deleted descendants of this path, then it's exists\n if (meta || getVfsNonDeletedDescendants(ctx, path).length > 0) return true;\n return await ctx.backend.exists(path);\n}\n\nexport async function isVfsFile(ctx: VfsContext, path = '.') {\n const meta = ctx.get(path);\n\n return meta ? !meta.deleted : await ctx.backend.isFile(path);\n}\n\nexport async function isVfsDir(ctx: VfsContext, path = '.') {\n return (\n ctx.getRelativeChanges(path).some(meta => !meta.deleted) || (await ctx.backend.isDir(path))\n );\n}\n\n/**\n * Returns actual children of a directory.\n */\nexport async function readVfsDir(ctx: VfsContext, path = '.') {\n ctx.log.debug('Read dir %s', displayPath(ctx, path));\n const actualChildren = await ctx.backend.readDir(path);\n const changes = ctx.getRelativeChanges(path);\n const isNotDeleted = (name: string) => !isKnownDeletedPath(ctx, name);\n const basePath = ctx.resolve(path);\n const getDirentName = (path: string) => relative(basePath, ctx.resolve(path)).split(sep)[0]!;\n\n return uniqBy(\n [\n ...actualChildren.filter(entry => isNotDeleted(ctx.resolve(path, entry.name))),\n ...changes\n .filter(meta => isNotDeleted(meta.path))\n .map(meta => createInMemoryDirent(getDirentName(meta.path), true))\n .filter(entry => Boolean(entry.name.replaceAll('.', '')))\n ],\n entry => entry.name\n );\n}\n\nexport async function tryReadVfsFile(ctx: VfsContext, path: string): Promise<Buffer | null>;\nexport async function tryReadVfsFile(\n ctx: VfsContext,\n path: string,\n encoding: BufferEncoding\n): Promise<string | null>;\nexport async function tryReadVfsFile(\n ctx: VfsContext,\n path: string,\n encoding?: BufferEncoding\n): Promise<Buffer | string | null> {\n ctx.log.debug('Read %s', displayPath(ctx, path));\n if (!(await isVfsFile(ctx, path))) return null;\n const content = ctx.get(path)?.content ?? (await ctx.backend.read(path));\n\n return encoding ? content!.toString(encoding) : content;\n}\n\nexport async function readVfsFile(ctx: VfsContext, path: string): Promise<Buffer>;\nexport async function readVfsFile(\n ctx: VfsContext,\n path: string,\n encoding: BufferEncoding\n): Promise<string>;\nexport async function readVfsFile(\n ctx: VfsContext,\n path: string,\n encoding?: BufferEncoding\n): Promise<Buffer | string> {\n const content = await tryReadVfsFile(ctx, path, encoding!);\n\n if (content === null) {\n throw new Error(`\"${path}\" is not file`);\n }\n return content;\n}\n\nexport async function writeVfsFile(ctx: VfsContext, path: string, content: VfsContentLike) {\n ctx.log.debug('Write %s', displayPath(ctx, path));\n const actualContent = await tryReadVfsBackendFile(ctx, path);\n\n ensureVfsPath(ctx, ctx.resolve(path));\n if (actualContent && Buffer.from(content).equals(actualContent)) {\n // If content is not changed, then we can just forget about this file\n ctx.unregister(path);\n } else {\n ctx.writePathContent(path, content);\n }\n}\n\nexport async function deleteVfsPath(ctx: VfsContext, path: string) {\n ctx.log.debug('Delete %s', displayPath(ctx, path));\n ctx.deletePath(path, true);\n for (const meta of ctx.getRelativeChanges(path)) {\n ctx.unregister(meta.path);\n }\n const parentDirName = dirname(ctx.resolve(path));\n const children = await readVfsDir(ctx, parentDirName);\n\n // TODO SEC-55 add condition\n if (children.length === 0) {\n await deleteVfsPath(ctx, parentDirName);\n }\n}\n\nexport async function renameVfs(ctx: VfsContext, from: string, ...to: string[]) {\n ctx.log.debug(\n 'Rename %s to %s',\n displayPath(ctx, from),\n to.map(path => displayPath(ctx, path)).join(', ')\n );\n if (!(await existsVfsPath(ctx, from))) {\n ctx.log.debug('Path %s not exists, rename skipped', displayPath(ctx, from));\n return;\n }\n const content = await readVfsFile(ctx, from);\n\n await deleteVfsPath(ctx, from);\n await concurrently(to, path => writeVfsFile(ctx, path, content), 5);\n}\n\nexport async function getVfsActions(ctx: VfsContext): Promise<VfsFileAction[]>;\nexport async function getVfsActions<T extends VfsFileAction['type']>(\n ctx: VfsContext,\n types: T[]\n): Promise<Extract<VfsFileAction, { type: T }>[]>;\nexport async function getVfsActions(ctx: VfsContext, types?: VfsFileAction['type'][]) {\n const changes = await concurrently(\n ctx.getAllDirectChanges(),\n async ({ path, deleted, content, ...meta }): Promise<VfsFileAction | null> => {\n // ctx.log.debug('Resolving required action for %s', displayPath(ctx, path));\n const exists = await ctx.backend.exists(path);\n\n if (deleted && !exists) {\n return null;\n }\n if (deleted) {\n return { ...meta, path, type: 'delete' };\n }\n return {\n ...meta,\n path,\n type: exists ? 'update' : 'create',\n content: content!\n };\n }\n );\n\n // ctx.log.debug('Found %d changes under \"%s\" working directory', changes.length, ctx.path);\n\n return types\n ? changes.filter(action => isTruthy(action) && types.includes(action.type))\n : compact(changes);\n}\n\n/** Guarantees all ancestor directories not deleted */\nexport function ensureVfsPath(ctx: VfsContext, path: string) {\n const parent = dirname(path);\n\n if (parent !== path) {\n ctx.unregister(parent);\n ensureVfsPath(ctx, parent);\n }\n}\n\nexport function getVfsNonDeletedDescendants(ctx: VfsContext, path: string) {\n return ctx.getRelativeChanges(path).filter(meta => !meta.deleted);\n}\n\nexport async function tryReadVfsBackendFile(ctx: VfsContext, path: string) {\n const resolved = ctx.resolve(path);\n\n return (await ctx.backend.isFile(resolved)) ? await ctx.backend.read(resolved) : null;\n}\n\nexport const displayPath = (ctx: VfsContext, path: string) => {\n const prefix =\n ctx.path.length > prefixSize\n ? `${ctx.path.slice(0, prefixSize / 4)}...${ctx.path.slice((-prefixSize * 3) / 4)}`\n : ctx.path;\n\n return `${colors.gray(prefix + sep)}${ctx.relative(path)}`;\n};\n\nconst isDirectDeletedPath = (ctx: VfsContext, path: string) => ctx.get(path)?.deleted;\n/** The directory itself or any of its ancestors is deleted */\nconst isKnownDeletedPath = (ctx: VfsContext, path: string) =>\n isDirectDeletedPath(ctx, path) ||\n ctx\n .relative(path)\n .split('/')\n .filter(path => !path.startsWith('.'))\n .some(path => isDirectDeletedPath(ctx, path));\nconst prefixSize = 28;\n"],"names":["createInMemoryBackend","root","initializer","store","Map","entries","createInMemoryFilesRecord","map","path","content","Buffer","from","deleted","Set","isFile","has","isDir","Array","keys","some","pathStartsBy","deletePath","delete","add","read","get","exists","readDir","uniq","filter","name","split","withTrailingSlash","createInMemoryDirent","join","write","set","dirname","pathStartsWith","__","kind","getStore","getDeleted","file","symlink","isDirectory","isSymbolicLink","endsWith","fullPath","basePath","startsWith","base","result","value","isTypeOfString","Object","assign","existsVfsPath","ctx","meta","log","debug","displayPath","isKnownDeletedPath","getVfsNonDeletedDescendants","getRelativeChanges","length","backend","isVfsFile","isVfsDir","readVfsDir","actualChildren","changes","isNotDeleted","resolve","getDirentName","relative","sep","uniqBy","entry","Boolean","replaceAll","tryReadVfsFile","encoding","toString","readVfsFile","Error","writeVfsFile","actualContent","tryReadVfsBackendFile","ensureVfsPath","parent","unregister","equals","writePathContent","deleteVfsPath","parentDirName","children","renameVfs","to","concurrently","getVfsActions","types","getAllDirectChanges","type","action","isTruthy","includes","compact","resolved","prefix","prefixSize","slice","colors","gray","isDirectDeletedPath"],"mappings":"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"}