Когда я работаю с файлами в Node.js, меня не оставляет мысль, что я пишу очень много однотипного кода. Создание, чтение и запись, перемещение, удаление, обход файлов и подкаталогов, всё это обрастает неимоверным количеством бойлерплейта, который еще усугубляется странными названиями функций модуля fs. Со всем этим можно жить, но меня не оставляла мысль, что можно сделать удобнее. Хотелось, чтобы такие элементарные вещи, как, например, чтение или запись текста (или json) в файл можно было написать в одну строчку.  Как итог этих размышлений, появилась библиотека FSTB, в которой я попытался улучшить способы взаимодействия с файловой системой. Решить, получилось у меня или нет вы сможете сами, прочитав эту статью и попробовав библиотеку в деле.  Работа с файлами в ноде проходит в несколько этапов: отрицание, гнев, торг... сначала мы получаем каким-либо образом путь к объекту файловой системы, потом проверяем его существование (при необходимости), потом работаем с ним. Работа с путями в ноде вообще вынесена в отдельный модуль. Самая классная функция для работы с путями, это path.join. Реально крутая штука, которая, когда я стал ей пользоваться, сэкономила мне кучу нервных клеток.  Но с путями есть проблема. Путь - это строка, хотя при этом он по сути описывает местоположение объекта иерархической структуре. А раз уж мы имеем дело с объектом, почему бы для работы с ним не использовать такие же механизмы, как при работе с обычными объектами яваскрипта.  Главная проблема, это то, что объект файловой системы может иметь любое имя из разрешённых символов. Если, я сделаю у этого объекта методы для работы с ним, то получится, что, например, такой код: root.home.mydir.unlink будет двусмысленным - а что, если у в директории mydir есть директория unlink? И что тогда? Я хочу удалить mydir или обратиться к unlink? Однажды я экспериментировал с яваскриптовым Proxу и придумал интересную конструкцию: Здесь FSPath– это функция, которая принимает на вход строку, содержащую в себе путь к файлу, и возвращающая новую функцию, замыкающую в себе этот путь и обернутая в Proxy, который перехватывает все обращения к свойствам получившейся функции и возвращает новую функцию FSPath, с присоединенным именем свойства в качестве сегмента. На первый взгляд выглядит странно, но оказалось, что на практике такая конструкция позволяет собирать пути интересным способом: Как результат, получаем функцию, которая при вызове возвращает сформированный путь. Например: Опять же, и что такого, обычные фокусы JS. Но тут я подумал – можно ведь возвращать не просто путь, а объект, у которого имеются все необходимые методы для работы с файлами и директориями: Так и появилась библиотека FSTB – расшифровывается как FileSystem ToolBox. Установим FSTB: И подключим в проект: Для формирования пути к файлу можно воспользоваться функцией FSPath, либо использовать одно из сокращений: cwd, dirname, homeили tmp(подробнее про них смотрите в документации). Также пути можно подтягивать из переменных окружения при помощи метода envPath. Чтение текста из файла: FSTB работает на промисах, так что можно использовать в коде async/await: Здесь мы десериализуем json из файла. На мой взгляд неплохо, мы одной строчкой объяснили, где лежит, что лежит и что с этим делать. Если бы я писал это с помощью стандартных функций, получилось бы что-то такое: Это конечно не тот код, которым стоит гордиться, но на это примере видно, какой многословной получается работа с файлами при помощи стандартной библиотеки. Другой пример. Допустим нужно прочитать текстовый файл построчно. Тут мне даже придумывать не надо, вот пример из документации Node.js: Теперь попробуем сделать это при помощи FSTB: Да, да я читер. В библиотеке есть эта функция, и под капотом работает тот самый код из документации. Но здесь интересно, что на ее выходе реализован итератор, который умеет filter, map, reduce и т.д. Поэтому, если надо, например, читать csv, просто добавьте .map(line => line.split(',')). Естественно, куда же без записи. Здесь тоже все просто. Допустим у нас есть строка и мы ее хотим записать в файл: Можно дописать в конец файла: Можно сериализовать в json: Ну и можно создать стрим для записи: Кстати, ничего странного не заметили? Я об этом: Дело в том, что это не простой WriteStream, а прокачанный до промиса. Точнее, не совсем полноценный промис, но хватает, чтобы await корректно работал. Теперь можно начать работу со стримом и дождаться, когда он закончит работу с помощью await. Итак, мы посмотрели, как можно писать и читать из файлов. Но что еще можно с ними делать при помощи FSTB? Да все тоже, что при помощи стандартных методов модуля fs. Можно получить информацию о файле: Получим: Можно посчитать хэш-сумму:  Переименовывать: Копировать:  И удалять: Также можно проверить, существует ли файл, доступен ли он на чтение и запись: Итак, весь джентельменский набор для работы с файлами в наличии, теперь посмотрим, что можно делать с директориями. На мой взгляд, самая вкусная часть проекта – это работа с директориями. Когда я ее реализовал и попробовал в деле, мне самому жутко понравился результат. Давайте посмотрим, что может делать FSTB с директориями. Для работы с каталогами используется объект FSDir, а получить его можно таким вот образом: Что можно с этим делать? Ну во-первых, мы можем итерировать подкаталоги и файлы в директории: Здесь доступны методы filter, map, reduce, forEach, toArray. Можно, для примера посчитать объем подкаталогов, названия которых начинаются с символа «@» и отсортировать их по убыванию. Получим что-то в этом роде: Бабель, конечно же, на первом месте )) Усложним задачу. Допустим нам надо посмотреть, в каких модулях при разработке используется typescript и вывести версии. Это немного посложнее, но тоже получится довольно компактно: И получим: Что же еще можно делать с директориями? Можно обратиться к любому файлу или поддиректории. Для этого служит свойство fspath:     Для того, чтобы не засорять временными файлами рабочую директорию иногда имеет смысл использовать каталог для временных файлов в директории temp операционной системы. Для этих целей в FSTB есть метод mkdtemp. Создание директории производится с помощью метода mkdir. Для копирования и перемещения директории есть методы copyTo и moveTo. Для удаления - rmdir (для пустых директорий) и rimraf (если надо удалить директорию со всем содержимым). Давайте посмотрим на примере: Получим следующий вывод в консоли:  Как видите, получается лаконичный, удобный в написании и использовании код. Большинство типовых операций пишутся в одну строчку, нет кучи join’ов для формирования сложных путей, проще выстраивать последовательность операций с файлами и директориям.     Когда я начинал писать эту библиотеку, моей целью было упростить работу с файловой системой в Node.js. Считаю, что со своей задачей я справился. Работать с файлами при помощи FSTB гораздо удобнее и приятнее. На проекте, в котором я ее обкатывал, объем кода, связанный с файловой системой, уменьшился раза в два. Если говорить о плюсах, которые дает FSTB, можно выделить следующее:  Сокращается объем кода Код получается более декларативный и менее запутанный Снижается когнитивная нагрузка при написании кода для работы с файловой системой. Библиотека хорошо типизирована, что при наличии поддержки тайпингов в вашей IDE заметно упрощает жизнь. Нет внешних зависимостей, так что она не притащит за собой в ваш проект ничего лишнего Поддержка Node.js начиная с 10-й версии, поэтому можно использовать даже в проектах с довольно старой кодовой базой Основной минус, о котором стоит сказать, это, синтаксис FSPath, который может сбивать с толку, если с кодом будут работать разработчики, незнакомые с библиотекой. В таком случае имеет смысл добавить в код поясняющие комментарии. На этом, пожалуй, все. Надеюсь, что моя разработка будет полезна вам. Буду рад любой критике, комментариям, предложениям. → Исходный код библиотеки доступен в GitHub → С документацией можно ознакомиться здесь Благодарю за внимание! Инженер и программист