Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add matchFilter and ignoreFilter #289

Merged
merged 4 commits into from
Jan 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,27 @@ Autoload can be customised using the following options:
})
```

- `matchFilter` (optional) - Filter matching any path that should be loaded. Can be a RegExp, a string or a function returning a boolean.

```js
fastify.register(autoLoad, {
dir: path.join(__dirname, 'plugins'),
matchFilter: (path) => path.split("/").at(-2) === "handlers"
})
```


- `ignoreFilter` (optional) - Filter matching any path that should not be loaded. Can be a RegExp, a string or a function returning a boolean.

```js
fastify.register(autoLoad, {
dir: path.join(__dirname, 'plugins'),
ignoreFilter: (path) => path.endsWith('.spec.js')
})
```

- `ignorePattern` (optional) - Regex matching any file that should not be loaded

- `ignorePattern` (optional) - RegExp matching any file or folder that should not be loaded.

```js
fastify.register(autoLoad, {
Expand All @@ -119,6 +138,7 @@ Autoload can be customised using the following options:
})
```


- `indexPattern` (optional) - Regex to override the `index.js` naming convention

```js
Expand Down
32 changes: 29 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ function getScriptType (fname, packageType) {

// eslint-disable-next-line default-param-last
async function findPlugins (dir, options, hookedAccumulator = {}, prefix, depth = 0, hooks = []) {
const { indexPattern, ignorePattern, scriptPattern, dirNameRoutePrefix, maxDepth, autoHooksPattern } = options
const { indexPattern, ignorePattern, ignoreFilter, matchFilter, scriptPattern, dirNameRoutePrefix, maxDepth, autoHooksPattern } = options
const list = await readdir(dir, { withFileTypes: true })
let currentHooks = []

Expand Down Expand Up @@ -171,7 +171,7 @@ async function findPlugins (dir, options, hookedAccumulator = {}, prefix, depth
throw new Error(`@fastify/autoload cannot import hooks plugin at '${file}'. To fix this error compile TypeScript to JavaScript or use 'ts-node' to run your app.`)
}

hookedAccumulator[prefix || '/'].plugins.push({ file, type, prefix })
accumulatePlugin({ file, type }, indexDirent.name)
const hasDirectory = list.find((dirent) => dirent.isDirectory())

if (!hasDirectory) {
Expand Down Expand Up @@ -226,13 +226,27 @@ async function findPlugins (dir, options, hookedAccumulator = {}, prefix, depth

// Don't place hook in plugin queue
if (!autoHooksPattern.test(dirent.name)) {
hookedAccumulator[prefix || '/'].plugins.push({ file, type, prefix })
accumulatePlugin({ file, type }, dirent.name)
}
}
}
await Promise.all(directoryPromises)

return hookedAccumulator

function accumulatePlugin ({ file, type }, direntName = 'index.ts') {
const routePath = `${prefix ?? ''}/${direntName}`

if (matchFilter && !filterPath(routePath, matchFilter)) {
return
}

if (ignoreFilter && filterPath(routePath, ignoreFilter)) {
return
}

hookedAccumulator[prefix || '/'].plugins.push({ file, type, prefix })
}
}

async function loadPlugin ({ file, type, directoryPrefix, options, log }) {
Expand Down Expand Up @@ -315,6 +329,18 @@ function registerPlugin (fastify, meta, allPlugins, parentPlugins = {}) {
meta.registered = true
}

function filterPath (path, filter) {
if (typeof filter === 'string') {
return path.includes(filter)
}

if (filter instanceof RegExp) {
return filter.test(path)
}

return filter(path)
}

/**
* Used to determine if the contents of a required autoloaded file matches
* the shape of a Fastify route configuration object.
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"typescript:tsx": "node scripts/unit-typescript-tsx.js",
"typescript:esbuild": "node scripts/unit-typescript-esbuild.js",
"typescript:vitest": "vitest run",
"typescript:vitest:dev": "vitest",
"unit": "node scripts/unit.js",
"unit:with-modules": "tap test/commonjs/*.js test/module/*.js test/typescript/*.ts"
},
Expand Down
5 changes: 5 additions & 0 deletions test/commonjs/ts-node/routes/bar/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports.default = async (fastify: any) => {
fastify.get("/", function () {
return { foo: "bar" };
})
};
5 changes: 5 additions & 0 deletions test/commonjs/ts-node/routes/foo/baz/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports.default = async (fastify: any) => {
fastify.get("/", function () {
return { foo: "bar" };
})
};
86 changes: 86 additions & 0 deletions test/vitest/filter.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
'use strict'

import { describe, test, expect } from 'vitest'
import Fastify from 'fastify'
import AutoLoad from '../../index'
import { join } from 'path'

describe.concurrent("Vitest ignore filters test suite", function () {
const app = Fastify()
app.register(AutoLoad, {
dir: join(__dirname, '../commonjs/ts-node/routes'),
ignoreFilter: "foo"
})

test("Test the root route", async function () {
const response = await app.inject({
method: 'GET',
url: '/'
})
expect(response.statusCode).toEqual(200)
})

test("Test /foo route", async function () {
const response = await app.inject({
method: 'GET',
url: '/foo'
})
expect(response.statusCode).toBe(404)
})

test("Test /bar route", async function () {
const response = await app.inject({
method: 'GET',
url: '/bar'
})
expect(response.statusCode).toBe(200)
})

test("Test /baz route", async function () {
const response = await app.inject({
method: 'GET',
url: '/foo/baz'
})
expect(response.statusCode).toBe(404)
})
})

describe.concurrent("Vitest match filters test suite", function () {
const app = Fastify()
app.register(AutoLoad, {
dir: join(__dirname, '../commonjs/ts-node/routes'),
matchFilter: "/foo"
})

test("Test the root route", async function () {
const response = await app.inject({
method: 'GET',
url: '/'
})
expect(response.statusCode).toEqual(404)
})

test("Test /foo route", async function () {
const response = await app.inject({
method: 'GET',
url: '/foo'
})
expect(response.statusCode).toBe(200)
})

test("Test /bar route", async function () {
const response = await app.inject({
method: 'GET',
url: '/bar'
})
expect(response.statusCode).toBe(404)
})

test("Test /baz route", async function () {
const response = await app.inject({
method: 'GET',
url: '/foo/baz'
})
expect(response.statusCode).toBe(200)
})
})
3 changes: 3 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ type FastifyAutoloadPlugin = FastifyPluginCallback<NonNullable<fastifyAutoload.A

declare namespace fastifyAutoload {
type RewritePrefix = (folderParent: string, folderName: string) => string | boolean
type Filter = string | RegExp | ((value: {file: string; path: string}) => boolean)

export interface AutoloadPluginOptions {
dir: string
dirNameRoutePrefix?: boolean | RewritePrefix
ignoreFilter?: Filter
matchFilter?: Filter
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please add a unit test for the types? We use tsd.

Copy link
Contributor Author

@hugoattal hugoattal Dec 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I wasn't familiar with this... I added types tests here: 838b200, is that okay ?

ignorePattern?: RegExp
scriptPattern?: RegExp
indexPattern?: RegExp
Expand Down
20 changes: 19 additions & 1 deletion types/index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,29 @@ const opt8: AutoloadPluginOptions = {
dir: 'test',
encapsulate: false,
}
const opt9: AutoloadPluginOptions = {
dir: 'test',
ignoreFilter: /test/,
matchFilter: /handler/
}
const opt10: AutoloadPluginOptions = {
dir: 'test',
ignoreFilter: 'test',
matchFilter: 'handler'
}
const opt11: AutoloadPluginOptions = {
dir: 'test',
ignoreFilter: ({file}) => file.endsWith('.spec.ts'),
matchFilter: ({path}) => path.split("/").at(-2) === 'handlers'
}
app.register(fastifyAutoloadDefault, opt1)
app.register(fastifyAutoloadDefault, opt2)
app.register(fastifyAutoloadDefault, opt3)
app.register(fastifyAutoloadDefault, opt4)
app.register(fastifyAutoloadDefault, opt5)
app.register(fastifyAutoloadDefault, opt6)
app.register(fastifyAutoloadDefault, opt7)
app.register(fastifyAutoloadDefault, opt8)
app.register(fastifyAutoloadDefault, opt8)
app.register(fastifyAutoloadDefault, opt9)
app.register(fastifyAutoloadDefault, opt10)
app.register(fastifyAutoloadDefault, opt11)