Skip to content

Commit

Permalink
Merge pull request #14 from GiovanniCardamone/dev
Browse files Browse the repository at this point in the history
release 1.0.6
  • Loading branch information
GiovanniCardamone authored Aug 9, 2020
2 parents 953d7d5 + 2539daf commit 4cd17ca
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 84 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
[![NPM downloads](https://img.shields.io/npm/dm/fastify-autoroutes.svg?style=flat)](https://www.npmjs.com/package/fastify-autoroutes)
[![Known Vulnerabilities](https://snyk.io/test/github/GiovanniCardamone/fastify-autoroutes/badge.svg)](https://snyk.io/test/github/GiovanniCardamone/fastify-autoroutes)

Automatic add routes based on file system hierarchy
> :star: Thanks everyone who want to star the project, it means a lot!
Automatic add routes based on file system hierarchy.

**[Full Documentation](https://giovannicardamone.github.io/fastify-autoroutes/)**

Expand Down Expand Up @@ -40,7 +42,7 @@ export default (fastifyInstance) => ({
get: {
// any of routes option allowed by fastify: https://www.fastify.io/docs/latest/Routes/#routes-option
// except for `url` and `method`

handler: (request, reply) => {
reply.send('hello index route')
}
Expand Down
220 changes: 163 additions & 57 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,92 +1,198 @@
# fastify-autoroutes
# [fastify-autoroutes](https://github.com/GiovanniCardamone/fastify-autoroutes)

Automatic add routes based on file system hierarchy
fastify-autoroutes help to manage the routes in your project and map it automatically based on the file system hierarchy. So you don't have to search around where a function mapped to url is locate. Just follow the url path in your filesystem.

## Install

to install fastify-autoroutes you can just download it from npmjs respository with:

```sh
npm install --save fastify-autoroutes
```

## Usage
## Initialize plugin

> :information_source: `dir` is relative to your current working directory.
>
> So if you are in `src` folder is `src/routes`.
> Otherwise if you are in `dist` folder it's `dist/routes`
>
> javascript
>
> ```javascript
> const fastify = require('fastify')
> const server = fastify()
>
> server.register(require('fastify-autoroutes'), {
> dir: './routes',
> })
> ```
## Your first autoroute
suppose to have a project thats looks like this:
```text
/
├── index.js
├── package.json
└── routes
└── index.js
```
```js
const fastify = require('fastify')
const server = fastify()
and the plugin configured in this way:

```javascript
server.register(require('fastify-autoroutes'), {
dir: './<autoroutes-directory>', // relative to your cwd
dir: './routes',
})
```

```js
//file: `<autoroutes-directory>/some/route/index.js`
//mapped to: `<your host>/some/route`
automatically on start the plugin will load the content of `routes` folder and map it at the start of your url.

export default (fastifyInstance) => {
get: {
// [optional] your resource on get
handler: (request, reply) => {
reply.send('hello index route')
}
},
// you can also use: ['delete', 'get', 'head', 'patch', 'post', 'put', 'options']
}
```
> `http://your-host` is mapped to `your-project/routes/index.js`
> :information_source: use syntax `:paramName` or `{paramName}` in file name to specify url parameters
and any of method in `your-project/routes/index.js` are exposed to that url.

```js
//file: `<autoroutes-directory>/users/{userId}/photos.js`
//mapped to: `<your host>/users/:userId/photos`
## Nested autoroutes

export default (fastifyInstance) => {
get: {
// [optional] your resource on get
handler: (request, reply) => {
reply.send(`photos of user ${request.params.userId}`)
}
},
}
let's suppose we have a more complex routes in our system like the following one:

```text
/
├── index.js
├── package.json
└── routes
└── hello
└── world.js
```

in this case, the plugin will recursivley scan any of routes subdirectory and map it urls

> example server
>
> ```javascript
> const fastify = require('fastify')
> const server = fastify()
>
> server.register(require('fastify-autoroutes'), {
> dir: './routes',
> })
>
> server.ready(function () {
> console.log(server.printRoutes())
> })
>
> server.listen(9999)
> ```
>
> output of `server.printRoutes()`
>
> ```text
> └── /
> └── hello/world (GET|POST)
> ```
> :warning: those two directory structure are **NOT** equivalent:
> :information_source: you have to set `ignoreTrailingSlash: true` to make it the same.
>
> ```text
> / | /
> ├── index.js | ├── index.js
> ├── package.json | ├── package.json
> └── routes | └── routes
> └── hello | └── hello
> └── world.js | └── world
> | └── index.js
> |
> mapped to url: | mapped to url:
> http://your-host/hello/world | http://your-host/hello/world/
> ```
## Url parameters in autoroutes
Is very useful to have parameters in urls, and we need some syntax to handle this "special" case. We use liquid variable format in file names to handle it.
> :information_source: you can also use syntax `:paramName` but is not windows an NTFS file name compatible, so be careful if you use it and than you want to move to Windows
example:
```text
.
├── index.js
├── package.json
└── routes
└── users
├── {userId}
│ └── posts.js
└── {userId}.js
```
## Accepted Methods in Module
in this scenario we will have a routes like the following one:

- delete
- get
- head
- patch
- post
- put
- options
```text
└── /
└── users/
└── :userId (GET)
└── /posts (GET)
```

## Url Parameters using path name
## Example of javascript module (es3)

to use url parameters in your route use `{parmName}` in your file or directory, it will be automatically changet to fastify parameter
here is the [List of supported routes options](https://www.fastify.io/docs/latest/Routes/#routes-option) provided by fastify, any of those you can use in your route method.

## Skip files in autoroutes directory
```javascript
module.exports = function (fastifyInstance) {
return {
get: {
// options `method` and `url` are ignored, the other one is the same
handler: function (request, reply) {
reply.send('this is get method')
},
},
}
}
```

to skip file in routes directory, prepend the `.` or `_` charater to filename
## Example of javascript module (es6)

examples:
```javascript
export default () => ({
get: {
handler: async () => 'this is get method',
},
})
```

- `.skipped_directory`
- `_also_skipped_directory`
- `.skipped_file.js`
- `.skipped_file.ts`
- `_also_skipped_file.js`
- `_also_skipped_file.ts`
## Typescript support for modules

this is useful if you want to have a lib file containts functions that don't have to be a route, so just create the file with `_` prepending character
is useful to have typescript for strict type check of the module we export and provide to fastify, here is an example of how to use is.

## Examples
```typescript
import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify'
import { Resource } from 'fastify-autoroutes'

- [Example javascript App](https://github.com/GiovanniCardamone/fastify-autoroutes/tree/master/examples/simple-js-app)
- [Example typescript App](https://github.com/GiovanniCardamone/fastify-autoroutes/tree/master/examples/simple-ts-app)
export default (fastify: FastifyInstance) => {
return <Resource> {
post: {
handler: async (request: FastifyRequest, reply: FastifyReply) => {
return 'hello world'
},
},
}
}
```

## Contribute

To contribute to [fastify-autoroutes](https://github.com/GiovanniCardamone/fastify-autoroutes) please check the [CONTRIBUTING](https://github.com/GiovanniCardamone/fastify-autoroutes/master/CONTRIBUTING.md) file.
That's all, i hope you like my little module and contribution of any kind are welcome!

If you want to contribute remember to comment on an issue or pull request with:

`@all-contributors please add @jakebolam for infrastructure, tests and code`

here you can check the [emoji key](https://allcontributors.org/docs/en/emoji-key)

All contributions are apprecciated :smiley:
and i will pull the request as soon as possible.

Consider to leave a :star: if you like the project :blush:
49 changes: 28 additions & 21 deletions docs/index.html
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="description" content="Description">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify/lib/themes/vue.css">
</head>
<body>
<div id="app"></div>
<script>
window.$docsify = {
name: '',
repo: ''
}
</script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/docsify.min.js"></script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="description" content="Description" />
<meta
name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
/>
<link
rel="stylesheet"
href="//cdn.jsdelivr.net/npm/docsify/lib/themes/vue.css"
/>
</head>
<body>
<div id="app"></div>
<script>
window.$docsify = {
name: '',
repo: '',
}
</script>
<script src="//cdn.jsdelivr.net/npm/docsify/lib/docsify.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/prismjs@1/components/prism-typescript.min.js"></script>
</body>
</html>
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fastify-autoroutes",
"version": "1.0.5",
"version": "1.0.6",
"description": "Map directory structure to routes",
"main": "dist/index.js",
"scripts": {
Expand Down
23 changes: 20 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,20 @@ function autoload(

function loadModule(path: string) {
try {
return require(path).default
const module = require(path)

if (typeof module === 'function') {
return module
}

if (typeof module === 'object' && 'default' in module) {
return module.default
}

throw new Error('unable to find any entrypoint for module')
} catch (error) {
throw new Error(`unable to load module ${path}`)
console.error(`[ERROR] fastify-autoload: unable to load module ${path}`)
throw error
}
}

Expand All @@ -155,7 +166,13 @@ export default fastifyPlugin<FastifyAutoroutesOptions>(
return next(new Error(message))
}

const dirPath = path.join(process.cwd(), process.argv[1], '..', options.dir)
let dirPath: string

if (path.isAbsolute(process.argv[1])) {
dirPath = path.join(process.argv[1], '..', options.dir)
} else {
dirPath = path.join(process.cwd(), process.argv[1], '..', options.dir)
}

if (!fs.existsSync(dirPath)) {
const message = `dir ${dirPath} does not exists`
Expand Down

0 comments on commit 4cd17ca

Please sign in to comment.