{"version":3,"file":"util.mjs","names":["constants","fsConstants","chmod","lstat","open","readdir","readlink","symlink","utimes","join","pathJoin","Writable","pipeline","PathType","O_WRONLY","O_SYMLINK","fsLchmodSupported","fsLutimesSupported","pathNormalize","path","replace","pathResourceFork","statToPathType","stat","isSymbolicLink","SYMLINK","isDirectory","DIRECTORY","isFile","FILE","modeToPathType","mode","bitwiseAndEqual","modePermissionBits","value","mask","streamToBuffer","stream","datas","size","write","data","_encoding","cb","push","length","Buffer","concat","fsLchmod","fd","close","fsUtimes","atime","mtime","fsLutimes","fsReadlinkRaw","fsSymlink","target","fsChmod","fsReaddir","sort","fsLstat","fsLstatExists","err","code","fsWalk","base","itter","options","ignoreUnreadableDirectories","stack","reverse","entry","pop","fullPath","recurse","subs","i"],"sources":["../src/util.ts"],"sourcesContent":["import {Stats, constants as fsConstants} from 'node:fs';\nimport {\n\tchmod,\n\tlstat,\n\topen,\n\treaddir,\n\treadlink,\n\tsymlink,\n\tutimes\n} from 'node:fs/promises';\nimport {join as pathJoin} from 'node:path';\nimport {Readable, Writable} from 'node:stream';\nimport {pipeline} from 'node:stream/promises';\n\nimport {PathType} from './types.ts';\n\nexport interface IFsWalkOptions {\n\t/**\n\t * Ignore unreadable directores when walking directory.\n\t *\n\t * @default false\n\t */\n\tignoreUnreadableDirectories?: boolean;\n}\n\nconst {O_WRONLY, O_SYMLINK} = fsConstants;\nexport const fsLchmodSupported = !!O_SYMLINK;\nexport const fsLutimesSupported = !!O_SYMLINK;\n\n/**\n * Normalize an entry path.\n *\n * @param path Path string.\n * @returns Normalized path.\n */\nexport function pathNormalize(path: string) {\n\treturn path.replace(/\\\\/g, '/').replace(/([^/])\\/+$/, '$1');\n}\n\n/**\n * Get path to the resource fork pseudo-file.\n *\n * @param path Path string.\n * @returns Resource fork pseudo-file path.\n */\nexport function pathResourceFork(path: string) {\n\treturn pathJoin(path, '..namedfork', 'rsrc');\n}\n\n/**\n * Get path type from stat object, or null if unsupported.\n *\n * @param stat Stats object.\n * @returns Path type.\n */\nexport function statToPathType(stat: Readonly<Stats>) {\n\tif (stat.isSymbolicLink()) {\n\t\treturn PathType.SYMLINK;\n\t}\n\tif (stat.isDirectory()) {\n\t\treturn PathType.DIRECTORY;\n\t}\n\tif (stat.isFile()) {\n\t\treturn PathType.FILE;\n\t}\n\treturn null;\n}\n\n/**\n * Get path type from stat mode, or null if unsupported.\n *\n * @param mode Stat mode.\n * @returns Path type.\n */\nexport function modeToPathType(mode: number) {\n\tif (bitwiseAndEqual(mode, 0o0120000)) {\n\t\treturn PathType.SYMLINK;\n\t}\n\tif (bitwiseAndEqual(mode, 0o0040000)) {\n\t\treturn PathType.DIRECTORY;\n\t}\n\tif (bitwiseAndEqual(mode, 0o0100000)) {\n\t\treturn PathType.FILE;\n\t}\n\treturn null;\n}\n\n/**\n * Get permission bits from mode value.\n *\n * @param mode Stat mode.\n * @returns Permission bits.\n */\nexport function modePermissionBits(mode: number) {\n\t// eslint-disable-next-line no-bitwise\n\treturn mode & 0b111111111;\n}\n\n/**\n * Check if all the bits set.\n *\n * @param value Bits value.\n * @param mask Mask value.\n * @returns True of all the bits set.\n */\nexport function bitwiseAndEqual(value: number, mask: number) {\n\t// eslint-disable-next-line no-bitwise\n\treturn (value & mask) === mask;\n}\n\n/**\n * Read a stream into a buffer.\n * Reading a stream into a buffer should be avoided where possible.\n * This is however useful for some small streams.\n *\n * @param stream Readable stream.\n * @returns Full buffer.\n */\nexport async function streamToBuffer(stream: Readable) {\n\tconst datas: Buffer[] = [];\n\tlet size = 0;\n\tawait pipeline(\n\t\tstream,\n\t\tnew Writable({\n\t\t\t// eslint-disable-next-line jsdoc/require-jsdoc\n\t\t\twrite: (data: Buffer, _encoding: unknown, cb) => {\n\t\t\t\tdatas.push(data);\n\t\t\t\tsize += data.length;\n\t\t\t\tcb();\n\t\t\t}\n\t\t})\n\t);\n\treturn Buffer.concat(datas, size);\n}\n\n/**\n * Wrapper for lchmod, does nothing on unsupported platforms.\n *\n * @param path File path.\n * @param mode File mode.\n */\nexport async function fsLchmod(path: string, mode: number) {\n\t// Skip if not supported.\n\tif (!fsLchmodSupported) {\n\t\treturn;\n\t}\n\n\t// eslint-disable-next-line no-bitwise\n\tconst fd = await open(path, O_WRONLY | O_SYMLINK);\n\ttry {\n\t\tawait fd.chmod(mode);\n\t} finally {\n\t\tawait fd.close();\n\t}\n}\n\n/**\n * Wrapper for utimes.\n *\n * @param path File path.\n * @param atime Access time.\n * @param mtime Modification time.\n */\nexport async function fsUtimes(\n\tpath: string,\n\tatime: Readonly<Date>,\n\tmtime: Readonly<Date>\n) {\n\tawait utimes(path, atime, mtime);\n}\n\n/**\n * Implementation of lutimes, does nothing on unsupported platforms.\n *\n * @param path File path.\n * @param atime Access time.\n * @param mtime Modification time.\n */\nexport async function fsLutimes(\n\tpath: string,\n\tatime: Readonly<Date>,\n\tmtime: Readonly<Date>\n) {\n\t// Skip if not supported.\n\tif (!fsLutimesSupported) {\n\t\treturn;\n\t}\n\n\t// eslint-disable-next-line no-bitwise\n\tconst fd = await open(path, O_WRONLY | O_SYMLINK);\n\ttry {\n\t\tawait fd.utimes(atime, mtime);\n\t} finally {\n\t\tawait fd.close();\n\t}\n}\n\n/**\n * A readlink wrapper that returns raw link buffer.\n *\n * @param path Link path.\n * @returns Raw link.\n */\nexport async function fsReadlinkRaw(path: string) {\n\treturn readlink(path, 'buffer');\n}\n\n/**\n * Wrapper for symlink.\n *\n * @param path Path of symbolic link.\n * @param target Target of symbolic link.\n */\nexport async function fsSymlink(\n\tpath: string | Readonly<Buffer>,\n\ttarget: string | Readonly<Buffer>\n) {\n\tawait symlink(target, path);\n}\n\n/**\n * Wrapper for chmod.\n *\n * @param path File path.\n * @param mode File mode.\n */\nexport async function fsChmod(path: string, mode: number) {\n\tawait chmod(path, mode);\n}\n\n/**\n * A readdir wrapper with consistent output.\n *\n * @param path Directory path.\n * @returns Directory listing.\n */\nexport async function fsReaddir(path: string) {\n\treturn (await readdir(path)).sort();\n}\n\n/**\n * An lstat wrapper.\n *\n * @param path Path string.\n * @returns Stat object.\n */\nexport async function fsLstat(path: string) {\n\treturn lstat(path);\n}\n\n/**\n * An lstat wrapper returning null if not exist.\n *\n * @param path Path string.\n * @returns Stat object.\n */\nexport async function fsLstatExists(path: string) {\n\ttry {\n\t\treturn await fsLstat(path);\n\t} catch (err) {\n\t\tconst {code} = err as {code: string};\n\t\tif (code === 'ENOENT' || code === 'ENOTDIR') {\n\t\t\treturn null;\n\t\t}\n\t\tthrow err;\n\t}\n}\n\n/**\n * Walk file system path.\n * If callback returns false skips recursing a directory.\n * If callback returns null aborts walking.\n *\n * @param base Directory path.\n * @param itter Callback for each entry.\n * @param options Walk options.\n */\nexport async function fsWalk(\n\tbase: string,\n\titter: (path: string, stat: Stats) => Promise<boolean | null | void>,\n\toptions: Readonly<IFsWalkOptions> = {}\n) {\n\tconst {ignoreUnreadableDirectories} = options;\n\tconst stack = (await fsReaddir(base)).reverse();\n\twhile (stack.length) {\n\t\tconst entry = stack.pop() as string;\n\t\tconst fullPath = pathJoin(base, entry);\n\t\t// eslint-disable-next-line no-await-in-loop\n\t\tconst stat = await fsLstat(fullPath);\n\n\t\t// Callback, possibly stop recursion on directory.\n\t\t// eslint-disable-next-line no-await-in-loop\n\t\tconst recurse = await itter(entry, stat);\n\t\tif (recurse === null) {\n\t\t\tbreak;\n\t\t}\n\t\tif (recurse === false || !stat.isDirectory()) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Recurse down.\n\t\tlet subs: string[] = [];\n\t\ttry {\n\t\t\t// eslint-disable-next-line no-await-in-loop\n\t\t\tsubs = await fsReaddir(fullPath);\n\t\t} catch (err) {\n\t\t\tif (\n\t\t\t\t!(\n\t\t\t\t\terr &&\n\t\t\t\t\tignoreUnreadableDirectories &&\n\t\t\t\t\t(err as {code: string}).code === 'EACCES'\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t}\n\t\tfor (let i = subs.length; i--; ) {\n\t\t\tstack.push(pathJoin(entry, subs[i]));\n\t\t}\n\t}\n}\n"],"mappings":"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","ignoreList":[]}