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 ''
}
}