import { constants } from 'fs' import { join } from 'node:path' import { access, readFile, readdir } from 'fs/promises' import type { Items, Item, Tree } from './type' export const PIJUL_DIR = '.pijul' export function getExtension(name: string): string | null { const splitted = name.split('.') if (splitted.length < 2) { return null } else { return splitted.at(-1) ?? null } } export function getParent(path: string): string { return path.split('/').at(-1) as string } export const cmpItems = (a: Item, b: Item): 0 | 1 | -1 => a.depth > b.depth ? 1 : a.depth < b.depth ? -1 : a.isDir && !b.isDir ? -1 : !a.isDir && b.isDir ? 1 : ((s1: string, s2: string) => (s1 === s2 ? 0 : s1 > s2 ? 1 : -1))( a.name, b.name ) export const toItems = async (path = 'repo', depth = 1): Promise<Items> => { const tree: Items = [] const fileCollector = async (tree: Items, path: string, depth: number) => { const entries = await readdir(path, { withFileTypes: true }) return entries .filter((dirent) => dirent.name !== PIJUL_DIR) .map(async (dirent) => { const item = { isDir: !!dirent.isDirectory(), extension: getExtension(dirent.name), name: dirent.name, path: join(path, dirent.name), depth, } tree.push({ ...item, id: tree.length + 1 }) if (dirent.isDirectory()) { await fileCollector(tree, join(path, dirent.name), depth + 1) } }) } try { await Promise.all(await fileCollector(tree, path, depth)) } catch (error) { console.error(error) } finally { // eslint-disable-next-line no-unsafe-finally return tree } } export const toTree = (data: Items, depth = 1): Tree => { const insertChildren = (data: Item[], depth: number) => data .filter((item) => item.depth === depth) .map((item) => ({ id: item.id, name: item.name, path: item.path, ...(item.isDir ? { children: insertChildren( data.filter((item) => item.depth > depth), depth + 1 ), } : null), })) return { id: 0, name: 'root', children: insertChildren(data, depth), } } export async function isFile(path: string) { try { await access(path, constants.F_OK | constants.R_OK) return true } catch (error) { return false } } export async function getContent(path: string) { const isFileExist = await isFile(path) if (!isFileExist) { console.error(`The file located at ${path} do not exist`) return '' } try { const buffer = await readFile(path) return buffer.toString() } catch (error) { console.error(error) return '' } }