From 3511fcc512d9da1930208061f46e657202f3ccd5 Mon Sep 17 00:00:00 2001 From: arcaniussainey Date: Mon, 24 Nov 2025 20:33:30 -0500 Subject: [PATCH 1/4] Refactored to match original codestyle --- index.js | 37 ++++++++++++++++++++----------------- package.json | 5 ++--- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/index.js b/index.js index 86b47dc..629dd57 100644 --- a/index.js +++ b/index.js @@ -3,7 +3,7 @@ const path = require('node:path') const { fileURLToPath } = require('node:url') const { statSync } = require('node:fs') -const { glob } = require('glob') +const { glob } = require('node:fs/promises') const fp = require('fastify-plugin') const send = require('@fastify/send') const encodingNegotiator = require('@fastify/accept-negotiator') @@ -139,27 +139,30 @@ async function fastifyStatic (fastify, opts) { for (let rootPath of roots) { rootPath = rootPath.split(path.win32.sep).join(path.posix.sep) !rootPath.endsWith('/') && (rootPath += '/') - const files = await glob('**/**', { - cwd: rootPath, absolute: false, follow: true, nodir: true, dot: opts.serveDotFiles, ignore: opts.globIgnore - }) - - for (let file of files) { - file = file.split(path.win32.sep).join(path.posix.sep) - const route = prefix + file - if (routes.has(route)) { - continue - } + const files = await Array.fromAsync(glob('**/**', { + cwd: rootPath, absolute: false, follow: true, nodir: true, dot: opts.serveDotFiles,ignore: opts.globIgnore + })) + + for (let file of files) + { + + file = file.split(path.win32.sep).join(path.posix.sep) + const route = prefix + file + + if (routes.has(route)) { + continue + } - routes.add(route) + routes.add(route) - setUpHeadAndGet(routeOpts, route, `/${file}`, rootPath) + setUpHeadAndGet(routeOpts, route, `/${file}`, rootPath) - const key = path.posix.basename(route) - if (indexes.has(key) && !indexDirs.has(key)) { - indexDirs.set(path.posix.dirname(route), rootPath) + const key = path.posix.basename(route) + if (indexes.has(key) && !indexDirs.has(key)) { + indexDirs.set(path.posix.dirname(route), rootPath) + } } - } } for (const [dirname, rootPath] of indexDirs.entries()) { diff --git a/package.json b/package.json index cb7fa66..1d5e6a2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fastify/static", - "version": "8.2.0", + "version": "8.3.0", "description": "Plugin for serving static files as fast as possible.", "main": "index.js", "type": "commonjs", @@ -62,8 +62,7 @@ "@fastify/send": "^4.0.0", "content-disposition": "^0.5.4", "fastify-plugin": "^5.0.0", - "fastq": "^1.17.1", - "glob": "^11.0.0" + "fastq": "^1.17.1" }, "devDependencies": { "@fastify/compress": "^8.0.0", From f91f97cf8ff26b8d765cc5dd03202f914bfea176 Mon Sep 17 00:00:00 2001 From: arcaniussainey Date: Sun, 30 Nov 2025 12:59:47 -0500 Subject: [PATCH 2/4] Ran linter --- index.js | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/index.js b/index.js index 629dd57..3caa81d 100644 --- a/index.js +++ b/index.js @@ -141,28 +141,26 @@ async function fastifyStatic (fastify, opts) { !rootPath.endsWith('/') && (rootPath += '/') const files = await Array.fromAsync(glob('**/**', { - cwd: rootPath, absolute: false, follow: true, nodir: true, dot: opts.serveDotFiles,ignore: opts.globIgnore - })) - - for (let file of files) - { - - file = file.split(path.win32.sep).join(path.posix.sep) - const route = prefix + file - - if (routes.has(route)) { - continue - } + cwd: rootPath, absolute: false, follow: true, nodir: true, dot: opts.serveDotFiles, ignore: opts.globIgnore + })) - routes.add(route) + for (let file of files) { + file = file.split(path.win32.sep).join(path.posix.sep) + const route = prefix + file - setUpHeadAndGet(routeOpts, route, `/${file}`, rootPath) + if (routes.has(route)) { + continue + } - const key = path.posix.basename(route) - if (indexes.has(key) && !indexDirs.has(key)) { - indexDirs.set(path.posix.dirname(route), rootPath) - } + routes.add(route) + + setUpHeadAndGet(routeOpts, route, `/${file}`, rootPath) + + const key = path.posix.basename(route) + if (indexes.has(key) && !indexDirs.has(key)) { + indexDirs.set(path.posix.dirname(route), rootPath) } + } } for (const [dirname, rootPath] of indexDirs.entries()) { From c0a8855866ee68ccb96a9548760a36bbca16f21a Mon Sep 17 00:00:00 2001 From: arcaniussainey Date: Sun, 30 Nov 2025 13:13:01 -0500 Subject: [PATCH 3/4] Converted Dirents to strings --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 3caa81d..87732a2 100644 --- a/index.js +++ b/index.js @@ -142,7 +142,7 @@ async function fastifyStatic (fastify, opts) { const files = await Array.fromAsync(glob('**/**', { cwd: rootPath, absolute: false, follow: true, nodir: true, dot: opts.serveDotFiles, ignore: opts.globIgnore - })) + }).map(dirent => dirent.name)) for (let file of files) { file = file.split(path.win32.sep).join(path.posix.sep) From fd647fcacbf3071b1a1a5eede1f84a07f7a0f52b Mon Sep 17 00:00:00 2001 From: arcaniussainey Date: Sun, 30 Nov 2025 13:54:14 -0500 Subject: [PATCH 4/4] Undid explicit conversion to string as it caused errors and lowered test coverage --- index.js | 2 +- out.txt | Bin 0 -> 63792 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 out.txt diff --git a/index.js b/index.js index 87732a2..3caa81d 100644 --- a/index.js +++ b/index.js @@ -142,7 +142,7 @@ async function fastifyStatic (fastify, opts) { const files = await Array.fromAsync(glob('**/**', { cwd: rootPath, absolute: false, follow: true, nodir: true, dot: opts.serveDotFiles, ignore: opts.globIgnore - }).map(dirent => dirent.name)) + })) for (let file of files) { file = file.split(path.win32.sep).join(path.posix.sep) diff --git a/out.txt b/out.txt new file mode 100644 index 0000000000000000000000000000000000000000..05f21133cd3e7fb13a862530f4f0867d646541d2 GIT binary patch literal 63792 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 literal 0 HcmV?d00001