{"version":3,"file":"read-dir.cjs","sources":["../src/utils/constants.ts","../src/utils/helpers/config.ts","../src/utils/helpers/strings.ts","../src/read-dir.ts"],"sourcesContent":["import type { ReadDirOptions } from '../types';\n\nexport const DEFAULT_OPTIONS = {\n  depth: undefined,\n  extensions: undefined,\n  includeFileContents: false,\n} as const satisfies ReadDirOptions;\n","import type { Maybe } from '@cretadoc/utils';\nimport type { ReadDirOptions } from '../../types';\nimport { DEFAULT_OPTIONS } from '../constants';\n\n/**\n * Merge the user options with the default options.\n *\n * @param {Maybe<Partial<ReadDirOptions>>} options - The user options.\n * @returns {Readonly<ReadDirOptions>}\n */\nexport const mergeOptionsWithDefault = (\n  options: Maybe<Partial<ReadDirOptions>>\n): Readonly<ReadDirOptions> => {\n  if (!options) return DEFAULT_OPTIONS;\n\n  return Object.freeze({ ...DEFAULT_OPTIONS, ...options });\n};\n","/**\n * Transform a path to a buffer.\n *\n * @param {string} path - A path.\n * @returns {string} An id.\n */\nexport const generateIdFrom = (path: string): string =>\n  Buffer.from(path).toString('base64');\n","import { readdir, readFile, stat } from 'node:fs/promises';\nimport { basename, join, parse } from 'node:path';\nimport { type Maybe, removeUndefined } from '@cretadoc/utils';\nimport type {\n  Dates,\n  Directory,\n  DirectoryContents,\n  Extension,\n  ReadDirOptions,\n  RegularFile,\n} from './types';\nimport { generateIdFrom, mergeOptionsWithDefault } from './utils/helpers';\n\n/**\n * Retrieve the creation date and the update date of a path.\n *\n * @param {string} path - The absolute path of a file.\n * @returns {Promise<Dates>} The creation date and the update date.\n */\nconst getDatesFrom = async (path: string): Promise<Dates> => {\n  const { birthtime, mtime } = await stat(path);\n\n  return {\n    createdAt: birthtime.toISOString(),\n    updatedAt: mtime.toISOString(),\n  };\n};\n\ntype CommonData = Pick<\n  Directory | RegularFile,\n  'createdAt' | 'id' | 'path' | 'updatedAt'\n>;\n\n/**\n * Retrieve the data shared by directories and files.\n * @param {string} path - A directory or file path.\n * @returns {Promise<CommonData>} The common data.\n */\nconst getCommonData = async (path: string): Promise<CommonData> => {\n  const { createdAt, updatedAt } = await getDatesFrom(path);\n\n  return {\n    createdAt,\n    id: generateIdFrom(path),\n    path,\n    updatedAt,\n  };\n};\n\n/**\n * Retrieve a RegularFile object.\n *\n * @param {string} path - The file path.\n * @param {Omit<Readonly<ReadDirOptions>, 'depth'>} options - The options.\n * @returns {Promise<Maybe<RegularFile>>} The file data.\n */\nconst getRegularFile = async (\n  path: string,\n  { extensions, includeFileContents }: Omit<Readonly<ReadDirOptions>, 'depth'>\n): Promise<Maybe<RegularFile>> => {\n  const commonData = await getCommonData(path);\n  const { ext, name } = parse(path);\n  const extension = ext as Extension;\n  const isValidExtension = extensions ? extensions.includes(extension) : true;\n\n  if (!isValidExtension) return undefined;\n\n  const contents = includeFileContents\n    ? await readFile(path, 'utf8')\n    : undefined;\n\n  return {\n    ...commonData,\n    contents,\n    extension,\n    name,\n    type: 'file',\n  };\n};\n\n/**\n * Retrieve an array of directories and regular files.\n *\n * @param {string} path - The directory path\n * @param {Readonly<ReadDirOptions>} options - The options\n * @returns {Promise<Array<Directory | RegularFile>>} The directories and files.\n */\nconst getDirAndFilesIn = async (\n  path: string,\n  options: Readonly<ReadDirOptions>\n): Promise<Array<Directory | RegularFile>> => {\n  const dirEntries = await readdir(path, {\n    encoding: 'utf8',\n    withFileTypes: true,\n  });\n\n  const promises = dirEntries.map(async (entry) => {\n    const fullPath = join(path, entry.name);\n\n    /* eslint-disable-next-line @typescript-eslint/no-use-before-define -- The\n    circular reference is needed to avoid repeats. */\n    if (entry.isDirectory()) return getDirectory(fullPath, options);\n    if (entry.isFile()) return getRegularFile(fullPath, options);\n    return undefined;\n  });\n\n  const awaitedPromises = await Promise.all(promises);\n\n  return awaitedPromises.filter(removeUndefined);\n};\n\n/**\n * Method to filter an array and remove Directory objects.\n *\n * @param {Directory | RegularFile} dirOrFile - A Directory or RegularFile obj.\n * @returns {boolean} True if it is a RegularFile.\n */\nconst removeDirectories = (\n  dirOrFile: Directory | RegularFile\n): dirOrFile is RegularFile => {\n  if (dirOrFile.type === 'directory') return false;\n  return true;\n};\n\n/**\n * Method to filter an array and remove RegularFile objects.\n *\n * @param {Directory | RegularFile} dirOrFile - A Directory or RegularFile obj.\n * @returns {boolean} True if it is a Directory.\n */\nconst removeRegularFiles = (\n  dirOrFile: Directory | RegularFile\n): dirOrFile is Directory => {\n  if (dirOrFile.type === 'file') return false;\n  return true;\n};\n\n/**\n * Retrieve all the contents from a directory.\n *\n * @param {string} path - The directory path.\n * @param {Readonly<ReadDirOptions>} options - The options.\n * @returns {Promise<Maybe<DirectoryContents>>} The directory contents.\n */\nconst getDirContents = async (\n  path: string,\n  { depth, ...options }: Readonly<ReadDirOptions>\n): Promise<Maybe<DirectoryContents>> => {\n  const depthLimit = 0;\n  const dirContents =\n    !depth || depth > depthLimit\n      ? await getDirAndFilesIn(path, { depth, ...options })\n      : undefined;\n\n  if (!dirContents) return undefined;\n\n  return {\n    directories: dirContents.filter(removeRegularFiles),\n    files: dirContents.filter(removeDirectories),\n  };\n};\n\n/**\n * Retrieve a Directory object.\n *\n * @param {string} path - The directory path.\n * @param {Readonly<ReadDirOptions>} options - The options.\n * @returns {Promise<Directory>} The directory data.\n */\nconst getDirectory = async (\n  path: string,\n  { depth, ...options }: Readonly<ReadDirOptions>\n): Promise<Directory> => {\n  const commonData = await getCommonData(path);\n  const depthCount = 1;\n  const updatedDepth = depth === undefined ? undefined : depth - depthCount;\n  const contents = await getDirContents(path, {\n    depth: updatedDepth,\n    ...options,\n  });\n\n  return {\n    ...commonData,\n    contents,\n    name: basename(path),\n    type: 'directory',\n  };\n};\n\n/**\n * Walk through a directory.\n *\n * @param {string} path - The directory path.\n * @param {Partial<ReadDirOptions>} [options] - The options.\n * @returns {Promise<Directory>} The directory data.\n */\nexport const readDir = async (\n  path: string,\n  options?: Partial<ReadDirOptions>\n): Promise<Directory> => {\n  const mergedOptions = mergeOptionsWithDefault(options);\n\n  return getDirectory(path, mergedOptions);\n};\n\nexport type {\n  Directory,\n  DirectoryContents,\n  Extension,\n  ReadDirOptions,\n  RegularFile,\n} from './types';\n"],"names":["DEFAULT_OPTIONS","mergeOptionsWithDefault","options","generateIdFrom","path","getDatesFrom","birthtime","mtime","stat","getCommonData","createdAt","updatedAt","getRegularFile","extensions","includeFileContents","commonData","ext","name","parse","extension","contents","readFile","getDirAndFilesIn","promises","readdir","entry","fullPath","join","getDirectory","removeUndefined","removeDirectories","dirOrFile","removeRegularFiles","getDirContents","depth","dirContents","updatedDepth","basename","readDir","mergedOptions"],"mappings":"mGAEO,MAAMA,EAAkB,CAC7B,MAAO,OACP,WAAY,OACZ,oBAAqB,EACvB,ECIaC,EACXC,GAEKA,EAEE,OAAO,OAAO,CAAE,GAAGF,EAAiB,GAAGE,CAAQ,CAAC,EAFlCF,ECPVG,EAAkBC,GAC7B,OAAO,KAAKA,CAAI,EAAE,SAAS,QAAQ,ECY/BC,EAAe,MAAOD,GAAiC,CAC3D,KAAM,CAAE,UAAAE,EAAW,MAAAC,CAAM,EAAI,MAAMC,EAAAA,KAAKJ,CAAI,EAE5C,MAAO,CACL,UAAWE,EAAU,YAAY,EACjC,UAAWC,EAAM,YACnB,CAAA,CACF,EAYME,EAAgB,MAAOL,GAAsC,CACjE,KAAM,CAAE,UAAAM,EAAW,UAAAC,CAAU,EAAI,MAAMN,EAAaD,CAAI,EAExD,MAAO,CACL,UAAAM,EACA,GAAIP,EAAeC,CAAI,EACvB,KAAAA,EACA,UAAAO,CACF,CACF,EASMC,EAAiB,MACrBR,EACA,CAAE,WAAAS,EAAY,oBAAAC,CAAoB,IACF,CAChC,MAAMC,EAAa,MAAMN,EAAcL,CAAI,EACrC,CAAE,IAAAY,EAAK,KAAAC,CAAK,EAAIC,QAAMd,CAAI,EAC1Be,EAAYH,EAGlB,GAAI,EAFqBH,CAAAA,GAAaA,EAAW,SAASM,CAAS,GAE5C,OAEvB,MAAMC,EAAWN,EACb,MAAMO,EAASjB,SAAAA,EAAM,MAAM,EAC3B,OAEJ,MAAO,CACL,GAAGW,EACH,SAAAK,EACA,UAAAD,EACA,KAAAF,EACA,KAAM,MACR,CACF,EASMK,EAAmB,MACvBlB,EACAF,IAC4C,CAM5C,MAAMqB,GALa,MAAMC,UAAQpB,EAAM,CACrC,SAAU,OACV,cAAe,EACjB,CAAC,GAE2B,IAAI,MAAOqB,GAAU,CAC/C,MAAMC,EAAWC,EAAAA,KAAKvB,EAAMqB,EAAM,IAAI,EAItC,GAAIA,EAAM,YAAY,EAAG,OAAOG,EAAaF,EAAUxB,CAAO,EAC9D,GAAIuB,EAAM,OAAA,EAAU,OAAOb,EAAec,EAAUxB,CAAO,CAE7D,CAAC,EAID,OAFwB,MAAM,QAAQ,IAAIqB,CAAQ,GAE3B,OAAOM,EAAe,eAAA,CAC/C,EAQMC,EACJC,GAEIA,EAAU,OAAS,YAUnBC,EACJD,GAEIA,EAAU,OAAS,OAWnBE,EAAiB,MACrB7B,EACA,CAAE,MAAA8B,EAAO,GAAGhC,CAAQ,IACkB,CAEtC,MAAMiC,EACJ,CAACD,GAASA,EAAQ,EACd,MAAMZ,EAAiBlB,EAAM,CAAE,MAAA8B,EAAO,GAAGhC,CAAQ,CAAC,EAClD,OAEN,GAAKiC,EAEL,MAAO,CACL,YAAaA,EAAY,OAAOH,CAAkB,EAClD,MAAOG,EAAY,OAAOL,CAAiB,CAC7C,CACF,EASMF,EAAe,MACnBxB,EACA,CAAE,MAAA8B,EAAO,GAAGhC,CAAQ,IACG,CACvB,MAAMa,EAAa,MAAMN,EAAcL,CAAI,EAErCgC,EAAeF,IAAU,OAAY,OAAYA,EADpC,EAEbd,EAAW,MAAMa,EAAe7B,EAAM,CAC1C,MAAOgC,EACP,GAAGlC,CACL,CAAC,EAED,MAAO,CACL,GAAGa,EACH,SAAAK,EACA,KAAMiB,EAAAA,SAASjC,CAAI,EACnB,KAAM,WACR,CACF,EASakC,EAAU,MACrBlC,EACAF,IACuB,CACvB,MAAMqC,EAAgBtC,EAAwBC,CAAO,EAErD,OAAO0B,EAAaxB,EAAMmC,CAAa,CACzC"}