Building a folder structure tree recursively with typescript and reduce
Recenlty i was working on a new CLI tool for my company, where we would have to work a lot with file system and files manipulation. For one of the tasks i needed to have a method that would generate me a directory structure in JSON format with all child directories and files listed. Now, i have to admit, that I still have struggles with reduce methods, but here it was exactly what i needed and , to be honest, I'm a bit proud of the solution i managed to get. My small personal victory. I'm writing it here, so that future me could use this and also I really hope that it will help others, who face with this problem as well. Here's what the method looks like :
import fs, { readdirSync, statSync } from 'fs'
import { dirname, resolve } from 'path'
export type GenericObject = Record<string, unknown>
export const getListOfFilesInDirectory = (dirPath: string): string[] => {
return readdirSync(dirPath).filter((entry) => statSync(resolve(dirPath, entry)).isFile())
}
export const getListOfDirectoriesInDirectory = (dirPath: string): string[] => {
return readdirSync(dirPath).filter((entry) => statSync(resolve(dirPath, entry)).isDirectory())
}
export const describeDirStructure = (dirPath: string): GenericObject => {
return readdirSync(dirPath).reduce((acc: GenericObject, currentPointer: string) => {
if (statSync(resolve(dirPath, currentPointer)).isDirectory()) {
const files: string[] = getListOfFilesInDirectory(resolve(dirPath, currentPointer))
const dirs: string[] = getListOfDirectoriesInDirectory(resolve(dirPath, currentPointer))
if (files.length > 0 && dirs.length > 0) {
const innerStructure = {
[currentPointer]: {
files,
...describeDirStructure(resolve(dirPath, currentPointer)),
},
}
acc = {
...acc,
...innerStructure,
}
return acc
}
if (dirs.length === 0 && files.length > 0) {
acc = {
...acc,
...{ [currentPointer]: files },
}
} else {
acc = {
...acc,
...{ [currentPointer]: describeDirStructure(resolve(dirPath, currentPointer)) },
}
}
}
return acc
}, {})
}
In order to verify this, i made a simple directory example that looks like this :
└── list-directory-example
└── demo
├── service-data
│ ├── service-details.json
│ └── transactions
│ └── transactions.json
└── user-data
├── billing.json
└── personal-information.json
And the unit test is also quite simple :
test('🟢 I can get a full list of all files in all directories recursively', () => {
const result = describeDirStructure(
resolve('./src/utils/__tests__/fixtures', 'list-directory-example')
)
expect(result).toEqual({
demo: {
'service-data': {
files: ['service-details.json'],
transactions: ['transactions.json'],
},
'user-data': ['billing.json', 'personal-information.json'],
},
})
})
I really hope that this will be helpful not only for me, but for others as well.
Happy coding everyone ! ☺️