{"version":3,"file":"fs.mjs","sourceRoot":"","sources":["../src/fs.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Json } from '@metamask/utils';\nimport { promises as fs } from 'fs';\nimport { mkdtemp } from 'fs/promises';\nimport os from 'os';\nimport pathUtils from 'path';\n\nimport { parseJson } from './json';\nimport type { VirtualFile } from './virtual-file';\nimport { readVirtualFile } from './virtual-file/node';\n\n/**\n * Checks whether the given path string resolves to an existing directory, and\n * optionally creates the directory if it doesn't exist.\n *\n * @param pathString - The path string to check.\n * @param createDir - Whether to create the directory if it doesn't exist.\n * @returns Whether the given path is an existing directory.\n */\nexport async function isDirectory(\n  pathString: string,\n  createDir: boolean,\n): Promise<boolean> {\n  try {\n    const stats = await fs.stat(pathString);\n    return stats.isDirectory();\n  } catch (error) {\n    if (error.code === 'ENOENT') {\n      if (!createDir) {\n        return false;\n      }\n\n      await fs.mkdir(pathString, { recursive: true });\n      return true;\n    }\n\n    return false;\n  }\n}\n\n/**\n * Checks whether the given path string resolves to an existing file.\n *\n * @param pathString - The path string to check.\n * @returns Whether the given path is an existing file.\n */\nexport async function isFile(pathString: string): Promise<boolean> {\n  try {\n    const stats = await fs.stat(pathString);\n    return stats.isFile();\n  } catch {\n    return false;\n  }\n}\n\n/**\n * Reads a `.json` file, parses its contents, and returns them.\n *\n * @param pathString - The path to the JSON file.\n * @returns The parsed contents of the JSON file.\n */\nexport async function readJsonFile<Type extends Json = Json>(\n  pathString: string,\n): Promise<VirtualFile<Type>> {\n  if (!pathString.endsWith('.json')) {\n    throw new Error('The specified file must be a \".json\" file.');\n  }\n\n  let file;\n  try {\n    file = await readVirtualFile(pathString, 'utf8');\n  } catch (error) {\n    if (error.code === 'ENOENT') {\n      throw new Error(\n        `Could not find '${pathString}'. Please ensure that the file exists.`,\n      );\n    }\n\n    throw error;\n  }\n  file.result = parseJson(file.toString());\n  return file as VirtualFile<Type>;\n}\n\n/**\n * Gets the complete out file path from an output file name and parent\n * directory path.\n *\n * @param outDir - The path to the out file's parent directory.\n * @param outFileName - The out file's name.\n * @returns The complete path to the out file.\n */\nexport function getOutfilePath(outDir: string, outFileName: string): string {\n  return pathUtils.join(outDir, outFileName || 'bundle.js');\n}\n\n/**\n * Ensures that the outfile name is just a `.js` file name.\n * Throws on validation failure.\n *\n * @param filename - The file name to validate.\n * @returns `true` if validation succeeded.\n * @throws If the file name is invalid.\n */\nexport function validateOutfileName(filename: string): boolean {\n  if (\n    !filename.endsWith('.js') ||\n    filename === '.js' ||\n    pathUtils.basename(filename) !== filename\n  ) {\n    throw new Error(`Invalid outfile name: ${filename}. Must be a .js file`);\n  }\n  return true;\n}\n\n/**\n * Validates a file path. Throws on validation failure.\n *\n * @param filePath - The file path to validate.\n * @returns `true` if validation succeeded.\n * @throws If the path does not resolve to a file.\n */\nexport async function validateFilePath(filePath: string): Promise<boolean> {\n  const exists = await isFile(filePath);\n  if (!exists) {\n    throw new Error(\n      `Invalid params: '${filePath}' is not a file or does not exist.`,\n    );\n  }\n  return true;\n}\n\n/**\n * Validates a directory path. Throws on validation failure.\n *\n * @param dirPath - The directory path to validate.\n * @param createDir - Whether to create the directory if it doesn't exist.\n * @returns `true` if validation succeeded or the directory was created.\n * @throws If the directory does not exist or could not be created.\n */\nexport async function validateDirPath(\n  dirPath: string,\n  createDir: boolean,\n): Promise<boolean> {\n  const exists = await isDirectory(dirPath, createDir);\n  if (!exists) {\n    throw new Error(\n      `Invalid params: '${dirPath}' is not a directory or could not be created.`,\n    );\n  }\n  return true;\n}\n\n/**\n * Create a temporary file with a given name and content, writes it to disk and\n * calls the provided function. This function handles deletion of the temporary\n * file after usage.\n *\n * @param fileName - The name of the temporary file.\n * @param fileContents - The content of the temporary file.\n * @param fn - The callback function to call when the temporary file has been\n * created.\n * @returns The result of the callback function.\n */\nexport async function useTemporaryFile<Type = unknown>(\n  fileName: string,\n  fileContents: string,\n  fn: (path: string) => Promise<Type>,\n): Promise<Type> {\n  const temporaryDirectory = await mkdtemp(\n    pathUtils.join(os.tmpdir(), 'snaps-'),\n  );\n\n  const filePath = pathUtils.join(temporaryDirectory, fileName);\n\n  await fs.mkdir(pathUtils.dirname(filePath), { recursive: true });\n  await fs.writeFile(filePath, fileContents);\n  try {\n    return await fn(filePath);\n  } finally {\n    if (await isFile(filePath)) {\n      await fs.unlink(filePath);\n    }\n  }\n}\n\n/**\n * Use the file system to cache a return value with a given key and TTL.\n *\n * @param cacheKey - The key to use for the cache.\n * @param ttl - The time-to-live in milliseconds.\n * @param fn - The callback function to wrap.\n * @returns The result from the callback.\n */\nexport function useFileSystemCache<Type = unknown>(\n  cacheKey: string,\n  ttl: number,\n  fn: () => Promise<Type>,\n) {\n  return async () => {\n    const filePath = pathUtils.join(\n      process.cwd(),\n      'node_modules/.cache/snaps',\n      `${cacheKey}.json`,\n    );\n\n    try {\n      const cacheContents = await fs.readFile(filePath, 'utf8');\n      const json = JSON.parse(cacheContents);\n\n      if (json.timestamp + ttl > Date.now()) {\n        return json.value;\n      }\n    } catch {\n      // No-op\n    }\n\n    const value = await fn();\n\n    // Null or undefined is not persisted.\n    if (value === null || value === undefined) {\n      return value;\n    }\n\n    try {\n      await fs.mkdir(pathUtils.dirname(filePath), { recursive: true });\n\n      const json = { timestamp: Date.now(), value };\n      await fs.writeFile(filePath, JSON.stringify(json), {\n        encoding: 'utf8',\n      });\n    } catch {\n      // No-op\n    }\n\n    return value;\n  };\n}\n"]}