From 7a3ba158dad0eb6bd5c68fe8b2ad2eef752a9aac Mon Sep 17 00:00:00 2001 From: Mirasaki Date: Sat, 8 Jun 2024 18:51:35 +0200 Subject: [PATCH 1/2] fix: use async file operations --- src/modules/json-database/controller.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/modules/json-database/controller.ts b/src/modules/json-database/controller.ts index f6b6d56..f6b271a 100644 --- a/src/modules/json-database/controller.ts +++ b/src/modules/json-database/controller.ts @@ -17,7 +17,7 @@ export const getAllJSONDataController = async ( } // Resolve data - const allJSONData = getAllJSONFiles(cfg.DIRECTORY); + const allJSONData = await getAllJSONFiles(cfg.DIRECTORY); // Don't handle error (empty), // provide empty array for null fallback @@ -41,7 +41,7 @@ export const getJSONDataController = async ( // Resolve data const { identifier } = req.params; - const jsonData = getJSONFile(cfg.DIRECTORY, identifier); + const jsonData = await getJSONFile(cfg.DIRECTORY, identifier); // Handle errors if (jsonData === null) { @@ -68,7 +68,7 @@ export const deleteJsonDataController = async ( // Resolve data const { identifier } = req.params; - const jsonData = getJSONFile(cfg.DIRECTORY, identifier); + const jsonData = await getJSONFile(cfg.DIRECTORY, identifier); // Handle errors if (jsonData === null) { @@ -77,7 +77,7 @@ export const deleteJsonDataController = async ( } // Delete the file/data - deleteJSONFile(cfg.DIRECTORY, identifier); + await deleteJSONFile(cfg.DIRECTORY, identifier); // Ok, send the response res.json({ data: jsonData }); @@ -99,7 +99,7 @@ export const putJSONDataController = async ( // Resolve data const { identifier } = req.params; const newJSONContent = req.body; - const response = putJSONFile(cfg.DIRECTORY, identifier, newJSONContent); + const response = await putJSONFile(cfg.DIRECTORY, identifier, newJSONContent); // Handle errors - target to overwrite doesn't exist if (response === null) { @@ -127,7 +127,7 @@ export const patchJSONDataController = async ( // Resolve data const { identifier } = req.params; const updatedJSONFields = req.body; - const jsonData = getJSONFile(cfg.DIRECTORY, identifier); + const jsonData = await getJSONFile(cfg.DIRECTORY, identifier); if (!jsonData) { next(resourceNotFound(`JSON_DATABASE(${name})-${identifier}`)); return; @@ -139,7 +139,7 @@ export const patchJSONDataController = async ( } // Reflect in file - can't 404 - putJSONFile(cfg.DIRECTORY, identifier, jsonData); + await putJSONFile(cfg.DIRECTORY, identifier, jsonData); // Ok, send the response res.json({ data: jsonData }); From d6e409ab9d91a171fcf1c451be9a368b4de0c925 Mon Sep 17 00:00:00 2001 From: Mirasaki Date: Sat, 8 Jun 2024 18:52:42 +0200 Subject: [PATCH 2/2] feat: improved async file operation error handling --- src/modules/json-database/helper.ts | 35 ++++++++++++++++------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/modules/json-database/helper.ts b/src/modules/json-database/helper.ts index 7eef5f1..88c660d 100644 --- a/src/modules/json-database/helper.ts +++ b/src/modules/json-database/helper.ts @@ -1,40 +1,42 @@ -import { readFileSync, writeFileSync, rmSync } from 'fs'; import { getFiles } from '../files'; import { debugLog } from '../../debug'; +import { rm, writeFile, readFile } from 'fs/promises'; -export const getAllJSONFiles = (targetPath: string) => { +export const getAllJSONFiles = async (targetPath: string) => { const allJSONFiles = getFiles(targetPath, [ '.json' ]); debugLog(`Found ${allJSONFiles.length} JSON files in ${targetPath}`); - return allJSONFiles - .map((pathToJSON) => { - const textData = readFileSync(pathToJSON, { encoding: 'utf-8' }); + return (await Promise.all( + allJSONFiles.map(async (pathToJSON) => { + const textData = await readFile(pathToJSON, { encoding: 'utf-8' }); try { return JSON.parse(textData); } - catch { + catch (err) { + console.error(`Error parsing JSON file at ${pathToJSON}`, err); // Either invalid syntax in JSON or not a file // full path is shown in those errors, avoid return null; } }) - .filter((e) => !!e); // Keep only truthy + )).filter((e) => !!e); // Keep only truthy }; -export const getJSONFile = (targetPath: string, identifier: string) => { +export const getJSONFile = async (targetPath: string, identifier: string) => { const finalPath = targetPath + `/${ identifier }.json`; debugLog(`Attempting to get JSON file from ${finalPath}`); try { - const textData = readFileSync(finalPath, { encoding: 'utf-8' }); + const textData = await readFile(finalPath, { encoding: 'utf-8' }); return JSON.parse(textData); } catch (err) { + console.error(`Error reading JSON file from ${finalPath}`, err); // Either invalid syntax in JSON or not a file // full path is shown in those errors, avoid return null; } }; -export const putJSONFile = ( +export const putJSONFile = async ( targetPath: string, identifier: string, newJSONContent: unknown @@ -42,26 +44,29 @@ export const putJSONFile = ( const finalPath = targetPath + `/${ identifier }.json`; debugLog(`Attempting to put JSON file to ${finalPath}`); try { - writeFileSync( + await writeFile( finalPath, JSON.stringify(newJSONContent, null, 2), - { encoding: 'utf-8' } + { encoding: 'utf-8'} ); return true; } - catch { + catch (err) { + console.error(`Error writing JSON file to ${finalPath}`, err); // Either invalid syntax in JSON or not a file // full path is shown in those errors, avoid return null; } }; -export const deleteJSONFile = (targetPath: string, identifier: string) => { +export const deleteJSONFile = async (targetPath: string, identifier: string) => { const finalPath = targetPath + `/${ identifier }.json`; + debugLog(`Attempting to delete JSON file at ${finalPath}`); try { - rmSync(finalPath, { recursive: false, force: false }); + await rm(finalPath, { recursive: false, force: false }); } catch (err) { + console.error(`Error deleting JSON file at ${finalPath}`, err); // Either invalid syntax in JSON or not a file // full path is shown in those errors, avoid return null;