diff --git a/.gitignore b/.gitignore index 0125458..bd50957 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# Autogenerated +*.d.ts + # Logs logs *.log diff --git a/README.md b/README.md new file mode 100644 index 0000000..405b278 --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +# @isbl/fs + +Wraps `node:fs/promises` and sync functions from `node:fs` to add proper async +error stack. + +Install + +```sh +yarn add @isbl/fs +``` + +If you are using typescript then you should also install type definitions + +```sh +yarn add -D @types/node +``` + +## Usage + +Same as original wrapped functions, also includes typescript definitions. +Note that this module is ESM-only so it can't be imported using `require`. + +```ts +import fs from '@isbl/fs' +await fs.readFile(...) + +// or + +import { readFile } from '@isbl/fs' +await readFile(...) +``` + +## Available functions + +See start of `index.mjs` file. It lists all the exports. diff --git a/index.js b/index.js new file mode 100644 index 0000000..1c949f6 --- /dev/null +++ b/index.js @@ -0,0 +1,58 @@ +import * as fsPromises from "fs/promises" +import * as fsSync from "fs" + +// Adding new function: +// 1. add `export const ...` here +// 2. add it to `export default { ... }` +export const readFile = wrap("readFile") +export const writeFile = wrap("writeFile") +export const readFileSync = wrapSync("readFileSync") +export const mkdir = wrap("mkdir") +export const copyFile = wrap("copyFile") +export const rm = wrap("rm") +export default { readFile, writeFile, readFileSync, mkdir, copyFile, rm } + +/** @type {(method: M) => fsPromises[M]} */ +function wrap(method) { + if (!fsPromises[method]) return null + Object.defineProperty(wrapper, "name", { writable: true }) + wrapper.name = fsPromises[method].name + Object.defineProperty(wrapper, "name", { writable: false }) + return wrapper + async function wrapper(...args) { + try { + return await fsPromises[method](...args) + } catch (e) { + const opt = { cause: e } + const err = new Error( + `Error in fsPromises.${method} ${args[0]}\n${e.message}`, + opt, + ) + Error.captureStackTrace?.(err, wrapper) + err.code = e.code + throw err + } + } +} + +/** @type (method: M) => fsSync[M] */ +function wrapSync(method) { + if (!fsSync[method]) return null + Object.defineProperty(wrapper, "name", { writable: true }) + wrapper.name = fsSync[method].name + Object.defineProperty(wrapper, "name", { writable: false }) + return wrapper + function wrapper(...args) { + try { + return fsSync[method](...args) + } catch (e) { + const opt = { cause: e } + const err = new Error( + `Error in fs.${method} ${args[0]}\n${e.message}`, + opt, + ) + err.code = e.code + throw err + } + } +} diff --git a/package.json b/package.json index a7beb7e..ac14a98 100644 --- a/package.json +++ b/package.json @@ -2,19 +2,40 @@ "name": "@isbl/fs", "version": "0.1.0", "description": "Wrappers around node:fs with proper error stack support", - "main": "index.js", "repository": { "type": "git", "url": "https://github.com/CodeWitchBella/isbl-fs.git" }, + "exports": "./index.js", + "types": "./index.d.ts", "author": "Isabella Skořepová ", "license": "MIT", "private": false, + "type": "module", + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + }, + "engines": { + "node": ">=14.15.0" + }, + "peerDependencies": { + "@types/node": ">=14.15.0" + }, + "files": [ + "index.js", + "index.d.ts", + "README.md" + ], "devDependencies": { "@isbl/publisher": "^0.7.1", - "prettier": "^2.3.2" + "@types/node": "^16.7.10", + "prettier": "^2.3.2", + "typescript": "^4.4.2" }, "scripts": { + "prepare": "tsc", "prepublishOnly": "isbl-publisher prepublishOnly", "publish:npm": "isbl-publisher publish --no-draft" } diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..c09876b --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "es2021", + "module": "ES2020", + "allowJs": true, + "declaration": true, + "emitDeclarationOnly": true, + "strict": false, + "skipLibCheck": false + }, + "include": ["index.js"] +} diff --git a/yarn.lock b/yarn.lock index 0903ff6..a141908 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10,6 +10,11 @@ node-fetch "^2.6.1" open "^8.2.1" +"@types/node@^16.7.10": + version "16.7.10" + resolved "https://registry.yarnpkg.com/@types/node/-/node-16.7.10.tgz#7aa732cc47341c12a16b7d562f519c2383b6d4fc" + integrity sha512-S63Dlv4zIPb8x6MMTgDq5WWRJQe56iBEY0O3SOFA9JrRienkOVDXSXBjjJw6HTNQYSE2JI6GMCR6LVbIMHJVvA== + define-lazy-prop@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" @@ -45,3 +50,8 @@ prettier@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.2.tgz#ef280a05ec253712e486233db5c6f23441e7342d" integrity sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ== + +typescript@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.2.tgz#6d618640d430e3569a1dfb44f7d7e600ced3ee86" + integrity sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==