@fastify/static
Advanced tools
Comparing version
168
index.d.ts
@@ -11,96 +11,106 @@ // Definitions by: Jannik <https://github.com/jannikkeye> | ||
sendFile(filename: string, rootPath?: string): FastifyReply; | ||
sendFile(filename: string, options?: SendOptions): FastifyReply; | ||
sendFile(filename: string, rootPath?: string, options?: SendOptions): FastifyReply; | ||
download(filepath: string, options?: SendOptions): FastifyReply; | ||
sendFile(filename: string, options?: fastifyStatic.SendOptions): FastifyReply; | ||
sendFile(filename: string, rootPath?: string, options?: fastifyStatic.SendOptions): FastifyReply; | ||
download(filepath: string, options?: fastifyStatic.SendOptions): FastifyReply; | ||
download(filepath: string, filename?: string): FastifyReply; | ||
download(filepath: string, filename?: string, options?: SendOptions): FastifyReply; | ||
download(filepath: string, filename?: string, options?: fastifyStatic.SendOptions): FastifyReply; | ||
} | ||
} | ||
interface ExtendedInformation { | ||
fileCount: number; | ||
totalFileCount: number; | ||
folderCount: number; | ||
totalFolderCount: number; | ||
totalSize: number; | ||
lastModified: number; | ||
} | ||
type FastifyStaticPlugin = FastifyPluginCallback<NonNullable<fastifyStatic.FastifyStaticOptions>>; | ||
interface ListDir { | ||
href: string; | ||
name: string; | ||
stats: Stats; | ||
extendedInfo?: ExtendedInformation; | ||
} | ||
declare namespace fastifyStatic { | ||
export interface ExtendedInformation { | ||
fileCount: number; | ||
totalFileCount: number; | ||
folderCount: number; | ||
totalFolderCount: number; | ||
totalSize: number; | ||
lastModified: number; | ||
} | ||
interface ListFile { | ||
href: string; | ||
name: string; | ||
stats: Stats; | ||
} | ||
export interface ListDir { | ||
href: string; | ||
name: string; | ||
stats: Stats; | ||
extendedInfo?: ExtendedInformation; | ||
} | ||
interface ListRender { | ||
(dirs: ListDir[], files: ListFile[]): string; | ||
} | ||
export interface ListFile { | ||
href: string; | ||
name: string; | ||
stats: Stats; | ||
} | ||
interface ListOptions { | ||
names?: string[]; | ||
extendedFolderInfo?: boolean; | ||
} | ||
export interface ListRender { | ||
(dirs: ListDir[], files: ListFile[]): string; | ||
} | ||
interface ListOptionsJsonFormat extends ListOptions { | ||
format: 'json'; | ||
jsonFormat?: 'names' | 'extended'; | ||
} | ||
export interface ListOptions { | ||
names?: string[]; | ||
extendedFolderInfo?: boolean; | ||
jsonFormat?: 'names' | 'extended'; | ||
} | ||
interface ListOptionsHtmlFormat extends ListOptions { | ||
format: 'html'; | ||
render: ListRender; | ||
} | ||
export interface ListOptionsJsonFormat extends ListOptions { | ||
format: 'json'; | ||
// Required when the URL parameter `format=html` exists | ||
render?: ListRender; | ||
} | ||
// Passed on to `send` | ||
interface SendOptions { | ||
acceptRanges?: boolean; | ||
cacheControl?: boolean; | ||
dotfiles?: 'allow' | 'deny' | 'ignore'; | ||
etag?: boolean; | ||
extensions?: string[]; | ||
immutable?: boolean; | ||
index?: string[] | string | false; | ||
lastModified?: boolean; | ||
maxAge?: string | number; | ||
} | ||
export interface ListOptionsHtmlFormat extends ListOptions { | ||
format: 'html'; | ||
render: ListRender; | ||
} | ||
export interface FastifyStaticOptions extends SendOptions { | ||
root: string | string[]; | ||
prefix?: string; | ||
prefixAvoidTrailingSlash?: boolean; | ||
serve?: boolean; | ||
decorateReply?: boolean; | ||
schemaHide?: boolean; | ||
setHeaders?: (...args: any[]) => void; | ||
redirect?: boolean; | ||
wildcard?: boolean; | ||
list?: boolean | ListOptionsJsonFormat | ListOptionsHtmlFormat; | ||
allowedPath?: (pathName: string, root?: string) => boolean; | ||
/** | ||
* @description | ||
* Opt-in to looking for pre-compressed files | ||
*/ | ||
preCompressed?: boolean; | ||
// Passed on to `send` | ||
export interface SendOptions { | ||
acceptRanges?: boolean; | ||
cacheControl?: boolean; | ||
dotfiles?: 'allow' | 'deny' | 'ignore'; | ||
etag?: boolean; | ||
extensions?: string[]; | ||
immutable?: boolean; | ||
index?: string[] | string | false; | ||
lastModified?: boolean; | ||
maxAge?: string | number; | ||
} | ||
// Passed on to `send` | ||
acceptRanges?: boolean; | ||
cacheControl?: boolean; | ||
dotfiles?: 'allow' | 'deny' | 'ignore'; | ||
etag?: boolean; | ||
extensions?: string[]; | ||
immutable?: boolean; | ||
index?: string[] | string | false; | ||
lastModified?: boolean; | ||
maxAge?: string | number; | ||
export interface FastifyStaticOptions extends SendOptions { | ||
root: string | string[]; | ||
prefix?: string; | ||
prefixAvoidTrailingSlash?: boolean; | ||
serve?: boolean; | ||
decorateReply?: boolean; | ||
schemaHide?: boolean; | ||
setHeaders?: (...args: any[]) => void; | ||
redirect?: boolean; | ||
wildcard?: boolean; | ||
list?: boolean | ListOptionsJsonFormat | ListOptionsHtmlFormat; | ||
allowedPath?: (pathName: string, root?: string) => boolean; | ||
/** | ||
* @description | ||
* Opt-in to looking for pre-compressed files | ||
*/ | ||
preCompressed?: boolean; | ||
// Passed on to `send` | ||
acceptRanges?: boolean; | ||
cacheControl?: boolean; | ||
dotfiles?: 'allow' | 'deny' | 'ignore'; | ||
etag?: boolean; | ||
extensions?: string[]; | ||
immutable?: boolean; | ||
index?: string[] | string | false; | ||
lastModified?: boolean; | ||
maxAge?: string | number; | ||
} | ||
export const fastifyStatic: FastifyStaticPlugin; | ||
export { fastifyStatic as default }; | ||
} | ||
export declare const fastifyStatic: FastifyPluginCallback<FastifyStaticOptions> | ||
declare function fastifyStatic(...params: Parameters<FastifyStaticPlugin>): ReturnType<FastifyStaticPlugin>; | ||
export default fastifyStatic; | ||
export = fastifyStatic; |
@@ -12,3 +12,3 @@ 'use strict' | ||
const globPromise = util.promisify(glob) | ||
const encodingNegotiator = require('encoding-negotiator') | ||
const encodingNegotiator = require('@fastify/accept-negotiator') | ||
@@ -199,3 +199,3 @@ const dirList = require('./lib/dirList') | ||
if (err.code === 'ENOENT') { | ||
// when preCompress is enabled and the path is a directoy without a trailing shash | ||
// when preCompress is enabled and the path is a directory without a trailing slash | ||
if (opts.preCompressed && encoding) { | ||
@@ -499,3 +499,3 @@ const indexPathname = findIndexFile(pathname, options.root, options.index) | ||
let i = 0 | ||
// we detech how many slash before a valid path | ||
// we detect how many slash before a valid path | ||
for (i; i < url.length; i++) { | ||
@@ -502,0 +502,0 @@ if (url[i] !== '/' && url[i] !== '\\') break |
@@ -107,2 +107,6 @@ 'use strict' | ||
send: async function ({ reply, dir, options, route, prefix, dotfiles }) { | ||
if (reply.request.query.format === 'html' && typeof options.render !== 'function') { | ||
throw new Error('The `list.render` option must be a function and is required with the URL parameter `format=html`') | ||
} | ||
let entries | ||
@@ -204,5 +208,2 @@ try { | ||
} | ||
if (options.list.format === 'html' && options.list.jsonFormat != null) { | ||
return new TypeError('The `list.jsonFormat` option must be with json format') | ||
} | ||
} | ||
@@ -209,0 +210,0 @@ |
{ | ||
"name": "@fastify/static", | ||
"version": "6.3.0", | ||
"version": "6.3.1", | ||
"description": "Plugin for serving static files as fast as possible.", | ||
@@ -33,7 +33,7 @@ "main": "index.js", | ||
"content-disposition": "^0.5.3", | ||
"encoding-negotiator": "^2.0.1", | ||
"fastify-plugin": "^3.0.0", | ||
"@fastify/accept-negotiator": "^1.0.0", | ||
"fastify-plugin": "^4.0.0", | ||
"glob": "^8.0.1", | ||
"p-limit": "^3.1.0", | ||
"readable-stream": "^3.4.0", | ||
"readable-stream": "^4.0.0", | ||
"send": "^0.18.0" | ||
@@ -43,3 +43,3 @@ }, | ||
"@fastify/compress": "^6.0.0", | ||
"@types/node": "^17.0.0", | ||
"@types/node": "^18.0.0", | ||
"@typescript-eslint/eslint-plugin": "^2.29.0", | ||
@@ -58,3 +58,3 @@ "@typescript-eslint/parser": "^2.29.0", | ||
"tap": "^16.0.0", | ||
"tsd": "^0.20.0", | ||
"tsd": "^0.22.0", | ||
"typescript": "^4.0.2" | ||
@@ -61,0 +61,0 @@ }, |
@@ -75,10 +75,2 @@ 'use strict' | ||
t.test('throws when `list.format` is html and `list.jsonFormat` is given', t => { | ||
t.plan(2) | ||
const err = dirList.validateOptions({ list: { format: 'html', render: () => '', jsonFormat: 'extended' } }) | ||
t.type(err, TypeError) | ||
t.equal(err.message, 'The `list.jsonFormat` option must be with json format') | ||
}) | ||
t.test('dir list wrong options', t => { | ||
@@ -489,3 +481,3 @@ t.plan(3) | ||
t.test('dir list - url parameter format', t => { | ||
t.test('json format with url parameter format', t => { | ||
t.plan(13) | ||
@@ -498,2 +490,98 @@ | ||
list: { | ||
format: 'json', | ||
render (dirs, files) { | ||
return 'html' | ||
} | ||
} | ||
} | ||
const route = '/public/' | ||
const jsonContent = { dirs: ['deep', 'shallow'], files: ['.example', 'a .md', 'foo.html', 'foobar.html', 'index.css', 'index.html'] } | ||
helper.arrange(t, options, (url) => { | ||
simple.concat({ | ||
method: 'GET', | ||
url: url + route | ||
}, (err, response, body) => { | ||
t.error(err) | ||
t.equal(response.statusCode, 200) | ||
t.equal(body.toString(), JSON.stringify(jsonContent)) | ||
t.ok(response.headers['content-type'].includes('application/json')) | ||
}) | ||
simple.concat({ | ||
method: 'GET', | ||
url: url + route + '?format=html' | ||
}, (err, response, body) => { | ||
t.error(err) | ||
t.equal(response.statusCode, 200) | ||
t.equal(body.toString(), 'html') | ||
t.ok(response.headers['content-type'].includes('text/html')) | ||
}) | ||
simple.concat({ | ||
method: 'GET', | ||
url: url + route + '?format=json' | ||
}, (err, response, body) => { | ||
t.error(err) | ||
t.equal(response.statusCode, 200) | ||
t.equal(body.toString(), JSON.stringify(jsonContent)) | ||
t.ok(response.headers['content-type'].includes('application/json')) | ||
}) | ||
}) | ||
}) | ||
t.test('json format with url parameter format and without render option', t => { | ||
t.plan(12) | ||
const options = { | ||
root: path.join(__dirname, '/static'), | ||
prefix: '/public', | ||
index: false, | ||
list: { | ||
format: 'json' | ||
} | ||
} | ||
const route = '/public/' | ||
const jsonContent = { dirs: ['deep', 'shallow'], files: ['.example', 'a .md', 'foo.html', 'foobar.html', 'index.css', 'index.html'] } | ||
helper.arrange(t, options, (url) => { | ||
simple.concat({ | ||
method: 'GET', | ||
url: url + route | ||
}, (err, response, body) => { | ||
t.error(err) | ||
t.equal(response.statusCode, 200) | ||
t.equal(body.toString(), JSON.stringify(jsonContent)) | ||
t.ok(response.headers['content-type'].includes('application/json')) | ||
}) | ||
simple.concat({ | ||
method: 'GET', | ||
url: url + route + '?format=html' | ||
}, (err, response, body) => { | ||
t.error(err) | ||
t.equal(response.statusCode, 500) | ||
t.equal(JSON.parse(body.toString()).message, 'The `list.render` option must be a function and is required with the URL parameter `format=html`') | ||
}) | ||
simple.concat({ | ||
method: 'GET', | ||
url: url + route + '?format=json' | ||
}, (err, response, body) => { | ||
t.error(err) | ||
t.equal(response.statusCode, 200) | ||
t.equal(body.toString(), JSON.stringify(jsonContent)) | ||
t.ok(response.headers['content-type'].includes('application/json')) | ||
}) | ||
}) | ||
}) | ||
t.test('html format with url parameter format', t => { | ||
t.plan(13) | ||
const options = { | ||
root: path.join(__dirname, '/static'), | ||
prefix: '/public', | ||
index: false, | ||
list: { | ||
format: 'html', | ||
@@ -506,2 +594,3 @@ render (dirs, files) { | ||
const route = '/public/' | ||
const jsonContent = { dirs: ['deep', 'shallow'], files: ['.example', 'a .md', 'foo.html', 'foobar.html', 'index.css', 'index.html'] } | ||
@@ -535,3 +624,3 @@ helper.arrange(t, options, (url) => { | ||
t.equal(response.statusCode, 200) | ||
t.ok(body.toString()) | ||
t.equal(body.toString(), JSON.stringify(jsonContent)) | ||
t.ok(response.headers['content-type'].includes('application/json')) | ||
@@ -538,0 +627,0 @@ }) |
@@ -1,5 +0,33 @@ | ||
import fastify from 'fastify' | ||
import { expectAssignable, expectError } from 'tsd' | ||
import fastifyStatic, { FastifyStaticOptions } from '../..' | ||
import fastify, { FastifyInstance, FastifyPluginCallback } from 'fastify' | ||
import { Server } from 'http'; | ||
import { expectAssignable, expectError, expectType } from 'tsd' | ||
import * as fastifyStaticStar from '../..'; | ||
import fastifyStatic, { | ||
FastifyStaticOptions, | ||
fastifyStatic as fastifyStaticNamed, | ||
} from '../..' | ||
import fastifyStaticCjsImport = require('../..'); | ||
const fastifyStaticCjs = require('../..'); | ||
const app: FastifyInstance = fastify(); | ||
app.register(fastifyStatic); | ||
app.register(fastifyStaticNamed); | ||
app.register(fastifyStaticCjs); | ||
app.register(fastifyStaticCjsImport.default); | ||
app.register(fastifyStaticCjsImport.fastifyStatic); | ||
app.register(fastifyStaticStar.default); | ||
app.register(fastifyStaticStar.fastifyStatic); | ||
expectType<FastifyPluginCallback<FastifyStaticOptions, Server>>(fastifyStatic); | ||
expectType<FastifyPluginCallback<FastifyStaticOptions, Server>>(fastifyStaticNamed); | ||
expectType<FastifyPluginCallback<FastifyStaticOptions, Server>>(fastifyStaticCjsImport.default); | ||
expectType<FastifyPluginCallback<FastifyStaticOptions, Server>>(fastifyStaticCjsImport.fastifyStatic); | ||
expectType<FastifyPluginCallback<FastifyStaticOptions, Server>>(fastifyStaticStar.default); | ||
expectType<FastifyPluginCallback<FastifyStaticOptions, Server>>( | ||
fastifyStaticStar.fastifyStatic | ||
); | ||
expectType<any>(fastifyStaticCjs); | ||
const appWithImplicitHttp = fastify() | ||
@@ -42,3 +70,3 @@ const options: FastifyStaticOptions = { | ||
expectError<FastifyStaticOptions>({ | ||
expectAssignable<FastifyStaticOptions>({ | ||
root: '', | ||
@@ -45,0 +73,0 @@ list: { |
Sorry, the diff of this file is too big to display
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
363939
1.25%4752
2.41%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
Updated
Updated