From 3a1f9d62a64fcb17514f64fae4a9c0dbd52040b5 Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Mon, 23 Dec 2024 00:42:25 +0800 Subject: [PATCH 1/4] feat: support fs.exists async function --- src/fs.ts | 17 +++++++++++++++++ src/index.ts | 1 + test/fs.test.ts | 30 ++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 src/fs.ts create mode 100644 test/fs.test.ts diff --git a/src/fs.ts b/src/fs.ts new file mode 100644 index 0000000..d1e3a87 --- /dev/null +++ b/src/fs.ts @@ -0,0 +1,17 @@ +import { Stats } from 'node:fs'; +import { stat } from 'node:fs/promises'; + +/** + * Check if a file exists. + * Returns the file stats if it exists, or `false` if it doesn't. + */ +export async function exists(file: string): Promise { + try { + return await stat(file); + } catch (err: any) { + if (err.code === 'ENOENT') { + return false; + } + throw err; + } +} diff --git a/src/index.ts b/src/index.ts index aecde29..ee2c139 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,3 +9,4 @@ export * from './string.js'; export * from './optimize.js'; export * from './object.js'; export * from './timeout.js'; +export * from './fs.js'; diff --git a/test/fs.test.ts b/test/fs.test.ts new file mode 100644 index 0000000..957422b --- /dev/null +++ b/test/fs.test.ts @@ -0,0 +1,30 @@ +import { strict as assert } from 'node:assert'; +import path from 'node:path'; +import { Stats } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import * as utility from '../src/index.js'; +import { exists } from '../src/index.js'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +describe('test/fs.test.ts', () => { + describe('exists()', () => { + it('should work', async () => { + let stats = await exists(__filename); + assert(stats instanceof Stats); + assert(stats.size > 0, 'stats.size > 0'); + assert.equal(stats.isFile(), true); + assert.equal(stats.isDirectory(), false); + + stats = await utility.exists(__dirname); + assert(stats instanceof Stats); + assert(stats.size > 0, 'stats.size > 0'); + assert.equal(stats.isDirectory(), true); + assert.equal(stats.isFile(), false); + assert.equal(await exists(__dirname + '/nonexistent'), false); + + assert.equal(await exists('/root/../../../../../etc/passwd'), false); + }); + }); +}); From 308fe3a3e6e276b72efc51e0b395ca6879568d93 Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Mon, 23 Dec 2024 00:44:06 +0800 Subject: [PATCH 2/4] f --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7869776..f47ce48 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ [![Test coverage][codecov-image]][codecov-url] [![npm download][download-image]][download-url] [![Node.js Version](https://img.shields.io/node/v/utility.svg?style=flat)](https://nodejs.org/en/download/) +[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://makeapullrequest.com) [npm-image]: https://img.shields.io/npm/v/utility.svg?style=flat-square [npm-url]: https://npmjs.org/package/utility From 554f468c7da4feab6252da388d627a94c5cdda4d Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Mon, 23 Dec 2024 00:50:57 +0800 Subject: [PATCH 3/4] f --- .github/workflows/nodejs.yml | 1 - test/fs.test.ts | 26 +++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 8e62f3d..97d3f98 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -11,7 +11,6 @@ jobs: name: Node.js uses: node-modules/github-actions/.github/workflows/node-test.yml@master with: - os: 'ubuntu-latest' version: '16, 18, 20, 22, 23' secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/test/fs.test.ts b/test/fs.test.ts index 957422b..1f451ef 100644 --- a/test/fs.test.ts +++ b/test/fs.test.ts @@ -23,8 +23,32 @@ describe('test/fs.test.ts', () => { assert.equal(stats.isDirectory(), true); assert.equal(stats.isFile(), false); assert.equal(await exists(__dirname + '/nonexistent'), false); + }); + + it('should throw error on Linux', async () => { + if (process.platform !== 'linux') { + return; + } + await assert.rejects(async () => { + await exists('/root/../../../../../etc/passwd'); + }, (err: any) => { + // Error: EACCES: permission denied, stat '/root/../../../../../etc/passwd' + assert.equal(err.code, 'EACCES'); + return true; + }); + }); - assert.equal(await exists('/root/../../../../../etc/passwd'), false); + it('should throw error on win32', async () => { + if (process.platform !== 'win32') { + return; + } + await assert.rejects(async () => { + await exists('C:\\Windows\\System32\\drivers\\etc\\hosts'); + }, (err: any) => { + // Error: EACCES: permission denied, stat 'C:\Windows\System32\drivers\etc\hosts' + assert.equal(err.code, 'EPERM'); + return true; + }); }); }); }); From 03a78d2bef89d6d364eba5b80a0bc4e269ac0a56 Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Mon, 23 Dec 2024 00:54:04 +0800 Subject: [PATCH 4/4] f --- test/fs.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/fs.test.ts b/test/fs.test.ts index 1f451ef..98c0370 100644 --- a/test/fs.test.ts +++ b/test/fs.test.ts @@ -19,7 +19,7 @@ describe('test/fs.test.ts', () => { stats = await utility.exists(__dirname); assert(stats instanceof Stats); - assert(stats.size > 0, 'stats.size > 0'); + // assert(stats.size > 0, 'stats.size > 0'); assert.equal(stats.isDirectory(), true); assert.equal(stats.isFile(), false); assert.equal(await exists(__dirname + '/nonexistent'), false); @@ -38,7 +38,7 @@ describe('test/fs.test.ts', () => { }); }); - it('should throw error on win32', async () => { + it.skip('should throw error on win32', async () => { if (process.platform !== 'win32') { return; }